aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--Documentation/HOWTO32
-rw-r--r--Documentation/kernel-parameters.txt5
-rw-r--r--Documentation/networking/ip-sysctl.txt4
-rw-r--r--Documentation/stable_kernel_rules.txt25
-rw-r--r--Documentation/trace/postprocess/trace-vmscan-postprocess.pl8
-rw-r--r--Documentation/usb/s3c-otg-host.txt83
-rw-r--r--MAINTAINERS2
-rw-r--r--Makefile2
-rw-r--r--arch/alpha/include/asm/atomic.h4
-rw-r--r--arch/alpha/include/asm/socket.h2
-rw-r--r--arch/arm/Kconfig68
-rw-r--r--arch/arm/boot/compressed/Makefile17
-rw-r--r--arch/arm/boot/compressed/decompress.c4
-rw-r--r--arch/arm/boot/compressed/head.S1
-rw-r--r--arch/arm/boot/compressed/piggy.xzkern.S7
-rw-r--r--arch/arm/common/fiq_debugger.c13
-rw-r--r--arch/arm/common/pl330.c16
-rw-r--r--arch/arm/common/vic.c36
-rw-r--r--arch/arm/configs/crespo_defconfig2672
-rw-r--r--arch/arm/configs/herring_defconfig408
-rw-r--r--arch/arm/configs/mxs_defconfig1
-rw-r--r--arch/arm/include/asm/cacheflush.h8
-rw-r--r--arch/arm/include/asm/hardware/vic.h1
-rw-r--r--arch/arm/include/asm/mutex.h119
-rw-r--r--arch/arm/include/asm/pgtable.h40
-rw-r--r--arch/arm/include/asm/vfpmacros.h4
-rw-r--r--arch/arm/kernel/smp.c30
-rw-r--r--arch/arm/kernel/sys_arm.c2
-rw-r--r--arch/arm/mach-at91/at91rm9200_devices.c2
-rw-r--r--arch/arm/mach-at91/at91sam9260_devices.c2
-rw-r--r--arch/arm/mach-at91/at91sam9261_devices.c2
-rw-r--r--arch/arm/mach-at91/at91sam9263_devices.c2
-rw-r--r--arch/arm/mach-at91/at91sam9rl_devices.c2
-rw-r--r--arch/arm/mach-imx/mach-mx21ads.c2
-rw-r--r--arch/arm/mach-omap2/opp.c3
-rw-r--r--arch/arm/mach-orion5x/mpp.h4
-rw-r--r--arch/arm/mach-s5pv210/Kconfig104
-rw-r--r--arch/arm/mach-s5pv210/Makefile26
-rw-r--r--arch/arm/mach-s5pv210/Makefile.boot6
-rw-r--r--arch/arm/mach-s5pv210/adc.c401
-rw-r--r--arch/arm/mach-s5pv210/clock.c419
-rwxr-xr-xarch/arm/mach-s5pv210/coresight.c163
-rw-r--r--arch/arm/mach-s5pv210/cpu.c30
-rw-r--r--arch/arm/mach-s5pv210/cpufreq.c347
-rw-r--r--arch/arm/mach-s5pv210/cpuidle.c551
-rw-r--r--arch/arm/mach-s5pv210/dev-audio.c4
-rw-r--r--arch/arm/mach-s5pv210/dev-cpufreq.c28
-rw-r--r--arch/arm/mach-s5pv210/dev-fiqdbg.c161
-rwxr-xr-xarch/arm/mach-s5pv210/dev-herring-phone.c79
-rw-r--r--arch/arm/mach-s5pv210/didle.S218
-rw-r--r--arch/arm/mach-s5pv210/dma.c74
-rw-r--r--arch/arm/mach-s5pv210/herring-btlpm.c66
-rwxr-xr-xarch/arm/mach-s5pv210/herring-panel.c1018
-rw-r--r--arch/arm/mach-s5pv210/herring-rfkill.c295
-rw-r--r--arch/arm/mach-s5pv210/herring-touchkey-led.c128
-rw-r--r--arch/arm/mach-s5pv210/herring-vibrator.c167
-rw-r--r--arch/arm/mach-s5pv210/herring-watchdog.c111
-rwxr-xr-xarch/arm/mach-s5pv210/herring.h34
-rw-r--r--arch/arm/mach-s5pv210/include/mach/adc.h36
-rw-r--r--arch/arm/mach-s5pv210/include/mach/battery.h13
-rw-r--r--arch/arm/mach-s5pv210/include/mach/cpu-freq-v210.h31
-rw-r--r--arch/arm/mach-s5pv210/include/mach/cpuidle.h16
-rw-r--r--arch/arm/mach-s5pv210/include/mach/gpio-herring.h603
-rw-r--r--arch/arm/mach-s5pv210/include/mach/gpio.h112
-rw-r--r--arch/arm/mach-s5pv210/include/mach/irqs.h91
-rw-r--r--arch/arm/mach-s5pv210/include/mach/map.h108
-rwxr-xr-xarch/arm/mach-s5pv210/include/mach/media.h32
-rw-r--r--arch/arm/mach-s5pv210/include/mach/memory.h6
-rw-r--r--arch/arm/mach-s5pv210/include/mach/param.h89
-rwxr-xr-x[-rw-r--r--]arch/arm/mach-s5pv210/include/mach/pm-core.h7
-rw-r--r--arch/arm/mach-s5pv210/include/mach/power-domain.h57
-rw-r--r--arch/arm/mach-s5pv210/include/mach/regs-adc.h119
-rw-r--r--arch/arm/mach-s5pv210/include/mach/regs-audss.h44
-rw-r--r--arch/arm/mach-s5pv210/include/mach/regs-clock.h178
-rw-r--r--arch/arm/mach-s5pv210/include/mach/regs-gpio.h229
-rw-r--r--arch/arm/mach-s5pv210/include/mach/regs-irq.h6
-rw-r--r--arch/arm/mach-s5pv210/include/mach/regs-mem.h28
-rw-r--r--arch/arm/mach-s5pv210/include/mach/tick.h6
-rw-r--r--arch/arm/mach-s5pv210/include/mach/vmalloc.h2
-rw-r--r--arch/arm/mach-s5pv210/init.c2
-rwxr-xr-xarch/arm/mach-s5pv210/mach-herring.c6162
-rwxr-xr-x[-rw-r--r--]arch/arm/mach-s5pv210/pm.c42
-rw-r--r--arch/arm/mach-s5pv210/power-domain.c566
-rw-r--r--arch/arm/mach-s5pv210/setup-fb.c226
-rw-r--r--arch/arm/mach-s5pv210/setup-fimc0.c122
-rw-r--r--arch/arm/mach-s5pv210/setup-fimc1.c21
-rw-r--r--arch/arm/mach-s5pv210/setup-fimc2.c21
-rw-r--r--arch/arm/mach-s5pv210/setup-i2c0.c2
-rw-r--r--arch/arm/mach-s5pv210/setup-i2c1.c2
-rw-r--r--arch/arm/mach-s5pv210/setup-i2c2.c2
-rw-r--r--arch/arm/mach-s5pv210/setup-sdhci-gpio.c135
-rw-r--r--arch/arm/mach-s5pv210/setup-sdhci.c226
-rw-r--r--arch/arm/mach-s5pv210/sleep.S4
-rw-r--r--arch/arm/mm/cache-v7.S3
-rw-r--r--arch/arm/mm/fault.c4
-rw-r--r--arch/arm/mm/flush.c2
-rw-r--r--arch/arm/mm/tlb-v7.S12
-rw-r--r--arch/arm/plat-s3c24xx/dma.c2
-rw-r--r--arch/arm/plat-s5p/Kconfig40
-rw-r--r--arch/arm/plat-s5p/Makefile26
-rw-r--r--arch/arm/plat-s5p/bootmem.c144
-rw-r--r--arch/arm/plat-s5p/clock.c10
-rw-r--r--arch/arm/plat-s5p/dev-csis0.c26
-rw-r--r--arch/arm/plat-s5p/dev-mfc.c65
-rw-r--r--arch/arm/plat-s5p/devs.c713
-rw-r--r--arch/arm/plat-s5p/hr-time-rtc.c512
-rw-r--r--arch/arm/plat-s5p/include/plat/csis.h29
-rw-r--r--arch/arm/plat-s5p/include/plat/fb.h127
-rw-r--r--arch/arm/plat-s5p/include/plat/fimc.h129
-rw-r--r--arch/arm/plat-s5p/include/plat/irq-eint-group.h16
-rw-r--r--arch/arm/plat-s5p/include/plat/irq-pm.h16
-rwxr-xr-xarch/arm/plat-s5p/include/plat/jpeg.h27
-rw-r--r--arch/arm/plat-s5p/include/plat/map-s5p.h1
-rw-r--r--arch/arm/plat-s5p/include/plat/media.h34
-rw-r--r--arch/arm/plat-s5p/include/plat/mfc.h24
-rw-r--r--arch/arm/plat-s5p/include/plat/pll.h2
-rw-r--r--arch/arm/plat-s5p/include/plat/regs-csis.h105
-rw-r--r--arch/arm/plat-s5p/include/plat/regs-fb.h396
-rw-r--r--arch/arm/plat-s5p/include/plat/regs-fimc.h446
-rw-r--r--arch/arm/plat-s5p/include/plat/regs-iis.h147
-rw-r--r--arch/arm/plat-s5p/include/plat/regs-ipc.h147
-rw-r--r--arch/arm/plat-s5p/include/plat/regs-mfc.h256
-rw-r--r--arch/arm/plat-s5p/include/plat/regs-systimer.h77
-rw-r--r--arch/arm/plat-s5p/include/plat/s5p-otghost.h56
-rw-r--r--arch/arm/plat-s5p/include/plat/system-reset.h18
-rw-r--r--arch/arm/plat-s5p/irq-eint-group.c605
-rw-r--r--arch/arm/plat-s5p/irq-eint.c28
-rw-r--r--arch/arm/plat-s5p/irq-pm.c63
-rw-r--r--arch/arm/plat-s5p/irq.c26
-rw-r--r--arch/arm/plat-s5p/reset.c33
-rw-r--r--arch/arm/plat-s5p/setup-mfc.c17
-rw-r--r--arch/arm/plat-samsung/Makefile2
-rw-r--r--arch/arm/plat-samsung/adc.c8
-rw-r--r--arch/arm/plat-samsung/clock.c152
-rw-r--r--arch/arm/plat-samsung/dev-hsmmc.c6
-rw-r--r--arch/arm/plat-samsung/dev-hsmmc1.c6
-rw-r--r--arch/arm/plat-samsung/dev-hsmmc2.c6
-rw-r--r--arch/arm/plat-samsung/dev-hsmmc3.c6
-rw-r--r--arch/arm/plat-samsung/dev-i2c0.c40
-rw-r--r--arch/arm/plat-samsung/dev-i2c1.c37
-rw-r--r--arch/arm/plat-samsung/dev-i2c2.c43
-rw-r--r--arch/arm/plat-samsung/dev-uart.c8
-rw-r--r--arch/arm/plat-samsung/gpio-config.c21
-rw-r--r--arch/arm/plat-samsung/include/plat/clock.h1
-rw-r--r--arch/arm/plat-samsung/include/plat/cpu.h4
-rw-r--r--arch/arm/plat-samsung/include/plat/devs.h41
-rw-r--r--arch/arm/plat-samsung/include/plat/dma.h4
-rw-r--r--arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h6
-rw-r--r--arch/arm/plat-samsung/include/plat/gpio-cfg.h5
-rwxr-xr-x[-rw-r--r--]arch/arm/plat-samsung/include/plat/gpio-core.h2
-rw-r--r--arch/arm/plat-samsung/include/plat/iic.h4
-rw-r--r--arch/arm/plat-samsung/include/plat/map-base.h6
-rw-r--r--arch/arm/plat-samsung/include/plat/pm.h3
-rw-r--r--arch/arm/plat-samsung/include/plat/regs-otg.h262
-rw-r--r--arch/arm/plat-samsung/include/plat/regs-rtc.h18
-rw-r--r--arch/arm/plat-samsung/include/plat/regs-sdhci.h2
-rw-r--r--arch/arm/plat-samsung/include/plat/regs-serial.h13
-rw-r--r--arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h8
-rw-r--r--arch/arm/plat-samsung/include/plat/sdhci.h23
-rw-r--r--arch/arm/plat-samsung/include/plat/watchdog-reset.h10
-rwxr-xr-x[-rw-r--r--]arch/arm/plat-samsung/pm-gpio.c9
-rw-r--r--arch/arm/plat-samsung/pm.c97
-rw-r--r--arch/arm/plat-samsung/pwm.c52
-rw-r--r--arch/arm/plat-samsung/s3c-pl330.c23
-rw-r--r--arch/arm/plat-samsung/time.c2
-rw-r--r--arch/ia64/include/asm/atomic.h4
-rw-r--r--arch/ia64/include/asm/unistd.h3
-rw-r--r--arch/ia64/kernel/entry.S3
-rw-r--r--arch/ia64/kernel/irq_ia64.c1
-rw-r--r--arch/m68k/include/asm/entry_mm.h4
-rw-r--r--arch/m68k/kernel/sys_m68k.c8
-rw-r--r--arch/mips/include/asm/thread_info.h4
-rw-r--r--arch/mips/kernel/kgdb.c9
-rw-r--r--arch/mips/kernel/vmlinux.lds.S3
-rw-r--r--arch/mn10300/Makefile2
-rw-r--r--arch/parisc/include/asm/atomic.h4
-rw-r--r--arch/parisc/include/asm/prefetch.h7
-rw-r--r--arch/parisc/kernel/entry.S28
-rw-r--r--arch/parisc/kernel/pacache.S38
-rw-r--r--arch/parisc/kernel/vmlinux.lds.S6
-rw-r--r--arch/powerpc/include/asm/cputime.h6
-rw-r--r--arch/powerpc/include/asm/reg.h3
-rw-r--r--arch/powerpc/kernel/asm-offsets.c1
-rw-r--r--arch/powerpc/kernel/entry_64.S23
-rw-r--r--arch/powerpc/kernel/ftrace.c12
-rw-r--r--arch/powerpc/kernel/module_32.c11
-rw-r--r--arch/powerpc/kernel/process.c12
-rw-r--r--arch/powerpc/kernel/time.c10
-rw-r--r--arch/powerpc/xmon/xmon.c2
-rw-r--r--arch/s390/kernel/compat_linux.c2
-rw-r--r--arch/s390/mm/fault.c14
-rw-r--r--arch/sparc/Kconfig3
-rw-r--r--arch/sparc/kernel/central.c2
-rw-r--r--arch/sparc/kernel/perf_event.c15
-rw-r--r--arch/sparc/kernel/sys_sparc_64.c10
-rw-r--r--arch/sparc/kernel/syscalls.S32
-rw-r--r--arch/sparc/kernel/systbls_64.S2
-rw-r--r--arch/sparc/mm/init_64.c28
-rw-r--r--arch/sparc/mm/ultra.S6
-rw-r--r--arch/tile/Kconfig1
-rw-r--r--arch/tile/Makefile4
-rw-r--r--arch/tile/include/asm/bitops.h12
-rw-r--r--arch/tile/kernel/compat_signal.c12
-rw-r--r--arch/um/include/asm/pgtable.h10
-rw-r--r--arch/x86/Kconfig9
-rw-r--r--arch/x86/crypto/aesni-intel_asm.S6
-rw-r--r--arch/x86/include/asm/archrandom.h75
-rw-r--r--arch/x86/include/asm/cpufeature.h2
-rw-r--r--arch/x86/include/asm/pgtable-3level.h50
-rw-r--r--arch/x86/include/asm/pgtable.h11
-rw-r--r--arch/x86/include/asm/processor.h2
-rw-r--r--arch/x86/kernel/acpi/boot.c27
-rw-r--r--arch/x86/kernel/alternative.c4
-rw-r--r--arch/x86/kernel/amd_nb.c8
-rw-r--r--arch/x86/kernel/cpu/Makefile1
-rw-r--r--arch/x86/kernel/cpu/amd.c2
-rw-r--r--arch/x86/kernel/cpu/common.c7
-rw-r--r--arch/x86/kernel/cpu/intel.c2
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce-severity.c16
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce.c11
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_amd.c60
-rw-r--r--arch/x86/kernel/cpu/perf_event_amd.c11
-rw-r--r--arch/x86/kernel/cpu/proc.c4
-rw-r--r--arch/x86/kernel/cpu/rdrand.c73
-rw-r--r--arch/x86/kernel/cpu/scattered.c2
-rw-r--r--arch/x86/kernel/entry_32.S8
-rw-r--r--arch/x86/kernel/entry_64.S2
-rw-r--r--arch/x86/kernel/microcode_core.c31
-rw-r--r--arch/x86/kernel/reboot.c8
-rw-r--r--arch/x86/kernel/setup.c17
-rw-r--r--arch/x86/kernel/setup_percpu.c14
-rw-r--r--arch/x86/mm/hugetlbpage.c21
-rw-r--r--arch/x86/mm/init.c69
-rw-r--r--arch/x86/oprofile/nmi_int.c2
-rw-r--r--arch/x86/pci/fixup.c17
-rw-r--r--arch/x86/xen/enlighten.c33
-rw-r--r--arch/x86/xen/mmu.c7
-rw-r--r--arch/x86/xen/p2m.c36
-rw-r--r--arch/x86/xen/setup.c4
-rw-r--r--bin/META-INF/CERT.RSAbin0 -> 1714 bytes
-rw-r--r--bin/META-INF/CERT.SF1734
-rw-r--r--bin/META-INF/MANIFEST.MF1733
-rwxr-xr-xbin/META-INF/com/google/android/update-binarybin0 -> 194596 bytes
-rw-r--r--bin/META-INF/com/google/android/updater-script20
-rwxr-xr-xbin/kernel/dump_imagebin0 -> 64012 bytes
-rwxr-xr-xbin/kernel/mkbootimgbin0 -> 59832 bytes
-rw-r--r--bin/kernel/mkbootimg.sh8
-rwxr-xr-xbin/kernel/unpackbootimgbin0 -> 54696 bytes
-rw-r--r--block/Kconfig.iosched26
-rw-r--r--block/Makefile1
-rw-r--r--block/bfq-cgroup.c831
-rw-r--r--block/bfq-ioc.c380
-rw-r--r--block/bfq-iosched.c3052
-rw-r--r--block/bfq-sched.c1066
-rw-r--r--block/bfq.h595
-rw-r--r--block/blk-ioc.c30
-rw-r--r--block/cfq-iosched.c10
-rw-r--r--block/genhd.c10
-rwxr-xr-xbuild.sh203
-rw-r--r--drivers/acpi/ac.c4
-rw-r--r--drivers/acpi/acpi_pad.c7
-rw-r--r--drivers/acpi/acpica/tbxface.c1
-rw-r--r--drivers/acpi/battery.c10
-rw-r--r--drivers/acpi/bus.c8
-rw-r--r--drivers/acpi/ec.c30
-rw-r--r--drivers/acpi/processor_core.c6
-rw-r--r--drivers/acpi/sleep.c8
-rw-r--r--drivers/acpi/sysfs.c4
-rw-r--r--drivers/acpi/video.c5
-rw-r--r--drivers/ata/ahci.c4
-rw-r--r--drivers/ata/libata-core.c1
-rw-r--r--drivers/atm/solos-pci.c4
-rw-r--r--drivers/base/memory.c58
-rw-r--r--drivers/base/power/runtime.c5
-rw-r--r--drivers/bcma/main.c5
-rw-r--r--drivers/block/aoe/aoecmd.c1
-rw-r--r--drivers/block/cciss_scsi.c12
-rw-r--r--drivers/block/umem.c40
-rw-r--r--drivers/bluetooth/ath3k.c6
-rw-r--r--drivers/bluetooth/btusb.c18
-rw-r--r--drivers/char/agp/intel-agp.c1
-rw-r--r--drivers/char/agp/intel-agp.h1
-rw-r--r--drivers/char/mspec.c2
-rw-r--r--drivers/char/random.c374
-rw-r--r--drivers/char/tpm/tpm.c21
-rw-r--r--drivers/char/ttyprintk.c2
-rw-r--r--drivers/cpufreq/cpufreq.c10
-rw-r--r--drivers/cpufreq/cpufreq_interactive.c28
-rw-r--r--drivers/cpufreq/cpufreq_ondemand.c73
-rw-r--r--drivers/cpufreq/powernow-k8.c56
-rw-r--r--drivers/crypto/Kconfig1
-rw-r--r--drivers/dma/at_hdmac.c13
-rw-r--r--drivers/edac/amd64_edac.c11
-rw-r--r--drivers/edac/i7core_edac.c2
-rw-r--r--drivers/firewire/core-cdev.c4
-rw-r--r--drivers/firmware/dmi_scan.c3
-rw-r--r--drivers/firmware/efivars.c17
-rw-r--r--drivers/firmware/pcdp.c4
-rw-r--r--drivers/gpio/Kconfig11
-rw-r--r--drivers/gpio/gpio-s5pv210.c345
-rw-r--r--drivers/gpio/pch_gpio.c1
-rw-r--r--drivers/gpu/Makefile2
-rw-r--r--drivers/gpu/drm/drm_edid.c2
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c9
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h20
-rw-r--r--drivers/gpu/drm/i915/i915_suspend.c5
-rw-r--r--drivers/gpu/drm/i915/intel_display.c23
-rw-r--r--drivers/gpu/drm/i915/intel_hdmi.c2
-rw-r--r--drivers/gpu/drm/i915/intel_lvds.c8
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c7
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo.c12
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo_regs.h5
-rw-r--r--drivers/gpu/drm/i915/intel_tv.c5
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fbcon.c2
-rw-r--r--drivers/gpu/drm/radeon/atombios_dp.c10
-rw-r--r--drivers/gpu/drm/radeon/evergreen.c66
-rw-r--r--drivers/gpu/drm/radeon/evergreend.h1
-rw-r--r--drivers/gpu/drm/radeon/radeon_asic.h8
-rw-r--r--drivers/gpu/drm/radeon/radeon_atombios.c6
-rw-r--r--drivers/gpu/drm/radeon/radeon_connectors.c35
-rw-r--r--drivers/gpu/drm/radeon/radeon_cursor.c8
-rw-r--r--drivers/gpu/drm/radeon/radeon_irq_kms.c10
-rw-r--r--drivers/gpu/drm/radeon/radeon_legacy_encoders.c6
-rw-r--r--drivers/gpu/drm/radeon/radeon_pm.c8
-rw-r--r--drivers/gpu/drm/radeon/rv515.c13
-rw-r--r--drivers/gpu/drm/radeon/rv770.c2
-rw-r--r--drivers/gpu/drm/radeon/rv770d.h1
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo.c1
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.c1
-rw-r--r--drivers/gpu/pvr/Kconfig107
-rw-r--r--drivers/gpu/pvr/Makefile137
-rw-r--r--drivers/gpu/pvr/bridged_pvr_bridge.c4894
-rw-r--r--drivers/gpu/pvr/bridged_pvr_bridge.h232
-rw-r--r--drivers/gpu/pvr/bridged_support.c89
-rw-r--r--drivers/gpu/pvr/bridged_support.h47
-rw-r--r--drivers/gpu/pvr/buffer_manager.c2549
-rw-r--r--drivers/gpu/pvr/buffer_manager.h248
-rw-r--r--drivers/gpu/pvr/dbgdrv/Makefile15
-rw-r--r--drivers/gpu/pvr/dbgdrv/dbgdriv.c2354
-rw-r--r--drivers/gpu/pvr/dbgdrv/dbgdriv.h122
-rw-r--r--drivers/gpu/pvr/dbgdrv/dbgdriv_ioctl.h35
-rw-r--r--drivers/gpu/pvr/dbgdrv/handle.c121
-rw-r--r--drivers/gpu/pvr/dbgdrv/hostfunc.c324
-rw-r--r--drivers/gpu/pvr/dbgdrv/hostfunc.h58
-rw-r--r--drivers/gpu/pvr/dbgdrv/hotkey.c135
-rw-r--r--drivers/gpu/pvr/dbgdrv/hotkey.h60
-rw-r--r--drivers/gpu/pvr/dbgdrv/ioctl.c587
-rw-r--r--drivers/gpu/pvr/dbgdrv/linuxsrv.h48
-rw-r--r--drivers/gpu/pvr/dbgdrv/main.c317
-rw-r--r--drivers/gpu/pvr/dbgdrvif.h358
-rw-r--r--drivers/gpu/pvr/device.h323
-rw-r--r--drivers/gpu/pvr/deviceclass.c2371
-rw-r--r--drivers/gpu/pvr/deviceid.h36
-rw-r--r--drivers/gpu/pvr/devicemem.c1837
-rw-r--r--drivers/gpu/pvr/env_data.h66
-rw-r--r--drivers/gpu/pvr/env_perproc.h56
-rw-r--r--drivers/gpu/pvr/event.c293
-rw-r--r--drivers/gpu/pvr/event.h32
-rw-r--r--drivers/gpu/pvr/handle.c1873
-rw-r--r--drivers/gpu/pvr/handle.h404
-rw-r--r--drivers/gpu/pvr/hash.c505
-rw-r--r--drivers/gpu/pvr/hash.h80
-rw-r--r--drivers/gpu/pvr/img_defs.h136
-rw-r--r--drivers/gpu/pvr/img_types.h206
-rw-r--r--drivers/gpu/pvr/ioctldef.h98
-rw-r--r--drivers/gpu/pvr/ion.c112
-rw-r--r--drivers/gpu/pvr/ion.h39
-rw-r--r--drivers/gpu/pvr/kernelbuffer.h72
-rw-r--r--drivers/gpu/pvr/kerneldisplay.h206
-rw-r--r--drivers/gpu/pvr/linkage.h52
-rw-r--r--drivers/gpu/pvr/lists.c99
-rw-r--r--drivers/gpu/pvr/lists.h244
-rw-r--r--drivers/gpu/pvr/lock.h32
-rw-r--r--drivers/gpu/pvr/mem.c155
-rw-r--r--drivers/gpu/pvr/mem_debug.c247
-rw-r--r--drivers/gpu/pvr/metrics.c160
-rw-r--r--drivers/gpu/pvr/metrics.h130
-rw-r--r--drivers/gpu/pvr/mm.c2717
-rw-r--r--drivers/gpu/pvr/mm.h384
-rw-r--r--drivers/gpu/pvr/mmap.c1220
-rw-r--r--drivers/gpu/pvr/mmap.h122
-rw-r--r--drivers/gpu/pvr/module.c854
-rw-r--r--drivers/gpu/pvr/mutex.c136
-rw-r--r--drivers/gpu/pvr/mutex.h70
-rw-r--r--drivers/gpu/pvr/mutils.c136
-rw-r--r--drivers/gpu/pvr/mutils.h103
-rw-r--r--drivers/gpu/pvr/ocpdefs.h271
-rw-r--r--drivers/gpu/pvr/osfunc.c3310
-rw-r--r--drivers/gpu/pvr/osfunc.h648
-rw-r--r--drivers/gpu/pvr/osfunc_common.c31
-rw-r--r--drivers/gpu/pvr/osperproc.c113
-rw-r--r--drivers/gpu/pvr/osperproc.h76
-rw-r--r--drivers/gpu/pvr/pdump.c628
-rw-r--r--drivers/gpu/pvr/pdump.h37
-rw-r--r--drivers/gpu/pvr/pdump_common.c2368
-rw-r--r--drivers/gpu/pvr/pdump_int.h67
-rw-r--r--drivers/gpu/pvr/pdump_km.h412
-rw-r--r--drivers/gpu/pvr/pdump_osfunc.h140
-rw-r--r--drivers/gpu/pvr/pdumpdefs.h111
-rw-r--r--drivers/gpu/pvr/perfkm.h36
-rw-r--r--drivers/gpu/pvr/perproc.c305
-rw-r--r--drivers/gpu/pvr/perproc.h126
-rw-r--r--drivers/gpu/pvr/power.c719
-rw-r--r--drivers/gpu/pvr/power.h120
-rw-r--r--drivers/gpu/pvr/private_data.h69
-rw-r--r--drivers/gpu/pvr/proc.c835
-rw-r--r--drivers/gpu/pvr/proc.h108
-rw-r--r--drivers/gpu/pvr/pvr_bridge.h1786
-rw-r--r--drivers/gpu/pvr/pvr_bridge_k.c464
-rw-r--r--drivers/gpu/pvr/pvr_bridge_km.h319
-rw-r--r--drivers/gpu/pvr/pvr_debug.c453
-rw-r--r--drivers/gpu/pvr/pvr_debug.h184
-rw-r--r--drivers/gpu/pvr/pvr_uaccess.h71
-rw-r--r--drivers/gpu/pvr/pvrmmap.h44
-rw-r--r--drivers/gpu/pvr/pvrmodule.h31
-rw-r--r--drivers/gpu/pvr/pvrsrv.c1364
-rw-r--r--drivers/gpu/pvr/pvrsrv_errors.h266
-rw-r--r--drivers/gpu/pvr/pvrversion.h51
-rw-r--r--drivers/gpu/pvr/queue.c1213
-rw-r--r--drivers/gpu/pvr/queue.h114
-rw-r--r--drivers/gpu/pvr/ra.c1736
-rw-r--r--drivers/gpu/pvr/ra.h163
-rw-r--r--drivers/gpu/pvr/refcount.c568
-rw-r--r--drivers/gpu/pvr/refcount.h188
-rw-r--r--drivers/gpu/pvr/regpaths.h43
-rw-r--r--drivers/gpu/pvr/resman.c765
-rw-r--r--drivers/gpu/pvr/resman.h118
-rw-r--r--drivers/gpu/pvr/s3c_lcd/s3c_displayclass.c1388
-rw-r--r--drivers/gpu/pvr/s3c_lcd/s3c_lcd.c58
-rw-r--r--drivers/gpu/pvr/s3c_lcd/s3c_lcd.h42
-rw-r--r--drivers/gpu/pvr/s5pc110/oemfuncs.h81
-rw-r--r--drivers/gpu/pvr/s5pc110/sysconfig.c1031
-rw-r--r--drivers/gpu/pvr/s5pc110/sysconfig.h59
-rw-r--r--drivers/gpu/pvr/s5pc110/sysinfo.h68
-rw-r--r--drivers/gpu/pvr/s5pc110/sysutils.c36
-rw-r--r--drivers/gpu/pvr/services.h1322
-rw-r--r--drivers/gpu/pvr/services_headers.h50
-rw-r--r--drivers/gpu/pvr/servicesext.h854
-rw-r--r--drivers/gpu/pvr/servicesint.h377
-rw-r--r--drivers/gpu/pvr/sgx/bridged_sgx_bridge.c3764
-rw-r--r--drivers/gpu/pvr/sgx/bridged_sgx_bridge.h42
-rw-r--r--drivers/gpu/pvr/sgx/mmu.c3935
-rw-r--r--drivers/gpu/pvr/sgx/mmu.h156
-rw-r--r--drivers/gpu/pvr/sgx/pb.c466
-rw-r--r--drivers/gpu/pvr/sgx/sgx_bridge_km.h160
-rw-r--r--drivers/gpu/pvr/sgx/sgxconfig.h401
-rw-r--r--drivers/gpu/pvr/sgx/sgxinfokm.h573
-rw-r--r--drivers/gpu/pvr/sgx/sgxinit.c2873
-rw-r--r--drivers/gpu/pvr/sgx/sgxkick.c808
-rw-r--r--drivers/gpu/pvr/sgx/sgxpower.c483
-rw-r--r--drivers/gpu/pvr/sgx/sgxreset.c671
-rw-r--r--drivers/gpu/pvr/sgx/sgxtransfer.c773
-rw-r--r--drivers/gpu/pvr/sgx/sgxutils.c1725
-rw-r--r--drivers/gpu/pvr/sgx/sgxutils.h143
-rw-r--r--drivers/gpu/pvr/sgx530defs.h488
-rw-r--r--drivers/gpu/pvr/sgx531defs.h544
-rw-r--r--drivers/gpu/pvr/sgx535defs.h650
-rw-r--r--drivers/gpu/pvr/sgx540defs.h547
-rw-r--r--drivers/gpu/pvr/sgx_bridge.h666
-rw-r--r--drivers/gpu/pvr/sgx_mkif_km.h349
-rw-r--r--drivers/gpu/pvr/sgx_options.h254
-rw-r--r--drivers/gpu/pvr/sgx_ukernel_status_codes.h940
-rw-r--r--drivers/gpu/pvr/sgxapi_km.h500
-rw-r--r--drivers/gpu/pvr/sgxdefs.h90
-rw-r--r--drivers/gpu/pvr/sgxerrata.h714
-rw-r--r--drivers/gpu/pvr/sgxfeaturedefs.h247
-rw-r--r--drivers/gpu/pvr/sgxinfo.h463
-rw-r--r--drivers/gpu/pvr/sgxmmu.h72
-rw-r--r--drivers/gpu/pvr/sgxscript.h83
-rw-r--r--drivers/gpu/pvr/srvkm.h78
-rw-r--r--drivers/gpu/pvr/staticversion.h33
-rw-r--r--drivers/gpu/pvr/syscommon.h270
-rw-r--r--drivers/gpu/pvr/ttrace.h184
-rw-r--r--drivers/gpu/pvr/ttrace_common.h84
-rw-r--r--drivers/gpu/pvr/ttrace_tokens.h84
-rw-r--r--drivers/hwmon/ads7871.c9
-rw-r--r--drivers/hwmon/applesmc.c4
-rw-r--r--drivers/hwmon/asus_atk0110.c6
-rw-r--r--drivers/hwmon/coretemp.c9
-rw-r--r--drivers/hwmon/fam15h_power.c23
-rw-r--r--drivers/hwmon/it87.c2
-rw-r--r--drivers/hwmon/twl4030-madc-hwmon.c9
-rw-r--r--drivers/i2c/busses/i2c-davinci.c2
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c71
-rw-r--r--drivers/infiniband/hw/cxgb4/cm.c6
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c2
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c19
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c88
-rw-r--r--drivers/input/joystick/xpad.c1
-rw-r--r--drivers/input/keyboard/Kconfig9
-rw-r--r--drivers/input/keyboard/Makefile2
-rw-r--r--drivers/input/keyboard/cypress-touchkey-firmware.c322
-rw-r--r--drivers/input/keyboard/cypress-touchkey-firmware.h212
-rwxr-xr-xdrivers/input/keyboard/cypress-touchkey.c632
-rw-r--r--drivers/input/misc/Kconfig13
-rw-r--r--drivers/input/misc/Makefile3
-rw-r--r--drivers/input/misc/gp2a.c641
-rw-r--r--drivers/input/misc/k3g.c707
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h20
-rw-r--r--drivers/input/tablet/wacom_wac.c2
-rw-r--r--drivers/input/touchscreen/Kconfig12
-rw-r--r--drivers/input/touchscreen/Makefile1
-rw-r--r--drivers/input/touchscreen/mxt224.c658
-rw-r--r--drivers/isdn/gigaset/capi.c22
-rw-r--r--drivers/isdn/isdnloop/isdnloop.c12
-rw-r--r--drivers/md/dm-raid1.c2
-rw-r--r--drivers/md/dm-region-hash.c5
-rw-r--r--drivers/md/dm.c56
-rw-r--r--drivers/md/md.c13
-rw-r--r--drivers/md/raid10.c6
-rw-r--r--drivers/md/raid5.c8
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.c1
-rw-r--r--drivers/media/dvb/siano/smsusb.c6
-rw-r--r--drivers/media/rc/ene_ir.c32
-rw-r--r--drivers/media/rc/fintek-cir.c20
-rw-r--r--drivers/media/rc/ite-cir.c22
-rw-r--r--drivers/media/rc/nuvoton-cir.c36
-rw-r--r--drivers/media/rc/rc-main.c5
-rw-r--r--drivers/media/rc/winbond-cir.c78
-rw-r--r--drivers/media/video/Kconfig36
-rw-r--r--drivers/media/video/Makefile3
-rw-r--r--drivers/media/video/au0828/au0828-video.c12
-rw-r--r--drivers/media/video/gspca/spca506.c2
-rwxr-xr-xdrivers/media/video/s5k4ecgx.c2837
-rwxr-xr-xdrivers/media/video/s5k4ecgx_regs_1_0.h4797
-rwxr-xr-xdrivers/media/video/s5k4ecgx_regs_1_1.h4783
-rwxr-xr-xdrivers/media/video/s5ka3dfx.c1229
-rwxr-xr-xdrivers/media/video/s5ka3dfx.h1691
-rw-r--r--drivers/media/video/samsung/Kconfig26
-rw-r--r--drivers/media/video/samsung/Makefile10
-rw-r--r--drivers/media/video/samsung/fimc/Kconfig32
-rw-r--r--drivers/media/video/samsung/fimc/Makefile12
-rw-r--r--drivers/media/video/samsung/fimc/csis.c431
-rw-r--r--drivers/media/video/samsung/fimc/csis.h42
-rw-r--r--drivers/media/video/samsung/fimc/fimc.h707
-rw-r--r--drivers/media/video/samsung/fimc/fimc_capture.c1733
-rw-r--r--drivers/media/video/samsung/fimc/fimc_dev.c1688
-rw-r--r--drivers/media/video/samsung/fimc/fimc_output.c2563
-rw-r--r--drivers/media/video/samsung/fimc/fimc_overlay.c312
-rw-r--r--drivers/media/video/samsung/fimc/fimc_regs.c1801
-rw-r--r--drivers/media/video/samsung/fimc/fimc_v4l2.c296
-rw-r--r--drivers/media/video/samsung/jpeg_v2/Kconfig15
-rw-r--r--drivers/media/video/samsung/jpeg_v2/Makefile3
-rw-r--r--drivers/media/video/samsung/jpeg_v2/jpg_conf.h282
-rw-r--r--drivers/media/video/samsung/jpeg_v2/jpg_mem.c61
-rw-r--r--drivers/media/video/samsung/jpeg_v2/jpg_mem.h111
-rw-r--r--drivers/media/video/samsung/jpeg_v2/jpg_misc.c81
-rw-r--r--drivers/media/video/samsung/jpeg_v2/jpg_misc.h27
-rw-r--r--drivers/media/video/samsung/jpeg_v2/jpg_opr.c320
-rw-r--r--drivers/media/video/samsung/jpeg_v2/jpg_opr.h158
-rw-r--r--drivers/media/video/samsung/jpeg_v2/regs-jpeg.h143
-rw-r--r--drivers/media/video/samsung/jpeg_v2/s3c-jpeg.c613
-rw-r--r--drivers/media/video/samsung/jpeg_v2/s3c-jpeg.h36
-rw-r--r--drivers/media/video/samsung/mfc50/Kconfig23
-rw-r--r--drivers/media/video/samsung/mfc50/Makefile7
-rwxr-xr-xdrivers/media/video/samsung/mfc50/mfc.c823
-rw-r--r--drivers/media/video/samsung/mfc50/mfc_buffer_manager.c350
-rw-r--r--drivers/media/video/samsung/mfc50/mfc_buffer_manager.h56
-rw-r--r--drivers/media/video/samsung/mfc50/mfc_errorno.h83
-rw-r--r--drivers/media/video/samsung/mfc50/mfc_interface.h340
-rw-r--r--drivers/media/video/samsung/mfc50/mfc_intr.c202
-rw-r--r--drivers/media/video/samsung/mfc50/mfc_intr.h25
-rw-r--r--drivers/media/video/samsung/mfc50/mfc_logmsg.h72
-rw-r--r--drivers/media/video/samsung/mfc50/mfc_memory.c70
-rw-r--r--drivers/media/video/samsung/mfc50/mfc_memory.h111
-rw-r--r--drivers/media/video/samsung/mfc50/mfc_opr.c2576
-rw-r--r--drivers/media/video/samsung/mfc50/mfc_opr.h204
-rw-r--r--drivers/media/video/samsung/mfc50/mfc_shared_mem.c123
-rw-r--r--drivers/media/video/samsung/mfc50/mfc_shared_mem.h97
-rw-r--r--drivers/media/video/uvc/uvc_v4l2.c2
-rw-r--r--drivers/mfd/ab3100-core.c5
-rw-r--r--drivers/mfd/ab3550-core.c2
-rw-r--r--drivers/mfd/ezx-pcap.c2
-rwxr-xr-x[-rw-r--r--]drivers/mfd/max8998.c2
-rw-r--r--drivers/mfd/wm831x-otp.c8
-rwxr-xr-x[-rw-r--r--]drivers/misc/Kconfig54
-rwxr-xr-x[-rw-r--r--]drivers/misc/Makefile10
-rw-r--r--drivers/misc/ak8973-reg.h47
-rw-r--r--drivers/misc/ak8973.c407
-rw-r--r--drivers/misc/bld.c272
-rw-r--r--drivers/misc/bln.c208
-rw-r--r--drivers/misc/deep_idle.c233
-rwxr-xr-xdrivers/misc/fsa9480.c612
-rw-r--r--drivers/misc/kr3dm.c508
-rw-r--r--drivers/misc/kr3dm_reg.h169
-rwxr-xr-xdrivers/misc/pn544.c364
-rw-r--r--drivers/misc/samsung_modemctl/Makefile1
-rwxr-xr-xdrivers/misc/samsung_modemctl/modem_ctl.c1195
-rw-r--r--drivers/misc/samsung_modemctl/modem_ctl.h45
-rw-r--r--drivers/misc/samsung_modemctl/modem_ctl_p.h318
-rwxr-xr-xdrivers/misc/samsung_modemctl/modem_ctl_recovery.h85
-rw-r--r--drivers/misc/samsung_modemctl/modem_dbg.c211
-rw-r--r--drivers/misc/samsung_modemctl/modem_io.c724
-rwxr-xr-xdrivers/misc/sec_jack.c495
-rw-r--r--drivers/misc/sgi-xp/xpc_uv.c84
-rw-r--r--drivers/mmc/core/sd.c6
-rw-r--r--drivers/mmc/core/sdio.c2
-rw-r--r--drivers/mmc/core/sdio_irq.c11
-rw-r--r--drivers/mmc/host/Kconfig2
-rw-r--r--drivers/mmc/host/mxs-mmc.c4
-rw-r--r--drivers/mmc/host/sdhci-esdhc.h6
-rw-r--r--drivers/mmc/host/sdhci-pci.c1
-rwxr-xr-x[-rw-r--r--]drivers/mmc/host/sdhci-s3c.c107
-rw-r--r--drivers/mmc/host/sdhci.c125
-rw-r--r--drivers/mmc/host/sdhci.h3
-rw-r--r--drivers/mtd/maps/autcpu12-nvram.c19
-rw-r--r--drivers/mtd/nand/cafe_nand.c2
-rw-r--r--drivers/mtd/nand/nand_bbt.c3
-rw-r--r--drivers/mtd/nand/nandsim.c13
-rw-r--r--drivers/mtd/nand/omap2.c3
-rw-r--r--drivers/mtd/onenand/onenand_base.c59
-rw-r--r--drivers/mtd/onenand/samsung.c145
-rw-r--r--drivers/mtd/sm_ftl.c2
-rw-r--r--drivers/mtd/ubi/build.c5
-rw-r--r--drivers/mtd/ubi/vtbl.c4
-rw-r--r--drivers/net/Kconfig11
-rw-r--r--drivers/net/benet/be_main.c5
-rw-r--r--drivers/net/bnx2.c6
-rw-r--r--drivers/net/bonding/bond_main.c9
-rw-r--r--drivers/net/caif/caif_serial.c3
-rw-r--r--drivers/net/can/c_can/c_can.c20
-rw-r--r--drivers/net/can/c_can/c_can.h1
-rw-r--r--drivers/net/can/janz-ican3.c4
-rw-r--r--drivers/net/can/mcp251x.c11
-rw-r--r--drivers/net/can/mscan/mpc5xxx_can.c4
-rw-r--r--drivers/net/can/ti_hecc.c2
-rw-r--r--drivers/net/davinci_cpdma.c1
-rw-r--r--drivers/net/dummy.c5
-rw-r--r--drivers/net/e1000/e1000.h2
-rw-r--r--drivers/net/e1000/e1000_main.c18
-rw-r--r--drivers/net/e1000e/82571.c10
-rw-r--r--drivers/net/macvlan.c2
-rw-r--r--drivers/net/netconsole.c1
-rw-r--r--drivers/net/netxen/netxen_nic_main.c4
-rw-r--r--drivers/net/pch_gbe/pch_gbe_main.c50
-rw-r--r--drivers/net/pch_gbe/pch_gbe_param.c15
-rw-r--r--drivers/net/pppoe.c2
-rw-r--r--drivers/net/r8169.c444
-rw-r--r--drivers/net/sfc/efx.c6
-rw-r--r--drivers/net/sfc/efx.h14
-rw-r--r--drivers/net/sfc/ethtool.c16
-rw-r--r--drivers/net/sfc/nic.h5
-rw-r--r--drivers/net/sfc/tx.c19
-rw-r--r--drivers/net/skge.c7
-rw-r--r--drivers/net/sky2.c41
-rw-r--r--drivers/net/sky2.h1
-rw-r--r--drivers/net/sungem.c2
-rw-r--r--drivers/net/tg3.c37
-rw-r--r--drivers/net/tun.c6
-rw-r--r--drivers/net/usb/asix.c8
-rw-r--r--drivers/net/usb/cdc_ether.c30
-rw-r--r--drivers/net/usb/ipheth.c5
-rw-r--r--drivers/net/usb/kaweth.c2
-rw-r--r--drivers/net/usb/sierra_net.c16
-rw-r--r--drivers/net/usb/smsc95xx.c2
-rw-r--r--drivers/net/usb/usbnet.c54
-rw-r--r--drivers/net/wan/ixp4xx_hss.c1
-rw-r--r--drivers/net/wimax/Kconfig1
-rw-r--r--drivers/net/wimax/Makefile1
-rwxr-xr-xdrivers/net/wimax/cmc7xx/Kconfig12
-rwxr-xr-xdrivers/net/wimax/cmc7xx/Makefile5
-rwxr-xr-xdrivers/net/wimax/cmc7xx/control.c220
-rwxr-xr-xdrivers/net/wimax/cmc7xx/ctl_types.h102
-rwxr-xr-xdrivers/net/wimax/cmc7xx/download.c215
-rwxr-xr-xdrivers/net/wimax/cmc7xx/download.h57
-rwxr-xr-xdrivers/net/wimax/cmc7xx/hardware.c230
-rwxr-xr-xdrivers/net/wimax/cmc7xx/headers.h85
-rwxr-xr-xdrivers/net/wimax/cmc7xx/hw_types.h111
-rwxr-xr-xdrivers/net/wimax/cmc7xx/receive.c464
-rwxr-xr-xdrivers/net/wimax/cmc7xx/send.c303
-rwxr-xr-xdrivers/net/wimax/cmc7xx/wimax_sdio.c823
-rwxr-xr-xdrivers/net/wimax/cmc7xx/wimax_sdio.h70
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c16
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c9
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c2
-rw-r--r--drivers/net/wireless/b43legacy/main.c2
-rw-r--r--drivers/net/wireless/bcmdhd/include/wlioctl.h1
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfg80211.c11
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfg80211.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-sta.c2
-rw-r--r--drivers/net/wireless/mwifiex/11n_rxreorder.c5
-rw-r--r--drivers/net/wireless/mwifiex/11n_rxreorder.h7
-rw-r--r--drivers/net/wireless/mwifiex/wmm.c2
-rw-r--r--drivers/net/wireless/p54/p54usb.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.c9
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.h1
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c9
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c11
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.h17
-rw-r--r--drivers/net/wireless/rt2x00/rt2800pci.c9
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c10
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.c12
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.h1
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c9
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.h3
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187/dev.c2
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187/leds.c2
-rw-r--r--drivers/net/wireless/wl1251/sdio.c2
-rw-r--r--drivers/net/wireless/wl1251/spi.c3
-rw-r--r--drivers/oprofile/oprofile_perf.c2
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c7
-rw-r--r--drivers/pci/pci-driver.c19
-rw-r--r--drivers/pci/probe.c6
-rw-r--r--drivers/pci/setup-bus.c26
-rw-r--r--drivers/pcmcia/pxa2xx_sharpsl.c2
-rw-r--r--drivers/platform/x86/asus-laptop.c8
-rw-r--r--drivers/platform/x86/asus-nb-wmi.c4
-rw-r--r--drivers/platform/x86/intel_ips.c22
-rw-r--r--drivers/platform/x86/sony-laptop.c2
-rw-r--r--drivers/power/Kconfig12
-rw-r--r--drivers/power/Makefile2
-rw-r--r--drivers/power/fuel_gauge.c204
-rwxr-xr-x[-rw-r--r--]drivers/power/max17040_battery.c112
-rw-r--r--drivers/power/s3c_fake_battery.c576
-rwxr-xr-xdrivers/power/s5pc110_battery.c990
-rw-r--r--drivers/power/s5pc110_battery.h89
-rw-r--r--drivers/regulator/Kconfig5
-rw-r--r--drivers/regulator/Makefile1
-rw-r--r--drivers/regulator/max8893.c349
-rw-r--r--drivers/regulator/max8997.c2
-rw-r--r--drivers/regulator/max8998.c273
-rw-r--r--drivers/rtc/Makefile2
-rw-r--r--drivers/rtc/rtc-imxdi.c2
-rw-r--r--drivers/rtc/rtc-max8998.c48
-rw-r--r--drivers/rtc/rtc-mxc.c5
-rw-r--r--drivers/rtc/rtc-pl031.c18
-rw-r--r--drivers/rtc/rtc-rs5c348.c7
-rw-r--r--drivers/rtc/rtc-s3c.c283
-rw-r--r--drivers/rtc/rtc-s3c.h5
-rw-r--r--drivers/rtc/rtc-twl.c5
-rw-r--r--drivers/rtc/rtc-wm831x.c24
-rw-r--r--drivers/s390/scsi/zfcp_aux.c1
-rw-r--r--drivers/s390/scsi/zfcp_ccw.c73
-rw-r--r--drivers/s390/scsi/zfcp_cfdc.c2
-rw-r--r--drivers/s390/scsi/zfcp_dbf.c20
-rw-r--r--drivers/s390/scsi/zfcp_dbf.h1
-rw-r--r--drivers/s390/scsi/zfcp_def.h2
-rw-r--r--drivers/s390/scsi/zfcp_ext.h2
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c23
-rw-r--r--drivers/s390/scsi/zfcp_sysfs.c18
-rw-r--r--drivers/s390/scsi/zfcp_unit.c36
-rw-r--r--drivers/scsi/atp870u.c11
-rw-r--r--drivers/scsi/bnx2i/bnx2i_hwi.c3
-rw-r--r--drivers/scsi/device_handler/scsi_dh_alua.c3
-rw-r--r--drivers/scsi/hpsa.c43
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c3
-rw-r--r--drivers/scsi/isci/init.c3
-rw-r--r--drivers/scsi/isci/probe_roms.c1
-rw-r--r--drivers/scsi/libsas/sas_expander.c47
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_base.c3
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.c26
-rw-r--r--drivers/scsi/scsi_error.c24
-rw-r--r--drivers/scsi/scsi_lib.c22
-rw-r--r--drivers/scsi/scsi_scan.c13
-rw-r--r--drivers/scsi/scsi_sysfs.c39
-rw-r--r--drivers/scsi/scsi_wait_scan.c2
-rw-r--r--drivers/spi/spi_fsl_spi.c6
-rw-r--r--drivers/staging/comedi/comedi_fops.c7
-rw-r--r--drivers/staging/comedi/drivers/amplc_pc236.c2
-rw-r--r--drivers/staging/comedi/drivers/das08.c2
-rw-r--r--drivers/staging/comedi/drivers/jr3_pci.c2
-rw-r--r--drivers/staging/comedi/drivers/s626.c2
-rw-r--r--drivers/staging/lirc/lirc_sir.c60
-rw-r--r--drivers/staging/rtl8712/recv_linux.c7
-rw-r--r--drivers/staging/speakup/main.c2
-rw-r--r--drivers/staging/speakup/speakup_soft.c13
-rw-r--r--drivers/staging/vt6656/dpc.c2
-rw-r--r--drivers/staging/vt6656/main_usb.c2
-rw-r--r--drivers/staging/vt6656/rxtx.c38
-rw-r--r--drivers/staging/winbond/wbusb.c2
-rw-r--r--drivers/target/target_core_transport.c9
-rw-r--r--drivers/target/tcm_fc/tfc_sess.c3
-rw-r--r--drivers/tty/n_gsm.c15
-rw-r--r--drivers/tty/n_tty.c3
-rw-r--r--drivers/tty/serial/8250_pci.c9
-rw-r--r--drivers/tty/serial/amba-pl011.c15
-rw-r--r--drivers/tty/serial/mxs-auart.c2
-rw-r--r--drivers/tty/serial/pch_uart.c21
-rw-r--r--drivers/tty/serial/s5pv210.c4
-rw-r--r--drivers/tty/serial/samsung.c136
-rw-r--r--drivers/tty/serial/samsung.h7
-rw-r--r--drivers/tty/serial/serial_core.c1
-rw-r--r--drivers/usb/Kconfig4
-rw-r--r--drivers/usb/Makefile4
-rw-r--r--drivers/usb/class/cdc-acm.c36
-rw-r--r--drivers/usb/class/cdc-wdm.c4
-rw-r--r--drivers/usb/core/devices.c2
-rw-r--r--drivers/usb/core/devio.c43
-rw-r--r--drivers/usb/core/driver.c7
-rw-r--r--drivers/usb/core/hcd-pci.c9
-rw-r--r--drivers/usb/core/hcd.c10
-rw-r--r--drivers/usb/core/hub.c16
-rw-r--r--drivers/usb/core/message.c3
-rw-r--r--drivers/usb/core/quirks.c7
-rw-r--r--drivers/usb/dwc/Kconfig84
-rw-r--r--drivers/usb/dwc/Makefile17
-rw-r--r--drivers/usb/dwc/apmppc.c372
-rw-r--r--drivers/usb/dwc/cil.c893
-rw-r--r--drivers/usb/dwc/cil.h1179
-rw-r--r--drivers/usb/dwc/cil_intr.c616
-rw-r--r--drivers/usb/dwc/driver.h76
-rw-r--r--drivers/usb/dwc/hcd.c2473
-rw-r--r--drivers/usb/dwc/hcd.h416
-rw-r--r--drivers/usb/dwc/hcd_intr.c1477
-rw-r--r--drivers/usb/dwc/hcd_queue.c696
-rw-r--r--drivers/usb/dwc/param.c180
-rw-r--r--drivers/usb/dwc/pcd.c1791
-rw-r--r--drivers/usb/dwc/pcd.h139
-rw-r--r--drivers/usb/dwc/pcd_intr.c2312
-rw-r--r--drivers/usb/dwc/regs.h1326
-rw-r--r--drivers/usb/early/ehci-dbgp.c2
-rw-r--r--drivers/usb/gadget/Kconfig58
-rwxr-xr-x[-rw-r--r--]drivers/usb/gadget/Makefile1
-rw-r--r--drivers/usb/gadget/epautoconf.c54
-rw-r--r--drivers/usb/gadget/f_mass_storage.c2
-rw-r--r--drivers/usb/gadget/fsl_udc_core.c2
-rw-r--r--drivers/usb/gadget/gadget_chips.h8
-rw-r--r--drivers/usb/gadget/s3c_udc.h164
-rw-r--r--drivers/usb/gadget/s3c_udc_otg.c1547
-rw-r--r--drivers/usb/gadget/s3c_udc_otg_xfer_dma.c1387
-rw-r--r--drivers/usb/gadget/u_ether.c37
-rw-r--r--drivers/usb/host/Kconfig16
-rw-r--r--drivers/usb/host/Makefile1
-rw-r--r--drivers/usb/host/ehci-pci.c12
-rw-r--r--drivers/usb/host/ehci-q.c12
-rw-r--r--drivers/usb/host/pci-quirks.c89
-rw-r--r--drivers/usb/host/pci-quirks.h2
-rw-r--r--drivers/usb/host/s3c-otg/Makefile18
-rw-r--r--drivers/usb/host/s3c-otg/debug-mem.c55
-rw-r--r--drivers/usb/host/s3c-otg/debug-mem.h9
-rw-r--r--drivers/usb/host/s3c-otg/s3c-otg-common-common.h49
-rw-r--r--drivers/usb/host/s3c-otg/s3c-otg-common-const.h167
-rw-r--r--drivers/usb/host/s3c-otg/s3c-otg-common-datastruct.h811
-rw-r--r--drivers/usb/host/s3c-otg/s3c-otg-common-errorcode.h115
-rw-r--r--drivers/usb/host/s3c-otg/s3c-otg-common-regdef.h302
-rw-r--r--drivers/usb/host/s3c-otg/s3c-otg-hcdi-debug.h88
-rw-r--r--drivers/usb/host/s3c-otg/s3c-otg-hcdi-driver.c386
-rw-r--r--drivers/usb/host/s3c-otg/s3c-otg-hcdi-driver.h75
-rw-r--r--drivers/usb/host/s3c-otg/s3c-otg-hcdi-hcd.c708
-rw-r--r--drivers/usb/host/s3c-otg/s3c-otg-hcdi-hcd.h152
-rw-r--r--drivers/usb/host/s3c-otg/s3c-otg-hcdi-kal.h420
-rw-r--r--drivers/usb/host/s3c-otg/s3c-otg-hcdi-list.h217
-rw-r--r--drivers/usb/host/s3c-otg/s3c-otg-hcdi-memory.h191
-rw-r--r--drivers/usb/host/s3c-otg/s3c-otg-isr.c294
-rw-r--r--drivers/usb/host/s3c-otg/s3c-otg-isr.h72
-rw-r--r--drivers/usb/host/s3c-otg/s3c-otg-oci.c815
-rw-r--r--drivers/usb/host/s3c-otg/s3c-otg-oci.h86
-rw-r--r--drivers/usb/host/s3c-otg/s3c-otg-roothub.c605
-rw-r--r--drivers/usb/host/s3c-otg/s3c-otg-roothub.h65
-rw-r--r--drivers/usb/host/s3c-otg/s3c-otg-scheduler-ischeduler.c369
-rw-r--r--drivers/usb/host/s3c-otg/s3c-otg-scheduler-readyq.c264
-rw-r--r--drivers/usb/host/s3c-otg/s3c-otg-scheduler-scheduler.c424
-rw-r--r--drivers/usb/host/s3c-otg/s3c-otg-scheduler-scheduler.h100
-rw-r--r--drivers/usb/host/s3c-otg/s3c-otg-transfer-common.c810
-rw-r--r--drivers/usb/host/s3c-otg/s3c-otg-transfer-nonperiodic.c140
-rw-r--r--drivers/usb/host/s3c-otg/s3c-otg-transfer-periodic.c128
-rw-r--r--drivers/usb/host/s3c-otg/s3c-otg-transfer-transfer.h144
-rw-r--r--drivers/usb/host/s3c-otg/s3c-otg-transferchecker-bulk.c720
-rw-r--r--drivers/usb/host/s3c-otg/s3c-otg-transferchecker-bulk.h88
-rw-r--r--drivers/usb/host/s3c-otg/s3c-otg-transferchecker-checker.h66
-rw-r--r--drivers/usb/host/s3c-otg/s3c-otg-transferchecker-common.c238
-rw-r--r--drivers/usb/host/s3c-otg/s3c-otg-transferchecker-common.h79
-rw-r--r--drivers/usb/host/s3c-otg/s3c-otg-transferchecker-control.c698
-rw-r--r--drivers/usb/host/s3c-otg/s3c-otg-transferchecker-control.h99
-rw-r--r--drivers/usb/host/s3c-otg/s3c-otg-transferchecker-interrupt.c574
-rw-r--r--drivers/usb/host/s3c-otg/s3c-otg-transferchecker-interrupt.h97
-rw-r--r--drivers/usb/host/xhci-mem.c8
-rw-r--r--drivers/usb/host/xhci-pci.c12
-rw-r--r--drivers/usb/host/xhci-ring.c357
-rw-r--r--drivers/usb/host/xhci.c51
-rw-r--r--drivers/usb/host/xhci.h25
-rw-r--r--drivers/usb/misc/emi62.c2
-rw-r--r--drivers/usb/misc/usbtest.c17
-rwxr-xr-xdrivers/usb/notify/Kconfig11
-rwxr-xr-xdrivers/usb/notify/Makefile4
-rwxr-xr-xdrivers/usb/notify/host_notify_class.c262
-rw-r--r--drivers/usb/serial/cp210x.c12
-rw-r--r--drivers/usb/serial/ftdi_sio.c27
-rw-r--r--drivers/usb/serial/ftdi_sio_ids.h48
-rw-r--r--drivers/usb/serial/mct_u232.c13
-rw-r--r--drivers/usb/serial/mos7840.c41
-rw-r--r--drivers/usb/serial/opticon.c11
-rw-r--r--drivers/usb/serial/option.c496
-rw-r--r--drivers/usb/serial/qcaux.c10
-rw-r--r--drivers/usb/serial/qcserial.c6
-rw-r--r--drivers/usb/serial/sierra.c30
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c6
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.h1
-rw-r--r--drivers/usb/serial/usb-serial.c6
-rw-r--r--drivers/usb/serial/whiteheat.c1
-rw-r--r--drivers/usb/storage/unusual_devs.h13
-rw-r--r--drivers/vhost/net.c3
-rw-r--r--drivers/vhost/vhost.c2
-rw-r--r--drivers/video/Kconfig51
-rw-r--r--drivers/video/Makefile2
-rw-r--r--drivers/video/console/fbcon.c9
-rw-r--r--drivers/video/fbmem.c10
-rwxr-xr-xdrivers/video/samsung/Kconfig174
-rw-r--r--drivers/video/samsung/Makefile22
-rwxr-xr-xdrivers/video/samsung/s3cfb.c1269
-rwxr-xr-xdrivers/video/samsung/s3cfb.h375
-rw-r--r--drivers/video/samsung/s3cfb_ams701ka.c723
-rw-r--r--drivers/video/samsung/s3cfb_fimd6x.c746
-rw-r--r--drivers/video/samsung/s3cfb_ht101hd1.c46
-rw-r--r--drivers/video/samsung/s3cfb_ielcd.c186
-rw-r--r--drivers/video/samsung/s3cfb_ielcd.h100
-rw-r--r--drivers/video/samsung/s3cfb_lte480wv.c46
-rw-r--r--drivers/video/samsung/s3cfb_lvds.c199
-rw-r--r--drivers/video/samsung/s3cfb_mdnie.c1264
-rw-r--r--drivers/video/samsung/s3cfb_mdnie.h349
-rwxr-xr-xdrivers/video/samsung/s3cfb_nt35580.c273
-rwxr-xr-xdrivers/video/samsung/s3cfb_tl2796.c1221
-rw-r--r--drivers/video/samsung/tune_cmc623.c1579
-rw-r--r--drivers/video/samsung/tune_cmc623.h138
-rw-r--r--drivers/video/udlfb.c2
-rw-r--r--drivers/video/via/via_clock.c19
-rw-r--r--drivers/watchdog/hpwdt.c3
-rw-r--r--firmware/Makefile1
-rw-r--r--firmware/samsung_mfc_fw.bin.ihex18777
-rw-r--r--fs/aio.c30
-rw-r--r--fs/autofs4/root.c6
-rw-r--r--fs/binfmt_elf.c19
-rw-r--r--fs/block_dev.c6
-rw-r--r--fs/btrfs/async-thread.c9
-rw-r--r--fs/btrfs/disk-io.c5
-rw-r--r--fs/btrfs/tree-log.c6
-rw-r--r--fs/buffer.c50
-rw-r--r--fs/ceph/export.c18
-rw-r--r--fs/cifs/cifsglob.h1
-rw-r--r--fs/cifs/file.c57
-rw-r--r--fs/cifs/readdir.c7
-rw-r--r--fs/compat.c10
-rw-r--r--fs/compat_ioctl.c2
-rw-r--r--fs/dcache.c10
-rw-r--r--fs/ecryptfs/inode.c5
-rw-r--r--fs/ecryptfs/kthread.c2
-rw-r--r--fs/ecryptfs/miscdev.c48
-rw-r--r--fs/ext3/ialloc.c8
-rw-r--r--fs/ext3/inode.c17
-rw-r--r--fs/ext4/balloc.c3
-rw-r--r--fs/ext4/bitmap.c8
-rw-r--r--fs/ext4/ext4.h2
-rw-r--r--fs/ext4/ialloc.c11
-rw-r--r--fs/ext4/inode.c17
-rw-r--r--fs/ext4/ioctl.c13
-rw-r--r--fs/ext4/mballoc.c6
-rw-r--r--fs/ext4/move_extent.c7
-rw-r--r--fs/ext4/namei.c2
-rw-r--r--fs/ext4/super.c4
-rw-r--r--fs/ext4/xattr.c7
-rw-r--r--fs/fifo.c9
-rw-r--r--fs/fuse/dev.c1
-rw-r--r--fs/fuse/dir.c1
-rw-r--r--fs/fuse/file.c2
-rw-r--r--fs/fuse/fuse_i.h3
-rw-r--r--fs/fuse/inode.c17
-rw-r--r--fs/gfs2/export.c4
-rw-r--r--fs/hfsplus/wrapper.c2
-rw-r--r--fs/hugetlbfs/inode.c3
-rw-r--r--fs/ioprio.c9
-rw-r--r--fs/isofs/export.c2
-rw-r--r--fs/jbd/commit.c45
-rw-r--r--fs/jbd/transaction.c64
-rw-r--r--fs/jbd2/commit.c9
-rw-r--r--fs/jffs2/gc.c2
-rw-r--r--fs/lockd/clntxdr.c2
-rw-r--r--fs/lockd/svcproc.c3
-rw-r--r--fs/locks.c6
-rw-r--r--fs/namespace.c3
-rw-r--r--fs/nfs/file.c7
-rw-r--r--fs/nfs/inode.c2
-rw-r--r--fs/nfs/internal.h2
-rw-r--r--fs/nfs/nfs3proc.c4
-rw-r--r--fs/nfs/nfs4proc.c15
-rw-r--r--fs/nfs/nfs4xdr.c3
-rw-r--r--fs/nfs/super.c4
-rw-r--r--fs/nfs/write.c4
-rw-r--r--fs/nfsd/nfs4xdr.c2
-rw-r--r--fs/nilfs2/gcinode.c2
-rw-r--r--fs/nilfs2/ioctl.c4
-rw-r--r--fs/nilfs2/segment.c2
-rw-r--r--fs/nilfs2/super.c3
-rw-r--r--fs/nilfs2/the_nilfs.c1
-rw-r--r--fs/nilfs2/the_nilfs.h2
-rw-r--r--fs/open.c13
-rw-r--r--fs/ramfs/file-nommu.c1
-rw-r--r--fs/reiserfs/inode.c6
-rw-r--r--fs/squashfs/super.c2
-rw-r--r--fs/stat.c2
-rw-r--r--fs/super.c2
-rw-r--r--fs/sysfs/dir.c16
-rw-r--r--fs/ubifs/sb.c8
-rw-r--r--fs/udf/file.c35
-rw-r--r--fs/udf/super.c103
-rw-r--r--fs/xfs/linux-2.6/xfs_export.c3
-rw-r--r--fs/yaffs2/yaffs_vfs.c24
-rw-r--r--include/asm-generic/mutex-xchg.h11
-rw-r--r--include/asm-generic/pgtable.h22
-rw-r--r--include/asm-generic/statfs.h2
-rw-r--r--include/drm/drm_pciids.h2
-rw-r--r--include/linux/bld.h17
-rw-r--r--include/linux/bln.h13
-rw-r--r--include/linux/cgroup_subsys.h6
-rw-r--r--include/linux/cpu.h5
-rw-r--r--include/linux/cpufreq.h1
-rw-r--r--include/linux/cpuset.h47
-rw-r--r--include/linux/dcache.h2
-rw-r--r--include/linux/deep_idle.h9
-rwxr-xr-xinclude/linux/earlysuspend.h2
-rw-r--r--include/linux/fs.h12
-rw-r--r--include/linux/fsa9480.h41
-rw-r--r--include/linux/genhd.h6
-rw-r--r--include/linux/gp2a.h36
-rwxr-xr-xinclude/linux/host_notify.h53
-rw-r--r--include/linux/hrtimer.h10
-rw-r--r--include/linux/i2c/ak8973.h72
-rw-r--r--include/linux/init_task.h20
-rwxr-xr-xinclude/linux/input/cypress-touchkey.h42
-rw-r--r--include/linux/input/k3g.h40
-rw-r--r--include/linux/input/mxt224.h92
-rw-r--r--include/linux/iocontext.h18
-rw-r--r--include/linux/irqdesc.h1
-rw-r--r--include/linux/kobject.h2
-rw-r--r--include/linux/kr3dm.h46
-rw-r--r--include/linux/ktime.h7
-rwxr-xr-x[-rw-r--r--]include/linux/max17040_battery.h4
-rw-r--r--include/linux/memcontrol.h3
-rw-r--r--include/linux/memory.h2
-rw-r--r--include/linux/mempolicy.h2
-rw-r--r--include/linux/mfd/ezx-pcap.h1
-rwxr-xr-x[-rw-r--r--]include/linux/mfd/max8998-private.h141
-rwxr-xr-x[-rw-r--r--]include/linux/mfd/max8998.h34
-rwxr-xr-xinclude/linux/mfd/wm8994/wm8994_pdata.h24
-rw-r--r--include/linux/migrate.h23
-rw-r--r--include/linux/mmc/host.h3
-rw-r--r--include/linux/mmc/sdhci.h5
-rw-r--r--include/linux/mmzone.h16
-rw-r--r--include/linux/mtd/onenand.h1
-rw-r--r--include/linux/netdevice.h11
-rw-r--r--include/linux/nfs_fs.h5
-rwxr-xr-xinclude/linux/nt35580.h27
-rw-r--r--include/linux/pci_ids.h1
-rw-r--r--include/linux/perf_event.h2
-rwxr-xr-xinclude/linux/pn544.h33
-rw-r--r--include/linux/random.h19
-rw-r--r--include/linux/regulator/max8893.h53
-rw-r--r--include/linux/sched.h7
-rwxr-xr-xinclude/linux/sec_jack.h60
-rw-r--r--include/linux/seqlock.h2
-rw-r--r--include/linux/skbuff.h2
-rw-r--r--include/linux/swap.h7
-rw-r--r--include/linux/time.h29
-rw-r--r--include/linux/timex.h2
-rwxr-xr-xinclude/linux/tl2796.h68
-rw-r--r--include/linux/usb.h21
-rw-r--r--include/linux/usb/gadget.h1
-rw-r--r--include/linux/usb/hcd.h11
-rw-r--r--include/linux/usb/usbnet.h3
-rwxr-xr-xinclude/linux/videodev2_samsung.h624
-rw-r--r--include/linux/wimax/samsung/wimax732.h78
-rw-r--r--include/linux/xfrm.h2
-rw-r--r--include/media/s5k4ecgx.h24
-rw-r--r--include/media/s5ka3dfx_platform.h22
-rw-r--r--include/net/cipso_ipv4.h29
-rw-r--r--include/net/dst.h1
-rw-r--r--include/net/ip_vs.h2
-rw-r--r--include/net/netfilter/nf_conntrack_ecache.h1
-rw-r--r--include/net/sch_generic.h7
-rw-r--r--include/net/sctp/sctp.h13
-rw-r--r--include/net/sock.h2
-rw-r--r--include/net/xfrm.h3
-rw-r--r--include/trace/events/kmem.h4
-rw-r--r--include/trace/events/random.h134
-rw-r--r--include/trace/events/vmscan.h85
-rw-r--r--init/do_mounts.c2
-rw-r--r--init/main.c7
-rw-r--r--kernel/async.c13
-rw-r--r--kernel/audit_tree.c11
-rw-r--r--kernel/cgroup.c3
-rw-r--r--kernel/compat.c63
-rw-r--r--kernel/cpuset.c66
-rw-r--r--kernel/events/core.c62
-rw-r--r--kernel/exit.c16
-rw-r--r--kernel/fork.c6
-rw-r--r--kernel/futex.c17
-rw-r--r--kernel/hrtimer.c53
-rw-r--r--kernel/irq/chip.c6
-rw-r--r--kernel/irq/handle.c7
-rw-r--r--kernel/irq/manage.c17
-rw-r--r--kernel/module.c4
-rw-r--r--kernel/power/earlysuspend.c40
-rw-r--r--kernel/power/fbearlysuspend.c3
-rw-r--r--kernel/power/hibernate.c6
-rw-r--r--kernel/power/suspend.c11
-rw-r--r--kernel/rcutree.c4
-rw-r--r--kernel/sched.c81
-rw-r--r--kernel/sys.c13
-rw-r--r--kernel/time/ntp.c128
-rw-r--r--kernel/time/timekeeping.c145
-rw-r--r--kernel/timer.c10
-rw-r--r--kernel/trace/trace.c2
-rw-r--r--kernel/workqueue.c83
-rw-r--r--lib/btree.c4
-rw-r--r--lib/gcd.c3
-rw-r--r--lib/genalloc.c2
-rw-r--r--lib/xz/xz_dec_stream.c1
-rw-r--r--mm/compaction.c46
-rw-r--r--mm/filemap.c11
-rw-r--r--mm/hugetlb.c68
-rw-r--r--mm/madvise.c16
-rw-r--r--mm/memcontrol.c9
-rw-r--r--mm/memory-failure.c6
-rw-r--r--mm/memory_hotplug.c18
-rw-r--r--mm/mempolicy.c148
-rw-r--r--mm/migrate.c240
-rw-r--r--mm/mmu_notifier.c45
-rw-r--r--mm/nobootmem.c3
-rw-r--r--mm/page_alloc.c120
-rw-r--r--mm/percpu.c10
-rw-r--r--mm/shmem.c6
-rw-r--r--mm/slab.c13
-rw-r--r--mm/slub.c40
-rw-r--r--mm/truncate.c3
-rw-r--r--mm/vmalloc.c11
-rw-r--r--mm/vmscan.c305
-rw-r--r--mm/vmstat.c2
-rw-r--r--net/8021q/vlan_core.c3
-rw-r--r--net/8021q/vlan_dev.c2
-rw-r--r--net/atm/common.c1
-rw-r--r--net/atm/pvc.c1
-rw-r--r--net/bluetooth/hci_sock.c2
-rw-r--r--net/bluetooth/l2cap_sock.c1
-rw-r--r--net/bluetooth/rfcomm/sock.c1
-rw-r--r--net/bluetooth/rfcomm/tty.c2
-rw-r--r--net/bridge/br_if.c1
-rw-r--r--net/bridge/br_netlink.c2
-rw-r--r--net/bridge/br_private.h1
-rw-r--r--net/caif/caif_dev.c2
-rw-r--r--net/core/dev.c87
-rw-r--r--net/core/drop_monitor.c113
-rw-r--r--net/core/ethtool.c1
-rw-r--r--net/core/neighbour.c6
-rw-r--r--net/core/net_namespace.c4
-rw-r--r--net/core/netpoll.c11
-rw-r--r--net/core/pktgen.c12
-rw-r--r--net/core/rtnetlink.c9
-rw-r--r--net/core/sock.c11
-rw-r--r--net/dccp/ccid.h4
-rw-r--r--net/dccp/ccids/ccid3.c1
-rw-r--r--net/ipv4/cipso_ipv4.c6
-rw-r--r--net/ipv4/esp4.c24
-rw-r--r--net/ipv4/fib_semantics.c20
-rw-r--r--net/ipv4/fib_trie.c2
-rw-r--r--net/ipv4/ipmr.c14
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c8
-rw-r--r--net/ipv4/netfilter/nf_nat_sip.c10
-rw-r--r--net/ipv4/raw.c14
-rw-r--r--net/ipv4/tcp.c31
-rw-r--r--net/ipv4/tcp_cong.c3
-rw-r--r--net/ipv4/tcp_input.c8
-rw-r--r--net/ipv4/tcp_ipv4.c7
-rw-r--r--net/ipv4/tcp_output.c21
-rw-r--r--net/ipv6/addrconf.c4
-rw-r--r--net/ipv6/esp6.c18
-rw-r--r--net/ipv6/ip6_output.c68
-rw-r--r--net/ipv6/mip6.c20
-rw-r--r--net/ipv6/raw.c21
-rw-r--r--net/ipv6/route.c52
-rw-r--r--net/ipv6/tcp_ipv6.c3
-rw-r--r--net/l2tp/l2tp_core.c3
-rw-r--r--net/l2tp/l2tp_core.h1
-rw-r--r--net/l2tp/l2tp_eth.c4
-rw-r--r--net/l2tp/l2tp_ip.c33
-rw-r--r--net/llc/af_llc.c3
-rw-r--r--net/mac80211/iface.c12
-rw-r--r--net/mac80211/mesh.c1
-rw-r--r--net/mac80211/offchannel.c16
-rw-r--r--net/mac80211/rx.c5
-rw-r--r--net/mac80211/util.c12
-rw-r--r--net/mac80211/wpa.c3
-rw-r--r--net/netfilter/ipvs/ip_vs_ctl.c6
-rw-r--r--net/netfilter/nf_conntrack_core.c16
-rw-r--r--net/netfilter/nf_conntrack_expect.c29
-rw-r--r--net/netfilter/xt_hashlimit.c8
-rw-r--r--net/netfilter/xt_limit.c13
-rw-r--r--net/netlink/af_netlink.c4
-rw-r--r--net/netrom/af_netrom.c7
-rw-r--r--net/packet/af_packet.c1
-rw-r--r--net/phonet/af_phonet.c2
-rw-r--r--net/phonet/socket.c2
-rw-r--r--net/rds/recv.c3
-rw-r--r--net/rds/send.c2
-rw-r--r--net/sched/act_gact.c14
-rw-r--r--net/sched/sch_cbq.c5
-rw-r--r--net/sched/sch_netem.c6
-rw-r--r--net/sched/sch_qfq.c5
-rw-r--r--net/sched/sch_sfb.c2
-rw-r--r--net/sctp/input.c7
-rw-r--r--net/sctp/output.c25
-rw-r--r--net/sctp/socket.c12
-rw-r--r--net/sctp/transport.c17
-rw-r--r--net/socket.c1
-rw-r--r--net/sunrpc/cache.c4
-rw-r--r--net/sunrpc/rpcb_clnt.c4
-rw-r--r--net/sunrpc/sched.c2
-rw-r--r--net/sunrpc/svc.c3
-rw-r--r--net/sunrpc/svc_xprt.c10
-rw-r--r--net/sunrpc/svcsock.c2
-rw-r--r--net/sunrpc/xprtrdma/transport.c3
-rw-r--r--net/sunrpc/xprtsock.c72
-rw-r--r--net/wanrouter/wanmain.c51
-rw-r--r--net/wireless/core.c5
-rw-r--r--net/wireless/core.h1
-rw-r--r--net/wireless/reg.c24
-rw-r--r--net/wireless/util.c26
-rw-r--r--net/xfrm/xfrm_input.c2
-rw-r--r--net/xfrm/xfrm_policy.c5
-rw-r--r--net/xfrm/xfrm_replay.c15
-rw-r--r--net/xfrm/xfrm_user.c57
-rw-r--r--scripts/Kbuild.include2
-rw-r--r--security/selinux/selinuxfs.c1
-rw-r--r--sound/drivers/aloop.c6
-rw-r--r--sound/drivers/mpu401/mpu401_uart.c1
-rw-r--r--sound/pci/ac97/ac97_codec.c2
-rw-r--r--sound/pci/echoaudio/echoaudio_dsp.c2
-rw-r--r--sound/pci/emu10k1/emu10k1_main.c9
-rw-r--r--sound/pci/hda/hda_intel.c6
-rw-r--r--sound/pci/hda/hda_proc.c2
-rw-r--r--sound/pci/hda/patch_realtek.c2
-rw-r--r--sound/pci/ice1712/prodigy_hifi.c3
-rw-r--r--sound/soc/Kconfig2
-rw-r--r--sound/soc/codecs/Kconfig3
-rw-r--r--sound/soc/codecs/Kconfig.voodoo60
-rw-r--r--sound/soc/codecs/Makefile13
-rw-r--r--sound/soc/codecs/tlv320aic3x.c4
-rw-r--r--sound/soc/codecs/tlv320aic3x.h1
-rw-r--r--sound/soc/codecs/wm8962.c3
-rw-r--r--sound/soc/codecs/wm8994.c2
-rw-r--r--sound/soc/codecs/wm8994.h265
-rw-r--r--sound/soc/codecs/wm8994_def.h9147
-rwxr-xr-xsound/soc/codecs/wm8994_herring.c3988
-rwxr-xr-xsound/soc/codecs/wm8994_samsung.c3219
-rwxr-xr-xsound/soc/codecs/wm8994_samsung.h207
-rw-r--r--sound/soc/codecs/wm8994_voodoo.c1872
-rw-r--r--sound/soc/codecs/wm8994_voodoo.h67
-rw-r--r--sound/soc/codecs/wm9712.c21
-rw-r--r--sound/soc/samsung/Kconfig20
-rw-r--r--sound/soc/samsung/Makefile7
-rw-r--r--sound/soc/samsung/dma.c25
-rw-r--r--sound/soc/samsung/dma.h2
-rw-r--r--sound/soc/samsung/herring-wm8994.c358
-rw-r--r--sound/soc/samsung/i2s.c65
-rw-r--r--sound/soc/samsung/s3c-dma-wrapper.c267
-rw-r--r--sound/soc/samsung/s3c-dma.c478
-rw-r--r--sound/soc/samsung/s3c-dma.h33
-rw-r--r--sound/soc/samsung/s3c-idma.c533
-rw-r--r--sound/soc/samsung/s3c-idma.h37
-rw-r--r--sound/soc/samsung/s5p-i2s_sec.c355
-rw-r--r--sound/soc/samsung/s5pc1xx-i2s.c1152
-rw-r--r--sound/soc/samsung/s5pc1xx-i2s.h124
-rw-r--r--sound/usb/clock.c3
-rw-r--r--sound/usb/mixer.c7
-rw-r--r--sound/usb/pcm.c3
-rw-r--r--sound/usb/quirks-table.h53
-rw-r--r--tools/usb/ffs-test.c2
-rw-r--r--usr/gen_init_cpio.c43
1270 files changed, 245418 insertions, 4438 deletions
diff --git a/.gitignore b/.gitignore
index 9dacde0..bafea10 100644
--- a/.gitignore
+++ b/.gitignore
@@ -44,6 +44,10 @@ modules.builtin
/System.map
/Module.markers
/Module.symvers
+/build
+/bin/kernel.cyano.*.zip
+/bin/kernel/zImage
+/bin/kernel/system/lib/modules
#
# git files that we don't want to ignore even it they are dot-files
diff --git a/Documentation/HOWTO b/Documentation/HOWTO
index f7ade3b..59c080f 100644
--- a/Documentation/HOWTO
+++ b/Documentation/HOWTO
@@ -218,16 +218,16 @@ The development process
Linux kernel development process currently consists of a few different
main kernel "branches" and lots of different subsystem-specific kernel
branches. These different branches are:
- - main 2.6.x kernel tree
- - 2.6.x.y -stable kernel tree
- - 2.6.x -git kernel patches
+ - main 3.x kernel tree
+ - 3.x.y -stable kernel tree
+ - 3.x -git kernel patches
- subsystem specific kernel trees and patches
- - the 2.6.x -next kernel tree for integration tests
+ - the 3.x -next kernel tree for integration tests
-2.6.x kernel tree
+3.x kernel tree
-----------------
-2.6.x kernels are maintained by Linus Torvalds, and can be found on
-kernel.org in the pub/linux/kernel/v2.6/ directory. Its development
+3.x kernels are maintained by Linus Torvalds, and can be found on
+kernel.org in the pub/linux/kernel/v3.x/ directory. Its development
process is as follows:
- As soon as a new kernel is released a two weeks window is open,
during this period of time maintainers can submit big diffs to
@@ -262,20 +262,20 @@ mailing list about kernel releases:
released according to perceived bug status, not according to a
preconceived timeline."
-2.6.x.y -stable kernel tree
+3.x.y -stable kernel tree
---------------------------
-Kernels with 4-part versions are -stable kernels. They contain
+Kernels with 3-part versions are -stable kernels. They contain
relatively small and critical fixes for security problems or significant
-regressions discovered in a given 2.6.x kernel.
+regressions discovered in a given 3.x kernel.
This is the recommended branch for users who want the most recent stable
kernel and are not interested in helping test development/experimental
versions.
-If no 2.6.x.y kernel is available, then the highest numbered 2.6.x
+If no 3.x.y kernel is available, then the highest numbered 3.x
kernel is the current stable kernel.
-2.6.x.y are maintained by the "stable" team <stable@vger.kernel.org>, and
+3.x.y are maintained by the "stable" team <stable@vger.kernel.org>, and
are released as needs dictate. The normal release period is approximately
two weeks, but it can be longer if there are no pressing problems. A
security-related problem, instead, can cause a release to happen almost
@@ -285,7 +285,7 @@ The file Documentation/stable_kernel_rules.txt in the kernel tree
documents what kinds of changes are acceptable for the -stable tree, and
how the release process works.
-2.6.x -git patches
+3.x -git patches
------------------
These are daily snapshots of Linus' kernel tree which are managed in a
git repository (hence the name.) These patches are usually released
@@ -317,13 +317,13 @@ revisions to it, and maintainers can mark patches as under review,
accepted, or rejected. Most of these patchwork sites are listed at
http://patchwork.kernel.org/.
-2.6.x -next kernel tree for integration tests
+3.x -next kernel tree for integration tests
---------------------------------------------
-Before updates from subsystem trees are merged into the mainline 2.6.x
+Before updates from subsystem trees are merged into the mainline 3.x
tree, they need to be integration-tested. For this purpose, a special
testing repository exists into which virtually all subsystem trees are
pulled on an almost daily basis:
- http://git.kernel.org/?p=linux/kernel/git/sfr/linux-next.git
+ http://git.kernel.org/?p=linux/kernel/git/next/linux-next.git
http://linux.f-seidel.de/linux-next/pmwiki/
This way, the -next kernel gives a summary outlook onto what will be
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index aa47be7..397ee05 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1764,6 +1764,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
noresidual [PPC] Don't use residual data on PReP machines.
+ nordrand [X86] Disable the direct use of the RDRAND
+ instruction even if it is supported by the
+ processor. RDRAND is still available to user
+ space applications.
+
noresume [SWSUSP] Disables resume and restores original swap
space.
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index bfe9242..7d4ecaa 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -147,7 +147,7 @@ tcp_adv_win_scale - INTEGER
(if tcp_adv_win_scale > 0) or bytes-bytes/2^(-tcp_adv_win_scale),
if it is <= 0.
Possible values are [-31, 31], inclusive.
- Default: 2
+ Default: 1
tcp_allowed_congestion_control - STRING
Show/set the congestion control choices available to non-privileged
@@ -407,7 +407,7 @@ tcp_rmem - vector of 3 INTEGERs: min, default, max
net.core.rmem_max. Calling setsockopt() with SO_RCVBUF disables
automatic tuning of that socket's receive buffer size, in which
case this value is ignored.
- Default: between 87380B and 4MB, depending on RAM size.
+ Default: between 87380B and 6MB, depending on RAM size.
tcp_sack - BOOLEAN
Enable select acknowledgments (SACKS).
diff --git a/Documentation/stable_kernel_rules.txt b/Documentation/stable_kernel_rules.txt
index 21fd05c..22bf11b 100644
--- a/Documentation/stable_kernel_rules.txt
+++ b/Documentation/stable_kernel_rules.txt
@@ -1,4 +1,4 @@
-Everything you ever wanted to know about Linux 2.6 -stable releases.
+Everything you ever wanted to know about Linux -stable releases.
Rules on what kind of patches are accepted, and which ones are not, into the
"-stable" tree:
@@ -12,6 +12,12 @@ Rules on what kind of patches are accepted, and which ones are not, into the
marked CONFIG_BROKEN), an oops, a hang, data corruption, a real
security issue, or some "oh, that's not good" issue. In short, something
critical.
+ - Serious issues as reported by a user of a distribution kernel may also
+ be considered if they fix a notable performance or interactivity issue.
+ As these fixes are not as obvious and have a higher risk of a subtle
+ regression they should only be submitted by a distribution kernel
+ maintainer and include an addendum linking to a bugzilla entry if it
+ exists and additional information on the user-visible impact.
- New device IDs and quirks are also accepted.
- No "theoretical race condition" issues, unless an explanation of how the
race can be exploited is also provided.
@@ -35,10 +41,10 @@ Procedure for submitting patches to the -stable tree:
cherry-picked than this can be specified in the following format in
the sign-off area:
- Cc: <stable@vger.kernel.org> # .32.x: a1f84a3: sched: Check for idle
- Cc: <stable@vger.kernel.org> # .32.x: 1b9508f: sched: Rate-limit newidle
- Cc: <stable@vger.kernel.org> # .32.x: fd21073: sched: Fix affinity logic
- Cc: <stable@vger.kernel.org> # .32.x
+ Cc: <stable@vger.kernel.org> # 3.3.x: a1f84a3: sched: Check for idle
+ Cc: <stable@vger.kernel.org> # 3.3.x: 1b9508f: sched: Rate-limit newidle
+ Cc: <stable@vger.kernel.org> # 3.3.x: fd21073: sched: Fix affinity logic
+ Cc: <stable@vger.kernel.org> # 3.3.x
Signed-off-by: Ingo Molnar <mingo@elte.hu>
The tag sequence has the meaning of:
@@ -72,6 +78,15 @@ Review cycle:
security kernel team, and not go through the normal review cycle.
Contact the kernel security team for more details on this procedure.
+Trees:
+
+ - The queues of patches, for both completed versions and in progress
+ versions can be found at:
+ http://git.kernel.org/?p=linux/kernel/git/stable/stable-queue.git
+ - The finalized and tagged releases of all stable kernels can be found
+ in separate branches per version at:
+ http://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git
+
Review committee:
diff --git a/Documentation/trace/postprocess/trace-vmscan-postprocess.pl b/Documentation/trace/postprocess/trace-vmscan-postprocess.pl
index 12cecc8..4a37c47 100644
--- a/Documentation/trace/postprocess/trace-vmscan-postprocess.pl
+++ b/Documentation/trace/postprocess/trace-vmscan-postprocess.pl
@@ -379,10 +379,10 @@ EVENT_PROCESS:
# To closer match vmstat scanning statistics, only count isolate_both
# and isolate_inactive as scanning. isolate_active is rotation
- # isolate_inactive == 0
- # isolate_active == 1
- # isolate_both == 2
- if ($isolate_mode != 1) {
+ # isolate_inactive == 1
+ # isolate_active == 2
+ # isolate_both == 3
+ if ($isolate_mode != 2) {
$perprocesspid{$process_pid}->{HIGH_NR_SCANNED} += $nr_scanned;
}
$perprocesspid{$process_pid}->{HIGH_NR_CONTIG_DIRTY} += $nr_contig_dirty;
diff --git a/Documentation/usb/s3c-otg-host.txt b/Documentation/usb/s3c-otg-host.txt
new file mode 100644
index 0000000..97e7f91
--- /dev/null
+++ b/Documentation/usb/s3c-otg-host.txt
@@ -0,0 +1,83 @@
+This file is a collection of notes on using the USB OTG port of the Samsung Galaxy Tab in HOST mode.
+
+1/17/12 - Zsolt Sz. Sztupak, mail@sztupy.hu, http://android.sztupy.hu
+
+Kevin's patch to the kernel was great, but it had some problems, namely:
+* it was based on an old Froyo (or Eclair?) branch of the kernel, which still had a lot of old code, and methods
+ that were deprecated in later kernel versions
+* the actual client/host changing code was put inside the 30pin connector file, which only exists in the Galaxy
+ Tab based Kernels
+
+The changes I've made are the following:
+* port some of the deprecated code to kernel version 3.x
+* change the otg detector/switcher code from the 30 pin connector module to the s3c otg gadget (client mode) module
+
+There is still a lof code not ported from the old kernel branch as it uses a lot of ugly old samsung kernel code,
+which are non existent in later kernel versions. These include interrupt, LDO and clock switchings, which might
+be the case of some of the hangups.
+
+8/24/11 - Kevin Hester, kevin@ridemission.com
+
+I'm writing this document to capture both the software and hardware changes needed for this device in one place.
+If you are a brave Android kernel hacker, please try these changes out and send pull requests to github with any
+fixes you add. I have been unable to find a 'master' github site where hobbyists are maintaining a master Samsung
+kernel and Android OS, if you have such a site feel free to include my fixes (though credit would be appreciated).
+These fixes are provided 'as-is' and you could bust your device or do any number of bad things.
+
+I'm going to post these notes on the xda forums, but for the latest code and documentation please see my github site.
+
+History: The Samsung open source kernel files (from opensource.samsung.com) contained a USB host mode driver for the
+S5PC110 chipset. These drivers were located in drivers/usb/host/s3c-otg. The driver contained a number of bugs which
+I've fixed and it now seems to work reasonably well for USB serial ports, flash drives etc.
+
+Hardware: To use USB host mode on your samsung tablet _external 5V DC seems to be required_. I have not found
+turning any of the samsung LDOs on to make the unit provide USB power (if you find different, please let me know).
+
+To wire up a USB host mode cable you'll need the following pinout (found on a web forum):
+1 Gnd P
+2 Gnd P
+3 USB_DP_CON I/O
+4 USB_DM_CON I/O
+5 IF_CON_SENSE I
+6 V_ACCESSORY_5.0V P
+7 V_BUS_1 P
+8 V_BUS_1 P
+9 VOUT_CHARGER P (gives out 4v when checked with a multimeter)
+10 VOUT_CHARGER P (gives out 4v when checked with a multimeter)
+11 --- --
+12 --- --
+13 ACCESSORY_ID / USB_ID I
+14 ACCESSORY_INT I
+15 Gnd P
+16 Gnd P
+17 MHL_DP I/O
+18 MHL_DM I/O
+19 MHL_ID I
+20 IF_RXD I
+21 IF_TXD O
+22 --- --
+23 AP_TV_OUT O
+24 REMOTE_SENSE I
+25 --- --
+26 --- --
+27 EAR_L_CRADLE O
+28 EAR_R_CRADLE O
+29 3.5_INT_TEST I
+30 Gnd P
+
+Your cable will need to connect the following five pins:
+1 Gnd
+3 USB_DP
+4 USB_DM
+8 5V+ (at least 1A if you want to support high speed charging of the tablet)
+13 Host mode (attach to ground to run tablet as a host, or leave disconnected to run tablet as a USB target)
+
+A summary of my driver changes:
+* Fix a nubmer of cases where TDs would be used after delete_td and the associated storage was freed (caused kernel
+heap corruption)
+* Allow a bit more time for some mystery Samsung LDO to power up before switching to host mode (caused failure in device detect)
+* Wait for channel disabled interrupt when cancelling transactions (prevents a race condition with the ISR)
+* Properly switch into USB host mode when a host mode cable is detected (see 30pin_con.c)
+* Mark transfers as done when cancel_to_transfer_td is called (prevents rescheduling transactions we have freed)
+* do not force is_need_to_insert_scheduler true in cancel_transfer, this caused list corruption in the ed list
+
diff --git a/MAINTAINERS b/MAINTAINERS
index b0209fb..74c8e4b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5247,7 +5247,7 @@ F: Documentation/blockdev/ramdisk.txt
F: drivers/block/brd.c
RANDOM NUMBER DRIVER
-M: Matt Mackall <mpm@selenic.com>
+M: Theodore Ts'o" <tytso@mit.edu>
S: Maintained
F: drivers/char/random.c
diff --git a/Makefile b/Makefile
index ac9701b..0210b63 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
VERSION = 3
PATCHLEVEL = 0
-SUBLEVEL = 31
+SUBLEVEL = 50
EXTRAVERSION =
NAME = Sneaky Weasel
diff --git a/arch/alpha/include/asm/atomic.h b/arch/alpha/include/asm/atomic.h
index e756d04..b15162f 100644
--- a/arch/alpha/include/asm/atomic.h
+++ b/arch/alpha/include/asm/atomic.h
@@ -14,8 +14,8 @@
*/
-#define ATOMIC_INIT(i) ( (atomic_t) { (i) } )
-#define ATOMIC64_INIT(i) ( (atomic64_t) { (i) } )
+#define ATOMIC_INIT(i) { (i) }
+#define ATOMIC64_INIT(i) { (i) }
#define atomic_read(v) (*(volatile int *)&(v)->counter)
#define atomic64_read(v) (*(volatile long *)&(v)->counter)
diff --git a/arch/alpha/include/asm/socket.h b/arch/alpha/include/asm/socket.h
index 06edfef..3eeb47c 100644
--- a/arch/alpha/include/asm/socket.h
+++ b/arch/alpha/include/asm/socket.h
@@ -69,9 +69,11 @@
#define SO_RXQ_OVFL 40
+#ifdef __KERNEL__
/* O_NONBLOCK clashes with the bits used for socket types. Therefore we
* have to define SOCK_NONBLOCK to a different value here.
*/
#define SOCK_NONBLOCK 0x40000000
+#endif /* __KERNEL__ */
#endif /* _ASM_SOCKET_H */
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index d8e2570..ed96fa0 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -20,6 +20,7 @@ config ARM
select HAVE_KERNEL_GZIP
select HAVE_KERNEL_LZO
select HAVE_KERNEL_LZMA
+ select HAVE_KERNEL_XZ
select HAVE_IRQ_WORK
select HAVE_PERF_EVENTS
select PERF_USE_VMALLOC
@@ -749,12 +750,13 @@ config ARCH_S5PV210
bool "Samsung S5PV210/S5PC110"
select CPU_V7
select ARCH_SPARSEMEM_ENABLE
+ select ARCH_HAS_HOLES_MEMORYMODEL
select GENERIC_GPIO
select HAVE_CLK
select ARM_L1_CACHE_SHIFT_6
select ARCH_HAS_CPUFREQ
select GENERIC_CLOCKEVENTS
- select HAVE_SCHED_CLOCK
+ select HAVE_SCHED_CLOCK if !S5P_HIGH_RES_TIMERS
select HAVE_S3C2410_I2C if I2C
select HAVE_S3C_RTC if RTC_CLASS
select HAVE_S3C2410_WATCHDOG if WATCHDOG
@@ -1234,6 +1236,42 @@ config ARM_ERRATA_754327
This workaround defines cpu_relax() as smp_mb(), preventing correctly
written polling loops from denying visibility of updates to memory.
+config ARM_ERRATA_764369
+ bool "ARM errata: Data cache line maintenance operation by MVA may not succeed"
+ depends on CPU_V7 && SMP
+ help
+ This option enables the workaround for erratum 764369
+ affecting Cortex-A9 MPCore with two or more processors (all
+ current revisions). Under certain timing circumstances, a data
+ cache line maintenance operation by MVA targeting an Inner
+ Shareable memory region may fail to proceed up to either the
+ Point of Coherency or to the Point of Unification of the
+ system. This workaround adds a DSB instruction before the
+ relevant cache maintenance functions and sets a specific bit
+ in the diagnostic control register of the SCU.
+
+config PL310_ERRATA_769419
+ bool "PL310 errata: no automatic Store Buffer drain"
+ depends on CACHE_L2X0
+ help
+ On revisions of the PL310 prior to r3p2, the Store Buffer does
+ not automatically drain. This can cause normal, non-cacheable
+ writes to be retained when the memory system is idle, leading
+ to suboptimal I/O performance for drivers using coherent DMA.
+ This option adds a write barrier to the cpu_idle loop so that,
+ on systems with an outer cache, the store buffer is drained
+ explicitly.
+
+config ARM_ERRATA_775420
+ bool "ARM errata: A data cache maintenance operation which aborts, might lead to deadlock"
+ depends on CPU_V7
+ help
+ This option enables the workaround for the 775420 Cortex-A9 (r2p2,
+ r2p6,r2p8,r2p10,r3p0) erratum. In case a date cache maintenance
+ operation aborts with MMU exception, it might cause the processor
+ to deadlock. This workaround puts DSB before executing ISB if
+ an abort may occur on cache maintenance.
+
endmenu
source "arch/arm/common/Kconfig"
@@ -1298,32 +1336,6 @@ source "drivers/pci/Kconfig"
source "drivers/pcmcia/Kconfig"
-config ARM_ERRATA_764369
- bool "ARM errata: Data cache line maintenance operation by MVA may not succeed"
- depends on CPU_V7 && SMP
- help
- This option enables the workaround for erratum 764369
- affecting Cortex-A9 MPCore with two or more processors (all
- current revisions). Under certain timing circumstances, a data
- cache line maintenance operation by MVA targeting an Inner
- Shareable memory region may fail to proceed up to either the
- Point of Coherency or to the Point of Unification of the
- system. This workaround adds a DSB instruction before the
- relevant cache maintenance functions and sets a specific bit
- in the diagnostic control register of the SCU.
-
-config PL310_ERRATA_769419
- bool "PL310 errata: no automatic Store Buffer drain"
- depends on CACHE_L2X0
- help
- On revisions of the PL310 prior to r3p2, the Store Buffer does
- not automatically drain. This can cause normal, non-cacheable
- writes to be retained when the memory system is idle, leading
- to suboptimal I/O performance for drivers using coherent DMA.
- This option adds a write barrier to the cpu_idle loop so that,
- on systems with an outer cache, the store buffer is drained
- explicitly.
-
endmenu
menu "Kernel Features"
@@ -1434,6 +1446,7 @@ source kernel/Kconfig.preempt
config HZ
int
+ default 256 if S5P_HIGH_RES_TIMERS
default 200 if ARCH_EBSA110 || ARCH_S3C2410 || ARCH_S5P64X0 || \
ARCH_S5PV210 || ARCH_EXYNOS4
default OMAP_32K_TIMER_HZ if ARCH_OMAP && OMAP_32K_TIMER
@@ -1884,6 +1897,7 @@ source "drivers/cpufreq/Kconfig"
config CPU_FREQ_IMX
tristate "CPUfreq driver for i.MX CPUs"
depends on ARCH_MXC && CPU_FREQ
+ select CPU_FREQ_TABLE
help
This enables the CPUfreq driver for i.MX CPUs.
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 23aad07..777f70d 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -79,16 +79,17 @@ endif
SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/
-suffix_$(CONFIG_KERNEL_GZIP) = gzip
-suffix_$(CONFIG_KERNEL_LZO) = lzo
-suffix_$(CONFIG_KERNEL_LZMA) = lzma
+suffix_$(CONFIG_KERNEL_GZIP) := gzip
+suffix_$(CONFIG_KERNEL_LZO) := lzo
+suffix_$(CONFIG_KERNEL_LZMA) := lzma
+suffix_$(CONFIG_KERNEL_XZ) := xzkern
targets := vmlinux vmlinux.lds \
piggy.$(suffix_y) piggy.$(suffix_y).o \
font.o font.c head.o misc.o $(OBJS)
# Make sure files are removed during clean
-extra-y += piggy.gzip piggy.lzo piggy.lzma lib1funcs.S
+extra-y += piggy.gzip piggy.lzo piggy.lzma piggy.xzkern lib1funcs.S ashldi3.S
ifeq ($(CONFIG_FUNCTION_TRACER),y)
ORIG_CFLAGS := $(KBUILD_CFLAGS)
@@ -120,6 +121,12 @@ lib1funcs = $(obj)/lib1funcs.o
$(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S FORCE
$(call cmd,shipped)
+# For __aeabi_llsl
+ashldi3 = $(obj)/ashldi3.o
+
+$(obj)/ashldi3.S: $(srctree)/arch/$(SRCARCH)/lib/ashldi3.S FORCE
+ $(call cmd,shipped)
+
# We need to prevent any GOTOFF relocs being used with references
# to symbols in the .bss section since we cannot relocate them
# independently from the rest at run time. This can be achieved by
@@ -134,7 +141,7 @@ bad_syms=$$($(CROSS_COMPILE)nm $@ | sed -n 's/^.\{8\} [bc] \(.*\)/\1/p') && \
echo "$$bad_syms" >&2; rm -f $@; false )
$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \
- $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) FORCE
+ $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) $(ashldi3) FORCE
$(call if_changed,ld)
@$(check_for_bad_syms)
diff --git a/arch/arm/boot/compressed/decompress.c b/arch/arm/boot/compressed/decompress.c
index 07be5a2..0ecd8b4 100644
--- a/arch/arm/boot/compressed/decompress.c
+++ b/arch/arm/boot/compressed/decompress.c
@@ -44,6 +44,10 @@ extern void error(char *);
#include "../../../../lib/decompress_unlzma.c"
#endif
+#ifdef CONFIG_KERNEL_XZ
+#include "../../../../lib/decompress_unxz.c"
+#endif
+
int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x))
{
return decompress(input, len, NULL, NULL, output, NULL, error);
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index e58603b..caddb9d 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -539,6 +539,7 @@ __armv7_mmu_cache_on:
mcrne p15, 0, r0, c8, c7, 0 @ flush I,D TLBs
#endif
mrc p15, 0, r0, c1, c0, 0 @ read control reg
+ bic r0, r0, #1 << 28 @ clear SCTLR.TRE
orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement
orr r0, r0, #0x003c @ write buffer
#ifdef CONFIG_MMU
diff --git a/arch/arm/boot/compressed/piggy.xzkern.S b/arch/arm/boot/compressed/piggy.xzkern.S
new file mode 100644
index 0000000..fc6f6a5
--- /dev/null
+++ b/arch/arm/boot/compressed/piggy.xzkern.S
@@ -0,0 +1,7 @@
+ .section .piggydata,#alloc
+ .globl input_data
+input_data:
+ .incbin "arch/arm/boot/compressed/piggy.xzkern"
+ .globl input_data_end
+input_data_end:
+
diff --git a/arch/arm/common/fiq_debugger.c b/arch/arm/common/fiq_debugger.c
index 3ed18ae..8e5bddb 100644
--- a/arch/arm/common/fiq_debugger.c
+++ b/arch/arm/common/fiq_debugger.c
@@ -90,7 +90,6 @@ struct fiq_debugger_state {
#endif
unsigned int last_irqs[NR_IRQS];
- unsigned int last_local_timer_irqs[NR_CPUS];
};
#ifdef CONFIG_FIQ_DEBUGGER_NO_SLEEP
@@ -357,8 +356,6 @@ static void dump_allregs(struct fiq_debugger_state *state, unsigned *regs)
static void dump_irqs(struct fiq_debugger_state *state)
{
int n;
- unsigned int cpu;
-
debug_printf(state, "irqnr total since-last status name\n");
for (n = 0; n < NR_IRQS; n++) {
struct irqaction *act = irq_desc[n].action;
@@ -371,16 +368,6 @@ static void dump_irqs(struct fiq_debugger_state *state)
(act && act->name) ? act->name : "???");
state->last_irqs[n] = kstat_irqs(n);
}
-
- for (cpu = 0; cpu < NR_CPUS; cpu++) {
-
- debug_printf(state, "LOC %d: %10u %11u\n", cpu,
- __IRQ_STAT(cpu, local_timer_irqs),
- __IRQ_STAT(cpu, local_timer_irqs) -
- state->last_local_timer_irqs[cpu]);
- state->last_local_timer_irqs[cpu] =
- __IRQ_STAT(cpu, local_timer_irqs);
- }
}
struct stacktrace_state {
diff --git a/arch/arm/common/pl330.c b/arch/arm/common/pl330.c
index 97912fa..3af5e11 100644
--- a/arch/arm/common/pl330.c
+++ b/arch/arm/common/pl330.c
@@ -1281,17 +1281,17 @@ int pl330_submit_req(void *ch_id, struct pl330_req *r)
goto xfer_exit;
}
- /* Prefer Secure Channel */
- if (!_manager_ns(thrd))
- r->cfg->nonsecure = 0;
- else
- r->cfg->nonsecure = 1;
-
/* Use last settings, if not provided */
- if (r->cfg)
+ if (r->cfg) {
+ /* Prefer Secure Channel */
+ if (!_manager_ns(thrd))
+ r->cfg->nonsecure = 0;
+ else
+ r->cfg->nonsecure = 1;
ccr = _prepare_ccr(r->cfg);
- else
+ } else {
ccr = readl(regs + CC(thrd->id));
+ }
/* If this req doesn't have valid xfer settings */
if (!_is_valid(ccr)) {
diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c
index 7aa4262..3a3622c 100644
--- a/arch/arm/common/vic.c
+++ b/arch/arm/common/vic.c
@@ -82,8 +82,6 @@ static void resume_one_vic(struct vic_device *vic)
{
void __iomem *base = vic->base;
- printk(KERN_DEBUG "%s: resuming vic at %p\n", __func__, base);
-
/* re-initialise static settings */
vic_init2(base);
@@ -112,8 +110,6 @@ static void suspend_one_vic(struct vic_device *vic)
{
void __iomem *base = vic->base;
- printk(KERN_DEBUG "%s: suspending vic at %p\n", __func__, base);
-
vic->int_select = readl(base + VIC_INT_SELECT);
vic->int_enable = readl(base + VIC_INT_ENABLE);
vic->soft_int = readl(base + VIC_INT_SOFT);
@@ -208,6 +204,37 @@ static void vic_unmask_irq(struct irq_data *d)
writel(1 << irq, base + VIC_INT_ENABLE);
}
+static int vic_retrigger_irq(struct irq_data *d)
+{
+ void __iomem *base = irq_data_get_irq_chip_data(d);
+ unsigned int irq = d->irq & 31;
+ writel(1 << irq, base + VIC_INT_SOFT);
+ return 1;
+}
+
+static DEFINE_SPINLOCK(vic_intselect_lock);
+int vic_set_fiq(unsigned int irq, bool enable)
+{
+ u32 int_select;
+ u32 mask;
+ unsigned long irq_flags;
+ void __iomem *base = irq_get_chip_data(irq);
+ irq &= 31;
+ mask = 1 << irq;
+
+ spin_lock_irqsave(&vic_intselect_lock, irq_flags);
+ int_select = readl(base + VIC_INT_SELECT);
+ if (enable)
+ int_select |= mask;
+ else
+ int_select &= ~mask;
+ writel(int_select, base + VIC_INT_SELECT);
+ spin_unlock_irqrestore(&vic_intselect_lock, irq_flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(vic_set_fiq);
+
#if defined(CONFIG_PM)
static struct vic_device *vic_from_irq(unsigned int irq)
{
@@ -251,6 +278,7 @@ static struct irq_chip vic_chip = {
.irq_ack = vic_ack_irq,
.irq_mask = vic_mask_irq,
.irq_unmask = vic_unmask_irq,
+ .irq_retrigger = vic_retrigger_irq,
.irq_set_wake = vic_set_wake,
};
diff --git a/arch/arm/configs/crespo_defconfig b/arch/arm/configs/crespo_defconfig
new file mode 100644
index 0000000..4f3997b
--- /dev/null
+++ b/arch/arm/configs/crespo_defconfig
@@ -0,0 +1,2672 @@
+#
+# Automatically generated make config: don't edit
+# Linux/arm 3.0.46 Kernel Configuration
+#
+CONFIG_ARM=y
+CONFIG_HAVE_PWM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+# CONFIG_ARCH_USES_GETTIMEOFFSET is not set
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_KTIME_SCALAR=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_NO_IOPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_ARCH_HAS_CPUFREQ=y
+CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_FIQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+# CONFIG_ARM_PATCH_PHYS_VIRT is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_HAVE_IRQ_WORK=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+CONFIG_LOCALVERSION="-Cyanogenmod"
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+# CONFIG_KERNEL_GZIP is not set
+# CONFIG_KERNEL_LZMA is not set
+CONFIG_KERNEL_XZ=y
+# CONFIG_KERNEL_LZO is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_FHANDLE is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_GENERIC_HARDIRQS=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_HAVE_SPARSE_IRQ=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_CHIP=y
+# CONFIG_SPARSE_IRQ is not set
+
+#
+# RCU Subsystem
+#
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_TINY_RCU is not set
+CONFIG_TINY_PREEMPT_RCU=y
+CONFIG_PREEMPT_RCU=y
+# CONFIG_RCU_TRACE is not set
+# CONFIG_TREE_RCU_TRACE is not set
+CONFIG_RCU_BOOST=y
+CONFIG_RCU_BOOST_PRIO=1
+CONFIG_RCU_BOOST_DELAY=500
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_CGROUPS=y
+# CONFIG_CGROUP_DEBUG is not set
+CONFIG_CGROUP_FREEZER=y
+# CONFIG_CGROUP_DEVICE is not set
+# CONFIG_CPUSETS is not set
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+# CONFIG_CGROUP_MEM_RES_CTLR is not set
+CONFIG_CGROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_RT_GROUP_SCHED=y
+# CONFIG_BLK_CGROUP is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_PANIC_TIMEOUT=5
+CONFIG_EXPERT=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_ASHMEM=y
+# CONFIG_AIO is not set
+CONFIG_EMBEDDED=y
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+# CONFIG_PERF_COUNTERS is not set
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_TRACEPOINTS=y
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_IOSCHED_BFQ=y
+CONFIG_CGROUP_BFQIO=y
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_BFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_SPIN_UNLOCK is not set
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_READ_UNLOCK is not set
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQ is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_WRITE_UNLOCK is not set
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_VEXPRESS is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_BCMRING is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CNS3XXX is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_MXS is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_LPC32XX is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_NUC93X is not set
+# CONFIG_ARCH_TEGRA is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_SHMOBILE is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_S5P64X0 is not set
+# CONFIG_ARCH_S5PC100 is not set
+CONFIG_ARCH_S5PV210=y
+# CONFIG_ARCH_EXYNOS4 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_TCC_926 is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_U8500 is not set
+# CONFIG_ARCH_NOMADIK is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_PLAT_SPEAR is not set
+# CONFIG_ARCH_VT8500 is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_KEYBOARD_GPIO_POLLED is not set
+CONFIG_PLAT_SAMSUNG=y
+
+#
+# Boot options
+#
+# CONFIG_S3C_BOOT_ERROR_RESET is not set
+CONFIG_S3C_BOOT_UART_FORCE_FIFO=y
+CONFIG_S3C_LOWLEVEL_UART_PORT=2
+CONFIG_SAMSUNG_CLKSRC=y
+CONFIG_SAMSUNG_IRQ_VIC_TIMER=y
+CONFIG_SAMSUNG_IRQ_UART=y
+CONFIG_SAMSUNG_GPIOLIB_4BIT=y
+CONFIG_S3C_GPIO_CFG_S3C24XX=y
+CONFIG_S3C_GPIO_CFG_S3C64XX=y
+CONFIG_S3C_GPIO_PULL_UPDOWN=y
+CONFIG_S5P_GPIO_DRVSTR=y
+CONFIG_SAMSUNG_GPIO_EXTRA=0
+CONFIG_S3C_GPIO_SPACE=0
+CONFIG_S3C_GPIO_TRACK=y
+# CONFIG_S3C_ADC is not set
+CONFIG_S3C_DEV_HSMMC=y
+CONFIG_S3C_DEV_HSMMC2=y
+CONFIG_S3C_DEV_HSMMC3=y
+CONFIG_S3C_DEV_I2C1=y
+CONFIG_S3C_DEV_I2C2=y
+CONFIG_S3C_DEV_WDT=y
+CONFIG_SAMSUNG_DEV_PWM=y
+# CONFIG_S3C24XX_PWM is not set
+CONFIG_S3C_PL330_DMA=y
+
+#
+# Power management
+#
+# CONFIG_SAMSUNG_PM_DEBUG is not set
+# CONFIG_SAMSUNG_PM_CHECK is not set
+
+#
+# Power Domain
+#
+CONFIG_PLAT_S5P=y
+CONFIG_S5P_EXT_INT=y
+CONFIG_S5P_HRT=y
+
+#
+# System MMU
+#
+CONFIG_S5P_DEV_ONENAND=y
+CONFIG_S5P_DEV_CSIS0=y
+CONFIG_S5P_SETUP_MIPIPHY=y
+CONFIG_S5P_DEV_FB=y
+CONFIG_S5P_HIGH_RES_TIMERS=y
+CONFIG_HRT_RTC=y
+CONFIG_S5P_DEV_MFC=y
+CONFIG_S5P_SETUP_MFC=y
+CONFIG_CPU_S5PV210=y
+# CONFIG_CPU_DIDLE is not set
+CONFIG_S5PV210_SETUP_I2C1=y
+CONFIG_S5PV210_SETUP_I2C2=y
+CONFIG_S5PV210_SETUP_SDHCI=y
+CONFIG_S5PV210_SETUP_SDHCI_GPIO=y
+CONFIG_S5PV210_POWER_DOMAIN=y
+CONFIG_S5PV210_CORESIGHT=y
+
+#
+# MMC/SD slot setup
+#
+
+#
+# Use 8-bit bus width
+#
+CONFIG_S5PV210_SD_CH0_8BIT=y
+# CONFIG_S5PV210_SD_CH2_8BIT is not set
+
+#
+# S5PC110 Machines
+#
+# CONFIG_MACH_AQUILA is not set
+# CONFIG_MACH_GONI is not set
+# CONFIG_MACH_SMDKC110 is not set
+
+#
+# S5PV210 Machines
+#
+# CONFIG_MACH_SMDKV210 is not set
+# CONFIG_MACH_TORBRECK is not set
+CONFIG_S5PV210_PM=y
+CONFIG_MACH_HERRING=y
+CONFIG_S5PV210_SETUP_FB=y
+CONFIG_S5P_ADC=y
+CONFIG_S5PV210_SETUP_FIMC0=y
+CONFIG_S5PV210_SETUP_FIMC1=y
+CONFIG_S5PV210_SETUP_FIMC2=y
+CONFIG_WIFI_CONTROL_FUNC=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_V7=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+CONFIG_ARM_THUMBEE=y
+# CONFIG_SWP_EMULATE is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_ARM_L1_CACHE_SHIFT_6=y
+CONFIG_ARM_L1_CACHE_SHIFT=6
+CONFIG_ARM_DMA_MEM_BUFFERABLE=y
+CONFIG_CPU_HAS_PMU=y
+# CONFIG_ARM_ERRATA_430973 is not set
+# CONFIG_ARM_ERRATA_458693 is not set
+# CONFIG_ARM_ERRATA_460075 is not set
+# CONFIG_ARM_ERRATA_743622 is not set
+# CONFIG_ARM_ERRATA_754322 is not set
+CONFIG_ARM_VIC=y
+CONFIG_ARM_VIC_NR=4
+CONFIG_PL330=y
+CONFIG_FIQ_GLUE=y
+CONFIG_FIQ_DEBUGGER=y
+# CONFIG_FIQ_DEBUGGER_NO_SLEEP is not set
+# CONFIG_FIQ_DEBUGGER_WAKEUP_IRQ_ALWAYS_ON is not set
+CONFIG_FIQ_DEBUGGER_CONSOLE=y
+# CONFIG_FIQ_DEBUGGER_CONSOLE_DEFAULT_ENABLE is not set
+
+#
+# Bus support
+#
+CONFIG_ARM_AMBA=y
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_HZ=256
+# CONFIG_THUMB2_KERNEL is not set
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_HAVE_ARCH_PFN_VALID=y
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_SPARSEMEM_EXTREME=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_KSM=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+# CONFIG_SECCOMP is not set
+# CONFIG_CC_STACKPROTECTOR is not set
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set
+
+#
+# Boot options
+#
+# CONFIG_USE_OF is not set
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_CMDLINE="console=ttyFIQ0"
+CONFIG_CMDLINE_FROM_BOOTLOADER=y
+# CONFIG_CMDLINE_EXTEND is not set
+# CONFIG_CMDLINE_FORCE is not set
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+# CONFIG_AUTO_ZRELADDR is not set
+
+#
+# CPU Power Management
+#
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_INTERACTIVE=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+# CONFIG_FPE_NWFPE is not set
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management options
+#
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_HAS_WAKELOCK=y
+CONFIG_HAS_EARLYSUSPEND=y
+CONFIG_WAKELOCK=y
+CONFIG_WAKELOCK_STAT=y
+CONFIG_USER_WAKELOCK=y
+CONFIG_EARLYSUSPEND=y
+# CONFIG_NO_USER_SPACE_SCREEN_ACCESS_CONTROL is not set
+CONFIG_FB_EARLYSUSPEND=y
+CONFIG_PM_SLEEP=y
+# CONFIG_PM_RUNTIME is not set
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_APM_EMULATION=y
+# CONFIG_SUSPEND_TIME is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=y
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+# CONFIG_IP_FIB_TRIE_STATS is not set
+CONFIG_IP_MULTIPLE_TABLES=y
+# CONFIG_IP_ROUTE_MULTIPATH is not set
+# CONFIG_IP_ROUTE_VERBOSE is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+CONFIG_INET_ESP=y
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+CONFIG_TCP_CONG_ADVANCED=y
+# CONFIG_TCP_CONG_BIC is not set
+# CONFIG_TCP_CONG_CUBIC is not set
+# CONFIG_TCP_CONG_WESTWOOD is not set
+# CONFIG_TCP_CONG_HTCP is not set
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
+# CONFIG_TCP_CONG_LP is not set
+CONFIG_TCP_CONG_VENO=y
+# CONFIG_TCP_CONG_YEAH is not set
+# CONFIG_TCP_CONG_ILLINOIS is not set
+CONFIG_DEFAULT_VENO=y
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="veno"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+# CONFIG_IPV6_ROUTE_INFO is not set
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_INET6_XFRM_TUNNEL=y
+CONFIG_INET6_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=y
+# CONFIG_IPV6_SIT_6RD is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+# CONFIG_IPV6_SUBTREES is not set
+# CONFIG_IPV6_MROUTE is not set
+CONFIG_ANDROID_PARANOID_NETWORK=y
+CONFIG_NET_ACTIVITY_STATS=y
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=y
+CONFIG_NETFILTER_NETLINK_QUEUE=y
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+# CONFIG_NF_CONNTRACK_TIMESTAMP is not set
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_GRE=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_BROADCAST=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+# CONFIG_NF_CONNTRACK_SNMP is not set
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+# CONFIG_NF_CONNTRACK_SIP is not set
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_TPROXY=y
+CONFIG_NETFILTER_XTABLES=y
+
+#
+# Xtables combined modules
+#
+CONFIG_NETFILTER_XT_MARK=y
+CONFIG_NETFILTER_XT_CONNMARK=y
+
+#
+# Xtables targets
+#
+# CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+# CONFIG_NETFILTER_XT_TARGET_CT is not set
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+# CONFIG_NETFILTER_XT_TARGET_HL is not set
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set
+# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
+# CONFIG_NETFILTER_XT_TARGET_TEE is not set
+CONFIG_NETFILTER_XT_TARGET_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+
+#
+# Xtables matches
+#
+# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+# CONFIG_NETFILTER_XT_MATCH_CPU is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_HL=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+# CONFIG_NETFILTER_XT_MATCH_OSF is not set
+# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y
+# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_RECENT is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+# CONFIG_IP_SET is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+# CONFIG_IP_NF_QUEUE is not set
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_REJECT_SKERR=y
+CONFIG_IP_NF_TARGET_LOG=y
+# CONFIG_IP_NF_TARGET_ULOG is not set
+CONFIG_NF_NAT=y
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_NF_NAT_PROTO_DCCP=y
+CONFIG_NF_NAT_PROTO_GRE=y
+CONFIG_NF_NAT_PROTO_UDPLITE=y
+CONFIG_NF_NAT_PROTO_SCTP=y
+CONFIG_NF_NAT_FTP=y
+CONFIG_NF_NAT_IRC=y
+CONFIG_NF_NAT_TFTP=y
+CONFIG_NF_NAT_AMANDA=y
+CONFIG_NF_NAT_PPTP=y
+CONFIG_NF_NAT_H323=y
+# CONFIG_NF_NAT_SIP is not set
+CONFIG_IP_NF_MANGLE=y
+# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
+# CONFIG_IP_NF_TARGET_ECN is not set
+# CONFIG_IP_NF_TARGET_TTL is not set
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV6=y
+CONFIG_NF_CONNTRACK_IPV6=y
+# CONFIG_IP6_NF_QUEUE is not set
+CONFIG_IP6_NF_IPTABLES=y
+# CONFIG_IP6_NF_MATCH_AH is not set
+# CONFIG_IP6_NF_MATCH_EUI64 is not set
+# CONFIG_IP6_NF_MATCH_FRAG is not set
+# CONFIG_IP6_NF_MATCH_OPTS is not set
+# CONFIG_IP6_NF_MATCH_HL is not set
+# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set
+# CONFIG_IP6_NF_MATCH_MH is not set
+# CONFIG_IP6_NF_MATCH_RT is not set
+# CONFIG_IP6_NF_TARGET_HL is not set
+CONFIG_IP6_NF_TARGET_LOG=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_TARGET_REJECT_SKERR=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+CONFIG_PHONET=y
+# CONFIG_IEEE802154 is not set
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+# CONFIG_NET_SCH_CBQ is not set
+# CONFIG_NET_SCH_HTB is not set
+# CONFIG_NET_SCH_HFSC is not set
+# CONFIG_NET_SCH_PRIO is not set
+# CONFIG_NET_SCH_MULTIQ is not set
+# CONFIG_NET_SCH_RED is not set
+CONFIG_NET_SCH_SFB=y
+# CONFIG_NET_SCH_SFQ is not set
+# CONFIG_NET_SCH_TEQL is not set
+# CONFIG_NET_SCH_TBF is not set
+# CONFIG_NET_SCH_GRED is not set
+# CONFIG_NET_SCH_DSMARK is not set
+# CONFIG_NET_SCH_NETEM is not set
+# CONFIG_NET_SCH_DRR is not set
+# CONFIG_NET_SCH_MQPRIO is not set
+# CONFIG_NET_SCH_CHOKE is not set
+# CONFIG_NET_SCH_QFQ is not set
+# CONFIG_NET_SCH_INGRESS is not set
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+# CONFIG_NET_CLS_BASIC is not set
+# CONFIG_NET_CLS_TCINDEX is not set
+# CONFIG_NET_CLS_ROUTE4 is not set
+# CONFIG_NET_CLS_FW is not set
+CONFIG_NET_CLS_U32=y
+# CONFIG_CLS_U32_PERF is not set
+# CONFIG_CLS_U32_MARK is not set
+# CONFIG_NET_CLS_RSVP is not set
+# CONFIG_NET_CLS_RSVP6 is not set
+# CONFIG_NET_CLS_FLOW is not set
+# CONFIG_NET_CLS_CGROUP is not set
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+# CONFIG_NET_EMATCH_CMP is not set
+# CONFIG_NET_EMATCH_NBYTE is not set
+CONFIG_NET_EMATCH_U32=y
+# CONFIG_NET_EMATCH_META is not set
+# CONFIG_NET_EMATCH_TEXT is not set
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=y
+CONFIG_NET_ACT_GACT=y
+# CONFIG_GACT_PROB is not set
+CONFIG_NET_ACT_MIRRED=y
+# CONFIG_NET_ACT_IPT is not set
+# CONFIG_NET_ACT_NAT is not set
+# CONFIG_NET_ACT_PEDIT is not set
+# CONFIG_NET_ACT_SIMP is not set
+# CONFIG_NET_ACT_SKBEDIT is not set
+# CONFIG_NET_ACT_CSUM is not set
+# CONFIG_NET_CLS_IND is not set
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+# CONFIG_BATMAN_ADV is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_DROP_MONITOR is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+# CONFIG_BT_BNEP_MC_FILTER is not set
+# CONFIG_BT_BNEP_PROTO_FILTER is not set
+CONFIG_BT_HIDP=y
+
+#
+# Bluetooth device drivers
+#
+# CONFIG_BT_HCIBTUSB is not set
+# CONFIG_BT_HCIBTSDIO is not set
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+# CONFIG_BT_HCIUART_BCSP is not set
+# CONFIG_BT_HCIUART_ATH3K is not set
+# CONFIG_BT_HCIUART_LL is not set
+# CONFIG_BT_HCIBCM203X is not set
+# CONFIG_BT_HCIBPA10X is not set
+# CONFIG_BT_HCIBFUSB is not set
+# CONFIG_BT_HCIVHCI is not set
+# CONFIG_BT_MRVL is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_CFG80211=y
+CONFIG_NL80211_TESTMODE=y
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_REG_DEBUG is not set
+CONFIG_CFG80211_DEFAULT_PS=y
+# CONFIG_CFG80211_DEBUGFS is not set
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+# CONFIG_CFG80211_WEXT is not set
+# CONFIG_LIB80211 is not set
+CONFIG_CFG80211_ALLOW_RECONNECT=y
+# CONFIG_MAC80211 is not set
+CONFIG_WIMAX=y
+CONFIG_WIMAX_DEBUG_LEVEL=8
+CONFIG_RFKILL=y
+CONFIG_RFKILL_PM=y
+CONFIG_RFKILL_INPUT=y
+# CONFIG_RFKILL_REGULATOR is not set
+# CONFIG_RFKILL_GPIO is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH=""
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_SYNC is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+# CONFIG_MTD_OOPS is not set
+# CONFIG_MTD_SWAP is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND_IDS is not set
+# CONFIG_MTD_NAND is not set
+CONFIG_MTD_ONENAND=y
+# CONFIG_MTD_ONENAND_VERIFY_WRITE is not set
+# CONFIG_MTD_ONENAND_GENERIC is not set
+CONFIG_MTD_ONENAND_SAMSUNG=y
+# CONFIG_MTD_ONENAND_OTP is not set
+# CONFIG_MTD_ONENAND_2X_PROGRAM is not set
+# CONFIG_MTD_ONENAND_SIM is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+
+#
+# DRBD disabled because PROC_FS, INET or CONNECTOR not selected
+#
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MG_DISK is not set
+# CONFIG_BLK_DEV_RBD is not set
+# CONFIG_SENSORS_LIS3LV02D is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_INTEL_MID_PTI is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1780 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+CONFIG_SENSORS_AK8973=y
+# CONFIG_SENSORS_AK8975 is not set
+CONFIG_SENSORS_KR3DM=y
+# CONFIG_DS1682 is not set
+# CONFIG_TI_DAC7512 is not set
+CONFIG_UID_STAT=y
+# CONFIG_BMP085 is not set
+# CONFIG_WL127X_RFKILL is not set
+CONFIG_APANIC=y
+CONFIG_APANIC_PLABEL="kpanic"
+CONFIG_SAMSUNG_JACK=y
+CONFIG_USB_SWITCH_FSA9480=y
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_IWMC3200TOP is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+CONFIG_SAMSUNG_MODEMCTL=y
+CONFIG_PN544=y
+CONFIG_GENERIC_BLN=y
+CONFIG_BLD=y
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_ISCSI_BOOT_SYSFS is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+CONFIG_MD=y
+# CONFIG_BLK_DEV_MD is not set
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_DEBUG=y
+CONFIG_DM_CRYPT=y
+# CONFIG_DM_SNAPSHOT is not set
+# CONFIG_DM_MIRROR is not set
+# CONFIG_DM_RAID is not set
+# CONFIG_DM_ZERO is not set
+# CONFIG_DM_MULTIPATH is not set
+# CONFIG_DM_DELAY is not set
+CONFIG_DM_UEVENT=y
+# CONFIG_DM_FLAKEY is not set
+# CONFIG_TARGET_CORE is not set
+CONFIG_NETDEVICES=y
+CONFIG_IFB=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=y
+# CONFIG_VETH is not set
+# CONFIG_MII is not set
+# CONFIG_PHYLIB is not set
+# CONFIG_NET_ETHERNET is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_STMMAC_ETH is not set
+CONFIG_NETDEV_10000=y
+CONFIG_WLAN=y
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_USB_NET_RNDIS_WLAN is not set
+# CONFIG_ATH_COMMON is not set
+# CONFIG_BCM4329 is not set
+CONFIG_BCMDHD=y
+CONFIG_BCMDHD_FW_PATH="/vendor/firmware/fw_bcmdhd.bin"
+CONFIG_BCMDHD_NVRAM_PATH="/vendor/firmware/nvram_net.txt"
+# CONFIG_DHD_USE_STATIC_BUF is not set
+# CONFIG_DHD_USE_SCHED_SCAN is not set
+# CONFIG_DHD_ENABLE_P2P is not set
+# CONFIG_HOSTAP is not set
+# CONFIG_IWM is not set
+# CONFIG_LIBERTAS is not set
+# CONFIG_MWIFIEX is not set
+
+#
+# WiMAX Wireless Broadband devices
+#
+# CONFIG_WIMAX_I2400M_USB is not set
+# CONFIG_WIMAX_I2400M_SDIO is not set
+CONFIG_WIMAX_CMC7XX=y
+# CONFIG_WIMAX_CMC7XX_DEBUG is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_HSO is not set
+# CONFIG_USB_CDC_PHONET is not set
+# CONFIG_USB_IPHETH is not set
+# CONFIG_WAN is not set
+
+#
+# CAIF transport drivers
+#
+CONFIG_PPP=y
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_MPPE=y
+# CONFIG_PPPOE is not set
+CONFIG_PPPOLAC=y
+CONFIG_PPPOPNS=y
+# CONFIG_SLIP is not set
+CONFIG_SLHC=y
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_FF_MEMLESS=y
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_JOYDEV=y
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+# CONFIG_INPUT_APMPOWER is not set
+# CONFIG_INPUT_KEYRESET is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
+# CONFIG_KEYBOARD_ADP5589 is not set
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_QT1070 is not set
+# CONFIG_KEYBOARD_QT2160 is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_TCA6416 is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_MAX7359 is not set
+# CONFIG_KEYBOARD_MCS is not set
+# CONFIG_KEYBOARD_MPR121 is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+CONFIG_KEYPAD_CYPRESS_TOUCH=y
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_ADS7846 is not set
+# CONFIG_TOUCHSCREEN_AD7877 is not set
+# CONFIG_TOUCHSCREEN_AD7879 is not set
+# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set
+# CONFIG_TOUCHSCREEN_BU21013 is not set
+# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set
+# CONFIG_TOUCHSCREEN_DYNAPRO is not set
+# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set
+# CONFIG_TOUCHSCREEN_EETI is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_MAX11801 is not set
+# CONFIG_TOUCHSCREEN_MCS5000 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+CONFIG_TOUCHSCREEN_MXT224=y
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC2005 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
+# CONFIG_TOUCHSCREEN_W90X900 is not set
+# CONFIG_TOUCHSCREEN_ST1232 is not set
+# CONFIG_TOUCHSCREEN_TPS6507X is not set
+CONFIG_INPUT_MISC=y
+CONFIG_GYRO_K3G=y
+# CONFIG_INPUT_AD714X is not set
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+CONFIG_INPUT_KEYCHORD=y
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_GPIO=y
+# CONFIG_INPUT_PCF8574 is not set
+# CONFIG_INPUT_PWM_BEEPER is not set
+# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
+# CONFIG_INPUT_ADXL34X is not set
+# CONFIG_INPUT_CMA3000 is not set
+CONFIG_OPTICAL_GP2A=y
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_AMBAKMI is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_SERIO_PS2MULT is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVMEM=y
+CONFIG_DEVKMEM=y
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_AMBA_PL010 is not set
+# CONFIG_SERIAL_AMBA_PL011 is not set
+CONFIG_SERIAL_SAMSUNG=y
+CONFIG_SERIAL_SAMSUNG_UARTS_4=y
+CONFIG_SERIAL_SAMSUNG_UARTS=4
+CONFIG_SERIAL_SAMSUNG_CONSOLE=y
+CONFIG_SERIAL_S5PV210=y
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX3107 is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_TIMBERDALE is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_IFX6X60 is not set
+# CONFIG_SERIAL_XILINX_PS_UART is not set
+# CONFIG_TTY_PRINTK is not set
+# CONFIG_HVC_DCC is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_DCC_TTY is not set
+# CONFIG_RAMOOPS is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_MUX is not set
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_ALGOBIT=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_DESIGNWARE is not set
+CONFIG_I2C_GPIO=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_PXA_PCI is not set
+CONFIG_HAVE_S3C2410_I2C=y
+CONFIG_I2C_S3C2410=y
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_ALTERA is not set
+CONFIG_SPI_BITBANG=y
+CONFIG_SPI_GPIO=y
+# CONFIG_SPI_OC_TINY is not set
+# CONFIG_SPI_PL022 is not set
+# CONFIG_SPI_PXA2XX_PCI is not set
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_DESIGNWARE is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+
+#
+# Enable Device Drivers -> PPS to see the PTP clock options.
+#
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO drivers:
+#
+# CONFIG_GPIO_BASIC_MMIO is not set
+# CONFIG_GPIO_IT8761E is not set
+CONFIG_GPIO_PLAT_SAMSUNG=y
+CONFIG_GPIO_S5PV210=y
+# CONFIG_GPIO_PL061 is not set
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_SX150X is not set
+# CONFIG_GPIO_ADP5588 is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_GPIO_MC33880 is not set
+# CONFIG_GPIO_74X164 is not set
+
+#
+# AC97 GPIO expanders:
+#
+
+#
+# MODULbus GPIO expanders:
+#
+# CONFIG_W1 is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_APM_POWER is not set
+# CONFIG_TEST_POWER is not set
+# CONFIG_BATTERY_DS2780 is not set
+# CONFIG_BATTERY_DS2782 is not set
+# CONFIG_BATTERY_BQ20Z75 is not set
+# CONFIG_BATTERY_BQ27x00 is not set
+CONFIG_BATTERY_MAX17040=y
+# CONFIG_BATTERY_MAX17042 is not set
+# CONFIG_BATTERY_S3C is not set
+CONFIG_BATTERY_S5PC110=y
+# CONFIG_CHARGER_ISP1704 is not set
+# CONFIG_CHARGER_MAX8903 is not set
+# CONFIG_CHARGER_GPIO is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+CONFIG_MFD_SUPPORT=y
+CONFIG_MFD_CORE=y
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_STMPE is not set
+# CONFIG_MFD_TC3589X is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+CONFIG_MFD_MAX8998=y
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM831X_SPI is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_MC13XXX is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_TPS65910 is not set
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+# CONFIG_REGULATOR_DUMMY is not set
+# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
+# CONFIG_REGULATOR_BQ24022 is not set
+# CONFIG_REGULATOR_MAX1586 is not set
+# CONFIG_REGULATOR_MAX8649 is not set
+# CONFIG_REGULATOR_MAX8660 is not set
+CONFIG_REGULATOR_MAX8893=y
+# CONFIG_REGULATOR_MAX8952 is not set
+CONFIG_REGULATOR_MAX8998=y
+# CONFIG_REGULATOR_LP3971 is not set
+# CONFIG_REGULATOR_LP3972 is not set
+# CONFIG_REGULATOR_TPS65023 is not set
+# CONFIG_REGULATOR_TPS6507X is not set
+# CONFIG_REGULATOR_ISL6271A is not set
+# CONFIG_REGULATOR_AD5398 is not set
+# CONFIG_REGULATOR_TPS6524X is not set
+CONFIG_MEDIA_SUPPORT=y
+
+#
+# Multimedia core support
+#
+# CONFIG_MEDIA_CONTROLLER is not set
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2_COMMON=y
+# CONFIG_DVB_CORE is not set
+CONFIG_VIDEO_MEDIA=y
+
+#
+# Multimedia drivers
+#
+# CONFIG_RC_CORE is not set
+# CONFIG_MEDIA_ATTACH is not set
+CONFIG_MEDIA_TUNER=y
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=y
+CONFIG_MEDIA_TUNER_TDA8290=y
+CONFIG_MEDIA_TUNER_TDA827X=y
+CONFIG_MEDIA_TUNER_TDA18271=y
+CONFIG_MEDIA_TUNER_TDA9887=y
+CONFIG_MEDIA_TUNER_TEA5761=y
+CONFIG_MEDIA_TUNER_TEA5767=y
+CONFIG_MEDIA_TUNER_MT20XX=y
+CONFIG_MEDIA_TUNER_XC2028=y
+CONFIG_MEDIA_TUNER_XC5000=y
+CONFIG_MEDIA_TUNER_MC44S803=y
+CONFIG_VIDEO_V4L2=y
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+CONFIG_VIDEO_FIXED_MINOR_RANGES=y
+# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
+
+#
+# Encoders, decoders, sensors and other helper chips
+#
+
+#
+# Audio decoders, processors and mixers
+#
+# CONFIG_VIDEO_TVAUDIO is not set
+# CONFIG_VIDEO_TDA7432 is not set
+# CONFIG_VIDEO_TDA9840 is not set
+# CONFIG_VIDEO_TEA6415C is not set
+# CONFIG_VIDEO_TEA6420 is not set
+# CONFIG_VIDEO_MSP3400 is not set
+# CONFIG_VIDEO_CS5345 is not set
+# CONFIG_VIDEO_CS53L32A is not set
+# CONFIG_VIDEO_TLV320AIC23B is not set
+# CONFIG_VIDEO_WM8775 is not set
+# CONFIG_VIDEO_WM8739 is not set
+# CONFIG_VIDEO_VP27SMPX is not set
+
+#
+# RDS decoders
+#
+# CONFIG_VIDEO_SAA6588 is not set
+
+#
+# Video decoders
+#
+# CONFIG_VIDEO_ADV7180 is not set
+# CONFIG_VIDEO_BT819 is not set
+# CONFIG_VIDEO_BT856 is not set
+# CONFIG_VIDEO_BT866 is not set
+# CONFIG_VIDEO_KS0127 is not set
+# CONFIG_VIDEO_SAA7110 is not set
+# CONFIG_VIDEO_SAA711X is not set
+# CONFIG_VIDEO_SAA7191 is not set
+# CONFIG_VIDEO_TVP514X is not set
+# CONFIG_VIDEO_TVP5150 is not set
+# CONFIG_VIDEO_TVP7002 is not set
+# CONFIG_VIDEO_VPX3220 is not set
+
+#
+# Video and audio decoders
+#
+# CONFIG_VIDEO_SAA717X is not set
+# CONFIG_VIDEO_CX25840 is not set
+
+#
+# MPEG video encoders
+#
+# CONFIG_VIDEO_CX2341X is not set
+
+#
+# Video encoders
+#
+# CONFIG_VIDEO_SAA7127 is not set
+# CONFIG_VIDEO_SAA7185 is not set
+# CONFIG_VIDEO_ADV7170 is not set
+# CONFIG_VIDEO_ADV7175 is not set
+# CONFIG_VIDEO_ADV7343 is not set
+# CONFIG_VIDEO_AK881X is not set
+
+#
+# Camera sensor devices
+#
+# CONFIG_VIDEO_OV7670 is not set
+# CONFIG_VIDEO_MT9V011 is not set
+# CONFIG_VIDEO_TCM825X is not set
+
+#
+# Video improvement chips
+#
+# CONFIG_VIDEO_UPD64031A is not set
+# CONFIG_VIDEO_UPD64083 is not set
+
+#
+# Miscelaneous helper chips
+#
+# CONFIG_VIDEO_THS7303 is not set
+# CONFIG_VIDEO_M52790 is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SR030PC30 is not set
+# CONFIG_VIDEO_NOON010PC30 is not set
+# CONFIG_SOC_CAMERA is not set
+# CONFIG_VIDEO_SAMSUNG_S5P_FIMC is not set
+# CONFIG_V4L_USB_DRIVERS is not set
+CONFIG_VIDEO_S5KA3DFX=y
+CONFIG_VIDEO_S5K4ECGX=y
+# CONFIG_VIDEO_S5K4ECGX_DEBUG is not set
+CONFIG_VIDEO_S5K4ECGX_V_1_0=y
+CONFIG_VIDEO_S5K4ECGX_V_1_1=y
+CONFIG_VIDEO_SAMSUNG=y
+CONFIG_VIDEO_SAMSUNG_V4L2=y
+CONFIG_VIDEO_FIMC=y
+CONFIG_VIDEO_FIMC_RANGE_NARROW=y
+# CONFIG_VIDEO_FIMC_RANGE_WIDE is not set
+# CONFIG_VIDEO_FIMC_DEBUG is not set
+# CONFIG_VIDEO_FIMC_MIPI is not set
+CONFIG_VIDEO_MFC50=y
+CONFIG_VIDEO_MFC_MAX_INSTANCE=4
+# CONFIG_VIDEO_MFC50_DEBUG is not set
+CONFIG_VIDEO_JPEG_V2=y
+# CONFIG_VIDEO_JPEG_DEBUG is not set
+# CONFIG_V4L_MEM2MEM_DRIVERS is not set
+# CONFIG_RADIO_ADAPTERS is not set
+
+#
+# Graphics support
+#
+# CONFIG_DRM is not set
+# CONFIG_ION is not set
+CONFIG_PVR_SGX=y
+CONFIG_PVR_BUILD_RELEASE=y
+# CONFIG_PVR_BUILD_DEBUG is not set
+CONFIG_PVR_NEED_PVR_DPF=y
+CONFIG_PVR_NEED_PVR_ASSERT=y
+CONFIG_PVR_PERCONTEXT_PB=y
+CONFIG_PVR_ACTIVE_POWER_MANAGEMENT=y
+CONFIG_PVR_ACTIVE_POWER_LATENCY_MS=100
+CONFIG_PVR_SGX_LOW_LATENCY_SCHEDULING=y
+CONFIG_PVR_USSE_EDM_STATUS_DEBUG=y
+CONFIG_PVR_DUMP_MK_TRACE=y
+# CONFIG_PVR_PDUMP is not set
+# CONFIG_PVR_LINUX_MEM_AREA_POOL is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_WMT_GE_ROPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+CONFIG_FB_S3C=y
+# CONFIG_FB_S3C_SPLASH_SCREEN is not set
+CONFIG_FB_S3C_LCD_INIT=y
+# CONFIG_FB_S3C_DEBUG is not set
+# CONFIG_FB_S3C_TRACE_UNDERRUN is not set
+CONFIG_FB_S3C_DEFAULT_WINDOW=2
+CONFIG_FB_S3C_NR_BUFFERS=7
+CONFIG_FB_S3C_NUM_OVLY_WIN=1
+CONFIG_FB_S3C_NUM_BUF_OVLY_WIN=3
+# CONFIG_FB_S3C_VIRTUAL is not set
+CONFIG_FB_S3C_TL2796=y
+CONFIG_FB_VOODOO=y
+# CONFIG_FB_VOODOO_DEBUG_LOG is not set
+CONFIG_FB_S3C_NT35580=y
+# CONFIG_FB_S3C_LVDS is not set
+# CONFIG_FB_S3C_AMS701KA is not set
+# CONFIG_FB_S3C_MDNIE is not set
+CONFIG_TL2796_CONVERT_COLORS_RES=y
+# CONFIG_FB_S3C_CMC623 is not set
+# CONFIG_FB_ARMCLCD is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_TMIO is not set
+# CONFIG_FB_UDL is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_BROADSHEET is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+# CONFIG_LCD_L4F00242T03 is not set
+# CONFIG_LCD_LMS283GF05 is not set
+# CONFIG_LCD_LTV350QV is not set
+# CONFIG_LCD_TDO24M is not set
+# CONFIG_LCD_VGG2432A4 is not set
+# CONFIG_LCD_PLATFORM is not set
+# CONFIG_LCD_S6E63M0 is not set
+# CONFIG_LCD_LD9040 is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+# CONFIG_BACKLIGHT_PWM is not set
+# CONFIG_BACKLIGHT_ADP8860 is not set
+# CONFIG_BACKLIGHT_ADP8870 is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_LOGO is not set
+CONFIG_SOUND=y
+# CONFIG_SOUND_OSS_CORE is not set
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_JACK=y
+# CONFIG_SND_SEQUENCER is not set
+# CONFIG_SND_MIXER_OSS is not set
+# CONFIG_SND_PCM_OSS is not set
+# CONFIG_SND_HRTIMER is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_ALOOP is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+CONFIG_SND_ARM=y
+# CONFIG_SND_ARMAACI is not set
+CONFIG_SND_SPI=y
+CONFIG_SND_USB=y
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_UA101 is not set
+# CONFIG_SND_USB_CAIAQ is not set
+# CONFIG_SND_USB_6FIRE is not set
+CONFIG_SND_SOC=y
+# CONFIG_SND_SOC_CACHE_LZO is not set
+CONFIG_SND_SOC_SAMSUNG=y
+CONFIG_SND_S5PC1XX_I2S=y
+CONFIG_S5P_INTERNAL_DMA=y
+CONFIG_SND_S5P_WM8994_MASTER=y
+CONFIG_SND_SOC_SAMSUNG_HERRING_WM8994=y
+CONFIG_SND_VOODOO=y
+CONFIG_SND_VOODOO_HP_LEVEL_CONTROL=y
+CONFIG_SND_VOODOO_HP_LEVEL=54
+CONFIG_SND_VOODOO_RECORD_PRESETS=y
+# CONFIG_SND_VOODOO_DEVELOPMENT is not set
+CONFIG_SND_SOC_I2C_AND_SPI=y
+# CONFIG_SND_SOC_ALL_CODECS is not set
+CONFIG_SND_SOC_WM8994_SAMSUNG=y
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HIDRAW is not set
+# CONFIG_UHID is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+# CONFIG_HID_PID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_ELECOM is not set
+# CONFIG_HID_MAGICMOUSE is not set
+# CONFIG_HID_WACOM is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+CONFIG_USB_S3C_OTG_HOST=y
+# CONFIG_USB_MUSB_HDRC is not set
+CONFIG_USB_DWC_OTG=y
+CONFIG_DWC_DEBUG=y
+CONFIG_DWC_HOST_ONLY=y
+# CONFIG_DWC_OTG_MODE is not set
+# CONFIG_DWC_DEVICE_ONLY is not set
+# CONFIG_DWC_SLAVE is not set
+CONFIG_DWC_DMA_MODE=y
+CONFIG_DWC_OTG_REG_LE=y
+CONFIG_DWC_OTG_FIFO_LE=y
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_REALTEK is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_STORAGE_ENE_UB6250 is not set
+# CONFIG_USB_UAS is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_YUREX is not set
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+# CONFIG_USB_GADGET_DEBUG_FS is not set
+CONFIG_USB_GADGET_VBUS_DRAW=500
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_FUSB300 is not set
+# CONFIG_USB_GADGET_R8A66597 is not set
+CONFIG_USB_GADGET_S3C_OTGD=y
+# CONFIG_USB_GADGET_PXA_U2O is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+
+#
+# NOTE: S3C OTG device role enables the controller driver below
+#
+CONFIG_USB_S3C_OTGD=y
+CONFIG_USB_GADGET_S3C_OTGD_DMA_MODE=y
+# CONFIG_USB_GADGET_S3C_OTGD_SLAVE_MODE is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+# CONFIG_USB_ZERO is not set
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_G_NCM is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FUNCTIONFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_MASS_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+CONFIG_USB_G_ANDROID=y
+CONFIG_USB_ANDROID_RNDIS_DWORD_ALIGNED=y
+# CONFIG_USB_CDC_COMPOSITE is not set
+# CONFIG_USB_G_NOKIA is not set
+# CONFIG_USB_G_MULTI is not set
+# CONFIG_USB_G_HID is not set
+# CONFIG_USB_G_DBGP is not set
+# CONFIG_USB_G_WEBCAM is not set
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+# CONFIG_USB_OTG_WAKELOCK is not set
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_ULPI is not set
+CONFIG_NOP_USB_XCEIV=y
+# CONFIG_USB_HOST_NOTIFY is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_UNSAFE_RESUME=y
+# CONFIG_MMC_CLKGATE is not set
+# CONFIG_MMC_EMBEDDED_SDIO is not set
+# CONFIG_MMC_PARANOID_SD_INIT is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_ARMMMCI is not set
+CONFIG_MMC_SDHCI=y
+# CONFIG_MMC_SDHCI_PLTFM is not set
+CONFIG_MMC_SDHCI_S3C=y
+CONFIG_MMC_SDHCI_S3C_DMA=y
+# CONFIG_MMC_SPI is not set
+# CONFIG_MMC_DW is not set
+# CONFIG_MMC_VUB300 is not set
+# CONFIG_MMC_USHC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_NFC_DEVICES is not set
+CONFIG_SWITCH=y
+# CONFIG_SWITCH_GPIO is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+CONFIG_RTC_INTF_ALARM=y
+CONFIG_RTC_INTF_ALARM_DEV=y
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_DS3232 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_MAX8998 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_ISL12022 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+# CONFIG_RTC_DRV_EM3027 is not set
+# CONFIG_RTC_DRV_RV3029C2 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T93 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_HAVE_S3C_RTC=y
+CONFIG_RTC_DRV_S3C=y
+# CONFIG_RTC_DRV_PL030 is not set
+# CONFIG_RTC_DRV_PL031 is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+CONFIG_STAGING=y
+# CONFIG_USBIP_CORE is not set
+# CONFIG_PRISM2_USB is not set
+# CONFIG_ECHO is not set
+# CONFIG_BRCMUTIL is not set
+# CONFIG_ASUS_OLED is not set
+# CONFIG_R8712U is not set
+# CONFIG_TRANZPORT is not set
+
+#
+# Android
+#
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_LOGGER=y
+CONFIG_ANDROID_RAM_CONSOLE=y
+CONFIG_ANDROID_RAM_CONSOLE_ENABLE_VERBOSE=y
+CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION=y
+CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_DATA_SIZE=128
+CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_ECC_SIZE=16
+CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE=8
+CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_POLYNOMIAL=0x11d
+# CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT is not set
+CONFIG_ANDROID_TIMED_OUTPUT=y
+CONFIG_ANDROID_TIMED_GPIO=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+# CONFIG_POHMELFS is not set
+# CONFIG_LINE6_USB is not set
+# CONFIG_VT6656 is not set
+# CONFIG_IIO is not set
+CONFIG_XVMALLOC=y
+CONFIG_ZRAM=y
+# CONFIG_ZRAM_DEBUG is not set
+# CONFIG_FB_SM7XX is not set
+# CONFIG_EASYCAP is not set
+CONFIG_MACH_NO_WESTBRIDGE=y
+# CONFIG_ATH6K_LEGACY is not set
+# CONFIG_USB_ENESTORAGE is not set
+# CONFIG_BCM_WIMAX is not set
+# CONFIG_FT1000 is not set
+
+#
+# Speakup console speech
+#
+# CONFIG_TOUCHSCREEN_CLEARPAD_TM1217 is not set
+# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_USE_FOR_EXT23=y
+# CONFIG_EXT4_FS_XATTR is not set
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_JBD2=y
+# CONFIG_JBD2_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_EXPORTFS=y
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+# CONFIG_DNOTIFY is not set
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
+# CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=y
+# CONFIG_CUSE is not set
+CONFIG_GENERIC_ACL=y
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=y
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_TMPFS_XATTR=y
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_YAFFS_FS=y
+CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_9BYTE_TAGS is not set
+# CONFIG_YAFFS_DOES_ECC is not set
+CONFIG_YAFFS_YAFFS2=y
+CONFIG_YAFFS_AUTO_YAFFS2=y
+# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set
+# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
+# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set
+# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set
+# CONFIG_YAFFS_DISABLE_BACKGROUND is not set
+CONFIG_YAFFS_XATTR=y
+# CONFIG_JFFS2_FS is not set
+# CONFIG_LOGFS is not set
+CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
+# CONFIG_PSTORE is not set
+CONFIG_SYSV_FS=y
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_DEPRECATED=y
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_V4 is not set
+CONFIG_LOCKD=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_CEPH_FS is not set
+CONFIG_CIFS=y
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+# CONFIG_MINIX_SUBPARTITION is not set
+CONFIG_SOLARIS_X86_PARTITION=y
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+# CONFIG_LOCKUP_DETECTOR is not set
+# CONFIG_HARDLOCKUP_DETECTOR is not set
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=10
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_LOCK_STAT is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_INFO_REDUCED is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_TEST_LIST_SORT is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_LKDTM is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_DEBUG_PAGEALLOC is not set
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACER_MAX_TRACE=y
+CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_EVENT_POWER_TRACING_DEPRECATED=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
+CONFIG_TRACING=y
+CONFIG_GENERIC_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+CONFIG_SCHED_TRACER=y
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_RING_BUFFER_BENCHMARK is not set
+CONFIG_DYNAMIC_DEBUG=y
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_STRICT_DEVMEM is not set
+# CONFIG_ARM_UNWIND is not set
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_LL is not set
+CONFIG_OC_ETM=y
+CONFIG_DEBUG_S3C_UART=2
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_AUTHENC=y
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_GHASH is not set
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_TWOFISH_COMMON=y
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=y
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_S5P is not set
+CONFIG_BINARY_PRINTF=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+# CONFIG_XZ_DEC is not set
+# CONFIG_XZ_DEC_BCJ is not set
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_REED_SOLOMON=y
+CONFIG_REED_SOLOMON_ENC8=y
+CONFIG_REED_SOLOMON_DEC8=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=y
+CONFIG_TEXTSEARCH_BM=y
+CONFIG_TEXTSEARCH_FSM=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
+# CONFIG_AVERAGE is not set
diff --git a/arch/arm/configs/herring_defconfig b/arch/arm/configs/herring_defconfig
new file mode 100644
index 0000000..74d6850
--- /dev/null
+++ b/arch/arm/configs/herring_defconfig
@@ -0,0 +1,408 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_DEBUG=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_PANIC_TIMEOUT=5
+CONFIG_KALLSYMS_ALL=y
+CONFIG_ASHMEM=y
+# CONFIG_AIO is not set
+CONFIG_EMBEDDED=y
+CONFIG_PERF_COUNTERS=y
+CONFIG_PROFILING=y
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_ARCH_S5PV210=y
+CONFIG_S3C_LOWLEVEL_UART_PORT=2
+CONFIG_S5P_HIGH_RES_TIMERS=y
+CONFIG_S5PV210_SD_CH0_8BIT=y
+CONFIG_MACH_HERRING=y
+CONFIG_WIFI_CONTROL_FUNC=y
+CONFIG_ARM_THUMBEE=y
+CONFIG_FIQ_DEBUGGER=y
+CONFIG_FIQ_DEBUGGER_CONSOLE=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_COMPACTION=y
+CONFIG_KSM=y
+CONFIG_CMDLINE="console=ttyFIQ0"
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_BINFMT_MISC=y
+CONFIG_WAKELOCK=y
+CONFIG_APM_EMULATION=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_INET_ESP=y
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+CONFIG_IPV6=y
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_TUNNEL=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_NETFILTER=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_REJECT_SKERR=y
+CONFIG_IP_NF_TARGET_LOG=y
+CONFIG_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_TARGET_LOG=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_TARGET_REJECT_SKERR=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+CONFIG_PHONET=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_INGRESS=y
+CONFIG_NET_CLS_U32=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=y
+CONFIG_NET_ACT_GACT=y
+CONFIG_NET_ACT_MIRRED=y
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_HIDP=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_CFG80211=y
+CONFIG_NL80211_TESTMODE=y
+# CONFIG_CFG80211_WEXT is not set
+CONFIG_CFG80211_ALLOW_RECONNECT=y
+CONFIG_WIMAX=y
+CONFIG_RFKILL=y
+CONFIG_RFKILL_INPUT=y
+CONFIG_MTD=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_ONENAND=y
+CONFIG_MTD_ONENAND_SAMSUNG=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_MISC_DEVICES=y
+CONFIG_SENSORS_AK8973=y
+CONFIG_SENSORS_KR3DM=y
+CONFIG_UID_STAT=y
+CONFIG_APANIC=y
+CONFIG_SAMSUNG_JACK=y
+CONFIG_USB_SWITCH_FSA9480=y
+CONFIG_SAMSUNG_MODEMCTL=y
+CONFIG_PN544=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_DEBUG=y
+CONFIG_DM_CRYPT=y
+CONFIG_DM_UEVENT=y
+CONFIG_NETDEVICES=y
+CONFIG_IFB=y
+CONFIG_TUN=y
+CONFIG_BCMDHD=y
+CONFIG_BCMDHD_FW_PATH="/vendor/firmware/fw_bcmdhd.bin"
+CONFIG_BCMDHD_NVRAM_PATH="/vendor/firmware/nvram_net.txt"
+CONFIG_WIMAX_CMC7XX=y
+CONFIG_PPP=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_MPPE=y
+CONFIG_PPPOLAC=y
+CONFIG_PPPOPNS=y
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=800
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
+CONFIG_INPUT_JOYDEV=y
+CONFIG_INPUT_EVDEV=y
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYPAD_CYPRESS_TOUCH=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_XPAD=y
+CONFIG_JOYSTICK_XPAD_FF=y
+CONFIG_INPUT_TABLET=y
+CONFIG_TABLET_USB_ACECAD=y
+CONFIG_TABLET_USB_AIPTEK=y
+CONFIG_TABLET_USB_GTCO=y
+CONFIG_TABLET_USB_HANWANG=y
+CONFIG_TABLET_USB_KBTAB=y
+CONFIG_TABLET_USB_WACOM=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_MXT224=y
+CONFIG_INPUT_MISC=y
+CONFIG_GYRO_K3G=y
+CONFIG_INPUT_KEYCHORD=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_GPIO=y
+CONFIG_OPTICAL_GP2A=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_SAMSUNG=y
+CONFIG_SERIAL_SAMSUNG_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_GPIO=y
+CONFIG_I2C_S3C2410=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_BATTERY_MAX17040=y
+CONFIG_BATTERY_S5PC110=y
+# CONFIG_HWMON is not set
+CONFIG_MFD_MAX8998=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_MAX8893=y
+CONFIG_REGULATOR_MAX8998=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_S5KA3DFX=y
+CONFIG_VIDEO_S5K4ECGX=y
+CONFIG_VIDEO_SAMSUNG=y
+CONFIG_VIDEO_SAMSUNG_V4L2=y
+CONFIG_VIDEO_FIMC=y
+# CONFIG_VIDEO_FIMC_MIPI is not set
+CONFIG_VIDEO_MFC50=y
+CONFIG_VIDEO_JPEG_V2=y
+CONFIG_PVR_SGX=y
+CONFIG_PVR_NEED_PVR_DPF=y
+CONFIG_PVR_NEED_PVR_ASSERT=y
+CONFIG_PVR_USSE_EDM_STATUS_DEBUG=y
+CONFIG_PVR_LINUX_MEM_AREA_POOL=y
+CONFIG_FB=y
+CONFIG_FB_S3C=y
+CONFIG_FB_S3C_NR_BUFFERS=7
+CONFIG_FB_S3C_TL2796=y
+CONFIG_FB_S3C_NT35580=y
+# CONFIG_FB_S3C_LVDS is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_SAMSUNG=y
+CONFIG_SND_SOC_SAMSUNG_HERRING_WM8994=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_ACRUX=y
+CONFIG_HID_ACRUX_FF=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_DRAGONRISE=y
+CONFIG_DRAGONRISE_FF=y
+CONFIG_HID_EMS_FF=y
+CONFIG_HID_ELECOM=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_KEYTOUCH=y
+CONFIG_HID_KYE=y
+CONFIG_HID_UCLOGIC=y
+CONFIG_HID_WALTOP=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_TWINHAN=y
+CONFIG_HID_KENSINGTON=y
+CONFIG_HID_LCPOWER=y
+CONFIG_HID_LOGITECH=y
+CONFIG_LOGITECH_FF=y
+CONFIG_LOGIRUMBLEPAD2_FF=y
+CONFIG_LOGIG940_FF=y
+CONFIG_LOGIWII_FF=y
+CONFIG_HID_MAGICMOUSE=y
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_MULTITOUCH=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_ORTEK=y
+CONFIG_HID_PANTHERLORD=y
+CONFIG_PANTHERLORD_FF=y
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_PICOLCD=y
+CONFIG_HID_QUANTA=y
+CONFIG_HID_ROCCAT_ARVO=y
+CONFIG_HID_ROCCAT_KONE=y
+CONFIG_HID_ROCCAT_KONEPLUS=y
+CONFIG_HID_ROCCAT_KOVAPLUS=y
+CONFIG_HID_ROCCAT_PYRA=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_HID_GREENASIA=y
+CONFIG_GREENASIA_FF=y
+CONFIG_HID_SMARTJOYPLUS=y
+CONFIG_SMARTJOYPLUS_FF=y
+CONFIG_HID_TOPSEED=y
+CONFIG_HID_THRUSTMASTER=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_HID_WACOM=y
+CONFIG_HID_ZEROPLUS=y
+CONFIG_ZEROPLUS_FF=y
+CONFIG_HID_ZYDACRON=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_VBUS_DRAW=500
+CONFIG_USB_G_ANDROID=y
+CONFIG_USB_ANDROID_RNDIS_DWORD_ALIGNED=y
+CONFIG_USB=y
+CONFIG_USB_S3C_OTG_HOST=y
+CONFIG_USB_DWC_OTG=y
+CONFIG_DWC_DEBUG=y
+CONFIG_DWC_HOST_ONLY=y
+CONFIG_USB_DEBUG=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_SERIAL=y
+CONFIG_USB_SERIAL_CONSOLE=y
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_FTDI_SIO=y
+CONFIG_USB_ACM=y
+CONFIG_MMC=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_S3C=y
+CONFIG_MMC_SDHCI_S3C_DMA=y
+CONFIG_SWITCH=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_S3C=y
+CONFIG_STAGING=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_LOGGER=y
+CONFIG_ANDROID_RAM_CONSOLE=y
+CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION=y
+CONFIG_ANDROID_TIMED_GPIO=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT4_FS=y
+# CONFIG_EXT4_FS_XATTR is not set
+# CONFIG_DNOTIFY is not set
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_YAFFS_FS=y
+CONFIG_CRAMFS=y
+CONFIG_ROMFS_FS=y
+CONFIG_SYSV_FS=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_EFI_PARTITION=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_SCHED_TRACER=y
+CONFIG_DYNAMIC_DEBUG=y
+# CONFIG_ARM_UNWIND is not set
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_S3C_UART=2
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRC_CCITT=y
diff --git a/arch/arm/configs/mxs_defconfig b/arch/arm/configs/mxs_defconfig
index 2bf2243..166d6aa 100644
--- a/arch/arm/configs/mxs_defconfig
+++ b/arch/arm/configs/mxs_defconfig
@@ -29,7 +29,6 @@ CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_PREEMPT_VOLUNTARY=y
CONFIG_AEABI=y
-CONFIG_DEFAULT_MMAP_MIN_ADDR=65536
CONFIG_AUTO_ZRELADDR=y
CONFIG_FPE_NWFPE=y
CONFIG_NET=y
diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h
index 1252a26..42dec04 100644
--- a/arch/arm/include/asm/cacheflush.h
+++ b/arch/arm/include/asm/cacheflush.h
@@ -215,7 +215,9 @@ static inline void vivt_flush_cache_mm(struct mm_struct *mm)
static inline void
vivt_flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end)
{
- if (cpumask_test_cpu(smp_processor_id(), mm_cpumask(vma->vm_mm)))
+ struct mm_struct *mm = vma->vm_mm;
+
+ if (!mm || cpumask_test_cpu(smp_processor_id(), mm_cpumask(mm)))
__cpuc_flush_user_range(start & PAGE_MASK, PAGE_ALIGN(end),
vma->vm_flags);
}
@@ -223,7 +225,9 @@ vivt_flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned
static inline void
vivt_flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned long pfn)
{
- if (cpumask_test_cpu(smp_processor_id(), mm_cpumask(vma->vm_mm))) {
+ struct mm_struct *mm = vma->vm_mm;
+
+ if (!mm || cpumask_test_cpu(smp_processor_id(), mm_cpumask(mm))) {
unsigned long addr = user_addr & PAGE_MASK;
__cpuc_flush_user_range(addr, addr + PAGE_SIZE, vma->vm_flags);
}
diff --git a/arch/arm/include/asm/hardware/vic.h b/arch/arm/include/asm/hardware/vic.h
index 5d72550..ec34fc7 100644
--- a/arch/arm/include/asm/hardware/vic.h
+++ b/arch/arm/include/asm/hardware/vic.h
@@ -42,6 +42,7 @@
#ifndef __ASSEMBLY__
void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources);
+int vic_set_fiq(unsigned int irq, bool enable);
#endif
#endif
diff --git a/arch/arm/include/asm/mutex.h b/arch/arm/include/asm/mutex.h
index 93226cf..b1479fd 100644
--- a/arch/arm/include/asm/mutex.h
+++ b/arch/arm/include/asm/mutex.h
@@ -7,121 +7,10 @@
*/
#ifndef _ASM_MUTEX_H
#define _ASM_MUTEX_H
-
-#if __LINUX_ARM_ARCH__ < 6
-/* On pre-ARMv6 hardware the swp based implementation is the most efficient. */
-# include <asm-generic/mutex-xchg.h>
-#else
-
/*
- * Attempting to lock a mutex on ARMv6+ can be done with a bastardized
- * atomic decrement (it is not a reliable atomic decrement but it satisfies
- * the defined semantics for our purpose, while being smaller and faster
- * than a real atomic decrement or atomic swap. The idea is to attempt
- * decrementing the lock value only once. If once decremented it isn't zero,
- * or if its store-back fails due to a dispute on the exclusive store, we
- * simply bail out immediately through the slow path where the lock will be
- * reattempted until it succeeds.
+ * On pre-ARMv6 hardware this results in a swp-based implementation,
+ * which is the most efficient. For ARMv6+, we emit a pair of exclusive
+ * accesses instead.
*/
-static inline void
-__mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
-{
- int __ex_flag, __res;
-
- __asm__ (
-
- "ldrex %0, [%2] \n\t"
- "sub %0, %0, #1 \n\t"
- "strex %1, %0, [%2] "
-
- : "=&r" (__res), "=&r" (__ex_flag)
- : "r" (&(count)->counter)
- : "cc","memory" );
-
- __res |= __ex_flag;
- if (unlikely(__res != 0))
- fail_fn(count);
-}
-
-static inline int
-__mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
-{
- int __ex_flag, __res;
-
- __asm__ (
-
- "ldrex %0, [%2] \n\t"
- "sub %0, %0, #1 \n\t"
- "strex %1, %0, [%2] "
-
- : "=&r" (__res), "=&r" (__ex_flag)
- : "r" (&(count)->counter)
- : "cc","memory" );
-
- __res |= __ex_flag;
- if (unlikely(__res != 0))
- __res = fail_fn(count);
- return __res;
-}
-
-/*
- * Same trick is used for the unlock fast path. However the original value,
- * rather than the result, is used to test for success in order to have
- * better generated assembly.
- */
-static inline void
-__mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *))
-{
- int __ex_flag, __res, __orig;
-
- __asm__ (
-
- "ldrex %0, [%3] \n\t"
- "add %1, %0, #1 \n\t"
- "strex %2, %1, [%3] "
-
- : "=&r" (__orig), "=&r" (__res), "=&r" (__ex_flag)
- : "r" (&(count)->counter)
- : "cc","memory" );
-
- __orig |= __ex_flag;
- if (unlikely(__orig != 0))
- fail_fn(count);
-}
-
-/*
- * If the unlock was done on a contended lock, or if the unlock simply fails
- * then the mutex remains locked.
- */
-#define __mutex_slowpath_needs_to_unlock() 1
-
-/*
- * For __mutex_fastpath_trylock we use another construct which could be
- * described as a "single value cmpxchg".
- *
- * This provides the needed trylock semantics like cmpxchg would, but it is
- * lighter and less generic than a true cmpxchg implementation.
- */
-static inline int
-__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *))
-{
- int __ex_flag, __res, __orig;
-
- __asm__ (
-
- "1: ldrex %0, [%3] \n\t"
- "subs %1, %0, #1 \n\t"
- "strexeq %2, %1, [%3] \n\t"
- "movlt %0, #0 \n\t"
- "cmpeq %2, #0 \n\t"
- "bgt 1b "
-
- : "=&r" (__orig), "=&r" (__res), "=&r" (__ex_flag)
- : "r" (&count->counter)
- : "cc", "memory" );
-
- return __orig;
-}
-
-#endif
+#include <asm-generic/mutex-xchg.h>
#endif
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index 5750704..6afd081 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -360,6 +360,18 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd)
#define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext)
#define pte_clear(mm,addr,ptep) set_pte_ext(ptep, __pte(0), 0)
+#define pte_none(pte) (!pte_val(pte))
+#define pte_present(pte) (pte_val(pte) & L_PTE_PRESENT)
+#define pte_write(pte) (!(pte_val(pte) & L_PTE_RDONLY))
+#define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY)
+#define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG)
+#define pte_exec(pte) (!(pte_val(pte) & L_PTE_XN))
+#define pte_special(pte) (0)
+
+#define pte_present_user(pte) \
+ ((pte_val(pte) & (L_PTE_PRESENT | L_PTE_USER)) == \
+ (L_PTE_PRESENT | L_PTE_USER))
+
#if __LINUX_ARM_ARCH__ < 6
static inline void __sync_icache_dcache(pte_t pteval)
{
@@ -371,25 +383,15 @@ extern void __sync_icache_dcache(pte_t pteval);
static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
pte_t *ptep, pte_t pteval)
{
- if (addr >= TASK_SIZE)
- set_pte_ext(ptep, pteval, 0);
- else {
+ unsigned long ext = 0;
+
+ if (addr < TASK_SIZE && pte_present_user(pteval)) {
__sync_icache_dcache(pteval);
- set_pte_ext(ptep, pteval, PTE_EXT_NG);
+ ext |= PTE_EXT_NG;
}
-}
-#define pte_none(pte) (!pte_val(pte))
-#define pte_present(pte) (pte_val(pte) & L_PTE_PRESENT)
-#define pte_write(pte) (!(pte_val(pte) & L_PTE_RDONLY))
-#define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY)
-#define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG)
-#define pte_exec(pte) (!(pte_val(pte) & L_PTE_XN))
-#define pte_special(pte) (0)
-
-#define pte_present_user(pte) \
- ((pte_val(pte) & (L_PTE_PRESENT | L_PTE_USER)) == \
- (L_PTE_PRESENT | L_PTE_USER))
+ set_pte_ext(ptep, pteval, ext);
+}
#define PTE_BIT_FUNC(fn,op) \
static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; }
@@ -416,13 +418,13 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
*
* 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
* 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * <--------------- offset --------------------> <- type --> 0 0 0
+ * <--------------- offset ----------------------> < type -> 0 0 0
*
- * This gives us up to 63 swap files and 32GB per swap file. Note that
+ * This gives us up to 31 swap files and 64GB per swap file. Note that
* the offset field is always non-zero.
*/
#define __SWP_TYPE_SHIFT 3
-#define __SWP_TYPE_BITS 6
+#define __SWP_TYPE_BITS 5
#define __SWP_TYPE_MASK ((1 << __SWP_TYPE_BITS) - 1)
#define __SWP_OFFSET_SHIFT (__SWP_TYPE_BITS + __SWP_TYPE_SHIFT)
diff --git a/arch/arm/include/asm/vfpmacros.h b/arch/arm/include/asm/vfpmacros.h
index 3d5fc41..bf53047 100644
--- a/arch/arm/include/asm/vfpmacros.h
+++ b/arch/arm/include/asm/vfpmacros.h
@@ -28,7 +28,7 @@
ldr \tmp, =elf_hwcap @ may not have MVFR regs
ldr \tmp, [\tmp, #0]
tst \tmp, #HWCAP_VFPv3D16
- ldceq p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d16-d31}
+ ldceql p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d16-d31}
addne \base, \base, #32*4 @ step over unused register space
#else
VFPFMRX \tmp, MVFR0 @ Media and VFP Feature Register 0
@@ -52,7 +52,7 @@
ldr \tmp, =elf_hwcap @ may not have MVFR regs
ldr \tmp, [\tmp, #0]
tst \tmp, #HWCAP_VFPv3D16
- stceq p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d16-d31}
+ stceql p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d16-d31}
addne \base, \base, #32*4 @ step over unused register space
#else
VFPFMRX \tmp, MVFR0 @ Media and VFP Feature Register 0
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 9739bb8..181baa2 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -278,20 +278,26 @@ static void __cpuinit smp_store_cpu_info(unsigned int cpuid)
asmlinkage void __cpuinit secondary_start_kernel(void)
{
struct mm_struct *mm = &init_mm;
- unsigned int cpu = smp_processor_id();
+ unsigned int cpu;
- printk("CPU%u: Booted secondary processor\n", cpu);
+ /*
+ * The identity mapping is uncached (strongly ordered), so
+ * switch away from it before attempting any exclusive accesses.
+ */
+ cpu_switch_mm(mm->pgd, mm);
+ enter_lazy_tlb(mm, current);
+ local_flush_tlb_all();
/*
* All kernel threads share the same mm context; grab a
* reference and switch to it.
*/
+ cpu = smp_processor_id();
atomic_inc(&mm->mm_count);
current->active_mm = mm;
cpumask_set_cpu(cpu, mm_cpumask(mm));
- cpu_switch_mm(mm->pgd, mm);
- enter_lazy_tlb(mm, current);
- local_flush_tlb_all();
+
+ printk("CPU%u: Booted secondary processor\n", cpu);
cpu_init();
preempt_disable();
@@ -450,9 +456,7 @@ static DEFINE_PER_CPU(struct clock_event_device, percpu_clockevent);
static void ipi_timer(void)
{
struct clock_event_device *evt = &__get_cpu_var(percpu_clockevent);
- irq_enter();
evt->event_handler(evt);
- irq_exit();
}
#ifdef CONFIG_LOCAL_TIMERS
@@ -463,7 +467,9 @@ asmlinkage void __exception_irq_entry do_local_timer(struct pt_regs *regs)
if (local_timer_ack()) {
__inc_irq_stat(cpu, local_timer_irqs);
+ irq_enter();
ipi_timer();
+ irq_exit();
}
set_irq_regs(old_regs);
@@ -625,23 +631,31 @@ asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs)
switch (ipinr) {
case IPI_TIMER:
+ irq_enter();
ipi_timer();
- break;
+ irq_exit();
+ break;
case IPI_RESCHEDULE:
scheduler_ipi();
break;
case IPI_CALL_FUNC:
+ irq_enter();
generic_smp_call_function_interrupt();
+ irq_exit();
break;
case IPI_CALL_FUNC_SINGLE:
+ irq_enter();
generic_smp_call_function_single_interrupt();
+ irq_exit();
break;
case IPI_CPU_STOP:
+ irq_enter();
ipi_cpu_stop(cpu);
+ irq_exit();
break;
case IPI_CPU_BACKTRACE:
diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c
index 62e7c61..0264ab4 100644
--- a/arch/arm/kernel/sys_arm.c
+++ b/arch/arm/kernel/sys_arm.c
@@ -115,7 +115,7 @@ int kernel_execve(const char *filename,
"Ir" (THREAD_START_SP - sizeof(regs)),
"r" (&regs),
"Ir" (sizeof(regs))
- : "r0", "r1", "r2", "r3", "ip", "lr", "memory");
+ : "r0", "r1", "r2", "r3", "r8", "r9", "ip", "lr", "memory");
out:
return ret;
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index 7227755..871a818 100644
--- a/arch/arm/mach-at91/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -454,7 +454,7 @@ static struct i2c_gpio_platform_data pdata = {
static struct platform_device at91rm9200_twi_device = {
.name = "i2c-gpio",
- .id = -1,
+ .id = 0,
.dev.platform_data = &pdata,
};
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index 39f81f4..89a8414 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -459,7 +459,7 @@ static struct i2c_gpio_platform_data pdata = {
static struct platform_device at91sam9260_twi_device = {
.name = "i2c-gpio",
- .id = -1,
+ .id = 0,
.dev.platform_data = &pdata,
};
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index 5004bf0..5d43cf4 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -276,7 +276,7 @@ static struct i2c_gpio_platform_data pdata = {
static struct platform_device at91sam9261_twi_device = {
.name = "i2c-gpio",
- .id = -1,
+ .id = 0,
.dev.platform_data = &pdata,
};
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index a050f41..2bbd163 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -534,7 +534,7 @@ static struct i2c_gpio_platform_data pdata = {
static struct platform_device at91sam9263_twi_device = {
.name = "i2c-gpio",
- .id = -1,
+ .id = 0,
.dev.platform_data = &pdata,
};
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index aacb19d..659870e 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -319,7 +319,7 @@ static struct i2c_gpio_platform_data pdata = {
static struct platform_device at91sam9rl_twi_device = {
.name = "i2c-gpio",
- .id = -1,
+ .id = 0,
.dev.platform_data = &pdata,
};
diff --git a/arch/arm/mach-imx/mach-mx21ads.c b/arch/arm/mach-imx/mach-mx21ads.c
index 74ac889..a37fe02 100644
--- a/arch/arm/mach-imx/mach-mx21ads.c
+++ b/arch/arm/mach-imx/mach-mx21ads.c
@@ -32,7 +32,7 @@
* Memory-mapped I/O on MX21ADS base board
*/
#define MX21ADS_MMIO_BASE_ADDR 0xf5000000
-#define MX21ADS_MMIO_SIZE SZ_16M
+#define MX21ADS_MMIO_SIZE 0xc00000
#define MX21ADS_REG_ADDR(offset) (void __force __iomem *) \
(MX21ADS_MMIO_BASE_ADDR + (offset))
diff --git a/arch/arm/mach-omap2/opp.c b/arch/arm/mach-omap2/opp.c
index ab8b35b..0627494 100644
--- a/arch/arm/mach-omap2/opp.c
+++ b/arch/arm/mach-omap2/opp.c
@@ -53,7 +53,7 @@ int __init omap_init_opp_table(struct omap_opp_def *opp_def,
omap_table_init = 1;
/* Lets now register with OPP library */
- for (i = 0; i < opp_def_size; i++) {
+ for (i = 0; i < opp_def_size; i++, opp_def++) {
struct omap_hwmod *oh;
struct device *dev;
@@ -86,7 +86,6 @@ int __init omap_init_opp_table(struct omap_opp_def *opp_def,
__func__, opp_def->freq,
opp_def->hwmod_name, i, r);
}
- opp_def++;
}
return 0;
diff --git a/arch/arm/mach-orion5x/mpp.h b/arch/arm/mach-orion5x/mpp.h
index eac6897..db70e79 100644
--- a/arch/arm/mach-orion5x/mpp.h
+++ b/arch/arm/mach-orion5x/mpp.h
@@ -65,8 +65,8 @@
#define MPP8_GIGE MPP(8, 0x1, 0, 0, 1, 1, 1)
#define MPP9_UNUSED MPP(9, 0x0, 0, 0, 1, 1, 1)
-#define MPP9_GPIO MPP(9, 0x0, 0, 0, 1, 1, 1)
-#define MPP9_GIGE MPP(9, 0x1, 1, 1, 1, 1, 1)
+#define MPP9_GPIO MPP(9, 0x0, 1, 1, 1, 1, 1)
+#define MPP9_GIGE MPP(9, 0x1, 0, 0, 1, 1, 1)
#define MPP10_UNUSED MPP(10, 0x0, 0, 0, 1, 1, 1)
#define MPP10_GPIO MPP(10, 0x0, 1, 1, 1, 1, 1)
diff --git a/arch/arm/mach-s5pv210/Kconfig b/arch/arm/mach-s5pv210/Kconfig
index 37b5a97..26672b0 100644
--- a/arch/arm/mach-s5pv210/Kconfig
+++ b/arch/arm/mach-s5pv210/Kconfig
@@ -18,13 +18,24 @@ config CPU_S5PV210
help
Enable S5PV210 CPU support
+config CPU_DIDLE
+ bool "Enable DEEP IDLE support for S5PV210 CPU"
+ depends on CPU_IDLE
+ default n
+ help
+ Enable DEEP IDLE support for S5PV210 CPU.
+
config S5PV210_SETUP_I2C1
bool
+ default y
+ select HAVE_S3C2410_I2C
help
Common setup code for i2c bus 1.
config S5PV210_SETUP_I2C2
bool
+ default y
+ select HAVE_S3C2410_I2C
help
Common setup code for i2c bus 2.
@@ -59,6 +70,39 @@ config S5PV210_SETUP_FIMC
help
Common setup code for the camera interfaces.
+config S5PV210_POWER_DOMAIN
+ bool
+ depends on REGULATOR
+ default y
+ help
+ Enable S5PV210 power domain support.
+
+config S5PV210_CORESIGHT
+ bool "Coresight"
+ select OC_ETM
+ default y
+ help
+ Support embedded trace cell
+
+comment "MMC/SD slot setup"
+depends on PLAT_S5P
+
+menu "Use 8-bit bus width"
+config S5PV210_SD_CH0_8BIT
+bool "Channel 0"
+depends on PLAT_S5P
+default n
+help
+IF channel 0 uses 8-bit bus, channel 1 is disabled.
+
+config S5PV210_SD_CH2_8BIT
+bool "Channel 2"
+depends on PLAT_S5P
+default n
+help
+IF channel 2 uses 8-bit bus, channel 3 is disabled.
+endmenu
+
menu "S5PC110 Machines"
config MACH_AQUILA
@@ -108,6 +152,7 @@ config MACH_SMDKC110
select S3C_DEV_I2C1
select S3C_DEV_I2C2
select S3C_DEV_RTC
+ select HAVE_S3C_RTC
select S3C_DEV_WDT
select SAMSUNG_DEV_IDE
select S5PV210_SETUP_I2C1
@@ -172,4 +217,63 @@ config S5PV210_PM
help
Power Management code common to S5PV210
+config MACH_HERRING
+ bool "Herring"
+ select CPU_S5PV210
+ select S3C_DEV_WDT
+ select S3C_DEV_I2C1
+ select S3C_DEV_I2C2
+ select S5P_DEV_ONENAND
+ select HAVE_PWM
+ select SAMSUNG_DEV_PWM
+ select S3C_DEV_HSMMC
+ select S3C_DEV_HSMMC1 if !S5PV210_SD_CH0_8BIT
+ select S3C_DEV_HSMMC2
+ select S3C_DEV_HSMMC3 if !S5PV210_SD_CH2_8BIT
+ select S5PV210_SETUP_SDHCI
+ select S5PV210_POWER_DOMAIN
+ select S5P_DEV_CSIS0
+ select S5P_SETUP_MIPIPHY
+ help
+ Machine support for Herring
+
+config S5PV210_SETUP_FB
+ bool
+ depends on FB_S3C
+ default y
+ help
+ Common setup code for FIMD controller.
+
+config S5P_ADC
+ bool "S5PXXXX ADC driver"
+ depends on PLAT_S5P
+ default y
+ help
+ ADC ( A/D Conversion ) driver for Samsung S5PXXXX
+
+config S5PV210_SETUP_FIMC0
+ bool
+ depends on VIDEO_FIMC || CPU_FREQ
+ default y
+ help
+ Common setup code for FIMC controller 0.
+
+config S5PV210_SETUP_FIMC1
+ bool
+ depends on VIDEO_FIMC || CPU_FREQ
+ default y
+ help
+ Common setup code for FIMC controller 1.
+
+config S5PV210_SETUP_FIMC2
+ bool
+ depends on VIDEO_FIMC || CPU_FREQ
+ default y
+ help
+ Common setup code for FIMC controller 2.
+
+config WIFI_CONTROL_FUNC
+ bool "Enable WiFi control function abstraction"
+ help
+ Enables Power/Reset/Carddetect function abstraction
endif
diff --git a/arch/arm/mach-s5pv210/Makefile b/arch/arm/mach-s5pv210/Makefile
index 50907ac..1c79fc9 100644
--- a/arch/arm/mach-s5pv210/Makefile
+++ b/arch/arm/mach-s5pv210/Makefile
@@ -1,7 +1,7 @@
# arch/arm/mach-s5pv210/Makefile
#
# Copyright (c) 2010 Samsung Electronics Co., Ltd.
-# http://www.samsung.com/
+# http://www.samsung.com/
#
# Licensed under GPLv2
@@ -17,6 +17,9 @@ obj-$(CONFIG_CPU_S5PV210) += setup-i2c0.o
obj-$(CONFIG_S5PV210_PM) += pm.o sleep.o
obj-$(CONFIG_CPU_FREQ) += cpufreq.o
+obj-$(CONFIG_S5PV210_POWER_DOMAIN) += power-domain.o
+obj-$(CONFIG_S5PV210_CORESIGHT) += coresight.o
+
# machine support
obj-$(CONFIG_MACH_AQUILA) += mach-aquila.o
@@ -24,13 +27,25 @@ obj-$(CONFIG_MACH_SMDKV210) += mach-smdkv210.o
obj-$(CONFIG_MACH_SMDKC110) += mach-smdkc110.o
obj-$(CONFIG_MACH_GONI) += mach-goni.o
obj-$(CONFIG_MACH_TORBRECK) += mach-torbreck.o
+obj-$(CONFIG_MACH_HERRING) += mach-herring.o herring-rfkill.o
+obj-$(CONFIG_MACH_HERRING) += herring-vibrator.o
+obj-$(CONFIG_MACH_HERRING) += herring-btlpm.o
+obj-$(CONFIG_MACH_HERRING) += herring-watchdog.o
+obj-$(CONFIG_MACH_HERRING) += herring-panel.o
+obj-$(CONFIG_MACH_HERRING) += herring-touchkey-led.o
+
+obj-$(CONFIG_MACH_HERRING) += dev-herring-phone.o
# device support
obj-y += dev-audio.o
+obj-y += dev-fiqdbg.o
obj-$(CONFIG_S3C64XX_DEV_SPI) += dev-spi.o
-obj-$(CONFIG_S5PV210_SETUP_FB_24BPP) += setup-fb-24bpp.o
+
+obj-$(CONFIG_S5P_ADC) += adc.o
+
+obj-$(CONFIG_S5PV210_SETUP_FB) += setup-fb.o
obj-$(CONFIG_S5PV210_SETUP_FIMC) += setup-fimc.o
obj-$(CONFIG_S5PV210_SETUP_I2C1) += setup-i2c1.o
obj-$(CONFIG_S5PV210_SETUP_I2C2) += setup-i2c2.o
@@ -38,3 +53,10 @@ obj-$(CONFIG_S5PV210_SETUP_IDE) += setup-ide.o
obj-$(CONFIG_S5PV210_SETUP_KEYPAD) += setup-keypad.o
obj-$(CONFIG_S5PV210_SETUP_SDHCI) += setup-sdhci.o
obj-$(CONFIG_S5PV210_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o
+obj-$(CONFIG_S5PV210_SETUP_FIMC0) += setup-fimc0.o
+obj-$(CONFIG_S5PV210_SETUP_FIMC1) += setup-fimc1.o
+obj-$(CONFIG_S5PV210_SETUP_FIMC2) += setup-fimc2.o
+
+obj-$(CONFIG_CPU_IDLE) += cpuidle.o
+obj-$(CONFIG_CPU_FREQ) += dev-cpufreq.o
+obj-$(CONFIG_CPU_DIDLE) += didle.o
diff --git a/arch/arm/mach-s5pv210/Makefile.boot b/arch/arm/mach-s5pv210/Makefile.boot
index ff90aa1..58ed679 100644
--- a/arch/arm/mach-s5pv210/Makefile.boot
+++ b/arch/arm/mach-s5pv210/Makefile.boot
@@ -1,2 +1,6 @@
- zreladdr-y := 0x20008000
+zreladdr-y := 0x20008000
params_phys-y := 0x20000100
+
+# override for Herring
+zreladdr-$(CONFIG_MACH_HERRING) := 0x30008000
+params_phys-$(CONFIG_MACH_HERRING) := 0x30000100
diff --git a/arch/arm/mach-s5pv210/adc.c b/arch/arm/mach-s5pv210/adc.c
new file mode 100644
index 0000000..d7945fb
--- /dev/null
+++ b/arch/arm/mach-s5pv210/adc.c
@@ -0,0 +1,401 @@
+/* linux/arch/arm/mach-s5pv210/adc.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Copyright (c) 2004 Arnaud Patard <arnaud.patard@rtp-net.org>
+ * iPAQ H1940 touchscreen support
+ *
+ * ChangeLog
+ *
+ * 2004-09-05: Herbert Pötzl <herbert@13thfloor.at>
+ * - added clock (de-)allocation code
+ *
+ * 2005-03-06: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - h1940_ -> s3c24xx (this driver is now also used on the n30
+ * machines :P)
+ * - Debug messages are now enabled with the config option
+ * TOUCHSCREEN_S3C_DEBUG
+ * - Changed the way the value are read
+ * - Input subsystem should now work
+ * - Use ioremap and readl/writel
+ *
+ * 2005-03-23: Arnaud Patard <arnaud.patard@rtp-net.org>
+ * - Make use of some undocumented features of the touchscreen
+ * controller
+ *
+ */
+
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/init.h>
+#include <linux/serio.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/miscdevice.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+
+#include <asm/irq.h>
+#include <mach/hardware.h>
+#include <linux/uaccess.h>
+
+#include <mach/regs-adc.h>
+#include <mach/adc.h>
+#include <mach/irqs.h>
+
+#define ADC_MINOR 131
+#define ADC_INPUT_PIN _IOW('S', 0x0c, unsigned long)
+
+#define ADC_WITH_TOUCHSCREEN
+
+static struct clk *adc_clock;
+
+static void __iomem *base_addr;
+static int adc_port;
+struct s3c_adc_mach_info *plat_data;
+
+#ifdef ADC_WITH_TOUCHSCREEN
+static DEFINE_MUTEX(adc_mutex);
+
+static unsigned long data_for_ADCCON;
+static unsigned long data_for_ADCTSC;
+
+static void s3c_adc_save_SFR_on_ADC(void)
+{
+ data_for_ADCCON = readl(base_addr + S3C_ADCCON);
+ data_for_ADCTSC = readl(base_addr + S3C_ADCTSC);
+}
+
+static void s3c_adc_restore_SFR_on_ADC(void)
+{
+ writel(data_for_ADCCON, base_addr + S3C_ADCCON);
+ writel(data_for_ADCTSC, base_addr + S3C_ADCTSC);
+}
+#else
+static struct resource *adc_mem;
+#endif
+
+static int s3c_adc_open(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static unsigned int s3c_adc_convert(void)
+{
+ unsigned int adc_return = 0;
+ unsigned long data0;
+ unsigned long data1;
+
+ writel((readl(base_addr + S3C_ADCCON) | S3C_ADCCON_PRSCEN) & ~S3C_ADCCON_STDBM,
+ base_addr + S3C_ADCCON);
+
+ writel((adc_port & 0xF), base_addr + S3C_ADCMUX);
+
+ udelay(10);
+
+ writel(readl(base_addr + S3C_ADCCON) | S3C_ADCCON_ENABLE_START,
+ base_addr + S3C_ADCCON);
+
+ do {
+ data0 = readl(base_addr + S3C_ADCCON);
+ } while (!(data0 & S3C_ADCCON_ECFLG));
+
+ data1 = readl(base_addr + S3C_ADCDAT0);
+
+ writel((readl(base_addr + S3C_ADCCON) | S3C_ADCCON_STDBM) & ~S3C_ADCCON_PRSCEN,
+ base_addr + S3C_ADCCON);
+
+ if (plat_data->resolution == 12)
+ adc_return = data1 & S3C_ADCDAT0_XPDATA_MASK_12BIT;
+ else
+ adc_return = data1 & S3C_ADCDAT0_XPDATA_MASK;
+
+ return adc_return;
+}
+
+
+int s3c_adc_get_adc_data(int channel)
+{
+ int adc_value = 0;
+ int cur_adc_port = 0;
+
+#ifdef ADC_WITH_TOUCHSCREEN
+ mutex_lock(&adc_mutex);
+ s3c_adc_save_SFR_on_ADC();
+#else
+ mutex_lock(&adc_mutex);
+#endif
+
+ cur_adc_port = adc_port;
+ adc_port = channel;
+
+ adc_value = s3c_adc_convert();
+
+ adc_port = cur_adc_port;
+
+#ifdef ADC_WITH_TOUCHSCREEN
+ s3c_adc_restore_SFR_on_ADC();
+ mutex_unlock(&adc_mutex);
+#else
+ mutex_unlock(&adc_mutex);
+#endif
+
+ pr_debug("%s : Converted Value: %03d\n", __func__, adc_value);
+
+ return adc_value;
+}
+EXPORT_SYMBOL(s3c_adc_get_adc_data);
+
+int s3c_adc_get(struct s3c_adc_request *req)
+{
+ unsigned adc_channel = req->channel;
+ int adc_value_ret = 0;
+
+ adc_value_ret = s3c_adc_convert();
+
+ req->callback(adc_channel, req->param, adc_value_ret);
+
+ return 0;
+}
+EXPORT_SYMBOL(s3c_adc_get);
+
+static ssize_t
+s3c_adc_read(struct file *file, char __user *buffer,
+ size_t size, loff_t *pos)
+{
+ int adc_value = 0;
+
+#ifdef ADC_WITH_TOUCHSCREEN
+ mutex_lock(&adc_mutex);
+ s3c_adc_save_SFR_on_ADC();
+#endif
+ printk(KERN_INFO "## delay: %d\n", readl(base_addr + S3C_ADCDLY));
+ adc_value = s3c_adc_convert();
+
+#ifdef ADC_WITH_TOUCHSCREEN
+ s3c_adc_restore_SFR_on_ADC();
+ mutex_unlock(&adc_mutex);
+#endif
+
+ if (copy_to_user(buffer, &adc_value, sizeof(unsigned int)))
+ return -EFAULT;
+
+ return sizeof(unsigned int);
+}
+
+
+static long s3c_adc_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+
+ switch (cmd) {
+ case ADC_INPUT_PIN:
+ adc_port = (unsigned int) arg;
+
+ if (adc_port >= 4)
+ printk(KERN_WARNING
+ " %d is already reserved for TouchScreen\n",
+ adc_port);
+ return 0;
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+static const struct file_operations s3c_adc_fops = {
+ .owner = THIS_MODULE,
+ .read = s3c_adc_read,
+ .open = s3c_adc_open,
+ .unlocked_ioctl = s3c_adc_ioctl,
+};
+
+static struct miscdevice s3c_adc_miscdev = {
+ .minor = ADC_MINOR,
+ .name = "adc",
+ .fops = &s3c_adc_fops,
+};
+
+static struct s3c_adc_mach_info *s3c_adc_get_platdata(struct device *dev)
+{
+ if (dev->platform_data != NULL)
+ return (struct s3c_adc_mach_info *) dev->platform_data;
+ else
+ return 0;
+}
+
+/*
+ * The functions for inserting/removing us as a module.
+ */
+
+static int __devinit s3c_adc_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ struct device *dev;
+ int ret;
+ int size;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ dev = &pdev->dev;
+
+ if (res == NULL) {
+ dev_err(dev, "no memory resource specified\n");
+ return -ENOENT;
+ }
+
+ size = (res->end - res->start) + 1;
+
+#if !defined(ADC_WITH_TOUCHSCREEN)
+ adc_mem = request_mem_region(res->start, size, pdev->name);
+ if (adc_mem == NULL) {
+ dev_err(dev, "failed to get memory region\n");
+ ret = -ENOENT;
+ goto err_req;
+ }
+#endif
+
+ base_addr = ioremap(res->start, size);
+ if (base_addr == NULL) {
+ dev_err(dev, "fail to ioremap() region\n");
+ ret = -ENOENT;
+ goto err_map;
+ }
+
+ adc_clock = clk_get(&pdev->dev, "adc");
+
+ if (IS_ERR(adc_clock)) {
+ dev_err(dev, "failed to fine ADC clock source\n");
+ ret = PTR_ERR(adc_clock);
+ goto err_clk;
+ }
+
+ clk_enable(adc_clock);
+
+ /* read platform data from device struct */
+ plat_data = s3c_adc_get_platdata(&pdev->dev);
+
+ if ((plat_data->presc & 0xff) > 0)
+ writel(S3C_ADCCON_PRSCEN |
+ S3C_ADCCON_PRSCVL(plat_data->presc & 0xff),
+ base_addr + S3C_ADCCON);
+ else
+ writel(0, base_addr + S3C_ADCCON);
+
+ /* Initialise registers */
+ if ((plat_data->delay & 0xffff) > 0)
+ writel(plat_data->delay & 0xffff, base_addr + S3C_ADCDLY);
+
+ if (plat_data->resolution == 12)
+ writel(readl(base_addr + S3C_ADCCON) |
+ S3C_ADCCON_RESSEL_12BIT, base_addr + S3C_ADCCON);
+
+ writel((readl(base_addr + S3C_ADCCON) | S3C_ADCCON_STDBM) & ~S3C_ADCCON_PRSCEN,
+ base_addr + S3C_ADCCON);
+
+ ret = misc_register(&s3c_adc_miscdev);
+ if (ret) {
+ printk(KERN_ERR "cannot register miscdev on minor=%d (%d)\n",
+ ADC_MINOR, ret);
+ goto err_clk;
+ }
+
+ return 0;
+
+err_clk:
+ clk_disable(adc_clock);
+ clk_put(adc_clock);
+
+err_map:
+ iounmap(base_addr);
+
+#if !defined(ADC_WITH_TOUCHSCREEN)
+err_req:
+ release_resource(adc_mem);
+ kfree(adc_mem);
+#endif
+
+ return ret;
+}
+
+
+static int s3c_adc_remove(struct platform_device *dev)
+{
+ clk_disable(adc_clock);
+ clk_put(adc_clock);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static unsigned int adccon, adctsc, adcdly;
+
+static int s3c_adc_suspend(struct platform_device *dev, pm_message_t state)
+{
+ adccon = readl(base_addr + S3C_ADCCON);
+ adctsc = readl(base_addr + S3C_ADCTSC);
+ adcdly = readl(base_addr + S3C_ADCDLY);
+
+ return 0;
+}
+
+static int s3c_adc_resume(struct platform_device *pdev)
+{
+ writel(adccon, base_addr + S3C_ADCCON);
+ writel(adctsc, base_addr + S3C_ADCTSC);
+ writel(adcdly, base_addr + S3C_ADCDLY);
+
+ return 0;
+}
+#else
+#define s3c_adc_suspend NULL
+#define s3c_adc_resume NULL
+#endif
+
+static struct platform_driver s3c_adc_driver = {
+ .probe = s3c_adc_probe,
+ .remove = s3c_adc_remove,
+ .suspend = s3c_adc_suspend,
+ .resume = s3c_adc_resume,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "s3c-adc",
+ },
+};
+
+static char banner[] __initdata = KERN_INFO \
+ "S5PV210 ADC driver, (c) 2010 Samsung Electronics\n";
+
+int __init s3c_adc_init(void)
+{
+ printk(banner);
+ return platform_driver_register(&s3c_adc_driver);
+}
+
+void __exit s3c_adc_exit(void)
+{
+ platform_driver_unregister(&s3c_adc_driver);
+}
+
+module_init(s3c_adc_init);
+module_exit(s3c_adc_exit);
+
+MODULE_AUTHOR("dsfine.ha@samsung.com");
+MODULE_DESCRIPTION("S5PV210 ADC driver");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c
index 2d59949..6d3e609 100644
--- a/arch/arm/mach-s5pv210/clock.c
+++ b/arch/arm/mach-s5pv210/clock.c
@@ -19,6 +19,8 @@
#include <linux/clk.h>
#include <linux/sysdev.h>
#include <linux/io.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
#include <mach/map.h>
@@ -30,9 +32,13 @@
#include <plat/s5p-clock.h>
#include <plat/clock-clksrc.h>
#include <plat/s5pv210.h>
+#include <plat/devs.h>
+#include <mach/regs-audss.h>
static unsigned long xtal;
+static int s5pv210_usbosc_enable(struct clk *clk, int enable);
+
static struct clksrc_clk clk_mout_apll = {
.clk = {
.name = "mout_apll",
@@ -175,6 +181,16 @@ static int s5pv210_clk_ip3_ctrl(struct clk *clk, int enable)
return s5p_gatectrl(S5P_CLKGATE_IP3, clk, enable);
}
+static int s5pv210_clk_ip4_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P_CLKGATE_IP4, clk, enable);
+}
+
+static int s5pv210_clk_ip5_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P_CLKGATE_IP5, clk, enable);
+}
+
static int s5pv210_clk_mask0_ctrl(struct clk *clk, int enable)
{
return s5p_gatectrl(S5P_CLK_SRC_MASK0, clk, enable);
@@ -185,6 +201,11 @@ static int s5pv210_clk_mask1_ctrl(struct clk *clk, int enable)
return s5p_gatectrl(S5P_CLK_SRC_MASK1, clk, enable);
}
+static int s5pv210_clk_audss_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P_CLKGATE_AUDSS, clk, enable);
+}
+
static struct clk clk_sclk_hdmi27m = {
.name = "sclk_hdmi27m",
.id = -1,
@@ -206,6 +227,21 @@ static struct clk clk_sclk_usbphy1 = {
.id = -1,
};
+static struct clk clk_i2scdclk0 = {
+ .name = "i2scdclk",
+ .id = 0,
+};
+
+static struct clk clk_i2scdclk1 = {
+ .name = "i2scdclk",
+ .id = 1,
+};
+
+static struct clk clk_i2scdclk2 = {
+ .name = "i2scdclk",
+ .id = 2,
+};
+
static struct clk clk_pcmcdclk0 = {
.name = "pcmcdclk",
.id = -1,
@@ -311,18 +347,6 @@ static struct clk_ops clk_fout_apll_ops = {
static struct clk init_clocks_off[] = {
{
- .name = "pdma",
- .id = 0,
- .parent = &clk_hclk_psys.clk,
- .enable = s5pv210_clk_ip0_ctrl,
- .ctrlbit = (1 << 3),
- }, {
- .name = "pdma",
- .id = 1,
- .parent = &clk_hclk_psys.clk,
- .enable = s5pv210_clk_ip0_ctrl,
- .ctrlbit = (1 << 4),
- }, {
.name = "rot",
.id = -1,
.parent = &clk_hclk_dsys.clk,
@@ -359,11 +383,30 @@ static struct clk init_clocks_off[] = {
.enable = s5pv210_clk_ip1_ctrl,
.ctrlbit = (1<<17),
}, {
- .name = "lcd",
+ .name = "jpeg",
+ .id = -1,
+ .parent = &clk_hclk_dsys.clk,
+ .enable = s5pv210_clk_ip5_ctrl,
+ .ctrlbit = S5P_CLKGATE_IP5_JPEG,
+ }, {
+ .name = "mfc",
+ .id = -1,
+ .parent = &clk_hclk_msys.clk,
+ .enable = s5pv210_clk_ip0_ctrl,
+ .ctrlbit = (1<<16),
+ }, {
+ .name = "dsim",
.id = -1,
.parent = &clk_hclk_dsys.clk,
.enable = s5pv210_clk_ip1_ctrl,
- .ctrlbit = (1<<0),
+ .ctrlbit = (1<<2),
+ }, {
+ .name = "onenand",
+ .id = -1,
+ .parent = &clk_hclk_psys.clk,
+ .enable = s5pv210_clk_ip1_ctrl,
+ .ctrlbit = (1 << 24),
+ .dev = &s5p_device_onenand.dev,
}, {
.name = "cfcon",
.id = 0,
@@ -401,12 +444,6 @@ static struct clk init_clocks_off[] = {
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1<<16),
}, {
- .name = "watchdog",
- .id = -1,
- .parent = &clk_pclk_psys.clk,
- .enable = s5pv210_clk_ip3_ctrl,
- .ctrlbit = (1<<22),
- }, {
.name = "rtc",
.id = -1,
.parent = &clk_pclk_psys.clk,
@@ -490,11 +527,117 @@ static struct clk init_clocks_off[] = {
.parent = &clk_p,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = (1 << 0),
+ }, {
+ .name = "pcm",
+ .id = 2,
+ .parent = &clk_pclk_psys.clk,
+ .enable = s5pv210_clk_ip3_ctrl,
+ .ctrlbit = S5P_CLKGATE_IP3_PCM2,
+ }, {
+#if 0
+ .name = "pcm",
+ .id = 1,
+ .parent = &clk_pclk_psys.clk,
+ .enable = s5pv210_clk_ip3_ctrl,
+ .ctrlbit = S5P_CLKGATE_IP3_PCM1 | S5P_CLKGATE_IP3_I2S1 ,
+ }, {
+ .name = "pcm",
+ .id = 0,
+ .parent = &clk_pclk_psys.clk,
+ .enable = s5pv210_clk_ip3_ctrl,
+ .ctrlbit = S5P_CLKGATE_IP3_PCM0,
+ }, {
+#endif
+ .name = "i2c-hdmiphy",
+ .id = -1,
+ .parent = &clk_pclk_psys.clk,
+ .enable = s5pv210_clk_ip3_ctrl,
+ .ctrlbit = (1 << 11),
+ }, {
+ .name = "hdmi",
+ .id = -1,
+ .parent = &clk_hclk_dsys.clk,
+ .enable = s5pv210_clk_ip1_ctrl,
+ .ctrlbit = (1 << 11),
+ }, {
+ .name = "tvenc",
+ .id = -1,
+ .parent = &clk_hclk_dsys.clk,
+ .enable = s5pv210_clk_ip1_ctrl,
+ .ctrlbit = (1 << 10),
+ }, {
+ .name = "mixer",
+ .id = -1,
+ .parent = &clk_hclk_dsys.clk,
+ .enable = s5pv210_clk_ip1_ctrl,
+ .ctrlbit = (1 << 9),
+ }, {
+ .name = "vp",
+ .id = -1,
+ .parent = &clk_hclk_dsys.clk,
+ .enable = s5pv210_clk_ip1_ctrl,
+ .ctrlbit = (1 << 8),
+ }, {
+ .name = "usb_osc",
+ .id = -1,
+ .enable = s5pv210_usbosc_enable,
+ .ctrlbit = (1 << 1),
+ }, {
+ .name = "secss",
+ .id = -1,
+ .parent = &clk_hclk_psys.clk,
+ .enable = s5pv210_clk_ip2_ctrl,
+ .ctrlbit = (1 << 0),
+ }, {
+ .name = "seckey",
+ .id = -1,
+ .parent = &clk_pclk_psys.clk,
+ .enable = s5pv210_clk_ip4_ctrl,
+ .ctrlbit = (1 << 3),
},
};
+static struct clk init_dmaclocks[] = {
+ {
+ .name = "pdma",
+ .id = 0,
+ .parent = &clk_hclk_dsys.clk,
+ .enable = s5pv210_clk_ip0_ctrl,
+ .ctrlbit = (1<<2),
+ .dev = &s5pv210_device_mdma.dev,
+ }, {
+ .name = "pdma",
+ .id = 1,
+ .parent = &clk_hclk_psys.clk,
+ .enable = s5pv210_clk_ip0_ctrl,
+ .ctrlbit = (1<<3),
+ .dev = &s5pv210_device_pdma0.dev,
+ }, {
+ .name = "pdma",
+ .id = 2,
+ .parent = &init_dmaclocks[1],
+ .enable = s5pv210_clk_ip0_ctrl,
+ .ctrlbit = (1<<4),
+ .dev = &s5pv210_device_pdma1.dev,
+ },
+};
+
+static int s5pc11x_clk_out_set_rate(struct clk *clk, unsigned long rate);
+static int s5pc11x_clk_out_set_parent(struct clk *clk, struct clk *parent);
+
+static struct clk_ops s5pc11x_clkout_ops = {
+ .set_parent = s5pc11x_clk_out_set_parent,
+ .set_rate = s5pc11x_clk_out_set_rate,
+};
+
static struct clk init_clocks[] = {
{
+ .name = "watchdog",
+ .id = -1,
+ .parent = &clk_pclk_psys.clk,
+ .enable = s5pv210_clk_ip3_ctrl,
+ .ctrlbit = (1<<22),
+ }, {
.name = "hclk_imem",
.id = -1,
.parent = &clk_hclk_msys.clk,
@@ -502,6 +645,12 @@ static struct clk init_clocks[] = {
.enable = s5pv210_clk_ip0_ctrl,
.ops = &clk_hclk_imem_ops,
}, {
+ .name = "lcd",
+ .id = -1,
+ .parent = &clk_hclk_dsys.clk,
+ .enable = s5pv210_clk_ip1_ctrl,
+ .ctrlbit = (1<<0),
+ }, {
.name = "uart",
.id = 0,
.parent = &clk_pclk_psys.clk,
@@ -531,6 +680,21 @@ static struct clk init_clocks[] = {
.parent = &clk_hclk_psys.clk,
.enable = s5pv210_clk_ip1_ctrl,
.ctrlbit = (1 << 26),
+ }, {
+#if 1
+ .name = "i2s_v50",
+ .id = 0,
+ .parent = &clk_p,
+ .enable = s5pv210_clk_ip3_ctrl,
+ .ctrlbit = S5P_CLKGATE_IP3_I2S0 | S5P_CLKGATE_IP3_PCM0,
+ }, {
+#endif
+ .name = "clk_out",
+ .id = -1,
+ .ops = &s5pc11x_clkout_ops,
+ }, {
+ .name = "apb_pclk",
+ .id = -1,
},
};
@@ -627,6 +791,54 @@ static struct clksrc_sources clkset_sclk_mixer = {
.nr_sources = ARRAY_SIZE(clkset_sclk_mixer_list),
};
+static int s5pc11x_clk_out_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 val = 0, div = 0, rate_div = 1;
+ int err = -EINVAL;
+
+ if (rate && clk->parent) {
+ if (clk->parent == &clk_fout_apll)
+ rate_div = 4;
+ if (clk->parent == &clk_fout_mpll)
+ rate_div = 2;
+
+ div = clk_get_rate(clk->parent) / rate / rate_div;
+ val = __raw_readl(S5P_CLK_OUT);
+ val &= (~(0xF << 20));
+ val |= (div - 1) << 20;
+ __raw_writel(val, S5P_CLK_OUT);
+ err = 0;
+ }
+ return err;
+}
+
+static int s5pc11x_clk_out_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 val = 0;
+ int err = 0;
+ clk->parent = parent;
+ val = __raw_readl(S5P_CLK_OUT);
+
+ if (parent == &clk_fout_apll) {
+ val = val & (~(0x1F << 12));
+ val |= (0x0 << 12);
+ } else if (parent == &clk_fout_mpll) {
+ val = val & (~(0x1F << 12));
+ val |= (0x1 << 12);
+ } else if (parent == &clk_fout_epll) {
+ val = val & (~(0x1F << 12));
+ val |= (0x2 << 12);
+ } else if (parent == &clk_sclk_vpll.clk) {
+ val = val & (~(0x1F << 12));
+ val |= (0x3 << 12);
+ } else {
+ err = -EINVAL;
+ }
+
+ __raw_writel(val, S5P_CLK_OUT);
+ return err;
+}
+
static struct clk *clkset_sclk_audio0_list[] = {
[0] = &clk_ext_xtal_mux,
[1] = &clk_pcmcdclk0,
@@ -656,6 +868,59 @@ static struct clksrc_clk clk_sclk_audio0 = {
.reg_div = { .reg = S5P_CLK_DIV6, .shift = 0, .size = 4 },
};
+static struct clk *clkset_mout_audss_list[] = {
+ &clk_ext_xtal_mux,
+ &clk_fout_epll,
+};
+
+static struct clksrc_sources clkset_mout_audss = {
+ .sources = clkset_mout_audss_list,
+ .nr_sources = ARRAY_SIZE(clkset_mout_audss_list),
+};
+
+static struct clksrc_clk clk_mout_audss = {
+ .clk = {
+ .name = "mout_audss",
+ .id = -1,
+ },
+ .sources = &clkset_mout_audss,
+ .reg_src = { .reg = S5P_CLKSRC_AUDSS, .shift = 0, .size = 1 },
+};
+
+static struct clk *clkset_mout_i2s_a_list[] = {
+ &clk_mout_audss.clk,
+ &clk_pcmcdclk0,
+ &clk_sclk_audio0.clk,
+};
+
+static struct clksrc_sources clkset_mout_i2s_a = {
+ .sources = clkset_mout_i2s_a_list,
+ .nr_sources = ARRAY_SIZE(clkset_mout_i2s_a_list),
+};
+
+static struct clksrc_clk clk_mout_i2s_a = {
+ .clk = {
+ .name = "audio-bus",
+ .id = 0,
+ .enable = s5pv210_clk_audss_ctrl,
+ .ctrlbit = (1 << 6),
+ },
+ .sources = &clkset_mout_i2s_a,
+ .reg_src = { .reg = S5P_CLKSRC_AUDSS, .shift = 2, .size = 2 },
+ .reg_div = { .reg = S5P_CLKDIV_AUDSS, .shift = 4, .size = 4 },
+};
+
+static struct clksrc_clk clk_dout_audio_bus_clk_i2s = {
+ .clk = {
+ .name = "dout_audio_bus_clk_i2s",
+ .id = -1,
+ .parent = &clk_mout_audss.clk,
+ .enable = s5pv210_clk_audss_ctrl,
+ .ctrlbit = (1 << 5),
+ },
+ .reg_div = { .reg = S5P_CLKDIV_AUDSS, .shift = 0, .size = 4 },
+};
+
static struct clk *clkset_sclk_audio1_list[] = {
[0] = &clk_ext_xtal_mux,
[1] = &clk_pcmcdclk1,
@@ -808,40 +1073,44 @@ static struct clksrc_clk clksrcs[] = {
.reg_div = { .reg = S5P_CLK_DIV6, .shift = 12, .size = 3 },
}, {
.clk = {
- .name = "uclk1",
+ .name = "sclk",
.id = 0,
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 12),
+ .dev = &s3c24xx_uart_device0.dev,
},
.sources = &clkset_uart,
.reg_src = { .reg = S5P_CLK_SRC4, .shift = 16, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV4, .shift = 16, .size = 4 },
}, {
.clk = {
- .name = "uclk1",
+ .name = "sclk",
.id = 1,
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 13),
+ .dev = &s3c24xx_uart_device1.dev,
},
.sources = &clkset_uart,
.reg_src = { .reg = S5P_CLK_SRC4, .shift = 20, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV4, .shift = 20, .size = 4 },
}, {
.clk = {
- .name = "uclk1",
+ .name = "sclk",
.id = 2,
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 14),
+ .dev = &s3c24xx_uart_device2.dev,
},
.sources = &clkset_uart,
.reg_src = { .reg = S5P_CLK_SRC4, .shift = 24, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV4, .shift = 24, .size = 4 },
}, {
.clk = {
- .name = "uclk1",
+ .name = "sclk",
.id = 3,
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 15),
+ .dev = &s3c24xx_uart_device3.dev,
},
.sources = &clkset_uart,
.reg_src = { .reg = S5P_CLK_SRC4, .shift = 28, .size = 4 },
@@ -909,8 +1178,8 @@ static struct clksrc_clk clksrcs[] = {
.clk = {
.name = "sclk_fimd",
.id = -1,
- .enable = s5pv210_clk_mask0_ctrl,
- .ctrlbit = (1 << 5),
+ .enable = s5pv210_clk_ip1_ctrl,
+ .ctrlbit = (1 << 0),
},
.sources = &clkset_group2,
.reg_src = { .reg = S5P_CLK_SRC1, .shift = 20, .size = 4 },
@@ -967,7 +1236,7 @@ static struct clksrc_clk clksrcs[] = {
.reg_div = { .reg = S5P_CLK_DIV2, .shift = 4, .size = 4 },
}, {
.clk = {
- .name = "sclk_g2d",
+ .name = "sclk_fimg2d",
.id = -1,
.enable = s5pv210_clk_ip0_ctrl,
.ctrlbit = (1 << 12),
@@ -977,10 +1246,11 @@ static struct clksrc_clk clksrcs[] = {
.reg_div = { .reg = S5P_CLK_DIV2, .shift = 8, .size = 4 },
}, {
.clk = {
- .name = "sclk_g3d",
+ .name = "sclk",
.id = -1,
.enable = s5pv210_clk_ip0_ctrl,
.ctrlbit = (1 << 8),
+ .dev = &s3c_device_g3d.dev,
},
.sources = &clkset_group1,
.reg_src = { .reg = S5P_CLK_SRC2, .shift = 0, .size = 2 },
@@ -1035,7 +1305,41 @@ static struct clksrc_clk clksrcs[] = {
.sources = &clkset_group2,
.reg_src = { .reg = S5P_CLK_SRC5, .shift = 12, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV5, .shift = 12, .size = 4 },
+ }, {
+ .clk = {
+ .name = "sclk_mdnie",
+ .id = -1,
+ .enable = s5pv210_clk_mask1_ctrl,
+ .ctrlbit = (1 << 0),
+ },
+ .sources = &clkset_group2,
+ .reg_src = { .reg = S5P_CLK_SRC3, .shift = 0,
+ .size = 4 },
+ .reg_div = { .reg = S5P_CLK_DIV3, .shift = 0, .size = 4 },
+ }, {
+ .clk = {
+ .name = "sclk_mdnie_pwm",
+ .id = -1,
+ .enable = s5pv210_clk_mask1_ctrl,
+ .ctrlbit = (1 << 1),
+ },
+ .sources = &clkset_group2,
+ .reg_src = { .reg = S5P_CLK_SRC3, .shift = 4,
+ .size = 4 },
+ .reg_div = { .reg = S5P_CLK_DIV3, .shift = 4, .size = 4 },
+ },
+};
+
+/* MOUT CSIS */
+static struct clksrc_clk clk_mout_csis = {
+ .clk = {
+ .name = "mout_csis",
+ .id = -1,
+ .enable = s5pv210_clk_mask0_ctrl,
+ .ctrlbit = (1 << 6),
},
+ .sources = &clkset_group1,
+ .reg_src = { .reg = S5P_CLK_SRC1, .shift = 24, .size = 4 },
};
/* Clock initialisation code */
@@ -1058,12 +1362,29 @@ static struct clksrc_clk *sysclks[] = {
&clk_sclk_hdmi,
&clk_mout_dmc0,
&clk_sclk_dmc0,
+ &clk_mout_csis,
&clk_sclk_audio0,
&clk_sclk_audio1,
&clk_sclk_audio2,
&clk_sclk_spdif,
+ &clk_mout_audss,
+ &clk_mout_i2s_a,
+ &clk_dout_audio_bus_clk_i2s,
};
+static int s5pv210_usbosc_enable(struct clk *clk, int enable)
+{
+ unsigned int ctrlbit = clk->ctrlbit;
+ unsigned int usbosc_con = __raw_readl(S5P_SLEEP_CFG) & ~ctrlbit;
+
+ if (enable)
+ usbosc_con |= ctrlbit;
+
+ writel(usbosc_con, S5P_SLEEP_CFG);
+
+ return 0;
+}
+
static u32 epll_div[][6] = {
{ 48000000, 0, 48, 3, 3, 0 },
{ 96000000, 0, 48, 3, 2, 0 },
@@ -1157,6 +1478,7 @@ void __init_or_cpufreq s5pv210_setup_clocks(void)
unsigned long vpll;
unsigned int ptr;
u32 clkdiv0, clkdiv1;
+ struct clksrc_clk *pclkSrc;
/* Set functions for clk_fout_epll */
clk_fout_epll.enable = s5p_epll_enable;
@@ -1210,8 +1532,38 @@ void __init_or_cpufreq s5pv210_setup_clocks(void)
clk_h.rate = hclk_psys;
clk_p.rate = pclk_psys;
- for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
- s3c_set_clksrc(&clksrcs[ptr], true);
+ /*Assign clock source and rates for IP's*/
+ for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) {
+ pclkSrc = &clksrcs[ptr];
+ if (!strcmp(pclkSrc->clk.name, "sclk_mdnie")) {
+ clk_set_parent(&pclkSrc->clk, &clk_mout_mpll.clk);
+ clk_set_rate(&pclkSrc->clk, 167*MHZ);
+ } else if (!strcmp(pclkSrc->clk.name, "sclk_mmc")) {
+ clk_set_parent(&pclkSrc->clk, &clk_mout_mpll.clk);
+
+ if (pclkSrc->clk.id == 0)
+ clk_set_rate(&pclkSrc->clk, 52*MHZ);
+ else
+ clk_set_rate(&pclkSrc->clk, 50*MHZ);
+ } else if (!strcmp(pclkSrc->clk.name, "sclk_spi")) {
+ clk_set_parent(&pclkSrc->clk, &clk_mout_epll.clk);
+ } else if (!strcmp(pclkSrc->clk.name, "sclk_cam") &&
+ (pclkSrc->clk.id == 0)) {
+ clk_set_parent(&pclkSrc->clk, &clk_xusbxti);
+ } else if (!strcmp(pclkSrc->clk.name, "sclk_g2d")) {
+ clk_set_parent(&pclkSrc->clk, &clk_mout_mpll.clk);
+ clk_set_rate(&pclkSrc->clk, 250*MHZ);
+ } else if (!strcmp(pclkSrc->clk.name, "sclk")) {
+ clk_set_parent(&pclkSrc->clk, &clk_mout_mpll.clk);
+
+ if (pclkSrc->clk.id == 0)
+ clk_set_rate(&pclkSrc->clk, 133400000);
+ else
+ clk_set_rate(&pclkSrc->clk, 66700000);
+ }
+ /* Display the clock source */
+ s3c_set_clksrc(pclkSrc, true);
+ }
}
static struct clk *clks[] __initdata = {
@@ -1219,6 +1571,9 @@ static struct clk *clks[] __initdata = {
&clk_sclk_hdmiphy,
&clk_sclk_usbphy0,
&clk_sclk_usbphy1,
+ &clk_i2scdclk0,
+ &clk_i2scdclk1,
+ &clk_i2scdclk2,
&clk_pcmcdclk0,
&clk_pcmcdclk1,
&clk_pcmcdclk2,
@@ -1239,5 +1594,9 @@ void __init s5pv210_register_clocks(void)
s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
+ /* Register DMA Clock */
+ s3c_register_clocks(init_dmaclocks, ARRAY_SIZE(init_dmaclocks));
+ s3c_disable_clocks(init_dmaclocks, ARRAY_SIZE(init_dmaclocks));
+
s3c_pwmclk_init();
}
diff --git a/arch/arm/mach-s5pv210/coresight.c b/arch/arm/mach-s5pv210/coresight.c
new file mode 100755
index 0000000..b8c29c7
--- /dev/null
+++ b/arch/arm/mach-s5pv210/coresight.c
@@ -0,0 +1,163 @@
+/* coresight.c
+ *
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <asm/hardware/coresight.h>
+#include <linux/amba/bus.h>
+#include <linux/io.h>
+#include <plat/pm.h>
+
+#define CS_ETB_BASE (0xE0D00000 + 0x1000)
+#define CS_FUNNEL_BASE (0xE0D00000 + 0x4000)
+#define CS_ETM_BASE (0xE0D00000 + 0x6000)
+#define TZPC3_BASE (0xE1C00000)
+
+static void __iomem *cs_etb_regs;
+static void __iomem *cs_funnel_regs;
+static void __iomem *cs_etm_regs;
+static void __iomem *tzpc3_regs;
+
+static void cs_unlock(void *regs)
+{
+ writel(UNLOCK_MAGIC, regs + CSMR_LOCKACCESS);
+ readl(regs + CSMR_LOCKSTATUS);
+}
+
+static void cs_relock(void *regs)
+{
+ writel(0, regs + CSMR_LOCKACCESS);
+}
+
+static void cs_init_static_regs(void)
+{
+ /* Enable NIDEN and SPNIDEN */
+ writel(0x5, tzpc3_regs + 0x828);
+
+ /* Set funnel control: Enable ATB port0 */
+ cs_unlock(cs_funnel_regs);
+ writel(0x301, cs_funnel_regs);
+ cs_relock(cs_funnel_regs);
+}
+
+#ifdef CONFIG_PM
+static void (*orig_pm_cpu_prep)(void);
+static void (*orig_pm_cpu_restore)(void);
+
+static u32 etm_state[64];
+static int etm_state_count;
+static u32 etb_ffcr;
+static u32 etb_ctl;
+
+static void cs_pm_prep(void)
+{
+ int save_count;
+
+ if (orig_pm_cpu_prep)
+ orig_pm_cpu_prep();
+
+ cs_unlock(cs_etb_regs);
+ etb_ctl = readl(cs_etb_regs + ETBR_CTRL);
+ etb_ffcr = readl(cs_etb_regs + ETBR_FORMATTERCTRL);
+ cs_relock(cs_etb_regs);
+
+ cs_unlock(cs_etm_regs);
+ writel(UNLOCK_MAGIC, cs_etm_regs + ETMMR_OSLAR);
+ save_count = readl(cs_etm_regs + ETMMR_OSSRR);
+ pr_debug("%s: trace_pm_prep reg count %d\n", __func__, save_count);
+ if (save_count > ARRAY_SIZE(etm_state))
+ save_count = 0;
+ etm_state_count = 0;
+ while (save_count--)
+ etm_state[etm_state_count++] = readl(cs_etm_regs + ETMMR_OSSRR);
+ writel(0, cs_etm_regs + ETMMR_OSLAR);
+ cs_relock(cs_etm_regs);
+}
+
+static void cs_pm_resume(void)
+{
+ int i;
+
+ cs_init_static_regs();
+
+ cs_unlock(cs_etb_regs);
+ writel(etb_ffcr, cs_etb_regs + ETBR_FORMATTERCTRL);
+ writel(etb_ctl, cs_etb_regs + ETBR_CTRL);
+ cs_relock(cs_etb_regs);
+
+ cs_unlock(cs_etm_regs);
+ readl(cs_etm_regs + ETMMR_PDSR);
+ writel(UNLOCK_MAGIC, cs_etm_regs + ETMMR_OSLAR);
+ readl(cs_etm_regs + ETMMR_OSSRR);
+ for (i = 0; i < etm_state_count; i++) {
+ writel(etm_state[i], cs_etm_regs + ETMMR_OSSRR);
+ pr_debug("%s: restore %d %08x\n", __func__, i, etm_state[i]);
+ }
+ writel(0, cs_etm_regs + ETMMR_OSLAR);
+ cs_relock(cs_etm_regs);
+
+ if (orig_pm_cpu_restore)
+ orig_pm_cpu_restore();
+}
+
+static void cs_pm_init(void)
+{
+ orig_pm_cpu_restore = pm_cpu_restore;
+ orig_pm_cpu_prep = pm_cpu_prep;
+ pm_cpu_restore = cs_pm_resume;
+ pm_cpu_prep = cs_pm_prep;
+}
+#else
+static inline void cs_pm_init(void) {}
+#endif
+
+static struct amba_device s5pv210_etb_device = {
+ .dev = {
+ .init_name = "etb",
+ },
+ .res = {
+ .start = CS_ETB_BASE,
+ .end = CS_ETB_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ .periphid = 0x000bb907,
+};
+
+static struct amba_device s5pv210_etm_device = {
+ .dev = {
+ .init_name = "etm",
+ },
+ .res = {
+ .start = CS_ETM_BASE,
+ .end = CS_ETM_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ .periphid = 0x005bb921,
+};
+
+static int trace_init(void)
+{
+ cs_etb_regs = ioremap(CS_ETB_BASE, SZ_4K);
+ cs_funnel_regs = ioremap(CS_FUNNEL_BASE, SZ_4K);
+ cs_etm_regs = ioremap(CS_ETM_BASE, SZ_4K);
+ tzpc3_regs = ioremap(TZPC3_BASE, SZ_4K);
+
+ cs_init_static_regs();
+
+ cs_pm_init();
+
+ amba_device_register(&s5pv210_etb_device, &iomem_resource);
+ amba_device_register(&s5pv210_etm_device, &iomem_resource);
+ return 0;
+}
+device_initcall(trace_init);
diff --git a/arch/arm/mach-s5pv210/cpu.c b/arch/arm/mach-s5pv210/cpu.c
index 61e6c24..9974724 100644
--- a/arch/arm/mach-s5pv210/cpu.c
+++ b/arch/arm/mach-s5pv210/cpu.c
@@ -25,6 +25,7 @@
#include <asm/mach/map.h>
#include <asm/mach/irq.h>
+#include <asm/mach-types.h>
#include <asm/proc-fns.h>
#include <mach/map.h>
#include <mach/regs-clock.h>
@@ -95,7 +96,31 @@ static struct map_desc s5pv210_iodesc[] __initdata = {
.pfn =__phys_to_pfn(S5PV210_PA_HSPHY),
.length = SZ_4K,
.type = MT_DEVICE,
- }
+ }, {
+ .virtual = (unsigned long)S3C_VA_OTG,
+ .pfn = __phys_to_pfn(S5PV210_PA_OTG),
+ .length = SZ_1M,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = (unsigned long)S3C_VA_OTGSFR,
+ .pfn = __phys_to_pfn(S5PV210_PA_OTGSFR),
+ .length = SZ_1M,
+ .type = MT_DEVICE,
+ },
+#if defined(CONFIG_HRT_RTC)
+ {
+ .virtual = (unsigned long)S5P_VA_RTC,
+ .pfn = __phys_to_pfn(S5PV210_PA_RTC),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ },
+#endif
+ {
+ .virtual = (unsigned long)S5P_VA_AUDSS,
+ .pfn = __phys_to_pfn(S5PV210_PA_AUDSS),
+ .length = SZ_1M,
+ .type = MT_DEVICE,
+ },
};
static void s5pv210_idle(void)
@@ -191,7 +216,8 @@ int __init s5pv210_init(void)
pm_idle = s5pv210_idle;
/* set sw_reset function */
- s5p_reset_hook = s5pv210_sw_reset;
+ if (!machine_is_herring())
+ s5p_reset_hook = s5pv210_sw_reset;
return sysdev_register(&s5pv210_sysdev);
}
diff --git a/arch/arm/mach-s5pv210/cpufreq.c b/arch/arm/mach-s5pv210/cpufreq.c
index 153af8b..8d07351 100644
--- a/arch/arm/mach-s5pv210/cpufreq.c
+++ b/arch/arm/mach-s5pv210/cpufreq.c
@@ -16,20 +16,48 @@
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/io.h>
+#include <linux/suspend.h>
+#include <linux/reboot.h>
+#include <linux/regulator/consumer.h>
#include <linux/cpufreq.h>
+#include <linux/platform_device.h>
#include <mach/map.h>
#include <mach/regs-clock.h>
+#include <mach/cpu-freq-v210.h>
+
+#ifdef CONFIG_CPU_DIDLE
+#include <linux/deep_idle.h>
+#endif
static struct clk *cpu_clk;
static struct clk *dmc0_clk;
static struct clk *dmc1_clk;
static struct cpufreq_freqs freqs;
-
-/* APLL M,P,S values for 1G/800Mhz */
+static DEFINE_MUTEX(set_freq_lock);
+
+/* APLL M,P,S values for 1.4GHz/1.2GHz/1.0GHz/800MHz */
+#define APLL_VAL_1400 ((1 << 31) | (175 << 16) | (3 << 8) | 1)
+#define APLL_VAL_1320 ((1 << 31) | (330 << 16) | (6 << 8) | 1)
+#define APLL_VAL_1300 ((1 << 31) | (325 << 16) | (6 << 8) | 0)
+#define APLL_VAL_1200 ((1 << 31) | (150 << 16) | (3 << 8) | 1)
+#define APLL_VAL_1100 ((1 << 31) | (275 << 16) | (6 << 8) | 1)
#define APLL_VAL_1000 ((1 << 31) | (125 << 16) | (3 << 8) | 1)
#define APLL_VAL_800 ((1 << 31) | (100 << 16) | (3 << 8) | 1)
+#define SLEEP_FREQ (800 * 1000) /* Use 800MHz when entering sleep */
+
+/*
+ * relation has an additional symantics other than the standard of cpufreq
+ * DISALBE_FURTHER_CPUFREQ: disable further access to target until being re-enabled.
+ * ENABLE_FURTUER_CPUFREQ: re-enable access to target
+*/
+enum cpufreq_access {
+ DISABLE_FURTHER_CPUFREQ = 0x10,
+ ENABLE_FURTHER_CPUFREQ = 0x20,
+};
+static bool no_cpufreq_access;
+
/*
* DRAM configurations to calculate refresh counter for changing
* frequency of memory.
@@ -43,7 +71,7 @@ struct dram_conf {
static struct dram_conf s5pv210_dram_conf[2];
enum perf_level {
- L0, L1, L2, L3, L4,
+ L0, L1, L2, L3, L4, L5, L6
};
enum s5pv210_mem_type {
@@ -58,15 +86,82 @@ enum s5pv210_dmc_port {
};
static struct cpufreq_frequency_table s5pv210_freq_table[] = {
- {L0, 1000*1000},
- {L1, 800*1000},
- {L2, 400*1000},
- {L3, 200*1000},
- {L4, 100*1000},
+ {L0, 1400*1000},
+ {L1, 1200*1000},
+ {L2, 1000*1000},
+ {L3, 800*1000},
+ {L4, 400*1000},
+ {L5, 200*1000},
+ {L6, 100*1000},
{0, CPUFREQ_TABLE_END},
};
-static u32 clkdiv_val[5][11] = {
+// Define the freqs affected on the code to reduce changes
+// if we add or remove a new freq on the table
+unsigned int L_100 = L6;
+unsigned int L_1000 = L2;
+unsigned int L_200 = L5;
+#define SpeedSteeps 7
+
+static u32 sAPLL_confs[] = {
+ APLL_VAL_1400,
+ APLL_VAL_1200,
+ APLL_VAL_1000,
+ APLL_VAL_800,
+ APLL_VAL_800,
+ APLL_VAL_800,
+ APLL_VAL_800,
+ APLL_VAL_800,
+};
+
+static struct regulator *arm_regulator;
+static struct regulator *internal_regulator;
+
+struct s5pv210_dvs_conf {
+ unsigned long arm_volt; /* uV */
+ unsigned long int_volt; /* uV */
+};
+
+#ifdef CONFIG_CUSTOM_VOLTAGE
+unsigned long arm_volt_max = 1450000;
+unsigned long int_volt_max = 1250000;
+#else
+const unsigned long arm_volt_max = 1450000;
+const unsigned long int_volt_max = 1250000;
+#endif
+
+static struct s5pv210_dvs_conf dvs_conf[] = {
+ [L0] = {
+ .arm_volt = 1420000,
+ .int_volt = 1180000,
+ },
+ [L1] = {
+ .arm_volt = 1320000,
+ .int_volt = 1110000,
+ },
+ [L2] = {
+ .arm_volt = 1250000,
+ .int_volt = 1100000,
+ },
+ [L3] = {
+ .arm_volt = 1200000,
+ .int_volt = 1100000,
+ },
+ [L4] = {
+ .arm_volt = 1050000,
+ .int_volt = 1100000,
+ },
+ [L5] = {
+ .arm_volt = 950000,
+ .int_volt = 1100000,
+ },
+ [L6] = {
+ .arm_volt = 950000,
+ .int_volt = 1000000,
+ },
+};
+
+static u32 clkdiv_val[SpeedSteeps][11] = {
/*
* Clock divider value for following
* { APLL, A2M, HCLK_MSYS, PCLK_MSYS,
@@ -74,19 +169,25 @@ static u32 clkdiv_val[5][11] = {
* ONEDRAM, MFC, G3D }
*/
- /* L0 : [1000/200/100][166/83][133/66][200/200] */
+ /* L0 : [1400/200/100][166/83][133/66][200/200] */
+ {0, 6, 6, 1, 3, 1, 4, 1, 3, 0, 0},
+
+ /* L1 : [1200/200/100][166/83][133/66][200/200] */
+ {0, 5, 5, 1, 3, 1, 4, 1, 3, 0, 0},
+
+ /* L2 : [1000/200/100][166/83][133/66][200/200] */
{0, 4, 4, 1, 3, 1, 4, 1, 3, 0, 0},
- /* L1 : [800/200/100][166/83][133/66][200/200] */
+ /* L3 : [800/200/100][166/83][133/66][200/200] */
{0, 3, 3, 1, 3, 1, 4, 1, 3, 0, 0},
- /* L2 : [400/200/100][166/83][133/66][200/200] */
+ /* L4 : [400/200/100][166/83][133/66][200/200] */
{1, 3, 1, 1, 3, 1, 4, 1, 3, 0, 0},
- /* L3 : [200/200/100][166/83][133/66][200/200] */
+ /* L5 : [200/200/100][166/83][133/66][200/200] */
{3, 3, 1, 1, 3, 1, 4, 1, 3, 0, 0},
- /* L4 : [100/100/100][83/83][66/66][100/100] */
+ /* L6 : [100/100/100][83/83][66/66][100/100] */
{7, 7, 0, 0, 7, 0, 9, 0, 7, 0, 0},
};
@@ -143,39 +244,82 @@ static int s5pv210_target(struct cpufreq_policy *policy,
unsigned int relation)
{
unsigned long reg;
- unsigned int index, priv_index;
+ unsigned int index;
unsigned int pll_changing = 0;
unsigned int bus_speed_changing = 0;
+ unsigned int arm_volt, int_volt;
+ int ret = 0;
+
+ mutex_lock(&set_freq_lock);
+
+ if (relation & ENABLE_FURTHER_CPUFREQ)
+ no_cpufreq_access = false;
+
+#ifdef CONFIG_CPU_DIDLE
+ // Ensures no application decreases the min freq when deepidle enabled at
+ // suspend mement
+ if (deepidle_is_enabled()) {
+ if (uIsSuspended == 1) {
+ if (policy->max != 800000) {
+ policy->user_policy.max = 800000;
+ policy->max = 800000;
+ }
+ }
+ }
+#endif
+
+ if (no_cpufreq_access) {
+#ifdef CONFIG_PM_VERBOSE
+ pr_err("%s:%d denied access to %s as it is disabled"
+ "temporarily\n", __FILE__, __LINE__, __func__);
+#endif
+ ret = -EINVAL;
+ goto out;
+ }
+ if (relation & DISABLE_FURTHER_CPUFREQ)
+ no_cpufreq_access = true;
+ relation &= ~(ENABLE_FURTHER_CPUFREQ | DISABLE_FURTHER_CPUFREQ);
freqs.old = s5pv210_getspeed(0);
if (cpufreq_frequency_table_target(policy, s5pv210_freq_table,
- target_freq, relation, &index))
- return -EINVAL;
+ target_freq, relation, &index)) {
+ ret = -EINVAL;
+ goto out;
+ }
freqs.new = s5pv210_freq_table[index].frequency;
freqs.cpu = 0;
if (freqs.new == freqs.old)
- return 0;
+ goto out;
- /* Finding current running level index */
- if (cpufreq_frequency_table_target(policy, s5pv210_freq_table,
- freqs.old, relation, &priv_index))
- return -EINVAL;
-
- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+ arm_volt = dvs_conf[index].arm_volt;
+ int_volt = dvs_conf[index].int_volt;
if (freqs.new > freqs.old) {
- /* Voltage up: will be implemented */
+ /* Voltage up code: increase ARM first */
+ if (!IS_ERR_OR_NULL(arm_regulator) &&
+ !IS_ERR_OR_NULL(internal_regulator)) {
+ ret = regulator_set_voltage(arm_regulator,
+ arm_volt, arm_volt_max);
+ if (ret)
+ goto out;
+ ret = regulator_set_voltage(internal_regulator,
+ int_volt, int_volt_max);
+ if (ret)
+ goto out;
+ }
}
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
/* Check if there need to change PLL */
- if ((index == L0) || (priv_index == L0))
+ if ((index <= L_1000) || (freqs.old >= s5pv210_freq_table[L_1000].frequency))
pll_changing = 1;
/* Check if there need to change System bus clock */
- if ((index == L4) || (priv_index == L4))
+ if ((index == L_100) || (freqs.old == s5pv210_freq_table[L_100].frequency))
bus_speed_changing = 1;
if (bus_speed_changing) {
@@ -229,7 +373,7 @@ static int s5pv210_target(struct cpufreq_policy *policy,
} while (reg & ((1 << 7) | (1 << 3)));
/*
- * 3. DMC1 refresh count for 133Mhz if (index == L4) is
+ * 3. DMC1 refresh count for 133Mhz if (index == L_100) is
* true refresh counter is already programed in upper
* code. 0x287@83Mhz
*/
@@ -274,7 +418,7 @@ static int s5pv210_target(struct cpufreq_policy *policy,
/* ARM MCS value changed */
reg = __raw_readl(S5P_ARM_MCS_CON);
reg &= ~0x3;
- if (index >= L3)
+ if (index >= L_200)
reg |= 0x3;
else
reg |= 0x1;
@@ -290,10 +434,7 @@ static int s5pv210_target(struct cpufreq_policy *policy,
* 6-1. Set PMS values
* 6-2. Wait untile the PLL is locked
*/
- if (index == L0)
- __raw_writel(APLL_VAL_1000, S5P_APLL_CON);
- else
- __raw_writel(APLL_VAL_800, S5P_APLL_CON);
+ __raw_writel(sAPLL_confs[index], S5P_APLL_CON);
do {
reg = __raw_readl(S5P_APLL_CON);
@@ -341,7 +482,7 @@ static int s5pv210_target(struct cpufreq_policy *policy,
/*
* 10. DMC1 refresh counter
- * L4 : DMC1 = 100Mhz 7.8us/(1/100) = 0x30c
+ * L_100 : DMC1 = 100Mhz 7.8us/(1/100) = 0x30c
* Others : DMC1 = 200Mhz 7.8us/(1/200) = 0x618
*/
if (!bus_speed_changing)
@@ -349,7 +490,7 @@ static int s5pv210_target(struct cpufreq_policy *policy,
}
/*
- * L4 level need to change memory bus speed, hence onedram clock divier
+ * L_100 level need to change memory bus speed, hence onedram clock divier
* and memory refresh parameter should be changed
*/
if (bus_speed_changing) {
@@ -363,7 +504,7 @@ static int s5pv210_target(struct cpufreq_policy *policy,
} while (reg & (1 << 15));
/* Reconfigure DRAM refresh counter value */
- if (index != L4) {
+ if (index != L_100) {
/*
* DMC0 : 166Mhz
* DMC1 : 200Mhz
@@ -380,15 +521,23 @@ static int s5pv210_target(struct cpufreq_policy *policy,
}
}
- if (freqs.new < freqs.old) {
- /* Voltage down: will be implemented */
- }
-
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
- printk(KERN_DEBUG "Perf changed[L%d]\n", index);
+ if (freqs.new < freqs.old) {
+ /* Voltage down: decrease INT first */
+ if (!IS_ERR_OR_NULL(arm_regulator) &&
+ !IS_ERR_OR_NULL(internal_regulator)) {
+ regulator_set_voltage(internal_regulator,
+ int_volt, int_volt_max);
+ regulator_set_voltage(arm_regulator,
+ arm_volt, arm_volt_max);
+ }
+ }
- return 0;
+ pr_debug("Perf changed[L%d]\n", index);
+out:
+ mutex_unlock(&set_freq_lock);
+ return ret;
}
#ifdef CONFIG_PM
@@ -417,6 +566,8 @@ static int __init s5pv210_cpu_init(struct cpufreq_policy *policy)
{
unsigned long mem_type;
+ int ret;
+
cpu_clk = clk_get(NULL, "armclk");
if (IS_ERR(cpu_clk))
return PTR_ERR(cpu_clk);
@@ -461,9 +612,54 @@ static int __init s5pv210_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.transition_latency = 40000;
- return cpufreq_frequency_table_cpuinfo(policy, s5pv210_freq_table);
+ ret = cpufreq_frequency_table_cpuinfo(policy, s5pv210_freq_table);
+
+ if (!ret)
+ policy->max = 1000000;
+
+ return ret;
+}
+
+static int s5pv210_cpufreq_notifier_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ int ret;
+
+ switch (event) {
+ case PM_SUSPEND_PREPARE:
+ ret = cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ,
+ DISABLE_FURTHER_CPUFREQ);
+ if (ret < 0)
+ return NOTIFY_BAD;
+ return NOTIFY_OK;
+ case PM_POST_RESTORE:
+ case PM_POST_SUSPEND:
+ cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ,
+ ENABLE_FURTHER_CPUFREQ);
+ return NOTIFY_OK;
+ }
+ return NOTIFY_DONE;
}
+static int s5pv210_cpufreq_reboot_notifier_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ int ret = 0;
+
+ ret = cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ,
+ DISABLE_FURTHER_CPUFREQ);
+
+ if (ret < 0)
+ return NOTIFY_BAD;
+
+ return NOTIFY_DONE;
+}
+
+static struct freq_attr *s5pv210_cpufreq_attr[] = {
+ &cpufreq_freq_attr_scaling_available_freqs,
+ NULL,
+};
+
static struct cpufreq_driver s5pv210_driver = {
.flags = CPUFREQ_STICKY,
.verify = s5pv210_verify_speed,
@@ -471,15 +667,78 @@ static struct cpufreq_driver s5pv210_driver = {
.get = s5pv210_getspeed,
.init = s5pv210_cpu_init,
.name = "s5pv210",
+ .attr = s5pv210_cpufreq_attr,
#ifdef CONFIG_PM
.suspend = s5pv210_cpufreq_suspend,
.resume = s5pv210_cpufreq_resume,
#endif
};
-static int __init s5pv210_cpufreq_init(void)
+static struct notifier_block s5pv210_cpufreq_notifier = {
+ .notifier_call = s5pv210_cpufreq_notifier_event,
+};
+
+static struct notifier_block s5pv210_cpufreq_reboot_notifier = {
+ .notifier_call = s5pv210_cpufreq_reboot_notifier_event,
+};
+
+static int __init s5pv210_cpufreq_probe(struct platform_device *pdev)
{
+ struct s5pv210_cpufreq_data *pdata = dev_get_platdata(&pdev->dev);
+ int i, j;
+
+ if (pdata && pdata->size) {
+ for (i = 0; i < pdata->size; i++) {
+ j = 0;
+ while (s5pv210_freq_table[j].frequency != CPUFREQ_TABLE_END) {
+ if (s5pv210_freq_table[j].frequency == pdata->volt[i].freq) {
+ dvs_conf[j].arm_volt = pdata->volt[i].varm;
+ dvs_conf[j].int_volt = pdata->volt[i].vint;
+ break;
+ }
+ j++;
+ }
+ }
+ }
+
+ arm_regulator = regulator_get(NULL, "vddarm");
+ if (IS_ERR(arm_regulator)) {
+ pr_err("failed to get regulater resource vddarm\n");
+ goto error;
+ }
+ internal_regulator = regulator_get(NULL, "vddint");
+ if (IS_ERR(internal_regulator)) {
+ pr_err("failed to get regulater resource vddint\n");
+ goto error;
+ }
+ goto finish;
+error:
+ pr_warn("Cannot get vddarm or vddint. CPUFREQ Will not"
+ " change the voltage.\n");
+finish:
+ register_pm_notifier(&s5pv210_cpufreq_notifier);
+ register_reboot_notifier(&s5pv210_cpufreq_reboot_notifier);
+
return cpufreq_register_driver(&s5pv210_driver);
}
+static struct platform_driver s5pv210_cpufreq_drv = {
+ .probe = s5pv210_cpufreq_probe,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "s5pv210-cpufreq",
+ },
+};
+
+static int __init s5pv210_cpufreq_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&s5pv210_cpufreq_drv);
+ if (!ret)
+ pr_info("%s: S5PV210 cpu-freq driver\n", __func__);
+
+ return ret;
+}
+
late_initcall(s5pv210_cpufreq_init);
diff --git a/arch/arm/mach-s5pv210/cpuidle.c b/arch/arm/mach-s5pv210/cpuidle.c
new file mode 100644
index 0000000..742bcfa
--- /dev/null
+++ b/arch/arm/mach-s5pv210/cpuidle.c
@@ -0,0 +1,551 @@
+/*
+ * arch/arm/mach-s5pv210/cpuidle.c
+ *
+ * Copyright (c) Samsung Electronics Co. Ltd
+ * (c) 2011 Ezekeel <notezekeel@googlemail.com>
+ *
+ * CPU idle driver for S5PV210
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/cpuidle.h>
+#include <linux/io.h>
+#include <asm/proc-fns.h>
+#include <asm/cacheflush.h>
+
+#include <mach/map.h>
+#include <mach/regs-irq.h>
+#include <mach/regs-clock.h>
+#include <mach/regs-gpio.h>
+#include <plat/pm.h>
+#include <plat/devs.h>
+
+#ifdef CONFIG_CPU_DIDLE
+#include <linux/dma-mapping.h>
+#include <linux/deep_idle.h>
+
+#include <plat/regs-otg.h>
+#include <mach/cpuidle.h>
+#include <mach/power-domain.h>
+
+extern bool suspend_ongoing(void);
+extern bool bt_is_running(void);
+extern bool gps_is_running(void);
+extern bool vibrator_is_running(void);
+
+/*
+ * For saving & restoring VIC register before entering
+ * didle mode
+ */
+static unsigned long vic_regs[4];
+static unsigned long *regs_save;
+static dma_addr_t phy_regs_save;
+
+#define MAX_CHK_DEV 0xf
+
+/*
+ * Specific device list for checking before entering
+ * didle mode
+ */
+struct check_device_op {
+ void __iomem *base;
+ struct platform_device *pdev;
+};
+
+/* Array of checking devices list */
+static struct check_device_op chk_dev_op[] = {
+#if defined(CONFIG_S3C_DEV_HSMMC)
+ {.base = 0, .pdev = &s3c_device_hsmmc0},
+#endif
+#if defined(CONFIG_S3C_DEV_HSMMC1)
+ {.base = 0, .pdev = &s3c_device_hsmmc1},
+#endif
+#if 0
+ {.base = 0, .pdev = &s3c_device_hsmmc2},
+#endif
+#if defined(CONFIG_S3C_DEV_HSMMC3)
+ {.base = 0, .pdev = &s3c_device_hsmmc3},
+#endif
+ {.base = 0, .pdev = NULL},
+};
+
+#define S3C_HSMMC_PRNSTS (0x24)
+#define S3C_HSMMC_CLKCON (0x2c)
+#define S3C_HSMMC_CMD_INHIBIT 0x00000001
+#define S3C_HSMMC_DATA_INHIBIT 0x00000002
+#define S3C_HSMMC_CLOCK_CARD_EN 0x0004
+
+static int sdmmc_dev_num;
+/* If SD/MMC interface is working: return = 1 or not 0 */
+static int check_sdmmc_op(unsigned int ch)
+{
+ unsigned int reg1, reg2;
+ void __iomem *base_addr;
+
+ if (unlikely(ch > sdmmc_dev_num)) {
+ printk(KERN_ERR "Invalid ch[%d] for SD/MMC\n", ch);
+ return 0;
+ }
+
+ base_addr = chk_dev_op[ch].base;
+ /* Check CMDINHDAT[1] and CMDINHCMD [0] */
+ reg1 = readl(base_addr + S3C_HSMMC_PRNSTS);
+ /* Check CLKCON [2]: ENSDCLK */
+ reg2 = readl(base_addr + S3C_HSMMC_CLKCON);
+
+ return !!(reg1 & (S3C_HSMMC_CMD_INHIBIT | S3C_HSMMC_DATA_INHIBIT)) ||
+ (reg2 & (S3C_HSMMC_CLOCK_CARD_EN));
+}
+
+/* Check all sdmmc controller */
+static int loop_sdmmc_check(void)
+{
+ unsigned int iter;
+
+ for (iter = 0; iter < sdmmc_dev_num + 1; iter++) {
+ if (check_sdmmc_op(iter))
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Check USBOTG is working or not
+ * GOTGCTL(0xEC000000)
+ * BSesVld (Indicates the Device mode transceiver status)
+ * BSesVld = 1b : B-session is valid
+ * 0b : B-session is not valid
+ */
+static int check_usbotg_op(void)
+{
+ unsigned int val;
+
+ val = __raw_readl(S3C_UDC_OTG_GOTGCTL);
+
+ return val & (B_SESSION_VALID);
+}
+
+/*
+ * Check power gating : LCD, CAM, TV, MFC, G3D
+ * Check clock gating : DMA, USBHOST, I2C
+ */
+extern volatile int s5p_rp_is_running;
+extern int s5p_rp_get_op_level(void);
+
+static int check_power_clock_gating(void)
+{
+ unsigned long val;
+
+ /* check power gating */
+ val = __raw_readl(S5P_NORMAL_CFG);
+ if (val & (S5PV210_PD_LCD | S5PV210_PD_CAM | S5PV210_PD_TV
+ | S5PV210_PD_MFC | S5PV210_PD_G3D))
+ return 1;
+
+#ifdef CONFIG_SND_S5P_RP
+ if (s5p_rp_get_op_level())
+ return 1;
+#endif
+ /* check clock gating */
+ val = __raw_readl(S5P_CLKGATE_IP0);
+ if (val & (S5P_CLKGATE_IP0_MDMA | S5P_CLKGATE_IP0_PDMA0
+ | S5P_CLKGATE_IP0_PDMA1))
+ return 1;
+
+ val = __raw_readl(S5P_CLKGATE_IP1);
+ if (val & S5P_CLKGATE_IP1_USBHOST)
+ return 1;
+
+ val = __raw_readl(S5P_CLKGATE_IP3);
+ if (val & (S5P_CLKGATE_IP3_I2C0 | S5P_CLKGATE_IP3_I2C_HDMI_DDC
+ | S5P_CLKGATE_IP3_I2C2))
+ return 1;
+
+ return 0;
+}
+
+/*
+ * Skipping enter the didle mode when RTC & I2S interrupts be issued
+ * during critical section of entering didle mode (around 20ms).
+ */
+#ifdef CONFIG_S5P_INTERNAL_DMA
+static int check_idmapos(void)
+{
+ dma_addr_t src;
+
+ i2sdma_getpos(&src);
+ src = src & 0x3FFF;
+ src = 0x4000 - src;
+
+ return src < 0x150;
+}
+#endif
+
+static int check_rtcint(void)
+{
+ unsigned int current_cnt = get_rtc_cnt();
+
+ return current_cnt < 0x40;
+}
+
+/*
+ * Before entering, didle mode GPIO Powe Down Mode
+ * Configuration register has to be set with same state
+ * in Normal Mode
+ */
+#define GPIO_OFFSET 0x20
+#define GPIO_CON_PDN_OFFSET 0x10
+#define GPIO_PUD_PDN_OFFSET 0x14
+#define GPIO_PUD_OFFSET 0x08
+
+static unsigned int pud_pdn[(S5PV210_MP28_BASE - S5PV210_GPA0_BASE) / GPIO_OFFSET + 1];
+static unsigned int con_pdn[(S5PV210_MP28_BASE - S5PV210_GPA0_BASE) / GPIO_OFFSET + 1];
+
+static void s5p_gpio_pdn_conf(void)
+{
+ void __iomem *gpio_base = S5PV210_GPA0_BASE;
+ unsigned int val;
+ int i = 0;
+
+ do {
+ /* Save power down control state */
+ con_pdn[i] = __raw_readl(gpio_base + GPIO_CON_PDN_OFFSET);
+ /* Keep the previous state in didle mode */
+ __raw_writel(0xffff, gpio_base + GPIO_CON_PDN_OFFSET);
+
+ /* Save power down pull up-down state */
+ pud_pdn[i] = __raw_readl(gpio_base + GPIO_PUD_PDN_OFFSET);
+ /* Pull up-down state in didle is same as normal */
+ val = __raw_readl(gpio_base + GPIO_PUD_OFFSET);
+ __raw_writel(val, gpio_base + GPIO_PUD_PDN_OFFSET);
+
+ gpio_base += GPIO_OFFSET;
+ i++;
+
+ } while (gpio_base <= S5PV210_MP28_BASE);
+
+ return;
+}
+
+static void s5p_gpio_restore_conf(void)
+{
+ void __iomem *gpio_base = S5PV210_GPA0_BASE;
+ int i = 0;
+
+ do {
+ /* Restore power down control state */
+ __raw_writel(con_pdn[i], gpio_base + GPIO_CON_PDN_OFFSET);
+
+ /* Restore power down pull up-down state */
+ __raw_writel(pud_pdn[i], gpio_base + GPIO_PUD_PDN_OFFSET);
+
+ gpio_base += GPIO_OFFSET;
+ i++;
+
+ } while (gpio_base <= S5PV210_MP28_BASE);
+
+ return;
+}
+
+static void s5p_enter_didle(bool top_on)
+{
+ unsigned long tmp;
+ unsigned long save_eint_mask;
+
+ /* store the physical address of the register recovery block */
+ __raw_writel(phy_regs_save, S5P_INFORM2);
+
+ /* ensure at least INFORM0 has the resume address */
+ __raw_writel(virt_to_phys(s5pv210_didle_resume), S5P_INFORM0);
+
+ /* Save current VIC_INT_ENABLE register*/
+ vic_regs[0] = __raw_readl(S5P_VIC0REG(VIC_INT_ENABLE));
+ vic_regs[1] = __raw_readl(S5P_VIC1REG(VIC_INT_ENABLE));
+ vic_regs[2] = __raw_readl(S5P_VIC2REG(VIC_INT_ENABLE));
+ vic_regs[3] = __raw_readl(S5P_VIC3REG(VIC_INT_ENABLE));
+
+ /* Disable all interrupt through VIC */
+ __raw_writel(0xffffffff, S5P_VIC0REG(VIC_INT_ENABLE_CLEAR));
+ __raw_writel(0xffffffff, S5P_VIC1REG(VIC_INT_ENABLE_CLEAR));
+ __raw_writel(0xffffffff, S5P_VIC2REG(VIC_INT_ENABLE_CLEAR));
+ __raw_writel(0xffffffff, S5P_VIC3REG(VIC_INT_ENABLE_CLEAR));
+
+ if (!top_on) {
+ /* GPIO Power Down Control */
+ s5p_gpio_pdn_conf();
+ }
+
+ /*
+ * Configure external interrupt wakeup mask
+ * We use the same wakeup mask as for sleep state plus make sure
+ * that at least XEINT[22] = GPH2[6] = GPIO_nPOWER = GPIO_N_POWER
+ * and XEINT[29] = GPH3[5] = GPIO_OK_KEY are enabled
+ */
+ save_eint_mask = __raw_readl(S5P_EINT_WAKEUP_MASK);
+ tmp = s3c_irqwake_eintmask;
+ tmp &= ~((1<<22) | (1<<29));
+ __raw_writel(tmp, S5P_EINT_WAKEUP_MASK);
+
+ /* Clear wakeup status register */
+ tmp = __raw_readl(S5P_WAKEUP_STAT);
+ __raw_writel(tmp, S5P_WAKEUP_STAT);
+
+ /*
+ * Wakeup source configuration for didle
+ * We use the same wakeup mask as for sleep state plus make
+ * sure that at least RTC ALARM, RTC TICK, KEY, I2S and ST are
+ * enabled as wakeup sources
+ */
+ tmp = s3c_irqwake_intmask;
+ tmp &= ~((1<<1) | (1<<2) | (1<<5) | (1<<13) | (1<<14));
+ __raw_writel(tmp, S5P_WAKEUP_MASK);
+
+ tmp = __raw_readl(S5P_IDLE_CFG);
+ tmp &= ~(0x3fU << 26);
+ if (top_on) {
+ /*
+ * IDLE config register set
+ * TOP_LOGIC = ON
+ * TOP_MEMORY = ON
+ * ARM_L2CACHE = Retention
+ * CFG_DIDLE = DEEP
+ */
+ tmp |= ((2<<30) | (2<<28) | (1<<26) | (1<<0));
+ } else {
+ /*
+ * IDLE config register set
+ * TOP_LOGIC = Retention
+ * TOP_MEMORY = Retention
+ * ARM_L2CACHE = Retention
+ * CFG_DIDLE = DEEP
+ */
+ tmp |= ((1<<30) | (1<<28) | (1<<26) | (1<<0));
+ }
+ __raw_writel(tmp, S5P_IDLE_CFG);
+
+ /* Power mode Config setting */
+ tmp = __raw_readl(S5P_PWR_CFG);
+ tmp &= S5P_CFG_WFI_CLEAN;
+ tmp |= S5P_CFG_WFI_IDLE;
+ __raw_writel(tmp, S5P_PWR_CFG);
+
+ /* To check VIC Status register before enter didle mode */
+ if ((__raw_readl(S5P_VIC0REG(VIC_RAW_STATUS)) & vic_regs[0]) |
+ (__raw_readl(S5P_VIC1REG(VIC_RAW_STATUS)) & vic_regs[1]) |
+ (__raw_readl(S5P_VIC2REG(VIC_RAW_STATUS)) & vic_regs[2]) |
+ (__raw_readl(S5P_VIC3REG(VIC_RAW_STATUS)) & vic_regs[3]))
+ goto skipped_didle;
+
+ /* SYSCON_INT_DISABLE */
+ tmp = __raw_readl(S5P_OTHERS);
+ tmp |= S5P_OTHER_SYSC_INTOFF;
+ __raw_writel(tmp, S5P_OTHERS);
+
+ /*
+ * s5pv210_didle_save will also act as our return point from when
+ * we resume as it saves its own register state and restore it
+ * during the resume.
+ */
+ s5pv210_didle_save(regs_save);
+
+ /* restore the cpu state using the kernel's cpu init code. */
+ cpu_init();
+
+skipped_didle:
+ __raw_writel(save_eint_mask, S5P_EINT_WAKEUP_MASK);
+
+ tmp = __raw_readl(S5P_IDLE_CFG);
+ tmp &= ~((3<<30) | (3<<28) | (3<<26) | (1<<0));
+ tmp |= ((2<<30) | (2<<28));
+ __raw_writel(tmp, S5P_IDLE_CFG);
+
+ /* Power mode Config setting */
+ tmp = __raw_readl(S5P_PWR_CFG);
+ tmp &= S5P_CFG_WFI_CLEAN;
+ __raw_writel(tmp, S5P_PWR_CFG);
+
+ if (!top_on) {
+ /* Release retention GPIO/CF/MMC/UART IO */
+ tmp = __raw_readl(S5P_OTHERS);
+ tmp |= (S5P_OTHERS_RET_IO | S5P_OTHERS_RET_CF | \
+ S5P_OTHERS_RET_MMC | S5P_OTHERS_RET_UART);
+ __raw_writel(tmp, S5P_OTHERS);
+ }
+
+ if (!top_on) {
+ /* Restore GPIO Power Down Configuration */
+ s5p_gpio_restore_conf();
+ }
+
+ __raw_writel(vic_regs[0], S5P_VIC0REG(VIC_INT_ENABLE));
+ __raw_writel(vic_regs[1], S5P_VIC1REG(VIC_INT_ENABLE));
+ __raw_writel(vic_regs[2], S5P_VIC2REG(VIC_INT_ENABLE));
+ __raw_writel(vic_regs[3], S5P_VIC3REG(VIC_INT_ENABLE));
+}
+#endif
+
+static void s5p_enter_idle(void)
+{
+ unsigned long tmp;
+
+ tmp = __raw_readl(S5P_IDLE_CFG);
+ tmp &= ~((3U<<30)|(3<<28)|(1<<0));
+ tmp |= ((2U<<30)|(2<<28));
+ __raw_writel(tmp, S5P_IDLE_CFG);
+
+ tmp = __raw_readl(S5P_PWR_CFG);
+ tmp &= S5P_CFG_WFI_CLEAN;
+ __raw_writel(tmp, S5P_PWR_CFG);
+
+ cpu_do_idle();
+}
+
+/* Actual code that puts the SoC in different idle states */
+static int s5p_enter_idle_state(struct cpuidle_device *dev,
+ struct cpuidle_state *state)
+{
+ struct timeval before, after;
+ int idle_time;
+#ifdef CONFIG_CPU_DIDLE
+ int idle_state = 0;
+#endif
+
+ local_irq_disable();
+ do_gettimeofday(&before);
+
+#ifdef CONFIG_CPU_DIDLE
+#ifdef CONFIG_S5P_INTERNAL_DMA
+ if (!deepidle_is_enabled() || check_power_clock_gating() || suspend_ongoing() || loop_sdmmc_check() || check_usbotg_op() || check_rtcint() || check_idmapos()) {
+#else
+ if (!deepidle_is_enabled() || check_power_clock_gating() || suspend_ongoing() || loop_sdmmc_check() || check_usbotg_op() || check_rtcint()) {
+#endif
+ s5p_enter_idle();
+ } else if (bt_is_running() || gps_is_running() || vibrator_is_running()) {
+ s5p_enter_didle(true);
+ idle_state = 1;
+ } else {
+ s5p_enter_didle(false);
+ idle_state = 2;
+ }
+#else
+ s5p_enter_idle();
+#endif
+
+ do_gettimeofday(&after);
+ local_irq_enable();
+ idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
+ (after.tv_usec - before.tv_usec);
+#ifdef CONFIG_CPU_DIDLE
+ report_idle_time(idle_state, idle_time);
+#endif
+ return idle_time;
+}
+
+static DEFINE_PER_CPU(struct cpuidle_device, s5p_cpuidle_device);
+
+static struct cpuidle_driver s5p_idle_driver = {
+ .name = "s5p_idle",
+ .owner = THIS_MODULE,
+};
+
+/* Initialize CPU idle by registering the idle states */
+static int s5p_init_cpuidle(void)
+{
+ struct cpuidle_device *device;
+ int ret;
+
+#ifdef CONFIG_CPU_DIDLE
+ struct resource *res;
+ struct platform_device *pdev;
+ int i = 0;
+#endif
+
+ ret = cpuidle_register_driver(&s5p_idle_driver);
+ if (ret) {
+ printk(KERN_ERR "%s: Failed registering driver\n", __func__);
+ goto err;
+ }
+
+ device = &per_cpu(s5p_cpuidle_device, smp_processor_id());
+ device->state_count = 1;
+
+ /* Wait for interrupt state */
+ device->states[0].enter = s5p_enter_idle_state;
+ device->states[0].exit_latency = 1; /* uS */
+ device->states[0].target_residency = 10000;
+ device->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
+#ifdef CONFIG_CPU_DIDLE
+ strcpy(device->states[0].name, "(DEEP)IDLE");
+ strcpy(device->states[0].desc, "ARM clock/power gating - WFI");
+#else
+ strcpy(device->states[0].name, "IDLE");
+ strcpy(device->states[0].desc, "ARM clock gating - WFI");
+#endif
+
+ ret = cpuidle_register_device(device);
+ if (ret) {
+ printk(KERN_ERR "%s: Failed registering device\n", __func__);
+ goto err_register_driver;
+ }
+
+#ifdef CONFIG_CPU_DIDLE
+ regs_save = dma_alloc_coherent(NULL, 4096, &phy_regs_save, GFP_KERNEL);
+ if (regs_save == NULL) {
+ printk(KERN_ERR "%s: DMA alloc error\n", __func__);
+ ret = -ENOMEM;
+ goto err_register_device;
+ }
+ printk(KERN_INFO "cpuidle: phy_regs_save:0x%x\n", phy_regs_save);
+
+ /* Allocate memory region to access IP's directly */
+ for (i = 0 ; i < MAX_CHK_DEV ; i++) {
+
+ pdev = chk_dev_op[i].pdev;
+
+ if (pdev == NULL) {
+ sdmmc_dev_num = i - 1;
+ break;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ printk(KERN_ERR "%s: failed to get io memory region\n",
+ __func__);
+ ret = -EINVAL;
+ goto err_alloc;
+ }
+ chk_dev_op[i].base = ioremap_nocache(res->start, 4096);
+
+ if (!chk_dev_op[i].base) {
+ printk(KERN_ERR "failed to remap io region\n");
+ ret = -EINVAL;
+ goto err_resource;
+ }
+ }
+#endif
+
+ return 0;
+
+#ifdef CONFIG_CPU_DIDLE
+err_alloc:
+ while (--i >= 0) {
+ iounmap(chk_dev_op[i].base);
+ }
+err_resource:
+ dma_free_coherent(NULL, 4096, regs_save, phy_regs_save);
+err_register_device:
+ cpuidle_unregister_device(device);
+#endif
+err_register_driver:
+ cpuidle_unregister_driver(&s5p_idle_driver);
+err:
+ return ret;
+}
+
+device_initcall(s5p_init_cpuidle);
diff --git a/arch/arm/mach-s5pv210/dev-audio.c b/arch/arm/mach-s5pv210/dev-audio.c
index 8d58f19..c6109b1 100644
--- a/arch/arm/mach-s5pv210/dev-audio.c
+++ b/arch/arm/mach-s5pv210/dev-audio.c
@@ -80,8 +80,8 @@ static struct resource s5pv210_iis0_resource[] = {
};
struct platform_device s5pv210_device_iis0 = {
- .name = "samsung-i2s",
- .id = 0,
+ .name = "samsung-i2s",
+ .id = 0,
.num_resources = ARRAY_SIZE(s5pv210_iis0_resource),
.resource = s5pv210_iis0_resource,
.dev = {
diff --git a/arch/arm/mach-s5pv210/dev-cpufreq.c b/arch/arm/mach-s5pv210/dev-cpufreq.c
new file mode 100644
index 0000000..ff0e0f1
--- /dev/null
+++ b/arch/arm/mach-s5pv210/dev-cpufreq.c
@@ -0,0 +1,28 @@
+/*
+ * linux/arch/arm/mach-s5pv210/dev-cpufreq.c
+ *
+ * Copyright (c) 2008-2010 Samsung Electronics
+ * Taekki Kim <taekki.kim@samsung.com>
+ *
+ * S5PV210 series device definition for cpufreq devices
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+#include <mach/cpu-freq-v210.h>
+
+struct platform_device s5pv210_device_cpufreq = {
+ .name = "s5pv210-cpufreq",
+ .id = -1,
+};
+
+void s5pv210_cpufreq_set_platdata(struct s5pv210_cpufreq_data *pdata)
+{
+ s5pv210_device_cpufreq.dev.platform_data = pdata;
+}
+
diff --git a/arch/arm/mach-s5pv210/dev-fiqdbg.c b/arch/arm/mach-s5pv210/dev-fiqdbg.c
new file mode 100644
index 0000000..16ef49b
--- /dev/null
+++ b/arch/arm/mach-s5pv210/dev-fiqdbg.c
@@ -0,0 +1,161 @@
+/* linux/arch/arm/mach-s5pv210/dev-fiqdbg.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/irq.h>
+#include <linux/sysdev.h>
+
+#include <asm/hardware/vic.h>
+#include <asm/fiq_debugger.h>
+
+#include <mach/irqs.h>
+#include <mach/map.h>
+#include <plat/regs-serial.h>
+
+static void *s5pv210_fiqdbg_get_base(struct platform_device *pdev)
+{
+ return S5P_VA_UART0 + S3C_UART_OFFSET * pdev->id;
+}
+
+static unsigned int s5pv210_fiqdbg_tx_empty(void *base)
+{
+ unsigned long ufstat = readl(base + S3C2410_UFSTAT);
+
+ return !(ufstat & (S5PV210_UFSTAT_TXMASK | S5PV210_UFSTAT_TXFULL));
+}
+
+static void s5pv210_fiqdbg_wait_for_tx_empty(void *base)
+{
+ unsigned int tmout = 10000;
+
+ while (true) {
+ if (s5pv210_fiqdbg_tx_empty(base))
+ return;
+ if (--tmout == 0)
+ break;
+ udelay(1);
+ }
+}
+
+static int s5pv210_fiqdbg_uart_getc(struct platform_device *pdev)
+{
+ void *base = s5pv210_fiqdbg_get_base(pdev);
+ unsigned int ufstat;
+
+ if (readl(base + S3C2410_UERSTAT) & S3C2410_UERSTAT_BREAK)
+ return FIQ_DEBUGGER_BREAK;
+
+ ufstat = readl(base + S3C2410_UFSTAT);
+ if (!(ufstat & (S5PV210_UFSTAT_RXMASK | S5PV210_UFSTAT_RXFULL)))
+ return FIQ_DEBUGGER_NO_CHAR;
+ return readb(base + S3C2410_URXH);
+}
+
+static void s5pv210_fiqdbg_uart_putc(struct platform_device *pdev,
+ unsigned int c)
+{
+ void *base = s5pv210_fiqdbg_get_base(pdev);
+ s5pv210_fiqdbg_wait_for_tx_empty(base);
+ writeb(c, base + S3C2410_UTXH);
+ if (c == 10) {
+ s5pv210_fiqdbg_wait_for_tx_empty(base);
+ writeb(13, base + S3C2410_UTXH);
+ }
+ s5pv210_fiqdbg_wait_for_tx_empty(base);
+}
+
+static void fiq_enable(struct platform_device *pdev,
+ unsigned int fiq, bool enabled)
+{
+ struct irq_chip *chip = irq_get_chip(fiq);
+ struct irq_data *d = irq_get_irq_data(fiq);
+
+ vic_set_fiq(fiq, enabled);
+ if (enabled)
+ chip->irq_unmask(d);
+ else
+ chip->irq_mask(d);
+}
+
+static void fiq_ack(struct platform_device *pdev, unsigned int fiq)
+{
+ void *base = s5pv210_fiqdbg_get_base(pdev);
+ writel(0x3, base + S5P_UINTP);
+}
+
+static int s5pv210_fiqdbg_uart_init(struct platform_device *pdev)
+{
+ void *base = s5pv210_fiqdbg_get_base(pdev);
+
+ writel(S3C2410_UCON_TXILEVEL |
+ S3C2410_UCON_RXILEVEL |
+ S3C2410_UCON_TXIRQMODE |
+ S3C2410_UCON_RXIRQMODE |
+ S3C2410_UCON_RXFIFO_TOI |
+ S3C2443_UCON_RXERR_IRQEN, base + S3C2410_UCON);
+ writel(S3C2410_LCON_CS8, base + S3C2410_ULCON);
+ writel(S3C2410_UFCON_FIFOMODE |
+ S5PV210_UFCON_TXTRIG4 |
+ S5PV210_UFCON_RXTRIG4 |
+ S3C2410_UFCON_RESETRX, base + S3C2410_UFCON);
+ writel(0, base + S3C2410_UMCON);
+ /* 115200 */
+ writel(35, base + S3C2410_UBRDIV);
+ writel(0x808, base + S3C2443_DIVSLOT);
+ writel(0xc, base + S5P_UINTM);
+ writel(0xf, base + S5P_UINTP);
+
+ return 0;
+}
+
+static struct fiq_debugger_pdata s5pv210_fiqdbg_pdata = {
+ .uart_init = s5pv210_fiqdbg_uart_init,
+ .uart_resume = s5pv210_fiqdbg_uart_init,
+ .uart_getc = s5pv210_fiqdbg_uart_getc,
+ .uart_putc = s5pv210_fiqdbg_uart_putc,
+ .fiq_enable = fiq_enable,
+ .fiq_ack = fiq_ack,
+};
+
+#define DEFINE_FIQDBG_UART(uart) \
+static struct resource s5pv210_fiqdbg_uart##uart##_resource[] = { \
+ { \
+ .start = IRQ_UART##uart, \
+ .end = IRQ_UART##uart, \
+ .name = "fiq", \
+ .flags = IORESOURCE_IRQ, \
+ }, \
+ { \
+ .start = IRQ_VIC_END-uart, \
+ .end = IRQ_VIC_END-uart, \
+ .name = "signal", \
+ .flags = IORESOURCE_IRQ, \
+ }, \
+}; \
+struct platform_device s5pv210_device_fiqdbg_uart##uart = { \
+ .name = "fiq_debugger", \
+ .id = uart, \
+ .num_resources = ARRAY_SIZE(s5pv210_fiqdbg_uart##uart##_resource), \
+ .resource = s5pv210_fiqdbg_uart##uart##_resource, \
+ .dev = { \
+ .platform_data = &s5pv210_fiqdbg_pdata, \
+ }, \
+}
+
+DEFINE_FIQDBG_UART(0);
+DEFINE_FIQDBG_UART(1);
+DEFINE_FIQDBG_UART(2);
+DEFINE_FIQDBG_UART(3);
diff --git a/arch/arm/mach-s5pv210/dev-herring-phone.c b/arch/arm/mach-s5pv210/dev-herring-phone.c
new file mode 100755
index 0000000..b605e02
--- /dev/null
+++ b/arch/arm/mach-s5pv210/dev-herring-phone.c
@@ -0,0 +1,79 @@
+/* linux/arch/arm/mach-s5pv210/dev-herring-phone.c
+ * Copyright (C) 2010 Samsung Electronics. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+
+#include <mach/map.h>
+#include <mach/gpio.h>
+#include <mach/gpio-herring.h>
+
+#include "../../../drivers/misc/samsung_modemctl/modem_ctl.h"
+#include "herring.h"
+
+/* Modem control */
+static struct modemctl_data mdmctl_data = {
+ .name = "xmm",
+ .gpio_phone_active = GPIO_PHONE_ACTIVE,
+ .gpio_pda_active = GPIO_PDA_ACTIVE,
+ .gpio_cp_reset = GPIO_CP_RST,
+ .gpio_phone_on = GPIO_PHONE_ON,
+ .is_cdma_modem = 0,
+ .num_pdp_contexts = 3,
+};
+
+static struct resource mdmctl_res[] = {
+ [0] = {
+ .name = "active",
+ .start = IRQ_EINT15,
+ .end = IRQ_EINT15,
+ .flags = IORESOURCE_IRQ,
+ },
+ [1] = {
+ .name = "onedram",
+ .start = IRQ_EINT11,
+ .end = IRQ_EINT11,
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .name = "onedram",
+ .start = (S5PV210_PA_SDRAM + 0x05000000),
+ .end = (S5PV210_PA_SDRAM + 0x05000000 + SZ_16M - 1),
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device modemctl = {
+ .name = "modemctl",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(mdmctl_res),
+ .resource = mdmctl_res,
+ .dev = {
+ .platform_data = &mdmctl_data,
+ },
+};
+
+static int __init herring_init_phone_interface(void)
+{
+ /* CDMA device */
+ if (herring_is_cdma_wimax_dev()) {
+ mdmctl_data.is_cdma_modem = 1;
+ mdmctl_data.num_pdp_contexts = 1;
+ }
+
+ platform_device_register(&modemctl);
+ return 0;
+}
+device_initcall(herring_init_phone_interface);
diff --git a/arch/arm/mach-s5pv210/didle.S b/arch/arm/mach-s5pv210/didle.S
new file mode 100644
index 0000000..2abaca0
--- /dev/null
+++ b/arch/arm/mach-s5pv210/didle.S
@@ -0,0 +1,218 @@
+/* linux/arch/arm/mach-s5pv210/didle.S
+ *
+ * Copyright (c) 2010 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.
+ *
+ * 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/linkage.h>
+#include <asm/assembler.h>
+#include <mach/hardware.h>
+#include <mach/map.h>
+#include <asm/asm-offsets.h>
+#include <asm/memory.h>
+#include <asm/system.h>
+
+/*
+ * v7_flush_l1_dcache()
+ *
+ * Flush the L1 D-cache.
+ */
+ENTRY(v7_flush_l1_dcache)
+ dmb @ ensure ordering with previous memory accesses
+ mrc p15, 1, r0, c0, c0, 1 @ read clidr
+ ands r3, r0, #0x7000000 @ extract loc from clidr
+ mov r3, r3, lsr #23 @ left align loc bit field
+ beq finished @ if loc is 0, then no need to clean
+ mov r10, #0 @ start clean at cache level 0
+loop1:
+ add r2, r10, r10, lsr #1 @ work out 3x current cache level
+ mov r1, r0, lsr r2 @ extract cache type bits from clidr
+ and r1, r1, #7 @ mask of the bits for current cache only
+ cmp r1, #2 @ see what cache we have at this level
+ blt finished @ finish if no cache, or just i-cache
+ mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr
+ isb @ isb to sych the new cssr&csidr
+ mrc p15, 1, r1, c0, c0, 0 @ read the new csidr
+ and r2, r1, #7 @ extract the length of the cache lines
+ add r2, r2, #4 @ add 4 (line length offset)
+ ldr r4, =0x3ff
+ ands r4, r4, r1, lsr #3 @ find maximum number on the way size
+ clz r5, r4 @ find bit position of way size increment
+ ldr r7, =0x7fff
+ ands r7, r7, r1, lsr #13 @ extract max number of the index size
+loop2:
+ mov r9, r4 @ create working copy of max way size
+loop3:
+ orr r11, r10, r9, lsl r5 @ factor way and cache number into r11
+ orr r11, r11, r7, lsl r2 @ factor index number into r11
+ mcr p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way
+ subs r9, r9, #1 @ decrement the way
+ bge loop3
+ subs r7, r7, #1 @ decrement the index
+ bge loop2
+finished:
+ mov r10, #0 @ swith back to cache level 0
+ mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr
+ dsb
+ isb
+ mov pc, lr
+ENDPROC(v7_flush_l1_dcache)
+
+ENTRY(v7_flush_cache_for_didle)
+ stmfd sp!, {r4-r5, r7, r9-r11, lr}
+ bl v7_flush_l1_dcache
+ mov r0, #0
+ mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate
+ ldmfd sp!, {r4-r5, r7, r9-r11, lr}
+ mov pc, lr
+ENDPROC(v7_flush_cache_for_didle)
+
+ENTRY(s5pv210_didle)
+ stmfd sp!, {r4-r5, r7, r9-r11, lr}
+
+ bl v7_flush_cache_for_didle
+
+ ldmfd sp!, {r4-r5, r7, r9-r11, lr}
+ dmb
+ dsb
+ wfi
+
+ b .
+
+ .text
+
+ /* s5pv210_didle_save
+ *
+ * entry:
+ * r0 = save address (virtual addr of s3c_sleep_save_phys)
+ */
+
+ENTRY(s5pv210_didle_save)
+
+ stmfd sp!, { r3 - r12, lr }
+
+ mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID
+ mrc p15, 0, r5, c3, c0, 0 @ Domain ID
+ mrc p15, 0, r6, c2, c0, 0 @ Translation Table BASE0
+ mrc p15, 0, r7, c2, c0, 1 @ Translation Table BASE1
+ mrc p15, 0, r8, c2, c0, 2 @ Translation Table Control
+ mrc p15, 0, r9, c1, c0, 0 @ Control register
+ mrc p15, 0, r10, c1, c0, 1 @ Auxiliary control register
+ mrc p15, 0, r11, c1, c0, 2 @ Co-processor access controls
+ mrc p15, 0, r12, c10, c2, 0 @ Read PRRR
+ mrc p15, 0, r3, c10, c2, 1 @ READ NMRR
+
+ /* Save CP15 registers */
+ stmia r0, { r3 - r13 }
+
+ bl s5pv210_didle
+
+ @@ return to the caller, after having the MMU
+ @@ turned on, this restores the last bits from the
+ @@ stack
+resume_with_mmu:
+ mrc p15, 0, r0, c1, c0, 1 @enable L2 cache
+ orr r0, r0, #(1<<1)
+ mcr p15, 0, r0, c1, c0, 1
+
+ mov r0, #1
+ /* delete added mmu table list */
+ ldr r9 , =(PAGE_OFFSET - PLAT_PHYS_OFFSET)
+ add r4, r4, r9
+ str r12, [r4]
+
+ ldmfd sp!, { r3 - r12, pc }
+
+ .ltorg
+
+ /* s5pv210_didle_resume
+ *
+ * resume code entry for bootloader to call
+ *
+ * we must put this code here in the data segment as we have no
+ * other way of restoring the stack pointer after sleep, and we
+ * must not write to the code segment (code is read-only)
+ */
+
+ENTRY(s5pv210_didle_resume)
+ mov r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
+ msr cpsr_c, r0
+
+ @@ load UART to allow us to print the two characters for
+ @@ resume debug
+
+ mov r1, #0
+ mcr p15, 0, r1, c8, c7, 0 @@ invalidate TLBs
+ mcr p15, 0, r1, c7, c5, 0 @@ invalidate I Cache
+
+ ldr r1, =0xe010f008 @ Read INFORM2 register
+ ldr r0, [r1] @ Load phy_regs_save value
+ ldmia r0, { r3 - r13 }
+
+ mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID
+ mcr p15, 0, r5, c3, c0, 0 @ Domain ID
+
+ mcr p15, 0, r8, c2, c0, 2 @ Translation Table Control
+ mcr p15, 0, r7, c2, c0, 1 @ Translation Table BASE1
+ mcr p15, 0, r6, c2, c0, 0 @ Translation Table BASE0
+
+ bic r10, r10, #(1<<1) @ disable L2cache
+ mcr p15, 0, r10, c1, c0, 1 @ Auxiliary control register
+
+ mov r0, #0
+ mcr p15, 0, r0, c8, c7, 0 @ Invalidate I & D TLB
+
+ mov r0, #0 @ restore copro access controls
+ mcr p15, 0, r11, c1, c0, 2 @ Co-processor access controls
+ mcr p15, 0, r0, c7, c5, 4
+
+ mcr p15, 0, r12, c10, c2, 0 @ write PRRR
+ mcr p15, 0, r3, c10, c2, 1 @ write NMRR
+
+ /* calculate first section address into r8 */
+ mov r4, r6
+ ldr r5, =0x3fff
+ bic r4, r4, r5
+ ldr r11, =0xe010f000
+ ldr r10, [r11, #0]
+ mov r10, r10 ,LSR #18
+ bic r10, r10, #0x3
+ orr r4, r4, r10
+
+ /* calculate mmu list value into r9 */
+ mov r10, r10, LSL #18
+ ldr r5, =0x40e
+ orr r10, r10, r5
+
+ /* back up originally data */
+ ldr r12, [r4]
+
+ /* Added list about mmu */
+ str r10, [r4]
+
+ ldr r2, =resume_with_mmu
+ mcr p15, 0, r9, c1, c0, 0 @ turn on MMU, etc
+
+ nop
+ nop
+ nop
+ nop
+ nop @ second-to-last before mmu
+
+ mov pc, r2 @ go back to virtual address
+
+ .ltorg
diff --git a/arch/arm/mach-s5pv210/dma.c b/arch/arm/mach-s5pv210/dma.c
index 497d343..34cfacc 100644
--- a/arch/arm/mach-s5pv210/dma.c
+++ b/arch/arm/mach-s5pv210/dma.c
@@ -30,6 +30,71 @@
static u64 dma_dmamask = DMA_BIT_MASK(32);
+static struct resource s5pv210_mdma_resource[] = {
+ [0] = {
+ .start = S5PV210_PA_MDMA,
+ .end = S5PV210_PA_MDMA + SZ_4K,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_MDMA,
+ .end = IRQ_MDMA,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct s3c_pl330_platdata s5pv210_mdma_pdata = {
+ .peri = {
+ /* The DMAC can have max 8 channel so there
+ * can be 8 M<->M requests served at any time.
+ */
+ [0] = DMACH_MTOM_0,
+ [1] = DMACH_MTOM_1,
+ [2] = DMACH_MTOM_2,
+ [3] = DMACH_MTOM_3,
+ [4] = DMACH_MTOM_4,
+ [5] = DMACH_MTOM_5,
+ [6] = DMACH_MTOM_6,
+ [7] = DMACH_MTOM_7,
+ [8] = DMACH_MAX,
+ [9] = DMACH_MAX,
+ [10] = DMACH_MAX,
+ [11] = DMACH_MAX,
+ [12] = DMACH_MAX,
+ [13] = DMACH_MAX,
+ [14] = DMACH_MAX,
+ [15] = DMACH_MAX,
+ [16] = DMACH_MAX,
+ [17] = DMACH_MAX,
+ [18] = DMACH_MAX,
+ [19] = DMACH_MAX,
+ [20] = DMACH_MAX,
+ [21] = DMACH_MAX,
+ [22] = DMACH_MAX,
+ [23] = DMACH_MAX,
+ [24] = DMACH_MAX,
+ [25] = DMACH_MAX,
+ [26] = DMACH_MAX,
+ [27] = DMACH_MAX,
+ [28] = DMACH_MAX,
+ [29] = DMACH_MAX,
+ [30] = DMACH_MAX,
+ [31] = DMACH_MAX,
+ },
+};
+
+struct platform_device s5pv210_device_mdma = {
+ .name = "s3c-pl330",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(s5pv210_mdma_resource),
+ .resource = s5pv210_mdma_resource,
+ .dev = {
+ .dma_mask = &dma_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &s5pv210_mdma_pdata,
+ },
+};
+
static struct resource s5pv210_pdma0_resource[] = {
[0] = {
.start = S5PV210_PA_PDMA0,
@@ -80,9 +145,9 @@ static struct s3c_pl330_platdata s5pv210_pdma0_pdata = {
},
};
-static struct platform_device s5pv210_device_pdma0 = {
+struct platform_device s5pv210_device_pdma0 = {
.name = "s3c-pl330",
- .id = 0,
+ .id = 1,
.num_resources = ARRAY_SIZE(s5pv210_pdma0_resource),
.resource = s5pv210_pdma0_resource,
.dev = {
@@ -142,9 +207,9 @@ static struct s3c_pl330_platdata s5pv210_pdma1_pdata = {
},
};
-static struct platform_device s5pv210_device_pdma1 = {
+struct platform_device s5pv210_device_pdma1 = {
.name = "s3c-pl330",
- .id = 1,
+ .id = 2,
.num_resources = ARRAY_SIZE(s5pv210_pdma1_resource),
.resource = s5pv210_pdma1_resource,
.dev = {
@@ -155,6 +220,7 @@ static struct platform_device s5pv210_device_pdma1 = {
};
static struct platform_device *s5pv210_dmacs[] __initdata = {
+ &s5pv210_device_mdma,
&s5pv210_device_pdma0,
&s5pv210_device_pdma1,
};
diff --git a/arch/arm/mach-s5pv210/herring-btlpm.c b/arch/arm/mach-s5pv210/herring-btlpm.c
new file mode 100644
index 0000000..362f35a
--- /dev/null
+++ b/arch/arm/mach-s5pv210/herring-btlpm.c
@@ -0,0 +1,66 @@
+/* linux/arch/arm/mach-s5pv210/herring-btlpm.c
+ * Copyright (C) 2010 Samsung Electronics. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/hrtimer.h>
+
+#include <asm/mach-types.h>
+
+#include <mach/gpio-herring.h>
+
+#include "herring.h"
+
+static struct herring_bt_lpm {
+ struct hrtimer bt_lpm_timer;
+ ktime_t bt_lpm_delay;
+} bt_lpm;
+
+static enum hrtimer_restart bt_enter_lpm(struct hrtimer *timer)
+{
+ gpio_set_value(GPIO_BT_WAKE, 0);
+
+ return HRTIMER_NORESTART;
+}
+
+void herring_bt_uart_wake_peer(struct uart_port *port)
+{
+ if (!bt_lpm.bt_lpm_timer.function)
+ return;
+
+ hrtimer_try_to_cancel(&bt_lpm.bt_lpm_timer);
+ gpio_set_value(GPIO_BT_WAKE, 1);
+ hrtimer_start(&bt_lpm.bt_lpm_timer, bt_lpm.bt_lpm_delay, HRTIMER_MODE_REL);
+}
+
+static int __init bt_lpm_init(void)
+{
+ int ret;
+
+ if (!machine_is_herring())
+ return 0;
+
+ ret = gpio_request(GPIO_BT_WAKE, "gpio_bt_wake");
+ if (ret) {
+ printk(KERN_ERR "Failed to request gpio_bt_wake control\n");
+ return 0;
+ }
+
+ gpio_direction_output(GPIO_BT_WAKE, GPIO_LEVEL_LOW);
+
+ hrtimer_init(&bt_lpm.bt_lpm_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ bt_lpm.bt_lpm_delay = ktime_set(1, 0); /* 1 sec */
+ bt_lpm.bt_lpm_timer.function = bt_enter_lpm;
+ return 0;
+}
+device_initcall(bt_lpm_init);
diff --git a/arch/arm/mach-s5pv210/herring-panel.c b/arch/arm/mach-s5pv210/herring-panel.c
new file mode 100755
index 0000000..e84d6e8
--- /dev/null
+++ b/arch/arm/mach-s5pv210/herring-panel.c
@@ -0,0 +1,1018 @@
+/*
+ * 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/types.h>
+#include <linux/tl2796.h>
+#include <linux/nt35580.h>
+#include <mach/gpio.h>
+#include <linux/delay.h>
+
+static const u16 s6e63m0_SEQ_STANDBY_ON[] = {
+ 0x010, /* Stand-by On Command */
+ SLEEPMSEC, 160,
+ ENDDEF, 0x0000
+};
+
+static const u16 s6e63m0_SEQ_STANDBY_OFF[] = {
+ 0x011, /* Stand-by Off Command */
+ SLEEPMSEC, 120,
+ ENDDEF, 0x0000
+};
+
+static const u16 s6e63m0_SEQ_DISPLAY_SETTING[] = {
+ SLEEPMSEC, 10,
+ 0x0F8, /* Panel Condition Set Command*/
+ 0x101, /* DOCT */
+ 0x127, /* CLWEA */
+ 0x127, /* CLWEB*/
+ 0x107, /* CLTE */
+ 0x107, /* SHE */
+ 0x154, /* FLTE */
+ 0x19F, /* FLWE */
+ 0x163, /* SCTE */
+ 0x186, /* SCWE */
+ 0x11A, /* INTE */
+ 0x133, /* INWE */
+ 0x10D, /* EMPS */
+ 0x100, /* E_INTE */
+ 0x100, /* E_INWE */
+ 0x0F2, /* Display Condition Set Command*/
+ 0x102, /* Number of Line */
+ 0x103, /* VBP */
+ 0x11C, /* VFP */
+ 0x110, /* HBP */
+ 0x110, /* HFP */
+ 0x0F7, /* Command */
+ 0x103, /* GTCON */
+ 0x100, /* Display Mode */
+ 0x100, /* Vsync/Hsync, DOCCLK, RGB mode */
+ ENDDEF, 0x0000
+};
+
+static const u16 s6e63m0_SEQ_ETC_SETTING[] = {
+ /* ETC Condition Set Command */
+ 0x0F6,
+ 0x100, 0x18E,
+ 0x107,
+ 0x0B3,
+ 0x16C,
+ 0x0B5,
+ 0x127, 0x10A,
+ 0x109, 0x107,
+ 0x130, 0x11C,
+ 0x113, 0x109,
+ 0x110, 0x11A,
+ 0x12A, 0x124,
+ 0x11F, 0x11B,
+ 0x11A, 0x117,
+ 0x12B, 0x126,
+ 0x122, 0x120,
+ 0x13A, 0x134,
+ 0x130, 0x12C,
+ 0x129, 0x126,
+ 0x125, 0x123,
+ 0x121, 0x120,
+ 0x11E, 0x11E,
+ 0x0B6,
+ 0x100, 0x100,
+ 0x123, 0x111,
+ 0x132, 0x144,
+ 0x144, 0x144,
+ 0x155, 0x155,
+ 0x166, 0x166,
+ 0x166, 0x166,
+ 0x166, 0x166,
+ 0x0B7,
+ 0x127, 0x10A,
+ 0x109, 0x107,
+ 0x130, 0x11C,
+ 0x113, 0x109,
+ 0x110, 0x11A,
+ 0x12A, 0x124,
+ 0x11F, 0x11B,
+ 0x11A, 0x117,
+ 0x12B, 0x126,
+ 0x122, 0x120,
+ 0x13A, 0x134,
+ 0x130, 0x12C,
+ 0x129, 0x126,
+ 0x125, 0x123,
+ 0x121, 0x120,
+ 0x11E, 0x11E,
+ 0x0B8,
+ 0x100, 0x100,
+ 0x123, 0x111,
+ 0x132, 0x144,
+ 0x144, 0x144,
+ 0x155, 0x155,
+ 0x166, 0x166,
+ 0x166, 0x166,
+ 0x166, 0x166,
+ 0x0B9,
+ 0x127, 0x10A,
+ 0x109, 0x107,
+ 0x130, 0x11C,
+ 0x113, 0x109,
+ 0x110, 0x11A,
+ 0x12A, 0x124,
+ 0x11F, 0x11B,
+ 0x11A, 0x117,
+ 0x12B, 0x126,
+ 0x122, 0x120,
+ 0x13A, 0x134,
+ 0x130, 0x12C,
+ 0x129, 0x126,
+ 0x125, 0x123,
+ 0x121, 0x120,
+ 0x11E, 0x11E,
+ 0x0BA,
+ 0x100, 0x100,
+ 0x123, 0x111,
+ 0x132, 0x144,
+ 0x144, 0x144,
+ 0x155, 0x155,
+ 0x166, 0x166,
+ 0x166, 0x166,
+ 0x166, 0x166,
+ 0x011,
+ SLEEPMSEC, 120,
+ 0x029,
+ ENDDEF, 0x0000
+};
+
+static const struct tl2796_gamma_adj_points gamma_adj_points = {
+ .v0 = 0,
+ .v1 = BV_1,
+ .v19 = BV_19,
+ .v43 = BV_43,
+ .v87 = BV_87,
+ .v171 = BV_171,
+ .v255 = BV_255,
+};
+
+#ifdef CONFIG_FB_VOODOO
+struct gamma_entry gamma_table[] = {
+#else
+static const struct gamma_entry gamma_table[] = {
+#endif
+ { BV_0, { 4200000, 4200000, 4200000, }, },
+ { 1, { 3994200, 4107600, 3910200, }, },
+ { 0x00000400, { 3669486, 3738030, 3655093, }, },
+ { 0x000004C2, { 3664456, 3732059, 3649872, }, },
+ { 0x000005A8, { 3659356, 3726019, 3644574, }, },
+ { 0x000006BA, { 3654160, 3719879, 3639171, }, },
+ { 0x00000800, { 3648872, 3713646, 3633668, }, },
+ { 0x00000983, { 3643502, 3707331, 3628075, }, },
+ { 0x00000B50, { 3638029, 3700909, 3622368, }, },
+ { 0x00000D74, { 3632461, 3694392, 3616558, }, },
+ { 0x00001000, { 3626792, 3687772, 3610636, }, },
+ { 0x00001307, { 3621022, 3681052, 3604605, }, },
+ { 0x000016A1, { 3615146, 3674224, 3598455, }, },
+ { 0x00001AE9, { 3609163, 3667289, 3592189, }, },
+ { 0x00002000, { 3603070, 3660245, 3585801, }, },
+ { 0x0000260E, { 3596860, 3653083, 3579284, }, },
+ { 0x00002D41, { 3590532, 3645805, 3572637, }, },
+ { 0x000035D1, { 3584081, 3638403, 3565854, }, },
+ { 0x00004000, { 3577504, 3630876, 3558930, }, },
+ { 0x00004C1C, { 3570797, 3623221, 3551863, }, },
+ { 0x00005A82, { 3563956, 3615434, 3544649, }, },
+ { 0x00006BA2, { 3556976, 3607510, 3537279, }, },
+ { 0x00008000, { 3549853, 3599444, 3529750, }, },
+ { 0x00009838, { 3542582, 3591234, 3522056, }, },
+ { 0x0000B505, { 3535159, 3582874, 3514193, }, },
+ { 0x0000D745, { 3527577, 3574360, 3506153, }, },
+ { 0x00010000, { 3519832, 3565687, 3497931, }, },
+ { 0x00013070, { 3511918, 3556849, 3489519, }, },
+ { 0x00016A0A, { 3503829, 3547842, 3480912, }, },
+ { 0x0001AE8A, { 3495559, 3538659, 3472102, }, },
+ { 0x00020000, { 3487101, 3529295, 3463080, }, },
+ { 0x000260E0, { 3478447, 3519742, 3453839, }, },
+ { 0x0002D414, { 3469592, 3509996, 3444372, }, },
+ { 0x00035D14, { 3460527, 3500049, 3434667, }, },
+ { 0x00040000, { 3451244, 3489893, 3424717, }, },
+ { 0x0004C1C0, { 3441734, 3479522, 3414512, }, },
+ { 0x0005A828, { 3431990, 3468927, 3404040, }, },
+ { 0x0006BA28, { 3422000, 3458099, 3393292, }, },
+ { 0x00080000, { 3411756, 3447030, 3382254, }, },
+ { 0x0009837F, { 3401247, 3435711, 3370915, }, },
+ { 0x000B504F, { 3390462, 3424131, 3359262, }, },
+ { 0x000D7450, { 3379388, 3412280, 3347281, }, },
+ { 0x00100000, { 3368014, 3400147, 3334957, }, },
+ { 0x001306FE, { 3356325, 3387721, 3322274, }, },
+ { 0x0016A09E, { 3344309, 3374988, 3309216, }, },
+ { 0x001AE8A0, { 3331950, 3361936, 3295765, }, },
+ { 0x00200000, { 3319231, 3348550, 3281902, }, },
+ { 0x00260DFC, { 3306137, 3334817, 3267607, }, },
+ { 0x002D413D, { 3292649, 3320719, 3252859, }, },
+ { 0x0035D13F, { 3278748, 3306240, 3237634, }, },
+ { 0x00400000, { 3264413, 3291361, 3221908, }, },
+ { 0x004C1BF8, { 3249622, 3276065, 3205654, }, },
+ { 0x005A827A, { 3234351, 3260329, 3188845, }, },
+ { 0x006BA27E, { 3218576, 3244131, 3171449, }, },
+ { 0x00800000, { 3202268, 3227448, 3153434, }, },
+ { 0x009837F0, { 3185399, 3210255, 3134765, }, },
+ { 0x00B504F3, { 3167936, 3192523, 3115404, }, },
+ { 0x00D744FD, { 3149847, 3174223, 3095308, }, },
+ { 0x01000000, { 3131093, 3155322, 3074435, }, },
+ { 0x01306FE1, { 3111635, 3135786, 3052735, }, },
+ { 0x016A09E6, { 3091431, 3115578, 3030156, }, },
+ { 0x01AE89FA, { 3070432, 3094655, 3006641, }, },
+ { 0x02000000, { 3048587, 3072974, 2982127, }, },
+ { 0x0260DFC1, { 3025842, 3050485, 2956547, }, },
+ { 0x02D413CD, { 3002134, 3027135, 2929824, }, },
+ { 0x035D13F3, { 2977397, 3002865, 2901879, }, },
+ { 0x04000000, { 2951558, 2977611, 2872620, }, },
+ { 0x04C1BF83, { 2924535, 2951302, 2841948, }, },
+ { 0x05A8279A, { 2896240, 2923858, 2809753, }, },
+ { 0x06BA27E6, { 2866574, 2895192, 2775914, }, },
+ { 0x08000000, { 2835426, 2865207, 2740295, }, },
+ { 0x09837F05, { 2802676, 2833793, 2702744, }, },
+ { 0x0B504F33, { 2768187, 2800829, 2663094, }, },
+ { 0x0D744FCD, { 2731806, 2766175, 2621155, }, },
+ { 0x10000000, { 2693361, 2729675, 2576712, }, },
+ { 0x1306FE0A, { 2652659, 2691153, 2529527, }, },
+ { 0x16A09E66, { 2609480, 2650402, 2479324, }, },
+ { 0x1AE89F99, { 2563575, 2607191, 2425793, }, },
+ { 0x20000000, { 2514655, 2561246, 2368579, }, },
+ { 0x260DFC14, { 2462394, 2512251, 2307272, }, },
+ { 0x2D413CCD, { 2406412, 2459834, 2241403, }, },
+ { 0x35D13F32, { 2346266, 2403554, 2170425, }, },
+ { 0x40000000, { 2281441, 2342883, 2093706, }, },
+ { 0x4C1BF828, { 2211332, 2277183, 2010504, }, },
+ { 0x5A82799A, { 2135220, 2205675, 1919951, }, },
+ { 0x6BA27E65, { 2052250, 2127391, 1821028, }, },
+ { 0x80000000, { 1961395, 2041114, 1712536, }, },
+ { 0x9837F051, { 1861415, 1945288, 1593066, }, },
+ { 0xB504F333, { 1750800, 1837874, 1460986, }, },
+ { 0xD744FCCA, { 1627706, 1716150, 1314437, }, },
+ { 0xFFFFFFFF, { 1489879, 1576363, 1151415, }, },
+};
+
+static void reset_lcd(struct s5p_panel_data *pdata)
+{
+ gpio_direction_output(pdata->gpio_rst, 1);
+ msleep(10);
+
+ gpio_set_value(pdata->gpio_rst, 0);
+ msleep(10);
+
+ gpio_set_value(pdata->gpio_rst, 1);
+ msleep(10);
+}
+
+static int configure_mtp_gpios(struct s5p_panel_data *pdata, bool enable)
+{
+ int i;
+ int ret = 0;
+ if (enable) {
+ /* wrx and csx are already requested by the spi driver */
+ ret = gpio_request(pdata->gpio_rdx, "tl2796_rdx");
+ if (ret)
+ goto err_rdx;
+ ret = gpio_request(pdata->gpio_dcx, "tl2796_dcx");
+ if (ret)
+ goto err_dcx;
+ ret = gpio_request(pdata->gpio_rst, "tl2796_rst");
+ if (ret)
+ goto err_rst;
+ for (i = 0; i < 8; i++) {
+ ret = gpio_request(pdata->gpio_db[i], "tl2796_dbx");
+ if (ret)
+ goto err_dbx;
+ }
+ for (i = 0; i < 8; i++) {
+ s3c_gpio_cfgpin(S5PV210_GPF0(i), S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(S5PV210_GPF0(i), S3C_GPIO_PULL_NONE);
+ gpio_set_value(S5PV210_GPF0(i), 0);
+ }
+ for (i = 0; i < 8; i++) {
+ s3c_gpio_cfgpin(S5PV210_GPF1(i), S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(S5PV210_GPF1(i), S3C_GPIO_PULL_UP);
+ gpio_set_value(S5PV210_GPF1(i), 0);
+ }
+ return 0;
+ }
+
+ for (i = 0; i < 8; i++) {
+ s3c_gpio_cfgpin(S5PV210_GPF0(i), S3C_GPIO_SFN(2));
+ s3c_gpio_setpull(S5PV210_GPF0(i), S3C_GPIO_PULL_NONE);
+ }
+ for (i = 0; i < 8; i++) {
+ s3c_gpio_cfgpin(S5PV210_GPF1(i), S3C_GPIO_SFN(2));
+ s3c_gpio_setpull(S5PV210_GPF1(i), S3C_GPIO_PULL_NONE);
+ }
+
+ reset_lcd(pdata);
+
+ for (i = 7; i >= 0; i--) {
+ gpio_free(pdata->gpio_db[i]);
+err_dbx:
+ ;
+ }
+ gpio_free(pdata->gpio_rst);
+err_rst:
+ gpio_free(pdata->gpio_dcx);
+err_dcx:
+ gpio_free(pdata->gpio_rdx);
+err_rdx:
+ return ret;
+}
+
+struct s5p_panel_data herring_panel_data = {
+ .seq_display_set = s6e63m0_SEQ_DISPLAY_SETTING,
+ .seq_etc_set = s6e63m0_SEQ_ETC_SETTING,
+ .standby_on = s6e63m0_SEQ_STANDBY_ON,
+ .standby_off = s6e63m0_SEQ_STANDBY_OFF,
+ .gpio_dcx = S5PV210_GPF0(0), /* H_SYNC pad */
+ .gpio_rdx = S5PV210_GPF0(2), /* Enable */
+ .gpio_csx = S5PV210_MP01(1),
+ .gpio_wrx = S5PV210_MP04(1), /* SCL pad */
+ .gpio_rst = S5PV210_MP05(5),
+ .gpio_db = {
+ S5PV210_GPF0(4),
+ S5PV210_GPF0(5),
+ S5PV210_GPF0(6),
+ S5PV210_GPF0(7),
+ S5PV210_GPF1(0),
+ S5PV210_GPF1(1),
+ S5PV210_GPF1(2),
+ S5PV210_GPF1(3),
+ },
+ .configure_mtp_gpios = configure_mtp_gpios,
+ .factory_v255_regs = {
+ 0x0b9,
+ 0x0b8,
+ 0x0fc,
+ },
+#ifdef CONFIG_TL2796_CONVERT_COLORS_RES
+ .color_adj = {
+ /* Convert from 8500K to D65, assuming:
+ * Rx 0.66950, Ry 0.33100
+ * Gx 0.18800, Gy 0.74350
+ * Bx 0.14142, By 0.04258
+ */
+ .mult = {
+ 2318372099U,
+ 2117262806U,
+ 1729744557U,
+ },
+ .rshift = 31,
+ },
+#endif
+
+ .gamma_adj_points = &gamma_adj_points,
+ .gamma_table = gamma_table,
+ .gamma_table_size = ARRAY_SIZE(gamma_table),
+};
+
+static const u16 brightness_setting_table[] = {
+ 0x051, 0x17f,
+ ENDDEF, 0x0000
+};
+
+static const u16 nt35580_SEQ_DISPLAY_ON[] = {
+ 0x029,
+ ENDDEF, 0x0000
+};
+
+static const u16 nt35580_SEQ_DISPLAY_OFF[] = {
+ 0x028,
+ SLEEPMSEC, 27, /* more than 25ms */
+ ENDDEF, 0x0000
+};
+
+static const u16 nt35580_SEQ_SETTING[] = {
+ /* SET_PIXEL_FORMAT */
+ 0x3A,
+ 0x177, /* 24 bpp */
+ /* RGBCTRL */
+ 0x3B,
+ /* RGB Mode1, DE is sampled at the rising edge of PCLK,
+ * P-rising edge, EP- low active, HSP-low active, VSP-low active */
+ 0x107,
+ 0x10A,
+ 0x10E,
+ 0x10A,
+ 0x10A,
+ /* SET_HORIZONTAL_ADDRESS (Frame Memory Area define) */
+ 0x2A,
+ 0x100,
+ 0x100,
+ 0x101, /* 480x800 */
+ 0x1DF, /* 480x800 */
+ /* SET_VERTICAL_ADDRESS (Frame Memory Area define) */
+ 0x2B,
+ 0x100,
+ 0x100,
+ 0x103, /* 480x800 */
+ 0x11F, /* 480x800 */
+ /* SET_ADDRESS_MODE */
+ 0x36,
+ 0x1D4,
+ SLEEPMSEC, 30, /* recommend by Sony-LCD, */
+ /* SLPOUT */
+ 0x11,
+ SLEEPMSEC, 155, /* recommend by Sony */
+ /* WRCTRLD-1 */
+ 0x55,
+ 0x100, /* CABC Off 1: UI-Mode, 2:Still-Mode, 3:Moving-Mode */
+ /* WRCABCMB */
+ 0x5E,
+ /* Minimum Brightness Value Setting 0:the lowest, 0xFF:the highest */
+ 0x100,
+ /* WRCTRLD-2 */
+ 0x53,
+ /* BCTRL(1)-PWM Output Enable, A(0)-LABC Off,
+ * DD(1)-Enable Dimming Function Only for CABC,
+ * BL(1)-turn on Backlight Control without dimming effect */
+ 0x12C,
+ ENDDEF, 0x0000
+};
+
+static const u16 nt35580_SEQ_SLEEP_IN[] = {
+ 0x010,
+ SLEEPMSEC, 155, /* more than 150ms */
+ ENDDEF, 0x0000
+};
+
+struct s5p_tft_panel_data herring_sony_panel_data = {
+ .seq_set = nt35580_SEQ_SETTING,
+ .sleep_in = nt35580_SEQ_SLEEP_IN,
+ .display_on = nt35580_SEQ_DISPLAY_ON,
+ .display_off = nt35580_SEQ_DISPLAY_OFF,
+ .brightness_set = brightness_setting_table,
+ .pwm_reg_offset = 1,
+};
+
+/* Hydis Panel (nt35510) */
+static const u16 nt35510_SEQ_SETTING[] = {
+ 0xFF,
+ 0x1AA,
+ 0x155,
+ 0x125,
+ 0x101,
+
+ 0xF3,
+ 0x100,
+ 0x132,
+ 0x100,
+ 0x138,
+ 0x131,
+ 0x108,
+ 0x111,
+ 0x100,
+
+ /* Enable CMD2_Page1 */
+ 0xF0,
+ 0x155,
+ 0x1AA,
+ 0x152,
+ 0x108,
+ 0x100,
+
+ 0xB0,
+ 0x104,
+ 0x10A,
+ 0x10E,
+ 0x109,
+ 0x104,
+
+ 0xB1,
+ 0x1CC,
+ 0x104,
+
+ 0x36, 0x102,
+ 0xB3, 0x100,
+
+ /* AVDD */
+ 0xB6,
+ 0x103,
+
+ 0xB7,
+ 0x170,
+ 0x170,
+
+ 0xB8,
+ 0x100,
+ 0x106,
+ 0x106,
+ 0x106,
+
+ 0xBC,
+ 0x100,
+ 0x100,
+ 0x100,
+
+ 0xBD,
+ 0x101,
+ 0x184,
+ 0x106,
+ 0x150,
+ 0x100,
+
+ 0xCC,
+ 0x101,
+ 0x101,
+ 0x106,
+
+ 0xF0,
+ 0x155,
+ 0x1AA,
+ 0x152,
+ 0x108,
+ 0x1101,
+
+ 0xB0,
+ 0x104,
+ 0x10A,
+ 0x10E,
+ 0x109,
+ 0x104,
+
+ 0xB1,
+ 0x105,
+ 0x105,
+ 0x105,
+
+ 0xB2,
+ 0x103,
+ 0x103,
+ 0x103,
+
+ 0xB8,
+ 0x125,
+ 0x125,
+ 0x125,
+
+ 0xB3,
+ 0x100,
+
+ 0xB9,
+ 0x134,
+ 0x134,
+ 0x134,
+
+ /* VGH */
+ 0xBF,
+ 0x101,
+
+ 0xB5,
+ 0x109,
+ 0x109,
+ 0x109,
+
+ /* VGL */
+ 0xBA,
+ 0x124,
+ 0x124,
+ 0x124,
+
+ 0xB4,
+ 0x124,
+ 0x124,
+ 0x124,
+
+ 0xBC,
+ 0x100,
+ 0x168,
+ 0x100,
+
+ 0xBD,
+ 0x100,
+ 0x17c,
+ 0x100,
+
+ 0xBE,
+ 0x100,
+ 0x145,
+
+ 0xD0,
+ 0x10A,
+ 0x114,
+ 0x10A,
+ 0x10E,
+
+ 0xD1,
+ 0x100,
+ 0x137,
+ 0x100,
+ 0x161,
+ 0x100,
+ 0x192,
+ 0x100,
+ 0x1B4,
+ 0x100,
+ 0x1CF,
+ 0x100,
+ 0x1F6,
+ 0x101,
+ 0x12F,
+ 0x101,
+ 0x17F,
+ 0x101,
+ 0x197,
+ 0x101,
+ 0x1C0,
+ 0x101,
+ 0x1E5,
+ 0x102,
+ 0x125,
+ 0x102,
+ 0x15E,
+ 0x102,
+ 0x160,
+ 0x102,
+ 0x187,
+ 0x102,
+ 0x1BE,
+ 0x102,
+ 0x1E2,
+ 0x103,
+ 0x10F,
+ 0x103,
+ 0x130,
+ 0x103,
+ 0x15C,
+ 0x103,
+ 0x177,
+ 0x103,
+ 0x194,
+ 0x103,
+ 0x19F,
+ 0x103,
+ 0x1AC,
+ 0x103,
+ 0x1BA,
+ 0x103,
+ 0x1F1,
+
+ 0xD2,
+ 0x100,
+ 0x137,
+ 0x100,
+ 0x161,
+ 0x100,
+ 0x192,
+ 0x100,
+ 0x1B4,
+ 0x100,
+ 0x1CF,
+ 0x100,
+ 0x1F6,
+ 0x101,
+ 0x12F,
+ 0x101,
+ 0x17F,
+ 0x101,
+ 0x197,
+ 0x101,
+ 0x1C0,
+ 0x101,
+ 0x1E5,
+ 0x102,
+ 0x125,
+ 0x102,
+ 0x15E,
+ 0x102,
+ 0x160,
+ 0x102,
+ 0x187,
+ 0x102,
+ 0x1BE,
+ 0x102,
+ 0x1E2,
+ 0x103,
+ 0x10F,
+ 0x103,
+ 0x130,
+ 0x103,
+ 0x15C,
+ 0x103,
+ 0x177,
+ 0x103,
+ 0x194,
+ 0x103,
+ 0x19F,
+ 0x103,
+ 0x1AC,
+ 0x103,
+ 0x1BA,
+ 0x103,
+ 0x1F1,
+
+ 0xD3,
+ 0x100,
+ 0x137,
+ 0x100,
+ 0x161,
+ 0x100,
+ 0x192,
+ 0x100,
+ 0x1B4,
+ 0x100,
+ 0x1CF,
+ 0x100,
+ 0x1F6,
+ 0x101,
+ 0x12F,
+ 0x101,
+ 0x17F,
+ 0x101,
+ 0x197,
+ 0x101,
+ 0x1C0,
+ 0x101,
+ 0x1E5,
+ 0x102,
+ 0x125,
+ 0x102,
+ 0x15E,
+ 0x102,
+ 0x160,
+ 0x102,
+ 0x187,
+ 0x102,
+ 0x1BE,
+ 0x102,
+ 0x1E2,
+ 0x103,
+ 0x10F,
+ 0x103,
+ 0x130,
+ 0x103,
+ 0x15C,
+ 0x103,
+ 0x177,
+ 0x103,
+ 0x194,
+ 0x103,
+ 0x19F,
+ 0x103,
+ 0x1AC,
+ 0x103,
+ 0x1BA,
+ 0x103,
+ 0x1F1,
+
+ 0xD4,
+ 0x100,
+ 0x137,
+ 0x100,
+ 0x150,
+ 0x100,
+ 0x189,
+ 0x100,
+ 0x1A9,
+ 0x100,
+ 0x1C0,
+ 0x100,
+ 0x1F6,
+ 0x101,
+ 0x114,
+ 0x101,
+ 0x148,
+ 0x101,
+ 0x16B,
+ 0x101,
+ 0x1A7,
+ 0x101,
+ 0x1D3,
+ 0x102,
+ 0x117,
+ 0x102,
+ 0x14F,
+ 0x102,
+ 0x151,
+ 0x102,
+ 0x186,
+ 0x102,
+ 0x1BD,
+ 0x102,
+ 0x1E2,
+ 0x103,
+ 0x10F,
+ 0x103,
+ 0x130,
+ 0x103,
+ 0x15C,
+ 0x103,
+ 0x177,
+ 0x103,
+ 0x194,
+ 0x103,
+ 0x19F,
+ 0x103,
+ 0x1AC,
+ 0x103,
+ 0x1BA,
+ 0x103,
+ 0x1F1,
+
+ 0xD5,
+ 0x100,
+ 0x137,
+ 0x100,
+ 0x150,
+ 0x100,
+ 0x189,
+ 0x100,
+ 0x1A9,
+ 0x100,
+ 0x1C0,
+ 0x100,
+ 0x1F6,
+ 0x101,
+ 0x114,
+ 0x101,
+ 0x148,
+ 0x101,
+ 0x16B,
+ 0x101,
+ 0x1A7,
+ 0x101,
+ 0x1D3,
+ 0x102,
+ 0x117,
+ 0x102,
+ 0x14F,
+ 0x102,
+ 0x151,
+ 0x102,
+ 0x186,
+ 0x102,
+ 0x1BD,
+ 0x102,
+ 0x1E2,
+ 0x103,
+ 0x10F,
+ 0x103,
+ 0x130,
+ 0x103,
+ 0x15C,
+ 0x103,
+ 0x177,
+ 0x103,
+ 0x194,
+ 0x103,
+ 0x19F,
+ 0x103,
+ 0x1AC,
+ 0x103,
+ 0x1BA,
+ 0x103,
+ 0x1F1,
+
+ 0xD6,
+ 0x100,
+ 0x137,
+ 0x100,
+ 0x150,
+ 0x100,
+ 0x189,
+ 0x100,
+ 0x1A9,
+ 0x100,
+ 0x1C0,
+ 0x100,
+ 0x1F6,
+ 0x101,
+ 0x114,
+ 0x101,
+ 0x148,
+ 0x101,
+ 0x16B,
+ 0x101,
+ 0x1A7,
+ 0x101,
+ 0x1D3,
+ 0x102,
+ 0x117,
+ 0x102,
+ 0x14F,
+ 0x102,
+ 0x151,
+ 0x102,
+ 0x186,
+ 0x102,
+ 0x1BD,
+ 0x102,
+ 0x1E2,
+ 0x103,
+ 0x10F,
+ 0x103,
+ 0x130,
+ 0x103,
+ 0x15C,
+ 0x103,
+ 0x177,
+ 0x103,
+ 0x194,
+ 0x103,
+ 0x19F,
+ 0x103,
+ 0x1AC,
+ 0x103,
+ 0x1BA,
+ 0x103,
+ 0x1F1,
+
+ 0xF0,
+ 0x155,
+ 0x1AA,
+ 0x152,
+ 0x108,
+ 0x101,
+
+ ENDDEF, 0x0000
+};
+
+static const u16 nt35510_SEQ_DISPLAY_ON[] = {
+ 0x53, 0x12C,
+ 0x11,
+ SLEEPMSEC, 120,
+ 0x29,
+ ENDDEF, 0x0000
+};
+
+static const u16 nt35510_SEQ_DISPLAY_OFF[] = {
+ 0x28,
+ SLEEPMSEC, 27,
+ ENDDEF, 0x0000
+};
+static const u16 nt35510_SEQ_SLEEP_IN[] = {
+ 0x10,
+ SLEEPMSEC, 155, /* more than 150ms */
+ ENDDEF, 0x0000
+};
+
+struct s5p_tft_panel_data herring_hydis_panel_data = {
+ .seq_set = nt35510_SEQ_SETTING,
+ .display_on = nt35510_SEQ_DISPLAY_ON,
+ .sleep_in = nt35510_SEQ_SLEEP_IN,
+ .display_off = nt35510_SEQ_DISPLAY_OFF,
+ .brightness_set = brightness_setting_table,
+ .pwm_reg_offset = 1,
+};
+
+/* hitachi panel (R61408) */
+static const u16 R61408_SEQ_SETTING[] = {
+ 0x36, 0x100,
+ 0x3A, 0x177,
+
+ 0x11,
+ SLEEPMSEC, 150,
+
+ 0xB0, 0x104,
+ 0xC1, 0x142,
+ 0x131, 0x104,
+ 0xB0, 0x103,
+ ENDDEF, 0x0000
+};
+
+static const u16 R61408_SEQ_DISPLAY_ON[] = {
+ 0x29,
+ ENDDEF, 0x0000
+};
+
+static const u16 R61408_SEQ_DISPLAY_OFF[] = {
+ 0xB0, 0x104,
+ 0xB1, 0x101,
+ SLEEPMSEC, 2,
+ ENDDEF, 0x0000
+};
+static const u16 R61408_SEQ_SLEEP_IN[] = {
+ 0x10,
+ SLEEPMSEC, 150, /* more than 150ms */
+ ENDDEF, 0x0000
+};
+
+static const u16 R61408_brightness_setting_table[] = {
+ 0xB0, 0x102,
+ 0xB9, 0x100,
+ 0x1F7, 0x102,
+ 0x108,
+ 0xB0, 0x103,
+ ENDDEF, 0x0000
+};
+struct s5p_tft_panel_data herring_hitachi_panel_data = {
+ .seq_set = R61408_SEQ_SETTING,
+ .display_on = R61408_SEQ_DISPLAY_ON,
+ .sleep_in = R61408_SEQ_SLEEP_IN,
+ .display_off = R61408_SEQ_DISPLAY_OFF,
+ .brightness_set = R61408_brightness_setting_table,
+ .pwm_reg_offset = 4,
+};
+
diff --git a/arch/arm/mach-s5pv210/herring-rfkill.c b/arch/arm/mach-s5pv210/herring-rfkill.c
new file mode 100644
index 0000000..ce7408f
--- /dev/null
+++ b/arch/arm/mach-s5pv210/herring-rfkill.c
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2010 Samsung Electronics Co., Ltd.
+ *
+ * Copyright (C) 2008 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Modified for Crespo on August, 2010 By Samsung Electronics Co.
+ * This is modified operate according to each status.
+ *
+ */
+
+/* Control bluetooth power for Crespo platform */
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/rfkill.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/wakelock.h>
+#include <linux/irq.h>
+#include <linux/workqueue.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <mach/gpio.h>
+#include <mach/gpio-herring.h>
+#include <mach/hardware.h>
+#include <plat/gpio-cfg.h>
+#include <plat/irqs.h>
+#include "herring.h"
+
+#define IRQ_BT_HOST_WAKE IRQ_EINT(21)
+
+static struct wake_lock rfkill_wake_lock;
+
+#ifndef GPIO_LEVEL_LOW
+#define GPIO_LEVEL_LOW 0
+#define GPIO_LEVEL_HIGH 1
+#endif
+
+static struct rfkill *bt_rfk;
+static const char bt_name[] = "bcm4329";
+
+#ifdef CONFIG_CPU_DIDLE
+static bool bt_running = false;
+
+bool bt_is_running(void)
+{
+ return bt_running;
+}
+EXPORT_SYMBOL(bt_is_running);
+#endif
+
+static int bluetooth_set_power(void *data, enum rfkill_user_states state)
+{
+ int ret = 0;
+ int irq;
+ /* BT Host Wake IRQ */
+ irq = IRQ_BT_HOST_WAKE;
+
+ switch (state) {
+
+ case RFKILL_USER_STATE_UNBLOCKED:
+ pr_debug("[BT] Device Powering ON\n");
+
+ s3c_setup_uart_cfg_gpio(0);
+
+ if (gpio_is_valid(GPIO_WLAN_BT_EN))
+ gpio_direction_output(GPIO_WLAN_BT_EN, GPIO_LEVEL_HIGH);
+
+ if (gpio_is_valid(GPIO_BT_nRST))
+ gpio_direction_output(GPIO_BT_nRST, GPIO_LEVEL_LOW);
+
+ pr_debug("[BT] GPIO_BT_nRST = %d\n",
+ gpio_get_value(GPIO_BT_nRST));
+
+ /* Set GPIO_BT_WLAN_REG_ON high */
+ s3c_gpio_setpull(GPIO_WLAN_BT_EN, S3C_GPIO_PULL_NONE);
+ gpio_set_value(GPIO_WLAN_BT_EN, GPIO_LEVEL_HIGH);
+
+ s3c_gpio_slp_cfgpin(GPIO_WLAN_BT_EN, S3C_GPIO_SLP_OUT1);
+ s3c_gpio_slp_setpull_updown(GPIO_WLAN_BT_EN,
+ S3C_GPIO_PULL_NONE);
+
+ pr_debug("[BT] GPIO_WLAN_BT_EN = %d\n",
+ gpio_get_value(GPIO_WLAN_BT_EN));
+ /*
+ * FIXME sleep should be enabled disabled since the device is
+ * not booting if its enabled
+ */
+ /*
+ * 100msec, delay between reg_on & rst.
+ * (bcm4329 powerup sequence)
+ */
+ msleep(100);
+
+ /* Set GPIO_BT_nRST high */
+ s3c_gpio_setpull(GPIO_BT_nRST, S3C_GPIO_PULL_NONE);
+ gpio_set_value(GPIO_BT_nRST, GPIO_LEVEL_HIGH);
+
+ s3c_gpio_slp_cfgpin(GPIO_BT_nRST, S3C_GPIO_SLP_OUT1);
+ s3c_gpio_slp_setpull_updown(GPIO_BT_nRST, S3C_GPIO_PULL_NONE);
+
+ pr_debug("[BT] GPIO_BT_nRST = %d\n",
+ gpio_get_value(GPIO_BT_nRST));
+
+ /*
+ * 50msec, delay after bt rst
+ * (bcm4329 powerup sequence)
+ */
+ msleep(50);
+
+ ret = enable_irq_wake(irq);
+ if (ret < 0)
+ pr_err("[BT] set wakeup src failed\n");
+
+ enable_irq(irq);
+ break;
+
+ case RFKILL_USER_STATE_SOFT_BLOCKED:
+ pr_debug("[BT] Device Powering OFF\n");
+
+#ifdef CONFIG_CPU_DIDLE
+ bt_running = false;
+#endif
+
+ ret = disable_irq_wake(irq);
+ if (ret < 0)
+ pr_err("[BT] unset wakeup src failed\n");
+
+ disable_irq(irq);
+ wake_unlock(&rfkill_wake_lock);
+
+ s3c_gpio_setpull(GPIO_BT_nRST, S3C_GPIO_PULL_NONE);
+ gpio_set_value(GPIO_BT_nRST, GPIO_LEVEL_LOW);
+
+ s3c_gpio_slp_cfgpin(GPIO_BT_nRST, S3C_GPIO_SLP_OUT0);
+ s3c_gpio_slp_setpull_updown(GPIO_BT_nRST, S3C_GPIO_PULL_NONE);
+
+ pr_debug("[BT] GPIO_BT_nRST = %d\n",
+ gpio_get_value(GPIO_BT_nRST));
+
+ if (gpio_get_value(GPIO_WLAN_nRST) == 0) {
+ s3c_gpio_setpull(GPIO_WLAN_BT_EN, S3C_GPIO_PULL_NONE);
+ gpio_set_value(GPIO_WLAN_BT_EN, GPIO_LEVEL_LOW);
+
+ s3c_gpio_slp_cfgpin(GPIO_WLAN_BT_EN, S3C_GPIO_SLP_OUT0);
+ s3c_gpio_slp_setpull_updown(GPIO_WLAN_BT_EN,
+ S3C_GPIO_PULL_NONE);
+
+ pr_debug("[BT] GPIO_WLAN_BT_EN = %d\n",
+ gpio_get_value(GPIO_WLAN_BT_EN));
+ }
+
+ break;
+
+ default:
+ pr_err("[BT] Bad bluetooth rfkill state %d\n", state);
+ }
+
+ return 0;
+}
+
+irqreturn_t bt_host_wake_irq_handler(int irq, void *dev_id)
+{
+ pr_debug("[BT] bt_host_wake_irq_handler start\n");
+
+#ifdef CONFIG_CPU_DIDLE
+ bt_running = true;
+#endif
+
+ if (gpio_get_value(GPIO_BT_HOST_WAKE))
+ wake_lock(&rfkill_wake_lock);
+ else
+ wake_lock_timeout(&rfkill_wake_lock, HZ);
+
+ return IRQ_HANDLED;
+}
+
+static int bt_rfkill_set_block(void *data, bool blocked)
+{
+ unsigned int ret = 0;
+
+ ret = bluetooth_set_power(data, blocked ?
+ RFKILL_USER_STATE_SOFT_BLOCKED :
+ RFKILL_USER_STATE_UNBLOCKED);
+
+ return ret;
+}
+
+static const struct rfkill_ops bt_rfkill_ops = {
+ .set_block = bt_rfkill_set_block,
+};
+
+static int __init herring_rfkill_probe(struct platform_device *pdev)
+{
+ int irq;
+ int ret;
+
+ /* Initialize wake locks */
+ wake_lock_init(&rfkill_wake_lock, WAKE_LOCK_SUSPEND, "bt_host_wake");
+
+ ret = gpio_request(GPIO_WLAN_BT_EN, "GPB");
+ if (ret < 0) {
+ pr_err("[BT] Failed to request GPIO_WLAN_BT_EN!\n");
+ goto err_req_gpio_wlan_bt_en;
+ }
+
+ ret = gpio_request(GPIO_BT_nRST, "GPB");
+ if (ret < 0) {
+ pr_err("[BT] Failed to request GPIO_BT_nRST!\n");
+ goto err_req_gpio_bt_nrst;
+ }
+
+ /* BT Host Wake IRQ */
+ irq = IRQ_BT_HOST_WAKE;
+
+ ret = request_irq(irq, bt_host_wake_irq_handler,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ "bt_host_wake_irq_handler", NULL);
+
+ if (ret < 0) {
+ pr_err("[BT] Request_irq failed\n");
+ goto err_req_irq;
+ }
+
+ disable_irq(irq);
+
+ bt_rfk = rfkill_alloc(bt_name, &pdev->dev, RFKILL_TYPE_BLUETOOTH,
+ &bt_rfkill_ops, NULL);
+
+ if (!bt_rfk) {
+ pr_err("[BT] bt_rfk : rfkill_alloc is failed\n");
+ ret = -ENOMEM;
+ goto err_alloc;
+ }
+
+ rfkill_init_sw_state(bt_rfk, 0);
+
+ pr_debug("[BT] rfkill_register(bt_rfk)\n");
+
+ ret = rfkill_register(bt_rfk);
+ if (ret) {
+ pr_debug("********ERROR IN REGISTERING THE RFKILL********\n");
+ goto err_register;
+ }
+
+ rfkill_set_sw_state(bt_rfk, 1);
+ bluetooth_set_power(NULL, RFKILL_USER_STATE_SOFT_BLOCKED);
+
+ return ret;
+
+ err_register:
+ rfkill_destroy(bt_rfk);
+
+ err_alloc:
+ free_irq(irq, NULL);
+
+ err_req_irq:
+ gpio_free(GPIO_BT_nRST);
+
+ err_req_gpio_bt_nrst:
+ gpio_free(GPIO_WLAN_BT_EN);
+
+ err_req_gpio_wlan_bt_en:
+ return ret;
+}
+
+static struct platform_driver herring_device_rfkill = {
+ .probe = herring_rfkill_probe,
+ .driver = {
+ .name = "bt_rfkill",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init herring_rfkill_init(void)
+{
+ int rc = 0;
+ rc = platform_driver_register(&herring_device_rfkill);
+
+ return rc;
+}
+
+module_init(herring_rfkill_init);
+MODULE_DESCRIPTION("herring rfkill");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-s5pv210/herring-touchkey-led.c b/arch/arm/mach-s5pv210/herring-touchkey-led.c
new file mode 100644
index 0000000..47c26a5
--- /dev/null
+++ b/arch/arm/mach-s5pv210/herring-touchkey-led.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2010 Samsung Electronics Co. Ltd. All Rights Reserved.
+ * Author: Rom Lemarchand <rlemarchand@sta.samsung.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <linux/earlysuspend.h>
+#include <linux/bln.h>
+#include <asm/mach-types.h>
+
+#ifdef CONFIG_BLD
+#include <linux/bld.h>
+#endif
+
+#include "herring.h"
+
+static int led_gpios[] = { 2, 3, 6, 7 };
+
+static void herring_touchkey_led_onoff(int onoff)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(led_gpios); i++)
+ gpio_direction_output(S5PV210_GPJ3(led_gpios[i]), !!onoff);
+}
+
+#ifdef CONFIG_GENERIC_BLN
+static void herring_touchkey_bln_enable(void)
+{
+ herring_touchkey_led_onoff(1);
+}
+
+static void herring_touchkey_bln_disable(void)
+{
+ herring_touchkey_led_onoff(0);
+}
+
+static struct bln_implementation herring_touchkey_bln = {
+ .enable = herring_touchkey_bln_enable,
+ .disable = herring_touchkey_bln_disable,
+};
+#endif
+
+#ifdef CONFIG_BLD
+static void herring_touchkey_bld_enable(void)
+{
+ herring_touchkey_led_onoff(1);
+}
+
+static void herring_touchkey_bld_disable(void)
+{
+ herring_touchkey_led_onoff(0);
+}
+
+static struct bld_implementation herring_touchkey_bld =
+ {
+ .enable = herring_touchkey_bld_enable,
+ .disable = herring_touchkey_bld_disable,
+ };
+#endif
+
+static void herring_touchkey_led_early_suspend(struct early_suspend *h)
+{
+ herring_touchkey_led_onoff(0);
+}
+
+static void herring_touchkey_led_late_resume(struct early_suspend *h)
+{
+ herring_touchkey_led_onoff(1);
+}
+
+static struct early_suspend early_suspend = {
+ .level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1,
+ .suspend = herring_touchkey_led_early_suspend,
+ .resume = herring_touchkey_led_late_resume,
+};
+
+static int __init herring_init_touchkey_led(void)
+{
+ int i;
+ int ret = 0;
+ u32 gpio;
+
+ if (!machine_is_herring() || !herring_is_tft_dev())
+ return 0;
+
+ for (i = 0; i < ARRAY_SIZE(led_gpios); i++) {
+ gpio = S5PV210_GPJ3(led_gpios[i]);
+ ret = gpio_request(gpio, "touchkey led");
+ if (ret) {
+ pr_err("Failed to request touchkey led gpio %d\n", i);
+ goto err_req;
+ }
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+ s3c_gpio_slp_cfgpin(gpio, S3C_GPIO_SLP_PREV);
+ s3c_gpio_slp_setpull_updown(gpio, S3C_GPIO_PULL_NONE);
+ }
+
+ herring_touchkey_led_onoff(1);
+
+ register_early_suspend(&early_suspend);
+
+#ifdef CONFIG_GENERIC_BLN
+ register_bln_implementation(&herring_touchkey_bln);
+#endif
+#ifdef CONFIG_BLD
+ register_bld_implementation(&herring_touchkey_bld);
+#endif
+
+ return 0;
+
+err_req:
+ while (--i >= 0)
+ gpio_free(S5PV210_GPJ3(led_gpios[i]));
+ return ret;
+}
+
+device_initcall(herring_init_touchkey_led);
diff --git a/arch/arm/mach-s5pv210/herring-vibrator.c b/arch/arm/mach-s5pv210/herring-vibrator.c
new file mode 100644
index 0000000..82959f5
--- /dev/null
+++ b/arch/arm/mach-s5pv210/herring-vibrator.c
@@ -0,0 +1,167 @@
+/* arch/arm/mach-s5pv210/herring-vibrator.c
+ *
+ * Copyright (C) 2010 Samsung Electronics Co. Ltd. All Rights Reserved.
+ * Author: Rom Lemarchand <rlemarchand@sta.samsung.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/hrtimer.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/pwm.h>
+#include <linux/wakelock.h>
+#include <linux/mutex.h>
+#include <linux/clk.h>
+#include <linux/workqueue.h>
+
+#include <asm/mach-types.h>
+
+#include <../../../drivers/staging/android/timed_output.h>
+
+#include <mach/gpio-herring.h>
+
+#define GPD0_TOUT_1 2 << 4
+
+#define PWM_PERIOD (89284 / 2)
+#define PWM_DUTY (87280 / 2)
+#define MAX_TIMEOUT 10000 /* 10s */
+
+static struct vibrator {
+ struct wake_lock wklock;
+ struct pwm_device *pwm_dev;
+ struct hrtimer timer;
+ struct mutex lock;
+ struct work_struct work;
+} vibdata;
+
+#ifdef CONFIG_CPU_DIDLE
+static bool vibrator_running = false;
+
+bool vibrator_is_running(void)
+{
+ return vibrator_running;
+}
+EXPORT_SYMBOL(vibrator_is_running);
+#endif
+
+static void herring_vibrator_off(void)
+{
+ pwm_disable(vibdata.pwm_dev);
+ gpio_direction_output(GPIO_VIBTONE_EN1, GPIO_LEVEL_LOW);
+ wake_unlock(&vibdata.wklock);
+
+#ifdef CONFIG_CPU_DIDLE
+ vibrator_running = false;
+#endif
+}
+
+static int herring_vibrator_get_time(struct timed_output_dev *dev)
+{
+ if (hrtimer_active(&vibdata.timer)) {
+ ktime_t r = hrtimer_get_remaining(&vibdata.timer);
+ return ktime_to_ms(r);
+ }
+
+ return 0;
+}
+
+static void herring_vibrator_enable(struct timed_output_dev *dev, int value)
+{
+ mutex_lock(&vibdata.lock);
+
+ /* cancel previous timer and set GPIO according to value */
+ hrtimer_cancel(&vibdata.timer);
+ cancel_work_sync(&vibdata.work);
+ if (value) {
+#ifdef CONFIG_CPU_DIDLE
+ vibrator_running = true;
+#endif
+
+ wake_lock(&vibdata.wklock);
+ pwm_config(vibdata.pwm_dev, PWM_DUTY, PWM_PERIOD);
+ pwm_enable(vibdata.pwm_dev);
+ gpio_direction_output(GPIO_VIBTONE_EN1, GPIO_LEVEL_HIGH);
+
+ if (value > 0) {
+ if (value > MAX_TIMEOUT)
+ value = MAX_TIMEOUT;
+
+ hrtimer_start(&vibdata.timer,
+ ns_to_ktime((u64)value * NSEC_PER_MSEC),
+ HRTIMER_MODE_REL);
+ }
+ } else
+ herring_vibrator_off();
+
+ mutex_unlock(&vibdata.lock);
+}
+
+static struct timed_output_dev to_dev = {
+ .name = "vibrator",
+ .get_time = herring_vibrator_get_time,
+ .enable = herring_vibrator_enable,
+};
+
+static enum hrtimer_restart herring_vibrator_timer_func(struct hrtimer *timer)
+{
+ schedule_work(&vibdata.work);
+ return HRTIMER_NORESTART;
+}
+
+static void herring_vibrator_work(struct work_struct *work)
+{
+ herring_vibrator_off();
+}
+
+static int __init herring_init_vibrator(void)
+{
+ int ret = 0;
+
+#ifdef CONFIG_MACH_HERRING
+ if (!machine_is_herring())
+ return 0;
+#endif
+ hrtimer_init(&vibdata.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ vibdata.timer.function = herring_vibrator_timer_func;
+ INIT_WORK(&vibdata.work, herring_vibrator_work);
+
+ ret = gpio_request(GPIO_VIBTONE_EN1, "vibrator-en");
+ if (ret < 0)
+ return ret;
+
+ s3c_gpio_cfgpin(GPIO_VIBTONE_PWM, GPD0_TOUT_1);
+
+ vibdata.pwm_dev = pwm_request(1, "vibrator-pwm");
+ if (IS_ERR(vibdata.pwm_dev)) {
+ ret = PTR_ERR(vibdata.pwm_dev);
+ goto err_pwm_req;
+ }
+
+ wake_lock_init(&vibdata.wklock, WAKE_LOCK_SUSPEND, "vibrator");
+ mutex_init(&vibdata.lock);
+
+ ret = timed_output_dev_register(&to_dev);
+ if (ret < 0)
+ goto err_to_dev_reg;
+
+ return 0;
+
+err_to_dev_reg:
+ mutex_destroy(&vibdata.lock);
+ wake_lock_destroy(&vibdata.wklock);
+ pwm_free(vibdata.pwm_dev);
+err_pwm_req:
+ gpio_free(GPIO_VIBTONE_EN1);
+ return ret;
+}
+
+device_initcall(herring_init_vibrator);
diff --git a/arch/arm/mach-s5pv210/herring-watchdog.c b/arch/arm/mach-s5pv210/herring-watchdog.c
new file mode 100644
index 0000000..7ff9fee
--- /dev/null
+++ b/arch/arm/mach-s5pv210/herring-watchdog.c
@@ -0,0 +1,111 @@
+/* herring-watchdog.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <plat/regs-watchdog.h>
+#include <mach/map.h>
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/cpufreq.h>
+#include <linux/err.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/io.h>
+
+/* reset timeout in PCLK/256/128 (~2048:1s) */
+static unsigned watchdog_reset = (30 * 2048);
+
+/* pet timeout in jiffies */
+static unsigned watchdog_pet = (10 * HZ);
+
+static struct workqueue_struct *watchdog_wq;
+static void watchdog_workfunc(struct work_struct *work);
+static DECLARE_DELAYED_WORK(watchdog_work, watchdog_workfunc);
+
+static void watchdog_workfunc(struct work_struct *work)
+{
+ writel(watchdog_reset, S3C2410_WTCNT);
+ queue_delayed_work(watchdog_wq, &watchdog_work, watchdog_pet);
+}
+
+static void watchdog_start(void)
+{
+ unsigned int val;
+
+ /* set to PCLK / 256 / 128 */
+ val = S3C2410_WTCON_DIV128;
+ val |= S3C2410_WTCON_PRESCALE(255);
+ writel(val, S3C2410_WTCON);
+
+ /* program initial count */
+ writel(watchdog_reset, S3C2410_WTCNT);
+ writel(watchdog_reset, S3C2410_WTDAT);
+
+ /* start timer */
+ val |= S3C2410_WTCON_RSTEN | S3C2410_WTCON_ENABLE;
+ writel(val, S3C2410_WTCON);
+
+ /* make sure we're ready to pet the dog */
+ queue_delayed_work(watchdog_wq, &watchdog_work, watchdog_pet);
+}
+
+static void watchdog_stop(void)
+{
+ writel(0, S3C2410_WTCON);
+}
+
+static int watchdog_probe(struct platform_device *pdev)
+{
+ watchdog_wq = alloc_workqueue("pet_watchdog",
+ WQ_UNBOUND | WQ_HIGHPRI, 1);
+ watchdog_start();
+ return 0;
+}
+
+static int watchdog_suspend(struct device *dev)
+{
+ watchdog_stop();
+ return 0;
+}
+
+static int watchdog_resume(struct device *dev)
+{
+ watchdog_start();
+ return 0;
+}
+
+static struct dev_pm_ops watchdog_pm_ops = {
+ .suspend_noirq = watchdog_suspend,
+ .resume_noirq = watchdog_resume,
+};
+
+static struct platform_driver watchdog_driver = {
+ .probe = watchdog_probe,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "watchdog",
+ .pm = &watchdog_pm_ops,
+ },
+};
+
+static int __init watchdog_init(void)
+{
+ return platform_driver_register(&watchdog_driver);
+}
+
+module_init(watchdog_init);
diff --git a/arch/arm/mach-s5pv210/herring.h b/arch/arm/mach-s5pv210/herring.h
new file mode 100755
index 0000000..9f8622e
--- /dev/null
+++ b/arch/arm/mach-s5pv210/herring.h
@@ -0,0 +1,34 @@
+/*
+ * arch/arm/mach-s5pv210/herring.h
+ */
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+
+#ifndef __HERRING_H__
+#define __HERRING_H__
+
+struct uart_port;
+
+void herring_bt_uart_wake_peer(struct uart_port *port);
+extern void s3c_setup_uart_cfg_gpio(unsigned char port);
+
+#ifdef CONFIG_MACH_HERRING
+# define herring_is_cdma_wimax_dev() (machine_is_herring() && \
+ ((system_rev & 0xFFF0) == 0x20))
+# define herring_is_cdma_wimax_rev(n) (herring_is_cdma_wimax_dev() && \
+ (system_rev & 0xF) == ((n) & 0xF))
+# define herring_is_cdma_wimax_rev0() herring_is_cdma_wimax_rev(0)
+# define herring_is_tft_dev() (machine_is_herring() && (system_rev >= 0x30))
+#else
+# define herring_is_cdma_wimax_dev() (0)
+# define herring_is_cdma_wimax_rev0() (0)
+# define herring_is_cdma_wimax_rev(n) (0)
+# define herring_is_tft_dev() (0)
+#endif
+
+extern struct s5p_panel_data herring_panel_data;
+extern struct s5p_tft_panel_data herring_sony_panel_data;
+extern struct s5p_tft_panel_data herring_hydis_panel_data;
+extern struct s5p_tft_panel_data herring_hitachi_panel_data;
+#endif
diff --git a/arch/arm/mach-s5pv210/include/mach/adc.h b/arch/arm/mach-s5pv210/include/mach/adc.h
new file mode 100644
index 0000000..a0f703a
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/adc.h
@@ -0,0 +1,36 @@
+/* arch/arm/plat-s3c/include/plat/adc.h
+ *
+ * Copyright (c) 2008 Simtec Electronics
+ * http://armlinux.simnte.co.uk/
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_PLAT_ADC_H
+#define __ASM_PLAT_ADC_H __FILE__
+
+struct s3c_adc_request {
+ /* for linked list */
+ struct list_head *list;
+ /* after finish ADC sampling, s3c_adc_request function call this function with three parameter */
+ void (*callback)(int channel, unsigned long int param, unsigned short sample);
+ /* for private data */
+ unsigned long int param;
+ /* selected channel for ADC sampling */
+ int channel;
+};
+
+struct s3c_adc_mach_info {
+ /* if you need to use some platform data, add in here*/
+ int delay;
+ int presc;
+ int resolution;
+};
+
+extern int s3c_adc_get_adc_data(int channel);
+void __init s3c_adc_set_platdata(struct s3c_adc_mach_info *pd);
+
+#endif /* __ASM_PLAT_ADC_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/battery.h b/arch/arm/mach-s5pv210/include/mach/battery.h
new file mode 100644
index 0000000..b5f7339
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/battery.h
@@ -0,0 +1,13 @@
+#ifndef __BATTERY_H_
+#define __BATTERY_H_
+
+typedef enum
+{
+ PM_CHARGER_NULL,
+ PM_CHARGER_TA,
+ PM_CHARGER_USB_CABLE, //after enumeration
+ PM_CHARGER_USB_INSERT,// when usb is connected.
+ PM_CHARGER_DEFAULT
+} charging_device_type;
+
+#endif
diff --git a/arch/arm/mach-s5pv210/include/mach/cpu-freq-v210.h b/arch/arm/mach-s5pv210/include/mach/cpu-freq-v210.h
new file mode 100644
index 0000000..8274a01
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/cpu-freq-v210.h
@@ -0,0 +1,31 @@
+/* arch/arm/mach-s5pv210/include/mach/cpu-freq-v210.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *
+ * S5PV210/S5PC110 CPU frequency scaling support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_CPU_FREQ_H
+#define __ASM_ARCH_CPU_FREQ_H
+
+#include <linux/cpufreq.h>
+
+/* For cpu-freq driver */
+struct s5pv210_cpufreq_voltage {
+ unsigned int freq; /* kHz */
+ unsigned long varm; /* uV */
+ unsigned long vint; /* uV */
+};
+
+struct s5pv210_cpufreq_data {
+ struct s5pv210_cpufreq_voltage *volt;
+ unsigned int size;
+};
+
+extern void s5pv210_cpufreq_set_platdata(struct s5pv210_cpufreq_data *pdata);
+
+#endif /* __ASM_ARCH_CPU_FREQ_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/cpuidle.h b/arch/arm/mach-s5pv210/include/mach/cpuidle.h
new file mode 100644
index 0000000..7454ae4
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/cpuidle.h
@@ -0,0 +1,16 @@
+/* arch/arm/mach-s5pv210/include/mach/cpuidle.h
+ *
+ * Copyright 2010 Samsung Electronics
+ * Jaecheol Lee <jc.lee@samsung>
+ *
+ * S5PV210 - CPUIDLE support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+extern int s5pv210_didle_save(unsigned long *saveblk);
+extern void s5pv210_didle_resume(void);
+extern void i2sdma_getpos(dma_addr_t *src);
+extern unsigned int get_rtc_cnt(void);
diff --git a/arch/arm/mach-s5pv210/include/mach/gpio-herring.h b/arch/arm/mach-s5pv210/include/mach/gpio-herring.h
new file mode 100644
index 0000000..b55d0f0
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/gpio-herring.h
@@ -0,0 +1,603 @@
+#ifndef __GPIO_HERRING_H_
+#define __GPIO_HERRING_H_
+
+#define GPIO_LEVEL_LOW 0
+#define GPIO_LEVEL_HIGH 1
+#define GPIO_LEVEL_NONE 2
+#define GPIO_INPUT 0
+#define GPIO_OUTPUT 1
+
+#define GPIO_BT_UART_RXD S5PV210_GPA0(0)
+#define GPIO_BT_UART_RXD_AF 2
+
+#define GPIO_BT_UART_TXD S5PV210_GPA0(1)
+#define GPIO_BT_UART_TXD_AF 2
+
+#define GPIO_BT_UART_CTS S5PV210_GPA0(2)
+#define GPIO_BT_UART_CTS_AF 2
+
+#define GPIO_BT_UART_RTS S5PV210_GPA0(3)
+#define GPIO_BT_UART_RTS_AF 2
+
+#define GPIO_GPS_UART_RXD S5PV210_GPA0(4)
+#define GPIO_GPS_UART_RXD_AF 2
+
+#define GPIO_GPS_UART_TXD S5PV210_GPA0(5)
+#define GPIO_GPS_UART_TXD_AF 2
+
+#define GPIO_GPS_UART_CTS S5PV210_GPA0(6)
+#define GPIO_GPS_UART_CTS_AF 2
+
+#define GPIO_GPS_UART_RTS S5PV210_GPA0(7)
+#define GPIO_GPS_UART_RTS_AF 2
+
+#define GPIO_AP_RXD S5PV210_GPA1(0)
+#define GPIO_AP_RXD_AF 2
+
+#define GPIO_AP_TXD S5PV210_GPA1(1)
+#define GPIO_AP_TXD_AF 2
+
+#define GPIO_AP_FLM_RXD S5PV210_GPA1(2)
+#define GPIO_AP_FLM_RXD_AF 2
+
+#define GPIO_AP_FLM_TXD S5PV210_GPA1(3)
+#define GPIO_AP_FLM_TXD_AF 2
+
+#define GPIO_CAM_VGA_nSTBY S5PV210_GPB(0)
+
+#define GPIO_MSENSE_nRST S5PV210_GPB(1)
+
+#define GPIO_CAM_VGA_nRST S5PV210_GPB(2)
+
+#define GPIO_BT_nRST S5PV210_GPB(3)
+
+#define GPIO_BOOT_MODE S5PV210_GPB(4)
+
+#define GPIO_WLAN_BT_EN S5PV210_GPB(5)
+
+#define GPIO_GPB6 S5PV210_GPB(6)
+
+#define GPIO_GPB7 S5PV210_GPB(7)
+
+#define GPIO_REC_PCM_CLK S5PV210_GPC0(0)
+#define GPIO_REC_PCM_CLK_AF 3
+
+#define GPIO_GPC01 S5PV210_GPC0(1)
+
+#define GPIO_REC_PCM_SYNC S5PV210_GPC0(2)
+#define GPIO_REC_PCM_SYNC_AF 3
+
+#define GPIO_REC_PCM_IN S5PV210_GPC0(3)
+#define GPIO_REC_PCM_IN_AF 3
+
+#define GPIO_REC_PCM_OUT S5PV210_GPC0(4)
+#define GPIO_REC_PCM_OUT_AF 3
+
+#define GPIO_WIMAX_PM_SDA S5PV210_GPC1(0)
+
+#define GPIO_WIMAX_I2C_CON S5PV210_GPC1(1)
+
+#define GPIO_WIMAX_PM_SCL S5PV210_GPC1(2)
+
+#define GPIO_GPC13 S5PV210_GPC1(3)
+
+#define GPIO_GPC14 S5PV210_GPC1(4)
+
+#define GPIO_WIMAX_DBGEN_28V S5PV210_GPD0(0)
+
+#define GPIO_VIBTONE_PWM S5PV210_GPD0(1)
+
+#define GPIO_VIBTONE_PWM1 S5PV210_GPD0(2)
+
+#define GPIO_WIMAX_RESET_N S5PV210_GPD0(3)
+
+#define GPIO_CAM_SDA_29V S5PV210_GPD1(0)
+#define GPIO_CAM_SDA_29V_AF 2
+
+#define GPIO_CAM_SCL_29V S5PV210_GPD1(1)
+#define GPIO_CAM_SCL_29V_AF 2
+
+#define GYRO_SDA_28V S5PV210_GPD1(2)
+#define GYRO_SCL_28V S5PV210_GPD1(3)
+
+#define GPIO_TSP_SDA_28V S5PV210_GPD1(4)
+#define GPIO_TSP_SDA_28V_AF 2
+
+#define GPIO_TSP_SCL_28V S5PV210_GPD1(5)
+#define GPIO_TSP_SCL_28V_AF 2
+#define GPIO_CAM_PCLK S5PV210_GPE0(0)
+#define GPIO_CAM_PCLK_AF 2
+
+#define GPIO_CAM_VSYNC S5PV210_GPE0(1)
+#define GPIO_CAM_VSYNC_AF 2
+
+#define GPIO_CAM_HSYNC S5PV210_GPE0(2)
+#define GPIO_CAM_HSYNC_AF 2
+
+#define GPIO_CAM_D0 S5PV210_GPE0(3)
+#define GPIO_CAM_D0_AF 2
+
+#define GPIO_CAM_D1 S5PV210_GPE0(4)
+#define GPIO_CAM_D1_AF 2
+
+#define GPIO_CAM_D2 S5PV210_GPE0(5)
+#define GPIO_CAM_D2_AF 2
+
+#define GPIO_CAM_D3 S5PV210_GPE0(6)
+#define GPIO_CAM_D3_AF 2
+
+#define GPIO_CAM_D4 S5PV210_GPE0(7)
+#define GPIO_CAM_D4_AF 2
+
+#define GPIO_CAM_D5 S5PV210_GPE1(0)
+#define GPIO_CAM_D5_AF 2
+
+#define GPIO_CAM_D6 S5PV210_GPE1(1)
+#define GPIO_CAM_D6_AF 2
+
+#define GPIO_CAM_D7 S5PV210_GPE1(2)
+#define GPIO_CAM_D7_AF 2
+
+#define GPIO_CAM_MCLK S5PV210_GPE1(3)
+#define GPIO_CAM_MCLK_AF 2
+
+#define GPIO_GPE14 S5PV210_GPE1(4)
+
+#define GPIO_DISPLAY_HSYNC S5PV210_GPF0(0)
+#define GPIO_DISPLAY_HSYNC_AF 2
+
+#define GPIO_DISPLAY_VSYNC S5PV210_GPF0(1)
+#define GPIO_DISPLAY_VSYNC_AF 2
+
+#define GPIO_DISPLAY_DE S5PV210_GPF0(2)
+#define GPIO_DISPLAY_DE_AF 2
+
+#define GPIO_DISPLAY_PCLK S5PV210_GPF0(3)
+#define GPIO_DISPLAY_PCLK_AF 2
+
+#define GPIO_LCD_D0 S5PV210_GPF0(4)
+#define GPIO_LCD_D0_AF 2
+
+#define GPIO_LCD_D1 S5PV210_GPF0(5)
+#define GPIO_LCD_D1_AF 2
+
+#define GPIO_LCD_D2 S5PV210_GPF0(6)
+#define GPIO_LCD_D2_AF 2
+
+#define GPIO_LCD_D3 S5PV210_GPF0(7)
+#define GPIO_LCD_D3_AF 2
+
+#define GPIO_LCD_D4 S5PV210_GPF1(0)
+#define GPIO_LCD_D4_AF 2
+
+#define GPIO_LCD_D5 S5PV210_GPF1(1)
+#define GPIO_LCD_D5_AF 2
+
+#define GPIO_LCD_D6 S5PV210_GPF1(2)
+#define GPIO_LCD_D6_AF 2
+
+#define GPIO_LCD_D7 S5PV210_GPF1(3)
+#define GPIO_LCD_D7_AF 2
+
+#define GPIO_LCD_D8 S5PV210_GPF1(4)
+#define GPIO_LCD_D8_AF 2
+
+#define GPIO_LCD_D9 S5PV210_GPF1(5)
+#define GPIO_LCD_D9_AF 2
+
+#define GPIO_LCD_D10 S5PV210_GPF1(6)
+#define GPIO_LCD_D10_AF 2
+
+#define GPIO_LCD_D11 S5PV210_GPF1(7)
+#define GPIO_LCD_D11_AF 2
+
+#define GPIO_LCD_D12 S5PV210_GPF2(0)
+#define GPIO_LCD_D12_AF 2
+
+#define GPIO_LCD_D13 S5PV210_GPF2(1)
+#define GPIO_LCD_D13_AF 2
+
+#define GPIO_LCD_D14 S5PV210_GPF2(2)
+#define GPIO_LCD_D14_AF 2
+
+#define GPIO_LCD_D15 S5PV210_GPF2(3)
+#define GPIO_LCD_D15_AF 2
+
+#define GPIO_LCD_D16 S5PV210_GPF2(4)
+#define GPIO_LCD_D16_AF 2
+
+#define GPIO_LCD_D17 S5PV210_GPF2(5)
+#define GPIO_LCD_D17_AF 2
+
+#define GPIO_LCD_D18 S5PV210_GPF2(6)
+#define GPIO_LCD_D18_AF 2
+
+#define GPIO_LCD_D19 S5PV210_GPF2(7)
+#define GPIO_LCD_D19_AF 2
+
+#define GPIO_LCD_D20 S5PV210_GPF3(0)
+#define GPIO_LCD_D20_AF 2
+
+#define GPIO_LCD_D21 S5PV210_GPF3(1)
+#define GPIO_LCD_D21_AF 2
+
+#define GPIO_LCD_D22 S5PV210_GPF3(2)
+#define GPIO_LCD_D22_AF 2
+
+#define GPIO_LCD_D23 S5PV210_GPF3(3)
+#define GPIO_LCD_D23_AF 2
+
+#define GPIO_CODEC_LDO_EN S5PV210_GPF3(4)
+
+#define GPIO_GPF35 S5PV210_GPF3(5)
+
+#define GPIO_NAND_CLK S5PV210_GPG0(0)
+#define GPIO_NAND_CLK_AF 2
+
+#define GPIO_NAND_CMD S5PV210_GPG0(1)
+#define GPIO_NAND_CMD_AF 2
+
+#define GPIO_ALS_SCL_28V S5PV210_GPG0(2)
+
+#define GPIO_NAND_D0 S5PV210_GPG0(3)
+#define GPIO_NAND_D0_AF 2
+
+#define GPIO_NAND_D1 S5PV210_GPG0(4)
+#define GPIO_NAND_D1_AF 2
+
+#define GPIO_NAND_D2 S5PV210_GPG0(5)
+#define GPIO_NAND_D2_AF 2
+
+#define GPIO_NAND_D3 S5PV210_GPG0(6)
+#define GPIO_NAND_D3_AF 2
+
+#define GPIO_GPS_nRST S5PV210_GPG1(0)
+
+#define GPIO_GPS_PWR_EN S5PV210_GPG1(1)
+
+#define GPIO_WLAN_RST S5PV210_GPG1(2)
+
+#define GPIO_NAND_D4 S5PV210_GPG1(3)
+#define GPIO_NAND_D4_AF 3
+
+#define GPIO_NAND_D5 S5PV210_GPG1(4)
+#define GPIO_NAND_D5_AF 3
+
+#define GPIO_NAND_D6 S5PV210_GPG1(5)
+#define GPIO_NAND_D6_AF 3
+
+#define GPIO_NAND_D7 S5PV210_GPG1(6)
+#define GPIO_NAND_D7_AF 3
+
+#define GPIO_WIMAX_SDIO_CLK S5PV210_GPG2(0)
+
+#define GPIO_WIMAX_SDIO_CMD S5PV210_GPG2(1)
+
+#define GPIO_ALS_SDA_28V S5PV210_GPG2(2)
+
+#define GPIO_WIMAX_SDIO_D0 S5PV210_GPG2(3)
+
+#define GPIO_WIMAX_SDIO_D1 S5PV210_GPG2(4)
+
+#define GPIO_WIMAX_SDIO_D2 S5PV210_GPG2(5)
+
+#define GPIO_WIMAX_SDIO_D3 S5PV210_GPG2(6)
+
+#define GPIO_WLAN_SDIO_CLK S5PV210_GPG3(0)
+#define GPIO_WLAN_SDIO_CLK_AF 2
+
+#define GPIO_WLAN_SDIO_CMD S5PV210_GPG3(1)
+#define GPIO_WLAN_SDIO_CMD_AF 2
+
+#define GPIO_WLAN_nRST S5PV210_GPG3(2)
+#define GPIO_WLAN_nRST_AF 1
+
+#define GPIO_WLAN_SDIO_D0 S5PV210_GPG3(3)
+#define GPIO_WLAN_SDIO_D0_AF 2
+
+#define GPIO_WLAN_SDIO_D1 S5PV210_GPG3(4)
+#define GPIO_WLAN_SDIO_D1_AF 2
+
+#define GPIO_WLAN_SDIO_D2 S5PV210_GPG3(5)
+#define GPIO_WLAN_SDIO_D2_AF 2
+
+#define GPIO_WLAN_SDIO_D3 S5PV210_GPG3(6)
+#define GPIO_WLAN_SDIO_D3_AF 2
+
+#define GPIO_AP_PS_HOLD S5PV210_GPH0(0)
+
+#define GPIO_ACC_INT S5PV210_GPH0(1)
+
+#define GPIO_PS_VOUT S5PV210_GPH0(2)
+#define GPIO_PS_VOUT_AF 0xFF
+
+#define GPIO_BUCK_1_EN_A S5PV210_GPH0(3)
+
+#define GPIO_BUCK_1_EN_B S5PV210_GPH0(4)
+
+#define GPIO_BUCK_2_EN S5PV210_GPH0(5)
+#define GPIO_DET_35 S5PV210_GPH0(6)
+#define GPIO_DET_35_AF 0xFF
+
+#define GPIO_AP_PMIC_IRQ S5PV210_GPH0(7)
+#define GPIO_AP_PMIC_IRQ_AF 0xFF
+
+#define GPIO_WIMAX_EN S5PV210_GPH1(0)
+
+#define GPIO_PDA_ACTIVE S5PV210_GPH1(1)
+
+#define GPIO_WIMAX_WAKEUP S5PV210_GPH1(2)
+
+#define GPIO_nINT_ONEDRAM_AP S5PV210_GPH1(3)
+#define GPIO_nINT_ONEDRAM_AP_AF 0xF
+
+#define GPIO_GPH14 S5PV210_GPH1(4)
+
+#define GPIO_GPH15 S5PV210_GPH1(5)
+
+#define GPIO_GPH16 S5PV210_GPH1(6)
+
+#define GPIO_PHONE_ACTIVE S5PV210_GPH1(7)
+#define GPIO_PHONE_ACTIVE_AF 2
+
+#define GPIO_KBC0 S5PV210_GPH2(0)
+#define GPIO_KBC0_AF 3
+#define GPIO_KBC1 S5PV210_GPH2(1)
+#define GPIO_KBC1_AF 3
+#define GPIO_KBC2 S5PV210_GPH2(2)
+#define GPIO_KBC2_AF 3
+
+#define GPIO_BT_WAKE S5PV210_GPH2(2)
+#define GPIO_WLAN_WAKE S5PV210_GPH2(3)
+#define GPIO_WLAN_WAKE_AF 1
+
+#define GPIO_KBC_DATA (GPIO_KBC2 + 0x04)
+
+#define GPIO_WLAN_HOST_WAKE S5PV210_GPH2(4)
+#define GPIO_WLAN_HOST_WAKE_AF 0xF
+
+#define GPIO_BT_HOST_WAKE S5PV210_GPH2(5)
+#define GPIO_BT_HOST_WAKE_AF 0xF
+
+#define GPIO_nPOWER S5PV210_GPH2(6)
+
+#define GPIO_JACK_nINT S5PV210_GPH2(7)
+
+#define GPIO_TA_CURRENT_SEL_AP S5PV210_GPH3(0)
+
+#define GPIO_KBR1 S5PV210_GPH3(1)
+#define GPIO_KBR1_AF 3
+
+#define GPIO_KBR2 S5PV210_GPH3(2)
+#define GPIO_KBR2_AF 3
+
+#define GPIO_MSENSE_IRQ S5PV210_GPH3(3)
+
+#define GPIO_KBR_DATA (GPIO_KBR1 + 0x04)
+
+#define GPIO_T_FLASH_DETECT S5PV210_GPH3(4)
+
+/* EAR_SEN_END_OPEN */
+#define GPIO_OK_KEY S5PV210_GPH3(5)
+
+#define GPIO_EAR_SEND_END S5PV210_GPH3(6)
+#define GPIO_EAR_SEND_END_AF 0xFF
+#define GPIO_CP_RST S5PV210_GPH3(7)
+
+#define GPIO_CODEC_I2S_CLK S5PV210_GPI(0)
+#define GPIO_CODEC_I2S_CLK_AF 2
+
+#define GPIO_GPI1 S5PV210_GPI(1)
+
+#define GPIO_CODEC_I2S_WS S5PV210_GPI(2)
+#define GPIO_CODEC_I2S_WS_AF 2
+
+#define GPIO_CODEC_I3S_DI S5PV210_GPI(3)
+#define GPIO_CODEC_I3S_DI_AF 2
+
+#define GPIO_CODEC_I3S_DO S5PV210_GPI(4)
+#define GPIO_CODEC_I3S_DO_AF 2
+
+#define GPIO_GPI5 S5PV210_GPI(5)
+
+#define GPIO_GPI6 S5PV210_GPI(6)
+
+#define GPIO_MSENSE_SCL_28V S5PV210_GPJ0(0)
+#define GPIO_MSENSE_SDA_28V S5PV210_GPJ0(1)
+
+#define GPIO_HWREV_MODE0 S5PV210_GPJ0(2)
+#define GPIO_HWREV_MODE1 S5PV210_GPJ0(3)
+#define GPIO_HWREV_MODE2 S5PV210_GPJ0(4)
+
+#define GPIO_TOUCH_INT S5PV210_GPJ0(5)
+
+#define GPIO_CAM_MEGA_EN S5PV210_GPJ0(6)
+
+#define GPIO_HWREV_MODE3 S5PV210_GPJ0(7)
+
+#define GPIO_CAM_FLASH_EN_SET S5PV210_GPJ1(0)
+
+#define GPIO_VIBTONE_EN1 S5PV210_GPJ1(1)
+
+#define GPIO_USB_HS_SEL S5PV210_GPJ2(0)
+#define GPIO_PHONE_ON S5PV210_GPJ2(1)
+
+#define GPIO_EAR_SEL S5PV210_GPJ2(3)
+#define GPIO_UART_SEL1 S5PV210_GPJ2(4)
+
+#define GPIO_FLASH_EN S5PV210_GPJ1(2)
+#define GPIO_TOUCH_EN S5PV210_GPJ1(3)
+#define GPIO_TOUCH_EN_AF 1
+
+#define GPIO_PS_ON S5PV210_GPJ1(4)
+
+#define GPIO_CAM_MEGA_nRST S5PV210_GPJ1(5)
+
+#define GPIO_OLED_DET S5PV210_GPJ2(2)
+
+#define GPIO_EAR_SEL S5PV210_GPJ2(3)
+#define GPIO_FM_INT S5PV210_GPJ2(4)
+#define GPIO_FM_RST S5PV210_GPJ2(5)
+#define GPIO_TV_OUT_SEL S5PV210_GPJ2(6)
+
+#define GPIO_MASSMEMORY_EN S5PV210_GPJ2(7)
+
+#define _3_TOUCH_SDA_28V S5PV210_GPJ3(0)
+#define _3_TOUCH_SCL_28V S5PV210_GPJ3(1)
+#define _3_GPIO_TOUCH_EN S5PV210_GPJ3(2)
+#define _3_GPIO_TOUCH_EN_AF 1
+#define GPIO_EAR_ADC_SEL S5PV210_GPJ3(3)
+#define GPIO_EAR_ADC_SEL_AF 1
+
+#define GPIO_USB_SDA_28V S5PV210_GPJ3(4)
+
+#define GPIO_USB_SCL_28V S5PV210_GPJ3(5)
+
+#define GPIO_AP_SDA_28V S5PV210_GPJ3(6)
+
+#define GPIO_AP_SCL_28V S5PV210_GPJ3(7)
+#define GPIO_AP_PMIC_SDA S5PV210_GPJ4(0)
+
+#define _3_GPIO_TOUCH_INT S5PV210_GPJ4(1)
+#define _3_GPIO_TOUCH_INT_AF 0xFF
+#define GPIO_MICBIAS_EN S5PV210_GPJ4(2)
+
+#define GPIO_AP_PMIC_SCL S5PV210_GPJ4(3)
+
+#define GPIO_EAR_MICBIAS_EN S5PV210_GPJ4(4)
+
+#define GPIO_MP010 S5PV210_MP01(0)
+
+#define GPIO_DISPLAY_CS S5PV210_MP01(1)
+
+#define GPIO_WIMAX_CON0 S5PV210_MP01(2)
+
+#define GPIO_OLED_ID S5PV210_MP01(3)
+
+#define GPIO_AP_NANDCS S5PV210_MP01(4)
+#define GPIO_AP_NANDCS_AF 5
+
+#define GPIO_DIC_ID S5PV210_MP01(5)
+
+#define GPIO_MP016 S5PV210_MP01(6)
+
+#define GPIO_MP017 S5PV210_MP01(7)
+
+#define GPIO_MP020 S5PV210_MP02(0)
+
+#define GPIO_MP021 S5PV210_MP02(1)
+
+#define GPIO_VCC_19V_PDA S5PV210_MP02(2)
+
+#define GPIO_MP023 S5PV210_MP02(3)
+
+#define GPIO_MP030 S5PV210_MP03(0)
+
+#define GPIO_MP031 S5PV210_MP03(1)
+
+#define GPIO_MP032 S5PV210_MP03(2)
+
+#define GPIO_MP033 S5PV210_MP03(3)
+
+#define GPIO_VCC_18V_PDA S5PV210_MP03(4)
+
+#define GPIO_CP_nRST S5PV210_MP03(5)
+
+#define GPIO_MP036 S5PV210_MP03(6)
+
+#define GPIO_PCM_SEL S5PV210_MP03(7)
+
+#define GPIO_USB_SEL S5PV210_MP04(0)
+
+#define GPIO_DISPLAY_CLK S5PV210_MP04(1)
+
+#define GPIO_WIMAX_IF_MODE0 S5PV210_MP04(2)
+
+#define GPIO_DISPLAY_SI S5PV210_MP04(3)
+
+#define GPIO_MP044 S5PV210_MP04(4)
+
+#define GPIO_LVDS_RST S5PV210_MP04(5)
+
+#define GPIO_GPS_CLK_EN S5PV210_MP04(6)
+
+#define GPIO_WIMAX_CON1 S5PV210_MP04(7)
+
+#define FUEL_SCL_18V S5PV210_MP05(0)
+#define FUEL_SDA_18V S5PV210_MP05(1)
+
+#define GPIO_AP_SCL_18V S5PV210_MP05(2)
+
+#define GPIO_AP_SDA_18V S5PV210_MP05(3)
+
+#define GPIO_WIMAX_IF_MODE1 S5PV210_MP05(4)
+
+#define GPIO_MLCD_RST S5PV210_MP05(5)
+
+#define GPIO_WIMAX_CON2 S5PV210_MP05(6)
+
+#define GPIO_UART_SEL S5PV210_MP05(7)
+
+#define GPOI_WIMAX_WAKEUP S5PV210_MP06(5)
+
+#define AP_I2C_SDA S5PV210_MP05(3)
+#define AP_I2C_SCL S5PV210_MP05(2)
+#define AP_I2C_SDA_28V S5PV210_GPJ3(6)
+#define AP_I2C_SCL_28V S5PV210_GPJ3(7)
+
+#define NFC_SCL_18V S5PV210_MP04(4)
+#define NFC_SDA_18V S5PV210_MP04(5)
+#define NFC_IRQ S5PV210_GPH1(4)
+#define NFC_EN S5PV210_GPH1(5)
+#define NFC_FIRM S5PV210_GPH1(6)
+
+#define PMIC_I2C_SDA S5PV210_GPJ4(0)
+#define PMIC_I2C_SCL S5PV210_GPJ4(3)
+
+#define GPIO_TOUCH_INT S5PV210_GPJ0(5)
+#define GPIO_TOUCH_INT_AF 0xFF
+
+#define GPIO_TOUCH_RST S5PV210_GPB(6)
+#define GPIO_TOUCH_ST_AF 1
+
+#define GPIO_BT_RXD S5PV210_GPA0(0)
+#define GPIO_BT_RXD_AF 2
+#define GPIO_BT_TXD S5PV210_GPA0(1)
+#define GPIO_BT_TXD_AF 2
+#define GPIO_BT_CTS S5PV210_GPA0(2)
+#define GPIO_BT_CTS_AF 2
+#define GPIO_BT_RTS S5PV210_GPA0(3)
+#define GPIO_BT_RTS_AF 2
+
+#define GPIO_GPS_RXD S5PV210_GPA0(4)
+#define GPIO_GPS_RXD_AF 2
+#define GPIO_GPS_TXD S5PV210_GPA0(5)
+#define GPIO_GPS_TXD_AF 2
+#define GPIO_GPS_CTS S5PV210_GPA0(6)
+#define GPIO_GPS_CTS_AF 2
+#define GPIO_GPS_RTS S5PV210_GPA0(7)
+#define GPIO_GPS_RTS_AF 2
+
+#define GPIO_AP_RXD S5PV210_GPA1(0)
+#define GPIO_AP_RXD_AF 2
+#define GPIO_AP_TXD S5PV210_GPA1(1)
+#define GPIO_AP_TXD_AF 2
+
+#define GPIO_FLM_RXD S5PV210_GPA1(2)
+#define GPIO_FLM_RXD_AF 2
+#define GPIO_FLM_TXD S5PV210_GPA1(3)
+#define GPIO_FLM_TXD_AF 2
+
+#define GPIO_AP_PS_HOLD S5PV210_GPH0(0)
+#define GPIO_AP_PS_HOLD_AF 1
+
+#define GPIO_N_POWER S5PV210_GPH2(6)
+#define GPIO_N_POWER_AF 2
+
+#define GPIO_JACK_INT_N S5PV210_GPH2(7)
+#define GPIO_JACK_INT_N_AF 0xFF
+
+#define _3_GPIO_TOUCH_CE S5PV210_GPJ3(3)
+#endif
+/* end of __GPIO_HERRING_H_ */
+
diff --git a/arch/arm/mach-s5pv210/include/mach/gpio.h b/arch/arm/mach-s5pv210/include/mach/gpio.h
index a5a1e33..16b38f1 100644
--- a/arch/arm/mach-s5pv210/include/mach/gpio.h
+++ b/arch/arm/mach-s5pv210/include/mach/gpio.h
@@ -54,6 +54,34 @@
#define S5PV210_GPIO_MP03_NR (8)
#define S5PV210_GPIO_MP04_NR (8)
#define S5PV210_GPIO_MP05_NR (8)
+#define S5PV210_GPIO_MP06_NR (8)
+#define S5PV210_GPIO_MP07_NR (8)
+
+#define S5PV210_GPIO_MP10_NR (8)
+#define S5PV210_GPIO_MP11_NR (8)
+#define S5PV210_GPIO_MP12_NR (8)
+#define S5PV210_GPIO_MP13_NR (8)
+#define S5PV210_GPIO_MP14_NR (8)
+#define S5PV210_GPIO_MP15_NR (8)
+#define S5PV210_GPIO_MP16_NR (8)
+#define S5PV210_GPIO_MP17_NR (8)
+#define S5PV210_GPIO_MP18_NR (7)
+
+#define S5PV210_GPIO_MP20_NR (8)
+#define S5PV210_GPIO_MP21_NR (8)
+#define S5PV210_GPIO_MP22_NR (8)
+#define S5PV210_GPIO_MP23_NR (8)
+#define S5PV210_GPIO_MP24_NR (8)
+#define S5PV210_GPIO_MP25_NR (8)
+#define S5PV210_GPIO_MP26_NR (8)
+#define S5PV210_GPIO_MP27_NR (8)
+#define S5PV210_GPIO_MP28_NR (7)
+
+#define S5PV210_GPIO_ETC0_NR (6)
+#define S5PV210_GPIO_ETC1_NR (8)
+#define S5PV210_GPIO_ETC2_NR (8)
+#define S5PV210_GPIO_ETC4_NR (6)
+
/* GPIO bank numbers */
@@ -98,6 +126,30 @@ enum s5p_gpio_number {
S5PV210_GPIO_MP03_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP02),
S5PV210_GPIO_MP04_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP03),
S5PV210_GPIO_MP05_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP04),
+ S5PV210_GPIO_MP06_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP05),
+ S5PV210_GPIO_MP07_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP06),
+ S5PV210_GPIO_MP10_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP07),
+ S5PV210_GPIO_MP11_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP10),
+ S5PV210_GPIO_MP12_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP11),
+ S5PV210_GPIO_MP13_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP12),
+ S5PV210_GPIO_MP14_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP13),
+ S5PV210_GPIO_MP15_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP14),
+ S5PV210_GPIO_MP16_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP15),
+ S5PV210_GPIO_MP17_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP16),
+ S5PV210_GPIO_MP18_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP17),
+ S5PV210_GPIO_MP20_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP18),
+ S5PV210_GPIO_MP21_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP20),
+ S5PV210_GPIO_MP22_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP21),
+ S5PV210_GPIO_MP23_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP22),
+ S5PV210_GPIO_MP24_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP23),
+ S5PV210_GPIO_MP25_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP24),
+ S5PV210_GPIO_MP26_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP25),
+ S5PV210_GPIO_MP27_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP26),
+ S5PV210_GPIO_MP28_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP27),
+ S5PV210_GPIO_ETC0_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP28),
+ S5PV210_GPIO_ETC1_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_ETC0),
+ S5PV210_GPIO_ETC2_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_ETC1),
+ S5PV210_GPIO_ETC4_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_ETC2),
};
/* S5PV210 GPIO number definitions */
@@ -133,15 +185,69 @@ enum s5p_gpio_number {
#define S5PV210_MP03(_nr) (S5PV210_GPIO_MP03_START + (_nr))
#define S5PV210_MP04(_nr) (S5PV210_GPIO_MP04_START + (_nr))
#define S5PV210_MP05(_nr) (S5PV210_GPIO_MP05_START + (_nr))
+#define S5PV210_MP06(_nr) (S5PV210_GPIO_MP06_START + (_nr))
+#define S5PV210_MP07(_nr) (S5PV210_GPIO_MP07_START + (_nr))
+#define S5PV210_MP10(_nr) (S5PV210_GPIO_MP10_START + (_nr))
+#define S5PV210_MP11(_nr) (S5PV210_GPIO_MP11_START + (_nr))
+#define S5PV210_MP12(_nr) (S5PV210_GPIO_MP12_START + (_nr))
+#define S5PV210_MP13(_nr) (S5PV210_GPIO_MP13_START + (_nr))
+#define S5PV210_MP14(_nr) (S5PV210_GPIO_MP14_START + (_nr))
+#define S5PV210_MP15(_nr) (S5PV210_GPIO_MP15_START + (_nr))
+#define S5PV210_MP16(_nr) (S5PV210_GPIO_MP16_START + (_nr))
+#define S5PV210_MP17(_nr) (S5PV210_GPIO_MP17_START + (_nr))
+#define S5PV210_MP18(_nr) (S5PV210_GPIO_MP18_START + (_nr))
+#define S5PV210_MP20(_nr) (S5PV210_GPIO_MP20_START + (_nr))
+#define S5PV210_MP21(_nr) (S5PV210_GPIO_MP21_START + (_nr))
+#define S5PV210_MP22(_nr) (S5PV210_GPIO_MP22_START + (_nr))
+#define S5PV210_MP23(_nr) (S5PV210_GPIO_MP23_START + (_nr))
+#define S5PV210_MP24(_nr) (S5PV210_GPIO_MP24_START + (_nr))
+#define S5PV210_MP25(_nr) (S5PV210_GPIO_MP25_START + (_nr))
+#define S5PV210_MP26(_nr) (S5PV210_GPIO_MP26_START + (_nr))
+#define S5PV210_MP27(_nr) (S5PV210_GPIO_MP27_START + (_nr))
+#define S5PV210_MP28(_nr) (S5PV210_GPIO_MP28_START + (_nr))
+#define S5PV210_ETC0(_nr) (S5PV210_GPIO_ETC0_START + (_nr))
+#define S5PV210_ETC1(_nr) (S5PV210_GPIO_ETC1_START + (_nr))
+#define S5PV210_ETC2(_nr) (S5PV210_GPIO_ETC2_START + (_nr))
+#define S5PV210_ETC4(_nr) (S5PV210_GPIO_ETC4_START + (_nr))
+
+/* Define EXT INT GPIO */
+#define S5P_EXT_INT0(x) S5PV210_GPH0(x)
+#define S5P_EXT_INT1(x) S5PV210_GPH1(x)
+#define S5P_EXT_INT2(x) S5PV210_GPH2(x)
+#define S5P_EXT_INT3(x) S5PV210_GPH3(x)
/* the end of the S5PV210 specific gpios */
-#define S5PV210_GPIO_END (S5PV210_MP05(S5PV210_GPIO_MP05_NR) + 1)
+#define S5PV210_GPIO_END (S5PV210_ETC4(S5PV210_GPIO_ETC4_NR) + 1)
#define S3C_GPIO_END S5PV210_GPIO_END
-/* define the number of gpios we need to the one after the MP05() range */
-#define ARCH_NR_GPIOS (S5PV210_MP05(S5PV210_GPIO_MP05_NR) + \
+/* define the number of gpios we need to the one after the GPJ4() range */
+#define ARCH_NR_GPIOS (S5PV210_ETC4(S5PV210_GPIO_ETC4_NR) + \
CONFIG_SAMSUNG_GPIO_EXTRA + 1)
#include <asm-generic/gpio.h>
+#include <plat/gpio-cfg.h>
+
+extern int s3c_gpio_slp_cfgpin(unsigned int pin, unsigned int to);
+extern s3c_gpio_pull_t s3c_gpio_get_slp_cfgpin(unsigned int pin);
+
+#define S3C_GPIO_SLP_OUT0 ((__force s3c_gpio_pull_t)0x00)
+#define S3C_GPIO_SLP_OUT1 ((__force s3c_gpio_pull_t)0x01)
+#define S3C_GPIO_SLP_INPUT ((__force s3c_gpio_pull_t)0x02)
+#define S3C_GPIO_SLP_PREV ((__force s3c_gpio_pull_t)0x03)
+
+extern int s3c_gpio_set_drvstrength(unsigned int pin, unsigned int config);
+extern int s3c_gpio_set_slewrate(unsigned int pin, unsigned int config);
+
+#define S3C_GPIO_DRVSTR_1X (0)
+#define S3C_GPIO_DRVSTR_2X (1)
+#define S3C_GPIO_DRVSTR_3X (2)
+#define S3C_GPIO_DRVSTR_4X (3)
+
+#define S3C_GPIO_SLEWRATE_FAST (0)
+#define S3C_GPIO_SLEWRATE_SLOW (1)
+
+extern int s3c_gpio_slp_setpull_updown(unsigned int pin, s3c_gpio_pull_t pull);
+extern int s5pv210_gpiolib_init(void);
+
#endif /* __ASM_ARCH_GPIO_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/irqs.h b/arch/arm/mach-s5pv210/include/mach/irqs.h
index b9f9ec3..b747128 100644
--- a/arch/arm/mach-s5pv210/include/mach/irqs.h
+++ b/arch/arm/mach-s5pv210/include/mach/irqs.h
@@ -17,6 +17,22 @@
/* VIC0: System, DMA, Timer */
+#define IRQ_EINT0 S5P_IRQ_VIC0(0)
+#define IRQ_EINT1 S5P_IRQ_VIC0(1)
+#define IRQ_EINT2 S5P_IRQ_VIC0(2)
+#define IRQ_EINT3 S5P_IRQ_VIC0(3)
+#define IRQ_EINT4 S5P_IRQ_VIC0(4)
+#define IRQ_EINT5 S5P_IRQ_VIC0(5)
+#define IRQ_EINT6 S5P_IRQ_VIC0(6)
+#define IRQ_EINT7 S5P_IRQ_VIC0(7)
+#define IRQ_EINT8 S5P_IRQ_VIC0(8)
+#define IRQ_EINT9 S5P_IRQ_VIC0(9)
+#define IRQ_EINT10 S5P_IRQ_VIC0(10)
+#define IRQ_EINT11 S5P_IRQ_VIC0(11)
+#define IRQ_EINT12 S5P_IRQ_VIC0(12)
+#define IRQ_EINT13 S5P_IRQ_VIC0(13)
+#define IRQ_EINT14 S5P_IRQ_VIC0(14)
+#define IRQ_EINT15 S5P_IRQ_VIC0(15)
#define IRQ_EINT16_31 S5P_IRQ_VIC0(16)
#define IRQ_BATF S5P_IRQ_VIC0(17)
#define IRQ_MDMA S5P_IRQ_VIC0(18)
@@ -116,17 +132,19 @@
#define IRQ_MDNIE1 S5P_IRQ_VIC3(6)
#define IRQ_MDNIE2 S5P_IRQ_VIC3(7)
#define IRQ_MDNIE3 S5P_IRQ_VIC3(8)
+#define IRQ_ADC1 S5P_IRQ_VIC3(9)
+#define IRQ_PENDN1 S5P_IRQ_VIC3(10)
#define IRQ_VIC_END S5P_IRQ_VIC3(31)
#define S5P_EINT_BASE1 (S5P_IRQ_VIC0(0))
#define S5P_EINT_BASE2 (IRQ_VIC_END + 1)
+#define S5P_IRQ_EINT_BASE S5P_EINT_BASE2
/* GPIO interrupt */
#define S5P_GPIOINT_BASE (IRQ_EINT(31) + 1)
#define S5P_GPIOINT_GROUP_MAXNR 22
-/* Set the default NR_IRQS */
-#define NR_IRQS (IRQ_EINT(31) + S5P_GPIOINT_COUNT + 1)
+#define S5P_EINT(x) ((x) + S5P_IRQ_EINT_BASE)
/* Compatibility */
#define IRQ_LCD_FIFO IRQ_LCD0
@@ -134,4 +152,73 @@
#define IRQ_LCD_SYSTEM IRQ_LCD2
#define IRQ_MIPI_CSIS0 IRQ_MIPI_CSIS
+/* Next the external interrupt groups. These are similar to the IRQ_EINT(x)
+ * that they are sourced from the GPIO pins but with a different scheme for
+ * priority and source indication.
+ *
+ * The IRQ_EINT(x) can be thought of as 'group 0' of the available GPIO
+ * interrupts, but for historical reasons they are kept apart from these
+ * next interrupts.
+ *
+ * Use IRQ_EINT_GROUP(group, offset) to get the number for use in the
+ * machine specific support files.
+ */
+
+#define IRQ_EINT_GROUP1_NR (8) /* A0 */
+#define IRQ_EINT_GROUP2_NR (4) /* A1 */
+#define IRQ_EINT_GROUP3_NR (8) /* B */
+#define IRQ_EINT_GROUP4_NR (5) /* C0 */
+#define IRQ_EINT_GROUP5_NR (5) /* C1 */
+#define IRQ_EINT_GROUP6_NR (4) /* D0 */
+#define IRQ_EINT_GROUP7_NR (6) /* D1 */
+#define IRQ_EINT_GROUP8_NR (8) /* E0 */
+#define IRQ_EINT_GROUP9_NR (5) /* E1 */
+#define IRQ_EINT_GROUP10_NR (8) /* F0 */
+#define IRQ_EINT_GROUP11_NR (8) /* F1 */
+#define IRQ_EINT_GROUP12_NR (8) /* F2 */
+#define IRQ_EINT_GROUP13_NR (6) /* F3 */
+#define IRQ_EINT_GROUP14_NR (7) /* G0 */
+#define IRQ_EINT_GROUP15_NR (7) /* G1 */
+#define IRQ_EINT_GROUP16_NR (7) /* G2 */
+#define IRQ_EINT_GROUP17_NR (7) /* G3 */
+#define IRQ_EINT_GROUP18_NR (8) /* J0 */
+#define IRQ_EINT_GROUP19_NR (6) /* J1 */
+#define IRQ_EINT_GROUP20_NR (8) /* J2 */
+#define IRQ_EINT_GROUP21_NR (8) /* J3 */
+#define IRQ_EINT_GROUP22_NR (5) /* J4 */
+
+#define IRQ_EINT_GROUP_BASE S5P_EINT(31 + 1)
+#define IRQ_EINT_GROUP1_BASE (IRQ_EINT_GROUP_BASE + 0x00)
+#define IRQ_EINT_GROUP2_BASE (IRQ_EINT_GROUP1_BASE + IRQ_EINT_GROUP1_NR)
+#define IRQ_EINT_GROUP3_BASE (IRQ_EINT_GROUP2_BASE + IRQ_EINT_GROUP2_NR)
+#define IRQ_EINT_GROUP4_BASE (IRQ_EINT_GROUP3_BASE + IRQ_EINT_GROUP3_NR)
+#define IRQ_EINT_GROUP5_BASE (IRQ_EINT_GROUP4_BASE + IRQ_EINT_GROUP4_NR)
+#define IRQ_EINT_GROUP6_BASE (IRQ_EINT_GROUP5_BASE + IRQ_EINT_GROUP5_NR)
+#define IRQ_EINT_GROUP7_BASE (IRQ_EINT_GROUP6_BASE + IRQ_EINT_GROUP6_NR)
+#define IRQ_EINT_GROUP8_BASE (IRQ_EINT_GROUP7_BASE + IRQ_EINT_GROUP7_NR)
+#define IRQ_EINT_GROUP9_BASE (IRQ_EINT_GROUP8_BASE + IRQ_EINT_GROUP8_NR)
+#define IRQ_EINT_GROUP10_BASE (IRQ_EINT_GROUP9_BASE + IRQ_EINT_GROUP9_NR)
+#define IRQ_EINT_GROUP11_BASE (IRQ_EINT_GROUP10_BASE + IRQ_EINT_GROUP10_NR)
+#define IRQ_EINT_GROUP12_BASE (IRQ_EINT_GROUP11_BASE + IRQ_EINT_GROUP11_NR)
+#define IRQ_EINT_GROUP13_BASE (IRQ_EINT_GROUP12_BASE + IRQ_EINT_GROUP12_NR)
+#define IRQ_EINT_GROUP14_BASE (IRQ_EINT_GROUP13_BASE + IRQ_EINT_GROUP13_NR)
+#define IRQ_EINT_GROUP15_BASE (IRQ_EINT_GROUP14_BASE + IRQ_EINT_GROUP14_NR)
+#define IRQ_EINT_GROUP16_BASE (IRQ_EINT_GROUP15_BASE + IRQ_EINT_GROUP15_NR)
+#define IRQ_EINT_GROUP17_BASE (IRQ_EINT_GROUP16_BASE + IRQ_EINT_GROUP16_NR)
+#define IRQ_EINT_GROUP18_BASE (IRQ_EINT_GROUP17_BASE + IRQ_EINT_GROUP17_NR)
+#define IRQ_EINT_GROUP19_BASE (IRQ_EINT_GROUP18_BASE + IRQ_EINT_GROUP18_NR)
+#define IRQ_EINT_GROUP20_BASE (IRQ_EINT_GROUP19_BASE + IRQ_EINT_GROUP19_NR)
+#define IRQ_EINT_GROUP21_BASE (IRQ_EINT_GROUP20_BASE + IRQ_EINT_GROUP20_NR)
+#define IRQ_EINT_GROUP22_BASE (IRQ_EINT_GROUP21_BASE + IRQ_EINT_GROUP21_NR)
+
+#define IRQ_EINT_GROUP(group, no) (IRQ_EINT_GROUP##group##_BASE + (no))
+
+/* Set the default NR_IRQS */
+//#define NR_IRQS (IRQ_EINT(31) + 1)
+#define NR_IRQS (IRQ_EINT_GROUP22_BASE + IRQ_EINT_GROUP22_NR + 1)
+
+#define HALL_SENSOR_IRQ IRQ_EINT3
+
+#define FIQ_START 0
+
#endif /* ASM_ARCH_IRQS_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/map.h b/arch/arm/mach-s5pv210/include/mach/map.h
index 1dd5883..704e192 100644
--- a/arch/arm/mach-s5pv210/include/mach/map.h
+++ b/arch/arm/mach-s5pv210/include/mach/map.h
@@ -16,7 +16,11 @@
#include <plat/map-base.h>
#include <plat/map-s5p.h>
-#define S5PV210_PA_SDRAM 0x20000000
+#if defined(CONFIG_MACH_SMDKV210)
+#define S5PV210_PA_SDRAM (0x20000000)
+#else
+#define S5PV210_PA_SDRAM (0x30000000)
+#endif
#define S5PV210_PA_SROM_BANK5 0xA8000000
@@ -53,6 +57,9 @@
#define S5PV210_PA_WATCHDOG 0xE2700000
#define S5PV210_PA_RTC 0xE2800000
+#define S5PV210_VA_RTC S3C_ADDR(0x00c00000)
+#define S5P_VA_RTC S5PV210_VA_RTC
+
#define S5PV210_PA_UART 0xE2900000
#define S5PV210_PA_SROMC 0xE8000000
@@ -61,9 +68,27 @@
#define S5PV210_PA_HSMMC(x) (0xEB000000 + ((x) * 0x100000))
+/* usb */
+#define S5PV210_PA_OTG (0xEC000000)
+#define S5PV210_SZ_OTG SZ_1M
+
+#define S5PV210_PA_OTGSFR (0xEC100000)
+#define S5PV210_SZ_OTGSFR SZ_1M
+
+#define S5PV210_PA_USB_EHCI (0xEC200000)
+#define S5P_PA_USB_EHCI S5PV210_PA_USB_EHCI
+#define S5P_SZ_USB_EHCI SZ_1M
+
+#define S5PV210_PA_USB_OHCI (0xEC300000)
+#define S5P_PA_USB_OHCI S5PV210_PA_USB_OHCI
+#define S5P_SZ_USB_OHCI SZ_1M
+/* end usb */
+
#define S5PV210_PA_HSOTG 0xEC000000
#define S5PV210_PA_HSPHY 0xEC100000
+#define S5PV210_PA_AUDSS (0xEEE10000)
+
#define S5PV210_PA_IIS0 0xEEE30000
#define S5PV210_PA_IIS1 0xE2100000
#define S5PV210_PA_IIS2 0xE2A00000
@@ -71,6 +96,31 @@
#define S5PV210_PA_DMC0 0xF0000000
#define S5PV210_PA_DMC1 0xF1400000
+#define S5P_VA_VIC0 (S3C_VA_IRQ + 0x0)
+#define S5P_VA_VIC1 (S3C_VA_IRQ + 0x10000)
+#define S5P_VA_VIC2 (S3C_VA_IRQ + 0x20000)
+#define S5P_VA_VIC3 (S3C_VA_IRQ + 0x30000)
+
+#define S5PV210_PA_LCD (0xF8000000)
+#define S5P_PA_LCD S5PV210_PA_LCD
+#define S5PV210_SZ_LCD SZ_1M
+#define S5P_SZ_LCD S5PV210_SZ_LCD
+
+#define S5PV210_PA_JPEG (0xFB600000)
+#define S5PV210_SZ_JPEG SZ_1M
+
+#define S5PV210_SZ_FIMC0 SZ_1M
+#define S5P_SZ_FIMC0 S5PV210_SZ_FIMC0
+#define S5PV210_SZ_FIMC1 SZ_1M
+#define S5P_SZ_FIMC1 S5PV210_SZ_FIMC1
+#define S5PV210_SZ_FIMC2 SZ_1M
+#define S5P_SZ_FIMC2 S5PV210_SZ_FIMC2
+
+#define S5PV210_PA_IPC (0xFB700000)
+#define S5P_PA_IPC S5PV210_PA_IPC
+#define S5PV210_SZ_IPC SZ_1M
+#define S5P_SZ_IPC S5PV210_SZ_IPC
+
#define S5PV210_PA_VIC0 0xF2000000
#define S5PV210_PA_VIC1 0xF2100000
#define S5PV210_PA_VIC2 0xF2200000
@@ -88,6 +138,28 @@
#define S5PV210_PA_FIMC1 0xFB300000
#define S5PV210_PA_FIMC2 0xFB400000
+/* mfc */
+#define S5PV210_PA_MFC (0xF1700000)
+#define S5PV210_SZ_MFC SZ_1M
+#define S5P_PA_MFC S5PV210_PA_MFC
+#define S5P_SZ_MFC S5PV210_SZ_MFC
+
+
+/* jpeg */
+#define S5PV210_PA_JPEG (0xFB600000)
+#define S5P_PA_JPEG S5PV210_PA_JPEG
+#define S5P_SZ_JPEG SZ_1M
+
+/* rotator */
+#define S5PV210_PA_ROTATOR (0xFA300000)
+#define S5P_PA_ROTATOR S5PV210_PA_ROTATOR
+#define S5P_SZ_ROTATOR SZ_1M
+
+/* fimg2d */
+#define S5PV210_PA_FIMG2D (0xFA000000)
+#define S5P_PA_FIMG2D S5PV210_PA_FIMG2D
+#define S5P_SZ_FIMG2D SZ_1M
+
/* Compatibiltiy Defines */
#define S3C_PA_FB S5PV210_PA_FB
@@ -132,4 +204,38 @@
#define S5P_SZ_UART SZ_256
+/* CEC */
+#define S5PV210_PA_CEC (0xE1B00000)
+#define S5P_PA_CEC S5PV210_PA_CEC
+#define S5P_SZ_CEC SZ_4K
+
+/* TVOUT */
+#define S5PV210_PA_TVENC (0xF9000000)
+#define S5P_PA_TVENC S5PV210_PA_TVENC
+#define S5P_SZ_TVENC SZ_1M
+
+#define S5PV210_PA_VP (0xF9100000)
+#define S5P_PA_VP S5PV210_PA_VP
+#define S5P_SZ_VP SZ_1M
+
+#define S5PV210_PA_MIXER (0xF9200000)
+#define S5P_PA_MIXER S5PV210_PA_MIXER
+#define S5P_SZ_MIXER SZ_1M
+
+#define S5PV210_PA_HDMI (0xFA100000)
+#define S5P_PA_HDMI S5PV210_PA_HDMI
+#define S5P_SZ_HDMI SZ_1M
+
+#define S5PV210_I2C_HDMI_PHY (0xFA900000)
+#define S5P_I2C_HDMI_PHY S5PV210_I2C_HDMI_PHY
+#define S5P_I2C_HDMI_SZ_PHY SZ_1K
+
+/* usb */
+#define S3C_PA_OTG S5PV210_PA_OTG
+#define S3C_SZ_OTG S5PV210_SZ_OTG
+
+#define S3C_PA_OTGSFR S5PV210_PA_OTGSFR
+#define S3C_SZ_OTGSFR S5PV210_SZ_OTGSFR
+
+/* end usb */
#endif /* __ASM_ARCH_MAP_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/media.h b/arch/arm/mach-s5pv210/include/mach/media.h
new file mode 100755
index 0000000..ad9eb82
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/media.h
@@ -0,0 +1,32 @@
+/* linux/arch/arm/mach-s5pv210/include/mach/media.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Samsung Media device descriptions for smdkv210
+ *
+ * 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 _S5PV210_MEDIA_H
+#define _S5PV210_MEDIA_H
+
+/* 3 fimc indexes should be fixed as n, n+1 and n+2 */
+#define S5P_MDEV_FIMC0 0
+#define S5P_MDEV_FIMC1 1
+#define S5P_MDEV_FIMC2 2
+#define S5P_MDEV_TV 3
+#define S5P_MDEV_MFC 4
+#define S5P_MDEV_JPEG 5
+#define S5P_MDEV_PMEM 6
+#define S5P_MDEV_PMEM_GPU1 7
+#define S5P_MDEV_PMEM_ADSP 8
+#define S5P_MDEV_TEXSTREAM 9
+#define S5P_MDEV_FIMD 10
+#define S5P_MDEV_MAX 11
+
+#define S5P_RANGE_MFC SZ_256M
+#endif
+
diff --git a/arch/arm/mach-s5pv210/include/mach/memory.h b/arch/arm/mach-s5pv210/include/mach/memory.h
index 7b5fcf0..003d287 100644
--- a/arch/arm/mach-s5pv210/include/mach/memory.h
+++ b/arch/arm/mach-s5pv210/include/mach/memory.h
@@ -13,7 +13,12 @@
#ifndef __ASM_ARCH_MEMORY_H
#define __ASM_ARCH_MEMORY_H
+#if defined(CONFIG_MACH_SMDKV210)
#define PLAT_PHYS_OFFSET UL(0x20000000)
+#else
+#define PLAT_PHYS_OFFSET UL(0x30000000)
+#endif
+
#define CONSISTENT_DMA_SIZE (SZ_8M + SZ_4M + SZ_2M)
/*
@@ -24,5 +29,6 @@
#define MAX_PHYSMEM_BITS 31
#define SECTION_SIZE_BITS 28
+#define NODE_MEM_SIZE_BITS 28
#endif /* __ASM_ARCH_MEMORY_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/param.h b/arch/arm/mach-s5pv210/include/mach/param.h
new file mode 100644
index 0000000..dbba308
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/param.h
@@ -0,0 +1,89 @@
+
+/*
+ * Parameter Infomation
+ */
+
+#ifndef ASM_MACH_PARAM_H
+#define ASM_MACH_PARAM_H
+
+#define PARAM_MAGIC 0x72726624
+#define PARAM_VERSION 0x13 /* Rev 1.3 */
+#define PARAM_STRING_SIZE 1024 /* 1024 Characters */
+
+#define MAX_PARAM 20
+#define MAX_STRING_PARAM 5
+
+/* Default Parameter Values */
+
+#define SERIAL_SPEED 7 /* Baudrate */
+#define LCD_LEVEL 0x061 /* Backlight Level */
+#define BOOT_DELAY 0 /* Boot Wait Time */
+#define LOAD_RAMDISK 0 /* Enable Ramdisk Loading */
+#define SWITCH_SEL 1 /* Switch Setting (UART[1], USB[0]) */
+#define PHONE_DEBUG_ON 0 /* Enable Phone Debug Mode */
+#define LCD_DIM_LEVEL 0x011 /* Backlight Dimming Level */
+#define LCD_DIM_TIME 0
+#define MELODY_MODE 0 /* Melody Mode */
+#define REBOOT_MODE 0 /* Reboot Mode */
+#define NATION_SEL 0 /* Language Configuration */
+#define LANGUAGE_SEL 0
+#define SET_DEFAULT_PARAM 0 /* Set Param to Default */
+#define VERSION_LINE "I8315XXIE00" /* Set Image Info */
+#define COMMAND_LINE "console=ttySAC2,115200"
+#define BOOT_VERSION " version=Sbl(1.0.0) "
+
+typedef enum {
+ __SERIAL_SPEED,
+ __LOAD_RAMDISK,
+ __BOOT_DELAY,
+ __LCD_LEVEL,
+ __SWITCH_SEL,
+ __PHONE_DEBUG_ON,
+ __LCD_DIM_LEVEL,
+ __LCD_DIM_TIME,
+ __MELODY_MODE,
+ __REBOOT_MODE,
+ __NATION_SEL,
+ __LANGUAGE_SEL,
+ __SET_DEFAULT_PARAM,
+ __PARAM_INT_13, /* Reserved. */
+ __PARAM_INT_14, /* Reserved. */
+ __VERSION,
+ __CMDLINE,
+ __PARAM_STR_2,
+ __PARAM_STR_3, /* Reserved. */
+ __PARAM_STR_4 /* Reserved. */
+} param_idx;
+
+typedef struct _param_int_t {
+ param_idx ident;
+ int value;
+} param_int_t;
+
+typedef struct _param_str_t {
+ param_idx ident;
+ char value[PARAM_STRING_SIZE];
+} param_str_t;
+
+typedef struct {
+ int param_magic;
+ int param_version;
+ param_int_t param_list[MAX_PARAM - MAX_STRING_PARAM];
+ param_str_t param_str_list[MAX_STRING_PARAM];
+} status_t;
+
+/* REBOOT_MODE */
+#define REBOOT_MODE_NONE 0
+#define REBOOT_MODE_DOWNLOAD 1
+#define REBOOT_MODE_CHARGING 3
+#define REBOOT_MODE_RECOVERY 4
+#define REBOOT_MODE_ARM11_FOTA 5
+#define REBOOT_MODE_ARM9_FOTA 6
+
+extern void (*sec_set_param_value)(int idx, void *value);
+extern void (*sec_get_param_value)(int idx, void *value);
+
+#define USB_SEL_MASK (1 << 0)
+#define UART_SEL_MASK (1 << 1)
+
+#endif /* ASM_MACH_PARAM_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/pm-core.h b/arch/arm/mach-s5pv210/include/mach/pm-core.h
index e8d394f..e0db671 100644..100755
--- a/arch/arm/mach-s5pv210/include/mach/pm-core.h
+++ b/arch/arm/mach-s5pv210/include/mach/pm-core.h
@@ -14,6 +14,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
+#include <mach/regs-gpio.h>
static inline void s3c_pm_debug_init_uart(void)
{
@@ -33,7 +34,10 @@ static inline void s3c_pm_arch_stop_clocks(void)
static inline void s3c_pm_arch_show_resume_irqs(void)
{
- /* nothing here yet */
+ printk(KERN_DEBUG "S5P_WAKEUP_STAT 0x%X\n", __raw_readl(S5P_WAKEUP_STAT));
+ printk(KERN_DEBUG "EINT_PEND 0x%X, 0x%X, 0x%X, 0x%X\n",
+ __raw_readl(S5P_EINT_PEND(0)), __raw_readl(S5P_EINT_PEND(1)),
+ __raw_readl(S5P_EINT_PEND(2)), __raw_readl(S5P_EINT_PEND(3)));
}
static inline void s3c_pm_arch_update_uart(void __iomem *regs,
@@ -41,3 +45,4 @@ static inline void s3c_pm_arch_update_uart(void __iomem *regs,
{
/* nothing here yet */
}
+
diff --git a/arch/arm/mach-s5pv210/include/mach/power-domain.h b/arch/arm/mach-s5pv210/include/mach/power-domain.h
new file mode 100644
index 0000000..8456c10
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/power-domain.h
@@ -0,0 +1,57 @@
+/* linux/arch/arm/mach-s5pv210/include/mach/power-domain.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * S5PV210 - Power domain support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_POWER_DOMAIN_H
+#define __ASM_ARCH_POWER_DOMAIN_H __FILE__
+
+#define S5PV210_PD_IROM (1 << 20)
+#define S5PV210_PD_AUDIO (1 << 7)
+#define S5PV210_PD_CAM (1 << 5)
+#define S5PV210_PD_TV (1 << 4)
+#define S5PV210_PD_LCD (1 << 3)
+#define S5PV210_PD_G3D (1 << 2)
+#define S5PV210_PD_MFC (1 << 1)
+
+struct regulator_init_data;
+
+/**
+ * struct s5pv210_pd_config - s5pv210_pd_config structure
+ * @supply_name: Name of the regulator supply
+ * @microvolts: Output voltage of regulator
+ * @startup_delay: Start-up time in microseconds
+ * @init_data: regulator_init_data
+ * @clk_should_be_running: the clocks for the IPs in the power domain
+ * should be running when the power domain
+ * is turned on
+ * @ctrlbit: register control bit
+ *
+ * This structure contains samsung power domain regulator configuration
+ * information that must be passed by platform code to the samsung
+ * power domain regulator driver.
+ */
+struct s5pv210_pd_config {
+ const char *supply_name;
+ int microvolts;
+ unsigned startup_delay;
+ struct regulator_init_data *init_data;
+ struct clk_should_be_running *clk_run;
+ int ctrlbit;
+};
+
+extern struct platform_device s5pv210_pd_audio;
+extern struct platform_device s5pv210_pd_cam;
+extern struct platform_device s5pv210_pd_tv;
+extern struct platform_device s5pv210_pd_lcd;
+extern struct platform_device s5pv210_pd_g3d;
+extern struct platform_device s5pv210_pd_mfc;
+
+#endif
diff --git a/arch/arm/mach-s5pv210/include/mach/regs-adc.h b/arch/arm/mach-s5pv210/include/mach/regs-adc.h
new file mode 100644
index 0000000..200fed9
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/regs-adc.h
@@ -0,0 +1,119 @@
+/* arch/arm/mach-s3c2410/include/mach/regs-adc.h
+ *
+ * Copyright (c) 2004 Shannon Holland <holland@loser.net>
+ *
+ * This program is free software; yosu 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.
+ *
+ * S3C2410 ADC registers
+*/
+
+#ifndef __ASM_ARCH_REGS_ADC_H
+#define __ASM_ARCH_REGS_ADC_H "regs-adc.h"
+
+#define S3C2410_ADCREG(x) (x)
+
+#define S3C2410_ADCCON S3C2410_ADCREG(0x00)
+#define S3C2410_ADCTSC S3C2410_ADCREG(0x04)
+#define S3C2410_ADCDLY S3C2410_ADCREG(0x08)
+#define S3C2410_ADCDAT0 S3C2410_ADCREG(0x0C)
+#define S3C2410_ADCDAT1 S3C2410_ADCREG(0x10)
+
+
+/* ADCCON Register Bits */
+#define S3C2410_ADCCON_ECFLG (1<<15)
+#define S3C2410_ADCCON_PRSCEN (1<<14)
+#define S3C2410_ADCCON_PRSCVL(x) (((x)&0xFF)<<6)
+#define S3C2410_ADCCON_PRSCVLMASK (0xFF<<6)
+#define S3C2410_ADCCON_SELMUX(x) (((x)&0x7)<<3)
+#define S3C2410_ADCCON_MUXMASK (0x7<<3)
+#define S3C2410_ADCCON_STDBM (1<<2)
+#define S3C2410_ADCCON_READ_START (1<<1)
+#define S3C2410_ADCCON_ENABLE_START (1<<0)
+#define S3C2410_ADCCON_STARTMASK (0x3<<0)
+
+
+/* ADCTSC Register Bits */
+#define S3C2410_ADCTSC_YM_SEN (1<<7)
+#define S3C2410_ADCTSC_YP_SEN (1<<6)
+#define S3C2410_ADCTSC_XM_SEN (1<<5)
+#define S3C2410_ADCTSC_XP_SEN (1<<4)
+#define S3C2410_ADCTSC_PULL_UP_DISABLE (1<<3)
+#define S3C2410_ADCTSC_AUTO_PST (1<<2)
+#define S3C2410_ADCTSC_XY_PST(x) (((x)&0x3)<<0)
+
+/* ADCDAT0 Bits */
+#define S3C2410_ADCDAT0_UPDOWN (1<<15)
+#define S3C2410_ADCDAT0_AUTO_PST (1<<14)
+#define S3C2410_ADCDAT0_XY_PST (0x3<<12)
+#define S3C2410_ADCDAT0_XPDATA_MASK (0x03FF)
+
+/* ADCDAT1 Bits */
+#define S3C2410_ADCDAT1_UPDOWN (1<<15)
+#define S3C2410_ADCDAT1_AUTO_PST (1<<14)
+#define S3C2410_ADCDAT1_XY_PST (0x3<<12)
+#define S3C2410_ADCDAT1_YPDATA_MASK (0x03FF)
+
+/*--------------------------- Common definitions for S3C ---------------------------*/
+/* The following definitions will be applied to S3C24XX, S3C64XX, S5PC1XX. */
+/*-----------------------------------------------------------------------------------*/
+
+#define S3C_ADCREG(x) (x)
+
+#define S3C_ADCCON S3C_ADCREG(0x00)
+#define S3C_ADCTSC S3C_ADCREG(0x04)
+#define S3C_ADCDLY S3C_ADCREG(0x08)
+#define S3C_ADCDAT0 S3C_ADCREG(0x0C)
+#define S3C_ADCDAT1 S3C_ADCREG(0x10)
+#define S3C_ADCUPDN S3C_ADCREG(0x14)
+#define S3C_ADCCLRINT S3C_ADCREG(0x18)
+#define S3C_ADCMUX S3C_ADCREG(0x1C)
+#define S3C_ADCCLRWK S3C_ADCREG(0x20)
+
+
+/* ADCCON Register Bits */
+#define S3C_ADCCON_RESSEL_10BIT (0x0<<16)
+#define S3C_ADCCON_RESSEL_12BIT (0x1<<16)
+#define S3C_ADCCON_ECFLG (1<<15)
+#define S3C_ADCCON_PRSCEN (1<<14)
+#define S3C_ADCCON_PRSCVL(x) (((x)&0xFF)<<6)
+#define S3C_ADCCON_PRSCVLMASK (0xFF<<6)
+#define S3C_ADCCON_SELMUX(x) (((x)&0x7)<<3)
+#define S3C_ADCCON_SELMUX_1(x) (((x)&0xF)<<0)
+#define S3C_ADCCON_MUXMASK (0x7<<3)
+#define S3C_ADCCON_RESSEL_10BIT_1 (0x0<<3)
+#define S3C_ADCCON_RESSEL_12BIT_1 (0x1<<3)
+#define S3C_ADCCON_STDBM (1<<2)
+#define S3C_ADCCON_READ_START (1<<1)
+#define S3C_ADCCON_ENABLE_START (1<<0)
+#define S3C_ADCCON_STARTMASK (0x3<<0)
+
+
+/* ADCTSC Register Bits */
+#define S3C_ADCTSC_UD_SEN (1<<8)
+#define S3C_ADCTSC_YM_SEN (1<<7)
+#define S3C_ADCTSC_YP_SEN (1<<6)
+#define S3C_ADCTSC_XM_SEN (1<<5)
+#define S3C_ADCTSC_XP_SEN (1<<4)
+#define S3C_ADCTSC_PULL_UP_DISABLE (1<<3)
+#define S3C_ADCTSC_AUTO_PST (1<<2)
+#define S3C_ADCTSC_XY_PST(x) (((x)&0x3)<<0)
+
+/* ADCDAT0 Bits */
+#define S3C_ADCDAT0_UPDOWN (1<<15)
+#define S3C_ADCDAT0_AUTO_PST (1<<14)
+#define S3C_ADCDAT0_XY_PST (0x3<<12)
+#define S3C_ADCDAT0_XPDATA_MASK (0x03FF)
+#define S3C_ADCDAT0_XPDATA_MASK_12BIT (0x0FFF)
+
+/* ADCDAT1 Bits */
+#define S3C_ADCDAT1_UPDOWN (1<<15)
+#define S3C_ADCDAT1_AUTO_PST (1<<14)
+#define S3C_ADCDAT1_XY_PST (0x3<<12)
+#define S3C_ADCDAT1_YPDATA_MASK (0x03FF)
+#define S3C_ADCDAT1_YPDATA_MASK_12BIT (0x0FFF)
+
+#endif /* __ASM_ARCH_REGS_ADC_H */
+
+
diff --git a/arch/arm/mach-s5pv210/include/mach/regs-audss.h b/arch/arm/mach-s5pv210/include/mach/regs-audss.h
new file mode 100644
index 0000000..b2cc2fd
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/regs-audss.h
@@ -0,0 +1,44 @@
+/* arch/arm/plat-s5pc1xx/include/plat/regs-clock.h
+ *
+ * Copyright 2008 Samsung Electronics
+ *
+ * S5PV2XX Audio SubSystem clock register definitions
+ *
+ * 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 __PLAT_REGS_AUDSS_H
+#define __PLAT_REGS_AUDSS_H __FILE__
+
+#define S5P_AUDSSREG(x) (S5P_VA_AUDSS + (x))
+
+#define S5P_CLKSRC_AUDSS S5P_AUDSSREG(0x0)
+#define S5P_CLKDIV_AUDSS S5P_AUDSSREG(0x4)
+#define S5P_CLKGATE_AUDSS S5P_AUDSSREG(0x8)
+
+/* CLKSRC0 */
+#define S5P_AUDSS_CLKSRC_MAIN_MASK (0x1<<0)
+#define S5P_AUDSS_CLKSRC_MAIN_SHIFT (0)
+#define S5P_AUDSS_CLKSRC_BUSCLK_MASK (0x1<<1)
+#define S5P_AUDSS_CLKSRC_BUSCLK_SHIFT (1)
+#define S5P_AUDSS_CLKSRC_I2SCLK_MASK (0x3<<2)
+#define S5P_AUDSS_CLKSRC_I2SCLK_SHIFT (2)
+
+/* CLKDIV0 */
+#define S5P_AUDSS_CLKDIV_BUSCLK_MASK (0xf<<0)
+#define S5P_AUDSS_CLKDIV_BUSCLK_SHIFT (0)
+#define S5P_AUDSS_CLKDIV_I2SCLK_MASK (0xf<<4)
+#define S5P_AUDSS_CLKDIV_I2SCLK_SHIFT (4)
+
+/* IP Clock Gate 0 Registers */
+#define S5P_AUDSS_CLKGATE_HCLKRP (1<<0)
+#define S5P_AUDSS_CLKGATE_HCLKBUF (1<<1)
+#define S5P_AUDSS_CLKGATE_HCLKDMA (1<<2)
+#define S5P_AUDSS_CLKGATE_HCLKHWA (1<<3)
+#define S5P_AUDSS_CLKGATE_HCLKUART (1<<4)
+#define S5P_AUDSS_CLKGATE_HCLKI2S (1<<5)
+#define S5P_AUDSS_CLKGATE_CLKI2S (1<<6)
+
+#endif /* _PLAT_REGS_AUDSS_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/regs-clock.h b/arch/arm/mach-s5pv210/include/mach/regs-clock.h
index 78925c5..d5d51cd 100644
--- a/arch/arm/mach-s5pv210/include/mach/regs-clock.h
+++ b/arch/arm/mach-s5pv210/include/mach/regs-clock.h
@@ -17,6 +17,9 @@
#define S5P_CLKREG(x) (S3C_VA_SYS + (x))
+#define S5P_IECREG(x) (S5PC11X_VA_IEC + (x))
+#define S5P_APCREG(x) (S5PC11X_VA_APC + (x))
+
#define S5P_APLL_LOCK S5P_CLKREG(0x00)
#define S5P_MPLL_LOCK S5P_CLKREG(0x08)
#define S5P_EPLL_LOCK S5P_CLKREG(0x10)
@@ -64,8 +67,7 @@
#define S5P_CLKGATE_IP4 S5P_CLKREG(0x470)
#define S5P_CLKGATE_BLOCK S5P_CLKREG(0x480)
-#define S5P_CLKGATE_BUS0 S5P_CLKREG(0x484)
-#define S5P_CLKGATE_BUS1 S5P_CLKREG(0x488)
+#define S5P_CLKGATE_IP5 S5P_CLKREG(0x484)
#define S5P_CLK_OUT S5P_CLKREG(0x500)
/* DIV/MUX STATUS */
@@ -77,6 +79,17 @@
/* CLKSRC0 */
#define S5P_CLKSRC0_MUX200_SHIFT (16)
#define S5P_CLKSRC0_MUX200_MASK (0x1 << S5P_CLKSRC0_MUX200_SHIFT)
+
+#define S5P_MIXER_OUT_SEL S5P_CLKREG(0x7004)
+
+#define S5P_EPLL_EN (1<<31)
+#define S5P_EPLL_MASK 0xffffffff
+#define S5P_EPLLVAL(_v,_m,_p,_s) ((_v) << 27 | (_m) << 16 | ((_p) << 8) | ((_s)))
+
+#define S5P_EPLL_MASK_VSEL (0x1<<27)
+#define S5P_EPLL_MASK_M (0x1FF<<16)
+#define S5P_EPLL_MASK_P (0x3F<<8)
+#define S5P_EPLL_MASK_S (0x3<<0)
#define S5P_CLKSRC0_MUX166_MASK (0x1<<20)
#define S5P_CLKSRC0_MUX133_MASK (0x1<<24)
@@ -122,6 +135,161 @@
#define S5P_ARM_MCS_CON S5P_CLKREG(0x6100)
+/* IP Clock Gate 0 Registers */
+#define S5P_CLKGATE_IP0_CSIS (1<<31)
+#define S5P_CLKGATE_IP0_IPC (1<<30)
+#define S5P_CLKGATE_IP0_ROTATOR (1<<29)
+#define S5P_CLKGATE_IP0_JPEG (1<<28)
+#define S5P_CLKGATE_IP0_FIMC2 (1<<26)
+#define S5P_CLKGATE_IP0_FIMC1 (1<<25)
+#define S5P_CLKGATE_IP0_FIMC0 (1<<24)
+#define S5P_CLKGATE_IP0_MFC (1<<16)
+#define S5P_CLKGATE_IP0_G2D (1<<12)
+#define S5P_CLKGATE_IP0_G3D (1<<8)
+#define S5P_CLKGATE_IP0_IMEM (1<<5)
+#define S5P_CLKGATE_IP0_PDMA1 (1<<4)
+#define S5P_CLKGATE_IP0_PDMA0 (1<<3)
+#define S5P_CLKGATE_IP0_MDMA (1<<2)
+#define S5P_CLKGATE_IP0_DMC1 (1<<1)
+#define S5P_CLKGATE_IP0_DMC0 (1<<0)
+
+/* IP Clock Gate 1 Registers */
+#define S5P_CLKGATE_IP1_NFCON (1<<28)
+#define S5P_CLKGATE_IP1_SROMC (1<<26)
+#define S5P_CLKGATE_IP1_CFCON (1<<25)
+#define S5P_CLKGATE_IP1_NANDXL (1<<24)
+#define S5P_CLKGATE_IP1_USBHOST (1<<17)
+#define S5P_CLKGATE_IP1_USBOTG (1<<16)
+#define S5P_CLKGATE_IP1_HDMI (1<<11)
+#define S5P_CLKGATE_IP1_TVENC (1<<10)
+#define S5P_CLKGATE_IP1_MIXER (1<<9)
+#define S5P_CLKGATE_IP1_VP (1<<8)
+#define S5P_CLKGATE_IP1_DSIM (1<<2)
+#define S5P_CLKGATE_IP1_MIE (1<<1)
+#define S5P_CLKGATE_IP1_FIMD (1<<0)
+
+/* IP Clock Gate 2 Registers */
+#define S5P_CLKGATE_IP2_TZIC3 (1<<31)
+#define S5P_CLKGATE_IP2_TZIC2 (1<<30)
+#define S5P_CLKGATE_IP2_TZIC1 (1<<29)
+#define S5P_CLKGATE_IP2_TZIC0 (1<<28)
+#define S5P_CLKGATE_IP2_VIC3 (1<<27)
+#define S5P_CLKGATE_IP2_VIC2 (1<<26)
+#define S5P_CLKGATE_IP2_VIC1 (1<<25)
+#define S5P_CLKGATE_IP2_VIC0 (1<<24)
+#define S5P_CLKGATE_IP2_TSI (1<<20)
+#define S5P_CLKGATE_IP2_HSMMC3 (1<<19)
+#define S5P_CLKGATE_IP2_HSMMC2 (1<<18)
+#define S5P_CLKGATE_IP2_HSMMC1 (1<<17)
+#define S5P_CLKGATE_IP2_HSMMC0 (1<<16)
+#define S5P_CLKGATE_IP2_SECJTAG (1<<11)
+#define S5P_CLKGATE_IP2_HOSTIF (1<<10)
+#define S5P_CLKGATE_IP2_MODEM (1<<9)
+#define S5P_CLKGATE_IP2_CORESIGHT (1<<8)
+#define S5P_CLKGATE_IP2_SDM (1<<1)
+#define S5P_CLKGATE_IP2_SECSS (1<<0)
+
+/* IP Clock Gate 3 Registers */
+#define S5P_CLKGATE_IP3_PCM2 (1<<30)
+#define S5P_CLKGATE_IP3_PCM1 (1<<29)
+#define S5P_CLKGATE_IP3_PCM0 (1<<28)
+#define S5P_CLKGATE_IP3_SYSCON (1<<27)
+#define S5P_CLKGATE_IP3_GPIO (1<<26)
+#define S5P_CLKGATE_IP3_TSADC (1<<24)
+#define S5P_CLKGATE_IP3_PWM (1<<23)
+#define S5P_CLKGATE_IP3_WDT (1<<22)
+#define S5P_CLKGATE_IP3_KEYIF (1<<21)
+#define S5P_CLKGATE_IP3_UART3 (1<<20)
+#define S5P_CLKGATE_IP3_UART2 (1<<19)
+#define S5P_CLKGATE_IP3_UART1 (1<<18)
+#define S5P_CLKGATE_IP3_UART0 (1<<17)
+#define S5P_CLKGATE_IP3_SYSTIMER (1<<16)
+#define S5P_CLKGATE_IP3_RTC (1<<15)
+#define S5P_CLKGATE_IP3_SPI2 (1<<14)
+#define S5P_CLKGATE_IP3_SPI1 (1<<13)
+#define S5P_CLKGATE_IP3_SPI0 (1<<12)
+#define S5P_CLKGATE_IP3_I2C_HDMI_PHY (1<<11)
+#define S5P_CLKGATE_IP3_I2C_HDMI_DDC (1<<10)
+#define S5P_CLKGATE_IP3_I2C2 (1<<9)
+#define S5P_CLKGATE_IP3_I2C1 (1<<8)
+#define S5P_CLKGATE_IP3_I2C0 (1<<7)
+#define S5P_CLKGATE_IP3_I2S2 (1<<6)
+#define S5P_CLKGATE_IP3_I2S1 (1<<5)
+#define S5P_CLKGATE_IP3_I2S0 (1<<4)
+#define S5P_CLKGATE_IP3_AC97 (1<<1)
+#define S5P_CLKGATE_IP3_SPDIF (1<<0)
+
+/* IP Clock Gate 4 Registers */
+#define S5P_CLKGATE_IP4_TZPC3 (1<<8)
+#define S5P_CLKGATE_IP4_TZPC2 (1<<7)
+#define S5P_CLKGATE_IP4_TZPC1 (1<<6)
+#define S5P_CLKGATE_IP4_TZPC0 (1<<5)
+#define S5P_CLKGATE_IP4_SECKEY (1<<3)
+#define S5P_CLKGATE_IP4_IEM_APC (1<<2)
+#define S5P_CLKGATE_IP4_IEM_IEC (1<<1)
+#define S5P_CLKGATE_IP4_CHIP_ID (1<<0)
+
+/* Block Clock Gate Registers */
+#define S5P_CLKGATE_BLOCK_INTC (1<<10)
+#define S5P_CLKGATE_BLOCK_HSMMC (1<<9)
+#define S5P_CLKGATE_BLOCK_DEBUG (1<<8)
+#define S5P_CLKGATE_BLOCK_SECURITY (1<<7)
+#define S5P_CLKGATE_BLOCK_MEMORY (1<<6)
+#define S5P_CLKGATE_BLOCK_USB (1<<5)
+#define S5P_CLKGATE_BLOCK_TV (1<<4)
+#define S5P_CLKGATE_BLOCK_LCD (1<<3)
+#define S5P_CLKGATE_BLOCK_IMG (1<<2)
+#define S5P_CLKGATE_BLOCK_MFC (1<<1)
+#define S5P_CLKGATE_BLOCK_G3D (1<<0)
+
+/* IP Clock Gate 5 Registers */
+#define S5P_CLKGATE_IP5_JPEG (1<<29)
+
+
+/* Bus Clock Gate Registers (hidden) */
+
+/* register for EINT on PM Driver */
+#define S5P_APM_REG(x) ((x) + 0xE0200C00)
+
+#define S5P_APM_BASE S5P_APM_REG(0x000)
+
+#define S5P_APM_GPH0CON (0x000)
+#define S5P_APM_GPH0DAT (0x004)
+#define S5P_APM_GPH0PUD (0x008)
+#define S5P_APM_GPH0DRV (0x00C)
+#define S5P_APM_GPH1CON (0x020)
+#define S5P_APM_GPH1DAT (0x024)
+#define S5P_APM_GPH1PUD (0x028)
+#define S5P_APM_GPH1DRV (0x02C)
+#define S5P_APM_GPH2CON (0x040)
+#define S5P_APM_GPH2DAT (0x044)
+#define S5P_APM_GPH2PUD (0x048)
+#define S5P_APM_GPH2DRV (0x04C)
+#define S5P_APM_GPH3CON (0x060)
+#define S5P_APM_GPH3DAT (0x064)
+#define S5P_APM_GPH3PUD (0x068)
+#define S5P_APM_GPH3DRV (0x06C)
+#define S5P_APM_WEINT0_CON (0x200)
+#define S5P_APM_WEINT1_CON (0x204)
+#define S5P_APM_WEINT2_CON (0x208)
+#define S5P_APM_WEINT3_CON (0x20C)
+#define S5P_APM_WEINT0_FLTCON0 (0x280)
+#define S5P_APM_WEINT0_FLTCON1 (0x284)
+#define S5P_APM_WEINT1_FLTCON0 (0x288)
+#define S5P_APM_WEINT1_FLTCON1 (0x28C)
+#define S5P_APM_WEINT2_FLTCON0 (0x290)
+#define S5P_APM_WEINT2_FLTCON1 (0x294)
+#define S5P_APM_WEINT3_FLTCON0 (0x298)
+#define S5P_APM_WEINT3_FLTCON1 (0x29C)
+#define S5P_APM_WEINT0_MASK (0x300)
+#define S5P_APM_WEINT1_MASK (0x304)
+#define S5P_APM_WEINT2_MASK (0x308)
+#define S5P_APM_WEINT3_MASK (0x30C)
+#define S5P_APM_WEINT0_PEND (0x340)
+#define S5P_APM_WEINT1_PEND (0x344)
+#define S5P_APM_WEINT2_PEND (0x348)
+#define S5P_APM_WEINT3_PEND (0x34C)
+
/* Registers related to power management */
#define S5P_PWR_CFG S5P_CLKREG(0xC000)
#define S5P_EINT_WAKEUP_MASK S5P_CLKREG(0xC004)
@@ -141,15 +309,21 @@
#define S5P_WAKEUP_STAT S5P_CLKREG(0xC200)
#define S5P_BLK_PWR_STAT S5P_CLKREG(0xC204)
+#define S5P_ABB_VALUE S5P_CLKREG(0xC300)
#define S5P_OTHERS S5P_CLKREG(0xE000)
#define S5P_OM_STAT S5P_CLKREG(0xE100)
+#define S5P_MIE_CONTROL S5P_CLKREG(0xE800)
+#define S5P_HDMI_CONTROL S5P_CLKREG(0xE804)
#define S5P_USB_PHY_CONTROL S5P_CLKREG(0xE80C)
+#define S5P_HDMI_PHY_CONTROL S5P_CLKREG(0xE804)
#define S5P_DAC_CONTROL S5P_CLKREG(0xE810)
#define S5P_MIPI_DPHY_CONTROL(x) S5P_CLKREG(0xE814)
#define S5P_MIPI_DPHY_ENABLE (1 << 0)
#define S5P_MIPI_DPHY_SRESETN (1 << 1)
#define S5P_MIPI_DPHY_MRESETN (1 << 2)
+#define S5P_ADC_CONTROL S5P_CLKREG(0xE818)
+#define S5P_PSHOLD_CONTROL S5P_CLKREG(0xE81C)
#define S5P_INFORM0 S5P_CLKREG(0xF000)
#define S5P_INFORM1 S5P_CLKREG(0xF004)
diff --git a/arch/arm/mach-s5pv210/include/mach/regs-gpio.h b/arch/arm/mach-s5pv210/include/mach/regs-gpio.h
index de0c899..b2c69e8 100644
--- a/arch/arm/mach-s5pv210/include/mach/regs-gpio.h
+++ b/arch/arm/mach-s5pv210/include/mach/regs-gpio.h
@@ -15,11 +15,230 @@
#include <mach/map.h>
+/* Base addresses for each of the banks */
+
+#define S5PV210_GPA0_BASE (S5P_VA_GPIO + 0x000)
+#define S5PV210_GPA1_BASE (S5P_VA_GPIO + 0x020)
+#define S5PV210_GPB_BASE (S5P_VA_GPIO + 0x040)
+#define S5PV210_GPC0_BASE (S5P_VA_GPIO + 0x060)
+#define S5PV210_GPC1_BASE (S5P_VA_GPIO + 0x080)
+#define S5PV210_GPD0_BASE (S5P_VA_GPIO + 0x0A0)
+#define S5PV210_GPD1_BASE (S5P_VA_GPIO + 0x0C0)
+#define S5PV210_GPE0_BASE (S5P_VA_GPIO + 0x0E0)
+#define S5PV210_GPE1_BASE (S5P_VA_GPIO + 0x100)
+#define S5PV210_GPF0_BASE (S5P_VA_GPIO + 0x120)
+#define S5PV210_GPF1_BASE (S5P_VA_GPIO + 0x140)
+#define S5PV210_GPF2_BASE (S5P_VA_GPIO + 0x160)
+#define S5PV210_GPF3_BASE (S5P_VA_GPIO + 0x180)
+#define S5PV210_GPG0_BASE (S5P_VA_GPIO + 0x1A0)
+#define S5PV210_GPG1_BASE (S5P_VA_GPIO + 0x1C0)
+#define S5PV210_GPG2_BASE (S5P_VA_GPIO + 0x1E0)
+#define S5PV210_GPG3_BASE (S5P_VA_GPIO + 0x200)
+#define S5PV210_GPH0_BASE (S5P_VA_GPIO + 0xC00)
+#define S5PV210_GPH1_BASE (S5P_VA_GPIO + 0xC20)
+#define S5PV210_GPH2_BASE (S5P_VA_GPIO + 0xC40)
+#define S5PV210_GPH3_BASE (S5P_VA_GPIO + 0xC60)
+#define S5PV210_GPI_BASE (S5P_VA_GPIO + 0x220)
+#define S5PV210_GPJ0_BASE (S5P_VA_GPIO + 0x240)
+#define S5PV210_GPJ1_BASE (S5P_VA_GPIO + 0x260)
+#define S5PV210_GPJ2_BASE (S5P_VA_GPIO + 0x280)
+#define S5PV210_GPJ3_BASE (S5P_VA_GPIO + 0x2A0)
+#define S5PV210_GPJ4_BASE (S5P_VA_GPIO + 0x2C0)
+#define S5PV210_MP01_BASE (S5P_VA_GPIO + 0x2E0)
+#define S5PV210_MP02_BASE (S5P_VA_GPIO + 0x300)
+#define S5PV210_MP03_BASE (S5P_VA_GPIO + 0x320)
+#define S5PV210_MP04_BASE (S5P_VA_GPIO + 0x340)
+#define S5PV210_MP05_BASE (S5P_VA_GPIO + 0x360)
+#define S5PV210_MP06_BASE (S5P_VA_GPIO + 0x380)
+#define S5PV210_MP07_BASE (S5P_VA_GPIO + 0x3A0)
+#define S5PV210_MP10_BASE (S5P_VA_GPIO + 0x3C0)
+#define S5PV210_MP11_BASE (S5P_VA_GPIO + 0x3E0)
+#define S5PV210_MP12_BASE (S5P_VA_GPIO + 0x400)
+#define S5PV210_MP13_BASE (S5P_VA_GPIO + 0x420)
+#define S5PV210_MP14_BASE (S5P_VA_GPIO + 0x440)
+#define S5PV210_MP15_BASE (S5P_VA_GPIO + 0x460)
+#define S5PV210_MP16_BASE (S5P_VA_GPIO + 0x480)
+#define S5PV210_MP17_BASE (S5P_VA_GPIO + 0x4A0)
+#define S5PV210_MP18_BASE (S5P_VA_GPIO + 0x4C0)
+#define S5PV210_MP20_BASE (S5P_VA_GPIO + 0x4E0)
+#define S5PV210_MP21_BASE (S5P_VA_GPIO + 0x500)
+#define S5PV210_MP22_BASE (S5P_VA_GPIO + 0x520)
+#define S5PV210_MP23_BASE (S5P_VA_GPIO + 0x540)
+#define S5PV210_MP24_BASE (S5P_VA_GPIO + 0x560)
+#define S5PV210_MP25_BASE (S5P_VA_GPIO + 0x580)
+#define S5PV210_MP26_BASE (S5P_VA_GPIO + 0x5A0)
+#define S5PV210_MP27_BASE (S5P_VA_GPIO + 0x5C0)
+#define S5PV210_MP28_BASE (S5P_VA_GPIO + 0x5E0)
+#define S5PV210_ETC0_BASE (S5P_VA_GPIO + 0x600)
+#define S5PV210_ETC1_BASE (S5P_VA_GPIO + 0x620)
+#define S5PV210_ETC2_BASE (S5P_VA_GPIO + 0x640)
+#define S5PV210_ETC4_BASE (S5P_VA_GPIO + 0x660)
+
+#define S5PV210_GPA0_INT_CON (S5P_VA_GPIO + 0x700)
+#define S5PV210_GPA0_INT_FLTCON0 (S5P_VA_GPIO + 0x800)
+#define S5PV210_GPA0_INT_FLTCON1 (S5P_VA_GPIO + 0x804)
+#define S5PV210_GPA0_INT_MASK (S5P_VA_GPIO + 0x900)
+#define S5PV210_GPA0_INT_PEND (S5P_VA_GPIO + 0xA00)
+#define S5PV210_GPA0_INT_FIXPRI (S5P_VA_GPIO + 0xB14)
+
+#define S5PV210_GPA1_INT_CON (S5P_VA_GPIO + 0x704)
+#define S5PV210_GPA1_INT_FLTCON0 (S5P_VA_GPIO + 0x808)
+#define S5PV210_GPA1_INT_FLTCON1 (S5P_VA_GPIO + 0x80C)
+#define S5PV210_GPA1_INT_MASK (S5P_VA_GPIO + 0x904)
+#define S5PV210_GPA1_INT_PEND (S5P_VA_GPIO + 0xA04)
+#define S5PV210_GPA1_INT_FIXPRI (S5P_VA_GPIO + 0xB18)
+
+#define S5PV210_GPB_INT_CON (S5P_VA_GPIO + 0x708)
+#define S5PV210_GPB_INT_FLTCON0 (S5P_VA_GPIO + 0x810)
+#define S5PV210_GPB_INT_FLTCON1 (S5P_VA_GPIO + 0x814)
+#define S5PV210_GPB_INT_MASK (S5P_VA_GPIO + 0x908)
+#define S5PV210_GPB_INT_PEND (S5P_VA_GPIO + 0xA08)
+#define S5PV210_GPB_INT_FIXPRI (S5P_VA_GPIO + 0xB1C)
+
+#define S5PV210_GPC0_INT_CON (S5P_VA_GPIO + 0x70C)
+#define S5PV210_GPC0_INT_FLTCON0 (S5P_VA_GPIO + 0x818)
+#define S5PV210_GPC0_INT_FLTCON1 (S5P_VA_GPIO + 0x81C)
+#define S5PV210_GPC0_INT_MASK (S5P_VA_GPIO + 0x90C)
+#define S5PV210_GPC0_INT_PEND (S5P_VA_GPIO + 0xA0C)
+#define S5PV210_GPC0_INT_FIXPRI (S5P_VA_GPIO + 0xB20)
+
+#define S5PV210_GPC1_INT_CON (S5P_VA_GPIO + 0x710)
+#define S5PV210_GPC1_INT_FLTCON0 (S5P_VA_GPIO + 0x820)
+#define S5PV210_GPC1_INT_FLTCON1 (S5P_VA_GPIO + 0x824)
+#define S5PV210_GPC1_INT_MASK (S5P_VA_GPIO + 0x910)
+#define S5PV210_GPC1_INT_PEND (S5P_VA_GPIO + 0xA10)
+#define S5PV210_GPC1_INT_FIXPRI (S5P_VA_GPIO + 0xB24)
+
+#define S5PV210_GPD0_INT_CON (S5P_VA_GPIO + 0x714)
+#define S5PV210_GPD0_INT_FLTCON0 (S5P_VA_GPIO + 0x828)
+#define S5PV210_GPD0_INT_FLTCON1 (S5P_VA_GPIO + 0x82C)
+#define S5PV210_GPD0_INT_MASK (S5P_VA_GPIO + 0x914)
+#define S5PV210_GPD0_INT_PEND (S5P_VA_GPIO + 0xA14)
+#define S5PV210_GPD0_INT_FIXPRI (S5P_VA_GPIO + 0xB28)
+
+#define S5PV210_GPD1_INT_CON (S5P_VA_GPIO + 0x718)
+#define S5PV210_GPD1_INT_FLTCON0 (S5P_VA_GPIO + 0x830)
+#define S5PV210_GPD1_INT_FLTCON1 (S5P_VA_GPIO + 0x834)
+#define S5PV210_GPD1_INT_MASK (S5P_VA_GPIO + 0x918)
+#define S5PV210_GPD1_INT_PEND (S5P_VA_GPIO + 0xA18)
+#define S5PV210_GPD1_INT_FIXPRI (S5P_VA_GPIO + 0xB2C)
+
+#define S5PV210_GPE0_INT_CON (S5P_VA_GPIO + 0x71C)
+#define S5PV210_GPE0_INT_FLTCON0 (S5P_VA_GPIO + 0x838)
+#define S5PV210_GPE0_INT_FLTCON1 (S5P_VA_GPIO + 0x83C)
+#define S5PV210_GPE0_INT_MASK (S5P_VA_GPIO + 0x91C)
+#define S5PV210_GPE0_INT_PEND (S5P_VA_GPIO + 0xA1C)
+#define S5PV210_GPE0_INT_FIXPRI (S5P_VA_GPIO + 0xB30)
+
+#define S5PV210_GPE1_INT_CON (S5P_VA_GPIO + 0x720)
+#define S5PV210_GPE1_INT_FLTCON0 (S5P_VA_GPIO + 0x840)
+#define S5PV210_GPE1_INT_FLTCON1 (S5P_VA_GPIO + 0x844)
+#define S5PV210_GPE1_INT_MASK (S5P_VA_GPIO + 0x920)
+#define S5PV210_GPE1_INT_PEND (S5P_VA_GPIO + 0xA20)
+#define S5PV210_GPE1_INT_FIXPRI (S5P_VA_GPIO + 0xB34)
+
+#define S5PV210_GPF0_INT_CON (S5P_VA_GPIO + 0x724)
+#define S5PV210_GPF0_INT_FLTCON0 (S5P_VA_GPIO + 0x848)
+#define S5PV210_GPF0_INT_FLTCON1 (S5P_VA_GPIO + 0x84C)
+#define S5PV210_GPF0_INT_MASK (S5P_VA_GPIO + 0x924)
+#define S5PV210_GPF0_INT_PEND (S5P_VA_GPIO + 0xA24)
+#define S5PV210_GPF0_INT_FIXPRI (S5P_VA_GPIO + 0xB38)
+
+#define S5PV210_GPF1_INT_CON (S5P_VA_GPIO + 0x728)
+#define S5PV210_GPF1_INT_FLTCON0 (S5P_VA_GPIO + 0x850)
+#define S5PV210_GPF1_INT_FLTCON1 (S5P_VA_GPIO + 0x854)
+#define S5PV210_GPF1_INT_MASK (S5P_VA_GPIO + 0x928)
+#define S5PV210_GPF1_INT_PEND (S5P_VA_GPIO + 0xA28)
+#define S5PV210_GPF1_INT_FIXPRI (S5P_VA_GPIO + 0xB3C)
+
+#define S5PV210_GPF2_INT_CON (S5P_VA_GPIO + 0x72C)
+#define S5PV210_GPF2_INT_FLTCON0 (S5P_VA_GPIO + 0x858)
+#define S5PV210_GPF2_INT_FLTCON1 (S5P_VA_GPIO + 0x85C)
+#define S5PV210_GPF2_INT_MASK (S5P_VA_GPIO + 0x92C)
+#define S5PV210_GPF2_INT_PEND (S5P_VA_GPIO + 0xA2C)
+#define S5PV210_GPF2_INT_FIXPRI (S5P_VA_GPIO + 0xB40)
+
+#define S5PV210_GPF3_INT_CON (S5P_VA_GPIO + 0x730)
+#define S5PV210_GPF3_INT_FLTCON0 (S5P_VA_GPIO + 0x860)
+#define S5PV210_GPF3_INT_FLTCON1 (S5P_VA_GPIO + 0x864)
+#define S5PV210_GPF3_INT_MASK (S5P_VA_GPIO + 0x930)
+#define S5PV210_GPF3_INT_PEND (S5P_VA_GPIO + 0xA30)
+#define S5PV210_GPF3_INT_FIXPRI (S5P_VA_GPIO + 0xB44)
+
+#define S5PV210_GPG0_INT_CON (S5P_VA_GPIO + 0x734)
+#define S5PV210_GPG0_INT_FLTCON0 (S5P_VA_GPIO + 0x868)
+#define S5PV210_GPG0_INT_FLTCON1 (S5P_VA_GPIO + 0x86C)
+#define S5PV210_GPG0_INT_MASK (S5P_VA_GPIO + 0x934)
+#define S5PV210_GPG0_INT_PEND (S5P_VA_GPIO + 0xA34)
+#define S5PV210_GPG0_INT_FIXPRI (S5P_VA_GPIO + 0xB48)
+
+#define S5PV210_GPG1_INT_CON (S5P_VA_GPIO + 0x738)
+#define S5PV210_GPG1_INT_FLTCON0 (S5P_VA_GPIO + 0x870)
+#define S5PV210_GPG1_INT_FLTCON1 (S5P_VA_GPIO + 0x874)
+#define S5PV210_GPG1_INT_MASK (S5P_VA_GPIO + 0x938)
+#define S5PV210_GPG1_INT_PEND (S5P_VA_GPIO + 0xA38)
+#define S5PV210_GPG1_INT_FIXPRI (S5P_VA_GPIO + 0xB4C)
+
+#define S5PV210_GPG2_INT_CON (S5P_VA_GPIO + 0x73C)
+#define S5PV210_GPG2_INT_FLTCON0 (S5P_VA_GPIO + 0x878)
+#define S5PV210_GPG2_INT_FLTCON1 (S5P_VA_GPIO + 0x87C)
+#define S5PV210_GPG2_INT_MASK (S5P_VA_GPIO + 0x93C)
+#define S5PV210_GPG2_INT_PEND (S5P_VA_GPIO + 0xA3C)
+#define S5PV210_GPG2_INT_FIXPRI (S5P_VA_GPIO + 0xB50)
+
+#define S5PV210_GPG3_INT_CON (S5P_VA_GPIO + 0x740)
+#define S5PV210_GPG3_INT_FLTCON0 (S5P_VA_GPIO + 0x880)
+#define S5PV210_GPG3_INT_FLTCON1 (S5P_VA_GPIO + 0x884)
+#define S5PV210_GPG3_INT_MASK (S5P_VA_GPIO + 0x940)
+#define S5PV210_GPG3_INT_PEND (S5P_VA_GPIO + 0xA40)
+#define S5PV210_GPG3_INT_FIXPRI (S5P_VA_GPIO + 0xB54)
+
+#define S5PV210_GPJ0_INT_CON (S5P_VA_GPIO + 0x744)
+#define S5PV210_GPJ0_INT_FLTCON0 (S5P_VA_GPIO + 0x888)
+#define S5PV210_GPJ0_INT_FLTCON1 (S5P_VA_GPIO + 0x88C)
+#define S5PV210_GPJ0_INT_MASK (S5P_VA_GPIO + 0x944)
+#define S5PV210_GPJ0_INT_PEND (S5P_VA_GPIO + 0xA44)
+#define S5PV210_GPJ0_INT_FIXPRI (S5P_VA_GPIO + 0xB58)
+
+#define S5PV210_GPJ1_INT_CON (S5P_VA_GPIO + 0x748)
+#define S5PV210_GPJ1_INT_FLTCON0 (S5P_VA_GPIO + 0x890)
+#define S5PV210_GPJ1_INT_FLTCON1 (S5P_VA_GPIO + 0x894)
+#define S5PV210_GPJ1_INT_MASK (S5P_VA_GPIO + 0x948)
+#define S5PV210_GPJ1_INT_PEND (S5P_VA_GPIO + 0xA48)
+#define S5PV210_GPJ1_INT_FIXPRI (S5P_VA_GPIO + 0xB5C)
+
+#define S5PV210_GPJ2_INT_CON (S5P_VA_GPIO + 0x74C)
+#define S5PV210_GPJ2_INT_FLTCON0 (S5P_VA_GPIO + 0x898)
+#define S5PV210_GPJ2_INT_FLTCON1 (S5P_VA_GPIO + 0x89C)
+#define S5PV210_GPJ2_INT_MASK (S5P_VA_GPIO + 0x94C)
+#define S5PV210_GPJ2_INT_PEND (S5P_VA_GPIO + 0xA4C)
+#define S5PV210_GPJ2_INT_FIXPRI (S5P_VA_GPIO + 0xB60)
+
+#define S5PV210_GPJ3_INT_CON (S5P_VA_GPIO + 0x750)
+#define S5PV210_GPJ3_INT_FLTCON0 (S5P_VA_GPIO + 0x8A0)
+#define S5PV210_GPJ3_INT_FLTCON1 (S5P_VA_GPIO + 0x8A4)
+#define S5PV210_GPJ3_INT_MASK (S5P_VA_GPIO + 0x950)
+#define S5PV210_GPJ3_INT_PEND (S5P_VA_GPIO + 0xA50)
+#define S5PV210_GPJ3_INT_FIXPRI (S5P_VA_GPIO + 0xB64)
+
+#define S5PV210_GPJ4_INT_CON (S5P_VA_GPIO + 0x754)
+#define S5PV210_GPJ4_INT_FLTCON0 (S5P_VA_GPIO + 0x8A8)
+#define S5PV210_GPJ4_INT_FLTCON1 (S5P_VA_GPIO + 0x8AC)
+#define S5PV210_GPJ4_INT_MASK (S5P_VA_GPIO + 0x954)
+#define S5PV210_GPJ4_INT_PEND (S5P_VA_GPIO + 0xA54)
+#define S5PV210_GPJ4_INT_FIXPRI (S5P_VA_GPIO + 0xB68)
+
+#define S5PV210_EXT_INT_GRPPRI (S5P_VA_GPIO + 0xB00)
+#define S5PV210_EXT_INT_PRIO (S5P_VA_GPIO + 0xB04)
+#define S5PV210_EXT_INT_SVC (S5P_VA_GPIO + 0xB08)
+#define S5PV210_EXT_INT_SVC_PND (S5P_VA_GPIO + 0xB0C)
+#define S5PV210_EXT_INT_GRPFIXPRI (S5P_VA_GPIO + 0xB10)
+
#define S5PV210_EINT30CON (S5P_VA_GPIO + 0xE00)
#define S5P_EINT_CON(x) (S5PV210_EINT30CON + ((x) * 0x4))
#define S5PV210_EINT30FLTCON0 (S5P_VA_GPIO + 0xE80)
-#define S5P_EINT_FLTCON(x) (S5PV210_EINT30FLTCON0 + ((x) * 0x4))
+#define S5P_EINT_FLTCON(x,y) (S5PV210_EINT30FLTCON0 + ((x) * 0x8) + ((y) * 0x4))
#define S5PV210_EINT30MASK (S5P_VA_GPIO + 0xF00)
#define S5P_EINT_MASK(x) (S5PV210_EINT30MASK + ((x) * 0x4))
@@ -29,8 +248,16 @@
#define EINT_REG_NR(x) (EINT_OFFSET(x) >> 3)
+#define eint_offset(irq) ((irq) < IRQ_EINT16_31 ? ((irq)-IRQ_EINT0)\
+ : (irq-S5P_IRQ_EINT_BASE))
+
#define eint_irq_to_bit(irq) (1 << (EINT_OFFSET(irq) & 0x7))
+#define eint_conf_reg(irq) ((eint_offset(irq)) >> 3)
+#define eint_filt_reg(irq) ((eint_offset(irq)) >> 2)
+#define eint_mask_reg(irq) ((eint_offset(irq)) >> 3)
+#define eint_pend_reg(irq) ((eint_offset(irq)) >> 3)
+
#define EINT_MODE S3C_GPIO_SFN(0xf)
#define EINT_GPIO_0(x) S5PV210_GPH0(x)
diff --git a/arch/arm/mach-s5pv210/include/mach/regs-irq.h b/arch/arm/mach-s5pv210/include/mach/regs-irq.h
index 5c3b104..e3b86f1 100644
--- a/arch/arm/mach-s5pv210/include/mach/regs-irq.h
+++ b/arch/arm/mach-s5pv210/include/mach/regs-irq.h
@@ -16,4 +16,10 @@
#include <asm/hardware/vic.h>
#include <mach/map.h>
+/* interrupt controller */
+#define S5P_VIC0REG(x) ((x) + S5P_VA_VIC0)
+#define S5P_VIC1REG(x) ((x) + S5P_VA_VIC1)
+#define S5P_VIC2REG(x) ((x) + S5P_VA_VIC2)
+#define S5P_VIC3REG(x) ((x) + S5P_VA_VIC3)
+
#endif /* __ASM_ARCH_REGS_IRQ_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/regs-mem.h b/arch/arm/mach-s5pv210/include/mach/regs-mem.h
new file mode 100644
index 0000000..1c79d54
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/regs-mem.h
@@ -0,0 +1,28 @@
+/* linux/arch/arm/mach-s5pv210/include/mach/regs-mem.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * S5PV210 - Memory Control register definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_REGS_MEM_H
+#define __ASM_ARCH_REGS_MEM_H __FILE__
+
+#include <mach/map.h>
+
+#define S5P_MEMREG(x) (S5P_VA_SROMC + (x))
+
+#define S5P_SROM_BW S5P_MEMREG(0x00)
+#define S5P_SROM_BC0 S5P_MEMREG(0x04)
+#define S5P_SROM_BC1 S5P_MEMREG(0x08)
+#define S5P_SROM_BC2 S5P_MEMREG(0x0C)
+#define S5P_SROM_BC3 S5P_MEMREG(0x10)
+#define S5P_SROM_BC4 S5P_MEMREG(0x14)
+#define S5P_SROM_BC5 S5P_MEMREG(0x18)
+
+#endif /* __ASM_ARCH_REGS_MEM_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/tick.h b/arch/arm/mach-s5pv210/include/mach/tick.h
index 7993b36..9fc5a8d 100644
--- a/arch/arm/mach-s5pv210/include/mach/tick.h
+++ b/arch/arm/mach-s5pv210/include/mach/tick.h
@@ -21,6 +21,12 @@ static inline u32 s3c24xx_ostimer_pending(void)
return pend & (1 << (IRQ_TIMER4_VIC - S5P_IRQ_VIC0(0)));
}
+static inline u32 s5p_ostimer_pending(void)
+{
+ u32 pend = __raw_readl(VA_VIC0 + VIC_RAW_STATUS);
+ return pend & (1 << (IRQ_SYSTIMER - S5P_IRQ_VIC0(0)));
+}
+
#define TICK_MAX (0xffffffff)
#endif /* __ASM_ARCH_TICK_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/vmalloc.h b/arch/arm/mach-s5pv210/include/mach/vmalloc.h
index a6c659d..223e21a 100644
--- a/arch/arm/mach-s5pv210/include/mach/vmalloc.h
+++ b/arch/arm/mach-s5pv210/include/mach/vmalloc.h
@@ -17,6 +17,6 @@
#ifndef __ASM_ARCH_VMALLOC_H
#define __ASM_ARCH_VMALLOC_H __FILE__
-#define VMALLOC_END 0xF6000000UL
+#define VMALLOC_END (0xFC000000)
#endif /* __ASM_ARCH_VMALLOC_H */
diff --git a/arch/arm/mach-s5pv210/init.c b/arch/arm/mach-s5pv210/init.c
index 4865ae2..aca3789 100644
--- a/arch/arm/mach-s5pv210/init.c
+++ b/arch/arm/mach-s5pv210/init.c
@@ -20,7 +20,7 @@
static struct s3c24xx_uart_clksrc s5pv210_serial_clocks[] = {
[0] = {
- .name = "pclk",
+ .name = "sclk",
.divisor = 1,
.min_baud = 0,
.max_baud = 0,
diff --git a/arch/arm/mach-s5pv210/mach-herring.c b/arch/arm/mach-s5pv210/mach-herring.c
new file mode 100755
index 0000000..78ae1fd
--- /dev/null
+++ b/arch/arm/mach-s5pv210/mach-herring.c
@@ -0,0 +1,6162 @@
+/* linux/arch/arm/mach-s5pv210/mach-herring.c
+ *
+ * Copyright (c) 2010 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 version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+#include <linux/gpio.h>
+#include <linux/gpio_event.h>
+#include <linux/videodev2.h>
+#include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
+#include <linux/regulator/consumer.h>
+#include <linux/mfd/max8998.h>
+#include <linux/i2c/ak8973.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/usb/ch9.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_gpio.h>
+#include <linux/clk.h>
+#include <linux/usb/ch9.h>
+#include <linux/input/cypress-touchkey.h>
+#include <linux/input.h>
+#include <linux/irq.h>
+#include <linux/skbuff.h>
+#include <linux/console.h>
+#include <linux/earlysuspend.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/system.h>
+
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/gpio.h>
+#include <mach/gpio-herring.h>
+#include <mach/adc.h>
+#include <mach/param.h>
+#include <mach/system.h>
+
+#include <linux/usb/gadget.h>
+#include <linux/fsa9480.h>
+#include <linux/pn544.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/wlan_plat.h>
+#include <linux/mfd/wm8994/wm8994_pdata.h>
+
+#ifdef CONFIG_ANDROID_PMEM
+#include <linux/android_pmem.h>
+#endif
+#include <plat/media.h>
+#include <mach/media.h>
+
+#ifdef CONFIG_S5PV210_POWER_DOMAIN
+#include <mach/power-domain.h>
+#endif
+#include <mach/cpu-freq-v210.h>
+
+#include <media/s5ka3dfx_platform.h>
+#include <media/s5k4ecgx.h>
+
+#include <plat/regs-serial.h>
+#include <plat/s5pv210.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+#include <plat/fb.h>
+#include <plat/mfc.h>
+#include <plat/iic.h>
+#include <plat/pm.h>
+#include <plat/s5p-time.h>
+
+#include <plat/sdhci.h>
+#include <plat/fimc.h>
+#include <plat/jpeg.h>
+#include <plat/clock.h>
+#include <plat/regs-otg.h>
+#include <linux/gp2a.h>
+#include <linux/kr3dm.h>
+#include <linux/input/k3g.h>
+#include <../../../drivers/video/samsung/s3cfb.h>
+#include <linux/sec_jack.h>
+#include <linux/input/mxt224.h>
+#include <linux/max17040_battery.h>
+#include <linux/mfd/max8998.h>
+#include <linux/regulator/max8893.h>
+#include <linux/wimax/samsung/wimax732.h>
+#include <linux/switch.h>
+
+#include "herring.h"
+
+struct class *sec_class;
+EXPORT_SYMBOL(sec_class);
+
+struct device *switch_dev;
+EXPORT_SYMBOL(switch_dev);
+
+void (*sec_set_param_value)(int idx, void *value);
+EXPORT_SYMBOL(sec_set_param_value);
+
+void (*sec_get_param_value)(int idx, void *value);
+EXPORT_SYMBOL(sec_get_param_value);
+
+unsigned int is_device_lcd;
+
+#define REBOOT_MODE_FAST_BOOT 7
+
+#define PREALLOC_WLAN_SEC_NUM 4
+#define PREALLOC_WLAN_BUF_NUM 160
+#define PREALLOC_WLAN_SECTION_HEADER 24
+
+#define WLAN_SECTION_SIZE_0 (PREALLOC_WLAN_BUF_NUM * 128)
+#define WLAN_SECTION_SIZE_1 (PREALLOC_WLAN_BUF_NUM * 128)
+#define WLAN_SECTION_SIZE_2 (PREALLOC_WLAN_BUF_NUM * 512)
+#define WLAN_SECTION_SIZE_3 (PREALLOC_WLAN_BUF_NUM * 1024)
+
+#define WLAN_SKB_BUF_NUM 16
+
+static struct sk_buff *wlan_static_skb[WLAN_SKB_BUF_NUM];
+
+struct wifi_mem_prealloc {
+ void *mem_ptr;
+ unsigned long size;
+};
+
+static int herring_notifier_call(struct notifier_block *this,
+ unsigned long code, void *_cmd)
+{
+ int mode = REBOOT_MODE_NONE;
+
+ if ((code == SYS_RESTART) && _cmd) {
+ if (!strcmp((char *)_cmd, "recovery"))
+ mode = REBOOT_MODE_RECOVERY;
+ else if (!strcmp((char *)_cmd, "bootloader"))
+ mode = REBOOT_MODE_FAST_BOOT;
+ else
+ mode = REBOOT_MODE_NONE;
+ }
+ __raw_writel(mode, S5P_INFORM6);
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block herring_reboot_notifier = {
+ .notifier_call = herring_notifier_call,
+};
+
+static void gps_gpio_init(void)
+{
+ struct device *gps_dev;
+
+ gps_dev = device_create(sec_class, NULL, 0, NULL, "gps");
+ if (IS_ERR(gps_dev)) {
+ pr_err("Failed to create device(gps)!\n");
+ goto err;
+ }
+
+ gpio_request(GPIO_GPS_nRST, "GPS_nRST"); /* XMMC3CLK */
+ s3c_gpio_setpull(GPIO_GPS_nRST, S3C_GPIO_PULL_NONE);
+ s3c_gpio_cfgpin(GPIO_GPS_nRST, S3C_GPIO_OUTPUT);
+ gpio_direction_output(GPIO_GPS_nRST, 1);
+
+ gpio_request(GPIO_GPS_PWR_EN, "GPS_PWR_EN"); /* XMMC3CLK */
+ s3c_gpio_setpull(GPIO_GPS_PWR_EN, S3C_GPIO_PULL_NONE);
+ s3c_gpio_cfgpin(GPIO_GPS_PWR_EN, S3C_GPIO_OUTPUT);
+ gpio_direction_output(GPIO_GPS_PWR_EN, 0);
+
+ s3c_gpio_setpull(GPIO_GPS_RXD, S3C_GPIO_PULL_UP);
+ gpio_export(GPIO_GPS_nRST, 1);
+ gpio_export(GPIO_GPS_PWR_EN, 1);
+
+ gpio_export_link(gps_dev, "GPS_nRST", GPIO_GPS_nRST);
+ gpio_export_link(gps_dev, "GPS_PWR_EN", GPIO_GPS_PWR_EN);
+
+ err:
+ return;
+}
+
+static void uart_switch_init(void)
+{
+ int ret;
+ struct device *uartswitch_dev;
+
+ uartswitch_dev = device_create(sec_class, NULL, 0, NULL, "uart_switch");
+ if (IS_ERR(uartswitch_dev)) {
+ pr_err("Failed to create device(uart_switch)!\n");
+ return;
+ }
+
+ ret = gpio_request(GPIO_UART_SEL, "UART_SEL");
+ if (ret < 0) {
+ pr_err("Failed to request GPIO_UART_SEL!\n");
+ return;
+ }
+ s3c_gpio_setpull(GPIO_UART_SEL, S3C_GPIO_PULL_NONE);
+ s3c_gpio_cfgpin(GPIO_UART_SEL, S3C_GPIO_OUTPUT);
+
+ gpio_direction_output(GPIO_UART_SEL, 1);
+
+ gpio_export(GPIO_UART_SEL, 1);
+
+ gpio_export_link(uartswitch_dev, "UART_SEL", GPIO_UART_SEL);
+
+ if (herring_is_cdma_wimax_dev()) {
+ ret = gpio_request(GPIO_UART_SEL1, "UART_SEL1");
+ if (ret < 0) {
+ pr_err("Failed to request GPIO_UART_SEL1!\n");
+ gpio_free(GPIO_UART_SEL);
+ return;
+ }
+
+ s3c_gpio_cfgpin(GPIO_UART_SEL1, S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(GPIO_UART_SEL1, S3C_GPIO_PULL_NONE);
+ gpio_direction_output(GPIO_UART_SEL1, 0);
+
+ gpio_export(GPIO_UART_SEL1, 1);
+ gpio_export_link(uartswitch_dev, "UART_SEL1", GPIO_UART_SEL1);
+ }
+}
+
+static void herring_switch_init(void)
+{
+ sec_class = class_create(THIS_MODULE, "sec");
+
+ if (IS_ERR(sec_class))
+ pr_err("Failed to create class(sec)!\n");
+
+ switch_dev = device_create(sec_class, NULL, 0, NULL, "switch");
+
+ if (IS_ERR(switch_dev))
+ pr_err("Failed to create device(switch)!\n");
+};
+
+/* Following are default values for UCON, ULCON and UFCON UART registers */
+#define S5PV210_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
+ S3C2410_UCON_RXILEVEL | \
+ S3C2410_UCON_TXIRQMODE | \
+ S3C2410_UCON_RXIRQMODE | \
+ S3C2410_UCON_RXFIFO_TOI | \
+ S3C2443_UCON_RXERR_IRQEN)
+
+#define S5PV210_ULCON_DEFAULT S3C2410_LCON_CS8
+
+#define S5PV210_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \
+ S5PV210_UFCON_TXTRIG4 | \
+ S5PV210_UFCON_RXTRIG4)
+
+static struct s3c2410_uartcfg herring_uartcfgs[] __initdata = {
+ {
+ .hwport = 0,
+ .flags = 0,
+ .ucon = S5PV210_UCON_DEFAULT,
+ .ulcon = S5PV210_ULCON_DEFAULT,
+ .ufcon = S5PV210_UFCON_DEFAULT,
+ .wake_peer = herring_bt_uart_wake_peer,
+ },
+ {
+ .hwport = 1,
+ .flags = 0,
+ .ucon = S5PV210_UCON_DEFAULT,
+ .ulcon = S5PV210_ULCON_DEFAULT,
+ .ufcon = S5PV210_UFCON_DEFAULT,
+ },
+#ifndef CONFIG_FIQ_DEBUGGER
+ {
+ .hwport = 2,
+ .flags = 0,
+ .ucon = S5PV210_UCON_DEFAULT,
+ .ulcon = S5PV210_ULCON_DEFAULT,
+ .ufcon = S5PV210_UFCON_DEFAULT,
+ },
+#endif
+ {
+ .hwport = 3,
+ .flags = 0,
+ .ucon = S5PV210_UCON_DEFAULT,
+ .ulcon = S5PV210_ULCON_DEFAULT,
+ .ufcon = S5PV210_UFCON_DEFAULT,
+ },
+};
+
+#define S5PV210_LCD_WIDTH 480
+#define S5PV210_LCD_HEIGHT 800
+
+static struct s3cfb_lcd s6e63m0 = {
+ .width = S5PV210_LCD_WIDTH,
+ .height = S5PV210_LCD_HEIGHT,
+ .p_width = 52,
+ .p_height = 86,
+ .bpp = 24,
+ .freq = 60,
+
+ .timing = {
+ .h_fp = 16,
+ .h_bp = 16,
+ .h_sw = 2,
+ .v_fp = 28,
+ .v_fpe = 1,
+ .v_bp = 1,
+ .v_bpe = 1,
+ .v_sw = 2,
+ },
+ .polarity = {
+ .rise_vclk = 1,
+ .inv_hsync = 1,
+ .inv_vsync = 1,
+ .inv_vden = 1,
+ },
+};
+
+static struct s3cfb_lcd nt35580 = {
+ .width = 480,
+ .height = 800,
+ .p_width = 52,
+ .p_height = 86,
+ .bpp = 24,
+ .freq = 60,
+ .timing = {
+ .h_fp = 10,
+ .h_bp = 20,
+ .h_sw = 10,
+ .v_fp = 6,
+ .v_fpe = 1,
+ .v_bp = 8,
+ .v_bpe = 1,
+ .v_sw = 2,
+ },
+ .polarity = {
+ .rise_vclk = 1,
+ .inv_hsync = 1,
+ .inv_vsync = 1,
+ .inv_vden = 1,
+ },
+};
+
+static struct s3cfb_lcd r61408 = {
+ .width = 480,
+ .height = 800,
+ .p_width = 52,
+ .p_height = 86,
+ .bpp = 24,
+ .freq = 60,
+ .timing = {
+ .h_fp = 100,
+ .h_bp = 2,
+ .h_sw = 2,
+ .v_fp = 8,
+ .v_fpe = 1,
+ .v_bp = 10,
+ .v_bpe = 1,
+ .v_sw = 2,
+ },
+ .polarity = {
+ .rise_vclk = 1,
+ .inv_hsync = 1,
+ .inv_vsync = 1,
+ .inv_vden = 0,
+ },
+};
+
+#define S5PV210_VIDEO_SAMSUNG_MEMSIZE_FIMC0 (6144 * SZ_1K)
+// #define S5PV210_VIDEO_SAMSUNG_MEMSIZE_FIMC1 (4 * SZ_1K)
+#define S5PV210_VIDEO_SAMSUNG_MEMSIZE_FIMC2 (6144 * SZ_1K)
+#define S5PV210_VIDEO_SAMSUNG_MEMSIZE_MFC0 (11264 * SZ_1K) // 11Mb
+#define S5PV210_VIDEO_SAMSUNG_MEMSIZE_MFC1 (11264 * SZ_1K) // 11Mb
+#define S5PV210_VIDEO_SAMSUNG_MEMSIZE_FIMD (S5PV210_LCD_WIDTH * \
+ S5PV210_LCD_HEIGHT * 4 * \
+ (CONFIG_FB_S3C_NR_BUFFERS + \
+ (CONFIG_FB_S3C_NUM_OVLY_WIN * \
+ CONFIG_FB_S3C_NUM_BUF_OVLY_WIN)))
+#define S5PV210_VIDEO_SAMSUNG_MEMSIZE_JPEG (4092 * SZ_1K)
+
+static struct s5p_media_device herring_media_devs[] = {
+ [0] = {
+ .id = S5P_MDEV_MFC,
+ .name = "mfc",
+ .bank = 0,
+ .memsize = S5PV210_VIDEO_SAMSUNG_MEMSIZE_MFC0,
+ .paddr = 0,
+ },
+ [1] = {
+ .id = S5P_MDEV_MFC,
+ .name = "mfc",
+ .bank = 1,
+ .memsize = S5PV210_VIDEO_SAMSUNG_MEMSIZE_MFC1,
+ .paddr = 0,
+ },
+ [2] = {
+ .id = S5P_MDEV_FIMC0,
+ .name = "fimc0",
+ .bank = 1,
+ .memsize = S5PV210_VIDEO_SAMSUNG_MEMSIZE_FIMC0,
+ .paddr = 0,
+ },
+ [4] = {
+ .id = S5P_MDEV_FIMC2,
+ .name = "fimc2",
+ .bank = 1,
+ .memsize = S5PV210_VIDEO_SAMSUNG_MEMSIZE_FIMC2,
+ .paddr = 0,
+ },
+ [5] = {
+ .id = S5P_MDEV_JPEG,
+ .name = "jpeg",
+ .bank = 0,
+ .memsize = S5PV210_VIDEO_SAMSUNG_MEMSIZE_JPEG,
+ .paddr = 0,
+ },
+ [6] = {
+ .id = S5P_MDEV_FIMD,
+ .name = "fimd",
+ .bank = 1,
+ .memsize = S5PV210_VIDEO_SAMSUNG_MEMSIZE_FIMD,
+ .paddr = 0,
+ },
+};
+
+#ifdef CONFIG_CPU_FREQ
+static struct s5pv210_cpufreq_voltage smdkc110_cpufreq_volt[] = {
+ {
+ .freq = 1400000,
+ .varm = 1420000,
+ .vint = 1180000,
+ }, {
+ .freq = 1200000,
+ .varm = 1320000,
+ .vint = 1110000,
+ }, {
+ .freq = 1000000,
+ .varm = 1275000,
+ .vint = 1100000,
+ }, {
+ .freq = 800000,
+ .varm = 1200000,
+ .vint = 1100000,
+ }, {
+ .freq = 400000,
+ .varm = 1050000,
+ .vint = 1100000,
+ }, {
+ .freq = 200000,
+ .varm = 950000,
+ .vint = 1100000,
+ }, {
+ .freq = 100000,
+ .varm = 950000,
+ .vint = 1000000,
+ },
+};
+
+static struct s5pv210_cpufreq_data smdkc110_cpufreq_plat = {
+ .volt = smdkc110_cpufreq_volt,
+ .size = ARRAY_SIZE(smdkc110_cpufreq_volt),
+};
+#endif
+
+static struct regulator_consumer_supply ldo3_consumer[] = {
+ REGULATOR_SUPPLY("pd_io", "s3c-usbgadget")
+};
+
+static struct regulator_consumer_supply ldo7_consumer[] = {
+ { .supply = "vlcd", },
+};
+
+static struct regulator_consumer_supply ldo8_consumer[] = {
+ REGULATOR_SUPPLY("pd_core", "s3c-usbgadget")
+};
+
+static struct regulator_consumer_supply ldo11_consumer[] = {
+ { .supply = "cam_af", },
+};
+
+static struct regulator_consumer_supply ldo12_consumer[] = {
+ { .supply = "cam_sensor", },
+};
+
+static struct regulator_consumer_supply ldo13_consumer[] = {
+ { .supply = "vga_vddio", },
+};
+
+static struct regulator_consumer_supply ldo14_consumer[] = {
+ { .supply = "vga_dvdd", },
+};
+
+static struct regulator_consumer_supply ldo15_consumer[] = {
+ { .supply = "cam_isp_host", },
+};
+
+static struct regulator_consumer_supply ldo16_consumer[] = {
+ { .supply = "vga_avdd", },
+};
+
+static struct regulator_consumer_supply ldo17_consumer[] = {
+ { .supply = "vcc_lcd", },
+};
+
+static struct regulator_consumer_supply buck1_consumer[] = {
+ { .supply = "vddarm", },
+};
+
+static struct regulator_consumer_supply buck2_consumer[] = {
+ { .supply = "vddint", },
+};
+
+static struct regulator_consumer_supply buck4_consumer[] = {
+ { .supply = "cam_isp_core", },
+};
+
+static struct regulator_init_data herring_ldo2_data = {
+ .constraints = {
+ .name = "VALIVE_1.2V",
+ .min_uV = 1200000,
+ .max_uV = 1200000,
+ .apply_uV = 1,
+ .always_on = 1,
+ .state_mem = {
+ .enabled = 1,
+ },
+ },
+};
+
+static struct regulator_init_data herring_ldo3_data = {
+ .constraints = {
+ .name = "VUSB_1.1V",
+ .min_uV = 1100000,
+ .max_uV = 1100000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(ldo3_consumer),
+ .consumer_supplies = ldo3_consumer,
+};
+
+static struct regulator_init_data herring_ldo4_data = {
+ .constraints = {
+ .name = "VADC_3.3V",
+ .min_uV = 3300000,
+ .max_uV = 3300000,
+ .apply_uV = 1,
+ .always_on = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+};
+
+static struct regulator_init_data herring_ldo7_data = {
+ .constraints = {
+ .name = "VLCD_1.8V",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .apply_uV = 1,
+ .always_on = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(ldo7_consumer),
+ .consumer_supplies = ldo7_consumer,
+};
+
+static struct regulator_init_data herring_ldo8_data = {
+ .constraints = {
+ .name = "VUSB_3.3V",
+ .min_uV = 3300000,
+ .max_uV = 3300000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(ldo8_consumer),
+ .consumer_supplies = ldo8_consumer,
+};
+
+static struct regulator_init_data herring_ldo9_data = {
+ .constraints = {
+ .name = "VCC_2.8V_PDA",
+ .min_uV = 2800000,
+ .max_uV = 2800000,
+ .apply_uV = 1,
+ .always_on = 1,
+ },
+};
+
+static struct regulator_init_data herring_ldo11_data = {
+ .constraints = {
+ .name = "CAM_AF_3.0V",
+ .min_uV = 3000000,
+ .max_uV = 3000000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(ldo11_consumer),
+ .consumer_supplies = ldo11_consumer,
+};
+
+static struct regulator_init_data herring_ldo12_data = {
+ .constraints = {
+ .name = "CAM_SENSOR_CORE_1.2V",
+ .min_uV = 1200000,
+ .max_uV = 1200000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(ldo12_consumer),
+ .consumer_supplies = ldo12_consumer,
+};
+
+static struct regulator_init_data herring_ldo13_data = {
+ .constraints = {
+ .name = "VGA_VDDIO_2.8V",
+ .min_uV = 2800000,
+ .max_uV = 2800000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(ldo13_consumer),
+ .consumer_supplies = ldo13_consumer,
+};
+
+static struct regulator_init_data herring_ldo14_data = {
+ .constraints = {
+ .name = "VGA_DVDD_1.8V",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(ldo14_consumer),
+ .consumer_supplies = ldo14_consumer,
+};
+
+static struct regulator_init_data herring_ldo15_data = {
+ .constraints = {
+ .name = "CAM_ISP_HOST_2.8V",
+ .min_uV = 2800000,
+ .max_uV = 2800000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(ldo15_consumer),
+ .consumer_supplies = ldo15_consumer,
+};
+
+static struct regulator_init_data herring_ldo16_data = {
+ .constraints = {
+ .name = "VGA_AVDD_2.8V",
+ .min_uV = 2800000,
+ .max_uV = 2800000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(ldo16_consumer),
+ .consumer_supplies = ldo16_consumer,
+};
+
+static struct regulator_init_data herring_ldo17_data = {
+ .constraints = {
+ .name = "VCC_3.0V_LCD",
+ .min_uV = 3000000,
+ .max_uV = 3000000,
+ .apply_uV = 1,
+ .always_on = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(ldo17_consumer),
+ .consumer_supplies = ldo17_consumer,
+};
+
+static struct regulator_init_data herring_buck1_data = {
+ .constraints = {
+ .name = "VDD_ARM",
+ .min_uV = 750000,
+ .max_uV = 1600000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .uV = 1600000,
+ .mode = REGULATOR_MODE_NORMAL,
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(buck1_consumer),
+ .consumer_supplies = buck1_consumer,
+};
+
+static struct regulator_init_data herring_buck2_data = {
+ .constraints = {
+ .name = "VDD_INT",
+ .min_uV = 750000,
+ .max_uV = 1500000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .uV = 1250000,
+ .mode = REGULATOR_MODE_NORMAL,
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(buck2_consumer),
+ .consumer_supplies = buck2_consumer,
+};
+
+static struct regulator_init_data herring_buck3_data = {
+ .constraints = {
+ .name = "VCC_1.8V",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .apply_uV = 1,
+ .always_on = 1,
+ },
+};
+
+static struct regulator_init_data herring_buck4_data = {
+ .constraints = {
+ .name = "CAM_ISP_CORE_1.2V",
+ .min_uV = 1200000,
+ .max_uV = 1200000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .state_mem = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(buck4_consumer),
+ .consumer_supplies = buck4_consumer,
+};
+
+static struct max8998_regulator_data herring_regulators[] = {
+ { MAX8998_LDO2, &herring_ldo2_data },
+ { MAX8998_LDO3, &herring_ldo3_data },
+ { MAX8998_LDO4, &herring_ldo4_data },
+ { MAX8998_LDO7, &herring_ldo7_data },
+ { MAX8998_LDO8, &herring_ldo8_data },
+ { MAX8998_LDO9, &herring_ldo9_data },
+ { MAX8998_LDO11, &herring_ldo11_data },
+ { MAX8998_LDO12, &herring_ldo12_data },
+ { MAX8998_LDO13, &herring_ldo13_data },
+ { MAX8998_LDO14, &herring_ldo14_data },
+ { MAX8998_LDO15, &herring_ldo15_data },
+ { MAX8998_LDO16, &herring_ldo16_data },
+ { MAX8998_LDO17, &herring_ldo17_data },
+ { MAX8998_BUCK1, &herring_buck1_data },
+ { MAX8998_BUCK2, &herring_buck2_data },
+ { MAX8998_BUCK3, &herring_buck3_data },
+ { MAX8998_BUCK4, &herring_buck4_data },
+};
+
+static struct max8998_regulator_data herring_cdma_wimax_regulators[] = {
+ { MAX8998_LDO2, &herring_ldo2_data },
+ { MAX8998_LDO3, &herring_ldo3_data },
+ { MAX8998_LDO4, &herring_ldo4_data },
+ { MAX8998_LDO7, &herring_ldo7_data },
+ { MAX8998_LDO8, &herring_ldo8_data },
+ { MAX8998_LDO9, &herring_ldo9_data },
+ { MAX8998_LDO11, &herring_ldo11_data },
+ { MAX8998_LDO13, &herring_ldo13_data },
+ { MAX8998_LDO14, &herring_ldo14_data },
+ { MAX8998_LDO15, &herring_ldo15_data },
+ { MAX8998_LDO16, &herring_ldo16_data },
+ { MAX8998_LDO17, &herring_ldo17_data },
+ { MAX8998_BUCK1, &herring_buck1_data },
+ { MAX8998_BUCK2, &herring_buck2_data },
+ { MAX8998_BUCK3, &herring_buck3_data },
+ { MAX8998_BUCK4, &herring_buck4_data },
+};
+
+static struct max8998_adc_table_data temper_table_oled[] = {
+ /* ADC, Temperature (C/10) */
+ { 222, 700 },
+ { 230, 690 },
+ { 238, 680 },
+ { 245, 670 },
+ { 253, 660 },
+ { 261, 650 },
+ { 274, 640 },
+ { 287, 630 },
+ { 300, 620 },
+ { 314, 610 },
+ { 327, 600 },
+ { 339, 590 },
+ { 350, 580 },
+ { 362, 570 },
+ { 374, 560 },
+ { 386, 550 },
+ { 401, 540 },
+ { 415, 530 },
+ { 430, 520 },
+ { 444, 510 },
+ { 459, 500 },
+ { 477, 490 },
+ { 495, 480 },
+ { 513, 470 },
+ { 526, 460 },
+ { 539, 450 },
+ { 559, 440 },
+ { 580, 430 },
+ { 600, 420 },
+ { 618, 410 },
+ { 642, 400 },
+ { 649, 390 },
+ { 674, 380 },
+ { 695, 370 },
+ { 717, 360 },
+ { 739, 350 },
+ { 760, 340 },
+ { 782, 330 },
+ { 803, 320 },
+ { 825, 310 },
+ { 847, 300 },
+ { 870, 290 },
+ { 894, 280 },
+ { 918, 270 },
+ { 942, 260 },
+ { 966, 250 },
+ { 990, 240 },
+ { 1014, 230 },
+ { 1038, 220 },
+ { 1062, 210 },
+ { 1086, 200 },
+ { 1110, 190 },
+ { 1134, 180 },
+ { 1158, 170 },
+ { 1182, 160 },
+ { 1206, 150 },
+ { 1228, 140 },
+ { 1251, 130 },
+ { 1274, 120 },
+ { 1297, 110 },
+ { 1320, 100 },
+ { 1341, 90 },
+ { 1362, 80 },
+ { 1384, 70 },
+ { 1405, 60 },
+ { 1427, 50 },
+ { 1450, 40 },
+ { 1474, 30 },
+ { 1498, 20 },
+ { 1514, 10 },
+ { 1533, 0 },
+ { 1544, (-10) },
+ { 1567, (-20) },
+ { 1585, (-30) },
+ { 1604, (-40) },
+ { 1623, (-50) },
+ { 1641, (-60) },
+ { 1659, (-70) },
+ { 1678, (-80) },
+ { 1697, (-90) },
+ { 1715, (-100) },
+};
+static struct max8998_adc_table_data temper_table_tft[] = {
+ /* ADC, Temperature (C/10) */
+ { 242, 700 },
+ { 253, 690 },
+ { 264, 680 },
+ { 275, 670 },
+ { 286, 660 },
+ { 297, 650 },
+ { 310, 640 },
+ { 323, 630 },
+ { 336, 620 },
+ { 349, 610 },
+ { 362, 600 },
+ { 375, 590 },
+ { 388, 580 },
+ { 401, 570 },
+ { 414, 560 },
+ { 430, 550 },
+ { 444, 540 },
+ { 458, 530 },
+ { 472, 520 },
+ { 486, 510 },
+ { 500, 500 },
+ { 515, 490 },
+ { 530, 480 },
+ { 545, 470 },
+ { 560, 460 },
+ { 575, 450 },
+ { 590, 440 },
+ { 605, 430 },
+ { 625, 420 },
+ { 645, 410 },
+ { 665, 400 },
+ { 683, 390 },
+ { 702, 380 },
+ { 735, 370 },
+ { 768, 360 },
+ { 768, 350 },
+ { 790, 340 },
+ { 812, 330 },
+ { 834, 320 },
+ { 856, 310 },
+ { 881, 300 },
+ { 905, 290 },
+ { 929, 280 },
+ { 955, 270 },
+ { 979, 260 },
+ { 1002, 250 },
+ { 1027, 240 },
+ { 1053, 230 },
+ { 1078, 220 },
+ { 1105, 210 },
+ { 1130, 200 },
+ { 1151, 190 },
+ { 1174, 180 },
+ { 1195, 170 },
+ { 1219, 160 },
+ { 1237, 150 },
+ { 1261, 140 },
+ { 1285, 130 },
+ { 1309, 120 },
+ { 1331, 110 },
+ { 1359, 100 },
+ { 1381, 90 },
+ { 1404, 80 },
+ { 1426, 70 },
+ { 1438, 60 },
+ { 1470, 50 },
+ { 1488, 40 },
+ { 1506, 30 },
+ { 1524, 20 },
+ { 1532, 10 },
+ { 1560, 0 },
+ { 1586, (-10) },
+ { 1604, (-20) },
+ { 1614, (-30) },
+ { 1622, (-40) },
+ { 1630, (-50) },
+ { 1648, (-60) },
+ { 1666, (-70) },
+ { 1684, (-80) },
+ { 1702, (-90) },
+ { 1720, (-100) },
+};
+
+static struct max8998_adc_table_data temper_table_cdma_wimax_oled[] = {
+ /* ADC, Temperature (C/10) */
+ { 116, 700 },
+ { 122, 690 },
+ { 128, 680 },
+ { 134, 670 },
+ { 140, 660 },
+ { 146, 650 },
+ { 152, 640 },
+ { 158, 630 },
+ { 164, 620 },
+ { 170, 610 },
+ { 176, 600 },
+ { 182, 590 },
+ { 188, 580 },
+ { 194, 570 },
+ { 200, 560 },
+ { 206, 550 },
+ { 212, 540 },
+ { 218, 530 },
+ { 222, 520 },
+ { 230, 510 },
+ { 238, 500 },
+ { 245, 490 },
+ { 260, 480 },
+ { 290, 470 },
+ { 325, 460 },
+ { 360, 450 },
+ { 395, 440 },
+ { 430, 430 },
+ { 465, 420 },
+ { 500, 410 },
+ { 535, 400 },
+ { 575, 390 },
+ { 615, 380 },
+ { 642, 370 },
+ { 695, 360 },
+ { 717, 350 },
+ { 737, 340 },
+ { 760, 330 },
+ { 782, 320 },
+ { 803, 310 },
+ { 825, 300 },
+ { 847, 290 },
+ { 870, 280 },
+ { 900, 270 },
+ { 942, 260 },
+ { 966, 250 },
+ { 990, 240 },
+ { 1014, 230 },
+ { 1038, 220 },
+ { 1062, 210 },
+ { 1086, 200 },
+ { 1110, 190 },
+ { 1134, 180 },
+ { 1158, 170 },
+ { 1182, 160 },
+ { 1206, 150 },
+ { 1228, 140 },
+ { 1251, 130 },
+ { 1274, 120 },
+ { 1297, 110 },
+ { 1320, 100 },
+ { 1341, 90 },
+ { 1362, 80 },
+ { 1384, 70 },
+ { 1405, 60 },
+ { 1427, 50 },
+ { 1450, 40 },
+ { 1474, 30 },
+ { 1498, 20 },
+ { 1514, 10 },
+ { 1533, 0 },
+ { 1544, (-10) },
+ { 1567, (-20) },
+ { 1585, (-30) },
+ { 1604, (-40) },
+ { 1623, (-50) },
+ { 1641, (-60) },
+ { 1659, (-70) },
+ { 1678, (-80) },
+ { 1697, (-90) },
+ { 1715, (-100) },
+};
+
+struct max8998_charger_callbacks *callbacks;
+static enum cable_type_t set_cable_status;
+
+static void max8998_charger_register_callbacks(
+ struct max8998_charger_callbacks *ptr)
+{
+ callbacks = ptr;
+ /* if there was a cable status change before the charger was
+ ready, send this now */
+ if ((set_cable_status != 0) && callbacks && callbacks->set_cable)
+ callbacks->set_cable(callbacks, set_cable_status);
+}
+
+static struct max8998_charger_data herring_charger = {
+ .register_callbacks = &max8998_charger_register_callbacks,
+};
+
+static void set_adc_table(void)
+{
+ if (!herring_is_tft_dev()) {
+ if (herring_is_cdma_wimax_dev()) {
+ herring_charger.adc_table =
+ temper_table_cdma_wimax_oled;
+ herring_charger.adc_array_size =
+ ARRAY_SIZE(temper_table_cdma_wimax_oled);
+ } else {
+ herring_charger.adc_table = temper_table_oled;
+ herring_charger.adc_array_size =
+ ARRAY_SIZE(temper_table_oled);
+ }
+ } else {
+ herring_charger.adc_table = temper_table_tft;
+ herring_charger.adc_array_size =
+ ARRAY_SIZE(temper_table_tft);
+ }
+}
+
+static struct max8998_platform_data max8998_pdata = {
+ .num_regulators = ARRAY_SIZE(herring_regulators),
+ .regulators = herring_regulators,
+ .charger = &herring_charger,
+ /* Preloads must be in increasing order of voltage value */
+ .buck1_voltage4 = 950000,
+ .buck1_voltage3 = 1050000,
+ .buck1_voltage2 = 1200000,
+ .buck1_voltage1 = 1275000,
+ .buck2_voltage2 = 1000000,
+ .buck2_voltage1 = 1100000,
+ .buck1_set1 = GPIO_BUCK_1_EN_A,
+ .buck1_set2 = GPIO_BUCK_1_EN_B,
+ .buck2_set3 = GPIO_BUCK_2_EN,
+ .buck1_default_idx = 1,
+ .buck2_default_idx = 0,
+};
+
+struct platform_device sec_device_dpram = {
+ .name = "dpram-device",
+ .id = -1,
+};
+
+static unsigned int lcd_type;
+module_param_named(lcd_type, lcd_type, uint, 0444);
+MODULE_PARM_DESC(lcd_type, "LCD type: default= sony, 1= hydis, 2= hitachi");
+
+static void panel_cfg_gpio(struct platform_device *pdev)
+{
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ s3c_gpio_cfgpin(S5PV210_GPF0(i), S3C_GPIO_SFN(2));
+ s3c_gpio_setpull(S5PV210_GPF0(i), S3C_GPIO_PULL_NONE);
+ }
+
+ for (i = 0; i < 8; i++) {
+ s3c_gpio_cfgpin(S5PV210_GPF1(i), S3C_GPIO_SFN(2));
+ s3c_gpio_setpull(S5PV210_GPF1(i), S3C_GPIO_PULL_NONE);
+ }
+
+ for (i = 0; i < 8; i++) {
+ s3c_gpio_cfgpin(S5PV210_GPF2(i), S3C_GPIO_SFN(2));
+ s3c_gpio_setpull(S5PV210_GPF2(i), S3C_GPIO_PULL_NONE);
+ }
+
+ for (i = 0; i < 4; i++) {
+ s3c_gpio_cfgpin(S5PV210_GPF3(i), S3C_GPIO_SFN(2));
+ s3c_gpio_setpull(S5PV210_GPF3(i), S3C_GPIO_PULL_NONE);
+ }
+
+ /* mDNIe SEL: why we shall write 0x2 ? */
+#ifdef CONFIG_FB_S3C_MDNIE
+ writel(0x1, S5P_MDNIE_SEL);
+#else
+ writel(0x2, S5P_MDNIE_SEL);
+#endif
+
+ /* DISPLAY_CS */
+ s3c_gpio_cfgpin(S5PV210_MP01(1), S3C_GPIO_SFN(1));
+ /* DISPLAY_CLK */
+ s3c_gpio_cfgpin(S5PV210_MP04(1), S3C_GPIO_SFN(1));
+ /* DISPLAY_SO */
+ s3c_gpio_cfgpin(S5PV210_MP04(2), S3C_GPIO_SFN(1));
+ /* DISPLAY_SI */
+ s3c_gpio_cfgpin(S5PV210_MP04(3), S3C_GPIO_SFN(1));
+
+ /* DISPLAY_CS */
+ s3c_gpio_setpull(S5PV210_MP01(1), S3C_GPIO_PULL_NONE);
+ /* DISPLAY_CLK */
+ s3c_gpio_setpull(S5PV210_MP04(1), S3C_GPIO_PULL_NONE);
+ /* DISPLAY_SO */
+ s3c_gpio_setpull(S5PV210_MP04(2), S3C_GPIO_PULL_NONE);
+ /* DISPLAY_SI */
+ s3c_gpio_setpull(S5PV210_MP04(3), S3C_GPIO_PULL_NONE);
+
+ /* OLED_ID */
+ if (herring_is_tft_dev()) {
+ s3c_gpio_cfgpin(GPIO_OLED_ID, S3C_GPIO_INPUT);
+ s3c_gpio_setpull(GPIO_OLED_ID, S3C_GPIO_PULL_DOWN);
+ }
+}
+
+void lcd_cfg_gpio_early_suspend(void)
+{
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ s3c_gpio_cfgpin(S5PV210_GPF0(i), S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(S5PV210_GPF0(i), S3C_GPIO_PULL_NONE);
+ gpio_set_value(S5PV210_GPF0(i), 0);
+ }
+
+ for (i = 0; i < 8; i++) {
+ s3c_gpio_cfgpin(S5PV210_GPF1(i), S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(S5PV210_GPF1(i), S3C_GPIO_PULL_NONE);
+ gpio_set_value(S5PV210_GPF1(i), 0);
+ }
+
+ for (i = 0; i < 8; i++) {
+ s3c_gpio_cfgpin(S5PV210_GPF2(i), S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(S5PV210_GPF2(i), S3C_GPIO_PULL_NONE);
+ gpio_set_value(S5PV210_GPF2(i), 0);
+ }
+
+ for (i = 0; i < 4; i++) {
+ s3c_gpio_cfgpin(S5PV210_GPF3(i), S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(S5PV210_GPF3(i), S3C_GPIO_PULL_NONE);
+ gpio_set_value(S5PV210_GPF3(i), 0);
+ }
+ /* drive strength to min */
+ writel(0x00000000, S5P_VA_GPIO + 0x12c); /* GPF0DRV */
+ writel(0x00000000, S5P_VA_GPIO + 0x14c); /* GPF1DRV */
+ writel(0x00000000, S5P_VA_GPIO + 0x16c); /* GPF2DRV */
+ writel(0x00000000, S5P_VA_GPIO + 0x18c); /* GPF3DRV */
+
+ /* OLED_DET */
+ s3c_gpio_cfgpin(GPIO_OLED_DET, S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(GPIO_OLED_DET, S3C_GPIO_PULL_NONE);
+ gpio_set_value(GPIO_OLED_DET, 0);
+
+ /* LCD_RST */
+ s3c_gpio_cfgpin(GPIO_MLCD_RST, S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(GPIO_MLCD_RST, S3C_GPIO_PULL_NONE);
+ gpio_set_value(GPIO_MLCD_RST, 0);
+
+ /* DISPLAY_CS */
+ s3c_gpio_cfgpin(GPIO_DISPLAY_CS, S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(GPIO_DISPLAY_CS, S3C_GPIO_PULL_NONE);
+ gpio_set_value(GPIO_DISPLAY_CS, 0);
+
+ /* DISPLAY_CLK */
+ s3c_gpio_cfgpin(GPIO_DISPLAY_CLK, S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(GPIO_DISPLAY_CLK, S3C_GPIO_PULL_NONE);
+ gpio_set_value(GPIO_DISPLAY_CLK, 0);
+
+ /* DISPLAY_SO */
+ /*
+ s3c_gpio_cfgpin(S5PV210_MP04(2), S3C_GPIO_INPUT);
+ s3c_gpio_setpull(S5PV210_MP04(2), S3C_GPIO_PULL_DOWN);
+ */
+
+ /* DISPLAY_SI */
+ s3c_gpio_cfgpin(GPIO_DISPLAY_SI, S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(GPIO_DISPLAY_SI, S3C_GPIO_PULL_NONE);
+ gpio_set_value(GPIO_DISPLAY_SI, 0);
+
+ /* OLED_ID */
+ if (!herring_is_tft_dev()) {
+ s3c_gpio_cfgpin(GPIO_OLED_ID, S3C_GPIO_INPUT);
+ s3c_gpio_setpull(GPIO_OLED_ID, S3C_GPIO_PULL_DOWN);
+ /* gpio_set_value(GPIO_OLED_ID, 0); */
+ }
+
+ /* DIC_ID */
+ s3c_gpio_cfgpin(GPIO_DIC_ID, S3C_GPIO_INPUT);
+ s3c_gpio_setpull(GPIO_DIC_ID, S3C_GPIO_PULL_DOWN);
+ /* gpio_set_value(GPIO_DIC_ID, 0); */
+}
+EXPORT_SYMBOL(lcd_cfg_gpio_early_suspend);
+
+void lcd_cfg_gpio_late_resume(void)
+{
+ /* OLED_DET */
+ s3c_gpio_cfgpin(GPIO_OLED_DET, S3C_GPIO_INPUT);
+ s3c_gpio_setpull(GPIO_OLED_DET, S3C_GPIO_PULL_NONE);
+ /* OLED_ID */
+ if (!herring_is_tft_dev()) {
+ s3c_gpio_cfgpin(GPIO_OLED_ID, S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(GPIO_OLED_ID, S3C_GPIO_PULL_NONE);
+ /* gpio_set_value(GPIO_OLED_ID, 0); */
+ }
+ /* DIC_ID */
+ s3c_gpio_cfgpin(GPIO_DIC_ID, S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(GPIO_DIC_ID, S3C_GPIO_PULL_NONE);
+ /* gpio_set_value(GPIO_DIC_ID, 0); */
+}
+EXPORT_SYMBOL(lcd_cfg_gpio_late_resume);
+
+static int panel_reset_lcd(struct platform_device *pdev)
+{
+ int err;
+
+ err = gpio_request(S5PV210_MP05(5), "MLCD_RST");
+ if (err) {
+ printk(KERN_ERR "failed to request MP0(5) for "
+ "lcd reset control\n");
+ return err;
+ }
+
+ gpio_direction_output(S5PV210_MP05(5), 1);
+ msleep(10);
+
+ gpio_set_value(S5PV210_MP05(5), 0);
+ msleep(10);
+
+ gpio_set_value(S5PV210_MP05(5), 1);
+ msleep(10);
+
+ gpio_free(S5PV210_MP05(5));
+
+ return 0;
+}
+
+static int panel_backlight_on(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static struct s3c_platform_fb tl2796_data __initdata = {
+ .hw_ver = 0x62,
+ .clk_name = "sclk_fimd",
+ .nr_wins = 5,
+ .default_win = CONFIG_FB_S3C_DEFAULT_WINDOW,
+ .swap = FB_SWAP_HWORD | FB_SWAP_WORD,
+
+ .lcd = &s6e63m0,
+ .cfg_gpio = panel_cfg_gpio,
+ .backlight_on = panel_backlight_on,
+ .reset_lcd = panel_reset_lcd,
+};
+
+static struct s3c_platform_fb nt35580_data __initdata = {
+ .hw_ver = 0x62,
+ .clk_name = "sclk_fimd",
+ .nr_wins = 5,
+ .default_win = CONFIG_FB_S3C_DEFAULT_WINDOW,
+ .swap = FB_SWAP_HWORD | FB_SWAP_WORD,
+
+ .lcd = &nt35580,
+ .cfg_gpio = panel_cfg_gpio,
+ .backlight_on = panel_backlight_on,
+ .reset_lcd = panel_reset_lcd,
+};
+
+static struct s3c_platform_fb r61408_data __initdata = {
+ .hw_ver = 0x62,
+ .clk_name = "sclk_fimd",
+ .nr_wins = 5,
+ .default_win = CONFIG_FB_S3C_DEFAULT_WINDOW,
+ .swap = FB_SWAP_HWORD | FB_SWAP_WORD,
+
+ .lcd = &r61408,
+ .cfg_gpio = panel_cfg_gpio,
+ .backlight_on = panel_backlight_on,
+ .reset_lcd = panel_reset_lcd,
+};
+
+#define LCD_BUS_NUM 3
+#define DISPLAY_CS S5PV210_MP01(1)
+#define SUB_DISPLAY_CS S5PV210_MP01(2)
+#define DISPLAY_CLK S5PV210_MP04(1)
+#define DISPLAY_SI S5PV210_MP04(3)
+
+static struct spi_board_info spi_board_info[] __initdata = {
+ {
+ .modalias = "tl2796",
+ .platform_data = &herring_panel_data,
+ .max_speed_hz = 1200000,
+ .bus_num = LCD_BUS_NUM,
+ .chip_select = 0,
+ .mode = SPI_MODE_3,
+ .controller_data = (void *)DISPLAY_CS,
+ },
+};
+
+static struct spi_board_info spi_board_info_sony[] __initdata = {
+ {
+ .modalias = "nt35580",
+ .platform_data = &herring_sony_panel_data,
+ .max_speed_hz = 1200000,
+ .bus_num = LCD_BUS_NUM,
+ .chip_select = 0,
+ .mode = SPI_MODE_3,
+ .controller_data = (void *)DISPLAY_CS,
+ },
+};
+
+static struct spi_board_info spi_board_info_hydis[] __initdata = {
+ {
+ .modalias = "nt35580",
+ .platform_data = &herring_hydis_panel_data,
+ .max_speed_hz = 1200000,
+ .bus_num = LCD_BUS_NUM,
+ .chip_select = 0,
+ .mode = SPI_MODE_3,
+ .controller_data = (void *)DISPLAY_CS,
+ },
+};
+
+static struct spi_board_info spi_board_info_hitachi[] __initdata = {
+ {
+ .modalias = "nt35580",
+ .platform_data = &herring_hitachi_panel_data,
+ .max_speed_hz = 1200000,
+ .bus_num = LCD_BUS_NUM,
+ .chip_select = 0,
+ .mode = SPI_MODE_3,
+ .controller_data = (void *)DISPLAY_CS,
+ },
+};
+
+
+static struct spi_gpio_platform_data tl2796_spi_gpio_data = {
+ .sck = DISPLAY_CLK,
+ .mosi = DISPLAY_SI,
+ .miso = -1,
+ .num_chipselect = 2,
+};
+
+static struct platform_device s3c_device_spi_gpio = {
+ .name = "spi_gpio",
+ .id = LCD_BUS_NUM,
+ .dev = {
+ .parent = &s3c_device_fb.dev,
+ .platform_data = &tl2796_spi_gpio_data,
+ },
+};
+
+static struct i2c_gpio_platform_data herring_i2c4_platdata = {
+ .sda_pin = GPIO_AP_SDA_18V,
+ .scl_pin = GPIO_AP_SCL_18V,
+ .udelay = 2, /* 250KHz */
+ .sda_is_open_drain = 0,
+ .scl_is_open_drain = 0,
+ .scl_is_output_only = 0,
+};
+
+static struct platform_device herring_i2c4_device = {
+ .name = "i2c-gpio",
+ .id = 4,
+ .dev.platform_data = &herring_i2c4_platdata,
+};
+
+static struct i2c_gpio_platform_data herring_i2c5_platdata = {
+ .sda_pin = GPIO_AP_SDA_28V,
+ .scl_pin = GPIO_AP_SCL_28V,
+ .udelay = 2, /* 250KHz */
+ .sda_is_open_drain = 0,
+ .scl_is_open_drain = 0,
+ .scl_is_output_only = 0,
+};
+
+static struct platform_device herring_i2c5_device = {
+ .name = "i2c-gpio",
+ .id = 5,
+ .dev.platform_data = &herring_i2c5_platdata,
+};
+
+static struct i2c_gpio_platform_data herring_i2c6_platdata = {
+ .sda_pin = GPIO_AP_PMIC_SDA,
+ .scl_pin = GPIO_AP_PMIC_SCL,
+ .udelay = 2, /* 250KHz */
+ .sda_is_open_drain = 0,
+ .scl_is_open_drain = 0,
+ .scl_is_output_only = 0,
+};
+
+static struct platform_device herring_i2c6_device = {
+ .name = "i2c-gpio",
+ .id = 6,
+ .dev.platform_data = &herring_i2c6_platdata,
+};
+
+static struct i2c_gpio_platform_data herring_i2c7_platdata = {
+ .sda_pin = GPIO_USB_SDA_28V,
+ .scl_pin = GPIO_USB_SCL_28V,
+ .udelay = 2, /* 250KHz */
+ .sda_is_open_drain = 0,
+ .scl_is_open_drain = 0,
+ .scl_is_output_only = 0,
+};
+
+static struct platform_device herring_i2c7_device = {
+ .name = "i2c-gpio",
+ .id = 7,
+ .dev.platform_data = &herring_i2c7_platdata,
+};
+
+static struct i2c_gpio_platform_data herring_i2c8_platdata = {
+ .sda_pin = GYRO_SDA_28V,
+ .scl_pin = GYRO_SCL_28V,
+ .udelay = 2, /* 250KHz */
+ .sda_is_open_drain = 0,
+ .scl_is_open_drain = 0,
+ .scl_is_output_only = 0,
+};
+
+static struct platform_device herring_i2c8_device = {
+ .name = "i2c-gpio",
+ .id = 8,
+ .dev.platform_data = &herring_i2c8_platdata,
+};
+
+static struct i2c_gpio_platform_data herring_i2c9_platdata = {
+ .sda_pin = FUEL_SDA_18V,
+ .scl_pin = FUEL_SCL_18V,
+ .udelay = 2, /* 250KHz */
+ .sda_is_open_drain = 0,
+ .scl_is_open_drain = 0,
+ .scl_is_output_only = 0,
+};
+
+static struct platform_device herring_i2c9_device = {
+ .name = "i2c-gpio",
+ .id = 9,
+ .dev.platform_data = &herring_i2c9_platdata,
+};
+
+static struct i2c_gpio_platform_data herring_i2c10_platdata = {
+ .sda_pin = _3_TOUCH_SDA_28V,
+ .scl_pin = _3_TOUCH_SCL_28V,
+ .udelay = 0, /* 250KHz */
+ .sda_is_open_drain = 0,
+ .scl_is_open_drain = 0,
+ .scl_is_output_only = 0,
+};
+
+static struct platform_device herring_i2c10_device = {
+ .name = "i2c-gpio",
+ .id = 10,
+ .dev.platform_data = &herring_i2c10_platdata,
+};
+
+static struct i2c_gpio_platform_data herring_i2c11_platdata = {
+ .sda_pin = GPIO_ALS_SDA_28V,
+ .scl_pin = GPIO_ALS_SCL_28V,
+ .udelay = 2, /* 250KHz */
+ .sda_is_open_drain = 0,
+ .scl_is_open_drain = 0,
+ .scl_is_output_only = 0,
+};
+
+static struct platform_device herring_i2c11_device = {
+ .name = "i2c-gpio",
+ .id = 11,
+ .dev.platform_data = &herring_i2c11_platdata,
+};
+
+static struct i2c_gpio_platform_data herring_i2c12_platdata = {
+ .sda_pin = GPIO_MSENSE_SDA_28V,
+ .scl_pin = GPIO_MSENSE_SCL_28V,
+ .udelay = 0, /* 250KHz */
+ .sda_is_open_drain = 0,
+ .scl_is_open_drain = 0,
+ .scl_is_output_only = 0,
+};
+
+static struct platform_device herring_i2c12_device = {
+ .name = "i2c-gpio",
+ .id = 12,
+ .dev.platform_data = &herring_i2c12_platdata,
+};
+
+static struct i2c_gpio_platform_data herring_i2c14_platdata = {
+ .sda_pin = NFC_SDA_18V,
+ .scl_pin = NFC_SCL_18V,
+ .udelay = 2,
+ .sda_is_open_drain = 0,
+ .scl_is_open_drain = 0,
+ .scl_is_output_only = 0,
+};
+
+static struct platform_device herring_i2c14_device = {
+ .name = "i2c-gpio",
+ .id = 14,
+ .dev.platform_data = &herring_i2c14_platdata,
+};
+
+/* max8893 wimax PMIC */
+static struct i2c_gpio_platform_data herring_i2c15_platdata = {
+ .sda_pin = GPIO_WIMAX_PM_SDA,
+ .scl_pin = GPIO_WIMAX_PM_SCL,
+};
+
+static struct platform_device herring_i2c15_device = {
+ .name = "i2c-gpio",
+ .id = 15,
+ .dev.platform_data = &herring_i2c15_platdata,
+};
+
+static struct regulator_init_data herring_max8893_buck_data = {
+ .constraints = {
+ .name = "max8893_buck",
+ .min_uV = 1200000,
+ .max_uV = 1200000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ },
+};
+
+static struct regulator_init_data herring_max8893_ldo1_data = {
+ .constraints = {
+ .name = "max8893_ldo1",
+ .min_uV = 2800000,
+ .max_uV = 2800000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ },
+};
+
+static struct regulator_init_data herring_max8893_ldo2_data = {
+ .constraints = {
+ .name = "max8893_ldo2",
+ .min_uV = 2800000,
+ .max_uV = 2800000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ },
+};
+
+static struct regulator_init_data herring_max8893_ldo3_data = {
+ .constraints = {
+ .name = "max8893_ldo3",
+ .min_uV = 3300000,
+ .max_uV = 3300000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ },
+};
+
+static struct regulator_init_data herring_max8893_ldo4_data = {
+ .constraints = {
+ .name = "max8893_ldo4",
+ .min_uV = 2900000,
+ .max_uV = 2900000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ },
+};
+
+static struct regulator_init_data herring_max8893_ldo5_data = {
+ .constraints = {
+ .name = "max8893_ldo5",
+ .min_uV = 2800000,
+ .max_uV = 2800000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ },
+};
+
+static struct max8893_subdev_data herring_max8893_subdev_data[] = {
+ {
+ .id = MAX8893_BUCK,
+ .initdata = &herring_max8893_buck_data,
+ },
+ {
+ .id = MAX8893_LDO1,
+ .initdata = &herring_max8893_ldo1_data,
+ },
+ {
+ .id = MAX8893_LDO2,
+ .initdata = &herring_max8893_ldo2_data,
+ },
+ {
+ .id = MAX8893_LDO3,
+ .initdata = &herring_max8893_ldo3_data,
+ },
+ {
+ .id = MAX8893_LDO4,
+ .initdata = &herring_max8893_ldo4_data,
+ },
+ {
+ .id = MAX8893_LDO5,
+ .initdata = &herring_max8893_ldo5_data,
+ },
+};
+
+static struct max8893_platform_data herring_max8893_pdata = {
+ .num_subdevs = ARRAY_SIZE(herring_max8893_subdev_data),
+ .subdevs = herring_max8893_subdev_data,
+};
+
+static struct i2c_board_info i2c_devs15[] __initdata = {
+ {
+ I2C_BOARD_INFO("max8893", 0x3E),
+ .platform_data = &herring_max8893_pdata,
+ },
+};
+
+static struct wimax_cfg wimax_config;
+
+static unsigned int wimax_sdio_on_table[][4] = {
+ {GPIO_WIMAX_SDIO_CLK, 2, GPIO_LEVEL_NONE, S3C_GPIO_PULL_UP},
+ {GPIO_WIMAX_SDIO_CMD, 2, GPIO_LEVEL_NONE, S3C_GPIO_PULL_UP},
+ {GPIO_WIMAX_SDIO_D0, 2, GPIO_LEVEL_NONE, S3C_GPIO_PULL_UP},
+ {GPIO_WIMAX_SDIO_D1, 2, GPIO_LEVEL_NONE, S3C_GPIO_PULL_UP},
+ {GPIO_WIMAX_SDIO_D2, 2, GPIO_LEVEL_NONE, S3C_GPIO_PULL_UP},
+ {GPIO_WIMAX_SDIO_D3, 2, GPIO_LEVEL_NONE, S3C_GPIO_PULL_UP},
+};
+
+static unsigned int wimax_sdio_off_table[][4] = {
+ {GPIO_WIMAX_SDIO_CLK, 0, GPIO_LEVEL_NONE, S3C_GPIO_PULL_NONE},
+ {GPIO_WIMAX_SDIO_CMD, 0, GPIO_LEVEL_NONE, S3C_GPIO_PULL_NONE},
+ {GPIO_WIMAX_SDIO_D0, 0, GPIO_LEVEL_NONE, S3C_GPIO_PULL_NONE},
+ {GPIO_WIMAX_SDIO_D1, 0, GPIO_LEVEL_NONE, S3C_GPIO_PULL_NONE},
+ {GPIO_WIMAX_SDIO_D2, 0, GPIO_LEVEL_NONE, S3C_GPIO_PULL_NONE},
+ {GPIO_WIMAX_SDIO_D3, 0, GPIO_LEVEL_NONE, S3C_GPIO_PULL_NONE},
+};
+
+static int wimax_sdio_en(int onoff)
+{
+ u32 i;
+ u32 sdio;
+ unsigned int (*wimax_gpio_table)[4];
+
+ wimax_gpio_table = onoff ? wimax_sdio_on_table : wimax_sdio_off_table;
+
+ for (i = 0; i < ARRAY_SIZE(wimax_sdio_on_table); i++) {
+ sdio = wimax_gpio_table[i][0];
+ s3c_gpio_cfgpin(sdio,
+ S3C_GPIO_SFN(wimax_gpio_table[i][1]));
+ s3c_gpio_setpull(sdio, wimax_gpio_table[i][3]);
+ s3c_gpio_set_drvstrength(sdio, S3C_GPIO_DRVSTR_2X);
+
+ if (wimax_gpio_table[i][2] != GPIO_LEVEL_NONE)
+ gpio_set_value(sdio, wimax_gpio_table[i][2]);
+ }
+ return 0;
+}
+
+static void wimax_deinit_gpios(void);
+/* signal wimax modem to wakeup if asleep */
+static void wimax_wakeup_assert(int enable)
+{
+ if (herring_is_cdma_wimax_rev(0) || herring_is_cdma_wimax_rev(1))
+ gpio_set_value(GPIO_WIMAX_WAKEUP, !enable);
+ else
+ gpio_set_value(GPIO_USB_SEL, !enable);
+}
+
+static int get_wimax_sleep_mode(void)
+{
+ return gpio_get_value(GPIO_WIMAX_IF_MODE1);
+}
+
+static int is_wimax_active(void)
+{
+ return gpio_get_value(GPIO_WIMAX_CON0);
+}
+
+/* signal AP is active*/
+static void signal_ap_active(int enable)
+{
+ gpio_set_value(GPIO_WIMAX_CON1, enable);
+}
+
+/* switch USB path to AP */
+void switch_usb_ap(void)
+{
+ gpio_set_value(GPIO_USB_HS_SEL, 1);
+ msleep(10);
+}
+
+/* switch USB path to WiMAX */
+void switch_usb_wimax(void)
+{
+ gpio_set_value(GPIO_USB_HS_SEL, 0);
+ msleep(10);
+}
+
+void wimax_init_gpios(void)
+{
+ s3c_gpio_cfgpin(GPIO_WIMAX_RESET_N, S3C_GPIO_OUTPUT);
+ gpio_set_value(GPIO_WIMAX_RESET_N, 0);
+
+ s3c_gpio_cfgpin(GPIO_WIMAX_DBGEN_28V, S3C_GPIO_OUTPUT);
+ gpio_set_value(GPIO_WIMAX_DBGEN_28V, 0);
+
+ s3c_gpio_cfgpin(GPIO_WIMAX_I2C_CON, S3C_GPIO_OUTPUT);
+ gpio_set_value(GPIO_WIMAX_I2C_CON, 1);
+ msleep(10);
+
+ if (herring_is_cdma_wimax_rev(0) || herring_is_cdma_wimax_rev(1)) {
+ s3c_gpio_setpull(GPIO_USB_SEL, S3C_GPIO_PULL_UP);
+ s3c_gpio_cfgpin(GPIO_WIMAX_WAKEUP, S3C_GPIO_OUTPUT);
+ } else {
+ /* g_pdata->wimax_int set Input and Pull up */
+ s3c_gpio_setpull(GPIO_WIMAX_WAKEUP, S3C_GPIO_PULL_UP);
+ s3c_gpio_cfgpin(GPIO_USB_SEL, S3C_GPIO_OUTPUT);
+ }
+ wimax_wakeup_assert(0);
+
+ /*
+ * IDLE, VI setting pin: high for suspend idle,
+ * low for suspend vi
+ */
+ s3c_gpio_cfgpin(GPIO_WIMAX_IF_MODE1, S3C_GPIO_OUTPUT);
+ gpio_set_value(GPIO_WIMAX_IF_MODE1, 1);
+
+ s3c_gpio_cfgpin(GPIO_WIMAX_IF_MODE0, S3C_GPIO_OUTPUT);
+
+ /* IDLE, VI interrupt for WiMAX */
+ s3c_gpio_cfgpin(GPIO_WIMAX_CON2, S3C_GPIO_OUTPUT);
+ gpio_set_value(GPIO_WIMAX_CON2, 1);/* active low interrupt */
+
+ /* PDA Active */
+ s3c_gpio_cfgpin(GPIO_WIMAX_CON1, S3C_GPIO_OUTPUT);
+ s3c_gpio_set_drvstrength(GPIO_WIMAX_CON1, S3C_GPIO_DRVSTR_2X);
+ signal_ap_active(1);
+
+}
+
+static void hw_set_wimax_mode(void)
+{
+ bool legacy_rev;
+
+ legacy_rev = herring_is_cdma_wimax_rev(0) ||
+ herring_is_cdma_wimax_rev(1);
+
+ switch (wimax_config.wimax_mode) {
+ case SDIO_MODE:
+ pr_debug("SDIO MODE");
+ if (legacy_rev)
+ gpio_set_value(GPIO_WIMAX_WAKEUP, 1);
+ else
+ gpio_set_value(GPIO_USB_SEL, 1);
+ gpio_set_value(GPIO_WIMAX_IF_MODE0, 1);
+ break;
+ case WTM_MODE:
+ case AUTH_MODE:
+ if (legacy_rev)
+ gpio_set_value(GPIO_WIMAX_WAKEUP, 0);
+ else
+ gpio_set_value(GPIO_USB_SEL, 0);
+ gpio_set_value(GPIO_WIMAX_IF_MODE0, 0);
+ break;
+ case DM_MODE:
+ pr_debug("DM MODE");
+ if (legacy_rev)
+ gpio_set_value(GPIO_WIMAX_WAKEUP, 1);
+ else
+ gpio_set_value(GPIO_USB_SEL, 1);
+ gpio_set_value(GPIO_WIMAX_IF_MODE0, 0);
+ break;
+ case USB_MODE:
+ case USIM_RELAY_MODE:
+ pr_debug("USB MODE");
+ if (legacy_rev)
+ gpio_set_value(GPIO_WIMAX_WAKEUP, 0);
+ else
+ gpio_set_value(GPIO_USB_SEL, 0);
+ gpio_set_value(GPIO_WIMAX_IF_MODE0, 1);
+ break;
+ }
+}
+
+void wimax_hsmmc_presence_check(void)
+{
+ sdhci_s3c_force_presence_change(&s3c_device_hsmmc2);
+}
+
+int gpio_wimax_power(int enable)
+{
+ if (!enable)
+ goto wimax_power_off;
+
+ if (gpio_get_value(GPIO_WIMAX_EN)) {
+ pr_debug("Already Wimax powered ON");
+ return WIMAX_ALREADY_POWER_ON;
+ }
+ /* wait for sdio remove complete*/
+ while (!wimax_config.card_removed)
+ msleep(100);
+
+ pr_debug("Wimax power ON");
+
+ wimax_sdio_en(1);
+ wimax_init_gpios();
+
+ if (wimax_config.wimax_mode != SDIO_MODE)
+ switch_usb_wimax();
+
+ gpio_set_value(GPIO_WIMAX_I2C_CON, 1);
+ msleep(10);
+
+ gpio_set_value(GPIO_WIMAX_EN, 1);
+
+ msleep(10);
+ pr_debug("RESET");
+
+ gpio_set_value(GPIO_WIMAX_RESET_N, 1);
+
+ /* Delay important for bootloader initialization */
+ msleep(1800);
+
+ /*Dont force detect if the card is already detected*/
+ if (wimax_config.card_removed)
+ wimax_hsmmc_presence_check();
+
+ return WIMAX_POWER_SUCCESS;
+
+wimax_power_off:
+ /*Wait for modem to flush EEPROM data*/
+ msleep(500);
+ wimax_deinit_gpios();
+
+ pr_debug("Wimax power OFF");
+
+ /*Dont force detect if the card is already detected as removed*/
+ if (!wimax_config.card_removed)
+ wimax_hsmmc_presence_check();
+
+ /*Not critial, just some safty margin*/
+ msleep(300);
+ wimax_sdio_en(0);
+
+ return WIMAX_POWER_SUCCESS;
+}
+
+static struct wimax732_platform_data wimax732_pdata = {
+ .power = gpio_wimax_power,
+ .set_mode = hw_set_wimax_mode,
+ .signal_ap_active = signal_ap_active,
+ .get_sleep_mode = get_wimax_sleep_mode,
+ .is_modem_awake = is_wimax_active,
+ .wakeup_assert = wimax_wakeup_assert,
+ .g_cfg = &wimax_config,
+ .wimax_int = GPIO_USB_SEL, /* GPIO_USB_SEL,*/
+};
+
+static struct platform_device s3c_device_cmc732 = {
+ .name = "wimax732_driver",
+ .id = 1,
+ .dev.platform_data = &wimax732_pdata,
+};
+
+void wimax_deinit_gpios(void)
+{
+ /* Disable WiMAX JTAG for freerun */
+ s3c_gpio_cfgpin(GPIO_WIMAX_DBGEN_28V, S3C_GPIO_INPUT);
+ s3c_gpio_setpull(GPIO_WIMAX_DBGEN_28V, S3C_GPIO_PULL_NONE);
+
+ /* g_pdata->wimax_int set Output low */
+ s3c_gpio_cfgpin(GPIO_USB_SEL, S3C_GPIO_INPUT);
+ s3c_gpio_setpull(GPIO_USB_SEL, S3C_GPIO_PULL_NONE);
+
+ /* MODE pin */
+ s3c_gpio_cfgpin(GPIO_WIMAX_WAKEUP, S3C_GPIO_INPUT);
+ s3c_gpio_setpull(GPIO_WIMAX_WAKEUP, S3C_GPIO_PULL_NONE);
+
+ s3c_gpio_cfgpin(GPIO_WIMAX_IF_MODE0, S3C_GPIO_INPUT);
+ s3c_gpio_setpull(GPIO_WIMAX_IF_MODE0, S3C_GPIO_PULL_NONE);
+
+ /* WiMAX active */
+ s3c_gpio_cfgpin(GPIO_WIMAX_CON0, S3C_GPIO_INPUT);
+ s3c_gpio_setpull(GPIO_WIMAX_CON0, S3C_GPIO_PULL_NONE);
+
+ /* IDLE, VI setting pin: high for suspend idle,
+ low for suspend vi */
+ s3c_gpio_cfgpin(GPIO_WIMAX_IF_MODE1, S3C_GPIO_INPUT);
+ s3c_gpio_setpull(GPIO_WIMAX_IF_MODE1, S3C_GPIO_PULL_NONE);
+
+ /* IDLE, VI interrupt for WiMAX */
+ s3c_gpio_cfgpin(GPIO_WIMAX_CON2, S3C_GPIO_INPUT);
+ s3c_gpio_setpull(GPIO_WIMAX_CON2, S3C_GPIO_PULL_NONE);
+
+ /* PDA Active */
+ s3c_gpio_cfgpin(GPIO_WIMAX_CON1, S3C_GPIO_INPUT);
+ s3c_gpio_setpull(GPIO_WIMAX_CON1, S3C_GPIO_PULL_NONE);
+
+ /* power related */
+ s3c_gpio_cfgpin(GPIO_WIMAX_RESET_N, S3C_GPIO_INPUT);
+ s3c_gpio_setpull(GPIO_WIMAX_RESET_N, S3C_GPIO_PULL_NONE);
+
+ s3c_gpio_cfgpin(GPIO_WIMAX_EN, S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(GPIO_WIMAX_EN, S3C_GPIO_PULL_NONE);
+
+ /* EEPROM switch to WiMAX */
+ s3c_gpio_cfgpin(GPIO_WIMAX_I2C_CON, S3C_GPIO_INPUT);
+ s3c_gpio_setpull(GPIO_WIMAX_I2C_CON, S3C_GPIO_PULL_NONE);
+
+ gpio_set_value(GPIO_WIMAX_EN, 0);
+ s3c_gpio_cfgpin(GPIO_WIMAX_I2C_CON, S3C_GPIO_INPUT);
+
+ s3c_gpio_cfgpin(GPIO_UART_SEL, S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(GPIO_UART_SEL, S3C_GPIO_PULL_NONE);
+
+ s3c_gpio_cfgpin(GPIO_UART_SEL1, S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(GPIO_UART_SEL1, S3C_GPIO_PULL_NONE);
+
+ s3c_gpio_cfgpin(GPIO_USB_HS_SEL, S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(GPIO_USB_HS_SEL, S3C_GPIO_PULL_NONE);
+ switch_usb_ap();
+
+ if (herring_is_cdma_wimax_rev(0) || herring_is_cdma_wimax_rev(1))
+ wimax732_pdata.wimax_int = GPIO_USB_SEL;
+ else
+ wimax732_pdata.wimax_int = GPIO_WIMAX_WAKEUP;
+}
+
+static void touch_keypad_gpio_init(void)
+{
+ int ret = 0;
+
+ ret = gpio_request(_3_GPIO_TOUCH_EN, "TOUCH_EN");
+ if (ret)
+ printk(KERN_ERR "Failed to request gpio touch_en.\n");
+}
+
+static void touch_keypad_onoff(int onoff)
+{
+ gpio_direction_output(_3_GPIO_TOUCH_EN, onoff);
+
+ if (onoff == TOUCHKEY_OFF)
+ msleep(30);
+ else
+ msleep(50);
+}
+
+static void touch_keypad_gpio_sleep(int onoff)
+{
+ if (onoff == TOUCHKEY_ON) {
+ /*
+ * reconfigure gpio to activate touchkey controller vdd in sleep mode
+ */
+ s3c_gpio_slp_cfgpin(_3_GPIO_TOUCH_EN, S3C_GPIO_SLP_OUT1);
+ //s3c_gpio_slp_setpull_updown(_3_GPIO_TOUCH_EN, S3C_GPIO_PULL_NONE);
+ } else {
+ /*
+ * reconfigure gpio to deactivate touchkey vdd in sleep mode,
+ * this is the default
+ */
+ s3c_gpio_slp_cfgpin(_3_GPIO_TOUCH_EN, S3C_GPIO_SLP_OUT0);
+ //s3c_gpio_slp_setpull_updown(_3_GPIO_TOUCH_EN, S3C_GPIO_PULL_NONE);
+ }
+
+}
+
+static const int touch_keypad_code[] = {
+ KEY_MENU,
+ KEY_HOME,
+ KEY_BACK,
+ KEY_SEARCH
+};
+
+static struct touchkey_platform_data touchkey_data = {
+ .keycode_cnt = ARRAY_SIZE(touch_keypad_code),
+ .keycode = touch_keypad_code,
+ .touchkey_onoff = touch_keypad_onoff,
+ .touchkey_sleep_onoff = touch_keypad_gpio_sleep,
+ .fw_name = "cypress-touchkey.bin",
+ .scl_pin = _3_TOUCH_SCL_28V,
+ .sda_pin = _3_TOUCH_SDA_28V,
+ .en_pin = _3_GPIO_TOUCH_EN,
+};
+
+static struct gpio_event_direct_entry herring_keypad_key_map[] = {
+ {
+ .gpio = S5PV210_GPH2(6),
+ .code = KEY_POWER,
+ },
+ {
+ .gpio = S5PV210_GPH3(1),
+ .code = KEY_VOLUMEDOWN,
+ },
+ {
+ .gpio = S5PV210_GPH3(2),
+ .code = KEY_VOLUMEUP,
+ }
+};
+
+static struct gpio_event_input_info herring_keypad_key_info = {
+ .info.func = gpio_event_input_func,
+ .info.no_suspend = true,
+ .debounce_time.tv64 = 5 * NSEC_PER_MSEC,
+ .type = EV_KEY,
+ .keymap = herring_keypad_key_map,
+ .keymap_size = ARRAY_SIZE(herring_keypad_key_map)
+};
+
+static struct gpio_event_info *herring_input_info[] = {
+ &herring_keypad_key_info.info,
+};
+
+
+static struct gpio_event_platform_data herring_input_data = {
+ .names = {
+ "herring-keypad",
+ NULL,
+ },
+ .info = herring_input_info,
+ .info_count = ARRAY_SIZE(herring_input_info),
+};
+
+static struct platform_device herring_input_device = {
+ .name = GPIO_EVENT_DEV_NAME,
+ .id = 0,
+ .dev = {
+ .platform_data = &herring_input_data,
+ },
+};
+
+#ifdef CONFIG_S5P_ADC
+static struct s3c_adc_mach_info s3c_adc_platform __initdata = {
+ /* s5pc110 support 12-bit resolution */
+ .delay = 10000,
+ .presc = 65,
+ .resolution = 12,
+};
+#endif
+
+/* in revisions before 0.9, there is a common mic bias gpio */
+
+static DEFINE_SPINLOCK(mic_bias_lock);
+static bool wm8994_mic_bias;
+static bool jack_mic_bias;
+static void set_shared_mic_bias(void)
+{
+ gpio_set_value(GPIO_MICBIAS_EN, wm8994_mic_bias || jack_mic_bias);
+}
+
+static void wm8994_set_mic_bias(bool on)
+{
+ if (system_rev < 0x09) {
+ unsigned long flags;
+ spin_lock_irqsave(&mic_bias_lock, flags);
+ wm8994_mic_bias = on;
+ set_shared_mic_bias();
+ spin_unlock_irqrestore(&mic_bias_lock, flags);
+ } else
+ gpio_set_value(GPIO_MICBIAS_EN, on);
+}
+
+static void sec_jack_set_micbias_state(bool on)
+{
+ if (system_rev < 0x09) {
+ unsigned long flags;
+ spin_lock_irqsave(&mic_bias_lock, flags);
+ jack_mic_bias = on;
+ set_shared_mic_bias();
+ spin_unlock_irqrestore(&mic_bias_lock, flags);
+ } else
+ gpio_set_value(GPIO_EAR_MICBIAS_EN, on);
+}
+
+static struct wm8994_platform_data wm8994_pdata = {
+ .ldo = GPIO_CODEC_LDO_EN,
+ .ear_sel = GPIO_EAR_SEL,
+ .set_mic_bias = wm8994_set_mic_bias,
+};
+
+/*
+ * Guide for Camera Configuration for Crespo board
+ * ITU CAM CH A: LSI s5k4ecgx
+ */
+static DEFINE_MUTEX(s5k4ecgx_lock);
+static struct regulator *cam_isp_core_regulator;
+static struct regulator *cam_isp_host_regulator;
+static struct regulator *cam_af_regulator;
+static bool s5k4ecgx_powered_on;
+static int s5k4ecgx_regulator_init(void)
+{
+ if (IS_ERR_OR_NULL(cam_isp_core_regulator)) {
+ cam_isp_core_regulator = regulator_get(NULL, "cam_isp_core");
+ if (IS_ERR_OR_NULL(cam_isp_core_regulator)) {
+ pr_err("failed to get cam_isp_core regulator");
+ return -EINVAL;
+ }
+ }
+ if (IS_ERR_OR_NULL(cam_isp_host_regulator)) {
+ cam_isp_host_regulator = regulator_get(NULL, "cam_isp_host");
+ if (IS_ERR_OR_NULL(cam_isp_host_regulator)) {
+ pr_err("failed to get cam_isp_host regulator");
+ return -EINVAL;
+ }
+ }
+ if (IS_ERR_OR_NULL(cam_af_regulator)) {
+ cam_af_regulator = regulator_get(NULL, "cam_af");
+ if (IS_ERR_OR_NULL(cam_af_regulator)) {
+ pr_err("failed to get cam_af regulator");
+ return -EINVAL;
+ }
+ }
+ pr_debug("cam_isp_core_regulator = %p\n", cam_isp_core_regulator);
+ pr_debug("cam_isp_host_regulator = %p\n", cam_isp_host_regulator);
+ pr_debug("cam_af_regulator = %p\n", cam_af_regulator);
+ return 0;
+}
+
+static void s5k4ecgx_init(void)
+{
+ /* CAM_IO_EN - GPB(7) */
+ if (gpio_request(GPIO_GPB7, "GPB7") < 0)
+ pr_err("failed gpio_request(GPB7) for camera control\n");
+ /* CAM_MEGA_nRST - GPJ1(5) */
+ if (gpio_request(GPIO_CAM_MEGA_nRST, "GPJ1") < 0)
+ pr_err("failed gpio_request(GPJ1) for camera control\n");
+ /* CAM_MEGA_EN - GPJ0(6) */
+ if (gpio_request(GPIO_CAM_MEGA_EN, "GPJ0") < 0)
+ pr_err("failed gpio_request(GPJ0) for camera control\n");
+ /* FLASH_EN - GPJ1(2) */
+ if (gpio_request(GPIO_FLASH_EN, "GPIO_FLASH_EN") < 0)
+ pr_err("failed gpio_request(GPIO_FLASH_EN)\n");
+ /* FLASH_EN_SET - GPJ1(0) */
+ if (gpio_request(GPIO_CAM_FLASH_EN_SET, "GPIO_CAM_FLASH_EN_SET") < 0)
+ pr_err("failed gpio_request(GPIO_CAM_FLASH_EN_SET)\n");
+}
+
+static int s5k4ecgx_ldo_en(bool en)
+{
+ int err = 0;
+ int result;
+
+ if (IS_ERR_OR_NULL(cam_isp_core_regulator) ||
+ IS_ERR_OR_NULL(cam_isp_host_regulator) ||
+ IS_ERR_OR_NULL(cam_af_regulator)) {
+ pr_err("Camera regulators not initialized\n");
+ return -EINVAL;
+ }
+
+ if (!en)
+ goto off;
+
+ /* Turn CAM_ISP_CORE_1.2V(VDD_REG) on */
+ err = regulator_enable(cam_isp_core_regulator);
+ if (err) {
+ pr_err("Failed to enable regulator cam_isp_core\n");
+ goto off;
+ }
+ mdelay(1);
+
+ /* Turn CAM_SENSOR_A_2.8V(VDDA) on */
+ gpio_set_value(GPIO_GPB7, 1);
+ mdelay(1);
+
+ /* Turn CAM_ISP_HOST_2.8V(VDDIO) on */
+ err = regulator_enable(cam_isp_host_regulator);
+ if (err) {
+ pr_err("Failed to enable regulator cam_isp_core\n");
+ goto off;
+ }
+ udelay(50);
+
+ /* Turn CAM_AF_2.8V or 3.0V on */
+ err = regulator_enable(cam_af_regulator);
+ if (err) {
+ pr_err("Failed to enable regulator cam_isp_core\n");
+ goto off;
+ }
+ udelay(50);
+ return 0;
+
+off:
+ result = err;
+ err = regulator_disable(cam_af_regulator);
+ if (err) {
+ pr_err("Failed to disable regulator cam_isp_core\n");
+ result = err;
+ }
+ err = regulator_disable(cam_isp_host_regulator);
+ if (err) {
+ pr_err("Failed to disable regulator cam_isp_core\n");
+ result = err;
+ }
+ gpio_set_value(GPIO_GPB7, 0);
+ err = regulator_disable(cam_isp_core_regulator);
+ if (err) {
+ pr_err("Failed to disable regulator cam_isp_core\n");
+ result = err;
+ }
+ return result;
+}
+
+static int s5k4ecgx_power_on(void)
+{
+ /* LDO on */
+ int err;
+
+ /* can't do this earlier because regulators aren't available in
+ * early boot
+ */
+ if (s5k4ecgx_regulator_init()) {
+ pr_err("Failed to initialize camera regulators\n");
+ return -EINVAL;
+ }
+
+ err = s5k4ecgx_ldo_en(true);
+ if (err)
+ return err;
+ mdelay(66);
+
+ /* MCLK on - default is input, to save power when camera not on */
+ s3c_gpio_cfgpin(GPIO_CAM_MCLK, S3C_GPIO_SFN(GPIO_CAM_MCLK_AF));
+ mdelay(1);
+
+ /* CAM_MEGA_EN - GPJ1(2) LOW */
+ gpio_set_value(GPIO_CAM_MEGA_EN, 1);
+ mdelay(1);
+
+ /* CAM_MEGA_nRST - GPJ1(5) LOW */
+ gpio_set_value(GPIO_CAM_MEGA_nRST, 1);
+ mdelay(1);
+
+ return 0;
+}
+
+static int s5k4ecgx_power_off(void)
+{
+ /* CAM_MEGA_nRST - GPJ1(5) LOW */
+ gpio_set_value(GPIO_CAM_MEGA_nRST, 0);
+ udelay(60);
+
+ /* Mclk disable - set to input function to save power */
+ s3c_gpio_cfgpin(GPIO_CAM_MCLK, 0);
+ udelay(10);
+
+ /* CAM_MEGA_EN - GPJ1(2) LOW */
+ gpio_set_value(GPIO_CAM_MEGA_EN, 0);
+ udelay(10);
+
+ s5k4ecgx_ldo_en(false);
+ mdelay(1);
+
+ return 0;
+}
+
+static int s5k4ecgx_power_en(int onoff)
+{
+ int err = 0;
+ mutex_lock(&s5k4ecgx_lock);
+ /* we can be asked to turn off even if we never were turned
+ * on if something odd happens and we are closed
+ * by camera framework before we even completely opened.
+ */
+ if (onoff != s5k4ecgx_powered_on) {
+ if (onoff)
+ err = s5k4ecgx_power_on();
+ else
+ err = s5k4ecgx_power_off();
+ if (!err)
+ s5k4ecgx_powered_on = onoff;
+ }
+ mutex_unlock(&s5k4ecgx_lock);
+ return err;
+}
+
+#define FLASH_MOVIE_MODE_CURRENT_50_PERCENT 7
+
+#define FLASH_TIME_LATCH_US 500
+#define FLASH_TIME_EN_SET_US 1
+
+/* The AAT1274 uses a single wire interface to write data to its
+ * control registers. An incoming value is written by sending a number
+ * of rising edges to EN_SET. Data is 4 bits, or 1-16 pulses, and
+ * addresses are 17 pulses or more. Data written without an address
+ * controls the current to the LED via the default address 17. */
+static void aat1274_write(int value)
+{
+ while (value--) {
+ gpio_set_value(GPIO_CAM_FLASH_EN_SET, 0);
+ udelay(FLASH_TIME_EN_SET_US);
+ gpio_set_value(GPIO_CAM_FLASH_EN_SET, 1);
+ udelay(FLASH_TIME_EN_SET_US);
+ }
+ udelay(FLASH_TIME_LATCH_US);
+ /* At this point, the LED will be on */
+}
+
+static int aat1274_flash(int enable)
+{
+ /* Turn main flash on or off by asserting a value on the EN line. */
+ gpio_set_value(GPIO_FLASH_EN, !!enable);
+
+ return 0;
+}
+
+static int aat1274_af_assist(int enable)
+{
+ /* Turn assist light on or off by asserting a value on the EN_SET
+ * line. The default illumination level of 1/7.3 at 100% is used */
+ gpio_set_value(GPIO_CAM_FLASH_EN_SET, !!enable);
+ if (!enable)
+ gpio_set_value(GPIO_FLASH_EN, 0);
+
+ return 0;
+}
+
+static int aat1274_torch(int enable)
+{
+ /* Turn torch mode on or off by writing to the EN_SET line. A level
+ * of 1/7.3 and 50% is used (half AF assist brightness). */
+ if (enable) {
+ aat1274_write(FLASH_MOVIE_MODE_CURRENT_50_PERCENT);
+ } else {
+ gpio_set_value(GPIO_CAM_FLASH_EN_SET, 0);
+ gpio_set_value(GPIO_FLASH_EN, 0);
+ }
+
+ return 0;
+}
+
+static struct s5k4ecgx_platform_data s5k4ecgx_plat = {
+ .default_width = 640,
+ .default_height = 480,
+ .pixelformat = V4L2_PIX_FMT_UYVY,
+ .freq = 24000000,
+ .flash_onoff = &aat1274_flash,
+ .af_assist_onoff = &aat1274_af_assist,
+ .torch_onoff = &aat1274_torch,
+};
+
+static struct i2c_board_info s5k4ecgx_i2c_info = {
+ I2C_BOARD_INFO("S5K4ECGX", 0x5A>>1),
+ .platform_data = &s5k4ecgx_plat,
+};
+
+static struct s3c_platform_camera s5k4ecgx = {
+ .id = CAMERA_PAR_A,
+ .type = CAM_TYPE_ITU,
+ .fmt = ITU_601_YCBCR422_8BIT,
+ .order422 = CAM_ORDER422_8BIT_CBYCRY,
+ .i2c_busnum = 0,
+ .info = &s5k4ecgx_i2c_info,
+ .pixelformat = V4L2_PIX_FMT_UYVY,
+ .srclk_name = "xusbxti",
+ .clk_name = "sclk_cam",
+ .clk_rate = 24000000,
+ .line_length = 1920,
+ .width = 640,
+ .height = 480,
+ .window = {
+ .left = 0,
+ .top = 0,
+ .width = 640,
+ .height = 480,
+ },
+
+ /* Polarity */
+ .inv_pclk = 0,
+ .inv_vsync = 1,
+ .inv_href = 0,
+ .inv_hsync = 0,
+
+ .initialized = 0,
+ .cam_power = s5k4ecgx_power_en,
+};
+
+
+/* External camera module setting */
+static DEFINE_MUTEX(s5ka3dfx_lock);
+static struct regulator *s5ka3dfx_vga_avdd;
+static struct regulator *s5ka3dfx_vga_vddio;
+static struct regulator *s5ka3dfx_cam_isp_host;
+static struct regulator *s5ka3dfx_vga_dvdd;
+static bool s5ka3dfx_powered_on;
+
+static int s5ka3dfx_request_gpio(void)
+{
+ int err;
+
+ /* CAM_VGA_nSTBY - GPB(0) */
+ err = gpio_request(GPIO_CAM_VGA_nSTBY, "GPB0");
+ if (err) {
+ pr_err("Failed to request GPB0 for camera control\n");
+ return -EINVAL;
+ }
+
+ /* CAM_VGA_nRST - GPB(2) */
+ err = gpio_request(GPIO_CAM_VGA_nRST, "GPB2");
+ if (err) {
+ pr_err("Failed to request GPB2 for camera control\n");
+ gpio_free(GPIO_CAM_VGA_nSTBY);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int s5ka3dfx_power_init(void)
+{
+ if (IS_ERR_OR_NULL(s5ka3dfx_vga_avdd))
+ s5ka3dfx_vga_avdd = regulator_get(NULL, "vga_avdd");
+
+ if (IS_ERR_OR_NULL(s5ka3dfx_vga_avdd)) {
+ pr_err("Failed to get regulator vga_avdd\n");
+ return -EINVAL;
+ }
+
+ if (IS_ERR_OR_NULL(s5ka3dfx_vga_vddio))
+ s5ka3dfx_vga_vddio = regulator_get(NULL, "vga_vddio");
+
+ if (IS_ERR_OR_NULL(s5ka3dfx_vga_vddio)) {
+ pr_err("Failed to get regulator vga_vddio\n");
+ return -EINVAL;
+ }
+
+ if (IS_ERR_OR_NULL(s5ka3dfx_cam_isp_host))
+ s5ka3dfx_cam_isp_host = regulator_get(NULL, "cam_isp_host");
+
+ if (IS_ERR_OR_NULL(s5ka3dfx_cam_isp_host)) {
+ pr_err("Failed to get regulator cam_isp_host\n");
+ return -EINVAL;
+ }
+
+ if (IS_ERR_OR_NULL(s5ka3dfx_vga_dvdd))
+ s5ka3dfx_vga_dvdd = regulator_get(NULL, "vga_dvdd");
+
+ if (IS_ERR_OR_NULL(s5ka3dfx_vga_dvdd)) {
+ pr_err("Failed to get regulator vga_dvdd\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int s5ka3dfx_power_on(void)
+{
+ int err = 0;
+ int result;
+
+ if (s5ka3dfx_power_init()) {
+ pr_err("Failed to get all regulator\n");
+ return -EINVAL;
+ }
+
+ /* Turn VGA_AVDD_2.8V on */
+ err = regulator_enable(s5ka3dfx_vga_avdd);
+ if (err) {
+ pr_err("Failed to enable regulator vga_avdd\n");
+ return -EINVAL;
+ }
+ msleep(3);
+
+ /* Turn VGA_VDDIO_2.8V on */
+ err = regulator_enable(s5ka3dfx_vga_vddio);
+ if (err) {
+ pr_err("Failed to enable regulator vga_vddio\n");
+ goto off_vga_vddio;
+ }
+ udelay(20);
+
+ /* Turn VGA_DVDD_1.8V on */
+ err = regulator_enable(s5ka3dfx_vga_dvdd);
+ if (err) {
+ pr_err("Failed to enable regulator vga_dvdd\n");
+ goto off_vga_dvdd;
+ }
+ udelay(100);
+
+ /* CAM_VGA_nSTBY HIGH */
+ gpio_direction_output(GPIO_CAM_VGA_nSTBY, 0);
+ gpio_set_value(GPIO_CAM_VGA_nSTBY, 1);
+
+ udelay(10);
+
+ /* Mclk enable */
+ s3c_gpio_cfgpin(GPIO_CAM_MCLK, S3C_GPIO_SFN(0x02));
+ udelay(430);
+
+ /* Turn CAM_ISP_HOST_2.8V on */
+ err = regulator_enable(s5ka3dfx_cam_isp_host);
+ if (err) {
+ pr_err("Failed to enable regulator cam_isp_host\n");
+ goto off_cam_isp_host;
+ }
+ udelay(150);
+
+ /* CAM_VGA_nRST HIGH */
+ gpio_direction_output(GPIO_CAM_VGA_nRST, 0);
+ gpio_set_value(GPIO_CAM_VGA_nRST, 1);
+ mdelay(5);
+
+ return 0;
+off_cam_isp_host:
+ s3c_gpio_cfgpin(GPIO_CAM_MCLK, 0);
+ udelay(1);
+ gpio_direction_output(GPIO_CAM_VGA_nSTBY, 1);
+ gpio_set_value(GPIO_CAM_VGA_nSTBY, 0);
+ udelay(1);
+ err = regulator_disable(s5ka3dfx_vga_dvdd);
+ if (err) {
+ pr_err("Failed to disable regulator vga_dvdd\n");
+ result = err;
+ }
+off_vga_dvdd:
+ err = regulator_disable(s5ka3dfx_vga_vddio);
+ if (err) {
+ pr_err("Failed to disable regulator vga_vddio\n");
+ result = err;
+ }
+off_vga_vddio:
+ err = regulator_disable(s5ka3dfx_vga_avdd);
+ if (err) {
+ pr_err("Failed to disable regulator vga_avdd\n");
+ result = err;
+ }
+
+ return result;
+}
+
+static int s5ka3dfx_power_off(void)
+{
+ int err;
+
+ if (!s5ka3dfx_vga_avdd || !s5ka3dfx_vga_vddio ||
+ !s5ka3dfx_cam_isp_host || !s5ka3dfx_vga_dvdd) {
+ pr_err("Faild to get all regulator\n");
+ return -EINVAL;
+ }
+
+ /* Turn CAM_ISP_HOST_2.8V off */
+ err = regulator_disable(s5ka3dfx_cam_isp_host);
+ if (err) {
+ pr_err("Failed to disable regulator cam_isp_host\n");
+ return -EINVAL;
+ }
+
+ /* CAM_VGA_nRST LOW */
+ gpio_direction_output(GPIO_CAM_VGA_nRST, 1);
+ gpio_set_value(GPIO_CAM_VGA_nRST, 0);
+ udelay(430);
+
+ /* Mclk disable */
+ s3c_gpio_cfgpin(GPIO_CAM_MCLK, 0);
+
+ udelay(1);
+
+ /* Turn VGA_VDDIO_2.8V off */
+ err = regulator_disable(s5ka3dfx_vga_vddio);
+ if (err) {
+ pr_err("Failed to disable regulator vga_vddio\n");
+ return -EINVAL;
+ }
+
+ /* Turn VGA_DVDD_1.8V off */
+ err = regulator_disable(s5ka3dfx_vga_dvdd);
+ if (err) {
+ pr_err("Failed to disable regulator vga_dvdd\n");
+ return -EINVAL;
+ }
+
+ /* CAM_VGA_nSTBY LOW */
+ gpio_direction_output(GPIO_CAM_VGA_nSTBY, 1);
+ gpio_set_value(GPIO_CAM_VGA_nSTBY, 0);
+
+ udelay(1);
+
+ /* Turn VGA_AVDD_2.8V off */
+ err = regulator_disable(s5ka3dfx_vga_avdd);
+ if (err) {
+ pr_err("Failed to disable regulator vga_avdd\n");
+ return -EINVAL;
+ }
+
+ return err;
+}
+
+static int s5ka3dfx_power_en(int onoff)
+{
+ int err = 0;
+ mutex_lock(&s5ka3dfx_lock);
+ /* we can be asked to turn off even if we never were turned
+ * on if something odd happens and we are closed
+ * by camera framework before we even completely opened.
+ */
+ if (onoff != s5ka3dfx_powered_on) {
+ if (onoff)
+ err = s5ka3dfx_power_on();
+ else {
+ err = s5ka3dfx_power_off();
+ s3c_i2c0_force_stop();
+ }
+ if (!err)
+ s5ka3dfx_powered_on = onoff;
+ }
+ mutex_unlock(&s5ka3dfx_lock);
+
+ return err;
+}
+
+static struct s5ka3dfx_platform_data s5ka3dfx_plat = {
+ .default_width = 640,
+ .default_height = 480,
+ .pixelformat = V4L2_PIX_FMT_UYVY,
+ .freq = 24000000,
+ .is_mipi = 0,
+
+ .cam_power = s5ka3dfx_power_en,
+};
+
+static struct i2c_board_info s5ka3dfx_i2c_info = {
+ I2C_BOARD_INFO("S5KA3DFX", 0xc4>>1),
+ .platform_data = &s5ka3dfx_plat,
+};
+
+static struct s3c_platform_camera s5ka3dfx = {
+ .id = CAMERA_PAR_A,
+ .type = CAM_TYPE_ITU,
+ .fmt = ITU_601_YCBCR422_8BIT,
+ .order422 = CAM_ORDER422_8BIT_CBYCRY,
+ .i2c_busnum = 0,
+ .info = &s5ka3dfx_i2c_info,
+ .pixelformat = V4L2_PIX_FMT_UYVY,
+ .srclk_name = "xusbxti",
+ .clk_name = "sclk_cam",
+ .clk_rate = 24000000,
+ .line_length = 480,
+ .width = 640,
+ .height = 480,
+ .window = {
+ .left = 0,
+ .top = 0,
+ .width = 640,
+ .height = 480,
+ },
+
+ /* Polarity */
+ .inv_pclk = 0,
+ .inv_vsync = 1,
+ .inv_href = 0,
+ .inv_hsync = 0,
+
+ .initialized = 0,
+ .cam_power = s5ka3dfx_power_en,
+};
+
+/* Interface setting */
+static struct s3c_platform_fimc fimc_plat_lsi = {
+ .srclk_name = "mout_mpll",
+ .clk_name = "sclk_fimc",
+ .lclk_name = "fimc",
+ .clk_rate = 166750000,
+ .default_cam = CAMERA_PAR_A,
+ .camera = {
+ &s5k4ecgx,
+ &s5ka3dfx,
+ },
+ .hw_ver = 0x43,
+};
+
+#ifdef CONFIG_VIDEO_JPEG_V2
+static struct s3c_platform_jpeg jpeg_plat __initdata = {
+ .max_main_width = 800,
+ .max_main_height = 480,
+ .max_thumb_width = 320,
+ .max_thumb_height = 240,
+};
+#endif
+
+static struct k3g_platform_data k3g_pdata = {
+ .axis_map_x = 1,
+ .axis_map_y = 1,
+ .axis_map_z = 1,
+ .negate_x = 0,
+ .negate_y = 0,
+ .negate_z = 0,
+};
+
+/* I2C0 */
+static struct i2c_board_info i2c_devs0[] __initdata = {
+ {
+ I2C_BOARD_INFO("k3g", 0x69),
+ .platform_data = &k3g_pdata,
+ },
+};
+
+static struct i2c_board_info i2c_devs4[] __initdata = {
+ {
+ I2C_BOARD_INFO("wm8994-samsung", (0x34>>1)),
+ .platform_data = &wm8994_pdata,
+ },
+};
+
+static struct akm8973_platform_data akm8973_pdata = {
+ .reset_line = GPIO_MSENSE_nRST,
+ .reset_asserted = GPIO_LEVEL_LOW,
+ .gpio_data_ready_int = GPIO_MSENSE_IRQ,
+};
+
+static struct kr3dm_platform_data kr3dm_data = {
+ .gpio_acc_int = GPIO_ACC_INT,
+};
+
+/* I2C1 */
+static struct i2c_board_info i2c_devs1[] __initdata = {
+ {
+ I2C_BOARD_INFO("ak8973", 0x1c),
+ .platform_data = &akm8973_pdata,
+ },
+ {
+ I2C_BOARD_INFO("kr3dm", 0x09),
+ .platform_data = &kr3dm_data,
+ },
+};
+
+static void mxt224_power_on(void)
+{
+ gpio_direction_output(GPIO_TOUCH_EN, 1);
+
+ mdelay(40);
+}
+
+static void mxt224_power_off(void)
+{
+ gpio_direction_output(GPIO_TOUCH_EN, 0);
+}
+
+#define MXT224_MAX_MT_FINGERS 5
+
+static u8 t7_config[] = {GEN_POWERCONFIG_T7,
+ 64, 255, 50};
+static u8 t8_config[] = {GEN_ACQUISITIONCONFIG_T8,
+ 7, 0, 5, 0, 0, 0, 9, 35};
+static u8 t9_config[] = {TOUCH_MULTITOUCHSCREEN_T9,
+ 139, 0, 0, 19, 11, 0, 32, 25, 2, 1, 10, 3, 1,
+ 46, MXT224_MAX_MT_FINGERS, 5, 40, 10, 255, 3,
+ 255, 3, 18, 18, 10, 10, 141, 65, 143, 110, 18};
+static u8 t18_config[] = {SPT_COMCONFIG_T18,
+ 0, 1};
+static u8 t20_config[] = {PROCI_GRIPFACESUPPRESSION_T20,
+ 7, 0, 0, 0, 0, 0, 0, 80, 40, 4, 35, 10};
+static u8 t22_config[] = {PROCG_NOISESUPPRESSION_T22,
+ 5, 0, 0, 0, 0, 0, 0, 3, 30, 0, 0, 29, 34, 39,
+ 49, 58, 3};
+static u8 t28_config[] = {SPT_CTECONFIG_T28,
+ 1, 0, 3, 16, 63, 60};
+static u8 end_config[] = {RESERVED_T255};
+
+static const u8 *mxt224_config[] = {
+ t7_config,
+ t8_config,
+ t9_config,
+ t18_config,
+ t20_config,
+ t22_config,
+ t28_config,
+ end_config,
+};
+
+static struct mxt224_platform_data mxt224_data = {
+ .max_finger_touches = MXT224_MAX_MT_FINGERS,
+ .gpio_read_done = GPIO_TOUCH_INT,
+ .config = mxt224_config,
+ .min_x = 0,
+ .max_x = 1023,
+ .min_y = 0,
+ .max_y = 1023,
+ .min_z = 0,
+ .max_z = 255,
+ .min_w = 0,
+ .max_w = 30,
+ .power_on = mxt224_power_on,
+ .power_off = mxt224_power_off,
+};
+
+/* I2C2 */
+static struct i2c_board_info i2c_devs2[] __initdata = {
+ {
+ I2C_BOARD_INFO(MXT224_DEV_NAME, 0x4a),
+ .platform_data = &mxt224_data,
+ .irq = IRQ_EINT_GROUP(18, 5),
+ },
+};
+
+static void mxt224_init(void)
+{
+ if (!herring_is_tft_dev())
+ return;
+ mxt224_data.max_y = 950;
+ t9_config[8] = 45;
+ t9_config[9] = 3;
+ t9_config[23] = 0;
+ t9_config[24] = 0;
+ t9_config[27] = 0;
+ t9_config[28] = 0;
+ t9_config[29] = 0;
+ t9_config[30] = 0;
+}
+
+static ssize_t herring_virtual_keys_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return sprintf(buf,
+ __stringify(EV_KEY) ":" __stringify(KEY_BACK) ":71:839:73:62"
+ ":" __stringify(EV_KEY) ":"
+ __stringify(KEY_MENU) ":183:839:73:62"
+ ":" __stringify(EV_KEY) ":"
+ __stringify(KEY_SEARCH) ":294:839:73:62"
+ ":" __stringify(EV_KEY) ":"
+ __stringify(KEY_HOME) ":406:839:73:62"
+ "\n");
+}
+
+static struct kobj_attribute herring_virtual_keys_attr = {
+ .attr = {
+ .name = "virtualkeys.mxt224_ts_input",
+ .mode = S_IRUGO,
+ },
+ .show = &herring_virtual_keys_show,
+};
+
+static struct attribute *herring_properties_attrs[] = {
+ &herring_virtual_keys_attr.attr,
+ NULL,
+};
+
+static struct attribute_group herring_properties_attr_group = {
+ .attrs = herring_properties_attrs,
+};
+
+static void herring_virtual_keys_init(void)
+{
+ struct kobject *properties_kobj;
+ int ret;
+
+ properties_kobj = kobject_create_and_add("board_properties", NULL);
+ if (properties_kobj)
+ ret = sysfs_create_group(properties_kobj,
+ &herring_properties_attr_group);
+ if (!properties_kobj || ret)
+ pr_err("failed to create board_properties\n");
+}
+
+/* I2C2 */
+static struct i2c_board_info i2c_devs10[] __initdata = {
+ {
+ I2C_BOARD_INFO(CYPRESS_TOUCHKEY_DEV_NAME, 0x20),
+ .platform_data = &touchkey_data,
+ .irq = (IRQ_EINT_GROUP22_BASE + 1),
+ },
+};
+
+static struct i2c_board_info i2c_devs5[] __initdata = {
+ {
+ I2C_BOARD_INFO("kr3dm", 0x09),
+ .platform_data = &kr3dm_data,
+ },
+};
+
+static struct i2c_board_info i2c_devs8[] __initdata = {
+ {
+ I2C_BOARD_INFO("k3g", 0x69),
+ .platform_data = &k3g_pdata,
+ .irq = -1,
+ },
+};
+
+static void k3g_irq_init(void)
+{
+ i2c_devs0[0].irq = (system_rev >= 0x0A) ? IRQ_EINT(29) : -1;
+}
+
+
+static void fsa9480_usb_cb(bool attached)
+{
+ struct usb_gadget *gadget = platform_get_drvdata(&s3c_device_usbgadget);
+
+ if (gadget) {
+ if (attached)
+ usb_gadget_vbus_connect(gadget);
+ else
+ usb_gadget_vbus_disconnect(gadget);
+ }
+
+ set_cable_status = attached ? CABLE_TYPE_USB : CABLE_TYPE_NONE;
+ if (callbacks && callbacks->set_cable)
+ callbacks->set_cable(callbacks, set_cable_status);
+}
+
+static void fsa9480_charger_cb(bool attached)
+{
+ set_cable_status = attached ? CABLE_TYPE_AC : CABLE_TYPE_NONE;
+ if (callbacks && callbacks->set_cable)
+ callbacks->set_cable(callbacks, set_cable_status);
+}
+
+static struct switch_dev switch_dock = {
+ .name = "dock",
+};
+
+static void fsa9480_deskdock_cb(bool attached)
+{
+ struct usb_gadget *gadget = platform_get_drvdata(&s3c_device_usbgadget);
+
+ if (attached)
+ switch_set_state(&switch_dock, 1);
+ else
+ switch_set_state(&switch_dock, 0);
+
+ if (gadget) {
+ if (attached)
+ usb_gadget_vbus_connect(gadget);
+ else
+ usb_gadget_vbus_disconnect(gadget);
+ }
+
+ set_cable_status = attached ? CABLE_TYPE_USB : CABLE_TYPE_NONE;
+ if (callbacks && callbacks->set_cable)
+ callbacks->set_cable(callbacks, set_cable_status);
+}
+
+static void fsa9480_cardock_cb(bool attached)
+{
+ if (attached)
+ switch_set_state(&switch_dock, 2);
+ else
+ switch_set_state(&switch_dock, 0);
+}
+
+static void fsa9480_reset_cb(void)
+{
+ int ret;
+
+ /* for CarDock, DeskDock */
+ ret = switch_dev_register(&switch_dock);
+ if (ret < 0)
+ pr_err("Failed to register dock switch. %d\n", ret);
+}
+
+static struct fsa9480_platform_data fsa9480_pdata = {
+ .usb_cb = fsa9480_usb_cb,
+ .charger_cb = fsa9480_charger_cb,
+ .deskdock_cb = fsa9480_deskdock_cb,
+ .cardock_cb = fsa9480_cardock_cb,
+ .reset_cb = fsa9480_reset_cb,
+};
+
+static struct i2c_board_info i2c_devs7[] __initdata = {
+ {
+ I2C_BOARD_INFO("fsa9480", 0x4A >> 1),
+ .platform_data = &fsa9480_pdata,
+ .irq = IRQ_EINT(23),
+ },
+};
+
+static struct i2c_board_info i2c_devs6[] __initdata = {
+#ifdef CONFIG_REGULATOR_MAX8998
+ {
+ /* The address is 0xCC used since SRAD = 0 */
+ I2C_BOARD_INFO("max8998", (0xCC >> 1)),
+ .platform_data = &max8998_pdata,
+ .irq = IRQ_EINT7,
+ }, {
+ I2C_BOARD_INFO("rtc_max8998", (0x0D >> 1)),
+ },
+#endif
+};
+
+static struct pn544_i2c_platform_data pn544_pdata = {
+ .irq_gpio = NFC_IRQ,
+ .ven_gpio = NFC_EN,
+ .firm_gpio = NFC_FIRM,
+};
+
+static struct i2c_board_info i2c_devs14[] __initdata = {
+ {
+ I2C_BOARD_INFO("pn544", 0x2b),
+ .irq = IRQ_EINT(12),
+ .platform_data = &pn544_pdata,
+ },
+};
+
+static int max17040_power_supply_register(struct device *parent,
+ struct power_supply *psy)
+{
+ herring_charger.psy_fuelgauge = psy;
+ return 0;
+}
+
+static void max17040_power_supply_unregister(struct power_supply *psy)
+{
+ herring_charger.psy_fuelgauge = NULL;
+}
+
+static struct max17040_platform_data max17040_pdata = {
+ .power_supply_register = max17040_power_supply_register,
+ .power_supply_unregister = max17040_power_supply_unregister,
+ .rcomp_value = 0xD700,
+};
+
+static struct i2c_board_info i2c_devs9[] __initdata = {
+ {
+ I2C_BOARD_INFO("max17040", (0x6D >> 1)),
+ .platform_data = &max17040_pdata,
+ },
+};
+
+static void gp2a_gpio_init(void)
+{
+ int ret = gpio_request(GPIO_PS_ON, "gp2a_power_supply_on");
+ if (ret)
+ printk(KERN_ERR "Failed to request gpio gp2a power supply.\n");
+}
+
+static int gp2a_power(bool on)
+{
+ /* this controls the power supply rail to the gp2a IC */
+ gpio_direction_output(GPIO_PS_ON, on);
+ return 0;
+}
+
+static int gp2a_light_adc_value(void)
+{
+ return s3c_adc_get_adc_data(9);
+}
+
+static struct gp2a_platform_data gp2a_pdata = {
+ .power = gp2a_power,
+ .p_out = GPIO_PS_VOUT,
+ .light_adc_value = gp2a_light_adc_value,
+ .light_adc_max = 4095,
+ .light_adc_fuzz = 64,
+};
+
+static struct i2c_board_info i2c_devs11[] __initdata = {
+ {
+ I2C_BOARD_INFO("gp2a", (0x88 >> 1)),
+ .platform_data = &gp2a_pdata,
+ },
+};
+
+static struct i2c_board_info i2c_devs12[] __initdata = {
+ {
+ I2C_BOARD_INFO("ak8973", 0x1c),
+ .platform_data = &akm8973_pdata,
+ },
+};
+
+static struct resource ram_console_resource[] = {
+ {
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static struct platform_device ram_console_device = {
+ .name = "ram_console",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(ram_console_resource),
+ .resource = ram_console_resource,
+};
+
+#ifdef CONFIG_ANDROID_PMEM
+static struct android_pmem_platform_data pmem_pdata = {
+ .name = "pmem",
+ .no_allocator = 1,
+ .cached = 1,
+ .start = 0,
+ .size = 0,
+};
+
+static struct android_pmem_platform_data pmem_gpu1_pdata = {
+ .name = "pmem_gpu1",
+ .no_allocator = 1,
+ .cached = 1,
+ .buffered = 1,
+ .start = 0,
+ .size = 0,
+};
+
+static struct android_pmem_platform_data pmem_adsp_pdata = {
+ .name = "pmem_adsp",
+ .no_allocator = 1,
+ .cached = 1,
+ .buffered = 1,
+ .start = 0,
+ .size = 0,
+};
+
+static struct platform_device pmem_device = {
+ .name = "android_pmem",
+ .id = 0,
+ .dev = { .platform_data = &pmem_pdata },
+};
+
+static struct platform_device pmem_gpu1_device = {
+ .name = "android_pmem",
+ .id = 1,
+ .dev = { .platform_data = &pmem_gpu1_pdata },
+};
+
+static struct platform_device pmem_adsp_device = {
+ .name = "android_pmem",
+ .id = 2,
+ .dev = { .platform_data = &pmem_adsp_pdata },
+};
+
+static void __init android_pmem_set_platdata(void)
+{
+ pmem_pdata.start = (u32)s5p_get_media_memory_bank(S5P_MDEV_PMEM, 0);
+ pmem_pdata.size = (u32)s5p_get_media_memsize_bank(S5P_MDEV_PMEM, 0);
+
+ pmem_gpu1_pdata.start =
+ (u32)s5p_get_media_memory_bank(S5P_MDEV_PMEM_GPU1, 0);
+ pmem_gpu1_pdata.size =
+ (u32)s5p_get_media_memsize_bank(S5P_MDEV_PMEM_GPU1, 0);
+
+ pmem_adsp_pdata.start =
+ (u32)s5p_get_media_memory_bank(S5P_MDEV_PMEM_ADSP, 0);
+ pmem_adsp_pdata.size =
+ (u32)s5p_get_media_memsize_bank(S5P_MDEV_PMEM_ADSP, 0);
+}
+#endif
+
+struct platform_device sec_device_battery = {
+ .name = "sec-battery",
+ .id = -1,
+};
+
+static struct platform_device sec_device_rfkill = {
+ .name = "bt_rfkill",
+ .id = -1,
+};
+
+static struct platform_device sec_device_btsleep = {
+ .name = "bt_sleep",
+ .id = -1,
+};
+
+static struct sec_jack_zone sec_jack_zones[] = {
+ {
+ /* adc == 0, unstable zone, default to 3pole if it stays
+ * in this range for a half second (20ms delays, 25 samples)
+ */
+ .adc_high = 0,
+ .delay_ms = 20,
+ .check_count = 25,
+ .jack_type = SEC_HEADSET_3POLE,
+ },
+ {
+ /* 0 < adc <= 1000, unstable zone, default to 3pole if it stays
+ * in this range for a second (10ms delays, 100 samples)
+ */
+ .adc_high = 1000,
+ .delay_ms = 10,
+ .check_count = 100,
+ .jack_type = SEC_HEADSET_3POLE,
+ },
+ {
+ /* 1000 < adc <= 2000, unstable zone, default to 4pole if it
+ * stays in this range for a second (10ms delays, 100 samples)
+ */
+ .adc_high = 2000,
+ .delay_ms = 10,
+ .check_count = 100,
+ .jack_type = SEC_HEADSET_4POLE,
+ },
+ {
+ /* 2000 < adc <= 3700, 4 pole zone, default to 4pole if it
+ * stays in this range for 200ms (20ms delays, 10 samples)
+ */
+ .adc_high = 3700,
+ .delay_ms = 20,
+ .check_count = 10,
+ .jack_type = SEC_HEADSET_4POLE,
+ },
+ {
+ /* adc > 3700, unstable zone, default to 3pole if it stays
+ * in this range for a second (10ms delays, 100 samples)
+ */
+ .adc_high = 0x7fffffff,
+ .delay_ms = 10,
+ .check_count = 100,
+ .jack_type = SEC_HEADSET_3POLE,
+ },
+};
+
+/* To support 3-buttons earjack */
+static struct sec_jack_buttons_zone sec_jack_buttons_zones[] = {
+ {
+ /* 0 <= adc <=110, stable zone */
+ .code = KEY_MEDIA,
+ .adc_low = 0,
+ .adc_high = 110,
+ },
+ {
+ /* 130 <= adc <= 365, stable zone */
+ .code = KEY_PREVIOUSSONG,
+ .adc_low = 130,
+ .adc_high = 365,
+ },
+ {
+ /* 385 <= adc <= 870, stable zone */
+ .code = KEY_NEXTSONG,
+ .adc_low = 385,
+ .adc_high = 870,
+ },
+};
+
+static int sec_jack_get_adc_value(void)
+{
+ return s3c_adc_get_adc_data(3);
+}
+
+struct sec_jack_platform_data sec_jack_pdata = {
+ .set_micbias_state = sec_jack_set_micbias_state,
+ .get_adc_value = sec_jack_get_adc_value,
+ .zones = sec_jack_zones,
+ .num_zones = ARRAY_SIZE(sec_jack_zones),
+ .buttons_zones = sec_jack_buttons_zones,
+ .num_buttons_zones = ARRAY_SIZE(sec_jack_buttons_zones),
+ .det_gpio = GPIO_DET_35,
+ .send_end_gpio = GPIO_EAR_SEND_END,
+};
+
+static struct platform_device sec_device_jack = {
+ .name = "sec_jack",
+ .id = 1, /* will be used also for gpio_event id */
+ .dev.platform_data = &sec_jack_pdata,
+};
+
+
+#define S3C_GPIO_SETPIN_ZERO 0
+#define S3C_GPIO_SETPIN_ONE 1
+#define S3C_GPIO_SETPIN_NONE 2
+
+struct gpio_init_data {
+ uint num;
+ uint cfg;
+ uint val;
+ uint pud;
+ uint drv;
+};
+
+static struct gpio_init_data herring_init_gpios[] = {
+ {
+ .num = S5PV210_GPB(0),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPB(1),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+
+ }, {
+ .num = S5PV210_GPB(2),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPB(3),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPB(4),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPB(5),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPB(6),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPB(7),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ },
+
+ {
+ .num = S5PV210_GPC0(0),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPC0(1),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPC0(2),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPC0(3),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPC0(4),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ },
+
+ {
+ .num = S5PV210_GPC1(0),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPC1(1),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPC1(2),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPC1(3),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPC1(4),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ },
+
+ {
+ .num = S5PV210_GPD0(0),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPD0(1),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPD0(2),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPD0(3),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ },
+
+ {
+ .num = S5PV210_GPD1(0),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPD1(1),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPD1(2),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPD1(3),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPD1(4),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPD1(5),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ },
+
+ {
+ .num = S5PV210_GPE0(0),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPE0(1),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPE0(2),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPE0(3),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPE0(4),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPE0(5),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPE0(6),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPE0(7),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ },
+
+
+ {
+ .num = S5PV210_GPE1(0),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPE1(1),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPE1(2),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPE1(3),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPE1(4),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ },
+
+ {
+ .num = S5PV210_GPF3(4),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPF3(5),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ },
+
+ {
+ .num = S5PV210_GPG0(0),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPG0(1),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPG0(2),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPG0(3),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPG0(4),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPG0(5),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPG0(6),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ },
+
+ {
+ .num = S5PV210_GPG1(0),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPG1(1),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPG1(2),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPG1(3),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPG1(4),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPG1(5),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPG1(6),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ },
+
+ {
+ .num = S5PV210_GPG2(0),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPG2(1),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPG2(2),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPG2(3),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPG2(4),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPG2(5),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPG2(6),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ },
+
+ {
+ .num = S5PV210_GPG3(0),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPG3(1),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPG3(2),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPG3(3),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPG3(4),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPG3(5),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPG3(6),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ },
+
+ {
+ .num = S5PV210_GPH0(0),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPH0(1),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPH0(2),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPH0(3),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPH0(4),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPH0(5),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, { /* GPIO_DET_35 - 3.5" ear jack */
+ .num = S5PV210_GPH0(6),
+ .cfg = S3C_GPIO_SFN(GPIO_DET_35_AF),
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPH0(7),
+ .cfg = S3C_GPIO_SFN(0xF),
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ },
+
+ {
+ .num = S5PV210_GPH1(0),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPH1(1),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPH1(2),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPH1(3),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, { /* NFC_IRQ */
+ .num = S5PV210_GPH1(4),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, { /* NFC_EN */
+ .num = S5PV210_GPH1(5),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ONE,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, { /* NFC_FIRM */
+ .num = S5PV210_GPH1(6),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPH1(7),
+ .cfg = S3C_GPIO_SFN(0xF),
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ },
+
+ {
+ .num = S5PV210_GPH2(0),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPH2(1),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPH2(2),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPH2(3),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPH2(4),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPH2(5),
+ .cfg = S3C_GPIO_SFN(0xF),
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPH2(6),
+ .cfg = S3C_GPIO_SFN(0xF),
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPH2(7),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ },
+
+ {
+ .num = S5PV210_GPH3(0),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_UP,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPH3(1),
+ .cfg = S3C_GPIO_SFN(0xF),
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPH3(2),
+ .cfg = S3C_GPIO_SFN(0xF),
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPH3(3),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPH3(4),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPH3(5),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, { /* GPIO_EAR_SEND_END */
+ .num = S5PV210_GPH3(6),
+ .cfg = S3C_GPIO_SFN(GPIO_EAR_SEND_END_AF),
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPH3(7),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ },
+
+ {
+ .num = S5PV210_GPI(0),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPI(1),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPI(2),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPI(3),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPI(4),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPI(5),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPI(6),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ },
+
+ {
+ .num = S5PV210_GPJ0(0),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPJ0(1),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPJ0(2),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPJ0(3),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPJ0(4),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPJ0(5),
+ .cfg = S3C_GPIO_SFN(0xF),
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPJ0(6),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPJ0(7),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ },
+
+ {
+ .num = S5PV210_GPJ1(0),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPJ1(1),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPJ1(2),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPJ1(3),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPJ1(4),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPJ1(5),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ },
+
+ {
+ .num = S5PV210_GPJ2(0),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPJ2(1),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPJ2(2),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPJ2(3),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPJ2(4),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPJ2(5),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPJ2(6),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPJ2(7),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ },
+
+ {
+ .num = S5PV210_GPJ3(0),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPJ3(1),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPJ3(2),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, { /* GPIO_EAR_ADC_SEL */
+ .num = S5PV210_GPJ3(3),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPJ3(4),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPJ3(5),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPJ3(6),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPJ3(7),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ },
+
+ {
+ .num = S5PV210_GPJ4(0),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPJ4(1),
+ .cfg = S3C_GPIO_SFN(0xF),
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPJ4(2),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPJ4(3),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_GPJ4(4),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ },
+
+ {
+ .num = S5PV210_MP01(0),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_MP01(2),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_MP01(5),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ },
+
+ {
+ .num = S5PV210_MP02(0),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_MP02(1),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_MP02(3),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ },
+
+ {
+ .num = S5PV210_MP03(3),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_MP03(5),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_MP03(6),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_MP03(7),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ },
+
+ {
+ .num = S5PV210_MP04(0),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_MP04(2),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, { /* NFC_SCL_18V - has external pull up resistor */
+ .num = S5PV210_MP04(4),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, { /* NFC_SDA_18V - has external pull up resistor */
+ .num = S5PV210_MP04(5),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_MP04(6),
+ .cfg = S3C_GPIO_OUTPUT,
+ .val = S3C_GPIO_SETPIN_ZERO,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_MP04(7),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ },
+
+ {
+ .num = S5PV210_MP05(0),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_MP05(1),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_MP05(2),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_MP05(3),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_NONE,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_MP05(4),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ }, {
+ .num = S5PV210_MP05(6),
+ .cfg = S3C_GPIO_INPUT,
+ .val = S3C_GPIO_SETPIN_NONE,
+ .pud = S3C_GPIO_PULL_DOWN,
+ .drv = S3C_GPIO_DRVSTR_1X,
+ },
+};
+
+void s3c_config_gpio_table(void)
+{
+ u32 i, gpio;
+
+ for (i = 0; i < ARRAY_SIZE(herring_init_gpios); i++) {
+ gpio = herring_init_gpios[i].num;
+ if (system_rev <= 0x07 && gpio == S5PV210_GPJ3(3)) {
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_OUTPUT);
+ gpio_set_value(gpio, S3C_GPIO_SETPIN_ONE);
+ } else if (gpio <= S5PV210_MP05(7)) {
+ s3c_gpio_cfgpin(gpio, herring_init_gpios[i].cfg);
+ s3c_gpio_setpull(gpio, herring_init_gpios[i].pud);
+
+ if (herring_init_gpios[i].val != S3C_GPIO_SETPIN_NONE)
+ gpio_set_value(gpio, herring_init_gpios[i].val);
+
+ s3c_gpio_set_drvstrength(gpio,
+ herring_init_gpios[i].drv);
+ }
+ }
+
+ if (herring_is_cdma_wimax_dev()) {
+ /* WiMAX_I2C_CON */
+ gpio = S5PV210_GPC1(1);
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
+ gpio_set_value(gpio, S3C_GPIO_SETPIN_ONE);
+ s3c_gpio_set_drvstrength(gpio, S3C_GPIO_DRVSTR_4X);
+
+ gpio = S5PV210_GPC1(3);
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_INPUT);
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
+ gpio_set_value(gpio, S3C_GPIO_SETPIN_NONE);
+ s3c_gpio_set_drvstrength(gpio, S3C_GPIO_DRVSTR_4X);
+
+ gpio = S5PV210_GPC1(4);
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_INPUT);
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
+ gpio_set_value(gpio, S3C_GPIO_SETPIN_NONE);
+ s3c_gpio_set_drvstrength(gpio, S3C_GPIO_DRVSTR_4X);
+
+ gpio = S5PV210_GPG2(0);
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+ gpio = S5PV210_GPG2(1);
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+ gpio = S5PV210_GPG2(3);
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+ gpio = S5PV210_GPG2(4);
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+ gpio = S5PV210_GPG2(5);
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+ gpio = S5PV210_GPG2(6);
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+
+ /* WIMAX_EN */
+ gpio = S5PV210_GPH1(0);
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+ gpio_set_value(gpio, S3C_GPIO_SETPIN_ZERO);
+ s3c_gpio_set_drvstrength(gpio, S3C_GPIO_DRVSTR_1X);
+
+ /* GPIO_CP_RST, CDMA modem specific setting */
+ gpio = S5PV210_GPH3(7);
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_DOWN);
+ gpio_set_value(gpio, S3C_GPIO_SETPIN_ZERO);
+ s3c_gpio_set_drvstrength(gpio, S3C_GPIO_DRVSTR_4X);
+
+ gpio = S5PV210_MP05(2);
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_INPUT);
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
+ gpio_set_value(gpio, S3C_GPIO_SETPIN_NONE);
+ s3c_gpio_set_drvstrength(gpio, S3C_GPIO_DRVSTR_4X);
+
+ gpio = S5PV210_MP05(3);
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_INPUT);
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
+ gpio_set_value(gpio, S3C_GPIO_SETPIN_NONE);
+ s3c_gpio_set_drvstrength(gpio, S3C_GPIO_DRVSTR_4X);
+ }
+}
+
+#define S5PV210_PS_HOLD_CONTROL_REG (S3C_VA_SYS+0xE81C)
+static void herring_power_off(void)
+{
+ int phone_wait_cnt = 0;
+
+ if (herring_is_cdma_wimax_dev()) {
+ /* confirm phone is powered-off */
+ while (1) {
+ if (gpio_get_value(GPIO_PHONE_ACTIVE)) {
+ pr_info("%s: Try to Turn Phone Off by CP_RST\n",
+ __func__);
+ gpio_set_value(GPIO_CP_RST, 0);
+ if (phone_wait_cnt > 1) {
+ pr_info("%s: PHONE OFF Fail\n",
+ __func__);
+ break;
+ }
+ phone_wait_cnt++;
+ mdelay(100);
+ } else {
+ pr_info("%s: PHONE OFF Success\n", __func__);
+ break;
+ }
+ }
+ }
+
+ while (1) {
+ /* Check reboot charging */
+ if (set_cable_status) {
+ /* watchdog reset */
+ pr_info("%s: charger connected, rebooting\n", __func__);
+ writel(3, S5P_INFORM6);
+ arch_reset('r', NULL);
+ pr_crit("%s: waiting for reset!\n", __func__);
+ while (1);
+ }
+
+ /* wait for power button release */
+ if (gpio_get_value(GPIO_nPOWER)) {
+ pr_info("%s: set PS_HOLD low\n", __func__);
+
+ /* PS_HOLD high PS_HOLD_CONTROL, R/W, 0xE010_E81C */
+ writel(readl(S5PV210_PS_HOLD_CONTROL_REG) & 0xFFFFFEFF,
+ S5PV210_PS_HOLD_CONTROL_REG);
+
+ pr_crit("%s: should not reach here!\n", __func__);
+ }
+
+ /* if power button is not released, wait and check TA again */
+ pr_info("%s: PowerButton is not released.\n", __func__);
+ mdelay(1000);
+ }
+}
+
+/* this table only for B4 board */
+static unsigned int herring_sleep_gpio_table[][3] = {
+ { S5PV210_GPA0(0), S3C_GPIO_SLP_PREV, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPA0(1), S3C_GPIO_SLP_PREV, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPA0(2), S3C_GPIO_SLP_PREV, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPA0(3), S3C_GPIO_SLP_PREV, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPA0(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPA0(5), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPA0(6), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPA0(7), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+
+ { S5PV210_GPA1(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPA1(1), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPA1(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPA1(3), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+
+ { S5PV210_GPB(0), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPB(1), S3C_GPIO_SLP_OUT1, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPB(2), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPB(3), S3C_GPIO_SLP_PREV, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPB(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPB(5), S3C_GPIO_SLP_PREV, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPB(6), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPB(7), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+
+ { S5PV210_GPC0(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPC0(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPC0(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPC0(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPC0(4), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+
+ { S5PV210_GPC1(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPC1(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPC1(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPC1(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPC1(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+
+ { S5PV210_GPD0(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPD0(1), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPD0(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPD0(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+
+ { S5PV210_GPD1(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPD1(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPD1(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPD1(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPD1(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPD1(5), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+
+ { S5PV210_GPE0(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPE0(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPE0(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPE0(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPE0(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPE0(5), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPE0(6), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPE0(7), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+
+ { S5PV210_GPE1(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPE1(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPE1(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPE1(3), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPE1(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+
+ { S5PV210_GPF0(0), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF0(1), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF0(2), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF0(3), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF0(4), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF0(5), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF0(6), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF0(7), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+
+ { S5PV210_GPF1(0), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF1(1), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF1(2), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF1(3), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF1(4), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF1(5), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF1(6), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF1(7), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+
+ { S5PV210_GPF2(0), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF2(1), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF2(2), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF2(3), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF2(4), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF2(5), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF2(6), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF2(7), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+
+ { S5PV210_GPF3(0), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF3(1), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF3(2), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF3(3), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF3(4), S3C_GPIO_SLP_PREV, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF3(5), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+
+ { S5PV210_GPG0(0), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPG0(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPG0(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPG0(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPG0(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPG0(5), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPG0(6), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+
+ { S5PV210_GPG1(0), S3C_GPIO_SLP_OUT1, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPG1(1), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPG1(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPG1(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPG1(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPG1(5), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPG1(6), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+
+ { S5PV210_GPG2(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPG2(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPG2(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPG2(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPG2(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPG2(5), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPG2(6), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+
+ { S5PV210_GPG3(0), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPG3(1), S3C_GPIO_SLP_OUT1, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPG3(2), S3C_GPIO_SLP_PREV, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPG3(3), S3C_GPIO_SLP_OUT1, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPG3(4), S3C_GPIO_SLP_OUT1, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPG3(5), S3C_GPIO_SLP_OUT1, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPG3(6), S3C_GPIO_SLP_OUT1, S3C_GPIO_PULL_NONE},
+
+ /* Alive part ending and off part start*/
+ { S5PV210_GPI(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPI(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPI(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPI(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPI(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPI(5), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPI(6), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+
+ { S5PV210_GPJ0(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPJ0(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPJ0(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPJ0(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPJ0(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPJ0(5), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPJ0(6), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPJ0(7), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+
+ { S5PV210_GPJ1(0), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPJ1(1), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPJ1(2), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPJ1(3), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPJ1(4), S3C_GPIO_SLP_PREV, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPJ1(5), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+
+ { S5PV210_GPJ2(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPJ2(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPJ2(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPJ2(3), S3C_GPIO_SLP_PREV, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPJ2(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPJ2(5), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPJ2(6), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPJ2(7), S3C_GPIO_SLP_OUT1, S3C_GPIO_PULL_NONE},
+
+ { S5PV210_GPJ3(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPJ3(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPJ3(2), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPJ3(3), S3C_GPIO_SLP_PREV, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPJ3(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPJ3(5), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPJ3(6), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPJ3(7), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+
+ { S5PV210_GPJ4(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPJ4(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPJ4(2), S3C_GPIO_SLP_PREV, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPJ4(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPJ4(4), S3C_GPIO_SLP_PREV, S3C_GPIO_PULL_NONE},
+
+ /* memory part */
+ { S5PV210_MP01(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP01(1), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_MP01(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP01(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP01(4), S3C_GPIO_SLP_OUT1, S3C_GPIO_PULL_NONE},
+ { S5PV210_MP01(5), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP01(6), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP01(7), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+
+ { S5PV210_MP02(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP02(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP02(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_MP02(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+
+ { S5PV210_MP03(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP03(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP03(2), S3C_GPIO_SLP_OUT1, S3C_GPIO_PULL_NONE},
+ { S5PV210_MP03(3), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_MP03(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_MP03(5), S3C_GPIO_SLP_OUT1, S3C_GPIO_PULL_NONE},
+ { S5PV210_MP03(6), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP03(7), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+
+ { S5PV210_MP04(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP04(1), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_MP04(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP04(3), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_MP04(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_MP04(5), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_MP04(6), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_MP04(7), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+
+ { S5PV210_MP05(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_MP05(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_MP05(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_MP05(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_MP05(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP05(5), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_MP05(6), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP05(7), S3C_GPIO_SLP_PREV, S3C_GPIO_PULL_NONE},
+
+ { S5PV210_MP06(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP06(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP06(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP06(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP06(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP06(5), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP06(6), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP06(7), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+
+ { S5PV210_MP07(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP07(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP07(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP07(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP07(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP07(5), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP07(6), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP07(7), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+
+ /* Memory part ending and off part ending */
+};
+
+static unsigned int herring_cdma_wimax_sleep_gpio_table[][3] = {
+ { S5PV210_GPA0(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPA0(1), S3C_GPIO_SLP_PREV, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPA0(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPA0(3), S3C_GPIO_SLP_OUT1, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPA0(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPA0(5), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPA0(6), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPA0(7), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+
+ { S5PV210_GPA1(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPA1(1), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPA1(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPA1(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+
+ { S5PV210_GPB(0), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPB(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPB(2), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPB(3), S3C_GPIO_SLP_PREV, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPB(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPB(5), S3C_GPIO_SLP_PREV, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPB(6), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPB(7), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+
+ { S5PV210_GPC0(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPC0(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPC0(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPC0(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPC0(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+
+ /*WIMAX PMIC SDA*/
+ { S5PV210_GPC1(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+
+ /*Wimax eeprom switch*/
+ { S5PV210_GPC1(1), S3C_GPIO_SLP_PREV, S3C_GPIO_PULL_NONE},
+
+ /*WIMAX PMIC SCL*/
+ { S5PV210_GPC1(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+
+ /*WIMAX EEPROM I2C LINES*/
+ { S5PV210_GPC1(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPC1(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+
+ /*WIMAX DBGEN*/
+ { S5PV210_GPD0(0), S3C_GPIO_SLP_PREV, S3C_GPIO_PULL_NONE},
+
+ { S5PV210_GPD0(1), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPD0(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+
+ /*WIMAX RESET_N*/
+ { S5PV210_GPD0(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_UP},
+
+ { S5PV210_GPD1(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPD1(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPD1(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPD1(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPD1(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPD1(5), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+
+ { S5PV210_GPE0(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPE0(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPE0(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPE0(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPE0(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPE0(5), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPE0(6), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPE0(7), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+
+
+ { S5PV210_GPE1(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPE1(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPE1(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPE1(3), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPE1(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+
+ { S5PV210_GPF0(0), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF0(1), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF0(2), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF0(3), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF0(4), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF0(5), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF0(6), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF0(7), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+
+ { S5PV210_GPF1(0), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF1(1), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF1(2), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF1(3), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF1(4), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF1(5), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF1(6), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF1(7), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+
+
+ { S5PV210_GPF2(0), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF2(1), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF2(2), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF2(3), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF2(4), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF2(5), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF2(6), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF2(7), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+
+ { S5PV210_GPF3(0), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF3(1), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF3(2), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF3(3), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF3(4), S3C_GPIO_SLP_PREV, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPF3(5), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+
+
+ { S5PV210_GPG0(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPG0(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPG0(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPG0(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPG0(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPG0(5), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPG0(6), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+
+ { S5PV210_GPG1(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPG1(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPG1(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPG1(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPG1(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPG1(5), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPG1(6), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+
+ /*wimax SDIO pins*/
+ { S5PV210_GPG2(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPG2(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPG2(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPG2(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPG2(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPG2(5), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPG2(6), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+
+ { S5PV210_GPG3(0), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPG3(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPG3(2), S3C_GPIO_SLP_PREV, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPG3(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPG3(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPG3(5), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPG3(6), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+
+ /*WIMAX*/
+ { S5PV210_GPH1(0), S3C_GPIO_SLP_PREV, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPH1(2), S3C_GPIO_SLP_PREV, S3C_GPIO_PULL_NONE},
+
+ { S5PV210_GPH2(7), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPH3(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_UP},
+ { S5PV210_GPH3(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+
+ /* Alive part ending and off part start*/
+ { S5PV210_GPI(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPI(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPI(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPI(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPI(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPI(5), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPI(6), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+
+ { S5PV210_GPJ0(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPJ0(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPJ0(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPJ0(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPJ0(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPJ0(5), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPJ0(6), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPJ0(7), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+
+ { S5PV210_GPJ1(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPJ1(1), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPJ1(2), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPJ1(3), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPJ1(4), S3C_GPIO_SLP_PREV, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPJ1(5), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+
+ { S5PV210_GPJ2(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPJ2(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPJ2(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPJ2(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPJ2(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPJ2(5), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+
+ { S5PV210_GPJ2(6), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPJ2(7), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+
+ { S5PV210_GPJ3(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPJ3(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPJ3(2), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPJ3(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPJ3(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPJ3(5), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPJ3(6), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPJ3(7), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+
+ { S5PV210_GPJ4(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPJ4(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_GPJ4(2), S3C_GPIO_SLP_PREV, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPJ4(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_GPJ4(4), S3C_GPIO_SLP_PREV, S3C_GPIO_PULL_NONE},
+
+ /* memory part */
+ { S5PV210_MP01(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP01(1), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+
+ /*WIMAX*/
+ { S5PV210_MP01(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+
+ { S5PV210_MP01(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP01(4), S3C_GPIO_SLP_OUT1, S3C_GPIO_PULL_NONE},
+ { S5PV210_MP01(5), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP01(6), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP01(7), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+
+ { S5PV210_MP02(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP02(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP02(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_MP02(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+
+ { S5PV210_MP03(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP03(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP03(2), S3C_GPIO_SLP_OUT1, S3C_GPIO_PULL_NONE},
+ { S5PV210_MP03(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP03(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_MP03(5), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP03(6), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP03(7), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+
+ /*WIMAX*/
+ { S5PV210_MP04(0), S3C_GPIO_SLP_PREV, S3C_GPIO_PULL_NONE},
+
+ { S5PV210_MP04(1), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+
+ /*WIMAX*/
+ { S5PV210_MP04(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+
+ { S5PV210_MP04(3), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+ { S5PV210_MP04(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP04(5), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP04(6), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+
+ /*WIMAX*/
+ { S5PV210_MP04(7), S3C_GPIO_SLP_PREV, S3C_GPIO_PULL_NONE},
+
+ { S5PV210_MP05(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_MP05(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_MP05(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+ { S5PV210_MP05(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE},
+
+ /*WIMAX*/
+ { S5PV210_MP05(4), S3C_GPIO_SLP_PREV, S3C_GPIO_PULL_NONE},
+
+ { S5PV210_MP05(5), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE},
+
+ /*WIMAX*/
+ { S5PV210_MP05(6), S3C_GPIO_SLP_PREV, S3C_GPIO_PULL_NONE},
+
+ { S5PV210_MP05(7), S3C_GPIO_SLP_PREV, S3C_GPIO_PULL_NONE},
+
+ { S5PV210_MP06(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP06(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP06(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP06(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP06(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP06(5), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP06(6), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP06(7), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+
+ { S5PV210_MP07(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP07(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP07(2), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP07(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP07(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP07(5), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP07(6), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+ { S5PV210_MP07(7), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN},
+
+ /* Memory part ending and off part ending */
+};
+
+void s3c_config_sleep_gpio_table(int array_size, unsigned int (*gpio_table)[3])
+{
+ u32 i, gpio;
+
+ for (i = 0; i < array_size; i++) {
+ gpio = gpio_table[i][0];
+ s3c_gpio_slp_cfgpin(gpio, gpio_table[i][1]);
+ s3c_gpio_slp_setpull_updown(gpio, gpio_table[i][2]);
+ }
+}
+
+void s3c_config_cdma_wimax_sleep_gpio(void)
+{
+ s3c_gpio_cfgpin(S5PV210_GPH0(0), S3C_GPIO_INPUT);
+ s3c_gpio_setpull(S5PV210_GPH0(0), S3C_GPIO_PULL_DOWN);
+
+ s3c_gpio_cfgpin(S5PV210_GPH0(1), S3C_GPIO_INPUT);
+ s3c_gpio_setpull(S5PV210_GPH0(1), S3C_GPIO_PULL_DOWN);
+
+ s3c_gpio_cfgpin(S5PV210_GPH0(2), S3C_GPIO_INPUT);
+ s3c_gpio_setpull(S5PV210_GPH0(2), S3C_GPIO_PULL_NONE);
+
+ s3c_gpio_cfgpin(S5PV210_GPH0(3), S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(S5PV210_GPH0(3), S3C_GPIO_PULL_NONE);
+ gpio_set_value(S5PV210_GPH0(3), 0);
+
+ s3c_gpio_cfgpin(S5PV210_GPH0(4), S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(S5PV210_GPH0(4), S3C_GPIO_PULL_NONE);
+ gpio_set_value(S5PV210_GPH0(4), 0);
+
+ s3c_gpio_cfgpin(S5PV210_GPH0(5), S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(S5PV210_GPH0(5), S3C_GPIO_PULL_NONE);
+ gpio_set_value(S5PV210_GPH0(5), 0);
+
+ s3c_gpio_cfgpin(S5PV210_GPH1(0), S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(S5PV210_GPH1(0), S3C_GPIO_PULL_NONE);
+ gpio_set_value(S5PV210_GPH1(0), 0);
+
+ s3c_gpio_cfgpin(S5PV210_GPH1(1), S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(S5PV210_GPH1(1), S3C_GPIO_PULL_DOWN);
+ gpio_set_value(S5PV210_GPH1(1), 0);
+
+ s3c_gpio_cfgpin(S5PV210_GPH1(2), S3C_GPIO_INPUT);
+ s3c_gpio_setpull(S5PV210_GPH1(2), S3C_GPIO_PULL_UP);
+ gpio_set_value(S5PV210_GPH1(2), 0);
+
+ s3c_gpio_cfgpin(S5PV210_GPH1(4), S3C_GPIO_INPUT);
+ s3c_gpio_setpull(S5PV210_GPH1(4), S3C_GPIO_PULL_DOWN);
+
+ s3c_gpio_cfgpin(S5PV210_GPH1(5), S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(S5PV210_GPH1(5), S3C_GPIO_PULL_DOWN);
+ gpio_set_value(S5PV210_GPH1(5), 0);
+
+ s3c_gpio_cfgpin(S5PV210_GPH1(6), S3C_GPIO_INPUT);
+ s3c_gpio_setpull(S5PV210_GPH1(6), S3C_GPIO_PULL_DOWN);
+
+ s3c_gpio_cfgpin(S5PV210_GPH1(7), S3C_GPIO_INPUT);
+ s3c_gpio_setpull(S5PV210_GPH1(7), S3C_GPIO_PULL_NONE);
+
+ s3c_gpio_cfgpin(S5PV210_GPH2(0), S3C_GPIO_INPUT);
+ s3c_gpio_setpull(S5PV210_GPH2(0), S3C_GPIO_PULL_NONE);
+
+ s3c_gpio_cfgpin(S5PV210_GPH2(2), S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(S5PV210_GPH2(2), S3C_GPIO_PULL_NONE);
+ gpio_set_value(S5PV210_GPH2(2), 0);
+
+ s3c_gpio_cfgpin(S5PV210_GPH2(6), S3C_GPIO_INPUT);
+ s3c_gpio_setpull(S5PV210_GPH2(6), S3C_GPIO_PULL_UP);
+
+ s3c_gpio_cfgpin(S5PV210_GPH2(3), S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(S5PV210_GPH2(3), S3C_GPIO_PULL_NONE);
+ gpio_set_value(S5PV210_GPH2(3), 0);
+
+ s3c_gpio_cfgpin(S5PV210_GPH3(0), S3C_GPIO_INPUT);
+ s3c_gpio_setpull(S5PV210_GPH3(0), S3C_GPIO_PULL_UP);
+
+ s3c_gpio_cfgpin(S5PV210_GPH3(3), S3C_GPIO_INPUT);
+ s3c_gpio_setpull(S5PV210_GPH3(3), S3C_GPIO_PULL_NONE);
+
+ s3c_gpio_cfgpin(S5PV210_GPH3(4), S3C_GPIO_INPUT);
+ s3c_gpio_setpull(S5PV210_GPH3(4), S3C_GPIO_PULL_UP);
+
+ s3c_gpio_cfgpin(S5PV210_GPH3(5), S3C_GPIO_INPUT);
+ s3c_gpio_setpull(S5PV210_GPH3(5), S3C_GPIO_PULL_DOWN);
+
+ s3c_gpio_cfgpin(S5PV210_GPH3(7), S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(S5PV210_GPH3(7), S3C_GPIO_PULL_UP);
+ gpio_set_value(S5PV210_GPH3(7), 1);
+
+}
+
+void s3c_config_gsm_sleep_gpio(void)
+{
+ /* setting the alive mode registers */
+ s3c_gpio_cfgpin(S5PV210_GPH0(1), S3C_GPIO_INPUT);
+ s3c_gpio_setpull(S5PV210_GPH0(1), S3C_GPIO_PULL_NONE);
+
+ s3c_gpio_cfgpin(S5PV210_GPH0(3), S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(S5PV210_GPH0(3), S3C_GPIO_PULL_NONE);
+ gpio_set_value(S5PV210_GPH0(3), 0);
+
+ s3c_gpio_cfgpin(S5PV210_GPH0(4), S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(S5PV210_GPH0(4), S3C_GPIO_PULL_NONE);
+ gpio_set_value(S5PV210_GPH0(4), 0);
+
+ s3c_gpio_cfgpin(S5PV210_GPH0(5), S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(S5PV210_GPH0(5), S3C_GPIO_PULL_NONE);
+ gpio_set_value(S5PV210_GPH0(5), 0);
+
+ s3c_gpio_cfgpin(S5PV210_GPH1(0), S3C_GPIO_INPUT);
+ s3c_gpio_setpull(S5PV210_GPH1(0), S3C_GPIO_PULL_DOWN);
+
+ s3c_gpio_cfgpin(S5PV210_GPH1(1), S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(S5PV210_GPH1(1), S3C_GPIO_PULL_NONE);
+ gpio_set_value(S5PV210_GPH1(1), 0);
+
+ s3c_gpio_cfgpin(S5PV210_GPH1(2), S3C_GPIO_INPUT);
+ s3c_gpio_setpull(S5PV210_GPH1(2), S3C_GPIO_PULL_DOWN);
+
+ s3c_gpio_cfgpin(S5PV210_GPH1(4), S3C_GPIO_INPUT);
+ s3c_gpio_setpull(S5PV210_GPH1(4), S3C_GPIO_PULL_DOWN);
+
+ s3c_gpio_cfgpin(S5PV210_GPH1(5), S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(S5PV210_GPH1(5), S3C_GPIO_PULL_NONE);
+ gpio_set_value(S5PV210_GPH1(5), 0);
+
+ s3c_gpio_cfgpin(S5PV210_GPH1(6), S3C_GPIO_INPUT);
+ s3c_gpio_setpull(S5PV210_GPH1(6), S3C_GPIO_PULL_DOWN);
+
+ s3c_gpio_cfgpin(S5PV210_GPH1(7), S3C_GPIO_INPUT);
+ s3c_gpio_setpull(S5PV210_GPH1(7), S3C_GPIO_PULL_NONE);
+
+ s3c_gpio_cfgpin(S5PV210_GPH2(0), S3C_GPIO_INPUT);
+ s3c_gpio_setpull(S5PV210_GPH2(0), S3C_GPIO_PULL_DOWN);
+
+ s3c_gpio_cfgpin(S5PV210_GPH2(2), S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(S5PV210_GPH2(2), S3C_GPIO_PULL_NONE);
+ gpio_set_value(S5PV210_GPH2(2), 0);
+
+ s3c_gpio_cfgpin(S5PV210_GPH2(3), S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(S5PV210_GPH2(3), S3C_GPIO_PULL_NONE);
+ gpio_set_value(S5PV210_GPH2(3), 0);
+
+ s3c_gpio_cfgpin(S5PV210_GPH3(0), S3C_GPIO_INPUT);
+ s3c_gpio_setpull(S5PV210_GPH3(0), S3C_GPIO_PULL_UP);
+
+ s3c_gpio_cfgpin(S5PV210_GPH3(3), S3C_GPIO_INPUT);
+ s3c_gpio_setpull(S5PV210_GPH3(3), S3C_GPIO_PULL_DOWN);
+
+ s3c_gpio_cfgpin(S5PV210_GPH3(4), S3C_GPIO_INPUT);
+ s3c_gpio_setpull(S5PV210_GPH3(4), S3C_GPIO_PULL_DOWN);
+}
+
+void s3c_config_sleep_gpio(void)
+{
+ if (herring_is_cdma_wimax_dev())
+ s3c_config_cdma_wimax_sleep_gpio();
+ else
+ s3c_config_gsm_sleep_gpio();
+}
+EXPORT_SYMBOL(s3c_config_sleep_gpio);
+
+static unsigned int wlan_sdio_on_table[][4] = {
+ {GPIO_WLAN_SDIO_CLK, GPIO_WLAN_SDIO_CLK_AF, GPIO_LEVEL_NONE,
+ S3C_GPIO_PULL_NONE},
+ {GPIO_WLAN_SDIO_CMD, GPIO_WLAN_SDIO_CMD_AF, GPIO_LEVEL_NONE,
+ S3C_GPIO_PULL_NONE},
+ {GPIO_WLAN_SDIO_D0, GPIO_WLAN_SDIO_D0_AF, GPIO_LEVEL_NONE,
+ S3C_GPIO_PULL_NONE},
+ {GPIO_WLAN_SDIO_D1, GPIO_WLAN_SDIO_D1_AF, GPIO_LEVEL_NONE,
+ S3C_GPIO_PULL_NONE},
+ {GPIO_WLAN_SDIO_D2, GPIO_WLAN_SDIO_D2_AF, GPIO_LEVEL_NONE,
+ S3C_GPIO_PULL_NONE},
+ {GPIO_WLAN_SDIO_D3, GPIO_WLAN_SDIO_D3_AF, GPIO_LEVEL_NONE,
+ S3C_GPIO_PULL_NONE},
+};
+
+static unsigned int wlan_sdio_off_table[][4] = {
+ {GPIO_WLAN_SDIO_CLK, 1, GPIO_LEVEL_LOW, S3C_GPIO_PULL_NONE},
+ {GPIO_WLAN_SDIO_CMD, 0, GPIO_LEVEL_NONE, S3C_GPIO_PULL_NONE},
+ {GPIO_WLAN_SDIO_D0, 0, GPIO_LEVEL_NONE, S3C_GPIO_PULL_NONE},
+ {GPIO_WLAN_SDIO_D1, 0, GPIO_LEVEL_NONE, S3C_GPIO_PULL_NONE},
+ {GPIO_WLAN_SDIO_D2, 0, GPIO_LEVEL_NONE, S3C_GPIO_PULL_NONE},
+ {GPIO_WLAN_SDIO_D3, 0, GPIO_LEVEL_NONE, S3C_GPIO_PULL_NONE},
+};
+
+static int wlan_power_en(int onoff)
+{
+ if (onoff) {
+ s3c_gpio_cfgpin(GPIO_WLAN_HOST_WAKE,
+ S3C_GPIO_SFN(GPIO_WLAN_HOST_WAKE_AF));
+ s3c_gpio_setpull(GPIO_WLAN_HOST_WAKE, S3C_GPIO_PULL_DOWN);
+
+ s3c_gpio_cfgpin(GPIO_WLAN_WAKE,
+ S3C_GPIO_SFN(GPIO_WLAN_WAKE_AF));
+ s3c_gpio_setpull(GPIO_WLAN_WAKE, S3C_GPIO_PULL_NONE);
+ gpio_set_value(GPIO_WLAN_WAKE, GPIO_LEVEL_LOW);
+
+ s3c_gpio_cfgpin(GPIO_WLAN_nRST,
+ S3C_GPIO_SFN(GPIO_WLAN_nRST_AF));
+ s3c_gpio_setpull(GPIO_WLAN_nRST, S3C_GPIO_PULL_NONE);
+ gpio_set_value(GPIO_WLAN_nRST, GPIO_LEVEL_HIGH);
+ s3c_gpio_slp_cfgpin(GPIO_WLAN_nRST, S3C_GPIO_SLP_OUT1);
+ s3c_gpio_slp_setpull_updown(GPIO_WLAN_nRST, S3C_GPIO_PULL_NONE);
+
+ s3c_gpio_cfgpin(GPIO_WLAN_BT_EN, S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(GPIO_WLAN_BT_EN, S3C_GPIO_PULL_NONE);
+ gpio_set_value(GPIO_WLAN_BT_EN, GPIO_LEVEL_HIGH);
+ s3c_gpio_slp_cfgpin(GPIO_WLAN_BT_EN, S3C_GPIO_SLP_OUT1);
+ s3c_gpio_slp_setpull_updown(GPIO_WLAN_BT_EN,
+ S3C_GPIO_PULL_NONE);
+
+ msleep(200);
+ } else {
+ gpio_set_value(GPIO_WLAN_nRST, GPIO_LEVEL_LOW);
+ s3c_gpio_slp_cfgpin(GPIO_WLAN_nRST, S3C_GPIO_SLP_OUT0);
+ s3c_gpio_slp_setpull_updown(GPIO_WLAN_nRST, S3C_GPIO_PULL_NONE);
+
+ if (gpio_get_value(GPIO_BT_nRST) == 0) {
+ gpio_set_value(GPIO_WLAN_BT_EN, GPIO_LEVEL_LOW);
+ s3c_gpio_slp_cfgpin(GPIO_WLAN_BT_EN, S3C_GPIO_SLP_OUT0);
+ s3c_gpio_slp_setpull_updown(GPIO_WLAN_BT_EN,
+ S3C_GPIO_PULL_NONE);
+ }
+ }
+ return 0;
+}
+
+static int wlan_reset_en(int onoff)
+{
+ gpio_set_value(GPIO_WLAN_nRST,
+ onoff ? GPIO_LEVEL_HIGH : GPIO_LEVEL_LOW);
+ return 0;
+}
+
+static int wlan_carddetect_en(int onoff)
+{
+ u32 i;
+ u32 sdio;
+
+ if (onoff) {
+ for (i = 0; i < ARRAY_SIZE(wlan_sdio_on_table); i++) {
+ sdio = wlan_sdio_on_table[i][0];
+ s3c_gpio_cfgpin(sdio,
+ S3C_GPIO_SFN(wlan_sdio_on_table[i][1]));
+ s3c_gpio_setpull(sdio, wlan_sdio_on_table[i][3]);
+ if (wlan_sdio_on_table[i][2] != GPIO_LEVEL_NONE)
+ gpio_set_value(sdio, wlan_sdio_on_table[i][2]);
+ }
+ } else {
+ for (i = 0; i < ARRAY_SIZE(wlan_sdio_off_table); i++) {
+ sdio = wlan_sdio_off_table[i][0];
+ s3c_gpio_cfgpin(sdio,
+ S3C_GPIO_SFN(wlan_sdio_off_table[i][1]));
+ s3c_gpio_setpull(sdio, wlan_sdio_off_table[i][3]);
+ if (wlan_sdio_off_table[i][2] != GPIO_LEVEL_NONE)
+ gpio_set_value(sdio, wlan_sdio_off_table[i][2]);
+ }
+ }
+ udelay(5);
+
+ sdhci_s3c_force_presence_change(&s3c_device_hsmmc3);
+ msleep(500); /* wait for carddetect */
+ return 0;
+}
+
+static struct resource wifi_resources[] = {
+ [0] = {
+ .name = "bcm4329_wlan_irq",
+ .start = IRQ_EINT(20),
+ .end = IRQ_EINT(20),
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+ },
+};
+
+static struct wifi_mem_prealloc wifi_mem_array[PREALLOC_WLAN_SEC_NUM] = {
+ {NULL, (WLAN_SECTION_SIZE_0 + PREALLOC_WLAN_SECTION_HEADER)},
+ {NULL, (WLAN_SECTION_SIZE_1 + PREALLOC_WLAN_SECTION_HEADER)},
+ {NULL, (WLAN_SECTION_SIZE_2 + PREALLOC_WLAN_SECTION_HEADER)},
+ {NULL, (WLAN_SECTION_SIZE_3 + PREALLOC_WLAN_SECTION_HEADER)}
+};
+
+static void *herring_mem_prealloc(int section, unsigned long size)
+{
+ if (section == PREALLOC_WLAN_SEC_NUM)
+ return wlan_static_skb;
+
+ if ((section < 0) || (section > PREALLOC_WLAN_SEC_NUM))
+ return NULL;
+
+ if (wifi_mem_array[section].size < size)
+ return NULL;
+
+ return wifi_mem_array[section].mem_ptr;
+}
+
+int __init herring_init_wifi_mem(void)
+{
+ int i;
+ int j;
+
+ for (i = 0 ; i < WLAN_SKB_BUF_NUM ; i++) {
+ wlan_static_skb[i] = dev_alloc_skb(
+ ((i < (WLAN_SKB_BUF_NUM / 2)) ? 4096 : 8192));
+
+ if (!wlan_static_skb[i])
+ goto err_skb_alloc;
+ }
+
+ for (i = 0 ; i < PREALLOC_WLAN_SEC_NUM ; i++) {
+ wifi_mem_array[i].mem_ptr =
+ kmalloc(wifi_mem_array[i].size, GFP_KERNEL);
+
+ if (!wifi_mem_array[i].mem_ptr)
+ goto err_mem_alloc;
+ }
+ return 0;
+
+ err_mem_alloc:
+ pr_err("Failed to mem_alloc for WLAN\n");
+ for (j = 0 ; j < i ; j++)
+ kfree(wifi_mem_array[j].mem_ptr);
+
+ i = WLAN_SKB_BUF_NUM;
+
+ err_skb_alloc:
+ pr_err("Failed to skb_alloc for WLAN\n");
+ for (j = 0 ; j < i ; j++)
+ dev_kfree_skb(wlan_static_skb[j]);
+
+ return -ENOMEM;
+}
+
+/* Customized Locale table : OPTIONAL feature */
+#define WLC_CNTRY_BUF_SZ 4
+typedef struct cntry_locales_custom {
+ char iso_abbrev[WLC_CNTRY_BUF_SZ];
+ char custom_locale[WLC_CNTRY_BUF_SZ];
+ int custom_locale_rev;
+} cntry_locales_custom_t;
+
+static cntry_locales_custom_t herring_wlan_translate_custom_table[] = {
+/* Table should be filled out based on custom platform regulatory requirement */
+ {"", "XY", 4}, /* universal */
+ {"US", "US", 69}, /* input ISO "US" to : US regrev 69 */
+ {"CA", "US", 69}, /* input ISO "CA" to : US regrev 69 */
+ {"EU", "EU", 5}, /* European union countries */
+ {"AT", "EU", 5},
+ {"BE", "EU", 5},
+ {"BG", "EU", 5},
+ {"CY", "EU", 5},
+ {"CZ", "EU", 5},
+ {"DK", "EU", 5},
+ {"EE", "EU", 5},
+ {"FI", "EU", 5},
+ {"FR", "EU", 5},
+ {"DE", "EU", 5},
+ {"GR", "EU", 5},
+ {"HU", "EU", 5},
+ {"IE", "EU", 5},
+ {"IT", "EU", 5},
+ {"LV", "EU", 5},
+ {"LI", "EU", 5},
+ {"LT", "EU", 5},
+ {"LU", "EU", 5},
+ {"MT", "EU", 5},
+ {"NL", "EU", 5},
+ {"PL", "EU", 5},
+ {"PT", "EU", 5},
+ {"RO", "EU", 5},
+ {"SK", "EU", 5},
+ {"SI", "EU", 5},
+ {"ES", "EU", 5},
+ {"SE", "EU", 5},
+ {"GB", "EU", 5}, /* input ISO "GB" to : EU regrev 05 */
+ {"IL", "IL", 0},
+ {"CH", "CH", 0},
+ {"TR", "TR", 0},
+ {"NO", "NO", 0},
+ {"KR", "XY", 3},
+ {"AU", "XY", 3},
+ {"CN", "XY", 3}, /* input ISO "CN" to : XY regrev 03 */
+ {"TW", "XY", 3},
+ {"AR", "XY", 3},
+ {"MX", "XY", 3}
+};
+
+static void *herring_wlan_get_country_code(char *ccode)
+{
+ int size = ARRAY_SIZE(herring_wlan_translate_custom_table);
+ int i;
+
+ if (!ccode)
+ return NULL;
+
+ for (i = 0; i < size; i++)
+ if (strcmp(ccode, herring_wlan_translate_custom_table[i].iso_abbrev) == 0)
+ return &herring_wlan_translate_custom_table[i];
+ return &herring_wlan_translate_custom_table[0];
+}
+
+
+static struct wifi_platform_data wifi_pdata = {
+ .set_power = wlan_power_en,
+ .set_reset = wlan_reset_en,
+ .set_carddetect = wlan_carddetect_en,
+ .mem_prealloc = herring_mem_prealloc,
+ .get_country_code = herring_wlan_get_country_code,
+};
+
+static struct platform_device sec_device_wifi = {
+ .name = "bcm4329_wlan",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(wifi_resources),
+ .resource = wifi_resources,
+ .dev = {
+ .platform_data = &wifi_pdata,
+ },
+};
+
+static struct platform_device watchdog_device = {
+ .name = "watchdog",
+ .id = -1,
+};
+
+static struct platform_device *herring_devices[] __initdata = {
+ &watchdog_device,
+#ifdef CONFIG_FIQ_DEBUGGER
+ &s5pv210_device_fiqdbg_uart2,
+#endif
+ &s5p_device_onenand,
+#ifdef CONFIG_RTC_DRV_S3C
+ &s5p_device_rtc,
+#endif
+ &herring_input_device,
+
+ &s5pv210_device_iis0,
+ &s3c_device_wdt,
+
+#ifdef CONFIG_FB_S3C
+ &s3c_device_fb,
+#endif
+
+#ifdef CONFIG_VIDEO_MFC50
+ &s3c_device_mfc,
+#endif
+#ifdef CONFIG_S5P_ADC
+ &s3c_device_adc,
+#endif
+#ifdef CONFIG_VIDEO_FIMC
+ &s3c_device_fimc0,
+ &s3c_device_fimc1,
+ &s3c_device_fimc2,
+#endif
+
+#ifdef CONFIG_VIDEO_JPEG_V2
+ &s3c_device_jpeg,
+#endif
+
+ &s3c_device_g3d,
+ &s3c_device_lcd,
+
+#ifdef CONFIG_FB_S3C_TL2796
+ &s3c_device_spi_gpio,
+#endif
+ &sec_device_jack,
+
+ &s3c_device_i2c0,
+#if defined(CONFIG_S3C_DEV_I2C1)
+ &s3c_device_i2c1,
+#endif
+
+#if defined(CONFIG_S3C_DEV_I2C2)
+ &s3c_device_i2c2,
+#endif
+ &herring_i2c4_device,
+ &herring_i2c6_device,
+ &herring_i2c7_device,
+ &herring_i2c8_device, /* gyro sensor */
+ &herring_i2c9_device, /* max1704x:fuel_guage */
+ &herring_i2c11_device, /* optical sensor */
+ &herring_i2c12_device, /* magnetic sensor */
+ &herring_i2c14_device, /* nfc sensor */
+#if defined CONFIG_USB_S3C_OTG_HOST
+ &s3c_device_usb_otghcd,
+#endif
+#if defined CONFIG_USB_DWC_OTG
+ &s3c_device_usb_dwcotg,
+#endif
+#ifdef CONFIG_USB_GADGET
+ &s3c_device_usbgadget,
+#endif
+#ifdef CONFIG_USB_ANDROID
+ &s3c_device_android_usb,
+#ifdef CONFIG_USB_ANDROID_MASS_STORAGE
+ &s3c_device_usb_mass_storage,
+#endif
+#ifdef CONFIG_USB_ANDROID_RNDIS
+ &s3c_device_rndis,
+#endif
+#endif
+
+#ifdef CONFIG_S3C_DEV_HSMMC
+ &s3c_device_hsmmc0,
+#endif
+#ifdef CONFIG_S3C_DEV_HSMMC1
+ &s3c_device_hsmmc1,
+#endif
+#ifdef CONFIG_S3C_DEV_HSMMC2
+ &s3c_device_hsmmc2,
+#endif
+#ifdef CONFIG_S3C_DEV_HSMMC3
+ &s3c_device_hsmmc3,
+#endif
+
+ &sec_device_battery,
+ &herring_i2c10_device,
+
+#ifdef CONFIG_S5PV210_POWER_DOMAIN
+ &s5pv210_pd_audio,
+ &s5pv210_pd_cam,
+ &s5pv210_pd_tv,
+ &s5pv210_pd_lcd,
+ &s5pv210_pd_g3d,
+ &s5pv210_pd_mfc,
+#endif
+
+#ifdef CONFIG_ANDROID_PMEM
+ &pmem_device,
+ &pmem_gpu1_device,
+ &pmem_adsp_device,
+#endif
+
+#ifdef CONFIG_HAVE_PWM
+ &s3c_device_timer[0],
+ &s3c_device_timer[1],
+ &s3c_device_timer[2],
+ &s3c_device_timer[3],
+#endif
+
+#ifdef CONFIG_CPU_FREQ
+ &s5pv210_device_cpufreq,
+#endif
+
+ &sec_device_rfkill,
+ &sec_device_btsleep,
+ &ram_console_device,
+ &sec_device_wifi,
+ &samsung_asoc_dma,
+};
+
+unsigned int HWREV;
+EXPORT_SYMBOL(HWREV);
+
+static void __init herring_map_io(void)
+{
+ s5p_init_io(NULL, 0, S5P_VA_CHIPID);
+ s3c24xx_init_clocks(24000000);
+ s5pv210_gpiolib_init();
+ s3c24xx_init_uarts(herring_uartcfgs, ARRAY_SIZE(herring_uartcfgs));
+#ifndef CONFIG_S5P_HIGH_RES_TIMERS
+ s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
+#endif
+ s5p_reserve_bootmem(herring_media_devs,
+ ARRAY_SIZE(herring_media_devs), S5P_RANGE_MFC);
+#ifdef CONFIG_MTD_ONENAND
+ s5p_device_onenand.name = "s5pc110-onenand";
+#endif
+}
+
+unsigned int pm_debug_scratchpad;
+
+static unsigned int ram_console_start;
+static unsigned int ram_console_size;
+
+static void __init herring_fixup(struct machine_desc *desc,
+ struct tag *tags, char **cmdline,
+ struct meminfo *mi)
+{
+ mi->bank[0].start = 0x30000000;
+ mi->bank[0].size = 80 * SZ_1M;
+
+ mi->bank[1].start = 0x40000000;
+ mi->bank[1].size = 256 * SZ_1M;
+
+ mi->bank[2].start = 0x50000000;
+ /* 1M for ram_console buffer */
+ mi->bank[2].size = 127 * SZ_1M;
+ mi->nr_banks = 3;
+
+ ram_console_start = mi->bank[2].start + mi->bank[2].size;
+ ram_console_size = SZ_1M - SZ_4K;
+
+ pm_debug_scratchpad = ram_console_start + ram_console_size;
+}
+
+/* this function are used to detect s5pc110 chip version temporally */
+int s5pc110_version ;
+
+void _hw_version_check(void)
+{
+ void __iomem *phy_address ;
+ int temp;
+
+ phy_address = ioremap(0x40, 1);
+
+ temp = __raw_readl(phy_address);
+
+ if (temp == 0xE59F010C)
+ s5pc110_version = 0;
+ else
+ s5pc110_version = 1;
+
+ printk(KERN_INFO "S5PC110 Hardware version : EVT%d\n",
+ s5pc110_version);
+
+ iounmap(phy_address);
+}
+
+/*
+ * Temporally used
+ * return value 0 -> EVT 0
+ * value 1 -> evt 1
+ */
+
+int hw_version_check(void)
+{
+ return s5pc110_version ;
+}
+EXPORT_SYMBOL(hw_version_check);
+
+static void herring_init_gpio(void)
+{
+ s3c_config_gpio_table();
+ s3c_config_sleep_gpio_table(ARRAY_SIZE(herring_sleep_gpio_table),
+ herring_sleep_gpio_table);
+ if (herring_is_cdma_wimax_dev())
+ s3c_config_sleep_gpio_table(
+ ARRAY_SIZE(herring_cdma_wimax_sleep_gpio_table),
+ herring_cdma_wimax_sleep_gpio_table);
+
+}
+
+static void __init fsa9480_gpio_init(void)
+{
+ if (herring_is_cdma_wimax_dev()) {
+ s3c_gpio_cfgpin(GPIO_USB_HS_SEL, S3C_GPIO_OUTPUT);
+ gpio_set_value(GPIO_USB_HS_SEL, 1);
+ } else {
+ s3c_gpio_cfgpin(GPIO_USB_SEL, S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(GPIO_USB_SEL, S3C_GPIO_PULL_NONE);
+ }
+
+ s3c_gpio_cfgpin(GPIO_UART_SEL, S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(GPIO_UART_SEL, S3C_GPIO_PULL_NONE);
+
+ s3c_gpio_cfgpin(GPIO_JACK_nINT, S3C_GPIO_SFN(0xf));
+ s3c_gpio_setpull(GPIO_JACK_nINT, S3C_GPIO_PULL_NONE);
+}
+
+static void __init setup_ram_console_mem(void)
+{
+ ram_console_resource[0].start = ram_console_start;
+ ram_console_resource[0].end = ram_console_start + ram_console_size - 1;
+}
+
+static void __init sound_init(void)
+{
+ u32 reg;
+
+ reg = __raw_readl(S5P_OTHERS);
+ reg &= ~(0x3 << 8);
+ reg |= 3 << 8;
+ __raw_writel(reg, S5P_OTHERS);
+
+ reg = __raw_readl(S5P_CLK_OUT);
+ reg &= ~(0x1f << 12);
+ reg |= 19 << 12;
+ __raw_writel(reg, S5P_CLK_OUT);
+
+ reg = __raw_readl(S5P_CLK_OUT);
+ reg &= ~0x1;
+ reg |= 0x1;
+ __raw_writel(reg, S5P_CLK_OUT);
+
+ gpio_request(GPIO_MICBIAS_EN, "micbias_enable");
+}
+
+static s8 accel_rotation_wimax_rev0[9] = {
+ 0, -1, 0,
+ -1, 0, 0,
+ 0, 0, -1,
+};
+
+static void __init accel_init(void)
+{
+ if (herring_is_cdma_wimax_rev0())
+ kr3dm_data.rotation = accel_rotation_wimax_rev0;
+}
+
+static bool console_flushed;
+
+static void flush_console(void)
+{
+ if (console_flushed)
+ return;
+
+ console_flushed = true;
+
+ printk("\n");
+ pr_emerg("Restarting %s\n", linux_banner);
+ if (!is_console_locked())
+ return;
+
+ mdelay(50);
+
+ local_irq_disable();
+ if (!console_trylock())
+ pr_emerg("flush_console: console was locked! busting!\n");
+ else
+ pr_emerg("flush_console: console was locked!\n");
+ console_unlock();
+}
+
+static void herring_pm_restart(char mode, const char *cmd)
+{
+ flush_console();
+
+ /* On a normal reboot, INFORM6 will contain a small integer
+ * reason code from the notifier hook. On a panic, it will
+ * contain the 0xee we set at boot. Write 0xbb to differentiate
+ * a watchdog-timeout-and-reboot (0xee) from a controlled reboot
+ * (0xbb)
+ */
+ if (__raw_readl(S5P_INFORM6) == 0xee)
+ __raw_writel(0xbb, S5P_INFORM6);
+
+ arm_machine_restart(mode, cmd);
+}
+
+static void __init herring_machine_init(void)
+{
+ arm_pm_restart = herring_pm_restart;
+
+ setup_ram_console_mem();
+ platform_add_devices(herring_devices, ARRAY_SIZE(herring_devices));
+ if (!herring_is_tft_dev())
+ platform_device_register(&herring_i2c5_device);
+
+ /* Find out S5PC110 chip version */
+ _hw_version_check();
+
+ pm_power_off = herring_power_off ;
+
+ s3c_gpio_cfgpin(GPIO_HWREV_MODE0, S3C_GPIO_INPUT);
+ s3c_gpio_setpull(GPIO_HWREV_MODE0, S3C_GPIO_PULL_NONE);
+ s3c_gpio_cfgpin(GPIO_HWREV_MODE1, S3C_GPIO_INPUT);
+ s3c_gpio_setpull(GPIO_HWREV_MODE1, S3C_GPIO_PULL_NONE);
+ s3c_gpio_cfgpin(GPIO_HWREV_MODE2, S3C_GPIO_INPUT);
+ s3c_gpio_setpull(GPIO_HWREV_MODE2, S3C_GPIO_PULL_NONE);
+ HWREV = gpio_get_value(GPIO_HWREV_MODE0);
+ HWREV = HWREV | (gpio_get_value(GPIO_HWREV_MODE1) << 1);
+ HWREV = HWREV | (gpio_get_value(GPIO_HWREV_MODE2) << 2);
+ s3c_gpio_cfgpin(GPIO_HWREV_MODE3, S3C_GPIO_INPUT);
+ s3c_gpio_setpull(GPIO_HWREV_MODE3, S3C_GPIO_PULL_NONE);
+ HWREV = HWREV | (gpio_get_value(GPIO_HWREV_MODE3) << 3);
+ printk(KERN_INFO "HWREV is 0x%x\n", HWREV);
+
+ /*initialise the gpio's*/
+ herring_init_gpio();
+
+#ifdef CONFIG_ANDROID_PMEM
+ android_pmem_set_platdata();
+#endif
+
+ /* headset/earjack detection */
+ if (system_rev >= 0x09)
+ gpio_request(GPIO_EAR_MICBIAS_EN, "ear_micbias_enable");
+
+ gpio_request(GPIO_TOUCH_EN, "touch en");
+
+ /* i2c */
+ s3c_i2c0_set_platdata(NULL);
+#ifdef CONFIG_S3C_DEV_I2C1
+ s3c_i2c1_set_platdata(NULL);
+#endif
+
+#ifdef CONFIG_S3C_DEV_I2C2
+ s3c_i2c2_set_platdata(NULL);
+#endif
+ k3g_irq_init();
+ set_adc_table();
+ accel_init();
+ /* H/W I2C lines */
+ if (system_rev >= 0x05) {
+ /* gyro sensor */
+ if (herring_is_cdma_wimax_dev() && herring_is_cdma_wimax_rev0())
+ i2c_register_board_info(5, i2c_devs0,
+ ARRAY_SIZE(i2c_devs0));
+ else
+ i2c_register_board_info(0, i2c_devs0,
+ ARRAY_SIZE(i2c_devs0));
+ /* magnetic and accel sensor */
+ i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
+ }
+ mxt224_init();
+ i2c_register_board_info(2, i2c_devs2, ARRAY_SIZE(i2c_devs2));
+
+ /* wm8994 codec */
+ sound_init();
+ i2c_register_board_info(4, i2c_devs4, ARRAY_SIZE(i2c_devs4));
+ /* accel sensor for rev04 */
+ if (system_rev == 0x04)
+ i2c_register_board_info(5, i2c_devs5, ARRAY_SIZE(i2c_devs5));
+
+ if (herring_is_cdma_wimax_dev()) {
+ struct max8998_platform_data *pdata =
+ (struct max8998_platform_data *)&max8998_pdata;
+ pdata->num_regulators =
+ ARRAY_SIZE(herring_cdma_wimax_regulators);
+ pdata->regulators = herring_cdma_wimax_regulators;
+ }
+
+ i2c_register_board_info(6, i2c_devs6, ARRAY_SIZE(i2c_devs6));
+ if (!herring_is_tft_dev()) {
+ /* Touch Key */
+ touch_keypad_gpio_init();
+ i2c_register_board_info(10, i2c_devs10, ARRAY_SIZE(i2c_devs10));
+ } else {
+ herring_virtual_keys_init();
+ }
+ /* FSA9480 */
+ fsa9480_gpio_init();
+ i2c_register_board_info(7, i2c_devs7, ARRAY_SIZE(i2c_devs7));
+
+ /* gyro sensor for rev04 */
+ if (system_rev == 0x04)
+ i2c_register_board_info(8, i2c_devs8, ARRAY_SIZE(i2c_devs8));
+
+ i2c_register_board_info(9, i2c_devs9, ARRAY_SIZE(i2c_devs9));
+ /* optical sensor */
+ gp2a_gpio_init();
+ i2c_register_board_info(11, i2c_devs11, ARRAY_SIZE(i2c_devs11));
+ /* magnetic sensor for rev04 */
+ if (system_rev == 0x04)
+ i2c_register_board_info(12, i2c_devs12, ARRAY_SIZE(i2c_devs12));
+
+ /* nfc sensor */
+ i2c_register_board_info(14, i2c_devs14, ARRAY_SIZE(i2c_devs14));
+
+ /* max8893 wimax PMIC */
+ if (herring_is_cdma_wimax_dev()) {
+ platform_device_register(&herring_i2c15_device);
+ i2c_register_board_info(15, i2c_devs15, ARRAY_SIZE(i2c_devs15));
+ }
+
+ if (!herring_is_tft_dev()) {
+ is_device_lcd = false;
+ spi_register_board_info(spi_board_info,
+ ARRAY_SIZE(spi_board_info));
+ s3cfb_set_platdata(&tl2796_data);
+ } else {
+ is_device_lcd = true;
+ switch (lcd_type) {
+ case 1:
+ spi_register_board_info(spi_board_info_hydis,
+ ARRAY_SIZE(spi_board_info_hydis));
+ s3cfb_set_platdata(&nt35580_data);
+ break;
+ case 2:
+ spi_register_board_info(spi_board_info_hitachi,
+ ARRAY_SIZE(spi_board_info_hitachi));
+ s3cfb_set_platdata(&r61408_data);
+ break;
+ default:
+ spi_register_board_info(spi_board_info_sony,
+ ARRAY_SIZE(spi_board_info_sony));
+ s3cfb_set_platdata(&nt35580_data);
+ break;
+ }
+ }
+
+#if defined(CONFIG_S5P_ADC)
+ s3c_adc_set_platdata(&s3c_adc_platform);
+#endif
+
+#if defined(CONFIG_PM)
+ s3c_pm_init();
+#endif
+
+ s5ka3dfx_request_gpio();
+
+ s5k4ecgx_init();
+
+#ifdef CONFIG_VIDEO_FIMC
+ /* fimc */
+ s3c_fimc0_set_platdata(&fimc_plat_lsi);
+ s3c_fimc1_set_platdata(&fimc_plat_lsi);
+ s3c_fimc2_set_platdata(&fimc_plat_lsi);
+#endif
+
+#ifdef CONFIG_VIDEO_JPEG_V2
+ s3c_jpeg_set_platdata(&jpeg_plat);
+#endif
+
+#ifdef CONFIG_VIDEO_MFC50
+ /* mfc */
+ s3c_mfc_set_platdata(NULL);
+#endif
+
+#ifdef CONFIG_S3C_DEV_HSMMC
+ s5pv210_default_sdhci0();
+#endif
+#ifdef CONFIG_S3C_DEV_HSMMC1
+ s5pv210_default_sdhci1();
+#endif
+#ifdef CONFIG_S3C_DEV_HSMMC2
+ s5pv210_default_sdhci2();
+#endif
+#ifdef CONFIG_S3C_DEV_HSMMC3
+ s5pv210_default_sdhci3();
+#endif
+#ifdef CONFIG_S5PV210_SETUP_SDHCI
+ s3c_sdhci_set_platdata();
+#endif
+
+#ifdef CONFIG_CPU_FREQ
+ s5pv210_cpufreq_set_platdata(&smdkc110_cpufreq_plat);
+#endif
+
+ regulator_has_full_constraints();
+
+ register_reboot_notifier(&herring_reboot_notifier);
+
+ herring_switch_init();
+
+ gps_gpio_init();
+
+ uart_switch_init();
+
+ herring_init_wifi_mem();
+
+ if (herring_is_cdma_wimax_dev())
+ platform_device_register(&s3c_device_cmc732);
+
+ /* write something into the INFORM6 register that we can use to
+ * differentiate an unclear reboot from a clean reboot (which
+ * writes a small integer code to INFORM6).
+ */
+ __raw_writel(0xee, S5P_INFORM6);
+}
+
+#ifdef CONFIG_USB_SUPPORT
+/* Initializes OTG Phy. */
+void otg_phy_init(void)
+{
+ /* USB PHY0 Enable */
+ writel(readl(S5P_USB_PHY_CONTROL) | (0x1<<0),
+ S5P_USB_PHY_CONTROL);
+ writel((readl(S3C_USBOTG_PHYPWR) & ~(0x3<<3) & ~(0x1<<0)) | (0x1<<5),
+ S3C_USBOTG_PHYPWR);
+ writel((readl(S3C_USBOTG_PHYCLK) & ~(0x5<<2)) | (0x3<<0),
+ S3C_USBOTG_PHYCLK);
+ writel((readl(S3C_USBOTG_RSTCON) & ~(0x3<<1)) | (0x1<<0),
+ S3C_USBOTG_RSTCON);
+ mdelay(1);
+ writel(readl(S3C_USBOTG_RSTCON) & ~(0x7<<0),
+ S3C_USBOTG_RSTCON);
+ mdelay(1);
+
+ /* rising/falling time */
+ writel(readl(S3C_USBOTG_PHYTUNE) | (0x1<<20),
+ S3C_USBOTG_PHYTUNE);
+
+ /* set DC level as 0xf (24%) */
+ writel(readl(S3C_USBOTG_PHYTUNE) | 0xf, S3C_USBOTG_PHYTUNE);
+}
+EXPORT_SYMBOL(otg_phy_init);
+
+/* USB Control request data struct must be located here for DMA transfer */
+struct usb_ctrlrequest usb_ctrl __attribute__((aligned(64)));
+
+/* OTG PHY Power Off */
+void otg_phy_off(void)
+{
+ writel(readl(S3C_USBOTG_PHYPWR) | (0x3<<3),
+ S3C_USBOTG_PHYPWR);
+ writel(readl(S5P_USB_PHY_CONTROL) & ~(1<<0),
+ S5P_USB_PHY_CONTROL);
+}
+EXPORT_SYMBOL(otg_phy_off);
+
+void usb_host_phy_init(void)
+{
+ struct clk *otg_clk;
+
+ otg_clk = clk_get(NULL, "otg");
+ clk_enable(otg_clk);
+
+ if (readl(S5P_USB_PHY_CONTROL) & (0x1<<1))
+ return;
+
+ __raw_writel(__raw_readl(S5P_USB_PHY_CONTROL) | (0x1<<1),
+ S5P_USB_PHY_CONTROL);
+ __raw_writel((__raw_readl(S3C_USBOTG_PHYPWR)
+ & ~(0x1<<7) & ~(0x1<<6)) | (0x1<<8) | (0x1<<5),
+ S3C_USBOTG_PHYPWR);
+ __raw_writel((__raw_readl(S3C_USBOTG_PHYCLK) & ~(0x1<<7)) | (0x3<<0),
+ S3C_USBOTG_PHYCLK);
+ __raw_writel((__raw_readl(S3C_USBOTG_RSTCON)) | (0x1<<4) | (0x1<<3),
+ S3C_USBOTG_RSTCON);
+ __raw_writel(__raw_readl(S3C_USBOTG_RSTCON) & ~(0x1<<4) & ~(0x1<<3),
+ S3C_USBOTG_RSTCON);
+}
+EXPORT_SYMBOL(usb_host_phy_init);
+
+void usb_host_phy_off(void)
+{
+ __raw_writel(__raw_readl(S3C_USBOTG_PHYPWR) | (0x1<<7)|(0x1<<6),
+ S3C_USBOTG_PHYPWR);
+ __raw_writel(__raw_readl(S5P_USB_PHY_CONTROL) & ~(1<<1),
+ S5P_USB_PHY_CONTROL);
+}
+EXPORT_SYMBOL(usb_host_phy_off);
+#endif
+
+#if defined CONFIG_USB_S3C_OTG_HOST || defined CONFIG_USB_DWC_OTG
+
+/* Initializes OTG Phy */
+void otg_host_phy_init(void)
+{
+ __raw_writel(__raw_readl(S5P_USB_PHY_CONTROL)
+ |(0x1<<0), S5P_USB_PHY_CONTROL); /*USB PHY0 Enable */
+// from galaxy tab otg host:
+ __raw_writel((__raw_readl(S3C_USBOTG_PHYPWR)
+ &~(0x3<<3)&~(0x1<<0))|(0x1<<5), S3C_USBOTG_PHYPWR);
+// from galaxy s2 otg host:
+// __raw_writel((__raw_readl(S3C_USBOTG_PHYPWR)
+// &~(0x7<<3)&~(0x1<<0)), S3C_USBOTG_PHYPWR);
+ __raw_writel((__raw_readl(S3C_USBOTG_PHYCLK)
+ &~(0x1<<4))|(0x7<<0), S3C_USBOTG_PHYCLK);
+
+ __raw_writel((__raw_readl(S3C_USBOTG_RSTCON)
+ &~(0x3<<1))|(0x1<<0), S3C_USBOTG_RSTCON);
+ mdelay(1);
+ __raw_writel((__raw_readl(S3C_USBOTG_RSTCON)
+ &~(0x7<<0)), S3C_USBOTG_RSTCON);
+ mdelay(1);
+
+ __raw_writel((__raw_readl(S3C_UDC_OTG_GUSBCFG)
+ |(0x3<<8)), S3C_UDC_OTG_GUSBCFG);
+
+// smb136_set_otg_mode(1);
+
+ printk("otg_host_phy_int : USBPHYCTL=0x%x,PHYPWR=0x%x,PHYCLK=0x%x,USBCFG=0x%x\n",
+ readl(S5P_USB_PHY_CONTROL),
+ readl(S3C_USBOTG_PHYPWR),
+ readl(S3C_USBOTG_PHYCLK),
+ readl(S3C_UDC_OTG_GUSBCFG)
+ );
+}
+EXPORT_SYMBOL(otg_host_phy_init);
+#endif
+
+MACHINE_START(HERRING, "herring")
+ .boot_params = S5P_PA_SDRAM + 0x100,
+ .fixup = herring_fixup,
+ .init_irq = s5pv210_init_irq,
+ .map_io = herring_map_io,
+ .init_machine = herring_machine_init,
+#ifdef CONFIG_S5P_HIGH_RES_TIMERS
+ .timer = &s5p_systimer,
+#else
+ .timer = &s5p_timer,
+#endif
+MACHINE_END
+
+void s3c_setup_uart_cfg_gpio(unsigned char port)
+{
+ switch (port) {
+ case 0:
+ s3c_gpio_cfgpin(GPIO_BT_RXD, S3C_GPIO_SFN(GPIO_BT_RXD_AF));
+ s3c_gpio_setpull(GPIO_BT_RXD, S3C_GPIO_PULL_NONE);
+ s3c_gpio_cfgpin(GPIO_BT_TXD, S3C_GPIO_SFN(GPIO_BT_TXD_AF));
+ s3c_gpio_setpull(GPIO_BT_TXD, S3C_GPIO_PULL_NONE);
+ s3c_gpio_cfgpin(GPIO_BT_CTS, S3C_GPIO_SFN(GPIO_BT_CTS_AF));
+ s3c_gpio_setpull(GPIO_BT_CTS, S3C_GPIO_PULL_NONE);
+ s3c_gpio_cfgpin(GPIO_BT_RTS, S3C_GPIO_SFN(GPIO_BT_RTS_AF));
+ s3c_gpio_setpull(GPIO_BT_RTS, S3C_GPIO_PULL_NONE);
+ s3c_gpio_slp_cfgpin(GPIO_BT_RXD, S3C_GPIO_SLP_PREV);
+ s3c_gpio_slp_setpull_updown(GPIO_BT_RXD, S3C_GPIO_PULL_NONE);
+ s3c_gpio_slp_cfgpin(GPIO_BT_TXD, S3C_GPIO_SLP_PREV);
+ s3c_gpio_slp_setpull_updown(GPIO_BT_TXD, S3C_GPIO_PULL_NONE);
+ s3c_gpio_slp_cfgpin(GPIO_BT_CTS, S3C_GPIO_SLP_PREV);
+ s3c_gpio_slp_setpull_updown(GPIO_BT_CTS, S3C_GPIO_PULL_NONE);
+ s3c_gpio_slp_cfgpin(GPIO_BT_RTS, S3C_GPIO_SLP_PREV);
+ s3c_gpio_slp_setpull_updown(GPIO_BT_RTS, S3C_GPIO_PULL_NONE);
+ break;
+ case 1:
+ s3c_gpio_cfgpin(GPIO_GPS_RXD, S3C_GPIO_SFN(GPIO_GPS_RXD_AF));
+ s3c_gpio_setpull(GPIO_GPS_RXD, S3C_GPIO_PULL_UP);
+ s3c_gpio_cfgpin(GPIO_GPS_TXD, S3C_GPIO_SFN(GPIO_GPS_TXD_AF));
+ s3c_gpio_setpull(GPIO_GPS_TXD, S3C_GPIO_PULL_NONE);
+ s3c_gpio_cfgpin(GPIO_GPS_CTS, S3C_GPIO_SFN(GPIO_GPS_CTS_AF));
+ s3c_gpio_setpull(GPIO_GPS_CTS, S3C_GPIO_PULL_NONE);
+ s3c_gpio_cfgpin(GPIO_GPS_RTS, S3C_GPIO_SFN(GPIO_GPS_RTS_AF));
+ s3c_gpio_setpull(GPIO_GPS_RTS, S3C_GPIO_PULL_NONE);
+ break;
+ case 2:
+ s3c_gpio_cfgpin(GPIO_AP_RXD, S3C_GPIO_SFN(GPIO_AP_RXD_AF));
+ s3c_gpio_setpull(GPIO_AP_RXD, S3C_GPIO_PULL_NONE);
+ s3c_gpio_cfgpin(GPIO_AP_TXD, S3C_GPIO_SFN(GPIO_AP_TXD_AF));
+ s3c_gpio_setpull(GPIO_AP_TXD, S3C_GPIO_PULL_NONE);
+ break;
+ case 3:
+ s3c_gpio_cfgpin(GPIO_FLM_RXD, S3C_GPIO_SFN(GPIO_FLM_RXD_AF));
+ s3c_gpio_setpull(GPIO_FLM_RXD, S3C_GPIO_PULL_NONE);
+ s3c_gpio_cfgpin(GPIO_FLM_TXD, S3C_GPIO_SFN(GPIO_FLM_TXD_AF));
+ s3c_gpio_setpull(GPIO_FLM_TXD, S3C_GPIO_PULL_NONE);
+ break;
+ default:
+ break;
+ }
+}
+EXPORT_SYMBOL(s3c_setup_uart_cfg_gpio);
diff --git a/arch/arm/mach-s5pv210/pm.c b/arch/arm/mach-s5pv210/pm.c
index 24febae..39f3270 100644..100755
--- a/arch/arm/mach-s5pv210/pm.c
+++ b/arch/arm/mach-s5pv210/pm.c
@@ -25,8 +25,16 @@
#include <mach/regs-irq.h>
#include <mach/regs-clock.h>
+#include <mach/regs-mem.h>
+#include <mach/power-domain.h>
+
+static struct sleep_save core_save[] = {
+ /* PLL Control */
+ SAVE_ITEM(S5P_APLL_CON),
+ SAVE_ITEM(S5P_MPLL_CON),
+ SAVE_ITEM(S5P_EPLL_CON),
+ SAVE_ITEM(S5P_VPLL_CON),
-static struct sleep_save s5pv210_core_save[] = {
/* Clock source */
SAVE_ITEM(S5P_CLK_SRC0),
SAVE_ITEM(S5P_CLK_SRC1),
@@ -72,7 +80,7 @@ static struct sleep_save s5pv210_core_save[] = {
/* Clock Blcok and Bus gate */
SAVE_ITEM(S5P_CLKGATE_BLOCK),
- SAVE_ITEM(S5P_CLKGATE_BUS0),
+ SAVE_ITEM(S5P_CLKGATE_IP5),
/* Clock ETC */
SAVE_ITEM(S5P_CLK_OUT),
@@ -115,10 +123,6 @@ static void s5pv210_pm_prepare(void)
/* ensure at least INFORM0 has the resume address */
__raw_writel(virt_to_phys(s3c_cpu_resume), S5P_INFORM0);
- tmp = __raw_readl(S5P_SLEEP_CFG);
- tmp &= ~(S5P_SLEEP_CFG_OSC_EN | S5P_SLEEP_CFG_USBOSC_EN);
- __raw_writel(tmp, S5P_SLEEP_CFG);
-
/* WFI for SLEEP mode configuration by SYSCON */
tmp = __raw_readl(S5P_PWR_CFG);
tmp &= S5P_CFG_WFI_CLEAN;
@@ -130,7 +134,12 @@ static void s5pv210_pm_prepare(void)
tmp |= S5P_OTHER_SYSC_INTOFF;
__raw_writel(tmp, S5P_OTHERS);
- s3c_pm_do_save(s5pv210_core_save, ARRAY_SIZE(s5pv210_core_save));
+ __raw_writel(0xffffffff, (VA_VIC0 + VIC_INT_ENABLE_CLEAR));
+ __raw_writel(0xffffffff, (VA_VIC1 + VIC_INT_ENABLE_CLEAR));
+ __raw_writel(0xffffffff, (VA_VIC2 + VIC_INT_ENABLE_CLEAR));
+ __raw_writel(0xffffffff, (VA_VIC3 + VIC_INT_ENABLE_CLEAR));
+
+ s3c_pm_do_save(core_save, ARRAY_SIZE(core_save));
}
static int s5pv210_pm_add(struct sys_device *sysdev)
@@ -153,14 +162,29 @@ arch_initcall(s5pv210_pm_drvinit);
static void s5pv210_pm_resume(void)
{
- u32 tmp;
+ u32 tmp, audiodomain_on;
+
+ tmp = __raw_readl(S5P_NORMAL_CFG);
+ if (tmp & S5PV210_PD_AUDIO)
+ audiodomain_on = 0;
+ else {
+ tmp |= S5PV210_PD_AUDIO;
+ __raw_writel(tmp , S5P_NORMAL_CFG);
+ audiodomain_on = 1;
+ }
tmp = __raw_readl(S5P_OTHERS);
tmp |= (S5P_OTHERS_RET_IO | S5P_OTHERS_RET_CF |\
S5P_OTHERS_RET_MMC | S5P_OTHERS_RET_UART);
__raw_writel(tmp , S5P_OTHERS);
- s3c_pm_do_restore_core(s5pv210_core_save, ARRAY_SIZE(s5pv210_core_save));
+ if (audiodomain_on) {
+ tmp = __raw_readl(S5P_NORMAL_CFG);
+ tmp &= ~S5PV210_PD_AUDIO;
+ __raw_writel(tmp , S5P_NORMAL_CFG);
+ }
+
+ s3c_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
}
static struct syscore_ops s5pv210_pm_syscore_ops = {
diff --git a/arch/arm/mach-s5pv210/power-domain.c b/arch/arm/mach-s5pv210/power-domain.c
new file mode 100644
index 0000000..683901c
--- /dev/null
+++ b/arch/arm/mach-s5pv210/power-domain.c
@@ -0,0 +1,566 @@
+/* linux/arch/arm/mach-s5pv210/power-domain.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * S5PV210 - Power domain support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/mutex.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <mach/power-domain.h>
+
+#include <mach/regs-clock.h>
+#include <plat/devs.h>
+
+struct s5pv210_pd_data {
+ struct regulator_desc desc;
+ struct regulator_dev *dev;
+ int microvolts;
+ unsigned startup_delay;
+ struct clk_should_be_running *clk_run;
+ int ctrlbit;
+};
+
+struct clk_should_be_running {
+ const char *clk_name;
+ struct device *dev;
+};
+static spinlock_t pd_lock;
+
+static struct regulator_consumer_supply s5pv210_pd_audio_supply[] = {
+ REGULATOR_SUPPLY("pd", "samsung-i2s.0"),
+};
+
+static struct regulator_consumer_supply s5pv210_pd_cam_supply[] = {
+ REGULATOR_SUPPLY("pd", "s3c-fimc.0"),
+ REGULATOR_SUPPLY("pd", "s3c-fimc.1"),
+ REGULATOR_SUPPLY("pd", "s3c-fimc.2"),
+ REGULATOR_SUPPLY("pd", "s3c-jpg"),
+ REGULATOR_SUPPLY("pd", "s3c-csis"),
+ REGULATOR_SUPPLY("pd", "s5p-rotator"),
+};
+
+static struct regulator_consumer_supply s5pv210_pd_tv_supply[] = {
+ REGULATOR_SUPPLY("pd", "s5p-tvout"),
+};
+
+static struct regulator_consumer_supply s5pv210_pd_lcd_supply[] = {
+ REGULATOR_SUPPLY("pd", "s3cfb"),
+};
+
+static struct regulator_consumer_supply s5pv210_pd_g3d_supply[] = {
+ REGULATOR_SUPPLY("pd", "pvrsrvkm"),
+};
+
+static struct regulator_consumer_supply s5pv210_pd_mfc_supply[] = {
+ REGULATOR_SUPPLY("pd", "s3c-mfc"),
+};
+
+static struct regulator_init_data s5pv210_pd_audio_data = {
+ .constraints = {
+ .valid_modes_mask = REGULATOR_MODE_NORMAL,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(s5pv210_pd_audio_supply),
+ .consumer_supplies = s5pv210_pd_audio_supply,
+};
+
+static struct regulator_init_data s5pv210_pd_cam_data = {
+ .constraints = {
+ .valid_modes_mask = REGULATOR_MODE_NORMAL,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(s5pv210_pd_cam_supply),
+ .consumer_supplies = s5pv210_pd_cam_supply,
+};
+
+static struct regulator_init_data s5pv210_pd_tv_data = {
+ .constraints = {
+ .valid_modes_mask = REGULATOR_MODE_NORMAL,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(s5pv210_pd_tv_supply),
+ .consumer_supplies = s5pv210_pd_tv_supply,
+};
+
+static struct regulator_init_data s5pv210_pd_lcd_data = {
+ .constraints = {
+ .valid_modes_mask = REGULATOR_MODE_NORMAL,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(s5pv210_pd_lcd_supply),
+ .consumer_supplies = s5pv210_pd_lcd_supply,
+};
+
+static struct regulator_init_data s5pv210_pd_g3d_data = {
+ .constraints = {
+ .valid_modes_mask = REGULATOR_MODE_NORMAL,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(s5pv210_pd_g3d_supply),
+ .consumer_supplies = s5pv210_pd_g3d_supply,
+};
+
+static struct regulator_init_data s5pv210_pd_mfc_data = {
+ .constraints = {
+ .valid_modes_mask = REGULATOR_MODE_NORMAL,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(s5pv210_pd_mfc_supply),
+ .consumer_supplies = s5pv210_pd_mfc_supply,
+};
+
+struct clk_should_be_running s5pv210_pd_audio_clk[] = {
+ {
+ .clk_name = "i2scdclk",
+ .dev = &s5pv210_device_iis0.dev,
+ }, {
+ /* end of the clock array */
+ },
+};
+
+struct clk_should_be_running s5pv210_pd_cam_clk[] = {
+ {
+ .clk_name = "fimc",
+ .dev = &s3c_device_fimc0.dev,
+ }, {
+ .clk_name = "fimc",
+ .dev = &s3c_device_fimc1.dev,
+ }, {
+ .clk_name = "fimc",
+ .dev = &s3c_device_fimc2.dev,
+ }, {
+ .clk_name = "sclk_csis",
+ .dev = &s5p_device_mipi_csis0.dev,
+ }, {
+ .clk_name = "jpeg",
+ .dev = &s3c_device_jpeg.dev,
+ }, {
+ .clk_name = "rot",
+ .dev = &s5p_device_rotator.dev,
+ }, {
+ /* end of the clock array */
+ },
+};
+
+struct clk_should_be_running s5pv210_pd_tv_clk[] = {
+ {
+ .clk_name = "vp",
+ .dev = &s5p_device_tvout.dev,
+ }, {
+ .clk_name = "mixer",
+ .dev = &s5p_device_tvout.dev,
+ }, {
+ .clk_name = "tvenc",
+ .dev = &s5p_device_tvout.dev,
+ }, {
+ .clk_name = "hdmi",
+ .dev = &s5p_device_tvout.dev,
+ }, {
+ /* end of the clock array */
+ },
+};
+
+struct clk_should_be_running s5pv210_pd_lcd_clk[] = {
+ {
+ .clk_name = "lcd",
+ .dev = &s3c_device_fb.dev,
+ }, {
+ .clk_name = "dsim",
+ .dev = &s3c_device_fb.dev,
+ }, {
+ .clk_name = "sclk_fimg2d",
+ .dev = &s3c_device_fb.dev,
+ }, {
+ /* end of the clock array */
+ },
+};
+
+struct clk_should_be_running s5pv210_pd_g3d_clk[] = {
+ {
+ .clk_name = "sclk",
+ .dev = &s3c_device_g3d.dev,
+ }, {
+ /* end of the clock array */
+ },
+};
+
+struct clk_should_be_running s5pv210_pd_mfc_clk[] = {
+ {
+ .clk_name = "mfc",
+ .dev = &s3c_device_mfc.dev,
+ }, {
+ /* end of the clock array */
+ },
+};
+
+static struct s5pv210_pd_config s5pv210_pd_audio_pdata = {
+ .supply_name = "pd_audio_supply",
+ .microvolts = 5000000,
+ .init_data = &s5pv210_pd_audio_data,
+ .clk_run = s5pv210_pd_audio_clk,
+ .ctrlbit = S5PV210_PD_AUDIO,
+};
+
+static struct s5pv210_pd_config s5pv210_pd_cam_pdata = {
+ .supply_name = "pd_cam_supply",
+ .microvolts = 5000000,
+ .init_data = &s5pv210_pd_cam_data,
+ .clk_run = s5pv210_pd_cam_clk,
+ .ctrlbit = S5PV210_PD_CAM,
+};
+
+static struct s5pv210_pd_config s5pv210_pd_tv_pdata = {
+ .supply_name = "pd_tv_supply",
+ .microvolts = 5000000,
+ .init_data = &s5pv210_pd_tv_data,
+ .clk_run = s5pv210_pd_tv_clk,
+ .ctrlbit = S5PV210_PD_TV,
+};
+
+static struct s5pv210_pd_config s5pv210_pd_lcd_pdata = {
+ .supply_name = "pd_lcd_supply",
+ .microvolts = 5000000,
+ .init_data = &s5pv210_pd_lcd_data,
+ .clk_run = s5pv210_pd_lcd_clk,
+ .ctrlbit = S5PV210_PD_LCD,
+};
+
+static struct s5pv210_pd_config s5pv210_pd_g3d_pdata = {
+ .supply_name = "pd_g3d_supply",
+ .microvolts = 5000000,
+ .init_data = &s5pv210_pd_g3d_data,
+ .clk_run = s5pv210_pd_g3d_clk,
+ .ctrlbit = S5PV210_PD_G3D,
+};
+
+static struct s5pv210_pd_config s5pv210_pd_mfc_pdata = {
+ .supply_name = "pd_mfc_supply",
+ .microvolts = 5000000,
+ .init_data = &s5pv210_pd_mfc_data,
+ .clk_run = s5pv210_pd_mfc_clk,
+ .ctrlbit = S5PV210_PD_MFC,
+};
+
+struct platform_device s5pv210_pd_audio = {
+ .name = "reg-s5pv210-pd",
+ .id = 0,
+ .dev = {
+ .platform_data = &s5pv210_pd_audio_pdata,
+ },
+};
+
+struct platform_device s5pv210_pd_cam = {
+ .name = "reg-s5pv210-pd",
+ .id = 1,
+ .dev = {
+ .platform_data = &s5pv210_pd_cam_pdata,
+ },
+};
+
+struct platform_device s5pv210_pd_tv = {
+ .name = "reg-s5pv210-pd",
+ .id = 2,
+ .dev = {
+ .platform_data = &s5pv210_pd_tv_pdata,
+ },
+};
+
+struct platform_device s5pv210_pd_lcd = {
+ .name = "reg-s5pv210-pd",
+ .id = 3,
+ .dev = {
+ .platform_data = &s5pv210_pd_lcd_pdata,
+ },
+};
+
+struct platform_device s5pv210_pd_g3d = {
+ .name = "reg-s5pv210-pd",
+ .id = 4,
+ .dev = {
+ .platform_data = &s5pv210_pd_g3d_pdata,
+ },
+};
+
+struct platform_device s5pv210_pd_mfc = {
+ .name = "reg-s5pv210-pd",
+ .id = 5,
+ .dev = {
+ .platform_data = &s5pv210_pd_mfc_pdata,
+ },
+};
+
+static int s5pv210_pd_pwr_done(int ctrl)
+{
+ unsigned int cnt;
+ cnt = 1000;
+
+ do {
+ if (__raw_readl(S5P_BLK_PWR_STAT) & ctrl)
+ return 0;
+ udelay(1);
+ } while (cnt-- > 0);
+
+ return -ETIME;
+}
+
+static int s5pv210_pd_pwr_off(int ctrl)
+{
+ unsigned int cnt;
+ cnt = 1000;
+
+ do {
+ if (!(__raw_readl(S5P_BLK_PWR_STAT) & ctrl))
+ return 0;
+ udelay(1);
+ } while (cnt-- > 0);
+
+ return -ETIME;
+}
+
+static int s5pv210_pd_ctrl(int ctrlbit, int enable)
+{
+ u32 pd_reg;
+
+ spin_lock(&pd_lock);
+ pd_reg = __raw_readl(S5P_NORMAL_CFG);
+ if (enable) {
+ __raw_writel((pd_reg | ctrlbit), S5P_NORMAL_CFG);
+ if (s5pv210_pd_pwr_done(ctrlbit))
+ goto out;
+ } else {
+ __raw_writel((pd_reg & ~(ctrlbit)), S5P_NORMAL_CFG);
+ if (s5pv210_pd_pwr_off(ctrlbit))
+ goto out;
+ }
+ spin_unlock(&pd_lock);
+ return 0;
+out:
+ spin_unlock(&pd_lock);
+ return -ETIME;
+
+}
+
+static int s5pv210_pd_clk_enable(struct clk_should_be_running *clk_run)
+{
+ struct clk *clkp;
+ int i;
+
+ for (i = 0;; i++) {
+ if (clk_run[i].clk_name == NULL)
+ break;
+
+ clkp = clk_get(clk_run[i].dev, clk_run[i].clk_name);
+
+ if (IS_ERR(clkp)) {
+ printk(KERN_ERR "unable to get clock %s\n",
+ clk_run[i].clk_name);
+ } else {
+ clk_enable(clkp);
+ clk_put(clkp);
+ }
+ }
+
+ return 0;
+}
+
+static int s5pv210_pd_clk_disable(struct clk_should_be_running *clk_run)
+{
+ struct clk *clkp;
+ int i;
+
+ for (i = 0;; i++) {
+ if (clk_run[i].clk_name == NULL)
+ break;
+
+ clkp = clk_get(clk_run[i].dev, clk_run[i].clk_name);
+
+ if (IS_ERR(clkp)) {
+ printk(KERN_ERR "unable to get clock %s\n",
+ clk_run[i].clk_name);
+ } else {
+ clk_disable(clkp);
+ clk_put(clkp);
+ }
+ }
+
+ return 0;
+}
+
+static int s5pv210_pd_is_enabled(struct regulator_dev *dev)
+{
+ struct s5pv210_pd_data *data = rdev_get_drvdata(dev);
+
+ return (__raw_readl(S5P_BLK_PWR_STAT) & data->ctrlbit) ? 1 : 0;
+}
+
+static int s5pv210_pd_enable(struct regulator_dev *dev)
+{
+ struct s5pv210_pd_data *data = rdev_get_drvdata(dev);
+ int ret = 0;
+
+ if (data->clk_run)
+ s5pv210_pd_clk_enable(data->clk_run);
+
+ ret = s5pv210_pd_ctrl(data->ctrlbit, 1);
+ if (ret < 0) {
+ printk(KERN_ERR "failed to enable power domain\n");
+ }
+
+ if (data->clk_run)
+ s5pv210_pd_clk_disable(data->clk_run);
+
+ return ret;
+}
+
+static int s5pv210_pd_disable(struct regulator_dev *dev)
+{
+ struct s5pv210_pd_data *data = rdev_get_drvdata(dev);
+ int ret;
+
+ ret = s5pv210_pd_ctrl(data->ctrlbit, 0);
+ if (ret < 0) {
+ printk(KERN_ERR "faild to disable power domain\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int s5pv210_pd_enable_time(struct regulator_dev *dev)
+{
+ struct s5pv210_pd_data *data = rdev_get_drvdata(dev);
+
+ return data->startup_delay;
+}
+
+static int s5pv210_pd_get_voltage(struct regulator_dev *dev)
+{
+ struct s5pv210_pd_data *data = rdev_get_drvdata(dev);
+
+ return data->microvolts;
+}
+
+static int s5pv210_pd_list_voltage(struct regulator_dev *dev,
+ unsigned selector)
+{
+ struct s5pv210_pd_data *data = rdev_get_drvdata(dev);
+
+ if (selector != 0)
+ return -EINVAL;
+
+ return data->microvolts;
+}
+
+static struct regulator_ops s5pv210_pd_ops = {
+ .is_enabled = s5pv210_pd_is_enabled,
+ .enable = s5pv210_pd_enable,
+ .disable = s5pv210_pd_disable,
+ .enable_time = s5pv210_pd_enable_time,
+ .get_voltage = s5pv210_pd_get_voltage,
+ .list_voltage = s5pv210_pd_list_voltage,
+};
+
+static int __devinit reg_s5pv210_pd_probe(struct platform_device *pdev)
+{
+ struct s5pv210_pd_config *config = pdev->dev.platform_data;
+ struct s5pv210_pd_data *drvdata;
+ int ret;
+
+ drvdata = kzalloc(sizeof(struct s5pv210_pd_data), GFP_KERNEL);
+ if (drvdata == NULL) {
+ dev_err(&pdev->dev, "Failed to allocate device data\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ drvdata->desc.name = kstrdup(config->supply_name, GFP_KERNEL);
+ if (drvdata->desc.name == NULL) {
+ dev_err(&pdev->dev, "Failed to allocate supply name\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ drvdata->desc.type = REGULATOR_VOLTAGE;
+ drvdata->desc.owner = THIS_MODULE;
+ drvdata->desc.ops = &s5pv210_pd_ops;
+ drvdata->desc.n_voltages = 1;
+
+ drvdata->microvolts = config->microvolts;
+ drvdata->startup_delay = config->startup_delay;
+
+ drvdata->clk_run = config->clk_run;
+ drvdata->ctrlbit = config->ctrlbit;
+ spin_lock_init(&pd_lock);
+
+ drvdata->dev = regulator_register(&drvdata->desc, &pdev->dev,
+ config->init_data, drvdata);
+ if (IS_ERR(drvdata->dev)) {
+ ret = PTR_ERR(drvdata->dev);
+ dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret);
+ goto err_name;
+ }
+
+ platform_set_drvdata(pdev, drvdata);
+
+ dev_dbg(&pdev->dev, "%s supplying %duV\n", drvdata->desc.name,
+ drvdata->microvolts);
+
+ return 0;
+
+err_name:
+ kfree(drvdata->desc.name);
+err:
+ kfree(drvdata);
+ return ret;
+}
+
+static int __devexit reg_s5pv210_pd_remove(struct platform_device *pdev)
+{
+ struct s5pv210_pd_data *drvdata = platform_get_drvdata(pdev);
+
+ regulator_unregister(drvdata->dev);
+ kfree(drvdata->desc.name);
+ kfree(drvdata);
+
+ return 0;
+}
+
+static struct platform_driver regulator_s5pv210_pd_driver = {
+ .probe = reg_s5pv210_pd_probe,
+ .remove = __devexit_p(reg_s5pv210_pd_remove),
+ .driver = {
+ .name = "reg-s5pv210-pd",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init regulator_s5pv210_pd_init(void)
+{
+ return platform_driver_register(&regulator_s5pv210_pd_driver);
+}
+subsys_initcall(regulator_s5pv210_pd_init);
+
+static void __exit regulator_s5pv210_pd_exit(void)
+{
+ platform_driver_unregister(&regulator_s5pv210_pd_driver);
+}
+module_exit(regulator_s5pv210_pd_exit);
+
+MODULE_AUTHOR("HuiSung Kang <hs1218.kang@samsung.com>");
+MODULE_DESCRIPTION("S5PV210 power domain regulator");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:reg-s5pv210-pd");
diff --git a/arch/arm/mach-s5pv210/setup-fb.c b/arch/arm/mach-s5pv210/setup-fb.c
new file mode 100644
index 0000000..85adf23
--- /dev/null
+++ b/arch/arm/mach-s5pv210/setup-fb.c
@@ -0,0 +1,226 @@
+/* linux/arch/arm/mach-s5pv210/setup-fb.c
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Base FIMD controller configuration
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+#include <plat/clock.h>
+#include <plat/gpio-cfg.h>
+#include <plat/fb.h>
+#include <mach/regs-clock.h>
+#include <mach/regs-gpio.h>
+#include <linux/io.h>
+#include <mach/map.h>
+
+struct platform_device; /* don't need the contents */
+
+void s3cfb_cfg_gpio(struct platform_device *pdev)
+{
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ s3c_gpio_cfgpin(S5PV210_GPF0(i), S3C_GPIO_SFN(2));
+ s3c_gpio_setpull(S5PV210_GPF0(i), S3C_GPIO_PULL_NONE);
+ }
+
+ for (i = 0; i < 8; i++) {
+ s3c_gpio_cfgpin(S5PV210_GPF1(i), S3C_GPIO_SFN(2));
+ s3c_gpio_setpull(S5PV210_GPF1(i), S3C_GPIO_PULL_NONE);
+ }
+
+ for (i = 0; i < 8; i++) {
+ s3c_gpio_cfgpin(S5PV210_GPF2(i), S3C_GPIO_SFN(2));
+ s3c_gpio_setpull(S5PV210_GPF2(i), S3C_GPIO_PULL_NONE);
+ }
+
+ for (i = 0; i < 4; i++) {
+ s3c_gpio_cfgpin(S5PV210_GPF3(i), S3C_GPIO_SFN(2));
+ s3c_gpio_setpull(S5PV210_GPF3(i), S3C_GPIO_PULL_NONE);
+ }
+
+ /* mDNIe SEL: why we shall write 0x2 ? */
+ writel(0x2, S5P_MDNIE_SEL);
+
+ /* drive strength to max */
+ writel(0xffffffff, S5PV210_GPF0_BASE + 0xc);
+ writel(0xffffffff, S5PV210_GPF1_BASE + 0xc);
+ writel(0xffffffff, S5PV210_GPF2_BASE + 0xc);
+ writel(0x000000ff, S5PV210_GPF3_BASE + 0xc);
+}
+
+int s3cfb_clk_on(struct platform_device *pdev, struct clk **s3cfb_clk)
+{
+ struct clk *sclk = NULL;
+ struct clk *mout_mpll = NULL;
+ u32 rate = 0;
+
+ sclk = clk_get(&pdev->dev, "sclk_fimd");
+ if (IS_ERR(sclk)) {
+ dev_err(&pdev->dev, "failed to get sclk for fimd\n");
+ goto err_clk1;
+ }
+
+ mout_mpll = clk_get(&pdev->dev, "mout_mpll");
+ if (IS_ERR(mout_mpll)) {
+ dev_err(&pdev->dev, "failed to get mout_mpll\n");
+ goto err_clk2;
+ }
+
+ clk_set_parent(sclk, mout_mpll);
+
+ if (!rate)
+ rate = 166750000;
+
+ clk_set_rate(sclk, rate);
+ dev_dbg(&pdev->dev, "set fimd sclk rate to %d\n", rate);
+
+ clk_put(mout_mpll);
+
+ clk_enable(sclk);
+
+ *s3cfb_clk = sclk;
+
+ return 0;
+
+err_clk2:
+ clk_put(sclk);
+
+err_clk1:
+ return -EINVAL;
+}
+
+int s3cfb_clk_off(struct platform_device *pdev, struct clk **clk)
+{
+ clk_disable(*clk);
+ clk_put(*clk);
+
+ *clk = NULL;
+
+ return 0;
+}
+
+void s3cfb_get_clk_name(char *clk_name)
+{
+ strcpy(clk_name, "sclk_fimd");
+}
+#ifdef CONFIG_FB_S3C_LTE480WV
+int s3cfb_backlight_onoff(struct platform_device *pdev, int onoff)
+{
+ int err;
+
+ err = gpio_request(S5PV210_GPD0(3), "GPD0");
+
+ if (err) {
+ printk(KERN_ERR "failed to request GPD0 for "
+ "lcd backlight control\n");
+ return err;
+ }
+
+ if (onoff) {
+ gpio_direction_output(S5PV210_GPD0(3), 1);
+ /* 2009.12.28 by icarus : added for PWM backlight */
+ s3c_gpio_cfgpin(S5PV210_GPD0(3), S5PV210_GPD_0_3_TOUT_3);
+
+ } else {
+ gpio_direction_output(S5PV210_GPD0(3), 0);
+ }
+ gpio_free(S5PV210_GPD0(3));
+ return 0;
+}
+
+int s3cfb_reset_lcd(struct platform_device *pdev)
+{
+ int err;
+
+ err = gpio_request(S5PV210_GPH0(6), "GPH0");
+ if (err) {
+ printk(KERN_ERR "failed to request GPH0 for "
+ "lcd reset control\n");
+ return err;
+ }
+
+ gpio_direction_output(S5PV210_GPH0(6), 1);
+ mdelay(100);
+
+ gpio_set_value(S5PV210_GPH0(6), 0);
+ mdelay(10);
+
+ gpio_set_value(S5PV210_GPH0(6), 1);
+ mdelay(10);
+
+ gpio_free(S5PV210_GPH0(6));
+
+ return 0;
+}
+#elif defined(CONFIG_FB_S3C_HT101HD1)
+int s3cfb_backlight_on(struct platform_device *pdev)
+{
+ int err;
+
+ err = gpio_request(S5PV210_GPB(2), "GPB");
+ if (err) {
+ printk(KERN_ERR "failed to request GPB for "
+ "lcd backlight control\n");
+ return err;
+ }
+
+#ifdef CONFIG_TYPE_PROTO3
+ err = gpio_request(S5PV210_GPD0(1), "GPD0");
+ if (err) {
+ printk(KERN_ERR "failed to request GPD0 for "
+ "lcd backlight control\n");
+ return err;
+ }
+#endif
+
+ gpio_direction_output(S5PV210_GPB(2), 1); /* LED_EN (SPI1_MOSI) */
+
+#ifdef CONFIG_TYPE_PROTO3
+ /* LCD_PWR_EN is only for Proto3 */
+ gpio_direction_output(S5PV210_GPD0(1), 1);
+ mdelay(10);
+#endif
+
+ gpio_free(S5PV210_GPB(2));
+#ifdef CONFIG_TYPE_PROTO3
+ gpio_free(S5PV210_GPD0(1));
+#endif
+
+ return 0;
+}
+
+int s3cfb_reset_lcd(struct platform_device *pdev)
+{
+ int err;
+
+ err = gpio_request(S5PV210_GPH0(1), "GPH0");
+ if (err) {
+ printk(KERN_ERR "failed to request GPH0 for "
+ "lcd reset control\n");
+ return err;
+ }
+
+ gpio_direction_output(S5PV210_GPH0(1), 1);
+
+ gpio_set_value(S5PV210_GPH0(1), 0);
+
+ gpio_set_value(S5PV210_GPH0(1), 1);
+
+ gpio_free(S5PV210_GPH0(1));
+
+ return 0;
+}
+#endif
diff --git a/arch/arm/mach-s5pv210/setup-fimc0.c b/arch/arm/mach-s5pv210/setup-fimc0.c
new file mode 100644
index 0000000..6b4b39b
--- /dev/null
+++ b/arch/arm/mach-s5pv210/setup-fimc0.c
@@ -0,0 +1,122 @@
+/* linux/arch/arm/mach-s5pv210/setup-fimc0.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Base FIMC 0 gpio configuration
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <plat/clock.h>
+#include <plat/gpio-cfg.h>
+#include <plat/map-s5p.h>
+#include <mach/regs-gpio.h>
+#include <mach/map.h>
+#include <plat/regs-fimc.h>
+
+struct platform_device; /* don't need the contents */
+
+void s3c_fimc0_cfg_gpio(struct platform_device *pdev)
+{
+ int i = 0;
+
+ /* CAM A port(b0010) : PCLK, VSYNC, HREF, DATA[0-4] */
+ for (i = 0; i < 8; i++) {
+ s3c_gpio_cfgpin(S5PV210_GPE0(i), S3C_GPIO_SFN(2));
+ s3c_gpio_setpull(S5PV210_GPE0(i), S3C_GPIO_PULL_NONE);
+ }
+ /* CAM A port(b0010) : DATA[5-7], CLKOUT(MIPI CAM also), FIELD */
+ for (i = 0; i < 3; i++) {
+ s3c_gpio_cfgpin(S5PV210_GPE1(i), S3C_GPIO_SFN(2));
+ s3c_gpio_setpull(S5PV210_GPE1(i), S3C_GPIO_PULL_NONE);
+ }
+
+#if defined(CONFIG_MACH_SMDKC110) || defined(CONFIG_MACH_SMDKV210)
+ s3c_gpio_cfgpin(S5PV210_GPE1(4), S5PV210_GPE1_4_CAM_A_FIELD);
+ s3c_gpio_setpull(S5PV210_GPE1(4), S3C_GPIO_PULL_NONE);
+
+ /* CAM B port(b0011) : DATA[0-7] */
+ for (i = 0; i < 8; i++) {
+ s3c_gpio_cfgpin(S5PV210_GPJ0(i), S3C_GPIO_SFN(3));
+ s3c_gpio_setpull(S5PV210_GPJ0(i), S3C_GPIO_PULL_NONE);
+ }
+ /* CAM B port(b0011) : PCLK, VSYNC, HREF, FIELD, CLCKOUT */
+ for (i = 0; i < 5; i++) {
+ s3c_gpio_cfgpin(S5PV210_GPJ1(i), S3C_GPIO_SFN(3));
+ s3c_gpio_setpull(S5PV210_GPJ1(i), S3C_GPIO_PULL_NONE);
+ }
+#endif
+
+ /* note : driver strength to max is unnecessary */
+}
+
+int s3c_fimc_clk_on(struct platform_device *pdev, struct clk *clk)
+{
+ struct clk *sclk_fimc_lclk = NULL;
+ struct clk *mout_fimc_lclk = NULL;
+ struct clk *mout_mpll = NULL;
+
+ mout_mpll = clk_get(&pdev->dev, "mout_mpll");
+ if (IS_ERR(mout_mpll)) {
+ dev_err(&pdev->dev, "failed to get mout_mpll\n");
+ goto err_clk1;
+ }
+
+ mout_fimc_lclk = clk_get(&pdev->dev, "mout_fimc_lclk");
+ if (IS_ERR(mout_fimc_lclk)) {
+ dev_err(&pdev->dev, "failed to get mout_fimc_lclk\n");
+ goto err_clk2;
+ }
+
+ sclk_fimc_lclk = clk_get(&pdev->dev, "fimc");
+ if (IS_ERR(sclk_fimc_lclk)) {
+ dev_err(&pdev->dev, "failed to get sclk_fimc_lclk\n");
+ goto err_clk3;
+ }
+
+ clk_set_parent(mout_fimc_lclk, mout_mpll);
+ clk_set_rate(sclk_fimc_lclk, 166750000);
+
+ /* be able to handle clock on/off only with this clock */
+ clk = clk_get(&pdev->dev, "fimc");
+ if (IS_ERR(clk)) {
+ dev_err(&pdev->dev, "failed to get interface clock\n");
+ goto err_clk3;
+ }
+
+ clk_put(mout_mpll);
+ clk_put(mout_fimc_lclk);
+
+ clk_enable(clk);
+
+ return 0;
+
+err_clk3:
+ clk_put(mout_fimc_lclk);
+
+err_clk2:
+ clk_put(mout_mpll);
+
+err_clk1:
+ return -EINVAL;
+}
+
+int s3c_fimc_clk_off(struct platform_device *pdev, struct clk *clk)
+{
+ clk_disable(clk);
+ clk_put(clk);
+
+ clk = NULL;
+
+ return 0;
+}
diff --git a/arch/arm/mach-s5pv210/setup-fimc1.c b/arch/arm/mach-s5pv210/setup-fimc1.c
new file mode 100644
index 0000000..5ec1301
--- /dev/null
+++ b/arch/arm/mach-s5pv210/setup-fimc1.c
@@ -0,0 +1,21 @@
+/* linux/arch/arm/mach-s5pv210/setup-fimc1.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Base FIMC 1 gpio configuration
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+struct platform_device; /* don't need the contents */
+
+#include <mach/gpio.h>
+#include <plat/gpio-cfg.h>
+
+void s3c_fimc1_cfg_gpio(struct platform_device *pdev) { }
diff --git a/arch/arm/mach-s5pv210/setup-fimc2.c b/arch/arm/mach-s5pv210/setup-fimc2.c
new file mode 100644
index 0000000..aaa6f6e
--- /dev/null
+++ b/arch/arm/mach-s5pv210/setup-fimc2.c
@@ -0,0 +1,21 @@
+/* linux/arch/arm/mach-s5pv210/setup-fimc2.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Base FIMC 2 gpio configuration
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+struct platform_device; /* don't need the contents */
+
+#include <mach/gpio.h>
+#include <plat/gpio-cfg.h>
+
+void s3c_fimc2_cfg_gpio(struct platform_device *pdev) { }
diff --git a/arch/arm/mach-s5pv210/setup-i2c0.c b/arch/arm/mach-s5pv210/setup-i2c0.c
index 0f1cc3a..39b644f 100644
--- a/arch/arm/mach-s5pv210/setup-i2c0.c
+++ b/arch/arm/mach-s5pv210/setup-i2c0.c
@@ -24,5 +24,5 @@ struct platform_device; /* don't need the contents */
void s3c_i2c0_cfg_gpio(struct platform_device *dev)
{
s3c_gpio_cfgall_range(S5PV210_GPD1(0), 2,
- S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
+ S3C_GPIO_SFN(2), S3C_GPIO_PULL_NONE);
}
diff --git a/arch/arm/mach-s5pv210/setup-i2c1.c b/arch/arm/mach-s5pv210/setup-i2c1.c
index f61365a..834b318 100644
--- a/arch/arm/mach-s5pv210/setup-i2c1.c
+++ b/arch/arm/mach-s5pv210/setup-i2c1.c
@@ -24,5 +24,5 @@ struct platform_device; /* don't need the contents */
void s3c_i2c1_cfg_gpio(struct platform_device *dev)
{
s3c_gpio_cfgall_range(S5PV210_GPD1(2), 2,
- S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
+ S3C_GPIO_SFN(2), S3C_GPIO_PULL_NONE);
}
diff --git a/arch/arm/mach-s5pv210/setup-i2c2.c b/arch/arm/mach-s5pv210/setup-i2c2.c
index 2f91b5c..3bdc649 100644
--- a/arch/arm/mach-s5pv210/setup-i2c2.c
+++ b/arch/arm/mach-s5pv210/setup-i2c2.c
@@ -24,5 +24,5 @@ struct platform_device; /* don't need the contents */
void s3c_i2c2_cfg_gpio(struct platform_device *dev)
{
s3c_gpio_cfgall_range(S5PV210_GPD1(4), 2,
- S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
+ S3C_GPIO_SFN(2), S3C_GPIO_PULL_NONE);
}
diff --git a/arch/arm/mach-s5pv210/setup-sdhci-gpio.c b/arch/arm/mach-s5pv210/setup-sdhci-gpio.c
index 3e3ac05..0ecc905 100644
--- a/arch/arm/mach-s5pv210/setup-sdhci-gpio.c
+++ b/arch/arm/mach-s5pv210/setup-sdhci-gpio.c
@@ -23,82 +23,125 @@
#include <plat/regs-sdhci.h>
#include <plat/sdhci.h>
+#include "herring.h"
+
void s5pv210_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
{
- struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
-
- /* Set all the necessary GPG0/GPG1 pins to special-function 2 */
- s3c_gpio_cfgrange_nopull(S5PV210_GPG0(0), 2, S3C_GPIO_SFN(2));
+ unsigned int gpio;
switch (width) {
+ /* Channel 0 supports 4 and 8-bit bus width */
case 8:
- /* GPG1[3:6] special-function 3 */
- s3c_gpio_cfgrange_nopull(S5PV210_GPG1(3), 4, S3C_GPIO_SFN(3));
+ /* Set all the necessary GPIO function and pull up/down */
+ for (gpio = S5PV210_GPG1(3); gpio <= S5PV210_GPG1(6); gpio++) {
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+ s3c_gpio_set_drvstrength(gpio, S3C_GPIO_DRVSTR_2X);
+ }
+
+ case 0:
+ case 1:
case 4:
- /* GPG0[3:6] special-function 2 */
- s3c_gpio_cfgrange_nopull(S5PV210_GPG0(3), 4, S3C_GPIO_SFN(2));
- default:
+ /* Set all the necessary GPIO function and pull up/down */
+ for (gpio = S5PV210_GPG0(0); gpio <= S5PV210_GPG0(6); gpio++) {
+ if (gpio != S5PV210_GPG0(2)) {
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+ }
+ s3c_gpio_set_drvstrength(gpio, S3C_GPIO_DRVSTR_2X);
+ }
break;
+ default:
+ printk(KERN_ERR "Wrong SD/MMC bus width : %d\n", width);
+ }
+
+ if (machine_is_herring()) {
+ s3c_gpio_cfgpin(S5PV210_GPJ2(7), S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(S5PV210_GPJ2(7), S3C_GPIO_PULL_NONE);
+ gpio_set_value(S5PV210_GPJ2(7), 1);
}
- if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
- s3c_gpio_setpull(S5PV210_GPG0(2), S3C_GPIO_PULL_UP);
- s3c_gpio_cfgpin(S5PV210_GPG0(2), S3C_GPIO_SFN(2));
+ if (machine_is_herring()) {
+ gpio_direction_output(S5PV210_GPJ2(7), 1);
+ s3c_gpio_setpull(S5PV210_GPJ2(7), S3C_GPIO_PULL_NONE);
}
}
void s5pv210_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
{
- struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
+ unsigned int gpio;
- /* Set all the necessary GPG1[0:1] pins to special-function 2 */
- s3c_gpio_cfgrange_nopull(S5PV210_GPG1(0), 2, S3C_GPIO_SFN(2));
-
- /* Data pin GPG1[3:6] to special-function 2 */
- s3c_gpio_cfgrange_nopull(S5PV210_GPG1(3), 4, S3C_GPIO_SFN(2));
-
- if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
- s3c_gpio_setpull(S5PV210_GPG1(2), S3C_GPIO_PULL_UP);
- s3c_gpio_cfgpin(S5PV210_GPG1(2), S3C_GPIO_SFN(2));
+ switch (width) {
+ /* Channel 1 supports 4-bit bus width */
+ case 0:
+ case 1:
+ case 4:
+ /* Set all the necessary GPIO function and pull up/down */
+ for (gpio = S5PV210_GPG1(0); gpio <= S5PV210_GPG1(6); gpio++) {
+ if (gpio != S5PV210_GPG1(2)) {
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+ }
+ s3c_gpio_set_drvstrength(gpio, S3C_GPIO_DRVSTR_2X);
+ }
+ break;
+ default:
+ printk(KERN_ERR "Wrong SD/MMC bus width : %d\n", width);
}
}
void s5pv210_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width)
{
- struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
-
- /* Set all the necessary GPG2[0:1] pins to special-function 2 */
- s3c_gpio_cfgrange_nopull(S5PV210_GPG2(0), 2, S3C_GPIO_SFN(2));
+ unsigned int gpio;
switch (width) {
+ /* Channel 2 supports 4 and 8-bit bus width */
case 8:
- /* Data pin GPG3[3:6] to special-function 3 */
- s3c_gpio_cfgrange_nopull(S5PV210_GPG3(3), 4, S3C_GPIO_SFN(3));
+ /* Set all the necessary GPIO function and pull up/down */
+ for (gpio = S5PV210_GPG3(3); gpio <= S5PV210_GPG3(6); gpio++) {
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+ s3c_gpio_set_drvstrength(gpio, S3C_GPIO_DRVSTR_2X);
+ }
+
+ case 0:
+ case 1:
case 4:
- /* Data pin GPG2[3:6] to special-function 2 */
- s3c_gpio_cfgrange_nopull(S5PV210_GPG2(3), 4, S3C_GPIO_SFN(2));
- default:
+ if (machine_is_herring() && herring_is_cdma_wimax_dev())
+ break;
+ /* Set all the necessary GPIO function and pull up/down */
+ for (gpio = S5PV210_GPG2(0); gpio <= S5PV210_GPG2(6); gpio++) {
+ if (gpio != S5PV210_GPG2(2)) {
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+ }
+ s3c_gpio_set_drvstrength(gpio, S3C_GPIO_DRVSTR_2X);
+ }
break;
- }
-
- if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
- s3c_gpio_setpull(S5PV210_GPG2(2), S3C_GPIO_PULL_UP);
- s3c_gpio_cfgpin(S5PV210_GPG2(2), S3C_GPIO_SFN(2));
+ default:
+ printk(KERN_ERR "Wrong SD/MMC bus width : %d\n", width);
}
}
void s5pv210_setup_sdhci3_cfg_gpio(struct platform_device *dev, int width)
{
- struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
-
- /* Set all the necessary GPG3[0:1] pins to special-function 2 */
- s3c_gpio_cfgrange_nopull(S5PV210_GPG3(0), 2, S3C_GPIO_SFN(2));
+ unsigned int gpio;
- /* Data pin GPG3[3:6] to special-function 2 */
- s3c_gpio_cfgrange_nopull(S5PV210_GPG3(3), 4, S3C_GPIO_SFN(2));
-
- if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
- s3c_gpio_setpull(S5PV210_GPG3(2), S3C_GPIO_PULL_UP);
- s3c_gpio_cfgpin(S5PV210_GPG3(2), S3C_GPIO_SFN(2));
+ switch (width) {
+ /* Channel 3 supports 4-bit bus width */
+ case 0:
+ case 1:
+ case 4:
+ /* Set all the necessary GPIO function and pull up/down */
+ for (gpio = S5PV210_GPG3(0); gpio <= S5PV210_GPG3(6); gpio++) {
+ if (gpio != S5PV210_GPG3(2)) {
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
+ }
+ s3c_gpio_set_drvstrength(gpio, S3C_GPIO_DRVSTR_2X);
+ }
+ break;
+ default:
+ printk(KERN_ERR "Wrong SD/MMC bus width : %d\n", width);
}
}
diff --git a/arch/arm/mach-s5pv210/setup-sdhci.c b/arch/arm/mach-s5pv210/setup-sdhci.c
index a83b6c9..04ec6af 100644
--- a/arch/arm/mach-s5pv210/setup-sdhci.c
+++ b/arch/arm/mach-s5pv210/setup-sdhci.c
@@ -15,6 +15,7 @@
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/io.h>
+#include <linux/irq.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
@@ -22,6 +23,13 @@
#include <plat/regs-sdhci.h>
#include <plat/sdhci.h>
+#include <plat/gpio-cfg.h>
+#include <plat/devs.h>
+#include <mach/regs-gpio.h>
+#include <mach/gpio.h>
+
+#include "herring.h"
+
/* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */
char *s5pv210_hsmmc_clksrcs[4] = {
@@ -31,33 +39,225 @@ char *s5pv210_hsmmc_clksrcs[4] = {
/* [3] = NULL, - reserved */
};
+#define S3C_SDHCI_CTRL3_FCSELTX_INVERT (0)
+#define S3C_SDHCI_CTRL3_FCSELTX_BASIC \
+ (S3C_SDHCI_CTRL3_FCSEL3 | S3C_SDHCI_CTRL3_FCSEL2)
+#define S3C_SDHCI_CTRL3_FCSELRX_INVERT (0)
+#define S3C_SDHCI_CTRL3_FCSELRX_BASIC \
+ (S3C_SDHCI_CTRL3_FCSEL1 | S3C_SDHCI_CTRL3_FCSEL0)
+
void s5pv210_setup_sdhci_cfg_card(struct platform_device *dev,
void __iomem *r,
struct mmc_ios *ios,
struct mmc_card *card)
{
- u32 ctrl2, ctrl3;
-
- /* don't need to alter anything according to card-type */
-
- writel(S3C64XX_SDHCI_CONTROL4_DRIVE_9mA, r + S3C64XX_SDHCI_CONTROL4);
+ u32 ctrl2;
+ u32 ctrl3;
ctrl2 = readl(r + S3C_SDHCI_CONTROL2);
ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK;
ctrl2 |= (S3C64XX_SDHCI_CTRL2_ENSTAASYNCCLR |
S3C64XX_SDHCI_CTRL2_ENCMDCNFMSK |
- S3C_SDHCI_CTRL2_ENFBCLKRX |
S3C_SDHCI_CTRL2_DFCNT_NONE |
S3C_SDHCI_CTRL2_ENCLKOUTHOLD);
- if (ios->clock < 25 * 1000000)
- ctrl3 = (S3C_SDHCI_CTRL3_FCSEL3 |
- S3C_SDHCI_CTRL3_FCSEL2 |
- S3C_SDHCI_CTRL3_FCSEL1 |
- S3C_SDHCI_CTRL3_FCSEL0);
- else
- ctrl3 = (S3C_SDHCI_CTRL3_FCSEL1 | S3C_SDHCI_CTRL3_FCSEL0);
+ if (ios->clock <= (400 * 1000)) {
+ ctrl2 &= ~(S3C_SDHCI_CTRL2_ENFBCLKTX |
+ S3C_SDHCI_CTRL2_ENFBCLKRX);
+ ctrl3 = 0;
+ } else {
+ u32 range_start;
+ u32 range_end;
+
+ ctrl2 |= S3C_SDHCI_CTRL2_ENFBCLKTX |
+ S3C_SDHCI_CTRL2_ENFBCLKRX;
+
+ if (card->type == MMC_TYPE_MMC) /* MMC */
+ range_start = 20 * 1000 * 1000;
+ //else /* SD, SDIO */
+ // range_start = 25 * 1000 * 1000;
+
+ range_end = 37 * 1000 * 1000;
+
+ if ((ios->clock > range_start) && (ios->clock < range_end))
+ ctrl3 = S3C_SDHCI_CTRL3_FCSELTX_BASIC |
+ S3C_SDHCI_CTRL3_FCSELRX_BASIC;
+ else if (machine_is_herring() && herring_is_cdma_wimax_dev() &&
+ dev->id == 2) {
+ ctrl3 = S3C_SDHCI_CTRL3_FCSELTX_BASIC;
+ //if(card->type & MMC_TYPE_SDIO)
+ ctrl3 |= S3C_SDHCI_CTRL3_FCSELRX_BASIC;
+ //else
+ // ctrl3 |= S3C_SDHCI_CTRL3_FCSELRX_INVERT;
+ } else
+ ctrl3 = S3C_SDHCI_CTRL3_FCSELTX_BASIC |
+ S3C_SDHCI_CTRL3_FCSELRX_INVERT;
+ }
+
+
+ writel(ctrl2, r + S3C_SDHCI_CONTROL2);
+ writel(ctrl3, r + S3C_SDHCI_CONTROL3);
+}
+
+void s5pv210_adjust_sdhci_cfg_card(struct s3c_sdhci_platdata *pdata,
+ void __iomem *r, int rw)
+{
+ u32 ctrl2, ctrl3;
+
+ ctrl2 = readl(r + S3C_SDHCI_CONTROL2);
+ ctrl3 = readl(r + S3C_SDHCI_CONTROL3);
+
+ if (rw == 0) {
+ pdata->rx_cfg++;
+ if (pdata->rx_cfg == 1) {
+ ctrl2 |= S3C_SDHCI_CTRL2_ENFBCLKRX;
+ ctrl3 |= S3C_SDHCI_CTRL3_FCSELRX_BASIC;
+ } else if (pdata->rx_cfg == 2) {
+ ctrl2 |= S3C_SDHCI_CTRL2_ENFBCLKRX;
+ ctrl3 &= ~S3C_SDHCI_CTRL3_FCSELRX_BASIC;
+ } else if (pdata->rx_cfg == 3) {
+ ctrl2 &= ~(S3C_SDHCI_CTRL2_ENFBCLKTX |
+ S3C_SDHCI_CTRL2_ENFBCLKRX);
+ pdata->rx_cfg = 0;
+ }
+ } else if (rw == 1) {
+ pdata->tx_cfg++;
+ if (pdata->tx_cfg == 1) {
+ if (ctrl2 & S3C_SDHCI_CTRL2_ENFBCLKRX) {
+ ctrl2 |= S3C_SDHCI_CTRL2_ENFBCLKTX;
+ ctrl3 |= S3C_SDHCI_CTRL3_FCSELTX_BASIC;
+ } else {
+ ctrl2 &= ~S3C_SDHCI_CTRL2_ENFBCLKTX;
+ }
+ } else if (pdata->tx_cfg == 2) {
+ ctrl2 &= ~S3C_SDHCI_CTRL2_ENFBCLKTX;
+ pdata->tx_cfg = 0;
+ }
+ } else {
+ printk(KERN_ERR "%s, unknown value rw:%d\n", __func__, rw);
+ return;
+ }
writel(ctrl2, r + S3C_SDHCI_CONTROL2);
writel(ctrl3, r + S3C_SDHCI_CONTROL3);
}
+
+void universal_sdhci2_cfg_ext_cd(void)
+{
+ printk(KERN_DEBUG "Universal :SD Detect configuration\n");
+ s3c_gpio_setpull(S5PV210_GPH3(4), S3C_GPIO_PULL_NONE);
+ irq_set_irq_type(IRQ_EINT(28), IRQ_TYPE_EDGE_BOTH);
+}
+
+static struct s3c_sdhci_platdata hsmmc0_platdata = {
+#if defined(CONFIG_S5PV210_SD_CH0_8BIT)
+ .max_width = 8,
+ .host_caps = MMC_CAP_8_BIT_DATA,
+#endif
+};
+
+#if defined(CONFIG_S3C_DEV_HSMMC2)
+static struct s3c_sdhci_platdata hsmmc2_platdata = {
+#if defined(CONFIG_S5PV210_SD_CH2_8BIT)
+ .max_width = 8,
+ .host_caps = MMC_CAP_8_BIT_DATA,
+#endif
+};
+#endif
+
+#if defined(CONFIG_S3C_DEV_HSMMC3)
+static struct s3c_sdhci_platdata hsmmc3_platdata = { 0 };
+#endif
+
+static DEFINE_MUTEX(notify_lock);
+
+#define DEFINE_MMC_CARD_NOTIFIER(num) \
+static void (*hsmmc##num##_notify_func)(struct platform_device *, int state); \
+static int ext_cd_init_hsmmc##num(void (*notify_func)( \
+ struct platform_device *, int state)) \
+{ \
+ mutex_lock(&notify_lock); \
+ WARN_ON(hsmmc##num##_notify_func); \
+ hsmmc##num##_notify_func = notify_func; \
+ mutex_unlock(&notify_lock); \
+ return 0; \
+} \
+static int ext_cd_cleanup_hsmmc##num(void (*notify_func)( \
+ struct platform_device *, int state)) \
+{ \
+ mutex_lock(&notify_lock); \
+ WARN_ON(hsmmc##num##_notify_func != notify_func); \
+ hsmmc##num##_notify_func = NULL; \
+ mutex_unlock(&notify_lock); \
+ return 0; \
+}
+
+#ifdef CONFIG_S3C_DEV_HSMMC2
+DEFINE_MMC_CARD_NOTIFIER(2)
+#endif
+#ifdef CONFIG_S3C_DEV_HSMMC3
+DEFINE_MMC_CARD_NOTIFIER(3)
+#endif
+
+/*
+ * call this when you need sd stack to recognize insertion or removal of card
+ * that can't be told by SDHCI regs
+ */
+void sdhci_s3c_force_presence_change(struct platform_device *pdev)
+{
+ void (*notify_func)(struct platform_device *, int state) = NULL;
+ mutex_lock(&notify_lock);
+#ifdef CONFIG_S3C_DEV_HSMMC2
+ if (pdev == &s3c_device_hsmmc2)
+ notify_func = hsmmc2_notify_func;
+#endif
+#ifdef CONFIG_S3C_DEV_HSMMC3
+ if (pdev == &s3c_device_hsmmc3)
+ notify_func = hsmmc3_notify_func;
+#endif
+
+ if (notify_func)
+ notify_func(pdev, 1);
+ else
+ pr_warn("%s: called for device with no notifier\n", __func__);
+ mutex_unlock(&notify_lock);
+}
+EXPORT_SYMBOL_GPL(sdhci_s3c_force_presence_change);
+
+void s3c_sdhci_set_platdata(void)
+{
+#if defined(CONFIG_S3C_DEV_HSMMC)
+ if (machine_is_herring()) { /* TODO: move to mach-herring.c */
+ hsmmc0_platdata.cd_type = S3C_SDHCI_CD_PERMANENT;
+ }
+ s3c_sdhci0_set_platdata(&hsmmc0_platdata);
+#endif
+#if defined(CONFIG_S3C_DEV_HSMMC2)
+ if (machine_is_herring()) {
+ if (herring_is_cdma_wimax_dev()) {
+ hsmmc2_platdata.cd_type = S3C_SDHCI_CD_EXTERNAL;
+ hsmmc2_platdata.ext_cd_init = ext_cd_init_hsmmc2;
+ hsmmc2_platdata.ext_cd_cleanup = ext_cd_cleanup_hsmmc2;
+ hsmmc2_platdata.built_in = 1;
+ hsmmc2_platdata.must_maintain_clock = 1;
+ hsmmc2_platdata.enable_intr_on_resume = 1;
+ } else {
+ hsmmc2_platdata.cd_type = S3C_SDHCI_CD_GPIO;
+ hsmmc2_platdata.ext_cd_gpio = S5PV210_GPH3(4);
+ hsmmc2_platdata.ext_cd_gpio_invert = true;
+ universal_sdhci2_cfg_ext_cd();
+ }
+ }
+
+ s3c_sdhci2_set_platdata(&hsmmc2_platdata);
+#endif
+#if defined(CONFIG_S3C_DEV_HSMMC3)
+ if (machine_is_herring()) {
+ hsmmc3_platdata.cd_type = S3C_SDHCI_CD_EXTERNAL;
+ hsmmc3_platdata.ext_cd_init = ext_cd_init_hsmmc3;
+ hsmmc3_platdata.ext_cd_cleanup = ext_cd_cleanup_hsmmc3;
+ hsmmc3_platdata.built_in = 1;
+ }
+ s3c_sdhci3_set_platdata(&hsmmc3_platdata);
+#endif
+};
diff --git a/arch/arm/mach-s5pv210/sleep.S b/arch/arm/mach-s5pv210/sleep.S
index a3d6494..758c913 100644
--- a/arch/arm/mach-s5pv210/sleep.S
+++ b/arch/arm/mach-s5pv210/sleep.S
@@ -49,6 +49,10 @@ ENTRY(s3c_cpu_save)
mov pc, r0
resume_with_mmu:
+ /* Invalidate TLB after mucking with MMU table. */
+ mov r0, #0
+ mcr p15, 0, r0, c8, c7, 0 @ Invalidate I & D TLB
+
ldmfd sp!, { r3 - r12, pc }
.ltorg
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S
index 1ed1fd3..428b243 100644
--- a/arch/arm/mm/cache-v7.S
+++ b/arch/arm/mm/cache-v7.S
@@ -211,6 +211,9 @@ ENTRY(v7_coherent_user_range)
* isn't mapped, just try the next page.
*/
9001:
+#ifdef CONFIG_ARM_ERRATA_775420
+ dsb
+#endif
mov r12, r12, lsr #12
mov r12, r12, lsl #12
add r12, r12, #4096
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index bc0e1d8..8799eae 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -266,7 +266,9 @@ good_area:
return fault;
check_stack:
- if (vma->vm_flags & VM_GROWSDOWN && !expand_stack(vma, addr))
+ /* Don't allow expansion below FIRST_USER_ADDRESS */
+ if (vma->vm_flags & VM_GROWSDOWN &&
+ addr >= FIRST_USER_ADDRESS && !expand_stack(vma, addr))
goto good_area;
out:
return fault;
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c
index 1a8d4aa..8fda9f7 100644
--- a/arch/arm/mm/flush.c
+++ b/arch/arm/mm/flush.c
@@ -236,8 +236,6 @@ void __sync_icache_dcache(pte_t pteval)
struct page *page;
struct address_space *mapping;
- if (!pte_present_user(pteval))
- return;
if (cache_is_vipt_nonaliasing() && !pte_exec(pteval))
/* only flush non-aliasing VIPT caches for exec mappings */
return;
diff --git a/arch/arm/mm/tlb-v7.S b/arch/arm/mm/tlb-v7.S
index 53cd5b4..d7d0f7f 100644
--- a/arch/arm/mm/tlb-v7.S
+++ b/arch/arm/mm/tlb-v7.S
@@ -39,10 +39,18 @@ ENTRY(v7wbi_flush_user_tlb_range)
mov r0, r0, lsr #PAGE_SHIFT @ align address
mov r1, r1, lsr #PAGE_SHIFT
asid r3, r3 @ mask ASID
+#ifdef CONFIG_ARM_ERRATA_720789
+ ALT_SMP(W(mov) r3, #0 )
+ ALT_UP(W(nop) )
+#endif
orr r0, r3, r0, lsl #PAGE_SHIFT @ Create initial MVA
mov r1, r1, lsl #PAGE_SHIFT
1:
+#ifdef CONFIG_ARM_ERRATA_720789
+ ALT_SMP(mcr p15, 0, r0, c8, c3, 3) @ TLB invalidate U MVA all ASID (shareable)
+#else
ALT_SMP(mcr p15, 0, r0, c8, c3, 1) @ TLB invalidate U MVA (shareable)
+#endif
ALT_UP(mcr p15, 0, r0, c8, c7, 1) @ TLB invalidate U MVA
add r0, r0, #PAGE_SZ
@@ -70,7 +78,11 @@ ENTRY(v7wbi_flush_kern_tlb_range)
mov r0, r0, lsl #PAGE_SHIFT
mov r1, r1, lsl #PAGE_SHIFT
1:
+#ifdef CONFIG_ARM_ERRATA_720789
+ ALT_SMP(mcr p15, 0, r0, c8, c3, 3) @ TLB invalidate U MVA all ASID (shareable)
+#else
ALT_SMP(mcr p15, 0, r0, c8, c3, 1) @ TLB invalidate U MVA (shareable)
+#endif
ALT_UP(mcr p15, 0, r0, c8, c7, 1) @ TLB invalidate U MVA
add r0, r0, #PAGE_SZ
cmp r0, r1
diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c
index 0719f49..9f422ba 100644
--- a/arch/arm/plat-s3c24xx/dma.c
+++ b/arch/arm/plat-s3c24xx/dma.c
@@ -431,7 +431,7 @@ s3c2410_dma_canload(struct s3c2410_dma_chan *chan)
* when necessary.
*/
-int s3c2410_dma_enqueue(unsigned int channel, void *id,
+int s3c2410_dma_enqueue(enum dma_ch channel, void *id,
dma_addr_t data, int size)
{
struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig
index e98f5c5..c2a98b8 100644
--- a/arch/arm/plat-s5p/Kconfig
+++ b/arch/arm/plat-s5p/Kconfig
@@ -94,3 +94,43 @@ config S5P_SETUP_MIPIPHY
bool
help
Compile in common setup code for MIPI-CSIS and MIPI-DSIM devices
+
+# FB part
+config S5P_DEV_FB
+ bool
+ depends on FB_S3C
+ default y
+ help
+ Compile in platform device definitions for FIMD controller
+
+config S5P_HIGH_RES_TIMERS
+ bool "HRtimer and Dynamic Tick support"
+ select GENERIC_CLOCKEVENTS
+ select HIGH_RES_TIMERS
+ select HRT_RTC
+ select NO_HZ
+ default n
+ help
+ Support for HRtimer and Dynamic Tick system.
+
+config HRT_RTC
+ bool
+ depends on S5P_HIGH_RES_TIMERS
+ default y
+ help
+ RTC and System timer are used as HRT
+
+# MFC part
+config S5P_DEV_MFC
+ bool
+ default y if CPU_FREQ
+ default n
+ help
+ Compile in platform device definitions for MFC
+
+config S5P_SETUP_MFC
+ bool
+ default n
+ help
+ Common setup code for MFC
+
diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile
index e234cc4..a9b3cb7 100644
--- a/arch/arm/plat-s5p/Makefile
+++ b/arch/arm/plat-s5p/Makefile
@@ -17,12 +17,17 @@ obj-y += dev-uart.o
obj-y += cpu.o
obj-y += clock.o
obj-y += irq.o
-obj-$(CONFIG_S5P_EXT_INT) += irq-eint.o
+obj-y += devs.o
+obj-y += bootmem.o
+obj-y += reset.o
+obj-$(CONFIG_S5P_EXT_INT) += irq-eint.o irq-eint-group.o
obj-$(CONFIG_S5P_GPIO_INT) += irq-gpioint.o
obj-$(CONFIG_S5P_SYSTEM_MMU) += sysmmu.o
obj-$(CONFIG_PM) += pm.o
obj-$(CONFIG_PM) += irq-pm.o
+ifndef CONFIG_S5P_HIGH_RES_TIMERS
obj-$(CONFIG_S5P_HRT) += s5p-time.o
+endif
# devices
@@ -35,3 +40,22 @@ obj-$(CONFIG_S5P_DEV_CSIS0) += dev-csis0.o
obj-$(CONFIG_S5P_DEV_CSIS1) += dev-csis1.o
obj-$(CONFIG_S5P_DEV_USB_EHCI) += dev-ehci.o
obj-$(CONFIG_S5P_SETUP_MIPIPHY) += setup-mipiphy.o
+
+# PM support
+
+# PM support
+
+obj-$(CONFIG_PM) += pm.o
+obj-$(CONFIG_PM) += irq-pm.o
+
+ifdef CONFIG_S5P_HIGH_RES_TIMERS
+ifdef CONFIG_HRT_RTC
+obj-y += hr-time-rtc.o
+endif
+endif
+
+obj-$(CONFIG_S5P_DEV_MFC) += dev-mfc.o
+obj-$(CONFIG_S5P_SETUP_MFC) += setup-mfc.o
+
+
+EXTRA_CFLAGS += -Idrivers/video/samsung
diff --git a/arch/arm/plat-s5p/bootmem.c b/arch/arm/plat-s5p/bootmem.c
new file mode 100644
index 0000000..8a79c34
--- /dev/null
+++ b/arch/arm/plat-s5p/bootmem.c
@@ -0,0 +1,144 @@
+/* linux/arch/arm/plat-s5p/bootmem.c
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Bootmem helper functions
+ *
+ * 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/memblock.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <asm/setup.h>
+#include <linux/io.h>
+#include <mach/memory.h>
+#include <plat/media.h>
+#include <mach/media.h>
+
+static struct s5p_media_device *media_devs;
+static int nr_media_devs;
+
+static dma_addr_t media_base[NR_BANKS];
+
+static struct s5p_media_device *s5p_get_media_device(int dev_id, int bank)
+{
+ struct s5p_media_device *mdev = NULL;
+ int i = 0, found = 0;
+
+ if (dev_id < 0)
+ return NULL;
+
+ while (!found && (i < nr_media_devs)) {
+ mdev = &media_devs[i];
+ if (mdev->id == dev_id && mdev->bank == bank)
+ found = 1;
+ else
+ i++;
+ }
+
+ if (!found)
+ mdev = NULL;
+
+ return mdev;
+}
+
+dma_addr_t s5p_get_media_memory_bank(int dev_id, int bank)
+{
+ struct s5p_media_device *mdev;
+
+ mdev = s5p_get_media_device(dev_id, bank);
+ if (!mdev) {
+ printk(KERN_ERR "invalid media device\n");
+ return 0;
+ }
+
+ if (!mdev->paddr) {
+ printk(KERN_ERR "no memory for %s\n", mdev->name);
+ return 0;
+ }
+
+ return mdev->paddr;
+}
+EXPORT_SYMBOL(s5p_get_media_memory_bank);
+
+size_t s5p_get_media_memsize_bank(int dev_id, int bank)
+{
+ struct s5p_media_device *mdev;
+
+ mdev = s5p_get_media_device(dev_id, bank);
+ if (!mdev) {
+ printk(KERN_ERR "invalid media device\n");
+ return 0;
+ }
+
+ return mdev->memsize;
+}
+EXPORT_SYMBOL(s5p_get_media_memsize_bank);
+
+dma_addr_t s5p_get_media_membase_bank(int bank)
+{
+ if (bank > meminfo.nr_banks) {
+ printk(KERN_ERR "invalid bank.\n");
+ return -EINVAL;
+ }
+
+ return media_base[bank];
+}
+EXPORT_SYMBOL(s5p_get_media_membase_bank);
+
+void s5p_reserve_bootmem(struct s5p_media_device *mdevs,
+ int nr_mdevs, size_t boundary)
+{
+ struct s5p_media_device *mdev;
+ u64 start, end;
+ int i, ret;
+
+ media_devs = mdevs;
+ nr_media_devs = nr_mdevs;
+
+ for (i = 0; i < meminfo.nr_banks; i++)
+ media_base[i] = meminfo.bank[i].start + meminfo.bank[i].size;
+
+ for (i = 0; i < nr_media_devs; i++) {
+ mdev = &media_devs[i];
+ if (mdev->memsize <= 0)
+ continue;
+
+ if (!mdev->paddr) {
+ start = meminfo.bank[mdev->bank].start;
+ end = start + meminfo.bank[mdev->bank].size;
+
+ if (boundary && (boundary < end - start))
+ start = end - boundary;
+
+ mdev->paddr = memblock_find_in_range(start, end,
+ mdev->memsize, PAGE_SIZE);
+ }
+
+ ret = memblock_remove(mdev->paddr, mdev->memsize);
+ if (ret < 0)
+ pr_err("memblock_reserve(%x, %x) failed\n",
+ mdev->paddr, mdev->memsize);
+
+ if (media_base[mdev->bank] > mdev->paddr)
+ media_base[mdev->bank] = mdev->paddr;
+
+ printk(KERN_INFO "s5p: %lu bytes system memory reserved "
+ "for %s at 0x%08x, %d-bank base(0x%08x)\n",
+ (unsigned long) mdev->memsize, mdev->name, mdev->paddr,
+ mdev->bank, media_base[mdev->bank]);
+ }
+}
+
+/* FIXME: temporary implementation to avoid compile error */
+int dma_needs_bounce(struct device *dev, dma_addr_t addr, size_t size)
+{
+ return 0;
+}
+
+
diff --git a/arch/arm/plat-s5p/clock.c b/arch/arm/plat-s5p/clock.c
index 8d081d9..10037b3 100644
--- a/arch/arm/plat-s5p/clock.c
+++ b/arch/arm/plat-s5p/clock.c
@@ -38,6 +38,13 @@ struct clk clk_ext_xtal_mux = {
struct clk clk_xusbxti = {
.name = "xusbxti",
.id = -1,
+ .rate = 24000000,
+};
+
+struct clk clk_xrtcxti = {
+ .name = "xrtcxti",
+ .id = -1,
+ .rate = 32768,
};
struct clk s5p_clk_27m = {
@@ -170,6 +177,8 @@ unsigned long s5p_epll_get_rate(struct clk *clk)
static struct clk *s5p_clks[] __initdata = {
&clk_ext_xtal_mux,
+ &clk_xrtcxti,
+ &clk_xusbxti,
&clk_48m,
&s5p_clk_27m,
&clk_fout_apll,
@@ -178,7 +187,6 @@ static struct clk *s5p_clks[] __initdata = {
&clk_fout_dpll,
&clk_fout_vpll,
&clk_vpll,
- &clk_xusbxti,
};
void __init s5p_register_clocks(unsigned long xtal_freq)
diff --git a/arch/arm/plat-s5p/dev-csis0.c b/arch/arm/plat-s5p/dev-csis0.c
index e3aabef..f61317c 100644
--- a/arch/arm/plat-s5p/dev-csis0.c
+++ b/arch/arm/plat-s5p/dev-csis0.c
@@ -11,6 +11,9 @@
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
+
+#include <plat/csis.h>
+#include <plat/mipi_csis.h>
#include <mach/map.h>
static struct resource s5p_mipi_csis0_resource[] = {
@@ -32,3 +35,26 @@ struct platform_device s5p_device_mipi_csis0 = {
.num_resources = ARRAY_SIZE(s5p_mipi_csis0_resource),
.resource = s5p_mipi_csis0_resource,
};
+
+static struct s3c_platform_csis default_csis_data __initdata = {
+ .srclk_name = "mout_mpll",
+ .clk_name = "sclk_csis",
+ .clk_rate = 166000000,
+};
+
+void __init s3c_csis_set_platdata(struct s3c_platform_csis *pd)
+{
+ struct s3c_platform_csis *npd;
+
+ if (!pd)
+ pd = &default_csis_data;
+
+ npd = kmemdup(pd, sizeof(struct s3c_platform_csis), GFP_KERNEL);
+ if (!npd)
+ printk(KERN_ERR "%s: no memory for platform data\n", __func__);
+
+ npd->cfg_gpio = NULL;
+ npd->cfg_phy_global = s5p_csis_phy_enable;
+
+ s5p_device_mipi_csis0.dev.platform_data = npd;
+}
diff --git a/arch/arm/plat-s5p/dev-mfc.c b/arch/arm/plat-s5p/dev-mfc.c
new file mode 100644
index 0000000..62d9f21
--- /dev/null
+++ b/arch/arm/plat-s5p/dev-mfc.c
@@ -0,0 +1,65 @@
+/* arch/arm/plat-s5p/dev-mfc.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Device definition for MFC device
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <mach/map.h>
+#include <asm/irq.h>
+#include <plat/mfc.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+#include <plat/media.h>
+#include <mach/media.h>
+
+static struct s3c_platform_mfc s3c_mfc_pdata = {
+ .buf_phy_base[0] = 0,
+ .buf_phy_base[1] = 0,
+ .buf_phy_size[0] = 0,
+ .buf_phy_size[1] = 0,
+};
+
+static struct resource s3c_mfc_resources[] = {
+ [0] = {
+ .start = S5PV210_PA_MFC,
+ .end = S5PV210_PA_MFC + S5PV210_SZ_MFC - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_MFC,
+ .end = IRQ_MFC,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+struct platform_device s3c_device_mfc = {
+ .name = "s3c-mfc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_mfc_resources),
+ .resource = s3c_mfc_resources,
+ .dev = {
+ .platform_data = &s3c_mfc_pdata,
+ },
+};
+
+void __init s3c_mfc_set_platdata(struct s3c_platform_mfc *pd)
+{
+ s3c_mfc_pdata.buf_phy_base[0] =
+ (u32)s5p_get_media_memory_bank(S5P_MDEV_MFC, 0);
+ s3c_mfc_pdata.buf_phy_size[0] =
+ (u32)s5p_get_media_memsize_bank(S5P_MDEV_MFC, 0);
+ s3c_mfc_pdata.buf_phy_base[1] =
+ (u32)s5p_get_media_memory_bank(S5P_MDEV_MFC, 1);
+ s3c_mfc_pdata.buf_phy_size[1] =
+ (u32)s5p_get_media_memsize_bank(S5P_MDEV_MFC, 1);
+}
+
diff --git a/arch/arm/plat-s5p/devs.c b/arch/arm/plat-s5p/devs.c
new file mode 100644
index 0000000..a5bacca
--- /dev/null
+++ b/arch/arm/plat-s5p/devs.c
@@ -0,0 +1,713 @@
+/* linux/arch/arm/plat-s5p/devs.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Base S5P platform device definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+#include <mach/hardware.h>
+#include <mach/map.h>
+#include <mach/dma.h>
+#include <mach/adc.h>
+
+
+#include <plat/devs.h>
+#include <plat/gpio-cfg.h>
+#include <plat/irqs.h>
+#include <plat/fb.h>
+#include <plat/fimc.h>
+#include <plat/csis.h>
+#include <plat/media.h>
+#include <plat/jpeg.h>
+#include <mach/media.h>
+#include <s3cfb.h>
+
+#if defined CONFIG_USB_S3C_OTG_HOST
+/* USB Device (OTG hcd)*/
+static struct resource s3c_usb_otghcd_resource[] = {
+ [0] = {
+ .start = S3C_PA_OTG,
+ .end = S3C_PA_OTG + S3C_SZ_OTG - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_OTG,
+ .end = IRQ_OTG,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static u64 s3c_device_usb_otghcd_dmamask = 0xffffffffUL;
+
+struct platform_device s3c_device_usb_otghcd = {
+ .name = "s3c_otghcd",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_usb_otghcd_resource),
+ .resource = s3c_usb_otghcd_resource,
+ .dev = {
+ .dma_mask = &s3c_device_usb_otghcd_dmamask,
+ .coherent_dma_mask = 0xffffffffUL
+ }
+};
+
+EXPORT_SYMBOL(s3c_device_usb_otghcd);
+#endif
+
+#if defined CONFIG_USB_DWC_OTG
+/* USB Device (OTG hcd)*/
+static struct resource s3c_usb_dwcotg_resource[] = {
+ [0] = {
+ .start = S3C_PA_OTG,
+ .end = S3C_PA_OTG + S3C_SZ_OTG - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_OTG,
+ .end = IRQ_OTG,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static u64 s3c_device_usb_dwcotg_dmamask = 0xffffffffUL;
+
+struct platform_device s3c_device_usb_dwcotg = {
+ .name = "dwc_otg",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_usb_dwcotg_resource),
+ .resource = s3c_usb_dwcotg_resource,
+ .dev = {
+ .dma_mask = &s3c_device_usb_dwcotg_dmamask,
+ .coherent_dma_mask = 0xffffffffUL
+ }
+};
+
+EXPORT_SYMBOL(s3c_device_usb_dwcotg);
+#endif
+
+/* RTC */
+static struct resource s5p_rtc_resource[] = {
+ [0] = {
+ .start = S3C_PA_RTC,
+ .end = S3C_PA_RTC + 0xff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_RTC_ALARM,
+ .end = IRQ_RTC_ALARM,
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .start = IRQ_RTC_TIC,
+ .end = IRQ_RTC_TIC,
+ .flags = IORESOURCE_IRQ
+ }
+};
+
+struct platform_device s5p_device_rtc = {
+ .name = "s3c2410-rtc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s5p_rtc_resource),
+ .resource = s5p_rtc_resource,
+};
+
+#ifdef CONFIG_S5P_ADC
+/* ADCTS */
+static struct resource s3c_adc_resource[] = {
+ [0] = {
+ .start = SAMSUNG_PA_ADC,
+ .end = SAMSUNG_PA_ADC + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_PENDN,
+ .end = IRQ_PENDN,
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .start = IRQ_ADC,
+ .end = IRQ_ADC,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+struct platform_device s3c_device_adc = {
+ .name = "s3c-adc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_adc_resource),
+ .resource = s3c_adc_resource,
+};
+
+void __init s3c_adc_set_platdata(struct s3c_adc_mach_info *pd)
+{
+ struct s3c_adc_mach_info *npd;
+
+ npd = kmalloc(sizeof(*npd), GFP_KERNEL);
+ if (npd) {
+ memcpy(npd, pd, sizeof(*npd));
+ s3c_device_adc.dev.platform_data = npd;
+ } else {
+ printk(KERN_ERR "no memory for ADC platform data\n");
+ }
+}
+#endif /* CONFIG_S5P_ADC */
+
+#if defined(CONFIG_VIDEO_MFC51) || defined(CONFIG_VIDEO_MFC50)
+static struct resource s5p_mfc_resources[] = {
+ [0] = {
+ .start = S5P_PA_MFC,
+ .end = S5P_PA_MFC + S5P_SZ_MFC - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_MFC,
+ .end = IRQ_MFC,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+struct platform_device s5p_device_mfc = {
+ .name = "mfc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s5p_mfc_resources),
+ .resource = s5p_mfc_resources,
+};
+#endif
+
+#if defined(CONFIG_S5P_DEV_FB)
+static struct resource s3cfb_resource[] = {
+ [0] = {
+ .start = S5P_PA_LCD,
+ .end = S5P_PA_LCD + S5P_SZ_LCD - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_LCD1,
+ .end = IRQ_LCD1,
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .start = IRQ_LCD0,
+ .end = IRQ_LCD0,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static u64 fb_dma_mask = 0xffffffffUL;
+
+struct platform_device s3c_device_fb = {
+ .name = "s3cfb",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3cfb_resource),
+ .resource = s3cfb_resource,
+ .dev = {
+ .dma_mask = &fb_dma_mask,
+ .coherent_dma_mask = 0xffffffffUL
+ }
+};
+
+static struct s3c_platform_fb default_fb_data __initdata = {
+#if defined(CONFIG_CPU_S5PV210_EVT0)
+ .hw_ver = 0x60,
+#else
+ .hw_ver = 0x62,
+#endif
+ .nr_wins = 5,
+ .default_win = CONFIG_FB_S3C_DEFAULT_WINDOW,
+ .swap = FB_SWAP_WORD | FB_SWAP_HWORD,
+};
+
+void __init s3cfb_set_platdata(struct s3c_platform_fb *pd)
+{
+ struct s3c_platform_fb *npd;
+ struct s3cfb_lcd *lcd;
+ phys_addr_t pmem_start;
+ int i, default_win, num_overlay_win;
+ int frame_size;
+
+ if (!pd)
+ pd = &default_fb_data;
+
+ npd = kmemdup(pd, sizeof(struct s3c_platform_fb), GFP_KERNEL);
+ if (!npd)
+ printk(KERN_ERR "%s: no memory for platform data\n", __func__);
+ else {
+ for (i = 0; i < npd->nr_wins; i++)
+ npd->nr_buffers[i] = 1;
+
+ default_win = npd->default_win;
+ num_overlay_win = CONFIG_FB_S3C_NUM_OVLY_WIN;
+
+ if (num_overlay_win >= default_win) {
+ printk(KERN_WARNING "%s: NUM_OVLY_WIN should be less than default \
+ window number. set to 0.\n", __func__);
+ num_overlay_win = 0;
+ }
+
+ for (i = 0; i < num_overlay_win; i++)
+ npd->nr_buffers[i] = CONFIG_FB_S3C_NUM_BUF_OVLY_WIN;
+ npd->nr_buffers[default_win] = CONFIG_FB_S3C_NR_BUFFERS;
+
+ lcd = (struct s3cfb_lcd *)npd->lcd;
+ frame_size = (lcd->width * lcd->height * 4);
+
+ s3cfb_get_clk_name(npd->clk_name);
+ npd->backlight_onoff = NULL;
+ npd->clk_on = s3cfb_clk_on;
+ npd->clk_off = s3cfb_clk_off;
+
+ /* set starting physical address & size of memory region for overlay
+ * window */
+ pmem_start = s5p_get_media_memory_bank(S5P_MDEV_FIMD, 1);
+ for (i = 0; i < num_overlay_win; i++) {
+ npd->pmem_start[i] = pmem_start;
+ npd->pmem_size[i] = frame_size * npd->nr_buffers[i];
+ pmem_start += npd->pmem_size[i];
+ }
+
+ /* set starting physical address & size of memory region for default
+ * window */
+ npd->pmem_start[default_win] = pmem_start;
+ npd->pmem_size[default_win] = frame_size * npd->nr_buffers[default_win];
+
+ s3c_device_fb.dev.platform_data = npd;
+ }
+}
+#endif
+
+#if defined(CONFIG_VIDEO_FIMC) || defined(CONFIG_CPU_FREQ) /* TODO: use existing dev */
+static struct resource s3c_fimc0_resource[] = {
+ [0] = {
+ .start = S5P_PA_FIMC0,
+ .end = S5P_PA_FIMC0 + S5P_SZ_FIMC0 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_FIMC0,
+ .end = IRQ_FIMC0,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device s3c_device_fimc0 = {
+ .name = "s3c-fimc",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(s3c_fimc0_resource),
+ .resource = s3c_fimc0_resource,
+};
+
+static struct s3c_platform_fimc default_fimc0_data __initdata = {
+ .default_cam = CAMERA_PAR_A,
+ .hw_ver = 0x45,
+};
+
+void __init s3c_fimc0_set_platdata(struct s3c_platform_fimc *pd)
+{
+ struct s3c_platform_fimc *npd;
+
+ if (!pd)
+ pd = &default_fimc0_data;
+
+ npd = kmemdup(pd, sizeof(struct s3c_platform_fimc), GFP_KERNEL);
+ if (!npd)
+ printk(KERN_ERR "%s: no memory for platform data\n", __func__);
+ else {
+ if (!npd->cfg_gpio)
+ npd->cfg_gpio = s3c_fimc0_cfg_gpio;
+
+ if (!npd->clk_on)
+ npd->clk_on = s3c_fimc_clk_on;
+
+ if (!npd->clk_off)
+ npd->clk_off = s3c_fimc_clk_off;
+
+ npd->hw_ver = 0x45;
+
+ /* starting physical address of memory region */
+ npd->pmem_start = s5p_get_media_memory_bank(S5P_MDEV_FIMC0, 1);
+ /* size of memory region */
+ npd->pmem_size = s5p_get_media_memsize_bank(S5P_MDEV_FIMC0, 1);
+
+ s3c_device_fimc0.dev.platform_data = npd;
+ }
+}
+
+static struct resource s3c_fimc1_resource[] = {
+ [0] = {
+ .start = S5P_PA_FIMC1,
+ .end = S5P_PA_FIMC1 + S5P_SZ_FIMC1 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_FIMC1,
+ .end = IRQ_FIMC1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device s3c_device_fimc1 = {
+ .name = "s3c-fimc",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(s3c_fimc1_resource),
+ .resource = s3c_fimc1_resource,
+};
+
+static struct s3c_platform_fimc default_fimc1_data __initdata = {
+ .default_cam = CAMERA_PAR_A,
+ .hw_ver = 0x50,
+};
+
+void __init s3c_fimc1_set_platdata(struct s3c_platform_fimc *pd)
+{
+ struct s3c_platform_fimc *npd;
+
+ if (!pd)
+ pd = &default_fimc1_data;
+
+ npd = kmemdup(pd, sizeof(struct s3c_platform_fimc), GFP_KERNEL);
+ if (!npd)
+ printk(KERN_ERR "%s: no memory for platform data\n", __func__);
+ else {
+ if (!npd->cfg_gpio)
+ npd->cfg_gpio = s3c_fimc1_cfg_gpio;
+
+ if (!npd->clk_on)
+ npd->clk_on = s3c_fimc_clk_on;
+
+ if (!npd->clk_off)
+ npd->clk_off = s3c_fimc_clk_off;
+
+ npd->hw_ver = 0x50;
+
+ /* starting physical address of memory region */
+ npd->pmem_start = s5p_get_media_memory_bank(S5P_MDEV_FIMC1, 1);
+ /* size of memory region */
+ npd->pmem_size = s5p_get_media_memsize_bank(S5P_MDEV_FIMC1, 1);
+
+ s3c_device_fimc1.dev.platform_data = npd;
+ }
+}
+
+static struct resource s3c_fimc2_resource[] = {
+ [0] = {
+ .start = S5P_PA_FIMC2,
+ .end = S5P_PA_FIMC2 + S5P_SZ_FIMC2 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_FIMC2,
+ .end = IRQ_FIMC2,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device s3c_device_fimc2 = {
+ .name = "s3c-fimc",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(s3c_fimc2_resource),
+ .resource = s3c_fimc2_resource,
+};
+
+static struct s3c_platform_fimc default_fimc2_data __initdata = {
+ .default_cam = CAMERA_PAR_A,
+ .hw_ver = 0x45,
+};
+
+void __init s3c_fimc2_set_platdata(struct s3c_platform_fimc *pd)
+{
+ struct s3c_platform_fimc *npd;
+
+ if (!pd)
+ pd = &default_fimc2_data;
+
+ npd = kmemdup(pd, sizeof(struct s3c_platform_fimc), GFP_KERNEL);
+ if (!npd)
+ printk(KERN_ERR "%s: no memory for platform data\n", __func__);
+ else {
+ if (!npd->cfg_gpio)
+ npd->cfg_gpio = s3c_fimc2_cfg_gpio;
+
+ if (!npd->clk_on)
+ npd->clk_on = s3c_fimc_clk_on;
+
+ if (!npd->clk_off)
+ npd->clk_off = s3c_fimc_clk_off;
+
+ npd->hw_ver = 0x45;
+
+ /* starting physical address of memory region */
+ npd->pmem_start = s5p_get_media_memory_bank(S5P_MDEV_FIMC2, 1);
+ /* size of memory region */
+ npd->pmem_size = s5p_get_media_memsize_bank(S5P_MDEV_FIMC2, 1);
+
+ s3c_device_fimc2.dev.platform_data = npd;
+ }
+}
+
+static struct resource s3c_ipc_resource[] = {
+ [0] = {
+ .start = S5P_PA_IPC,
+ .end = S5P_PA_IPC + S5P_SZ_IPC - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+struct platform_device s3c_device_ipc = {
+ .name = "s3c-ipc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_ipc_resource),
+ .resource = s3c_ipc_resource,
+};
+#endif
+
+/* JPEG controller */
+static struct s3c_platform_jpeg default_jpeg_data __initdata = {
+ .max_main_width = 2560,
+ .max_main_height = 1920,
+ .max_thumb_width = 0,
+ .max_thumb_height = 0,
+};
+
+void __init s3c_jpeg_set_platdata(struct s3c_platform_jpeg *pd)
+{
+ struct s3c_platform_jpeg *npd;
+
+ if (!pd)
+ pd = &default_jpeg_data;
+
+ npd = kmemdup(pd, sizeof(struct s3c_platform_jpeg), GFP_KERNEL);
+ if (!npd)
+ printk(KERN_ERR "%s: no memory for platform data\n", __func__);
+ else
+ s3c_device_jpeg.dev.platform_data = npd;
+}
+
+static struct resource s3c_jpeg_resource[] = {
+ [0] = {
+ .start = S5PV210_PA_JPEG,
+ .end = S5PV210_PA_JPEG + S5PV210_SZ_JPEG - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_JPEG,
+ .end = IRQ_JPEG,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+struct platform_device s3c_device_jpeg = {
+ .name = "s3c-jpg",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_jpeg_resource),
+ .resource = s3c_jpeg_resource,
+};
+
+/* G3D */
+struct platform_device s3c_device_g3d = {
+ .name = "pvrsrvkm",
+ .id = -1,
+};
+
+struct platform_device s3c_device_lcd = {
+ .name = "s3c_lcd",
+ .id = -1,
+};
+
+/* rotator interface */
+static struct resource s5p_rotator_resource[] = {
+ [0] = {
+ .start = S5P_PA_ROTATOR,
+ .end = S5P_PA_ROTATOR + S5P_SZ_ROTATOR - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_ROTATOR,
+ .end = IRQ_ROTATOR,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+struct platform_device s5p_device_rotator = {
+ .name = "s5p-rotator",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s5p_rotator_resource),
+ .resource = s5p_rotator_resource
+};
+
+/* TVOUT interface */
+static struct resource s5p_tvout_resources[] = {
+ [0] = {
+ .start = S5P_PA_TVENC,
+ .end = S5P_PA_TVENC + S5P_SZ_TVENC - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = S5P_PA_VP,
+ .end = S5P_PA_VP + S5P_SZ_VP - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .start = S5P_PA_MIXER,
+ .end = S5P_PA_MIXER + S5P_SZ_MIXER - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [3] = {
+ .start = S5P_PA_HDMI,
+ .end = S5P_PA_HDMI + S5P_SZ_HDMI - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [4] = {
+ .start = S5P_I2C_HDMI_PHY,
+ .end = S5P_I2C_HDMI_PHY + S5P_I2C_HDMI_SZ_PHY - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [5] = {
+ .start = IRQ_MIXER,
+ .end = IRQ_MIXER,
+ .flags = IORESOURCE_IRQ,
+ },
+ [6] = {
+ .start = IRQ_HDMI,
+ .end = IRQ_HDMI,
+ .flags = IORESOURCE_IRQ,
+ },
+ [7] = {
+ .start = IRQ_TVENC,
+ .end = IRQ_TVENC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device s5p_device_tvout = {
+ .name = "s5p-tvout",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s5p_tvout_resources),
+ .resource = s5p_tvout_resources,
+};
+
+/* CEC */
+static struct resource s5p_cec_resources[] = {
+ [0] = {
+ .start = S5P_PA_CEC,
+ .end = S5P_PA_CEC + S5P_SZ_CEC - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_CEC,
+ .end = IRQ_CEC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device s5p_device_cec = {
+ .name = "s5p-cec",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s5p_cec_resources),
+ .resource = s5p_cec_resources,
+};
+
+/* HPD */
+struct platform_device s5p_device_hpd = {
+ .name = "s5p-hpd",
+ .id = -1,
+};
+
+#ifdef CONFIG_USB_SUPPORT
+#ifdef CONFIG_USB_ARCH_HAS_EHCI
+ /* USB Host Controlle EHCI registrations */
+static struct resource s3c_usb__ehci_resource[] = {
+ [0] = {
+ .start = S5P_PA_USB_EHCI,
+ .end = S5P_PA_USB_EHCI + S5P_SZ_USB_EHCI - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_UHOST,
+ .end = IRQ_UHOST,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static u64 s3c_device_usb_ehci_dmamask = 0xffffffffUL;
+
+struct platform_device s3c_device_usb_ehci = {
+ .name = "s5p-ehci",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_usb__ehci_resource),
+ .resource = s3c_usb__ehci_resource,
+ .dev = {
+ .dma_mask = &s3c_device_usb_ehci_dmamask,
+ .coherent_dma_mask = 0xffffffffUL
+ }
+};
+#endif /* CONFIG_USB_ARCH_HAS_EHCI */
+
+#ifdef CONFIG_USB_ARCH_HAS_OHCI
+/* USB Host Controlle OHCI registrations */
+static struct resource s3c_usb__ohci_resource[] = {
+ [0] = {
+ .start = S5P_PA_USB_OHCI,
+ .end = S5P_PA_USB_OHCI + S5P_SZ_USB_OHCI - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_UHOST,
+ .end = IRQ_UHOST,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static u64 s3c_device_usb_ohci_dmamask = 0xffffffffUL;
+
+struct platform_device s3c_device_usb_ohci = {
+ .name = "s5p-ohci",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_usb__ohci_resource),
+ .resource = s3c_usb__ohci_resource,
+ .dev = {
+ .dma_mask = &s3c_device_usb_ohci_dmamask,
+ .coherent_dma_mask = 0xffffffffUL
+ }
+};
+#endif /* CONFIG_USB_ARCH_HAS_EHCI */
+
+/* USB Device (Gadget)*/
+static struct resource s3c_usbgadget_resource[] = {
+ [0] = {
+ .start = S3C_PA_OTG,
+ .end = S3C_PA_OTG + S3C_SZ_OTG - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_OTG,
+ .end = IRQ_OTG,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+struct platform_device s3c_device_usbgadget = {
+ .name = "s3c-usbgadget",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_usbgadget_resource),
+ .resource = s3c_usbgadget_resource,
+};
+#endif
+
diff --git a/arch/arm/plat-s5p/hr-time-rtc.c b/arch/arm/plat-s5p/hr-time-rtc.c
new file mode 100644
index 0000000..9dfc727
--- /dev/null
+++ b/arch/arm/plat-s5p/hr-time-rtc.c
@@ -0,0 +1,512 @@
+/*
+ * linux/arch/arm/plat-s5p/hr-time-rtc.c
+ *
+ * S5P Timers
+ *
+ * Copyright (c) 2006 Samsung Electronics
+ *
+ *
+ * S5P (and compatible) HRT support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <mach/hardware.h>
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+#include <asm/mach-types.h>
+#include <mach/map.h>
+#include <plat/regs-timer.h>
+#include <plat/regs-rtc.h>
+#include <plat/regs-systimer.h>
+#include <mach/regs-irq.h>
+#include <mach/regs-clock.h>
+#include <mach/tick.h>
+
+#include <plat/clock.h>
+#include <plat/cpu.h>
+
+static unsigned long long time_stamp;
+static unsigned long long s5p_sched_timer_overflows;
+static unsigned long long old_overflows;
+static cycle_t last_ticks;
+
+/* Sched timer interrupt is not processed right after
+ * timer counter expired
+ */
+static unsigned int pending_irq;
+#define USE_SYSTIMER_IRQ
+
+/* sched_timer_running
+ * 0 : sched timer stopped or not initialized
+ * 1 : sched timer started
+ */
+static unsigned int sched_timer_running;
+
+void __iomem *rtc_base = S5P_VA_RTC;
+static struct clk *clk_event;
+static struct clk *clk_sched;
+static int tick_timer_mode; /* 0: oneshot, 1: autoreload */
+
+#define RTC_CLOCK (32768)
+#define RTC_DEFAULT_TICK ((RTC_CLOCK / HZ) - 1)
+/*
+ * Helper functions
+ * s5p_systimer_read() : Read from System timer register
+ * s5p_systimer_write(): Write to System timer register
+ *
+ */
+static unsigned int s5p_systimer_read(unsigned int *reg_offset)
+{
+ return __raw_readl(reg_offset);
+}
+
+static unsigned int s5p_systimer_write(unsigned int *reg_offset,
+ unsigned int value)
+{
+ unsigned int temp_regs;
+
+ __raw_writel(value, reg_offset);
+
+ if (reg_offset == S5P_SYSTIMER_TCON) {
+ while (!(__raw_readl(S5P_SYSTIMER_INT_CSTAT) &
+ S5P_SYSTIMER_INT_TCON))
+ ;
+ temp_regs = __raw_readl(S5P_SYSTIMER_INT_CSTAT);
+ temp_regs |= S5P_SYSTIMER_INT_TCON;
+ __raw_writel(temp_regs, S5P_SYSTIMER_INT_CSTAT);
+
+ } else if (reg_offset == S5P_SYSTIMER_ICNTB) {
+ while (!(__raw_readl(S5P_SYSTIMER_INT_CSTAT) &
+ S5P_SYSTIMER_INT_ICNTB))
+ ;
+ temp_regs = __raw_readl(S5P_SYSTIMER_INT_CSTAT);
+ temp_regs |= S5P_SYSTIMER_INT_ICNTB;
+ __raw_writel(temp_regs, S5P_SYSTIMER_INT_CSTAT);
+
+ } else if (reg_offset == S5P_SYSTIMER_TICNTB) {
+ while (!(__raw_readl(S5P_SYSTIMER_INT_CSTAT) &
+ S5P_SYSTIMER_INT_TICNTB))
+ ;
+ temp_regs = __raw_readl(S5P_SYSTIMER_INT_CSTAT);
+ temp_regs |= S5P_SYSTIMER_INT_TICNTB;
+ __raw_writel(temp_regs, S5P_SYSTIMER_INT_CSTAT);
+ }
+
+ return 0;
+}
+
+unsigned int get_rtc_cnt(void)
+{
+ unsigned int ticcnt, current_cnt, rtccnt;
+
+ ticcnt = __raw_readl(rtc_base + S3C2410_TICNT);
+ current_cnt = __raw_readl(rtc_base + S3C2410_CURTICCNT);
+ rtccnt = ticcnt - current_cnt;
+
+ return rtccnt;
+}
+
+static void s5p_tick_timer_setup(void);
+
+static void s5p_tick_timer_start(unsigned long load_val,
+ int autoreset)
+{
+ unsigned int tmp;
+
+ tmp = __raw_readl(rtc_base + S3C2410_RTCCON) &
+ ~(S3C_RTCCON_TICEN);
+ __raw_writel(tmp, rtc_base + S3C2410_RTCCON);
+
+ __raw_writel(load_val, rtc_base + S3C2410_TICNT);
+
+ tmp |= S3C_RTCCON_TICEN;
+
+ __raw_writel(tmp, rtc_base + S3C2410_RTCCON);
+}
+
+static inline void s5p_tick_timer_stop(void)
+{
+ unsigned int tmp;
+
+ tmp = __raw_readl(rtc_base + S3C2410_RTCCON) &
+ ~(S3C_RTCCON_TICEN);
+
+ __raw_writel(tmp, rtc_base + S3C2410_RTCCON);
+}
+
+static void s5p_sched_timer_start(unsigned long load_val,
+ int autoreset)
+{
+ unsigned long tcon;
+ unsigned long tcnt;
+ unsigned long tcfg;
+
+ tcnt = TICK_MAX; /* default value for tcnt */
+
+ /* initialize system timer clock */
+ tcfg = s5p_systimer_read(S5P_SYSTIMER_TCFG);
+
+ tcfg &= ~S5P_SYSTIMER_TCLK_MASK;
+ tcfg |= S5P_SYSTIMER_TCLK_USB;
+
+ s5p_systimer_write(S5P_SYSTIMER_TCFG, tcfg);
+
+ /* TCFG must not be changed at run-time.
+ * If you want to change TCFG, stop timer(TCON[0] = 0)
+ */
+ s5p_systimer_write(S5P_SYSTIMER_TCON, 0);
+
+ /* read the current timer configuration bits */
+ tcon = s5p_systimer_read(S5P_SYSTIMER_TCON);
+ tcfg = s5p_systimer_read(S5P_SYSTIMER_TCFG);
+
+ tcfg &= ~S5P_SYSTIMER_TCLK_MASK;
+ tcfg |= S5P_SYSTIMER_TCLK_USB;
+ tcfg &= ~S5P_SYSTIMER_PRESCALER_MASK;
+
+ /* check to see if timer is within 16bit range... */
+ if (tcnt > TICK_MAX) {
+ panic("setup_timer: cannot configure timer!");
+ return;
+ }
+
+ s5p_systimer_write(S5P_SYSTIMER_TCFG, tcfg);
+
+ s5p_systimer_write(S5P_SYSTIMER_TICNTB, tcnt);
+
+#if !defined(USE_SYSTIMER_IRQ)
+ /* set timer con */
+ tcon = (S5P_SYSTIMER_START | S5P_SYSTIMER_AUTO_RELOAD);
+ s5p_systimer_write(S5P_SYSTIMER_TCON, tcon);
+#else
+ /* set timer con */
+ tcon = S5P_SYSTIMER_INT_AUTO | S5P_SYSTIMER_START |
+ S5P_SYSTIMER_AUTO_RELOAD;
+ s5p_systimer_write(S5P_SYSTIMER_TCON, tcon);
+
+ tcon |= S5P_SYSTIMER_INT_START;
+ s5p_systimer_write(S5P_SYSTIMER_TCON, tcon);
+
+ /* Interrupt Start and Enable */
+ s5p_systimer_write(S5P_SYSTIMER_INT_CSTAT,
+ (S5P_SYSTIMER_INT_ICNTEIE |
+ S5P_SYSTIMER_INT_INTENABLE));
+#endif
+ sched_timer_running = 1;
+}
+
+/*
+ * RTC tick : count down to zero, interrupt, reload
+ */
+static int s5p_tick_set_next_event(unsigned long cycles,
+ struct clock_event_device *evt)
+{
+ /* printk(KERN_INFO "%d\n", cycles); */
+ if (cycles == 0) /* Should be larger than 0 */
+ cycles = 1;
+ s5p_tick_timer_start(cycles, 0);
+ return 0;
+}
+
+static void s5p_tick_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ tick_timer_mode = 1;
+ break;
+ case CLOCK_EVT_MODE_ONESHOT:
+ s5p_tick_timer_stop();
+ tick_timer_mode = 0;
+ break;
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ /* Sched timer stopped */
+ sched_timer_running = 0;
+
+ /* Reset sched_clock variables after sleep/wakeup */
+ last_ticks = 0;
+ s5p_sched_timer_overflows = 0;
+ old_overflows = 0;
+ pending_irq = 0;
+ break;
+ case CLOCK_EVT_MODE_RESUME:
+ s5p_tick_timer_setup();
+ s5p_sched_timer_start(~0, 1);
+ break;
+ }
+}
+
+static struct clock_event_device clockevent_tick_timer = {
+ .name = "S5PC110 event timer",
+ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+ .shift = 32,
+ .set_next_event = s5p_tick_set_next_event,
+ .set_mode = s5p_tick_set_mode,
+};
+
+static irqreturn_t s5p_tick_timer_interrupt(int irq, void *dev_id)
+{
+ struct clock_event_device *evt = &clockevent_tick_timer;
+
+ __raw_writel(S3C_INTP_TIC, rtc_base + S3C_INTP);
+ /* In case of oneshot mode */
+ if (tick_timer_mode == 0)
+ s5p_tick_timer_stop();
+
+ evt->event_handler(evt);
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction s5p_tick_timer_irq = {
+ .name = "rtc-tick",
+ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+ .handler = s5p_tick_timer_interrupt,
+};
+
+static void s5p_init_dynamic_tick_timer(unsigned long rate)
+{
+ tick_timer_mode = 1;
+
+ s5p_tick_timer_stop();
+
+ s5p_tick_timer_start((rate / HZ) - 1, 1);
+
+ clockevent_tick_timer.mult = div_sc(rate, NSEC_PER_SEC,
+ clockevent_tick_timer.shift);
+ clockevent_tick_timer.max_delta_ns =
+ clockevent_delta2ns(-1, &clockevent_tick_timer);
+ clockevent_tick_timer.min_delta_ns =
+ clockevent_delta2ns(1, &clockevent_tick_timer);
+
+ clockevent_tick_timer.cpumask = cpumask_of(0);
+ clockevents_register_device(&clockevent_tick_timer);
+
+ printk(KERN_INFO "mult[%lu]\n",
+ (long unsigned int)clockevent_tick_timer.mult);
+ printk(KERN_INFO "max_delta_ns[%lu]\n",
+ (long unsigned int)clockevent_tick_timer.max_delta_ns);
+ printk(KERN_INFO "min_delta_ns[%lu]\n",
+ (long unsigned int)clockevent_tick_timer.min_delta_ns);
+ printk(KERN_INFO "rate[%lu]\n",
+ (long unsigned int)rate);
+ printk(KERN_INFO "HZ[%d]\n", HZ);
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * SYSTEM TIMER ... free running 32-bit clock source and scheduler clock
+ * ---------------------------------------------------------------------------
+ */
+irqreturn_t s5p_sched_timer_interrupt(int irq, void *dev_id)
+{
+ unsigned int temp_cstat;
+
+ temp_cstat = s5p_systimer_read(S5P_SYSTIMER_INT_CSTAT);
+ temp_cstat |= S5P_SYSTIMER_INT_INTCNT;
+
+ s5p_systimer_write(S5P_SYSTIMER_INT_CSTAT, temp_cstat);
+
+ if (unlikely(pending_irq))
+ pending_irq = 0;
+ else
+ s5p_sched_timer_overflows++;
+
+ return IRQ_HANDLED;
+}
+
+struct irqaction s5p_systimer_irq = {
+ .name = "System timer",
+ .flags = IRQF_DISABLED ,
+ .handler = s5p_sched_timer_interrupt,
+};
+
+
+static cycle_t s5p_sched_timer_read(struct clocksource *cs)
+{
+
+ return (cycle_t)~__raw_readl(S5P_SYSTIMER_TICNTO);
+}
+
+struct clocksource clocksource_s5p = {
+ .name = "clock_source_systimer",
+ .rating = 300,
+ .read = s5p_sched_timer_read,
+ .mask = CLOCKSOURCE_MASK(32),
+ .shift = 20,
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static void s5p_init_clocksource(unsigned long rate)
+{
+ static char err[] __initdata = KERN_ERR
+ "%s: can't register clocksource!\n";
+
+ clocksource_s5p.mult
+ = clocksource_khz2mult(rate/1000, clocksource_s5p.shift);
+
+ s5p_sched_timer_start(~0, 1);
+
+ if (clocksource_register(&clocksource_s5p))
+ printk(err, clocksource_s5p.name);
+}
+
+/*
+ * Returns current time from boot in nsecs. It's OK for this to wrap
+ * around for now, as it's just a relative time stamp.
+ */
+unsigned long long sched_clock(void)
+{
+ unsigned long irq_flags;
+ cycle_t ticks, elapsed_ticks = 0;
+ unsigned long long increment = 0;
+ unsigned int overflow_cnt = 0;
+
+ local_irq_save(irq_flags);
+
+ if (likely(sched_timer_running)) {
+ overflow_cnt = (s5p_sched_timer_overflows - old_overflows);
+ ticks = s5p_sched_timer_read(&clocksource_s5p);
+
+ if (overflow_cnt) {
+ increment = (overflow_cnt - 1) *
+ (clocksource_cyc2ns(clocksource_s5p.read(&clocksource_s5p),
+ clocksource_s5p.mult, clocksource_s5p.shift));
+ elapsed_ticks =
+ (clocksource_s5p.mask - last_ticks) + ticks;
+ } else {
+ if (unlikely(last_ticks > ticks)) {
+ pending_irq = 1;
+ elapsed_ticks =
+ (clocksource_s5p.mask - last_ticks) + ticks;
+ s5p_sched_timer_overflows++;
+ } else {
+ elapsed_ticks = (ticks - last_ticks);
+ }
+ }
+
+ time_stamp += (clocksource_cyc2ns(elapsed_ticks,
+ clocksource_s5p.mult,
+ clocksource_s5p.shift) + increment);
+
+ old_overflows = s5p_sched_timer_overflows;
+ last_ticks = ticks;
+ }
+ local_irq_restore(irq_flags);
+
+ return time_stamp;
+}
+
+/*
+ * Event/Sched Timer initialization
+ */
+static void s5p_timer_setup(void)
+{
+ unsigned long rate;
+ unsigned int tmp;
+
+ /* Setup event timer using XrtcXTI */
+ if (clk_event == NULL)
+ clk_event = clk_get(NULL, "xrtcxti");
+
+ if (IS_ERR(clk_event))
+ panic("failed to get clock for event timer");
+
+ rate = clk_get_rate(clk_event);
+
+ tmp = readl(rtc_base + S3C2410_RTCCON) &
+ ~(S3C_RTCCON_TICEN);
+
+ /* We only support 32768 Hz : [7:4] = 0x0 */
+ writel(tmp & ~0xf0, rtc_base + S3C2410_RTCCON);
+
+ s5p_init_dynamic_tick_timer(rate);
+
+ /* Setup sched-timer using XusbXTI */
+ if (clk_sched == NULL)
+ clk_sched = clk_get(NULL, "xusbxti");
+ if (IS_ERR(clk_sched))
+ panic("failed to get clock for sched-timer");
+ rate = clk_get_rate(clk_sched);
+
+ s5p_init_clocksource(rate);
+}
+
+static void s5p_tick_timer_setup(void)
+{
+ unsigned long rate;
+
+ rate = clk_get_rate(clk_event);
+ s5p_tick_timer_start((rate / HZ) - 1, 1);
+}
+
+static void __init s5p_timer_init(void)
+{
+
+ /* clock configuration setting and enable */
+ struct clk *clk_systimer;
+ struct clk *clk_rtc;
+
+ /* Initialize variables before starting each timers */
+ last_ticks = 0;
+ s5p_sched_timer_overflows = 0;
+ old_overflows = 0;
+ time_stamp = 0;
+ sched_timer_running = 0;
+ pending_irq = 0;
+
+ /* Setup system timer */
+ clk_systimer = clk_get(NULL, "systimer");
+ if (IS_ERR(clk_systimer))
+ panic("failed to get clock[%s] for system timer", "systimer");
+
+ clk_enable(clk_systimer);
+ clk_put(clk_systimer);
+
+ /* Setup rtc timer */
+ clk_rtc = clk_get(NULL, "rtc");
+ if (IS_ERR(clk_rtc))
+ panic("failed to get clock[%s] for system timer", "rtc");
+
+ clk_enable(clk_rtc);
+ clk_put(clk_rtc);
+
+ s5p_timer_setup();
+ setup_irq(IRQ_RTC_TIC, &s5p_tick_timer_irq);
+#if defined(USE_SYSTIMER_IRQ)
+ setup_irq(IRQ_SYSTIMER, &s5p_systimer_irq);
+#endif
+}
+
+struct sys_timer s5p_systimer = {
+ .init = s5p_timer_init,
+};
+
diff --git a/arch/arm/plat-s5p/include/plat/csis.h b/arch/arm/plat-s5p/include/plat/csis.h
new file mode 100644
index 0000000..23a9b527b
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/csis.h
@@ -0,0 +1,29 @@
+/* linux/arch/arm/plat-s5p/include/plat/csis.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * S5PV210 - Platform header file for MIPI-CSI2 driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_PLAT_CSIS_H
+#define __ASM_PLAT_CSIS_H __FILE__
+
+struct platform_device;
+
+struct s3c_platform_csis {
+ const char srclk_name[16];
+ const char clk_name[16];
+ unsigned long clk_rate;
+
+ void (*cfg_gpio)(void);
+ void (*cfg_phy_global)(int on);
+};
+
+extern void s3c_csis_set_platdata(struct s3c_platform_csis *csis);
+
+#endif /* __ASM_PLAT_CSIS_H */
diff --git a/arch/arm/plat-s5p/include/plat/fb.h b/arch/arm/plat-s5p/include/plat/fb.h
new file mode 100644
index 0000000..de4725b
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/fb.h
@@ -0,0 +1,127 @@
+/* linux/arch/arm/plat-s3c/include/plat/fb.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * http://armlinux.simtec.co.uk/
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C - FB platform data definitions
+ *
+ * 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 __PLAT_S3C_FB_H
+#define __PLAT_S3C_FB_H __FILE__
+
+#ifdef CONFIG_FB_S3C
+
+#define FB_SWAP_WORD (1 << 24)
+#define FB_SWAP_HWORD (1 << 16)
+#define FB_SWAP_BYTE (1 << 8)
+#define FB_SWAP_BIT (1 << 0)
+
+struct platform_device;
+struct clk;
+
+struct s3c_platform_fb {
+ int hw_ver;
+ char clk_name[16];
+ int nr_wins;
+ int nr_buffers[5];
+ int default_win;
+ int swap;
+ phys_addr_t pmem_start[5]; /* starting physical address of memory region */
+ size_t pmem_size[5]; /* size of memory region */
+ void *lcd;
+ void (*cfg_gpio)(struct platform_device *dev);
+ int (*backlight_on)(struct platform_device *dev);
+ int (*backlight_onoff)(struct platform_device *dev, int onoff);
+ int (*reset_lcd)(struct platform_device *dev);
+ int (*clk_on)(struct platform_device *pdev, struct clk **s3cfb_clk);
+ int (*clk_off)(struct platform_device *pdev, struct clk **clk);
+};
+
+extern void s3cfb_set_platdata(struct s3c_platform_fb *fimd);
+
+/* defined by architecture to configure gpio */
+extern void s3cfb_cfg_gpio(struct platform_device *pdev);
+extern int s3cfb_backlight_on(struct platform_device *pdev);
+extern int s3cfb_backlight_onoff(struct platform_device *pdev, int onoff);
+extern int s3cfb_reset_lcd(struct platform_device *pdev);
+extern int s3cfb_clk_on(struct platform_device *pdev, struct clk **s3cfb_clk);
+extern int s3cfb_clk_off(struct platform_device *pdev, struct clk **clk);
+extern void s3cfb_get_clk_name(char *clk_name);
+
+#else
+
+#ifdef CONFIG_S3C_FB
+
+/**
+ * struct s3c_fb_pd_win - per window setup data
+ * @win_mode: The display parameters to initialise (not for window 0)
+ * @virtual_x: The virtual X size.
+ * @virtual_y: The virtual Y size.
+ */
+struct s3c_fb_pd_win {
+ struct fb_videomode win_mode;
+
+ unsigned short default_bpp;
+ unsigned short max_bpp;
+ unsigned short virtual_x;
+ unsigned short virtual_y;
+};
+
+/**
+ * struct s3c_fb_platdata - S3C driver platform specific information
+ * @setup_gpio: Setup the external GPIO pins to the right state to transfer
+ * the data from the display system to the connected display
+ * device.
+ * @vidcon0: The base vidcon0 values to control the panel data format.
+ * @vidcon1: The base vidcon1 values to control the panel data output.
+ * @win: The setup data for each hardware window, or NULL for unused.
+ * @display_mode: The LCD output display mode.
+ *
+ * The platform data supplies the video driver with all the information
+ * it requires to work with the display(s) attached to the machine. It
+ * controls the initial mode, the number of display windows (0 is always
+ * the base framebuffer) that are initialised etc.
+ *
+ */
+struct s3c_fb_platdata {
+ void (*setup_gpio)(void);
+
+ struct s3c_fb_pd_win *win[S3C_FB_MAX_WIN];
+
+ u32 vidcon0;
+ u32 vidcon1;
+};
+
+/**
+ * s3c_fb_set_platdata() - Setup the FB device with platform data.
+ * @pd: The platform data to set. The data is copied from the passed structure
+ * so the machine data can mark the data __initdata so that any unused
+ * machines will end up dumping their data at runtime.
+ */
+extern void s3c_fb_set_platdata(struct s3c_fb_platdata *pd);
+
+/**
+ * s3c64xx_fb_gpio_setup_24bpp() - S3C64XX setup function for 24bpp LCD
+ *
+ * Initialise the GPIO for an 24bpp LCD display on the RGB interface.
+ */
+extern void s3c64xx_fb_gpio_setup_24bpp(void);
+
+/**
+ * s5pc100_fb_gpio_setup_24bpp() - S5PC100 setup function for 24bpp LCD
+ *
+ * Initialise the GPIO for an 24bpp LCD display on the RGB interface.
+ */
+extern void s5pc100_fb_gpio_setup_24bpp(void);
+
+#endif /* CONFIG_FB */
+
+#endif
+
+#endif /* __PLAT_S3C_FB_H */
diff --git a/arch/arm/plat-s5p/include/plat/fimc.h b/arch/arm/plat-s5p/include/plat/fimc.h
new file mode 100644
index 0000000..5685ed1
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/fimc.h
@@ -0,0 +1,129 @@
+/* linux/arch/arm/plat-s5p/include/plat/fimc.h
+ *
+ * Copyright 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Platform header file for Samsung Camera Interface (FIMC) driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+#ifndef __ASM_PLAT_FIMC_H
+#define __ASM_PLAT_FIMC_H __FILE__
+
+#include <linux/videodev2.h>
+
+#define FIMC_SRC_MAX_W 1920
+#define FIMC_SRC_MAX_H 1280
+
+struct platform_device;
+
+/* For exnternal camera device */
+enum fimc_cam_type {
+ CAM_TYPE_ITU = 0,
+ CAM_TYPE_MIPI = 1,
+};
+
+enum fimc_cam_format {
+ ITU_601_YCBCR422_8BIT = (1 << 31),
+ ITU_656_YCBCR422_8BIT = (0 << 31),
+ ITU_601_YCBCR422_16BIT = (1 << 29),
+ MIPI_CSI_YCBCR422_8BIT = 0x1e,
+ MIPI_CSI_RAW8 = 0x2a,
+ MIPI_CSI_RAW10 = 0x2b,
+ MIPI_CSI_RAW12 = 0x2c,
+ MIPI_USER_DEF_PACKET_1 = 0x30, /* User defined Byte-based packet 1 */
+};
+
+enum fimc_cam_order422 {
+ CAM_ORDER422_8BIT_YCBYCR = (0 << 14),
+ CAM_ORDER422_8BIT_YCRYCB = (1 << 14),
+ CAM_ORDER422_8BIT_CBYCRY = (2 << 14),
+ CAM_ORDER422_8BIT_CRYCBY = (3 << 14),
+ CAM_ORDER422_16BIT_Y4CBCRCBCR = (0 << 14),
+ CAM_ORDER422_16BIT_Y4CRCBCRCB = (1 << 14),
+};
+
+enum fimc_cam_index {
+ CAMERA_PAR_A = 0,
+ CAMERA_PAR_B = 1,
+ CAMERA_CSI_C = 2,
+ CAMERA_PATTERN = 3, /* Not actual camera but test pattern */
+ CAMERA_WB = 4, /* Not actual camera but write back */
+};
+
+/* struct s3c_platform_camera: abstraction for input camera */
+struct s3c_platform_camera {
+ /*
+ * ITU cam A,B: 0,1
+ * CSI-2 cam C: 2
+ */
+ enum fimc_cam_index id;
+
+ enum fimc_cam_type type; /* ITU or MIPI */
+ enum fimc_cam_format fmt; /* input format */
+ enum fimc_cam_order422 order422; /* YCBCR422 order for ITU */
+ u32 pixelformat; /* default fourcc */
+
+ int i2c_busnum;
+ struct i2c_board_info *info;
+ struct v4l2_subdev *sd;
+
+ const char srclk_name[16]; /* source of mclk name */
+ const char clk_name[16]; /* mclk name */
+ u32 clk_rate; /* mclk ratio */
+ struct clk *srclk; /* parent for mclk */
+ struct clk *clk; /* mclk */
+ int line_length; /* max length */
+ int width; /* default resol */
+ int height; /* default resol */
+ struct v4l2_rect window; /* real cut region from source */
+
+ int mipi_lanes; /* MIPI data lanes */
+ int mipi_settle; /* MIPI settle */
+ int mipi_align; /* MIPI data align: 24/32 */
+
+ /* Polarity: 1 if inverted polarity used */
+ int inv_pclk;
+ int inv_vsync;
+ int inv_href;
+ int inv_hsync;
+
+ int initialized;
+
+ /* Board specific power pin control */
+ int (*cam_power)(int onoff);
+};
+
+/* For camera interface driver */
+struct s3c_platform_fimc {
+ const char srclk_name[16]; /* source of interface clock name */
+ const char clk_name[16]; /* interface clock name */
+ const char lclk_name[16]; /* interface clock name */
+ u32 clk_rate; /* clockrate for interface clock */
+ enum fimc_cam_index default_cam; /* index of default cam */
+ struct s3c_platform_camera *camera[5]; /* FIXME */
+ int hw_ver;
+ phys_addr_t pmem_start; /* starting physical address of memory region */
+ size_t pmem_size; /* size of memory region */
+
+ void (*cfg_gpio)(struct platform_device *pdev);
+ int (*clk_on)(struct platform_device *pdev, struct clk *clk);
+ int (*clk_off)(struct platform_device *pdev, struct clk *clk);
+};
+
+extern void s3c_fimc0_set_platdata(struct s3c_platform_fimc *fimc);
+extern void s3c_fimc1_set_platdata(struct s3c_platform_fimc *fimc);
+extern void s3c_fimc2_set_platdata(struct s3c_platform_fimc *fimc);
+
+/* defined by architecture to configure gpio */
+extern void s3c_fimc0_cfg_gpio(struct platform_device *pdev);
+extern void s3c_fimc1_cfg_gpio(struct platform_device *pdev);
+extern void s3c_fimc2_cfg_gpio(struct platform_device *pdev);
+
+/* platform specific clock functions */
+extern int s3c_fimc_clk_on(struct platform_device *pdev, struct clk *clk);
+extern int s3c_fimc_clk_off(struct platform_device *pdev, struct clk *clk);
+
+#endif /*__ASM_PLAT_FIMC_H */
diff --git a/arch/arm/plat-s5p/include/plat/irq-eint-group.h b/arch/arm/plat-s5p/include/plat/irq-eint-group.h
new file mode 100644
index 0000000..430985b
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/irq-eint-group.h
@@ -0,0 +1,16 @@
+/* linux/arch/arm/plat-s5p/include/plat/irq-eint-group.h
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * S5P Common IRQ support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __PLAT_S5P_IRQ_EINT_GROUP_H
+#define __PLAT_S5P_IRQ_EINT_GROUP_H
+void s5pv210_restore_eint_group(void);
+#endif /* __PLAT_S5P_IRQ_EINT_GROUP_H */
diff --git a/arch/arm/plat-s5p/include/plat/irq-pm.h b/arch/arm/plat-s5p/include/plat/irq-pm.h
new file mode 100644
index 0000000..a104998
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/irq-pm.h
@@ -0,0 +1,16 @@
+/* linux/arch/arm/plat-s5p/include/plat/irq-pm.h
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * S5P Common IRQ support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __PLAT_S5P_IRQ_PM_H
+#define __PLAT_S5P_IRQ_PM_H
+int s3c_irq_wake(struct irq_data *data, unsigned int state);
+#endif /* __PLAT_S5P_IRQ_PM_H */
diff --git a/arch/arm/plat-s5p/include/plat/jpeg.h b/arch/arm/plat-s5p/include/plat/jpeg.h
new file mode 100755
index 0000000..cf52000
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/jpeg.h
@@ -0,0 +1,27 @@
+/* linux/arch/arm/plat-s5p/include/plat/jpeg.h
+ *
+ * Copyright 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Platform header file for JPEG device driver driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+#ifndef __ASM_PLAT_JPEG_H
+#define __ASM_PLAT_JPEG_H __FILE__
+
+struct platform_device;
+
+/* For camera interface driver */
+struct s3c_platform_jpeg {
+ unsigned int max_main_width;
+ unsigned int max_main_height;
+ unsigned int max_thumb_width;
+ unsigned int max_thumb_height;
+};
+
+extern void s3c_jpeg_set_platdata(struct s3c_platform_jpeg *jpeg);
+
+#endif /*__ASM_PLAT_FIMC_H */
diff --git a/arch/arm/plat-s5p/include/plat/map-s5p.h b/arch/arm/plat-s5p/include/plat/map-s5p.h
index d973d39..56b0432 100644
--- a/arch/arm/plat-s5p/include/plat/map-s5p.h
+++ b/arch/arm/plat-s5p/include/plat/map-s5p.h
@@ -25,6 +25,7 @@
#define S5P_VA_DMC0 S3C_ADDR(0x02440000)
#define S5P_VA_DMC1 S3C_ADDR(0x02480000)
#define S5P_VA_SROMC S3C_ADDR(0x024C0000)
+#define S5P_VA_AUDSS S3C_ADDR(0X01600000)
#define S5P_VA_SYSTIMER S3C_ADDR(0x02500000)
#define S5P_VA_L2CC S3C_ADDR(0x02600000)
diff --git a/arch/arm/plat-s5p/include/plat/media.h b/arch/arm/plat-s5p/include/plat/media.h
new file mode 100644
index 0000000..79761da
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/media.h
@@ -0,0 +1,34 @@
+/* linux/arch/arm/plat-s5p/include/plat/media.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Samsung Media device descriptions
+ *
+ * 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 _S5P_MEDIA_H
+#define _S5P_MEDIA_H
+
+#include <linux/types.h>
+#include <asm/setup.h>
+
+struct s5p_media_device {
+ u32 id;
+ const char *name;
+ u32 bank;
+ size_t memsize;
+ dma_addr_t paddr;
+};
+
+extern struct meminfo meminfo;
+extern dma_addr_t s5p_get_media_memory_bank(int dev_id, int bank);
+extern size_t s5p_get_media_memsize_bank(int dev_id, int bank);
+extern dma_addr_t s5p_get_media_membase_bank(int bank);
+extern void s5p_reserve_bootmem(struct s5p_media_device *mdevs, int nr_mdevs, size_t boundary);
+
+#endif
+
diff --git a/arch/arm/plat-s5p/include/plat/mfc.h b/arch/arm/plat-s5p/include/plat/mfc.h
new file mode 100644
index 0000000..bba97a9
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/mfc.h
@@ -0,0 +1,24 @@
+/* arch/arm/plat-s5p/include/plat/mfc.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Platform header file for MFC driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _S3C_MFC_H
+#define _S3C_MFC_H
+
+#include <linux/types.h>
+
+struct s3c_platform_mfc {
+ dma_addr_t buf_phy_base[2];
+ size_t buf_phy_size[2];
+};
+
+extern void s3c_mfc_set_platdata(struct s3c_platform_mfc *pd);
+#endif
diff --git a/arch/arm/plat-s5p/include/plat/pll.h b/arch/arm/plat-s5p/include/plat/pll.h
index bf28fad..9c2332f 100644
--- a/arch/arm/plat-s5p/include/plat/pll.h
+++ b/arch/arm/plat-s5p/include/plat/pll.h
@@ -94,10 +94,12 @@ static inline unsigned long s5p_get_pll46xx(unsigned long baseclk,
return result;
}
+#define PLL90XX_VDIV_MASK (0x1)
#define PLL90XX_MDIV_MASK (0xFF)
#define PLL90XX_PDIV_MASK (0x3F)
#define PLL90XX_SDIV_MASK (0x7)
#define PLL90XX_KDIV_MASK (0xffff)
+#define PLL90XX_VDIV_SHIFT (27)
#define PLL90XX_MDIV_SHIFT (16)
#define PLL90XX_PDIV_SHIFT (8)
#define PLL90XX_SDIV_SHIFT (0)
diff --git a/arch/arm/plat-s5p/include/plat/regs-csis.h b/arch/arm/plat-s5p/include/plat/regs-csis.h
new file mode 100644
index 0000000..aaab7bc
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/regs-csis.h
@@ -0,0 +1,105 @@
+/* linux/arch/arm/plat-s5p/include/plat/regs-csis.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * S5PV210 - Register definition file for MIPI-CSI2 Driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef _REGS_CSIS_H
+#define _REGS_CSIS_H
+
+#define S3C_CSISREG(x) (x)
+
+/*************************************************************************
+ * Registers
+ ************************************************************************/
+#define S3C_CSIS_CONTROL S3C_CSISREG(0x00)
+#define S3C_CSIS_DPHYCTRL S3C_CSISREG(0x04)
+#define S3C_CSIS_CONFIG S3C_CSISREG(0x08)
+#define S3C_CSIS_DPHYSTS S3C_CSISREG(0x0c)
+#define S3C_CSIS_INTMSK S3C_CSISREG(0x10)
+#define S3C_CSIS_INTSRC S3C_CSISREG(0x14)
+#define S3C_CSIS_RESOL S3C_CSISREG(0x2c)
+
+/*************************************************************************
+ * Bit Definitions
+ ************************************************************************/
+/* Control Register */
+#define S3C_CSIS_CONTROL_DPDN_DEFAULT (0 << 31)
+#define S3C_CSIS_CONTROL_DPDN_SWAP (1 << 31)
+#define S3C_CSIS_CONTROL_ALIGN_32BIT (1 << 20)
+#define S3C_CSIS_CONTROL_ALIGN_24BIT (0 << 20)
+#define S3C_CSIS_CONTROL_ALIGN_MASK (1 << 20)
+#define S3C_CSIS_CONTROL_UPDATE_SHADOW (1 << 16)
+#define S3C_CSIS_CONTROL_WCLK_PCLK (0 << 8)
+#define S3C_CSIS_CONTROL_WCLK_EXTCLK (1 << 8)
+#define S3C_CSIS_CONTROL_WCLK_MASK (1 << 8)
+#define S3C_CSIS_CONTROL_RESET (1 << 4)
+#define S3C_CSIS_CONTROL_DISABLE (0 << 0)
+#define S3C_CSIS_CONTROL_ENABLE (1 << 0)
+
+/* D-PHY Control Register */
+#define S3C_CSIS_DPHYCTRL_HS_SETTLE_MASK (0x1f << 27)
+#define S3C_CSIS_DPHYCTRL_HS_SETTLE_SHIFT (27)
+#define S3C_CSIS_DPHYCTRL_DISABLE (0xf << 0)
+#define S3C_CSIS_DPHYCTRL_ENABLE (0xf << 0)
+
+/* Configuration Register */
+#define S3C_CSIS_CONFIG_FORMAT_SHIFT (2)
+#define S3C_CSIS_CONFIG_FORMAT_MASK (0x1f << 2)
+#define S3C_CSIS_CONFIG_NR_LANE_1 (0 << 0)
+#define S3C_CSIS_CONFIG_NR_LANE_2 (1 << 0)
+#define S3C_CSIS_CONFIG_NR_LANE_MASK (1 << 0)
+
+/* D-PHY Status Register */
+#define S3C_CSIS_DPHYSTS_STOPSTATE_LANE1 (1 << 5)
+#define S3C_CSIS_DPHYSTS_STOPSTATE_LANE0 (1 << 4)
+#define S3C_CSIS_DPHYSTS_STOPSTATE_CLOCK (1 << 0)
+
+/* Interrupt Mask Register */
+#define S3C_CSIS_INTMSK_EVEN_BEFORE_DISABLE (0 << 31)
+#define S3C_CSIS_INTMSK_EVEN_BEFORE_ENABLE (1 << 31)
+#define S3C_CSIS_INTMSK_EVEN_AFTER_DISABLE (0 << 30)
+#define S3C_CSIS_INTMSK_EVEN_AFTER_ENABLE (1 << 30)
+#define S3C_CSIS_INTMSK_ODD_BEFORE_DISABLE (0 << 29)
+#define S3C_CSIS_INTMSK_ODD_BEFORE_ENABLE (1 << 29)
+#define S3C_CSIS_INTMSK_ODD_AFTER_DISABLE (0 << 28)
+#define S3C_CSIS_INTMSK_ODD_AFTER_ENABLE (1 << 28)
+#define S3C_CSIS_INTMSK_ERR_SOT_HS_DISABLE (0 << 12)
+#define S3C_CSIS_INTMSK_ERR_SOT_HS_ENABLE (1 << 12)
+#define S3C_CSIS_INTMSK_ERR_ESC_DISABLE (0 << 8)
+#define S3C_CSIS_INTMSK_ERR_ESC_ENABLE (1 << 8)
+#define S3C_CSIS_INTMSK_ERR_CTRL_DISABLE (0 << 4)
+#define S3C_CSIS_INTMSK_ERR_CTRL_ENABLE (1 << 4)
+#define S3C_CSIS_INTMSK_ERR_ECC_DISABLE (0 << 2)
+#define S3C_CSIS_INTMSK_ERR_ECC_ENABLE (1 << 2)
+#define S3C_CSIS_INTMSK_ERR_CRC_DISABLE (0 << 1)
+#define S3C_CSIS_INTMSK_ERR_CRC_ENABLE (1 << 1)
+#define S3C_CSIS_INTMSK_ERR_ID_DISABLE (0 << 0)
+#define S3C_CSIS_INTMSK_ERR_ID_ENABLE (1 << 0)
+
+/* Interrupt Source Register */
+#define S3C_CSIS_INTSRC_EVEN_BEFORE (1 << 31)
+#define S3C_CSIS_INTSRC_EVEN_AFTER (1 << 30)
+#define S3C_CSIS_INTSRC_ODD_BEFORE (1 << 29)
+#define S3C_CSIS_INTSRC_ODD_AFTER (1 << 28)
+#define S3C_CSIS_INTSRC_ERR_SOT_HS_LANE1 (1 << 13)
+#define S3C_CSIS_INTSRC_ERR_SOT_HS_LANE0 (1 << 12)
+#define S3C_CSIS_INTSRC_ERR_ESC_LANE1 (1 << 9)
+#define S3C_CSIS_INTSRC_ERR_ESC_LANE0 (1 << 8)
+#define S3C_CSIS_INTSRC_ERR_CTRL1 (1 << 5)
+#define S3C_CSIS_INTSRC_ERR_CTRL0 (1 << 4)
+#define S3C_CSIS_INTSRC_ERR_ECC (1 << 2)
+#define S3C_CSIS_INTSRC_ERR_CRC (1 << 1)
+#define S3C_CSIS_INTSRC_ERR_ID (1 << 0)
+
+/* Resolution Register */
+#define S3C_CSIS_RESOL_HOR_SHIFT (16)
+#define S3C_CSIS_RESOL_VER_SHIFT (0)
+
+#endif /* _REGS_CSIS_H */
diff --git a/arch/arm/plat-s5p/include/plat/regs-fb.h b/arch/arm/plat-s5p/include/plat/regs-fb.h
new file mode 100644
index 0000000..9945ebf
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/regs-fb.h
@@ -0,0 +1,396 @@
+/* linux/arch/arm/plat-s5p/include/plat/regs-fb.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Register definition file for Samsung Display Controller (FIMD) driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef _REGS_FB_H
+#define _REGS_FB_H
+
+#define S3C_LCDREG(x) (x)
+#define S3C_WINCON(x) S3C_LCDREG(0x0020 + (x * 0x04))
+#define S3C_VIDOSD_A(x) S3C_LCDREG(0x0040 + (x * 0x10))
+#define S3C_VIDOSD_B(x) S3C_LCDREG(0x0044 + (x * 0x10))
+#define S3C_VIDOSD_C(x) S3C_LCDREG(0x0048 + (x * 0x10))
+#define S3C_VIDOSD_D(x) S3C_LCDREG(0x004C + (x * 0x10))
+#define S3C_VIDADDR_START0(x) S3C_LCDREG(0x00A0 + (x * 0x08))
+#define S3C_VIDADDR_START1(x) S3C_LCDREG(0x00A4 + (x * 0x08))
+#define S3C_VIDADDR_END0(x) S3C_LCDREG(0x00D0 + (x * 0x08))
+#define S3C_VIDADDR_END1(x) S3C_LCDREG(0x00D4 + (x * 0x08))
+#define S3C_VIDADDR_SIZE(x) S3C_LCDREG(0x0100 + (x * 0x04))
+#define S3C_KEYCON(x) S3C_LCDREG(0x0140 + ((x - 1) * 0x08))
+#define S3C_KEYVAL(x) S3C_LCDREG(0x0144 + ((x - 1) * 0x08))
+#define S3C_WINMAP(x) S3C_LCDREG(0x0180 + (x * 0x04))
+
+/*
+ * Register Map
+*/
+#define S3C_VIDCON0 S3C_LCDREG(0x0000) /* Video control 0 */
+#define S3C_VIDCON1 S3C_LCDREG(0x0004) /* Video control 1 */
+#define S3C_VIDCON2 S3C_LCDREG(0x0008) /* Video control 2 */
+#define S3C_PRTCON S3C_LCDREG(0x000C) /* Protect control */
+
+#define S3C_VIDTCON0 S3C_LCDREG(0x0010) /* Video time control 0 */
+#define S3C_VIDTCON1 S3C_LCDREG(0x0014) /* Video time control 1 */
+#define S3C_VIDTCON2 S3C_LCDREG(0x0018) /* Video time control 2 */
+
+#define S3C_WINCON0 S3C_LCDREG(0x0020) /* Window control 0 */
+#define S3C_WINCON1 S3C_LCDREG(0x0024) /* Window control 1 */
+#define S3C_WINCON2 S3C_LCDREG(0x0028) /* Window control 2 */
+#define S3C_WINCON3 S3C_LCDREG(0x002C) /* Window control 3 */
+#define S3C_WINCON4 S3C_LCDREG(0x0030) /* Window control 4 */
+
+#define S3C_WINSHMAP S3C_LCDREG(0x0034) /* Window Shadow control */
+
+#define S3C_VIDOSD0A S3C_LCDREG(0x0040) /* Video Window 0 position control */
+#define S3C_VIDOSD0B S3C_LCDREG(0x0044) /* Video Window 0 position control1 */
+#define S3C_VIDOSD0C S3C_LCDREG(0x0048) /* Video Window 0 position control */
+
+#define S3C_VIDOSD1A S3C_LCDREG(0x0050) /* Video Window 1 position control */
+#define S3C_VIDOSD1B S3C_LCDREG(0x0054) /* Video Window 1 position control */
+#define S3C_VIDOSD1C S3C_LCDREG(0x0058) /* Video Window 1 position control */
+#define S3C_VIDOSD1D S3C_LCDREG(0x005C) /* Video Window 1 position control */
+
+#define S3C_VIDOSD2A S3C_LCDREG(0x0060) /* Video Window 2 position control */
+#define S3C_VIDOSD2B S3C_LCDREG(0x0064) /* Video Window 2 position control */
+#define S3C_VIDOSD2C S3C_LCDREG(0x0068) /* Video Window 2 position control */
+#define S3C_VIDOSD2D S3C_LCDREG(0x006C) /* Video Window 2 position control */
+
+#define S3C_VIDOSD3A S3C_LCDREG(0x0070) /* Video Window 3 position control */
+#define S3C_VIDOSD3B S3C_LCDREG(0x0074) /* Video Window 3 position control */
+#define S3C_VIDOSD3C S3C_LCDREG(0x0078) /* Video Window 3 position control */
+
+#define S3C_VIDOSD4A S3C_LCDREG(0x0080) /* Video Window 4 position control */
+#define S3C_VIDOSD4B S3C_LCDREG(0x0084) /* Video Window 4 position control */
+#define S3C_VIDOSD4C S3C_LCDREG(0x0088) /* Video Window 4 position control */
+
+#define S3C_VIDW00ADD0B0 S3C_LCDREG(0x00A0) /* Window 0 buffer start address, buffer 0 */
+#define S3C_VIDW00ADD0B1 S3C_LCDREG(0x00A4) /* Window 0 buffer start address, buffer 1 */
+#define S3C_VIDW01ADD0B0 S3C_LCDREG(0x00A8) /* Window 1 buffer start address, buffer 0 */
+#define S3C_VIDW01ADD0B1 S3C_LCDREG(0x00AC) /* Window 1 buffer start address, buffer 1 */
+#define S3C_VIDW02ADD0 S3C_LCDREG(0x00B0) /* Window 2 buffer start address, buffer 0 */
+#define S3C_VIDW03ADD0 S3C_LCDREG(0x00B8) /* Window 3 buffer start address, buffer 0 */
+#define S3C_VIDW04ADD0 S3C_LCDREG(0x00C0) /* Window 4 buffer start address, buffer 0 */
+#define S3C_VIDW00ADD1B0 S3C_LCDREG(0x00D0) /* Window 0 buffer end address, buffer 0 */
+#define S3C_VIDW00ADD1B1 S3C_LCDREG(0x00D4) /* Window 0 buffer end address, buffer 1 */
+#define S3C_VIDW01ADD1B0 S3C_LCDREG(0x00D8) /* Window 1 buffer end address, buffer 0 */
+#define S3C_VIDW01ADD1B1 S3C_LCDREG(0x00DC) /* Window 1 buffer end address, buffer 1 */
+#define S3C_VIDW02ADD1 S3C_LCDREG(0x00E0) /* Window 2 buffer end address */
+#define S3C_VIDW03ADD1 S3C_LCDREG(0x00E8) /* Window 3 buffer end address */
+#define S3C_VIDW04ADD1 S3C_LCDREG(0x00F0) /* Window 4 buffer end address */
+#define S3C_VIDW00ADD2 S3C_LCDREG(0x0100) /* Window 0 buffer size */
+#define S3C_VIDW01ADD2 S3C_LCDREG(0x0104) /* Window 1 buffer size */
+#define S3C_VIDW02ADD2 S3C_LCDREG(0x0108) /* Window 2 buffer size */
+#define S3C_VIDW03ADD2 S3C_LCDREG(0x010C) /* Window 3 buffer size */
+#define S3C_VIDW04ADD2 S3C_LCDREG(0x0110) /* Window 4 buffer size */
+
+#define S3C_VP1TCON0 S3C_LCDREG(0x0118) /* VP1 interface timing control 0 */
+#define S3C_VP1TCON1 S3C_LCDREG(0x011C) /* VP1 interface timing control 1 */
+
+#define S3C_VIDINTCON0 S3C_LCDREG(0x0130) /* Indicate the Video interrupt control */
+#define S3C_VIDINTCON1 S3C_LCDREG(0x0134) /* Video Interrupt Pending */
+
+#define S3C_W1KEYCON0 S3C_LCDREG(0x0140) /* Color key control */
+#define S3C_W1KEYCON1 S3C_LCDREG(0x0144) /* Color key value (transparent value) */
+#define S3C_W2KEYCON0 S3C_LCDREG(0x0148) /* Color key control */
+#define S3C_W2KEYCON1 S3C_LCDREG(0x014C) /* Color key value (transparent value) */
+#define S3C_W3KEYCON0 S3C_LCDREG(0x0150) /* Color key control */
+#define S3C_W3KEYCON1 S3C_LCDREG(0x0154) /* Color key value (transparent value) */
+#define S3C_W4KEYCON0 S3C_LCDREG(0x0158) /* Color key control */
+#define S3C_W4KEYCON1 S3C_LCDREG(0x015C) /* Color key value (transparent value) */
+
+#define S3C_W1KEYALPHA S3C_LCDREG(0x0160) /* Color key alpha value */
+#define S3C_W2KEYALPHA S3C_LCDREG(0x0164) /* Color key alpha value */
+#define S3C_W3KEYALPHA S3C_LCDREG(0x0168) /* Color key alpha value */
+#define S3C_W4KEYALPHA S3C_LCDREG(0x016C) /* Color key alpha value */
+
+#define S3C_DITHMODE S3C_LCDREG(0x0170) /* Dithering mode */
+
+#define S3C_WIN0MAP S3C_LCDREG(0x0180) /* Window color control */
+#define S3C_WIN1MAP S3C_LCDREG(0x0184) /* Window color control */
+#define S3C_WIN2MAP S3C_LCDREG(0x0188) /* Window color control */
+#define S3C_WIN3MAP S3C_LCDREG(0x018C) /* Window color control */
+#define S3C_WIN4MAP S3C_LCDREG(0x0190) /* Window color control */
+
+#define S3C_WPALCON_H S3C_LCDREG(0x019C) /* Window Palette control */
+#define S3C_WPALCON_L S3C_LCDREG(0x01A0) /* Window Palette control */
+
+#define S3C_VIDW0ALPHA0 S3C_LCDREG(0x0200) /* Window 0 alpha value 0 */
+#define S3C_VIDW0ALPHA1 S3C_LCDREG(0x0204) /* Window 0 alpha value 1 */
+#define S3C_VIDW1ALPHA0 S3C_LCDREG(0x0208) /* Window 1 alpha value 0 */
+#define S3C_VIDW1ALPHA1 S3C_LCDREG(0x020C) /* Window 1 alpha value 1 */
+#define S3C_VIDW2ALPHA0 S3C_LCDREG(0x0210) /* Window 2 alpha value 0 */
+#define S3C_VIDW2ALPHA1 S3C_LCDREG(0x0214) /* Window 2 alpha value 1 */
+#define S3C_VIDW3ALPHA0 S3C_LCDREG(0x0218) /* Window 3 alpha value 0 */
+#define S3C_VIDW3ALPHA1 S3C_LCDREG(0x021C) /* Window 3 alpha value 1 */
+#define S3C_VIDW4ALPHA0 S3C_LCDREG(0x0220) /* Window 4 alpha value 0 */
+#define S3C_VIDW4ALPHA1 S3C_LCDREG(0x0224) /* Window 4 alpha value 1 */
+
+#define S3C_BLENDEQ1 S3C_LCDREG(0x0244) /* Window 1 blending equation control */
+#define S3C_BLENDEQ2 S3C_LCDREG(0x0248) /* Window 2 blending equation control */
+#define S3C_BLENDEQ3 S3C_LCDREG(0x024C) /* Window 3 blending equation control */
+#define S3C_BLENDEQ4 S3C_LCDREG(0x0250) /* Window 4 blending equation control */
+#define S3C_BLENDCON S3C_LCDREG(0x0260) /* Blending control */
+
+/*
+ * Bit Definitions
+*/
+
+/* VIDCON0 */
+#define S3C_VIDCON0_DSI_DISABLE (0 << 30)
+#define S3C_VIDCON0_DSI_ENABLE (1 << 30)
+#define S3C_VIDCON0_SCAN_PROGRESSIVE (0 << 29)
+#define S3C_VIDCON0_SCAN_INTERLACE (1 << 29)
+#define S3C_VIDCON0_SCAN_MASK (1 << 29)
+#define S3C_VIDCON0_VIDOUT_RGB (0 << 26)
+#define S3C_VIDCON0_VIDOUT_ITU (1 << 26)
+#define S3C_VIDCON0_VIDOUT_I80LDI0 (2 << 26)
+#define S3C_VIDCON0_VIDOUT_I80LDI1 (3 << 26)
+#define S3C_VIDCON0_VIDOUT_WB_RGB (4 << 26)
+#define S3C_VIDCON0_VIDOUT_WB_I80LDI0 (6 << 26)
+#define S3C_VIDCON0_VIDOUT_WB_I80LDI1 (7 << 26)
+#define S3C_VIDCON0_VIDOUT_MASK (7 << 26)
+#define S3C_VIDCON0_PNRMODE_RGB_P (0 << 17)
+#define S3C_VIDCON0_PNRMODE_BGR_P (1 << 17)
+#define S3C_VIDCON0_PNRMODE_RGB_S (2 << 17)
+#define S3C_VIDCON0_PNRMODE_BGR_S (3 << 17)
+#define S3C_VIDCON0_PNRMODE_MASK (3 << 17)
+#define S3C_VIDCON0_PNRMODE_SHIFT (17)
+#define S3C_VIDCON0_CLKVALUP_ALWAYS (0 << 16)
+#define S3C_VIDCON0_CLKVALUP_START_FRAME (1 << 16)
+#define S3C_VIDCON0_CLKVALUP_MASK (1 << 16)
+#define S3C_VIDCON0_CLKVAL_F(x) (((x) & 0xff) << 6)
+#define S3C_VIDCON0_VCLKEN_NORMAL (0 << 5)
+#define S3C_VIDCON0_VCLKEN_FREERUN (1 << 5)
+#define S3C_VIDCON0_VCLKEN_MASK (1 << 5)
+#define S3C_VIDCON0_CLKDIR_DIRECTED (0 << 4)
+#define S3C_VIDCON0_CLKDIR_DIVIDED (1 << 4)
+#define S3C_VIDCON0_CLKDIR_MASK (1 << 4)
+#define S3C_VIDCON0_CLKSEL_HCLK (0 << 2)
+#define S3C_VIDCON0_CLKSEL_SCLK (1 << 2)
+#define S3C_VIDCON0_CLKSEL_MASK (1 << 2)
+#define S3C_VIDCON0_ENVID_ENABLE (1 << 1)
+#define S3C_VIDCON0_ENVID_DISABLE (0 << 1)
+#define S3C_VIDCON0_ENVID_F_ENABLE (1 << 0)
+#define S3C_VIDCON0_ENVID_F_DISABLE (0 << 0)
+
+/* VIDCON1 */
+#define S3C_VIDCON1_IVCLK_FALLING_EDGE (0 << 7)
+#define S3C_VIDCON1_IVCLK_RISING_EDGE (1 << 7)
+#define S3C_VIDCON1_IHSYNC_NORMAL (0 << 6)
+#define S3C_VIDCON1_IHSYNC_INVERT (1 << 6)
+#define S3C_VIDCON1_IVSYNC_NORMAL (0 << 5)
+#define S3C_VIDCON1_IVSYNC_INVERT (1 << 5)
+#define S3C_VIDCON1_IVDEN_NORMAL (0 << 4)
+#define S3C_VIDCON1_IVDEN_INVERT (1 << 4)
+
+/* VIDCON2 */
+#define S3C_VIDCON2_EN601_DISABLE (0 << 23)
+#define S3C_VIDCON2_EN601_ENABLE (1 << 23)
+#define S3C_VIDCON2_EN601_MASK (1 << 23)
+#define S3C_VIDCON2_WB_DISABLE (0 << 15)
+#define S3C_VIDCON2_WB_ENABLE (1 << 15)
+#define S3C_VIDCON2_WB_MASK (1 << 15)
+#define S3C_VIDCON2_TVFORMATSEL_HW (0 << 14)
+#define S3C_VIDCON2_TVFORMATSEL_SW (1 << 14)
+#define S3C_VIDCON2_TVFORMATSEL_MASK (1 << 14)
+#define S3C_VIDCON2_TVFORMATSEL_YUV422 (1 << 12)
+#define S3C_VIDCON2_TVFORMATSEL_YUV444 (2 << 12)
+#define S3C_VIDCON2_TVFORMATSEL_YUV_MASK (3 << 12)
+#define S3C_VIDCON2_ORGYUV_YCBCR (0 << 8)
+#define S3C_VIDCON2_ORGYUV_CBCRY (1 << 8)
+#define S3C_VIDCON2_ORGYUV_MASK (1 << 8)
+#define S3C_VIDCON2_YUVORD_CBCR (0 << 7)
+#define S3C_VIDCON2_YUVORD_CRCB (1 << 7)
+#define S3C_VIDCON2_YUVORD_MASK (1 << 7)
+
+/* PRTCON */
+#define S3C_PRTCON_UPDATABLE (0 << 11)
+#define S3C_PRTCON_PROTECT (1 << 11)
+
+/* VIDTCON0 */
+#define S3C_VIDTCON0_VBPDE(x) (((x) & 0xff) << 24)
+#define S3C_VIDTCON0_VBPD(x) (((x) & 0xff) << 16)
+#define S3C_VIDTCON0_VFPD(x) (((x) & 0xff) << 8)
+#define S3C_VIDTCON0_VSPW(x) (((x) & 0xff) << 0)
+
+/* VIDTCON1 */
+#define S3C_VIDTCON1_VFPDE(x) (((x) & 0xff) << 24)
+#define S3C_VIDTCON1_HBPD(x) (((x) & 0xff) << 16)
+#define S3C_VIDTCON1_HFPD(x) (((x) & 0xff) << 8)
+#define S3C_VIDTCON1_HSPW(x) (((x) & 0xff) << 0)
+
+/* VIDTCON2 */
+#define S3C_VIDTCON2_LINEVAL(x) (((x) & 0x7ff) << 11)
+#define S3C_VIDTCON2_HOZVAL(x) (((x) & 0x7ff) << 0)
+
+/* Window 0~4 Control - WINCONx */
+#define S3C_WINCON_DATAPATH_DMA (0 << 22)
+#define S3C_WINCON_DATAPATH_LOCAL (1 << 22)
+#define S3C_WINCON_DATAPATH_MASK (1 << 22)
+#define S3C_WINCON_BUFSEL_0 (0 << 20)
+#define S3C_WINCON_BUFSEL_1 (1 << 20)
+#define S3C_WINCON_BUFSEL_MASK (1 << 20)
+#define S3C_WINCON_BUFSEL_SHIFT (20)
+#define S3C_WINCON_BUFAUTO_DISABLE (0 << 19)
+#define S3C_WINCON_BUFAUTO_ENABLE (1 << 19)
+#define S3C_WINCON_BUFAUTO_MASK (1 << 19)
+#define S3C_WINCON_BITSWP_DISABLE (0 << 18)
+#define S3C_WINCON_BITSWP_ENABLE (1 << 18)
+#define S3C_WINCON_BITSWP_SHIFT (18)
+#define S3C_WINCON_BYTESWP_DISABLE (0 << 17)
+#define S3C_WINCON_BYTESWP_ENABLE (1 << 17)
+#define S3C_WINCON_BYTESWP_SHIFT (17)
+#define S3C_WINCON_HAWSWP_DISABLE (0 << 16)
+#define S3C_WINCON_HAWSWP_ENABLE (1 << 16)
+#define S3C_WINCON_HAWSWP_SHIFT (16)
+#define S3C_WINCON_WSWP_DISABLE (0 << 15)
+#define S3C_WINCON_WSWP_ENABLE (1 << 15)
+#define S3C_WINCON_WSWP_SHIFT (15)
+#define S3C_WINCON_INRGB_RGB (0 << 13)
+#define S3C_WINCON_INRGB_YUV (1 << 13)
+#define S3C_WINCON_INRGB_MASK (1 << 13)
+#define S3C_WINCON_BURSTLEN_16WORD (0 << 9)
+#define S3C_WINCON_BURSTLEN_8WORD (1 << 9)
+#define S3C_WINCON_BURSTLEN_4WORD (2 << 9)
+#define S3C_WINCON_BURSTLEN_MASK (3 << 9)
+#define S3C_WINCON_ALPHA_MULTI_DISABLE (0 << 7)
+#define S3C_WINCON_ALPHA_MULTI_ENABLE (1 << 7)
+#define S3C_WINCON_BLD_PLANE (0 << 6)
+#define S3C_WINCON_BLD_PIXEL (1 << 6)
+#define S3C_WINCON_BLD_MASK (1 << 6)
+#define S3C_WINCON_BPPMODE_1BPP (0 << 2)
+#define S3C_WINCON_BPPMODE_2BPP (1 << 2)
+#define S3C_WINCON_BPPMODE_4BPP (2 << 2)
+#define S3C_WINCON_BPPMODE_8BPP_PAL (3 << 2)
+#define S3C_WINCON_BPPMODE_8BPP (4 << 2)
+#define S3C_WINCON_BPPMODE_16BPP_565 (5 << 2)
+#define S3C_WINCON_BPPMODE_16BPP_A555 (6 << 2)
+#define S3C_WINCON_BPPMODE_18BPP_666 (8 << 2)
+#define S3C_WINCON_BPPMODE_18BPP_A665 (9 << 2)
+#define S3C_WINCON_BPPMODE_24BPP_888 (0xb << 2)
+#define S3C_WINCON_BPPMODE_24BPP_A887 (0xc << 2)
+#define S3C_WINCON_BPPMODE_32BPP (0xd << 2)
+#define S3C_WINCON_BPPMODE_16BPP_A444 (0xe << 2)
+#define S3C_WINCON_BPPMODE_15BPP_555 (0xf << 2)
+#define S3C_WINCON_BPPMODE_MASK (0xf << 2)
+#define S3C_WINCON_BPPMODE_SHIFT (2)
+#define S3C_WINCON_ALPHA0_SEL (0 << 1)
+#define S3C_WINCON_ALPHA1_SEL (1 << 1)
+#define S3C_WINCON_ALPHA_SEL_MASK (1 << 1)
+#define S3C_WINCON_ENWIN_DISABLE (0 << 0)
+#define S3C_WINCON_ENWIN_ENABLE (1 << 0)
+
+/* WINCON1 special */
+#define S3C_WINCON1_VP_DISABLE (0 << 24)
+#define S3C_WINCON1_VP_ENABLE (1 << 24)
+#define S3C_WINCON1_LOCALSEL_FIMC1 (0 << 23)
+#define S3C_WINCON1_LOCALSEL_VP (1 << 23)
+#define S3C_WINCON1_LOCALSEL_MASK (1 << 23)
+
+/* WINSHMAP */
+#define S3C_WINSHMAP_PROTECT(x) (((x) & 0x1f) << 10)
+#define S3C_WINSHMAP_CH_ENABLE(x) (1 << (x))
+#define S3C_WINSHMAP_CH_DISABLE(x) (1 << (x))
+#define S3C_WINSHMAP_LOCAL_ENABLE(x) (0x20 << (x))
+#define S3C_WINSHMAP_LOCAL_DISABLE(x) (0x20 << (x))
+
+
+/* VIDOSDxA, VIDOSDxB */
+#define S3C_VIDOSD_LEFT_X(x) (((x) & 0x7ff) << 11)
+#define S3C_VIDOSD_TOP_Y(x) (((x) & 0x7ff) << 0)
+#define S3C_VIDOSD_RIGHT_X(x) (((x) & 0x7ff) << 11)
+#define S3C_VIDOSD_BOTTOM_Y(x) (((x) & 0x7ff) << 0)
+
+/* VIDOSD0C, VIDOSDxD */
+#define S3C_VIDOSD_SIZE(x) (((x) & 0xffffff) << 0)
+
+/* VIDOSDxC (1~4) */
+#define S3C_VIDOSD_ALPHA0_R(x) (((x) & 0xf) << 20)
+#define S3C_VIDOSD_ALPHA0_G(x) (((x) & 0xf) << 16)
+#define S3C_VIDOSD_ALPHA0_B(x) (((x) & 0xf) << 12)
+#define S3C_VIDOSD_ALPHA1_R(x) (((x) & 0xf) << 8)
+#define S3C_VIDOSD_ALPHA1_G(x) (((x) & 0xf) << 4)
+#define S3C_VIDOSD_ALPHA1_B(x) (((x) & 0xf) << 0)
+#define S3C_VIDOSD_ALPHA0_SHIFT (12)
+#define S3C_VIDOSD_ALPHA1_SHIFT (0)
+
+/* Start Address */
+#define S3C_VIDADDR_START_VBANK(x) (((x) & 0xff) << 24)
+#define S3C_VIDADDR_START_VBASEU(x) (((x) & 0xffffff) << 0)
+
+/* End Address */
+#define S3C_VIDADDR_END_VBASEL(x) (((x) & 0xffffff) << 0)
+
+/* Buffer Size */
+#define S3C_VIDADDR_OFFSIZE(x) (((x) & 0x1fff) << 13)
+#define S3C_VIDADDR_PAGEWIDTH(x) (((x) & 0x1fff) << 0)
+
+/* WIN Color Map */
+#define S3C_WINMAP_COLOR(x) ((x) & 0xffffff)
+
+/* VIDINTCON0 */
+#define S3C_VIDINTCON0_SYSMAINCON_DISABLE (0 << 19)
+#define S3C_VIDINTCON0_SYSMAINCON_ENABLE (1 << 19)
+#define S3C_VIDINTCON0_SYSSUBCON_DISABLE (0 << 18)
+#define S3C_VIDINTCON0_SYSSUBCON_ENABLE (1 << 18)
+#define S3C_VIDINTCON0_SYSIFDONE_DISABLE (0 << 17)
+#define S3C_VIDINTCON0_SYSIFDONE_ENABLE (1 << 17)
+#define S3C_VIDINTCON0_FRAMESEL0_BACK (0 << 15)
+#define S3C_VIDINTCON0_FRAMESEL0_VSYNC (1 << 15)
+#define S3C_VIDINTCON0_FRAMESEL0_ACTIVE (2 << 15)
+#define S3C_VIDINTCON0_FRAMESEL0_FRONT (3 << 15)
+#define S3C_VIDINTCON0_FRAMESEL0_MASK (3 << 15)
+#define S3C_VIDINTCON0_FRAMESEL1_NONE (0 << 13)
+#define S3C_VIDINTCON0_FRAMESEL1_BACK (1 << 13)
+#define S3C_VIDINTCON0_FRAMESEL1_VSYNC (2 << 13)
+#define S3C_VIDINTCON0_FRAMESEL1_FRONT (3 << 13)
+#define S3C_VIDINTCON0_INTFRMEN_DISABLE (0 << 12)
+#define S3C_VIDINTCON0_INTFRMEN_ENABLE (1 << 12)
+#define S3C_VIDINTCON0_FIFOSEL_WIN4 (1 << 11)
+#define S3C_VIDINTCON0_FIFOSEL_WIN3 (1 << 10)
+#define S3C_VIDINTCON0_FIFOSEL_WIN2 (1 << 9)
+#define S3C_VIDINTCON0_FIFOSEL_WIN1 (1 << 6)
+#define S3C_VIDINTCON0_FIFOSEL_WIN0 (1 << 5)
+#define S3C_VIDINTCON0_FIFOSEL_ALL (0x73 << 5)
+#define S3C_VIDINTCON0_FIFOSEL_MASK (0x73 << 5)
+#define S3C_VIDINTCON0_FIFOLEVEL_25 (0 << 2)
+#define S3C_VIDINTCON0_FIFOLEVEL_50 (1 << 2)
+#define S3C_VIDINTCON0_FIFOLEVEL_75 (2 << 2)
+#define S3C_VIDINTCON0_FIFOLEVEL_EMPTY (3 << 2)
+#define S3C_VIDINTCON0_FIFOLEVEL_FULL (4 << 2)
+#define S3C_VIDINTCON0_FIFOLEVEL_MASK (7 << 2)
+#define S3C_VIDINTCON0_INTFIFO_DISABLE (0 << 1)
+#define S3C_VIDINTCON0_INTFIFO_ENABLE (1 << 1)
+#define S3C_VIDINTCON0_INT_DISABLE (0 << 0)
+#define S3C_VIDINTCON0_INT_ENABLE (1 << 0)
+#define S3C_VIDINTCON0_INT_MASK (1 << 0)
+
+/* VIDINTCON1 */
+#define S3C_VIDINTCON1_INTVPPEND (1 << 5)
+#define S3C_VIDINTCON1_INTI80PEND (1 << 2)
+#define S3C_VIDINTCON1_INTFRMPEND (1 << 1)
+#define S3C_VIDINTCON1_INTFIFOPEND (1 << 0)
+
+/* WINMAP */
+#define S3C_WINMAP_ENABLE (1 << 24)
+
+/* WxKEYCON0 (1~4) */
+#define S3C_KEYCON0_KEYBLEN_DISABLE (0 << 26)
+#define S3C_KEYCON0_KEYBLEN_ENABLE (1 << 26)
+#define S3C_KEYCON0_KEY_DISABLE (0 << 25)
+#define S3C_KEYCON0_KEY_ENABLE (1 << 25)
+#define S3C_KEYCON0_DIRCON_MATCH_FG (0 << 24)
+#define S3C_KEYCON0_DIRCON_MATCH_BG (1 << 24)
+#define S3C_KEYCON0_COMPKEY(x) (((x) & 0xffffff) << 0)
+
+/* WxKEYCON1 (1~4) */
+#define S3C_KEYCON1_COLVAL(x) (((x) & 0xffffff) << 0)
+
+#endif /* _REGS_FB_H */
diff --git a/arch/arm/plat-s5p/include/plat/regs-fimc.h b/arch/arm/plat-s5p/include/plat/regs-fimc.h
new file mode 100644
index 0000000..26cd622
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/regs-fimc.h
@@ -0,0 +1,446 @@
+/* linux/arch/arm/plat-s5p/include/plat/regs-fimc.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Register definition file for Samsung Camera Interface (FIMC) driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_PLAT_REGS_FIMC_H
+#define __ASM_PLAT_REGS_FIMC_H __FILE__
+
+/*
+ * Register part
+*/
+#define S3C_CIOYSA(__x) (0x18 + (__x) * 4)
+#define S3C_CIOCBSA(__x) (0x28 + (__x) * 4)
+#define S3C_CIOCRSA(__x) (0x38 + (__x) * 4)
+
+#define S3C_CISRCFMT (0x00) /* Input source format */
+#define S3C_CIWDOFST (0x04) /* Window offset */
+#define S3C_CIGCTRL (0x08) /* Global control */
+#define S3C_CIWDOFST2 (0x14) /* Window offset 2 */
+#define S3C_CIOYSA1 (0x18) /* Y 1st frame start address for output DMA */
+#define S3C_CIOYSA2 (0x1c) /* Y 2nd frame start address for output DMA */
+#define S3C_CIOYSA3 (0x20) /* Y 3rd frame start address for output DMA */
+#define S3C_CIOYSA4 (0x24) /* Y 4th frame start address for output DMA */
+#define S3C_CIOCBSA1 (0x28) /* Cb 1st frame start address for output DMA */
+#define S3C_CIOCBSA2 (0x2c) /* Cb 2nd frame start address for output DMA */
+#define S3C_CIOCBSA3 (0x30) /* Cb 3rd frame start address for output DMA */
+#define S3C_CIOCBSA4 (0x34) /* Cb 4th frame start address for output DMA */
+#define S3C_CIOCRSA1 (0x38) /* Cr 1st frame start address for output DMA */
+#define S3C_CIOCRSA2 (0x3c) /* Cr 2nd frame start address for output DMA */
+#define S3C_CIOCRSA3 (0x40) /* Cr 3rd frame start address for output DMA */
+#define S3C_CIOCRSA4 (0x44) /* Cr 4th frame start address for output DMA */
+#define S3C_CITRGFMT (0x48) /* Target image format */
+#define S3C_CIOCTRL (0x4c) /* Output DMA control */
+#define S3C_CISCPRERATIO (0x50) /* Pre-scaler control 1 */
+#define S3C_CISCPREDST (0x54) /* Pre-scaler control 2 */
+#define S3C_CISCCTRL (0x58) /* Main scaler control */
+#define S3C_CITAREA (0x5c) /* Target area */
+#define S3C_CISTATUS (0x64) /* Status */
+#define S3C_CIIMGCPT (0xc0) /* Image capture enable command */
+#define S3C_CICPTSEQ (0xc4) /* Capture sequence */
+#define S3C_CIIMGEFF (0xd0) /* Image effects */
+#define S3C_CIIYSA0 (0xd4) /* Y frame start address for input DMA */
+#define S3C_CIICBSA0 (0xd8) /* Cb frame start address for input DMA */
+#define S3C_CIICRSA0 (0xdc) /* Cr frame start address for input DMA */
+#define S3C_CIILINESKIP_Y (0xec) /* Input DMA Y Line Skip */
+#define S3C_CIILINESKIP_CB (0xf0) /* Input DMA Cb Line Skip */
+#define S3C_CIILINESKIP_CR (0xf4) /* Input DMA Cr Line Skip */
+#define S3C_CIREAL_ISIZE (0xf8) /* Real input DMA image size */
+#define S3C_MSCTRL (0xfc) /* Input DMA control */
+#define S3C_CIOYOFF (0x168) /* Output DMA Y offset */
+#define S3C_CIOCBOFF (0x16c) /* Output DMA CB offset */
+#define S3C_CIOCROFF (0x170) /* Output DMA CR offset */
+#define S3C_CIIYOFF (0x174) /* Input DMA Y offset */
+#define S3C_CIICBOFF (0x178) /* Input DMA CB offset */
+#define S3C_CIICROFF (0x17c) /* Input DMA CR offset */
+#define S3C_ORGISIZE (0x180) /* Input DMA original image size */
+#define S3C_ORGOSIZE (0x184) /* Output DMA original image size */
+#define S3C_CIEXTEN (0x188) /* Real output DMA image size */
+#define S3C_CIDMAPARAM (0x18c) /* DMA parameter */
+#define S3C_CSIIMGFMT (0x194) /* MIPI CSI image format */
+#define S3C_MISC_FIMC (0x198) /* FIMC Clock Source Select */
+
+/*
+ * Macro part
+*/
+#define S3C_CISRCFMT_SOURCEHSIZE(x) ((x) << 16)
+#define S3C_CISRCFMT_SOURCEVSIZE(x) ((x) << 0)
+
+#define S3C_CIWDOFST_WINHOROFST(x) ((x) << 16)
+#define S3C_CIWDOFST_WINVEROFST(x) ((x) << 0)
+
+#define S3C_CIWDOFST2_WINHOROFST2(x) ((x) << 16)
+#define S3C_CIWDOFST2_WINVEROFST2(x) ((x) << 0)
+
+#define S3C_CITRGFMT_TARGETHSIZE(x) (((x) & 0x1fff) << 16)
+#define S3C_CITRGFMT_TARGETVSIZE(x) (((x) & 0x1fff) << 0)
+
+#define S3C_CISCPRERATIO_SHFACTOR(x) ((x) << 28)
+#define S3C_CISCPRERATIO_PREHORRATIO(x) ((x) << 16)
+#define S3C_CISCPRERATIO_PREVERRATIO(x) ((x) << 0)
+
+#define S3C_CISCPREDST_PREDSTWIDTH(x) ((x) << 16)
+#define S3C_CISCPREDST_PREDSTHEIGHT(x) ((x) << 0)
+
+#define S3C_CISCCTRL_MAINHORRATIO(x) ((x) << 16)
+#define S3C_CISCCTRL_MAINVERRATIO(x) ((x) << 0)
+
+#define S3C_CITAREA_TARGET_AREA(x) ((x) << 0)
+
+#define S3C_CISTATUS_GET_FRAME_COUNT(x) (((x) >> 26) & 0x3)
+#define S3C_CISTATUS_GET_FRAME_END(x) (((x) >> 17) & 0x1)
+#define S3C_CISTATUS_GET_LAST_CAPTURE_END(x) (((x) >> 16) & 0x1)
+#define S3C_CISTATUS_GET_LCD_STATUS(x) (((x) >> 9) & 0x1)
+#define S3C_CISTATUS_GET_ENVID_STATUS(x) ((x) & 0x1)
+
+#define S3C_CIIMGEFF_FIN(x) ((x & 0x7) << 26)
+#define S3C_CIIMGEFF_PAT_CB(x) ((x) << 13)
+#define S3C_CIIMGEFF_PAT_CR(x) ((x) << 0)
+
+#define S3C_CIILINESKIP(x) (((x) & 0xf) << 24)
+
+#define S3C_CIREAL_ISIZE_HEIGHT(x) ((x) << 16)
+#define S3C_CIREAL_ISIZE_WIDTH(x) ((x) << 0)
+
+#define S3C_MSCTRL_SUCCESSIVE_COUNT(x) ((x) << 24)
+#define S3C_MSCTRL_GET_INDMA_STATUS(x) ((x) & 0x1)
+
+#define S3C_CIOYOFF_VERTICAL(x) ((x) << 16)
+#define S3C_CIOYOFF_HORIZONTAL(x) ((x) << 0)
+
+#define S3C_CIOCBOFF_VERTICAL(x) ((x) << 16)
+#define S3C_CIOCBOFF_HORIZONTAL(x) ((x) << 0)
+
+#define S3C_CIOCROFF_VERTICAL(x) ((x) << 16)
+#define S3C_CIOCROFF_HORIZONTAL(x) ((x) << 0)
+
+#define S3C_CIIYOFF_VERTICAL(x) ((x) << 16)
+#define S3C_CIIYOFF_HORIZONTAL(x) ((x) << 0)
+
+#define S3C_CIICBOFF_VERTICAL(x) ((x) << 16)
+#define S3C_CIICBOFF_HORIZONTAL(x) ((x) << 0)
+
+#define S3C_CIICROFF_VERTICAL(x) ((x) << 16)
+#define S3C_CIICROFF_HORIZONTAL(x) ((x) << 0)
+
+#define S3C_ORGISIZE_VERTICAL(x) ((x) << 16)
+#define S3C_ORGISIZE_HORIZONTAL(x) ((x) << 0)
+
+#define S3C_ORGOSIZE_VERTICAL(x) ((x) << 16)
+#define S3C_ORGOSIZE_HORIZONTAL(x) ((x) << 0)
+
+#define S3C_CIEXTEN_TARGETH_EXT(x) (((x) & 0x2000) << 26)
+#define S3C_CIEXTEN_TARGETV_EXT(x) (((x) & 0x2000) << 24)
+#define S3C_CIEXTEN_MAINHORRATIO_EXT(x) (((x) & 0x3F) << 10)
+#define S3C_CIEXTEN_MAINVERRATIO_EXT(x) ((x) & 0x3F)
+
+/*
+ * Bit definition part
+*/
+/* Source format register */
+#define S3C_CISRCFMT_ITU601_8BIT (1 << 31)
+#define S3C_CISRCFMT_ITU656_8BIT (0 << 31)
+#define S3C_CISRCFMT_ITU601_16BIT (1 << 29)
+#define S3C_CISRCFMT_ORDER422_YCBYCR (0 << 14)
+#define S3C_CISRCFMT_ORDER422_YCRYCB (1 << 14)
+#define S3C_CISRCFMT_ORDER422_CBYCRY (2 << 14)
+#define S3C_CISRCFMT_ORDER422_CRYCBY (3 << 14)
+#define S3C_CISRCFMT_ORDER422_Y4CBCRCBCR (0 << 14) /* ITU601 16bit only */
+#define S3C_CISRCFMT_ORDER422_Y4CRCBCRCB (1 << 14) /* ITU601 16bit only */
+
+/* Window offset register */
+#define S3C_CIWDOFST_WINOFSEN (1 << 31)
+#define S3C_CIWDOFST_CLROVFIY (1 << 30)
+#define S3C_CIWDOFST_CLROVRLB (1 << 29)
+#define S3C_CIWDOFST_WINHOROFST_MASK (0x7ff << 16)
+#define S3C_CIWDOFST_CLROVFICB (1 << 15)
+#define S3C_CIWDOFST_CLROVFICR (1 << 14)
+#define S3C_CIWDOFST_WINVEROFST_MASK (0xfff << 0)
+
+/* Global control register */
+#define S3C_CIGCTRL_SWRST (1 << 31)
+#define S3C_CIGCTRL_CAMRST_A (1 << 30)
+#define S3C_CIGCTRL_SELCAM_ITU_B (0 << 29)
+#define S3C_CIGCTRL_SELCAM_ITU_A (1 << 29)
+#define S3C_CIGCTRL_SELCAM_ITU_MASK (1 << 29)
+#define S3C_CIGCTRL_TESTPATTERN_NORMAL (0 << 27)
+#define S3C_CIGCTRL_TESTPATTERN_COLOR_BAR (1 << 27)
+#define S3C_CIGCTRL_TESTPATTERN_HOR_INC (2 << 27)
+#define S3C_CIGCTRL_TESTPATTERN_VER_INC (3 << 27)
+#define S3C_CIGCTRL_TESTPATTERN_MASK (3 << 27)
+#define S3C_CIGCTRL_TESTPATTERN_SHIFT (27)
+#define S3C_CIGCTRL_INVPOLPCLK (1 << 26)
+#define S3C_CIGCTRL_INVPOLVSYNC (1 << 25)
+#define S3C_CIGCTRL_INVPOLHREF (1 << 24)
+#define S3C_CIGCTRL_IRQ_OVFEN (1 << 22)
+#define S3C_CIGCTRL_HREF_MASK (1 << 21)
+#define S3C_CIGCTRL_IRQ_EDGE (0 << 20)
+#define S3C_CIGCTRL_IRQ_LEVEL (1 << 20)
+#define S3C_CIGCTRL_IRQ_CLR (1 << 19)
+#define S3C_CIGCTRL_IRQ_DISABLE (0 << 16)
+#define S3C_CIGCTRL_IRQ_ENABLE (1 << 16)
+#define S3C_CIGCTRL_SHADOW_DISABLE (1 << 12)
+#define S3C_CIGCTRL_CAM_JPEG (1 << 8)
+#define S3C_CIGCTRL_SELCAM_MIPI_B (0 << 7)
+#define S3C_CIGCTRL_SELCAM_MIPI_A (1 << 7)
+#define S3C_CIGCTRL_SELCAM_MIPI_MASK (1 << 7)
+#define S3C_CIGCTRL_SELWB_CAMIF_CAMERA (0 << 6)
+#define S3C_CIGCTRL_SELWB_CAMIF_WRITEBACK (1 << 6)
+#define S3C_CIGCTRL_SELWB_CAMIF_MASK (1 << 6)
+#define S3C_CIGCTRL_CSC_ITU601 (0 << 5)
+#define S3C_CIGCTRL_CSC_ITU709 (1 << 5)
+#define S3C_CIGCTRL_CSC_MASK (1 << 5)
+#define S3C_CIGCTRL_INVPOLHSYNC (1 << 4)
+#define S3C_CIGCTRL_SELCAM_FIMC_ITU (0 << 3)
+#define S3C_CIGCTRL_SELCAM_FIMC_MIPI (1 << 3)
+#define S3C_CIGCTRL_SELCAM_FIMC_MASK (1 << 3)
+#define S3C_CIGCTRL_PROGRESSIVE (0 << 0)
+#define S3C_CIGCTRL_INTERLACE (1 << 0)
+
+/* Window offset2 register */
+#define S3C_CIWDOFST_WINHOROFST2_MASK (0xfff << 16)
+#define S3C_CIWDOFST_WINVEROFST2_MASK (0xfff << 16)
+
+/* Target format register */
+#define S3C_CITRGFMT_INROT90_CLOCKWISE (1 << 31)
+#define S3C_CITRGFMT_OUTFORMAT_YCBCR420 (0 << 29)
+#define S3C_CITRGFMT_OUTFORMAT_YCBCR422 (1 << 29)
+#define S3C_CITRGFMT_OUTFORMAT_YCBCR422_1PLANE (2 << 29)
+#define S3C_CITRGFMT_OUTFORMAT_RGB (3 << 29)
+#define S3C_CITRGFMT_OUTFORMAT_MASK (3 << 29)
+#define S3C_CITRGFMT_FLIP_SHIFT (14)
+#define S3C_CITRGFMT_FLIP_NORMAL (0 << 14)
+#define S3C_CITRGFMT_FLIP_X_MIRROR (1 << 14)
+#define S3C_CITRGFMT_FLIP_Y_MIRROR (2 << 14)
+#define S3C_CITRGFMT_FLIP_180 (3 << 14)
+#define S3C_CITRGFMT_FLIP_MASK (3 << 14)
+#define S3C_CITRGFMT_OUTROT90_CLOCKWISE (1 << 13)
+#define S3C_CITRGFMT_TARGETV_MASK (0x1fff << 0)
+#define S3C_CITRGFMT_TARGETH_MASK (0x1fff << 16)
+
+/* Output DMA control register */
+#define S3C_CIOCTRL_WEAVE_OUT (1 << 31)
+#define S3C_CIOCTRL_WEAVE_MASK (1 << 31)
+#define S3C_CIOCTRL_ORDER2P_LSB_CBCR (0 << 24)
+#define S3C_CIOCTRL_ORDER2P_LSB_CRCB (1 << 24)
+#define S3C_CIOCTRL_ORDER2P_MSB_CRCB (2 << 24)
+#define S3C_CIOCTRL_ORDER2P_MSB_CBCR (3 << 24)
+#define S3C_CIOCTRL_ORDER2P_SHIFT (24)
+#define S3C_CIOCTRL_ORDER2P_MASK (3 << 24)
+#define S3C_CIOCTRL_YCBCR_3PLANE (0 << 3)
+#define S3C_CIOCTRL_YCBCR_2PLANE (1 << 3)
+#define S3C_CIOCTRL_YCBCR_PLANE_MASK (1 << 3)
+#define S3C_CIOCTRL_LASTIRQ_ENABLE (1 << 2)
+#define S3C_CIOCTRL_ORDER422_YCBYCR (0 << 0)
+#define S3C_CIOCTRL_ORDER422_YCRYCB (1 << 0)
+#define S3C_CIOCTRL_ORDER422_CBYCRY (2 << 0)
+#define S3C_CIOCTRL_ORDER422_CRYCBY (3 << 0)
+#define S3C_CIOCTRL_ORDER422_MASK (3 << 0)
+
+/* Main scaler control register */
+#define S3C_CISCCTRL_SCALERBYPASS (1 << 31)
+#define S3C_CISCCTRL_SCALEUP_H (1 << 30)
+#define S3C_CISCCTRL_SCALEUP_V (1 << 29)
+#define S3C_CISCCTRL_CSCR2Y_NARROW (0 << 28)
+#define S3C_CISCCTRL_CSCR2Y_WIDE (1 << 28)
+#define S3C_CISCCTRL_CSCY2R_NARROW (0 << 27)
+#define S3C_CISCCTRL_CSCY2R_WIDE (1 << 27)
+#define S3C_CISCCTRL_LCDPATHEN_FIFO (1 << 26)
+#define S3C_CISCCTRL_PROGRESSIVE (0 << 25)
+#define S3C_CISCCTRL_INTERLACE (1 << 25)
+#define S3C_CISCCTRL_SCAN_MASK (1 << 25)
+#define S3C_CISCCTRL_SCALERSTART (1 << 15)
+#define S3C_CISCCTRL_INRGB_FMT_RGB565 (0 << 13)
+#define S3C_CISCCTRL_INRGB_FMT_RGB666 (1 << 13)
+#define S3C_CISCCTRL_INRGB_FMT_RGB888 (2 << 13)
+#define S3C_CISCCTRL_INRGB_FMT_RGB_MASK (3 << 13)
+#define S3C_CISCCTRL_OUTRGB_FMT_RGB565 (0 << 11)
+#define S3C_CISCCTRL_OUTRGB_FMT_RGB666 (1 << 11)
+#define S3C_CISCCTRL_OUTRGB_FMT_RGB888 (2 << 11)
+#define S3C_CISCCTRL_OUTRGB_FMT_RGB_MASK (3 << 11)
+#define S3C_CISCCTRL_EXTRGB_NORMAL (0 << 10)
+#define S3C_CISCCTRL_EXTRGB_EXTENSION (1 << 10)
+#define S3C_CISCCTRL_ONE2ONE (1 << 9)
+#define S3C_CISCCTRL_MAIN_V_RATIO_MASK (0x1ff << 0)
+#define S3C_CISCCTRL_MAIN_H_RATIO_MASK (0x1ff << 16)
+
+/* Status register */
+#define S3C_CISTATUS_OVFIY (1 << 31)
+#define S3C_CISTATUS_OVFICB (1 << 30)
+#define S3C_CISTATUS_OVFICR (1 << 29)
+#define S3C_CISTATUS_VSYNC (1 << 28)
+#define S3C_CISTATUS_WINOFSTEN (1 << 25)
+#define S3C_CISTATUS_IMGCPTEN (1 << 22)
+#define S3C_CISTATUS_IMGCPTENSC (1 << 21)
+#define S3C_CISTATUS_VSYNC_A (1 << 20)
+#define S3C_CISTATUS_VSYNC_B (1 << 19)
+#define S3C_CISTATUS_OVRLB (1 << 18)
+#define S3C_CISTATUS_FRAMEEND (1 << 17)
+#define S3C_CISTATUS_LASTCAPTUREEND (1 << 16)
+#define S3C_CISTATUS_VVALID_A (1 << 15)
+#define S3C_CISTATUS_VVALID_B (1 << 14)
+
+/* Image capture enable register */
+#define S3C_CIIMGCPT_IMGCPTEN (1 << 31)
+#define S3C_CIIMGCPT_IMGCPTEN_SC (1 << 30)
+#define S3C_CIIMGCPT_CPT_FREN_ENABLE (1 << 25)
+#define S3C_CIIMGCPT_CPT_FRMOD_EN (0 << 18)
+#define S3C_CIIMGCPT_CPT_FRMOD_CNT (1 << 18)
+
+/* Image effects register */
+#define S3C_CIIMGEFF_IE_DISABLE (0 << 30)
+#define S3C_CIIMGEFF_IE_ENABLE (1 << 30)
+#define S3C_CIIMGEFF_IE_SC_BEFORE (0 << 29)
+#define S3C_CIIMGEFF_IE_SC_AFTER (1 << 29)
+#define S3C_CIIMGEFF_FIN_BYPASS (0 << 26)
+#define S3C_CIIMGEFF_FIN_ARBITRARY (1 << 26)
+#define S3C_CIIMGEFF_FIN_NEGATIVE (2 << 26)
+#define S3C_CIIMGEFF_FIN_ARTFREEZE (3 << 26)
+#define S3C_CIIMGEFF_FIN_EMBOSSING (4 << 26)
+#define S3C_CIIMGEFF_FIN_SILHOUETTE (5 << 26)
+#define S3C_CIIMGEFF_FIN_MASK (7 << 26)
+#define S3C_CIIMGEFF_PAT_CBCR_MASK ((0xff < 13) | (0xff < 0))
+
+/* Real input DMA size register */
+#define S3C_CIREAL_ISIZE_AUTOLOAD_ENABLE (1 << 31)
+#define S3C_CIREAL_ISIZE_ADDR_CH_DISABLE (1 << 30)
+#define S3C_CIREAL_ISIZE_HEIGHT_MASK (0x3FFF << 16)
+#define S3C_CIREAL_ISIZE_WIDTH_MASK (0x3FFF << 0)
+
+/* Input DMA control register */
+#define S3C_MSCTRL_FIELD_MASK (1 << 31)
+#define S3C_MSCTRL_FIELD_WEAVE (1 << 31)
+#define S3C_MSCTRL_FIELD_NORMAL (0 << 31)
+#define S3C_MSCTRL_BURST_CNT (24)
+#define S3C_MSCTRL_BURST_CNT_MASK (0xf << 24)
+#define S3C_MSCTRL_ORDER2P_LSB_CBCR (0 << 16)
+#define S3C_MSCTRL_ORDER2P_LSB_CRCB (1 << 16)
+#define S3C_MSCTRL_ORDER2P_MSB_CRCB (2 << 16)
+#define S3C_MSCTRL_ORDER2P_MSB_CBCR (3 << 16)
+#define S3C_MSCTRL_ORDER2P_SHIFT (16)
+#define S3C_MSCTRL_ORDER2P_SHIFT_MASK (0x3 << 16)
+#define S3C_MSCTRL_C_INT_IN_3PLANE (0 << 15)
+#define S3C_MSCTRL_C_INT_IN_2PLANE (1 << 15)
+#define S3C_MSCTRL_FLIP_SHIFT (13)
+#define S3C_MSCTRL_FLIP_NORMAL (0 << 13)
+#define S3C_MSCTRL_FLIP_X_MIRROR (1 << 13)
+#define S3C_MSCTRL_FLIP_Y_MIRROR (2 << 13)
+#define S3C_MSCTRL_FLIP_180 (3 << 13)
+#define S3C_MSCTRL_FLIP_MASK (3 << 13)
+#define S3C_MSCTRL_ORDER422_CRYCBY (0 << 4)
+#define S3C_MSCTRL_ORDER422_YCRYCB (1 << 4)
+#define S3C_MSCTRL_ORDER422_CBYCRY (2 << 4)
+#define S3C_MSCTRL_ORDER422_YCBYCR (3 << 4)
+#define S3C_MSCTRL_INPUT_EXTCAM (0 << 3)
+#define S3C_MSCTRL_INPUT_MEMORY (1 << 3)
+#define S3C_MSCTRL_INPUT_MASK (1 << 3)
+#define S3C_MSCTRL_INFORMAT_YCBCR420 (0 << 1)
+#define S3C_MSCTRL_INFORMAT_YCBCR422 (1 << 1)
+#define S3C_MSCTRL_INFORMAT_YCBCR422_1PLANE (2 << 1)
+#define S3C_MSCTRL_INFORMAT_RGB (3 << 1)
+#define S3C_MSCTRL_ENVID (1 << 0)
+
+/* DMA parameter register */
+#define S3C_CIDMAPARAM_R_MODE_LINEAR (0 << 29)
+#define S3C_CIDMAPARAM_R_MODE_CONFTILE (1 << 29)
+#define S3C_CIDMAPARAM_R_MODE_16X16 (2 << 29)
+#define S3C_CIDMAPARAM_R_MODE_64X32 (3 << 29)
+#define S3C_CIDMAPARAM_R_MODE_MASK (3 << 29)
+#define S3C_CIDMAPARAM_R_TILE_HSIZE_64 (0 << 24)
+#define S3C_CIDMAPARAM_R_TILE_HSIZE_128 (1 << 24)
+#define S3C_CIDMAPARAM_R_TILE_HSIZE_256 (2 << 24)
+#define S3C_CIDMAPARAM_R_TILE_HSIZE_512 (3 << 24)
+#define S3C_CIDMAPARAM_R_TILE_HSIZE_1024 (4 << 24)
+#define S3C_CIDMAPARAM_R_TILE_HSIZE_2048 (5 << 24)
+#define S3C_CIDMAPARAM_R_TILE_HSIZE_4096 (6 << 24)
+#define S3C_CIDMAPARAM_R_TILE_VSIZE_1 (0 << 20)
+#define S3C_CIDMAPARAM_R_TILE_VSIZE_2 (1 << 20)
+#define S3C_CIDMAPARAM_R_TILE_VSIZE_4 (2 << 20)
+#define S3C_CIDMAPARAM_R_TILE_VSIZE_8 (3 << 20)
+#define S3C_CIDMAPARAM_R_TILE_VSIZE_16 (4 << 20)
+#define S3C_CIDMAPARAM_R_TILE_VSIZE_32 (5 << 20)
+#define S3C_CIDMAPARAM_W_MODE_LINEAR (0 << 13)
+#define S3C_CIDMAPARAM_W_MODE_CONFTILE (1 << 13)
+#define S3C_CIDMAPARAM_W_MODE_16X16 (2 << 13)
+#define S3C_CIDMAPARAM_W_MODE_64X32 (3 << 13)
+#define S3C_CIDMAPARAM_W_MODE_MASK (3 << 13)
+#define S3C_CIDMAPARAM_W_TILE_HSIZE_64 (0 << 8)
+#define S3C_CIDMAPARAM_W_TILE_HSIZE_128 (1 << 8)
+#define S3C_CIDMAPARAM_W_TILE_HSIZE_256 (2 << 8)
+#define S3C_CIDMAPARAM_W_TILE_HSIZE_512 (3 << 8)
+#define S3C_CIDMAPARAM_W_TILE_HSIZE_1024 (4 << 8)
+#define S3C_CIDMAPARAM_W_TILE_HSIZE_2048 (5 << 8)
+#define S3C_CIDMAPARAM_W_TILE_HSIZE_4096 (6 << 8)
+#define S3C_CIDMAPARAM_W_TILE_VSIZE_1 (0 << 4)
+#define S3C_CIDMAPARAM_W_TILE_VSIZE_2 (1 << 4)
+#define S3C_CIDMAPARAM_W_TILE_VSIZE_4 (2 << 4)
+#define S3C_CIDMAPARAM_W_TILE_VSIZE_8 (3 << 4)
+#define S3C_CIDMAPARAM_W_TILE_VSIZE_16 (4 << 4)
+#define S3C_CIDMAPARAM_W_TILE_VSIZE_32 (5 << 4)
+
+/* Gathering Extension register */
+#define S3C_CIEXTEN_TARGETH_EXT_MASK (1 << 26)
+#define S3C_CIEXTEN_TARGETV_EXT_MASK (1 << 24)
+#define S3C_CIEXTEN_MAINHORRATIO_EXT_MASK (0x3F << 10)
+#define S3C_CIEXTEN_MAINVERRATIO_EXT_MASK (0x3F)
+#define S3C_CIEXTEN_YUV444_OUT (1 << 22)
+
+/* FIMC Clock Source Select register */
+#define S3C_CLKSRC_HCLK (0 << 1)
+#define S3C_CLKSRC_HCLK_MASK (1 << 1)
+#define S3C_CLKSRC_SCLK (1 << 1)
+
+/* FIMC GPIO */
+#define S5PV210_GPE0_0_CAM_A_PCLK (0x2 << 0)
+#define S5PV210_GPE0_0_GPIO_INT8_0 (0xf << 0)
+
+#define S5PV210_GPE0_1_CAM_A_VSYNC (0x2 << 4)
+#define S5PV210_GPE0_1_GPIO_INT8_1 (0xf << 4)
+
+#define S5PV210_GPE0_2_CAM_A_HREF (0x2 << 8)
+#define S5PV210_GPE0_2_GPIO_INT8_2 (0xf << 8)
+
+#define S5PV210_GPE0_3_CAM_A_DATA_0 (0x2 << 12)
+#define S5PV210_GPE0_3_GPIO_INT8_3 (0xf << 12)
+
+#define S5PV210_GPE0_4_CAM_A_DATA_1 (0x2 << 16)
+#define S5PV210_GPE0_4_GPIO_INT8_4 (0xf << 16)
+
+#define S5PV210_GPE0_5_CAM_A_DATA_2 (0x2 << 20)
+#define S5PV210_GPE0_5_GPIO_INT8_5 (0xf << 20)
+
+#define S5PV210_GPE0_6_CAM_A_DATA_3 (0x2 << 24)
+#define S5PV210_GPE0_6_GPIO_INT8_6 (0xf << 24)
+
+#define S5PV210_GPE0_7_CAM_A_DATA_4 (0x2 << 28)
+#define S5PV210_GPE0_7_GPIO_INT8_7 (0xf << 28)
+
+#define S5PV210_GPE1_0_CAM_A_DATA_5 (0x2 << 0)
+#define S5PV210_GPE1_1_CAM_A_DATA_6 (0x2 << 4)
+#define S5PV210_GPE1_2_CAM_A_DATA_7 (0x2 << 8)
+#define S5PV210_GPE1_3_CAM_A_CLKOUT (0x2 << 12)
+#define S5PV210_GPE1_4_CAM_A_FIELD (0x2 << 16)
+
+#define S5PV210_GPJ0_0_CAM_B_DATA_0 (0x3 << 0)
+#define S5PV210_GPJ0_1_CAM_B_DATA_1 (0x3 << 4)
+#define S5PV210_GPJ0_2_CAM_B_DATA_2 (0x3 << 8)
+#define S5PV210_GPJ0_3_CAM_B_DATA_3 (0x3 << 12)
+#define S5PV210_GPJ0_4_CAM_B_DATA_4 (0x3 << 16)
+#define S5PV210_GPJ0_5_CAM_B_DATA_5 (0x3 << 20)
+#define S5PV210_GPJ0_6_CAM_B_DATA_6 (0x3 << 24)
+#define S5PV210_GPJ0_7_CAM_B_DATA_7 (0x3 << 28)
+
+#define S5PV210_GPJ1_0_CAM_B_PCLK (0x3 << 0)
+#define S5PV210_GPJ1_1_CAM_B_VSYNC (0x3 << 4)
+#define S5PV210_GPJ1_2_CAM_B_HREF (0x3 << 8)
+#define S5PV210_GPJ1_3_CAM_B_FIELD (0x3 << 12)
+#define S5PV210_GPJ1_4_CAM_B_CLKOUT (0x3 << 16)
+
+#endif /* __ASM_PLAT_REGS_FIMC_H */
diff --git a/arch/arm/plat-s5p/include/plat/regs-iis.h b/arch/arm/plat-s5p/include/plat/regs-iis.h
new file mode 100644
index 0000000..db94a13
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/regs-iis.h
@@ -0,0 +1,147 @@
+/* linux/include/asm-arm/plat-s3c24xx/regs-s3c2412-iis.h
+ *
+ * Copyright 2007 Simtec Electronics <linux@simtec.co.uk>
+ * http://armlinux.simtec.co.uk/
+ *
+ * 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.
+ *
+ * S3C2412 IIS register definition
+*/
+
+#ifndef __ASM_ARCH_REGS_S3C2412_IIS_H
+#define __ASM_ARCH_REGS_S3C2412_IIS_H
+
+#define S3C2412_IISCON (0x00)
+#define S3C2412_IISMOD (0x04)
+#define S3C2412_IISFIC (0x08)
+#define S3C2412_IISPSR (0x0C)
+#define S3C2412_IISTXD (0x10)
+#define S3C2412_IISRXD (0x14)
+#define S5P_IISFICS (0x18)
+#define S5P_IISTXDS (0x1C)
+#define S5P_IISAHB (0x20)
+#define S5P_IISSTR (0x24)
+#define S5P_IISSIZE (0x28)
+#define S5P_IISTRNCNT (0x2C)
+#define S5P_IISADDR0 (0x30)
+#define S5P_IISADDR1 (0x34)
+#define S5P_IISADDR2 (0x38)
+#define S5P_IISADDR3 (0x3C)
+
+#define S5P_IISCON_FTXSURSTAT (1 << 24)
+#define S5P_IISCON_FTXSURINTEN (1 << 23)
+#define S5P_IISCON_TXSDMAPAUSE (1 << 20)
+#define S5P_IISCON_TXSDMACTIVE (1 << 18)
+#define S5P_IISCON_FTXURSTATUS (1 << 17)
+#define S5P_IISCON_FTXURINTEN (1 << 16)
+
+#define S3C2412_IISCON_LRINDEX (1 << 11)
+#define S3C2412_IISCON_TXFIFO_EMPTY (1 << 10)
+#define S3C2412_IISCON_RXFIFO_EMPTY (1 << 9)
+#define S3C2412_IISCON_TXFIFO_FULL (1 << 8)
+#define S3C2412_IISCON_RXFIFO_FULL (1 << 7)
+#define S3C2412_IISCON_TXDMA_PAUSE (1 << 6)
+#define S3C2412_IISCON_RXDMA_PAUSE (1 << 5)
+#define S3C2412_IISCON_TXCH_PAUSE (1 << 4)
+#define S3C2412_IISCON_RXCH_PAUSE (1 << 3)
+#define S3C2412_IISCON_TXDMA_ACTIVE (1 << 2)
+#define S3C2412_IISCON_RXDMA_ACTIVE (1 << 1)
+#define S3C2412_IISCON_IIS_ACTIVE (1 << 0)
+
+#define S3C64XX_IISMOD_OPPCLK (3<<30)
+
+#define S5P_IISMOD_TXSLP (1<<28)
+#define S5P_IISMOD_BLCPMASK (3<<24)
+#define S5P_IISMOD_BLCSMASK (3<<26)
+
+#define S3C64XX_IISMOD_BLC_16BIT (0 << 13)
+#define S3C64XX_IISMOD_BLC_8BIT (1 << 13)
+#define S3C64XX_IISMOD_BLC_24BIT (2 << 13)
+#define S3C64XX_IISMOD_BLC_MASK (3 << 13)
+
+#define S3C64XX_IISMOD_IMSMASK (3 << 10)
+#define S3C64XX_IISMOD_IMS_PCLK (0 << 10)
+#define S3C64XX_IISMOD_IMS_SYSMUX (1 << 10)
+#define S3C64XX_CLKSRC_I2SEXT (3 << 10)
+#define S3C64XX_CDCLKSRC_EXT (5 << 10)
+
+#define S3C2412_IISMOD_MASTER_INTERNAL (0 << 10)
+#define S3C2412_IISMOD_MASTER_EXTERNAL (1 << 10)
+#define S3C2412_IISMOD_SLAVE (2 << 10)
+#define S3C2412_IISMOD_MASTER_MASK (3 << 10)
+#define S3C2412_IISMOD_MODE_TXONLY (0 << 8)
+#define S3C2412_IISMOD_MODE_RXONLY (1 << 8)
+#define S3C2412_IISMOD_MODE_TXRX (2 << 8)
+#define S3C2412_IISMOD_MODE_MASK (3 << 8)
+#define S3C2412_IISMOD_LR_LLOW (0 << 7)
+#define S3C2412_IISMOD_LR_RLOW (1 << 7)
+#define S3C2412_IISMOD_SDF_IIS (0 << 5)
+#define S3C2412_IISMOD_SDF_MSB (1 << 5)
+#define S3C2412_IISMOD_SDF_LSB (2 << 5)
+#define S3C2412_IISMOD_SDF_MASK (3 << 5)
+#define S3C2412_IISMOD_RCLK_256FS (0 << 3)
+#define S3C2412_IISMOD_RCLK_512FS (1 << 3)
+#define S3C2412_IISMOD_RCLK_384FS (2 << 3)
+#define S3C2412_IISMOD_RCLK_768FS (3 << 3)
+#define S3C2412_IISMOD_RCLK_MASK (3 << 3)
+#define S3C2412_IISMOD_BCLK_32FS (0 << 1)
+#define S3C2412_IISMOD_BCLK_48FS (1 << 1)
+#define S3C2412_IISMOD_BCLK_16FS (2 << 1)
+#define S3C2412_IISMOD_BCLK_24FS (3 << 1)
+#define S3C2412_IISMOD_BCLK_MASK (3 << 1)
+#define S3C2412_IISMOD_8BIT (1 << 0)
+
+#define S3C64XX_IISMOD_CDCLKCON (1 << 12)
+
+#define S3C2412_IISPSR_PSREN (1 << 15)
+
+#define S3C2412_IISFIC_TXFLUSH (1 << 15)
+#define S3C2412_IISFIC_RXFLUSH (1 << 7)
+#define S3C2412_IISFIC_TXCOUNT(x) (((x) >> 8) & 0xf)
+#define S3C2412_IISFIC_RXCOUNT(x) (((x) >> 0) & 0xf)
+
+#define S5P_IISAHB_INTENLVL3 (1<<27)
+#define S5P_IISAHB_INTENLVL2 (1<<26)
+#define S5P_IISAHB_INTENLVL1 (1<<25)
+#define S5P_IISAHB_INTENLVL0 (1<<24)
+#define S5P_IISAHB_LVL3INT (1<<23)
+#define S5P_IISAHB_LVL2INT (1<<22)
+#define S5P_IISAHB_LVL1INT (1<<21)
+#define S5P_IISAHB_LVL0INT (1<<20)
+#define S5P_IISAHB_CLRLVL3 (1<<19)
+#define S5P_IISAHB_CLRLVL2 (1<<18)
+#define S5P_IISAHB_CLRLVL1 (1<<17)
+#define S5P_IISAHB_CLRLVL0 (1<<16)
+#define S5P_IISAHB_DMARLD (1<<5)
+#define S5P_IISAHB_DISRLDINT (1<<3)
+#define S5P_IISAHB_DMAEND (1<<2)
+#define S5P_IISAHB_DMACLR (1<<1)
+#define S5P_IISAHB_DMAEN (1<<0)
+
+#define S5P_IISSIZE_SHIFT (16)
+#define S5P_IISSIZE_TRNMSK (0xffff)
+#define S5P_IISTRNCNT_MASK (0xffffff)
+
+#define S5P_IISADDR_MASK (0x3fffff)
+#define S5P_IISADDR_SHIFT (10)
+#define S5P_IISADDR_ENSTOP (1<<0)
+
+/* clock sources */
+#define S3C_IISMOD_IMSMASK (3<<10)
+#define S3C_IISMOD_MSTPCLK (0<<10)
+#define S3C_IISMOD_MSTCLKAUDIO (1<<10)
+#define S3C_IISMOD_SLVPCLK (2<<10)
+#define S3C_IISMOD_SLVI2SCLK (3<<10)
+
+#define S3C_CLKSRC_PCLK S3C_IISMOD_MSTPCLK
+#define S3C_CLKSRC_CLKAUDIO S3C_IISMOD_MSTCLKAUDIO
+#define S3C_CLKSRC_SLVPCLK S3C_IISMOD_SLVPCLK
+#define S3C_CLKSRC_I2SEXT S3C_IISMOD_SLVI2SCLK
+#define S3C_CDCLKSRC_INT (4<<10)
+#define S3C_CDCLKSRC_EXT (5<<10)
+
+
+#endif /* __ASM_ARCH_REGS_S3C2412_IIS_H */
+
diff --git a/arch/arm/plat-s5p/include/plat/regs-ipc.h b/arch/arm/plat-s5p/include/plat/regs-ipc.h
new file mode 100644
index 0000000..4d1172a
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/regs-ipc.h
@@ -0,0 +1,147 @@
+/* linux/arch/arm/plat-s5p/include/plat/regs-ipc.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Register definition file for IPC driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef _REGS_IPC_H
+#define _REGS_IPC_H
+
+#define S3C_IPCREG(x) (x)
+
+#define IPC_2D_ENABLE 0x10000
+#define IPC_HOR_SCALING_ENABLE 0x8000
+
+/*************************************************************************
+ * Registers
+ ************************************************************************/
+#define S3C_IPC_ENABLE S3C_IPCREG(0x00)
+#define S3C_IPC_SRESET S3C_IPCREG(0x04)
+#define S3C_IPC_SHADOW_UPDATE S3C_IPCREG(0x08)
+#define S3C_IPC_FIELD_ID S3C_IPCREG(0x0c)
+#define S3C_IPC_MODE S3C_IPCREG(0x10)
+#define S3C_IPC_PEL_RATE_CTRL S3C_IPCREG(0x1C)
+#define S3C_IPC_ENDIAN_MODE S3C_IPCREG(0x3C)
+#define S3C_IPC_SRC_WIDTH S3C_IPCREG(0x4C)
+#define S3C_IPC_SRC_HEIGHT S3C_IPCREG(0x50)
+#define S3C_IPC_DST_WIDTH S3C_IPCREG(0x5C)
+#define S3C_IPC_DST_HEIGHT S3C_IPCREG(0x60)
+#define S3C_IPC_H_RATIO S3C_IPCREG(0x64)
+#define S3C_IPC_V_RATIO S3C_IPCREG(0x68)
+
+#define S3C_IPC_POLY8_Y0_LL S3C_IPCREG(0x6C)
+#define S3C_IPC_POLY8_Y0_LH S3C_IPCREG(0x70)
+#define S3C_IPC_POLY8_Y0_HL S3C_IPCREG(0x74)
+#define S3C_IPC_POLY8_Y0_HH S3C_IPCREG(0x78)
+#define S3C_IPC_POLY8_Y1_LL S3C_IPCREG(0x7C)
+#define S3C_IPC_POLY8_Y1_LH S3C_IPCREG(0x80)
+#define S3C_IPC_POLY8_Y1_HL S3C_IPCREG(0x84)
+#define S3C_IPC_POLY8_Y1_HH S3C_IPCREG(0x88)
+#define S3C_IPC_POLY8_Y2_LL S3C_IPCREG(0x8C)
+#define S3C_IPC_POLY8_Y2_LH S3C_IPCREG(0x90)
+#define S3C_IPC_POLY8_Y2_HL S3C_IPCREG(0x94)
+#define S3C_IPC_POLY8_Y2_HH S3C_IPCREG(0x98)
+#define S3C_IPC_POLY8_Y3_LL S3C_IPCREG(0x9C)
+#define S3C_IPC_POLY8_Y3_LH S3C_IPCREG(0xA0)
+#define S3C_IPC_POLY8_Y3_HL S3C_IPCREG(0xA4)
+#define S3C_IPC_POLY8_Y3_HH S3C_IPCREG(0xA8)
+#define S3C_IPC_POLY4_Y0_LL S3C_IPCREG(0xEC)
+#define S3C_IPC_POLY4_Y0_LH S3C_IPCREG(0xF0)
+#define S3C_IPC_POLY4_Y0_HL S3C_IPCREG(0xF4)
+#define S3C_IPC_POLY4_Y0_HH S3C_IPCREG(0xF8)
+#define S3C_IPC_POLY4_Y1_LL S3C_IPCREG(0xFC)
+#define S3C_IPC_POLY4_Y1_LH S3C_IPCREG(0x100)
+#define S3C_IPC_POLY4_Y1_HL S3C_IPCREG(0x104)
+#define S3C_IPC_POLY4_Y1_HH S3C_IPCREG(0x108)
+#define S3C_IPC_POLY4_Y2_LL S3C_IPCREG(0x10C)
+#define S3C_IPC_POLY4_Y2_LH S3C_IPCREG(0x110)
+#define S3C_IPC_POLY4_Y2_HL S3C_IPCREG(0x114)
+#define S3C_IPC_POLY4_Y2_HH S3C_IPCREG(0x118)
+#define S3C_IPC_POLY4_Y3_LL S3C_IPCREG(0x11C)
+#define S3C_IPC_POLY4_Y3_LH S3C_IPCREG(0x120)
+#define S3C_IPC_POLY4_Y3_HL S3C_IPCREG(0x124)
+#define S3C_IPC_POLY4_Y3_HH S3C_IPCREG(0x128)
+#define S3C_IPC_POLY4_C0_LL S3C_IPCREG(0x12C)
+#define S3C_IPC_POLY4_C0_LH S3C_IPCREG(0x130)
+#define S3C_IPC_POLY4_C0_HL S3C_IPCREG(0x134)
+#define S3C_IPC_POLY4_C0_HH S3C_IPCREG(0x138)
+#define S3C_IPC_POLY4_C1_LL S3C_IPCREG(0x13C)
+#define S3C_IPC_POLY4_C1_LH S3C_IPCREG(0x140)
+#define S3C_IPC_POLY4_C1_HL S3C_IPCREG(0x144)
+#define S3C_IPC_POLY4_C1_HH S3C_IPCREG(0x148)
+#define S3C_IPC_BYPASS S3C_IPCREG(0x200)
+#define S3C_IPC_PP_SATURATION S3C_IPCREG(0x20C)
+#define S3C_IPC_PP_SHARPNESS S3C_IPCREG(0x210)
+#define S3C_IPC_PP_LINE_EQ0 S3C_IPCREG(0x218)
+#define S3C_IPC_PP_LINE_EQ1 S3C_IPCREG(0x21C)
+#define S3C_IPC_PP_LINE_EQ2 S3C_IPCREG(0x220)
+#define S3C_IPC_PP_LINE_EQ3 S3C_IPCREG(0x224)
+#define S3C_IPC_PP_LINE_EQ4 S3C_IPCREG(0x228)
+#define S3C_IPC_PP_LINE_EQ5 S3C_IPCREG(0x22C)
+#define S3C_IPC_PP_LINE_EQ6 S3C_IPCREG(0x230)
+#define S3C_IPC_PP_LINE_EQ7 S3C_IPCREG(0x234)
+#define S3C_IPC_PP_BRIGHT_OFFSET S3C_IPCREG(0x238)
+#define S3C_IPC_VERSION_INFO S3C_IPCREG(0x3FC)
+
+/* Bit Definitions
+ ************************************************************************/
+/* ENABLE/DISABLE CONTROL */
+#define S3C_IPC_ON (1 << 0)
+#define S3C_IPC_OFF (0 << 0)
+
+/* SOFTWARE RESET */
+#define S3C_IPC_SRESET_ENABLE (1 << 0)
+#define S3C_IPC_SRESET_MASK (1 << 0)
+
+/* SHADOW UPDATE ENABLE CONTROL */
+#define S3C_IPC_SHADOW_UPDATE_ENABLE (1 << 0)
+#define S3C_IPC_SHADOW_UPDATE_DISABLE (0 << 0)
+
+/* OPERATION MODE CONTROL */
+#define S3C_IPC_2D_ENABLE (1 << 0)
+#define S3C_IPC_2D_DISABLE (0 << 0)
+#define S3C_IPC_2D_MASK (1 << 1)
+
+/* VERTICAL SCALER PIXEL RATE CONTROL */
+#define S3C_IPC_PEL_RATE_SET (0 << 0)
+
+/* HORIZONTAL ZOOM RATIO */
+#define S3C_IPC_H_RATIO_MASK (0x7fff << 0)
+#define S3C_IPC_V_RATIO_MASK (0x7fff << 0)
+
+/* POST PROCESSING IMAGE BYPASS MODE CONTROL */
+#define S3C_IPC_PP_BYPASS_ENABLE (0 << 0)
+#define S3C_IPC_PP_BYPASS_DISABLE (1 << 0)
+#define S3C_IPC_PP_BYPASS_MASK (1 << 0)
+
+/* BRIGHTNESS AND CONTRAST CONTROL */
+#define S3C_IPC_PP_LINE_CONTRAST_MASK (0xff << 0)
+#define S3C_IPC_PP_LINE_BRIGTHNESS_MASK (0xffff << 8)
+
+/*************************************************************************/
+/* Macro part */
+/*************************************************************************/
+#define S3C_IPC_FIELD_ID_SELECTION(x) ((x) << 6)
+#define S3C_IPC_FIELD_ID_AUTO_TOGGLING(x) ((x) << 2)
+#define S3C_IPC_2D_CTRL(x) ((x) << 1)
+#define S3C_IPC_SRC_WIDTH_SET(x) ((x) & 0x7ff << 0)
+#define S3C_IPC_SRC_HEIGHT_SET(x) ((x) & 0x3ff << 0)
+#define S3C_IPC_DST_WIDTH_SET(x) ((x) & 0x7ff << 0)
+#define S3C_IPC_DST_HEIGHT_SET(x) ((x) & 0x3ff << 0)
+#define S3C_IPC_PP_SATURATION_SET(x) ((x) & 0xff << 0)
+#define S3C_IPC_PP_TH_HNOISE_SET(x) ((x) & 0xff << 8)
+#define S3C_IPC_PP_SHARPNESS_SET(x) ((x) & 0x3 << 8)
+#define S3C_IPC_PP_BRIGHT_OFFSET_SET(x) ((x) & 0x1ff << 8)
+#define S3C_IPC_PP_LINE_CONTRAST(x)\
+ (((x) & S3C_IPC_PP_LINE_CONTRAST_MASK) << 0)
+#define S3C_IPC_PP_LINE_BRIGHT(x)\
+ (((x) & S3C_IPC_PP_LINE_BRIGTHNESS_MASK) << 8)
+
+#endif /* _REGS_IPC_H */
+
diff --git a/arch/arm/plat-s5p/include/plat/regs-mfc.h b/arch/arm/plat-s5p/include/plat/regs-mfc.h
new file mode 100644
index 0000000..1cecb53
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/regs-mfc.h
@@ -0,0 +1,256 @@
+/* linux/arch/arm/plat-s5pc1xx/include/plat/regs-mfc.h
+ *
+ * Register definition file for Samsung MFC V5.0 Interface (FIMV) driver
+ *
+ * Jaeryul Oh, Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * history:
+ * 2009.09.14 : Delete MFC v4.0 codes & rewrite defintion (Key-Young, Park)
+ * 2009.10.08 - Apply 9/30 firmware(Key Young, Park)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef _REGS_FIMV_H
+#define _REGS_FIMV_H
+
+#if defined(CONFIG_CPU_S5PV210)
+#define MFC_REG(x) (x)
+#define MFC_START_ADDR MFC_REG(0x0000)
+#define MFC_END_ADDR MFC_REG(0xe008 + 4)
+#define MFC_REG_SIZE (MFC_END_ADDR - MFC_START_ADDR)
+#define MFC_REG_COUNT ((MFC_END_ADDR - MFC_START_ADDR) / 4)
+
+/*====================================================================================================*/
+/* MFC Core Control Register */
+/*====================================================================================================*/
+#define MFC_SW_RESET MFC_REG(0x0000) /* MFC Software Reset Register */
+#define MFC_RISC_HOST_INT MFC_REG(0x0008) /* RISC to HOST Interrupt Reigser */
+
+#define MFC_HOST2RISC_COMMAND MFC_REG(0x0030) /* HOST to RISC Command Register */
+#define MFC_HOST2RISC_ARG1 MFC_REG(0x0034) /* first argument register */
+#define MFC_HOST2RISC_ARG2 MFC_REG(0x0038) /* second argument register */
+#define MFC_HOST2RISC_ARG3 MFC_REG(0x003c) /* third argument register */
+#define MFC_HOST2RISC_ARG4 MFC_REG(0x0040) /* fourth argument register */
+
+#define MFC_RISC2HOST_COMMAND MFC_REG(0x0044) /* RISC to HOST Command Register */
+#define MFC_RISC2HOST_ARG1 MFC_REG(0x0048) /* first argument register */
+#define MFC_RISC2HOST_ARG2 MFC_REG(0x004c) /* second argument register */
+#define MFC_RISC2HOST_ARG3 MFC_REG(0x0050) /* third argument register */
+#define MFC_RISC2HOST_ARG4 MFC_REG(0x0054) /* fourth argument register */
+
+#define MFC_FW_VERSION MFC_REG(0x0058) /* firmware version register */
+#define MFC_FW_STATUS MFC_REG(0x0080) /* 0: Not ready, 1: Ready */
+
+
+/*====================================================================================================*/
+/* Memory Controller Register */
+/*====================================================================================================*/
+#define MFC_MC_DRAMBASE_ADDR_A MFC_REG(0x0508) /* Port A DRAM base address */
+#define MFC_MC_DRAMBASE_ADDR_B MFC_REG(0x050c) /* Port B DRAM base address */
+#define MFC_MC_STATUS MFC_REG(0x0510) /* Bus arbiter's status */
+
+
+/*====================================================================================================*/
+/* Common Address Control */
+/*====================================================================================================*/
+/*----------------------------------------------------------------------------------------------------*/
+/* H264 Decoder Buffer Register */
+/*----------------------------------------------------------------------------------------------------*/
+#define MFC_H264DEC_VERT_NB_MV MFC_REG(0x068c) /* Base:35, vertical neighbor motion vector */
+#define MFC_H264DEC_NB_IP MFC_REG(0x0690) /* Base:36, neighbor pixels for intra pred */
+#define MFC_H264DEC_LUMA MFC_REG(0x0700) /* Base:64, Luma0 ~ Luma31 */
+#define MFC_H264DEC_CHROMA MFC_REG(0x0600) /* Base:0, Chroma0 ~ Chroma31 */
+#define MFC_H264DEC_MV MFC_REG(0x0780) /* Base:96, Mv0 ~ Mv31 */
+
+/*----------------------------------------------------------------------------------------------------*/
+/* Other Decoder Buffer Register */
+/*----------------------------------------------------------------------------------------------------*/
+#define MFC_NB_DCAC MFC_REG(0x068c) /* Base:35, neighbor AC/DC coeff. buffer */
+#define MFC_UPNB_MV MFC_REG(0x0690) /* Base:36, upper neighbor motion vector buffer */
+#define MFC_SUB_ANCHOR_MV MFC_REG(0x0694) /* Base:37, subseq. anchor motion vector buffer */
+#define MFC_OVERLAP_TRANSFORM MFC_REG(0x0698) /* Base:38, overlap transform line buffer */
+#define MFC_STX_PARSER MFC_REG(0x06A8) /* Base:42, syntax parser addr */
+#define MFC_DEC_LUMA MFC_REG(0x0700) /* Base:64, Luma0 ~ Luma5 */
+#define MFC_DEC_CHROMA MFC_REG(0x0600) /* Base:0, Chroma0 ~ Chroma5 */
+#define MFC_BITPLANE1 MFC_REG(0x06A4) /* Base:41, bitplane1 addr */
+#define MFC_BITPLANE2 MFC_REG(0x06A0) /* Base:40, bitplane2 addr */
+#define MFC_BITPLANE3 MFC_REG(0x069C) /* Base:39, bitplane3 addr */
+
+/*----------------------------------------------------------------------------------------------------*/
+/* Encoder Buffer Register */
+/*----------------------------------------------------------------------------------------------------*/
+#define MFC_UPPER_MV_ADDR MFC_REG(0x0600) /* Base:0, upper motion vector addr */
+#define MFC_DIRECT_COLZERO_FLAG_ADDR MFC_REG(0x0610) /* Base:4, direct cozero flag addr */
+#define MFC_UPPER_INTRA_MD_ADDR MFC_REG(0x0608) /* Base:2, upper intra MD addr */
+#define MFC_UPPER_INTRA_PRED_ADDR MFC_REG(0x0740) /* Base:80, upper intra PRED addr */
+#define MFC_NBOR_INFO_MPENC_ADDR MFC_REG(0x0604) /* Base:1, entropy engine's AC/DC coeff. */
+#define MFC_ACDC_COEF_BASE_ADDR MFC_REG(0x0604) /* Base:1, entropy engine's AC/DC coeff. */
+#define MFC_ENC_DPB_Y0_ADDR MFC_REG(0x061C) /* Base:7, ref0 Luma addr */
+#define MFC_ENC_DPB_C0_ADDR MFC_REG(0x0700) /* Base:64, ref0 Chroma addr */
+#define MFC_ENC_DPB_Y1_ADDR MFC_REG(0x0620) /* Base:8, ref1 Luma addr */
+#define MFC_ENC_DPB_C1_ADDR MFC_REG(0x0704) /* Base:65, ref1 Chroma addr */
+#define MFC_ENC_DPB_Y2_ADDR MFC_REG(0x0710) /* Base:68, ref2 Luma addr */
+#define MFC_ENC_DPB_C2_ADDR MFC_REG(0x0708) /* Base:66, ref2 Chroma addr */
+#define MFC_ENC_DPB_Y3_ADDR MFC_REG(0x0714) /* Base:69, ref3 Luma addr */
+#define MFC_ENC_DPB_C3_ADDR MFC_REG(0x070c) /* Base:67, ref3 Chroma addr */
+
+
+/*====================================================================================================*/
+/* Channel & Stream Interface Register */
+/*====================================================================================================*/
+#define MFC_HSIZE_PX MFC_REG(0x0818) /* frame width at encoder */
+#define MFC_VSIZE_PX MFC_REG(0x081c) /* frame height at encoder */
+#define MFC_PROFILE MFC_REG(0x0830) /* profile register */
+#define MFC_PICTURE_STRUCT MFC_REG(0x083c) /* picture field/frame flag */
+#define MFC_LF_CONTROL MFC_REG(0x0848) /* loop filter control */
+#define MFC_LF_ALPHA_OFF MFC_REG(0x084c) /* H.264 loop filter alpha offset */
+#define MFC_LF_BETA_OFF MFC_REG(0x0850) /* H.264 loop filter beta offset */
+#define MFC_QP_OFFSET MFC_REG(0x0c30) /* QP information offset from the DPB address */
+#define MFC_QP_OUT_EN MFC_REG(0x0c34) /* QP infomration enable at decoder */
+
+
+/*====================================================================================================*/
+/* Channel & Stream Interface Register */
+/*====================================================================================================*/
+#define MFC_SI_RTN_CHID MFC_REG(0x2000) /* Return CH instance ID register */
+#define MFC_SI_CH0_INST_ID MFC_REG(0x2040) /* CH0 instance ID and control register */
+#define MFC_SI_CH1_INST_ID MFC_REG(0x2080) /* CH1 instance ID and control register */
+
+/*----------------------------------------------------------------------------------------------------*/
+/* Decoder Channel and Stream Interface Register */
+/*----------------------------------------------------------------------------------------------------*/
+#define MFC_SI_VER_RESOL MFC_REG(0x2004) /* vertical resolution of decoder */
+#define MFC_SI_HOR_RESOL MFC_REG(0x2008) /* horizontal resolution of decoder */
+#define MFC_SI_MIN_NUM_DPB MFC_REG(0x200c) /* number of frames in the decoded pic */
+#define MFC_SI_DISPLAY_Y_ADR MFC_REG(0x2010) /* luma address of displayed pic */
+#define MFC_SI_DISPLAY_C_ADR MFC_REG(0x2014) /* chroma address of displayed pic */
+#define MFC_SI_DEC_FRM_SIZE MFC_REG(0x2018) /* consumed number of bytes to decode a frame */
+#define MFC_SI_DISPLAY_STATUS MFC_REG(0x201c) /* status of displayed picture */
+#define MFC_SI_FRAME_TYPE MFC_REG(0x2020) /* frame type such as skip/I/P/B */
+#define MFC_SI_DECODE_Y_ADR MFC_REG(0x2024) /* luma address of decoded pic */
+#define MFC_SI_DECODE_C_ADR MFC_REG(0x2028) /* chroma address of decoded pic */
+#define MFC_SI_DECODE_STATUS MFC_REG(0x202c) /* status of decoded picture */
+
+#define MFC_SI_CH0_ES_ADDR MFC_REG(0x2044) /* start addr of stream buf */
+#define MFC_SI_CH0_ES_DEC_UNIT_SIZE MFC_REG(0x2048) /* size of stream buf */
+#define MFC_SI_CH0_DESC_ADDR MFC_REG(0x204c) /* addr of descriptor buf */
+#define MFC_SI_CH0_FIMV1_VRESOL MFC_REG(0x2050) /* horizontal resolution */
+#define MFC_SI_CH0_FIMV1_HRESOL MFC_REG(0x2054) /* vertical resolution */
+#define MFC_SI_CH0_CPB_SIZE MFC_REG(0x2058) /* max size of coded pic. buf */
+#define MFC_SI_CH0_DESC_SIZE MFC_REG(0x205c) /* max size of descriptor buf */
+#define MFC_SI_CH0_RELEASE_BUFFER MFC_REG(0x2060) /* specifices the availability of each DPB */
+#define MFC_SI_CH0_HOST_WR_ADR MFC_REG(0x2064) /* start addr of shared memory */
+#define MFC_SI_CH0_DPB_CONFIG_CTRL MFC_REG(0x2068) /* DPB configuarion control */
+#define MFC_SI_CH0_CMD_SEQ_NUM MFC_REG(0x206c) /* Command sequence number from the host */
+
+#define MFC_SI_CH1_ES_ADDR MFC_REG(0x2084) /* start addr of stream buf */
+#define MFC_SI_CH1_ES_DEC_UNIT_SIZE MFC_REG(0x2088) /* size of stream buf */
+#define MFC_SI_CH1_DESC_ADDR MFC_REG(0x208c) /* addr of descriptor buf */
+#define MFC_SI_CH1_FIMV1_VRESOL MFC_REG(0x2090) /* horizontal resolution */
+#define MFC_SI_CH1_FIMV1_HRESOL MFC_REG(0x2094) /* vertical resolution */
+#define MFC_SI_CH1_CPB_SIZE MFC_REG(0x2098) /* max size of coded pic. buf */
+#define MFC_SI_CH1_DESC_SIZE MFC_REG(0x209c) /* max size of descriptor buf */
+#define MFC_SI_CH1_RELEASE_BUFFER MFC_REG(0x20a0) /* specifices the availability of each DPB */
+#define MFC_SI_CH1_HOST_WR_ADR MFC_REG(0x20a4) /* start addr of shared memory */
+#define MFC_SI_CH1_DPB_CONFIG_CTRL MFC_REG(0x20a8) /* DPB configuarion control */
+#define MFC_SI_CH1_CMD_SEQ_NUM MFC_REG(0x20ac) /* Command sequence number from the host */
+
+/*----------------------------------------------------------------------------------------------------*/
+/* Encoder Channel and Stream Interface Register */
+/*----------------------------------------------------------------------------------------------------*/
+#define MFC_CRC_LUMA0 MFC_REG(0x2030) /* luma crc data per frame(or top field) */
+#define MFC_CRC_CHROMA0 MFC_REG(0x2034) /* chroma crc data per frame(or top field) */
+#define MFC_CRC_LUMA1 MFC_REG(0x2038) /* luma crc data per bottom field */
+#define MFC_CRC_CHROMA1 MFC_REG(0x203c) /* chroma crc data per bottom field */
+
+#define MFC_SI_ENC_STREAM_SIZE MFC_REG(0x2004) /* stream size */
+#define MFC_SI_ENC_PICTURE_CNT MFC_REG(0x2008) /* picture count */
+#define MFC_SI_WRITE_POINTER MFC_REG(0x200c) /* stream buffer write pointer */
+#define MFC_SI_ENC_SLICE_TYPE MFC_REG(0x2010) /* slice type(I/P/B/IDR) */
+#define MFC_SI_ENCODED_Y_ADDR MFC_REG(0x2014) /* address of the encoded luminance picture */
+#define MFC_SI_ENCODED_C_ADDR MFC_REG(0x2018) /* address of the encoded chroma address */
+
+#define MFC_SI_CH0_SB_U_ADDR MFC_REG(0x2044) /* addr of upper stream buf */
+#define MFC_SI_CH0_SB_L_ADDR MFC_REG(0x2048) /* addr of lower stream buf */
+#define MFC_SI_CH0_BUFFER_SIZE MFC_REG(0x204c) /* size of stream buf */
+#define MFC_SI_CH0_CURRENT_Y_ADDR MFC_REG(0x2050) /* current Luma addr */
+#define MFC_SI_CH0_CURRENT_C_ADDR MFC_REG(0x2054) /* current Chroma addr */
+#define MFC_SI_CH0_ENC_PARA MFC_REG(0x2058) /* frame insertion control register */
+
+#define MFC_SI_CH1_SB_U_ADDR MFC_REG(0x2084) /* addr of upper stream buf */
+#define MFC_SI_CH1_SB_L_ADDR MFC_REG(0x2088) /* addr of lower stream buf */
+#define MFC_SI_CH1_BUFFER_SIZE MFC_REG(0x208c) /* size of stream buf */
+#define MFC_SI_CH1_CURRENT_Y_ADDR MFC_REG(0x2090) /* current Luma addr */
+#define MFC_SI_CH1_CURRENT_C_ADDR MFC_REG(0x2094) /* current Chroma addr */
+#define MFC_SI_CH1_ENC_PARA MFC_REG(0x2098) /* frame insertion control register */
+
+/*----------------------------------------------------------------------------------------------------*/
+/* Encoded Data Formatter Unit Register */
+/*----------------------------------------------------------------------------------------------------*/
+#define MFC_STR_BF_U_FULL MFC_REG(0xc004) /* upper stream buf full status */
+#define MFC_STR_BF_U_EMPTY MFC_REG(0xc008) /* upper stream buf empty status */
+#define MFC_STR_BF_L_FULL MFC_REG(0xc00c) /* lower stream buf full status */
+#define MFC_STR_BF_L_EMPTY MFC_REG(0xc010) /* lower stream buf empty status */
+#define MFC_STR_BF_STATUS MFC_REG(0xc018) /* stream buf interrupt status */
+#define MFC_EDFU_SF_EPB_ON_CTRL MFC_REG(0xc054) /* EDFU stream control */
+#define MFC_EDFU_SF_BUF_CTRL MFC_REG(0xc058) /* EDFU buffer control */
+#define MFC_STR_BF_MODE_CTRL MFC_REG(0xc05c) /* stream buffer mode control */
+
+
+/*====================================================================================================*/
+/* Encoding Registers */
+/*====================================================================================================*/
+/*----------------------------------------------------------------------------------------------------*/
+/* Common Encoder Register */
+/*----------------------------------------------------------------------------------------------------*/
+#define MFC_RC_CONTROL_CONFIG MFC_REG(0x00a0) /* Rate Control Configuration */
+#define MFC_ENC_PIC_TYPE_CTRL MFC_REG(0xc504) /* pic type level control */
+#define MFC_ENC_B_RECON_WRITE_ON MFC_REG(0xc508) /* B frame recon data write cotrl */
+#define MFC_ENC_MSLICE_CTRL MFC_REG(0xc50c) /* multi slice control */
+#define MFC_ENC_MSLICE_MB MFC_REG(0xc510) /* MB number in the one slice */
+#define MFC_ENC_MSLICE_BYTE MFC_REG(0xc514) /* byte count number for one slice */
+#define MFC_ENC_CIR_CTRL MFC_REG(0xc518) /* number of intra refresh MB */
+#define MFC_ENC_MAP_FOR_CUR MFC_REG(0xc51c) /* linear or 64x32 tiled mode */
+#define MFC_ENC_PADDING_CTRL MFC_REG(0xc520) /* padding control */
+#define MFC_ENC_INT_MASK MFC_REG(0xc528) /* interrupt mask */
+#define MFC_ENC_COMMON_INTRA_BIAS MFC_REG(0xc528) /* intra mode bias register */
+#define MFC_ENC_COMMON_BI_DIRECT_BIAS MFC_REG(0xc528) /* bi-directional mode bias register */
+
+/*----------------------------------------------------------------------------------------------------*/
+/* Rate Control Register */
+/*----------------------------------------------------------------------------------------------------*/
+#define MFC_RC_CONFIG MFC_REG(0xc5a0) /* RC config */
+#define MFC_RC_FRAME_RATE MFC_REG(0xc5a4) /* frame rate */
+#define MFC_RC_BIT_RATE MFC_REG(0xc5a8) /* bit rate */
+#define MFC_RC_QBOUND MFC_REG(0xc5ac) /* max/min QP */
+#define MFC_RC_RPARA MFC_REG(0xc5b0) /* rate control reaction coeff. */
+#define MFC_RC_MB_CTRL MFC_REG(0xc5b4) /* MB adaptive scaling */
+
+/*----------------------------------------------------------------------------------------------------*/
+/* H.264 Encoder Register */
+/*----------------------------------------------------------------------------------------------------*/
+#define MFC_H264_ENC_ENTRP_MODE MFC_REG(0xd004) /* CAVLC or CABAC */
+#define MFC_H264_ENC_NUM_OF_REF MFC_REG(0xd010) /* number of reference for P/B */
+#define MFC_H264_ENC_MDINTER_WEIGHT MFC_REG(0xd01c) /* inter weighted parameter */
+#define MFC_H264_ENC_MDINTRA_WEIGHT MFC_REG(0xd020) /* intra weighted parameter */
+#define MFC_H264_ENC_TRANS_8X8_FLAG MFC_REG(0xd034) /* 8x8 transform flag in PPS & high profile */
+
+/*----------------------------------------------------------------------------------------------------*/
+/* MPEG4 Encoder Register */
+/*----------------------------------------------------------------------------------------------------*/
+#define MFC_MPEG4_ENC_QUART_PXL MFC_REG(0xe008) /* quarter pel interpolation control */
+
+
+/*====================================================================================================*/
+/* Etc Registers */
+/*====================================================================================================*/
+#define MFC_NUM_MASTER MFC_REG(0x0b14) /* Number of master port */
+
+//#define MFC_SI_DEC_FRM_SIZE MFC_REG(0x2018)
+#endif /* CONFIG_CPU_S5PC1xx */
+
+#endif
diff --git a/arch/arm/plat-s5p/include/plat/regs-systimer.h b/arch/arm/plat-s5p/include/plat/regs-systimer.h
new file mode 100644
index 0000000..7091c40
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/regs-systimer.h
@@ -0,0 +1,77 @@
+/* linux/arch/arm/plat-s5p/include/plat/regs-systimer.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * S5P System Timer Driver Header information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_PLAT_REGS_SYSTIMER_H
+#define __ASM_PLAT_REGS_SYSTIMER_H __FILE__
+
+#define S5P_SYSTIMERREG(x) (S5P_VA_SYSTIMER + (x))
+
+#define S5P_SYSTIMER_TCFG S5P_SYSTIMERREG(0x00)
+#define S5P_SYSTIMER_TCON S5P_SYSTIMERREG(0x04)
+#define S5P_SYSTIMER_TICNTB S5P_SYSTIMERREG(0x08)
+#define S5P_SYSTIMER_TICNTO S5P_SYSTIMERREG(0x0c)
+#define S5P_SYSTIMER_TFCNTB S5P_SYSTIMERREG(0x10)
+#define S5P_SYSTIMER_ICNTB S5P_SYSTIMERREG(0x18)
+#define S5P_SYSTIMER_ICNTO S5P_SYSTIMERREG(0x1c)
+#define S5P_SYSTIMER_INT_CSTAT S5P_SYSTIMERREG(0x20)
+
+/* Value for TCFG */
+
+#define S5P_SYSTIMER_SWRST (1<<16)
+
+#define S5P_SYSTIMER_DIV_GEN (0<<15)
+#define S5P_SYSTIMER_DIV_RTC (1<<15)
+
+#define S5P_SYSTIMER_TICK_INT (0<<14)
+#define S5P_SYSTIMER_TICK_FRA (1<<14)
+
+#define S5P_SYSTIMER_TCLK_MASK (3<<12)
+#define S5P_SYSTIMER_TCLK_XXTI (0<<12)
+#define S5P_SYSTIMER_TCLK_RTC (1<<12)
+#define S5P_SYSTIMER_TCLK_USB (2<<12)
+#define S5P_SYSTIMER_TCLK_PCLK (3<<12)
+
+#define S5P_SYSTIMER_DIV_MASK (7<<8)
+#define S5P_SYSTIMER_DIV_1 (0<<8)
+#define S5P_SYSTIMER_DIV_2 (1<<8)
+#define S5P_SYSTIMER_DIV_4 (2<<8)
+#define S5P_SYSTIMER_DIV_8 (3<<8)
+#define S5P_SYSTIMER_DIV_16 (4<<8)
+
+#define S5P_SYSTIMER_TARGET_HZ 200
+#define S5P_SYSTIMER_PRESCALER 5
+#define S5P_SYSTIMER_PRESCALER_MASK (0x3f<<0)
+
+/* value for TCON */
+
+#define S5P_SYSTIMER_INT_AUTO (1<<5)
+#define S5P_SYSTIMER_INT_IMM (1<<4)
+#define S5P_SYSTIMER_INT_START (1<<3)
+#define S5P_SYSTIMER_AUTO_RELOAD (1<<2)
+#define S5P_SYSTIMER_IMM_UPDATE (1<<1)
+#define S5P_SYSTIMER_START (1<<0)
+
+/* Value for INT_CSTAT */
+
+#define S5P_SYSTIMER_INT_TWIE (1<<10)
+#define S5P_SYSTIMER_INT_IWIE (1<<9)
+#define S5P_SYSTIMER_INT_TFWIE (1<<8)
+#define S5P_SYSTIMER_INT_TIWIE (1<<7)
+#define S5P_SYSTIMER_INT_ICNTEIE (1<<6)
+#define S5P_SYSTIMER_INT_TCON (1<<5)
+#define S5P_SYSTIMER_INT_ICNTB (1<<4)
+#define S5P_SYSTIMER_INT_TFCNTB (1<<3)
+#define S5P_SYSTIMER_INT_TICNTB (1<<2)
+#define S5P_SYSTIMER_INT_INTCNT (1<<1)
+#define S5P_SYSTIMER_INT_INTENABLE (1<<0)
+
+#endif /* __ASM_PLAT_REGS_SYSTIMER_H */
diff --git a/arch/arm/plat-s5p/include/plat/s5p-otghost.h b/arch/arm/plat-s5p/include/plat/s5p-otghost.h
new file mode 100644
index 0000000..a466c93
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/s5p-otghost.h
@@ -0,0 +1,56 @@
+/* linux/arch/arm/plat-s5p/include/plat/s5p-otghost.h
+ *
+ * Copyright 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Platform header file for Samsung OTG Host driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+#ifndef _PLAT_S5P_OTGHOST_H
+#define _PLAT_S5P_OTGHOST_H __FILE__
+
+#include <linux/wakelock.h>
+
+/*#define CONFIG_USB_S3C_OTG_HOST_HANDLING_CLOCK*/
+#define CONFIG_USB_S3C_OTG_HOST_DTGDRVVBUS
+
+union port_flags_t {
+ /** raw register data */
+ u32 d32;
+ /** register bits */
+ struct {
+ unsigned port_connect_status_change:1;
+ unsigned port_connect_status:1;
+ unsigned port_reset_change:1;
+ unsigned port_enable_change:1;
+ unsigned port_suspend_change:1;
+ unsigned port_over_current_change:1;
+ unsigned reserved:26;
+ } b;
+};
+
+struct sec_otghost_data {
+ bool clk_usage;
+ void (*set_pwr_cb)(int on);
+ int host_notify;
+ int sec_whlist_table_num;
+};
+
+struct sec_otghost {
+ spinlock_t lock;
+
+ bool ch_halt;
+ bool is_hs;
+ union port_flags_t port_flag;
+ struct wake_lock wake_lock;
+
+ struct work_struct work;
+ struct workqueue_struct *wq;
+
+ struct sec_otghost_data *otg_data;
+};
+
+#endif /*_PLAT_S5P_OTGHOST_H */
diff --git a/arch/arm/plat-s5p/include/plat/system-reset.h b/arch/arm/plat-s5p/include/plat/system-reset.h
index f307f34..9e0a095 100644
--- a/arch/arm/plat-s5p/include/plat/system-reset.h
+++ b/arch/arm/plat-s5p/include/plat/system-reset.h
@@ -12,20 +12,6 @@
* published by the Free Software Foundation.
*/
-#include <plat/watchdog-reset.h>
+extern void (*s5p_reset_hook)(void);
-void (*s5p_reset_hook)(void);
-
-static void arch_reset(char mode, const char *cmd)
-{
- /* SWRESET support in s5p_reset_hook() */
-
- if (s5p_reset_hook)
- s5p_reset_hook();
-
- /* Perform reset using Watchdog reset
- * if there is no s5p_reset_hook()
- */
-
- arch_wdt_reset();
-}
+void arch_reset(char mode, const char *cmd);
diff --git a/arch/arm/plat-s5p/irq-eint-group.c b/arch/arm/plat-s5p/irq-eint-group.c
new file mode 100644
index 0000000..0fe4d5a
--- /dev/null
+++ b/arch/arm/plat-s5p/irq-eint-group.c
@@ -0,0 +1,605 @@
+/* linux/arch/arm/mach-s5pv210/irq-eint-group.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * S5P - IRQ EINT Group support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <plat/regs-irqtype.h>
+
+#include <mach/map.h>
+#include <plat/cpu.h>
+
+#include <mach/gpio.h>
+#include <plat/gpio-cfg.h>
+#include <plat/irq-eint-group.h>
+#include <mach/regs-gpio.h>
+
+#define S5PV210_EINT_MAX_SOURCES 8
+
+static DEFINE_SPINLOCK(eint_group_lock);
+
+struct s5pv210_eint_group_t {
+ int sources;
+ int base;
+ void __iomem *cont_reg;
+ void __iomem *mask_reg;
+ void __iomem *pend_reg;
+ int mask_ofs;
+ int pend_ofs;
+ unsigned int int_con;
+ unsigned int int_mask;
+
+ /* start offset in control register for each source */
+ int cont_map[S5PV210_EINT_MAX_SOURCES];
+};
+
+static struct s5pv210_eint_group_t eint_groups[] = {
+ [0] = {
+ .sources = 0,
+ .base = 0,
+ .cont_reg = 0x0,
+ .mask_reg = 0x0,
+ .pend_reg = 0x0,
+ .mask_ofs = 0,
+ .pend_ofs = 0,
+ .int_con = 0x0,
+ .int_mask = 0xff,
+ .cont_map = {
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ },
+ },
+ [1] = {
+ .sources = IRQ_EINT_GROUP1_NR,
+ .base = IRQ_EINT_GROUP1_BASE,
+ .cont_reg = S5PV210_GPA0_INT_CON,
+ .mask_reg = S5PV210_GPA0_INT_MASK,
+ .pend_reg = S5PV210_GPA0_INT_PEND,
+ .mask_ofs = 0,
+ .pend_ofs = 0,
+ .int_con = 0x0,
+ .int_mask = 0xff,
+ .cont_map = {
+ 0, 4, 8, 12, 16, 20, 24, 28,
+ },
+ },
+ [2] = {
+ .sources = IRQ_EINT_GROUP2_NR,
+ .base = IRQ_EINT_GROUP2_BASE,
+ .cont_reg = S5PV210_GPA1_INT_CON,
+ .mask_reg = S5PV210_GPA1_INT_MASK,
+ .pend_reg = S5PV210_GPA1_INT_PEND,
+ .mask_ofs = 0,
+ .pend_ofs = 0,
+ .int_con = 0x0,
+ .int_mask = 0xff,
+ .cont_map = {
+ 0, 4, 8, 12, -1, -1, -1, -1,
+ },
+ },
+ [3] = {
+ .sources = IRQ_EINT_GROUP3_NR,
+ .base = IRQ_EINT_GROUP3_BASE,
+ .cont_reg = S5PV210_GPB_INT_CON,
+ .mask_reg = S5PV210_GPB_INT_MASK,
+ .pend_reg = S5PV210_GPB_INT_PEND,
+ .mask_ofs = 0,
+ .pend_ofs = 0,
+ .int_con = 0x0,
+ .int_mask = 0xff,
+ .cont_map = {
+ 0, 4, 8, 12, 16, 20, 24, 28,
+ },
+ },
+ [4] = {
+ .sources = IRQ_EINT_GROUP4_NR,
+ .base = IRQ_EINT_GROUP4_BASE,
+ .cont_reg = S5PV210_GPC0_INT_CON,
+ .mask_reg = S5PV210_GPC0_INT_MASK,
+ .pend_reg = S5PV210_GPC0_INT_PEND,
+ .mask_ofs = 0,
+ .pend_ofs = 0,
+ .int_con = 0x0,
+ .int_mask = 0xff,
+ .cont_map = {
+ 0, 4, 8, 12, 16, -1, -1, -1,
+ },
+ },
+ [5] = {
+ .sources = IRQ_EINT_GROUP5_NR,
+ .base = IRQ_EINT_GROUP5_BASE,
+ .cont_reg = S5PV210_GPC1_INT_CON,
+ .mask_reg = S5PV210_GPC1_INT_MASK,
+ .pend_reg = S5PV210_GPC1_INT_PEND,
+ .mask_ofs = 0,
+ .pend_ofs = 0,
+ .int_con = 0x0,
+ .int_mask = 0xff,
+ .cont_map = {
+ 0, 4, 8, 12, 16, -1, -1, -1,
+ },
+ },
+ [6] = {
+ .sources = IRQ_EINT_GROUP6_NR,
+ .base = IRQ_EINT_GROUP6_BASE,
+ .cont_reg = S5PV210_GPD0_INT_CON,
+ .mask_reg = S5PV210_GPD0_INT_MASK,
+ .pend_reg = S5PV210_GPD0_INT_PEND,
+ .mask_ofs = 0,
+ .pend_ofs = 0,
+ .int_con = 0x0,
+ .int_mask = 0xff,
+ .cont_map = {
+ 0, 4, 8, 12, -1, -1, -1, -1,
+ },
+ },
+ [7] = {
+ .sources = IRQ_EINT_GROUP7_NR,
+ .base = IRQ_EINT_GROUP7_BASE,
+ .cont_reg = S5PV210_GPD1_INT_CON,
+ .mask_reg = S5PV210_GPD1_INT_MASK,
+ .pend_reg = S5PV210_GPD1_INT_PEND,
+ .mask_ofs = 0,
+ .pend_ofs = 0,
+ .int_con = 0x0,
+ .int_mask = 0xff,
+ .cont_map = {
+ 0, 4, 8, 12, 16, 20, -1, -1,
+ },
+ },
+ [8] = {
+ .sources = IRQ_EINT_GROUP8_NR,
+ .base = IRQ_EINT_GROUP8_BASE,
+ .cont_reg = S5PV210_GPE0_INT_CON,
+ .mask_reg = S5PV210_GPE0_INT_MASK,
+ .pend_reg = S5PV210_GPE0_INT_PEND,
+ .mask_ofs = 0,
+ .pend_ofs = 0,
+ .int_con = 0x0,
+ .int_mask = 0xff,
+ .cont_map = {
+ 0, 4, 8, 12, 16, 20, 24, 28,
+ },
+ },
+ [9] = {
+ .sources = IRQ_EINT_GROUP9_NR,
+ .base = IRQ_EINT_GROUP9_BASE,
+ .cont_reg = S5PV210_GPE1_INT_CON,
+ .mask_reg = S5PV210_GPE1_INT_MASK,
+ .pend_reg = S5PV210_GPE1_INT_PEND,
+ .mask_ofs = 0,
+ .pend_ofs = 0,
+ .int_con = 0x0,
+ .int_mask = 0xff,
+ .cont_map = {
+ 0, 4, 8, 12, 16, -1, -1, -1,
+ },
+ },
+ [10] = {
+ .sources = IRQ_EINT_GROUP10_NR,
+ .base = IRQ_EINT_GROUP10_BASE,
+ .cont_reg = S5PV210_GPF0_INT_CON,
+ .mask_reg = S5PV210_GPF0_INT_MASK,
+ .pend_reg = S5PV210_GPF0_INT_PEND,
+ .mask_ofs = 0,
+ .pend_ofs = 0,
+ .int_con = 0x0,
+ .int_mask = 0xff,
+ .cont_map = {
+ 0, 4, 8, 12, 16, 20, 24, 28,
+ },
+ },
+ [11] = {
+ .sources = IRQ_EINT_GROUP11_NR,
+ .base = IRQ_EINT_GROUP11_BASE,
+ .cont_reg = S5PV210_GPF1_INT_CON,
+ .mask_reg = S5PV210_GPF1_INT_MASK,
+ .pend_reg = S5PV210_GPF1_INT_PEND,
+ .mask_ofs = 0,
+ .pend_ofs = 0,
+ .int_con = 0x0,
+ .int_mask = 0xff,
+ .cont_map = {
+ 0, 4, 8, 12, 16, 20, 24, 28,
+ },
+ },
+ [12] = {
+ .sources = IRQ_EINT_GROUP12_NR,
+ .base = IRQ_EINT_GROUP12_BASE,
+ .cont_reg = S5PV210_GPF2_INT_CON,
+ .mask_reg = S5PV210_GPF2_INT_MASK,
+ .pend_reg = S5PV210_GPF2_INT_PEND,
+ .mask_ofs = 0,
+ .pend_ofs = 0,
+ .int_con = 0x0,
+ .int_mask = 0xff,
+ .cont_map = {
+ 0, 4, 8, 12, 16, 20, 24, 28,
+ },
+ },
+ [13] = {
+ .sources = IRQ_EINT_GROUP13_NR,
+ .base = IRQ_EINT_GROUP13_BASE,
+ .cont_reg = S5PV210_GPF3_INT_CON,
+ .mask_reg = S5PV210_GPF3_INT_MASK,
+ .pend_reg = S5PV210_GPF3_INT_PEND,
+ .mask_ofs = 0,
+ .pend_ofs = 0,
+ .int_con = 0x0,
+ .int_mask = 0xff,
+ .cont_map = {
+ 0, 4, 8, 12, 16, 20, -1, -1,
+ },
+ },
+ [14] = {
+ .sources = IRQ_EINT_GROUP14_NR,
+ .base = IRQ_EINT_GROUP14_BASE,
+ .cont_reg = S5PV210_GPG0_INT_CON,
+ .mask_reg = S5PV210_GPG0_INT_MASK,
+ .pend_reg = S5PV210_GPG0_INT_PEND,
+ .mask_ofs = 0,
+ .pend_ofs = 0,
+ .int_con = 0x0,
+ .int_mask = 0xff,
+ .cont_map = {
+ 0, 4, 8, 12, 16, 20, 24, -1,
+ },
+ },
+ [15] = {
+ .sources = IRQ_EINT_GROUP15_NR,
+ .base = IRQ_EINT_GROUP15_BASE,
+ .cont_reg = S5PV210_GPG1_INT_CON,
+ .mask_reg = S5PV210_GPG1_INT_MASK,
+ .pend_reg = S5PV210_GPG1_INT_PEND,
+ .mask_ofs = 0,
+ .pend_ofs = 0,
+ .int_con = 0x0,
+ .int_mask = 0xff,
+ .cont_map = {
+ 0, 4, 8, 12, 16, 20, 24, -1,
+ },
+ },
+ [16] = {
+ .sources = IRQ_EINT_GROUP16_NR,
+ .base = IRQ_EINT_GROUP16_BASE,
+ .cont_reg = S5PV210_GPG2_INT_CON,
+ .mask_reg = S5PV210_GPG2_INT_MASK,
+ .pend_reg = S5PV210_GPG2_INT_PEND,
+ .mask_ofs = 0,
+ .pend_ofs = 0,
+ .int_con = 0x0,
+ .int_mask = 0xff,
+ .cont_map = {
+ 0, 4, 8, 12, 16, 20, 24, -1,
+ },
+ },
+ [17] = {
+ .sources = IRQ_EINT_GROUP17_NR,
+ .base = IRQ_EINT_GROUP17_BASE,
+ .cont_reg = S5PV210_GPG3_INT_CON,
+ .mask_reg = S5PV210_GPG3_INT_MASK,
+ .pend_reg = S5PV210_GPG3_INT_PEND,
+ .mask_ofs = 0,
+ .pend_ofs = 0,
+ .int_con = 0x0,
+ .int_mask = 0xff,
+ .cont_map = {
+ 0, 4, 8, 12, 16, 20, 24, -1,
+ },
+ },
+ [18] = {
+ .sources = IRQ_EINT_GROUP18_NR,
+ .base = IRQ_EINT_GROUP18_BASE,
+ .cont_reg = S5PV210_GPJ0_INT_CON,
+ .mask_reg = S5PV210_GPJ0_INT_MASK,
+ .pend_reg = S5PV210_GPJ0_INT_PEND,
+ .mask_ofs = 0,
+ .pend_ofs = 0,
+ .int_con = 0x0,
+ .int_mask = 0xff,
+ .cont_map = {
+ 0, 4, 8, 12, 16, 20, 24, 28,
+ },
+ },
+ [19] = {
+ .sources = IRQ_EINT_GROUP19_NR,
+ .base = IRQ_EINT_GROUP19_BASE,
+ .cont_reg = S5PV210_GPJ1_INT_CON,
+ .mask_reg = S5PV210_GPJ1_INT_MASK,
+ .pend_reg = S5PV210_GPJ1_INT_PEND,
+ .mask_ofs = 0,
+ .pend_ofs = 0,
+ .int_con = 0x0,
+ .int_mask = 0xff,
+ .cont_map = {
+ 0, 4, 8, 12, 16, 20, -1, -1,
+ },
+ },
+ [20] = {
+ .sources = IRQ_EINT_GROUP20_NR,
+ .base = IRQ_EINT_GROUP20_BASE,
+ .cont_reg = S5PV210_GPJ2_INT_CON,
+ .mask_reg = S5PV210_GPJ2_INT_MASK,
+ .pend_reg = S5PV210_GPJ2_INT_PEND,
+ .mask_ofs = 0,
+ .pend_ofs = 0,
+ .int_con = 0x0,
+ .int_mask = 0xff,
+ .cont_map = {
+ 0, 4, 8, 12, 16, 20, 24, 28,
+ },
+ },
+ [21] = {
+ .sources = IRQ_EINT_GROUP21_NR,
+ .base = IRQ_EINT_GROUP21_BASE,
+ .cont_reg = S5PV210_GPJ3_INT_CON,
+ .mask_reg = S5PV210_GPJ3_INT_MASK,
+ .pend_reg = S5PV210_GPJ3_INT_PEND,
+ .mask_ofs = 0,
+ .pend_ofs = 0,
+ .int_con = 0x0,
+ .int_mask = 0xff,
+ .cont_map = {
+ 0, 4, 8, 12, 16, 20, 24, 28,
+ },
+ },
+ [22] = {
+ .sources = IRQ_EINT_GROUP22_NR,
+ .base = IRQ_EINT_GROUP22_BASE,
+ .cont_reg = S5PV210_GPJ4_INT_CON,
+ .mask_reg = S5PV210_GPJ4_INT_MASK,
+ .pend_reg = S5PV210_GPJ4_INT_PEND,
+ .mask_ofs = 0,
+ .pend_ofs = 0,
+ .int_con = 0x0,
+ .int_mask = 0xff,
+ .cont_map = {
+ 0, 4, 8, 12, 16, -1, -1, -1,
+ },
+ },
+};
+
+#define S5PV210_EINT_GROUPS (sizeof(eint_groups) / sizeof(eint_groups[0]))
+
+static int to_group_number(unsigned int irq)
+{
+ int grp, found;
+
+ for (grp = 1; grp < S5PV210_EINT_GROUPS; grp++) {
+ if (irq >= eint_groups[grp].base + eint_groups[grp].sources)
+ continue;
+ else {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ printk(KERN_ERR "failed to find out the eint group number\n");
+ grp = 0;
+ }
+
+ return grp;
+}
+
+static inline int to_irq_number(int grp, unsigned int irq)
+{
+ return irq - eint_groups[grp].base;
+}
+
+static inline int to_bit_offset(int grp, unsigned int irq)
+{
+ int offset;
+
+ offset = eint_groups[grp].cont_map[to_irq_number(grp, irq)];
+
+ if (offset == -1) {
+ printk(KERN_ERR "invalid bit offset\n");
+ offset = 0;
+ }
+
+ return offset;
+}
+
+static inline void s5pv210_irq_eint_group_mask(struct irq_data *d)
+{
+ struct s5pv210_eint_group_t *group;
+ unsigned long flags;
+ int grp;
+
+ grp = to_group_number(d->irq);
+ group = &eint_groups[grp];
+ spin_lock_irqsave(&eint_group_lock, flags);
+ eint_groups[grp].int_mask |=
+ (1 << (group->mask_ofs + to_irq_number(grp, d->irq)));
+
+ writel(eint_groups[grp].int_mask, group->mask_reg);
+ spin_unlock_irqrestore(&eint_group_lock, flags);
+}
+
+static inline void s5pv210_irq_eint_group_ack(struct irq_data *d)
+{
+ struct s5pv210_eint_group_t *group;
+ unsigned long flags;
+ int grp;
+ u32 pend;
+
+ grp = to_group_number(d->irq);
+ group = &eint_groups[grp];
+
+ spin_lock_irqsave(&eint_group_lock, flags);
+ pend = (1 << (group->pend_ofs + to_irq_number(grp, d->irq)));
+
+ writel(pend, group->pend_reg);
+ spin_unlock_irqrestore(&eint_group_lock, flags);
+}
+
+static void s5pv210_irq_eint_group_unmask(struct irq_data *d)
+{
+ struct s5pv210_eint_group_t *group;
+ unsigned long flags;
+ int grp;
+
+ grp = to_group_number(d->irq);
+ group = &eint_groups[grp];
+
+ /* for level triggered interrupts, masking doesn't prevent
+ * the interrupt from becoming pending again. by the time
+ * the handler (either irq or thread) can do its thing to clear
+ * the interrupt, it's too late because it could be pending
+ * already. we have to ack it here, after the handler runs,
+ * or else we get a false interrupt.
+ */
+ if (irqd_is_level_type(d))
+ s5pv210_irq_eint_group_ack(d);
+
+ spin_lock_irqsave(&eint_group_lock, flags);
+ eint_groups[grp].int_mask &=
+ ~(1 << (group->mask_ofs + to_irq_number(grp, d->irq)));
+
+ writel(eint_groups[grp].int_mask, group->mask_reg);
+ spin_unlock_irqrestore(&eint_group_lock, flags);
+}
+
+static void s5pv210_irq_eint_group_maskack(struct irq_data *d)
+{
+ /* compiler should in-line these */
+ s5pv210_irq_eint_group_mask(d);
+ s5pv210_irq_eint_group_ack(d);
+}
+
+static int s5pv210_irq_eint_group_set_type(struct irq_data *d,
+ unsigned int type)
+{
+ struct s5pv210_eint_group_t *group;
+ unsigned long flags;
+ int grp, shift;
+ u32 mask, newvalue = 0;
+
+ grp = to_group_number(d->irq);
+ group = &eint_groups[grp];
+
+ switch (type) {
+ case IRQ_TYPE_NONE:
+ printk(KERN_WARNING "No edge setting!\n");
+ break;
+
+ case IRQ_TYPE_EDGE_RISING:
+ newvalue = S5P_IRQ_TYPE_EDGE_RISING;
+ break;
+
+ case IRQ_TYPE_EDGE_FALLING:
+ newvalue = S5P_IRQ_TYPE_EDGE_FALLING;
+ break;
+
+ case IRQ_TYPE_EDGE_BOTH:
+ newvalue = S5P_IRQ_TYPE_EDGE_BOTH;
+ break;
+
+ case IRQ_TYPE_LEVEL_LOW:
+ newvalue = S5P_IRQ_TYPE_LEVEL_LOW;
+ break;
+
+ case IRQ_TYPE_LEVEL_HIGH:
+ newvalue = S5P_IRQ_TYPE_LEVEL_HIGH;
+ break;
+
+ default:
+ printk(KERN_ERR "No such irq type %d", type);
+ return -1;
+ }
+
+ shift = to_bit_offset(grp, d->irq);
+ mask = 0x7 << shift;
+
+ spin_lock_irqsave(&eint_group_lock, flags);
+ eint_groups[grp].int_con &= ~mask;
+ eint_groups[grp].int_con |= newvalue << shift;
+ writel(eint_groups[grp].int_con, group->cont_reg);
+ spin_unlock_irqrestore(&eint_group_lock, flags);
+
+ return 0;
+}
+
+static struct irq_chip s5pv210_irq_eint_group = {
+ .name = "s5pv210-eint-group",
+ .irq_mask = s5pv210_irq_eint_group_mask,
+ .irq_unmask = s5pv210_irq_eint_group_unmask,
+ .irq_mask_ack = s5pv210_irq_eint_group_maskack,
+ .irq_ack = s5pv210_irq_eint_group_ack,
+ .irq_set_type = s5pv210_irq_eint_group_set_type,
+};
+
+/*
+ * s5p_irq_demux_eint_group
+*/
+static inline void s5pv210_irq_demux_eint_group(unsigned int irq,
+ struct irq_desc *desc)
+{
+ struct s5pv210_eint_group_t *group;
+ u32 status, newirq;
+ int grp, src;
+
+ for (grp = 1; grp < S5PV210_EINT_GROUPS; grp++) {
+ group = &eint_groups[grp];
+ status = __raw_readl(group->pend_reg);
+
+ status &= ~eint_groups[grp].int_mask;
+ status >>= group->pend_ofs;
+ status &= 0xff; /* MAX IRQ in a group is 8 */
+
+ if (!status)
+ continue;
+
+ for (src = 0; src < S5PV210_EINT_MAX_SOURCES; src++) {
+ if (status & 1) {
+ newirq = group->base + src;
+ generic_handle_irq(newirq);
+ }
+
+ status >>= 1;
+ }
+ }
+}
+
+void s5pv210_restore_eint_group(void)
+{
+ struct s5pv210_eint_group_t *group;
+ unsigned long flags;
+ int grp;
+
+ spin_lock_irqsave(&eint_group_lock, flags);
+ for (grp = 1; grp < S5PV210_EINT_GROUPS; grp++) {
+ group = &eint_groups[grp];
+ writel(eint_groups[grp].int_con, group->cont_reg);
+ writel(eint_groups[grp].int_mask, group->mask_reg);
+ }
+ spin_unlock_irqrestore(&eint_group_lock, flags);
+}
+
+int __init s5pv210_init_irq_eint_group(void)
+{
+ int irq;
+
+ for (irq = IRQ_EINT_GROUP_BASE; irq < NR_IRQS; irq++) {
+ irq_set_chip(irq, &s5pv210_irq_eint_group);
+ irq_set_handler(irq, handle_level_irq);
+ set_irq_flags(irq, IRQF_VALID);
+ }
+
+ irq_set_chained_handler(IRQ_GPIOINT, s5pv210_irq_demux_eint_group);
+
+ return 0;
+}
+
+arch_initcall(s5pv210_init_irq_eint_group);
diff --git a/arch/arm/plat-s5p/irq-eint.c b/arch/arm/plat-s5p/irq-eint.c
index b5bb774..8380951 100644
--- a/arch/arm/plat-s5p/irq-eint.c
+++ b/arch/arm/plat-s5p/irq-eint.c
@@ -37,21 +37,31 @@ static inline void s5p_irq_eint_mask(struct irq_data *data)
__raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq)));
}
+static inline void s5p_irq_eint_ack(struct irq_data *data)
+{
+ __raw_writel(eint_irq_to_bit(data->irq),
+ S5P_EINT_PEND(EINT_REG_NR(data->irq)));
+}
+
static void s5p_irq_eint_unmask(struct irq_data *data)
{
u32 mask;
+ /* for level triggered interrupts, masking doesn't prevent
+ * the interrupt from becoming pending again. by the time
+ * the handler (either irq or thread) can do its thing to clear
+ * the interrupt, it's too late because it could be pending
+ * already. we have to ack it here, after the handler runs,
+ * or else we get a false interrupt.
+ */
+ if (irqd_is_level_type(data))
+ s5p_irq_eint_ack(data);
+
mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq)));
mask &= ~(eint_irq_to_bit(data->irq));
__raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq)));
}
-static inline void s5p_irq_eint_ack(struct irq_data *data)
-{
- __raw_writel(eint_irq_to_bit(data->irq),
- S5P_EINT_PEND(EINT_REG_NR(data->irq)));
-}
-
static void s5p_irq_eint_maskack(struct irq_data *data)
{
/* compiler should in-line these */
@@ -65,6 +75,7 @@ static int s5p_irq_eint_set_type(struct irq_data *data, unsigned int type)
int shift;
u32 ctrl, mask;
u32 newvalue = 0;
+ struct irq_desc *desc = irq_to_desc(data->irq);
switch (type) {
case IRQ_TYPE_EDGE_RISING:
@@ -115,6 +126,11 @@ static int s5p_irq_eint_set_type(struct irq_data *data, unsigned int type)
else
printk(KERN_ERR "No such irq number %d", offs);
+ if (type & IRQ_TYPE_EDGE_BOTH)
+ desc->handle_irq = handle_edge_irq;
+ else
+ desc->handle_irq = handle_level_irq;
+
return 0;
}
diff --git a/arch/arm/plat-s5p/irq-pm.c b/arch/arm/plat-s5p/irq-pm.c
index 327acb3..d957398 100644
--- a/arch/arm/plat-s5p/irq-pm.c
+++ b/arch/arm/plat-s5p/irq-pm.c
@@ -21,6 +21,7 @@
#include <plat/irqs.h>
#include <plat/pm.h>
#include <mach/map.h>
+#include <plat/irq-pm.h>
#include <mach/regs-gpio.h>
#include <mach/regs-irq.h>
@@ -41,17 +42,49 @@ int s3c_irq_wake(struct irq_data *data, unsigned int state)
unsigned long irqbit;
switch (data->irq) {
- case IRQ_RTC_TIC:
case IRQ_RTC_ALARM:
- irqbit = 1 << (data->irq + 1 - IRQ_RTC_ALARM);
- if (!state)
- s3c_irqwake_intmask |= irqbit;
- else
- s3c_irqwake_intmask &= ~irqbit;
+ irqbit = 1 << 1;
+ break;
+ case IRQ_RTC_TIC:
+ irqbit = 1 << 2;
+ break;
+ case IRQ_ADC:
+ irqbit = 1 << 3;
+ break;
+ case IRQ_ADC1:
+ irqbit = 1 << 4;
+ break;
+ case IRQ_KEYPAD:
+ irqbit = 1 << 5;
+ break;
+ case IRQ_HSMMC0:
+ irqbit = 1 << 9;
+ break;
+ case IRQ_HSMMC1:
+ irqbit = 1 << 10;
+ break;
+ case IRQ_HSMMC2:
+ irqbit = 1 << 11;
+ break;
+ case IRQ_HSMMC3:
+ irqbit = 1 << 12;
+ break;
+ case IRQ_I2S0:
+ irqbit = 1 << 13;
+ break;
+ case IRQ_SYSTIMER:
+ irqbit = 1 << 14;
+ break;
+ case IRQ_CEC:
+ irqbit = 1 << 15;
break;
default:
return -ENOENT;
}
+ if (!state)
+ s3c_irqwake_intmask |= irqbit;
+ else
+ s3c_irqwake_intmask &= ~irqbit;
return 0;
}
@@ -61,19 +94,19 @@ static struct sleep_save eint_save[] = {
SAVE_ITEM(S5P_EINT_CON(2)),
SAVE_ITEM(S5P_EINT_CON(3)),
- SAVE_ITEM(S5P_EINT_FLTCON(0)),
- SAVE_ITEM(S5P_EINT_FLTCON(1)),
- SAVE_ITEM(S5P_EINT_FLTCON(2)),
- SAVE_ITEM(S5P_EINT_FLTCON(3)),
- SAVE_ITEM(S5P_EINT_FLTCON(4)),
- SAVE_ITEM(S5P_EINT_FLTCON(5)),
- SAVE_ITEM(S5P_EINT_FLTCON(6)),
- SAVE_ITEM(S5P_EINT_FLTCON(7)),
-
SAVE_ITEM(S5P_EINT_MASK(0)),
SAVE_ITEM(S5P_EINT_MASK(1)),
SAVE_ITEM(S5P_EINT_MASK(2)),
SAVE_ITEM(S5P_EINT_MASK(3)),
+
+ SAVE_ITEM(S5P_EINT_FLTCON(0,0)),
+ SAVE_ITEM(S5P_EINT_FLTCON(0,1)),
+ SAVE_ITEM(S5P_EINT_FLTCON(1,0)),
+ SAVE_ITEM(S5P_EINT_FLTCON(1,1)),
+ SAVE_ITEM(S5P_EINT_FLTCON(2,0)),
+ SAVE_ITEM(S5P_EINT_FLTCON(2,1)),
+ SAVE_ITEM(S5P_EINT_FLTCON(3,0)),
+ SAVE_ITEM(S5P_EINT_FLTCON(3,1)),
};
int s3c24xx_irq_suspend(void)
diff --git a/arch/arm/plat-s5p/irq.c b/arch/arm/plat-s5p/irq.c
index a97c089..c4b561c 100644
--- a/arch/arm/plat-s5p/irq.c
+++ b/arch/arm/plat-s5p/irq.c
@@ -24,6 +24,23 @@
#include <plat/cpu.h>
#include <plat/irq-vic-timer.h>
#include <plat/irq-uart.h>
+#include <plat/irq-pm.h>
+
+/* Wakeup source */
+static int wakeup_source[] = {
+ IRQ_RTC_ALARM,
+ IRQ_RTC_TIC,
+ IRQ_ADC,
+ IRQ_ADC1,
+ IRQ_KEYPAD,
+ IRQ_HSMMC0,
+ IRQ_HSMMC1,
+ IRQ_HSMMC2,
+ IRQ_HSMMC3,
+ IRQ_I2S0,
+ IRQ_SYSTIMER,
+ IRQ_CEC
+};
/*
* Note, we make use of the fact that the parent IRQs, IRQ_UART[0..3]
@@ -56,9 +73,10 @@ static struct s3c_uart_irq uart_irqs[] = {
void __init s5p_init_irq(u32 *vic, u32 num_vic)
{
-#ifdef CONFIG_ARM_VIC
+ struct irq_chip *chip;
int irq;
+#ifdef CONFIG_ARM_VIC
/* initialize the VICs */
for (irq = 0; irq < num_vic; irq++)
vic_init(VA_VIC(irq), VIC_BASE(irq), vic[irq], 0);
@@ -67,4 +85,10 @@ void __init s5p_init_irq(u32 *vic, u32 num_vic)
s3c_init_vic_timer_irq(5, IRQ_TIMER0);
s3c_init_uart_irqs(uart_irqs, ARRAY_SIZE(uart_irqs));
+
+ /* Register wakeup source. */
+ for (irq = 0; irq < ARRAY_SIZE(wakeup_source); irq++) {
+ chip = irq_get_chip(wakeup_source[irq]);
+ chip->irq_set_wake = s3c_irq_wake;
+ }
}
diff --git a/arch/arm/plat-s5p/reset.c b/arch/arm/plat-s5p/reset.c
new file mode 100644
index 0000000..96dfdab
--- /dev/null
+++ b/arch/arm/plat-s5p/reset.c
@@ -0,0 +1,33 @@
+/* linux/arch/arm/plat-s5p/include/plat/system-reset.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Based on arch/arm/mach-s3c2410/include/mach/system-reset.h
+ *
+ * S5P - System define for arch_reset()
+ *
+ * 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 <plat/system-reset.h>
+#include <plat/watchdog-reset.h>
+
+
+void (*s5p_reset_hook)(void);
+
+void arch_reset(char mode, const char *cmd)
+{
+ /* SWRESET support in s5p_reset_hook() */
+
+ if (s5p_reset_hook)
+ s5p_reset_hook();
+
+ /* Perform reset using Watchdog reset
+ * if there is no s5p_reset_hook()
+ */
+
+ arch_wdt_reset();
+}
diff --git a/arch/arm/plat-s5p/setup-mfc.c b/arch/arm/plat-s5p/setup-mfc.c
new file mode 100644
index 0000000..2bb3f06
--- /dev/null
+++ b/arch/arm/plat-s5p/setup-mfc.c
@@ -0,0 +1,17 @@
+/* arch/arm/plat-s5pv2xx/setup-mfc.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * MFC configuration
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+struct platform_device; /* don't need the contents */
+
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
index 53eb15b..c4bc9cb 100644
--- a/arch/arm/plat-samsung/Makefile
+++ b/arch/arm/plat-samsung/Makefile
@@ -12,7 +12,9 @@ obj- :=
# Objects we always build independent of SoC choice
obj-y += init.o
+ifndef CONFIG_S5P_HIGH_RES_TIMERS
obj-$(CONFIG_ARCH_USES_GETTIMEOFFSET) += time.o
+endif
obj-y += clock.o
obj-y += pwm-clock.o
obj-y += gpio.o
diff --git a/arch/arm/plat-samsung/adc.c b/arch/arm/plat-samsung/adc.c
index e8f2be2..df14954 100644
--- a/arch/arm/plat-samsung/adc.c
+++ b/arch/arm/plat-samsung/adc.c
@@ -143,11 +143,13 @@ int s3c_adc_start(struct s3c_adc_client *client,
return -EINVAL;
}
- if (client->is_ts && adc->ts_pend)
- return -EAGAIN;
-
spin_lock_irqsave(&adc->lock, flags);
+ if (client->is_ts && adc->ts_pend) {
+ spin_unlock_irqrestore(&adc->lock, flags);
+ return -EAGAIN;
+ }
+
client->channel = channel;
client->nr_samples = nr_samples;
diff --git a/arch/arm/plat-samsung/clock.c b/arch/arm/plat-samsung/clock.c
index 7728928..a3101e5 100644
--- a/arch/arm/plat-samsung/clock.c
+++ b/arch/arm/plat-samsung/clock.c
@@ -95,10 +95,19 @@ static int dev_is_platform_device(struct device *dev)
/* Clock API calls */
+static int nullstrcmp(const char *a, const char *b)
+{
+ if (!a)
+ return b ? -1 : 0;
+ if (!b)
+ return 1;
+
+ return strcmp(a, b);
+}
+
struct clk *clk_get(struct device *dev, const char *id)
{
- struct clk *p;
- struct clk *clk = ERR_PTR(-ENOENT);
+ struct clk *clk;
int idno;
if (dev == NULL || !dev_is_platform_device(dev))
@@ -108,65 +117,96 @@ struct clk *clk_get(struct device *dev, const char *id)
spin_lock(&clocks_lock);
- list_for_each_entry(p, &clocks, list) {
- if (p->id == idno &&
- strcmp(id, p->name) == 0 &&
- try_module_get(p->owner)) {
- clk = p;
- break;
- }
- }
+ list_for_each_entry(clk, &clocks, list)
+ if (!nullstrcmp(id, clk->name) && clk->dev == dev)
+ goto found_it;
- /* check for the case where a device was supplied, but the
- * clock that was being searched for is not device specific */
+ list_for_each_entry(clk, &clocks, list)
+ if (clk->id == idno && nullstrcmp(id, clk->name) == 0)
+ goto found_it;
- if (IS_ERR(clk)) {
- list_for_each_entry(p, &clocks, list) {
- if (p->id == -1 && strcmp(id, p->name) == 0 &&
- try_module_get(p->owner)) {
- clk = p;
- break;
- }
- }
- }
+ list_for_each_entry(clk, &clocks, list)
+ if (clk->id == -1 && !nullstrcmp(id, clk->name) &&
+ clk->dev == NULL)
+ goto found_it;
+ clk = ERR_PTR(-ENOENT);
+ pr_warning("%s: could not find clock %s for dev %pS (%s)\n",
+ __func__, id, dev, dev ? dev_name(dev) : "");
+ spin_unlock(&clocks_lock);
+ return clk;
+found_it:
+ pr_debug("%s(%p, %s) found %s %d %pS\n",
+ __func__, dev, id, clk->name, clk->id, clk->dev);
+ if (!try_module_get(clk->owner))
+ clk = ERR_PTR(-ENOENT);
spin_unlock(&clocks_lock);
return clk;
}
void clk_put(struct clk *clk)
{
+ pr_debug("%s on %s %d %pS", __func__, clk->name, clk->id, clk->dev);
module_put(clk->owner);
}
-int clk_enable(struct clk *clk)
+void _clk_enable(struct clk *clk)
{
- if (IS_ERR(clk) || clk == NULL)
- return -EINVAL;
+ if (!clk || IS_ERR(clk))
+ return;
- clk_enable(clk->parent);
+ if ((clk->usage++) > 0)
+ return;
- spin_lock(&clocks_lock);
+ _clk_enable(clk->parent);
+ pr_debug("%s update hardware clock %s %d %pS\n",
+ __func__, clk->name, clk->id, clk->dev);
+ (clk->enable)(clk, 1);
+}
- if ((clk->usage++) == 0)
- (clk->enable)(clk, 1);
+int clk_enable(struct clk *clk)
+{
+ if (WARN_ON_ONCE(IS_ERR(clk) || clk == NULL)) {
+ pr_debug("%s request on invalid clock\n", __func__);
+ return -EINVAL;
+ }
+ pr_debug("%s request on %s %d %pS\n",
+ __func__, clk->name, clk->id, clk->dev);
+ spin_lock(&clocks_lock);
+ _clk_enable(clk);
spin_unlock(&clocks_lock);
+
return 0;
}
-void clk_disable(struct clk *clk)
+void _clk_disable(struct clk *clk)
{
- if (IS_ERR(clk) || clk == NULL)
+ if (!clk || IS_ERR(clk))
+ return;
+
+ if ((--clk->usage) > 0)
return;
- spin_lock(&clocks_lock);
+ pr_debug("%s update hardware clock %s %d %pS\n",
+ __func__, clk->name, clk->id, clk->dev);
+ (clk->enable)(clk, 0);
+ _clk_disable(clk->parent);
+}
- if ((--clk->usage) == 0)
- (clk->enable)(clk, 0);
+void clk_disable(struct clk *clk)
+{
+ if (IS_ERR(clk) || clk == NULL) {
+ pr_debug("%s request on invalid clock\n", __func__);
+ return;
+ }
+ pr_debug("%s request on %s %d %pS\n",
+ __func__, clk->name, clk->id, clk->dev);
+
+ spin_lock(&clocks_lock);
+ _clk_disable(clk);
spin_unlock(&clocks_lock);
- clk_disable(clk->parent);
}
@@ -352,6 +392,25 @@ int s3c24xx_register_clock(struct clk *clk)
BUG_ON(clk->list.prev != clk->list.next);
spin_lock(&clocks_lock);
+ if (clk->enable != clk_null_enable) {
+ struct clk *c;
+ list_for_each_entry(c, &clocks, list) {
+ if (c->enable == clk->enable &&
+ c->ctrlbit & clk->ctrlbit) {
+ pr_warning("%s: new clock %s, id %d, dev %p "
+ "uses same enable bit as "
+ "%s, id %d, dev %p\n", __func__,
+ clk->name, clk->id, clk->dev,
+ c->name, c->id, c->dev);
+ }
+ if (!nullstrcmp(c->name, clk->name) &&
+ c->id == clk->id && c->dev == clk->dev) {
+ pr_warning("%s: duplicate clock id: "
+ "%s, id %d, dev %p\n", __func__,
+ clk->name, clk->id, clk->dev);
+ }
+ }
+ }
list_add(&clk->list, &clocks);
spin_unlock(&clocks_lock);
@@ -462,18 +521,35 @@ static int clk_debugfs_register_one(struct clk *c)
struct clk *pa = c->parent;
char s[255];
char *p = s;
+ int i;
p += sprintf(p, "%s", c->name);
if (c->id >= 0)
- sprintf(p, ":%d", c->id);
+ p += sprintf(p, ":%d", c->id);
- d = debugfs_create_dir(s, pa ? pa->dent : clk_debugfs_root);
- if (!d)
- return -ENOMEM;
+ for (i = 1; i < 16; i++) {
+ d = debugfs_create_dir(s, clk_debugfs_root);
+ if (d)
+ break;
+ sprintf(p, " copy %d", i);
+ }
+ if (!d) {
+ pr_warning("%s: failed to register %s\n", __func__, s);
+ return 0;
+ }
c->dent = d;
+ if (pa) {
+ d = debugfs_create_symlink("parent",
+ c->dent, pa->dent->d_name.name);
+ if (!d) {
+ err = -ENOMEM;
+ goto err_out;
+ }
+ }
+
d = debugfs_create_u8("usecount", S_IRUGO, c->dent, (u8 *)&c->usage);
if (!d) {
err = -ENOMEM;
diff --git a/arch/arm/plat-samsung/dev-hsmmc.c b/arch/arm/plat-samsung/dev-hsmmc.c
index db7a65c..9296bd8 100644
--- a/arch/arm/plat-samsung/dev-hsmmc.c
+++ b/arch/arm/plat-samsung/dev-hsmmc.c
@@ -76,4 +76,10 @@ void s3c_sdhci0_set_platdata(struct s3c_sdhci_platdata *pd)
set->host_caps |= pd->host_caps;
if (pd->clk_type)
set->clk_type = pd->clk_type;
+ if (pd->built_in)
+ set->built_in = pd->built_in;
+ if (pd->must_maintain_clock)
+ set->must_maintain_clock = pd->must_maintain_clock;
+ if (pd->enable_intr_on_resume)
+ set->enable_intr_on_resume = pd->enable_intr_on_resume;
}
diff --git a/arch/arm/plat-samsung/dev-hsmmc1.c b/arch/arm/plat-samsung/dev-hsmmc1.c
index 2497321..4e7b100 100644
--- a/arch/arm/plat-samsung/dev-hsmmc1.c
+++ b/arch/arm/plat-samsung/dev-hsmmc1.c
@@ -76,4 +76,10 @@ void s3c_sdhci1_set_platdata(struct s3c_sdhci_platdata *pd)
set->host_caps |= pd->host_caps;
if (pd->clk_type)
set->clk_type = pd->clk_type;
+ if (pd->built_in)
+ set->built_in = pd->built_in;
+ if (pd->must_maintain_clock)
+ set->must_maintain_clock = pd->must_maintain_clock;
+ if (pd->enable_intr_on_resume)
+ set->enable_intr_on_resume = pd->enable_intr_on_resume;
}
diff --git a/arch/arm/plat-samsung/dev-hsmmc2.c b/arch/arm/plat-samsung/dev-hsmmc2.c
index f60aedb..ef2e8c6 100644
--- a/arch/arm/plat-samsung/dev-hsmmc2.c
+++ b/arch/arm/plat-samsung/dev-hsmmc2.c
@@ -77,4 +77,10 @@ void s3c_sdhci2_set_platdata(struct s3c_sdhci_platdata *pd)
set->host_caps |= pd->host_caps;
if (pd->clk_type)
set->clk_type = pd->clk_type;
+ if (pd->built_in)
+ set->built_in = pd->built_in;
+ if (pd->must_maintain_clock)
+ set->must_maintain_clock = pd->must_maintain_clock;
+ if (pd->enable_intr_on_resume)
+ set->enable_intr_on_resume = pd->enable_intr_on_resume;
}
diff --git a/arch/arm/plat-samsung/dev-hsmmc3.c b/arch/arm/plat-samsung/dev-hsmmc3.c
index ede776f..da729c5 100644
--- a/arch/arm/plat-samsung/dev-hsmmc3.c
+++ b/arch/arm/plat-samsung/dev-hsmmc3.c
@@ -80,4 +80,10 @@ void s3c_sdhci3_set_platdata(struct s3c_sdhci_platdata *pd)
set->host_caps |= pd->host_caps;
if (pd->clk_type)
set->clk_type = pd->clk_type;
+ if (pd->built_in)
+ set->built_in = pd->built_in;
+ if (pd->must_maintain_clock)
+ set->must_maintain_clock = pd->must_maintain_clock;
+ if (pd->enable_intr_on_resume)
+ set->enable_intr_on_resume = pd->enable_intr_on_resume;
}
diff --git a/arch/arm/plat-samsung/dev-i2c0.c b/arch/arm/plat-samsung/dev-i2c0.c
index 3a601c1..0aa46b1 100644
--- a/arch/arm/plat-samsung/dev-i2c0.c
+++ b/arch/arm/plat-samsung/dev-i2c0.c
@@ -15,6 +15,8 @@
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/err.h>
#include <mach/irqs.h>
#include <mach/map.h>
@@ -24,6 +26,8 @@
#include <plat/devs.h>
#include <plat/cpu.h>
+#include <asm/io.h>
+
static struct resource s3c_i2c_resource[] = {
[0] = {
.start = S3C_PA_IIC,
@@ -39,11 +43,7 @@ static struct resource s3c_i2c_resource[] = {
struct platform_device s3c_device_i2c0 = {
.name = "s3c2410-i2c",
-#ifdef CONFIG_S3C_DEV_I2C1
.id = 0,
-#else
- .id = -1,
-#endif
.num_resources = ARRAY_SIZE(s3c_i2c_resource),
.resource = s3c_i2c_resource,
};
@@ -51,8 +51,8 @@ struct platform_device s3c_device_i2c0 = {
static struct s3c2410_platform_i2c default_i2c_data0 __initdata = {
.flags = 0,
.slave_addr = 0x10,
- .frequency = 100*1000,
- .sda_delay = 100,
+ .frequency = 400*1000,
+ .sda_delay = S3C2410_IICLC_SDA_DELAY15 | S3C2410_IICLC_FILTER_ON,
};
void __init s3c_i2c0_set_platdata(struct s3c2410_platform_i2c *pd)
@@ -70,3 +70,31 @@ void __init s3c_i2c0_set_platdata(struct s3c2410_platform_i2c *pd)
s3c_device_i2c0.dev.platform_data = npd;
}
+
+void s3c_i2c0_force_stop()
+{
+ void __iomem *regs;
+ struct clk *clk;
+ unsigned long iicstat;
+
+ regs = ioremap(S3C_PA_IIC, SZ_4K);
+ if(regs == NULL) {
+ printk(KERN_ERR "%s, cannot request IO\n", __func__);
+ return;
+ }
+
+ clk = clk_get(&s3c_device_i2c0.dev, "i2c");
+ if(clk == NULL || IS_ERR(clk)) {
+ printk(KERN_ERR "%s, cannot get cloock\n", __func__);
+ return;
+ }
+
+ clk_enable(clk);
+ iicstat = readl(regs + S3C2410_IICSTAT);
+ writel(iicstat & ~S3C2410_IICSTAT_TXRXEN, regs + S3C2410_IICSTAT);
+ clk_disable(clk);
+
+ iounmap(regs);
+}
+EXPORT_SYMBOL(s3c_i2c0_force_stop);
+
diff --git a/arch/arm/plat-samsung/dev-i2c1.c b/arch/arm/plat-samsung/dev-i2c1.c
index 858ee2a..3a1a85f 100644
--- a/arch/arm/plat-samsung/dev-i2c1.c
+++ b/arch/arm/plat-samsung/dev-i2c1.c
@@ -15,6 +15,8 @@
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/err.h>
#include <mach/irqs.h>
#include <mach/map.h>
@@ -24,6 +26,8 @@
#include <plat/devs.h>
#include <plat/cpu.h>
+#include <asm/io.h>
+
static struct resource s3c_i2c_resource[] = {
[0] = {
.start = S3C_PA_IIC1,
@@ -48,8 +52,8 @@ static struct s3c2410_platform_i2c default_i2c_data1 __initdata = {
.flags = 0,
.bus_num = 1,
.slave_addr = 0x10,
- .frequency = 100*1000,
- .sda_delay = 100,
+ .frequency = 400*1000,
+ .sda_delay = S3C2410_IICLC_SDA_DELAY5 | S3C2410_IICLC_FILTER_ON,
};
void __init s3c_i2c1_set_platdata(struct s3c2410_platform_i2c *pd)
@@ -67,3 +71,32 @@ void __init s3c_i2c1_set_platdata(struct s3c2410_platform_i2c *pd)
s3c_device_i2c1.dev.platform_data = npd;
}
+
+void s3c_i2c1_force_stop()
+{
+ struct resource *ioarea;
+ void __iomem *regs;
+ struct clk *clk;
+ unsigned long iicstat;
+
+ regs = ioremap(S3C_PA_IIC1, SZ_4K);
+ if(regs == NULL) {
+ printk(KERN_ERR "%s, cannot request IO\n", __func__);
+ return;
+ }
+
+ clk = clk_get(&s3c_device_i2c1.dev, "i2c");
+ if(clk == NULL || IS_ERR(clk)) {
+ printk(KERN_ERR "%s, cannot get cloock\n", __func__);
+ return;
+ }
+
+ clk_enable(clk);
+ iicstat = readl(regs + S3C2410_IICSTAT);
+ writel(iicstat & ~S3C2410_IICSTAT_TXRXEN, regs + S3C2410_IICSTAT);
+ clk_disable(clk);
+
+ iounmap(regs);
+}
+EXPORT_SYMBOL(s3c_i2c1_force_stop);
+
diff --git a/arch/arm/plat-samsung/dev-i2c2.c b/arch/arm/plat-samsung/dev-i2c2.c
index ff4ba69..d9b5fb6 100644
--- a/arch/arm/plat-samsung/dev-i2c2.c
+++ b/arch/arm/plat-samsung/dev-i2c2.c
@@ -1,12 +1,11 @@
/* linux/arch/arm/plat-s3c/dev-i2c2.c
*
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
+ * Copyright 2008-2009 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ * http://armlinux.simtec.co.uk/
*
* S3C series device definition for i2c device 2
*
- * Based on plat-samsung/dev-i2c0.c
- *
* 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.
@@ -16,6 +15,8 @@
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/err.h>
#include <mach/irqs.h>
#include <mach/map.h>
@@ -25,6 +26,8 @@
#include <plat/devs.h>
#include <plat/cpu.h>
+#include <asm/io.h>
+
static struct resource s3c_i2c_resource[] = {
[0] = {
.start = S3C_PA_IIC2,
@@ -49,8 +52,8 @@ static struct s3c2410_platform_i2c default_i2c_data2 __initdata = {
.flags = 0,
.bus_num = 2,
.slave_addr = 0x10,
- .frequency = 100*1000,
- .sda_delay = 100,
+ .frequency = 400*1000,
+ .sda_delay = S3C2410_IICLC_SDA_DELAY5 | S3C2410_IICLC_FILTER_ON,
};
void __init s3c_i2c2_set_platdata(struct s3c2410_platform_i2c *pd)
@@ -68,3 +71,31 @@ void __init s3c_i2c2_set_platdata(struct s3c2410_platform_i2c *pd)
s3c_device_i2c2.dev.platform_data = npd;
}
+
+void s3c_i2c2_force_stop()
+{
+ void __iomem *regs;
+ struct clk *clk;
+ unsigned long iicstat;
+
+ regs = ioremap(S3C_PA_IIC2, SZ_4K);
+ if(regs == NULL) {
+ printk(KERN_ERR "%s, cannot request IO\n", __func__);
+ return;
+ }
+
+ clk = clk_get(&s3c_device_i2c2.dev, "i2c");
+ if(clk == NULL || IS_ERR(clk)) {
+ printk(KERN_ERR "%s, cannot get cloock\n", __func__);
+ return;
+ }
+
+ clk_enable(clk);
+ iicstat = readl(regs + S3C2410_IICSTAT);
+ writel(iicstat & ~S3C2410_IICSTAT_TXRXEN, regs + S3C2410_IICSTAT);
+ clk_disable(clk);
+
+ iounmap(regs);
+}
+EXPORT_SYMBOL(s3c_i2c2_force_stop);
+
diff --git a/arch/arm/plat-samsung/dev-uart.c b/arch/arm/plat-samsung/dev-uart.c
index 5928105..6db1f63 100644
--- a/arch/arm/plat-samsung/dev-uart.c
+++ b/arch/arm/plat-samsung/dev-uart.c
@@ -19,19 +19,19 @@
/* uart devices */
-static struct platform_device s3c24xx_uart_device0 = {
+struct platform_device s3c24xx_uart_device0 = {
.id = 0,
};
-static struct platform_device s3c24xx_uart_device1 = {
+struct platform_device s3c24xx_uart_device1 = {
.id = 1,
};
-static struct platform_device s3c24xx_uart_device2 = {
+struct platform_device s3c24xx_uart_device2 = {
.id = 2,
};
-static struct platform_device s3c24xx_uart_device3 = {
+struct platform_device s3c24xx_uart_device3 = {
.id = 3,
};
diff --git a/arch/arm/plat-samsung/gpio-config.c b/arch/arm/plat-samsung/gpio-config.c
index 1c0b040..a899173 100644
--- a/arch/arm/plat-samsung/gpio-config.c
+++ b/arch/arm/plat-samsung/gpio-config.c
@@ -130,6 +130,27 @@ s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin)
}
EXPORT_SYMBOL(s3c_gpio_getpull);
+int s3c_gpio_setpin(unsigned int pin, s3c_gpio_pull_t level)
+{
+ struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
+ unsigned long flags;
+ int offset, ret;
+
+ if (!chip)
+ return -EINVAL;
+
+ offset = pin - chip->chip.base;
+
+ local_irq_save(flags);
+ //ret = s3c_gpio_do_setpin(chip, offset, level);
+ ret = (chip->config->set_pin)(chip, offset, level);
+ local_irq_restore(flags);
+
+ return ret;
+}
+
+EXPORT_SYMBOL(s3c_gpio_setpin);
+
#ifdef CONFIG_S3C_GPIO_CFG_S3C24XX
int s3c_gpio_setcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
unsigned int off, unsigned int cfg)
diff --git a/arch/arm/plat-samsung/include/plat/clock.h b/arch/arm/plat-samsung/include/plat/clock.h
index 983c578..0533827 100644
--- a/arch/arm/plat-samsung/include/plat/clock.h
+++ b/arch/arm/plat-samsung/include/plat/clock.h
@@ -46,6 +46,7 @@ struct clk {
unsigned long ctrlbit;
struct clk_ops *ops;
+ struct device *dev;
int (*enable)(struct clk *, int enable);
#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
struct dentry *dent; /* For visible tree hierarchy */
diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h
index c0a5741..8865194 100644
--- a/arch/arm/plat-samsung/include/plat/cpu.h
+++ b/arch/arm/plat-samsung/include/plat/cpu.h
@@ -66,7 +66,11 @@ extern void s3c24xx_init_uartdevs(char *name,
/* timer for 2410/2440 */
struct sys_timer;
+#if defined(CONFIG_S5P_HIGH_RES_TIMERS)
+extern struct sys_timer s5p_systimer;
+#else
extern struct sys_timer s3c24xx_timer;
+#endif
extern struct syscore_ops s3c2410_pm_syscore_ops;
extern struct syscore_ops s3c2412_pm_syscore_ops;
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h
index e3b31c2..9a918d0 100644
--- a/arch/arm/plat-samsung/include/plat/devs.h
+++ b/arch/arm/plat-samsung/include/plat/devs.h
@@ -30,6 +30,16 @@ extern struct s3c24xx_uart_resources s5p_uart_resources[];
extern struct platform_device *s3c24xx_uart_devs[];
extern struct platform_device *s3c24xx_uart_src[];
+extern struct platform_device s3c24xx_uart_device0;
+extern struct platform_device s3c24xx_uart_device1;
+extern struct platform_device s3c24xx_uart_device2;
+extern struct platform_device s3c24xx_uart_device3;
+
+extern struct platform_device s5pv210_device_fiqdbg_uart0;
+extern struct platform_device s5pv210_device_fiqdbg_uart1;
+extern struct platform_device s5pv210_device_fiqdbg_uart2;
+extern struct platform_device s5pv210_device_fiqdbg_uart3;
+
extern struct platform_device s3c_device_timer[];
extern struct platform_device s3c64xx_device_iis0;
@@ -49,6 +59,15 @@ extern struct platform_device s3c64xx_device_ac97;
extern struct platform_device s3c_device_ts;
extern struct platform_device s3c_device_fb;
+
+extern struct platform_device s3c_device_fimc0;
+extern struct platform_device s3c_device_fimc1;
+extern struct platform_device s3c_device_fimc2;
+extern struct platform_device s3c_device_ipc;
+extern struct platform_device s3c_device_mfc;
+extern struct platform_device s3c_device_jpeg;
+extern struct platform_device s3c_device_g3d;
+
extern struct platform_device s3c_device_ohci;
extern struct platform_device s3c_device_lcd;
extern struct platform_device s3c_device_wdt;
@@ -91,7 +110,19 @@ extern struct platform_device s5p_device_onenand;
extern struct platform_device s3c_device_usbgadget;
extern struct platform_device s3c_device_usb_hsudc;
+extern struct platform_device s3c_device_android_usb;
+extern struct platform_device s3c_device_usb_mass_storage;
+extern struct platform_device s3c_device_rndis;
extern struct platform_device s3c_device_usb_hsotg;
+#if defined CONFIG_USB_S3C_OTG_HOST
+extern struct platform_device s3c_device_usb_otghcd;
+#endif
+#if defined CONFIG_USB_DWC_OTG
+extern struct platform_device s3c_device_usb_dwcotg;
+#endif
+extern struct platform_device s5p_device_rotator;
+extern struct platform_device s5p_device_tvout;
+extern struct platform_device s5p_device_g3d;
extern struct platform_device s5pv210_device_ac97;
extern struct platform_device s5pv210_device_pcm0;
@@ -142,9 +173,17 @@ extern struct platform_device s5p_device_mipi_csis1;
extern struct platform_device s5p_device_ehci;
extern struct platform_device exynos4_device_sysmmu;
+extern struct platform_device s5p_device_rtc;
+extern struct platform_device s3c_device_adc;
/* s3c2440 specific devices */
+extern struct platform_device s5pv210_device_pdma0;
+extern struct platform_device s5pv210_device_pdma1;
+extern struct platform_device s5pv210_device_mdma;
+
+extern struct platform_device s5pv210_device_cpufreq;
+
#ifdef CONFIG_CPU_S3C2440
extern struct platform_device s3c_device_camif;
@@ -164,4 +203,6 @@ extern struct platform_device s3c_device_ac97;
extern void *s3c_set_platdata(void *pd, size_t pdsize,
struct platform_device *pdev);
+void __init s3c_usb_set_serial(void);
+
#endif /* __PLAT_DEVS_H */
diff --git a/arch/arm/plat-samsung/include/plat/dma.h b/arch/arm/plat-samsung/include/plat/dma.h
index 8c273b7..459bdc8 100644
--- a/arch/arm/plat-samsung/include/plat/dma.h
+++ b/arch/arm/plat-samsung/include/plat/dma.h
@@ -18,7 +18,9 @@ enum s3c2410_dma_buffresult {
enum s3c2410_dmasrc {
S3C2410_DMASRC_HW, /* source is memory */
- S3C2410_DMASRC_MEM /* source is hardware */
+ S3C2410_DMASRC_MEM, /* source is hardware */
+ S3C_DMA_MEM2MEM,
+ S3C_DMA_MEM2MEM_SET,
};
/* enum s3c2410_chan_op
diff --git a/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h b/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h
index 3ad8386..33cc2ca 100644
--- a/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h
+++ b/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h
@@ -48,6 +48,12 @@ static inline s3c_gpio_pull_t s3c_gpio_do_getpull(struct s3c_gpio_chip *chip,
return chip->config->get_pull(chip, off);
}
+static inline int s3c_gpio_do_setpin(struct s3c_gpio_chip *chip,
+ unsigned int off, s3c_gpio_pull_t level)
+{
+ return (chip->config->set_pin)(chip, off, level);
+}
+
/**
* s3c_gpio_setcfg_s3c24xx - S3C24XX style GPIO configuration.
* @chip: The gpio chip that is being configured.
diff --git a/arch/arm/plat-samsung/include/plat/gpio-cfg.h b/arch/arm/plat-samsung/include/plat/gpio-cfg.h
index 1762dcb..60b7460 100644
--- a/arch/arm/plat-samsung/include/plat/gpio-cfg.h
+++ b/arch/arm/plat-samsung/include/plat/gpio-cfg.h
@@ -56,11 +56,16 @@ struct s3c_gpio_cfg {
int (*set_pull)(struct s3c_gpio_chip *chip, unsigned offs,
s3c_gpio_pull_t pull);
+ int (*set_pin)(struct s3c_gpio_chip *chip, unsigned offs,
+ s3c_gpio_pull_t level);
+
unsigned (*get_config)(struct s3c_gpio_chip *chip, unsigned offs);
int (*set_config)(struct s3c_gpio_chip *chip, unsigned offs,
unsigned config);
};
+extern int s3c_gpio_setpin(unsigned int pin, s3c_gpio_pull_t level);
+
#define S3C_GPIO_SPECIAL_MARK (0xfffffff0)
#define S3C_GPIO_SPECIAL(x) (S3C_GPIO_SPECIAL_MARK | (x))
diff --git a/arch/arm/plat-samsung/include/plat/gpio-core.h b/arch/arm/plat-samsung/include/plat/gpio-core.h
index 8cad4cf..0ce5225 100644..100755
--- a/arch/arm/plat-samsung/include/plat/gpio-core.h
+++ b/arch/arm/plat-samsung/include/plat/gpio-core.h
@@ -69,7 +69,7 @@ struct s3c_gpio_chip {
int group;
spinlock_t lock;
#ifdef CONFIG_PM
- u32 pm_save[4];
+ u32 pm_save[7];
#endif
};
diff --git a/arch/arm/plat-samsung/include/plat/iic.h b/arch/arm/plat-samsung/include/plat/iic.h
index 1543da8..aec3471 100644
--- a/arch/arm/plat-samsung/include/plat/iic.h
+++ b/arch/arm/plat-samsung/include/plat/iic.h
@@ -71,4 +71,8 @@ extern void s3c_i2c5_cfg_gpio(struct platform_device *dev);
extern void s3c_i2c6_cfg_gpio(struct platform_device *dev);
extern void s3c_i2c7_cfg_gpio(struct platform_device *dev);
+extern void s3c_i2c0_force_stop(void);
+extern void s3c_i2c1_force_stop(void);
+extern void s3c_i2c2_force_stop(void);
+
#endif /* __ASM_ARCH_IIC_H */
diff --git a/arch/arm/plat-samsung/include/plat/map-base.h b/arch/arm/plat-samsung/include/plat/map-base.h
index 3ffac4d..da2414c 100644
--- a/arch/arm/plat-samsung/include/plat/map-base.h
+++ b/arch/arm/plat-samsung/include/plat/map-base.h
@@ -14,7 +14,7 @@
#ifndef __ASM_PLAT_MAP_H
#define __ASM_PLAT_MAP_H __FILE__
-/* Fit all our registers in at 0xF6000000 upwards, trying to use as
+/* Fit all our registers in at 0xFC000000 upwards, trying to use as
* little of the VA space as possible so vmalloc and friends have a
* better chance of getting memory.
*
@@ -22,7 +22,7 @@
* an single MOVS instruction (ie, only 8 bits of set data)
*/
-#define S3C_ADDR_BASE 0xF6000000
+#define S3C_ADDR_BASE (0xFC000000)
#ifndef __ASSEMBLY__
#define S3C_ADDR(x) ((void __iomem __force *)S3C_ADDR_BASE + (x))
@@ -35,6 +35,8 @@
#define S3C_VA_MEM S3C_ADDR(0x00200000) /* memory control */
#define S3C_VA_TIMER S3C_ADDR(0x00300000) /* timer block */
#define S3C_VA_WATCHDOG S3C_ADDR(0x00400000) /* watchdog */
+#define S3C_VA_OTG S3C_ADDR(0x00E00000) /* OTG */
+#define S3C_VA_OTGSFR S3C_ADDR(0x00F00000) /* OTG PHY */
#define S3C_VA_UART S3C_ADDR(0x01000000) /* UART */
/* This is used for the CPU specific mappings that may be needed, so that
diff --git a/arch/arm/plat-samsung/include/plat/pm.h b/arch/arm/plat-samsung/include/plat/pm.h
index 7fb6f6b..b85132d 100644
--- a/arch/arm/plat-samsung/include/plat/pm.h
+++ b/arch/arm/plat-samsung/include/plat/pm.h
@@ -43,6 +43,7 @@ extern unsigned long s3c_irqwake_eintallow;
extern void (*pm_cpu_prep)(void);
extern void (*pm_cpu_sleep)(void);
+extern void (*pm_cpu_restore)(void);
/* Flags for PM Control */
@@ -128,7 +129,7 @@ extern void s3c_pm_dbg(const char *msg, ...);
#define S3C_PMDBG(fmt...) s3c_pm_dbg(fmt)
#else
-#define S3C_PMDBG(fmt...) printk(KERN_DEBUG fmt)
+#define S3C_PMDBG(fmt...) pr_debug(fmt)
#endif
#ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK
diff --git a/arch/arm/plat-samsung/include/plat/regs-otg.h b/arch/arm/plat-samsung/include/plat/regs-otg.h
new file mode 100644
index 0000000..dccdb26
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/regs-otg.h
@@ -0,0 +1,262 @@
+/* arch/arm/plat-samsung/include/plat/regs-otg.h
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ * Kyoungil Kim <ki0351.kim@samsung.com>
+ *
+ * This include file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+*/
+
+#ifndef __ASM_ARCH_REGS_USB_OTG_HS_H
+#define __ASM_ARCH_REGS_USB_OTG_HS_H
+
+/* USB2.0 OTG Controller register */
+#define S3C_USBOTG_PHYREG(x) ((x) + S3C_VA_OTGSFR)
+#define S3C_USBOTG_PHYPWR S3C_USBOTG_PHYREG(0x0)
+#define S3C_USBOTG_PHYCLK S3C_USBOTG_PHYREG(0x4)
+#define S3C_USBOTG_RSTCON S3C_USBOTG_PHYREG(0x8)
+#define S3C_USBOTG_PHYTUNE S3C_USBOTG_PHYREG(0x24)
+
+/* USB2.0 OTG Controller register */
+#define S3C_USBOTGREG(x) ((x) + S3C_VA_OTG)
+/*============================================================================================== */
+ /* Core Global Registers */
+#define S3C_UDC_OTG_GOTGCTL S3C_USBOTGREG(0x000) /* OTG Control & Status */
+#define S3C_UDC_OTG_GOTGINT S3C_USBOTGREG(0x004) /* OTG Interrupt */
+#define S3C_UDC_OTG_GAHBCFG S3C_USBOTGREG(0x008) /* Core AHB Configuration */
+#define S3C_UDC_OTG_GUSBCFG S3C_USBOTGREG(0x00C) /* Core USB Configuration */
+#define S3C_UDC_OTG_GRSTCTL S3C_USBOTGREG(0x010) /* Core Reset */
+#define S3C_UDC_OTG_GINTSTS S3C_USBOTGREG(0x014) /* Core Interrupt */
+#define S3C_UDC_OTG_GINTMSK S3C_USBOTGREG(0x018) /* Core Interrupt Mask */
+#define S3C_UDC_OTG_GRXSTSR S3C_USBOTGREG(0x01C) /* Receive Status Debug Read/Status Read */
+#define S3C_UDC_OTG_GRXSTSP S3C_USBOTGREG(0x020) /* Receive Status Debug Pop/Status Pop */
+#define S3C_UDC_OTG_GRXFSIZ S3C_USBOTGREG(0x024) /* Receive FIFO Size */
+#define S3C_UDC_OTG_GNPTXFSIZ S3C_USBOTGREG(0x028) /* Non-Periodic Transmit FIFO Size */
+#define S3C_UDC_OTG_GNPTXSTS S3C_USBOTGREG(0x02C) /* Non-Periodic Transmit FIFO/Queue Status */
+
+#define S3C_UDC_OTG_HPTXFSIZ S3C_USBOTGREG(0x100) /* Host Periodic Transmit FIFO Size */
+#define S3C_UDC_OTG_DIEPTXF(n) S3C_USBOTGREG(0x104 + (n-1)*0x4)/* Device IN EP Transmit FIFO Size Register */
+
+/*============================================================================================== */
+/* Host Mode Registers */
+/*------------------------------------------------ */
+/* Host Global Registers */
+#define S3C_UDC_OTG_HCFG S3C_USBOTGREG(0x400) /* Host Configuration */
+#define S3C_UDC_OTG_HFIR S3C_USBOTGREG(0x404) /* Host Frame Interval */
+#define S3C_UDC_OTG_HFNUM S3C_USBOTGREG(0x408) /* Host Frame Number/Frame Time Remaining */
+#define S3C_UDC_OTG_HPTXSTS S3C_USBOTGREG(0x410) /* Host Periodic Transmit FIFO/Queue Status */
+#define S3C_UDC_OTG_HAINT S3C_USBOTGREG(0x414) /* Host All Channels Interrupt */
+#define S3C_UDC_OTG_HAINTMSK S3C_USBOTGREG(0x418) /* Host All Channels Interrupt Mask */
+
+/*------------------------------------------------ */
+/* Host Port Control & Status Registers */
+#define S3C_UDC_OTG_HPRT S3C_USBOTGREG(0x440) /* Host Port Control & Status */
+
+/*------------------------------------------------ */
+/* Host Channel-Specific Registers */
+#define S3C_UDC_OTG_HCCHAR0 S3C_USBOTGREG(0x500) /* Host Channel-0 Characteristics */
+#define S3C_UDC_OTG_HCSPLT0 S3C_USBOTGREG(0x504) /* Host Channel-0 Split Control */
+#define S3C_UDC_OTG_HCINT0 S3C_USBOTGREG(0x508) /* Host Channel-0 Interrupt */
+#define S3C_UDC_OTG_HCINTMSK0 S3C_USBOTGREG(0x50C) /* Host Channel-0 Interrupt Mask */
+#define S3C_UDC_OTG_HCTSIZ0 S3C_USBOTGREG(0x510) /* Host Channel-0 Transfer Size */
+#define S3C_UDC_OTG_HCDMA0 S3C_USBOTGREG(0x514) /* Host Channel-0 DMA Address */
+
+
+/*============================================================================================== */
+/* Device Mode Registers */
+/*------------------------------------------------ */
+/* Device Global Registers */
+#define S3C_UDC_OTG_DCFG S3C_USBOTGREG(0x800) /* Device Configuration */
+#define S3C_UDC_OTG_DCTL S3C_USBOTGREG(0x804) /* Device Control */
+#define S3C_UDC_OTG_DSTS S3C_USBOTGREG(0x808) /* Device Status */
+#define S3C_UDC_OTG_DIEPMSK S3C_USBOTGREG(0x810) /* Device IN Endpoint Common Interrupt Mask */
+#define S3C_UDC_OTG_DOEPMSK S3C_USBOTGREG(0x814) /* Device OUT Endpoint Common Interrupt Mask */
+#define S3C_UDC_OTG_DAINT S3C_USBOTGREG(0x818) /* Device All Endpoints Interrupt */
+#define S3C_UDC_OTG_DAINTMSK S3C_USBOTGREG(0x81C) /* Device All Endpoints Interrupt Mask */
+#define S3C_UDC_OTG_DTKNQR1 S3C_USBOTGREG(0x820) /* Device IN Token Sequence Learning Queue Read 1 */
+#define S3C_UDC_OTG_DTKNQR2 S3C_USBOTGREG(0x824) /* Device IN Token Sequence Learning Queue Read 2 */
+#define S3C_UDC_OTG_DVBUSDIS S3C_USBOTGREG(0x828) /* Device VBUS Discharge Time */
+#define S3C_UDC_OTG_DVBUSPULSE S3C_USBOTGREG(0x82C) /* Device VBUS Pulsing Time */
+#define S3C_UDC_OTG_DTKNQR3 S3C_USBOTGREG(0x830) /* Device IN Token Sequence Learning Queue Read 3 */
+#define S3C_UDC_OTG_DTKNQR4 S3C_USBOTGREG(0x834) /* Device IN Token Sequence Learning Queue Read 4 */
+
+/*------------------------------------------------ */
+/* Device Logical IN Endpoint-Specific Registers */
+#define S3C_UDC_OTG_DIEPCTL(n) S3C_USBOTGREG(0x900 + n*0x20) /* Device IN Endpoint n Control */
+#define S3C_UDC_OTG_DIEPINT(n) S3C_USBOTGREG(0x908 + n*0x20) /* Device IN Endpoint n Interrupt */
+#define S3C_UDC_OTG_DIEPTSIZ(n) S3C_USBOTGREG(0x910 + n*0x20) /* Device IN Endpoint n Transfer Size */
+#define S3C_UDC_OTG_DIEPDMA(n) S3C_USBOTGREG(0x914 + n*0x20) /* Device IN Endpoint n DMA Address */
+
+/*------------------------------------------------ */
+/* Device Logical OUT Endpoint-Specific Registers */
+#define S3C_UDC_OTG_DOEPCTL(n) S3C_USBOTGREG(0xB00 + n*0x20) /* Device OUT Endpoint n Control */
+#define S3C_UDC_OTG_DOEPINT(n) S3C_USBOTGREG(0xB08 + n*0x20) /* Device OUT Endpoint n Interrupt */
+#define S3C_UDC_OTG_DOEPTSIZ(n) S3C_USBOTGREG(0xB10 + n*0x20) /* Device OUT Endpoint n Transfer Size */
+#define S3C_UDC_OTG_DOEPDMA(n) S3C_USBOTGREG(0xB14 + n*0x20) /* Device OUT Endpoint n DMA Address */
+
+/*------------------------------------------------ */
+/* Endpoint FIFO address */
+#define S3C_UDC_OTG_EP0_FIFO S3C_USBOTGREG(0x1000)
+#define S3C_UDC_OTG_EP1_FIFO S3C_USBOTGREG(0x2000)
+#define S3C_UDC_OTG_EP2_FIFO S3C_USBOTGREG(0x3000)
+#define S3C_UDC_OTG_EP3_FIFO S3C_USBOTGREG(0x4000)
+#define S3C_UDC_OTG_EP4_FIFO S3C_USBOTGREG(0x5000)
+#define S3C_UDC_OTG_EP5_FIFO S3C_USBOTGREG(0x6000)
+#define S3C_UDC_OTG_EP6_FIFO S3C_USBOTGREG(0x7000)
+#define S3C_UDC_OTG_EP7_FIFO S3C_USBOTGREG(0x8000)
+#define S3C_UDC_OTG_EP8_FIFO S3C_USBOTGREG(0x9000)
+#define S3C_UDC_OTG_EP9_FIFO S3C_USBOTGREG(0xA000)
+#define S3C_UDC_OTG_EP10_FIFO S3C_USBOTGREG(0xB000)
+#define S3C_UDC_OTG_EP11_FIFO S3C_USBOTGREG(0xC000)
+#define S3C_UDC_OTG_EP12_FIFO S3C_USBOTGREG(0xD000)
+#define S3C_UDC_OTG_EP13_FIFO S3C_USBOTGREG(0xE000)
+#define S3C_UDC_OTG_EP14_FIFO S3C_USBOTGREG(0xF000)
+#define S3C_UDC_OTG_EP15_FIFO S3C_USBOTGREG(0x10000)
+
+/*===================================================================== */
+/*definitions related to CSR setting */
+
+/* S3C_UDC_OTG_GOTGCTL */
+#define B_SESSION_VALID (0x1<<19)
+#define A_SESSION_VALID (0x1<<18)
+#define SESSION_REQ (0x1<<1)
+/* S3C_UDC_OTG_GAHBCFG */
+#define PTXFE_HALF (0<<8)
+#define PTXFE_ZERO (1<<8)
+#define NPTXFE_HALF (0<<7)
+#define NPTXFE_ZERO (1<<7)
+#define MODE_SLAVE (0<<5)
+#define MODE_DMA (1<<5)
+#define BURST_SINGLE (0<<1)
+#define BURST_INCR (1<<1)
+#define BURST_INCR4 (3<<1)
+#define BURST_INCR8 (5<<1)
+#define BURST_INCR16 (7<<1)
+#define GBL_INT_UNMASK (1<<0)
+#define GBL_INT_MASK (0<<0)
+
+/* S3C_UDC_OTG_GRSTCTL */
+#define AHB_MASTER_IDLE (1u<<31)
+#define HCLK_SOFT_RESET (0x1<<1)
+#define CORE_SOFT_RESET (0x1<<0)
+
+/* S3C_UDC_OTG_GINTSTS/S3C_UDC_OTG_GINTMSK core interrupt register */
+#define INT_RESUME (1u<<31)
+#define INT_DISCONN (0x1<<29)
+#define INT_CONN_ID_STS_CNG (0x1<<28)
+#define INT_OUT_EP (0x1<<19)
+#define INT_IN_EP (0x1<<18)
+#define INT_ENUMDONE (0x1<<13)
+#define INT_RESET (0x1<<12)
+#define INT_SUSPEND (0x1<<11)
+#define INT_EARLY_SUSPEND (0x1<<10)
+#define INT_NP_TX_FIFO_EMPTY (0x1<<5)
+#define INT_RX_FIFO_NOT_EMPTY (0x1<<4)
+#define INT_SOF (0x1<<3)
+#define INT_DEV_MODE (0x0<<0)
+#define INT_HOST_MODE (0x1<<1)
+#define INT_GOUTNakEff (0x01<<7)
+#define INT_GINNakEff (0x01<<6)
+
+#define FULL_SPEED_CONTROL_PKT_SIZE 8
+#define FULL_SPEED_BULK_PKT_SIZE 64
+
+#define HIGH_SPEED_CONTROL_PKT_SIZE 64
+#define HIGH_SPEED_BULK_PKT_SIZE 512
+
+#define RX_FIFO_SIZE (4096>>2)
+#define NPTX_FIFO_START_ADDR RX_FIFO_SIZE
+#define NPTX_FIFO_SIZE (4096>>2)
+#define PTX_FIFO_SIZE (1024>>1)
+
+/* Enumeration speed */
+#define USB_HIGH_30_60MHZ (0x0<<1)
+#define USB_FULL_30_60MHZ (0x1<<1)
+#define USB_LOW_6MHZ (0x2<<1)
+#define USB_FULL_48MHZ (0x3<<1)
+
+/* S3C_UDC_OTG_GRXSTSP STATUS */
+#define OUT_PKT_RECEIVED (0x2<<17)
+#define OUT_TRANSFER_COMPLELTED (0x3<<17)
+#define SETUP_TRANSACTION_COMPLETED (0x4<<17)
+#define SETUP_PKT_RECEIVED (0x6<<17)
+#define GLOBAL_OUT_NAK (0x1<<17)
+
+/* S3C_UDC_OTG_DCTL device control register */
+#define NORMAL_OPERATION (0x1<<0)
+#define SOFT_DISCONNECT (0x1<<1)
+#define TEST_CONTROL_MASK (0x7<<4)
+#define TEST_J_MODE (0x1<<4)
+#define TEST_K_MODE (0x2<<4)
+#define TEST_SE0_NAK_MODE (0x3<<4)
+#define TEST_PACKET_MODE (0x4<<4)
+#define TEST_FORCE_ENABLE_MODE (0x5<<4)
+#define REMOTE_WAKEUP (0x1<<0)
+
+/* S3C_UDC_OTG_DSTS device status register */
+#define SOFFN_MASK (0x3fff << 8)
+#define SOFFN_SHIFT (8)
+#define USB_SUSPEND (0x1<<0)
+
+/* S3C_UDC_OTG_DAINT device all endpoint interrupt register */
+#define DAINT_OUT_BIT (16)
+#define DAINT_MASK (0xFFFF)
+
+/* S3C_UDC_OTG_DIEPCTL0/DOEPCTL0 device control IN/OUT endpoint 0 control register */
+#define DEPCTL_EPENA (0x1<<31)
+#define DEPCTL_EPDIS (0x1<<30)
+#define DEPCTL_SETD1PID (0x1<<29)
+#define DEPCTL_SET_ODD_FRM (0x1<<29)
+#define DEPCTL_SETD0PID (0x1<<28)
+#define DEPCTL_SET_EVEN_FRM (0x1<<28)
+#define DEPCTL_SNAK (0x1<<27)
+#define DEPCTL_CNAK (0x1<<26)
+#define DEPCTL_STALL (0x1<<21)
+#define DEPCTL_TYPE_BIT (18)
+#define DEPCTL_TXFNUM_BIT (22)
+#define DEPCTL_TXFNUM_MASK (0xF<<22)
+#define DEPCTL_TYPE_MASK (0x3<<18)
+#define DEPCTL_CTRL_TYPE (0x0<<18)
+#define DEPCTL_ISO_TYPE (0x1<<18)
+#define DEPCTL_BULK_TYPE (0x2<<18)
+#define DEPCTL_INTR_TYPE (0x3<<18)
+#define DEPCTL_USBACTEP (0x1<<15)
+#define DEPCTL_NEXT_EP_BIT (11)
+#define DEPCTL_MPS_BIT (0)
+#define DEPCTL_MPS_MASK (0x7FF)
+
+#define DEPCTL0_MPS_64 (0x0<<0)
+#define DEPCTL0_MPS_32 (0x1<<0)
+#define DEPCTL0_MPS_16 (0x2<<0)
+#define DEPCTL0_MPS_8 (0x3<<0)
+#define DEPCTL_MPS_BULK_512 (512<<0)
+#define DEPCTL_MPS_INT_MPS_16 (16<<0)
+
+#define DIEPCTL0_NEXT_EP_BIT (11)
+
+/* S3C_UDC_OTG_DIEPCTLn/DOEPCTLn device control IN/OUT endpoint n control register */
+
+/* S3C_UDC_OTG_DIEPMSK/DOEPMSK device IN/OUT endpoint common interrupt mask register */
+/* S3C_UDC_OTG_DIEPINTn/DOEPINTn device IN/OUT endpoint interrupt register */
+#define BACK2BACK_SETUP_RECEIVED (0x1<<6)
+#define INTKNEPMIS (0x1<<5)
+#define INTKN_TXFEMP (0x1<<4)
+#define NON_ISO_IN_EP_TIMEOUT (0x1<<3)
+#define CTRL_OUT_EP_SETUP_PHASE_DONE (0x1<<3)
+#define AHB_ERROR (0x1<<2)
+#define EPDISBLD (0x1<<1)
+#define TRANSFER_DONE (0x1<<0)
+
+/*DIEPTSIZ0 / DOEPTSIZ0 */
+
+/* DEPTSIZ common bit */
+#define DEPTSIZ_PKT_CNT_BIT (19)
+#define DEPTSIZ_XFER_SIZE_BIT (0)
+
+#define DEPTSIZ_SETUP_PKCNT_1 (1<<29)
+#define DEPTSIZ_SETUP_PKCNT_2 (2<<29)
+#define DEPTSIZ_SETUP_PKCNT_3 (3<<29)
+
+#endif
diff --git a/arch/arm/plat-samsung/include/plat/regs-rtc.h b/arch/arm/plat-samsung/include/plat/regs-rtc.h
index 30b7cc1..b8daf4b 100644
--- a/arch/arm/plat-samsung/include/plat/regs-rtc.h
+++ b/arch/arm/plat-samsung/include/plat/regs-rtc.h
@@ -28,6 +28,22 @@
#define S3C64XX_RTCCON_TICMSK (0xF<<7)
#define S3C64XX_RTCCON_TICSHT (7)
+#if defined(CONFIG_CPU_S5PC100) || defined(CONFIG_CPU_S5PV210)
+#define S3C_MAX_CNT 32768
+#define S3C_RTCCON_TICEN (1<<8)
+#define S3C_RTC_TICNT S3C2410_RTCREG(0x40)
+#else
+#define S3C_INTP_ALM (1<<1)
+#define S3C_MAX_CNT 128
+#define S3C_RTCCON_TICEN (1<<7)
+#define S3C_RTC_TICNT S3C2410_RTCREG(0x44)
+#endif
+
+/* Common Reg for samsung AP*/
+#define S3C_INTP S3C2410_RTCREG(0x30)
+#define S3C_INTP_ALM (1<<1)
+#define S3C_INTP_TIC (1<<0)
+
#define S3C2410_TICNT S3C2410_RTCREG(0x44)
#define S3C2410_TICNT_ENABLE (1<<7)
@@ -63,6 +79,6 @@
#define S3C2410_RTCDAY S3C2410_RTCREG(0x80)
#define S3C2410_RTCMON S3C2410_RTCREG(0x84)
#define S3C2410_RTCYEAR S3C2410_RTCREG(0x88)
-
+#define S3C2410_CURTICCNT S3C2410_RTCREG(0x90)
#endif /* __ASM_ARCH_REGS_RTC_H */
diff --git a/arch/arm/plat-samsung/include/plat/regs-sdhci.h b/arch/arm/plat-samsung/include/plat/regs-sdhci.h
index e34049a..a9d956d 100644
--- a/arch/arm/plat-samsung/include/plat/regs-sdhci.h
+++ b/arch/arm/plat-samsung/include/plat/regs-sdhci.h
@@ -83,5 +83,5 @@
#define S3C64XX_SDHCI_CONTROL4_DRIVE_9mA (0x3 << 16)
#define S3C64XX_SDHCI_CONTROL4_BUSY (1)
-
+#define SDHCI_S3C_CTRL_8BITBUS (1 << 5)
#endif /* __PLAT_S3C_SDHCI_REGS_H */
diff --git a/arch/arm/plat-samsung/include/plat/regs-serial.h b/arch/arm/plat-samsung/include/plat/regs-serial.h
index 116edfe..48a91dd 100644
--- a/arch/arm/plat-samsung/include/plat/regs-serial.h
+++ b/arch/arm/plat-samsung/include/plat/regs-serial.h
@@ -53,6 +53,8 @@
#define S3C2410_UERSTAT (0x14)
#define S3C2410_UFSTAT (0x18)
#define S3C2410_UMSTAT (0x1C)
+#define S3C2410_UDIVSLOT (0x2C)
+#define S3C2410_UINTMSK (0x38)
#define S3C2410_LCON_CFGMASK ((0xF<<3)|(0x3))
@@ -194,6 +196,11 @@
#define S3C64XX_UINTSP 0x34
#define S3C64XX_UINTM 0x38
+/* S5V210 interrupt registers. */
+#define S5P_UINTP 0x30
+#define S5P_UINTSP 0x34
+#define S5P_UINTM 0x38
+
/* Following are specific to S5PV210 */
#define S5PV210_UCON_CLKMASK (1<<10)
#define S5PV210_UCON_PCLK (0<<10)
@@ -259,7 +266,11 @@ struct s3c2410_uartcfg {
unsigned char hwport; /* hardware port number */
unsigned char unused;
unsigned short flags;
+#if !defined(CONFIG_CPU_S5PV210)
upf_t uart_flags; /* default uart flags */
+#else
+ unsigned long uart_flags; /* default uart flags */
+#endif
unsigned int has_fracval;
@@ -269,6 +280,8 @@ struct s3c2410_uartcfg {
struct s3c24xx_uart_clksrc *clocks;
unsigned int clocks_size;
+
+ void (*wake_peer)(struct uart_port *);
};
/* s3c24xx_uart_devs
diff --git a/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h b/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h
index 8107442..333e381 100644
--- a/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h
+++ b/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h
@@ -84,6 +84,14 @@ enum dma_ch {
DMACH_SLIMBUS4_TX,
DMACH_SLIMBUS5_RX,
DMACH_SLIMBUS5_TX,
+ DMACH_MTOM_0,
+ DMACH_MTOM_1,
+ DMACH_MTOM_2,
+ DMACH_MTOM_3,
+ DMACH_MTOM_4,
+ DMACH_MTOM_5,
+ DMACH_MTOM_6,
+ DMACH_MTOM_7,
/* END Marker, also used to denote a reserved channel */
DMACH_MAX,
};
diff --git a/arch/arm/plat-samsung/include/plat/sdhci.h b/arch/arm/plat-samsung/include/plat/sdhci.h
index 058e096..0c386fc 100644
--- a/arch/arm/plat-samsung/include/plat/sdhci.h
+++ b/arch/arm/plat-samsung/include/plat/sdhci.h
@@ -84,6 +84,15 @@ struct s3c_sdhci_platdata {
void __iomem *regbase,
struct mmc_ios *ios,
struct mmc_card *card);
+ void (*adjust_cfg_card)(struct s3c_sdhci_platdata *pdata, void __iomem *regbase, int rw);
+ int rx_cfg;
+ int tx_cfg;
+
+ /* add to deal with non-removable device */
+ int built_in;
+
+ int must_maintain_clock;
+ int enable_intr_on_resume;
};
/**
@@ -94,6 +103,7 @@ struct s3c_sdhci_platdata {
* The call will copy the platform data, so the board definitions can
* make the structure itself __initdata.
*/
+extern void s3c_sdhci_set_platdata(void);
extern void s3c_sdhci0_set_platdata(struct s3c_sdhci_platdata *pd);
extern void s3c_sdhci1_set_platdata(struct s3c_sdhci_platdata *pd);
extern void s3c_sdhci2_set_platdata(struct s3c_sdhci_platdata *pd);
@@ -289,9 +299,10 @@ static inline void s5pc100_default_sdhci2(void) { }
extern char *s5pv210_hsmmc_clksrcs[4];
extern void s5pv210_setup_sdhci_cfg_card(struct platform_device *dev,
- void __iomem *r,
- struct mmc_ios *ios,
- struct mmc_card *card);
+ void __iomem *r,
+ struct mmc_ios *ios,
+ struct mmc_card *card);
+extern void s5pv210_adjust_sdhci_cfg_card(struct s3c_sdhci_platdata *pdata, void __iomem *r, int rw);
static inline void s5pv210_default_sdhci0(void)
{
@@ -299,6 +310,7 @@ static inline void s5pv210_default_sdhci0(void)
s3c_hsmmc0_def_platdata.clocks = s5pv210_hsmmc_clksrcs;
s3c_hsmmc0_def_platdata.cfg_gpio = s5pv210_setup_sdhci0_cfg_gpio;
s3c_hsmmc0_def_platdata.cfg_card = s5pv210_setup_sdhci_cfg_card;
+ s3c_hsmmc0_def_platdata.adjust_cfg_card = s5pv210_adjust_sdhci_cfg_card;
#endif
}
@@ -308,6 +320,7 @@ static inline void s5pv210_default_sdhci1(void)
s3c_hsmmc1_def_platdata.clocks = s5pv210_hsmmc_clksrcs;
s3c_hsmmc1_def_platdata.cfg_gpio = s5pv210_setup_sdhci1_cfg_gpio;
s3c_hsmmc1_def_platdata.cfg_card = s5pv210_setup_sdhci_cfg_card;
+ s3c_hsmmc1_def_platdata.adjust_cfg_card = s5pv210_adjust_sdhci_cfg_card;
#endif
}
@@ -317,6 +330,7 @@ static inline void s5pv210_default_sdhci2(void)
s3c_hsmmc2_def_platdata.clocks = s5pv210_hsmmc_clksrcs;
s3c_hsmmc2_def_platdata.cfg_gpio = s5pv210_setup_sdhci2_cfg_gpio;
s3c_hsmmc2_def_platdata.cfg_card = s5pv210_setup_sdhci_cfg_card;
+ s3c_hsmmc2_def_platdata.adjust_cfg_card = s5pv210_adjust_sdhci_cfg_card;
#endif
}
@@ -326,6 +340,7 @@ static inline void s5pv210_default_sdhci3(void)
s3c_hsmmc3_def_platdata.clocks = s5pv210_hsmmc_clksrcs;
s3c_hsmmc3_def_platdata.cfg_gpio = s5pv210_setup_sdhci3_cfg_gpio;
s3c_hsmmc3_def_platdata.cfg_card = s5pv210_setup_sdhci_cfg_card;
+ s3c_hsmmc3_def_platdata.adjust_cfg_card = s5pv210_adjust_sdhci_cfg_card;
#endif
}
@@ -390,4 +405,6 @@ static inline void exynos4_default_sdhci3(void) { }
#endif /* CONFIG_EXYNOS4_SETUP_SDHCI */
+extern void sdhci_s3c_force_presence_change(struct platform_device *pdev);
+
#endif /* __PLAT_S3C_SDHCI_H */
diff --git a/arch/arm/plat-samsung/include/plat/watchdog-reset.h b/arch/arm/plat-samsung/include/plat/watchdog-reset.h
index 54b762a..632e1ed 100644
--- a/arch/arm/plat-samsung/include/plat/watchdog-reset.h
+++ b/arch/arm/plat-samsung/include/plat/watchdog-reset.h
@@ -13,24 +13,18 @@
#include <plat/regs-watchdog.h>
#include <mach/map.h>
+#include <linux/kernel.h>
#include <linux/clk.h>
+#include <linux/delay.h>
#include <linux/err.h>
#include <linux/io.h>
static inline void arch_wdt_reset(void)
{
- struct clk *wdtclk;
-
printk("arch_reset: attempting watchdog reset\n");
__raw_writel(0, S3C2410_WTCON); /* disable watchdog, to be safe */
- wdtclk = clk_get(NULL, "watchdog");
- if (!IS_ERR(wdtclk)) {
- clk_enable(wdtclk);
- } else
- printk(KERN_WARNING "%s: warning: cannot get watchdog clock\n", __func__);
-
/* put initial values into count and data */
__raw_writel(0x80, S3C2410_WTCNT);
__raw_writel(0x80, S3C2410_WTDAT);
diff --git a/arch/arm/plat-samsung/pm-gpio.c b/arch/arm/plat-samsung/pm-gpio.c
index 9652820..f7dccb0 100644..100755
--- a/arch/arm/plat-samsung/pm-gpio.c
+++ b/arch/arm/plat-samsung/pm-gpio.c
@@ -27,6 +27,9 @@
#define OFFS_CON (0x00)
#define OFFS_DAT (0x04)
#define OFFS_UP (0x08)
+#define OFFS_DRV (0x0C)
+#define OFFS_CONPDN (0x10)
+#define OFFS_PUDPDN (0x14)
static void s3c_gpio_pm_1bit_save(struct s3c_gpio_chip *chip)
{
@@ -198,6 +201,9 @@ static void s3c_gpio_pm_4bit_save(struct s3c_gpio_chip *chip)
chip->pm_save[1] = __raw_readl(chip->base + OFFS_CON);
chip->pm_save[2] = __raw_readl(chip->base + OFFS_DAT);
chip->pm_save[3] = __raw_readl(chip->base + OFFS_UP);
+ chip->pm_save[4] = __raw_readl(chip->base + OFFS_DRV);
+ chip->pm_save[5] = __raw_readl(chip->base + OFFS_CONPDN);
+ chip->pm_save[6] = __raw_readl(chip->base + OFFS_PUDPDN);
if (chip->chip.ngpio > 8)
chip->pm_save[0] = __raw_readl(chip->base - 4);
@@ -284,6 +290,9 @@ static void s3c_gpio_pm_4bit_resume(struct s3c_gpio_chip *chip)
__raw_writel(chip->pm_save[2], base + OFFS_DAT);
__raw_writel(chip->pm_save[3], base + OFFS_UP);
+ __raw_writel(chip->pm_save[4], base + OFFS_DRV);
+ __raw_writel(chip->pm_save[5], base + OFFS_CONPDN);
+ __raw_writel(chip->pm_save[6], base + OFFS_PUDPDN);
if (chip->chip.ngpio > 8) {
S3C_PMDBG("%s: CON4 %08x,%08x => %08x,%08x, DAT %08x => %08x\n",
diff --git a/arch/arm/plat-samsung/pm.c b/arch/arm/plat-samsung/pm.c
index 5c0a440..b351133 100644
--- a/arch/arm/plat-samsung/pm.c
+++ b/arch/arm/plat-samsung/pm.c
@@ -26,15 +26,87 @@
#include <plat/regs-serial.h>
#include <mach/regs-clock.h>
#include <mach/regs-irq.h>
+#include <asm/fiq_glue.h>
#include <asm/irq.h>
#include <plat/pm.h>
+#include <plat/irq-eint-group.h>
#include <mach/pm-core.h>
/* for external use */
unsigned long s3c_pm_flags;
+/* ---------------------------------------------- */
+extern unsigned int pm_debug_scratchpad;
+#include <linux/slab.h>
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+#include <linux/module.h>
+
+#define PMSTATS_MAGIC "*PM*DEBUG*STATS*"
+
+struct pmstats {
+ char magic[16];
+ unsigned sleep_count;
+ unsigned wake_count;
+ unsigned sleep_freq;
+ unsigned wake_freq;
+};
+
+static struct pmstats *pmstats;
+static struct pmstats *pmstats_last;
+
+static ssize_t pmstats_read(struct file *file, char __user *buf,
+ size_t len, loff_t *offset)
+{
+ if (*offset != 0)
+ return 0;
+ if (len > 4096)
+ len = 4096;
+
+ if (copy_to_user(buf, file->private_data, len))
+ return -EFAULT;
+
+ *offset += len;
+ return len;
+}
+
+static int pmstats_open(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+static const struct file_operations pmstats_ops = {
+ .owner = THIS_MODULE,
+ .read = pmstats_read,
+ .open = pmstats_open,
+};
+
+void __init pmstats_init(void)
+{
+ pr_info("pmstats at %08x\n", pm_debug_scratchpad);
+ if (pm_debug_scratchpad)
+ pmstats = ioremap(pm_debug_scratchpad, 4096);
+ else
+ pmstats = kzalloc(4096, GFP_ATOMIC);
+
+ if (!memcmp(pmstats->magic, PMSTATS_MAGIC, 16)) {
+ pmstats_last = kzalloc(4096, GFP_ATOMIC);
+ if (pmstats_last)
+ memcpy(pmstats_last, pmstats, 4096);
+ }
+
+ memset(pmstats, 0, 4096);
+ memcpy(pmstats->magic, PMSTATS_MAGIC, 16);
+
+ debugfs_create_file("pmstats", 0444, NULL, pmstats, &pmstats_ops);
+ if (pmstats_last)
+ debugfs_create_file("pmstats_last", 0444, NULL, pmstats_last, &pmstats_ops);
+}
+/* ---------------------------------------------- */
+
/* Debug code:
*
* This code supports debug output to the low level UARTs for use on
@@ -185,12 +257,8 @@ void s3c_pm_do_save(struct sleep_save *ptr, int count)
void s3c_pm_do_restore(struct sleep_save *ptr, int count)
{
- for (; count > 0; count--, ptr++) {
- printk(KERN_DEBUG "restore %p (restore %08lx, was %08x)\n",
- ptr->reg, ptr->val, __raw_readl(ptr->reg));
-
+ for (; count > 0; count--, ptr++)
__raw_writel(ptr->val, ptr->reg);
- }
}
/**
@@ -232,6 +300,7 @@ static void __maybe_unused s3c_pm_show_resume_irqs(int start,
void (*pm_cpu_prep)(void);
void (*pm_cpu_sleep)(void);
+void (*pm_cpu_restore)(void);
#define any_allowed(mask, allow) (((mask) & (allow)) != (allow))
@@ -271,6 +340,7 @@ static int s3c_pm_enter(suspend_state_t state)
s3c_pm_save_uarts();
s3c_pm_save_core();
+
/* set the irq configuration for wake */
s3c_pm_configure_extint();
@@ -290,6 +360,9 @@ static int s3c_pm_enter(suspend_state_t state)
s3c_pm_check_store();
+ /* clear wakeup_stat register for next wakeup reason */
+ __raw_writel(__raw_readl(S5P_WAKEUP_STAT), S5P_WAKEUP_STAT);
+
/* send the cpu to sleep... */
s3c_pm_arch_stop_clocks();
@@ -298,20 +371,31 @@ static int s3c_pm_enter(suspend_state_t state)
* we resume as it saves its own register state and restores it
* during the resume. */
+ pmstats->sleep_count++;
+ pmstats->sleep_freq = __raw_readl(S5P_CLK_DIV0);
s3c_cpu_save(0, PLAT_PHYS_OFFSET - PAGE_OFFSET);
+ pmstats->wake_count++;
+ pmstats->wake_freq = __raw_readl(S5P_CLK_DIV0);
/* restore the cpu state using the kernel's cpu init code. */
cpu_init();
- /* restore the system state */
+ fiq_glue_resume();
+ local_fiq_enable();
s3c_pm_restore_core();
s3c_pm_restore_uarts();
s3c_pm_restore_gpios();
+ s5pv210_restore_eint_group();
s3c_pm_debug_init();
+ /* restore the system state */
+
+ if (pm_cpu_restore)
+ pm_cpu_restore();
+
/* check what irq (if any) restored the system */
s3c_pm_arch_show_resume_irqs();
@@ -359,6 +443,7 @@ static const struct platform_suspend_ops s3c_pm_ops = {
int __init s3c_pm_init(void)
{
printk("S3C Power Management, Copyright 2004 Simtec Electronics\n");
+ pmstats_init();
suspend_set_ops(&s3c_pm_ops);
return 0;
diff --git a/arch/arm/plat-samsung/pwm.c b/arch/arm/plat-samsung/pwm.c
index f37457c..84723bd 100644
--- a/arch/arm/plat-samsung/pwm.c
+++ b/arch/arm/plat-samsung/pwm.c
@@ -44,6 +44,7 @@ struct pwm_device {
#define pwm_dbg(_pwm, msg...) dev_dbg(&(_pwm)->pdev->dev, msg)
static struct clk *clk_scaler[2];
+static DEFINE_SPINLOCK(pwm_spin_lock);
static inline int pwm_is_tdiv(struct pwm_device *pwm)
{
@@ -108,15 +109,21 @@ int pwm_enable(struct pwm_device *pwm)
unsigned long flags;
unsigned long tcon;
- local_irq_save(flags);
+ spin_lock_irqsave(&pwm_spin_lock, flags);
- tcon = __raw_readl(S3C2410_TCON);
- tcon |= pwm_tcon_start(pwm);
- __raw_writel(tcon, S3C2410_TCON);
+ if (!pwm->running) {
+ clk_enable(pwm->clk);
+ clk_enable(pwm->clk_div);
- local_irq_restore(flags);
+ tcon = __raw_readl(S3C2410_TCON);
+ tcon |= pwm_tcon_start(pwm);
+ __raw_writel(tcon, S3C2410_TCON);
+
+ pwm->running = 1;
+ }
+
+ spin_unlock_irqrestore(&pwm_spin_lock, flags);
- pwm->running = 1;
return 0;
}
@@ -127,15 +134,20 @@ void pwm_disable(struct pwm_device *pwm)
unsigned long flags;
unsigned long tcon;
- local_irq_save(flags);
+ spin_lock_irqsave(&pwm_spin_lock, flags);
- tcon = __raw_readl(S3C2410_TCON);
- tcon &= ~pwm_tcon_start(pwm);
- __raw_writel(tcon, S3C2410_TCON);
+ if (pwm->running) {
+ tcon = __raw_readl(S3C2410_TCON);
+ tcon &= ~pwm_tcon_start(pwm);
+ __raw_writel(tcon, S3C2410_TCON);
- local_irq_restore(flags);
+ clk_disable(pwm->clk);
+ clk_disable(pwm->clk_div);
- pwm->running = 0;
+ pwm->running = 0;
+ }
+
+ spin_unlock_irqrestore(&pwm_spin_lock, flags);
}
EXPORT_SYMBOL(pwm_disable);
@@ -185,6 +197,9 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
/* The TCMP and TCNT can be read without a lock, they're not
* shared between the timers. */
+ clk_enable(pwm->clk);
+ clk_enable(pwm->clk_div);
+
tcmp = __raw_readl(S3C2410_TCMPB(pwm->pwm_id));
tcnt = __raw_readl(S3C2410_TCNTB(pwm->pwm_id));
@@ -227,7 +242,7 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
/* Update the PWM register block. */
- local_irq_save(flags);
+ spin_lock_irqsave(&pwm_spin_lock, flags);
__raw_writel(tcmp, S3C2410_TCMPB(pwm->pwm_id));
__raw_writel(tcnt, S3C2410_TCNTB(pwm->pwm_id));
@@ -240,9 +255,13 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
tcon &= ~pwm_tcon_manulupdate(pwm);
__raw_writel(tcon, S3C2410_TCON);
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&pwm_spin_lock, flags);
+
+ clk_disable(pwm->clk);
+ clk_disable(pwm->clk_div);
return 0;
+
}
EXPORT_SYMBOL(pwm_config);
@@ -299,14 +318,13 @@ static int s3c_pwm_probe(struct platform_device *pdev)
goto err_clk_tin;
}
- local_irq_save(flags);
+ spin_lock_irqsave(&pwm_spin_lock, flags);
tcon = __raw_readl(S3C2410_TCON);
tcon |= pwm_tcon_invert(pwm);
__raw_writel(tcon, S3C2410_TCON);
- local_irq_restore(flags);
-
+ spin_unlock_irqrestore(&pwm_spin_lock, flags);
ret = pwm_register(pwm);
if (ret) {
diff --git a/arch/arm/plat-samsung/s3c-pl330.c b/arch/arm/plat-samsung/s3c-pl330.c
index f85638c..3b88d8f 100644
--- a/arch/arm/plat-samsung/s3c-pl330.c
+++ b/arch/arm/plat-samsung/s3c-pl330.c
@@ -747,8 +747,11 @@ int s3c2410_dma_request(enum dma_ch id,
dmac = ch->dmac;
+ clk_enable(dmac->clk);
+
ch->pl330_chan_id = pl330_request_channel(dmac->pi);
if (!ch->pl330_chan_id) {
+ clk_disable(dmac->clk);
chan_release(ch);
ret = -EBUSY;
goto req_exit;
@@ -860,7 +863,7 @@ int s3c2410_dma_free(enum dma_ch id, struct s3c2410_dma_client *client)
pl330_release_channel(ch->pl330_chan_id);
ch->pl330_chan_id = NULL;
-
+ clk_disable(ch->dmac->clk);
chan_release(ch);
free_exit:
@@ -986,6 +989,18 @@ int s3c2410_dma_devconfig(enum dma_ch id, enum s3c2410_dmasrc source,
ch->rqcfg.src_inc = 1;
ch->rqcfg.dst_inc = 0;
break;
+ case S3C_DMA_MEM2MEM:
+ ch->req[0].rqtype = MEMTOMEM;
+ ch->req[1].rqtype = MEMTOMEM;
+ ch->rqcfg.src_inc = 1;
+ ch->rqcfg.dst_inc = 1;
+ break;
+ case S3C_DMA_MEM2MEM_SET:
+ ch->req[0].rqtype = MEMTOMEM;
+ ch->req[1].rqtype = MEMTOMEM;
+ ch->rqcfg.src_inc = 0;
+ ch->rqcfg.dst_inc = 1;
+ break;
default:
ret = -EINVAL;
goto devcfg_exit;
@@ -1131,6 +1146,7 @@ static int pl330_probe(struct platform_device *pdev)
pl330_info->pcfg.data_bus_width / 8, pl330_info->pcfg.num_chan,
pl330_info->pcfg.num_peri, pl330_info->pcfg.num_events);
+ clk_disable(s3c_pl330_dmac->clk);
return 0;
probe_err8:
@@ -1156,7 +1172,7 @@ probe_err1:
static int pl330_remove(struct platform_device *pdev)
{
struct s3c_pl330_dmac *dmac, *d;
- struct s3c_pl330_chan *ch;
+ struct s3c_pl330_chan *ch, *cht;
unsigned long flags;
int del, found;
@@ -1180,7 +1196,7 @@ static int pl330_remove(struct platform_device *pdev)
dmac = d;
/* Remove all Channels that are managed only by this DMAC */
- list_for_each_entry(ch, &chan_list, node) {
+ list_for_each_entry_safe(ch, cht, &chan_list, node) {
/* Only channels that are handled by this DMAC */
if (iface_of_dmac(dmac, ch->id))
@@ -1205,7 +1221,6 @@ static int pl330_remove(struct platform_device *pdev)
}
/* Disable operation clock */
- clk_disable(dmac->clk);
clk_put(dmac->clk);
/* Remove the DMAC */
diff --git a/arch/arm/plat-samsung/time.c b/arch/arm/plat-samsung/time.c
index 2231d80..a16a57b 100644
--- a/arch/arm/plat-samsung/time.c
+++ b/arch/arm/plat-samsung/time.c
@@ -132,7 +132,9 @@ static unsigned long s3c2410_gettimeoffset (void)
static irqreturn_t
s3c2410_timer_interrupt(int irq, void *dev_id)
{
+#ifndef CONFIG_GENERIC_CLOCKEVENTS
timer_tick();
+#endif
return IRQ_HANDLED;
}
diff --git a/arch/ia64/include/asm/atomic.h b/arch/ia64/include/asm/atomic.h
index 4468814..6fcc9a0 100644
--- a/arch/ia64/include/asm/atomic.h
+++ b/arch/ia64/include/asm/atomic.h
@@ -18,8 +18,8 @@
#include <asm/system.h>
-#define ATOMIC_INIT(i) ((atomic_t) { (i) })
-#define ATOMIC64_INIT(i) ((atomic64_t) { (i) })
+#define ATOMIC_INIT(i) { (i) }
+#define ATOMIC64_INIT(i) { (i) }
#define atomic_read(v) (*(volatile int *)&(v)->counter)
#define atomic64_read(v) (*(volatile long *)&(v)->counter)
diff --git a/arch/ia64/include/asm/unistd.h b/arch/ia64/include/asm/unistd.h
index 7c928da..d8de182 100644
--- a/arch/ia64/include/asm/unistd.h
+++ b/arch/ia64/include/asm/unistd.h
@@ -321,11 +321,12 @@
#define __NR_syncfs 1329
#define __NR_setns 1330
#define __NR_sendmmsg 1331
+#define __NR_accept4 1334
#ifdef __KERNEL__
-#define NR_syscalls 308 /* length of syscall table */
+#define NR_syscalls 311 /* length of syscall table */
/*
* The following defines stop scripts/checksyscalls.sh from complaining about
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index 97dd2ab..df477f8 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -1777,6 +1777,9 @@ sys_call_table:
data8 sys_syncfs
data8 sys_setns // 1330
data8 sys_sendmmsg
+ data8 sys_ni_syscall /* process_vm_readv */
+ data8 sys_ni_syscall /* process_vm_writev */
+ data8 sys_accept4
.org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls
#endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */
diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c
index 782c3a35..3540c5e 100644
--- a/arch/ia64/kernel/irq_ia64.c
+++ b/arch/ia64/kernel/irq_ia64.c
@@ -23,7 +23,6 @@
#include <linux/ioport.h>
#include <linux/kernel_stat.h>
#include <linux/ptrace.h>
-#include <linux/random.h> /* for rand_initialize_irq() */
#include <linux/signal.h>
#include <linux/smp.h>
#include <linux/threads.h>
diff --git a/arch/m68k/include/asm/entry_mm.h b/arch/m68k/include/asm/entry_mm.h
index 73b8c8f..bdace4b 100644
--- a/arch/m68k/include/asm/entry_mm.h
+++ b/arch/m68k/include/asm/entry_mm.h
@@ -35,8 +35,8 @@
/* the following macro is used when enabling interrupts */
#if defined(MACH_ATARI_ONLY)
- /* block out HSYNC on the atari */
-#define ALLOWINT (~0x400)
+ /* block out HSYNC = ipl 2 on the atari */
+#define ALLOWINT (~0x500)
#define MAX_NOINT_IPL 3
#else
/* portable version */
diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
index 8623f8d..9a5932e 100644
--- a/arch/m68k/kernel/sys_m68k.c
+++ b/arch/m68k/kernel/sys_m68k.c
@@ -479,9 +479,13 @@ sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5,
goto bad_access;
}
- mem_value = *mem;
+ /*
+ * No need to check for EFAULT; we know that the page is
+ * present and writable.
+ */
+ __get_user(mem_value, mem);
if (mem_value == oldval)
- *mem = newval;
+ __put_user(newval, mem);
pte_unmap_unlock(pte, ptl);
up_read(&mm->mmap_sem);
diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h
index 97f8bf6..adda036 100644
--- a/arch/mips/include/asm/thread_info.h
+++ b/arch/mips/include/asm/thread_info.h
@@ -60,6 +60,8 @@ struct thread_info {
register struct thread_info *__current_thread_info __asm__("$28");
#define current_thread_info() __current_thread_info
+#endif /* !__ASSEMBLY__ */
+
/* thread information allocation */
#if defined(CONFIG_PAGE_SIZE_4KB) && defined(CONFIG_32BIT)
#define THREAD_SIZE_ORDER (1)
@@ -97,8 +99,6 @@ register struct thread_info *__current_thread_info __asm__("$28");
#define free_thread_info(info) kfree(info)
-#endif /* !__ASSEMBLY__ */
-
#define PREEMPT_ACTIVE 0x10000000
/*
diff --git a/arch/mips/kernel/kgdb.c b/arch/mips/kernel/kgdb.c
index f4546e9..23817a6 100644
--- a/arch/mips/kernel/kgdb.c
+++ b/arch/mips/kernel/kgdb.c
@@ -283,6 +283,15 @@ static int kgdb_mips_notify(struct notifier_block *self, unsigned long cmd,
struct pt_regs *regs = args->regs;
int trap = (regs->cp0_cause & 0x7c) >> 2;
+#ifdef CONFIG_KPROBES
+ /*
+ * Return immediately if the kprobes fault notifier has set
+ * DIE_PAGE_FAULT.
+ */
+ if (cmd == DIE_PAGE_FAULT)
+ return NOTIFY_DONE;
+#endif /* CONFIG_KPROBES */
+
/* Userspace events, ignore. */
if (user_mode(regs))
return NOTIFY_DONE;
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index a81176f..be281c6 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -1,5 +1,6 @@
#include <asm/asm-offsets.h>
#include <asm/page.h>
+#include <asm/thread_info.h>
#include <asm-generic/vmlinux.lds.h>
#undef mips
@@ -73,7 +74,7 @@ SECTIONS
.data : { /* Data */
. = . + DATAOFFSET; /* for CONFIG_MAPPED_KERNEL */
- INIT_TASK_DATA(PAGE_SIZE)
+ INIT_TASK_DATA(THREAD_SIZE)
NOSAVE_DATA
CACHELINE_ALIGNED_DATA(1 << CONFIG_MIPS_L1_CACHE_SHIFT)
READ_MOSTLY_DATA(1 << CONFIG_MIPS_L1_CACHE_SHIFT)
diff --git a/arch/mn10300/Makefile b/arch/mn10300/Makefile
index 7120282..3eb4a52 100644
--- a/arch/mn10300/Makefile
+++ b/arch/mn10300/Makefile
@@ -26,7 +26,7 @@ CHECKFLAGS +=
PROCESSOR := unset
UNIT := unset
-KBUILD_CFLAGS += -mam33 -mmem-funcs -DCPU=AM33
+KBUILD_CFLAGS += -mam33 -DCPU=AM33 $(call cc-option,-mmem-funcs,)
KBUILD_AFLAGS += -mam33 -DCPU=AM33
ifeq ($(CONFIG_MN10300_CURRENT_IN_E2),y)
diff --git a/arch/parisc/include/asm/atomic.h b/arch/parisc/include/asm/atomic.h
index 26fd114..3706cf0 100644
--- a/arch/parisc/include/asm/atomic.h
+++ b/arch/parisc/include/asm/atomic.h
@@ -248,7 +248,7 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
#define atomic_sub_and_test(i,v) (atomic_sub_return((i),(v)) == 0)
-#define ATOMIC_INIT(i) ((atomic_t) { (i) })
+#define ATOMIC_INIT(i) { (i) }
#define smp_mb__before_atomic_dec() smp_mb()
#define smp_mb__after_atomic_dec() smp_mb()
@@ -257,7 +257,7 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
#ifdef CONFIG_64BIT
-#define ATOMIC64_INIT(i) ((atomic64_t) { (i) })
+#define ATOMIC64_INIT(i) { (i) }
static __inline__ s64
__atomic64_add_return(s64 i, atomic64_t *v)
diff --git a/arch/parisc/include/asm/prefetch.h b/arch/parisc/include/asm/prefetch.h
index c5edc60..1ee7c82 100644
--- a/arch/parisc/include/asm/prefetch.h
+++ b/arch/parisc/include/asm/prefetch.h
@@ -21,7 +21,12 @@
#define ARCH_HAS_PREFETCH
static inline void prefetch(const void *addr)
{
- __asm__("ldw 0(%0), %%r0" : : "r" (addr));
+ __asm__(
+#ifndef CONFIG_PA20
+ /* Need to avoid prefetch of NULL on PA7300LC */
+ " extrw,u,= %0,31,32,%%r0\n"
+#endif
+ " ldw 0(%0), %%r0" : : "r" (addr));
}
/* LDD is a PA2.0 addition. */
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index 6f05944..07ef351 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -552,7 +552,7 @@
* entry (identifying the physical page) and %r23 up with
* the from tlb entry (or nothing if only a to entry---for
* clear_user_page_asm) */
- .macro do_alias spc,tmp,tmp1,va,pte,prot,fault
+ .macro do_alias spc,tmp,tmp1,va,pte,prot,fault,patype
cmpib,COND(<>),n 0,\spc,\fault
ldil L%(TMPALIAS_MAP_START),\tmp
#if defined(CONFIG_64BIT) && (TMPALIAS_MAP_START >= 0x80000000)
@@ -581,7 +581,15 @@
*/
cmpiclr,= 0x01,\tmp,%r0
ldi (_PAGE_DIRTY|_PAGE_READ|_PAGE_WRITE),\prot
+.ifc \patype,20
depd,z \prot,8,7,\prot
+.else
+.ifc \patype,11
+ depw,z \prot,8,7,\prot
+.else
+ .error "undefined PA type to do_alias"
+.endif
+.endif
/*
* OK, it is in the temp alias region, check whether "from" or "to".
* Check "subtle" note in pacache.S re: r23/r26.
@@ -1185,7 +1193,7 @@ dtlb_miss_20w:
nop
dtlb_check_alias_20w:
- do_alias spc,t0,t1,va,pte,prot,dtlb_fault
+ do_alias spc,t0,t1,va,pte,prot,dtlb_fault,20
idtlbt pte,prot
@@ -1209,7 +1217,7 @@ nadtlb_miss_20w:
nop
nadtlb_check_alias_20w:
- do_alias spc,t0,t1,va,pte,prot,nadtlb_emulate
+ do_alias spc,t0,t1,va,pte,prot,nadtlb_emulate,20
idtlbt pte,prot
@@ -1241,7 +1249,7 @@ dtlb_miss_11:
nop
dtlb_check_alias_11:
- do_alias spc,t0,t1,va,pte,prot,dtlb_fault
+ do_alias spc,t0,t1,va,pte,prot,dtlb_fault,11
idtlba pte,(va)
idtlbp prot,(va)
@@ -1273,7 +1281,7 @@ nadtlb_miss_11:
nop
nadtlb_check_alias_11:
- do_alias spc,t0,t1,va,pte,prot,nadtlb_emulate
+ do_alias spc,t0,t1,va,pte,prot,nadtlb_emulate,11
idtlba pte,(va)
idtlbp prot,(va)
@@ -1300,7 +1308,7 @@ dtlb_miss_20:
nop
dtlb_check_alias_20:
- do_alias spc,t0,t1,va,pte,prot,dtlb_fault
+ do_alias spc,t0,t1,va,pte,prot,dtlb_fault,20
idtlbt pte,prot
@@ -1326,7 +1334,7 @@ nadtlb_miss_20:
nop
nadtlb_check_alias_20:
- do_alias spc,t0,t1,va,pte,prot,nadtlb_emulate
+ do_alias spc,t0,t1,va,pte,prot,nadtlb_emulate,20
idtlbt pte,prot
@@ -1453,7 +1461,7 @@ naitlb_miss_20w:
nop
naitlb_check_alias_20w:
- do_alias spc,t0,t1,va,pte,prot,naitlb_fault
+ do_alias spc,t0,t1,va,pte,prot,naitlb_fault,20
iitlbt pte,prot
@@ -1507,7 +1515,7 @@ naitlb_miss_11:
nop
naitlb_check_alias_11:
- do_alias spc,t0,t1,va,pte,prot,itlb_fault
+ do_alias spc,t0,t1,va,pte,prot,itlb_fault,11
iitlba pte,(%sr0, va)
iitlbp prot,(%sr0, va)
@@ -1553,7 +1561,7 @@ naitlb_miss_20:
nop
naitlb_check_alias_20:
- do_alias spc,t0,t1,va,pte,prot,naitlb_fault
+ do_alias spc,t0,t1,va,pte,prot,naitlb_fault,20
iitlbt pte,prot
diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S
index 93ff3d9..5d7218a 100644
--- a/arch/parisc/kernel/pacache.S
+++ b/arch/parisc/kernel/pacache.S
@@ -692,7 +692,7 @@ ENTRY(flush_icache_page_asm)
/* Purge any old translation */
- pitlb (%sr0,%r28)
+ pitlb (%sr4,%r28)
ldil L%icache_stride, %r1
ldw R%icache_stride(%r1), %r1
@@ -706,27 +706,29 @@ ENTRY(flush_icache_page_asm)
sub %r25, %r1, %r25
-1: fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
+ /* fic only has the type 26 form on PA1.1, requiring an
+ * explicit space specification, so use %sr4 */
+1: fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
cmpb,COND(<<) %r28, %r25,1b
- fic,m %r1(%r28)
+ fic,m %r1(%sr4,%r28)
sync
bv %r0(%r2)
- pitlb (%sr0,%r25)
+ pitlb (%sr4,%r25)
.exit
.procend
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index fa6f2b8..64a9998 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -50,8 +50,10 @@ SECTIONS
. = KERNEL_BINARY_TEXT_START;
_text = .; /* Text and read-only data */
- .text ALIGN(16) : {
+ .head ALIGN(16) : {
HEAD_TEXT
+ } = 0
+ .text ALIGN(16) : {
TEXT_TEXT
SCHED_TEXT
LOCK_TEXT
@@ -65,7 +67,7 @@ SECTIONS
*(.fixup)
*(.lock.text) /* out-of-line lock text */
*(.gnu.warning)
- } = 0
+ }
/* End of text section */
_etext = .;
diff --git a/arch/powerpc/include/asm/cputime.h b/arch/powerpc/include/asm/cputime.h
index 1cf20bd..33a3580 100644
--- a/arch/powerpc/include/asm/cputime.h
+++ b/arch/powerpc/include/asm/cputime.h
@@ -126,11 +126,11 @@ static inline u64 cputime64_to_jiffies64(const cputime_t ct)
/*
* Convert cputime <-> microseconds
*/
-extern u64 __cputime_msec_factor;
+extern u64 __cputime_usec_factor;
static inline unsigned long cputime_to_usecs(const cputime_t ct)
{
- return mulhdu(ct, __cputime_msec_factor) * USEC_PER_MSEC;
+ return mulhdu(ct, __cputime_usec_factor);
}
static inline cputime_t usecs_to_cputime(const unsigned long us)
@@ -143,7 +143,7 @@ static inline cputime_t usecs_to_cputime(const unsigned long us)
sec = us / 1000000;
if (ct) {
ct *= tb_ticks_per_sec;
- do_div(ct, 1000);
+ do_div(ct, 1000000);
}
if (sec)
ct += (cputime_t) sec * tb_ticks_per_sec;
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index c5cae0d..764e99c 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -1000,7 +1000,8 @@
/* Macros for setting and retrieving special purpose registers */
#ifndef __ASSEMBLY__
#define mfmsr() ({unsigned long rval; \
- asm volatile("mfmsr %0" : "=r" (rval)); rval;})
+ asm volatile("mfmsr %0" : "=r" (rval) : \
+ : "memory"); rval;})
#ifdef CONFIG_PPC_BOOK3S_64
#define __mtmsrd(v, l) asm volatile("mtmsrd %0," __stringify(l) \
: : "r" (v) : "memory")
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 36e1c8a..4c12a751 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -75,6 +75,7 @@ int main(void)
DEFINE(SIGSEGV, SIGSEGV);
DEFINE(NMI_MASK, NMI_MASK);
DEFINE(THREAD_DSCR, offsetof(struct thread_struct, dscr));
+ DEFINE(THREAD_DSCR_INHERIT, offsetof(struct thread_struct, dscr_inherit));
#else
DEFINE(THREAD_INFO, offsetof(struct task_struct, stack));
#endif /* CONFIG_PPC64 */
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index d834425..654fc53 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -380,6 +380,12 @@ _GLOBAL(ret_from_fork)
li r3,0
b syscall_exit
+ .section ".toc","aw"
+DSCR_DEFAULT:
+ .tc dscr_default[TC],dscr_default
+
+ .section ".text"
+
/*
* This routine switches between two different tasks. The process
* state of one is saved on its kernel stack. Then the state
@@ -519,9 +525,6 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
mr r1,r8 /* start using new stack pointer */
std r7,PACAKSAVE(r13)
- ld r6,_CCR(r1)
- mtcrf 0xFF,r6
-
#ifdef CONFIG_ALTIVEC
BEGIN_FTR_SECTION
ld r0,THREAD_VRSAVE(r4)
@@ -530,14 +533,22 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
#endif /* CONFIG_ALTIVEC */
#ifdef CONFIG_PPC64
BEGIN_FTR_SECTION
+ lwz r6,THREAD_DSCR_INHERIT(r4)
+ ld r7,DSCR_DEFAULT@toc(2)
ld r0,THREAD_DSCR(r4)
- cmpd r0,r25
- beq 1f
+ cmpwi r6,0
+ bne 1f
+ ld r0,0(r7)
+1: cmpd r0,r25
+ beq 2f
mtspr SPRN_DSCR,r0
-1:
+2:
END_FTR_SECTION_IFSET(CPU_FTR_DSCR)
#endif
+ ld r6,_CCR(r1)
+ mtcrf 0xFF,r6
+
/* r3-r13 are destroyed -- Cort */
REST_8GPRS(14, r1)
REST_10GPRS(22, r1)
diff --git a/arch/powerpc/kernel/ftrace.c b/arch/powerpc/kernel/ftrace.c
index bf99cfa..6324008 100644
--- a/arch/powerpc/kernel/ftrace.c
+++ b/arch/powerpc/kernel/ftrace.c
@@ -245,9 +245,9 @@ __ftrace_make_nop(struct module *mod,
/*
* On PPC32 the trampoline looks like:
- * 0x3d, 0x60, 0x00, 0x00 lis r11,sym@ha
- * 0x39, 0x6b, 0x00, 0x00 addi r11,r11,sym@l
- * 0x7d, 0x69, 0x03, 0xa6 mtctr r11
+ * 0x3d, 0x80, 0x00, 0x00 lis r12,sym@ha
+ * 0x39, 0x8c, 0x00, 0x00 addi r12,r12,sym@l
+ * 0x7d, 0x89, 0x03, 0xa6 mtctr r12
* 0x4e, 0x80, 0x04, 0x20 bctr
*/
@@ -262,9 +262,9 @@ __ftrace_make_nop(struct module *mod,
pr_devel(" %08x %08x ", jmp[0], jmp[1]);
/* verify that this is what we expect it to be */
- if (((jmp[0] & 0xffff0000) != 0x3d600000) ||
- ((jmp[1] & 0xffff0000) != 0x396b0000) ||
- (jmp[2] != 0x7d6903a6) ||
+ if (((jmp[0] & 0xffff0000) != 0x3d800000) ||
+ ((jmp[1] & 0xffff0000) != 0x398c0000) ||
+ (jmp[2] != 0x7d8903a6) ||
(jmp[3] != 0x4e800420)) {
printk(KERN_ERR "Not a trampoline\n");
return -EINVAL;
diff --git a/arch/powerpc/kernel/module_32.c b/arch/powerpc/kernel/module_32.c
index f832773..449a7e0 100644
--- a/arch/powerpc/kernel/module_32.c
+++ b/arch/powerpc/kernel/module_32.c
@@ -187,8 +187,8 @@ int apply_relocate(Elf32_Shdr *sechdrs,
static inline int entry_matches(struct ppc_plt_entry *entry, Elf32_Addr val)
{
- if (entry->jump[0] == 0x3d600000 + ((val + 0x8000) >> 16)
- && entry->jump[1] == 0x396b0000 + (val & 0xffff))
+ if (entry->jump[0] == 0x3d800000 + ((val + 0x8000) >> 16)
+ && entry->jump[1] == 0x398c0000 + (val & 0xffff))
return 1;
return 0;
}
@@ -215,10 +215,9 @@ static uint32_t do_plt_call(void *location,
entry++;
}
- /* Stolen from Paul Mackerras as well... */
- entry->jump[0] = 0x3d600000+((val+0x8000)>>16); /* lis r11,sym@ha */
- entry->jump[1] = 0x396b0000 + (val&0xffff); /* addi r11,r11,sym@l*/
- entry->jump[2] = 0x7d6903a6; /* mtctr r11 */
+ entry->jump[0] = 0x3d800000+((val+0x8000)>>16); /* lis r12,sym@ha */
+ entry->jump[1] = 0x398c0000 + (val&0xffff); /* addi r12,r12,sym@l*/
+ entry->jump[2] = 0x7d8903a6; /* mtctr r12 */
entry->jump[3] = 0x4e800420; /* bctr */
DEBUGP("Initialized plt for 0x%x at %p\n", val, entry);
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 91e52df..5596397 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -794,16 +794,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
#endif /* CONFIG_PPC_STD_MMU_64 */
#ifdef CONFIG_PPC64
if (cpu_has_feature(CPU_FTR_DSCR)) {
- if (current->thread.dscr_inherit) {
- p->thread.dscr_inherit = 1;
- p->thread.dscr = current->thread.dscr;
- } else if (0 != dscr_default) {
- p->thread.dscr_inherit = 1;
- p->thread.dscr = dscr_default;
- } else {
- p->thread.dscr_inherit = 0;
- p->thread.dscr = 0;
- }
+ p->thread.dscr_inherit = current->thread.dscr_inherit;
+ p->thread.dscr = current->thread.dscr;
}
#endif
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 2de304a..1becd7b 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -168,13 +168,13 @@ EXPORT_SYMBOL_GPL(ppc_tb_freq);
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
/*
* Factors for converting from cputime_t (timebase ticks) to
- * jiffies, milliseconds, seconds, and clock_t (1/USER_HZ seconds).
+ * jiffies, microseconds, seconds, and clock_t (1/USER_HZ seconds).
* These are all stored as 0.64 fixed-point binary fractions.
*/
u64 __cputime_jiffies_factor;
EXPORT_SYMBOL(__cputime_jiffies_factor);
-u64 __cputime_msec_factor;
-EXPORT_SYMBOL(__cputime_msec_factor);
+u64 __cputime_usec_factor;
+EXPORT_SYMBOL(__cputime_usec_factor);
u64 __cputime_sec_factor;
EXPORT_SYMBOL(__cputime_sec_factor);
u64 __cputime_clockt_factor;
@@ -192,8 +192,8 @@ static void calc_cputime_factors(void)
div128_by_32(HZ, 0, tb_ticks_per_sec, &res);
__cputime_jiffies_factor = res.result_low;
- div128_by_32(1000, 0, tb_ticks_per_sec, &res);
- __cputime_msec_factor = res.result_low;
+ div128_by_32(1000000, 0, tb_ticks_per_sec, &res);
+ __cputime_usec_factor = res.result_low;
div128_by_32(1, 0, tb_ticks_per_sec, &res);
__cputime_sec_factor = res.result_low;
div128_by_32(USER_HZ, 0, tb_ticks_per_sec, &res);
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 42541bb..ace1784 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -975,7 +975,7 @@ static int cpu_cmd(void)
/* print cpus waiting or in xmon */
printf("cpus stopped:");
count = 0;
- for (cpu = 0; cpu < NR_CPUS; ++cpu) {
+ for_each_possible_cpu(cpu) {
if (cpumask_test_cpu(cpu, &cpus_in_xmon)) {
if (count == 0)
printf(" %x", cpu);
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index 53acaa8..f98af03 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -631,7 +631,6 @@ asmlinkage unsigned long old32_mmap(struct mmap_arg_struct_emu31 __user *arg)
return -EFAULT;
if (a.offset & ~PAGE_MASK)
return -EINVAL;
- a.addr = (unsigned long) compat_ptr(a.addr);
return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd,
a.offset >> PAGE_SHIFT);
}
@@ -642,7 +641,6 @@ asmlinkage long sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg)
if (copy_from_user(&a, arg, sizeof(a)))
return -EFAULT;
- a.addr = (unsigned long) compat_ptr(a.addr);
return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
}
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index d814f79..6903d44 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -567,6 +567,7 @@ static void pfault_interrupt(unsigned int ext_int_code,
tsk->thread.pfault_wait = 0;
list_del(&tsk->thread.list);
wake_up_process(tsk);
+ put_task_struct(tsk);
} else {
/* Completion interrupt was faster than initial
* interrupt. Set pfault_wait to -1 so the initial
@@ -576,14 +577,22 @@ static void pfault_interrupt(unsigned int ext_int_code,
put_task_struct(tsk);
} else {
/* signal bit not set -> a real page is missing. */
- if (tsk->thread.pfault_wait == -1) {
+ if (tsk->thread.pfault_wait == 1) {
+ /* Already on the list with a reference: put to sleep */
+ set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+ set_tsk_need_resched(tsk);
+ } else if (tsk->thread.pfault_wait == -1) {
/* Completion interrupt was faster than the initial
* interrupt (pfault_wait == -1). Set pfault_wait
* back to zero and exit. */
tsk->thread.pfault_wait = 0;
} else {
/* Initial interrupt arrived before completion
- * interrupt. Let the task sleep. */
+ * interrupt. Let the task sleep.
+ * An extra task reference is needed since a different
+ * cpu may set the task state to TASK_RUNNING again
+ * before the scheduler is reached. */
+ get_task_struct(tsk);
tsk->thread.pfault_wait = 1;
list_add(&tsk->thread.list, &pfault_list);
set_task_state(tsk, TASK_UNINTERRUPTIBLE);
@@ -608,6 +617,7 @@ static int __cpuinit pfault_cpu_notify(struct notifier_block *self,
list_del(&thread->list);
tsk = container_of(thread, struct task_struct, thread);
wake_up_process(tsk);
+ put_task_struct(tsk);
}
spin_unlock_irq(&pfault_lock);
break;
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 2e79419..9e70257 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -590,6 +590,9 @@ config SYSVIPC_COMPAT
depends on COMPAT && SYSVIPC
default y
+config KEYS_COMPAT
+ def_bool y if COMPAT && KEYS
+
endmenu
source "net/Kconfig"
diff --git a/arch/sparc/kernel/central.c b/arch/sparc/kernel/central.c
index 7eef3f7..f5ddc0b 100644
--- a/arch/sparc/kernel/central.c
+++ b/arch/sparc/kernel/central.c
@@ -268,4 +268,4 @@ static int __init sunfire_init(void)
return 0;
}
-subsys_initcall(sunfire_init);
+fs_initcall(sunfire_init);
diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c
index 6860d40..904ed63 100644
--- a/arch/sparc/kernel/perf_event.c
+++ b/arch/sparc/kernel/perf_event.c
@@ -513,11 +513,13 @@ static u64 nop_for_index(int idx)
static inline void sparc_pmu_enable_event(struct cpu_hw_events *cpuc, struct hw_perf_event *hwc, int idx)
{
- u64 val, mask = mask_for_index(idx);
+ u64 enc, val, mask = mask_for_index(idx);
+
+ enc = perf_event_get_enc(cpuc->events[idx]);
val = cpuc->pcr;
val &= ~mask;
- val |= hwc->config;
+ val |= event_encoding(enc, idx);
cpuc->pcr = val;
pcr_ops->write(cpuc->pcr);
@@ -1380,8 +1382,6 @@ static void perf_callchain_user_64(struct perf_callchain_entry *entry,
{
unsigned long ufp;
- perf_callchain_store(entry, regs->tpc);
-
ufp = regs->u_regs[UREG_I6] + STACK_BIAS;
do {
struct sparc_stackf *usf, sf;
@@ -1402,8 +1402,6 @@ static void perf_callchain_user_32(struct perf_callchain_entry *entry,
{
unsigned long ufp;
- perf_callchain_store(entry, regs->tpc);
-
ufp = regs->u_regs[UREG_I6] & 0xffffffffUL;
do {
struct sparc_stackf32 *usf, sf;
@@ -1422,6 +1420,11 @@ static void perf_callchain_user_32(struct perf_callchain_entry *entry,
void
perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
{
+ perf_callchain_store(entry, regs->tpc);
+
+ if (!current->mm)
+ return;
+
flushw_user();
if (test_thread_flag(TIF_32BIT))
perf_callchain_user_32(entry, regs);
diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c
index 908b47a..10c9b36 100644
--- a/arch/sparc/kernel/sys_sparc_64.c
+++ b/arch/sparc/kernel/sys_sparc_64.c
@@ -519,12 +519,12 @@ SYSCALL_DEFINE1(sparc64_personality, unsigned long, personality)
{
int ret;
- if (current->personality == PER_LINUX32 &&
- personality == PER_LINUX)
- personality = PER_LINUX32;
+ if (personality(current->personality) == PER_LINUX32 &&
+ personality(personality) == PER_LINUX)
+ personality |= PER_LINUX32;
ret = sys_personality(personality);
- if (ret == PER_LINUX32)
- ret = PER_LINUX;
+ if (personality(ret) == PER_LINUX32)
+ ret &= ~PER_LINUX32;
return ret;
}
diff --git a/arch/sparc/kernel/syscalls.S b/arch/sparc/kernel/syscalls.S
index 1d7e274..7f5f65d 100644
--- a/arch/sparc/kernel/syscalls.S
+++ b/arch/sparc/kernel/syscalls.S
@@ -212,24 +212,20 @@ linux_sparc_syscall:
3: stx %o0, [%sp + PTREGS_OFF + PT_V9_I0]
ret_sys_call:
ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %g3
- ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc
sra %o0, 0, %o0
mov %ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2
sllx %g2, 32, %g2
- /* Check if force_successful_syscall_return()
- * was invoked.
- */
- ldub [%g6 + TI_SYS_NOERROR], %l2
- brnz,a,pn %l2, 80f
- stb %g0, [%g6 + TI_SYS_NOERROR]
-
cmp %o0, -ERESTART_RESTARTBLOCK
bgeu,pn %xcc, 1f
- andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %l6
-80:
+ andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %g0
+ ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc
+
+2:
+ stb %g0, [%g6 + TI_SYS_NOERROR]
/* System call success, clear Carry condition code. */
andn %g3, %g2, %g3
+3:
stx %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE]
bne,pn %icc, linux_syscall_trace2
add %l1, 0x4, %l2 ! npc = npc+4
@@ -238,20 +234,20 @@ ret_sys_call:
stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
1:
+ /* Check if force_successful_syscall_return()
+ * was invoked.
+ */
+ ldub [%g6 + TI_SYS_NOERROR], %l2
+ brnz,pn %l2, 2b
+ ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc
/* System call failure, set Carry condition code.
* Also, get abs(errno) to return to the process.
*/
- andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %l6
sub %g0, %o0, %o0
- or %g3, %g2, %g3
stx %o0, [%sp + PTREGS_OFF + PT_V9_I0]
- stx %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE]
- bne,pn %icc, linux_syscall_trace2
- add %l1, 0x4, %l2 ! npc = npc+4
- stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC]
+ ba,pt %xcc, 3b
+ or %g3, %g2, %g3
- b,pt %xcc, rtrap
- stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
linux_syscall_trace2:
call syscall_trace_leave
add %sp, PTREGS_OFF, %o0
diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S
index f566518..248fb67 100644
--- a/arch/sparc/kernel/systbls_64.S
+++ b/arch/sparc/kernel/systbls_64.S
@@ -74,7 +74,7 @@ sys_call_table32:
.word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy
/*270*/ .word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink
.word compat_sys_mq_timedsend, compat_sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid
-/*280*/ .word sys32_tee, sys_add_key, sys_request_key, sys_keyctl, compat_sys_openat
+/*280*/ .word sys32_tee, sys_add_key, sys_request_key, compat_sys_keyctl, compat_sys_openat
.word sys_mkdirat, sys_mknodat, sys_fchownat, compat_sys_futimesat, compat_sys_fstatat64
/*290*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
.word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll, sys_unshare
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 8e073d8..6ff4d78 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -2118,6 +2118,9 @@ EXPORT_SYMBOL(_PAGE_CACHE);
#ifdef CONFIG_SPARSEMEM_VMEMMAP
unsigned long vmemmap_table[VMEMMAP_SIZE];
+static long __meminitdata addr_start, addr_end;
+static int __meminitdata node_start;
+
int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node)
{
unsigned long vstart = (unsigned long) start;
@@ -2148,15 +2151,30 @@ int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node)
*vmem_pp = pte_base | __pa(block);
- printk(KERN_INFO "[%p-%p] page_structs=%lu "
- "node=%d entry=%lu/%lu\n", start, block, nr,
- node,
- addr >> VMEMMAP_CHUNK_SHIFT,
- VMEMMAP_SIZE);
+ /* check to see if we have contiguous blocks */
+ if (addr_end != addr || node_start != node) {
+ if (addr_start)
+ printk(KERN_DEBUG " [%lx-%lx] on node %d\n",
+ addr_start, addr_end-1, node_start);
+ addr_start = addr;
+ node_start = node;
+ }
+ addr_end = addr + VMEMMAP_CHUNK;
}
}
return 0;
}
+
+void __meminit vmemmap_populate_print_last(void)
+{
+ if (addr_start) {
+ printk(KERN_DEBUG " [%lx-%lx] on node %d\n",
+ addr_start, addr_end-1, node_start);
+ addr_start = 0;
+ addr_end = 0;
+ node_start = 0;
+ }
+}
#endif /* CONFIG_SPARSEMEM_VMEMMAP */
static void prot_init_common(unsigned long page_none,
diff --git a/arch/sparc/mm/ultra.S b/arch/sparc/mm/ultra.S
index b57a594..874162a 100644
--- a/arch/sparc/mm/ultra.S
+++ b/arch/sparc/mm/ultra.S
@@ -495,11 +495,11 @@ xcall_fetch_glob_regs:
stx %o7, [%g1 + GR_SNAP_O7]
stx %i7, [%g1 + GR_SNAP_I7]
/* Don't try this at home kids... */
- rdpr %cwp, %g2
- sub %g2, 1, %g7
+ rdpr %cwp, %g3
+ sub %g3, 1, %g7
wrpr %g7, %cwp
mov %i7, %g7
- wrpr %g2, %cwp
+ wrpr %g3, %cwp
stx %g7, [%g1 + GR_SNAP_RPC]
sethi %hi(trap_block), %g7
or %g7, %lo(trap_block), %g7
diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig
index 0249b8b..532a2a4 100644
--- a/arch/tile/Kconfig
+++ b/arch/tile/Kconfig
@@ -11,6 +11,7 @@ config TILE
select GENERIC_IRQ_PROBE
select GENERIC_PENDING_IRQ if SMP
select GENERIC_IRQ_SHOW
+ select HAVE_SYSCALL_WRAPPERS if TILEGX
select SYS_HYPERVISOR
# FIXME: investigate whether we need/want these options.
diff --git a/arch/tile/Makefile b/arch/tile/Makefile
index 17acce7..04c637c 100644
--- a/arch/tile/Makefile
+++ b/arch/tile/Makefile
@@ -26,6 +26,10 @@ $(error Set TILERA_ROOT or CROSS_COMPILE when building $(ARCH) on $(HOST_ARCH))
endif
endif
+# The tile compiler may emit .eh_frame information for backtracing.
+# In kernel modules, this causes load failures due to unsupported relocations.
+KBUILD_CFLAGS += -fno-asynchronous-unwind-tables
+
ifneq ($(CONFIG_DEBUG_EXTRA_FLAGS),"")
KBUILD_CFLAGS += $(CONFIG_DEBUG_EXTRA_FLAGS)
endif
diff --git a/arch/tile/include/asm/bitops.h b/arch/tile/include/asm/bitops.h
index 16f1fa5..bd186c4 100644
--- a/arch/tile/include/asm/bitops.h
+++ b/arch/tile/include/asm/bitops.h
@@ -77,6 +77,11 @@ static inline int ffs(int x)
return __builtin_ffs(x);
}
+static inline int fls64(__u64 w)
+{
+ return (sizeof(__u64) * 8) - __builtin_clzll(w);
+}
+
/**
* fls - find last set bit in word
* @x: the word to search
@@ -90,12 +95,7 @@ static inline int ffs(int x)
*/
static inline int fls(int x)
{
- return (sizeof(int) * 8) - __builtin_clz(x);
-}
-
-static inline int fls64(__u64 w)
-{
- return (sizeof(__u64) * 8) - __builtin_clzll(w);
+ return fls64((unsigned int) x);
}
static inline unsigned int __arch_hweight32(unsigned int w)
diff --git a/arch/tile/kernel/compat_signal.c b/arch/tile/kernel/compat_signal.c
index a7869ad..41459d8 100644
--- a/arch/tile/kernel/compat_signal.c
+++ b/arch/tile/kernel/compat_signal.c
@@ -406,19 +406,17 @@ int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
* Set up registers for signal handler.
* Registers that we don't modify keep the value they had from
* user-space at the time we took the signal.
+ * We always pass siginfo and mcontext, regardless of SA_SIGINFO,
+ * since some things rely on this (e.g. glibc's debug/segfault.c).
*/
regs->pc = ptr_to_compat_reg(ka->sa.sa_handler);
regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */
regs->sp = ptr_to_compat_reg(frame);
regs->lr = restorer;
regs->regs[0] = (unsigned long) usig;
-
- if (ka->sa.sa_flags & SA_SIGINFO) {
- /* Need extra arguments, so mark to restore caller-saves. */
- regs->regs[1] = ptr_to_compat_reg(&frame->info);
- regs->regs[2] = ptr_to_compat_reg(&frame->uc);
- regs->flags |= PT_FLAGS_CALLER_SAVES;
- }
+ regs->regs[1] = ptr_to_compat_reg(&frame->info);
+ regs->regs[2] = ptr_to_compat_reg(&frame->uc);
+ regs->flags |= PT_FLAGS_CALLER_SAVES;
/*
* Notify any tracer that was single-stepping it.
diff --git a/arch/um/include/asm/pgtable.h b/arch/um/include/asm/pgtable.h
index 41474fb..aa365c5 100644
--- a/arch/um/include/asm/pgtable.h
+++ b/arch/um/include/asm/pgtable.h
@@ -271,6 +271,12 @@ static inline void set_pte(pte_t *pteptr, pte_t pteval)
}
#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
+#define __HAVE_ARCH_PTE_SAME
+static inline int pte_same(pte_t pte_a, pte_t pte_b)
+{
+ return !((pte_val(pte_a) ^ pte_val(pte_b)) & ~_PAGE_NEWPAGE);
+}
+
/*
* Conversion functions: convert a page and protection to a page entry,
* and a page entry and page directory to the page they refer to.
@@ -346,11 +352,11 @@ extern pte_t *virt_to_pte(struct mm_struct *mm, unsigned long addr);
#define update_mmu_cache(vma,address,ptep) do ; while (0)
/* Encode and de-code a swap entry */
-#define __swp_type(x) (((x).val >> 4) & 0x3f)
+#define __swp_type(x) (((x).val >> 5) & 0x1f)
#define __swp_offset(x) ((x).val >> 11)
#define __swp_entry(type, offset) \
- ((swp_entry_t) { ((type) << 4) | ((offset) << 11) })
+ ((swp_entry_t) { ((type) << 5) | ((offset) << 11) })
#define __pte_to_swp_entry(pte) \
((swp_entry_t) { pte_val(pte_mkuptodate(pte)) })
#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 37357a5..a0e9bda 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1451,6 +1451,15 @@ config ARCH_USES_PG_UNCACHED
def_bool y
depends on X86_PAT
+config ARCH_RANDOM
+ def_bool y
+ prompt "x86 architectural random number generator" if EXPERT
+ ---help---
+ Enable the x86 architectural RDRAND instruction
+ (Intel Bull Mountain technology) to generate random numbers.
+ If supported, this is a high bandwidth, cryptographically
+ secure hardware random number generator.
+
config EFI
bool "EFI runtime service support"
depends on ACPI
diff --git a/arch/x86/crypto/aesni-intel_asm.S b/arch/x86/crypto/aesni-intel_asm.S
index be6d9e3..3470624 100644
--- a/arch/x86/crypto/aesni-intel_asm.S
+++ b/arch/x86/crypto/aesni-intel_asm.S
@@ -2460,10 +2460,12 @@ ENTRY(aesni_cbc_dec)
pxor IN3, STATE4
movaps IN4, IV
#else
- pxor (INP), STATE2
- pxor 0x10(INP), STATE3
pxor IN1, STATE4
movaps IN2, IV
+ movups (INP), IN1
+ pxor IN1, STATE2
+ movups 0x10(INP), IN2
+ pxor IN2, STATE3
#endif
movups STATE1, (OUTP)
movups STATE2, 0x10(OUTP)
diff --git a/arch/x86/include/asm/archrandom.h b/arch/x86/include/asm/archrandom.h
new file mode 100644
index 0000000..0d9ec77
--- /dev/null
+++ b/arch/x86/include/asm/archrandom.h
@@ -0,0 +1,75 @@
+/*
+ * This file is part of the Linux kernel.
+ *
+ * Copyright (c) 2011, Intel Corporation
+ * Authors: Fenghua Yu <fenghua.yu@intel.com>,
+ * H. Peter Anvin <hpa@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef ASM_X86_ARCHRANDOM_H
+#define ASM_X86_ARCHRANDOM_H
+
+#include <asm/processor.h>
+#include <asm/cpufeature.h>
+#include <asm/alternative.h>
+#include <asm/nops.h>
+
+#define RDRAND_RETRY_LOOPS 10
+
+#define RDRAND_INT ".byte 0x0f,0xc7,0xf0"
+#ifdef CONFIG_X86_64
+# define RDRAND_LONG ".byte 0x48,0x0f,0xc7,0xf0"
+#else
+# define RDRAND_LONG RDRAND_INT
+#endif
+
+#ifdef CONFIG_ARCH_RANDOM
+
+#define GET_RANDOM(name, type, rdrand, nop) \
+static inline int name(type *v) \
+{ \
+ int ok; \
+ alternative_io("movl $0, %0\n\t" \
+ nop, \
+ "\n1: " rdrand "\n\t" \
+ "jc 2f\n\t" \
+ "decl %0\n\t" \
+ "jnz 1b\n\t" \
+ "2:", \
+ X86_FEATURE_RDRAND, \
+ ASM_OUTPUT2("=r" (ok), "=a" (*v)), \
+ "0" (RDRAND_RETRY_LOOPS)); \
+ return ok; \
+}
+
+#ifdef CONFIG_X86_64
+
+GET_RANDOM(arch_get_random_long, unsigned long, RDRAND_LONG, ASM_NOP5);
+GET_RANDOM(arch_get_random_int, unsigned int, RDRAND_INT, ASM_NOP4);
+
+#else
+
+GET_RANDOM(arch_get_random_long, unsigned long, RDRAND_LONG, ASM_NOP3);
+GET_RANDOM(arch_get_random_int, unsigned int, RDRAND_INT, ASM_NOP3);
+
+#endif /* CONFIG_X86_64 */
+
+#endif /* CONFIG_ARCH_RANDOM */
+
+extern void x86_init_rdrand(struct cpuinfo_x86 *c);
+
+#endif /* ASM_X86_ARCHRANDOM_H */
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index 71cc380..c5d941f 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -173,7 +173,7 @@
#define X86_FEATURE_XSAVEOPT (7*32+ 4) /* Optimized Xsave */
#define X86_FEATURE_PLN (7*32+ 5) /* Intel Power Limit Notification */
#define X86_FEATURE_PTS (7*32+ 6) /* Intel Package Thermal Status */
-#define X86_FEATURE_DTS (7*32+ 7) /* Digital Thermal Sensor */
+#define X86_FEATURE_DTHERM (7*32+ 7) /* Digital Thermal Sensor */
/* Virtualization flags: Linux defined, word 8 */
#define X86_FEATURE_TPR_SHADOW (8*32+ 0) /* Intel TPR Shadow */
diff --git a/arch/x86/include/asm/pgtable-3level.h b/arch/x86/include/asm/pgtable-3level.h
index effff47..43876f1 100644
--- a/arch/x86/include/asm/pgtable-3level.h
+++ b/arch/x86/include/asm/pgtable-3level.h
@@ -31,6 +31,56 @@ static inline void native_set_pte(pte_t *ptep, pte_t pte)
ptep->pte_low = pte.pte_low;
}
+#define pmd_read_atomic pmd_read_atomic
+/*
+ * pte_offset_map_lock on 32bit PAE kernels was reading the pmd_t with
+ * a "*pmdp" dereference done by gcc. Problem is, in certain places
+ * where pte_offset_map_lock is called, concurrent page faults are
+ * allowed, if the mmap_sem is hold for reading. An example is mincore
+ * vs page faults vs MADV_DONTNEED. On the page fault side
+ * pmd_populate rightfully does a set_64bit, but if we're reading the
+ * pmd_t with a "*pmdp" on the mincore side, a SMP race can happen
+ * because gcc will not read the 64bit of the pmd atomically. To fix
+ * this all places running pmd_offset_map_lock() while holding the
+ * mmap_sem in read mode, shall read the pmdp pointer using this
+ * function to know if the pmd is null nor not, and in turn to know if
+ * they can run pmd_offset_map_lock or pmd_trans_huge or other pmd
+ * operations.
+ *
+ * Without THP if the mmap_sem is hold for reading, the
+ * pmd can only transition from null to not null while pmd_read_atomic runs.
+ * So there's no need of literally reading it atomically.
+ *
+ * With THP if the mmap_sem is hold for reading, the pmd can become
+ * THP or null or point to a pte (and in turn become "stable") at any
+ * time under pmd_read_atomic, so it's mandatory to read it atomically
+ * with cmpxchg8b.
+ */
+#ifndef CONFIG_TRANSPARENT_HUGEPAGE
+static inline pmd_t pmd_read_atomic(pmd_t *pmdp)
+{
+ pmdval_t ret;
+ u32 *tmp = (u32 *)pmdp;
+
+ ret = (pmdval_t) (*tmp);
+ if (ret) {
+ /*
+ * If the low part is null, we must not read the high part
+ * or we can end up with a partial pmd.
+ */
+ smp_rmb();
+ ret |= ((pmdval_t)*(tmp + 1)) << 32;
+ }
+
+ return (pmd_t) { ret };
+}
+#else /* CONFIG_TRANSPARENT_HUGEPAGE */
+static inline pmd_t pmd_read_atomic(pmd_t *pmdp)
+{
+ return (pmd_t) { atomic64_read((atomic64_t *)pmdp) };
+}
+#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
+
static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte)
{
set_64bit((unsigned long long *)(ptep), native_pte_val(pte));
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
index 18601c8..884507e 100644
--- a/arch/x86/include/asm/pgtable.h
+++ b/arch/x86/include/asm/pgtable.h
@@ -146,8 +146,7 @@ static inline unsigned long pmd_pfn(pmd_t pmd)
static inline int pmd_large(pmd_t pte)
{
- return (pmd_flags(pte) & (_PAGE_PSE | _PAGE_PRESENT)) ==
- (_PAGE_PSE | _PAGE_PRESENT);
+ return pmd_flags(pte) & _PAGE_PSE;
}
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
@@ -415,7 +414,13 @@ static inline int pte_hidden(pte_t pte)
static inline int pmd_present(pmd_t pmd)
{
- return pmd_flags(pmd) & _PAGE_PRESENT;
+ /*
+ * Checking for _PAGE_PSE is needed too because
+ * split_huge_page will temporarily clear the present bit (but
+ * the _PAGE_PSE flag will remain set at all times while the
+ * _PAGE_PRESENT bit is clear).
+ */
+ return pmd_flags(pmd) & (_PAGE_PRESENT | _PAGE_PROTNONE | _PAGE_PSE);
}
static inline int pmd_none(pmd_t pmd)
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 5d9c61d..e5f7248 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -99,7 +99,6 @@ struct cpuinfo_x86 {
u16 apicid;
u16 initial_apicid;
u16 x86_clflush_size;
-#ifdef CONFIG_SMP
/* number of cores as seen by the OS: */
u16 booted_cores;
/* Physical processor id: */
@@ -110,7 +109,6 @@ struct cpuinfo_x86 {
u8 compute_unit_id;
/* Index into per_cpu list: */
u16 cpu_index;
-#endif
} __attribute__((__aligned__(SMP_CACHE_BYTES)));
#define X86_VENDOR_INTEL 0
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 4558f0d..479d03c 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -416,12 +416,14 @@ acpi_parse_int_src_ovr(struct acpi_subtable_header * header,
return 0;
}
- if (intsrc->source_irq == 0 && intsrc->global_irq == 2) {
+ if (intsrc->source_irq == 0) {
if (acpi_skip_timer_override) {
- printk(PREFIX "BIOS IRQ0 pin2 override ignored.\n");
+ printk(PREFIX "BIOS IRQ0 override ignored.\n");
return 0;
}
- if (acpi_fix_pin2_polarity && (intsrc->inti_flags & ACPI_MADT_POLARITY_MASK)) {
+
+ if ((intsrc->global_irq == 2) && acpi_fix_pin2_polarity
+ && (intsrc->inti_flags & ACPI_MADT_POLARITY_MASK)) {
intsrc->inti_flags &= ~ACPI_MADT_POLARITY_MASK;
printk(PREFIX "BIOS IRQ0 pin2 override: forcing polarity to high active.\n");
}
@@ -1327,17 +1329,12 @@ static int __init dmi_disable_acpi(const struct dmi_system_id *d)
}
/*
- * Force ignoring BIOS IRQ0 pin2 override
+ * Force ignoring BIOS IRQ0 override
*/
static int __init dmi_ignore_irq0_timer_override(const struct dmi_system_id *d)
{
- /*
- * The ati_ixp4x0_rev() early PCI quirk should have set
- * the acpi_skip_timer_override flag already:
- */
if (!acpi_skip_timer_override) {
- WARN(1, KERN_ERR "ati_ixp4x0 quirk not complete.\n");
- pr_notice("%s detected: Ignoring BIOS IRQ0 pin2 override\n",
+ pr_notice("%s detected: Ignoring BIOS IRQ0 override\n",
d->ident);
acpi_skip_timer_override = 1;
}
@@ -1431,7 +1428,7 @@ static struct dmi_system_id __initdata acpi_dmi_table_late[] = {
* is enabled. This input is incorrectly designated the
* ISA IRQ 0 via an interrupt source override even though
* it is wired to the output of the master 8259A and INTIN0
- * is not connected at all. Force ignoring BIOS IRQ0 pin2
+ * is not connected at all. Force ignoring BIOS IRQ0
* override in that cases.
*/
{
@@ -1466,6 +1463,14 @@ static struct dmi_system_id __initdata acpi_dmi_table_late[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6715b"),
},
},
+ {
+ .callback = dmi_ignore_irq0_timer_override,
+ .ident = "FUJITSU SIEMENS",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "AMILO PRO V2030"),
+ },
+ },
{}
};
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index a81f2d5..4c734e6 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -161,7 +161,7 @@ static const unsigned char * const k7_nops[ASM_NOP_MAX+2] =
#endif
#ifdef P6_NOP1
-static const unsigned char __initconst_or_module p6nops[] =
+static const unsigned char p6nops[] =
{
P6_NOP1,
P6_NOP2,
@@ -220,7 +220,7 @@ void __init arch_init_ideal_nops(void)
ideal_nops = intel_nops;
#endif
}
-
+ break;
default:
#ifdef CONFIG_X86_64
ideal_nops = k8_nops;
diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c
index bae1efe..be16854 100644
--- a/arch/x86/kernel/amd_nb.c
+++ b/arch/x86/kernel/amd_nb.c
@@ -154,16 +154,14 @@ int amd_get_subcaches(int cpu)
{
struct pci_dev *link = node_to_amd_nb(amd_get_nb_id(cpu))->link;
unsigned int mask;
- int cuid = 0;
+ int cuid;
if (!amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
return 0;
pci_read_config_dword(link, 0x1d4, &mask);
-#ifdef CONFIG_SMP
cuid = cpu_data(cpu).compute_unit_id;
-#endif
return (mask >> (4 * cuid)) & 0xf;
}
@@ -172,7 +170,7 @@ int amd_set_subcaches(int cpu, int mask)
static unsigned int reset, ban;
struct amd_northbridge *nb = node_to_amd_nb(amd_get_nb_id(cpu));
unsigned int reg;
- int cuid = 0;
+ int cuid;
if (!amd_nb_has_feature(AMD_NB_L3_PARTITIONING) || mask > 0xf)
return -EINVAL;
@@ -190,9 +188,7 @@ int amd_set_subcaches(int cpu, int mask)
pci_write_config_dword(nb->misc, 0x1b8, reg & ~0x180000);
}
-#ifdef CONFIG_SMP
cuid = cpu_data(cpu).compute_unit_id;
-#endif
mask <<= 4 * cuid;
mask |= (0xf ^ (1 << cuid)) << 26;
diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile
index 6042981..0e3a82a 100644
--- a/arch/x86/kernel/cpu/Makefile
+++ b/arch/x86/kernel/cpu/Makefile
@@ -15,6 +15,7 @@ CFLAGS_common.o := $(nostackp)
obj-y := intel_cacheinfo.o scattered.o topology.o
obj-y += proc.o capflags.o powerflags.o common.o
obj-y += vmware.o hypervisor.o sched.o mshyperv.o
+obj-y += rdrand.o
obj-$(CONFIG_X86_32) += bugs.o
obj-$(CONFIG_X86_64) += bugs_64.o
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index b13ed39..8115040 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -146,7 +146,6 @@ static void __cpuinit init_amd_k6(struct cpuinfo_x86 *c)
static void __cpuinit amd_k7_smp_check(struct cpuinfo_x86 *c)
{
-#ifdef CONFIG_SMP
/* calling is from identify_secondary_cpu() ? */
if (!c->cpu_index)
return;
@@ -190,7 +189,6 @@ static void __cpuinit amd_k7_smp_check(struct cpuinfo_x86 *c)
valid_k7:
;
-#endif
}
static void __cpuinit init_amd_k7(struct cpuinfo_x86 *c)
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 22a073d..1579ab9 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -15,6 +15,7 @@
#include <asm/stackprotector.h>
#include <asm/perf_event.h>
#include <asm/mmu_context.h>
+#include <asm/archrandom.h>
#include <asm/hypervisor.h>
#include <asm/processor.h>
#include <asm/sections.h>
@@ -675,9 +676,7 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
if (this_cpu->c_early_init)
this_cpu->c_early_init(c);
-#ifdef CONFIG_SMP
c->cpu_index = 0;
-#endif
filter_cpuid_features(c, false);
setup_smep(c);
@@ -760,10 +759,7 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 *c)
c->apicid = c->initial_apicid;
# endif
#endif
-
-#ifdef CONFIG_X86_HT
c->phys_proc_id = c->initial_apicid;
-#endif
}
setup_smep(c);
@@ -857,6 +853,7 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
#endif
init_hypervisor(c);
+ x86_init_rdrand(c);
/*
* Clear/Set all flags overriden by options, need do it
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index ed6086e..e0dc000 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -179,7 +179,6 @@ static void __cpuinit trap_init_f00f_bug(void)
static void __cpuinit intel_smp_check(struct cpuinfo_x86 *c)
{
-#ifdef CONFIG_SMP
/* calling is from identify_secondary_cpu() ? */
if (!c->cpu_index)
return;
@@ -196,7 +195,6 @@ static void __cpuinit intel_smp_check(struct cpuinfo_x86 *c)
WARN_ONCE(1, "WARNING: SMP operation may be unreliable"
"with B stepping processors.\n");
}
-#endif
}
static void __cpuinit intel_workarounds(struct cpuinfo_x86 *c)
diff --git a/arch/x86/kernel/cpu/mcheck/mce-severity.c b/arch/x86/kernel/cpu/mcheck/mce-severity.c
index 1e8d66c..362190b 100644
--- a/arch/x86/kernel/cpu/mcheck/mce-severity.c
+++ b/arch/x86/kernel/cpu/mcheck/mce-severity.c
@@ -101,15 +101,19 @@ static struct severity {
};
/*
- * If the EIPV bit is set, it means the saved IP is the
- * instruction which caused the MCE.
+ * If mcgstatus indicated that ip/cs on the stack were
+ * no good, then "m->cs" will be zero and we will have
+ * to assume the worst case (IN_KERNEL) as we actually
+ * have no idea what we were executing when the machine
+ * check hit.
+ * If we do have a good "m->cs" (or a faked one in the
+ * case we were executing in VM86 mode) we can use it to
+ * distinguish an exception taken in user from from one
+ * taken in the kernel.
*/
static int error_context(struct mce *m)
{
- if (m->mcgstatus & MCG_STATUS_EIPV)
- return (m->ip && (m->cs & 3) == 3) ? IN_USER : IN_KERNEL;
- /* Unknown, assume kernel */
- return IN_KERNEL;
+ return ((m->cs & 3) == 3) ? IN_USER : IN_KERNEL;
}
int mce_severity(struct mce *a, int tolerant, char **msg)
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index ff1ae9b..1396edf 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -122,9 +122,7 @@ void mce_setup(struct mce *m)
m->time = get_seconds();
m->cpuvendor = boot_cpu_data.x86_vendor;
m->cpuid = cpuid_eax(1);
-#ifdef CONFIG_SMP
m->socketid = cpu_data(m->extcpu).phys_proc_id;
-#endif
m->apicid = cpu_data(m->extcpu).initial_apicid;
rdmsrl(MSR_IA32_MCG_CAP, m->mcgcap);
}
@@ -453,6 +451,13 @@ static inline void mce_get_rip(struct mce *m, struct pt_regs *regs)
if (regs && (m->mcgstatus & (MCG_STATUS_RIPV|MCG_STATUS_EIPV))) {
m->ip = regs->ip;
m->cs = regs->cs;
+ /*
+ * When in VM86 mode make the cs look like ring 3
+ * always. This is a lie, but it's better than passing
+ * the additional vm86 bit around everywhere.
+ */
+ if (v8086_mode(regs))
+ m->cs |= 3;
} else {
m->ip = 0;
m->cs = 0;
@@ -990,6 +995,7 @@ void do_machine_check(struct pt_regs *regs, long error_code)
*/
add_taint(TAINT_MACHINE_CHECK);
+ mce_get_rip(&m, regs);
severity = mce_severity(&m, tolerant, NULL);
/*
@@ -1028,7 +1034,6 @@ void do_machine_check(struct pt_regs *regs, long error_code)
if (severity == MCE_AO_SEVERITY && mce_usable_address(&m))
mce_ring_add(m.addr >> PAGE_SHIFT);
- mce_get_rip(&m, regs);
mce_log(&m);
if (severity > worst) {
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index bb0adad..b97aa72 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -52,6 +52,7 @@ struct threshold_block {
unsigned int cpu;
u32 address;
u16 interrupt_enable;
+ bool interrupt_capable;
u16 threshold_limit;
struct kobject kobj;
struct list_head miscj;
@@ -64,11 +65,9 @@ struct threshold_bank {
};
static DEFINE_PER_CPU(struct threshold_bank * [NR_BANKS], threshold_banks);
-#ifdef CONFIG_SMP
static unsigned char shared_bank[NR_BANKS] = {
0, 0, 0, 0, 1
};
-#endif
static DEFINE_PER_CPU(unsigned char, bank_map); /* see which banks are on */
@@ -86,6 +85,21 @@ struct thresh_restart {
u16 old_limit;
};
+static bool lvt_interrupt_supported(unsigned int bank, u32 msr_high_bits)
+{
+ /*
+ * bank 4 supports APIC LVT interrupts implicitly since forever.
+ */
+ if (bank == 4)
+ return true;
+
+ /*
+ * IntP: interrupt present; if this bit is set, the thresholding
+ * bank can generate APIC LVT interrupts
+ */
+ return msr_high_bits & BIT(28);
+}
+
static int lvt_off_valid(struct threshold_block *b, int apic, u32 lo, u32 hi)
{
int msr = (hi & MASK_LVTOFF_HI) >> 20;
@@ -107,8 +121,10 @@ static int lvt_off_valid(struct threshold_block *b, int apic, u32 lo, u32 hi)
return 1;
};
-/* must be called with correct cpu affinity */
-/* Called via smp_call_function_single() */
+/*
+ * Called via smp_call_function_single(), must be called with correct
+ * cpu affinity.
+ */
static void threshold_restart_bank(void *_tr)
{
struct thresh_restart *tr = _tr;
@@ -131,6 +147,12 @@ static void threshold_restart_bank(void *_tr)
(new_count & THRESHOLD_MAX);
}
+ /* clear IntType */
+ hi &= ~MASK_INT_TYPE_HI;
+
+ if (!tr->b->interrupt_capable)
+ goto done;
+
if (tr->set_lvt_off) {
if (lvt_off_valid(tr->b, tr->lvt_off, lo, hi)) {
/* set new lvt offset */
@@ -139,9 +161,10 @@ static void threshold_restart_bank(void *_tr)
}
}
- tr->b->interrupt_enable ?
- (hi = (hi & ~MASK_INT_TYPE_HI) | INT_TYPE_APIC) :
- (hi &= ~MASK_INT_TYPE_HI);
+ if (tr->b->interrupt_enable)
+ hi |= INT_TYPE_APIC;
+
+ done:
hi |= MASK_COUNT_EN_HI;
wrmsr(tr->b->address, lo, hi);
@@ -202,18 +225,21 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c)
if (!block)
per_cpu(bank_map, cpu) |= (1 << bank);
-#ifdef CONFIG_SMP
+
if (shared_bank[bank] && c->cpu_core_id)
break;
-#endif
- offset = setup_APIC_mce(offset,
- (high & MASK_LVTOFF_HI) >> 20);
memset(&b, 0, sizeof(b));
- b.cpu = cpu;
- b.bank = bank;
- b.block = block;
- b.address = address;
+ b.cpu = cpu;
+ b.bank = bank;
+ b.block = block;
+ b.address = address;
+ b.interrupt_capable = lvt_interrupt_supported(bank, high);
+
+ if (b.interrupt_capable) {
+ int new = (high & MASK_LVTOFF_HI) >> 20;
+ offset = setup_APIC_mce(offset, new);
+ }
mce_threshold_block_init(&b, offset);
mce_threshold_vector = amd_threshold_interrupt;
@@ -313,6 +339,9 @@ store_interrupt_enable(struct threshold_block *b, const char *buf, size_t size)
struct thresh_restart tr;
unsigned long new;
+ if (!b->interrupt_capable)
+ return -EINVAL;
+
if (strict_strtoul(buf, 0, &new) < 0)
return -EINVAL;
@@ -471,6 +500,7 @@ static __cpuinit int allocate_threshold_blocks(unsigned int cpu,
b->cpu = cpu;
b->address = address;
b->interrupt_enable = 0;
+ b->interrupt_capable = lvt_interrupt_supported(bank, high);
b->threshold_limit = THRESHOLD_MAX;
INIT_LIST_HEAD(&b->miscj);
diff --git a/arch/x86/kernel/cpu/perf_event_amd.c b/arch/x86/kernel/cpu/perf_event_amd.c
index fe29c1d..4b50c96 100644
--- a/arch/x86/kernel/cpu/perf_event_amd.c
+++ b/arch/x86/kernel/cpu/perf_event_amd.c
@@ -437,6 +437,7 @@ static __initconst const struct x86_pmu amd_pmu = {
* 0x023 DE PERF_CTL[2:0]
* 0x02D LS PERF_CTL[3]
* 0x02E LS PERF_CTL[3,0]
+ * 0x031 LS PERF_CTL[2:0] (**)
* 0x043 CU PERF_CTL[2:0]
* 0x045 CU PERF_CTL[2:0]
* 0x046 CU PERF_CTL[2:0]
@@ -450,10 +451,12 @@ static __initconst const struct x86_pmu amd_pmu = {
* 0x0DD LS PERF_CTL[5:0]
* 0x0DE LS PERF_CTL[5:0]
* 0x0DF LS PERF_CTL[5:0]
+ * 0x1C0 EX PERF_CTL[5:3]
* 0x1D6 EX PERF_CTL[5:0]
* 0x1D8 EX PERF_CTL[5:0]
*
- * (*) depending on the umask all FPU counters may be used
+ * (*) depending on the umask all FPU counters may be used
+ * (**) only one unitmask enabled at a time
*/
static struct event_constraint amd_f15_PMC0 = EVENT_CONSTRAINT(0, 0x01, 0);
@@ -503,6 +506,12 @@ amd_get_event_constraints_f15h(struct cpu_hw_events *cpuc, struct perf_event *ev
return &amd_f15_PMC3;
case 0x02E:
return &amd_f15_PMC30;
+ case 0x031:
+ if (hweight_long(hwc->config & ARCH_PERFMON_EVENTSEL_UMASK) <= 1)
+ return &amd_f15_PMC20;
+ return &emptyconstraint;
+ case 0x1C0:
+ return &amd_f15_PMC53;
default:
return &amd_f15_PMC50;
}
diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c
index 62ac8cb..72c365a 100644
--- a/arch/x86/kernel/cpu/proc.c
+++ b/arch/x86/kernel/cpu/proc.c
@@ -64,12 +64,10 @@ static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c)
static int show_cpuinfo(struct seq_file *m, void *v)
{
struct cpuinfo_x86 *c = v;
- unsigned int cpu = 0;
+ unsigned int cpu;
int i;
-#ifdef CONFIG_SMP
cpu = c->cpu_index;
-#endif
seq_printf(m, "processor\t: %u\n"
"vendor_id\t: %s\n"
"cpu family\t: %d\n"
diff --git a/arch/x86/kernel/cpu/rdrand.c b/arch/x86/kernel/cpu/rdrand.c
new file mode 100644
index 0000000..feca286
--- /dev/null
+++ b/arch/x86/kernel/cpu/rdrand.c
@@ -0,0 +1,73 @@
+/*
+ * This file is part of the Linux kernel.
+ *
+ * Copyright (c) 2011, Intel Corporation
+ * Authors: Fenghua Yu <fenghua.yu@intel.com>,
+ * H. Peter Anvin <hpa@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <asm/processor.h>
+#include <asm/archrandom.h>
+#include <asm/sections.h>
+
+static int __init x86_rdrand_setup(char *s)
+{
+ setup_clear_cpu_cap(X86_FEATURE_RDRAND);
+ return 1;
+}
+__setup("nordrand", x86_rdrand_setup);
+
+/* We can't use arch_get_random_long() here since alternatives haven't run */
+static inline int rdrand_long(unsigned long *v)
+{
+ int ok;
+ asm volatile("1: " RDRAND_LONG "\n\t"
+ "jc 2f\n\t"
+ "decl %0\n\t"
+ "jnz 1b\n\t"
+ "2:"
+ : "=r" (ok), "=a" (*v)
+ : "0" (RDRAND_RETRY_LOOPS));
+ return ok;
+}
+
+/*
+ * Force a reseed cycle; we are architecturally guaranteed a reseed
+ * after no more than 512 128-bit chunks of random data. This also
+ * acts as a test of the CPU capability.
+ */
+#define RESEED_LOOP ((512*128)/sizeof(unsigned long))
+
+void __cpuinit x86_init_rdrand(struct cpuinfo_x86 *c)
+{
+#ifdef CONFIG_ARCH_RANDOM
+ unsigned long tmp;
+ int i, count, ok;
+
+ if (!cpu_has(c, X86_FEATURE_RDRAND))
+ return; /* Nothing to do */
+
+ for (count = i = 0; i < RESEED_LOOP; i++) {
+ ok = rdrand_long(&tmp);
+ if (ok)
+ count++;
+ }
+
+ if (count != RESEED_LOOP)
+ clear_cpu_cap(c, X86_FEATURE_RDRAND);
+#endif
+}
diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c
index c7f64e6..ea6106c 100644
--- a/arch/x86/kernel/cpu/scattered.c
+++ b/arch/x86/kernel/cpu/scattered.c
@@ -31,7 +31,7 @@ void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c)
const struct cpuid_bit *cb;
static const struct cpuid_bit __cpuinitconst cpuid_bits[] = {
- { X86_FEATURE_DTS, CR_EAX, 0, 0x00000006, 0 },
+ { X86_FEATURE_DTHERM, CR_EAX, 0, 0x00000006, 0 },
{ X86_FEATURE_IDA, CR_EAX, 1, 0x00000006, 0 },
{ X86_FEATURE_ARAT, CR_EAX, 2, 0x00000006, 0 },
{ X86_FEATURE_PLN, CR_EAX, 4, 0x00000006, 0 },
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index edb3d46..268b40d 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -1029,7 +1029,7 @@ ENTRY(xen_sysenter_target)
ENTRY(xen_hypervisor_callback)
CFI_STARTPROC
- pushl_cfi $0
+ pushl_cfi $-1 /* orig_ax = -1 => not a system call */
SAVE_ALL
TRACE_IRQS_OFF
@@ -1071,14 +1071,16 @@ ENTRY(xen_failsafe_callback)
2: mov 8(%esp),%es
3: mov 12(%esp),%fs
4: mov 16(%esp),%gs
+ /* EAX == 0 => Category 1 (Bad segment)
+ EAX != 0 => Category 2 (Bad IRET) */
testl %eax,%eax
popl_cfi %eax
lea 16(%esp),%esp
CFI_ADJUST_CFA_OFFSET -16
jz 5f
addl $16,%esp
- jmp iret_exc # EAX != 0 => Category 2 (Bad IRET)
-5: pushl_cfi $0 # EAX == 0 => Category 1 (Bad segment)
+ jmp iret_exc
+5: pushl_cfi $-1 /* orig_ax = -1 => not a system call */
SAVE_ALL
jmp ret_from_exception
CFI_ENDPROC
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 8a445a0..dd4dba4 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -1308,7 +1308,7 @@ ENTRY(xen_failsafe_callback)
CFI_RESTORE r11
addq $0x30,%rsp
CFI_ADJUST_CFA_OFFSET -0x30
- pushq_cfi $0
+ pushq_cfi $-1 /* orig_ax = -1 => not a system call */
SAVE_ALL
jmp error_exit
CFI_ENDPROC
diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c
index f924280..c4e2465 100644
--- a/arch/x86/kernel/microcode_core.c
+++ b/arch/x86/kernel/microcode_core.c
@@ -297,20 +297,31 @@ static ssize_t reload_store(struct sys_device *dev,
const char *buf, size_t size)
{
unsigned long val;
- int cpu = dev->id;
- int ret = 0;
- char *end;
+ int cpu;
+ ssize_t ret = 0, tmp_ret;
- val = simple_strtoul(buf, &end, 0);
- if (end == buf)
+ /* allow reload only from the BSP */
+ if (boot_cpu_data.cpu_index != dev->id)
return -EINVAL;
- if (val == 1) {
- get_online_cpus();
- if (cpu_online(cpu))
- ret = reload_for_cpu(cpu);
- put_online_cpus();
+ ret = kstrtoul(buf, 0, &val);
+ if (ret)
+ return ret;
+
+ if (val != 1)
+ return size;
+
+ get_online_cpus();
+ for_each_online_cpu(cpu) {
+ tmp_ret = reload_for_cpu(cpu);
+ if (tmp_ret != 0)
+ pr_warn("Error reloading microcode on CPU %d\n", cpu);
+
+ /* save retval of the first encountered reload error */
+ if (!ret)
+ ret = tmp_ret;
}
+ put_online_cpus();
if (!ret)
ret = size;
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index d4a705f..89d6877 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -452,6 +452,14 @@ static struct dmi_system_id __initdata pci_reboot_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6420"),
},
},
+ { /* Handle problems with rebooting on the Precision M6600. */
+ .callback = set_pci_reboot,
+ .ident = "Dell OptiPlex 990",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Precision M6600"),
+ },
+ },
{ }
};
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index afaf384..af19a61 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -937,8 +937,21 @@ void __init setup_arch(char **cmdline_p)
#ifdef CONFIG_X86_64
if (max_pfn > max_low_pfn) {
- max_pfn_mapped = init_memory_mapping(1UL<<32,
- max_pfn<<PAGE_SHIFT);
+ int i;
+ for (i = 0; i < e820.nr_map; i++) {
+ struct e820entry *ei = &e820.map[i];
+
+ if (ei->addr + ei->size <= 1UL << 32)
+ continue;
+
+ if (ei->type == E820_RESERVED)
+ continue;
+
+ max_pfn_mapped = init_memory_mapping(
+ ei->addr < 1UL << 32 ? 1UL << 32 : ei->addr,
+ ei->addr + ei->size);
+ }
+
/* can we preseve max_low_pfn ?*/
max_low_pfn = max_pfn;
}
diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c
index 71f4727..5a98aa2 100644
--- a/arch/x86/kernel/setup_percpu.c
+++ b/arch/x86/kernel/setup_percpu.c
@@ -185,10 +185,22 @@ void __init setup_per_cpu_areas(void)
#endif
rc = -EINVAL;
if (pcpu_chosen_fc != PCPU_FC_PAGE) {
- const size_t atom_size = cpu_has_pse ? PMD_SIZE : PAGE_SIZE;
const size_t dyn_size = PERCPU_MODULE_RESERVE +
PERCPU_DYNAMIC_RESERVE - PERCPU_FIRST_CHUNK_RESERVE;
+ size_t atom_size;
+ /*
+ * On 64bit, use PMD_SIZE for atom_size so that embedded
+ * percpu areas are aligned to PMD. This, in the future,
+ * can also allow using PMD mappings in vmalloc area. Use
+ * PAGE_SIZE on 32bit as vmalloc space is highly contended
+ * and large vmalloc area allocs can easily fail.
+ */
+#ifdef CONFIG_X86_64
+ atom_size = PMD_SIZE;
+#else
+ atom_size = PAGE_SIZE;
+#endif
rc = pcpu_embed_first_chunk(PERCPU_FIRST_CHUNK_RESERVE,
dyn_size, atom_size,
pcpu_cpu_distance,
diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c
index f581a18..df7d12c 100644
--- a/arch/x86/mm/hugetlbpage.c
+++ b/arch/x86/mm/hugetlbpage.c
@@ -56,9 +56,16 @@ static int vma_shareable(struct vm_area_struct *vma, unsigned long addr)
}
/*
- * search for a shareable pmd page for hugetlb.
+ * Search for a shareable pmd page for hugetlb. In any case calls pmd_alloc()
+ * and returns the corresponding pte. While this is not necessary for the
+ * !shared pmd case because we can allocate the pmd later as well, it makes the
+ * code much cleaner. pmd allocation is essential for the shared case because
+ * pud has to be populated inside the same i_mmap_mutex section - otherwise
+ * racing tasks could either miss the sharing (see huge_pte_offset) or select a
+ * bad pmd for sharing.
*/
-static void huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud)
+static pte_t *
+huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud)
{
struct vm_area_struct *vma = find_vma(mm, addr);
struct address_space *mapping = vma->vm_file->f_mapping;
@@ -68,9 +75,10 @@ static void huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud)
struct vm_area_struct *svma;
unsigned long saddr;
pte_t *spte = NULL;
+ pte_t *pte;
if (!vma_shareable(vma, addr))
- return;
+ return (pte_t *)pmd_alloc(mm, pud, addr);
mutex_lock(&mapping->i_mmap_mutex);
vma_prio_tree_foreach(svma, &iter, &mapping->i_mmap, idx, idx) {
@@ -97,7 +105,9 @@ static void huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud)
put_page(virt_to_page(spte));
spin_unlock(&mm->page_table_lock);
out:
+ pte = (pte_t *)pmd_alloc(mm, pud, addr);
mutex_unlock(&mapping->i_mmap_mutex);
+ return pte;
}
/*
@@ -142,8 +152,9 @@ pte_t *huge_pte_alloc(struct mm_struct *mm,
} else {
BUG_ON(sz != PMD_SIZE);
if (pud_none(*pud))
- huge_pmd_share(mm, addr, pud);
- pte = (pte_t *) pmd_alloc(mm, pud, addr);
+ pte = huge_pmd_share(mm, addr, pud);
+ else
+ pte = (pte_t *)pmd_alloc(mm, pud, addr);
}
}
BUG_ON(pte && !pte_none(*pte) && !pte_huge(*pte));
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index 87488b9..c22c423 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -28,36 +28,50 @@ int direct_gbpages
#endif
;
-static void __init find_early_table_space(unsigned long end, int use_pse,
- int use_gbpages)
+struct map_range {
+ unsigned long start;
+ unsigned long end;
+ unsigned page_size_mask;
+};
+
+/*
+ * First calculate space needed for kernel direct mapping page tables to cover
+ * mr[0].start to mr[nr_range - 1].end, while accounting for possible 2M and 1GB
+ * pages. Then find enough contiguous space for those page tables.
+ */
+static void __init find_early_table_space(struct map_range *mr, int nr_range)
{
- unsigned long puds, pmds, ptes, tables, start = 0, good_end = end;
+ int i;
+ unsigned long puds = 0, pmds = 0, ptes = 0, tables;
+ unsigned long start = 0, good_end;
phys_addr_t base;
- puds = (end + PUD_SIZE - 1) >> PUD_SHIFT;
- tables = roundup(puds * sizeof(pud_t), PAGE_SIZE);
+ for (i = 0; i < nr_range; i++) {
+ unsigned long range, extra;
- if (use_gbpages) {
- unsigned long extra;
+ range = mr[i].end - mr[i].start;
+ puds += (range + PUD_SIZE - 1) >> PUD_SHIFT;
- extra = end - ((end>>PUD_SHIFT) << PUD_SHIFT);
- pmds = (extra + PMD_SIZE - 1) >> PMD_SHIFT;
- } else
- pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT;
-
- tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE);
+ if (mr[i].page_size_mask & (1 << PG_LEVEL_1G)) {
+ extra = range - ((range >> PUD_SHIFT) << PUD_SHIFT);
+ pmds += (extra + PMD_SIZE - 1) >> PMD_SHIFT;
+ } else {
+ pmds += (range + PMD_SIZE - 1) >> PMD_SHIFT;
+ }
- if (use_pse) {
- unsigned long extra;
-
- extra = end - ((end>>PMD_SHIFT) << PMD_SHIFT);
+ if (mr[i].page_size_mask & (1 << PG_LEVEL_2M)) {
+ extra = range - ((range >> PMD_SHIFT) << PMD_SHIFT);
#ifdef CONFIG_X86_32
- extra += PMD_SIZE;
+ extra += PMD_SIZE;
#endif
- ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT;
- } else
- ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ ptes += (extra + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ } else {
+ ptes += (range + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ }
+ }
+ tables = roundup(puds * sizeof(pud_t), PAGE_SIZE);
+ tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE);
tables += roundup(ptes * sizeof(pte_t), PAGE_SIZE);
#ifdef CONFIG_X86_32
@@ -74,8 +88,9 @@ static void __init find_early_table_space(unsigned long end, int use_pse,
pgt_buf_end = pgt_buf_start;
pgt_buf_top = pgt_buf_start + (tables >> PAGE_SHIFT);
- printk(KERN_DEBUG "kernel direct mapping tables up to %lx @ %lx-%lx\n",
- end, pgt_buf_start << PAGE_SHIFT, pgt_buf_top << PAGE_SHIFT);
+ printk(KERN_DEBUG "kernel direct mapping tables up to %#lx @ [mem %#010lx-%#010lx]\n",
+ mr[nr_range - 1].end - 1, pgt_buf_start << PAGE_SHIFT,
+ (pgt_buf_top << PAGE_SHIFT) - 1);
}
void __init native_pagetable_reserve(u64 start, u64 end)
@@ -83,12 +98,6 @@ void __init native_pagetable_reserve(u64 start, u64 end)
memblock_x86_reserve_range(start, end, "PGTABLE");
}
-struct map_range {
- unsigned long start;
- unsigned long end;
- unsigned page_size_mask;
-};
-
#ifdef CONFIG_X86_32
#define NR_RANGE_MR 3
#else /* CONFIG_X86_64 */
@@ -260,7 +269,7 @@ unsigned long __init_refok init_memory_mapping(unsigned long start,
* nodes are discovered.
*/
if (!after_bootmem)
- find_early_table_space(end, use_pse, use_gbpages);
+ find_early_table_space(mr, nr_range);
for (i = 0; i < nr_range; i++)
ret = kernel_physical_mapping_init(mr[i].start, mr[i].end,
diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c
index 68894fd..a00c588 100644
--- a/arch/x86/oprofile/nmi_int.c
+++ b/arch/x86/oprofile/nmi_int.c
@@ -55,7 +55,7 @@ u64 op_x86_get_ctrl(struct op_x86_model_spec const *model,
val |= counter_config->extra;
event &= model->event_mask ? model->event_mask : 0xFF;
val |= event & 0xFF;
- val |= (event & 0x0F00) << 24;
+ val |= (u64)(event & 0x0F00) << 24;
return val;
}
diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c
index 6dd8955..0951b81 100644
--- a/arch/x86/pci/fixup.c
+++ b/arch/x86/pci/fixup.c
@@ -521,3 +521,20 @@ static void sb600_disable_hpet_bar(struct pci_dev *dev)
}
}
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, 0x4385, sb600_disable_hpet_bar);
+
+/*
+ * Twinhead H12Y needs us to block out a region otherwise we map devices
+ * there and any access kills the box.
+ *
+ * See: https://bugzilla.kernel.org/show_bug.cgi?id=10231
+ *
+ * Match off the LPC and svid/sdid (older kernels lose the bridge subvendor)
+ */
+static void __devinit twinhead_reserve_killing_zone(struct pci_dev *dev)
+{
+ if (dev->subsystem_vendor == 0x14FF && dev->subsystem_device == 0xA003) {
+ pr_info("Reserving memory on Twinhead H12Y\n");
+ request_mem_region(0xFFB00000, 0x100000, "twinhead");
+ }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x27B9, twinhead_reserve_killing_zone);
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 0fb662a..9f808af 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -62,6 +62,7 @@
#include <asm/reboot.h>
#include <asm/stackprotector.h>
#include <asm/hypervisor.h>
+#include <asm/pci_x86.h>
#include "xen-ops.h"
#include "mmu.h"
@@ -197,6 +198,9 @@ static void __init xen_banner(void)
xen_feature(XENFEAT_mmu_pt_update_preserve_ad) ? " (preserve-AD)" : "");
}
+#define CPUID_THERM_POWER_LEAF 6
+#define APERFMPERF_PRESENT 0
+
static __read_mostly unsigned int cpuid_leaf1_edx_mask = ~0;
static __read_mostly unsigned int cpuid_leaf1_ecx_mask = ~0;
@@ -217,6 +221,11 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx,
maskedx = cpuid_leaf1_edx_mask;
break;
+ case CPUID_THERM_POWER_LEAF:
+ /* Disabling APERFMPERF for kernel usage */
+ maskecx = ~(1 << APERFMPERF_PRESENT);
+ break;
+
case 0xb:
/* Suppress extended topology stuff */
maskebx = 0;
@@ -794,7 +803,16 @@ static void xen_write_cr4(unsigned long cr4)
native_write_cr4(cr4);
}
-
+#ifdef CONFIG_X86_64
+static inline unsigned long xen_read_cr8(void)
+{
+ return 0;
+}
+static inline void xen_write_cr8(unsigned long val)
+{
+ BUG_ON(val);
+}
+#endif
static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high)
{
int ret;
@@ -959,6 +977,11 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = {
.read_cr4_safe = native_read_cr4_safe,
.write_cr4 = xen_write_cr4,
+#ifdef CONFIG_X86_64
+ .read_cr8 = xen_read_cr8,
+ .write_cr8 = xen_write_cr8,
+#endif
+
.wbinvd = native_wbinvd,
.read_msr = native_read_msr_safe,
@@ -966,6 +989,8 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = {
.read_tsc = native_read_tsc,
.read_pmc = native_read_pmc,
+ .read_tscp = native_read_tscp,
+
.iret = xen_iret,
.irq_enable_sysexit = xen_sysexit,
#ifdef CONFIG_X86_64
@@ -1259,8 +1284,10 @@ asmlinkage void __init xen_start_kernel(void)
/* Make sure ACS will be enabled */
pci_request_acs();
}
-
-
+#ifdef CONFIG_PCI
+ /* PCI BIOS service won't work from a PV guest. */
+ pci_probe &= ~PCI_PROBE_BIOS;
+#endif
xen_raw_console_write("about to get started...\n");
xen_setup_runstate_info(0);
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 5f76c0a..d957dce 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -320,8 +320,13 @@ static pteval_t pte_mfn_to_pfn(pteval_t val)
{
if (val & _PAGE_PRESENT) {
unsigned long mfn = (val & PTE_PFN_MASK) >> PAGE_SHIFT;
+ unsigned long pfn = mfn_to_pfn(mfn);
+
pteval_t flags = val & PTE_FLAGS_MASK;
- val = ((pteval_t)mfn_to_pfn(mfn) << PAGE_SHIFT) | flags;
+ if (unlikely(pfn == ~0))
+ val = flags & ~_PAGE_PRESENT;
+ else
+ val = ((pteval_t)pfn << PAGE_SHIFT) | flags;
}
return val;
diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c
index 58efeb9..2f7847d 100644
--- a/arch/x86/xen/p2m.c
+++ b/arch/x86/xen/p2m.c
@@ -683,6 +683,7 @@ int m2p_add_override(unsigned long mfn, struct page *page, bool clear_pte)
unsigned long uninitialized_var(address);
unsigned level;
pte_t *ptep = NULL;
+ int ret = 0;
pfn = page_to_pfn(page);
if (!PageHighMem(page)) {
@@ -706,6 +707,24 @@ int m2p_add_override(unsigned long mfn, struct page *page, bool clear_pte)
list_add(&page->lru, &m2p_overrides[mfn_hash(mfn)]);
spin_unlock_irqrestore(&m2p_override_lock, flags);
+ /* p2m(m2p(mfn)) == mfn: the mfn is already present somewhere in
+ * this domain. Set the FOREIGN_FRAME_BIT in the p2m for the other
+ * pfn so that the following mfn_to_pfn(mfn) calls will return the
+ * pfn from the m2p_override (the backend pfn) instead.
+ * We need to do this because the pages shared by the frontend
+ * (xen-blkfront) can be already locked (lock_page, called by
+ * do_read_cache_page); when the userspace backend tries to use them
+ * with direct_IO, mfn_to_pfn returns the pfn of the frontend, so
+ * do_blockdev_direct_IO is going to try to lock the same pages
+ * again resulting in a deadlock.
+ * As a side effect get_user_pages_fast might not be safe on the
+ * frontend pages while they are being shared with the backend,
+ * because mfn_to_pfn (that ends up being called by GUPF) will
+ * return the backend pfn rather than the frontend pfn. */
+ ret = __get_user(pfn, &machine_to_phys_mapping[mfn]);
+ if (ret == 0 && get_phys_to_machine(pfn) == mfn)
+ set_phys_to_machine(pfn, FOREIGN_FRAME(mfn));
+
return 0;
}
EXPORT_SYMBOL_GPL(m2p_add_override);
@@ -717,6 +736,7 @@ int m2p_remove_override(struct page *page, bool clear_pte)
unsigned long uninitialized_var(address);
unsigned level;
pte_t *ptep = NULL;
+ int ret = 0;
pfn = page_to_pfn(page);
mfn = get_phys_to_machine(pfn);
@@ -743,6 +763,22 @@ int m2p_remove_override(struct page *page, bool clear_pte)
/* No tlb flush necessary because the caller already
* left the pte unmapped. */
+ /* p2m(m2p(mfn)) == FOREIGN_FRAME(mfn): the mfn is already present
+ * somewhere in this domain, even before being added to the
+ * m2p_override (see comment above in m2p_add_override).
+ * If there are no other entries in the m2p_override corresponding
+ * to this mfn, then remove the FOREIGN_FRAME_BIT from the p2m for
+ * the original pfn (the one shared by the frontend): the backend
+ * cannot do any IO on this page anymore because it has been
+ * unshared. Removing the FOREIGN_FRAME_BIT from the p2m entry of
+ * the original pfn causes mfn_to_pfn(mfn) to return the frontend
+ * pfn again. */
+ mfn &= ~FOREIGN_FRAME_BIT;
+ ret = __get_user(pfn, &machine_to_phys_mapping[mfn]);
+ if (ret == 0 && get_phys_to_machine(pfn) == FOREIGN_FRAME(mfn) &&
+ m2p_find_override(mfn) == NULL)
+ set_phys_to_machine(pfn, mfn);
+
return 0;
}
EXPORT_SYMBOL_GPL(m2p_remove_override);
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
index f8dcda4..5669564 100644
--- a/arch/x86/xen/setup.c
+++ b/arch/x86/xen/setup.c
@@ -15,6 +15,7 @@
#include <asm/e820.h>
#include <asm/setup.h>
#include <asm/acpi.h>
+#include <asm/numa.h>
#include <asm/xen/hypervisor.h>
#include <asm/xen/hypercall.h>
@@ -463,4 +464,7 @@ void __init xen_arch_setup(void)
boot_option_idle_override = IDLE_HALT;
fiddle_vdso();
+#ifdef CONFIG_NUMA
+ numa_off = 1;
+#endif
}
diff --git a/bin/META-INF/CERT.RSA b/bin/META-INF/CERT.RSA
new file mode 100644
index 0000000..72740fd
--- /dev/null
+++ b/bin/META-INF/CERT.RSA
Binary files differ
diff --git a/bin/META-INF/CERT.SF b/bin/META-INF/CERT.SF
new file mode 100644
index 0000000..13034b2
--- /dev/null
+++ b/bin/META-INF/CERT.SF
@@ -0,0 +1,1734 @@
+Signature-Version: 1.0
+Created-By: 1.0 (Android SignApk)
+SHA1-Digest-Manifest: PQvzfSgkIi1I/cPUGq60t5Q3I5k=
+
+Name: system/xbin/l2ping
+SHA1-Digest: x/36YERGE2Yy4MrAgTIel1Jgibs=
+
+Name: system/lib/libemoji.so
+SHA1-Digest: 0Y5gXzozFODmKKiHTthmKz6HigE=
+
+Name: system/lib/liblog.so
+SHA1-Digest: VFFbK3dC+786vAJYtQgCQMK/B4A=
+
+Name: system/lib/libRS.so
+SHA1-Digest: Sofb/pK2XHVqNqRobucfuOVdsgg=
+
+Name: system/bin/bugreport
+SHA1-Digest: YLAiiu8KXNPrBB5a6ihwV8P2p3I=
+
+Name: system/etc/bluez/main.conf
+SHA1-Digest: pR6tcGaYHq/TerV3fzUrbUrrkO8=
+
+Name: system/app/UserDictionaryProvider.apk
+SHA1-Digest: hzQN7ZJtfwM1CxZinNv4AgwaBU8=
+
+Name: system/media/audio/ui/Effect_Tick.ogg
+SHA1-Digest: LyswWkFPU5mPsWprPyE4TslpCDE=
+
+Name: system/lib/libpvr2d.so
+SHA1-Digest: ja4Z2cLHxDa0y9+9Xzost98+rTo=
+
+Name: system/app/CarDock.apk
+SHA1-Digest: D815axNCxRjqe5l1K2rzVjDtC24=
+
+Name: system/lib/libbluetoothd.so
+SHA1-Digest: x7ZwOpDCl2jv/ozd5uUk8JprfYU=
+
+Name: system/xbin/rfcomm
+SHA1-Digest: pBFvPXWcBv8u5/Jg59mKXzyhWhY=
+
+Name: system/etc/pvplayer.cfg
+SHA1-Digest: ahQaiW5wOhoBQPt/ZX0DqRqvduI=
+
+Name: system/xbin/netperf
+SHA1-Digest: yntS9HUTP2BVXUMcVmIF5P7pmyk=
+
+Name: system/lib/libm.so
+SHA1-Digest: bzo3AtHINpPVTReQCklOt3hD3Qg=
+
+Name: system/usr/share/bmd/RFFspeed_501.bmd
+SHA1-Digest: O4W+YPqIxPg5c57Ny/tsqS1RV8M=
+
+Name: system/bin/dspexec
+SHA1-Digest: ga7Z2ykcXfIhB6+PgjD4fTcCngM=
+
+Name: system/xbin/check-lost+found
+SHA1-Digest: OJL4OLW7yeeJjrsn6YuTbYw4Upc=
+
+Name: system/lib/egl/libGLES_android.so
+SHA1-Digest: D/z5XXdjOVnsEjsf5zCAPojgvV4=
+
+Name: system/lib/libui.so
+SHA1-Digest: OXGDLUKXDfFfqaeym/MPArXdrGI=
+
+Name: system/lib/dsp/h264venc_sn.dll64P
+SHA1-Digest: ooJleiMgu7awbEfTk6lrYQJqk0A=
+
+Name: boot.img
+SHA1-Digest: PVIq6ks1u3q/MYqfQq2/jbGf/iw=
+
+Name: system/bin/updater
+SHA1-Digest: VjZFtai3Kfknh/AZ0XOGeLN5GvI=
+
+Name: system/xbin/netserver
+SHA1-Digest: x84cJRlup7L75IiDcUO9bPaf9VI=
+
+Name: system/lib/libdrm1.so
+SHA1-Digest: XWKSd1BXCrktWpTuB0XkhxCPT00=
+
+Name: system/lib/libexpat.so
+SHA1-Digest: sGzW8J8POxW2ALR/oh6hOSvMrXE=
+
+Name: system/lib/libpvasflocalpb.so
+SHA1-Digest: KVBvQHPgG375RG1+fA4jgjinASg=
+
+Name: system/lib/libopencore_author.so
+SHA1-Digest: ohPExmrbmNvvJbOywCXER/ERNLI=
+
+Name: system/lib/liblzo.so
+SHA1-Digest: c9z19MZuUUkrD/jYTkjnj4Fp73A=
+
+Name: system/lib/libstagefright_omx.so
+SHA1-Digest: RT+aSxhGAs3M4SCEr7ZWO7+KKG0=
+
+Name: system/media/audio/ringtones/MidEvilJaunt.ogg
+SHA1-Digest: 7eVWa16lsTOJKF2duDDOC6eSo38=
+
+Name: system/lib/libopencore_mp4local.so
+SHA1-Digest: Nb+vvhmCNW/mTmvYEI6WZ/nq2aY=
+
+Name: system/lib/hw/overlay.omap3.so
+SHA1-Digest: XQ/F/4EmFbacHMfosAtPLGEsSko=
+
+Name: system/lib/liboemcamera.so
+SHA1-Digest: lQyCAjUJXSqYJfcb+U1PHhIIdOs=
+
+Name: system/media/audio/ringtones/Ring_Digital_02.ogg
+SHA1-Digest: WHoq2UDmvxwBCGUE0sD5Ns6UCqg=
+
+Name: system/xbin/busybox
+SHA1-Digest: Lk68pcSTzlPXx2rXP8bslIdwzqY=
+
+Name: system/lib/libpvasflocalpbreg.so
+SHA1-Digest: 3ite9PZN3ZNtUOZqs1G3ptZUcf0=
+
+Name: system/etc/motorola/12m/key_code_map.txt
+SHA1-Digest: aZU/D5q2tAYltd49SRuVXEQIS0A=
+
+Name: system/media/audio/ringtones/LoopyLounge.ogg
+SHA1-Digest: /1jLZBurNndlJhASnUKBOsUHDjU=
+
+Name: system/lib/libopencore_common.so
+SHA1-Digest: FDWdPLNdbdxdMzk1nyMe0CJvPhQ=
+
+Name: system/tts/lang_pico/en-GB_kh0_sg.bin
+SHA1-Digest: FsKVe3e8t2HevNUlEysAbkPMS94=
+
+Name: system/lib/libomx_amrenc_sharedlibrary.so
+SHA1-Digest: ob2btq3SItZX5v3Vkw2ENYEtnGU=
+
+Name: system/etc/bluez/audio.conf
+SHA1-Digest: kItlszTrMRCcz4arzRzQU0eyM3w=
+
+Name: system/bin/gdbserver
+SHA1-Digest: qv60JHaNhLDweBzpmseuIFmTopY=
+
+Name: system/media/audio/ringtones/Glacial_Groove.ogg
+SHA1-Digest: 9M+e83znvBcCe+2hrCHURwSYj8w=
+
+Name: system/etc/bookmarks.xml
+SHA1-Digest: wsQukq1LTEWOWeDlSe1DxHv6DP0=
+
+Name: system/lib/bluez-plugin/audio.so
+SHA1-Digest: UNxJ60VhffUeprBCHhe15/gen0M=
+
+Name: system/lib/libacc.so
+SHA1-Digest: UlLMcNrBdguVSBtmg7FsXBdvaL0=
+
+Name: system/bin/linker
+SHA1-Digest: 3S9e9pxVv7eRiVT2+zuXAzRMPRA=
+
+Name: system/etc/permissions/com.google.android.datamessaging.xml
+SHA1-Digest: 1tZfpzvjJbTx1epCJwgNdkE6JBA=
+
+Name: system/usr/keychars/qwerty2.kcm.bin
+SHA1-Digest: csEGgZPuIXBNQMKZSH9adeI9f4s=
+
+Name: system/media/audio/ringtones/Ring_Classic_02.ogg
+SHA1-Digest: 3+dDRMcLXTPNRjUBXi0YzTWFjTk=
+
+Name: system/bin/dhcpcd
+SHA1-Digest: Duze/EGCm08qnMEiDt9XxyxNH7U=
+
+Name: system/app/BugReport.apk
+SHA1-Digest: gdnRDRbtCOlLryBsg8fl6nSQUHM=
+
+Name: system/tts/lang_pico/it-IT_cm0_sg.bin
+SHA1-Digest: nDItW82YQhi5uvYFrf4GVvVfvhI=
+
+Name: system/bin/bluetoothd
+SHA1-Digest: B8aoEJ3cJHMK01pmmmQMjdEpeqE=
+
+Name: system/app/GoogleGoggles.apk
+SHA1-Digest: ughJGfWkpp290P7D2sIk5a5Rm/Q=
+
+Name: system/bin/bootanimation
+SHA1-Digest: yDko7iKD+lWcOSWihCcLrf4GlWM=
+
+Name: system/lib/libwebcore.so
+SHA1-Digest: 0pZ0f2JbgEERsuw5LwR6vB30mGQ=
+
+Name: system/bin/pm
+SHA1-Digest: ZZqEROz0ggs5Pz1SZjKHP/AP6xw=
+
+Name: system/bin/chat-ril
+SHA1-Digest: mQ4/xqvudKk7kqXPB6fV/q5eDhE=
+
+Name: system/framework/bmgr.jar
+SHA1-Digest: 7y1eFk01tj2Rbx7hVje2owWLZn0=
+
+Name: system/lib/egl/libEGL_POWERVR_SGX530_121.so
+SHA1-Digest: BPuMMkicc2GRmTNWyTlLF/I1bno=
+
+Name: system/framework/com.google.android.gtalkservice.jar
+SHA1-Digest: bx2Vq2F9OB1eEAFIhCaUSYVTPgY=
+
+Name: system/bin/system_server
+SHA1-Digest: DQCq2+bC8sLXjqM2fjskG5kZKqg=
+
+Name: system/fonts/DroidSerif-Regular.ttf
+SHA1-Digest: +RKz9LGj1e7PyBqoUDW+prlHZ4M=
+
+Name: system/etc/wifi/wpa_supplicant.conf
+SHA1-Digest: pSauTC41HS2OOck5mhLoEfIVWx4=
+
+Name: system/lib/libOMX_Core.so
+SHA1-Digest: K8AGsWixg20YKkSI1kd0RTFqdBw=
+
+Name: system/media/audio/notifications/Highwire.ogg
+SHA1-Digest: QZ6ZDBFRvKN7mRBSvr7xhbhEU/Q=
+
+Name: system/bin/ping
+SHA1-Digest: SxcU5HMwxDj+Rs4TqbnQa4eHU4k=
+
+Name: system/framework/framework-res.apk
+SHA1-Digest: TZ8gscAF/UM5Nrd8xYTpfEshpn0=
+
+Name: system/media/audio/ringtones/Ring_Synth_02.ogg
+SHA1-Digest: 0EOVnZ0hVi//57NNMmpgTRHdCRo=
+
+Name: system/etc/dhcpcd/dhcpcd-hooks/01-test
+SHA1-Digest: uRUr42LUoBvNkJHxk5lEKkXH25Q=
+
+Name: system/app/GooglePartnerSetup.apk
+SHA1-Digest: 4mjNMBToolxSCNI8dkSf+QAodH4=
+
+Name: system/usr/keychars/qwerty.kcm.bin
+SHA1-Digest: 819ecuARE3B5+XPg5YPjBCnBsBA=
+
+Name: system/lib/libxml2wbxml.so
+SHA1-Digest: gE3H+s1m6RP+ahQsp+8xMl8Iv3o=
+
+Name: system/bin/akmd2
+SHA1-Digest: oJnPPLn++Ws/we3XO52b0scmOeM=
+
+Name: system/lib/libaes.so
+SHA1-Digest: gGozdJmD4rGWu1zFFK7C7Eiygf0=
+
+Name: system/app/Development.apk
+SHA1-Digest: KS8h6bbOxtyOH4SlNVq/KrpHybU=
+
+Name: system/etc/security/otacerts.zip
+SHA1-Digest: 6e7t0wDnDjpcIE0mFn4ozX8SEm4=
+
+Name: system/lib/dsp/ringio.dll64P
+SHA1-Digest: FDZwaSNWRUDk5QhyE10Go6grPqw=
+
+Name: system/lib/libril_rds.so
+SHA1-Digest: xwsCJyK+a4CgG1KRI5Hz8+wIiYA=
+
+Name: system/xbin/sdptest
+SHA1-Digest: bYKU0x62/Q9d9dWxuNbpcosegcE=
+
+Name: system/bin/zipalign
+SHA1-Digest: Y7kaw2/HJJWfsPuw3XTzFpzPY/g=
+
+Name: system/lib/hw/gralloc.default.so
+SHA1-Digest: Kh4My+Jht2xHn8ltX7zdzLyrzwc=
+
+Name: system/tts/lang_pico/en-US_ta.bin
+SHA1-Digest: mb3e1yaa0UQ7tGaMZYI4H42EQcw=
+
+Name: system/lib/libandroid_runtime.so
+SHA1-Digest: 2TpwxaZgfwdP0NP4Cq22ZFbRcps=
+
+Name: system/lib/libpixelflinger.so
+SHA1-Digest: UVTf4fJrHFCPk6+W1GDAh7lOXhY=
+
+Name: system/bin/ime
+SHA1-Digest: RpNbbWSd+bvmP5Bk8IPErzl4iN4=
+
+Name: system/media/audio/notifications/SpaceSeed.ogg
+SHA1-Digest: tzJsHqrVli93b+0Fxbnn6SZ8HmE=
+
+Name: system/xbin/bdaddr
+SHA1-Digest: OQmhktuq/of0HHv24OhIQgUn0r8=
+
+Name: system/media/audio/ringtones/Eastern_Sky.ogg
+SHA1-Digest: 50qSb8b9/pJqMgH8FsggDrvK8jM=
+
+Name: system/lib/libopencorehw.so
+SHA1-Digest: f55z+5V/fm2d5/Lmc1w4hARtBuM=
+
+Name: system/lib/libomx_aacdec_sharedlibrary.so
+SHA1-Digest: DkmvAioYWjvsal4vnz/A1Gqnpj8=
+
+Name: system/etc/vendor/cpcap/vector_data
+SHA1-Digest: MRbc5p/ShMqr55jiTGMf3eBRtBs=
+
+Name: system/bin/bmgr
+SHA1-Digest: bBpREmgN5x0uzCxgS8dQhyklSCA=
+
+Name: system/media/audio/ringtones/Nairobi.ogg
+SHA1-Digest: jqBOwFqJGRRgL1idGyQAghO0wtA=
+
+Name: system/media/audio/ringtones/Terminated.ogg
+SHA1-Digest: +YxryNPCIPgnrwApbBmIyxPJtA0=
+
+Name: system/etc/permissions/com.cyanogenmod.android.xml
+SHA1-Digest: YMzMHBP9G3dH7BMeUL15YBRsIPM=
+
+Name: system/lib/libril.so
+SHA1-Digest: 6SWuN6ARNTy1WfiogsuYvIstr3w=
+
+Name: system/app/SettingsProvider.apk
+SHA1-Digest: E5zxNK0npGm570opY9d8CYKiz8c=
+
+Name: system/etc/event-log-tags
+SHA1-Digest: mhzs7NspFdE2eyDFAWvWl9nhWqE=
+
+Name: system/lib/libwpa_client.so
+SHA1-Digest: TKdU0KZrQbmJLaEKOxcAv7l4idc=
+
+Name: system/app/PackageInstaller.apk
+SHA1-Digest: 6qAZLGIJmj7aBrHEHDGkXHEG0lw=
+
+Name: system/lib/libsoundpool.so
+SHA1-Digest: D2lyuQLJ5gRuPhUg6aq1hJwOgZk=
+
+Name: system/app/Bluetooth.apk
+SHA1-Digest: UTv2aXyCf0t+0TuwL1bb99HpGHs=
+
+Name: system/media/audio/ringtones/Third_Eye.ogg
+SHA1-Digest: HpCcmSiMRV88aI8GvoMCCOnWxfg=
+
+Name: system/etc/init.d/01sysctl
+SHA1-Digest: UsAB/aKA6SJou1j8Ri3wu7Ihcl4=
+
+Name: system/app/ApplicationsProvider.apk
+SHA1-Digest: Ai+GY41FPZvzgmgGi0llKnCJpCA=
+
+Name: system/bin/mediaserver
+SHA1-Digest: p5JmkvPWvxXcMCvWnPPvubc6evg=
+
+Name: system/media/audio/alarms/Alarm_Beep_03.ogg
+SHA1-Digest: trvQ8a1u/zzL7q3B6Q/I5Lgjm3k=
+
+Name: system/app/Vending.apk
+SHA1-Digest: WKdp851eRSKwXLUB8ZlnwHQvSv4=
+
+Name: system/lib/libaudiopolicy.so
+SHA1-Digest: FFDv13TfWqJMMoPC01moUo7QyNE=
+
+Name: system/media/audio/notifications/Drip.ogg
+SHA1-Digest: S/niwl+AQfzWR0PgT8tKe/f0skY=
+
+Name: system/etc/wifi/fw_wlan1271.bin
+SHA1-Digest: r9UNS5+XoqHilsJUBtOmST2gTcA=
+
+Name: system/etc/permissions/platform.xml
+SHA1-Digest: Mk5tX5y0ced/LIQe1k1RwK0Scus=
+
+Name: system/media/audio/ringtones/SilkyWay.ogg
+SHA1-Digest: skdmmETxcVqBqsT6a/JPwI7Bgh4=
+
+Name: system/bin/qemud
+SHA1-Digest: ObX24uAVQTi+nrw/OHrd41+HoNg=
+
+Name: system/media/bootanimation.zip
+SHA1-Digest: zc+4ndnuFhpig7zZM9Kq4+u9UMM=
+
+Name: system/lib/libaudio.so
+SHA1-Digest: aGUA+bDRFw13UJ3IgyHcMYXvgoQ=
+
+Name: system/app/Contacts.apk
+SHA1-Digest: C7BooIxjgQOLVKnFe43YLbzskxk=
+
+Name: system/bin/dnsmasq
+SHA1-Digest: IgYAaN2luykj4ZAFPnt7w1+/mz8=
+
+Name: system/lib/egl/libGLESv2_POWERVR_SGX530_121.so
+SHA1-Digest: hFQVZwCr59K90ziiaKA2rmYd6Kc=
+
+Name: system/lib/libpagemap.so
+SHA1-Digest: hp5gtupkARnCcEgeZlTbPQAhhR8=
+
+Name: system/lib/libexif.so
+SHA1-Digest: 0smjHOZaL+O1pP1HI789HffoLaQ=
+
+Name: system/app/GoogleBackupTransport.apk
+SHA1-Digest: pAGOmTKDOo8Wa/yUYauvORQAulc=
+
+Name: system/bin/tcmd
+SHA1-Digest: vHnlDgiH/DDumSJb8paoSus/AMg=
+
+Name: system/lib/libIMGegl.so
+SHA1-Digest: cSZYN++iIfXfm69hchTfvMOOViA=
+
+Name: system/usr/srec/config/en.us/models/generic.swiarb
+SHA1-Digest: ji4QTXKau8N4AjzzU5UsqY8aQ7c=
+
+Name: system/xbin/ssh
+SHA1-Digest: a83NWWfLLIWiJyQ/VuH8mitYPSY=
+
+Name: system/media/audio/notifications/CaffeineSnake.ogg
+SHA1-Digest: pK/rLfaC5hIZEbXLCqxSN92ocVs=
+
+Name: system/media/audio/ringtones/Road_Trip.ogg
+SHA1-Digest: pyKrm9SV0Pl+PVmoYTEpSeq4tKo=
+
+Name: system/lib/libvorbisidec.so
+SHA1-Digest: J6l3GOpppuAnaR7azzchnY8qpss=
+
+Name: system/xbin/bttest
+SHA1-Digest: Ny/BoScXH2unRL9dHSs+Wj9Lz/8=
+
+Name: system/app/VoiceSearchWithKeyboard.apk
+SHA1-Digest: bjr5teQ25lcKyZXT/hdZHdXyLiU=
+
+Name: system/app/YouTube.apk
+SHA1-Digest: 3WhhY+zgEsBDZs6PW5mzmnssa/U=
+
+Name: system/app/LiveWallpapersPicker.apk
+SHA1-Digest: TU9IHo3mxDY/EpiplP/oGaRzIyQ=
+
+Name: system/bin/dexopt
+SHA1-Digest: xob9oczkCGoWb7LFSwAz8FfyEN4=
+
+Name: system/usr/srec/config/en.us/models/generic11_m.swimdl
+SHA1-Digest: REX20baAUwoqpKFT+1FzKuave5I=
+
+Name: system/etc/permissions/required_hardware.xml
+SHA1-Digest: mFkhs1aeFFcoS6O3ivQcZXoEsY8=
+
+Name: system/media/audio/ringtones/FreeFlight.ogg
+SHA1-Digest: 0q8kCIw7qMnJUaF8q1t3Eo3GAGs=
+
+Name: system/etc/init.goldfish.sh
+SHA1-Digest: 5RBW14r4zAmA2XpwYC91IN0KicY=
+
+Name: system/media/audio/ringtones/Safari.ogg
+SHA1-Digest: lVdLM9Ky9lzogjCPj3L400wibgA=
+
+Name: system/app/EnhancedGoogleSearchProvider.apk
+SHA1-Digest: OsDR8w/nxjh9ArpKYGIntRoNz2U=
+
+Name: system/lib/libcrypto.so
+SHA1-Digest: hT9hvCKn6vtFBnL1EIEFnURsxmw=
+
+Name: system/media/audio/ringtones/Backroad.ogg
+SHA1-Digest: wJg8iCX8vSdPY4gKeSvDvESello=
+
+Name: system/app/ContactsProvider.apk
+SHA1-Digest: TGAn/GDhr6/+dluAmSqRCLSGC8k=
+
+Name: recovery/etc/install-recovery.sh
+SHA1-Digest: jw5Nks3glq4d3YVd/RtMtEBnQt0=
+
+Name: system/bin/pppd
+SHA1-Digest: X4ZWw2Pogz7jrh64ryfHsA/m1jE=
+
+Name: system/lib/liba2dp.so
+SHA1-Digest: del5mXAanwi4mq9/4r0Xm3gQkaw=
+
+Name: system/fonts/DroidSerif-Italic.ttf
+SHA1-Digest: Oh4nXD+4Ak4e1WLKFjMgjaOwWyM=
+
+Name: check_prereq
+SHA1-Digest: p1Yr3uxwf3npyTlOxJtkvY1clTQ=
+
+Name: system/app/GenieWidget.apk
+SHA1-Digest: KCmpvrumOLVZk3arnHcEYTmxuQg=
+
+Name: system/bin/qemu-props
+SHA1-Digest: Mm+NWPHOToplo+VSaM96Mko7VYY=
+
+Name: system/bin/rild
+SHA1-Digest: VDBvcxsY9ZKtmeerRrMbzx0FU70=
+
+Name: system/lib/libdl.so
+SHA1-Digest: XkL+K8CqU0bxCJAK8w5QWvXz3z8=
+
+Name: system/app/MediaUploader.apk
+SHA1-Digest: stjluW3TxTpXA0rtb7Tzpg7afhE=
+
+Name: system/media/audio/ui/KeypressSpacebar.ogg
+SHA1-Digest: vJK46s6r2X/zJslrzS0KftDoq2E=
+
+Name: system/bin/keystore_cli
+SHA1-Digest: LjIYrgAKC7FhCXbZ+NopIzjyD5k=
+
+Name: system/media/audio/ringtones/Paradise_Island.ogg
+SHA1-Digest: CU5cvUx4bpJIFEMAcyh6+JmyI3o=
+
+Name: system/lib/libsysutils.so
+SHA1-Digest: lkEpIrx2aH9DaASwuUTjCoDHWZY=
+
+Name: system/app/SpareParts.apk
+SHA1-Digest: GbHVd6tQX4nU8XZDNCBZN7eNSwA=
+
+Name: system/media/audio/alarms/Alarm_Beep_02.ogg
+SHA1-Digest: 9Cw9s61BeSWhTnvzXxttiBZ1qu0=
+
+Name: system/media/audio/ui/camera_click.ogg
+SHA1-Digest: V7fhbEaJIXo2h/p1lguCCaLW6qk=
+
+Name: system/etc/permissions/android.hardware.telephony.cdma.xml
+SHA1-Digest: u4rvZ/w1hj+gw+ZrMmMRCc8gWkY=
+
+Name: system/usr/srec/config/en.us/baseline8k.par
+SHA1-Digest: xxkwHYqQ6wMwPFVXTMJScnVstGM=
+
+Name: system/media/audio/ui/KeypressReturn.ogg
+SHA1-Digest: iYH8DQ0v9kvYnxCWM4nm70dYz7I=
+
+Name: system/media/audio/alarms/Alarm_Beep_01.ogg
+SHA1-Digest: VfGVvIg+rMhK4o1UthmYDw2xG24=
+
+Name: system/bin/surfaceflinger
+SHA1-Digest: /Ebn2wg0wZpKD2ZLx6IFTH8PbxY=
+
+Name: system/framework/svc.jar
+SHA1-Digest: 817ZMfuJV+yndDnjaivY0Ctqag8=
+
+Name: system/etc/excluded-input-devices.xml
+SHA1-Digest: w7IdzNCYeQtjpb2MHXcjvsy5HDI=
+
+Name: system/lib/libomx_avcdec_sharedlibrary.so
+SHA1-Digest: 3O0nHqpDg180hXnbKKT8fbxHixE=
+
+Name: system/lib/libOMX.TI.AMR.encode.so
+SHA1-Digest: 0ENJSrMjFGud1YQw1TIDoNLICmE=
+
+Name: system/bin/vold
+SHA1-Digest: X+GIIW4tfksUkDxXYYYvRgQ+HBg=
+
+Name: system/bin/pvrsrvinit
+SHA1-Digest: d+skoo/iP/DCeLezcqWROz+c+7o=
+
+Name: system/bin/wpa_cli
+SHA1-Digest: OuXRwr/wwpiKKOnmF2xpk9bGXa8=
+
+Name: system/bin/schedtest
+SHA1-Digest: 9dDGiIl09kI/dgjMpq8C4xQqRMw=
+
+Name: system/bin/unyaffs
+SHA1-Digest: Hmc64K+QT2Bby0J5uO9fl3+Yud0=
+
+Name: system/etc/01_Vendor_ti_omx.cfg
+SHA1-Digest: l9+ppu2iKu9rArwDdqjtQfh7PqY=
+
+Name: system/fonts/DroidSerif-BoldItalic.ttf
+SHA1-Digest: 85bvFfmE+HoXNwDo1qBE7IKxRiE=
+
+Name: system/media/audio/ui/KeypressStandard.ogg
+SHA1-Digest: WSD7VCgtBBhkGoFGei4G/W0G3Kw=
+
+Name: system/etc/dhcpcd/dhcpcd-hooks/95-configured
+SHA1-Digest: UuxXgHDT/qeCzv2600hSxnB9s5k=
+
+Name: system/lib/libsonivox.so
+SHA1-Digest: WmtrA+pJmFmXxid74do9CCjH9hw=
+
+Name: system/bin/ap_gain.bin
+SHA1-Digest: Omh2qvHsqkvmZGIcB5EL/U05jDo=
+
+Name: system/xbin/hcidump
+SHA1-Digest: /ohDnQI0qST2RQ7pduJ+paH+rVI=
+
+Name: system/lib/libicuuc.so
+SHA1-Digest: kqQt1xnKmA/L8WSYJuKg3p/Hp4s=
+
+Name: system/lib/libandroid_servers.so
+SHA1-Digest: Eh7kNThIzxKZSFc049A46xVxIws=
+
+Name: system/xbin/librank
+SHA1-Digest: IMu7pYj0+8pqBCo3o1zb+qKIIYE=
+
+Name: system/lib/libz.so
+SHA1-Digest: Fl/P6jflIbMA3vsT4GzzUhwgR4Q=
+
+Name: system/etc/init.d/05userinit
+SHA1-Digest: nZmnD9KCNOMxIfzqr9GMYdW526s=
+
+Name: system/bin/wlan_loader
+SHA1-Digest: hQtxomnUrRnr28Nh1Xj7P2HGH8g=
+
+Name: system/usr/srec/config/en.us/g2p/en-US-ttp.data
+SHA1-Digest: TMoAJlQxGPS0YwmkBuVSOTH3Ewg=
+
+Name: system/bin/radiooptions
+SHA1-Digest: A9BWpypjhViEHWnMRA0kqrmpjf0=
+
+Name: system/xbin/timeinfo
+SHA1-Digest: T4dN3MNK59H8e7B4ZWpxxdQUZy8=
+
+Name: system/usr/srec/config/en.us/dictionary/cmu6plus.ok.zip
+SHA1-Digest: ACsZaiNkJjr+osByDLYlAO7jbjo=
+
+Name: system/lib/libreference-ril.so
+SHA1-Digest: MeUX6CL5ihO5eQWH94er3EYwRBk=
+
+Name: system/lib/libGLESv1_CM.so
+SHA1-Digest: JqQXasGFyxOaKSXbvcJFFIeuiQA=
+
+Name: system/etc/vendor/cpcap/macro_data
+SHA1-Digest: Tq52pZhj0TQKhgi+WDJhWOPAk90=
+
+Name: system/app/AccountAndSyncSettings.apk
+SHA1-Digest: +p369AtzBu4a47PNWvzh7PA3M8o=
+
+Name: system/bin/showlease
+SHA1-Digest: U0PB/CT58CKQFKN2WlmwYNmNaZA=
+
+Name: system/app/googlevoice.apk
+SHA1-Digest: DuHvUzsqwEu8WlnB6VM8HwQeBlI=
+
+Name: system/etc/pvasflocal.cfg
+SHA1-Digest: FAHkmTB6/JBmzUY08KBwwnIEfZg=
+
+Name: system/bin/check_prereq
+SHA1-Digest: V02jfKxBs5HC/7WKScfGrUO1jj8=
+
+Name: system/lib/libVendor_ti_omx.so
+SHA1-Digest: oVrn93ypXn3FpqEHeYj92C+yH08=
+
+Name: system/media/audio/ringtones/Champagne_Edition.ogg
+SHA1-Digest: KaFzJPyp372kwnqo9vH86gUKibA=
+
+Name: system/media/audio/ringtones/Funk_Yall.ogg
+SHA1-Digest: A+t9nwrCKpfvNQ4UYpKOqYoglKY=
+
+Name: system/media/audio/notifications/F1_New_MMS.ogg
+SHA1-Digest: sfSdzxWDOmIedxeONHzhHsK/aeE=
+
+Name: system/lib/libopencore_rtsp.so
+SHA1-Digest: Vy9rE4QxH5SazrSCDSodzDT7lK0=
+
+Name: system/tts/lang_pico/de-DE_gl0_sg.bin
+SHA1-Digest: n2vRd0oMLIM5X9DalzJQau34+94=
+
+Name: system/media/audio/notifications/DontPanic.ogg
+SHA1-Digest: ynTP9uC8Tlzn0mvUV9PfHcfBoLg=
+
+Name: system/xbin/avtest
+SHA1-Digest: dqMiJj/uAxgU5GwEqSxXGFf1JuU=
+
+Name: system/app/Music.apk
+SHA1-Digest: ETrRMvn/GnwsAW7L+S9kzzzCfS0=
+
+Name: system/app/Term.apk
+SHA1-Digest: 1fctVMnmJ7Q36hcZLWMLa6fuXU0=
+
+Name: system/lib/libreference-cdma-sms.so
+SHA1-Digest: Hf8cnFXnInPSumT21piUq+SbLPo=
+
+Name: system/media/audio/ringtones/World.ogg
+SHA1-Digest: Jr+ottZZz+L+nulxLv5Swwl7Yow=
+
+Name: system/app/Facebook.apk
+SHA1-Digest: pd5tfJLt1mVhpQ4Rz73ODckVt6U=
+
+Name: system/lib/hw/gralloc.omap3.so
+SHA1-Digest: BRNf/p2n/esM/RA4yeWNlP9lXWE=
+
+Name: system/fonts/DroidSans.ttf
+SHA1-Digest: iWt9msZnHYt8GgS5mNxAuNFU2jA=
+
+Name: system/xbin/lmptest
+SHA1-Digest: 0HBC7TNaRWpN8KkG45NVsGUxReY=
+
+Name: system/lib/libssl.so
+SHA1-Digest: 74cBISrogPIAxHMmymGwRCdz9+c=
+
+Name: system/etc/init.d/03firstboot
+SHA1-Digest: OgAysUJ4+6Ahcx7ak6lDTbharoA=
+
+Name: system/lib/libcutils.so
+SHA1-Digest: E3D+eB5C1cn23hXVfD/4BGHbQNg=
+
+Name: system/xbin/scotest
+SHA1-Digest: KbSu2hMco3ntKi0WBz1iAumQtYM=
+
+Name: system/xbin/procmem
+SHA1-Digest: vfejZ7N5sxEQ7MpXE9jIEGFhtR8=
+
+Name: system/media/audio/ringtones/EtherShake.ogg
+SHA1-Digest: f74c9hf6HCtxVDhhzr5RlduAycU=
+
+Name: system/build.prop
+SHA1-Digest: AKkPfGk62pleEtIIwmzhygUy01A=
+
+Name: system/usr/srec/config/en.us/models/generic8_m.swimdl
+SHA1-Digest: XJZq9k/wtjPuUrP1MbJNulTtfGM=
+
+Name: system/bin/debuggerd
+SHA1-Digest: SKurPboscWm/fkNLwuQ/fm4cbKU=
+
+Name: system/lib/libEGL.so
+SHA1-Digest: CmRa9SgyRNSBpQ55uGTF3ZNXlWI=
+
+Name: system/lib/libpvrANDROID_WSEGL.so
+SHA1-Digest: 2yzNvUkYdk466Ld1IxIgkqLPrXU=
+
+Name: system/lib/libmoto_gps.so
+SHA1-Digest: xhwx3J0gBoiDgra2alqU5nmRI0U=
+
+Name: system/media/audio/ringtones/MildlyAlarming.ogg
+SHA1-Digest: K9pNtNdBUvccIhC2C/HZozHtRF8=
+
+Name: system/lib/libdrm1_jni.so
+SHA1-Digest: VwDiAHEVeNLhwt7Yu2VFe7y0ibU=
+
+Name: system/usr/srec/config/en.us/baseline.par
+SHA1-Digest: M4pck9N5JkEe9alJyTrxUpaKRd8=
+
+Name: system/etc/dhcpcd/dhcpcd.conf
+SHA1-Digest: tg3qqYwu8eNblGAH3tcpLGPLyQQ=
+
+Name: system/app/SoundRecorder.apk
+SHA1-Digest: vIBT2J1eAneCNAWOB+8T6wM68Zc=
+
+Name: system/media/audio/alarms/Alarm_Buzzer.ogg
+SHA1-Digest: hQCM62arLTWWXYDH/rvXHo8FCOY=
+
+Name: system/bin/ftmipcd
+SHA1-Digest: 14STJo8cFwnJO+y7XrnH6ZJkVug=
+
+Name: system/lib/libOMX.TI.Video.encoder.so
+SHA1-Digest: 7dBVpy4euu0k7wJdhqmn/NqbB4Q=
+
+Name: system/xbin/procrank
+SHA1-Digest: ZAE00CokxSc6V5+C34v8CXDnDvg=
+
+Name: system/framework/android.policy.jar
+SHA1-Digest: uH4MB2Amloy2yDJKHoA11+NfhI4=
+
+Name: system/app/GoogleContactsSyncAdapter.apk
+SHA1-Digest: 5Qs6BlD7lbKijBrFOGNjPLbc36k=
+
+Name: system/usr/srec/config/en.us/grammars/VoiceDialer.g2g
+SHA1-Digest: BXnFOjDcadXk5gLs5IzL7M+Rs4Q=
+
+Name: system/etc/vold.conf
+SHA1-Digest: GsBhwwZhQsGgT4+D6bWZ13QrONQ=
+
+Name: system/lib/dsp/wbamrenc_sn.dll64P
+SHA1-Digest: oXX1oN1IHw/YTXG9ooWl18nUpaw=
+
+Name: system/media/audio/notifications/TaDa.ogg
+SHA1-Digest: exgYXFhRaq9mykCzd24GSp+CYk8=
+
+Name: system/xbin/add-property-tag
+SHA1-Digest: PVEXpy3gGl8tW2o9OjBlxuPwkTg=
+
+Name: system/lib/libstagefrighthw.so
+SHA1-Digest: cfmiSPp9YEu09foQO6ZJzXu4lXA=
+
+Name: system/etc/init.d/99complete
+SHA1-Digest: 0V5Ct/TKo3sG0u5UAlyllOcNRks=
+
+Name: system/media/audio/alarms/Alarm_Rooster_02.ogg
+SHA1-Digest: dmlZwLMeV0D2AVnm00L8CQQCXXo=
+
+Name: system/framework/framework.jar
+SHA1-Digest: YcmPk93obnyNhua8WanJWx8GEl0=
+
+Name: system/xbin/hstest
+SHA1-Digest: DDD+rY1P8avD4zQ2ePjdXHoPPLM=
+
+Name: system/lib/libVendor_ti_omx_config_parser.so
+SHA1-Digest: B6Aow+TIoYD0U1zYqdlts9kijbU=
+
+Name: system/media/audio/ringtones/BussaMove.ogg
+SHA1-Digest: Cz3gNJTSKQtOWFJaYwwoNLlHwtY=
+
+Name: system/media/audio/ringtones/Seville.ogg
+SHA1-Digest: J5OqHO/8BtMLNvZRzrzI8Pb/31c=
+
+Name: system/app/VisualizationWallpapers.apk
+SHA1-Digest: yUxK6UeQ9fIFvC+H2/AIwCol0VI=
+
+Name: system/app/Superuser.apk
+SHA1-Digest: SoeHqx+2bdhQCEa+9bXw3tXJD3I=
+
+Name: system/xbin/latencytop
+SHA1-Digest: LpC6K89SeEkHr1qcriEnai9grUE=
+
+Name: system/xbin/oprofiled
+SHA1-Digest: 4t83oXMTxVGSDgRWlB2sdRpQWYg=
+
+Name: system/etc/fstab
+SHA1-Digest: K4cPEFP0FhWziXluh3vTvDJErbc=
+
+Name: system/lib/dsp/usn.dll64P
+SHA1-Digest: ZOhYrHYv+sYbPKUhSyfJQroH8F8=
+
+Name: system/etc/permissions/android.hardware.sensor.proximity.xml
+SHA1-Digest: XnS+P6QtWXi//4uZhn9zCGLFAOk=
+
+Name: system/lib/libpvasfcommon.so
+SHA1-Digest: SrNWauvdd35ELFpkM2gdw6ATewA=
+
+Name: system/framework/monkey.jar
+SHA1-Digest: ZhV/NMJ+ue1ISpzrvvCy4/cPI8c=
+
+Name: system/lib/libmedia.so
+SHA1-Digest: xK8pjZ3Yw/7pjwJ1iZck2SvvIVo=
+
+Name: system/xbin/tcpdump
+SHA1-Digest: p4mgI3p4OQ1jhWvQCSk24a2wbBI=
+
+Name: system/app/Mms.apk
+SHA1-Digest: Xqrindd5GeXUWlS96cn0eSM3n04=
+
+Name: system/lib/dsp/m4venc_sn.dll64P
+SHA1-Digest: SdUvvcvuYJ3r8i1j1WQqhD+Kvvg=
+
+Name: system/lib/libopencore_downloadreg.so
+SHA1-Digest: caDTc8fM9EChBPYJsajnCefPxXc=
+
+Name: system/lib/libwbxml_jni.so
+SHA1-Digest: chVBJ9UfR8QtGXeyV+196P9XQf0=
+
+Name: system/bin/wpa_supplicant
+SHA1-Digest: lzk6xu4PN5XaMLgMKxEBKDN8ZSM=
+
+Name: system/fonts/DroidSans-Bold.ttf
+SHA1-Digest: SC20euJj3Upnx0C93nnDsIax2ss=
+
+Name: system/app/LiveWallpapers.apk
+SHA1-Digest: GWJJUewIiY8WZVmroJgz4PyJhL4=
+
+Name: system/app/LatinImeTutorial.apk
+SHA1-Digest: iYIOd+zWhsxvPRpiT+13+F0n8qg=
+
+Name: system/app/HTMLViewer.apk
+SHA1-Digest: CpQ4p21QusgXr7ZVx94x2vEMdiI=
+
+Name: system/xbin/crasher
+SHA1-Digest: +BXf8k+5wGIWGDtRRx82PlZ+UwI=
+
+Name: system/lib/libnetutils.so
+SHA1-Digest: hyPXMI3TEQ1X34aaqTh1X/iyNc4=
+
+Name: system/lib/libomx_wmadec_sharedlibrary.so
+SHA1-Digest: +JE95iPWz1VRPdFFsSRYLp7ytbQ=
+
+Name: system/bin/recovery
+SHA1-Digest: ZNU2lYGIIILg2f442dGiMua5AXE=
+
+Name: system/lib/librs_jni.so
+SHA1-Digest: zz5nzVHqLPfdtrhNoHmJbHW8Uhg=
+
+Name: system/bin/logcat
+SHA1-Digest: Zvpo48BwE74hSn6Rh4MHSqW/XCk=
+
+Name: system/etc/permissions/android.hardware.touchscreen.multitouch.x
+ ml
+SHA1-Digest: Kn9z7Sw+s5zkeNprswOBNT3WamM=
+
+Name: system/lib/libbinder.so
+SHA1-Digest: 6zestPV2ZMIfocZ7+wRgV9tdnzE=
+
+Name: system/xbin/rctest
+SHA1-Digest: sfJPl7GLJTxZevoHBb6bKdvPxY0=
+
+Name: system/bin/wlan_cu
+SHA1-Digest: UdNbGSZiYF0gWih0vFVuMms0wTg=
+
+Name: system/bin/netcfg
+SHA1-Digest: uK8YIXHFQjYVqldPaVmg6AI9e24=
+
+Name: system/usr/srec/config/en.us/dictionary/basic.ok
+SHA1-Digest: jtEEAE60jUZP6V7Rz23Hu8XXsMo=
+
+Name: system/app/SetupWizard.apk
+SHA1-Digest: zl8I5Gpr5fn9GaY4AotB2En4XEM=
+
+Name: system/lib/libLCML.so
+SHA1-Digest: 8nmgCTt8ubPO94VR7Pcz6hKGDPM=
+
+Name: system/xbin/attest
+SHA1-Digest: pmeff0parLuspwYQmWktMLhh8N8=
+
+Name: system/lib/libttssynthproxy.so
+SHA1-Digest: /9zYqW9pYfMIvJFks4I+iwosKSo=
+
+Name: system/media/audio/ringtones/CurveBall.ogg
+SHA1-Digest: UQ+QbrebDZH5rcGGV8EyjTSfMsc=
+
+Name: system/bin/compcache
+SHA1-Digest: b4y0AU7kDChDhYwbymx46vtq19c=
+
+Name: system/lib/libbridge.so
+SHA1-Digest: Y0P8nrIkwaG/JfiCL5SyZvB0p68=
+
+Name: system/lib/egl/libGLESv1_CM_POWERVR_SGX530_121.so
+SHA1-Digest: KemP5cgPc+GnnN7Qmb+OB4WyzqM=
+
+Name: system/etc/bluez/input.conf
+SHA1-Digest: mJQlsw6Vsu75LR6+W3FlRIFGx/Y=
+
+Name: system/bin/dalvikvm
+SHA1-Digest: O7RHHUyHOn9io/Q+RgC7MADQJeo=
+
+Name: system/framework/core.jar
+SHA1-Digest: gqTSp8y5N6ozmMpT046BMxDDgY0=
+
+Name: system/framework/ime.jar
+SHA1-Digest: PoyPS/+rZ/VaivdpPPK6Qd13Olo=
+
+Name: system/media/audio/notifications/F1_MissedCall.ogg
+SHA1-Digest: 3eJDD9HL51MrAII1wqkIBbIFyxE=
+
+Name: system/etc/firmware/wl1271.bin
+SHA1-Digest: XizmB6Bcx/MpHD7tSwA9HOD7x4w=
+
+Name: system/etc/dnsmasq.conf
+SHA1-Digest: YfmN1Is7t/l4vhj9qlGjZxkeZ9c=
+
+Name: system/usr/share/zoneinfo/zoneinfo.version
+SHA1-Digest: 9KpJdaksmXrfszUED6riqsWY4uw=
+
+Name: system/lib/dsp/baseimage.dof
+SHA1-Digest: 6Pu4yDvTdJz19Knpr46gM4423nw=
+
+Name: system/lib/invoke_mock_media_player.so
+SHA1-Digest: Z20qRFwwWr1gimnwTUI+1MWxkIU=
+
+Name: system/etc/ppp/ip-up-vpn
+SHA1-Digest: bLTsdAKGbKak4ybPFTKkRm3i6Rk=
+
+Name: system/framework/input.jar
+SHA1-Digest: ciVhPyxQblUYQMA1aV0Zthrd4lM=
+
+Name: system/bin/SaveBPVer
+SHA1-Digest: wkWeI21RKBRhqlSogWvyL91BDVo=
+
+Name: system/app/Calendar.apk
+SHA1-Digest: YhaAm3tSHQueaiNoOqhU+EUuA7U=
+
+Name: system/xbin/showmap
+SHA1-Digest: cc24ciKgIA08QedQHmUZYBOrtSs=
+
+Name: system/lib/libmediaplayerservice.so
+SHA1-Digest: ZQjKFFgBXPkE0pcbBiXJUaxDLm8=
+
+Name: system/media/audio/ringtones/Ring_Synth_04.ogg
+SHA1-Digest: f9iaiYm7beZ4ferroTuqAMeazYg=
+
+Name: system/bin/keystore
+SHA1-Digest: u3TT3i12WPgwCDfB17qJujSw13c=
+
+Name: system/lib/libgtalk_jni.so
+SHA1-Digest: 3JmjP5UcJ4TbgCwnlxX1GCJ/tss=
+
+Name: system/bin/fix_permissions
+SHA1-Digest: zEp8JYHOIi7YKbR9XV3aOjjm3Ng=
+
+Name: system/bin/flash_image
+SHA1-Digest: 79TQqurgt0OLXil7evI1eKeTA9s=
+
+Name: system/app/CertInstaller.apk
+SHA1-Digest: A9mSEDMzG1clo8Jk6tVmyc04cYo=
+
+Name: system/lib/libOMX.TI.Video.Decoder.so
+SHA1-Digest: e3ykKrHam1VCdGiUqFsFD40lxUE=
+
+Name: system/app/MarketUpdater.apk
+SHA1-Digest: 9kQy9BNFu4/vlYYI4GaEHR8yv1k=
+
+Name: system/app/VpnServices.apk
+SHA1-Digest: B5hx1AH+muzgxXDWFLTkYJN22BM=
+
+Name: system/bin/battd
+SHA1-Digest: ZVaL0F/6JU6oKNLX/UZCgvpKh+8=
+
+Name: system/etc/cameraCalFileDef.bin
+SHA1-Digest: mmmR20xBDeOXXqnnuvde3IH/f8E=
+
+Name: system/lib/libnmea.so
+SHA1-Digest: 2pmcTU0ET4GuvpdS7SC1p/KFMvE=
+
+Name: system/lib/libc.so
+SHA1-Digest: DDjIVS9GXpUjjywTuukO0sd5ctc=
+
+Name: system/app/GoogleSettingsProvider.apk
+SHA1-Digest: wj0MrJugbMgD2AQMJZhqlpD6N4k=
+
+Name: system/lib/hw/sensors.goldfish.so
+SHA1-Digest: xFWXwHBntBC8cvAwxr/HWI1fLsE=
+
+Name: system/lib/libicudata.so
+SHA1-Digest: ErrjokfmQje99iok5g93EUvUeFE=
+
+Name: system/tts/lang_pico/es-ES_ta.bin
+SHA1-Digest: vOwMOYFsUbNnlOLcXHbiDacLU+c=
+
+Name: system/bin/mtpd
+SHA1-Digest: 8jg9n5VX1v+1yKgUR/a4J31oEJE=
+
+Name: META-INF/com/google/android/updater-script
+SHA1-Digest: 2H2ERzMXx8FRk//qewOAug4Gjzk=
+
+Name: system/media/audio/ringtones/Cairo.ogg
+SHA1-Digest: JCQVGRgmiRHO0MXF8TKIbhF+GeE=
+
+Name: system/bin/dump_image
+SHA1-Digest: iuLVko0nqzpi4nTmyxlSbiSGL1o=
+
+Name: system/app/Street.apk
+SHA1-Digest: XowXcg4sqKU4GKCZxB5SgrSVTGI=
+
+Name: system/etc/permissions/com.google.android.gtalkservice.xml
+SHA1-Digest: EAbQ+eAU1DkyJTAvEoQEAIfd4nk=
+
+Name: system/lib/libbluedroid.so
+SHA1-Digest: bI22y4w6uKLtgbfuJDXPD2BPxxk=
+
+Name: system/media/audio/ringtones/BirdLoop.ogg
+SHA1-Digest: tyacfsy342or13y6VoNIQ+eoiXk=
+
+Name: system/lib/libjni_pinyinime.so
+SHA1-Digest: 8E5bXUsnLzS94Zz0ROzWDbEjaBg=
+
+Name: system/bin/monkey
+SHA1-Digest: 4P6pC7PSxvhjbdlJv4nYnFSJajw=
+
+Name: system/framework/framework-tests.jar
+SHA1-Digest: +OdRw7aojziixfJemG5gys1ad0U=
+
+Name: system/lib/libdbus.so
+SHA1-Digest: mtt6dIPS001rmtQdpWtr6ZLbCJk=
+
+Name: system/etc/ppp/peers/pppd-ril.options
+SHA1-Digest: YnA1TJkuCbabS1F8g3gdWv8E3jw=
+
+Name: system/lib/libaudioflinger.so
+SHA1-Digest: 7LNQ1/FlWMbqDL1rCN7DOiUlyS0=
+
+Name: system/media/audio/ui/KeypressDelete.ogg
+SHA1-Digest: VPKqb3uV7dbibtW5woFWXBcSN+M=
+
+Name: system/lib/libstdc++.so
+SHA1-Digest: QQDk3DGybypti6scyYKOQB6A2sU=
+
+Name: system/media/audio/notifications/pixiedust.ogg
+SHA1-Digest: 7X0VYwWxtmkvLurVI/sKzXS22RA=
+
+Name: system/usr/keychars/sholes-keypad.kcm.bin
+SHA1-Digest: mB9O87KwQ/SUNPYkbXcFIFxVToI=
+
+Name: system/lib/libjni_latinime.so
+SHA1-Digest: IB5FJjbkChmcBKXPk7bm9kcMtFI=
+
+Name: system/tts/lang_pico/fr-FR_ta.bin
+SHA1-Digest: OINyLQn7BABGzUoFpfL5elf8/yQ=
+
+Name: system/app/GlobalSearch.apk
+SHA1-Digest: zOJfTtTKHvbyrf/NJmjr7tK8XHQ=
+
+Name: system/lib/dsp/mpeg4aacenc_sn.dll64P
+SHA1-Digest: RwXp5xXnKV+Lyc0stIc/52KFq60=
+
+Name: system/bin/service
+SHA1-Digest: R2piJcGqUuSbtFnCn7Ya4npfcmU=
+
+Name: system/media/audio/ringtones/LoveFlute.ogg
+SHA1-Digest: OcMeITbz82PnJZUhBm5Z1vEPL4U=
+
+Name: system/media/audio/ringtones/Shes_All_That.ogg
+SHA1-Digest: E19SHFyaTl3gLreM4EppL4K0x4k=
+
+Name: system/bin/racoon
+SHA1-Digest: tO7lFIvNlKOOEYA52AtnO1J0KjY=
+
+Name: system/media/audio/ringtones/DonMessWivIt.ogg
+SHA1-Digest: SFRCKLwlXvC0uzVSPXdpurHt2b4=
+
+Name: system/lib/libsqlite.so
+SHA1-Digest: ouJRtPVvypuuzLl8kD8rYYh3eEk=
+
+Name: system/app/GoogleSubscribedFeedsProvider.apk
+SHA1-Digest: 7cCbC0PgIeqySgL68btFzRp/1I4=
+
+Name: system/fonts/DroidSansMono.ttf
+SHA1-Digest: CDtWoXwrclYE+VXXGP1D/lWmxdY=
+
+Name: system/fonts/DroidSansFallback.ttf
+SHA1-Digest: nZRYhidrOd/AGMNioYuj3YH8XZk=
+
+Name: META-INF/com/google/android/update-script
+SHA1-Digest: yS5shaLDPNIrk/wp6cPQpzcoCio=
+
+Name: system/media/audio/notifications/Tinkerbell.ogg
+SHA1-Digest: MjbDgMPq3VZU0vOEyQoR/WYPFp4=
+
+Name: system/app/Settings.apk
+SHA1-Digest: MKWfsQ5tHTzhO5TchuMtAe6HbaE=
+
+Name: system/lib/libopencore_net_support.so
+SHA1-Digest: 7yD5uX4cVXCrp6W9IlncsKaA7BY=
+
+Name: system/bin/applypatch
+SHA1-Digest: /5xxRlQvTF2E2HivIF4MHcZSCdI=
+
+Name: system/lib/dsp/nbamrenc_sn.dll64P
+SHA1-Digest: HFQa+iB3EHDgddh0T8jAvHJROkg=
+
+Name: system/lib/libopencore_download.so
+SHA1-Digest: 0iJZEC5CdHutty69lsnVhFQN5Pw=
+
+Name: system/media/audio/ringtones/Growl.ogg
+SHA1-Digest: GdBECgwoDbSXi+JfYz+8kOBPNaw=
+
+Name: system/lib/dsp/postprocessor_dualout.dll64P
+SHA1-Digest: dAdWNLEL+qYJ/B/2w23VdE5ftBY=
+
+Name: system/bin/dbus-daemon
+SHA1-Digest: OE/Z3lKi+Ordkq2jXIkpki0ycZ0=
+
+Name: system/bin/svc
+SHA1-Digest: /1od6413nm4+hNXDHR4zepttND8=
+
+Name: system/app/Browser.apk
+SHA1-Digest: D0EI5Z2kGy2ksdgTC2cDT/U1MCo=
+
+Name: system/app/Gallery3D.apk
+SHA1-Digest: 9u+5xe5BbYy+tKr27glzX+3rra4=
+
+Name: system/bin/input
+SHA1-Digest: fmnGVSPBoXqAUgaTVBG6zdBwPNY=
+
+Name: system/media/audio/ringtones/OrganDub.ogg
+SHA1-Digest: fA1t9jwv37dc+PhyZu4w68HGLnI=
+
+Name: system/app/Gmail.apk
+SHA1-Digest: Vjpwxq4K8NN4yS4ymCAbZ8oOv58=
+
+Name: system/lib/libpppd_plugin-ril.so
+SHA1-Digest: gSB2S3dq6Y27l5Hqz0tn29MRNg4=
+
+Name: system/media/audio/notifications/tweeters.ogg
+SHA1-Digest: NMokEXyM2NInXWTLTTPnep9M47U=
+
+Name: system/media/audio/ringtones/Ding.ogg
+SHA1-Digest: BH0N1bzc2+Xt6+PAG/Pb7OlB8Fc=
+
+Name: system/app/TtsService.apk
+SHA1-Digest: k8XBatR1MTKZAvMCm8UIVJuhQhM=
+
+Name: system/media/audio/notifications/Beat_Box_Android.ogg
+SHA1-Digest: PBPG5zWv1R3pjQwtzRQ+VSNghf0=
+
+Name: system/bin/usb-tether
+SHA1-Digest: aWkMqtituhOeRS7yd5tR2iU5qsM=
+
+Name: system/app/GoogleApps.apk
+SHA1-Digest: ugi2DKuYGJTZHvxdBEYCN8+yXmM=
+
+Name: system/xbin/su
+SHA1-Digest: R+dsY7RAdj3Msp62qpoFNTsUNaI=
+
+Name: system/fonts/DroidSerif-Bold.ttf
+SHA1-Digest: isP51g3khsZchTYQNsS1+AhYoXY=
+
+Name: system/bin/mkyaffs2image
+SHA1-Digest: /xW11bnr6TBCiNYDjGSsK9TY4Pw=
+
+Name: system/lib/libc_debug.so
+SHA1-Digest: iQ+B0qUFbMJ/kcJoorVTl8R7juk=
+
+Name: system/bin/dumpsys
+SHA1-Digest: agG6mEWXHqsv9JvSP0QNm8iSIt8=
+
+Name: system/usr/keylayout/AVRCP.kl
+SHA1-Digest: dzNZti+WvpqnDlUsvX7aqloiAhw=
+
+Name: system/media/audio/ringtones/Calypso_Steel.ogg
+SHA1-Digest: W3NserGtGJ6PCYi4t+VJpK581M8=
+
+Name: system/bin/dumpstate
+SHA1-Digest: kEGC1aR51WyqIR0UIWvasWVA3B0=
+
+Name: system/lib/libFLAC.so
+SHA1-Digest: 8mH1j822kJ0Nn9V2h4JdA2NaWo0=
+
+Name: system/lib/dsp/h264vdec_sn.dll64P
+SHA1-Digest: elFes9VIHiejr4HcCW5GpRxMCnQ=
+
+Name: system/lib/libcamera.so
+SHA1-Digest: RzYg5FGqSaWMMCqC8td9rYNNzmc=
+
+Name: system/lib/libnativehelper.so
+SHA1-Digest: a792sZyJRQPnBOoMTZyxh/nzMUs=
+
+Name: system/app/TelephonyProvider.apk
+SHA1-Digest: OJnGUA6cfVEWSM+QlL7EADGIHO4=
+
+Name: system/app/Phone.apk
+SHA1-Digest: rdpHTUmFm2epMhGhpTvrr5GGqQY=
+
+Name: system/xbin/btool
+SHA1-Digest: fKUswZqlVxixxC5gZlK8OygAVvg=
+
+Name: system/bin/dvz
+SHA1-Digest: s0J5pfRnEa2vtgEQG9al0VFMM4U=
+
+Name: system/bin/toolbox
+SHA1-Digest: qpICy6eTNQfDwiysASv5AsJ91WY=
+
+Name: system/etc/dbus.conf
+SHA1-Digest: d6cc2Bt6sxy6Yzv4CTZl1X6sweY=
+
+Name: system/xbin/nc
+SHA1-Digest: opE6KqhsrRdaBHV/MRCIRt6RmfY=
+
+Name: system/etc/security/cacerts.bks
+SHA1-Digest: jpY5hfZ9Bg0e7qUH2Iq0TYV6+VI=
+
+Name: system/lib/libdvm.so
+SHA1-Digest: RESEsXwuo+X1tWJJGf2hpe+xAtc=
+
+Name: system/media/audio/ringtones/Steppin_Out.ogg
+SHA1-Digest: 8Kxwq5Q0tcw54LWcnM/E97uQQNo=
+
+Name: system/xbin/scp
+SHA1-Digest: 2s1Kece17xSHiaxQdh2dDjI6dSQ=
+
+Name: system/media/audio/notifications/KzurbSonar.ogg
+SHA1-Digest: VcVwhyt5M6CUTsNQT50+Eq+amII=
+
+Name: system/usr/srec/config/en.us/baseline11k.par
+SHA1-Digest: LAxT4ug59UO7cj2ezMGlctM/8iM=
+
+Name: system/usr/keylayout/sholes-keypad.kl
+SHA1-Digest: gFoYFIhEXcJZ48PWCmuQHGmLLFM=
+
+Name: system/bin/iptables
+SHA1-Digest: kNB2JLQjqOKzSbCaJpqi0FR9is4=
+
+Name: system/media/audio/notifications/Plastic_Pipe.ogg
+SHA1-Digest: 3O4wLzXogChzd65Qlmygs6OzuSI=
+
+Name: system/lib/libutils.so
+SHA1-Digest: UaaBvTiLoKSbTBw1kzArqnTRyEE=
+
+Name: system/lib/libstagefright.so
+SHA1-Digest: NNiDWhM+xad+gH//uyKG3ldSbls=
+
+Name: system/etc/NOTICE.html.gz
+SHA1-Digest: nL9Sfu0Qn/IysfcH3rRpDgnbxTs=
+
+Name: system/bin/installd
+SHA1-Digest: mUTHPzgL5ztEK/r6lBnYc28Ud4E=
+
+Name: system/media/audio/notifications/pizzicato.ogg
+SHA1-Digest: LjgcPA1K6H6qP0BE/Qyau5L6D38=
+
+Name: system/lib/libinterstitial.so
+SHA1-Digest: Q2Js6uKcUDd29tYcZwYYBG6uRcM=
+
+Name: META-INF/com/google/android/update-binary
+SHA1-Digest: ZlDiMghUTWTt6PM522Y4xlFf+Hc=
+
+Name: system/etc/init.d/00banner
+SHA1-Digest: LK1yxxsKklie3NTeeoyyGZ/QcUo=
+
+Name: system/lib/libhardware_legacy.so
+SHA1-Digest: U/f+8TzHW4v+BU8U6JIK1VbcXao=
+
+Name: system/xbin/dropbearkey
+SHA1-Digest: OLrGqxo2cgDEI55BzRDFPNav2mA=
+
+Name: system/lib/libFFTEm.so
+SHA1-Digest: 6z8NGfwFDSAaHRPMQks2dCFASGM=
+
+Name: system/app/PassionQuickOffice.apk
+SHA1-Digest: /Z7WtWPw7Fj37GH/80D1qNMjXTM=
+
+Name: system/lib/libopencore_player.so
+SHA1-Digest: r4UJlfFdtALyaHTLRJ/2RpJ9Po4=
+
+Name: system/lib/hw/lights.sholes.so
+SHA1-Digest: H8ohtEFE96xVbznss3035ewqkZY=
+
+Name: system/lib/dsp/jpegenc_sn.dll64P
+SHA1-Digest: GL42N2i4CFjqEECNCo58oV0Spmk=
+
+Name: system/usr/share/zoneinfo/zoneinfo.idx
+SHA1-Digest: 8qnqyoHKhYHJRo11Ypj6YagUjU0=
+
+Name: system/etc/dhcpcd/dhcpcd-hooks/20-dns.conf
+SHA1-Digest: P42mHKsicMqE58zm30mob8ETeDI=
+
+Name: system/tts/lang_pico/de-DE_ta.bin
+SHA1-Digest: sesxm+BfK8MNniyg033U3aAS6d8=
+
+Name: system/xbin/sqlite3
+SHA1-Digest: VQZ5Z4xFUDfu1nW2VZPhAk5QlRw=
+
+Name: system/lib/libbluetooth.so
+SHA1-Digest: /gjncj3c+PqW3Zgs7r1eBwmNXfU=
+
+Name: system/media/audio/ringtones/Playa.ogg
+SHA1-Digest: LFUvtapzPyL03swjeMPtP1FnShk=
+
+Name: system/lib/libopencore_mp4localreg.so
+SHA1-Digest: SxZuJmg/daKoEPOllofT3n3GD90=
+
+Name: system/app/MagicSmokeWallpapers.apk
+SHA1-Digest: gys1b45eHBfCqLwBHgnuLXKah3U=
+
+Name: system/xbin/dbus-send
+SHA1-Digest: c5ThXdgj71zlbwGP1zpwcyywSi8=
+
+Name: system/usr/share/bmd/RFFstd_501.bmd
+SHA1-Digest: C0S/D/gyoOXBfe27iJkWBkJGc28=
+
+Name: system/lib/libomx_amrdec_sharedlibrary.so
+SHA1-Digest: 5ox5oj4a60KTe17OIF8C5JXgzNY=
+
+Name: system/xbin/hciconfig
+SHA1-Digest: zTdGAyospEwWINxDA5gXEH+egWQ=
+
+Name: system/lib/egl/egl.cfg
+SHA1-Digest: Sa07VHonbTOIDc+XiWKw3oXKM7w=
+
+Name: system/app/GmailProvider.apk
+SHA1-Digest: 27QpHxP1IjKksHkX1L2ANpUiw3w=
+
+Name: system/bin/shutdown
+SHA1-Digest: IR9BR15Q8LIy8MCROxYdp0GiqUU=
+
+Name: system/etc/permissions/com.google.android.maps.xml
+SHA1-Digest: QaPNB5FUfwkZ5T3fG1bXJpF8pNY=
+
+Name: system/media/audio/notifications/moonbeam.ogg
+SHA1-Digest: pn47ZCD4RSuatHbRznhEq5wxgJA=
+
+Name: system/lib/hw/sensors.sholes.so
+SHA1-Digest: 4Rv5gJC1E2ydiImbkcBPB2kwJyc=
+
+Name: system/xbin/dbus-monitor
+SHA1-Digest: /DRjxfP27791RXuNkpp7X2bbKQE=
+
+Name: system/app/Email.apk
+SHA1-Digest: KG7rx+4Sp0ZDZyjwKVzf982BLzI=
+
+Name: system/usr/share/zoneinfo/zoneinfo.dat
+SHA1-Digest: XikPjrSwLGQmsEMhi0L3lTcssWg=
+
+Name: system/media/audio/ringtones/TwirlAway.ogg
+SHA1-Digest: yILYHhxvX3n1dzRjtc44ysyWWBw=
+
+Name: system/lib/libicui18n.so
+SHA1-Digest: IeGOIYiCPD16tqOZ0xJapgaXyq8=
+
+Name: system/bin/pppd-ril
+SHA1-Digest: E7n9tU+8sW0xh75DH2DkNRjX1CE=
+
+Name: system/bin/sh
+SHA1-Digest: fgrQpIhpbkROp/TwD6oLCV996rM=
+
+Name: system/lib/libOMX.TI.WBAMR.encode.so
+SHA1-Digest: MDPj2ZBQKzBEgizA6SMeL0kN05k=
+
+Name: system/etc/permissions/android.hardware.sensor.light.xml
+SHA1-Digest: Pn0I13jrVn51nOyc4S/jiw/Xw6U=
+
+Name: system/usr/srec/config/en.us/dictionary/enroll.ok
+SHA1-Digest: RuJqPgJuq9pkqvVscU5w1p03aas=
+
+Name: system/framework/ext.jar
+SHA1-Digest: gVuMN6G2xLL8b3Npiik/WvTU3lw=
+
+Name: system/media/audio/notifications/F1_New_SMS.ogg
+SHA1-Digest: a6PaKmVHQ3ldqiKT9cb1lEXKi7A=
+
+Name: recovery/recovery-from-boot.p
+SHA1-Digest: I9SJBS8vdgbxfjYGZX2nysJl8Gk=
+
+Name: system/app/DownloadProvider.apk
+SHA1-Digest: H8tqOH5zwo9Y7qYot3+xIlUvmV4=
+
+Name: system/etc/permissions/android.hardware.camera.flash-autofocus.x
+ ml
+SHA1-Digest: aDfHvVEe0svv+HGWg3e4S1UZY1k=
+
+Name: system/media/audio/ringtones/Bollywood.ogg
+SHA1-Digest: lp+O3MhWrS1FoZZYuyGBRcHyiz8=
+
+Name: system/lib/libmedia_jni.so
+SHA1-Digest: JkiDc7jvybW86zG7uL/ladx6NOo=
+
+Name: system/app/GoogleCheckin.apk
+SHA1-Digest: UPmobA9pxKwwG9KKl5fZ9U1zhjU=
+
+Name: system/media/audio/ringtones/No_Limits.ogg
+SHA1-Digest: 5skJUZ9GZHPeSneCQAWFXA1scWA=
+
+Name: system/media/audio/alarms/Alarm_Classic.ogg
+SHA1-Digest: o3VRB0mJ2Lu8mY3zQAuPnFcrO+A=
+
+Name: system/lib/libspeech.so
+SHA1-Digest: PQdi4RMPtmrEYMlDH2PSNdqGfIQ=
+
+Name: system/usr/srec/config/en.us/models/generic8.lda
+SHA1-Digest: OYQ/W3VpcPHMWi23NHXjTYvQcIM=
+
+Name: system/lib/libhardware.so
+SHA1-Digest: UvK6ajLYyAX8WhUOOFDkNrPNnAg=
+
+Name: system/lib/libglslcompiler.so
+SHA1-Digest: MiRPhfLWT1CbXfFr1v5AJtW5GrI=
+
+Name: system/lib/libsrec_jni.so
+SHA1-Digest: xXsJb011kdXL4dM50xSCDxDOnwM=
+
+Name: system/framework/com.cyanogenmod.android.jar
+SHA1-Digest: ATDy97tjKpQZIJlSVVvOhMB4w60=
+
+Name: system/app/Talk.apk
+SHA1-Digest: IaK/At5kksD0xOv7SPj0etZ3lA8=
+
+Name: system/lib/libsrv_um.so
+SHA1-Digest: llKW5O1Var9TI+SkCCHhO8/nFvo=
+
+Name: system/xbin/daemonize
+SHA1-Digest: fAppVkUidvDk0Cw2NWhnfBnH/iE=
+
+Name: system/framework/services.jar
+SHA1-Digest: 5dVMdaARFUj8jVSv04jbighgCeI=
+
+Name: system/lib/modules/tiwlan_drv.ko
+SHA1-Digest: +b05j0eH/rkQqsbSgwLg8Y4anQ4=
+
+Name: system/bin/fsck_msdos
+SHA1-Digest: Wa6+KzEwh3IeB2FJFe9HkYVVpyc=
+
+Name: system/media/audio/notifications/Doink.ogg
+SHA1-Digest: IyT26D6bxZf8XqiL+VS645K/XE8=
+
+Name: system/app/MediaProvider.apk
+SHA1-Digest: i8ipLeSj0bmPNJMAp4Bu91qMCHI=
+
+Name: system/media/audio/ringtones/DancinFool.ogg
+SHA1-Digest: FFpA1ZPrtUsjI4CLfR0/+xpAlWQ=
+
+Name: system/usr/keylayout/cpcap-key.kl
+SHA1-Digest: mYzv0mdbHnol/6SSsPhXFdrBlxk=
+
+Name: system/usr/srec/config/en.us/models/generic11_f.swimdl
+SHA1-Digest: 5eK+Uqn7V9+/aGXZDDzZ5MstkII=
+
+Name: system/xbin/cpueater
+SHA1-Digest: jomaejERFiRxdbvy1MXh1oST0WQ=
+
+Name: system/tts/lang_pico/it-IT_ta.bin
+SHA1-Digest: c8PcYiQLwUGDoW5eJBrpQtDXodA=
+
+Name: system/app/com.amazon.mp3.apk
+SHA1-Digest: yXJ7BbG9y5szCwff/lcMvFuGUMI=
+
+Name: system/lib/libskiagl.so
+SHA1-Digest: hFGZr3mptF06oGBNH85Z7KRjkE4=
+
+Name: system/app/DrmProvider.apk
+SHA1-Digest: VmojQix603ZWvS+K98/0JzIMSQs=
+
+Name: system/bin/mdm_panicd
+SHA1-Digest: jzfvdbGZV3OEC9FfzgtdYGxzGC4=
+
+Name: system/lib/libomx_mp3dec_sharedlibrary.so
+SHA1-Digest: W4u4tQVrTTNWwLc3tbzsXKMHdac=
+
+Name: system/xbin/avinfo
+SHA1-Digest: cyqS06u9l0IMy1AW6E3HvP/gSWU=
+
+Name: system/etc/dhcpcd/dhcpcd-run-hooks
+SHA1-Digest: MgZi93yT42VYffTWMv81JkB68RA=
+
+Name: system/xbin/hcitool
+SHA1-Digest: fgx4IYgVnN9rXraYE7FGLrWn4XQ=
+
+Name: system/tts/lang_pico/en-US_lh0_sg.bin
+SHA1-Digest: VZN0Rmcj/fnhpKGKAs3zvqqPrt0=
+
+Name: system/bin/am
+SHA1-Digest: JU7gkgpcGs2BY+uIS5nNG1/nRtY=
+
+Name: system/xbin/showslab
+SHA1-Digest: 9Bu8bP4Xd1JPNzIdCmsn8nkaPEw=
+
+Name: system/app/HtcCopyright.apk
+SHA1-Digest: DK/u8Hn66G6cKiWbq+JznYBKWQI=
+
+Name: system/etc/apns-conf.xml
+SHA1-Digest: NKlRmmeBE3E2nAYbfyQdmVeCNpQ=
+
+Name: system/bin/hciattach
+SHA1-Digest: TK/4qXcKe0elN0SAUpyoLpB6J/0=
+
+Name: system/usr/srec/config/en.us/models/generic8_f.swimdl
+SHA1-Digest: OUQtGxyzBG46RkofSQn8ez34OlE=
+
+Name: system/xbin/opcontrol
+SHA1-Digest: YSa/rCSpEzMv+1Co8xZdwQz6RvA=
+
+Name: system/bin/picd
+SHA1-Digest: wFlWxDmFgvsuhDpF4ISYki/l0Rw=
+
+Name: system/lib/libskia.so
+SHA1-Digest: vL9IPes0Q26Mxqk7tznWfFv8rAQ=
+
+Name: system/app/Calculator.apk
+SHA1-Digest: OhYBnwNjeVrsifMJBPhf71r98pU=
+
+Name: system/bin/gzip
+SHA1-Digest: KaAEpSzvejKW2IOOq9cUcW7TRf4=
+
+Name: system/lib/libsurfaceflinger.so
+SHA1-Digest: msxr7T7/uBGk9mv4ZBWO2ReeQJ8=
+
+Name: system/app/NetworkLocation.apk
+SHA1-Digest: folnffE2JGPDD99MVpllEWLb9fM=
+
+Name: system/media/audio/ringtones/Nassau.ogg
+SHA1-Digest: UA0O0SLCOE2NPdJ/UmNGmELMiG0=
+
+Name: system/bin/bthelp
+SHA1-Digest: flcRiGXGPbmcs+4ToJn89A7QgYk=
+
+Name: system/bin/sdptool
+SHA1-Digest: OlvneKEjmczAmBjcIvvja9whNM0=
+
+Name: system/lib/libOMX.TI.AAC.encode.so
+SHA1-Digest: rym6c50s2xDQJkXm+Jbxga7ESpM=
+
+Name: system/framework/android.test.runner.jar
+SHA1-Digest: LHqBzReOS56ksE21QaaQBqigRS4=
+
+Name: system/fonts/Clockopia.ttf
+SHA1-Digest: +vgYgkUemnpjfwZ99j4TWmseawE=
+
+Name: system/framework/pm.jar
+SHA1-Digest: yLTrrYwE2SAsBqvVCblPyGLAAj0=
+
+Name: system/media/audio/ringtones/Gimme_Mo_Town.ogg
+SHA1-Digest: LNVjQUp8VmYJaHeA2fNsKY2ZIgA=
+
+Name: system/lib/libmoto_ril.so
+SHA1-Digest: PjunyMXFCnaTi1L1iF2DgI0ip+4=
+
+Name: system/lib/libbattd.so
+SHA1-Digest: yEOFUt6AvRdbTJsKZ3IVdsRLDjM=
+
+Name: system/lib/libPERF.so
+SHA1-Digest: 821fXt5NTWxrKBYVo/u41amHVYY=
+
+Name: system/etc/hosts
+SHA1-Digest: eK7U5SmrOpeCSrjJ5BsrWKeuSoE=
+
+Name: system/app/Camera.apk
+SHA1-Digest: s/qHEnPM7+TBAsc84wxZnsQfICc=
+
+Name: system/etc/sysctl.conf
+SHA1-Digest: RV+Bhw5FzZYSDBirQlCgID4B+ik=
+
+Name: system/app/PicoTts.apk
+SHA1-Digest: TbfDbNORhyxq4LMrjPqvKGtc/uc=
+
+Name: system/app/Launcher2.apk
+SHA1-Digest: vdWkSguUy3SJ3lFjfLmBhtTEHcc=
+
+Name: system/media/audio/ui/VideoRecord.ogg
+SHA1-Digest: op0jkXcHGjUiRs4Ps9209mGlsNE=
+
+Name: system/framework/am.jar
+SHA1-Digest: W1/CDlSe7gzFOAxA2zJ0lutEuok=
+
+Name: system/bin/logwrapper
+SHA1-Digest: VyUx21blGh4Y8a/rqiRUiAG5aSU=
+
+Name: system/bin/app_process
+SHA1-Digest: UrEelICyT0n7Oo1dLb4qTnBmxX4=
+
+Name: system/lib/libttspico.so
+SHA1-Digest: 0KCqV++Dl4gjXDNZsUxv70bJ+MI=
+
+Name: system/app/DeskClock.apk
+SHA1-Digest: 2fGzvKiAQIE2tbUS6FWUI+cEw2k=
+
+Name: system/xbin/dexdump
+SHA1-Digest: fDrJzw8vl1226+r6gT10Bci14u8=
+
+Name: system/media/audio/ringtones/CrayonRock.ogg
+SHA1-Digest: 7HGDQ/+DQJHGxd5FJfDT3VhnPEc=
+
+Name: system/media/audio/ringtones/Big_Easy.ogg
+SHA1-Digest: XwOAShMm4jbw1/ZNB62JjB8iyEo=
+
+Name: system/bin/sdutil
+SHA1-Digest: 5CqyDOLvzaW4AlaRpSfAJae6HqE=
+
+Name: system/lib/libaudiopolicygeneric.so
+SHA1-Digest: bcsqCLYE3RN690aUCXhByfzOI6I=
+
+Name: system/lib/libctest.so
+SHA1-Digest: Xg37PUK4cMO1PKcPB0QF57ERQlQ=
+
+Name: system/lib/modules/wl127x_test.ko
+SHA1-Digest: TPZ5J2/faCdA0feNdvHp+JdJ2aY=
+
+Name: system/lib/libterm.so
+SHA1-Digest: vI0HA/Jqh/KE852oajBJt6hh8oA=
+
+Name: system/app/gtalkservice.apk
+SHA1-Digest: 33iGYRY9qTAFQP+g4kL3vAaEBY8=
+
+Name: system/media/audio/notifications/Voila.ogg
+SHA1-Digest: 8k2ncBzwwD2NoWUvRt/+U/BMgGE=
+
+Name: system/usr/srec/config/en.us/models/generic11.lda
+SHA1-Digest: gCp5FAUl5aR0GnFC/tkkamX7ic8=
+
+Name: system/lib/libHPImgApi.so
+SHA1-Digest: zBpri6quqCqTiv/139otPi4PAw4=
+
+Name: system/lib/libcameraservice.so
+SHA1-Digest: E0XPmemZDJK6N73+4xncwqQpXHw=
+
+Name: system/bin/applypatch_static
+SHA1-Digest: pxfxr3tm1cVCJHTLGcR6x1d8Lxc=
+
+Name: system/xbin/agent
+SHA1-Digest: Dq1nrtuGvdrVfMMyn/Abxple2XY=
+
+Name: system/lib/libomx_m4vdec_sharedlibrary.so
+SHA1-Digest: ix60QzWThcyaoAtLboUDM3C7bwI=
+
+Name: system/app/CalendarProvider.apk
+SHA1-Digest: 3p1WtDJmTisUq1SjPv1YIJlHKUI=
+
+Name: system/lib/libOMX.TI.JPEG.Encoder.so
+SHA1-Digest: T8M3+5EDQKiEgtEr1fy+m2Zj+dA=
+
+Name: system/lib/dsp/mp4vdec_sn.dll64P
+SHA1-Digest: nMMp5OIu7tv0fCieDgbfZQ3KDgI=
+
+Name: system/media/audio/ringtones/Enter_the_Nexus.ogg
+SHA1-Digest: zACA+wwMoEDVgps4LpZPvSgDIUM=
+
+Name: system/media/audio/ringtones/HalfwayHome.ogg
+SHA1-Digest: wyrYCffeViie8bRhm/IRXnw6lYo=
+
+Name: system/xbin/strace
+SHA1-Digest: L0G1/5AMEKW7o9cjRo0MDA04FJQ=
+
+Name: system/app/Maps.apk
+SHA1-Digest: 8NvcPZz9pDB+coSsm3hSOO/oRf0=
+
+Name: system/etc/gps.conf
+SHA1-Digest: fdiNck4CecH4doyprSn7phFh9xQ=
+
+Name: system/xbin/dropbear
+SHA1-Digest: HaH2wE1LLRZ3Hu327uKIM1NB65E=
+
+Name: system/lib/libomx_wmvdec_sharedlibrary.so
+SHA1-Digest: d89YL/VRALYjgzIvjeRmiGjPlXo=
+
+Name: system/usr/keylayout/qwerty.kl
+SHA1-Digest: xFyn0VlIXS0r5AOczuI9b3dEHMo=
+
+Name: system/app/VoiceDialer.apk
+SHA1-Digest: kAlHFAu69VgN+jl879QiMIQ8C+k=
+
+Name: system/framework/com.google.android.maps.jar
+SHA1-Digest: UUvA0dAukTKZn34LQ242dltDAZo=
+
+Name: system/media/audio/notifications/OnTheHunt.ogg
+SHA1-Digest: btYib2szrK5TKBS52wvGzYp+z7Y=
+
+Name: system/media/audio/notifications/DearDeer.ogg
+SHA1-Digest: PqQWPpaTrtYxRVymXbHHNl4TDcY=
+
+Name: system/xbin/l2test
+SHA1-Digest: uuPooy99q7+tFPX24u3PY1nfafE=
+
+Name: system/media/audio/notifications/Cricket.ogg
+SHA1-Digest: F+Lh3iN/UwLe6hyzV0y4fFC6BFM=
+
+Name: system/lib/libomx_sharedlibrary.so
+SHA1-Digest: i/skXgSUJWchnrAaleMSpj5YJto=
+
+Name: system/app/TalkProvider.apk
+SHA1-Digest: fZQKfFee/etmEL73ijIFqzSD3LA=
+
+Name: system/bin/servicemanager
+SHA1-Digest: VPGsXuQ9XTiQD0bkMepMTQ+Bpbk=
+
+Name: system/framework/javax.obex.jar
+SHA1-Digest: 4BI2TDxPrchUUbgQmmz6hzZzEXg=
+
+Name: system/lib/libthread_db.so
+SHA1-Digest: m7wC6thlKMS7tGuKLxYIB8ta3VY=
+
+Name: system/tts/lang_pico/fr-FR_nk0_sg.bin
+SHA1-Digest: I7WPANRD1+z2Y30qxM7CeAx+7tI=
+
+Name: system/lib/libopencore_rtspreg.so
+SHA1-Digest: YOLHhiOLAFpptfgNCoxJiM0Rg/g=
+
+Name: system/xbin/openvpn
+SHA1-Digest: +R4O3h0SbyDAQOPeJibjw0TEX1c=
+
+Name: system/tts/lang_pico/en-GB_ta.bin
+SHA1-Digest: RxVuaVHGuJBd5VNkkKXD5rieWrM=
+
+Name: system/media/audio/notifications/Heaven.ogg
+SHA1-Digest: h6yb9TGCOptNKd1zNXcuxsZvYRg=
+
+Name: system/lib/bluez-plugin/input.so
+SHA1-Digest: 6cm2eufa3A4NXDPCG+rp0LqZ74k=
+
+Name: system/lib/libsystem_server.so
+SHA1-Digest: CnUmwWUk60j8mF9zhJzK9404op8=
+
+Name: system/lib/dsp/conversions.dll64P
+SHA1-Digest: Q27/vtW39PLoVVAQBH4xjOb/76k=
+
+Name: system/tts/lang_pico/es-ES_zl0_sg.bin
+SHA1-Digest: t4V/1pUzbaBDcAz2GDES2I1aPWY=
+
+Name: system/etc/wifi/tiwlan.ini
+SHA1-Digest: 7HbAKUwPlj8yZFEH1wSYv0SdSko=
+
+Name: system/media/audio/ringtones/Club_Cubano.ogg
+SHA1-Digest: pBTpYFzvdovd5dDbHiv/rNkcECM=
+
+Name: system/lib/libGLESv2.so
+SHA1-Digest: MjaUfQ897zJGYhdGDHbAoAM30nM=
+
diff --git a/bin/META-INF/MANIFEST.MF b/bin/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..3bf07e3
--- /dev/null
+++ b/bin/META-INF/MANIFEST.MF
@@ -0,0 +1,1733 @@
+Manifest-Version: 1.0
+Created-By: 1.0 (Android SignApk)
+
+Name: system/xbin/l2ping
+SHA1-Digest: gbyU8XuH2NsrB6pFyD1jYmhAJGo=
+
+Name: system/lib/libemoji.so
+SHA1-Digest: K9yR+sjKtxpnx0WtVueZ13Vg2Pg=
+
+Name: system/lib/liblog.so
+SHA1-Digest: 2OOEvU0noFCgf9cYm+69IrJBUdc=
+
+Name: system/lib/libRS.so
+SHA1-Digest: ojF07fS5btKppoWNUF2hLE17wwc=
+
+Name: system/bin/bugreport
+SHA1-Digest: RPxLdv83klTGYx6HCFGkikurKJ4=
+
+Name: system/etc/bluez/main.conf
+SHA1-Digest: /VHeG/SMhksDhwBSl4jcZGQtKdE=
+
+Name: system/media/audio/ui/Effect_Tick.ogg
+SHA1-Digest: 1oYW2A2HlwkfYAypLme5TD8X9LI=
+
+Name: system/app/UserDictionaryProvider.apk
+SHA1-Digest: DzUYu6Ds0Ub4Fus86QQ15L1Lgo4=
+
+Name: system/lib/libpvr2d.so
+SHA1-Digest: gUTASwyMYRy7tqXECyuzSOUMM0E=
+
+Name: system/app/CarDock.apk
+SHA1-Digest: +RB4TbeAj3lPWTovE26loIpLCgU=
+
+Name: system/lib/libbluetoothd.so
+SHA1-Digest: GImNvOizQo+60k4vRVF9AYmEfC4=
+
+Name: system/xbin/rfcomm
+SHA1-Digest: RQ1sjOpJv7dHbr+ofkMaqQCcJzg=
+
+Name: system/etc/pvplayer.cfg
+SHA1-Digest: 9Lkk2Y8QxQIYY5Kq7TWBTuAbwZk=
+
+Name: system/xbin/netperf
+SHA1-Digest: F+OKS6xPtWmnJOP3mLYK0NVWIvc=
+
+Name: system/lib/libm.so
+SHA1-Digest: A0I6ZMaOTIM3IuZNLf5Gum5BGJ4=
+
+Name: system/usr/share/bmd/RFFspeed_501.bmd
+SHA1-Digest: U8VAt4ToJM9cf23UWSW02bJYN+M=
+
+Name: system/bin/dspexec
+SHA1-Digest: kYi24owrHO1k/ljMsXQNEIYK/eo=
+
+Name: system/xbin/check-lost+found
+SHA1-Digest: I48QRBGM6zSCgFMKU70DXsF61d0=
+
+Name: system/lib/egl/libGLES_android.so
+SHA1-Digest: ROuhIrgE6O9iRdbRrNOLRlPUyL4=
+
+Name: system/lib/libui.so
+SHA1-Digest: y1/IKUvNKAVA4CWEvpps708bP9A=
+
+Name: system/lib/dsp/h264venc_sn.dll64P
+SHA1-Digest: PrpvuPANgxMk0qagDE4bvWcJtok=
+
+Name: boot.img
+SHA1-Digest: d9jNe4z0lbBjMCbAZPKs65X6bls=
+
+Name: system/bin/updater
+SHA1-Digest: S8DOFyaN6V4S7TVCOZbED9BWxmA=
+
+Name: system/xbin/netserver
+SHA1-Digest: egCkcOW7tqdiWVlbFoVDOX1ICPU=
+
+Name: system/lib/libdrm1.so
+SHA1-Digest: nAP4CvXuPsw83puwcM7z/40x7eQ=
+
+Name: system/lib/libexpat.so
+SHA1-Digest: iYgWLHHU8yCGUQ9XMPlQaOETcYE=
+
+Name: system/lib/libpvasflocalpb.so
+SHA1-Digest: w+z+wQkuE+cn0H7/z6I3V/e5VpM=
+
+Name: system/lib/libopencore_author.so
+SHA1-Digest: ho1btaVnkGXdQCusqTp2YKmt6PU=
+
+Name: system/lib/liblzo.so
+SHA1-Digest: NFL+5Bf3fbf/hu2hCnKSXIF2joM=
+
+Name: system/lib/libstagefright_omx.so
+SHA1-Digest: g2DCQSGpITdJG17CO+CSmp45T+0=
+
+Name: system/media/audio/ringtones/MidEvilJaunt.ogg
+SHA1-Digest: Ve5lq504xLevxS2Z6KFKBl0H3f4=
+
+Name: system/lib/libopencore_mp4local.so
+SHA1-Digest: gP6w/7hE3wYltiZSoifVFhW9GdI=
+
+Name: system/lib/hw/overlay.omap3.so
+SHA1-Digest: x8ajmU8ZL2d8ihb5YzSjk2KDz+8=
+
+Name: system/xbin/busybox
+SHA1-Digest: IY3/C9KotUFY35MEHtEvTgQiUfA=
+
+Name: system/media/audio/ringtones/Ring_Digital_02.ogg
+SHA1-Digest: PIB2thaCvs7H7y7pq0qK0WO+g/0=
+
+Name: system/lib/liboemcamera.so
+SHA1-Digest: S0PQ9RhE9/8PEXN3SJjG8gAmF88=
+
+Name: system/lib/libpvasflocalpbreg.so
+SHA1-Digest: lf5zKElh618a01Wq0kzrr4lioGA=
+
+Name: system/media/audio/ringtones/LoopyLounge.ogg
+SHA1-Digest: QWQkLIPZ5SsqJvVqfT//Rs6ffv8=
+
+Name: system/etc/motorola/12m/key_code_map.txt
+SHA1-Digest: mc8v+2eLOi0IncnY66drvz3NVIY=
+
+Name: system/lib/libopencore_common.so
+SHA1-Digest: mFjSgzMdDit4o768jEdrzmREISE=
+
+Name: system/tts/lang_pico/en-GB_kh0_sg.bin
+SHA1-Digest: GdOsfbAkt85177IqmERhpEEd7Ow=
+
+Name: system/lib/libomx_amrenc_sharedlibrary.so
+SHA1-Digest: Z79xh577qgkHEkzw5CVYZsqNJGE=
+
+Name: system/etc/bluez/audio.conf
+SHA1-Digest: LVKXWoT+9rivzEz+ZLxDyNshfew=
+
+Name: system/media/audio/ringtones/Glacial_Groove.ogg
+SHA1-Digest: 8ioRWpc66yq2afqZAmtcHDy4WTw=
+
+Name: system/bin/gdbserver
+SHA1-Digest: toe9rXH6jyytx6qe06eaTvOqIsI=
+
+Name: system/etc/bookmarks.xml
+SHA1-Digest: 0V/HrR5w/UFYRAGwpgknLqPur6A=
+
+Name: system/lib/bluez-plugin/audio.so
+SHA1-Digest: EWkZ/Eld7qIp0/DBnvY9QQI9FvA=
+
+Name: system/lib/libacc.so
+SHA1-Digest: iJGOcZLTXdn7+nxm40E7epeZmcw=
+
+Name: system/bin/linker
+SHA1-Digest: lmTmsBxIOJzMyVBe6MhghJ5vgLM=
+
+Name: system/etc/permissions/com.google.android.datamessaging.xml
+SHA1-Digest: k6R5V2Yakso9uykyML6KGe2eZMQ=
+
+Name: system/usr/keychars/qwerty2.kcm.bin
+SHA1-Digest: rDDkv0uj8pR+OAVyD5lgOS45nlA=
+
+Name: system/media/audio/ringtones/Ring_Classic_02.ogg
+SHA1-Digest: WhrmdNO1Thyne87iSbuEMHRXp4w=
+
+Name: system/bin/dhcpcd
+SHA1-Digest: Z0x5uVRNBzONHmIMOmiJzXXQ78w=
+
+Name: system/app/BugReport.apk
+SHA1-Digest: V+Ai2r2hHxqPitVO8u132BpnP/c=
+
+Name: system/tts/lang_pico/it-IT_cm0_sg.bin
+SHA1-Digest: NkGOu0bzLCZzOF5ItD3p2GJTI+M=
+
+Name: system/bin/bluetoothd
+SHA1-Digest: 0Egow2uEH3QfBLZN3U725yj2Muk=
+
+Name: system/app/GoogleGoggles.apk
+SHA1-Digest: V00x+xJ2nh+AzgCUjp6UDNh1u8s=
+
+Name: system/bin/bootanimation
+SHA1-Digest: vzTZOKiEIAoJk6EatDBGs+w4lDY=
+
+Name: system/lib/libwebcore.so
+SHA1-Digest: G0U0xDGbooNCFK8tqi1yNZzHBns=
+
+Name: system/bin/pm
+SHA1-Digest: XY3kUD4TG6bh8EMZiFFrRWiG7Ec=
+
+Name: system/bin/chat-ril
+SHA1-Digest: Qky2zongY/zuM6WKxT3bI+3dQjw=
+
+Name: system/framework/bmgr.jar
+SHA1-Digest: rbRioBW1KES+3nQr+WIKkbVwIJk=
+
+Name: system/lib/egl/libEGL_POWERVR_SGX530_121.so
+SHA1-Digest: g5uIpsJ9DU9dZHLyMuo7jDiYvEg=
+
+Name: system/framework/com.google.android.gtalkservice.jar
+SHA1-Digest: edUpg/THwMA97q5uaQWVI41sr74=
+
+Name: system/bin/system_server
+SHA1-Digest: Gy4488Bkk1Cgr+2HSTWiRSh+hGk=
+
+Name: system/fonts/DroidSerif-Regular.ttf
+SHA1-Digest: fyQ4WOSW7Rux+sqfOnu+Ut78u10=
+
+Name: system/etc/wifi/wpa_supplicant.conf
+SHA1-Digest: mCyu4uaIH928cDSQucj9xlPdN+U=
+
+Name: system/lib/libOMX_Core.so
+SHA1-Digest: TY4GdpN809IyADDCGMWG1FHmGR0=
+
+Name: system/media/audio/notifications/Highwire.ogg
+SHA1-Digest: a4posBTV+0q5h7jBDw3WmUDYT6o=
+
+Name: system/bin/ping
+SHA1-Digest: b+fLt1BAByWQvt8wbZIPEtT46j4=
+
+Name: system/framework/framework-res.apk
+SHA1-Digest: zKnj2MAixKQ9R+0e8DEEEG0itIg=
+
+Name: system/media/audio/ringtones/Ring_Synth_02.ogg
+SHA1-Digest: GAkS3fU7B8v3z0jDjkeiFay+c3c=
+
+Name: system/etc/dhcpcd/dhcpcd-hooks/01-test
+SHA1-Digest: j3BHrGmvjyUveupOy4QHRy8ioqg=
+
+Name: system/app/GooglePartnerSetup.apk
+SHA1-Digest: T5ljjOAFIWAbLSLy2v1JG9EFC8o=
+
+Name: system/usr/keychars/qwerty.kcm.bin
+SHA1-Digest: ibVknsf+brcf2jzJ4U0ZpOaaNfY=
+
+Name: system/lib/libxml2wbxml.so
+SHA1-Digest: QIhTVubBcXqKOw8RewcRgl7vDjI=
+
+Name: system/bin/akmd2
+SHA1-Digest: TnsugS8PHB+/HrabJdR3LASorBY=
+
+Name: system/lib/libaes.so
+SHA1-Digest: +fcykx6YU5uMAxROLCOHHgh7X2g=
+
+Name: system/app/Development.apk
+SHA1-Digest: skI528qDu+/SS1NPzCMqaLgMm1M=
+
+Name: system/etc/security/otacerts.zip
+SHA1-Digest: V/2bJdeReihfGBtXCFB19HtNaEw=
+
+Name: system/lib/dsp/ringio.dll64P
+SHA1-Digest: 6ylGaFYXIkT3+60sH7ofzdS6ZjE=
+
+Name: system/lib/libril_rds.so
+SHA1-Digest: ODh3jiIdiEgCDQXBOett0yT89NQ=
+
+Name: system/xbin/sdptest
+SHA1-Digest: R9jCDHMRWgLZtxC6S0yz6h0JNqM=
+
+Name: system/bin/zipalign
+SHA1-Digest: 4jQfe97MbqG+CnI0j2VLXICrOlk=
+
+Name: system/lib/hw/gralloc.default.so
+SHA1-Digest: i81trnZrwONdPdW4T2FUC9m2Kn4=
+
+Name: system/tts/lang_pico/en-US_ta.bin
+SHA1-Digest: t0mPNI+8qbi3okSuWNdcDjlTdxk=
+
+Name: system/lib/libandroid_runtime.so
+SHA1-Digest: cRgnlTd9flUVnON116WsIIGN3N4=
+
+Name: system/lib/libpixelflinger.so
+SHA1-Digest: 45zCsfxAcZpCn9WKVdxdJnViW3Q=
+
+Name: system/bin/ime
+SHA1-Digest: tRT4xXnmwLMmpCiARGf1xmn/8K0=
+
+Name: system/media/audio/notifications/SpaceSeed.ogg
+SHA1-Digest: xkyifT2mJnaopxECgJoFmq76mWM=
+
+Name: system/xbin/bdaddr
+SHA1-Digest: aksVbAGD+ic0yb0vIWhcjFAl068=
+
+Name: system/media/audio/ringtones/Eastern_Sky.ogg
+SHA1-Digest: YrStd4w+/OpCwxpaCDJzPRpcNBw=
+
+Name: system/lib/libopencorehw.so
+SHA1-Digest: Kqm2qXzKoqqVJA1zrYVSq8Uepko=
+
+Name: system/lib/libomx_aacdec_sharedlibrary.so
+SHA1-Digest: zrwve8vs1UnDeprBdVocCtO4hRY=
+
+Name: system/etc/vendor/cpcap/vector_data
+SHA1-Digest: kJXShklze512ktVf8WDns5OWYzo=
+
+Name: system/bin/bmgr
+SHA1-Digest: txVKgTGjXkxUtbIhsor6EUCfLsM=
+
+Name: system/media/audio/ringtones/Nairobi.ogg
+SHA1-Digest: gxwjln9YZiFK/JFcQuwVM4gpoFQ=
+
+Name: system/media/audio/ringtones/Terminated.ogg
+SHA1-Digest: RkwketEuvqQu+kkQTFhrddZx4Fs=
+
+Name: system/etc/permissions/com.cyanogenmod.android.xml
+SHA1-Digest: UBY66aXVrGiAvZYkBVdCXl80T1I=
+
+Name: system/lib/libwpa_client.so
+SHA1-Digest: Sm188OA/KktRsElTSsML3HXd840=
+
+Name: system/etc/event-log-tags
+SHA1-Digest: afr7g+VJz6rlkISpTUbaNWJUuxs=
+
+Name: system/app/SettingsProvider.apk
+SHA1-Digest: 0g9p1awFuuAeeri6Rgl7nRYqkCY=
+
+Name: system/lib/libril.so
+SHA1-Digest: eRiLHFOk/v3Xj7XNo5tJov0Abjc=
+
+Name: system/app/PackageInstaller.apk
+SHA1-Digest: zu52ZzchSZ1Q3EpNCFYfIoqXHyA=
+
+Name: system/app/Bluetooth.apk
+SHA1-Digest: ydr8fNEMN9a8wgIZOixzTM2v3MM=
+
+Name: system/lib/libsoundpool.so
+SHA1-Digest: 6XP8lLuczGNgr7ziZEpg7dQdDXo=
+
+Name: system/media/audio/ringtones/Third_Eye.ogg
+SHA1-Digest: nlM0uYvrywXGt38Hwrmxc8nh9jc=
+
+Name: system/etc/init.d/01sysctl
+SHA1-Digest: 7mSigaDiH0MXZf1X1u5gsO28Dvg=
+
+Name: system/app/ApplicationsProvider.apk
+SHA1-Digest: DbbZ3blBRIlOIdYNDNl4vAjWIWk=
+
+Name: system/media/audio/alarms/Alarm_Beep_03.ogg
+SHA1-Digest: h/yxjAGYwFu7hk6fuC+OyL1QG18=
+
+Name: system/bin/mediaserver
+SHA1-Digest: VIxuTqf/oMQ+HCUk1x/8WJjyrSI=
+
+Name: system/app/Vending.apk
+SHA1-Digest: 8v7qaSK34XOgzljSwsZP2thVO0s=
+
+Name: system/lib/libaudiopolicy.so
+SHA1-Digest: 1ljJOo62nS5zAj3X3HiZDmuY6dc=
+
+Name: system/media/audio/notifications/Drip.ogg
+SHA1-Digest: sE+btoNoJLKDl3c9m4fbGnA/+UY=
+
+Name: system/etc/wifi/fw_wlan1271.bin
+SHA1-Digest: ZMY1bZFsIEkfzocWMh/eFW4KCZM=
+
+Name: system/media/audio/ringtones/SilkyWay.ogg
+SHA1-Digest: 8KPere+EFoojUsaVaP/JDSh6pug=
+
+Name: system/etc/permissions/platform.xml
+SHA1-Digest: wpwSti+kmkFRCUIT7/Lde9IfjaQ=
+
+Name: system/media/bootanimation.zip
+SHA1-Digest: JTIldn7kQcANcBwxqEaf/7n7YqY=
+
+Name: system/bin/qemud
+SHA1-Digest: VO/I2akVmVVtI50ESX+sSCzMzvI=
+
+Name: system/app/Contacts.apk
+SHA1-Digest: tMzg0w01Wjo1bN1NMYVXW2rcklY=
+
+Name: system/lib/libaudio.so
+SHA1-Digest: N4Nl9BKji/9oYIIrBmSQfq4qzzg=
+
+Name: system/bin/dnsmasq
+SHA1-Digest: JglGMtXemLTU05waLXMdkxjaPOU=
+
+Name: system/lib/egl/libGLESv2_POWERVR_SGX530_121.so
+SHA1-Digest: P4QNILCt/NqrTY64lmaaVtc56lY=
+
+Name: system/lib/libpagemap.so
+SHA1-Digest: 88yZsUnJ703AHLTzC9tui3Gs4JM=
+
+Name: system/lib/libexif.so
+SHA1-Digest: EtMwyUv4V5UV5ja74aQNhoEiXXM=
+
+Name: system/app/GoogleBackupTransport.apk
+SHA1-Digest: qa3h/jV1LRT+UrD2JPpBqWdGjPA=
+
+Name: system/bin/tcmd
+SHA1-Digest: kg8rnygSx5+74pGzA8BWzSO5gT4=
+
+Name: system/xbin/ssh
+SHA1-Digest: SsozzqhdRiZT9ASfLmiBNR3Krcs=
+
+Name: system/usr/srec/config/en.us/models/generic.swiarb
+SHA1-Digest: QGzUh5WkfKQRmuaI+sJtXBZrEFg=
+
+Name: system/lib/libIMGegl.so
+SHA1-Digest: hEkOOsSn7wHmfL7bIImcxzeiwYU=
+
+Name: system/media/audio/ringtones/Road_Trip.ogg
+SHA1-Digest: KwIZKMKgxnFwdH8QswcuRPBUxdc=
+
+Name: system/media/audio/notifications/CaffeineSnake.ogg
+SHA1-Digest: 74akGXnH3pLhPveosocbS/cIf/I=
+
+Name: system/lib/libvorbisidec.so
+SHA1-Digest: u4l/ktVuaBajuWGkVZfySz2DXP0=
+
+Name: system/xbin/bttest
+SHA1-Digest: qw7FfTSU2AolZbkSk0avXBoTlu4=
+
+Name: system/app/VoiceSearchWithKeyboard.apk
+SHA1-Digest: Ah3B5+3IUdEum7ucfaj6DPFM+f8=
+
+Name: system/app/LiveWallpapersPicker.apk
+SHA1-Digest: VnTErlHTAYXSvwO417lhCY6ie5g=
+
+Name: system/app/YouTube.apk
+SHA1-Digest: swSIP8FdSi4n8js1UlDdjdWjUfo=
+
+Name: system/bin/dexopt
+SHA1-Digest: 3MlisTIWojpkXJhjhEKikTNnu/s=
+
+Name: system/usr/srec/config/en.us/models/generic11_m.swimdl
+SHA1-Digest: N2jOonTixJLNBvuNMlZ1cmcMhzU=
+
+Name: system/etc/permissions/required_hardware.xml
+SHA1-Digest: d3pBuqURQWyNGskUmxE6nD3i6+8=
+
+Name: system/media/audio/ringtones/FreeFlight.ogg
+SHA1-Digest: 77NJsEoo7DvWMcYhX25A2uRtmSg=
+
+Name: system/etc/init.goldfish.sh
+SHA1-Digest: IEA4BccWDrH9B5SdD8qBZwiUUts=
+
+Name: system/media/audio/ringtones/Safari.ogg
+SHA1-Digest: EzIFjZLlvbJEbUA25p8qWS71eCQ=
+
+Name: system/app/EnhancedGoogleSearchProvider.apk
+SHA1-Digest: MluKl0hFCGcVQxoGTinEqQAX9Ds=
+
+Name: system/media/audio/ringtones/Backroad.ogg
+SHA1-Digest: aZLwTqcBx2p0u1zbo93/JP5MMNg=
+
+Name: system/lib/libcrypto.so
+SHA1-Digest: QY/xATwJdWE9dPtbzz7xPCXdu4A=
+
+Name: system/bin/pppd
+SHA1-Digest: Gs3aUDxwZViWx89T2tcjCLXndN0=
+
+Name: recovery/etc/install-recovery.sh
+SHA1-Digest: Z97Tacvaq9ntFlvKJg9KDxl96Zg=
+
+Name: system/app/ContactsProvider.apk
+SHA1-Digest: Y8BassaTu4l0LD1pJxYmnUfrw6I=
+
+Name: system/lib/liba2dp.so
+SHA1-Digest: wvdEd/Fy6sJdnwtX1IrSgqTCPns=
+
+Name: check_prereq
+SHA1-Digest: hok22N88YOU4dRoW8EEyM510uXw=
+
+Name: system/fonts/DroidSerif-Italic.ttf
+SHA1-Digest: EXlBvhAsjzioanDrzK7LgHj3An4=
+
+Name: system/app/GenieWidget.apk
+SHA1-Digest: 9mzUCb+A0lnLx7lMnqp7pfAecPc=
+
+Name: system/bin/qemu-props
+SHA1-Digest: EEqEU26yM5pR6VYYfMISU55VW/Q=
+
+Name: system/bin/rild
+SHA1-Digest: 2jfM6IDAVBfmTOgSg23R4Gv0QDI=
+
+Name: system/media/audio/ui/KeypressSpacebar.ogg
+SHA1-Digest: W5H8TwiuPBEoXIq85+hJWUrkOVU=
+
+Name: system/app/MediaUploader.apk
+SHA1-Digest: Vrc73iYFaEhIQ1/5tel148qFkwk=
+
+Name: system/lib/libdl.so
+SHA1-Digest: cZzCR+8x+luDVg6BE+fZ7M+vY7Q=
+
+Name: system/bin/keystore_cli
+SHA1-Digest: 6jgABf9CKtJKTqieYo9g2AgSvOA=
+
+Name: system/media/audio/ringtones/Paradise_Island.ogg
+SHA1-Digest: AOrVuisOvS6TsvHo3oMWYNpVEOs=
+
+Name: system/lib/libsysutils.so
+SHA1-Digest: 9eV8brBCJxcIjySNvHjf/UrkJjw=
+
+Name: system/app/SpareParts.apk
+SHA1-Digest: vaioTBmKkxpedQJDmgAv94RLs7U=
+
+Name: system/media/audio/ui/camera_click.ogg
+SHA1-Digest: jet4ZWI3QDsJT8T3YoNr9gH1NUc=
+
+Name: system/media/audio/alarms/Alarm_Beep_02.ogg
+SHA1-Digest: 9CSCsIo9GbrhKAQ0QscX714pNNQ=
+
+Name: system/etc/permissions/android.hardware.telephony.cdma.xml
+SHA1-Digest: n/osMau222JSnc7CbuAZcT3FUbs=
+
+Name: system/usr/srec/config/en.us/baseline8k.par
+SHA1-Digest: cR3ErVVeWITO4QendRZRkkfChHc=
+
+Name: system/media/audio/ui/KeypressReturn.ogg
+SHA1-Digest: AhKAuhFRUYILt2u43zNK389U9hE=
+
+Name: system/media/audio/alarms/Alarm_Beep_01.ogg
+SHA1-Digest: tyeJsmvjmrcQcal3Ex/JIhCgSC0=
+
+Name: system/bin/surfaceflinger
+SHA1-Digest: oaq0EljDGTUYp4VsWsCrG7XH+RU=
+
+Name: system/etc/excluded-input-devices.xml
+SHA1-Digest: B5U7/ca3f7KBgdLJpgvRzuHml18=
+
+Name: system/framework/svc.jar
+SHA1-Digest: 1Fvhhd3pdhwLVd12BxJeFABuh5M=
+
+Name: system/lib/libomx_avcdec_sharedlibrary.so
+SHA1-Digest: 5Uuzgfiy19UOkRPGayidcxa92jk=
+
+Name: system/lib/libOMX.TI.AMR.encode.so
+SHA1-Digest: 4lPjdAMnHVxWig0I4WS5iG0nZzA=
+
+Name: system/bin/vold
+SHA1-Digest: qsLVo0YIthlfuZVIt5rAzb5b/lU=
+
+Name: system/bin/pvrsrvinit
+SHA1-Digest: V7MYfTFC5pKMa/bEGeFFdpIEdZE=
+
+Name: system/bin/wpa_cli
+SHA1-Digest: MdD6aqkYWLMgJKXAPFjR6+bSbzA=
+
+Name: system/bin/schedtest
+SHA1-Digest: vSYLfGiDtsnwGTrlCO45/X2YOEs=
+
+Name: system/bin/unyaffs
+SHA1-Digest: 33fBy3mJicN74QYoZgl8pwkNpTU=
+
+Name: system/etc/01_Vendor_ti_omx.cfg
+SHA1-Digest: nH4yxxP+mJTflHgfZLkoZluz2ys=
+
+Name: system/fonts/DroidSerif-BoldItalic.ttf
+SHA1-Digest: wWAtwRvw9xMa7CHHw4iBla145IY=
+
+Name: system/media/audio/ui/KeypressStandard.ogg
+SHA1-Digest: WFdYi785ujyp6JwqtdsHziO5hjU=
+
+Name: system/etc/dhcpcd/dhcpcd-hooks/95-configured
+SHA1-Digest: Bx3HWG3Z64tjmNNnphc7KD9ltE8=
+
+Name: system/lib/libsonivox.so
+SHA1-Digest: +utZHcJMT7A0yr9qkZO0VSzAAco=
+
+Name: system/bin/ap_gain.bin
+SHA1-Digest: EGFjuXM4Tz6IUewS0OYEJrIJlM4=
+
+Name: system/xbin/hcidump
+SHA1-Digest: WaSOYtGU9HDEqfsd22VRD3Yzo50=
+
+Name: system/lib/libicuuc.so
+SHA1-Digest: G+2H+806xztt5Mp2tycY8A9+Zp8=
+
+Name: system/lib/libandroid_servers.so
+SHA1-Digest: tzjOOTiARy4rSSfcwbbKQJur3sc=
+
+Name: system/xbin/librank
+SHA1-Digest: KnMMjrqlkxILFQxLugvuB72Chyc=
+
+Name: system/lib/libz.so
+SHA1-Digest: qXZALbKCETX/y2NPUHzH4nJCV5k=
+
+Name: system/etc/init.d/05userinit
+SHA1-Digest: Jwtv6zqrniODFFrGHz9psEDrG7w=
+
+Name: system/bin/wlan_loader
+SHA1-Digest: EWyzIxowU7HM6vKF8b+Zl7losMg=
+
+Name: system/usr/srec/config/en.us/g2p/en-US-ttp.data
+SHA1-Digest: EeTucxvP4KvwmGxmWn6mzatobhQ=
+
+Name: system/bin/radiooptions
+SHA1-Digest: tz3HRmB2pIVrE/8aGHwwKfyZzoE=
+
+Name: system/xbin/timeinfo
+SHA1-Digest: tmB6zyTfyJetrf3W+wALMW5B8EA=
+
+Name: system/usr/srec/config/en.us/dictionary/cmu6plus.ok.zip
+SHA1-Digest: gix9zeNXUv3/qb72caDqmlPws9U=
+
+Name: system/lib/libreference-ril.so
+SHA1-Digest: XHqnSCxiWS8/uS35z/q/dfbZXF8=
+
+Name: system/lib/libGLESv1_CM.so
+SHA1-Digest: gVJH6r371GGTeGt7v2IdmT3TGo4=
+
+Name: system/etc/vendor/cpcap/macro_data
+SHA1-Digest: qlj5i/S+gAEsa7BVr06zoOFMm/4=
+
+Name: system/app/AccountAndSyncSettings.apk
+SHA1-Digest: ShPZWtI9u7BV9Q4M6VVMK8ZPp4Y=
+
+Name: system/bin/showlease
+SHA1-Digest: Iow5V/7F6eqtkxD6vHfkW4SMX0g=
+
+Name: system/app/googlevoice.apk
+SHA1-Digest: S1TaCuG5TRwLqy+WDnUJAw+cPT8=
+
+Name: system/etc/pvasflocal.cfg
+SHA1-Digest: UiNMuewTOXPRGYxBQQfbiwiX430=
+
+Name: system/bin/check_prereq
+SHA1-Digest: hok22N88YOU4dRoW8EEyM510uXw=
+
+Name: system/lib/libVendor_ti_omx.so
+SHA1-Digest: Vb6ma8FfafOZWsLqLxBo5YMauL0=
+
+Name: system/media/audio/ringtones/Champagne_Edition.ogg
+SHA1-Digest: esPrbBKq0PnHjnJrEbosjS+RQV0=
+
+Name: system/media/audio/ringtones/Funk_Yall.ogg
+SHA1-Digest: bTUJuGij78XPtGvYGLa1OX0f8X8=
+
+Name: system/media/audio/notifications/F1_New_MMS.ogg
+SHA1-Digest: ZDxbtCijMgIk3unZCNBIGcObmhE=
+
+Name: system/lib/libopencore_rtsp.so
+SHA1-Digest: HJoDbRIKOdnhzwnlYTMg0EDpqR8=
+
+Name: system/tts/lang_pico/de-DE_gl0_sg.bin
+SHA1-Digest: Tm6YYAq0JD0AJl6K4sBSqvymGGk=
+
+Name: system/media/audio/notifications/DontPanic.ogg
+SHA1-Digest: pvgx0GchjymMGo64MMLTPpnFCeU=
+
+Name: system/xbin/avtest
+SHA1-Digest: Qtsuc0dWcFJbQ2WJbhcgbtD2kDA=
+
+Name: system/app/Music.apk
+SHA1-Digest: UWMIEBIsW4VKiXLRFQsPf9r/700=
+
+Name: system/app/Term.apk
+SHA1-Digest: x08uHR15Hh0EYmYgHpp6mmClxDc=
+
+Name: system/lib/libreference-cdma-sms.so
+SHA1-Digest: nFvec4pV7x/LZOC+w4LECGL3T4Y=
+
+Name: system/media/audio/ringtones/World.ogg
+SHA1-Digest: gyfmfSAdpTHm8s9n/pFE1zF1XGo=
+
+Name: system/app/Facebook.apk
+SHA1-Digest: Vcn3orf77rZHQENxIbH07qNsCd4=
+
+Name: system/lib/hw/gralloc.omap3.so
+SHA1-Digest: 4TvvAGMivk5WgoSsu80gB4zCk6c=
+
+Name: system/fonts/DroidSans.ttf
+SHA1-Digest: 2ls8d1iiyPvEd1vradcVBJPH0xI=
+
+Name: system/xbin/lmptest
+SHA1-Digest: lFEMutLfIqDFuV0LX+RChpmev6k=
+
+Name: system/lib/libssl.so
+SHA1-Digest: yrGinxt5eTB8BkeUe2qEx7OUsz0=
+
+Name: system/etc/init.d/03firstboot
+SHA1-Digest: w6t6q9gUeRE2+c3bun8jqZvOoWU=
+
+Name: system/lib/libcutils.so
+SHA1-Digest: msW0P0X9kdorcrj+TrfAZoLBj3A=
+
+Name: system/xbin/scotest
+SHA1-Digest: DicMWUa6RvWtO6kpMhd+84Ca46g=
+
+Name: system/xbin/procmem
+SHA1-Digest: z5Nd0JWbyJAjS6eS6p0yALAIZus=
+
+Name: system/media/audio/ringtones/EtherShake.ogg
+SHA1-Digest: NiKWkI2F8IIjupEUKtBUeigWqIE=
+
+Name: system/build.prop
+SHA1-Digest: EEcpqScTJDuQ6Ro32AcgcF/eb8k=
+
+Name: system/usr/srec/config/en.us/models/generic8_m.swimdl
+SHA1-Digest: bFt0FGX1o+r+WlmE2dUzuoGlyao=
+
+Name: system/bin/debuggerd
+SHA1-Digest: 435M21L2Az6gcRXT2TheAs6+tqY=
+
+Name: system/lib/libEGL.so
+SHA1-Digest: gsH7TjaWhi8L50d9YzJu4w+TlRg=
+
+Name: system/lib/libpvrANDROID_WSEGL.so
+SHA1-Digest: gW86IXT/ZSjIRlhOMFrZbCL960s=
+
+Name: system/lib/libmoto_gps.so
+SHA1-Digest: sGh9ZeSLyvZYOxdrZh0QqsnE9+A=
+
+Name: system/media/audio/ringtones/MildlyAlarming.ogg
+SHA1-Digest: 4k0XurVfPApEkCgYUTKi/uLT1sA=
+
+Name: system/lib/libdrm1_jni.so
+SHA1-Digest: KqbScW/qD1zMBRje9WoSyJBCQvI=
+
+Name: system/usr/srec/config/en.us/baseline.par
+SHA1-Digest: mOE8GQoDRu/VLgUGSPxYHPuTfIc=
+
+Name: system/etc/dhcpcd/dhcpcd.conf
+SHA1-Digest: r/j6SUk2OTzgG7q+PDrb0yTGo5s=
+
+Name: system/app/SoundRecorder.apk
+SHA1-Digest: m4d0VripkfrSzgjZwHV77VbRIIM=
+
+Name: system/media/audio/alarms/Alarm_Buzzer.ogg
+SHA1-Digest: VtCKqWvleTvqHgGxm4oVDA0RBfU=
+
+Name: system/bin/ftmipcd
+SHA1-Digest: zHdAZGWyjH3I4vi5tYI3B/XK1iA=
+
+Name: system/lib/libOMX.TI.Video.encoder.so
+SHA1-Digest: LhUkz1VAkMxJTT/1fMPrbdXuazU=
+
+Name: system/xbin/procrank
+SHA1-Digest: VxUnVp18bib5rhepxzVzQW6+2MI=
+
+Name: system/framework/android.policy.jar
+SHA1-Digest: emRmN+oZukEmWFNqguvzFDWLCXg=
+
+Name: system/app/GoogleContactsSyncAdapter.apk
+SHA1-Digest: NXPv6HAFdzU+aOtjqTooeyMUOHs=
+
+Name: system/usr/srec/config/en.us/grammars/VoiceDialer.g2g
+SHA1-Digest: d505rUOtdG/rAwjHo2j8g16rJDo=
+
+Name: system/etc/vold.conf
+SHA1-Digest: LaZ64sZA7zWhxhxRiD93s/9Bvik=
+
+Name: system/lib/dsp/wbamrenc_sn.dll64P
+SHA1-Digest: BCJYAbnJTHSM2LqNZDAujsPx6UU=
+
+Name: system/media/audio/notifications/TaDa.ogg
+SHA1-Digest: 6Nl+aLRFsxE78qVDMBmNBDhnHoM=
+
+Name: system/xbin/add-property-tag
+SHA1-Digest: b9+1Sgy6RM0IgerFa05n1e3kpv8=
+
+Name: system/lib/libstagefrighthw.so
+SHA1-Digest: 6W6OCR4pLRzR20Bojcoy4U9shuU=
+
+Name: system/etc/init.d/99complete
+SHA1-Digest: GJOqw3ZjV0A4RndQ4jYuwsJL2gU=
+
+Name: system/media/audio/alarms/Alarm_Rooster_02.ogg
+SHA1-Digest: JhaluUQTr5D/bqpvzCXxM4fZMOw=
+
+Name: system/framework/framework.jar
+SHA1-Digest: t60LwZ+Ur4lRv5c0kLOTwhdYMys=
+
+Name: system/xbin/hstest
+SHA1-Digest: 5gEdIKsh11LP4Dhpdnh5SxxzwS4=
+
+Name: system/lib/libVendor_ti_omx_config_parser.so
+SHA1-Digest: /Um7kfAxsRhiRpltsXexaHUwfpQ=
+
+Name: system/media/audio/ringtones/BussaMove.ogg
+SHA1-Digest: oguWfy6XljWZ8Di8erEPg5r2Waw=
+
+Name: system/media/audio/ringtones/Seville.ogg
+SHA1-Digest: i74ARuYFFMCbQRq2aJOx8mW/K40=
+
+Name: system/app/VisualizationWallpapers.apk
+SHA1-Digest: 1mWpYaJUSLXiraY0coyLH+Dnaa4=
+
+Name: system/app/Superuser.apk
+SHA1-Digest: ZG/0PbP8+VWSzmAyxIhAu1Pmac0=
+
+Name: system/xbin/latencytop
+SHA1-Digest: e3usNuoZEsVcyVfPqXdBFSsNNlo=
+
+Name: system/xbin/oprofiled
+SHA1-Digest: hhzUngmcFtj2sbw6GVRdZpZN95g=
+
+Name: system/etc/fstab
+SHA1-Digest: unky+hpvPF4/i2BCV28O1U8NeQo=
+
+Name: system/lib/dsp/usn.dll64P
+SHA1-Digest: coWgA0PvVhJx28vIzwB8sJpazPo=
+
+Name: system/etc/permissions/android.hardware.sensor.proximity.xml
+SHA1-Digest: Ir4TfyGxk4QiuORZa9Esndgmxfk=
+
+Name: system/lib/libpvasfcommon.so
+SHA1-Digest: +dwEed/iLOaZY6v+R40ZqgbBFRo=
+
+Name: system/framework/monkey.jar
+SHA1-Digest: PRkOd30OVSmyOY3/VnKu9at1g9c=
+
+Name: system/lib/libmedia.so
+SHA1-Digest: kI3PfEhiP15qlwxmHPNGzuML7AU=
+
+Name: system/xbin/tcpdump
+SHA1-Digest: YjUuEfAUYkxg+IJ4ldvUHH5XhHo=
+
+Name: system/app/Mms.apk
+SHA1-Digest: GQbU5VUcb223NfUrqtpE13v05ig=
+
+Name: system/lib/dsp/m4venc_sn.dll64P
+SHA1-Digest: hTnomiDJDWE5gbeeiRv74IRPEiM=
+
+Name: system/lib/libopencore_downloadreg.so
+SHA1-Digest: QDV0hmNhFKCoUPCHtMrzFrZq334=
+
+Name: system/lib/libwbxml_jni.so
+SHA1-Digest: +9NmcJmib/5+ZRemOdaJU+AAXMA=
+
+Name: system/bin/wpa_supplicant
+SHA1-Digest: 7Wk5GyJGHPiXMes5h+J00wu3MdI=
+
+Name: system/fonts/DroidSans-Bold.ttf
+SHA1-Digest: raTnnFkvPFRUa3WHtI8rIy2Vzi8=
+
+Name: system/app/LiveWallpapers.apk
+SHA1-Digest: 2jhnMfbPxk/BKcIo/914zItb3Y8=
+
+Name: system/app/LatinImeTutorial.apk
+SHA1-Digest: fbZYoQzqws0pyDUACGe5MpfFMqo=
+
+Name: system/app/HTMLViewer.apk
+SHA1-Digest: xzTYMLlDKZ+1QnzJfSCqrJcg4jQ=
+
+Name: system/xbin/crasher
+SHA1-Digest: BBEcuPaAYje14UR//+mcaNLzpcs=
+
+Name: system/lib/libnetutils.so
+SHA1-Digest: bwQMrFUuV9knTSGJcM95CLB/KfU=
+
+Name: system/lib/libomx_wmadec_sharedlibrary.so
+SHA1-Digest: 30nMWMBj/JAK/duwd9zU6rY6iKM=
+
+Name: system/bin/recovery
+SHA1-Digest: EBOveK+RGcU5R6v19bCzKRGp4vg=
+
+Name: system/lib/librs_jni.so
+SHA1-Digest: xDAVTTbXrTkPJaQipI2/vDgtaYc=
+
+Name: system/bin/logcat
+SHA1-Digest: NPsaEli+Kt2uoS8V7OohTRSSlGA=
+
+Name: system/etc/permissions/android.hardware.touchscreen.multitouch.x
+ ml
+SHA1-Digest: UYQyq4o46E60Eop6Ho1WPW879wM=
+
+Name: system/lib/libbinder.so
+SHA1-Digest: ishB7ZRdCkQEkKbsF33XljvmZD0=
+
+Name: system/xbin/rctest
+SHA1-Digest: X811VtwXZ2uGGbJ34lPC/NqN6CQ=
+
+Name: system/bin/wlan_cu
+SHA1-Digest: uNjuvaNqDlk6na1FodbQBFwUMGQ=
+
+Name: system/bin/netcfg
+SHA1-Digest: nDUiX6jzvxL0DxxbZa5OGitMT2M=
+
+Name: system/usr/srec/config/en.us/dictionary/basic.ok
+SHA1-Digest: /nwZFjqTU6CKLzpmEnxPxb7aqks=
+
+Name: system/app/SetupWizard.apk
+SHA1-Digest: lEsSmwUH/Au7bXHu4vTmU9aq9Mo=
+
+Name: system/lib/libLCML.so
+SHA1-Digest: xvCJoekco+96u2afwZi4Rg2Y0h8=
+
+Name: system/xbin/attest
+SHA1-Digest: XuVEAz5D9V9dU/kV9YTTra7yjck=
+
+Name: system/lib/libttssynthproxy.so
+SHA1-Digest: NI54ctFsfU4Lvs+F1g3JGdMw6Lg=
+
+Name: system/media/audio/ringtones/CurveBall.ogg
+SHA1-Digest: caUx/gIqqrDoh5d8LIfMo60fHxE=
+
+Name: system/bin/compcache
+SHA1-Digest: K8Hq3cETtR+zHQApRr2tMnA1BGM=
+
+Name: system/lib/libbridge.so
+SHA1-Digest: XBDzy2GjGJztfCV4+37BSKBLo3E=
+
+Name: system/lib/egl/libGLESv1_CM_POWERVR_SGX530_121.so
+SHA1-Digest: OhJ3r2VzAxAn5c8MuA3Agxxp1tY=
+
+Name: system/etc/bluez/input.conf
+SHA1-Digest: Tgwt4ltLhyMYLAEDfZMe0/GHQ8c=
+
+Name: system/bin/dalvikvm
+SHA1-Digest: tlewLUORThlcB2zcuCY8KP+fNdU=
+
+Name: system/framework/core.jar
+SHA1-Digest: qjNOzrz7xcgHXCUd7EVb4fbEYiA=
+
+Name: system/framework/ime.jar
+SHA1-Digest: TZPkA6VZyY70CYw0mh2gxAo40+o=
+
+Name: system/media/audio/notifications/F1_MissedCall.ogg
+SHA1-Digest: yknFSdzyGFZj1bYrnuPvZJBZHfM=
+
+Name: system/etc/firmware/wl1271.bin
+SHA1-Digest: eP3pzNE4S7q2bxpot3XYF1agAhk=
+
+Name: system/etc/dnsmasq.conf
+SHA1-Digest: nnIG3TNzVtuhxAgyyS2Uumir/Ig=
+
+Name: system/usr/share/zoneinfo/zoneinfo.version
+SHA1-Digest: PjLoI+6w6ftcfRN8cCLGJXEfOYo=
+
+Name: system/lib/dsp/baseimage.dof
+SHA1-Digest: 0UAW3DT/+EwxURXwUPBd/tBq+vU=
+
+Name: system/lib/invoke_mock_media_player.so
+SHA1-Digest: NyDdNW5pZ36CLDHNmAvv+5RGroI=
+
+Name: system/etc/ppp/ip-up-vpn
+SHA1-Digest: 5mBHeZ0MVERmMtBIdIIqD6eFYLs=
+
+Name: system/framework/input.jar
+SHA1-Digest: EA0t7EZJbK04yDCKtzUabq0ADZg=
+
+Name: system/bin/SaveBPVer
+SHA1-Digest: CKOp+OKsGR0uwo+XCv77ngJfax8=
+
+Name: system/app/Calendar.apk
+SHA1-Digest: 4+uoxis+NOmpL859QF5bTP7HbOs=
+
+Name: system/xbin/showmap
+SHA1-Digest: H3xZmlGLszlwlVJr4/Z/Xyz/GDg=
+
+Name: system/lib/libmediaplayerservice.so
+SHA1-Digest: h/FQi+sXBrjvy7LLxZWr7DgF1eg=
+
+Name: system/media/audio/ringtones/Ring_Synth_04.ogg
+SHA1-Digest: vI1klZ5YZXy7m2sGhPE5xWrm/ow=
+
+Name: system/bin/keystore
+SHA1-Digest: Pg4bWiTvg47tEWRCy9AjJAcFNOg=
+
+Name: system/lib/libgtalk_jni.so
+SHA1-Digest: g4oKKqXqpJuY+qne4sPvM0H97T0=
+
+Name: system/bin/fix_permissions
+SHA1-Digest: 9ujb7m6sE0IiwxsrawTRoDRLDq4=
+
+Name: system/bin/flash_image
+SHA1-Digest: InDDo69YUV2uff4MXML6hnThR9k=
+
+Name: system/app/CertInstaller.apk
+SHA1-Digest: /Wgc4irGf4r06TQh+VEP6kokBRI=
+
+Name: system/lib/libOMX.TI.Video.Decoder.so
+SHA1-Digest: DAq8oacCWv+OwsFvE1+/xP0Sofs=
+
+Name: system/app/MarketUpdater.apk
+SHA1-Digest: XeSXdUYXeCr1p8aw87fHfLMEDJk=
+
+Name: system/app/VpnServices.apk
+SHA1-Digest: UGUfg5L95ZIzlep3vu3omL3LMak=
+
+Name: system/bin/battd
+SHA1-Digest: PCs02wvnjMiOyp6CDu22X0rtRS8=
+
+Name: system/etc/cameraCalFileDef.bin
+SHA1-Digest: W7vl6l1BM0v4rQvQhqUblmYhYuY=
+
+Name: system/lib/libnmea.so
+SHA1-Digest: 8njQqI3pSfjwFwIELn5GJrDLwrI=
+
+Name: system/lib/libc.so
+SHA1-Digest: 46tOPTXzv/0Bxyq32mbSNl6zomE=
+
+Name: system/app/GoogleSettingsProvider.apk
+SHA1-Digest: F9SfhH3PbmzpAfa+mThL/SSzHA4=
+
+Name: system/lib/hw/sensors.goldfish.so
+SHA1-Digest: AzodonrqYQQNS1y4hyY6V12jBQA=
+
+Name: system/lib/libicudata.so
+SHA1-Digest: DyaN44wwfEXhlDlA5CJ12eL1Izk=
+
+Name: system/tts/lang_pico/es-ES_ta.bin
+SHA1-Digest: pNLmuNKy3n8IL1+g9ohMWMeKi/A=
+
+Name: system/bin/mtpd
+SHA1-Digest: yLVNCmljT3gLdNyEu09d7RCnydg=
+
+Name: META-INF/com/google/android/updater-script
+SHA1-Digest: A2OiQMXAdQ/6REFLDUoSyyc0bI4=
+
+Name: system/media/audio/ringtones/Cairo.ogg
+SHA1-Digest: Wu1Tj8Y+jFP5JQjo9tA46NAXzHo=
+
+Name: system/bin/dump_image
+SHA1-Digest: MezOLOdf2o367SwvQ1JSHdLP2tw=
+
+Name: system/app/Street.apk
+SHA1-Digest: iN67gaFp1wES4Zzh758j3eYI2kY=
+
+Name: system/etc/permissions/com.google.android.gtalkservice.xml
+SHA1-Digest: 8LUBoeTWHJQGW3JZMxpkv6YCgIM=
+
+Name: system/lib/libbluedroid.so
+SHA1-Digest: 5ae+z7ATsYuySpapfr03uUg1PBo=
+
+Name: system/media/audio/ringtones/BirdLoop.ogg
+SHA1-Digest: RYVSjXjMHcZg8XPUlE1qk6YYMII=
+
+Name: system/lib/libjni_pinyinime.so
+SHA1-Digest: YQEPR7Md1JA0sJC9JDE77RoINfA=
+
+Name: system/bin/monkey
+SHA1-Digest: EuahMwdKZ8XXZ3Dq0yOrSronmBs=
+
+Name: system/framework/framework-tests.jar
+SHA1-Digest: uJeNAp5Kaq/LmXexgIjqFWmMen4=
+
+Name: system/lib/libdbus.so
+SHA1-Digest: pzy2OfyrHFTNv1hNdRKjoTU6Co8=
+
+Name: system/etc/ppp/peers/pppd-ril.options
+SHA1-Digest: 4T5iMdK99ptXEVn9M6YltqGSpEk=
+
+Name: system/lib/libaudioflinger.so
+SHA1-Digest: e8KnFoPgJUl2IpgUxp7DuNYCWZE=
+
+Name: system/media/audio/ui/KeypressDelete.ogg
+SHA1-Digest: bZEM7p2jzlwy0AICXAOSF3LdqGw=
+
+Name: system/lib/libstdc++.so
+SHA1-Digest: o+NOhViTYZfG7IuKH1uZ5UNOnCs=
+
+Name: system/media/audio/notifications/pixiedust.ogg
+SHA1-Digest: Yq+A5vQcS/Crf5p4QWHtzFUzqeo=
+
+Name: system/usr/keychars/sholes-keypad.kcm.bin
+SHA1-Digest: SBim+OyKqVJ/1FpvLLf0guoq7nA=
+
+Name: system/lib/libjni_latinime.so
+SHA1-Digest: HHhs9M+rhRH6FOzLTweYonQsZTQ=
+
+Name: system/tts/lang_pico/fr-FR_ta.bin
+SHA1-Digest: rVFLIwmW8ECL/i4NH8rQN4i6NNg=
+
+Name: system/app/GlobalSearch.apk
+SHA1-Digest: /QK70s+jaVhcUTQtcFS06348vcM=
+
+Name: system/lib/dsp/mpeg4aacenc_sn.dll64P
+SHA1-Digest: W/a51K01RNP6U1r8OEzDqDn1Zuw=
+
+Name: system/bin/service
+SHA1-Digest: DiZpwTR9/+oum+fBIKiN6YS7zMQ=
+
+Name: system/media/audio/ringtones/LoveFlute.ogg
+SHA1-Digest: pFizy1Z0ZkRaHi3MkgwVV3sVuCw=
+
+Name: system/media/audio/ringtones/Shes_All_That.ogg
+SHA1-Digest: uBTEc31R1CJoKBCHSn20tvxXHf4=
+
+Name: system/bin/racoon
+SHA1-Digest: V6I61xq+LYq3ucRxzR81HlyBuyM=
+
+Name: system/media/audio/ringtones/DonMessWivIt.ogg
+SHA1-Digest: EDblLh6e8Ftzqsa1MbImc2jtfH0=
+
+Name: system/lib/libsqlite.so
+SHA1-Digest: oAqmCUJJOSg6r+WIK/NgNje2YGc=
+
+Name: system/app/GoogleSubscribedFeedsProvider.apk
+SHA1-Digest: FoWoX1WYGUXS+YI5CTXx9LCUIwk=
+
+Name: system/fonts/DroidSansMono.ttf
+SHA1-Digest: 8IFcbzbHK+HQ8vXiuC+oXIv5VlU=
+
+Name: system/fonts/DroidSansFallback.ttf
+SHA1-Digest: +UURxXUfLQCfXjZRbeCyPSEL9Y0=
+
+Name: META-INF/com/google/android/update-script
+SHA1-Digest: 3TNMYnESf6gs3d07vraREpvKOUE=
+
+Name: system/media/audio/notifications/Tinkerbell.ogg
+SHA1-Digest: pqg0+/U/fm7flY7jUkBGVslsiV4=
+
+Name: system/app/Settings.apk
+SHA1-Digest: S/tonzcixMI+gxQuI4HGAyLYekA=
+
+Name: system/lib/libopencore_net_support.so
+SHA1-Digest: D9HQf97RiuytuIXJwoYsjxWvrrE=
+
+Name: system/bin/applypatch
+SHA1-Digest: RcnYqlgBJRqiQfgcgAS5Da6R/N4=
+
+Name: system/lib/dsp/nbamrenc_sn.dll64P
+SHA1-Digest: ui8P8vPP+K4Oj4ZIuX1nrpiBEmc=
+
+Name: system/lib/libopencore_download.so
+SHA1-Digest: H8hxHHl3jVmiC39yuE+BxVS6T2M=
+
+Name: system/media/audio/ringtones/Growl.ogg
+SHA1-Digest: Sw2PM10h0ouQLIH8v21n7myXN7I=
+
+Name: system/lib/dsp/postprocessor_dualout.dll64P
+SHA1-Digest: h+/f9WZtZCZfYd7SpMhyhfqMRzs=
+
+Name: system/bin/dbus-daemon
+SHA1-Digest: Nekm8+QT0jfFApldtwuWCHDqoxI=
+
+Name: system/bin/svc
+SHA1-Digest: laWKf0PV0fXkGCVIDLsyLTOEAMc=
+
+Name: system/app/Browser.apk
+SHA1-Digest: ET5BZKn9Kh0hfPP2HMMvjLjsfWc=
+
+Name: system/app/Gallery3D.apk
+SHA1-Digest: yZBqC9ZKFBzcclpRBHoPFsCQWyg=
+
+Name: system/bin/input
+SHA1-Digest: QALzgk6btxyAeKYglJuc20newks=
+
+Name: system/media/audio/ringtones/OrganDub.ogg
+SHA1-Digest: B0hF9Oq6Ixz2/YNXo1zjEh12grM=
+
+Name: system/app/Gmail.apk
+SHA1-Digest: HMW5IMGOK+mRpVuzqogeWnnPLY0=
+
+Name: system/lib/libpppd_plugin-ril.so
+SHA1-Digest: ry3//tRZeonBO4cfBi2fdenB0SM=
+
+Name: system/media/audio/notifications/tweeters.ogg
+SHA1-Digest: Br+2brWDR9+PWPNVtoSFWZHOdao=
+
+Name: system/media/audio/ringtones/Ding.ogg
+SHA1-Digest: +2fD8KGZD2CYEqTc4lDo80frSp0=
+
+Name: system/app/TtsService.apk
+SHA1-Digest: MYAYZeaEqCz5KPv9s8FxF36XlVY=
+
+Name: system/media/audio/notifications/Beat_Box_Android.ogg
+SHA1-Digest: bd1z7M+noewQDmKs5wYZwZSH10c=
+
+Name: system/bin/usb-tether
+SHA1-Digest: X48J0HuROO2wvwFX2qVGVz4rGa0=
+
+Name: system/app/GoogleApps.apk
+SHA1-Digest: EbNqP5WZw3sfo6YY5az/ZSligGg=
+
+Name: system/xbin/su
+SHA1-Digest: uUZVDEq6hKERDKzKrLaYgEyaY+s=
+
+Name: system/fonts/DroidSerif-Bold.ttf
+SHA1-Digest: 14lrnAcjKZVT6VoA0ny+UvdRXIw=
+
+Name: system/bin/mkyaffs2image
+SHA1-Digest: IsMTVQYrXbhsDY0n90F0q4e9a9M=
+
+Name: system/lib/libc_debug.so
+SHA1-Digest: VgGvQIjyj11Xp70HBN7SAPq7h2s=
+
+Name: system/bin/dumpsys
+SHA1-Digest: /ZZubuP3F8/FdS2JJtImBwzPeck=
+
+Name: system/usr/keylayout/AVRCP.kl
+SHA1-Digest: UbvW1cYTqi83Ear/5AzpYG9w52E=
+
+Name: system/media/audio/ringtones/Calypso_Steel.ogg
+SHA1-Digest: rMAikmGoWc4QIoaY8XM5sv8lPe4=
+
+Name: system/bin/dumpstate
+SHA1-Digest: caLITCf9pavAgMtPJ8NI2HI2QvA=
+
+Name: system/lib/dsp/h264vdec_sn.dll64P
+SHA1-Digest: wVg2QTmGkGr607WajaYSbeFtIYU=
+
+Name: system/lib/libFLAC.so
+SHA1-Digest: hDUSpc/TKO+o9fo4oiajTzK3110=
+
+Name: system/lib/libcamera.so
+SHA1-Digest: yNLS/1RJ6FvmPLn63d2EuyZgfRw=
+
+Name: system/xbin/btool
+SHA1-Digest: MM/a710YHqnotehhRFilc20reCE=
+
+Name: system/app/Phone.apk
+SHA1-Digest: NC1GHVa+y/mw7wU0f0NowfpuWhQ=
+
+Name: system/app/TelephonyProvider.apk
+SHA1-Digest: U4QFZwJtOcRmVLGwEUy7/AwFbS0=
+
+Name: system/lib/libnativehelper.so
+SHA1-Digest: RhMnprXlFmNIJCrqmike4TAdNT8=
+
+Name: system/bin/dvz
+SHA1-Digest: H8vQqZ9MLswgu9vZdIgJr8NeL04=
+
+Name: system/xbin/nc
+SHA1-Digest: tTc8llV3Qa5/sZsRbRFpyc++XgQ=
+
+Name: system/etc/dbus.conf
+SHA1-Digest: tFSSxBd60rDOWFVGzFY7lMyaFcs=
+
+Name: system/bin/toolbox
+SHA1-Digest: KQxyaaOjeiAethxRj0m7XvssqGA=
+
+Name: system/etc/security/cacerts.bks
+SHA1-Digest: fXQVVCTfaUbxvrCVTi2sRctuL7w=
+
+Name: system/xbin/scp
+SHA1-Digest: 0wpN0J1m5LNK38bWi3kg/nH3AR0=
+
+Name: system/media/audio/ringtones/Steppin_Out.ogg
+SHA1-Digest: dNC3VLVUwKgjX+8vHJ3FVAPG1Vc=
+
+Name: system/lib/libdvm.so
+SHA1-Digest: nt82gz3ES/71ElcEdMuvywD0ZMM=
+
+Name: system/media/audio/notifications/KzurbSonar.ogg
+SHA1-Digest: 8PjixrBAEb9YkpuOd/Vdb2isbTc=
+
+Name: system/usr/srec/config/en.us/baseline11k.par
+SHA1-Digest: Mq1IVDJlLzTaUQHLe+XE3eS3jPQ=
+
+Name: system/usr/keylayout/sholes-keypad.kl
+SHA1-Digest: 0m7QkILO9jyHsHNOmdOYMQdgNUo=
+
+Name: system/bin/iptables
+SHA1-Digest: XzLAZUT0GBFLom1XJtwGQgKR51c=
+
+Name: system/media/audio/notifications/Plastic_Pipe.ogg
+SHA1-Digest: WkcBmxIwrC4GozDBaKrXl0hLejY=
+
+Name: system/lib/libutils.so
+SHA1-Digest: PPdgNQGspA0AWlot4xxI4l6j82s=
+
+Name: system/etc/NOTICE.html.gz
+SHA1-Digest: zf/jbY8KlwaxoqyoH2tQZsNgPbg=
+
+Name: system/lib/libstagefright.so
+SHA1-Digest: TDLew0yGnI/05wwYm+WtAaXj0e8=
+
+Name: system/bin/installd
+SHA1-Digest: wwIIpCgYMbCGmdKiKVLpGe2l9S8=
+
+Name: system/media/audio/notifications/pizzicato.ogg
+SHA1-Digest: bSV+J4IqXsas7z3tp5SozNYcKUI=
+
+Name: system/etc/init.d/00banner
+SHA1-Digest: 0JvB42ZqQeFzW35K9RREqxE1Z3k=
+
+Name: META-INF/com/google/android/update-binary
+SHA1-Digest: S8DOFyaN6V4S7TVCOZbED9BWxmA=
+
+Name: system/lib/libinterstitial.so
+SHA1-Digest: 2HiStNCV5Xhuzh/EfSGQVbWY7ZU=
+
+Name: system/lib/libhardware_legacy.so
+SHA1-Digest: HpZcq+sld7wVXoXvRLSB73MFbGI=
+
+Name: system/xbin/dropbearkey
+SHA1-Digest: NIf7tVkHqNyvMytAx/KNg7UQKTw=
+
+Name: system/app/PassionQuickOffice.apk
+SHA1-Digest: Rx1bUKbIgn67I4+2hU4CEqOO2CU=
+
+Name: system/lib/libFFTEm.so
+SHA1-Digest: Xva9iz3e+F9dULyWZjlfHLqgK2I=
+
+Name: system/lib/libopencore_player.so
+SHA1-Digest: 4aC4Jq4Xpy0HIQKp5OBE5s98Pkg=
+
+Name: system/lib/hw/lights.sholes.so
+SHA1-Digest: MJ5yMLMfGyOuiEApCumT+Hx5yLY=
+
+Name: system/usr/share/zoneinfo/zoneinfo.idx
+SHA1-Digest: LOd3n5eygwOKosr5GBgCpQYFiz8=
+
+Name: system/lib/dsp/jpegenc_sn.dll64P
+SHA1-Digest: ZJ/Go12MXFldA4XQJomNozLuFqw=
+
+Name: system/etc/dhcpcd/dhcpcd-hooks/20-dns.conf
+SHA1-Digest: mOSkCz4GKlLKyPWmpkR/Z+sFMvc=
+
+Name: system/tts/lang_pico/de-DE_ta.bin
+SHA1-Digest: cwdePIurlh9G2BMZzHra87JUunI=
+
+Name: system/xbin/sqlite3
+SHA1-Digest: GOMA1LQTnK89zXHXEs2ptIO6yM8=
+
+Name: system/lib/libbluetooth.so
+SHA1-Digest: uye9KvV7Kw0xwsXRLSfJgTOpPPc=
+
+Name: system/media/audio/ringtones/Playa.ogg
+SHA1-Digest: SbrgqdRkRkClgD/CLsbXdj3oVXE=
+
+Name: system/app/MagicSmokeWallpapers.apk
+SHA1-Digest: iB61mM0QyelE0LTLgz8zng67df4=
+
+Name: system/lib/libopencore_mp4localreg.so
+SHA1-Digest: 2xxyolC8TzFdctEIUIRZGeGMIWA=
+
+Name: system/xbin/dbus-send
+SHA1-Digest: +bLGmtnGPhsqwhjQZLlp3a8CY/Q=
+
+Name: system/usr/share/bmd/RFFstd_501.bmd
+SHA1-Digest: 0k98ukIhHL0h2zs4tRS2FMidCtE=
+
+Name: system/lib/libomx_amrdec_sharedlibrary.so
+SHA1-Digest: QEb/bobXKKMadHoBh+lilCvudEE=
+
+Name: system/xbin/hciconfig
+SHA1-Digest: aXSClrllaSshRNWuoo2YZefIz2I=
+
+Name: system/app/GmailProvider.apk
+SHA1-Digest: bzgG+fBcTwNH7/Af2H4kzvrRmo4=
+
+Name: system/lib/egl/egl.cfg
+SHA1-Digest: uK4Lt+GDOvu+/0l5WBlj0f8/fQY=
+
+Name: system/bin/shutdown
+SHA1-Digest: xTQggVgzgoLSryT5OWrVjV52Syo=
+
+Name: system/etc/permissions/com.google.android.maps.xml
+SHA1-Digest: BbK4aFOA+G3wd2qESxbxITfwZYM=
+
+Name: system/media/audio/notifications/moonbeam.ogg
+SHA1-Digest: tLYdZg4VRMe2cRL9Vl+yC0h2O10=
+
+Name: system/xbin/dbus-monitor
+SHA1-Digest: CW3tvP9q8v8hbrVUHIp6MIznFY0=
+
+Name: system/lib/hw/sensors.sholes.so
+SHA1-Digest: 3m59wcgKNgNWTS/zNp/LCCB+O38=
+
+Name: system/usr/share/zoneinfo/zoneinfo.dat
+SHA1-Digest: KcT4777/fImEElXQ1N7Y45FANR4=
+
+Name: system/app/Email.apk
+SHA1-Digest: XeEP9h1AG2z4nzmMb0Mr7hXjg2c=
+
+Name: system/media/audio/ringtones/TwirlAway.ogg
+SHA1-Digest: blTx6mtBWYYR9LPSijRqEYiANsY=
+
+Name: system/lib/libicui18n.so
+SHA1-Digest: NYF4Z6J4CEQ+xmDrhUV1lUwBQ7M=
+
+Name: system/bin/pppd-ril
+SHA1-Digest: KXHSUihwhvt2nyV0Oj88OODobks=
+
+Name: system/bin/sh
+SHA1-Digest: 6LOefzrQlbtwQUOdU3KSHLPeFoE=
+
+Name: system/usr/srec/config/en.us/dictionary/enroll.ok
+SHA1-Digest: rcl7CO9ZOIxVX+yaPLoqJv8ZtwY=
+
+Name: system/etc/permissions/android.hardware.sensor.light.xml
+SHA1-Digest: o5fC0OmTC1XhEfP9A5C41jbAt2w=
+
+Name: system/lib/libOMX.TI.WBAMR.encode.so
+SHA1-Digest: 6MC9bJ+MCcdG0XucGkDtWATzAMU=
+
+Name: system/media/audio/notifications/F1_New_SMS.ogg
+SHA1-Digest: CJJKBUbpfCwTi++7C7Jvf5hbJ2Q=
+
+Name: system/framework/ext.jar
+SHA1-Digest: 0e8zkOrJ69wBuhAwWi+gRzljnH4=
+
+Name: recovery/recovery-from-boot.p
+SHA1-Digest: AiGU6mSkHKYMzEbhJnWC+MyGZqE=
+
+Name: system/media/audio/ringtones/Bollywood.ogg
+SHA1-Digest: IdN6NI8pDVcoJ9tzm9H6JwBC02U=
+
+Name: system/etc/permissions/android.hardware.camera.flash-autofocus.x
+ ml
+SHA1-Digest: B9lECmkbQ6pSctxuPBeUiDPmthA=
+
+Name: system/app/DownloadProvider.apk
+SHA1-Digest: MGmmUBqZG7lM2LqgF6v7OoX8Q5Y=
+
+Name: system/lib/libmedia_jni.so
+SHA1-Digest: HauWGlAHxxd/jJyot9gIkFSox6Y=
+
+Name: system/app/GoogleCheckin.apk
+SHA1-Digest: IKEt52hPMYP8MvTxCLTC+BUMFBg=
+
+Name: system/media/audio/ringtones/No_Limits.ogg
+SHA1-Digest: XAELJ6mvSSWmVJzcMXqKwsdsZt8=
+
+Name: system/media/audio/alarms/Alarm_Classic.ogg
+SHA1-Digest: E2gJ5/u593JhCG9fsMgrNxzopjE=
+
+Name: system/lib/libspeech.so
+SHA1-Digest: HkJxLH0dFCnKM5n7r0xbvJgFPVg=
+
+Name: system/usr/srec/config/en.us/models/generic8.lda
+SHA1-Digest: /y/sXjBSqRQkFc848OCkAh9PhTE=
+
+Name: system/lib/libhardware.so
+SHA1-Digest: 94P60WFVYBJ+55IeHnlbhbT7+Jw=
+
+Name: system/lib/libglslcompiler.so
+SHA1-Digest: hAeofMkOJuFN2jN5BhPaqwy23JU=
+
+Name: system/app/Talk.apk
+SHA1-Digest: Cc7aLNoSfDR+Da3actgxOXG8tXg=
+
+Name: system/framework/com.cyanogenmod.android.jar
+SHA1-Digest: b1knN0gEktAwPnHRs+wUVmZDSz8=
+
+Name: system/lib/libsrec_jni.so
+SHA1-Digest: t38GCGPRgD/sYT+GCBdnsgKbF5k=
+
+Name: system/xbin/daemonize
+SHA1-Digest: nhYdzomtkV1AEWbv4IuZIqx/oxA=
+
+Name: system/lib/libsrv_um.so
+SHA1-Digest: 7Aaf9YCdJIvrqSDsCXCBCvuiRIE=
+
+Name: system/lib/modules/tiwlan_drv.ko
+SHA1-Digest: VMlywzOjfKPxXaH1KABZGWur1SQ=
+
+Name: system/framework/services.jar
+SHA1-Digest: e8HekrgM1KqRzzCK24U3bTQMOks=
+
+Name: system/media/audio/notifications/Doink.ogg
+SHA1-Digest: ER8L9DVZQWrQdyHSsTJLrT9oMi8=
+
+Name: system/bin/fsck_msdos
+SHA1-Digest: 4rJ5GCCLmQ2ZKbFq1EPKPoDQpcg=
+
+Name: system/app/MediaProvider.apk
+SHA1-Digest: UXZ/vzwO2dkcNdO6+vSRPLU6v9o=
+
+Name: system/media/audio/ringtones/DancinFool.ogg
+SHA1-Digest: BbZ9r+HeEb7McJR/ybLMoMHqbd0=
+
+Name: system/usr/srec/config/en.us/models/generic11_f.swimdl
+SHA1-Digest: 5e8IIA7SPCk0zXso+yzwYfaIl4Q=
+
+Name: system/usr/keylayout/cpcap-key.kl
+SHA1-Digest: J2axNrueX/sMOYnVILIBb1Ctioc=
+
+Name: system/xbin/cpueater
+SHA1-Digest: mJFRVe92UmF4DlFNHPCI6vmqYE4=
+
+Name: system/tts/lang_pico/it-IT_ta.bin
+SHA1-Digest: TDYB40+wY/jh/Gh2+f5KUkAxG/Q=
+
+Name: system/app/com.amazon.mp3.apk
+SHA1-Digest: l3LJ/XUtuzb48xd4zkz3BqNwubA=
+
+Name: system/app/DrmProvider.apk
+SHA1-Digest: 0rhaNokMDoL5YRxSiSvSofuBNq0=
+
+Name: system/lib/libskiagl.so
+SHA1-Digest: YA1y1ikQwv38L0KeoJzzsiCiqR8=
+
+Name: system/bin/mdm_panicd
+SHA1-Digest: 9GSGGEnA1MVOjhil8cwDnJPzY54=
+
+Name: system/lib/libomx_mp3dec_sharedlibrary.so
+SHA1-Digest: AZRM0VypbkLzmuc015hSrUlolKs=
+
+Name: system/xbin/avinfo
+SHA1-Digest: PcvttjsOjySWHvYEpwGAFpY8iGM=
+
+Name: system/xbin/hcitool
+SHA1-Digest: fGZ7sdat9NizVS7wolGhX4rDqes=
+
+Name: system/etc/dhcpcd/dhcpcd-run-hooks
+SHA1-Digest: u36Xc6dkZAzq4Qwfn6rrAYbaVfM=
+
+Name: system/tts/lang_pico/en-US_lh0_sg.bin
+SHA1-Digest: dQD1vzURXrJa4wSg3tcBxGqr7G0=
+
+Name: system/bin/am
+SHA1-Digest: tGduMx5JPECn+7U+fdIzcrCdrlk=
+
+Name: system/xbin/showslab
+SHA1-Digest: 8Pei9pDT6eEfxJbLPrG/0G/iG2A=
+
+Name: system/app/HtcCopyright.apk
+SHA1-Digest: z8WH4HjbMhqPfxuqz1jlw/6T+Ro=
+
+Name: system/etc/apns-conf.xml
+SHA1-Digest: XXUcR0+AZIIT2gUqJfkYnK5fw34=
+
+Name: system/bin/hciattach
+SHA1-Digest: blU3To3/zto4ZYQVGrG2M/eToWI=
+
+Name: system/xbin/opcontrol
+SHA1-Digest: hw+jRHw6wBo4mxbK6h0Lb1Q6Crw=
+
+Name: system/usr/srec/config/en.us/models/generic8_f.swimdl
+SHA1-Digest: GgnYWcIdaKmXR6fAvPMIhiEu1Wo=
+
+Name: system/bin/picd
+SHA1-Digest: SVDMNlOm7KG6feXbGUPUQoY7v54=
+
+Name: system/lib/libskia.so
+SHA1-Digest: cW6wkeKX1ryvnxLMti5tEDi/gY4=
+
+Name: system/app/Calculator.apk
+SHA1-Digest: TgYXrl5GmCTYiV/Fu8HemZFrSvw=
+
+Name: system/lib/libsurfaceflinger.so
+SHA1-Digest: 7wC8mkl72FJIqV5gDuTUGtnjD1c=
+
+Name: system/bin/gzip
+SHA1-Digest: bajNR+OHBpHMHJ4BwdY/YwPhpEs=
+
+Name: system/app/NetworkLocation.apk
+SHA1-Digest: W4Lka5651tunYKcdyXfUXkhcrnw=
+
+Name: system/media/audio/ringtones/Nassau.ogg
+SHA1-Digest: UxAOHSzF6B3ws8+wHazzGoWu0IE=
+
+Name: system/bin/bthelp
+SHA1-Digest: lXkz4ursAPjdAAlHPgwmzrFWEPU=
+
+Name: system/bin/sdptool
+SHA1-Digest: Sp/HVnXhGmSGl73V9xvuEuTl65w=
+
+Name: system/lib/libOMX.TI.AAC.encode.so
+SHA1-Digest: 8iwhlY35SYlVnwQPMWKT1YtTHk4=
+
+Name: system/fonts/Clockopia.ttf
+SHA1-Digest: iw96Cm9uf/w/SbVQekBynrfv48I=
+
+Name: system/framework/android.test.runner.jar
+SHA1-Digest: L52Ewe9KxZ9Yxb/rQRwTEg3ZJrc=
+
+Name: system/media/audio/ringtones/Gimme_Mo_Town.ogg
+SHA1-Digest: jxLAdtBtLZWcPDzvjvOiaECZ9GY=
+
+Name: system/framework/pm.jar
+SHA1-Digest: bn2WzziqzJomQvE/oEn5RaUOenk=
+
+Name: system/lib/libPERF.so
+SHA1-Digest: og4KUxIIt6tJYl0ltbTEuQHiSeA=
+
+Name: system/lib/libbattd.so
+SHA1-Digest: 8qTYmJALmS6awdF6X0POMyzBGLw=
+
+Name: system/lib/libmoto_ril.so
+SHA1-Digest: YltVW7CppJG6Z6krpu9K4wIrChs=
+
+Name: system/etc/hosts
+SHA1-Digest: qoLbiBHBDHEvqhMNitAGjBu/De8=
+
+Name: system/app/Camera.apk
+SHA1-Digest: aROQGuqAaEhdTJA1r6WdWgKMJTY=
+
+Name: system/app/PicoTts.apk
+SHA1-Digest: 10vygTUGSBp4M6y76U0XSHUcdyo=
+
+Name: system/etc/sysctl.conf
+SHA1-Digest: 2jmj7l5rSw0yVb/vlWAYkK/YBwk=
+
+Name: system/media/audio/ui/VideoRecord.ogg
+SHA1-Digest: lNxenUZXTJQfFT2OxJHkWx8URbg=
+
+Name: system/app/Launcher2.apk
+SHA1-Digest: 8NwnjHCisA4ocz3raS1MmaDIhs4=
+
+Name: system/bin/logwrapper
+SHA1-Digest: pmKP3KLgr4hvchaXZuS33SqUymg=
+
+Name: system/framework/am.jar
+SHA1-Digest: cuV2xs0E6Zl/e4bPE3Z1x+6VjPg=
+
+Name: system/lib/libttspico.so
+SHA1-Digest: erIZ9Ly0NZHJzdnuHoUsLcQOMGo=
+
+Name: system/bin/app_process
+SHA1-Digest: 4F1oCLnEfxKqa/rEvoBasjUzydg=
+
+Name: system/xbin/dexdump
+SHA1-Digest: R3SDPBT8QUEcXEmGq/NA1Bha3fg=
+
+Name: system/app/DeskClock.apk
+SHA1-Digest: ZOYQhe2FgKl5JNC5x6jf2446mbI=
+
+Name: system/media/audio/ringtones/CrayonRock.ogg
+SHA1-Digest: DNaxkL8L38L3top7fT1b4bn+POs=
+
+Name: system/media/audio/ringtones/Big_Easy.ogg
+SHA1-Digest: Po/q9Ek2+3nuG8LkRgTY2OZAj8E=
+
+Name: system/bin/sdutil
+SHA1-Digest: pLZkvNRl9qH2Hs0T0Kh4tXIRA8Y=
+
+Name: system/lib/libaudiopolicygeneric.so
+SHA1-Digest: td/Pd+TgfBFrc43PKdl65bL7IV0=
+
+Name: system/lib/modules/wl127x_test.ko
+SHA1-Digest: lOMKr6Q8D0T6A/lxV7r01lXcKEI=
+
+Name: system/lib/libctest.so
+SHA1-Digest: +6Qd8wG2D2TAALbUnfdwPk31s7U=
+
+Name: system/lib/libterm.so
+SHA1-Digest: aqqlJmgK0/0KYscNIDJQD14y0gY=
+
+Name: system/media/audio/notifications/Voila.ogg
+SHA1-Digest: Vgp0tlasszURGzqkpv18KW6052I=
+
+Name: system/app/gtalkservice.apk
+SHA1-Digest: /xOxFoBZ6htEPkINhIvFWCpZt6o=
+
+Name: system/usr/srec/config/en.us/models/generic11.lda
+SHA1-Digest: /y/sXjBSqRQkFc848OCkAh9PhTE=
+
+Name: system/lib/libHPImgApi.so
+SHA1-Digest: cyS8T43bFY40xfGrKLN8ZWfd9BY=
+
+Name: system/lib/libcameraservice.so
+SHA1-Digest: hNt2Qtzw4zR2VaJi4muEP7zOLSw=
+
+Name: system/bin/applypatch_static
+SHA1-Digest: iwcMsc6H8gc0048CAEd6UCW9yE8=
+
+Name: system/xbin/agent
+SHA1-Digest: rEV9yZm/0sy4KCSR/cVg+mPnnIY=
+
+Name: system/lib/libomx_m4vdec_sharedlibrary.so
+SHA1-Digest: Y1ebyw11BfbQgAYwa4yBsTYSfLs=
+
+Name: system/app/CalendarProvider.apk
+SHA1-Digest: Ez4IRuDfmF04ey5qyLGREpoMFtQ=
+
+Name: system/media/audio/ringtones/Enter_the_Nexus.ogg
+SHA1-Digest: mLYNvCNYnKhcSp8V8lVXQ137hTA=
+
+Name: system/lib/dsp/mp4vdec_sn.dll64P
+SHA1-Digest: xSMqHsyGmBpTWROYiD6aEo2bO4w=
+
+Name: system/lib/libOMX.TI.JPEG.Encoder.so
+SHA1-Digest: slrhJwQsX6qIIARwln7x/ml0owM=
+
+Name: system/xbin/strace
+SHA1-Digest: KgJXdyw+tgAP4v5pnNUVFOEJjXo=
+
+Name: system/media/audio/ringtones/HalfwayHome.ogg
+SHA1-Digest: WmgmslPp4WieG3XbK6B1cQQV57w=
+
+Name: system/xbin/dropbear
+SHA1-Digest: BSS8XjMcBfBaidn+qZFlmIzqlH0=
+
+Name: system/etc/gps.conf
+SHA1-Digest: chhGlmWDbn2LYgx1KBiKJ1D+Ve4=
+
+Name: system/app/Maps.apk
+SHA1-Digest: Qkjt7epjebXz01P+useqOL0FXpA=
+
+Name: system/lib/libomx_wmvdec_sharedlibrary.so
+SHA1-Digest: 6cFhOlYN11Z0KRa09RE2uibWMqE=
+
+Name: system/usr/keylayout/qwerty.kl
+SHA1-Digest: Txu6Vy7q9pPb/qpnLzudT372ak8=
+
+Name: system/app/VoiceDialer.apk
+SHA1-Digest: HONHUKV10aDQNO88IPgLPcRunZM=
+
+Name: system/framework/com.google.android.maps.jar
+SHA1-Digest: yub294vTwuQWKdbQqdysVIVLiF0=
+
+Name: system/media/audio/notifications/OnTheHunt.ogg
+SHA1-Digest: zAIQHLBvgqgE3jbWB8UeCc+Wxis=
+
+Name: system/xbin/l2test
+SHA1-Digest: 0aP1gjA/Y+dU493NkOJASgkawKM=
+
+Name: system/media/audio/notifications/DearDeer.ogg
+SHA1-Digest: iq1AmmBFNXzh7VopP5NqbwZf+Gk=
+
+Name: system/media/audio/notifications/Cricket.ogg
+SHA1-Digest: NpFveOeUG++Fu9AA2dz90yZ52Bs=
+
+Name: system/lib/libomx_sharedlibrary.so
+SHA1-Digest: lEm4cjvEjnGvd5TMkppeG7z6r84=
+
+Name: system/app/TalkProvider.apk
+SHA1-Digest: 6CIg4IvM4Mem2tUKEZjU2yO1kiM=
+
+Name: system/bin/servicemanager
+SHA1-Digest: 3FK3JZZyfSdOrIoysc67lS+597M=
+
+Name: system/framework/javax.obex.jar
+SHA1-Digest: 68Znvc1q4Po0wd7ViyaGGtNlr3Y=
+
+Name: system/lib/libthread_db.so
+SHA1-Digest: /ICPq4Jcoe4/wO/ARVO0RONsQnw=
+
+Name: system/tts/lang_pico/fr-FR_nk0_sg.bin
+SHA1-Digest: 6unqLoUjPJ/ozhN8wxGOh7Lb+Aw=
+
+Name: system/xbin/openvpn
+SHA1-Digest: 08uolLEEo2tHXHTYIzCbQ7LL2ds=
+
+Name: system/lib/libopencore_rtspreg.so
+SHA1-Digest: WX2ehSUowgvs8Y+FNt/WtBEH+0I=
+
+Name: system/tts/lang_pico/en-GB_ta.bin
+SHA1-Digest: O92zn5smwWIc3U9Pms11gFIGwHE=
+
+Name: system/media/audio/notifications/Heaven.ogg
+SHA1-Digest: jGewjg2m5+5bVmE98bUc78RO9ts=
+
+Name: system/lib/libsystem_server.so
+SHA1-Digest: Tz6YJnRvy9wIe7J0HH665A9ivVk=
+
+Name: system/lib/bluez-plugin/input.so
+SHA1-Digest: JnqaGh9YYUwSz8h2KWbRRK6Y2b8=
+
+Name: system/lib/dsp/conversions.dll64P
+SHA1-Digest: E9VFb71dEHKf+RcBaHPv1cDabv8=
+
+Name: system/tts/lang_pico/es-ES_zl0_sg.bin
+SHA1-Digest: G70e/LrL8d4m47RJzZtaU8UxIfE=
+
+Name: system/etc/wifi/tiwlan.ini
+SHA1-Digest: rGA/qSfn5h4z0gWr2NoiZSxAOlU=
+
+Name: system/media/audio/ringtones/Club_Cubano.ogg
+SHA1-Digest: MPXwYj7Xd6qdmm7MKsiBjUFPPMA=
+
+Name: system/lib/libGLESv2.so
+SHA1-Digest: /wSaPamLYBIFZdnNgkhjv1BHN9M=
+
diff --git a/bin/META-INF/com/google/android/update-binary b/bin/META-INF/com/google/android/update-binary
new file mode 100755
index 0000000..cb5fefe
--- /dev/null
+++ b/bin/META-INF/com/google/android/update-binary
Binary files differ
diff --git a/bin/META-INF/com/google/android/updater-script b/bin/META-INF/com/google/android/updater-script
new file mode 100644
index 0000000..2ea65d1
--- /dev/null
+++ b/bin/META-INF/com/google/android/updater-script
@@ -0,0 +1,20 @@
+ui_print("CyanogenMOD Team and Koush kernel instalation presents NEW Kernel.");
+ui_print("CyanogenMOD & Teamhackung provided build auto tool (c) 2012");
+ui_print("Extracting System Files...");
+set_progress(1.000000);
+mount("ext4", "EMMC", "/dev/block/platform/s3c-sdhci.0/by-name/system", "/system");
+package_extract_dir("system", "/system");
+set_perm(0, 0, 06755, "/system/xbin/su");
+unmount("/system");
+ui_print("Extracting Kernel files...");
+package_extract_dir("kernel", "/tmp");
+ui_print("Installing kernel...");
+set_perm(0, 0, 0777, "/tmp/dump_image");
+set_perm(0, 0, 0777, "/tmp/mkbootimg.sh");
+set_perm(0, 0, 0777, "/tmp/mkbootimg");
+set_perm(0, 0, 0777, "/tmp/unpackbootimg");
+run_program("/tmp/dump_image", "boot", "/tmp/boot.img");
+run_program("/tmp/unpackbootimg", "-i", "/tmp/boot.img", "-o", "/tmp/");
+run_program("/tmp/mkbootimg.sh");
+write_raw_image("/tmp/newboot.img", "boot");
+ui_print("Done!");
diff --git a/bin/kernel/dump_image b/bin/kernel/dump_image
new file mode 100755
index 0000000..75e6da0
--- /dev/null
+++ b/bin/kernel/dump_image
Binary files differ
diff --git a/bin/kernel/mkbootimg b/bin/kernel/mkbootimg
new file mode 100755
index 0000000..9635257
--- /dev/null
+++ b/bin/kernel/mkbootimg
Binary files differ
diff --git a/bin/kernel/mkbootimg.sh b/bin/kernel/mkbootimg.sh
new file mode 100644
index 0000000..0649b08
--- /dev/null
+++ b/bin/kernel/mkbootimg.sh
@@ -0,0 +1,8 @@
+#!/sbin/sh
+echo \#!/sbin/sh > /tmp/createnewboot.sh
+PAGESIZE_HEX=`cat /tmp/boot.img-pagesize`
+PAGESIZE_DEC=`printf "%d" 0x$PAGESIZE_HEX`
+echo /tmp/mkbootimg --kernel /tmp/zImage --ramdisk /tmp/boot.img-ramdisk.gz --cmdline \"$(cat /tmp/boot.img-cmdline)\" --base $(cat /tmp/boot.img-base) --pagesize $PAGESIZE_DEC --output /tmp/newboot.img >> /tmp/createnewboot.sh
+chmod 777 /tmp/createnewboot.sh
+/tmp/createnewboot.sh
+return $?
diff --git a/bin/kernel/unpackbootimg b/bin/kernel/unpackbootimg
new file mode 100755
index 0000000..9ca6a81
--- /dev/null
+++ b/bin/kernel/unpackbootimg
Binary files differ
diff --git a/block/Kconfig.iosched b/block/Kconfig.iosched
index 3199b76..5905452 100644
--- a/block/Kconfig.iosched
+++ b/block/Kconfig.iosched
@@ -43,6 +43,28 @@ config CFQ_GROUP_IOSCHED
---help---
Enable group IO scheduling in CFQ.
+config IOSCHED_BFQ
+ tristate "BFQ I/O scheduler"
+ depends on EXPERIMENTAL
+ default n
+ ---help---
+ The BFQ I/O scheduler tries to distribute bandwidth among
+ all processes according to their weights.
+ It aims at distributing the bandwidth as desired, independently of
+ the disk parameters and with any workload. It also tries to
+ guarantee low latency to interactive and soft real-time
+ applications. If compiled built-in (saying Y here), BFQ can
+ be configured to support hierarchical scheduling.
+
+config CGROUP_BFQIO
+ bool "BFQ hierarchical scheduling support"
+ depends on CGROUPS && IOSCHED_BFQ=y
+ default n
+ ---help---
+ Enable hierarchical scheduling in BFQ, using the cgroups
+ filesystem interface. The name of the subsystem will be
+ bfqio.
+
choice
prompt "Default I/O scheduler"
default DEFAULT_CFQ
@@ -56,6 +78,9 @@ choice
config DEFAULT_CFQ
bool "CFQ" if IOSCHED_CFQ=y
+ config DEFAULT_BFQ
+ bool "BFQ" if IOSCHED_BFQ=y
+
config DEFAULT_NOOP
bool "No-op"
@@ -65,6 +90,7 @@ config DEFAULT_IOSCHED
string
default "deadline" if DEFAULT_DEADLINE
default "cfq" if DEFAULT_CFQ
+ default "bfq" if DEFAULT_BFQ
default "noop" if DEFAULT_NOOP
endmenu
diff --git a/block/Makefile b/block/Makefile
index 0fec4b3..22d8608 100644
--- a/block/Makefile
+++ b/block/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_BLK_DEV_THROTTLING) += blk-throttle.o
obj-$(CONFIG_IOSCHED_NOOP) += noop-iosched.o
obj-$(CONFIG_IOSCHED_DEADLINE) += deadline-iosched.o
obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched.o
+obj-$(CONFIG_IOSCHED_BFQ) += bfq-iosched.o
obj-$(CONFIG_BLOCK_COMPAT) += compat_ioctl.o
obj-$(CONFIG_BLK_DEV_INTEGRITY) += blk-integrity.o
diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c
new file mode 100644
index 0000000..74ae73b
--- /dev/null
+++ b/block/bfq-cgroup.c
@@ -0,0 +1,831 @@
+/*
+ * BFQ: CGROUPS support.
+ *
+ * Based on ideas and code from CFQ:
+ * Copyright (C) 2003 Jens Axboe <axboe@kernel.dk>
+ *
+ * Copyright (C) 2008 Fabio Checconi <fabio@gandalf.sssup.it>
+ * Paolo Valente <paolo.valente@unimore.it>
+ *
+ * Licensed under the GPL-2 as detailed in the accompanying COPYING.BFQ file.
+ */
+
+#ifdef CONFIG_CGROUP_BFQIO
+static struct bfqio_cgroup bfqio_root_cgroup = {
+ .weight = BFQ_DEFAULT_GRP_WEIGHT,
+ .ioprio = BFQ_DEFAULT_GRP_IOPRIO,
+ .ioprio_class = BFQ_DEFAULT_GRP_CLASS,
+};
+
+static inline void bfq_init_entity(struct bfq_entity *entity,
+ struct bfq_group *bfqg)
+{
+ entity->weight = entity->new_weight;
+ entity->orig_weight = entity->new_weight;
+ entity->ioprio = entity->new_ioprio;
+ entity->ioprio_class = entity->new_ioprio_class;
+ entity->parent = bfqg->my_entity;
+ entity->sched_data = &bfqg->sched_data;
+}
+
+static struct bfqio_cgroup *cgroup_to_bfqio(struct cgroup *cgroup)
+{
+ return container_of(cgroup_subsys_state(cgroup, bfqio_subsys_id),
+ struct bfqio_cgroup, css);
+}
+
+/*
+ * Search the bfq_group for bfqd into the hash table (by now only a list)
+ * of bgrp. Must be called under rcu_read_lock().
+ */
+static struct bfq_group *bfqio_lookup_group(struct bfqio_cgroup *bgrp,
+ struct bfq_data *bfqd)
+{
+ struct bfq_group *bfqg;
+ struct hlist_node *n;
+ void *key;
+
+ hlist_for_each_entry_rcu(bfqg, n, &bgrp->group_data, group_node) {
+ key = rcu_dereference(bfqg->bfqd);
+ if (key == bfqd)
+ return bfqg;
+ }
+
+ return NULL;
+}
+
+static inline void bfq_group_init_entity(struct bfqio_cgroup *bgrp,
+ struct bfq_group *bfqg)
+{
+ struct bfq_entity *entity = &bfqg->entity;
+
+ entity->weight = entity->new_weight = bgrp->weight;
+ entity->orig_weight = entity->new_weight;
+ entity->ioprio = entity->new_ioprio = bgrp->ioprio;
+ entity->ioprio_class = entity->new_ioprio_class = bgrp->ioprio_class;
+ entity->ioprio_changed = 1;
+ entity->my_sched_data = &bfqg->sched_data;
+}
+
+static inline void bfq_group_set_parent(struct bfq_group *bfqg,
+ struct bfq_group *parent)
+{
+ struct bfq_entity *entity;
+
+ BUG_ON(parent == NULL);
+ BUG_ON(bfqg == NULL);
+
+ entity = &bfqg->entity;
+ entity->parent = parent->my_entity;
+ entity->sched_data = &parent->sched_data;
+}
+
+/**
+ * bfq_group_chain_alloc - allocate a chain of groups.
+ * @bfqd: queue descriptor.
+ * @cgroup: the leaf cgroup this chain starts from.
+ *
+ * Allocate a chain of groups starting from the one belonging to
+ * @cgroup up to the root cgroup. Stop if a cgroup on the chain
+ * to the root has already an allocated group on @bfqd.
+ */
+static struct bfq_group *bfq_group_chain_alloc(struct bfq_data *bfqd,
+ struct cgroup *cgroup)
+{
+ struct bfqio_cgroup *bgrp;
+ struct bfq_group *bfqg, *prev = NULL, *leaf = NULL;
+
+ for (; cgroup != NULL; cgroup = cgroup->parent) {
+ bgrp = cgroup_to_bfqio(cgroup);
+
+ bfqg = bfqio_lookup_group(bgrp, bfqd);
+ if (bfqg != NULL) {
+ /*
+ * All the cgroups in the path from there to the
+ * root must have a bfq_group for bfqd, so we don't
+ * need any more allocations.
+ */
+ break;
+ }
+
+ bfqg = kzalloc(sizeof(*bfqg), GFP_ATOMIC);
+ if (bfqg == NULL)
+ goto cleanup;
+
+ bfq_group_init_entity(bgrp, bfqg);
+ bfqg->my_entity = &bfqg->entity;
+
+ if (leaf == NULL) {
+ leaf = bfqg;
+ prev = leaf;
+ } else {
+ bfq_group_set_parent(prev, bfqg);
+ /*
+ * Build a list of allocated nodes using the bfqd
+ * filed, that is still unused and will be initialized
+ * only after the node will be connected.
+ */
+ prev->bfqd = bfqg;
+ prev = bfqg;
+ }
+ }
+
+ return leaf;
+
+cleanup:
+ while (leaf != NULL) {
+ prev = leaf;
+ leaf = leaf->bfqd;
+ kfree(prev);
+ }
+
+ return NULL;
+}
+
+/**
+ * bfq_group_chain_link - link an allocatd group chain to a cgroup hierarchy.
+ * @bfqd: the queue descriptor.
+ * @cgroup: the leaf cgroup to start from.
+ * @leaf: the leaf group (to be associated to @cgroup).
+ *
+ * Try to link a chain of groups to a cgroup hierarchy, connecting the
+ * nodes bottom-up, so we can be sure that when we find a cgroup in the
+ * hierarchy that already as a group associated to @bfqd all the nodes
+ * in the path to the root cgroup have one too.
+ *
+ * On locking: the queue lock protects the hierarchy (there is a hierarchy
+ * per device) while the bfqio_cgroup lock protects the list of groups
+ * belonging to the same cgroup.
+ */
+static void bfq_group_chain_link(struct bfq_data *bfqd, struct cgroup *cgroup,
+ struct bfq_group *leaf)
+{
+ struct bfqio_cgroup *bgrp;
+ struct bfq_group *bfqg, *next, *prev = NULL;
+ unsigned long flags;
+
+ assert_spin_locked(bfqd->queue->queue_lock);
+
+ for (; cgroup != NULL && leaf != NULL; cgroup = cgroup->parent) {
+ bgrp = cgroup_to_bfqio(cgroup);
+ next = leaf->bfqd;
+
+ bfqg = bfqio_lookup_group(bgrp, bfqd);
+ BUG_ON(bfqg != NULL);
+
+ spin_lock_irqsave(&bgrp->lock, flags);
+
+ rcu_assign_pointer(leaf->bfqd, bfqd);
+ hlist_add_head_rcu(&leaf->group_node, &bgrp->group_data);
+ hlist_add_head(&leaf->bfqd_node, &bfqd->group_list);
+
+ spin_unlock_irqrestore(&bgrp->lock, flags);
+
+ prev = leaf;
+ leaf = next;
+ }
+
+ BUG_ON(cgroup == NULL && leaf != NULL);
+ if (cgroup != NULL && prev != NULL) {
+ bgrp = cgroup_to_bfqio(cgroup);
+ bfqg = bfqio_lookup_group(bgrp, bfqd);
+ bfq_group_set_parent(prev, bfqg);
+ }
+}
+
+/**
+ * bfq_find_alloc_group - return the group associated to @bfqd in @cgroup.
+ * @bfqd: queue descriptor.
+ * @cgroup: cgroup being searched for.
+ *
+ * Return a group associated to @bfqd in @cgroup, allocating one if
+ * necessary. When a group is returned all the cgroups in the path
+ * to the root have a group associated to @bfqd.
+ *
+ * If the allocation fails, return the root group: this breaks guarantees
+ * but is a safe fallbak. If this loss becames a problem it can be
+ * mitigated using the equivalent weight (given by the product of the
+ * weights of the groups in the path from @group to the root) in the
+ * root scheduler.
+ *
+ * We allocate all the missing nodes in the path from the leaf cgroup
+ * to the root and we connect the nodes only after all the allocations
+ * have been successful.
+ */
+static struct bfq_group *bfq_find_alloc_group(struct bfq_data *bfqd,
+ struct cgroup *cgroup)
+{
+ struct bfqio_cgroup *bgrp = cgroup_to_bfqio(cgroup);
+ struct bfq_group *bfqg;
+
+ bfqg = bfqio_lookup_group(bgrp, bfqd);
+ if (bfqg != NULL)
+ return bfqg;
+
+ bfqg = bfq_group_chain_alloc(bfqd, cgroup);
+ if (bfqg != NULL)
+ bfq_group_chain_link(bfqd, cgroup, bfqg);
+ else
+ bfqg = bfqd->root_group;
+
+ return bfqg;
+}
+
+/**
+ * bfq_bfqq_move - migrate @bfqq to @bfqg.
+ * @bfqd: queue descriptor.
+ * @bfqq: the queue to move.
+ * @entity: @bfqq's entity.
+ * @bfqg: the group to move to.
+ *
+ * Move @bfqq to @bfqg, deactivating it from its old group and reactivating
+ * it on the new one. Avoid putting the entity on the old group idle tree.
+ *
+ * Must be called under the queue lock; the cgroup owning @bfqg must
+ * not disappear (by now this just means that we are called under
+ * rcu_read_lock()).
+ */
+static void bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq,
+ struct bfq_entity *entity, struct bfq_group *bfqg)
+{
+ int busy, resume;
+
+ busy = bfq_bfqq_busy(bfqq);
+ resume = !RB_EMPTY_ROOT(&bfqq->sort_list);
+
+ BUG_ON(resume && !entity->on_st);
+ BUG_ON(busy && !resume && entity->on_st && bfqq != bfqd->active_queue);
+
+ if (busy) {
+ BUG_ON(atomic_read(&bfqq->ref) < 2);
+
+ if (!resume)
+ bfq_del_bfqq_busy(bfqd, bfqq, 0);
+ else
+ bfq_deactivate_bfqq(bfqd, bfqq, 0);
+ } else if (entity->on_st)
+ bfq_put_idle_entity(bfq_entity_service_tree(entity), entity);
+
+ /*
+ * Here we use a reference to bfqg. We don't need a refcounter
+ * as the cgroup reference will not be dropped, so that its
+ * destroy() callback will not be invoked.
+ */
+ entity->parent = bfqg->my_entity;
+ entity->sched_data = &bfqg->sched_data;
+
+ if (busy && resume)
+ bfq_activate_bfqq(bfqd, bfqq);
+}
+
+/**
+ * __bfq_cic_change_cgroup - move @cic to @cgroup.
+ * @bfqd: the queue descriptor.
+ * @cic: the cic to move.
+ * @cgroup: the cgroup to move to.
+ *
+ * Move cic to cgroup, assuming that bfqd->queue is locked; the caller
+ * has to make sure that the reference to cgroup is valid across the call.
+ *
+ * NOTE: an alternative approach might have been to store the current
+ * cgroup in bfqq and getting a reference to it, reducing the lookup
+ * time here, at the price of slightly more complex code.
+ */
+static struct bfq_group *__bfq_cic_change_cgroup(struct bfq_data *bfqd,
+ struct cfq_io_context *cic,
+ struct cgroup *cgroup)
+{
+ struct bfq_queue *async_bfqq = cic_to_bfqq(cic, 0);
+ struct bfq_queue *sync_bfqq = cic_to_bfqq(cic, 1);
+ struct bfq_entity *entity;
+ struct bfq_group *bfqg;
+
+ bfqg = bfq_find_alloc_group(bfqd, cgroup);
+ if (async_bfqq != NULL) {
+ entity = &async_bfqq->entity;
+
+ if (entity->sched_data != &bfqg->sched_data) {
+ cic_set_bfqq(cic, NULL, 0);
+ bfq_log_bfqq(bfqd, async_bfqq,
+ "cic_change_group: %p %d",
+ async_bfqq, atomic_read(&async_bfqq->ref));
+ bfq_put_queue(async_bfqq);
+ }
+ }
+
+ if (sync_bfqq != NULL) {
+ entity = &sync_bfqq->entity;
+ if (entity->sched_data != &bfqg->sched_data)
+ bfq_bfqq_move(bfqd, sync_bfqq, entity, bfqg);
+ }
+
+ return bfqg;
+}
+
+/**
+ * bfq_cic_change_cgroup - move @cic to @cgroup.
+ * @cic: the cic being migrated.
+ * @cgroup: the destination cgroup.
+ *
+ * When the task owning @cic is moved to @cgroup, @cic is immediately
+ * moved into its new parent group.
+ */
+static void bfq_cic_change_cgroup(struct cfq_io_context *cic,
+ struct cgroup *cgroup)
+{
+ struct bfq_data *bfqd;
+ unsigned long uninitialized_var(flags);
+
+ bfqd = bfq_get_bfqd_locked(&cic->key, &flags);
+ if (bfqd != NULL &&
+ !strncmp(bfqd->queue->elevator->elevator_type->elevator_name,
+ "bfq", ELV_NAME_MAX)) {
+ __bfq_cic_change_cgroup(bfqd, cic, cgroup);
+ bfq_put_bfqd_unlock(bfqd, &flags);
+ }
+}
+
+/**
+ * bfq_cic_update_cgroup - update the cgroup of @cic.
+ * @cic: the @cic to update.
+ *
+ * Make sure that @cic is enqueued in the cgroup of the current task.
+ * We need this in addition to moving cics during the cgroup attach
+ * phase because the task owning @cic could be at its first disk
+ * access or we may end up in the root cgroup as the result of a
+ * memory allocation failure and here we try to move to the right
+ * group.
+ *
+ * Must be called under the queue lock. It is safe to use the returned
+ * value even after the rcu_read_unlock() as the migration/destruction
+ * paths act under the queue lock too. IOW it is impossible to race with
+ * group migration/destruction and end up with an invalid group as:
+ * a) here cgroup has not yet been destroyed, nor its destroy callback
+ * has started execution, as current holds a reference to it,
+ * b) if it is destroyed after rcu_read_unlock() [after current is
+ * migrated to a different cgroup] its attach() callback will have
+ * taken care of remove all the references to the old cgroup data.
+ */
+static struct bfq_group *bfq_cic_update_cgroup(struct cfq_io_context *cic)
+{
+ struct bfq_data *bfqd = cic->key;
+ struct bfq_group *bfqg;
+ struct cgroup *cgroup;
+
+ BUG_ON(bfqd == NULL);
+
+ rcu_read_lock();
+ cgroup = task_cgroup(current, bfqio_subsys_id);
+ bfqg = __bfq_cic_change_cgroup(bfqd, cic, cgroup);
+ rcu_read_unlock();
+
+ return bfqg;
+}
+
+/**
+ * bfq_flush_idle_tree - deactivate any entity on the idle tree of @st.
+ * @st: the service tree being flushed.
+ */
+static inline void bfq_flush_idle_tree(struct bfq_service_tree *st)
+{
+ struct bfq_entity *entity = st->first_idle;
+
+ for (; entity != NULL; entity = st->first_idle)
+ __bfq_deactivate_entity(entity, 0);
+}
+
+/**
+ * bfq_reparent_leaf_entity - move leaf entity to the root_group.
+ * @bfqd: the device data structure with the root group.
+ * @entity: the entity to move.
+ */
+static inline void bfq_reparent_leaf_entity(struct bfq_data *bfqd,
+ struct bfq_entity *entity)
+{
+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity);
+
+ BUG_ON(bfqq == NULL);
+ bfq_bfqq_move(bfqd, bfqq, entity, bfqd->root_group);
+ return;
+}
+
+/**
+ * bfq_reparent_active_entities - move to the root group all active entities.
+ * @bfqd: the device data structure with the root group.
+ * @bfqg: the group to move from.
+ * @st: the service tree with the entities.
+ *
+ * Needs queue_lock to be taken and reference to be valid over the call.
+ */
+static inline void bfq_reparent_active_entities(struct bfq_data *bfqd,
+ struct bfq_group *bfqg,
+ struct bfq_service_tree *st)
+{
+ struct rb_root *active = &st->active;
+ struct bfq_entity *entity = NULL;
+
+ if (!RB_EMPTY_ROOT(&st->active))
+ entity = bfq_entity_of(rb_first(active));
+
+ for (; entity != NULL ; entity = bfq_entity_of(rb_first(active)))
+ bfq_reparent_leaf_entity(bfqd, entity);
+
+ if (bfqg->sched_data.active_entity != NULL)
+ bfq_reparent_leaf_entity(bfqd, bfqg->sched_data.active_entity);
+
+ return;
+}
+
+/**
+ * bfq_destroy_group - destroy @bfqg.
+ * @bgrp: the bfqio_cgroup containing @bfqg.
+ * @bfqg: the group being destroyed.
+ *
+ * Destroy @bfqg, making sure that it is not referenced from its parent.
+ */
+static void bfq_destroy_group(struct bfqio_cgroup *bgrp, struct bfq_group *bfqg)
+{
+ struct bfq_data *bfqd;
+ struct bfq_service_tree *st;
+ struct bfq_entity *entity = bfqg->my_entity;
+ unsigned long uninitialized_var(flags);
+ int i;
+
+ hlist_del(&bfqg->group_node);
+
+ /*
+ * Empty all service_trees belonging to this group before deactivating
+ * the group itself.
+ */
+ for (i = 0; i < BFQ_IOPRIO_CLASSES; i++) {
+ st = bfqg->sched_data.service_tree + i;
+
+ /*
+ * The idle tree may still contain bfq_queues belonging
+ * to exited task because they never migrated to a different
+ * cgroup from the one being destroyed now. Noone else
+ * can access them so it's safe to act without any lock.
+ */
+ bfq_flush_idle_tree(st);
+
+ /*
+ * It may happen that some queues are still active
+ * (busy) upon group destruction (if the corresponding
+ * processes have been forced to terminate). We move
+ * all the leaf entities corresponding to these queues
+ * to the root_group.
+ * Also, it may happen that the group has an entity
+ * under service, which is disconnected from the active
+ * tree: it must be moved, too.
+ * There is no need to put the sync queues, as the
+ * scheduler has taken no reference.
+ */
+ bfqd = bfq_get_bfqd_locked(&bfqg->bfqd, &flags);
+ if (bfqd != NULL) {
+ bfq_reparent_active_entities(bfqd, bfqg, st);
+ bfq_put_bfqd_unlock(bfqd, &flags);
+ }
+ BUG_ON(!RB_EMPTY_ROOT(&st->active));
+ BUG_ON(!RB_EMPTY_ROOT(&st->idle));
+ }
+ BUG_ON(bfqg->sched_data.next_active != NULL);
+ BUG_ON(bfqg->sched_data.active_entity != NULL);
+
+ /*
+ * We may race with device destruction, take extra care when
+ * dereferencing bfqg->bfqd.
+ */
+ bfqd = bfq_get_bfqd_locked(&bfqg->bfqd, &flags);
+ if (bfqd != NULL) {
+ hlist_del(&bfqg->bfqd_node);
+ __bfq_deactivate_entity(entity, 0);
+ bfq_put_async_queues(bfqd, bfqg);
+ bfq_put_bfqd_unlock(bfqd, &flags);
+ }
+ BUG_ON(entity->tree != NULL);
+
+ /*
+ * No need to defer the kfree() to the end of the RCU grace
+ * period: we are called from the destroy() callback of our
+ * cgroup, so we can be sure that noone is a) still using
+ * this cgroup or b) doing lookups in it.
+ */
+ kfree(bfqg);
+}
+
+/**
+ * bfq_disconnect_groups - diconnect @bfqd from all its groups.
+ * @bfqd: the device descriptor being exited.
+ *
+ * When the device exits we just make sure that no lookup can return
+ * the now unused group structures. They will be deallocated on cgroup
+ * destruction.
+ */
+static void bfq_disconnect_groups(struct bfq_data *bfqd)
+{
+ struct hlist_node *pos, *n;
+ struct bfq_group *bfqg;
+
+ bfq_log(bfqd, "disconnect_groups beginning") ;
+ hlist_for_each_entry_safe(bfqg, pos, n, &bfqd->group_list, bfqd_node) {
+ hlist_del(&bfqg->bfqd_node);
+
+ __bfq_deactivate_entity(bfqg->my_entity, 0);
+
+ /*
+ * Don't remove from the group hash, just set an
+ * invalid key. No lookups can race with the
+ * assignment as bfqd is being destroyed; this
+ * implies also that new elements cannot be added
+ * to the list.
+ */
+ rcu_assign_pointer(bfqg->bfqd, NULL);
+
+ bfq_log(bfqd, "disconnect_groups: put async for group %p",
+ bfqg) ;
+ bfq_put_async_queues(bfqd, bfqg);
+ }
+}
+
+static inline void bfq_free_root_group(struct bfq_data *bfqd)
+{
+ struct bfqio_cgroup *bgrp = &bfqio_root_cgroup;
+ struct bfq_group *bfqg = bfqd->root_group;
+
+ bfq_put_async_queues(bfqd, bfqg);
+
+ spin_lock_irq(&bgrp->lock);
+ hlist_del_rcu(&bfqg->group_node);
+ spin_unlock_irq(&bgrp->lock);
+
+ /*
+ * No need to synchronize_rcu() here: since the device is gone
+ * there cannot be any read-side access to its root_group.
+ */
+ kfree(bfqg);
+}
+
+static struct bfq_group *bfq_alloc_root_group(struct bfq_data *bfqd, int node)
+{
+ struct bfq_group *bfqg;
+ struct bfqio_cgroup *bgrp;
+ int i;
+
+ bfqg = kmalloc_node(sizeof(*bfqg), GFP_KERNEL | __GFP_ZERO, node);
+ if (bfqg == NULL)
+ return NULL;
+
+ bfqg->entity.parent = NULL;
+ for (i = 0; i < BFQ_IOPRIO_CLASSES; i++)
+ bfqg->sched_data.service_tree[i] = BFQ_SERVICE_TREE_INIT;
+
+ bgrp = &bfqio_root_cgroup;
+ spin_lock_irq(&bgrp->lock);
+ rcu_assign_pointer(bfqg->bfqd, bfqd);
+ hlist_add_head_rcu(&bfqg->group_node, &bgrp->group_data);
+ spin_unlock_irq(&bgrp->lock);
+
+ return bfqg;
+}
+
+#define SHOW_FUNCTION(__VAR) \
+static u64 bfqio_cgroup_##__VAR##_read(struct cgroup *cgroup, \
+ struct cftype *cftype) \
+{ \
+ struct bfqio_cgroup *bgrp; \
+ u64 ret; \
+ \
+ if (!cgroup_lock_live_group(cgroup)) \
+ return -ENODEV; \
+ \
+ bgrp = cgroup_to_bfqio(cgroup); \
+ spin_lock_irq(&bgrp->lock); \
+ ret = bgrp->__VAR; \
+ spin_unlock_irq(&bgrp->lock); \
+ \
+ cgroup_unlock(); \
+ \
+ return ret; \
+}
+
+SHOW_FUNCTION(weight);
+SHOW_FUNCTION(ioprio);
+SHOW_FUNCTION(ioprio_class);
+#undef SHOW_FUNCTION
+
+#define STORE_FUNCTION(__VAR, __MIN, __MAX) \
+static int bfqio_cgroup_##__VAR##_write(struct cgroup *cgroup, \
+ struct cftype *cftype, \
+ u64 val) \
+{ \
+ struct bfqio_cgroup *bgrp; \
+ struct bfq_group *bfqg; \
+ struct hlist_node *n; \
+ \
+ if (val < (__MIN) || val > (__MAX)) \
+ return -EINVAL; \
+ \
+ if (!cgroup_lock_live_group(cgroup)) \
+ return -ENODEV; \
+ \
+ bgrp = cgroup_to_bfqio(cgroup); \
+ \
+ spin_lock_irq(&bgrp->lock); \
+ bgrp->__VAR = (unsigned short)val; \
+ hlist_for_each_entry(bfqg, n, &bgrp->group_data, group_node) { \
+ bfqg->entity.new_##__VAR = (unsigned short)val; \
+ smp_wmb(); \
+ bfqg->entity.ioprio_changed = 1; \
+ } \
+ spin_unlock_irq(&bgrp->lock); \
+ \
+ cgroup_unlock(); \
+ \
+ return 0; \
+}
+
+STORE_FUNCTION(weight, BFQ_MIN_WEIGHT, BFQ_MAX_WEIGHT);
+STORE_FUNCTION(ioprio, 0, IOPRIO_BE_NR - 1);
+STORE_FUNCTION(ioprio_class, IOPRIO_CLASS_RT, IOPRIO_CLASS_IDLE);
+#undef STORE_FUNCTION
+
+static struct cftype bfqio_files[] = {
+ {
+ .name = "weight",
+ .read_u64 = bfqio_cgroup_weight_read,
+ .write_u64 = bfqio_cgroup_weight_write,
+ },
+ {
+ .name = "ioprio",
+ .read_u64 = bfqio_cgroup_ioprio_read,
+ .write_u64 = bfqio_cgroup_ioprio_write,
+ },
+ {
+ .name = "ioprio_class",
+ .read_u64 = bfqio_cgroup_ioprio_class_read,
+ .write_u64 = bfqio_cgroup_ioprio_class_write,
+ },
+};
+
+static int bfqio_populate(struct cgroup_subsys *subsys, struct cgroup *cgroup)
+{
+ return cgroup_add_files(cgroup, subsys, bfqio_files,
+ ARRAY_SIZE(bfqio_files));
+}
+
+static struct cgroup_subsys_state *bfqio_create(struct cgroup_subsys *subsys,
+ struct cgroup *cgroup)
+{
+ struct bfqio_cgroup *bgrp;
+
+ if (cgroup->parent != NULL) {
+ bgrp = kzalloc(sizeof(*bgrp), GFP_KERNEL);
+ if (bgrp == NULL)
+ return ERR_PTR(-ENOMEM);
+ } else
+ bgrp = &bfqio_root_cgroup;
+
+ spin_lock_init(&bgrp->lock);
+ INIT_HLIST_HEAD(&bgrp->group_data);
+ bgrp->ioprio = BFQ_DEFAULT_GRP_IOPRIO;
+ bgrp->ioprio_class = BFQ_DEFAULT_GRP_CLASS;
+
+ return &bgrp->css;
+}
+
+/*
+ * We cannot support shared io contexts, as we have no mean to support
+ * two tasks with the same ioc in two different groups without major rework
+ * of the main cic/bfqq data structures. By now we allow a task to change
+ * its cgroup only if it's the only owner of its ioc; the drawback of this
+ * behavior is that a group containing a task that forked using CLONE_IO
+ * will not be destroyed until the tasks sharing the ioc die.
+ */
+static int bfqio_can_attach(struct cgroup_subsys *subsys, struct cgroup *cgroup,
+ struct task_struct *tsk)
+{
+ struct io_context *ioc;
+ int ret = 0;
+
+ /* task_lock() is needed to avoid races with exit_io_context() */
+ task_lock(tsk);
+ ioc = tsk->io_context;
+ if (ioc != NULL && atomic_read(&ioc->nr_tasks) > 1)
+ /*
+ * ioc == NULL means that the task is either too young or
+ * exiting: if it has still no ioc the ioc can't be shared,
+ * if the task is exiting the attach will fail anyway, no
+ * matter what we return here.
+ */
+ ret = -EINVAL;
+ task_unlock(tsk);
+
+ return ret;
+}
+
+static void bfqio_attach(struct cgroup_subsys *subsys, struct cgroup *cgroup,
+ struct cgroup *prev, struct task_struct *tsk)
+{
+ struct io_context *ioc;
+ struct cfq_io_context *cic;
+ struct hlist_node *n;
+
+ task_lock(tsk);
+ ioc = tsk->io_context;
+ if (ioc != NULL) {
+ BUG_ON(atomic_long_read(&ioc->refcount) == 0);
+ atomic_long_inc(&ioc->refcount);
+ }
+ task_unlock(tsk);
+
+ if (ioc == NULL)
+ return;
+
+ rcu_read_lock();
+ hlist_for_each_entry_rcu(cic, n, &ioc->bfq_cic_list, cic_list)
+ bfq_cic_change_cgroup(cic, cgroup);
+ rcu_read_unlock();
+
+ put_io_context(ioc);
+}
+
+static void bfqio_destroy(struct cgroup_subsys *subsys, struct cgroup *cgroup)
+{
+ struct bfqio_cgroup *bgrp = cgroup_to_bfqio(cgroup);
+ struct hlist_node *n, *tmp;
+ struct bfq_group *bfqg;
+
+ /*
+ * Since we are destroying the cgroup, there are no more tasks
+ * referencing it, and all the RCU grace periods that may have
+ * referenced it are ended (as the destruction of the parent
+ * cgroup is RCU-safe); bgrp->group_data will not be accessed by
+ * anything else and we don't need any synchronization.
+ */
+ hlist_for_each_entry_safe(bfqg, n, tmp, &bgrp->group_data, group_node)
+ bfq_destroy_group(bgrp, bfqg);
+
+ BUG_ON(!hlist_empty(&bgrp->group_data));
+
+ kfree(bgrp);
+}
+
+struct cgroup_subsys bfqio_subsys = {
+ .name = "bfqio",
+ .create = bfqio_create,
+ .can_attach = bfqio_can_attach,
+ .attach = bfqio_attach,
+ .destroy = bfqio_destroy,
+ .populate = bfqio_populate,
+ .subsys_id = bfqio_subsys_id,
+};
+#else
+static inline void bfq_init_entity(struct bfq_entity *entity,
+ struct bfq_group *bfqg)
+{
+ entity->weight = entity->new_weight;
+ entity->orig_weight = entity->new_weight;
+ entity->ioprio = entity->new_ioprio;
+ entity->ioprio_class = entity->new_ioprio_class;
+ entity->sched_data = &bfqg->sched_data;
+}
+
+static inline struct bfq_group *
+bfq_cic_update_cgroup(struct cfq_io_context *cic)
+{
+ struct bfq_data *bfqd = cic->key;
+ return bfqd->root_group;
+}
+
+static inline void bfq_bfqq_move(struct bfq_data *bfqd,
+ struct bfq_queue *bfqq,
+ struct bfq_entity *entity,
+ struct bfq_group *bfqg)
+{
+}
+
+static inline void bfq_disconnect_groups(struct bfq_data *bfqd)
+{
+ bfq_put_async_queues(bfqd, bfqd->root_group);
+}
+
+static inline void bfq_free_root_group(struct bfq_data *bfqd)
+{
+ kfree(bfqd->root_group);
+}
+
+static struct bfq_group *bfq_alloc_root_group(struct bfq_data *bfqd, int node)
+{
+ struct bfq_group *bfqg;
+ int i;
+
+ bfqg = kmalloc_node(sizeof(*bfqg), GFP_KERNEL | __GFP_ZERO, node);
+ if (bfqg == NULL)
+ return NULL;
+
+ for (i = 0; i < BFQ_IOPRIO_CLASSES; i++)
+ bfqg->sched_data.service_tree[i] = BFQ_SERVICE_TREE_INIT;
+
+ return bfqg;
+}
+#endif
diff --git a/block/bfq-ioc.c b/block/bfq-ioc.c
new file mode 100644
index 0000000..01f8313
--- /dev/null
+++ b/block/bfq-ioc.c
@@ -0,0 +1,380 @@
+/*
+ * BFQ: I/O context handling.
+ *
+ * Based on ideas and code from CFQ:
+ * Copyright (C) 2003 Jens Axboe <axboe@kernel.dk>
+ *
+ * Copyright (C) 2008 Fabio Checconi <fabio@gandalf.sssup.it>
+ * Paolo Valente <paolo.valente@unimore.it>
+ */
+
+/**
+ * bfq_cic_free_rcu - deferred cic freeing.
+ * @head: RCU head of the cic to free.
+ *
+ * Free the cic containing @head and, if it was the last one and
+ * the module is exiting wake up anyone waiting for its deallocation
+ * (see bfq_exit()).
+ */
+static void bfq_cic_free_rcu(struct rcu_head *head)
+{
+ struct cfq_io_context *cic;
+
+ cic = container_of(head, struct cfq_io_context, rcu_head);
+
+ kmem_cache_free(bfq_ioc_pool, cic);
+ elv_ioc_count_dec(bfq_ioc_count);
+
+ if (bfq_ioc_gone != NULL) {
+ spin_lock(&bfq_ioc_gone_lock);
+ if (bfq_ioc_gone != NULL &&
+ !elv_ioc_count_read(bfq_ioc_count)) {
+ complete(bfq_ioc_gone);
+ bfq_ioc_gone = NULL;
+ }
+ spin_unlock(&bfq_ioc_gone_lock);
+ }
+}
+
+static void bfq_cic_free(struct cfq_io_context *cic)
+{
+ call_rcu(&cic->rcu_head, bfq_cic_free_rcu);
+}
+
+/**
+ * cic_free_func - disconnect a cic ready to be freed.
+ * @ioc: the io_context @cic belongs to.
+ * @cic: the cic to be freed.
+ *
+ * Remove @cic from the @ioc radix tree hash and from its cic list,
+ * deferring the deallocation of @cic to the end of the current RCU
+ * grace period. This assumes that __bfq_exit_single_io_context()
+ * has already been called for @cic.
+ */
+static void cic_free_func(struct io_context *ioc, struct cfq_io_context *cic)
+{
+ unsigned long flags;
+ unsigned long dead_key = (unsigned long) cic->key;
+
+ BUG_ON(!(dead_key & CIC_DEAD_KEY));
+
+ spin_lock_irqsave(&ioc->lock, flags);
+ radix_tree_delete(&ioc->bfq_radix_root,
+ dead_key >> CIC_DEAD_INDEX_SHIFT);
+ hlist_del_init_rcu(&cic->cic_list);
+ spin_unlock_irqrestore(&ioc->lock, flags);
+
+ bfq_cic_free(cic);
+}
+
+static void bfq_free_io_context(struct io_context *ioc)
+{
+ /*
+ * ioc->refcount is zero here, or we are called from elv_unregister(),
+ * so no more cic's are allowed to be linked into this ioc. So it
+ * should be ok to iterate over the known list, we will see all cic's
+ * since no new ones are added.
+ */
+ call_for_each_cic(ioc, cic_free_func);
+}
+
+/**
+ * __bfq_exit_single_io_context - deassociate @cic from any running task.
+ * @bfqd: bfq_data on which @cic is valid.
+ * @cic: the cic being exited.
+ *
+ * Whenever no more tasks are using @cic or @bfqd is deallocated we
+ * need to invalidate its entry in the radix tree hash table and to
+ * release the queues it refers to.
+ *
+ * Called under the queue lock.
+ */
+static void __bfq_exit_single_io_context(struct bfq_data *bfqd,
+ struct cfq_io_context *cic)
+{
+ struct io_context *ioc = cic->ioc;
+
+ list_del_init(&cic->queue_list);
+
+ /*
+ * Make sure dead mark is seen for dead queues
+ */
+ smp_wmb();
+ rcu_assign_pointer(cic->key, bfqd_dead_key(bfqd));
+
+ /*
+ * No write-side locking as no task is using @ioc (they're exited
+ * or bfqd is being deallocated.
+ */
+ rcu_read_lock();
+ if (rcu_dereference(ioc->ioc_data) == cic) {
+ rcu_read_unlock();
+ spin_lock(&ioc->lock);
+ rcu_assign_pointer(ioc->ioc_data, NULL);
+ spin_unlock(&ioc->lock);
+ } else
+ rcu_read_unlock();
+
+ if (cic->cfqq[BLK_RW_ASYNC] != NULL) {
+ bfq_exit_bfqq(bfqd, cic->cfqq[BLK_RW_ASYNC]);
+ cic->cfqq[BLK_RW_ASYNC] = NULL;
+ }
+
+ if (cic->cfqq[BLK_RW_SYNC] != NULL) {
+ bfq_exit_bfqq(bfqd, cic->cfqq[BLK_RW_SYNC]);
+ cic->cfqq[BLK_RW_SYNC] = NULL;
+ }
+}
+
+/**
+ * bfq_exit_single_io_context - deassociate @cic from @ioc (unlocked version).
+ * @ioc: the io_context @cic belongs to.
+ * @cic: the cic being exited.
+ *
+ * Take the queue lock and call __bfq_exit_single_io_context() to do the
+ * rest of the work. We take care of possible races with bfq_exit_queue()
+ * using bfq_get_bfqd_locked() (and abusing a little bit the RCU mechanism).
+ */
+static void bfq_exit_single_io_context(struct io_context *ioc,
+ struct cfq_io_context *cic)
+{
+ struct bfq_data *bfqd;
+ unsigned long uninitialized_var(flags);
+
+ bfqd = bfq_get_bfqd_locked(&cic->key, &flags);
+ if (bfqd != NULL) {
+ __bfq_exit_single_io_context(bfqd, cic);
+ bfq_put_bfqd_unlock(bfqd, &flags);
+ }
+}
+
+/**
+ * bfq_exit_io_context - deassociate @ioc from all cics it owns.
+ * @ioc: the @ioc being exited.
+ *
+ * No more processes are using @ioc we need to clean up and put the
+ * internal structures we have that belongs to that process. Loop
+ * through all its cics, locking their queues and exiting them.
+ */
+static void bfq_exit_io_context(struct io_context *ioc)
+{
+ call_for_each_cic(ioc, bfq_exit_single_io_context);
+}
+
+static struct cfq_io_context *bfq_alloc_io_context(struct bfq_data *bfqd,
+ gfp_t gfp_mask)
+{
+ struct cfq_io_context *cic;
+
+ cic = kmem_cache_alloc_node(bfq_ioc_pool, gfp_mask | __GFP_ZERO,
+ bfqd->queue->node);
+ if (cic != NULL) {
+ cic->last_end_request = jiffies;
+ INIT_LIST_HEAD(&cic->queue_list);
+ INIT_HLIST_NODE(&cic->cic_list);
+ cic->dtor = bfq_free_io_context;
+ cic->exit = bfq_exit_io_context;
+ elv_ioc_count_inc(bfq_ioc_count);
+ }
+
+ return cic;
+}
+
+/**
+ * bfq_drop_dead_cic - free an exited cic.
+ * @bfqd: bfq data for the device in use.
+ * @ioc: io_context owning @cic.
+ * @cic: the @cic to free.
+ *
+ * We drop cfq io contexts lazily, so we may find a dead one.
+ */
+static void bfq_drop_dead_cic(struct bfq_data *bfqd, struct io_context *ioc,
+ struct cfq_io_context *cic)
+{
+ unsigned long flags;
+
+ WARN_ON(!list_empty(&cic->queue_list));
+ BUG_ON(cic->key != bfqd_dead_key(bfqd));
+
+ spin_lock_irqsave(&ioc->lock, flags);
+
+ BUG_ON(ioc->ioc_data == cic);
+
+ /*
+ * With shared I/O contexts two lookups may race and drop the
+ * same cic more than one time: RCU guarantees that the storage
+ * will not be freed too early, here we make sure that we do
+ * not try to remove the cic from the hashing structures multiple
+ * times.
+ */
+ if (!hlist_unhashed(&cic->cic_list)) {
+ radix_tree_delete(&ioc->bfq_radix_root, bfqd->cic_index);
+ hlist_del_init_rcu(&cic->cic_list);
+ bfq_cic_free(cic);
+ }
+
+ spin_unlock_irqrestore(&ioc->lock, flags);
+}
+
+/**
+ * bfq_cic_lookup - search into @ioc a cic associated to @bfqd.
+ * @bfqd: the lookup key.
+ * @ioc: the io_context of the process doing I/O.
+ *
+ * If @ioc already has a cic associated to @bfqd return it, return %NULL
+ * otherwise.
+ */
+static struct cfq_io_context *bfq_cic_lookup(struct bfq_data *bfqd,
+ struct io_context *ioc)
+{
+ struct cfq_io_context *cic;
+ unsigned long flags;
+ void *k;
+
+ if (unlikely(ioc == NULL))
+ return NULL;
+
+ rcu_read_lock();
+
+ /* We maintain a last-hit cache, to avoid browsing over the tree. */
+ cic = rcu_dereference(ioc->ioc_data);
+ if (cic != NULL) {
+ k = rcu_dereference(cic->key);
+ if (k == bfqd)
+ goto out;
+ }
+
+ do {
+ cic = radix_tree_lookup(&ioc->bfq_radix_root,
+ bfqd->cic_index);
+ if (cic == NULL)
+ goto out;
+
+ k = rcu_dereference(cic->key);
+ if (unlikely(k != bfqd)) {
+ rcu_read_unlock();
+ bfq_drop_dead_cic(bfqd, ioc, cic);
+ rcu_read_lock();
+ continue;
+ }
+
+ spin_lock_irqsave(&ioc->lock, flags);
+ rcu_assign_pointer(ioc->ioc_data, cic);
+ spin_unlock_irqrestore(&ioc->lock, flags);
+ break;
+ } while (1);
+
+out:
+ rcu_read_unlock();
+
+ return cic;
+}
+
+/**
+ * bfq_cic_link - add @cic to @ioc.
+ * @bfqd: bfq_data @cic refers to.
+ * @ioc: io_context @cic belongs to.
+ * @cic: the cic to link.
+ * @gfp_mask: the mask to use for radix tree preallocations.
+ *
+ * Add @cic to @ioc, using @bfqd as the search key. This enables us to
+ * lookup the process specific cfq io context when entered from the block
+ * layer. Also adds @cic to a per-bfqd list, used when this queue is
+ * removed.
+ */
+static int bfq_cic_link(struct bfq_data *bfqd, struct io_context *ioc,
+ struct cfq_io_context *cic, gfp_t gfp_mask)
+{
+ unsigned long flags;
+ int ret;
+
+ ret = radix_tree_preload(gfp_mask);
+ if (ret == 0) {
+ cic->ioc = ioc;
+
+ /* No write-side locking, cic is not published yet. */
+ rcu_assign_pointer(cic->key, bfqd);
+
+ spin_lock_irqsave(&ioc->lock, flags);
+ ret = radix_tree_insert(&ioc->bfq_radix_root,
+ bfqd->cic_index, cic);
+ if (ret == 0)
+ hlist_add_head_rcu(&cic->cic_list, &ioc->bfq_cic_list);
+ spin_unlock_irqrestore(&ioc->lock, flags);
+
+ radix_tree_preload_end();
+
+ if (ret == 0) {
+ spin_lock_irqsave(bfqd->queue->queue_lock, flags);
+ list_add(&cic->queue_list, &bfqd->cic_list);
+ spin_unlock_irqrestore(bfqd->queue->queue_lock, flags);
+ }
+ }
+
+ if (ret != 0)
+ printk(KERN_ERR "bfq: cic link failed!\n");
+
+ return ret;
+}
+
+/**
+ * bfq_ioc_set_ioprio - signal a priority change to the cics belonging to @ioc.
+ * @ioc: the io_context changing its priority.
+ */
+static inline void bfq_ioc_set_ioprio(struct io_context *ioc)
+{
+ call_for_each_cic(ioc, bfq_changed_ioprio);
+}
+
+/**
+ * bfq_get_io_context - return the @cic associated to @bfqd in @ioc.
+ * @bfqd: the search key.
+ * @gfp_mask: the mask to use for cic allocation.
+ *
+ * Setup general io context and cfq io context. There can be several cfq
+ * io contexts per general io context, if this process is doing io to more
+ * than one device managed by cfq.
+ */
+static struct cfq_io_context *bfq_get_io_context(struct bfq_data *bfqd,
+ gfp_t gfp_mask)
+{
+ struct io_context *ioc = NULL;
+ struct cfq_io_context *cic;
+
+ might_sleep_if(gfp_mask & __GFP_WAIT);
+
+ ioc = get_io_context(gfp_mask, bfqd->queue->node);
+ if (ioc == NULL)
+ return NULL;
+
+ /* Lookup for an existing cic. */
+ cic = bfq_cic_lookup(bfqd, ioc);
+ if (cic != NULL)
+ goto out;
+
+ /* Alloc one if needed. */
+ cic = bfq_alloc_io_context(bfqd, gfp_mask);
+ if (cic == NULL)
+ goto err;
+
+ /* Link it into the ioc's radix tree and cic list. */
+ if (bfq_cic_link(bfqd, ioc, cic, gfp_mask) != 0)
+ goto err_free;
+
+out:
+ /*
+ * test_and_clear_bit() implies a memory barrier, paired with
+ * the wmb() in fs/ioprio.c, so the value seen for ioprio is the
+ * new one.
+ */
+ if (unlikely(test_and_clear_bit(IOC_BFQ_IOPRIO_CHANGED,
+ ioc->ioprio_changed)))
+ bfq_ioc_set_ioprio(ioc);
+
+ return cic;
+err_free:
+ bfq_cic_free(cic);
+err:
+ put_io_context(ioc);
+ return NULL;
+}
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
new file mode 100644
index 0000000..ca7f280
--- /dev/null
+++ b/block/bfq-iosched.c
@@ -0,0 +1,3052 @@
+/*
+ * BFQ, or Budget Fair Queueing, disk scheduler.
+ *
+ * Based on ideas and code from CFQ:
+ * Copyright (C) 2003 Jens Axboe <axboe@kernel.dk>
+ *
+ * Copyright (C) 2008 Fabio Checconi <fabio@gandalf.sssup.it>
+ * Paolo Valente <paolo.valente@unimore.it>
+ *
+ * Licensed under the GPL-2 as detailed in the accompanying COPYING.BFQ file.
+ *
+ * BFQ is a proportional share disk scheduling algorithm based on the
+ * slice-by-slice service scheme of CFQ. But BFQ assigns budgets,
+ * measured in number of sectors, to tasks instead of time slices.
+ * The disk is not granted to the active task for a given time slice,
+ * but until it has exahusted its assigned budget. This change from
+ * the time to the service domain allows BFQ to distribute the disk
+ * bandwidth among tasks as desired, without any distortion due to
+ * ZBR, workload fluctuations or other factors. BFQ uses an ad hoc
+ * internal scheduler, called B-WF2Q+, to schedule tasks according to
+ * their budgets. Thanks to this accurate scheduler, BFQ can afford
+ * to assign high budgets to disk-bound non-seeky tasks (to boost the
+ * throughput), and yet guarantee low latencies to interactive and
+ * soft real-time applications.
+ *
+ * BFQ has been introduced in [1], where the interested reader can
+ * find an accurate description of the algorithm, the bandwidth
+ * distribution and latency guarantees it provides, plus formal proofs
+ * of all the properties. With respect to the algorithm presented in
+ * the paper, this implementation adds several little heuristics, and
+ * a hierarchical extension, based on H-WF2Q+.
+ *
+ * B-WF2Q+ is based on WF2Q+, that is described in [2], together with
+ * H-WF2Q+, while the augmented tree used to implement B-WF2Q+ with O(log N)
+ * complexity derives from the one introduced with EEVDF in [3].
+ *
+ * [1] P. Valente and F. Checconi, ``High Throughput Disk Scheduling
+ * with Deterministic Guarantees on Bandwidth Distribution,'',
+ * IEEE Transactions on Computer, May 2010.
+ *
+ * http://algo.ing.unimo.it/people/paolo/disk_sched/bfq-techreport.pdf
+ *
+ * [2] Jon C.R. Bennett and H. Zhang, ``Hierarchical Packet Fair Queueing
+ * Algorithms,'' IEEE/ACM Transactions on Networking, 5(5):675-689,
+ * Oct 1997.
+ *
+ * http://www.cs.cmu.edu/~hzhang/papers/TON-97-Oct.ps.gz
+ *
+ * [3] I. Stoica and H. Abdel-Wahab, ``Earliest Eligible Virtual Deadline
+ * First: A Flexible and Accurate Mechanism for Proportional Share
+ * Resource Allocation,'' technical report.
+ *
+ * http://www.cs.berkeley.edu/~istoica/papers/eevdf-tr-95.pdf
+ */
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/blkdev.h>
+#include <linux/cgroup.h>
+#include <linux/elevator.h>
+#include <linux/jiffies.h>
+#include <linux/rbtree.h>
+#include <linux/ioprio.h>
+#include "bfq.h"
+
+/* Max number of dispatches in one round of service. */
+static const int bfq_quantum = 4;
+
+/* Expiration time of sync (0) and async (1) requests, in jiffies. */
+static const int bfq_fifo_expire[2] = { HZ / 4, HZ / 8 };
+
+/* Maximum backwards seek, in KiB. */
+static const int bfq_back_max = 16 * 1024;
+
+/* Penalty of a backwards seek, in number of sectors. */
+static const int bfq_back_penalty = 2;
+
+/* Idling period duration, in jiffies. */
+static int bfq_slice_idle = HZ / 125;
+
+/* Default maximum budget values, in sectors and number of requests. */
+static const int bfq_default_max_budget = 16 * 1024;
+static const int bfq_max_budget_async_rq = 4;
+
+/*
+ * Async to sync throughput distribution is controlled as follows:
+ * when an async request is served, the entity is charged the number
+ * of sectors of the request, multipled by the factor below
+ */
+static const int bfq_async_charge_factor = 10;
+
+/* Default timeout values, in jiffies, approximating CFQ defaults. */
+static const int bfq_timeout_sync = HZ / 8;
+static int bfq_timeout_async = HZ / 25;
+
+struct kmem_cache *bfq_pool;
+struct kmem_cache *bfq_ioc_pool;
+
+static DEFINE_PER_CPU(unsigned long, bfq_ioc_count);
+static struct completion *bfq_ioc_gone;
+static DEFINE_SPINLOCK(bfq_ioc_gone_lock);
+
+static DEFINE_SPINLOCK(cic_index_lock);
+static DEFINE_IDA(cic_index_ida);
+
+/* Below this threshold (in ms), we consider thinktime immediate. */
+#define BFQ_MIN_TT 2
+
+/* hw_tag detection: parallel requests threshold and min samples needed. */
+#define BFQ_HW_QUEUE_THRESHOLD 4
+#define BFQ_HW_QUEUE_SAMPLES 32
+
+#define BFQQ_SEEK_THR (sector_t)(8 * 1024)
+#define BFQQ_SEEKY(bfqq) ((bfqq)->seek_mean > BFQQ_SEEK_THR)
+
+/* Min samples used for peak rate estimation (for autotuning). */
+#define BFQ_PEAK_RATE_SAMPLES 32
+
+/* Shift used for peak rate fixed precision calculations. */
+#define BFQ_RATE_SHIFT 16
+
+/*
+ * The duration of the weight raising for interactive applications is
+ * computed automatically (as default behaviour), using the following
+ * formula: duration = (R / r) * T, where r is the peak rate of the
+ * disk, and R and T are two reference parameters. In particular, R is
+ * the peak rate of a reference disk, and T is about the maximum time
+ * for starting popular large applications on that disk, under BFQ and
+ * while reading two files in parallel. Finally, BFQ uses two
+ * different pairs (R, T) depending on whether the disk is rotational
+ * or non-rotational.
+ */
+#define T_rot (msecs_to_jiffies(5500))
+#define T_nonrot (msecs_to_jiffies(2000))
+/* Next two quantities are in sectors/usec, left-shifted by BFQ_RATE_SHIFT */
+#define R_rot 17415
+#define R_nonrot 34791
+
+#define BFQ_SERVICE_TREE_INIT ((struct bfq_service_tree) \
+ { RB_ROOT, RB_ROOT, NULL, NULL, 0, 0 })
+
+#define RQ_CIC(rq) \
+ ((struct cfq_io_context *) (rq)->elevator_private[0])
+#define RQ_BFQQ(rq) ((rq)->elevator_private[1])
+
+#include "bfq-ioc.c"
+#include "bfq-sched.c"
+#include "bfq-cgroup.c"
+
+#define bfq_class_idle(bfqq) ((bfqq)->entity.ioprio_class ==\
+ IOPRIO_CLASS_IDLE)
+#define bfq_class_rt(bfqq) ((bfqq)->entity.ioprio_class ==\
+ IOPRIO_CLASS_RT)
+
+#define bfq_sample_valid(samples) ((samples) > 80)
+
+/*
+ * We regard a request as SYNC, if either it's a read or has the SYNC bit
+ * set (in which case it could also be a direct WRITE).
+ */
+static inline int bfq_bio_sync(struct bio *bio)
+{
+ if (bio_data_dir(bio) == READ || (bio->bi_rw & REQ_SYNC))
+ return 1;
+
+ return 0;
+}
+
+/*
+ * Scheduler run of queue, if there are requests pending and no one in the
+ * driver that will restart queueing.
+ */
+static inline void bfq_schedule_dispatch(struct bfq_data *bfqd)
+{
+ if (bfqd->queued != 0) {
+ bfq_log(bfqd, "schedule dispatch");
+ kblockd_schedule_work(bfqd->queue, &bfqd->unplug_work);
+ }
+}
+
+/*
+ * Lifted from AS - choose which of rq1 and rq2 that is best served now.
+ * We choose the request that is closesr to the head right now. Distance
+ * behind the head is penalized and only allowed to a certain extent.
+ */
+static struct request *bfq_choose_req(struct bfq_data *bfqd,
+ struct request *rq1,
+ struct request *rq2,
+ sector_t last)
+{
+ sector_t s1, s2, d1 = 0, d2 = 0;
+ unsigned long back_max;
+#define BFQ_RQ1_WRAP 0x01 /* request 1 wraps */
+#define BFQ_RQ2_WRAP 0x02 /* request 2 wraps */
+ unsigned wrap = 0; /* bit mask: requests behind the disk head? */
+
+ if (rq1 == NULL || rq1 == rq2)
+ return rq2;
+ if (rq2 == NULL)
+ return rq1;
+
+ if (rq_is_sync(rq1) && !rq_is_sync(rq2))
+ return rq1;
+ else if (rq_is_sync(rq2) && !rq_is_sync(rq1))
+ return rq2;
+ if ((rq1->cmd_flags & REQ_META) && !(rq2->cmd_flags & REQ_META))
+ return rq1;
+ else if ((rq2->cmd_flags & REQ_META) && !(rq1->cmd_flags & REQ_META))
+ return rq2;
+
+ s1 = blk_rq_pos(rq1);
+ s2 = blk_rq_pos(rq2);
+
+ /*
+ * By definition, 1KiB is 2 sectors.
+ */
+ back_max = bfqd->bfq_back_max * 2;
+
+ /*
+ * Strict one way elevator _except_ in the case where we allow
+ * short backward seeks which are biased as twice the cost of a
+ * similar forward seek.
+ */
+ if (s1 >= last)
+ d1 = s1 - last;
+ else if (s1 + back_max >= last)
+ d1 = (last - s1) * bfqd->bfq_back_penalty;
+ else
+ wrap |= BFQ_RQ1_WRAP;
+
+ if (s2 >= last)
+ d2 = s2 - last;
+ else if (s2 + back_max >= last)
+ d2 = (last - s2) * bfqd->bfq_back_penalty;
+ else
+ wrap |= BFQ_RQ2_WRAP;
+
+ /* Found required data */
+
+ /*
+ * By doing switch() on the bit mask "wrap" we avoid having to
+ * check two variables for all permutations: --> faster!
+ */
+ switch (wrap) {
+ case 0: /* common case for CFQ: rq1 and rq2 not wrapped */
+ if (d1 < d2)
+ return rq1;
+ else if (d2 < d1)
+ return rq2;
+ else {
+ if (s1 >= s2)
+ return rq1;
+ else
+ return rq2;
+ }
+
+ case BFQ_RQ2_WRAP:
+ return rq1;
+ case BFQ_RQ1_WRAP:
+ return rq2;
+ case (BFQ_RQ1_WRAP|BFQ_RQ2_WRAP): /* both rqs wrapped */
+ default:
+ /*
+ * Since both rqs are wrapped,
+ * start with the one that's further behind head
+ * (--> only *one* back seek required),
+ * since back seek takes more time than forward.
+ */
+ if (s1 <= s2)
+ return rq1;
+ else
+ return rq2;
+ }
+}
+
+static struct bfq_queue *
+bfq_rq_pos_tree_lookup(struct bfq_data *bfqd, struct rb_root *root,
+ sector_t sector, struct rb_node **ret_parent,
+ struct rb_node ***rb_link)
+{
+ struct rb_node **p, *parent;
+ struct bfq_queue *bfqq = NULL;
+
+ parent = NULL;
+ p = &root->rb_node;
+ while (*p) {
+ struct rb_node **n;
+
+ parent = *p;
+ bfqq = rb_entry(parent, struct bfq_queue, pos_node);
+
+ /*
+ * Sort strictly based on sector. Smallest to the left,
+ * largest to the right.
+ */
+ if (sector > blk_rq_pos(bfqq->next_rq))
+ n = &(*p)->rb_right;
+ else if (sector < blk_rq_pos(bfqq->next_rq))
+ n = &(*p)->rb_left;
+ else
+ break;
+ p = n;
+ bfqq = NULL;
+ }
+
+ *ret_parent = parent;
+ if (rb_link)
+ *rb_link = p;
+
+ bfq_log(bfqd, "rq_pos_tree_lookup %llu: returning %d",
+ (long long unsigned)sector,
+ bfqq != NULL ? bfqq->pid : 0);
+
+ return bfqq;
+}
+
+static void bfq_rq_pos_tree_add(struct bfq_data *bfqd, struct bfq_queue *bfqq)
+{
+ struct rb_node **p, *parent;
+ struct bfq_queue *__bfqq;
+
+ if (bfqq->pos_root != NULL) {
+ rb_erase(&bfqq->pos_node, bfqq->pos_root);
+ bfqq->pos_root = NULL;
+ }
+
+ if (bfq_class_idle(bfqq))
+ return;
+ if (!bfqq->next_rq)
+ return;
+
+ bfqq->pos_root = &bfqd->rq_pos_tree;
+ __bfqq = bfq_rq_pos_tree_lookup(bfqd, bfqq->pos_root,
+ blk_rq_pos(bfqq->next_rq), &parent, &p);
+ if (__bfqq == NULL) {
+ rb_link_node(&bfqq->pos_node, parent, p);
+ rb_insert_color(&bfqq->pos_node, bfqq->pos_root);
+ } else
+ bfqq->pos_root = NULL;
+}
+
+static struct request *bfq_find_next_rq(struct bfq_data *bfqd,
+ struct bfq_queue *bfqq,
+ struct request *last)
+{
+ struct rb_node *rbnext = rb_next(&last->rb_node);
+ struct rb_node *rbprev = rb_prev(&last->rb_node);
+ struct request *next = NULL, *prev = NULL;
+
+ BUG_ON(RB_EMPTY_NODE(&last->rb_node));
+
+ if (rbprev != NULL)
+ prev = rb_entry_rq(rbprev);
+
+ if (rbnext != NULL)
+ next = rb_entry_rq(rbnext);
+ else {
+ rbnext = rb_first(&bfqq->sort_list);
+ if (rbnext && rbnext != &last->rb_node)
+ next = rb_entry_rq(rbnext);
+ }
+
+ return bfq_choose_req(bfqd, next, prev, blk_rq_pos(last));
+}
+
+static void bfq_del_rq_rb(struct request *rq)
+{
+ struct bfq_queue *bfqq = RQ_BFQQ(rq);
+ struct bfq_data *bfqd = bfqq->bfqd;
+ const int sync = rq_is_sync(rq);
+
+ BUG_ON(bfqq->queued[sync] == 0);
+ bfqq->queued[sync]--;
+ bfqd->queued--;
+
+ elv_rb_del(&bfqq->sort_list, rq);
+
+ if (RB_EMPTY_ROOT(&bfqq->sort_list)) {
+ if (bfq_bfqq_busy(bfqq) && bfqq != bfqd->active_queue)
+ bfq_del_bfqq_busy(bfqd, bfqq, 1);
+ /*
+ * Remove queue from request-position tree as it is empty.
+ */
+ if (bfqq->pos_root != NULL) {
+ rb_erase(&bfqq->pos_node, bfqq->pos_root);
+ bfqq->pos_root = NULL;
+ }
+ }
+}
+
+/* see the definition of bfq_async_charge_factor for details */
+static inline unsigned long bfq_serv_to_charge(struct request *rq,
+ struct bfq_queue *bfqq)
+{
+ return blk_rq_sectors(rq) *
+ (1 + ((!bfq_bfqq_sync(bfqq)) * (bfqq->raising_coeff == 1) *
+ bfq_async_charge_factor));
+}
+
+/**
+ * bfq_updated_next_req - update the queue after a new next_rq selection.
+ * @bfqd: the device data the queue belongs to.
+ * @bfqq: the queue to update.
+ *
+ * If the first request of a queue changes we make sure that the queue
+ * has enough budget to serve at least its first request (if the
+ * request has grown). We do this because if the queue has not enough
+ * budget for its first request, it has to go through two dispatch
+ * rounds to actually get it dispatched.
+ */
+static void bfq_updated_next_req(struct bfq_data *bfqd,
+ struct bfq_queue *bfqq)
+{
+ struct bfq_entity *entity = &bfqq->entity;
+ struct bfq_service_tree *st = bfq_entity_service_tree(entity);
+ struct request *next_rq = bfqq->next_rq;
+ unsigned long new_budget;
+
+ if (next_rq == NULL)
+ return;
+
+ if (bfqq == bfqd->active_queue)
+ /*
+ * In order not to break guarantees, budgets cannot be
+ * changed after an entity has been selected.
+ */
+ return;
+
+ BUG_ON(entity->tree != &st->active);
+ BUG_ON(entity == entity->sched_data->active_entity);
+
+ new_budget = max_t(unsigned long, bfqq->max_budget,
+ bfq_serv_to_charge(next_rq, bfqq));
+ entity->budget = new_budget;
+ bfq_log_bfqq(bfqd, bfqq, "updated next rq: new budget %lu", new_budget);
+ bfq_activate_bfqq(bfqd, bfqq);
+}
+
+static inline unsigned int bfq_wrais_duration(struct bfq_data *bfqd)
+{
+ u64 dur;
+
+ if (bfqd->bfq_raising_max_time > 0)
+ return bfqd->bfq_raising_max_time;
+
+ dur = bfqd->RT_prod;
+ do_div(dur, bfqd->peak_rate);
+
+ return dur;
+}
+
+static void bfq_add_rq_rb(struct request *rq)
+{
+ struct bfq_queue *bfqq = RQ_BFQQ(rq);
+ struct bfq_entity *entity = &bfqq->entity;
+ struct bfq_data *bfqd = bfqq->bfqd;
+ struct request *__alias, *next_rq, *prev;
+ unsigned long old_raising_coeff = bfqq->raising_coeff;
+ int idle_for_long_time = bfqq->budget_timeout +
+ bfqd->bfq_raising_min_idle_time < jiffies;
+
+ bfq_log_bfqq(bfqd, bfqq, "add_rq_rb %d", rq_is_sync(rq));
+ bfqq->queued[rq_is_sync(rq)]++;
+ bfqd->queued++;
+
+ /*
+ * Looks a little odd, but the first insert might return an alias,
+ * if that happens, put the alias on the dispatch list.
+ */
+ while ((__alias = elv_rb_add(&bfqq->sort_list, rq)) != NULL)
+ bfq_dispatch_insert(bfqd->queue, __alias);
+
+ /*
+ * Check if this request is a better next-serve candidate.
+ */
+ prev = bfqq->next_rq;
+ next_rq = bfq_choose_req(bfqd, bfqq->next_rq, rq, bfqd->last_position);
+ BUG_ON(next_rq == NULL);
+ bfqq->next_rq = next_rq;
+
+ /*
+ * Adjust priority tree position, if next_rq changes.
+ */
+ if (prev != bfqq->next_rq)
+ bfq_rq_pos_tree_add(bfqd, bfqq);
+
+ if (!bfq_bfqq_busy(bfqq)) {
+ int soft_rt = bfqd->bfq_raising_max_softrt_rate > 0 &&
+ bfqq->soft_rt_next_start < jiffies;
+ entity->budget = max_t(unsigned long, bfqq->max_budget,
+ bfq_serv_to_charge(next_rq, bfqq));
+
+ if (! bfqd->low_latency)
+ goto add_bfqq_busy;
+
+ /*
+ * If the queue is not being boosted and has been idle
+ * for enough time, start a weight-raising period
+ */
+ if(old_raising_coeff == 1 && (idle_for_long_time || soft_rt)) {
+ bfqq->raising_coeff = bfqd->bfq_raising_coeff;
+ if (idle_for_long_time)
+ bfqq->raising_cur_max_time =
+ bfq_wrais_duration(bfqd);
+ else
+ bfqq->raising_cur_max_time =
+ bfqd->bfq_raising_rt_max_time;
+ bfq_log_bfqq(bfqd, bfqq,
+ "wrais starting at %llu msec,"
+ "rais_max_time %u",
+ bfqq->last_rais_start_finish,
+ jiffies_to_msecs(bfqq->
+ raising_cur_max_time));
+ } else if (old_raising_coeff > 1) {
+ if (idle_for_long_time)
+ bfqq->raising_cur_max_time =
+ bfq_wrais_duration(bfqd);
+ else if (bfqq->raising_cur_max_time ==
+ bfqd->bfq_raising_rt_max_time &&
+ !soft_rt) {
+ bfqq->raising_coeff = 1;
+ bfq_log_bfqq(bfqd, bfqq,
+ "wrais ending at %llu msec,"
+ "rais_max_time %u",
+ bfqq->last_rais_start_finish,
+ jiffies_to_msecs(bfqq->
+ raising_cur_max_time));
+ }
+ }
+ if (old_raising_coeff != bfqq->raising_coeff)
+ entity->ioprio_changed = 1;
+add_bfqq_busy:
+ bfq_add_bfqq_busy(bfqd, bfqq);
+ } else {
+ if(bfqd->low_latency && old_raising_coeff == 1 &&
+ !rq_is_sync(rq) &&
+ bfqq->last_rais_start_finish +
+ bfqd->bfq_raising_min_inter_arr_async < jiffies) {
+ bfqq->raising_coeff = bfqd->bfq_raising_coeff;
+ bfqq->raising_cur_max_time = bfq_wrais_duration(bfqd);
+
+ entity->ioprio_changed = 1;
+ bfq_log_bfqq(bfqd, bfqq,
+ "non-idle wrais starting at %llu msec,"
+ "rais_max_time %u",
+ bfqq->last_rais_start_finish,
+ jiffies_to_msecs(bfqq->
+ raising_cur_max_time));
+ }
+ bfq_updated_next_req(bfqd, bfqq);
+ }
+
+ if(bfqd->low_latency &&
+ (old_raising_coeff == 1 || bfqq->raising_coeff == 1 ||
+ idle_for_long_time))
+ bfqq->last_rais_start_finish = jiffies;
+}
+
+static void bfq_reposition_rq_rb(struct bfq_queue *bfqq, struct request *rq)
+{
+ elv_rb_del(&bfqq->sort_list, rq);
+ bfqq->queued[rq_is_sync(rq)]--;
+ bfqq->bfqd->queued--;
+ bfq_add_rq_rb(rq);
+}
+
+static struct request *bfq_find_rq_fmerge(struct bfq_data *bfqd,
+ struct bio *bio)
+{
+ struct task_struct *tsk = current;
+ struct cfq_io_context *cic;
+ struct bfq_queue *bfqq;
+
+ cic = bfq_cic_lookup(bfqd, tsk->io_context);
+ if (cic == NULL)
+ return NULL;
+
+ bfqq = cic_to_bfqq(cic, bfq_bio_sync(bio));
+ if (bfqq != NULL) {
+ sector_t sector = bio->bi_sector + bio_sectors(bio);
+
+ return elv_rb_find(&bfqq->sort_list, sector);
+ }
+
+ return NULL;
+}
+
+static void bfq_activate_request(struct request_queue *q, struct request *rq)
+{
+ struct bfq_data *bfqd = q->elevator->elevator_data;
+
+ bfqd->rq_in_driver++;
+ bfqd->last_position = blk_rq_pos(rq) + blk_rq_sectors(rq);
+ bfq_log(bfqd, "activate_request: new bfqd->last_position %llu",
+ (long long unsigned)bfqd->last_position);
+}
+
+static void bfq_deactivate_request(struct request_queue *q, struct request *rq)
+{
+ struct bfq_data *bfqd = q->elevator->elevator_data;
+
+ WARN_ON(bfqd->rq_in_driver == 0);
+ bfqd->rq_in_driver--;
+}
+
+static void bfq_remove_request(struct request *rq)
+{
+ struct bfq_queue *bfqq = RQ_BFQQ(rq);
+ struct bfq_data *bfqd = bfqq->bfqd;
+
+ if (bfqq->next_rq == rq) {
+ bfqq->next_rq = bfq_find_next_rq(bfqd, bfqq, rq);
+ bfq_updated_next_req(bfqd, bfqq);
+ }
+
+ list_del_init(&rq->queuelist);
+ bfq_del_rq_rb(rq);
+
+ if (rq->cmd_flags & REQ_META) {
+ WARN_ON(bfqq->meta_pending == 0);
+ bfqq->meta_pending--;
+ }
+}
+
+static int bfq_merge(struct request_queue *q, struct request **req,
+ struct bio *bio)
+{
+ struct bfq_data *bfqd = q->elevator->elevator_data;
+ struct request *__rq;
+
+ __rq = bfq_find_rq_fmerge(bfqd, bio);
+ if (__rq != NULL && elv_rq_merge_ok(__rq, bio)) {
+ *req = __rq;
+ return ELEVATOR_FRONT_MERGE;
+ }
+
+ return ELEVATOR_NO_MERGE;
+}
+
+static void bfq_merged_request(struct request_queue *q, struct request *req,
+ int type)
+{
+ if (type == ELEVATOR_FRONT_MERGE) {
+ struct bfq_queue *bfqq = RQ_BFQQ(req);
+
+ bfq_reposition_rq_rb(bfqq, req);
+ }
+}
+
+static void bfq_merged_requests(struct request_queue *q, struct request *rq,
+ struct request *next)
+{
+ struct bfq_queue *bfqq = RQ_BFQQ(rq);
+
+ /*
+ * Reposition in fifo if next is older than rq.
+ */
+ if (!list_empty(&rq->queuelist) && !list_empty(&next->queuelist) &&
+ time_before(rq_fifo_time(next), rq_fifo_time(rq))) {
+ list_move(&rq->queuelist, &next->queuelist);
+ rq_set_fifo_time(rq, rq_fifo_time(next));
+ }
+
+ if (bfqq->next_rq == next)
+ bfqq->next_rq = rq;
+
+ bfq_remove_request(next);
+}
+
+static int bfq_allow_merge(struct request_queue *q, struct request *rq,
+ struct bio *bio)
+{
+ struct bfq_data *bfqd = q->elevator->elevator_data;
+ struct cfq_io_context *cic;
+ struct bfq_queue *bfqq;
+
+ /* Disallow merge of a sync bio into an async request. */
+ if (bfq_bio_sync(bio) && !rq_is_sync(rq))
+ return 0;
+
+ /*
+ * Lookup the bfqq that this bio will be queued with. Allow
+ * merge only if rq is queued there.
+ */
+ cic = bfq_cic_lookup(bfqd, current->io_context);
+ if (cic == NULL)
+ return 0;
+
+ bfqq = cic_to_bfqq(cic, bfq_bio_sync(bio));
+ return bfqq == RQ_BFQQ(rq);
+}
+
+static void __bfq_set_active_queue(struct bfq_data *bfqd,
+ struct bfq_queue *bfqq)
+{
+ if (bfqq != NULL) {
+ bfq_mark_bfqq_must_alloc(bfqq);
+ bfq_mark_bfqq_budget_new(bfqq);
+ bfq_clear_bfqq_fifo_expire(bfqq);
+
+ bfqd->budgets_assigned = (bfqd->budgets_assigned*7 + 256) / 8;
+
+ bfq_log_bfqq(bfqd, bfqq, "set_active_queue, cur-budget = %lu",
+ bfqq->entity.budget);
+ }
+
+ bfqd->active_queue = bfqq;
+}
+
+/*
+ * Get and set a new active queue for service.
+ */
+static struct bfq_queue *bfq_set_active_queue(struct bfq_data *bfqd,
+ struct bfq_queue *bfqq)
+{
+ if (!bfqq)
+ bfqq = bfq_get_next_queue(bfqd);
+ else
+ bfq_get_next_queue_forced(bfqd, bfqq);
+
+ __bfq_set_active_queue(bfqd, bfqq);
+ return bfqq;
+}
+
+static inline sector_t bfq_dist_from_last(struct bfq_data *bfqd,
+ struct request *rq)
+{
+ if (blk_rq_pos(rq) >= bfqd->last_position)
+ return blk_rq_pos(rq) - bfqd->last_position;
+ else
+ return bfqd->last_position - blk_rq_pos(rq);
+}
+
+/*
+ * Return true if bfqq has no request pending and rq is close enough to
+ * bfqd->last_position, or if rq is closer to bfqd->last_position than
+ * bfqq->next_rq
+ */
+static inline int bfq_rq_close(struct bfq_data *bfqd, struct request *rq)
+{
+ return bfq_dist_from_last(bfqd, rq) <= BFQQ_SEEK_THR;
+}
+
+static struct bfq_queue *bfqq_close(struct bfq_data *bfqd)
+{
+ struct rb_root *root = &bfqd->rq_pos_tree;
+ struct rb_node *parent, *node;
+ struct bfq_queue *__bfqq;
+ sector_t sector = bfqd->last_position;
+
+ if (RB_EMPTY_ROOT(root))
+ return NULL;
+
+ /*
+ * First, if we find a request starting at the end of the last
+ * request, choose it.
+ */
+ __bfqq = bfq_rq_pos_tree_lookup(bfqd, root, sector, &parent, NULL);
+ if (__bfqq != NULL)
+ return __bfqq;
+
+ /*
+ * If the exact sector wasn't found, the parent of the NULL leaf
+ * will contain the closest sector (rq_pos_tree sorted by next_request
+ * position).
+ */
+ __bfqq = rb_entry(parent, struct bfq_queue, pos_node);
+ if (bfq_rq_close(bfqd, __bfqq->next_rq))
+ return __bfqq;
+
+ if (blk_rq_pos(__bfqq->next_rq) < sector)
+ node = rb_next(&__bfqq->pos_node);
+ else
+ node = rb_prev(&__bfqq->pos_node);
+ if (node == NULL)
+ return NULL;
+
+ __bfqq = rb_entry(node, struct bfq_queue, pos_node);
+ if (bfq_rq_close(bfqd, __bfqq->next_rq))
+ return __bfqq;
+
+ return NULL;
+}
+
+/*
+ * bfqd - obvious
+ * cur_bfqq - passed in so that we don't decide that the current queue
+ * is closely cooperating with itself.
+ *
+ * We are assuming that cur_bfqq has dispatched at least one request,
+ * and that bfqd->last_position reflects a position on the disk associated
+ * with the I/O issued by cur_bfqq.
+ */
+static struct bfq_queue *bfq_close_cooperator(struct bfq_data *bfqd,
+ struct bfq_queue *cur_bfqq)
+{
+ struct bfq_queue *bfqq;
+
+ if (bfq_class_idle(cur_bfqq))
+ return NULL;
+ if (!bfq_bfqq_sync(cur_bfqq))
+ return NULL;
+ if (BFQQ_SEEKY(cur_bfqq))
+ return NULL;
+
+ /* If device has only one backlogged bfq_queue, don't search. */
+ if (bfqd->busy_queues == 1)
+ return NULL;
+
+ /*
+ * We should notice if some of the queues are cooperating, e.g.
+ * working closely on the same area of the disk. In that case,
+ * we can group them together and don't waste time idling.
+ */
+ bfqq = bfqq_close(bfqd);
+ if (bfqq == NULL || bfqq == cur_bfqq)
+ return NULL;
+
+ /*
+ * Do not merge queues from different bfq_groups.
+ */
+ if (bfqq->entity.parent != cur_bfqq->entity.parent)
+ return NULL;
+
+ /*
+ * It only makes sense to merge sync queues.
+ */
+ if (!bfq_bfqq_sync(bfqq))
+ return NULL;
+ if (BFQQ_SEEKY(bfqq))
+ return NULL;
+
+ /*
+ * Do not merge queues of different priority classes.
+ */
+ if (bfq_class_rt(bfqq) != bfq_class_rt(cur_bfqq))
+ return NULL;
+
+ return bfqq;
+}
+
+/*
+ * If enough samples have been computed, return the current max budget
+ * stored in bfqd, which is dynamically updated according to the
+ * estimated disk peak rate; otherwise return the default max budget
+ */
+static inline unsigned long bfq_max_budget(struct bfq_data *bfqd)
+{
+ if (bfqd->budgets_assigned < 194)
+ return bfq_default_max_budget;
+ else
+ return bfqd->bfq_max_budget;
+}
+
+/*
+ * Return min budget, which is a fraction of the current or default
+ * max budget (trying with 1/32)
+ */
+static inline unsigned long bfq_min_budget(struct bfq_data *bfqd)
+{
+ if (bfqd->budgets_assigned < 194)
+ return bfq_default_max_budget;
+ else
+ return bfqd->bfq_max_budget / 32;
+}
+
+/*
+ * Decides whether idling should be done for given device and
+ * given active queue.
+ */
+static inline bool bfq_queue_nonrot_noidle(struct bfq_data *bfqd,
+ struct bfq_queue *active_bfqq)
+{
+ if (active_bfqq == NULL)
+ return false;
+ /*
+ * If device is SSD it has no seek penalty, disable idling; but
+ * do so only if:
+ * - device does not support queuing, otherwise we still have
+ * a problem with sync vs async workloads;
+ * - the queue is not weight-raised, to preserve guarantees.
+ */
+ return (blk_queue_nonrot(bfqd->queue) && bfqd->hw_tag &&
+ active_bfqq->raising_coeff == 1);
+}
+
+static void bfq_arm_slice_timer(struct bfq_data *bfqd)
+{
+ struct bfq_queue *bfqq = bfqd->active_queue;
+ struct cfq_io_context *cic;
+ unsigned long sl;
+
+ WARN_ON(!RB_EMPTY_ROOT(&bfqq->sort_list));
+
+ if (bfq_queue_nonrot_noidle(bfqd, bfqq))
+ return;
+
+ /* Idling is disabled, either manually or by past process history. */
+ if (bfqd->bfq_slice_idle == 0 || !bfq_bfqq_idle_window(bfqq))
+ return;
+
+ /* Tasks have exited, don't wait. */
+ cic = bfqd->active_cic;
+ if (cic == NULL || atomic_read(&cic->ioc->nr_tasks) == 0)
+ return;
+
+ bfq_mark_bfqq_wait_request(bfqq);
+
+ /*
+ * We don't want to idle for seeks, but we do want to allow
+ * fair distribution of slice time for a process doing back-to-back
+ * seeks. So allow a little bit of time for him to submit a new rq.
+ *
+ * To prevent processes with (partly) seeky workloads from
+ * being too ill-treated, grant them a small fraction of the
+ * assigned budget before reducing the waiting time to
+ * BFQ_MIN_TT. This happened to help reduce latency.
+ */
+ sl = bfqd->bfq_slice_idle;
+ if (bfq_sample_valid(bfqq->seek_samples) && BFQQ_SEEKY(bfqq) &&
+ bfqq->entity.service > bfq_max_budget(bfqd) / 8 &&
+ bfqq->raising_coeff == 1)
+ sl = min(sl, msecs_to_jiffies(BFQ_MIN_TT));
+ else if (bfqq->raising_coeff > 1)
+ sl = sl * 3;
+ bfqd->last_idling_start = ktime_get();
+ mod_timer(&bfqd->idle_slice_timer, jiffies + sl);
+ bfq_log(bfqd, "arm idle: %u/%u ms",
+ jiffies_to_msecs(sl), jiffies_to_msecs(bfqd->bfq_slice_idle));
+}
+
+/*
+ * Set the maximum time for the active queue to consume its
+ * budget. This prevents seeky processes from lowering the disk
+ * throughput (always guaranteed with a time slice scheme as in CFQ).
+ */
+static void bfq_set_budget_timeout(struct bfq_data *bfqd)
+{
+ struct bfq_queue *bfqq = bfqd->active_queue;
+ unsigned int timeout_coeff;
+ if (bfqq->raising_cur_max_time == bfqd->bfq_raising_rt_max_time)
+ timeout_coeff = 1;
+ else
+ timeout_coeff = bfqq->entity.weight / bfqq->entity.orig_weight;
+
+ bfqd->last_budget_start = ktime_get();
+
+ bfq_clear_bfqq_budget_new(bfqq);
+ bfqq->budget_timeout = jiffies +
+ bfqd->bfq_timeout[bfq_bfqq_sync(bfqq)] * timeout_coeff;
+
+ bfq_log_bfqq(bfqd, bfqq, "set budget_timeout %u",
+ jiffies_to_msecs(bfqd->bfq_timeout[bfq_bfqq_sync(bfqq)] *
+ timeout_coeff));
+}
+
+/*
+ * Move request from internal lists to the request queue dispatch list.
+ */
+static void bfq_dispatch_insert(struct request_queue *q, struct request *rq)
+{
+ struct bfq_data *bfqd = q->elevator->elevator_data;
+ struct bfq_queue *bfqq = RQ_BFQQ(rq);
+
+ bfq_remove_request(rq);
+ bfqq->dispatched++;
+ elv_dispatch_sort(q, rq);
+
+ if (bfq_bfqq_sync(bfqq))
+ bfqd->sync_flight++;
+}
+
+/*
+ * Return expired entry, or NULL to just start from scratch in rbtree.
+ */
+static struct request *bfq_check_fifo(struct bfq_queue *bfqq)
+{
+ struct request *rq = NULL;
+
+ if (bfq_bfqq_fifo_expire(bfqq))
+ return NULL;
+
+ bfq_mark_bfqq_fifo_expire(bfqq);
+
+ if (list_empty(&bfqq->fifo))
+ return NULL;
+
+ rq = rq_entry_fifo(bfqq->fifo.next);
+
+ if (time_before(jiffies, rq_fifo_time(rq)))
+ return NULL;
+
+ return rq;
+}
+
+/*
+ * Must be called with the queue_lock held.
+ */
+static int bfqq_process_refs(struct bfq_queue *bfqq)
+{
+ int process_refs, io_refs;
+
+ io_refs = bfqq->allocated[READ] + bfqq->allocated[WRITE];
+ process_refs = atomic_read(&bfqq->ref) - io_refs - bfqq->entity.on_st;
+ BUG_ON(process_refs < 0);
+ return process_refs;
+}
+
+static void bfq_setup_merge(struct bfq_queue *bfqq, struct bfq_queue *new_bfqq)
+{
+ int process_refs, new_process_refs;
+ struct bfq_queue *__bfqq;
+
+ /*
+ * If there are no process references on the new_bfqq, then it is
+ * unsafe to follow the ->new_bfqq chain as other bfqq's in the chain
+ * may have dropped their last reference (not just their last process
+ * reference).
+ */
+ if (!bfqq_process_refs(new_bfqq))
+ return;
+
+ /* Avoid a circular list and skip interim queue merges. */
+ while ((__bfqq = new_bfqq->new_bfqq)) {
+ if (__bfqq == bfqq)
+ return;
+ new_bfqq = __bfqq;
+ }
+
+ process_refs = bfqq_process_refs(bfqq);
+ new_process_refs = bfqq_process_refs(new_bfqq);
+ /*
+ * If the process for the bfqq has gone away, there is no
+ * sense in merging the queues.
+ */
+ if (process_refs == 0 || new_process_refs == 0)
+ return;
+
+ /*
+ * Merge in the direction of the lesser amount of work.
+ */
+ if (new_process_refs >= process_refs) {
+ bfqq->new_bfqq = new_bfqq;
+ atomic_add(process_refs, &new_bfqq->ref);
+ } else {
+ new_bfqq->new_bfqq = bfqq;
+ atomic_add(new_process_refs, &bfqq->ref);
+ }
+ bfq_log_bfqq(bfqq->bfqd, bfqq, "scheduling merge with queue %d",
+ new_bfqq->pid);
+}
+
+static inline unsigned long bfq_bfqq_budget_left(struct bfq_queue *bfqq)
+{
+ struct bfq_entity *entity = &bfqq->entity;
+ return entity->budget - entity->service;
+}
+
+static void __bfq_bfqq_expire(struct bfq_data *bfqd, struct bfq_queue *bfqq)
+{
+ BUG_ON(bfqq != bfqd->active_queue);
+
+ __bfq_bfqd_reset_active(bfqd);
+
+ if (RB_EMPTY_ROOT(&bfqq->sort_list)) {
+ bfq_del_bfqq_busy(bfqd, bfqq, 1);
+ /*
+ * overloading budget_timeout field to store when
+ * the queue remains with no backlog, used by
+ * the weight-raising mechanism
+ */
+ bfqq->budget_timeout = jiffies ;
+ }
+ else {
+ bfq_activate_bfqq(bfqd, bfqq);
+ /*
+ * Resort priority tree of potential close cooperators.
+ */
+ bfq_rq_pos_tree_add(bfqd, bfqq);
+ }
+
+ /*
+ * If this bfqq is shared between multiple processes, check
+ * to make sure that those processes are still issuing I/Os
+ * within the mean seek distance. If not, it may be time to
+ * break the queues apart again.
+ */
+ if (bfq_bfqq_coop(bfqq) && BFQQ_SEEKY(bfqq))
+ bfq_mark_bfqq_split_coop(bfqq);
+}
+
+/**
+ * __bfq_bfqq_recalc_budget - try to adapt the budget to the @bfqq behavior.
+ * @bfqd: device data.
+ * @bfqq: queue to update.
+ * @reason: reason for expiration.
+ *
+ * Handle the feedback on @bfqq budget. See the body for detailed
+ * comments.
+ */
+static void __bfq_bfqq_recalc_budget(struct bfq_data *bfqd,
+ struct bfq_queue *bfqq,
+ enum bfqq_expiration reason)
+{
+ struct request *next_rq;
+ unsigned long budget, min_budget;
+
+ budget = bfqq->max_budget;
+ min_budget = bfq_min_budget(bfqd);
+
+ BUG_ON(bfqq != bfqd->active_queue);
+
+ bfq_log_bfqq(bfqd, bfqq, "recalc_budg: last budg %lu, budg left %lu",
+ bfqq->entity.budget, bfq_bfqq_budget_left(bfqq));
+ bfq_log_bfqq(bfqd, bfqq, "recalc_budg: last max_budg %lu, min budg %lu",
+ budget, bfq_min_budget(bfqd));
+ bfq_log_bfqq(bfqd, bfqq, "recalc_budg: sync %d, seeky %d",
+ bfq_bfqq_sync(bfqq), BFQQ_SEEKY(bfqd->active_queue));
+
+ if (bfq_bfqq_sync(bfqq)) {
+ switch (reason) {
+ /*
+ * Caveat: in all the following cases we trade latency
+ * for throughput.
+ */
+ case BFQ_BFQQ_TOO_IDLE:
+ /*
+ * This is the only case where we may reduce
+ * the budget: if there is no requets of the
+ * process still waiting for completion, then
+ * we assume (tentatively) that the timer has
+ * expired because the batch of requests of
+ * the process could have been served with a
+ * smaller budget. Hence, betting that
+ * process will behave in the same way when it
+ * becomes backlogged again, we reduce its
+ * next budget. As long as we guess right,
+ * this budget cut reduces the latency
+ * experienced by the process.
+ *
+ * However, if there are still outstanding
+ * requests, then the process may have not yet
+ * issued its next request just because it is
+ * still waiting for the completion of some of
+ * the still oustanding ones. So in this
+ * subcase we do not reduce its budget, on the
+ * contrary we increase it to possibly boost
+ * the throughput, as discussed in the
+ * comments to the BUDGET_TIMEOUT case.
+ */
+ if (bfqq->dispatched > 0) /* still oustanding reqs */
+ budget = min(budget * 2, bfqd->bfq_max_budget);
+ else {
+ if (budget > 5 * min_budget)
+ budget -= 4 * min_budget;
+ else
+ budget = min_budget;
+ }
+ break;
+ case BFQ_BFQQ_BUDGET_TIMEOUT:
+ /*
+ * We double the budget here because: 1) it
+ * gives the chance to boost the throughput if
+ * this is not a seeky process (which may have
+ * bumped into this timeout because of, e.g.,
+ * ZBR), 2) together with charge_full_budget
+ * it helps give seeky processes higher
+ * timestamps, and hence be served less
+ * frequently.
+ */
+ budget = min(budget * 2, bfqd->bfq_max_budget);
+ break;
+ case BFQ_BFQQ_BUDGET_EXHAUSTED:
+ /*
+ * The process still has backlog, and did not
+ * let either the budget timeout or the disk
+ * idling timeout expire. Hence it is not
+ * seeky, has a short thinktime and may be
+ * happy with a higher budget too. So
+ * definitely increase the budget of this good
+ * candidate to boost the disk throughput.
+ */
+ budget = min(budget * 4, bfqd->bfq_max_budget);
+ break;
+ case BFQ_BFQQ_NO_MORE_REQUESTS:
+ /*
+ * Leave the budget unchanged.
+ */
+ default:
+ return;
+ }
+ } else /* async queue */
+ /* async queues get always the maximum possible budget
+ * (their ability to dispatch is limited by
+ * @bfqd->bfq_max_budget_async_rq).
+ */
+ budget = bfqd->bfq_max_budget;
+
+ bfqq->max_budget = budget;
+
+ if (bfqd->budgets_assigned >= 194 && bfqd->bfq_user_max_budget == 0 &&
+ bfqq->max_budget > bfqd->bfq_max_budget)
+ bfqq->max_budget = bfqd->bfq_max_budget;
+
+ /*
+ * Make sure that we have enough budget for the next request.
+ * Since the finish time of the bfqq must be kept in sync with
+ * the budget, be sure to call __bfq_bfqq_expire() after the
+ * update.
+ */
+ next_rq = bfqq->next_rq;
+ if (next_rq != NULL)
+ bfqq->entity.budget = max_t(unsigned long, bfqq->max_budget,
+ bfq_serv_to_charge(next_rq, bfqq));
+ else
+ bfqq->entity.budget = bfqq->max_budget;
+
+ bfq_log_bfqq(bfqd, bfqq, "head sect: %u, new budget %lu",
+ next_rq != NULL ? blk_rq_sectors(next_rq) : 0,
+ bfqq->entity.budget);
+}
+
+static unsigned long bfq_calc_max_budget(u64 peak_rate, u64 timeout)
+{
+ unsigned long max_budget;
+
+ /*
+ * The max_budget calculated when autotuning is equal to the
+ * amount of sectors transfered in timeout_sync at the
+ * estimated peak rate.
+ */
+ max_budget = (unsigned long)(peak_rate * 1000 *
+ timeout >> BFQ_RATE_SHIFT);
+
+ return max_budget;
+}
+
+/*
+ * In addition to updating the peak rate, checks whether the process
+ * is "slow", and returns 1 if so. This slow flag is used, in addition
+ * to the budget timeout, to reduce the amount of service provided to
+ * seeky processes, and hence reduce their chances to lower the
+ * throughput. See the code for more details.
+ */
+static int bfq_update_peak_rate(struct bfq_data *bfqd, struct bfq_queue *bfqq,
+ int compensate, enum bfqq_expiration reason)
+{
+ u64 bw, usecs, expected, timeout;
+ ktime_t delta;
+ int update = 0;
+
+ if (!bfq_bfqq_sync(bfqq) || bfq_bfqq_budget_new(bfqq))
+ return 0;
+
+ if (compensate)
+ delta = bfqd->last_idling_start;
+ else
+ delta = ktime_get();
+ delta = ktime_sub(delta, bfqd->last_budget_start);
+ usecs = ktime_to_us(delta);
+
+ /* Don't trust short/unrealistic values. */
+ if (usecs < 100 || usecs >= LONG_MAX)
+ return 0;
+
+ /*
+ * Calculate the bandwidth for the last slice. We use a 64 bit
+ * value to store the peak rate, in sectors per usec in fixed
+ * point math. We do so to have enough precision in the estimate
+ * and to avoid overflows.
+ */
+ bw = (u64)bfqq->entity.service << BFQ_RATE_SHIFT;
+ do_div(bw, (unsigned long)usecs);
+
+ timeout = jiffies_to_msecs(bfqd->bfq_timeout[BLK_RW_SYNC]);
+
+ /*
+ * Use only long (> 20ms) intervals to filter out spikes for
+ * the peak rate estimation.
+ */
+ if (usecs > 20000) {
+ if (bw > bfqd->peak_rate ||
+ (!BFQQ_SEEKY(bfqq) &&
+ reason == BFQ_BFQQ_BUDGET_TIMEOUT)) {
+ bfq_log(bfqd, "measured bw =%llu", bw);
+ /*
+ * To smooth oscillations use a low-pass filter with
+ * alpha=7/8, i.e.,
+ * new_rate = (7/8) * old_rate + (1/8) * bw
+ */
+ do_div(bw, 8);
+ bfqd->peak_rate *= 7;
+ do_div(bfqd->peak_rate, 8);
+ bfqd->peak_rate += bw;
+ update = 1;
+ bfq_log(bfqd, "new peak_rate=%llu", bfqd->peak_rate);
+ }
+
+ update |= bfqd->peak_rate_samples == BFQ_PEAK_RATE_SAMPLES - 1;
+
+ if (bfqd->peak_rate_samples < BFQ_PEAK_RATE_SAMPLES)
+ bfqd->peak_rate_samples++;
+
+ if (bfqd->peak_rate_samples == BFQ_PEAK_RATE_SAMPLES &&
+ update && bfqd->bfq_user_max_budget == 0) {
+ bfqd->bfq_max_budget =
+ bfq_calc_max_budget(bfqd->peak_rate, timeout);
+ bfq_log(bfqd, "new max_budget=%lu",
+ bfqd->bfq_max_budget);
+ }
+ }
+
+ /*
+ * If the process has been served for a too short time
+ * interval to let its possible sequential accesses prevail on
+ * the initial seek time needed to move the disk head on the
+ * first sector it requested, then give the process a chance
+ * and for the moment return false.
+ */
+ if (bfqq->entity.budget <= bfq_max_budget(bfqd) / 8)
+ return 0;
+
+ /*
+ * A process is considered ``slow'' (i.e., seeky, so that we
+ * cannot treat it fairly in the service domain, as it would
+ * slow down too much the other processes) if, when a slice
+ * ends for whatever reason, it has received service at a
+ * rate that would not be high enough to complete the budget
+ * before the budget timeout expiration.
+ */
+ expected = bw * 1000 * timeout >> BFQ_RATE_SHIFT;
+
+ /*
+ * Caveat: processes doing IO in the slower disk zones will
+ * tend to be slow(er) even if not seeky. And the estimated
+ * peak rate will actually be an average over the disk
+ * surface. Hence, to not be too harsh with unlucky processes,
+ * we keep a budget/3 margin of safety before declaring a
+ * process slow.
+ */
+ return expected > (4 * bfqq->entity.budget) / 3;
+}
+
+/**
+ * bfq_bfqq_expire - expire a queue.
+ * @bfqd: device owning the queue.
+ * @bfqq: the queue to expire.
+ * @compensate: if true, compensate for the time spent idling.
+ * @reason: the reason causing the expiration.
+ *
+ *
+ * If the process associated to the queue is slow (i.e., seeky), or in
+ * case of budget timeout, or, finally, if it is async, we
+ * artificially charge it an entire budget (independently of the
+ * actual service it received). As a consequence, the queue will get
+ * higher timestamps than the correct ones upon reactivation, and
+ * hence it will be rescheduled as if it had received more service
+ * than what it actually received. In the end, this class of processes
+ * will receive less service in proportion to how slowly they consume
+ * their budgets (and hence how seriously they tend to lower the
+ * throughput).
+ *
+ * In contrast, when a queue expires because it has been idling for
+ * too much or because it exhausted its budget, we do not touch the
+ * amount of service it has received. Hence when the queue will be
+ * reactivated and its timestamps updated, the latter will be in sync
+ * with the actual service received by the queue until expiration.
+ *
+ * Charging a full budget to the first type of queues and the exact
+ * service to the others has the effect of using the WF2Q+ policy to
+ * schedule the former on a timeslice basis, without violating the
+ * service domain guarantees of the latter.
+ */
+static void bfq_bfqq_expire(struct bfq_data *bfqd,
+ struct bfq_queue *bfqq,
+ int compensate,
+ enum bfqq_expiration reason)
+{
+ int slow;
+ BUG_ON(bfqq != bfqd->active_queue);
+
+ /* Update disk peak rate for autotuning and check whether the
+ * process is slow (see bfq_update_peak_rate).
+ */
+ slow = bfq_update_peak_rate(bfqd, bfqq, compensate, reason);
+
+ /*
+ * As above explained, 'punish' slow (i.e., seeky), timed-out
+ * and async queues, to favor sequential sync workloads.
+ *
+ * Processes doing IO in the slower disk zones will tend to be
+ * slow(er) even if not seeky. Hence, since the estimated peak
+ * rate is actually an average over the disk surface, these
+ * processes may timeout just for bad luck. To avoid punishing
+ * them we do not charge a full budget to a process that
+ * succeeded in consuming at least 2/3 of its budget.
+ */
+ if (slow || (reason == BFQ_BFQQ_BUDGET_TIMEOUT &&
+ bfq_bfqq_budget_left(bfqq) >= bfqq->entity.budget / 3))
+ bfq_bfqq_charge_full_budget(bfqq);
+
+ if (bfqd->low_latency && bfqq->raising_coeff == 1)
+ bfqq->last_rais_start_finish = jiffies;
+
+ if (bfqd->low_latency && bfqd->bfq_raising_max_softrt_rate > 0) {
+ if(reason != BFQ_BFQQ_BUDGET_TIMEOUT)
+ bfqq->soft_rt_next_start =
+ jiffies +
+ HZ * bfqq->entity.service /
+ bfqd->bfq_raising_max_softrt_rate;
+ else
+ bfqq->soft_rt_next_start = -1; /* infinity */
+ }
+ bfq_log_bfqq(bfqd, bfqq,
+ "expire (%d, slow %d, num_disp %d, idle_win %d)", reason, slow,
+ bfqq->dispatched, bfq_bfqq_idle_window(bfqq));
+
+ /* Increase, decrease or leave budget unchanged according to reason */
+ __bfq_bfqq_recalc_budget(bfqd, bfqq, reason);
+ __bfq_bfqq_expire(bfqd, bfqq);
+}
+
+/*
+ * Budget timeout is not implemented through a dedicated timer, but
+ * just checked on request arrivals and completions, as well as on
+ * idle timer expirations.
+ */
+static int bfq_bfqq_budget_timeout(struct bfq_queue *bfqq)
+{
+ if (bfq_bfqq_budget_new(bfqq))
+ return 0;
+
+ if (time_before(jiffies, bfqq->budget_timeout))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * If we expire a queue that is waiting for the arrival of a new
+ * request, we may prevent the fictitious timestamp backshifting that
+ * allows the guarantees of the queue to be preserved (see [1] for
+ * this tricky aspect). Hence we return true only if this condition
+ * does not hold, or if the queue is slow enough to deserve only to be
+ * kicked off for preserving a high throughput.
+*/
+static inline int bfq_may_expire_for_budg_timeout(struct bfq_queue *bfqq)
+{
+ bfq_log_bfqq(bfqq->bfqd, bfqq,
+ "may_budget_timeout: wr %d left %d timeout %d",
+ bfq_bfqq_wait_request(bfqq),
+ bfq_bfqq_budget_left(bfqq) >= bfqq->entity.budget / 3,
+ bfq_bfqq_budget_timeout(bfqq));
+
+ return (!bfq_bfqq_wait_request(bfqq) ||
+ bfq_bfqq_budget_left(bfqq) >= bfqq->entity.budget / 3)
+ &&
+ bfq_bfqq_budget_timeout(bfqq);
+}
+
+/*
+ * Select a queue for service. If we have a current active queue,
+ * check whether to continue servicing it, or retrieve and set a new one.
+ */
+static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd)
+{
+ struct bfq_queue *bfqq, *new_bfqq = NULL;
+ struct request *next_rq;
+ enum bfqq_expiration reason = BFQ_BFQQ_BUDGET_TIMEOUT;
+
+ bfqq = bfqd->active_queue;
+ if (bfqq == NULL)
+ goto new_queue;
+
+ bfq_log_bfqq(bfqd, bfqq, "select_queue: already active queue");
+
+ /*
+ * If another queue has a request waiting within our mean seek
+ * distance, let it run. The expire code will check for close
+ * cooperators and put the close queue at the front of the
+ * service tree. If possible, merge the expiring queue with the
+ * new bfqq.
+ */
+ new_bfqq = bfq_close_cooperator(bfqd, bfqq);
+ if (new_bfqq != NULL && bfqq->new_bfqq == NULL)
+ bfq_setup_merge(bfqq, new_bfqq);
+
+ if (bfq_may_expire_for_budg_timeout(bfqq))
+ goto expire;
+
+ next_rq = bfqq->next_rq;
+ /*
+ * If bfqq has requests queued and it has enough budget left to
+ * serve them, keep the queue, otherwise expire it.
+ */
+ if (next_rq != NULL) {
+ if (bfq_serv_to_charge(next_rq, bfqq) >
+ bfq_bfqq_budget_left(bfqq)) {
+ reason = BFQ_BFQQ_BUDGET_EXHAUSTED;
+ goto expire;
+ } else {
+ /*
+ * The idle timer may be pending because we may not
+ * disable disk idling even when a new request arrives
+ */
+ if (timer_pending(&bfqd->idle_slice_timer)) {
+ /*
+ * If we get here: 1) at least a new request
+ * has arrived but we have not disabled the
+ * timer because the request was too small,
+ * 2) then the block layer has unplugged the
+ * device, causing the dispatch to be invoked.
+ *
+ * Since the device is unplugged, now the
+ * requests are probably large enough to
+ * provide a reasonable throughput.
+ * So we disable idling.
+ */
+ bfq_clear_bfqq_wait_request(bfqq);
+ del_timer(&bfqd->idle_slice_timer);
+ }
+ if (new_bfqq == NULL)
+ goto keep_queue;
+ else
+ goto expire;
+ }
+ }
+
+ /*
+ * No requests pending. If there is no cooperator, and the active
+ * queue still has requests in flight or is idling for a new request,
+ * then keep it.
+ */
+ if (new_bfqq == NULL && (timer_pending(&bfqd->idle_slice_timer) ||
+ (bfqq->dispatched != 0 && bfq_bfqq_idle_window(bfqq) &&
+ !bfq_queue_nonrot_noidle(bfqd, bfqq)))) {
+ bfqq = NULL;
+ goto keep_queue;
+ } else if (new_bfqq != NULL && timer_pending(&bfqd->idle_slice_timer)) {
+ /*
+ * Expiring the queue because there is a close cooperator,
+ * cancel timer.
+ */
+ bfq_clear_bfqq_wait_request(bfqq);
+ del_timer(&bfqd->idle_slice_timer);
+ }
+
+ reason = BFQ_BFQQ_NO_MORE_REQUESTS;
+expire:
+ bfq_bfqq_expire(bfqd, bfqq, 0, reason);
+new_queue:
+ bfqq = bfq_set_active_queue(bfqd, new_bfqq);
+ bfq_log(bfqd, "select_queue: new queue %d returned",
+ bfqq != NULL ? bfqq->pid : 0);
+keep_queue:
+ return bfqq;
+}
+
+static void update_raising_data(struct bfq_data *bfqd, struct bfq_queue *bfqq)
+{
+ if (bfqq->raising_coeff > 1) { /* queue is being boosted */
+ struct bfq_entity *entity = &bfqq->entity;
+
+ bfq_log_bfqq(bfqd, bfqq,
+ "raising period dur %u/%u msec, "
+ "old raising coeff %u, w %d(%d)",
+ jiffies_to_msecs(jiffies -
+ bfqq->last_rais_start_finish),
+ jiffies_to_msecs(bfqq->raising_cur_max_time),
+ bfqq->raising_coeff,
+ bfqq->entity.weight, bfqq->entity.orig_weight);
+
+ BUG_ON(bfqq != bfqd->active_queue && entity->weight !=
+ entity->orig_weight * bfqq->raising_coeff);
+ if(entity->ioprio_changed)
+ bfq_log_bfqq(bfqd, bfqq,
+ "WARN: pending prio change");
+ /*
+ * If too much time has elapsed from the beginning
+ * of this weight-raising period and process is not soft
+ * real-time, stop it
+ */
+ if (jiffies - bfqq->last_rais_start_finish >
+ bfqq->raising_cur_max_time) {
+ int soft_rt = bfqd->bfq_raising_max_softrt_rate > 0 &&
+ bfqq->soft_rt_next_start < jiffies;
+
+ bfqq->last_rais_start_finish = jiffies;
+ if (soft_rt)
+ bfqq->raising_cur_max_time =
+ bfqd->bfq_raising_rt_max_time;
+ else {
+ bfqq->raising_coeff = 1;
+ entity->ioprio_changed = 1;
+ __bfq_entity_update_weight_prio(
+ bfq_entity_service_tree(entity),
+ entity);
+ }
+ }
+ }
+}
+
+
+/*
+ * Dispatch one request from bfqq, moving it to the request queue
+ * dispatch list.
+ */
+static int bfq_dispatch_request(struct bfq_data *bfqd,
+ struct bfq_queue *bfqq)
+{
+ int dispatched = 0;
+ struct request *rq;
+ unsigned long service_to_charge;
+
+ BUG_ON(RB_EMPTY_ROOT(&bfqq->sort_list));
+
+ /* Follow expired path, else get first next available. */
+ rq = bfq_check_fifo(bfqq);
+ if (rq == NULL)
+ rq = bfqq->next_rq;
+ service_to_charge = bfq_serv_to_charge(rq, bfqq);
+
+ if (service_to_charge > bfq_bfqq_budget_left(bfqq)) {
+ /*
+ * This may happen if the next rq is chosen
+ * in fifo order instead of sector order.
+ * The budget is properly dimensioned
+ * to be always sufficient to serve the next request
+ * only if it is chosen in sector order. The reason is
+ * that it would be quite inefficient and little useful
+ * to always make sure that the budget is large enough
+ * to serve even the possible next rq in fifo order.
+ * In fact, requests are seldom served in fifo order.
+ *
+ * Expire the queue for budget exhaustion, and
+ * make sure that the next act_budget is enough
+ * to serve the next request, even if it comes
+ * from the fifo expired path.
+ */
+ bfqq->next_rq = rq;
+ /*
+ * Since this dispatch is failed, make sure that
+ * a new one will be performed
+ */
+ if (!bfqd->rq_in_driver)
+ bfq_schedule_dispatch(bfqd);
+ goto expire;
+ }
+
+ /* Finally, insert request into driver dispatch list. */
+ bfq_bfqq_served(bfqq, service_to_charge);
+ bfq_dispatch_insert(bfqd->queue, rq);
+
+ update_raising_data(bfqd, bfqq);
+
+ bfq_log_bfqq(bfqd, bfqq, "dispatched %u sec req (%llu), "
+ "budg left %lu",
+ blk_rq_sectors(rq),
+ (long long unsigned)blk_rq_pos(rq),
+ bfq_bfqq_budget_left(bfqq));
+
+ dispatched++;
+
+ if (bfqd->active_cic == NULL) {
+ atomic_long_inc(&RQ_CIC(rq)->ioc->refcount);
+ bfqd->active_cic = RQ_CIC(rq);
+ }
+
+ if (bfqd->busy_queues > 1 && ((!bfq_bfqq_sync(bfqq) &&
+ dispatched >= bfqd->bfq_max_budget_async_rq) ||
+ bfq_class_idle(bfqq)))
+ goto expire;
+
+ return dispatched;
+
+expire:
+ bfq_bfqq_expire(bfqd, bfqq, 0, BFQ_BFQQ_BUDGET_EXHAUSTED);
+ return dispatched;
+}
+
+static int __bfq_forced_dispatch_bfqq(struct bfq_queue *bfqq)
+{
+ int dispatched = 0;
+
+ while (bfqq->next_rq != NULL) {
+ bfq_dispatch_insert(bfqq->bfqd->queue, bfqq->next_rq);
+ dispatched++;
+ }
+
+ BUG_ON(!list_empty(&bfqq->fifo));
+ return dispatched;
+}
+
+/*
+ * Drain our current requests. Used for barriers and when switching
+ * io schedulers on-the-fly.
+ */
+static int bfq_forced_dispatch(struct bfq_data *bfqd)
+{
+ struct bfq_queue *bfqq, *n;
+ struct bfq_service_tree *st;
+ int dispatched = 0;
+
+ bfqq = bfqd->active_queue;
+ if (bfqq != NULL)
+ __bfq_bfqq_expire(bfqd, bfqq);
+
+ /*
+ * Loop through classes, and be careful to leave the scheduler
+ * in a consistent state, as feedback mechanisms and vtime
+ * updates cannot be disabled during the process.
+ */
+ list_for_each_entry_safe(bfqq, n, &bfqd->active_list, bfqq_list) {
+ st = bfq_entity_service_tree(&bfqq->entity);
+
+ dispatched += __bfq_forced_dispatch_bfqq(bfqq);
+ bfqq->max_budget = bfq_max_budget(bfqd);
+
+ bfq_forget_idle(st);
+ }
+
+ BUG_ON(bfqd->busy_queues != 0);
+
+ return dispatched;
+}
+
+static int bfq_dispatch_requests(struct request_queue *q, int force)
+{
+ struct bfq_data *bfqd = q->elevator->elevator_data;
+ struct bfq_queue *bfqq;
+ int max_dispatch;
+
+ bfq_log(bfqd, "dispatch requests: %d busy queues", bfqd->busy_queues);
+ if (bfqd->busy_queues == 0)
+ return 0;
+
+ if (unlikely(force))
+ return bfq_forced_dispatch(bfqd);
+
+ if((bfqq = bfq_select_queue(bfqd)) == NULL)
+ return 0;
+
+ max_dispatch = bfqd->bfq_quantum;
+ if (bfq_class_idle(bfqq))
+ max_dispatch = 1;
+
+ if (!bfq_bfqq_sync(bfqq))
+ max_dispatch = bfqd->bfq_max_budget_async_rq;
+
+ if (bfqq->dispatched >= max_dispatch) {
+ if (bfqd->busy_queues > 1)
+ return 0;
+ if (bfqq->dispatched >= 4 * max_dispatch)
+ return 0;
+ }
+
+ if (bfqd->sync_flight != 0 && !bfq_bfqq_sync(bfqq))
+ return 0;
+
+ bfq_clear_bfqq_wait_request(bfqq);
+ BUG_ON(timer_pending(&bfqd->idle_slice_timer));
+
+ if (! bfq_dispatch_request(bfqd, bfqq))
+ return 0;
+
+ bfq_log_bfqq(bfqd, bfqq, "dispatched one request of %d"
+ "(max_disp %d)", bfqq->pid, max_dispatch);
+
+ return 1;
+}
+
+/*
+ * Task holds one reference to the queue, dropped when task exits. Each rq
+ * in-flight on this queue also holds a reference, dropped when rq is freed.
+ *
+ * Queue lock must be held here.
+ */
+static void bfq_put_queue(struct bfq_queue *bfqq)
+{
+ struct bfq_data *bfqd = bfqq->bfqd;
+
+ BUG_ON(atomic_read(&bfqq->ref) <= 0);
+
+ bfq_log_bfqq(bfqd, bfqq, "put_queue: %p %d", bfqq,
+ atomic_read(&bfqq->ref));
+ if (!atomic_dec_and_test(&bfqq->ref))
+ return;
+
+ BUG_ON(rb_first(&bfqq->sort_list) != NULL);
+ BUG_ON(bfqq->allocated[READ] + bfqq->allocated[WRITE] != 0);
+ BUG_ON(bfqq->entity.tree != NULL);
+ BUG_ON(bfq_bfqq_busy(bfqq));
+ BUG_ON(bfqd->active_queue == bfqq);
+
+ bfq_log_bfqq(bfqd, bfqq, "put_queue: %p freed", bfqq);
+
+ kmem_cache_free(bfq_pool, bfqq);
+}
+
+static void bfq_put_cooperator(struct bfq_queue *bfqq)
+{
+ struct bfq_queue *__bfqq, *next;
+
+ /*
+ * If this queue was scheduled to merge with another queue, be
+ * sure to drop the reference taken on that queue (and others in
+ * the merge chain). See bfq_setup_merge and bfq_merge_bfqqs.
+ */
+ __bfqq = bfqq->new_bfqq;
+ while (__bfqq) {
+ if (__bfqq == bfqq) {
+ WARN(1, "bfqq->new_bfqq loop detected.\n");
+ break;
+ }
+ next = __bfqq->new_bfqq;
+ bfq_put_queue(__bfqq);
+ __bfqq = next;
+ }
+}
+
+static void bfq_exit_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq)
+{
+ if (bfqq == bfqd->active_queue) {
+ __bfq_bfqq_expire(bfqd, bfqq);
+ bfq_schedule_dispatch(bfqd);
+ }
+
+ bfq_log_bfqq(bfqd, bfqq, "exit_bfqq: %p, %d", bfqq,
+ atomic_read(&bfqq->ref));
+
+ bfq_put_cooperator(bfqq);
+
+ bfq_put_queue(bfqq);
+}
+
+/*
+ * Update the entity prio values; note that the new values will not
+ * be used until the next (re)activation.
+ */
+static void bfq_init_prio_data(struct bfq_queue *bfqq, struct io_context *ioc)
+{
+ struct task_struct *tsk = current;
+ int ioprio_class;
+
+ if (!bfq_bfqq_prio_changed(bfqq))
+ return;
+
+ ioprio_class = IOPRIO_PRIO_CLASS(ioc->ioprio);
+ switch (ioprio_class) {
+ default:
+ printk(KERN_ERR "bfq: bad prio %x\n", ioprio_class);
+ case IOPRIO_CLASS_NONE:
+ /*
+ * No prio set, inherit CPU scheduling settings.
+ */
+ bfqq->entity.new_ioprio = task_nice_ioprio(tsk);
+ bfqq->entity.new_ioprio_class = task_nice_ioclass(tsk);
+ break;
+ case IOPRIO_CLASS_RT:
+ bfqq->entity.new_ioprio = task_ioprio(ioc);
+ bfqq->entity.new_ioprio_class = IOPRIO_CLASS_RT;
+ break;
+ case IOPRIO_CLASS_BE:
+ bfqq->entity.new_ioprio = task_ioprio(ioc);
+ bfqq->entity.new_ioprio_class = IOPRIO_CLASS_BE;
+ break;
+ case IOPRIO_CLASS_IDLE:
+ bfqq->entity.new_ioprio_class = IOPRIO_CLASS_IDLE;
+ bfqq->entity.new_ioprio = 7;
+ bfq_clear_bfqq_idle_window(bfqq);
+ break;
+ }
+
+ bfqq->entity.ioprio_changed = 1;
+
+ /*
+ * Keep track of original prio settings in case we have to temporarily
+ * elevate the priority of this queue.
+ */
+ bfqq->org_ioprio = bfqq->entity.new_ioprio;
+ bfqq->org_ioprio_class = bfqq->entity.new_ioprio_class;
+ bfq_clear_bfqq_prio_changed(bfqq);
+}
+
+static void bfq_changed_ioprio(struct io_context *ioc,
+ struct cfq_io_context *cic)
+{
+ struct bfq_data *bfqd;
+ struct bfq_queue *bfqq, *new_bfqq;
+ struct bfq_group *bfqg;
+ unsigned long uninitialized_var(flags);
+
+ bfqd = bfq_get_bfqd_locked(&cic->key, &flags);
+ if (unlikely(bfqd == NULL))
+ return;
+
+ bfqq = cic->cfqq[BLK_RW_ASYNC];
+ if (bfqq != NULL) {
+ bfqg = container_of(bfqq->entity.sched_data, struct bfq_group,
+ sched_data);
+ new_bfqq = bfq_get_queue(bfqd, bfqg, BLK_RW_ASYNC, cic->ioc,
+ GFP_ATOMIC);
+ if (new_bfqq != NULL) {
+ cic->cfqq[BLK_RW_ASYNC] = new_bfqq;
+ bfq_log_bfqq(bfqd, bfqq,
+ "changed_ioprio: bfqq %p %d",
+ bfqq, atomic_read(&bfqq->ref));
+ bfq_put_queue(bfqq);
+ }
+ }
+
+ bfqq = cic->cfqq[BLK_RW_SYNC];
+ if (bfqq != NULL)
+ bfq_mark_bfqq_prio_changed(bfqq);
+
+ bfq_put_bfqd_unlock(bfqd, &flags);
+}
+
+static void bfq_init_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq,
+ pid_t pid, int is_sync)
+{
+ RB_CLEAR_NODE(&bfqq->entity.rb_node);
+ INIT_LIST_HEAD(&bfqq->fifo);
+
+ atomic_set(&bfqq->ref, 0);
+ bfqq->bfqd = bfqd;
+
+ bfq_mark_bfqq_prio_changed(bfqq);
+
+ if (is_sync) {
+ if (!bfq_class_idle(bfqq))
+ bfq_mark_bfqq_idle_window(bfqq);
+ bfq_mark_bfqq_sync(bfqq);
+ }
+
+ /* Tentative initial value to trade off between thr and lat */
+ bfqq->max_budget = (2 * bfq_max_budget(bfqd)) / 3;
+ bfqq->pid = pid;
+
+ bfqq->raising_coeff = 1;
+ bfqq->last_rais_start_finish = 0;
+ bfqq->soft_rt_next_start = -1;
+}
+
+static struct bfq_queue *bfq_find_alloc_queue(struct bfq_data *bfqd,
+ struct bfq_group *bfqg,
+ int is_sync,
+ struct io_context *ioc,
+ gfp_t gfp_mask)
+{
+ struct bfq_queue *bfqq, *new_bfqq = NULL;
+ struct cfq_io_context *cic;
+
+retry:
+ cic = bfq_cic_lookup(bfqd, ioc);
+ /* cic always exists here */
+ bfqq = cic_to_bfqq(cic, is_sync);
+
+ /*
+ * Always try a new alloc if we fall back to the OOM bfqq
+ * originally, since it should just be a temporary situation.
+ */
+ if (bfqq == NULL || bfqq == &bfqd->oom_bfqq) {
+ bfqq = NULL;
+ if (new_bfqq != NULL) {
+ bfqq = new_bfqq;
+ new_bfqq = NULL;
+ } else if (gfp_mask & __GFP_WAIT) {
+ spin_unlock_irq(bfqd->queue->queue_lock);
+ new_bfqq = kmem_cache_alloc_node(bfq_pool,
+ gfp_mask | __GFP_ZERO,
+ bfqd->queue->node);
+ spin_lock_irq(bfqd->queue->queue_lock);
+ if (new_bfqq != NULL)
+ goto retry;
+ } else {
+ bfqq = kmem_cache_alloc_node(bfq_pool,
+ gfp_mask | __GFP_ZERO,
+ bfqd->queue->node);
+ }
+
+ if (bfqq != NULL) {
+ bfq_init_bfqq(bfqd, bfqq, current->pid, is_sync);
+ bfq_log_bfqq(bfqd, bfqq, "allocated");
+ } else {
+ bfqq = &bfqd->oom_bfqq;
+ bfq_log_bfqq(bfqd, bfqq, "using oom bfqq");
+ }
+
+ bfq_init_prio_data(bfqq, ioc);
+ bfq_init_entity(&bfqq->entity, bfqg);
+ }
+
+ if (new_bfqq != NULL)
+ kmem_cache_free(bfq_pool, new_bfqq);
+
+ return bfqq;
+}
+
+static struct bfq_queue **bfq_async_queue_prio(struct bfq_data *bfqd,
+ struct bfq_group *bfqg,
+ int ioprio_class, int ioprio)
+{
+ switch (ioprio_class) {
+ case IOPRIO_CLASS_RT:
+ return &bfqg->async_bfqq[0][ioprio];
+ case IOPRIO_CLASS_BE:
+ return &bfqg->async_bfqq[1][ioprio];
+ case IOPRIO_CLASS_IDLE:
+ return &bfqg->async_idle_bfqq;
+ default:
+ BUG();
+ }
+}
+
+static struct bfq_queue *bfq_get_queue(struct bfq_data *bfqd,
+ struct bfq_group *bfqg, int is_sync,
+ struct io_context *ioc, gfp_t gfp_mask)
+{
+ const int ioprio = task_ioprio(ioc);
+ const int ioprio_class = task_ioprio_class(ioc);
+ struct bfq_queue **async_bfqq = NULL;
+ struct bfq_queue *bfqq = NULL;
+
+ if (!is_sync) {
+ async_bfqq = bfq_async_queue_prio(bfqd, bfqg, ioprio_class,
+ ioprio);
+ bfqq = *async_bfqq;
+ }
+
+ if (bfqq == NULL)
+ bfqq = bfq_find_alloc_queue(bfqd, bfqg, is_sync, ioc, gfp_mask);
+
+ /*
+ * Pin the queue now that it's allocated, scheduler exit will prune it.
+ */
+ if (!is_sync && *async_bfqq == NULL) {
+ atomic_inc(&bfqq->ref);
+ bfq_log_bfqq(bfqd, bfqq, "get_queue, bfqq not in async: %p, %d",
+ bfqq, atomic_read(&bfqq->ref));
+ *async_bfqq = bfqq;
+ }
+
+ atomic_inc(&bfqq->ref);
+ bfq_log_bfqq(bfqd, bfqq, "get_queue, at end: %p, %d", bfqq,
+ atomic_read(&bfqq->ref));
+ return bfqq;
+}
+
+static void bfq_update_io_thinktime(struct bfq_data *bfqd,
+ struct cfq_io_context *cic)
+{
+ unsigned long elapsed = jiffies - cic->last_end_request;
+ unsigned long ttime = min(elapsed, 2UL * bfqd->bfq_slice_idle);
+
+ cic->ttime_samples = (7*cic->ttime_samples + 256) / 8;
+ cic->ttime_total = (7*cic->ttime_total + 256*ttime) / 8;
+ cic->ttime_mean = (cic->ttime_total + 128) / cic->ttime_samples;
+}
+
+static void bfq_update_io_seektime(struct bfq_data *bfqd,
+ struct bfq_queue *bfqq,
+ struct request *rq)
+{
+ sector_t sdist;
+ u64 total;
+
+ if (bfqq->last_request_pos < blk_rq_pos(rq))
+ sdist = blk_rq_pos(rq) - bfqq->last_request_pos;
+ else
+ sdist = bfqq->last_request_pos - blk_rq_pos(rq);
+
+ /*
+ * Don't allow the seek distance to get too large from the
+ * odd fragment, pagein, etc.
+ */
+ if (bfqq->seek_samples == 0) /* first request, not really a seek */
+ sdist = 0;
+ else if (bfqq->seek_samples <= 60) /* second & third seek */
+ sdist = min(sdist, (bfqq->seek_mean * 4) + 2*1024*1024);
+ else
+ sdist = min(sdist, (bfqq->seek_mean * 4) + 2*1024*64);
+
+ bfqq->seek_samples = (7*bfqq->seek_samples + 256) / 8;
+ bfqq->seek_total = (7*bfqq->seek_total + (u64)256*sdist) / 8;
+ total = bfqq->seek_total + (bfqq->seek_samples/2);
+ do_div(total, bfqq->seek_samples);
+ if (bfq_bfqq_coop(bfqq)) {
+ /*
+ * If the mean seektime increases for a (non-seeky) shared
+ * queue, some cooperator is likely to be idling too much.
+ * On the contrary, if it decreases, some cooperator has
+ * probably waked up.
+ *
+ */
+ if ((sector_t)total < bfqq->seek_mean)
+ bfq_mark_bfqq_some_coop_idle(bfqq) ;
+ else if ((sector_t)total > bfqq->seek_mean)
+ bfq_clear_bfqq_some_coop_idle(bfqq) ;
+ }
+ bfqq->seek_mean = (sector_t)total;
+
+ bfq_log_bfqq(bfqd, bfqq, "dist=%llu mean=%llu", (u64)sdist,
+ (u64)bfqq->seek_mean);
+}
+
+/*
+ * Disable idle window if the process thinks too long or seeks so much that
+ * it doesn't matter.
+ */
+static void bfq_update_idle_window(struct bfq_data *bfqd,
+ struct bfq_queue *bfqq,
+ struct cfq_io_context *cic)
+{
+ int enable_idle;
+
+ /* Don't idle for async or idle io prio class. */
+ if (!bfq_bfqq_sync(bfqq) || bfq_class_idle(bfqq))
+ return;
+
+ enable_idle = bfq_bfqq_idle_window(bfqq);
+
+ if (atomic_read(&cic->ioc->nr_tasks) == 0 ||
+ bfqd->bfq_slice_idle == 0 ||
+ (bfqd->hw_tag && BFQQ_SEEKY(bfqq) &&
+ bfqq->raising_coeff == 1))
+ enable_idle = 0;
+ else if (bfq_sample_valid(cic->ttime_samples)) {
+ if (cic->ttime_mean > bfqd->bfq_slice_idle &&
+ bfqq->raising_coeff == 1)
+ enable_idle = 0;
+ else
+ enable_idle = 1;
+ }
+ bfq_log_bfqq(bfqd, bfqq, "update_idle_window: enable_idle %d",
+ enable_idle);
+
+ if (enable_idle)
+ bfq_mark_bfqq_idle_window(bfqq);
+ else
+ bfq_clear_bfqq_idle_window(bfqq);
+}
+
+/*
+ * Called when a new fs request (rq) is added to bfqq. Check if there's
+ * something we should do about it.
+ */
+static void bfq_rq_enqueued(struct bfq_data *bfqd, struct bfq_queue *bfqq,
+ struct request *rq)
+{
+ struct cfq_io_context *cic = RQ_CIC(rq);
+
+ if (rq->cmd_flags & REQ_META)
+ bfqq->meta_pending++;
+
+ bfq_update_io_thinktime(bfqd, cic);
+ bfq_update_io_seektime(bfqd, bfqq, rq);
+ if (bfqq->entity.service > bfq_max_budget(bfqd) / 8 ||
+ !BFQQ_SEEKY(bfqq))
+ bfq_update_idle_window(bfqd, bfqq, cic);
+
+ bfq_log_bfqq(bfqd, bfqq,
+ "rq_enqueued: idle_window=%d (seeky %d, mean %llu)",
+ bfq_bfqq_idle_window(bfqq), BFQQ_SEEKY(bfqq),
+ (long long unsigned)bfqq->seek_mean);
+
+ bfqq->last_request_pos = blk_rq_pos(rq) + blk_rq_sectors(rq);
+
+ if (bfqq == bfqd->active_queue) {
+ /*
+ * If there is just this request queued and the request
+ * is small, just exit.
+ * In this way, if the disk is being idled to wait for a new
+ * request from the active queue, we avoid unplugging the
+ * device now.
+ *
+ * By doing so, we spare the disk to be committed
+ * to serve just a small request. On the contrary, we wait for
+ * the block layer to decide when to unplug the device:
+ * hopefully, new requests will be merged to this
+ * one quickly, then the device will be unplugged
+ * and larger requests will be dispatched.
+ */
+ if (bfqq->queued[rq_is_sync(rq)] == 1 &&
+ blk_rq_sectors(rq) < 32) {
+ return;
+ }
+ if (bfq_bfqq_wait_request(bfqq)) {
+ /*
+ * If we are waiting for a request for this queue, let
+ * it rip immediately and flag that we must not expire
+ * this queue just now.
+ */
+ bfq_clear_bfqq_wait_request(bfqq);
+ del_timer(&bfqd->idle_slice_timer);
+ /*
+ * Here we can safely expire the queue, in
+ * case of budget timeout, without wasting
+ * guarantees
+ */
+ if (bfq_bfqq_budget_timeout(bfqq))
+ bfq_bfqq_expire(bfqd, bfqq, 0,
+ BFQ_BFQQ_BUDGET_TIMEOUT);
+ __blk_run_queue(bfqd->queue);
+ }
+ }
+}
+
+static void bfq_insert_request(struct request_queue *q, struct request *rq)
+{
+ struct bfq_data *bfqd = q->elevator->elevator_data;
+ struct bfq_queue *bfqq = RQ_BFQQ(rq);
+
+ assert_spin_locked(bfqd->queue->queue_lock);
+ bfq_init_prio_data(bfqq, RQ_CIC(rq)->ioc);
+
+ bfq_add_rq_rb(rq);
+
+ rq_set_fifo_time(rq, jiffies + bfqd->bfq_fifo_expire[rq_is_sync(rq)]);
+ list_add_tail(&rq->queuelist, &bfqq->fifo);
+
+ bfq_rq_enqueued(bfqd, bfqq, rq);
+}
+
+static void bfq_update_hw_tag(struct bfq_data *bfqd)
+{
+ bfqd->max_rq_in_driver = max(bfqd->max_rq_in_driver,
+ bfqd->rq_in_driver);
+
+ if (bfqd->hw_tag == 1)
+ return;
+
+ /*
+ * This sample is valid if the number of outstanding requests
+ * is large enough to allow a queueing behavior. Note that the
+ * sum is not exact, as it's not taking into account deactivated
+ * requests.
+ */
+ if (bfqd->rq_in_driver + bfqd->queued < BFQ_HW_QUEUE_THRESHOLD)
+ return;
+
+ if (bfqd->hw_tag_samples++ < BFQ_HW_QUEUE_SAMPLES)
+ return;
+
+ bfqd->hw_tag = bfqd->max_rq_in_driver > BFQ_HW_QUEUE_THRESHOLD;
+ bfqd->max_rq_in_driver = 0;
+ bfqd->hw_tag_samples = 0;
+}
+
+static void bfq_completed_request(struct request_queue *q, struct request *rq)
+{
+ struct bfq_queue *bfqq = RQ_BFQQ(rq);
+ struct bfq_data *bfqd = bfqq->bfqd;
+ const int sync = rq_is_sync(rq);
+
+ bfq_log_bfqq(bfqd, bfqq, "completed %u sects req (%d)",
+ blk_rq_sectors(rq), sync);
+
+ bfq_update_hw_tag(bfqd);
+
+ WARN_ON(!bfqd->rq_in_driver);
+ WARN_ON(!bfqq->dispatched);
+ bfqd->rq_in_driver--;
+ bfqq->dispatched--;
+
+ if (bfq_bfqq_sync(bfqq))
+ bfqd->sync_flight--;
+
+ if (sync)
+ RQ_CIC(rq)->last_end_request = jiffies;
+
+ /*
+ * If this is the active queue, check if it needs to be expired,
+ * or if we want to idle in case it has no pending requests.
+ */
+ if (bfqd->active_queue == bfqq) {
+ if (bfq_bfqq_budget_new(bfqq))
+ bfq_set_budget_timeout(bfqd);
+
+ /* Idling is disabled also for cooperation issues:
+ * 1) there is a close cooperator for the queue, or
+ * 2) the queue is shared and some cooperator is likely
+ * to be idle (in this case, by not arming the idle timer,
+ * we try to slow down the queue, to prevent the zones
+ * of the disk accessed by the active cooperators to become
+ * too distant from the zone that will be accessed by the
+ * currently idle cooperators)
+ */
+ if (bfq_may_expire_for_budg_timeout(bfqq))
+ bfq_bfqq_expire(bfqd, bfqq, 0, BFQ_BFQQ_BUDGET_TIMEOUT);
+ else if (sync &&
+ (bfqd->rq_in_driver == 0 ||
+ bfqq->raising_coeff > 1)
+ && RB_EMPTY_ROOT(&bfqq->sort_list)
+ && !bfq_close_cooperator(bfqd, bfqq)
+ && (!bfq_bfqq_coop(bfqq) ||
+ !bfq_bfqq_some_coop_idle(bfqq)))
+ bfq_arm_slice_timer(bfqd);
+ }
+
+ if (!bfqd->rq_in_driver)
+ bfq_schedule_dispatch(bfqd);
+}
+
+/*
+ * We temporarily boost lower priority queues if they are holding fs exclusive
+ * resources. They are boosted to normal prio (CLASS_BE/4).
+ */
+static void bfq_prio_boost(struct bfq_queue *bfqq)
+{
+ if (has_fs_excl()) {
+ /*
+ * Boost idle prio on transactions that would lock out other
+ * users of the filesystem
+ */
+ if (bfq_class_idle(bfqq))
+ bfqq->entity.new_ioprio_class = IOPRIO_CLASS_BE;
+ if (bfqq->entity.new_ioprio > IOPRIO_NORM)
+ bfqq->entity.new_ioprio = IOPRIO_NORM;
+ } else {
+ /*
+ * Unboost the queue (if needed)
+ */
+ bfqq->entity.new_ioprio_class = bfqq->org_ioprio_class;
+ bfqq->entity.new_ioprio = bfqq->org_ioprio;
+ }
+}
+
+static inline int __bfq_may_queue(struct bfq_queue *bfqq)
+{
+ if (bfq_bfqq_wait_request(bfqq) && bfq_bfqq_must_alloc(bfqq)) {
+ bfq_clear_bfqq_must_alloc(bfqq);
+ return ELV_MQUEUE_MUST;
+ }
+
+ return ELV_MQUEUE_MAY;
+}
+
+static int bfq_may_queue(struct request_queue *q, int rw)
+{
+ struct bfq_data *bfqd = q->elevator->elevator_data;
+ struct task_struct *tsk = current;
+ struct cfq_io_context *cic;
+ struct bfq_queue *bfqq;
+
+ /*
+ * Don't force setup of a queue from here, as a call to may_queue
+ * does not necessarily imply that a request actually will be queued.
+ * So just lookup a possibly existing queue, or return 'may queue'
+ * if that fails.
+ */
+ cic = bfq_cic_lookup(bfqd, tsk->io_context);
+ if (cic == NULL)
+ return ELV_MQUEUE_MAY;
+
+ bfqq = cic_to_bfqq(cic, rw_is_sync(rw));
+ if (bfqq != NULL) {
+ bfq_init_prio_data(bfqq, cic->ioc);
+ bfq_prio_boost(bfqq);
+
+ return __bfq_may_queue(bfqq);
+ }
+
+ return ELV_MQUEUE_MAY;
+}
+
+/*
+ * Queue lock held here.
+ */
+static void bfq_put_request(struct request *rq)
+{
+ struct bfq_queue *bfqq = RQ_BFQQ(rq);
+
+ if (bfqq != NULL) {
+ const int rw = rq_data_dir(rq);
+
+ BUG_ON(!bfqq->allocated[rw]);
+ bfqq->allocated[rw]--;
+
+ put_io_context(RQ_CIC(rq)->ioc);
+
+ rq->elevator_private[0] = NULL;
+ rq->elevator_private[1] = NULL;
+
+ bfq_log_bfqq(bfqq->bfqd, bfqq, "put_request %p, %d",
+ bfqq, atomic_read(&bfqq->ref));
+ bfq_put_queue(bfqq);
+ }
+}
+
+static struct bfq_queue *
+bfq_merge_bfqqs(struct bfq_data *bfqd, struct cfq_io_context *cic,
+ struct bfq_queue *bfqq)
+{
+ bfq_log_bfqq(bfqd, bfqq, "merging with queue %lu",
+ (long unsigned)bfqq->new_bfqq->pid);
+ cic_set_bfqq(cic, bfqq->new_bfqq, 1);
+ bfq_mark_bfqq_coop(bfqq->new_bfqq);
+ bfq_put_queue(bfqq);
+ return cic_to_bfqq(cic, 1);
+}
+
+/*
+ * Returns NULL if a new bfqq should be allocated, or the old bfqq if this
+ * was the last process referring to said bfqq.
+ */
+static struct bfq_queue *
+bfq_split_bfqq(struct cfq_io_context *cic, struct bfq_queue *bfqq)
+{
+ bfq_log_bfqq(bfqq->bfqd, bfqq, "splitting queue");
+ if (bfqq_process_refs(bfqq) == 1) {
+ bfqq->pid = current->pid;
+ bfq_clear_bfqq_some_coop_idle(bfqq);
+ bfq_clear_bfqq_coop(bfqq);
+ bfq_clear_bfqq_split_coop(bfqq);
+ return bfqq;
+ }
+
+ cic_set_bfqq(cic, NULL, 1);
+
+ bfq_put_cooperator(bfqq);
+
+ bfq_put_queue(bfqq);
+ return NULL;
+}
+
+/*
+ * Allocate bfq data structures associated with this request.
+ */
+static int bfq_set_request(struct request_queue *q, struct request *rq,
+ gfp_t gfp_mask)
+{
+ struct bfq_data *bfqd = q->elevator->elevator_data;
+ struct cfq_io_context *cic;
+ const int rw = rq_data_dir(rq);
+ const int is_sync = rq_is_sync(rq);
+ struct bfq_queue *bfqq;
+ struct bfq_group *bfqg;
+ unsigned long flags;
+
+ might_sleep_if(gfp_mask & __GFP_WAIT);
+
+ cic = bfq_get_io_context(bfqd, gfp_mask);
+
+ spin_lock_irqsave(q->queue_lock, flags);
+
+ if (cic == NULL)
+ goto queue_fail;
+
+ bfqg = bfq_cic_update_cgroup(cic);
+
+new_queue:
+ bfqq = cic_to_bfqq(cic, is_sync);
+ if (bfqq == NULL || bfqq == &bfqd->oom_bfqq) {
+ bfqq = bfq_get_queue(bfqd, bfqg, is_sync, cic->ioc, gfp_mask);
+ cic_set_bfqq(cic, bfqq, is_sync);
+ } else {
+ /*
+ * If the queue was seeky for too long, break it apart.
+ */
+ if (bfq_bfqq_coop(bfqq) && bfq_bfqq_split_coop(bfqq)) {
+ bfq_log_bfqq(bfqd, bfqq, "breaking apart bfqq");
+ bfqq = bfq_split_bfqq(cic, bfqq);
+ if (!bfqq)
+ goto new_queue;
+ }
+
+ /*
+ * Check to see if this queue is scheduled to merge with
+ * another closely cooperating queue. The merging of queues
+ * happens here as it must be done in process context.
+ * The reference on new_bfqq was taken in merge_bfqqs.
+ */
+ if (bfqq->new_bfqq != NULL)
+ bfqq = bfq_merge_bfqqs(bfqd, cic, bfqq);
+ }
+
+ bfqq->allocated[rw]++;
+ atomic_inc(&bfqq->ref);
+ bfq_log_bfqq(bfqd, bfqq, "set_request: bfqq %p, %d", bfqq,
+ atomic_read(&bfqq->ref));
+
+ spin_unlock_irqrestore(q->queue_lock, flags);
+
+ rq->elevator_private[0] = cic;
+ rq->elevator_private[1] = bfqq;
+
+ return 0;
+
+queue_fail:
+ if (cic != NULL)
+ put_io_context(cic->ioc);
+
+ bfq_schedule_dispatch(bfqd);
+ spin_unlock_irqrestore(q->queue_lock, flags);
+
+ return 1;
+}
+
+static void bfq_kick_queue(struct work_struct *work)
+{
+ struct bfq_data *bfqd =
+ container_of(work, struct bfq_data, unplug_work);
+ struct request_queue *q = bfqd->queue;
+
+ spin_lock_irq(q->queue_lock);
+ __blk_run_queue(q);
+ spin_unlock_irq(q->queue_lock);
+}
+
+/*
+ * Handler of the expiration of the timer running if the active_queue
+ * is idling inside its time slice.
+ */
+static void bfq_idle_slice_timer(unsigned long data)
+{
+ struct bfq_data *bfqd = (struct bfq_data *)data;
+ struct bfq_queue *bfqq;
+ unsigned long flags;
+ enum bfqq_expiration reason;
+
+ spin_lock_irqsave(bfqd->queue->queue_lock, flags);
+
+ bfqq = bfqd->active_queue;
+ /*
+ * Theoretical race here: active_queue can be NULL or different
+ * from the queue that was idling if the timer handler spins on
+ * the queue_lock and a new request arrives for the current
+ * queue and there is a full dispatch cycle that changes the
+ * active_queue. This can hardly happen, but in the worst case
+ * we just expire a queue too early.
+ */
+ if (bfqq != NULL) {
+ bfq_log_bfqq(bfqd, bfqq, "slice_timer expired");
+ if (bfq_bfqq_budget_timeout(bfqq))
+ /*
+ * Also here the queue can be safely expired
+ * for budget timeout without wasting
+ * guarantees
+ */
+ reason = BFQ_BFQQ_BUDGET_TIMEOUT;
+ else if (bfqq->queued[0] == 0 && bfqq->queued[1] == 0)
+ /*
+ * The queue may not be empty upon timer expiration,
+ * because we may not disable the timer when the first
+ * request of the active queue arrives during
+ * disk idling
+ */
+ reason = BFQ_BFQQ_TOO_IDLE;
+ else
+ goto schedule_dispatch;
+
+ bfq_bfqq_expire(bfqd, bfqq, 1, reason);
+ }
+
+schedule_dispatch:
+ bfq_schedule_dispatch(bfqd);
+
+ spin_unlock_irqrestore(bfqd->queue->queue_lock, flags);
+}
+
+static void bfq_shutdown_timer_wq(struct bfq_data *bfqd)
+{
+ del_timer_sync(&bfqd->idle_slice_timer);
+ cancel_work_sync(&bfqd->unplug_work);
+}
+
+static inline void __bfq_put_async_bfqq(struct bfq_data *bfqd,
+ struct bfq_queue **bfqq_ptr)
+{
+ struct bfq_group *root_group = bfqd->root_group;
+ struct bfq_queue *bfqq = *bfqq_ptr;
+
+ bfq_log(bfqd, "put_async_bfqq: %p", bfqq);
+ if (bfqq != NULL) {
+ bfq_bfqq_move(bfqd, bfqq, &bfqq->entity, root_group);
+ bfq_log_bfqq(bfqd, bfqq, "put_async_bfqq: putting %p, %d",
+ bfqq, atomic_read(&bfqq->ref));
+ bfq_put_queue(bfqq);
+ *bfqq_ptr = NULL;
+ }
+}
+
+/*
+ * Release all the bfqg references to its async queues. If we are
+ * deallocating the group these queues may still contain requests, so
+ * we reparent them to the root cgroup (i.e., the only one that will
+ * exist for sure untill all the requests on a device are gone).
+ */
+static void bfq_put_async_queues(struct bfq_data *bfqd, struct bfq_group *bfqg)
+{
+ int i, j;
+
+ for (i = 0; i < 2; i++)
+ for (j = 0; j < IOPRIO_BE_NR; j++)
+ __bfq_put_async_bfqq(bfqd, &bfqg->async_bfqq[i][j]);
+
+ __bfq_put_async_bfqq(bfqd, &bfqg->async_idle_bfqq);
+}
+
+static void bfq_exit_queue(struct elevator_queue *e)
+{
+ struct bfq_data *bfqd = e->elevator_data;
+ struct request_queue *q = bfqd->queue;
+ struct bfq_queue *bfqq, *n;
+ struct cfq_io_context *cic;
+
+ bfq_shutdown_timer_wq(bfqd);
+
+ spin_lock_irq(q->queue_lock);
+
+ while (!list_empty(&bfqd->cic_list)) {
+ cic = list_entry(bfqd->cic_list.next, struct cfq_io_context,
+ queue_list);
+ __bfq_exit_single_io_context(bfqd, cic);
+ }
+
+ BUG_ON(bfqd->active_queue != NULL);
+ list_for_each_entry_safe(bfqq, n, &bfqd->idle_list, bfqq_list)
+ bfq_deactivate_bfqq(bfqd, bfqq, 0);
+
+ bfq_disconnect_groups(bfqd);
+ spin_unlock_irq(q->queue_lock);
+
+ bfq_shutdown_timer_wq(bfqd);
+
+ spin_lock(&cic_index_lock);
+ ida_remove(&cic_index_ida, bfqd->cic_index);
+ spin_unlock(&cic_index_lock);
+
+ /* Wait for cic->key accessors to exit their grace periods. */
+ synchronize_rcu();
+
+ BUG_ON(timer_pending(&bfqd->idle_slice_timer));
+
+ bfq_free_root_group(bfqd);
+ kfree(bfqd);
+}
+
+static int bfq_alloc_cic_index(void)
+{
+ int index, error;
+
+ do {
+ if (!ida_pre_get(&cic_index_ida, GFP_KERNEL))
+ return -ENOMEM;
+
+ spin_lock(&cic_index_lock);
+ error = ida_get_new(&cic_index_ida, &index);
+ spin_unlock(&cic_index_lock);
+ if (error && error != -EAGAIN)
+ return error;
+ } while (error);
+
+ return index;
+}
+
+static void *bfq_init_queue(struct request_queue *q)
+{
+ struct bfq_group *bfqg;
+ struct bfq_data *bfqd;
+ int i;
+
+ i = bfq_alloc_cic_index();
+ if (i < 0)
+ return NULL;
+
+ bfqd = kmalloc_node(sizeof(*bfqd), GFP_KERNEL | __GFP_ZERO, q->node);
+ if (bfqd == NULL)
+ return NULL;
+
+ bfqd->cic_index = i;
+
+ /*
+ * Our fallback bfqq if bfq_find_alloc_queue() runs into OOM issues.
+ * Grab a permanent reference to it, so that the normal code flow
+ * will not attempt to free it.
+ */
+ bfq_init_bfqq(bfqd, &bfqd->oom_bfqq, 1, 0);
+ atomic_inc(&bfqd->oom_bfqq.ref);
+
+ INIT_LIST_HEAD(&bfqd->cic_list);
+
+ bfqd->queue = q;
+
+ bfqg = bfq_alloc_root_group(bfqd, q->node);
+ if (bfqg == NULL) {
+ kfree(bfqd);
+ return NULL;
+ }
+
+ bfqd->root_group = bfqg;
+
+ init_timer(&bfqd->idle_slice_timer);
+ bfqd->idle_slice_timer.function = bfq_idle_slice_timer;
+ bfqd->idle_slice_timer.data = (unsigned long)bfqd;
+
+ bfqd->rq_pos_tree = RB_ROOT;
+
+ INIT_WORK(&bfqd->unplug_work, bfq_kick_queue);
+
+ INIT_LIST_HEAD(&bfqd->active_list);
+ INIT_LIST_HEAD(&bfqd->idle_list);
+
+ bfqd->hw_tag = -1;
+
+ bfqd->bfq_max_budget = bfq_default_max_budget;
+
+ bfqd->bfq_quantum = bfq_quantum;
+ bfqd->bfq_fifo_expire[0] = bfq_fifo_expire[0];
+ bfqd->bfq_fifo_expire[1] = bfq_fifo_expire[1];
+ bfqd->bfq_back_max = bfq_back_max;
+ bfqd->bfq_back_penalty = bfq_back_penalty;
+ bfqd->bfq_slice_idle = bfq_slice_idle;
+ bfqd->bfq_class_idle_last_service = 0;
+ bfqd->bfq_max_budget_async_rq = bfq_max_budget_async_rq;
+ bfqd->bfq_timeout[BLK_RW_ASYNC] = bfq_timeout_async;
+ bfqd->bfq_timeout[BLK_RW_SYNC] = bfq_timeout_sync;
+
+ bfqd->low_latency = true;
+
+ bfqd->bfq_raising_coeff = 20;
+ bfqd->bfq_raising_rt_max_time = msecs_to_jiffies(300);
+ bfqd->bfq_raising_max_time = 0;
+ bfqd->bfq_raising_min_idle_time = msecs_to_jiffies(2000);
+ bfqd->bfq_raising_min_inter_arr_async = msecs_to_jiffies(500);
+ bfqd->bfq_raising_max_softrt_rate = 7000;
+
+ /* Initially estimate the device's peak rate as the reference rate */
+ if (blk_queue_nonrot(bfqd->queue)) {
+ bfqd->RT_prod = R_nonrot * T_nonrot;
+ bfqd->peak_rate = R_nonrot;
+ } else {
+ bfqd->RT_prod = R_rot * T_rot;
+ bfqd->peak_rate = R_rot;
+ }
+
+ return bfqd;
+}
+
+static void bfq_slab_kill(void)
+{
+ if (bfq_pool != NULL)
+ kmem_cache_destroy(bfq_pool);
+ if (bfq_ioc_pool != NULL)
+ kmem_cache_destroy(bfq_ioc_pool);
+}
+
+static int __init bfq_slab_setup(void)
+{
+ bfq_pool = KMEM_CACHE(bfq_queue, 0);
+ if (bfq_pool == NULL)
+ goto fail;
+
+ bfq_ioc_pool = kmem_cache_create("bfq_io_context",
+ sizeof(struct cfq_io_context),
+ __alignof__(struct cfq_io_context),
+ 0, NULL);
+ if (bfq_ioc_pool == NULL)
+ goto fail;
+
+ return 0;
+fail:
+ bfq_slab_kill();
+ return -ENOMEM;
+}
+
+static ssize_t bfq_var_show(unsigned int var, char *page)
+{
+ return sprintf(page, "%d\n", var);
+}
+
+static ssize_t bfq_var_store(unsigned long *var, const char *page, size_t count)
+{
+ unsigned long new_val;
+ int ret = strict_strtoul(page, 10, &new_val);
+
+ if (ret == 0)
+ *var = new_val;
+
+ return count;
+}
+
+static ssize_t bfq_raising_max_time_show(struct elevator_queue *e, char *page)
+{
+ struct bfq_data *bfqd = e->elevator_data;
+ return sprintf(page, "%d\n", bfqd->bfq_raising_max_time > 0 ?
+ bfqd->bfq_raising_max_time :
+ bfq_wrais_duration(bfqd));
+}
+
+static ssize_t bfq_weights_show(struct elevator_queue *e, char *page)
+{
+ struct bfq_queue *bfqq;
+ struct bfq_data *bfqd = e->elevator_data;
+ ssize_t num_char = 0;
+
+ num_char += sprintf(page + num_char, "Active:\n");
+ list_for_each_entry(bfqq, &bfqd->active_list, bfqq_list) {
+ num_char += sprintf(page + num_char,
+ "pid%d: weight %hu, dur %d/%u\n",
+ bfqq->pid,
+ bfqq->entity.weight,
+ jiffies_to_msecs(jiffies -
+ bfqq->last_rais_start_finish),
+ jiffies_to_msecs(bfqq->raising_cur_max_time));
+ }
+ num_char += sprintf(page + num_char, "Idle:\n");
+ list_for_each_entry(bfqq, &bfqd->idle_list, bfqq_list) {
+ num_char += sprintf(page + num_char,
+ "pid%d: weight %hu, dur %d/%u\n",
+ bfqq->pid,
+ bfqq->entity.weight,
+ jiffies_to_msecs(jiffies -
+ bfqq->last_rais_start_finish),
+ jiffies_to_msecs(bfqq->raising_cur_max_time));
+ }
+ return num_char;
+}
+
+#define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \
+static ssize_t __FUNC(struct elevator_queue *e, char *page) \
+{ \
+ struct bfq_data *bfqd = e->elevator_data; \
+ unsigned int __data = __VAR; \
+ if (__CONV) \
+ __data = jiffies_to_msecs(__data); \
+ return bfq_var_show(__data, (page)); \
+}
+SHOW_FUNCTION(bfq_quantum_show, bfqd->bfq_quantum, 0);
+SHOW_FUNCTION(bfq_fifo_expire_sync_show, bfqd->bfq_fifo_expire[1], 1);
+SHOW_FUNCTION(bfq_fifo_expire_async_show, bfqd->bfq_fifo_expire[0], 1);
+SHOW_FUNCTION(bfq_back_seek_max_show, bfqd->bfq_back_max, 0);
+SHOW_FUNCTION(bfq_back_seek_penalty_show, bfqd->bfq_back_penalty, 0);
+SHOW_FUNCTION(bfq_slice_idle_show, bfqd->bfq_slice_idle, 1);
+SHOW_FUNCTION(bfq_max_budget_show, bfqd->bfq_user_max_budget, 0);
+SHOW_FUNCTION(bfq_max_budget_async_rq_show, bfqd->bfq_max_budget_async_rq, 0);
+SHOW_FUNCTION(bfq_timeout_sync_show, bfqd->bfq_timeout[BLK_RW_SYNC], 1);
+SHOW_FUNCTION(bfq_timeout_async_show, bfqd->bfq_timeout[BLK_RW_ASYNC], 1);
+SHOW_FUNCTION(bfq_low_latency_show, bfqd->low_latency, 0);
+SHOW_FUNCTION(bfq_raising_coeff_show, bfqd->bfq_raising_coeff, 0);
+SHOW_FUNCTION(bfq_raising_rt_max_time_show, bfqd->bfq_raising_rt_max_time, 1);
+SHOW_FUNCTION(bfq_raising_min_idle_time_show, bfqd->bfq_raising_min_idle_time,
+ 1);
+SHOW_FUNCTION(bfq_raising_min_inter_arr_async_show,
+ bfqd->bfq_raising_min_inter_arr_async,
+ 1);
+SHOW_FUNCTION(bfq_raising_max_softrt_rate_show,
+ bfqd->bfq_raising_max_softrt_rate, 0);
+#undef SHOW_FUNCTION
+
+#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \
+static ssize_t \
+__FUNC(struct elevator_queue *e, const char *page, size_t count) \
+{ \
+ struct bfq_data *bfqd = e->elevator_data; \
+ unsigned long __data; \
+ int ret = bfq_var_store(&__data, (page), count); \
+ if (__data < (MIN)) \
+ __data = (MIN); \
+ else if (__data > (MAX)) \
+ __data = (MAX); \
+ if (__CONV) \
+ *(__PTR) = msecs_to_jiffies(__data); \
+ else \
+ *(__PTR) = __data; \
+ return ret; \
+}
+STORE_FUNCTION(bfq_quantum_store, &bfqd->bfq_quantum, 1, INT_MAX, 0);
+STORE_FUNCTION(bfq_fifo_expire_sync_store, &bfqd->bfq_fifo_expire[1], 1,
+ INT_MAX, 1);
+STORE_FUNCTION(bfq_fifo_expire_async_store, &bfqd->bfq_fifo_expire[0], 1,
+ INT_MAX, 1);
+STORE_FUNCTION(bfq_back_seek_max_store, &bfqd->bfq_back_max, 0, INT_MAX, 0);
+STORE_FUNCTION(bfq_back_seek_penalty_store, &bfqd->bfq_back_penalty, 1,
+ INT_MAX, 0);
+STORE_FUNCTION(bfq_slice_idle_store, &bfqd->bfq_slice_idle, 0, INT_MAX, 1);
+STORE_FUNCTION(bfq_max_budget_async_rq_store, &bfqd->bfq_max_budget_async_rq,
+ 1, INT_MAX, 0);
+STORE_FUNCTION(bfq_timeout_async_store, &bfqd->bfq_timeout[BLK_RW_ASYNC], 0,
+ INT_MAX, 1);
+STORE_FUNCTION(bfq_raising_coeff_store, &bfqd->bfq_raising_coeff, 1,
+ INT_MAX, 0);
+STORE_FUNCTION(bfq_raising_max_time_store, &bfqd->bfq_raising_max_time, 0,
+ INT_MAX, 1);
+STORE_FUNCTION(bfq_raising_rt_max_time_store, &bfqd->bfq_raising_rt_max_time, 0,
+ INT_MAX, 1);
+STORE_FUNCTION(bfq_raising_min_idle_time_store,
+ &bfqd->bfq_raising_min_idle_time, 0, INT_MAX, 1);
+STORE_FUNCTION(bfq_raising_min_inter_arr_async_store,
+ &bfqd->bfq_raising_min_inter_arr_async, 0, INT_MAX, 1);
+STORE_FUNCTION(bfq_raising_max_softrt_rate_store,
+ &bfqd->bfq_raising_max_softrt_rate, 0, INT_MAX, 0);
+#undef STORE_FUNCTION
+
+/* do nothing for the moment */
+static ssize_t bfq_weights_store(struct elevator_queue *e,
+ const char *page, size_t count)
+{
+ return count;
+}
+
+static inline unsigned long bfq_estimated_max_budget(struct bfq_data *bfqd)
+{
+ u64 timeout = jiffies_to_msecs(bfqd->bfq_timeout[BLK_RW_SYNC]);
+
+ if (bfqd->peak_rate_samples >= BFQ_PEAK_RATE_SAMPLES)
+ return bfq_calc_max_budget(bfqd->peak_rate, timeout);
+ else
+ return bfq_default_max_budget;
+}
+
+static ssize_t bfq_max_budget_store(struct elevator_queue *e,
+ const char *page, size_t count)
+{
+ struct bfq_data *bfqd = e->elevator_data;
+ unsigned long __data;
+ int ret = bfq_var_store(&__data, (page), count);
+
+ if (__data == 0)
+ bfqd->bfq_max_budget = bfq_estimated_max_budget(bfqd);
+ else {
+ if (__data > INT_MAX)
+ __data = INT_MAX;
+ bfqd->bfq_max_budget = __data;
+ }
+
+ bfqd->bfq_user_max_budget = __data;
+
+ return ret;
+}
+
+static ssize_t bfq_timeout_sync_store(struct elevator_queue *e,
+ const char *page, size_t count)
+{
+ struct bfq_data *bfqd = e->elevator_data;
+ unsigned long __data;
+ int ret = bfq_var_store(&__data, (page), count);
+
+ if (__data < 1)
+ __data = 1;
+ else if (__data > INT_MAX)
+ __data = INT_MAX;
+
+ bfqd->bfq_timeout[BLK_RW_SYNC] = msecs_to_jiffies(__data);
+ if (bfqd->bfq_user_max_budget == 0)
+ bfqd->bfq_max_budget = bfq_estimated_max_budget(bfqd);
+
+ return ret;
+}
+
+static ssize_t bfq_low_latency_store(struct elevator_queue *e,
+ const char *page, size_t count)
+{
+ struct bfq_data *bfqd = e->elevator_data;
+ unsigned long __data;
+ int ret = bfq_var_store(&__data, (page), count);
+
+ if (__data > 1)
+ __data = 1;
+ bfqd->low_latency = __data;
+
+ return ret;
+}
+
+#define BFQ_ATTR(name) \
+ __ATTR(name, S_IRUGO|S_IWUSR, bfq_##name##_show, bfq_##name##_store)
+
+static struct elv_fs_entry bfq_attrs[] = {
+ BFQ_ATTR(quantum),
+ BFQ_ATTR(fifo_expire_sync),
+ BFQ_ATTR(fifo_expire_async),
+ BFQ_ATTR(back_seek_max),
+ BFQ_ATTR(back_seek_penalty),
+ BFQ_ATTR(slice_idle),
+ BFQ_ATTR(max_budget),
+ BFQ_ATTR(max_budget_async_rq),
+ BFQ_ATTR(timeout_sync),
+ BFQ_ATTR(timeout_async),
+ BFQ_ATTR(low_latency),
+ BFQ_ATTR(raising_coeff),
+ BFQ_ATTR(raising_max_time),
+ BFQ_ATTR(raising_rt_max_time),
+ BFQ_ATTR(raising_min_idle_time),
+ BFQ_ATTR(raising_min_inter_arr_async),
+ BFQ_ATTR(raising_max_softrt_rate),
+ BFQ_ATTR(weights),
+ __ATTR_NULL
+};
+
+static struct elevator_type iosched_bfq = {
+ .ops = {
+ .elevator_merge_fn = bfq_merge,
+ .elevator_merged_fn = bfq_merged_request,
+ .elevator_merge_req_fn = bfq_merged_requests,
+ .elevator_allow_merge_fn = bfq_allow_merge,
+ .elevator_dispatch_fn = bfq_dispatch_requests,
+ .elevator_add_req_fn = bfq_insert_request,
+ .elevator_activate_req_fn = bfq_activate_request,
+ .elevator_deactivate_req_fn = bfq_deactivate_request,
+ .elevator_completed_req_fn = bfq_completed_request,
+ .elevator_former_req_fn = elv_rb_former_request,
+ .elevator_latter_req_fn = elv_rb_latter_request,
+ .elevator_set_req_fn = bfq_set_request,
+ .elevator_put_req_fn = bfq_put_request,
+ .elevator_may_queue_fn = bfq_may_queue,
+ .elevator_init_fn = bfq_init_queue,
+ .elevator_exit_fn = bfq_exit_queue,
+ .trim = bfq_free_io_context,
+ },
+ .elevator_attrs = bfq_attrs,
+ .elevator_name = "bfq",
+ .elevator_owner = THIS_MODULE,
+};
+
+static int __init bfq_init(void)
+{
+ /*
+ * Can be 0 on HZ < 1000 setups.
+ */
+ if (bfq_slice_idle == 0)
+ bfq_slice_idle = 1;
+
+ if (bfq_timeout_async == 0)
+ bfq_timeout_async = 1;
+
+ if (bfq_slab_setup())
+ return -ENOMEM;
+
+ elv_register(&iosched_bfq);
+
+ return 0;
+}
+
+static void __exit bfq_exit(void)
+{
+ DECLARE_COMPLETION_ONSTACK(all_gone);
+ elv_unregister(&iosched_bfq);
+ bfq_ioc_gone = &all_gone;
+ /* bfq_ioc_gone's update must be visible before reading bfq_ioc_count */
+ smp_wmb();
+ if (elv_ioc_count_read(bfq_ioc_count) != 0)
+ wait_for_completion(&all_gone);
+ ida_destroy(&cic_index_ida);
+ bfq_slab_kill();
+}
+
+module_init(bfq_init);
+module_exit(bfq_exit);
+
+MODULE_AUTHOR("Fabio Checconi, Paolo Valente");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Budget Fair Queueing IO scheduler");
diff --git a/block/bfq-sched.c b/block/bfq-sched.c
new file mode 100644
index 0000000..fd50b7f
--- /dev/null
+++ b/block/bfq-sched.c
@@ -0,0 +1,1066 @@
+/*
+ * BFQ: Hierarchical B-WF2Q+ scheduler.
+ *
+ * Based on ideas and code from CFQ:
+ * Copyright (C) 2003 Jens Axboe <axboe@kernel.dk>
+ *
+ * Copyright (C) 2008 Fabio Checconi <fabio@gandalf.sssup.it>
+ * Paolo Valente <paolo.valente@unimore.it>
+ */
+
+#ifdef CONFIG_CGROUP_BFQIO
+#define for_each_entity(entity) \
+ for (; entity != NULL; entity = entity->parent)
+
+#define for_each_entity_safe(entity, parent) \
+ for (; entity && ({ parent = entity->parent; 1; }); entity = parent)
+
+static struct bfq_entity *bfq_lookup_next_entity(struct bfq_sched_data *sd,
+ int extract,
+ struct bfq_data *bfqd);
+
+static inline void bfq_update_budget(struct bfq_entity *next_active)
+{
+ struct bfq_entity *bfqg_entity;
+ struct bfq_group *bfqg;
+ struct bfq_sched_data *group_sd;
+
+ BUG_ON(next_active == NULL);
+
+ group_sd = next_active->sched_data;
+
+ bfqg = container_of(group_sd, struct bfq_group, sched_data);
+ /*
+ * bfq_group's my_entity field is not NULL only if the group
+ * is not the root group. We must not touch the root entity
+ * as it must never become an active entity.
+ */
+ bfqg_entity = bfqg->my_entity;
+ if (bfqg_entity != NULL)
+ bfqg_entity->budget = next_active->budget;
+}
+
+static int bfq_update_next_active(struct bfq_sched_data *sd)
+{
+ struct bfq_entity *next_active;
+
+ if (sd->active_entity != NULL)
+ /* will update/requeue at the end of service */
+ return 0;
+
+ /*
+ * NOTE: this can be improved in many ways, such as returning
+ * 1 (and thus propagating upwards the update) only when the
+ * budget changes, or caching the bfqq that will be scheduled
+ * next from this subtree. By now we worry more about
+ * correctness than about performance...
+ */
+ next_active = bfq_lookup_next_entity(sd, 0, NULL);
+ sd->next_active = next_active;
+
+ if (next_active != NULL)
+ bfq_update_budget(next_active);
+
+ return 1;
+}
+
+static inline void bfq_check_next_active(struct bfq_sched_data *sd,
+ struct bfq_entity *entity)
+{
+ BUG_ON(sd->next_active != entity);
+}
+#else
+#define for_each_entity(entity) \
+ for (; entity != NULL; entity = NULL)
+
+#define for_each_entity_safe(entity, parent) \
+ for (parent = NULL; entity != NULL; entity = parent)
+
+static inline int bfq_update_next_active(struct bfq_sched_data *sd)
+{
+ return 0;
+}
+
+static inline void bfq_check_next_active(struct bfq_sched_data *sd,
+ struct bfq_entity *entity)
+{
+}
+
+static inline void bfq_update_budget(struct bfq_entity *next_active)
+{
+}
+#endif
+
+/*
+ * Shift for timestamp calculations. This actually limits the maximum
+ * service allowed in one timestamp delta (small shift values increase it),
+ * the maximum total weight that can be used for the queues in the system
+ * (big shift values increase it), and the period of virtual time wraparounds.
+ */
+#define WFQ_SERVICE_SHIFT 22
+
+/**
+ * bfq_gt - compare two timestamps.
+ * @a: first ts.
+ * @b: second ts.
+ *
+ * Return @a > @b, dealing with wrapping correctly.
+ */
+static inline int bfq_gt(u64 a, u64 b)
+{
+ return (s64)(a - b) > 0;
+}
+
+static inline struct bfq_queue *bfq_entity_to_bfqq(struct bfq_entity *entity)
+{
+ struct bfq_queue *bfqq = NULL;
+
+ BUG_ON(entity == NULL);
+
+ if (entity->my_sched_data == NULL)
+ bfqq = container_of(entity, struct bfq_queue, entity);
+
+ return bfqq;
+}
+
+
+/**
+ * bfq_delta - map service into the virtual time domain.
+ * @service: amount of service.
+ * @weight: scale factor (weight of an entity or weight sum).
+ */
+static inline u64 bfq_delta(unsigned long service,
+ unsigned long weight)
+{
+ u64 d = (u64)service << WFQ_SERVICE_SHIFT;
+
+ do_div(d, weight);
+ return d;
+}
+
+/**
+ * bfq_calc_finish - assign the finish time to an entity.
+ * @entity: the entity to act upon.
+ * @service: the service to be charged to the entity.
+ */
+static inline void bfq_calc_finish(struct bfq_entity *entity,
+ unsigned long service)
+{
+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity);
+
+ BUG_ON(entity->weight == 0);
+
+ entity->finish = entity->start +
+ bfq_delta(service, entity->weight);
+
+ if (bfqq != NULL) {
+ bfq_log_bfqq(bfqq->bfqd, bfqq,
+ "calc_finish: serv %lu, w %d",
+ service, entity->weight);
+ bfq_log_bfqq(bfqq->bfqd, bfqq,
+ "calc_finish: start %llu, finish %llu, delta %llu",
+ entity->start, entity->finish,
+ bfq_delta(service, entity->weight));
+ }
+}
+
+/**
+ * bfq_entity_of - get an entity from a node.
+ * @node: the node field of the entity.
+ *
+ * Convert a node pointer to the relative entity. This is used only
+ * to simplify the logic of some functions and not as the generic
+ * conversion mechanism because, e.g., in the tree walking functions,
+ * the check for a %NULL value would be redundant.
+ */
+static inline struct bfq_entity *bfq_entity_of(struct rb_node *node)
+{
+ struct bfq_entity *entity = NULL;
+
+ if (node != NULL)
+ entity = rb_entry(node, struct bfq_entity, rb_node);
+
+ return entity;
+}
+
+/**
+ * bfq_extract - remove an entity from a tree.
+ * @root: the tree root.
+ * @entity: the entity to remove.
+ */
+static inline void bfq_extract(struct rb_root *root,
+ struct bfq_entity *entity)
+{
+ BUG_ON(entity->tree != root);
+
+ entity->tree = NULL;
+ rb_erase(&entity->rb_node, root);
+}
+
+/**
+ * bfq_idle_extract - extract an entity from the idle tree.
+ * @st: the service tree of the owning @entity.
+ * @entity: the entity being removed.
+ */
+static void bfq_idle_extract(struct bfq_service_tree *st,
+ struct bfq_entity *entity)
+{
+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity);
+ struct rb_node *next;
+
+ BUG_ON(entity->tree != &st->idle);
+
+ if (entity == st->first_idle) {
+ next = rb_next(&entity->rb_node);
+ st->first_idle = bfq_entity_of(next);
+ }
+
+ if (entity == st->last_idle) {
+ next = rb_prev(&entity->rb_node);
+ st->last_idle = bfq_entity_of(next);
+ }
+
+ bfq_extract(&st->idle, entity);
+
+ if (bfqq != NULL)
+ list_del(&bfqq->bfqq_list);
+}
+
+/**
+ * bfq_insert - generic tree insertion.
+ * @root: tree root.
+ * @entity: entity to insert.
+ *
+ * This is used for the idle and the active tree, since they are both
+ * ordered by finish time.
+ */
+static void bfq_insert(struct rb_root *root, struct bfq_entity *entity)
+{
+ struct bfq_entity *entry;
+ struct rb_node **node = &root->rb_node;
+ struct rb_node *parent = NULL;
+
+ BUG_ON(entity->tree != NULL);
+
+ while (*node != NULL) {
+ parent = *node;
+ entry = rb_entry(parent, struct bfq_entity, rb_node);
+
+ if (bfq_gt(entry->finish, entity->finish))
+ node = &parent->rb_left;
+ else
+ node = &parent->rb_right;
+ }
+
+ rb_link_node(&entity->rb_node, parent, node);
+ rb_insert_color(&entity->rb_node, root);
+
+ entity->tree = root;
+}
+
+/**
+ * bfq_update_min - update the min_start field of a entity.
+ * @entity: the entity to update.
+ * @node: one of its children.
+ *
+ * This function is called when @entity may store an invalid value for
+ * min_start due to updates to the active tree. The function assumes
+ * that the subtree rooted at @node (which may be its left or its right
+ * child) has a valid min_start value.
+ */
+static inline void bfq_update_min(struct bfq_entity *entity,
+ struct rb_node *node)
+{
+ struct bfq_entity *child;
+
+ if (node != NULL) {
+ child = rb_entry(node, struct bfq_entity, rb_node);
+ if (bfq_gt(entity->min_start, child->min_start))
+ entity->min_start = child->min_start;
+ }
+}
+
+/**
+ * bfq_update_active_node - recalculate min_start.
+ * @node: the node to update.
+ *
+ * @node may have changed position or one of its children may have moved,
+ * this function updates its min_start value. The left and right subtrees
+ * are assumed to hold a correct min_start value.
+ */
+static inline void bfq_update_active_node(struct rb_node *node)
+{
+ struct bfq_entity *entity = rb_entry(node, struct bfq_entity, rb_node);
+
+ entity->min_start = entity->start;
+ bfq_update_min(entity, node->rb_right);
+ bfq_update_min(entity, node->rb_left);
+}
+
+/**
+ * bfq_update_active_tree - update min_start for the whole active tree.
+ * @node: the starting node.
+ *
+ * @node must be the deepest modified node after an update. This function
+ * updates its min_start using the values held by its children, assuming
+ * that they did not change, and then updates all the nodes that may have
+ * changed in the path to the root. The only nodes that may have changed
+ * are the ones in the path or their siblings.
+ */
+static void bfq_update_active_tree(struct rb_node *node)
+{
+ struct rb_node *parent;
+
+up:
+ bfq_update_active_node(node);
+
+ parent = rb_parent(node);
+ if (parent == NULL)
+ return;
+
+ if (node == parent->rb_left && parent->rb_right != NULL)
+ bfq_update_active_node(parent->rb_right);
+ else if (parent->rb_left != NULL)
+ bfq_update_active_node(parent->rb_left);
+
+ node = parent;
+ goto up;
+}
+
+/**
+ * bfq_active_insert - insert an entity in the active tree of its group/device.
+ * @st: the service tree of the entity.
+ * @entity: the entity being inserted.
+ *
+ * The active tree is ordered by finish time, but an extra key is kept
+ * per each node, containing the minimum value for the start times of
+ * its children (and the node itself), so it's possible to search for
+ * the eligible node with the lowest finish time in logarithmic time.
+ */
+static void bfq_active_insert(struct bfq_service_tree *st,
+ struct bfq_entity *entity)
+{
+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity);
+ struct rb_node *node = &entity->rb_node;
+
+ bfq_insert(&st->active, entity);
+
+ if (node->rb_left != NULL)
+ node = node->rb_left;
+ else if (node->rb_right != NULL)
+ node = node->rb_right;
+
+ bfq_update_active_tree(node);
+
+ if (bfqq != NULL)
+ list_add(&bfqq->bfqq_list, &bfqq->bfqd->active_list);
+}
+
+/**
+ * bfq_ioprio_to_weight - calc a weight from an ioprio.
+ * @ioprio: the ioprio value to convert.
+ */
+static unsigned short bfq_ioprio_to_weight(int ioprio)
+{
+ WARN_ON(ioprio < 0 || ioprio >= IOPRIO_BE_NR);
+ return IOPRIO_BE_NR - ioprio;
+}
+
+/**
+ * bfq_weight_to_ioprio - calc an ioprio from a weight.
+ * @weight: the weight value to convert.
+ *
+ * To preserve as mush as possible the old only-ioprio user interface,
+ * 0 is used as an escape ioprio value for weights (numerically) equal or
+ * larger than IOPRIO_BE_NR
+ */
+static unsigned short bfq_weight_to_ioprio(int weight)
+{
+ WARN_ON(weight < BFQ_MIN_WEIGHT || weight > BFQ_MAX_WEIGHT);
+ return IOPRIO_BE_NR - weight < 0 ? 0 : IOPRIO_BE_NR - weight;
+}
+
+static inline void bfq_get_entity(struct bfq_entity *entity)
+{
+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity);
+
+ if (bfqq != NULL) {
+ atomic_inc(&bfqq->ref);
+ bfq_log_bfqq(bfqq->bfqd, bfqq, "get_entity: %p %d",
+ bfqq, atomic_read(&bfqq->ref));
+ }
+}
+
+/**
+ * bfq_find_deepest - find the deepest node that an extraction can modify.
+ * @node: the node being removed.
+ *
+ * Do the first step of an extraction in an rb tree, looking for the
+ * node that will replace @node, and returning the deepest node that
+ * the following modifications to the tree can touch. If @node is the
+ * last node in the tree return %NULL.
+ */
+static struct rb_node *bfq_find_deepest(struct rb_node *node)
+{
+ struct rb_node *deepest;
+
+ if (node->rb_right == NULL && node->rb_left == NULL)
+ deepest = rb_parent(node);
+ else if (node->rb_right == NULL)
+ deepest = node->rb_left;
+ else if (node->rb_left == NULL)
+ deepest = node->rb_right;
+ else {
+ deepest = rb_next(node);
+ if (deepest->rb_right != NULL)
+ deepest = deepest->rb_right;
+ else if (rb_parent(deepest) != node)
+ deepest = rb_parent(deepest);
+ }
+
+ return deepest;
+}
+
+/**
+ * bfq_active_extract - remove an entity from the active tree.
+ * @st: the service_tree containing the tree.
+ * @entity: the entity being removed.
+ */
+static void bfq_active_extract(struct bfq_service_tree *st,
+ struct bfq_entity *entity)
+{
+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity);
+ struct rb_node *node;
+
+ node = bfq_find_deepest(&entity->rb_node);
+ bfq_extract(&st->active, entity);
+
+ if (node != NULL)
+ bfq_update_active_tree(node);
+
+ if (bfqq != NULL)
+ list_del(&bfqq->bfqq_list);
+}
+
+/**
+ * bfq_idle_insert - insert an entity into the idle tree.
+ * @st: the service tree containing the tree.
+ * @entity: the entity to insert.
+ */
+static void bfq_idle_insert(struct bfq_service_tree *st,
+ struct bfq_entity *entity)
+{
+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity);
+ struct bfq_entity *first_idle = st->first_idle;
+ struct bfq_entity *last_idle = st->last_idle;
+
+ if (first_idle == NULL || bfq_gt(first_idle->finish, entity->finish))
+ st->first_idle = entity;
+ if (last_idle == NULL || bfq_gt(entity->finish, last_idle->finish))
+ st->last_idle = entity;
+
+ bfq_insert(&st->idle, entity);
+
+ if (bfqq != NULL)
+ list_add(&bfqq->bfqq_list, &bfqq->bfqd->idle_list);
+}
+
+/**
+ * bfq_forget_entity - remove an entity from the wfq trees.
+ * @st: the service tree.
+ * @entity: the entity being removed.
+ *
+ * Update the device status and forget everything about @entity, putting
+ * the device reference to it, if it is a queue. Entities belonging to
+ * groups are not refcounted.
+ */
+static void bfq_forget_entity(struct bfq_service_tree *st,
+ struct bfq_entity *entity)
+{
+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity);
+
+ BUG_ON(!entity->on_st);
+
+ entity->on_st = 0;
+ st->wsum -= entity->weight;
+ if (bfqq != NULL) {
+ bfq_log_bfqq(bfqq->bfqd, bfqq, "forget_entity: %p %d",
+ bfqq, atomic_read(&bfqq->ref));
+ bfq_put_queue(bfqq);
+ }
+}
+
+/**
+ * bfq_put_idle_entity - release the idle tree ref of an entity.
+ * @st: service tree for the entity.
+ * @entity: the entity being released.
+ */
+static void bfq_put_idle_entity(struct bfq_service_tree *st,
+ struct bfq_entity *entity)
+{
+ bfq_idle_extract(st, entity);
+ bfq_forget_entity(st, entity);
+}
+
+/**
+ * bfq_forget_idle - update the idle tree if necessary.
+ * @st: the service tree to act upon.
+ *
+ * To preserve the global O(log N) complexity we only remove one entry here;
+ * as the idle tree will not grow indefinitely this can be done safely.
+ */
+static void bfq_forget_idle(struct bfq_service_tree *st)
+{
+ struct bfq_entity *first_idle = st->first_idle;
+ struct bfq_entity *last_idle = st->last_idle;
+
+ if (RB_EMPTY_ROOT(&st->active) && last_idle != NULL &&
+ !bfq_gt(last_idle->finish, st->vtime)) {
+ /*
+ * Forget the whole idle tree, increasing the vtime past
+ * the last finish time of idle entities.
+ */
+ st->vtime = last_idle->finish;
+ }
+
+ if (first_idle != NULL && !bfq_gt(first_idle->finish, st->vtime))
+ bfq_put_idle_entity(st, first_idle);
+}
+
+static struct bfq_service_tree *
+__bfq_entity_update_weight_prio(struct bfq_service_tree *old_st,
+ struct bfq_entity *entity)
+{
+ struct bfq_service_tree *new_st = old_st;
+
+ if (entity->ioprio_changed) {
+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity);
+
+ BUG_ON(old_st->wsum < entity->weight);
+ old_st->wsum -= entity->weight;
+
+ if (entity->new_weight != entity->orig_weight) {
+ entity->orig_weight = entity->new_weight;
+ entity->ioprio =
+ bfq_weight_to_ioprio(entity->orig_weight);
+ } else if (entity->new_ioprio != entity->ioprio) {
+ entity->ioprio = entity->new_ioprio;
+ entity->orig_weight =
+ bfq_ioprio_to_weight(entity->ioprio);
+ } else
+ entity->new_weight = entity->orig_weight =
+ bfq_ioprio_to_weight(entity->ioprio);
+
+ entity->ioprio_class = entity->new_ioprio_class;
+ entity->ioprio_changed = 0;
+
+ /*
+ * NOTE: here we may be changing the weight too early,
+ * this will cause unfairness. The correct approach
+ * would have required additional complexity to defer
+ * weight changes to the proper time instants (i.e.,
+ * when entity->finish <= old_st->vtime).
+ */
+ new_st = bfq_entity_service_tree(entity);
+ entity->weight = entity->orig_weight *
+ (bfqq != NULL ? bfqq->raising_coeff : 1);
+ new_st->wsum += entity->weight;
+
+ if (new_st != old_st)
+ entity->start = new_st->vtime;
+ }
+
+ return new_st;
+}
+
+/**
+ * bfq_bfqq_served - update the scheduler status after selection for service.
+ * @bfqq: the queue being served.
+ * @served: bytes to transfer.
+ *
+ * NOTE: this can be optimized, as the timestamps of upper level entities
+ * are synchronized every time a new bfqq is selected for service. By now,
+ * we keep it to better check consistency.
+ */
+static void bfq_bfqq_served(struct bfq_queue *bfqq, unsigned long served)
+{
+ struct bfq_entity *entity = &bfqq->entity;
+ struct bfq_service_tree *st;
+
+ for_each_entity(entity) {
+ st = bfq_entity_service_tree(entity);
+
+ entity->service += served;
+ BUG_ON(entity->service > entity->budget);
+ BUG_ON(st->wsum == 0);
+
+ st->vtime += bfq_delta(served, st->wsum);
+ bfq_forget_idle(st);
+ }
+ bfq_log_bfqq(bfqq->bfqd, bfqq, "bfqq_served %lu secs", served);
+}
+
+/**
+ * bfq_bfqq_charge_full_budget - set the service to the entity budget.
+ * @bfqq: the queue that needs a service update.
+ *
+ * When it's not possible to be fair in the service domain, because
+ * a queue is not consuming its budget fast enough (the meaning of
+ * fast depends on the timeout parameter), we charge it a full
+ * budget. In this way we should obtain a sort of time-domain
+ * fairness among all the seeky/slow queues.
+ */
+static inline void bfq_bfqq_charge_full_budget(struct bfq_queue *bfqq)
+{
+ struct bfq_entity *entity = &bfqq->entity;
+
+ bfq_log_bfqq(bfqq->bfqd, bfqq, "charge_full_budget");
+
+ bfq_bfqq_served(bfqq, entity->budget - entity->service);
+}
+
+/**
+ * __bfq_activate_entity - activate an entity.
+ * @entity: the entity being activated.
+ *
+ * Called whenever an entity is activated, i.e., it is not active and one
+ * of its children receives a new request, or has to be reactivated due to
+ * budget exhaustion. It uses the current budget of the entity (and the
+ * service received if @entity is active) of the queue to calculate its
+ * timestamps.
+ */
+static void __bfq_activate_entity(struct bfq_entity *entity)
+{
+ struct bfq_sched_data *sd = entity->sched_data;
+ struct bfq_service_tree *st = bfq_entity_service_tree(entity);
+
+ if (entity == sd->active_entity) {
+ BUG_ON(entity->tree != NULL);
+ /*
+ * If we are requeueing the current entity we have
+ * to take care of not charging to it service it has
+ * not received.
+ */
+ bfq_calc_finish(entity, entity->service);
+ entity->start = entity->finish;
+ sd->active_entity = NULL;
+ } else if (entity->tree == &st->active) {
+ /*
+ * Requeueing an entity due to a change of some
+ * next_active entity below it. We reuse the old
+ * start time.
+ */
+ bfq_active_extract(st, entity);
+ } else if (entity->tree == &st->idle) {
+ /*
+ * Must be on the idle tree, bfq_idle_extract() will
+ * check for that.
+ */
+ bfq_idle_extract(st, entity);
+ entity->start = bfq_gt(st->vtime, entity->finish) ?
+ st->vtime : entity->finish;
+ } else {
+ /*
+ * The finish time of the entity may be invalid, and
+ * it is in the past for sure, otherwise the queue
+ * would have been on the idle tree.
+ */
+ entity->start = st->vtime;
+ st->wsum += entity->weight;
+ bfq_get_entity(entity);
+
+ BUG_ON(entity->on_st);
+ entity->on_st = 1;
+ }
+
+ st = __bfq_entity_update_weight_prio(st, entity);
+ bfq_calc_finish(entity, entity->budget);
+ bfq_active_insert(st, entity);
+}
+
+/**
+ * bfq_activate_entity - activate an entity and its ancestors if necessary.
+ * @entity: the entity to activate.
+ *
+ * Activate @entity and all the entities on the path from it to the root.
+ */
+static void bfq_activate_entity(struct bfq_entity *entity)
+{
+ struct bfq_sched_data *sd;
+
+ for_each_entity(entity) {
+ __bfq_activate_entity(entity);
+
+ sd = entity->sched_data;
+ if (!bfq_update_next_active(sd))
+ /*
+ * No need to propagate the activation to the
+ * upper entities, as they will be updated when
+ * the active entity is rescheduled.
+ */
+ break;
+ }
+}
+
+/**
+ * __bfq_deactivate_entity - deactivate an entity from its service tree.
+ * @entity: the entity to deactivate.
+ * @requeue: if false, the entity will not be put into the idle tree.
+ *
+ * Deactivate an entity, independently from its previous state. If the
+ * entity was not on a service tree just return, otherwise if it is on
+ * any scheduler tree, extract it from that tree, and if necessary
+ * and if the caller did not specify @requeue, put it on the idle tree.
+ *
+ * Return %1 if the caller should update the entity hierarchy, i.e.,
+ * if the entity was under service or if it was the next_active for
+ * its sched_data; return %0 otherwise.
+ */
+static int __bfq_deactivate_entity(struct bfq_entity *entity, int requeue)
+{
+ struct bfq_sched_data *sd = entity->sched_data;
+ struct bfq_service_tree *st = bfq_entity_service_tree(entity);
+ int was_active = entity == sd->active_entity;
+ int ret = 0;
+
+ if (!entity->on_st)
+ return 0;
+
+ BUG_ON(was_active && entity->tree != NULL);
+
+ if (was_active) {
+ bfq_calc_finish(entity, entity->service);
+ sd->active_entity = NULL;
+ } else if (entity->tree == &st->active)
+ bfq_active_extract(st, entity);
+ else if (entity->tree == &st->idle)
+ bfq_idle_extract(st, entity);
+ else if (entity->tree != NULL)
+ BUG();
+
+ if (was_active || sd->next_active == entity)
+ ret = bfq_update_next_active(sd);
+
+ if (!requeue || !bfq_gt(entity->finish, st->vtime))
+ bfq_forget_entity(st, entity);
+ else
+ bfq_idle_insert(st, entity);
+
+ BUG_ON(sd->active_entity == entity);
+ BUG_ON(sd->next_active == entity);
+
+ return ret;
+}
+
+/**
+ * bfq_deactivate_entity - deactivate an entity.
+ * @entity: the entity to deactivate.
+ * @requeue: true if the entity can be put on the idle tree
+ */
+static void bfq_deactivate_entity(struct bfq_entity *entity, int requeue)
+{
+ struct bfq_sched_data *sd;
+ struct bfq_entity *parent;
+
+ for_each_entity_safe(entity, parent) {
+ sd = entity->sched_data;
+
+ if (!__bfq_deactivate_entity(entity, requeue))
+ /*
+ * The parent entity is still backlogged, and
+ * we don't need to update it as it is still
+ * under service.
+ */
+ break;
+
+ if (sd->next_active != NULL)
+ /*
+ * The parent entity is still backlogged and
+ * the budgets on the path towards the root
+ * need to be updated.
+ */
+ goto update;
+
+ /*
+ * If we reach there the parent is no more backlogged and
+ * we want to propagate the dequeue upwards.
+ */
+ requeue = 1;
+ }
+
+ return;
+
+update:
+ entity = parent;
+ for_each_entity(entity) {
+ __bfq_activate_entity(entity);
+
+ sd = entity->sched_data;
+ if (!bfq_update_next_active(sd))
+ break;
+ }
+}
+
+/**
+ * bfq_update_vtime - update vtime if necessary.
+ * @st: the service tree to act upon.
+ *
+ * If necessary update the service tree vtime to have at least one
+ * eligible entity, skipping to its start time. Assumes that the
+ * active tree of the device is not empty.
+ *
+ * NOTE: this hierarchical implementation updates vtimes quite often,
+ * we may end up with reactivated tasks getting timestamps after a
+ * vtime skip done because we needed a ->first_active entity on some
+ * intermediate node.
+ */
+static void bfq_update_vtime(struct bfq_service_tree *st)
+{
+ struct bfq_entity *entry;
+ struct rb_node *node = st->active.rb_node;
+
+ entry = rb_entry(node, struct bfq_entity, rb_node);
+ if (bfq_gt(entry->min_start, st->vtime)) {
+ st->vtime = entry->min_start;
+ bfq_forget_idle(st);
+ }
+}
+
+/**
+ * bfq_first_active - find the eligible entity with the smallest finish time
+ * @st: the service tree to select from.
+ *
+ * This function searches the first schedulable entity, starting from the
+ * root of the tree and going on the left every time on this side there is
+ * a subtree with at least one eligible (start >= vtime) entity. The path
+ * on the right is followed only if a) the left subtree contains no eligible
+ * entities and b) no eligible entity has been found yet.
+ */
+static struct bfq_entity *bfq_first_active_entity(struct bfq_service_tree *st)
+{
+ struct bfq_entity *entry, *first = NULL;
+ struct rb_node *node = st->active.rb_node;
+
+ while (node != NULL) {
+ entry = rb_entry(node, struct bfq_entity, rb_node);
+left:
+ if (!bfq_gt(entry->start, st->vtime))
+ first = entry;
+
+ BUG_ON(bfq_gt(entry->min_start, st->vtime));
+
+ if (node->rb_left != NULL) {
+ entry = rb_entry(node->rb_left,
+ struct bfq_entity, rb_node);
+ if (!bfq_gt(entry->min_start, st->vtime)) {
+ node = node->rb_left;
+ goto left;
+ }
+ }
+ if (first != NULL)
+ break;
+ node = node->rb_right;
+ }
+
+ BUG_ON(first == NULL && !RB_EMPTY_ROOT(&st->active));
+ return first;
+}
+
+/**
+ * __bfq_lookup_next_entity - return the first eligible entity in @st.
+ * @st: the service tree.
+ *
+ * Update the virtual time in @st and return the first eligible entity
+ * it contains.
+ */
+static struct bfq_entity *__bfq_lookup_next_entity(struct bfq_service_tree *st,
+ bool force)
+{
+ struct bfq_entity *entity, *new_next_active = NULL;
+
+ if (RB_EMPTY_ROOT(&st->active))
+ return NULL;
+
+ bfq_update_vtime(st);
+ entity = bfq_first_active_entity(st);
+ BUG_ON(bfq_gt(entity->start, st->vtime));
+
+ /*
+ * If the chosen entity does not match with the sched_data's
+ * next_active and we are forcedly serving the IDLE priority
+ * class tree, bubble up budget update.
+ */
+ if (unlikely(force && entity != entity->sched_data->next_active)) {
+ new_next_active = entity;
+ for_each_entity(new_next_active)
+ bfq_update_budget(new_next_active);
+ }
+
+ return entity;
+}
+
+/**
+ * bfq_lookup_next_entity - return the first eligible entity in @sd.
+ * @sd: the sched_data.
+ * @extract: if true the returned entity will be also extracted from @sd.
+ *
+ * NOTE: since we cache the next_active entity at each level of the
+ * hierarchy, the complexity of the lookup can be decreased with
+ * absolutely no effort just returning the cached next_active value;
+ * we prefer to do full lookups to test the consistency of * the data
+ * structures.
+ */
+static struct bfq_entity *bfq_lookup_next_entity(struct bfq_sched_data *sd,
+ int extract,
+ struct bfq_data *bfqd)
+{
+ struct bfq_service_tree *st = sd->service_tree;
+ struct bfq_entity *entity;
+ int i=0;
+
+ BUG_ON(sd->active_entity != NULL);
+
+ if (bfqd != NULL &&
+ jiffies - bfqd->bfq_class_idle_last_service > BFQ_CL_IDLE_TIMEOUT) {
+ entity = __bfq_lookup_next_entity(st + BFQ_IOPRIO_CLASSES - 1, true);
+ if (entity != NULL) {
+ i = BFQ_IOPRIO_CLASSES - 1;
+ bfqd->bfq_class_idle_last_service = jiffies;
+ sd->next_active = entity;
+ }
+ }
+ for (; i < BFQ_IOPRIO_CLASSES; i++) {
+ entity = __bfq_lookup_next_entity(st + i, false);
+ if (entity != NULL) {
+ if (extract) {
+ bfq_check_next_active(sd, entity);
+ bfq_active_extract(st + i, entity);
+ sd->active_entity = entity;
+ sd->next_active = NULL;
+ }
+ break;
+ }
+ }
+
+ return entity;
+}
+
+/*
+ * Get next queue for service.
+ */
+static struct bfq_queue *bfq_get_next_queue(struct bfq_data *bfqd)
+{
+ struct bfq_entity *entity = NULL;
+ struct bfq_sched_data *sd;
+ struct bfq_queue *bfqq;
+
+ BUG_ON(bfqd->active_queue != NULL);
+
+ if (bfqd->busy_queues == 0)
+ return NULL;
+
+ sd = &bfqd->root_group->sched_data;
+ for (; sd != NULL; sd = entity->my_sched_data) {
+ entity = bfq_lookup_next_entity(sd, 1, bfqd);
+ BUG_ON(entity == NULL);
+ entity->service = 0;
+ }
+
+ bfqq = bfq_entity_to_bfqq(entity);
+ BUG_ON(bfqq == NULL);
+
+ return bfqq;
+}
+
+/*
+ * Forced extraction of the given queue.
+ */
+static void bfq_get_next_queue_forced(struct bfq_data *bfqd,
+ struct bfq_queue *bfqq)
+{
+ struct bfq_entity *entity;
+ struct bfq_sched_data *sd;
+
+ BUG_ON(bfqd->active_queue != NULL);
+
+ entity = &bfqq->entity;
+ /*
+ * Bubble up extraction/update from the leaf to the root.
+ */
+ for_each_entity(entity) {
+ sd = entity->sched_data;
+ bfq_update_budget(entity);
+ bfq_update_vtime(bfq_entity_service_tree(entity));
+ bfq_active_extract(bfq_entity_service_tree(entity), entity);
+ sd->active_entity = entity;
+ sd->next_active = NULL;
+ entity->service = 0;
+ }
+
+ return;
+}
+
+static void __bfq_bfqd_reset_active(struct bfq_data *bfqd)
+{
+ if (bfqd->active_cic != NULL) {
+ put_io_context(bfqd->active_cic->ioc);
+ bfqd->active_cic = NULL;
+ }
+
+ bfqd->active_queue = NULL;
+ del_timer(&bfqd->idle_slice_timer);
+}
+
+static void bfq_deactivate_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq,
+ int requeue)
+{
+ struct bfq_entity *entity = &bfqq->entity;
+
+ if (bfqq == bfqd->active_queue)
+ __bfq_bfqd_reset_active(bfqd);
+
+ bfq_deactivate_entity(entity, requeue);
+}
+
+static void bfq_activate_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq)
+{
+ struct bfq_entity *entity = &bfqq->entity;
+
+ bfq_activate_entity(entity);
+}
+
+/*
+ * Called when the bfqq no longer has requests pending, remove it from
+ * the service tree.
+ */
+static void bfq_del_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq,
+ int requeue)
+{
+ BUG_ON(!bfq_bfqq_busy(bfqq));
+ BUG_ON(!RB_EMPTY_ROOT(&bfqq->sort_list));
+
+ bfq_log_bfqq(bfqd, bfqq, "del from busy");
+
+ bfq_clear_bfqq_busy(bfqq);
+
+ BUG_ON(bfqd->busy_queues == 0);
+ bfqd->busy_queues--;
+
+ bfq_deactivate_bfqq(bfqd, bfqq, requeue);
+}
+
+/*
+ * Called when an inactive queue receives a new request.
+ */
+static void bfq_add_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq)
+{
+ BUG_ON(bfq_bfqq_busy(bfqq));
+ BUG_ON(bfqq == bfqd->active_queue);
+
+ bfq_log_bfqq(bfqd, bfqq, "add to busy");
+
+ bfq_activate_bfqq(bfqd, bfqq);
+
+ bfq_mark_bfqq_busy(bfqq);
+ bfqd->busy_queues++;
+}
diff --git a/block/bfq.h b/block/bfq.h
new file mode 100644
index 0000000..e2ce505
--- /dev/null
+++ b/block/bfq.h
@@ -0,0 +1,595 @@
+/*
+ * BFQ-v5 for 3.0: data structures and common functions prototypes.
+ *
+ * Based on ideas and code from CFQ:
+ * Copyright (C) 2003 Jens Axboe <axboe@kernel.dk>
+ *
+ * Copyright (C) 2008 Fabio Checconi <fabio@gandalf.sssup.it>
+ * Paolo Valente <paolo.valente@unimore.it>
+ */
+
+#ifndef _BFQ_H
+#define _BFQ_H
+
+#include <linux/blktrace_api.h>
+#include <linux/hrtimer.h>
+#include <linux/ioprio.h>
+#include <linux/rbtree.h>
+
+#define BFQ_IOPRIO_CLASSES 3
+#define BFQ_CL_IDLE_TIMEOUT HZ/5
+
+#define BFQ_MIN_WEIGHT 1
+#define BFQ_MAX_WEIGHT 1000
+
+#define BFQ_DEFAULT_GRP_WEIGHT 10
+#define BFQ_DEFAULT_GRP_IOPRIO 0
+#define BFQ_DEFAULT_GRP_CLASS IOPRIO_CLASS_BE
+
+struct bfq_entity;
+
+/**
+ * struct bfq_service_tree - per ioprio_class service tree.
+ * @active: tree for active entities (i.e., those backlogged).
+ * @idle: tree for idle entities (i.e., those not backlogged, with V <= F_i).
+ * @first_idle: idle entity with minimum F_i.
+ * @last_idle: idle entity with maximum F_i.
+ * @vtime: scheduler virtual time.
+ * @wsum: scheduler weight sum; active and idle entities contribute to it.
+ *
+ * Each service tree represents a B-WF2Q+ scheduler on its own. Each
+ * ioprio_class has its own independent scheduler, and so its own
+ * bfq_service_tree. All the fields are protected by the queue lock
+ * of the containing bfqd.
+ */
+struct bfq_service_tree {
+ struct rb_root active;
+ struct rb_root idle;
+
+ struct bfq_entity *first_idle;
+ struct bfq_entity *last_idle;
+
+ u64 vtime;
+ unsigned long wsum;
+};
+
+/**
+ * struct bfq_sched_data - multi-class scheduler.
+ * @active_entity: entity under service.
+ * @next_active: head-of-the-line entity in the scheduler.
+ * @service_tree: array of service trees, one per ioprio_class.
+ *
+ * bfq_sched_data is the basic scheduler queue. It supports three
+ * ioprio_classes, and can be used either as a toplevel queue or as
+ * an intermediate queue on a hierarchical setup.
+ * @next_active points to the active entity of the sched_data service
+ * trees that will be scheduled next.
+ *
+ * The supported ioprio_classes are the same as in CFQ, in descending
+ * priority order, IOPRIO_CLASS_RT, IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE.
+ * Requests from higher priority queues are served before all the
+ * requests from lower priority queues; among requests of the same
+ * queue requests are served according to B-WF2Q+.
+ * All the fields are protected by the queue lock of the containing bfqd.
+ */
+struct bfq_sched_data {
+ struct bfq_entity *active_entity;
+ struct bfq_entity *next_active;
+ struct bfq_service_tree service_tree[BFQ_IOPRIO_CLASSES];
+};
+
+/**
+ * struct bfq_entity - schedulable entity.
+ * @rb_node: service_tree member.
+ * @on_st: flag, true if the entity is on a tree (either the active or
+ * the idle one of its service_tree).
+ * @finish: B-WF2Q+ finish timestamp (aka F_i).
+ * @start: B-WF2Q+ start timestamp (aka S_i).
+ * @tree: tree the entity is enqueued into; %NULL if not on a tree.
+ * @min_start: minimum start time of the (active) subtree rooted at
+ * this entity; used for O(log N) lookups into active trees.
+ * @service: service received during the last round of service.
+ * @budget: budget used to calculate F_i; F_i = S_i + @budget / @weight.
+ * @weight: weight of the queue
+ * @parent: parent entity, for hierarchical scheduling.
+ * @my_sched_data: for non-leaf nodes in the cgroup hierarchy, the
+ * associated scheduler queue, %NULL on leaf nodes.
+ * @sched_data: the scheduler queue this entity belongs to.
+ * @ioprio: the ioprio in use.
+ * @new_weight: when a weight change is requested, the new weight value.
+ * @orig_weight: original weight, used to implement weight boosting
+ * @new_ioprio: when an ioprio change is requested, the new ioprio value.
+ * @ioprio_class: the ioprio_class in use.
+ * @new_ioprio_class: when an ioprio_class change is requested, the new
+ * ioprio_class value.
+ * @ioprio_changed: flag, true when the user requested a weight, ioprio or
+ * ioprio_class change.
+ *
+ * A bfq_entity is used to represent either a bfq_queue (leaf node in the
+ * cgroup hierarchy) or a bfq_group into the upper level scheduler. Each
+ * entity belongs to the sched_data of the parent group in the cgroup
+ * hierarchy. Non-leaf entities have also their own sched_data, stored
+ * in @my_sched_data.
+ *
+ * Each entity stores independently its priority values; this would
+ * allow different weights on different devices, but this
+ * functionality is not exported to userspace by now. Priorities and
+ * weights are updated lazily, first storing the new values into the
+ * new_* fields, then setting the @ioprio_changed flag. As soon as
+ * there is a transition in the entity state that allows the priority
+ * update to take place the effective and the requested priority
+ * values are synchronized.
+ *
+ * Unless cgroups are used, the weight value is calculated from the
+ * ioprio to export the same interface as CFQ. When dealing with
+ * ``well-behaved'' queues (i.e., queues that do not spend too much
+ * time to consume their budget and have true sequential behavior, and
+ * when there are no external factors breaking anticipation) the
+ * relative weights at each level of the cgroups hierarchy should be
+ * guaranteed. All the fields are protected by the queue lock of the
+ * containing bfqd.
+ */
+struct bfq_entity {
+ struct rb_node rb_node;
+
+ int on_st;
+
+ u64 finish;
+ u64 start;
+
+ struct rb_root *tree;
+
+ u64 min_start;
+
+ unsigned long service, budget;
+ unsigned short weight, new_weight;
+ unsigned short orig_weight;
+
+ struct bfq_entity *parent;
+
+ struct bfq_sched_data *my_sched_data;
+ struct bfq_sched_data *sched_data;
+
+ unsigned short ioprio, new_ioprio;
+ unsigned short ioprio_class, new_ioprio_class;
+
+ int ioprio_changed;
+};
+
+struct bfq_group;
+
+/**
+ * struct bfq_queue - leaf schedulable entity.
+ * @ref: reference counter.
+ * @bfqd: parent bfq_data.
+ * @new_bfqq: shared bfq_queue if queue is cooperating with
+ * one or more other queues.
+ * @pos_node: request-position tree member (see bfq_data's @rq_pos_tree).
+ * @pos_root: request-position tree root (see bfq_data's @rq_pos_tree).
+ * @sort_list: sorted list of pending requests.
+ * @next_rq: if fifo isn't expired, next request to serve.
+ * @queued: nr of requests queued in @sort_list.
+ * @allocated: currently allocated requests.
+ * @meta_pending: pending metadata requests.
+ * @fifo: fifo list of requests in sort_list.
+ * @entity: entity representing this queue in the scheduler.
+ * @max_budget: maximum budget allowed from the feedback mechanism.
+ * @budget_timeout: budget expiration (in jiffies).
+ * @dispatched: number of requests on the dispatch list or inside driver.
+ * @org_ioprio: saved ioprio during boosted periods.
+ * @org_ioprio_class: saved ioprio_class during boosted periods.
+ * @flags: status flags.
+ * @bfqq_list: node for active/idle bfqq list inside our bfqd.
+ * @seek_samples: number of seeks sampled
+ * @seek_total: sum of the distances of the seeks sampled
+ * @seek_mean: mean seek distance
+ * @last_request_pos: position of the last request enqueued
+ * @pid: pid of the process owning the queue, used for logging purposes.
+ * @last_rais_start_time: last (idle -> weight-raised) transition attempt
+ * @raising_cur_max_time: current max raising time for this queue
+ *
+ * A bfq_queue is a leaf request queue; it can be associated to an io_context
+ * or more (if it is an async one). @cgroup holds a reference to the
+ * cgroup, to be sure that it does not disappear while a bfqq still
+ * references it (mostly to avoid races between request issuing and task
+ * migration followed by cgroup distruction).
+ * All the fields are protected by the queue lock of the containing bfqd.
+ */
+struct bfq_queue {
+ atomic_t ref;
+ struct bfq_data *bfqd;
+
+ /* fields for cooperating queues handling */
+ struct bfq_queue *new_bfqq;
+ struct rb_node pos_node;
+ struct rb_root *pos_root;
+
+ struct rb_root sort_list;
+ struct request *next_rq;
+ int queued[2];
+ int allocated[2];
+ int meta_pending;
+ struct list_head fifo;
+
+ struct bfq_entity entity;
+
+ unsigned long max_budget;
+ unsigned long budget_timeout;
+
+ int dispatched;
+
+ unsigned short org_ioprio;
+ unsigned short org_ioprio_class;
+
+ unsigned int flags;
+
+ struct list_head bfqq_list;
+
+ unsigned int seek_samples;
+ u64 seek_total;
+ sector_t seek_mean;
+ sector_t last_request_pos;
+
+ pid_t pid;
+
+ /* weight-raising fields */
+ unsigned int raising_cur_max_time;
+ u64 last_rais_start_finish, soft_rt_next_start;
+ unsigned int raising_coeff;
+};
+
+/**
+ * struct bfq_data - per device data structure.
+ * @queue: request queue for the managed device.
+ * @root_group: root bfq_group for the device.
+ * @rq_pos_tree: rbtree sorted by next_request position,
+ * used when determining if two or more queues
+ * have interleaving requests (see bfq_close_cooperator).
+ * @busy_queues: number of bfq_queues containing requests (including the
+ * queue under service, even if it is idling).
+ * @queued: number of queued requests.
+ * @rq_in_driver: number of requests dispatched and waiting for completion.
+ * @sync_flight: number of sync requests in the driver.
+ * @max_rq_in_driver: max number of reqs in driver in the last @hw_tag_samples
+ * completed requests .
+ * @hw_tag_samples: nr of samples used to calculate hw_tag.
+ * @hw_tag: flag set to one if the driver is showing a queueing behavior.
+ * @budgets_assigned: number of budgets assigned.
+ * @idle_slice_timer: timer set when idling for the next sequential request
+ * from the queue under service.
+ * @unplug_work: delayed work to restart dispatching on the request queue.
+ * @active_queue: bfq_queue under service.
+ * @active_cic: cfq_io_context (cic) associated with the @active_queue.
+ * @last_position: on-disk position of the last served request.
+ * @last_budget_start: beginning of the last budget.
+ * @last_idling_start: beginning of the last idle slice.
+ * @peak_rate: peak transfer rate observed for a budget.
+ * @peak_rate_samples: number of samples used to calculate @peak_rate.
+ * @bfq_max_budget: maximum budget allotted to a bfq_queue before rescheduling.
+ * @cic_index: use small consequent indexes as radix tree keys to reduce depth
+ * @cic_list: list of all the cics active on the bfq_data device.
+ * @group_list: list of all the bfq_groups active on the device.
+ * @active_list: list of all the bfq_queues active on the device.
+ * @idle_list: list of all the bfq_queues idle on the device.
+ * @bfq_quantum: max number of requests dispatched per dispatch round.
+ * @bfq_fifo_expire: timeout for async/sync requests; when it expires
+ * requests are served in fifo order.
+ * @bfq_back_penalty: weight of backward seeks wrt forward ones.
+ * @bfq_back_max: maximum allowed backward seek.
+ * @bfq_slice_idle: maximum idling time.
+ * @bfq_user_max_budget: user-configured max budget value (0 for auto-tuning).
+ * @bfq_max_budget_async_rq: maximum budget (in nr of requests) allotted to
+ * async queues.
+ * @bfq_timeout: timeout for bfq_queues to consume their budget; used to
+ * to prevent seeky queues to impose long latencies to well
+ * behaved ones (this also implies that seeky queues cannot
+ * receive guarantees in the service domain; after a timeout
+ * they are charged for the whole allocated budget, to try
+ * to preserve a behavior reasonably fair among them, but
+ * without service-domain guarantees).
+ * @bfq_raising_coeff: Maximum factor by which the weight of a boosted
+ * queue is multiplied
+ * @bfq_raising_max_time: maximum duration of a weight-raising period (jiffies)
+ * @bfq_raising_rt_max_time: maximum duration for soft real-time processes
+ * @bfq_raising_min_idle_time: minimum idle period after which weight-raising
+ * may be reactivated for a queue (in jiffies)
+ * @bfq_raising_min_inter_arr_async: minimum period between request arrivals
+ * after which weight-raising may be
+ * reactivated for an already busy queue
+ * (in jiffies)
+ * @bfq_raising_max_softrt_rate: max service-rate for a soft real-time queue,
+ * sectors per seconds
+ * @RT_prod: cached value of the product R*T used for computing the maximum
+ * duration of the weight raising automatically
+ * @oom_bfqq: fallback dummy bfqq for extreme OOM conditions
+ *
+ * All the fields are protected by the @queue lock.
+ */
+struct bfq_data {
+ struct request_queue *queue;
+
+ struct bfq_group *root_group;
+
+ struct rb_root rq_pos_tree;
+
+ int busy_queues;
+ int queued;
+ int rq_in_driver;
+ int sync_flight;
+
+ int max_rq_in_driver;
+ int hw_tag_samples;
+ int hw_tag;
+
+ int budgets_assigned;
+
+ struct timer_list idle_slice_timer;
+ struct work_struct unplug_work;
+
+ struct bfq_queue *active_queue;
+ struct cfq_io_context *active_cic;
+
+ sector_t last_position;
+
+ ktime_t last_budget_start;
+ ktime_t last_idling_start;
+ int peak_rate_samples;
+ u64 peak_rate;
+ unsigned long bfq_max_budget;
+
+ unsigned int cic_index;
+ struct list_head cic_list;
+ struct hlist_head group_list;
+ struct list_head active_list;
+ struct list_head idle_list;
+
+ unsigned int bfq_quantum;
+ unsigned int bfq_fifo_expire[2];
+ unsigned int bfq_back_penalty;
+ unsigned int bfq_back_max;
+ unsigned int bfq_slice_idle;
+ u64 bfq_class_idle_last_service;
+
+ unsigned int bfq_user_max_budget;
+ unsigned int bfq_max_budget_async_rq;
+ unsigned int bfq_timeout[2];
+
+ bool low_latency;
+
+ /* parameters of the low_latency heuristics */
+ unsigned int bfq_raising_coeff;
+ unsigned int bfq_raising_max_time;
+ unsigned int bfq_raising_rt_max_time;
+ unsigned int bfq_raising_min_idle_time;
+ unsigned int bfq_raising_min_inter_arr_async;
+ unsigned int bfq_raising_max_softrt_rate;
+ u64 RT_prod;
+
+ struct bfq_queue oom_bfqq;
+};
+
+enum bfqq_state_flags {
+ BFQ_BFQQ_FLAG_busy = 0, /* has requests or is under service */
+ BFQ_BFQQ_FLAG_wait_request, /* waiting for a request */
+ BFQ_BFQQ_FLAG_must_alloc, /* must be allowed rq alloc */
+ BFQ_BFQQ_FLAG_fifo_expire, /* FIFO checked in this slice */
+ BFQ_BFQQ_FLAG_idle_window, /* slice idling enabled */
+ BFQ_BFQQ_FLAG_prio_changed, /* task priority has changed */
+ BFQ_BFQQ_FLAG_sync, /* synchronous queue */
+ BFQ_BFQQ_FLAG_budget_new, /* no completion with this budget */
+ BFQ_BFQQ_FLAG_coop, /* bfqq is shared */
+ BFQ_BFQQ_FLAG_split_coop, /* shared bfqq will be splitted */
+ BFQ_BFQQ_FLAG_some_coop_idle, /* some cooperator is inactive */
+};
+
+#define BFQ_BFQQ_FNS(name) \
+static inline void bfq_mark_bfqq_##name(struct bfq_queue *bfqq) \
+{ \
+ (bfqq)->flags |= (1 << BFQ_BFQQ_FLAG_##name); \
+} \
+static inline void bfq_clear_bfqq_##name(struct bfq_queue *bfqq) \
+{ \
+ (bfqq)->flags &= ~(1 << BFQ_BFQQ_FLAG_##name); \
+} \
+static inline int bfq_bfqq_##name(const struct bfq_queue *bfqq) \
+{ \
+ return ((bfqq)->flags & (1 << BFQ_BFQQ_FLAG_##name)) != 0; \
+}
+
+BFQ_BFQQ_FNS(busy);
+BFQ_BFQQ_FNS(wait_request);
+BFQ_BFQQ_FNS(must_alloc);
+BFQ_BFQQ_FNS(fifo_expire);
+BFQ_BFQQ_FNS(idle_window);
+BFQ_BFQQ_FNS(prio_changed);
+BFQ_BFQQ_FNS(sync);
+BFQ_BFQQ_FNS(budget_new);
+BFQ_BFQQ_FNS(coop);
+BFQ_BFQQ_FNS(split_coop);
+BFQ_BFQQ_FNS(some_coop_idle);
+#undef BFQ_BFQQ_FNS
+
+/* Logging facilities. */
+#define bfq_log_bfqq(bfqd, bfqq, fmt, args...) \
+ blk_add_trace_msg((bfqd)->queue, "bfq%d " fmt, (bfqq)->pid, ##args)
+
+#define bfq_log(bfqd, fmt, args...) \
+ blk_add_trace_msg((bfqd)->queue, "bfq " fmt, ##args)
+
+/* Expiration reasons. */
+enum bfqq_expiration {
+ BFQ_BFQQ_TOO_IDLE = 0, /* queue has been idling for too long */
+ BFQ_BFQQ_BUDGET_TIMEOUT, /* budget took too long to be used */
+ BFQ_BFQQ_BUDGET_EXHAUSTED, /* budget consumed */
+ BFQ_BFQQ_NO_MORE_REQUESTS, /* the queue has no more requests */
+};
+
+#ifdef CONFIG_CGROUP_BFQIO
+/**
+ * struct bfq_group - per (device, cgroup) data structure.
+ * @entity: schedulable entity to insert into the parent group sched_data.
+ * @sched_data: own sched_data, to contain child entities (they may be
+ * both bfq_queues and bfq_groups).
+ * @group_node: node to be inserted into the bfqio_cgroup->group_data
+ * list of the containing cgroup's bfqio_cgroup.
+ * @bfqd_node: node to be inserted into the @bfqd->group_list list
+ * of the groups active on the same device; used for cleanup.
+ * @bfqd: the bfq_data for the device this group acts upon.
+ * @async_bfqq: array of async queues for all the tasks belonging to
+ * the group, one queue per ioprio value per ioprio_class,
+ * except for the idle class that has only one queue.
+ * @async_idle_bfqq: async queue for the idle class (ioprio is ignored).
+ * @my_entity: pointer to @entity, %NULL for the toplevel group; used
+ * to avoid too many special cases during group creation/migration.
+ *
+ * Each (device, cgroup) pair has its own bfq_group, i.e., for each cgroup
+ * there is a set of bfq_groups, each one collecting the lower-level
+ * entities belonging to the group that are acting on the same device.
+ *
+ * Locking works as follows:
+ * o @group_node is protected by the bfqio_cgroup lock, and is accessed
+ * via RCU from its readers.
+ * o @bfqd is protected by the queue lock, RCU is used to access it
+ * from the readers.
+ * o All the other fields are protected by the @bfqd queue lock.
+ */
+struct bfq_group {
+ struct bfq_entity entity;
+ struct bfq_sched_data sched_data;
+
+ struct hlist_node group_node;
+ struct hlist_node bfqd_node;
+
+ void *bfqd;
+
+ struct bfq_queue *async_bfqq[2][IOPRIO_BE_NR];
+ struct bfq_queue *async_idle_bfqq;
+
+ struct bfq_entity *my_entity;
+};
+
+/**
+ * struct bfqio_cgroup - bfq cgroup data structure.
+ * @css: subsystem state for bfq in the containing cgroup.
+ * @weight: cgroup weight.
+ * @ioprio: cgroup ioprio.
+ * @ioprio_class: cgroup ioprio_class.
+ * @lock: spinlock that protects @ioprio, @ioprio_class and @group_data.
+ * @group_data: list containing the bfq_group belonging to this cgroup.
+ *
+ * @group_data is accessed using RCU, with @lock protecting the updates,
+ * @ioprio and @ioprio_class are protected by @lock.
+ */
+struct bfqio_cgroup {
+ struct cgroup_subsys_state css;
+
+ unsigned short weight, ioprio, ioprio_class;
+
+ spinlock_t lock;
+ struct hlist_head group_data;
+};
+#else
+struct bfq_group {
+ struct bfq_sched_data sched_data;
+
+ struct bfq_queue *async_bfqq[2][IOPRIO_BE_NR];
+ struct bfq_queue *async_idle_bfqq;
+};
+#endif
+
+static inline struct bfq_service_tree *
+bfq_entity_service_tree(struct bfq_entity *entity)
+{
+ struct bfq_sched_data *sched_data = entity->sched_data;
+ unsigned int idx = entity->ioprio_class - 1;
+
+ BUG_ON(idx >= BFQ_IOPRIO_CLASSES);
+ BUG_ON(sched_data == NULL);
+
+ return sched_data->service_tree + idx;
+}
+
+static inline struct bfq_queue *cic_to_bfqq(struct cfq_io_context *cic,
+ int is_sync)
+{
+ return cic->cfqq[!!is_sync];
+}
+
+static inline void cic_set_bfqq(struct cfq_io_context *cic,
+ struct bfq_queue *bfqq, int is_sync)
+{
+ cic->cfqq[!!is_sync] = bfqq;
+}
+
+static inline void call_for_each_cic(struct io_context *ioc,
+ void (*func)(struct io_context *,
+ struct cfq_io_context *))
+{
+ struct cfq_io_context *cic;
+ struct hlist_node *n;
+
+ rcu_read_lock();
+ hlist_for_each_entry_rcu(cic, n, &ioc->bfq_cic_list, cic_list)
+ func(ioc, cic);
+ rcu_read_unlock();
+}
+
+#define CIC_DEAD_KEY 1ul
+#define CIC_DEAD_INDEX_SHIFT 1
+
+static inline void *bfqd_dead_key(struct bfq_data *bfqd)
+{
+ return (void *)(bfqd->cic_index << CIC_DEAD_INDEX_SHIFT | CIC_DEAD_KEY);
+}
+
+/**
+ * bfq_get_bfqd_locked - get a lock to a bfqd using a RCU protected pointer.
+ * @ptr: a pointer to a bfqd.
+ * @flags: storage for the flags to be saved.
+ *
+ * This function allows cic->key and bfqg->bfqd to be protected by the
+ * queue lock of the bfqd they reference; the pointer is dereferenced
+ * under RCU, so the storage for bfqd is assured to be safe as long
+ * as the RCU read side critical section does not end. After the
+ * bfqd->queue->queue_lock is taken the pointer is rechecked, to be
+ * sure that no other writer accessed it. If we raced with a writer,
+ * the function returns NULL, with the queue unlocked, otherwise it
+ * returns the dereferenced pointer, with the queue locked.
+ */
+static inline struct bfq_data *bfq_get_bfqd_locked(void **ptr,
+ unsigned long *flags)
+{
+ struct bfq_data *bfqd;
+
+ rcu_read_lock();
+ bfqd = rcu_dereference(*(struct bfq_data **)ptr);
+
+ if (bfqd != NULL && !((unsigned long) bfqd & CIC_DEAD_KEY)) {
+ spin_lock_irqsave(bfqd->queue->queue_lock, *flags);
+ if (*ptr == bfqd)
+ goto out;
+ spin_unlock_irqrestore(bfqd->queue->queue_lock, *flags);
+ }
+
+ bfqd = NULL;
+out:
+ rcu_read_unlock();
+ return bfqd;
+}
+
+static inline void bfq_put_bfqd_unlock(struct bfq_data *bfqd,
+ unsigned long *flags)
+{
+ spin_unlock_irqrestore(bfqd->queue->queue_lock, *flags);
+}
+
+static void bfq_changed_ioprio(struct io_context *ioc,
+ struct cfq_io_context *cic);
+static void bfq_put_queue(struct bfq_queue *bfqq);
+static void bfq_dispatch_insert(struct request_queue *q, struct request *rq);
+static struct bfq_queue *bfq_get_queue(struct bfq_data *bfqd,
+ struct bfq_group *bfqg, int is_sync,
+ struct io_context *ioc, gfp_t gfp_mask);
+static void bfq_put_async_queues(struct bfq_data *bfqd, struct bfq_group *bfqg);
+static void bfq_exit_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq);
+#endif
diff --git a/block/blk-ioc.c b/block/blk-ioc.c
index 342eae9..21f13b1 100644
--- a/block/blk-ioc.c
+++ b/block/blk-ioc.c
@@ -5,6 +5,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/bio.h>
+#include <linux/bitmap.h>
#include <linux/blkdev.h>
#include <linux/bootmem.h> /* for max_pfn/max_low_pfn */
#include <linux/slab.h>
@@ -16,13 +17,12 @@
*/
static struct kmem_cache *iocontext_cachep;
-static void cfq_dtor(struct io_context *ioc)
+static void hlist_sched_dtor(struct io_context *ioc, struct hlist_head *list)
{
- if (!hlist_empty(&ioc->cic_list)) {
+ if (!hlist_empty(list)) {
struct cfq_io_context *cic;
- cic = hlist_entry(ioc->cic_list.first, struct cfq_io_context,
- cic_list);
+ cic = hlist_entry(list->first, struct cfq_io_context, cic_list);
cic->dtor(ioc);
}
}
@@ -40,7 +40,9 @@ int put_io_context(struct io_context *ioc)
if (atomic_long_dec_and_test(&ioc->refcount)) {
rcu_read_lock();
- cfq_dtor(ioc);
+
+ hlist_sched_dtor(ioc, &ioc->cic_list);
+ hlist_sched_dtor(ioc, &ioc->bfq_cic_list);
rcu_read_unlock();
kmem_cache_free(iocontext_cachep, ioc);
@@ -50,15 +52,14 @@ int put_io_context(struct io_context *ioc)
}
EXPORT_SYMBOL(put_io_context);
-static void cfq_exit(struct io_context *ioc)
+static void hlist_sched_exit(struct io_context *ioc, struct hlist_head *list)
{
rcu_read_lock();
- if (!hlist_empty(&ioc->cic_list)) {
+ if (!hlist_empty(list)) {
struct cfq_io_context *cic;
- cic = hlist_entry(ioc->cic_list.first, struct cfq_io_context,
- cic_list);
+ cic = hlist_entry(list->first, struct cfq_io_context, cic_list);
cic->exit(ioc);
}
rcu_read_unlock();
@@ -74,9 +75,10 @@ void exit_io_context(struct task_struct *task)
task->io_context = NULL;
task_unlock(task);
- if (atomic_dec_and_test(&ioc->nr_tasks))
- cfq_exit(ioc);
-
+ if (atomic_dec_and_test(&ioc->nr_tasks)) {
+ hlist_sched_exit(ioc, &ioc->cic_list);
+ hlist_sched_exit(ioc, &ioc->bfq_cic_list);
+ }
put_io_context(ioc);
}
@@ -89,12 +91,14 @@ struct io_context *alloc_io_context(gfp_t gfp_flags, int node)
atomic_long_set(&ret->refcount, 1);
atomic_set(&ret->nr_tasks, 1);
spin_lock_init(&ret->lock);
- ret->ioprio_changed = 0;
+ bitmap_zero(ret->ioprio_changed, IOC_IOPRIO_CHANGED_BITS);
ret->ioprio = 0;
ret->last_waited = 0; /* doesn't matter... */
ret->nr_batch_requests = 0; /* because this is 0 */
INIT_RADIX_TREE(&ret->radix_root, GFP_ATOMIC | __GFP_HIGH);
INIT_HLIST_HEAD(&ret->cic_list);
+ INIT_RADIX_TREE(&ret->bfq_radix_root, GFP_ATOMIC | __GFP_HIGH);
+ INIT_HLIST_HEAD(&ret->bfq_cic_list);
ret->ioc_data = NULL;
#if defined(CONFIG_BLK_CGROUP) || defined(CONFIG_BLK_CGROUP_MODULE)
ret->cgroup_changed = 0;
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 23500ac..1142aba 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -2919,7 +2919,6 @@ static void changed_ioprio(struct io_context *ioc, struct cfq_io_context *cic)
static void cfq_ioc_set_ioprio(struct io_context *ioc)
{
call_for_each_cic(ioc, changed_ioprio);
- ioc->ioprio_changed = 0;
}
static void cfq_init_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq,
@@ -3211,8 +3210,13 @@ retry:
goto err_free;
out:
- smp_read_barrier_depends();
- if (unlikely(ioc->ioprio_changed))
+ /*
+ * test_and_clear_bit() implies a memory barrier, paired with
+ * the wmb() in fs/ioprio.c, so the value seen for ioprio is the
+ * new one.
+ */
+ if (unlikely(test_and_clear_bit(IOC_CFQ_IOPRIO_CHANGED,
+ ioc->ioprio_changed)))
cfq_ioc_set_ioprio(ioc);
#ifdef CONFIG_CFQ_GROUP_IOSCHED
diff --git a/block/genhd.c b/block/genhd.c
index 026d070..a1b0b90 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -744,7 +744,7 @@ void __init printk_all_partitions(void)
struct hd_struct *part;
char name_buf[BDEVNAME_SIZE];
char devt_buf[BDEVT_SIZE];
- u8 uuid[PARTITION_META_INFO_UUIDLTH * 2 + 1];
+ char uuid_buf[PARTITION_META_INFO_UUIDLTH * 2 + 5];
/*
* Don't show empty devices or things that have been
@@ -763,14 +763,16 @@ void __init printk_all_partitions(void)
while ((part = disk_part_iter_next(&piter))) {
bool is_part0 = part == &disk->part0;
- uuid[0] = 0;
+ uuid_buf[0] = '\0';
if (part->info)
- part_unpack_uuid(part->info->uuid, uuid);
+ snprintf(uuid_buf, sizeof(uuid_buf), "%pU",
+ part->info->uuid);
printk("%s%s %10llu %s %s", is_part0 ? "" : " ",
bdevt_str(part_devt(part), devt_buf),
(unsigned long long)part->nr_sects >> 1,
- disk_name(disk, part->partno, name_buf), uuid);
+ disk_name(disk, part->partno, name_buf),
+ uuid_buf);
if (is_part0) {
if (disk->driverfs_dev != NULL &&
disk->driverfs_dev->driver != NULL)
diff --git a/build.sh b/build.sh
new file mode 100755
index 0000000..81fcaed
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,203 @@
+#!/bin/bash
+
+BOARD=crespo
+DEVICEDIR=/sdcard/AROM
+KNAME=kernel.cyano.RELEASE
+DEVICE_CM_DIR=$ANDROID_BUILD_TOP/device/samsung/${BOARD}
+
+WaitForDevice()
+{
+ adb start-server
+ if [ $(adb get-state) != device -a $(adb shell busybox test -e /sbin/recovery 2> /dev/null; echo $?) != 0 ] ; then
+ echo "No device is online. Waiting for one..."
+ echo "Please connect USB and/or enable USB debugging"
+ until [ $(adb get-state) = device -o $(adb shell busybox test -e /sbin/recovery 2> /dev/null; echo $?) = 0 ];do
+ sleep 1
+ done
+ echo "Device Found.."
+ fi
+}
+
+setup ()
+{
+ if [ x = "x$ANDROID_BUILD_TOP" ] ; then
+ echo "Android build environment must be configured"
+ exit 1
+ fi
+ . "$ANDROID_BUILD_TOP"/build/envsetup.sh
+
+ KERNEL_DIR="$(dirname "$(readlink -f "$0")")"
+ BUILD_DIR="$KERNEL_DIR/build"
+
+ if [ x = "x$NO_CCACHE" ] && ccache -V &>/dev/null ; then
+ CCACHE=ccache
+ CCACHE_BASEDIR="$KERNEL_DIR"
+ CCACHE_COMPRESS=1
+ CCACHE_DIR="$BUILD_DIR/.ccache"
+ export CCACHE_DIR CCACHE_COMPRESS CCACHE_BASEDIR
+ else
+ CCACHE=""
+ fi
+
+ CROSS_PREFIX="$ANDROID_BUILD_TOP/prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin/arm-eabi-"
+}
+
+CheckVersion ()
+{
+ if [ ! -f .Mayor ]
+ then
+ echo 1 > .Mayor
+ fi
+ if [ ! -f .Minor ]
+ then
+ echo 0 > .Minor
+ fi
+ sVersion=$(cat build/${BOARD}/include/config/kernel.release)
+ echo $sVersion
+ sVersionMerge=${sVersion:(-8)}
+ echo sVersionMerge
+ iMayor=$(cat .Mayor)
+ iMinor=$(cat .Minor)
+}
+
+CreateKernelZip ()
+{
+ cd bin
+ rm *.zip
+ KZIPNAME=$KNAME.v$iMayor.$iMinor.$sVersionMerge.zip
+ zip $KZIPNAME * -r
+ if [ "$responseSend" == "y" ] ; then
+ WaitForDevice
+ echo Going into fastboot
+ if adb reboot-bootloader ; then
+ sleep 4
+ echo Pushing kernel file
+ if fastboot flash zimage kernel/zImage ; then
+ sleep 1
+ fastboot reboot
+ WaitForDevice
+ sleep 2
+ adb root
+ sleep 4
+ adb remount
+ sleep 2
+ echo Sending modules
+ for filename in system/modules/* ; do
+ echo Sending $filename to /system/modules
+ if adb push $filename /system/modules ; then
+ echo "Rebooting again"
+ fi
+ done
+ adb reboot
+ fi
+ fi
+ fi
+ cd ..
+ echo $KZIPNAME
+}
+
+UpgradeMinor ()
+{
+ iMinor=$(($iMinor+1))
+ echo $iMinor > .Minor
+}
+
+CompileError ()
+{
+ echo !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ echo ! COMPILACION FAILED
+ echo !
+ echo !
+ echo ! ---------------------- COMPILACION ERROR CODE: $RET
+ echo !
+ echo !
+ echo !
+ echo !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+}
+
+SenModulesToCMDevice()
+{
+ CURDIR=`pwd`;
+ cd bin/system/modules
+ rm $DEVICE_CM_DIR/KernelModules.mk
+ echo "# Kernel Modules TO BE COPIED" > $DEVICE_CM_DIR/KernelModules.mk
+ echo 'PRODUCT_COPY_FILES += \' >> $DEVICE_CM_DIR/KernelModules.mk
+ MODULEF=( $(find * -type f) )
+ # get length of an array
+ tLen=${#MODULEF[@]}
+ # use for loop read all modules but not the last
+ for (( i=0; i<${tLen}-1; i++ ));
+ do
+ echo ' device/samsung/'${BOARD}'/'${MODULEF[$i]}':system/modules/'${MODULEF[$i]}' \' >>$DEVICE_CM_DIR/KernelModules.mk
+ echo ${MODULEF[$i]}
+ done
+ echo ' device/samsung/'${BOARD}'/'${MODULEF[$i]}':system/modules/'${MODULEF[$i]} >>$DEVICE_CM_DIR/KernelModules.mk
+ cd $CURDIR
+}
+
+build ()
+{
+ local target=$1
+ echo "Building for $target"
+ local target_dir="$BUILD_DIR/$target"
+ local module
+ [ x = "x$NO_RM" ]
+ mkdir -p "$target_dir"
+ [ x = "x$NO_DEFCONFIG" ] && mka -C "$KERNEL_DIR" O="$target_dir" ARCH=arm ${BOARD}_defconfig HOSTCC="$CCACHE gcc"
+ if [ x = "x$NO_BUILD" ] ; then
+ mka -C "$KERNEL_DIR" O="$target_dir" ARCH=arm HOSTCC="$CCACHE gcc" CROSS_COMPILE="$CCACHE $CROSS_PREFIX" modules
+ RET=$?
+ if [[ $RET == 0 ]] ; then
+ mka -C "$KERNEL_DIR" O="$target_dir" ARCH=arm HOSTCC="$CCACHE gcc" CROSS_COMPILE="$CCACHE $CROSS_PREFIX" zImage
+ RET=$?
+ if [[ $RET == 0 ]] ; then
+ cp "$target_dir"/arch/arm/boot/zImage bin/kernel/zImage
+ MODULES=( $(find $target_dir/* -type f -name *.ko) )
+ for module in "${MODULES[@]}" ; do
+ echo $module
+ cp "$module" bin/system/lib/modules
+ done
+ # SenModulesToCMDevice
+ CheckVersion
+ CreateKernelZip
+ UpgradeMinor
+ else
+ CompileError
+ fi
+ else
+ CompileError
+ fi
+ fi
+}
+
+setup
+
+echo Type y + \"intro\" to send kernel to your mobile:
+read -t 10 responseSend;
+if [ "$responseSend" == "y" ] ; then
+ echo Sending to device after build .. $responseSend
+else
+ echo Only compile .. $responseSend
+fi
+
+
+if [ "$1" = clean ] ; then
+ rm -fr "$BUILD_DIR"/*
+ exit 0
+fi
+
+targets=(crespo)
+
+START=$(date +%s)
+
+for target in "${targets[@]}" ; do
+ build $target
+done
+
+END=$(date +%s)
+ELAPSED=$((END - START))
+E_MIN=$((ELAPSED / 60))
+E_SEC=$((ELAPSED - E_MIN * 60))
+printf "Elapsed: "
+[ $E_MIN != 0 ] && printf "%d min(s) " $E_MIN
+printf "%d sec(s)\n" $E_SEC
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index 58c3f74..9582050 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -292,7 +292,9 @@ static int acpi_ac_add(struct acpi_device *device)
ac->charger.properties = ac_props;
ac->charger.num_properties = ARRAY_SIZE(ac_props);
ac->charger.get_property = get_ac_property;
- power_supply_register(&ac->device->dev, &ac->charger);
+ result = power_supply_register(&ac->device->dev, &ac->charger);
+ if (result)
+ goto end;
printk(KERN_INFO PREFIX "%s [%s] (%s)\n",
acpi_device_name(device), acpi_device_bid(device),
diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c
index a43fa1a..1502c50 100644
--- a/drivers/acpi/acpi_pad.c
+++ b/drivers/acpi/acpi_pad.c
@@ -36,6 +36,7 @@
#define ACPI_PROCESSOR_AGGREGATOR_DEVICE_NAME "Processor Aggregator"
#define ACPI_PROCESSOR_AGGREGATOR_NOTIFY 0x80
static DEFINE_MUTEX(isolated_cpus_lock);
+static DEFINE_MUTEX(round_robin_lock);
static unsigned long power_saving_mwait_eax;
@@ -107,7 +108,7 @@ static void round_robin_cpu(unsigned int tsk_index)
if (!alloc_cpumask_var(&tmp, GFP_KERNEL))
return;
- mutex_lock(&isolated_cpus_lock);
+ mutex_lock(&round_robin_lock);
cpumask_clear(tmp);
for_each_cpu(cpu, pad_busy_cpus)
cpumask_or(tmp, tmp, topology_thread_cpumask(cpu));
@@ -116,7 +117,7 @@ static void round_robin_cpu(unsigned int tsk_index)
if (cpumask_empty(tmp))
cpumask_andnot(tmp, cpu_online_mask, pad_busy_cpus);
if (cpumask_empty(tmp)) {
- mutex_unlock(&isolated_cpus_lock);
+ mutex_unlock(&round_robin_lock);
return;
}
for_each_cpu(cpu, tmp) {
@@ -131,7 +132,7 @@ static void round_robin_cpu(unsigned int tsk_index)
tsk_in_cpu[tsk_index] = preferred_cpu;
cpumask_set_cpu(preferred_cpu, pad_busy_cpus);
cpu_weight[preferred_cpu]++;
- mutex_unlock(&isolated_cpus_lock);
+ mutex_unlock(&round_robin_lock);
set_cpus_allowed_ptr(current, cpumask_of(preferred_cpu));
}
diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c
index 4b7085d..55edd4a 100644
--- a/drivers/acpi/acpica/tbxface.c
+++ b/drivers/acpi/acpica/tbxface.c
@@ -435,6 +435,7 @@ acpi_get_table_with_size(char *signature,
return (AE_NOT_FOUND);
}
+ACPI_EXPORT_SYMBOL(acpi_get_table_with_size)
acpi_status
acpi_get_table(char *signature,
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index fcc13ac..d77c97d 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -635,11 +635,19 @@ static int acpi_battery_update(struct acpi_battery *battery)
static void acpi_battery_refresh(struct acpi_battery *battery)
{
+ int power_unit;
+
if (!battery->bat.dev)
return;
+ power_unit = battery->power_unit;
+
acpi_battery_get_info(battery);
- /* The battery may have changed its reporting units. */
+
+ if (power_unit == battery->power_unit)
+ return;
+
+ /* The battery has changed its reporting units. */
sysfs_remove_battery(battery);
sysfs_add_battery(battery);
}
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index d1e06c1..1c57307 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -944,8 +944,6 @@ static int __init acpi_bus_init(void)
status = acpi_ec_ecdt_probe();
/* Ignore result. Not having an ECDT is not fatal. */
- acpi_bus_osc_support();
-
status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION);
if (ACPI_FAILURE(status)) {
printk(KERN_ERR PREFIX "Unable to initialize ACPI objects\n");
@@ -953,6 +951,12 @@ static int __init acpi_bus_init(void)
}
/*
+ * _OSC method may exist in module level code,
+ * so it must be run after ACPI_FULL_INITIALIZATION
+ */
+ acpi_bus_osc_support();
+
+ /*
* _PDC control method may load dynamic SSDT tables,
* and we need to install the table handler before that.
*/
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index b19a18d..d2519b2 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -71,9 +71,6 @@ enum ec_command {
#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */
#define ACPI_EC_MSI_UDELAY 550 /* Wait 550us for MSI EC */
-#define ACPI_EC_STORM_THRESHOLD 8 /* number of false interrupts
- per one transaction */
-
enum {
EC_FLAGS_QUERY_PENDING, /* Query is pending */
EC_FLAGS_GPE_STORM, /* GPE storm detected */
@@ -87,6 +84,15 @@ static unsigned int ec_delay __read_mostly = ACPI_EC_DELAY;
module_param(ec_delay, uint, 0644);
MODULE_PARM_DESC(ec_delay, "Timeout(ms) waited until an EC command completes");
+/*
+ * If the number of false interrupts per one transaction exceeds
+ * this threshold, will think there is a GPE storm happened and
+ * will disable the GPE for normal transaction.
+ */
+static unsigned int ec_storm_threshold __read_mostly = 8;
+module_param(ec_storm_threshold, uint, 0644);
+MODULE_PARM_DESC(ec_storm_threshold, "Maxim false GPE numbers not considered as GPE storm");
+
/* If we find an EC via the ECDT, we need to keep a ptr to its context */
/* External interfaces use first EC only, so remember */
typedef int (*acpi_ec_query_func) (void *data);
@@ -319,7 +325,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
msleep(1);
/* It is safe to enable the GPE outside of the transaction. */
acpi_enable_gpe(NULL, ec->gpe);
- } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) {
+ } else if (t->irq_count > ec_storm_threshold) {
pr_info(PREFIX "GPE storm detected, "
"transactions will use polling mode\n");
set_bit(EC_FLAGS_GPE_STORM, &ec->flags);
@@ -914,6 +920,17 @@ static int ec_flag_msi(const struct dmi_system_id *id)
return 0;
}
+/*
+ * Clevo M720 notebook actually works ok with IRQ mode, if we lifted
+ * the GPE storm threshold back to 20
+ */
+static int ec_enlarge_storm_threshold(const struct dmi_system_id *id)
+{
+ pr_debug("Setting the EC GPE storm threshold to 20\n");
+ ec_storm_threshold = 20;
+ return 0;
+}
+
static struct dmi_system_id __initdata ec_dmi_table[] = {
{
ec_skip_dsdt_scan, "Compal JFL92", {
@@ -945,10 +962,13 @@ static struct dmi_system_id __initdata ec_dmi_table[] = {
{
ec_validate_ecdt, "ASUS hardware", {
DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc.") }, NULL},
+ {
+ ec_enlarge_storm_threshold, "CLEVO hardware", {
+ DMI_MATCH(DMI_SYS_VENDOR, "CLEVO Co."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "M720T/M730T"),}, NULL},
{},
};
-
int __init acpi_ec_ecdt_probe(void)
{
acpi_status status;
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 0c0669f..1893506 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -188,10 +188,12 @@ int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id)
* Processor (CPU3, 0x03, 0x00000410, 0x06) {}
* }
*
- * Ignores apic_id and always return 0 for CPU0's handle.
+ * Ignores apic_id and always returns 0 for the processor
+ * handle with acpi id 0 if nr_cpu_ids is 1.
+ * This should be the case if SMP tables are not found.
* Return -1 for other CPU's handle.
*/
- if (acpi_id == 0)
+ if (nr_cpu_ids <= 1 && acpi_id == 0)
return acpi_id;
else
return apic_id;
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index 0bd4832..79ddcde 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -422,6 +422,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
},
{
.callback = init_nvs_nosave,
+ .ident = "Sony Vaio VPCCW29FX",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "VPCCW29FX"),
+ },
+ },
+ {
+ .callback = init_nvs_nosave,
.ident = "Averatec AV1020-ED2",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "AVERATEC"),
diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c
index 77255f2..0364b05 100644
--- a/drivers/acpi/sysfs.c
+++ b/drivers/acpi/sysfs.c
@@ -173,7 +173,7 @@ static int param_set_trace_state(const char *val, struct kernel_param *kp)
{
int result = 0;
- if (!strncmp(val, "enable", strlen("enable") - 1)) {
+ if (!strncmp(val, "enable", strlen("enable"))) {
result = acpi_debug_trace(trace_method_name, trace_debug_level,
trace_debug_layer, 0);
if (result)
@@ -181,7 +181,7 @@ static int param_set_trace_state(const char *val, struct kernel_param *kp)
goto exit;
}
- if (!strncmp(val, "disable", strlen("disable") - 1)) {
+ if (!strncmp(val, "disable", strlen("disable"))) {
int name = 0;
result = acpi_debug_trace((char *)&name, trace_debug_level,
trace_debug_layer, 0);
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index db39e9e..623a335 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -1732,6 +1732,7 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type)
static int __init intel_opregion_present(void)
{
+ int i915 = 0;
#if defined(CONFIG_DRM_I915) || defined(CONFIG_DRM_I915_MODULE)
struct pci_dev *dev = NULL;
u32 address;
@@ -1744,10 +1745,10 @@ static int __init intel_opregion_present(void)
pci_read_config_dword(dev, 0xfc, &address);
if (!address)
continue;
- return 1;
+ i915 = 1;
}
#endif
- return 0;
+ return i915;
}
int acpi_video_register(void)
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 1e9ab9b..8300250 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -392,6 +392,10 @@ static const struct pci_device_id ahci_pci_tbl[] = {
.driver_data = board_ahci_yes_fbs }, /* 88se9128 */
{ PCI_DEVICE(0x1b4b, 0x9125),
.driver_data = board_ahci_yes_fbs }, /* 88se9125 */
+ { PCI_DEVICE(0x1b4b, 0x917a),
+ .driver_data = board_ahci_yes_fbs }, /* 88se9172 */
+ { PCI_DEVICE(0x1b4b, 0x9192),
+ .driver_data = board_ahci_yes_fbs }, /* 88se9172 on some Gigabyte */
{ PCI_DEVICE(0x1b4b, 0x91a3),
.driver_data = board_ahci_yes_fbs },
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 000d03a..600ede0 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -4138,6 +4138,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
/* Devices which aren't very happy with higher link speeds */
{ "WD My Book", NULL, ATA_HORKAGE_1_5_GBPS, },
+ { "Seagate FreeAgent GoFlex", NULL, ATA_HORKAGE_1_5_GBPS, },
/*
* Devices which choke on SETXFER. Applies only if both the
diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c
index 5d1d076..d452592 100644
--- a/drivers/atm/solos-pci.c
+++ b/drivers/atm/solos-pci.c
@@ -984,6 +984,7 @@ static uint32_t fpga_tx(struct solos_card *card)
} else if (skb && card->using_dma) {
SKB_CB(skb)->dma_addr = pci_map_single(card->dev, skb->data,
skb->len, PCI_DMA_TODEVICE);
+ card->tx_skb[port] = skb;
iowrite32(SKB_CB(skb)->dma_addr,
card->config_regs + TX_DMA_ADDR(port));
}
@@ -1152,7 +1153,8 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
db_fpga_upgrade = db_firmware_upgrade = 0;
}
- if (card->fpga_version >= DMA_SUPPORTED){
+ if (card->fpga_version >= DMA_SUPPORTED) {
+ pci_set_master(dev);
card->using_dma = 1;
} else {
card->using_dma = 0;
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 45d7c8f..5fb6aae 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -224,13 +224,48 @@ int memory_isolate_notify(unsigned long val, void *v)
}
/*
+ * The probe routines leave the pages reserved, just as the bootmem code does.
+ * Make sure they're still that way.
+ */
+static bool pages_correctly_reserved(unsigned long start_pfn,
+ unsigned long nr_pages)
+{
+ int i, j;
+ struct page *page;
+ unsigned long pfn = start_pfn;
+
+ /*
+ * memmap between sections is not contiguous except with
+ * SPARSEMEM_VMEMMAP. We lookup the page once per section
+ * and assume memmap is contiguous within each section
+ */
+ for (i = 0; i < sections_per_block; i++, pfn += PAGES_PER_SECTION) {
+ if (WARN_ON_ONCE(!pfn_valid(pfn)))
+ return false;
+ page = pfn_to_page(pfn);
+
+ for (j = 0; j < PAGES_PER_SECTION; j++) {
+ if (PageReserved(page + j))
+ continue;
+
+ printk(KERN_WARNING "section number %ld page number %d "
+ "not reserved, was it already online?\n",
+ pfn_to_section_nr(pfn), j);
+
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/*
* MEMORY_HOTPLUG depends on SPARSEMEM in mm/Kconfig, so it is
* OK to have direct references to sparsemem variables in here.
*/
static int
memory_block_action(unsigned long phys_index, unsigned long action)
{
- int i;
unsigned long start_pfn, start_paddr;
unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block;
struct page *first_page;
@@ -238,26 +273,13 @@ memory_block_action(unsigned long phys_index, unsigned long action)
first_page = pfn_to_page(phys_index << PFN_SECTION_SHIFT);
- /*
- * The probe routines leave the pages reserved, just
- * as the bootmem code does. Make sure they're still
- * that way.
- */
- if (action == MEM_ONLINE) {
- for (i = 0; i < nr_pages; i++) {
- if (PageReserved(first_page+i))
- continue;
-
- printk(KERN_WARNING "section number %ld page number %d "
- "not reserved, was it already online?\n",
- phys_index, i);
- return -EBUSY;
- }
- }
-
switch (action) {
case MEM_ONLINE:
start_pfn = page_to_pfn(first_page);
+
+ if (!pages_correctly_reserved(start_pfn, nr_pages))
+ return -EBUSY;
+
ret = online_pages(start_pfn, nr_pages);
break;
case MEM_OFFLINE:
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 184cf54..da39fa5 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -360,7 +360,6 @@ static int rpm_suspend(struct device *dev, int rpmflags)
goto repeat;
}
- dev->power.deferred_resume = false;
if (dev->power.no_callbacks)
goto no_callback; /* Assume success. */
@@ -420,6 +419,7 @@ static int rpm_suspend(struct device *dev, int rpmflags)
wake_up_all(&dev->power.wait_queue);
if (dev->power.deferred_resume) {
+ dev->power.deferred_resume = false;
rpm_resume(dev, 0);
retval = -EAGAIN;
goto out;
@@ -533,6 +533,7 @@ static int rpm_resume(struct device *dev, int rpmflags)
|| dev->parent->power.runtime_status == RPM_ACTIVE) {
atomic_inc(&dev->parent->power.child_count);
spin_unlock(&dev->parent->power.lock);
+ retval = 1;
goto no_callback; /* Assume success. */
}
spin_unlock(&dev->parent->power.lock);
@@ -610,7 +611,7 @@ static int rpm_resume(struct device *dev, int rpmflags)
}
wake_up_all(&dev->power.wait_queue);
- if (!retval)
+ if (retval >= 0)
rpm_idle(dev, RPM_ASYNC);
out:
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c
index be52344..a9cb238 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -110,9 +110,10 @@ static int bcma_register_cores(struct bcma_bus *bus)
static void bcma_unregister_cores(struct bcma_bus *bus)
{
- struct bcma_device *core;
+ struct bcma_device *core, *tmp;
- list_for_each_entry(core, &bus->cores, list) {
+ list_for_each_entry_safe(core, tmp, &bus->cores, list) {
+ list_del(&core->list);
if (core->dev_registered)
device_unregister(&core->dev);
}
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
index de0435e..887f68f 100644
--- a/drivers/block/aoe/aoecmd.c
+++ b/drivers/block/aoe/aoecmd.c
@@ -35,6 +35,7 @@ new_skb(ulong len)
skb_reset_mac_header(skb);
skb_reset_network_header(skb);
skb->protocol = __constant_htons(ETH_P_AOE);
+ skb_checksum_none_assert(skb);
}
return skb;
}
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index a552cab..f01b350 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -763,16 +763,7 @@ static void complete_scsi_command(CommandList_struct *c, int timeout,
{
case CMD_TARGET_STATUS:
/* Pass it up to the upper layers... */
- if( ei->ScsiStatus)
- {
-#if 0
- printk(KERN_WARNING "cciss: cmd %p "
- "has SCSI Status = %x\n",
- c, ei->ScsiStatus);
-#endif
- cmd->result |= (ei->ScsiStatus << 1);
- }
- else { /* scsi status is zero??? How??? */
+ if (!ei->ScsiStatus) {
/* Ordinarily, this case should never happen, but there is a bug
in some released firmware revisions that allows it to happen
@@ -804,6 +795,7 @@ static void complete_scsi_command(CommandList_struct *c, int timeout,
}
break;
case CMD_PROTOCOL_ERR:
+ cmd->result = DID_ERROR << 16;
dev_warn(&h->pdev->dev,
"%p has protocol error\n", c);
break;
diff --git a/drivers/block/umem.c b/drivers/block/umem.c
index 031ca72..afa8463 100644
--- a/drivers/block/umem.c
+++ b/drivers/block/umem.c
@@ -513,6 +513,44 @@ static void process_page(unsigned long data)
}
}
+struct mm_plug_cb {
+ struct blk_plug_cb cb;
+ struct cardinfo *card;
+};
+
+static void mm_unplug(struct blk_plug_cb *cb)
+{
+ struct mm_plug_cb *mmcb = container_of(cb, struct mm_plug_cb, cb);
+
+ spin_lock_irq(&mmcb->card->lock);
+ activate(mmcb->card);
+ spin_unlock_irq(&mmcb->card->lock);
+ kfree(mmcb);
+}
+
+static int mm_check_plugged(struct cardinfo *card)
+{
+ struct blk_plug *plug = current->plug;
+ struct mm_plug_cb *mmcb;
+
+ if (!plug)
+ return 0;
+
+ list_for_each_entry(mmcb, &plug->cb_list, cb.list) {
+ if (mmcb->cb.callback == mm_unplug && mmcb->card == card)
+ return 1;
+ }
+ /* Not currently on the callback list */
+ mmcb = kmalloc(sizeof(*mmcb), GFP_ATOMIC);
+ if (!mmcb)
+ return 0;
+
+ mmcb->card = card;
+ mmcb->cb.callback = mm_unplug;
+ list_add(&mmcb->cb.list, &plug->cb_list);
+ return 1;
+}
+
static int mm_make_request(struct request_queue *q, struct bio *bio)
{
struct cardinfo *card = q->queuedata;
@@ -523,6 +561,8 @@ static int mm_make_request(struct request_queue *q, struct bio *bio)
*card->biotail = bio;
bio->bi_next = NULL;
card->biotail = &bio->bi_next;
+ if (bio->bi_rw & REQ_SYNC || !mm_check_plugged(card))
+ activate(card);
spin_unlock_irq(&card->lock);
return 0;
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c
index a714c73..305e752 100644
--- a/drivers/bluetooth/ath3k.c
+++ b/drivers/bluetooth/ath3k.c
@@ -78,6 +78,9 @@ static struct usb_device_id ath3k_table[] = {
/* Atheros AR5BBU12 with sflash firmware */
{ USB_DEVICE(0x0489, 0xE02C) },
+ /* Atheros AR5BBU22 with sflash firmware */
+ { USB_DEVICE(0x0489, 0xE03C) },
+
{ } /* Terminating entry */
};
@@ -94,6 +97,9 @@ static struct usb_device_id ath3k_blist_tbl[] = {
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
+ /* Atheros AR5BBU22 with sflash firmware */
+ { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 },
+
{ } /* Terminating entry */
};
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 8fbda40..71346fe 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -60,8 +60,11 @@ static struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */
{ USB_DEVICE_INFO(0xe0, 0x01, 0x01) },
+ /* Apple-specific (Broadcom) devices */
+ { USB_VENDOR_AND_INTERFACE_INFO(0x05ac, 0xff, 0x01, 0x01) },
+
/* Broadcom SoftSailing reporting vendor specific */
- { USB_DEVICE(0x05ac, 0x21e1) },
+ { USB_DEVICE(0x0a5c, 0x21e1) },
/* Apple MacBookPro 7,1 */
{ USB_DEVICE(0x05ac, 0x8213) },
@@ -100,6 +103,16 @@ static struct usb_device_id btusb_table[] = {
/* Canyon CN-BTU1 with HID interfaces */
{ USB_DEVICE(0x0c10, 0x0000) },
+ /* Broadcom BCM20702A0 */
+ { USB_DEVICE(0x0489, 0xe042) },
+ { USB_DEVICE(0x413c, 0x8197) },
+
+ /* Foxconn - Hon Hai */
+ { USB_DEVICE(0x0489, 0xe033) },
+
+ /*Broadcom devices with vendor specific id */
+ { USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) },
+
{ } /* Terminating entry */
};
@@ -130,6 +143,9 @@ static struct usb_device_id blacklist_table[] = {
/* Atheros AR5BBU12 with sflash firmware */
{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
+ /* Atheros AR5BBU12 with sflash firmware */
+ { USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 },
+
/* Broadcom BCM2035 */
{ USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU },
{ USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index b427711..58b49d1 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -897,6 +897,7 @@ static struct pci_device_id agp_intel_pci_table[] = {
ID(PCI_DEVICE_ID_INTEL_B43_HB),
ID(PCI_DEVICE_ID_INTEL_B43_1_HB),
ID(PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB),
+ ID(PCI_DEVICE_ID_INTEL_IRONLAKE_D2_HB),
ID(PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB),
ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB),
ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB),
diff --git a/drivers/char/agp/intel-agp.h b/drivers/char/agp/intel-agp.h
index 5da67f1..6f24604 100644
--- a/drivers/char/agp/intel-agp.h
+++ b/drivers/char/agp/intel-agp.h
@@ -211,6 +211,7 @@
#define PCI_DEVICE_ID_INTEL_G41_HB 0x2E30
#define PCI_DEVICE_ID_INTEL_G41_IG 0x2E32
#define PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB 0x0040
+#define PCI_DEVICE_ID_INTEL_IRONLAKE_D2_HB 0x0069
#define PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG 0x0042
#define PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB 0x0044
#define PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB 0x0062
diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c
index 25d139c..579051c 100644
--- a/drivers/char/mspec.c
+++ b/drivers/char/mspec.c
@@ -284,7 +284,7 @@ mspec_mmap(struct file *file, struct vm_area_struct *vma,
vdata->flags = flags;
vdata->type = type;
spin_lock_init(&vdata->lock);
- vdata->refcnt = ATOMIC_INIT(1);
+ atomic_set(&vdata->refcnt, 1);
vma->vm_private_data = vdata;
vma->vm_flags |= (VM_IO | VM_RESERVED | VM_PFNMAP | VM_DONTEXPAND);
diff --git a/drivers/char/random.c b/drivers/char/random.c
index c35a785..fceac95 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -125,21 +125,26 @@
* The current exported interfaces for gathering environmental noise
* from the devices are:
*
+ * void add_device_randomness(const void *buf, unsigned int size);
* void add_input_randomness(unsigned int type, unsigned int code,
* unsigned int value);
- * void add_interrupt_randomness(int irq);
+ * void add_interrupt_randomness(int irq, int irq_flags);
* void add_disk_randomness(struct gendisk *disk);
*
+ * add_device_randomness() is for adding data to the random pool that
+ * is likely to differ between two devices (or possibly even per boot).
+ * This would be things like MAC addresses or serial numbers, or the
+ * read-out of the RTC. This does *not* add any actual entropy to the
+ * pool, but it initializes the pool to different values for devices
+ * that might otherwise be identical and have very little entropy
+ * available to them (particularly common in the embedded world).
+ *
* add_input_randomness() uses the input layer interrupt timing, as well as
* the event type information from the hardware.
*
- * add_interrupt_randomness() uses the inter-interrupt timing as random
- * inputs to the entropy pool. Note that not all interrupts are good
- * sources of randomness! For example, the timer interrupts is not a
- * good choice, because the periodicity of the interrupts is too
- * regular, and hence predictable to an attacker. Network Interface
- * Controller interrupts are a better measure, since the timing of the
- * NIC interrupts are more unpredictable.
+ * add_interrupt_randomness() uses the interrupt timing as random
+ * inputs to the entropy pool. Using the cycle counters and the irq source
+ * as inputs, it feeds the randomness roughly once a second.
*
* add_disk_randomness() uses what amounts to the seek time of block
* layer request events, on a per-disk_devt basis, as input to the
@@ -248,6 +253,8 @@
#include <linux/percpu.h>
#include <linux/cryptohash.h>
#include <linux/fips.h>
+#include <linux/ptrace.h>
+#include <linux/kmemcheck.h>
#ifdef CONFIG_GENERIC_HARDIRQS
# include <linux/irq.h>
@@ -256,8 +263,12 @@
#include <asm/processor.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
+#include <asm/irq_regs.h>
#include <asm/io.h>
+#define CREATE_TRACE_POINTS
+#include <trace/events/random.h>
+
/*
* Configuration information
*/
@@ -266,6 +277,8 @@
#define SEC_XFER_SIZE 512
#define EXTRACT_SIZE 10
+#define LONGS(x) (((x) + sizeof(unsigned long) - 1)/sizeof(unsigned long))
+
/*
* The minimum number of bits of entropy before we wake up a read on
* /dev/random. Should be enough to do a significant reseed.
@@ -420,8 +433,10 @@ struct entropy_store {
/* read-write data: */
spinlock_t lock;
unsigned add_ptr;
+ unsigned input_rotate;
int entropy_count;
- int input_rotate;
+ int entropy_total;
+ unsigned int initialized:1;
__u8 last_data[EXTRACT_SIZE];
};
@@ -454,6 +469,10 @@ static struct entropy_store nonblocking_pool = {
.pool = nonblocking_pool_data
};
+static __u32 const twist_table[8] = {
+ 0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
+ 0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
+
/*
* This function adds bytes into the entropy "pool". It does not
* update the entropy estimate. The caller should call
@@ -464,29 +483,24 @@ static struct entropy_store nonblocking_pool = {
* it's cheap to do so and helps slightly in the expected case where
* the entropy is concentrated in the low-order bits.
*/
-static void mix_pool_bytes_extract(struct entropy_store *r, const void *in,
- int nbytes, __u8 out[64])
+static void _mix_pool_bytes(struct entropy_store *r, const void *in,
+ int nbytes, __u8 out[64])
{
- static __u32 const twist_table[8] = {
- 0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
- 0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
unsigned long i, j, tap1, tap2, tap3, tap4, tap5;
int input_rotate;
int wordmask = r->poolinfo->poolwords - 1;
const char *bytes = in;
__u32 w;
- unsigned long flags;
- /* Taps are constant, so we can load them without holding r->lock. */
tap1 = r->poolinfo->tap1;
tap2 = r->poolinfo->tap2;
tap3 = r->poolinfo->tap3;
tap4 = r->poolinfo->tap4;
tap5 = r->poolinfo->tap5;
- spin_lock_irqsave(&r->lock, flags);
- input_rotate = r->input_rotate;
- i = r->add_ptr;
+ smp_rmb();
+ input_rotate = ACCESS_ONCE(r->input_rotate);
+ i = ACCESS_ONCE(r->add_ptr);
/* mix one byte at a time to simplify size handling and churn faster */
while (nbytes--) {
@@ -513,19 +527,61 @@ static void mix_pool_bytes_extract(struct entropy_store *r, const void *in,
input_rotate += i ? 7 : 14;
}
- r->input_rotate = input_rotate;
- r->add_ptr = i;
+ ACCESS_ONCE(r->input_rotate) = input_rotate;
+ ACCESS_ONCE(r->add_ptr) = i;
+ smp_wmb();
if (out)
for (j = 0; j < 16; j++)
((__u32 *)out)[j] = r->pool[(i - j) & wordmask];
+}
+static void __mix_pool_bytes(struct entropy_store *r, const void *in,
+ int nbytes, __u8 out[64])
+{
+ trace_mix_pool_bytes_nolock(r->name, nbytes, _RET_IP_);
+ _mix_pool_bytes(r, in, nbytes, out);
+}
+
+static void mix_pool_bytes(struct entropy_store *r, const void *in,
+ int nbytes, __u8 out[64])
+{
+ unsigned long flags;
+
+ trace_mix_pool_bytes(r->name, nbytes, _RET_IP_);
+ spin_lock_irqsave(&r->lock, flags);
+ _mix_pool_bytes(r, in, nbytes, out);
spin_unlock_irqrestore(&r->lock, flags);
}
-static void mix_pool_bytes(struct entropy_store *r, const void *in, int bytes)
+struct fast_pool {
+ __u32 pool[4];
+ unsigned long last;
+ unsigned short count;
+ unsigned char rotate;
+ unsigned char last_timer_intr;
+};
+
+/*
+ * This is a fast mixing routine used by the interrupt randomness
+ * collector. It's hardcoded for an 128 bit pool and assumes that any
+ * locks that might be needed are taken by the caller.
+ */
+static void fast_mix(struct fast_pool *f, const void *in, int nbytes)
{
- mix_pool_bytes_extract(r, in, bytes, NULL);
+ const char *bytes = in;
+ __u32 w;
+ unsigned i = f->count;
+ unsigned input_rotate = f->rotate;
+
+ while (nbytes--) {
+ w = rol32(*bytes++, input_rotate & 31) ^ f->pool[i & 3] ^
+ f->pool[(i + 1) & 3];
+ f->pool[i & 3] = (w >> 3) ^ twist_table[w & 7];
+ input_rotate += (i++ & 3) ? 7 : 14;
+ }
+ f->count = i;
+ f->rotate = input_rotate;
}
/*
@@ -533,30 +589,38 @@ static void mix_pool_bytes(struct entropy_store *r, const void *in, int bytes)
*/
static void credit_entropy_bits(struct entropy_store *r, int nbits)
{
- unsigned long flags;
- int entropy_count;
+ int entropy_count, orig;
if (!nbits)
return;
- spin_lock_irqsave(&r->lock, flags);
-
DEBUG_ENT("added %d entropy credits to %s\n", nbits, r->name);
- entropy_count = r->entropy_count;
+retry:
+ entropy_count = orig = ACCESS_ONCE(r->entropy_count);
entropy_count += nbits;
+
if (entropy_count < 0) {
DEBUG_ENT("negative entropy/overflow\n");
entropy_count = 0;
} else if (entropy_count > r->poolinfo->POOLBITS)
entropy_count = r->poolinfo->POOLBITS;
- r->entropy_count = entropy_count;
+ if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
+ goto retry;
+
+ if (!r->initialized && nbits > 0) {
+ r->entropy_total += nbits;
+ if (r->entropy_total > 128)
+ r->initialized = 1;
+ }
+
+ trace_credit_entropy_bits(r->name, nbits, entropy_count,
+ r->entropy_total, _RET_IP_);
/* should we wake readers? */
if (r == &input_pool && entropy_count >= random_read_wakeup_thresh) {
wake_up_interruptible(&random_read_wait);
kill_fasync(&fasync, SIGIO, POLL_IN);
}
- spin_unlock_irqrestore(&r->lock, flags);
}
/*********************************************************************
@@ -572,42 +636,24 @@ struct timer_rand_state {
unsigned dont_count_entropy:1;
};
-#ifndef CONFIG_GENERIC_HARDIRQS
-
-static struct timer_rand_state *irq_timer_state[NR_IRQS];
-
-static struct timer_rand_state *get_timer_rand_state(unsigned int irq)
-{
- return irq_timer_state[irq];
-}
-
-static void set_timer_rand_state(unsigned int irq,
- struct timer_rand_state *state)
-{
- irq_timer_state[irq] = state;
-}
-
-#else
-
-static struct timer_rand_state *get_timer_rand_state(unsigned int irq)
-{
- struct irq_desc *desc;
-
- desc = irq_to_desc(irq);
-
- return desc->timer_rand_state;
-}
-
-static void set_timer_rand_state(unsigned int irq,
- struct timer_rand_state *state)
+/*
+ * Add device- or boot-specific data to the input and nonblocking
+ * pools to help initialize them to unique values.
+ *
+ * None of this adds any entropy, it is meant to avoid the
+ * problem of the nonblocking pool having similar initial state
+ * across largely identical devices.
+ */
+void add_device_randomness(const void *buf, unsigned int size)
{
- struct irq_desc *desc;
-
- desc = irq_to_desc(irq);
+ unsigned long time = get_cycles() ^ jiffies;
- desc->timer_rand_state = state;
+ mix_pool_bytes(&input_pool, buf, size, NULL);
+ mix_pool_bytes(&input_pool, &time, sizeof(time), NULL);
+ mix_pool_bytes(&nonblocking_pool, buf, size, NULL);
+ mix_pool_bytes(&nonblocking_pool, &time, sizeof(time), NULL);
}
-#endif
+EXPORT_SYMBOL(add_device_randomness);
static struct timer_rand_state input_timer_state;
@@ -624,8 +670,8 @@ static struct timer_rand_state input_timer_state;
static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
{
struct {
- cycles_t cycles;
long jiffies;
+ unsigned cycles;
unsigned num;
} sample;
long delta, delta2, delta3;
@@ -639,7 +685,7 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
sample.jiffies = jiffies;
sample.cycles = get_cycles();
sample.num = num;
- mix_pool_bytes(&input_pool, &sample, sizeof(sample));
+ mix_pool_bytes(&input_pool, &sample, sizeof(sample), NULL);
/*
* Calculate number of bits of randomness we probably added.
@@ -696,17 +742,48 @@ void add_input_randomness(unsigned int type, unsigned int code,
}
EXPORT_SYMBOL_GPL(add_input_randomness);
-void add_interrupt_randomness(int irq)
+static DEFINE_PER_CPU(struct fast_pool, irq_randomness);
+
+void add_interrupt_randomness(int irq, int irq_flags)
{
- struct timer_rand_state *state;
+ struct entropy_store *r;
+ struct fast_pool *fast_pool = &__get_cpu_var(irq_randomness);
+ struct pt_regs *regs = get_irq_regs();
+ unsigned long now = jiffies;
+ __u32 input[4], cycles = get_cycles();
+
+ input[0] = cycles ^ jiffies;
+ input[1] = irq;
+ if (regs) {
+ __u64 ip = instruction_pointer(regs);
+ input[2] = ip;
+ input[3] = ip >> 32;
+ }
- state = get_timer_rand_state(irq);
+ fast_mix(fast_pool, input, sizeof(input));
- if (state == NULL)
+ if ((fast_pool->count & 1023) &&
+ !time_after(now, fast_pool->last + HZ))
return;
- DEBUG_ENT("irq event %d\n", irq);
- add_timer_randomness(state, 0x100 + irq);
+ fast_pool->last = now;
+
+ r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool;
+ __mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool), NULL);
+ /*
+ * If we don't have a valid cycle counter, and we see
+ * back-to-back timer interrupts, then skip giving credit for
+ * any entropy.
+ */
+ if (cycles == 0) {
+ if (irq_flags & __IRQF_TIMER) {
+ if (fast_pool->last_timer_intr)
+ return;
+ fast_pool->last_timer_intr = 1;
+ } else
+ fast_pool->last_timer_intr = 0;
+ }
+ credit_entropy_bits(r, 1);
}
#ifdef CONFIG_BLOCK
@@ -738,7 +815,7 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
*/
static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
{
- __u32 tmp[OUTPUT_POOL_WORDS];
+ __u32 tmp[OUTPUT_POOL_WORDS];
if (r->pull && r->entropy_count < nbytes * 8 &&
r->entropy_count < r->poolinfo->POOLBITS) {
@@ -757,7 +834,7 @@ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
bytes = extract_entropy(r->pull, tmp, bytes,
random_read_wakeup_thresh / 8, rsvd);
- mix_pool_bytes(r, tmp, bytes);
+ mix_pool_bytes(r, tmp, bytes, NULL);
credit_entropy_bits(r, bytes*8);
}
}
@@ -816,13 +893,19 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
static void extract_buf(struct entropy_store *r, __u8 *out)
{
int i;
- __u32 hash[5], workspace[SHA_WORKSPACE_WORDS];
+ union {
+ __u32 w[5];
+ unsigned long l[LONGS(EXTRACT_SIZE)];
+ } hash;
+ __u32 workspace[SHA_WORKSPACE_WORDS];
__u8 extract[64];
+ unsigned long flags;
/* Generate a hash across the pool, 16 words (512 bits) at a time */
- sha_init(hash);
+ sha_init(hash.w);
+ spin_lock_irqsave(&r->lock, flags);
for (i = 0; i < r->poolinfo->poolwords; i += 16)
- sha_transform(hash, (__u8 *)(r->pool + i), workspace);
+ sha_transform(hash.w, (__u8 *)(r->pool + i), workspace);
/*
* We mix the hash back into the pool to prevent backtracking
@@ -833,13 +916,14 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
* brute-forcing the feedback as hard as brute-forcing the
* hash.
*/
- mix_pool_bytes_extract(r, hash, sizeof(hash), extract);
+ __mix_pool_bytes(r, hash.w, sizeof(hash.w), extract);
+ spin_unlock_irqrestore(&r->lock, flags);
/*
* To avoid duplicates, we atomically extract a portion of the
* pool while mixing, and hash one final time.
*/
- sha_transform(hash, extract, workspace);
+ sha_transform(hash.w, extract, workspace);
memset(extract, 0, sizeof(extract));
memset(workspace, 0, sizeof(workspace));
@@ -848,20 +932,32 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
* pattern, we fold it in half. Thus, we always feed back
* twice as much data as we output.
*/
- hash[0] ^= hash[3];
- hash[1] ^= hash[4];
- hash[2] ^= rol32(hash[2], 16);
- memcpy(out, hash, EXTRACT_SIZE);
- memset(hash, 0, sizeof(hash));
+ hash.w[0] ^= hash.w[3];
+ hash.w[1] ^= hash.w[4];
+ hash.w[2] ^= rol32(hash.w[2], 16);
+
+ /*
+ * If we have a architectural hardware random number
+ * generator, mix that in, too.
+ */
+ for (i = 0; i < LONGS(EXTRACT_SIZE); i++) {
+ unsigned long v;
+ if (!arch_get_random_long(&v))
+ break;
+ hash.l[i] ^= v;
+ }
+
+ memcpy(out, &hash, EXTRACT_SIZE);
+ memset(&hash, 0, sizeof(hash));
}
static ssize_t extract_entropy(struct entropy_store *r, void *buf,
- size_t nbytes, int min, int reserved)
+ size_t nbytes, int min, int reserved)
{
ssize_t ret = 0, i;
__u8 tmp[EXTRACT_SIZE];
- unsigned long flags;
+ trace_extract_entropy(r->name, nbytes, r->entropy_count, _RET_IP_);
xfer_secondary_pool(r, nbytes);
nbytes = account(r, nbytes, min, reserved);
@@ -869,6 +965,8 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
extract_buf(r, tmp);
if (fips_enabled) {
+ unsigned long flags;
+
spin_lock_irqsave(&r->lock, flags);
if (!memcmp(tmp, r->last_data, EXTRACT_SIZE))
panic("Hardware RNG duplicated output!\n");
@@ -894,6 +992,7 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
ssize_t ret = 0, i;
__u8 tmp[EXTRACT_SIZE];
+ trace_extract_entropy_user(r->name, nbytes, r->entropy_count, _RET_IP_);
xfer_secondary_pool(r, nbytes);
nbytes = account(r, nbytes, 0, 0);
@@ -927,8 +1026,9 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
/*
* This function is the exported kernel interface. It returns some
- * number of good random numbers, suitable for seeding TCP sequence
- * numbers, etc.
+ * number of good random numbers, suitable for key generation, seeding
+ * TCP sequence numbers, etc. It does not use the hw random number
+ * generator, if available; use get_random_bytes_arch() for that.
*/
void get_random_bytes(void *buf, int nbytes)
{
@@ -937,6 +1037,39 @@ void get_random_bytes(void *buf, int nbytes)
EXPORT_SYMBOL(get_random_bytes);
/*
+ * This function will use the architecture-specific hardware random
+ * number generator if it is available. The arch-specific hw RNG will
+ * almost certainly be faster than what we can do in software, but it
+ * is impossible to verify that it is implemented securely (as
+ * opposed, to, say, the AES encryption of a sequence number using a
+ * key known by the NSA). So it's useful if we need the speed, but
+ * only if we're willing to trust the hardware manufacturer not to
+ * have put in a back door.
+ */
+void get_random_bytes_arch(void *buf, int nbytes)
+{
+ char *p = buf;
+
+ trace_get_random_bytes(nbytes, _RET_IP_);
+ while (nbytes) {
+ unsigned long v;
+ int chunk = min(nbytes, (int)sizeof(unsigned long));
+
+ if (!arch_get_random_long(&v))
+ break;
+
+ memcpy(p, &v, chunk);
+ p += chunk;
+ nbytes -= chunk;
+ }
+
+ if (nbytes)
+ extract_entropy(&nonblocking_pool, p, nbytes, 0, 0);
+}
+EXPORT_SYMBOL(get_random_bytes_arch);
+
+
+/*
* init_std_data - initialize pool with system data
*
* @r: pool to initialize
@@ -947,18 +1080,31 @@ EXPORT_SYMBOL(get_random_bytes);
*/
static void init_std_data(struct entropy_store *r)
{
- ktime_t now;
- unsigned long flags;
+ int i;
+ ktime_t now = ktime_get_real();
+ unsigned long rv;
- spin_lock_irqsave(&r->lock, flags);
r->entropy_count = 0;
- spin_unlock_irqrestore(&r->lock, flags);
-
- now = ktime_get_real();
- mix_pool_bytes(r, &now, sizeof(now));
- mix_pool_bytes(r, utsname(), sizeof(*(utsname())));
+ r->entropy_total = 0;
+ mix_pool_bytes(r, &now, sizeof(now), NULL);
+ for (i = r->poolinfo->POOLBYTES; i > 0; i -= sizeof(rv)) {
+ if (!arch_get_random_long(&rv))
+ break;
+ mix_pool_bytes(r, &rv, sizeof(rv), NULL);
+ }
+ mix_pool_bytes(r, utsname(), sizeof(*(utsname())), NULL);
}
+/*
+ * Note that setup_arch() may call add_device_randomness()
+ * long before we get here. This allows seeding of the pools
+ * with some platform dependent data very early in the boot
+ * process. But it limits our options here. We must use
+ * statically allocated structures that already have all
+ * initializations complete at compile time. We should also
+ * take care not to overwrite the precious per platform data
+ * we were given.
+ */
static int rand_initialize(void)
{
init_std_data(&input_pool);
@@ -968,24 +1114,6 @@ static int rand_initialize(void)
}
module_init(rand_initialize);
-void rand_initialize_irq(int irq)
-{
- struct timer_rand_state *state;
-
- state = get_timer_rand_state(irq);
-
- if (state)
- return;
-
- /*
- * If kzalloc returns null, we just won't use that entropy
- * source.
- */
- state = kzalloc(sizeof(struct timer_rand_state), GFP_KERNEL);
- if (state)
- set_timer_rand_state(irq, state);
-}
-
#ifdef CONFIG_BLOCK
void rand_initialize_disk(struct gendisk *disk)
{
@@ -1093,7 +1221,7 @@ write_pool(struct entropy_store *r, const char __user *buffer, size_t count)
count -= bytes;
p += bytes;
- mix_pool_bytes(r, buf, bytes);
+ mix_pool_bytes(r, buf, bytes, NULL);
cond_resched();
}
@@ -1236,10 +1364,15 @@ static int proc_do_uuid(ctl_table *table, int write,
uuid = table->data;
if (!uuid) {
uuid = tmp_uuid;
- uuid[8] = 0;
- }
- if (uuid[8] == 0)
generate_random_uuid(uuid);
+ } else {
+ static DEFINE_SPINLOCK(bootid_spinlock);
+
+ spin_lock(&bootid_spinlock);
+ if (!uuid[8])
+ generate_random_uuid(uuid);
+ spin_unlock(&bootid_spinlock);
+ }
sprintf(buf, "%pU", uuid);
@@ -1318,9 +1451,14 @@ late_initcall(random_int_secret_init);
DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash);
unsigned int get_random_int(void)
{
- __u32 *hash = get_cpu_var(get_random_int_hash);
+ __u32 *hash;
unsigned int ret;
+ if (arch_get_random_int(&ret))
+ return ret;
+
+ hash = get_cpu_var(get_random_int_hash);
+
hash[0] += current->pid + jiffies + get_cycles();
md5_transform(hash, random_int_secret);
ret = hash[0];
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index b85ee76..65b9d6f 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -1019,17 +1019,20 @@ ssize_t tpm_write(struct file *file, const char __user *buf,
size_t size, loff_t *off)
{
struct tpm_chip *chip = file->private_data;
- size_t in_size = size, out_size;
+ size_t in_size = size;
+ ssize_t out_size;
/* cannot perform a write until the read has cleared
- either via tpm_read or a user_read_timer timeout */
- while (atomic_read(&chip->data_pending) != 0)
- msleep(TPM_TIMEOUT);
-
- mutex_lock(&chip->buffer_mutex);
+ either via tpm_read or a user_read_timer timeout.
+ This also prevents splitted buffered writes from blocking here.
+ */
+ if (atomic_read(&chip->data_pending) != 0)
+ return -EBUSY;
if (in_size > TPM_BUFSIZE)
- in_size = TPM_BUFSIZE;
+ return -E2BIG;
+
+ mutex_lock(&chip->buffer_mutex);
if (copy_from_user
(chip->data_buffer, (void __user *) buf, in_size)) {
@@ -1039,6 +1042,10 @@ ssize_t tpm_write(struct file *file, const char __user *buf,
/* atomic tpm command send and result receive */
out_size = tpm_transmit(chip, chip->data_buffer, TPM_BUFSIZE);
+ if (out_size < 0) {
+ mutex_unlock(&chip->buffer_mutex);
+ return out_size;
+ }
atomic_set(&chip->data_pending, out_size);
mutex_unlock(&chip->buffer_mutex);
diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c
index a1f68af..acce1a7 100644
--- a/drivers/char/ttyprintk.c
+++ b/drivers/char/ttyprintk.c
@@ -66,7 +66,7 @@ static int tpk_printk(const unsigned char *buf, int count)
tmp[tpk_curr + 1] = '\0';
printk(KERN_INFO "%s%s", tpk_tag, tmp);
tpk_curr = 0;
- if (buf[i + 1] == '\n')
+ if ((i + 1) < count && buf[i + 1] == '\n')
i++;
break;
case '\n':
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 0a5bea9..9852b9a 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -433,6 +433,9 @@ static ssize_t store_scaling_governor(struct cpufreq_policy *policy,
unsigned int ret = -EINVAL;
char str_governor[16];
struct cpufreq_policy new_policy;
+ char *envp[3];
+ char buf1[64];
+ char buf2[64];
ret = cpufreq_get_policy(&new_policy, policy->cpu);
if (ret)
@@ -453,6 +456,13 @@ static ssize_t store_scaling_governor(struct cpufreq_policy *policy,
policy->user_policy.policy = policy->policy;
policy->user_policy.governor = policy->governor;
+ snprintf(buf1, sizeof(buf1), "GOV=%s", policy->governor->name);
+ snprintf(buf2, sizeof(buf2), "CPU=%u", policy->cpu);
+ envp[0] = buf1;
+ envp[1] = buf2;
+ envp[2] = NULL;
+ kobject_uevent_env(cpufreq_global_kobject, KOBJ_ADD, envp);
+
if (ret)
return ret;
else
diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c
index 7dbacf0..5a69436 100644
--- a/drivers/cpufreq/cpufreq_interactive.c
+++ b/drivers/cpufreq/cpufreq_interactive.c
@@ -69,6 +69,14 @@ static struct mutex set_speed_lock;
/* Hi speed to bump to from lo speed when load burst (default max) */
static u64 hispeed_freq;
+/* When the boostpulse was activated */
+static u64 boostpulse_boosted_time;
+
+/* How long the boostpulse will remain active */
+#define DEFAULT_BOOSTPULSE_DURATION 500000
+#define MAX_BOOSTPULSE_DURATION 5000000
+static int boostpulse_duration;
+
/* Go to hi speed when CPU load at or above this value. */
#define DEFAULT_GO_HISPEED_LOAD 85
static unsigned long go_hispeed_load;
@@ -138,6 +146,7 @@ static void cpufreq_interactive_timer(unsigned long data)
unsigned int new_freq;
unsigned int index;
unsigned long flags;
+ u64 now = ktime_to_us(ktime_get());
smp_rmb();
@@ -196,7 +205,14 @@ static void cpufreq_interactive_timer(unsigned long data)
if (load_since_change > cpu_load)
cpu_load = load_since_change;
- if (cpu_load >= go_hispeed_load || boost_val) {
+ if (boostpulse_boosted_time &&
+ now > boostpulse_boosted_time + boostpulse_duration) {
+ /* Disable the boostpulse. */
+ boostpulse_boosted_time = 0;
+ boostpulse_duration = 0;
+ }
+
+ if (cpu_load >= go_hispeed_load || boost_val || boostpulse_boosted_time) {
if (pcpu->target_freq <= pcpu->policy->min) {
new_freq = hispeed_freq;
} else {
@@ -787,12 +803,18 @@ static ssize_t store_boostpulse(struct kobject *kobj, struct attribute *attr,
const char *buf, size_t count)
{
int ret;
- unsigned long val;
+ unsigned int val;
- ret = kstrtoul(buf, 0, &val);
+ ret = sscanf(buf, "%u", &val);
if (ret < 0)
return ret;
+ boostpulse_boosted_time = ktime_to_us(ktime_get());
+ if (val > 1 && val <= MAX_BOOSTPULSE_DURATION)
+ boostpulse_duration = val;
+ else
+ boostpulse_duration = DEFAULT_BOOSTPULSE_DURATION;
+
trace_cpufreq_interactive_boost("pulse");
cpufreq_interactive_boost();
return count;
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 891360e..63e354b 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -37,6 +37,10 @@
#define MICRO_FREQUENCY_MIN_SAMPLE_RATE (10000)
#define MIN_FREQUENCY_UP_THRESHOLD (11)
#define MAX_FREQUENCY_UP_THRESHOLD (100)
+#define DEFAULT_FREQ_BOOST_TIME (500000)
+#define MAX_FREQ_BOOST_TIME (5000000)
+
+u64 freq_boosted_time;
/*
* The polling frequency of this governor depends on the capability of
@@ -111,12 +115,17 @@ static struct dbs_tuners {
unsigned int sampling_down_factor;
unsigned int powersave_bias;
unsigned int io_is_busy;
+ unsigned int boosted;
+ unsigned int freq_boost_time;
+ unsigned int boostfreq;
} dbs_tuners_ins = {
.up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
.sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR,
.down_differential = DEF_FREQUENCY_DOWN_DIFFERENTIAL,
.ignore_nice = 0,
.powersave_bias = 0,
+ .freq_boost_time = DEFAULT_FREQ_BOOST_TIME,
+ .boostfreq = 0,
};
static inline cputime64_t get_cpu_idle_time_jiffy(unsigned int cpu,
@@ -255,6 +264,9 @@ show_one(up_threshold, up_threshold);
show_one(sampling_down_factor, sampling_down_factor);
show_one(ignore_nice_load, ignore_nice);
show_one(powersave_bias, powersave_bias);
+show_one(boostpulse, boosted);
+show_one(boosttime, freq_boost_time);
+show_one(boostfreq, boostfreq);
static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b,
const char *buf, size_t count)
@@ -367,12 +379,47 @@ static ssize_t store_powersave_bias(struct kobject *a, struct attribute *b,
return count;
}
+
+static ssize_t store_boostpulse(struct kobject *kobj, struct attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret;
+ unsigned int input;
+
+ ret = sscanf(buf, "%u", &input);
+ if (ret < 0)
+ return ret;
+
+ if (input > 1 && input <= MAX_FREQ_BOOST_TIME)
+ dbs_tuners_ins.freq_boost_time = input;
+ else
+ dbs_tuners_ins.freq_boost_time = DEFAULT_FREQ_BOOST_TIME;
+
+ dbs_tuners_ins.boosted = 1;
+ freq_boosted_time = ktime_to_us(ktime_get());
+ return count;
+}
+
+static ssize_t store_boostfreq(struct kobject *a, struct attribute *b,
+ const char *buf, size_t count)
+{
+ unsigned int input;
+ int ret;
+ ret = sscanf(buf, "%u", &input);
+ if (ret != 1)
+ return -EINVAL;
+ dbs_tuners_ins.boostfreq = input;
+ return count;
+}
+
define_one_global_rw(sampling_rate);
define_one_global_rw(io_is_busy);
define_one_global_rw(up_threshold);
define_one_global_rw(sampling_down_factor);
define_one_global_rw(ignore_nice_load);
define_one_global_rw(powersave_bias);
+define_one_global_rw(boostpulse);
+define_one_global_rw(boostfreq);
static struct attribute *dbs_attributes[] = {
&sampling_rate_min.attr,
@@ -382,6 +429,8 @@ static struct attribute *dbs_attributes[] = {
&ignore_nice_load.attr,
&powersave_bias.attr,
&io_is_busy.attr,
+ &boostpulse.attr,
+ &boostfreq.attr,
NULL
};
@@ -409,10 +458,21 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
struct cpufreq_policy *policy;
unsigned int j;
+ unsigned int boostfreq;
this_dbs_info->freq_lo = 0;
policy = this_dbs_info->cur_policy;
-
+ /* Only core0 controls the boost */
+ if (dbs_tuners_ins.boosted && policy->cpu == 0) {
+ if (ktime_to_us(ktime_get()) - freq_boosted_time >=
+ dbs_tuners_ins.freq_boost_time) {
+ dbs_tuners_ins.boosted = 0;
+ }
+ }
+ if (dbs_tuners_ins.boostfreq != 0)
+ boostfreq = dbs_tuners_ins.boostfreq;
+ else
+ boostfreq = policy->max;
/*
* Every sampling_rate, we check, if current idle time is less
* than 20% (default), then we try to increase frequency
@@ -503,6 +563,13 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
return;
}
+ /* check for frequency boost */
+ if (dbs_tuners_ins.boosted && policy->cur < boostfreq) {
+ dbs_freq_increase(policy, boostfreq);
+ dbs_tuners_ins.boostfreq = policy->cur;
+ return;
+ }
+
/* Check for frequency decrease */
/* if we cannot reduce the frequency anymore, break out early */
if (policy->cur == policy->min)
@@ -521,6 +588,10 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
(dbs_tuners_ins.up_threshold -
dbs_tuners_ins.down_differential);
+ if (dbs_tuners_ins.boosted &&
+ freq_next < boostfreq) {
+ freq_next = boostfreq;
+ }
/* No longer fully busy, reset rate_mult */
this_dbs_info->rate_mult = 1;
diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c
index ad683ec..f6cd315 100644
--- a/drivers/cpufreq/powernow-k8.c
+++ b/drivers/cpufreq/powernow-k8.c
@@ -32,7 +32,6 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/cpumask.h>
-#include <linux/sched.h> /* for current / set_cpus_allowed() */
#include <linux/io.h>
#include <linux/delay.h>
@@ -1132,16 +1131,23 @@ static int transition_frequency_pstate(struct powernow_k8_data *data,
return res;
}
-/* Driver entry point to switch to the target frequency */
-static int powernowk8_target(struct cpufreq_policy *pol,
- unsigned targfreq, unsigned relation)
+struct powernowk8_target_arg {
+ struct cpufreq_policy *pol;
+ unsigned targfreq;
+ unsigned relation;
+};
+
+static long powernowk8_target_fn(void *arg)
{
- cpumask_var_t oldmask;
+ struct powernowk8_target_arg *pta = arg;
+ struct cpufreq_policy *pol = pta->pol;
+ unsigned targfreq = pta->targfreq;
+ unsigned relation = pta->relation;
struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu);
u32 checkfid;
u32 checkvid;
unsigned int newstate;
- int ret = -EIO;
+ int ret;
if (!data)
return -EINVAL;
@@ -1149,29 +1155,16 @@ static int powernowk8_target(struct cpufreq_policy *pol,
checkfid = data->currfid;
checkvid = data->currvid;
- /* only run on specific CPU from here on. */
- /* This is poor form: use a workqueue or smp_call_function_single */
- if (!alloc_cpumask_var(&oldmask, GFP_KERNEL))
- return -ENOMEM;
-
- cpumask_copy(oldmask, tsk_cpus_allowed(current));
- set_cpus_allowed_ptr(current, cpumask_of(pol->cpu));
-
- if (smp_processor_id() != pol->cpu) {
- printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu);
- goto err_out;
- }
-
if (pending_bit_stuck()) {
printk(KERN_ERR PFX "failing targ, change pending bit set\n");
- goto err_out;
+ return -EIO;
}
pr_debug("targ: cpu %d, %d kHz, min %d, max %d, relation %d\n",
pol->cpu, targfreq, pol->min, pol->max, relation);
if (query_current_values_with_pending_wait(data))
- goto err_out;
+ return -EIO;
if (cpu_family != CPU_HW_PSTATE) {
pr_debug("targ: curr fid 0x%x, vid 0x%x\n",
@@ -1189,7 +1182,7 @@ static int powernowk8_target(struct cpufreq_policy *pol,
if (cpufreq_frequency_table_target(pol, data->powernow_table,
targfreq, relation, &newstate))
- goto err_out;
+ return -EIO;
mutex_lock(&fidvid_mutex);
@@ -1202,9 +1195,8 @@ static int powernowk8_target(struct cpufreq_policy *pol,
ret = transition_frequency_fidvid(data, newstate);
if (ret) {
printk(KERN_ERR PFX "transition frequency failed\n");
- ret = 1;
mutex_unlock(&fidvid_mutex);
- goto err_out;
+ return 1;
}
mutex_unlock(&fidvid_mutex);
@@ -1213,12 +1205,18 @@ static int powernowk8_target(struct cpufreq_policy *pol,
data->powernow_table[newstate].index);
else
pol->cur = find_khz_freq_from_fid(data->currfid);
- ret = 0;
-err_out:
- set_cpus_allowed_ptr(current, oldmask);
- free_cpumask_var(oldmask);
- return ret;
+ return 0;
+}
+
+/* Driver entry point to switch to the target frequency */
+static int powernowk8_target(struct cpufreq_policy *pol,
+ unsigned targfreq, unsigned relation)
+{
+ struct powernowk8_target_arg pta = { .pol = pol, .targfreq = targfreq,
+ .relation = relation };
+
+ return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta);
}
/* Driver entry point to verify the policy and range of frequencies */
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index e0b25de..98caccf 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -173,6 +173,7 @@ config CRYPTO_DEV_MV_CESA
select CRYPTO_ALGAPI
select CRYPTO_AES
select CRYPTO_BLKCIPHER2
+ select CRYPTO_HASH
help
This driver allows you to utilize the Cryptographic Engines and
Security Accelerator (CESA) which can be found on the Marvell Orion
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
index 10c6349..1357c3b 100644
--- a/drivers/dma/at_hdmac.c
+++ b/drivers/dma/at_hdmac.c
@@ -674,7 +674,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
flags);
if (unlikely(!atslave || !sg_len)) {
- dev_dbg(chan2dev(chan), "prep_dma_memcpy: length is zero!\n");
+ dev_dbg(chan2dev(chan), "prep_slave_sg: sg length is zero!\n");
return NULL;
}
@@ -702,6 +702,11 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
mem = sg_dma_address(sg);
len = sg_dma_len(sg);
+ if (unlikely(!len)) {
+ dev_dbg(chan2dev(chan),
+ "prep_slave_sg: sg(%d) data length is zero\n", i);
+ goto err;
+ }
mem_width = 2;
if (unlikely(mem & 3 || len & 3))
mem_width = 0;
@@ -736,6 +741,11 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
mem = sg_dma_address(sg);
len = sg_dma_len(sg);
+ if (unlikely(!len)) {
+ dev_dbg(chan2dev(chan),
+ "prep_slave_sg: sg(%d) data length is zero\n", i);
+ goto err;
+ }
mem_width = 2;
if (unlikely(mem & 3 || len & 3))
mem_width = 0;
@@ -769,6 +779,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
err_desc_get:
dev_err(chan2dev(chan), "not enough descriptors available\n");
+err:
atc_desc_put(atchan, first);
return NULL;
}
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index 9a8bebc..feb2d10 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -161,8 +161,11 @@ static int __amd64_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate)
* memory controller and apply to register. Search for the first
* bandwidth entry that is greater or equal than the setting requested
* and program that. If at last entry, turn off DRAM scrubbing.
+ *
+ * If no suitable bandwidth is found, turn off DRAM scrubbing entirely
+ * by falling back to the last element in scrubrates[].
*/
- for (i = 0; i < ARRAY_SIZE(scrubrates); i++) {
+ for (i = 0; i < ARRAY_SIZE(scrubrates) - 1; i++) {
/*
* skip scrub rates which aren't recommended
* (see F10 BKDG, F3x58)
@@ -172,12 +175,6 @@ static int __amd64_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate)
if (scrubrates[i].bandwidth <= new_bw)
break;
-
- /*
- * if no suitable bandwidth found, turn off DRAM scrubbing
- * entirely by falling back to the last element in the
- * scrubrates array.
- */
}
scrubval = scrubrates[i].scrubval;
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c
index f6cf448..240966b 100644
--- a/drivers/edac/i7core_edac.c
+++ b/drivers/edac/i7core_edac.c
@@ -1842,11 +1842,9 @@ static int i7core_mce_check_error(void *priv, struct mce *mce)
if (mce->bank != 8)
return 0;
-#ifdef CONFIG_SMP
/* Only handle if it is the right mc controller */
if (cpu_data(mce->cpu).phys_proc_id != pvt->i7core_dev->socket)
return 0;
-#endif
smp_rmb();
if ((pvt->mce_out + 1) % MCE_LOG_LEN == pvt->mce_in) {
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c
index 4799393..b97d4f0 100644
--- a/drivers/firewire/core-cdev.c
+++ b/drivers/firewire/core-cdev.c
@@ -471,8 +471,8 @@ static int ioctl_get_info(struct client *client, union ioctl_arg *arg)
client->bus_reset_closure = a->bus_reset_closure;
if (a->bus_reset != 0) {
fill_bus_reset_event(&bus_reset, client);
- ret = copy_to_user(u64_to_uptr(a->bus_reset),
- &bus_reset, sizeof(bus_reset));
+ /* unaligned size of bus_reset is 36 bytes */
+ ret = copy_to_user(u64_to_uptr(a->bus_reset), &bus_reset, 36);
}
if (ret == 0 && list_empty(&client->link))
list_add_tail(&client->link, &client->device->client_list);
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
index bcb1126..02a52d1 100644
--- a/drivers/firmware/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -6,6 +6,7 @@
#include <linux/dmi.h>
#include <linux/efi.h>
#include <linux/bootmem.h>
+#include <linux/random.h>
#include <asm/dmi.h>
/*
@@ -111,6 +112,8 @@ static int __init dmi_walk_early(void (*decode)(const struct dmi_header *,
dmi_table(buf, dmi_len, dmi_num, decode, NULL);
+ add_device_randomness(buf, dmi_len);
+
dmi_iounmap(buf, dmi_len);
return 0;
}
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index e27d56c..6871ed3 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -400,12 +400,23 @@ efivar_attr_read(struct efivar_entry *entry, char *buf)
if (status != EFI_SUCCESS)
return -EIO;
- if (var->Attributes & 0x1)
+ if (var->Attributes & EFI_VARIABLE_NON_VOLATILE)
str += sprintf(str, "EFI_VARIABLE_NON_VOLATILE\n");
- if (var->Attributes & 0x2)
+ if (var->Attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS)
str += sprintf(str, "EFI_VARIABLE_BOOTSERVICE_ACCESS\n");
- if (var->Attributes & 0x4)
+ if (var->Attributes & EFI_VARIABLE_RUNTIME_ACCESS)
str += sprintf(str, "EFI_VARIABLE_RUNTIME_ACCESS\n");
+ if (var->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD)
+ str += sprintf(str, "EFI_VARIABLE_HARDWARE_ERROR_RECORD\n");
+ if (var->Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS)
+ str += sprintf(str,
+ "EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS\n");
+ if (var->Attributes &
+ EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)
+ str += sprintf(str,
+ "EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS\n");
+ if (var->Attributes & EFI_VARIABLE_APPEND_WRITE)
+ str += sprintf(str, "EFI_VARIABLE_APPEND_WRITE\n");
return str - buf;
}
diff --git a/drivers/firmware/pcdp.c b/drivers/firmware/pcdp.c
index 51e0e2d..a330492 100644
--- a/drivers/firmware/pcdp.c
+++ b/drivers/firmware/pcdp.c
@@ -95,7 +95,7 @@ efi_setup_pcdp_console(char *cmdline)
if (efi.hcdp == EFI_INVALID_TABLE_ADDR)
return -ENODEV;
- pcdp = ioremap(efi.hcdp, 4096);
+ pcdp = early_ioremap(efi.hcdp, 4096);
printk(KERN_INFO "PCDP: v%d at 0x%lx\n", pcdp->rev, efi.hcdp);
if (strstr(cmdline, "console=hcdp")) {
@@ -131,6 +131,6 @@ efi_setup_pcdp_console(char *cmdline)
}
out:
- iounmap(pcdp);
+ early_iounmap(pcdp, 4096);
return rc;
}
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 2967002..80ccce9 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -350,18 +350,19 @@ config GPIO_LANGWELL
Say Y here to support Intel Langwell/Penwell GPIO.
config GPIO_PCH
- tristate "Intel EG20T PCH / OKI SEMICONDUCTOR ML7223 IOH GPIO"
+ tristate "Intel EG20T PCH/LAPIS Semiconductor IOH(ML7223/ML7831) GPIO"
depends on PCI && X86
help
This driver is for PCH(Platform controller Hub) GPIO of Intel Topcliff
which is an IOH(Input/Output Hub) for x86 embedded processor.
This driver can access PCH GPIO device.
- This driver also can be used for OKI SEMICONDUCTOR IOH(Input/
- Output Hub), ML7223.
+ This driver also can be used for LAPIS Semiconductor IOH(Input/
+ Output Hub), ML7223 and ML7831.
ML7223 IOH is for MP(Media Phone) use.
- ML7223 is companion chip for Intel Atom E6xx series.
- ML7223 is completely compatible for Intel EG20T PCH.
+ ML7831 IOH is for general purpose use.
+ ML7223/ML7831 is companion chip for Intel Atom E6xx series.
+ ML7223/ML7831 is completely compatible for Intel EG20T PCH.
config GPIO_ML_IOH
tristate "OKI SEMICONDUCTOR ML7213 IOH GPIO support"
diff --git a/drivers/gpio/gpio-s5pv210.c b/drivers/gpio/gpio-s5pv210.c
index 1ba20a7..955a0f5 100644
--- a/drivers/gpio/gpio-s5pv210.c
+++ b/drivers/gpio/gpio-s5pv210.c
@@ -14,6 +14,7 @@
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/gpio.h>
+#include <linux/module.h>
#include <plat/gpio-core.h>
#include <plat/gpio-cfg.h>
#include <plat/gpio-cfg-helpers.h>
@@ -222,6 +223,174 @@ static struct s3c_gpio_chip s5pv210_gpio_4bit[] = {
.label = "MP05",
},
}, {
+ .config = &gpio_cfg_noint,
+ .chip = {
+ .base = S5PV210_MP06(0),
+ .ngpio = S5PV210_GPIO_MP06_NR,
+ .label = "MP06",
+ },
+ }, {
+ .config = &gpio_cfg_noint,
+ .chip = {
+ .base = S5PV210_MP07(0),
+ .ngpio = S5PV210_GPIO_MP07_NR,
+ .label = "MP07",
+ },
+ }, {
+ .config = &gpio_cfg_noint,
+ .chip = {
+ .base = S5PV210_MP10(0),
+ .ngpio = S5PV210_GPIO_MP10_NR,
+ .label = "MP10",
+ },
+ }, {
+ .config = &gpio_cfg_noint,
+ .chip = {
+ .base = S5PV210_MP11(0),
+ .ngpio = S5PV210_GPIO_MP11_NR,
+ .label = "MP11",
+ },
+ }, {
+ .config = &gpio_cfg_noint,
+ .chip = {
+ .base = S5PV210_MP12(0),
+ .ngpio = S5PV210_GPIO_MP12_NR,
+ .label = "MP12",
+ },
+ }, {
+ .config = &gpio_cfg_noint,
+ .chip = {
+ .base = S5PV210_MP13(0),
+ .ngpio = S5PV210_GPIO_MP13_NR,
+ .label = "MP13",
+ },
+ }, {
+ .config = &gpio_cfg_noint,
+ .chip = {
+ .base = S5PV210_MP14(0),
+ .ngpio = S5PV210_GPIO_MP14_NR,
+ .label = "MP14",
+ },
+ }, {
+ .config = &gpio_cfg_noint,
+ .chip = {
+ .base = S5PV210_MP15(0),
+ .ngpio = S5PV210_GPIO_MP15_NR,
+ .label = "MP15",
+ },
+ }, {
+ .config = &gpio_cfg_noint,
+ .chip = {
+ .base = S5PV210_MP16(0),
+ .ngpio = S5PV210_GPIO_MP16_NR,
+ .label = "MP16",
+ },
+ }, {
+ .config = &gpio_cfg_noint,
+ .chip = {
+ .base = S5PV210_MP17(0),
+ .ngpio = S5PV210_GPIO_MP17_NR,
+ .label = "MP17",
+ },
+ }, {
+ .config = &gpio_cfg_noint,
+ .chip = {
+ .base = S5PV210_MP18(0),
+ .ngpio = S5PV210_GPIO_MP18_NR,
+ .label = "MP18",
+ },
+ }, {
+ .config = &gpio_cfg_noint,
+ .chip = {
+ .base = S5PV210_MP20(0),
+ .ngpio = S5PV210_GPIO_MP20_NR,
+ .label = "MP20",
+ },
+ }, {
+ .config = &gpio_cfg_noint,
+ .chip = {
+ .base = S5PV210_MP21(0),
+ .ngpio = S5PV210_GPIO_MP21_NR,
+ .label = "MP21",
+ },
+ }, {
+ .config = &gpio_cfg_noint,
+ .chip = {
+ .base = S5PV210_MP22(0),
+ .ngpio = S5PV210_GPIO_MP22_NR,
+ .label = "MP22",
+ },
+ }, {
+ .config = &gpio_cfg_noint,
+ .chip = {
+ .base = S5PV210_MP23(0),
+ .ngpio = S5PV210_GPIO_MP23_NR,
+ .label = "MP23",
+ },
+ }, {
+ .config = &gpio_cfg_noint,
+ .chip = {
+ .base = S5PV210_MP24(0),
+ .ngpio = S5PV210_GPIO_MP24_NR,
+ .label = "MP24",
+ },
+ }, {
+ .config = &gpio_cfg_noint,
+ .chip = {
+ .base = S5PV210_MP25(0),
+ .ngpio = S5PV210_GPIO_MP25_NR,
+ .label = "MP25",
+ },
+ }, {
+ .config = &gpio_cfg_noint,
+ .chip = {
+ .base = S5PV210_MP26(0),
+ .ngpio = S5PV210_GPIO_MP26_NR,
+ .label = "MP26",
+ },
+ }, {
+ .config = &gpio_cfg_noint,
+ .chip = {
+ .base = S5PV210_MP27(0),
+ .ngpio = S5PV210_GPIO_MP27_NR,
+ .label = "MP27",
+ },
+ }, {
+ .config = &gpio_cfg_noint,
+ .chip = {
+ .base = S5PV210_MP28(0),
+ .ngpio = S5PV210_GPIO_MP28_NR,
+ .label = "MP28",
+ },
+ }, {
+ .config = &gpio_cfg_noint,
+ .chip = {
+ .base = S5PV210_ETC0(0),
+ .ngpio = S5PV210_GPIO_ETC0_NR,
+ .label = "ETC0",
+ },
+ }, {
+ .config = &gpio_cfg_noint,
+ .chip = {
+ .base = S5PV210_ETC1(0),
+ .ngpio = S5PV210_GPIO_ETC1_NR,
+ .label = "ETC1",
+ },
+ }, {
+ .config = &gpio_cfg_noint,
+ .chip = {
+ .base = S5PV210_ETC2(0),
+ .ngpio = S5PV210_GPIO_ETC2_NR,
+ .label = "ETC2",
+ },
+ }, {
+ .config = &gpio_cfg_noint,
+ .chip = {
+ .base = S5PV210_ETC4(0),
+ .ngpio = S5PV210_GPIO_ETC4_NR,
+ .label = "ETC4",
+ },
+ }, {
.base = (S5P_VA_GPIO + 0xC00),
.config = &gpio_cfg_noint,
.irq_base = IRQ_EINT(0),
@@ -264,7 +433,180 @@ static struct s3c_gpio_chip s5pv210_gpio_4bit[] = {
},
};
-static __init int s5pv210_gpiolib_init(void)
+/* S5PV210 machine dependent GPIO help function */
+int s3c_gpio_slp_cfgpin(unsigned int pin, unsigned int config)
+{
+ struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
+ void __iomem *reg;
+ unsigned long flags;
+ int offset;
+ u32 con;
+ int shift;
+
+ if (!chip)
+ return -EINVAL;
+
+ if ((pin <= S5PV210_GPH3(7)) && (pin >= S5PV210_GPH0(0)))
+ return -EINVAL;
+
+ if (config > S3C_GPIO_SLP_PREV)
+ return -EINVAL;
+
+ reg = chip->base + 0x10;
+
+ offset = pin - chip->chip.base;
+ shift = offset * 2;
+
+ local_irq_save(flags);
+
+ con = __raw_readl(reg);
+ con &= ~(3 << shift);
+ con |= config << shift;
+ __raw_writel(con, reg);
+
+ local_irq_restore(flags);
+ return 0;
+}
+
+s3c_gpio_pull_t s3c_gpio_get_slp_cfgpin(unsigned int pin)
+{
+ struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
+ void __iomem *reg;
+ unsigned long flags;
+ int offset;
+ u32 con;
+ int shift;
+
+ if (!chip)
+ return -EINVAL;
+
+ if ((pin <= S5PV210_GPH3(7)) && (pin >= S5PV210_GPH0(0)))
+ return -EINVAL;
+
+ reg = chip->base + 0x10;
+
+ offset = pin - chip->chip.base;
+ shift = offset * 2;
+
+ local_irq_save(flags);
+
+ con = __raw_readl(reg);
+ con >>= shift;
+ con &= 0x3;
+
+ local_irq_restore(flags);
+
+ return (__force s3c_gpio_pull_t)con;
+}
+
+int s3c_gpio_slp_setpull_updown(unsigned int pin, unsigned int config)
+{
+ struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
+ void __iomem *reg;
+ unsigned long flags;
+ int offset;
+ u32 con;
+ int shift;
+
+ if (!chip)
+ return -EINVAL;
+
+ if ((pin <= S5PV210_GPH3(7)) && (pin >= S5PV210_GPH0(0)))
+ return -EINVAL;
+
+ if (config > S3C_GPIO_PULL_UP)
+ return -EINVAL;
+ reg = chip->base + 0x14;
+
+ offset = pin - chip->chip.base;
+ shift = offset * 2;
+
+ local_irq_save(flags);
+
+ con = __raw_readl(reg);
+ con &= ~(3 << shift);
+ con |= config << shift;
+ __raw_writel(con, reg);
+
+ local_irq_restore(flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(s3c_gpio_slp_setpull_updown);
+
+int s3c_gpio_set_drvstrength(unsigned int pin, unsigned int config)
+{
+ struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
+ void __iomem *reg;
+ unsigned long flags;
+ int offset;
+ u32 con;
+ int shift;
+
+ if (!chip)
+ return -EINVAL;
+
+ if (config > S3C_GPIO_DRVSTR_4X)
+ return -EINVAL;
+
+ reg = chip->base + 0x0c;
+
+ offset = pin - chip->chip.base;
+ shift = offset * 2;
+
+ local_irq_save(flags);
+
+ con = __raw_readl(reg);
+ con &= ~(3 << shift);
+ con |= config << shift;
+
+ __raw_writel(con, reg);
+#ifdef S5PC11X_ALIVEGPIO_STORE
+ con = __raw_readl(reg);
+#endif
+
+ local_irq_restore(flags);
+
+ return 0;
+}
+
+int s3c_gpio_set_slewrate(unsigned int pin, unsigned int config)
+{
+ struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
+ void __iomem *reg;
+ unsigned long flags;
+ int offset;
+ u32 con;
+ int shift;
+
+ if (!chip)
+ return -EINVAL;
+
+ if (config > S3C_GPIO_SLEWRATE_SLOW)
+ return -EINVAL;
+
+ reg = chip->base + 0x0c;
+
+ offset = pin - chip->chip.base;
+ shift = offset;
+
+ local_irq_save(flags);
+
+ con = __raw_readl(reg);
+ con &= ~(1 << shift);
+ con |= config << shift;
+
+ __raw_writel(con, reg);
+#ifdef S5PC11X_ALIVEGPIO_STORE
+ con = __raw_readl(reg);
+#endif
+
+ local_irq_restore(flags);
+
+ return 0;
+}
+
+__init int s5pv210_gpiolib_init(void)
{
struct s3c_gpio_chip *chip = s5pv210_gpio_4bit;
int nr_chips = ARRAY_SIZE(s5pv210_gpio_4bit);
@@ -285,4 +627,3 @@ static __init int s5pv210_gpiolib_init(void)
return 0;
}
-core_initcall(s5pv210_gpiolib_init);
diff --git a/drivers/gpio/pch_gpio.c b/drivers/gpio/pch_gpio.c
index 36919e7..de26978 100644
--- a/drivers/gpio/pch_gpio.c
+++ b/drivers/gpio/pch_gpio.c
@@ -287,6 +287,7 @@ static int pch_gpio_resume(struct pci_dev *pdev)
static DEFINE_PCI_DEVICE_TABLE(pch_gpio_pcidev_id) = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) },
{ PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8014) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8803) },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, pch_gpio_pcidev_id);
diff --git a/drivers/gpu/Makefile b/drivers/gpu/Makefile
index ca2d3b3..9a10381 100644
--- a/drivers/gpu/Makefile
+++ b/drivers/gpu/Makefile
@@ -1 +1,3 @@
obj-y += drm/ vga/ stub/ ion/
+
+obj-$(CONFIG_PVR_SGX) += pvr/
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 1bbb85b..a303b61 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -584,7 +584,7 @@ static bool
drm_monitor_supports_rb(struct edid *edid)
{
if (edid->revision >= 4) {
- bool ret;
+ bool ret = false;
drm_for_each_detailed_block((u8 *)edid, is_rb, &ret);
return ret;
}
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 997db7f..d05f03c 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -422,14 +422,11 @@ static void gen6_pm_rps_work(struct work_struct *work)
mutex_unlock(&dev_priv->dev->struct_mutex);
}
-static void pch_irq_handler(struct drm_device *dev)
+static void pch_irq_handler(struct drm_device *dev, u32 pch_iir)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- u32 pch_iir;
int pipe;
- pch_iir = I915_READ(SDEIIR);
-
if (pch_iir & SDE_AUDIO_POWER_MASK)
DRM_DEBUG_DRIVER("PCH audio power change on port %d\n",
(pch_iir & SDE_AUDIO_POWER_MASK) >>
@@ -527,7 +524,7 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS)
if (de_iir & DE_PCH_EVENT_IVB) {
if (pch_iir & SDE_HOTPLUG_MASK_CPT)
queue_work(dev_priv->wq, &dev_priv->hotplug_work);
- pch_irq_handler(dev);
+ pch_irq_handler(dev, pch_iir);
}
if (pm_iir & GEN6_PM_DEFERRED_EVENTS) {
@@ -626,7 +623,7 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS)
if (de_iir & DE_PCH_EVENT) {
if (pch_iir & hotplug_mask)
queue_work(dev_priv->wq, &dev_priv->hotplug_work);
- pch_irq_handler(dev);
+ pch_irq_handler(dev, pch_iir);
}
if (de_iir & DE_PCU_EVENT) {
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index b05c256..557e007 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -537,6 +537,21 @@
#define GEN6_BSD_RNCID 0x12198
+#define GEN7_FF_THREAD_MODE 0x20a0
+#define GEN7_FF_SCHED_MASK 0x0077070
+#define GEN7_FF_TS_SCHED_HS1 (0x5<<16)
+#define GEN7_FF_TS_SCHED_HS0 (0x3<<16)
+#define GEN7_FF_TS_SCHED_LOAD_BALANCE (0x1<<16)
+#define GEN7_FF_TS_SCHED_HW (0x0<<16) /* Default */
+#define GEN7_FF_VS_SCHED_HS1 (0x5<<12)
+#define GEN7_FF_VS_SCHED_HS0 (0x3<<12)
+#define GEN7_FF_VS_SCHED_LOAD_BALANCE (0x1<<12) /* Default */
+#define GEN7_FF_VS_SCHED_HW (0x0<<12)
+#define GEN7_FF_DS_SCHED_HS1 (0x5<<4)
+#define GEN7_FF_DS_SCHED_HS0 (0x3<<4)
+#define GEN7_FF_DS_SCHED_LOAD_BALANCE (0x1<<4) /* Default */
+#define GEN7_FF_DS_SCHED_HW (0x0<<4)
+
/*
* Framebuffer compression (915+ only)
*/
@@ -3098,6 +3113,11 @@
#define TRANS_6BPC (2<<5)
#define TRANS_12BPC (3<<5)
+#define _TRANSA_CHICKEN2 0xf0064
+#define _TRANSB_CHICKEN2 0xf1064
+#define TRANS_CHICKEN2(pipe) _PIPE(pipe, _TRANSA_CHICKEN2, _TRANSB_CHICKEN2)
+#define TRANS_AUTOTRAIN_GEN_STALL_DIS (1<<31)
+
#define SOUTH_CHICKEN2 0xc2004
#define DPLS_EDP_PPS_FIX_DIS (1<<0)
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
index bc7dcaa..5ad0b51 100644
--- a/drivers/gpu/drm/i915/i915_suspend.c
+++ b/drivers/gpu/drm/i915/i915_suspend.c
@@ -739,8 +739,11 @@ static void i915_restore_display(struct drm_device *dev)
if (HAS_PCH_SPLIT(dev)) {
I915_WRITE(BLC_PWM_PCH_CTL1, dev_priv->saveBLC_PWM_CTL);
I915_WRITE(BLC_PWM_PCH_CTL2, dev_priv->saveBLC_PWM_CTL2);
- I915_WRITE(BLC_PWM_CPU_CTL, dev_priv->saveBLC_CPU_PWM_CTL);
+ /* NOTE: BLC_PWM_CPU_CTL must be written after BLC_PWM_CPU_CTL2;
+ * otherwise we get blank eDP screen after S3 on some machines
+ */
I915_WRITE(BLC_PWM_CPU_CTL2, dev_priv->saveBLC_CPU_PWM_CTL2);
+ I915_WRITE(BLC_PWM_CPU_CTL, dev_priv->saveBLC_CPU_PWM_CTL);
I915_WRITE(PCH_PP_ON_DELAYS, dev_priv->savePP_ON_DELAYS);
I915_WRITE(PCH_PP_OFF_DELAYS, dev_priv->savePP_OFF_DELAYS);
I915_WRITE(PCH_PP_DIVISOR, dev_priv->savePP_DIVISOR);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index f150a15..36d76989 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6579,10 +6579,11 @@ static void intel_sanitize_modesetting(struct drm_device *dev,
{
struct drm_i915_private *dev_priv = dev->dev_private;
u32 reg, val;
+ int i;
/* Clear any frame start delays used for debugging left by the BIOS */
- for_each_pipe(pipe) {
- reg = PIPECONF(pipe);
+ for_each_pipe(i) {
+ reg = PIPECONF(i);
I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
}
@@ -7451,6 +7452,18 @@ static void gen6_init_clock_gating(struct drm_device *dev)
DISPPLANE_TRICKLE_FEED_DISABLE);
}
+static void gen7_setup_fixed_func_scheduler(struct drm_i915_private *dev_priv)
+{
+ uint32_t reg = I915_READ(GEN7_FF_THREAD_MODE);
+
+ reg &= ~GEN7_FF_SCHED_MASK;
+ reg |= GEN7_FF_TS_SCHED_HW;
+ reg |= GEN7_FF_VS_SCHED_HW;
+ reg |= GEN7_FF_DS_SCHED_HW;
+
+ I915_WRITE(GEN7_FF_THREAD_MODE, reg);
+}
+
static void ivybridge_init_clock_gating(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -7571,6 +7584,7 @@ static void ibx_init_clock_gating(struct drm_device *dev)
static void cpt_init_clock_gating(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
+ int pipe;
/*
* On Ibex Peak and Cougar Point, we need to disable clock
@@ -7580,6 +7594,9 @@ static void cpt_init_clock_gating(struct drm_device *dev)
I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE);
I915_WRITE(SOUTH_CHICKEN2, I915_READ(SOUTH_CHICKEN2) |
DPLS_EDP_PPS_FIX_DIS);
+ /* Without this, mode sets may fail silently on FDI */
+ for_each_pipe(pipe)
+ I915_WRITE(TRANS_CHICKEN2(pipe), TRANS_AUTOTRAIN_GEN_STALL_DIS);
}
static void ironlake_teardown_rc6(struct drm_device *dev)
@@ -7597,6 +7614,8 @@ static void ironlake_teardown_rc6(struct drm_device *dev)
drm_gem_object_unreference(&dev_priv->pwrctx->base);
dev_priv->pwrctx = NULL;
}
+
+ gen7_setup_fixed_func_scheduler(dev_priv);
}
static void ironlake_disable_rc6(struct drm_device *dev)
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 236bbe0..918bac8 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -160,7 +160,7 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
u32 temp;
u32 enable_bits = SDVO_ENABLE;
- if (intel_hdmi->has_audio)
+ if (intel_hdmi->has_audio || mode != DRM_MODE_DPMS_ON)
enable_bits |= SDVO_AUDIO_ENABLE;
temp = I915_READ(intel_hdmi->sdvox_reg);
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index ff85a91..7adba11 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -751,6 +751,14 @@ static const struct dmi_system_id intel_no_lvds[] = {
DMI_MATCH(DMI_BOARD_NAME, "MS-7469"),
},
},
+ {
+ .callback = intel_no_lvds_dmi_callback,
+ .ident = "ZOTAC ZBOXSD-ID12/ID13",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ZOTAC"),
+ DMI_MATCH(DMI_BOARD_NAME, "ZBOXSD-ID12/ID13"),
+ },
+ },
{ } /* terminating entry */
};
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 2d6039b..3bd85f7 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -150,8 +150,6 @@ static int init_ring_common(struct intel_ring_buffer *ring)
I915_WRITE_HEAD(ring, 0);
ring->write_tail(ring, 0);
- /* Initialize the ring. */
- I915_WRITE_START(ring, obj->gtt_offset);
head = I915_READ_HEAD(ring) & HEAD_ADDR;
/* G45 ring initialization fails to reset head to zero */
@@ -177,6 +175,11 @@ static int init_ring_common(struct intel_ring_buffer *ring)
}
}
+ /* Initialize the ring. This must happen _after_ we've cleared the ring
+ * registers with the above sequence (the readback of the HEAD registers
+ * also enforces ordering), otherwise the hw might lose the new ring
+ * register values. */
+ I915_WRITE_START(ring, obj->gtt_offset);
I915_WRITE_CTL(ring,
((ring->size - PAGE_SIZE) & RING_NR_PAGES)
| RING_REPORT_64K | RING_VALID);
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 06bc46e..c901060 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -762,10 +762,12 @@ static void intel_sdvo_get_dtd_from_mode(struct intel_sdvo_dtd *dtd,
((v_sync_len & 0x30) >> 4);
dtd->part2.dtd_flags = 0x18;
+ if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+ dtd->part2.dtd_flags |= DTD_FLAG_INTERLACE;
if (mode->flags & DRM_MODE_FLAG_PHSYNC)
- dtd->part2.dtd_flags |= 0x2;
+ dtd->part2.dtd_flags |= DTD_FLAG_HSYNC_POSITIVE;
if (mode->flags & DRM_MODE_FLAG_PVSYNC)
- dtd->part2.dtd_flags |= 0x4;
+ dtd->part2.dtd_flags |= DTD_FLAG_VSYNC_POSITIVE;
dtd->part2.sdvo_flags = 0;
dtd->part2.v_sync_off_high = v_sync_offset & 0xc0;
@@ -799,9 +801,11 @@ static void intel_sdvo_get_mode_from_dtd(struct drm_display_mode * mode,
mode->clock = dtd->part1.clock * 10;
mode->flags &= ~(DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC);
- if (dtd->part2.dtd_flags & 0x2)
+ if (dtd->part2.dtd_flags & DTD_FLAG_INTERLACE)
+ mode->flags |= DRM_MODE_FLAG_INTERLACE;
+ if (dtd->part2.dtd_flags & DTD_FLAG_HSYNC_POSITIVE)
mode->flags |= DRM_MODE_FLAG_PHSYNC;
- if (dtd->part2.dtd_flags & 0x4)
+ if (dtd->part2.dtd_flags & DTD_FLAG_VSYNC_POSITIVE)
mode->flags |= DRM_MODE_FLAG_PVSYNC;
}
diff --git a/drivers/gpu/drm/i915/intel_sdvo_regs.h b/drivers/gpu/drm/i915/intel_sdvo_regs.h
index 4f4e23b..c5c8ddf 100644
--- a/drivers/gpu/drm/i915/intel_sdvo_regs.h
+++ b/drivers/gpu/drm/i915/intel_sdvo_regs.h
@@ -61,6 +61,11 @@ struct intel_sdvo_caps {
u16 output_flags;
} __attribute__((packed));
+/* Note: SDVO detailed timing flags match EDID misc flags. */
+#define DTD_FLAG_HSYNC_POSITIVE (1 << 1)
+#define DTD_FLAG_VSYNC_POSITIVE (1 << 2)
+#define DTD_FLAG_INTERLACE (1 << 7)
+
/** This matches the EDID DTD structure, more or less */
struct intel_sdvo_dtd {
struct {
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index f57b08b..2136e6b 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -1301,6 +1301,11 @@ intel_tv_detect_type (struct intel_tv *intel_tv,
I915_WRITE(TV_DAC, save_tv_dac & ~TVDAC_STATE_CHG_EN);
I915_WRITE(TV_CTL, save_tv_ctl);
+ POSTING_READ(TV_CTL);
+
+ /* For unknown reasons the hw barfs if we don't do this vblank wait. */
+ intel_wait_for_vblank(intel_tv->base.base.dev,
+ to_intel_crtc(intel_tv->base.base.crtc)->pipe);
/* Restore interrupt config */
if (connector->polled & DRM_CONNECTOR_POLL_HPD) {
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index 2ad49cb..5fb98de 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -1075,7 +1075,7 @@ nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo)
nvbo->placement.fpfn = 0;
nvbo->placement.lpfn = dev_priv->fb_mappable_pages;
- nouveau_bo_placement_set(nvbo, TTM_PL_VRAM, 0);
+ nouveau_bo_placement_set(nvbo, TTM_PL_FLAG_VRAM, 0);
return nouveau_bo_validate(nvbo, false, true, false);
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
index 39aee6d..ea71f78 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
@@ -487,7 +487,7 @@ int nouveau_fbcon_init(struct drm_device *dev)
nfbdev->helper.funcs = &nouveau_fbcon_helper_funcs;
ret = drm_fb_helper_init(dev, &nfbdev->helper,
- nv_two_heads(dev) ? 2 : 1, 4);
+ dev->mode_config.num_crtc, 4);
if (ret) {
kfree(nfbdev);
return ret;
diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c
index 3b77ad6..efc2b21 100644
--- a/drivers/gpu/drm/radeon/atombios_dp.c
+++ b/drivers/gpu/drm/radeon/atombios_dp.c
@@ -22,6 +22,7 @@
*
* Authors: Dave Airlie
* Alex Deucher
+ * Jerome Glisse
*/
#include "drmP.h"
#include "radeon_drm.h"
@@ -624,7 +625,6 @@ static bool radeon_dp_get_link_status(struct radeon_connector *radeon_connector,
ret = radeon_dp_aux_native_read(radeon_connector, DP_LANE0_1_STATUS,
link_status, DP_LINK_STATUS_SIZE, 100);
if (ret <= 0) {
- DRM_ERROR("displayport link status failed\n");
return false;
}
@@ -797,8 +797,10 @@ static int radeon_dp_link_train_cr(struct radeon_dp_link_train_info *dp_info)
else
mdelay(dp_info->rd_interval * 4);
- if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status))
+ if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) {
+ DRM_ERROR("displayport link status failed\n");
break;
+ }
if (dp_clock_recovery_ok(dp_info->link_status, dp_info->dp_lane_count)) {
clock_recovery = true;
@@ -860,8 +862,10 @@ static int radeon_dp_link_train_ce(struct radeon_dp_link_train_info *dp_info)
else
mdelay(dp_info->rd_interval * 4);
- if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status))
+ if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) {
+ DRM_ERROR("displayport link status failed\n");
break;
+ }
if (dp_channel_eq_ok(dp_info->link_status, dp_info->dp_lane_count)) {
channel_eq = true;
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index fe052c6..314e217 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -926,6 +926,11 @@ int evergreen_pcie_gart_enable(struct radeon_device *rdev)
WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp);
WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp);
WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp);
+ if ((rdev->family == CHIP_JUNIPER) ||
+ (rdev->family == CHIP_CYPRESS) ||
+ (rdev->family == CHIP_HEMLOCK) ||
+ (rdev->family == CHIP_BARTS))
+ WREG32(MC_VM_MD_L1_TLB3_CNTL, tmp);
}
WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp);
WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp);
@@ -1014,24 +1019,8 @@ void evergreen_agp_enable(struct radeon_device *rdev)
void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save)
{
- save->vga_control[0] = RREG32(D1VGA_CONTROL);
- save->vga_control[1] = RREG32(D2VGA_CONTROL);
save->vga_render_control = RREG32(VGA_RENDER_CONTROL);
save->vga_hdp_control = RREG32(VGA_HDP_CONTROL);
- save->crtc_control[0] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET);
- save->crtc_control[1] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET);
- if (rdev->num_crtc >= 4) {
- save->vga_control[2] = RREG32(EVERGREEN_D3VGA_CONTROL);
- save->vga_control[3] = RREG32(EVERGREEN_D4VGA_CONTROL);
- save->crtc_control[2] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET);
- save->crtc_control[3] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET);
- }
- if (rdev->num_crtc >= 6) {
- save->vga_control[4] = RREG32(EVERGREEN_D5VGA_CONTROL);
- save->vga_control[5] = RREG32(EVERGREEN_D6VGA_CONTROL);
- save->crtc_control[4] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET);
- save->crtc_control[5] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET);
- }
/* Stop all video */
WREG32(VGA_RENDER_CONTROL, 0);
@@ -1142,47 +1131,6 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s
/* Unlock host access */
WREG32(VGA_HDP_CONTROL, save->vga_hdp_control);
mdelay(1);
- /* Restore video state */
- WREG32(D1VGA_CONTROL, save->vga_control[0]);
- WREG32(D2VGA_CONTROL, save->vga_control[1]);
- if (rdev->num_crtc >= 4) {
- WREG32(EVERGREEN_D3VGA_CONTROL, save->vga_control[2]);
- WREG32(EVERGREEN_D4VGA_CONTROL, save->vga_control[3]);
- }
- if (rdev->num_crtc >= 6) {
- WREG32(EVERGREEN_D5VGA_CONTROL, save->vga_control[4]);
- WREG32(EVERGREEN_D6VGA_CONTROL, save->vga_control[5]);
- }
- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1);
- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1);
- if (rdev->num_crtc >= 4) {
- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1);
- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1);
- }
- if (rdev->num_crtc >= 6) {
- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1);
- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1);
- }
- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, save->crtc_control[0]);
- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, save->crtc_control[1]);
- if (rdev->num_crtc >= 4) {
- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, save->crtc_control[2]);
- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, save->crtc_control[3]);
- }
- if (rdev->num_crtc >= 6) {
- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, save->crtc_control[4]);
- WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, save->crtc_control[5]);
- }
- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);
- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0);
- if (rdev->num_crtc >= 4) {
- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
- }
- if (rdev->num_crtc >= 6) {
- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);
- WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
- }
WREG32(VGA_RENDER_CONTROL, save->vga_render_control);
}
@@ -2064,9 +2012,9 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
WREG32(CC_SYS_RB_BACKEND_DISABLE, rb);
WREG32(GC_USER_RB_BACKEND_DISABLE, rb);
WREG32(CC_GC_SHADER_PIPE_CONFIG, sp);
- }
+ }
- grbm_gfx_index |= SE_BROADCAST_WRITES;
+ grbm_gfx_index = INSTANCE_BROADCAST_WRITES | SE_BROADCAST_WRITES;
WREG32(GRBM_GFX_INDEX, grbm_gfx_index);
WREG32(RLC_GFX_INDEX, grbm_gfx_index);
diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h
index b7b2714..6078ae4 100644
--- a/drivers/gpu/drm/radeon/evergreend.h
+++ b/drivers/gpu/drm/radeon/evergreend.h
@@ -230,6 +230,7 @@
#define MC_VM_MD_L1_TLB0_CNTL 0x2654
#define MC_VM_MD_L1_TLB1_CNTL 0x2658
#define MC_VM_MD_L1_TLB2_CNTL 0x265C
+#define MC_VM_MD_L1_TLB3_CNTL 0x2698
#define FUS_MC_VM_MD_L1_TLB0_CNTL 0x265C
#define FUS_MC_VM_MD_L1_TLB1_CNTL 0x2660
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h
index 3dedaa0..4d81e96 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.h
+++ b/drivers/gpu/drm/radeon/radeon_asic.h
@@ -253,13 +253,10 @@ void rs690_line_buffer_adjust(struct radeon_device *rdev,
* rv515
*/
struct rv515_mc_save {
- u32 d1vga_control;
- u32 d2vga_control;
u32 vga_render_control;
u32 vga_hdp_control;
- u32 d1crtc_control;
- u32 d2crtc_control;
};
+
int rv515_init(struct radeon_device *rdev);
void rv515_fini(struct radeon_device *rdev);
uint32_t rv515_mc_rreg(struct radeon_device *rdev, uint32_t reg);
@@ -387,11 +384,10 @@ void r700_cp_fini(struct radeon_device *rdev);
* evergreen
*/
struct evergreen_mc_save {
- u32 vga_control[6];
u32 vga_render_control;
u32 vga_hdp_control;
- u32 crtc_control[6];
};
+
void evergreen_pcie_gart_tlb_flush(struct radeon_device *rdev);
int evergreen_init(struct radeon_device *rdev);
void evergreen_fini(struct radeon_device *rdev);
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index a324564..cee3184 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -480,13 +480,15 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev,
*/
if ((dev->pdev->device == 0x9498) &&
(dev->pdev->subsystem_vendor == 0x1682) &&
- (dev->pdev->subsystem_device == 0x2452)) {
+ (dev->pdev->subsystem_device == 0x2452) &&
+ (i2c_bus->valid == false) &&
+ !(supported_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))) {
struct radeon_device *rdev = dev->dev_private;
*i2c_bus = radeon_lookup_i2c_gpio(rdev, 0x93);
}
/* Fujitsu D3003-S2 board lists DVI-I as DVI-D and VGA */
- if ((dev->pdev->device == 0x9802) &&
+ if (((dev->pdev->device == 0x9802) || (dev->pdev->device == 0x9806)) &&
(dev->pdev->subsystem_vendor == 0x1734) &&
(dev->pdev->subsystem_device == 0x11bd)) {
if (*connector_type == DRM_MODE_CONNECTOR_VGA) {
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index 1f6a0f5..f1a1e8a 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -66,14 +66,33 @@ void radeon_connector_hotplug(struct drm_connector *connector)
/* just deal with DP (not eDP) here. */
if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) {
- int saved_dpms = connector->dpms;
-
- /* Only turn off the display it it's physically disconnected */
- if (!radeon_hpd_sense(rdev, radeon_connector->hpd.hpd))
- drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
- else if (radeon_dp_needs_link_train(radeon_connector))
- drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
- connector->dpms = saved_dpms;
+ struct radeon_connector_atom_dig *dig_connector =
+ radeon_connector->con_priv;
+
+ /* if existing sink type was not DP no need to retrain */
+ if (dig_connector->dp_sink_type != CONNECTOR_OBJECT_ID_DISPLAYPORT)
+ return;
+
+ /* first get sink type as it may be reset after (un)plug */
+ dig_connector->dp_sink_type = radeon_dp_getsinktype(radeon_connector);
+ /* don't do anything if sink is not display port, i.e.,
+ * passive dp->(dvi|hdmi) adaptor
+ */
+ if (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) {
+ int saved_dpms = connector->dpms;
+ /* Only turn off the display if it's physically disconnected */
+ if (!radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) {
+ drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
+ } else if (radeon_dp_needs_link_train(radeon_connector)) {
+ /* set it to OFF so that drm_helper_connector_dpms()
+ * won't return immediately since the current state
+ * is ON at this point.
+ */
+ connector->dpms = DRM_MODE_DPMS_OFF;
+ drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
+ }
+ connector->dpms = saved_dpms;
+ }
}
}
diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c
index 3fb2226..72f749d 100644
--- a/drivers/gpu/drm/radeon/radeon_cursor.c
+++ b/drivers/gpu/drm/radeon/radeon_cursor.c
@@ -257,8 +257,14 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc,
if (!(cursor_end & 0x7f))
w--;
}
- if (w <= 0)
+ if (w <= 0) {
w = 1;
+ cursor_end = x - xorigin + w;
+ if (!(cursor_end & 0x7f)) {
+ x--;
+ WARN_ON_ONCE(x < 0);
+ }
+ }
}
}
diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c
index eb6fe79..1cfe753 100644
--- a/drivers/gpu/drm/radeon/radeon_irq_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c
@@ -143,6 +143,16 @@ static bool radeon_msi_ok(struct radeon_device *rdev)
(rdev->pdev->subsystem_device == 0x01fd))
return true;
+ /* Gateway RS690 only seems to work with MSIs. */
+ if ((rdev->pdev->device == 0x791f) &&
+ (rdev->pdev->subsystem_vendor == 0x107b) &&
+ (rdev->pdev->subsystem_device == 0x0185))
+ return true;
+
+ /* try and enable MSIs by default on all RS690s */
+ if (rdev->family == CHIP_RS690)
+ return true;
+
/* RV515 seems to have MSI issues where it loses
* MSI rearms occasionally. This leads to lockups and freezes.
* disable it by default.
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
index 2f46e0c..3ad3cc6 100644
--- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
+++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
@@ -973,11 +973,7 @@ static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder,
static void radeon_ext_tmds_enc_destroy(struct drm_encoder *encoder)
{
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
- struct radeon_encoder_ext_tmds *tmds = radeon_encoder->enc_priv;
- if (tmds) {
- if (tmds->i2c_bus)
- radeon_i2c_destroy(tmds->i2c_bus);
- }
+ /* don't destroy the i2c bus record here, this will be done in radeon_i2c_fini */
kfree(radeon_encoder->enc_priv);
drm_encoder_cleanup(encoder);
kfree(radeon_encoder);
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c
index 6fabe89..4f88863 100644
--- a/drivers/gpu/drm/radeon/radeon_pm.c
+++ b/drivers/gpu/drm/radeon/radeon_pm.c
@@ -535,7 +535,9 @@ void radeon_pm_suspend(struct radeon_device *rdev)
void radeon_pm_resume(struct radeon_device *rdev)
{
/* set up the default clocks if the MC ucode is loaded */
- if (ASIC_IS_DCE5(rdev) && rdev->mc_fw) {
+ if ((rdev->family >= CHIP_BARTS) &&
+ (rdev->family <= CHIP_CAYMAN) &&
+ rdev->mc_fw) {
if (rdev->pm.default_vddc)
radeon_atom_set_voltage(rdev, rdev->pm.default_vddc,
SET_VOLTAGE_TYPE_ASIC_VDDC);
@@ -590,7 +592,9 @@ int radeon_pm_init(struct radeon_device *rdev)
radeon_pm_print_states(rdev);
radeon_pm_init_profile(rdev);
/* set up the default clocks if the MC ucode is loaded */
- if (ASIC_IS_DCE5(rdev) && rdev->mc_fw) {
+ if ((rdev->family >= CHIP_BARTS) &&
+ (rdev->family <= CHIP_CAYMAN) &&
+ rdev->mc_fw) {
if (rdev->pm.default_vddc)
radeon_atom_set_voltage(rdev, rdev->pm.default_vddc,
SET_VOLTAGE_TYPE_ASIC_VDDC);
diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c
index 6613ee9..d5f45b4 100644
--- a/drivers/gpu/drm/radeon/rv515.c
+++ b/drivers/gpu/drm/radeon/rv515.c
@@ -281,12 +281,8 @@ int rv515_debugfs_ga_info_init(struct radeon_device *rdev)
void rv515_mc_stop(struct radeon_device *rdev, struct rv515_mc_save *save)
{
- save->d1vga_control = RREG32(R_000330_D1VGA_CONTROL);
- save->d2vga_control = RREG32(R_000338_D2VGA_CONTROL);
save->vga_render_control = RREG32(R_000300_VGA_RENDER_CONTROL);
save->vga_hdp_control = RREG32(R_000328_VGA_HDP_CONTROL);
- save->d1crtc_control = RREG32(R_006080_D1CRTC_CONTROL);
- save->d2crtc_control = RREG32(R_006880_D2CRTC_CONTROL);
/* Stop all video */
WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0);
@@ -311,15 +307,6 @@ void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save)
/* Unlock host access */
WREG32(R_000328_VGA_HDP_CONTROL, save->vga_hdp_control);
mdelay(1);
- /* Restore video state */
- WREG32(R_000330_D1VGA_CONTROL, save->d1vga_control);
- WREG32(R_000338_D2VGA_CONTROL, save->d2vga_control);
- WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 1);
- WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 1);
- WREG32(R_006080_D1CRTC_CONTROL, save->d1crtc_control);
- WREG32(R_006880_D2CRTC_CONTROL, save->d2crtc_control);
- WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 0);
- WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0);
WREG32(R_000300_VGA_RENDER_CONTROL, save->vga_render_control);
}
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index 84cf82f..51d20aa 100644
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -151,6 +151,8 @@ int rv770_pcie_gart_enable(struct radeon_device *rdev)
WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp);
WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp);
WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp);
+ if (rdev->family == CHIP_RV740)
+ WREG32(MC_VM_MD_L1_TLB3_CNTL, tmp);
WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp);
WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp);
WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp);
diff --git a/drivers/gpu/drm/radeon/rv770d.h b/drivers/gpu/drm/radeon/rv770d.h
index 79fa588..7538092 100644
--- a/drivers/gpu/drm/radeon/rv770d.h
+++ b/drivers/gpu/drm/radeon/rv770d.h
@@ -174,6 +174,7 @@
#define MC_VM_MD_L1_TLB0_CNTL 0x2654
#define MC_VM_MD_L1_TLB1_CNTL 0x2658
#define MC_VM_MD_L1_TLB2_CNTL 0x265C
+#define MC_VM_MD_L1_TLB3_CNTL 0x2698
#define MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR 0x203C
#define MC_VM_SYSTEM_APERTURE_HIGH_ADDR 0x2038
#define MC_VM_SYSTEM_APERTURE_LOW_ADDR 0x2034
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 81b6850..7632edb 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -1809,6 +1809,7 @@ static int ttm_bo_swapout(struct ttm_mem_shrink *shrink)
spin_unlock(&glob->lru_lock);
(void) ttm_bo_cleanup_refs(bo, false, false, false);
kref_put(&bo->list_kref, ttm_bo_release_list);
+ spin_lock(&glob->lru_lock);
continue;
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 96949b9..8b8c85c 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -147,6 +147,7 @@ static struct pci_device_id vmw_pci_id_list[] = {
{0x15ad, 0x0405, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VMWGFX_CHIP_SVGAII},
{0, 0, 0}
};
+MODULE_DEVICE_TABLE(pci, vmw_pci_id_list);
static int enable_fbdev;
diff --git a/drivers/gpu/pvr/Kconfig b/drivers/gpu/pvr/Kconfig
new file mode 100644
index 0000000..aa6139e
--- /dev/null
+++ b/drivers/gpu/pvr/Kconfig
@@ -0,0 +1,107 @@
+config PVR_SGX
+ tristate "PowerVR SGX support"
+ depends on ARCH_S5PV210
+ help
+ Enable this option to build support for the PowerVR SGX 3D core.
+
+ To compile this driver as a module, choose M here:
+ this will generate two modules, called pvrsrvkm and s3c_lcd.
+
+choice
+ prompt "PowerVR build type"
+ depends on PVR_SGX
+ default PVR_BUILD_RELEASE
+
+config PVR_BUILD_RELEASE
+ bool "Release"
+
+config PVR_BUILD_DEBUG
+ bool "Debug"
+
+endchoice
+
+# Release build debugging options
+
+config PVR_NEED_PVR_DPF
+ bool "Enable debugging messages in release build"
+ depends on PVR_BUILD_RELEASE
+
+config PVR_NEED_PVR_ASSERT
+ bool "Enable assertions in release build"
+ depends on PVR_BUILD_RELEASE
+
+# Debugging options
+
+config PVR_DEBUG_MEMORY
+ bool "Record memory-related debugging information"
+ depends on PVR_BUILD_DEBUG
+ default y
+
+config PVR_DEBUG_BRIDGE_KM
+ bool "Collect bridge statistics"
+ depends on PVR_BUILD_DEBUG
+ default y
+
+config PVR_DEBUG_TRACE_BRIDGE_KM
+ bool "Trace bridge calls"
+ depends on PVR_DEBUG_BRIDGE_KM
+ default n
+
+config PVR_DEBUG_BRIDGE_KM_DISPATCH_TABLE
+ bool "Dump bridge dispatch table entries"
+ depends on PVR_BUILD_DEBUG
+ default n
+
+
+#
+# General options
+#
+
+config PVR_PERCONTEXT_PB
+ bool "Per-context parameter buffer (recommended)"
+ depends on PVR_SGX
+ default y
+
+config PVR_ACTIVE_POWER_MANAGEMENT
+ bool "Support for active power management (recommended)"
+ depends on PVR_SGX
+ default y
+
+config PVR_ACTIVE_POWER_LATENCY_MS
+ int "Active power event latency (ms)"
+ depends on PVR_ACTIVE_POWER_MANAGEMENT
+ default 100
+
+config PVR_SGX_LOW_LATENCY_SCHEDULING
+ bool "Enable low-latency scheduling"
+ depends on PVR_SGX
+ default y
+
+config PVR_USSE_EDM_STATUS_DEBUG
+ bool "Trace microkernel status"
+ depends on PVR_SGX
+ default y if PVR_BUILD_DEBUG
+
+config PVR_DUMP_MK_TRACE
+ bool "Dump microkernel trace on HW recovery"
+ depends on PVR_USSE_EDM_STATUS_DEBUG
+ default y
+
+config PVR_PDUMP
+ bool "Support for parameter dumping (Pdump)"
+ depends on PVR_SGX
+ default n
+
+config PVR_LINUX_MEM_AREA_POOL
+ bool "Enable uncached allocation pool"
+ depends on PVR_SGX
+ default n
+
+config PVR_LINUX_MEM_AREA_POOL_MAX_PAGES
+ int "Maximum number of pages in pool"
+ depends on PVR_LINUX_MEM_AREA_POOL
+ default 5400
+ help
+ Pool size in pages.
+ A size of 0 disables the pool.
+ A size of -1 allows the pool to grow indefinitely.
diff --git a/drivers/gpu/pvr/Makefile b/drivers/gpu/pvr/Makefile
new file mode 100644
index 0000000..d428d50
--- /dev/null
+++ b/drivers/gpu/pvr/Makefile
@@ -0,0 +1,137 @@
+ccflags-y := \
+ -Wno-pointer-sign\
+ -fno-strict-overflow\
+ -fconserve-stack\
+ -Wdeclaration-after-statement\
+ -Wpointer-arith\
+ -Wmissing-format-attribute\
+ -Wno-format-zero-length\
+ -Wmissing-prototypes\
+ -Wstrict-prototypes\
+ -Wno-unused-parameter\
+ -Wno-sign-compare\
+ -Werror\
+ -fno-strict-aliasing\
+ -Wno-pointer-arith\
+ -Os
+
+ccflags-y += -DLINUX -D__linux__ -DANDROID
+ccflags-y += -Idrivers/gpu/pvr
+
+ccflags-y += \
+ -DSUPPORT_SGX_NEW_STATUS_VALS \
+ -DSUPPORT_SGX_HWPERF \
+ -DSYS_USING_INTERRUPTS \
+ -DPVR_SECURE_HANDLES \
+ -DTRANSFER_QUEUE \
+ -DSUPPORT_SGX \
+ -DSUPPORT_HW_RECOVERY \
+ -DLDM_PLATFORM \
+ -DPVR_LINUX_USING_WORKQUEUES \
+ -DPVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE \
+ -DPVR_LINUX_TIMERS_USING_WORKQUEUES \
+ -DSYS_CUSTOM_POWERLOCK_WRAP \
+ -DSUPPORT_MEMINFO_IDS \
+ -DSYS_SGX_ACTIVE_POWER_LATENCY_MS=100 \
+ -DPVRSRV_MODNAME="\"pvrsrvkm\"" \
+ -Idrivers/gpu/pvr/sgx \
+ -DSUPPORT_GET_DC_BUFFERS_SYS_PHYADDRS \
+ -DPVRSRV_MMU_MAKE_READWRITE_ON_DEMAND \
+ -DPVRSRV_AVOID_RANGED_INVALIDATE \
+ -DPVR_LDM_DRIVER_REGISTRATION_NAME="\"pvrsrvkm\""
+
+ccflags-$(CONFIG_PVR_BUILD_RELEASE) += \
+ -DPVR_BUILD_TYPE="\"release\"" -DRELEASE
+
+ccflags-$(CONFIG_PVR_BUILD_DEBUG) += \
+ -DPVR_BUILD_TYPE="\"debug\"" -DDEBUG
+
+ccflags-$(CONFIG_PVR_NEED_PVR_DPF) += -DPVRSRV_NEED_PVR_DPF
+ccflags-$(CONFIG_PVR_NEED_PVR_ASSERT) += -DPVRSRV_NEED_PVR_ASSERT
+
+ccflags-$(CONFIG_PVR_DEBUG_MEMORY) += \
+ -DDEBUG_LINUX_MEMORY_ALLOCATIONS \
+ -DDEBUG_LINUX_MEM_AREAS \
+ -DDEBUG_LINUX_MMAP_AREAS
+
+ccflags-$(CONFIG_PVR_DEBUG_BRIDGE_KM) += -DDEBUG_BRIDGE_KM
+ccflags-$(CONFIG_PVR_DEBUG_TRACE_BRIDGE_KM) += -DDEBUG_TRACE_BRIDGE_KM
+ccflags-$(CONFIG_PVR_DEBUG_BRIDGE_KM_DISPATCH_TABLE) += -DDEBUG_BRIDGE_KM_DISPATCH_TABLE
+
+ccflags-$(CONFIG_PVR_PERCONTEXT_PB) += -DSUPPORT_PERCONTEXT_PB
+ccflags-$(CONFIG_PVR_SGX_LOW_LATENCY_SCHEDULING) += -DSUPPORT_SGX_LOW_LATENCY_SCHEDULING
+ccflags-$(CONFIG_PVR_ACTIVE_POWER_MANAGEMENT) += -DSUPPORT_ACTIVE_POWER_MANAGEMENT
+ccflags-$(CONFIG_PVR_USSE_EDM_STATUS_DEBUG) += -DPVRSRV_USSE_EDM_STATUS_DEBUG
+ccflags-$(CONFIG_PVR_DUMP_MK_TRACE) += -DPVRSRV_DUMP_MK_TRACE
+
+ccflags-$(CONFIG_PVR_PDUMP) += \
+ -DPDUMP -DSUPPORT_PDUMP_MULTI_PROCESS
+
+ccflags-$(CONFIG_PVR_LINUX_MEM_AREA_POOL) += \
+ -DPVR_LINUX_MEM_AREA_POOL_MAX_PAGES=CONFIG_PVR_LINUX_MEM_AREA_POOL_MAX_PAGES \
+ -DPVR_LINUX_MEM_AREA_USE_VMAP -DPVR_LINUX_MEM_AREA_POOL_ALLOW_SHRINK
+
+pvrsrvkm-y := \
+ osfunc.o \
+ mutils.o \
+ mmap.o \
+ module.o \
+ pdump.o \
+ proc.o \
+ pvr_bridge_k.o \
+ pvr_debug.o \
+ mm.o \
+ mutex.o \
+ event.o \
+ osperproc.o \
+ buffer_manager.o \
+ devicemem.o \
+ deviceclass.o \
+ handle.o \
+ hash.o \
+ metrics.o \
+ pvrsrv.o \
+ queue.o \
+ ra.o \
+ resman.o \
+ power.o \
+ mem.o \
+ pdump_common.o \
+ bridged_support.o \
+ bridged_pvr_bridge.o \
+ perproc.o \
+ lists.o \
+ refcount.o \
+ sgx/bridged_sgx_bridge.o \
+ sgx/sgxinit.o \
+ sgx/sgxpower.o \
+ sgx/sgxreset.o \
+ sgx/sgxutils.o \
+ sgx/sgxkick.o \
+ sgx/sgxtransfer.o \
+ sgx/mmu.o \
+ sgx/pb.o
+
+ccflags-$(CONFIG_ARCH_S5PV210) += \
+ -DPVR_BUILD_DIR="\"smdkc110_android\"" \
+ -Idrivers/gpu/pvr/s5pc110 \
+ -DDISPLAY_CONTROLLER=s3c_lcd \
+ -DSLSI_S5PC110
+
+ccflags-$(CONFIG_ARCH_S5PV210) += \
+ -DSGX540 -DSUPPORT_SGX540 \
+ -DSGX_CORE_REV=120
+
+pvrsrvkm-$(CONFIG_ARCH_S5PV210) += \
+ s5pc110/sysconfig.o \
+ s5pc110/sysutils.o
+
+s3c_lcd-y := \
+ s3c_lcd/s3c_displayclass.o \
+ s3c_lcd/s3c_lcd.o
+
+obj-$(CONFIG_PVR_PDUMP) += dbgdrv/
+
+obj-$(CONFIG_PVR_SGX) += pvrsrvkm.o
+
+obj-$(CONFIG_ARCH_S5PV210) += s3c_lcd.o
diff --git a/drivers/gpu/pvr/bridged_pvr_bridge.c b/drivers/gpu/pvr/bridged_pvr_bridge.c
new file mode 100644
index 0000000..b585b99
--- /dev/null
+++ b/drivers/gpu/pvr/bridged_pvr_bridge.c
@@ -0,0 +1,4894 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+
+
+#include <stddef.h>
+
+#include "img_defs.h"
+#include "services.h"
+#include "pvr_bridge_km.h"
+#include "pvr_debug.h"
+#include "ra.h"
+#include "pvr_bridge.h"
+#if defined(SUPPORT_SGX)
+#include "sgx_bridge.h"
+#endif
+#if defined(SUPPORT_VGX)
+#include "vgx_bridge.h"
+#endif
+#if defined(SUPPORT_MSVDX)
+#include "msvdx_bridge.h"
+#endif
+#include "perproc.h"
+#include "device.h"
+#include "buffer_manager.h"
+#include "refcount.h"
+
+#include "pdump_km.h"
+#include "syscommon.h"
+
+#include "bridged_pvr_bridge.h"
+#if defined(SUPPORT_SGX)
+#include "bridged_sgx_bridge.h"
+#endif
+#if defined(SUPPORT_VGX)
+#include "bridged_vgx_bridge.h"
+#endif
+#if defined(SUPPORT_MSVDX)
+#include "bridged_msvdx_bridge.h"
+#endif
+
+#include "env_data.h"
+
+#if defined (__linux__)
+#include "mmap.h"
+#endif
+
+
+#include "srvkm.h"
+
+PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY g_BridgeDispatchTable[BRIDGE_DISPATCH_TABLE_ENTRY_COUNT];
+
+#if defined(DEBUG_BRIDGE_KM)
+PVRSRV_BRIDGE_GLOBAL_STATS g_BridgeGlobalStats;
+#endif
+
+#if defined(PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE)
+static IMG_BOOL abSharedDeviceMemHeap[PVRSRV_MAX_CLIENT_HEAPS];
+static IMG_BOOL *pbSharedDeviceMemHeap = abSharedDeviceMemHeap;
+#else
+static IMG_BOOL *pbSharedDeviceMemHeap = (IMG_BOOL*)IMG_NULL;
+#endif
+
+
+#if defined(DEBUG_BRIDGE_KM)
+PVRSRV_ERROR
+CopyFromUserWrapper(PVRSRV_PER_PROCESS_DATA *pProcData,
+ IMG_UINT32 ui32BridgeID,
+ IMG_VOID *pvDest,
+ IMG_VOID *pvSrc,
+ IMG_UINT32 ui32Size)
+{
+ g_BridgeDispatchTable[ui32BridgeID].ui32CopyFromUserTotalBytes+=ui32Size;
+ g_BridgeGlobalStats.ui32TotalCopyFromUserBytes+=ui32Size;
+ return OSCopyFromUser(pProcData, pvDest, pvSrc, ui32Size);
+}
+PVRSRV_ERROR
+CopyToUserWrapper(PVRSRV_PER_PROCESS_DATA *pProcData,
+ IMG_UINT32 ui32BridgeID,
+ IMG_VOID *pvDest,
+ IMG_VOID *pvSrc,
+ IMG_UINT32 ui32Size)
+{
+ g_BridgeDispatchTable[ui32BridgeID].ui32CopyToUserTotalBytes+=ui32Size;
+ g_BridgeGlobalStats.ui32TotalCopyToUserBytes+=ui32Size;
+ return OSCopyToUser(pProcData, pvDest, pvSrc, ui32Size);
+}
+#endif
+
+
+static IMG_INT
+PVRSRVEnumerateDevicesBW(IMG_UINT32 ui32BridgeID,
+ IMG_VOID *psBridgeIn,
+ PVRSRV_BRIDGE_OUT_ENUMDEVICE *psEnumDeviceOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ENUM_DEVICES);
+
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+
+ psEnumDeviceOUT->eError =
+ PVRSRVEnumerateDevicesKM(&psEnumDeviceOUT->ui32NumDevices,
+ psEnumDeviceOUT->asDeviceIdentifier);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVAcquireDeviceDataBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_ACQUIRE_DEVICEINFO *psAcquireDevInfoIN,
+ PVRSRV_BRIDGE_OUT_ACQUIRE_DEVICEINFO *psAcquireDevInfoOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ACQUIRE_DEVICEINFO);
+
+ psAcquireDevInfoOUT->eError =
+ PVRSRVAcquireDeviceDataKM(psAcquireDevInfoIN->uiDevIndex,
+ psAcquireDevInfoIN->eDeviceType,
+ &hDevCookieInt);
+ if(psAcquireDevInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ psAcquireDevInfoOUT->eError =
+ PVRSRVAllocHandle(psPerProc->psHandleBase,
+ &psAcquireDevInfoOUT->hDevCookie,
+ hDevCookieInt,
+ PVRSRV_HANDLE_TYPE_DEV_NODE,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVCreateDeviceMemContextBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_CREATE_DEVMEMCONTEXT *psCreateDevMemContextIN,
+ PVRSRV_BRIDGE_OUT_CREATE_DEVMEMCONTEXT *psCreateDevMemContextOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_HANDLE hDevMemContextInt;
+ IMG_UINT32 i;
+ IMG_BOOL bCreated;
+#if defined (SUPPORT_SID_INTERFACE)
+ PVRSRV_HEAP_INFO_KM asHeapInfo[PVRSRV_MAX_CLIENT_HEAPS];
+#endif
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CREATE_DEVMEMCONTEXT);
+
+
+ NEW_HANDLE_BATCH_OR_ERROR(psCreateDevMemContextOUT->eError, psPerProc, PVRSRV_MAX_CLIENT_HEAPS + 1)
+
+ psCreateDevMemContextOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psCreateDevMemContextIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psCreateDevMemContextOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psCreateDevMemContextOUT->eError =
+ PVRSRVCreateDeviceMemContextKM(hDevCookieInt,
+ psPerProc,
+ &hDevMemContextInt,
+ &psCreateDevMemContextOUT->ui32ClientHeapCount,
+#if defined (SUPPORT_SID_INTERFACE)
+ &asHeapInfo[0],
+#else
+ &psCreateDevMemContextOUT->sHeapInfo[0],
+#endif
+ &bCreated,
+ pbSharedDeviceMemHeap);
+
+ if(psCreateDevMemContextOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ if(bCreated)
+ {
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psCreateDevMemContextOUT->hDevMemContext,
+ hDevMemContextInt,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+ }
+ else
+ {
+ psCreateDevMemContextOUT->eError =
+ PVRSRVFindHandle(psPerProc->psHandleBase,
+ &psCreateDevMemContextOUT->hDevMemContext,
+ hDevMemContextInt,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+ if(psCreateDevMemContextOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ for(i = 0; i < psCreateDevMemContextOUT->ui32ClientHeapCount; i++)
+ {
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevMemHeapExt;
+#else
+ IMG_HANDLE hDevMemHeapExt;
+#endif
+
+#if defined(PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE)
+ if(abSharedDeviceMemHeap[i])
+#endif
+ {
+
+#if defined (SUPPORT_SID_INTERFACE)
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &hDevMemHeapExt,
+ asHeapInfo[i].hDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+#else
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase, &hDevMemHeapExt,
+ psCreateDevMemContextOUT->sHeapInfo[i].hDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+#endif
+ }
+#if defined(PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE)
+ else
+ {
+
+ if(bCreated)
+ {
+#if defined (SUPPORT_SID_INTERFACE)
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &hDevMemHeapExt,
+ asHeapInfo[i].hDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+ psCreateDevMemContextOUT->hDevMemContext);
+#else
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase, &hDevMemHeapExt,
+ psCreateDevMemContextOUT->sHeapInfo[i].hDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+ psCreateDevMemContextOUT->hDevMemContext);
+#endif
+ }
+ else
+ {
+ psCreateDevMemContextOUT->eError =
+ PVRSRVFindHandle(psPerProc->psHandleBase,
+ &hDevMemHeapExt,
+#if defined (SUPPORT_SID_INTERFACE)
+ asHeapInfo[i].hDevMemHeap,
+#else
+ psCreateDevMemContextOUT->sHeapInfo[i].hDevMemHeap,
+#endif
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP);
+ if(psCreateDevMemContextOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+ }
+#endif
+ psCreateDevMemContextOUT->sHeapInfo[i].hDevMemHeap = hDevMemHeapExt;
+#if defined (SUPPORT_SID_INTERFACE)
+ psCreateDevMemContextOUT->sHeapInfo[i].ui32HeapID = asHeapInfo[i].ui32HeapID;
+ psCreateDevMemContextOUT->sHeapInfo[i].sDevVAddrBase = asHeapInfo[i].sDevVAddrBase;
+ psCreateDevMemContextOUT->sHeapInfo[i].ui32HeapByteSize = asHeapInfo[i].ui32HeapByteSize;
+ psCreateDevMemContextOUT->sHeapInfo[i].ui32Attribs = asHeapInfo[i].ui32Attribs;
+ psCreateDevMemContextOUT->sHeapInfo[i].ui32XTileStride = asHeapInfo[i].ui32XTileStride;
+#endif
+ }
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psCreateDevMemContextOUT->eError, psPerProc)
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVDestroyDeviceMemContextBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DESTROY_DEVMEMCONTEXT *psDestroyDevMemContextIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_HANDLE hDevMemContextInt;
+ IMG_BOOL bDestroyed;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DESTROY_DEVMEMCONTEXT);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psDestroyDevMemContextIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemContextInt,
+ psDestroyDevMemContextIN->hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVDestroyDeviceMemContextKM(hDevCookieInt, hDevMemContextInt, &bDestroyed);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ if(bDestroyed)
+ {
+ psRetOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psDestroyDevMemContextIN->hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+ }
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVGetDeviceMemHeapInfoBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GET_DEVMEM_HEAPINFO *psGetDevMemHeapInfoIN,
+ PVRSRV_BRIDGE_OUT_GET_DEVMEM_HEAPINFO *psGetDevMemHeapInfoOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_HANDLE hDevMemContextInt;
+ IMG_UINT32 i;
+#if defined (SUPPORT_SID_INTERFACE)
+ PVRSRV_HEAP_INFO_KM asHeapInfo[PVRSRV_MAX_CLIENT_HEAPS];
+#endif
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_DEVMEM_HEAPINFO);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psGetDevMemHeapInfoOUT->eError, psPerProc, PVRSRV_MAX_CLIENT_HEAPS)
+
+ psGetDevMemHeapInfoOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psGetDevMemHeapInfoIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psGetDevMemHeapInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psGetDevMemHeapInfoOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemContextInt,
+ psGetDevMemHeapInfoIN->hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+ if(psGetDevMemHeapInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psGetDevMemHeapInfoOUT->eError =
+ PVRSRVGetDeviceMemHeapInfoKM(hDevCookieInt,
+ hDevMemContextInt,
+ &psGetDevMemHeapInfoOUT->ui32ClientHeapCount,
+#if defined (SUPPORT_SID_INTERFACE)
+ &asHeapInfo[0],
+#else
+ &psGetDevMemHeapInfoOUT->sHeapInfo[0],
+#endif
+ pbSharedDeviceMemHeap);
+
+ if(psGetDevMemHeapInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ for(i = 0; i < psGetDevMemHeapInfoOUT->ui32ClientHeapCount; i++)
+ {
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevMemHeapExt;
+#else
+ IMG_HANDLE hDevMemHeapExt;
+#endif
+
+#if defined(PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE)
+ if(abSharedDeviceMemHeap[i])
+#endif
+ {
+
+#if defined (SUPPORT_SID_INTERFACE)
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &hDevMemHeapExt,
+ asHeapInfo[i].hDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+#else
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase, &hDevMemHeapExt,
+ psGetDevMemHeapInfoOUT->sHeapInfo[i].hDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+#endif
+ }
+#if defined(PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE)
+ else
+ {
+
+ psGetDevMemHeapInfoOUT->eError =
+ PVRSRVFindHandle(psPerProc->psHandleBase,
+ &hDevMemHeapExt,
+#if defined (SUPPORT_SID_INTERFACE)
+ asHeapInfo[i].hDevMemHeap,
+#else
+ psGetDevMemHeapInfoOUT->sHeapInfo[i].hDevMemHeap,
+#endif
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP);
+ if(psGetDevMemHeapInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+#endif
+ psGetDevMemHeapInfoOUT->sHeapInfo[i].hDevMemHeap = hDevMemHeapExt;
+#if defined (SUPPORT_SID_INTERFACE)
+ psGetDevMemHeapInfoOUT->sHeapInfo[i].ui32HeapID = asHeapInfo[i].ui32HeapID;
+ psGetDevMemHeapInfoOUT->sHeapInfo[i].sDevVAddrBase = asHeapInfo[i].sDevVAddrBase;
+ psGetDevMemHeapInfoOUT->sHeapInfo[i].ui32HeapByteSize = asHeapInfo[i].ui32HeapByteSize;
+ psGetDevMemHeapInfoOUT->sHeapInfo[i].ui32Attribs = asHeapInfo[i].ui32Attribs;
+ psGetDevMemHeapInfoOUT->sHeapInfo[i].ui32XTileStride = asHeapInfo[i].ui32XTileStride;
+#endif
+ }
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psGetDevMemHeapInfoOUT->eError, psPerProc)
+
+ return 0;
+}
+
+
+#if defined(OS_PVRSRV_ALLOC_DEVICE_MEM_BW)
+IMG_INT
+PVRSRVAllocDeviceMemBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM *psAllocDeviceMemIN,
+ PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM *psAllocDeviceMemOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc);
+#else
+static IMG_INT
+PVRSRVAllocDeviceMemBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM *psAllocDeviceMemIN,
+ PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM *psAllocDeviceMemOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+ IMG_HANDLE hDevCookieInt;
+ IMG_HANDLE hDevMemHeapInt;
+ IMG_UINT32 ui32ShareIndex;
+ IMG_BOOL bUseShareMemWorkaround;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ALLOC_DEVICEMEM);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psAllocDeviceMemOUT->eError, psPerProc, 2)
+
+ psAllocDeviceMemOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psAllocDeviceMemIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psAllocDeviceMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psAllocDeviceMemOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemHeapInt,
+ psAllocDeviceMemIN->hDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP);
+
+ if(psAllocDeviceMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+
+ bUseShareMemWorkaround = ((psAllocDeviceMemIN->ui32Attribs & PVRSRV_MEM_XPROC) != 0) ? IMG_TRUE : IMG_FALSE;
+ ui32ShareIndex = 7654321;
+
+ if (bUseShareMemWorkaround)
+ {
+
+
+
+ psAllocDeviceMemOUT->eError =
+ BM_XProcWorkaroundFindNewBufferAndSetShareIndex(&ui32ShareIndex);
+ if(psAllocDeviceMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+
+ if(psAllocDeviceMemIN->pvPrivData)
+ {
+ if(!OSAccessOK(PVR_VERIFY_READ,
+ psAllocDeviceMemIN->pvPrivData,
+ psAllocDeviceMemIN->ui32PrivDataLength))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocDeviceMemBW: Access check failed for pvPrivData"));
+ return -EFAULT;
+ }
+ }
+
+ psAllocDeviceMemOUT->eError =
+ PVRSRVAllocDeviceMemKM(hDevCookieInt,
+ psPerProc,
+ hDevMemHeapInt,
+ psAllocDeviceMemIN->ui32Attribs,
+ psAllocDeviceMemIN->ui32Size,
+ psAllocDeviceMemIN->ui32Alignment,
+ psAllocDeviceMemIN->pvPrivData,
+ psAllocDeviceMemIN->ui32PrivDataLength,
+ &psMemInfo,
+ "" );
+
+ if (bUseShareMemWorkaround)
+ {
+ PVR_ASSERT(ui32ShareIndex != 7654321);
+ BM_XProcWorkaroundUnsetShareIndex(ui32ShareIndex);
+ }
+
+ if(psAllocDeviceMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psMemInfo->sShareMemWorkaround.bInUse = bUseShareMemWorkaround;
+ if (bUseShareMemWorkaround)
+ {
+ PVR_ASSERT(ui32ShareIndex != 7654321);
+ psMemInfo->sShareMemWorkaround.ui32ShareIndex = ui32ShareIndex;
+ psMemInfo->sShareMemWorkaround.hDevCookieInt = hDevCookieInt;
+ psMemInfo->sShareMemWorkaround.ui32OrigReqAttribs = psAllocDeviceMemIN->ui32Attribs;
+ psMemInfo->sShareMemWorkaround.ui32OrigReqSize = (IMG_UINT32)psAllocDeviceMemIN->ui32Size;
+ psMemInfo->sShareMemWorkaround.ui32OrigReqAlignment = (IMG_UINT32)psAllocDeviceMemIN->ui32Alignment;
+ }
+
+ OSMemSet(&psAllocDeviceMemOUT->sClientMemInfo,
+ 0,
+ sizeof(psAllocDeviceMemOUT->sClientMemInfo));
+
+ psAllocDeviceMemOUT->sClientMemInfo.pvLinAddrKM =
+ psMemInfo->pvLinAddrKM;
+
+#if defined (__linux__)
+ psAllocDeviceMemOUT->sClientMemInfo.pvLinAddr = 0;
+#else
+ psAllocDeviceMemOUT->sClientMemInfo.pvLinAddr = psMemInfo->pvLinAddrKM;
+#endif
+ psAllocDeviceMemOUT->sClientMemInfo.sDevVAddr = psMemInfo->sDevVAddr;
+ psAllocDeviceMemOUT->sClientMemInfo.ui32Flags = psMemInfo->ui32Flags;
+ psAllocDeviceMemOUT->sClientMemInfo.uAllocSize = psMemInfo->uAllocSize;
+#if defined (SUPPORT_SID_INTERFACE)
+
+#else
+ psAllocDeviceMemOUT->sClientMemInfo.hMappingInfo = psMemInfo->sMemBlk.hOSMemHandle;
+#endif
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psAllocDeviceMemOUT->sClientMemInfo.hKernelMemInfo,
+ psMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+#if defined (SUPPORT_SID_INTERFACE)
+ PVR_ASSERT(psAllocDeviceMemOUT->sClientMemInfo.hKernelMemInfo != 0);
+
+ if (psMemInfo->sMemBlk.hOSMemHandle != IMG_NULL)
+ {
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psAllocDeviceMemOUT->sClientMemInfo.hMappingInfo,
+ psMemInfo->sMemBlk.hOSMemHandle,
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+ psAllocDeviceMemOUT->sClientMemInfo.hKernelMemInfo);
+ }
+ else
+ {
+ psAllocDeviceMemOUT->sClientMemInfo.hMappingInfo = 0;
+ }
+#endif
+
+ if(psAllocDeviceMemIN->ui32Attribs & PVRSRV_MEM_NO_SYNCOBJ)
+ {
+
+ OSMemSet(&psAllocDeviceMemOUT->sClientSyncInfo,
+ 0,
+ sizeof (PVRSRV_CLIENT_SYNC_INFO));
+ psAllocDeviceMemOUT->sClientMemInfo.psClientSyncInfo = IMG_NULL;
+ }
+ else
+ {
+
+
+#if !defined(PVRSRV_DISABLE_UM_SYNCOBJ_MAPPINGS)
+ psAllocDeviceMemOUT->sClientSyncInfo.psSyncData =
+ psMemInfo->psKernelSyncInfo->psSyncData;
+ psAllocDeviceMemOUT->sClientSyncInfo.sWriteOpsCompleteDevVAddr =
+ psMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+ psAllocDeviceMemOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
+ psMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+ psAllocDeviceMemOUT->sClientSyncInfo.sReadOps2CompleteDevVAddr =
+ psMemInfo->psKernelSyncInfo->sReadOps2CompleteDevVAddr;
+
+#if defined (SUPPORT_SID_INTERFACE)
+ if (psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle != IMG_NULL)
+ {
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psAllocDeviceMemOUT->sClientSyncInfo.hMappingInfo,
+ psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+ psAllocDeviceMemOUT->sClientMemInfo.hKernelMemInfo);
+ }
+ else
+ {
+ psAllocDeviceMemOUT->sClientSyncInfo.hMappingInfo = 0;
+ }
+#else
+ psAllocDeviceMemOUT->sClientSyncInfo.hMappingInfo =
+ psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle;
+#endif
+#endif
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psAllocDeviceMemOUT->sClientSyncInfo.hKernelSyncInfo,
+ psMemInfo->psKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+ psAllocDeviceMemOUT->sClientMemInfo.hKernelMemInfo);
+
+ psAllocDeviceMemOUT->sClientMemInfo.psClientSyncInfo =
+ &psAllocDeviceMemOUT->sClientSyncInfo;
+ }
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psAllocDeviceMemOUT->eError, psPerProc)
+
+ return 0;
+}
+
+#endif
+
+static IMG_INT
+PVRSRVFreeDeviceMemBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_FREEDEVICEMEM *psFreeDeviceMemIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_VOID *pvKernelMemInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_FREE_DEVICEMEM);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psFreeDeviceMemIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvKernelMemInfo,
+#if defined (SUPPORT_SID_INTERFACE)
+ psFreeDeviceMemIN->hKernelMemInfo,
+#else
+ psFreeDeviceMemIN->psKernelMemInfo,
+#endif
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = PVRSRVFreeDeviceMemKM(hDevCookieInt, pvKernelMemInfo);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ psFreeDeviceMemIN->hKernelMemInfo,
+#else
+ psFreeDeviceMemIN->psKernelMemInfo,
+#endif
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVExportDeviceMemBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_EXPORTDEVICEMEM *psExportDeviceMemIN,
+ PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM *psExportDeviceMemOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+#if defined (SUPPORT_SID_INTERFACE)
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = IMG_NULL;
+#else
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+#endif
+
+ PVR_ASSERT(ui32BridgeID == PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_EXPORT_DEVICEMEM) ||
+ ui32BridgeID == PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_EXPORT_DEVICEMEM_2));
+ PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+
+
+ psExportDeviceMemOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psExportDeviceMemIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psExportDeviceMemOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVExportDeviceMemBW: can't find devcookie"));
+ return 0;
+ }
+
+
+ psExportDeviceMemOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_PVOID *)&psKernelMemInfo,
+#if defined (SUPPORT_SID_INTERFACE)
+ psExportDeviceMemIN->hKernelMemInfo,
+#else
+ psExportDeviceMemIN->psKernelMemInfo,
+#endif
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ if(psExportDeviceMemOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVExportDeviceMemBW: can't find kernel meminfo"));
+ return 0;
+ }
+
+
+ psExportDeviceMemOUT->eError =
+ PVRSRVFindHandle(KERNEL_HANDLE_BASE,
+ &psExportDeviceMemOUT->hMemInfo,
+ psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(psExportDeviceMemOUT->eError == PVRSRV_OK)
+ {
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVExportDeviceMemBW: allocation is already exported"));
+ return 0;
+ }
+
+
+ psExportDeviceMemOUT->eError = PVRSRVAllocHandle(KERNEL_HANDLE_BASE,
+ &psExportDeviceMemOUT->hMemInfo,
+ psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+ if (psExportDeviceMemOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVExportDeviceMemBW: failed to allocate handle from global handle list"));
+ return 0;
+ }
+
+
+ psKernelMemInfo->ui32Flags |= PVRSRV_MEM_EXPORTED;
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVMapDeviceMemoryBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY *psMapDevMemIN,
+ PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *psMapDevMemOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_KERNEL_MEM_INFO *psSrcKernelMemInfo = IMG_NULL;
+ PVRSRV_KERNEL_MEM_INFO *psDstKernelMemInfo = IMG_NULL;
+ IMG_HANDLE hDstDevMemHeap = IMG_NULL;
+
+ PVR_ASSERT(ui32BridgeID == PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_MAP_DEV_MEMORY) ||
+ ui32BridgeID == PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_MAP_DEV_MEMORY_2));
+ PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psMapDevMemOUT->eError, psPerProc, 2)
+
+
+ psMapDevMemOUT->eError = PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+ (IMG_VOID**)&psSrcKernelMemInfo,
+ psMapDevMemIN->hKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(psMapDevMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ psMapDevMemOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDstDevMemHeap,
+ psMapDevMemIN->hDstDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP);
+ if(psMapDevMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ if (psSrcKernelMemInfo->sShareMemWorkaround.bInUse)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "using the mem wrap workaround."));
+
+
+
+
+
+
+
+
+
+ psMapDevMemOUT->eError = BM_XProcWorkaroundSetShareIndex(psSrcKernelMemInfo->sShareMemWorkaround.ui32ShareIndex);
+ if(psMapDevMemOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVMapDeviceMemoryBW(): failed to recycle shared buffer"));
+ return 0;
+ }
+
+ psMapDevMemOUT->eError =
+ PVRSRVAllocDeviceMemKM(psSrcKernelMemInfo->sShareMemWorkaround.hDevCookieInt,
+ psPerProc,
+ hDstDevMemHeap,
+ psSrcKernelMemInfo->sShareMemWorkaround.ui32OrigReqAttribs | PVRSRV_MEM_NO_SYNCOBJ,
+ psSrcKernelMemInfo->sShareMemWorkaround.ui32OrigReqSize,
+ psSrcKernelMemInfo->sShareMemWorkaround.ui32OrigReqAlignment,
+ IMG_NULL,
+ 0,
+ &psDstKernelMemInfo,
+ "" );
+
+
+ BM_XProcWorkaroundUnsetShareIndex(psSrcKernelMemInfo->sShareMemWorkaround.ui32ShareIndex);
+ if(psMapDevMemOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVMapDeviceMemoryBW: Failed to create allocation for cross-process memory map"));
+ return 0;
+ }
+
+ if(psSrcKernelMemInfo->psKernelSyncInfo)
+ {
+ PVRSRVKernelSyncInfoIncRef(psSrcKernelMemInfo->psKernelSyncInfo, psSrcKernelMemInfo);
+ }
+
+ psDstKernelMemInfo->psKernelSyncInfo = psSrcKernelMemInfo->psKernelSyncInfo;
+ }
+ else
+ {
+
+ psMapDevMemOUT->eError = PVRSRVMapDeviceMemoryKM(psPerProc,
+ psSrcKernelMemInfo,
+ hDstDevMemHeap,
+ &psDstKernelMemInfo);
+ if(psMapDevMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+
+ psDstKernelMemInfo->sShareMemWorkaround = psSrcKernelMemInfo->sShareMemWorkaround;
+
+ OSMemSet(&psMapDevMemOUT->sDstClientMemInfo,
+ 0,
+ sizeof(psMapDevMemOUT->sDstClientMemInfo));
+ OSMemSet(&psMapDevMemOUT->sDstClientSyncInfo,
+ 0,
+ sizeof(psMapDevMemOUT->sDstClientSyncInfo));
+
+ psMapDevMemOUT->sDstClientMemInfo.pvLinAddrKM =
+ psDstKernelMemInfo->pvLinAddrKM;
+
+ psMapDevMemOUT->sDstClientMemInfo.pvLinAddr = 0;
+ psMapDevMemOUT->sDstClientMemInfo.sDevVAddr = psDstKernelMemInfo->sDevVAddr;
+ psMapDevMemOUT->sDstClientMemInfo.ui32Flags = psDstKernelMemInfo->ui32Flags;
+ psMapDevMemOUT->sDstClientMemInfo.uAllocSize = psDstKernelMemInfo->uAllocSize;
+#if defined (SUPPORT_SID_INTERFACE)
+
+#else
+ psMapDevMemOUT->sDstClientMemInfo.hMappingInfo = psDstKernelMemInfo->sMemBlk.hOSMemHandle;
+#endif
+
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psMapDevMemOUT->sDstClientMemInfo.hKernelMemInfo,
+ psDstKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+ psMapDevMemOUT->sDstClientSyncInfo.hKernelSyncInfo = IMG_NULL;
+
+#if defined (SUPPORT_SID_INTERFACE)
+
+ if (psDstKernelMemInfo->sMemBlk.hOSMemHandle != IMG_NULL)
+ {
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psMapDevMemOUT->sDstClientMemInfo.hMappingInfo,
+ psDstKernelMemInfo->sMemBlk.hOSMemHandle,
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+ psMapDevMemOUT->sDstClientMemInfo.hKernelMemInfo);
+ }
+ else
+ {
+ psMapDevMemOUT->sDstClientMemInfo.hMappingInfo = 0;
+ }
+#endif
+
+
+ if(psDstKernelMemInfo->psKernelSyncInfo)
+ {
+#if !defined(PVRSRV_DISABLE_UM_SYNCOBJ_MAPPINGS)
+ psMapDevMemOUT->sDstClientSyncInfo.psSyncData =
+ psDstKernelMemInfo->psKernelSyncInfo->psSyncData;
+ psMapDevMemOUT->sDstClientSyncInfo.sWriteOpsCompleteDevVAddr =
+ psDstKernelMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+ psMapDevMemOUT->sDstClientSyncInfo.sReadOpsCompleteDevVAddr =
+ psDstKernelMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+ psMapDevMemOUT->sDstClientSyncInfo.sReadOps2CompleteDevVAddr =
+ psDstKernelMemInfo->psKernelSyncInfo->sReadOps2CompleteDevVAddr;
+
+#if defined (SUPPORT_SID_INTERFACE)
+
+ if (psDstKernelMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle != IMG_NULL)
+ {
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psMapDevMemOUT->sDstClientSyncInfo.hMappingInfo,
+ psDstKernelMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle,
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+ psMapDevMemOUT->sDstClientMemInfo.hKernelMemInfo);
+ }
+ else
+ {
+ psMapDevMemOUT->sDstClientSyncInfo.hMappingInfo = 0;
+ }
+#else
+ psMapDevMemOUT->sDstClientSyncInfo.hMappingInfo =
+ psDstKernelMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle;
+#endif
+#endif
+
+ psMapDevMemOUT->sDstClientMemInfo.psClientSyncInfo = &psMapDevMemOUT->sDstClientSyncInfo;
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psMapDevMemOUT->sDstClientSyncInfo.hKernelSyncInfo,
+ psDstKernelMemInfo->psKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ psMapDevMemOUT->sDstClientMemInfo.hKernelMemInfo);
+ }
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psMapDevMemOUT->eError, psPerProc)
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVUnmapDeviceMemoryBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_UNMAP_DEV_MEMORY *psUnmapDevMemIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_UNMAP_DEV_MEMORY);
+
+ psRetOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID**)&psKernelMemInfo,
+#if defined (SUPPORT_SID_INTERFACE)
+ psUnmapDevMemIN->hKernelMemInfo,
+#else
+ psUnmapDevMemIN->psKernelMemInfo,
+#endif
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ if (psKernelMemInfo->sShareMemWorkaround.bInUse)
+ {
+ psRetOUT->eError = PVRSRVFreeDeviceMemKM(psKernelMemInfo->sShareMemWorkaround.hDevCookieInt, psKernelMemInfo);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVUnmapDeviceMemoryBW: internal error, should expect FreeDeviceMem to fail"));
+ return 0;
+ }
+ }
+ else
+ {
+ psRetOUT->eError = PVRSRVUnmapDeviceMemoryKM(psKernelMemInfo);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ psRetOUT->eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ psUnmapDevMemIN->hKernelMemInfo,
+#else
+ psUnmapDevMemIN->psKernelMemInfo,
+#endif
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ return 0;
+}
+
+
+
+static IMG_INT
+PVRSRVMapDeviceClassMemoryBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_MAP_DEVICECLASS_MEMORY *psMapDevClassMemIN,
+ PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY *psMapDevClassMemOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+ IMG_HANDLE hOSMapInfo;
+ IMG_HANDLE hDeviceClassBufferInt;
+ IMG_HANDLE hDevMemContextInt;
+ PVRSRV_HANDLE_TYPE eHandleType;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psMapDevClassMemOUT->eError, psPerProc, 2)
+
+
+ psMapDevClassMemOUT->eError =
+ PVRSRVLookupHandleAnyType(psPerProc->psHandleBase,
+ &hDeviceClassBufferInt,
+ &eHandleType,
+ psMapDevClassMemIN->hDeviceClassBuffer);
+
+ if(psMapDevClassMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ psMapDevClassMemOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevMemContextInt,
+ psMapDevClassMemIN->hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+ if(psMapDevClassMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ switch(eHandleType)
+ {
+#if defined(PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE)
+ case PVRSRV_HANDLE_TYPE_DISP_BUFFER:
+ case PVRSRV_HANDLE_TYPE_BUF_BUFFER:
+#else
+ case PVRSRV_HANDLE_TYPE_NONE:
+#endif
+ break;
+ default:
+ psMapDevClassMemOUT->eError = PVRSRV_ERROR_INVALID_HANDLE_TYPE;
+ return 0;
+ }
+
+ psMapDevClassMemOUT->eError =
+ PVRSRVMapDeviceClassMemoryKM(psPerProc,
+ hDevMemContextInt,
+ hDeviceClassBufferInt,
+ &psMemInfo,
+ &hOSMapInfo);
+ if(psMapDevClassMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ OSMemSet(&psMapDevClassMemOUT->sClientMemInfo,
+ 0,
+ sizeof(psMapDevClassMemOUT->sClientMemInfo));
+ OSMemSet(&psMapDevClassMemOUT->sClientSyncInfo,
+ 0,
+ sizeof(psMapDevClassMemOUT->sClientSyncInfo));
+
+ psMapDevClassMemOUT->sClientMemInfo.pvLinAddrKM =
+ psMemInfo->pvLinAddrKM;
+
+ psMapDevClassMemOUT->sClientMemInfo.pvLinAddr = 0;
+ psMapDevClassMemOUT->sClientMemInfo.sDevVAddr = psMemInfo->sDevVAddr;
+ psMapDevClassMemOUT->sClientMemInfo.ui32Flags = psMemInfo->ui32Flags;
+ psMapDevClassMemOUT->sClientMemInfo.uAllocSize = psMemInfo->uAllocSize;
+#if defined (SUPPORT_SID_INTERFACE)
+ if (psMemInfo->sMemBlk.hOSMemHandle != 0)
+ {
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psMapDevClassMemOUT->sClientMemInfo.hMappingInfo,
+ psMemInfo->sMemBlk.hOSMemHandle,
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+ psMapDevClassMemIN->hDeviceClassBuffer);
+ }
+ else
+ {
+ psMapDevClassMemOUT->sClientMemInfo.hMappingInfo = 0;
+ }
+#else
+ psMapDevClassMemOUT->sClientMemInfo.hMappingInfo = psMemInfo->sMemBlk.hOSMemHandle;
+#endif
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psMapDevClassMemOUT->sClientMemInfo.hKernelMemInfo,
+ psMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+ psMapDevClassMemIN->hDeviceClassBuffer);
+
+ psMapDevClassMemOUT->sClientSyncInfo.hKernelSyncInfo = IMG_NULL;
+
+
+ if(psMemInfo->psKernelSyncInfo)
+ {
+#if !defined(PVRSRV_DISABLE_UM_SYNCOBJ_MAPPINGS)
+ psMapDevClassMemOUT->sClientSyncInfo.psSyncData =
+ psMemInfo->psKernelSyncInfo->psSyncData;
+ psMapDevClassMemOUT->sClientSyncInfo.sWriteOpsCompleteDevVAddr =
+ psMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+ psMapDevClassMemOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
+ psMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+ psMapDevClassMemOUT->sClientSyncInfo.sReadOps2CompleteDevVAddr =
+ psMemInfo->psKernelSyncInfo->sReadOps2CompleteDevVAddr;
+
+#if defined (SUPPORT_SID_INTERFACE)
+ if (psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle != 0)
+ {
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psMapDevClassMemOUT->sClientSyncInfo.hMappingInfo,
+ psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ psMapDevClassMemOUT->sClientMemInfo.hKernelMemInfo);
+ }
+ else
+ {
+ psMapDevClassMemOUT->sClientSyncInfo.hMappingInfo = 0;
+ }
+#else
+ psMapDevClassMemOUT->sClientSyncInfo.hMappingInfo =
+ psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle;
+#endif
+#endif
+
+ psMapDevClassMemOUT->sClientMemInfo.psClientSyncInfo = &psMapDevClassMemOUT->sClientSyncInfo;
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psMapDevClassMemOUT->sClientSyncInfo.hKernelSyncInfo,
+ psMemInfo->psKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ psMapDevClassMemOUT->sClientMemInfo.hKernelMemInfo);
+ }
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psMapDevClassMemOUT->eError, psPerProc)
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVUnmapDeviceClassMemoryBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_UNMAP_DEVICECLASS_MEMORY *psUnmapDevClassMemIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvKernelMemInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_UNMAP_DEVICECLASS_MEMORY);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &pvKernelMemInfo,
+#if defined (SUPPORT_SID_INTERFACE)
+ psUnmapDevClassMemIN->hKernelMemInfo,
+#else
+ psUnmapDevClassMemIN->psKernelMemInfo,
+#endif
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = PVRSRVUnmapDeviceClassMemoryKM(pvKernelMemInfo);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ psUnmapDevClassMemIN->hKernelMemInfo,
+#else
+ psUnmapDevClassMemIN->psKernelMemInfo,
+#endif
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ return 0;
+}
+
+
+#if defined(OS_PVRSRV_WRAP_EXT_MEM_BW)
+IMG_INT
+PVRSRVWrapExtMemoryBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_WRAP_EXT_MEMORY *psWrapExtMemIN,
+ PVRSRV_BRIDGE_OUT_WRAP_EXT_MEMORY *psWrapExtMemOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc);
+#else
+static IMG_INT
+PVRSRVWrapExtMemoryBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_WRAP_EXT_MEMORY *psWrapExtMemIN,
+ PVRSRV_BRIDGE_OUT_WRAP_EXT_MEMORY *psWrapExtMemOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_HANDLE hDevMemContextInt;
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+ IMG_SYS_PHYADDR *psSysPAddr = IMG_NULL;
+ IMG_UINT32 ui32PageTableSize = 0;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_WRAP_EXT_MEMORY);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psWrapExtMemOUT->eError, psPerProc, 2)
+
+
+ psWrapExtMemOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psWrapExtMemIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psWrapExtMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ psWrapExtMemOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemContextInt,
+ psWrapExtMemIN->hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+ if(psWrapExtMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ if(psWrapExtMemIN->ui32NumPageTableEntries)
+ {
+ ui32PageTableSize = psWrapExtMemIN->ui32NumPageTableEntries
+ * sizeof(IMG_SYS_PHYADDR);
+
+ ASSIGN_AND_EXIT_ON_ERROR(psWrapExtMemOUT->eError,
+ OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32PageTableSize,
+ (IMG_VOID **)&psSysPAddr, 0,
+ "Page Table"));
+
+ if(CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ psSysPAddr,
+ psWrapExtMemIN->psSysPAddr,
+ ui32PageTableSize) != PVRSRV_OK)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32PageTableSize, (IMG_VOID *)psSysPAddr, 0);
+
+ return -EFAULT;
+ }
+ }
+
+ psWrapExtMemOUT->eError =
+ PVRSRVWrapExtMemoryKM(hDevCookieInt,
+ psPerProc,
+ hDevMemContextInt,
+ psWrapExtMemIN->ui32ByteSize,
+ psWrapExtMemIN->ui32PageOffset,
+ psWrapExtMemIN->bPhysContig,
+ psSysPAddr,
+ psWrapExtMemIN->pvLinAddr,
+ psWrapExtMemIN->ui32Flags,
+ &psMemInfo);
+
+ if(psWrapExtMemIN->ui32NumPageTableEntries)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32PageTableSize,
+ (IMG_VOID *)psSysPAddr, 0);
+
+ }
+
+ if(psWrapExtMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psWrapExtMemOUT->sClientMemInfo.pvLinAddrKM =
+ psMemInfo->pvLinAddrKM;
+
+
+ psWrapExtMemOUT->sClientMemInfo.pvLinAddr = 0;
+ psWrapExtMemOUT->sClientMemInfo.sDevVAddr = psMemInfo->sDevVAddr;
+ psWrapExtMemOUT->sClientMemInfo.ui32Flags = psMemInfo->ui32Flags;
+ psWrapExtMemOUT->sClientMemInfo.uAllocSize = psMemInfo->uAllocSize;
+#if defined (SUPPORT_SID_INTERFACE)
+#else
+ psWrapExtMemOUT->sClientMemInfo.hMappingInfo = psMemInfo->sMemBlk.hOSMemHandle;
+#endif
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psWrapExtMemOUT->sClientMemInfo.hKernelMemInfo,
+ psMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+#if defined (SUPPORT_SID_INTERFACE)
+
+ if (psMemInfo->sMemBlk.hOSMemHandle != IMG_NULL)
+ {
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psWrapExtMemOUT->sClientMemInfo.hMappingInfo,
+ psMemInfo->sMemBlk.hOSMemHandle,
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+ psWrapExtMemOUT->sClientMemInfo.hKernelMemInfo);
+ }
+ else
+ {
+ psWrapExtMemOUT->sClientMemInfo.hMappingInfo = 0;
+ }
+#endif
+
+
+#if !defined(PVRSRV_DISABLE_UM_SYNCOBJ_MAPPINGS)
+ psWrapExtMemOUT->sClientSyncInfo.psSyncData =
+ psMemInfo->psKernelSyncInfo->psSyncData;
+ psWrapExtMemOUT->sClientSyncInfo.sWriteOpsCompleteDevVAddr =
+ psMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+ psWrapExtMemOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
+ psMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+ psWrapExtMemOUT->sClientSyncInfo.sReadOps2CompleteDevVAddr =
+ psMemInfo->psKernelSyncInfo->sReadOps2CompleteDevVAddr;
+
+#if defined (SUPPORT_SID_INTERFACE)
+
+ if (psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle != IMG_NULL)
+ {
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psWrapExtMemOUT->sClientSyncInfo.hMappingInfo,
+ psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle,
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+ psWrapExtMemOUT->sClientMemInfo.hKernelMemInfo);
+ }
+ else
+ {
+ psWrapExtMemOUT->sClientSyncInfo.hMappingInfo = 0;
+ }
+#else
+ psWrapExtMemOUT->sClientSyncInfo.hMappingInfo =
+ psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle;
+#endif
+#endif
+
+ psWrapExtMemOUT->sClientMemInfo.psClientSyncInfo = &psWrapExtMemOUT->sClientSyncInfo;
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psWrapExtMemOUT->sClientSyncInfo.hKernelSyncInfo,
+ (IMG_HANDLE)psMemInfo->psKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+ psWrapExtMemOUT->sClientMemInfo.hKernelMemInfo);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psWrapExtMemOUT->eError, psPerProc)
+
+ return 0;
+}
+#endif
+
+static IMG_INT
+PVRSRVUnwrapExtMemoryBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_UNWRAP_EXT_MEMORY *psUnwrapExtMemIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvMemInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_UNWRAP_EXT_MEMORY);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvMemInfo,
+ psUnwrapExtMemIN->hKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVUnwrapExtMemoryKM((PVRSRV_KERNEL_MEM_INFO *)pvMemInfo);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psUnwrapExtMemIN->hKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVGetFreeDeviceMemBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GETFREEDEVICEMEM *psGetFreeDeviceMemIN,
+ PVRSRV_BRIDGE_OUT_GETFREEDEVICEMEM *psGetFreeDeviceMemOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GETFREE_DEVICEMEM);
+
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ psGetFreeDeviceMemOUT->eError =
+ PVRSRVGetFreeDeviceMemKM(psGetFreeDeviceMemIN->ui32Flags,
+ &psGetFreeDeviceMemOUT->ui32Total,
+ &psGetFreeDeviceMemOUT->ui32Free,
+ &psGetFreeDeviceMemOUT->ui32LargestBlock);
+
+ return 0;
+}
+
+static IMG_INT
+PVRMMapOSMemHandleToMMapDataBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_MHANDLE_TO_MMAP_DATA *psMMapDataIN,
+ PVRSRV_BRIDGE_OUT_MHANDLE_TO_MMAP_DATA *psMMapDataOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MHANDLE_TO_MMAP_DATA);
+
+#if defined (__linux__)
+ psMMapDataOUT->eError =
+ PVRMMapOSMemHandleToMMapData(psPerProc,
+ psMMapDataIN->hMHandle,
+ &psMMapDataOUT->ui32MMapOffset,
+ &psMMapDataOUT->ui32ByteOffset,
+ &psMMapDataOUT->ui32RealByteSize,
+ &psMMapDataOUT->ui32UserVAddr);
+#else
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+ PVR_UNREFERENCED_PARAMETER(psMMapDataIN);
+
+ psMMapDataOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
+#endif
+ return 0;
+}
+
+
+static IMG_INT
+PVRMMapReleaseMMapDataBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RELEASE_MMAP_DATA *psMMapDataIN,
+ PVRSRV_BRIDGE_OUT_RELEASE_MMAP_DATA *psMMapDataOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RELEASE_MMAP_DATA);
+
+#if defined (__linux__)
+ psMMapDataOUT->eError =
+ PVRMMapReleaseMMapData(psPerProc,
+ psMMapDataIN->hMHandle,
+ &psMMapDataOUT->bMUnmap,
+ &psMMapDataOUT->ui32RealByteSize,
+ &psMMapDataOUT->ui32UserVAddr);
+#else
+
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+ PVR_UNREFERENCED_PARAMETER(psMMapDataIN);
+
+ psMMapDataOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
+#endif
+ return 0;
+}
+
+
+#if defined (SUPPORT_SID_INTERFACE)
+static IMG_INT
+PVRSRVChangeDeviceMemoryAttributesBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_CHG_DEV_MEM_ATTRIBS *psChgMemAttribIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hKernelMemInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CHG_DEV_MEM_ATTRIBS);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hKernelMemInfo,
+ psChgMemAttribIN->hKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVChangeDeviceMemoryAttributesKM(hKernelMemInfo, psChgMemAttribIN->ui32Attribs);
+
+ return 0;
+}
+#else
+static IMG_INT
+PVRSRVChangeDeviceMemoryAttributesBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_CHG_DEV_MEM_ATTRIBS *psChgMemAttribIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+ PVR_UNREFERENCED_PARAMETER(psChgMemAttribIN);
+ PVR_UNREFERENCED_PARAMETER(psRetOUT);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ return 0;
+}
+#endif
+
+#ifdef PDUMP
+static IMG_INT
+PDumpIsCaptureFrameBW(IMG_UINT32 ui32BridgeID,
+ IMG_VOID *psBridgeIn,
+ PVRSRV_BRIDGE_OUT_PDUMP_ISCAPTURING *psPDumpIsCapturingOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_ISCAPTURING);
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ psPDumpIsCapturingOUT->bIsCapturing = PDumpIsCaptureFrameKM();
+ psPDumpIsCapturingOUT->eError = PVRSRV_OK;
+
+ return 0;
+}
+
+static IMG_INT
+PDumpCommentBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_COMMENT *psPDumpCommentIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_COMMENT);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ psRetOUT->eError = PDumpCommentKM(&psPDumpCommentIN->szComment[0],
+ psPDumpCommentIN->ui32Flags);
+ return 0;
+}
+
+static IMG_INT
+PDumpSetFrameBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_SETFRAME *psPDumpSetFrameIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_SETFRAME);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ psRetOUT->eError = PDumpSetFrameKM(psPDumpSetFrameIN->ui32Frame);
+
+ return 0;
+}
+
+static IMG_INT
+PDumpRegWithFlagsBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_DUMPREG *psPDumpRegDumpIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_REG);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID **)&psDeviceNode,
+ psPDumpRegDumpIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = PDumpRegWithFlagsKM (psPDumpRegDumpIN->szRegRegion,
+ psPDumpRegDumpIN->sHWReg.ui32RegAddr,
+ psPDumpRegDumpIN->sHWReg.ui32RegVal,
+ psPDumpRegDumpIN->ui32Flags);
+
+ return 0;
+}
+
+static IMG_INT
+PDumpRegPolBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_REGPOL *psPDumpRegPolIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_REGPOL);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID **)&psDeviceNode,
+ psPDumpRegPolIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ psRetOUT->eError =
+ PDumpRegPolWithFlagsKM(psPDumpRegPolIN->szRegRegion,
+ psPDumpRegPolIN->sHWReg.ui32RegAddr,
+ psPDumpRegPolIN->sHWReg.ui32RegVal,
+ psPDumpRegPolIN->ui32Mask,
+ psPDumpRegPolIN->ui32Flags,
+ PDUMP_POLL_OPERATOR_EQUAL);
+
+ return 0;
+}
+
+static IMG_INT
+PDumpMemPolBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_MEMPOL *psPDumpMemPolIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvMemInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_MEMPOL);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvMemInfo,
+#if defined (SUPPORT_SID_INTERFACE)
+ psPDumpMemPolIN->hKernelMemInfo,
+#else
+ psPDumpMemPolIN->psKernelMemInfo,
+#endif
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PDumpMemPolKM(((PVRSRV_KERNEL_MEM_INFO *)pvMemInfo),
+ psPDumpMemPolIN->ui32Offset,
+ psPDumpMemPolIN->ui32Value,
+ psPDumpMemPolIN->ui32Mask,
+ psPDumpMemPolIN->eOperator,
+ psPDumpMemPolIN->ui32Flags,
+ MAKEUNIQUETAG(pvMemInfo));
+
+ return 0;
+}
+
+static IMG_INT
+PDumpMemBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_DUMPMEM *psPDumpMemDumpIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvMemInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DUMPMEM);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvMemInfo,
+#if defined (SUPPORT_SID_INTERFACE)
+ psPDumpMemDumpIN->hKernelMemInfo,
+#else
+ psPDumpMemDumpIN->psKernelMemInfo,
+#endif
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PDumpMemUM(psPerProc,
+ psPDumpMemDumpIN->pvAltLinAddr,
+ psPDumpMemDumpIN->pvLinAddr,
+ pvMemInfo,
+ psPDumpMemDumpIN->ui32Offset,
+ psPDumpMemDumpIN->ui32Bytes,
+ psPDumpMemDumpIN->ui32Flags,
+ MAKEUNIQUETAG(pvMemInfo));
+
+ return 0;
+}
+
+static IMG_INT
+PDumpBitmapBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_BITMAP *psPDumpBitmapIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_HANDLE hDevMemContextInt;
+
+ PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_VOID **)&psDeviceNode,
+ psPDumpBitmapIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle( psPerProc->psHandleBase,
+ &hDevMemContextInt,
+ psPDumpBitmapIN->hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PDumpBitmapKM(psDeviceNode,
+ &psPDumpBitmapIN->szFileName[0],
+ psPDumpBitmapIN->ui32FileOffset,
+ psPDumpBitmapIN->ui32Width,
+ psPDumpBitmapIN->ui32Height,
+ psPDumpBitmapIN->ui32StrideInBytes,
+ psPDumpBitmapIN->sDevBaseAddr,
+ hDevMemContextInt,
+ psPDumpBitmapIN->ui32Size,
+ psPDumpBitmapIN->ePixelFormat,
+ psPDumpBitmapIN->eMemFormat,
+ psPDumpBitmapIN->ui32Flags);
+
+ return 0;
+}
+
+static IMG_INT
+PDumpReadRegBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_READREG *psPDumpReadRegIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DUMPREADREG);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_VOID **)&psDeviceNode,
+ psPDumpReadRegIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ psRetOUT->eError =
+ PDumpReadRegKM(&psPDumpReadRegIN->szRegRegion[0],
+ &psPDumpReadRegIN->szFileName[0],
+ psPDumpReadRegIN->ui32FileOffset,
+ psPDumpReadRegIN->ui32Address,
+ psPDumpReadRegIN->ui32Size,
+ psPDumpReadRegIN->ui32Flags);
+
+ return 0;
+}
+
+static IMG_INT
+PDumpMemPagesBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_MEMPAGES *psPDumpMemPagesIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_MEMPAGES);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID **)&psDeviceNode,
+ psPDumpMemPagesIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ return 0;
+}
+
+static IMG_INT
+PDumpDriverInfoBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_DRIVERINFO *psPDumpDriverInfoIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_UINT32 ui32PDumpFlags;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DRIVERINFO);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ ui32PDumpFlags = 0;
+ if(psPDumpDriverInfoIN->bContinuous)
+ {
+ ui32PDumpFlags |= PDUMP_FLAGS_CONTINUOUS;
+ }
+ psRetOUT->eError =
+ PDumpDriverInfoKM(&psPDumpDriverInfoIN->szString[0],
+ ui32PDumpFlags);
+
+ return 0;
+}
+
+static IMG_INT
+PDumpSyncDumpBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_DUMPSYNC *psPDumpSyncDumpIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_UINT32 ui32Bytes = psPDumpSyncDumpIN->ui32Bytes;
+ IMG_VOID *pvSyncInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DUMPSYNC);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &pvSyncInfo,
+#if defined (SUPPORT_SID_INTERFACE)
+ psPDumpSyncDumpIN->hKernelSyncInfo,
+#else
+ psPDumpSyncDumpIN->psKernelSyncInfo,
+#endif
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PDumpMemUM(psPerProc,
+ psPDumpSyncDumpIN->pvAltLinAddr,
+ IMG_NULL,
+ ((PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo)->psSyncDataMemInfoKM,
+ psPDumpSyncDumpIN->ui32Offset,
+ ui32Bytes,
+ 0,
+ MAKEUNIQUETAG(((PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo)->psSyncDataMemInfoKM));
+
+ return 0;
+}
+
+static IMG_INT
+PDumpSyncPolBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_SYNCPOL *psPDumpSyncPolIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_UINT32 ui32Offset;
+ IMG_VOID *pvSyncInfo;
+ IMG_UINT32 ui32Value;
+ IMG_UINT32 ui32Mask;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_SYNCPOL);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvSyncInfo,
+#if defined (SUPPORT_SID_INTERFACE)
+ psPDumpSyncPolIN->hKernelSyncInfo,
+#else
+ psPDumpSyncPolIN->psKernelSyncInfo,
+#endif
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ if(psPDumpSyncPolIN->bIsRead)
+ {
+ ui32Offset = offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete);
+ }
+ else
+ {
+ ui32Offset = offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete);
+ }
+
+
+ if (psPDumpSyncPolIN->bUseLastOpDumpVal)
+ {
+ if(psPDumpSyncPolIN->bIsRead)
+ {
+ ui32Value = ((PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo)->psSyncData->ui32LastReadOpDumpVal;
+ }
+ else
+ {
+ ui32Value = ((PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo)->psSyncData->ui32LastOpDumpVal;
+ }
+ ui32Mask = 0xffffffff;
+ }
+ else
+ {
+ ui32Value = psPDumpSyncPolIN->ui32Value;
+ ui32Mask = psPDumpSyncPolIN->ui32Mask;
+ }
+
+ psRetOUT->eError =
+ PDumpMemPolKM(((PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo)->psSyncDataMemInfoKM,
+ ui32Offset,
+ ui32Value,
+ ui32Mask,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ 0,
+ MAKEUNIQUETAG(((PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo)->psSyncDataMemInfoKM));
+
+ return 0;
+}
+
+
+static IMG_INT
+PDumpCycleCountRegReadBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_CYCLE_COUNT_REG_READ *psPDumpCycleCountRegReadIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_CYCLE_COUNT_REG_READ);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID **)&psDeviceNode,
+ psPDumpCycleCountRegReadIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ PDumpCycleCountRegRead(&psDeviceNode->sDevId,
+ psPDumpCycleCountRegReadIN->ui32RegOffset,
+ psPDumpCycleCountRegReadIN->bLastFrame);
+
+ psRetOUT->eError = PVRSRV_OK;
+
+ return 0;
+}
+
+static IMG_INT
+PDumpPDDevPAddrBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_DUMPPDDEVPADDR *psPDumpPDDevPAddrIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvMemInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DUMPPDDEVPADDR);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &pvMemInfo,
+ psPDumpPDDevPAddrIN->hKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PDumpPDDevPAddrKM((PVRSRV_KERNEL_MEM_INFO *)pvMemInfo,
+ psPDumpPDDevPAddrIN->ui32Offset,
+ psPDumpPDDevPAddrIN->sPDDevPAddr,
+ MAKEUNIQUETAG(pvMemInfo),
+ PDUMP_PD_UNIQUETAG);
+ return 0;
+}
+
+static IMG_INT
+PDumpStartInitPhaseBW(IMG_UINT32 ui32BridgeID,
+ IMG_VOID *psBridgeIn,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_STARTINITPHASE);
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ psRetOUT->eError = PDumpStartInitPhaseKM();
+
+ return 0;
+}
+
+static IMG_INT
+PDumpStopInitPhaseBW(IMG_UINT32 ui32BridgeID,
+ IMG_VOID *psBridgeIn,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_STOPINITPHASE);
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ psRetOUT->eError = PDumpStopInitPhaseKM();
+
+ return 0;
+}
+
+#endif
+
+
+static IMG_INT
+PVRSRVGetMiscInfoBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GET_MISC_INFO *psGetMiscInfoIN,
+ PVRSRV_BRIDGE_OUT_GET_MISC_INFO *psGetMiscInfoOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+#if defined (SUPPORT_SID_INTERFACE)
+ PVRSRV_MISC_INFO_KM sMiscInfo = {0};
+#endif
+ PVRSRV_ERROR eError;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_MISC_INFO);
+
+#if defined (SUPPORT_SID_INTERFACE)
+ sMiscInfo.ui32StateRequest = psGetMiscInfoIN->sMiscInfo.ui32StateRequest;
+ sMiscInfo.ui32StatePresent = psGetMiscInfoIN->sMiscInfo.ui32StatePresent;
+ sMiscInfo.ui32MemoryStrLen = psGetMiscInfoIN->sMiscInfo.ui32MemoryStrLen;
+ sMiscInfo.pszMemoryStr = psGetMiscInfoIN->sMiscInfo.pszMemoryStr;
+
+ OSMemCopy(&sMiscInfo.sCacheOpCtl,
+ &psGetMiscInfoIN->sMiscInfo.sCacheOpCtl,
+ sizeof(sMiscInfo.sCacheOpCtl));
+ OSMemCopy(&sMiscInfo.sGetRefCountCtl,
+ &psGetMiscInfoIN->sMiscInfo.sGetRefCountCtl,
+ sizeof(sMiscInfo.sGetRefCountCtl));
+#else
+ OSMemCopy(&psGetMiscInfoOUT->sMiscInfo,
+ &psGetMiscInfoIN->sMiscInfo,
+ sizeof(PVRSRV_MISC_INFO));
+#endif
+
+ if (((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0) &&
+ ((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0) &&
+ ((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_FREEMEM_PRESENT) != 0))
+ {
+
+ psGetMiscInfoOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+
+ if (((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0) ||
+ ((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0) ||
+ ((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_FREEMEM_PRESENT) != 0))
+ {
+
+#if defined (SUPPORT_SID_INTERFACE)
+ ASSIGN_AND_EXIT_ON_ERROR(psGetMiscInfoOUT->eError,
+ OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ psGetMiscInfoOUT->sMiscInfo.ui32MemoryStrLen,
+ (IMG_VOID **)&sMiscInfo.pszMemoryStr, 0,
+ "Output string buffer"));
+ psGetMiscInfoOUT->eError = PVRSRVGetMiscInfoKM(&sMiscInfo);
+
+
+ eError = CopyToUserWrapper(psPerProc, ui32BridgeID,
+ psGetMiscInfoIN->sMiscInfo.pszMemoryStr,
+ sMiscInfo.pszMemoryStr,
+ sMiscInfo.ui32MemoryStrLen);
+#else
+ ASSIGN_AND_EXIT_ON_ERROR(psGetMiscInfoOUT->eError,
+ OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ psGetMiscInfoOUT->sMiscInfo.ui32MemoryStrLen,
+ (IMG_VOID **)&psGetMiscInfoOUT->sMiscInfo.pszMemoryStr, 0,
+ "Output string buffer"));
+
+ psGetMiscInfoOUT->eError = PVRSRVGetMiscInfoKM(&psGetMiscInfoOUT->sMiscInfo);
+
+
+ eError = CopyToUserWrapper(psPerProc, ui32BridgeID,
+ psGetMiscInfoIN->sMiscInfo.pszMemoryStr,
+ psGetMiscInfoOUT->sMiscInfo.pszMemoryStr,
+ psGetMiscInfoOUT->sMiscInfo.ui32MemoryStrLen);
+#endif
+
+
+#if defined (SUPPORT_SID_INTERFACE)
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sMiscInfo.ui32MemoryStrLen,
+ (IMG_VOID *)sMiscInfo.pszMemoryStr, 0);
+#else
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ psGetMiscInfoOUT->sMiscInfo.ui32MemoryStrLen,
+ (IMG_VOID *)psGetMiscInfoOUT->sMiscInfo.pszMemoryStr, 0);
+#endif
+
+
+ psGetMiscInfoOUT->sMiscInfo.pszMemoryStr = psGetMiscInfoIN->sMiscInfo.pszMemoryStr;
+
+ if(eError != PVRSRV_OK)
+ {
+
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetMiscInfoBW Error copy to user"));
+ return -EFAULT;
+ }
+ }
+ else
+ {
+#if defined (SUPPORT_SID_INTERFACE)
+ psGetMiscInfoOUT->eError = PVRSRVGetMiscInfoKM(&sMiscInfo);
+#else
+ psGetMiscInfoOUT->eError = PVRSRVGetMiscInfoKM(&psGetMiscInfoOUT->sMiscInfo);
+#endif
+ }
+
+
+ if (psGetMiscInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+#if defined (SUPPORT_SID_INTERFACE)
+ if (sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT)
+#else
+ if (psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT)
+#endif
+ {
+ psGetMiscInfoOUT->eError = PVRSRVAllocHandle(psPerProc->psHandleBase,
+ &psGetMiscInfoOUT->sMiscInfo.sGlobalEventObject.hOSEventKM,
+#if defined (SUPPORT_SID_INTERFACE)
+ sMiscInfo.sGlobalEventObject.hOSEventKM,
+#else
+ psGetMiscInfoOUT->sMiscInfo.sGlobalEventObject.hOSEventKM,
+#endif
+ PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+
+ if (psGetMiscInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+#if defined (SUPPORT_SID_INTERFACE)
+ OSMemCopy(&psGetMiscInfoOUT->sMiscInfo.sGlobalEventObject.szName,
+ sMiscInfo.sGlobalEventObject.szName,
+ EVENTOBJNAME_MAXLENGTH);
+#endif
+ }
+
+#if defined (SUPPORT_SID_INTERFACE)
+ if (sMiscInfo.hSOCTimerRegisterOSMemHandle)
+#else
+ if (psGetMiscInfoOUT->sMiscInfo.hSOCTimerRegisterOSMemHandle)
+#endif
+ {
+
+ psGetMiscInfoOUT->eError = PVRSRVAllocHandle(psPerProc->psHandleBase,
+ &psGetMiscInfoOUT->sMiscInfo.hSOCTimerRegisterOSMemHandle,
+#if defined (SUPPORT_SID_INTERFACE)
+ sMiscInfo.hSOCTimerRegisterOSMemHandle,
+#else
+ psGetMiscInfoOUT->sMiscInfo.hSOCTimerRegisterOSMemHandle,
+#endif
+ PVRSRV_HANDLE_TYPE_SOC_TIMER,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+
+ if (psGetMiscInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+#if defined (SUPPORT_SID_INTERFACE)
+ else
+ {
+ psGetMiscInfoOUT->sMiscInfo.hSOCTimerRegisterOSMemHandle = 0;
+ }
+
+
+ psGetMiscInfoOUT->sMiscInfo.ui32StateRequest = sMiscInfo.ui32StateRequest;
+ psGetMiscInfoOUT->sMiscInfo.ui32StatePresent = sMiscInfo.ui32StatePresent;
+
+ psGetMiscInfoOUT->sMiscInfo.pvSOCTimerRegisterKM = sMiscInfo.pvSOCTimerRegisterKM;
+ psGetMiscInfoOUT->sMiscInfo.pvSOCTimerRegisterUM = sMiscInfo.pvSOCTimerRegisterUM;
+ psGetMiscInfoOUT->sMiscInfo.pvSOCClockGateRegs = sMiscInfo.pvSOCClockGateRegs;
+
+ psGetMiscInfoOUT->sMiscInfo.ui32SOCClockGateRegsSize = sMiscInfo.ui32SOCClockGateRegsSize;
+
+ OSMemCopy(&psGetMiscInfoOUT->sMiscInfo.aui32DDKVersion,
+ &sMiscInfo.aui32DDKVersion,
+ sizeof(psGetMiscInfoOUT->sMiscInfo.aui32DDKVersion));
+ OSMemCopy(&psGetMiscInfoOUT->sMiscInfo.sCacheOpCtl,
+ &sMiscInfo.sCacheOpCtl,
+ sizeof(psGetMiscInfoOUT->sMiscInfo.sCacheOpCtl));
+ OSMemCopy(&psGetMiscInfoOUT->sMiscInfo.sGetRefCountCtl,
+ &sMiscInfo.sGetRefCountCtl,
+ sizeof(psGetMiscInfoOUT->sMiscInfo.sGetRefCountCtl));
+#endif
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVConnectBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_CONNECT_SERVICES *psConnectServicesIN,
+ PVRSRV_BRIDGE_OUT_CONNECT_SERVICES *psConnectServicesOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CONNECT_SERVICES);
+
+#if defined(PDUMP)
+
+ if ((psConnectServicesIN->ui32Flags & SRV_FLAGS_PERSIST) != 0)
+ {
+ psPerProc->bPDumpPersistent = IMG_TRUE;
+ }
+
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+
+ if ((psConnectServicesIN->ui32Flags & SRV_FLAGS_PDUMP_ACTIVE) != 0)
+ {
+ psPerProc->bPDumpActive = IMG_TRUE;
+ }
+#endif
+#else
+ PVR_UNREFERENCED_PARAMETER(psConnectServicesIN);
+#endif
+ psConnectServicesOUT->hKernelServices = psPerProc->hPerProcData;
+ psConnectServicesOUT->eError = PVRSRV_OK;
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVDisconnectBW(IMG_UINT32 ui32BridgeID,
+ IMG_VOID *psBridgeIn,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DISCONNECT_SERVICES);
+
+
+ psRetOUT->eError = PVRSRV_OK;
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVEnumerateDCBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_ENUMCLASS *psEnumDispClassIN,
+ PVRSRV_BRIDGE_OUT_ENUMCLASS *psEnumDispClassOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ENUM_CLASS);
+
+ psEnumDispClassOUT->eError =
+ PVRSRVEnumerateDCKM(psEnumDispClassIN->sDeviceClass,
+ &psEnumDispClassOUT->ui32NumDevices,
+ &psEnumDispClassOUT->ui32DevID[0]);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVOpenDCDeviceBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_OPEN_DISPCLASS_DEVICE *psOpenDispClassDeviceIN,
+ PVRSRV_BRIDGE_OUT_OPEN_DISPCLASS_DEVICE *psOpenDispClassDeviceOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_HANDLE hDispClassInfoInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_OPEN_DISPCLASS_DEVICE);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psOpenDispClassDeviceOUT->eError, psPerProc, 1)
+
+ psOpenDispClassDeviceOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psOpenDispClassDeviceIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psOpenDispClassDeviceOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psOpenDispClassDeviceOUT->eError =
+ PVRSRVOpenDCDeviceKM(psPerProc,
+ psOpenDispClassDeviceIN->ui32DeviceID,
+ hDevCookieInt,
+ &hDispClassInfoInt);
+
+ if(psOpenDispClassDeviceOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psOpenDispClassDeviceOUT->hDeviceKM,
+ hDispClassInfoInt,
+ PVRSRV_HANDLE_TYPE_DISP_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+ COMMIT_HANDLE_BATCH_OR_ERROR(psOpenDispClassDeviceOUT->eError, psPerProc)
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVCloseDCDeviceBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_CLOSE_DISPCLASS_DEVICE *psCloseDispClassDeviceIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvDispClassInfoInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CLOSE_DISPCLASS_DEVICE);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfoInt,
+ psCloseDispClassDeviceIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = PVRSRVCloseDCDeviceKM(pvDispClassInfoInt, IMG_FALSE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psCloseDispClassDeviceIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ return 0;
+}
+
+static IMG_INT
+PVRSRVEnumDCFormatsBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_FORMATS *psEnumDispClassFormatsIN,
+ PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_FORMATS *psEnumDispClassFormatsOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvDispClassInfoInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ENUM_DISPCLASS_FORMATS);
+
+ psEnumDispClassFormatsOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfoInt,
+ psEnumDispClassFormatsIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if(psEnumDispClassFormatsOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psEnumDispClassFormatsOUT->eError =
+ PVRSRVEnumDCFormatsKM(pvDispClassInfoInt,
+ &psEnumDispClassFormatsOUT->ui32Count,
+ psEnumDispClassFormatsOUT->asFormat);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVEnumDCDimsBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_DIMS *psEnumDispClassDimsIN,
+ PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_DIMS *psEnumDispClassDimsOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvDispClassInfoInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ENUM_DISPCLASS_DIMS);
+
+ psEnumDispClassDimsOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfoInt,
+ psEnumDispClassDimsIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+
+ if(psEnumDispClassDimsOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psEnumDispClassDimsOUT->eError =
+ PVRSRVEnumDCDimsKM(pvDispClassInfoInt,
+ &psEnumDispClassDimsIN->sFormat,
+ &psEnumDispClassDimsOUT->ui32Count,
+ psEnumDispClassDimsOUT->asDim);
+
+ return 0;
+}
+
+#if defined(SUPPORT_PVRSRV_GET_DC_SYSTEM_BUFFER)
+static IMG_INT
+PVRSRVGetDCSystemBufferBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GET_DISPCLASS_SYSBUFFER *psGetDispClassSysBufferIN,
+ PVRSRV_BRIDGE_OUT_GET_DISPCLASS_SYSBUFFER *psGetDispClassSysBufferOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hBufferInt;
+ IMG_VOID *pvDispClassInfoInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_DISPCLASS_SYSBUFFER);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psGetDispClassSysBufferOUT->eError, psPerProc, 1)
+
+ psGetDispClassSysBufferOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfoInt,
+ psGetDispClassSysBufferIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if(psGetDispClassSysBufferOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psGetDispClassSysBufferOUT->eError =
+ PVRSRVGetDCSystemBufferKM(pvDispClassInfoInt,
+ &hBufferInt);
+
+ if(psGetDispClassSysBufferOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psGetDispClassSysBufferOUT->hBuffer,
+ hBufferInt,
+ PVRSRV_HANDLE_TYPE_DISP_BUFFER,
+ (PVRSRV_HANDLE_ALLOC_FLAG)(PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE | PVRSRV_HANDLE_ALLOC_FLAG_SHARED),
+ psGetDispClassSysBufferIN->hDeviceKM);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psGetDispClassSysBufferOUT->eError, psPerProc)
+
+ return 0;
+}
+#endif
+
+static IMG_INT
+PVRSRVGetDCInfoBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GET_DISPCLASS_INFO *psGetDispClassInfoIN,
+ PVRSRV_BRIDGE_OUT_GET_DISPCLASS_INFO *psGetDispClassInfoOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvDispClassInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_DISPCLASS_INFO);
+
+ psGetDispClassInfoOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psGetDispClassInfoIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if(psGetDispClassInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psGetDispClassInfoOUT->eError =
+ PVRSRVGetDCInfoKM(pvDispClassInfo,
+ &psGetDispClassInfoOUT->sDisplayInfo);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVCreateDCSwapChainBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_CREATE_DISPCLASS_SWAPCHAIN *psCreateDispClassSwapChainIN,
+ PVRSRV_BRIDGE_OUT_CREATE_DISPCLASS_SWAPCHAIN *psCreateDispClassSwapChainOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvDispClassInfo;
+ IMG_HANDLE hSwapChainInt;
+ IMG_UINT32 ui32SwapChainID;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CREATE_DISPCLASS_SWAPCHAIN);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psCreateDispClassSwapChainOUT->eError, psPerProc, 1)
+
+ psCreateDispClassSwapChainOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psCreateDispClassSwapChainIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+
+ if(psCreateDispClassSwapChainOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ ui32SwapChainID = psCreateDispClassSwapChainIN->ui32SwapChainID;
+
+ psCreateDispClassSwapChainOUT->eError =
+ PVRSRVCreateDCSwapChainKM(psPerProc, pvDispClassInfo,
+ psCreateDispClassSwapChainIN->ui32Flags,
+ &psCreateDispClassSwapChainIN->sDstSurfAttrib,
+ &psCreateDispClassSwapChainIN->sSrcSurfAttrib,
+ psCreateDispClassSwapChainIN->ui32BufferCount,
+ psCreateDispClassSwapChainIN->ui32OEMFlags,
+ &hSwapChainInt,
+ &ui32SwapChainID);
+
+ if(psCreateDispClassSwapChainOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ psCreateDispClassSwapChainOUT->ui32SwapChainID = ui32SwapChainID;
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psCreateDispClassSwapChainOUT->hSwapChain,
+ hSwapChainInt,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+ psCreateDispClassSwapChainIN->hDeviceKM);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psCreateDispClassSwapChainOUT->eError, psPerProc)
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVDestroyDCSwapChainBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DESTROY_DISPCLASS_SWAPCHAIN *psDestroyDispClassSwapChainIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvSwapChain;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DESTROY_DISPCLASS_SWAPCHAIN);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &pvSwapChain,
+ psDestroyDispClassSwapChainIN->hSwapChain,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVDestroyDCSwapChainKM(pvSwapChain);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psDestroyDispClassSwapChainIN->hSwapChain,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVSetDCDstRectBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SET_DISPCLASS_RECT *psSetDispClassDstRectIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvDispClassInfo;
+ IMG_VOID *pvSwapChain;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SET_DISPCLASS_DSTRECT);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psSetDispClassDstRectIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvSwapChain,
+ psSetDispClassDstRectIN->hSwapChain,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVSetDCDstRectKM(pvDispClassInfo,
+ pvSwapChain,
+ &psSetDispClassDstRectIN->sRect);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVSetDCSrcRectBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SET_DISPCLASS_RECT *psSetDispClassSrcRectIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvDispClassInfo;
+ IMG_VOID *pvSwapChain;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SET_DISPCLASS_SRCRECT);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psSetDispClassSrcRectIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvSwapChain,
+ psSetDispClassSrcRectIN->hSwapChain,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVSetDCSrcRectKM(pvDispClassInfo,
+ pvSwapChain,
+ &psSetDispClassSrcRectIN->sRect);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVSetDCDstColourKeyBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SET_DISPCLASS_COLOURKEY *psSetDispClassColKeyIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvDispClassInfo;
+ IMG_VOID *pvSwapChain;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SET_DISPCLASS_DSTCOLOURKEY);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psSetDispClassColKeyIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvSwapChain,
+ psSetDispClassColKeyIN->hSwapChain,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVSetDCDstColourKeyKM(pvDispClassInfo,
+ pvSwapChain,
+ psSetDispClassColKeyIN->ui32CKColour);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVSetDCSrcColourKeyBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SET_DISPCLASS_COLOURKEY *psSetDispClassColKeyIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvDispClassInfo;
+ IMG_VOID *pvSwapChain;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SET_DISPCLASS_SRCCOLOURKEY);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psSetDispClassColKeyIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvSwapChain,
+ psSetDispClassColKeyIN->hSwapChain,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVSetDCSrcColourKeyKM(pvDispClassInfo,
+ pvSwapChain,
+ psSetDispClassColKeyIN->ui32CKColour);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVGetDCBuffersBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GET_DISPCLASS_BUFFERS *psGetDispClassBuffersIN,
+ PVRSRV_BRIDGE_OUT_GET_DISPCLASS_BUFFERS *psGetDispClassBuffersOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvDispClassInfo;
+ IMG_VOID *pvSwapChain;
+ IMG_UINT32 i;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_HANDLE *pahBuffer;
+#endif
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_DISPCLASS_BUFFERS);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psGetDispClassBuffersOUT->eError, psPerProc, PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS)
+
+ psGetDispClassBuffersOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psGetDispClassBuffersIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if(psGetDispClassBuffersOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psGetDispClassBuffersOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvSwapChain,
+ psGetDispClassBuffersIN->hSwapChain,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+ if(psGetDispClassBuffersOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+#if defined (SUPPORT_SID_INTERFACE)
+ psGetDispClassBuffersOUT->eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(IMG_HANDLE) * PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS,
+ (IMG_PVOID *)&pahBuffer, 0,
+ "Temp Swapchain Buffers");
+
+ if (psGetDispClassBuffersOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+#endif
+
+ psGetDispClassBuffersOUT->eError =
+ PVRSRVGetDCBuffersKM(pvDispClassInfo,
+ pvSwapChain,
+ &psGetDispClassBuffersOUT->ui32BufferCount,
+#if defined (SUPPORT_SID_INTERFACE)
+ pahBuffer,
+#else
+ psGetDispClassBuffersOUT->ahBuffer,
+#endif
+ psGetDispClassBuffersOUT->asPhyAddr);
+ if (psGetDispClassBuffersOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ PVR_ASSERT(psGetDispClassBuffersOUT->ui32BufferCount <= PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS);
+
+ for(i = 0; i < psGetDispClassBuffersOUT->ui32BufferCount; i++)
+ {
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hBufferExt;
+#else
+ IMG_HANDLE hBufferExt;
+#endif
+
+
+#if defined (SUPPORT_SID_INTERFACE)
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &hBufferExt,
+ pahBuffer[i],
+ PVRSRV_HANDLE_TYPE_DISP_BUFFER,
+ (PVRSRV_HANDLE_ALLOC_FLAG)(PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE | PVRSRV_HANDLE_ALLOC_FLAG_SHARED),
+ psGetDispClassBuffersIN->hSwapChain);
+#else
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &hBufferExt,
+ psGetDispClassBuffersOUT->ahBuffer[i],
+ PVRSRV_HANDLE_TYPE_DISP_BUFFER,
+ (PVRSRV_HANDLE_ALLOC_FLAG)(PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE | PVRSRV_HANDLE_ALLOC_FLAG_SHARED),
+ psGetDispClassBuffersIN->hSwapChain);
+#endif
+
+ psGetDispClassBuffersOUT->ahBuffer[i] = hBufferExt;
+ }
+
+#if defined (SUPPORT_SID_INTERFACE)
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(IMG_HANDLE) * PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS,
+ (IMG_PVOID)pahBuffer, 0);
+#endif
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psGetDispClassBuffersOUT->eError, psPerProc)
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVSwapToDCBufferBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_BUFFER *psSwapDispClassBufferIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvDispClassInfo;
+ IMG_VOID *pvSwapChainBuf;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_HANDLE hPrivateTag;
+#endif
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_BUFFER);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psSwapDispClassBufferIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupSubHandle(psPerProc->psHandleBase,
+ &pvSwapChainBuf,
+ psSwapDispClassBufferIN->hBuffer,
+ PVRSRV_HANDLE_TYPE_DISP_BUFFER,
+ psSwapDispClassBufferIN->hDeviceKM);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+#if defined (SUPPORT_SID_INTERFACE)
+ if (psSwapDispClassBufferIN->hPrivateTag != 0)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupSubHandle(psPerProc->psHandleBase,
+ &hPrivateTag,
+ psSwapDispClassBufferIN->hPrivateTag,
+ PVRSRV_HANDLE_TYPE_DISP_BUFFER,
+ psSwapDispClassBufferIN->hDeviceKM);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+ else
+ {
+ hPrivateTag = IMG_NULL;
+ }
+#endif
+
+ psRetOUT->eError =
+ PVRSRVSwapToDCBufferKM(pvDispClassInfo,
+ pvSwapChainBuf,
+ psSwapDispClassBufferIN->ui32SwapInterval,
+#if defined (SUPPORT_SID_INTERFACE)
+ hPrivateTag,
+#else
+ psSwapDispClassBufferIN->hPrivateTag,
+#endif
+ psSwapDispClassBufferIN->ui32ClipRectCount,
+ psSwapDispClassBufferIN->sClipRect);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVSwapToDCBuffer2BW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_BUFFER2 *psSwapDispClassBufferIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvPrivData = IMG_NULL;
+ IMG_VOID *pvDispClassInfo;
+ IMG_VOID *pvSwapChain;
+ IMG_UINT32 i;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_BUFFER2);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psSwapDispClassBufferIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSwapToDCBuffer2BW: Failed to look up DISP_INFO handle"));
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupSubHandle(psPerProc->psHandleBase,
+ &pvSwapChain,
+ psSwapDispClassBufferIN->hSwapChain,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN,
+ psSwapDispClassBufferIN->hDeviceKM);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSwapToDCBuffer2BW: Failed to look up DISP_BUFFER handle"));
+ return 0;
+ }
+
+ if(!OSAccessOK(PVR_VERIFY_WRITE,
+ psSwapDispClassBufferIN->ppsKernelMemInfos,
+ sizeof(IMG_HANDLE) * psSwapDispClassBufferIN->ui32NumMemInfos))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSwapToDCBuffer2BW: Access check failed for ppsKernelMemInfos"));
+ return -EFAULT;
+ }
+
+ if(!OSAccessOK(PVR_VERIFY_WRITE,
+ psSwapDispClassBufferIN->ppsKernelSyncInfos,
+ sizeof(IMG_HANDLE) * psSwapDispClassBufferIN->ui32NumMemInfos))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSwapToDCBuffer2BW: Access check failed for ppsKernelSyncInfos"));
+ return -EFAULT;
+ }
+
+ for (i = 0; i < psSwapDispClassBufferIN->ui32NumMemInfos; i++)
+ {
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_PVOID *)&psKernelMemInfo,
+ psSwapDispClassBufferIN->ppsKernelMemInfos[i],
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSwapToDCBuffer2BW: Failed to look up MEM_INFO handle"));
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_PVOID *)&psKernelSyncInfo,
+ psSwapDispClassBufferIN->ppsKernelSyncInfos[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSwapToDCBuffer2BW: Failed to look up SYNC_INFO handle"));
+ return 0;
+ }
+
+ psSwapDispClassBufferIN->ppsKernelMemInfos[i] = psKernelMemInfo;
+ psSwapDispClassBufferIN->ppsKernelSyncInfos[i] = psKernelSyncInfo;
+ }
+
+ if(psSwapDispClassBufferIN->ui32PrivDataLength > 0)
+ {
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ psSwapDispClassBufferIN->ui32PrivDataLength,
+ (IMG_VOID **)&pvPrivData, IMG_NULL,
+ "Swap Command Private Data") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2BW: Failed to allocate private data space"));
+ return -ENOMEM;
+ }
+
+ if(CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ pvPrivData,
+ psSwapDispClassBufferIN->pvPrivData,
+ psSwapDispClassBufferIN->ui32PrivDataLength) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSwapToDCBuffer2BW: Failed to copy private data"));
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ psSwapDispClassBufferIN->ui32PrivDataLength,
+ pvPrivData, IMG_NULL);
+ return -EFAULT;
+ }
+ }
+
+ psRetOUT->eError =
+ PVRSRVSwapToDCBuffer2KM(pvDispClassInfo,
+ pvSwapChain,
+ psSwapDispClassBufferIN->ui32SwapInterval,
+ psSwapDispClassBufferIN->ppsKernelMemInfos,
+ psSwapDispClassBufferIN->ppsKernelSyncInfos,
+ psSwapDispClassBufferIN->ui32NumMemInfos,
+ pvPrivData,
+ psSwapDispClassBufferIN->ui32PrivDataLength);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ psSwapDispClassBufferIN->ui32PrivDataLength,
+ pvPrivData, IMG_NULL);
+ }
+
+ return 0;
+}
+
+
+
+static IMG_INT
+PVRSRVSwapToDCSystemBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_SYSTEM *psSwapDispClassSystemIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvDispClassInfo;
+ IMG_VOID *pvSwapChain;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_SYSTEM);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psSwapDispClassSystemIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupSubHandle(psPerProc->psHandleBase,
+ &pvSwapChain,
+ psSwapDispClassSystemIN->hSwapChain,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN,
+ psSwapDispClassSystemIN->hDeviceKM);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ psRetOUT->eError =
+ PVRSRVSwapToDCSystemKM(pvDispClassInfo,
+ pvSwapChain);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVOpenBCDeviceBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_OPEN_BUFFERCLASS_DEVICE *psOpenBufferClassDeviceIN,
+ PVRSRV_BRIDGE_OUT_OPEN_BUFFERCLASS_DEVICE *psOpenBufferClassDeviceOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_HANDLE hBufClassInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_OPEN_BUFFERCLASS_DEVICE);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psOpenBufferClassDeviceOUT->eError, psPerProc, 1)
+
+ psOpenBufferClassDeviceOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psOpenBufferClassDeviceIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psOpenBufferClassDeviceOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psOpenBufferClassDeviceOUT->eError =
+ PVRSRVOpenBCDeviceKM(psPerProc,
+ psOpenBufferClassDeviceIN->ui32DeviceID,
+ hDevCookieInt,
+ &hBufClassInfo);
+ if(psOpenBufferClassDeviceOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psOpenBufferClassDeviceOUT->hDeviceKM,
+ hBufClassInfo,
+ PVRSRV_HANDLE_TYPE_BUF_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psOpenBufferClassDeviceOUT->eError, psPerProc)
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVCloseBCDeviceBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_CLOSE_BUFFERCLASS_DEVICE *psCloseBufferClassDeviceIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvBufClassInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CLOSE_BUFFERCLASS_DEVICE);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvBufClassInfo,
+ psCloseBufferClassDeviceIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_BUF_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVCloseBCDeviceKM(pvBufClassInfo, IMG_FALSE);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psCloseBufferClassDeviceIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_BUF_INFO);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVGetBCInfoBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_INFO *psGetBufferClassInfoIN,
+ PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_INFO *psGetBufferClassInfoOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvBufClassInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_BUFFERCLASS_INFO);
+
+ psGetBufferClassInfoOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvBufClassInfo,
+ psGetBufferClassInfoIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_BUF_INFO);
+ if(psGetBufferClassInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psGetBufferClassInfoOUT->eError =
+ PVRSRVGetBCInfoKM(pvBufClassInfo,
+ &psGetBufferClassInfoOUT->sBufferInfo);
+ return 0;
+}
+
+static IMG_INT
+PVRSRVGetBCBufferBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_BUFFER *psGetBufferClassBufferIN,
+ PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_BUFFER *psGetBufferClassBufferOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvBufClassInfo;
+ IMG_HANDLE hBufferInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_BUFFERCLASS_BUFFER);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psGetBufferClassBufferOUT->eError, psPerProc, 1)
+
+ psGetBufferClassBufferOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvBufClassInfo,
+ psGetBufferClassBufferIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_BUF_INFO);
+ if(psGetBufferClassBufferOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psGetBufferClassBufferOUT->eError =
+ PVRSRVGetBCBufferKM(pvBufClassInfo,
+ psGetBufferClassBufferIN->ui32BufferIndex,
+ &hBufferInt);
+
+ if(psGetBufferClassBufferOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psGetBufferClassBufferOUT->hBuffer,
+ hBufferInt,
+ PVRSRV_HANDLE_TYPE_BUF_BUFFER,
+ (PVRSRV_HANDLE_ALLOC_FLAG)(PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE | PVRSRV_HANDLE_ALLOC_FLAG_SHARED),
+ psGetBufferClassBufferIN->hDeviceKM);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psGetBufferClassBufferOUT->eError, psPerProc)
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVAllocSharedSysMemoryBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_ALLOC_SHARED_SYS_MEM *psAllocSharedSysMemIN,
+ PVRSRV_BRIDGE_OUT_ALLOC_SHARED_SYS_MEM *psAllocSharedSysMemOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ALLOC_SHARED_SYS_MEM);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psAllocSharedSysMemOUT->eError, psPerProc, 1)
+
+ psAllocSharedSysMemOUT->eError =
+ PVRSRVAllocSharedSysMemoryKM(psPerProc,
+ psAllocSharedSysMemIN->ui32Flags,
+ psAllocSharedSysMemIN->ui32Size,
+ &psKernelMemInfo);
+ if(psAllocSharedSysMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ OSMemSet(&psAllocSharedSysMemOUT->sClientMemInfo,
+ 0,
+ sizeof(psAllocSharedSysMemOUT->sClientMemInfo));
+
+ psAllocSharedSysMemOUT->sClientMemInfo.pvLinAddrKM =
+ psKernelMemInfo->pvLinAddrKM;
+
+ psAllocSharedSysMemOUT->sClientMemInfo.pvLinAddr = 0;
+ psAllocSharedSysMemOUT->sClientMemInfo.ui32Flags =
+ psKernelMemInfo->ui32Flags;
+ psAllocSharedSysMemOUT->sClientMemInfo.uAllocSize =
+ psKernelMemInfo->uAllocSize;
+#if defined (SUPPORT_SID_INTERFACE)
+ if (psKernelMemInfo->sMemBlk.hOSMemHandle != IMG_NULL)
+ {
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psAllocSharedSysMemOUT->sClientMemInfo.hMappingInfo,
+ psKernelMemInfo->sMemBlk.hOSMemHandle,
+ PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+ }
+ else
+ {
+ psAllocSharedSysMemOUT->sClientMemInfo.hMappingInfo = 0;
+ }
+#else
+ psAllocSharedSysMemOUT->sClientMemInfo.hMappingInfo = psKernelMemInfo->sMemBlk.hOSMemHandle;
+#endif
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psAllocSharedSysMemOUT->sClientMemInfo.hKernelMemInfo,
+ psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psAllocSharedSysMemOUT->eError, psPerProc)
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVFreeSharedSysMemoryBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_FREE_SHARED_SYS_MEM *psFreeSharedSysMemIN,
+ PVRSRV_BRIDGE_OUT_FREE_SHARED_SYS_MEM *psFreeSharedSysMemOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_FREE_SHARED_SYS_MEM);
+
+ psFreeSharedSysMemOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID **)&psKernelMemInfo,
+#if defined (SUPPORT_SID_INTERFACE)
+ psFreeSharedSysMemIN->hKernelMemInfo,
+#else
+ psFreeSharedSysMemIN->psKernelMemInfo,
+#endif
+ PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+
+ if(psFreeSharedSysMemOUT->eError != PVRSRV_OK)
+ return 0;
+
+ psFreeSharedSysMemOUT->eError =
+ PVRSRVFreeSharedSysMemoryKM(psKernelMemInfo);
+ if(psFreeSharedSysMemOUT->eError != PVRSRV_OK)
+ return 0;
+#if defined (SUPPORT_SID_INTERFACE)
+ if (psFreeSharedSysMemIN->hMappingInfo != 0)
+ {
+ psFreeSharedSysMemOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psFreeSharedSysMemIN->hMappingInfo,
+ PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+ if(psFreeSharedSysMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+#endif
+
+ psFreeSharedSysMemOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ psFreeSharedSysMemIN->hKernelMemInfo,
+#else
+ psFreeSharedSysMemIN->psKernelMemInfo,
+#endif
+ PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+ return 0;
+}
+
+static IMG_INT
+PVRSRVMapMemInfoMemBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_MAP_MEMINFO_MEM *psMapMemInfoMemIN,
+ PVRSRV_BRIDGE_OUT_MAP_MEMINFO_MEM *psMapMemInfoMemOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ PVRSRV_HANDLE_TYPE eHandleType;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hParent;
+#else
+ IMG_HANDLE hParent;
+#endif
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MAP_MEMINFO_MEM);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psMapMemInfoMemOUT->eError, psPerProc, 2)
+
+ psMapMemInfoMemOUT->eError =
+ PVRSRVLookupHandleAnyType(psPerProc->psHandleBase,
+ (IMG_VOID **)&psKernelMemInfo,
+ &eHandleType,
+ psMapMemInfoMemIN->hKernelMemInfo);
+ if(psMapMemInfoMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ switch (eHandleType)
+ {
+#if defined(PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE)
+ case PVRSRV_HANDLE_TYPE_MEM_INFO:
+ case PVRSRV_HANDLE_TYPE_MEM_INFO_REF:
+ case PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO:
+#else
+ case PVRSRV_HANDLE_TYPE_NONE:
+#endif
+ break;
+ default:
+ psMapMemInfoMemOUT->eError = PVRSRV_ERROR_INVALID_HANDLE_TYPE;
+ return 0;
+ }
+
+
+ psMapMemInfoMemOUT->eError =
+ PVRSRVGetParentHandle(psPerProc->psHandleBase,
+ &hParent,
+ psMapMemInfoMemIN->hKernelMemInfo,
+ eHandleType);
+ if (psMapMemInfoMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+#if defined (SUPPORT_SID_INTERFACE)
+ if (hParent == 0)
+#else
+ if (hParent == IMG_NULL)
+#endif
+ {
+ hParent = psMapMemInfoMemIN->hKernelMemInfo;
+ }
+
+ OSMemSet(&psMapMemInfoMemOUT->sClientMemInfo,
+ 0,
+ sizeof(psMapMemInfoMemOUT->sClientMemInfo));
+
+ psMapMemInfoMemOUT->sClientMemInfo.pvLinAddrKM =
+ psKernelMemInfo->pvLinAddrKM;
+
+ psMapMemInfoMemOUT->sClientMemInfo.pvLinAddr = 0;
+ psMapMemInfoMemOUT->sClientMemInfo.sDevVAddr =
+ psKernelMemInfo->sDevVAddr;
+ psMapMemInfoMemOUT->sClientMemInfo.ui32Flags =
+ psKernelMemInfo->ui32Flags;
+ psMapMemInfoMemOUT->sClientMemInfo.uAllocSize =
+ psKernelMemInfo->uAllocSize;
+#if defined (SUPPORT_SID_INTERFACE)
+ if (psKernelMemInfo->sMemBlk.hOSMemHandle != IMG_NULL)
+ {
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psMapMemInfoMemOUT->sClientMemInfo.hMappingInfo,
+ psKernelMemInfo->sMemBlk.hOSMemHandle,
+ PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ hParent);
+ }
+ else
+ {
+ psMapMemInfoMemOUT->sClientMemInfo.hMappingInfo = 0;
+ }
+#else
+ psMapMemInfoMemOUT->sClientMemInfo.hMappingInfo = psKernelMemInfo->sMemBlk.hOSMemHandle;
+#endif
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psMapMemInfoMemOUT->sClientMemInfo.hKernelMemInfo,
+ psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ hParent);
+
+ if(psKernelMemInfo->ui32Flags & PVRSRV_MEM_NO_SYNCOBJ)
+ {
+
+ OSMemSet(&psMapMemInfoMemOUT->sClientSyncInfo,
+ 0,
+ sizeof (PVRSRV_CLIENT_SYNC_INFO));
+ }
+ else
+ {
+
+#if !defined(PVRSRV_DISABLE_UM_SYNCOBJ_MAPPINGS)
+ psMapMemInfoMemOUT->sClientSyncInfo.psSyncData =
+ psKernelMemInfo->psKernelSyncInfo->psSyncData;
+ psMapMemInfoMemOUT->sClientSyncInfo.sWriteOpsCompleteDevVAddr =
+ psKernelMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+ psMapMemInfoMemOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
+ psKernelMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+ psMapMemInfoMemOUT->sClientSyncInfo.sReadOps2CompleteDevVAddr =
+ psKernelMemInfo->psKernelSyncInfo->sReadOps2CompleteDevVAddr;
+ psMapMemInfoMemOUT->sClientSyncInfo.sReadOps2CompleteDevVAddr =
+ psKernelMemInfo->psKernelSyncInfo->sReadOps2CompleteDevVAddr;
+
+#if defined (SUPPORT_SID_INTERFACE)
+ if (psKernelMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle != IMG_NULL)
+ {
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psMapMemInfoMemOUT->sClientSyncInfo.hMappingInfo,
+ psKernelMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ psMapMemInfoMemOUT->sClientMemInfo.hKernelMemInfo);
+ }
+ else
+ {
+ psMapMemInfoMemOUT->sClientSyncInfo.hMappingInfo = 0;
+ }
+#else
+ psMapMemInfoMemOUT->sClientSyncInfo.hMappingInfo =
+ psKernelMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle;
+#endif
+#endif
+
+ psMapMemInfoMemOUT->sClientMemInfo.psClientSyncInfo = &psMapMemInfoMemOUT->sClientSyncInfo;
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psMapMemInfoMemOUT->sClientSyncInfo.hKernelSyncInfo,
+ psKernelMemInfo->psKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ psMapMemInfoMemOUT->sClientMemInfo.hKernelMemInfo);
+ }
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psMapMemInfoMemOUT->eError, psPerProc)
+
+ return 0;
+}
+
+
+
+IMG_INT
+DummyBW(IMG_UINT32 ui32BridgeID,
+ IMG_VOID *psBridgeIn,
+ IMG_VOID *psBridgeOut,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+#if !defined(DEBUG)
+ PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+#endif
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+ PVR_UNREFERENCED_PARAMETER(psBridgeOut);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+#if defined(DEBUG_BRIDGE_KM)
+ PVR_DPF((PVR_DBG_ERROR, "%s: BRIDGE ERROR: BridgeID %u (%s) mapped to "
+ "Dummy Wrapper (probably not what you want!)",
+ __FUNCTION__, ui32BridgeID, g_BridgeDispatchTable[ui32BridgeID].pszIOCName));
+#else
+ PVR_DPF((PVR_DBG_ERROR, "%s: BRIDGE ERROR: BridgeID %u mapped to "
+ "Dummy Wrapper (probably not what you want!)",
+ __FUNCTION__, ui32BridgeID));
+#endif
+ return -ENOTTY;
+}
+
+
+IMG_VOID
+_SetDispatchTableEntry(IMG_UINT32 ui32Index,
+ const IMG_CHAR *pszIOCName,
+ BridgeWrapperFunction pfFunction,
+ const IMG_CHAR *pszFunctionName)
+{
+ static IMG_UINT32 ui32PrevIndex = ~0UL;
+#if !defined(DEBUG)
+ PVR_UNREFERENCED_PARAMETER(pszIOCName);
+#endif
+#if !defined(DEBUG_BRIDGE_KM_DISPATCH_TABLE) && !defined(DEBUG_BRIDGE_KM)
+ PVR_UNREFERENCED_PARAMETER(pszFunctionName);
+#endif
+
+#if defined(DEBUG_BRIDGE_KM_DISPATCH_TABLE)
+
+ PVR_DPF((PVR_DBG_WARNING, "%s: %d %s %s", __FUNCTION__, ui32Index, pszIOCName, pszFunctionName));
+#endif
+
+
+ if(g_BridgeDispatchTable[ui32Index].pfFunction)
+ {
+#if defined(DEBUG_BRIDGE_KM)
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: BUG!: Adding dispatch table entry for %s clobbers an existing entry for %s",
+ __FUNCTION__, pszIOCName, g_BridgeDispatchTable[ui32Index].pszIOCName));
+#else
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: BUG!: Adding dispatch table entry for %s clobbers an existing entry (index=%u)",
+ __FUNCTION__, pszIOCName, ui32Index));
+#endif
+ PVR_DPF((PVR_DBG_ERROR, "NOTE: Enabling DEBUG_BRIDGE_KM_DISPATCH_TABLE may help debug this issue."));
+ }
+
+
+ if((ui32PrevIndex != ~0UL) &&
+ ((ui32Index >= ui32PrevIndex + DISPATCH_TABLE_GAP_THRESHOLD) ||
+ (ui32Index <= ui32PrevIndex)))
+ {
+#if defined(DEBUG_BRIDGE_KM)
+ PVR_DPF((PVR_DBG_WARNING,
+ "%s: There is a gap in the dispatch table between indices %u (%s) and %u (%s)",
+ __FUNCTION__, ui32PrevIndex, g_BridgeDispatchTable[ui32PrevIndex].pszIOCName,
+ ui32Index, pszIOCName));
+#else
+ PVR_DPF((PVR_DBG_WARNING,
+ "%s: There is a gap in the dispatch table between indices %u and %u (%s)",
+ __FUNCTION__, (IMG_UINT)ui32PrevIndex, (IMG_UINT)ui32Index, pszIOCName));
+#endif
+ PVR_DPF((PVR_DBG_ERROR, "NOTE: Enabling DEBUG_BRIDGE_KM_DISPATCH_TABLE may help debug this issue."));
+ }
+
+ g_BridgeDispatchTable[ui32Index].pfFunction = pfFunction;
+#if defined(DEBUG_BRIDGE_KM)
+ g_BridgeDispatchTable[ui32Index].pszIOCName = pszIOCName;
+ g_BridgeDispatchTable[ui32Index].pszFunctionName = pszFunctionName;
+ g_BridgeDispatchTable[ui32Index].ui32CallCount = 0;
+ g_BridgeDispatchTable[ui32Index].ui32CopyFromUserTotalBytes = 0;
+#endif
+
+ ui32PrevIndex = ui32Index;
+}
+
+static IMG_INT
+PVRSRVInitSrvConnectBW(IMG_UINT32 ui32BridgeID,
+ IMG_VOID *psBridgeIn,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_INITSRV_CONNECT);
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+
+
+ if((OSProcHasPrivSrvInit() == IMG_FALSE) || PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RUNNING) || PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RAN))
+ {
+ psRetOUT->eError = PVRSRV_ERROR_SRV_CONNECT_FAILED;
+ return 0;
+ }
+
+#if defined (__linux__)
+ PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_RUNNING, IMG_TRUE);
+#endif
+ psPerProc->bInitProcess = IMG_TRUE;
+
+ psRetOUT->eError = PVRSRV_OK;
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVInitSrvDisconnectBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_INITSRV_DISCONNECT *psInitSrvDisconnectIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_INITSRV_DISCONNECT);
+
+ if(!psPerProc->bInitProcess)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_SRV_DISCONNECT_FAILED;
+ return 0;
+ }
+
+ psPerProc->bInitProcess = IMG_FALSE;
+
+ PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_RUNNING, IMG_FALSE);
+ PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_RAN, IMG_TRUE);
+
+ psRetOUT->eError = PVRSRVFinaliseSystem(psInitSrvDisconnectIN->bInitSuccesful);
+
+ PVRSRVSetInitServerState( PVRSRV_INIT_SERVER_SUCCESSFUL ,
+ ((psRetOUT->eError == PVRSRV_OK) && (psInitSrvDisconnectIN->bInitSuccesful))
+ ? IMG_TRUE : IMG_FALSE);
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVEventObjectWaitBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_EVENT_OBJECT_WAIT *psEventObjectWaitIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hOSEventKM;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_EVENT_OBJECT_WAIT);
+
+ psRetOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hOSEventKM,
+ psEventObjectWaitIN->hOSEventKM,
+ PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = OSEventObjectWaitKM(hOSEventKM);
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVEventObjectOpenBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_EVENT_OBJECT_OPEN *psEventObjectOpenIN,
+ PVRSRV_BRIDGE_OUT_EVENT_OBJECT_OPEN *psEventObjectOpenOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+#if defined (SUPPORT_SID_INTERFACE)
+ PVRSRV_EVENTOBJECT_KM sEventObject;
+ IMG_HANDLE hOSEvent;
+#endif
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_EVENT_OBJECT_OPEN);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psEventObjectOpenOUT->eError, psPerProc, 1)
+
+ psEventObjectOpenOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &sEventObject.hOSEventKM,
+#else
+ &psEventObjectOpenIN->sEventObject.hOSEventKM,
+#endif
+ psEventObjectOpenIN->sEventObject.hOSEventKM,
+ PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT);
+
+ if(psEventObjectOpenOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+#if defined (SUPPORT_SID_INTERFACE)
+ OSMemCopy(&sEventObject.szName,
+ &psEventObjectOpenIN->sEventObject.szName,
+ EVENTOBJNAME_MAXLENGTH);
+
+ psEventObjectOpenOUT->eError = OSEventObjectOpenKM(&sEventObject, &hOSEvent);
+#else
+ psEventObjectOpenOUT->eError = OSEventObjectOpenKM(&psEventObjectOpenIN->sEventObject, &psEventObjectOpenOUT->hOSEvent);
+#endif
+
+ if(psEventObjectOpenOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+#if defined (SUPPORT_SID_INTERFACE)
+#if !defined (WINXP) && !defined(SUPPORT_VISTA)
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psEventObjectOpenOUT->hOSEvent,
+ hOSEvent,
+ PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI);
+#endif
+#else
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psEventObjectOpenOUT->hOSEvent,
+ psEventObjectOpenOUT->hOSEvent,
+ PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI);
+#endif
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psEventObjectOpenOUT->eError, psPerProc)
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVEventObjectCloseBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_EVENT_OBJECT_CLOSE *psEventObjectCloseIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hOSEventKM;
+#if defined (SUPPORT_SID_INTERFACE)
+ PVRSRV_EVENTOBJECT_KM sEventObject;
+#endif
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_EVENT_OBJECT_CLOSE);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &sEventObject.hOSEventKM,
+#else
+ &psEventObjectCloseIN->sEventObject.hOSEventKM,
+#endif
+ psEventObjectCloseIN->sEventObject.hOSEventKM,
+ PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &hOSEventKM,
+ psEventObjectCloseIN->hOSEventKM,
+ PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+#if defined (SUPPORT_SID_INTERFACE)
+ if(CopyFromUserWrapper(psPerProc, ui32BridgeID,
+ &sEventObject.szName,
+ &psEventObjectCloseIN->sEventObject.szName,
+ EVENTOBJNAME_MAXLENGTH) != PVRSRV_OK)
+ {
+
+ return -EFAULT;
+ }
+
+ psRetOUT->eError = OSEventObjectCloseKM(&sEventObject, hOSEventKM);
+#else
+ psRetOUT->eError = OSEventObjectCloseKM(&psEventObjectCloseIN->sEventObject, hOSEventKM);
+#endif
+
+ return 0;
+}
+
+
+typedef struct _MODIFY_SYNC_OP_INFO
+{
+ IMG_HANDLE hResItem;
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+ IMG_UINT32 ui32ModifyFlags;
+ IMG_UINT32 ui32ReadOpsPendingSnapShot;
+ IMG_UINT32 ui32WriteOpsPendingSnapShot;
+ IMG_UINT32 ui32ReadOps2PendingSnapShot;
+} MODIFY_SYNC_OP_INFO;
+
+
+static PVRSRV_ERROR DoQuerySyncOpsSatisfied(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo,
+ IMG_UINT32 ui32ReadOpsPendingSnapShot,
+ IMG_UINT32 ui32WriteOpsPendingSnapShot,
+ IMG_UINT32 ui32ReadOps2PendingSnapShot)
+{
+ IMG_UINT32 ui32WriteOpsPending;
+ IMG_UINT32 ui32ReadOpsPending;
+ IMG_UINT32 ui32ReadOps2Pending;
+
+
+ if (!psKernelSyncInfo)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+
+
+
+
+
+
+
+
+
+ ui32WriteOpsPending = psKernelSyncInfo->psSyncData->ui32WriteOpsPending;
+ ui32ReadOpsPending = psKernelSyncInfo->psSyncData->ui32ReadOpsPending;
+ ui32ReadOps2Pending = psKernelSyncInfo->psSyncData->ui32ReadOps2Pending;
+
+ if((ui32WriteOpsPending - ui32WriteOpsPendingSnapShot >=
+ ui32WriteOpsPending - psKernelSyncInfo->psSyncData->ui32WriteOpsComplete) &&
+ (ui32ReadOpsPending - ui32ReadOpsPendingSnapShot >=
+ ui32ReadOpsPending - psKernelSyncInfo->psSyncData->ui32ReadOpsComplete) &&
+ (ui32ReadOps2Pending - ui32ReadOps2PendingSnapShot >=
+ ui32ReadOps2Pending - psKernelSyncInfo->psSyncData->ui32ReadOps2Complete))
+ {
+#if defined(PDUMP) && !defined(SUPPORT_VGX)
+
+ PDumpComment("Poll for read ops complete to reach value (pdump: %u, actual snapshot: %u)",
+ psKernelSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ ui32ReadOpsPendingSnapShot);
+ PDumpMemPolKM(psKernelSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete),
+ psKernelSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ 0xFFFFFFFF,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ 0,
+ MAKEUNIQUETAG(psKernelSyncInfo->psSyncDataMemInfoKM));
+
+
+ PDumpComment("Poll for write ops complete to reach value (pdump: %u, actual snapshot: %u)",
+ psKernelSyncInfo->psSyncData->ui32LastOpDumpVal,
+ ui32WriteOpsPendingSnapShot);
+ PDumpMemPolKM(psKernelSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete),
+ psKernelSyncInfo->psSyncData->ui32LastOpDumpVal,
+ 0xFFFFFFFF,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ 0,
+ MAKEUNIQUETAG(psKernelSyncInfo->psSyncDataMemInfoKM));
+
+
+#endif
+ return PVRSRV_OK;
+ }
+ else
+ {
+ return PVRSRV_ERROR_RETRY;
+ }
+}
+
+
+static PVRSRV_ERROR DoModifyCompleteSyncOps(MODIFY_SYNC_OP_INFO *psModSyncOpInfo)
+{
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+
+ psKernelSyncInfo = psModSyncOpInfo->psKernelSyncInfo;
+
+ if (!psKernelSyncInfo)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ if((psModSyncOpInfo->ui32WriteOpsPendingSnapShot != psKernelSyncInfo->psSyncData->ui32WriteOpsComplete)
+ || (psModSyncOpInfo->ui32ReadOpsPendingSnapShot != psKernelSyncInfo->psSyncData->ui32ReadOpsComplete))
+ {
+ return PVRSRV_ERROR_BAD_SYNC_STATE;
+ }
+
+
+ if(psModSyncOpInfo->ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_WO_INC)
+ {
+ psKernelSyncInfo->psSyncData->ui32WriteOpsComplete++;
+ }
+
+
+ if(psModSyncOpInfo->ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_RO_INC)
+ {
+ psKernelSyncInfo->psSyncData->ui32ReadOpsComplete++;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR ModifyCompleteSyncOpsCallBack(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param,
+ IMG_BOOL bDummy)
+{
+ MODIFY_SYNC_OP_INFO *psModSyncOpInfo;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+ PVR_UNREFERENCED_PARAMETER(bDummy);
+
+ if (!pvParam)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ModifyCompleteSyncOpsCallBack: invalid parameter"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psModSyncOpInfo = (MODIFY_SYNC_OP_INFO*)pvParam;
+
+ if (psModSyncOpInfo->psKernelSyncInfo)
+ {
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ if (DoQuerySyncOpsSatisfied(psModSyncOpInfo->psKernelSyncInfo,
+ psModSyncOpInfo->ui32ReadOpsPendingSnapShot,
+ psModSyncOpInfo->ui32WriteOpsPendingSnapShot,
+ psModSyncOpInfo->ui32ReadOps2PendingSnapShot) == PVRSRV_OK)
+ {
+ goto OpFlushedComplete;
+ }
+ PVR_DPF((PVR_DBG_WARNING, "ModifyCompleteSyncOpsCallBack: waiting for current Ops to flush"));
+ OSSleepms(1);
+ } END_LOOP_UNTIL_TIMEOUT();
+
+ PVR_DPF((PVR_DBG_ERROR, "ModifyCompleteSyncOpsCallBack: timeout whilst waiting for current Ops to flush."));
+ PVR_DPF((PVR_DBG_ERROR, " Write ops pending snapshot = %d, write ops complete = %d",
+ psModSyncOpInfo->ui32WriteOpsPendingSnapShot,
+ psModSyncOpInfo->psKernelSyncInfo->psSyncData->ui32WriteOpsComplete));
+ PVR_DPF((PVR_DBG_ERROR, " Read ops pending snapshot = %d, read ops complete = %d",
+ psModSyncOpInfo->ui32ReadOpsPendingSnapShot,
+ psModSyncOpInfo->psKernelSyncInfo->psSyncData->ui32ReadOpsComplete));
+ PVR_DPF((PVR_DBG_ERROR, " Read ops pending snapshot = %d, read ops2 complete = %d",
+ psModSyncOpInfo->ui32ReadOps2PendingSnapShot,
+ psModSyncOpInfo->psKernelSyncInfo->psSyncData->ui32ReadOps2Complete));
+ return PVRSRV_ERROR_TIMEOUT;
+
+OpFlushedComplete:
+ DoModifyCompleteSyncOps(psModSyncOpInfo);
+ PVRSRVKernelSyncInfoDecRef(psModSyncOpInfo->psKernelSyncInfo, IMG_NULL);
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(MODIFY_SYNC_OP_INFO), (IMG_VOID *)psModSyncOpInfo, 0);
+
+
+
+ PVRSRVScheduleDeviceCallbacks();
+
+ return PVRSRV_OK;
+}
+
+
+static IMG_INT
+PVRSRVCreateSyncInfoModObjBW(IMG_UINT32 ui32BridgeID,
+ IMG_VOID *psBridgeIn,
+ PVRSRV_BRIDGE_OUT_CREATE_SYNC_INFO_MOD_OBJ *psCreateSyncInfoModObjOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ MODIFY_SYNC_OP_INFO *psModSyncOpInfo;
+
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CREATE_SYNC_INFO_MOD_OBJ);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psCreateSyncInfoModObjOUT->eError, psPerProc, 1)
+
+ ASSIGN_AND_EXIT_ON_ERROR(psCreateSyncInfoModObjOUT->eError,
+ OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(MODIFY_SYNC_OP_INFO),
+ (IMG_VOID **)&psModSyncOpInfo, 0,
+ "ModSyncOpInfo (MODIFY_SYNC_OP_INFO)"));
+
+ psModSyncOpInfo->psKernelSyncInfo = IMG_NULL;
+
+ psCreateSyncInfoModObjOUT->eError = PVRSRVAllocHandle(psPerProc->psHandleBase,
+ &psCreateSyncInfoModObjOUT->hKernelSyncInfoModObj,
+ psModSyncOpInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO_MOD_OBJ,
+ PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE);
+
+ if (psCreateSyncInfoModObjOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psModSyncOpInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_MODIFY_SYNC_OPS,
+ psModSyncOpInfo,
+ 0,
+ &ModifyCompleteSyncOpsCallBack);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psCreateSyncInfoModObjOUT->eError, psPerProc)
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVDestroySyncInfoModObjBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DESTROY_SYNC_INFO_MOD_OBJ *psDestroySyncInfoModObjIN,
+ PVRSRV_BRIDGE_RETURN *psDestroySyncInfoModObjOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ MODIFY_SYNC_OP_INFO *psModSyncOpInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DESTROY_SYNC_INFO_MOD_OBJ);
+
+ psDestroySyncInfoModObjOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID**)&psModSyncOpInfo,
+ psDestroySyncInfoModObjIN->hKernelSyncInfoModObj,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO_MOD_OBJ);
+ if (psDestroySyncInfoModObjOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVDestroySyncInfoModObjBW: PVRSRVLookupHandle failed"));
+ return 0;
+ }
+
+ if(psModSyncOpInfo->psKernelSyncInfo != IMG_NULL)
+ {
+
+ psDestroySyncInfoModObjOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+
+ PVRSRVKernelSyncInfoDecRef(psModSyncOpInfo->psKernelSyncInfo, IMG_NULL);
+
+ psDestroySyncInfoModObjOUT->eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psDestroySyncInfoModObjIN->hKernelSyncInfoModObj,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO_MOD_OBJ);
+
+ if (psDestroySyncInfoModObjOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVDestroySyncInfoModObjBW: PVRSRVReleaseHandle failed"));
+ return 0;
+ }
+
+ psDestroySyncInfoModObjOUT->eError = ResManFreeResByPtr(psModSyncOpInfo->hResItem, CLEANUP_WITH_POLL);
+ if (psDestroySyncInfoModObjOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVDestroySyncInfoModObjBW: ResManFreeResByPtr failed"));
+ return 0;
+ }
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVModifyPendingSyncOpsBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_MODIFY_PENDING_SYNC_OPS *psModifySyncOpsIN,
+ PVRSRV_BRIDGE_OUT_MODIFY_PENDING_SYNC_OPS *psModifySyncOpsOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+ MODIFY_SYNC_OP_INFO *psModSyncOpInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MODIFY_PENDING_SYNC_OPS);
+
+ psModifySyncOpsOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID**)&psModSyncOpInfo,
+ psModifySyncOpsIN->hKernelSyncInfoModObj,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO_MOD_OBJ);
+ if (psModifySyncOpsOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVModifyPendingSyncOpsBW: PVRSRVLookupHandle failed"));
+ return 0;
+ }
+
+ psModifySyncOpsOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID**)&psKernelSyncInfo,
+ psModifySyncOpsIN->hKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if (psModifySyncOpsOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVModifyPendingSyncOpsBW: PVRSRVLookupHandle failed"));
+ return 0;
+ }
+
+ if(psModSyncOpInfo->psKernelSyncInfo)
+ {
+
+ psModifySyncOpsOUT->eError = PVRSRV_ERROR_RETRY;
+ PVR_DPF((PVR_DBG_VERBOSE, "PVRSRVModifyPendingSyncOpsBW: SyncInfo Modification object is not empty"));
+ return 0;
+ }
+
+
+ if (psKernelSyncInfo == IMG_NULL)
+ {
+ psModifySyncOpsOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ PVR_DPF((PVR_DBG_VERBOSE, "PVRSRVModifyPendingSyncOpsBW: SyncInfo bad handle"));
+ return 0;
+ }
+
+ PVRSRVKernelSyncInfoIncRef(psKernelSyncInfo, IMG_NULL);
+
+ psModSyncOpInfo->psKernelSyncInfo = psKernelSyncInfo;
+ psModSyncOpInfo->ui32ModifyFlags = psModifySyncOpsIN->ui32ModifyFlags;
+ psModSyncOpInfo->ui32ReadOpsPendingSnapShot = psKernelSyncInfo->psSyncData->ui32ReadOpsPending;
+ psModSyncOpInfo->ui32WriteOpsPendingSnapShot = psKernelSyncInfo->psSyncData->ui32WriteOpsPending;
+ psModSyncOpInfo->ui32ReadOps2PendingSnapShot = psKernelSyncInfo->psSyncData->ui32ReadOps2Pending;
+
+
+
+ psModifySyncOpsOUT->ui32ReadOpsPending = psKernelSyncInfo->psSyncData->ui32ReadOpsPending;
+ psModifySyncOpsOUT->ui32WriteOpsPending = psKernelSyncInfo->psSyncData->ui32WriteOpsPending;
+ psModifySyncOpsOUT->ui32ReadOps2Pending = psKernelSyncInfo->psSyncData->ui32ReadOps2Pending;
+
+ if(psModifySyncOpsIN->ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_WO_INC)
+ {
+ psKernelSyncInfo->psSyncData->ui32WriteOpsPending++;
+ }
+
+ if(psModifySyncOpsIN->ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_RO_INC)
+ {
+ psKernelSyncInfo->psSyncData->ui32ReadOpsPending++;
+ }
+
+
+ psModifySyncOpsOUT->eError = ResManDissociateRes(psModSyncOpInfo->hResItem,
+ psPerProc->hResManContext);
+
+ if (psModifySyncOpsOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVModifyPendingSyncOpsBW: PVRSRVLookupHandle failed"));
+ return 0;
+ }
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVModifyCompleteSyncOpsBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_MODIFY_COMPLETE_SYNC_OPS *psModifySyncOpsIN,
+ PVRSRV_BRIDGE_RETURN *psModifySyncOpsOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ MODIFY_SYNC_OP_INFO *psModSyncOpInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MODIFY_COMPLETE_SYNC_OPS);
+
+ psModifySyncOpsOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID**)&psModSyncOpInfo,
+ psModifySyncOpsIN->hKernelSyncInfoModObj,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO_MOD_OBJ);
+ if (psModifySyncOpsOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVModifyCompleteSyncOpsBW: PVRSRVLookupHandle failed"));
+ return 0;
+ }
+
+ if(psModSyncOpInfo->psKernelSyncInfo == IMG_NULL)
+ {
+
+ psModifySyncOpsOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+
+ psModifySyncOpsOUT->eError = DoModifyCompleteSyncOps(psModSyncOpInfo);
+
+ if (psModifySyncOpsOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVModifyCompleteSyncOpsBW: DoModifyCompleteSyncOps failed"));
+ return 0;
+ }
+
+ PVRSRVKernelSyncInfoDecRef(psModSyncOpInfo->psKernelSyncInfo, IMG_NULL);
+ psModSyncOpInfo->psKernelSyncInfo = IMG_NULL;
+
+
+ PVRSRVScheduleDeviceCallbacks();
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVSyncOpsTakeTokenBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SYNC_OPS_TAKE_TOKEN *psSyncOpsTakeTokenIN,
+ PVRSRV_BRIDGE_OUT_SYNC_OPS_TAKE_TOKEN *psSyncOpsTakeTokenOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_OPS_TAKE_TOKEN);
+
+ psSyncOpsTakeTokenOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID**)&psKernelSyncInfo,
+ psSyncOpsTakeTokenIN->hKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if (psSyncOpsTakeTokenOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSyncOpsTakeTokenBW: PVRSRVLookupHandle failed"));
+ return 0;
+ }
+
+
+
+ psSyncOpsTakeTokenOUT->ui32ReadOpsPending = psKernelSyncInfo->psSyncData->ui32ReadOpsPending;
+ psSyncOpsTakeTokenOUT->ui32WriteOpsPending = psKernelSyncInfo->psSyncData->ui32WriteOpsPending;
+ psSyncOpsTakeTokenOUT->ui32ReadOps2Pending = psKernelSyncInfo->psSyncData->ui32ReadOps2Pending;
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVSyncOpsFlushToTokenBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SYNC_OPS_FLUSH_TO_TOKEN *psSyncOpsFlushToTokenIN,
+ PVRSRV_BRIDGE_RETURN *psSyncOpsFlushToTokenOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+ IMG_UINT32 ui32ReadOpsPendingSnapshot;
+ IMG_UINT32 ui32WriteOpsPendingSnapshot;
+ IMG_UINT32 ui32ReadOps2PendingSnapshot;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_OPS_FLUSH_TO_TOKEN);
+
+ psSyncOpsFlushToTokenOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID**)&psKernelSyncInfo,
+ psSyncOpsFlushToTokenIN->hKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if (psSyncOpsFlushToTokenOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSyncOpsFlushToTokenBW: PVRSRVLookupHandle failed"));
+ return 0;
+ }
+
+ ui32ReadOpsPendingSnapshot = psSyncOpsFlushToTokenIN->ui32ReadOpsPendingSnapshot;
+ ui32WriteOpsPendingSnapshot = psSyncOpsFlushToTokenIN->ui32WriteOpsPendingSnapshot;
+ ui32ReadOps2PendingSnapshot = psSyncOpsFlushToTokenIN->ui32ReadOps2PendingSnapshot;
+
+ psSyncOpsFlushToTokenOUT->eError = DoQuerySyncOpsSatisfied(psKernelSyncInfo,
+ ui32ReadOpsPendingSnapshot,
+ ui32WriteOpsPendingSnapshot,
+ ui32ReadOps2PendingSnapshot);
+
+ if (psSyncOpsFlushToTokenOUT->eError != PVRSRV_OK && psSyncOpsFlushToTokenOUT->eError != PVRSRV_ERROR_RETRY)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSyncOpsFlushToTokenBW: DoQuerySyncOpsSatisfied failed"));
+ return 0;
+ }
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVSyncOpsFlushToModObjBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SYNC_OPS_FLUSH_TO_MOD_OBJ *psSyncOpsFlushToModObjIN,
+ PVRSRV_BRIDGE_RETURN *psSyncOpsFlushToModObjOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ MODIFY_SYNC_OP_INFO *psModSyncOpInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_OPS_FLUSH_TO_MOD_OBJ);
+
+ psSyncOpsFlushToModObjOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID**)&psModSyncOpInfo,
+ psSyncOpsFlushToModObjIN->hKernelSyncInfoModObj,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO_MOD_OBJ);
+ if (psSyncOpsFlushToModObjOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSyncOpsFlushToModObjBW: PVRSRVLookupHandle failed"));
+ return 0;
+ }
+
+ if(psModSyncOpInfo->psKernelSyncInfo == IMG_NULL)
+ {
+
+ psSyncOpsFlushToModObjOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+
+ psSyncOpsFlushToModObjOUT->eError = DoQuerySyncOpsSatisfied(psModSyncOpInfo->psKernelSyncInfo,
+ psModSyncOpInfo->ui32ReadOpsPendingSnapShot,
+ psModSyncOpInfo->ui32WriteOpsPendingSnapShot,
+ psModSyncOpInfo->ui32ReadOps2PendingSnapShot);
+
+ if (psSyncOpsFlushToModObjOUT->eError != PVRSRV_OK && psSyncOpsFlushToModObjOUT->eError != PVRSRV_ERROR_RETRY)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSyncOpsFlushToModObjBW: DoQuerySyncOpsSatisfied failed"));
+ return 0;
+ }
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVSyncOpsFlushToDeltaBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SYNC_OPS_FLUSH_TO_DELTA *psSyncOpsFlushToDeltaIN,
+ PVRSRV_BRIDGE_RETURN *psSyncOpsFlushToDeltaOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+ IMG_UINT32 ui32DeltaRead;
+ IMG_UINT32 ui32DeltaWrite;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_OPS_FLUSH_TO_DELTA);
+
+ psSyncOpsFlushToDeltaOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID**)&psSyncInfo,
+ psSyncOpsFlushToDeltaIN->hKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if (psSyncOpsFlushToDeltaOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSyncOpsFlushToDeltaBW: PVRSRVLookupHandle failed"));
+ return 0;
+ }
+
+
+ ui32DeltaRead = psSyncInfo->psSyncData->ui32ReadOpsPending - psSyncInfo->psSyncData->ui32ReadOpsComplete;
+ ui32DeltaWrite = psSyncInfo->psSyncData->ui32WriteOpsPending - psSyncInfo->psSyncData->ui32WriteOpsComplete;
+
+ if (ui32DeltaRead <= psSyncOpsFlushToDeltaIN->ui32Delta && ui32DeltaWrite <= psSyncOpsFlushToDeltaIN->ui32Delta)
+ {
+#if defined(PDUMP) && !defined(SUPPORT_VGX)
+
+ PDumpComment("Poll for read ops complete to delta (%u)",
+ psSyncOpsFlushToDeltaIN->ui32Delta);
+ psSyncOpsFlushToDeltaOUT->eError =
+ PDumpMemPolKM(psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete),
+ psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ 0xFFFFFFFF,
+ PDUMP_POLL_OPERATOR_GREATEREQUAL,
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+
+
+ PDumpComment("Poll for write ops complete to delta (%u)",
+ psSyncOpsFlushToDeltaIN->ui32Delta);
+ psSyncOpsFlushToDeltaOUT->eError =
+ PDumpMemPolKM(psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete),
+ psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ 0xFFFFFFFF,
+ PDUMP_POLL_OPERATOR_GREATEREQUAL,
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+#endif
+
+ psSyncOpsFlushToDeltaOUT->eError = PVRSRV_OK;
+ }
+ else
+ {
+ psSyncOpsFlushToDeltaOUT->eError = PVRSRV_ERROR_RETRY;
+ }
+
+ return 0;
+}
+
+
+static PVRSRV_ERROR
+FreeSyncInfoCallback(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param,
+ IMG_BOOL bDummy)
+{
+ PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+ PVR_UNREFERENCED_PARAMETER(bDummy);
+
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)pvParam;
+
+ PVRSRVKernelSyncInfoDecRef(psSyncInfo, IMG_NULL);
+
+ return PVRSRV_OK;
+}
+
+
+static IMG_INT
+PVRSRVAllocSyncInfoBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_ALLOC_SYNC_INFO *psAllocSyncInfoIN,
+ PVRSRV_BRIDGE_OUT_ALLOC_SYNC_INFO *psAllocSyncInfoOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+ PVRSRV_ERROR eError;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_HANDLE hDevMemContext;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ALLOC_SYNC_INFO);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psAllocSyncInfoOUT->eError, psPerProc, 1)
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_HANDLE *)&psDeviceNode,
+ psAllocSyncInfoIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(eError != PVRSRV_OK)
+ {
+ goto allocsyncinfo_errorexit;
+ }
+
+ hDevMemContext = psDeviceNode->sDevMemoryInfo.pBMKernelContext;
+
+ eError = PVRSRVAllocSyncInfoKM(psDeviceNode,
+ hDevMemContext,
+ &psSyncInfo);
+
+ if (eError != PVRSRV_OK)
+ {
+ goto allocsyncinfo_errorexit;
+ }
+
+ eError = PVRSRVAllocHandle(psPerProc->psHandleBase,
+ &psAllocSyncInfoOUT->hKernelSyncInfo,
+ psSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE);
+
+ if(eError != PVRSRV_OK)
+ {
+ goto allocsyncinfo_errorexit_freesyncinfo;
+ }
+
+ psSyncInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_SYNC_INFO,
+ psSyncInfo,
+ 0,
+ FreeSyncInfoCallback);
+
+
+ goto allocsyncinfo_commit;
+
+
+ allocsyncinfo_errorexit_freesyncinfo:
+ PVRSRVKernelSyncInfoDecRef(psSyncInfo, IMG_NULL);
+
+ allocsyncinfo_errorexit:
+
+
+ allocsyncinfo_commit:
+ psAllocSyncInfoOUT->eError = eError;
+ COMMIT_HANDLE_BATCH_OR_ERROR(eError, psPerProc);
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVFreeSyncInfoBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_FREE_SYNC_INFO *psFreeSyncInfoIN,
+ PVRSRV_BRIDGE_RETURN *psFreeSyncInfoOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+ PVRSRV_ERROR eError;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_FREE_SYNC_INFO);
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID**)&psSyncInfo,
+ psFreeSyncInfoIN->hKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVFreeSyncInfoBW: PVRSRVLookupHandle failed"));
+ psFreeSyncInfoOUT->eError = eError;
+ return 0;
+ }
+
+ eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psFreeSyncInfoIN->hKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVFreeSyncInfoBW: PVRSRVReleaseHandle failed"));
+ psFreeSyncInfoOUT->eError = eError;
+ return 0;
+ }
+
+ eError = ResManFreeResByPtr(psSyncInfo->hResItem, CLEANUP_WITH_POLL);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVFreeSyncInfoBW: ResManFreeResByPtr failed"));
+ psFreeSyncInfoOUT->eError = eError;
+ return 0;
+ }
+
+ return 0;
+}
+
+
+PVRSRV_ERROR
+CommonBridgeInit(IMG_VOID)
+{
+ IMG_UINT32 i;
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_ENUM_DEVICES, PVRSRVEnumerateDevicesBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_ACQUIRE_DEVICEINFO, PVRSRVAcquireDeviceDataBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RELEASE_DEVICEINFO, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_CREATE_DEVMEMCONTEXT, PVRSRVCreateDeviceMemContextBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DESTROY_DEVMEMCONTEXT, PVRSRVDestroyDeviceMemContextBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DEVMEM_HEAPINFO, PVRSRVGetDeviceMemHeapInfoBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_ALLOC_DEVICEMEM, PVRSRVAllocDeviceMemBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_FREE_DEVICEMEM, PVRSRVFreeDeviceMemBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GETFREE_DEVICEMEM, PVRSRVGetFreeDeviceMemBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_CREATE_COMMANDQUEUE, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DESTROY_COMMANDQUEUE, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MHANDLE_TO_MMAP_DATA, PVRMMapOSMemHandleToMMapDataBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_CONNECT_SERVICES, PVRSRVConnectBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DISCONNECT_SERVICES, PVRSRVDisconnectBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_WRAP_DEVICE_MEM, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DEVICEMEMINFO, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RESERVE_DEV_VIRTMEM , DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_FREE_DEV_VIRTMEM, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_EXT_MEMORY, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAP_EXT_MEMORY, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_DEV_MEMORY, PVRSRVMapDeviceMemoryBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAP_DEV_MEMORY, PVRSRVUnmapDeviceMemoryBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY, PVRSRVMapDeviceClassMemoryBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAP_DEVICECLASS_MEMORY, PVRSRVUnmapDeviceClassMemoryBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_MEM_INFO_TO_USER, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAP_MEM_INFO_FROM_USER, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_EXPORT_DEVICEMEM, PVRSRVExportDeviceMemBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RELEASE_MMAP_DATA, PVRMMapReleaseMMapDataBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_CHG_DEV_MEM_ATTRIBS, PVRSRVChangeDeviceMemoryAttributesBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_DEV_MEMORY_2, PVRSRVMapDeviceMemoryBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_EXPORT_DEVICEMEM_2, PVRSRVExportDeviceMemBW);
+
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PROCESS_SIMISR_EVENT, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_REGISTER_SIM_PROCESS, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_UNREGISTER_SIM_PROCESS, DummyBW);
+
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MAPPHYSTOUSERSPACE, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAPPHYSTOUSERSPACE, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GETPHYSTOUSERSPACEMAP, DummyBW);
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GET_FB_STATS, DummyBW);
+
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GET_MISC_INFO, PVRSRVGetMiscInfoBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RELEASE_MISC_INFO, DummyBW);
+
+
+#if defined (SUPPORT_OVERLAY_ROTATE_BLIT)
+ SetDispatchTableEntry(PVRSRV_BRIDGE_INIT_3D_OVL_BLT_RES, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DEINIT_3D_OVL_BLT_RES, DummyBW);
+#endif
+
+
+
+#if defined(PDUMP)
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_INIT, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_MEMPOL, PDumpMemPolBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_DUMPMEM, PDumpMemBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_REG, PDumpRegWithFlagsBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_REGPOL, PDumpRegPolBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_COMMENT, PDumpCommentBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_SETFRAME, PDumpSetFrameBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_ISCAPTURING, PDumpIsCaptureFrameBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_DUMPBITMAP, PDumpBitmapBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_DUMPREADREG, PDumpReadRegBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_SYNCPOL, PDumpSyncPolBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_DUMPSYNC, PDumpSyncDumpBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_MEMPAGES, PDumpMemPagesBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_DRIVERINFO, PDumpDriverInfoBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_DUMPPDDEVPADDR, PDumpPDDevPAddrBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_CYCLE_COUNT_REG_READ, PDumpCycleCountRegReadBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_STARTINITPHASE, PDumpStartInitPhaseBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_STOPINITPHASE, PDumpStopInitPhaseBW);
+#endif
+
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GET_OEMJTABLE, DummyBW);
+
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_ENUM_CLASS, PVRSRVEnumerateDCBW);
+
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_OPEN_DISPCLASS_DEVICE, PVRSRVOpenDCDeviceBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_CLOSE_DISPCLASS_DEVICE, PVRSRVCloseDCDeviceBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_ENUM_DISPCLASS_FORMATS, PVRSRVEnumDCFormatsBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_ENUM_DISPCLASS_DIMS, PVRSRVEnumDCDimsBW);
+#if defined(SUPPORT_PVRSRV_GET_DC_SYSTEM_BUFFER)
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DISPCLASS_SYSBUFFER, PVRSRVGetDCSystemBufferBW);
+#else
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DISPCLASS_SYSBUFFER, DummyBW);
+#endif
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DISPCLASS_INFO, PVRSRVGetDCInfoBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_CREATE_DISPCLASS_SWAPCHAIN, PVRSRVCreateDCSwapChainBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DESTROY_DISPCLASS_SWAPCHAIN, PVRSRVDestroyDCSwapChainBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SET_DISPCLASS_DSTRECT, PVRSRVSetDCDstRectBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SET_DISPCLASS_SRCRECT, PVRSRVSetDCSrcRectBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SET_DISPCLASS_DSTCOLOURKEY, PVRSRVSetDCDstColourKeyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SET_DISPCLASS_SRCCOLOURKEY, PVRSRVSetDCSrcColourKeyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DISPCLASS_BUFFERS, PVRSRVGetDCBuffersBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_BUFFER, PVRSRVSwapToDCBufferBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_BUFFER2, PVRSRVSwapToDCBuffer2BW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_SYSTEM, PVRSRVSwapToDCSystemBW);
+
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_OPEN_BUFFERCLASS_DEVICE, PVRSRVOpenBCDeviceBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_CLOSE_BUFFERCLASS_DEVICE, PVRSRVCloseBCDeviceBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GET_BUFFERCLASS_INFO, PVRSRVGetBCInfoBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GET_BUFFERCLASS_BUFFER, PVRSRVGetBCBufferBW);
+
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_WRAP_EXT_MEMORY, PVRSRVWrapExtMemoryBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_UNWRAP_EXT_MEMORY, PVRSRVUnwrapExtMemoryBW);
+
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_ALLOC_SHARED_SYS_MEM, PVRSRVAllocSharedSysMemoryBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_FREE_SHARED_SYS_MEM, PVRSRVFreeSharedSysMemoryBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_MEMINFO_MEM, PVRSRVMapMemInfoMemBW);
+
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_INITSRV_CONNECT, &PVRSRVInitSrvConnectBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_INITSRV_DISCONNECT, &PVRSRVInitSrvDisconnectBW);
+
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_EVENT_OBJECT_WAIT, &PVRSRVEventObjectWaitBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_EVENT_OBJECT_OPEN, &PVRSRVEventObjectOpenBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_EVENT_OBJECT_CLOSE, &PVRSRVEventObjectCloseBW);
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_CREATE_SYNC_INFO_MOD_OBJ, PVRSRVCreateSyncInfoModObjBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DESTROY_SYNC_INFO_MOD_OBJ, PVRSRVDestroySyncInfoModObjBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MODIFY_PENDING_SYNC_OPS, PVRSRVModifyPendingSyncOpsBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MODIFY_COMPLETE_SYNC_OPS, PVRSRVModifyCompleteSyncOpsBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SYNC_OPS_TAKE_TOKEN, PVRSRVSyncOpsTakeTokenBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SYNC_OPS_FLUSH_TO_TOKEN, PVRSRVSyncOpsFlushToTokenBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SYNC_OPS_FLUSH_TO_MOD_OBJ, PVRSRVSyncOpsFlushToModObjBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SYNC_OPS_FLUSH_TO_DELTA, PVRSRVSyncOpsFlushToDeltaBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_ALLOC_SYNC_INFO, PVRSRVAllocSyncInfoBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_FREE_SYNC_INFO, PVRSRVFreeSyncInfoBW);
+
+#if defined (SUPPORT_SGX)
+ SetSGXDispatchTableEntry();
+#endif
+#if defined (SUPPORT_VGX)
+ SetVGXDispatchTableEntry();
+#endif
+#if defined (SUPPORT_MSVDX)
+ SetMSVDXDispatchTableEntry();
+#endif
+
+
+
+ for(i=0;i<BRIDGE_DISPATCH_TABLE_ENTRY_COUNT;i++)
+ {
+ if(!g_BridgeDispatchTable[i].pfFunction)
+ {
+ g_BridgeDispatchTable[i].pfFunction = &DummyBW;
+#if defined(DEBUG_BRIDGE_KM)
+ g_BridgeDispatchTable[i].pszIOCName = "_PVRSRV_BRIDGE_DUMMY";
+ g_BridgeDispatchTable[i].pszFunctionName = "DummyBW";
+ g_BridgeDispatchTable[i].ui32CallCount = 0;
+ g_BridgeDispatchTable[i].ui32CopyFromUserTotalBytes = 0;
+ g_BridgeDispatchTable[i].ui32CopyToUserTotalBytes = 0;
+#endif
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+IMG_INT BridgedDispatchKM(PVRSRV_PER_PROCESS_DATA * psPerProc,
+ PVRSRV_BRIDGE_PACKAGE * psBridgePackageKM)
+{
+ IMG_VOID * psBridgeIn;
+ IMG_VOID * psBridgeOut;
+ BridgeWrapperFunction pfBridgeHandler;
+ IMG_UINT32 ui32BridgeID = psBridgePackageKM->ui32BridgeID;
+ IMG_INT err = -EFAULT;
+
+#if defined(DEBUG_TRACE_BRIDGE_KM)
+ PVR_DPF((PVR_DBG_ERROR, "%s: %s",
+ __FUNCTION__,
+ g_BridgeDispatchTable[ui32BridgeID].pszIOCName));
+#endif
+
+#if defined(DEBUG_BRIDGE_KM)
+ g_BridgeDispatchTable[ui32BridgeID].ui32CallCount++;
+ g_BridgeGlobalStats.ui32IOCTLCount++;
+#endif
+
+ if(!psPerProc->bInitProcess)
+ {
+ if(PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RAN))
+ {
+ if(!PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Initialisation failed. Driver unusable.",
+ __FUNCTION__));
+ goto return_fault;
+ }
+ }
+ else
+ {
+ if(PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RUNNING))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Initialisation is in progress",
+ __FUNCTION__));
+ goto return_fault;
+ }
+ else
+ {
+
+ switch(ui32BridgeID)
+ {
+ case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_CONNECT_SERVICES):
+ case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_DISCONNECT_SERVICES):
+ case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_INITSRV_CONNECT):
+ case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_INITSRV_DISCONNECT):
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "%s: Driver initialisation not completed yet.",
+ __FUNCTION__));
+ goto return_fault;
+ }
+ }
+ }
+ }
+
+#if defined(__linux__)
+ {
+
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+
+ psBridgeIn = ((ENV_DATA *)psSysData->pvEnvSpecificData)->pvBridgeData;
+ psBridgeOut = (IMG_PVOID)((IMG_PBYTE)psBridgeIn + PVRSRV_MAX_BRIDGE_IN_SIZE);
+
+
+ if((psBridgePackageKM->ui32InBufferSize > PVRSRV_MAX_BRIDGE_IN_SIZE) ||
+ (psBridgePackageKM->ui32OutBufferSize > PVRSRV_MAX_BRIDGE_OUT_SIZE))
+ {
+ goto return_fault;
+ }
+
+
+ if(psBridgePackageKM->ui32InBufferSize > 0)
+ {
+ if(!OSAccessOK(PVR_VERIFY_READ,
+ psBridgePackageKM->pvParamIn,
+ psBridgePackageKM->ui32InBufferSize))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Invalid pvParamIn pointer", __FUNCTION__));
+ }
+
+ if(CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ psBridgeIn,
+ psBridgePackageKM->pvParamIn,
+ psBridgePackageKM->ui32InBufferSize)
+ != PVRSRV_OK)
+ {
+ goto return_fault;
+ }
+ }
+ }
+#else
+ psBridgeIn = psBridgePackageKM->pvParamIn;
+ psBridgeOut = psBridgePackageKM->pvParamOut;
+#endif
+
+ if(ui32BridgeID >= (BRIDGE_DISPATCH_TABLE_ENTRY_COUNT))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: ui32BridgeID = %d is out if range!",
+ __FUNCTION__, ui32BridgeID));
+ goto return_fault;
+ }
+ pfBridgeHandler =
+ (BridgeWrapperFunction)g_BridgeDispatchTable[ui32BridgeID].pfFunction;
+ err = pfBridgeHandler(ui32BridgeID,
+ psBridgeIn,
+ psBridgeOut,
+ psPerProc);
+ if(err < 0)
+ {
+ goto return_fault;
+ }
+
+#if defined(__linux__)
+
+ if(CopyToUserWrapper(psPerProc,
+ ui32BridgeID,
+ psBridgePackageKM->pvParamOut,
+ psBridgeOut,
+ psBridgePackageKM->ui32OutBufferSize)
+ != PVRSRV_OK)
+ {
+ goto return_fault;
+ }
+#endif
+
+ err = 0;
+return_fault:
+
+ ReleaseHandleBatch(psPerProc);
+ return err;
+}
+
diff --git a/drivers/gpu/pvr/bridged_pvr_bridge.h b/drivers/gpu/pvr/bridged_pvr_bridge.h
new file mode 100644
index 0000000..6b0dd88
--- /dev/null
+++ b/drivers/gpu/pvr/bridged_pvr_bridge.h
@@ -0,0 +1,232 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __BRIDGED_PVR_BRIDGE_H__
+#define __BRIDGED_PVR_BRIDGE_H__
+
+#include "pvr_bridge.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#if defined(__linux__)
+#define PVRSRV_GET_BRIDGE_ID(X) _IOC_NR(X)
+#else
+#define PVRSRV_GET_BRIDGE_ID(X) ((X) - PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST))
+#endif
+
+#ifndef ENOMEM
+#define ENOMEM 12
+#endif
+#ifndef EFAULT
+#define EFAULT 14
+#endif
+#ifndef ENOTTY
+#define ENOTTY 25
+#endif
+
+#if defined(DEBUG_BRIDGE_KM)
+PVRSRV_ERROR
+CopyFromUserWrapper(PVRSRV_PER_PROCESS_DATA *pProcData,
+ IMG_UINT32 ui32BridgeID,
+ IMG_VOID *pvDest,
+ IMG_VOID *pvSrc,
+ IMG_UINT32 ui32Size);
+PVRSRV_ERROR
+CopyToUserWrapper(PVRSRV_PER_PROCESS_DATA *pProcData,
+ IMG_UINT32 ui32BridgeID,
+ IMG_VOID *pvDest,
+ IMG_VOID *pvSrc,
+ IMG_UINT32 ui32Size);
+#else
+#define CopyFromUserWrapper(pProcData, ui32BridgeID, pvDest, pvSrc, ui32Size) \
+ OSCopyFromUser(pProcData, pvDest, pvSrc, ui32Size)
+#define CopyToUserWrapper(pProcData, ui32BridgeID, pvDest, pvSrc, ui32Size) \
+ OSCopyToUser(pProcData, pvDest, pvSrc, ui32Size)
+#endif
+
+
+#define ASSIGN_AND_RETURN_ON_ERROR(error, src, res) \
+ do \
+ { \
+ (error) = (src); \
+ if ((error) != PVRSRV_OK) \
+ { \
+ return (res); \
+ } \
+ } while ((error) != PVRSRV_OK);
+
+#define ASSIGN_AND_EXIT_ON_ERROR(error, src) \
+ ASSIGN_AND_RETURN_ON_ERROR(error, src, 0)
+
+#if defined (PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE)
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(NewHandleBatch)
+#endif
+static INLINE PVRSRV_ERROR
+NewHandleBatch(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_UINT32 ui32BatchSize)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(!psPerProc->bHandlesBatched);
+
+ eError = PVRSRVNewHandleBatch(psPerProc->psHandleBase, ui32BatchSize);
+
+ if (eError == PVRSRV_OK)
+ {
+ psPerProc->bHandlesBatched = IMG_TRUE;
+ }
+
+ return eError;
+}
+
+#define NEW_HANDLE_BATCH_OR_ERROR(error, psPerProc, ui32BatchSize) \
+ ASSIGN_AND_EXIT_ON_ERROR(error, NewHandleBatch(psPerProc, ui32BatchSize))
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(CommitHandleBatch)
+#endif
+static INLINE PVRSRV_ERROR
+CommitHandleBatch(PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVR_ASSERT(psPerProc->bHandlesBatched);
+
+ psPerProc->bHandlesBatched = IMG_FALSE;
+
+ return PVRSRVCommitHandleBatch(psPerProc->psHandleBase);
+}
+
+
+#define COMMIT_HANDLE_BATCH_OR_ERROR(error, psPerProc) \
+ ASSIGN_AND_EXIT_ON_ERROR(error, CommitHandleBatch(psPerProc))
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(ReleaseHandleBatch)
+#endif
+static INLINE IMG_VOID
+ReleaseHandleBatch(PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ if (psPerProc->bHandlesBatched)
+ {
+ psPerProc->bHandlesBatched = IMG_FALSE;
+
+ PVRSRVReleaseHandleBatch(psPerProc->psHandleBase);
+ }
+}
+#else
+#define NEW_HANDLE_BATCH_OR_ERROR(error, psPerProc, ui32BatchSize)
+#define COMMIT_HANDLE_BATCH_OR_ERROR(error, psPerProc)
+#define ReleaseHandleBatch(psPerProc)
+#endif
+
+IMG_INT
+DummyBW(IMG_UINT32 ui32BridgeID,
+ IMG_VOID *psBridgeIn,
+ IMG_VOID *psBridgeOut,
+ PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+typedef IMG_INT (*BridgeWrapperFunction)(IMG_UINT32 ui32BridgeID,
+ IMG_VOID *psBridgeIn,
+ IMG_VOID *psBridgeOut,
+ PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+typedef struct _PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY
+{
+ BridgeWrapperFunction pfFunction;
+#if defined(DEBUG_BRIDGE_KM)
+ const IMG_CHAR *pszIOCName;
+ const IMG_CHAR *pszFunctionName;
+ IMG_UINT32 ui32CallCount;
+ IMG_UINT32 ui32CopyFromUserTotalBytes;
+ IMG_UINT32 ui32CopyToUserTotalBytes;
+#endif
+}PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY;
+
+#if defined(SUPPORT_VGX) || defined(SUPPORT_MSVDX)
+ #if defined(SUPPORT_VGX)
+ #define BRIDGE_DISPATCH_TABLE_ENTRY_COUNT (PVRSRV_BRIDGE_LAST_VGX_CMD+1)
+ #define PVRSRV_BRIDGE_LAST_DEVICE_CMD PVRSRV_BRIDGE_LAST_VGX_CMD
+ #else
+ #define BRIDGE_DISPATCH_TABLE_ENTRY_COUNT (PVRSRV_BRIDGE_LAST_MSVDX_CMD+1)
+ #define PVRSRV_BRIDGE_LAST_DEVICE_CMD PVRSRV_BRIDGE_LAST_MSVDX_CMD
+ #endif
+#else
+ #if defined(SUPPORT_SGX)
+ #define BRIDGE_DISPATCH_TABLE_ENTRY_COUNT (PVRSRV_BRIDGE_LAST_SGX_CMD+1)
+ #define PVRSRV_BRIDGE_LAST_DEVICE_CMD PVRSRV_BRIDGE_LAST_SGX_CMD
+ #else
+ #define BRIDGE_DISPATCH_TABLE_ENTRY_COUNT (PVRSRV_BRIDGE_LAST_NON_DEVICE_CMD+1)
+ #define PVRSRV_BRIDGE_LAST_DEVICE_CMD PVRSRV_BRIDGE_LAST_NON_DEVICE_CMD
+ #endif
+#endif
+
+extern PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY g_BridgeDispatchTable[BRIDGE_DISPATCH_TABLE_ENTRY_COUNT];
+
+IMG_VOID
+_SetDispatchTableEntry(IMG_UINT32 ui32Index,
+ const IMG_CHAR *pszIOCName,
+ BridgeWrapperFunction pfFunction,
+ const IMG_CHAR *pszFunctionName);
+
+
+
+#define SetDispatchTableEntry(ui32Index, pfFunction) \
+ _SetDispatchTableEntry(PVRSRV_GET_BRIDGE_ID(ui32Index), #ui32Index, (BridgeWrapperFunction)pfFunction, #pfFunction)
+
+#define DISPATCH_TABLE_GAP_THRESHOLD 5
+
+#if defined(DEBUG)
+#define PVRSRV_BRIDGE_ASSERT_CMD(X, Y) PVR_ASSERT(X == PVRSRV_GET_BRIDGE_ID(Y))
+#else
+#define PVRSRV_BRIDGE_ASSERT_CMD(X, Y) PVR_UNREFERENCED_PARAMETER(X)
+#endif
+
+
+#if defined(DEBUG_BRIDGE_KM)
+typedef struct _PVRSRV_BRIDGE_GLOBAL_STATS
+{
+ IMG_UINT32 ui32IOCTLCount;
+ IMG_UINT32 ui32TotalCopyFromUserBytes;
+ IMG_UINT32 ui32TotalCopyToUserBytes;
+}PVRSRV_BRIDGE_GLOBAL_STATS;
+
+extern PVRSRV_BRIDGE_GLOBAL_STATS g_BridgeGlobalStats;
+#endif
+
+
+PVRSRV_ERROR CommonBridgeInit(IMG_VOID);
+
+IMG_INT BridgedDispatchKM(PVRSRV_PER_PROCESS_DATA * psPerProc,
+ PVRSRV_BRIDGE_PACKAGE * psBridgePackageKM);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/pvr/bridged_support.c b/drivers/gpu/pvr/bridged_support.c
new file mode 100644
index 0000000..dad0800
--- /dev/null
+++ b/drivers/gpu/pvr/bridged_support.c
@@ -0,0 +1,89 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "img_defs.h"
+#include "servicesint.h"
+#include "bridged_support.h"
+
+
+PVRSRV_ERROR
+#if defined (SUPPORT_SID_INTERFACE)
+PVRSRVLookupOSMemHandle(PVRSRV_HANDLE_BASE *psHandleBase, IMG_HANDLE *phOSMemHandle, IMG_SID hMHandle)
+#else
+PVRSRVLookupOSMemHandle(PVRSRV_HANDLE_BASE *psHandleBase, IMG_HANDLE *phOSMemHandle, IMG_HANDLE hMHandle)
+#endif
+{
+ IMG_HANDLE hMHandleInt;
+ PVRSRV_HANDLE_TYPE eHandleType;
+ PVRSRV_ERROR eError;
+
+
+ eError = PVRSRVLookupHandleAnyType(psHandleBase, &hMHandleInt,
+ &eHandleType,
+ hMHandle);
+ if(eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ switch(eHandleType)
+ {
+#if defined(PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE)
+ case PVRSRV_HANDLE_TYPE_MEM_INFO:
+ case PVRSRV_HANDLE_TYPE_MEM_INFO_REF:
+ case PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO:
+ {
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo = (PVRSRV_KERNEL_MEM_INFO *)hMHandleInt;
+
+ *phOSMemHandle = psMemInfo->sMemBlk.hOSMemHandle;
+
+ break;
+ }
+ case PVRSRV_HANDLE_TYPE_SYNC_INFO:
+ {
+ PVRSRV_KERNEL_SYNC_INFO *psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)hMHandleInt;
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo = psSyncInfo->psSyncDataMemInfoKM;
+
+ *phOSMemHandle = psMemInfo->sMemBlk.hOSMemHandle;
+
+ break;
+ }
+ case PVRSRV_HANDLE_TYPE_SOC_TIMER:
+ {
+ *phOSMemHandle = (IMG_VOID *)hMHandleInt;
+ break;
+ }
+#else
+ case PVRSRV_HANDLE_TYPE_NONE:
+ *phOSMemHandle = (IMG_VOID *)hMHandleInt;
+ break;
+#endif
+ default:
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+
+ return PVRSRV_OK;
+}
diff --git a/drivers/gpu/pvr/bridged_support.h b/drivers/gpu/pvr/bridged_support.h
new file mode 100644
index 0000000..d027290
--- /dev/null
+++ b/drivers/gpu/pvr/bridged_support.h
@@ -0,0 +1,47 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __BRIDGED_SUPPORT_H__
+#define __BRIDGED_SUPPORT_H__
+
+#include "handle.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#if defined (SUPPORT_SID_INTERFACE)
+PVRSRV_ERROR PVRSRVLookupOSMemHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phOSMemHandle, IMG_SID hMHandle);
+#else
+PVRSRV_ERROR PVRSRVLookupOSMemHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phOSMemHandle, IMG_HANDLE hMHandle);
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/pvr/buffer_manager.c b/drivers/gpu/pvr/buffer_manager.c
new file mode 100644
index 0000000..ee65df0
--- /dev/null
+++ b/drivers/gpu/pvr/buffer_manager.c
@@ -0,0 +1,2549 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "services_headers.h"
+
+#include "sysconfig.h"
+#include "hash.h"
+#include "ra.h"
+#include "pdump_km.h"
+#include "lists.h"
+
+static IMG_BOOL
+ZeroBuf(BM_BUF *pBuf, BM_MAPPING *pMapping, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags);
+static IMG_VOID
+BM_FreeMemory (IMG_VOID *pH, IMG_UINTPTR_T base, BM_MAPPING *psMapping);
+static IMG_BOOL
+BM_ImportMemory(IMG_VOID *pH, IMG_SIZE_T uSize,
+ IMG_SIZE_T *pActualSize, BM_MAPPING **ppsMapping,
+ IMG_UINT32 uFlags, IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength, IMG_UINTPTR_T *pBase);
+
+static IMG_BOOL
+DevMemoryAlloc (BM_CONTEXT *pBMContext,
+ BM_MAPPING *pMapping,
+ IMG_SIZE_T *pActualSize,
+ IMG_UINT32 uFlags,
+ IMG_UINT32 dev_vaddr_alignment,
+ IMG_DEV_VIRTADDR *pDevVAddr);
+static IMG_VOID
+DevMemoryFree (BM_MAPPING *pMapping);
+
+static IMG_BOOL
+AllocMemory (BM_CONTEXT *pBMContext,
+ BM_HEAP *psBMHeap,
+ IMG_DEV_VIRTADDR *psDevVAddr,
+ IMG_SIZE_T uSize,
+ IMG_UINT32 uFlags,
+ IMG_UINT32 uDevVAddrAlignment,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
+ BM_BUF *pBuf)
+{
+ BM_MAPPING *pMapping;
+ IMG_UINTPTR_T uOffset;
+ RA_ARENA *pArena = IMG_NULL;
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "AllocMemory (uSize=0x%x, uFlags=0x%x, align=0x%x)",
+ uSize, uFlags, uDevVAddrAlignment));
+
+
+
+
+ if(uFlags & PVRSRV_MEM_RAM_BACKED_ALLOCATION)
+ {
+ if(uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR)
+ {
+
+ PVR_DPF ((PVR_DBG_ERROR, "AllocMemory: combination of DevVAddr management and RAM backing mode unsupported"));
+ return IMG_FALSE;
+ }
+
+
+
+
+ if(psBMHeap->ui32Attribs
+ & (PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG
+ |PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG))
+ {
+
+ pArena = psBMHeap->pImportArena;
+ PVR_ASSERT(psBMHeap->sDevArena.psDeviceMemoryHeapInfo->ui32Attribs & PVRSRV_MEM_RAM_BACKED_ALLOCATION);
+ }
+ else
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "AllocMemory: backing store type doesn't match heap"));
+ return IMG_FALSE;
+ }
+
+
+ if (!RA_Alloc(pArena,
+ uSize,
+ IMG_NULL,
+ (IMG_VOID*) &pMapping,
+ uFlags,
+ uDevVAddrAlignment,
+ 0,
+ pvPrivData,
+ ui32PrivDataLength,
+ (IMG_UINTPTR_T *)&(pBuf->DevVAddr.uiAddr)))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "AllocMemory: RA_Alloc(0x%x) FAILED", uSize));
+ return IMG_FALSE;
+ }
+
+ uOffset = pBuf->DevVAddr.uiAddr - pMapping->DevVAddr.uiAddr;
+ if(pMapping->CpuVAddr)
+ {
+ pBuf->CpuVAddr = (IMG_VOID*) ((IMG_UINTPTR_T)pMapping->CpuVAddr + uOffset);
+ }
+ else
+ {
+ pBuf->CpuVAddr = IMG_NULL;
+ }
+
+ if(uSize == pMapping->uSize)
+ {
+ pBuf->hOSMemHandle = pMapping->hOSMemHandle;
+ }
+ else
+ {
+ if(OSGetSubMemHandle(pMapping->hOSMemHandle,
+ uOffset,
+ uSize,
+ psBMHeap->ui32Attribs,
+ &pBuf->hOSMemHandle)!=PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "AllocMemory: OSGetSubMemHandle FAILED"));
+ return IMG_FALSE;
+ }
+ }
+
+
+ pBuf->CpuPAddr.uiAddr = pMapping->CpuPAddr.uiAddr + uOffset;
+
+ if(uFlags & PVRSRV_MEM_ZERO)
+ {
+ if(!ZeroBuf(pBuf, pMapping, uSize, psBMHeap->ui32Attribs | uFlags))
+ {
+ return IMG_FALSE;
+ }
+ }
+ }
+ else
+ {
+ if(uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR)
+ {
+
+ PVR_ASSERT(psDevVAddr != IMG_NULL);
+
+ if (psDevVAddr == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "AllocMemory: invalid parameter - psDevVAddr"));
+ return IMG_FALSE;
+ }
+
+
+ pBMContext->psDeviceNode->pfnMMUAlloc (psBMHeap->pMMUHeap,
+ uSize,
+ IMG_NULL,
+ PVRSRV_MEM_USER_SUPPLIED_DEVVADDR,
+ uDevVAddrAlignment,
+ psDevVAddr);
+
+
+ pBuf->DevVAddr = *psDevVAddr;
+ }
+ else
+ {
+ IMG_BOOL bResult;
+
+
+
+ bResult = pBMContext->psDeviceNode->pfnMMUAlloc (psBMHeap->pMMUHeap,
+ uSize,
+ IMG_NULL,
+ 0,
+ uDevVAddrAlignment,
+ &pBuf->DevVAddr);
+
+ if(!bResult)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "AllocMemory: MMUAlloc failed"));
+ return IMG_FALSE;
+ }
+ }
+
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof (struct _BM_MAPPING_),
+ (IMG_PVOID *)&pMapping, IMG_NULL,
+ "Buffer Manager Mapping") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "AllocMemory: OSAllocMem(0x%x) FAILED", sizeof(*pMapping)));
+ return IMG_FALSE;
+ }
+
+
+ pBuf->CpuVAddr = IMG_NULL;
+ pBuf->hOSMemHandle = 0;
+ pBuf->CpuPAddr.uiAddr = 0;
+
+
+ pMapping->CpuVAddr = IMG_NULL;
+ pMapping->CpuPAddr.uiAddr = 0;
+ pMapping->DevVAddr = pBuf->DevVAddr;
+ pMapping->psSysAddr = IMG_NULL;
+ pMapping->uSize = uSize;
+ pMapping->hOSMemHandle = 0;
+ }
+
+
+ pMapping->pArena = pArena;
+
+
+ pMapping->pBMHeap = psBMHeap;
+ pBuf->pMapping = pMapping;
+
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "AllocMemory: pMapping=%08x: DevV=%08X CpuV=%08x CpuP=%08X uSize=0x%x",
+ (IMG_UINTPTR_T)pMapping,
+ pMapping->DevVAddr.uiAddr,
+ (IMG_UINTPTR_T)pMapping->CpuVAddr,
+ pMapping->CpuPAddr.uiAddr,
+ pMapping->uSize));
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "AllocMemory: pBuf=%08x: DevV=%08X CpuV=%08x CpuP=%08X uSize=0x%x",
+ (IMG_UINTPTR_T)pBuf,
+ pBuf->DevVAddr.uiAddr,
+ (IMG_UINTPTR_T)pBuf->CpuVAddr,
+ pBuf->CpuPAddr.uiAddr,
+ uSize));
+
+
+ PVR_ASSERT(((pBuf->DevVAddr.uiAddr) & (uDevVAddrAlignment - 1)) == 0);
+
+ return IMG_TRUE;
+}
+
+
+static IMG_BOOL
+WrapMemory (BM_HEAP *psBMHeap,
+ IMG_SIZE_T uSize,
+ IMG_SIZE_T ui32BaseOffset,
+ IMG_BOOL bPhysContig,
+ IMG_SYS_PHYADDR *psAddr,
+ IMG_VOID *pvCPUVAddr,
+ IMG_UINT32 uFlags,
+ BM_BUF *pBuf)
+{
+ IMG_DEV_VIRTADDR DevVAddr = {0};
+ BM_MAPPING *pMapping;
+ IMG_BOOL bResult;
+ IMG_SIZE_T const ui32PageSize = HOST_PAGESIZE();
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "WrapMemory(psBMHeap=%08X, size=0x%x, offset=0x%x, bPhysContig=0x%x, pvCPUVAddr = 0x%08x, flags=0x%x)",
+ (IMG_UINTPTR_T)psBMHeap, uSize, ui32BaseOffset, bPhysContig, (IMG_UINTPTR_T)pvCPUVAddr, uFlags));
+
+ PVR_ASSERT((psAddr->uiAddr & (ui32PageSize - 1)) == 0);
+
+ PVR_ASSERT(((IMG_UINTPTR_T)pvCPUVAddr & (ui32PageSize - 1)) == 0);
+
+ uSize += ui32BaseOffset;
+ uSize = HOST_PAGEALIGN (uSize);
+
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*pMapping),
+ (IMG_PVOID *)&pMapping, IMG_NULL,
+ "Mocked-up mapping") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "WrapMemory: OSAllocMem(0x%x) FAILED",sizeof(*pMapping)));
+ return IMG_FALSE;
+ }
+
+ OSMemSet(pMapping, 0, sizeof (*pMapping));
+
+ pMapping->uSize = uSize;
+ pMapping->pBMHeap = psBMHeap;
+
+ if(pvCPUVAddr)
+ {
+ pMapping->CpuVAddr = pvCPUVAddr;
+
+ if (bPhysContig)
+ {
+ pMapping->eCpuMemoryOrigin = hm_wrapped_virtaddr;
+ pMapping->CpuPAddr = SysSysPAddrToCpuPAddr(psAddr[0]);
+
+ if(OSRegisterMem(pMapping->CpuPAddr,
+ pMapping->CpuVAddr,
+ pMapping->uSize,
+ uFlags,
+ &pMapping->hOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "WrapMemory: OSRegisterMem Phys=0x%08X, Size=%d) failed",
+ pMapping->CpuPAddr.uiAddr, pMapping->uSize));
+ goto fail_cleanup;
+ }
+ }
+ else
+ {
+ pMapping->eCpuMemoryOrigin = hm_wrapped_scatter_virtaddr;
+ pMapping->psSysAddr = psAddr;
+
+ if(OSRegisterDiscontigMem(pMapping->psSysAddr,
+ pMapping->CpuVAddr,
+ pMapping->uSize,
+ uFlags,
+ &pMapping->hOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "WrapMemory: OSRegisterDiscontigMem Size=%d) failed",
+ pMapping->uSize));
+ goto fail_cleanup;
+ }
+ }
+ }
+ else
+ {
+ if (bPhysContig)
+ {
+ pMapping->eCpuMemoryOrigin = hm_wrapped;
+ pMapping->CpuPAddr = SysSysPAddrToCpuPAddr(psAddr[0]);
+
+ if(OSReservePhys(pMapping->CpuPAddr,
+ pMapping->uSize,
+ uFlags,
+ &pMapping->CpuVAddr,
+ &pMapping->hOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "WrapMemory: OSReservePhys Phys=0x%08X, Size=%d) failed",
+ pMapping->CpuPAddr.uiAddr, pMapping->uSize));
+ goto fail_cleanup;
+ }
+ }
+ else
+ {
+ pMapping->eCpuMemoryOrigin = hm_wrapped_scatter;
+ pMapping->psSysAddr = psAddr;
+
+ if(OSReserveDiscontigPhys(pMapping->psSysAddr,
+ pMapping->uSize,
+ uFlags,
+ &pMapping->CpuVAddr,
+ &pMapping->hOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "WrapMemory: OSReserveDiscontigPhys Size=%d) failed",
+ pMapping->uSize));
+ goto fail_cleanup;
+ }
+ }
+ }
+
+
+ bResult = DevMemoryAlloc(psBMHeap->pBMContext,
+ pMapping,
+ IMG_NULL,
+ uFlags | PVRSRV_MEM_READ | PVRSRV_MEM_WRITE,
+ IMG_CAST_TO_DEVVADDR_UINT(ui32PageSize),
+ &DevVAddr);
+ if (!bResult)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "WrapMemory: DevMemoryAlloc(0x%x) failed",
+ pMapping->uSize));
+ goto fail_cleanup;
+ }
+
+
+ pBuf->CpuPAddr.uiAddr = pMapping->CpuPAddr.uiAddr + ui32BaseOffset;
+ if(!ui32BaseOffset)
+ {
+ pBuf->hOSMemHandle = pMapping->hOSMemHandle;
+ }
+ else
+ {
+ if(OSGetSubMemHandle(pMapping->hOSMemHandle,
+ ui32BaseOffset,
+ (pMapping->uSize-ui32BaseOffset),
+ uFlags,
+ &pBuf->hOSMemHandle)!=PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "WrapMemory: OSGetSubMemHandle failed"));
+ goto fail_cleanup;
+ }
+ }
+ if(pMapping->CpuVAddr)
+ {
+ pBuf->CpuVAddr = (IMG_VOID*) ((IMG_UINTPTR_T)pMapping->CpuVAddr + ui32BaseOffset);
+ }
+ pBuf->DevVAddr.uiAddr = pMapping->DevVAddr.uiAddr + IMG_CAST_TO_DEVVADDR_UINT(ui32BaseOffset);
+
+ if(uFlags & PVRSRV_MEM_ZERO)
+ {
+ if(!ZeroBuf(pBuf, pMapping, uSize, uFlags))
+ {
+ return IMG_FALSE;
+ }
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "DevVaddr.uiAddr=%08X", DevVAddr.uiAddr));
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "WrapMemory: DevV=%08X CpuP=%08X uSize=0x%x",
+ pMapping->DevVAddr.uiAddr, pMapping->CpuPAddr.uiAddr, pMapping->uSize));
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "WrapMemory: DevV=%08X CpuP=%08X uSize=0x%x",
+ pBuf->DevVAddr.uiAddr, pBuf->CpuPAddr.uiAddr, uSize));
+
+ pBuf->pMapping = pMapping;
+ return IMG_TRUE;
+
+fail_cleanup:
+ if(ui32BaseOffset && pBuf->hOSMemHandle)
+ {
+ OSReleaseSubMemHandle(pBuf->hOSMemHandle, uFlags);
+ }
+
+ if(pMapping && (pMapping->CpuVAddr || pMapping->hOSMemHandle))
+ {
+ switch(pMapping->eCpuMemoryOrigin)
+ {
+ case hm_wrapped:
+ OSUnReservePhys(pMapping->CpuVAddr, pMapping->uSize, uFlags, pMapping->hOSMemHandle);
+ break;
+ case hm_wrapped_virtaddr:
+ OSUnRegisterMem(pMapping->CpuVAddr, pMapping->uSize, uFlags, pMapping->hOSMemHandle);
+ break;
+ case hm_wrapped_scatter:
+ OSUnReserveDiscontigPhys(pMapping->CpuVAddr, pMapping->uSize, uFlags, pMapping->hOSMemHandle);
+ break;
+ case hm_wrapped_scatter_virtaddr:
+ OSUnRegisterDiscontigMem(pMapping->CpuVAddr, pMapping->uSize, uFlags, pMapping->hOSMemHandle);
+ break;
+ default:
+ break;
+ }
+
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL);
+
+
+ return IMG_FALSE;
+}
+
+
+static IMG_BOOL
+ZeroBuf(BM_BUF *pBuf, BM_MAPPING *pMapping, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags)
+{
+ IMG_VOID *pvCpuVAddr;
+
+ if(pBuf->CpuVAddr)
+ {
+ OSMemSet(pBuf->CpuVAddr, 0, ui32Bytes);
+ }
+ else if(pMapping->eCpuMemoryOrigin == hm_contiguous
+ || pMapping->eCpuMemoryOrigin == hm_wrapped)
+ {
+ pvCpuVAddr = OSMapPhysToLin(pBuf->CpuPAddr,
+ ui32Bytes,
+ PVRSRV_HAP_KERNEL_ONLY
+ | (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK),
+ IMG_NULL);
+ if(!pvCpuVAddr)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ZeroBuf: OSMapPhysToLin for contiguous buffer failed"));
+ return IMG_FALSE;
+ }
+ OSMemSet(pvCpuVAddr, 0, ui32Bytes);
+ OSUnMapPhysToLin(pvCpuVAddr,
+ ui32Bytes,
+ PVRSRV_HAP_KERNEL_ONLY
+ | (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK),
+ IMG_NULL);
+ }
+ else
+ {
+ IMG_SIZE_T ui32BytesRemaining = ui32Bytes;
+ IMG_SIZE_T ui32CurrentOffset = 0;
+ IMG_CPU_PHYADDR CpuPAddr;
+
+
+ PVR_ASSERT(pBuf->hOSMemHandle);
+
+ while(ui32BytesRemaining > 0)
+ {
+ IMG_SIZE_T ui32BlockBytes = MIN(ui32BytesRemaining, HOST_PAGESIZE());
+ CpuPAddr = OSMemHandleToCpuPAddr(pBuf->hOSMemHandle, ui32CurrentOffset);
+
+ if(CpuPAddr.uiAddr & (HOST_PAGESIZE() -1))
+ {
+ ui32BlockBytes =
+ MIN(ui32BytesRemaining, (IMG_UINT32)(HOST_PAGEALIGN(CpuPAddr.uiAddr) - CpuPAddr.uiAddr));
+ }
+
+ pvCpuVAddr = OSMapPhysToLin(CpuPAddr,
+ ui32BlockBytes,
+ PVRSRV_HAP_KERNEL_ONLY
+ | (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK),
+ IMG_NULL);
+ if(!pvCpuVAddr)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ZeroBuf: OSMapPhysToLin while zeroing non-contiguous memory FAILED"));
+ return IMG_FALSE;
+ }
+ OSMemSet(pvCpuVAddr, 0, ui32BlockBytes);
+ OSUnMapPhysToLin(pvCpuVAddr,
+ ui32BlockBytes,
+ PVRSRV_HAP_KERNEL_ONLY
+ | (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK),
+ IMG_NULL);
+
+ ui32BytesRemaining -= ui32BlockBytes;
+ ui32CurrentOffset += ui32BlockBytes;
+ }
+ }
+
+ return IMG_TRUE;
+}
+
+static IMG_VOID
+FreeBuf (BM_BUF *pBuf, IMG_UINT32 ui32Flags, IMG_BOOL bFromAllocator)
+{
+ BM_MAPPING *pMapping;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "FreeBuf: pBuf=0x%x: DevVAddr=%08X CpuVAddr=0x%x CpuPAddr=%08X",
+ (IMG_UINTPTR_T)pBuf, pBuf->DevVAddr.uiAddr,
+ (IMG_UINTPTR_T)pBuf->CpuVAddr, pBuf->CpuPAddr.uiAddr));
+
+
+ pMapping = pBuf->pMapping;
+
+ psDeviceNode = pMapping->pBMHeap->pBMContext->psDeviceNode;
+ if (psDeviceNode->pfnCacheInvalidate)
+ {
+ psDeviceNode->pfnCacheInvalidate(psDeviceNode);
+ }
+
+ if(ui32Flags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR)
+ {
+
+ if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
+ {
+
+ if(ui32Flags & PVRSRV_MEM_RAM_BACKED_ALLOCATION)
+ {
+
+ PVR_DPF ((PVR_DBG_ERROR, "FreeBuf: combination of DevVAddr management and RAM backing mode unsupported"));
+ }
+ else
+ {
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL);
+ pBuf->pMapping = IMG_NULL;
+ }
+ }
+ }
+ else
+ {
+
+ if(pBuf->hOSMemHandle != pMapping->hOSMemHandle)
+ {
+
+ if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
+ {
+
+ OSReleaseSubMemHandle(pBuf->hOSMemHandle, ui32Flags);
+ }
+ }
+ if(ui32Flags & PVRSRV_MEM_RAM_BACKED_ALLOCATION)
+ {
+
+
+ if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
+ {
+
+
+
+ PVR_ASSERT(pBuf->ui32ExportCount == 0)
+ RA_Free (pBuf->pMapping->pArena, pBuf->DevVAddr.uiAddr, IMG_FALSE);
+ }
+ }
+ else
+ {
+ if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
+ {
+ switch (pMapping->eCpuMemoryOrigin)
+ {
+ case hm_wrapped:
+ OSUnReservePhys(pMapping->CpuVAddr, pMapping->uSize, ui32Flags, pMapping->hOSMemHandle);
+ break;
+ case hm_wrapped_virtaddr:
+ OSUnRegisterMem(pMapping->CpuVAddr, pMapping->uSize, ui32Flags, pMapping->hOSMemHandle);
+ break;
+ case hm_wrapped_scatter:
+ OSUnReserveDiscontigPhys(pMapping->CpuVAddr, pMapping->uSize, ui32Flags, pMapping->hOSMemHandle);
+ break;
+ case hm_wrapped_scatter_virtaddr:
+ OSUnRegisterDiscontigMem(pMapping->CpuVAddr, pMapping->uSize, ui32Flags, pMapping->hOSMemHandle);
+ break;
+ default:
+ break;
+ }
+ }
+ if (bFromAllocator)
+ DevMemoryFree (pMapping);
+
+ if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
+ {
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL);
+ pBuf->pMapping = IMG_NULL;
+ }
+ }
+ }
+
+
+ if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_BUF), pBuf, IMG_NULL);
+
+ }
+}
+
+static PVRSRV_ERROR BM_DestroyContext_AnyCb(BM_HEAP *psBMHeap)
+{
+ if(psBMHeap->ui32Attribs
+ & (PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG
+ |PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG))
+ {
+ if (psBMHeap->pImportArena)
+ {
+ IMG_BOOL bTestDelete = RA_TestDelete(psBMHeap->pImportArena);
+ if (!bTestDelete)
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext_AnyCb: RA_TestDelete failed"));
+ return PVRSRV_ERROR_UNABLE_TO_DESTROY_BM_HEAP;
+ }
+ }
+ }
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+BM_DestroyContext(IMG_HANDLE hBMContext,
+ IMG_BOOL *pbDestroyed)
+{
+ PVRSRV_ERROR eError;
+ BM_CONTEXT *pBMContext = (BM_CONTEXT*)hBMContext;
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "BM_DestroyContext"));
+
+ if (pbDestroyed != IMG_NULL)
+ {
+ *pbDestroyed = IMG_FALSE;
+ }
+
+
+
+ if (pBMContext == IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: Invalid handle"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ pBMContext->ui32RefCount--;
+
+ if (pBMContext->ui32RefCount > 0)
+ {
+
+ return PVRSRV_OK;
+ }
+
+
+
+
+ eError = List_BM_HEAP_PVRSRV_ERROR_Any(pBMContext->psBMHeap, &BM_DestroyContext_AnyCb);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: List_BM_HEAP_PVRSRV_ERROR_Any failed"));
+#if 0
+
+
+
+
+ PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: Cleaning up with ResManFreeSpecial"));
+ if(ResManFreeSpecial() != PVRSRV_OK)
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: ResManFreeSpecial failed %d",eError));
+ }
+
+#endif
+ return eError;
+ }
+ else
+ {
+
+ eError = ResManFreeResByPtr(pBMContext->hResItem, CLEANUP_WITH_POLL);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: ResManFreeResByPtr failed %d",eError));
+ return eError;
+ }
+
+
+ if (pbDestroyed != IMG_NULL)
+ {
+ *pbDestroyed = IMG_TRUE;
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR BM_DestroyContextCallBack_AnyVaCb(BM_HEAP *psBMHeap, va_list va)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ psDeviceNode = va_arg(va, PVRSRV_DEVICE_NODE*);
+
+
+ if(psBMHeap->ui32Attribs
+ & (PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG
+ |PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG))
+ {
+ if (psBMHeap->pImportArena)
+ {
+ RA_Delete (psBMHeap->pImportArena);
+ }
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_DestroyContext: backing store type unsupported"));
+ return PVRSRV_ERROR_UNSUPPORTED_BACKING_STORE;
+ }
+
+
+ psDeviceNode->pfnMMUDelete(psBMHeap->pMMUHeap);
+
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_HEAP), psBMHeap, IMG_NULL);
+
+
+ return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR BM_DestroyContextCallBack(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param,
+ IMG_BOOL bDummy)
+{
+ BM_CONTEXT *pBMContext = pvParam;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ PVRSRV_ERROR eError;
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+ PVR_UNREFERENCED_PARAMETER(bDummy);
+
+
+
+ psDeviceNode = pBMContext->psDeviceNode;
+
+
+
+ eError = List_BM_HEAP_PVRSRV_ERROR_Any_va(pBMContext->psBMHeap,
+ &BM_DestroyContextCallBack_AnyVaCb,
+ psDeviceNode);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+
+ if (pBMContext->psMMUContext)
+ {
+ psDeviceNode->pfnMMUFinalise(pBMContext->psMMUContext);
+ }
+
+
+
+ if (pBMContext->pBufferHash)
+ {
+ HASH_Delete(pBMContext->pBufferHash);
+ }
+
+ if (pBMContext == psDeviceNode->sDevMemoryInfo.pBMKernelContext)
+ {
+
+ psDeviceNode->sDevMemoryInfo.pBMKernelContext = IMG_NULL;
+ }
+ else
+ {
+ if (pBMContext->ppsThis != IMG_NULL)
+ {
+
+ List_BM_CONTEXT_Remove(pBMContext);
+ }
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_CONTEXT), pBMContext, IMG_NULL);
+
+
+ return PVRSRV_OK;
+}
+
+
+static IMG_HANDLE BM_CreateContext_IncRefCount_AnyVaCb(BM_CONTEXT *pBMContext, va_list va)
+{
+ PRESMAN_CONTEXT hResManContext;
+ hResManContext = va_arg(va, PRESMAN_CONTEXT);
+ if(ResManFindResourceByPtr(hResManContext, pBMContext->hResItem) == PVRSRV_OK)
+ {
+
+ pBMContext->ui32RefCount++;
+ return pBMContext;
+ }
+ return IMG_NULL;
+}
+
+static IMG_VOID BM_CreateContext_InsertHeap_ForEachVaCb(BM_HEAP *psBMHeap, va_list va)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ BM_CONTEXT *pBMContext;
+ psDeviceNode = va_arg(va, PVRSRV_DEVICE_NODE*);
+ pBMContext = va_arg(va, BM_CONTEXT*);
+ switch(psBMHeap->sDevArena.DevMemHeapType)
+ {
+ case DEVICE_MEMORY_HEAP_SHARED:
+ case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+ {
+
+ psDeviceNode->pfnMMUInsertHeap(pBMContext->psMMUContext, psBMHeap->pMMUHeap);
+ break;
+ }
+ }
+}
+
+IMG_HANDLE
+BM_CreateContext(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_DEV_PHYADDR *psPDDevPAddr,
+ PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_BOOL *pbCreated)
+{
+ BM_CONTEXT *pBMContext;
+ DEVICE_MEMORY_INFO *psDevMemoryInfo;
+ IMG_BOOL bKernelContext;
+ PRESMAN_CONTEXT hResManContext;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "BM_CreateContext"));
+
+ if (psPerProc == IMG_NULL)
+ {
+ bKernelContext = IMG_TRUE;
+ hResManContext = psDeviceNode->hResManContext;
+ }
+ else
+ {
+ bKernelContext = IMG_FALSE;
+ hResManContext = psPerProc->hResManContext;
+ }
+
+ if (pbCreated != IMG_NULL)
+ {
+ *pbCreated = IMG_FALSE;
+ }
+
+
+ psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+
+ if (bKernelContext == IMG_FALSE)
+ {
+ IMG_HANDLE res = (IMG_HANDLE) List_BM_CONTEXT_Any_va(psDevMemoryInfo->pBMContext,
+ &BM_CreateContext_IncRefCount_AnyVaCb,
+ hResManContext);
+ if (res)
+ {
+ return res;
+ }
+ }
+
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof (struct _BM_CONTEXT_),
+ (IMG_PVOID *)&pBMContext, IMG_NULL,
+ "Buffer Manager Context") != PVRSRV_OK)
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "BM_CreateContext: Alloc failed"));
+ return IMG_NULL;
+ }
+ OSMemSet(pBMContext, 0, sizeof (BM_CONTEXT));
+
+
+ pBMContext->psDeviceNode = psDeviceNode;
+
+
+
+ pBMContext->pBufferHash = HASH_Create(32);
+ if (pBMContext->pBufferHash==IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "BM_CreateContext: HASH_Create failed"));
+ goto cleanup;
+ }
+
+ if((IMG_NULL == psDeviceNode->pfnMMUInitialise) || (psDeviceNode->pfnMMUInitialise(psDeviceNode,
+ &pBMContext->psMMUContext,
+ psPDDevPAddr) != PVRSRV_OK))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_CreateContext: MMUInitialise failed"));
+ goto cleanup;
+ }
+
+ if(bKernelContext)
+ {
+
+ PVR_ASSERT(psDevMemoryInfo->pBMKernelContext == IMG_NULL);
+ psDevMemoryInfo->pBMKernelContext = pBMContext;
+ }
+ else
+ {
+
+
+
+
+
+ PVR_ASSERT(psDevMemoryInfo->pBMKernelContext);
+
+ if (psDevMemoryInfo->pBMKernelContext == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_CreateContext: psDevMemoryInfo->pBMKernelContext invalid"));
+ goto cleanup;
+ }
+
+ PVR_ASSERT(psDevMemoryInfo->pBMKernelContext->psBMHeap);
+
+
+
+
+
+ pBMContext->psBMSharedHeap = psDevMemoryInfo->pBMKernelContext->psBMHeap;
+
+
+
+
+ List_BM_HEAP_ForEach_va(pBMContext->psBMSharedHeap,
+ &BM_CreateContext_InsertHeap_ForEachVaCb,
+ psDeviceNode,
+ pBMContext);
+
+
+ List_BM_CONTEXT_Insert(&psDevMemoryInfo->pBMContext, pBMContext);
+ }
+
+
+ pBMContext->ui32RefCount++;
+
+
+ pBMContext->hResItem = ResManRegisterRes(hResManContext,
+ RESMAN_TYPE_DEVICEMEM_CONTEXT,
+ pBMContext,
+ 0,
+ &BM_DestroyContextCallBack);
+ if (pBMContext->hResItem == IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "BM_CreateContext: ResManRegisterRes failed"));
+ goto cleanup;
+ }
+
+ if (pbCreated != IMG_NULL)
+ {
+ *pbCreated = IMG_TRUE;
+ }
+ return (IMG_HANDLE)pBMContext;
+
+cleanup:
+ (IMG_VOID)BM_DestroyContextCallBack(pBMContext, 0, CLEANUP_WITH_POLL);
+
+ return IMG_NULL;
+}
+
+
+static IMG_VOID *BM_CreateHeap_AnyVaCb(BM_HEAP *psBMHeap, va_list va)
+{
+ DEVICE_MEMORY_HEAP_INFO *psDevMemHeapInfo;
+ psDevMemHeapInfo = va_arg(va, DEVICE_MEMORY_HEAP_INFO*);
+ if (psBMHeap->sDevArena.ui32HeapID == psDevMemHeapInfo->ui32HeapID)
+ {
+
+ return psBMHeap;
+ }
+ else
+ {
+ return IMG_NULL;
+ }
+}
+
+IMG_HANDLE
+BM_CreateHeap (IMG_HANDLE hBMContext,
+ DEVICE_MEMORY_HEAP_INFO *psDevMemHeapInfo)
+{
+ BM_CONTEXT *pBMContext = (BM_CONTEXT*)hBMContext;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ BM_HEAP *psBMHeap;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "BM_CreateHeap"));
+
+ if(!pBMContext)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: BM_CONTEXT null"));
+ return IMG_NULL;
+ }
+
+ psDeviceNode = pBMContext->psDeviceNode;
+
+
+
+ PVR_ASSERT((psDevMemHeapInfo->ui32HeapSize & (psDevMemHeapInfo->ui32DataPageSize - 1)) == 0);
+ PVR_ASSERT(psDevMemHeapInfo->ui32HeapSize > 0);
+
+
+
+
+
+
+ if(pBMContext->ui32RefCount > 0)
+ {
+ psBMHeap = (BM_HEAP*)List_BM_HEAP_Any_va(pBMContext->psBMHeap,
+ &BM_CreateHeap_AnyVaCb,
+ psDevMemHeapInfo);
+
+ if (psBMHeap)
+ {
+ return psBMHeap;
+ }
+ }
+
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof (BM_HEAP),
+ (IMG_PVOID *)&psBMHeap, IMG_NULL,
+ "Buffer Manager Heap") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: Alloc failed"));
+ return IMG_NULL;
+ }
+
+ OSMemSet (psBMHeap, 0, sizeof (BM_HEAP));
+
+ psBMHeap->sDevArena.ui32HeapID = psDevMemHeapInfo->ui32HeapID;
+ psBMHeap->sDevArena.pszName = psDevMemHeapInfo->pszName;
+ psBMHeap->sDevArena.BaseDevVAddr = psDevMemHeapInfo->sDevVAddrBase;
+ psBMHeap->sDevArena.ui32Size = psDevMemHeapInfo->ui32HeapSize;
+ psBMHeap->sDevArena.DevMemHeapType = psDevMemHeapInfo->DevMemHeapType;
+ psBMHeap->sDevArena.ui32DataPageSize = psDevMemHeapInfo->ui32DataPageSize;
+ psBMHeap->sDevArena.psDeviceMemoryHeapInfo = psDevMemHeapInfo;
+ psBMHeap->ui32Attribs = psDevMemHeapInfo->ui32Attribs;
+#if defined(SUPPORT_MEMORY_TILING)
+ psBMHeap->ui32XTileStride = psDevMemHeapInfo->ui32XTileStride;
+#endif
+
+
+ psBMHeap->pBMContext = pBMContext;
+
+ psBMHeap->pMMUHeap = psDeviceNode->pfnMMUCreate (pBMContext->psMMUContext,
+ &psBMHeap->sDevArena,
+ &psBMHeap->pVMArena,
+ &psBMHeap->psMMUAttrib);
+ if (!psBMHeap->pMMUHeap)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: MMUCreate failed"));
+ goto ErrorExit;
+ }
+
+
+ psBMHeap->pImportArena = RA_Create (psDevMemHeapInfo->pszBSName,
+ 0, 0, IMG_NULL,
+ MAX(HOST_PAGESIZE(), psBMHeap->sDevArena.ui32DataPageSize),
+ &BM_ImportMemory,
+ &BM_FreeMemory,
+ IMG_NULL,
+ psBMHeap);
+ if(psBMHeap->pImportArena == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: RA_Create failed"));
+ goto ErrorExit;
+ }
+
+ if(psBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG)
+ {
+
+
+
+
+ psBMHeap->pLocalDevMemArena = psDevMemHeapInfo->psLocalDevMemArena;
+ if(psBMHeap->pLocalDevMemArena == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: LocalDevMemArena null"));
+ goto ErrorExit;
+ }
+ }
+
+
+ List_BM_HEAP_Insert(&pBMContext->psBMHeap, psBMHeap);
+
+ return (IMG_HANDLE)psBMHeap;
+
+
+ErrorExit:
+
+
+ if (psBMHeap->pMMUHeap != IMG_NULL)
+ {
+ psDeviceNode->pfnMMUDelete (psBMHeap->pMMUHeap);
+
+ }
+
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_HEAP), psBMHeap, IMG_NULL);
+
+
+ return IMG_NULL;
+}
+
+IMG_VOID
+BM_DestroyHeap (IMG_HANDLE hDevMemHeap)
+{
+ BM_HEAP* psBMHeap = (BM_HEAP*)hDevMemHeap;
+ PVRSRV_DEVICE_NODE *psDeviceNode = psBMHeap->pBMContext->psDeviceNode;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "BM_DestroyHeap"));
+
+ if(psBMHeap)
+ {
+
+ if(psBMHeap->ui32Attribs
+ & (PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG
+ |PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG))
+ {
+ if (psBMHeap->pImportArena)
+ {
+ RA_Delete (psBMHeap->pImportArena);
+ }
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_DestroyHeap: backing store type unsupported"));
+ return;
+ }
+
+
+ psDeviceNode->pfnMMUDelete (psBMHeap->pMMUHeap);
+
+
+ List_BM_HEAP_Remove(psBMHeap);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_HEAP), psBMHeap, IMG_NULL);
+
+ }
+ else
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyHeap: invalid heap handle"));
+ }
+}
+
+
+IMG_BOOL
+BM_Reinitialise (PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+
+ PVR_DPF((PVR_DBG_MESSAGE, "BM_Reinitialise"));
+ PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+
+
+ return IMG_TRUE;
+}
+
+IMG_BOOL
+BM_Alloc ( IMG_HANDLE hDevMemHeap,
+ IMG_DEV_VIRTADDR *psDevVAddr,
+ IMG_SIZE_T uSize,
+ IMG_UINT32 *pui32Flags,
+ IMG_UINT32 uDevVAddrAlignment,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
+ BM_HANDLE *phBuf)
+{
+ BM_BUF *pBuf;
+ BM_CONTEXT *pBMContext;
+ BM_HEAP *psBMHeap;
+ SYS_DATA *psSysData;
+ IMG_UINT32 uFlags;
+
+ if (pui32Flags == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_Alloc: invalid parameter"));
+ PVR_DBG_BREAK;
+ return IMG_FALSE;
+ }
+
+ uFlags = *pui32Flags;
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "BM_Alloc (uSize=0x%x, uFlags=0x%x, uDevVAddrAlignment=0x%x)",
+ uSize, uFlags, uDevVAddrAlignment));
+
+ SysAcquireData(&psSysData);
+
+ psBMHeap = (BM_HEAP*)hDevMemHeap;
+ pBMContext = psBMHeap->pBMContext;
+
+ if(uDevVAddrAlignment == 0)
+ {
+ uDevVAddrAlignment = 1;
+ }
+
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof (BM_BUF),
+ (IMG_PVOID *)&pBuf, IMG_NULL,
+ "Buffer Manager buffer") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_Alloc: BM_Buf alloc FAILED"));
+ return IMG_FALSE;
+ }
+ OSMemSet(pBuf, 0, sizeof (BM_BUF));
+
+
+ if (AllocMemory(pBMContext,
+ psBMHeap,
+ psDevVAddr,
+ uSize,
+ uFlags,
+ uDevVAddrAlignment,
+ pvPrivData,
+ ui32PrivDataLength,
+ pBuf) != IMG_TRUE)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof (BM_BUF), pBuf, IMG_NULL);
+
+ PVR_DPF((PVR_DBG_ERROR, "BM_Alloc: AllocMemory FAILED"));
+ return IMG_FALSE;
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "BM_Alloc (uSize=0x%x, uFlags=0x%x)",
+ uSize, uFlags));
+
+
+ pBuf->ui32RefCount = 1;
+ *phBuf = (BM_HANDLE)pBuf;
+ *pui32Flags = uFlags | psBMHeap->ui32Attribs;
+
+
+ if(uFlags & PVRSRV_HAP_CACHETYPE_MASK)
+ {
+ *pui32Flags &= ~PVRSRV_HAP_CACHETYPE_MASK;
+ *pui32Flags |= (uFlags & PVRSRV_HAP_CACHETYPE_MASK);
+ }
+
+ return IMG_TRUE;
+}
+
+
+
+#if defined(PVR_LMA)
+static IMG_BOOL
+ValidSysPAddrArrayForDev(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_SYS_PHYADDR *psSysPAddr, IMG_UINT32 ui32PageCount, IMG_SIZE_T ui32PageSize)
+{
+ IMG_UINT32 i;
+
+ for (i = 0; i < ui32PageCount; i++)
+ {
+ IMG_SYS_PHYADDR sStartSysPAddr = psSysPAddr[i];
+ IMG_SYS_PHYADDR sEndSysPAddr;
+
+ if (!SysVerifySysPAddrToDevPAddr(psDeviceNode->sDevId.eDeviceType, sStartSysPAddr))
+ {
+ return IMG_FALSE;
+ }
+
+ sEndSysPAddr.uiAddr = sStartSysPAddr.uiAddr + ui32PageSize;
+
+ if (!SysVerifySysPAddrToDevPAddr(psDeviceNode->sDevId.eDeviceType, sEndSysPAddr))
+ {
+ return IMG_FALSE;
+ }
+ }
+
+ return IMG_TRUE;
+}
+
+static IMG_BOOL
+ValidSysPAddrRangeForDev(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_SYS_PHYADDR sStartSysPAddr, IMG_SIZE_T ui32Range)
+{
+ IMG_SYS_PHYADDR sEndSysPAddr;
+
+ if (!SysVerifySysPAddrToDevPAddr(psDeviceNode->sDevId.eDeviceType, sStartSysPAddr))
+ {
+ return IMG_FALSE;
+ }
+
+ sEndSysPAddr.uiAddr = sStartSysPAddr.uiAddr + ui32Range;
+
+ if (!SysVerifySysPAddrToDevPAddr(psDeviceNode->sDevId.eDeviceType, sEndSysPAddr))
+ {
+ return IMG_FALSE;
+ }
+
+ return IMG_TRUE;
+}
+
+#define WRAP_MAPPING_SIZE(ui32ByteSize, ui32PageOffset) HOST_PAGEALIGN((ui32ByteSize) + (ui32PageOffset))
+
+#define WRAP_PAGE_COUNT(ui32ByteSize, ui32PageOffset, ui32HostPageSize) (WRAP_MAPPING_SIZE(ui32ByteSize, ui32PageOffset) / (ui32HostPageSize))
+
+#endif
+
+
+IMG_BOOL
+BM_Wrap ( IMG_HANDLE hDevMemHeap,
+ IMG_SIZE_T ui32Size,
+ IMG_SIZE_T ui32Offset,
+ IMG_BOOL bPhysContig,
+ IMG_SYS_PHYADDR *psSysAddr,
+ IMG_VOID *pvCPUVAddr,
+ IMG_UINT32 *pui32Flags,
+ BM_HANDLE *phBuf)
+{
+ BM_BUF *pBuf;
+ BM_CONTEXT *psBMContext;
+ BM_HEAP *psBMHeap;
+ SYS_DATA *psSysData;
+ IMG_SYS_PHYADDR sHashAddress;
+ IMG_UINT32 uFlags;
+
+ psBMHeap = (BM_HEAP*)hDevMemHeap;
+ psBMContext = psBMHeap->pBMContext;
+
+ uFlags = psBMHeap->ui32Attribs & (PVRSRV_HAP_CACHETYPE_MASK | PVRSRV_HAP_MAPTYPE_MASK);
+
+ if ((pui32Flags != IMG_NULL) && ((*pui32Flags & PVRSRV_HAP_CACHETYPE_MASK) != 0))
+ {
+ uFlags &= ~PVRSRV_HAP_CACHETYPE_MASK;
+ uFlags |= *pui32Flags & PVRSRV_HAP_CACHETYPE_MASK;
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "BM_Wrap (uSize=0x%x, uOffset=0x%x, bPhysContig=0x%x, pvCPUVAddr=0x%x, uFlags=0x%x)",
+ ui32Size, ui32Offset, bPhysContig, (IMG_UINTPTR_T)pvCPUVAddr, uFlags));
+
+ SysAcquireData(&psSysData);
+
+#if defined(PVR_LMA)
+ if (bPhysContig)
+ {
+ if (!ValidSysPAddrRangeForDev(psBMContext->psDeviceNode, *psSysAddr, WRAP_MAPPING_SIZE(ui32Size, ui32Offset)))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: System address range invalid for device"));
+ return IMG_FALSE;
+ }
+ }
+ else
+ {
+ IMG_SIZE_T ui32HostPageSize = HOST_PAGESIZE();
+
+ if (!ValidSysPAddrArrayForDev(psBMContext->psDeviceNode, psSysAddr, WRAP_PAGE_COUNT(ui32Size, ui32Offset, ui32HostPageSize), ui32HostPageSize))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: Array of system addresses invalid for device"));
+ return IMG_FALSE;
+ }
+ }
+#endif
+
+ sHashAddress = psSysAddr[0];
+
+
+ sHashAddress.uiAddr += ui32Offset;
+
+
+ pBuf = (BM_BUF *)HASH_Retrieve(psBMContext->pBufferHash, sHashAddress.uiAddr);
+
+ if(pBuf)
+ {
+ IMG_SIZE_T ui32MappingSize = HOST_PAGEALIGN (ui32Size + ui32Offset);
+
+
+ if(pBuf->pMapping->uSize == ui32MappingSize && (pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped ||
+ pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr))
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "BM_Wrap (Matched previous Wrap! uSize=0x%x, uOffset=0x%x, SysAddr=%08X)",
+ ui32Size, ui32Offset, sHashAddress.uiAddr));
+
+ PVRSRVBMBufIncRef(pBuf);
+ *phBuf = (BM_HANDLE)pBuf;
+ if(pui32Flags)
+ *pui32Flags = uFlags;
+
+ return IMG_TRUE;
+ }
+ else
+ {
+
+ HASH_Remove(psBMContext->pBufferHash, (IMG_UINTPTR_T)sHashAddress.uiAddr);
+ }
+ }
+
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof (BM_BUF),
+ (IMG_PVOID *)&pBuf, IMG_NULL,
+ "Buffer Manager buffer") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: BM_Buf alloc FAILED"));
+ return IMG_FALSE;
+ }
+ OSMemSet(pBuf, 0, sizeof (BM_BUF));
+
+
+ if (WrapMemory (psBMHeap, ui32Size, ui32Offset, bPhysContig, psSysAddr, pvCPUVAddr, uFlags, pBuf) != IMG_TRUE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: WrapMemory FAILED"));
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof (BM_BUF), pBuf, IMG_NULL);
+
+ return IMG_FALSE;
+ }
+
+
+ if(pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped || pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr)
+ {
+
+ PVR_ASSERT(SysSysPAddrToCpuPAddr(sHashAddress).uiAddr == pBuf->CpuPAddr.uiAddr);
+
+ if (!HASH_Insert (psBMContext->pBufferHash, sHashAddress.uiAddr, (IMG_UINTPTR_T)pBuf))
+ {
+ FreeBuf (pBuf, uFlags, IMG_TRUE);
+ PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: HASH_Insert FAILED"));
+ return IMG_FALSE;
+ }
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "BM_Wrap (uSize=0x%x, uFlags=0x%x, devVAddr=%08X)",
+ ui32Size, uFlags, pBuf->DevVAddr.uiAddr));
+
+
+ pBuf->ui32RefCount = 1;
+ *phBuf = (BM_HANDLE)pBuf;
+ if(pui32Flags)
+ {
+
+ *pui32Flags = (uFlags & ~PVRSRV_HAP_MAPTYPE_MASK) | PVRSRV_HAP_MULTI_PROCESS;
+ }
+
+ return IMG_TRUE;
+}
+
+IMG_VOID
+BM_Export (BM_HANDLE hBuf)
+{
+ BM_BUF *pBuf = (BM_BUF *)hBuf;
+
+ PVRSRVBMBufIncExport(pBuf);
+}
+
+IMG_VOID
+BM_FreeExport(BM_HANDLE hBuf,
+ IMG_UINT32 ui32Flags)
+{
+ BM_BUF *pBuf = (BM_BUF *)hBuf;
+
+ PVRSRVBMBufDecExport(pBuf);
+ FreeBuf (pBuf, ui32Flags, IMG_FALSE);
+}
+
+IMG_VOID
+BM_Free (BM_HANDLE hBuf,
+ IMG_UINT32 ui32Flags)
+{
+ BM_BUF *pBuf = (BM_BUF *)hBuf;
+ SYS_DATA *psSysData;
+ IMG_SYS_PHYADDR sHashAddr;
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "BM_Free (h=0x%x)", (IMG_UINTPTR_T)hBuf));
+ PVR_ASSERT (pBuf!=IMG_NULL);
+
+ if (pBuf == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_Free: invalid parameter"));
+ return;
+ }
+
+ SysAcquireData(&psSysData);
+
+ PVRSRVBMBufDecRef(pBuf);
+ if(pBuf->ui32RefCount == 0)
+ {
+ if(pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped || pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr)
+ {
+ sHashAddr = SysCpuPAddrToSysPAddr(pBuf->CpuPAddr);
+
+ HASH_Remove (pBuf->pMapping->pBMHeap->pBMContext->pBufferHash, (IMG_UINTPTR_T)sHashAddr.uiAddr);
+ }
+ FreeBuf (pBuf, ui32Flags, IMG_TRUE);
+ }
+}
+
+
+IMG_CPU_VIRTADDR
+BM_HandleToCpuVaddr (BM_HANDLE hBuf)
+{
+ BM_BUF *pBuf = (BM_BUF *)hBuf;
+
+ PVR_ASSERT (pBuf != IMG_NULL);
+ if (pBuf == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_HandleToCpuVaddr: invalid parameter"));
+ return IMG_NULL;
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "BM_HandleToCpuVaddr(h=0x%x)=0x%x",
+ (IMG_UINTPTR_T)hBuf, (IMG_UINTPTR_T)pBuf->CpuVAddr));
+ return pBuf->CpuVAddr;
+}
+
+
+IMG_DEV_VIRTADDR
+BM_HandleToDevVaddr (BM_HANDLE hBuf)
+{
+ BM_BUF *pBuf = (BM_BUF *)hBuf;
+
+ PVR_ASSERT (pBuf != IMG_NULL);
+ if (pBuf == IMG_NULL)
+ {
+ IMG_DEV_VIRTADDR DevVAddr = {0};
+ PVR_DPF((PVR_DBG_ERROR, "BM_HandleToDevVaddr: invalid parameter"));
+ return DevVAddr;
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "BM_HandleToDevVaddr(h=0x%x)=%08X", (IMG_UINTPTR_T)hBuf, pBuf->DevVAddr.uiAddr));
+ return pBuf->DevVAddr;
+}
+
+
+IMG_SYS_PHYADDR
+BM_HandleToSysPaddr (BM_HANDLE hBuf)
+{
+ BM_BUF *pBuf = (BM_BUF *)hBuf;
+
+ PVR_ASSERT (pBuf != IMG_NULL);
+
+ if (pBuf == IMG_NULL)
+ {
+ IMG_SYS_PHYADDR PhysAddr = {0};
+ PVR_DPF((PVR_DBG_ERROR, "BM_HandleToSysPaddr: invalid parameter"));
+ return PhysAddr;
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "BM_HandleToSysPaddr(h=0x%x)=%08X", (IMG_UINTPTR_T)hBuf, pBuf->CpuPAddr.uiAddr));
+ return SysCpuPAddrToSysPAddr (pBuf->CpuPAddr);
+}
+
+IMG_HANDLE
+BM_HandleToOSMemHandle(BM_HANDLE hBuf)
+{
+ BM_BUF *pBuf = (BM_BUF *)hBuf;
+
+ PVR_ASSERT (pBuf != IMG_NULL);
+
+ if (pBuf == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_HandleToOSMemHandle: invalid parameter"));
+ return IMG_NULL;
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "BM_HandleToOSMemHandle(h=0x%x)=0x%x",
+ (IMG_UINTPTR_T)hBuf, (IMG_UINTPTR_T)pBuf->hOSMemHandle));
+ return pBuf->hOSMemHandle;
+}
+
+static IMG_BOOL
+DevMemoryAlloc (BM_CONTEXT *pBMContext,
+ BM_MAPPING *pMapping,
+ IMG_SIZE_T *pActualSize,
+ IMG_UINT32 uFlags,
+ IMG_UINT32 dev_vaddr_alignment,
+ IMG_DEV_VIRTADDR *pDevVAddr)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+#ifdef PDUMP
+ IMG_UINT32 ui32PDumpSize = (IMG_UINT32)pMapping->uSize;
+#endif
+
+ psDeviceNode = pBMContext->psDeviceNode;
+
+ if(uFlags & PVRSRV_MEM_INTERLEAVED)
+ {
+
+ pMapping->uSize *= 2;
+ }
+
+#ifdef PDUMP
+ if(uFlags & PVRSRV_MEM_DUMMY)
+ {
+
+ ui32PDumpSize = pMapping->pBMHeap->sDevArena.ui32DataPageSize;
+ }
+#endif
+
+
+ if (!psDeviceNode->pfnMMUAlloc (pMapping->pBMHeap->pMMUHeap,
+ pMapping->uSize,
+ pActualSize,
+ 0,
+ dev_vaddr_alignment,
+ &(pMapping->DevVAddr)))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DevMemoryAlloc ERROR MMU_Alloc"));
+ return IMG_FALSE;
+ }
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+ EnableHostAccess(pBMContext->psMMUContext);
+#endif
+
+#if defined(PDUMP)
+
+ PDUMPMALLOCPAGES(&psDeviceNode->sDevId,
+ pMapping->DevVAddr.uiAddr,
+ pMapping->CpuVAddr,
+ pMapping->hOSMemHandle,
+ ui32PDumpSize,
+ pMapping->pBMHeap->sDevArena.ui32DataPageSize,
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+ psDeviceNode->pfnMMUIsHeapShared(pMapping->pBMHeap->pMMUHeap),
+#else
+ IMG_FALSE,
+#endif
+ (IMG_HANDLE)pMapping);
+#endif
+
+ switch (pMapping->eCpuMemoryOrigin)
+ {
+ case hm_wrapped:
+ case hm_wrapped_virtaddr:
+ case hm_contiguous:
+ {
+ psDeviceNode->pfnMMUMapPages ( pMapping->pBMHeap->pMMUHeap,
+ pMapping->DevVAddr,
+ SysCpuPAddrToSysPAddr (pMapping->CpuPAddr),
+ pMapping->uSize,
+ uFlags,
+ (IMG_HANDLE)pMapping);
+
+ *pDevVAddr = pMapping->DevVAddr;
+ break;
+ }
+ case hm_env:
+ {
+ psDeviceNode->pfnMMUMapShadow ( pMapping->pBMHeap->pMMUHeap,
+ pMapping->DevVAddr,
+ pMapping->uSize,
+ pMapping->CpuVAddr,
+ pMapping->hOSMemHandle,
+ pDevVAddr,
+ uFlags,
+ (IMG_HANDLE)pMapping);
+ break;
+ }
+ case hm_wrapped_scatter:
+ case hm_wrapped_scatter_virtaddr:
+ {
+ psDeviceNode->pfnMMUMapScatter (pMapping->pBMHeap->pMMUHeap,
+ pMapping->DevVAddr,
+ pMapping->psSysAddr,
+ pMapping->uSize,
+ uFlags,
+ (IMG_HANDLE)pMapping);
+
+ *pDevVAddr = pMapping->DevVAddr;
+ break;
+ }
+ default:
+ PVR_DPF((PVR_DBG_ERROR,
+ "Illegal value %d for pMapping->eCpuMemoryOrigin",
+ pMapping->eCpuMemoryOrigin));
+ return IMG_FALSE;
+ }
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+ DisableHostAccess(pBMContext->psMMUContext);
+#endif
+
+ return IMG_TRUE;
+}
+
+static IMG_VOID
+DevMemoryFree (BM_MAPPING *pMapping)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_DEV_PHYADDR sDevPAddr;
+#ifdef PDUMP
+ IMG_UINT32 ui32PSize;
+#endif
+
+ psDeviceNode = pMapping->pBMHeap->pBMContext->psDeviceNode;
+ sDevPAddr = psDeviceNode->pfnMMUGetPhysPageAddr(pMapping->pBMHeap->pMMUHeap, pMapping->DevVAddr);
+
+ if (sDevPAddr.uiAddr != 0)
+ {
+#ifdef PDUMP
+
+ if(pMapping->ui32Flags & PVRSRV_MEM_DUMMY)
+ {
+
+ ui32PSize = pMapping->pBMHeap->sDevArena.ui32DataPageSize;
+ }
+ else
+ {
+ ui32PSize = (IMG_UINT32)pMapping->uSize;
+ }
+
+ PDUMPFREEPAGES(pMapping->pBMHeap,
+ pMapping->DevVAddr,
+ ui32PSize,
+ pMapping->pBMHeap->sDevArena.ui32DataPageSize,
+ (IMG_HANDLE)pMapping,
+ (pMapping->ui32Flags & PVRSRV_MEM_INTERLEAVED) ? IMG_TRUE : IMG_FALSE);
+#endif
+ }
+ psDeviceNode->pfnMMUFree (pMapping->pBMHeap->pMMUHeap, pMapping->DevVAddr, IMG_CAST_TO_DEVVADDR_UINT(pMapping->uSize));
+}
+
+#ifndef XPROC_WORKAROUND_NUM_SHAREABLES
+#define XPROC_WORKAROUND_NUM_SHAREABLES 200
+#endif
+
+#define XPROC_WORKAROUND_BAD_SHAREINDEX 0773407734
+
+#define XPROC_WORKAROUND_UNKNOWN 0
+#define XPROC_WORKAROUND_ALLOC 1
+#define XPROC_WORKAROUND_MAP 2
+
+static IMG_UINT32 gXProcWorkaroundShareIndex = XPROC_WORKAROUND_BAD_SHAREINDEX;
+static IMG_UINT32 gXProcWorkaroundState = XPROC_WORKAROUND_UNKNOWN;
+
+
+XPROC_DATA gXProcWorkaroundShareData[XPROC_WORKAROUND_NUM_SHAREABLES] = {{0}};
+
+PVRSRV_ERROR BM_XProcWorkaroundSetShareIndex(IMG_UINT32 ui32Index)
+{
+
+
+
+ if (gXProcWorkaroundShareIndex != XPROC_WORKAROUND_BAD_SHAREINDEX)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "No, it's already set!"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ gXProcWorkaroundShareIndex = ui32Index;
+ gXProcWorkaroundState = XPROC_WORKAROUND_MAP;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR BM_XProcWorkaroundUnsetShareIndex(IMG_UINT32 ui32Index)
+{
+
+
+
+ if (gXProcWorkaroundShareIndex == XPROC_WORKAROUND_BAD_SHAREINDEX)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "huh? how can it be bad??"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ if (gXProcWorkaroundShareIndex != ui32Index)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "gXProcWorkaroundShareIndex == 0x%08x != 0x%08x == ui32Index", gXProcWorkaroundShareIndex, ui32Index));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ gXProcWorkaroundShareIndex = XPROC_WORKAROUND_BAD_SHAREINDEX;
+ gXProcWorkaroundState = XPROC_WORKAROUND_UNKNOWN;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR BM_XProcWorkaroundFindNewBufferAndSetShareIndex(IMG_UINT32 *pui32Index)
+{
+
+
+
+ if (gXProcWorkaroundShareIndex != XPROC_WORKAROUND_BAD_SHAREINDEX)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ for (*pui32Index = 0; *pui32Index < XPROC_WORKAROUND_NUM_SHAREABLES; (*pui32Index)++)
+ {
+ if (gXProcWorkaroundShareData[*pui32Index].ui32RefCount == 0)
+ {
+ gXProcWorkaroundShareIndex = *pui32Index;
+ gXProcWorkaroundState = XPROC_WORKAROUND_ALLOC;
+ return PVRSRV_OK;
+ }
+ }
+
+ PVR_DPF((PVR_DBG_ERROR, "ran out of shared buffers"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+}
+
+static PVRSRV_ERROR
+XProcWorkaroundAllocShareable(RA_ARENA *psArena,
+ IMG_UINT32 ui32AllocFlags,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32PageSize,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
+ IMG_VOID **ppvCpuVAddr,
+ IMG_HANDLE *phOSMemHandle)
+{
+ if ((ui32AllocFlags & PVRSRV_MEM_XPROC) == 0)
+ {
+ PVR_DPF((PVR_DBG_VERBOSE, "XProcWorkaroundAllocShareable: bad flags"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if (gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32RefCount > 0)
+ {
+ PVR_DPF((PVR_DBG_VERBOSE,
+ "XProcWorkaroundAllocShareable: re-using previously allocated pages"));
+
+ ui32AllocFlags &= ~PVRSRV_HAP_MAPTYPE_MASK;
+ ui32AllocFlags |= PVRSRV_HAP_SINGLE_PROCESS;
+
+ if (ui32AllocFlags != gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32AllocFlags)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "Can't! Flags don't match! (I had 0x%08x, you gave 0x%08x)",
+ gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32AllocFlags,
+ ui32AllocFlags));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if (ui32Size != gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32Size)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "Can't! Size doesn't match!"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if (ui32PageSize != gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32PageSize)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "Can't! Page Size doesn't match!"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ *ppvCpuVAddr = gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].pvCpuVAddr;
+ *phOSMemHandle = gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].hOSMemHandle;
+
+ BM_XProcIndexAcquire(gXProcWorkaroundShareIndex);
+
+ return PVRSRV_OK;
+ }
+ else
+ {
+ if (gXProcWorkaroundState != XPROC_WORKAROUND_ALLOC)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "XPROC workaround in bad state! About to allocate memory from non-alloc state! (%d)",
+ gXProcWorkaroundState));
+ }
+ PVR_ASSERT(gXProcWorkaroundState == XPROC_WORKAROUND_ALLOC);
+
+ if (psArena != IMG_NULL)
+ {
+ IMG_CPU_PHYADDR sCpuPAddr;
+ IMG_SYS_PHYADDR sSysPAddr;
+
+ PVR_DPF((PVR_DBG_VERBOSE,
+ "XProcWorkaroundAllocShareable: making a NEW allocation from local mem"));
+
+ if (!RA_Alloc (psArena,
+ ui32Size,
+ IMG_NULL,
+ IMG_NULL,
+ 0,
+ ui32PageSize,
+ 0,
+ pvPrivData,
+ ui32PrivDataLength,
+ (IMG_UINTPTR_T *)&sSysPAddr.uiAddr))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "XProcWorkaroundAllocShareable: RA_Alloc(0x%x) FAILED", ui32Size));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+ if(OSReservePhys(sCpuPAddr,
+ ui32Size,
+ ui32AllocFlags,
+ (IMG_VOID **)&gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].pvCpuVAddr,
+ &gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].hOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "XProcWorkaroundAllocShareable: OSReservePhys failed"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].sSysPAddr = sSysPAddr;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_VERBOSE,
+ "XProcWorkaroundAllocShareable: making a NEW allocation from OS"));
+
+ ui32AllocFlags &= ~PVRSRV_HAP_MAPTYPE_MASK;
+ ui32AllocFlags |= PVRSRV_HAP_SINGLE_PROCESS;
+
+
+ if (OSAllocPages(ui32AllocFlags,
+ ui32Size,
+ ui32PageSize,
+ pvPrivData,
+ ui32PrivDataLength,
+ (IMG_VOID **)&gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].pvCpuVAddr,
+ &gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].hOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "XProcWorkaroundAllocShareable: OSAllocPages(0x%x) failed",
+ ui32PageSize));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ }
+
+ gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].psArena = psArena;
+ gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32AllocFlags = ui32AllocFlags;
+ gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32Size = ui32Size;
+ gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32PageSize = ui32PageSize;
+
+ *ppvCpuVAddr = gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].pvCpuVAddr;
+ *phOSMemHandle = gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].hOSMemHandle;
+
+ BM_XProcIndexAcquire(gXProcWorkaroundShareIndex);
+
+ return PVRSRV_OK;
+ }
+}
+
+static PVRSRV_ERROR XProcWorkaroundHandleToSI(IMG_HANDLE hOSMemHandle, IMG_UINT32 *pui32SI)
+{
+
+ IMG_UINT32 ui32SI;
+ IMG_BOOL bFound;
+ IMG_BOOL bErrorDups;
+
+ bFound = IMG_FALSE;
+ bErrorDups = IMG_FALSE;
+
+ for (ui32SI = 0; ui32SI < XPROC_WORKAROUND_NUM_SHAREABLES; ui32SI++)
+ {
+ if (gXProcWorkaroundShareData[ui32SI].ui32RefCount>0 && gXProcWorkaroundShareData[ui32SI].hOSMemHandle == hOSMemHandle)
+ {
+ if (bFound)
+ {
+ bErrorDups = IMG_TRUE;
+ }
+ else
+ {
+ *pui32SI = ui32SI;
+ bFound = IMG_TRUE;
+ }
+ }
+ }
+
+ if (bErrorDups || !bFound)
+ {
+ return PVRSRV_ERROR_BM_BAD_SHAREMEM_HANDLE;
+ }
+
+ return PVRSRV_OK;
+}
+
+#if defined(PVRSRV_REFCOUNT_DEBUG)
+IMG_VOID _BM_XProcIndexAcquireDebug(const IMG_CHAR *pszFile, IMG_INT iLine, IMG_UINT32 ui32Index)
+#else
+IMG_VOID _BM_XProcIndexAcquire(IMG_UINT32 ui32Index)
+#endif
+{
+#if defined(PVRSRV_REFCOUNT_DEBUG)
+ PVRSRVBMXProcIncRef2(pszFile, iLine, ui32Index);
+#else
+ PVRSRVBMXProcIncRef(ui32Index);
+#endif
+}
+
+#if defined(PVRSRV_REFCOUNT_DEBUG)
+IMG_VOID _BM_XProcIndexReleaseDebug(const IMG_CHAR *pszFile, IMG_INT iLine, IMG_UINT32 ui32Index)
+#else
+IMG_VOID _BM_XProcIndexRelease(IMG_UINT32 ui32Index)
+#endif
+{
+#if defined(PVRSRV_REFCOUNT_DEBUG)
+ PVRSRVBMXProcDecRef2(pszFile, iLine, ui32Index);
+#else
+ PVRSRVBMXProcDecRef(ui32Index);
+#endif
+
+ PVR_DPF((PVR_DBG_VERBOSE, "Reduced refcount of SI[%d] from %d to %d",
+ ui32Index, gXProcWorkaroundShareData[ui32Index].ui32RefCount+1, gXProcWorkaroundShareData[ui32Index].ui32RefCount));
+
+ if (gXProcWorkaroundShareData[ui32Index].ui32RefCount == 0)
+ {
+ if (gXProcWorkaroundShareData[ui32Index].psArena != IMG_NULL)
+ {
+ IMG_SYS_PHYADDR sSysPAddr;
+
+ if (gXProcWorkaroundShareData[ui32Index].pvCpuVAddr != IMG_NULL)
+ {
+ OSUnReservePhys(gXProcWorkaroundShareData[ui32Index].pvCpuVAddr,
+ gXProcWorkaroundShareData[ui32Index].ui32Size,
+ gXProcWorkaroundShareData[ui32Index].ui32AllocFlags,
+ gXProcWorkaroundShareData[ui32Index].hOSMemHandle);
+ }
+ sSysPAddr = gXProcWorkaroundShareData[ui32Index].sSysPAddr;
+ RA_Free (gXProcWorkaroundShareData[ui32Index].psArena,
+ sSysPAddr.uiAddr,
+ IMG_FALSE);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_VERBOSE, "freeing OS memory"));
+ OSFreePages(gXProcWorkaroundShareData[ui32Index].ui32AllocFlags,
+ gXProcWorkaroundShareData[ui32Index].ui32PageSize,
+ gXProcWorkaroundShareData[ui32Index].pvCpuVAddr,
+ gXProcWorkaroundShareData[ui32Index].hOSMemHandle);
+ }
+ }
+}
+
+static IMG_VOID XProcWorkaroundFreeShareable(IMG_HANDLE hOSMemHandle)
+{
+ IMG_UINT32 ui32SI = (IMG_UINT32)((IMG_UINTPTR_T)hOSMemHandle & 0xffffU);
+ PVRSRV_ERROR eError;
+
+ eError = XProcWorkaroundHandleToSI(hOSMemHandle, &ui32SI);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "bad handle"));
+ return;
+ }
+
+ BM_XProcIndexRelease(ui32SI);
+}
+
+
+static IMG_BOOL
+BM_ImportMemory (IMG_VOID *pH,
+ IMG_SIZE_T uRequestSize,
+ IMG_SIZE_T *pActualSize,
+ BM_MAPPING **ppsMapping,
+ IMG_UINT32 uFlags,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
+ IMG_UINTPTR_T *pBase)
+{
+ BM_MAPPING *pMapping;
+ BM_HEAP *pBMHeap = pH;
+ BM_CONTEXT *pBMContext = pBMHeap->pBMContext;
+ IMG_BOOL bResult;
+ IMG_SIZE_T uSize;
+ IMG_SIZE_T uPSize;
+ IMG_SIZE_T uDevVAddrAlignment = 0;
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "BM_ImportMemory (pBMContext=0x%x, uRequestSize=0x%x, uFlags=0x%x, uAlign=0x%x)",
+ (IMG_UINTPTR_T)pBMContext, uRequestSize, uFlags, uDevVAddrAlignment));
+
+ PVR_ASSERT (ppsMapping != IMG_NULL);
+ PVR_ASSERT (pBMContext != IMG_NULL);
+
+ if (ppsMapping == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_ImportMemory: invalid parameter"));
+ goto fail_exit;
+ }
+
+ uSize = HOST_PAGEALIGN (uRequestSize);
+ PVR_ASSERT (uSize >= uRequestSize);
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof (BM_MAPPING),
+ (IMG_PVOID *)&pMapping, IMG_NULL,
+ "Buffer Manager Mapping") != PVRSRV_OK)
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "BM_ImportMemory: failed BM_MAPPING alloc"));
+ goto fail_exit;
+ }
+
+ pMapping->hOSMemHandle = 0;
+ pMapping->CpuVAddr = 0;
+ pMapping->DevVAddr.uiAddr = 0;
+ pMapping->CpuPAddr.uiAddr = 0;
+ pMapping->uSize = uSize;
+ pMapping->pBMHeap = pBMHeap;
+ pMapping->ui32Flags = uFlags;
+
+
+ if (pActualSize)
+ {
+ *pActualSize = uSize;
+ }
+
+
+ if(pMapping->ui32Flags & PVRSRV_MEM_DUMMY)
+ {
+ uPSize = pBMHeap->sDevArena.ui32DataPageSize;
+ }
+ else
+ {
+ uPSize = pMapping->uSize;
+ }
+
+ if (uFlags & PVRSRV_MEM_XPROC)
+ {
+ IMG_UINT32 ui32Attribs = pBMHeap->ui32Attribs | PVRSRV_MEM_XPROC;
+ IMG_BOOL bBadBackingStoreType;
+
+
+ if(uFlags & PVRSRV_MEM_ION)
+ {
+ ui32Attribs |= PVRSRV_MEM_ION;
+ }
+
+ bBadBackingStoreType = IMG_TRUE;
+
+ if ((ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG) != 0)
+ {
+#ifndef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+ uDevVAddrAlignment = MAX(pBMHeap->sDevArena.ui32DataPageSize, HOST_PAGESIZE());
+
+
+ if (uPSize % uDevVAddrAlignment != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Cannot use use this memory sharing workaround with allocations that might be suballocated"));
+ goto fail_mapping_alloc;
+ }
+ uDevVAddrAlignment = 0;
+
+
+ if (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)
+ {
+ ui32Attribs &= ~PVRSRV_HAP_CACHETYPE_MASK;
+ ui32Attribs |= (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK);
+ }
+
+
+ if (XProcWorkaroundAllocShareable(IMG_NULL,
+ ui32Attribs,
+ (IMG_UINT32)uPSize,
+ pBMHeap->sDevArena.ui32DataPageSize,
+ pvPrivData,
+ ui32PrivDataLength,
+ (IMG_VOID **)&pMapping->CpuVAddr,
+ &pMapping->hOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "BM_ImportMemory: XProcWorkaroundAllocShareable(0x%x) failed",
+ uPSize));
+ goto fail_mapping_alloc;
+ }
+
+
+
+
+ pMapping->eCpuMemoryOrigin = hm_env;
+ bBadBackingStoreType = IMG_FALSE;
+ }
+
+ if ((ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG) != 0)
+ {
+ uDevVAddrAlignment = pBMHeap->sDevArena.ui32DataPageSize;
+
+ if (uPSize % uDevVAddrAlignment != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Cannot use use this memory sharing workaround with allocations that might be suballocated"));
+ goto fail_mapping_alloc;
+ }
+ uDevVAddrAlignment = 0;
+
+
+ if (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)
+ {
+ ui32Attribs &= ~PVRSRV_HAP_CACHETYPE_MASK;
+ ui32Attribs |= (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK);
+ }
+
+
+ if (XProcWorkaroundAllocShareable(pBMHeap->pLocalDevMemArena,
+ ui32Attribs,
+ (IMG_UINT32)uPSize,
+ pBMHeap->sDevArena.ui32DataPageSize,
+ pvPrivData,
+ ui32PrivDataLength,
+ (IMG_VOID **)&pMapping->CpuVAddr,
+ &pMapping->hOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "BM_ImportMemory: XProcWorkaroundAllocShareable(0x%x) failed",
+ uPSize));
+ goto fail_mapping_alloc;
+ }
+
+
+
+
+ pMapping->eCpuMemoryOrigin = hm_env;
+ bBadBackingStoreType = IMG_FALSE;
+ }
+
+ if (bBadBackingStoreType)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Cannot use this memory sharing workaround with this type of backing store"));
+ goto fail_mapping_alloc;
+ }
+ }
+ else
+
+
+
+ if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG)
+ {
+ IMG_UINT32 ui32Attribs = pBMHeap->ui32Attribs;
+
+
+ if (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)
+ {
+ ui32Attribs &= ~PVRSRV_HAP_CACHETYPE_MASK;
+ ui32Attribs |= (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK);
+ }
+
+ if (pMapping->ui32Flags & PVRSRV_MEM_ALLOCATENONCACHEDMEM)
+ {
+ ui32Attribs &= ~PVRSRV_MEM_ALLOCATENONCACHEDMEM;
+ ui32Attribs |= (pMapping->ui32Flags & PVRSRV_MEM_ALLOCATENONCACHEDMEM);
+ }
+
+
+ if (OSAllocPages(ui32Attribs,
+ uPSize,
+ pBMHeap->sDevArena.ui32DataPageSize,
+ pvPrivData,
+ ui32PrivDataLength,
+ (IMG_VOID **)&pMapping->CpuVAddr,
+ &pMapping->hOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "BM_ImportMemory: OSAllocPages(0x%x) failed",
+ uPSize));
+ goto fail_mapping_alloc;
+ }
+
+
+ pMapping->eCpuMemoryOrigin = hm_env;
+ }
+ else if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG)
+ {
+ IMG_SYS_PHYADDR sSysPAddr;
+ IMG_UINT32 ui32Attribs = pBMHeap->ui32Attribs;
+
+
+ PVR_ASSERT(pBMHeap->pLocalDevMemArena != IMG_NULL);
+
+
+ if (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)
+ {
+ ui32Attribs &= ~PVRSRV_HAP_CACHETYPE_MASK;
+ ui32Attribs |= (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK);
+ }
+
+ if (!RA_Alloc (pBMHeap->pLocalDevMemArena,
+ uPSize,
+ IMG_NULL,
+ IMG_NULL,
+ 0,
+ pBMHeap->sDevArena.ui32DataPageSize,
+ 0,
+ pvPrivData,
+ ui32PrivDataLength,
+ (IMG_UINTPTR_T *)&sSysPAddr.uiAddr))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_ImportMemory: RA_Alloc(0x%x) FAILED", uPSize));
+ goto fail_mapping_alloc;
+ }
+
+
+ pMapping->CpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+ if(OSReservePhys(pMapping->CpuPAddr,
+ uPSize,
+ ui32Attribs,
+ &pMapping->CpuVAddr,
+ &pMapping->hOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_ImportMemory: OSReservePhys failed"));
+ goto fail_dev_mem_alloc;
+ }
+
+
+ pMapping->eCpuMemoryOrigin = hm_contiguous;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_ImportMemory: Invalid backing store type"));
+ goto fail_mapping_alloc;
+ }
+
+
+ bResult = DevMemoryAlloc (pBMContext,
+ pMapping,
+ IMG_NULL,
+ uFlags,
+ (IMG_UINT32)uDevVAddrAlignment,
+ &pMapping->DevVAddr);
+ if (!bResult)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "BM_ImportMemory: DevMemoryAlloc(0x%x) failed",
+ pMapping->uSize));
+ goto fail_dev_mem_alloc;
+ }
+
+
+
+ PVR_ASSERT (uDevVAddrAlignment>1?(pMapping->DevVAddr.uiAddr%uDevVAddrAlignment)==0:1);
+
+ *pBase = pMapping->DevVAddr.uiAddr;
+ *ppsMapping = pMapping;
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "BM_ImportMemory: IMG_TRUE"));
+ return IMG_TRUE;
+
+fail_dev_mem_alloc:
+ if (pMapping && (pMapping->CpuVAddr || pMapping->hOSMemHandle))
+ {
+
+ if(pMapping->ui32Flags & PVRSRV_MEM_INTERLEAVED)
+ {
+ pMapping->uSize /= 2;
+ }
+
+ if(pMapping->ui32Flags & PVRSRV_MEM_DUMMY)
+ {
+ uPSize = pBMHeap->sDevArena.ui32DataPageSize;
+ }
+ else
+ {
+ uPSize = pMapping->uSize;
+ }
+
+ if (uFlags & PVRSRV_MEM_XPROC)
+ {
+ XProcWorkaroundFreeShareable(pMapping->hOSMemHandle);
+ }
+ else
+ if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG)
+ {
+ OSFreePages(pBMHeap->ui32Attribs,
+ uPSize,
+ (IMG_VOID *)pMapping->CpuVAddr,
+ pMapping->hOSMemHandle);
+ }
+ else
+ {
+ IMG_SYS_PHYADDR sSysPAddr;
+
+ if(pMapping->CpuVAddr)
+ {
+ OSUnReservePhys(pMapping->CpuVAddr,
+ uPSize,
+ pBMHeap->ui32Attribs,
+ pMapping->hOSMemHandle);
+ }
+ sSysPAddr = SysCpuPAddrToSysPAddr(pMapping->CpuPAddr);
+ RA_Free (pBMHeap->pLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
+ }
+ }
+fail_mapping_alloc:
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL);
+
+fail_exit:
+ return IMG_FALSE;
+}
+
+
+static IMG_VOID
+BM_FreeMemory (IMG_VOID *h, IMG_UINTPTR_T _base, BM_MAPPING *psMapping)
+{
+ BM_HEAP *pBMHeap = h;
+ IMG_SIZE_T uPSize;
+
+ PVR_UNREFERENCED_PARAMETER (_base);
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "BM_FreeMemory (h=0x%x, base=0x%x, psMapping=0x%x)",
+ (IMG_UINTPTR_T)h, _base, (IMG_UINTPTR_T)psMapping));
+
+ PVR_ASSERT (psMapping != IMG_NULL);
+
+ if (psMapping == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_FreeMemory: invalid parameter"));
+ return;
+ }
+
+ DevMemoryFree (psMapping);
+
+
+ if((psMapping->ui32Flags & PVRSRV_MEM_INTERLEAVED) != 0)
+ {
+ psMapping->uSize /= 2;
+ }
+
+ if(psMapping->ui32Flags & PVRSRV_MEM_DUMMY)
+ {
+ uPSize = psMapping->pBMHeap->sDevArena.ui32DataPageSize;
+ }
+ else
+ {
+ uPSize = psMapping->uSize;
+ }
+
+ if (psMapping->ui32Flags & PVRSRV_MEM_XPROC)
+ {
+ XProcWorkaroundFreeShareable(psMapping->hOSMemHandle);
+ }
+ else
+ if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG)
+ {
+ OSFreePages(pBMHeap->ui32Attribs,
+ uPSize,
+ (IMG_VOID *) psMapping->CpuVAddr,
+ psMapping->hOSMemHandle);
+ }
+ else if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG)
+ {
+ IMG_SYS_PHYADDR sSysPAddr;
+
+ OSUnReservePhys(psMapping->CpuVAddr, uPSize, pBMHeap->ui32Attribs, psMapping->hOSMemHandle);
+
+ sSysPAddr = SysCpuPAddrToSysPAddr(psMapping->CpuPAddr);
+
+ RA_Free (pBMHeap->pLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_FreeMemory: Invalid backing store type"));
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), psMapping, IMG_NULL);
+
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "..BM_FreeMemory (h=0x%x, base=0x%x)",
+ (IMG_UINTPTR_T)h, _base));
+}
+
+IMG_VOID BM_GetPhysPageAddr(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_DEV_VIRTADDR sDevVPageAddr,
+ IMG_DEV_PHYADDR *psDevPAddr)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "BM_GetPhysPageAddr"));
+
+ PVR_ASSERT (psMemInfo && psDevPAddr)
+
+
+ PVR_ASSERT((sDevVPageAddr.uiAddr & 0xFFF) == 0);
+
+
+ psDeviceNode = ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->pBMContext->psDeviceNode;
+
+ *psDevPAddr = psDeviceNode->pfnMMUGetPhysPageAddr(((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->pMMUHeap,
+ sDevVPageAddr);
+}
+
+
+MMU_CONTEXT* BM_GetMMUContext(IMG_HANDLE hDevMemHeap)
+{
+ BM_HEAP *pBMHeap = (BM_HEAP*)hDevMemHeap;
+
+ PVR_DPF((PVR_DBG_VERBOSE, "BM_GetMMUContext"));
+
+ return pBMHeap->pBMContext->psMMUContext;
+}
+
+MMU_CONTEXT* BM_GetMMUContextFromMemContext(IMG_HANDLE hDevMemContext)
+{
+ BM_CONTEXT *pBMContext = (BM_CONTEXT*)hDevMemContext;
+
+ PVR_DPF ((PVR_DBG_VERBOSE, "BM_GetMMUContextFromMemContext"));
+
+ return pBMContext->psMMUContext;
+}
+
+IMG_HANDLE BM_GetMMUHeap(IMG_HANDLE hDevMemHeap)
+{
+ PVR_DPF((PVR_DBG_VERBOSE, "BM_GetMMUHeap"));
+
+ return (IMG_HANDLE)((BM_HEAP*)hDevMemHeap)->pMMUHeap;
+}
+
+
+PVRSRV_DEVICE_NODE* BM_GetDeviceNode(IMG_HANDLE hDevMemContext)
+{
+ PVR_DPF((PVR_DBG_VERBOSE, "BM_GetDeviceNode"));
+
+ return ((BM_CONTEXT*)hDevMemContext)->psDeviceNode;
+}
+
+
+IMG_HANDLE BM_GetMappingHandle(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+ PVR_DPF((PVR_DBG_VERBOSE, "BM_GetMappingHandle"));
+
+ return ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->hOSMemHandle;
+}
+
diff --git a/drivers/gpu/pvr/buffer_manager.h b/drivers/gpu/pvr/buffer_manager.h
new file mode 100644
index 0000000..b78b0ae
--- /dev/null
+++ b/drivers/gpu/pvr/buffer_manager.h
@@ -0,0 +1,248 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef _BUFFER_MANAGER_H_
+#define _BUFFER_MANAGER_H_
+
+#include "img_types.h"
+#include "ra.h"
+#include "perproc.h"
+
+#if defined(__cplusplus)
+extern "C"{
+#endif
+
+typedef struct _BM_HEAP_ BM_HEAP;
+
+struct _BM_MAPPING_
+{
+ enum
+ {
+ hm_wrapped = 1,
+ hm_wrapped_scatter,
+ hm_wrapped_virtaddr,
+ hm_wrapped_scatter_virtaddr,
+ hm_env,
+ hm_contiguous
+ } eCpuMemoryOrigin;
+
+ BM_HEAP *pBMHeap;
+ RA_ARENA *pArena;
+
+ IMG_CPU_VIRTADDR CpuVAddr;
+ IMG_CPU_PHYADDR CpuPAddr;
+ IMG_DEV_VIRTADDR DevVAddr;
+ IMG_SYS_PHYADDR *psSysAddr;
+ IMG_SIZE_T uSize;
+ IMG_HANDLE hOSMemHandle;
+ IMG_UINT32 ui32Flags;
+};
+
+typedef struct _BM_BUF_
+{
+ IMG_CPU_VIRTADDR *CpuVAddr;
+ IMG_VOID *hOSMemHandle;
+ IMG_CPU_PHYADDR CpuPAddr;
+ IMG_DEV_VIRTADDR DevVAddr;
+
+ BM_MAPPING *pMapping;
+ IMG_UINT32 ui32RefCount;
+ IMG_UINT32 ui32ExportCount;
+} BM_BUF;
+
+struct _BM_HEAP_
+{
+ IMG_UINT32 ui32Attribs;
+ BM_CONTEXT *pBMContext;
+ RA_ARENA *pImportArena;
+ RA_ARENA *pLocalDevMemArena;
+ RA_ARENA *pVMArena;
+ DEV_ARENA_DESCRIPTOR sDevArena;
+ MMU_HEAP *pMMUHeap;
+ PDUMP_MMU_ATTRIB *psMMUAttrib;
+
+ struct _BM_HEAP_ *psNext;
+ struct _BM_HEAP_ **ppsThis;
+
+ IMG_UINT32 ui32XTileStride;
+};
+
+struct _BM_CONTEXT_
+{
+ MMU_CONTEXT *psMMUContext;
+
+
+ BM_HEAP *psBMHeap;
+
+
+ BM_HEAP *psBMSharedHeap;
+
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+
+ HASH_TABLE *pBufferHash;
+
+
+ IMG_HANDLE hResItem;
+
+ IMG_UINT32 ui32RefCount;
+
+
+
+ struct _BM_CONTEXT_ *psNext;
+ struct _BM_CONTEXT_ **ppsThis;
+};
+
+typedef struct _XPROC_DATA_{
+ IMG_UINT32 ui32RefCount;
+ IMG_UINT32 ui32AllocFlags;
+ IMG_UINT32 ui32Size;
+ IMG_UINT32 ui32PageSize;
+ RA_ARENA *psArena;
+ IMG_SYS_PHYADDR sSysPAddr;
+ IMG_VOID *pvCpuVAddr;
+ IMG_HANDLE hOSMemHandle;
+} XPROC_DATA;
+
+extern XPROC_DATA gXProcWorkaroundShareData[];
+typedef IMG_VOID *BM_HANDLE;
+
+#define BP_POOL_MASK 0x7
+
+#define BP_CONTIGUOUS (1 << 3)
+#define BP_PARAMBUFFER (1 << 4)
+
+#define BM_MAX_DEVMEM_ARENAS 2
+
+IMG_HANDLE
+BM_CreateContext(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_DEV_PHYADDR *psPDDevPAddr,
+ PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_BOOL *pbCreated);
+
+
+PVRSRV_ERROR
+BM_DestroyContext (IMG_HANDLE hBMContext,
+ IMG_BOOL *pbCreated);
+
+
+IMG_HANDLE
+BM_CreateHeap (IMG_HANDLE hBMContext,
+ DEVICE_MEMORY_HEAP_INFO *psDevMemHeapInfo);
+
+IMG_VOID
+BM_DestroyHeap (IMG_HANDLE hDevMemHeap);
+
+
+IMG_BOOL
+BM_Reinitialise (PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_BOOL
+BM_Alloc (IMG_HANDLE hDevMemHeap,
+ IMG_DEV_VIRTADDR *psDevVAddr,
+ IMG_SIZE_T uSize,
+ IMG_UINT32 *pui32Flags,
+ IMG_UINT32 uDevVAddrAlignment,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
+ BM_HANDLE *phBuf);
+
+IMG_BOOL
+BM_Wrap ( IMG_HANDLE hDevMemHeap,
+ IMG_SIZE_T ui32Size,
+ IMG_SIZE_T ui32Offset,
+ IMG_BOOL bPhysContig,
+ IMG_SYS_PHYADDR *psSysAddr,
+ IMG_VOID *pvCPUVAddr,
+ IMG_UINT32 *pui32Flags,
+ BM_HANDLE *phBuf);
+
+IMG_VOID
+BM_Free (BM_HANDLE hBuf,
+ IMG_UINT32 ui32Flags);
+
+
+IMG_CPU_VIRTADDR
+BM_HandleToCpuVaddr (BM_HANDLE hBuf);
+
+IMG_DEV_VIRTADDR
+BM_HandleToDevVaddr (BM_HANDLE hBuf);
+
+IMG_SYS_PHYADDR
+BM_HandleToSysPaddr (BM_HANDLE hBuf);
+
+IMG_HANDLE
+BM_HandleToOSMemHandle (BM_HANDLE hBuf);
+
+IMG_VOID BM_GetPhysPageAddr(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_DEV_VIRTADDR sDevVPageAddr,
+ IMG_DEV_PHYADDR *psDevPAddr);
+
+MMU_CONTEXT* BM_GetMMUContext(IMG_HANDLE hDevMemHeap);
+
+MMU_CONTEXT* BM_GetMMUContextFromMemContext(IMG_HANDLE hDevMemContext);
+
+IMG_HANDLE BM_GetMMUHeap(IMG_HANDLE hDevMemHeap);
+
+PVRSRV_DEVICE_NODE* BM_GetDeviceNode(IMG_HANDLE hDevMemContext);
+
+
+IMG_HANDLE BM_GetMappingHandle(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+IMG_VOID BM_Export(BM_HANDLE hBuf);
+
+IMG_VOID BM_FreeExport(BM_HANDLE hBuf, IMG_UINT32 ui32Flags);
+
+PVRSRV_ERROR BM_XProcWorkaroundSetShareIndex(IMG_UINT32 ui32Index);
+PVRSRV_ERROR BM_XProcWorkaroundUnsetShareIndex(IMG_UINT32 ui32Index);
+PVRSRV_ERROR BM_XProcWorkaroundFindNewBufferAndSetShareIndex(IMG_UINT32 *pui32Index);
+
+#if defined(PVRSRV_REFCOUNT_DEBUG)
+IMG_VOID _BM_XProcIndexAcquireDebug(const IMG_CHAR *pszFile, IMG_INT iLine, IMG_UINT32 ui32Index);
+IMG_VOID _BM_XProcIndexReleaseDebug(const IMG_CHAR *pszFile, IMG_INT iLine, IMG_UINT32 ui32Index);
+
+#define BM_XProcIndexAcquire(x...) \
+ _BM_XProcIndexAcquireDebug(__FILE__, __LINE__, x)
+#define BM_XProcIndexRelease(x...) \
+ _BM_XProcIndexReleaseDebug(__FILE__, __LINE__, x)
+
+#else
+IMG_VOID _BM_XProcIndexAcquire(IMG_UINT32 ui32Index);
+IMG_VOID _BM_XProcIndexRelease(IMG_UINT32 ui32Index);
+
+#define BM_XProcIndexAcquire(x...) \
+ _BM_XProcIndexAcquire( x)
+#define BM_XProcIndexRelease(x...) \
+ _BM_XProcIndexRelease( x)
+#endif
+
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/pvr/dbgdrv/Makefile b/drivers/gpu/pvr/dbgdrv/Makefile
new file mode 100644
index 0000000..5fdb46d
--- /dev/null
+++ b/drivers/gpu/pvr/dbgdrv/Makefile
@@ -0,0 +1,15 @@
+ccflags-y := \
+ -D__linux__ -DLINUX \
+ -Idrivers/gpu/pvr \
+ -DSUPPORT_DBGDRV_EVENT_OBJECTS \
+ -DLDM_PLATFORM
+
+dbgdrv-$(CONFIG_PVR_PDUMP) := \
+ dbgdriv.o \
+ handle.o \
+ hostfunc.o \
+ hotkey.o \
+ ioctl.o \
+ main.o
+
+obj-$(CONFIG_PVR_PDUMP) := dbgdrv.o
diff --git a/drivers/gpu/pvr/dbgdrv/dbgdriv.c b/drivers/gpu/pvr/dbgdrv/dbgdriv.c
new file mode 100644
index 0000000..386aca4
--- /dev/null
+++ b/drivers/gpu/pvr/dbgdrv/dbgdriv.c
@@ -0,0 +1,2354 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+
+#ifdef LINUX
+#include <linux/string.h>
+#endif
+
+#include "img_types.h"
+#include "pvr_debug.h"
+#include "dbgdrvif.h"
+#include "dbgdriv.h"
+#include "hotkey.h"
+#include "hostfunc.h"
+#include "pvr_debug.h"
+
+
+
+
+#define LAST_FRAME_BUF_SIZE 1024
+
+typedef struct _DBG_LASTFRAME_BUFFER_
+{
+ PDBG_STREAM psStream;
+ IMG_UINT8 ui8Buffer[LAST_FRAME_BUF_SIZE];
+ IMG_UINT32 ui32BufLen;
+ struct _DBG_LASTFRAME_BUFFER_ *psNext;
+} *PDBG_LASTFRAME_BUFFER;
+
+
+static PDBG_STREAM g_psStreamList = 0;
+static PDBG_LASTFRAME_BUFFER g_psLFBufferList;
+
+static IMG_UINT32 g_ui32LOff = 0;
+static IMG_UINT32 g_ui32Line = 0;
+static IMG_UINT32 g_ui32MonoLines = 25;
+
+static IMG_BOOL g_bHotkeyMiddump = IMG_FALSE;
+static IMG_UINT32 g_ui32HotkeyMiddumpStart = 0xffffffff;
+static IMG_UINT32 g_ui32HotkeyMiddumpEnd = 0xffffffff;
+
+IMG_VOID * g_pvAPIMutex=IMG_NULL;
+
+extern IMG_UINT32 g_ui32HotKeyFrame;
+extern IMG_BOOL g_bHotKeyPressed;
+extern IMG_BOOL g_bHotKeyRegistered;
+
+IMG_BOOL gbDumpThisFrame = IMG_FALSE;
+
+
+IMG_UINT32 SpaceInStream(PDBG_STREAM psStream);
+IMG_BOOL ExpandStreamBuffer(PDBG_STREAM psStream, IMG_UINT32 ui32NewSize);
+PDBG_LASTFRAME_BUFFER FindLFBuf(PDBG_STREAM psStream);
+
+DBGKM_SERVICE_TABLE g_sDBGKMServices =
+{
+ sizeof (DBGKM_SERVICE_TABLE),
+ ExtDBGDrivCreateStream,
+ ExtDBGDrivDestroyStream,
+ ExtDBGDrivFindStream,
+ ExtDBGDrivWriteString,
+ ExtDBGDrivReadString,
+ ExtDBGDrivWrite,
+ ExtDBGDrivRead,
+ ExtDBGDrivSetCaptureMode,
+ ExtDBGDrivSetOutputMode,
+ ExtDBGDrivSetDebugLevel,
+ ExtDBGDrivSetFrame,
+ ExtDBGDrivGetFrame,
+ ExtDBGDrivOverrideMode,
+ ExtDBGDrivDefaultMode,
+ ExtDBGDrivWrite2,
+ ExtDBGDrivWriteStringCM,
+ ExtDBGDrivWriteCM,
+ ExtDBGDrivSetMarker,
+ ExtDBGDrivGetMarker,
+ ExtDBGDrivStartInitPhase,
+ ExtDBGDrivStopInitPhase,
+ ExtDBGDrivIsCaptureFrame,
+ ExtDBGDrivWriteLF,
+ ExtDBGDrivReadLF,
+ ExtDBGDrivGetStreamOffset,
+ ExtDBGDrivSetStreamOffset,
+ ExtDBGDrivIsLastCaptureFrame,
+ ExtDBGDrivWaitForEvent,
+ ExtDBGDrivSetConnectNotifier,
+ ExtDBGDrivWritePersist
+};
+
+
+static IMG_UINT32 DBGDrivWritePersist(PDBG_STREAM psMainStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+static IMG_VOID InvalidateAllStreams(IMG_VOID);
+
+
+
+
+DBGKM_CONNECT_NOTIFIER g_fnDBGKMNotifier;
+
+IMG_VOID IMG_CALLCONV ExtDBGDrivSetConnectNotifier(DBGKM_CONNECT_NOTIFIER fn_notifier)
+{
+
+ g_fnDBGKMNotifier = fn_notifier;
+}
+
+IMG_VOID * IMG_CALLCONV ExtDBGDrivCreateStream(IMG_CHAR * pszName, IMG_UINT32 ui32CapMode, IMG_UINT32 ui32OutMode, IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size)
+{
+ IMG_VOID * pvRet;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ pvRet=DBGDrivCreateStream(pszName, ui32CapMode, ui32OutMode, ui32Flags, ui32Size);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return pvRet;
+}
+
+void IMG_CALLCONV ExtDBGDrivDestroyStream(PDBG_STREAM psStream)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivDestroyStream(psStream);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+IMG_VOID * IMG_CALLCONV ExtDBGDrivFindStream(IMG_CHAR * pszName, IMG_BOOL bResetStream)
+{
+ IMG_VOID * pvRet;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ pvRet=DBGDrivFindStream(pszName, bResetStream);
+ if(g_fnDBGKMNotifier.pfnConnectNotifier)
+ {
+ g_fnDBGKMNotifier.pfnConnectNotifier();
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "pfnConnectNotifier not initialised.\n"));
+ }
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return pvRet;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level)
+{
+ IMG_UINT32 ui32Ret;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret=DBGDrivWriteString(psStream, pszString, ui32Level);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivReadString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Limit)
+{
+ IMG_UINT32 ui32Ret;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret=DBGDrivReadString(psStream, pszString, ui32Limit);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWrite(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
+{
+ IMG_UINT32 ui32Ret;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret=DBGDrivWrite(psStream, pui8InBuf, ui32InBuffSize, ui32Level);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivRead(PDBG_STREAM psStream, IMG_BOOL bReadInitBuffer, IMG_UINT32 ui32OutBuffSize,IMG_UINT8 * pui8OutBuf)
+{
+ IMG_UINT32 ui32Ret;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret=DBGDrivRead(psStream, bReadInitBuffer, ui32OutBuffSize, pui8OutBuf);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+void IMG_CALLCONV ExtDBGDrivSetCaptureMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode,IMG_UINT32 ui32Start,IMG_UINT32 ui32End,IMG_UINT32 ui32SampleRate)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivSetCaptureMode(psStream, ui32Mode, ui32Start, ui32End, ui32SampleRate);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+void IMG_CALLCONV ExtDBGDrivSetOutputMode(PDBG_STREAM psStream,IMG_UINT32 ui32OutMode)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivSetOutputMode(psStream, ui32OutMode);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+void IMG_CALLCONV ExtDBGDrivSetDebugLevel(PDBG_STREAM psStream,IMG_UINT32 ui32DebugLevel)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivSetDebugLevel(psStream, ui32DebugLevel);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+void IMG_CALLCONV ExtDBGDrivSetFrame(PDBG_STREAM psStream,IMG_UINT32 ui32Frame)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivSetFrame(psStream, ui32Frame);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetFrame(PDBG_STREAM psStream)
+{
+ IMG_UINT32 ui32Ret;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret=DBGDrivGetFrame(psStream);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+IMG_BOOL IMG_CALLCONV ExtDBGDrivIsLastCaptureFrame(PDBG_STREAM psStream)
+{
+ IMG_BOOL bRet;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ bRet = DBGDrivIsLastCaptureFrame(psStream);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return bRet;
+}
+
+IMG_BOOL IMG_CALLCONV ExtDBGDrivIsCaptureFrame(PDBG_STREAM psStream, IMG_BOOL bCheckPreviousFrame)
+{
+ IMG_BOOL bRet;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ bRet = DBGDrivIsCaptureFrame(psStream, bCheckPreviousFrame);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return bRet;
+}
+
+void IMG_CALLCONV ExtDBGDrivOverrideMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivOverrideMode(psStream, ui32Mode);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+void IMG_CALLCONV ExtDBGDrivDefaultMode(PDBG_STREAM psStream)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivDefaultMode(psStream);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWrite2(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
+{
+ IMG_UINT32 ui32Ret;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret=DBGDrivWrite2(psStream, pui8InBuf, ui32InBuffSize, ui32Level);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWritePersist(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
+{
+ IMG_UINT32 ui32Ret;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret=DBGDrivWritePersist(psStream, pui8InBuf, ui32InBuffSize, ui32Level);
+ if(ui32Ret==0xFFFFFFFFU)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "An error occurred in DBGDrivWritePersist."));
+ }
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteStringCM(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level)
+{
+ IMG_UINT32 ui32Ret;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret=DBGDrivWriteStringCM(psStream, pszString, ui32Level);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteCM(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
+{
+ IMG_UINT32 ui32Ret;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret=DBGDrivWriteCM(psStream, pui8InBuf, ui32InBuffSize, ui32Level);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+void IMG_CALLCONV ExtDBGDrivSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivSetMarker(psStream, ui32Marker);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetMarker(PDBG_STREAM psStream)
+{
+ IMG_UINT32 ui32Marker;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Marker = DBGDrivGetMarker(psStream);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Marker;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteLF(PDBG_STREAM psStream, IMG_UINT8 * pui8InBuf, IMG_UINT32 ui32InBuffSize, IMG_UINT32 ui32Level, IMG_UINT32 ui32Flags)
+{
+ IMG_UINT32 ui32Ret;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret = DBGDrivWriteLF(psStream, pui8InBuf, ui32InBuffSize, ui32Level, ui32Flags);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivReadLF(PDBG_STREAM psStream, IMG_UINT32 ui32OutBuffSize, IMG_UINT8 * pui8OutBuf)
+{
+ IMG_UINT32 ui32Ret;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret = DBGDrivReadLF(psStream, ui32OutBuffSize, pui8OutBuf);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+
+IMG_VOID IMG_CALLCONV ExtDBGDrivStartInitPhase(PDBG_STREAM psStream)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivStartInitPhase(psStream);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+IMG_VOID IMG_CALLCONV ExtDBGDrivStopInitPhase(PDBG_STREAM psStream)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivStopInitPhase(psStream);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetStreamOffset(PDBG_STREAM psStream)
+{
+ IMG_UINT32 ui32Ret;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret = DBGDrivGetStreamOffset(psStream);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+IMG_VOID IMG_CALLCONV ExtDBGDrivSetStreamOffset(PDBG_STREAM psStream, IMG_UINT32 ui32StreamOffset)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivSetStreamOffset(psStream, ui32StreamOffset);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+}
+
+IMG_VOID IMG_CALLCONV ExtDBGDrivWaitForEvent(DBG_EVENT eEvent)
+{
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+ DBGDrivWaitForEvent(eEvent);
+#else
+ PVR_UNREFERENCED_PARAMETER(eEvent);
+#endif
+}
+
+IMG_UINT32 AtoI(IMG_CHAR *szIn)
+{
+ IMG_INT iLen = 0;
+ IMG_UINT32 ui32Value = 0;
+ IMG_UINT32 ui32Digit=1;
+ IMG_UINT32 ui32Base=10;
+ IMG_INT iPos;
+ IMG_CHAR bc;
+
+
+ while (szIn[iLen] > 0)
+ {
+ iLen ++;
+ }
+
+
+ if (iLen == 0)
+ {
+ return (0);
+ }
+
+
+ iPos=0;
+ while (szIn[iPos] == '0')
+ {
+ iPos++;
+ }
+ if (szIn[iPos] == '\0')
+ {
+ return 0;
+ }
+ if (szIn[iPos] == 'x' || szIn[iPos] == 'X')
+ {
+ ui32Base=16;
+ szIn[iPos]='0';
+ }
+
+
+ for (iPos = iLen - 1; iPos >= 0; iPos --)
+ {
+ bc = szIn[iPos];
+
+ if ( (bc >= 'a') && (bc <= 'f') && ui32Base == 16)
+ {
+ bc -= 'a' - 0xa;
+ }
+ else
+ if ( (bc >= 'A') && (bc <= 'F') && ui32Base == 16)
+ {
+ bc -= 'A' - 0xa;
+ }
+ else
+ if ((bc >= '0') && (bc <= '9'))
+ {
+ bc -= '0';
+ }
+ else
+ return (0);
+
+ ui32Value += (IMG_UINT32)bc * ui32Digit;
+
+ ui32Digit = ui32Digit * ui32Base;
+ }
+ return (ui32Value);
+}
+
+
+static IMG_BOOL StreamValid(PDBG_STREAM psStream)
+{
+ PDBG_STREAM psThis;
+
+ psThis = g_psStreamList;
+
+ while (psThis)
+ {
+ if (psStream && (psThis == psStream) )
+ {
+ return(IMG_TRUE);
+ }
+ else
+ {
+ psThis = psThis->psNext;
+ }
+ }
+
+ return(IMG_FALSE);
+}
+
+
+static IMG_BOOL StreamValidForRead(PDBG_STREAM psStream)
+{
+ if( StreamValid(psStream) &&
+ ((psStream->psCtrl->ui32Flags & DEBUG_FLAGS_WRITEONLY) == 0) )
+ {
+ return(IMG_TRUE);
+ }
+
+ return(IMG_FALSE);
+}
+
+static IMG_BOOL StreamValidForWrite(PDBG_STREAM psStream)
+{
+ if( StreamValid(psStream) &&
+ ((psStream->psCtrl->ui32Flags & DEBUG_FLAGS_READONLY) == 0) )
+ {
+ return(IMG_TRUE);
+ }
+
+ return(IMG_FALSE);
+}
+
+
+static void Write(PDBG_STREAM psStream,IMG_PUINT8 pui8Data,IMG_UINT32 ui32InBuffSize)
+{
+
+
+ if (!psStream->bCircularAllowed)
+ {
+
+ }
+
+ if ((psStream->ui32WPtr + ui32InBuffSize) > psStream->ui32Size)
+ {
+
+ IMG_UINT32 ui32B1 = psStream->ui32Size - psStream->ui32WPtr;
+ IMG_UINT32 ui32B2 = ui32InBuffSize - ui32B1;
+
+
+ HostMemCopy((IMG_PVOID)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32WPtr),
+ (IMG_PVOID) pui8Data,
+ ui32B1);
+
+
+ HostMemCopy(psStream->pvBase,
+ (IMG_PVOID)(pui8Data + ui32B1),
+ ui32B2);
+
+
+ psStream->ui32WPtr = ui32B2;
+ }
+ else
+ {
+ HostMemCopy((IMG_PVOID)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32WPtr),
+ (IMG_PVOID) pui8Data,
+ ui32InBuffSize);
+
+ psStream->ui32WPtr += ui32InBuffSize;
+
+ if (psStream->ui32WPtr == psStream->ui32Size)
+ {
+ psStream->ui32WPtr = 0;
+ }
+ }
+ psStream->ui32DataWritten += ui32InBuffSize;
+}
+
+
+void MonoOut(IMG_CHAR * pszString,IMG_BOOL bNewLine)
+{
+#if defined (_WIN64)
+ PVR_UNREFERENCED_PARAMETER(pszString);
+ PVR_UNREFERENCED_PARAMETER(bNewLine);
+
+#else
+ IMG_UINT32 i;
+ IMG_CHAR * pScreen;
+
+ pScreen = (IMG_CHAR *) DBGDRIV_MONOBASE;
+
+ pScreen += g_ui32Line * 160;
+
+
+
+ i=0;
+ do
+ {
+ pScreen[g_ui32LOff + (i*2)] = pszString[i];
+ pScreen[g_ui32LOff + (i*2)+1] = 127;
+ i++;
+ }
+ while ((pszString[i] != 0) && (i < 4096));
+
+ g_ui32LOff += i * 2;
+
+ if (bNewLine)
+ {
+ g_ui32LOff = 0;
+ g_ui32Line++;
+ }
+
+
+
+ if (g_ui32Line == g_ui32MonoLines)
+ {
+ g_ui32Line = g_ui32MonoLines - 1;
+
+ HostMemCopy((IMG_VOID *)DBGDRIV_MONOBASE,(IMG_VOID *)(DBGDRIV_MONOBASE + 160),160 * (g_ui32MonoLines - 1));
+
+ HostMemSet((IMG_VOID *)(DBGDRIV_MONOBASE + (160 * (g_ui32MonoLines - 1))),0,160);
+ }
+#endif
+}
+
+static IMG_UINT32 WriteExpandingBuffer(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize)
+{
+ IMG_UINT ui32Space;
+
+
+
+ ui32Space = SpaceInStream(psStream);
+
+
+
+ if ((psStream->psCtrl->ui32OutMode & DEBUG_OUTMODE_STREAMENABLE) == 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "WriteExpandingBuffer: buffer %x is disabled", (IMG_UINTPTR_T) psStream));
+ return(0);
+ }
+
+
+
+ if (psStream->psCtrl->ui32Flags & DEBUG_FLAGS_NO_BUF_EXPANDSION)
+ {
+
+
+
+ if (ui32Space < 32)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "WriteExpandingBuffer: buffer %x is full and isn't expandable", (IMG_UINTPTR_T) psStream));
+ return(0);
+ }
+ }
+ else
+ {
+ if ((ui32Space < 32) || (ui32Space <= (ui32InBuffSize + 4)))
+ {
+ IMG_UINT32 ui32NewBufSize;
+
+
+
+ ui32NewBufSize = 2 * psStream->ui32Size;
+
+ PVR_DPF((PVR_DBGDRIV_MESSAGE, "Expanding buffer size = %x, new size = %x",
+ psStream->ui32Size, ui32NewBufSize));
+
+ if (ui32InBuffSize > psStream->ui32Size)
+ {
+ ui32NewBufSize += ui32InBuffSize;
+ }
+
+
+
+ if (!ExpandStreamBuffer(psStream,ui32NewBufSize))
+ {
+ if (ui32Space < 32)
+ {
+ if(psStream->bCircularAllowed)
+ {
+ return(0);
+ }
+ else
+ {
+
+ PVR_DPF((PVR_DBG_ERROR, "WriteExpandingBuffer: Unable to expand %x. Out of memory.", (IMG_UINTPTR_T) psStream));
+ InvalidateAllStreams();
+ return (0xFFFFFFFFUL);
+ }
+ }
+ }
+
+
+
+ ui32Space = SpaceInStream(psStream);
+ PVR_DPF((PVR_DBGDRIV_MESSAGE, "Expanded buffer, free space = %x",
+ ui32Space));
+ }
+ }
+
+
+
+ if (ui32Space <= (ui32InBuffSize + 4))
+ {
+ ui32InBuffSize = ui32Space - 4;
+ }
+
+
+
+ Write(psStream,pui8InBuf,ui32InBuffSize);
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+ if (ui32InBuffSize)
+ {
+ HostSignalEvent(DBG_EVENT_STREAM_DATA);
+ }
+#endif
+ return(ui32InBuffSize);
+}
+
+IMG_VOID * IMG_CALLCONV DBGDrivCreateStream(IMG_CHAR * pszName,
+ IMG_UINT32 ui32CapMode,
+ IMG_UINT32 ui32OutMode,
+ IMG_UINT32 ui32Flags,
+ IMG_UINT32 ui32Size)
+{
+ PDBG_STREAM psStream;
+ PDBG_STREAM psInitStream;
+ PDBG_LASTFRAME_BUFFER psLFBuffer;
+ PDBG_STREAM_CONTROL psCtrl;
+ IMG_UINT32 ui32Off;
+ IMG_VOID * pvBase;
+ static IMG_CHAR pszNameInitSuffix[] = "_Init";
+ IMG_UINT32 ui32OffSuffix;
+
+
+
+
+ psStream = (PDBG_STREAM) DBGDrivFindStream(pszName, IMG_FALSE);
+
+ if (psStream)
+ {
+ return ((IMG_VOID *) psStream);
+ }
+
+
+
+ psStream = HostNonPageablePageAlloc(1);
+ psInitStream = HostNonPageablePageAlloc(1);
+ psLFBuffer = HostNonPageablePageAlloc(1);
+ psCtrl = HostNonPageablePageAlloc(1);
+ if (
+ (!psStream) ||
+ (!psInitStream) ||
+ (!psLFBuffer) ||
+ (!psCtrl)
+ )
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DBGDriv: Couldn't alloc control structs\n\r"));
+ return((IMG_VOID *) 0);
+ }
+
+
+ if ((ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+ {
+ pvBase = HostNonPageablePageAlloc(ui32Size);
+ }
+ else
+ {
+ pvBase = HostPageablePageAlloc(ui32Size);
+ }
+
+ if (!pvBase)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DBGDriv: Couldn't alloc Stream buffer\n\r"));
+ HostNonPageablePageFree(psStream);
+ return((IMG_VOID *) 0);
+ }
+
+
+ psCtrl->ui32Flags = ui32Flags;
+ psCtrl->ui32CapMode = ui32CapMode;
+ psCtrl->ui32OutMode = ui32OutMode;
+ psCtrl->ui32DebugLevel = DEBUG_LEVEL_0;
+ psCtrl->ui32DefaultMode = ui32CapMode;
+ psCtrl->ui32Start = 0;
+ psCtrl->ui32End = 0;
+ psCtrl->ui32Current = 0;
+ psCtrl->ui32SampleRate = 1;
+ psCtrl->bInitPhaseComplete = IMG_FALSE;
+
+
+
+ psStream->psNext = 0;
+ psStream->pvBase = pvBase;
+ psStream->psCtrl = psCtrl;
+ psStream->ui32Size = ui32Size * 4096UL;
+ psStream->ui32RPtr = 0;
+ psStream->ui32WPtr = 0;
+ psStream->ui32DataWritten = 0;
+ psStream->ui32Marker = 0;
+ psStream->bCircularAllowed = IMG_TRUE;
+ psStream->ui32InitPhaseWOff = 0;
+
+
+
+
+ if ((ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+ {
+ pvBase = HostNonPageablePageAlloc(ui32Size);
+ }
+ else
+ {
+ pvBase = HostPageablePageAlloc(ui32Size);
+ }
+
+ if (!pvBase)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DBGDriv: Couldn't alloc InitStream buffer\n\r"));
+
+ if ((psStream->psCtrl->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+ {
+ HostNonPageablePageFree(psStream->pvBase);
+ }
+ else
+ {
+ HostPageablePageFree(psStream->pvBase);
+ }
+ HostNonPageablePageFree(psStream);
+ return((IMG_VOID *) 0);
+ }
+
+
+ psInitStream->psNext = 0;
+ psInitStream->pvBase = pvBase;
+ psInitStream->psCtrl = psCtrl;
+ psInitStream->ui32Size = ui32Size * 4096UL;
+ psInitStream->ui32RPtr = 0;
+ psInitStream->ui32WPtr = 0;
+ psInitStream->ui32DataWritten = 0;
+ psInitStream->ui32Marker = 0;
+ psInitStream->bCircularAllowed = IMG_FALSE;
+ psInitStream->ui32InitPhaseWOff = 0;
+
+
+
+ psStream->psInitStream = psInitStream;
+
+
+ psLFBuffer->psStream = psStream;
+ psLFBuffer->ui32BufLen = 0UL;
+
+ g_bHotkeyMiddump = IMG_FALSE;
+ g_ui32HotkeyMiddumpStart = 0xffffffffUL;
+ g_ui32HotkeyMiddumpEnd = 0xffffffffUL;
+
+
+
+ ui32Off = 0;
+
+ do
+ {
+ psStream->szName[ui32Off] = pszName[ui32Off];
+ psInitStream->szName[ui32Off] = pszName[ui32Off];
+ ui32Off++;
+ }
+ while ((pszName[ui32Off] != 0) && (ui32Off < (4096UL - sizeof(DBG_STREAM))));
+ psStream->szName[ui32Off] = pszName[ui32Off];
+
+
+
+ ui32OffSuffix = 0;
+ do
+ {
+ psInitStream->szName[ui32Off] = pszNameInitSuffix[ui32OffSuffix];
+ ui32Off++;
+ ui32OffSuffix++;
+ }
+ while ( (pszNameInitSuffix[ui32OffSuffix] != 0) &&
+ (ui32Off < (4096UL - sizeof(DBG_STREAM))));
+ psInitStream->szName[ui32Off] = pszNameInitSuffix[ui32OffSuffix];
+
+
+
+ psStream->psNext = g_psStreamList;
+ g_psStreamList = psStream;
+
+ psLFBuffer->psNext = g_psLFBufferList;
+ g_psLFBufferList = psLFBuffer;
+
+ AddSIDEntry(psStream);
+
+ return((IMG_VOID *) psStream);
+}
+
+void IMG_CALLCONV DBGDrivDestroyStream(PDBG_STREAM psStream)
+{
+ PDBG_STREAM psStreamThis;
+ PDBG_STREAM psStreamPrev;
+ PDBG_LASTFRAME_BUFFER psLFBuffer;
+ PDBG_LASTFRAME_BUFFER psLFThis;
+ PDBG_LASTFRAME_BUFFER psLFPrev;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "DBGDriv: Destroying stream %s\r\n", psStream->szName ));
+
+
+
+ if (!StreamValid(psStream))
+ {
+ return;
+ }
+
+ RemoveSIDEntry(psStream);
+
+ psLFBuffer = FindLFBuf(psStream);
+
+
+
+ psStreamThis = g_psStreamList;
+ psStreamPrev = 0;
+
+ while (psStreamThis)
+ {
+ if (psStreamThis == psStream)
+ {
+ if (psStreamPrev)
+ {
+ psStreamPrev->psNext = psStreamThis->psNext;
+ }
+ else
+ {
+ g_psStreamList = psStreamThis->psNext;
+ }
+
+ psStreamThis = 0;
+ }
+ else
+ {
+ psStreamPrev = psStreamThis;
+ psStreamThis = psStreamThis->psNext;
+ }
+ }
+
+ psLFThis = g_psLFBufferList;
+ psLFPrev = 0;
+
+ while (psLFThis)
+ {
+ if (psLFThis == psLFBuffer)
+ {
+ if (psLFPrev)
+ {
+ psLFPrev->psNext = psLFThis->psNext;
+ }
+ else
+ {
+ g_psLFBufferList = psLFThis->psNext;
+ }
+
+ psLFThis = 0;
+ }
+ else
+ {
+ psLFPrev = psLFThis;
+ psLFThis = psLFThis->psNext;
+ }
+ }
+
+
+ if (psStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_HOTKEY)
+ {
+ DeactivateHotKeys();
+ }
+
+
+
+ if ((psStream->psCtrl->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+ {
+ HostNonPageablePageFree(psStream->psCtrl);
+ HostNonPageablePageFree(psStream->pvBase);
+ HostNonPageablePageFree(psStream->psInitStream->pvBase);
+ }
+ else
+ {
+ HostNonPageablePageFree(psStream->psCtrl);
+ HostPageablePageFree(psStream->pvBase);
+ HostPageablePageFree(psStream->psInitStream->pvBase);
+ }
+
+ HostNonPageablePageFree(psStream->psInitStream);
+ HostNonPageablePageFree(psStream);
+ HostNonPageablePageFree(psLFBuffer);
+
+ if (g_psStreamList == 0)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"DBGDriv: Stream list now empty" ));
+ }
+
+ return;
+}
+
+IMG_VOID * IMG_CALLCONV DBGDrivFindStream(IMG_CHAR * pszName, IMG_BOOL bResetStream)
+{
+ PDBG_STREAM psStream;
+ PDBG_STREAM psThis;
+ IMG_UINT32 ui32Off;
+ IMG_BOOL bAreSame;
+
+ psStream = 0;
+
+ PVR_DPF((PVR_DBGDRIV_MESSAGE, "PDump client connecting to %s %s",
+ pszName,
+ (bResetStream == IMG_TRUE) ? "with reset" : "no reset"));
+
+
+
+ for (psThis = g_psStreamList; psThis != IMG_NULL; psThis = psThis->psNext)
+ {
+ bAreSame = IMG_TRUE;
+ ui32Off = 0;
+
+ if (strlen(psThis->szName) == strlen(pszName))
+ {
+ while ((psThis->szName[ui32Off] != 0) && (pszName[ui32Off] != 0) && (ui32Off < 128) && bAreSame)
+ {
+ if (psThis->szName[ui32Off] != pszName[ui32Off])
+ {
+ bAreSame = IMG_FALSE;
+ }
+
+ ui32Off++;
+ }
+ }
+ else
+ {
+ bAreSame = IMG_FALSE;
+ }
+
+ if (bAreSame)
+ {
+ psStream = psThis;
+ break;
+ }
+ }
+
+ if(bResetStream && psStream)
+ {
+ static IMG_CHAR szComment[] = "-- Init phase terminated\r\n";
+ psStream->psInitStream->ui32RPtr = 0;
+ psStream->ui32RPtr = 0;
+ psStream->ui32WPtr = 0;
+ psStream->ui32DataWritten = psStream->psInitStream->ui32DataWritten;
+ if (psStream->psCtrl->bInitPhaseComplete == IMG_FALSE)
+ {
+ if (psStream->psCtrl->ui32Flags & DEBUG_FLAGS_TEXTSTREAM)
+ {
+ DBGDrivWrite2(psStream, (IMG_UINT8 *)szComment, sizeof(szComment) - 1, 0x01);
+ }
+ psStream->psCtrl->bInitPhaseComplete = IMG_TRUE;
+ }
+
+ {
+
+
+ psStream->psInitStream->ui32InitPhaseWOff = psStream->psInitStream->ui32WPtr;
+ PVR_DPF((PVR_DBGDRIV_MESSAGE, "Set %s client marker bo %x, total bw %x",
+ psStream->szName,
+ psStream->psInitStream->ui32InitPhaseWOff,
+ psStream->psInitStream->ui32DataWritten ));
+ }
+ }
+
+ return((IMG_VOID *) psStream);
+}
+
+static void IMG_CALLCONV DBGDrivInvalidateStream(PDBG_STREAM psStream)
+{
+ IMG_CHAR pszErrorMsg[] = "**OUTOFMEM\n";
+ IMG_UINT32 ui32Space;
+ IMG_UINT32 ui32Off = 0;
+ IMG_UINT32 ui32WPtr = psStream->ui32WPtr;
+ IMG_PUINT8 pui8Buffer = (IMG_UINT8 *) psStream->pvBase;
+
+ PVR_DPF((PVR_DBG_ERROR, "DBGDrivInvalidateStream: An error occurred for stream %s\r\n", psStream->szName ));
+
+
+
+
+
+
+
+
+
+ ui32Space = SpaceInStream(psStream);
+
+
+ if(ui32Space > 0)
+ {
+ ui32Space--;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DBGDrivInvalidateStream: Buffer full."));
+ }
+
+ while((pszErrorMsg[ui32Off] != 0) && (ui32Off < ui32Space))
+ {
+ pui8Buffer[ui32WPtr] = (IMG_UINT8)pszErrorMsg[ui32Off];
+ ui32Off++;
+ ui32WPtr++;
+ }
+ pui8Buffer[ui32WPtr++] = '\0';
+ psStream->ui32WPtr = ui32WPtr;
+
+
+ psStream->psCtrl->ui32Flags |= DEBUG_FLAGS_READONLY;
+}
+
+static IMG_VOID InvalidateAllStreams(IMG_VOID)
+{
+ PDBG_STREAM psStream = g_psStreamList;
+ while (psStream != IMG_NULL)
+ {
+ DBGDrivInvalidateStream(psStream);
+ psStream = psStream->psNext;
+ }
+ return;
+}
+
+
+
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteStringCM(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level)
+{
+
+
+ if (!StreamValidForWrite(psStream))
+ {
+ return(0xFFFFFFFFUL);
+ }
+
+
+
+ if (psStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_FRAMED)
+ {
+ if ((psStream->psCtrl->ui32Flags & DEBUG_FLAGS_ENABLESAMPLE) == 0)
+ {
+ return(0);
+ }
+ }
+ else
+ {
+ if (psStream->psCtrl->ui32CapMode == DEBUG_CAPMODE_HOTKEY)
+ {
+ if ((psStream->psCtrl->ui32Current != g_ui32HotKeyFrame) || (g_bHotKeyPressed == IMG_FALSE))
+ {
+ return(0);
+ }
+ }
+ }
+
+ return(DBGDrivWriteString(psStream,pszString,ui32Level));
+
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level)
+{
+ IMG_UINT32 ui32Len;
+ IMG_UINT32 ui32Space;
+ IMG_UINT32 ui32WPtr;
+ IMG_UINT8 * pui8Buffer;
+
+
+
+ if (!StreamValidForWrite(psStream))
+ {
+ return(0xFFFFFFFFUL);
+ }
+
+
+
+ if ((psStream->psCtrl->ui32DebugLevel & ui32Level) == 0)
+ {
+ return(0xFFFFFFFFUL);
+ }
+
+
+
+
+ if ((psStream->psCtrl->ui32OutMode & DEBUG_OUTMODE_ASYNC) == 0)
+ {
+ if (psStream->psCtrl->ui32OutMode & DEBUG_OUTMODE_STANDARDDBG)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"%s: %s\r\n",psStream->szName, pszString));
+ }
+
+
+
+ if (psStream->psCtrl->ui32OutMode & DEBUG_OUTMODE_MONO)
+ {
+ MonoOut(psStream->szName,IMG_FALSE);
+ MonoOut(": ",IMG_FALSE);
+ MonoOut(pszString,IMG_TRUE);
+ }
+ }
+
+
+
+ if (
+ !(
+ ((psStream->psCtrl->ui32OutMode & DEBUG_OUTMODE_STREAMENABLE) != 0) ||
+ ((psStream->psCtrl->ui32OutMode & DEBUG_OUTMODE_ASYNC) != 0)
+ )
+ )
+ {
+ return(0xFFFFFFFFUL);
+ }
+
+
+
+ ui32Space=SpaceInStream(psStream);
+
+
+ if(ui32Space > 0)
+ {
+ ui32Space--;
+ }
+
+ ui32Len = 0;
+ ui32WPtr = psStream->ui32WPtr;
+ pui8Buffer = (IMG_UINT8 *) psStream->pvBase;
+
+ while((pszString[ui32Len] != 0) && (ui32Len < ui32Space))
+ {
+ pui8Buffer[ui32WPtr] = (IMG_UINT8)pszString[ui32Len];
+ ui32Len++;
+ ui32WPtr++;
+ if (ui32WPtr == psStream->ui32Size)
+ {
+ ui32WPtr = 0;
+ }
+ }
+
+ if (ui32Len < ui32Space)
+ {
+
+ pui8Buffer[ui32WPtr] = (IMG_UINT8)pszString[ui32Len];
+ ui32Len++;
+ ui32WPtr++;
+ if (ui32WPtr == psStream->ui32Size)
+ {
+ ui32WPtr = 0;
+ }
+
+
+ psStream->ui32WPtr = ui32WPtr;
+ psStream->ui32DataWritten+= ui32Len;
+ } else
+ {
+ ui32Len = 0;
+ }
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+ if (ui32Len)
+ {
+ HostSignalEvent(DBG_EVENT_STREAM_DATA);
+ }
+#endif
+
+ return(ui32Len);
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivReadString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Limit)
+{
+ IMG_UINT32 ui32OutLen;
+ IMG_UINT32 ui32Len;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT8 *pui8Buff;
+
+
+
+ if (!StreamValidForRead(psStream))
+ {
+ return(0);
+ }
+
+
+
+ pui8Buff = (IMG_UINT8 *)psStream->pvBase;
+ ui32Offset = psStream->ui32RPtr;
+
+ if (psStream->ui32RPtr == psStream->ui32WPtr)
+ {
+ return(0);
+ }
+
+
+
+ ui32Len = 0;
+ while((pui8Buff[ui32Offset] != 0) && (ui32Offset != psStream->ui32WPtr))
+ {
+ ui32Offset++;
+ ui32Len++;
+
+
+
+ if (ui32Offset == psStream->ui32Size)
+ {
+ ui32Offset = 0;
+ }
+ }
+
+ ui32OutLen = ui32Len + 1;
+
+
+
+ if (ui32Len > ui32Limit)
+ {
+ return(0);
+ }
+
+
+
+ ui32Offset = psStream->ui32RPtr;
+ ui32Len = 0;
+
+ while ((pui8Buff[ui32Offset] != 0) && (ui32Len < ui32Limit))
+ {
+ pszString[ui32Len] = (IMG_CHAR)pui8Buff[ui32Offset];
+ ui32Offset++;
+ ui32Len++;
+
+
+
+ if (ui32Offset == psStream->ui32Size)
+ {
+ ui32Offset = 0;
+ }
+ }
+
+ pszString[ui32Len] = (IMG_CHAR)pui8Buff[ui32Offset];
+
+ psStream->ui32RPtr = ui32Offset + 1;
+
+ if (psStream->ui32RPtr == psStream->ui32Size)
+ {
+ psStream->ui32RPtr = 0;
+ }
+
+ return(ui32OutLen);
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivWrite(PDBG_STREAM psMainStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
+{
+ IMG_UINT32 ui32Space;
+ DBG_STREAM *psStream;
+
+
+
+ if (!StreamValidForWrite(psMainStream))
+ {
+ return(0xFFFFFFFFUL);
+ }
+
+
+
+ if ((psMainStream->psCtrl->ui32DebugLevel & ui32Level) == 0)
+ {
+ return(0xFFFFFFFFUL);
+ }
+
+
+
+ if (psMainStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_FRAMED)
+ {
+ if ((psMainStream->psCtrl->ui32Flags & DEBUG_FLAGS_ENABLESAMPLE) == 0)
+ {
+
+ return(ui32InBuffSize);
+ }
+ }
+ else if (psMainStream->psCtrl->ui32CapMode == DEBUG_CAPMODE_HOTKEY)
+ {
+ if ((psMainStream->psCtrl->ui32Current != g_ui32HotKeyFrame) || (g_bHotKeyPressed == IMG_FALSE))
+ {
+
+ return(ui32InBuffSize);
+ }
+ }
+
+ if(psMainStream->psCtrl->bInitPhaseComplete)
+ {
+ psStream = psMainStream;
+ }
+ else
+ {
+ psStream = psMainStream->psInitStream;
+ }
+
+
+
+ ui32Space=SpaceInStream(psStream);
+
+ PVR_DPF((PVR_DBGDRIV_MESSAGE, "Recv %d b for %s: Roff = %x, WOff = %x",
+ ui32InBuffSize,
+ psStream->szName,
+ psStream->ui32RPtr,
+ psStream->ui32WPtr));
+
+
+
+ if ((psStream->psCtrl->ui32OutMode & DEBUG_OUTMODE_STREAMENABLE) == 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DBGDrivWrite: buffer %x is disabled", (IMG_UINTPTR_T) psStream));
+ return(0);
+ }
+
+ if (ui32Space < 8)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DBGDrivWrite: buffer %x is full", (IMG_UINTPTR_T) psStream));
+ return(0);
+ }
+
+
+
+ if (ui32Space <= (ui32InBuffSize + 4))
+ {
+ ui32InBuffSize = ui32Space - 8;
+ }
+
+
+
+ Write(psStream,(IMG_UINT8 *) &ui32InBuffSize,4);
+ Write(psStream,pui8InBuf,ui32InBuffSize);
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+ if (ui32InBuffSize)
+ {
+ HostSignalEvent(DBG_EVENT_STREAM_DATA);
+ }
+#endif
+ return(ui32InBuffSize);
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteCM(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
+{
+
+
+ if (!StreamValidForWrite(psStream))
+ {
+ return(0xFFFFFFFFUL);
+ }
+
+
+
+ if (psStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_FRAMED)
+ {
+ if ((psStream->psCtrl->ui32Flags & DEBUG_FLAGS_ENABLESAMPLE) == 0)
+ {
+
+ return(ui32InBuffSize);
+ }
+ }
+ else
+ {
+ if (psStream->psCtrl->ui32CapMode == DEBUG_CAPMODE_HOTKEY)
+ {
+ if ((psStream->psCtrl->ui32Current != g_ui32HotKeyFrame) || (g_bHotKeyPressed == IMG_FALSE))
+ {
+
+ return(ui32InBuffSize);
+ }
+ }
+ }
+
+ return(DBGDrivWrite2(psStream,pui8InBuf,ui32InBuffSize,ui32Level));
+}
+
+
+static IMG_UINT32 DBGDrivWritePersist(PDBG_STREAM psMainStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
+{
+ DBG_STREAM *psStream;
+ PVR_UNREFERENCED_PARAMETER(ui32Level);
+
+
+
+ if (!StreamValidForWrite(psMainStream))
+ {
+ return(0xFFFFFFFFUL);
+ }
+
+
+ psStream = psMainStream->psInitStream;
+ if(psStream->bCircularAllowed == IMG_TRUE)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "DBGDrivWritePersist: Init phase is a circular buffer, some data may be lost"));
+ }
+
+ PVR_DPF((PVR_DBGDRIV_MESSAGE, "Append %x b to %s: Roff = %x, WOff = %x [bw = %x]",
+ ui32InBuffSize,
+ psStream->szName,
+ psStream->ui32RPtr,
+ psStream->ui32WPtr,
+ psStream->ui32DataWritten));
+
+ return( WriteExpandingBuffer(psStream, pui8InBuf, ui32InBuffSize) );
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivWrite2(PDBG_STREAM psMainStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
+{
+ DBG_STREAM *psStream;
+
+
+
+ if (!StreamValidForWrite(psMainStream))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DBGDrivWrite2: stream not valid"));
+ return(0xFFFFFFFFUL);
+ }
+
+
+
+ if ((psMainStream->psCtrl->ui32DebugLevel & ui32Level) == 0)
+ {
+ return(0);
+ }
+
+ if(psMainStream->psCtrl->bInitPhaseComplete)
+ {
+ psStream = psMainStream;
+ }
+ else
+ {
+ psStream = psMainStream->psInitStream;
+ }
+
+ PVR_DPF((PVR_DBGDRIV_MESSAGE, "Recv(exp) %d b for %s: Roff = %x, WOff = %x",
+ ui32InBuffSize,
+ psStream->szName,
+ psStream->ui32RPtr,
+ psStream->ui32WPtr));
+
+ return( WriteExpandingBuffer(psStream, pui8InBuf, ui32InBuffSize) );
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivRead(PDBG_STREAM psMainStream, IMG_BOOL bReadInitBuffer, IMG_UINT32 ui32OutBuffSize,IMG_UINT8 * pui8OutBuf)
+{
+ IMG_UINT32 ui32Data;
+ DBG_STREAM *psStream;
+
+
+
+ if (!StreamValidForRead(psMainStream))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DBGDrivRead: buffer %x is invalid", (IMG_UINTPTR_T) psMainStream));
+ return(0);
+ }
+
+ if(bReadInitBuffer)
+ {
+ psStream = psMainStream->psInitStream;
+ }
+ else
+ {
+ psStream = psMainStream;
+ }
+
+
+ if (psStream->ui32RPtr == psStream->ui32WPtr ||
+ ((psStream->ui32InitPhaseWOff > 0) &&
+ (psStream->ui32RPtr >= psStream->ui32InitPhaseWOff)) )
+ {
+ return(0);
+ }
+
+
+
+ if (psStream->ui32RPtr <= psStream->ui32WPtr)
+ {
+ ui32Data = psStream->ui32WPtr - psStream->ui32RPtr;
+ }
+ else
+ {
+ ui32Data = psStream->ui32WPtr + (psStream->ui32Size - psStream->ui32RPtr);
+ }
+
+
+
+ if ((psStream->ui32InitPhaseWOff > 0) &&
+ (psStream->ui32InitPhaseWOff < psStream->ui32WPtr))
+ {
+ ui32Data = psStream->ui32InitPhaseWOff - psStream->ui32RPtr;
+ }
+
+
+
+ if (ui32Data > ui32OutBuffSize)
+ {
+ ui32Data = ui32OutBuffSize;
+ }
+
+ PVR_DPF((PVR_DBGDRIV_MESSAGE, "Send %x b from %s: Roff = %x, WOff = %x",
+ ui32Data,
+ psStream->szName,
+ psStream->ui32RPtr,
+ psStream->ui32WPtr));
+
+
+
+ if ((psStream->ui32RPtr + ui32Data) > psStream->ui32Size)
+ {
+ IMG_UINT32 ui32B1 = psStream->ui32Size - psStream->ui32RPtr;
+ IMG_UINT32 ui32B2 = ui32Data - ui32B1;
+
+
+ HostMemCopy((IMG_VOID *) pui8OutBuf,
+ (IMG_VOID *)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32RPtr),
+ ui32B1);
+
+
+ HostMemCopy((IMG_VOID *)(pui8OutBuf + ui32B1),
+ psStream->pvBase,
+ ui32B2);
+
+
+ psStream->ui32RPtr = ui32B2;
+ }
+ else
+ {
+ HostMemCopy((IMG_VOID *) pui8OutBuf,
+ (IMG_VOID *)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32RPtr),
+ ui32Data);
+
+
+ psStream->ui32RPtr += ui32Data;
+
+
+ if (psStream->ui32RPtr == psStream->ui32Size)
+ {
+ psStream->ui32RPtr = 0;
+ }
+ }
+
+ return(ui32Data);
+}
+
+void IMG_CALLCONV DBGDrivSetCaptureMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode,IMG_UINT32 ui32Start,IMG_UINT32 ui32End,IMG_UINT32 ui32SampleRate)
+{
+
+
+ if (!StreamValid(psStream))
+ {
+ return;
+ }
+
+ psStream->psCtrl->ui32CapMode = ui32Mode;
+ psStream->psCtrl->ui32DefaultMode = ui32Mode;
+ psStream->psCtrl->ui32Start = ui32Start;
+ psStream->psCtrl->ui32End = ui32End;
+ psStream->psCtrl->ui32SampleRate = ui32SampleRate;
+
+
+
+ if (psStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_HOTKEY)
+ {
+ ActivateHotKeys(psStream);
+ }
+}
+
+void IMG_CALLCONV DBGDrivSetOutputMode(PDBG_STREAM psStream,IMG_UINT32 ui32OutMode)
+{
+
+
+ if (!StreamValid(psStream))
+ {
+ return;
+ }
+
+ psStream->psCtrl->ui32OutMode = ui32OutMode;
+}
+
+void IMG_CALLCONV DBGDrivSetDebugLevel(PDBG_STREAM psStream,IMG_UINT32 ui32DebugLevel)
+{
+
+
+ if (!StreamValid(psStream))
+ {
+ return;
+ }
+
+ psStream->psCtrl->ui32DebugLevel = ui32DebugLevel;
+}
+
+void IMG_CALLCONV DBGDrivSetFrame(PDBG_STREAM psStream,IMG_UINT32 ui32Frame)
+{
+
+
+ if (!StreamValid(psStream))
+ {
+ return;
+ }
+
+ psStream->psCtrl->ui32Current = ui32Frame;
+
+ if ((ui32Frame >= psStream->psCtrl->ui32Start) &&
+ (ui32Frame <= psStream->psCtrl->ui32End) &&
+ (((ui32Frame - psStream->psCtrl->ui32Start) % psStream->psCtrl->ui32SampleRate) == 0))
+ {
+ psStream->psCtrl->ui32Flags |= DEBUG_FLAGS_ENABLESAMPLE;
+ }
+ else
+ {
+ psStream->psCtrl->ui32Flags &= ~DEBUG_FLAGS_ENABLESAMPLE;
+ }
+
+ if (g_bHotkeyMiddump)
+ {
+ if ((ui32Frame >= g_ui32HotkeyMiddumpStart) &&
+ (ui32Frame <= g_ui32HotkeyMiddumpEnd) &&
+ (((ui32Frame - g_ui32HotkeyMiddumpStart) % psStream->psCtrl->ui32SampleRate) == 0))
+ {
+ psStream->psCtrl->ui32Flags |= DEBUG_FLAGS_ENABLESAMPLE;
+ }
+ else
+ {
+ psStream->psCtrl->ui32Flags &= ~DEBUG_FLAGS_ENABLESAMPLE;
+ if (psStream->psCtrl->ui32Current > g_ui32HotkeyMiddumpEnd)
+ {
+ g_bHotkeyMiddump = IMG_FALSE;
+ }
+ }
+ }
+
+
+ if (g_bHotKeyRegistered)
+ {
+ g_bHotKeyRegistered = IMG_FALSE;
+
+ PVR_DPF((PVR_DBG_MESSAGE,"Hotkey pressed (%p)!\n",psStream));
+
+ if (!g_bHotKeyPressed)
+ {
+
+
+ g_ui32HotKeyFrame = psStream->psCtrl->ui32Current + 2;
+
+
+
+ g_bHotKeyPressed = IMG_TRUE;
+ }
+
+
+
+ if (((psStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_FRAMED) != 0) &&
+ ((psStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_HOTKEY) != 0))
+ {
+ if (!g_bHotkeyMiddump)
+ {
+
+ g_ui32HotkeyMiddumpStart = g_ui32HotKeyFrame + 1;
+ g_ui32HotkeyMiddumpEnd = 0xffffffff;
+ g_bHotkeyMiddump = IMG_TRUE;
+ PVR_DPF((PVR_DBG_MESSAGE,"Sampling every %d frame(s)\n", psStream->psCtrl->ui32SampleRate));
+ }
+ else
+ {
+
+ g_ui32HotkeyMiddumpEnd = g_ui32HotKeyFrame;
+ PVR_DPF((PVR_DBG_MESSAGE,"Turning off sampling\n"));
+ }
+ }
+
+ }
+
+
+
+ if (psStream->psCtrl->ui32Current > g_ui32HotKeyFrame)
+ {
+ g_bHotKeyPressed = IMG_FALSE;
+ }
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivGetFrame(PDBG_STREAM psStream)
+{
+
+
+ if (!StreamValid(psStream))
+ {
+ return(0);
+ }
+
+ return(psStream->psCtrl->ui32Current);
+}
+
+IMG_BOOL IMG_CALLCONV DBGDrivIsLastCaptureFrame(PDBG_STREAM psStream)
+{
+ IMG_UINT32 ui32NextFrame;
+
+
+
+ if (!StreamValid(psStream))
+ {
+ return IMG_FALSE;
+ }
+
+ if (psStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_FRAMED)
+ {
+ ui32NextFrame = psStream->psCtrl->ui32Current + psStream->psCtrl->ui32SampleRate;
+ if (ui32NextFrame > psStream->psCtrl->ui32End)
+ {
+ return IMG_TRUE;
+ }
+ }
+ return IMG_FALSE;
+}
+
+IMG_BOOL IMG_CALLCONV DBGDrivIsCaptureFrame(PDBG_STREAM psStream, IMG_BOOL bCheckPreviousFrame)
+{
+ IMG_UINT32 ui32FrameShift = bCheckPreviousFrame ? 1UL : 0UL;
+
+
+
+ if (!StreamValid(psStream))
+ {
+ return IMG_FALSE;
+ }
+
+ if (psStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_FRAMED)
+ {
+
+ if (g_bHotkeyMiddump)
+ {
+ if ((psStream->psCtrl->ui32Current >= (g_ui32HotkeyMiddumpStart - ui32FrameShift)) &&
+ (psStream->psCtrl->ui32Current <= (g_ui32HotkeyMiddumpEnd - ui32FrameShift)) &&
+ ((((psStream->psCtrl->ui32Current + ui32FrameShift) - g_ui32HotkeyMiddumpStart) % psStream->psCtrl->ui32SampleRate) == 0))
+ {
+ return IMG_TRUE;
+ }
+ }
+ else
+ {
+ if ((psStream->psCtrl->ui32Current >= (psStream->psCtrl->ui32Start - ui32FrameShift)) &&
+ (psStream->psCtrl->ui32Current <= (psStream->psCtrl->ui32End - ui32FrameShift)) &&
+ ((((psStream->psCtrl->ui32Current + ui32FrameShift) - psStream->psCtrl->ui32Start) % psStream->psCtrl->ui32SampleRate) == 0))
+ {
+ return IMG_TRUE;
+ }
+ }
+ }
+ else if (psStream->psCtrl->ui32CapMode == DEBUG_CAPMODE_HOTKEY)
+ {
+ if ((psStream->psCtrl->ui32Current == (g_ui32HotKeyFrame-ui32FrameShift)) && (g_bHotKeyPressed))
+ {
+ return IMG_TRUE;
+ }
+ }
+ return IMG_FALSE;
+}
+
+void IMG_CALLCONV DBGDrivOverrideMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode)
+{
+
+
+ if (!StreamValid(psStream))
+ {
+ return;
+ }
+
+ psStream->psCtrl->ui32CapMode = ui32Mode;
+}
+
+void IMG_CALLCONV DBGDrivDefaultMode(PDBG_STREAM psStream)
+{
+
+
+ if (!StreamValid(psStream))
+ {
+ return;
+ }
+
+ psStream->psCtrl->ui32CapMode = psStream->psCtrl->ui32DefaultMode;
+}
+
+IMG_VOID IMG_CALLCONV DBGDrivSetClientMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker)
+{
+
+
+ if (!StreamValid(psStream))
+ {
+ return;
+ }
+
+ psStream->ui32InitPhaseWOff = ui32Marker;
+}
+
+void IMG_CALLCONV DBGDrivSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker)
+{
+
+
+ if (!StreamValid(psStream))
+ {
+ return;
+ }
+
+ psStream->ui32Marker = ui32Marker;
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivGetMarker(PDBG_STREAM psStream)
+{
+
+
+ if (!StreamValid(psStream))
+ {
+ return 0;
+ }
+
+ return psStream->ui32Marker;
+}
+
+
+IMG_UINT32 IMG_CALLCONV DBGDrivGetStreamOffset(PDBG_STREAM psMainStream)
+{
+ PDBG_STREAM psStream;
+
+
+
+ if (!StreamValid(psMainStream))
+ {
+ return 0;
+ }
+
+ if(psMainStream->psCtrl->bInitPhaseComplete)
+ {
+ psStream = psMainStream;
+ }
+ else
+ {
+ psStream = psMainStream->psInitStream;
+ }
+
+ return psStream->ui32DataWritten;
+}
+
+IMG_VOID IMG_CALLCONV DBGDrivSetStreamOffset(PDBG_STREAM psMainStream, IMG_UINT32 ui32StreamOffset)
+{
+ PDBG_STREAM psStream;
+
+
+
+ if (!StreamValid(psMainStream))
+ {
+ return;
+ }
+
+ if(psMainStream->psCtrl->bInitPhaseComplete)
+ {
+ psStream = psMainStream;
+ }
+ else
+ {
+ psStream = psMainStream->psInitStream;
+ }
+
+ PVR_DPF((PVR_DBGDRIV_MESSAGE, "DBGDrivSetStreamOffset: %s set to %x b",
+ psStream->szName,
+ ui32StreamOffset));
+ psStream->ui32DataWritten = ui32StreamOffset;
+}
+
+IMG_PVOID IMG_CALLCONV DBGDrivGetServiceTable(IMG_VOID)
+{
+ return((IMG_PVOID)&g_sDBGKMServices);
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteLF(PDBG_STREAM psStream, IMG_UINT8 * pui8InBuf, IMG_UINT32 ui32InBuffSize, IMG_UINT32 ui32Level, IMG_UINT32 ui32Flags)
+{
+ PDBG_LASTFRAME_BUFFER psLFBuffer;
+
+
+
+ if (!StreamValidForWrite(psStream))
+ {
+ return(0xFFFFFFFFUL);
+ }
+
+
+
+ if ((psStream->psCtrl->ui32DebugLevel & ui32Level) == 0)
+ {
+ return(0xFFFFFFFFUL);
+ }
+
+
+
+ if ((psStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_FRAMED) != 0)
+ {
+ if ((psStream->psCtrl->ui32Flags & DEBUG_FLAGS_ENABLESAMPLE) == 0)
+ {
+
+ return(ui32InBuffSize);
+ }
+ }
+ else if (psStream->psCtrl->ui32CapMode == DEBUG_CAPMODE_HOTKEY)
+ {
+ if ((psStream->psCtrl->ui32Current != g_ui32HotKeyFrame) || (g_bHotKeyPressed == IMG_FALSE))
+ {
+
+ return(ui32InBuffSize);
+ }
+ }
+
+ psLFBuffer = FindLFBuf(psStream);
+
+ if (ui32Flags & WRITELF_FLAGS_RESETBUF)
+ {
+
+
+ ui32InBuffSize = (ui32InBuffSize > LAST_FRAME_BUF_SIZE) ? LAST_FRAME_BUF_SIZE : ui32InBuffSize;
+ HostMemCopy((IMG_VOID *)psLFBuffer->ui8Buffer, (IMG_VOID *)pui8InBuf, ui32InBuffSize);
+ psLFBuffer->ui32BufLen = ui32InBuffSize;
+ }
+ else
+ {
+
+
+ ui32InBuffSize = ((psLFBuffer->ui32BufLen + ui32InBuffSize) > LAST_FRAME_BUF_SIZE) ? (LAST_FRAME_BUF_SIZE - psLFBuffer->ui32BufLen) : ui32InBuffSize;
+ HostMemCopy((IMG_VOID *)(&psLFBuffer->ui8Buffer[psLFBuffer->ui32BufLen]), (IMG_VOID *)pui8InBuf, ui32InBuffSize);
+ psLFBuffer->ui32BufLen += ui32InBuffSize;
+ }
+
+ return(ui32InBuffSize);
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivReadLF(PDBG_STREAM psStream, IMG_UINT32 ui32OutBuffSize, IMG_UINT8 * pui8OutBuf)
+{
+ PDBG_LASTFRAME_BUFFER psLFBuffer;
+ IMG_UINT32 ui32Data;
+
+
+
+ if (!StreamValidForRead(psStream))
+ {
+ return(0);
+ }
+
+ psLFBuffer = FindLFBuf(psStream);
+
+
+
+ ui32Data = (ui32OutBuffSize < psLFBuffer->ui32BufLen) ? ui32OutBuffSize : psLFBuffer->ui32BufLen;
+
+
+
+ HostMemCopy((IMG_VOID *)pui8OutBuf, (IMG_VOID *)psLFBuffer->ui8Buffer, ui32Data);
+
+ return ui32Data;
+}
+
+IMG_VOID IMG_CALLCONV DBGDrivStartInitPhase(PDBG_STREAM psStream)
+{
+ psStream->psCtrl->bInitPhaseComplete = IMG_FALSE;
+}
+
+IMG_VOID IMG_CALLCONV DBGDrivStopInitPhase(PDBG_STREAM psStream)
+{
+ psStream->psCtrl->bInitPhaseComplete = IMG_TRUE;
+}
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+IMG_VOID IMG_CALLCONV DBGDrivWaitForEvent(DBG_EVENT eEvent)
+{
+ HostWaitForEvent(eEvent);
+}
+#endif
+
+IMG_BOOL ExpandStreamBuffer(PDBG_STREAM psStream, IMG_UINT32 ui32NewSize)
+{
+ IMG_VOID * pvNewBuf;
+ IMG_UINT32 ui32NewSizeInPages;
+ IMG_UINT32 ui32NewWOffset;
+ IMG_UINT32 ui32NewROffset;
+ IMG_UINT32 ui32SpaceInOldBuf;
+
+
+
+ if (psStream->ui32Size >= ui32NewSize)
+ {
+ return IMG_FALSE;
+ }
+
+
+
+ ui32SpaceInOldBuf = SpaceInStream(psStream);
+
+
+
+ ui32NewSizeInPages = ((ui32NewSize + 0xfffUL) & ~0xfffUL) / 4096UL;
+
+ if ((psStream->psCtrl->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+ {
+ pvNewBuf = HostNonPageablePageAlloc(ui32NewSizeInPages);
+ }
+ else
+ {
+ pvNewBuf = HostPageablePageAlloc(ui32NewSizeInPages);
+ }
+
+ if (pvNewBuf == IMG_NULL)
+ {
+ return IMG_FALSE;
+ }
+
+ if(psStream->bCircularAllowed)
+ {
+
+
+
+ if (psStream->ui32RPtr <= psStream->ui32WPtr)
+ {
+
+
+ HostMemCopy(pvNewBuf,
+ (IMG_VOID *)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32RPtr),
+ psStream->ui32WPtr - psStream->ui32RPtr);
+ }
+ else
+ {
+ IMG_UINT32 ui32FirstCopySize;
+
+
+
+ ui32FirstCopySize = psStream->ui32Size - psStream->ui32RPtr;
+
+ HostMemCopy(pvNewBuf,
+ (IMG_VOID *)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32RPtr),
+ ui32FirstCopySize);
+
+
+
+ HostMemCopy((IMG_VOID *)((IMG_UINTPTR_T)pvNewBuf + ui32FirstCopySize),
+ (IMG_VOID *)(IMG_PBYTE)psStream->pvBase,
+ psStream->ui32WPtr);
+ }
+ ui32NewROffset = 0;
+ }
+ else
+ {
+
+ HostMemCopy(pvNewBuf, psStream->pvBase, psStream->ui32WPtr);
+ ui32NewROffset = psStream->ui32RPtr;
+ }
+
+
+
+
+ ui32NewWOffset = psStream->ui32Size - ui32SpaceInOldBuf;
+
+
+
+ if ((psStream->psCtrl->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+ {
+ HostNonPageablePageFree(psStream->pvBase);
+ }
+ else
+ {
+ HostPageablePageFree(psStream->pvBase);
+ }
+
+
+
+ psStream->pvBase = pvNewBuf;
+ psStream->ui32RPtr = ui32NewROffset;
+ psStream->ui32WPtr = ui32NewWOffset;
+ psStream->ui32Size = ui32NewSizeInPages * 4096;
+
+ return IMG_TRUE;
+}
+
+IMG_UINT32 SpaceInStream(PDBG_STREAM psStream)
+{
+ IMG_UINT32 ui32Space;
+
+ if (psStream->bCircularAllowed)
+ {
+
+ if (psStream->ui32RPtr > psStream->ui32WPtr)
+ {
+ ui32Space = psStream->ui32RPtr - psStream->ui32WPtr;
+ }
+ else
+ {
+ ui32Space = psStream->ui32RPtr + (psStream->ui32Size - psStream->ui32WPtr);
+ }
+ }
+ else
+ {
+
+ ui32Space = psStream->ui32Size - psStream->ui32WPtr;
+ }
+
+ return ui32Space;
+}
+
+
+void DestroyAllStreams(void)
+{
+ while (g_psStreamList != IMG_NULL)
+ {
+ DBGDrivDestroyStream(g_psStreamList);
+ }
+ return;
+}
+
+PDBG_LASTFRAME_BUFFER FindLFBuf(PDBG_STREAM psStream)
+{
+ PDBG_LASTFRAME_BUFFER psLFBuffer;
+
+ psLFBuffer = g_psLFBufferList;
+
+ while (psLFBuffer)
+ {
+ if (psLFBuffer->psStream == psStream)
+ {
+ break;
+ }
+
+ psLFBuffer = psLFBuffer->psNext;
+ }
+
+ return psLFBuffer;
+}
+
diff --git a/drivers/gpu/pvr/dbgdrv/dbgdriv.h b/drivers/gpu/pvr/dbgdrv/dbgdriv.h
new file mode 100644
index 0000000..2db4843
--- /dev/null
+++ b/drivers/gpu/pvr/dbgdrv/dbgdriv.h
@@ -0,0 +1,122 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef _DBGDRIV_
+#define _DBGDRIV_
+
+#define BUFFER_SIZE 64*PAGESIZE
+
+#define DBGDRIV_VERSION 0x100
+#define MAX_PROCESSES 2
+#define BLOCK_USED 0x01
+#define BLOCK_LOCKED 0x02
+#define DBGDRIV_MONOBASE 0x000B0000
+
+
+extern IMG_VOID * g_pvAPIMutex;
+
+IMG_VOID * IMG_CALLCONV DBGDrivCreateStream(IMG_CHAR * pszName,
+ IMG_UINT32 ui32CapMode,
+ IMG_UINT32 ui32OutMode,
+ IMG_UINT32 ui32Flags,
+ IMG_UINT32 ui32Pages);
+IMG_VOID IMG_CALLCONV DBGDrivDestroyStream(PDBG_STREAM psStream);
+IMG_VOID * IMG_CALLCONV DBGDrivFindStream(IMG_CHAR * pszName, IMG_BOOL bResetStream);
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV DBGDrivReadString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Limit);
+IMG_UINT32 IMG_CALLCONV DBGDrivWrite(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV DBGDrivWrite2(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV DBGDrivRead(PDBG_STREAM psStream, IMG_BOOL bReadInitBuffer, IMG_UINT32 ui32OutBufferSize,IMG_UINT8 *pui8OutBuf);
+IMG_VOID IMG_CALLCONV DBGDrivSetCaptureMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode,IMG_UINT32 ui32Start,IMG_UINT32 ui32Stop,IMG_UINT32 ui32SampleRate);
+IMG_VOID IMG_CALLCONV DBGDrivSetOutputMode(PDBG_STREAM psStream,IMG_UINT32 ui32OutMode);
+IMG_VOID IMG_CALLCONV DBGDrivSetDebugLevel(PDBG_STREAM psStream,IMG_UINT32 ui32DebugLevel);
+IMG_VOID IMG_CALLCONV DBGDrivSetFrame(PDBG_STREAM psStream,IMG_UINT32 ui32Frame);
+IMG_UINT32 IMG_CALLCONV DBGDrivGetFrame(PDBG_STREAM psStream);
+IMG_VOID IMG_CALLCONV DBGDrivOverrideMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode);
+IMG_VOID IMG_CALLCONV DBGDrivDefaultMode(PDBG_STREAM psStream);
+IMG_PVOID IMG_CALLCONV DBGDrivGetServiceTable(IMG_VOID);
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteStringCM(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteCM(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+IMG_VOID IMG_CALLCONV DBGDrivSetClientMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker);
+IMG_VOID IMG_CALLCONV DBGDrivSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker);
+IMG_UINT32 IMG_CALLCONV DBGDrivGetMarker(PDBG_STREAM psStream);
+IMG_BOOL IMG_CALLCONV DBGDrivIsLastCaptureFrame(PDBG_STREAM psStream);
+IMG_BOOL IMG_CALLCONV DBGDrivIsCaptureFrame(PDBG_STREAM psStream, IMG_BOOL bCheckPreviousFrame);
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteLF(PDBG_STREAM psStream, IMG_UINT8 *pui8InBuf, IMG_UINT32 ui32InBuffSize, IMG_UINT32 ui32Level, IMG_UINT32 ui32Flags);
+IMG_UINT32 IMG_CALLCONV DBGDrivReadLF(PDBG_STREAM psStream, IMG_UINT32 ui32OutBuffSize, IMG_UINT8 *pui8OutBuf);
+IMG_VOID IMG_CALLCONV DBGDrivStartInitPhase(PDBG_STREAM psStream);
+IMG_VOID IMG_CALLCONV DBGDrivStopInitPhase(PDBG_STREAM psStream);
+IMG_UINT32 IMG_CALLCONV DBGDrivGetStreamOffset(PDBG_STREAM psStream);
+IMG_VOID IMG_CALLCONV DBGDrivSetStreamOffset(PDBG_STREAM psStream, IMG_UINT32 ui32StreamOffset);
+IMG_VOID IMG_CALLCONV DBGDrivWaitForEvent(DBG_EVENT eEvent);
+
+IMG_VOID DestroyAllStreams(IMG_VOID);
+
+IMG_UINT32 AtoI(IMG_CHAR *szIn);
+
+IMG_VOID HostMemSet(IMG_VOID *pvDest,IMG_UINT8 ui8Value,IMG_UINT32 ui32Size);
+IMG_VOID HostMemCopy(IMG_VOID *pvDest,IMG_VOID *pvSrc,IMG_UINT32 ui32Size);
+IMG_VOID MonoOut(IMG_CHAR * pszString,IMG_BOOL bNewLine);
+
+IMG_SID PStream2SID(PDBG_STREAM psStream);
+PDBG_STREAM SID2PStream(IMG_SID hStream);
+IMG_BOOL AddSIDEntry(PDBG_STREAM psStream);
+IMG_BOOL RemoveSIDEntry(PDBG_STREAM psStream);
+
+IMG_VOID * IMG_CALLCONV ExtDBGDrivCreateStream(IMG_CHAR * pszName, IMG_UINT32 ui32CapMode, IMG_UINT32 ui32OutMode, IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size);
+IMG_VOID IMG_CALLCONV ExtDBGDrivDestroyStream(PDBG_STREAM psStream);
+IMG_VOID * IMG_CALLCONV ExtDBGDrivFindStream(IMG_CHAR * pszName, IMG_BOOL bResetStream);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivReadString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Limit);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWrite(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivRead(PDBG_STREAM psStream, IMG_BOOL bReadInitBuffer, IMG_UINT32 ui32OutBuffSize,IMG_UINT8 *pui8OutBuf);
+IMG_VOID IMG_CALLCONV ExtDBGDrivSetCaptureMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode,IMG_UINT32 ui32Start,IMG_UINT32 ui32End,IMG_UINT32 ui32SampleRate);
+IMG_VOID IMG_CALLCONV ExtDBGDrivSetOutputMode(PDBG_STREAM psStream,IMG_UINT32 ui32OutMode);
+IMG_VOID IMG_CALLCONV ExtDBGDrivSetDebugLevel(PDBG_STREAM psStream,IMG_UINT32 ui32DebugLevel);
+IMG_VOID IMG_CALLCONV ExtDBGDrivSetFrame(PDBG_STREAM psStream,IMG_UINT32 ui32Frame);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetFrame(PDBG_STREAM psStream);
+IMG_VOID IMG_CALLCONV ExtDBGDrivOverrideMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode);
+IMG_VOID IMG_CALLCONV ExtDBGDrivDefaultMode(PDBG_STREAM psStream);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWrite2(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteStringCM(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteCM(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+IMG_VOID IMG_CALLCONV ExtDBGDrivSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetMarker(PDBG_STREAM psStream);
+IMG_VOID IMG_CALLCONV ExtDBGDrivStartInitPhase(PDBG_STREAM psStream);
+IMG_VOID IMG_CALLCONV ExtDBGDrivStopInitPhase(PDBG_STREAM psStream);
+IMG_BOOL IMG_CALLCONV ExtDBGDrivIsLastCaptureFrame(PDBG_STREAM psStream);
+IMG_BOOL IMG_CALLCONV ExtDBGDrivIsCaptureFrame(PDBG_STREAM psStream, IMG_BOOL bCheckPreviousFrame);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteLF(PDBG_STREAM psStream, IMG_UINT8 *pui8InBuf, IMG_UINT32 ui32InBuffSize, IMG_UINT32 ui32Level, IMG_UINT32 ui32Flags);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivReadLF(PDBG_STREAM psStream, IMG_UINT32 ui32OutBuffSize, IMG_UINT8 *pui8OutBuf);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetStreamOffset(PDBG_STREAM psStream);
+IMG_VOID IMG_CALLCONV ExtDBGDrivSetStreamOffset(PDBG_STREAM psStream, IMG_UINT32 ui32StreamOffset);
+IMG_VOID IMG_CALLCONV ExtDBGDrivWaitForEvent(DBG_EVENT eEvent);
+IMG_VOID IMG_CALLCONV ExtDBGDrivSetConnectNotifier(DBGKM_CONNECT_NOTIFIER fn_notifier);
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWritePersist(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+
+#endif
+
diff --git a/drivers/gpu/pvr/dbgdrv/dbgdriv_ioctl.h b/drivers/gpu/pvr/dbgdrv/dbgdriv_ioctl.h
new file mode 100644
index 0000000..130c146
--- /dev/null
+++ b/drivers/gpu/pvr/dbgdrv/dbgdriv_ioctl.h
@@ -0,0 +1,35 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef _IOCTL_
+#define _IOCTL_
+
+#define MAX_DBGVXD_W32_API 25
+
+extern IMG_UINT32 (*g_DBGDrivProc[MAX_DBGVXD_W32_API])(IMG_VOID *, IMG_VOID *);
+
+#endif
+
diff --git a/drivers/gpu/pvr/dbgdrv/handle.c b/drivers/gpu/pvr/dbgdrv/handle.c
new file mode 100644
index 0000000..ddffb3f
--- /dev/null
+++ b/drivers/gpu/pvr/dbgdrv/handle.c
@@ -0,0 +1,121 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "img_defs.h"
+#include "dbgdrvif.h"
+#include "dbgdriv.h"
+
+#define MAX_SID_ENTRIES 8
+
+typedef struct _SID_INFO
+{
+ PDBG_STREAM psStream;
+} SID_INFO, *PSID_INFO;
+
+static SID_INFO gaSID_Xlat_Table[MAX_SID_ENTRIES];
+
+IMG_SID PStream2SID(PDBG_STREAM psStream)
+{
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ IMG_INT32 iIdx;
+
+ for (iIdx = 0; iIdx < MAX_SID_ENTRIES; iIdx++)
+ {
+ if (psStream == gaSID_Xlat_Table[iIdx].psStream)
+ {
+
+ return (IMG_SID)iIdx+1;
+ }
+ }
+ }
+
+ return (IMG_SID)0;
+}
+
+
+PDBG_STREAM SID2PStream(IMG_SID hStream)
+{
+
+ IMG_INT32 iIdx = (IMG_INT32)hStream-1;
+
+ if (iIdx >= 0 && iIdx < MAX_SID_ENTRIES)
+ {
+ return gaSID_Xlat_Table[iIdx].psStream;
+ }
+ else
+ {
+ return (PDBG_STREAM)IMG_NULL;
+ }
+}
+
+
+IMG_BOOL AddSIDEntry(PDBG_STREAM psStream)
+{
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ IMG_INT32 iIdx;
+
+ for (iIdx = 0; iIdx < MAX_SID_ENTRIES; iIdx++)
+ {
+ if (psStream == gaSID_Xlat_Table[iIdx].psStream)
+ {
+
+ return IMG_TRUE;
+ }
+
+ if (gaSID_Xlat_Table[iIdx].psStream == (PDBG_STREAM)IMG_NULL)
+ {
+
+ gaSID_Xlat_Table[iIdx].psStream = psStream;
+ return IMG_TRUE;
+ }
+ }
+ }
+
+ return IMG_FALSE;
+}
+
+IMG_BOOL RemoveSIDEntry(PDBG_STREAM psStream)
+{
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ IMG_INT32 iIdx;
+
+ for (iIdx = 0; iIdx < MAX_SID_ENTRIES; iIdx++)
+ {
+ if (psStream == gaSID_Xlat_Table[iIdx].psStream)
+ {
+ gaSID_Xlat_Table[iIdx].psStream = (PDBG_STREAM)IMG_NULL;
+ return IMG_TRUE;
+ }
+ }
+ }
+
+ return IMG_FALSE;
+}
+
+
diff --git a/drivers/gpu/pvr/dbgdrv/hostfunc.c b/drivers/gpu/pvr/dbgdrv/hostfunc.c
new file mode 100644
index 0000000..18c8898
--- /dev/null
+++ b/drivers/gpu/pvr/dbgdrv/hostfunc.c
@@ -0,0 +1,324 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include <linux/version.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <asm/page.h>
+#include <linux/vmalloc.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+#include <linux/mutex.h>
+#else
+#include <asm/semaphore.h>
+#endif
+#include <linux/hardirq.h>
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/jiffies.h>
+#include <linux/delay.h>
+#endif
+
+#include "img_types.h"
+#include "pvr_debug.h"
+
+#include "dbgdrvif.h"
+#include "hostfunc.h"
+#include "dbgdriv.h"
+
+#if defined(MODULE) && defined(DEBUG) && !defined(SUPPORT_DRI_DRM)
+IMG_UINT32 gPVRDebugLevel = (DBGPRIV_FATAL | DBGPRIV_ERROR | DBGPRIV_WARNING);
+
+#define PVR_STRING_TERMINATOR '\0'
+#define PVR_IS_FILE_SEPARATOR(character) ( ((character) == '\\') || ((character) == '/') )
+
+void PVRSRVDebugPrintf (
+ IMG_UINT32 ui32DebugLevel,
+ const IMG_CHAR* pszFileName,
+ IMG_UINT32 ui32Line,
+ const IMG_CHAR* pszFormat,
+ ...
+ )
+{
+ IMG_BOOL bTrace;
+#if !defined(__sh__)
+ IMG_CHAR *pszLeafName;
+
+ pszLeafName = (char *)strrchr (pszFileName, '\\');
+
+ if (pszLeafName)
+ {
+ pszFileName = pszLeafName;
+ }
+#endif
+
+ bTrace = (IMG_BOOL)(ui32DebugLevel & DBGPRIV_CALLTRACE) ? IMG_TRUE : IMG_FALSE;
+
+ if (gPVRDebugLevel & ui32DebugLevel)
+ {
+ va_list vaArgs;
+ char szBuffer[256];
+ char *szBufferEnd = szBuffer;
+ char *szBufferLimit = szBuffer + sizeof(szBuffer) - 1;
+
+
+ *szBufferLimit = '\0';
+
+ snprintf(szBufferEnd, szBufferLimit - szBufferEnd, "PVR_K:");
+ szBufferEnd += strlen(szBufferEnd);
+
+
+ if (bTrace == IMG_FALSE)
+ {
+ switch(ui32DebugLevel)
+ {
+ case DBGPRIV_FATAL:
+ {
+ snprintf(szBufferEnd, szBufferLimit - szBufferEnd, "(Fatal):");
+ break;
+ }
+ case DBGPRIV_ERROR:
+ {
+ snprintf(szBufferEnd, szBufferLimit - szBufferEnd, "(Error):");
+ break;
+ }
+ case DBGPRIV_WARNING:
+ {
+ snprintf(szBufferEnd, szBufferLimit - szBufferEnd, "(Warning):");
+ break;
+ }
+ case DBGPRIV_MESSAGE:
+ {
+ snprintf(szBufferEnd, szBufferLimit - szBufferEnd, "(Message):");
+ break;
+ }
+ case DBGPRIV_VERBOSE:
+ {
+ snprintf(szBufferEnd, szBufferLimit - szBufferEnd, "(Verbose):");
+ break;
+ }
+ default:
+ {
+ snprintf(szBufferEnd, szBufferLimit - szBufferEnd, "(Unknown message level)");
+ break;
+ }
+ }
+ szBufferEnd += strlen(szBufferEnd);
+ }
+ snprintf(szBufferEnd, szBufferLimit - szBufferEnd, " ");
+ szBufferEnd += strlen(szBufferEnd);
+
+ va_start (vaArgs, pszFormat);
+ vsnprintf(szBufferEnd, szBufferLimit - szBufferEnd, pszFormat, vaArgs);
+ va_end (vaArgs);
+ szBufferEnd += strlen(szBufferEnd);
+
+
+ if (bTrace == IMG_FALSE)
+ {
+ snprintf(szBufferEnd, szBufferLimit - szBufferEnd,
+ " [%d, %s]", (int)ui32Line, pszFileName);
+ szBufferEnd += strlen(szBufferEnd);
+ }
+
+ printk(KERN_INFO "%s\r\n", szBuffer);
+ }
+}
+#endif
+
+IMG_VOID HostMemSet(IMG_VOID *pvDest, IMG_UINT8 ui8Value, IMG_UINT32 ui32Size)
+{
+ memset(pvDest, (int) ui8Value, (size_t) ui32Size);
+}
+
+IMG_VOID HostMemCopy(IMG_VOID *pvDst, IMG_VOID *pvSrc, IMG_UINT32 ui32Size)
+{
+#if defined(USE_UNOPTIMISED_MEMCPY)
+ unsigned char *src,*dst;
+ int i;
+
+ src=(unsigned char *)pvSrc;
+ dst=(unsigned char *)pvDst;
+ for(i=0;i<ui32Size;i++)
+ {
+ dst[i]=src[i];
+ }
+#else
+ memcpy(pvDst, pvSrc, ui32Size);
+#endif
+}
+
+IMG_UINT32 HostReadRegistryDWORDFromString(char *pcKey, char *pcValueName, IMG_UINT32 *pui32Data)
+{
+
+ return 0;
+}
+
+IMG_VOID * HostPageablePageAlloc(IMG_UINT32 ui32Pages)
+{
+ return (void*)vmalloc(ui32Pages * PAGE_SIZE);
+}
+
+IMG_VOID HostPageablePageFree(IMG_VOID * pvBase)
+{
+ vfree(pvBase);
+}
+
+IMG_VOID * HostNonPageablePageAlloc(IMG_UINT32 ui32Pages)
+{
+ return (void*)vmalloc(ui32Pages * PAGE_SIZE);
+}
+
+IMG_VOID HostNonPageablePageFree(IMG_VOID * pvBase)
+{
+ vfree(pvBase);
+}
+
+IMG_VOID * HostMapKrnBufIntoUser(IMG_VOID * pvKrnAddr, IMG_UINT32 ui32Size, IMG_VOID **ppvMdl)
+{
+
+ return IMG_NULL;
+}
+
+IMG_VOID HostUnMapKrnBufFromUser(IMG_VOID * pvUserAddr, IMG_VOID * pvMdl, IMG_VOID * pvProcess)
+{
+
+}
+
+IMG_VOID HostCreateRegDeclStreams(IMG_VOID)
+{
+
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+typedef struct mutex MUTEX;
+#define INIT_MUTEX(m) mutex_init(m)
+#define DOWN_TRYLOCK(m) (!mutex_trylock(m))
+#define DOWN(m) mutex_lock(m)
+#define UP(m) mutex_unlock(m)
+#else
+typedef struct semaphore MUTEX;
+#define INIT_MUTEX(m) init_MUTEX(m)
+#define DOWN_TRYLOCK(m) down_trylock(m)
+#define DOWN(m) down(m)
+#define UP(m) up(m)
+#endif
+
+IMG_VOID *HostCreateMutex(IMG_VOID)
+{
+ MUTEX *psMutex;
+
+ psMutex = kmalloc(sizeof(*psMutex), GFP_KERNEL);
+ if (psMutex)
+ {
+ INIT_MUTEX(psMutex);
+ }
+
+ return psMutex;
+}
+
+IMG_VOID HostAquireMutex(IMG_VOID * pvMutex)
+{
+ BUG_ON(in_interrupt());
+
+#if defined(PVR_DEBUG_DBGDRV_DETECT_HOST_MUTEX_COLLISIONS)
+ if (DOWN_TRYLOCK((MUTEX *)pvMutex))
+ {
+ printk(KERN_INFO "HostAquireMutex: Waiting for mutex\n");
+ DOWN((MUTEX *)pvMutex);
+ }
+#else
+ DOWN((MUTEX *)pvMutex);
+#endif
+}
+
+IMG_VOID HostReleaseMutex(IMG_VOID * pvMutex)
+{
+ UP((MUTEX *)pvMutex);
+}
+
+IMG_VOID HostDestroyMutex(IMG_VOID * pvMutex)
+{
+ if (pvMutex)
+ {
+ kfree(pvMutex);
+ }
+}
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+
+#define EVENT_WAIT_TIMEOUT_MS 500
+#define EVENT_WAIT_TIMEOUT_JIFFIES (EVENT_WAIT_TIMEOUT_MS * HZ / 1000)
+
+static int iStreamData;
+static wait_queue_head_t sStreamDataEvent;
+
+IMG_INT32 HostCreateEventObjects(IMG_VOID)
+{
+ init_waitqueue_head(&sStreamDataEvent);
+
+ return 0;
+}
+
+IMG_VOID HostWaitForEvent(DBG_EVENT eEvent)
+{
+ switch(eEvent)
+ {
+ case DBG_EVENT_STREAM_DATA:
+
+ wait_event_interruptible_timeout(sStreamDataEvent, iStreamData != 0, EVENT_WAIT_TIMEOUT_JIFFIES);
+ iStreamData = 0;
+ break;
+ default:
+
+ msleep_interruptible(EVENT_WAIT_TIMEOUT_MS);
+ break;
+ }
+}
+
+IMG_VOID HostSignalEvent(DBG_EVENT eEvent)
+{
+ switch(eEvent)
+ {
+ case DBG_EVENT_STREAM_DATA:
+ iStreamData = 1;
+ wake_up_interruptible(&sStreamDataEvent);
+ break;
+ default:
+ break;
+ }
+}
+
+IMG_VOID HostDestroyEventObjects(IMG_VOID)
+{
+}
+#endif
diff --git a/drivers/gpu/pvr/dbgdrv/hostfunc.h b/drivers/gpu/pvr/dbgdrv/hostfunc.h
new file mode 100644
index 0000000..70192fb
--- /dev/null
+++ b/drivers/gpu/pvr/dbgdrv/hostfunc.h
@@ -0,0 +1,58 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef _HOSTFUNC_
+#define _HOSTFUNC_
+
+#define HOST_PAGESIZE (4096)
+#define DBG_MEMORY_INITIALIZER (0xe2)
+
+IMG_UINT32 HostReadRegistryDWORDFromString(IMG_CHAR *pcKey, IMG_CHAR *pcValueName, IMG_UINT32 *pui32Data);
+
+IMG_VOID * HostPageablePageAlloc(IMG_UINT32 ui32Pages);
+IMG_VOID HostPageablePageFree(IMG_VOID * pvBase);
+IMG_VOID * HostNonPageablePageAlloc(IMG_UINT32 ui32Pages);
+IMG_VOID HostNonPageablePageFree(IMG_VOID * pvBase);
+
+IMG_VOID * HostMapKrnBufIntoUser(IMG_VOID * pvKrnAddr, IMG_UINT32 ui32Size, IMG_VOID * *ppvMdl);
+IMG_VOID HostUnMapKrnBufFromUser(IMG_VOID * pvUserAddr, IMG_VOID * pvMdl, IMG_VOID * pvProcess);
+
+IMG_VOID HostCreateRegDeclStreams(IMG_VOID);
+
+IMG_VOID * HostCreateMutex(IMG_VOID);
+IMG_VOID HostAquireMutex(IMG_VOID * pvMutex);
+IMG_VOID HostReleaseMutex(IMG_VOID * pvMutex);
+IMG_VOID HostDestroyMutex(IMG_VOID * pvMutex);
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+IMG_INT32 HostCreateEventObjects(IMG_VOID);
+IMG_VOID HostWaitForEvent(DBG_EVENT eEvent);
+IMG_VOID HostSignalEvent(DBG_EVENT eEvent);
+IMG_VOID HostDestroyEventObjects(IMG_VOID);
+#endif
+
+#endif
+
diff --git a/drivers/gpu/pvr/dbgdrv/hotkey.c b/drivers/gpu/pvr/dbgdrv/hotkey.c
new file mode 100644
index 0000000..a456fee
--- /dev/null
+++ b/drivers/gpu/pvr/dbgdrv/hotkey.c
@@ -0,0 +1,135 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+
+#if !defined(LINUX)
+#include <ntddk.h>
+#include <windef.h>
+#endif
+
+#include "img_types.h"
+#include "pvr_debug.h"
+#include "dbgdrvif.h"
+#include "dbgdriv.h"
+#include "hotkey.h"
+#include "hostfunc.h"
+
+
+
+
+
+IMG_UINT32 g_ui32HotKeyFrame = 0xFFFFFFFF;
+IMG_BOOL g_bHotKeyPressed = IMG_FALSE;
+IMG_BOOL g_bHotKeyRegistered = IMG_FALSE;
+
+PRIVATEHOTKEYDATA g_PrivateHotKeyData;
+
+
+IMG_VOID ReadInHotKeys(IMG_VOID)
+{
+ g_PrivateHotKeyData.ui32ScanCode = 0x58;
+ g_PrivateHotKeyData.ui32ShiftState = 0x0;
+
+
+
+#if 0
+ if (_RegOpenKey(HKEY_LOCAL_MACHINE,pszRegPath,&hKey) == ERROR_SUCCESS)
+ {
+
+
+ QueryReg(hKey,"ui32ScanCode",&g_PrivateHotKeyData.ui32ScanCode);
+ QueryReg(hKey,"ui32ShiftState",&g_PrivateHotKeyData.ui32ShiftState);
+ }
+#else
+ HostReadRegistryDWORDFromString("DEBUG\\Streams", "ui32ScanCode" , &g_PrivateHotKeyData.ui32ScanCode);
+ HostReadRegistryDWORDFromString("DEBUG\\Streams", "ui32ShiftState", &g_PrivateHotKeyData.ui32ShiftState);
+#endif
+}
+
+IMG_VOID RegisterKeyPressed(IMG_UINT32 dwui32ScanCode, PHOTKEYINFO pInfo)
+{
+ PDBG_STREAM psStream;
+
+ PVR_UNREFERENCED_PARAMETER(pInfo);
+
+ if (dwui32ScanCode == g_PrivateHotKeyData.ui32ScanCode)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"PDUMP Hotkey pressed !\n"));
+
+ psStream = (PDBG_STREAM) g_PrivateHotKeyData.sHotKeyInfo.pvStream;
+
+ if (!g_bHotKeyPressed)
+ {
+
+
+ g_ui32HotKeyFrame = psStream->psCtrl->ui32Current + 2;
+
+
+
+ g_bHotKeyPressed = IMG_TRUE;
+ }
+ }
+}
+
+IMG_VOID ActivateHotKeys(PDBG_STREAM psStream)
+{
+
+
+ ReadInHotKeys();
+
+
+
+ if (!g_PrivateHotKeyData.sHotKeyInfo.hHotKey)
+ {
+ if (g_PrivateHotKeyData.ui32ScanCode != 0)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"Activate HotKey for PDUMP.\n"));
+
+
+
+ g_PrivateHotKeyData.sHotKeyInfo.pvStream = psStream;
+
+ DefineHotKey(g_PrivateHotKeyData.ui32ScanCode, g_PrivateHotKeyData.ui32ShiftState, &g_PrivateHotKeyData.sHotKeyInfo);
+ }
+ else
+ {
+ g_PrivateHotKeyData.sHotKeyInfo.hHotKey = 0;
+ }
+ }
+}
+
+IMG_VOID DeactivateHotKeys(IMG_VOID)
+{
+ if (g_PrivateHotKeyData.sHotKeyInfo.hHotKey != 0)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"Deactivate HotKey.\n"));
+
+ RemoveHotKey(g_PrivateHotKeyData.sHotKeyInfo.hHotKey);
+ g_PrivateHotKeyData.sHotKeyInfo.hHotKey = 0;
+ }
+}
+
+
diff --git a/drivers/gpu/pvr/dbgdrv/hotkey.h b/drivers/gpu/pvr/dbgdrv/hotkey.h
new file mode 100644
index 0000000..c5d84bb
--- /dev/null
+++ b/drivers/gpu/pvr/dbgdrv/hotkey.h
@@ -0,0 +1,60 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef _HOTKEY_
+#define _HOTKEY_
+
+
+typedef struct _hotkeyinfo
+{
+ IMG_UINT8 ui8ScanCode;
+ IMG_UINT8 ui8Type;
+ IMG_UINT8 ui8Flag;
+ IMG_UINT8 ui8Filler1;
+ IMG_UINT32 ui32ShiftState;
+ IMG_UINT32 ui32HotKeyProc;
+ IMG_VOID *pvStream;
+ IMG_UINT32 hHotKey;
+} HOTKEYINFO, *PHOTKEYINFO;
+
+typedef struct _privatehotkeydata
+{
+ IMG_UINT32 ui32ScanCode;
+ IMG_UINT32 ui32ShiftState;
+ HOTKEYINFO sHotKeyInfo;
+} PRIVATEHOTKEYDATA, *PPRIVATEHOTKEYDATA;
+
+
+IMG_VOID ReadInHotKeys (IMG_VOID);
+IMG_VOID ActivateHotKeys(PDBG_STREAM psStream);
+IMG_VOID DeactivateHotKeys(IMG_VOID);
+
+IMG_VOID RemoveHotKey (IMG_UINT32 hHotKey);
+IMG_VOID DefineHotKey (IMG_UINT32 ui32ScanCode, IMG_UINT32 ui32ShiftState, PHOTKEYINFO psInfo);
+IMG_VOID RegisterKeyPressed (IMG_UINT32 ui32ScanCode, PHOTKEYINFO psInfo);
+
+#endif
+
diff --git a/drivers/gpu/pvr/dbgdrv/ioctl.c b/drivers/gpu/pvr/dbgdrv/ioctl.c
new file mode 100644
index 0000000..47487b0
--- /dev/null
+++ b/drivers/gpu/pvr/dbgdrv/ioctl.c
@@ -0,0 +1,587 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+
+
+#ifdef LINUX
+#include <asm/uaccess.h>
+#include "pvr_uaccess.h"
+#endif
+
+#include "img_types.h"
+#include "dbgdrvif.h"
+#include "dbgdriv.h"
+#include "hotkey.h"
+#include "dbgdriv_ioctl.h"
+
+
+static IMG_UINT32 DBGDIOCDrivCreateStream(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_IN_CREATESTREAM psIn;
+ IMG_VOID * *ppvOut;
+ #ifdef LINUX
+ static IMG_CHAR name[32];
+ #endif
+
+ psIn = (PDBG_IN_CREATESTREAM) pvInBuffer;
+ ppvOut = (IMG_VOID * *) pvOutBuffer;
+
+ #ifdef LINUX
+
+ if(pvr_copy_from_user(name, psIn->u.pszName, 32) != 0)
+ {
+ return IMG_FALSE;
+ }
+
+ *ppvOut = ExtDBGDrivCreateStream(name, psIn->ui32CapMode, psIn->ui32OutMode, 0, psIn->ui32Pages);
+
+ #else
+ *ppvOut = ExtDBGDrivCreateStream(psIn->u.pszName, psIn->ui32CapMode, psIn->ui32OutMode, DEBUG_FLAGS_NO_BUF_EXPANDSION, psIn->ui32Pages);
+ #endif
+
+
+ return(IMG_TRUE);
+}
+
+static IMG_UINT32 DBGDIOCDrivDestroyStream(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_STREAM *ppsStream;
+ PDBG_STREAM psStream;
+
+ ppsStream = (PDBG_STREAM *) pvInBuffer;
+ psStream = (PDBG_STREAM) *ppsStream;
+
+ PVR_UNREFERENCED_PARAMETER( pvOutBuffer);
+
+ ExtDBGDrivDestroyStream(psStream);
+
+ return(IMG_TRUE);
+}
+
+static IMG_UINT32 DBGDIOCDrivGetStream(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_IN_FINDSTREAM psParams;
+ IMG_SID * phStream;
+
+ psParams = (PDBG_IN_FINDSTREAM)pvInBuffer;
+ phStream = (IMG_SID *)pvOutBuffer;
+
+ *phStream = PStream2SID(ExtDBGDrivFindStream(psParams->u.pszName, psParams->bResetStream));
+
+ return(IMG_TRUE);
+}
+
+static IMG_UINT32 DBGDIOCDrivWriteString(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_IN_WRITESTRING psParams;
+ IMG_UINT32 *pui32OutLen;
+ PDBG_STREAM psStream;
+
+ psParams = (PDBG_IN_WRITESTRING) pvInBuffer;
+ pui32OutLen = (IMG_UINT32 *) pvOutBuffer;
+
+ psStream = SID2PStream(psParams->hStream);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ *pui32OutLen = ExtDBGDrivWriteString(psStream,psParams->u.pszString,psParams->ui32Level);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ *pui32OutLen = 0;
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivWriteStringCM(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_IN_WRITESTRING psParams;
+ IMG_UINT32 *pui32OutLen;
+ PDBG_STREAM psStream;
+
+ psParams = (PDBG_IN_WRITESTRING) pvInBuffer;
+ pui32OutLen = (IMG_UINT32 *) pvOutBuffer;
+
+ psStream = SID2PStream(psParams->hStream);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ *pui32OutLen = ExtDBGDrivWriteStringCM(psStream,psParams->u.pszString,psParams->ui32Level);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ *pui32OutLen = 0;
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivReadString(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ IMG_UINT32 * pui32OutLen;
+ PDBG_IN_READSTRING psParams;
+ PDBG_STREAM psStream;
+
+ psParams = (PDBG_IN_READSTRING) pvInBuffer;
+ pui32OutLen = (IMG_UINT32 *) pvOutBuffer;
+
+ psStream = SID2PStream(psParams->hStream);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ *pui32OutLen = ExtDBGDrivReadString(psStream,
+ psParams->u.pszString,psParams->ui32StringLen);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ *pui32OutLen = 0;
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivWrite(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ IMG_UINT32 * pui32BytesCopied;
+ PDBG_IN_WRITE psInParams;
+ PDBG_STREAM psStream;
+
+ psInParams = (PDBG_IN_WRITE) pvInBuffer;
+ pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+ psStream = SID2PStream(psInParams->hStream);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ *pui32BytesCopied = ExtDBGDrivWrite(psStream,
+ psInParams->u.pui8InBuffer,
+ psInParams->ui32TransferSize,
+ psInParams->ui32Level);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ *pui32BytesCopied = 0;
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivWrite2(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ IMG_UINT32 * pui32BytesCopied;
+ PDBG_IN_WRITE psInParams;
+ PDBG_STREAM psStream;
+
+ psInParams = (PDBG_IN_WRITE) pvInBuffer;
+ pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+ psStream = SID2PStream(psInParams->hStream);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ *pui32BytesCopied = ExtDBGDrivWrite2(psStream,
+ psInParams->u.pui8InBuffer,
+ psInParams->ui32TransferSize,
+ psInParams->ui32Level);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ *pui32BytesCopied = 0;
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivWriteCM(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ IMG_UINT32 * pui32BytesCopied;
+ PDBG_IN_WRITE psInParams;
+ PDBG_STREAM psStream;
+
+ psInParams = (PDBG_IN_WRITE) pvInBuffer;
+ pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+ psStream = SID2PStream(psInParams->hStream);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ *pui32BytesCopied = ExtDBGDrivWriteCM(psStream,
+ psInParams->u.pui8InBuffer,
+ psInParams->ui32TransferSize,
+ psInParams->ui32Level);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ *pui32BytesCopied = 0;
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivRead(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ IMG_UINT32 * pui32BytesCopied;
+ PDBG_IN_READ psInParams;
+ PDBG_STREAM psStream;
+
+ psInParams = (PDBG_IN_READ) pvInBuffer;
+ pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+ psStream = SID2PStream(psInParams->hStream);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ *pui32BytesCopied = ExtDBGDrivRead(psStream,
+ psInParams->bReadInitBuffer,
+ psInParams->ui32OutBufferSize,
+ psInParams->u.pui8OutBuffer);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ *pui32BytesCopied = 0;
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivSetCaptureMode(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_IN_SETDEBUGMODE psParams;
+ PDBG_STREAM psStream;
+
+ psParams = (PDBG_IN_SETDEBUGMODE) pvInBuffer;
+ PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+ psStream = SID2PStream(psParams->hStream);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ ExtDBGDrivSetCaptureMode(psStream,
+ psParams->ui32Mode,
+ psParams->ui32Start,
+ psParams->ui32End,
+ psParams->ui32SampleRate);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivSetOutMode(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_IN_SETDEBUGOUTMODE psParams;
+ PDBG_STREAM psStream;
+
+ psParams = (PDBG_IN_SETDEBUGOUTMODE) pvInBuffer;
+ PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+ psStream = SID2PStream(psParams->hStream);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ ExtDBGDrivSetOutputMode(psStream,psParams->ui32Mode);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivSetDebugLevel(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_IN_SETDEBUGLEVEL psParams;
+ PDBG_STREAM psStream;
+
+ psParams = (PDBG_IN_SETDEBUGLEVEL) pvInBuffer;
+ PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+ psStream = SID2PStream(psParams->hStream);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ ExtDBGDrivSetDebugLevel(psStream,psParams->ui32Level);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivSetFrame(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_IN_SETFRAME psParams;
+ PDBG_STREAM psStream;
+
+ psParams = (PDBG_IN_SETFRAME) pvInBuffer;
+ PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+ psStream = SID2PStream(psParams->hStream);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ ExtDBGDrivSetFrame(psStream,psParams->ui32Frame);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivGetFrame(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_STREAM psStream;
+ IMG_UINT32 *pui32Current;
+
+ pui32Current = (IMG_UINT32 *) pvOutBuffer;
+ psStream = SID2PStream(*(IMG_SID *)pvInBuffer);
+
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ *pui32Current = ExtDBGDrivGetFrame(psStream);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ *pui32Current = 0;
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivIsCaptureFrame(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_IN_ISCAPTUREFRAME psParams;
+ IMG_UINT32 * pui32Current;
+ PDBG_STREAM psStream;
+
+ psParams = (PDBG_IN_ISCAPTUREFRAME) pvInBuffer;
+ pui32Current = (IMG_UINT32 *) pvOutBuffer;
+
+ psStream = SID2PStream(psParams->hStream);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ *pui32Current = ExtDBGDrivIsCaptureFrame(psStream,
+ psParams->bCheckPreviousFrame);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ *pui32Current = 0;
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivOverrideMode(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_IN_OVERRIDEMODE psParams;
+ PDBG_STREAM psStream;
+
+ psParams = (PDBG_IN_OVERRIDEMODE) pvInBuffer;
+ PVR_UNREFERENCED_PARAMETER( pvOutBuffer);
+
+ psStream = SID2PStream(psParams->hStream);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ ExtDBGDrivOverrideMode(psStream,psParams->ui32Mode);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivDefaultMode(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_STREAM psStream;
+
+ PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+ psStream = SID2PStream(*(IMG_SID *)pvInBuffer);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ ExtDBGDrivDefaultMode(psStream);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivSetMarker(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_IN_SETMARKER psParams;
+ PDBG_STREAM psStream;
+
+ psParams = (PDBG_IN_SETMARKER) pvInBuffer;
+ PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+ psStream = SID2PStream(psParams->hStream);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ ExtDBGDrivSetMarker(psStream, psParams->ui32Marker);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivGetMarker(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_STREAM psStream;
+ IMG_UINT32 *pui32Current;
+
+ pui32Current = (IMG_UINT32 *) pvOutBuffer;
+
+ psStream = SID2PStream(*(IMG_SID *)pvInBuffer);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ *pui32Current = ExtDBGDrivGetMarker(psStream);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ *pui32Current = 0;
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivGetServiceTable(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ IMG_PVOID * ppvOut;
+
+ PVR_UNREFERENCED_PARAMETER(pvInBuffer);
+ ppvOut = (IMG_PVOID *) pvOutBuffer;
+
+ *ppvOut = DBGDrivGetServiceTable();
+
+ return(IMG_TRUE);
+}
+
+static IMG_UINT32 DBGDIOCDrivWriteLF(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_IN_WRITE_LF psInParams;
+ IMG_UINT32 *pui32BytesCopied;
+ PDBG_STREAM psStream;
+
+ psInParams = (PDBG_IN_WRITE_LF) pvInBuffer;
+ pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+ psStream = SID2PStream(psInParams->hStream);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ *pui32BytesCopied = ExtDBGDrivWriteLF(psStream,
+ psInParams->u.pui8InBuffer,
+ psInParams->ui32BufferSize,
+ psInParams->ui32Level,
+ psInParams->ui32Flags);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivReadLF(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ IMG_UINT32 * pui32BytesCopied;
+ PDBG_IN_READ psInParams;
+ PDBG_STREAM psStream;
+
+ psInParams = (PDBG_IN_READ) pvInBuffer;
+ pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+ psStream = SID2PStream(psInParams->hStream);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ *pui32BytesCopied = ExtDBGDrivReadLF(psStream,
+ psInParams->ui32OutBufferSize,
+ psInParams->u.pui8OutBuffer);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ *pui32BytesCopied = 0;
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivWaitForEvent(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ DBG_EVENT eEvent = (DBG_EVENT)(*(IMG_UINT32 *)pvInBuffer);
+
+ PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+ ExtDBGDrivWaitForEvent(eEvent);
+
+ return(IMG_TRUE);
+}
+
+IMG_UINT32 (*g_DBGDrivProc[25])(IMG_VOID *, IMG_VOID *) =
+{
+ DBGDIOCDrivCreateStream,
+ DBGDIOCDrivDestroyStream,
+ DBGDIOCDrivGetStream,
+ DBGDIOCDrivWriteString,
+ DBGDIOCDrivReadString,
+ DBGDIOCDrivWrite,
+ DBGDIOCDrivRead,
+ DBGDIOCDrivSetCaptureMode,
+ DBGDIOCDrivSetOutMode,
+ DBGDIOCDrivSetDebugLevel,
+ DBGDIOCDrivSetFrame,
+ DBGDIOCDrivGetFrame,
+ DBGDIOCDrivOverrideMode,
+ DBGDIOCDrivDefaultMode,
+ DBGDIOCDrivGetServiceTable,
+ DBGDIOCDrivWrite2,
+ DBGDIOCDrivWriteStringCM,
+ DBGDIOCDrivWriteCM,
+ DBGDIOCDrivSetMarker,
+ DBGDIOCDrivGetMarker,
+ DBGDIOCDrivIsCaptureFrame,
+ DBGDIOCDrivWriteLF,
+ DBGDIOCDrivReadLF,
+ DBGDIOCDrivWaitForEvent
+};
+
diff --git a/drivers/gpu/pvr/dbgdrv/linuxsrv.h b/drivers/gpu/pvr/dbgdrv/linuxsrv.h
new file mode 100644
index 0000000..f1cb02a
--- /dev/null
+++ b/drivers/gpu/pvr/dbgdrv/linuxsrv.h
@@ -0,0 +1,48 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ **************************************************************************/
+
+#ifndef _LINUXSRV_H__
+#define _LINUXSRV_H__
+
+typedef struct tagIOCTL_PACKAGE
+{
+ IMG_UINT32 ui32Cmd; // ioctl command
+ IMG_UINT32 ui32Size; // needs to be correctly set
+ IMG_VOID *pInBuffer; // input data buffer
+ IMG_UINT32 ui32InBufferSize; // size of input data buffer
+ IMG_VOID *pOutBuffer; // output data buffer
+ IMG_UINT32 ui32OutBufferSize; // size of output data buffer
+} IOCTL_PACKAGE;
+
+IMG_UINT32 DeviceIoControl(IMG_UINT32 hDevice,
+ IMG_UINT32 ui32ControlCode,
+ IMG_VOID *pInBuffer,
+ IMG_UINT32 ui32InBufferSize,
+ IMG_VOID *pOutBuffer,
+ IMG_UINT32 ui32OutBufferSize,
+ IMG_UINT32 *pui32BytesReturned);
+
+#endif /* _LINUXSRV_H__*/
diff --git a/drivers/gpu/pvr/dbgdrv/main.c b/drivers/gpu/pvr/dbgdrv/main.c
new file mode 100644
index 0000000..6556249
--- /dev/null
+++ b/drivers/gpu/pvr/dbgdrv/main.c
@@ -0,0 +1,317 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/kdev_t.h>
+#include <linux/pci.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/vmalloc.h>
+#include <linux/version.h>
+
+#if defined(LDM_PLATFORM) && !defined(SUPPORT_DRI_DRM)
+#include <linux/platform_device.h>
+#endif
+
+#if defined(LDM_PCI) && !defined(SUPPORT_DRI_DRM)
+#include <linux/pci.h>
+#endif
+
+#include <asm/uaccess.h>
+
+#if defined(SUPPORT_DRI_DRM)
+#include "drmP.h"
+#include "drm.h"
+#endif
+
+#include "img_types.h"
+#include "linuxsrv.h"
+#include "dbgdriv_ioctl.h"
+#include "dbgdrvif.h"
+#include "dbgdriv.h"
+#include "hostfunc.h"
+#include "hotkey.h"
+#include "pvr_debug.h"
+#include "pvrmodule.h"
+#include "pvr_uaccess.h"
+
+#if defined(SUPPORT_DRI_DRM)
+
+#include "pvr_drm_shared.h"
+#include "pvr_drm.h"
+
+#else
+
+#define DRVNAME "dbgdrv"
+MODULE_SUPPORTED_DEVICE(DRVNAME);
+
+#if (defined(LDM_PLATFORM) || defined(LDM_PCI)) && !defined(SUPPORT_DRI_DRM)
+static struct class *psDbgDrvClass;
+#endif
+
+static int AssignedMajorNumber = 0;
+
+long dbgdrv_ioctl(struct file *, unsigned int, unsigned long);
+
+static int dbgdrv_open(struct inode unref__ * pInode, struct file unref__ * pFile)
+{
+ return 0;
+}
+
+static int dbgdrv_release(struct inode unref__ * pInode, struct file unref__ * pFile)
+{
+ return 0;
+}
+
+static int dbgdrv_mmap(struct file* pFile, struct vm_area_struct* ps_vma)
+{
+ return 0;
+}
+
+static struct file_operations dbgdrv_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = dbgdrv_ioctl,
+ .open = dbgdrv_open,
+ .release = dbgdrv_release,
+ .mmap = dbgdrv_mmap,
+};
+
+#endif
+
+IMG_VOID DBGDrvGetServiceTable(IMG_VOID **fn_table);
+
+IMG_VOID DBGDrvGetServiceTable(IMG_VOID **fn_table)
+{
+ extern DBGKM_SERVICE_TABLE g_sDBGKMServices;
+
+ *fn_table = &g_sDBGKMServices;
+}
+
+#if defined(SUPPORT_DRI_DRM)
+void dbgdrv_cleanup(void)
+#else
+static void __exit dbgdrv_cleanup(void)
+#endif
+{
+#if !defined(SUPPORT_DRI_DRM)
+#if defined(LDM_PLATFORM) || defined(LDM_PCI)
+ device_destroy(psDbgDrvClass, MKDEV(AssignedMajorNumber, 0));
+ class_destroy(psDbgDrvClass);
+#endif
+ unregister_chrdev(AssignedMajorNumber, DRVNAME);
+#endif
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+ HostDestroyEventObjects();
+#endif
+ HostDestroyMutex(g_pvAPIMutex);
+ return;
+}
+
+#if defined(SUPPORT_DRI_DRM)
+IMG_INT dbgdrv_init(void)
+#else
+static int __init dbgdrv_init(void)
+#endif
+{
+#if (defined(LDM_PLATFORM) || defined(LDM_PCI)) && !defined(SUPPORT_DRI_DRM)
+ struct device *psDev;
+#endif
+
+#if !defined(SUPPORT_DRI_DRM)
+ int err = -EBUSY;
+#endif
+
+
+ if ((g_pvAPIMutex=HostCreateMutex()) == IMG_NULL)
+ {
+ return -ENOMEM;
+ }
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+
+ (void) HostCreateEventObjects();
+#endif
+
+#if !defined(SUPPORT_DRI_DRM)
+ AssignedMajorNumber =
+ register_chrdev(AssignedMajorNumber, DRVNAME, &dbgdrv_fops);
+
+ if (AssignedMajorNumber <= 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR," unable to get major\n"));
+ goto ErrDestroyEventObjects;
+ }
+
+#if defined(LDM_PLATFORM) || defined(LDM_PCI)
+
+ psDbgDrvClass = class_create(THIS_MODULE, DRVNAME);
+ if (IS_ERR(psDbgDrvClass))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: unable to create class (%ld)",
+ __func__, PTR_ERR(psDbgDrvClass)));
+ goto ErrUnregisterCharDev;
+ }
+
+ psDev = device_create(psDbgDrvClass, NULL, MKDEV(AssignedMajorNumber, 0),
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26))
+ NULL,
+#endif
+ DRVNAME);
+ if (IS_ERR(psDev))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: unable to create device (%ld)",
+ __func__, PTR_ERR(psDev)));
+ goto ErrDestroyClass;
+ }
+#endif
+#endif
+
+ return 0;
+
+#if !defined(SUPPORT_DRI_DRM)
+ErrDestroyEventObjects:
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+ HostDestroyEventObjects();
+#endif
+#if defined(LDM_PLATFORM) || defined(LDM_PCI)
+ErrUnregisterCharDev:
+ unregister_chrdev(AssignedMajorNumber, DRVNAME);
+ErrDestroyClass:
+ class_destroy(psDbgDrvClass);
+#endif
+ return err;
+#endif
+}
+
+#if defined(SUPPORT_DRI_DRM)
+int dbgdrv_ioctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile)
+#else
+long dbgdrv_ioctl(struct file *file, unsigned int ioctlCmd, unsigned long arg)
+#endif
+{
+ IOCTL_PACKAGE *pIP = (IOCTL_PACKAGE *) arg;
+ char *buffer, *in, *out;
+ unsigned int cmd;
+
+ if((pIP->ui32InBufferSize > (PAGE_SIZE >> 1) ) || (pIP->ui32OutBufferSize > (PAGE_SIZE >> 1)))
+ {
+ PVR_DPF((PVR_DBG_ERROR,"Sizes of the buffers are too large, cannot do ioctl\n"));
+ return -1;
+ }
+
+ buffer = (char *) HostPageablePageAlloc(1);
+ if(!buffer)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"Failed to allocate buffer, cannot do ioctl\n"));
+ return -EFAULT;
+ }
+
+ in = buffer;
+ out = buffer + (PAGE_SIZE >>1);
+
+ if(pvr_copy_from_user(in, pIP->pInBuffer, pIP->ui32InBufferSize) != 0)
+ {
+ goto init_failed;
+ }
+
+
+ cmd = MAKEIOCTLINDEX(pIP->ui32Cmd) - DEBUG_SERVICE_IOCTL_BASE - 1;
+
+ if(pIP->ui32Cmd == DEBUG_SERVICE_READ)
+ {
+ IMG_UINT32 *pui32BytesCopied = (IMG_UINT32 *)out;
+ DBG_IN_READ *psReadInParams = (DBG_IN_READ *)in;
+ DBG_STREAM *psStream;
+ IMG_CHAR *ui8Tmp;
+
+ ui8Tmp = vmalloc(psReadInParams->ui32OutBufferSize);
+
+ if(!ui8Tmp)
+ {
+ goto init_failed;
+ }
+
+ psStream = SID2PStream(psReadInParams->hStream);
+ if(!psStream)
+ {
+ goto init_failed;
+ }
+
+ *pui32BytesCopied = ExtDBGDrivRead(psStream,
+ psReadInParams->bReadInitBuffer,
+ psReadInParams->ui32OutBufferSize,
+ ui8Tmp);
+
+ if(pvr_copy_to_user(psReadInParams->u.pui8OutBuffer,
+ ui8Tmp,
+ *pui32BytesCopied) != 0)
+ {
+ vfree(ui8Tmp);
+ goto init_failed;
+ }
+
+ vfree(ui8Tmp);
+ }
+ else
+ {
+ (g_DBGDrivProc[cmd])(in, out);
+ }
+
+ if(copy_to_user(pIP->pOutBuffer, out, pIP->ui32OutBufferSize) != 0)
+ {
+ goto init_failed;
+ }
+
+ HostPageablePageFree((IMG_VOID *)buffer);
+ return 0;
+
+init_failed:
+ HostPageablePageFree((IMG_VOID *)buffer);
+ return -EFAULT;
+}
+
+
+IMG_VOID RemoveHotKey (IMG_UINT32 hHotKey)
+{
+ PVR_UNREFERENCED_PARAMETER(hHotKey);
+}
+
+IMG_VOID DefineHotKey (IMG_UINT32 ui32ScanCode, IMG_UINT32 ui32ShiftState, PHOTKEYINFO psInfo)
+{
+ PVR_UNREFERENCED_PARAMETER(ui32ScanCode);
+ PVR_UNREFERENCED_PARAMETER(ui32ShiftState);
+ PVR_UNREFERENCED_PARAMETER(psInfo);
+}
+
+EXPORT_SYMBOL(DBGDrvGetServiceTable);
+
+#if !defined(SUPPORT_DRI_DRM)
+subsys_initcall(dbgdrv_init);
+module_exit(dbgdrv_cleanup);
+#endif
diff --git a/drivers/gpu/pvr/dbgdrvif.h b/drivers/gpu/pvr/dbgdrvif.h
new file mode 100644
index 0000000..09c1608
--- /dev/null
+++ b/drivers/gpu/pvr/dbgdrvif.h
@@ -0,0 +1,358 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+
+*****************************************************************************/
+#ifndef _DBGDRVIF_
+#define _DBGDRVIF_
+
+
+#if defined(__linux__)
+
+#define FILE_DEVICE_UNKNOWN 0
+#define METHOD_BUFFERED 0
+#define FILE_ANY_ACCESS 0
+
+#define CTL_CODE( DeviceType, Function, Method, Access ) (Function)
+#define MAKEIOCTLINDEX(i) ((i) & 0xFFF)
+
+#else
+
+#include "ioctldef.h"
+
+#endif
+
+/*****************************************************************************
+ Stream mode stuff.
+*****************************************************************************/
+#define DEBUG_CAPMODE_FRAMED 0x00000001UL
+#define DEBUG_CAPMODE_CONTINUOUS 0x00000002UL
+#define DEBUG_CAPMODE_HOTKEY 0x00000004UL
+
+#define DEBUG_OUTMODE_STANDARDDBG 0x00000001UL
+#define DEBUG_OUTMODE_MONO 0x00000002UL
+#define DEBUG_OUTMODE_STREAMENABLE 0x00000004UL
+#define DEBUG_OUTMODE_ASYNC 0x00000008UL
+#define DEBUG_OUTMODE_SGXVGA 0x00000010UL
+
+#define DEBUG_FLAGS_USE_NONPAGED_MEM 0x00000001UL
+#define DEBUG_FLAGS_NO_BUF_EXPANDSION 0x00000002UL
+#define DEBUG_FLAGS_ENABLESAMPLE 0x00000004UL
+#define DEBUG_FLAGS_READONLY 0x00000008UL
+#define DEBUG_FLAGS_WRITEONLY 0x00000010UL
+
+#define DEBUG_FLAGS_TEXTSTREAM 0x80000000UL
+
+/*****************************************************************************
+ Debug level control. Only bothered with the first 12 levels, I suspect you
+ get the idea...
+*****************************************************************************/
+#define DEBUG_LEVEL_0 0x00000001UL
+#define DEBUG_LEVEL_1 0x00000003UL
+#define DEBUG_LEVEL_2 0x00000007UL
+#define DEBUG_LEVEL_3 0x0000000FUL
+#define DEBUG_LEVEL_4 0x0000001FUL
+#define DEBUG_LEVEL_5 0x0000003FUL
+#define DEBUG_LEVEL_6 0x0000007FUL
+#define DEBUG_LEVEL_7 0x000000FFUL
+#define DEBUG_LEVEL_8 0x000001FFUL
+#define DEBUG_LEVEL_9 0x000003FFUL
+#define DEBUG_LEVEL_10 0x000007FFUL
+#define DEBUG_LEVEL_11 0x00000FFFUL
+
+#define DEBUG_LEVEL_SEL0 0x00000001UL
+#define DEBUG_LEVEL_SEL1 0x00000002UL
+#define DEBUG_LEVEL_SEL2 0x00000004UL
+#define DEBUG_LEVEL_SEL3 0x00000008UL
+#define DEBUG_LEVEL_SEL4 0x00000010UL
+#define DEBUG_LEVEL_SEL5 0x00000020UL
+#define DEBUG_LEVEL_SEL6 0x00000040UL
+#define DEBUG_LEVEL_SEL7 0x00000080UL
+#define DEBUG_LEVEL_SEL8 0x00000100UL
+#define DEBUG_LEVEL_SEL9 0x00000200UL
+#define DEBUG_LEVEL_SEL10 0x00000400UL
+#define DEBUG_LEVEL_SEL11 0x00000800UL
+
+/*****************************************************************************
+ IOCTL values.
+*****************************************************************************/
+#define DEBUG_SERVICE_IOCTL_BASE 0x800UL
+#define DEBUG_SERVICE_CREATESTREAM CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x01, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_DESTROYSTREAM CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x02, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_GETSTREAM CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x03, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITESTRING CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x04, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_READSTRING CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x05, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITE CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x06, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_READ CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x07, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETDEBUGMODE CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x08, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETDEBUGOUTMODE CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x09, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETDEBUGLEVEL CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0A, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETFRAME CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0B, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_GETFRAME CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0C, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_OVERRIDEMODE CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0D, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_DEFAULTMODE CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0E, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_GETSERVICETABLE CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0F, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITE2 CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x10, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITESTRINGCM CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x11, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITECM CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x12, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETMARKER CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x13, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_GETMARKER CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x14, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_ISCAPTUREFRAME CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x15, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITELF CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x16, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_READLF CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x17, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WAITFOREVENT CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x18, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETCONNNOTIFY CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x19, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+
+typedef enum _DBG_EVENT_
+{
+ DBG_EVENT_STREAM_DATA = 1
+} DBG_EVENT;
+
+
+/*****************************************************************************
+ In/Out Structures
+*****************************************************************************/
+typedef struct _DBG_IN_CREATESTREAM_
+{
+ union
+ {
+ IMG_CHAR *pszName;
+ IMG_UINT64 ui64Name;
+ } u;
+ IMG_UINT32 ui32Pages;
+ IMG_UINT32 ui32CapMode;
+ IMG_UINT32 ui32OutMode;
+}DBG_IN_CREATESTREAM, *PDBG_IN_CREATESTREAM;
+
+typedef struct _DBG_IN_FINDSTREAM_
+{
+ union
+ {
+ IMG_CHAR *pszName;
+ IMG_UINT64 ui64Name;
+ }u;
+ IMG_BOOL bResetStream;
+}DBG_IN_FINDSTREAM, *PDBG_IN_FINDSTREAM;
+
+typedef struct _DBG_IN_WRITESTRING_
+{
+ union
+ {
+ IMG_CHAR *pszString;
+ IMG_UINT64 ui64String;
+ } u;
+ IMG_SID hStream;
+ IMG_UINT32 ui32Level;
+}DBG_IN_WRITESTRING, *PDBG_IN_WRITESTRING;
+
+typedef struct _DBG_IN_READSTRING_
+{
+ union
+ {
+ IMG_CHAR *pszString;
+ IMG_UINT64 ui64String;
+ } u;
+ IMG_SID hStream;
+ IMG_UINT32 ui32StringLen;
+} DBG_IN_READSTRING, *PDBG_IN_READSTRING;
+
+typedef struct _DBG_IN_SETDEBUGMODE_
+{
+ IMG_SID hStream;
+ IMG_UINT32 ui32Mode;
+ IMG_UINT32 ui32Start;
+ IMG_UINT32 ui32End;
+ IMG_UINT32 ui32SampleRate;
+} DBG_IN_SETDEBUGMODE, *PDBG_IN_SETDEBUGMODE;
+
+typedef struct _DBG_IN_SETDEBUGOUTMODE_
+{
+ IMG_SID hStream;
+ IMG_UINT32 ui32Mode;
+} DBG_IN_SETDEBUGOUTMODE, *PDBG_IN_SETDEBUGOUTMODE;
+
+typedef struct _DBG_IN_SETDEBUGLEVEL_
+{
+ IMG_SID hStream;
+ IMG_UINT32 ui32Level;
+} DBG_IN_SETDEBUGLEVEL, *PDBG_IN_SETDEBUGLEVEL;
+
+typedef struct _DBG_IN_SETFRAME_
+{
+ IMG_SID hStream;
+ IMG_UINT32 ui32Frame;
+} DBG_IN_SETFRAME, *PDBG_IN_SETFRAME;
+
+typedef struct _DBG_IN_WRITE_
+{
+ union
+ {
+ IMG_UINT8 *pui8InBuffer;
+ IMG_UINT64 ui64InBuffer;
+ } u;
+ IMG_SID hStream;
+ IMG_UINT32 ui32Level;
+ IMG_UINT32 ui32TransferSize;
+} DBG_IN_WRITE, *PDBG_IN_WRITE;
+
+typedef struct _DBG_IN_READ_
+{
+ union
+ {
+ IMG_UINT8 *pui8OutBuffer;
+ IMG_UINT64 ui64OutBuffer;
+ } u;
+ IMG_SID hStream;
+ IMG_BOOL bReadInitBuffer;
+ IMG_UINT32 ui32OutBufferSize;
+} DBG_IN_READ, *PDBG_IN_READ;
+
+typedef struct _DBG_IN_OVERRIDEMODE_
+{
+ IMG_SID hStream;
+ IMG_UINT32 ui32Mode;
+} DBG_IN_OVERRIDEMODE, *PDBG_IN_OVERRIDEMODE;
+
+typedef struct _DBG_IN_ISCAPTUREFRAME_
+{
+ IMG_SID hStream;
+ IMG_BOOL bCheckPreviousFrame;
+} DBG_IN_ISCAPTUREFRAME, *PDBG_IN_ISCAPTUREFRAME;
+
+typedef struct _DBG_IN_SETMARKER_
+{
+ IMG_SID hStream;
+ IMG_UINT32 ui32Marker;
+} DBG_IN_SETMARKER, *PDBG_IN_SETMARKER;
+
+typedef struct _DBG_IN_WRITE_LF_
+{
+ union
+ {
+ IMG_UINT8 *pui8InBuffer;
+ IMG_UINT64 ui64InBuffer;
+ } u;
+ IMG_UINT32 ui32Flags;
+ IMG_SID hStream;
+ IMG_UINT32 ui32Level;
+ IMG_UINT32 ui32BufferSize;
+} DBG_IN_WRITE_LF, *PDBG_IN_WRITE_LF;
+
+/*
+ Flags for above struct
+*/
+#define WRITELF_FLAGS_RESETBUF 0x00000001UL
+
+/*
+ Common control structure (don't duplicate control in main stream
+ and init phase stream).
+*/
+typedef struct _DBG_STREAM_CONTROL_
+{
+ IMG_BOOL bInitPhaseComplete; /*!< init phase has finished */
+ IMG_UINT32 ui32Flags; /*!< flags (see DEBUG_FLAGS above) */
+
+ IMG_UINT32 ui32CapMode; /*!< capturing mode framed/hot key */
+ IMG_UINT32 ui32OutMode; /*!< output mode, e.g. files */
+ IMG_UINT32 ui32DebugLevel;
+ IMG_UINT32 ui32DefaultMode;
+ IMG_UINT32 ui32Start; /*!< first capture frame */
+ IMG_UINT32 ui32End; /*!< last frame */
+ IMG_UINT32 ui32Current; /*!< current frame */
+ IMG_UINT32 ui32SampleRate; /*!< capture frequency */
+ IMG_UINT32 ui32Reserved;
+} DBG_STREAM_CONTROL, *PDBG_STREAM_CONTROL;
+/*
+ Per-buffer control structure.
+*/
+typedef struct _DBG_STREAM_
+{
+ struct _DBG_STREAM_ *psNext;
+ struct _DBG_STREAM_ *psInitStream;
+ DBG_STREAM_CONTROL *psCtrl;
+ IMG_BOOL bCircularAllowed;
+ IMG_PVOID pvBase;
+ IMG_UINT32 ui32Size;
+ IMG_UINT32 ui32RPtr;
+ IMG_UINT32 ui32WPtr;
+ IMG_UINT32 ui32DataWritten;
+ IMG_UINT32 ui32Marker; /*!< marker for file splitting */
+ IMG_UINT32 ui32InitPhaseWOff; /*!< snapshot offset for init phase end for follow-on pdump */
+ IMG_CHAR szName[30]; /* Give this a size, some compilers don't like [] */
+} DBG_STREAM,*PDBG_STREAM;
+
+/*
+ * Allows dbgdrv to notify services when events happen, e.g. pdump.exe starts.
+ * (better than resetting psDevInfo->psKernelCCBInfo->ui32CCBDumpWOff = 0
+ * in SGXGetClientInfoKM.)
+ */
+typedef struct _DBGKM_CONNECT_NOTIFIER_
+{
+ IMG_VOID (IMG_CALLCONV *pfnConnectNotifier) (IMG_VOID);
+} DBGKM_CONNECT_NOTIFIER, *PDBGKM_CONNECT_NOTIFIER;
+
+/*****************************************************************************
+ Kernel mode service table
+*****************************************************************************/
+typedef struct _DBGKM_SERVICE_TABLE_
+{
+ IMG_UINT32 ui32Size;
+ IMG_VOID * (IMG_CALLCONV *pfnCreateStream) (IMG_CHAR * pszName,IMG_UINT32 ui32CapMode,IMG_UINT32 ui32OutMode,IMG_UINT32 ui32Flags,IMG_UINT32 ui32Pages);
+ IMG_VOID (IMG_CALLCONV *pfnDestroyStream) (PDBG_STREAM psStream);
+ IMG_VOID * (IMG_CALLCONV *pfnFindStream) (IMG_CHAR * pszName, IMG_BOOL bResetInitBuffer);
+ IMG_UINT32 (IMG_CALLCONV *pfnWriteString) (PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level);
+ IMG_UINT32 (IMG_CALLCONV *pfnReadString) (PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Limit);
+ IMG_UINT32 (IMG_CALLCONV *pfnWriteBIN) (PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+ IMG_UINT32 (IMG_CALLCONV *pfnReadBIN) (PDBG_STREAM psStream,IMG_BOOL bReadInitBuffer, IMG_UINT32 ui32OutBufferSize,IMG_UINT8 *pui8OutBuf);
+ IMG_VOID (IMG_CALLCONV *pfnSetCaptureMode) (PDBG_STREAM psStream,IMG_UINT32 ui32CapMode,IMG_UINT32 ui32Start,IMG_UINT32 ui32Stop,IMG_UINT32 ui32SampleRate);
+ IMG_VOID (IMG_CALLCONV *pfnSetOutputMode) (PDBG_STREAM psStream,IMG_UINT32 ui32OutMode);
+ IMG_VOID (IMG_CALLCONV *pfnSetDebugLevel) (PDBG_STREAM psStream,IMG_UINT32 ui32DebugLevel);
+ IMG_VOID (IMG_CALLCONV *pfnSetFrame) (PDBG_STREAM psStream,IMG_UINT32 ui32Frame);
+ IMG_UINT32 (IMG_CALLCONV *pfnGetFrame) (PDBG_STREAM psStream);
+ IMG_VOID (IMG_CALLCONV *pfnOverrideMode) (PDBG_STREAM psStream,IMG_UINT32 ui32Mode);
+ IMG_VOID (IMG_CALLCONV *pfnDefaultMode) (PDBG_STREAM psStream);
+ IMG_UINT32 (IMG_CALLCONV *pfnDBGDrivWrite2) (PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+ IMG_UINT32 (IMG_CALLCONV *pfnWriteStringCM) (PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level);
+ IMG_UINT32 (IMG_CALLCONV *pfnWriteBINCM) (PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+ IMG_VOID (IMG_CALLCONV *pfnSetMarker) (PDBG_STREAM psStream,IMG_UINT32 ui32Marker);
+ IMG_UINT32 (IMG_CALLCONV *pfnGetMarker) (PDBG_STREAM psStream);
+ IMG_VOID (IMG_CALLCONV *pfnStartInitPhase) (PDBG_STREAM psStream);
+ IMG_VOID (IMG_CALLCONV *pfnStopInitPhase) (PDBG_STREAM psStream);
+ IMG_BOOL (IMG_CALLCONV *pfnIsCaptureFrame) (PDBG_STREAM psStream, IMG_BOOL bCheckPreviousFrame);
+ IMG_UINT32 (IMG_CALLCONV *pfnWriteLF) (PDBG_STREAM psStream, IMG_UINT8 *pui8InBuf, IMG_UINT32 ui32InBuffSize, IMG_UINT32 ui32Level, IMG_UINT32 ui32Flags);
+ IMG_UINT32 (IMG_CALLCONV *pfnReadLF) (PDBG_STREAM psStream, IMG_UINT32 ui32OutBuffSize, IMG_UINT8 *pui8OutBuf);
+ IMG_UINT32 (IMG_CALLCONV *pfnGetStreamOffset) (PDBG_STREAM psStream);
+ IMG_VOID (IMG_CALLCONV *pfnSetStreamOffset) (PDBG_STREAM psStream, IMG_UINT32 ui32StreamOffset);
+ IMG_BOOL (IMG_CALLCONV *pfnIsLastCaptureFrame) (PDBG_STREAM psStream);
+ IMG_VOID (IMG_CALLCONV *pfnWaitForEvent) (DBG_EVENT eEvent);
+ IMG_VOID (IMG_CALLCONV *pfnSetConnectNotifier) (DBGKM_CONNECT_NOTIFIER fn_notifier);
+ IMG_UINT32 (IMG_CALLCONV *pfnWritePersist) (PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+} DBGKM_SERVICE_TABLE, *PDBGKM_SERVICE_TABLE;
+
+
+#endif
+/*****************************************************************************
+ End of file (DBGDRVIF.H)
+*****************************************************************************/
diff --git a/drivers/gpu/pvr/device.h b/drivers/gpu/pvr/device.h
new file mode 100644
index 0000000..9df2c73
--- /dev/null
+++ b/drivers/gpu/pvr/device.h
@@ -0,0 +1,323 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __DEVICE_H__
+#define __DEVICE_H__
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#include "ra.h"
+#include "resman.h"
+
+typedef struct _BM_CONTEXT_ BM_CONTEXT;
+
+typedef struct _MMU_HEAP_ MMU_HEAP;
+typedef struct _MMU_CONTEXT_ MMU_CONTEXT;
+
+#define PVRSRV_BACKINGSTORE_SYSMEM_CONTIG (1<<(PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT+0))
+#define PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG (1<<(PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT+1))
+#define PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG (1<<(PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT+2))
+#define PVRSRV_BACKINGSTORE_LOCALMEM_NONCONTIG (1<<(PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT+3))
+
+typedef IMG_UINT32 DEVICE_MEMORY_HEAP_TYPE;
+#define DEVICE_MEMORY_HEAP_PERCONTEXT 0
+#define DEVICE_MEMORY_HEAP_KERNEL 1
+#define DEVICE_MEMORY_HEAP_SHARED 2
+#define DEVICE_MEMORY_HEAP_SHARED_EXPORTED 3
+
+#define PVRSRV_DEVICE_NODE_FLAGS_PORT80DISPLAY 1
+#define PVRSRV_DEVICE_NODE_FLAGS_MMU_OPT_INV 2
+
+typedef struct _DEVICE_MEMORY_HEAP_INFO_
+{
+
+ IMG_UINT32 ui32HeapID;
+
+
+ IMG_CHAR *pszName;
+
+
+ IMG_CHAR *pszBSName;
+
+
+ IMG_DEV_VIRTADDR sDevVAddrBase;
+
+
+ IMG_UINT32 ui32HeapSize;
+
+
+ IMG_UINT32 ui32Attribs;
+
+
+ DEVICE_MEMORY_HEAP_TYPE DevMemHeapType;
+
+
+ IMG_HANDLE hDevMemHeap;
+
+
+ RA_ARENA *psLocalDevMemArena;
+
+
+ IMG_UINT32 ui32DataPageSize;
+
+ IMG_UINT32 ui32XTileStride;
+
+} DEVICE_MEMORY_HEAP_INFO;
+
+typedef struct _DEVICE_MEMORY_INFO_
+{
+
+ IMG_UINT32 ui32AddressSpaceSizeLog2;
+
+
+
+
+ IMG_UINT32 ui32Flags;
+
+
+ IMG_UINT32 ui32HeapCount;
+
+
+ IMG_UINT32 ui32SyncHeapID;
+
+
+ IMG_UINT32 ui32MappingHeapID;
+
+
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+
+
+ BM_CONTEXT *pBMKernelContext;
+
+
+ BM_CONTEXT *pBMContext;
+
+} DEVICE_MEMORY_INFO;
+
+
+typedef struct DEV_ARENA_DESCRIPTOR_TAG
+{
+ IMG_UINT32 ui32HeapID;
+
+ IMG_CHAR *pszName;
+
+ IMG_DEV_VIRTADDR BaseDevVAddr;
+
+ IMG_UINT32 ui32Size;
+
+ DEVICE_MEMORY_HEAP_TYPE DevMemHeapType;
+
+
+ IMG_UINT32 ui32DataPageSize;
+
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeapInfo;
+
+} DEV_ARENA_DESCRIPTOR;
+
+
+typedef struct _PDUMP_MMU_ATTRIB_
+{
+ PVRSRV_DEVICE_IDENTIFIER sDevId;
+
+ IMG_CHAR *pszPDRegRegion;
+
+
+ IMG_UINT32 ui32DataPageMask;
+
+
+ IMG_UINT32 ui32PTEValid;
+ IMG_UINT32 ui32PTSize;
+ IMG_UINT32 ui32PTEAlignShift;
+
+
+ IMG_UINT32 ui32PDEMask;
+ IMG_UINT32 ui32PDEAlignShift;
+
+} PDUMP_MMU_ATTRIB;
+
+typedef struct _SYS_DATA_TAG_ *PSYS_DATA;
+
+typedef struct _PVRSRV_DEVICE_NODE_
+{
+ PVRSRV_DEVICE_IDENTIFIER sDevId;
+ IMG_UINT32 ui32RefCount;
+
+
+
+
+ PVRSRV_ERROR (*pfnInitDevice) (IMG_VOID*);
+
+ PVRSRV_ERROR (*pfnDeInitDevice) (IMG_VOID*);
+
+
+ PVRSRV_ERROR (*pfnInitDeviceCompatCheck) (struct _PVRSRV_DEVICE_NODE_*);
+
+
+ PVRSRV_ERROR (*pfnMMUInitialise)(struct _PVRSRV_DEVICE_NODE_*, MMU_CONTEXT**, IMG_DEV_PHYADDR*);
+ IMG_VOID (*pfnMMUFinalise)(MMU_CONTEXT*);
+ IMG_VOID (*pfnMMUInsertHeap)(MMU_CONTEXT*, MMU_HEAP*);
+ MMU_HEAP* (*pfnMMUCreate)(MMU_CONTEXT*,DEV_ARENA_DESCRIPTOR*,RA_ARENA**,PDUMP_MMU_ATTRIB **ppsMMUAttrib);
+ IMG_VOID (*pfnMMUDelete)(MMU_HEAP*);
+ IMG_BOOL (*pfnMMUAlloc)(MMU_HEAP*pMMU,
+ IMG_SIZE_T uSize,
+ IMG_SIZE_T *pActualSize,
+ IMG_UINT32 uFlags,
+ IMG_UINT32 uDevVAddrAlignment,
+ IMG_DEV_VIRTADDR *pDevVAddr);
+ IMG_VOID (*pfnMMUFree)(MMU_HEAP*,IMG_DEV_VIRTADDR,IMG_UINT32);
+ IMG_VOID (*pfnMMUEnable)(MMU_HEAP*);
+ IMG_VOID (*pfnMMUDisable)(MMU_HEAP*);
+ IMG_VOID (*pfnMMUMapPages)(MMU_HEAP *pMMU,
+ IMG_DEV_VIRTADDR devVAddr,
+ IMG_SYS_PHYADDR SysPAddr,
+ IMG_SIZE_T uSize,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag);
+ IMG_VOID (*pfnMMUMapShadow)(MMU_HEAP *pMMU,
+ IMG_DEV_VIRTADDR MapBaseDevVAddr,
+ IMG_SIZE_T uSize,
+ IMG_CPU_VIRTADDR CpuVAddr,
+ IMG_HANDLE hOSMemHandle,
+ IMG_DEV_VIRTADDR *pDevVAddr,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag);
+ IMG_VOID (*pfnMMUUnmapPages)(MMU_HEAP *pMMU,
+ IMG_DEV_VIRTADDR dev_vaddr,
+ IMG_UINT32 ui32PageCount,
+ IMG_HANDLE hUniqueTag);
+
+ IMG_VOID (*pfnMMUMapScatter)(MMU_HEAP *pMMU,
+ IMG_DEV_VIRTADDR DevVAddr,
+ IMG_SYS_PHYADDR *psSysAddr,
+ IMG_SIZE_T uSize,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag);
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+ IMG_BOOL (*pfnMMUIsHeapShared)(MMU_HEAP *);
+#endif
+ IMG_DEV_PHYADDR (*pfnMMUGetPhysPageAddr)(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR sDevVPageAddr);
+ IMG_DEV_PHYADDR (*pfnMMUGetPDDevPAddr)(MMU_CONTEXT *pMMUContext);
+ IMG_VOID (*pfnMMUGetCacheFlushRange)(MMU_CONTEXT *pMMUContext, IMG_UINT32 *pui32RangeMask);
+ IMG_VOID (*pfnMMUGetPDPhysAddr)(MMU_CONTEXT *pMMUContext, IMG_DEV_PHYADDR *psDevPAddr);
+
+
+ PVRSRV_ERROR (*pfnAllocMemTilingRange)(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32TilingStride,
+ IMG_UINT32 *pui32RangeIndex);
+ PVRSRV_ERROR (*pfnFreeMemTilingRange)(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode,
+ IMG_UINT32 ui32RangeIndex);
+
+
+ IMG_BOOL (*pfnDeviceISR)(IMG_VOID*);
+
+ IMG_VOID *pvISRData;
+
+ IMG_UINT32 ui32SOCInterruptBit;
+
+ IMG_VOID (*pfnDeviceMISR)(IMG_VOID*);
+
+
+ IMG_VOID (*pfnDeviceCommandComplete)(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode);
+
+ IMG_BOOL bReProcessDeviceCommandComplete;
+
+ IMG_VOID (*pfnCacheInvalidate)(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode);
+
+
+ DEVICE_MEMORY_INFO sDevMemoryInfo;
+
+
+ IMG_VOID *pvDevice;
+ IMG_UINT32 ui32pvDeviceSize;
+
+
+ PRESMAN_CONTEXT hResManContext;
+
+
+ PSYS_DATA psSysData;
+
+
+ RA_ARENA *psLocalDevMemArena;
+
+ IMG_UINT32 ui32Flags;
+
+ struct _PVRSRV_DEVICE_NODE_ *psNext;
+ struct _PVRSRV_DEVICE_NODE_ **ppsThis;
+
+#if defined(PDUMP)
+
+ PVRSRV_ERROR (*pfnPDumpInitDevice)(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode);
+
+ IMG_UINT32 (*pfnMMUGetContextID)(IMG_HANDLE hDevMemContext);
+#endif
+} PVRSRV_DEVICE_NODE;
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVRegisterDevice(PSYS_DATA psSysData,
+ PVRSRV_ERROR (*pfnRegisterDevice)(PVRSRV_DEVICE_NODE*),
+ IMG_UINT32 ui32SOCInterruptBit,
+ IMG_UINT32 *pui32DeviceIndex );
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInitialiseDevice(IMG_UINT32 ui32DevIndex);
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFinaliseSystem(IMG_BOOL bInitSuccesful);
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDeinitialiseDevice(IMG_UINT32 ui32DevIndex);
+
+#if !defined(USE_CODE)
+
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PollForValueKM(volatile IMG_UINT32* pui32LinMemAddr,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ IMG_UINT32 ui32Timeoutus,
+ IMG_UINT32 ui32PollPeriodus,
+ IMG_BOOL bAllowPreemption);
+
+#endif
+
+
+#if defined (USING_ISR_INTERRUPTS)
+PVRSRV_ERROR IMG_CALLCONV PollForInterruptKM(IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ IMG_UINT32 ui32Waitus,
+ IMG_UINT32 ui32Tries);
+#endif
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInit(PSYS_DATA psSysData);
+IMG_VOID IMG_CALLCONV PVRSRVDeInit(PSYS_DATA psSysData);
+IMG_BOOL IMG_CALLCONV PVRSRVDeviceLISR(PVRSRV_DEVICE_NODE *psDeviceNode);
+IMG_BOOL IMG_CALLCONV PVRSRVSystemLISR(IMG_VOID *pvSysData);
+IMG_VOID IMG_CALLCONV PVRSRVMISR(IMG_VOID *pvSysData);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/pvr/deviceclass.c b/drivers/gpu/pvr/deviceclass.c
new file mode 100644
index 0000000..233ac08
--- /dev/null
+++ b/drivers/gpu/pvr/deviceclass.c
@@ -0,0 +1,2371 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "kernelbuffer.h"
+#include "kerneldisplay.h"
+#include "pvr_bridge_km.h"
+#include "pdump_km.h"
+#include "deviceid.h"
+
+#include "lists.h"
+
+PVRSRV_ERROR AllocateDeviceID(SYS_DATA *psSysData, IMG_UINT32 *pui32DevID);
+PVRSRV_ERROR FreeDeviceID(SYS_DATA *psSysData, IMG_UINT32 ui32DevID);
+
+#if defined(SUPPORT_MISR_IN_THREAD)
+void OSVSyncMISR(IMG_HANDLE, IMG_BOOL);
+#endif
+
+#if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS)
+IMG_VOID PVRSRVFreeCommandCompletePacketKM(IMG_HANDLE hCmdCookie,
+ IMG_BOOL bScheduleMISR);
+#endif
+typedef struct PVRSRV_DC_SRV2DISP_KMJTABLE_TAG *PPVRSRV_DC_SRV2DISP_KMJTABLE;
+
+typedef struct PVRSRV_DC_BUFFER_TAG
+{
+
+ PVRSRV_DEVICECLASS_BUFFER sDeviceClassBuffer;
+
+ struct PVRSRV_DISPLAYCLASS_INFO_TAG *psDCInfo;
+ struct PVRSRV_DC_SWAPCHAIN_TAG *psSwapChain;
+} PVRSRV_DC_BUFFER;
+
+typedef struct PVRSRV_DC_SWAPCHAIN_TAG
+{
+ IMG_HANDLE hExtSwapChain;
+ IMG_UINT32 ui32SwapChainID;
+ IMG_UINT32 ui32RefCount;
+ IMG_UINT32 ui32Flags;
+ PVRSRV_QUEUE_INFO *psQueue;
+ PVRSRV_DC_BUFFER asBuffer[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
+ IMG_UINT32 ui32BufferCount;
+ PVRSRV_DC_BUFFER *psLastFlipBuffer;
+ IMG_UINT32 ui32MinSwapInterval;
+ IMG_UINT32 ui32MaxSwapInterval;
+#if !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED)
+ PVRSRV_KERNEL_SYNC_INFO **ppsLastSyncInfos;
+ IMG_UINT32 ui32LastNumSyncInfos;
+#endif
+ struct PVRSRV_DISPLAYCLASS_INFO_TAG *psDCInfo;
+ struct PVRSRV_DC_SWAPCHAIN_TAG *psNext;
+} PVRSRV_DC_SWAPCHAIN;
+
+
+typedef struct PVRSRV_DC_SWAPCHAIN_REF_TAG
+{
+ struct PVRSRV_DC_SWAPCHAIN_TAG *psSwapChain;
+ IMG_HANDLE hResItem;
+} PVRSRV_DC_SWAPCHAIN_REF;
+
+
+typedef struct PVRSRV_DISPLAYCLASS_INFO_TAG
+{
+ IMG_UINT32 ui32RefCount;
+ IMG_UINT32 ui32DeviceID;
+ IMG_HANDLE hExtDevice;
+ PPVRSRV_DC_SRV2DISP_KMJTABLE psFuncTable;
+ IMG_HANDLE hDevMemContext;
+ PVRSRV_DC_BUFFER sSystemBuffer;
+ struct PVRSRV_DC_SWAPCHAIN_TAG *psDCSwapChainShared;
+} PVRSRV_DISPLAYCLASS_INFO;
+
+
+typedef struct PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO_TAG
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PRESMAN_ITEM hResItem;
+} PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO;
+
+
+typedef struct PVRSRV_BC_SRV2BUFFER_KMJTABLE_TAG *PPVRSRV_BC_SRV2BUFFER_KMJTABLE;
+
+typedef struct PVRSRV_BC_BUFFER_TAG
+{
+
+ PVRSRV_DEVICECLASS_BUFFER sDeviceClassBuffer;
+
+ struct PVRSRV_BUFFERCLASS_INFO_TAG *psBCInfo;
+} PVRSRV_BC_BUFFER;
+
+
+typedef struct PVRSRV_BUFFERCLASS_INFO_TAG
+{
+ IMG_UINT32 ui32RefCount;
+ IMG_UINT32 ui32DeviceID;
+ IMG_HANDLE hExtDevice;
+ PPVRSRV_BC_SRV2BUFFER_KMJTABLE psFuncTable;
+ IMG_HANDLE hDevMemContext;
+
+ IMG_UINT32 ui32BufferCount;
+ PVRSRV_BC_BUFFER *psBuffer;
+
+} PVRSRV_BUFFERCLASS_INFO;
+
+
+typedef struct PVRSRV_BUFFERCLASS_PERCONTEXT_INFO_TAG
+{
+ PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+ IMG_HANDLE hResItem;
+} PVRSRV_BUFFERCLASS_PERCONTEXT_INFO;
+
+
+static PVRSRV_DISPLAYCLASS_INFO* DCDeviceHandleToDCInfo (IMG_HANDLE hDeviceKM)
+{
+ PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
+
+ psDCPerContextInfo = (PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *)hDeviceKM;
+
+ return psDCPerContextInfo->psDCInfo;
+}
+
+
+static PVRSRV_BUFFERCLASS_INFO* BCDeviceHandleToBCInfo (IMG_HANDLE hDeviceKM)
+{
+ PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
+
+ psBCPerContextInfo = (PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *)hDeviceKM;
+
+ return psBCPerContextInfo->psBCInfo;
+}
+
+static IMG_VOID PVRSRVEnumerateDCKM_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+ IMG_UINT *pui32DevCount;
+ IMG_UINT32 **ppui32DevID;
+ PVRSRV_DEVICE_CLASS peDeviceClass;
+
+ pui32DevCount = va_arg(va, IMG_UINT*);
+ ppui32DevID = va_arg(va, IMG_UINT32**);
+ peDeviceClass = va_arg(va, PVRSRV_DEVICE_CLASS);
+
+ if ((psDeviceNode->sDevId.eDeviceClass == peDeviceClass)
+ && (psDeviceNode->sDevId.eDeviceType == PVRSRV_DEVICE_TYPE_EXT))
+ {
+ (*pui32DevCount)++;
+ if(*ppui32DevID)
+ {
+ *(*ppui32DevID)++ = psDeviceNode->sDevId.ui32DeviceIndex;
+ }
+ }
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVEnumerateDCKM (PVRSRV_DEVICE_CLASS DeviceClass,
+ IMG_UINT32 *pui32DevCount,
+ IMG_UINT32 *pui32DevID )
+{
+
+ IMG_UINT ui32DevCount = 0;
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+
+ List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
+ &PVRSRVEnumerateDCKM_ForEachVaCb,
+ &ui32DevCount,
+ &pui32DevID,
+ DeviceClass);
+
+ if(pui32DevCount)
+ {
+ *pui32DevCount = ui32DevCount;
+ }
+ else if(pui32DevID == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumerateDCKM: Invalid parameters"));
+ return (PVRSRV_ERROR_INVALID_PARAMS);
+ }
+
+ return PVRSRV_OK;
+}
+
+
+static
+PVRSRV_ERROR PVRSRVRegisterDCDeviceKM (PVRSRV_DC_SRV2DISP_KMJTABLE *psFuncTable,
+ IMG_UINT32 *pui32DeviceID)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo = IMG_NULL;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ SYS_DATA *psSysData;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SysAcquireData(&psSysData);
+
+
+
+
+
+ if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*psDCInfo),
+ (IMG_VOID **)&psDCInfo, IMG_NULL,
+ "Display Class Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDCDeviceKM: Failed psDCInfo alloc"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OSMemSet (psDCInfo, 0, sizeof(*psDCInfo));
+
+
+ if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE),
+ (IMG_VOID **)&psDCInfo->psFuncTable, IMG_NULL,
+ "Function table for SRVKM->DISPLAY") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDCDeviceKM: Failed psFuncTable alloc"));
+ goto ErrorExit;
+ }
+ OSMemSet (psDCInfo->psFuncTable, 0, sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE));
+
+
+ *psDCInfo->psFuncTable = *psFuncTable;
+
+
+ if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DEVICE_NODE),
+ (IMG_VOID **)&psDeviceNode, IMG_NULL,
+ "Device Node") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDCDeviceKM: Failed psDeviceNode alloc"));
+ goto ErrorExit;
+ }
+ OSMemSet (psDeviceNode, 0, sizeof(PVRSRV_DEVICE_NODE));
+
+ psDeviceNode->pvDevice = (IMG_VOID*)psDCInfo;
+ psDeviceNode->ui32pvDeviceSize = sizeof(*psDCInfo);
+ psDeviceNode->ui32RefCount = 1;
+ psDeviceNode->sDevId.eDeviceType = PVRSRV_DEVICE_TYPE_EXT;
+ psDeviceNode->sDevId.eDeviceClass = PVRSRV_DEVICE_CLASS_DISPLAY;
+ psDeviceNode->psSysData = psSysData;
+
+
+ if (AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed to allocate Device ID"));
+ goto ErrorExit;
+ }
+ psDCInfo->ui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
+ if (pui32DeviceID)
+ {
+ *pui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
+ }
+
+
+ SysRegisterExternalDevice(psDeviceNode);
+
+
+ List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList, psDeviceNode);
+
+ return PVRSRV_OK;
+
+ErrorExit:
+
+ if(psDCInfo->psFuncTable)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE), psDCInfo->psFuncTable, IMG_NULL);
+ psDCInfo->psFuncTable = IMG_NULL;
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_INFO), psDCInfo, IMG_NULL);
+
+
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+}
+
+static PVRSRV_ERROR PVRSRVRemoveDCDeviceKM(IMG_UINT32 ui32DevIndex)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+
+ SysAcquireData(&psSysData);
+
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE*)
+ List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ &MatchDeviceKM_AnyVaCb,
+ ui32DevIndex,
+ IMG_FALSE,
+ PVRSRV_DEVICE_CLASS_DISPLAY);
+ if (!psDeviceNode)
+ {
+
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveDCDeviceKM: requested device %d not present", ui32DevIndex));
+ return PVRSRV_ERROR_NO_DEVICENODE_FOUND;
+ }
+
+
+ psDCInfo = (PVRSRV_DISPLAYCLASS_INFO*)psDeviceNode->pvDevice;
+
+
+
+
+ if(psDCInfo->ui32RefCount == 0)
+ {
+
+
+ List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode);
+
+
+ SysRemoveExternalDevice(psDeviceNode);
+
+
+
+
+ PVR_ASSERT(psDCInfo->ui32RefCount == 0);
+ (IMG_VOID)FreeDeviceID(psSysData, ui32DevIndex);
+ (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE), psDCInfo->psFuncTable, IMG_NULL);
+ psDCInfo->psFuncTable = IMG_NULL;
+ (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_INFO), psDCInfo, IMG_NULL);
+
+ (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL);
+
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveDCDeviceKM: failed as %d Services DC API connections are still open", psDCInfo->ui32RefCount));
+ return PVRSRV_ERROR_UNABLE_TO_REMOVE_DEVICE;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+static
+PVRSRV_ERROR PVRSRVRegisterBCDeviceKM (PVRSRV_BC_SRV2BUFFER_KMJTABLE *psFuncTable,
+ IMG_UINT32 *pui32DeviceID)
+{
+ PVRSRV_BUFFERCLASS_INFO *psBCInfo = IMG_NULL;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ SYS_DATA *psSysData;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SysAcquireData(&psSysData);
+
+
+
+
+
+ if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*psBCInfo),
+ (IMG_VOID **)&psBCInfo, IMG_NULL,
+ "Buffer Class Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed psBCInfo alloc"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OSMemSet (psBCInfo, 0, sizeof(*psBCInfo));
+
+
+ if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE),
+ (IMG_VOID **)&psBCInfo->psFuncTable, IMG_NULL,
+ "Function table for SRVKM->BUFFER") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed psFuncTable alloc"));
+ goto ErrorExit;
+ }
+ OSMemSet (psBCInfo->psFuncTable, 0, sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE));
+
+
+ *psBCInfo->psFuncTable = *psFuncTable;
+
+
+ if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DEVICE_NODE),
+ (IMG_VOID **)&psDeviceNode, IMG_NULL,
+ "Device Node") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed psDeviceNode alloc"));
+ goto ErrorExit;
+ }
+ OSMemSet (psDeviceNode, 0, sizeof(PVRSRV_DEVICE_NODE));
+
+ psDeviceNode->pvDevice = (IMG_VOID*)psBCInfo;
+ psDeviceNode->ui32pvDeviceSize = sizeof(*psBCInfo);
+ psDeviceNode->ui32RefCount = 1;
+ psDeviceNode->sDevId.eDeviceType = PVRSRV_DEVICE_TYPE_EXT;
+ psDeviceNode->sDevId.eDeviceClass = PVRSRV_DEVICE_CLASS_BUFFER;
+ psDeviceNode->psSysData = psSysData;
+
+
+ if (AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed to allocate Device ID"));
+ goto ErrorExit;
+ }
+ psBCInfo->ui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
+ if (pui32DeviceID)
+ {
+ *pui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
+ }
+
+
+ List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList, psDeviceNode);
+
+ return PVRSRV_OK;
+
+ErrorExit:
+
+ if(psBCInfo->psFuncTable)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PPVRSRV_BC_SRV2BUFFER_KMJTABLE), psBCInfo->psFuncTable, IMG_NULL);
+ psBCInfo->psFuncTable = IMG_NULL;
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_INFO), psBCInfo, IMG_NULL);
+
+
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+}
+
+
+static PVRSRV_ERROR PVRSRVRemoveBCDeviceKM(IMG_UINT32 ui32DevIndex)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_DEVICE_NODE *psDevNode;
+ PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+
+ SysAcquireData(&psSysData);
+
+
+ psDevNode = (PVRSRV_DEVICE_NODE*)
+ List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ &MatchDeviceKM_AnyVaCb,
+ ui32DevIndex,
+ IMG_FALSE,
+ PVRSRV_DEVICE_CLASS_BUFFER);
+
+ if (!psDevNode)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveBCDeviceKM: requested device %d not present", ui32DevIndex));
+ return PVRSRV_ERROR_NO_DEVICENODE_FOUND;
+ }
+
+
+
+ psBCInfo = (PVRSRV_BUFFERCLASS_INFO*)psDevNode->pvDevice;
+
+
+
+
+ if(psBCInfo->ui32RefCount == 0)
+ {
+
+
+ List_PVRSRV_DEVICE_NODE_Remove(psDevNode);
+
+
+
+
+ (IMG_VOID)FreeDeviceID(psSysData, ui32DevIndex);
+
+
+ (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE), psBCInfo->psFuncTable, IMG_NULL);
+ psBCInfo->psFuncTable = IMG_NULL;
+ (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_INFO), psBCInfo, IMG_NULL);
+
+ (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE), psDevNode, IMG_NULL);
+
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveBCDeviceKM: failed as %d Services BC API connections are still open", psBCInfo->ui32RefCount));
+ return PVRSRV_ERROR_UNABLE_TO_REMOVE_DEVICE;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVCloseDCDeviceKM (IMG_HANDLE hDeviceKM,
+ IMG_BOOL bResManCallback)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
+
+ PVR_UNREFERENCED_PARAMETER(bResManCallback);
+
+ psDCPerContextInfo = (PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *)hDeviceKM;
+
+
+ eError = ResManFreeResByPtr(psDCPerContextInfo->hResItem, CLEANUP_WITH_POLL);
+
+ return eError;
+}
+
+
+static PVRSRV_ERROR CloseDCDeviceCallBack(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param,
+ IMG_BOOL bDummy)
+{
+ PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+ PVR_UNREFERENCED_PARAMETER(bDummy);
+
+ psDCPerContextInfo = (PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *)pvParam;
+ psDCInfo = psDCPerContextInfo->psDCInfo;
+
+ if(psDCInfo->sSystemBuffer.sDeviceClassBuffer.ui32MemMapRefCount != 0)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"CloseDCDeviceCallBack: system buffer (0x%p) still mapped (refcount = %d)",
+ &psDCInfo->sSystemBuffer.sDeviceClassBuffer,
+ psDCInfo->sSystemBuffer.sDeviceClassBuffer.ui32MemMapRefCount));
+#if 0
+
+ return PVRSRV_ERROR_STILL_MAPPED;
+#endif
+ }
+
+ psDCInfo->ui32RefCount--;
+ if(psDCInfo->ui32RefCount == 0)
+ {
+
+ psDCInfo->psFuncTable->pfnCloseDCDevice(psDCInfo->hExtDevice);
+
+ PVRSRVKernelSyncInfoDecRef(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL);
+
+ psDCInfo->hDevMemContext = IMG_NULL;
+ psDCInfo->hExtDevice = IMG_NULL;
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO), psDCPerContextInfo, IMG_NULL);
+
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVOpenDCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_UINT32 ui32DeviceID,
+ IMG_HANDLE hDevCookie,
+ IMG_HANDLE *phDeviceKM)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ SYS_DATA *psSysData;
+ PVRSRV_ERROR eError;
+
+ if(!phDeviceKM || !hDevCookie)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Invalid params"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ SysAcquireData(&psSysData);
+
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE*)
+ List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ &MatchDeviceKM_AnyVaCb,
+ ui32DeviceID,
+ IMG_FALSE,
+ PVRSRV_DEVICE_CLASS_DISPLAY);
+ if (!psDeviceNode)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: no devnode matching index %d", ui32DeviceID));
+ return PVRSRV_ERROR_NO_DEVICENODE_FOUND;
+ }
+ psDCInfo = (PVRSRV_DISPLAYCLASS_INFO*)psDeviceNode->pvDevice;
+
+
+
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*psDCPerContextInfo),
+ (IMG_VOID **)&psDCPerContextInfo, IMG_NULL,
+ "Display Class per Context Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed psDCPerContextInfo alloc"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OSMemSet(psDCPerContextInfo, 0, sizeof(*psDCPerContextInfo));
+
+ if(psDCInfo->ui32RefCount++ == 0)
+ {
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
+
+
+ psDCInfo->hDevMemContext = (IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext;
+
+
+ eError = PVRSRVAllocSyncInfoKM(IMG_NULL,
+ (IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext,
+ &psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed sync info alloc"));
+ psDCInfo->ui32RefCount--;
+ return eError;
+ }
+
+
+ eError = psDCInfo->psFuncTable->pfnOpenDCDevice(ui32DeviceID,
+ &psDCInfo->hExtDevice,
+ (PVRSRV_SYNC_DATA*)psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed to open external DC device"));
+ psDCInfo->ui32RefCount--;
+ PVRSRVKernelSyncInfoDecRef(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL);
+ return eError;
+ }
+
+ psDCPerContextInfo->psDCInfo = psDCInfo;
+ eError = PVRSRVGetDCSystemBufferKM(psDCPerContextInfo, IMG_NULL);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed to get system buffer"));
+ psDCInfo->ui32RefCount--;
+ PVRSRVKernelSyncInfoDecRef(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL);
+ return eError;
+ }
+ psDCInfo->sSystemBuffer.sDeviceClassBuffer.ui32MemMapRefCount = 0;
+ }
+ else
+ {
+ psDCPerContextInfo->psDCInfo = psDCInfo;
+ }
+
+ psDCPerContextInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_DISPLAYCLASS_DEVICE,
+ psDCPerContextInfo,
+ 0,
+ &CloseDCDeviceCallBack);
+
+
+ *phDeviceKM = (IMG_HANDLE)psDCPerContextInfo;
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVEnumDCFormatsKM (IMG_HANDLE hDeviceKM,
+ IMG_UINT32 *pui32Count,
+ DISPLAY_FORMAT *psFormat)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+
+ if(!hDeviceKM || !pui32Count || !psFormat)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumDCFormatsKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+
+ return psDCInfo->psFuncTable->pfnEnumDCFormats(psDCInfo->hExtDevice, pui32Count, psFormat);
+}
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVEnumDCDimsKM (IMG_HANDLE hDeviceKM,
+ DISPLAY_FORMAT *psFormat,
+ IMG_UINT32 *pui32Count,
+ DISPLAY_DIMS *psDim)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+
+ if(!hDeviceKM || !pui32Count || !psFormat)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumDCDimsKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+
+ return psDCInfo->psFuncTable->pfnEnumDCDims(psDCInfo->hExtDevice, psFormat, pui32Count, psDim);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVGetDCSystemBufferKM (IMG_HANDLE hDeviceKM,
+ IMG_HANDLE *phBuffer)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ IMG_HANDLE hExtBuffer;
+
+ if(!hDeviceKM)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCSystemBufferKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+
+ eError = psDCInfo->psFuncTable->pfnGetDCSystemBuffer(psDCInfo->hExtDevice, &hExtBuffer);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCSystemBufferKM: Failed to get valid buffer handle from external driver"));
+ return eError;
+ }
+
+
+ psDCInfo->sSystemBuffer.sDeviceClassBuffer.pfnGetBufferAddr = psDCInfo->psFuncTable->pfnGetBufferAddr;
+ psDCInfo->sSystemBuffer.sDeviceClassBuffer.hDevMemContext = psDCInfo->hDevMemContext;
+ psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtDevice = psDCInfo->hExtDevice;
+ psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtBuffer = hExtBuffer;
+
+ psDCInfo->sSystemBuffer.psDCInfo = psDCInfo;
+
+
+ if (phBuffer)
+ {
+ *phBuffer = (IMG_HANDLE)&(psDCInfo->sSystemBuffer);
+ }
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVGetDCInfoKM (IMG_HANDLE hDeviceKM,
+ DISPLAY_INFO *psDisplayInfo)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_ERROR eError;
+
+ if(!hDeviceKM || !psDisplayInfo)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCInfoKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+
+ eError = psDCInfo->psFuncTable->pfnGetDCInfo(psDCInfo->hExtDevice, psDisplayInfo);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ if (psDisplayInfo->ui32MaxSwapChainBuffers > PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS)
+ {
+ psDisplayInfo->ui32MaxSwapChainBuffers = PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVDestroyDCSwapChainKM(IMG_HANDLE hSwapChainRef)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef;
+
+ if(!hSwapChainRef)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDestroyDCSwapChainKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psSwapChainRef = hSwapChainRef;
+
+ eError = ResManFreeResByPtr(psSwapChainRef->hResItem, CLEANUP_WITH_POLL);
+
+ return eError;
+}
+
+
+static PVRSRV_ERROR DestroyDCSwapChain(PVRSRV_DC_SWAPCHAIN *psSwapChain)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo = psSwapChain->psDCInfo;
+ IMG_UINT32 i;
+
+
+ if( psDCInfo->psDCSwapChainShared )
+ {
+ if( psDCInfo->psDCSwapChainShared == psSwapChain )
+ {
+ psDCInfo->psDCSwapChainShared = psSwapChain->psNext;
+ }
+ else
+ {
+ PVRSRV_DC_SWAPCHAIN *psCurrentSwapChain;
+ psCurrentSwapChain = psDCInfo->psDCSwapChainShared;
+ while( psCurrentSwapChain->psNext )
+ {
+ if( psCurrentSwapChain->psNext != psSwapChain )
+ {
+ psCurrentSwapChain = psCurrentSwapChain->psNext;
+ continue;
+ }
+ psCurrentSwapChain->psNext = psSwapChain->psNext;
+ break;
+ }
+ }
+ }
+
+
+ PVRSRVDestroyCommandQueueKM(psSwapChain->psQueue);
+
+
+ eError = psDCInfo->psFuncTable->pfnDestroyDCSwapChain(psDCInfo->hExtDevice,
+ psSwapChain->hExtSwapChain);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DestroyDCSwapChainCallBack: Failed to destroy DC swap chain"));
+ return eError;
+ }
+
+
+ for(i=0; i<psSwapChain->ui32BufferCount; i++)
+ {
+ if(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo)
+ {
+ PVRSRVKernelSyncInfoDecRef(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL);
+ }
+ }
+
+#if !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED)
+ if (psSwapChain->ppsLastSyncInfos)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_SYNC_INFO *) * psSwapChain->ui32LastNumSyncInfos,
+ psSwapChain->ppsLastSyncInfos, IMG_NULL);
+ }
+#endif
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN), psSwapChain, IMG_NULL);
+
+
+ return eError;
+}
+
+
+static PVRSRV_ERROR DestroyDCSwapChainRefCallBack(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param,
+ IMG_BOOL bDummy)
+{
+ PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef = (PVRSRV_DC_SWAPCHAIN_REF *) pvParam;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ IMG_UINT32 i;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+ PVR_UNREFERENCED_PARAMETER(bDummy);
+
+ for (i = 0; i < psSwapChainRef->psSwapChain->ui32BufferCount; i++)
+ {
+ if (psSwapChainRef->psSwapChain->asBuffer[i].sDeviceClassBuffer.ui32MemMapRefCount != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DestroyDCSwapChainRefCallBack: swapchain (0x%p) still mapped (ui32MemMapRefCount = %d)",
+ &psSwapChainRef->psSwapChain->asBuffer[i].sDeviceClassBuffer,
+ psSwapChainRef->psSwapChain->asBuffer[i].sDeviceClassBuffer.ui32MemMapRefCount));
+#if 0
+
+ return PVRSRV_ERROR_STILL_MAPPED;
+#endif
+ }
+ }
+
+ if(--psSwapChainRef->psSwapChain->ui32RefCount == 0)
+ {
+ eError = DestroyDCSwapChain(psSwapChainRef->psSwapChain);
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN_REF), psSwapChainRef, IMG_NULL);
+ return eError;
+}
+
+static PVRSRV_DC_SWAPCHAIN* PVRSRVFindSharedDCSwapChainKM(PVRSRV_DISPLAYCLASS_INFO *psDCInfo,
+ IMG_UINT32 ui32SwapChainID)
+{
+ PVRSRV_DC_SWAPCHAIN *psCurrentSwapChain;
+
+ for(psCurrentSwapChain = psDCInfo->psDCSwapChainShared;
+ psCurrentSwapChain;
+ psCurrentSwapChain = psCurrentSwapChain->psNext)
+ {
+ if(psCurrentSwapChain->ui32SwapChainID == ui32SwapChainID)
+ return psCurrentSwapChain;
+ }
+ return IMG_NULL;
+}
+
+static PVRSRV_ERROR PVRSRVCreateDCSwapChainRefKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ PVRSRV_DC_SWAPCHAIN *psSwapChain,
+ PVRSRV_DC_SWAPCHAIN_REF **ppsSwapChainRef)
+{
+ PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef = IMG_NULL;
+
+
+ if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DC_SWAPCHAIN_REF),
+ (IMG_VOID **)&psSwapChainRef, IMG_NULL,
+ "Display Class Swapchain Reference") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainRefKM: Failed psSwapChainRef alloc"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OSMemSet (psSwapChainRef, 0, sizeof(PVRSRV_DC_SWAPCHAIN_REF));
+
+
+ psSwapChain->ui32RefCount++;
+
+
+ psSwapChainRef->psSwapChain = psSwapChain;
+ psSwapChainRef->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN_REF,
+ psSwapChainRef,
+ 0,
+ &DestroyDCSwapChainRefCallBack);
+ *ppsSwapChainRef = psSwapChainRef;
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVCreateDCSwapChainKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDeviceKM,
+ IMG_UINT32 ui32Flags,
+ DISPLAY_SURF_ATTRIBUTES *psDstSurfAttrib,
+ DISPLAY_SURF_ATTRIBUTES *psSrcSurfAttrib,
+ IMG_UINT32 ui32BufferCount,
+ IMG_UINT32 ui32OEMFlags,
+ IMG_HANDLE *phSwapChainRef,
+ IMG_UINT32 *pui32SwapChainID)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DC_SWAPCHAIN *psSwapChain = IMG_NULL;
+ PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef = IMG_NULL;
+ PVRSRV_SYNC_DATA *apsSyncData[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
+ PVRSRV_QUEUE_INFO *psQueue = IMG_NULL;
+ PVRSRV_ERROR eError;
+ IMG_UINT32 i;
+ DISPLAY_INFO sDisplayInfo;
+
+
+ if(!hDeviceKM
+ || !psDstSurfAttrib
+ || !psSrcSurfAttrib
+ || !phSwapChainRef
+ || !pui32SwapChainID)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if (ui32BufferCount > PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Too many buffers"));
+ return PVRSRV_ERROR_TOOMANYBUFFERS;
+ }
+
+ if (ui32BufferCount < 2)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Too few buffers"));
+ return PVRSRV_ERROR_TOO_FEW_BUFFERS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+ if( ui32Flags & PVRSRV_CREATE_SWAPCHAIN_QUERY )
+ {
+
+ psSwapChain = PVRSRVFindSharedDCSwapChainKM(psDCInfo, *pui32SwapChainID );
+ if( psSwapChain )
+ {
+
+ eError = PVRSRVCreateDCSwapChainRefKM(psPerProc,
+ psSwapChain,
+ &psSwapChainRef);
+ if( eError != PVRSRV_OK )
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Couldn't create swap chain reference"));
+ return eError;
+ }
+
+ *phSwapChainRef = (IMG_HANDLE)psSwapChainRef;
+ return PVRSRV_OK;
+ }
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: No shared SwapChain found for query"));
+ return PVRSRV_ERROR_FLIP_CHAIN_EXISTS;
+ }
+
+
+ if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DC_SWAPCHAIN),
+ (IMG_VOID **)&psSwapChain, IMG_NULL,
+ "Display Class Swapchain") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed psSwapChain alloc"));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ErrorExit;
+ }
+ OSMemSet (psSwapChain, 0, sizeof(PVRSRV_DC_SWAPCHAIN));
+
+
+ eError = PVRSRVCreateCommandQueueKM(1024, &psQueue);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed to create CmdQueue"));
+ goto ErrorExit;
+ }
+
+
+ psSwapChain->psQueue = psQueue;
+
+
+ for(i=0; i<ui32BufferCount; i++)
+ {
+ eError = PVRSRVAllocSyncInfoKM(IMG_NULL,
+ psDCInfo->hDevMemContext,
+ &psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed to alloc syninfo for psSwapChain"));
+ goto ErrorExit;
+ }
+
+
+ psSwapChain->asBuffer[i].sDeviceClassBuffer.pfnGetBufferAddr = psDCInfo->psFuncTable->pfnGetBufferAddr;
+ psSwapChain->asBuffer[i].sDeviceClassBuffer.hDevMemContext = psDCInfo->hDevMemContext;
+ psSwapChain->asBuffer[i].sDeviceClassBuffer.hExtDevice = psDCInfo->hExtDevice;
+
+
+ psSwapChain->asBuffer[i].psDCInfo = psDCInfo;
+ psSwapChain->asBuffer[i].psSwapChain = psSwapChain;
+
+
+ apsSyncData[i] = (PVRSRV_SYNC_DATA*)psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM;
+ }
+
+ psSwapChain->ui32BufferCount = ui32BufferCount;
+ psSwapChain->psDCInfo = psDCInfo;
+
+#if defined(PDUMP)
+ PDUMPCOMMENT("Allocate DC swap chain (SwapChainID == %u, BufferCount == %u)",
+ *pui32SwapChainID,
+ ui32BufferCount);
+ PDUMPCOMMENT(" Src surface dimensions == %u x %u",
+ psSrcSurfAttrib->sDims.ui32Width,
+ psSrcSurfAttrib->sDims.ui32Height);
+ PDUMPCOMMENT(" Dst surface dimensions == %u x %u",
+ psDstSurfAttrib->sDims.ui32Width,
+ psDstSurfAttrib->sDims.ui32Height);
+#endif
+
+ eError = psDCInfo->psFuncTable->pfnGetDCInfo(psDCInfo->hExtDevice, &sDisplayInfo);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed to get DC info"));
+ return eError;
+ }
+
+ psSwapChain->ui32MinSwapInterval = sDisplayInfo.ui32MinSwapInterval;
+ psSwapChain->ui32MaxSwapInterval = sDisplayInfo.ui32MaxSwapInterval;
+
+
+ eError = psDCInfo->psFuncTable->pfnCreateDCSwapChain(psDCInfo->hExtDevice,
+ ui32Flags,
+ psDstSurfAttrib,
+ psSrcSurfAttrib,
+ ui32BufferCount,
+ apsSyncData,
+ ui32OEMFlags,
+ &psSwapChain->hExtSwapChain,
+ &psSwapChain->ui32SwapChainID);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed to create 3rd party SwapChain"));
+ PDUMPCOMMENT("Swapchain allocation failed.");
+ goto ErrorExit;
+ }
+
+
+ eError = PVRSRVCreateDCSwapChainRefKM(psPerProc,
+ psSwapChain,
+ &psSwapChainRef);
+ if( eError != PVRSRV_OK )
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Couldn't create swap chain reference"));
+ PDUMPCOMMENT("Swapchain allocation failed.");
+ goto ErrorExit;
+ }
+
+ psSwapChain->ui32RefCount = 1;
+ psSwapChain->ui32Flags = ui32Flags;
+
+
+ if( ui32Flags & PVRSRV_CREATE_SWAPCHAIN_SHARED )
+ {
+ if(! psDCInfo->psDCSwapChainShared )
+ {
+ psDCInfo->psDCSwapChainShared = psSwapChain;
+ }
+ else
+ {
+ PVRSRV_DC_SWAPCHAIN *psOldHead = psDCInfo->psDCSwapChainShared;
+ psDCInfo->psDCSwapChainShared = psSwapChain;
+ psSwapChain->psNext = psOldHead;
+ }
+ }
+
+
+ *pui32SwapChainID = psSwapChain->ui32SwapChainID;
+
+
+ *phSwapChainRef= (IMG_HANDLE)psSwapChainRef;
+
+ return eError;
+
+ErrorExit:
+
+ for(i=0; i<ui32BufferCount; i++)
+ {
+ if(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo)
+ {
+ PVRSRVKernelSyncInfoDecRef(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL);
+ }
+ }
+
+ if(psQueue)
+ {
+ PVRSRVDestroyCommandQueueKM(psQueue);
+ }
+
+ if(psSwapChain)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN), psSwapChain, IMG_NULL);
+
+ }
+
+ return eError;
+}
+
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetDCDstRectKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChainRef,
+ IMG_RECT *psRect)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+ if(!hDeviceKM || !hSwapChainRef)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSetDCDstRectKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+ psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
+
+ return psDCInfo->psFuncTable->pfnSetDCDstRect(psDCInfo->hExtDevice,
+ psSwapChain->hExtSwapChain,
+ psRect);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetDCSrcRectKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChainRef,
+ IMG_RECT *psRect)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+ if(!hDeviceKM || !hSwapChainRef)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSetDCSrcRectKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+ psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
+
+ return psDCInfo->psFuncTable->pfnSetDCSrcRect(psDCInfo->hExtDevice,
+ psSwapChain->hExtSwapChain,
+ psRect);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetDCDstColourKeyKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChainRef,
+ IMG_UINT32 ui32CKColour)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+ if(!hDeviceKM || !hSwapChainRef)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSetDCDstColourKeyKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+ psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
+
+ return psDCInfo->psFuncTable->pfnSetDCDstColourKey(psDCInfo->hExtDevice,
+ psSwapChain->hExtSwapChain,
+ ui32CKColour);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetDCSrcColourKeyKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChainRef,
+ IMG_UINT32 ui32CKColour)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+ if(!hDeviceKM || !hSwapChainRef)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSetDCSrcColourKeyKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+ psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
+
+ return psDCInfo->psFuncTable->pfnSetDCSrcColourKey(psDCInfo->hExtDevice,
+ psSwapChain->hExtSwapChain,
+ ui32CKColour);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVGetDCBuffersKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChainRef,
+ IMG_UINT32 *pui32BufferCount,
+ IMG_HANDLE *phBuffer,
+ IMG_SYS_PHYADDR *psPhyAddr)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DC_SWAPCHAIN *psSwapChain;
+ IMG_HANDLE ahExtBuffer[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
+ PVRSRV_ERROR eError;
+ IMG_UINT32 i;
+
+ if(!hDeviceKM || !hSwapChainRef || !phBuffer || !psPhyAddr)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCBuffersKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+ psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
+
+
+ eError = psDCInfo->psFuncTable->pfnGetDCBuffers(psDCInfo->hExtDevice,
+ psSwapChain->hExtSwapChain,
+ pui32BufferCount,
+ ahExtBuffer);
+
+ PVR_ASSERT(*pui32BufferCount <= PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS);
+
+
+
+
+ for(i=0; i<*pui32BufferCount; i++)
+ {
+ psSwapChain->asBuffer[i].sDeviceClassBuffer.hExtBuffer = ahExtBuffer[i];
+ phBuffer[i] = (IMG_HANDLE)&psSwapChain->asBuffer[i];
+ }
+
+#if defined(SUPPORT_GET_DC_BUFFERS_SYS_PHYADDRS)
+ for(i = 0; i < *pui32BufferCount; i++)
+ {
+ IMG_UINT32 ui32ByteSize, ui32TilingStride;
+ IMG_SYS_PHYADDR *pPhyAddr;
+ IMG_BOOL bIsContiguous;
+ IMG_HANDLE hOSMapInfo;
+ IMG_VOID *pvVAddr;
+
+ eError = psDCInfo->psFuncTable->pfnGetBufferAddr(psDCInfo->hExtDevice,
+ ahExtBuffer[i],
+ &pPhyAddr,
+ &ui32ByteSize,
+ &pvVAddr,
+ &hOSMapInfo,
+ &bIsContiguous,
+ &ui32TilingStride);
+ if(eError != PVRSRV_OK)
+ {
+ break;
+ }
+
+ psPhyAddr[i] = *pPhyAddr;
+ }
+#endif
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSwapToDCBufferKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hBuffer,
+ IMG_UINT32 ui32SwapInterval,
+ IMG_HANDLE hPrivateTag,
+ IMG_UINT32 ui32ClipRectCount,
+ IMG_RECT *psClipRect)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DC_BUFFER *psBuffer;
+ PVRSRV_QUEUE_INFO *psQueue;
+ DISPLAYCLASS_FLIP_COMMAND *psFlipCmd;
+ IMG_UINT32 i;
+ IMG_BOOL bAddReferenceToLast = IMG_TRUE;
+ IMG_UINT16 ui16SwapCommandID = DC_FLIP_COMMAND;
+ IMG_UINT32 ui32NumSrcSyncs = 1;
+ PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[2];
+ PVRSRV_COMMAND *psCommand;
+ SYS_DATA *psSysData;
+
+ if(!hDeviceKM || !hBuffer || !psClipRect)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psBuffer = (PVRSRV_DC_BUFFER*)hBuffer;
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+
+ if(ui32SwapInterval < psBuffer->psSwapChain->ui32MinSwapInterval ||
+ ui32SwapInterval > psBuffer->psSwapChain->ui32MaxSwapInterval)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Invalid swap interval. Requested %u, Allowed range %u-%u",
+ ui32SwapInterval, psBuffer->psSwapChain->ui32MinSwapInterval, psBuffer->psSwapChain->ui32MaxSwapInterval));
+ return PVRSRV_ERROR_INVALID_SWAPINTERVAL;
+ }
+
+#if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS)
+
+ if(psDCInfo->psFuncTable->pfnQuerySwapCommandID != IMG_NULL)
+ {
+ psDCInfo->psFuncTable->pfnQuerySwapCommandID(psDCInfo->hExtDevice,
+ psBuffer->psSwapChain->hExtSwapChain,
+ psBuffer->sDeviceClassBuffer.hExtBuffer,
+ hPrivateTag,
+ &ui16SwapCommandID,
+ &bAddReferenceToLast);
+
+ }
+
+#endif
+
+
+ psQueue = psBuffer->psSwapChain->psQueue;
+
+
+ apsSrcSync[0] = psBuffer->sDeviceClassBuffer.psKernelSyncInfo;
+
+
+
+ if(bAddReferenceToLast && psBuffer->psSwapChain->psLastFlipBuffer &&
+ psBuffer != psBuffer->psSwapChain->psLastFlipBuffer)
+ {
+ apsSrcSync[1] = psBuffer->psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo;
+
+
+
+ ui32NumSrcSyncs++;
+ }
+
+
+ eError = PVRSRVInsertCommandKM (psQueue,
+ &psCommand,
+ psDCInfo->ui32DeviceID,
+ ui16SwapCommandID,
+ 0,
+ IMG_NULL,
+ ui32NumSrcSyncs,
+ apsSrcSync,
+ sizeof(DISPLAYCLASS_FLIP_COMMAND) + (sizeof(IMG_RECT) * ui32ClipRectCount),
+ IMG_NULL,
+ IMG_NULL);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Failed to get space in queue"));
+ goto Exit;
+ }
+
+
+ psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND*)psCommand->pvData;
+
+
+ psFlipCmd->hExtDevice = psDCInfo->hExtDevice;
+
+
+ psFlipCmd->hExtSwapChain = psBuffer->psSwapChain->hExtSwapChain;
+
+
+ psFlipCmd->hExtBuffer = psBuffer->sDeviceClassBuffer.hExtBuffer;
+
+
+ psFlipCmd->hPrivateTag = hPrivateTag;
+
+
+ psFlipCmd->ui32ClipRectCount = ui32ClipRectCount;
+
+ psFlipCmd->psClipRect = (IMG_RECT*)((IMG_UINT8*)psFlipCmd + sizeof(DISPLAYCLASS_FLIP_COMMAND));
+
+ for(i=0; i<ui32ClipRectCount; i++)
+ {
+ psFlipCmd->psClipRect[i] = psClipRect[i];
+ }
+
+
+ psFlipCmd->ui32SwapInterval = ui32SwapInterval;
+
+ SysAcquireData(&psSysData);
+
+
+ {
+ if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH)
+ {
+ OSFlushCPUCacheKM();
+ }
+ else if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN)
+ {
+ OSCleanCPUCacheKM();
+ }
+
+ psSysData->ePendingCacheOpType = PVRSRV_MISC_INFO_CPUCACHEOP_NONE;
+ }
+
+
+ eError = PVRSRVSubmitCommandKM (psQueue, psCommand);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Failed to submit command"));
+ goto Exit;
+ }
+
+
+
+ eError = OSScheduleMISR(psSysData);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Failed to schedule MISR"));
+ goto Exit;
+ }
+
+
+ psBuffer->psSwapChain->psLastFlipBuffer = psBuffer;
+
+Exit:
+
+ if(eError == PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE)
+ {
+ eError = PVRSRV_ERROR_RETRY;
+ }
+
+ return eError;
+}
+
+typedef struct _CALLBACK_DATA_
+{
+ IMG_PVOID pvPrivData;
+ IMG_UINT32 ui32PrivDataLength;
+ IMG_PVOID ppvMemInfos;
+ IMG_UINT32 ui32NumMemInfos;
+} CALLBACK_DATA;
+
+static IMG_VOID FreePrivateData(IMG_HANDLE hCallbackData)
+{
+ CALLBACK_DATA *psCallbackData = hCallbackData;
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, psCallbackData->ui32PrivDataLength,
+ psCallbackData->pvPrivData, IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(IMG_VOID *) * psCallbackData->ui32NumMemInfos,
+ psCallbackData->ppvMemInfos, IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(CALLBACK_DATA), hCallbackData, IMG_NULL);
+}
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSwapToDCBuffer2KM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChain,
+ IMG_UINT32 ui32SwapInterval,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfos,
+ PVRSRV_KERNEL_SYNC_INFO **ppsSyncInfos,
+ IMG_UINT32 ui32NumMemSyncInfos,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength)
+{
+ PVRSRV_KERNEL_SYNC_INFO **ppsCompiledSyncInfos;
+ IMG_UINT32 i, ui32NumCompiledSyncInfos;
+ DISPLAYCLASS_FLIP_COMMAND2 *psFlipCmd;
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DC_SWAPCHAIN *psSwapChain;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ CALLBACK_DATA *psCallbackData;
+ PVRSRV_QUEUE_INFO *psQueue;
+ PVRSRV_COMMAND *psCommand;
+ IMG_PVOID *ppvMemInfos;
+ SYS_DATA *psSysData;
+
+ if(!hDeviceKM || !hSwapChain || !ppsMemInfos || !ppsSyncInfos || ui32NumMemSyncInfos < 1)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChain)->psSwapChain;
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+
+ if(ui32SwapInterval < psSwapChain->ui32MinSwapInterval ||
+ ui32SwapInterval > psSwapChain->ui32MaxSwapInterval)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Invalid swap interval. Requested %u, Allowed range %u-%u",
+ ui32SwapInterval, psSwapChain->ui32MinSwapInterval, psSwapChain->ui32MaxSwapInterval));
+ return PVRSRV_ERROR_INVALID_SWAPINTERVAL;
+ }
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(CALLBACK_DATA),
+ (IMG_VOID **)&psCallbackData, IMG_NULL,
+ "PVRSRVSwapToDCBuffer2KM callback data");
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ psCallbackData->pvPrivData = pvPrivData;
+ psCallbackData->ui32PrivDataLength = ui32PrivDataLength;
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(IMG_VOID *) * ui32NumMemSyncInfos,
+ (IMG_VOID **)&ppvMemInfos, IMG_NULL,
+ "Swap Command Meminfos") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to allocate space for meminfo list"));
+ psCallbackData->ppvMemInfos = IMG_NULL;
+ goto Exit;
+ }
+
+ for(i = 0; i < ui32NumMemSyncInfos; i++)
+ {
+ ppvMemInfos[i] = ppsMemInfos[i];
+ }
+
+ psCallbackData->ppvMemInfos = ppvMemInfos;
+ psCallbackData->ui32NumMemInfos = ui32NumMemSyncInfos;
+
+
+ psQueue = psSwapChain->psQueue;
+
+#if !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED)
+ if(psSwapChain->ppsLastSyncInfos)
+ {
+ IMG_UINT32 ui32NumUniqueSyncInfos = psSwapChain->ui32LastNumSyncInfos;
+ IMG_UINT32 j;
+
+ for(j = 0; j < psSwapChain->ui32LastNumSyncInfos; j++)
+ {
+ for(i = 0; i < ui32NumMemSyncInfos; i++)
+ {
+ if(psSwapChain->ppsLastSyncInfos[j] == ppsSyncInfos[i])
+ {
+ psSwapChain->ppsLastSyncInfos[j] = IMG_NULL;
+ ui32NumUniqueSyncInfos--;
+ }
+ }
+ }
+
+ ui32NumCompiledSyncInfos = ui32NumMemSyncInfos + ui32NumUniqueSyncInfos;
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_SYNC_INFO *) * ui32NumCompiledSyncInfos,
+ (IMG_VOID **)&ppsCompiledSyncInfos, IMG_NULL,
+ "Compiled syncinfos") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to allocate space for meminfo list"));
+ goto Exit;
+ }
+
+ OSMemCopy(ppsCompiledSyncInfos, ppsSyncInfos, sizeof(PVRSRV_KERNEL_SYNC_INFO *) * ui32NumMemSyncInfos);
+ for(j = 0, i = ui32NumMemSyncInfos; j < psSwapChain->ui32LastNumSyncInfos; j++)
+ {
+ if(psSwapChain->ppsLastSyncInfos[j])
+ {
+ ppsCompiledSyncInfos[i] = psSwapChain->ppsLastSyncInfos[j];
+ i++;
+ }
+ }
+ }
+ else
+#endif
+ {
+ ppsCompiledSyncInfos = ppsSyncInfos;
+ ui32NumCompiledSyncInfos = ui32NumMemSyncInfos;
+ }
+
+
+ eError = PVRSRVInsertCommandKM (psQueue,
+ &psCommand,
+ psDCInfo->ui32DeviceID,
+ DC_FLIP_COMMAND,
+ 0,
+ IMG_NULL,
+ ui32NumCompiledSyncInfos,
+ ppsCompiledSyncInfos,
+ sizeof(DISPLAYCLASS_FLIP_COMMAND2),
+ FreePrivateData,
+ psCallbackData);
+
+ if (ppsCompiledSyncInfos != ppsSyncInfos)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_SYNC_INFO *) * ui32NumCompiledSyncInfos,
+ (IMG_VOID *)ppsCompiledSyncInfos,
+ IMG_NULL);
+ }
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to get space in queue"));
+ goto Exit;
+ }
+
+
+ psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND2*)psCommand->pvData;
+
+
+ psFlipCmd->hUnused = IMG_NULL;
+
+
+ psFlipCmd->hExtDevice = psDCInfo->hExtDevice;
+
+
+ psFlipCmd->hExtSwapChain = psSwapChain->hExtSwapChain;
+
+
+ psFlipCmd->ui32SwapInterval = ui32SwapInterval;
+
+
+ psFlipCmd->pvPrivData = pvPrivData;
+ psFlipCmd->ui32PrivDataLength = ui32PrivDataLength;
+
+ psFlipCmd->ppsMemInfos = (PDC_MEM_INFO *)ppvMemInfos;
+ psFlipCmd->ui32NumMemInfos = ui32NumMemSyncInfos;
+
+
+ psFlipCmd->hUnused = IMG_NULL;
+
+ SysAcquireData(&psSysData);
+
+
+ {
+ if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH)
+ {
+ OSFlushCPUCacheKM();
+ }
+ else if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN)
+ {
+ OSCleanCPUCacheKM();
+ }
+
+ psSysData->ePendingCacheOpType = PVRSRV_MISC_INFO_CPUCACHEOP_NONE;
+ }
+
+
+ eError = PVRSRVSubmitCommandKM (psQueue, psCommand);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to submit command"));
+ goto Exit;
+ }
+
+
+ psCallbackData = IMG_NULL;
+
+
+
+ eError = OSScheduleMISR(psSysData);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to schedule MISR"));
+ goto Exit;
+ }
+
+#if !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED)
+
+ if (psSwapChain->ui32LastNumSyncInfos < ui32NumMemSyncInfos)
+ {
+ if (psSwapChain->ppsLastSyncInfos)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_SYNC_INFO *) * psSwapChain->ui32LastNumSyncInfos,
+ psSwapChain->ppsLastSyncInfos, IMG_NULL);
+ }
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_SYNC_INFO *) * ui32NumMemSyncInfos,
+ (IMG_VOID **)&psSwapChain->ppsLastSyncInfos, IMG_NULL,
+ "Last syncinfos") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to allocate space for meminfo list"));
+ goto Exit;
+ }
+ }
+
+ psSwapChain->ui32LastNumSyncInfos = ui32NumMemSyncInfos;
+
+ for(i = 0; i < ui32NumMemSyncInfos; i++)
+ {
+ psSwapChain->ppsLastSyncInfos[i] = ppsSyncInfos[i];
+ }
+#endif
+
+Exit:
+ if (psCallbackData)
+ {
+ if(psCallbackData->ppvMemInfos)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(IMG_VOID *) * psCallbackData->ui32NumMemInfos,
+ psCallbackData->ppvMemInfos, IMG_NULL);
+ }
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(CALLBACK_DATA), psCallbackData, IMG_NULL);
+ }
+ if(eError == PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE)
+ {
+ eError = PVRSRV_ERROR_RETRY;
+ }
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSwapToDCSystemKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChainRef)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_QUEUE_INFO *psQueue;
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DC_SWAPCHAIN *psSwapChain;
+ PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef;
+ DISPLAYCLASS_FLIP_COMMAND *psFlipCmd;
+ IMG_UINT32 ui32NumSrcSyncs = 1;
+ PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[2];
+ PVRSRV_COMMAND *psCommand;
+ IMG_BOOL bAddReferenceToLast = IMG_TRUE;
+ IMG_UINT16 ui16SwapCommandID = DC_FLIP_COMMAND;
+ SYS_DATA *psSysData;
+
+ if(!hDeviceKM || !hSwapChainRef)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+ psSwapChainRef = (PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef;
+ psSwapChain = psSwapChainRef->psSwapChain;
+
+
+ psQueue = psSwapChain->psQueue;
+
+#if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS)
+
+ if(psDCInfo->psFuncTable->pfnQuerySwapCommandID != IMG_NULL)
+ {
+ psDCInfo->psFuncTable->pfnQuerySwapCommandID(psDCInfo->hExtDevice,
+ psSwapChain->hExtSwapChain,
+ psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtBuffer,
+ 0,
+ &ui16SwapCommandID,
+ &bAddReferenceToLast);
+
+ }
+
+#endif
+
+
+ apsSrcSync[0] = psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo;
+
+
+
+ if(bAddReferenceToLast && psSwapChain->psLastFlipBuffer)
+ {
+
+ if (apsSrcSync[0] != psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo)
+ {
+ apsSrcSync[1] = psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo;
+
+
+
+ ui32NumSrcSyncs++;
+ }
+ }
+
+
+ eError = PVRSRVInsertCommandKM (psQueue,
+ &psCommand,
+ psDCInfo->ui32DeviceID,
+ ui16SwapCommandID,
+ 0,
+ IMG_NULL,
+ ui32NumSrcSyncs,
+ apsSrcSync,
+ sizeof(DISPLAYCLASS_FLIP_COMMAND),
+ IMG_NULL,
+ IMG_NULL);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Failed to get space in queue"));
+ goto Exit;
+ }
+
+
+ psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND*)psCommand->pvData;
+
+
+ psFlipCmd->hExtDevice = psDCInfo->hExtDevice;
+
+
+ psFlipCmd->hExtSwapChain = psSwapChain->hExtSwapChain;
+
+
+ psFlipCmd->hExtBuffer = psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtBuffer;
+
+
+ psFlipCmd->hPrivateTag = IMG_NULL;
+
+
+ psFlipCmd->ui32ClipRectCount = 0;
+
+ psFlipCmd->ui32SwapInterval = 1;
+
+
+ eError = PVRSRVSubmitCommandKM (psQueue, psCommand);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Failed to submit command"));
+ goto Exit;
+ }
+
+
+ SysAcquireData(&psSysData);
+ eError = OSScheduleMISR(psSysData);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Failed to schedule MISR"));
+ goto Exit;
+ }
+
+
+ psSwapChain->psLastFlipBuffer = &psDCInfo->sSystemBuffer;
+
+ eError = PVRSRV_OK;
+
+Exit:
+
+ if(eError == PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE)
+ {
+ eError = PVRSRV_ERROR_RETRY;
+ }
+
+ return eError;
+}
+
+
+static
+PVRSRV_ERROR PVRSRVRegisterSystemISRHandler (PFN_ISR_HANDLER pfnISRHandler,
+ IMG_VOID *pvISRHandlerData,
+ IMG_UINT32 ui32ISRSourceMask,
+ IMG_UINT32 ui32DeviceID)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_DEVICE_NODE *psDevNode;
+
+ PVR_UNREFERENCED_PARAMETER(ui32ISRSourceMask);
+
+ SysAcquireData(&psSysData);
+
+
+ psDevNode = (PVRSRV_DEVICE_NODE*)
+ List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ &MatchDeviceKM_AnyVaCb,
+ ui32DeviceID,
+ IMG_TRUE);
+
+ if (psDevNode == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterSystemISRHandler: Failed to get psDevNode"));
+ PVR_DBG_BREAK;
+ return PVRSRV_ERROR_NO_DEVICENODE_FOUND;
+ }
+
+
+ psDevNode->pvISRData = (IMG_VOID*) pvISRHandlerData;
+
+
+ psDevNode->pfnDeviceISR = pfnISRHandler;
+
+ return PVRSRV_OK;
+}
+
+static
+IMG_VOID PVRSRVSetDCState_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ IMG_UINT32 ui32State;
+ ui32State = va_arg(va, IMG_UINT32);
+
+ if (psDeviceNode->sDevId.eDeviceClass == PVRSRV_DEVICE_CLASS_DISPLAY)
+ {
+ psDCInfo = (PVRSRV_DISPLAYCLASS_INFO *)psDeviceNode->pvDevice;
+ if (psDCInfo->psFuncTable->pfnSetDCState && psDCInfo->hExtDevice)
+ {
+ psDCInfo->psFuncTable->pfnSetDCState(psDCInfo->hExtDevice, ui32State);
+ }
+ }
+}
+
+
+IMG_VOID IMG_CALLCONV PVRSRVSetDCState(IMG_UINT32 ui32State)
+{
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+ List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
+ &PVRSRVSetDCState_ForEachVaCb,
+ ui32State);
+}
+
+static PVRSRV_ERROR
+PVRSRVDCMemInfoGetCpuVAddr(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo,
+ IMG_CPU_VIRTADDR *pVAddr)
+{
+ *pVAddr = psKernelMemInfo->pvLinAddrKM;
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR
+PVRSRVDCMemInfoGetCpuPAddr(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo,
+ IMG_SIZE_T uByteOffset, IMG_CPU_PHYADDR *pPAddr)
+{
+ *pPAddr = OSMemHandleToCpuPAddr(psKernelMemInfo->sMemBlk.hOSMemHandle, uByteOffset);
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR
+PVRSRVDCMemInfoGetByteSize(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo,
+ IMG_SIZE_T *uByteSize)
+{
+ *uByteSize = psKernelMemInfo->uAllocSize;
+ return PVRSRV_OK;
+}
+
+static IMG_BOOL
+PVRSRVDCMemInfoIsPhysContig(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ return OSMemHandleIsPhysContig(psKernelMemInfo->sMemBlk.hOSMemHandle);
+}
+
+IMG_EXPORT
+IMG_BOOL PVRGetDisplayClassJTable(PVRSRV_DC_DISP2SRV_KMJTABLE *psJTable)
+{
+ psJTable->ui32TableSize = sizeof(PVRSRV_DC_DISP2SRV_KMJTABLE);
+ psJTable->pfnPVRSRVRegisterDCDevice = &PVRSRVRegisterDCDeviceKM;
+ psJTable->pfnPVRSRVRemoveDCDevice = &PVRSRVRemoveDCDeviceKM;
+ psJTable->pfnPVRSRVOEMFunction = &SysOEMFunction;
+ psJTable->pfnPVRSRVRegisterCmdProcList = &PVRSRVRegisterCmdProcListKM;
+ psJTable->pfnPVRSRVRemoveCmdProcList = &PVRSRVRemoveCmdProcListKM;
+#if defined(SUPPORT_MISR_IN_THREAD)
+ psJTable->pfnPVRSRVCmdComplete = &OSVSyncMISR;
+#else
+ psJTable->pfnPVRSRVCmdComplete = &PVRSRVCommandCompleteKM;
+#endif
+ psJTable->pfnPVRSRVRegisterSystemISRHandler = &PVRSRVRegisterSystemISRHandler;
+ psJTable->pfnPVRSRVRegisterPowerDevice = &PVRSRVRegisterPowerDevice;
+#if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS)
+ psJTable->pfnPVRSRVFreeCmdCompletePacket = &PVRSRVFreeCommandCompletePacketKM;
+#endif
+ psJTable->pfnPVRSRVDCMemInfoGetCpuVAddr = &PVRSRVDCMemInfoGetCpuVAddr;
+ psJTable->pfnPVRSRVDCMemInfoGetCpuPAddr = &PVRSRVDCMemInfoGetCpuPAddr;
+ psJTable->pfnPVRSRVDCMemInfoGetByteSize = &PVRSRVDCMemInfoGetByteSize;
+ psJTable->pfnPVRSRVDCMemInfoIsPhysContig = &PVRSRVDCMemInfoIsPhysContig;
+ return IMG_TRUE;
+}
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVCloseBCDeviceKM (IMG_HANDLE hDeviceKM,
+ IMG_BOOL bResManCallback)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
+
+ PVR_UNREFERENCED_PARAMETER(bResManCallback);
+
+ psBCPerContextInfo = (PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *)hDeviceKM;
+
+
+ eError = ResManFreeResByPtr(psBCPerContextInfo->hResItem, CLEANUP_WITH_POLL);
+
+ return eError;
+}
+
+
+static PVRSRV_ERROR CloseBCDeviceCallBack(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param,
+ IMG_BOOL bDummy)
+{
+ PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
+ PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+ IMG_UINT32 i;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+ PVR_UNREFERENCED_PARAMETER(bDummy);
+
+ psBCPerContextInfo = (PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *)pvParam;
+
+ psBCInfo = psBCPerContextInfo->psBCInfo;
+
+ for (i = 0; i < psBCInfo->ui32BufferCount; i++)
+ {
+ if (psBCInfo->psBuffer[i].sDeviceClassBuffer.ui32MemMapRefCount != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CloseBCDeviceCallBack: buffer %d (0x%p) still mapped (ui32MemMapRefCount = %d)",
+ i,
+ &psBCInfo->psBuffer[i].sDeviceClassBuffer,
+ psBCInfo->psBuffer[i].sDeviceClassBuffer.ui32MemMapRefCount));
+ return PVRSRV_ERROR_STILL_MAPPED;
+ }
+ }
+
+ psBCInfo->ui32RefCount--;
+ if(psBCInfo->ui32RefCount == 0)
+ {
+
+ psBCInfo->psFuncTable->pfnCloseBCDevice(psBCInfo->ui32DeviceID, psBCInfo->hExtDevice);
+
+
+ for(i=0; i<psBCInfo->ui32BufferCount; i++)
+ {
+ if(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo)
+ {
+ PVRSRVKernelSyncInfoDecRef(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL);
+ }
+ }
+
+
+ if(psBCInfo->psBuffer)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_BUFFER) * psBCInfo->ui32BufferCount, psBCInfo->psBuffer, IMG_NULL);
+ psBCInfo->psBuffer = IMG_NULL;
+ }
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_PERCONTEXT_INFO), psBCPerContextInfo, IMG_NULL);
+
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVOpenBCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_UINT32 ui32DeviceID,
+ IMG_HANDLE hDevCookie,
+ IMG_HANDLE *phDeviceKM)
+{
+ PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+ PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ SYS_DATA *psSysData;
+ IMG_UINT32 i;
+ PVRSRV_ERROR eError;
+
+ if(!phDeviceKM || !hDevCookie)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Invalid params"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ SysAcquireData(&psSysData);
+
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE*)
+ List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ &MatchDeviceKM_AnyVaCb,
+ ui32DeviceID,
+ IMG_FALSE,
+ PVRSRV_DEVICE_CLASS_BUFFER);
+ if (!psDeviceNode)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: No devnode matching index %d", ui32DeviceID));
+ return PVRSRV_ERROR_NO_DEVICENODE_FOUND;
+ }
+ psBCInfo = (PVRSRV_BUFFERCLASS_INFO*)psDeviceNode->pvDevice;
+
+
+
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*psBCPerContextInfo),
+ (IMG_VOID **)&psBCPerContextInfo, IMG_NULL,
+ "Buffer Class per Context Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed psBCPerContextInfo alloc"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OSMemSet(psBCPerContextInfo, 0, sizeof(*psBCPerContextInfo));
+
+ if(psBCInfo->ui32RefCount++ == 0)
+ {
+ BUFFER_INFO sBufferInfo;
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
+
+
+ psBCInfo->hDevMemContext = (IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext;
+
+
+ eError = psBCInfo->psFuncTable->pfnOpenBCDevice(ui32DeviceID, &psBCInfo->hExtDevice);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed to open external BC device"));
+ return eError;
+ }
+
+
+ eError = psBCInfo->psFuncTable->pfnGetBCInfo(psBCInfo->hExtDevice, &sBufferInfo);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM : Failed to get BC Info"));
+ return eError;
+ }
+
+
+ psBCInfo->ui32BufferCount = sBufferInfo.ui32BufferCount;
+
+
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_BC_BUFFER) * sBufferInfo.ui32BufferCount,
+ (IMG_VOID **)&psBCInfo->psBuffer,
+ IMG_NULL,
+ "Array of Buffer Class Buffer");
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed to allocate BC buffers"));
+ return eError;
+ }
+ OSMemSet (psBCInfo->psBuffer,
+ 0,
+ sizeof(PVRSRV_BC_BUFFER) * sBufferInfo.ui32BufferCount);
+
+ for(i=0; i<psBCInfo->ui32BufferCount; i++)
+ {
+
+ eError = PVRSRVAllocSyncInfoKM(IMG_NULL,
+ psBCInfo->hDevMemContext,
+ &psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed sync info alloc"));
+ goto ErrorExit;
+ }
+
+
+
+
+ eError = psBCInfo->psFuncTable->pfnGetBCBuffer(psBCInfo->hExtDevice,
+ i,
+ psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->psSyncData,
+ &psBCInfo->psBuffer[i].sDeviceClassBuffer.hExtBuffer);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed to get BC buffers"));
+ goto ErrorExit;
+ }
+
+
+ psBCInfo->psBuffer[i].sDeviceClassBuffer.pfnGetBufferAddr = psBCInfo->psFuncTable->pfnGetBufferAddr;
+ psBCInfo->psBuffer[i].sDeviceClassBuffer.hDevMemContext = psBCInfo->hDevMemContext;
+ psBCInfo->psBuffer[i].sDeviceClassBuffer.hExtDevice = psBCInfo->hExtDevice;
+ psBCInfo->psBuffer[i].sDeviceClassBuffer.ui32MemMapRefCount = 0;
+ }
+ }
+
+ psBCPerContextInfo->psBCInfo = psBCInfo;
+ psBCPerContextInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_BUFFERCLASS_DEVICE,
+ psBCPerContextInfo,
+ 0,
+ &CloseBCDeviceCallBack);
+
+
+ *phDeviceKM = (IMG_HANDLE)psBCPerContextInfo;
+
+ return PVRSRV_OK;
+
+ErrorExit:
+
+
+ for(i=0; i<psBCInfo->ui32BufferCount; i++)
+ {
+ if(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo)
+ {
+ PVRSRVKernelSyncInfoDecRef(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL);
+ }
+ }
+
+
+ if(psBCInfo->psBuffer)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_BUFFER), psBCInfo->psBuffer, IMG_NULL);
+ psBCInfo->psBuffer = IMG_NULL;
+ }
+
+ return eError;
+}
+
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVGetBCInfoKM (IMG_HANDLE hDeviceKM,
+ BUFFER_INFO *psBufferInfo)
+{
+ PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+ PVRSRV_ERROR eError;
+
+ if(!hDeviceKM || !psBufferInfo)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetBCInfoKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psBCInfo = BCDeviceHandleToBCInfo(hDeviceKM);
+
+ eError = psBCInfo->psFuncTable->pfnGetBCInfo(psBCInfo->hExtDevice, psBufferInfo);
+
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetBCInfoKM : Failed to get BC Info"));
+ return eError;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVGetBCBufferKM (IMG_HANDLE hDeviceKM,
+ IMG_UINT32 ui32BufferIndex,
+ IMG_HANDLE *phBuffer)
+{
+ PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+
+ if(!hDeviceKM || !phBuffer)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetBCBufferKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psBCInfo = BCDeviceHandleToBCInfo(hDeviceKM);
+
+ if(ui32BufferIndex < psBCInfo->ui32BufferCount)
+ {
+ *phBuffer = (IMG_HANDLE)&psBCInfo->psBuffer[ui32BufferIndex];
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetBCBufferKM: Buffer index %d out of range (%d)", ui32BufferIndex,psBCInfo->ui32BufferCount));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+IMG_BOOL PVRGetBufferClassJTable(PVRSRV_BC_BUFFER2SRV_KMJTABLE *psJTable)
+{
+ psJTable->ui32TableSize = sizeof(PVRSRV_BC_BUFFER2SRV_KMJTABLE);
+
+ psJTable->pfnPVRSRVRegisterBCDevice = &PVRSRVRegisterBCDeviceKM;
+ psJTable->pfnPVRSRVScheduleDevices = &PVRSRVScheduleDevicesKM;
+ psJTable->pfnPVRSRVRemoveBCDevice = &PVRSRVRemoveBCDeviceKM;
+
+ return IMG_TRUE;
+}
+
diff --git a/drivers/gpu/pvr/deviceid.h b/drivers/gpu/pvr/deviceid.h
new file mode 100644
index 0000000..9a7bdb3
--- /dev/null
+++ b/drivers/gpu/pvr/deviceid.h
@@ -0,0 +1,36 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __DEVICEID_H__
+#define __DEVICEID_H__
+
+#include "services.h"
+#include "syscommon.h"
+
+PVRSRV_ERROR AllocateDeviceID(SYS_DATA *psSysData, IMG_UINT32 *pui32DevID);
+PVRSRV_ERROR FreeDeviceID(SYS_DATA *psSysData, IMG_UINT32 ui32DevID);
+
+#endif
diff --git a/drivers/gpu/pvr/devicemem.c b/drivers/gpu/pvr/devicemem.c
new file mode 100644
index 0000000..8874d61
--- /dev/null
+++ b/drivers/gpu/pvr/devicemem.c
@@ -0,0 +1,1837 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include <stddef.h>
+
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "pdump_km.h"
+#include "pvr_bridge_km.h"
+#include "osfunc.h"
+
+static PVRSRV_ERROR AllocDeviceMem(IMG_HANDLE hDevCookie,
+ IMG_HANDLE hDevMemHeap,
+ IMG_UINT32 ui32Flags,
+ IMG_SIZE_T ui32Size,
+ IMG_SIZE_T ui32Alignment,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfo);
+
+typedef struct _RESMAN_MAP_DEVICE_MEM_DATA_
+{
+
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+
+ PVRSRV_KERNEL_MEM_INFO *psSrcMemInfo;
+} RESMAN_MAP_DEVICE_MEM_DATA;
+
+typedef struct _PVRSRV_DC_MAPINFO_
+{
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_UINT32 ui32RangeIndex;
+ IMG_UINT32 ui32TilingStride;
+ PVRSRV_DEVICECLASS_BUFFER *psDeviceClassBuffer;
+} PVRSRV_DC_MAPINFO;
+
+static IMG_UINT32 g_ui32SyncUID = 0;
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapsKM(IMG_HANDLE hDevCookie,
+#if defined (SUPPORT_SID_INTERFACE)
+ PVRSRV_HEAP_INFO_KM *psHeapInfo)
+#else
+ PVRSRV_HEAP_INFO *psHeapInfo)
+#endif
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_UINT32 ui32HeapCount;
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+ IMG_UINT32 i;
+
+ if (hDevCookie == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetDeviceMemHeapsKM: hDevCookie invalid"));
+ PVR_DBG_BREAK;
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
+
+
+ ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount;
+ psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
+
+
+ PVR_ASSERT(ui32HeapCount <= PVRSRV_MAX_CLIENT_HEAPS);
+
+
+ for(i=0; i<ui32HeapCount; i++)
+ {
+
+ psHeapInfo[i].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
+ psHeapInfo[i].hDevMemHeap = psDeviceMemoryHeap[i].hDevMemHeap;
+ psHeapInfo[i].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase;
+ psHeapInfo[i].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize;
+ psHeapInfo[i].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
+
+ psHeapInfo[i].ui32XTileStride = psDeviceMemoryHeap[i].ui32XTileStride;
+ }
+
+ for(; i < PVRSRV_MAX_CLIENT_HEAPS; i++)
+ {
+ OSMemSet(psHeapInfo + i, 0, sizeof(*psHeapInfo));
+ psHeapInfo[i].ui32HeapID = (IMG_UINT32)PVRSRV_UNDEFINED_HEAP_ID;
+ }
+
+ return PVRSRV_OK;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateDeviceMemContextKM(IMG_HANDLE hDevCookie,
+ PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE *phDevMemContext,
+ IMG_UINT32 *pui32ClientHeapCount,
+#if defined (SUPPORT_SID_INTERFACE)
+ PVRSRV_HEAP_INFO_KM *psHeapInfo,
+#else
+ PVRSRV_HEAP_INFO *psHeapInfo,
+#endif
+ IMG_BOOL *pbCreated,
+ IMG_BOOL *pbShared)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_UINT32 ui32HeapCount, ui32ClientHeapCount=0;
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+ IMG_HANDLE hDevMemContext;
+ IMG_HANDLE hDevMemHeap;
+ IMG_DEV_PHYADDR sPDDevPAddr;
+ IMG_UINT32 i;
+
+#if !defined(PVR_SECURE_HANDLES) && !defined (SUPPORT_SID_INTERFACE)
+ PVR_UNREFERENCED_PARAMETER(pbShared);
+#endif
+
+ if (hDevCookie == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVCreateDeviceMemContextKM: hDevCookie invalid"));
+ PVR_DBG_BREAK;
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
+
+
+
+ ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount;
+ psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
+
+
+
+ PVR_ASSERT(ui32HeapCount <= PVRSRV_MAX_CLIENT_HEAPS);
+
+
+
+ hDevMemContext = BM_CreateContext(psDeviceNode,
+ &sPDDevPAddr,
+ psPerProc,
+ pbCreated);
+ if (hDevMemContext == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDeviceMemContextKM: Failed BM_CreateContext"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+
+ for(i=0; i<ui32HeapCount; i++)
+ {
+ switch(psDeviceMemoryHeap[i].DevMemHeapType)
+ {
+ case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+ {
+
+ psHeapInfo[ui32ClientHeapCount].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
+ psHeapInfo[ui32ClientHeapCount].hDevMemHeap = psDeviceMemoryHeap[i].hDevMemHeap;
+ psHeapInfo[ui32ClientHeapCount].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase;
+ psHeapInfo[ui32ClientHeapCount].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize;
+ psHeapInfo[ui32ClientHeapCount].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
+ #if defined(SUPPORT_MEMORY_TILING)
+ psHeapInfo[ui32ClientHeapCount].ui32XTileStride = psDeviceMemoryHeap[i].ui32XTileStride;
+ #else
+ psHeapInfo[ui32ClientHeapCount].ui32XTileStride = 0;
+ #endif
+
+#if defined(PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE)
+ pbShared[ui32ClientHeapCount] = IMG_TRUE;
+#endif
+ ui32ClientHeapCount++;
+ break;
+ }
+ case DEVICE_MEMORY_HEAP_PERCONTEXT:
+ {
+ if (psDeviceMemoryHeap[i].ui32HeapSize > 0)
+ {
+ hDevMemHeap = BM_CreateHeap(hDevMemContext,
+ &psDeviceMemoryHeap[i]);
+ if (hDevMemHeap == IMG_NULL)
+ {
+ BM_DestroyContext(hDevMemContext, IMG_NULL);
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ }
+ else
+ {
+ hDevMemHeap = IMG_NULL;
+ }
+
+
+ psHeapInfo[ui32ClientHeapCount].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
+ psHeapInfo[ui32ClientHeapCount].hDevMemHeap = hDevMemHeap;
+ psHeapInfo[ui32ClientHeapCount].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase;
+ psHeapInfo[ui32ClientHeapCount].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize;
+ psHeapInfo[ui32ClientHeapCount].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
+ #if defined(SUPPORT_MEMORY_TILING)
+ psHeapInfo[ui32ClientHeapCount].ui32XTileStride = psDeviceMemoryHeap[i].ui32XTileStride;
+ #else
+ psHeapInfo[ui32ClientHeapCount].ui32XTileStride = 0;
+ #endif
+#if defined(PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE)
+ pbShared[ui32ClientHeapCount] = IMG_FALSE;
+#endif
+
+ ui32ClientHeapCount++;
+ break;
+ }
+ }
+ }
+
+
+ *pui32ClientHeapCount = ui32ClientHeapCount;
+ *phDevMemContext = hDevMemContext;
+
+ return PVRSRV_OK;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyDeviceMemContextKM(IMG_HANDLE hDevCookie,
+ IMG_HANDLE hDevMemContext,
+ IMG_BOOL *pbDestroyed)
+{
+ PVR_UNREFERENCED_PARAMETER(hDevCookie);
+
+ return BM_DestroyContext(hDevMemContext, pbDestroyed);
+}
+
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapInfoKM(IMG_HANDLE hDevCookie,
+ IMG_HANDLE hDevMemContext,
+ IMG_UINT32 *pui32ClientHeapCount,
+#if defined (SUPPORT_SID_INTERFACE)
+ PVRSRV_HEAP_INFO_KM *psHeapInfo,
+#else
+ PVRSRV_HEAP_INFO *psHeapInfo,
+#endif
+ IMG_BOOL *pbShared)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_UINT32 ui32HeapCount, ui32ClientHeapCount=0;
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+ IMG_HANDLE hDevMemHeap;
+ IMG_UINT32 i;
+
+#if !defined(PVR_SECURE_HANDLES) && !defined (SUPPORT_SID_INTERFACE)
+ PVR_UNREFERENCED_PARAMETER(pbShared);
+#endif
+
+ if (hDevCookie == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetDeviceMemHeapInfoKM: hDevCookie invalid"));
+ PVR_DBG_BREAK;
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
+
+
+
+ ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount;
+ psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
+
+
+
+ PVR_ASSERT(ui32HeapCount <= PVRSRV_MAX_CLIENT_HEAPS);
+
+
+ for(i=0; i<ui32HeapCount; i++)
+ {
+ switch(psDeviceMemoryHeap[i].DevMemHeapType)
+ {
+ case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+ {
+
+ psHeapInfo[ui32ClientHeapCount].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
+ psHeapInfo[ui32ClientHeapCount].hDevMemHeap = psDeviceMemoryHeap[i].hDevMemHeap;
+ psHeapInfo[ui32ClientHeapCount].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase;
+ psHeapInfo[ui32ClientHeapCount].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize;
+ psHeapInfo[ui32ClientHeapCount].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
+ psHeapInfo[ui32ClientHeapCount].ui32XTileStride = psDeviceMemoryHeap[i].ui32XTileStride;
+#if defined(PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE)
+ pbShared[ui32ClientHeapCount] = IMG_TRUE;
+#endif
+ ui32ClientHeapCount++;
+ break;
+ }
+ case DEVICE_MEMORY_HEAP_PERCONTEXT:
+ {
+ if (psDeviceMemoryHeap[i].ui32HeapSize > 0)
+ {
+ hDevMemHeap = BM_CreateHeap(hDevMemContext,
+ &psDeviceMemoryHeap[i]);
+
+ if (hDevMemHeap == IMG_NULL)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ }
+ else
+ {
+ hDevMemHeap = IMG_NULL;
+ }
+
+
+ psHeapInfo[ui32ClientHeapCount].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
+ psHeapInfo[ui32ClientHeapCount].hDevMemHeap = hDevMemHeap;
+ psHeapInfo[ui32ClientHeapCount].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase;
+ psHeapInfo[ui32ClientHeapCount].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize;
+ psHeapInfo[ui32ClientHeapCount].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
+ psHeapInfo[ui32ClientHeapCount].ui32XTileStride = psDeviceMemoryHeap[i].ui32XTileStride;
+#if defined(PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE)
+ pbShared[ui32ClientHeapCount] = IMG_FALSE;
+#endif
+
+ ui32ClientHeapCount++;
+ break;
+ }
+ }
+ }
+
+
+ *pui32ClientHeapCount = ui32ClientHeapCount;
+
+ return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR AllocDeviceMem(IMG_HANDLE hDevCookie,
+ IMG_HANDLE hDevMemHeap,
+ IMG_UINT32 ui32Flags,
+ IMG_SIZE_T ui32Size,
+ IMG_SIZE_T ui32Alignment,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfo)
+{
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+ BM_HANDLE hBuffer;
+
+ PVRSRV_MEMBLK *psMemBlock;
+ IMG_BOOL bBMError;
+
+ PVR_UNREFERENCED_PARAMETER(hDevCookie);
+
+ *ppsMemInfo = IMG_NULL;
+
+ if(OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(PVRSRV_KERNEL_MEM_INFO),
+ (IMG_VOID **)&psMemInfo, IMG_NULL,
+ "Kernel Memory Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"AllocDeviceMem: Failed to alloc memory for block"));
+ return (PVRSRV_ERROR_OUT_OF_MEMORY);
+ }
+
+ OSMemSet(psMemInfo, 0, sizeof(*psMemInfo));
+
+ psMemBlock = &(psMemInfo->sMemBlk);
+
+
+ psMemInfo->ui32Flags = ui32Flags | PVRSRV_MEM_RAM_BACKED_ALLOCATION;
+
+ bBMError = BM_Alloc (hDevMemHeap,
+ IMG_NULL,
+ ui32Size,
+ &psMemInfo->ui32Flags,
+ IMG_CAST_TO_DEVVADDR_UINT(ui32Alignment),
+ pvPrivData,
+ ui32PrivDataLength,
+ &hBuffer);
+
+ if (!bBMError)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"AllocDeviceMem: BM_Alloc Failed"));
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
+
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+
+ psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
+ psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
+
+
+ psMemBlock->hBuffer = (IMG_HANDLE)hBuffer;
+
+
+
+ psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer);
+
+ psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
+
+ psMemInfo->uAllocSize = ui32Size;
+
+
+ psMemInfo->pvSysBackupBuffer = IMG_NULL;
+
+
+ *ppsMemInfo = psMemInfo;
+
+
+ return (PVRSRV_OK);
+}
+
+static PVRSRV_ERROR FreeDeviceMem2(PVRSRV_KERNEL_MEM_INFO *psMemInfo, PVRSRV_FREE_CALLBACK_ORIGIN eCallbackOrigin)
+{
+ BM_HANDLE hBuffer;
+
+ if (!psMemInfo)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ hBuffer = psMemInfo->sMemBlk.hBuffer;
+
+
+ switch(eCallbackOrigin)
+ {
+ case PVRSRV_FREE_CALLBACK_ORIGIN_ALLOCATOR:
+ BM_Free(hBuffer, psMemInfo->ui32Flags);
+ break;
+ case PVRSRV_FREE_CALLBACK_ORIGIN_IMPORTER:
+ BM_FreeExport(hBuffer, psMemInfo->ui32Flags);
+ break;
+ default:
+ break;
+ }
+
+
+ if (psMemInfo->pvSysBackupBuffer &&
+ eCallbackOrigin == PVRSRV_FREE_CALLBACK_ORIGIN_ALLOCATOR)
+ {
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, psMemInfo->uAllocSize, psMemInfo->pvSysBackupBuffer, IMG_NULL);
+ psMemInfo->pvSysBackupBuffer = IMG_NULL;
+ }
+
+ if (psMemInfo->ui32RefCount == 0)
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
+
+
+ return(PVRSRV_OK);
+}
+
+static PVRSRV_ERROR FreeDeviceMem(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+ BM_HANDLE hBuffer;
+
+ if (!psMemInfo)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ hBuffer = psMemInfo->sMemBlk.hBuffer;
+
+
+ BM_Free(hBuffer, psMemInfo->ui32Flags);
+
+ if(psMemInfo->pvSysBackupBuffer)
+ {
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, psMemInfo->uAllocSize, psMemInfo->pvSysBackupBuffer, IMG_NULL);
+ psMemInfo->pvSysBackupBuffer = IMG_NULL;
+ }
+
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
+
+
+ return(PVRSRV_OK);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocSyncInfoKM(IMG_HANDLE hDevCookie,
+ IMG_HANDLE hDevMemContext,
+ PVRSRV_KERNEL_SYNC_INFO **ppsKernelSyncInfo)
+{
+ IMG_HANDLE hSyncDevMemHeap;
+ DEVICE_MEMORY_INFO *psDevMemoryInfo;
+ BM_CONTEXT *pBMContext;
+ PVRSRV_ERROR eError;
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+ PVRSRV_SYNC_DATA *psSyncData;
+
+ eError = OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(PVRSRV_KERNEL_SYNC_INFO),
+ (IMG_VOID **)&psKernelSyncInfo, IMG_NULL,
+ "Kernel Synchronization Info");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVAllocSyncInfoKM: Failed to alloc memory"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ eError = OSAtomicAlloc(&psKernelSyncInfo->pvRefCount);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVAllocSyncInfoKM: Failed to allocate atomic"));
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_SYNC_INFO), psKernelSyncInfo, IMG_NULL);
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+
+
+ pBMContext = (BM_CONTEXT*)hDevMemContext;
+ psDevMemoryInfo = &pBMContext->psDeviceNode->sDevMemoryInfo;
+
+
+ hSyncDevMemHeap = psDevMemoryInfo->psDeviceMemoryHeap[psDevMemoryInfo->ui32SyncHeapID].hDevMemHeap;
+
+
+
+
+ eError = AllocDeviceMem(hDevCookie,
+ hSyncDevMemHeap,
+ PVRSRV_MEM_CACHE_CONSISTENT,
+ sizeof(PVRSRV_SYNC_DATA),
+ sizeof(IMG_UINT32),
+ IMG_NULL,
+ 0,
+ &psKernelSyncInfo->psSyncDataMemInfoKM);
+
+ if (eError != PVRSRV_OK)
+ {
+
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVAllocSyncInfoKM: Failed to alloc memory"));
+ OSAtomicFree(psKernelSyncInfo->pvRefCount);
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_SYNC_INFO), psKernelSyncInfo, IMG_NULL);
+
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+
+ psKernelSyncInfo->psSyncData = psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM;
+ psSyncData = psKernelSyncInfo->psSyncData;
+
+ psSyncData->ui32WriteOpsPending = 0;
+ psSyncData->ui32WriteOpsComplete = 0;
+ psSyncData->ui32ReadOpsPending = 0;
+ psSyncData->ui32ReadOpsComplete = 0;
+ psSyncData->ui32ReadOps2Pending = 0;
+ psSyncData->ui32ReadOps2Complete = 0;
+ psSyncData->ui32LastOpDumpVal = 0;
+ psSyncData->ui32LastReadOpDumpVal = 0;
+ psSyncData->ui64LastWrite = 0;
+
+#if defined(PDUMP)
+ PDUMPCOMMENT("Allocating kernel sync object");
+ PDUMPMEM(psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM,
+ psKernelSyncInfo->psSyncDataMemInfoKM,
+ 0,
+ (IMG_UINT32)psKernelSyncInfo->psSyncDataMemInfoKM->uAllocSize,
+ PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psKernelSyncInfo->psSyncDataMemInfoKM));
+#endif
+
+ psKernelSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr = psKernelSyncInfo->psSyncDataMemInfoKM->sDevVAddr.uiAddr + offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete);
+ psKernelSyncInfo->sReadOpsCompleteDevVAddr.uiAddr = psKernelSyncInfo->psSyncDataMemInfoKM->sDevVAddr.uiAddr + offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete);
+ psKernelSyncInfo->sReadOps2CompleteDevVAddr.uiAddr = psKernelSyncInfo->psSyncDataMemInfoKM->sDevVAddr.uiAddr + offsetof(PVRSRV_SYNC_DATA, ui32ReadOps2Complete);
+ psKernelSyncInfo->ui32UID = g_ui32SyncUID++;
+
+
+ psKernelSyncInfo->psSyncDataMemInfoKM->psKernelSyncInfo = IMG_NULL;
+
+ OSAtomicInc(psKernelSyncInfo->pvRefCount);
+
+
+ *ppsKernelSyncInfo = psKernelSyncInfo;
+
+ return PVRSRV_OK;
+}
+
+IMG_EXPORT
+IMG_VOID PVRSRVAcquireSyncInfoKM(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo)
+{
+ OSAtomicInc(psKernelSyncInfo->pvRefCount);
+}
+
+IMG_EXPORT
+IMG_VOID IMG_CALLCONV PVRSRVReleaseSyncInfoKM(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo)
+{
+ if (OSAtomicDecAndTest(psKernelSyncInfo->pvRefCount))
+ {
+ FreeDeviceMem(psKernelSyncInfo->psSyncDataMemInfoKM);
+
+
+ psKernelSyncInfo->psSyncDataMemInfoKM = IMG_NULL;
+ psKernelSyncInfo->psSyncData = IMG_NULL;
+ OSAtomicFree(psKernelSyncInfo->pvRefCount);
+ (IMG_VOID)OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_SYNC_INFO), psKernelSyncInfo, IMG_NULL);
+
+ }
+}
+
+static IMG_VOID freeWrapped(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+ IMG_HANDLE hOSWrapMem = psMemInfo->sMemBlk.hOSWrapMem;
+
+
+ if(psMemInfo->sMemBlk.psIntSysPAddr)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(IMG_SYS_PHYADDR), psMemInfo->sMemBlk.psIntSysPAddr, IMG_NULL);
+ psMemInfo->sMemBlk.psIntSysPAddr = IMG_NULL;
+ }
+
+ if(hOSWrapMem)
+ {
+ OSReleasePhysPageAddr(hOSWrapMem);
+ }
+}
+
+
+#if defined (PVRSRV_FLUSH_KERNEL_OPS_LAST_ONLY)
+static
+PVRSRV_ERROR _PollUntilAtLeast(volatile IMG_UINT32* pui32WatchedValue,
+ IMG_UINT32 ui32MinimumValue,
+ IMG_UINT32 ui32Waitus,
+ IMG_UINT32 ui32Tries)
+{
+ PVRSRV_ERROR eError;
+ IMG_INT32 iDiff;
+
+ for(;;)
+ {
+ SYS_DATA *psSysData = SysAcquireDataNoCheck();
+ iDiff = *pui32WatchedValue - ui32MinimumValue;
+
+ if (iDiff >= 0)
+ {
+ eError = PVRSRV_OK;
+ break;
+ }
+
+ if(!ui32Tries)
+ {
+ eError = PVRSRV_ERROR_TIMEOUT_POLLING_FOR_VALUE;
+ break;
+ }
+
+ ui32Tries--;
+
+
+ if (psSysData->psGlobalEventObject)
+ {
+ IMG_HANDLE hOSEventKM;
+ if(psSysData->psGlobalEventObject)
+ {
+ eError = OSEventObjectOpenKM(psSysData->psGlobalEventObject, &hOSEventKM);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "_PollUntilAtLeast: OSEventObjectOpen failed"));
+ goto Exit;
+ }
+ eError = OSEventObjectWaitKM(hOSEventKM);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "_PollUntilAtLeast: PVRSRVEventObjectWait failed"));
+ goto Exit;
+ }
+ eError = OSEventObjectCloseKM(psSysData->psGlobalEventObject, hOSEventKM);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "_PollUntilAtLeast: OSEventObjectClose failed"));
+ }
+ }
+ }
+ }
+Exit:
+ return eError;
+}
+
+static PVRSRV_ERROR FlushKernelOps(PVRSRV_SYNC_DATA *psSyncData)
+{
+ PVRSRV_ERROR eError;
+
+ if(!psSyncData)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FlushKernelOps: invalid psSyncData"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+
+
+
+
+
+
+
+
+ eError = _PollUntilAtLeast(&psSyncData->ui32ReadOpsComplete,
+ psSyncData->ui32ReadOpsPending,
+ MAX_HW_TIME_US/WAIT_TRY_COUNT,
+ WAIT_TRY_COUNT);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FlushClientOps: Read ops pending timeout"));
+ PVR_DBG_BREAK;
+ return eError;
+ }
+
+ eError = _PollUntilAtLeast(&psSyncData->ui32WriteOpsComplete,
+ psSyncData->ui32WriteOpsPending,
+ MAX_HW_TIME_US/WAIT_TRY_COUNT,
+ WAIT_TRY_COUNT);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FlushClientOps: Write ops pending timeout"));
+ PVR_DBG_BREAK;
+ }
+
+ return eError;
+}
+#endif
+
+IMG_EXPORT
+PVRSRV_ERROR FreeMemCallBackCommon(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Param,
+ PVRSRV_FREE_CALLBACK_ORIGIN eCallbackOrigin)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+
+ PVRSRVKernelMemInfoDecRef(psMemInfo);
+
+
+ if (psMemInfo->ui32RefCount == 0)
+ {
+ if((psMemInfo->ui32Flags & PVRSRV_MEM_EXPORTED) != 0)
+ {
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hMemInfo = 0;
+#else
+ IMG_HANDLE hMemInfo = IMG_NULL;
+#endif
+
+
+ eError = PVRSRVFindHandle(KERNEL_HANDLE_BASE,
+ &hMemInfo,
+ psMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeMemCallBackCommon: can't find exported meminfo in the global handle list"));
+ return eError;
+ }
+
+
+ eError = PVRSRVReleaseHandle(KERNEL_HANDLE_BASE,
+ hMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeMemCallBackCommon: PVRSRVReleaseHandle failed for exported meminfo"));
+ return eError;
+ }
+ }
+
+#if defined (PVRSRV_FLUSH_KERNEL_OPS_LAST_ONLY)
+ if (psMemInfo->psKernelSyncInfo)
+ {
+ if (psMemInfo->psKernelSyncInfo->ui32RefCount == 1)
+ {
+ FlushKernelOps(psMemInfo->psKernelSyncInfo->psSyncData);
+ }
+ }
+#endif
+ switch(psMemInfo->memType)
+ {
+
+ case PVRSRV_MEMTYPE_WRAPPED:
+ freeWrapped(psMemInfo);
+ case PVRSRV_MEMTYPE_DEVICE:
+ case PVRSRV_MEMTYPE_DEVICECLASS:
+ if (psMemInfo->psKernelSyncInfo)
+ {
+ PVRSRVKernelSyncInfoDecRef(psMemInfo->psKernelSyncInfo, psMemInfo);
+ }
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "FreeMemCallBackCommon: Unknown memType"));
+ eError = PVRSRV_ERROR_INVALID_MEMINFO;
+ }
+ }
+
+
+ if (eError == PVRSRV_OK)
+ {
+ eError = FreeDeviceMem2(psMemInfo, eCallbackOrigin);
+ }
+
+ return eError;
+}
+
+static PVRSRV_ERROR FreeDeviceMemCallBack(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param,
+ IMG_BOOL bDummy)
+{
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo = (PVRSRV_KERNEL_MEM_INFO *)pvParam;
+
+ PVR_UNREFERENCED_PARAMETER(bDummy);
+
+ return FreeMemCallBackCommon(psMemInfo, ui32Param,
+ PVRSRV_FREE_CALLBACK_ORIGIN_ALLOCATOR);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeDeviceMemKM(IMG_HANDLE hDevCookie,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_UNREFERENCED_PARAMETER(hDevCookie);
+
+ if (!psMemInfo)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if (psMemInfo->sMemBlk.hResItem != IMG_NULL)
+ {
+ eError = ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem, CLEANUP_WITH_POLL);
+ }
+ else
+ {
+
+ eError = FreeDeviceMemCallBack(psMemInfo, 0, CLEANUP_WITH_POLL);
+ }
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV _PVRSRVAllocDeviceMemKM(IMG_HANDLE hDevCookie,
+ PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevMemHeap,
+ IMG_UINT32 ui32Flags,
+ IMG_SIZE_T ui32Size,
+ IMG_SIZE_T ui32Alignment,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfo)
+{
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+ PVRSRV_ERROR eError;
+ BM_HEAP *psBMHeap;
+ IMG_HANDLE hDevMemContext;
+
+ if (!hDevMemHeap ||
+ (ui32Size == 0))
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ if (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)
+ {
+
+ if (((ui32Size % HOST_PAGESIZE()) != 0) ||
+ ((ui32Alignment % HOST_PAGESIZE()) != 0))
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ }
+
+ eError = AllocDeviceMem(hDevCookie,
+ hDevMemHeap,
+ ui32Flags,
+ ui32Size,
+ ui32Alignment,
+ pvPrivData,
+ ui32PrivDataLength,
+ &psMemInfo);
+
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ if (ui32Flags & PVRSRV_MEM_NO_SYNCOBJ)
+ {
+ psMemInfo->psKernelSyncInfo = IMG_NULL;
+ }
+ else
+ {
+
+
+
+ psBMHeap = (BM_HEAP*)hDevMemHeap;
+ hDevMemContext = (IMG_HANDLE)psBMHeap->pBMContext;
+ eError = PVRSRVAllocSyncInfoKM(hDevCookie,
+ hDevMemContext,
+ &psMemInfo->psKernelSyncInfo);
+ if(eError != PVRSRV_OK)
+ {
+ goto free_mainalloc;
+ }
+ }
+
+
+ *ppsMemInfo = psMemInfo;
+
+ if (ui32Flags & PVRSRV_MEM_NO_RESMAN)
+ {
+ psMemInfo->sMemBlk.hResItem = IMG_NULL;
+ }
+ else
+ {
+
+ psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_DEVICEMEM_ALLOCATION,
+ psMemInfo,
+ 0,
+ &FreeDeviceMemCallBack);
+ if (psMemInfo->sMemBlk.hResItem == IMG_NULL)
+ {
+
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto free_mainalloc;
+ }
+ }
+
+
+ PVRSRVKernelMemInfoIncRef(psMemInfo);
+
+ psMemInfo->memType = PVRSRV_MEMTYPE_DEVICE;
+
+
+ return (PVRSRV_OK);
+
+free_mainalloc:
+ if (psMemInfo->psKernelSyncInfo)
+ {
+ PVRSRVKernelSyncInfoDecRef(psMemInfo->psKernelSyncInfo, psMemInfo);
+ }
+ FreeDeviceMem(psMemInfo);
+
+ return eError;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDissociateDeviceMemKM(IMG_HANDLE hDevCookie,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DEVICE_NODE *psDeviceNode = hDevCookie;
+
+ PVR_UNREFERENCED_PARAMETER(hDevCookie);
+
+ if (!psMemInfo)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ eError = ResManDissociateRes(psMemInfo->sMemBlk.hResItem, psDeviceNode->hResManContext);
+
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetFreeDeviceMemKM(IMG_UINT32 ui32Flags,
+ IMG_SIZE_T *pui32Total,
+ IMG_SIZE_T *pui32Free,
+ IMG_SIZE_T *pui32LargestBlock)
+{
+
+
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+ PVR_UNREFERENCED_PARAMETER(pui32Total);
+ PVR_UNREFERENCED_PARAMETER(pui32Free);
+ PVR_UNREFERENCED_PARAMETER(pui32LargestBlock);
+
+ return PVRSRV_OK;
+}
+
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnwrapExtMemoryKM (PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+ if (!psMemInfo)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem, CLEANUP_WITH_POLL);
+}
+
+
+static PVRSRV_ERROR UnwrapExtMemoryCallBack(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param,
+ IMG_BOOL bDummy)
+{
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo = (PVRSRV_KERNEL_MEM_INFO *)pvParam;
+
+ PVR_UNREFERENCED_PARAMETER(bDummy);
+
+ return FreeMemCallBackCommon(psMemInfo, ui32Param,
+ PVRSRV_FREE_CALLBACK_ORIGIN_ALLOCATOR);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVWrapExtMemoryKM(IMG_HANDLE hDevCookie,
+ PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevMemContext,
+ IMG_SIZE_T uByteSize,
+ IMG_SIZE_T uPageOffset,
+ IMG_BOOL bPhysContig,
+ IMG_SYS_PHYADDR *psExtSysPAddr,
+ IMG_VOID *pvLinAddr,
+ IMG_UINT32 ui32Flags,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfo)
+{
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo = IMG_NULL;
+ DEVICE_MEMORY_INFO *psDevMemoryInfo;
+ IMG_SIZE_T ui32HostPageSize = HOST_PAGESIZE();
+ IMG_HANDLE hDevMemHeap = IMG_NULL;
+ PVRSRV_DEVICE_NODE* psDeviceNode;
+ BM_HANDLE hBuffer;
+ PVRSRV_MEMBLK *psMemBlock;
+ IMG_BOOL bBMError;
+ BM_HEAP *psBMHeap;
+ PVRSRV_ERROR eError;
+ IMG_VOID *pvPageAlignedCPUVAddr;
+ IMG_SYS_PHYADDR *psIntSysPAddr = IMG_NULL;
+ IMG_HANDLE hOSWrapMem = IMG_NULL;
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+ IMG_UINT32 i;
+ IMG_SIZE_T uPageCount = 0;
+
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE*)hDevCookie;
+ PVR_ASSERT(psDeviceNode != IMG_NULL);
+
+ if (psDeviceNode == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVWrapExtMemoryKM: invalid parameter"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if(pvLinAddr)
+ {
+
+ uPageOffset = (IMG_UINTPTR_T)pvLinAddr & (ui32HostPageSize - 1);
+
+
+ uPageCount = HOST_PAGEALIGN(uByteSize + uPageOffset) / ui32HostPageSize;
+ pvPageAlignedCPUVAddr = (IMG_VOID *)((IMG_UINTPTR_T)pvLinAddr - uPageOffset);
+
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ uPageCount * sizeof(IMG_SYS_PHYADDR),
+ (IMG_VOID **)&psIntSysPAddr, IMG_NULL,
+ "Array of Page Addresses") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: Failed to alloc memory for block"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ eError = OSAcquirePhysPageAddr(pvPageAlignedCPUVAddr,
+ uPageCount * ui32HostPageSize,
+ psIntSysPAddr,
+ &hOSWrapMem);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: Failed to alloc memory for block"));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ErrorExitPhase1;
+ }
+
+
+ psExtSysPAddr = psIntSysPAddr;
+
+
+
+ bPhysContig = IMG_FALSE;
+ }
+ else
+ {
+
+ }
+
+
+ psDevMemoryInfo = &((BM_CONTEXT*)hDevMemContext)->psDeviceNode->sDevMemoryInfo;
+ psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
+ for(i=0; i<PVRSRV_MAX_CLIENT_HEAPS; i++)
+ {
+ if(HEAP_IDX(psDeviceMemoryHeap[i].ui32HeapID) == psDevMemoryInfo->ui32MappingHeapID)
+ {
+ if(psDeviceMemoryHeap[i].DevMemHeapType == DEVICE_MEMORY_HEAP_PERCONTEXT)
+ {
+
+ if (psDeviceMemoryHeap[i].ui32HeapSize > 0)
+ {
+ hDevMemHeap = BM_CreateHeap(hDevMemContext, &psDeviceMemoryHeap[i]);
+ }
+ else
+ {
+ hDevMemHeap = IMG_NULL;
+ }
+ }
+ else
+ {
+ hDevMemHeap = psDevMemoryInfo->psDeviceMemoryHeap[i].hDevMemHeap;
+ }
+ break;
+ }
+ }
+
+ if(hDevMemHeap == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: unable to find mapping heap"));
+ eError = PVRSRV_ERROR_UNABLE_TO_FIND_MAPPING_HEAP;
+ goto ErrorExitPhase2;
+ }
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO),
+ (IMG_VOID **)&psMemInfo, IMG_NULL,
+ "Kernel Memory Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: Failed to alloc memory for block"));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ErrorExitPhase2;
+ }
+
+ OSMemSet(psMemInfo, 0, sizeof(*psMemInfo));
+ psMemInfo->ui32Flags = ui32Flags;
+
+ psMemBlock = &(psMemInfo->sMemBlk);
+
+ bBMError = BM_Wrap(hDevMemHeap,
+ uByteSize,
+ uPageOffset,
+ bPhysContig,
+ psExtSysPAddr,
+ IMG_NULL,
+ &psMemInfo->ui32Flags,
+ &hBuffer);
+ if (!bBMError)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: BM_Wrap Failed"));
+ eError = PVRSRV_ERROR_BAD_MAPPING;
+ goto ErrorExitPhase3;
+ }
+
+
+ psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
+ psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
+ psMemBlock->hOSWrapMem = hOSWrapMem;
+ psMemBlock->psIntSysPAddr = psIntSysPAddr;
+
+
+ psMemBlock->hBuffer = (IMG_HANDLE)hBuffer;
+
+
+ psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer);
+ psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
+ psMemInfo->uAllocSize = uByteSize;
+
+
+
+ psMemInfo->pvSysBackupBuffer = IMG_NULL;
+
+
+
+
+ psBMHeap = (BM_HEAP*)hDevMemHeap;
+ hDevMemContext = (IMG_HANDLE)psBMHeap->pBMContext;
+ eError = PVRSRVAllocSyncInfoKM(hDevCookie,
+ hDevMemContext,
+ &psMemInfo->psKernelSyncInfo);
+ if(eError != PVRSRV_OK)
+ {
+ goto ErrorExitPhase4;
+ }
+
+
+ PVRSRVKernelMemInfoIncRef(psMemInfo);
+
+ psMemInfo->memType = PVRSRV_MEMTYPE_WRAPPED;
+
+
+ psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_DEVICEMEM_WRAP,
+ psMemInfo,
+ 0,
+ &UnwrapExtMemoryCallBack);
+
+
+ *ppsMemInfo = psMemInfo;
+
+ return PVRSRV_OK;
+
+
+
+ErrorExitPhase4:
+ if(psMemInfo)
+ {
+ FreeDeviceMem(psMemInfo);
+
+
+
+ psMemInfo = IMG_NULL;
+ }
+
+ErrorExitPhase3:
+ if(psMemInfo)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
+
+ }
+
+ErrorExitPhase2:
+ if(psIntSysPAddr)
+ {
+ OSReleasePhysPageAddr(hOSWrapMem);
+ }
+
+ErrorExitPhase1:
+ if(psIntSysPAddr)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, uPageCount * sizeof(IMG_SYS_PHYADDR), psIntSysPAddr, IMG_NULL);
+
+ }
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceMemoryKM (PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+ if (!psMemInfo)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem, CLEANUP_WITH_POLL);
+}
+
+
+static PVRSRV_ERROR UnmapDeviceMemoryCallBack(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param,
+ IMG_BOOL bDummy)
+{
+ PVRSRV_ERROR eError;
+ RESMAN_MAP_DEVICE_MEM_DATA *psMapData = pvParam;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+ PVR_UNREFERENCED_PARAMETER(bDummy);
+
+ if(psMapData->psMemInfo->sMemBlk.psIntSysPAddr)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(IMG_SYS_PHYADDR), psMapData->psMemInfo->sMemBlk.psIntSysPAddr, IMG_NULL);
+ psMapData->psMemInfo->sMemBlk.psIntSysPAddr = IMG_NULL;
+ }
+
+ if( psMapData->psMemInfo->psKernelSyncInfo )
+ {
+ PVRSRVKernelSyncInfoDecRef(psMapData->psMemInfo->psKernelSyncInfo, psMapData->psMemInfo);
+ }
+
+ eError = FreeDeviceMem(psMapData->psMemInfo);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"UnmapDeviceMemoryCallBack: Failed to free DST meminfo"));
+ return eError;
+ }
+
+
+ eError = FreeMemCallBackCommon(psMapData->psSrcMemInfo, 0,
+ PVRSRV_FREE_CALLBACK_ORIGIN_IMPORTER);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_MAP_DEVICE_MEM_DATA), psMapData, IMG_NULL);
+
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceMemoryKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ PVRSRV_KERNEL_MEM_INFO *psSrcMemInfo,
+ IMG_HANDLE hDstDevMemHeap,
+ PVRSRV_KERNEL_MEM_INFO **ppsDstMemInfo)
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 i;
+ IMG_SIZE_T uPageCount, uPageOffset;
+ IMG_SIZE_T ui32HostPageSize = HOST_PAGESIZE();
+ IMG_SYS_PHYADDR *psSysPAddr = IMG_NULL;
+ IMG_DEV_PHYADDR sDevPAddr;
+ BM_BUF *psBuf;
+ IMG_DEV_VIRTADDR sDevVAddr;
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo = IMG_NULL;
+ BM_HANDLE hBuffer;
+ PVRSRV_MEMBLK *psMemBlock;
+ IMG_BOOL bBMError;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_VOID *pvPageAlignedCPUVAddr;
+ RESMAN_MAP_DEVICE_MEM_DATA *psMapData = IMG_NULL;
+
+
+ if(!psSrcMemInfo || !hDstDevMemHeap || !ppsDstMemInfo)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ *ppsDstMemInfo = IMG_NULL;
+
+ uPageOffset = psSrcMemInfo->sDevVAddr.uiAddr & (ui32HostPageSize - 1);
+ uPageCount = HOST_PAGEALIGN(psSrcMemInfo->uAllocSize + uPageOffset) / ui32HostPageSize;
+ pvPageAlignedCPUVAddr = (IMG_VOID *)((IMG_UINTPTR_T)psSrcMemInfo->pvLinAddrKM - uPageOffset);
+
+
+
+
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ uPageCount*sizeof(IMG_SYS_PHYADDR),
+ (IMG_VOID **)&psSysPAddr, IMG_NULL,
+ "Array of Page Addresses") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: Failed to alloc memory for block"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ psBuf = psSrcMemInfo->sMemBlk.hBuffer;
+
+
+ psDeviceNode = psBuf->pMapping->pBMHeap->pBMContext->psDeviceNode;
+
+
+ sDevVAddr.uiAddr = psSrcMemInfo->sDevVAddr.uiAddr - IMG_CAST_TO_DEVVADDR_UINT(uPageOffset);
+ for(i=0; i<uPageCount; i++)
+ {
+ BM_GetPhysPageAddr(psSrcMemInfo, sDevVAddr, &sDevPAddr);
+
+
+ psSysPAddr[i] = SysDevPAddrToSysPAddr (psDeviceNode->sDevId.eDeviceType, sDevPAddr);
+
+
+ sDevVAddr.uiAddr += IMG_CAST_TO_DEVVADDR_UINT(ui32HostPageSize);
+ }
+
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(RESMAN_MAP_DEVICE_MEM_DATA),
+ (IMG_VOID **)&psMapData, IMG_NULL,
+ "Resource Manager Map Data") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: Failed to alloc resman map data"));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ErrorExit;
+ }
+
+ if(OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(PVRSRV_KERNEL_MEM_INFO),
+ (IMG_VOID **)&psMemInfo, IMG_NULL,
+ "Kernel Memory Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: Failed to alloc memory for block"));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ErrorExit;
+ }
+
+ OSMemSet(psMemInfo, 0, sizeof(*psMemInfo));
+ psMemInfo->ui32Flags = psSrcMemInfo->ui32Flags;
+
+ psMemBlock = &(psMemInfo->sMemBlk);
+
+ bBMError = BM_Wrap(hDstDevMemHeap,
+ psSrcMemInfo->uAllocSize,
+ uPageOffset,
+ IMG_FALSE,
+ psSysPAddr,
+ pvPageAlignedCPUVAddr,
+ &psMemInfo->ui32Flags,
+ &hBuffer);
+
+ if (!bBMError)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: BM_Wrap Failed"));
+ eError = PVRSRV_ERROR_BAD_MAPPING;
+ goto ErrorExit;
+ }
+
+
+ psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
+ psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
+
+
+ psMemBlock->hBuffer = (IMG_HANDLE)hBuffer;
+
+
+ psMemBlock->psIntSysPAddr = psSysPAddr;
+
+
+ psMemInfo->pvLinAddrKM = psSrcMemInfo->pvLinAddrKM;
+
+
+ psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
+ psMemInfo->uAllocSize = psSrcMemInfo->uAllocSize;
+ psMemInfo->psKernelSyncInfo = psSrcMemInfo->psKernelSyncInfo;
+
+
+ if(psMemInfo->psKernelSyncInfo)
+ {
+ PVRSRVKernelSyncInfoIncRef(psMemInfo->psKernelSyncInfo, psMemInfo);
+ }
+
+
+
+ psMemInfo->pvSysBackupBuffer = IMG_NULL;
+
+
+ PVRSRVKernelMemInfoIncRef(psMemInfo);
+
+
+ PVRSRVKernelMemInfoIncRef(psSrcMemInfo);
+
+
+ BM_Export(psSrcMemInfo->sMemBlk.hBuffer);
+
+ psMemInfo->memType = PVRSRV_MEMTYPE_MAPPED;
+
+
+ psMapData->psMemInfo = psMemInfo;
+ psMapData->psSrcMemInfo = psSrcMemInfo;
+
+
+ psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_DEVICEMEM_MAPPING,
+ psMapData,
+ 0,
+ &UnmapDeviceMemoryCallBack);
+
+ *ppsDstMemInfo = psMemInfo;
+
+ return PVRSRV_OK;
+
+
+
+ErrorExit:
+
+ if(psSysPAddr)
+ {
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(IMG_SYS_PHYADDR), psSysPAddr, IMG_NULL);
+
+ }
+
+ if(psMemInfo)
+ {
+
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
+
+ }
+
+ if(psMapData)
+ {
+
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(RESMAN_MAP_DEVICE_MEM_DATA), psMapData, IMG_NULL);
+
+ }
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceClassMemoryKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+ if (!psMemInfo)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem, CLEANUP_WITH_POLL);
+}
+
+
+static PVRSRV_ERROR UnmapDeviceClassMemoryCallBack(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param,
+ IMG_BOOL bDummy)
+{
+ PVRSRV_DC_MAPINFO *psDCMapInfo = pvParam;
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+ PVR_UNREFERENCED_PARAMETER(bDummy);
+
+ psMemInfo = psDCMapInfo->psMemInfo;
+
+#if defined(SUPPORT_MEMORY_TILING)
+ if(psDCMapInfo->ui32TilingStride > 0)
+ {
+ PVRSRV_DEVICE_NODE *psDeviceNode = psDCMapInfo->psDeviceNode;
+
+ if (psDeviceNode->pfnFreeMemTilingRange(psDeviceNode,
+ psDCMapInfo->ui32RangeIndex) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"UnmapDeviceClassMemoryCallBack: FreeMemTilingRange failed"));
+ }
+ }
+#endif
+
+ (psDCMapInfo->psDeviceClassBuffer->ui32MemMapRefCount)--;
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_MAPINFO), psDCMapInfo, IMG_NULL);
+
+ return FreeMemCallBackCommon(psMemInfo, ui32Param,
+ PVRSRV_FREE_CALLBACK_ORIGIN_ALLOCATOR);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceClassMemoryKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevMemContext,
+ IMG_HANDLE hDeviceClassBuffer,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfo,
+ IMG_HANDLE *phOSMapInfo)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DEVICE_NODE* psDeviceNode;
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo = IMG_NULL;
+ PVRSRV_DEVICECLASS_BUFFER *psDeviceClassBuffer;
+ IMG_SYS_PHYADDR *psSysPAddr;
+ IMG_VOID *pvCPUVAddr, *pvPageAlignedCPUVAddr;
+ IMG_BOOL bPhysContig;
+ BM_CONTEXT *psBMContext;
+ DEVICE_MEMORY_INFO *psDevMemoryInfo;
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+ IMG_HANDLE hDevMemHeap = IMG_NULL;
+ IMG_SIZE_T uByteSize;
+ IMG_SIZE_T ui32Offset;
+ IMG_SIZE_T ui32PageSize = HOST_PAGESIZE();
+ BM_HANDLE hBuffer;
+ PVRSRV_MEMBLK *psMemBlock;
+ IMG_BOOL bBMError;
+ IMG_UINT32 i;
+ PVRSRV_DC_MAPINFO *psDCMapInfo = IMG_NULL;
+
+ if(!hDeviceClassBuffer || !ppsMemInfo || !phOSMapInfo || !hDevMemContext)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DC_MAPINFO),
+ (IMG_VOID **)&psDCMapInfo, IMG_NULL,
+ "PVRSRV_DC_MAPINFO") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: Failed to alloc memory for psDCMapInfo"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OSMemSet(psDCMapInfo, 0, sizeof(PVRSRV_DC_MAPINFO));
+
+ psDeviceClassBuffer = (PVRSRV_DEVICECLASS_BUFFER*)hDeviceClassBuffer;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ eError = psDeviceClassBuffer->pfnGetBufferAddr(psDeviceClassBuffer->hExtDevice,
+ psDeviceClassBuffer->hExtBuffer,
+ &psSysPAddr,
+ &uByteSize,
+ &pvCPUVAddr,
+ phOSMapInfo,
+ &bPhysContig,
+ &psDCMapInfo->ui32TilingStride);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: unable to get buffer address"));
+ goto ErrorExitPhase1;
+ }
+
+
+ psBMContext = (BM_CONTEXT*)psDeviceClassBuffer->hDevMemContext;
+ psDeviceNode = psBMContext->psDeviceNode;
+ psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+ psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
+ for(i=0; i<PVRSRV_MAX_CLIENT_HEAPS; i++)
+ {
+ if(HEAP_IDX(psDeviceMemoryHeap[i].ui32HeapID) == psDevMemoryInfo->ui32MappingHeapID)
+ {
+ if(psDeviceMemoryHeap[i].DevMemHeapType == DEVICE_MEMORY_HEAP_PERCONTEXT)
+ {
+
+ if (psDeviceMemoryHeap[i].ui32HeapSize > 0)
+ {
+ hDevMemHeap = BM_CreateHeap(hDevMemContext, &psDeviceMemoryHeap[i]);
+ }
+ else
+ {
+ hDevMemHeap = IMG_NULL;
+ }
+ }
+ else
+ {
+ hDevMemHeap = psDevMemoryInfo->psDeviceMemoryHeap[i].hDevMemHeap;
+ }
+ break;
+ }
+ }
+
+ if(hDevMemHeap == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: unable to find mapping heap"));
+ eError = PVRSRV_ERROR_UNABLE_TO_FIND_RESOURCE;
+ goto ErrorExitPhase1;
+ }
+
+
+ ui32Offset = ((IMG_UINTPTR_T)pvCPUVAddr) & (ui32PageSize - 1);
+ pvPageAlignedCPUVAddr = (IMG_VOID *)((IMG_UINTPTR_T)pvCPUVAddr - ui32Offset);
+
+ eError = OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(PVRSRV_KERNEL_MEM_INFO),
+ (IMG_VOID **)&psMemInfo, IMG_NULL,
+ "Kernel Memory Info");
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: Failed to alloc memory for block"));
+ goto ErrorExitPhase1;
+ }
+
+ OSMemSet(psMemInfo, 0, sizeof(*psMemInfo));
+
+ psMemBlock = &(psMemInfo->sMemBlk);
+
+ bBMError = BM_Wrap(hDevMemHeap,
+ uByteSize,
+ ui32Offset,
+ bPhysContig,
+ psSysPAddr,
+ pvPageAlignedCPUVAddr,
+ &psMemInfo->ui32Flags,
+ &hBuffer);
+
+ if (!bBMError)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: BM_Wrap Failed"));
+
+ eError = PVRSRV_ERROR_BAD_MAPPING;
+ goto ErrorExitPhase2;
+ }
+
+
+ psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
+ psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
+
+
+ psMemBlock->hBuffer = (IMG_HANDLE)hBuffer;
+
+
+
+ psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer);
+
+
+ psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
+ psMemInfo->uAllocSize = uByteSize;
+ psMemInfo->psKernelSyncInfo = psDeviceClassBuffer->psKernelSyncInfo;
+
+ PVR_ASSERT(psMemInfo->psKernelSyncInfo != IMG_NULL);
+ if (psMemInfo->psKernelSyncInfo)
+ {
+ PVRSRVKernelSyncInfoIncRef(psMemInfo->psKernelSyncInfo, psMemInfo);
+ }
+
+
+
+ psMemInfo->pvSysBackupBuffer = IMG_NULL;
+
+
+ psDCMapInfo->psMemInfo = psMemInfo;
+ psDCMapInfo->psDeviceClassBuffer = psDeviceClassBuffer;
+
+#if defined(SUPPORT_MEMORY_TILING)
+ psDCMapInfo->psDeviceNode = psDeviceNode;
+
+ if(psDCMapInfo->ui32TilingStride > 0)
+ {
+
+ eError = psDeviceNode->pfnAllocMemTilingRange(psDeviceNode,
+ psMemInfo,
+ psDCMapInfo->ui32TilingStride,
+ &psDCMapInfo->ui32RangeIndex);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: AllocMemTilingRange failed"));
+ goto ErrorExitPhase3;
+ }
+ }
+#endif
+
+
+ psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_DEVICECLASSMEM_MAPPING,
+ psDCMapInfo,
+ 0,
+ &UnmapDeviceClassMemoryCallBack);
+
+ (psDeviceClassBuffer->ui32MemMapRefCount)++;
+ PVRSRVKernelMemInfoIncRef(psMemInfo);
+
+ psMemInfo->memType = PVRSRV_MEMTYPE_DEVICECLASS;
+
+
+ *ppsMemInfo = psMemInfo;
+
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+
+ if(psMemInfo->pvLinAddrKM)
+ {
+
+ PDUMPCOMMENT("Dump display surface");
+ PDUMPMEM(IMG_NULL, psMemInfo, ui32Offset, psMemInfo->uAllocSize, PDUMP_FLAGS_CONTINUOUS, ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping);
+ }
+#endif
+ return PVRSRV_OK;
+
+#if defined(SUPPORT_MEMORY_TILING)
+ErrorExitPhase3:
+ if(psMemInfo)
+ {
+ if (psMemInfo->psKernelSyncInfo)
+ {
+ PVRSRVKernelSyncInfoDecRef(psMemInfo->psKernelSyncInfo, psMemInfo);
+ }
+
+ FreeDeviceMem(psMemInfo);
+
+
+
+ psMemInfo = IMG_NULL;
+ }
+#endif
+
+ErrorExitPhase2:
+ if(psMemInfo)
+ {
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
+ }
+
+ErrorExitPhase1:
+ if(psDCMapInfo)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_MEM_INFO), psDCMapInfo, IMG_NULL);
+ }
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVChangeDeviceMemoryAttributesKM(IMG_HANDLE hKernelMemInfo, IMG_UINT32 ui32Attribs)
+{
+ PVRSRV_KERNEL_MEM_INFO *psKMMemInfo;
+
+ if (hKernelMemInfo == IMG_NULL)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psKMMemInfo = (PVRSRV_KERNEL_MEM_INFO *)hKernelMemInfo;
+
+ if (ui32Attribs & PVRSRV_CHANGEDEVMEM_ATTRIBS_CACHECOHERENT)
+ {
+ psKMMemInfo->ui32Flags |= PVRSRV_MEM_CACHE_CONSISTENT;
+ }
+ else
+ {
+ psKMMemInfo->ui32Flags &= ~PVRSRV_MEM_CACHE_CONSISTENT;
+ }
+
+ return PVRSRV_OK;
+}
+
+
diff --git a/drivers/gpu/pvr/env_data.h b/drivers/gpu/pvr/env_data.h
new file mode 100644
index 0000000..7716529
--- /dev/null
+++ b/drivers/gpu/pvr/env_data.h
@@ -0,0 +1,66 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef _ENV_DATA_
+#define _ENV_DATA_
+
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+
+#if defined(PVR_LINUX_MISR_USING_WORKQUEUE) || defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+#include <linux/workqueue.h>
+#endif
+
+#define PVRSRV_MAX_BRIDGE_IN_SIZE 0x1000
+#define PVRSRV_MAX_BRIDGE_OUT_SIZE 0x1000
+
+typedef struct _PVR_PCI_DEV_TAG
+{
+ struct pci_dev *psPCIDev;
+ HOST_PCI_INIT_FLAGS ePCIFlags;
+ IMG_BOOL abPCIResourceInUse[DEVICE_COUNT_RESOURCE];
+} PVR_PCI_DEV;
+
+typedef struct _ENV_DATA_TAG
+{
+ IMG_VOID *pvBridgeData;
+ struct pm_dev *psPowerDevice;
+ IMG_BOOL bLISRInstalled;
+ IMG_BOOL bMISRInstalled;
+ IMG_UINT32 ui32IRQ;
+ IMG_VOID *pvISRCookie;
+#if defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+ struct workqueue_struct *psWorkQueue;
+#endif
+#if defined(PVR_LINUX_MISR_USING_WORKQUEUE) || defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+ struct work_struct sMISRWork;
+ IMG_VOID *pvMISRData;
+#else
+ struct tasklet_struct sMISRTasklet;
+#endif
+} ENV_DATA;
+
+#endif
diff --git a/drivers/gpu/pvr/env_perproc.h b/drivers/gpu/pvr/env_perproc.h
new file mode 100644
index 0000000..dabf1e3
--- /dev/null
+++ b/drivers/gpu/pvr/env_perproc.h
@@ -0,0 +1,56 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __ENV_PERPROC_H__
+#define __ENV_PERPROC_H__
+
+#include <linux/list.h>
+#include <linux/proc_fs.h>
+
+#include "services.h"
+#include "handle.h"
+
+typedef struct _PVRSRV_ENV_PER_PROCESS_DATA_
+{
+ IMG_HANDLE hBlockAlloc;
+ struct proc_dir_entry *psProcDir;
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+ struct list_head sDRMAuthListHead;
+#endif
+} PVRSRV_ENV_PER_PROCESS_DATA;
+
+IMG_VOID RemovePerProcessProcDir(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc);
+
+PVRSRV_ERROR LinuxMMapPerProcessConnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc);
+
+IMG_VOID LinuxMMapPerProcessDisconnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc);
+
+PVRSRV_ERROR LinuxMMapPerProcessHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase);
+
+IMG_HANDLE LinuxTerminatingProcessPrivateData(IMG_VOID);
+
+#endif
+
diff --git a/drivers/gpu/pvr/event.c b/drivers/gpu/pvr/event.c
new file mode 100644
index 0000000..7e160c3
--- /dev/null
+++ b/drivers/gpu/pvr/event.c
@@ -0,0 +1,293 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#endif
+
+#include <asm/io.h>
+#include <asm/page.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
+#include <asm/system.h>
+#endif
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <asm/hardirq.h>
+#include <linux/spinlock.h>
+#include <linux/timer.h>
+#include <linux/capability.h>
+#include <linux/sched.h>
+#include <asm/uaccess.h>
+
+#include "img_types.h"
+#include "services_headers.h"
+#include "mm.h"
+#include "pvrmmap.h"
+#include "mmap.h"
+#include "env_data.h"
+#include "proc.h"
+#include "mutex.h"
+#include "lock.h"
+#include "event.h"
+
+typedef struct PVRSRV_LINUX_EVENT_OBJECT_LIST_TAG
+{
+ rwlock_t sLock;
+ struct list_head sList;
+
+} PVRSRV_LINUX_EVENT_OBJECT_LIST;
+
+
+typedef struct PVRSRV_LINUX_EVENT_OBJECT_TAG
+{
+ atomic_t sTimeStamp;
+ IMG_UINT32 ui32TimeStampPrevious;
+#if defined(DEBUG)
+ IMG_UINT ui32Stats;
+#endif
+ wait_queue_head_t sWait;
+ struct list_head sList;
+ IMG_HANDLE hResItem;
+ PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList;
+} PVRSRV_LINUX_EVENT_OBJECT;
+
+PVRSRV_ERROR LinuxEventObjectListCreate(IMG_HANDLE *phEventObjectList)
+{
+ PVRSRV_LINUX_EVENT_OBJECT_LIST *psEventObjectList;
+
+ if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT_LIST),
+ (IMG_VOID **)&psEventObjectList, IMG_NULL,
+ "Linux Event Object List") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectCreate: failed to allocate memory for event list"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ INIT_LIST_HEAD(&psEventObjectList->sList);
+
+ rwlock_init(&psEventObjectList->sLock);
+
+ *phEventObjectList = (IMG_HANDLE *) psEventObjectList;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR LinuxEventObjectListDestroy(IMG_HANDLE hEventObjectList)
+{
+
+ PVRSRV_LINUX_EVENT_OBJECT_LIST *psEventObjectList = (PVRSRV_LINUX_EVENT_OBJECT_LIST *) hEventObjectList ;
+
+ if(psEventObjectList)
+ {
+ IMG_BOOL bListEmpty;
+
+ read_lock(&psEventObjectList->sLock);
+ bListEmpty = list_empty(&psEventObjectList->sList);
+ read_unlock(&psEventObjectList->sLock);
+
+ if (!bListEmpty)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectListDestroy: Event List is not empty"));
+ return PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT;
+ }
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT_LIST), psEventObjectList, IMG_NULL);
+
+ }
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR LinuxEventObjectDelete(IMG_HANDLE hOSEventObjectList, IMG_HANDLE hOSEventObject)
+{
+ if(hOSEventObjectList)
+ {
+ if(hOSEventObject)
+ {
+ PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = (PVRSRV_LINUX_EVENT_OBJECT *)hOSEventObject;
+#if defined(DEBUG)
+ PVR_DPF((PVR_DBG_MESSAGE, "LinuxEventObjectListDelete: Event object waits: %u", psLinuxEventObject->ui32Stats));
+#endif
+ if(ResManFreeResByPtr(psLinuxEventObject->hResItem, CLEANUP_WITH_POLL) != PVRSRV_OK)
+ {
+ return PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT;
+ }
+
+ return PVRSRV_OK;
+ }
+ }
+ return PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT;
+
+}
+
+static PVRSRV_ERROR LinuxEventObjectDeleteCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param, IMG_BOOL bForceCleanup)
+{
+ PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = pvParam;
+ PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList = psLinuxEventObject->psLinuxEventObjectList;
+ unsigned long ulLockFlags;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+ PVR_UNREFERENCED_PARAMETER(bForceCleanup);
+
+ write_lock_irqsave(&psLinuxEventObjectList->sLock, ulLockFlags);
+ list_del(&psLinuxEventObject->sList);
+ write_unlock_irqrestore(&psLinuxEventObjectList->sLock, ulLockFlags);
+
+#if defined(DEBUG)
+ PVR_DPF((PVR_DBG_MESSAGE, "LinuxEventObjectDeleteCallback: Event object waits: %u", psLinuxEventObject->ui32Stats));
+#endif
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT), psLinuxEventObject, IMG_NULL);
+
+
+ return PVRSRV_OK;
+}
+PVRSRV_ERROR LinuxEventObjectAdd(IMG_HANDLE hOSEventObjectList, IMG_HANDLE *phOSEventObject)
+ {
+ PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject;
+ PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList = (PVRSRV_LINUX_EVENT_OBJECT_LIST*)hOSEventObjectList;
+ IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+ PVRSRV_PER_PROCESS_DATA *psPerProc;
+ unsigned long ulLockFlags;
+
+ psPerProc = PVRSRVPerProcessData(ui32PID);
+ if (psPerProc == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectAdd: Couldn't find per-process data"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+
+ if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT),
+ (IMG_VOID **)&psLinuxEventObject, IMG_NULL,
+ "Linux Event Object") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectAdd: failed to allocate memory "));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ INIT_LIST_HEAD(&psLinuxEventObject->sList);
+
+ atomic_set(&psLinuxEventObject->sTimeStamp, 0);
+ psLinuxEventObject->ui32TimeStampPrevious = 0;
+
+#if defined(DEBUG)
+ psLinuxEventObject->ui32Stats = 0;
+#endif
+ init_waitqueue_head(&psLinuxEventObject->sWait);
+
+ psLinuxEventObject->psLinuxEventObjectList = psLinuxEventObjectList;
+
+ psLinuxEventObject->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_EVENT_OBJECT,
+ psLinuxEventObject,
+ 0,
+ &LinuxEventObjectDeleteCallback);
+
+ write_lock_irqsave(&psLinuxEventObjectList->sLock, ulLockFlags);
+ list_add(&psLinuxEventObject->sList, &psLinuxEventObjectList->sList);
+ write_unlock_irqrestore(&psLinuxEventObjectList->sLock, ulLockFlags);
+
+ *phOSEventObject = psLinuxEventObject;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR LinuxEventObjectSignal(IMG_HANDLE hOSEventObjectList)
+{
+ PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject;
+ PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList = (PVRSRV_LINUX_EVENT_OBJECT_LIST*)hOSEventObjectList;
+ struct list_head *psListEntry, *psList;
+
+ psList = &psLinuxEventObjectList->sList;
+
+
+ read_lock(&psLinuxEventObjectList->sLock);
+ list_for_each(psListEntry, psList)
+ {
+
+ psLinuxEventObject = (PVRSRV_LINUX_EVENT_OBJECT *)list_entry(psListEntry, PVRSRV_LINUX_EVENT_OBJECT, sList);
+
+ atomic_inc(&psLinuxEventObject->sTimeStamp);
+ wake_up_interruptible(&psLinuxEventObject->sWait);
+ }
+ read_unlock(&psLinuxEventObjectList->sLock);
+
+ return PVRSRV_OK;
+
+}
+
+PVRSRV_ERROR LinuxEventObjectWait(IMG_HANDLE hOSEventObject, IMG_UINT32 ui32MSTimeout)
+{
+ IMG_UINT32 ui32TimeStamp;
+ DEFINE_WAIT(sWait);
+
+ PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = (PVRSRV_LINUX_EVENT_OBJECT *) hOSEventObject;
+
+ IMG_UINT32 ui32TimeOutJiffies = msecs_to_jiffies(ui32MSTimeout);
+
+ do
+ {
+ prepare_to_wait(&psLinuxEventObject->sWait, &sWait, TASK_INTERRUPTIBLE);
+ ui32TimeStamp = (IMG_UINT32)atomic_read(&psLinuxEventObject->sTimeStamp);
+
+ if(psLinuxEventObject->ui32TimeStampPrevious != ui32TimeStamp)
+ {
+ break;
+ }
+
+ LinuxUnLockMutex(&gPVRSRVLock);
+
+ ui32TimeOutJiffies = (IMG_UINT32)schedule_timeout((IMG_INT32)ui32TimeOutJiffies);
+
+ LinuxLockMutex(&gPVRSRVLock);
+#if defined(DEBUG)
+ psLinuxEventObject->ui32Stats++;
+#endif
+
+
+ } while (ui32TimeOutJiffies);
+
+ finish_wait(&psLinuxEventObject->sWait, &sWait);
+
+ psLinuxEventObject->ui32TimeStampPrevious = ui32TimeStamp;
+
+ return ui32TimeOutJiffies ? PVRSRV_OK : PVRSRV_ERROR_TIMEOUT;
+
+}
+
diff --git a/drivers/gpu/pvr/event.h b/drivers/gpu/pvr/event.h
new file mode 100644
index 0000000..3035283
--- /dev/null
+++ b/drivers/gpu/pvr/event.h
@@ -0,0 +1,32 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+PVRSRV_ERROR LinuxEventObjectListCreate(IMG_HANDLE *phEventObjectList);
+PVRSRV_ERROR LinuxEventObjectListDestroy(IMG_HANDLE hEventObjectList);
+PVRSRV_ERROR LinuxEventObjectAdd(IMG_HANDLE hOSEventObjectList, IMG_HANDLE *phOSEventObject);
+PVRSRV_ERROR LinuxEventObjectDelete(IMG_HANDLE hOSEventObjectList, IMG_HANDLE hOSEventObject);
+PVRSRV_ERROR LinuxEventObjectSignal(IMG_HANDLE hOSEventObjectList);
+PVRSRV_ERROR LinuxEventObjectWait(IMG_HANDLE hOSEventObject, IMG_UINT32 ui32MSTimeout);
diff --git a/drivers/gpu/pvr/handle.c b/drivers/gpu/pvr/handle.c
new file mode 100644
index 0000000..d911b38
--- /dev/null
+++ b/drivers/gpu/pvr/handle.c
@@ -0,0 +1,1873 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#if defined(PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE)
+#include <stddef.h>
+
+#include "services_headers.h"
+#include "handle.h"
+
+#ifdef DEBUG
+#define HANDLE_BLOCK_SHIFT 2
+#else
+#define HANDLE_BLOCK_SHIFT 8
+#endif
+
+#define DIVIDE_BY_BLOCK_SIZE(i) (((IMG_UINT32)(i)) >> HANDLE_BLOCK_SHIFT)
+#define MULTIPLY_BY_BLOCK_SIZE(i) (((IMG_UINT32)(i)) << HANDLE_BLOCK_SHIFT)
+
+#define HANDLE_BLOCK_SIZE MULTIPLY_BY_BLOCK_SIZE(1)
+#define HANDLE_SUB_BLOCK_MASK (HANDLE_BLOCK_SIZE - 1)
+#define HANDLE_BLOCK_MASK (~(HANDLE_SUB_BLOCK_MASK))
+
+#define HANDLE_HASH_TAB_INIT_SIZE 32
+
+#define INDEX_IS_VALID(psBase, i) ((i) < (psBase)->ui32TotalHandCount)
+
+#if defined (SUPPORT_SID_INTERFACE)
+#define INDEX_TO_HANDLE(i) ((IMG_SID)((i) + 1))
+#define HANDLE_TO_INDEX(h) ((IMG_UINT32)(h) - 1)
+#else
+#define INDEX_TO_HANDLE(i) ((IMG_HANDLE)((IMG_UINTPTR_T)(i) + 1))
+#define HANDLE_TO_INDEX(h) ((IMG_UINT32)(IMG_UINTPTR_T)(h) - 1)
+
+#endif
+
+#define INDEX_TO_BLOCK_INDEX(i) DIVIDE_BY_BLOCK_SIZE(i)
+#define BLOCK_INDEX_TO_INDEX(i) MULTIPLY_BY_BLOCK_SIZE(i)
+#define INDEX_TO_SUB_BLOCK_INDEX(i) ((i) & HANDLE_SUB_BLOCK_MASK)
+
+#define INDEX_TO_INDEX_STRUCT_PTR(psArray, i) (&((psArray)[INDEX_TO_BLOCK_INDEX(i)]))
+#define BASE_AND_INDEX_TO_INDEX_STRUCT_PTR(psBase, i) INDEX_TO_INDEX_STRUCT_PTR((psBase)->psHandleArray, i)
+
+#define INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, i) (BASE_AND_INDEX_TO_INDEX_STRUCT_PTR(psBase, i)->ui32FreeHandBlockCount)
+
+#define INDEX_TO_HANDLE_STRUCT_PTR(psBase, i) (BASE_AND_INDEX_TO_INDEX_STRUCT_PTR(psBase, i)->psHandle + INDEX_TO_SUB_BLOCK_INDEX(i))
+
+#define HANDLE_TO_HANDLE_STRUCT_PTR(psBase, h) (INDEX_TO_HANDLE_STRUCT_PTR(psBase, HANDLE_TO_INDEX(h)))
+
+#define HANDLE_PTR_TO_INDEX(psHandle) ((psHandle)->ui32Index)
+#define HANDLE_PTR_TO_HANDLE(psHandle) INDEX_TO_HANDLE(HANDLE_PTR_TO_INDEX(psHandle))
+
+#define ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE(a) (HANDLE_BLOCK_MASK & (a))
+#define ROUND_UP_TO_MULTIPLE_OF_BLOCK_SIZE(a) ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE((a) + HANDLE_BLOCK_SIZE - 1)
+
+#define DEFAULT_MAX_HANDLE 0x7fffffffu
+#define DEFAULT_MAX_INDEX_PLUS_ONE ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE(DEFAULT_MAX_HANDLE)
+
+#define HANDLES_BATCHED(psBase) ((psBase)->ui32HandBatchSize != 0)
+
+#define HANDLE_ARRAY_SIZE(handleCount) DIVIDE_BY_BLOCK_SIZE(ROUND_UP_TO_MULTIPLE_OF_BLOCK_SIZE(handleCount))
+
+#define SET_FLAG(v, f) ((IMG_VOID)((v) |= (f)))
+#define CLEAR_FLAG(v, f) ((IMG_VOID)((v) &= ~(f)))
+#define TEST_FLAG(v, f) ((IMG_BOOL)(((v) & (f)) != 0))
+
+#define TEST_ALLOC_FLAG(psHandle, f) TEST_FLAG((psHandle)->eFlag, f)
+
+#define SET_INTERNAL_FLAG(psHandle, f) SET_FLAG((psHandle)->eInternalFlag, f)
+#define CLEAR_INTERNAL_FLAG(psHandle, f) CLEAR_FLAG((psHandle)->eInternalFlag, f)
+#define TEST_INTERNAL_FLAG(psHandle, f) TEST_FLAG((psHandle)->eInternalFlag, f)
+
+#define BATCHED_HANDLE(psHandle) TEST_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED)
+
+#define SET_BATCHED_HANDLE(psHandle) SET_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED)
+
+#define SET_UNBATCHED_HANDLE(psHandle) CLEAR_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED)
+
+#define BATCHED_HANDLE_PARTIALLY_FREE(psHandle) TEST_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED_PARTIALLY_FREE)
+
+#define SET_BATCHED_HANDLE_PARTIALLY_FREE(psHandle) SET_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED_PARTIALLY_FREE)
+
+#define HANDLE_STRUCT_IS_FREE(psHandle) ((psHandle)->eType == PVRSRV_HANDLE_TYPE_NONE && (psHandle)->eInternalFlag == INTERNAL_HANDLE_FLAG_NONE)
+
+#ifdef MIN
+#undef MIN
+#endif
+
+#define MIN(x, y) (((x) < (y)) ? (x) : (y))
+
+struct sHandleList
+{
+ IMG_UINT32 ui32Prev;
+ IMG_UINT32 ui32Next;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hParent;
+#else
+ IMG_HANDLE hParent;
+#endif
+};
+
+enum ePVRSRVInternalHandleFlag
+{
+ INTERNAL_HANDLE_FLAG_NONE = 0x00,
+ INTERNAL_HANDLE_FLAG_BATCHED = 0x01,
+ INTERNAL_HANDLE_FLAG_BATCHED_PARTIALLY_FREE = 0x02,
+};
+
+struct sHandle
+{
+
+ PVRSRV_HANDLE_TYPE eType;
+
+
+ IMG_VOID *pvData;
+
+
+ IMG_UINT32 ui32NextIndexPlusOne;
+
+
+ enum ePVRSRVInternalHandleFlag eInternalFlag;
+
+
+ PVRSRV_HANDLE_ALLOC_FLAG eFlag;
+
+
+ IMG_UINT32 ui32Index;
+
+
+ struct sHandleList sChildren;
+
+
+ struct sHandleList sSiblings;
+};
+
+struct sHandleIndex
+{
+
+ struct sHandle *psHandle;
+
+
+ IMG_HANDLE hBlockAlloc;
+
+
+ IMG_UINT32 ui32FreeHandBlockCount;
+};
+
+struct _PVRSRV_HANDLE_BASE_
+{
+
+ IMG_HANDLE hBaseBlockAlloc;
+
+
+ IMG_HANDLE hArrayBlockAlloc;
+
+
+ struct sHandleIndex *psHandleArray;
+
+
+ HASH_TABLE *psHashTab;
+
+
+ IMG_UINT32 ui32FreeHandCount;
+
+
+ IMG_UINT32 ui32FirstFreeIndex;
+
+
+ IMG_UINT32 ui32MaxIndexPlusOne;
+
+
+ IMG_UINT32 ui32TotalHandCount;
+
+
+ IMG_UINT32 ui32LastFreeIndexPlusOne;
+
+
+ IMG_UINT32 ui32HandBatchSize;
+
+
+ IMG_UINT32 ui32TotalHandCountPreBatch;
+
+
+ IMG_UINT32 ui32FirstBatchIndexPlusOne;
+
+
+ IMG_UINT32 ui32BatchHandAllocFailures;
+
+
+ IMG_BOOL bPurgingEnabled;
+};
+
+enum eHandKey {
+ HAND_KEY_DATA = 0,
+ HAND_KEY_TYPE,
+ HAND_KEY_PARENT,
+ HAND_KEY_LEN
+};
+
+PVRSRV_HANDLE_BASE *gpsKernelHandleBase = IMG_NULL;
+
+typedef IMG_UINTPTR_T HAND_KEY[HAND_KEY_LEN];
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(HandleListInit)
+#endif
+static INLINE
+#if defined (SUPPORT_SID_INTERFACE)
+IMG_VOID HandleListInit(IMG_UINT32 ui32Index, struct sHandleList *psList, IMG_SID hParent)
+#else
+IMG_VOID HandleListInit(IMG_UINT32 ui32Index, struct sHandleList *psList, IMG_HANDLE hParent)
+#endif
+{
+ psList->ui32Next = ui32Index;
+ psList->ui32Prev = ui32Index;
+ psList->hParent = hParent;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(InitParentList)
+#endif
+static INLINE
+IMG_VOID InitParentList(struct sHandle *psHandle)
+{
+ IMG_UINT32 ui32Parent = HANDLE_PTR_TO_INDEX(psHandle);
+
+ HandleListInit(ui32Parent, &psHandle->sChildren, INDEX_TO_HANDLE(ui32Parent));
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(InitChildEntry)
+#endif
+static INLINE
+IMG_VOID InitChildEntry(struct sHandle *psHandle)
+{
+ HandleListInit(HANDLE_PTR_TO_INDEX(psHandle), &psHandle->sSiblings, IMG_NULL);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(HandleListIsEmpty)
+#endif
+static INLINE
+IMG_BOOL HandleListIsEmpty(IMG_UINT32 ui32Index, struct sHandleList *psList)
+{
+ IMG_BOOL bIsEmpty;
+
+ bIsEmpty = (IMG_BOOL)(psList->ui32Next == ui32Index);
+
+#ifdef DEBUG
+ {
+ IMG_BOOL bIsEmpty2;
+
+ bIsEmpty2 = (IMG_BOOL)(psList->ui32Prev == ui32Index);
+ PVR_ASSERT(bIsEmpty == bIsEmpty2)
+ }
+#endif
+
+ return bIsEmpty;
+}
+
+#ifdef DEBUG
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(NoChildren)
+#endif
+static INLINE
+IMG_BOOL NoChildren(struct sHandle *psHandle)
+{
+ PVR_ASSERT(psHandle->sChildren.hParent == HANDLE_PTR_TO_HANDLE(psHandle))
+
+ return HandleListIsEmpty(HANDLE_PTR_TO_INDEX(psHandle), &psHandle->sChildren);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(NoParent)
+#endif
+static INLINE
+IMG_BOOL NoParent(struct sHandle *psHandle)
+{
+ if (HandleListIsEmpty(HANDLE_PTR_TO_INDEX(psHandle), &psHandle->sSiblings))
+ {
+ PVR_ASSERT(psHandle->sSiblings.hParent == IMG_NULL)
+
+ return IMG_TRUE;
+ }
+ else
+ {
+ PVR_ASSERT(psHandle->sSiblings.hParent != IMG_NULL)
+ }
+ return IMG_FALSE;
+}
+#endif
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(ParentHandle)
+#endif
+static INLINE
+#if defined (SUPPORT_SID_INTERFACE)
+IMG_SID ParentHandle(struct sHandle *psHandle)
+#else
+IMG_HANDLE ParentHandle(struct sHandle *psHandle)
+#endif
+{
+ return psHandle->sSiblings.hParent;
+}
+
+#define LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, i, p, po, eo) \
+ ((struct sHandleList *)((IMG_CHAR *)(INDEX_TO_HANDLE_STRUCT_PTR(psBase, i)) + (((i) == (p)) ? (po) : (eo))))
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(HandleListInsertBefore)
+#endif
+static INLINE
+IMG_VOID HandleListInsertBefore(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32InsIndex, struct sHandleList *psIns, IMG_SIZE_T uiParentOffset, IMG_UINT32 ui32EntryIndex, struct sHandleList *psEntry, IMG_SIZE_T uiEntryOffset, IMG_UINT32 ui32ParentIndex)
+{
+
+ struct sHandleList *psPrevIns = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psIns->ui32Prev, ui32ParentIndex, uiParentOffset, uiEntryOffset);
+
+ PVR_ASSERT(psEntry->hParent == IMG_NULL)
+ PVR_ASSERT(ui32InsIndex == psPrevIns->ui32Next)
+ PVR_ASSERT(LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, ui32ParentIndex, ui32ParentIndex, uiParentOffset, uiParentOffset)->hParent == INDEX_TO_HANDLE(ui32ParentIndex))
+
+ psEntry->ui32Prev = psIns->ui32Prev;
+ psIns->ui32Prev = ui32EntryIndex;
+ psEntry->ui32Next = ui32InsIndex;
+ psPrevIns->ui32Next = ui32EntryIndex;
+
+ psEntry->hParent = INDEX_TO_HANDLE(ui32ParentIndex);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(AdoptChild)
+#endif
+static INLINE
+IMG_VOID AdoptChild(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psParent, struct sHandle *psChild)
+{
+ IMG_UINT32 ui32Parent = HANDLE_TO_INDEX(psParent->sChildren.hParent);
+
+ PVR_ASSERT(ui32Parent == HANDLE_PTR_TO_INDEX(psParent))
+
+ HandleListInsertBefore(psBase, ui32Parent, &psParent->sChildren, offsetof(struct sHandle, sChildren), HANDLE_PTR_TO_INDEX(psChild), &psChild->sSiblings, offsetof(struct sHandle, sSiblings), ui32Parent);
+
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(HandleListRemove)
+#endif
+static INLINE
+IMG_VOID HandleListRemove(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32EntryIndex, struct sHandleList *psEntry, IMG_SIZE_T uiEntryOffset, IMG_SIZE_T uiParentOffset)
+{
+ if (!HandleListIsEmpty(ui32EntryIndex, psEntry))
+ {
+
+ struct sHandleList *psPrev = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psEntry->ui32Prev, HANDLE_TO_INDEX(psEntry->hParent), uiParentOffset, uiEntryOffset);
+ struct sHandleList *psNext = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psEntry->ui32Next, HANDLE_TO_INDEX(psEntry->hParent), uiParentOffset, uiEntryOffset);
+
+
+ PVR_ASSERT(psEntry->hParent != IMG_NULL)
+
+ psPrev->ui32Next = psEntry->ui32Next;
+ psNext->ui32Prev = psEntry->ui32Prev;
+
+ HandleListInit(ui32EntryIndex, psEntry, IMG_NULL);
+ }
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(UnlinkFromParent)
+#endif
+static INLINE
+IMG_VOID UnlinkFromParent(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHandle)
+{
+ HandleListRemove(psBase, HANDLE_PTR_TO_INDEX(psHandle), &psHandle->sSiblings, offsetof(struct sHandle, sSiblings), offsetof(struct sHandle, sChildren));
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(HandleListIterate)
+#endif
+static INLINE
+PVRSRV_ERROR HandleListIterate(PVRSRV_HANDLE_BASE *psBase, struct sHandleList *psHead, IMG_SIZE_T uiParentOffset, IMG_SIZE_T uiEntryOffset, PVRSRV_ERROR (*pfnIterFunc)(PVRSRV_HANDLE_BASE *, struct sHandle *))
+{
+ IMG_UINT32 ui32Index;
+ IMG_UINT32 ui32Parent = HANDLE_TO_INDEX(psHead->hParent);
+
+ PVR_ASSERT(psHead->hParent != IMG_NULL)
+
+
+ for(ui32Index = psHead->ui32Next; ui32Index != ui32Parent; )
+ {
+ struct sHandle *psHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32Index);
+
+ struct sHandleList *psEntry = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, ui32Index, ui32Parent, uiParentOffset, uiEntryOffset);
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(psEntry->hParent == psHead->hParent)
+
+ ui32Index = psEntry->ui32Next;
+
+ eError = (*pfnIterFunc)(psBase, psHandle);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(IterateOverChildren)
+#endif
+static INLINE
+PVRSRV_ERROR IterateOverChildren(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psParent, PVRSRV_ERROR (*pfnIterFunc)(PVRSRV_HANDLE_BASE *, struct sHandle *))
+{
+ return HandleListIterate(psBase, &psParent->sChildren, offsetof(struct sHandle, sChildren), offsetof(struct sHandle, sSiblings), pfnIterFunc);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(GetHandleStructure)
+#endif
+static INLINE
+#if defined (SUPPORT_SID_INTERFACE)
+PVRSRV_ERROR GetHandleStructure(PVRSRV_HANDLE_BASE *psBase, struct sHandle **ppsHandle, IMG_SID hHandle, PVRSRV_HANDLE_TYPE eType)
+#else
+PVRSRV_ERROR GetHandleStructure(PVRSRV_HANDLE_BASE *psBase, struct sHandle **ppsHandle, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+#endif
+{
+ IMG_UINT32 ui32Index = HANDLE_TO_INDEX(hHandle);
+ struct sHandle *psHandle;
+
+
+ if (!INDEX_IS_VALID(psBase, ui32Index))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "GetHandleStructure: Handle index out of range (%u >= %u)", ui32Index, psBase->ui32TotalHandCount));
+#if defined (SUPPORT_SID_INTERFACE)
+ PVR_DBG_BREAK
+#endif
+ return PVRSRV_ERROR_HANDLE_INDEX_OUT_OF_RANGE;
+ }
+
+ psHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32Index);
+ if (psHandle->eType == PVRSRV_HANDLE_TYPE_NONE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "GetHandleStructure: Handle not allocated (index: %u)", ui32Index));
+#if defined (SUPPORT_SID_INTERFACE)
+ PVR_DBG_BREAK
+#endif
+ return PVRSRV_ERROR_HANDLE_NOT_ALLOCATED;
+ }
+
+
+ if (eType != PVRSRV_HANDLE_TYPE_NONE && eType != psHandle->eType)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "GetHandleStructure: Handle type mismatch (%d != %d)", eType, psHandle->eType));
+#if defined (SUPPORT_SID_INTERFACE)
+ PVR_DBG_BREAK
+#endif
+ return PVRSRV_ERROR_HANDLE_TYPE_MISMATCH;
+ }
+
+
+ *ppsHandle = psHandle;
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(ParentIfPrivate)
+#endif
+static INLINE
+#if defined (SUPPORT_SID_INTERFACE)
+IMG_SID ParentIfPrivate(struct sHandle *psHandle)
+#else
+IMG_HANDLE ParentIfPrivate(struct sHandle *psHandle)
+#endif
+{
+ return TEST_ALLOC_FLAG(psHandle, PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE) ?
+ ParentHandle(psHandle) : IMG_NULL;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(InitKey)
+#endif
+static INLINE
+#if defined (SUPPORT_SID_INTERFACE)
+IMG_VOID InitKey(HAND_KEY aKey, PVRSRV_HANDLE_BASE *psBase, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, IMG_SID hParent)
+#else
+IMG_VOID InitKey(HAND_KEY aKey, PVRSRV_HANDLE_BASE *psBase, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hParent)
+#endif
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ aKey[HAND_KEY_DATA] = (IMG_UINTPTR_T)pvData;
+ aKey[HAND_KEY_TYPE] = (IMG_UINTPTR_T)eType;
+ aKey[HAND_KEY_PARENT] = (IMG_UINTPTR_T)hParent;
+}
+
+static
+PVRSRV_ERROR ReallocHandleArray(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32NewCount)
+{
+ struct sHandleIndex *psOldArray = psBase->psHandleArray;
+ IMG_HANDLE hOldArrayBlockAlloc = psBase->hArrayBlockAlloc;
+ IMG_UINT32 ui32OldCount = psBase->ui32TotalHandCount;
+ struct sHandleIndex *psNewArray = IMG_NULL;
+ IMG_HANDLE hNewArrayBlockAlloc = IMG_NULL;
+ PVRSRV_ERROR eError;
+ PVRSRV_ERROR eReturn = PVRSRV_OK;
+ IMG_UINT32 ui32Index;
+
+ if (ui32NewCount == ui32OldCount)
+ {
+ return PVRSRV_OK;
+ }
+
+ if (ui32NewCount != 0 && !psBase->bPurgingEnabled &&
+ ui32NewCount < ui32OldCount)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if (((ui32OldCount % HANDLE_BLOCK_SIZE) != 0) ||
+ ((ui32NewCount % HANDLE_BLOCK_SIZE) != 0))
+ {
+ PVR_ASSERT((ui32OldCount % HANDLE_BLOCK_SIZE) == 0)
+ PVR_ASSERT((ui32NewCount % HANDLE_BLOCK_SIZE) == 0)
+
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if (ui32NewCount != 0)
+ {
+
+ eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ HANDLE_ARRAY_SIZE(ui32NewCount) * sizeof(struct sHandleIndex),
+ (IMG_VOID **)&psNewArray,
+ &hNewArrayBlockAlloc,
+ "Memory Area");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Couldn't allocate new handle array (%d)", eError));
+ eReturn = eError;
+ goto error;
+ }
+
+ if (ui32OldCount != 0)
+ {
+ OSMemCopy(psNewArray, psOldArray, HANDLE_ARRAY_SIZE(MIN(ui32NewCount, ui32OldCount)) * sizeof(struct sHandleIndex));
+ }
+ }
+
+
+ for(ui32Index = ui32NewCount; ui32Index < ui32OldCount; ui32Index += HANDLE_BLOCK_SIZE)
+ {
+ struct sHandleIndex *psIndex = INDEX_TO_INDEX_STRUCT_PTR(psOldArray, ui32Index);
+
+ eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct sHandle) * HANDLE_BLOCK_SIZE,
+ psIndex->psHandle,
+ psIndex->hBlockAlloc);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Couldn't free handle structures (%d)", eError));
+ }
+ }
+
+
+ for(ui32Index = ui32OldCount; ui32Index < ui32NewCount; ui32Index += HANDLE_BLOCK_SIZE)
+ {
+
+ struct sHandleIndex *psIndex = INDEX_TO_INDEX_STRUCT_PTR(psNewArray, ui32Index);
+
+ eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(struct sHandle) * HANDLE_BLOCK_SIZE,
+ (IMG_VOID **)&psIndex->psHandle,
+ &psIndex->hBlockAlloc,
+ "Memory Area");
+ if (eError != PVRSRV_OK)
+ {
+ psIndex->psHandle = IMG_NULL;
+ PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Couldn't allocate handle structures (%d)", eError));
+ eReturn = eError;
+ }
+ else
+ {
+ IMG_UINT32 ui32SubIndex;
+
+ psIndex->ui32FreeHandBlockCount = HANDLE_BLOCK_SIZE;
+
+ for(ui32SubIndex = 0; ui32SubIndex < HANDLE_BLOCK_SIZE; ui32SubIndex++)
+ {
+ struct sHandle *psHandle = psIndex->psHandle + ui32SubIndex;
+
+
+ psHandle->ui32Index = ui32SubIndex + ui32Index;
+ psHandle->eType = PVRSRV_HANDLE_TYPE_NONE;
+ psHandle->eInternalFlag = INTERNAL_HANDLE_FLAG_NONE;
+ psHandle->ui32NextIndexPlusOne = 0;
+ }
+ }
+ }
+ if (eReturn != PVRSRV_OK)
+ {
+ goto error;
+ }
+
+#ifdef DEBUG_MAX_HANDLE_COUNT
+
+ if (ui32NewCount > DEBUG_MAX_HANDLE_COUNT)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Max handle count (%u) reached", DEBUG_MAX_HANDLE_COUNT));
+ eReturn = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto error;
+ }
+#endif
+
+ if (psOldArray != IMG_NULL)
+ {
+
+ eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ HANDLE_ARRAY_SIZE(ui32OldCount) * sizeof(struct sHandleIndex),
+ psOldArray,
+ hOldArrayBlockAlloc);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Couldn't free old handle array (%d)", eError));
+ }
+ }
+
+ psBase->psHandleArray = psNewArray;
+ psBase->hArrayBlockAlloc = hNewArrayBlockAlloc;
+ psBase->ui32TotalHandCount = ui32NewCount;
+
+ if (ui32NewCount > ui32OldCount)
+ {
+
+ PVR_ASSERT(psBase->ui32FreeHandCount + (ui32NewCount - ui32OldCount) > psBase->ui32FreeHandCount)
+
+
+ psBase->ui32FreeHandCount += (ui32NewCount - ui32OldCount);
+
+
+ if (psBase->ui32FirstFreeIndex == 0)
+ {
+ PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0)
+
+ psBase->ui32FirstFreeIndex = ui32OldCount;
+ }
+ else
+ {
+ if (!psBase->bPurgingEnabled)
+ {
+ PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0)
+ PVR_ASSERT(INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne == 0)
+
+ INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne = ui32OldCount + 1;
+ }
+ }
+
+ if (!psBase->bPurgingEnabled)
+ {
+ psBase->ui32LastFreeIndexPlusOne = ui32NewCount;
+ }
+ }
+ else
+ {
+ PVR_ASSERT(ui32NewCount == 0 || psBase->bPurgingEnabled)
+ PVR_ASSERT(ui32NewCount == 0 || psBase->ui32FirstFreeIndex <= ui32NewCount)
+ PVR_ASSERT(psBase->ui32FreeHandCount - (ui32OldCount - ui32NewCount) < psBase->ui32FreeHandCount)
+
+
+ psBase->ui32FreeHandCount -= (ui32OldCount - ui32NewCount);
+
+ if (ui32NewCount == 0)
+ {
+ psBase->ui32FirstFreeIndex = 0;
+ psBase->ui32LastFreeIndexPlusOne = 0;
+ }
+ }
+
+ PVR_ASSERT(psBase->ui32FirstFreeIndex <= psBase->ui32TotalHandCount)
+
+ return PVRSRV_OK;
+
+error:
+ PVR_ASSERT(eReturn != PVRSRV_OK)
+
+ if (psNewArray != IMG_NULL)
+ {
+
+ for(ui32Index = ui32OldCount; ui32Index < ui32NewCount; ui32Index += HANDLE_BLOCK_SIZE)
+ {
+ struct sHandleIndex *psIndex = INDEX_TO_INDEX_STRUCT_PTR(psNewArray, ui32Index);
+ if (psIndex->psHandle != IMG_NULL)
+ {
+ eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct sHandle) * HANDLE_BLOCK_SIZE,
+ psIndex->psHandle,
+ psIndex->hBlockAlloc);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Couldn't free handle structures (%d)", eError));
+ }
+ }
+ }
+
+
+ eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ HANDLE_ARRAY_SIZE(ui32NewCount) * sizeof(struct sHandleIndex),
+ psNewArray,
+ hNewArrayBlockAlloc);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Couldn't free new handle array (%d)", eError));
+ }
+ }
+
+ return eReturn;
+}
+
+static PVRSRV_ERROR FreeHandleArray(PVRSRV_HANDLE_BASE *psBase)
+{
+ return ReallocHandleArray(psBase, 0);
+}
+
+static PVRSRV_ERROR FreeHandle(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHandle)
+{
+ HAND_KEY aKey;
+ IMG_UINT32 ui32Index = HANDLE_PTR_TO_INDEX(psHandle);
+ PVRSRV_ERROR eError;
+
+
+ InitKey(aKey, psBase, psHandle->pvData, psHandle->eType, ParentIfPrivate(psHandle));
+
+ if (!TEST_ALLOC_FLAG(psHandle, PVRSRV_HANDLE_ALLOC_FLAG_MULTI) && !BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
+ {
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hHandle;
+ hHandle = (IMG_SID) HASH_Remove_Extended(psBase->psHashTab, aKey);
+#else
+ IMG_HANDLE hHandle;
+ hHandle = (IMG_HANDLE) HASH_Remove_Extended(psBase->psHashTab, aKey);
+
+#endif
+
+ PVR_ASSERT(hHandle != IMG_NULL)
+ PVR_ASSERT(hHandle == INDEX_TO_HANDLE(ui32Index))
+ PVR_UNREFERENCED_PARAMETER(hHandle);
+ }
+
+
+ UnlinkFromParent(psBase, psHandle);
+
+
+ eError = IterateOverChildren(psBase, psHandle, FreeHandle);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeHandle: Error whilst freeing subhandles (%d)", eError));
+ return eError;
+ }
+
+
+ psHandle->eType = PVRSRV_HANDLE_TYPE_NONE;
+
+ if (BATCHED_HANDLE(psHandle) && !BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
+ {
+
+ SET_BATCHED_HANDLE_PARTIALLY_FREE(psHandle);
+
+ return PVRSRV_OK;
+ }
+
+
+ if (!psBase->bPurgingEnabled)
+ {
+ if (psBase->ui32FreeHandCount == 0)
+ {
+ PVR_ASSERT(psBase->ui32FirstFreeIndex == 0)
+ PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0)
+
+ psBase->ui32FirstFreeIndex = ui32Index;
+ }
+ else
+ {
+
+ PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0)
+ PVR_ASSERT(INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne == 0)
+ INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne = ui32Index + 1;
+ }
+
+ PVR_ASSERT(psHandle->ui32NextIndexPlusOne == 0)
+
+
+ psBase->ui32LastFreeIndexPlusOne = ui32Index + 1;
+ }
+
+ psBase->ui32FreeHandCount++;
+ INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32Index)++;
+
+ PVR_ASSERT(INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32Index)<= HANDLE_BLOCK_SIZE)
+
+#ifdef DEBUG
+ {
+ IMG_UINT32 ui32BlockedIndex;
+ IMG_UINT32 ui32FreeHandCount = 0;
+
+ for (ui32BlockedIndex = 0; ui32BlockedIndex < psBase->ui32TotalHandCount; ui32BlockedIndex += HANDLE_BLOCK_SIZE)
+ {
+ ui32FreeHandCount += INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32BlockedIndex);
+ }
+
+ PVR_ASSERT(ui32FreeHandCount == psBase->ui32FreeHandCount)
+ }
+#endif
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR FreeAllHandles(PVRSRV_HANDLE_BASE *psBase)
+{
+ IMG_UINT32 i;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if (psBase->ui32FreeHandCount == psBase->ui32TotalHandCount)
+ {
+ return eError;
+ }
+
+ for (i = 0; i < psBase->ui32TotalHandCount; i++)
+ {
+ struct sHandle *psHandle;
+
+ psHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, i);
+
+ if (psHandle->eType != PVRSRV_HANDLE_TYPE_NONE)
+ {
+ eError = FreeHandle(psBase, psHandle);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeAllHandles: FreeHandle failed (%d)", eError));
+ break;
+ }
+
+
+ if (psBase->ui32FreeHandCount == psBase->ui32TotalHandCount)
+ {
+ break;
+ }
+ }
+ }
+
+ return eError;
+}
+
+static PVRSRV_ERROR FreeHandleBase(PVRSRV_HANDLE_BASE *psBase)
+{
+ PVRSRV_ERROR eError;
+
+ if (HANDLES_BATCHED(psBase))
+ {
+ PVR_DPF((PVR_DBG_WARNING, "FreeHandleBase: Uncommitted/Unreleased handle batch"));
+ PVRSRVReleaseHandleBatch(psBase);
+ }
+
+
+ eError = FreeAllHandles(psBase);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeHandleBase: Couldn't free handles (%d)", eError));
+ return eError;
+ }
+
+
+ eError = FreeHandleArray(psBase);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeHandleBase: Couldn't free handle array (%d)", eError));
+ return eError;
+ }
+
+ if (psBase->psHashTab != IMG_NULL)
+ {
+
+ HASH_Delete(psBase->psHashTab);
+ }
+
+ eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*psBase),
+ psBase,
+ psBase->hBaseBlockAlloc);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeHandleBase: Couldn't free handle base (%d)", eError));
+ return eError;
+ }
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(FindHandle)
+#endif
+static INLINE
+#if defined (SUPPORT_SID_INTERFACE)
+IMG_SID FindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, IMG_SID hParent)
+#else
+IMG_HANDLE FindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hParent)
+#endif
+{
+ HAND_KEY aKey;
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
+
+ InitKey(aKey, psBase, pvData, eType, hParent);
+
+#if defined (SUPPORT_SID_INTERFACE)
+ return (IMG_SID) HASH_Retrieve_Extended(psBase->psHashTab, aKey);
+#else
+ return (IMG_HANDLE) HASH_Retrieve_Extended(psBase->psHashTab, aKey);
+#endif
+}
+
+static PVRSRV_ERROR IncreaseHandleArraySize(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32Delta)
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32DeltaAdjusted = ROUND_UP_TO_MULTIPLE_OF_BLOCK_SIZE(ui32Delta);
+ IMG_UINT32 ui32NewTotalHandCount = psBase->ui32TotalHandCount + ui32DeltaAdjusted;
+;
+
+ PVR_ASSERT(ui32Delta != 0)
+
+
+ if (ui32NewTotalHandCount > psBase->ui32MaxIndexPlusOne || ui32NewTotalHandCount <= psBase->ui32TotalHandCount)
+ {
+ ui32NewTotalHandCount = psBase->ui32MaxIndexPlusOne;
+
+ ui32DeltaAdjusted = ui32NewTotalHandCount - psBase->ui32TotalHandCount;
+
+ if (ui32DeltaAdjusted < ui32Delta)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "IncreaseHandleArraySize: Maximum handle limit reached (%d)", psBase->ui32MaxIndexPlusOne));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ }
+
+ PVR_ASSERT(ui32DeltaAdjusted >= ui32Delta)
+
+
+ eError = ReallocHandleArray(psBase, ui32NewTotalHandCount);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "IncreaseHandleArraySize: ReallocHandleArray failed (%d)", eError));
+ return eError;
+ }
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR EnsureFreeHandles(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32Free)
+{
+ PVRSRV_ERROR eError;
+
+ if (ui32Free > psBase->ui32FreeHandCount)
+ {
+ IMG_UINT32 ui32FreeHandDelta = ui32Free - psBase->ui32FreeHandCount;
+ eError = IncreaseHandleArraySize(psBase, ui32FreeHandDelta);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "EnsureFreeHandles: Couldn't allocate %u handles to ensure %u free handles (IncreaseHandleArraySize failed with error %d)", ui32FreeHandDelta, ui32Free, eError));
+
+ return eError;
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+#if defined (SUPPORT_SID_INTERFACE)
+static PVRSRV_ERROR AllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_SID *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_SID hParent)
+#else
+static PVRSRV_ERROR AllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_HANDLE hParent)
+#endif
+{
+ IMG_UINT32 ui32NewIndex = DEFAULT_MAX_INDEX_PLUS_ONE;
+ struct sHandle *psNewHandle = IMG_NULL;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hHandle;
+#else
+ IMG_HANDLE hHandle;
+#endif
+ HAND_KEY aKey;
+ PVRSRV_ERROR eError;
+
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
+ PVR_ASSERT(psBase != IMG_NULL)
+ PVR_ASSERT(psBase->psHashTab != IMG_NULL)
+
+ if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
+ {
+
+ PVR_ASSERT(FindHandle(psBase, pvData, eType, hParent) == IMG_NULL)
+ }
+
+ if (psBase->ui32FreeHandCount == 0 && HANDLES_BATCHED(psBase))
+ {
+ PVR_DPF((PVR_DBG_WARNING, "AllocHandle: Handle batch size (%u) was too small, allocating additional space", psBase->ui32HandBatchSize));
+ }
+
+
+ eError = EnsureFreeHandles(psBase, 1);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "AllocHandle: EnsureFreeHandles failed (%d)", eError));
+ return eError;
+ }
+ PVR_ASSERT(psBase->ui32FreeHandCount != 0)
+
+ if (!psBase->bPurgingEnabled)
+ {
+
+ ui32NewIndex = psBase->ui32FirstFreeIndex;
+
+
+ psNewHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32NewIndex);
+ }
+ else
+ {
+ IMG_UINT32 ui32BlockedIndex;
+
+
+
+ PVR_ASSERT((psBase->ui32FirstFreeIndex % HANDLE_BLOCK_SIZE) == 0)
+
+ for (ui32BlockedIndex = ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE(psBase->ui32FirstFreeIndex); ui32BlockedIndex < psBase->ui32TotalHandCount; ui32BlockedIndex += HANDLE_BLOCK_SIZE)
+ {
+ struct sHandleIndex *psIndex = BASE_AND_INDEX_TO_INDEX_STRUCT_PTR(psBase, ui32BlockedIndex);
+
+ if (psIndex->ui32FreeHandBlockCount == 0)
+ {
+ continue;
+ }
+
+ for (ui32NewIndex = ui32BlockedIndex; ui32NewIndex < ui32BlockedIndex + HANDLE_BLOCK_SIZE; ui32NewIndex++)
+ {
+ psNewHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32NewIndex);
+ if (HANDLE_STRUCT_IS_FREE(psNewHandle))
+ {
+ break;
+ }
+ }
+ }
+ psBase->ui32FirstFreeIndex = 0;
+ PVR_ASSERT(ui32NewIndex < psBase->ui32TotalHandCount)
+ }
+ PVR_ASSERT(psNewHandle != IMG_NULL)
+
+
+ hHandle = INDEX_TO_HANDLE(ui32NewIndex);
+
+
+ if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
+ {
+
+ InitKey(aKey, psBase, pvData, eType, hParent);
+
+
+ if (!HASH_Insert_Extended(psBase->psHashTab, aKey, (IMG_UINTPTR_T)hHandle))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "AllocHandle: Couldn't add handle to hash table"));
+
+ return PVRSRV_ERROR_UNABLE_TO_ADD_HANDLE;
+ }
+ }
+
+ psBase->ui32FreeHandCount--;
+
+ PVR_ASSERT(INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32NewIndex) <= HANDLE_BLOCK_SIZE)
+ PVR_ASSERT(INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32NewIndex) > 0)
+
+ INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32NewIndex)--;
+
+
+ if (!psBase->bPurgingEnabled)
+ {
+
+ if (psBase->ui32FreeHandCount == 0)
+ {
+ PVR_ASSERT(psBase->ui32FirstFreeIndex == ui32NewIndex)
+ PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == (ui32NewIndex + 1))
+
+ psBase->ui32LastFreeIndexPlusOne = 0;
+ psBase->ui32FirstFreeIndex = 0;
+ }
+ else
+ {
+
+ psBase->ui32FirstFreeIndex = (psNewHandle->ui32NextIndexPlusOne == 0) ?
+ ui32NewIndex + 1 :
+ psNewHandle->ui32NextIndexPlusOne - 1;
+ }
+ }
+
+
+ PVR_ASSERT(psNewHandle->ui32Index == ui32NewIndex)
+
+
+ psNewHandle->eType = eType;
+ psNewHandle->pvData = pvData;
+ psNewHandle->eInternalFlag = INTERNAL_HANDLE_FLAG_NONE;
+ psNewHandle->eFlag = eFlag;
+
+ InitParentList(psNewHandle);
+#if defined(DEBUG)
+ PVR_ASSERT(NoChildren(psNewHandle))
+#endif
+
+ InitChildEntry(psNewHandle);
+#if defined(DEBUG)
+ PVR_ASSERT(NoParent(psNewHandle))
+#endif
+
+ if (HANDLES_BATCHED(psBase))
+ {
+
+ psNewHandle->ui32NextIndexPlusOne = psBase->ui32FirstBatchIndexPlusOne;
+
+ psBase->ui32FirstBatchIndexPlusOne = ui32NewIndex + 1;
+
+
+ SET_BATCHED_HANDLE(psNewHandle);
+ }
+ else
+ {
+ psNewHandle->ui32NextIndexPlusOne = 0;
+ }
+
+
+ *phHandle = hHandle;
+
+ return PVRSRV_OK;
+}
+
+#if defined (SUPPORT_SID_INTERFACE)
+PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_SID *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag)
+#else
+PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag)
+#endif
+{
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hHandle;
+#else
+ IMG_HANDLE hHandle;
+#endif
+ PVRSRV_ERROR eError;
+
+#if defined (SUPPORT_SID_INTERFACE)
+ *phHandle = 0;
+#else
+ *phHandle = IMG_NULL;
+#endif
+
+ if (HANDLES_BATCHED(psBase))
+ {
+
+ psBase->ui32BatchHandAllocFailures++;
+ }
+
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
+
+ if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
+ {
+
+ hHandle = FindHandle(psBase, pvData, eType, IMG_NULL);
+#if defined (SUPPORT_SID_INTERFACE)
+ if (hHandle != 0)
+#else
+ if (hHandle != IMG_NULL)
+#endif
+ {
+ struct sHandle *psHandle;
+
+ eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandle: Lookup of existing handle failed"));
+ return eError;
+ }
+
+
+ if (TEST_FLAG(psHandle->eFlag & eFlag, PVRSRV_HANDLE_ALLOC_FLAG_SHARED))
+ {
+ *phHandle = hHandle;
+ eError = PVRSRV_OK;
+ goto exit_ok;
+ }
+
+#if defined (SUPPORT_SID_INTERFACE)
+ PVR_DBG_BREAK
+#endif
+ return PVRSRV_ERROR_HANDLE_NOT_SHAREABLE;
+ }
+ }
+
+ eError = AllocHandle(psBase, phHandle, pvData, eType, eFlag, IMG_NULL);
+
+exit_ok:
+ if (HANDLES_BATCHED(psBase) && (eError == PVRSRV_OK))
+ {
+ psBase->ui32BatchHandAllocFailures--;
+ }
+
+ return eError;
+}
+
+#if defined (SUPPORT_SID_INTERFACE)
+PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_SID *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_SID hParent)
+#else
+PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_HANDLE hParent)
+#endif
+{
+ struct sHandle *psPHand;
+ struct sHandle *psCHand;
+ PVRSRV_ERROR eError;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hParentKey;
+ IMG_SID hHandle;
+
+ *phHandle = 0;
+#else
+ IMG_HANDLE hParentKey;
+ IMG_HANDLE hHandle;
+
+ *phHandle = IMG_NULL;
+#endif
+
+ if (HANDLES_BATCHED(psBase))
+ {
+
+ psBase->ui32BatchHandAllocFailures++;
+ }
+
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
+
+ hParentKey = TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE) ?
+ hParent : IMG_NULL;
+
+
+ eError = GetHandleStructure(psBase, &psPHand, hParent, PVRSRV_HANDLE_TYPE_NONE);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
+ {
+
+ hHandle = FindHandle(psBase, pvData, eType, hParentKey);
+#if defined (SUPPORT_SID_INTERFACE)
+ if (hHandle != 0)
+#else
+ if (hHandle != IMG_NULL)
+#endif
+ {
+ struct sHandle *psCHandle;
+ PVRSRV_ERROR eErr;
+
+ eErr = GetHandleStructure(psBase, &psCHandle, hHandle, eType);
+ if (eErr != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocSubHandle: Lookup of existing handle failed"));
+ return eErr;
+ }
+
+ PVR_ASSERT(hParentKey != IMG_NULL && ParentHandle(HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hHandle)) == hParent)
+
+
+ if (TEST_FLAG(psCHandle->eFlag & eFlag, PVRSRV_HANDLE_ALLOC_FLAG_SHARED) && ParentHandle(HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hHandle)) == hParent)
+ {
+ *phHandle = hHandle;
+ goto exit_ok;
+ }
+#if defined (SUPPORT_SID_INTERFACE)
+ PVR_DBG_BREAK
+#endif
+ return PVRSRV_ERROR_HANDLE_NOT_SHAREABLE;
+ }
+ }
+
+ eError = AllocHandle(psBase, &hHandle, pvData, eType, eFlag, hParentKey);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+
+ psPHand = HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hParent);
+
+ psCHand = HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hHandle);
+
+ AdoptChild(psBase, psPHand, psCHand);
+
+ *phHandle = hHandle;
+
+exit_ok:
+ if (HANDLES_BATCHED(psBase))
+ {
+ psBase->ui32BatchHandAllocFailures--;
+ }
+
+ return PVRSRV_OK;
+}
+
+#if defined (SUPPORT_SID_INTERFACE)
+PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_SID *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType)
+#else
+PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType)
+#endif
+{
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hHandle;
+#else
+ IMG_HANDLE hHandle;
+#endif
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
+
+
+#if defined (SUPPORT_SID_INTERFACE)
+ hHandle = (IMG_SID) FindHandle(psBase, pvData, eType, IMG_NULL);
+#else
+ hHandle = (IMG_HANDLE) FindHandle(psBase, pvData, eType, IMG_NULL);
+#endif
+ if (hHandle == IMG_NULL)
+ {
+ return PVRSRV_ERROR_HANDLE_NOT_FOUND;
+ }
+
+ *phHandle = hHandle;
+
+ return PVRSRV_OK;
+}
+
+#if defined (SUPPORT_SID_INTERFACE)
+PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, PVRSRV_HANDLE_TYPE *peType, IMG_SID hHandle)
+#else
+PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, PVRSRV_HANDLE_TYPE *peType, IMG_HANDLE hHandle)
+#endif
+{
+ struct sHandle *psHandle;
+ PVRSRV_ERROR eError;
+
+ eError = GetHandleStructure(psBase, &psHandle, hHandle, PVRSRV_HANDLE_TYPE_NONE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupHandleAnyType: Error looking up handle (%d)", eError));
+#if defined (SUPPORT_SID_INTERFACE)
+ PVR_DBG_BREAK
+#endif
+ return eError;
+ }
+
+ *ppvData = psHandle->pvData;
+ *peType = psHandle->eType;
+
+ return PVRSRV_OK;
+}
+
+#if defined (SUPPORT_SID_INTERFACE)
+PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_SID hHandle, PVRSRV_HANDLE_TYPE eType)
+#else
+PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+#endif
+{
+ struct sHandle *psHandle;
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
+#if defined (SUPPORT_SID_INTERFACE)
+ PVR_ASSERT(hHandle != 0)
+#endif
+
+ eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupHandle: Error looking up handle (%d)", eError));
+#if defined (SUPPORT_SID_INTERFACE)
+ PVR_DBG_BREAK
+#endif
+ return eError;
+ }
+
+ *ppvData = psHandle->pvData;
+
+ return PVRSRV_OK;
+}
+
+#if defined (SUPPORT_SID_INTERFACE)
+PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_SID hHandle, PVRSRV_HANDLE_TYPE eType, IMG_SID hAncestor)
+#else
+PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hAncestor)
+#endif
+{
+ struct sHandle *psPHand;
+ struct sHandle *psCHand;
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
+#if defined (SUPPORT_SID_INTERFACE)
+ PVR_ASSERT(hHandle != 0)
+#endif
+
+ eError = GetHandleStructure(psBase, &psCHand, hHandle, eType);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupSubHandle: Error looking up subhandle (%d)", eError));
+ return eError;
+ }
+
+
+ for (psPHand = psCHand; ParentHandle(psPHand) != hAncestor; )
+ {
+ eError = GetHandleStructure(psBase, &psPHand, ParentHandle(psPHand), PVRSRV_HANDLE_TYPE_NONE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupSubHandle: Subhandle doesn't belong to given ancestor"));
+ return PVRSRV_ERROR_INVALID_SUBHANDLE;
+ }
+ }
+
+ *ppvData = psCHand->pvData;
+
+ return PVRSRV_OK;
+}
+
+#if defined (SUPPORT_SID_INTERFACE)
+PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase, IMG_SID *phParent, IMG_SID hHandle, PVRSRV_HANDLE_TYPE eType)
+#else
+PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *phParent, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+#endif
+{
+ struct sHandle *psHandle;
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
+
+ eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetParentHandle: Error looking up subhandle (%d)", eError));
+ return eError;
+ }
+
+ *phParent = ParentHandle(psHandle);
+
+ return PVRSRV_OK;
+}
+
+#if defined (SUPPORT_SID_INTERFACE)
+PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_SID hHandle, PVRSRV_HANDLE_TYPE eType)
+#else
+PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+#endif
+{
+ struct sHandle *psHandle;
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
+
+ eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupAndReleaseHandle: Error looking up handle (%d)", eError));
+#if defined (SUPPORT_SID_INTERFACE)
+ PVR_DBG_BREAK
+#endif
+ return eError;
+ }
+
+ *ppvData = psHandle->pvData;
+
+ eError = FreeHandle(psBase, psHandle);
+
+ return eError;
+}
+
+#if defined (SUPPORT_SID_INTERFACE)
+PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_SID hHandle, PVRSRV_HANDLE_TYPE eType)
+#else
+PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+#endif
+{
+ struct sHandle *psHandle;
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
+
+ eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVReleaseHandle: Error looking up handle (%d)", eError));
+ return eError;
+ }
+
+ eError = FreeHandle(psBase, psHandle);
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVNewHandleBatch(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32BatchSize)
+{
+ PVRSRV_ERROR eError;
+
+ if (HANDLES_BATCHED(psBase))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVNewHandleBatch: There is a handle batch already in use (size %u)", psBase->ui32HandBatchSize));
+ return PVRSRV_ERROR_HANDLE_BATCH_IN_USE;
+ }
+
+ if (ui32BatchSize == 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVNewHandleBatch: Invalid batch size (%u)", ui32BatchSize));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ eError = EnsureFreeHandles(psBase, ui32BatchSize);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVNewHandleBatch: EnsureFreeHandles failed (error %d)", eError));
+ return eError;
+ }
+
+ psBase->ui32HandBatchSize = ui32BatchSize;
+
+
+ psBase->ui32TotalHandCountPreBatch = psBase->ui32TotalHandCount;
+
+ PVR_ASSERT(psBase->ui32BatchHandAllocFailures == 0)
+
+ PVR_ASSERT(psBase->ui32FirstBatchIndexPlusOne == 0)
+
+ PVR_ASSERT(HANDLES_BATCHED(psBase))
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR PVRSRVHandleBatchCommitOrRelease(PVRSRV_HANDLE_BASE *psBase, IMG_BOOL bCommit)
+{
+
+ IMG_UINT32 ui32IndexPlusOne;
+ IMG_BOOL bCommitBatch = bCommit;
+
+ if (!HANDLES_BATCHED(psBase))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleBatchCommitOrRelease: There is no handle batch"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+
+ }
+
+ if (psBase->ui32BatchHandAllocFailures != 0)
+ {
+ if (bCommit)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleBatchCommitOrRelease: Attempting to commit batch with handle allocation failures."));
+ }
+ bCommitBatch = IMG_FALSE;
+ }
+
+ PVR_ASSERT(psBase->ui32BatchHandAllocFailures == 0 || !bCommit)
+
+ ui32IndexPlusOne = psBase->ui32FirstBatchIndexPlusOne;
+ while(ui32IndexPlusOne != 0)
+ {
+ struct sHandle *psHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32IndexPlusOne - 1);
+ IMG_UINT32 ui32NextIndexPlusOne = psHandle->ui32NextIndexPlusOne;
+ PVR_ASSERT(BATCHED_HANDLE(psHandle))
+
+ psHandle->ui32NextIndexPlusOne = 0;
+
+ if (!bCommitBatch || BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
+ {
+ PVRSRV_ERROR eError;
+
+
+ if (!BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
+ {
+
+ SET_UNBATCHED_HANDLE(psHandle);
+ }
+
+ eError = FreeHandle(psBase, psHandle);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleBatchCommitOrRelease: Error freeing handle (%d)", eError));
+ }
+ PVR_ASSERT(eError == PVRSRV_OK)
+ }
+ else
+ {
+
+ SET_UNBATCHED_HANDLE(psHandle);
+ }
+
+ ui32IndexPlusOne = ui32NextIndexPlusOne;
+ }
+
+#ifdef DEBUG
+ if (psBase->ui32TotalHandCountPreBatch != psBase->ui32TotalHandCount)
+ {
+ IMG_UINT32 ui32Delta = psBase->ui32TotalHandCount - psBase->ui32TotalHandCountPreBatch;
+
+ PVR_ASSERT(psBase->ui32TotalHandCount > psBase->ui32TotalHandCountPreBatch)
+
+ PVR_DPF((PVR_DBG_WARNING, "PVRSRVHandleBatchCommitOrRelease: The batch size was too small. Batch size was %u, but needs to be %u", psBase->ui32HandBatchSize, psBase->ui32HandBatchSize + ui32Delta));
+
+ }
+#endif
+
+ psBase->ui32HandBatchSize = 0;
+ psBase->ui32FirstBatchIndexPlusOne = 0;
+ psBase->ui32TotalHandCountPreBatch = 0;
+ psBase->ui32BatchHandAllocFailures = 0;
+
+ if (psBase->ui32BatchHandAllocFailures != 0 && bCommit)
+ {
+ PVR_ASSERT(!bCommitBatch)
+
+ return PVRSRV_ERROR_HANDLE_BATCH_COMMIT_FAILURE;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVCommitHandleBatch(PVRSRV_HANDLE_BASE *psBase)
+{
+ return PVRSRVHandleBatchCommitOrRelease(psBase, IMG_TRUE);
+}
+
+IMG_VOID PVRSRVReleaseHandleBatch(PVRSRV_HANDLE_BASE *psBase)
+{
+ (IMG_VOID) PVRSRVHandleBatchCommitOrRelease(psBase, IMG_FALSE);
+}
+
+PVRSRV_ERROR PVRSRVSetMaxHandle(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32MaxHandle)
+{
+ IMG_UINT32 ui32MaxHandleRounded;
+
+ if (HANDLES_BATCHED(psBase))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetMaxHandle: Limit cannot be set whilst in batch mode"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ if (ui32MaxHandle == 0 || ui32MaxHandle > DEFAULT_MAX_HANDLE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetMaxHandle: Limit must be between %u and %u, inclusive", 0, DEFAULT_MAX_HANDLE));
+
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ if (psBase->ui32TotalHandCount != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetMaxHandle: Limit cannot be set because handles have already been allocated"));
+
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ ui32MaxHandleRounded = ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE(ui32MaxHandle);
+
+
+ if (ui32MaxHandleRounded != 0 && ui32MaxHandleRounded < psBase->ui32MaxIndexPlusOne)
+ {
+ psBase->ui32MaxIndexPlusOne = ui32MaxHandleRounded;
+ }
+
+ PVR_ASSERT(psBase->ui32MaxIndexPlusOne != 0)
+ PVR_ASSERT(psBase->ui32MaxIndexPlusOne <= DEFAULT_MAX_INDEX_PLUS_ONE)
+ PVR_ASSERT((psBase->ui32MaxIndexPlusOne % HANDLE_BLOCK_SIZE) == 0)
+
+ return PVRSRV_OK;
+}
+
+IMG_UINT32 PVRSRVGetMaxHandle(PVRSRV_HANDLE_BASE *psBase)
+{
+ return psBase->ui32MaxIndexPlusOne;
+}
+
+PVRSRV_ERROR PVRSRVEnableHandlePurging(PVRSRV_HANDLE_BASE *psBase)
+{
+ if (psBase->bPurgingEnabled)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "PVRSRVEnableHandlePurging: Purging already enabled"));
+ return PVRSRV_OK;
+ }
+
+
+ if (psBase->ui32TotalHandCount != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVEnableHandlePurging: Handles have already been allocated"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psBase->bPurgingEnabled = IMG_TRUE;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase)
+{
+ IMG_UINT32 ui32BlockIndex;
+ IMG_UINT32 ui32NewHandCount;
+
+ if (!psBase->bPurgingEnabled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPurgeHandles: Purging not enabled for this handle base"));
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+ }
+
+ if (HANDLES_BATCHED(psBase))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPurgeHandles: Purging not allowed whilst in batch mode"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ PVR_ASSERT((psBase->ui32TotalHandCount % HANDLE_BLOCK_SIZE) == 0)
+
+ for (ui32BlockIndex = INDEX_TO_BLOCK_INDEX(psBase->ui32TotalHandCount); ui32BlockIndex != 0; ui32BlockIndex--)
+ {
+ if (psBase->psHandleArray[ui32BlockIndex - 1].ui32FreeHandBlockCount != HANDLE_BLOCK_SIZE)
+ {
+ break;
+ }
+ }
+ ui32NewHandCount = BLOCK_INDEX_TO_INDEX(ui32BlockIndex);
+
+
+ if (ui32NewHandCount <= (psBase->ui32TotalHandCount/2))
+ {
+ PVRSRV_ERROR eError;
+
+
+
+ eError = ReallocHandleArray(psBase, ui32NewHandCount);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase)
+{
+ PVRSRV_HANDLE_BASE *psBase;
+ IMG_HANDLE hBlockAlloc;
+ PVRSRV_ERROR eError;
+
+ eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(*psBase),
+ (IMG_PVOID *)&psBase,
+ &hBlockAlloc,
+ "Handle Base");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandleBase: Couldn't allocate handle base (%d)", eError));
+ return eError;
+ }
+ OSMemSet(psBase, 0, sizeof(*psBase));
+
+
+ psBase->psHashTab = HASH_Create_Extended(HANDLE_HASH_TAB_INIT_SIZE, sizeof(HAND_KEY), HASH_Func_Default, HASH_Key_Comp_Default);
+ if (psBase->psHashTab == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandleBase: Couldn't create data pointer hash table\n"));
+ (IMG_VOID)PVRSRVFreeHandleBase(psBase);
+ return PVRSRV_ERROR_UNABLE_TO_CREATE_HASH_TABLE;
+ }
+
+ psBase->hBaseBlockAlloc = hBlockAlloc;
+
+ psBase->ui32MaxIndexPlusOne = DEFAULT_MAX_INDEX_PLUS_ONE;
+
+ *ppsBase = psBase;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVFreeHandleBase(PVRSRV_HANDLE_BASE *psBase)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(psBase != gpsKernelHandleBase)
+
+ eError = FreeHandleBase(psBase);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVFreeHandleBase: FreeHandleBase failed (%d)", eError));
+ }
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVHandleInit(IMG_VOID)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(gpsKernelHandleBase == IMG_NULL)
+
+ eError = PVRSRVAllocHandleBase(&gpsKernelHandleBase);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleInit: PVRSRVAllocHandleBase failed (%d)", eError));
+ goto error;
+ }
+
+ eError = PVRSRVEnableHandlePurging(gpsKernelHandleBase);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleInit: PVRSRVEnableHandlePurging failed (%d)", eError));
+ goto error;
+ }
+
+ return PVRSRV_OK;
+error:
+ (IMG_VOID) PVRSRVHandleDeInit();
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVHandleDeInit(IMG_VOID)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if (gpsKernelHandleBase != IMG_NULL)
+ {
+ eError = FreeHandleBase(gpsKernelHandleBase);
+ if (eError == PVRSRV_OK)
+ {
+ gpsKernelHandleBase = IMG_NULL;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleDeInit: FreeHandleBase failed (%d)", eError));
+ }
+ }
+
+ return eError;
+}
+#else
+#endif
diff --git a/drivers/gpu/pvr/handle.h b/drivers/gpu/pvr/handle.h
new file mode 100644
index 0000000..536fa56
--- /dev/null
+++ b/drivers/gpu/pvr/handle.h
@@ -0,0 +1,404 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __HANDLE_H__
+#define __HANDLE_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "img_types.h"
+#include "hash.h"
+#include "resman.h"
+
+typedef enum
+{
+ PVRSRV_HANDLE_TYPE_NONE = 0,
+ PVRSRV_HANDLE_TYPE_PERPROC_DATA,
+ PVRSRV_HANDLE_TYPE_DEV_NODE,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO,
+ PVRSRV_HANDLE_TYPE_DISP_INFO,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN,
+ PVRSRV_HANDLE_TYPE_BUF_INFO,
+ PVRSRV_HANDLE_TYPE_DISP_BUFFER,
+ PVRSRV_HANDLE_TYPE_BUF_BUFFER,
+ PVRSRV_HANDLE_TYPE_SGX_HW_RENDER_CONTEXT,
+ PVRSRV_HANDLE_TYPE_SGX_HW_TRANSFER_CONTEXT,
+ PVRSRV_HANDLE_TYPE_SGX_HW_2D_CONTEXT,
+ PVRSRV_HANDLE_TYPE_SHARED_PB_DESC,
+ PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+ PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO,
+ PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT,
+ PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT,
+ PVRSRV_HANDLE_TYPE_MMAP_INFO,
+ PVRSRV_HANDLE_TYPE_SOC_TIMER,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO_MOD_OBJ,
+ PVRSRV_HANDLE_TYPE_RESITEM_INFO
+} PVRSRV_HANDLE_TYPE;
+
+typedef enum
+{
+
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE = 0,
+
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED = 0x01,
+
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI = 0x02,
+
+ PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE = 0x04
+} PVRSRV_HANDLE_ALLOC_FLAG;
+
+struct _PVRSRV_HANDLE_BASE_;
+typedef struct _PVRSRV_HANDLE_BASE_ PVRSRV_HANDLE_BASE;
+
+#if defined (PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE)
+extern PVRSRV_HANDLE_BASE *gpsKernelHandleBase;
+
+#define KERNEL_HANDLE_BASE (gpsKernelHandleBase)
+
+#if defined (SUPPORT_SID_INTERFACE)
+PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_SID *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag);
+
+PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_SID *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_SID hParent);
+
+PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_SID *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, PVRSRV_HANDLE_TYPE *peType, IMG_SID hHandle);
+
+PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_SID hHandle, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_SID hHandle, PVRSRV_HANDLE_TYPE eType, IMG_SID hAncestor);
+
+PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase, IMG_SID *phParent, IMG_SID hHandle, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_SID hHandle, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_SID hHandle, PVRSRV_HANDLE_TYPE eType);
+#else
+PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag);
+
+PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_HANDLE hParent);
+
+PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, PVRSRV_HANDLE_TYPE *peType, IMG_HANDLE hHandle);
+
+PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hAncestor);
+
+PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *phParent, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+#endif
+
+PVRSRV_ERROR PVRSRVNewHandleBatch(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32BatchSize);
+
+PVRSRV_ERROR PVRSRVCommitHandleBatch(PVRSRV_HANDLE_BASE *psBase);
+
+IMG_VOID PVRSRVReleaseHandleBatch(PVRSRV_HANDLE_BASE *psBase);
+
+PVRSRV_ERROR PVRSRVSetMaxHandle(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32MaxHandle);
+
+IMG_UINT32 PVRSRVGetMaxHandle(PVRSRV_HANDLE_BASE *psBase);
+
+PVRSRV_ERROR PVRSRVEnableHandlePurging(PVRSRV_HANDLE_BASE *psBase);
+
+PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase);
+
+PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase);
+
+PVRSRV_ERROR PVRSRVFreeHandleBase(PVRSRV_HANDLE_BASE *psBase);
+
+PVRSRV_ERROR PVRSRVHandleInit(IMG_VOID);
+
+PVRSRV_ERROR PVRSRVHandleDeInit(IMG_VOID);
+
+#else
+
+#define KERNEL_HANDLE_BASE IMG_NULL
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVAllocHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag)
+{
+ PVR_UNREFERENCED_PARAMETER(eType);
+ PVR_UNREFERENCED_PARAMETER(eFlag);
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ *phHandle = pvData;
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVAllocSubHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_HANDLE hParent)
+{
+ PVR_UNREFERENCED_PARAMETER(eType);
+ PVR_UNREFERENCED_PARAMETER(eFlag);
+ PVR_UNREFERENCED_PARAMETER(hParent);
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ *phHandle = pvData;
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVFindHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType)
+{
+ PVR_UNREFERENCED_PARAMETER(eType);
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ *phHandle = pvData;
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVLookupHandleAnyType)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, PVRSRV_HANDLE_TYPE *peType, IMG_HANDLE hHandle)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ *peType = PVRSRV_HANDLE_TYPE_NONE;
+
+ *ppvData = hHandle;
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVLookupHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+ PVR_UNREFERENCED_PARAMETER(eType);
+
+ *ppvData = hHandle;
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVLookupSubHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hAncestor)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+ PVR_UNREFERENCED_PARAMETER(eType);
+ PVR_UNREFERENCED_PARAMETER(hAncestor);
+
+ *ppvData = hHandle;
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVGetParentHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *phParent, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+ PVR_UNREFERENCED_PARAMETER(eType);
+ PVR_UNREFERENCED_PARAMETER(hHandle);
+
+ *phParent = IMG_NULL;
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVLookupAndReleaseHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+ PVR_UNREFERENCED_PARAMETER(eType);
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ *ppvData = hHandle;
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVReleaseHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+ PVR_UNREFERENCED_PARAMETER(hHandle);
+ PVR_UNREFERENCED_PARAMETER(eType);
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVNewHandleBatch)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVNewHandleBatch(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32BatchSize)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+ PVR_UNREFERENCED_PARAMETER(ui32BatchSize);
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVCommitHandleBatch)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVCommitHandleBatch(PVRSRV_HANDLE_BASE *psBase)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVReleaseHandleBatch)
+#endif
+static INLINE
+IMG_VOID PVRSRVReleaseHandleBatch(PVRSRV_HANDLE_BASE *psBase)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVSetMaxHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVSetMaxHandle(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32MaxHandle)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+ PVR_UNREFERENCED_PARAMETER(ui32MaxHandle);
+
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVGetMaxHandle)
+#endif
+static INLINE
+IMG_UINT32 PVRSRVGetMaxHandle(PVRSRV_HANDLE_BASE *psBase)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ return 0;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVEnableHandlePurging)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVEnableHandlePurging(PVRSRV_HANDLE_BASE *psBase)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVPurgeHandles)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVAllocHandleBase)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase)
+{
+ *ppsBase = IMG_NULL;
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVFreeHandleBase)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVFreeHandleBase(PVRSRV_HANDLE_BASE *psBase)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVHandleInit)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVHandleInit(IMG_VOID)
+{
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVHandleDeInit)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVHandleDeInit(IMG_VOID)
+{
+ return PVRSRV_OK;
+}
+
+#endif
+
+#define PVRSRVAllocHandleNR(psBase, phHandle, pvData, eType, eFlag) \
+ (IMG_VOID)PVRSRVAllocHandle(psBase, phHandle, pvData, eType, eFlag)
+
+#define PVRSRVAllocSubHandleNR(psBase, phHandle, pvData, eType, eFlag, hParent) \
+ (IMG_VOID)PVRSRVAllocSubHandle(psBase, phHandle, pvData, eType, eFlag, hParent)
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/pvr/hash.c b/drivers/gpu/pvr/hash.c
new file mode 100644
index 0000000..78eab44
--- /dev/null
+++ b/drivers/gpu/pvr/hash.c
@@ -0,0 +1,505 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "pvr_debug.h"
+#include "img_defs.h"
+#include "services.h"
+#include "servicesint.h"
+#include "hash.h"
+#include "osfunc.h"
+
+#define PRIVATE_MAX(a,b) ((a)>(b)?(a):(b))
+
+#define KEY_TO_INDEX(pHash, key, uSize) \
+ ((pHash)->pfnHashFunc((pHash)->uKeySize, (key), (uSize)) % (uSize))
+
+#define KEY_COMPARE(pHash, pKey1, pKey2) \
+ ((pHash)->pfnKeyComp((pHash)->uKeySize, (pKey1), (pKey2)))
+
+struct _BUCKET_
+{
+
+ struct _BUCKET_ *pNext;
+
+
+ IMG_UINTPTR_T v;
+
+
+ IMG_UINTPTR_T k[];
+};
+typedef struct _BUCKET_ BUCKET;
+
+struct _HASH_TABLE_
+{
+
+ BUCKET **ppBucketTable;
+
+
+ IMG_UINT32 uSize;
+
+
+ IMG_UINT32 uCount;
+
+
+ IMG_UINT32 uMinimumSize;
+
+
+ IMG_UINT32 uKeySize;
+
+
+ HASH_FUNC *pfnHashFunc;
+
+
+ HASH_KEY_COMP *pfnKeyComp;
+};
+
+IMG_UINT32
+HASH_Func_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey, IMG_UINT32 uHashTabLen)
+{
+ IMG_UINTPTR_T *p = (IMG_UINTPTR_T *)pKey;
+ IMG_UINT32 uKeyLen = (IMG_UINT32)(uKeySize / sizeof(IMG_UINTPTR_T));
+ IMG_UINT32 ui;
+ IMG_UINT32 uHashKey = 0;
+
+ PVR_UNREFERENCED_PARAMETER(uHashTabLen);
+
+ PVR_ASSERT((uKeySize % sizeof(IMG_UINTPTR_T)) == 0);
+
+ for (ui = 0; ui < uKeyLen; ui++)
+ {
+ IMG_UINT32 uHashPart = (IMG_UINT32)*p++;
+
+ uHashPart += (uHashPart << 12);
+ uHashPart ^= (uHashPart >> 22);
+ uHashPart += (uHashPart << 4);
+ uHashPart ^= (uHashPart >> 9);
+ uHashPart += (uHashPart << 10);
+ uHashPart ^= (uHashPart >> 2);
+ uHashPart += (uHashPart << 7);
+ uHashPart ^= (uHashPart >> 12);
+
+ uHashKey += uHashPart;
+ }
+
+ return uHashKey;
+}
+
+IMG_BOOL
+HASH_Key_Comp_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey1, IMG_VOID *pKey2)
+{
+ IMG_UINTPTR_T *p1 = (IMG_UINTPTR_T *)pKey1;
+ IMG_UINTPTR_T *p2 = (IMG_UINTPTR_T *)pKey2;
+ IMG_UINT32 uKeyLen = (IMG_UINT32)(uKeySize / sizeof(IMG_UINTPTR_T));
+ IMG_UINT32 ui;
+
+ PVR_ASSERT((uKeySize % sizeof(IMG_UINTPTR_T)) == 0);
+
+ for (ui = 0; ui < uKeyLen; ui++)
+ {
+ if (*p1++ != *p2++)
+ return IMG_FALSE;
+ }
+
+ return IMG_TRUE;
+}
+
+static PVRSRV_ERROR
+_ChainInsert (HASH_TABLE *pHash, BUCKET *pBucket, BUCKET **ppBucketTable, IMG_UINT32 uSize)
+{
+ IMG_UINT32 uIndex;
+
+ PVR_ASSERT (pBucket != IMG_NULL);
+ PVR_ASSERT (ppBucketTable != IMG_NULL);
+ PVR_ASSERT (uSize != 0);
+
+ if ((pBucket == IMG_NULL) || (ppBucketTable == IMG_NULL) || (uSize == 0))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "_ChainInsert: invalid parameter"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ uIndex = KEY_TO_INDEX(pHash, pBucket->k, uSize);
+ pBucket->pNext = ppBucketTable[uIndex];
+ ppBucketTable[uIndex] = pBucket;
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR
+_Rehash (HASH_TABLE *pHash,
+ BUCKET **ppOldTable, IMG_UINT32 uOldSize,
+ BUCKET **ppNewTable, IMG_UINT32 uNewSize)
+{
+ IMG_UINT32 uIndex;
+ for (uIndex=0; uIndex< uOldSize; uIndex++)
+ {
+ BUCKET *pBucket;
+ pBucket = ppOldTable[uIndex];
+ while (pBucket != IMG_NULL)
+ {
+ PVRSRV_ERROR eError;
+ BUCKET *pNextBucket = pBucket->pNext;
+ eError = _ChainInsert (pHash, pBucket, ppNewTable, uNewSize);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "_Rehash: call to _ChainInsert failed"));
+ return eError;
+ }
+ pBucket = pNextBucket;
+ }
+ }
+ return PVRSRV_OK;
+}
+
+static IMG_BOOL
+_Resize (HASH_TABLE *pHash, IMG_UINT32 uNewSize)
+{
+ if (uNewSize != pHash->uSize)
+ {
+ BUCKET **ppNewTable;
+ IMG_UINT32 uIndex;
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "HASH_Resize: oldsize=0x%x newsize=0x%x count=0x%x",
+ pHash->uSize, uNewSize, pHash->uCount));
+
+ OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof (BUCKET *) * uNewSize,
+ (IMG_PVOID*)&ppNewTable, IMG_NULL,
+ "Hash Table Buckets");
+ if (ppNewTable == IMG_NULL)
+ return IMG_FALSE;
+
+ for (uIndex=0; uIndex<uNewSize; uIndex++)
+ ppNewTable[uIndex] = IMG_NULL;
+
+ if (_Rehash (pHash, pHash->ppBucketTable, pHash->uSize, ppNewTable, uNewSize) != PVRSRV_OK)
+ {
+ return IMG_FALSE;
+ }
+
+ OSFreeMem (PVRSRV_PAGEABLE_SELECT, sizeof(BUCKET *)*pHash->uSize, pHash->ppBucketTable, IMG_NULL);
+
+ pHash->ppBucketTable = ppNewTable;
+ pHash->uSize = uNewSize;
+ }
+ return IMG_TRUE;
+}
+
+
+HASH_TABLE * HASH_Create_Extended (IMG_UINT32 uInitialLen, IMG_SIZE_T uKeySize, HASH_FUNC *pfnHashFunc, HASH_KEY_COMP *pfnKeyComp)
+{
+ HASH_TABLE *pHash;
+ IMG_UINT32 uIndex;
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Create_Extended: InitialSize=0x%x", uInitialLen));
+
+ if(OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(HASH_TABLE),
+ (IMG_VOID **)&pHash, IMG_NULL,
+ "Hash Table") != PVRSRV_OK)
+ {
+ return IMG_NULL;
+ }
+
+ pHash->uCount = 0;
+ pHash->uSize = uInitialLen;
+ pHash->uMinimumSize = uInitialLen;
+ pHash->uKeySize = (IMG_UINT32)uKeySize;
+ pHash->pfnHashFunc = pfnHashFunc;
+ pHash->pfnKeyComp = pfnKeyComp;
+
+ OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof (BUCKET *) * pHash->uSize,
+ (IMG_PVOID*)&pHash->ppBucketTable, IMG_NULL,
+ "Hash Table Buckets");
+
+ if (pHash->ppBucketTable == IMG_NULL)
+ {
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(HASH_TABLE), pHash, IMG_NULL);
+
+ return IMG_NULL;
+ }
+
+ for (uIndex=0; uIndex<pHash->uSize; uIndex++)
+ pHash->ppBucketTable[uIndex] = IMG_NULL;
+ return pHash;
+}
+
+HASH_TABLE * HASH_Create (IMG_UINT32 uInitialLen)
+{
+ return HASH_Create_Extended(uInitialLen, sizeof(IMG_UINTPTR_T),
+ &HASH_Func_Default, &HASH_Key_Comp_Default);
+}
+
+IMG_VOID
+HASH_Delete (HASH_TABLE *pHash)
+{
+ if (pHash != IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Delete"));
+
+ PVR_ASSERT (pHash->uCount==0);
+ if(pHash->uCount != 0)
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "HASH_Delete: leak detected in hash table!"));
+ PVR_DPF ((PVR_DBG_ERROR, "Likely Cause: client drivers not freeing alocations before destroying devmemcontext"));
+ }
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(BUCKET *)*pHash->uSize, pHash->ppBucketTable, IMG_NULL);
+ pHash->ppBucketTable = IMG_NULL;
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(HASH_TABLE), pHash, IMG_NULL);
+
+ }
+}
+
+IMG_BOOL
+HASH_Insert_Extended (HASH_TABLE *pHash, IMG_VOID *pKey, IMG_UINTPTR_T v)
+{
+ BUCKET *pBucket;
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "HASH_Insert_Extended: Hash=0x%08x, pKey=0x%08x, v=0x%x",
+ (IMG_UINTPTR_T)pHash, (IMG_UINTPTR_T)pKey, v));
+
+ PVR_ASSERT (pHash != IMG_NULL);
+
+ if (pHash == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "HASH_Insert_Extended: invalid parameter"));
+ return IMG_FALSE;
+ }
+
+ if(OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(BUCKET) + pHash->uKeySize,
+ (IMG_VOID **)&pBucket, IMG_NULL,
+ "Hash Table entry") != PVRSRV_OK)
+ {
+ return IMG_FALSE;
+ }
+
+ pBucket->v = v;
+
+ OSMemCopy(pBucket->k, pKey, pHash->uKeySize);
+ if (_ChainInsert (pHash, pBucket, pHash->ppBucketTable, pHash->uSize) != PVRSRV_OK)
+ {
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(BUCKET) + pHash->uKeySize,
+ pBucket, IMG_NULL);
+ return IMG_FALSE;
+ }
+
+ pHash->uCount++;
+
+
+ if (pHash->uCount << 1 > pHash->uSize)
+ {
+
+
+ _Resize (pHash, pHash->uSize << 1);
+ }
+
+
+ return IMG_TRUE;
+}
+
+IMG_BOOL
+HASH_Insert (HASH_TABLE *pHash, IMG_UINTPTR_T k, IMG_UINTPTR_T v)
+{
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "HASH_Insert: Hash=0x%x, k=0x%x, v=0x%x",
+ (IMG_UINTPTR_T)pHash, k, v));
+
+ return HASH_Insert_Extended(pHash, &k, v);
+}
+
+IMG_UINTPTR_T
+HASH_Remove_Extended(HASH_TABLE *pHash, IMG_VOID *pKey)
+{
+ BUCKET **ppBucket;
+ IMG_UINT32 uIndex;
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Remove_Extended: Hash=0x%x, pKey=0x%x",
+ (IMG_UINTPTR_T)pHash, (IMG_UINTPTR_T)pKey));
+
+ PVR_ASSERT (pHash != IMG_NULL);
+
+ if (pHash == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "HASH_Remove_Extended: Null hash table"));
+ return 0;
+ }
+
+ uIndex = KEY_TO_INDEX(pHash, pKey, pHash->uSize);
+
+ for (ppBucket = &(pHash->ppBucketTable[uIndex]); *ppBucket != IMG_NULL; ppBucket = &((*ppBucket)->pNext))
+ {
+
+ if (KEY_COMPARE(pHash, (*ppBucket)->k, pKey))
+ {
+ BUCKET *pBucket = *ppBucket;
+ IMG_UINTPTR_T v = pBucket->v;
+ (*ppBucket) = pBucket->pNext;
+
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(BUCKET) + pHash->uKeySize, pBucket, IMG_NULL);
+
+
+ pHash->uCount--;
+
+
+ if (pHash->uSize > (pHash->uCount << 2) &&
+ pHash->uSize > pHash->uMinimumSize)
+ {
+
+
+ _Resize (pHash,
+ PRIVATE_MAX (pHash->uSize >> 1,
+ pHash->uMinimumSize));
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "HASH_Remove_Extended: Hash=0x%x, pKey=0x%x = 0x%x",
+ (IMG_UINTPTR_T)pHash, (IMG_UINTPTR_T)pKey, v));
+ return v;
+ }
+ }
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "HASH_Remove_Extended: Hash=0x%x, pKey=0x%x = 0x0 !!!!",
+ (IMG_UINTPTR_T)pHash, (IMG_UINTPTR_T)pKey));
+ return 0;
+}
+
+IMG_UINTPTR_T
+HASH_Remove (HASH_TABLE *pHash, IMG_UINTPTR_T k)
+{
+ PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Remove: Hash=0x%x, k=0x%x",
+ (IMG_UINTPTR_T)pHash, k));
+
+ return HASH_Remove_Extended(pHash, &k);
+}
+
+IMG_UINTPTR_T
+HASH_Retrieve_Extended (HASH_TABLE *pHash, IMG_VOID *pKey)
+{
+ BUCKET **ppBucket;
+ IMG_UINT32 uIndex;
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Retrieve_Extended: Hash=0x%x, pKey=0x%x",
+ (IMG_UINTPTR_T)pHash, (IMG_UINTPTR_T)pKey));
+
+ PVR_ASSERT (pHash != IMG_NULL);
+
+ if (pHash == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "HASH_Retrieve_Extended: Null hash table"));
+ return 0;
+ }
+
+ uIndex = KEY_TO_INDEX(pHash, pKey, pHash->uSize);
+
+ for (ppBucket = &(pHash->ppBucketTable[uIndex]); *ppBucket != IMG_NULL; ppBucket = &((*ppBucket)->pNext))
+ {
+
+ if (KEY_COMPARE(pHash, (*ppBucket)->k, pKey))
+ {
+ BUCKET *pBucket = *ppBucket;
+ IMG_UINTPTR_T v = pBucket->v;
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "HASH_Retrieve: Hash=0x%x, pKey=0x%x = 0x%x",
+ (IMG_UINTPTR_T)pHash, (IMG_UINTPTR_T)pKey, v));
+ return v;
+ }
+ }
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "HASH_Retrieve: Hash=0x%x, pKey=0x%x = 0x0 !!!!",
+ (IMG_UINTPTR_T)pHash, (IMG_UINTPTR_T)pKey));
+ return 0;
+}
+
+IMG_UINTPTR_T
+HASH_Retrieve (HASH_TABLE *pHash, IMG_UINTPTR_T k)
+{
+ PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Retrieve: Hash=0x%x, k=0x%x",
+ (IMG_UINTPTR_T)pHash, k));
+ return HASH_Retrieve_Extended(pHash, &k);
+}
+
+PVRSRV_ERROR
+HASH_Iterate(HASH_TABLE *pHash, HASH_pfnCallback pfnCallback)
+{
+ IMG_UINT32 uIndex;
+ for (uIndex=0; uIndex < pHash->uSize; uIndex++)
+ {
+ BUCKET *pBucket;
+ pBucket = pHash->ppBucketTable[uIndex];
+ while (pBucket != IMG_NULL)
+ {
+ PVRSRV_ERROR eError;
+ BUCKET *pNextBucket = pBucket->pNext;
+
+ eError = pfnCallback((IMG_UINTPTR_T) ((IMG_VOID *) *(pBucket->k)), (IMG_UINTPTR_T) pBucket->v);
+
+
+ if (eError != PVRSRV_OK)
+ return eError;
+
+ pBucket = pNextBucket;
+ }
+ }
+ return PVRSRV_OK;
+}
+
+#ifdef HASH_TRACE
+IMG_VOID
+HASH_Dump (HASH_TABLE *pHash)
+{
+ IMG_UINT32 uIndex;
+ IMG_UINT32 uMaxLength=0;
+ IMG_UINT32 uEmptyCount=0;
+
+ PVR_ASSERT (pHash != IMG_NULL);
+ for (uIndex=0; uIndex<pHash->uSize; uIndex++)
+ {
+ BUCKET *pBucket;
+ IMG_UINT32 uLength = 0;
+ if (pHash->ppBucketTable[uIndex] == IMG_NULL)
+ {
+ uEmptyCount++;
+ }
+ for (pBucket=pHash->ppBucketTable[uIndex];
+ pBucket != IMG_NULL;
+ pBucket = pBucket->pNext)
+ {
+ uLength++;
+ }
+ uMaxLength = PRIVATE_MAX (uMaxLength, uLength);
+ }
+
+ PVR_TRACE(("hash table: uMinimumSize=%d size=%d count=%d",
+ pHash->uMinimumSize, pHash->uSize, pHash->uCount));
+ PVR_TRACE((" empty=%d max=%d", uEmptyCount, uMaxLength));
+}
+#endif
diff --git a/drivers/gpu/pvr/hash.h b/drivers/gpu/pvr/hash.h
new file mode 100644
index 0000000..3662089
--- /dev/null
+++ b/drivers/gpu/pvr/hash.h
@@ -0,0 +1,80 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef _HASH_H_
+#define _HASH_H_
+
+#include "img_types.h"
+#include "osfunc.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+typedef IMG_UINT32 HASH_FUNC(IMG_SIZE_T uKeySize, IMG_VOID *pKey, IMG_UINT32 uHashTabLen);
+typedef IMG_BOOL HASH_KEY_COMP(IMG_SIZE_T uKeySize, IMG_VOID *pKey1, IMG_VOID *pKey2);
+
+typedef struct _HASH_TABLE_ HASH_TABLE;
+
+typedef PVRSRV_ERROR (*HASH_pfnCallback) (
+ IMG_UINTPTR_T k,
+ IMG_UINTPTR_T v
+);
+
+IMG_UINT32 HASH_Func_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey, IMG_UINT32 uHashTabLen);
+
+IMG_BOOL HASH_Key_Comp_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey1, IMG_VOID *pKey2);
+
+HASH_TABLE * HASH_Create_Extended (IMG_UINT32 uInitialLen, IMG_SIZE_T uKeySize, HASH_FUNC *pfnHashFunc, HASH_KEY_COMP *pfnKeyComp);
+
+HASH_TABLE * HASH_Create (IMG_UINT32 uInitialLen);
+
+IMG_VOID HASH_Delete (HASH_TABLE *pHash);
+
+IMG_BOOL HASH_Insert_Extended (HASH_TABLE *pHash, IMG_VOID *pKey, IMG_UINTPTR_T v);
+
+IMG_BOOL HASH_Insert (HASH_TABLE *pHash, IMG_UINTPTR_T k, IMG_UINTPTR_T v);
+
+IMG_UINTPTR_T HASH_Remove_Extended(HASH_TABLE *pHash, IMG_VOID *pKey);
+
+IMG_UINTPTR_T HASH_Remove (HASH_TABLE *pHash, IMG_UINTPTR_T k);
+
+IMG_UINTPTR_T HASH_Retrieve_Extended (HASH_TABLE *pHash, IMG_VOID *pKey);
+
+IMG_UINTPTR_T HASH_Retrieve (HASH_TABLE *pHash, IMG_UINTPTR_T k);
+
+PVRSRV_ERROR HASH_Iterate(HASH_TABLE *pHash, HASH_pfnCallback pfnCallback);
+
+#ifdef HASH_TRACE
+IMG_VOID HASH_Dump (HASH_TABLE *pHash);
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/pvr/img_defs.h b/drivers/gpu/pvr/img_defs.h
new file mode 100644
index 0000000..d5408cf
--- /dev/null
+++ b/drivers/gpu/pvr/img_defs.h
@@ -0,0 +1,136 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+*******************************************************************************/
+#if !defined (__IMG_DEFS_H__)
+#define __IMG_DEFS_H__
+
+#include "img_types.h"
+
+typedef enum img_tag_TriStateSwitch
+{
+ IMG_ON = 0x00,
+ IMG_OFF,
+ IMG_IGNORE
+
+} img_TriStateSwitch, * img_pTriStateSwitch;
+
+#define IMG_SUCCESS 0
+
+#define IMG_NO_REG 1
+
+#if defined (NO_INLINE_FUNCS)
+ #define INLINE
+ #define FORCE_INLINE
+#else
+#if defined (__cplusplus)
+ #define INLINE inline
+ #define FORCE_INLINE inline
+#else
+#if !defined(INLINE)
+ #define INLINE __inline
+#endif
+ #define FORCE_INLINE static __inline
+#endif
+#endif
+
+
+/* Use this in any file, or use attributes under GCC - see below */
+#ifndef PVR_UNREFERENCED_PARAMETER
+#define PVR_UNREFERENCED_PARAMETER(param) (param) = (param)
+#endif
+
+/* The best way to supress unused parameter warnings using GCC is to use a
+ * variable attribute. Place the unref__ between the type and name of an
+ * unused parameter in a function parameter list, eg `int unref__ var'. This
+ * should only be used in GCC build environments, for example, in files that
+ * compile only on Linux. Other files should use UNREFERENCED_PARAMETER */
+#ifdef __GNUC__
+#define unref__ __attribute__ ((unused))
+#else
+#define unref__
+#endif
+
+/*
+ Wide character definitions
+*/
+#ifndef _TCHAR_DEFINED
+#if defined(UNICODE)
+typedef unsigned short TCHAR, *PTCHAR, *PTSTR;
+#else /* #if defined(UNICODE) */
+typedef char TCHAR, *PTCHAR, *PTSTR;
+#endif /* #if defined(UNICODE) */
+#define _TCHAR_DEFINED
+#endif /* #ifndef _TCHAR_DEFINED */
+
+
+ #if defined(__linux__) || defined(__METAG)
+
+ #define IMG_CALLCONV
+ #define IMG_INTERNAL __attribute__((visibility("hidden")))
+ #define IMG_EXPORT __attribute__((visibility("default")))
+ #define IMG_IMPORT
+ #define IMG_RESTRICT __restrict__
+
+ #else
+ #error("define an OS")
+ #endif
+
+// Use default definition if not overridden
+#ifndef IMG_ABORT
+ #define IMG_ABORT() abort()
+#endif
+
+#ifndef IMG_MALLOC
+ #define IMG_MALLOC(A) malloc (A)
+#endif
+
+#ifndef IMG_FREE
+ #define IMG_FREE(A) free (A)
+#endif
+
+#define IMG_CONST const
+
+#if defined(__GNUC__)
+#define IMG_FORMAT_PRINTF(x,y) __attribute__((format(printf,x,y)))
+#else
+#define IMG_FORMAT_PRINTF(x,y)
+#endif
+
+/*
+ * Cleanup request defines
+ */
+#define CLEANUP_WITH_POLL IMG_FALSE
+#define FORCE_CLEANUP IMG_TRUE
+
+#if defined (_WIN64)
+#define IMG_UNDEF (~0ULL)
+#else
+#define IMG_UNDEF (~0UL)
+#endif
+
+#endif /* #if !defined (__IMG_DEFS_H__) */
+/*****************************************************************************
+ End of file (IMG_DEFS.H)
+*****************************************************************************/
diff --git a/drivers/gpu/pvr/img_types.h b/drivers/gpu/pvr/img_types.h
new file mode 100644
index 0000000..71dcebb
--- /dev/null
+++ b/drivers/gpu/pvr/img_types.h
@@ -0,0 +1,206 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+******************************************************************************/
+
+#ifndef __IMG_TYPES_H__
+#define __IMG_TYPES_H__
+
+/* define all address space bit depths: */
+/* CPU virtual address space defaults to 32bits */
+#if !defined(IMG_ADDRSPACE_CPUVADDR_BITS)
+#define IMG_ADDRSPACE_CPUVADDR_BITS 32
+#endif
+
+/* Physical address space defaults to 32bits */
+#if !defined(IMG_ADDRSPACE_PHYSADDR_BITS)
+#define IMG_ADDRSPACE_PHYSADDR_BITS 32
+#endif
+
+typedef unsigned int IMG_UINT, *IMG_PUINT;
+typedef signed int IMG_INT, *IMG_PINT;
+
+typedef unsigned char IMG_UINT8, *IMG_PUINT8;
+typedef unsigned char IMG_BYTE, *IMG_PBYTE;
+typedef signed char IMG_INT8, *IMG_PINT8;
+typedef char IMG_CHAR, *IMG_PCHAR;
+
+typedef unsigned short IMG_UINT16, *IMG_PUINT16;
+typedef signed short IMG_INT16, *IMG_PINT16;
+#if !defined(IMG_UINT32_IS_ULONG)
+typedef unsigned int IMG_UINT32, *IMG_PUINT32;
+typedef signed int IMG_INT32, *IMG_PINT32;
+#else
+typedef unsigned long IMG_UINT32, *IMG_PUINT32;
+typedef signed long IMG_INT32, *IMG_PINT32;
+#endif
+#if !defined(IMG_UINT32_MAX)
+ #define IMG_UINT32_MAX 0xFFFFFFFFUL
+#endif
+
+#if defined(USE_CODE)
+
+typedef unsigned __int64 IMG_UINT64, *IMG_PUINT64;
+typedef __int64 IMG_INT64, *IMG_PINT64;
+
+#else
+ #if (defined(LINUX) || defined(__METAG))
+ typedef unsigned long long IMG_UINT64, *IMG_PUINT64;
+ typedef long long IMG_INT64, *IMG_PINT64;
+ #else
+ #error("define an OS")
+ #endif
+#endif
+
+#if !(defined(LINUX) && defined (__KERNEL__))
+/* Linux kernel mode does not use floating point */
+typedef float IMG_FLOAT, *IMG_PFLOAT;
+typedef double IMG_DOUBLE, *IMG_PDOUBLE;
+#endif
+
+typedef enum tag_img_bool
+{
+ IMG_FALSE = 0,
+ IMG_TRUE = 1,
+ IMG_FORCE_ALIGN = 0x7FFFFFFF
+} IMG_BOOL, *IMG_PBOOL;
+
+typedef void IMG_VOID, *IMG_PVOID;
+
+typedef IMG_INT32 IMG_RESULT;
+
+#if defined(_WIN64)
+ typedef unsigned __int64 IMG_UINTPTR_T;
+ typedef signed __int64 IMG_PTRDIFF_T;
+ typedef IMG_UINT64 IMG_SIZE_T;
+#else
+ typedef unsigned int IMG_UINTPTR_T;
+ typedef IMG_UINT32 IMG_SIZE_T;
+#endif
+
+typedef IMG_PVOID IMG_HANDLE;
+
+typedef void** IMG_HVOID, * IMG_PHVOID;
+
+#define IMG_NULL 0
+
+/* services/stream ID */
+typedef IMG_UINT32 IMG_SID;
+
+typedef IMG_UINT32 IMG_EVENTSID;
+
+/* Which of IMG_HANDLE/IMG_SID depends on SUPPORT_SID_INTERFACE */
+#if defined(SUPPORT_SID_INTERFACE)
+ typedef IMG_SID IMG_S_HANDLE;
+#else
+ typedef IMG_HANDLE IMG_S_HANDLE;
+#endif
+
+/*
+ * Address types.
+ * All types used to refer to a block of memory are wrapped in structures
+ * to enforce some degree of type safety, i.e. a IMG_DEV_VIRTADDR cannot
+ * be assigned to a variable of type IMG_DEV_PHYADDR because they are not the
+ * same thing.
+ *
+ * There is an assumption that the system contains at most one non-cpu mmu,
+ * and a memory block is only mapped by the MMU once.
+ *
+ * Different devices could have offset views of the physical address space.
+ *
+ */
+
+
+/*
+ *
+ * +------------+ +------------+ +------------+ +------------+
+ * | CPU | | DEV | | DEV | | DEV |
+ * +------------+ +------------+ +------------+ +------------+
+ * | | | |
+ * | PVOID |IMG_DEV_VIRTADDR |IMG_DEV_VIRTADDR |
+ * | \-------------------/ |
+ * | | |
+ * +------------+ +------------+ |
+ * | MMU | | MMU | |
+ * +------------+ +------------+ |
+ * | | |
+ * | | |
+ * | | |
+ * +--------+ +---------+ +--------+
+ * | Offset | | (Offset)| | Offset |
+ * +--------+ +---------+ +--------+
+ * | | IMG_DEV_PHYADDR |
+ * | | |
+ * | | IMG_DEV_PHYADDR |
+ * +---------------------------------------------------------------------+
+ * | System Address bus |
+ * +---------------------------------------------------------------------+
+ *
+ */
+
+typedef IMG_PVOID IMG_CPU_VIRTADDR;
+
+/* device virtual address */
+typedef struct _IMG_DEV_VIRTADDR
+{
+ /* device virtual addresses are 32bit for now */
+ IMG_UINT32 uiAddr;
+#define IMG_CAST_TO_DEVVADDR_UINT(var) (IMG_UINT32)(var)
+
+} IMG_DEV_VIRTADDR;
+
+typedef IMG_UINT32 IMG_DEVMEM_SIZE_T;
+
+/* cpu physical address */
+typedef struct _IMG_CPU_PHYADDR
+{
+ /* variable sized type (32,64) */
+ IMG_UINTPTR_T uiAddr;
+} IMG_CPU_PHYADDR;
+
+/* device physical address */
+typedef struct _IMG_DEV_PHYADDR
+{
+#if IMG_ADDRSPACE_PHYSADDR_BITS == 32
+ /* variable sized type (32,64) */
+ IMG_UINTPTR_T uiAddr;
+#else
+ IMG_UINT32 uiAddr;
+ IMG_UINT32 uiHighAddr;
+#endif
+} IMG_DEV_PHYADDR;
+
+/* system physical address */
+typedef struct _IMG_SYS_PHYADDR
+{
+ /* variable sized type (32,64) */
+ IMG_UINTPTR_T uiAddr;
+} IMG_SYS_PHYADDR;
+
+#include "img_defs.h"
+
+#endif /* __IMG_TYPES_H__ */
+/******************************************************************************
+ End of file (img_types.h)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/ioctldef.h b/drivers/gpu/pvr/ioctldef.h
new file mode 100644
index 0000000..4b23ad4
--- /dev/null
+++ b/drivers/gpu/pvr/ioctldef.h
@@ -0,0 +1,98 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __IOCTLDEF_H__
+#define __IOCTLDEF_H__
+
+#define MAKEIOCTLINDEX(i) (((i) >> 2) & 0xFFF)
+
+#ifndef CTL_CODE
+
+#define DEVICE_TYPE ULONG
+
+#define FILE_DEVICE_BEEP 0x00000001
+#define FILE_DEVICE_CD_ROM 0x00000002
+#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003
+#define FILE_DEVICE_CONTROLLER 0x00000004
+#define FILE_DEVICE_DATALINK 0x00000005
+#define FILE_DEVICE_DFS 0x00000006
+#define FILE_DEVICE_DISK 0x00000007
+#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008
+#define FILE_DEVICE_FILE_SYSTEM 0x00000009
+#define FILE_DEVICE_INPORT_PORT 0x0000000a
+#define FILE_DEVICE_KEYBOARD 0x0000000b
+#define FILE_DEVICE_MAILSLOT 0x0000000c
+#define FILE_DEVICE_MIDI_IN 0x0000000d
+#define FILE_DEVICE_MIDI_OUT 0x0000000e
+#define FILE_DEVICE_MOUSE 0x0000000f
+#define FILE_DEVICE_MULTI_UNC_PROVIDER 0x00000010
+#define FILE_DEVICE_NAMED_PIPE 0x00000011
+#define FILE_DEVICE_NETWORK 0x00000012
+#define FILE_DEVICE_NETWORK_BROWSER 0x00000013
+#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014
+#define FILE_DEVICE_NULL 0x00000015
+#define FILE_DEVICE_PARALLEL_PORT 0x00000016
+#define FILE_DEVICE_PHYSICAL_NETCARD 0x00000017
+#define FILE_DEVICE_PRINTER 0x00000018
+#define FILE_DEVICE_SCANNER 0x00000019
+#define FILE_DEVICE_SERIAL_MOUSE_PORT 0x0000001a
+#define FILE_DEVICE_SERIAL_PORT 0x0000001b
+#define FILE_DEVICE_SCREEN 0x0000001c
+#define FILE_DEVICE_SOUND 0x0000001d
+#define FILE_DEVICE_STREAMS 0x0000001e
+#define FILE_DEVICE_TAPE 0x0000001f
+#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020
+#define FILE_DEVICE_TRANSPORT 0x00000021
+#define FILE_DEVICE_UNKNOWN 0x00000022
+#define FILE_DEVICE_VIDEO 0x00000023
+#define FILE_DEVICE_VIRTUAL_DISK 0x00000024
+#define FILE_DEVICE_WAVE_IN 0x00000025
+#define FILE_DEVICE_WAVE_OUT 0x00000026
+#define FILE_DEVICE_8042_PORT 0x00000027
+#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028
+#define FILE_DEVICE_BATTERY 0x00000029
+#define FILE_DEVICE_BUS_EXTENDER 0x0000002a
+#define FILE_DEVICE_MODEM 0x0000002b
+#define FILE_DEVICE_VDM 0x0000002c
+#define FILE_DEVICE_MASS_STORAGE 0x0000002d
+
+#define CTL_CODE( DeviceType, Function, Method, Access ) ( \
+ ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
+)
+
+#define METHOD_BUFFERED 0
+#define METHOD_IN_DIRECT 1
+#define METHOD_OUT_DIRECT 2
+#define METHOD_NEITHER 3
+
+#define FILE_ANY_ACCESS 0
+#define FILE_READ_ACCESS ( 0x0001 )
+#define FILE_WRITE_ACCESS ( 0x0002 )
+
+#endif
+
+#endif
+
diff --git a/drivers/gpu/pvr/ion.c b/drivers/gpu/pvr/ion.c
new file mode 100644
index 0000000..b00fdb1
--- /dev/null
+++ b/drivers/gpu/pvr/ion.c
@@ -0,0 +1,112 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ *****************************************************************************/
+
+#include "ion.h"
+
+#include "services.h"
+#include "servicesint.h"
+#include "mutex.h"
+#include "lock.h"
+#include "mm.h"
+#include "handle.h"
+#include "perproc.h"
+#include "env_perproc.h"
+#include "private_data.h"
+#include "pvr_debug.h"
+
+#include <linux/module.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+
+extern struct ion_client *gpsIONClient;
+
+void PVRSRVExportFDToIONHandles(int fd, struct ion_client **client,
+ struct ion_handle *handles[2])
+{
+ PVRSRV_FILE_PRIVATE_DATA *psPrivateData;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ LinuxMemArea *psLinuxMemArea;
+ PVRSRV_ERROR eError;
+ struct file *psFile;
+
+ /* Take the bridge mutex so the handle won't be freed underneath us */
+ LinuxLockMutex(&gPVRSRVLock);
+
+ psFile = fget(fd);
+ if(!psFile)
+ goto err_unlock;
+
+ psPrivateData = psFile->private_data;
+ if(!psPrivateData)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: struct file* has no private_data; "
+ "invalid export handle", __func__));
+ goto err_fput;
+ }
+
+ eError = PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+ (IMG_PVOID *)&psKernelMemInfo,
+ psPrivateData->hKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to look up MEM_INFO handle",
+ __func__));
+ goto err_fput;
+ }
+
+ psLinuxMemArea = (LinuxMemArea *)psKernelMemInfo->sMemBlk.hOSMemHandle;
+ BUG_ON(psLinuxMemArea == IMG_NULL);
+
+ if(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_ION)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Valid handle, but not an ION buffer",
+ __func__));
+ goto err_fput;
+ }
+
+ handles[0] = psLinuxMemArea->uData.sIONTilerAlloc.psIONHandle[0];
+ handles[1] = psLinuxMemArea->uData.sIONTilerAlloc.psIONHandle[1];
+ if(client)
+ *client = gpsIONClient;
+
+err_fput:
+ fput(psFile);
+err_unlock:
+ /* Allow PVRSRV clients to communicate with srvkm again */
+ LinuxUnLockMutex(&gPVRSRVLock);
+}
+
+struct ion_handle *
+PVRSRVExportFDToIONHandle(int fd, struct ion_client **client)
+{
+ struct ion_handle *psHandles[2] = { IMG_NULL, IMG_NULL };
+ PVRSRVExportFDToIONHandles(fd, client, psHandles);
+ return psHandles[0];
+}
+
+EXPORT_SYMBOL(PVRSRVExportFDToIONHandles);
+EXPORT_SYMBOL(PVRSRVExportFDToIONHandle);
diff --git a/drivers/gpu/pvr/ion.h b/drivers/gpu/pvr/ion.h
new file mode 100644
index 0000000..9b0868c
--- /dev/null
+++ b/drivers/gpu/pvr/ion.h
@@ -0,0 +1,39 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ *****************************************************************************/
+
+#ifndef __IMG_LINUX_ION_H__
+#define __IMG_LINUX_ION_H__
+
+#include <linux/ion.h>
+#include <linux/omap_ion.h>
+
+void PVRSRVExportFDToIONHandles(int fd, struct ion_client **client,
+ struct ion_handle *handles[2]);
+
+struct ion_handle *PVRSRVExportFDToIONHandle(int fd,
+ struct ion_client **client);
+
+#endif /* __IMG_LINUX_ION_H__ */
diff --git a/drivers/gpu/pvr/kernelbuffer.h b/drivers/gpu/pvr/kernelbuffer.h
new file mode 100644
index 0000000..4cd36d2
--- /dev/null
+++ b/drivers/gpu/pvr/kernelbuffer.h
@@ -0,0 +1,72 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#if !defined (__KERNELBUFFER_H__)
+#define __KERNELBUFFER_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+typedef PVRSRV_ERROR (*PFN_OPEN_BC_DEVICE)(IMG_UINT32, IMG_HANDLE*);
+typedef PVRSRV_ERROR (*PFN_CLOSE_BC_DEVICE)(IMG_UINT32, IMG_HANDLE);
+typedef PVRSRV_ERROR (*PFN_GET_BC_INFO)(IMG_HANDLE, BUFFER_INFO*);
+typedef PVRSRV_ERROR (*PFN_GET_BC_BUFFER)(IMG_HANDLE, IMG_UINT32, PVRSRV_SYNC_DATA*, IMG_HANDLE*);
+
+typedef struct PVRSRV_BC_SRV2BUFFER_KMJTABLE_TAG
+{
+ IMG_UINT32 ui32TableSize;
+ PFN_OPEN_BC_DEVICE pfnOpenBCDevice;
+ PFN_CLOSE_BC_DEVICE pfnCloseBCDevice;
+ PFN_GET_BC_INFO pfnGetBCInfo;
+ PFN_GET_BC_BUFFER pfnGetBCBuffer;
+ PFN_GET_BUFFER_ADDR pfnGetBufferAddr;
+
+} PVRSRV_BC_SRV2BUFFER_KMJTABLE;
+
+
+typedef PVRSRV_ERROR (*PFN_BC_REGISTER_BUFFER_DEV)(PVRSRV_BC_SRV2BUFFER_KMJTABLE*, IMG_UINT32*);
+typedef IMG_VOID (*PFN_BC_SCHEDULE_DEVICES)(IMG_VOID);
+typedef PVRSRV_ERROR (*PFN_BC_REMOVE_BUFFER_DEV)(IMG_UINT32);
+
+typedef struct PVRSRV_BC_BUFFER2SRV_KMJTABLE_TAG
+{
+ IMG_UINT32 ui32TableSize;
+ PFN_BC_REGISTER_BUFFER_DEV pfnPVRSRVRegisterBCDevice;
+ PFN_BC_SCHEDULE_DEVICES pfnPVRSRVScheduleDevices;
+ PFN_BC_REMOVE_BUFFER_DEV pfnPVRSRVRemoveBCDevice;
+
+} PVRSRV_BC_BUFFER2SRV_KMJTABLE, *PPVRSRV_BC_BUFFER2SRV_KMJTABLE;
+
+typedef IMG_BOOL (*PFN_BC_GET_PVRJTABLE) (PPVRSRV_BC_BUFFER2SRV_KMJTABLE);
+
+IMG_IMPORT IMG_BOOL PVRGetBufferClassJTable(PVRSRV_BC_BUFFER2SRV_KMJTABLE *psJTable);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
diff --git a/drivers/gpu/pvr/kerneldisplay.h b/drivers/gpu/pvr/kerneldisplay.h
new file mode 100644
index 0000000..55111d3
--- /dev/null
+++ b/drivers/gpu/pvr/kerneldisplay.h
@@ -0,0 +1,206 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#if !defined (__KERNELDISPLAY_H__)
+#define __KERNELDISPLAY_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+typedef PVRSRV_ERROR (*PFN_OPEN_DC_DEVICE)(IMG_UINT32, IMG_HANDLE*, PVRSRV_SYNC_DATA*);
+typedef PVRSRV_ERROR (*PFN_CLOSE_DC_DEVICE)(IMG_HANDLE);
+typedef PVRSRV_ERROR (*PFN_ENUM_DC_FORMATS)(IMG_HANDLE, IMG_UINT32*, DISPLAY_FORMAT*);
+typedef PVRSRV_ERROR (*PFN_ENUM_DC_DIMS)(IMG_HANDLE,
+ DISPLAY_FORMAT*,
+ IMG_UINT32*,
+ DISPLAY_DIMS*);
+typedef PVRSRV_ERROR (*PFN_GET_DC_SYSTEMBUFFER)(IMG_HANDLE, IMG_HANDLE*);
+typedef PVRSRV_ERROR (*PFN_GET_DC_INFO)(IMG_HANDLE, DISPLAY_INFO*);
+typedef PVRSRV_ERROR (*PFN_CREATE_DC_SWAPCHAIN)(IMG_HANDLE,
+ IMG_UINT32,
+ DISPLAY_SURF_ATTRIBUTES*,
+ DISPLAY_SURF_ATTRIBUTES*,
+ IMG_UINT32,
+ PVRSRV_SYNC_DATA**,
+ IMG_UINT32,
+ IMG_HANDLE*,
+ IMG_UINT32*);
+typedef PVRSRV_ERROR (*PFN_DESTROY_DC_SWAPCHAIN)(IMG_HANDLE,
+ IMG_HANDLE);
+typedef PVRSRV_ERROR (*PFN_SET_DC_DSTRECT)(IMG_HANDLE, IMG_HANDLE, IMG_RECT*);
+typedef PVRSRV_ERROR (*PFN_SET_DC_SRCRECT)(IMG_HANDLE, IMG_HANDLE, IMG_RECT*);
+typedef PVRSRV_ERROR (*PFN_SET_DC_DSTCK)(IMG_HANDLE, IMG_HANDLE, IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_SET_DC_SRCCK)(IMG_HANDLE, IMG_HANDLE, IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_GET_DC_BUFFERS)(IMG_HANDLE,
+ IMG_HANDLE,
+ IMG_UINT32*,
+ IMG_HANDLE*);
+typedef PVRSRV_ERROR (*PFN_SWAP_TO_DC_BUFFER)(IMG_HANDLE,
+ IMG_HANDLE,
+ IMG_UINT32,
+ IMG_HANDLE,
+ IMG_UINT32,
+ IMG_RECT*);
+typedef PVRSRV_ERROR (*PFN_SWAP_TO_DC_SYSTEM)(IMG_HANDLE, IMG_HANDLE);
+typedef IMG_VOID (*PFN_QUERY_SWAP_COMMAND_ID)(IMG_HANDLE, IMG_HANDLE, IMG_HANDLE, IMG_HANDLE, IMG_UINT16*, IMG_BOOL*);
+typedef IMG_VOID (*PFN_SET_DC_STATE)(IMG_HANDLE, IMG_UINT32);
+
+typedef struct PVRSRV_DC_SRV2DISP_KMJTABLE_TAG
+{
+ IMG_UINT32 ui32TableSize;
+ PFN_OPEN_DC_DEVICE pfnOpenDCDevice;
+ PFN_CLOSE_DC_DEVICE pfnCloseDCDevice;
+ PFN_ENUM_DC_FORMATS pfnEnumDCFormats;
+ PFN_ENUM_DC_DIMS pfnEnumDCDims;
+ PFN_GET_DC_SYSTEMBUFFER pfnGetDCSystemBuffer;
+ PFN_GET_DC_INFO pfnGetDCInfo;
+ PFN_GET_BUFFER_ADDR pfnGetBufferAddr;
+ PFN_CREATE_DC_SWAPCHAIN pfnCreateDCSwapChain;
+ PFN_DESTROY_DC_SWAPCHAIN pfnDestroyDCSwapChain;
+ PFN_SET_DC_DSTRECT pfnSetDCDstRect;
+ PFN_SET_DC_SRCRECT pfnSetDCSrcRect;
+ PFN_SET_DC_DSTCK pfnSetDCDstColourKey;
+ PFN_SET_DC_SRCCK pfnSetDCSrcColourKey;
+ PFN_GET_DC_BUFFERS pfnGetDCBuffers;
+ PFN_SWAP_TO_DC_BUFFER pfnSwapToDCBuffer;
+ PFN_SWAP_TO_DC_SYSTEM pfnSwapToDCSystem;
+ PFN_SET_DC_STATE pfnSetDCState;
+ PFN_QUERY_SWAP_COMMAND_ID pfnQuerySwapCommandID;
+
+} PVRSRV_DC_SRV2DISP_KMJTABLE;
+
+typedef IMG_BOOL (*PFN_ISR_HANDLER)(IMG_VOID*);
+
+typedef PVRSRV_ERROR (*PFN_DC_REGISTER_DISPLAY_DEV)(PVRSRV_DC_SRV2DISP_KMJTABLE*, IMG_UINT32*);
+typedef PVRSRV_ERROR (*PFN_DC_REMOVE_DISPLAY_DEV)(IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_DC_OEM_FUNCTION)(IMG_UINT32, IMG_VOID*, IMG_UINT32, IMG_VOID*, IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_DC_REGISTER_COMMANDPROCLIST)(IMG_UINT32, PPFN_CMD_PROC,IMG_UINT32[][2], IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_DC_REMOVE_COMMANDPROCLIST)(IMG_UINT32, IMG_UINT32);
+typedef IMG_VOID (*PFN_DC_CMD_COMPLETE)(IMG_HANDLE, IMG_BOOL);
+typedef PVRSRV_ERROR (*PFN_DC_REGISTER_SYS_ISR)(PFN_ISR_HANDLER, IMG_VOID*, IMG_UINT32, IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_DC_REGISTER_POWER)(IMG_UINT32, PFN_PRE_POWER, PFN_POST_POWER,
+ PFN_PRE_CLOCKSPEED_CHANGE, PFN_POST_CLOCKSPEED_CHANGE,
+ IMG_HANDLE, PVRSRV_DEV_POWER_STATE, PVRSRV_DEV_POWER_STATE);
+
+typedef struct _PVRSRV_KERNEL_MEM_INFO_* PDC_MEM_INFO;
+
+typedef PVRSRV_ERROR (*PFN_DC_MEMINFO_GET_CPU_VADDR)(PDC_MEM_INFO, IMG_CPU_VIRTADDR *pVAddr);
+typedef PVRSRV_ERROR (*PFN_DC_MEMINFO_GET_CPU_PADDR)(PDC_MEM_INFO, IMG_SIZE_T uByteOffset, IMG_CPU_PHYADDR *pPAddr);
+typedef PVRSRV_ERROR (*PFN_DC_MEMINFO_GET_BYTE_SIZE)(PDC_MEM_INFO, IMG_SIZE_T *uByteSize);
+typedef IMG_BOOL (*PFN_DC_MEMINFO_IS_PHYS_CONTIG)(PDC_MEM_INFO);
+
+typedef struct PVRSRV_DC_DISP2SRV_KMJTABLE_TAG
+{
+ IMG_UINT32 ui32TableSize;
+ PFN_DC_REGISTER_DISPLAY_DEV pfnPVRSRVRegisterDCDevice;
+ PFN_DC_REMOVE_DISPLAY_DEV pfnPVRSRVRemoveDCDevice;
+ PFN_DC_OEM_FUNCTION pfnPVRSRVOEMFunction;
+ PFN_DC_REGISTER_COMMANDPROCLIST pfnPVRSRVRegisterCmdProcList;
+ PFN_DC_REMOVE_COMMANDPROCLIST pfnPVRSRVRemoveCmdProcList;
+ PFN_DC_CMD_COMPLETE pfnPVRSRVCmdComplete;
+ PFN_DC_REGISTER_SYS_ISR pfnPVRSRVRegisterSystemISRHandler;
+ PFN_DC_REGISTER_POWER pfnPVRSRVRegisterPowerDevice;
+ PFN_DC_CMD_COMPLETE pfnPVRSRVFreeCmdCompletePacket;
+ PFN_DC_MEMINFO_GET_CPU_VADDR pfnPVRSRVDCMemInfoGetCpuVAddr;
+ PFN_DC_MEMINFO_GET_CPU_PADDR pfnPVRSRVDCMemInfoGetCpuPAddr;
+ PFN_DC_MEMINFO_GET_BYTE_SIZE pfnPVRSRVDCMemInfoGetByteSize;
+ PFN_DC_MEMINFO_IS_PHYS_CONTIG pfnPVRSRVDCMemInfoIsPhysContig;
+
+} PVRSRV_DC_DISP2SRV_KMJTABLE, *PPVRSRV_DC_DISP2SRV_KMJTABLE;
+
+
+typedef struct DISPLAYCLASS_FLIP_COMMAND_TAG
+{
+
+ IMG_HANDLE hExtDevice;
+
+
+ IMG_HANDLE hExtSwapChain;
+
+
+ IMG_HANDLE hExtBuffer;
+
+
+ IMG_HANDLE hPrivateTag;
+
+
+ IMG_UINT32 ui32ClipRectCount;
+
+
+ IMG_RECT *psClipRect;
+
+
+ IMG_UINT32 ui32SwapInterval;
+
+} DISPLAYCLASS_FLIP_COMMAND;
+
+
+typedef struct DISPLAYCLASS_FLIP_COMMAND2_TAG
+{
+
+ IMG_HANDLE hExtDevice;
+
+
+ IMG_HANDLE hExtSwapChain;
+
+
+ IMG_HANDLE hUnused;
+
+
+ IMG_UINT32 ui32SwapInterval;
+
+
+ IMG_PVOID pvPrivData;
+
+
+ IMG_UINT32 ui32PrivDataLength;
+
+
+ PDC_MEM_INFO *ppsMemInfos;
+
+
+ IMG_UINT32 ui32NumMemInfos;
+
+} DISPLAYCLASS_FLIP_COMMAND2;
+
+#define DC_FLIP_COMMAND 0
+
+#define DC_STATE_NO_FLUSH_COMMANDS 0
+#define DC_STATE_FLUSH_COMMANDS 1
+
+
+typedef IMG_BOOL (*PFN_DC_GET_PVRJTABLE)(PPVRSRV_DC_DISP2SRV_KMJTABLE);
+
+IMG_IMPORT IMG_BOOL PVRGetDisplayClassJTable(PVRSRV_DC_DISP2SRV_KMJTABLE *psJTable);
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/pvr/linkage.h b/drivers/gpu/pvr/linkage.h
new file mode 100644
index 0000000..e64012c
--- /dev/null
+++ b/drivers/gpu/pvr/linkage.h
@@ -0,0 +1,52 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __LINKAGE_H__
+#define __LINKAGE_H__
+
+#if !defined(SUPPORT_DRI_DRM)
+long PVRSRV_BridgeDispatchKM(struct file *file, unsigned int cmd, unsigned long arg);
+#endif
+
+IMG_VOID PVRDPFInit(IMG_VOID);
+PVRSRV_ERROR PVROSFuncInit(IMG_VOID);
+IMG_VOID PVROSFuncDeInit(IMG_VOID);
+
+#ifdef DEBUG
+
+IMG_INT PVRDebugProcSetLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data);
+void ProcSeqShowDebugLevel(struct seq_file *sfile,void* el);
+
+#ifdef PVR_MANUAL_POWER_CONTROL
+IMG_INT PVRProcSetPowerLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data);
+
+void ProcSeqShowPowerLevel(struct seq_file *sfile,void* el);
+
+#endif
+
+#endif
+
+#endif
diff --git a/drivers/gpu/pvr/lists.c b/drivers/gpu/pvr/lists.c
new file mode 100644
index 0000000..1081781
--- /dev/null
+++ b/drivers/gpu/pvr/lists.c
@@ -0,0 +1,99 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "lists.h"
+#include "services_headers.h"
+
+IMPLEMENT_LIST_ANY_VA(BM_HEAP)
+IMPLEMENT_LIST_ANY_2(BM_HEAP, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_ANY_VA_2(BM_HEAP, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_FOR_EACH_VA(BM_HEAP)
+IMPLEMENT_LIST_REMOVE(BM_HEAP)
+IMPLEMENT_LIST_INSERT(BM_HEAP)
+
+IMPLEMENT_LIST_ANY_VA(BM_CONTEXT)
+IMPLEMENT_LIST_ANY_VA_2(BM_CONTEXT, IMG_HANDLE, IMG_NULL)
+IMPLEMENT_LIST_ANY_VA_2(BM_CONTEXT, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_FOR_EACH(BM_CONTEXT)
+IMPLEMENT_LIST_REMOVE(BM_CONTEXT)
+IMPLEMENT_LIST_INSERT(BM_CONTEXT)
+
+IMPLEMENT_LIST_ANY_2(PVRSRV_DEVICE_NODE, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_ANY_VA(PVRSRV_DEVICE_NODE)
+IMPLEMENT_LIST_ANY_VA_2(PVRSRV_DEVICE_NODE, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_FOR_EACH(PVRSRV_DEVICE_NODE)
+IMPLEMENT_LIST_FOR_EACH_VA(PVRSRV_DEVICE_NODE)
+IMPLEMENT_LIST_INSERT(PVRSRV_DEVICE_NODE)
+IMPLEMENT_LIST_REMOVE(PVRSRV_DEVICE_NODE)
+
+IMPLEMENT_LIST_ANY_VA(PVRSRV_POWER_DEV)
+IMPLEMENT_LIST_ANY_VA_2(PVRSRV_POWER_DEV, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_INSERT(PVRSRV_POWER_DEV)
+IMPLEMENT_LIST_REMOVE(PVRSRV_POWER_DEV)
+
+
+IMG_VOID* MatchDeviceKM_AnyVaCb(PVRSRV_DEVICE_NODE* psDeviceNode, va_list va)
+{
+ IMG_UINT32 ui32DevIndex;
+ IMG_BOOL bIgnoreClass;
+ PVRSRV_DEVICE_CLASS eDevClass;
+
+ ui32DevIndex = va_arg(va, IMG_UINT32);
+ bIgnoreClass = va_arg(va, IMG_BOOL);
+ if (!bIgnoreClass)
+ {
+ eDevClass = va_arg(va, PVRSRV_DEVICE_CLASS);
+ }
+ else
+ {
+
+
+ eDevClass = PVRSRV_DEVICE_CLASS_FORCE_I32;
+ }
+
+ if ((bIgnoreClass || psDeviceNode->sDevId.eDeviceClass == eDevClass) &&
+ psDeviceNode->sDevId.ui32DeviceIndex == ui32DevIndex)
+ {
+ return psDeviceNode;
+ }
+ return IMG_NULL;
+}
+
+IMG_VOID* MatchPowerDeviceIndex_AnyVaCb(PVRSRV_POWER_DEV *psPowerDev, va_list va)
+{
+ IMG_UINT32 ui32DeviceIndex;
+
+ ui32DeviceIndex = va_arg(va, IMG_UINT32);
+
+ if (psPowerDev->ui32DeviceIndex == ui32DeviceIndex)
+ {
+ return psPowerDev;
+ }
+ else
+ {
+ return IMG_NULL;
+ }
+}
diff --git a/drivers/gpu/pvr/lists.h b/drivers/gpu/pvr/lists.h
new file mode 100644
index 0000000..a02307a
--- /dev/null
+++ b/drivers/gpu/pvr/lists.h
@@ -0,0 +1,244 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __LISTS_UTILS__
+#define __LISTS_UTILS__
+
+#include <stdarg.h>
+#include "img_types.h"
+
+#define DECLARE_LIST_FOR_EACH(TYPE) \
+IMG_VOID List_##TYPE##_ForEach(TYPE *psHead, IMG_VOID(*pfnCallBack)(TYPE* psNode))
+
+#define IMPLEMENT_LIST_FOR_EACH(TYPE) \
+IMG_VOID List_##TYPE##_ForEach(TYPE *psHead, IMG_VOID(*pfnCallBack)(TYPE* psNode))\
+{\
+ while(psHead)\
+ {\
+ pfnCallBack(psHead);\
+ psHead = psHead->psNext;\
+ }\
+}
+
+
+#define DECLARE_LIST_FOR_EACH_VA(TYPE) \
+IMG_VOID List_##TYPE##_ForEach_va(TYPE *psHead, IMG_VOID(*pfnCallBack)(TYPE* psNode, va_list va), ...)
+
+#define IMPLEMENT_LIST_FOR_EACH_VA(TYPE) \
+IMG_VOID List_##TYPE##_ForEach_va(TYPE *psHead, IMG_VOID(*pfnCallBack)(TYPE* psNode, va_list va), ...) \
+{\
+ va_list ap;\
+ while(psHead)\
+ {\
+ va_start(ap, pfnCallBack);\
+ pfnCallBack(psHead, ap);\
+ psHead = psHead->psNext;\
+ va_end(ap);\
+ }\
+}
+
+
+#define DECLARE_LIST_ANY(TYPE) \
+IMG_VOID* List_##TYPE##_Any(TYPE *psHead, IMG_VOID* (*pfnCallBack)(TYPE* psNode))
+
+#define IMPLEMENT_LIST_ANY(TYPE) \
+IMG_VOID* List_##TYPE##_Any(TYPE *psHead, IMG_VOID* (*pfnCallBack)(TYPE* psNode))\
+{ \
+ IMG_VOID *pResult;\
+ TYPE *psNextNode;\
+ pResult = IMG_NULL;\
+ psNextNode = psHead;\
+ while(psHead && !pResult)\
+ {\
+ psNextNode = psNextNode->psNext;\
+ pResult = pfnCallBack(psHead);\
+ psHead = psNextNode;\
+ }\
+ return pResult;\
+}
+
+
+#define DECLARE_LIST_ANY_VA(TYPE) \
+IMG_VOID* List_##TYPE##_Any_va(TYPE *psHead, IMG_VOID*(*pfnCallBack)(TYPE* psNode, va_list va), ...)
+
+#define IMPLEMENT_LIST_ANY_VA(TYPE) \
+IMG_VOID* List_##TYPE##_Any_va(TYPE *psHead, IMG_VOID*(*pfnCallBack)(TYPE* psNode, va_list va), ...)\
+{\
+ va_list ap;\
+ TYPE *psNextNode;\
+ IMG_VOID* pResult = IMG_NULL;\
+ while(psHead && !pResult)\
+ {\
+ psNextNode = psHead->psNext;\
+ va_start(ap, pfnCallBack);\
+ pResult = pfnCallBack(psHead, ap);\
+ va_end(ap);\
+ psHead = psNextNode;\
+ }\
+ return pResult;\
+}
+
+#define DECLARE_LIST_ANY_2(TYPE, RTYPE, CONTINUE) \
+RTYPE List_##TYPE##_##RTYPE##_Any(TYPE *psHead, RTYPE (*pfnCallBack)(TYPE* psNode))
+
+#define IMPLEMENT_LIST_ANY_2(TYPE, RTYPE, CONTINUE) \
+RTYPE List_##TYPE##_##RTYPE##_Any(TYPE *psHead, RTYPE (*pfnCallBack)(TYPE* psNode))\
+{ \
+ RTYPE result;\
+ TYPE *psNextNode;\
+ result = CONTINUE;\
+ psNextNode = psHead;\
+ while(psHead && result == CONTINUE)\
+ {\
+ psNextNode = psNextNode->psNext;\
+ result = pfnCallBack(psHead);\
+ psHead = psNextNode;\
+ }\
+ return result;\
+}
+
+
+#define DECLARE_LIST_ANY_VA_2(TYPE, RTYPE, CONTINUE) \
+RTYPE List_##TYPE##_##RTYPE##_Any_va(TYPE *psHead, RTYPE(*pfnCallBack)(TYPE* psNode, va_list va), ...)
+
+#define IMPLEMENT_LIST_ANY_VA_2(TYPE, RTYPE, CONTINUE) \
+RTYPE List_##TYPE##_##RTYPE##_Any_va(TYPE *psHead, RTYPE(*pfnCallBack)(TYPE* psNode, va_list va), ...)\
+{\
+ va_list ap;\
+ TYPE *psNextNode;\
+ RTYPE result = CONTINUE;\
+ while(psHead && result == CONTINUE)\
+ {\
+ psNextNode = psHead->psNext;\
+ va_start(ap, pfnCallBack);\
+ result = pfnCallBack(psHead, ap);\
+ va_end(ap);\
+ psHead = psNextNode;\
+ }\
+ return result;\
+}
+
+
+#define DECLARE_LIST_REMOVE(TYPE) \
+IMG_VOID List_##TYPE##_Remove(TYPE *psNode)
+
+#define IMPLEMENT_LIST_REMOVE(TYPE) \
+IMG_VOID List_##TYPE##_Remove(TYPE *psNode)\
+{\
+ (*psNode->ppsThis)=psNode->psNext;\
+ if(psNode->psNext)\
+ {\
+ psNode->psNext->ppsThis = psNode->ppsThis;\
+ }\
+}
+
+#define DECLARE_LIST_INSERT(TYPE) \
+IMG_VOID List_##TYPE##_Insert(TYPE **ppsHead, TYPE *psNewNode)
+
+#define IMPLEMENT_LIST_INSERT(TYPE) \
+IMG_VOID List_##TYPE##_Insert(TYPE **ppsHead, TYPE *psNewNode)\
+{\
+ psNewNode->ppsThis = ppsHead;\
+ psNewNode->psNext = *ppsHead;\
+ *ppsHead = psNewNode;\
+ if(psNewNode->psNext)\
+ {\
+ psNewNode->psNext->ppsThis = &(psNewNode->psNext);\
+ }\
+}
+
+#define DECLARE_LIST_REVERSE(TYPE) \
+IMG_VOID List_##TYPE##_Reverse(TYPE **ppsHead)
+
+#define IMPLEMENT_LIST_REVERSE(TYPE) \
+IMG_VOID List_##TYPE##_Reverse(TYPE **ppsHead)\
+{\
+ TYPE *psTmpNode1; \
+ TYPE *psTmpNode2; \
+ TYPE *psCurNode; \
+ psTmpNode1 = IMG_NULL; \
+ psCurNode = *ppsHead; \
+ while(psCurNode) { \
+ psTmpNode2 = psCurNode->psNext; \
+ psCurNode->psNext = psTmpNode1; \
+ psTmpNode1 = psCurNode; \
+ psCurNode = psTmpNode2; \
+ if(psCurNode) \
+ { \
+ psTmpNode1->ppsThis = &(psCurNode->psNext); \
+ } \
+ else \
+ { \
+ psTmpNode1->ppsThis = ppsHead; \
+ } \
+ } \
+ *ppsHead = psTmpNode1; \
+}
+
+#define IS_LAST_ELEMENT(x) ((x)->psNext == IMG_NULL)
+
+#include "services_headers.h"
+
+DECLARE_LIST_ANY_VA(BM_HEAP);
+DECLARE_LIST_ANY_2(BM_HEAP, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_ANY_VA_2(BM_HEAP, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_FOR_EACH_VA(BM_HEAP);
+DECLARE_LIST_REMOVE(BM_HEAP);
+DECLARE_LIST_INSERT(BM_HEAP);
+
+DECLARE_LIST_ANY_VA(BM_CONTEXT);
+DECLARE_LIST_ANY_VA_2(BM_CONTEXT, IMG_HANDLE, IMG_NULL);
+DECLARE_LIST_ANY_VA_2(BM_CONTEXT, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_FOR_EACH(BM_CONTEXT);
+DECLARE_LIST_REMOVE(BM_CONTEXT);
+DECLARE_LIST_INSERT(BM_CONTEXT);
+
+DECLARE_LIST_ANY_2(PVRSRV_DEVICE_NODE, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_ANY_VA(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_ANY_VA_2(PVRSRV_DEVICE_NODE, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_FOR_EACH(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_FOR_EACH_VA(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_INSERT(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_REMOVE(PVRSRV_DEVICE_NODE);
+
+DECLARE_LIST_ANY_VA(PVRSRV_POWER_DEV);
+DECLARE_LIST_ANY_VA_2(PVRSRV_POWER_DEV, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_INSERT(PVRSRV_POWER_DEV);
+DECLARE_LIST_REMOVE(PVRSRV_POWER_DEV);
+
+#undef DECLARE_LIST_ANY_2
+#undef DECLARE_LIST_ANY_VA
+#undef DECLARE_LIST_ANY_VA_2
+#undef DECLARE_LIST_FOR_EACH
+#undef DECLARE_LIST_FOR_EACH_VA
+#undef DECLARE_LIST_INSERT
+#undef DECLARE_LIST_REMOVE
+
+IMG_VOID* MatchDeviceKM_AnyVaCb(PVRSRV_DEVICE_NODE* psDeviceNode, va_list va);
+IMG_VOID* MatchPowerDeviceIndex_AnyVaCb(PVRSRV_POWER_DEV *psPowerDev, va_list va);
+
+#endif
+
diff --git a/drivers/gpu/pvr/lock.h b/drivers/gpu/pvr/lock.h
new file mode 100644
index 0000000..a0854c3
--- /dev/null
+++ b/drivers/gpu/pvr/lock.h
@@ -0,0 +1,32 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __LOCK_H__
+#define __LOCK_H__
+
+extern PVRSRV_LINUX_MUTEX gPVRSRVLock;
+
+#endif
diff --git a/drivers/gpu/pvr/mem.c b/drivers/gpu/pvr/mem.c
new file mode 100644
index 0000000..746494a
--- /dev/null
+++ b/drivers/gpu/pvr/mem.c
@@ -0,0 +1,155 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "pvr_bridge_km.h"
+
+
+static PVRSRV_ERROR
+FreeSharedSysMemCallBack(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param,
+ IMG_BOOL bDummy)
+{
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = pvParam;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+ PVR_UNREFERENCED_PARAMETER(bDummy);
+
+ OSFreePages(psKernelMemInfo->ui32Flags,
+ psKernelMemInfo->uAllocSize,
+ psKernelMemInfo->pvLinAddrKM,
+ psKernelMemInfo->sMemBlk.hOSMemHandle);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO),
+ psKernelMemInfo,
+ IMG_NULL);
+
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVAllocSharedSysMemoryKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_UINT32 ui32Flags,
+ IMG_SIZE_T uSize,
+ PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfo)
+{
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO),
+ (IMG_VOID **)&psKernelMemInfo, IMG_NULL,
+ "Kernel Memory Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVAllocSharedSysMemoryKM: Failed to alloc memory for meminfo"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ OSMemSet(psKernelMemInfo, 0, sizeof(*psKernelMemInfo));
+
+ ui32Flags &= ~PVRSRV_HAP_MAPTYPE_MASK;
+ ui32Flags |= PVRSRV_HAP_MULTI_PROCESS;
+ psKernelMemInfo->ui32Flags = ui32Flags;
+ psKernelMemInfo->uAllocSize = uSize;
+
+ if(OSAllocPages(psKernelMemInfo->ui32Flags,
+ psKernelMemInfo->uAllocSize,
+ (IMG_UINT32)HOST_PAGESIZE(),
+ IMG_NULL,
+ 0,
+ &psKernelMemInfo->pvLinAddrKM,
+ &psKernelMemInfo->sMemBlk.hOSMemHandle)
+ != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocSharedSysMemoryKM: Failed to alloc memory for block"));
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO),
+ psKernelMemInfo,
+ 0);
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+
+ psKernelMemInfo->sMemBlk.hResItem =
+ ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_SHARED_MEM_INFO,
+ psKernelMemInfo,
+ 0,
+ &FreeSharedSysMemCallBack);
+
+ *ppsKernelMemInfo = psKernelMemInfo;
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVFreeSharedSysMemoryKM(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ PVRSRV_ERROR eError;
+
+ if(psKernelMemInfo->sMemBlk.hResItem)
+ {
+ eError = ResManFreeResByPtr(psKernelMemInfo->sMemBlk.hResItem, CLEANUP_WITH_POLL);
+ }
+ else
+ {
+ eError = FreeSharedSysMemCallBack(psKernelMemInfo, 0, CLEANUP_WITH_POLL);
+ }
+
+ return eError;
+}
+
+
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVDissociateMemFromResmanKM(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if(!psKernelMemInfo)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if(psKernelMemInfo->sMemBlk.hResItem)
+ {
+ eError = ResManDissociateRes(psKernelMemInfo->sMemBlk.hResItem, IMG_NULL);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDissociateMemFromResmanKM: ResManDissociateRes failed"));
+ PVR_DBG_BREAK;
+ return eError;
+ }
+
+ psKernelMemInfo->sMemBlk.hResItem = IMG_NULL;
+ }
+
+ return eError;
+}
+
diff --git a/drivers/gpu/pvr/mem_debug.c b/drivers/gpu/pvr/mem_debug.c
new file mode 100644
index 0000000..b9cc780
--- /dev/null
+++ b/drivers/gpu/pvr/mem_debug.c
@@ -0,0 +1,247 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef MEM_DEBUG_C
+#define MEM_DEBUG_C
+
+#if defined(PVRSRV_DEBUG_OS_MEMORY)
+
+#include "img_types.h"
+#include "services_headers.h"
+
+#if defined (__cplusplus)
+extern "C"
+{
+#endif
+
+#define STOP_ON_ERROR 0
+
+
+
+
+
+
+
+ IMG_BOOL MemCheck(const IMG_PVOID pvAddr, const IMG_UINT8 ui8Pattern, IMG_SIZE_T uSize)
+ {
+ IMG_UINT8 *pui8Addr;
+ for (pui8Addr = (IMG_UINT8*)pvAddr; uSize > 0; uSize--, pui8Addr++)
+ {
+ if (*pui8Addr != ui8Pattern)
+ {
+ return IMG_FALSE;
+ }
+ }
+ return IMG_TRUE;
+ }
+
+
+
+ IMG_VOID OSCheckMemDebug(IMG_PVOID pvCpuVAddr, IMG_SIZE_T uSize, const IMG_CHAR *pszFileName, const IMG_UINT32 uLine)
+ {
+ OSMEM_DEBUG_INFO const *psInfo = (OSMEM_DEBUG_INFO *)((IMG_UINT32)pvCpuVAddr - TEST_BUFFER_PADDING_STATUS);
+
+
+ if (pvCpuVAddr == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : null pointer"
+ " - referenced %s:%d - allocated %s:%d",
+ pvCpuVAddr,
+ pszFileName, uLine,
+ psInfo->sFileName, psInfo->uLineNo));
+ while (STOP_ON_ERROR);
+ }
+
+
+ if (((IMG_UINT32)pvCpuVAddr&3) != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : invalid alignment"
+ " - referenced %s:%d - allocated %s:%d",
+ pvCpuVAddr,
+ pszFileName, uLine,
+ psInfo->sFileName, psInfo->uLineNo));
+ while (STOP_ON_ERROR);
+ }
+
+
+ if (!MemCheck((IMG_PVOID)psInfo->sGuardRegionBefore, 0xB1, sizeof(psInfo->sGuardRegionBefore)))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : guard region before overwritten"
+ " - referenced %s:%d - allocated %s:%d",
+ pvCpuVAddr,
+ pszFileName, uLine,
+ psInfo->sFileName, psInfo->uLineNo));
+ while (STOP_ON_ERROR);
+ }
+
+
+ if (uSize != psInfo->uSize)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "Pointer 0x%X : supplied size was different to stored size (0x%X != 0x%X)"
+ " - referenced %s:%d - allocated %s:%d",
+ pvCpuVAddr, uSize, psInfo->uSize,
+ pszFileName, uLine,
+ psInfo->sFileName, psInfo->uLineNo));
+ while (STOP_ON_ERROR);
+ }
+
+
+ if ((0x01234567 ^ psInfo->uSizeParityCheck) != psInfo->uSize)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "Pointer 0x%X : stored size parity error (0x%X != 0x%X)"
+ " - referenced %s:%d - allocated %s:%d",
+ pvCpuVAddr, psInfo->uSize, 0x01234567 ^ psInfo->uSizeParityCheck,
+ pszFileName, uLine,
+ psInfo->sFileName, psInfo->uLineNo));
+ while (STOP_ON_ERROR);
+ }
+ else
+ {
+
+ uSize = psInfo->uSize;
+ }
+
+
+ if (uSize)
+ {
+ if (!MemCheck((IMG_VOID*)((IMG_UINT32)pvCpuVAddr + uSize), 0xB2, TEST_BUFFER_PADDING_AFTER))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : guard region after overwritten"
+ " - referenced from %s:%d - allocated from %s:%d",
+ pvCpuVAddr,
+ pszFileName, uLine,
+ psInfo->sFileName, psInfo->uLineNo));
+ }
+ }
+
+
+ if (psInfo->eValid != isAllocated)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : not allocated (freed? %d)"
+ " - referenced %s:%d - freed %s:%d",
+ pvCpuVAddr, psInfo->eValid == isFree,
+ pszFileName, uLine,
+ psInfo->sFileName, psInfo->uLineNo));
+ while (STOP_ON_ERROR);
+ }
+ }
+
+ IMG_VOID debug_strcpy(IMG_CHAR *pDest, const IMG_CHAR *pSrc)
+ {
+ IMG_SIZE_T i = 0;
+
+ for (; i < 128; i++)
+ {
+ *pDest = *pSrc;
+ if (*pSrc == '\0') break;
+ pDest++;
+ pSrc++;
+ }
+ }
+
+ PVRSRV_ERROR OSAllocMem_Debug_Wrapper(IMG_UINT32 ui32Flags,
+ IMG_UINT32 ui32Size,
+ IMG_PVOID *ppvCpuVAddr,
+ IMG_HANDLE *phBlockAlloc,
+ IMG_CHAR *pszFilename,
+ IMG_UINT32 ui32Line)
+ {
+ OSMEM_DEBUG_INFO *psInfo;
+
+ PVRSRV_ERROR eError;
+
+ eError = OSAllocMem_Debug_Linux_Memory_Allocations(ui32Flags,
+ ui32Size + TEST_BUFFER_PADDING,
+ ppvCpuVAddr,
+ phBlockAlloc,
+ pszFilename,
+ ui32Line);
+
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ OSMemSet((IMG_CHAR *)(*ppvCpuVAddr) + TEST_BUFFER_PADDING_STATUS, 0xBB, ui32Size);
+ OSMemSet((IMG_CHAR *)(*ppvCpuVAddr) + ui32Size + TEST_BUFFER_PADDING_STATUS, 0xB2, TEST_BUFFER_PADDING_AFTER);
+
+
+ psInfo = (OSMEM_DEBUG_INFO *)(*ppvCpuVAddr);
+
+ OSMemSet(psInfo->sGuardRegionBefore, 0xB1, sizeof(psInfo->sGuardRegionBefore));
+ debug_strcpy(psInfo->sFileName, pszFilename);
+ psInfo->uLineNo = ui32Line;
+ psInfo->eValid = isAllocated;
+ psInfo->uSize = ui32Size;
+ psInfo->uSizeParityCheck = 0x01234567 ^ ui32Size;
+
+
+ *ppvCpuVAddr = (IMG_PVOID) ((IMG_UINT32)*ppvCpuVAddr)+TEST_BUFFER_PADDING_STATUS;
+
+#ifdef PVRSRV_LOG_MEMORY_ALLOCS
+
+ PVR_TRACE(("Allocated pointer (after debug info): 0x%X from %s:%d", *ppvCpuVAddr, pszFilename, ui32Line));
+#endif
+
+ return PVRSRV_OK;
+ }
+
+ PVRSRV_ERROR OSFreeMem_Debug_Wrapper(IMG_UINT32 ui32Flags,
+ IMG_UINT32 ui32Size,
+ IMG_PVOID pvCpuVAddr,
+ IMG_HANDLE hBlockAlloc,
+ IMG_CHAR *pszFilename,
+ IMG_UINT32 ui32Line)
+ {
+ OSMEM_DEBUG_INFO *psInfo;
+
+
+ OSCheckMemDebug(pvCpuVAddr, ui32Size, pszFilename, ui32Line);
+
+
+ OSMemSet(pvCpuVAddr, 0xBF, ui32Size + TEST_BUFFER_PADDING_AFTER);
+
+
+ psInfo = (OSMEM_DEBUG_INFO *)((IMG_UINT32) pvCpuVAddr - TEST_BUFFER_PADDING_STATUS);
+
+
+ psInfo->uSize = 0;
+ psInfo->uSizeParityCheck = 0;
+ psInfo->eValid = isFree;
+ psInfo->uLineNo = ui32Line;
+ debug_strcpy(psInfo->sFileName, pszFilename);
+
+ return OSFreeMem_Debug_Linux_Memory_Allocations(ui32Flags, ui32Size + TEST_BUFFER_PADDING, psInfo, hBlockAlloc, pszFilename, ui32Line);
+ }
+
+#if defined (__cplusplus)
+
+}
+#endif
+
+#endif
+
+#endif
diff --git a/drivers/gpu/pvr/metrics.c b/drivers/gpu/pvr/metrics.c
new file mode 100644
index 0000000..640eb04
--- /dev/null
+++ b/drivers/gpu/pvr/metrics.c
@@ -0,0 +1,160 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "metrics.h"
+
+#if defined(SUPPORT_VGX)
+#include "vgxapi_km.h"
+#endif
+
+#if defined(SUPPORT_SGX)
+#include "sgxapi_km.h"
+#endif
+
+#if defined(DEBUG) || defined(TIMING)
+
+static volatile IMG_UINT32 *pui32TimerRegister = 0;
+
+#define PVRSRV_TIMER_TOTAL_IN_TICKS(X) asTimers[X].ui32Total
+#define PVRSRV_TIMER_TOTAL_IN_MS(X) ((1000*asTimers[X].ui32Total)/ui32TicksPerMS)
+#define PVRSRV_TIMER_COUNT(X) asTimers[X].ui32Count
+
+
+Temporal_Data asTimers[PVRSRV_NUM_TIMERS];
+
+
+IMG_UINT32 PVRSRVTimeNow(IMG_VOID)
+{
+ if (!pui32TimerRegister)
+ {
+ static IMG_BOOL bFirstTime = IMG_TRUE;
+
+ if (bFirstTime)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVTimeNow: No timer register set up"));
+
+ bFirstTime = IMG_FALSE;
+ }
+
+ return 0;
+ }
+
+#if defined(__sh__)
+
+ return (0xffffffff-*pui32TimerRegister);
+
+#else
+
+ return 0;
+
+#endif
+}
+
+
+static IMG_UINT32 PVRSRVGetCPUFreq(IMG_VOID)
+{
+ IMG_UINT32 ui32Time1, ui32Time2;
+
+ ui32Time1 = PVRSRVTimeNow();
+
+ OSWaitus(1000000);
+
+ ui32Time2 = PVRSRVTimeNow();
+
+ PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetCPUFreq: timer frequency = %d Hz", ui32Time2 - ui32Time1));
+
+ return (ui32Time2 - ui32Time1);
+}
+
+
+IMG_VOID PVRSRVSetupMetricTimers(IMG_VOID *pvDevInfo)
+{
+ IMG_UINT32 ui32Loop;
+
+ PVR_UNREFERENCED_PARAMETER(pvDevInfo);
+
+ for(ui32Loop=0; ui32Loop < (PVRSRV_NUM_TIMERS); ui32Loop++)
+ {
+ asTimers[ui32Loop].ui32Total = 0;
+ asTimers[ui32Loop].ui32Count = 0;
+ }
+
+
+ #if defined(__sh__)
+
+
+
+
+
+ *TCR_2 = TIMER_DIVISOR;
+
+
+ *TCOR_2 = *TCNT_2 = (IMG_UINT)0xffffffff;
+
+
+ *TST_REG |= (IMG_UINT8)0x04;
+
+ pui32TimerRegister = (IMG_UINT32 *)TCNT_2;
+
+ #else
+
+ pui32TimerRegister = 0;
+
+ #endif
+
+}
+
+
+IMG_VOID PVRSRVOutputMetricTotals(IMG_VOID)
+{
+ IMG_UINT32 ui32TicksPerMS, ui32Loop;
+
+ ui32TicksPerMS = PVRSRVGetCPUFreq();
+
+ if (!ui32TicksPerMS)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOutputMetricTotals: Failed to get CPU Freq"));
+ return;
+ }
+
+ for(ui32Loop=0; ui32Loop < (PVRSRV_NUM_TIMERS); ui32Loop++)
+ {
+ if (asTimers[ui32Loop].ui32Count & 0x80000000L)
+ {
+ PVR_DPF((PVR_DBG_WARNING,"PVRSRVOutputMetricTotals: Timer %u is still ON", ui32Loop));
+ }
+ }
+#if 0
+
+ PVR_DPF((PVR_DBG_ERROR," Timer(%u): Total = %u",PVRSRV_TIMER_EXAMPLE_1, PVRSRV_TIMER_TOTAL_IN_TICKS(PVRSRV_TIMER_EXAMPLE_1)));
+ PVR_DPF((PVR_DBG_ERROR," Timer(%u): Time = %ums",PVRSRV_TIMER_EXAMPLE_1, PVRSRV_TIMER_TOTAL_IN_MS(PVRSRV_TIMER_EXAMPLE_1)));
+ PVR_DPF((PVR_DBG_ERROR," Timer(%u): Count = %u",PVRSRV_TIMER_EXAMPLE_1, PVRSRV_TIMER_COUNT(PVRSRV_TIMER_EXAMPLE_1)));
+#endif
+}
+
+#endif
+
diff --git a/drivers/gpu/pvr/metrics.h b/drivers/gpu/pvr/metrics.h
new file mode 100644
index 0000000..69e1b3d
--- /dev/null
+++ b/drivers/gpu/pvr/metrics.h
@@ -0,0 +1,130 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef _METRICS_
+#define _METRICS_
+
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+
+#if defined(DEBUG) || defined(TIMING)
+
+
+typedef struct
+{
+ IMG_UINT32 ui32Start;
+ IMG_UINT32 ui32Stop;
+ IMG_UINT32 ui32Total;
+ IMG_UINT32 ui32Count;
+} Temporal_Data;
+
+extern Temporal_Data asTimers[];
+
+extern IMG_UINT32 PVRSRVTimeNow(IMG_VOID);
+extern IMG_VOID PVRSRVSetupMetricTimers(IMG_VOID *pvDevInfo);
+extern IMG_VOID PVRSRVOutputMetricTotals(IMG_VOID);
+
+
+#define PVRSRV_TIMER_DUMMY 0
+
+#define PVRSRV_TIMER_EXAMPLE_1 1
+#define PVRSRV_TIMER_EXAMPLE_2 2
+
+
+#define PVRSRV_NUM_TIMERS (PVRSRV_TIMER_EXAMPLE_2 + 1)
+
+#define PVRSRV_TIME_START(X) { \
+ asTimers[X].ui32Count += 1; \
+ asTimers[X].ui32Count |= 0x80000000L; \
+ asTimers[X].ui32Start = PVRSRVTimeNow(); \
+ asTimers[X].ui32Stop = 0; \
+ }
+
+#define PVRSRV_TIME_SUSPEND(X) { \
+ asTimers[X].ui32Stop += PVRSRVTimeNow() - asTimers[X].ui32Start; \
+ }
+
+#define PVRSRV_TIME_RESUME(X) { \
+ asTimers[X].ui32Start = PVRSRVTimeNow(); \
+ }
+
+#define PVRSRV_TIME_STOP(X) { \
+ asTimers[X].ui32Stop += PVRSRVTimeNow() - asTimers[X].ui32Start; \
+ asTimers[X].ui32Total += asTimers[X].ui32Stop; \
+ asTimers[X].ui32Count &= 0x7FFFFFFFL; \
+ }
+
+#define PVRSRV_TIME_RESET(X) { \
+ asTimers[X].ui32Start = 0; \
+ asTimers[X].ui32Stop = 0; \
+ asTimers[X].ui32Total = 0; \
+ asTimers[X].ui32Count = 0; \
+ }
+
+
+#if defined(__sh__)
+
+#define TST_REG ((volatile IMG_UINT8 *) (psDevInfo->pvSOCRegsBaseKM))
+
+#define TCOR_2 ((volatile IMG_UINT *) (psDevInfo->pvSOCRegsBaseKM+28))
+#define TCNT_2 ((volatile IMG_UINT *) (psDevInfo->pvSOCRegsBaseKM+32))
+#define TCR_2 ((volatile IMG_UINT16 *)(psDevInfo->pvSOCRegsBaseKM+36))
+
+#define TIMER_DIVISOR 4
+
+#endif
+
+
+
+
+
+#else
+
+
+
+#define PVRSRV_TIME_START(X)
+#define PVRSRV_TIME_SUSPEND(X)
+#define PVRSRV_TIME_RESUME(X)
+#define PVRSRV_TIME_STOP(X)
+#define PVRSRV_TIME_RESET(X)
+
+#define PVRSRVSetupMetricTimers(X)
+#define PVRSRVOutputMetricTotals()
+
+
+
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+
+
+#endif
+
diff --git a/drivers/gpu/pvr/mm.c b/drivers/gpu/pvr/mm.c
new file mode 100644
index 0000000..80f0efe
--- /dev/null
+++ b/drivers/gpu/pvr/mm.c
@@ -0,0 +1,2717 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+
+
+
+
+
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#endif
+
+#if !defined(PVR_LINUX_MEM_AREA_POOL_MAX_PAGES)
+#define PVR_LINUX_MEM_AREA_POOL_MAX_PAGES 0
+#endif
+
+#include <linux/kernel.h>
+#include <asm/atomic.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+#include <linux/wrapper.h>
+#endif
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/sched.h>
+
+#if defined(PVR_LINUX_MEM_AREA_POOL_ALLOW_SHRINK)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0))
+#include <linux/shrinker.h>
+#endif
+#endif
+
+#include "img_defs.h"
+#include "services.h"
+#include "servicesint.h"
+#include "syscommon.h"
+#include "mutils.h"
+#include "mm.h"
+#include "pvrmmap.h"
+#include "mmap.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+#include "proc.h"
+#include "mutex.h"
+#include "lock.h"
+
+#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ #include "lists.h"
+#endif
+
+static atomic_t g_sPagePoolEntryCount = ATOMIC_INIT(0);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+typedef enum {
+ DEBUG_MEM_ALLOC_TYPE_KMALLOC,
+ DEBUG_MEM_ALLOC_TYPE_VMALLOC,
+ DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES,
+ DEBUG_MEM_ALLOC_TYPE_IOREMAP,
+ DEBUG_MEM_ALLOC_TYPE_IO,
+ DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE,
+ DEBUG_MEM_ALLOC_TYPE_ION,
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ DEBUG_MEM_ALLOC_TYPE_VMAP,
+#endif
+ DEBUG_MEM_ALLOC_TYPE_COUNT
+} DEBUG_MEM_ALLOC_TYPE;
+
+typedef struct _DEBUG_MEM_ALLOC_REC
+{
+ DEBUG_MEM_ALLOC_TYPE eAllocType;
+ IMG_VOID *pvKey;
+ IMG_VOID *pvCpuVAddr;
+ IMG_UINT32 ulCpuPAddr;
+ IMG_VOID *pvPrivateData;
+ IMG_UINT32 ui32Bytes;
+ pid_t pid;
+ IMG_CHAR *pszFileName;
+ IMG_UINT32 ui32Line;
+
+ struct _DEBUG_MEM_ALLOC_REC *psNext;
+ struct _DEBUG_MEM_ALLOC_REC **ppsThis;
+} DEBUG_MEM_ALLOC_REC;
+
+static IMPLEMENT_LIST_ANY_VA_2(DEBUG_MEM_ALLOC_REC, IMG_BOOL, IMG_FALSE)
+static IMPLEMENT_LIST_ANY_VA(DEBUG_MEM_ALLOC_REC)
+static IMPLEMENT_LIST_FOR_EACH(DEBUG_MEM_ALLOC_REC)
+static IMPLEMENT_LIST_INSERT(DEBUG_MEM_ALLOC_REC)
+static IMPLEMENT_LIST_REMOVE(DEBUG_MEM_ALLOC_REC)
+
+
+static DEBUG_MEM_ALLOC_REC *g_MemoryRecords;
+
+static IMG_UINT32 g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_COUNT];
+static IMG_UINT32 g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_COUNT];
+
+static IMG_UINT32 g_SysRAMWaterMark;
+static IMG_UINT32 g_SysRAMHighWaterMark;
+
+static inline IMG_UINT32
+SysRAMTrueWaterMark(void)
+{
+ return g_SysRAMWaterMark + PAGES_TO_BYTES(atomic_read(&g_sPagePoolEntryCount));
+}
+
+static IMG_UINT32 g_IOMemWaterMark;
+static IMG_UINT32 g_IOMemHighWaterMark;
+
+static IMG_VOID DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE eAllocType,
+ IMG_VOID *pvKey,
+ IMG_VOID *pvCpuVAddr,
+ IMG_UINT32 ulCpuPAddr,
+ IMG_VOID *pvPrivateData,
+ IMG_UINT32 ui32Bytes,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32Line);
+
+static IMG_VOID DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE eAllocType, IMG_VOID *pvKey, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+
+static IMG_CHAR *DebugMemAllocRecordTypeToString(DEBUG_MEM_ALLOC_TYPE eAllocType);
+
+
+static struct proc_dir_entry *g_SeqFileMemoryRecords;
+static void* ProcSeqNextMemoryRecords(struct seq_file *sfile,void* el,loff_t off);
+static void ProcSeqShowMemoryRecords(struct seq_file *sfile,void* el);
+static void* ProcSeqOff2ElementMemoryRecords(struct seq_file * sfile, loff_t off);
+
+#endif
+
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+typedef struct _DEBUG_LINUX_MEM_AREA_REC
+{
+ LinuxMemArea *psLinuxMemArea;
+ IMG_UINT32 ui32Flags;
+ pid_t pid;
+
+ struct _DEBUG_LINUX_MEM_AREA_REC *psNext;
+ struct _DEBUG_LINUX_MEM_AREA_REC **ppsThis;
+}DEBUG_LINUX_MEM_AREA_REC;
+
+
+static IMPLEMENT_LIST_ANY_VA(DEBUG_LINUX_MEM_AREA_REC)
+static IMPLEMENT_LIST_FOR_EACH(DEBUG_LINUX_MEM_AREA_REC)
+static IMPLEMENT_LIST_INSERT(DEBUG_LINUX_MEM_AREA_REC)
+static IMPLEMENT_LIST_REMOVE(DEBUG_LINUX_MEM_AREA_REC)
+
+
+
+
+static DEBUG_LINUX_MEM_AREA_REC *g_LinuxMemAreaRecords;
+static IMG_UINT32 g_LinuxMemAreaCount;
+static IMG_UINT32 g_LinuxMemAreaWaterMark;
+static IMG_UINT32 g_LinuxMemAreaHighWaterMark;
+
+
+static struct proc_dir_entry *g_SeqFileMemArea;
+
+static void* ProcSeqNextMemArea(struct seq_file *sfile,void* el,loff_t off);
+static void ProcSeqShowMemArea(struct seq_file *sfile,void* el);
+static void* ProcSeqOff2ElementMemArea(struct seq_file *sfile, loff_t off);
+
+#endif
+
+#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+static PVRSRV_LINUX_MUTEX g_sDebugMutex;
+#endif
+
+#if (defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS))
+static void ProcSeqStartstopDebugMutex(struct seq_file *sfile,IMG_BOOL start);
+#endif
+
+typedef struct
+{
+
+ struct list_head sPagePoolItem;
+
+ struct page *psPage;
+} LinuxPagePoolEntry;
+
+static LinuxKMemCache *g_PsLinuxMemAreaCache;
+static LinuxKMemCache *g_PsLinuxPagePoolCache;
+
+static LIST_HEAD(g_sPagePoolList);
+static int g_iPagePoolMaxEntries;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+static IMG_VOID ReservePages(IMG_VOID *pvAddress, IMG_UINT32 ui32Length);
+static IMG_VOID UnreservePages(IMG_VOID *pvAddress, IMG_UINT32 ui32Length);
+#endif
+
+static LinuxMemArea *LinuxMemAreaStructAlloc(IMG_VOID);
+static IMG_VOID LinuxMemAreaStructFree(LinuxMemArea *psLinuxMemArea);
+#if defined(DEBUG_LINUX_MEM_AREAS)
+static IMG_VOID DebugLinuxMemAreaRecordAdd(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32Flags);
+static DEBUG_LINUX_MEM_AREA_REC *DebugLinuxMemAreaRecordFind(LinuxMemArea *psLinuxMemArea);
+static IMG_VOID DebugLinuxMemAreaRecordRemove(LinuxMemArea *psLinuxMemArea);
+#endif
+
+
+static inline IMG_BOOL
+AreaIsUncached(IMG_UINT32 ui32AreaFlags)
+{
+ return (ui32AreaFlags & (PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_UNCACHED)) != 0;
+}
+
+static inline IMG_BOOL
+CanFreeToPool(LinuxMemArea *psLinuxMemArea)
+{
+ return AreaIsUncached(psLinuxMemArea->ui32AreaFlags) && !psLinuxMemArea->bNeedsCacheInvalidate;
+}
+
+IMG_VOID *
+_KMallocWrapper(IMG_UINT32 ui32ByteSize, gfp_t uFlags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+ IMG_VOID *pvRet;
+ pvRet = kmalloc(ui32ByteSize, uFlags);
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ if (pvRet)
+ {
+ DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_KMALLOC,
+ pvRet,
+ pvRet,
+ 0,
+ NULL,
+ ui32ByteSize,
+ pszFileName,
+ ui32Line
+ );
+ }
+#else
+ PVR_UNREFERENCED_PARAMETER(pszFileName);
+ PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+ return pvRet;
+}
+
+
+IMG_VOID
+_KFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_KMALLOC, pvCpuVAddr, pszFileName, ui32Line);
+#else
+ PVR_UNREFERENCED_PARAMETER(pszFileName);
+ PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+ kfree(pvCpuVAddr);
+}
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+static IMG_VOID
+DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE eAllocType,
+ IMG_VOID *pvKey,
+ IMG_VOID *pvCpuVAddr,
+ IMG_UINT32 ulCpuPAddr,
+ IMG_VOID *pvPrivateData,
+ IMG_UINT32 ui32Bytes,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32Line)
+{
+ DEBUG_MEM_ALLOC_REC *psRecord;
+
+ LinuxLockMutex(&g_sDebugMutex);
+
+ psRecord = kmalloc(sizeof(DEBUG_MEM_ALLOC_REC), GFP_KERNEL);
+
+ psRecord->eAllocType = eAllocType;
+ psRecord->pvKey = pvKey;
+ psRecord->pvCpuVAddr = pvCpuVAddr;
+ psRecord->ulCpuPAddr = ulCpuPAddr;
+ psRecord->pvPrivateData = pvPrivateData;
+ psRecord->pid = OSGetCurrentProcessIDKM();
+ psRecord->ui32Bytes = ui32Bytes;
+ psRecord->pszFileName = pszFileName;
+ psRecord->ui32Line = ui32Line;
+
+ List_DEBUG_MEM_ALLOC_REC_Insert(&g_MemoryRecords, psRecord);
+
+ g_WaterMarkData[eAllocType] += ui32Bytes;
+ if (g_WaterMarkData[eAllocType] > g_HighWaterMarkData[eAllocType])
+ {
+ g_HighWaterMarkData[eAllocType] = g_WaterMarkData[eAllocType];
+ }
+
+ if (eAllocType == DEBUG_MEM_ALLOC_TYPE_KMALLOC
+ || eAllocType == DEBUG_MEM_ALLOC_TYPE_VMALLOC
+ || eAllocType == DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES
+ || eAllocType == DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE)
+ {
+ IMG_UINT32 ui32SysRAMTrueWaterMark;
+
+ g_SysRAMWaterMark += ui32Bytes;
+ ui32SysRAMTrueWaterMark = SysRAMTrueWaterMark();
+
+ if (ui32SysRAMTrueWaterMark > g_SysRAMHighWaterMark)
+ {
+ g_SysRAMHighWaterMark = ui32SysRAMTrueWaterMark;
+ }
+ }
+ else if (eAllocType == DEBUG_MEM_ALLOC_TYPE_IOREMAP
+ || eAllocType == DEBUG_MEM_ALLOC_TYPE_IO)
+ {
+ g_IOMemWaterMark += ui32Bytes;
+ if (g_IOMemWaterMark > g_IOMemHighWaterMark)
+ {
+ g_IOMemHighWaterMark = g_IOMemWaterMark;
+ }
+ }
+
+ LinuxUnLockMutex(&g_sDebugMutex);
+}
+
+
+static IMG_BOOL DebugMemAllocRecordRemove_AnyVaCb(DEBUG_MEM_ALLOC_REC *psCurrentRecord, va_list va)
+{
+ DEBUG_MEM_ALLOC_TYPE eAllocType;
+ IMG_VOID *pvKey;
+
+ eAllocType = va_arg(va, DEBUG_MEM_ALLOC_TYPE);
+ pvKey = va_arg(va, IMG_VOID*);
+
+ if (psCurrentRecord->eAllocType == eAllocType
+ && psCurrentRecord->pvKey == pvKey)
+ {
+ eAllocType = psCurrentRecord->eAllocType;
+ g_WaterMarkData[eAllocType] -= psCurrentRecord->ui32Bytes;
+
+ if (eAllocType == DEBUG_MEM_ALLOC_TYPE_KMALLOC
+ || eAllocType == DEBUG_MEM_ALLOC_TYPE_VMALLOC
+ || eAllocType == DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES
+ || eAllocType == DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE)
+ {
+ g_SysRAMWaterMark -= psCurrentRecord->ui32Bytes;
+ }
+ else if (eAllocType == DEBUG_MEM_ALLOC_TYPE_IOREMAP
+ || eAllocType == DEBUG_MEM_ALLOC_TYPE_IO)
+ {
+ g_IOMemWaterMark -= psCurrentRecord->ui32Bytes;
+ }
+
+ List_DEBUG_MEM_ALLOC_REC_Remove(psCurrentRecord);
+ kfree(psCurrentRecord);
+
+ return IMG_TRUE;
+ }
+ else
+ {
+ return IMG_FALSE;
+ }
+}
+
+
+static IMG_VOID
+DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE eAllocType, IMG_VOID *pvKey, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+ LinuxLockMutex(&g_sDebugMutex);
+
+
+ if (!List_DEBUG_MEM_ALLOC_REC_IMG_BOOL_Any_va(g_MemoryRecords,
+ DebugMemAllocRecordRemove_AnyVaCb,
+ eAllocType,
+ pvKey))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: couldn't find an entry for type=%s with pvKey=%p (called from %s, line %d\n",
+ __FUNCTION__, DebugMemAllocRecordTypeToString(eAllocType), pvKey,
+ pszFileName, ui32Line));
+ }
+
+ LinuxUnLockMutex(&g_sDebugMutex);
+}
+
+
+static IMG_CHAR *
+DebugMemAllocRecordTypeToString(DEBUG_MEM_ALLOC_TYPE eAllocType)
+{
+ IMG_CHAR *apszDebugMemoryRecordTypes[] = {
+ "KMALLOC",
+ "VMALLOC",
+ "ALLOC_PAGES",
+ "IOREMAP",
+ "IO",
+ "KMEM_CACHE_ALLOC",
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ "VMAP"
+#endif
+ };
+ return apszDebugMemoryRecordTypes[eAllocType];
+}
+#endif
+
+
+static IMG_BOOL
+AllocFlagsToPGProt(pgprot_t *pPGProtFlags, IMG_UINT32 ui32AllocFlags)
+{
+ pgprot_t PGProtFlags;
+
+ switch (ui32AllocFlags & PVRSRV_HAP_CACHETYPE_MASK)
+ {
+ case PVRSRV_HAP_CACHED:
+ PGProtFlags = PAGE_KERNEL;
+ break;
+ case PVRSRV_HAP_WRITECOMBINE:
+ PGProtFlags = PGPROT_WC(PAGE_KERNEL);
+ break;
+ case PVRSRV_HAP_UNCACHED:
+ PGProtFlags = PGPROT_UC(PAGE_KERNEL);
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: Unknown mapping flags=0x%08x",
+ __FUNCTION__, ui32AllocFlags));
+ dump_stack();
+ return IMG_FALSE;
+ }
+
+ *pPGProtFlags = PGProtFlags;
+
+ return IMG_TRUE;
+}
+
+IMG_VOID *
+_VMallocWrapper(IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32AllocFlags,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32Line)
+{
+ pgprot_t PGProtFlags;
+ IMG_VOID *pvRet;
+
+ if (!AllocFlagsToPGProt(&PGProtFlags, ui32AllocFlags))
+ {
+ return NULL;
+ }
+
+
+ pvRet = __vmalloc(ui32Bytes, GFP_KERNEL | __GFP_HIGHMEM, PGProtFlags);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ if (pvRet)
+ {
+ DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_VMALLOC,
+ pvRet,
+ pvRet,
+ 0,
+ NULL,
+ PAGE_ALIGN(ui32Bytes),
+ pszFileName,
+ ui32Line
+ );
+ }
+#else
+ PVR_UNREFERENCED_PARAMETER(pszFileName);
+ PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+
+ return pvRet;
+}
+
+
+IMG_VOID
+_VFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_VMALLOC, pvCpuVAddr, pszFileName, ui32Line);
+#else
+ PVR_UNREFERENCED_PARAMETER(pszFileName);
+ PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+ vfree(pvCpuVAddr);
+}
+
+
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+static IMG_VOID *
+_VMapWrapper(struct page **ppsPageList, IMG_UINT32 ui32NumPages, IMG_UINT32 ui32AllocFlags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+ pgprot_t PGProtFlags;
+ IMG_VOID *pvRet;
+
+ if (!AllocFlagsToPGProt(&PGProtFlags, ui32AllocFlags))
+ {
+ return NULL;
+ }
+
+ pvRet = vmap(ppsPageList, ui32NumPages, GFP_KERNEL | __GFP_HIGHMEM, PGProtFlags);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ if (pvRet)
+ {
+ DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_VMAP,
+ pvRet,
+ pvRet,
+ 0,
+ NULL,
+ PAGES_TO_BYTES(ui32NumPages),
+ pszFileName,
+ ui32Line
+ );
+ }
+#else
+ PVR_UNREFERENCED_PARAMETER(pszFileName);
+ PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+
+ return pvRet;
+}
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define VMapWrapper(ppsPageList, ui32Bytes, ui32AllocFlags) _VMapWrapper(ppsPageList, ui32Bytes, ui32AllocFlags, __FILE__, __LINE__)
+#else
+#define VMapWrapper(ppsPageList, ui32Bytes, ui32AllocFlags) _VMapWrapper(ppsPageList, ui32Bytes, ui32AllocFlags, NULL, 0)
+#endif
+
+
+static IMG_VOID
+_VUnmapWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_VMAP, pvCpuVAddr, pszFileName, ui32Line);
+#else
+ PVR_UNREFERENCED_PARAMETER(pszFileName);
+ PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+ vunmap(pvCpuVAddr);
+}
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define VUnmapWrapper(pvCpuVAddr) _VUnmapWrapper(pvCpuVAddr, __FILE__, __LINE__)
+#else
+#define VUnmapWrapper(pvCpuVAddr) _VUnmapWrapper(pvCpuVAddr, NULL, 0)
+#endif
+
+#endif
+
+
+IMG_VOID
+_KMemCacheFreeWrapper(LinuxKMemCache *psCache, IMG_VOID *pvObject, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE, pvObject, pszFileName, ui32Line);
+#else
+ PVR_UNREFERENCED_PARAMETER(pszFileName);
+ PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+
+ kmem_cache_free(psCache, pvObject);
+}
+
+
+const IMG_CHAR *
+KMemCacheNameWrapper(LinuxKMemCache *psCache)
+{
+ PVR_UNREFERENCED_PARAMETER(psCache);
+
+
+ return "";
+}
+
+
+static LinuxPagePoolEntry *
+LinuxPagePoolEntryAlloc(IMG_VOID)
+{
+ return KMemCacheAllocWrapper(g_PsLinuxPagePoolCache, GFP_KERNEL);
+}
+
+static IMG_VOID
+LinuxPagePoolEntryFree(LinuxPagePoolEntry *psPagePoolEntry)
+{
+ KMemCacheFreeWrapper(g_PsLinuxPagePoolCache, psPagePoolEntry);
+}
+
+
+static struct page *
+AllocPageFromLinux(void)
+{
+ struct page *psPage;
+
+ psPage = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, 0);
+ if (!psPage)
+ {
+ return NULL;
+
+ }
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
+ SetPageReserved(psPage);
+#else
+ mem_map_reserve(psPage);
+#endif
+#endif
+ return psPage;
+}
+
+
+static IMG_VOID
+FreePageToLinux(struct page *psPage)
+{
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
+ ClearPageReserved(psPage);
+#else
+ mem_map_reserve(psPage);
+#endif
+#endif
+ __free_pages(psPage, 0);
+}
+
+
+#if (PVR_LINUX_MEM_AREA_POOL_MAX_PAGES != 0)
+static DEFINE_MUTEX(g_sPagePoolMutex);
+
+static inline void
+PagePoolLock(void)
+{
+ mutex_lock(&g_sPagePoolMutex);
+}
+
+static inline void
+PagePoolUnlock(void)
+{
+ mutex_unlock(&g_sPagePoolMutex);
+}
+
+static inline int
+PagePoolTrylock(void)
+{
+ return mutex_trylock(&g_sPagePoolMutex);
+}
+
+#else
+static inline void
+PagePoolLock(void)
+{
+}
+
+static inline void
+PagePoolUnlock(void)
+{
+}
+
+static inline int
+PagePoolTrylock(void)
+{
+ return 1;
+}
+#endif
+
+
+static inline void
+AddEntryToPool(LinuxPagePoolEntry *psPagePoolEntry)
+{
+ list_add_tail(&psPagePoolEntry->sPagePoolItem, &g_sPagePoolList);
+ atomic_inc(&g_sPagePoolEntryCount);
+}
+
+static inline void
+RemoveEntryFromPool(LinuxPagePoolEntry *psPagePoolEntry)
+{
+ list_del(&psPagePoolEntry->sPagePoolItem);
+ atomic_dec(&g_sPagePoolEntryCount);
+}
+
+static inline LinuxPagePoolEntry *
+RemoveFirstEntryFromPool(void)
+{
+ LinuxPagePoolEntry *psPagePoolEntry;
+
+ if (list_empty(&g_sPagePoolList))
+ {
+ PVR_ASSERT(atomic_read(&g_sPagePoolEntryCount) == 0);
+
+ return NULL;
+ }
+
+ PVR_ASSERT(atomic_read(&g_sPagePoolEntryCount) > 0);
+
+ psPagePoolEntry = list_first_entry(&g_sPagePoolList, LinuxPagePoolEntry, sPagePoolItem);
+
+ RemoveEntryFromPool(psPagePoolEntry);
+
+ return psPagePoolEntry;
+}
+
+static struct page *
+AllocPage(IMG_UINT32 ui32AreaFlags, IMG_BOOL *pbFromPagePool)
+{
+ struct page *psPage = NULL;
+
+
+ if (AreaIsUncached(ui32AreaFlags) && atomic_read(&g_sPagePoolEntryCount) != 0)
+ {
+ LinuxPagePoolEntry *psPagePoolEntry;
+
+ PagePoolLock();
+ psPagePoolEntry = RemoveFirstEntryFromPool();
+ PagePoolUnlock();
+
+
+ if (psPagePoolEntry)
+ {
+ psPage = psPagePoolEntry->psPage;
+ LinuxPagePoolEntryFree(psPagePoolEntry);
+ *pbFromPagePool = IMG_TRUE;
+ }
+ }
+
+ if (!psPage)
+ {
+ psPage = AllocPageFromLinux();
+ if (psPage)
+ {
+ *pbFromPagePool = IMG_FALSE;
+ }
+ }
+
+ return psPage;
+
+}
+
+static IMG_VOID
+FreePage(IMG_BOOL bToPagePool, struct page *psPage)
+{
+
+ if (bToPagePool && atomic_read(&g_sPagePoolEntryCount) < g_iPagePoolMaxEntries)
+ {
+ LinuxPagePoolEntry *psPagePoolEntry = LinuxPagePoolEntryAlloc();
+ if (psPagePoolEntry)
+ {
+ psPagePoolEntry->psPage = psPage;
+
+ PagePoolLock();
+ AddEntryToPool(psPagePoolEntry);
+ PagePoolUnlock();
+
+ return;
+ }
+ }
+
+ FreePageToLinux(psPage);
+}
+
+static IMG_VOID
+FreePagePool(IMG_VOID)
+{
+ LinuxPagePoolEntry *psPagePoolEntry, *psTempPoolEntry;
+
+ PagePoolLock();
+
+#if (PVR_LINUX_MEM_AREA_POOL_MAX_PAGES != 0)
+ PVR_TRACE(("%s: Freeing %d pages from pool", __FUNCTION__, atomic_read(&g_sPagePoolEntryCount)));
+#else
+ PVR_ASSERT(atomic_read(&g_sPagePoolEntryCount) == 0);
+ PVR_ASSERT(list_empty(&g_sPagePoolList));
+#endif
+
+ list_for_each_entry_safe(psPagePoolEntry, psTempPoolEntry, &g_sPagePoolList, sPagePoolItem)
+ {
+ RemoveEntryFromPool(psPagePoolEntry);
+
+ FreePageToLinux(psPagePoolEntry->psPage);
+ LinuxPagePoolEntryFree(psPagePoolEntry);
+ }
+
+ PVR_ASSERT(atomic_read(&g_sPagePoolEntryCount) == 0);
+
+ PagePoolUnlock();
+}
+
+#if defined(PVR_LINUX_MEM_AREA_POOL_ALLOW_SHRINK)
+#if defined(PVRSRV_NEED_PVR_ASSERT)
+static struct shrinker g_sShrinker;
+#endif
+
+static int
+ShrinkPagePool(struct shrinker *psShrinker, struct shrink_control *psShrinkControl)
+{
+ unsigned long uNumToScan = psShrinkControl->nr_to_scan;
+
+ PVR_ASSERT(psShrinker == &g_sShrinker);
+ (void)psShrinker;
+
+ if (uNumToScan != 0)
+ {
+ LinuxPagePoolEntry *psPagePoolEntry, *psTempPoolEntry;
+
+ PVR_TRACE(("%s: Number to scan: %ld", __FUNCTION__, uNumToScan));
+ PVR_TRACE(("%s: Pages in pool before scan: %d", __FUNCTION__, atomic_read(&g_sPagePoolEntryCount)));
+
+ if (!PagePoolTrylock())
+ {
+ PVR_TRACE(("%s: Couldn't get page pool lock", __FUNCTION__));
+ return -1;
+ }
+
+ list_for_each_entry_safe(psPagePoolEntry, psTempPoolEntry, &g_sPagePoolList, sPagePoolItem)
+ {
+ RemoveEntryFromPool(psPagePoolEntry);
+
+ FreePageToLinux(psPagePoolEntry->psPage);
+ LinuxPagePoolEntryFree(psPagePoolEntry);
+
+ if (--uNumToScan == 0)
+ {
+ break;
+ }
+ }
+
+ if (list_empty(&g_sPagePoolList))
+ {
+ PVR_ASSERT(atomic_read(&g_sPagePoolEntryCount) == 0);
+ }
+
+ PagePoolUnlock();
+
+ PVR_TRACE(("%s: Pages in pool after scan: %d", __FUNCTION__, atomic_read(&g_sPagePoolEntryCount)));
+ }
+
+ return atomic_read(&g_sPagePoolEntryCount);
+}
+#endif
+
+static IMG_BOOL
+AllocPages(IMG_UINT32 ui32AreaFlags, struct page ***pppsPageList, IMG_HANDLE *phBlockPageList, IMG_UINT32 ui32NumPages, IMG_BOOL *pbFromPagePool)
+{
+ struct page **ppsPageList;
+ IMG_HANDLE hBlockPageList;
+ IMG_INT32 i;
+ PVRSRV_ERROR eError;
+ IMG_BOOL bFromPagePool = IMG_FALSE;
+
+ eError = OSAllocMem(0, sizeof(*ppsPageList) * ui32NumPages, (IMG_VOID **)&ppsPageList, &hBlockPageList,
+ "Array of pages");
+ if (eError != PVRSRV_OK)
+ {
+ goto failed_page_list_alloc;
+ }
+
+ *pbFromPagePool = IMG_TRUE;
+ for(i = 0; i < (IMG_INT32)ui32NumPages; i++)
+ {
+ ppsPageList[i] = AllocPage(ui32AreaFlags, &bFromPagePool);
+ if (!ppsPageList[i])
+ {
+ goto failed_alloc_pages;
+ }
+ *pbFromPagePool &= bFromPagePool;
+ }
+
+ *pppsPageList = ppsPageList;
+ *phBlockPageList = hBlockPageList;
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES,
+ ppsPageList,
+ 0,
+ 0,
+ NULL,
+ PAGES_TO_BYTES(ui32NumPages),
+ "unknown",
+ 0
+ );
+#endif
+
+ return IMG_TRUE;
+
+failed_alloc_pages:
+ for(i--; i >= 0; i--)
+ {
+ FreePage(*pbFromPagePool, ppsPageList[i]);
+ }
+ (IMG_VOID) OSFreeMem(0, sizeof(*ppsPageList) * ui32NumPages, ppsPageList, hBlockPageList);
+
+failed_page_list_alloc:
+ return IMG_FALSE;
+}
+
+
+static IMG_VOID
+FreePages(IMG_BOOL bToPagePool, struct page **ppsPageList, IMG_HANDLE hBlockPageList, IMG_UINT32 ui32NumPages)
+{
+ IMG_INT32 i;
+
+ for(i = 0; i < (IMG_INT32)ui32NumPages; i++)
+ {
+ FreePage(bToPagePool, ppsPageList[i]);
+ }
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES, ppsPageList, __FILE__, __LINE__);
+#endif
+
+ (IMG_VOID) OSFreeMem(0, sizeof(*ppsPageList) * ui32NumPages, ppsPageList, hBlockPageList);
+}
+
+
+LinuxMemArea *
+NewVMallocLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags)
+{
+ LinuxMemArea *psLinuxMemArea = NULL;
+ IMG_VOID *pvCpuVAddr;
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ IMG_UINT32 ui32NumPages = 0;
+ struct page **ppsPageList = NULL;
+ IMG_HANDLE hBlockPageList;
+#endif
+ IMG_BOOL bFromPagePool = IMG_FALSE;
+
+ psLinuxMemArea = LinuxMemAreaStructAlloc();
+ if (!psLinuxMemArea)
+ {
+ goto failed;
+ }
+
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ ui32NumPages = RANGE_TO_PAGES(ui32Bytes);
+
+ if (!AllocPages(ui32AreaFlags, &ppsPageList, &hBlockPageList, ui32NumPages, &bFromPagePool))
+ {
+ goto failed;
+ }
+
+ pvCpuVAddr = VMapWrapper(ppsPageList, ui32NumPages, ui32AreaFlags);
+#else
+ pvCpuVAddr = VMallocWrapper(ui32Bytes, ui32AreaFlags);
+ if (!pvCpuVAddr)
+ {
+ goto failed;
+ }
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+
+ ReservePages(pvCpuVAddr, ui32Bytes);
+#endif
+#endif
+
+ psLinuxMemArea->eAreaType = LINUX_MEM_AREA_VMALLOC;
+ psLinuxMemArea->uData.sVmalloc.pvVmallocAddress = pvCpuVAddr;
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ psLinuxMemArea->uData.sVmalloc.ppsPageList = ppsPageList;
+ psLinuxMemArea->uData.sVmalloc.hBlockPageList = hBlockPageList;
+#endif
+ psLinuxMemArea->ui32ByteSize = ui32Bytes;
+ psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+ INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+
+ if (AreaIsUncached(ui32AreaFlags) && !bFromPagePool)
+ {
+#if !defined(PVRSRV_AVOID_RANGED_INVALIDATE)
+ OSInvalidateCPUCacheRangeKM(psLinuxMemArea, pvCpuVAddr, ui32Bytes);
+#else
+ OSFlushCPUCacheKM();
+#endif
+ }
+
+ return psLinuxMemArea;
+
+failed:
+ PVR_DPF((PVR_DBG_ERROR, "%s: failed!", __FUNCTION__));
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ if (ppsPageList)
+ {
+ FreePages(bFromPagePool, ppsPageList, hBlockPageList, ui32NumPages);
+ }
+#endif
+ if (psLinuxMemArea)
+ {
+ LinuxMemAreaStructFree(psLinuxMemArea);
+ }
+
+ return NULL;
+}
+
+
+IMG_VOID
+FreeVMallocLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ IMG_UINT32 ui32NumPages;
+ struct page **ppsPageList;
+ IMG_HANDLE hBlockPageList;
+#endif
+
+ PVR_ASSERT(psLinuxMemArea);
+ PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_VMALLOC);
+ PVR_ASSERT(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+ PVR_DPF((PVR_DBG_MESSAGE,"%s: pvCpuVAddr: %p",
+ __FUNCTION__, psLinuxMemArea->uData.sVmalloc.pvVmallocAddress));
+
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ VUnmapWrapper(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress);
+
+ ui32NumPages = RANGE_TO_PAGES(psLinuxMemArea->ui32ByteSize);
+ ppsPageList = psLinuxMemArea->uData.sVmalloc.ppsPageList;
+ hBlockPageList = psLinuxMemArea->uData.sVmalloc.hBlockPageList;
+
+ FreePages(CanFreeToPool(psLinuxMemArea), ppsPageList, hBlockPageList, ui32NumPages);
+#else
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+ UnreservePages(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress,
+ psLinuxMemArea->ui32ByteSize);
+#endif
+
+ VFreeWrapper(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress);
+#endif
+
+ LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+static IMG_VOID
+ReservePages(IMG_VOID *pvAddress, IMG_UINT32 ui32Length)
+{
+ IMG_VOID *pvPage;
+ IMG_VOID *pvEnd = pvAddress + ui32Length;
+
+ for(pvPage = pvAddress; pvPage < pvEnd; pvPage += PAGE_SIZE)
+ {
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
+ SetPageReserved(vmalloc_to_page(pvPage));
+#else
+ mem_map_reserve(vmalloc_to_page(pvPage));
+#endif
+ }
+}
+
+
+static IMG_VOID
+UnreservePages(IMG_VOID *pvAddress, IMG_UINT32 ui32Length)
+{
+ IMG_VOID *pvPage;
+ IMG_VOID *pvEnd = pvAddress + ui32Length;
+
+ for(pvPage = pvAddress; pvPage < pvEnd; pvPage += PAGE_SIZE)
+ {
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
+ ClearPageReserved(vmalloc_to_page(pvPage));
+#else
+ mem_map_unreserve(vmalloc_to_page(pvPage));
+#endif
+ }
+}
+#endif
+
+
+IMG_VOID *
+_IORemapWrapper(IMG_CPU_PHYADDR BasePAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32MappingFlags,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32Line)
+{
+ IMG_VOID *pvIORemapCookie;
+
+ switch (ui32MappingFlags & PVRSRV_HAP_CACHETYPE_MASK)
+ {
+ case PVRSRV_HAP_CACHED:
+ pvIORemapCookie = (IMG_VOID *)IOREMAP(BasePAddr.uiAddr, ui32Bytes);
+ break;
+ case PVRSRV_HAP_WRITECOMBINE:
+ pvIORemapCookie = (IMG_VOID *)IOREMAP_WC(BasePAddr.uiAddr, ui32Bytes);
+ break;
+ case PVRSRV_HAP_UNCACHED:
+ pvIORemapCookie = (IMG_VOID *)IOREMAP_UC(BasePAddr.uiAddr, ui32Bytes);
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "IORemapWrapper: unknown mapping flags"));
+ return NULL;
+ }
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ if (pvIORemapCookie)
+ {
+ DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_IOREMAP,
+ pvIORemapCookie,
+ pvIORemapCookie,
+ BasePAddr.uiAddr,
+ NULL,
+ ui32Bytes,
+ pszFileName,
+ ui32Line
+ );
+ }
+#else
+ PVR_UNREFERENCED_PARAMETER(pszFileName);
+ PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+
+ return pvIORemapCookie;
+}
+
+
+IMG_VOID
+_IOUnmapWrapper(IMG_VOID *pvIORemapCookie, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_IOREMAP, pvIORemapCookie, pszFileName, ui32Line);
+#else
+ PVR_UNREFERENCED_PARAMETER(pszFileName);
+ PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+ iounmap(pvIORemapCookie);
+}
+
+
+LinuxMemArea *
+NewIORemapLinuxMemArea(IMG_CPU_PHYADDR BasePAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32AreaFlags)
+{
+ LinuxMemArea *psLinuxMemArea;
+ IMG_VOID *pvIORemapCookie;
+
+ psLinuxMemArea = LinuxMemAreaStructAlloc();
+ if (!psLinuxMemArea)
+ {
+ return NULL;
+ }
+
+ pvIORemapCookie = IORemapWrapper(BasePAddr, ui32Bytes, ui32AreaFlags);
+ if (!pvIORemapCookie)
+ {
+ LinuxMemAreaStructFree(psLinuxMemArea);
+ return NULL;
+ }
+
+ psLinuxMemArea->eAreaType = LINUX_MEM_AREA_IOREMAP;
+ psLinuxMemArea->uData.sIORemap.pvIORemapCookie = pvIORemapCookie;
+ psLinuxMemArea->uData.sIORemap.CPUPhysAddr = BasePAddr;
+ psLinuxMemArea->ui32ByteSize = ui32Bytes;
+ psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+ INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+ return psLinuxMemArea;
+}
+
+
+IMG_VOID
+FreeIORemapLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+ PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_IOREMAP);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+ IOUnmapWrapper(psLinuxMemArea->uData.sIORemap.pvIORemapCookie);
+
+ LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+static IMG_BOOL
+TreatExternalPagesAsContiguous(IMG_SYS_PHYADDR *psSysPhysAddr, IMG_UINT32 ui32Bytes, IMG_BOOL bPhysContig)
+{
+ IMG_UINT32 ui32;
+ IMG_UINT32 ui32AddrChk;
+ IMG_UINT32 ui32NumPages = RANGE_TO_PAGES(ui32Bytes);
+
+
+ for (ui32 = 0, ui32AddrChk = psSysPhysAddr[0].uiAddr;
+ ui32 < ui32NumPages;
+ ui32++, ui32AddrChk = (bPhysContig) ? (ui32AddrChk + PAGE_SIZE) : psSysPhysAddr[ui32].uiAddr)
+ {
+ if (!pfn_valid(PHYS_TO_PFN(ui32AddrChk)))
+ {
+ break;
+ }
+ }
+ if (ui32 == ui32NumPages)
+ {
+ return IMG_FALSE;
+ }
+
+ if (!bPhysContig)
+ {
+ for (ui32 = 0, ui32AddrChk = psSysPhysAddr[0].uiAddr;
+ ui32 < ui32NumPages;
+ ui32++, ui32AddrChk += PAGE_SIZE)
+ {
+ if (psSysPhysAddr[ui32].uiAddr != ui32AddrChk)
+ {
+ return IMG_FALSE;
+ }
+ }
+ }
+
+ return IMG_TRUE;
+}
+#endif
+
+LinuxMemArea *NewExternalKVLinuxMemArea(IMG_SYS_PHYADDR *pBasePAddr, IMG_VOID *pvCPUVAddr, IMG_UINT32 ui32Bytes, IMG_BOOL bPhysContig, IMG_UINT32 ui32AreaFlags)
+{
+ LinuxMemArea *psLinuxMemArea;
+
+ psLinuxMemArea = LinuxMemAreaStructAlloc();
+ if (!psLinuxMemArea)
+ {
+ return NULL;
+ }
+
+ psLinuxMemArea->eAreaType = LINUX_MEM_AREA_EXTERNAL_KV;
+ psLinuxMemArea->uData.sExternalKV.pvExternalKV = pvCPUVAddr;
+ psLinuxMemArea->uData.sExternalKV.bPhysContig =
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+ (bPhysContig || TreatExternalPagesAsContiguous(pBasePAddr, ui32Bytes, bPhysContig))
+ ? IMG_TRUE : IMG_FALSE;
+#else
+ bPhysContig;
+#endif
+ if (psLinuxMemArea->uData.sExternalKV.bPhysContig)
+ {
+ psLinuxMemArea->uData.sExternalKV.uPhysAddr.SysPhysAddr = *pBasePAddr;
+ }
+ else
+ {
+ psLinuxMemArea->uData.sExternalKV.uPhysAddr.pSysPhysAddr = pBasePAddr;
+ }
+ psLinuxMemArea->ui32ByteSize = ui32Bytes;
+ psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+ INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+ return psLinuxMemArea;
+}
+
+
+IMG_VOID
+FreeExternalKVLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+ PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_EXTERNAL_KV);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+ LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+
+LinuxMemArea *
+NewIOLinuxMemArea(IMG_CPU_PHYADDR BasePAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32AreaFlags)
+{
+ LinuxMemArea *psLinuxMemArea = LinuxMemAreaStructAlloc();
+ if (!psLinuxMemArea)
+ {
+ return NULL;
+ }
+
+
+ psLinuxMemArea->eAreaType = LINUX_MEM_AREA_IO;
+ psLinuxMemArea->uData.sIO.CPUPhysAddr.uiAddr = BasePAddr.uiAddr;
+ psLinuxMemArea->ui32ByteSize = ui32Bytes;
+ psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+ INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_IO,
+ (IMG_VOID *)BasePAddr.uiAddr,
+ 0,
+ BasePAddr.uiAddr,
+ NULL,
+ ui32Bytes,
+ "unknown",
+ 0
+ );
+#endif
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+ return psLinuxMemArea;
+}
+
+
+IMG_VOID
+FreeIOLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+ PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_IO);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_IO,
+ (IMG_VOID *)psLinuxMemArea->uData.sIO.CPUPhysAddr.uiAddr, __FILE__, __LINE__);
+#endif
+
+
+
+ LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+
+LinuxMemArea *
+NewAllocPagesLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags)
+{
+ LinuxMemArea *psLinuxMemArea;
+ IMG_UINT32 ui32NumPages;
+ struct page **ppsPageList;
+ IMG_HANDLE hBlockPageList;
+ IMG_BOOL bFromPagePool;
+
+ psLinuxMemArea = LinuxMemAreaStructAlloc();
+ if (!psLinuxMemArea)
+ {
+ goto failed_area_alloc;
+ }
+
+ ui32NumPages = RANGE_TO_PAGES(ui32Bytes);
+
+ if (!AllocPages(ui32AreaFlags, &ppsPageList, &hBlockPageList, ui32NumPages, &bFromPagePool))
+ {
+ goto failed_alloc_pages;
+ }
+
+ psLinuxMemArea->eAreaType = LINUX_MEM_AREA_ALLOC_PAGES;
+ psLinuxMemArea->uData.sPageList.ppsPageList = ppsPageList;
+ psLinuxMemArea->uData.sPageList.hBlockPageList = hBlockPageList;
+ psLinuxMemArea->ui32ByteSize = ui32Bytes;
+ psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+ INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+
+ psLinuxMemArea->bNeedsCacheInvalidate = AreaIsUncached(ui32AreaFlags) && !bFromPagePool;
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+ return psLinuxMemArea;
+
+failed_alloc_pages:
+ LinuxMemAreaStructFree(psLinuxMemArea);
+failed_area_alloc:
+ PVR_DPF((PVR_DBG_ERROR, "%s: failed", __FUNCTION__));
+
+ return NULL;
+}
+
+
+IMG_VOID
+FreeAllocPagesLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+ IMG_UINT32 ui32NumPages;
+ struct page **ppsPageList;
+ IMG_HANDLE hBlockPageList;
+
+ PVR_ASSERT(psLinuxMemArea);
+ PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_ALLOC_PAGES);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+ ui32NumPages = RANGE_TO_PAGES(psLinuxMemArea->ui32ByteSize);
+ ppsPageList = psLinuxMemArea->uData.sPageList.ppsPageList;
+ hBlockPageList = psLinuxMemArea->uData.sPageList.hBlockPageList;
+
+ FreePages(CanFreeToPool(psLinuxMemArea), ppsPageList, hBlockPageList, ui32NumPages);
+
+ LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+#if defined(CONFIG_ION_OMAP)
+
+#include "env_perproc.h"
+
+#include <linux/ion.h>
+#include <linux/omap_ion.h>
+
+extern struct ion_client *gpsIONClient;
+
+LinuxMemArea *
+NewIONLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags,
+ IMG_PVOID pvPrivData, IMG_UINT32 ui32PrivDataLength)
+{
+ const IMG_UINT32 ui32AllocDataLen =
+ offsetof(struct omap_ion_tiler_alloc_data, handle);
+ struct omap_ion_tiler_alloc_data asAllocData[2] = {};
+ u32 *pu32PageAddrs[2] = { NULL, NULL };
+ IMG_UINT32 i, ui32NumHandlesPerFd;
+ IMG_BYTE *pbPrivData = pvPrivData;
+ IMG_CPU_PHYADDR *pCPUPhysAddrs;
+ int iNumPages[2] = { 0, 0 };
+ LinuxMemArea *psLinuxMemArea;
+
+ psLinuxMemArea = LinuxMemAreaStructAlloc();
+ if (!psLinuxMemArea)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate LinuxMemArea struct", __func__));
+ goto err_out;
+ }
+
+
+ BUG_ON(ui32PrivDataLength != ui32AllocDataLen &&
+ ui32PrivDataLength != ui32AllocDataLen * 2);
+ ui32NumHandlesPerFd = ui32PrivDataLength / ui32AllocDataLen;
+
+
+ for(i = 0; i < ui32NumHandlesPerFd; i++)
+ {
+ memcpy(&asAllocData[i], &pbPrivData[i * ui32AllocDataLen], ui32AllocDataLen);
+
+ if (omap_ion_tiler_alloc(gpsIONClient, &asAllocData[i]) < 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate via ion_tiler", __func__));
+ goto err_free;
+ }
+
+ if (omap_tiler_pages(gpsIONClient, asAllocData[i].handle, &iNumPages[i],
+ &pu32PageAddrs[i]) < 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to compute tiler pages", __func__));
+ goto err_free;
+ }
+ }
+
+
+ BUG_ON(ui32Bytes != (iNumPages[0] + iNumPages[1]) * PAGE_SIZE);
+ BUG_ON(sizeof(IMG_CPU_PHYADDR) != sizeof(int));
+
+
+ pCPUPhysAddrs = vmalloc(sizeof(IMG_CPU_PHYADDR) * (iNumPages[0] + iNumPages[1]));
+ if (!pCPUPhysAddrs)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate page list", __func__));
+ goto err_free;
+ }
+ for(i = 0; i < iNumPages[0]; i++)
+ pCPUPhysAddrs[i].uiAddr = pu32PageAddrs[0][i];
+ for(i = 0; i < iNumPages[1]; i++)
+ pCPUPhysAddrs[iNumPages[0] + i].uiAddr = pu32PageAddrs[1][i];
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_ION,
+ asAllocData[0].handle,
+ 0,
+ 0,
+ NULL,
+ PAGE_ALIGN(ui32Bytes),
+ "unknown",
+ 0
+ );
+#endif
+
+ for(i = 0; i < 2; i++)
+ psLinuxMemArea->uData.sIONTilerAlloc.psIONHandle[i] = asAllocData[i].handle;
+
+ psLinuxMemArea->eAreaType = LINUX_MEM_AREA_ION;
+ psLinuxMemArea->uData.sIONTilerAlloc.pCPUPhysAddrs = pCPUPhysAddrs;
+ psLinuxMemArea->ui32ByteSize = ui32Bytes;
+ psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+ INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+
+ psLinuxMemArea->bNeedsCacheInvalidate = AreaIsUncached(ui32AreaFlags);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+err_out:
+ return psLinuxMemArea;
+
+err_free:
+ LinuxMemAreaStructFree(psLinuxMemArea);
+ psLinuxMemArea = IMG_NULL;
+ goto err_out;
+}
+
+
+IMG_VOID
+FreeIONLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+ IMG_UINT32 i;
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_ION,
+ psLinuxMemArea->uData.sIONTilerAlloc.psIONHandle[0],
+ __FILE__, __LINE__);
+#endif
+
+ for(i = 0; i < 2; i++)
+ {
+ if (!psLinuxMemArea->uData.sIONTilerAlloc.psIONHandle[i])
+ break;
+ ion_free(gpsIONClient, psLinuxMemArea->uData.sIONTilerAlloc.psIONHandle[i]);
+ psLinuxMemArea->uData.sIONTilerAlloc.psIONHandle[i] = IMG_NULL;
+ }
+
+
+ vfree(psLinuxMemArea->uData.sIONTilerAlloc.pCPUPhysAddrs);
+ psLinuxMemArea->uData.sIONTilerAlloc.pCPUPhysAddrs = IMG_NULL;
+
+ LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+#endif
+
+struct page*
+LinuxMemAreaOffsetToPage(LinuxMemArea *psLinuxMemArea,
+ IMG_UINT32 ui32ByteOffset)
+{
+ IMG_UINT32 ui32PageIndex;
+ IMG_CHAR *pui8Addr;
+
+ switch (psLinuxMemArea->eAreaType)
+ {
+ case LINUX_MEM_AREA_ALLOC_PAGES:
+ ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset);
+ return psLinuxMemArea->uData.sPageList.ppsPageList[ui32PageIndex];
+
+ case LINUX_MEM_AREA_VMALLOC:
+ pui8Addr = psLinuxMemArea->uData.sVmalloc.pvVmallocAddress;
+ pui8Addr += ui32ByteOffset;
+ return vmalloc_to_page(pui8Addr);
+
+ case LINUX_MEM_AREA_SUB_ALLOC:
+
+ return LinuxMemAreaOffsetToPage(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea,
+ psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset
+ + ui32ByteOffset);
+ default:
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: Unsupported request for struct page from LinuxMemArea with type=%s",
+ __FUNCTION__, LinuxMemAreaTypeToString(psLinuxMemArea->eAreaType)));
+ return NULL;
+ }
+}
+
+
+LinuxKMemCache *
+KMemCacheCreateWrapper(IMG_CHAR *pszName,
+ size_t Size,
+ size_t Align,
+ IMG_UINT32 ui32Flags)
+{
+#if defined(DEBUG_LINUX_SLAB_ALLOCATIONS)
+ ui32Flags |= SLAB_POISON|SLAB_RED_ZONE;
+#endif
+ return kmem_cache_create(pszName, Size, Align, ui32Flags, NULL
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
+ , NULL
+#endif
+ );
+}
+
+
+IMG_VOID
+KMemCacheDestroyWrapper(LinuxKMemCache *psCache)
+{
+ kmem_cache_destroy(psCache);
+}
+
+
+IMG_VOID *
+_KMemCacheAllocWrapper(LinuxKMemCache *psCache,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14))
+ gfp_t Flags,
+#else
+ IMG_INT Flags,
+#endif
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32Line)
+{
+ IMG_VOID *pvRet;
+
+ pvRet = kmem_cache_zalloc(psCache, Flags);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE,
+ pvRet,
+ pvRet,
+ 0,
+ psCache,
+ kmem_cache_size(psCache),
+ pszFileName,
+ ui32Line
+ );
+#else
+ PVR_UNREFERENCED_PARAMETER(pszFileName);
+ PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+
+ return pvRet;
+}
+
+
+LinuxMemArea *
+NewSubLinuxMemArea(LinuxMemArea *psParentLinuxMemArea,
+ IMG_UINT32 ui32ByteOffset,
+ IMG_UINT32 ui32Bytes)
+{
+ LinuxMemArea *psLinuxMemArea;
+
+ PVR_ASSERT((ui32ByteOffset+ui32Bytes) <= psParentLinuxMemArea->ui32ByteSize);
+
+ psLinuxMemArea = LinuxMemAreaStructAlloc();
+ if (!psLinuxMemArea)
+ {
+ return NULL;
+ }
+
+ psLinuxMemArea->eAreaType = LINUX_MEM_AREA_SUB_ALLOC;
+ psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea = psParentLinuxMemArea;
+ psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset = ui32ByteOffset;
+ psLinuxMemArea->ui32ByteSize = ui32Bytes;
+ psLinuxMemArea->ui32AreaFlags = psParentLinuxMemArea->ui32AreaFlags;
+ psLinuxMemArea->bNeedsCacheInvalidate = psParentLinuxMemArea->bNeedsCacheInvalidate;
+ INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ {
+ DEBUG_LINUX_MEM_AREA_REC *psParentRecord;
+ psParentRecord = DebugLinuxMemAreaRecordFind(psParentLinuxMemArea);
+ DebugLinuxMemAreaRecordAdd(psLinuxMemArea, psParentRecord->ui32Flags);
+ }
+#endif
+
+ return psLinuxMemArea;
+}
+
+
+static IMG_VOID
+FreeSubLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+ PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+
+
+ LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+
+static LinuxMemArea *
+LinuxMemAreaStructAlloc(IMG_VOID)
+{
+#if 0
+ LinuxMemArea *psLinuxMemArea;
+ psLinuxMemArea = kmem_cache_alloc(g_PsLinuxMemAreaCache, GFP_KERNEL);
+ printk(KERN_ERR "%s: psLinuxMemArea=%p\n", __FUNCTION__, psLinuxMemArea);
+ dump_stack();
+ return psLinuxMemArea;
+#else
+ return KMemCacheAllocWrapper(g_PsLinuxMemAreaCache, GFP_KERNEL);
+#endif
+}
+
+
+static IMG_VOID
+LinuxMemAreaStructFree(LinuxMemArea *psLinuxMemArea)
+{
+ KMemCacheFreeWrapper(g_PsLinuxMemAreaCache, psLinuxMemArea);
+
+
+}
+
+
+IMG_VOID
+LinuxMemAreaDeepFree(LinuxMemArea *psLinuxMemArea)
+{
+ switch (psLinuxMemArea->eAreaType)
+ {
+ case LINUX_MEM_AREA_VMALLOC:
+ FreeVMallocLinuxMemArea(psLinuxMemArea);
+ break;
+ case LINUX_MEM_AREA_ALLOC_PAGES:
+ FreeAllocPagesLinuxMemArea(psLinuxMemArea);
+ break;
+ case LINUX_MEM_AREA_IOREMAP:
+ FreeIORemapLinuxMemArea(psLinuxMemArea);
+ break;
+ case LINUX_MEM_AREA_EXTERNAL_KV:
+ FreeExternalKVLinuxMemArea(psLinuxMemArea);
+ break;
+ case LINUX_MEM_AREA_IO:
+ FreeIOLinuxMemArea(psLinuxMemArea);
+ break;
+ case LINUX_MEM_AREA_SUB_ALLOC:
+ FreeSubLinuxMemArea(psLinuxMemArea);
+ break;
+ case LINUX_MEM_AREA_ION:
+ FreeIONLinuxMemArea(psLinuxMemArea);
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "%s: Unknown are type (%d)\n",
+ __FUNCTION__, psLinuxMemArea->eAreaType));
+ break;
+ }
+}
+
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+static IMG_VOID
+DebugLinuxMemAreaRecordAdd(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32Flags)
+{
+ DEBUG_LINUX_MEM_AREA_REC *psNewRecord;
+ const IMG_CHAR *pi8FlagsString;
+
+ LinuxLockMutex(&g_sDebugMutex);
+
+ if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
+ {
+ g_LinuxMemAreaWaterMark += psLinuxMemArea->ui32ByteSize;
+ if (g_LinuxMemAreaWaterMark > g_LinuxMemAreaHighWaterMark)
+ {
+ g_LinuxMemAreaHighWaterMark = g_LinuxMemAreaWaterMark;
+ }
+ }
+ g_LinuxMemAreaCount++;
+
+
+ psNewRecord = kmalloc(sizeof(DEBUG_LINUX_MEM_AREA_REC), GFP_KERNEL);
+ if (psNewRecord)
+ {
+
+ psNewRecord->psLinuxMemArea = psLinuxMemArea;
+ psNewRecord->ui32Flags = ui32Flags;
+ psNewRecord->pid = OSGetCurrentProcessIDKM();
+
+ List_DEBUG_LINUX_MEM_AREA_REC_Insert(&g_LinuxMemAreaRecords, psNewRecord);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: failed to allocate linux memory area record.",
+ __FUNCTION__));
+ }
+
+
+ pi8FlagsString = HAPFlagsToString(ui32Flags);
+ if (strstr(pi8FlagsString, "UNKNOWN"))
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: Unexpected flags (0x%08x) associated with psLinuxMemArea @ %p",
+ __FUNCTION__,
+ ui32Flags,
+ psLinuxMemArea));
+
+ }
+
+ LinuxUnLockMutex(&g_sDebugMutex);
+}
+
+
+
+static IMG_VOID* MatchLinuxMemArea_AnyVaCb(DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord,
+ va_list va)
+{
+ LinuxMemArea *psLinuxMemArea;
+
+ psLinuxMemArea = va_arg(va, LinuxMemArea*);
+ if (psCurrentRecord->psLinuxMemArea == psLinuxMemArea)
+ {
+ return psCurrentRecord;
+ }
+ else
+ {
+ return IMG_NULL;
+ }
+}
+
+
+static DEBUG_LINUX_MEM_AREA_REC *
+DebugLinuxMemAreaRecordFind(LinuxMemArea *psLinuxMemArea)
+{
+ DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord;
+
+ LinuxLockMutex(&g_sDebugMutex);
+ psCurrentRecord = List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords,
+ MatchLinuxMemArea_AnyVaCb,
+ psLinuxMemArea);
+
+ LinuxUnLockMutex(&g_sDebugMutex);
+
+ return psCurrentRecord;
+}
+
+
+static IMG_VOID
+DebugLinuxMemAreaRecordRemove(LinuxMemArea *psLinuxMemArea)
+{
+ DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord;
+
+ LinuxLockMutex(&g_sDebugMutex);
+
+ if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
+ {
+ g_LinuxMemAreaWaterMark -= psLinuxMemArea->ui32ByteSize;
+ }
+ g_LinuxMemAreaCount--;
+
+
+ psCurrentRecord = List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords,
+ MatchLinuxMemArea_AnyVaCb,
+ psLinuxMemArea);
+ if (psCurrentRecord)
+ {
+
+ List_DEBUG_LINUX_MEM_AREA_REC_Remove(psCurrentRecord);
+ kfree(psCurrentRecord);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: couldn't find an entry for psLinuxMemArea=%p\n",
+ __FUNCTION__, psLinuxMemArea));
+ }
+
+ LinuxUnLockMutex(&g_sDebugMutex);
+}
+#endif
+
+
+IMG_VOID *
+LinuxMemAreaToCpuVAddr(LinuxMemArea *psLinuxMemArea)
+{
+ switch (psLinuxMemArea->eAreaType)
+ {
+ case LINUX_MEM_AREA_VMALLOC:
+ return psLinuxMemArea->uData.sVmalloc.pvVmallocAddress;
+ case LINUX_MEM_AREA_IOREMAP:
+ return psLinuxMemArea->uData.sIORemap.pvIORemapCookie;
+ case LINUX_MEM_AREA_EXTERNAL_KV:
+ return psLinuxMemArea->uData.sExternalKV.pvExternalKV;
+ case LINUX_MEM_AREA_SUB_ALLOC:
+ {
+ IMG_CHAR *pAddr =
+ LinuxMemAreaToCpuVAddr(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea);
+ if (!pAddr)
+ {
+ return NULL;
+ }
+ return pAddr + psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset;
+ }
+ default:
+ return NULL;
+ }
+}
+
+
+IMG_CPU_PHYADDR
+LinuxMemAreaToCpuPAddr(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32ByteOffset)
+{
+ IMG_CPU_PHYADDR CpuPAddr;
+
+ CpuPAddr.uiAddr = 0;
+
+ switch (psLinuxMemArea->eAreaType)
+ {
+ case LINUX_MEM_AREA_IOREMAP:
+ {
+ CpuPAddr = psLinuxMemArea->uData.sIORemap.CPUPhysAddr;
+ CpuPAddr.uiAddr += ui32ByteOffset;
+ break;
+ }
+ case LINUX_MEM_AREA_EXTERNAL_KV:
+ {
+ if (psLinuxMemArea->uData.sExternalKV.bPhysContig)
+ {
+ CpuPAddr = SysSysPAddrToCpuPAddr(psLinuxMemArea->uData.sExternalKV.uPhysAddr.SysPhysAddr);
+ CpuPAddr.uiAddr += ui32ByteOffset;
+ }
+ else
+ {
+ IMG_UINT32 ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset);
+ IMG_SYS_PHYADDR SysPAddr = psLinuxMemArea->uData.sExternalKV.uPhysAddr.pSysPhysAddr[ui32PageIndex];
+
+ CpuPAddr = SysSysPAddrToCpuPAddr(SysPAddr);
+ CpuPAddr.uiAddr += ADDR_TO_PAGE_OFFSET(ui32ByteOffset);
+ }
+ break;
+ }
+ case LINUX_MEM_AREA_IO:
+ {
+ CpuPAddr = psLinuxMemArea->uData.sIO.CPUPhysAddr;
+ CpuPAddr.uiAddr += ui32ByteOffset;
+ break;
+ }
+ case LINUX_MEM_AREA_VMALLOC:
+ {
+ IMG_CHAR *pCpuVAddr;
+ pCpuVAddr =
+ (IMG_CHAR *)psLinuxMemArea->uData.sVmalloc.pvVmallocAddress;
+ pCpuVAddr += ui32ByteOffset;
+ CpuPAddr.uiAddr = VMallocToPhys(pCpuVAddr);
+ break;
+ }
+ case LINUX_MEM_AREA_ION:
+ {
+ IMG_UINT32 ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset);
+ CpuPAddr = psLinuxMemArea->uData.sIONTilerAlloc.pCPUPhysAddrs[ui32PageIndex];
+ CpuPAddr.uiAddr += ADDR_TO_PAGE_OFFSET(ui32ByteOffset);
+ break;
+ }
+ case LINUX_MEM_AREA_ALLOC_PAGES:
+ {
+ struct page *page;
+ IMG_UINT32 ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset);
+ page = psLinuxMemArea->uData.sPageList.ppsPageList[ui32PageIndex];
+ CpuPAddr.uiAddr = page_to_phys(page);
+ CpuPAddr.uiAddr += ADDR_TO_PAGE_OFFSET(ui32ByteOffset);
+ break;
+ }
+ case LINUX_MEM_AREA_SUB_ALLOC:
+ {
+ CpuPAddr =
+ OSMemHandleToCpuPAddr(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea,
+ psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset
+ + ui32ByteOffset);
+ break;
+ }
+ default:
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Unknown LinuxMemArea type (%d)\n",
+ __FUNCTION__, psLinuxMemArea->eAreaType));
+ PVR_ASSERT(CpuPAddr.uiAddr);
+ break;
+ }
+ }
+
+ return CpuPAddr;
+}
+
+
+IMG_BOOL
+LinuxMemAreaPhysIsContig(LinuxMemArea *psLinuxMemArea)
+{
+ switch (psLinuxMemArea->eAreaType)
+ {
+ case LINUX_MEM_AREA_IOREMAP:
+ case LINUX_MEM_AREA_IO:
+ return IMG_TRUE;
+
+ case LINUX_MEM_AREA_EXTERNAL_KV:
+ return psLinuxMemArea->uData.sExternalKV.bPhysContig;
+
+ case LINUX_MEM_AREA_ION:
+ case LINUX_MEM_AREA_VMALLOC:
+ case LINUX_MEM_AREA_ALLOC_PAGES:
+ return IMG_FALSE;
+
+ case LINUX_MEM_AREA_SUB_ALLOC:
+
+ return LinuxMemAreaPhysIsContig(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea);
+
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "%s: Unknown LinuxMemArea type (%d)\n",
+ __FUNCTION__, psLinuxMemArea->eAreaType));
+ break;
+ }
+ return IMG_FALSE;
+}
+
+
+const IMG_CHAR *
+LinuxMemAreaTypeToString(LINUX_MEM_AREA_TYPE eMemAreaType)
+{
+
+ switch (eMemAreaType)
+ {
+ case LINUX_MEM_AREA_IOREMAP:
+ return "LINUX_MEM_AREA_IOREMAP";
+ case LINUX_MEM_AREA_EXTERNAL_KV:
+ return "LINUX_MEM_AREA_EXTERNAL_KV";
+ case LINUX_MEM_AREA_IO:
+ return "LINUX_MEM_AREA_IO";
+ case LINUX_MEM_AREA_VMALLOC:
+ return "LINUX_MEM_AREA_VMALLOC";
+ case LINUX_MEM_AREA_SUB_ALLOC:
+ return "LINUX_MEM_AREA_SUB_ALLOC";
+ case LINUX_MEM_AREA_ALLOC_PAGES:
+ return "LINUX_MEM_AREA_ALLOC_PAGES";
+ case LINUX_MEM_AREA_ION:
+ return "LINUX_MEM_AREA_ION";
+ default:
+ PVR_ASSERT(0);
+ }
+
+ return "";
+}
+
+
+#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+static void ProcSeqStartstopDebugMutex(struct seq_file *sfile, IMG_BOOL start)
+{
+ if (start)
+ {
+ LinuxLockMutex(&g_sDebugMutex);
+ }
+ else
+ {
+ LinuxUnLockMutex(&g_sDebugMutex);
+ }
+}
+#endif
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+
+static IMG_VOID* DecOffMemAreaRec_AnyVaCb(DEBUG_LINUX_MEM_AREA_REC *psNode, va_list va)
+{
+ off_t *pOff = va_arg(va, off_t*);
+ if (--(*pOff))
+ {
+ return IMG_NULL;
+ }
+ else
+ {
+ return psNode;
+ }
+}
+
+
+static void* ProcSeqNextMemArea(struct seq_file *sfile,void* el,loff_t off)
+{
+ DEBUG_LINUX_MEM_AREA_REC *psRecord;
+ psRecord = (DEBUG_LINUX_MEM_AREA_REC*)
+ List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords,
+ DecOffMemAreaRec_AnyVaCb,
+ &off);
+ return (void*)psRecord;
+}
+
+static void* ProcSeqOff2ElementMemArea(struct seq_file * sfile, loff_t off)
+{
+ DEBUG_LINUX_MEM_AREA_REC *psRecord;
+ if (!off)
+ {
+ return PVR_PROC_SEQ_START_TOKEN;
+ }
+
+ psRecord = (DEBUG_LINUX_MEM_AREA_REC*)
+ List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords,
+ DecOffMemAreaRec_AnyVaCb,
+ &off);
+ return (void*)psRecord;
+}
+
+
+static void ProcSeqShowMemArea(struct seq_file *sfile,void* el)
+{
+ DEBUG_LINUX_MEM_AREA_REC *psRecord = (DEBUG_LINUX_MEM_AREA_REC*)el;
+ if (el == PVR_PROC_SEQ_START_TOKEN)
+ {
+
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+ seq_printf(sfile,
+ "Number of Linux Memory Areas: %u\n"
+ "At the current water mark these areas correspond to %u bytes (excluding SUB areas)\n"
+ "At the highest water mark these areas corresponded to %u bytes (excluding SUB areas)\n"
+ "\nDetails for all Linux Memory Areas:\n"
+ "%s %-24s %s %s %-8s %-5s %s\n",
+ g_LinuxMemAreaCount,
+ g_LinuxMemAreaWaterMark,
+ g_LinuxMemAreaHighWaterMark,
+ "psLinuxMemArea",
+ "LinuxMemType",
+ "CpuVAddr",
+ "CpuPAddr",
+ "Bytes",
+ "Pid",
+ "Flags"
+ );
+#else
+ seq_printf(sfile,
+ "<mem_areas_header>\n"
+ "\t<count>%u</count>\n"
+ "\t<watermark key=\"mar0\" description=\"current\" bytes=\"%u\"/>\n"
+ "\t<watermark key=\"mar1\" description=\"high\" bytes=\"%u\"/>\n"
+ "</mem_areas_header>\n",
+ g_LinuxMemAreaCount,
+ g_LinuxMemAreaWaterMark,
+ g_LinuxMemAreaHighWaterMark
+ );
+#endif
+ return;
+ }
+
+ seq_printf(sfile,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+ "%8p %-24s %8p %08x %-8d %-5u %08x=(%s)\n",
+#else
+ "<linux_mem_area>\n"
+ "\t<pointer>%8p</pointer>\n"
+ "\t<type>%s</type>\n"
+ "\t<cpu_virtual>%8p</cpu_virtual>\n"
+ "\t<cpu_physical>%08x</cpu_physical>\n"
+ "\t<bytes>%d</bytes>\n"
+ "\t<pid>%u</pid>\n"
+ "\t<flags>%08x</flags>\n"
+ "\t<flags_string>%s</flags_string>\n"
+ "</linux_mem_area>\n",
+#endif
+ psRecord->psLinuxMemArea,
+ LinuxMemAreaTypeToString(psRecord->psLinuxMemArea->eAreaType),
+ LinuxMemAreaToCpuVAddr(psRecord->psLinuxMemArea),
+ LinuxMemAreaToCpuPAddr(psRecord->psLinuxMemArea,0).uiAddr,
+ psRecord->psLinuxMemArea->ui32ByteSize,
+ psRecord->pid,
+ psRecord->ui32Flags,
+ HAPFlagsToString(psRecord->ui32Flags)
+ );
+
+}
+
+#endif
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+
+static IMG_VOID* DecOffMemAllocRec_AnyVaCb(DEBUG_MEM_ALLOC_REC *psNode, va_list va)
+{
+ off_t *pOff = va_arg(va, off_t*);
+ if (--(*pOff))
+ {
+ return IMG_NULL;
+ }
+ else
+ {
+ return psNode;
+ }
+}
+
+
+
+static void* ProcSeqNextMemoryRecords(struct seq_file *sfile,void* el,loff_t off)
+{
+ DEBUG_MEM_ALLOC_REC *psRecord;
+ psRecord = (DEBUG_MEM_ALLOC_REC*)
+ List_DEBUG_MEM_ALLOC_REC_Any_va(g_MemoryRecords,
+ DecOffMemAllocRec_AnyVaCb,
+ &off);
+#if defined(DEBUG_LINUX_XML_PROC_FILES)
+ if (!psRecord)
+ {
+ seq_printf(sfile, "</meminfo>\n");
+ }
+#endif
+
+ return (void*)psRecord;
+}
+
+static void* ProcSeqOff2ElementMemoryRecords(struct seq_file *sfile, loff_t off)
+{
+ DEBUG_MEM_ALLOC_REC *psRecord;
+ if (!off)
+ {
+ return PVR_PROC_SEQ_START_TOKEN;
+ }
+
+ psRecord = (DEBUG_MEM_ALLOC_REC*)
+ List_DEBUG_MEM_ALLOC_REC_Any_va(g_MemoryRecords,
+ DecOffMemAllocRec_AnyVaCb,
+ &off);
+
+#if defined(DEBUG_LINUX_XML_PROC_FILES)
+ if (!psRecord)
+ {
+ seq_printf(sfile, "</meminfo>\n");
+ }
+#endif
+
+ return (void*)psRecord;
+}
+
+static void ProcSeqShowMemoryRecords(struct seq_file *sfile,void* el)
+{
+ DEBUG_MEM_ALLOC_REC *psRecord = (DEBUG_MEM_ALLOC_REC*)el;
+ if (el == PVR_PROC_SEQ_START_TOKEN)
+ {
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+
+ seq_printf(sfile, "%-60s: %d bytes\n",
+ "Current Water Mark of bytes allocated via kmalloc",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
+ seq_printf(sfile, "%-60s: %d bytes\n",
+ "Highest Water Mark of bytes allocated via kmalloc",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
+ seq_printf(sfile, "%-60s: %d bytes\n",
+ "Current Water Mark of bytes allocated via vmalloc",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+ seq_printf(sfile, "%-60s: %d bytes\n",
+ "Highest Water Mark of bytes allocated via vmalloc",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+ seq_printf(sfile, "%-60s: %d bytes\n",
+ "Current Water Mark of bytes allocated via alloc_pages",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+ seq_printf(sfile, "%-60s: %d bytes\n",
+ "Highest Water Mark of bytes allocated via alloc_pages",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+ seq_printf(sfile, "%-60s: %d bytes\n",
+ "Current Water Mark of bytes allocated via ioremap",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+ seq_printf(sfile, "%-60s: %d bytes\n",
+ "Highest Water Mark of bytes allocated via ioremap",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+ seq_printf(sfile, "%-60s: %d bytes\n",
+ "Current Water Mark of bytes reserved for \"IO\" memory areas",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+ seq_printf(sfile, "%-60s: %d bytes\n",
+ "Highest Water Mark of bytes allocated for \"IO\" memory areas",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+ seq_printf(sfile, "%-60s: %d bytes\n",
+ "Current Water Mark of bytes allocated via kmem_cache_alloc",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+ seq_printf(sfile, "%-60s: %d bytes\n",
+ "Highest Water Mark of bytes allocated via kmem_cache_alloc",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ seq_printf(sfile, "%-60s: %d bytes\n",
+ "Current Water Mark of bytes mapped via vmap",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMAP]);
+ seq_printf(sfile, "%-60s: %d bytes\n",
+ "Highest Water Mark of bytes mapped via vmap",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMAP]);
+#endif
+#if (PVR_LINUX_MEM_AREA_POOL_MAX_PAGES != 0)
+ seq_printf(sfile, "%-60s: %d pages\n",
+ "Number of pages in page pool",
+ atomic_read(&g_sPagePoolEntryCount));
+#endif
+ seq_printf( sfile, "\n");
+ seq_printf(sfile, "%-60s: %d bytes\n",
+ "The Current Water Mark for memory allocated from system RAM",
+ SysRAMTrueWaterMark());
+ seq_printf(sfile, "%-60s: %d bytes\n",
+ "The Highest Water Mark for memory allocated from system RAM",
+ g_SysRAMHighWaterMark);
+ seq_printf(sfile, "%-60s: %d bytes\n",
+ "The Current Water Mark for memory allocated from IO memory",
+ g_IOMemWaterMark);
+ seq_printf(sfile, "%-60s: %d bytes\n",
+ "The Highest Water Mark for memory allocated from IO memory",
+ g_IOMemHighWaterMark);
+
+ seq_printf( sfile, "\n");
+
+ seq_printf(sfile, "Details for all known allocations:\n"
+ "%-16s %-8s %-8s %-10s %-5s %-10s %s\n",
+ "Type",
+ "CpuVAddr",
+ "CpuPAddr",
+ "Bytes",
+ "PID",
+ "PrivateData",
+ "Filename:Line");
+
+#else
+
+
+ seq_printf(sfile, "<meminfo>\n<meminfo_header>\n");
+ seq_printf(sfile,
+ "<watermark key=\"mr0\" description=\"kmalloc_current\" bytes=\"%d\"/>\n",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
+ seq_printf(sfile,
+ "<watermark key=\"mr1\" description=\"kmalloc_high\" bytes=\"%d\"/>\n",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
+ seq_printf(sfile,
+ "<watermark key=\"mr2\" description=\"vmalloc_current\" bytes=\"%d\"/>\n",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+ seq_printf(sfile,
+ "<watermark key=\"mr3\" description=\"vmalloc_high\" bytes=\"%d\"/>\n",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+ seq_printf(sfile,
+ "<watermark key=\"mr4\" description=\"alloc_pages_current\" bytes=\"%d\"/>\n",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+ seq_printf(sfile,
+ "<watermark key=\"mr5\" description=\"alloc_pages_high\" bytes=\"%d\"/>\n",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+ seq_printf(sfile,
+ "<watermark key=\"mr6\" description=\"ioremap_current\" bytes=\"%d\"/>\n",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+ seq_printf(sfile,
+ "<watermark key=\"mr7\" description=\"ioremap_high\" bytes=\"%d\"/>\n",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+ seq_printf(sfile,
+ "<watermark key=\"mr8\" description=\"io_current\" bytes=\"%d\"/>\n",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+ seq_printf(sfile,
+ "<watermark key=\"mr9\" description=\"io_high\" bytes=\"%d\"/>\n",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+ seq_printf(sfile,
+ "<watermark key=\"mr10\" description=\"kmem_cache_current\" bytes=\"%d\"/>\n",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+ seq_printf(sfile,
+ "<watermark key=\"mr11\" description=\"kmem_cache_high\" bytes=\"%d\"/>\n",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ seq_printf(sfile,
+ "<watermark key=\"mr12\" description=\"vmap_current\" bytes=\"%d\"/>\n",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMAP]);
+ seq_printf(sfile,
+ "<watermark key=\"mr13\" description=\"vmap_high\" bytes=\"%d\"/>\n",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMAP]);
+#endif
+ seq_printf(sfile,
+ "<watermark key=\"mr14\" description=\"system_ram_current\" bytes=\"%d\"/>\n",
+ SysRAMTrueWaterMark());
+ seq_printf(sfile,
+ "<watermark key=\"mr15\" description=\"system_ram_high\" bytes=\"%d\"/>\n",
+ g_SysRAMHighWaterMark);
+ seq_printf(sfile,
+ "<watermark key=\"mr16\" description=\"system_io_current\" bytes=\"%d\"/>\n",
+ g_IOMemWaterMark);
+ seq_printf(sfile,
+ "<watermark key=\"mr17\" description=\"system_io_high\" bytes=\"%d\"/>\n",
+ g_IOMemHighWaterMark);
+
+#if (PVR_LINUX_MEM_AREA_POOL_MAX_PAGES != 0)
+ seq_printf(sfile,
+ "<watermark key=\"mr18\" description=\"page_pool_current\" bytes=\"%d\"/>\n",
+ PAGES_TO_BYTES(atomic_read(&g_sPagePoolEntryCount)));
+#endif
+ seq_printf(sfile, "</meminfo_header>\n");
+
+#endif
+ return;
+ }
+
+ if (psRecord->eAllocType != DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE)
+ {
+ seq_printf(sfile,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+ "%-16s %-8p %08x %-10d %-5d %-10s %s:%d\n",
+#else
+ "<allocation>\n"
+ "\t<type>%s</type>\n"
+ "\t<cpu_virtual>%-8p</cpu_virtual>\n"
+ "\t<cpu_physical>%08x</cpu_physical>\n"
+ "\t<bytes>%d</bytes>\n"
+ "\t<pid>%d</pid>\n"
+ "\t<private>%s</private>\n"
+ "\t<filename>%s</filename>\n"
+ "\t<line>%d</line>\n"
+ "</allocation>\n",
+#endif
+ DebugMemAllocRecordTypeToString(psRecord->eAllocType),
+ psRecord->pvCpuVAddr,
+ psRecord->ulCpuPAddr,
+ psRecord->ui32Bytes,
+ psRecord->pid,
+ "NULL",
+ psRecord->pszFileName,
+ psRecord->ui32Line);
+ }
+ else
+ {
+ seq_printf(sfile,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+ "%-16s %-8p %08x %-10d %-5d %-10s %s:%d\n",
+#else
+ "<allocation>\n"
+ "\t<type>%s</type>\n"
+ "\t<cpu_virtual>%-8p</cpu_virtual>\n"
+ "\t<cpu_physical>%08x</cpu_physical>\n"
+ "\t<bytes>%d</bytes>\n"
+ "\t<pid>%d</pid>\n"
+ "\t<private>%s</private>\n"
+ "\t<filename>%s</filename>\n"
+ "\t<line>%d</line>\n"
+ "</allocation>\n",
+#endif
+ DebugMemAllocRecordTypeToString(psRecord->eAllocType),
+ psRecord->pvCpuVAddr,
+ psRecord->ulCpuPAddr,
+ psRecord->ui32Bytes,
+ psRecord->pid,
+ KMemCacheNameWrapper(psRecord->pvPrivateData),
+ psRecord->pszFileName,
+ psRecord->ui32Line);
+ }
+}
+
+#endif
+
+
+#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MMAP_AREAS)
+const IMG_CHAR *
+HAPFlagsToString(IMG_UINT32 ui32Flags)
+{
+ static IMG_CHAR szFlags[50];
+ IMG_INT32 i32Pos = 0;
+ IMG_UINT32 ui32CacheTypeIndex, ui32MapTypeIndex;
+ IMG_CHAR *apszCacheTypes[] = {
+ "UNCACHED",
+ "CACHED",
+ "WRITECOMBINE",
+ "UNKNOWN"
+ };
+ IMG_CHAR *apszMapType[] = {
+ "KERNEL_ONLY",
+ "SINGLE_PROCESS",
+ "MULTI_PROCESS",
+ "FROM_EXISTING_PROCESS",
+ "NO_CPU_VIRTUAL",
+ "UNKNOWN"
+ };
+
+
+ if (ui32Flags & PVRSRV_HAP_UNCACHED) {
+ ui32CacheTypeIndex = 0;
+ } else if (ui32Flags & PVRSRV_HAP_CACHED) {
+ ui32CacheTypeIndex = 1;
+ } else if (ui32Flags & PVRSRV_HAP_WRITECOMBINE) {
+ ui32CacheTypeIndex = 2;
+ } else {
+ ui32CacheTypeIndex = 3;
+ PVR_DPF((PVR_DBG_ERROR, "%s: unknown cache type (%u)",
+ __FUNCTION__, (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)));
+ }
+
+
+ if (ui32Flags & PVRSRV_HAP_KERNEL_ONLY) {
+ ui32MapTypeIndex = 0;
+ } else if (ui32Flags & PVRSRV_HAP_SINGLE_PROCESS) {
+ ui32MapTypeIndex = 1;
+ } else if (ui32Flags & PVRSRV_HAP_MULTI_PROCESS) {
+ ui32MapTypeIndex = 2;
+ } else if (ui32Flags & PVRSRV_HAP_FROM_EXISTING_PROCESS) {
+ ui32MapTypeIndex = 3;
+ } else if (ui32Flags & PVRSRV_HAP_NO_CPU_VIRTUAL) {
+ ui32MapTypeIndex = 4;
+ } else {
+ ui32MapTypeIndex = 5;
+ PVR_DPF((PVR_DBG_ERROR, "%s: unknown map type (%u)",
+ __FUNCTION__, (ui32Flags & PVRSRV_HAP_MAPTYPE_MASK)));
+ }
+
+ i32Pos = sprintf(szFlags, "%s|", apszCacheTypes[ui32CacheTypeIndex]);
+ if (i32Pos <= 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: sprintf for cache type %u failed (%d)",
+ __FUNCTION__, ui32CacheTypeIndex, i32Pos));
+ szFlags[0] = 0;
+ }
+ else
+ {
+ sprintf(szFlags + i32Pos, "%s", apszMapType[ui32MapTypeIndex]);
+ }
+
+ return szFlags;
+}
+#endif
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+static IMG_VOID LinuxMMCleanup_MemAreas_ForEachCb(DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord)
+{
+ LinuxMemArea *psLinuxMemArea;
+
+ psLinuxMemArea = psCurrentRecord->psLinuxMemArea;
+ PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: Cleaning up Linux memory area (%p), type=%s, size=%d bytes",
+ __FUNCTION__,
+ psCurrentRecord->psLinuxMemArea,
+ LinuxMemAreaTypeToString(psCurrentRecord->psLinuxMemArea->eAreaType),
+ psCurrentRecord->psLinuxMemArea->ui32ByteSize));
+
+ LinuxMemAreaDeepFree(psLinuxMemArea);
+}
+#endif
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+static IMG_VOID LinuxMMCleanup_MemRecords_ForEachVa(DEBUG_MEM_ALLOC_REC *psCurrentRecord)
+
+{
+
+ PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: Cleaning up memory: "
+ "type=%s "
+ "CpuVAddr=%p "
+ "CpuPAddr=0x%08x, "
+ "allocated @ file=%s,line=%d",
+ __FUNCTION__,
+ DebugMemAllocRecordTypeToString(psCurrentRecord->eAllocType),
+ psCurrentRecord->pvCpuVAddr,
+ psCurrentRecord->ulCpuPAddr,
+ psCurrentRecord->pszFileName,
+ psCurrentRecord->ui32Line));
+ switch (psCurrentRecord->eAllocType)
+ {
+ case DEBUG_MEM_ALLOC_TYPE_KMALLOC:
+ KFreeWrapper(psCurrentRecord->pvCpuVAddr);
+ break;
+ case DEBUG_MEM_ALLOC_TYPE_IOREMAP:
+ IOUnmapWrapper(psCurrentRecord->pvCpuVAddr);
+ break;
+ case DEBUG_MEM_ALLOC_TYPE_IO:
+
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_IO, psCurrentRecord->pvKey, __FILE__, __LINE__);
+ break;
+ case DEBUG_MEM_ALLOC_TYPE_VMALLOC:
+ VFreeWrapper(psCurrentRecord->pvCpuVAddr);
+ break;
+ case DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES:
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES, psCurrentRecord->pvKey, __FILE__, __LINE__);
+ break;
+ case DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE:
+ KMemCacheFreeWrapper(psCurrentRecord->pvPrivateData, psCurrentRecord->pvCpuVAddr);
+ break;
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ case DEBUG_MEM_ALLOC_TYPE_VMAP:
+ VUnmapWrapper(psCurrentRecord->pvCpuVAddr);
+ break;
+#endif
+ default:
+ PVR_ASSERT(0);
+ }
+}
+#endif
+
+
+#if defined(PVR_LINUX_MEM_AREA_POOL_ALLOW_SHRINK)
+static struct shrinker g_sShrinker =
+{
+ .shrink = ShrinkPagePool,
+ .seeks = DEFAULT_SEEKS
+};
+
+static IMG_BOOL g_bShrinkerRegistered;
+#endif
+
+IMG_VOID
+LinuxMMCleanup(IMG_VOID)
+{
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ {
+ if (g_LinuxMemAreaCount)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: There are %d LinuxMemArea allocation unfreed (%d bytes)",
+ __FUNCTION__, g_LinuxMemAreaCount, g_LinuxMemAreaWaterMark));
+ }
+
+ List_DEBUG_LINUX_MEM_AREA_REC_ForEach(g_LinuxMemAreaRecords, LinuxMMCleanup_MemAreas_ForEachCb);
+
+ if (g_SeqFileMemArea)
+ {
+ RemoveProcEntrySeq(g_SeqFileMemArea);
+ }
+ }
+#endif
+
+#if defined(PVR_LINUX_MEM_AREA_POOL_ALLOW_SHRINK)
+ if (g_bShrinkerRegistered)
+ {
+ unregister_shrinker(&g_sShrinker);
+ }
+#endif
+
+
+ FreePagePool();
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ {
+
+
+ List_DEBUG_MEM_ALLOC_REC_ForEach(g_MemoryRecords, LinuxMMCleanup_MemRecords_ForEachVa);
+
+ if (g_SeqFileMemoryRecords)
+ {
+ RemoveProcEntrySeq(g_SeqFileMemoryRecords);
+ }
+ }
+#endif
+
+ if (g_PsLinuxMemAreaCache)
+ {
+ KMemCacheDestroyWrapper(g_PsLinuxMemAreaCache);
+ }
+
+ if (g_PsLinuxPagePoolCache)
+ {
+ KMemCacheDestroyWrapper(g_PsLinuxPagePoolCache);
+ }
+}
+
+PVRSRV_ERROR
+LinuxMMInit(IMG_VOID)
+{
+#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ LinuxInitMutex(&g_sDebugMutex);
+#endif
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ {
+ g_SeqFileMemArea = CreateProcReadEntrySeq(
+ "mem_areas",
+ NULL,
+ ProcSeqNextMemArea,
+ ProcSeqShowMemArea,
+ ProcSeqOff2ElementMemArea,
+ ProcSeqStartstopDebugMutex
+ );
+ if (!g_SeqFileMemArea)
+ {
+ goto failed;
+ }
+ }
+#endif
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ {
+ g_SeqFileMemoryRecords = CreateProcReadEntrySeq(
+ "meminfo",
+ NULL,
+ ProcSeqNextMemoryRecords,
+ ProcSeqShowMemoryRecords,
+ ProcSeqOff2ElementMemoryRecords,
+ ProcSeqStartstopDebugMutex
+ );
+ if (!g_SeqFileMemoryRecords)
+ {
+ goto failed;
+ }
+ }
+#endif
+
+ g_PsLinuxMemAreaCache = KMemCacheCreateWrapper("img-mm", sizeof(LinuxMemArea), 0, 0);
+ if (!g_PsLinuxMemAreaCache)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: failed to allocate mem area kmem_cache", __FUNCTION__));
+ goto failed;
+ }
+
+#if (PVR_LINUX_MEM_AREA_POOL_MAX_PAGES != 0)
+ g_iPagePoolMaxEntries = PVR_LINUX_MEM_AREA_POOL_MAX_PAGES;
+ if (g_iPagePoolMaxEntries <= 0 || g_iPagePoolMaxEntries > INT_MAX/2)
+ {
+ g_iPagePoolMaxEntries = INT_MAX/2;
+ PVR_TRACE(("%s: No limit set for page pool size", __FUNCTION__));
+ }
+ else
+ {
+ PVR_TRACE(("%s: Maximum page pool size: %d", __FUNCTION__, g_iPagePoolMaxEntries));
+ }
+
+ g_PsLinuxPagePoolCache = KMemCacheCreateWrapper("img-mm-pool", sizeof(LinuxPagePoolEntry), 0, 0);
+ if (!g_PsLinuxPagePoolCache)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: failed to allocate page pool kmem_cache", __FUNCTION__));
+ goto failed;
+ }
+#endif
+
+#if defined(PVR_LINUX_MEM_AREA_POOL_ALLOW_SHRINK)
+ register_shrinker(&g_sShrinker);
+ g_bShrinkerRegistered = IMG_TRUE;
+#endif
+
+ return PVRSRV_OK;
+
+failed:
+ LinuxMMCleanup();
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+}
+
diff --git a/drivers/gpu/pvr/mm.h b/drivers/gpu/pvr/mm.h
new file mode 100644
index 0000000..e62bf33
--- /dev/null
+++ b/drivers/gpu/pvr/mm.h
@@ -0,0 +1,384 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __IMG_LINUX_MM_H__
+#define __IMG_LINUX_MM_H__
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#endif
+
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/list.h>
+
+#include <asm/io.h>
+
+#define PHYS_TO_PFN(phys) ((phys) >> PAGE_SHIFT)
+#define PFN_TO_PHYS(pfn) ((pfn) << PAGE_SHIFT)
+
+#define RANGE_TO_PAGES(range) (((range) + (PAGE_SIZE - 1)) >> PAGE_SHIFT)
+
+#define ADDR_TO_PAGE_OFFSET(addr) (((unsigned long)(addr)) & (PAGE_SIZE - 1))
+
+#define PAGES_TO_BYTES(pages) ((pages) << PAGE_SHIFT)
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10))
+#define REMAP_PFN_RANGE(vma, addr, pfn, size, prot) remap_pfn_range(vma, addr, pfn, size, prot)
+#else
+#define REMAP_PFN_RANGE(vma, addr, pfn, size, prot) remap_page_range(vma, addr, PFN_TO_PHYS(pfn), size, prot)
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12))
+#define IO_REMAP_PFN_RANGE(vma, addr, pfn, size, prot) io_remap_pfn_range(vma, addr, pfn, size, prot)
+#else
+#define IO_REMAP_PFN_RANGE(vma, addr, pfn, size, prot) io_remap_page_range(vma, addr, PFN_TO_PHYS(pfn), size, prot)
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+#define VM_INSERT_PAGE(vma, addr, page) vm_insert_page(vma, addr, page)
+#else
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10))
+#define VM_INSERT_PAGE(vma, addr, page) remap_pfn_range(vma, addr, page_to_pfn(page), PAGE_SIZE, vma->vm_page_prot);
+#else
+#define VM_INSERT_PAGE(vma, addr, page) remap_page_range(vma, addr, page_to_phys(page), PAGE_SIZE, vma->vm_page_prot);
+#endif
+#endif
+
+static inline IMG_UINT32 VMallocToPhys(IMG_VOID *pCpuVAddr)
+{
+ return (page_to_phys(vmalloc_to_page(pCpuVAddr)) + ADDR_TO_PAGE_OFFSET(pCpuVAddr));
+
+}
+
+typedef enum {
+ LINUX_MEM_AREA_IOREMAP,
+ LINUX_MEM_AREA_EXTERNAL_KV,
+ LINUX_MEM_AREA_IO,
+ LINUX_MEM_AREA_VMALLOC,
+ LINUX_MEM_AREA_ALLOC_PAGES,
+ LINUX_MEM_AREA_SUB_ALLOC,
+ LINUX_MEM_AREA_ION,
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ LINUX_MEM_AREA_VMAP,
+#endif
+ LINUX_MEM_AREA_TYPE_COUNT
+}LINUX_MEM_AREA_TYPE;
+
+typedef struct _LinuxMemArea LinuxMemArea;
+
+
+struct _LinuxMemArea {
+ LINUX_MEM_AREA_TYPE eAreaType;
+ union _uData
+ {
+ struct _sIORemap
+ {
+
+ IMG_CPU_PHYADDR CPUPhysAddr;
+ IMG_VOID *pvIORemapCookie;
+ }sIORemap;
+ struct _sExternalKV
+ {
+
+ IMG_BOOL bPhysContig;
+ union {
+
+ IMG_SYS_PHYADDR SysPhysAddr;
+ IMG_SYS_PHYADDR *pSysPhysAddr;
+ } uPhysAddr;
+ IMG_VOID *pvExternalKV;
+ }sExternalKV;
+ struct _sIO
+ {
+
+ IMG_CPU_PHYADDR CPUPhysAddr;
+ }sIO;
+ struct _sVmalloc
+ {
+
+ IMG_VOID *pvVmallocAddress;
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ struct page **ppsPageList;
+ IMG_HANDLE hBlockPageList;
+#endif
+ }sVmalloc;
+ struct _sPageList
+ {
+
+ struct page **ppsPageList;
+ IMG_HANDLE hBlockPageList;
+ }sPageList;
+ struct _sIONTilerAlloc
+ {
+
+ IMG_CPU_PHYADDR *pCPUPhysAddrs;
+ struct ion_handle *psIONHandle[2];
+ }sIONTilerAlloc;
+ struct _sSubAlloc
+ {
+
+ LinuxMemArea *psParentLinuxMemArea;
+ IMG_UINT32 ui32ByteOffset;
+ }sSubAlloc;
+ }uData;
+
+ IMG_UINT32 ui32ByteSize;
+
+ IMG_UINT32 ui32AreaFlags;
+
+ IMG_BOOL bMMapRegistered;
+
+ IMG_BOOL bNeedsCacheInvalidate;
+
+
+ struct list_head sMMapItem;
+
+
+ struct list_head sMMapOffsetStructList;
+};
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17))
+typedef kmem_cache_t LinuxKMemCache;
+#else
+typedef struct kmem_cache LinuxKMemCache;
+#endif
+
+
+PVRSRV_ERROR LinuxMMInit(IMG_VOID);
+
+
+IMG_VOID LinuxMMCleanup(IMG_VOID);
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define KMallocWrapper(ui32ByteSize, uFlags) _KMallocWrapper(ui32ByteSize, uFlags, __FILE__, __LINE__)
+#else
+#define KMallocWrapper(ui32ByteSize, uFlags) _KMallocWrapper(ui32ByteSize, uFlags, NULL, 0)
+#endif
+IMG_VOID *_KMallocWrapper(IMG_UINT32 ui32ByteSize, gfp_t uFlags, IMG_CHAR *szFileName, IMG_UINT32 ui32Line);
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define KFreeWrapper(pvCpuVAddr) _KFreeWrapper(pvCpuVAddr, __FILE__, __LINE__)
+#else
+#define KFreeWrapper(pvCpuVAddr) _KFreeWrapper(pvCpuVAddr, NULL, 0)
+#endif
+IMG_VOID _KFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define VMallocWrapper(ui32Bytes, ui32AllocFlags) _VMallocWrapper(ui32Bytes, ui32AllocFlags, __FILE__, __LINE__)
+#else
+#define VMallocWrapper(ui32Bytes, ui32AllocFlags) _VMallocWrapper(ui32Bytes, ui32AllocFlags, NULL, 0)
+#endif
+IMG_VOID *_VMallocWrapper(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AllocFlags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define VFreeWrapper(pvCpuVAddr) _VFreeWrapper(pvCpuVAddr, __FILE__, __LINE__)
+#else
+#define VFreeWrapper(pvCpuVAddr) _VFreeWrapper(pvCpuVAddr, NULL, 0)
+#endif
+IMG_VOID _VFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+
+
+LinuxMemArea *NewVMallocLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags);
+
+
+IMG_VOID FreeVMallocLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags) \
+ _IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags, __FILE__, __LINE__)
+#else
+#define IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags) \
+ _IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags, NULL, 0)
+#endif
+IMG_VOID *_IORemapWrapper(IMG_CPU_PHYADDR BasePAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32MappingFlags,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32Line);
+
+
+LinuxMemArea *NewIORemapLinuxMemArea(IMG_CPU_PHYADDR BasePAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags);
+
+
+IMG_VOID FreeIORemapLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+
+LinuxMemArea *NewExternalKVLinuxMemArea(IMG_SYS_PHYADDR *pBasePAddr, IMG_VOID *pvCPUVAddr, IMG_UINT32 ui32Bytes, IMG_BOOL bPhysContig, IMG_UINT32 ui32AreaFlags);
+
+
+IMG_VOID FreeExternalKVLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define IOUnmapWrapper(pvIORemapCookie) \
+ _IOUnmapWrapper(pvIORemapCookie, __FILE__, __LINE__)
+#else
+#define IOUnmapWrapper(pvIORemapCookie) \
+ _IOUnmapWrapper(pvIORemapCookie, NULL, 0)
+#endif
+IMG_VOID _IOUnmapWrapper(IMG_VOID *pvIORemapCookie, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+
+
+struct page *LinuxMemAreaOffsetToPage(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32ByteOffset);
+
+
+LinuxKMemCache *KMemCacheCreateWrapper(IMG_CHAR *pszName, size_t Size, size_t Align, IMG_UINT32 ui32Flags);
+
+
+IMG_VOID KMemCacheDestroyWrapper(LinuxKMemCache *psCache);
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define KMemCacheAllocWrapper(psCache, Flags) _KMemCacheAllocWrapper(psCache, Flags, __FILE__, __LINE__)
+#else
+#define KMemCacheAllocWrapper(psCache, Flags) _KMemCacheAllocWrapper(psCache, Flags, NULL, 0)
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14))
+IMG_VOID *_KMemCacheAllocWrapper(LinuxKMemCache *psCache, gfp_t Flags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+#else
+IMG_VOID *_KMemCacheAllocWrapper(LinuxKMemCache *psCache, int Flags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+#endif
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define KMemCacheFreeWrapper(psCache, pvObject) _KMemCacheFreeWrapper(psCache, pvObject, __FILE__, __LINE__)
+#else
+#define KMemCacheFreeWrapper(psCache, pvObject) _KMemCacheFreeWrapper(psCache, pvObject, NULL, 0)
+#endif
+IMG_VOID _KMemCacheFreeWrapper(LinuxKMemCache *psCache, IMG_VOID *pvObject, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+
+
+const IMG_CHAR *KMemCacheNameWrapper(LinuxKMemCache *psCache);
+
+
+LinuxMemArea *NewIOLinuxMemArea(IMG_CPU_PHYADDR BasePAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags);
+
+
+IMG_VOID FreeIOLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+
+
+LinuxMemArea *NewAllocPagesLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags);
+
+
+IMG_VOID FreeAllocPagesLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+
+
+#if defined(CONFIG_ION_OMAP)
+
+LinuxMemArea *
+NewIONLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags,
+ IMG_PVOID pvPrivData, IMG_UINT32 ui32PrivDataLength);
+
+
+IMG_VOID FreeIONLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+
+#else
+
+static inline LinuxMemArea *
+NewIONLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags,
+ IMG_PVOID pvPrivData, IMG_UINT32 ui32PrivDataLength)
+{
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+ PVR_UNREFERENCED_PARAMETER(ui32AreaFlags);
+ PVR_UNREFERENCED_PARAMETER(pvPrivData);
+ PVR_UNREFERENCED_PARAMETER(ui32PrivDataLength);
+ BUG();
+ return IMG_NULL;
+}
+
+static inline IMG_VOID FreeIONLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+ PVR_UNREFERENCED_PARAMETER(psLinuxMemArea);
+ BUG();
+}
+
+#endif
+
+
+LinuxMemArea *NewSubLinuxMemArea(LinuxMemArea *psParentLinuxMemArea,
+ IMG_UINT32 ui32ByteOffset,
+ IMG_UINT32 ui32Bytes);
+
+
+IMG_VOID LinuxMemAreaDeepFree(LinuxMemArea *psLinuxMemArea);
+
+
+#if defined(LINUX_MEM_AREAS_DEBUG)
+IMG_VOID LinuxMemAreaRegister(LinuxMemArea *psLinuxMemArea);
+#else
+#define LinuxMemAreaRegister(X)
+#endif
+
+
+IMG_VOID *LinuxMemAreaToCpuVAddr(LinuxMemArea *psLinuxMemArea);
+
+
+IMG_CPU_PHYADDR LinuxMemAreaToCpuPAddr(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32ByteOffset);
+
+
+#define LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32ByteOffset) PHYS_TO_PFN(LinuxMemAreaToCpuPAddr(psLinuxMemArea, ui32ByteOffset).uiAddr)
+
+IMG_BOOL LinuxMemAreaPhysIsContig(LinuxMemArea *psLinuxMemArea);
+
+static inline LinuxMemArea *
+LinuxMemAreaRoot(LinuxMemArea *psLinuxMemArea)
+{
+ if(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC)
+ {
+ return psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea;
+ }
+ else
+ {
+ return psLinuxMemArea;
+ }
+}
+
+
+static inline LINUX_MEM_AREA_TYPE
+LinuxMemAreaRootType(LinuxMemArea *psLinuxMemArea)
+{
+ return LinuxMemAreaRoot(psLinuxMemArea)->eAreaType;
+}
+
+
+const IMG_CHAR *LinuxMemAreaTypeToString(LINUX_MEM_AREA_TYPE eMemAreaType);
+
+
+#if defined(DEBUG) || defined(DEBUG_LINUX_MEM_AREAS)
+const IMG_CHAR *HAPFlagsToString(IMG_UINT32 ui32Flags);
+#endif
+
+#endif
+
diff --git a/drivers/gpu/pvr/mmap.c b/drivers/gpu/pvr/mmap.c
new file mode 100644
index 0000000..a63223c
--- /dev/null
+++ b/drivers/gpu/pvr/mmap.c
@@ -0,0 +1,1220 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#endif
+
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+#include <linux/wrapper.h>
+#endif
+#include <linux/slab.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26))
+#include <linux/highmem.h>
+#endif
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/shmparam.h>
+#include <asm/pgtable.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
+#include <linux/sched.h>
+#include <asm/current.h>
+#endif
+#if defined(SUPPORT_DRI_DRM)
+#include <drm/drmP.h>
+#endif
+
+#include "services_headers.h"
+
+#include "pvrmmap.h"
+#include "mutils.h"
+#include "mmap.h"
+#include "mm.h"
+#include "proc.h"
+#include "mutex.h"
+#include "handle.h"
+#include "perproc.h"
+#include "env_perproc.h"
+#include "bridged_support.h"
+#if defined(SUPPORT_DRI_DRM)
+#include "pvr_drm.h"
+#endif
+
+#if !defined(PVR_SECURE_HANDLES) && !defined (SUPPORT_SID_INTERFACE)
+#error "The mmap code requires PVR_SECURE_HANDLES"
+#endif
+
+PVRSRV_LINUX_MUTEX g_sMMapMutex;
+
+static LinuxKMemCache *g_psMemmapCache = NULL;
+static LIST_HEAD(g_sMMapAreaList);
+static LIST_HEAD(g_sMMapOffsetStructList);
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+static IMG_UINT32 g_ui32RegisteredAreas = 0;
+static IMG_UINT32 g_ui32TotalByteSize = 0;
+#endif
+
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+static struct proc_dir_entry *g_ProcMMap;
+#endif
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+#define MMAP2_PGOFF_RESOLUTION (32-PAGE_SHIFT+12)
+#define RESERVED_PGOFF_BITS 1
+#define MAX_MMAP_HANDLE ((1UL<<(MMAP2_PGOFF_RESOLUTION-RESERVED_PGOFF_BITS))-1)
+
+#define FIRST_PHYSICAL_PFN 0
+#define LAST_PHYSICAL_PFN (FIRST_PHYSICAL_PFN + MAX_MMAP_HANDLE)
+#define FIRST_SPECIAL_PFN (LAST_PHYSICAL_PFN + 1)
+#define LAST_SPECIAL_PFN (FIRST_SPECIAL_PFN + MAX_MMAP_HANDLE)
+
+#else
+
+#if PAGE_SHIFT != 12
+#error This build variant has not yet been made non-4KB page-size aware
+#endif
+
+#if defined(PVR_MMAP_OFFSET_BASE)
+#define FIRST_SPECIAL_PFN PVR_MMAP_OFFSET_BASE
+#else
+#define FIRST_SPECIAL_PFN 0x80000000UL
+#endif
+
+#if defined(PVR_NUM_MMAP_HANDLES)
+#define MAX_MMAP_HANDLE PVR_NUM_MMAP_HANDLES
+#else
+#define MAX_MMAP_HANDLE 0x7fffffffUL
+#endif
+
+#endif
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+static inline IMG_BOOL
+PFNIsPhysical(IMG_UINT32 pfn)
+{
+
+ return ( (pfn <= LAST_PHYSICAL_PFN)) ? IMG_TRUE : IMG_FALSE;
+}
+
+static inline IMG_BOOL
+PFNIsSpecial(IMG_UINT32 pfn)
+{
+
+ return ((pfn >= FIRST_SPECIAL_PFN) ) ? IMG_TRUE : IMG_FALSE;
+}
+#endif
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+static inline IMG_HANDLE
+MMapOffsetToHandle(IMG_UINT32 pfn)
+{
+ if (PFNIsPhysical(pfn))
+ {
+ PVR_ASSERT(PFNIsPhysical(pfn));
+ return IMG_NULL;
+ }
+ return (IMG_HANDLE)(pfn - FIRST_SPECIAL_PFN);
+}
+#endif
+
+static inline IMG_UINT32
+#if defined (SUPPORT_SID_INTERFACE)
+HandleToMMapOffset(IMG_SID hHandle)
+#else
+HandleToMMapOffset(IMG_HANDLE hHandle)
+#endif
+{
+ IMG_UINT32 ulHandle = (IMG_UINT32)hHandle;
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+ if (PFNIsSpecial(ulHandle))
+ {
+ PVR_ASSERT(PFNIsSpecial(ulHandle));
+ return 0;
+ }
+#endif
+ return ulHandle + FIRST_SPECIAL_PFN;
+}
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+static inline IMG_BOOL
+LinuxMemAreaUsesPhysicalMap(LinuxMemArea *psLinuxMemArea)
+{
+ return LinuxMemAreaPhysIsContig(psLinuxMemArea);
+}
+#endif
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+static inline IMG_UINT32
+GetCurrentThreadID(IMG_VOID)
+{
+
+ return (IMG_UINT32)current->pid;
+}
+#endif
+
+static PKV_OFFSET_STRUCT
+CreateOffsetStruct(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32Offset, IMG_UINT32 ui32RealByteSize)
+{
+ PKV_OFFSET_STRUCT psOffsetStruct;
+#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS)
+ const IMG_CHAR *pszName = LinuxMemAreaTypeToString(LinuxMemAreaRootType(psLinuxMemArea));
+#endif
+
+#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS)
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "%s(%s, psLinuxMemArea: 0x%p, ui32AllocFlags: 0x%8x)",
+ __FUNCTION__, pszName, psLinuxMemArea, psLinuxMemArea->ui32AreaFlags));
+#endif
+
+ PVR_ASSERT(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC || LinuxMemAreaRoot(psLinuxMemArea)->eAreaType != LINUX_MEM_AREA_SUB_ALLOC);
+
+ PVR_ASSERT(psLinuxMemArea->bMMapRegistered);
+
+ psOffsetStruct = KMemCacheAllocWrapper(g_psMemmapCache, GFP_KERNEL);
+ if(psOffsetStruct == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRMMapRegisterArea: Couldn't alloc another mapping record from cache"));
+ return IMG_NULL;
+ }
+
+ psOffsetStruct->ui32MMapOffset = ui32Offset;
+
+ psOffsetStruct->psLinuxMemArea = psLinuxMemArea;
+
+ psOffsetStruct->ui32RealByteSize = ui32RealByteSize;
+
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+ psOffsetStruct->ui32TID = GetCurrentThreadID();
+#endif
+ psOffsetStruct->ui32PID = OSGetCurrentProcessIDKM();
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+
+ psOffsetStruct->pszName = pszName;
+#endif
+
+ list_add_tail(&psOffsetStruct->sAreaItem, &psLinuxMemArea->sMMapOffsetStructList);
+
+ return psOffsetStruct;
+}
+
+
+static IMG_VOID
+DestroyOffsetStruct(PKV_OFFSET_STRUCT psOffsetStruct)
+{
+#ifdef DEBUG
+ IMG_CPU_PHYADDR CpuPAddr;
+ CpuPAddr = LinuxMemAreaToCpuPAddr(psOffsetStruct->psLinuxMemArea, 0);
+#endif
+
+ list_del(&psOffsetStruct->sAreaItem);
+
+ if (psOffsetStruct->bOnMMapList)
+ {
+ list_del(&psOffsetStruct->sMMapItem);
+ }
+
+#ifdef DEBUG
+ PVR_DPF((PVR_DBG_MESSAGE, "%s: Table entry: "
+ "psLinuxMemArea=%p, CpuPAddr=0x%08X", __FUNCTION__,
+ psOffsetStruct->psLinuxMemArea,
+ CpuPAddr.uiAddr));
+#endif
+
+ KMemCacheFreeWrapper(g_psMemmapCache, psOffsetStruct);
+}
+
+
+static inline IMG_VOID
+DetermineUsersSizeAndByteOffset(LinuxMemArea *psLinuxMemArea,
+ IMG_UINT32 *pui32RealByteSize,
+ IMG_UINT32 *pui32ByteOffset)
+{
+ IMG_UINT32 ui32PageAlignmentOffset;
+ IMG_CPU_PHYADDR CpuPAddr;
+
+ CpuPAddr = LinuxMemAreaToCpuPAddr(psLinuxMemArea, 0);
+ ui32PageAlignmentOffset = ADDR_TO_PAGE_OFFSET(CpuPAddr.uiAddr);
+
+ *pui32ByteOffset = ui32PageAlignmentOffset;
+
+ *pui32RealByteSize = PAGE_ALIGN(psLinuxMemArea->ui32ByteSize + ui32PageAlignmentOffset);
+}
+
+
+PVRSRV_ERROR
+PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hMHandle,
+#else
+ IMG_HANDLE hMHandle,
+#endif
+ IMG_UINT32 *pui32MMapOffset,
+ IMG_UINT32 *pui32ByteOffset,
+ IMG_UINT32 *pui32RealByteSize,
+ IMG_UINT32 *pui32UserVAddr)
+{
+ LinuxMemArea *psLinuxMemArea;
+ PKV_OFFSET_STRUCT psOffsetStruct;
+ IMG_HANDLE hOSMemHandle;
+ PVRSRV_ERROR eError;
+
+ LinuxLockMutex(&g_sMMapMutex);
+
+ PVR_ASSERT(PVRSRVGetMaxHandle(psPerProc->psHandleBase) <= MAX_MMAP_HANDLE);
+
+ eError = PVRSRVLookupOSMemHandle(psPerProc->psHandleBase, &hOSMemHandle, hMHandle);
+ if (eError != PVRSRV_OK)
+ {
+#if defined (SUPPORT_SID_INTERFACE)
+ PVR_DPF((PVR_DBG_ERROR, "%s: Lookup of handle %x failed", __FUNCTION__, hMHandle));
+#else
+ PVR_DPF((PVR_DBG_ERROR, "%s: Lookup of handle %p failed", __FUNCTION__, hMHandle));
+#endif
+
+ goto exit_unlock;
+ }
+
+ psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+ DetermineUsersSizeAndByteOffset(psLinuxMemArea,
+ pui32RealByteSize,
+ pui32ByteOffset);
+
+
+ list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
+ {
+ if (psPerProc->ui32PID == psOffsetStruct->ui32PID)
+ {
+
+ PVR_ASSERT(*pui32RealByteSize == psOffsetStruct->ui32RealByteSize);
+
+ *pui32MMapOffset = psOffsetStruct->ui32MMapOffset;
+ *pui32UserVAddr = psOffsetStruct->ui32UserVAddr;
+ PVRSRVOffsetStructIncRef(psOffsetStruct);
+
+ eError = PVRSRV_OK;
+ goto exit_unlock;
+ }
+ }
+
+
+ *pui32UserVAddr = 0;
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+ if (LinuxMemAreaUsesPhysicalMap(psLinuxMemArea))
+ {
+ *pui32MMapOffset = LinuxMemAreaToCpuPFN(psLinuxMemArea, 0);
+ PVR_ASSERT(PFNIsPhysical(*pui32MMapOffset));
+ }
+ else
+#endif
+ {
+ *pui32MMapOffset = HandleToMMapOffset(hMHandle);
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+ PVR_ASSERT(PFNIsSpecial(*pui32MMapOffset));
+#endif
+ }
+
+ psOffsetStruct = CreateOffsetStruct(psLinuxMemArea, *pui32MMapOffset, *pui32RealByteSize);
+ if (psOffsetStruct == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto exit_unlock;
+ }
+
+
+ list_add_tail(&psOffsetStruct->sMMapItem, &g_sMMapOffsetStructList);
+
+ psOffsetStruct->bOnMMapList = IMG_TRUE;
+
+ PVRSRVOffsetStructIncRef(psOffsetStruct);
+
+ eError = PVRSRV_OK;
+
+
+
+
+ *pui32MMapOffset = *pui32MMapOffset << (PAGE_SHIFT - 12);
+
+exit_unlock:
+ LinuxUnLockMutex(&g_sMMapMutex);
+
+ return eError;
+}
+
+
+PVRSRV_ERROR
+PVRMMapReleaseMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hMHandle,
+#else
+ IMG_HANDLE hMHandle,
+#endif
+ IMG_BOOL *pbMUnmap,
+ IMG_UINT32 *pui32RealByteSize,
+ IMG_UINT32 *pui32UserVAddr)
+{
+ LinuxMemArea *psLinuxMemArea;
+ PKV_OFFSET_STRUCT psOffsetStruct;
+ IMG_HANDLE hOSMemHandle;
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+
+ LinuxLockMutex(&g_sMMapMutex);
+
+ PVR_ASSERT(PVRSRVGetMaxHandle(psPerProc->psHandleBase) <= MAX_MMAP_HANDLE);
+
+ eError = PVRSRVLookupOSMemHandle(psPerProc->psHandleBase, &hOSMemHandle, hMHandle);
+ if (eError != PVRSRV_OK)
+ {
+#if defined (SUPPORT_SID_INTERFACE)
+ PVR_DPF((PVR_DBG_ERROR, "%s: Lookup of handle %x failed", __FUNCTION__, hMHandle));
+#else
+ PVR_DPF((PVR_DBG_ERROR, "%s: Lookup of handle %p failed", __FUNCTION__, hMHandle));
+#endif
+
+ goto exit_unlock;
+ }
+
+ psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+
+ list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
+ {
+ if (psOffsetStruct->ui32PID == ui32PID)
+ {
+ if (psOffsetStruct->ui32RefCount == 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Attempt to release mmap data with zero reference count for offset struct 0x%p, memory area %p", __FUNCTION__, psOffsetStruct, psLinuxMemArea));
+ eError = PVRSRV_ERROR_STILL_MAPPED;
+ goto exit_unlock;
+ }
+
+ PVRSRVOffsetStructDecRef(psOffsetStruct);
+
+ *pbMUnmap = (IMG_BOOL)((psOffsetStruct->ui32RefCount == 0) && (psOffsetStruct->ui32UserVAddr != 0));
+
+ *pui32UserVAddr = (*pbMUnmap) ? psOffsetStruct->ui32UserVAddr : 0;
+ *pui32RealByteSize = (*pbMUnmap) ? psOffsetStruct->ui32RealByteSize : 0;
+
+ eError = PVRSRV_OK;
+ goto exit_unlock;
+ }
+ }
+
+
+#if defined (SUPPORT_SID_INTERFACE)
+ PVR_DPF((PVR_DBG_ERROR, "%s: Mapping data not found for handle %x (memory area %p)", __FUNCTION__, hMHandle, psLinuxMemArea));
+#else
+ PVR_DPF((PVR_DBG_ERROR, "%s: Mapping data not found for handle %p (memory area %p)", __FUNCTION__, hMHandle, psLinuxMemArea));
+#endif
+
+ eError = PVRSRV_ERROR_MAPPING_NOT_FOUND;
+
+exit_unlock:
+ LinuxUnLockMutex(&g_sMMapMutex);
+
+ return eError;
+}
+
+static inline PKV_OFFSET_STRUCT
+FindOffsetStructByOffset(IMG_UINT32 ui32Offset, IMG_UINT32 ui32RealByteSize)
+{
+ PKV_OFFSET_STRUCT psOffsetStruct;
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+ IMG_UINT32 ui32TID = GetCurrentThreadID();
+#endif
+ IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+
+ list_for_each_entry(psOffsetStruct, &g_sMMapOffsetStructList, sMMapItem)
+ {
+ if (ui32Offset == psOffsetStruct->ui32MMapOffset && ui32RealByteSize == psOffsetStruct->ui32RealByteSize && psOffsetStruct->ui32PID == ui32PID)
+ {
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+
+ if (!PFNIsPhysical(ui32Offset) || psOffsetStruct->ui32TID == ui32TID)
+#endif
+ {
+ return psOffsetStruct;
+ }
+ }
+ }
+
+ return IMG_NULL;
+}
+
+
+static IMG_BOOL
+DoMapToUser(LinuxMemArea *psLinuxMemArea,
+ struct vm_area_struct* ps_vma,
+ IMG_UINT32 ui32ByteOffset)
+{
+ IMG_UINT32 ui32ByteSize;
+
+ if (psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC)
+ {
+ return DoMapToUser(LinuxMemAreaRoot(psLinuxMemArea),
+ ps_vma,
+ psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset + ui32ByteOffset);
+ }
+
+
+ ui32ByteSize = ps_vma->vm_end - ps_vma->vm_start;
+ PVR_ASSERT(ADDR_TO_PAGE_OFFSET(ui32ByteSize) == 0);
+
+#if defined (__sparc__)
+
+#error "SPARC not supported"
+#endif
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+ if (PFNIsPhysical(ps_vma->vm_pgoff))
+ {
+ IMG_INT result;
+
+ PVR_ASSERT(LinuxMemAreaPhysIsContig(psLinuxMemArea));
+ PVR_ASSERT(LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32ByteOffset) == ps_vma->vm_pgoff);
+
+ result = IO_REMAP_PFN_RANGE(ps_vma, ps_vma->vm_start, ps_vma->vm_pgoff, ui32ByteSize, ps_vma->vm_page_prot);
+
+ if(result == 0)
+ {
+ return IMG_TRUE;
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE, "%s: Failed to map contiguous physical address range (%d), trying non-contiguous path", __FUNCTION__, result));
+ }
+#endif
+
+ {
+
+ IMG_UINT32 ulVMAPos;
+ IMG_UINT32 ui32ByteEnd = ui32ByteOffset + ui32ByteSize;
+ IMG_UINT32 ui32PA;
+#if defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+ IMG_BOOL bMixedMap = IMG_FALSE;
+#endif
+
+ for(ui32PA = ui32ByteOffset; ui32PA < ui32ByteEnd; ui32PA += PAGE_SIZE)
+ {
+ IMG_UINT32 pfn = LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32PA);
+
+ if (!pfn_valid(pfn))
+ {
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+ PVR_DPF((PVR_DBG_ERROR,"%s: Error - PFN invalid: 0x%x", __FUNCTION__, pfn));
+ return IMG_FALSE;
+#else
+ bMixedMap = IMG_TRUE;
+#endif
+ }
+ }
+
+#if defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+ if (bMixedMap)
+ {
+ ps_vma->vm_flags |= VM_MIXEDMAP;
+ }
+#endif
+
+ ulVMAPos = ps_vma->vm_start;
+ for(ui32PA = ui32ByteOffset; ui32PA < ui32ByteEnd; ui32PA += PAGE_SIZE)
+ {
+ IMG_UINT32 pfn;
+ IMG_INT result;
+
+ pfn = LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32PA);
+
+#if defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+ if (bMixedMap)
+ {
+ result = vm_insert_mixed(ps_vma, ulVMAPos, pfn);
+ if(result != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: Error - vm_insert_mixed failed (%d)", __FUNCTION__, result));
+ return IMG_FALSE;
+ }
+ }
+ else
+#endif
+ {
+ struct page *psPage;
+
+ PVR_ASSERT(pfn_valid(pfn));
+
+ psPage = pfn_to_page(pfn);
+
+ result = VM_INSERT_PAGE(ps_vma, ulVMAPos, psPage);
+ if(result != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: Error - VM_INSERT_PAGE failed (%d)", __FUNCTION__, result));
+ return IMG_FALSE;
+ }
+ }
+ ulVMAPos += PAGE_SIZE;
+ }
+ }
+
+ return IMG_TRUE;
+}
+
+
+static IMG_VOID
+MMapVOpenNoLock(struct vm_area_struct* ps_vma)
+{
+ PKV_OFFSET_STRUCT psOffsetStruct = (PKV_OFFSET_STRUCT)ps_vma->vm_private_data;
+
+ PVR_ASSERT(psOffsetStruct != IMG_NULL);
+ PVR_ASSERT(!psOffsetStruct->bOnMMapList);
+
+ PVRSRVOffsetStructIncMapped(psOffsetStruct);
+
+ if (psOffsetStruct->ui32Mapped > 1)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "%s: Offset structure 0x%p is being shared across processes (psOffsetStruct->ui32Mapped: %u)", __FUNCTION__, psOffsetStruct, psOffsetStruct->ui32Mapped));
+ PVR_ASSERT((ps_vma->vm_flags & VM_DONTCOPY) == 0);
+ }
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "%s: psLinuxMemArea 0x%p, KVAddress 0x%p MMapOffset %d, ui32Mapped %d",
+ __FUNCTION__,
+ psOffsetStruct->psLinuxMemArea,
+ LinuxMemAreaToCpuVAddr(psOffsetStruct->psLinuxMemArea),
+ psOffsetStruct->ui32MMapOffset,
+ psOffsetStruct->ui32Mapped));
+#endif
+}
+
+
+static void
+MMapVOpen(struct vm_area_struct* ps_vma)
+{
+ LinuxLockMutex(&g_sMMapMutex);
+
+ MMapVOpenNoLock(ps_vma);
+
+ LinuxUnLockMutex(&g_sMMapMutex);
+}
+
+
+static IMG_VOID
+MMapVCloseNoLock(struct vm_area_struct* ps_vma)
+{
+ PKV_OFFSET_STRUCT psOffsetStruct = (PKV_OFFSET_STRUCT)ps_vma->vm_private_data;
+ PVR_ASSERT(psOffsetStruct != IMG_NULL)
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "%s: psLinuxMemArea %p, CpuVAddr %p ui32MMapOffset %d, ui32Mapped %d",
+ __FUNCTION__,
+ psOffsetStruct->psLinuxMemArea,
+ LinuxMemAreaToCpuVAddr(psOffsetStruct->psLinuxMemArea),
+ psOffsetStruct->ui32MMapOffset,
+ psOffsetStruct->ui32Mapped));
+#endif
+
+ PVR_ASSERT(!psOffsetStruct->bOnMMapList);
+ PVRSRVOffsetStructDecMapped(psOffsetStruct);
+ if (psOffsetStruct->ui32Mapped == 0)
+ {
+ if (psOffsetStruct->ui32RefCount != 0)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "%s: psOffsetStruct %p has non-zero reference count (ui32RefCount = %u). User mode address of start of mapping: 0x%x", __FUNCTION__, psOffsetStruct, psOffsetStruct->ui32RefCount, psOffsetStruct->ui32UserVAddr));
+ }
+
+ DestroyOffsetStruct(psOffsetStruct);
+ }
+
+ ps_vma->vm_private_data = NULL;
+}
+
+static void
+MMapVClose(struct vm_area_struct* ps_vma)
+{
+ LinuxLockMutex(&g_sMMapMutex);
+
+ MMapVCloseNoLock(ps_vma);
+
+ LinuxUnLockMutex(&g_sMMapMutex);
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26))
+static int MMapVAccess(struct vm_area_struct *ps_vma, unsigned long addr,
+ void *buf, int len, int write)
+{
+ PKV_OFFSET_STRUCT psOffsetStruct;
+ LinuxMemArea *psLinuxMemArea;
+ unsigned long ulOffset;
+ int iRetVal = -EINVAL;
+ IMG_VOID *pvKernelAddr;
+
+ LinuxLockMutex(&g_sMMapMutex);
+
+ psOffsetStruct = (PKV_OFFSET_STRUCT)ps_vma->vm_private_data;
+ psLinuxMemArea = psOffsetStruct->psLinuxMemArea;
+ ulOffset = addr - ps_vma->vm_start;
+
+ if (ulOffset+len > psLinuxMemArea->ui32ByteSize)
+
+ goto exit_unlock;
+
+ pvKernelAddr = LinuxMemAreaToCpuVAddr(psLinuxMemArea);
+
+ if (pvKernelAddr)
+ {
+ memcpy(buf, pvKernelAddr+ulOffset, len);
+ iRetVal = len;
+ }
+ else
+ {
+ IMG_UINT32 pfn, ui32OffsetInPage;
+ struct page *page;
+
+ pfn = LinuxMemAreaToCpuPFN(psLinuxMemArea, ulOffset);
+
+ if (!pfn_valid(pfn))
+ goto exit_unlock;
+
+ page = pfn_to_page(pfn);
+ ui32OffsetInPage = ADDR_TO_PAGE_OFFSET(ulOffset);
+
+ if (ui32OffsetInPage+len > PAGE_SIZE)
+
+ goto exit_unlock;
+
+ pvKernelAddr = kmap(page);
+ memcpy(buf, pvKernelAddr+ui32OffsetInPage, len);
+ kunmap(page);
+
+ iRetVal = len;
+ }
+
+exit_unlock:
+ LinuxUnLockMutex(&g_sMMapMutex);
+ return iRetVal;
+}
+#endif
+
+static struct vm_operations_struct MMapIOOps =
+{
+ .open=MMapVOpen,
+ .close=MMapVClose,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26))
+ .access=MMapVAccess,
+#endif
+};
+
+
+int
+PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma)
+{
+ LinuxMemArea *psFlushMemArea = IMG_NULL;
+ PKV_OFFSET_STRUCT psOffsetStruct;
+ IMG_UINT32 ui32ByteSize;
+ IMG_VOID *pvBase = IMG_NULL;
+ int iRetVal = 0;
+
+ PVR_UNREFERENCED_PARAMETER(pFile);
+
+ LinuxLockMutex(&g_sMMapMutex);
+
+ ui32ByteSize = ps_vma->vm_end - ps_vma->vm_start;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "%s: Received mmap(2) request with ui32MMapOffset 0x%08lx,"
+ " and ui32ByteSize %d(0x%08x)",
+ __FUNCTION__,
+ ps_vma->vm_pgoff,
+ ui32ByteSize, ui32ByteSize));
+
+ psOffsetStruct = FindOffsetStructByOffset(ps_vma->vm_pgoff, ui32ByteSize);
+ if (psOffsetStruct == IMG_NULL)
+ {
+#if defined(SUPPORT_DRI_DRM)
+ LinuxUnLockMutex(&g_sMMapMutex);
+
+#if !defined(SUPPORT_DRI_DRM_EXT)
+
+ return drm_mmap(pFile, ps_vma);
+#else
+
+ return -ENOENT;
+#endif
+#else
+ PVR_UNREFERENCED_PARAMETER(pFile);
+
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: Attempted to mmap unregistered area at vm_pgoff 0x%lx",
+ __FUNCTION__, ps_vma->vm_pgoff));
+ iRetVal = -EINVAL;
+#endif
+ goto unlock_and_return;
+ }
+
+ list_del(&psOffsetStruct->sMMapItem);
+ psOffsetStruct->bOnMMapList = IMG_FALSE;
+
+
+ if (((ps_vma->vm_flags & VM_WRITE) != 0) &&
+ ((ps_vma->vm_flags & VM_SHARED) == 0))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Cannot mmap non-shareable writable areas", __FUNCTION__));
+ iRetVal = -EINVAL;
+ goto unlock_and_return;
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE, "%s: Mapped psLinuxMemArea 0x%p\n",
+ __FUNCTION__, psOffsetStruct->psLinuxMemArea));
+
+ ps_vma->vm_flags |= VM_RESERVED;
+ ps_vma->vm_flags |= VM_IO;
+
+
+ ps_vma->vm_flags |= VM_DONTEXPAND;
+
+
+ ps_vma->vm_flags |= VM_DONTCOPY;
+
+ ps_vma->vm_private_data = (void *)psOffsetStruct;
+
+ switch(psOffsetStruct->psLinuxMemArea->ui32AreaFlags & PVRSRV_HAP_CACHETYPE_MASK)
+ {
+ case PVRSRV_HAP_CACHED:
+
+ break;
+ case PVRSRV_HAP_WRITECOMBINE:
+ ps_vma->vm_page_prot = PGPROT_WC(ps_vma->vm_page_prot);
+ break;
+ case PVRSRV_HAP_UNCACHED:
+ ps_vma->vm_page_prot = PGPROT_UC(ps_vma->vm_page_prot);
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "%s: unknown cache type", __FUNCTION__));
+ iRetVal = -EINVAL;
+ goto unlock_and_return;
+ }
+
+
+ ps_vma->vm_ops = &MMapIOOps;
+
+ if(!DoMapToUser(psOffsetStruct->psLinuxMemArea, ps_vma, 0))
+ {
+ iRetVal = -EAGAIN;
+ goto unlock_and_return;
+ }
+
+ PVR_ASSERT(psOffsetStruct->ui32UserVAddr == 0)
+
+ psOffsetStruct->ui32UserVAddr = ps_vma->vm_start;
+
+
+ if(psOffsetStruct->psLinuxMemArea->bNeedsCacheInvalidate)
+ {
+ IMG_UINT32 ui32ByteOffset, ui32DummyByteSize;
+
+ DetermineUsersSizeAndByteOffset(psOffsetStruct->psLinuxMemArea,
+ &ui32DummyByteSize,
+ &ui32ByteOffset);
+
+ pvBase = (IMG_VOID *)ps_vma->vm_start + ui32ByteOffset;
+ psFlushMemArea = psOffsetStruct->psLinuxMemArea;
+
+ psOffsetStruct->psLinuxMemArea->bNeedsCacheInvalidate = IMG_FALSE;
+ }
+
+
+ MMapVOpenNoLock(ps_vma);
+
+ PVR_DPF((PVR_DBG_MESSAGE, "%s: Mapped area at offset 0x%08lx\n",
+ __FUNCTION__, ps_vma->vm_pgoff));
+
+unlock_and_return:
+ if (iRetVal != 0 && psOffsetStruct != IMG_NULL)
+ {
+ DestroyOffsetStruct(psOffsetStruct);
+ }
+
+ LinuxUnLockMutex(&g_sMMapMutex);
+
+ if(psFlushMemArea)
+ {
+ OSInvalidateCPUCacheRangeKM(psFlushMemArea, pvBase,
+ psFlushMemArea->ui32ByteSize);
+ }
+
+ return iRetVal;
+}
+
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+
+static void ProcSeqStartstopMMapRegistations(struct seq_file *sfile,IMG_BOOL start)
+{
+ if(start)
+ {
+ LinuxLockMutex(&g_sMMapMutex);
+ }
+ else
+ {
+ LinuxUnLockMutex(&g_sMMapMutex);
+ }
+}
+
+
+static void* ProcSeqOff2ElementMMapRegistrations(struct seq_file *sfile, loff_t off)
+{
+ LinuxMemArea *psLinuxMemArea;
+ if(!off)
+ {
+ return PVR_PROC_SEQ_START_TOKEN;
+ }
+
+ list_for_each_entry(psLinuxMemArea, &g_sMMapAreaList, sMMapItem)
+ {
+ PKV_OFFSET_STRUCT psOffsetStruct;
+
+ list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
+ {
+ off--;
+ if (off == 0)
+ {
+ PVR_ASSERT(psOffsetStruct->psLinuxMemArea == psLinuxMemArea);
+ return (void*)psOffsetStruct;
+ }
+ }
+ }
+ return (void*)0;
+}
+
+static void* ProcSeqNextMMapRegistrations(struct seq_file *sfile,void* el,loff_t off)
+{
+ return ProcSeqOff2ElementMMapRegistrations(sfile,off);
+}
+
+
+static void ProcSeqShowMMapRegistrations(struct seq_file *sfile, void *el)
+{
+ KV_OFFSET_STRUCT *psOffsetStruct = (KV_OFFSET_STRUCT*)el;
+ LinuxMemArea *psLinuxMemArea;
+ IMG_UINT32 ui32RealByteSize;
+ IMG_UINT32 ui32ByteOffset;
+
+ if(el == PVR_PROC_SEQ_START_TOKEN)
+ {
+ seq_printf( sfile,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+ "Allocations registered for mmap: %u\n"
+ "In total these areas correspond to %u bytes\n"
+ "psLinuxMemArea "
+ "UserVAddr "
+ "KernelVAddr "
+ "CpuPAddr "
+ "MMapOffset "
+ "ByteLength "
+ "LinuxMemType "
+ "Pid Name Flags\n",
+#else
+ "<mmap_header>\n"
+ "\t<count>%u</count>\n"
+ "\t<bytes>%u</bytes>\n"
+ "</mmap_header>\n",
+#endif
+ g_ui32RegisteredAreas,
+ g_ui32TotalByteSize
+ );
+ return;
+ }
+
+ psLinuxMemArea = psOffsetStruct->psLinuxMemArea;
+
+ DetermineUsersSizeAndByteOffset(psLinuxMemArea,
+ &ui32RealByteSize,
+ &ui32ByteOffset);
+
+ seq_printf( sfile,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+ "%-8p %08x %-8p %08x %08x %-8d %-24s %-5u %-8s %08x(%s)\n",
+#else
+ "<mmap_record>\n"
+ "\t<pointer>%-8p</pointer>\n"
+ "\t<user_virtual>%-8x</user_virtual>\n"
+ "\t<kernel_virtual>%-8p</kernel_virtual>\n"
+ "\t<cpu_physical>%08x</cpu_physical>\n"
+ "\t<mmap_offset>%08x</mmap_offset>\n"
+ "\t<bytes>%-8d</bytes>\n"
+ "\t<linux_mem_area_type>%-24s</linux_mem_area_type>\n"
+ "\t<pid>%-5u</pid>\n"
+ "\t<name>%-8s</name>\n"
+ "\t<flags>%08x</flags>\n"
+ "\t<flags_string>%s</flags_string>\n"
+ "</mmap_record>\n",
+#endif
+ psLinuxMemArea,
+ psOffsetStruct->ui32UserVAddr + ui32ByteOffset,
+ LinuxMemAreaToCpuVAddr(psLinuxMemArea),
+ LinuxMemAreaToCpuPAddr(psLinuxMemArea,0).uiAddr,
+ psOffsetStruct->ui32MMapOffset,
+ psLinuxMemArea->ui32ByteSize,
+ LinuxMemAreaTypeToString(psLinuxMemArea->eAreaType),
+ psOffsetStruct->ui32PID,
+ psOffsetStruct->pszName,
+ psLinuxMemArea->ui32AreaFlags,
+ HAPFlagsToString(psLinuxMemArea->ui32AreaFlags));
+}
+
+#endif
+
+
+PVRSRV_ERROR
+PVRMMapRegisterArea(LinuxMemArea *psLinuxMemArea)
+{
+ PVRSRV_ERROR eError;
+#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS)
+ const IMG_CHAR *pszName = LinuxMemAreaTypeToString(LinuxMemAreaRootType(psLinuxMemArea));
+#endif
+
+ LinuxLockMutex(&g_sMMapMutex);
+
+#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS)
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "%s(%s, psLinuxMemArea 0x%p, ui32AllocFlags 0x%8x)",
+ __FUNCTION__, pszName, psLinuxMemArea, psLinuxMemArea->ui32AreaFlags));
+#endif
+
+ PVR_ASSERT(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC || LinuxMemAreaRoot(psLinuxMemArea)->eAreaType != LINUX_MEM_AREA_SUB_ALLOC);
+
+
+ if(psLinuxMemArea->bMMapRegistered)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: psLinuxMemArea 0x%p is already registered",
+ __FUNCTION__, psLinuxMemArea));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto exit_unlock;
+ }
+
+ list_add_tail(&psLinuxMemArea->sMMapItem, &g_sMMapAreaList);
+
+ psLinuxMemArea->bMMapRegistered = IMG_TRUE;
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+ g_ui32RegisteredAreas++;
+
+ if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
+ {
+ g_ui32TotalByteSize += psLinuxMemArea->ui32ByteSize;
+ }
+#endif
+
+ eError = PVRSRV_OK;
+
+exit_unlock:
+ LinuxUnLockMutex(&g_sMMapMutex);
+
+ return eError;
+}
+
+
+PVRSRV_ERROR
+PVRMMapRemoveRegisteredArea(LinuxMemArea *psLinuxMemArea)
+{
+ PVRSRV_ERROR eError;
+ PKV_OFFSET_STRUCT psOffsetStruct, psTmpOffsetStruct;
+
+ LinuxLockMutex(&g_sMMapMutex);
+
+ PVR_ASSERT(psLinuxMemArea->bMMapRegistered);
+
+ list_for_each_entry_safe(psOffsetStruct, psTmpOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
+ {
+ if (psOffsetStruct->ui32Mapped != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: psOffsetStruct 0x%p for memory area 0x0x%p is still mapped; psOffsetStruct->ui32Mapped %u", __FUNCTION__, psOffsetStruct, psLinuxMemArea, psOffsetStruct->ui32Mapped));
+ dump_stack();
+ PVRSRVDumpRefCountCCB();
+ eError = PVRSRV_ERROR_STILL_MAPPED;
+ goto exit_unlock;
+ }
+ else
+ {
+
+ PVR_DPF((PVR_DBG_WARNING, "%s: psOffsetStruct 0x%p was never mapped", __FUNCTION__, psOffsetStruct));
+ }
+
+ PVR_ASSERT((psOffsetStruct->ui32Mapped == 0) && psOffsetStruct->bOnMMapList);
+
+ DestroyOffsetStruct(psOffsetStruct);
+ }
+
+ list_del(&psLinuxMemArea->sMMapItem);
+
+ psLinuxMemArea->bMMapRegistered = IMG_FALSE;
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+ g_ui32RegisteredAreas--;
+ if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
+ {
+ g_ui32TotalByteSize -= psLinuxMemArea->ui32ByteSize;
+ }
+#endif
+
+ eError = PVRSRV_OK;
+
+exit_unlock:
+ LinuxUnLockMutex(&g_sMMapMutex);
+ return eError;
+}
+
+
+PVRSRV_ERROR
+LinuxMMapPerProcessConnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc)
+{
+ PVR_UNREFERENCED_PARAMETER(psEnvPerProc);
+
+ return PVRSRV_OK;
+}
+
+IMG_VOID
+LinuxMMapPerProcessDisconnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc)
+{
+ PKV_OFFSET_STRUCT psOffsetStruct, psTmpOffsetStruct;
+ IMG_BOOL bWarn = IMG_FALSE;
+ IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+
+ PVR_UNREFERENCED_PARAMETER(psEnvPerProc);
+
+ LinuxLockMutex(&g_sMMapMutex);
+
+ list_for_each_entry_safe(psOffsetStruct, psTmpOffsetStruct, &g_sMMapOffsetStructList, sMMapItem)
+ {
+ if (psOffsetStruct->ui32PID == ui32PID)
+ {
+ if (!bWarn)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "%s: process has unmapped offset structures. Removing them", __FUNCTION__));
+ bWarn = IMG_TRUE;
+ }
+ PVR_ASSERT(psOffsetStruct->ui32Mapped == 0);
+ PVR_ASSERT(psOffsetStruct->bOnMMapList);
+
+ DestroyOffsetStruct(psOffsetStruct);
+ }
+ }
+
+ LinuxUnLockMutex(&g_sMMapMutex);
+}
+
+
+PVRSRV_ERROR LinuxMMapPerProcessHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase)
+{
+ PVRSRV_ERROR eError;
+
+ eError = PVRSRVSetMaxHandle(psHandleBase, MAX_MMAP_HANDLE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: failed to set handle limit (%d)", __FUNCTION__, eError));
+ return eError;
+ }
+
+ return eError;
+}
+
+
+IMG_VOID
+PVRMMapInit(IMG_VOID)
+{
+ LinuxInitMutex(&g_sMMapMutex);
+
+ g_psMemmapCache = KMemCacheCreateWrapper("img-mmap", sizeof(KV_OFFSET_STRUCT), 0, 0);
+ if (!g_psMemmapCache)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: failed to allocate kmem_cache", __FUNCTION__));
+ goto error;
+ }
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+ g_ProcMMap = CreateProcReadEntrySeq("mmap", NULL,
+ ProcSeqNextMMapRegistrations,
+ ProcSeqShowMMapRegistrations,
+ ProcSeqOff2ElementMMapRegistrations,
+ ProcSeqStartstopMMapRegistations
+ );
+#endif
+ return;
+
+error:
+ PVRMMapCleanup();
+ return;
+}
+
+
+IMG_VOID
+PVRMMapCleanup(IMG_VOID)
+{
+ PVRSRV_ERROR eError;
+
+ if (!list_empty(&g_sMMapAreaList))
+ {
+ LinuxMemArea *psLinuxMemArea, *psTmpMemArea;
+
+ PVR_DPF((PVR_DBG_ERROR, "%s: Memory areas are still registered with MMap", __FUNCTION__));
+
+ PVR_TRACE(("%s: Unregistering memory areas", __FUNCTION__));
+ list_for_each_entry_safe(psLinuxMemArea, psTmpMemArea, &g_sMMapAreaList, sMMapItem)
+ {
+ eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: PVRMMapRemoveRegisteredArea failed (%d)", __FUNCTION__, eError));
+ }
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ LinuxMemAreaDeepFree(psLinuxMemArea);
+ }
+ }
+ PVR_ASSERT(list_empty((&g_sMMapAreaList)));
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+ RemoveProcEntrySeq(g_ProcMMap);
+#endif
+
+ if(g_psMemmapCache)
+ {
+ KMemCacheDestroyWrapper(g_psMemmapCache);
+ g_psMemmapCache = NULL;
+ }
+}
diff --git a/drivers/gpu/pvr/mmap.h b/drivers/gpu/pvr/mmap.h
new file mode 100644
index 0000000..224e652
--- /dev/null
+++ b/drivers/gpu/pvr/mmap.h
@@ -0,0 +1,122 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#if !defined(__MMAP_H__)
+#define __MMAP_H__
+
+#include <linux/mm.h>
+#include <linux/list.h>
+
+#if defined(VM_MIXEDMAP)
+#define PVR_MAKE_ALL_PFNS_SPECIAL
+#endif
+
+#include "perproc.h"
+#include "mm.h"
+
+typedef struct KV_OFFSET_STRUCT_TAG
+{
+
+ IMG_UINT32 ui32Mapped;
+
+
+ IMG_UINT32 ui32MMapOffset;
+
+ IMG_UINT32 ui32RealByteSize;
+
+
+ LinuxMemArea *psLinuxMemArea;
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+
+ IMG_UINT32 ui32TID;
+#endif
+
+
+ IMG_UINT32 ui32PID;
+
+
+ IMG_BOOL bOnMMapList;
+
+
+ IMG_UINT32 ui32RefCount;
+
+
+ IMG_UINT32 ui32UserVAddr;
+
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+ const IMG_CHAR *pszName;
+#endif
+
+
+ struct list_head sMMapItem;
+
+
+ struct list_head sAreaItem;
+}KV_OFFSET_STRUCT, *PKV_OFFSET_STRUCT;
+
+
+
+IMG_VOID PVRMMapInit(IMG_VOID);
+
+
+IMG_VOID PVRMMapCleanup(IMG_VOID);
+
+
+PVRSRV_ERROR PVRMMapRegisterArea(LinuxMemArea *psLinuxMemArea);
+
+
+PVRSRV_ERROR PVRMMapRemoveRegisteredArea(LinuxMemArea *psLinuxMemArea);
+
+
+PVRSRV_ERROR PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hMHandle,
+#else
+ IMG_HANDLE hMHandle,
+#endif
+ IMG_UINT32 *pui32MMapOffset,
+ IMG_UINT32 *pui32ByteOffset,
+ IMG_UINT32 *pui32RealByteSize,
+ IMG_UINT32 *pui32UserVAddr);
+
+PVRSRV_ERROR
+PVRMMapReleaseMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hMHandle,
+#else
+ IMG_HANDLE hMHandle,
+#endif
+ IMG_BOOL *pbMUnmap,
+ IMG_UINT32 *pui32RealByteSize,
+ IMG_UINT32 *pui32UserVAddr);
+
+int PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma);
+
+
+#endif
+
diff --git a/drivers/gpu/pvr/module.c b/drivers/gpu/pvr/module.c
new file mode 100644
index 0000000..37eb5cc
--- /dev/null
+++ b/drivers/gpu/pvr/module.c
@@ -0,0 +1,854 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#endif
+
+#if defined(SUPPORT_DRI_DRM) && !defined(SUPPORT_DRI_DRM_PLUGIN)
+#define PVR_MOD_STATIC
+#else
+
+ #if defined(LDM_PLATFORM)
+ #define PVR_LDM_PLATFORM_MODULE
+ #define PVR_LDM_MODULE
+ #else
+ #if defined(LDM_PCI)
+ #define PVR_LDM_PCI_MODULE
+ #define PVR_LDM_MODULE
+ #endif
+ #endif
+#define PVR_MOD_STATIC static
+#endif
+
+#if defined(PVR_LDM_PLATFORM_PRE_REGISTERED)
+#if !defined(NO_HARDWARE)
+#define PVR_USE_PRE_REGISTERED_PLATFORM_DEV
+#endif
+#endif
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+
+#if defined(SUPPORT_DRI_DRM)
+#include <drm/drmP.h>
+#if defined(PVR_SECURE_DRM_AUTH_EXPORT)
+#include "env_perproc.h"
+#endif
+#endif
+
+#if defined(PVR_LDM_PLATFORM_MODULE)
+#include <linux/platform_device.h>
+#endif
+
+#if defined(PVR_LDM_PCI_MODULE)
+#include <linux/pci.h>
+#endif
+
+#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
+#include <asm/uaccess.h>
+#endif
+
+#if defined(PVR_LDM_MODULE) || defined(PVR_DRI_DRM_PLATFORM_DEV)
+#include <asm/atomic.h>
+#endif
+
+#include "img_defs.h"
+#include "services.h"
+#include "kerneldisplay.h"
+#include "kernelbuffer.h"
+#include "syscommon.h"
+#include "pvrmmap.h"
+#include "mutils.h"
+#include "mm.h"
+#include "mmap.h"
+#include "mutex.h"
+#include "pvr_debug.h"
+#include "srvkm.h"
+#include "perproc.h"
+#include "handle.h"
+#include "pvr_bridge_km.h"
+#include "proc.h"
+#include "pvrmodule.h"
+#include "private_data.h"
+#include "lock.h"
+#include "linkage.h"
+#include "buffer_manager.h"
+
+#if defined(SUPPORT_DRI_DRM)
+#include "pvr_drm.h"
+#endif
+#if defined(PVR_LDM_MODULE)
+#define DRVNAME PVR_LDM_DRIVER_REGISTRATION_NAME
+#endif
+#define DEVNAME PVRSRV_MODNAME
+
+#if defined(SUPPORT_DRI_DRM)
+#define PRIVATE_DATA(pFile) ((pFile)->driver_priv)
+#else
+#define PRIVATE_DATA(pFile) ((pFile)->private_data)
+#endif
+
+MODULE_SUPPORTED_DEVICE(DEVNAME);
+
+#if defined(PVRSRV_NEED_PVR_DPF)
+#include <linux/moduleparam.h>
+extern IMG_UINT32 gPVRDebugLevel;
+module_param(gPVRDebugLevel, uint, 0644);
+MODULE_PARM_DESC(gPVRDebugLevel, "Sets the level of debug output (default 0x7)");
+#endif
+
+#if defined(CONFIG_ION_OMAP)
+#include <linux/ion.h>
+#include <linux/omap_ion.h>
+extern struct ion_device *omap_ion_device;
+struct ion_client *gpsIONClient;
+EXPORT_SYMBOL(gpsIONClient);
+#endif
+
+
+EXPORT_SYMBOL(PVRGetDisplayClassJTable);
+EXPORT_SYMBOL(PVRGetBufferClassJTable);
+
+#if defined(PVR_LDM_MODULE) && !defined(SUPPORT_DRI_DRM)
+static struct class *psPvrClass;
+#endif
+
+#if !defined(SUPPORT_DRI_DRM)
+static int AssignedMajorNumber;
+
+static int PVRSRVOpen(struct inode* pInode, struct file* pFile);
+static int PVRSRVRelease(struct inode* pInode, struct file* pFile);
+
+static struct file_operations pvrsrv_fops =
+{
+ .owner=THIS_MODULE,
+ .unlocked_ioctl = PVRSRV_BridgeDispatchKM,
+ .open=PVRSRVOpen,
+ .release=PVRSRVRelease,
+ .mmap=PVRMMap,
+};
+#endif
+
+PVRSRV_LINUX_MUTEX gPVRSRVLock;
+
+IMG_UINT32 gui32ReleasePID;
+
+#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
+static IMG_UINT32 gPVRPowerLevel;
+#endif
+
+#if defined(PVR_LDM_MODULE)
+
+#if defined(PVR_LDM_PLATFORM_MODULE)
+#define LDM_DEV struct platform_device
+#define LDM_DRV struct platform_driver
+#endif
+
+#if defined(PVR_LDM_PCI_MODULE)
+#define LDM_DEV struct pci_dev
+#define LDM_DRV struct pci_driver
+#endif
+#if defined(PVR_LDM_PLATFORM_MODULE)
+static int PVRSRVDriverRemove(LDM_DEV *device);
+static int PVRSRVDriverProbe(LDM_DEV *device);
+#endif
+#if defined(PVR_LDM_PCI_MODULE)
+static void PVRSRVDriverRemove(LDM_DEV *device);
+static int PVRSRVDriverProbe(LDM_DEV *device, const struct pci_device_id *id);
+#endif
+static int PVRSRVDriverSuspend(LDM_DEV *device, pm_message_t state);
+static void PVRSRVDriverShutdown(LDM_DEV *device);
+static int PVRSRVDriverResume(LDM_DEV *device);
+
+#if defined(PVR_LDM_PCI_MODULE)
+struct pci_device_id powervr_id_table[] __devinitdata = {
+ {PCI_DEVICE(SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV_DEVICE_ID)},
+#if defined (SYS_SGX_DEV1_DEVICE_ID)
+ {PCI_DEVICE(SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV1_DEVICE_ID)},
+#endif
+ {0}
+};
+
+MODULE_DEVICE_TABLE(pci, powervr_id_table);
+#endif
+
+#if defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV)
+static struct platform_device_id powervr_id_table[] __devinitdata = {
+ {SYS_SGX_DEV_NAME, 0},
+ {}
+};
+#endif
+
+static LDM_DRV powervr_driver = {
+#if defined(PVR_LDM_PLATFORM_MODULE)
+ .driver = {
+ .name = DRVNAME,
+ },
+#endif
+#if defined(PVR_LDM_PCI_MODULE)
+ .name = DRVNAME,
+#endif
+#if defined(PVR_LDM_PCI_MODULE) || defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV)
+ .id_table = powervr_id_table,
+#endif
+ .probe = PVRSRVDriverProbe,
+#if defined(PVR_LDM_PLATFORM_MODULE)
+ .remove = PVRSRVDriverRemove,
+#endif
+#if defined(PVR_LDM_PCI_MODULE)
+ .remove = __devexit_p(PVRSRVDriverRemove),
+#endif
+ .suspend = PVRSRVDriverSuspend,
+ .resume = PVRSRVDriverResume,
+ .shutdown = PVRSRVDriverShutdown,
+};
+
+LDM_DEV *gpsPVRLDMDev;
+
+#if defined(MODULE) && defined(PVR_LDM_PLATFORM_MODULE) && \
+ !defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV)
+static void PVRSRVDeviceRelease(struct device unref__ *pDevice)
+{
+}
+
+static struct platform_device powervr_device = {
+ .name = DEVNAME,
+ .id = -1,
+ .dev = {
+ .release = PVRSRVDeviceRelease
+ }
+};
+#endif
+
+#if defined(PVR_LDM_PLATFORM_MODULE)
+static int PVRSRVDriverProbe(LDM_DEV *pDevice)
+#endif
+#if defined(PVR_LDM_PCI_MODULE)
+static int __devinit PVRSRVDriverProbe(LDM_DEV *pDevice, const struct pci_device_id *id)
+#endif
+{
+ SYS_DATA *psSysData;
+
+ PVR_TRACE(("PVRSRVDriverProbe(pDevice=%p)", pDevice));
+
+#if 0
+
+ if (PerDeviceSysInitialise((IMG_PVOID)pDevice) != PVRSRV_OK)
+ {
+ return -EINVAL;
+ }
+#endif
+
+ psSysData = SysAcquireDataNoCheck();
+ if (psSysData == IMG_NULL)
+ {
+ gpsPVRLDMDev = pDevice;
+ if (SysInitialise() != PVRSRV_OK)
+ {
+ return -ENODEV;
+ }
+ }
+
+#if defined(CONFIG_ION_OMAP)
+ gpsIONClient = ion_client_create(omap_ion_device,
+ 1 << ION_HEAP_TYPE_CARVEOUT |
+ 1 << OMAP_ION_HEAP_TYPE_TILER,
+ "pvr");
+ if (IS_ERR_OR_NULL(gpsIONClient))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVDriverProbe: Couldn't create ion client"));
+ return PTR_ERR(gpsIONClient);
+ }
+#endif
+
+ return 0;
+}
+
+
+#if defined (PVR_LDM_PLATFORM_MODULE)
+static int PVRSRVDriverRemove(LDM_DEV *pDevice)
+#endif
+#if defined(PVR_LDM_PCI_MODULE)
+static void __devexit PVRSRVDriverRemove(LDM_DEV *pDevice)
+#endif
+{
+ SYS_DATA *psSysData;
+
+ PVR_TRACE(("PVRSRVDriverRemove(pDevice=%p)", pDevice));
+
+#if defined(CONFIG_ION_OMAP)
+ ion_client_destroy(gpsIONClient);
+ gpsIONClient = IMG_NULL;
+#endif
+
+ SysAcquireData(&psSysData);
+
+#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
+ if (gPVRPowerLevel != 0)
+ {
+ if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) == PVRSRV_OK)
+ {
+ gPVRPowerLevel = 0;
+ }
+ }
+#endif
+ (void) SysDeinitialise(psSysData);
+
+ gpsPVRLDMDev = IMG_NULL;
+
+#if 0
+ if (PerDeviceSysDeInitialise((IMG_PVOID)pDevice) != PVRSRV_OK)
+ {
+ return -EINVAL;
+ }
+#endif
+
+#if defined (PVR_LDM_PLATFORM_MODULE)
+ return 0;
+#endif
+#if defined (PVR_LDM_PCI_MODULE)
+ return;
+#endif
+}
+#endif
+
+
+#if defined(PVR_LDM_MODULE) || defined(PVR_DRI_DRM_PLATFORM_DEV)
+#if defined(SUPPORT_DRI_DRM) && !defined(PVR_DRI_DRM_PLATFORM_DEV) && \
+ !defined(SUPPORT_DRI_DRM_PLUGIN)
+void PVRSRVDriverShutdown(struct drm_device *pDevice)
+#else
+PVR_MOD_STATIC void PVRSRVDriverShutdown(LDM_DEV *pDevice)
+#endif
+{
+ static atomic_t sDriverIsShutdown = ATOMIC_INIT(1);
+
+ PVR_TRACE(("PVRSRVDriverShutdown(pDevice=%p)", pDevice));
+
+ if (atomic_dec_and_test(&sDriverIsShutdown))
+ {
+
+ LinuxLockMutex(&gPVRSRVLock);
+
+ (void) PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3);
+ }
+}
+
+#endif
+
+
+#if defined(PVR_LDM_MODULE) || defined(SUPPORT_DRI_DRM)
+#if defined(SUPPORT_DRI_DRM) && !defined(PVR_DRI_DRM_PLATFORM_DEV) && \
+ !defined(SUPPORT_DRI_DRM_PLUGIN)
+int PVRSRVDriverSuspend(struct drm_device *pDevice, pm_message_t state)
+#else
+PVR_MOD_STATIC int PVRSRVDriverSuspend(LDM_DEV *pDevice, pm_message_t state)
+#endif
+{
+#if !(defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) && !defined(SUPPORT_DRI_DRM))
+ PVR_TRACE(( "PVRSRVDriverSuspend(pDevice=%p)", pDevice));
+
+ if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3) != PVRSRV_OK)
+ {
+ return -EINVAL;
+ }
+#endif
+ return 0;
+}
+
+
+#if defined(SUPPORT_DRI_DRM) && !defined(PVR_DRI_DRM_PLATFORM_DEV) && \
+ !defined(SUPPORT_DRI_DRM_PLUGIN)
+int PVRSRVDriverResume(struct drm_device *pDevice)
+#else
+PVR_MOD_STATIC int PVRSRVDriverResume(LDM_DEV *pDevice)
+#endif
+{
+#if !(defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) && !defined(SUPPORT_DRI_DRM))
+ PVR_TRACE(("PVRSRVDriverResume(pDevice=%p)", pDevice));
+
+ if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) != PVRSRV_OK)
+ {
+ return -EINVAL;
+ }
+#endif
+ return 0;
+}
+#endif
+
+
+#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) && !defined(SUPPORT_DRI_DRM)
+IMG_INT PVRProcSetPowerLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data)
+{
+ IMG_CHAR data_buffer[2];
+ IMG_UINT32 PVRPowerLevel;
+
+ if (count != sizeof(data_buffer))
+ {
+ return -EINVAL;
+ }
+ else
+ {
+ if (copy_from_user(data_buffer, buffer, count))
+ return -EINVAL;
+ if (data_buffer[count - 1] != '\n')
+ return -EINVAL;
+ PVRPowerLevel = data_buffer[0] - '0';
+ if (PVRPowerLevel != gPVRPowerLevel)
+ {
+ if (PVRPowerLevel != 0)
+ {
+ if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3) != PVRSRV_OK)
+ {
+ return -EINVAL;
+ }
+ }
+ else
+ {
+ if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) != PVRSRV_OK)
+ {
+ return -EINVAL;
+ }
+ }
+
+ gPVRPowerLevel = PVRPowerLevel;
+ }
+ }
+ return (count);
+}
+
+void ProcSeqShowPowerLevel(struct seq_file *sfile,void* el)
+{
+ seq_printf(sfile, "%lu\n", gPVRPowerLevel);
+}
+
+#endif
+
+#if defined(SUPPORT_DRI_DRM)
+int PVRSRVOpen(struct drm_device unref__ *dev, struct drm_file *pFile)
+#else
+static int PVRSRVOpen(struct inode unref__ * pInode, struct file *pFile)
+#endif
+{
+ PVRSRV_FILE_PRIVATE_DATA *psPrivateData;
+ IMG_HANDLE hBlockAlloc;
+ int iRet = -ENOMEM;
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32PID;
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+ PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc;
+#endif
+
+ LinuxLockMutex(&gPVRSRVLock);
+
+ ui32PID = OSGetCurrentProcessIDKM();
+
+ if (PVRSRVProcessConnect(ui32PID, 0) != PVRSRV_OK)
+ goto err_unlock;
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+ psEnvPerProc = PVRSRVPerProcessPrivateData(ui32PID);
+ if (psEnvPerProc == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: No per-process private data", __FUNCTION__));
+ goto err_unlock;
+ }
+#endif
+
+ eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_FILE_PRIVATE_DATA),
+ (IMG_PVOID *)&psPrivateData,
+ &hBlockAlloc,
+ "File Private Data");
+
+ if(eError != PVRSRV_OK)
+ goto err_unlock;
+
+#if defined (SUPPORT_SID_INTERFACE)
+ psPrivateData->hKernelMemInfo = 0;
+#else
+ psPrivateData->hKernelMemInfo = NULL;
+#endif
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+ psPrivateData->psDRMFile = pFile;
+
+ list_add_tail(&psPrivateData->sDRMAuthListItem, &psEnvPerProc->sDRMAuthListHead);
+#endif
+ psPrivateData->ui32OpenPID = ui32PID;
+ psPrivateData->hBlockAlloc = hBlockAlloc;
+ PRIVATE_DATA(pFile) = psPrivateData;
+ iRet = 0;
+err_unlock:
+ LinuxUnLockMutex(&gPVRSRVLock);
+ return iRet;
+}
+
+
+#if defined(SUPPORT_DRI_DRM)
+void PVRSRVRelease(void *pvPrivData)
+#else
+static int PVRSRVRelease(struct inode unref__ * pInode, struct file *pFile)
+#endif
+{
+ PVRSRV_FILE_PRIVATE_DATA *psPrivateData;
+ int err = 0;
+
+ LinuxLockMutex(&gPVRSRVLock);
+
+#if defined(SUPPORT_DRI_DRM)
+ psPrivateData = (PVRSRV_FILE_PRIVATE_DATA *)pvPrivData;
+#else
+ psPrivateData = PRIVATE_DATA(pFile);
+#endif
+ if (psPrivateData != IMG_NULL)
+ {
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+ list_del(&psPrivateData->sDRMAuthListItem);
+#endif
+
+ if(psPrivateData->hKernelMemInfo)
+ {
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+
+ if(PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+ (IMG_PVOID *)&psKernelMemInfo,
+ psPrivateData->hKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to look up export handle", __FUNCTION__));
+ err = -EFAULT;
+ goto err_unlock;
+ }
+
+
+ if (psKernelMemInfo->sShareMemWorkaround.bInUse)
+ {
+ BM_XProcIndexRelease(psKernelMemInfo->sShareMemWorkaround.ui32ShareIndex);
+ }
+
+
+ if(FreeMemCallBackCommon(psKernelMemInfo, 0,
+ PVRSRV_FREE_CALLBACK_ORIGIN_EXTERNAL) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: FreeMemCallBackCommon failed", __FUNCTION__));
+ err = -EFAULT;
+ goto err_unlock;
+ }
+ }
+
+
+ gui32ReleasePID = psPrivateData->ui32OpenPID;
+ PVRSRVProcessDisconnect(psPrivateData->ui32OpenPID);
+ gui32ReleasePID = 0;
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_FILE_PRIVATE_DATA),
+ psPrivateData, psPrivateData->hBlockAlloc);
+
+#if !defined(SUPPORT_DRI_DRM)
+ PRIVATE_DATA(pFile) = IMG_NULL;
+#endif
+ }
+
+err_unlock:
+ LinuxUnLockMutex(&gPVRSRVLock);
+#if defined(SUPPORT_DRI_DRM)
+ return;
+#else
+ return err;
+#endif
+}
+
+
+#if defined(SUPPORT_DRI_DRM)
+int PVRCore_Init(void)
+#else
+static int __init PVRCore_Init(void)
+#endif
+{
+ int error;
+#if !defined(PVR_LDM_MODULE)
+ PVRSRV_ERROR eError;
+#else
+#if !defined(SUPPORT_DRI_DRM)
+ struct device *psDev;
+#endif
+#endif
+
+#if !defined(SUPPORT_DRI_DRM)
+
+ PVRDPFInit();
+#endif
+ PVR_TRACE(("PVRCore_Init"));
+
+ LinuxInitMutex(&gPVRSRVLock);
+
+ if (CreateProcEntries ())
+ {
+ error = -ENOMEM;
+ return error;
+ }
+
+ if (PVROSFuncInit() != PVRSRV_OK)
+ {
+ error = -ENOMEM;
+ goto init_failed;
+ }
+
+ PVRLinuxMUtilsInit();
+
+ if(LinuxMMInit() != PVRSRV_OK)
+ {
+ error = -ENOMEM;
+ goto init_failed;
+ }
+
+ LinuxBridgeInit();
+
+ PVRMMapInit();
+
+#if defined(PVR_LDM_MODULE)
+
+#if defined(PVR_LDM_PLATFORM_MODULE) || defined(SUPPORT_DRI_DRM_PLUGIN)
+ if ((error = platform_driver_register(&powervr_driver)) != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to register platform driver (%d)", error));
+
+ goto init_failed;
+ }
+
+#if defined(MODULE) && !defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV)
+ if ((error = platform_device_register(&powervr_device)) != 0)
+ {
+ platform_driver_unregister(&powervr_driver);
+
+ PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to register platform device (%d)", error));
+
+ goto init_failed;
+ }
+#endif
+#endif
+
+#if defined(PVR_LDM_PCI_MODULE)
+ if ((error = pci_register_driver(&powervr_driver)) != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to register PCI driver (%d)", error));
+
+ goto init_failed;
+ }
+#endif
+#endif
+
+#if !defined(PVR_LDM_MODULE)
+
+ if ((eError = SysInitialise()) != PVRSRV_OK)
+ {
+ error = -ENODEV;
+#if defined(TCF_REV) && (TCF_REV == 110)
+ if(eError == PVRSRV_ERROR_NOT_SUPPORTED)
+ {
+ printk("\nAtlas wrapper (FPGA image) version mismatch");
+ error = -ENODEV;
+ }
+#endif
+ goto init_failed;
+ }
+#endif
+
+#if !defined(SUPPORT_DRI_DRM)
+ AssignedMajorNumber = register_chrdev(0, DEVNAME, &pvrsrv_fops);
+
+ if (AssignedMajorNumber <= 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to get major number"));
+
+ error = -EBUSY;
+ goto sys_deinit;
+ }
+
+ PVR_TRACE(("PVRCore_Init: major device %d", AssignedMajorNumber));
+
+#if defined(PVR_LDM_MODULE)
+
+ psPvrClass = class_create(THIS_MODULE, "pvr");
+
+ if (IS_ERR(psPvrClass))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to create class (%ld)", PTR_ERR(psPvrClass)));
+ error = -EBUSY;
+ goto unregister_device;
+ }
+
+ psDev = device_create(psPvrClass, NULL, MKDEV(AssignedMajorNumber, 0),
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26))
+ NULL,
+#endif
+ DEVNAME);
+ if (IS_ERR(psDev))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to create device (%ld)", PTR_ERR(psDev)));
+ error = -EBUSY;
+ goto destroy_class;
+ }
+#endif
+#endif
+
+ return 0;
+
+#if !defined(SUPPORT_DRI_DRM)
+#if defined(PVR_LDM_MODULE)
+destroy_class:
+ class_destroy(psPvrClass);
+unregister_device:
+ unregister_chrdev((IMG_UINT)AssignedMajorNumber, DEVNAME);
+#endif
+sys_deinit:
+#endif
+#if defined(PVR_LDM_MODULE)
+#if defined(PVR_LDM_PCI_MODULE)
+ pci_unregister_driver(&powervr_driver);
+#endif
+
+#if defined (PVR_LDM_PLATFORM_MODULE)
+#if defined(MODULE) && !defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV)
+ platform_device_unregister(&powervr_device);
+#endif
+ platform_driver_unregister(&powervr_driver);
+#endif
+
+#else
+
+ {
+ SYS_DATA *psSysData;
+
+ psSysData = SysAcquireDataNoCheck();
+ if (psSysData != IMG_NULL)
+ {
+ (void) SysDeinitialise(psSysData);
+ }
+ }
+#endif
+init_failed:
+ PVRMMapCleanup();
+ LinuxMMCleanup();
+ LinuxBridgeDeInit();
+ PVROSFuncDeInit();
+ RemoveProcEntries();
+
+ return error;
+
+}
+
+
+#if defined(SUPPORT_DRI_DRM)
+void PVRCore_Cleanup(void)
+#else
+static void __exit PVRCore_Cleanup(void)
+#endif
+{
+#if !defined(PVR_LDM_MODULE)
+ SYS_DATA *psSysData;
+#endif
+ PVR_TRACE(("PVRCore_Cleanup"));
+
+#if !defined(PVR_LDM_MODULE)
+ SysAcquireData(&psSysData);
+#endif
+
+#if !defined(SUPPORT_DRI_DRM)
+
+#if defined(PVR_LDM_MODULE)
+ device_destroy(psPvrClass, MKDEV(AssignedMajorNumber, 0));
+ class_destroy(psPvrClass);
+#endif
+
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
+ if (
+#endif
+ unregister_chrdev((IMG_UINT)AssignedMajorNumber, DEVNAME)
+#if !(LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
+ ;
+#else
+ )
+ {
+ PVR_DPF((PVR_DBG_ERROR," can't unregister device major %d", AssignedMajorNumber));
+ }
+#endif
+#endif
+
+#if defined(PVR_LDM_MODULE)
+
+#if defined(PVR_LDM_PCI_MODULE)
+ pci_unregister_driver(&powervr_driver);
+#endif
+
+#if defined (PVR_LDM_PLATFORM_MODULE)
+#if defined(MODULE) && !defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV)
+ platform_device_unregister(&powervr_device);
+#endif
+ platform_driver_unregister(&powervr_driver);
+#endif
+
+#else
+#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
+ if (gPVRPowerLevel != 0)
+ {
+ if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) == PVRSRV_OK)
+ {
+ gPVRPowerLevel = 0;
+ }
+ }
+#endif
+
+ (void) SysDeinitialise(psSysData);
+#endif
+
+ PVRMMapCleanup();
+
+ LinuxMMCleanup();
+
+ LinuxBridgeDeInit();
+
+ PVROSFuncDeInit();
+
+ RemoveProcEntries();
+
+ PVR_TRACE(("PVRCore_Cleanup: unloading"));
+}
+
+#if !defined(SUPPORT_DRI_DRM)
+module_init(PVRCore_Init);
+module_exit(PVRCore_Cleanup);
+#endif
diff --git a/drivers/gpu/pvr/mutex.c b/drivers/gpu/pvr/mutex.c
new file mode 100644
index 0000000..742fa03
--- /dev/null
+++ b/drivers/gpu/pvr/mutex.c
@@ -0,0 +1,136 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include <linux/version.h>
+#include <linux/errno.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+#include <linux/mutex.h>
+#else
+#include <asm/semaphore.h>
+#endif
+#include <linux/module.h>
+
+#include <img_defs.h>
+#include <services.h>
+
+#include "mutex.h"
+
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+
+IMG_VOID LinuxInitMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+ mutex_init(psPVRSRVMutex);
+}
+
+IMG_VOID LinuxLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+ mutex_lock(psPVRSRVMutex);
+}
+
+PVRSRV_ERROR LinuxLockMutexInterruptible(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+ if(mutex_lock_interruptible(psPVRSRVMutex) == -EINTR)
+ {
+ return PVRSRV_ERROR_MUTEX_INTERRUPTIBLE_ERROR;
+ }
+ else
+ {
+ return PVRSRV_OK;
+ }
+}
+
+IMG_INT32 LinuxTryLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+ return mutex_trylock(psPVRSRVMutex);
+}
+
+IMG_VOID LinuxUnLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+ mutex_unlock(psPVRSRVMutex);
+}
+
+IMG_BOOL LinuxIsLockedMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+ return (mutex_is_locked(psPVRSRVMutex)) ? IMG_TRUE : IMG_FALSE;
+}
+
+
+#else
+
+
+IMG_VOID LinuxInitMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+ init_MUTEX(&psPVRSRVMutex->sSemaphore);
+ atomic_set(&psPVRSRVMutex->Count, 0);
+}
+
+IMG_VOID LinuxLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+ down(&psPVRSRVMutex->sSemaphore);
+ atomic_dec(&psPVRSRVMutex->Count);
+}
+
+PVRSRV_ERROR LinuxLockMutexInterruptible(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+ if(down_interruptible(&psPVRSRVMutex->sSemaphore) == -EINTR)
+ {
+
+ return PVRSRV_ERROR_MUTEX_INTERRUPTIBLE_ERROR;
+ }else{
+ atomic_dec(&psPVRSRVMutex->Count);
+ return PVRSRV_OK;
+ }
+}
+
+IMG_INT32 LinuxTryLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+ IMG_INT32 Status = down_trylock(&psPVRSRVMutex->sSemaphore);
+ if(Status == 0)
+ {
+ atomic_dec(&psPVRSRVMutex->Count);
+ }
+
+ return Status;
+}
+
+IMG_VOID LinuxUnLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+ atomic_inc(&psPVRSRVMutex->Count);
+ up(&psPVRSRVMutex->sSemaphore);
+}
+
+IMG_BOOL LinuxIsLockedMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+ IMG_INT32 iCount;
+
+ iCount = atomic_read(&psPVRSRVMutex->Count);
+
+ return (IMG_BOOL)iCount;
+}
+
+#endif
+
diff --git a/drivers/gpu/pvr/mutex.h b/drivers/gpu/pvr/mutex.h
new file mode 100644
index 0000000..5e787b7
--- /dev/null
+++ b/drivers/gpu/pvr/mutex.h
@@ -0,0 +1,70 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __INCLUDED_LINUX_MUTEX_H_
+#define __INCLUDED_LINUX_MUTEX_H_
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+#include <linux/mutex.h>
+#else
+#include <asm/semaphore.h>
+#endif
+
+
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+
+typedef struct mutex PVRSRV_LINUX_MUTEX;
+
+#else
+
+
+typedef struct {
+ struct semaphore sSemaphore;
+
+ atomic_t Count;
+}PVRSRV_LINUX_MUTEX;
+
+#endif
+
+
+extern IMG_VOID LinuxInitMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex);
+
+extern IMG_VOID LinuxLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex);
+
+extern PVRSRV_ERROR LinuxLockMutexInterruptible(PVRSRV_LINUX_MUTEX *psPVRSRVMutex);
+
+extern IMG_INT32 LinuxTryLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex);
+
+extern IMG_VOID LinuxUnLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex);
+
+extern IMG_BOOL LinuxIsLockedMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex);
+
+
+#endif
+
diff --git a/drivers/gpu/pvr/mutils.c b/drivers/gpu/pvr/mutils.c
new file mode 100644
index 0000000..a012cf5
--- /dev/null
+++ b/drivers/gpu/pvr/mutils.c
@@ -0,0 +1,136 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#endif
+
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+#include "img_defs.h"
+#include "pvr_debug.h"
+#include "mutils.h"
+
+#if defined(SUPPORT_LINUX_X86_PAT)
+#define PAT_LINUX_X86_WC 1
+
+#define PAT_X86_ENTRY_BITS 8
+
+#define PAT_X86_BIT_PWT 1U
+#define PAT_X86_BIT_PCD 2U
+#define PAT_X86_BIT_PAT 4U
+#define PAT_X86_BIT_MASK (PAT_X86_BIT_PAT | PAT_X86_BIT_PCD | PAT_X86_BIT_PWT)
+
+static IMG_BOOL g_write_combining_available = IMG_FALSE;
+
+#define PROT_TO_PAT_INDEX(v, B) ((v & _PAGE_ ## B) ? PAT_X86_BIT_ ## B : 0)
+
+static inline IMG_UINT
+pvr_pat_index(pgprotval_t prot_val)
+{
+ IMG_UINT ret = 0;
+ pgprotval_t val = prot_val & _PAGE_CACHE_MASK;
+
+ ret |= PROT_TO_PAT_INDEX(val, PAT);
+ ret |= PROT_TO_PAT_INDEX(val, PCD);
+ ret |= PROT_TO_PAT_INDEX(val, PWT);
+
+ return ret;
+}
+
+static inline IMG_UINT
+pvr_pat_entry(u64 pat, IMG_UINT index)
+{
+ return (IMG_UINT)(pat >> (index * PAT_X86_ENTRY_BITS)) & PAT_X86_BIT_MASK;
+}
+
+static IMG_VOID
+PVRLinuxX86PATProbe(IMG_VOID)
+{
+
+ if (cpu_has_pat)
+ {
+ u64 pat;
+ IMG_UINT pat_index;
+ IMG_UINT pat_entry;
+
+ PVR_TRACE(("%s: PAT available", __FUNCTION__));
+
+ rdmsrl(MSR_IA32_CR_PAT, pat);
+ PVR_TRACE(("%s: Top 32 bits of PAT: 0x%.8x", __FUNCTION__, (IMG_UINT)(pat >> 32)));
+ PVR_TRACE(("%s: Bottom 32 bits of PAT: 0x%.8x", __FUNCTION__, (IMG_UINT)(pat)));
+
+ pat_index = pvr_pat_index(_PAGE_CACHE_WC);
+ PVR_TRACE(("%s: PAT index for write combining: %u", __FUNCTION__, pat_index));
+
+ pat_entry = pvr_pat_entry(pat, pat_index);
+ PVR_TRACE(("%s: PAT entry for write combining: 0x%.2x (should be 0x%.2x)", __FUNCTION__, pat_entry, PAT_LINUX_X86_WC));
+
+#if defined(SUPPORT_LINUX_X86_WRITECOMBINE)
+ g_write_combining_available = (IMG_BOOL)(pat_entry == PAT_LINUX_X86_WC);
+#endif
+ }
+#if defined(DEBUG)
+#if defined(SUPPORT_LINUX_X86_WRITECOMBINE)
+ if (g_write_combining_available)
+ {
+ PVR_TRACE(("%s: Write combining available via PAT", __FUNCTION__));
+ }
+ else
+ {
+ PVR_TRACE(("%s: Write combining not available", __FUNCTION__));
+ }
+#else
+ PVR_TRACE(("%s: Write combining disabled in driver build", __FUNCTION__));
+#endif
+#endif
+}
+
+pgprot_t
+pvr_pgprot_writecombine(pgprot_t prot)
+{
+
+
+ return (g_write_combining_available) ?
+ __pgprot((pgprot_val(prot) & ~_PAGE_CACHE_MASK) | _PAGE_CACHE_WC) : pgprot_noncached(prot);
+}
+#endif
+
+IMG_VOID
+PVRLinuxMUtilsInit(IMG_VOID)
+{
+#if defined(SUPPORT_LINUX_X86_PAT)
+ PVRLinuxX86PATProbe();
+#endif
+}
+
diff --git a/drivers/gpu/pvr/mutils.h b/drivers/gpu/pvr/mutils.h
new file mode 100644
index 0000000..b2a8ba0
--- /dev/null
+++ b/drivers/gpu/pvr/mutils.h
@@ -0,0 +1,103 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __IMG_LINUX_MUTILS_H__
+#define __IMG_LINUX_MUTILS_H__
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#endif
+
+#if !(defined(__i386__) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)))
+#if defined(SUPPORT_LINUX_X86_PAT)
+#undef SUPPORT_LINUX_X86_PAT
+#endif
+#endif
+
+#if defined(SUPPORT_LINUX_X86_PAT)
+ pgprot_t pvr_pgprot_writecombine(pgprot_t prot);
+ #define PGPROT_WC(pv) pvr_pgprot_writecombine(pv)
+#else
+ #if defined(__arm__) || defined(__sh__)
+ #define PGPROT_WC(pv) pgprot_writecombine(pv)
+ #else
+ #if defined(__i386__) || defined(__mips__)
+ #define PGPROT_WC(pv) pgprot_noncached(pv)
+ #else
+ #define PGPROT_WC(pv) pgprot_noncached(pv)
+ #error Unsupported architecture!
+ #endif
+ #endif
+#endif
+
+#define PGPROT_UC(pv) pgprot_noncached(pv)
+
+#if defined(__i386__) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26))
+ #define IOREMAP(pa, bytes) ioremap_cache(pa, bytes)
+#else
+ #if defined(__arm__) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+ #define IOREMAP(pa, bytes) ioremap_cached(pa, bytes)
+ #else
+ #define IOREMAP(pa, bytes) ioremap(pa, bytes)
+ #endif
+#endif
+
+#if defined(SUPPORT_LINUX_X86_PAT)
+ #if defined(SUPPORT_LINUX_X86_WRITECOMBINE)
+ #define IOREMAP_WC(pa, bytes) ioremap_wc(pa, bytes)
+ #else
+ #define IOREMAP_WC(pa, bytes) ioremap_nocache(pa, bytes)
+ #endif
+#else
+ #if defined(__arm__)
+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
+ #define IOREMAP_WC(pa, bytes) ioremap_wc(pa, bytes)
+ #else
+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
+ #define IOREMAP_WC(pa, bytes) ioremap_nocache(pa, bytes)
+ #else
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17))
+ #define IOREMAP_WC(pa, bytes) __ioremap(pa, bytes, L_PTE_BUFFERABLE)
+ #else
+ #define IOREMAP_WC(pa, bytes) __ioremap(pa, bytes, , L_PTE_BUFFERABLE, 1)
+ #endif
+ #endif
+ #endif
+ #else
+ #define IOREMAP_WC(pa, bytes) ioremap_nocache(pa, bytes)
+ #endif
+#endif
+
+#define IOREMAP_UC(pa, bytes) ioremap_nocache(pa, bytes)
+
+IMG_VOID PVRLinuxMUtilsInit(IMG_VOID);
+
+#endif
+
diff --git a/drivers/gpu/pvr/ocpdefs.h b/drivers/gpu/pvr/ocpdefs.h
new file mode 100644
index 0000000..3bbab7b
--- /dev/null
+++ b/drivers/gpu/pvr/ocpdefs.h
@@ -0,0 +1,271 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef _OCPDEFS_H_
+#define _OCPDEFS_H_
+
+#define EUR_CR_OCP_REVISION 0xFE00
+#define EUR_CR_OCP_REVISION_REV_MASK 0xFFFFFFFFUL
+#define EUR_CR_OCP_REVISION_REV_SHIFT 0
+#define EUR_CR_OCP_REVISION_REV_SIGNED 0
+
+#define EUR_CR_OCP_HWINFO 0xFE04
+#define EUR_CR_OCP_HWINFO_SYS_BUS_WIDTH_MASK 0x00000003UL
+#define EUR_CR_OCP_HWINFO_SYS_BUS_WIDTH_SHIFT 0
+#define EUR_CR_OCP_HWINFO_SYS_BUS_WIDTH_SIGNED 0
+
+#define EUR_CR_OCP_HWINFO_MEM_BUS_WIDTH_MASK 0x00000004UL
+#define EUR_CR_OCP_HWINFO_MEM_BUS_WIDTH_SHIFT 2
+#define EUR_CR_OCP_HWINFO_MEM_BUS_WIDTH_SIGNED 0
+
+#define EUR_CR_OCP_SYSCONFIG 0xFE10
+#define EUR_CR_OCP_SYSCONFIG_IDLE_MODE_MASK 0x0000000CUL
+#define EUR_CR_OCP_SYSCONFIG_IDLE_MODE_SHIFT 2
+#define EUR_CR_OCP_SYSCONFIG_IDLE_MODE_SIGNED 0
+
+#define EUR_CR_OCP_SYSCONFIG_STANDBY_MODE_MASK 0x00000030UL
+#define EUR_CR_OCP_SYSCONFIG_STANDBY_MODE_SHIFT 4
+#define EUR_CR_OCP_SYSCONFIG_STANDBY_MODE_SIGNED 0
+
+#define EUR_CR_OCP_IRQSTATUS_RAW_0 0xFE24
+#define EUR_CR_OCP_IRQSTATUS_RAW_0_INIT_MASK 0x00000001UL
+#define EUR_CR_OCP_IRQSTATUS_RAW_0_INIT_SHIFT 0
+#define EUR_CR_OCP_IRQSTATUS_RAW_0_INIT_SIGNED 0
+
+#define EUR_CR_OCP_IRQSTATUS_RAW_1 0xFE28
+#define EUR_CR_OCP_IRQSTATUS_RAW_1_TARGET_MASK 0x00000001UL
+#define EUR_CR_OCP_IRQSTATUS_RAW_1_TARGET_SHIFT 0
+#define EUR_CR_OCP_IRQSTATUS_RAW_1_TARGET_SIGNED 0
+
+#define EUR_CR_OCP_IRQSTATUS_RAW_2 0xFE2C
+#define EUR_CR_OCP_IRQSTATUS_RAW_2_SGXCORE_MASK 0x00000001UL
+#define EUR_CR_OCP_IRQSTATUS_RAW_2_SGXCORE_SHIFT 0
+#define EUR_CR_OCP_IRQSTATUS_RAW_2_SGXCORE_SIGNED 0
+
+#define EUR_CR_OCP_IRQSTATUS_0 0xFE30
+#define EUR_CR_OCP_IRQSTATUS_0_INIT_MASK 0x00000001UL
+#define EUR_CR_OCP_IRQSTATUS_0_INIT_SHIFT 0
+#define EUR_CR_OCP_IRQSTATUS_0_INIT_SIGNED 0
+
+#define EUR_CR_OCP_IRQSTATUS_1 0xFE34
+#define EUR_CR_OCP_IRQSTATUS_1_TARGET_MASK 0x00000001UL
+#define EUR_CR_OCP_IRQSTATUS_1_TARGET_SHIFT 0
+#define EUR_CR_OCP_IRQSTATUS_1_TARGET_SIGNED 0
+
+#define EUR_CR_OCP_IRQSTATUS_2 0xFE38
+#define EUR_CR_OCP_IRQSTATUS_2_SGXCORE_MASK 0x00000001UL
+#define EUR_CR_OCP_IRQSTATUS_2_SGXCORE_SHIFT 0
+#define EUR_CR_OCP_IRQSTATUS_2_SGXCORE_SIGNED 0
+
+#define EUR_CR_OCP_IRQENABLE_SET_0 0xFE3C
+#define EUR_CR_OCP_IRQENABLE_SET_0_INIT_MASK 0x00000001UL
+#define EUR_CR_OCP_IRQENABLE_SET_0_INIT_SHIFT 0
+#define EUR_CR_OCP_IRQENABLE_SET_0_INIT_SIGNED 0
+
+#define EUR_CR_OCP_IRQENABLE_SET_1 0xFE40
+#define EUR_CR_OCP_IRQENABLE_SET_1_TARGET_MASK 0x00000001UL
+#define EUR_CR_OCP_IRQENABLE_SET_1_TARGET_SHIFT 0
+#define EUR_CR_OCP_IRQENABLE_SET_1_TARGET_SIGNED 0
+
+#define EUR_CR_OCP_IRQENABLE_SET_2 0xFE44
+#define EUR_CR_OCP_IRQENABLE_SET_2_SGXCORE_MASK 0x00000001UL
+#define EUR_CR_OCP_IRQENABLE_SET_2_SGXCORE_SHIFT 0
+#define EUR_CR_OCP_IRQENABLE_SET_2_SGXCORE_SIGNED 0
+
+#define EUR_CR_OCP_IRQENABLE_CLR_0 0xFE48
+#define EUR_CR_OCP_IRQENABLE_CLR_0_INIT_MASK 0x00000001UL
+#define EUR_CR_OCP_IRQENABLE_CLR_0_INIT_SHIFT 0
+#define EUR_CR_OCP_IRQENABLE_CLR_0_INIT_SIGNED 0
+
+#define EUR_CR_OCP_IRQENABLE_CLR_1 0xFE4C
+#define EUR_CR_OCP_IRQENABLE_CLR_1_TARGET_MASK 0x00000001UL
+#define EUR_CR_OCP_IRQENABLE_CLR_1_TARGET_SHIFT 0
+#define EUR_CR_OCP_IRQENABLE_CLR_1_TARGET_SIGNED 0
+
+#define EUR_CR_OCP_IRQENABLE_CLR_2 0xFE50
+#define EUR_CR_OCP_IRQENABLE_CLR_2_SGXCORE_MASK 0x00000001UL
+#define EUR_CR_OCP_IRQENABLE_CLR_2_SGXCORE_SHIFT 0
+#define EUR_CR_OCP_IRQENABLE_CLR_2_SGXCORE_SIGNED 0
+
+#define EUR_CR_OCP_PAGE_CONFIG 0xFF00
+#define EUR_CR_OCP_PAGE_CONFIG_MEM_PAGE_SIZE_MASK 0x00000001UL
+#define EUR_CR_OCP_PAGE_CONFIG_MEM_PAGE_SIZE_SHIFT 0
+#define EUR_CR_OCP_PAGE_CONFIG_MEM_PAGE_SIZE_SIGNED 0
+
+#define EUR_CR_OCP_PAGE_CONFIG_MEM_PAGE_CHECK_ENABLE_MASK 0x00000004UL
+#define EUR_CR_OCP_PAGE_CONFIG_MEM_PAGE_CHECK_ENABLE_SHIFT 2
+#define EUR_CR_OCP_PAGE_CONFIG_MEM_PAGE_CHECK_ENABLE_SIGNED 0
+
+#define EUR_CR_OCP_PAGE_CONFIG_SIZE_MASK 0x00000018UL
+#define EUR_CR_OCP_PAGE_CONFIG_SIZE_SHIFT 3
+#define EUR_CR_OCP_PAGE_CONFIG_SIZE_SIGNED 0
+
+#define EUR_CR_OCP_INTERRUPT_EVENT 0xFF04
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_RESP_UNEXPECTED_MASK 0x00000001UL
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_RESP_UNEXPECTED_SHIFT 0
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_RESP_UNEXPECTED_SIGNED 0
+
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_RESP_UNUSED_TAG_MASK 0x00000002UL
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_RESP_UNUSED_TAG_SHIFT 1
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_RESP_UNUSED_TAG_SIGNED 0
+
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_RESP_ERROR_MASK 0x00000004UL
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_RESP_ERROR_SHIFT 2
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_RESP_ERROR_SIGNED 0
+
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_PAGE_CROSS_ERROR_MASK 0x00000008UL
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_PAGE_CROSS_ERROR_SHIFT 3
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_PAGE_CROSS_ERROR_SIGNED 0
+
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_READ_TAG_FIFO_OVR_MASK 0x00000010UL
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_READ_TAG_FIFO_OVR_SHIFT 4
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_READ_TAG_FIFO_OVR_SIGNED 0
+
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_MEM_REQ_FIFO_OVR_MASK 0x00000020UL
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_MEM_REQ_FIFO_OVR_SHIFT 5
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_MEM_REQ_FIFO_OVR_SIGNED 0
+
+#define EUR_CR_OCP_INTERRUPT_EVENT_TARGET_RESP_FIFO_FULL_MASK 0x00000100UL
+#define EUR_CR_OCP_INTERRUPT_EVENT_TARGET_RESP_FIFO_FULL_SHIFT 8
+#define EUR_CR_OCP_INTERRUPT_EVENT_TARGET_RESP_FIFO_FULL_SIGNED 0
+
+#define EUR_CR_OCP_INTERRUPT_EVENT_TARGET_CMD_FIFO_FULL_MASK 0x00000200UL
+#define EUR_CR_OCP_INTERRUPT_EVENT_TARGET_CMD_FIFO_FULL_SHIFT 9
+#define EUR_CR_OCP_INTERRUPT_EVENT_TARGET_CMD_FIFO_FULL_SIGNED 0
+
+#define EUR_CR_OCP_INTERRUPT_EVENT_TARGET_INVALID_OCP_CMD_MASK 0x00000400UL
+#define EUR_CR_OCP_INTERRUPT_EVENT_TARGET_INVALID_OCP_CMD_SHIFT 10
+#define EUR_CR_OCP_INTERRUPT_EVENT_TARGET_INVALID_OCP_CMD_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_CONFIG 0xFF08
+#define EUR_CR_OCP_DEBUG_CONFIG_FORCE_TARGET_IDLE_MASK 0x00000003UL
+#define EUR_CR_OCP_DEBUG_CONFIG_FORCE_TARGET_IDLE_SHIFT 0
+#define EUR_CR_OCP_DEBUG_CONFIG_FORCE_TARGET_IDLE_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_CONFIG_FORCE_INIT_IDLE_MASK 0x0000000CUL
+#define EUR_CR_OCP_DEBUG_CONFIG_FORCE_INIT_IDLE_SHIFT 2
+#define EUR_CR_OCP_DEBUG_CONFIG_FORCE_INIT_IDLE_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_CONFIG_FORCE_PASS_DATA_MASK 0x00000010UL
+#define EUR_CR_OCP_DEBUG_CONFIG_FORCE_PASS_DATA_SHIFT 4
+#define EUR_CR_OCP_DEBUG_CONFIG_FORCE_PASS_DATA_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_CONFIG_SELECT_INIT_IDLE_MASK 0x00000020UL
+#define EUR_CR_OCP_DEBUG_CONFIG_SELECT_INIT_IDLE_SHIFT 5
+#define EUR_CR_OCP_DEBUG_CONFIG_SELECT_INIT_IDLE_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_CONFIG_THALIA_INT_BYPASS_MASK 0x80000000UL
+#define EUR_CR_OCP_DEBUG_CONFIG_THALIA_INT_BYPASS_SHIFT 31
+#define EUR_CR_OCP_DEBUG_CONFIG_THALIA_INT_BYPASS_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS 0xFF0C
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_MCONNECT_MASK 0x00000003UL
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_MCONNECT_SHIFT 0
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_MCONNECT_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_SCONNECT_MASK 0x00000004UL
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_SCONNECT_SHIFT 2
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_SCONNECT_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_SIDLEREQ_MASK 0x00000008UL
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_SIDLEREQ_SHIFT 3
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_SIDLEREQ_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_SDISCACK_MASK 0x00000030UL
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_SDISCACK_SHIFT 4
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_SDISCACK_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_SIDLEACK_MASK 0x000000C0UL
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_SIDLEACK_SHIFT 6
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_SIDLEACK_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MCONNECT0_MASK 0x00000300UL
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MCONNECT0_SHIFT 8
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MCONNECT0_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_SCONNECT0_MASK 0x00000400UL
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_SCONNECT0_SHIFT 10
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_SCONNECT0_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_SCONNECT1_MASK 0x00000800UL
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_SCONNECT1_SHIFT 11
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_SCONNECT1_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_SCONNECT2_MASK 0x00001000UL
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_SCONNECT2_SHIFT 12
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_SCONNECT2_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MDISCACK_MASK 0x00006000UL
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MDISCACK_SHIFT 13
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MDISCACK_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MDISCREQ_MASK 0x00008000UL
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MDISCREQ_SHIFT 15
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MDISCREQ_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MWAIT_MASK 0x00010000UL
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MWAIT_SHIFT 16
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MWAIT_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MSTANDBY_MASK 0x00020000UL
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MSTANDBY_SHIFT 17
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MSTANDBY_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_CMD_OUT_MASK 0x001C0000UL
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_CMD_OUT_SHIFT 18
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_CMD_OUT_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_WHICH_TARGET_REGISTER_MASK 0x03E00000UL
+#define EUR_CR_OCP_DEBUG_STATUS_WHICH_TARGET_REGISTER_SHIFT 21
+#define EUR_CR_OCP_DEBUG_STATUS_WHICH_TARGET_REGISTER_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_RESP_ERROR_MASK 0x04000000UL
+#define EUR_CR_OCP_DEBUG_STATUS_RESP_ERROR_SHIFT 26
+#define EUR_CR_OCP_DEBUG_STATUS_RESP_ERROR_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_CMD_FIFO_FULL_MASK 0x08000000UL
+#define EUR_CR_OCP_DEBUG_STATUS_CMD_FIFO_FULL_SHIFT 27
+#define EUR_CR_OCP_DEBUG_STATUS_CMD_FIFO_FULL_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_RESP_FIFO_FULL_MASK 0x10000000UL
+#define EUR_CR_OCP_DEBUG_STATUS_RESP_FIFO_FULL_SHIFT 28
+#define EUR_CR_OCP_DEBUG_STATUS_RESP_FIFO_FULL_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_IDLE_MASK 0x20000000UL
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_IDLE_SHIFT 29
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_IDLE_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_CMD_RESP_DEBUG_STATE_MASK 0x40000000UL
+#define EUR_CR_OCP_DEBUG_STATUS_CMD_RESP_DEBUG_STATE_SHIFT 30
+#define EUR_CR_OCP_DEBUG_STATUS_CMD_RESP_DEBUG_STATE_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_CMD_DEBUG_STATE_MASK 0x80000000UL
+#define EUR_CR_OCP_DEBUG_STATUS_CMD_DEBUG_STATE_SHIFT 31
+#define EUR_CR_OCP_DEBUG_STATUS_CMD_DEBUG_STATE_SIGNED 0
+
+
+#endif
+
diff --git a/drivers/gpu/pvr/osfunc.c b/drivers/gpu/pvr/osfunc.c
new file mode 100644
index 0000000..28e2b00
--- /dev/null
+++ b/drivers/gpu/pvr/osfunc.c
@@ -0,0 +1,3310 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#endif
+
+#include <asm/io.h>
+#include <asm/page.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
+#include <asm/system.h>
+#endif
+#include <asm/cacheflush.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/hugetlb.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <asm/hardirq.h>
+#include <linux/timer.h>
+#include <linux/capability.h>
+#include <asm/uaccess.h>
+#include <linux/spinlock.h>
+#if defined(PVR_LINUX_MISR_USING_WORKQUEUE) || \
+ defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE) || \
+ defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || \
+ defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE) || \
+ defined(PVR_LINUX_USING_WORKQUEUES)
+#include <linux/workqueue.h>
+#endif
+
+#include "img_types.h"
+#include "services_headers.h"
+#include "mm.h"
+#include "pvrmmap.h"
+#include "mmap.h"
+#include "env_data.h"
+#include "proc.h"
+#include "mutex.h"
+#include "event.h"
+#include "linkage.h"
+#include "pvr_uaccess.h"
+#include "lock.h"
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
+#define ON_EACH_CPU(func, info, wait) on_each_cpu(func, info, wait)
+#else
+#define ON_EACH_CPU(func, info, wait) on_each_cpu(func, info, 0, wait)
+#endif
+
+#if defined(PVR_LINUX_USING_WORKQUEUES) && !defined(CONFIG_PREEMPT)
+#error "A preemptible Linux kernel is required when using workqueues"
+#endif
+
+#if defined(EMULATOR)
+#define EVENT_OBJECT_TIMEOUT_MS (2000)
+#else
+#define EVENT_OBJECT_TIMEOUT_MS (100)
+#endif
+
+#if !defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+PVRSRV_ERROR OSAllocMem_Impl(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID *ppvCpuVAddr, IMG_HANDLE *phBlockAlloc)
+#else
+PVRSRV_ERROR OSAllocMem_Impl(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID *ppvCpuVAddr, IMG_HANDLE *phBlockAlloc, IMG_CHAR *pszFilename, IMG_UINT32 ui32Line)
+#endif
+{
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+ PVR_UNREFERENCED_PARAMETER(phBlockAlloc);
+
+ if (ui32Size > PAGE_SIZE)
+ {
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ *ppvCpuVAddr = _VMallocWrapper(ui32Size, PVRSRV_HAP_CACHED, pszFilename, ui32Line);
+#else
+ *ppvCpuVAddr = VMallocWrapper(ui32Size, PVRSRV_HAP_CACHED);
+#endif
+ if (*ppvCpuVAddr)
+ {
+ return PVRSRV_OK;
+ }
+ }
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ *ppvCpuVAddr = _KMallocWrapper(ui32Size, GFP_KERNEL | __GFP_NOWARN, pszFilename, ui32Line);
+#else
+ *ppvCpuVAddr = KMallocWrapper(ui32Size, GFP_KERNEL | __GFP_NOWARN);
+#endif
+ if (!*ppvCpuVAddr)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ return PVRSRV_OK;
+}
+
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,24))
+
+static inline int is_vmalloc_addr(const void *pvCpuVAddr)
+{
+ unsigned long lAddr = (unsigned long)pvCpuVAddr;
+ return lAddr >= VMALLOC_START && lAddr < VMALLOC_END;
+}
+
+#endif
+
+#if !defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+PVRSRV_ERROR OSFreeMem_Impl(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID pvCpuVAddr, IMG_HANDLE hBlockAlloc)
+#else
+PVRSRV_ERROR OSFreeMem_Impl(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID pvCpuVAddr, IMG_HANDLE hBlockAlloc, IMG_CHAR *pszFilename, IMG_UINT32 ui32Line)
+#endif
+{
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+ PVR_UNREFERENCED_PARAMETER(ui32Size);
+ PVR_UNREFERENCED_PARAMETER(hBlockAlloc);
+
+ if (is_vmalloc_addr(pvCpuVAddr))
+ {
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ _VFreeWrapper(pvCpuVAddr, pszFilename, ui32Line);
+#else
+ VFreeWrapper(pvCpuVAddr);
+#endif
+ }
+ else
+ {
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ _KFreeWrapper(pvCpuVAddr, pszFilename, ui32Line);
+#else
+ KFreeWrapper(pvCpuVAddr);
+#endif
+ }
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+OSAllocPages_Impl(IMG_UINT32 ui32AllocFlags,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32PageSize,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
+ IMG_VOID **ppvCpuVAddr,
+ IMG_HANDLE *phOSMemHandle)
+{
+ LinuxMemArea *psLinuxMemArea;
+
+ PVR_UNREFERENCED_PARAMETER(ui32PageSize);
+
+#if 0
+
+ if(ui32AllocFlags & PVRSRV_HAP_SINGLE_PROCESS)
+ {
+ ui32AllocFlags &= ~PVRSRV_HAP_SINGLE_PROCESS;
+ ui32AllocFlags |= PVRSRV_HAP_MULTI_PROCESS;
+ }
+#endif
+
+ if(ui32AllocFlags & PVRSRV_MEM_ION)
+ {
+
+ BUG_ON((ui32AllocFlags & PVRSRV_HAP_MAPTYPE_MASK) != PVRSRV_HAP_SINGLE_PROCESS);
+
+ psLinuxMemArea = NewIONLinuxMemArea(ui32Size, ui32AllocFlags,
+ pvPrivData, ui32PrivDataLength);
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ PVRMMapRegisterArea(psLinuxMemArea);
+ goto ExitSkipSwitch;
+ }
+
+ switch(ui32AllocFlags & PVRSRV_HAP_MAPTYPE_MASK)
+ {
+ case PVRSRV_HAP_KERNEL_ONLY:
+ {
+ psLinuxMemArea = NewVMallocLinuxMemArea(ui32Size, ui32AllocFlags);
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ break;
+ }
+ case PVRSRV_HAP_SINGLE_PROCESS:
+ {
+
+ psLinuxMemArea = NewAllocPagesLinuxMemArea(ui32Size, ui32AllocFlags);
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ PVRMMapRegisterArea(psLinuxMemArea);
+ break;
+ }
+
+ case PVRSRV_HAP_MULTI_PROCESS:
+ {
+
+#if defined(VIVT_CACHE) || defined(__sh__)
+
+ ui32AllocFlags &= ~PVRSRV_HAP_CACHED;
+#endif
+ psLinuxMemArea = NewVMallocLinuxMemArea(ui32Size, ui32AllocFlags);
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ PVRMMapRegisterArea(psLinuxMemArea);
+ break;
+ }
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "OSAllocPages: invalid flags 0x%x\n", ui32AllocFlags));
+ *ppvCpuVAddr = NULL;
+ *phOSMemHandle = (IMG_HANDLE)0;
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ExitSkipSwitch:
+ *ppvCpuVAddr = LinuxMemAreaToCpuVAddr(psLinuxMemArea);
+ *phOSMemHandle = psLinuxMemArea;
+
+ LinuxMemAreaRegister(psLinuxMemArea);
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+OSFreePages(IMG_UINT32 ui32AllocFlags, IMG_UINT32 ui32Bytes, IMG_VOID *pvCpuVAddr, IMG_HANDLE hOSMemHandle)
+{
+ LinuxMemArea *psLinuxMemArea;
+ PVRSRV_ERROR eError;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+ PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+
+ psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+ switch(ui32AllocFlags & PVRSRV_HAP_MAPTYPE_MASK)
+ {
+ case PVRSRV_HAP_KERNEL_ONLY:
+ break;
+ case PVRSRV_HAP_SINGLE_PROCESS:
+ case PVRSRV_HAP_MULTI_PROCESS:
+ eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSFreePages(ui32AllocFlags=0x%08X, ui32Bytes=%d, "
+ "pvCpuVAddr=%p, hOSMemHandle=%p) FAILED!",
+ ui32AllocFlags, ui32Bytes, pvCpuVAddr, hOSMemHandle));
+ return eError;
+ }
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR,"%s: invalid flags 0x%x\n",
+ __FUNCTION__, ui32AllocFlags));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ LinuxMemAreaDeepFree(psLinuxMemArea);
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+OSGetSubMemHandle(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE *phOSMemHandleRet)
+{
+ LinuxMemArea *psParentLinuxMemArea, *psLinuxMemArea;
+ PVRSRV_ERROR eError;
+
+ psParentLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+ psLinuxMemArea = NewSubLinuxMemArea(psParentLinuxMemArea, ui32ByteOffset, ui32Bytes);
+ if(!psLinuxMemArea)
+ {
+ *phOSMemHandleRet = NULL;
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ *phOSMemHandleRet = psLinuxMemArea;
+
+
+ if(ui32Flags & PVRSRV_HAP_KERNEL_ONLY)
+ {
+ return PVRSRV_OK;
+ }
+
+ eError = PVRMMapRegisterArea(psLinuxMemArea);
+ if(eError != PVRSRV_OK)
+ {
+ goto failed_register_area;
+ }
+
+ return PVRSRV_OK;
+
+failed_register_area:
+ *phOSMemHandleRet = NULL;
+ LinuxMemAreaDeepFree(psLinuxMemArea);
+ return eError;
+}
+
+PVRSRV_ERROR
+OSReleaseSubMemHandle(IMG_VOID *hOSMemHandle, IMG_UINT32 ui32Flags)
+{
+ LinuxMemArea *psLinuxMemArea;
+ PVRSRV_ERROR eError;
+
+ psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+ PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC);
+
+ if((ui32Flags & PVRSRV_HAP_KERNEL_ONLY) == 0)
+ {
+ eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea);
+ if(eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+ LinuxMemAreaDeepFree(psLinuxMemArea);
+
+ return PVRSRV_OK;
+}
+
+
+IMG_CPU_PHYADDR
+OSMemHandleToCpuPAddr(IMG_VOID *hOSMemHandle, IMG_UINT32 ui32ByteOffset)
+{
+ PVR_ASSERT(hOSMemHandle);
+
+ return LinuxMemAreaToCpuPAddr(hOSMemHandle, ui32ByteOffset);
+}
+
+
+IMG_BOOL OSMemHandleIsPhysContig(IMG_VOID *hOSMemHandle)
+{
+ LinuxMemArea *psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+ PVR_ASSERT(psLinuxMemArea);
+
+ if(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_EXTERNAL_KV)
+ return psLinuxMemArea->uData.sExternalKV.bPhysContig;
+
+ return IMG_FALSE;
+}
+
+
+IMG_VOID OSMemCopy(IMG_VOID *pvDst, IMG_VOID *pvSrc, IMG_UINT32 ui32Size)
+{
+#if defined(USE_UNOPTIMISED_MEMCPY)
+ IMG_UINT8 *Src,*Dst;
+ IMG_INT i;
+
+ Src=(IMG_UINT8 *)pvSrc;
+ Dst=(IMG_UINT8 *)pvDst;
+ for(i=0;i<ui32Size;i++)
+ {
+ Dst[i]=Src[i];
+ }
+#else
+ memcpy(pvDst, pvSrc, ui32Size);
+#endif
+}
+
+
+IMG_VOID OSMemSet(IMG_VOID *pvDest, IMG_UINT8 ui8Value, IMG_UINT32 ui32Size)
+{
+#if defined(USE_UNOPTIMISED_MEMSET)
+ IMG_UINT8 *Buff;
+ IMG_INT i;
+
+ Buff=(IMG_UINT8 *)pvDest;
+ for(i=0;i<ui32Size;i++)
+ {
+ Buff[i]=ui8Value;
+ }
+#else
+ memset(pvDest, (IMG_INT) ui8Value, (size_t) ui32Size);
+#endif
+}
+
+
+IMG_CHAR *OSStringCopy(IMG_CHAR *pszDest, const IMG_CHAR *pszSrc)
+{
+ return (strcpy(pszDest, pszSrc));
+}
+
+IMG_INT32 OSSNPrintf(IMG_CHAR *pStr, IMG_UINT32 ui32Size, const IMG_CHAR *pszFormat, ...)
+{
+ va_list argList;
+ IMG_INT32 iCount;
+
+ va_start(argList, pszFormat);
+ iCount = vsnprintf(pStr, (size_t)ui32Size, pszFormat, argList);
+ va_end(argList);
+
+ return iCount;
+}
+
+IMG_VOID OSBreakResourceLock (PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID)
+{
+ volatile IMG_UINT32 *pui32Access = (volatile IMG_UINT32 *)&psResource->ui32Lock;
+
+ if(*pui32Access)
+ {
+ if(psResource->ui32ID == ui32ID)
+ {
+ psResource->ui32ID = 0;
+ *pui32Access = 0;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"OSBreakResourceLock: Resource is not locked for this process."));
+ }
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"OSBreakResourceLock: Resource is not locked"));
+ }
+}
+
+
+PVRSRV_ERROR OSCreateResource(PVRSRV_RESOURCE *psResource)
+{
+ psResource->ui32ID = 0;
+ psResource->ui32Lock = 0;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSDestroyResource (PVRSRV_RESOURCE *psResource)
+{
+ OSBreakResourceLock (psResource, psResource->ui32ID);
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSInitEnvData(IMG_PVOID *ppvEnvSpecificData)
+{
+ ENV_DATA *psEnvData;
+ PVRSRV_ERROR eError;
+
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(ENV_DATA), (IMG_VOID **)&psEnvData, IMG_NULL,
+ "Environment Data");
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, PVRSRV_MAX_BRIDGE_IN_SIZE + PVRSRV_MAX_BRIDGE_OUT_SIZE,
+ &psEnvData->pvBridgeData, IMG_NULL,
+ "Bridge Data");
+ if (eError != PVRSRV_OK)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(ENV_DATA), psEnvData, IMG_NULL);
+
+ return eError;
+ }
+
+
+
+ psEnvData->bMISRInstalled = IMG_FALSE;
+ psEnvData->bLISRInstalled = IMG_FALSE;
+
+
+ *ppvEnvSpecificData = psEnvData;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSDeInitEnvData(IMG_PVOID pvEnvSpecificData)
+{
+ ENV_DATA *psEnvData = (ENV_DATA*)pvEnvSpecificData;
+
+ PVR_ASSERT(!psEnvData->bMISRInstalled);
+ PVR_ASSERT(!psEnvData->bLISRInstalled);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, PVRSRV_MAX_BRIDGE_IN_SIZE + PVRSRV_MAX_BRIDGE_OUT_SIZE, psEnvData->pvBridgeData, IMG_NULL);
+ psEnvData->pvBridgeData = IMG_NULL;
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(ENV_DATA), pvEnvSpecificData, IMG_NULL);
+
+
+ return PVRSRV_OK;
+}
+
+
+
+IMG_VOID OSReleaseThreadQuanta(IMG_VOID)
+{
+ schedule();
+}
+
+
+
+IMG_UINT32 OSClockus(IMG_VOID)
+{
+ IMG_UINT32 time, j = jiffies;
+
+ time = j * (1000000 / HZ);
+
+ return time;
+}
+
+
+IMG_VOID OSWaitus(IMG_UINT32 ui32Timeus)
+{
+ udelay(ui32Timeus);
+}
+
+
+IMG_VOID OSSleepms(IMG_UINT32 ui32Timems)
+{
+ msleep(ui32Timems);
+}
+
+
+
+IMG_HANDLE OSFuncHighResTimerCreate(IMG_VOID)
+{
+
+ return (IMG_HANDLE) 1;
+}
+
+
+IMG_UINT32 OSFuncHighResTimerGetus(IMG_HANDLE hTimer)
+{
+ return (IMG_UINT32) jiffies_to_usecs(jiffies);
+}
+
+
+IMG_VOID OSFuncHighResTimerDestroy(IMG_HANDLE hTimer)
+{
+ PVR_UNREFERENCED_PARAMETER(hTimer);
+}
+
+IMG_UINT32 OSGetCurrentProcessIDKM(IMG_VOID)
+{
+ if (in_interrupt())
+ {
+ return KERNEL_ID;
+ }
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+ return (IMG_UINT32)current->pgrp;
+#else
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24))
+ return (IMG_UINT32)task_tgid_nr(current);
+#else
+ return (IMG_UINT32)current->tgid;
+#endif
+#endif
+}
+
+
+IMG_UINT32 OSGetPageSize(IMG_VOID)
+{
+#if defined(__sh__)
+ IMG_UINT32 ui32ReturnValue = PAGE_SIZE;
+
+ return (ui32ReturnValue);
+#else
+ return PAGE_SIZE;
+#endif
+}
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
+static irqreturn_t DeviceISRWrapper(int irq, void *dev_id
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
+ , struct pt_regs *regs
+#endif
+ )
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_BOOL bStatus = IMG_FALSE;
+
+ PVR_UNREFERENCED_PARAMETER(irq);
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
+ PVR_UNREFERENCED_PARAMETER(regs);
+#endif
+ psDeviceNode = (PVRSRV_DEVICE_NODE*)dev_id;
+ if(!psDeviceNode)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DeviceISRWrapper: invalid params\n"));
+ goto out;
+ }
+
+ bStatus = PVRSRVDeviceLISR(psDeviceNode);
+
+ if (bStatus)
+ {
+ OSScheduleMISR((IMG_VOID *)psDeviceNode->psSysData);
+ }
+
+out:
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+ return bStatus ? IRQ_HANDLED : IRQ_NONE;
+#endif
+}
+
+
+
+static irqreturn_t SystemISRWrapper(int irq, void *dev_id
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
+ , struct pt_regs *regs
+#endif
+ )
+{
+ SYS_DATA *psSysData;
+ IMG_BOOL bStatus = IMG_FALSE;
+
+ PVR_UNREFERENCED_PARAMETER(irq);
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
+ PVR_UNREFERENCED_PARAMETER(regs);
+#endif
+ psSysData = (SYS_DATA *)dev_id;
+ if(!psSysData)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SystemISRWrapper: invalid params\n"));
+ goto out;
+ }
+
+ bStatus = PVRSRVSystemLISR(psSysData);
+
+ if (bStatus)
+ {
+ OSScheduleMISR((IMG_VOID *)psSysData);
+ }
+
+out:
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+ return bStatus ? IRQ_HANDLED : IRQ_NONE;
+#endif
+}
+PVRSRV_ERROR OSInstallDeviceLISR(IMG_VOID *pvSysData,
+ IMG_UINT32 ui32Irq,
+ IMG_CHAR *pszISRName,
+ IMG_VOID *pvDeviceNode)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (psEnvData->bLISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSInstallDeviceLISR: An ISR has already been installed: IRQ %d cookie %p", psEnvData->ui32IRQ, psEnvData->pvISRCookie));
+ return PVRSRV_ERROR_ISR_ALREADY_INSTALLED;
+ }
+
+ PVR_TRACE(("Installing device LISR %s on IRQ %d with cookie %p", pszISRName, ui32Irq, pvDeviceNode));
+
+ if(request_irq(ui32Irq, DeviceISRWrapper,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22))
+ SA_SHIRQ
+#else
+ IRQF_SHARED
+#endif
+ , pszISRName, pvDeviceNode))
+ {
+ PVR_DPF((PVR_DBG_ERROR,"OSInstallDeviceLISR: Couldn't install device LISR on IRQ %d", ui32Irq));
+
+ return PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR;
+ }
+
+ psEnvData->ui32IRQ = ui32Irq;
+ psEnvData->pvISRCookie = pvDeviceNode;
+ psEnvData->bLISRInstalled = IMG_TRUE;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSUninstallDeviceLISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (!psEnvData->bLISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSUninstallDeviceLISR: No LISR has been installed"));
+ return PVRSRV_ERROR_ISR_NOT_INSTALLED;
+ }
+
+ PVR_TRACE(("Uninstalling device LISR on IRQ %d with cookie %p", psEnvData->ui32IRQ, psEnvData->pvISRCookie));
+
+ free_irq(psEnvData->ui32IRQ, psEnvData->pvISRCookie);
+
+ psEnvData->bLISRInstalled = IMG_FALSE;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSInstallSystemLISR(IMG_VOID *pvSysData, IMG_UINT32 ui32Irq)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (psEnvData->bLISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSInstallSystemLISR: An LISR has already been installed: IRQ %d cookie %p", psEnvData->ui32IRQ, psEnvData->pvISRCookie));
+ return PVRSRV_ERROR_ISR_ALREADY_INSTALLED;
+ }
+
+ PVR_TRACE(("Installing system LISR on IRQ %d with cookie %p", ui32Irq, pvSysData));
+
+ if(request_irq(ui32Irq, SystemISRWrapper,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22))
+ SA_SHIRQ
+#else
+ IRQF_SHARED
+#endif
+ , PVRSRV_MODNAME, pvSysData))
+ {
+ PVR_DPF((PVR_DBG_ERROR,"OSInstallSystemLISR: Couldn't install system LISR on IRQ %d", ui32Irq));
+
+ return PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR;
+ }
+
+ psEnvData->ui32IRQ = ui32Irq;
+ psEnvData->pvISRCookie = pvSysData;
+ psEnvData->bLISRInstalled = IMG_TRUE;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSUninstallSystemLISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (!psEnvData->bLISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSUninstallSystemLISR: No LISR has been installed"));
+ return PVRSRV_ERROR_ISR_NOT_INSTALLED;
+ }
+
+ PVR_TRACE(("Uninstalling system LISR on IRQ %d with cookie %p", psEnvData->ui32IRQ, psEnvData->pvISRCookie));
+
+ free_irq(psEnvData->ui32IRQ, psEnvData->pvISRCookie);
+
+ psEnvData->bLISRInstalled = IMG_FALSE;
+
+ return PVRSRV_OK;
+}
+
+#if defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+static void MISRWrapper(
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
+ void *data
+#else
+ struct work_struct *data
+#endif
+)
+{
+ ENV_DATA *psEnvData = container_of(data, ENV_DATA, sMISRWork);
+ SYS_DATA *psSysData = (SYS_DATA *)psEnvData->pvMISRData;
+
+ PVRSRVMISR(psSysData);
+}
+
+
+PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (psEnvData->bMISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSInstallMISR: An MISR has already been installed"));
+ return PVRSRV_ERROR_ISR_ALREADY_INSTALLED;
+ }
+
+ PVR_TRACE(("Installing MISR with cookie %p", pvSysData));
+
+ psEnvData->psWorkQueue = create_singlethread_workqueue("pvr_workqueue");
+
+ if (psEnvData->psWorkQueue == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSInstallMISR: create_singlethreaded_workqueue failed"));
+ return PVRSRV_ERROR_UNABLE_TO_CREATE_THREAD;
+ }
+
+ INIT_WORK(&psEnvData->sMISRWork, MISRWrapper
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
+ , (void *)&psEnvData->sMISRWork
+#endif
+ );
+
+ psEnvData->pvMISRData = pvSysData;
+ psEnvData->bMISRInstalled = IMG_TRUE;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (!psEnvData->bMISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSUninstallMISR: No MISR has been installed"));
+ return PVRSRV_ERROR_ISR_NOT_INSTALLED;
+ }
+
+ PVR_TRACE(("Uninstalling MISR"));
+
+ destroy_workqueue(psEnvData->psWorkQueue);
+
+ psEnvData->bMISRInstalled = IMG_FALSE;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA*)psSysData->pvEnvSpecificData;
+
+ if (psEnvData->bMISRInstalled)
+ {
+ queue_work(psEnvData->psWorkQueue, &psEnvData->sMISRWork);
+ }
+
+ return PVRSRV_OK;
+}
+#else
+#if defined(PVR_LINUX_MISR_USING_WORKQUEUE)
+static void MISRWrapper(
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
+ void *data
+#else
+ struct work_struct *data
+#endif
+)
+{
+ ENV_DATA *psEnvData = container_of(data, ENV_DATA, sMISRWork);
+ SYS_DATA *psSysData = (SYS_DATA *)psEnvData->pvMISRData;
+
+ PVRSRVMISR(psSysData);
+}
+
+
+PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (psEnvData->bMISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSInstallMISR: An MISR has already been installed"));
+ return PVRSRV_ERROR_ISR_ALREADY_INSTALLED;
+ }
+
+ PVR_TRACE(("Installing MISR with cookie %p", pvSysData));
+
+ INIT_WORK(&psEnvData->sMISRWork, MISRWrapper
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
+ , (void *)&psEnvData->sMISRWork
+#endif
+ );
+
+ psEnvData->pvMISRData = pvSysData;
+ psEnvData->bMISRInstalled = IMG_TRUE;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (!psEnvData->bMISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSUninstallMISR: No MISR has been installed"));
+ return PVRSRV_ERROR_ISR_NOT_INSTALLED;
+ }
+
+ PVR_TRACE(("Uninstalling MISR"));
+
+ flush_scheduled_work();
+
+ psEnvData->bMISRInstalled = IMG_FALSE;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA*)psSysData->pvEnvSpecificData;
+
+ if (psEnvData->bMISRInstalled)
+ {
+ schedule_work(&psEnvData->sMISRWork);
+ }
+
+ return PVRSRV_OK;
+}
+
+#else
+
+
+static void MISRWrapper(unsigned long data)
+{
+ SYS_DATA *psSysData;
+
+ psSysData = (SYS_DATA *)data;
+
+ PVRSRVMISR(psSysData);
+}
+
+
+PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (psEnvData->bMISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSInstallMISR: An MISR has already been installed"));
+ return PVRSRV_ERROR_ISR_ALREADY_INSTALLED;
+ }
+
+ PVR_TRACE(("Installing MISR with cookie %p", pvSysData));
+
+ tasklet_init(&psEnvData->sMISRTasklet, MISRWrapper, (unsigned long)pvSysData);
+
+ psEnvData->bMISRInstalled = IMG_TRUE;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (!psEnvData->bMISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSUninstallMISR: No MISR has been installed"));
+ return PVRSRV_ERROR_ISR_NOT_INSTALLED;
+ }
+
+ PVR_TRACE(("Uninstalling MISR"));
+
+ tasklet_kill(&psEnvData->sMISRTasklet);
+
+ psEnvData->bMISRInstalled = IMG_FALSE;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA*)psSysData->pvEnvSpecificData;
+
+ if (psEnvData->bMISRInstalled)
+ {
+ tasklet_schedule(&psEnvData->sMISRTasklet);
+ }
+
+ return PVRSRV_OK;
+}
+
+#endif
+#endif
+
+#endif
+
+IMG_VOID OSPanic(IMG_VOID)
+{
+ BUG();
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
+#define OS_TAS(p) xchg((p), 1)
+#else
+#define OS_TAS(p) tas(p)
+#endif
+PVRSRV_ERROR OSLockResource ( PVRSRV_RESOURCE *psResource,
+ IMG_UINT32 ui32ID)
+
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if(!OS_TAS(&psResource->ui32Lock))
+ psResource->ui32ID = ui32ID;
+ else
+ eError = PVRSRV_ERROR_UNABLE_TO_LOCK_RESOURCE;
+
+ return eError;
+}
+
+
+PVRSRV_ERROR OSUnlockResource (PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID)
+{
+ volatile IMG_UINT32 *pui32Access = (volatile IMG_UINT32 *)&psResource->ui32Lock;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if(*pui32Access)
+ {
+ if(psResource->ui32ID == ui32ID)
+ {
+ psResource->ui32ID = 0;
+ smp_mb();
+ *pui32Access = 0;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,"OSUnlockResource: Resource %p is not locked with expected value.", psResource));
+ PVR_DPF((PVR_DBG_MESSAGE,"Should be %x is actually %x", ui32ID, psResource->ui32ID));
+ eError = PVRSRV_ERROR_INVALID_LOCK_ID;
+ }
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,"OSUnlockResource: Resource %p is not locked", psResource));
+ eError = PVRSRV_ERROR_RESOURCE_NOT_LOCKED;
+ }
+
+ return eError;
+}
+
+
+IMG_BOOL OSIsResourceLocked (PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID)
+{
+ volatile IMG_UINT32 *pui32Access = (volatile IMG_UINT32 *)&psResource->ui32Lock;
+
+ return (*(volatile IMG_UINT32 *)pui32Access == 1) && (psResource->ui32ID == ui32ID)
+ ? IMG_TRUE
+ : IMG_FALSE;
+}
+
+
+#if !defined(SYS_CUSTOM_POWERLOCK_WRAP)
+PVRSRV_ERROR OSPowerLockWrap(IMG_BOOL bTryLock)
+{
+ PVR_UNREFERENCED_PARAMETER(bTryLock);
+
+ return PVRSRV_OK;
+}
+
+IMG_VOID OSPowerLockUnwrap (IMG_VOID)
+{
+}
+#endif
+
+
+IMG_CPU_PHYADDR OSMapLinToCPUPhys(IMG_HANDLE hOSMemHandle,
+ IMG_VOID *pvLinAddr)
+{
+ IMG_CPU_PHYADDR CpuPAddr;
+ LinuxMemArea *psLinuxMemArea;
+ IMG_UINTPTR_T uiByteOffset;
+ IMG_UINT32 ui32ByteOffset;
+
+ PVR_ASSERT(hOSMemHandle != IMG_NULL);
+
+
+
+ psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+ uiByteOffset = (IMG_UINTPTR_T)pvLinAddr - (IMG_UINTPTR_T)LinuxMemAreaToCpuVAddr(psLinuxMemArea);
+ ui32ByteOffset = (IMG_UINT32)uiByteOffset;
+
+ CpuPAddr = LinuxMemAreaToCpuPAddr(hOSMemHandle, ui32ByteOffset);
+
+ return CpuPAddr;
+}
+
+
+IMG_VOID *
+OSMapPhysToLin(IMG_CPU_PHYADDR BasePAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32MappingFlags,
+ IMG_HANDLE *phOSMemHandle)
+{
+ if(ui32MappingFlags & PVRSRV_HAP_KERNEL_ONLY)
+ {
+
+ if(phOSMemHandle == IMG_NULL)
+ {
+ IMG_VOID *pvIORemapCookie;
+ pvIORemapCookie = IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags);
+ if(pvIORemapCookie == IMG_NULL)
+ {
+ return IMG_NULL;
+ }
+ return pvIORemapCookie;
+ }
+ else
+ {
+ LinuxMemArea *psLinuxMemArea = NewIORemapLinuxMemArea(BasePAddr, ui32Bytes, ui32MappingFlags);
+
+ if(psLinuxMemArea == IMG_NULL)
+ {
+ return IMG_NULL;
+ }
+
+ *phOSMemHandle = (IMG_HANDLE)psLinuxMemArea;
+ return LinuxMemAreaToCpuVAddr(psLinuxMemArea);
+ }
+ }
+
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSMapPhysToLin should only be used with PVRSRV_HAP_KERNEL_ONLY "
+ " (Use OSReservePhys otherwise)"));
+
+ return IMG_NULL;
+}
+
+IMG_BOOL
+OSUnMapPhysToLin(IMG_VOID *pvLinAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32MappingFlags, IMG_HANDLE hOSMemHandle)
+{
+ PVR_TRACE(("%s: unmapping %d bytes from %p", __FUNCTION__, ui32Bytes, pvLinAddr));
+
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+
+ if(ui32MappingFlags & PVRSRV_HAP_KERNEL_ONLY)
+ {
+ if (hOSMemHandle == IMG_NULL)
+ {
+ IOUnmapWrapper(pvLinAddr);
+ }
+ else
+ {
+ LinuxMemArea *psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+ PVR_ASSERT(LinuxMemAreaToCpuVAddr(psLinuxMemArea) == pvLinAddr);
+
+ FreeIORemapLinuxMemArea(psLinuxMemArea);
+ }
+
+ return IMG_TRUE;
+ }
+
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSUnMapPhysToLin should only be used with PVRSRV_HAP_KERNEL_ONLY "
+ " (Use OSUnReservePhys otherwise)"));
+ return IMG_FALSE;
+}
+
+static PVRSRV_ERROR
+RegisterExternalMem(IMG_SYS_PHYADDR *pBasePAddr,
+ IMG_VOID *pvCPUVAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_BOOL bPhysContig,
+ IMG_UINT32 ui32MappingFlags,
+ IMG_HANDLE *phOSMemHandle)
+{
+ LinuxMemArea *psLinuxMemArea;
+
+ switch(ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK)
+ {
+ case PVRSRV_HAP_KERNEL_ONLY:
+ {
+ psLinuxMemArea = NewExternalKVLinuxMemArea(pBasePAddr, pvCPUVAddr, ui32Bytes, bPhysContig, ui32MappingFlags);
+
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+ break;
+ }
+ case PVRSRV_HAP_SINGLE_PROCESS:
+ {
+ psLinuxMemArea = NewExternalKVLinuxMemArea(pBasePAddr, pvCPUVAddr, ui32Bytes, bPhysContig, ui32MappingFlags);
+
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+ PVRMMapRegisterArea(psLinuxMemArea);
+ break;
+ }
+ case PVRSRV_HAP_MULTI_PROCESS:
+ {
+
+#if defined(VIVT_CACHE) || defined(__sh__)
+
+ ui32MappingFlags &= ~PVRSRV_HAP_CACHED;
+#endif
+ psLinuxMemArea = NewExternalKVLinuxMemArea(pBasePAddr, pvCPUVAddr, ui32Bytes, bPhysContig, ui32MappingFlags);
+
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+ PVRMMapRegisterArea(psLinuxMemArea);
+ break;
+ }
+ default:
+ PVR_DPF((PVR_DBG_ERROR,"OSRegisterMem : invalid flags 0x%x\n", ui32MappingFlags));
+ *phOSMemHandle = (IMG_HANDLE)0;
+ return PVRSRV_ERROR_INVALID_FLAGS;
+ }
+
+ *phOSMemHandle = (IMG_HANDLE)psLinuxMemArea;
+
+ LinuxMemAreaRegister(psLinuxMemArea);
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+OSRegisterMem(IMG_CPU_PHYADDR BasePAddr,
+ IMG_VOID *pvCPUVAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32MappingFlags,
+ IMG_HANDLE *phOSMemHandle)
+{
+ IMG_SYS_PHYADDR SysPAddr = SysCpuPAddrToSysPAddr(BasePAddr);
+
+ return RegisterExternalMem(&SysPAddr, pvCPUVAddr, ui32Bytes, IMG_TRUE, ui32MappingFlags, phOSMemHandle);
+}
+
+
+PVRSRV_ERROR OSRegisterDiscontigMem(IMG_SYS_PHYADDR *pBasePAddr, IMG_VOID *pvCPUVAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32MappingFlags, IMG_HANDLE *phOSMemHandle)
+{
+ return RegisterExternalMem(pBasePAddr, pvCPUVAddr, ui32Bytes, IMG_FALSE, ui32MappingFlags, phOSMemHandle);
+}
+
+
+PVRSRV_ERROR
+OSUnRegisterMem (IMG_VOID *pvCpuVAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32MappingFlags,
+ IMG_HANDLE hOSMemHandle)
+{
+ LinuxMemArea *psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+ PVRSRV_ERROR eError;
+
+ PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+
+ switch(ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK)
+ {
+ case PVRSRV_HAP_KERNEL_ONLY:
+ break;
+ case PVRSRV_HAP_SINGLE_PROCESS:
+ case PVRSRV_HAP_MULTI_PROCESS:
+ {
+ eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s(%p, %d, 0x%08X, %p) FAILED!",
+ __FUNCTION__, pvCpuVAddr, ui32Bytes,
+ ui32MappingFlags, hOSMemHandle));
+ return eError;
+ }
+ break;
+ }
+ default:
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSUnRegisterMem : invalid flags 0x%x", ui32MappingFlags));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ }
+
+ LinuxMemAreaDeepFree(psLinuxMemArea);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSUnRegisterDiscontigMem(IMG_VOID *pvCpuVAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle)
+{
+ return OSUnRegisterMem(pvCpuVAddr, ui32Bytes, ui32Flags, hOSMemHandle);
+}
+
+PVRSRV_ERROR
+OSReservePhys(IMG_CPU_PHYADDR BasePAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32MappingFlags,
+ IMG_VOID **ppvCpuVAddr,
+ IMG_HANDLE *phOSMemHandle)
+{
+ LinuxMemArea *psLinuxMemArea;
+
+#if 0
+
+ if(ui32MappingFlags & PVRSRV_HAP_SINGLE_PROCESS)
+ {
+ ui32MappingFlags &= ~PVRSRV_HAP_SINGLE_PROCESS;
+ ui32MappingFlags |= PVRSRV_HAP_MULTI_PROCESS;
+ }
+#endif
+
+ switch(ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK)
+ {
+ case PVRSRV_HAP_KERNEL_ONLY:
+ {
+
+ psLinuxMemArea = NewIORemapLinuxMemArea(BasePAddr, ui32Bytes, ui32MappingFlags);
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+ break;
+ }
+ case PVRSRV_HAP_SINGLE_PROCESS:
+ {
+
+ psLinuxMemArea = NewIOLinuxMemArea(BasePAddr, ui32Bytes, ui32MappingFlags);
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+ PVRMMapRegisterArea(psLinuxMemArea);
+ break;
+ }
+ case PVRSRV_HAP_MULTI_PROCESS:
+ {
+
+#if defined(VIVT_CACHE) || defined(__sh__)
+
+ ui32MappingFlags &= ~PVRSRV_HAP_CACHED;
+#endif
+ psLinuxMemArea = NewIORemapLinuxMemArea(BasePAddr, ui32Bytes, ui32MappingFlags);
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+ PVRMMapRegisterArea(psLinuxMemArea);
+ break;
+ }
+ default:
+ PVR_DPF((PVR_DBG_ERROR,"OSMapPhysToLin : invalid flags 0x%x\n", ui32MappingFlags));
+ *ppvCpuVAddr = NULL;
+ *phOSMemHandle = (IMG_HANDLE)0;
+ return PVRSRV_ERROR_INVALID_FLAGS;
+ }
+
+ *phOSMemHandle = (IMG_HANDLE)psLinuxMemArea;
+ *ppvCpuVAddr = LinuxMemAreaToCpuVAddr(psLinuxMemArea);
+
+ LinuxMemAreaRegister(psLinuxMemArea);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+OSUnReservePhys(IMG_VOID *pvCpuVAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32MappingFlags,
+ IMG_HANDLE hOSMemHandle)
+{
+ LinuxMemArea *psLinuxMemArea;
+ PVRSRV_ERROR eError;
+
+ PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+
+ psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+ switch(ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK)
+ {
+ case PVRSRV_HAP_KERNEL_ONLY:
+ break;
+ case PVRSRV_HAP_SINGLE_PROCESS:
+ case PVRSRV_HAP_MULTI_PROCESS:
+ {
+ eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s(%p, %d, 0x%08X, %p) FAILED!",
+ __FUNCTION__, pvCpuVAddr, ui32Bytes,
+ ui32MappingFlags, hOSMemHandle));
+ return eError;
+ }
+ break;
+ }
+ default:
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSUnMapPhysToLin : invalid flags 0x%x", ui32MappingFlags));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ }
+
+ LinuxMemAreaDeepFree(psLinuxMemArea);
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSBaseAllocContigMemory(IMG_UINT32 ui32Size, IMG_CPU_VIRTADDR *pvLinAddr, IMG_CPU_PHYADDR *psPhysAddr)
+{
+#if !defined(NO_HARDWARE)
+ PVR_UNREFERENCED_PARAMETER(ui32Size);
+ PVR_UNREFERENCED_PARAMETER(pvLinAddr);
+ PVR_UNREFERENCED_PARAMETER(psPhysAddr);
+ PVR_DPF((PVR_DBG_ERROR, "%s: Not available", __FUNCTION__));
+
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+#else
+ IMG_VOID *pvKernLinAddr;
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ pvKernLinAddr = _KMallocWrapper(ui32Size, GFP_KERNEL, __FILE__, __LINE__);
+#else
+ pvKernLinAddr = KMallocWrapper(ui32Size, GFP_KERNEL);
+#endif
+ if (!pvKernLinAddr)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ *pvLinAddr = pvKernLinAddr;
+
+ psPhysAddr->uiAddr = virt_to_phys(pvKernLinAddr);
+
+ return PVRSRV_OK;
+#endif
+}
+
+
+PVRSRV_ERROR OSBaseFreeContigMemory(IMG_UINT32 ui32Size, IMG_CPU_VIRTADDR pvLinAddr, IMG_CPU_PHYADDR psPhysAddr)
+{
+#if !defined(NO_HARDWARE)
+ PVR_UNREFERENCED_PARAMETER(ui32Size);
+ PVR_UNREFERENCED_PARAMETER(pvLinAddr);
+ PVR_UNREFERENCED_PARAMETER(psPhysAddr.uiAddr);
+
+ PVR_DPF((PVR_DBG_WARNING, "%s: Not available", __FUNCTION__));
+#else
+ PVR_UNREFERENCED_PARAMETER(ui32Size);
+ PVR_UNREFERENCED_PARAMETER(psPhysAddr.uiAddr);
+
+ KFreeWrapper(pvLinAddr);
+#endif
+ return PVRSRV_OK;
+}
+
+IMG_UINT32 OSReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset)
+{
+#if !defined(NO_HARDWARE)
+ return (IMG_UINT32) readl((IMG_PBYTE)pvLinRegBaseAddr+ui32Offset);
+#else
+ return *(IMG_UINT32 *)((IMG_PBYTE)pvLinRegBaseAddr+ui32Offset);
+#endif
+}
+
+IMG_VOID OSWriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value)
+{
+#if !defined(NO_HARDWARE)
+ writel(ui32Value, (IMG_PBYTE)pvLinRegBaseAddr+ui32Offset);
+#else
+ *(IMG_UINT32 *)((IMG_PBYTE)pvLinRegBaseAddr+ui32Offset) = ui32Value;
+#endif
+}
+
+#if defined(CONFIG_PCI) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14))
+
+PVRSRV_PCI_DEV_HANDLE OSPCISetDev(IMG_VOID *pvPCICookie, HOST_PCI_INIT_FLAGS eFlags)
+{
+ int err;
+ IMG_UINT32 i;
+ PVR_PCI_DEV *psPVRPCI;
+
+ PVR_TRACE(("OSPCISetDev"));
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psPVRPCI), (IMG_VOID **)&psPVRPCI, IMG_NULL,
+ "PCI Device") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSPCISetDev: Couldn't allocate PVR PCI structure"));
+ return IMG_NULL;
+ }
+
+ psPVRPCI->psPCIDev = (struct pci_dev *)pvPCICookie;
+ psPVRPCI->ePCIFlags = eFlags;
+
+ err = pci_enable_device(psPVRPCI->psPCIDev);
+ if (err != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSPCISetDev: Couldn't enable device (%d)", err));
+ return IMG_NULL;
+ }
+
+ if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER)
+ {
+ pci_set_master(psPVRPCI->psPCIDev);
+ }
+
+ if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_MSI)
+ {
+#if defined(CONFIG_PCI_MSI)
+ err = pci_enable_msi(psPVRPCI->psPCIDev);
+ if (err != 0)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "OSPCISetDev: Couldn't enable MSI (%d)", err));
+ psPVRPCI->ePCIFlags &= ~HOST_PCI_INIT_FLAG_MSI;
+ }
+#else
+ PVR_DPF((PVR_DBG_WARNING, "OSPCISetDev: MSI support not enabled in the kernel"));
+#endif
+ }
+
+
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+ {
+ psPVRPCI->abPCIResourceInUse[i] = IMG_FALSE;
+ }
+
+ return (PVRSRV_PCI_DEV_HANDLE)psPVRPCI;
+}
+
+PVRSRV_PCI_DEV_HANDLE OSPCIAcquireDev(IMG_UINT16 ui16VendorID, IMG_UINT16 ui16DeviceID, HOST_PCI_INIT_FLAGS eFlags)
+{
+ struct pci_dev *psPCIDev;
+
+ psPCIDev = pci_get_device(ui16VendorID, ui16DeviceID, NULL);
+ if (psPCIDev == NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSPCIAcquireDev: Couldn't acquire device"));
+ return IMG_NULL;
+ }
+
+ return OSPCISetDev((IMG_VOID *)psPCIDev, eFlags);
+}
+
+PVRSRV_ERROR OSPCIIRQ(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 *pui32IRQ)
+{
+ PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+
+ *pui32IRQ = psPVRPCI->psPCIDev->irq;
+
+ return PVRSRV_OK;
+}
+
+enum HOST_PCI_ADDR_RANGE_FUNC
+{
+ HOST_PCI_ADDR_RANGE_FUNC_LEN,
+ HOST_PCI_ADDR_RANGE_FUNC_START,
+ HOST_PCI_ADDR_RANGE_FUNC_END,
+ HOST_PCI_ADDR_RANGE_FUNC_REQUEST,
+ HOST_PCI_ADDR_RANGE_FUNC_RELEASE
+};
+
+static IMG_UINT32 OSPCIAddrRangeFunc(enum HOST_PCI_ADDR_RANGE_FUNC eFunc,
+ PVRSRV_PCI_DEV_HANDLE hPVRPCI,
+ IMG_UINT32 ui32Index)
+{
+ PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+
+ if (ui32Index >= DEVICE_COUNT_RESOURCE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSPCIAddrRangeFunc: Index out of range"));
+ return 0;
+
+ }
+
+ switch (eFunc)
+ {
+ case HOST_PCI_ADDR_RANGE_FUNC_LEN:
+ return pci_resource_len(psPVRPCI->psPCIDev, ui32Index);
+ case HOST_PCI_ADDR_RANGE_FUNC_START:
+ return pci_resource_start(psPVRPCI->psPCIDev, ui32Index);
+ case HOST_PCI_ADDR_RANGE_FUNC_END:
+ return pci_resource_end(psPVRPCI->psPCIDev, ui32Index);
+ case HOST_PCI_ADDR_RANGE_FUNC_REQUEST:
+ {
+ int err;
+
+ err = pci_request_region(psPVRPCI->psPCIDev, (IMG_INT)ui32Index, PVRSRV_MODNAME);
+ if (err != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSPCIAddrRangeFunc: pci_request_region_failed (%d)", err));
+ return 0;
+ }
+ psPVRPCI->abPCIResourceInUse[ui32Index] = IMG_TRUE;
+ return 1;
+ }
+ case HOST_PCI_ADDR_RANGE_FUNC_RELEASE:
+ if (psPVRPCI->abPCIResourceInUse[ui32Index])
+ {
+ pci_release_region(psPVRPCI->psPCIDev, (IMG_INT)ui32Index);
+ psPVRPCI->abPCIResourceInUse[ui32Index] = IMG_FALSE;
+ }
+ return 1;
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "OSPCIAddrRangeFunc: Unknown function"));
+ break;
+ }
+
+ return 0;
+}
+
+IMG_UINT32 OSPCIAddrRangeLen(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
+{
+ return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_LEN, hPVRPCI, ui32Index);
+}
+
+IMG_UINT32 OSPCIAddrRangeStart(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
+{
+ return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_START, hPVRPCI, ui32Index);
+}
+
+IMG_UINT32 OSPCIAddrRangeEnd(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
+{
+ return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_END, hPVRPCI, ui32Index);
+}
+
+PVRSRV_ERROR OSPCIRequestAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI,
+ IMG_UINT32 ui32Index)
+{
+ return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_REQUEST, hPVRPCI, ui32Index) == 0 ? PVRSRV_ERROR_PCI_CALL_FAILED : PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPCIReleaseAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
+{
+ return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_RELEASE, hPVRPCI, ui32Index) == 0 ? PVRSRV_ERROR_PCI_CALL_FAILED : PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPCIReleaseDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
+{
+ PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+ int i;
+
+ PVR_TRACE(("OSPCIReleaseDev"));
+
+
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+ {
+ if (psPVRPCI->abPCIResourceInUse[i])
+ {
+ PVR_TRACE(("OSPCIReleaseDev: Releasing Address range %d", i));
+ pci_release_region(psPVRPCI->psPCIDev, i);
+ psPVRPCI->abPCIResourceInUse[i] = IMG_FALSE;
+ }
+ }
+
+#if defined(CONFIG_PCI_MSI)
+ if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_MSI)
+ {
+ pci_disable_msi(psPVRPCI->psPCIDev);
+ }
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29))
+ if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER)
+ {
+ pci_clear_master(psPVRPCI->psPCIDev);
+ }
+#endif
+ pci_disable_device(psPVRPCI->psPCIDev);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psPVRPCI), (IMG_VOID *)psPVRPCI, IMG_NULL);
+
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPCISuspendDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
+{
+ PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+ int i;
+ int err;
+
+ PVR_TRACE(("OSPCISuspendDev"));
+
+
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+ {
+ if (psPVRPCI->abPCIResourceInUse[i])
+ {
+ pci_release_region(psPVRPCI->psPCIDev, i);
+ }
+ }
+
+ err = pci_save_state(psPVRPCI->psPCIDev);
+ if (err != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSPCISuspendDev: pci_save_state_failed (%d)", err));
+ return PVRSRV_ERROR_PCI_CALL_FAILED;
+ }
+
+ pci_disable_device(psPVRPCI->psPCIDev);
+
+ err = pci_set_power_state(psPVRPCI->psPCIDev, pci_choose_state(psPVRPCI->psPCIDev, PMSG_SUSPEND));
+ switch(err)
+ {
+ case 0:
+ break;
+ case -EIO:
+ PVR_DPF((PVR_DBG_WARNING, "OSPCISuspendDev: device doesn't support PCI PM"));
+ break;
+ case -EINVAL:
+ PVR_DPF((PVR_DBG_ERROR, "OSPCISuspendDev: can't enter requested power state"));
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "OSPCISuspendDev: pci_set_power_state failed (%d)", err));
+ break;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPCIResumeDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
+{
+ PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+ int err;
+ int i;
+
+ PVR_TRACE(("OSPCIResumeDev"));
+
+ err = pci_set_power_state(psPVRPCI->psPCIDev, pci_choose_state(psPVRPCI->psPCIDev, PMSG_ON));
+ switch(err)
+ {
+ case 0:
+ break;
+ case -EIO:
+ PVR_DPF((PVR_DBG_WARNING, "OSPCIResumeDev: device doesn't support PCI PM"));
+ break;
+ case -EINVAL:
+ PVR_DPF((PVR_DBG_ERROR, "OSPCIResumeDev: can't enter requested power state"));
+ return PVRSRV_ERROR_UNKNOWN_POWER_STATE;
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "OSPCIResumeDev: pci_set_power_state failed (%d)", err));
+ return PVRSRV_ERROR_UNKNOWN_POWER_STATE;
+ }
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+ pci_restore_state(psPVRPCI->psPCIDev);
+#else
+ err = pci_restore_state(psPVRPCI->psPCIDev);
+ if (err != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSPCIResumeDev: pci_restore_state failed (%d)", err));
+ return PVRSRV_ERROR_PCI_CALL_FAILED;
+ }
+#endif
+
+ err = pci_enable_device(psPVRPCI->psPCIDev);
+ if (err != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSPCIResumeDev: Couldn't enable device (%d)", err));
+ return PVRSRV_ERROR_PCI_CALL_FAILED;
+ }
+
+ if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER)
+ pci_set_master(psPVRPCI->psPCIDev);
+
+
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+ {
+ if (psPVRPCI->abPCIResourceInUse[i])
+ {
+ err = pci_request_region(psPVRPCI->psPCIDev, i, PVRSRV_MODNAME);
+ if (err != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSPCIResumeDev: pci_request_region_failed (region %d, error %d)", i, err));
+ }
+ }
+
+ }
+
+ return PVRSRV_OK;
+}
+
+#endif
+
+#define OS_MAX_TIMERS 8
+
+typedef struct TIMER_CALLBACK_DATA_TAG
+{
+ IMG_BOOL bInUse;
+ PFN_TIMER_FUNC pfnTimerFunc;
+ IMG_VOID *pvData;
+ struct timer_list sTimer;
+ IMG_UINT32 ui32Delay;
+ IMG_BOOL bActive;
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+ struct work_struct sWork;
+#endif
+}TIMER_CALLBACK_DATA;
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+static struct workqueue_struct *psTimerWorkQueue;
+#endif
+
+static TIMER_CALLBACK_DATA sTimers[OS_MAX_TIMERS];
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+DEFINE_MUTEX(sTimerStructLock);
+#else
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39))
+
+static spinlock_t sTimerStructLock = SPIN_LOCK_UNLOCKED;
+#else
+static DEFINE_SPINLOCK(sTimerStructLock);
+#endif
+#endif
+
+static void OSTimerCallbackBody(TIMER_CALLBACK_DATA *psTimerCBData)
+{
+ if (!psTimerCBData->bActive)
+ return;
+
+
+ psTimerCBData->pfnTimerFunc(psTimerCBData->pvData);
+
+
+ mod_timer(&psTimerCBData->sTimer, psTimerCBData->ui32Delay + jiffies);
+}
+
+
+static IMG_VOID OSTimerCallbackWrapper(IMG_UINT32 ui32Data)
+{
+ TIMER_CALLBACK_DATA *psTimerCBData = (TIMER_CALLBACK_DATA*)ui32Data;
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+ int res;
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+ res = queue_work(psTimerWorkQueue, &psTimerCBData->sWork);
+#else
+ res = schedule_work(&psTimerCBData->sWork);
+#endif
+ if (res == 0)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "OSTimerCallbackWrapper: work already queued"));
+ }
+#else
+ OSTimerCallbackBody(psTimerCBData);
+#endif
+}
+
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+static void OSTimerWorkQueueCallBack(struct work_struct *psWork)
+{
+ TIMER_CALLBACK_DATA *psTimerCBData = container_of(psWork, TIMER_CALLBACK_DATA, sWork);
+
+ OSTimerCallbackBody(psTimerCBData);
+}
+#endif
+
+IMG_HANDLE OSAddTimer(PFN_TIMER_FUNC pfnTimerFunc, IMG_VOID *pvData, IMG_UINT32 ui32MsTimeout)
+{
+ TIMER_CALLBACK_DATA *psTimerCBData;
+ IMG_UINT32 ui32i;
+#if !(defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE))
+ unsigned long ulLockFlags;
+#endif
+
+
+ if(!pfnTimerFunc)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSAddTimer: passed invalid callback"));
+ return IMG_NULL;
+ }
+
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+ mutex_lock(&sTimerStructLock);
+#else
+ spin_lock_irqsave(&sTimerStructLock, ulLockFlags);
+#endif
+ for (ui32i = 0; ui32i < OS_MAX_TIMERS; ui32i++)
+ {
+ psTimerCBData = &sTimers[ui32i];
+ if (!psTimerCBData->bInUse)
+ {
+ psTimerCBData->bInUse = IMG_TRUE;
+ break;
+ }
+ }
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+ mutex_unlock(&sTimerStructLock);
+#else
+ spin_unlock_irqrestore(&sTimerStructLock, ulLockFlags);
+#endif
+ if (ui32i >= OS_MAX_TIMERS)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSAddTimer: all timers are in use"));
+ return IMG_NULL;
+ }
+
+ psTimerCBData->pfnTimerFunc = pfnTimerFunc;
+ psTimerCBData->pvData = pvData;
+ psTimerCBData->bActive = IMG_FALSE;
+
+
+
+
+ psTimerCBData->ui32Delay = ((HZ * ui32MsTimeout) < 1000)
+ ? 1
+ : ((HZ * ui32MsTimeout) / 1000);
+
+ init_timer(&psTimerCBData->sTimer);
+
+
+
+ psTimerCBData->sTimer.function = (IMG_VOID *)OSTimerCallbackWrapper;
+ psTimerCBData->sTimer.data = (IMG_UINT32)psTimerCBData;
+
+ return (IMG_HANDLE)(ui32i + 1);
+}
+
+
+static inline TIMER_CALLBACK_DATA *GetTimerStructure(IMG_HANDLE hTimer)
+{
+ IMG_UINT32 ui32i = ((IMG_UINT32)hTimer) - 1;
+
+ PVR_ASSERT(ui32i < OS_MAX_TIMERS);
+
+ return &sTimers[ui32i];
+}
+
+PVRSRV_ERROR OSRemoveTimer (IMG_HANDLE hTimer)
+{
+ TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
+
+ PVR_ASSERT(psTimerCBData->bInUse);
+ PVR_ASSERT(!psTimerCBData->bActive);
+
+
+ psTimerCBData->bInUse = IMG_FALSE;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSEnableTimer (IMG_HANDLE hTimer)
+{
+ TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
+
+ PVR_ASSERT(psTimerCBData->bInUse);
+ PVR_ASSERT(!psTimerCBData->bActive);
+
+
+ psTimerCBData->bActive = IMG_TRUE;
+
+
+ psTimerCBData->sTimer.expires = psTimerCBData->ui32Delay + jiffies;
+
+
+ add_timer(&psTimerCBData->sTimer);
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSDisableTimer (IMG_HANDLE hTimer)
+{
+ TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
+
+ PVR_ASSERT(psTimerCBData->bInUse);
+ PVR_ASSERT(psTimerCBData->bActive);
+
+
+ psTimerCBData->bActive = IMG_FALSE;
+ smp_mb();
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+ flush_workqueue(psTimerWorkQueue);
+#endif
+#if defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+ flush_scheduled_work();
+#endif
+
+
+ del_timer_sync(&psTimerCBData->sTimer);
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+
+ flush_workqueue(psTimerWorkQueue);
+#endif
+#if defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+ flush_scheduled_work();
+#endif
+
+ return PVRSRV_OK;
+}
+
+
+#if defined (SUPPORT_SID_INTERFACE)
+PVRSRV_ERROR OSEventObjectCreateKM(const IMG_CHAR *pszName, PVRSRV_EVENTOBJECT_KM *psEventObject)
+#else
+PVRSRV_ERROR OSEventObjectCreateKM(const IMG_CHAR *pszName, PVRSRV_EVENTOBJECT *psEventObject)
+#endif
+{
+
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if(psEventObject)
+ {
+ if(pszName)
+ {
+
+ strncpy(psEventObject->szName, pszName, EVENTOBJNAME_MAXLENGTH);
+ }
+ else
+ {
+
+ static IMG_UINT16 ui16NameIndex = 0;
+#if defined (SUPPORT_SID_INTERFACE)
+ snprintf(psEventObject->szName, EVENTOBJNAME_MAXLENGTH, "PVRSRV_EVENTOBJECT_KM_%d", ui16NameIndex++);
+#else
+ snprintf(psEventObject->szName, EVENTOBJNAME_MAXLENGTH, "PVRSRV_EVENTOBJECT_%d", ui16NameIndex++);
+#endif
+ }
+
+ if(LinuxEventObjectListCreate(&psEventObject->hOSEventKM) != PVRSRV_OK)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSEventObjectCreateKM: psEventObject is not a valid pointer"));
+ eError = PVRSRV_ERROR_UNABLE_TO_CREATE_EVENT;
+ }
+
+ return eError;
+
+}
+
+
+#if defined (SUPPORT_SID_INTERFACE)
+PVRSRV_ERROR OSEventObjectDestroyKM(PVRSRV_EVENTOBJECT_KM *psEventObject)
+#else
+PVRSRV_ERROR OSEventObjectDestroyKM(PVRSRV_EVENTOBJECT *psEventObject)
+#endif
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if(psEventObject)
+ {
+ if(psEventObject->hOSEventKM)
+ {
+ LinuxEventObjectListDestroy(psEventObject->hOSEventKM);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSEventObjectDestroyKM: hOSEventKM is not a valid pointer"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSEventObjectDestroyKM: psEventObject is not a valid pointer"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return eError;
+}
+
+PVRSRV_ERROR OSEventObjectWaitKM(IMG_HANDLE hOSEventKM)
+{
+ PVRSRV_ERROR eError;
+
+ if(hOSEventKM)
+ {
+ eError = LinuxEventObjectWait(hOSEventKM, EVENT_OBJECT_TIMEOUT_MS);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSEventObjectWaitKM: hOSEventKM is not a valid handle"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return eError;
+}
+
+#if defined (SUPPORT_SID_INTERFACE)
+PVRSRV_ERROR OSEventObjectOpenKM(PVRSRV_EVENTOBJECT_KM *psEventObject,
+#else
+PVRSRV_ERROR OSEventObjectOpenKM(PVRSRV_EVENTOBJECT *psEventObject,
+#endif
+ IMG_HANDLE *phOSEvent)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if(psEventObject)
+ {
+ if(LinuxEventObjectAdd(psEventObject->hOSEventKM, phOSEvent) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectAdd: failed"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSEventObjectCreateKM: psEventObject is not a valid pointer"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return eError;
+}
+
+#if defined (SUPPORT_SID_INTERFACE)
+PVRSRV_ERROR OSEventObjectCloseKM(PVRSRV_EVENTOBJECT_KM *psEventObject,
+#else
+PVRSRV_ERROR OSEventObjectCloseKM(PVRSRV_EVENTOBJECT *psEventObject,
+#endif
+ IMG_HANDLE hOSEventKM)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if(psEventObject)
+ {
+ if(LinuxEventObjectDelete(psEventObject->hOSEventKM, hOSEventKM) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectDelete: failed"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSEventObjectDestroyKM: psEventObject is not a valid pointer"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return eError;
+
+}
+
+PVRSRV_ERROR OSEventObjectSignalKM(IMG_HANDLE hOSEventKM)
+{
+ PVRSRV_ERROR eError;
+
+ if(hOSEventKM)
+ {
+ eError = LinuxEventObjectSignal(hOSEventKM);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSEventObjectSignalKM: hOSEventKM is not a valid handle"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return eError;
+}
+
+IMG_BOOL OSProcHasPrivSrvInit(IMG_VOID)
+{
+ return (capable(CAP_SYS_MODULE) != 0) ? IMG_TRUE : IMG_FALSE;
+}
+
+PVRSRV_ERROR OSCopyToUser(IMG_PVOID pvProcess,
+ IMG_VOID *pvDest,
+ IMG_VOID *pvSrc,
+ IMG_UINT32 ui32Bytes)
+{
+ PVR_UNREFERENCED_PARAMETER(pvProcess);
+
+ if(pvr_copy_to_user(pvDest, pvSrc, ui32Bytes)==0)
+ return PVRSRV_OK;
+ else
+ return PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY;
+}
+
+PVRSRV_ERROR OSCopyFromUser( IMG_PVOID pvProcess,
+ IMG_VOID *pvDest,
+ IMG_VOID *pvSrc,
+ IMG_UINT32 ui32Bytes)
+{
+ PVR_UNREFERENCED_PARAMETER(pvProcess);
+
+ if(pvr_copy_from_user(pvDest, pvSrc, ui32Bytes)==0)
+ return PVRSRV_OK;
+ else
+ return PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY;
+}
+
+IMG_BOOL OSAccessOK(IMG_VERIFY_TEST eVerification, IMG_VOID *pvUserPtr, IMG_UINT32 ui32Bytes)
+{
+ IMG_INT linuxType;
+
+ if (eVerification == PVR_VERIFY_READ)
+ {
+ linuxType = VERIFY_READ;
+ }
+ else
+ {
+ PVR_ASSERT(eVerification == PVR_VERIFY_WRITE);
+ linuxType = VERIFY_WRITE;
+ }
+
+ return access_ok(linuxType, pvUserPtr, ui32Bytes);
+}
+
+typedef enum _eWrapMemType_
+{
+ WRAP_TYPE_NULL = 0,
+ WRAP_TYPE_GET_USER_PAGES,
+ WRAP_TYPE_FIND_VMA
+} eWrapMemType;
+
+typedef struct _sWrapMemInfo_
+{
+ eWrapMemType eType;
+ IMG_INT iNumPages;
+ IMG_INT iNumPagesMapped;
+ struct page **ppsPages;
+ IMG_SYS_PHYADDR *psPhysAddr;
+ IMG_INT iPageOffset;
+#if defined(DEBUG)
+ IMG_UINT32 ulStartAddr;
+ IMG_UINT32 ulBeyondEndAddr;
+ struct vm_area_struct *psVMArea;
+#endif
+} sWrapMemInfo;
+
+
+static IMG_BOOL CPUVAddrToPFN(struct vm_area_struct *psVMArea, IMG_UINT32 ulCPUVAddr, IMG_UINT32 *pulPFN, struct page **ppsPage)
+{
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10))
+ pgd_t *psPGD;
+ pud_t *psPUD;
+ pmd_t *psPMD;
+ pte_t *psPTE;
+ struct mm_struct *psMM = psVMArea->vm_mm;
+ spinlock_t *psPTLock;
+ IMG_BOOL bRet = IMG_FALSE;
+
+ *pulPFN = 0;
+ *ppsPage = NULL;
+
+ psPGD = pgd_offset(psMM, ulCPUVAddr);
+ if (pgd_none(*psPGD) || pgd_bad(*psPGD))
+ return bRet;
+
+ psPUD = pud_offset(psPGD, ulCPUVAddr);
+ if (pud_none(*psPUD) || pud_bad(*psPUD))
+ return bRet;
+
+ psPMD = pmd_offset(psPUD, ulCPUVAddr);
+ if (pmd_none(*psPMD) || pmd_bad(*psPMD))
+ return bRet;
+
+ psPTE = (pte_t *)pte_offset_map_lock(psMM, psPMD, ulCPUVAddr, &psPTLock);
+
+ if ((pte_none(*psPTE) == 0) && (pte_present(*psPTE) != 0) && (pte_write(*psPTE) != 0))
+ {
+ *pulPFN = pte_pfn(*psPTE);
+ bRet = IMG_TRUE;
+
+ if (pfn_valid(*pulPFN))
+ {
+ *ppsPage = pfn_to_page(*pulPFN);
+
+ get_page(*ppsPage);
+ }
+ }
+
+ pte_unmap_unlock(psPTE, psPTLock);
+
+ return bRet;
+#else
+ return IMG_FALSE;
+#endif
+}
+
+PVRSRV_ERROR OSReleasePhysPageAddr(IMG_HANDLE hOSWrapMem)
+{
+ sWrapMemInfo *psInfo = (sWrapMemInfo *)hOSWrapMem;
+ IMG_INT i;
+
+ if (psInfo == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "OSReleasePhysPageAddr: called with null wrap handle"));
+ return PVRSRV_OK;
+ }
+
+ switch (psInfo->eType)
+ {
+ case WRAP_TYPE_NULL:
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "OSReleasePhysPageAddr: called with wrap type WRAP_TYPE_NULL"));
+ break;
+ }
+ case WRAP_TYPE_GET_USER_PAGES:
+ {
+ for (i = 0; i < psInfo->iNumPagesMapped; i++)
+ {
+ struct page *psPage = psInfo->ppsPages[i];
+
+ PVR_ASSERT(psPage != NULL);
+
+
+ if (psInfo->iNumPagesMapped == psInfo->iNumPages)
+ {
+ if (!PageReserved(psPage))
+ {
+ SetPageDirty(psPage);
+ }
+ }
+ page_cache_release(psPage);
+ }
+ break;
+ }
+ case WRAP_TYPE_FIND_VMA:
+ {
+ for (i = 0; i < psInfo->iNumPages; i++)
+ {
+ if (psInfo->ppsPages[i] != IMG_NULL)
+ {
+ put_page(psInfo->ppsPages[i]);
+ }
+ }
+ break;
+ }
+ default:
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSReleasePhysPageAddr: Unknown wrap type (%d)", psInfo->eType));
+ return PVRSRV_ERROR_INVALID_WRAP_TYPE;
+ }
+ }
+
+ if (psInfo->ppsPages != IMG_NULL)
+ {
+ kfree(psInfo->ppsPages);
+ }
+
+ if (psInfo->psPhysAddr != IMG_NULL)
+ {
+ kfree(psInfo->psPhysAddr);
+ }
+
+ kfree(psInfo);
+
+ return PVRSRV_OK;
+}
+
+#if defined(CONFIG_TI_TILER)
+
+static IMG_UINT32 CPUAddrToTilerPhy(IMG_UINT32 uiAddr)
+{
+ IMG_UINT32 ui32PhysAddr = 0;
+ pte_t *ptep, pte;
+ pgd_t *pgd;
+ pmd_t *pmd;
+
+ pgd = pgd_offset(current->mm, uiAddr);
+ if (pgd_none(*pgd) || pgd_bad(*pgd))
+ goto err_out;
+
+ pmd = pmd_offset(pgd, uiAddr);
+ if (pmd_none(*pmd) || pmd_bad(*pmd))
+ goto err_out;
+
+ ptep = pte_offset_map(pmd, uiAddr);
+ if (!ptep)
+ goto err_out;
+
+ pte = *ptep;
+ if (!pte_present(pte))
+ goto err_out;
+
+ ui32PhysAddr = (pte & PAGE_MASK) | (~PAGE_MASK & uiAddr);
+
+
+ if (ui32PhysAddr < 0x60000000 && ui32PhysAddr > 0x7fffffff)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CPUAddrToTilerPhy: Not in tiler range"));
+ ui32PhysAddr = 0;
+ goto err_out;
+ }
+
+err_out:
+ return ui32PhysAddr;
+}
+
+#endif
+
+PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID *pvCPUVAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_SYS_PHYADDR *psSysPAddr,
+ IMG_HANDLE *phOSWrapMem)
+{
+ IMG_UINT32 ulStartAddrOrig = (IMG_UINT32) pvCPUVAddr;
+ IMG_UINT32 ulAddrRangeOrig = (IMG_UINT32) ui32Bytes;
+ IMG_UINT32 ulBeyondEndAddrOrig = ulStartAddrOrig + ulAddrRangeOrig;
+ IMG_UINT32 ulStartAddr;
+ IMG_UINT32 ulAddrRange;
+ IMG_UINT32 ulBeyondEndAddr;
+ IMG_UINT32 ulAddr;
+ IMG_INT i;
+ struct vm_area_struct *psVMArea;
+ sWrapMemInfo *psInfo = NULL;
+ IMG_BOOL bHavePageStructs = IMG_FALSE;
+ IMG_BOOL bHaveNoPageStructs = IMG_FALSE;
+ IMG_BOOL bMMapSemHeld = IMG_FALSE;
+ PVRSRV_ERROR eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+
+ ulStartAddr = ulStartAddrOrig & PAGE_MASK;
+ ulBeyondEndAddr = PAGE_ALIGN(ulBeyondEndAddrOrig);
+ ulAddrRange = ulBeyondEndAddr - ulStartAddr;
+
+
+ if (ulBeyondEndAddr <= ulStartAddr)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: Invalid address range (start %x, length %x)",
+ ulStartAddrOrig, ulAddrRangeOrig));
+ goto error;
+ }
+
+
+ psInfo = kmalloc(sizeof(*psInfo), GFP_KERNEL);
+ if (psInfo == NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: Couldn't allocate information structure"));
+ goto error;
+ }
+ memset(psInfo, 0, sizeof(*psInfo));
+
+#if defined(DEBUG)
+ psInfo->ulStartAddr = ulStartAddrOrig;
+ psInfo->ulBeyondEndAddr = ulBeyondEndAddrOrig;
+#endif
+
+ psInfo->iNumPages = (IMG_INT)(ulAddrRange >> PAGE_SHIFT);
+ psInfo->iPageOffset = (IMG_INT)(ulStartAddrOrig & ~PAGE_MASK);
+
+
+ psInfo->psPhysAddr = kmalloc((size_t)psInfo->iNumPages * sizeof(*psInfo->psPhysAddr), GFP_KERNEL);
+ if (psInfo->psPhysAddr == NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: Couldn't allocate page array"));
+ goto error;
+ }
+ memset(psInfo->psPhysAddr, 0, (size_t)psInfo->iNumPages * sizeof(*psInfo->psPhysAddr));
+
+
+ psInfo->ppsPages = kmalloc((size_t)psInfo->iNumPages * sizeof(*psInfo->ppsPages), GFP_KERNEL);
+ if (psInfo->ppsPages == NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: Couldn't allocate page array"));
+ goto error;
+ }
+ memset(psInfo->ppsPages, 0, (size_t)psInfo->iNumPages * sizeof(*psInfo->ppsPages));
+
+
+ eError = PVRSRV_ERROR_BAD_MAPPING;
+
+
+ psInfo->eType = WRAP_TYPE_GET_USER_PAGES;
+
+
+ down_read(&current->mm->mmap_sem);
+ bMMapSemHeld = IMG_TRUE;
+
+
+ psInfo->iNumPagesMapped = get_user_pages(current, current->mm, ulStartAddr, psInfo->iNumPages, 1, 0, psInfo->ppsPages, NULL);
+
+ if (psInfo->iNumPagesMapped >= 0)
+ {
+
+ if (psInfo->iNumPagesMapped != psInfo->iNumPages)
+ {
+ PVR_TRACE(("OSAcquirePhysPageAddr: Couldn't map all the pages needed (wanted: %d, got %d)", psInfo->iNumPages, psInfo->iNumPagesMapped));
+
+ goto error;
+ }
+
+
+ for (i = 0; i < psInfo->iNumPages; i++)
+ {
+ IMG_CPU_PHYADDR CPUPhysAddr;
+ IMG_UINT32 ulPFN;
+
+ ulPFN = page_to_pfn(psInfo->ppsPages[i]);
+ CPUPhysAddr.uiAddr = ulPFN << PAGE_SHIFT;
+ if ((CPUPhysAddr.uiAddr >> PAGE_SHIFT) != ulPFN)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: Page frame number out of range (%x)", ulPFN));
+
+ goto error;
+ }
+ psInfo->psPhysAddr[i] = SysCpuPAddrToSysPAddr(CPUPhysAddr);
+ psSysPAddr[i] = psInfo->psPhysAddr[i];
+
+ }
+
+ goto exit;
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE, "OSAcquirePhysPageAddr: get_user_pages failed (%d), using CPU page table", psInfo->iNumPagesMapped));
+
+
+ psInfo->eType = WRAP_TYPE_NULL;
+ psInfo->iNumPagesMapped = 0;
+ memset(psInfo->ppsPages, 0, (size_t)psInfo->iNumPages * sizeof(*psInfo->ppsPages));
+
+
+
+ psInfo->eType = WRAP_TYPE_FIND_VMA;
+
+ psVMArea = find_vma(current->mm, ulStartAddrOrig);
+ if (psVMArea == NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: Couldn't find memory region containing start address %x", ulStartAddrOrig));
+
+ goto error;
+ }
+#if defined(DEBUG)
+ psInfo->psVMArea = psVMArea;
+#endif
+
+
+ if (ulStartAddrOrig < psVMArea->vm_start)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: Start address %x is outside of the region returned by find_vma", ulStartAddrOrig));
+ goto error;
+ }
+
+
+ if (ulBeyondEndAddrOrig > psVMArea->vm_end)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: End address %x is outside of the region returned by find_vma", ulBeyondEndAddrOrig));
+ goto error;
+ }
+
+
+ if ((psVMArea->vm_flags & (VM_IO | VM_RESERVED)) != (VM_IO | VM_RESERVED))
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: Memory region does not represent memory mapped I/O (VMA flags: 0x%lx)", psVMArea->vm_flags));
+ goto error;
+ }
+
+
+ if ((psVMArea->vm_flags & (VM_READ | VM_WRITE)) != (VM_READ | VM_WRITE))
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: No read/write access to memory region (VMA flags: 0x%lx)", psVMArea->vm_flags));
+ goto error;
+ }
+
+ for (ulAddr = ulStartAddrOrig, i = 0; ulAddr < ulBeyondEndAddrOrig; ulAddr += PAGE_SIZE, i++)
+ {
+ IMG_CPU_PHYADDR CPUPhysAddr;
+ IMG_UINT32 ulPFN = 0;
+
+ PVR_ASSERT(i < psInfo->iNumPages);
+
+ if (!CPUVAddrToPFN(psVMArea, ulAddr, &ulPFN, &psInfo->ppsPages[i]))
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: Invalid CPU virtual address"));
+
+ goto error;
+ }
+ if (psInfo->ppsPages[i] == NULL)
+ {
+#if defined(CONFIG_TI_TILER)
+
+ IMG_UINT32 ui32TilerAddr = CPUAddrToTilerPhy(ulAddr);
+ if (ui32TilerAddr)
+ {
+ bHavePageStructs = IMG_TRUE;
+ psInfo->iNumPagesMapped++;
+ psInfo->psPhysAddr[i].uiAddr = ui32TilerAddr;
+ psSysPAddr[i].uiAddr = ui32TilerAddr;
+ continue;
+ }
+#endif
+
+ bHaveNoPageStructs = IMG_TRUE;
+ }
+ else
+ {
+ bHavePageStructs = IMG_TRUE;
+
+ psInfo->iNumPagesMapped++;
+
+ PVR_ASSERT(ulPFN == page_to_pfn(psInfo->ppsPages[i]));
+ }
+
+ CPUPhysAddr.uiAddr = ulPFN << PAGE_SHIFT;
+ if ((CPUPhysAddr.uiAddr >> PAGE_SHIFT) != ulPFN)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: Page frame number out of range (%x)", ulPFN));
+
+ goto error;
+ }
+
+ psInfo->psPhysAddr[i] = SysCpuPAddrToSysPAddr(CPUPhysAddr);
+ psSysPAddr[i] = psInfo->psPhysAddr[i];
+ }
+ PVR_ASSERT(i == psInfo->iNumPages);
+
+#if defined(VM_MIXEDMAP)
+ if ((psVMArea->vm_flags & VM_MIXEDMAP) != 0)
+ {
+ goto exit;
+ }
+#endif
+
+ if (bHavePageStructs && bHaveNoPageStructs)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: Region is VM_MIXEDMAP, but isn't marked as such"));
+ goto error;
+ }
+
+ if (!bHaveNoPageStructs)
+ {
+
+ goto exit;
+ }
+
+#if defined(VM_PFNMAP)
+ if ((psVMArea->vm_flags & VM_PFNMAP) == 0)
+#endif
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: Region is VM_PFNMAP, but isn't marked as such"));
+ goto error;
+ }
+
+exit:
+ PVR_ASSERT(bMMapSemHeld);
+ up_read(&current->mm->mmap_sem);
+
+
+ *phOSWrapMem = (IMG_HANDLE)psInfo;
+
+ if (bHaveNoPageStructs)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "OSAcquirePhysPageAddr: Region contains pages which can't be locked down (no page structures)"));
+ }
+
+ PVR_ASSERT(psInfo->eType != 0);
+
+#if 0
+
+
+ OSCleanCPUCacheRangeKM(pvCPUVAddr, (IMG_VOID *)((IMG_CHAR *)pvCPUVAddr + ui32Bytes));
+#endif
+
+ return PVRSRV_OK;
+
+error:
+ if (bMMapSemHeld)
+ {
+ up_read(&current->mm->mmap_sem);
+ }
+ OSReleasePhysPageAddr((IMG_HANDLE)psInfo);
+
+ PVR_ASSERT(eError != PVRSRV_OK);
+
+ return eError;
+}
+
+typedef void (*InnerCacheOp_t)(const void *pvStart, const void *pvEnd);
+
+#if defined(__arm__) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39))
+typedef void (*OuterCacheOp_t)(phys_addr_t uStart, phys_addr_t uEnd);
+#else
+typedef void (*OuterCacheOp_t)(unsigned long ulStart, unsigned long ulEnd);
+#endif
+
+#if defined(CONFIG_OUTER_CACHE)
+
+typedef unsigned long (*MemAreaToPhys_t)(LinuxMemArea *psLinuxMemArea,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32PageNumOffset,
+ IMG_UINT32 ui32PageNum);
+
+static unsigned long VMallocAreaToPhys(LinuxMemArea *psLinuxMemArea,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32PageNumOffset,
+ IMG_UINT32 ui32PageNum)
+{
+ return vmalloc_to_pfn(pvRangeAddrStart + ui32PageNum * PAGE_SIZE) << PAGE_SHIFT;
+}
+
+static unsigned long ExternalKVAreaToPhys(LinuxMemArea *psLinuxMemArea,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32PageNumOffset,
+ IMG_UINT32 ui32PageNum)
+{
+ IMG_SYS_PHYADDR SysPAddr;
+ IMG_CPU_PHYADDR CpuPAddr;
+ SysPAddr = psLinuxMemArea->uData.sExternalKV.uPhysAddr.pSysPhysAddr[ui32PageNumOffset + ui32PageNum];
+ CpuPAddr = SysSysPAddrToCpuPAddr(SysPAddr);
+ return CpuPAddr.uiAddr;
+}
+
+static unsigned long AllocPagesAreaToPhys(LinuxMemArea *psLinuxMemArea,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32PageNumOffset,
+ IMG_UINT32 ui32PageNum)
+{
+ struct page *pPage;
+ pPage = psLinuxMemArea->uData.sPageList.ppsPageList[ui32PageNumOffset + ui32PageNum];
+ return page_to_pfn(pPage) << PAGE_SHIFT;
+}
+
+static unsigned long IONAreaToPhys(LinuxMemArea *psLinuxMemArea,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32PageNumOffset,
+ IMG_UINT32 ui32PageNum)
+{
+ IMG_CPU_PHYADDR CpuPAddr;
+ CpuPAddr = psLinuxMemArea->uData.sIONTilerAlloc.pCPUPhysAddrs[ui32PageNumOffset + ui32PageNum];
+ return CpuPAddr.uiAddr;
+}
+
+#endif
+
+static
+IMG_VOID *FindMMapBaseVAddr(struct list_head *psMMapOffsetStructList,
+ IMG_VOID *pvRangeAddrStart, IMG_UINT32 ui32Length)
+{
+ PKV_OFFSET_STRUCT psOffsetStruct;
+ IMG_VOID *pvMinVAddr;
+
+
+ list_for_each_entry(psOffsetStruct, psMMapOffsetStructList, sAreaItem)
+ {
+ if(OSGetCurrentProcessIDKM() != psOffsetStruct->ui32PID)
+ continue;
+
+ pvMinVAddr = (IMG_VOID *)psOffsetStruct->ui32UserVAddr;
+
+
+ if(pvRangeAddrStart >= pvMinVAddr &&
+ ui32Length <= psOffsetStruct->ui32RealByteSize)
+ return pvMinVAddr;
+ }
+
+ return IMG_NULL;
+}
+
+extern PVRSRV_LINUX_MUTEX g_sMMapMutex;
+
+static
+IMG_BOOL CheckExecuteCacheOp(IMG_HANDLE hOSMemHandle,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32Length,
+ InnerCacheOp_t pfnInnerCacheOp,
+ OuterCacheOp_t pfnOuterCacheOp)
+{
+ LinuxMemArea *psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+ IMG_UINT32 ui32AreaLength, ui32AreaOffset = 0;
+ struct list_head *psMMapOffsetStructList;
+ IMG_VOID *pvMinVAddr;
+
+#if defined(CONFIG_OUTER_CACHE)
+ MemAreaToPhys_t pfnMemAreaToPhys = IMG_NULL;
+ IMG_UINT32 ui32PageNumOffset = 0;
+#endif
+
+ PVR_ASSERT(psLinuxMemArea != IMG_NULL);
+
+ LinuxLockMutex(&g_sMMapMutex);
+
+ psMMapOffsetStructList = &psLinuxMemArea->sMMapOffsetStructList;
+ ui32AreaLength = psLinuxMemArea->ui32ByteSize;
+
+ PVR_ASSERT(ui32Length <= ui32AreaLength);
+
+ if(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC)
+ {
+ ui32AreaOffset = psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset;
+ psLinuxMemArea = psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea;
+ }
+
+
+ PVR_ASSERT(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC);
+
+ switch(psLinuxMemArea->eAreaType)
+ {
+ case LINUX_MEM_AREA_VMALLOC:
+ {
+ if(is_vmalloc_addr(pvRangeAddrStart))
+ {
+ pvMinVAddr = psLinuxMemArea->uData.sVmalloc.pvVmallocAddress + ui32AreaOffset;
+
+
+ if(pvRangeAddrStart < pvMinVAddr)
+ goto err_blocked;
+
+ pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
+ }
+ else
+ {
+
+ pvMinVAddr = FindMMapBaseVAddr(psMMapOffsetStructList,
+ pvRangeAddrStart, ui32Length);
+ if(!pvMinVAddr)
+ goto err_blocked;
+
+ pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
+
+#if defined(CONFIG_OUTER_CACHE)
+
+ pvRangeAddrStart = psLinuxMemArea->uData.sVmalloc.pvVmallocAddress +
+ (ui32AreaOffset & PAGE_MASK) + (pvRangeAddrStart - pvMinVAddr);
+ }
+
+ pfnMemAreaToPhys = VMallocAreaToPhys;
+#else
+ }
+#endif
+ break;
+ }
+
+ case LINUX_MEM_AREA_EXTERNAL_KV:
+ {
+
+ if (psLinuxMemArea->uData.sExternalKV.bPhysContig == IMG_TRUE)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "%s: Attempt to flush contiguous external memory", __func__));
+ goto err_blocked;
+ }
+
+
+ if (psLinuxMemArea->uData.sExternalKV.pvExternalKV != IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "%s: Attempt to flush external memory with a kernel virtual address", __func__));
+ goto err_blocked;
+ }
+
+ pvMinVAddr = FindMMapBaseVAddr(psMMapOffsetStructList,
+ pvRangeAddrStart, ui32Length);
+ if(!pvMinVAddr)
+ goto err_blocked;
+
+ pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
+
+#if defined(CONFIG_OUTER_CACHE)
+ ui32PageNumOffset = ((ui32AreaOffset & PAGE_MASK) + (pvRangeAddrStart - pvMinVAddr)) >> PAGE_SHIFT;
+ pfnMemAreaToPhys = ExternalKVAreaToPhys;
+#endif
+ break;
+ }
+
+ case LINUX_MEM_AREA_ION:
+ {
+ pvMinVAddr = FindMMapBaseVAddr(psMMapOffsetStructList,
+ pvRangeAddrStart, ui32Length);
+ if(!pvMinVAddr)
+ goto err_blocked;
+
+ pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
+
+#if defined(CONFIG_OUTER_CACHE)
+ ui32PageNumOffset = ((ui32AreaOffset & PAGE_MASK) + (pvRangeAddrStart - pvMinVAddr)) >> PAGE_SHIFT;
+ pfnMemAreaToPhys = IONAreaToPhys;
+#endif
+ break;
+ }
+
+ case LINUX_MEM_AREA_ALLOC_PAGES:
+ {
+ pvMinVAddr = FindMMapBaseVAddr(psMMapOffsetStructList,
+ pvRangeAddrStart, ui32Length);
+ if(!pvMinVAddr)
+ goto err_blocked;
+
+ pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
+
+#if defined(CONFIG_OUTER_CACHE)
+ ui32PageNumOffset = ((ui32AreaOffset & PAGE_MASK) + (pvRangeAddrStart - pvMinVAddr)) >> PAGE_SHIFT;
+ pfnMemAreaToPhys = AllocPagesAreaToPhys;
+#endif
+ break;
+ }
+
+ default:
+ PVR_DBG_BREAK;
+ }
+
+ LinuxUnLockMutex(&g_sMMapMutex);
+
+#if defined(CONFIG_OUTER_CACHE)
+ PVR_ASSERT(pfnMemAreaToPhys != IMG_NULL);
+
+
+ {
+ unsigned long ulStart, ulEnd, ulLength, ulStartOffset, ulEndOffset;
+ IMG_UINT32 i, ui32NumPages;
+
+
+ ulLength = (unsigned long)ui32Length;
+ ulStartOffset = ((unsigned long)pvRangeAddrStart) & (PAGE_SIZE - 1);
+ ulEndOffset = ((unsigned long)pvRangeAddrStart + ulLength) & (PAGE_SIZE - 1);
+
+
+ ui32NumPages = (ulStartOffset + ulLength + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+ for(i = 0; i < ui32NumPages; i++)
+ {
+ ulStart = pfnMemAreaToPhys(psLinuxMemArea, pvRangeAddrStart,
+ ui32PageNumOffset, i);
+ ulEnd = ulStart + PAGE_SIZE;
+
+ if(i == ui32NumPages - 1 && ulEndOffset != 0)
+ ulEnd = ulStart + ulEndOffset;
+
+ if(i == 0)
+ ulStart += ulStartOffset;
+
+ pfnOuterCacheOp(ulStart, ulEnd);
+ }
+ }
+#endif
+
+ return IMG_TRUE;
+
+err_blocked:
+ PVR_DPF((PVR_DBG_WARNING, "%s: Blocked cache op on virtual range "
+ "%p-%p (type %d)", __func__,
+ pvRangeAddrStart, pvRangeAddrStart + ui32Length,
+ psLinuxMemArea->eAreaType));
+ LinuxUnLockMutex(&g_sMMapMutex);
+ return IMG_FALSE;
+}
+
+#if defined(__i386__)
+
+#define ROUND_UP(x,a) (((x) + (a) - 1) & ~((a) - 1))
+
+static void per_cpu_cache_flush(void *arg)
+{
+ PVR_UNREFERENCED_PARAMETER(arg);
+ wbinvd();
+}
+
+static void x86_flush_cache_range(const void *pvStart, const void *pvEnd)
+{
+ IMG_BYTE *pbStart = (IMG_BYTE *)pvStart;
+ IMG_BYTE *pbEnd = (IMG_BYTE *)pvEnd;
+ IMG_BYTE *pbBase;
+
+ pbEnd = (IMG_BYTE *)ROUND_UP((IMG_UINTPTR_T)pbEnd,
+ boot_cpu_data.x86_clflush_size);
+
+ mb();
+ for(pbBase = pbStart; pbBase < pbEnd; pbBase += boot_cpu_data.x86_clflush_size)
+ clflush(pbBase);
+ mb();
+}
+
+IMG_VOID OSCleanCPUCacheKM(IMG_VOID)
+{
+
+ ON_EACH_CPU(per_cpu_cache_flush, NULL, 1);
+}
+
+IMG_VOID OSFlushCPUCacheKM(IMG_VOID)
+{
+ ON_EACH_CPU(per_cpu_cache_flush, NULL, 1);
+}
+
+IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32Length)
+{
+
+ return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
+ x86_flush_cache_range, IMG_NULL);
+}
+
+IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32Length)
+{
+
+ return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
+ x86_flush_cache_range, IMG_NULL);
+}
+
+IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32Length)
+{
+
+ return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
+ x86_flush_cache_range, IMG_NULL);
+}
+
+#else
+
+#if defined(__arm__)
+
+static void per_cpu_cache_flush(void *arg)
+{
+ PVR_UNREFERENCED_PARAMETER(arg);
+ flush_cache_all();
+}
+
+IMG_VOID OSCleanCPUCacheKM(IMG_VOID)
+{
+
+ ON_EACH_CPU(per_cpu_cache_flush, NULL, 1);
+#if defined(CONFIG_OUTER_CACHE) && !defined(PVR_NO_FULL_CACHE_OPS)
+ outer_clean_range(0, ULONG_MAX);
+#endif
+}
+
+IMG_VOID OSFlushCPUCacheKM(IMG_VOID)
+{
+ ON_EACH_CPU(per_cpu_cache_flush, NULL, 1);
+#if defined(CONFIG_OUTER_CACHE) && !defined(PVR_NO_FULL_CACHE_OPS)
+ outer_flush_all();
+#endif
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34))
+static inline size_t pvr_dmac_range_len(const void *pvStart, const void *pvEnd)
+{
+ return (size_t)((char *)pvEnd - (char *)pvStart);
+}
+#endif
+
+static void pvr_dmac_inv_range(const void *pvStart, const void *pvEnd)
+{
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34))
+ dmac_inv_range(pvStart, pvEnd);
+#else
+ dmac_map_area(pvStart, pvr_dmac_range_len(pvStart, pvEnd), DMA_FROM_DEVICE);
+#endif
+}
+
+static void pvr_dmac_clean_range(const void *pvStart, const void *pvEnd)
+{
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34))
+ dmac_clean_range(pvStart, pvEnd);
+#else
+ dmac_map_area(pvStart, pvr_dmac_range_len(pvStart, pvEnd), DMA_TO_DEVICE);
+#endif
+}
+
+IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32Length)
+{
+ return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
+ dmac_flush_range, outer_flush_range);
+}
+
+IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32Length)
+{
+ return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
+ pvr_dmac_clean_range, outer_clean_range);
+}
+
+IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32Length)
+{
+ return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
+ pvr_dmac_inv_range, outer_inv_range);
+}
+
+#else
+
+#if defined(__mips__)
+IMG_VOID OSCleanCPUCacheKM(IMG_VOID)
+{
+
+ dma_cache_wback(0, 0x100000);
+}
+
+IMG_VOID OSFlushCPUCacheKM(IMG_VOID)
+{
+
+ dma_cache_wback_inv(0, 0x100000);
+}
+
+IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32Length)
+{
+ if (ui32Length)
+ dma_cache_wback_inv((IMG_UINTPTR_T)pvRangeAddrStart, ui32Length);
+ return IMG_TRUE;
+}
+
+IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32Length)
+{
+ if (ui32Length)
+ dma_cache_wback((IMG_UINTPTR_T)pvRangeAddrStart, ui32Length);
+ return IMG_TRUE;
+}
+
+IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32Length)
+{
+ if (ui32Length)
+ dma_cache_inv((IMG_UINTPTR_T)pvRangeAddrStart, ui32Length);
+ return IMG_TRUE;
+}
+
+#else
+
+#error "Implement CPU cache flush/clean/invalidate primitives for this CPU!"
+
+#endif
+
+#endif
+
+#endif
+
+typedef struct _AtomicStruct
+{
+ atomic_t RefCount;
+} AtomicStruct;
+
+PVRSRV_ERROR OSAtomicAlloc(IMG_PVOID *ppvRefCount)
+{
+ AtomicStruct *psRefCount;
+
+ psRefCount = kmalloc(sizeof(AtomicStruct), GFP_KERNEL);
+ if (psRefCount == NULL)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ atomic_set(&psRefCount->RefCount, 0);
+
+ *ppvRefCount = psRefCount;
+ return PVRSRV_OK;
+}
+
+IMG_VOID OSAtomicFree(IMG_PVOID pvRefCount)
+{
+ AtomicStruct *psRefCount = pvRefCount;
+
+ PVR_ASSERT(atomic_read(&psRefCount->RefCount) == 0);
+ kfree(psRefCount);
+}
+
+IMG_VOID OSAtomicInc(IMG_PVOID pvRefCount)
+{
+ AtomicStruct *psRefCount = pvRefCount;
+
+ atomic_inc(&psRefCount->RefCount);
+}
+
+IMG_BOOL OSAtomicDecAndTest(IMG_PVOID pvRefCount)
+{
+ AtomicStruct *psRefCount = pvRefCount;
+
+ return atomic_dec_and_test(&psRefCount->RefCount) ? IMG_TRUE:IMG_FALSE;
+}
+
+IMG_UINT32 OSAtomicRead(IMG_PVOID pvRefCount)
+{
+ AtomicStruct *psRefCount = pvRefCount;
+
+ return (IMG_UINT32) atomic_read(&psRefCount->RefCount);
+}
+
+IMG_VOID OSReleaseBridgeLock(IMG_VOID)
+{
+ LinuxUnLockMutex(&gPVRSRVLock);
+}
+
+IMG_VOID OSReacquireBridgeLock(IMG_VOID)
+{
+ LinuxLockMutex(&gPVRSRVLock);
+}
+
+typedef struct _OSTime
+{
+ unsigned long ulTime;
+} OSTime;
+
+PVRSRV_ERROR OSTimeCreateWithUSOffset(IMG_PVOID *pvRet, IMG_UINT32 ui32USOffset)
+{
+ OSTime *psOSTime;
+
+ psOSTime = kmalloc(sizeof(OSTime), GFP_KERNEL);
+ if (psOSTime == IMG_NULL)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ psOSTime->ulTime = usecs_to_jiffies(jiffies_to_usecs(jiffies) + ui32USOffset);
+ *pvRet = psOSTime;
+ return PVRSRV_OK;
+}
+
+
+IMG_BOOL OSTimeHasTimePassed(IMG_PVOID pvData)
+{
+ OSTime *psOSTime = pvData;
+
+ if (time_is_before_jiffies(psOSTime->ulTime))
+ {
+ return IMG_TRUE;
+ }
+ return IMG_FALSE;
+}
+
+IMG_VOID OSTimeDestroy(IMG_PVOID pvData)
+{
+ kfree(pvData);
+}
+
+PVRSRV_ERROR PVROSFuncInit(IMG_VOID)
+{
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+ {
+ psTimerWorkQueue = create_workqueue("pvr_timer");
+ if (psTimerWorkQueue == NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: couldn't create timer workqueue", __FUNCTION__));
+ return PVRSRV_ERROR_UNABLE_TO_CREATE_THREAD;
+
+ }
+ }
+#endif
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+ {
+ IMG_UINT32 ui32i;
+
+ for (ui32i = 0; ui32i < OS_MAX_TIMERS; ui32i++)
+ {
+ TIMER_CALLBACK_DATA *psTimerCBData = &sTimers[ui32i];
+
+ INIT_WORK(&psTimerCBData->sWork, OSTimerWorkQueueCallBack);
+ }
+ }
+#endif
+ return PVRSRV_OK;
+}
+
+IMG_VOID PVROSFuncDeInit(IMG_VOID)
+{
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+ if (psTimerWorkQueue != NULL)
+ {
+ destroy_workqueue(psTimerWorkQueue);
+ }
+#endif
+}
diff --git a/drivers/gpu/pvr/osfunc.h b/drivers/gpu/pvr/osfunc.h
new file mode 100644
index 0000000..70caf57
--- /dev/null
+++ b/drivers/gpu/pvr/osfunc.h
@@ -0,0 +1,648 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifdef DEBUG_RELEASE_BUILD
+#pragma optimize( "", off )
+#define DEBUG 1
+#endif
+
+#ifndef __OSFUNC_H__
+#define __OSFUNC_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if defined(__linux__) && defined(__KERNEL__)
+#include <linux/hardirq.h>
+#include <linux/string.h>
+#include <asm/system.h>
+#if defined(__arm__)
+#include <asm/memory.h>
+#endif
+#endif
+
+
+
+ #define PVRSRV_PAGEABLE_SELECT PVRSRV_OS_PAGEABLE_HEAP
+
+#define KERNEL_ID 0xffffffffL
+#define POWER_MANAGER_ID 0xfffffffeL
+#define ISR_ID 0xfffffffdL
+#define TIMER_ID 0xfffffffcL
+
+
+#define HOST_PAGESIZE OSGetPageSize
+#define HOST_PAGEMASK (HOST_PAGESIZE()-1)
+#define HOST_PAGEALIGN(addr) (((addr) + HOST_PAGEMASK) & ~HOST_PAGEMASK)
+
+#define PVRSRV_OS_HEAP_MASK 0xf
+#define PVRSRV_OS_PAGEABLE_HEAP 0x1
+#define PVRSRV_OS_NON_PAGEABLE_HEAP 0x2
+
+
+IMG_UINT32 OSClockus(IMG_VOID);
+IMG_SIZE_T OSGetPageSize(IMG_VOID);
+PVRSRV_ERROR OSInstallDeviceLISR(IMG_VOID *pvSysData,
+ IMG_UINT32 ui32Irq,
+ IMG_CHAR *pszISRName,
+ IMG_VOID *pvDeviceNode);
+PVRSRV_ERROR OSUninstallDeviceLISR(IMG_VOID *pvSysData);
+PVRSRV_ERROR OSInstallSystemLISR(IMG_VOID *pvSysData, IMG_UINT32 ui32Irq);
+PVRSRV_ERROR OSUninstallSystemLISR(IMG_VOID *pvSysData);
+PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData);
+PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData);
+IMG_CPU_PHYADDR OSMapLinToCPUPhys(IMG_HANDLE, IMG_VOID* pvLinAddr);
+IMG_VOID OSMemCopy(IMG_VOID *pvDst, IMG_VOID *pvSrc, IMG_SIZE_T ui32Size);
+IMG_VOID *OSMapPhysToLin(IMG_CPU_PHYADDR BasePAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE *phOSMemHandle);
+IMG_BOOL OSUnMapPhysToLin(IMG_VOID *pvLinAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle);
+
+PVRSRV_ERROR OSReservePhys(IMG_CPU_PHYADDR BasePAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_VOID **ppvCpuVAddr, IMG_HANDLE *phOSMemHandle);
+PVRSRV_ERROR OSUnReservePhys(IMG_VOID *pvCpuVAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle);
+
+#if (defined(__linux__) && defined(__KERNEL__)) || (UNDER_CE >= 600)
+
+IMG_VOID OSFlushCPUCacheKM(IMG_VOID);
+
+IMG_VOID OSCleanCPUCacheKM(IMG_VOID);
+
+IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32Length);
+IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32Length);
+IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32Length);
+
+#else
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSFlushCPUCacheKM)
+#endif
+static INLINE IMG_VOID OSFlushCPUCacheKM(IMG_VOID) {}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSCleanCPUCacheKM)
+#endif
+static INLINE IMG_VOID OSCleanCPUCacheKM(IMG_VOID) {}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSFlushCPUCacheRangeKM)
+#endif
+static INLINE IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32Length)
+{
+ PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+ PVR_UNREFERENCED_PARAMETER(pvRangeAddrStart);
+ PVR_UNREFERENCED_PARAMETER(ui32Length);
+ return IMG_FALSE;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSCleanCPUCacheRangeKM)
+#endif
+static INLINE IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32Length)
+{
+ PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+ PVR_UNREFERENCED_PARAMETER(pvRangeAddrStart);
+ PVR_UNREFERENCED_PARAMETER(ui32Length);
+ return IMG_FALSE;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSInvalidateCPUCacheRangeKM)
+#endif
+static INLINE IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32Length)
+{
+ PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+ PVR_UNREFERENCED_PARAMETER(pvRangeAddrStart);
+ PVR_UNREFERENCED_PARAMETER(ui32Length);
+ return IMG_FALSE;
+}
+
+#endif
+
+#if defined(__linux__)
+PVRSRV_ERROR OSRegisterDiscontigMem(IMG_SYS_PHYADDR *pBasePAddr,
+ IMG_VOID *pvCpuVAddr,
+ IMG_SIZE_T ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE *phOSMemHandle);
+PVRSRV_ERROR OSUnRegisterDiscontigMem(IMG_VOID *pvCpuVAddr,
+ IMG_SIZE_T ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hOSMemHandle);
+#else
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSRegisterDiscontigMem)
+#endif
+static INLINE PVRSRV_ERROR OSRegisterDiscontigMem(IMG_SYS_PHYADDR *pBasePAddr,
+ IMG_VOID *pvCpuVAddr,
+ IMG_SIZE_T ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE *phOSMemHandle)
+{
+ PVR_UNREFERENCED_PARAMETER(pBasePAddr);
+ PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+ PVR_UNREFERENCED_PARAMETER(phOSMemHandle);
+
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSUnRegisterDiscontigMem)
+#endif
+static INLINE PVRSRV_ERROR OSUnRegisterDiscontigMem(IMG_VOID *pvCpuVAddr,
+ IMG_SIZE_T ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hOSMemHandle)
+{
+ PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+ PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+#endif
+
+
+#if defined(__linux__)
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSReserveDiscontigPhys)
+#endif
+static INLINE PVRSRV_ERROR OSReserveDiscontigPhys(IMG_SYS_PHYADDR *pBasePAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_VOID **ppvCpuVAddr, IMG_HANDLE *phOSMemHandle)
+{
+#if defined(__linux__)
+ *ppvCpuVAddr = IMG_NULL;
+ return OSRegisterDiscontigMem(pBasePAddr, *ppvCpuVAddr, ui32Bytes, ui32Flags, phOSMemHandle);
+#else
+ extern IMG_CPU_PHYADDR SysSysPAddrToCpuPAddr(IMG_SYS_PHYADDR SysPAddr);
+
+
+ return OSReservePhys(SysSysPAddrToCpuPAddr(pBasePAddr[0]), ui32Bytes, ui32Flags, ppvCpuVAddr, phOSMemHandle);
+#endif
+}
+
+static INLINE PVRSRV_ERROR OSUnReserveDiscontigPhys(IMG_VOID *pvCpuVAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle)
+{
+#if defined(__linux__)
+ OSUnRegisterDiscontigMem(pvCpuVAddr, ui32Bytes, ui32Flags, hOSMemHandle);
+#endif
+
+ return PVRSRV_OK;
+}
+#else
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSReserveDiscontigPhys)
+#endif
+static INLINE PVRSRV_ERROR OSReserveDiscontigPhys(IMG_SYS_PHYADDR *pBasePAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_VOID **ppvCpuVAddr, IMG_HANDLE *phOSMemHandle)
+{
+ PVR_UNREFERENCED_PARAMETER(pBasePAddr);
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+ PVR_UNREFERENCED_PARAMETER(ppvCpuVAddr);
+ PVR_UNREFERENCED_PARAMETER(phOSMemHandle);
+
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSUnReserveDiscontigPhys)
+#endif
+static INLINE PVRSRV_ERROR OSUnReserveDiscontigPhys(IMG_VOID *pvCpuVAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle)
+{
+ PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+ PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+#endif
+
+PVRSRV_ERROR OSRegisterMem(IMG_CPU_PHYADDR BasePAddr,
+ IMG_VOID *pvCpuVAddr,
+ IMG_SIZE_T ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE *phOSMemHandle);
+PVRSRV_ERROR OSUnRegisterMem(IMG_VOID *pvCpuVAddr,
+ IMG_SIZE_T ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hOSMemHandle);
+
+
+
+#if defined(__linux__)
+PVRSRV_ERROR OSGetSubMemHandle(IMG_HANDLE hOSMemHandle,
+ IMG_UINTPTR_T ui32ByteOffset,
+ IMG_SIZE_T ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE *phOSMemHandleRet);
+PVRSRV_ERROR OSReleaseSubMemHandle(IMG_HANDLE hOSMemHandle, IMG_UINT32 ui32Flags);
+#else
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSGetSubMemHandle)
+#endif
+static INLINE PVRSRV_ERROR OSGetSubMemHandle(IMG_HANDLE hOSMemHandle,
+ IMG_UINTPTR_T ui32ByteOffset,
+ IMG_SIZE_T ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE *phOSMemHandleRet)
+{
+ PVR_UNREFERENCED_PARAMETER(ui32ByteOffset);
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+
+ *phOSMemHandleRet = hOSMemHandle;
+ return PVRSRV_OK;
+}
+
+static INLINE PVRSRV_ERROR OSReleaseSubMemHandle(IMG_HANDLE hOSMemHandle, IMG_UINT32 ui32Flags)
+{
+ PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+ return PVRSRV_OK;
+}
+#endif
+
+IMG_UINT32 OSGetCurrentProcessIDKM(IMG_VOID);
+IMG_UINTPTR_T OSGetCurrentThreadID( IMG_VOID );
+IMG_VOID OSMemSet(IMG_VOID *pvDest, IMG_UINT8 ui8Value, IMG_SIZE_T ui32Size);
+
+PVRSRV_ERROR OSAllocPages_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_UINT32 ui32PageSize,
+ IMG_PVOID pvPrivData, IMG_UINT32 ui32PrivDataLength, IMG_PVOID *ppvLinAddr, IMG_HANDLE *phPageAlloc);
+PVRSRV_ERROR OSFreePages(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_PVOID pvLinAddr, IMG_HANDLE hPageAlloc);
+
+
+#ifdef PVRSRV_LOG_MEMORY_ALLOCS
+ #define OSAllocMem(flags, size, linAddr, blockAlloc, logStr) \
+ (PVR_TRACE(("OSAllocMem(" #flags ", " #size ", " #linAddr ", " #blockAlloc "): " logStr " (size = 0x%lx)", size)), \
+ OSAllocMem_Debug_Wrapper(flags, size, linAddr, blockAlloc, __FILE__, __LINE__))
+
+ #define OSAllocPages(flags, size, pageSize, privdata, privdatalength, linAddr, pageAlloc) \
+ (PVR_TRACE(("OSAllocPages(" #flags ", " #size ", " #pageSize ", " #linAddr ", " #pageAlloc "): (size = 0x%lx)", size)), \
+ OSAllocPages_Impl(flags, size, pageSize, linAddr, privdata, privdatalength, pageAlloc))
+
+ #define OSFreeMem(flags, size, linAddr, blockAlloc) \
+ (PVR_TRACE(("OSFreeMem(" #flags ", " #size ", " #linAddr ", " #blockAlloc "): (pointer = 0x%X)", linAddr)), \
+ OSFreeMem_Debug_Wrapper(flags, size, linAddr, blockAlloc, __FILE__, __LINE__))
+#else
+ #define OSAllocMem(flags, size, linAddr, blockAlloc, logString) \
+ OSAllocMem_Debug_Wrapper(flags, size, linAddr, blockAlloc, __FILE__, __LINE__)
+
+ #define OSAllocPages OSAllocPages_Impl
+
+ #define OSFreeMem(flags, size, linAddr, blockAlloc) \
+ OSFreeMem_Debug_Wrapper(flags, size, linAddr, blockAlloc, __FILE__, __LINE__)
+#endif
+
+#ifdef PVRSRV_DEBUG_OS_MEMORY
+
+ PVRSRV_ERROR OSAllocMem_Debug_Wrapper(IMG_UINT32 ui32Flags,
+ IMG_UINT32 ui32Size,
+ IMG_PVOID *ppvCpuVAddr,
+ IMG_HANDLE *phBlockAlloc,
+ IMG_CHAR *pszFilename,
+ IMG_UINT32 ui32Line);
+
+ PVRSRV_ERROR OSFreeMem_Debug_Wrapper(IMG_UINT32 ui32Flags,
+ IMG_UINT32 ui32Size,
+ IMG_PVOID pvCpuVAddr,
+ IMG_HANDLE hBlockAlloc,
+ IMG_CHAR *pszFilename,
+ IMG_UINT32 ui32Line);
+
+
+ typedef struct
+ {
+ IMG_UINT8 sGuardRegionBefore[8];
+ IMG_CHAR sFileName[128];
+ IMG_UINT32 uLineNo;
+ IMG_SIZE_T uSize;
+ IMG_SIZE_T uSizeParityCheck;
+ enum valid_tag
+ { isFree = 0x277260FF,
+ isAllocated = 0x260511AA
+ } eValid;
+ } OSMEM_DEBUG_INFO;
+
+ #define TEST_BUFFER_PADDING_STATUS (sizeof(OSMEM_DEBUG_INFO))
+ #define TEST_BUFFER_PADDING_AFTER (8)
+ #define TEST_BUFFER_PADDING (TEST_BUFFER_PADDING_STATUS + TEST_BUFFER_PADDING_AFTER)
+#else
+ #define OSAllocMem_Debug_Wrapper OSAllocMem_Debug_Linux_Memory_Allocations
+ #define OSFreeMem_Debug_Wrapper OSFreeMem_Debug_Linux_Memory_Allocations
+#endif
+
+#if defined(__linux__) && defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ PVRSRV_ERROR OSAllocMem_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_PVOID *ppvLinAddr, IMG_HANDLE *phBlockAlloc, IMG_CHAR *pszFilename, IMG_UINT32 ui32Line);
+ PVRSRV_ERROR OSFreeMem_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_PVOID pvLinAddr, IMG_HANDLE hBlockAlloc, IMG_CHAR *pszFilename, IMG_UINT32 ui32Line);
+
+ #define OSAllocMem_Debug_Linux_Memory_Allocations OSAllocMem_Impl
+ #define OSFreeMem_Debug_Linux_Memory_Allocations OSFreeMem_Impl
+#else
+ PVRSRV_ERROR OSAllocMem_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_PVOID *ppvLinAddr, IMG_HANDLE *phBlockAlloc);
+ PVRSRV_ERROR OSFreeMem_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_PVOID pvLinAddr, IMG_HANDLE hBlockAlloc);
+
+ #define OSAllocMem_Debug_Linux_Memory_Allocations(flags, size, addr, blockAlloc, file, line) \
+ OSAllocMem_Impl(flags, size, addr, blockAlloc)
+ #define OSFreeMem_Debug_Linux_Memory_Allocations(flags, size, addr, blockAlloc, file, line) \
+ OSFreeMem_Impl(flags, size, addr, blockAlloc)
+#endif
+
+
+#if defined(__linux__)
+IMG_CPU_PHYADDR OSMemHandleToCpuPAddr(IMG_VOID *hOSMemHandle, IMG_SIZE_T ui32ByteOffset);
+#else
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSMemHandleToCpuPAddr)
+#endif
+static INLINE IMG_CPU_PHYADDR OSMemHandleToCpuPAddr(IMG_HANDLE hOSMemHandle, IMG_SIZE_T ui32ByteOffset)
+{
+ IMG_CPU_PHYADDR sCpuPAddr;
+ PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+ PVR_UNREFERENCED_PARAMETER(ui32ByteOffset);
+ sCpuPAddr.uiAddr = 0;
+ return sCpuPAddr;
+}
+#endif
+
+#if defined(__linux__)
+IMG_BOOL OSMemHandleIsPhysContig(IMG_VOID *hOSMemHandle);
+#else
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSMemHandleIsPhysContig)
+#endif
+static INLINE IMG_BOOL OSMemHandleIsPhysContig(IMG_HANDLE hOSMemHandle)
+{
+ PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+ return IMG_FALSE;
+}
+#endif
+
+PVRSRV_ERROR OSInitEnvData(IMG_PVOID *ppvEnvSpecificData);
+PVRSRV_ERROR OSDeInitEnvData(IMG_PVOID pvEnvSpecificData);
+IMG_CHAR* OSStringCopy(IMG_CHAR *pszDest, const IMG_CHAR *pszSrc);
+IMG_INT32 OSSNPrintf(IMG_CHAR *pStr, IMG_SIZE_T ui32Size, const IMG_CHAR *pszFormat, ...) IMG_FORMAT_PRINTF(3, 4);
+#define OSStringLength(pszString) strlen(pszString)
+
+#if defined (SUPPORT_SID_INTERFACE)
+PVRSRV_ERROR OSEventObjectCreateKM(const IMG_CHAR *pszName,
+ PVRSRV_EVENTOBJECT_KM *psEventObject);
+PVRSRV_ERROR OSEventObjectDestroyKM(PVRSRV_EVENTOBJECT_KM *psEventObject);
+PVRSRV_ERROR OSEventObjectSignalKM(IMG_HANDLE hOSEventKM);
+PVRSRV_ERROR OSEventObjectWaitKM(IMG_HANDLE hOSEventKM);
+PVRSRV_ERROR OSEventObjectOpenKM(PVRSRV_EVENTOBJECT_KM *psEventObject,
+ IMG_HANDLE *phOSEvent);
+PVRSRV_ERROR OSEventObjectCloseKM(PVRSRV_EVENTOBJECT_KM *psEventObject,
+ IMG_HANDLE hOSEventKM);
+#else
+PVRSRV_ERROR OSEventObjectCreateKM(const IMG_CHAR *pszName,
+ PVRSRV_EVENTOBJECT *psEventObject);
+PVRSRV_ERROR OSEventObjectDestroyKM(PVRSRV_EVENTOBJECT *psEventObject);
+PVRSRV_ERROR OSEventObjectSignalKM(IMG_HANDLE hOSEventKM);
+PVRSRV_ERROR OSEventObjectWaitKM(IMG_HANDLE hOSEventKM);
+PVRSRV_ERROR OSEventObjectOpenKM(PVRSRV_EVENTOBJECT *psEventObject,
+ IMG_HANDLE *phOSEvent);
+PVRSRV_ERROR OSEventObjectCloseKM(PVRSRV_EVENTOBJECT *psEventObject,
+ IMG_HANDLE hOSEventKM);
+#endif
+
+
+PVRSRV_ERROR OSBaseAllocContigMemory(IMG_SIZE_T ui32Size, IMG_CPU_VIRTADDR *pLinAddr, IMG_CPU_PHYADDR *pPhysAddr);
+PVRSRV_ERROR OSBaseFreeContigMemory(IMG_SIZE_T ui32Size, IMG_CPU_VIRTADDR LinAddr, IMG_CPU_PHYADDR PhysAddr);
+
+IMG_PVOID MapUserFromKernel(IMG_PVOID pvLinAddrKM,IMG_SIZE_T ui32Size,IMG_HANDLE *phMemBlock);
+IMG_PVOID OSMapHWRegsIntoUserSpace(IMG_HANDLE hDevCookie, IMG_SYS_PHYADDR sRegAddr, IMG_UINT32 ulSize, IMG_PVOID *ppvProcess);
+IMG_VOID OSUnmapHWRegsFromUserSpace(IMG_HANDLE hDevCookie, IMG_PVOID pvUserAddr, IMG_PVOID pvProcess);
+
+IMG_VOID UnmapUserFromKernel(IMG_PVOID pvLinAddrUM, IMG_SIZE_T ui32Size, IMG_HANDLE hMemBlock);
+
+PVRSRV_ERROR OSMapPhysToUserSpace(IMG_HANDLE hDevCookie,
+ IMG_SYS_PHYADDR sCPUPhysAddr,
+ IMG_SIZE_T uiSizeInBytes,
+ IMG_UINT32 ui32CacheFlags,
+ IMG_PVOID *ppvUserAddr,
+ IMG_SIZE_T *puiActualSize,
+ IMG_HANDLE hMappingHandle);
+
+PVRSRV_ERROR OSUnmapPhysToUserSpace(IMG_HANDLE hDevCookie,
+ IMG_PVOID pvUserAddr,
+ IMG_PVOID pvProcess);
+
+PVRSRV_ERROR OSLockResource(PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID);
+PVRSRV_ERROR OSUnlockResource(PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID);
+IMG_BOOL OSIsResourceLocked(PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID);
+PVRSRV_ERROR OSCreateResource(PVRSRV_RESOURCE *psResource);
+PVRSRV_ERROR OSDestroyResource(PVRSRV_RESOURCE *psResource);
+IMG_VOID OSBreakResourceLock(PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID);
+
+#if defined(SYS_CUSTOM_POWERLOCK_WRAP)
+#define OSPowerLockWrap SysPowerLockWrap
+#define OSPowerLockUnwrap SysPowerLockUnwrap
+#else
+PVRSRV_ERROR OSPowerLockWrap(IMG_BOOL bTryLock);
+
+IMG_VOID OSPowerLockUnwrap(IMG_VOID);
+#endif
+
+
+IMG_VOID OSWaitus(IMG_UINT32 ui32Timeus);
+
+
+IMG_VOID OSSleepms(IMG_UINT32 ui32Timems);
+
+IMG_HANDLE OSFuncHighResTimerCreate(IMG_VOID);
+IMG_UINT32 OSFuncHighResTimerGetus(IMG_HANDLE hTimer);
+IMG_VOID OSFuncHighResTimerDestroy(IMG_HANDLE hTimer);
+IMG_VOID OSReleaseThreadQuanta(IMG_VOID);
+IMG_UINT32 OSPCIReadDword(IMG_UINT32 ui32Bus, IMG_UINT32 ui32Dev, IMG_UINT32 ui32Func, IMG_UINT32 ui32Reg);
+IMG_VOID OSPCIWriteDword(IMG_UINT32 ui32Bus, IMG_UINT32 ui32Dev, IMG_UINT32 ui32Func, IMG_UINT32 ui32Reg, IMG_UINT32 ui32Value);
+
+#ifndef OSReadHWReg
+IMG_UINT32 OSReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset);
+#endif
+#ifndef OSWriteHWReg
+IMG_VOID OSWriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value);
+#endif
+
+typedef IMG_VOID (*PFN_TIMER_FUNC)(IMG_VOID*);
+IMG_HANDLE OSAddTimer(PFN_TIMER_FUNC pfnTimerFunc, IMG_VOID *pvData, IMG_UINT32 ui32MsTimeout);
+PVRSRV_ERROR OSRemoveTimer (IMG_HANDLE hTimer);
+PVRSRV_ERROR OSEnableTimer (IMG_HANDLE hTimer);
+PVRSRV_ERROR OSDisableTimer (IMG_HANDLE hTimer);
+
+PVRSRV_ERROR OSGetSysMemSize(IMG_SIZE_T *pui32Bytes);
+
+typedef enum _HOST_PCI_INIT_FLAGS_
+{
+ HOST_PCI_INIT_FLAG_BUS_MASTER = 0x00000001,
+ HOST_PCI_INIT_FLAG_MSI = 0x00000002,
+ HOST_PCI_INIT_FLAG_FORCE_I32 = 0x7fffffff
+} HOST_PCI_INIT_FLAGS;
+
+struct _PVRSRV_PCI_DEV_OPAQUE_STRUCT_;
+typedef struct _PVRSRV_PCI_DEV_OPAQUE_STRUCT_ *PVRSRV_PCI_DEV_HANDLE;
+
+PVRSRV_PCI_DEV_HANDLE OSPCIAcquireDev(IMG_UINT16 ui16VendorID, IMG_UINT16 ui16DeviceID, HOST_PCI_INIT_FLAGS eFlags);
+PVRSRV_PCI_DEV_HANDLE OSPCISetDev(IMG_VOID *pvPCICookie, HOST_PCI_INIT_FLAGS eFlags);
+PVRSRV_ERROR OSPCIReleaseDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI);
+PVRSRV_ERROR OSPCIIRQ(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 *pui32IRQ);
+IMG_UINT32 OSPCIAddrRangeLen(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index);
+IMG_UINT32 OSPCIAddrRangeStart(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index);
+IMG_UINT32 OSPCIAddrRangeEnd(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index);
+PVRSRV_ERROR OSPCIRequestAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index);
+PVRSRV_ERROR OSPCIReleaseAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index);
+PVRSRV_ERROR OSPCISuspendDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI);
+PVRSRV_ERROR OSPCIResumeDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI);
+
+PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData);
+
+IMG_VOID OSPanic(IMG_VOID);
+
+IMG_BOOL OSProcHasPrivSrvInit(IMG_VOID);
+
+typedef enum _img_verify_test
+{
+ PVR_VERIFY_WRITE = 0,
+ PVR_VERIFY_READ
+} IMG_VERIFY_TEST;
+
+IMG_BOOL OSAccessOK(IMG_VERIFY_TEST eVerification, IMG_VOID *pvUserPtr, IMG_SIZE_T ui32Bytes);
+
+PVRSRV_ERROR OSCopyToUser(IMG_PVOID pvProcess, IMG_VOID *pvDest, IMG_VOID *pvSrc, IMG_SIZE_T ui32Bytes);
+PVRSRV_ERROR OSCopyFromUser(IMG_PVOID pvProcess, IMG_VOID *pvDest, IMG_VOID *pvSrc, IMG_SIZE_T ui32Bytes);
+
+#if defined(__linux__)
+PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID* pvCPUVAddr,
+ IMG_SIZE_T ui32Bytes,
+ IMG_SYS_PHYADDR *psSysPAddr,
+ IMG_HANDLE *phOSWrapMem);
+PVRSRV_ERROR OSReleasePhysPageAddr(IMG_HANDLE hOSWrapMem);
+#else
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSAcquirePhysPageAddr)
+#endif
+static INLINE PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID* pvCPUVAddr,
+ IMG_SIZE_T ui32Bytes,
+ IMG_SYS_PHYADDR *psSysPAddr,
+ IMG_HANDLE *phOSWrapMem)
+{
+ PVR_UNREFERENCED_PARAMETER(pvCPUVAddr);
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+ PVR_UNREFERENCED_PARAMETER(psSysPAddr);
+ PVR_UNREFERENCED_PARAMETER(phOSWrapMem);
+ return PVRSRV_OK;
+}
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSReleasePhysPageAddr)
+#endif
+static INLINE PVRSRV_ERROR OSReleasePhysPageAddr(IMG_HANDLE hOSWrapMem)
+{
+ PVR_UNREFERENCED_PARAMETER(hOSWrapMem);
+ return PVRSRV_OK;
+}
+#endif
+
+#if defined(__linux__) && defined(__KERNEL__)
+
+#define OS_SUPPORTS_IN_LISR
+
+static inline IMG_BOOL OSInLISR(IMG_VOID unref__ *pvSysData)
+{
+ PVR_UNREFERENCED_PARAMETER(pvSysData);
+ return (in_irq()) ? IMG_TRUE : IMG_FALSE;
+}
+
+static inline IMG_VOID OSWriteMemoryBarrier(IMG_VOID)
+{
+ wmb();
+}
+
+static inline IMG_VOID OSMemoryBarrier(IMG_VOID)
+{
+ mb();
+}
+
+#else
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSWriteMemoryBarrier)
+#endif
+static INLINE IMG_VOID OSWriteMemoryBarrier(IMG_VOID) { }
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSMemoryBarrier)
+#endif
+static INLINE IMG_VOID OSMemoryBarrier(IMG_VOID) { }
+
+#endif
+
+PVRSRV_ERROR OSAtomicAlloc(IMG_PVOID *ppvRefCount);
+IMG_VOID OSAtomicFree(IMG_PVOID pvRefCount);
+IMG_VOID OSAtomicInc(IMG_PVOID pvRefCount);
+IMG_BOOL OSAtomicDecAndTest(IMG_PVOID pvRefCount);
+IMG_UINT32 OSAtomicRead(IMG_PVOID pvRefCount);
+
+PVRSRV_ERROR OSTimeCreateWithUSOffset(IMG_PVOID *pvRet, IMG_UINT32 ui32MSOffset);
+IMG_BOOL OSTimeHasTimePassed(IMG_PVOID pvData);
+IMG_VOID OSTimeDestroy(IMG_PVOID pvData);
+
+#if defined(__linux__)
+IMG_VOID OSReleaseBridgeLock(IMG_VOID);
+IMG_VOID OSReacquireBridgeLock(IMG_VOID);
+#else
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSReleaseBridgeLock)
+#endif
+static INLINE IMG_VOID OSReleaseBridgeLock(IMG_VOID) { }
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSReacquireBridgeLock)
+#endif
+static INLINE IMG_VOID OSReacquireBridgeLock(IMG_VOID) { }
+
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/pvr/osfunc_common.c b/drivers/gpu/pvr/osfunc_common.c
new file mode 100644
index 0000000..e0a46da
--- /dev/null
+++ b/drivers/gpu/pvr/osfunc_common.c
@@ -0,0 +1,31 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "img_types.h"
+#include "services_headers.h"
+#include "osfunc.h"
+
+
diff --git a/drivers/gpu/pvr/osperproc.c b/drivers/gpu/pvr/osperproc.c
new file mode 100644
index 0000000..6b57dfc
--- /dev/null
+++ b/drivers/gpu/pvr/osperproc.c
@@ -0,0 +1,113 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "osperproc.h"
+
+#include "env_perproc.h"
+#include "proc.h"
+
+extern IMG_UINT32 gui32ReleasePID;
+
+PVRSRV_ERROR OSPerProcessPrivateDataInit(IMG_HANDLE *phOsPrivateData)
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hBlockAlloc;
+ PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc;
+
+ eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_ENV_PER_PROCESS_DATA),
+ phOsPrivateData,
+ &hBlockAlloc,
+ "Environment per Process Data");
+
+ if (eError != PVRSRV_OK)
+ {
+ *phOsPrivateData = IMG_NULL;
+
+ PVR_DPF((PVR_DBG_ERROR, "%s: OSAllocMem failed (%d)", __FUNCTION__, eError));
+ return eError;
+ }
+
+ psEnvPerProc = (PVRSRV_ENV_PER_PROCESS_DATA *)*phOsPrivateData;
+ OSMemSet(psEnvPerProc, 0, sizeof(*psEnvPerProc));
+
+ psEnvPerProc->hBlockAlloc = hBlockAlloc;
+
+
+ LinuxMMapPerProcessConnect(psEnvPerProc);
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+
+ INIT_LIST_HEAD(&psEnvPerProc->sDRMAuthListHead);
+#endif
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPerProcessPrivateDataDeInit(IMG_HANDLE hOsPrivateData)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc;
+
+ if (hOsPrivateData == IMG_NULL)
+ {
+ return PVRSRV_OK;
+ }
+
+ psEnvPerProc = (PVRSRV_ENV_PER_PROCESS_DATA *)hOsPrivateData;
+
+
+ LinuxMMapPerProcessDisconnect(psEnvPerProc);
+
+
+ RemovePerProcessProcDir(psEnvPerProc);
+
+ eError = OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_ENV_PER_PROCESS_DATA),
+ hOsPrivateData,
+ psEnvPerProc->hBlockAlloc);
+
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: OSFreeMem failed (%d)", __FUNCTION__, eError));
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPerProcessSetHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase)
+{
+ return LinuxMMapPerProcessHandleOptions(psHandleBase);
+}
+
+IMG_HANDLE LinuxTerminatingProcessPrivateData(IMG_VOID)
+{
+ if(!gui32ReleasePID)
+ return NULL;
+ return PVRSRVPerProcessPrivateData(gui32ReleasePID);
+}
diff --git a/drivers/gpu/pvr/osperproc.h b/drivers/gpu/pvr/osperproc.h
new file mode 100644
index 0000000..02aa230
--- /dev/null
+++ b/drivers/gpu/pvr/osperproc.h
@@ -0,0 +1,76 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __OSPERPROC_H__
+#define __OSPERPROC_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if defined(__linux__)
+PVRSRV_ERROR OSPerProcessPrivateDataInit(IMG_HANDLE *phOsPrivateData);
+PVRSRV_ERROR OSPerProcessPrivateDataDeInit(IMG_HANDLE hOsPrivateData);
+
+PVRSRV_ERROR OSPerProcessSetHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase);
+#else
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSPerProcessPrivateDataInit)
+#endif
+static INLINE PVRSRV_ERROR OSPerProcessPrivateDataInit(IMG_HANDLE *phOsPrivateData)
+{
+ PVR_UNREFERENCED_PARAMETER(phOsPrivateData);
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSPerProcessPrivateDataDeInit)
+#endif
+static INLINE PVRSRV_ERROR OSPerProcessPrivateDataDeInit(IMG_HANDLE hOsPrivateData)
+{
+ PVR_UNREFERENCED_PARAMETER(hOsPrivateData);
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSPerProcessSetHandleOptions)
+#endif
+static INLINE PVRSRV_ERROR OSPerProcessSetHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase)
+{
+ PVR_UNREFERENCED_PARAMETER(psHandleBase);
+
+ return PVRSRV_OK;
+}
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/pvr/pdump.c b/drivers/gpu/pvr/pdump.c
new file mode 100644
index 0000000..13d9b0d
--- /dev/null
+++ b/drivers/gpu/pvr/pdump.c
@@ -0,0 +1,628 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#if defined (SUPPORT_SGX) || defined (SUPPORT_VGX)
+#if defined (PDUMP)
+
+#include <asm/atomic.h>
+#include <stdarg.h>
+#if defined (SUPPORT_SGX)
+#include "sgxdefs.h"
+#endif
+#include "services_headers.h"
+
+#include "pvrversion.h"
+#include "pvr_debug.h"
+
+#include "dbgdrvif.h"
+#if defined (SUPPORT_SGX)
+#include "sgxmmu.h"
+#endif
+#include "mm.h"
+#include "pdump_km.h"
+#include "pdump_int.h"
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+
+static IMG_BOOL PDumpWriteString2 (IMG_CHAR * pszString, IMG_UINT32 ui32Flags);
+static IMG_BOOL PDumpWriteILock (PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32Count, IMG_UINT32 ui32Flags);
+static IMG_VOID DbgSetFrame (PDBG_STREAM psStream, IMG_UINT32 ui32Frame);
+static IMG_VOID DbgSetMarker (PDBG_STREAM psStream, IMG_UINT32 ui32Marker);
+
+#define PDUMP_DATAMASTER_PIXEL (1)
+#define PDUMP_DATAMASTER_EDM (3)
+
+#define MAX_FILE_SIZE 0x40000000
+
+static atomic_t gsPDumpSuspended = ATOMIC_INIT(0);
+
+static PDBGKM_SERVICE_TABLE gpfnDbgDrv = IMG_NULL;
+
+
+
+IMG_CHAR *pszStreamName[PDUMP_NUM_STREAMS] = { "ParamStream2",
+ "ScriptStream2",
+ "DriverInfoStream"};
+typedef struct PDBG_PDUMP_STATE_TAG
+{
+ PDBG_STREAM psStream[PDUMP_NUM_STREAMS];
+ IMG_UINT32 ui32ParamFileNum;
+
+ IMG_CHAR *pszMsg;
+ IMG_CHAR *pszScript;
+ IMG_CHAR *pszFile;
+
+} PDBG_PDUMP_STATE;
+
+static PDBG_PDUMP_STATE gsDBGPdumpState = {{IMG_NULL}, 0, IMG_NULL, IMG_NULL, IMG_NULL};
+
+#define SZ_MSG_SIZE_MAX PVRSRV_PDUMP_MAX_COMMENT_SIZE-1
+#define SZ_SCRIPT_SIZE_MAX PVRSRV_PDUMP_MAX_COMMENT_SIZE-1
+#define SZ_FILENAME_SIZE_MAX PVRSRV_PDUMP_MAX_COMMENT_SIZE-1
+
+
+
+
+IMG_VOID DBGDrvGetServiceTable(IMG_VOID **fn_table);
+
+static inline IMG_BOOL PDumpSuspended(IMG_VOID)
+{
+ return (atomic_read(&gsPDumpSuspended) != 0) ? IMG_TRUE : IMG_FALSE;
+}
+
+PVRSRV_ERROR PDumpOSGetScriptString(IMG_HANDLE *phScript,
+ IMG_UINT32 *pui32MaxLen)
+{
+ *phScript = (IMG_HANDLE)gsDBGPdumpState.pszScript;
+ *pui32MaxLen = SZ_SCRIPT_SIZE_MAX;
+ if ((!*phScript) || PDumpSuspended())
+ {
+ return PVRSRV_ERROR_PDUMP_NOT_ACTIVE;
+ }
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpOSGetMessageString(IMG_CHAR **ppszMsg,
+ IMG_UINT32 *pui32MaxLen)
+{
+ *ppszMsg = gsDBGPdumpState.pszMsg;
+ *pui32MaxLen = SZ_MSG_SIZE_MAX;
+ if ((!*ppszMsg) || PDumpSuspended())
+ {
+ return PVRSRV_ERROR_PDUMP_NOT_ACTIVE;
+ }
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpOSGetFilenameString(IMG_CHAR **ppszFile,
+ IMG_UINT32 *pui32MaxLen)
+{
+ *ppszFile = gsDBGPdumpState.pszFile;
+ *pui32MaxLen = SZ_FILENAME_SIZE_MAX;
+ if ((!*ppszFile) || PDumpSuspended())
+ {
+ return PVRSRV_ERROR_PDUMP_NOT_ACTIVE;
+ }
+ return PVRSRV_OK;
+}
+
+IMG_BOOL PDumpOSWriteString2(IMG_HANDLE hScript, IMG_UINT32 ui32Flags)
+{
+ return PDumpWriteString2(hScript, ui32Flags);
+}
+
+PVRSRV_ERROR PDumpOSBufprintf(IMG_HANDLE hBuf, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, ...)
+{
+ IMG_CHAR* pszBuf = hBuf;
+ IMG_INT32 n;
+ va_list vaArgs;
+
+ va_start(vaArgs, pszFormat);
+
+ n = vsnprintf(pszBuf, ui32ScriptSizeMax, pszFormat, vaArgs);
+
+ va_end(vaArgs);
+
+ if (n>=(IMG_INT32)ui32ScriptSizeMax || n==-1)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete."));
+
+ return PVRSRV_ERROR_PDUMP_BUF_OVERFLOW;
+ }
+
+#if defined(PDUMP_DEBUG_OUTFILES)
+ g_ui32EveryLineCounter++;
+#endif
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpOSVSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, PDUMP_va_list vaArgs)
+{
+ IMG_INT32 n;
+
+ n = vsnprintf(pszComment, ui32ScriptSizeMax, pszFormat, vaArgs);
+
+ if (n>=(IMG_INT32)ui32ScriptSizeMax || n==-1)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete."));
+
+ return PVRSRV_ERROR_PDUMP_BUF_OVERFLOW;
+ }
+
+ return PVRSRV_OK;
+}
+
+IMG_VOID PDumpOSDebugPrintf(IMG_CHAR* pszFormat, ...)
+{
+ PVR_UNREFERENCED_PARAMETER(pszFormat);
+
+
+}
+
+PVRSRV_ERROR PDumpOSSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR *pszFormat, ...)
+{
+ IMG_INT32 n;
+ va_list vaArgs;
+
+ va_start(vaArgs, pszFormat);
+
+ n = vsnprintf(pszComment, ui32ScriptSizeMax, pszFormat, vaArgs);
+
+ va_end(vaArgs);
+
+ if (n>=(IMG_INT32)ui32ScriptSizeMax || n==-1)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete."));
+
+ return PVRSRV_ERROR_PDUMP_BUF_OVERFLOW;
+ }
+
+ return PVRSRV_OK;
+}
+
+IMG_UINT32 PDumpOSBuflen(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax)
+{
+ IMG_CHAR* pszBuf = hBuffer;
+ IMG_UINT32 ui32Count = 0;
+
+ while ((pszBuf[ui32Count]!=0) && (ui32Count<ui32BufferSizeMax) )
+ {
+ ui32Count++;
+ }
+ return(ui32Count);
+}
+
+IMG_VOID PDumpOSVerifyLineEnding(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax)
+{
+ IMG_UINT32 ui32Count;
+ IMG_CHAR* pszBuf = hBuffer;
+
+
+ ui32Count = PDumpOSBuflen(hBuffer, ui32BufferSizeMax);
+
+
+ if ((ui32Count >= 1) && (pszBuf[ui32Count-1] != '\n') && (ui32Count<ui32BufferSizeMax))
+ {
+ pszBuf[ui32Count] = '\n';
+ ui32Count++;
+ pszBuf[ui32Count] = '\0';
+ }
+ if ((ui32Count >= 2) && (pszBuf[ui32Count-2] != '\r') && (ui32Count<ui32BufferSizeMax))
+ {
+ pszBuf[ui32Count-1] = '\r';
+ pszBuf[ui32Count] = '\n';
+ ui32Count++;
+ pszBuf[ui32Count] = '\0';
+ }
+}
+
+IMG_HANDLE PDumpOSGetStream(IMG_UINT32 ePDumpStream)
+{
+ return (IMG_HANDLE)gsDBGPdumpState.psStream[ePDumpStream];
+}
+
+IMG_UINT32 PDumpOSGetStreamOffset(IMG_UINT32 ePDumpStream)
+{
+ PDBG_STREAM psStream = gsDBGPdumpState.psStream[ePDumpStream];
+ return gpfnDbgDrv->pfnGetStreamOffset(psStream);
+}
+
+IMG_UINT32 PDumpOSGetParamFileNum(IMG_VOID)
+{
+ return gsDBGPdumpState.ui32ParamFileNum;
+}
+
+IMG_BOOL PDumpOSWriteString(IMG_HANDLE hStream,
+ IMG_UINT8 *psui8Data,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32Flags)
+{
+ PDBG_STREAM psStream = (PDBG_STREAM)hStream;
+ return PDumpWriteILock(psStream,
+ psui8Data,
+ ui32Size,
+ ui32Flags);
+}
+
+IMG_VOID PDumpOSCheckForSplitting(IMG_HANDLE hStream, IMG_UINT32 ui32Size, IMG_UINT32 ui32Flags)
+{
+
+ PVR_UNREFERENCED_PARAMETER(hStream);
+ PVR_UNREFERENCED_PARAMETER(ui32Size);
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+}
+
+IMG_BOOL PDumpOSJTInitialised(IMG_VOID)
+{
+ if(gpfnDbgDrv)
+ {
+ return IMG_TRUE;
+ }
+ return IMG_FALSE;
+}
+
+inline IMG_BOOL PDumpOSIsSuspended(IMG_VOID)
+{
+ return (atomic_read(&gsPDumpSuspended) != 0) ? IMG_TRUE : IMG_FALSE;
+}
+
+IMG_VOID PDumpOSCPUVAddrToDevPAddr(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT8 *pui8LinAddr,
+ IMG_UINT32 ui32PageSize,
+ IMG_DEV_PHYADDR *psDevPAddr)
+{
+ IMG_CPU_PHYADDR sCpuPAddr;
+
+ PVR_UNREFERENCED_PARAMETER(pui8LinAddr);
+ PVR_UNREFERENCED_PARAMETER(ui32PageSize);
+
+
+
+ PVR_ASSERT (hOSMemHandle != IMG_NULL);
+
+ sCpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, ui32Offset);
+ PVR_ASSERT((sCpuPAddr.uiAddr & (ui32PageSize - 1)) == 0);
+
+
+ *psDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
+}
+
+IMG_VOID PDumpOSCPUVAddrToPhysPages(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32Offset,
+ IMG_PUINT8 pui8LinAddr,
+ IMG_UINT32 ui32DataPageMask,
+ IMG_UINT32 *pui32PageOffset)
+{
+ if(hOSMemHandle)
+ {
+
+ IMG_CPU_PHYADDR sCpuPAddr;
+
+ PVR_UNREFERENCED_PARAMETER(pui8LinAddr);
+
+ sCpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, ui32Offset);
+ *pui32PageOffset = sCpuPAddr.uiAddr & ui32DataPageMask;
+ }
+ else
+ {
+ PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+ PVR_UNREFERENCED_PARAMETER(ui32Offset);
+
+ *pui32PageOffset = ((IMG_UINT32)pui8LinAddr & ui32DataPageMask);
+ }
+}
+
+IMG_UINT32 PDumpOSDebugDriverWrite( PDBG_STREAM psStream,
+ PDUMP_DDWMODE eDbgDrvWriteMode,
+ IMG_UINT8 *pui8Data,
+ IMG_UINT32 ui32BCount,
+ IMG_UINT32 ui32Level,
+ IMG_UINT32 ui32DbgDrvFlags)
+{
+ switch(eDbgDrvWriteMode)
+ {
+ case PDUMP_WRITE_MODE_CONTINUOUS:
+ PVR_UNREFERENCED_PARAMETER(ui32DbgDrvFlags);
+ return gpfnDbgDrv->pfnDBGDrivWrite2(psStream, pui8Data, ui32BCount, ui32Level);
+ case PDUMP_WRITE_MODE_LASTFRAME:
+ return gpfnDbgDrv->pfnWriteLF(psStream, pui8Data, ui32BCount, ui32Level, ui32DbgDrvFlags);
+ case PDUMP_WRITE_MODE_BINCM:
+ PVR_UNREFERENCED_PARAMETER(ui32DbgDrvFlags);
+ return gpfnDbgDrv->pfnWriteBINCM(psStream, pui8Data, ui32BCount, ui32Level);
+ case PDUMP_WRITE_MODE_PERSISTENT:
+ PVR_UNREFERENCED_PARAMETER(ui32DbgDrvFlags);
+ return gpfnDbgDrv->pfnWritePersist(psStream, pui8Data, ui32BCount, ui32Level);
+ default:
+ PVR_UNREFERENCED_PARAMETER(ui32DbgDrvFlags);
+ break;
+ }
+ return 0xFFFFFFFFU;
+}
+
+IMG_VOID PDumpOSReleaseExecution(IMG_VOID)
+{
+ OSReleaseThreadQuanta();
+}
+
+IMG_VOID PDumpInit(IMG_VOID)
+{
+ IMG_UINT32 i;
+ DBGKM_CONNECT_NOTIFIER sConnectNotifier;
+
+
+ if (!gpfnDbgDrv)
+ {
+ DBGDrvGetServiceTable((IMG_VOID **)&gpfnDbgDrv);
+
+
+
+ if (gpfnDbgDrv == IMG_NULL)
+ {
+ return;
+ }
+
+
+ sConnectNotifier.pfnConnectNotifier = &PDumpConnectionNotify;
+ gpfnDbgDrv->pfnSetConnectNotifier(sConnectNotifier);
+
+ if(!gsDBGPdumpState.pszFile)
+ {
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_FILENAME_SIZE_MAX, (IMG_PVOID *)&gsDBGPdumpState.pszFile, 0,
+ "Filename string") != PVRSRV_OK)
+ {
+ goto init_failed;
+ }
+ }
+
+ if(!gsDBGPdumpState.pszMsg)
+ {
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_MSG_SIZE_MAX, (IMG_PVOID *)&gsDBGPdumpState.pszMsg, 0,
+ "Message string") != PVRSRV_OK)
+ {
+ goto init_failed;
+ }
+ }
+
+ if(!gsDBGPdumpState.pszScript)
+ {
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_SCRIPT_SIZE_MAX, (IMG_PVOID *)&gsDBGPdumpState.pszScript, 0,
+ "Script string") != PVRSRV_OK)
+ {
+ goto init_failed;
+ }
+ }
+
+ for(i=0; i < PDUMP_NUM_STREAMS; i++)
+ {
+ gsDBGPdumpState.psStream[i] = gpfnDbgDrv->pfnCreateStream(pszStreamName[i],
+ DEBUG_CAPMODE_FRAMED,
+ DEBUG_OUTMODE_STREAMENABLE,
+ 0,
+ 10);
+
+ gpfnDbgDrv->pfnSetCaptureMode(gsDBGPdumpState.psStream[i],DEBUG_CAPMODE_FRAMED,0xFFFFFFFF, 0xFFFFFFFF, 1);
+ gpfnDbgDrv->pfnSetFrame(gsDBGPdumpState.psStream[i],0);
+ }
+
+ PDUMPCOMMENT("Driver Product Name: %s", VS_PRODUCT_NAME);
+ PDUMPCOMMENT("Driver Product Version: %s (%s)", PVRVERSION_STRING, PVRVERSION_FAMILY);
+ PDUMPCOMMENT("Start of Init Phase");
+ }
+
+ return;
+
+init_failed:
+
+ if(gsDBGPdumpState.pszFile)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_FILENAME_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszFile, 0);
+ gsDBGPdumpState.pszFile = IMG_NULL;
+ }
+
+ if(gsDBGPdumpState.pszScript)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_SCRIPT_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszScript, 0);
+ gsDBGPdumpState.pszScript = IMG_NULL;
+ }
+
+ if(gsDBGPdumpState.pszMsg)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_MSG_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszMsg, 0);
+ gsDBGPdumpState.pszMsg = IMG_NULL;
+ }
+
+
+ sConnectNotifier.pfnConnectNotifier = 0;
+ gpfnDbgDrv->pfnSetConnectNotifier(sConnectNotifier);
+
+ gpfnDbgDrv = IMG_NULL;
+}
+
+
+IMG_VOID PDumpDeInit(IMG_VOID)
+{
+ IMG_UINT32 i;
+ DBGKM_CONNECT_NOTIFIER sConnectNotifier;
+
+ for(i=0; i < PDUMP_NUM_STREAMS; i++)
+ {
+ gpfnDbgDrv->pfnDestroyStream(gsDBGPdumpState.psStream[i]);
+ }
+
+ if(gsDBGPdumpState.pszFile)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_FILENAME_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszFile, 0);
+ gsDBGPdumpState.pszFile = IMG_NULL;
+ }
+
+ if(gsDBGPdumpState.pszScript)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_SCRIPT_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszScript, 0);
+ gsDBGPdumpState.pszScript = IMG_NULL;
+ }
+
+ if(gsDBGPdumpState.pszMsg)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_MSG_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszMsg, 0);
+ gsDBGPdumpState.pszMsg = IMG_NULL;
+ }
+
+
+ sConnectNotifier.pfnConnectNotifier = 0;
+ gpfnDbgDrv->pfnSetConnectNotifier(sConnectNotifier);
+
+ gpfnDbgDrv = IMG_NULL;
+}
+
+PVRSRV_ERROR PDumpStartInitPhaseKM(IMG_VOID)
+{
+ IMG_UINT32 i;
+
+ if (gpfnDbgDrv)
+ {
+ PDUMPCOMMENT("Start Init Phase");
+ for(i=0; i < PDUMP_NUM_STREAMS; i++)
+ {
+ gpfnDbgDrv->pfnStartInitPhase(gsDBGPdumpState.psStream[i]);
+ }
+ }
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpStopInitPhaseKM(IMG_VOID)
+{
+ IMG_UINT32 i;
+
+ if (gpfnDbgDrv)
+ {
+ PDUMPCOMMENT("Stop Init Phase");
+
+ for(i=0; i < PDUMP_NUM_STREAMS; i++)
+ {
+ gpfnDbgDrv->pfnStopInitPhase(gsDBGPdumpState.psStream[i]);
+ }
+ }
+ return PVRSRV_OK;
+}
+
+IMG_BOOL PDumpIsLastCaptureFrameKM(IMG_VOID)
+{
+ return gpfnDbgDrv->pfnIsLastCaptureFrame(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2]);
+}
+
+
+IMG_BOOL PDumpOSIsCaptureFrameKM(IMG_VOID)
+{
+ if (PDumpSuspended())
+ {
+ return IMG_FALSE;
+ }
+ return gpfnDbgDrv->pfnIsCaptureFrame(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2], IMG_FALSE);
+}
+
+PVRSRV_ERROR PDumpOSSetFrameKM(IMG_UINT32 ui32Frame)
+{
+ IMG_UINT32 ui32Stream;
+
+ for (ui32Stream = 0; ui32Stream < PDUMP_NUM_STREAMS; ui32Stream++)
+ {
+ if (gsDBGPdumpState.psStream[ui32Stream])
+ {
+ DbgSetFrame(gsDBGPdumpState.psStream[ui32Stream], ui32Frame);
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+
+static IMG_BOOL PDumpWriteString2(IMG_CHAR * pszString, IMG_UINT32 ui32Flags)
+{
+ return PDumpWriteILock(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2], (IMG_UINT8 *) pszString, strlen(pszString), ui32Flags);
+}
+
+
+static IMG_BOOL PDumpWriteILock(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32Count, IMG_UINT32 ui32Flags)
+{
+ IMG_UINT32 ui32Written = 0;
+ if ((psStream == IMG_NULL) || PDumpSuspended() || ((ui32Flags & PDUMP_FLAGS_NEVER) != 0))
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "PDumpWriteILock: Failed to write 0x%x bytes to stream 0x%x", ui32Count, (IMG_UINT32)psStream));
+ return IMG_TRUE;
+ }
+
+
+
+
+ if (psStream == gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2])
+ {
+ IMG_UINT32 ui32ParamOutPos = gpfnDbgDrv->pfnGetStreamOffset(gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2]);
+
+ if (ui32ParamOutPos + ui32Count > MAX_FILE_SIZE)
+ {
+ if ((gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2] && PDumpWriteString2("\r\n-- Splitting pdump output file\r\n\r\n", ui32Flags)))
+ {
+ DbgSetMarker(gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2], ui32ParamOutPos);
+ gsDBGPdumpState.ui32ParamFileNum++;
+ }
+ }
+ }
+
+ ui32Written = DbgWrite(psStream, pui8Data, ui32Count, ui32Flags);
+
+ if (ui32Written == 0xFFFFFFFF)
+ {
+ return IMG_FALSE;
+ }
+
+ return IMG_TRUE;
+}
+
+static IMG_VOID DbgSetFrame(PDBG_STREAM psStream, IMG_UINT32 ui32Frame)
+{
+ gpfnDbgDrv->pfnSetFrame(psStream, ui32Frame);
+}
+
+static IMG_VOID DbgSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker)
+{
+ gpfnDbgDrv->pfnSetMarker(psStream, ui32Marker);
+}
+
+IMG_VOID PDumpSuspendKM(IMG_VOID)
+{
+ atomic_inc(&gsPDumpSuspended);
+}
+
+IMG_VOID PDumpResumeKM(IMG_VOID)
+{
+ atomic_dec(&gsPDumpSuspended);
+}
+
+#endif
+#endif
diff --git a/drivers/gpu/pvr/pdump.h b/drivers/gpu/pvr/pdump.h
new file mode 100644
index 0000000..c41a6d4
--- /dev/null
+++ b/drivers/gpu/pvr/pdump.h
@@ -0,0 +1,37 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef _SERVICES_PDUMP_H_
+#define _SERVICES_PDUMP_H_
+
+#define PDUMP_FLAGS_NEVER 0x08000000U
+#define PDUMP_FLAGS_LASTFRAME 0x10000000U
+#define PDUMP_FLAGS_RESETLFBUFFER 0x20000000U
+#define PDUMP_FLAGS_CONTINUOUS 0x40000000U
+#define PDUMP_FLAGS_PERSISTENT 0x80000000U
+
+#endif
+
diff --git a/drivers/gpu/pvr/pdump_common.c b/drivers/gpu/pvr/pdump_common.c
new file mode 100644
index 0000000..45845b6cc
--- /dev/null
+++ b/drivers/gpu/pvr/pdump_common.c
@@ -0,0 +1,2368 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#if defined(PDUMP)
+#include <stdarg.h>
+
+#include "services_headers.h"
+#include "perproc.h"
+
+#include "pdump_km.h"
+#include "pdump_int.h"
+
+#if !defined(PDUMP_TEMP_BUFFER_SIZE)
+#define PDUMP_TEMP_BUFFER_SIZE (64 * 1024U)
+#endif
+
+#if 1
+#define PDUMP_DBG(a) PDumpOSDebugPrintf (a)
+#else
+#define PDUMP_DBG(a)
+#endif
+
+
+#define PTR_PLUS(t, p, x) ((t)(((IMG_CHAR *)(p)) + (x)))
+#define VPTR_PLUS(p, x) PTR_PLUS(IMG_VOID *, p, x)
+#define VPTR_INC(p, x) ((p) = VPTR_PLUS(p, x))
+#define MAX_PDUMP_MMU_CONTEXTS (32)
+static IMG_VOID *gpvTempBuffer = IMG_NULL;
+static IMG_HANDLE ghTempBufferBlockAlloc;
+static IMG_UINT16 gui16MMUContextUsage = 0;
+
+#if defined(PDUMP_DEBUG_OUTFILES)
+IMG_UINT32 g_ui32EveryLineCounter = 1U;
+#endif
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(_PDumpIsPersistent)
+#endif
+static INLINE
+IMG_BOOL _PDumpIsPersistent(IMG_VOID)
+{
+ PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData();
+
+ if(psPerProc == IMG_NULL)
+ {
+
+ return IMG_FALSE;
+ }
+ return psPerProc->bPDumpPersistent;
+}
+
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+
+
+static INLINE
+IMG_BOOL _PDumpIsProcessActive(IMG_VOID)
+{
+ PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData();
+ if(psPerProc == IMG_NULL)
+ {
+
+ return IMG_TRUE;
+ }
+ return psPerProc->bPDumpActive;
+}
+
+#endif
+
+#if defined(PDUMP_DEBUG_OUTFILES)
+static INLINE
+IMG_UINT32 _PDumpGetPID(IMG_VOID)
+{
+ PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData();
+ if(psPerProc == IMG_NULL)
+ {
+
+ return 0;
+ }
+ return psPerProc->ui32PID;
+}
+#endif
+
+static IMG_VOID *GetTempBuffer(IMG_VOID)
+{
+
+ if (gpvTempBuffer == IMG_NULL)
+ {
+ PVRSRV_ERROR eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ PDUMP_TEMP_BUFFER_SIZE,
+ &gpvTempBuffer,
+ &ghTempBufferBlockAlloc,
+ "PDUMP Temporary Buffer");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "GetTempBuffer: OSAllocMem failed: %d", eError));
+ }
+ }
+
+ return gpvTempBuffer;
+}
+
+static IMG_VOID FreeTempBuffer(IMG_VOID)
+{
+
+ if (gpvTempBuffer != IMG_NULL)
+ {
+ PVRSRV_ERROR eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ PDUMP_TEMP_BUFFER_SIZE,
+ gpvTempBuffer,
+ ghTempBufferBlockAlloc);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeTempBuffer: OSFreeMem failed: %d", eError));
+ }
+ else
+ {
+ gpvTempBuffer = IMG_NULL;
+ }
+ }
+}
+
+IMG_VOID PDumpInitCommon(IMG_VOID)
+{
+
+ (IMG_VOID) GetTempBuffer();
+
+
+ PDumpInit();
+}
+
+IMG_VOID PDumpDeInitCommon(IMG_VOID)
+{
+
+ FreeTempBuffer();
+
+
+ PDumpDeInit();
+}
+
+IMG_BOOL PDumpIsSuspended(IMG_VOID)
+{
+ return PDumpOSIsSuspended();
+}
+
+IMG_BOOL PDumpIsCaptureFrameKM(IMG_VOID)
+{
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+ if( _PDumpIsProcessActive() )
+ {
+ return PDumpOSIsCaptureFrameKM();
+ }
+ return IMG_FALSE;
+#else
+ return PDumpOSIsCaptureFrameKM();
+#endif
+}
+
+PVRSRV_ERROR PDumpSetFrameKM(IMG_UINT32 ui32Frame)
+{
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+ if( _PDumpIsProcessActive() )
+ {
+ return PDumpOSSetFrameKM(ui32Frame);
+ }
+ return PVRSRV_OK;
+#else
+ return PDumpOSSetFrameKM(ui32Frame);
+#endif
+}
+
+PVRSRV_ERROR PDumpRegWithFlagsKM(IMG_CHAR *pszPDumpRegName,
+ IMG_UINT32 ui32Reg,
+ IMG_UINT32 ui32Data,
+ IMG_UINT32 ui32Flags)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING()
+ PDUMP_DBG(("PDumpRegWithFlagsKM"));
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "WRW :%s:0x%08X 0x%08X\r\n",
+ pszPDumpRegName, ui32Reg, ui32Data);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpRegKM(IMG_CHAR *pszPDumpRegName,
+ IMG_UINT32 ui32Reg,
+ IMG_UINT32 ui32Data)
+{
+ return PDumpRegWithFlagsKM(pszPDumpRegName, ui32Reg, ui32Data, PDUMP_FLAGS_CONTINUOUS);
+}
+
+PVRSRV_ERROR PDumpRegPolWithFlagsKM(IMG_CHAR *pszPDumpRegName,
+ IMG_UINT32 ui32RegAddr,
+ IMG_UINT32 ui32RegValue,
+ IMG_UINT32 ui32Mask,
+ IMG_UINT32 ui32Flags,
+ PDUMP_POLL_OPERATOR eOperator)
+{
+
+ #define POLL_DELAY 1000U
+ #define POLL_COUNT_LONG (2000000000U / POLL_DELAY)
+ #define POLL_COUNT_SHORT (1000000U / POLL_DELAY)
+
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32PollCount;
+
+ PDUMP_GET_SCRIPT_STRING();
+ PDUMP_DBG(("PDumpRegPolWithFlagsKM"));
+ if ( _PDumpIsPersistent() )
+ {
+
+ return PVRSRV_OK;
+ }
+
+#if 0
+ if (((ui32RegAddr == EUR_CR_EVENT_STATUS) &&
+ (ui32RegValue & ui32Mask & EUR_CR_EVENT_STATUS_TA_FINISHED_MASK) != 0) ||
+ ((ui32RegAddr == EUR_CR_EVENT_STATUS) &&
+ (ui32RegValue & ui32Mask & EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_MASK) != 0) ||
+ ((ui32RegAddr == EUR_CR_EVENT_STATUS) &&
+ (ui32RegValue & ui32Mask & EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK) != 0))
+ {
+ ui32PollCount = POLL_COUNT_LONG;
+ }
+ else
+#endif
+ {
+ ui32PollCount = POLL_COUNT_LONG;
+ }
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "POL :%s:0x%08X 0x%08X 0x%08X %d %u %d\r\n",
+ pszPDumpRegName, ui32RegAddr, ui32RegValue,
+ ui32Mask, eOperator, ui32PollCount, POLL_DELAY);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PDumpRegPolKM(IMG_CHAR *pszPDumpRegName, IMG_UINT32 ui32RegAddr, IMG_UINT32 ui32RegValue, IMG_UINT32 ui32Mask, PDUMP_POLL_OPERATOR eOperator)
+{
+ return PDumpRegPolWithFlagsKM(pszPDumpRegName, ui32RegAddr, ui32RegValue, ui32Mask, PDUMP_FLAGS_CONTINUOUS, eOperator);
+}
+
+PVRSRV_ERROR PDumpMallocPages (PVRSRV_DEVICE_IDENTIFIER *psDevID,
+ IMG_UINT32 ui32DevVAddr,
+ IMG_CPU_VIRTADDR pvLinAddr,
+ IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32NumBytes,
+ IMG_UINT32 ui32PageSize,
+ IMG_BOOL bShared,
+ IMG_HANDLE hUniqueTag)
+{
+ PVRSRV_ERROR eErr;
+ IMG_PUINT8 pui8LinAddr;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT32 ui32NumPages;
+ IMG_DEV_PHYADDR sDevPAddr;
+ IMG_UINT32 ui32Page;
+ IMG_UINT32 ui32Flags = PDUMP_FLAGS_CONTINUOUS;
+
+ PDUMP_GET_SCRIPT_STRING();
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+
+ ui32Flags |= ( _PDumpIsPersistent() || bShared ) ? PDUMP_FLAGS_PERSISTENT : 0;
+#else
+ PVR_UNREFERENCED_PARAMETER(bShared);
+ ui32Flags |= ( _PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
+#endif
+
+
+#if !defined(LINUX)
+ PVR_ASSERT(((IMG_UINTPTR_T)pvLinAddr & HOST_PAGEMASK) == 0);
+#endif
+
+ PVR_ASSERT(((IMG_UINT32) ui32DevVAddr & HOST_PAGEMASK) == 0);
+ PVR_ASSERT(((IMG_UINT32) ui32NumBytes & HOST_PAGEMASK) == 0);
+
+
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "-- MALLOC :%s:VA_%08X 0x%08X %u\r\n",
+ psDevID->pszPDumpDevName, ui32DevVAddr, ui32NumBytes, ui32PageSize);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+
+
+ pui8LinAddr = (IMG_PUINT8) pvLinAddr;
+ ui32Offset = 0;
+ ui32NumPages = ui32NumBytes / ui32PageSize;
+ while (ui32NumPages)
+ {
+ ui32NumPages--;
+
+
+
+
+
+
+
+
+
+
+
+ PDumpOSCPUVAddrToDevPAddr(psDevID->eDeviceType,
+ hOSMemHandle,
+ ui32Offset,
+ pui8LinAddr,
+ ui32PageSize,
+ &sDevPAddr);
+ ui32Page = (IMG_UINT32)(sDevPAddr.uiAddr / ui32PageSize);
+
+ pui8LinAddr += ui32PageSize;
+ ui32Offset += ui32PageSize;
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "MALLOC :%s:PA_%08X%08X %u %u 0x%08X\r\n",
+ psDevID->pszPDumpDevName,
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag,
+ ui32Page * ui32PageSize,
+ ui32PageSize,
+ ui32PageSize,
+ ui32Page * ui32PageSize);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+ }
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PDumpMallocPageTable (PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32Offset,
+ IMG_CPU_VIRTADDR pvLinAddr,
+ IMG_UINT32 ui32PTSize,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag)
+{
+ PVRSRV_ERROR eErr;
+ IMG_DEV_PHYADDR sDevPAddr;
+
+ PDUMP_GET_SCRIPT_STRING();
+
+ PVR_ASSERT(((IMG_UINTPTR_T)pvLinAddr & (ui32PTSize - 1)) == 0);
+ ui32Flags |= PDUMP_FLAGS_CONTINUOUS;
+ ui32Flags |= ( _PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
+
+
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "-- MALLOC :%s:PAGE_TABLE 0x%08X %u\r\n",
+ psDevId->pszPDumpDevName,
+ ui32PTSize,
+ ui32PTSize);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+
+
+
+
+
+
+
+ PDumpOSCPUVAddrToDevPAddr(psDevId->eDeviceType,
+ hOSMemHandle,
+ ui32Offset,
+ (IMG_PUINT8) pvLinAddr,
+ ui32PTSize,
+ &sDevPAddr);
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "MALLOC :%s:PA_%08X%08X 0x%X %u 0x%08X\r\n",
+ psDevId->pszPDumpDevName,
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag,
+ sDevPAddr.uiAddr,
+ ui32PTSize,
+ ui32PTSize,
+ sDevPAddr.uiAddr);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpFreePages (BM_HEAP *psBMHeap,
+ IMG_DEV_VIRTADDR sDevVAddr,
+ IMG_UINT32 ui32NumBytes,
+ IMG_UINT32 ui32PageSize,
+ IMG_HANDLE hUniqueTag,
+ IMG_BOOL bInterleaved)
+{
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32NumPages, ui32PageCounter;
+ IMG_DEV_PHYADDR sDevPAddr;
+ IMG_UINT32 ui32Flags = PDUMP_FLAGS_CONTINUOUS;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ PDUMP_GET_SCRIPT_STRING();
+
+ PVR_ASSERT(((IMG_UINT32) sDevVAddr.uiAddr & (ui32PageSize - 1)) == 0);
+ PVR_ASSERT(((IMG_UINT32) ui32NumBytes & (ui32PageSize - 1)) == 0);
+
+ psDeviceNode = psBMHeap->pBMContext->psDeviceNode;
+ ui32Flags |= ( _PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
+
+
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "-- FREE :%s:VA_%08X\r\n",
+ psDeviceNode->sDevId.pszPDumpDevName, sDevVAddr.uiAddr);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+
+ {
+ PVRSRV_DEVICE_NODE *psDeviceNode = psBMHeap->pBMContext->psDeviceNode;
+
+ if( psDeviceNode->pfnMMUIsHeapShared(psBMHeap->pMMUHeap) )
+ {
+ ui32Flags |= PDUMP_FLAGS_PERSISTENT;
+ }
+ }
+#endif
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+
+
+ ui32NumPages = ui32NumBytes / ui32PageSize;
+ for (ui32PageCounter = 0; ui32PageCounter < ui32NumPages; ui32PageCounter++)
+ {
+ if (!bInterleaved || (ui32PageCounter % 2) == 0)
+ {
+ sDevPAddr = psDeviceNode->pfnMMUGetPhysPageAddr(psBMHeap->pMMUHeap, sDevVAddr);
+
+ PVR_ASSERT(sDevPAddr.uiAddr != 0)
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "FREE :%s:PA_%08X%08X\r\n",
+ psDeviceNode->sDevId.pszPDumpDevName, (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag, sDevPAddr.uiAddr);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+ }
+ else
+ {
+
+ }
+
+ sDevVAddr.uiAddr += ui32PageSize;
+ }
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpFreePageTable (PVRSRV_DEVICE_IDENTIFIER *psDevID,
+ IMG_HANDLE hOSMemHandle,
+ IMG_CPU_VIRTADDR pvLinAddr,
+ IMG_UINT32 ui32PTSize,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag)
+{
+ PVRSRV_ERROR eErr;
+ IMG_DEV_PHYADDR sDevPAddr;
+
+ PDUMP_GET_SCRIPT_STRING();
+
+ PVR_UNREFERENCED_PARAMETER(ui32PTSize);
+ ui32Flags |= PDUMP_FLAGS_CONTINUOUS;
+ ui32Flags |= ( _PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
+
+
+ PVR_ASSERT(((IMG_UINTPTR_T)pvLinAddr & (ui32PTSize-1UL)) == 0);
+
+
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "-- FREE :%s:PAGE_TABLE\r\n", psDevID->pszPDumpDevName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+
+
+
+
+
+
+
+ PDumpOSCPUVAddrToDevPAddr(psDevID->eDeviceType,
+ hOSMemHandle,
+ 0,
+ (IMG_PUINT8) pvLinAddr,
+ ui32PTSize,
+ &sDevPAddr);
+
+ {
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "FREE :%s:PA_%08X%08X\r\n",
+ psDevID->pszPDumpDevName,
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag,
+ sDevPAddr.uiAddr);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpPDRegWithFlags(PDUMP_MMU_ATTRIB *psMMUAttrib,
+ IMG_UINT32 ui32Reg,
+ IMG_UINT32 ui32Data,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag)
+{
+ PVRSRV_ERROR eErr;
+ IMG_CHAR *pszRegString;
+ PDUMP_GET_SCRIPT_STRING()
+
+ if(psMMUAttrib->pszPDRegRegion != IMG_NULL)
+ {
+ pszRegString = psMMUAttrib->pszPDRegRegion;
+ }
+ else
+ {
+ pszRegString = psMMUAttrib->sDevId.pszPDumpRegName;
+ }
+
+
+
+#if defined(SGX_FEATURE_36BIT_MMU)
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen,
+ "WRW :%s:$1 :%s:PA_%08X%08X:0x0\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)hUniqueTag,
+ (ui32Data & psMMUAttrib->ui32PDEMask) << psMMUAttrib->ui32PDEAlignShift);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "SHR :%s:$1 :%s:$1 0x4\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ psMMUAttrib->sDevId.pszPDumpDevName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen,
+ "WRW :%s:0x%08X: %s:$1\r\n",
+ pszRegString,
+ ui32Reg,
+ psMMUAttrib->sDevId.pszPDumpDevName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+#else
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "WRW :%s:0x%08X :%s:PA_%08X%08X:0x%08X\r\n",
+ pszRegString,
+ ui32Reg,
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag,
+ (ui32Data & psMMUAttrib->ui32PDEMask) << psMMUAttrib->ui32PDEAlignShift,
+ ui32Data & ~psMMUAttrib->ui32PDEMask);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+#endif
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpPDReg (PDUMP_MMU_ATTRIB *psMMUAttrib,
+ IMG_UINT32 ui32Reg,
+ IMG_UINT32 ui32Data,
+ IMG_HANDLE hUniqueTag)
+{
+ return PDumpPDRegWithFlags(psMMUAttrib, ui32Reg, ui32Data, PDUMP_FLAGS_CONTINUOUS, hUniqueTag);
+}
+
+PVRSRV_ERROR PDumpMemPolKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ PDUMP_POLL_OPERATOR eOperator,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag)
+{
+ #define MEMPOLL_DELAY (1000)
+ #define MEMPOLL_COUNT (2000000000 / MEMPOLL_DELAY)
+
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32PageOffset;
+ IMG_UINT8 *pui8LinAddr;
+ IMG_DEV_PHYADDR sDevPAddr;
+ IMG_DEV_VIRTADDR sDevVPageAddr;
+ PDUMP_MMU_ATTRIB *psMMUAttrib;
+
+ PDUMP_GET_SCRIPT_STRING();
+
+ if (PDumpOSIsSuspended())
+ {
+ return PVRSRV_OK;
+ }
+
+ if ( _PDumpIsPersistent() )
+ {
+
+ return PVRSRV_OK;
+ }
+
+
+ PVR_ASSERT((ui32Offset + sizeof(IMG_UINT32)) <= psMemInfo->uAllocSize);
+
+ psMMUAttrib = ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->psMMUAttrib;
+
+
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "-- POL :%s:VA_%08X 0x%08X 0x%08X %d %d %d\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ psMemInfo->sDevVAddr.uiAddr + ui32Offset,
+ ui32Value,
+ ui32Mask,
+ eOperator,
+ MEMPOLL_COUNT,
+ MEMPOLL_DELAY);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+
+ pui8LinAddr = psMemInfo->pvLinAddrKM;
+
+
+ pui8LinAddr += ui32Offset;
+
+
+
+
+ PDumpOSCPUVAddrToPhysPages(psMemInfo->sMemBlk.hOSMemHandle,
+ ui32Offset,
+ pui8LinAddr,
+ psMMUAttrib->ui32DataPageMask,
+ &ui32PageOffset);
+
+
+ sDevVPageAddr.uiAddr = psMemInfo->sDevVAddr.uiAddr + ui32Offset - ui32PageOffset;
+
+ PVR_ASSERT((sDevVPageAddr.uiAddr & psMMUAttrib->ui32DataPageMask) == 0);
+
+
+ BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
+
+
+ sDevPAddr.uiAddr += ui32PageOffset;
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "POL :%s:PA_%08X%08X:0x%08X 0x%08X 0x%08X %d %d %d\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag,
+ sDevPAddr.uiAddr & ~(psMMUAttrib->ui32DataPageMask),
+ sDevPAddr.uiAddr & (psMMUAttrib->ui32DataPageMask),
+ ui32Value,
+ ui32Mask,
+ eOperator,
+ MEMPOLL_COUNT,
+ MEMPOLL_DELAY);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpMemKM(IMG_PVOID pvAltLinAddr,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag)
+{
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32NumPages;
+ IMG_UINT32 ui32PageByteOffset;
+ IMG_UINT32 ui32BlockBytes;
+ IMG_UINT8* pui8LinAddr;
+ IMG_UINT8* pui8DataLinAddr = IMG_NULL;
+ IMG_DEV_VIRTADDR sDevVPageAddr;
+ IMG_DEV_VIRTADDR sDevVAddr;
+ IMG_DEV_PHYADDR sDevPAddr;
+ IMG_UINT32 ui32ParamOutPos;
+ PDUMP_MMU_ATTRIB *psMMUAttrib;
+ IMG_UINT32 ui32DataPageSize;
+
+ PDUMP_GET_SCRIPT_AND_FILE_STRING();
+
+
+ if (ui32Bytes == 0 || PDumpOSIsSuspended())
+ {
+ return PVRSRV_OK;
+ }
+
+ psMMUAttrib = ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->psMMUAttrib;
+
+
+
+ PVR_ASSERT((ui32Offset + ui32Bytes) <= psMemInfo->uAllocSize);
+
+ if (!PDumpOSJTInitialised())
+ {
+ return PVRSRV_ERROR_PDUMP_NOT_AVAILABLE;
+ }
+
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+
+ {
+ BM_HEAP *pHeap = ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap;
+ PVRSRV_DEVICE_NODE *psDeviceNode = pHeap->pBMContext->psDeviceNode;
+
+ if( psDeviceNode->pfnMMUIsHeapShared(pHeap->pMMUHeap) )
+ {
+ ui32Flags |= PDUMP_FLAGS_PERSISTENT;
+ }
+ }
+#endif
+
+
+ if(pvAltLinAddr)
+ {
+ pui8DataLinAddr = pvAltLinAddr;
+ }
+ else if(psMemInfo->pvLinAddrKM)
+ {
+ pui8DataLinAddr = (IMG_UINT8 *)psMemInfo->pvLinAddrKM + ui32Offset;
+ }
+ pui8LinAddr = (IMG_UINT8 *)psMemInfo->pvLinAddrKM;
+ sDevVAddr = psMemInfo->sDevVAddr;
+
+
+ sDevVAddr.uiAddr += ui32Offset;
+ pui8LinAddr += ui32Offset;
+
+ PVR_ASSERT(pui8DataLinAddr);
+
+ PDumpOSCheckForSplitting(PDumpOSGetStream(PDUMP_STREAM_PARAM2), ui32Bytes, ui32Flags);
+
+ ui32ParamOutPos = PDumpOSGetStreamOffset(PDUMP_STREAM_PARAM2);
+
+
+
+ if(!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_PARAM2),
+ pui8DataLinAddr,
+ ui32Bytes,
+ ui32Flags))
+ {
+ return PVRSRV_ERROR_PDUMP_BUFFER_FULL;
+ }
+
+ if (PDumpOSGetParamFileNum() == 0)
+ {
+ eErr = PDumpOSSprintf(pszFileName, ui32MaxLenFileName, "%%0%%.prm");
+ }
+ else
+ {
+ eErr = PDumpOSSprintf(pszFileName, ui32MaxLenFileName, "%%0%%_%u.prm", PDumpOSGetParamFileNum());
+ }
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "-- LDB :%s:VA_%08X%08X:0x%08X 0x%08X 0x%08X %s\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag,
+ psMemInfo->sDevVAddr.uiAddr,
+ ui32Offset,
+ ui32Bytes,
+ ui32ParamOutPos,
+ pszFileName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+
+
+
+ PDumpOSCPUVAddrToPhysPages(psMemInfo->sMemBlk.hOSMemHandle,
+ ui32Offset,
+ pui8LinAddr,
+ psMMUAttrib->ui32DataPageMask,
+ &ui32PageByteOffset);
+ ui32DataPageSize = psMMUAttrib->ui32DataPageMask + 1;
+ ui32NumPages = (ui32PageByteOffset + ui32Bytes + psMMUAttrib->ui32DataPageMask) / ui32DataPageSize;
+
+ while(ui32NumPages)
+ {
+ ui32NumPages--;
+
+
+ sDevVPageAddr.uiAddr = sDevVAddr.uiAddr - ui32PageByteOffset;
+
+ if (ui32DataPageSize <= PDUMP_TEMP_BUFFER_SIZE)
+ {
+
+ PVR_ASSERT((sDevVPageAddr.uiAddr & psMMUAttrib->ui32DataPageMask) == 0);
+ }
+
+
+ BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
+
+
+ sDevPAddr.uiAddr += ui32PageByteOffset;
+
+
+ if (ui32PageByteOffset + ui32Bytes > ui32DataPageSize)
+ {
+
+ ui32BlockBytes = ui32DataPageSize - ui32PageByteOffset;
+ }
+ else
+ {
+
+ ui32BlockBytes = ui32Bytes;
+ }
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "LDB :%s:PA_%08X%08X:0x%08X 0x%08X 0x%08X %s\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag,
+ sDevPAddr.uiAddr & ~(psMMUAttrib->ui32DataPageMask),
+ sDevPAddr.uiAddr & (psMMUAttrib->ui32DataPageMask),
+ ui32BlockBytes,
+ ui32ParamOutPos,
+ pszFileName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+
+
+#if defined(SGX_FEATURE_VARIABLE_MMU_PAGE_SIZE)
+
+ ui32PageByteOffset = (ui32PageByteOffset + ui32BlockBytes) % ui32DataPageSize;
+#else
+
+ ui32PageByteOffset = 0;
+#endif
+
+ ui32Bytes -= ui32BlockBytes;
+
+ sDevVAddr.uiAddr += ui32BlockBytes;
+
+ pui8LinAddr += ui32BlockBytes;
+
+ ui32ParamOutPos += ui32BlockBytes;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpMemPDEntriesKM(PDUMP_MMU_ATTRIB *psMMUAttrib,
+ IMG_HANDLE hOSMemHandle,
+ IMG_CPU_VIRTADDR pvLinAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_BOOL bInitialisePages,
+ IMG_HANDLE hUniqueTag1,
+ IMG_HANDLE hUniqueTag2)
+{
+ PDUMP_MMU_ATTRIB sMMUAttrib;
+
+
+ sMMUAttrib = *psMMUAttrib;
+ sMMUAttrib.ui32PTSize = (IMG_UINT32)HOST_PAGESIZE();
+ return PDumpMemPTEntriesKM( &sMMUAttrib,
+ hOSMemHandle,
+ pvLinAddr,
+ ui32Bytes,
+ ui32Flags,
+ bInitialisePages,
+ hUniqueTag1,
+ hUniqueTag2);
+}
+
+PVRSRV_ERROR PDumpMemPTEntriesKM(PDUMP_MMU_ATTRIB *psMMUAttrib,
+ IMG_HANDLE hOSMemHandle,
+ IMG_CPU_VIRTADDR pvLinAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_BOOL bInitialisePages,
+ IMG_HANDLE hUniqueTag1,
+ IMG_HANDLE hUniqueTag2)
+{
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32NumPages;
+ IMG_UINT32 ui32PageOffset;
+ IMG_UINT32 ui32BlockBytes;
+ IMG_UINT8* pui8LinAddr;
+ IMG_DEV_PHYADDR sDevPAddr;
+ IMG_CPU_PHYADDR sCpuPAddr;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT32 ui32ParamOutPos;
+ IMG_UINT32 ui32PageMask;
+
+ PDUMP_GET_SCRIPT_AND_FILE_STRING();
+ ui32Flags |= ( _PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
+
+ if (PDumpOSIsSuspended())
+ {
+ return PVRSRV_OK;
+ }
+
+ if (!PDumpOSJTInitialised())
+ {
+ return PVRSRV_ERROR_PDUMP_NOT_AVAILABLE;
+ }
+
+ if (!pvLinAddr)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ PDumpOSCheckForSplitting(PDumpOSGetStream(PDUMP_STREAM_PARAM2), ui32Bytes, ui32Flags);
+
+ ui32ParamOutPos = PDumpOSGetStreamOffset(PDUMP_STREAM_PARAM2);
+
+ if (bInitialisePages)
+ {
+
+
+
+ if (!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_PARAM2),
+ pvLinAddr,
+ ui32Bytes,
+ ui32Flags | PDUMP_FLAGS_CONTINUOUS))
+ {
+ return PVRSRV_ERROR_PDUMP_BUFFER_FULL;
+ }
+
+ if (PDumpOSGetParamFileNum() == 0)
+ {
+ eErr = PDumpOSSprintf(pszFileName, ui32MaxLenFileName, "%%0%%.prm");
+ }
+ else
+ {
+ eErr = PDumpOSSprintf(pszFileName, ui32MaxLenFileName, "%%0%%_%u.prm", PDumpOSGetParamFileNum());
+ }
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ }
+
+
+
+
+
+
+ ui32PageMask = psMMUAttrib->ui32PTSize - 1;
+
+
+
+
+ ui32PageOffset = (IMG_UINT32)((IMG_UINTPTR_T)pvLinAddr & (psMMUAttrib->ui32PTSize - 1));
+ ui32NumPages = (ui32PageOffset + ui32Bytes + psMMUAttrib->ui32PTSize - 1) / psMMUAttrib->ui32PTSize;
+ pui8LinAddr = (IMG_UINT8*) pvLinAddr;
+
+ while (ui32NumPages)
+ {
+ ui32NumPages--;
+
+
+
+
+
+
+ sCpuPAddr = OSMapLinToCPUPhys(hOSMemHandle, pui8LinAddr);
+ sDevPAddr = SysCpuPAddrToDevPAddr(psMMUAttrib->sDevId.eDeviceType, sCpuPAddr);
+
+
+ if (ui32PageOffset + ui32Bytes > psMMUAttrib->ui32PTSize)
+ {
+
+ ui32BlockBytes = psMMUAttrib->ui32PTSize - ui32PageOffset;
+ }
+ else
+ {
+
+ ui32BlockBytes = ui32Bytes;
+ }
+
+
+
+
+ if (bInitialisePages)
+ {
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "LDB :%s:PA_%08X%08X:0x%08X 0x%08X 0x%08X %s\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag1,
+ sDevPAddr.uiAddr & ~ui32PageMask,
+ sDevPAddr.uiAddr & ui32PageMask,
+ ui32BlockBytes,
+ ui32ParamOutPos,
+ pszFileName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+ }
+ else
+ {
+ for (ui32Offset = 0; ui32Offset < ui32BlockBytes; ui32Offset += sizeof(IMG_UINT32))
+ {
+ IMG_UINT32 ui32PTE = *((IMG_UINT32 *)(IMG_UINTPTR_T)(pui8LinAddr + ui32Offset));
+
+ if ((ui32PTE & psMMUAttrib->ui32PDEMask) != 0)
+ {
+
+#if defined(SGX_FEATURE_36BIT_MMU)
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "WRW :%s:$1 :%s:PA_%08X%08X:0x0\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)hUniqueTag2,
+ (ui32PTE & psMMUAttrib->ui32PDEMask) << psMMUAttrib->ui32PTEAlignShift);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLenScript, "SHR :%s:$1 :%s:$1 0x4\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ psMMUAttrib->sDevId.pszPDumpDevName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLenScript, "OR :%s:$1 :%s:$1 0x%08X\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ ui32PTE & ~psMMUAttrib->ui32PDEMask);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "WRW :%s:PA_%08X%08X:0x%08X :%s:$1\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)hUniqueTag1,
+ (sDevPAddr.uiAddr + ui32Offset) & ~ui32PageMask,
+ (sDevPAddr.uiAddr + ui32Offset) & ui32PageMask,
+ psMMUAttrib->sDevId.pszPDumpDevName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+#else
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "WRW :%s:PA_%08X%08X:0x%08X :%s:PA_%08X%08X:0x%08X\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag1,
+ (sDevPAddr.uiAddr + ui32Offset) & ~ui32PageMask,
+ (sDevPAddr.uiAddr + ui32Offset) & ui32PageMask,
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag2,
+ (ui32PTE & psMMUAttrib->ui32PDEMask) << psMMUAttrib->ui32PTEAlignShift,
+ ui32PTE & ~psMMUAttrib->ui32PDEMask);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+#endif
+ }
+ else
+ {
+#if !defined(FIX_HW_BRN_31620)
+ PVR_ASSERT((ui32PTE & psMMUAttrib->ui32PTEValid) == 0UL);
+#endif
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "WRW :%s:PA_%08X%08X:0x%08X 0x%08X%08X\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag1,
+ (sDevPAddr.uiAddr + ui32Offset) & ~ui32PageMask,
+ (sDevPAddr.uiAddr + ui32Offset) & ui32PageMask,
+ (ui32PTE << psMMUAttrib->ui32PTEAlignShift),
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag2);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+ }
+ }
+ }
+
+
+
+
+ ui32PageOffset = 0;
+
+ ui32Bytes -= ui32BlockBytes;
+
+ pui8LinAddr += ui32BlockBytes;
+
+ ui32ParamOutPos += ui32BlockBytes;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpPDDevPAddrKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_DEV_PHYADDR sPDDevPAddr,
+ IMG_HANDLE hUniqueTag1,
+ IMG_HANDLE hUniqueTag2)
+{
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32PageByteOffset;
+ IMG_DEV_VIRTADDR sDevVAddr;
+ IMG_DEV_VIRTADDR sDevVPageAddr;
+ IMG_DEV_PHYADDR sDevPAddr;
+ IMG_UINT32 ui32Flags = PDUMP_FLAGS_CONTINUOUS;
+ IMG_UINT32 ui32ParamOutPos;
+ PDUMP_MMU_ATTRIB *psMMUAttrib;
+ IMG_UINT32 ui32PageMask;
+
+ PDUMP_GET_SCRIPT_AND_FILE_STRING();
+
+ if (!PDumpOSJTInitialised())
+ {
+ return PVRSRV_ERROR_PDUMP_NOT_AVAILABLE;
+ }
+
+ psMMUAttrib = ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->psMMUAttrib;
+ ui32PageMask = psMMUAttrib->ui32PTSize - 1;
+
+ ui32ParamOutPos = PDumpOSGetStreamOffset(PDUMP_STREAM_PARAM2);
+
+
+ if(!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_PARAM2),
+ (IMG_UINT8 *)&sPDDevPAddr,
+ sizeof(IMG_DEV_PHYADDR),
+ ui32Flags))
+ {
+ return PVRSRV_ERROR_PDUMP_BUFFER_FULL;
+ }
+
+ if (PDumpOSGetParamFileNum() == 0)
+ {
+ eErr = PDumpOSSprintf(pszFileName, ui32MaxLenFileName, "%%0%%.prm");
+ }
+ else
+ {
+ eErr = PDumpOSSprintf(pszFileName, ui32MaxLenFileName, "%%0%%_%u.prm", PDumpOSGetParamFileNum());
+ }
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "-- LDB :%s:PA_0x%08X%08X:0x%08X 0x%08X 0x%08X %s\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag1,
+ sPDDevPAddr.uiAddr & ~ui32PageMask,
+ sPDDevPAddr.uiAddr & ui32PageMask,
+ sizeof(IMG_DEV_PHYADDR),
+ ui32ParamOutPos,
+ pszFileName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+
+ sDevVAddr = psMemInfo->sDevVAddr;
+ ui32PageByteOffset = sDevVAddr.uiAddr & ui32PageMask;
+
+ sDevVPageAddr.uiAddr = sDevVAddr.uiAddr - ui32PageByteOffset;
+ PVR_ASSERT((sDevVPageAddr.uiAddr & 0xFFF) == 0);
+
+ BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
+ sDevPAddr.uiAddr += ui32PageByteOffset + ui32Offset;
+
+ if ((sPDDevPAddr.uiAddr & psMMUAttrib->ui32PDEMask) != 0UL)
+ {
+#if defined(SGX_FEATURE_36BIT_MMU)
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "WRW :%s:$1 :%s:PA_%08X%08X:0x0\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)hUniqueTag2,
+ sPDDevPAddr.uiAddr);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLenScript, "AND :%s:$2 :%s:$1 0xFFFFFFFF\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ psMMUAttrib->sDevId.pszPDumpDevName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "WRW :%s:PA_%08X%08X:0x%08X :%s:$2\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)hUniqueTag1,
+ (sDevPAddr.uiAddr) & ~(psMMUAttrib->ui32DataPageMask),
+ (sDevPAddr.uiAddr) & (psMMUAttrib->ui32DataPageMask),
+ psMMUAttrib->sDevId.pszPDumpDevName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLenScript, "SHR :%s:$2 :%s:$1 0x20\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ psMMUAttrib->sDevId.pszPDumpDevName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "WRW :%s:PA_%08X%08X:0x%08X :%s:$2\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)hUniqueTag1,
+ (sDevPAddr.uiAddr + 4) & ~(psMMUAttrib->ui32DataPageMask),
+ (sDevPAddr.uiAddr + 4) & (psMMUAttrib->ui32DataPageMask),
+ psMMUAttrib->sDevId.pszPDumpDevName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+#else
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "WRW :%s:PA_%08X%08X:0x%08X :%s:PA_%08X%08X:0x%08X\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag1,
+ sDevPAddr.uiAddr & ~ui32PageMask,
+ sDevPAddr.uiAddr & ui32PageMask,
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag2,
+ sPDDevPAddr.uiAddr & psMMUAttrib->ui32PDEMask,
+ sPDDevPAddr.uiAddr & ~psMMUAttrib->ui32PDEMask);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+#endif
+ }
+ else
+ {
+ PVR_ASSERT(!(sDevPAddr.uiAddr & psMMUAttrib->ui32PTEValid));
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "WRW :%s:PA_%08X%08X:0x%08X 0x%08X\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag1,
+ sDevPAddr.uiAddr & ~ui32PageMask,
+ sDevPAddr.uiAddr & ui32PageMask,
+ sPDDevPAddr.uiAddr);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpCommentKM(IMG_CHAR *pszComment, IMG_UINT32 ui32Flags)
+{
+ PVRSRV_ERROR eErr;
+ IMG_CHAR pszCommentPrefix[] = "-- ";
+#if defined(PDUMP_DEBUG_OUTFILES)
+ IMG_CHAR pszTemp[256];
+#endif
+ IMG_UINT32 ui32LenCommentPrefix;
+ PDUMP_GET_SCRIPT_STRING();
+ PDUMP_DBG(("PDumpCommentKM"));
+#if defined(PDUMP_DEBUG_OUTFILES)
+
+ ui32Flags |= ( _PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
+#endif
+
+ PDumpOSVerifyLineEnding(pszComment, ui32MaxLen);
+
+
+ ui32LenCommentPrefix = PDumpOSBuflen(pszCommentPrefix, sizeof(pszCommentPrefix));
+
+
+
+ if (!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_SCRIPT2),
+ (IMG_UINT8*)pszCommentPrefix,
+ ui32LenCommentPrefix,
+ ui32Flags))
+ {
+#if defined(PDUMP_DEBUG_OUTFILES)
+ if(ui32Flags & PDUMP_FLAGS_CONTINUOUS)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "Incomplete comment, %d: %s (continuous set)",
+ g_ui32EveryLineCounter, pszComment));
+ return PVRSRV_ERROR_PDUMP_BUFFER_FULL;
+ }
+ else if(ui32Flags & PDUMP_FLAGS_PERSISTENT)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "Incomplete comment, %d: %s (persistent set)",
+ g_ui32EveryLineCounter, pszComment));
+ return PVRSRV_ERROR_CMD_NOT_PROCESSED;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_WARNING, "Incomplete comment, %d: %s",
+ g_ui32EveryLineCounter, pszComment));
+ return PVRSRV_ERROR_CMD_NOT_PROCESSED;
+ }
+#else
+ PVR_DPF((PVR_DBG_WARNING, "Incomplete comment, %s",
+ pszComment));
+ return PVRSRV_ERROR_CMD_NOT_PROCESSED;
+#endif
+ }
+
+#if defined(PDUMP_DEBUG_OUTFILES)
+
+ eErr = PDumpOSSprintf(pszTemp, 256, "%d-%d %s",
+ _PDumpGetPID(),
+ g_ui32EveryLineCounter,
+ pszComment);
+
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "%s",
+ pszTemp);
+#else
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "%s",
+ pszComment);
+#endif
+ if( (eErr != PVRSRV_OK) &&
+ (eErr != PVRSRV_ERROR_PDUMP_BUF_OVERFLOW))
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpCommentWithFlags(IMG_UINT32 ui32Flags, IMG_CHAR * pszFormat, ...)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_va_list ap;
+ PDUMP_GET_MSG_STRING();
+
+
+ PDUMP_va_start(ap, pszFormat);
+ eErr = PDumpOSVSprintf(pszMsg, ui32MaxLen, pszFormat, ap);
+ PDUMP_va_end(ap);
+
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ return PDumpCommentKM(pszMsg, ui32Flags);
+}
+
+PVRSRV_ERROR PDumpComment(IMG_CHAR *pszFormat, ...)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_va_list ap;
+ PDUMP_GET_MSG_STRING();
+
+
+ PDUMP_va_start(ap, pszFormat);
+ eErr = PDumpOSVSprintf(pszMsg, ui32MaxLen, pszFormat, ap);
+ PDUMP_va_end(ap);
+
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ return PDumpCommentKM(pszMsg, PDUMP_FLAGS_CONTINUOUS);
+}
+
+PVRSRV_ERROR PDumpDriverInfoKM(IMG_CHAR *pszString, IMG_UINT32 ui32Flags)
+{
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32MsgLen;
+ PDUMP_GET_MSG_STRING();
+
+
+ eErr = PDumpOSSprintf(pszMsg, ui32MaxLen, "%s", pszString);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+
+ PDumpOSVerifyLineEnding(pszMsg, ui32MaxLen);
+ ui32MsgLen = PDumpOSBuflen(pszMsg, ui32MaxLen);
+
+ if (!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_DRIVERINFO),
+ (IMG_UINT8*)pszMsg,
+ ui32MsgLen,
+ ui32Flags))
+ {
+ if (ui32Flags & PDUMP_FLAGS_CONTINUOUS)
+ {
+ return PVRSRV_ERROR_PDUMP_BUFFER_FULL;
+ }
+ else
+ {
+ return PVRSRV_ERROR_CMD_NOT_PROCESSED;
+ }
+ }
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpBitmapKM( PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ IMG_UINT32 ui32Width,
+ IMG_UINT32 ui32Height,
+ IMG_UINT32 ui32StrideInBytes,
+ IMG_DEV_VIRTADDR sDevBaseAddr,
+ IMG_HANDLE hDevMemContext,
+ IMG_UINT32 ui32Size,
+ PDUMP_PIXEL_FORMAT ePixelFormat,
+ PDUMP_MEM_FORMAT eMemFormat,
+ IMG_UINT32 ui32PDumpFlags)
+{
+ PVRSRV_DEVICE_IDENTIFIER *psDevId = &psDeviceNode->sDevId;
+ IMG_UINT32 ui32MMUContextID;
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING();
+
+ if ( _PDumpIsPersistent() )
+ {
+ return PVRSRV_OK;
+ }
+
+ PDumpCommentWithFlags(ui32PDumpFlags, "\r\n-- Dump bitmap of render\r\n");
+
+
+ ui32MMUContextID = psDeviceNode->pfnMMUGetContextID( hDevMemContext );
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "SII %s %s.bin :%s:v%x:0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X\r\n",
+ pszFileName,
+ pszFileName,
+ psDevId->pszPDumpDevName,
+ ui32MMUContextID,
+ sDevBaseAddr.uiAddr,
+ ui32Size,
+ ui32FileOffset,
+ ePixelFormat,
+ ui32Width,
+ ui32Height,
+ ui32StrideInBytes,
+ eMemFormat);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+ PDumpOSWriteString2( hScript, ui32PDumpFlags);
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpReadRegKM ( IMG_CHAR *pszPDumpRegName,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ IMG_UINT32 ui32Address,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32PDumpFlags)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING();
+
+ PVR_UNREFERENCED_PARAMETER(ui32Size);
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "SAB :%s:0x%08X 0x%08X %s\r\n",
+ pszPDumpRegName,
+ ui32Address,
+ ui32FileOffset,
+ pszFileName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+ PDumpOSWriteString2( hScript, ui32PDumpFlags);
+
+ return PVRSRV_OK;
+}
+
+IMG_BOOL PDumpTestNextFrame(IMG_UINT32 ui32CurrentFrame)
+{
+ IMG_BOOL bFrameDumped;
+
+
+
+ (IMG_VOID) PDumpSetFrameKM(ui32CurrentFrame + 1);
+ bFrameDumped = PDumpIsCaptureFrameKM();
+ (IMG_VOID) PDumpSetFrameKM(ui32CurrentFrame);
+
+ return bFrameDumped;
+}
+
+static PVRSRV_ERROR PDumpSignatureRegister (PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32Address,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 *pui32FileOffset,
+ IMG_UINT32 ui32Flags)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING();
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "SAB :%s:0x%08X 0x%08X %s\r\n",
+ psDevId->pszPDumpRegName,
+ ui32Address,
+ *pui32FileOffset,
+ pszFileName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+ PDumpOSWriteString2(hScript, ui32Flags);
+ *pui32FileOffset += ui32Size;
+ return PVRSRV_OK;
+}
+
+static IMG_VOID PDumpRegisterRange(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 *pui32Registers,
+ IMG_UINT32 ui32NumRegisters,
+ IMG_UINT32 *pui32FileOffset,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32Flags)
+{
+ IMG_UINT32 i;
+ for (i = 0; i < ui32NumRegisters; i++)
+ {
+ PDumpSignatureRegister(psDevId, pszFileName, pui32Registers[i], ui32Size, pui32FileOffset, ui32Flags);
+ }
+}
+
+PVRSRV_ERROR PDump3DSignatureRegisters(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ IMG_UINT32 ui32DumpFrameNum,
+ IMG_BOOL bLastFrame,
+ IMG_UINT32 *pui32Registers,
+ IMG_UINT32 ui32NumRegisters)
+{
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32FileOffset, ui32Flags;
+
+ PDUMP_GET_FILE_STRING();
+
+ ui32Flags = bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0;
+ ui32FileOffset = 0;
+
+ PDumpCommentWithFlags(ui32Flags, "\r\n-- Dump 3D signature registers\r\n");
+ eErr = PDumpOSSprintf(pszFileName, ui32MaxLen, "out%u_3d.sig", ui32DumpFrameNum);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+ PDumpRegisterRange(psDevId,
+ pszFileName,
+ pui32Registers,
+ ui32NumRegisters,
+ &ui32FileOffset,
+ sizeof(IMG_UINT32),
+ ui32Flags);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpTASignatureRegisters (PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ IMG_UINT32 ui32DumpFrameNum,
+ IMG_UINT32 ui32TAKickCount,
+ IMG_BOOL bLastFrame,
+ IMG_UINT32 *pui32Registers,
+ IMG_UINT32 ui32NumRegisters)
+{
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32FileOffset, ui32Flags;
+
+ PDUMP_GET_FILE_STRING();
+
+ ui32Flags = bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0;
+ ui32FileOffset = ui32TAKickCount * ui32NumRegisters * sizeof(IMG_UINT32);
+
+ PDumpCommentWithFlags(ui32Flags, "\r\n-- Dump TA signature registers\r\n");
+ eErr = PDumpOSSprintf(pszFileName, ui32MaxLen, "out%u_ta.sig", ui32DumpFrameNum);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+ PDumpRegisterRange(psDevId,
+ pszFileName,
+ pui32Registers,
+ ui32NumRegisters,
+ &ui32FileOffset,
+ sizeof(IMG_UINT32),
+ ui32Flags);
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpCounterRegisters (PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ IMG_UINT32 ui32DumpFrameNum,
+ IMG_BOOL bLastFrame,
+ IMG_UINT32 *pui32Registers,
+ IMG_UINT32 ui32NumRegisters)
+{
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32FileOffset, ui32Flags;
+
+ PDUMP_GET_FILE_STRING();
+
+ ui32Flags = bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0UL;
+ ui32FileOffset = 0UL;
+
+ PDumpCommentWithFlags(ui32Flags, "\r\n-- Dump counter registers\r\n");
+ eErr = PDumpOSSprintf(pszFileName, ui32MaxLen, "out%u.perf", ui32DumpFrameNum);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+ PDumpRegisterRange(psDevId,
+ pszFileName,
+ pui32Registers,
+ ui32NumRegisters,
+ &ui32FileOffset,
+ sizeof(IMG_UINT32),
+ ui32Flags);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpRegRead(IMG_CHAR *pszPDumpRegName,
+ const IMG_UINT32 ui32RegOffset,
+ IMG_UINT32 ui32Flags)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING();
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "RDW :%s:0x%X\r\n",
+ pszPDumpRegName,
+ ui32RegOffset);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpSaveMemKM (PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ IMG_DEV_VIRTADDR sDevBaseAddr,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32MMUContextID,
+ IMG_UINT32 ui32PDumpFlags)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING();
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "SAB :%s:v%x:0x%08X 0x%08X 0x%08X %s.bin\r\n",
+ psDevId->pszPDumpDevName,
+ ui32MMUContextID,
+ sDevBaseAddr.uiAddr,
+ ui32Size,
+ ui32FileOffset,
+ pszFileName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+ PDumpOSWriteString2(hScript, ui32PDumpFlags);
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpCycleCountRegRead(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ const IMG_UINT32 ui32RegOffset,
+ IMG_BOOL bLastFrame)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING();
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "RDW :%s:0x%X\r\n",
+ psDevId->pszPDumpRegName,
+ ui32RegOffset);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PDumpSignatureBuffer (PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ IMG_CHAR *pszFileName,
+ IMG_CHAR *pszBufferType,
+ IMG_UINT32 ui32FileOffset,
+ IMG_DEV_VIRTADDR sDevBaseAddr,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32MMUContextID,
+ IMG_UINT32 ui32PDumpFlags)
+{
+ PDumpCommentWithFlags(ui32PDumpFlags, "\r\n-- Dump microkernel %s signature Buffer\r\n",
+ pszBufferType);
+ PDumpCommentWithFlags(ui32PDumpFlags, "Buffer format (sizes in 32-bit words):\r\n");
+ PDumpCommentWithFlags(ui32PDumpFlags, "\tNumber of signatures per sample (1)\r\n");
+ PDumpCommentWithFlags(ui32PDumpFlags, "\tNumber of samples (1)\r\n");
+ PDumpCommentWithFlags(ui32PDumpFlags, "\tSignature register offsets (1 * number of signatures)\r\n");
+ PDumpCommentWithFlags(ui32PDumpFlags, "\tSignature sample values (number of samples * number of signatures)\r\n");
+ PDumpCommentWithFlags(ui32PDumpFlags, "Note: If buffer is full, last sample is final state after test completed\r\n");
+ return PDumpSaveMemKM(psDevId, pszFileName, ui32FileOffset, sDevBaseAddr, ui32Size,
+ ui32MMUContextID, ui32PDumpFlags);
+}
+
+
+PVRSRV_ERROR PDumpHWPerfCBKM (PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ IMG_DEV_VIRTADDR sDevBaseAddr,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32MMUContextID,
+ IMG_UINT32 ui32PDumpFlags)
+{
+ PDumpCommentWithFlags(ui32PDumpFlags, "\r\n-- Dump Hardware Performance Circular Buffer\r\n");
+ return PDumpSaveMemKM(psDevId, pszFileName, ui32FileOffset, sDevBaseAddr, ui32Size,
+ ui32MMUContextID, ui32PDumpFlags);
+}
+
+
+PVRSRV_ERROR PDumpCBP(PPVRSRV_KERNEL_MEM_INFO psROffMemInfo,
+ IMG_UINT32 ui32ROffOffset,
+ IMG_UINT32 ui32WPosVal,
+ IMG_UINT32 ui32PacketSize,
+ IMG_UINT32 ui32BufferSize,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag)
+{
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32PageOffset;
+ IMG_UINT8 *pui8LinAddr;
+ IMG_DEV_VIRTADDR sDevVAddr;
+ IMG_DEV_PHYADDR sDevPAddr;
+ IMG_DEV_VIRTADDR sDevVPageAddr;
+
+ PDUMP_MMU_ATTRIB *psMMUAttrib;
+
+ PDUMP_GET_SCRIPT_STRING();
+
+ psMMUAttrib = ((BM_BUF*)psROffMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->psMMUAttrib;
+
+
+ PVR_ASSERT((ui32ROffOffset + sizeof(IMG_UINT32)) <= psROffMemInfo->uAllocSize);
+
+ pui8LinAddr = psROffMemInfo->pvLinAddrKM;
+ sDevVAddr = psROffMemInfo->sDevVAddr;
+
+
+ pui8LinAddr += ui32ROffOffset;
+ sDevVAddr.uiAddr += ui32ROffOffset;
+
+
+
+
+ PDumpOSCPUVAddrToPhysPages(psROffMemInfo->sMemBlk.hOSMemHandle,
+ ui32ROffOffset,
+ pui8LinAddr,
+ psMMUAttrib->ui32DataPageMask,
+ &ui32PageOffset);
+
+
+ sDevVPageAddr.uiAddr = sDevVAddr.uiAddr - ui32PageOffset;
+
+ PVR_ASSERT((sDevVPageAddr.uiAddr & 0xFFF) == 0);
+
+
+ BM_GetPhysPageAddr(psROffMemInfo, sDevVPageAddr, &sDevPAddr);
+
+
+ sDevPAddr.uiAddr += ui32PageOffset;
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "CBP :%s:PA_%08X%08X:0x%08X 0x%08X 0x%08X 0x%08X\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag,
+ sDevPAddr.uiAddr & ~(psMMUAttrib->ui32DataPageMask),
+ sDevPAddr.uiAddr & (psMMUAttrib->ui32DataPageMask),
+ ui32WPosVal,
+ ui32PacketSize,
+ ui32BufferSize);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PDumpIDLWithFlags(IMG_UINT32 ui32Clocks, IMG_UINT32 ui32Flags)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING();
+ PDUMP_DBG(("PDumpIDLWithFlags"));
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "IDL %u\r\n", ui32Clocks);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PDumpIDL(IMG_UINT32 ui32Clocks)
+{
+ return PDumpIDLWithFlags(ui32Clocks, PDUMP_FLAGS_CONTINUOUS);
+}
+
+PVRSRV_ERROR PDumpMemUM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_PVOID pvAltLinAddrUM,
+ IMG_PVOID pvLinAddrUM,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag)
+{
+ IMG_VOID *pvAddrUM;
+ IMG_VOID *pvAddrKM;
+ IMG_UINT32 ui32BytesDumped;
+ IMG_UINT32 ui32CurrentOffset;
+
+ if (psMemInfo->pvLinAddrKM != IMG_NULL && pvAltLinAddrUM == IMG_NULL)
+ {
+
+ return PDumpMemKM(IMG_NULL,
+ psMemInfo,
+ ui32Offset,
+ ui32Bytes,
+ ui32Flags,
+ hUniqueTag);
+ }
+
+ pvAddrUM = (pvAltLinAddrUM != IMG_NULL) ? pvAltLinAddrUM : ((pvLinAddrUM != IMG_NULL) ? VPTR_PLUS(pvLinAddrUM, ui32Offset) : IMG_NULL);
+
+ pvAddrKM = GetTempBuffer();
+
+
+ PVR_ASSERT(pvAddrUM != IMG_NULL && pvAddrKM != IMG_NULL);
+ if (pvAddrUM == IMG_NULL || pvAddrKM == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpMemUM: Nothing to dump"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if (ui32Bytes > PDUMP_TEMP_BUFFER_SIZE)
+ {
+ PDumpCommentWithFlags(ui32Flags, "Dumping 0x%08x bytes of memory, in blocks of 0x%08x bytes", ui32Bytes, (IMG_UINT32)PDUMP_TEMP_BUFFER_SIZE);
+ }
+
+ ui32CurrentOffset = ui32Offset;
+ for (ui32BytesDumped = 0; ui32BytesDumped < ui32Bytes;)
+ {
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32BytesToDump = MIN(PDUMP_TEMP_BUFFER_SIZE, ui32Bytes - ui32BytesDumped);
+
+ eError = OSCopyFromUser(psPerProc,
+ pvAddrKM,
+ pvAddrUM,
+ ui32BytesToDump);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpMemUM: OSCopyFromUser failed (%d)", eError));
+ return eError;
+ }
+
+ eError = PDumpMemKM(pvAddrKM,
+ psMemInfo,
+ ui32CurrentOffset,
+ ui32BytesToDump,
+ ui32Flags,
+ hUniqueTag);
+
+ if (eError != PVRSRV_OK)
+ {
+
+ if (ui32BytesDumped != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpMemUM: PDumpMemKM failed (%d)", eError));
+ }
+ PVR_ASSERT(ui32BytesDumped == 0);
+ return eError;
+ }
+
+ VPTR_INC(pvAddrUM, ui32BytesToDump);
+ ui32CurrentOffset += ui32BytesToDump;
+ ui32BytesDumped += ui32BytesToDump;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR _PdumpAllocMMUContext(IMG_UINT32 *pui32MMUContextID)
+{
+ IMG_UINT32 i;
+
+
+ for(i=0; i<MAX_PDUMP_MMU_CONTEXTS; i++)
+ {
+ if((gui16MMUContextUsage & (1U << i)) == 0)
+ {
+
+ gui16MMUContextUsage |= 1U << i;
+ *pui32MMUContextID = i;
+ return PVRSRV_OK;
+ }
+ }
+
+ PVR_DPF((PVR_DBG_ERROR, "_PdumpAllocMMUContext: no free MMU context ids"));
+
+ return PVRSRV_ERROR_MMU_CONTEXT_NOT_FOUND;
+}
+
+
+static PVRSRV_ERROR _PdumpFreeMMUContext(IMG_UINT32 ui32MMUContextID)
+{
+ if(ui32MMUContextID < MAX_PDUMP_MMU_CONTEXTS)
+ {
+
+ gui16MMUContextUsage &= ~(1U << ui32MMUContextID);
+ return PVRSRV_OK;
+ }
+
+ PVR_DPF((PVR_DBG_ERROR, "_PdumpFreeMMUContext: MMU context ids invalid"));
+
+ return PVRSRV_ERROR_MMU_CONTEXT_NOT_FOUND;
+}
+
+
+PVRSRV_ERROR PDumpSetMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_CHAR *pszMemSpace,
+ IMG_UINT32 *pui32MMUContextID,
+ IMG_UINT32 ui32MMUType,
+ IMG_HANDLE hUniqueTag1,
+ IMG_HANDLE hOSMemHandle,
+ IMG_VOID *pvPDCPUAddr)
+{
+ IMG_UINT8 *pui8LinAddr = (IMG_UINT8 *)pvPDCPUAddr;
+ IMG_CPU_PHYADDR sCpuPAddr;
+ IMG_DEV_PHYADDR sDevPAddr;
+ IMG_UINT32 ui32MMUContextID;
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING();
+
+ eErr = _PdumpAllocMMUContext(&ui32MMUContextID);
+ if(eErr != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpSetMMUContext: _PdumpAllocMMUContext failed: %d", eErr));
+ return eErr;
+ }
+
+
+
+ sCpuPAddr = OSMapLinToCPUPhys(hOSMemHandle, pui8LinAddr);
+ sDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
+
+ sDevPAddr.uiAddr &= ~((PVRSRV_4K_PAGE_SIZE) -1);
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "MMU :%s:v%d %d :%s:PA_%08X%08X\r\n",
+ pszMemSpace,
+ ui32MMUContextID,
+ ui32MMUType,
+ pszMemSpace,
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag1,
+ sDevPAddr.uiAddr);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+
+
+ *pui32MMUContextID = ui32MMUContextID;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PDumpClearMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_CHAR *pszMemSpace,
+ IMG_UINT32 ui32MMUContextID,
+ IMG_UINT32 ui32MMUType)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING();
+ PVR_UNREFERENCED_PARAMETER(eDeviceType);
+ PVR_UNREFERENCED_PARAMETER(ui32MMUType);
+
+
+ PDumpComment("Clear MMU Context for memory space %s\r\n", pszMemSpace);
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "MMU :%s:v%d\r\n",
+ pszMemSpace,
+ ui32MMUContextID);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+
+ eErr = _PdumpFreeMMUContext(ui32MMUContextID);
+ if(eErr != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpClearMMUContext: _PdumpFreeMMUContext failed: %d", eErr));
+ return eErr;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpStoreMemToFile(PDUMP_MMU_ATTRIB *psMMUAttrib,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 uiAddr,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32PDumpFlags,
+ IMG_HANDLE hUniqueTag)
+{
+ IMG_DEV_PHYADDR sDevPAddr;
+ IMG_DEV_VIRTADDR sDevVPageAddr;
+ IMG_UINT32 ui32PageOffset;
+
+ PDUMP_GET_SCRIPT_STRING();
+
+
+
+
+ ui32PageOffset = (IMG_UINT32)((IMG_UINTPTR_T)psMemInfo->pvLinAddrKM & psMMUAttrib->ui32DataPageMask);
+
+
+ sDevVPageAddr.uiAddr = uiAddr - ui32PageOffset;
+
+
+ BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
+
+
+ sDevPAddr.uiAddr += ui32PageOffset;
+
+ PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "SAB :%s:PA_%08X%08X:0x%08X 0x%08X 0x%08X %s\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag,
+ sDevPAddr.uiAddr & ~psMMUAttrib->ui32DataPageMask,
+ sDevPAddr.uiAddr & psMMUAttrib->ui32DataPageMask,
+ ui32Size,
+ ui32FileOffset,
+ pszFileName);
+
+ PDumpOSWriteString2(hScript, ui32PDumpFlags);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpRegBasedCBP(IMG_CHAR *pszPDumpRegName,
+ IMG_UINT32 ui32RegOffset,
+ IMG_UINT32 ui32WPosVal,
+ IMG_UINT32 ui32PacketSize,
+ IMG_UINT32 ui32BufferSize,
+ IMG_UINT32 ui32Flags)
+{
+ PDUMP_GET_SCRIPT_STRING();
+
+ PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "CBP :%s:0x%08X 0x%08X 0x%08X 0x%08X\r\n",
+ pszPDumpRegName,
+ ui32RegOffset,
+ ui32WPosVal,
+ ui32PacketSize,
+ ui32BufferSize);
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+ return PVRSRV_OK;
+}
+
+
+
+#include "syscommon.h"
+
+IMG_EXPORT IMG_VOID PDumpConnectionNotify(IMG_VOID)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_DEVICE_NODE *psThis;
+ PVR_DPF((PVR_DBG_WARNING, "PDump has connected."));
+
+
+ SysAcquireData(&psSysData);
+
+ psThis = psSysData->psDeviceNodeList;
+ while (psThis)
+ {
+ if (psThis->pfnPDumpInitDevice)
+ {
+
+ psThis->pfnPDumpInitDevice(psThis);
+ }
+ psThis = psThis->psNext;
+ }
+}
+
+IMG_UINT32 DbgWrite(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32BCount, IMG_UINT32 ui32Flags)
+{
+ IMG_UINT32 ui32BytesWritten = 0;
+ IMG_UINT32 ui32Off = 0;
+ PDBG_STREAM_CONTROL psCtrl = psStream->psCtrl;
+
+
+ if ((ui32Flags & PDUMP_FLAGS_NEVER) != 0)
+ {
+ return ui32BCount;
+ }
+
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+
+ if ( (_PDumpIsProcessActive() == IMG_FALSE ) &&
+ ((ui32Flags & PDUMP_FLAGS_PERSISTENT) == 0) )
+ {
+ return ui32BCount;
+ }
+#endif
+
+
+ if ( ((ui32Flags & PDUMP_FLAGS_PERSISTENT) != 0) && (psCtrl->bInitPhaseComplete) )
+ {
+ while (ui32BCount > 0)
+ {
+
+
+
+ ui32BytesWritten = PDumpOSDebugDriverWrite( psStream,
+ PDUMP_WRITE_MODE_PERSISTENT,
+ &pui8Data[ui32Off], ui32BCount, 1, 0);
+
+ if (ui32BytesWritten == 0)
+ {
+ PDumpOSReleaseExecution();
+ }
+
+ if (ui32BytesWritten != 0xFFFFFFFFU)
+ {
+ ui32Off += ui32BytesWritten;
+ ui32BCount -= ui32BytesWritten;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DbgWrite: Failed to send persistent data"));
+ if( (psCtrl->ui32Flags & DEBUG_FLAGS_READONLY) != 0)
+ {
+
+ PDumpSuspendKM();
+ }
+ return 0xFFFFFFFFU;
+ }
+ }
+
+
+ ui32BCount = ui32Off; ui32Off = 0; ui32BytesWritten = 0;
+ }
+
+ while (((IMG_UINT32) ui32BCount > 0) && (ui32BytesWritten != 0xFFFFFFFFU))
+ {
+ if ((ui32Flags & PDUMP_FLAGS_CONTINUOUS) != 0)
+ {
+
+
+ if (((psCtrl->ui32CapMode & DEBUG_CAPMODE_FRAMED) != 0) &&
+ (psCtrl->ui32Start == 0xFFFFFFFFU) &&
+ (psCtrl->ui32End == 0xFFFFFFFFU) &&
+ psCtrl->bInitPhaseComplete)
+ {
+ ui32BytesWritten = ui32BCount;
+ }
+ else
+ {
+ ui32BytesWritten = PDumpOSDebugDriverWrite( psStream,
+ PDUMP_WRITE_MODE_CONTINUOUS,
+ &pui8Data[ui32Off], ui32BCount, 1, 0);
+ }
+ }
+ else
+ {
+ if (ui32Flags & PDUMP_FLAGS_LASTFRAME)
+ {
+ IMG_UINT32 ui32DbgFlags;
+
+ ui32DbgFlags = 0;
+ if (ui32Flags & PDUMP_FLAGS_RESETLFBUFFER)
+ {
+ ui32DbgFlags |= WRITELF_FLAGS_RESETBUF;
+ }
+
+ ui32BytesWritten = PDumpOSDebugDriverWrite( psStream,
+ PDUMP_WRITE_MODE_LASTFRAME,
+ &pui8Data[ui32Off], ui32BCount, 1, ui32DbgFlags);
+ }
+ else
+ {
+ ui32BytesWritten = PDumpOSDebugDriverWrite( psStream,
+ PDUMP_WRITE_MODE_BINCM,
+ &pui8Data[ui32Off], ui32BCount, 1, 0);
+ }
+ }
+
+
+
+
+ if (ui32BytesWritten == 0)
+ {
+ PDumpOSReleaseExecution();
+ }
+
+ if (ui32BytesWritten != 0xFFFFFFFFU)
+ {
+ ui32Off += ui32BytesWritten;
+ ui32BCount -= ui32BytesWritten;
+ }
+
+
+ }
+
+
+
+ return ui32BytesWritten;
+}
+
+
+
+#else
+#endif
diff --git a/drivers/gpu/pvr/pdump_int.h b/drivers/gpu/pvr/pdump_int.h
new file mode 100644
index 0000000..9f68549
--- /dev/null
+++ b/drivers/gpu/pvr/pdump_int.h
@@ -0,0 +1,67 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __PDUMP_INT_H__
+#define __PDUMP_INT_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if !defined(_UITRON)
+#include "dbgdrvif.h"
+
+IMG_EXPORT IMG_VOID PDumpConnectionNotify(IMG_VOID);
+
+#endif
+
+typedef enum
+{
+
+ PDUMP_WRITE_MODE_CONTINUOUS = 0,
+
+ PDUMP_WRITE_MODE_LASTFRAME,
+
+ PDUMP_WRITE_MODE_BINCM,
+
+ PDUMP_WRITE_MODE_PERSISTENT
+} PDUMP_DDWMODE;
+
+
+IMG_UINT32 DbgWrite(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32BCount, IMG_UINT32 ui32Flags);
+
+IMG_UINT32 PDumpOSDebugDriverWrite( PDBG_STREAM psStream,
+ PDUMP_DDWMODE eDbgDrvWriteMode,
+ IMG_UINT8 *pui8Data,
+ IMG_UINT32 ui32BCount,
+ IMG_UINT32 ui32Level,
+ IMG_UINT32 ui32DbgDrvFlags);
+
+#if defined (__cplusplus)
+}
+#endif
+#endif
+
diff --git a/drivers/gpu/pvr/pdump_km.h b/drivers/gpu/pvr/pdump_km.h
new file mode 100644
index 0000000..6c516e0
--- /dev/null
+++ b/drivers/gpu/pvr/pdump_km.h
@@ -0,0 +1,412 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef _PDUMP_KM_H_
+#define _PDUMP_KM_H_
+
+
+#include "pdump_osfunc.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#include "pdump.h"
+
+#define PDUMP_PD_UNIQUETAG (IMG_HANDLE)0
+#define PDUMP_PT_UNIQUETAG (IMG_HANDLE)0
+
+#define PDUMP_STREAM_PARAM2 0
+#define PDUMP_STREAM_SCRIPT2 1
+#define PDUMP_STREAM_DRIVERINFO 2
+#define PDUMP_NUM_STREAMS 3
+
+#if defined(PDUMP_DEBUG_OUTFILES)
+extern IMG_UINT32 g_ui32EveryLineCounter;
+#endif
+
+#ifndef PDUMP
+#define MAKEUNIQUETAG(hMemInfo) (0)
+#endif
+
+#ifdef PDUMP
+
+#define MAKEUNIQUETAG(hMemInfo) (((BM_BUF *)(((PVRSRV_KERNEL_MEM_INFO *)(hMemInfo))->sMemBlk.hBuffer))->pMapping)
+
+ IMG_IMPORT PVRSRV_ERROR PDumpMemPolKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ PDUMP_POLL_OPERATOR eOperator,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag);
+
+ IMG_IMPORT PVRSRV_ERROR PDumpMemUM(PVRSRV_PER_PROCESS_DATA *psProcData,
+ IMG_PVOID pvAltLinAddr,
+ IMG_PVOID pvLinAddr,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag);
+
+ IMG_IMPORT PVRSRV_ERROR PDumpMemKM(IMG_PVOID pvAltLinAddr,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag);
+ PVRSRV_ERROR PDumpMemPagesKM(PVRSRV_DEVICE_IDENTIFIER *psDevID,
+ IMG_DEV_PHYADDR *pPages,
+ IMG_UINT32 ui32NumPages,
+ IMG_DEV_VIRTADDR sDevAddr,
+ IMG_UINT32 ui32Start,
+ IMG_UINT32 ui32Length,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag);
+
+ PVRSRV_ERROR PDumpMemPDEntriesKM(PDUMP_MMU_ATTRIB *psMMUAttrib,
+ IMG_HANDLE hOSMemHandle,
+ IMG_CPU_VIRTADDR pvLinAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_BOOL bInitialisePages,
+ IMG_HANDLE hUniqueTag1,
+ IMG_HANDLE hUniqueTag2);
+
+ PVRSRV_ERROR PDumpMemPTEntriesKM(PDUMP_MMU_ATTRIB *psMMUAttrib,
+ IMG_HANDLE hOSMemHandle,
+ IMG_CPU_VIRTADDR pvLinAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_BOOL bInitialisePages,
+ IMG_HANDLE hUniqueTag1,
+ IMG_HANDLE hUniqueTag2);
+ IMG_VOID PDumpInitCommon(IMG_VOID);
+ IMG_VOID PDumpDeInitCommon(IMG_VOID);
+ IMG_VOID PDumpInit(IMG_VOID);
+ IMG_VOID PDumpDeInit(IMG_VOID);
+ IMG_BOOL PDumpIsSuspended(IMG_VOID);
+ PVRSRV_ERROR PDumpStartInitPhaseKM(IMG_VOID);
+ PVRSRV_ERROR PDumpStopInitPhaseKM(IMG_VOID);
+ IMG_IMPORT PVRSRV_ERROR PDumpSetFrameKM(IMG_UINT32 ui32Frame);
+ IMG_IMPORT PVRSRV_ERROR PDumpCommentKM(IMG_CHAR *pszComment, IMG_UINT32 ui32Flags);
+ IMG_IMPORT PVRSRV_ERROR PDumpDriverInfoKM(IMG_CHAR *pszString, IMG_UINT32 ui32Flags);
+
+ PVRSRV_ERROR PDumpRegWithFlagsKM(IMG_CHAR *pszPDumpRegName,
+ IMG_UINT32 ui32RegAddr,
+ IMG_UINT32 ui32RegValue,
+ IMG_UINT32 ui32Flags);
+ PVRSRV_ERROR PDumpRegPolWithFlagsKM(IMG_CHAR *pszPDumpRegName,
+ IMG_UINT32 ui32RegAddr,
+ IMG_UINT32 ui32RegValue,
+ IMG_UINT32 ui32Mask,
+ IMG_UINT32 ui32Flags,
+ PDUMP_POLL_OPERATOR eOperator);
+ PVRSRV_ERROR PDumpRegPolKM(IMG_CHAR *pszPDumpRegName,
+ IMG_UINT32 ui32RegAddr,
+ IMG_UINT32 ui32RegValue,
+ IMG_UINT32 ui32Mask,
+ PDUMP_POLL_OPERATOR eOperator);
+
+ IMG_IMPORT PVRSRV_ERROR PDumpBitmapKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ IMG_UINT32 ui32Width,
+ IMG_UINT32 ui32Height,
+ IMG_UINT32 ui32StrideInBytes,
+ IMG_DEV_VIRTADDR sDevBaseAddr,
+ IMG_HANDLE hDevMemContext,
+ IMG_UINT32 ui32Size,
+ PDUMP_PIXEL_FORMAT ePixelFormat,
+ PDUMP_MEM_FORMAT eMemFormat,
+ IMG_UINT32 ui32PDumpFlags);
+ IMG_IMPORT PVRSRV_ERROR PDumpReadRegKM(IMG_CHAR *pszPDumpRegName,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ IMG_UINT32 ui32Address,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32PDumpFlags);
+
+ PVRSRV_ERROR PDumpRegKM(IMG_CHAR* pszPDumpRegName,
+ IMG_UINT32 dwReg,
+ IMG_UINT32 dwData);
+
+ PVRSRV_ERROR PDumpComment(IMG_CHAR* pszFormat, ...) IMG_FORMAT_PRINTF(1, 2);
+ PVRSRV_ERROR PDumpCommentWithFlags(IMG_UINT32 ui32Flags,
+ IMG_CHAR* pszFormat,
+ ...) IMG_FORMAT_PRINTF(2, 3);
+
+ PVRSRV_ERROR PDumpPDReg(PDUMP_MMU_ATTRIB *psMMUAttrib,
+ IMG_UINT32 ui32Reg,
+ IMG_UINT32 ui32dwData,
+ IMG_HANDLE hUniqueTag);
+ PVRSRV_ERROR PDumpPDRegWithFlags(PDUMP_MMU_ATTRIB *psMMUAttrib,
+ IMG_UINT32 ui32Reg,
+ IMG_UINT32 ui32Data,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag);
+
+ IMG_BOOL PDumpIsLastCaptureFrameKM(IMG_VOID);
+ IMG_IMPORT IMG_BOOL PDumpIsCaptureFrameKM(IMG_VOID);
+
+ IMG_VOID PDumpMallocPagesPhys(PVRSRV_DEVICE_IDENTIFIER *psDevID,
+ IMG_UINT32 ui32DevVAddr,
+ IMG_PUINT32 pui32PhysPages,
+ IMG_UINT32 ui32NumPages,
+ IMG_HANDLE hUniqueTag);
+ PVRSRV_ERROR PDumpSetMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_CHAR *pszMemSpace,
+ IMG_UINT32 *pui32MMUContextID,
+ IMG_UINT32 ui32MMUType,
+ IMG_HANDLE hUniqueTag1,
+ IMG_HANDLE hOSMemHandle,
+ IMG_VOID *pvPDCPUAddr);
+ PVRSRV_ERROR PDumpClearMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_CHAR *pszMemSpace,
+ IMG_UINT32 ui32MMUContextID,
+ IMG_UINT32 ui32MMUType);
+
+ PVRSRV_ERROR PDumpPDDevPAddrKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_DEV_PHYADDR sPDDevPAddr,
+ IMG_HANDLE hUniqueTag1,
+ IMG_HANDLE hUniqueTag2);
+
+ IMG_BOOL PDumpTestNextFrame(IMG_UINT32 ui32CurrentFrame);
+
+ PVRSRV_ERROR PDumpSaveMemKM (PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ IMG_DEV_VIRTADDR sDevBaseAddr,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32DataMaster,
+ IMG_UINT32 ui32PDumpFlags);
+
+ PVRSRV_ERROR PDumpTASignatureRegisters(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ IMG_UINT32 ui32DumpFrameNum,
+ IMG_UINT32 ui32TAKickCount,
+ IMG_BOOL bLastFrame,
+ IMG_UINT32 *pui32Registers,
+ IMG_UINT32 ui32NumRegisters);
+
+ PVRSRV_ERROR PDump3DSignatureRegisters(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ IMG_UINT32 ui32DumpFrameNum,
+ IMG_BOOL bLastFrame,
+ IMG_UINT32 *pui32Registers,
+ IMG_UINT32 ui32NumRegisters);
+
+ PVRSRV_ERROR PDumpCounterRegisters(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ IMG_UINT32 ui32DumpFrameNum,
+ IMG_BOOL bLastFrame,
+ IMG_UINT32 *pui32Registers,
+ IMG_UINT32 ui32NumRegisters);
+
+ PVRSRV_ERROR PDumpRegRead(IMG_CHAR *pszPDumpRegName,
+ const IMG_UINT32 dwRegOffset,
+ IMG_UINT32 ui32Flags);
+
+ PVRSRV_ERROR PDumpCycleCountRegRead(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ const IMG_UINT32 dwRegOffset,
+ IMG_BOOL bLastFrame);
+
+ PVRSRV_ERROR PDumpIDLWithFlags(IMG_UINT32 ui32Clocks, IMG_UINT32 ui32Flags);
+ PVRSRV_ERROR PDumpIDL(IMG_UINT32 ui32Clocks);
+
+ PVRSRV_ERROR PDumpMallocPages(PVRSRV_DEVICE_IDENTIFIER *psDevID,
+ IMG_UINT32 ui32DevVAddr,
+ IMG_CPU_VIRTADDR pvLinAddr,
+ IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32NumBytes,
+ IMG_UINT32 ui32PageSize,
+ IMG_BOOL bShared,
+ IMG_HANDLE hUniqueTag);
+ PVRSRV_ERROR PDumpMallocPageTable(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32Offset,
+ IMG_CPU_VIRTADDR pvLinAddr,
+ IMG_UINT32 ui32NumBytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag);
+ PVRSRV_ERROR PDumpFreePages(struct _BM_HEAP_ *psBMHeap,
+ IMG_DEV_VIRTADDR sDevVAddr,
+ IMG_UINT32 ui32NumBytes,
+ IMG_UINT32 ui32PageSize,
+ IMG_HANDLE hUniqueTag,
+ IMG_BOOL bInterleaved);
+ PVRSRV_ERROR PDumpFreePageTable(PVRSRV_DEVICE_IDENTIFIER *psDevID,
+ IMG_HANDLE hOSMemHandle,
+ IMG_CPU_VIRTADDR pvLinAddr,
+ IMG_UINT32 ui32NumBytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag);
+
+ IMG_IMPORT PVRSRV_ERROR PDumpHWPerfCBKM(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ IMG_DEV_VIRTADDR sDevBaseAddr,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32MMUContextID,
+ IMG_UINT32 ui32PDumpFlags);
+
+ PVRSRV_ERROR PDumpSignatureBuffer(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ IMG_CHAR *pszFileName,
+ IMG_CHAR *pszBufferType,
+ IMG_UINT32 ui32FileOffset,
+ IMG_DEV_VIRTADDR sDevBaseAddr,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32MMUContextID,
+ IMG_UINT32 ui32PDumpFlags);
+
+ PVRSRV_ERROR PDumpCBP(PPVRSRV_KERNEL_MEM_INFO psROffMemInfo,
+ IMG_UINT32 ui32ROffOffset,
+ IMG_UINT32 ui32WPosVal,
+ IMG_UINT32 ui32PacketSize,
+ IMG_UINT32 ui32BufferSize,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag);
+
+ PVRSRV_ERROR PDumpRegBasedCBP(IMG_CHAR *pszPDumpRegName,
+ IMG_UINT32 ui32RegOffset,
+ IMG_UINT32 ui32WPosVal,
+ IMG_UINT32 ui32PacketSize,
+ IMG_UINT32 ui32BufferSize,
+ IMG_UINT32 ui32Flags);
+
+ IMG_VOID PDumpVGXMemToFile(IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 uiAddr,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32PDumpFlags,
+ IMG_HANDLE hUniqueTag);
+
+ IMG_VOID PDumpSuspendKM(IMG_VOID);
+ IMG_VOID PDumpResumeKM(IMG_VOID);
+
+
+ PVRSRV_ERROR PDumpStoreMemToFile(PDUMP_MMU_ATTRIB *psMMUAttrib,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 uiAddr,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32PDumpFlags,
+ IMG_HANDLE hUniqueTag);
+
+ #define PDUMPMEMPOL PDumpMemPolKM
+ #define PDUMPMEM PDumpMemKM
+ #define PDUMPMEMPTENTRIES PDumpMemPTEntriesKM
+ #define PDUMPPDENTRIES PDumpMemPDEntriesKM
+ #define PDUMPMEMUM PDumpMemUM
+ #define PDUMPINIT PDumpInitCommon
+ #define PDUMPDEINIT PDumpDeInitCommon
+ #define PDUMPISLASTFRAME PDumpIsLastCaptureFrameKM
+ #define PDUMPTESTFRAME PDumpIsCaptureFrameKM
+ #define PDUMPTESTNEXTFRAME PDumpTestNextFrame
+ #define PDUMPREGWITHFLAGS PDumpRegWithFlagsKM
+ #define PDUMPREG PDumpRegKM
+ #define PDUMPCOMMENT PDumpComment
+ #define PDUMPCOMMENTWITHFLAGS PDumpCommentWithFlags
+ #define PDUMPREGPOL PDumpRegPolKM
+ #define PDUMPREGPOLWITHFLAGS PDumpRegPolWithFlagsKM
+ #define PDUMPMALLOCPAGES PDumpMallocPages
+ #define PDUMPMALLOCPAGETABLE PDumpMallocPageTable
+ #define PDUMPSETMMUCONTEXT PDumpSetMMUContext
+ #define PDUMPCLEARMMUCONTEXT PDumpClearMMUContext
+ #define PDUMPPDDEVPADDR PDumpPDDevPAddrKM
+ #define PDUMPFREEPAGES PDumpFreePages
+ #define PDUMPFREEPAGETABLE PDumpFreePageTable
+ #define PDUMPPDREG PDumpPDReg
+ #define PDUMPPDREGWITHFLAGS PDumpPDRegWithFlags
+ #define PDUMPCBP PDumpCBP
+ #define PDUMPREGBASEDCBP PDumpRegBasedCBP
+ #define PDUMPMALLOCPAGESPHYS PDumpMallocPagesPhys
+ #define PDUMPENDINITPHASE PDumpStopInitPhaseKM
+ #define PDUMPBITMAPKM PDumpBitmapKM
+ #define PDUMPDRIVERINFO PDumpDriverInfoKM
+ #define PDUMPIDLWITHFLAGS PDumpIDLWithFlags
+ #define PDUMPIDL PDumpIDL
+ #define PDUMPSUSPEND PDumpSuspendKM
+ #define PDUMPRESUME PDumpResumeKM
+
+#else
+ #if ((defined(LINUX) || defined(GCC_IA32)) || defined(GCC_ARM))
+ #define PDUMPMEMPOL(args...)
+ #define PDUMPMEM(args...)
+ #define PDUMPMEMPTENTRIES(args...)
+ #define PDUMPPDENTRIES(args...)
+ #define PDUMPMEMUM(args...)
+ #define PDUMPINIT(args...)
+ #define PDUMPDEINIT(args...)
+ #define PDUMPISLASTFRAME(args...)
+ #define PDUMPTESTFRAME(args...)
+ #define PDUMPTESTNEXTFRAME(args...)
+ #define PDUMPREGWITHFLAGS(args...)
+ #define PDUMPREG(args...)
+ #define PDUMPCOMMENT(args...)
+ #define PDUMPREGPOL(args...)
+ #define PDUMPREGPOLWITHFLAGS(args...)
+ #define PDUMPMALLOCPAGES(args...)
+ #define PDUMPMALLOCPAGETABLE(args...)
+ #define PDUMPSETMMUCONTEXT(args...)
+ #define PDUMPCLEARMMUCONTEXT(args...)
+ #define PDUMPPDDEVPADDR(args...)
+ #define PDUMPFREEPAGES(args...)
+ #define PDUMPFREEPAGETABLE(args...)
+ #define PDUMPPDREG(args...)
+ #define PDUMPPDREGWITHFLAGS(args...)
+ #define PDUMPSYNC(args...)
+ #define PDUMPCOPYTOMEM(args...)
+ #define PDUMPWRITE(args...)
+ #define PDUMPCBP(args...)
+ #define PDUMPREGBASEDCBP(args...)
+ #define PDUMPCOMMENTWITHFLAGS(args...)
+ #define PDUMPMALLOCPAGESPHYS(args...)
+ #define PDUMPENDINITPHASE(args...)
+ #define PDUMPMSVDXREG(args...)
+ #define PDUMPMSVDXREGWRITE(args...)
+ #define PDUMPMSVDXREGREAD(args...)
+ #define PDUMPMSVDXPOLEQ(args...)
+ #define PDUMPMSVDXPOL(args...)
+ #define PDUMPBITMAPKM(args...)
+ #define PDUMPDRIVERINFO(args...)
+ #define PDUMPIDLWITHFLAGS(args...)
+ #define PDUMPIDL(args...)
+ #define PDUMPSUSPEND(args...)
+ #define PDUMPRESUME(args...)
+ #define PDUMPMSVDXWRITEREF(args...)
+ #else
+ #error Compiler not specified
+ #endif
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/pvr/pdump_osfunc.h b/drivers/gpu/pvr/pdump_osfunc.h
new file mode 100644
index 0000000..4daacf4
--- /dev/null
+++ b/drivers/gpu/pvr/pdump_osfunc.h
@@ -0,0 +1,140 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include <stdarg.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+#define MAX_PDUMP_STRING_LENGTH (256)
+
+
+
+#define PDUMP_GET_SCRIPT_STRING() \
+ IMG_HANDLE hScript; \
+ IMG_UINT32 ui32MaxLen; \
+ PVRSRV_ERROR eError; \
+ eError = PDumpOSGetScriptString(&hScript, &ui32MaxLen);\
+ if(eError != PVRSRV_OK) return eError;
+
+#define PDUMP_GET_MSG_STRING() \
+ IMG_CHAR *pszMsg; \
+ IMG_UINT32 ui32MaxLen; \
+ PVRSRV_ERROR eError; \
+ eError = PDumpOSGetMessageString(&pszMsg, &ui32MaxLen);\
+ if(eError != PVRSRV_OK) return eError;
+
+#define PDUMP_GET_FILE_STRING() \
+ IMG_CHAR *pszFileName; \
+ IMG_UINT32 ui32MaxLen; \
+ PVRSRV_ERROR eError; \
+ eError = PDumpOSGetFilenameString(&pszFileName, &ui32MaxLen);\
+ if(eError != PVRSRV_OK) return eError;
+
+#define PDUMP_GET_SCRIPT_AND_FILE_STRING() \
+ IMG_HANDLE hScript; \
+ IMG_CHAR *pszFileName; \
+ IMG_UINT32 ui32MaxLenScript; \
+ IMG_UINT32 ui32MaxLenFileName; \
+ PVRSRV_ERROR eError; \
+ eError = PDumpOSGetScriptString(&hScript, &ui32MaxLenScript);\
+ if(eError != PVRSRV_OK) return eError; \
+ eError = PDumpOSGetFilenameString(&pszFileName, &ui32MaxLenFileName);\
+ if(eError != PVRSRV_OK) return eError;
+
+
+ PVRSRV_ERROR PDumpOSGetScriptString(IMG_HANDLE *phScript, IMG_UINT32 *pui32MaxLen);
+
+
+ PVRSRV_ERROR PDumpOSGetMessageString(IMG_CHAR **ppszMsg, IMG_UINT32 *pui32MaxLen);
+
+
+ PVRSRV_ERROR PDumpOSGetFilenameString(IMG_CHAR **ppszFile, IMG_UINT32 *pui32MaxLen);
+
+
+
+
+#define PDUMP_va_list va_list
+#define PDUMP_va_start va_start
+#define PDUMP_va_end va_end
+
+
+
+IMG_HANDLE PDumpOSGetStream(IMG_UINT32 ePDumpStream);
+
+IMG_UINT32 PDumpOSGetStreamOffset(IMG_UINT32 ePDumpStream);
+
+IMG_UINT32 PDumpOSGetParamFileNum(IMG_VOID);
+
+IMG_VOID PDumpOSCheckForSplitting(IMG_HANDLE hStream, IMG_UINT32 ui32Size, IMG_UINT32 ui32Flags);
+
+IMG_BOOL PDumpOSIsSuspended(IMG_VOID);
+
+IMG_BOOL PDumpOSJTInitialised(IMG_VOID);
+
+IMG_BOOL PDumpOSWriteString(IMG_HANDLE hDbgStream,
+ IMG_UINT8 *psui8Data,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32Flags);
+
+IMG_BOOL PDumpOSWriteString2(IMG_HANDLE hScript, IMG_UINT32 ui32Flags);
+
+PVRSRV_ERROR PDumpOSBufprintf(IMG_HANDLE hBuf, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, ...) IMG_FORMAT_PRINTF(3, 4);
+
+IMG_VOID PDumpOSDebugPrintf(IMG_CHAR* pszFormat, ...) IMG_FORMAT_PRINTF(1, 2);
+
+PVRSRV_ERROR PDumpOSSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR *pszFormat, ...) IMG_FORMAT_PRINTF(3, 4);
+
+PVRSRV_ERROR PDumpOSVSprintf(IMG_CHAR *pszMsg, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, PDUMP_va_list vaArgs) IMG_FORMAT_PRINTF(3, 0);
+
+IMG_UINT32 PDumpOSBuflen(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax);
+
+IMG_VOID PDumpOSVerifyLineEnding(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax);
+
+IMG_VOID PDumpOSCPUVAddrToDevPAddr(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT8 *pui8LinAddr,
+ IMG_UINT32 ui32PageSize,
+ IMG_DEV_PHYADDR *psDevPAddr);
+
+IMG_VOID PDumpOSCPUVAddrToPhysPages(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32Offset,
+ IMG_PUINT8 pui8LinAddr,
+ IMG_UINT32 ui32DataPageMask,
+ IMG_UINT32 *pui32PageOffset);
+
+IMG_VOID PDumpOSReleaseExecution(IMG_VOID);
+
+IMG_BOOL PDumpOSIsCaptureFrameKM(IMG_VOID);
+
+PVRSRV_ERROR PDumpOSSetFrameKM(IMG_UINT32 ui32Frame);
+
+#if defined (__cplusplus)
+}
+#endif
diff --git a/drivers/gpu/pvr/pdumpdefs.h b/drivers/gpu/pvr/pdumpdefs.h
new file mode 100644
index 0000000..e43ce2f
--- /dev/null
+++ b/drivers/gpu/pvr/pdumpdefs.h
@@ -0,0 +1,111 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+*****************************************************************************/
+
+#if !defined (__PDUMPDEFS_H__)
+#define __PDUMPDEFS_H__
+
+typedef enum _PDUMP_PIXEL_FORMAT_
+{
+ PVRSRV_PDUMP_PIXEL_FORMAT_UNSUPPORTED = 0,
+ PVRSRV_PDUMP_PIXEL_FORMAT_RGB8 = 1,
+ PVRSRV_PDUMP_PIXEL_FORMAT_RGB332 = 2,
+ PVRSRV_PDUMP_PIXEL_FORMAT_KRGB555 = 3,
+ PVRSRV_PDUMP_PIXEL_FORMAT_RGB565 = 4,
+ PVRSRV_PDUMP_PIXEL_FORMAT_ARGB4444 = 5,
+ PVRSRV_PDUMP_PIXEL_FORMAT_ARGB1555 = 6,
+ PVRSRV_PDUMP_PIXEL_FORMAT_RGB888 = 7,
+ PVRSRV_PDUMP_PIXEL_FORMAT_ARGB8888 = 8,
+ PVRSRV_PDUMP_PIXEL_FORMAT_YUV8 = 9,
+ PVRSRV_PDUMP_PIXEL_FORMAT_AYUV4444 = 10,
+ PVRSRV_PDUMP_PIXEL_FORMAT_VY0UY1_8888 = 11,
+ PVRSRV_PDUMP_PIXEL_FORMAT_UY0VY1_8888 = 12,
+ PVRSRV_PDUMP_PIXEL_FORMAT_Y0UY1V_8888 = 13,
+ PVRSRV_PDUMP_PIXEL_FORMAT_Y0VY1U_8888 = 14,
+ PVRSRV_PDUMP_PIXEL_FORMAT_YUV888 = 15,
+ PVRSRV_PDUMP_PIXEL_FORMAT_UYVY10101010 = 16,
+ PVRSRV_PDUMP_PIXEL_FORMAT_VYAUYA8888 = 17,
+ PVRSRV_PDUMP_PIXEL_FORMAT_AYUV8888 = 18,
+ PVRSRV_PDUMP_PIXEL_FORMAT_AYUV2101010 = 19,
+ PVRSRV_PDUMP_PIXEL_FORMAT_YUV101010 = 20,
+ PVRSRV_PDUMP_PIXEL_FORMAT_PL12Y8 = 21,
+ PVRSRV_PDUMP_PIXEL_FORMAT_YUV_IMC2 = 22,
+ PVRSRV_PDUMP_PIXEL_FORMAT_YUV_YV12 = 23,
+ PVRSRV_PDUMP_PIXEL_FORMAT_YUV_PL8 = 24,
+ PVRSRV_PDUMP_PIXEL_FORMAT_YUV_PL12 = 25,
+ PVRSRV_PDUMP_PIXEL_FORMAT_422PL12YUV8 = 26,
+ PVRSRV_PDUMP_PIXEL_FORMAT_420PL12YUV8 = 27,
+ PVRSRV_PDUMP_PIXEL_FORMAT_PL12Y10 = 28,
+ PVRSRV_PDUMP_PIXEL_FORMAT_422PL12YUV10 = 29,
+ PVRSRV_PDUMP_PIXEL_FORMAT_420PL12YUV10 = 30,
+ PVRSRV_PDUMP_PIXEL_FORMAT_ABGR8888 = 31,
+ PVRSRV_PDUMP_PIXEL_FORMAT_BGRA8888 = 32,
+ PVRSRV_PDUMP_PIXEL_FORMAT_ARGB8332 = 33,
+ PVRSRV_PDUMP_PIXEL_FORMAT_RGB555 = 34,
+ PVRSRV_PDUMP_PIXEL_FORMAT_F16 = 35,
+ PVRSRV_PDUMP_PIXEL_FORMAT_F32 = 36,
+ PVRSRV_PDUMP_PIXEL_FORMAT_L16 = 37,
+ PVRSRV_PDUMP_PIXEL_FORMAT_L32 = 38,
+ PVRSRV_PDUMP_PIXEL_FORMAT_RGBA8888 = 39,
+ PVRSRV_PDUMP_PIXEL_FORMAT_ABGR4444 = 40,
+ PVRSRV_PDUMP_PIXEL_FORMAT_RGBA4444 = 41,
+ PVRSRV_PDUMP_PIXEL_FORMAT_BGRA4444 = 42,
+ PVRSRV_PDUMP_PIXEL_FORMAT_ABGR1555 = 43,
+ PVRSRV_PDUMP_PIXEL_FORMAT_RGBA5551 = 44,
+ PVRSRV_PDUMP_PIXEL_FORMAT_BGRA5551 = 45,
+ PVRSRV_PDUMP_PIXEL_FORMAT_BGR565 = 46,
+ PVRSRV_PDUMP_PIXEL_FORMAT_A8 = 47,
+
+ PVRSRV_PDUMP_PIXEL_FORMAT_FORCE_I32 = 0x7fffffff
+
+} PDUMP_PIXEL_FORMAT;
+
+typedef enum _PDUMP_MEM_FORMAT_
+{
+ PVRSRV_PDUMP_MEM_FORMAT_STRIDE = 0,
+ PVRSRV_PDUMP_MEM_FORMAT_RESERVED = 1,
+ PVRSRV_PDUMP_MEM_FORMAT_TILED = 8,
+ PVRSRV_PDUMP_MEM_FORMAT_TWIDDLED = 9,
+ PVRSRV_PDUMP_MEM_FORMAT_HYBRID = 10,
+
+ PVRSRV_PDUMP_MEM_FORMAT_FORCE_I32 = 0x7fffffff
+} PDUMP_MEM_FORMAT;
+
+typedef enum _PDUMP_POLL_OPERATOR
+{
+ PDUMP_POLL_OPERATOR_EQUAL = 0,
+ PDUMP_POLL_OPERATOR_LESS = 1,
+ PDUMP_POLL_OPERATOR_LESSEQUAL = 2,
+ PDUMP_POLL_OPERATOR_GREATER = 3,
+ PDUMP_POLL_OPERATOR_GREATEREQUAL = 4,
+ PDUMP_POLL_OPERATOR_NOTEQUAL = 5,
+} PDUMP_POLL_OPERATOR;
+
+
+#endif /* __PDUMPDEFS_H__ */
+
+/*****************************************************************************
+ End of file (pdumpdefs.h)
+*****************************************************************************/
diff --git a/drivers/gpu/pvr/perfkm.h b/drivers/gpu/pvr/perfkm.h
new file mode 100644
index 0000000..e12bc2e
--- /dev/null
+++ b/drivers/gpu/pvr/perfkm.h
@@ -0,0 +1,36 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef _PERFKM_H_
+#define _PERFKM_H_
+
+#include "img_types.h"
+
+#define PERFINIT()
+#define PERFDEINIT()
+
+#endif
+
diff --git a/drivers/gpu/pvr/perproc.c b/drivers/gpu/pvr/perproc.c
new file mode 100644
index 0000000..eb73166
--- /dev/null
+++ b/drivers/gpu/pvr/perproc.c
@@ -0,0 +1,305 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "resman.h"
+#include "handle.h"
+#include "perproc.h"
+#include "osperproc.h"
+#if defined(TTRACE)
+#include "ttrace.h"
+#endif
+
+#define HASH_TAB_INIT_SIZE 32
+
+static HASH_TABLE *psHashTab = IMG_NULL;
+
+static PVRSRV_ERROR FreePerProcessData(PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_ERROR eError;
+ IMG_UINTPTR_T uiPerProc;
+
+ PVR_ASSERT(psPerProc != IMG_NULL);
+
+ if (psPerProc == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: invalid parameter"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ uiPerProc = HASH_Remove(psHashTab, (IMG_UINTPTR_T)psPerProc->ui32PID);
+ if (uiPerProc == 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't find process in per-process data hash table"));
+
+ PVR_ASSERT(psPerProc->ui32PID == 0);
+ }
+ else
+ {
+ PVR_ASSERT((PVRSRV_PER_PROCESS_DATA *)uiPerProc == psPerProc);
+ PVR_ASSERT(((PVRSRV_PER_PROCESS_DATA *)uiPerProc)->ui32PID == psPerProc->ui32PID);
+ }
+
+
+ if (psPerProc->psHandleBase != IMG_NULL)
+ {
+ eError = PVRSRVFreeHandleBase(psPerProc->psHandleBase);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't free handle base for process (%d)", eError));
+ return eError;
+ }
+ }
+
+
+ if (psPerProc->hPerProcData != IMG_NULL)
+ {
+ eError = PVRSRVReleaseHandle(KERNEL_HANDLE_BASE, psPerProc->hPerProcData, PVRSRV_HANDLE_TYPE_PERPROC_DATA);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't release per-process data handle (%d)", eError));
+ return eError;
+ }
+ }
+
+
+ eError = OSPerProcessPrivateDataDeInit(psPerProc->hOsPrivateData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: OSPerProcessPrivateDataDeInit failed (%d)", eError));
+ return eError;
+ }
+
+ eError = OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(*psPerProc),
+ psPerProc,
+ psPerProc->hBlockAlloc);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't free per-process data (%d)", eError));
+ return eError;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_PER_PROCESS_DATA *PVRSRVPerProcessData(IMG_UINT32 ui32PID)
+{
+ PVRSRV_PER_PROCESS_DATA *psPerProc;
+
+ PVR_ASSERT(psHashTab != IMG_NULL);
+
+
+ psPerProc = (PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab, (IMG_UINTPTR_T)ui32PID);
+ return psPerProc;
+}
+
+
+PVRSRV_ERROR PVRSRVPerProcessDataConnect(IMG_UINT32 ui32PID, IMG_UINT32 ui32Flags)
+{
+ PVRSRV_PER_PROCESS_DATA *psPerProc;
+ IMG_HANDLE hBlockAlloc;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if (psHashTab == IMG_NULL)
+ {
+ return PVRSRV_ERROR_INIT_FAILURE;
+ }
+
+
+ psPerProc = (PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab, (IMG_UINTPTR_T)ui32PID);
+
+ if (psPerProc == IMG_NULL)
+ {
+
+ eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(*psPerProc),
+ (IMG_PVOID *)&psPerProc,
+ &hBlockAlloc,
+ "Per Process Data");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't allocate per-process data (%d)", eError));
+ return eError;
+ }
+ OSMemSet(psPerProc, 0, sizeof(*psPerProc));
+ psPerProc->hBlockAlloc = hBlockAlloc;
+
+ if (!HASH_Insert(psHashTab, (IMG_UINTPTR_T)ui32PID, (IMG_UINTPTR_T)psPerProc))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't insert per-process data into hash table"));
+ eError = PVRSRV_ERROR_INSERT_HASH_TABLE_DATA_FAILED;
+ goto failure;
+ }
+
+ psPerProc->ui32PID = ui32PID;
+ psPerProc->ui32RefCount = 0;
+
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+ if (ui32Flags == SRV_FLAGS_PDUMP_ACTIVE)
+ {
+ psPerProc->bPDumpActive = IMG_TRUE;
+ }
+#else
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+#endif
+
+
+ eError = OSPerProcessPrivateDataInit(&psPerProc->hOsPrivateData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: OSPerProcessPrivateDataInit failed (%d)", eError));
+ goto failure;
+ }
+
+
+ eError = PVRSRVAllocHandle(KERNEL_HANDLE_BASE,
+ &psPerProc->hPerProcData,
+ psPerProc,
+ PVRSRV_HANDLE_TYPE_PERPROC_DATA,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't allocate handle for per-process data (%d)", eError));
+ goto failure;
+ }
+
+
+ eError = PVRSRVAllocHandleBase(&psPerProc->psHandleBase);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't allocate handle base for process (%d)", eError));
+ goto failure;
+ }
+
+
+ eError = OSPerProcessSetHandleOptions(psPerProc->psHandleBase);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't set handle options (%d)", eError));
+ goto failure;
+ }
+
+
+ eError = PVRSRVResManConnect(psPerProc, &psPerProc->hResManContext);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't register with the resource manager"));
+ goto failure;
+ }
+#if defined (TTRACE)
+ PVRSRVTimeTraceBufferCreate(ui32PID);
+#endif
+ }
+
+ psPerProc->ui32RefCount++;
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "PVRSRVPerProcessDataConnect: Process 0x%x has ref-count %d",
+ ui32PID, psPerProc->ui32RefCount));
+
+ return eError;
+
+failure:
+ (IMG_VOID)FreePerProcessData(psPerProc);
+ return eError;
+}
+
+
+IMG_VOID PVRSRVPerProcessDataDisconnect(IMG_UINT32 ui32PID)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_PER_PROCESS_DATA *psPerProc;
+
+ PVR_ASSERT(psHashTab != IMG_NULL);
+
+ psPerProc = (PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab, (IMG_UINTPTR_T)ui32PID);
+ if (psPerProc == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataDealloc: Couldn't locate per-process data for PID %u", ui32PID));
+ }
+ else
+ {
+ psPerProc->ui32RefCount--;
+ if (psPerProc->ui32RefCount == 0)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVPerProcessDataDisconnect: "
+ "Last close from process 0x%x received", ui32PID));
+
+#if defined (TTRACE)
+ PVRSRVTimeTraceBufferDestroy(ui32PID);
+#endif
+
+
+ PVRSRVResManDisconnect(psPerProc->hResManContext, IMG_FALSE);
+
+
+ eError = FreePerProcessData(psPerProc);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataDisconnect: Error freeing per-process data"));
+ }
+ }
+ }
+
+ eError = PVRSRVPurgeHandles(KERNEL_HANDLE_BASE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataDisconnect: Purge of global handle pool failed (%d)", eError));
+ }
+}
+
+
+PVRSRV_ERROR PVRSRVPerProcessDataInit(IMG_VOID)
+{
+ PVR_ASSERT(psHashTab == IMG_NULL);
+
+
+ psHashTab = HASH_Create(HASH_TAB_INIT_SIZE);
+ if (psHashTab == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataInit: Couldn't create per-process data hash table"));
+ return PVRSRV_ERROR_UNABLE_TO_CREATE_HASH_TABLE;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVPerProcessDataDeInit(IMG_VOID)
+{
+
+ if (psHashTab != IMG_NULL)
+ {
+
+ HASH_Delete(psHashTab);
+ psHashTab = IMG_NULL;
+ }
+
+ return PVRSRV_OK;
+}
+
diff --git a/drivers/gpu/pvr/perproc.h b/drivers/gpu/pvr/perproc.h
new file mode 100644
index 0000000..842680c
--- /dev/null
+++ b/drivers/gpu/pvr/perproc.h
@@ -0,0 +1,126 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __PERPROC_H__
+#define __PERPROC_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "img_types.h"
+#include "resman.h"
+
+#include "handle.h"
+
+typedef struct _PVRSRV_PER_PROCESS_DATA_
+{
+ IMG_UINT32 ui32PID;
+ IMG_HANDLE hBlockAlloc;
+ PRESMAN_CONTEXT hResManContext;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hPerProcData;
+#else
+ IMG_HANDLE hPerProcData;
+#endif
+ PVRSRV_HANDLE_BASE *psHandleBase;
+#if defined (SUPPORT_SID_INTERFACE)
+
+ IMG_BOOL bHandlesBatched;
+#else
+#if defined (PVR_SECURE_HANDLES)
+
+ IMG_BOOL bHandlesBatched;
+#endif
+#endif
+ IMG_UINT32 ui32RefCount;
+
+
+ IMG_BOOL bInitProcess;
+#if defined(PDUMP)
+
+ IMG_BOOL bPDumpPersistent;
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+
+ IMG_BOOL bPDumpActive;
+#endif
+#endif
+
+ IMG_HANDLE hOsPrivateData;
+} PVRSRV_PER_PROCESS_DATA;
+
+PVRSRV_PER_PROCESS_DATA *PVRSRVPerProcessData(IMG_UINT32 ui32PID);
+
+PVRSRV_ERROR PVRSRVPerProcessDataConnect(IMG_UINT32 ui32PID, IMG_UINT32 ui32Flags);
+IMG_VOID PVRSRVPerProcessDataDisconnect(IMG_UINT32 ui32PID);
+
+PVRSRV_ERROR PVRSRVPerProcessDataInit(IMG_VOID);
+PVRSRV_ERROR PVRSRVPerProcessDataDeInit(IMG_VOID);
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVFindPerProcessData)
+#endif
+static INLINE
+PVRSRV_PER_PROCESS_DATA *PVRSRVFindPerProcessData(IMG_VOID)
+{
+ return PVRSRVPerProcessData(OSGetCurrentProcessIDKM());
+}
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVProcessPrivateData)
+#endif
+static INLINE
+IMG_HANDLE PVRSRVProcessPrivateData(PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ return (psPerProc != IMG_NULL) ? psPerProc->hOsPrivateData : IMG_NULL;
+}
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVPerProcessPrivateData)
+#endif
+static INLINE
+IMG_HANDLE PVRSRVPerProcessPrivateData(IMG_UINT32 ui32PID)
+{
+ return PVRSRVProcessPrivateData(PVRSRVPerProcessData(ui32PID));
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVFindPerProcessPrivateData)
+#endif
+static INLINE
+IMG_HANDLE PVRSRVFindPerProcessPrivateData(IMG_VOID)
+{
+ return PVRSRVProcessPrivateData(PVRSRVFindPerProcessData());
+}
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/pvr/power.c b/drivers/gpu/pvr/power.c
new file mode 100644
index 0000000..21d7ad4
--- /dev/null
+++ b/drivers/gpu/pvr/power.c
@@ -0,0 +1,719 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "pdump_km.h"
+
+#include "lists.h"
+
+static IMG_BOOL gbInitServerRunning = IMG_FALSE;
+static IMG_BOOL gbInitServerRan = IMG_FALSE;
+static IMG_BOOL gbInitSuccessful = IMG_FALSE;
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_STATE eInitServerState, IMG_BOOL bState)
+{
+
+ switch(eInitServerState)
+ {
+ case PVRSRV_INIT_SERVER_RUNNING:
+ gbInitServerRunning = bState;
+ break;
+ case PVRSRV_INIT_SERVER_RAN:
+ gbInitServerRan = bState;
+ break;
+ case PVRSRV_INIT_SERVER_SUCCESSFUL:
+ gbInitSuccessful = bState;
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVSetInitServerState : Unknown state %x", eInitServerState));
+ return PVRSRV_ERROR_UNKNOWN_INIT_SERVER_STATE;
+ }
+
+ return PVRSRV_OK;
+}
+
+IMG_EXPORT
+IMG_BOOL PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_STATE eInitServerState)
+{
+ IMG_BOOL bReturnVal;
+
+ switch(eInitServerState)
+ {
+ case PVRSRV_INIT_SERVER_RUNNING:
+ bReturnVal = gbInitServerRunning;
+ break;
+ case PVRSRV_INIT_SERVER_RAN:
+ bReturnVal = gbInitServerRan;
+ break;
+ case PVRSRV_INIT_SERVER_SUCCESSFUL:
+ bReturnVal = gbInitSuccessful;
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVGetInitServerState : Unknown state %x", eInitServerState));
+ bReturnVal = IMG_FALSE;
+ }
+
+ return bReturnVal;
+}
+
+static IMG_BOOL _IsSystemStatePowered(PVRSRV_SYS_POWER_STATE eSystemPowerState)
+{
+ return (IMG_BOOL)(eSystemPowerState < PVRSRV_SYS_POWER_STATE_D2);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVPowerLock(IMG_UINT32 ui32CallerID,
+ IMG_BOOL bSystemPowerEvent)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+ IMG_UINT32 ui32Timeout = 1000000;
+ IMG_BOOL bTryLock = (ui32CallerID == ISR_ID);
+
+ SysAcquireData(&psSysData);
+
+ eError = OSPowerLockWrap(bTryLock);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ do
+ {
+ eError = OSLockResource(&psSysData->sPowerStateChangeResource,
+ ui32CallerID);
+ if (eError == PVRSRV_OK)
+ {
+ break;
+ }
+ else if (bTryLock)
+ {
+
+
+ eError = PVRSRV_ERROR_RETRY;
+ break;
+ }
+
+ OSWaitus(1);
+ ui32Timeout--;
+ } while (ui32Timeout > 0);
+
+ if (eError != PVRSRV_OK)
+ {
+ OSPowerLockUnwrap();
+ }
+
+
+ if ((eError == PVRSRV_OK) &&
+ !bSystemPowerEvent &&
+ !_IsSystemStatePowered(psSysData->eCurrentPowerState))
+ {
+
+ PVRSRVPowerUnlock(ui32CallerID);
+ eError = PVRSRV_ERROR_RETRY;
+ }
+
+ return eError;
+}
+
+
+IMG_EXPORT
+IMG_VOID PVRSRVPowerUnlock(IMG_UINT32 ui32CallerID)
+{
+ OSUnlockResource(&gpsSysData->sPowerStateChangeResource, ui32CallerID);
+ OSPowerLockUnwrap();
+}
+
+
+static PVRSRV_ERROR PVRSRVDevicePrePowerStateKM_AnyVaCb(PVRSRV_POWER_DEV *psPowerDevice, va_list va)
+{
+ PVRSRV_DEV_POWER_STATE eNewDevicePowerState;
+ PVRSRV_ERROR eError;
+
+
+ IMG_BOOL bAllDevices;
+ IMG_UINT32 ui32DeviceIndex;
+ PVRSRV_DEV_POWER_STATE eNewPowerState;
+
+
+ bAllDevices = va_arg(va, IMG_BOOL);
+ ui32DeviceIndex = va_arg(va, IMG_UINT32);
+ eNewPowerState = va_arg(va, PVRSRV_DEV_POWER_STATE);
+
+ if (bAllDevices || (ui32DeviceIndex == psPowerDevice->ui32DeviceIndex))
+ {
+ eNewDevicePowerState = (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT) ?
+ psPowerDevice->eDefaultPowerState : eNewPowerState;
+
+ if (psPowerDevice->eCurrentPowerState != eNewDevicePowerState)
+ {
+ if (psPowerDevice->pfnPrePower != IMG_NULL)
+ {
+
+ eError = psPowerDevice->pfnPrePower(psPowerDevice->hDevCookie,
+ eNewDevicePowerState,
+ psPowerDevice->eCurrentPowerState);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+
+
+ eError = SysDevicePrePowerState(psPowerDevice->ui32DeviceIndex,
+ eNewDevicePowerState,
+ psPowerDevice->eCurrentPowerState);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+static
+PVRSRV_ERROR PVRSRVDevicePrePowerStateKM(IMG_BOOL bAllDevices,
+ IMG_UINT32 ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE eNewPowerState)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+
+ eError = List_PVRSRV_POWER_DEV_PVRSRV_ERROR_Any_va(psSysData->psPowerDeviceList,
+ &PVRSRVDevicePrePowerStateKM_AnyVaCb,
+ bAllDevices,
+ ui32DeviceIndex,
+ eNewPowerState);
+
+ return eError;
+}
+
+static PVRSRV_ERROR PVRSRVDevicePostPowerStateKM_AnyVaCb(PVRSRV_POWER_DEV *psPowerDevice, va_list va)
+{
+ PVRSRV_DEV_POWER_STATE eNewDevicePowerState;
+ PVRSRV_ERROR eError;
+
+
+ IMG_BOOL bAllDevices;
+ IMG_UINT32 ui32DeviceIndex;
+ PVRSRV_DEV_POWER_STATE eNewPowerState;
+
+
+ bAllDevices = va_arg(va, IMG_BOOL);
+ ui32DeviceIndex = va_arg(va, IMG_UINT32);
+ eNewPowerState = va_arg(va, PVRSRV_DEV_POWER_STATE);
+
+ if (bAllDevices || (ui32DeviceIndex == psPowerDevice->ui32DeviceIndex))
+ {
+ eNewDevicePowerState = (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT) ?
+ psPowerDevice->eDefaultPowerState : eNewPowerState;
+
+ if (psPowerDevice->eCurrentPowerState != eNewDevicePowerState)
+ {
+
+ eError = SysDevicePostPowerState(psPowerDevice->ui32DeviceIndex,
+ eNewDevicePowerState,
+ psPowerDevice->eCurrentPowerState);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ if (psPowerDevice->pfnPostPower != IMG_NULL)
+ {
+
+ eError = psPowerDevice->pfnPostPower(psPowerDevice->hDevCookie,
+ eNewDevicePowerState,
+ psPowerDevice->eCurrentPowerState);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+
+ psPowerDevice->eCurrentPowerState = eNewDevicePowerState;
+ }
+ }
+ return PVRSRV_OK;
+}
+
+static
+PVRSRV_ERROR PVRSRVDevicePostPowerStateKM(IMG_BOOL bAllDevices,
+ IMG_UINT32 ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE eNewPowerState)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+
+ eError = List_PVRSRV_POWER_DEV_PVRSRV_ERROR_Any_va(psSysData->psPowerDeviceList,
+ &PVRSRVDevicePostPowerStateKM_AnyVaCb,
+ bAllDevices,
+ ui32DeviceIndex,
+ eNewPowerState);
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(IMG_UINT32 ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ IMG_UINT32 ui32CallerID,
+ IMG_BOOL bRetainMutex)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+ eError = PVRSRVPowerLock(ui32CallerID, IMG_FALSE);
+ if(eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ #if defined(PDUMP)
+ if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT)
+ {
+
+
+
+
+ eError = PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex, PVRSRV_DEV_POWER_STATE_ON);
+ if(eError != PVRSRV_OK)
+ {
+ goto Exit;
+ }
+
+ eError = PVRSRVDevicePostPowerStateKM(IMG_FALSE, ui32DeviceIndex, PVRSRV_DEV_POWER_STATE_ON);
+
+ if (eError != PVRSRV_OK)
+ {
+ goto Exit;
+ }
+
+ PDUMPSUSPEND();
+ }
+ #endif
+
+ eError = PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex, eNewPowerState);
+ if(eError != PVRSRV_OK)
+ {
+ if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT)
+ {
+ PDUMPRESUME();
+ }
+ goto Exit;
+ }
+
+ eError = PVRSRVDevicePostPowerStateKM(IMG_FALSE, ui32DeviceIndex, eNewPowerState);
+
+ if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT)
+ {
+ PDUMPRESUME();
+ }
+
+Exit:
+
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVSetDevicePowerStateKM : Transition to %d FAILED 0x%x", eNewPowerState, eError));
+ }
+
+ if (!bRetainMutex || (eError != PVRSRV_OK))
+ {
+ PVRSRVPowerUnlock(ui32CallerID);
+ }
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSystemPrePowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerState)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+ PVRSRV_DEV_POWER_STATE eNewDevicePowerState;
+
+ SysAcquireData(&psSysData);
+
+
+ eError = PVRSRVPowerLock(KERNEL_ID, IMG_TRUE);
+ if(eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ if (_IsSystemStatePowered(eNewSysPowerState) !=
+ _IsSystemStatePowered(psSysData->eCurrentPowerState))
+ {
+ if (_IsSystemStatePowered(eNewSysPowerState))
+ {
+
+ eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_DEFAULT;
+ }
+ else
+ {
+ eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_OFF;
+ }
+
+
+ eError = PVRSRVDevicePrePowerStateKM(IMG_TRUE, 0, eNewDevicePowerState);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+ }
+
+ if (eNewSysPowerState != psSysData->eCurrentPowerState)
+ {
+
+ eError = SysSystemPrePowerState(eNewSysPowerState);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+ }
+
+ return eError;
+
+ErrorExit:
+
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVSystemPrePowerStateKM: Transition from %d to %d FAILED 0x%x",
+ psSysData->eCurrentPowerState, eNewSysPowerState, eError));
+
+
+ psSysData->eFailedPowerState = eNewSysPowerState;
+
+ PVRSRVPowerUnlock(KERNEL_ID);
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSystemPostPowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerState)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ SYS_DATA *psSysData;
+ PVRSRV_DEV_POWER_STATE eNewDevicePowerState;
+
+ SysAcquireData(&psSysData);
+
+ if (eNewSysPowerState != psSysData->eCurrentPowerState)
+ {
+
+ eError = SysSystemPostPowerState(eNewSysPowerState);
+ if (eError != PVRSRV_OK)
+ {
+ goto Exit;
+ }
+ }
+
+ if (_IsSystemStatePowered(eNewSysPowerState) !=
+ _IsSystemStatePowered(psSysData->eCurrentPowerState))
+ {
+ if (_IsSystemStatePowered(eNewSysPowerState))
+ {
+
+ eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_DEFAULT;
+ }
+ else
+ {
+ eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_OFF;
+ }
+
+
+ eError = PVRSRVDevicePostPowerStateKM(IMG_TRUE, 0, eNewDevicePowerState);
+ if (eError != PVRSRV_OK)
+ {
+ goto Exit;
+ }
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "PVRSRVSystemPostPowerStateKM: System Power Transition from %d to %d OK",
+ psSysData->eCurrentPowerState, eNewSysPowerState));
+
+ psSysData->eCurrentPowerState = eNewSysPowerState;
+
+Exit:
+
+ PVRSRVPowerUnlock(KERNEL_ID);
+
+
+ if (_IsSystemStatePowered(eNewSysPowerState) &&
+ PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL))
+ {
+
+
+
+ PVRSRVScheduleDeviceCallbacks();
+ }
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerState)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+ eError = PVRSRVSystemPrePowerStateKM(eNewSysPowerState);
+ if(eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+
+ eError = PVRSRVSystemPostPowerStateKM(eNewSysPowerState);
+ if(eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+
+
+ psSysData->eFailedPowerState = PVRSRV_SYS_POWER_STATE_Unspecified;
+
+ return PVRSRV_OK;
+
+ErrorExit:
+
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVSetPowerStateKM: Transition from %d to %d FAILED 0x%x",
+ psSysData->eCurrentPowerState, eNewSysPowerState, eError));
+
+
+ psSysData->eFailedPowerState = eNewSysPowerState;
+
+ return eError;
+}
+
+
+PVRSRV_ERROR PVRSRVRegisterPowerDevice(IMG_UINT32 ui32DeviceIndex,
+ PFN_PRE_POWER pfnPrePower,
+ PFN_POST_POWER pfnPostPower,
+ PFN_PRE_CLOCKSPEED_CHANGE pfnPreClockSpeedChange,
+ PFN_POST_CLOCKSPEED_CHANGE pfnPostClockSpeedChange,
+ IMG_HANDLE hDevCookie,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState,
+ PVRSRV_DEV_POWER_STATE eDefaultPowerState)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+ PVRSRV_POWER_DEV *psPowerDevice;
+
+ if (pfnPrePower == IMG_NULL &&
+ pfnPostPower == IMG_NULL)
+ {
+ return PVRSRVRemovePowerDevice(ui32DeviceIndex);
+ }
+
+ SysAcquireData(&psSysData);
+
+ eError = OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_POWER_DEV),
+ (IMG_VOID **)&psPowerDevice, IMG_NULL,
+ "Power Device");
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterPowerDevice: Failed to alloc PVRSRV_POWER_DEV"));
+ return eError;
+ }
+
+
+ psPowerDevice->pfnPrePower = pfnPrePower;
+ psPowerDevice->pfnPostPower = pfnPostPower;
+ psPowerDevice->pfnPreClockSpeedChange = pfnPreClockSpeedChange;
+ psPowerDevice->pfnPostClockSpeedChange = pfnPostClockSpeedChange;
+ psPowerDevice->hDevCookie = hDevCookie;
+ psPowerDevice->ui32DeviceIndex = ui32DeviceIndex;
+ psPowerDevice->eCurrentPowerState = eCurrentPowerState;
+ psPowerDevice->eDefaultPowerState = eDefaultPowerState;
+
+
+ List_PVRSRV_POWER_DEV_Insert(&(psSysData->psPowerDeviceList), psPowerDevice);
+
+ return (PVRSRV_OK);
+}
+
+
+PVRSRV_ERROR PVRSRVRemovePowerDevice (IMG_UINT32 ui32DeviceIndex)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_POWER_DEV *psPowerDev;
+
+ SysAcquireData(&psSysData);
+
+
+ psPowerDev = (PVRSRV_POWER_DEV*)
+ List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList,
+ &MatchPowerDeviceIndex_AnyVaCb,
+ ui32DeviceIndex);
+
+ if (psPowerDev)
+ {
+ List_PVRSRV_POWER_DEV_Remove(psPowerDev);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_POWER_DEV), psPowerDev, IMG_NULL);
+
+ }
+
+ return (PVRSRV_OK);
+}
+
+
+IMG_EXPORT
+IMG_BOOL PVRSRVIsDevicePowered(IMG_UINT32 ui32DeviceIndex)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_POWER_DEV *psPowerDevice;
+
+ SysAcquireData(&psSysData);
+
+
+ if (OSIsResourceLocked(&psSysData->sPowerStateChangeResource, KERNEL_ID) ||
+ OSIsResourceLocked(&psSysData->sPowerStateChangeResource, ISR_ID))
+ {
+ return IMG_FALSE;
+ }
+
+ psPowerDevice = (PVRSRV_POWER_DEV*)
+ List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList,
+ &MatchPowerDeviceIndex_AnyVaCb,
+ ui32DeviceIndex);
+ return (psPowerDevice && (psPowerDevice->eCurrentPowerState == PVRSRV_DEV_POWER_STATE_ON))
+ ? IMG_TRUE : IMG_FALSE;
+}
+
+
+PVRSRV_ERROR PVRSRVDevicePreClockSpeedChange(IMG_UINT32 ui32DeviceIndex,
+ IMG_BOOL bIdleDevice,
+ IMG_VOID *pvInfo)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ SYS_DATA *psSysData;
+ PVRSRV_POWER_DEV *psPowerDevice;
+
+ PVR_UNREFERENCED_PARAMETER(pvInfo);
+
+ SysAcquireData(&psSysData);
+
+ if (bIdleDevice)
+ {
+
+ eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVDevicePreClockSpeedChange : failed to acquire lock, error:0x%x", eError));
+ return eError;
+ }
+ }
+
+
+ psPowerDevice = (PVRSRV_POWER_DEV*)
+ List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList,
+ &MatchPowerDeviceIndex_AnyVaCb,
+ ui32DeviceIndex);
+
+ if (psPowerDevice && psPowerDevice->pfnPostClockSpeedChange)
+ {
+ eError = psPowerDevice->pfnPreClockSpeedChange(psPowerDevice->hDevCookie,
+ bIdleDevice,
+ psPowerDevice->eCurrentPowerState);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVDevicePreClockSpeedChange : Device %u failed, error:0x%x",
+ ui32DeviceIndex, eError));
+ }
+ }
+
+ if (bIdleDevice && eError != PVRSRV_OK)
+ {
+ PVRSRVPowerUnlock(KERNEL_ID);
+ }
+
+ return eError;
+}
+
+
+IMG_VOID PVRSRVDevicePostClockSpeedChange(IMG_UINT32 ui32DeviceIndex,
+ IMG_BOOL bIdleDevice,
+ IMG_VOID *pvInfo)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+ PVRSRV_POWER_DEV *psPowerDevice;
+
+ PVR_UNREFERENCED_PARAMETER(pvInfo);
+
+ SysAcquireData(&psSysData);
+
+
+ psPowerDevice = (PVRSRV_POWER_DEV*)
+ List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList,
+ &MatchPowerDeviceIndex_AnyVaCb,
+ ui32DeviceIndex);
+
+ if (psPowerDevice && psPowerDevice->pfnPostClockSpeedChange)
+ {
+ eError = psPowerDevice->pfnPostClockSpeedChange(psPowerDevice->hDevCookie,
+ bIdleDevice,
+ psPowerDevice->eCurrentPowerState);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVDevicePostClockSpeedChange : Device %u failed, error:0x%x",
+ ui32DeviceIndex, eError));
+ }
+ }
+
+
+ if (bIdleDevice)
+ {
+
+ PVRSRVPowerUnlock(KERNEL_ID);
+ }
+}
+
diff --git a/drivers/gpu/pvr/power.h b/drivers/gpu/pvr/power.h
new file mode 100644
index 0000000..9e3dcc40
--- /dev/null
+++ b/drivers/gpu/pvr/power.h
@@ -0,0 +1,120 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef POWER_H
+#define POWER_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+
+typedef struct _PVRSRV_POWER_DEV_TAG_
+{
+ PFN_PRE_POWER pfnPrePower;
+ PFN_POST_POWER pfnPostPower;
+ PFN_PRE_CLOCKSPEED_CHANGE pfnPreClockSpeedChange;
+ PFN_POST_CLOCKSPEED_CHANGE pfnPostClockSpeedChange;
+ IMG_HANDLE hDevCookie;
+ IMG_UINT32 ui32DeviceIndex;
+ PVRSRV_DEV_POWER_STATE eDefaultPowerState;
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState;
+ struct _PVRSRV_POWER_DEV_TAG_ *psNext;
+ struct _PVRSRV_POWER_DEV_TAG_ **ppsThis;
+
+} PVRSRV_POWER_DEV;
+
+typedef enum _PVRSRV_INIT_SERVER_STATE_
+{
+ PVRSRV_INIT_SERVER_Unspecified = -1,
+ PVRSRV_INIT_SERVER_RUNNING = 0,
+ PVRSRV_INIT_SERVER_RAN = 1,
+ PVRSRV_INIT_SERVER_SUCCESSFUL = 2,
+ PVRSRV_INIT_SERVER_NUM = 3,
+ PVRSRV_INIT_SERVER_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_INIT_SERVER_STATE, *PPVRSRV_INIT_SERVER_STATE;
+
+IMG_IMPORT
+IMG_BOOL PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_STATE eInitServerState);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_STATE eInitServerState, IMG_BOOL bState);
+
+
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVPowerLock(IMG_UINT32 ui32CallerID,
+ IMG_BOOL bSystemPowerEvent);
+IMG_IMPORT
+IMG_VOID PVRSRVPowerUnlock(IMG_UINT32 ui32CallerID);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(IMG_UINT32 ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ IMG_UINT32 ui32CallerID,
+ IMG_BOOL bRetainMutex);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSystemPrePowerStateKM(PVRSRV_SYS_POWER_STATE eNewPowerState);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSystemPostPowerStateKM(PVRSRV_SYS_POWER_STATE eNewPowerState);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetPowerStateKM (PVRSRV_SYS_POWER_STATE ePVRState);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVRegisterPowerDevice(IMG_UINT32 ui32DeviceIndex,
+ PFN_PRE_POWER pfnPrePower,
+ PFN_POST_POWER pfnPostPower,
+ PFN_PRE_CLOCKSPEED_CHANGE pfnPreClockSpeedChange,
+ PFN_POST_CLOCKSPEED_CHANGE pfnPostClockSpeedChange,
+ IMG_HANDLE hDevCookie,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState,
+ PVRSRV_DEV_POWER_STATE eDefaultPowerState);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVRemovePowerDevice (IMG_UINT32 ui32DeviceIndex);
+
+IMG_IMPORT
+IMG_BOOL PVRSRVIsDevicePowered(IMG_UINT32 ui32DeviceIndex);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVDevicePreClockSpeedChange(IMG_UINT32 ui32DeviceIndex,
+ IMG_BOOL bIdleDevice,
+ IMG_VOID *pvInfo);
+
+IMG_IMPORT
+IMG_VOID PVRSRVDevicePostClockSpeedChange(IMG_UINT32 ui32DeviceIndex,
+ IMG_BOOL bIdleDevice,
+ IMG_VOID *pvInfo);
+
+#if defined (__cplusplus)
+}
+#endif
+#endif
+
diff --git a/drivers/gpu/pvr/private_data.h b/drivers/gpu/pvr/private_data.h
new file mode 100644
index 0000000..b8751d3
--- /dev/null
+++ b/drivers/gpu/pvr/private_data.h
@@ -0,0 +1,69 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __INCLUDED_PRIVATE_DATA_H_
+#define __INCLUDED_PRIVATE_DATA_H_
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+#include <linux/list.h>
+#include <drm/drmP.h>
+#endif
+
+typedef struct
+{
+
+ IMG_UINT32 ui32OpenPID;
+
+
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelMemInfo;
+#else
+ IMG_HANDLE hKernelMemInfo;
+#endif
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+
+ struct list_head sDRMAuthListItem;
+
+ struct drm_file *psDRMFile;
+#endif
+
+#if defined(SUPPORT_MEMINFO_IDS)
+
+ IMG_UINT64 ui64Stamp;
+#endif
+
+
+ IMG_HANDLE hBlockAlloc;
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+ IMG_PVOID pPriv;
+#endif
+}
+PVRSRV_FILE_PRIVATE_DATA;
+
+#endif
+
diff --git a/drivers/gpu/pvr/proc.c b/drivers/gpu/pvr/proc.c
new file mode 100644
index 0000000..1df8aff
--- /dev/null
+++ b/drivers/gpu/pvr/proc.c
@@ -0,0 +1,835 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#endif
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+#include "services_headers.h"
+
+#include "queue.h"
+#include "resman.h"
+#include "pvrmmap.h"
+#include "pvr_debug.h"
+#include "pvrversion.h"
+#include "proc.h"
+#include "perproc.h"
+#include "env_perproc.h"
+#include "linkage.h"
+
+#include "lists.h"
+
+static struct proc_dir_entry * dir;
+
+static const IMG_CHAR PVRProcDirRoot[] = "pvr";
+
+static IMG_INT pvr_proc_open(struct inode *inode,struct file *file);
+static void *pvr_proc_seq_start (struct seq_file *m, loff_t *pos);
+static void pvr_proc_seq_stop (struct seq_file *m, void *v);
+static void *pvr_proc_seq_next (struct seq_file *m, void *v, loff_t *pos);
+static int pvr_proc_seq_show (struct seq_file *m, void *v);
+static ssize_t pvr_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos);
+
+static struct file_operations pvr_proc_operations =
+{
+ .open = pvr_proc_open,
+ .read = seq_read,
+ .write = pvr_proc_write,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static struct seq_operations pvr_proc_seq_operations =
+{
+ .start = pvr_proc_seq_start,
+ .next = pvr_proc_seq_next,
+ .stop = pvr_proc_seq_stop,
+ .show = pvr_proc_seq_show,
+};
+
+static struct proc_dir_entry* g_pProcQueue;
+static struct proc_dir_entry* g_pProcVersion;
+static struct proc_dir_entry* g_pProcSysNodes;
+
+#ifdef DEBUG
+static struct proc_dir_entry* g_pProcDebugLevel;
+#endif
+
+#ifdef PVR_MANUAL_POWER_CONTROL
+static struct proc_dir_entry* g_pProcPowerLevel;
+#endif
+
+
+static void ProcSeqShowVersion(struct seq_file *sfile,void* el);
+
+static void ProcSeqShowSysNodes(struct seq_file *sfile,void* el);
+static void* ProcSeqOff2ElementSysNodes(struct seq_file * sfile, loff_t off);
+
+off_t printAppend(IMG_CHAR * buffer, size_t size, off_t off, const IMG_CHAR * format, ...)
+{
+ IMG_INT n;
+ size_t space = size - (size_t)off;
+ va_list ap;
+
+ va_start (ap, format);
+
+ n = vsnprintf (buffer+off, space, format, ap);
+
+ va_end (ap);
+
+ if (n >= (IMG_INT)space || n < 0)
+ {
+
+ buffer[size - 1] = 0;
+ return (off_t)(size - 1);
+ }
+ else
+ {
+ return (off + (off_t)n);
+ }
+}
+
+
+void* ProcSeq1ElementOff2Element(struct seq_file *sfile, loff_t off)
+{
+ PVR_UNREFERENCED_PARAMETER(sfile);
+
+ if(!off)
+ return (void*)2;
+ return NULL;
+}
+
+
+void* ProcSeq1ElementHeaderOff2Element(struct seq_file *sfile, loff_t off)
+{
+ PVR_UNREFERENCED_PARAMETER(sfile);
+
+ if(!off)
+ {
+ return PVR_PROC_SEQ_START_TOKEN;
+ }
+
+
+ if(off == 1)
+ return (void*)2;
+
+ return NULL;
+}
+
+
+static IMG_INT pvr_proc_open(struct inode *inode,struct file *file)
+{
+ IMG_INT ret = seq_open(file, &pvr_proc_seq_operations);
+
+ struct seq_file *seq = (struct seq_file*)file->private_data;
+ struct proc_dir_entry* pvr_proc_entry = PDE(inode);
+
+
+ seq->private = pvr_proc_entry->data;
+ return ret;
+}
+
+static ssize_t pvr_proc_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ struct inode *inode = file->f_path.dentry->d_inode;
+ struct proc_dir_entry * dp;
+
+ PVR_UNREFERENCED_PARAMETER(ppos);
+ dp = PDE(inode);
+
+ if (!dp->write_proc)
+ return -EIO;
+
+ return dp->write_proc(file, buffer, count, dp->data);
+}
+
+
+static void *pvr_proc_seq_start (struct seq_file *proc_seq_file, loff_t *pos)
+{
+ PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
+ if(handlers->startstop != NULL)
+ handlers->startstop(proc_seq_file, IMG_TRUE);
+ return handlers->off2element(proc_seq_file, *pos);
+}
+
+static void pvr_proc_seq_stop (struct seq_file *proc_seq_file, void *v)
+{
+ PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
+ PVR_UNREFERENCED_PARAMETER(v);
+
+ if(handlers->startstop != NULL)
+ handlers->startstop(proc_seq_file, IMG_FALSE);
+}
+
+static void *pvr_proc_seq_next (struct seq_file *proc_seq_file, void *v, loff_t *pos)
+{
+ PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
+ (*pos)++;
+ if( handlers->next != NULL)
+ return handlers->next( proc_seq_file, v, *pos );
+ return handlers->off2element(proc_seq_file, *pos);
+}
+
+static int pvr_proc_seq_show (struct seq_file *proc_seq_file, void *v)
+{
+ PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
+ handlers->show( proc_seq_file,v );
+ return 0;
+}
+
+
+
+static struct proc_dir_entry* CreateProcEntryInDirSeq(
+ struct proc_dir_entry *pdir,
+ const IMG_CHAR * name,
+ IMG_VOID* data,
+ pvr_next_proc_seq_t next_handler,
+ pvr_show_proc_seq_t show_handler,
+ pvr_off2element_proc_seq_t off2element_handler,
+ pvr_startstop_proc_seq_t startstop_handler,
+ write_proc_t whandler
+ )
+{
+
+ struct proc_dir_entry * file;
+ mode_t mode;
+
+ if (!dir)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcEntryInDirSeq: cannot make proc entry /proc/%s/%s: no parent", PVRProcDirRoot, name));
+ return NULL;
+ }
+
+ mode = S_IFREG;
+
+ if (show_handler)
+ {
+ mode |= S_IRUGO;
+ }
+
+ if (whandler)
+ {
+ mode |= S_IWUSR;
+ }
+
+ file=create_proc_entry(name, mode, pdir);
+
+ if (file)
+ {
+ PVR_PROC_SEQ_HANDLERS *seq_handlers;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
+ file->owner = THIS_MODULE;
+#endif
+
+ file->proc_fops = &pvr_proc_operations;
+ file->write_proc = whandler;
+
+
+ file->data = kmalloc(sizeof(PVR_PROC_SEQ_HANDLERS), GFP_KERNEL);
+ if(file->data)
+ {
+ seq_handlers = (PVR_PROC_SEQ_HANDLERS*)file->data;
+ seq_handlers->next = next_handler;
+ seq_handlers->show = show_handler;
+ seq_handlers->off2element = off2element_handler;
+ seq_handlers->startstop = startstop_handler;
+ seq_handlers->data = data;
+
+ return file;
+ }
+ }
+
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcEntryInDirSeq: cannot make proc entry /proc/%s/%s: no memory", PVRProcDirRoot, name));
+ return NULL;
+}
+
+
+struct proc_dir_entry* CreateProcReadEntrySeq (
+ const IMG_CHAR * name,
+ IMG_VOID* data,
+ pvr_next_proc_seq_t next_handler,
+ pvr_show_proc_seq_t show_handler,
+ pvr_off2element_proc_seq_t off2element_handler,
+ pvr_startstop_proc_seq_t startstop_handler
+ )
+{
+ return CreateProcEntrySeq(name,
+ data,
+ next_handler,
+ show_handler,
+ off2element_handler,
+ startstop_handler,
+ NULL);
+}
+
+struct proc_dir_entry* CreateProcEntrySeq (
+ const IMG_CHAR * name,
+ IMG_VOID* data,
+ pvr_next_proc_seq_t next_handler,
+ pvr_show_proc_seq_t show_handler,
+ pvr_off2element_proc_seq_t off2element_handler,
+ pvr_startstop_proc_seq_t startstop_handler,
+ write_proc_t whandler
+ )
+{
+ return CreateProcEntryInDirSeq(
+ dir,
+ name,
+ data,
+ next_handler,
+ show_handler,
+ off2element_handler,
+ startstop_handler,
+ whandler
+ );
+}
+
+
+
+struct proc_dir_entry* CreatePerProcessProcEntrySeq (
+ const IMG_CHAR * name,
+ IMG_VOID* data,
+ pvr_next_proc_seq_t next_handler,
+ pvr_show_proc_seq_t show_handler,
+ pvr_off2element_proc_seq_t off2element_handler,
+ pvr_startstop_proc_seq_t startstop_handler,
+ write_proc_t whandler
+ )
+{
+ PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
+ IMG_UINT32 ui32PID;
+
+ if (!dir)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntrySeq: /proc/%s doesn't exist", PVRProcDirRoot));
+ return NULL;
+ }
+
+ ui32PID = OSGetCurrentProcessIDKM();
+
+ psPerProc = PVRSRVPerProcessPrivateData(ui32PID);
+ if (!psPerProc)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntrySeq: no per process data"));
+
+ return NULL;
+ }
+
+ if (!psPerProc->psProcDir)
+ {
+ IMG_CHAR dirname[16];
+ IMG_INT ret;
+
+ ret = snprintf(dirname, sizeof(dirname), "%u", ui32PID);
+
+ if (ret <=0 || ret >= (IMG_INT)sizeof(dirname))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: couldn't generate per process proc directory name \"%u\"", ui32PID));
+ return NULL;
+ }
+ else
+ {
+ psPerProc->psProcDir = proc_mkdir(dirname, dir);
+ if (!psPerProc->psProcDir)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: couldn't create per process proc directory /proc/%s/%u",
+ PVRProcDirRoot, ui32PID));
+ return NULL;
+ }
+ }
+ }
+
+ return CreateProcEntryInDirSeq(psPerProc->psProcDir, name, data, next_handler,
+ show_handler,off2element_handler,startstop_handler,whandler);
+}
+
+
+IMG_VOID RemoveProcEntrySeq( struct proc_dir_entry* proc_entry )
+{
+ if (dir)
+ {
+ void* data = proc_entry->data ;
+ PVR_DPF((PVR_DBG_MESSAGE, "Removing /proc/%s/%s", PVRProcDirRoot, proc_entry->name));
+
+ remove_proc_entry(proc_entry->name, dir);
+ if( data)
+ kfree( data );
+
+ }
+}
+
+IMG_VOID RemovePerProcessProcEntrySeq(struct proc_dir_entry* proc_entry)
+{
+ PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
+
+ psPerProc = LinuxTerminatingProcessPrivateData();
+ if (!psPerProc)
+ {
+ psPerProc = PVRSRVFindPerProcessPrivateData();
+ if (!psPerProc)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: can't "
+ "remove %s, no per process data", proc_entry->name));
+ return;
+ }
+ }
+
+ if (psPerProc->psProcDir)
+ {
+ void* data = proc_entry->data ;
+ PVR_DPF((PVR_DBG_MESSAGE, "Removing proc entry %s from %s", proc_entry->name, psPerProc->psProcDir->name));
+
+ remove_proc_entry(proc_entry->name, psPerProc->psProcDir);
+ if(data)
+ kfree( data );
+ }
+}
+
+static IMG_INT pvr_read_proc(IMG_CHAR *page, IMG_CHAR **start, off_t off,
+ IMG_INT count, IMG_INT *eof, IMG_VOID *data)
+{
+
+ pvr_read_proc_t *pprn = (pvr_read_proc_t *)data;
+
+ off_t len = pprn (page, (size_t)count, off);
+
+ if (len == END_OF_FILE)
+ {
+ len = 0;
+ *eof = 1;
+ }
+ else if (!len)
+ {
+ *start = (IMG_CHAR *) 0;
+ }
+ else
+ {
+ *start = (IMG_CHAR *) 1;
+ }
+
+ return len;
+}
+
+
+static IMG_INT CreateProcEntryInDir(struct proc_dir_entry *pdir, const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data)
+{
+ struct proc_dir_entry * file;
+ mode_t mode;
+
+ if (!pdir)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcEntryInDir: parent directory doesn't exist"));
+
+ return -ENOMEM;
+ }
+
+ mode = S_IFREG;
+
+ if (rhandler)
+ {
+ mode |= S_IRUGO;
+ }
+
+ if (whandler)
+ {
+ mode |= S_IWUSR;
+ }
+
+ file = create_proc_entry(name, mode, pdir);
+
+ if (file)
+ {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
+ file->owner = THIS_MODULE;
+#endif
+ file->read_proc = rhandler;
+ file->write_proc = whandler;
+ file->data = data;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "Created proc entry %s in %s", name, pdir->name));
+
+ return 0;
+ }
+
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcEntry: cannot create proc entry %s in %s", name, pdir->name));
+
+ return -ENOMEM;
+}
+
+
+IMG_INT CreateProcEntry(const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data)
+{
+ return CreateProcEntryInDir(dir, name, rhandler, whandler, data);
+}
+
+
+IMG_INT CreatePerProcessProcEntry(const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data)
+{
+ PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
+ IMG_UINT32 ui32PID;
+
+ if (!dir)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: /proc/%s doesn't exist", PVRProcDirRoot));
+
+ return -ENOMEM;
+ }
+
+ ui32PID = OSGetCurrentProcessIDKM();
+
+ psPerProc = PVRSRVPerProcessPrivateData(ui32PID);
+ if (!psPerProc)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: no per process data"));
+
+ return -ENOMEM;
+ }
+
+ if (!psPerProc->psProcDir)
+ {
+ IMG_CHAR dirname[16];
+ IMG_INT ret;
+
+ ret = snprintf(dirname, sizeof(dirname), "%u", ui32PID);
+
+ if (ret <=0 || ret >= (IMG_INT)sizeof(dirname))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: couldn't generate per process proc directory name \"%u\"", ui32PID));
+
+ return -ENOMEM;
+ }
+ else
+ {
+ psPerProc->psProcDir = proc_mkdir(dirname, dir);
+ if (!psPerProc->psProcDir)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: couldn't create per process proc directory /proc/%s/%u", PVRProcDirRoot, ui32PID));
+
+ return -ENOMEM;
+ }
+ }
+ }
+
+ return CreateProcEntryInDir(psPerProc->psProcDir, name, rhandler, whandler, data);
+}
+
+
+IMG_INT CreateProcReadEntry(const IMG_CHAR * name, pvr_read_proc_t handler)
+{
+ struct proc_dir_entry * file;
+
+ if (!dir)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcReadEntry: cannot make proc entry /proc/%s/%s: no parent", PVRProcDirRoot, name));
+
+ return -ENOMEM;
+ }
+
+
+ file = create_proc_read_entry (name, S_IFREG | S_IRUGO, dir, pvr_read_proc, (IMG_VOID *)handler);
+
+ if (file)
+ {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
+ file->owner = THIS_MODULE;
+#endif
+ return 0;
+ }
+
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcReadEntry: cannot make proc entry /proc/%s/%s: no memory", PVRProcDirRoot, name));
+
+ return -ENOMEM;
+}
+
+
+IMG_INT CreateProcEntries(IMG_VOID)
+{
+ dir = proc_mkdir (PVRProcDirRoot, NULL);
+
+ if (!dir)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: cannot make /proc/%s directory", PVRProcDirRoot));
+
+ return -ENOMEM;
+ }
+
+ g_pProcQueue = CreateProcReadEntrySeq("queue", NULL, NULL, ProcSeqShowQueue, ProcSeqOff2ElementQueue, NULL);
+ g_pProcVersion = CreateProcReadEntrySeq("version", NULL, NULL, ProcSeqShowVersion, ProcSeq1ElementHeaderOff2Element, NULL);
+ g_pProcSysNodes = CreateProcReadEntrySeq("nodes", NULL, NULL, ProcSeqShowSysNodes, ProcSeqOff2ElementSysNodes, NULL);
+
+ if(!g_pProcQueue || !g_pProcVersion || !g_pProcSysNodes)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: couldn't make /proc/%s files", PVRProcDirRoot));
+
+ return -ENOMEM;
+ }
+
+
+#ifdef DEBUG
+
+ g_pProcDebugLevel = CreateProcEntrySeq("debug_level", NULL, NULL,
+ ProcSeqShowDebugLevel,
+ ProcSeq1ElementOff2Element, NULL,
+ (IMG_VOID*)PVRDebugProcSetLevel);
+ if(!g_pProcDebugLevel)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: couldn't make /proc/%s/debug_level", PVRProcDirRoot));
+
+ return -ENOMEM;
+ }
+
+#ifdef PVR_MANUAL_POWER_CONTROL
+ g_pProcPowerLevel = CreateProcEntrySeq("power_control", NULL, NULL,
+ ProcSeqShowPowerLevel,
+ ProcSeq1ElementOff2Element, NULL,
+ PVRProcSetPowerLevel);
+ if(!g_pProcPowerLevel)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: couldn't make /proc/%s/power_control", PVRProcDirRoot));
+
+ return -ENOMEM;
+ }
+#endif
+#endif
+
+ return 0;
+}
+
+
+IMG_VOID RemoveProcEntry(const IMG_CHAR * name)
+{
+ if (dir)
+ {
+ remove_proc_entry(name, dir);
+ PVR_DPF((PVR_DBG_MESSAGE, "Removing /proc/%s/%s", PVRProcDirRoot, name));
+ }
+}
+
+
+IMG_VOID RemovePerProcessProcEntry(const IMG_CHAR *name)
+{
+ PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
+
+ psPerProc = LinuxTerminatingProcessPrivateData();
+ if (!psPerProc)
+ {
+ psPerProc = PVRSRVFindPerProcessPrivateData();
+ if (!psPerProc)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: can't "
+ "remove %s, no per process data", name));
+ return;
+ }
+ }
+
+ if (psPerProc->psProcDir)
+ {
+ remove_proc_entry(name, psPerProc->psProcDir);
+
+ PVR_DPF((PVR_DBG_MESSAGE, "Removing proc entry %s from %s", name, psPerProc->psProcDir->name));
+ }
+}
+
+
+IMG_VOID RemovePerProcessProcDir(PVRSRV_ENV_PER_PROCESS_DATA *psPerProc)
+{
+ if (psPerProc->psProcDir)
+ {
+ while (psPerProc->psProcDir->subdir)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "Belatedly removing /proc/%s/%s/%s", PVRProcDirRoot, psPerProc->psProcDir->name, psPerProc->psProcDir->subdir->name));
+
+ RemoveProcEntry(psPerProc->psProcDir->subdir->name);
+ }
+ RemoveProcEntry(psPerProc->psProcDir->name);
+ }
+}
+
+IMG_VOID RemoveProcEntries(IMG_VOID)
+{
+#ifdef DEBUG
+ RemoveProcEntrySeq( g_pProcDebugLevel );
+#ifdef PVR_MANUAL_POWER_CONTROL
+ RemoveProcEntrySeq( g_pProcPowerLevel );
+#endif
+#endif
+
+ RemoveProcEntrySeq(g_pProcQueue);
+ RemoveProcEntrySeq(g_pProcVersion);
+ RemoveProcEntrySeq(g_pProcSysNodes);
+
+ while (dir->subdir)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "Belatedly removing /proc/%s/%s", PVRProcDirRoot, dir->subdir->name));
+
+ RemoveProcEntry(dir->subdir->name);
+ }
+
+ remove_proc_entry(PVRProcDirRoot, NULL);
+}
+
+static void ProcSeqShowVersion(struct seq_file *sfile,void* el)
+{
+ SYS_DATA *psSysData;
+ IMG_CHAR *pszSystemVersionString = "None";
+
+ if(el == PVR_PROC_SEQ_START_TOKEN)
+ {
+ seq_printf(sfile,
+ "Version %s (%s) %s\n",
+ PVRVERSION_STRING,
+ PVR_BUILD_TYPE, PVR_BUILD_DIR);
+ return;
+ }
+
+ psSysData = SysAcquireDataNoCheck();
+ if(psSysData != IMG_NULL && psSysData->pszVersionString != IMG_NULL)
+ {
+ pszSystemVersionString = psSysData->pszVersionString;
+ }
+
+ seq_printf( sfile, "System Version String: %s\n", pszSystemVersionString);
+}
+
+static const IMG_CHAR *deviceTypeToString(PVRSRV_DEVICE_TYPE deviceType)
+{
+ switch (deviceType)
+ {
+ default:
+ {
+ static IMG_CHAR text[10];
+
+ sprintf(text, "?%x", (IMG_UINT)deviceType);
+
+ return text;
+ }
+ }
+}
+
+
+static const IMG_CHAR *deviceClassToString(PVRSRV_DEVICE_CLASS deviceClass)
+{
+ switch (deviceClass)
+ {
+ case PVRSRV_DEVICE_CLASS_3D:
+ {
+ return "3D";
+ }
+ case PVRSRV_DEVICE_CLASS_DISPLAY:
+ {
+ return "display";
+ }
+ case PVRSRV_DEVICE_CLASS_BUFFER:
+ {
+ return "buffer";
+ }
+ default:
+ {
+ static IMG_CHAR text[10];
+
+ sprintf(text, "?%x", (IMG_UINT)deviceClass);
+ return text;
+ }
+ }
+}
+
+static IMG_VOID* DecOffPsDev_AnyVaCb(PVRSRV_DEVICE_NODE *psNode, va_list va)
+{
+ off_t *pOff = va_arg(va, off_t*);
+ if (--(*pOff))
+ {
+ return IMG_NULL;
+ }
+ else
+ {
+ return psNode;
+ }
+}
+
+static void ProcSeqShowSysNodes(struct seq_file *sfile,void* el)
+{
+ PVRSRV_DEVICE_NODE *psDevNode;
+
+ if(el == PVR_PROC_SEQ_START_TOKEN)
+ {
+ seq_printf( sfile,
+ "Registered nodes\n"
+ "Addr Type Class Index Ref pvDev Size Res\n");
+ return;
+ }
+
+ psDevNode = (PVRSRV_DEVICE_NODE*)el;
+
+ seq_printf( sfile,
+ "%p %-8s %-8s %4d %2u %p %3u %p\n",
+ psDevNode,
+ deviceTypeToString(psDevNode->sDevId.eDeviceType),
+ deviceClassToString(psDevNode->sDevId.eDeviceClass),
+ psDevNode->sDevId.eDeviceClass,
+ psDevNode->ui32RefCount,
+ psDevNode->pvDevice,
+ psDevNode->ui32pvDeviceSize,
+ psDevNode->hResManContext);
+}
+
+static void* ProcSeqOff2ElementSysNodes(struct seq_file * sfile, loff_t off)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_DEVICE_NODE*psDevNode = IMG_NULL;
+
+ PVR_UNREFERENCED_PARAMETER(sfile);
+
+ if(!off)
+ {
+ return PVR_PROC_SEQ_START_TOKEN;
+ }
+
+ psSysData = SysAcquireDataNoCheck();
+ if (psSysData != IMG_NULL)
+ {
+
+ psDevNode = (PVRSRV_DEVICE_NODE*)
+ List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ DecOffPsDev_AnyVaCb,
+ &off);
+ }
+
+
+ return (void*)psDevNode;
+}
+
diff --git a/drivers/gpu/pvr/proc.h b/drivers/gpu/pvr/proc.h
new file mode 100644
index 0000000..2066d71
--- /dev/null
+++ b/drivers/gpu/pvr/proc.h
@@ -0,0 +1,108 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __SERVICES_PROC_H__
+#define __SERVICES_PROC_H__
+
+#include <asm/system.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+#define END_OF_FILE (off_t) -1
+
+typedef off_t (pvr_read_proc_t)(IMG_CHAR *, size_t, off_t);
+
+
+#define PVR_PROC_SEQ_START_TOKEN (void*)1
+typedef void* (pvr_next_proc_seq_t)(struct seq_file *,void*,loff_t);
+typedef void* (pvr_off2element_proc_seq_t)(struct seq_file *, loff_t);
+typedef void (pvr_show_proc_seq_t)(struct seq_file *,void*);
+typedef void (pvr_startstop_proc_seq_t)(struct seq_file *, IMG_BOOL start);
+
+typedef struct _PVR_PROC_SEQ_HANDLERS_ {
+ pvr_next_proc_seq_t *next;
+ pvr_show_proc_seq_t *show;
+ pvr_off2element_proc_seq_t *off2element;
+ pvr_startstop_proc_seq_t *startstop;
+ IMG_VOID *data;
+} PVR_PROC_SEQ_HANDLERS;
+
+
+void* ProcSeq1ElementOff2Element(struct seq_file *sfile, loff_t off);
+
+void* ProcSeq1ElementHeaderOff2Element(struct seq_file *sfile, loff_t off);
+
+off_t printAppend(IMG_CHAR * buffer, size_t size, off_t off, const IMG_CHAR * format, ...)
+ __attribute__((format(printf, 4, 5)));
+
+IMG_INT CreateProcEntries(IMG_VOID);
+
+IMG_INT CreateProcReadEntry (const IMG_CHAR * name, pvr_read_proc_t handler);
+
+IMG_INT CreateProcEntry(const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data);
+
+IMG_INT CreatePerProcessProcEntry(const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data);
+
+IMG_VOID RemoveProcEntry(const IMG_CHAR * name);
+
+IMG_VOID RemovePerProcessProcEntry(const IMG_CHAR * name);
+
+IMG_VOID RemoveProcEntries(IMG_VOID);
+
+struct proc_dir_entry* CreateProcReadEntrySeq (
+ const IMG_CHAR* name,
+ IMG_VOID* data,
+ pvr_next_proc_seq_t next_handler,
+ pvr_show_proc_seq_t show_handler,
+ pvr_off2element_proc_seq_t off2element_handler,
+ pvr_startstop_proc_seq_t startstop_handler
+ );
+
+struct proc_dir_entry* CreateProcEntrySeq (
+ const IMG_CHAR* name,
+ IMG_VOID* data,
+ pvr_next_proc_seq_t next_handler,
+ pvr_show_proc_seq_t show_handler,
+ pvr_off2element_proc_seq_t off2element_handler,
+ pvr_startstop_proc_seq_t startstop_handler,
+ write_proc_t whandler
+ );
+
+struct proc_dir_entry* CreatePerProcessProcEntrySeq (
+ const IMG_CHAR* name,
+ IMG_VOID* data,
+ pvr_next_proc_seq_t next_handler,
+ pvr_show_proc_seq_t show_handler,
+ pvr_off2element_proc_seq_t off2element_handler,
+ pvr_startstop_proc_seq_t startstop_handler,
+ write_proc_t whandler
+ );
+
+
+IMG_VOID RemoveProcEntrySeq(struct proc_dir_entry* proc_entry);
+IMG_VOID RemovePerProcessProcEntrySeq(struct proc_dir_entry* proc_entry);
+
+#endif
diff --git a/drivers/gpu/pvr/pvr_bridge.h b/drivers/gpu/pvr/pvr_bridge.h
new file mode 100644
index 0000000..443ad1e
--- /dev/null
+++ b/drivers/gpu/pvr/pvr_bridge.h
@@ -0,0 +1,1786 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __PVR_BRIDGE_H__
+#define __PVR_BRIDGE_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "servicesint.h"
+
+#ifdef __linux__
+
+ #include <linux/ioctl.h>
+
+ #define PVRSRV_IOC_GID 'g'
+ #define PVRSRV_IO(INDEX) _IO(PVRSRV_IOC_GID, INDEX, PVRSRV_BRIDGE_PACKAGE)
+ #define PVRSRV_IOW(INDEX) _IOW(PVRSRV_IOC_GID, INDEX, PVRSRV_BRIDGE_PACKAGE)
+ #define PVRSRV_IOR(INDEX) _IOR(PVRSRV_IOC_GID, INDEX, PVRSRV_BRIDGE_PACKAGE)
+ #define PVRSRV_IOWR(INDEX) _IOWR(PVRSRV_IOC_GID, INDEX, PVRSRV_BRIDGE_PACKAGE)
+
+#else
+
+ #error Unknown platform: Cannot define ioctls
+
+ #define PVRSRV_IO(INDEX) (PVRSRV_IOC_GID + (INDEX))
+ #define PVRSRV_IOW(INDEX) (PVRSRV_IOC_GID + (INDEX))
+ #define PVRSRV_IOR(INDEX) (PVRSRV_IOC_GID + (INDEX))
+ #define PVRSRV_IOWR(INDEX) (PVRSRV_IOC_GID + (INDEX))
+
+ #define PVRSRV_BRIDGE_BASE PVRSRV_IOC_GID
+#endif
+
+
+#define PVRSRV_BRIDGE_CORE_CMD_FIRST 0UL
+#define PVRSRV_BRIDGE_ENUM_DEVICES PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_ACQUIRE_DEVICEINFO PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_RELEASE_DEVICEINFO PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_CREATE_DEVMEMCONTEXT PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_DESTROY_DEVMEMCONTEXT PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_GET_DEVMEM_HEAPINFO PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+5)
+#define PVRSRV_BRIDGE_ALLOC_DEVICEMEM PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+6)
+#define PVRSRV_BRIDGE_FREE_DEVICEMEM PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+7)
+#define PVRSRV_BRIDGE_GETFREE_DEVICEMEM PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+8)
+#define PVRSRV_BRIDGE_CREATE_COMMANDQUEUE PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+9)
+#define PVRSRV_BRIDGE_DESTROY_COMMANDQUEUE PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+10)
+#define PVRSRV_BRIDGE_MHANDLE_TO_MMAP_DATA PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+11)
+#define PVRSRV_BRIDGE_CONNECT_SERVICES PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+12)
+#define PVRSRV_BRIDGE_DISCONNECT_SERVICES PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+13)
+#define PVRSRV_BRIDGE_WRAP_DEVICE_MEM PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+14)
+#define PVRSRV_BRIDGE_GET_DEVICEMEMINFO PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+15)
+#define PVRSRV_BRIDGE_RESERVE_DEV_VIRTMEM PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+16)
+#define PVRSRV_BRIDGE_FREE_DEV_VIRTMEM PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+17)
+#define PVRSRV_BRIDGE_MAP_EXT_MEMORY PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+18)
+#define PVRSRV_BRIDGE_UNMAP_EXT_MEMORY PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+19)
+#define PVRSRV_BRIDGE_MAP_DEV_MEMORY PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+20)
+#define PVRSRV_BRIDGE_UNMAP_DEV_MEMORY PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+21)
+#define PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+22)
+#define PVRSRV_BRIDGE_UNMAP_DEVICECLASS_MEMORY PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+23)
+#define PVRSRV_BRIDGE_MAP_MEM_INFO_TO_USER PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+24)
+#define PVRSRV_BRIDGE_UNMAP_MEM_INFO_FROM_USER PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+25)
+#define PVRSRV_BRIDGE_EXPORT_DEVICEMEM PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+26)
+#define PVRSRV_BRIDGE_RELEASE_MMAP_DATA PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+27)
+#define PVRSRV_BRIDGE_CHG_DEV_MEM_ATTRIBS PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+28)
+#define PVRSRV_BRIDGE_MAP_DEV_MEMORY_2 PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+29)
+#define PVRSRV_BRIDGE_EXPORT_DEVICEMEM_2 PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+30)
+#define PVRSRV_BRIDGE_CORE_CMD_LAST (PVRSRV_BRIDGE_CORE_CMD_FIRST+30)
+
+#define PVRSRV_BRIDGE_SIM_CMD_FIRST (PVRSRV_BRIDGE_CORE_CMD_LAST+1)
+#define PVRSRV_BRIDGE_PROCESS_SIMISR_EVENT PVRSRV_IOWR(PVRSRV_BRIDGE_SIM_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_REGISTER_SIM_PROCESS PVRSRV_IOWR(PVRSRV_BRIDGE_SIM_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_UNREGISTER_SIM_PROCESS PVRSRV_IOWR(PVRSRV_BRIDGE_SIM_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_SIM_CMD_LAST (PVRSRV_BRIDGE_SIM_CMD_FIRST+2)
+
+#define PVRSRV_BRIDGE_MAPPING_CMD_FIRST (PVRSRV_BRIDGE_SIM_CMD_LAST+1)
+#define PVRSRV_BRIDGE_MAPPHYSTOUSERSPACE PVRSRV_IOWR(PVRSRV_BRIDGE_MAPPING_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_UNMAPPHYSTOUSERSPACE PVRSRV_IOWR(PVRSRV_BRIDGE_MAPPING_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_GETPHYSTOUSERSPACEMAP PVRSRV_IOWR(PVRSRV_BRIDGE_MAPPING_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_MAPPING_CMD_LAST (PVRSRV_BRIDGE_MAPPING_CMD_FIRST+2)
+
+#define PVRSRV_BRIDGE_STATS_CMD_FIRST (PVRSRV_BRIDGE_MAPPING_CMD_LAST+1)
+#define PVRSRV_BRIDGE_GET_FB_STATS PVRSRV_IOWR(PVRSRV_BRIDGE_STATS_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_STATS_CMD_LAST (PVRSRV_BRIDGE_STATS_CMD_FIRST+0)
+
+#define PVRSRV_BRIDGE_MISC_CMD_FIRST (PVRSRV_BRIDGE_STATS_CMD_LAST+1)
+#define PVRSRV_BRIDGE_GET_MISC_INFO PVRSRV_IOWR(PVRSRV_BRIDGE_MISC_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_RELEASE_MISC_INFO PVRSRV_IOWR(PVRSRV_BRIDGE_MISC_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_MISC_CMD_LAST (PVRSRV_BRIDGE_MISC_CMD_FIRST+1)
+
+#if defined (SUPPORT_OVERLAY_ROTATE_BLIT)
+#define PVRSRV_BRIDGE_OVERLAY_CMD_FIRST (PVRSRV_BRIDGE_MISC_CMD_LAST+1)
+#define PVRSRV_BRIDGE_INIT_3D_OVL_BLT_RES PVRSRV_IOWR(PVRSRV_BRIDGE_OVERLAY_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_DEINIT_3D_OVL_BLT_RES PVRSRV_IOWR(PVRSRV_BRIDGE_OVERLAY_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_OVERLAY_CMD_LAST (PVRSRV_BRIDGE_OVERLAY_CMD_FIRST+1)
+#else
+#define PVRSRV_BRIDGE_OVERLAY_CMD_LAST PVRSRV_BRIDGE_MISC_CMD_LAST
+#endif
+
+#if defined(PDUMP)
+#define PVRSRV_BRIDGE_PDUMP_CMD_FIRST (PVRSRV_BRIDGE_OVERLAY_CMD_LAST+1)
+#define PVRSRV_BRIDGE_PDUMP_INIT PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_PDUMP_MEMPOL PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_PDUMP_DUMPMEM PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_PDUMP_REG PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_PDUMP_REGPOL PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_PDUMP_COMMENT PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+5)
+#define PVRSRV_BRIDGE_PDUMP_SETFRAME PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+6)
+#define PVRSRV_BRIDGE_PDUMP_ISCAPTURING PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+7)
+#define PVRSRV_BRIDGE_PDUMP_DUMPBITMAP PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+8)
+#define PVRSRV_BRIDGE_PDUMP_DUMPREADREG PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+9)
+#define PVRSRV_BRIDGE_PDUMP_SYNCPOL PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+10)
+#define PVRSRV_BRIDGE_PDUMP_DUMPSYNC PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+11)
+#define PVRSRV_BRIDGE_PDUMP_MEMPAGES PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+12)
+#define PVRSRV_BRIDGE_PDUMP_DRIVERINFO PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+13)
+#define PVRSRV_BRIDGE_PDUMP_DUMPPDDEVPADDR PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+15)
+#define PVRSRV_BRIDGE_PDUMP_CYCLE_COUNT_REG_READ PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+16)
+#define PVRSRV_BRIDGE_PDUMP_STARTINITPHASE PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+17)
+#define PVRSRV_BRIDGE_PDUMP_STOPINITPHASE PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+18)
+#define PVRSRV_BRIDGE_PDUMP_CMD_LAST (PVRSRV_BRIDGE_PDUMP_CMD_FIRST+18)
+#else
+#define PVRSRV_BRIDGE_PDUMP_CMD_LAST PVRSRV_BRIDGE_OVERLAY_CMD_LAST
+#endif
+
+#define PVRSRV_BRIDGE_OEM_CMD_FIRST (PVRSRV_BRIDGE_PDUMP_CMD_LAST+1)
+#define PVRSRV_BRIDGE_GET_OEMJTABLE PVRSRV_IOWR(PVRSRV_BRIDGE_OEM_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_OEM_CMD_LAST (PVRSRV_BRIDGE_OEM_CMD_FIRST+0)
+
+#define PVRSRV_BRIDGE_DEVCLASS_CMD_FIRST (PVRSRV_BRIDGE_OEM_CMD_LAST+1)
+#define PVRSRV_BRIDGE_ENUM_CLASS PVRSRV_IOWR(PVRSRV_BRIDGE_DEVCLASS_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_DEVCLASS_CMD_LAST (PVRSRV_BRIDGE_DEVCLASS_CMD_FIRST+0)
+
+#define PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST (PVRSRV_BRIDGE_DEVCLASS_CMD_LAST+1)
+#define PVRSRV_BRIDGE_OPEN_DISPCLASS_DEVICE PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_CLOSE_DISPCLASS_DEVICE PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_ENUM_DISPCLASS_FORMATS PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_ENUM_DISPCLASS_DIMS PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_GET_DISPCLASS_SYSBUFFER PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_GET_DISPCLASS_INFO PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+5)
+#define PVRSRV_BRIDGE_CREATE_DISPCLASS_SWAPCHAIN PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+6)
+#define PVRSRV_BRIDGE_DESTROY_DISPCLASS_SWAPCHAIN PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+7)
+#define PVRSRV_BRIDGE_SET_DISPCLASS_DSTRECT PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+8)
+#define PVRSRV_BRIDGE_SET_DISPCLASS_SRCRECT PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+9)
+#define PVRSRV_BRIDGE_SET_DISPCLASS_DSTCOLOURKEY PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+10)
+#define PVRSRV_BRIDGE_SET_DISPCLASS_SRCCOLOURKEY PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+11)
+#define PVRSRV_BRIDGE_GET_DISPCLASS_BUFFERS PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+12)
+#define PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_BUFFER PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+13)
+#define PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_BUFFER2 PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+14)
+#define PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_SYSTEM PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+15)
+#define PVRSRV_BRIDGE_DISPCLASS_CMD_LAST (PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+15)
+
+#define PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST (PVRSRV_BRIDGE_DISPCLASS_CMD_LAST+1)
+#define PVRSRV_BRIDGE_OPEN_BUFFERCLASS_DEVICE PVRSRV_IOWR(PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_CLOSE_BUFFERCLASS_DEVICE PVRSRV_IOWR(PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_GET_BUFFERCLASS_INFO PVRSRV_IOWR(PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_GET_BUFFERCLASS_BUFFER PVRSRV_IOWR(PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_BUFCLASS_CMD_LAST (PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+3)
+
+#define PVRSRV_BRIDGE_WRAP_CMD_FIRST (PVRSRV_BRIDGE_BUFCLASS_CMD_LAST+1)
+#define PVRSRV_BRIDGE_WRAP_EXT_MEMORY PVRSRV_IOWR(PVRSRV_BRIDGE_WRAP_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_UNWRAP_EXT_MEMORY PVRSRV_IOWR(PVRSRV_BRIDGE_WRAP_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_WRAP_CMD_LAST (PVRSRV_BRIDGE_WRAP_CMD_FIRST+1)
+
+#define PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST (PVRSRV_BRIDGE_WRAP_CMD_LAST+1)
+#define PVRSRV_BRIDGE_ALLOC_SHARED_SYS_MEM PVRSRV_IOWR(PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_FREE_SHARED_SYS_MEM PVRSRV_IOWR(PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_MAP_MEMINFO_MEM PVRSRV_IOWR(PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_UNMAP_MEMINFO_MEM PVRSRV_IOWR(PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_SHAREDMEM_CMD_LAST (PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+3)
+
+#define PVRSRV_BRIDGE_INITSRV_CMD_FIRST (PVRSRV_BRIDGE_SHAREDMEM_CMD_LAST+1)
+#define PVRSRV_BRIDGE_INITSRV_CONNECT PVRSRV_IOWR(PVRSRV_BRIDGE_INITSRV_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_INITSRV_DISCONNECT PVRSRV_IOWR(PVRSRV_BRIDGE_INITSRV_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_INITSRV_CMD_LAST (PVRSRV_BRIDGE_INITSRV_CMD_FIRST+1)
+
+#define PVRSRV_BRIDGE_EVENT_OBJECT_CMD_FIRST (PVRSRV_BRIDGE_INITSRV_CMD_LAST+1)
+#define PVRSRV_BRIDGE_EVENT_OBJECT_WAIT PVRSRV_IOWR(PVRSRV_BRIDGE_EVENT_OBJECT_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_EVENT_OBJECT_OPEN PVRSRV_IOWR(PVRSRV_BRIDGE_EVENT_OBJECT_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_EVENT_OBJECT_CLOSE PVRSRV_IOWR(PVRSRV_BRIDGE_EVENT_OBJECT_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_EVENT_OBJECT_CMD_LAST (PVRSRV_BRIDGE_EVENT_OBJECT_CMD_FIRST+2)
+
+#define PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST (PVRSRV_BRIDGE_EVENT_OBJECT_CMD_LAST+1)
+#define PVRSRV_BRIDGE_CREATE_SYNC_INFO_MOD_OBJ PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_DESTROY_SYNC_INFO_MOD_OBJ PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_MODIFY_PENDING_SYNC_OPS PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_MODIFY_COMPLETE_SYNC_OPS PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_SYNC_OPS_TAKE_TOKEN PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_SYNC_OPS_FLUSH_TO_TOKEN PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+5)
+#define PVRSRV_BRIDGE_SYNC_OPS_FLUSH_TO_MOD_OBJ PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+6)
+#define PVRSRV_BRIDGE_SYNC_OPS_FLUSH_TO_DELTA PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+7)
+#define PVRSRV_BRIDGE_ALLOC_SYNC_INFO PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+8)
+#define PVRSRV_BRIDGE_FREE_SYNC_INFO PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+9)
+#define PVRSRV_BRIDGE_SYNC_OPS_CMD_LAST (PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+9)
+
+#define PVRSRV_BRIDGE_LAST_NON_DEVICE_CMD (PVRSRV_BRIDGE_SYNC_OPS_CMD_LAST+1)
+
+
+#define PVRSRV_KERNEL_MODE_CLIENT 1
+
+typedef struct PVRSRV_BRIDGE_RETURN_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_VOID *pvData;
+
+}PVRSRV_BRIDGE_RETURN;
+
+
+typedef struct PVRSRV_BRIDGE_PACKAGE_TAG
+{
+ IMG_UINT32 ui32BridgeID;
+ IMG_UINT32 ui32Size;
+ IMG_VOID *pvParamIn;
+ IMG_UINT32 ui32InBufferSize;
+ IMG_VOID *pvParamOut;
+ IMG_UINT32 ui32OutBufferSize;
+
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelServices;
+#else
+ IMG_HANDLE hKernelServices;
+#endif
+}PVRSRV_BRIDGE_PACKAGE;
+
+
+typedef struct PVRSRV_BRIDGE_IN_CONNECT_SERVICES_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32Flags;
+} PVRSRV_BRIDGE_IN_CONNECT_SERVICES;
+
+typedef struct PVRSRV_BRIDGE_IN_ACQUIRE_DEVICEINFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 uiDevIndex;
+ PVRSRV_DEVICE_TYPE eDeviceType;
+
+} PVRSRV_BRIDGE_IN_ACQUIRE_DEVICEINFO;
+
+
+typedef struct PVRSRV_BRIDGE_IN_ENUMCLASS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_DEVICE_CLASS sDeviceClass;
+} PVRSRV_BRIDGE_IN_ENUMCLASS;
+
+
+typedef struct PVRSRV_BRIDGE_IN_CLOSE_DISPCLASS_DEVICE_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDeviceKM;
+#else
+ IMG_HANDLE hDeviceKM;
+#endif
+} PVRSRV_BRIDGE_IN_CLOSE_DISPCLASS_DEVICE;
+
+
+typedef struct PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_FORMATS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDeviceKM;
+#else
+ IMG_HANDLE hDeviceKM;
+#endif
+} PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_FORMATS;
+
+
+typedef struct PVRSRV_BRIDGE_IN_GET_DISPCLASS_SYSBUFFER_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDeviceKM;
+#else
+ IMG_HANDLE hDeviceKM;
+#endif
+} PVRSRV_BRIDGE_IN_GET_DISPCLASS_SYSBUFFER;
+
+
+typedef struct PVRSRV_BRIDGE_IN_GET_DISPCLASS_INFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDeviceKM;
+#else
+ IMG_HANDLE hDeviceKM;
+#endif
+} PVRSRV_BRIDGE_IN_GET_DISPCLASS_INFO;
+
+
+typedef struct PVRSRV_BRIDGE_IN_CLOSE_BUFFERCLASS_DEVICE_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDeviceKM;
+#else
+ IMG_HANDLE hDeviceKM;
+#endif
+} PVRSRV_BRIDGE_IN_CLOSE_BUFFERCLASS_DEVICE;
+
+
+typedef struct PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_INFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDeviceKM;
+#else
+ IMG_HANDLE hDeviceKM;
+#endif
+} PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_INFO;
+
+
+typedef struct PVRSRV_BRIDGE_IN_RELEASE_DEVICEINFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+
+} PVRSRV_BRIDGE_IN_RELEASE_DEVICEINFO;
+
+
+typedef struct PVRSRV_BRIDGE_IN_FREE_CLASSDEVICEINFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_DEVICE_CLASS DeviceClass;
+ IMG_VOID* pvDevInfo;
+
+}PVRSRV_BRIDGE_IN_FREE_CLASSDEVICEINFO;
+
+
+typedef struct PVRSRV_BRIDGE_IN_GET_DEVMEM_HEAPINFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+ IMG_SID hDevMemContext;
+#else
+ IMG_HANDLE hDevCookie;
+ IMG_HANDLE hDevMemContext;
+#endif
+
+}PVRSRV_BRIDGE_IN_GET_DEVMEM_HEAPINFO;
+
+
+typedef struct PVRSRV_BRIDGE_IN_CREATE_DEVMEMCONTEXT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+
+}PVRSRV_BRIDGE_IN_CREATE_DEVMEMCONTEXT;
+
+
+typedef struct PVRSRV_BRIDGE_IN_DESTROY_DEVMEMCONTEXT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+ IMG_SID hDevMemContext;
+#else
+ IMG_HANDLE hDevCookie;
+ IMG_HANDLE hDevMemContext;
+#endif
+
+}PVRSRV_BRIDGE_IN_DESTROY_DEVMEMCONTEXT;
+
+
+typedef struct PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+ IMG_SID hDevMemHeap;
+#else
+ IMG_HANDLE hDevCookie;
+ IMG_HANDLE hDevMemHeap;
+#endif
+ IMG_UINT32 ui32Attribs;
+ IMG_SIZE_T ui32Size;
+ IMG_SIZE_T ui32Alignment;
+ IMG_PVOID pvPrivData;
+ IMG_UINT32 ui32PrivDataLength;
+
+}PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM;
+
+typedef struct PVRSRV_BRIDGE_IN_MAPMEMINFOTOUSER_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelMemInfo;
+#else
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+#endif
+
+}PVRSRV_BRIDGE_IN_MAPMEMINFOTOUSER;
+
+typedef struct PVRSRV_BRIDGE_IN_UNMAPMEMINFOFROMUSER_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelMemInfo;
+#else
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+#endif
+ IMG_PVOID pvLinAddr;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hMappingInfo;
+#else
+ IMG_HANDLE hMappingInfo;
+#endif
+
+}PVRSRV_BRIDGE_IN_UNMAPMEMINFOFROMUSER;
+
+typedef struct PVRSRV_BRIDGE_IN_FREEDEVICEMEM_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+ IMG_SID hKernelMemInfo;
+#else
+ IMG_HANDLE hDevCookie;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+#endif
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+
+}PVRSRV_BRIDGE_IN_FREEDEVICEMEM;
+
+typedef struct PVRSRV_BRIDGE_IN_EXPORTDEVICEMEM_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+ IMG_SID hKernelMemInfo;
+#else
+ IMG_HANDLE hDevCookie;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+#endif
+
+}PVRSRV_BRIDGE_IN_EXPORTDEVICEMEM;
+
+typedef struct PVRSRV_BRIDGE_IN_GETFREEDEVICEMEM_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32Flags;
+
+} PVRSRV_BRIDGE_IN_GETFREEDEVICEMEM;
+
+typedef struct PVRSRV_BRIDGE_IN_CREATECOMMANDQUEUE_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+ IMG_SIZE_T ui32QueueSize;
+
+}PVRSRV_BRIDGE_IN_CREATECOMMANDQUEUE;
+
+
+typedef struct PVRSRV_BRIDGE_IN_DESTROYCOMMANDQUEUE_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+ PVRSRV_QUEUE_INFO *psQueueInfo;
+
+}PVRSRV_BRIDGE_IN_DESTROYCOMMANDQUEUE;
+
+
+typedef struct PVRSRV_BRIDGE_IN_MHANDLE_TO_MMAP_DATA_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hMHandle;
+#else
+ IMG_HANDLE hMHandle;
+#endif
+} PVRSRV_BRIDGE_IN_MHANDLE_TO_MMAP_DATA;
+
+
+typedef struct PVRSRV_BRIDGE_IN_RELEASE_MMAP_DATA_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hMHandle;
+#else
+ IMG_HANDLE hMHandle;
+#endif
+} PVRSRV_BRIDGE_IN_RELEASE_MMAP_DATA;
+
+
+typedef struct PVRSRV_BRIDGE_IN_RESERVE_DEV_VIRTMEM_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevMemHeap;
+#else
+ IMG_HANDLE hDevMemHeap;
+#endif
+ IMG_DEV_VIRTADDR *psDevVAddr;
+ IMG_SIZE_T ui32Size;
+ IMG_SIZE_T ui32Alignment;
+
+}PVRSRV_BRIDGE_IN_RESERVE_DEV_VIRTMEM;
+
+typedef struct PVRSRV_BRIDGE_OUT_CONNECT_SERVICES_TAG
+{
+ PVRSRV_ERROR eError;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelServices;
+#else
+ IMG_HANDLE hKernelServices;
+#endif
+}PVRSRV_BRIDGE_OUT_CONNECT_SERVICES;
+
+typedef struct PVRSRV_BRIDGE_OUT_RESERVE_DEV_VIRTMEM_TAG
+{
+ PVRSRV_ERROR eError;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelMemInfo;
+ IMG_SID hKernelSyncInfo;
+#else
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+#endif
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+
+}PVRSRV_BRIDGE_OUT_RESERVE_DEV_VIRTMEM;
+
+
+typedef struct PVRSRV_BRIDGE_IN_FREE_DEV_VIRTMEM_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelMemInfo;
+#else
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+#endif
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+
+}PVRSRV_BRIDGE_IN_FREE_DEV_VIRTMEM;
+
+
+typedef struct PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelMemInfo;
+ IMG_SID hDstDevMemHeap;
+#else
+ IMG_HANDLE hKernelMemInfo;
+ IMG_HANDLE hDstDevMemHeap;
+#endif
+
+}PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY_TAG
+{
+ PVRSRV_ERROR eError;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDstKernelMemInfo;
+#else
+ PVRSRV_KERNEL_MEM_INFO *psDstKernelMemInfo;
+#endif
+ PVRSRV_CLIENT_MEM_INFO sDstClientMemInfo;
+ PVRSRV_CLIENT_SYNC_INFO sDstClientSyncInfo;
+
+}PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY;
+
+
+typedef struct PVRSRV_BRIDGE_IN_UNMAP_DEV_MEMORY_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelMemInfo;
+#else
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+#endif
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+
+}PVRSRV_BRIDGE_IN_UNMAP_DEV_MEMORY;
+
+
+typedef struct PVRSRV_BRIDGE_IN_MAP_EXT_MEMORY_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelMemInfo;
+#else
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+#endif
+ IMG_SYS_PHYADDR *psSysPAddr;
+ IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_MAP_EXT_MEMORY;
+
+typedef struct PVRSRV_BRIDGE_IN_UNMAP_EXT_MEMORY_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+ IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_UNMAP_EXT_MEMORY;
+
+typedef struct PVRSRV_BRIDGE_IN_MAP_DEVICECLASS_MEMORY_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDeviceClassBuffer;
+ IMG_SID hDevMemContext;
+#else
+ IMG_HANDLE hDeviceClassBuffer;
+ IMG_HANDLE hDevMemContext;
+#endif
+
+}PVRSRV_BRIDGE_IN_MAP_DEVICECLASS_MEMORY;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY_TAG
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelMemInfo;
+ IMG_SID hMappingInfo;
+#else
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ IMG_HANDLE hMappingInfo;
+#endif
+
+}PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY;
+
+
+typedef struct PVRSRV_BRIDGE_IN_UNMAP_DEVICECLASS_MEMORY_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelMemInfo;
+#else
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+#endif
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+
+}PVRSRV_BRIDGE_IN_UNMAP_DEVICECLASS_MEMORY;
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_MEMPOL_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelMemInfo;
+#else
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+#endif
+ IMG_UINT32 ui32Offset;
+ IMG_UINT32 ui32Value;
+ IMG_UINT32 ui32Mask;
+ PDUMP_POLL_OPERATOR eOperator;
+ IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_MEMPOL;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_SYNCPOL_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelSyncInfo;
+#else
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+#endif
+ IMG_BOOL bIsRead;
+ IMG_BOOL bUseLastOpDumpVal;
+ IMG_UINT32 ui32Value;
+ IMG_UINT32 ui32Mask;
+
+}PVRSRV_BRIDGE_IN_PDUMP_SYNCPOL;
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_DUMPMEM_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_PVOID pvLinAddr;
+ IMG_PVOID pvAltLinAddr;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelMemInfo;
+#else
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+#endif
+ IMG_UINT32 ui32Offset;
+ IMG_UINT32 ui32Bytes;
+ IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_DUMPMEM;
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_DUMPSYNC_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_PVOID pvAltLinAddr;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelSyncInfo;
+#else
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+#endif
+ IMG_UINT32 ui32Offset;
+ IMG_UINT32 ui32Bytes;
+
+}PVRSRV_BRIDGE_IN_PDUMP_DUMPSYNC;
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_DUMPREG_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+ PVRSRV_HWREG sHWReg;
+ IMG_UINT32 ui32Flags;
+ IMG_CHAR szRegRegion[32];
+
+}PVRSRV_BRIDGE_IN_PDUMP_DUMPREG;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_REGPOL_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+ PVRSRV_HWREG sHWReg;
+ IMG_UINT32 ui32Mask;
+ IMG_UINT32 ui32Flags;
+ IMG_CHAR szRegRegion[32];
+}PVRSRV_BRIDGE_IN_PDUMP_REGPOL;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_DUMPPDREG_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_HWREG sHWReg;
+ IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_DUMPPDREG;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_MEMPAGES_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+ IMG_SID hKernelMemInfo;
+#else
+ IMG_HANDLE hDevCookie;
+ IMG_HANDLE hKernelMemInfo;
+#endif
+ IMG_DEV_PHYADDR *pPages;
+ IMG_UINT32 ui32NumPages;
+ IMG_DEV_VIRTADDR sDevVAddr;
+ IMG_UINT32 ui32Start;
+ IMG_UINT32 ui32Length;
+ IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_MEMPAGES;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_COMMENT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_CHAR szComment[PVRSRV_PDUMP_MAX_COMMENT_SIZE];
+ IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_COMMENT;
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_SETFRAME_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32Frame;
+
+}PVRSRV_BRIDGE_IN_PDUMP_SETFRAME;
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_BITMAP_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+ IMG_CHAR szFileName[PVRSRV_PDUMP_MAX_FILENAME_SIZE];
+ IMG_UINT32 ui32FileOffset;
+ IMG_UINT32 ui32Width;
+ IMG_UINT32 ui32Height;
+ IMG_UINT32 ui32StrideInBytes;
+ IMG_DEV_VIRTADDR sDevBaseAddr;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevMemContext;
+#else
+ IMG_HANDLE hDevMemContext;
+#endif
+ IMG_UINT32 ui32Size;
+ PDUMP_PIXEL_FORMAT ePixelFormat;
+ PDUMP_MEM_FORMAT eMemFormat;
+ IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_BITMAP;
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_READREG_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+ IMG_CHAR szFileName[PVRSRV_PDUMP_MAX_FILENAME_SIZE];
+ IMG_UINT32 ui32FileOffset;
+ IMG_UINT32 ui32Address;
+ IMG_UINT32 ui32Size;
+ IMG_UINT32 ui32Flags;
+ IMG_CHAR szRegRegion[32];
+
+}PVRSRV_BRIDGE_IN_PDUMP_READREG;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_DRIVERINFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_CHAR szString[PVRSRV_PDUMP_MAX_COMMENT_SIZE];
+ IMG_BOOL bContinuous;
+
+}PVRSRV_BRIDGE_IN_PDUMP_DRIVERINFO;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_DUMPPDDEVPADDR_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelMemInfo;
+#else
+ IMG_HANDLE hKernelMemInfo;
+#endif
+ IMG_UINT32 ui32Offset;
+ IMG_DEV_PHYADDR sPDDevPAddr;
+}PVRSRV_BRIDGE_IN_PDUMP_DUMPPDDEVPADDR;
+
+typedef struct PVRSRV_BRIDGE_PDUM_IN_CYCLE_COUNT_REG_READ_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+ IMG_UINT32 ui32RegOffset;
+ IMG_BOOL bLastFrame;
+}PVRSRV_BRIDGE_IN_PDUMP_CYCLE_COUNT_REG_READ;
+
+typedef struct PVRSRV_BRIDGE_OUT_ENUMDEVICE_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32NumDevices;
+ PVRSRV_DEVICE_IDENTIFIER asDeviceIdentifier[PVRSRV_MAX_DEVICES];
+
+}PVRSRV_BRIDGE_OUT_ENUMDEVICE;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_ACQUIRE_DEVICEINFO_TAG
+{
+
+ PVRSRV_ERROR eError;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+
+} PVRSRV_BRIDGE_OUT_ACQUIRE_DEVICEINFO;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_ENUMCLASS_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32NumDevices;
+ IMG_UINT32 ui32DevID[PVRSRV_MAX_DEVICES];
+
+}PVRSRV_BRIDGE_OUT_ENUMCLASS;
+
+
+typedef struct PVRSRV_BRIDGE_IN_OPEN_DISPCLASS_DEVICE_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32DeviceID;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+
+}PVRSRV_BRIDGE_IN_OPEN_DISPCLASS_DEVICE;
+
+typedef struct PVRSRV_BRIDGE_OUT_OPEN_DISPCLASS_DEVICE_TAG
+{
+ PVRSRV_ERROR eError;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDeviceKM;
+#else
+ IMG_HANDLE hDeviceKM;
+#endif
+
+}PVRSRV_BRIDGE_OUT_OPEN_DISPCLASS_DEVICE;
+
+
+typedef struct PVRSRV_BRIDGE_IN_WRAP_EXT_MEMORY_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+ IMG_SID hDevMemContext;
+#else
+ IMG_HANDLE hDevCookie;
+ IMG_HANDLE hDevMemContext;
+#endif
+ IMG_VOID *pvLinAddr;
+ IMG_SIZE_T ui32ByteSize;
+ IMG_SIZE_T ui32PageOffset;
+ IMG_BOOL bPhysContig;
+ IMG_UINT32 ui32NumPageTableEntries;
+ IMG_SYS_PHYADDR *psSysPAddr;
+ IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_WRAP_EXT_MEMORY;
+
+typedef struct PVRSRV_BRIDGE_OUT_WRAP_EXT_MEMORY_TAG
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+
+}PVRSRV_BRIDGE_OUT_WRAP_EXT_MEMORY;
+
+typedef struct PVRSRV_BRIDGE_IN_UNWRAP_EXT_MEMORY_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelMemInfo;
+#else
+ IMG_HANDLE hKernelMemInfo;
+#endif
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+
+}PVRSRV_BRIDGE_IN_UNWRAP_EXT_MEMORY;
+
+
+#define PVRSRV_MAX_DC_DISPLAY_FORMATS 10
+#define PVRSRV_MAX_DC_DISPLAY_DIMENSIONS 10
+#define PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS 4
+#define PVRSRV_MAX_DC_CLIP_RECTS 32
+
+typedef struct PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_FORMATS_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32Count;
+ DISPLAY_FORMAT asFormat[PVRSRV_MAX_DC_DISPLAY_FORMATS];
+
+}PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_FORMATS;
+
+
+typedef struct PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_DIMS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDeviceKM;
+#else
+ IMG_HANDLE hDeviceKM;
+#endif
+ DISPLAY_FORMAT sFormat;
+
+}PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_DIMS;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_DIMS_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32Count;
+ DISPLAY_DIMS asDim[PVRSRV_MAX_DC_DISPLAY_DIMENSIONS];
+
+}PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_DIMS;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_DISPCLASS_INFO_TAG
+{
+ PVRSRV_ERROR eError;
+ DISPLAY_INFO sDisplayInfo;
+
+}PVRSRV_BRIDGE_OUT_GET_DISPCLASS_INFO;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_DISPCLASS_SYSBUFFER_TAG
+{
+ PVRSRV_ERROR eError;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hBuffer;
+#else
+ IMG_HANDLE hBuffer;
+#endif
+
+}PVRSRV_BRIDGE_OUT_GET_DISPCLASS_SYSBUFFER;
+
+
+typedef struct PVRSRV_BRIDGE_IN_CREATE_DISPCLASS_SWAPCHAIN_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDeviceKM;
+#else
+ IMG_HANDLE hDeviceKM;
+#endif
+ IMG_UINT32 ui32Flags;
+ DISPLAY_SURF_ATTRIBUTES sDstSurfAttrib;
+ DISPLAY_SURF_ATTRIBUTES sSrcSurfAttrib;
+ IMG_UINT32 ui32BufferCount;
+ IMG_UINT32 ui32OEMFlags;
+ IMG_UINT32 ui32SwapChainID;
+
+} PVRSRV_BRIDGE_IN_CREATE_DISPCLASS_SWAPCHAIN;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_CREATE_DISPCLASS_SWAPCHAIN_TAG
+{
+ PVRSRV_ERROR eError;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hSwapChain;
+#else
+ IMG_HANDLE hSwapChain;
+#endif
+ IMG_UINT32 ui32SwapChainID;
+
+} PVRSRV_BRIDGE_OUT_CREATE_DISPCLASS_SWAPCHAIN;
+
+
+typedef struct PVRSRV_BRIDGE_IN_DESTROY_DISPCLASS_SWAPCHAIN_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDeviceKM;
+ IMG_SID hSwapChain;
+#else
+ IMG_HANDLE hDeviceKM;
+ IMG_HANDLE hSwapChain;
+#endif
+
+} PVRSRV_BRIDGE_IN_DESTROY_DISPCLASS_SWAPCHAIN;
+
+
+typedef struct PVRSRV_BRIDGE_IN_SET_DISPCLASS_RECT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDeviceKM;
+ IMG_SID hSwapChain;
+#else
+ IMG_HANDLE hDeviceKM;
+ IMG_HANDLE hSwapChain;
+#endif
+ IMG_RECT sRect;
+
+} PVRSRV_BRIDGE_IN_SET_DISPCLASS_RECT;
+
+
+typedef struct PVRSRV_BRIDGE_IN_SET_DISPCLASS_COLOURKEY_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDeviceKM;
+ IMG_SID hSwapChain;
+#else
+ IMG_HANDLE hDeviceKM;
+ IMG_HANDLE hSwapChain;
+#endif
+ IMG_UINT32 ui32CKColour;
+
+} PVRSRV_BRIDGE_IN_SET_DISPCLASS_COLOURKEY;
+
+
+typedef struct PVRSRV_BRIDGE_IN_GET_DISPCLASS_BUFFERS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDeviceKM;
+ IMG_SID hSwapChain;
+#else
+ IMG_HANDLE hDeviceKM;
+ IMG_HANDLE hSwapChain;
+#endif
+
+} PVRSRV_BRIDGE_IN_GET_DISPCLASS_BUFFERS;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_DISPCLASS_BUFFERS_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32BufferCount;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID ahBuffer[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
+#else
+ IMG_HANDLE ahBuffer[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
+#endif
+ IMG_SYS_PHYADDR asPhyAddr[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
+} PVRSRV_BRIDGE_OUT_GET_DISPCLASS_BUFFERS;
+
+
+typedef struct PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_BUFFER_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDeviceKM;
+ IMG_SID hBuffer;
+#else
+ IMG_HANDLE hDeviceKM;
+ IMG_HANDLE hBuffer;
+#endif
+ IMG_UINT32 ui32SwapInterval;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hPrivateTag;
+#else
+ IMG_HANDLE hPrivateTag;
+#endif
+ IMG_UINT32 ui32ClipRectCount;
+ IMG_RECT sClipRect[PVRSRV_MAX_DC_CLIP_RECTS];
+
+} PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_BUFFER;
+
+typedef struct PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_BUFFER2_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDeviceKM;
+ IMG_SID hSwapChain;
+#else
+ IMG_HANDLE hDeviceKM;
+ IMG_HANDLE hSwapChain;
+#endif
+ IMG_UINT32 ui32SwapInterval;
+
+ IMG_UINT32 ui32NumMemInfos;
+ PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfos;
+ PVRSRV_KERNEL_SYNC_INFO **ppsKernelSyncInfos;
+
+ IMG_UINT32 ui32PrivDataLength;
+ IMG_PVOID pvPrivData;
+
+} PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_BUFFER2;
+
+typedef struct PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_SYSTEM_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDeviceKM;
+ IMG_SID hSwapChain;
+#else
+ IMG_HANDLE hDeviceKM;
+ IMG_HANDLE hSwapChain;
+#endif
+
+} PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_SYSTEM;
+
+
+typedef struct PVRSRV_BRIDGE_IN_OPEN_BUFFERCLASS_DEVICE_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32DeviceID;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+
+} PVRSRV_BRIDGE_IN_OPEN_BUFFERCLASS_DEVICE;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_OPEN_BUFFERCLASS_DEVICE_TAG
+{
+ PVRSRV_ERROR eError;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDeviceKM;
+#else
+ IMG_HANDLE hDeviceKM;
+#endif
+
+} PVRSRV_BRIDGE_OUT_OPEN_BUFFERCLASS_DEVICE;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_INFO_TAG
+{
+ PVRSRV_ERROR eError;
+ BUFFER_INFO sBufferInfo;
+
+} PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_INFO;
+
+
+typedef struct PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_BUFFER_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDeviceKM;
+#else
+ IMG_HANDLE hDeviceKM;
+#endif
+ IMG_UINT32 ui32BufferIndex;
+
+} PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_BUFFER;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_BUFFER_TAG
+{
+ PVRSRV_ERROR eError;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hBuffer;
+#else
+ IMG_HANDLE hBuffer;
+#endif
+
+} PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_BUFFER;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_DEVMEM_HEAPINFO_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32ClientHeapCount;
+ PVRSRV_HEAP_INFO sHeapInfo[PVRSRV_MAX_CLIENT_HEAPS];
+
+} PVRSRV_BRIDGE_OUT_GET_DEVMEM_HEAPINFO;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_CREATE_DEVMEMCONTEXT_TAG
+{
+ PVRSRV_ERROR eError;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevMemContext;
+#else
+ IMG_HANDLE hDevMemContext;
+#endif
+ IMG_UINT32 ui32ClientHeapCount;
+ PVRSRV_HEAP_INFO sHeapInfo[PVRSRV_MAX_CLIENT_HEAPS];
+
+} PVRSRV_BRIDGE_OUT_CREATE_DEVMEMCONTEXT;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_CREATE_DEVMEMHEAP_TAG
+{
+ PVRSRV_ERROR eError;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevMemHeap;
+#else
+ IMG_HANDLE hDevMemHeap;
+#endif
+
+} PVRSRV_BRIDGE_OUT_CREATE_DEVMEMHEAP;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM_TAG
+{
+ PVRSRV_ERROR eError;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelMemInfo;
+#else
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+#endif
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+
+} PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM_TAG
+{
+ PVRSRV_ERROR eError;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hMemInfo;
+#else
+ IMG_HANDLE hMemInfo;
+#endif
+#if defined(SUPPORT_MEMINFO_IDS)
+ IMG_UINT64 ui64Stamp;
+#endif
+
+} PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_MAPMEMINFOTOUSER_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_PVOID pvLinAddr;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hMappingInfo;
+#else
+ IMG_HANDLE hMappingInfo;
+#endif
+
+}PVRSRV_BRIDGE_OUT_MAPMEMINFOTOUSER;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GETFREEDEVICEMEM_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_SIZE_T ui32Total;
+ IMG_SIZE_T ui32Free;
+ IMG_SIZE_T ui32LargestBlock;
+
+} PVRSRV_BRIDGE_OUT_GETFREEDEVICEMEM;
+
+
+#include "pvrmmap.h"
+typedef struct PVRSRV_BRIDGE_OUT_MHANDLE_TO_MMAP_DATA_TAG
+{
+ PVRSRV_ERROR eError;
+
+
+ IMG_UINT32 ui32MMapOffset;
+
+
+ IMG_UINT32 ui32ByteOffset;
+
+
+ IMG_UINT32 ui32RealByteSize;
+
+
+ IMG_UINT32 ui32UserVAddr;
+
+} PVRSRV_BRIDGE_OUT_MHANDLE_TO_MMAP_DATA;
+
+typedef struct PVRSRV_BRIDGE_OUT_RELEASE_MMAP_DATA_TAG
+{
+ PVRSRV_ERROR eError;
+
+
+ IMG_BOOL bMUnmap;
+
+
+ IMG_UINT32 ui32UserVAddr;
+
+
+ IMG_UINT32 ui32RealByteSize;
+} PVRSRV_BRIDGE_OUT_RELEASE_MMAP_DATA;
+typedef struct PVRSRV_BRIDGE_IN_GET_MISC_INFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_MISC_INFO sMiscInfo;
+
+}PVRSRV_BRIDGE_IN_GET_MISC_INFO;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_MISC_INFO_TAG
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_MISC_INFO sMiscInfo;
+
+}PVRSRV_BRIDGE_OUT_GET_MISC_INFO;
+
+
+typedef struct PVRSRV_BRIDGE_IN_RELEASE_MISC_INFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_MISC_INFO sMiscInfo;
+
+}PVRSRV_BRIDGE_IN_RELEASE_MISC_INFO;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_RELEASE_MISC_INFO_TAG
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_MISC_INFO sMiscInfo;
+
+}PVRSRV_BRIDGE_OUT_RELEASE_MISC_INFO;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_PDUMP_ISCAPTURING_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_BOOL bIsCapturing;
+
+} PVRSRV_BRIDGE_OUT_PDUMP_ISCAPTURING;
+
+typedef struct PVRSRV_BRIDGE_IN_GET_FB_STATS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_SIZE_T ui32Total;
+ IMG_SIZE_T ui32Available;
+
+} PVRSRV_BRIDGE_IN_GET_FB_STATS;
+
+
+typedef struct PVRSRV_BRIDGE_IN_MAPPHYSTOUSERSPACE_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+ IMG_SYS_PHYADDR sSysPhysAddr;
+ IMG_UINT32 uiSizeInBytes;
+
+} PVRSRV_BRIDGE_IN_MAPPHYSTOUSERSPACE;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_MAPPHYSTOUSERSPACE_TAG
+{
+ IMG_PVOID pvUserAddr;
+ IMG_UINT32 uiActualSize;
+ IMG_PVOID pvProcess;
+
+} PVRSRV_BRIDGE_OUT_MAPPHYSTOUSERSPACE;
+
+
+typedef struct PVRSRV_BRIDGE_IN_UNMAPPHYSTOUSERSPACE_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+ IMG_PVOID pvUserAddr;
+ IMG_PVOID pvProcess;
+
+} PVRSRV_BRIDGE_IN_UNMAPPHYSTOUSERSPACE;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GETPHYSTOUSERSPACEMAP_TAG
+{
+ IMG_PVOID *ppvTbl;
+ IMG_UINT32 uiTblSize;
+
+} PVRSRV_BRIDGE_OUT_GETPHYSTOUSERSPACEMAP;
+
+
+#if !defined (SUPPORT_SID_INTERFACE)
+typedef struct PVRSRV_BRIDGE_IN_REGISTER_SIM_PROCESS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_PVOID pvProcess;
+
+} PVRSRV_BRIDGE_IN_REGISTER_SIM_PROCESS;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_REGISTER_SIM_PROCESS_TAG
+{
+ IMG_SYS_PHYADDR sRegsPhysBase;
+ IMG_VOID *pvRegsBase;
+ IMG_PVOID pvProcess;
+ IMG_UINT32 ulNoOfEntries;
+ IMG_PVOID pvTblLinAddr;
+
+} PVRSRV_BRIDGE_OUT_REGISTER_SIM_PROCESS;
+
+
+typedef struct PVRSRV_BRIDGE_IN_UNREGISTER_SIM_PROCESS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_PVOID pvProcess;
+ IMG_VOID *pvRegsBase;
+
+} PVRSRV_BRIDGE_IN_UNREGISTER_SIM_PROCESS;
+
+typedef struct PVRSRV_BRIDGE_IN_PROCESS_SIMISR_EVENT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_UINT32 ui32StatusAndMask;
+ PVRSRV_ERROR eError;
+
+} PVRSRV_BRIDGE_IN_PROCESS_SIMISR_EVENT;
+#endif
+
+typedef struct PVRSRV_BRIDGE_IN_INITSRV_DISCONNECT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_BOOL bInitSuccesful;
+} PVRSRV_BRIDGE_IN_INITSRV_DISCONNECT;
+
+
+typedef struct PVRSRV_BRIDGE_IN_ALLOC_SHARED_SYS_MEM_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32Flags;
+ IMG_SIZE_T ui32Size;
+}PVRSRV_BRIDGE_IN_ALLOC_SHARED_SYS_MEM;
+
+typedef struct PVRSRV_BRIDGE_OUT_ALLOC_SHARED_SYS_MEM_TAG
+{
+ PVRSRV_ERROR eError;
+#if defined (SUPPORT_SID_INTERFACE)
+#else
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+#endif
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+}PVRSRV_BRIDGE_OUT_ALLOC_SHARED_SYS_MEM;
+
+typedef struct PVRSRV_BRIDGE_IN_FREE_SHARED_SYS_MEM_TAG
+{
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelMemInfo;
+ IMG_SID hMappingInfo;
+#else
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+#endif
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+}PVRSRV_BRIDGE_IN_FREE_SHARED_SYS_MEM;
+
+typedef struct PVRSRV_BRIDGE_OUT_FREE_SHARED_SYS_MEM_TAG
+{
+ PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_FREE_SHARED_SYS_MEM;
+
+typedef struct PVRSRV_BRIDGE_IN_MAP_MEMINFO_MEM_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelMemInfo;
+#else
+ IMG_HANDLE hKernelMemInfo;
+#endif
+}PVRSRV_BRIDGE_IN_MAP_MEMINFO_MEM;
+
+typedef struct PVRSRV_BRIDGE_OUT_MAP_MEMINFO_MEM_TAG
+{
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelMemInfo;
+#else
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+#endif
+ PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_MAP_MEMINFO_MEM;
+
+typedef struct PVRSRV_BRIDGE_IN_UNMAP_MEMINFO_MEM_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+}PVRSRV_BRIDGE_IN_UNMAP_MEMINFO_MEM;
+
+typedef struct PVRSRV_BRIDGE_OUT_UNMAP_MEMINFO_MEM_TAG
+{
+ PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_UNMAP_MEMINFO_MEM;
+
+typedef struct PVRSRV_BRIDGE_IN_EVENT_OBJECT_WAI_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hOSEventKM;
+#else
+ IMG_HANDLE hOSEventKM;
+#endif
+} PVRSRV_BRIDGE_IN_EVENT_OBJECT_WAIT;
+
+typedef struct PVRSRV_BRIDGE_IN_EVENT_OBJECT_OPEN_TAG
+{
+ PVRSRV_EVENTOBJECT sEventObject;
+} PVRSRV_BRIDGE_IN_EVENT_OBJECT_OPEN;
+
+typedef struct PVRSRV_BRIDGE_OUT_EVENT_OBJECT_OPEN_TAG
+{
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_UINT32 hOSEvent;
+#else
+ IMG_HANDLE hOSEvent;
+#endif
+ PVRSRV_ERROR eError;
+} PVRSRV_BRIDGE_OUT_EVENT_OBJECT_OPEN;
+
+typedef struct PVRSRV_BRIDGE_IN_EVENT_OBJECT_CLOSE_TAG
+{
+ PVRSRV_EVENTOBJECT sEventObject;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hOSEventKM;
+#else
+ IMG_HANDLE hOSEventKM;
+#endif
+} PVRSRV_BRIDGE_IN_EVENT_OBJECT_CLOSE;
+
+typedef struct PVRSRV_BRIDGE_OUT_CREATE_SYNC_INFO_MOD_OBJ_TAG
+{
+ PVRSRV_ERROR eError;
+
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelSyncInfoModObj;
+#else
+ IMG_HANDLE hKernelSyncInfoModObj;
+#endif
+
+} PVRSRV_BRIDGE_OUT_CREATE_SYNC_INFO_MOD_OBJ;
+
+typedef struct PVRSRV_BRIDGE_IN_DESTROY_SYNC_INFO_MOD_OBJ
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelSyncInfoModObj;
+#else
+ IMG_HANDLE hKernelSyncInfoModObj;
+#endif
+} PVRSRV_BRIDGE_IN_DESTROY_SYNC_INFO_MOD_OBJ;
+
+typedef struct PVRSRV_BRIDGE_IN_MODIFY_PENDING_SYNC_OPS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelSyncInfoModObj;
+ IMG_SID hKernelSyncInfo;
+#else
+ IMG_HANDLE hKernelSyncInfoModObj;
+ IMG_HANDLE hKernelSyncInfo;
+#endif
+ IMG_UINT32 ui32ModifyFlags;
+
+} PVRSRV_BRIDGE_IN_MODIFY_PENDING_SYNC_OPS;
+
+typedef struct PVRSRV_BRIDGE_IN_MODIFY_COMPLETE_SYNC_OPS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelSyncInfoModObj;
+#else
+ IMG_HANDLE hKernelSyncInfoModObj;
+#endif
+} PVRSRV_BRIDGE_IN_MODIFY_COMPLETE_SYNC_OPS;
+
+typedef struct PVRSRV_BRIDGE_OUT_MODIFY_PENDING_SYNC_OPS_TAG
+{
+ PVRSRV_ERROR eError;
+
+
+ IMG_UINT32 ui32ReadOpsPending;
+ IMG_UINT32 ui32WriteOpsPending;
+ IMG_UINT32 ui32ReadOps2Pending;
+
+} PVRSRV_BRIDGE_OUT_MODIFY_PENDING_SYNC_OPS;
+
+typedef struct PVRSRV_BRIDGE_IN_SYNC_OPS_TAKE_TOKEN_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelSyncInfo;
+#else
+ IMG_HANDLE hKernelSyncInfo;
+#endif
+
+} PVRSRV_BRIDGE_IN_SYNC_OPS_TAKE_TOKEN;
+
+typedef struct PVRSRV_BRIDGE_OUT_SYNC_OPS_TAKE_TOKEN_TAG
+{
+ PVRSRV_ERROR eError;
+
+ IMG_UINT32 ui32ReadOpsPending;
+ IMG_UINT32 ui32WriteOpsPending;
+ IMG_UINT32 ui32ReadOps2Pending;
+
+} PVRSRV_BRIDGE_OUT_SYNC_OPS_TAKE_TOKEN;
+
+typedef struct PVRSRV_BRIDGE_IN_SYNC_OPS_FLUSH_TO_TOKEN_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelSyncInfo;
+#else
+ IMG_HANDLE hKernelSyncInfo;
+#endif
+ IMG_UINT32 ui32ReadOpsPendingSnapshot;
+ IMG_UINT32 ui32WriteOpsPendingSnapshot;
+ IMG_UINT32 ui32ReadOps2PendingSnapshot;
+} PVRSRV_BRIDGE_IN_SYNC_OPS_FLUSH_TO_TOKEN;
+
+typedef struct PVRSRV_BRIDGE_IN_SYNC_OPS_FLUSH_TO_MOD_OBJ_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelSyncInfoModObj;
+#else
+ IMG_HANDLE hKernelSyncInfoModObj;
+#endif
+} PVRSRV_BRIDGE_IN_SYNC_OPS_FLUSH_TO_MOD_OBJ;
+
+typedef struct PVRSRV_BRIDGE_IN_SYNC_OPS_FLUSH_TO_DELTA_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelSyncInfo;
+#else
+ IMG_HANDLE hKernelSyncInfo;
+#endif
+ IMG_UINT32 ui32Delta;
+} PVRSRV_BRIDGE_IN_SYNC_OPS_FLUSH_TO_DELTA;
+
+typedef struct PVRSRV_BRIDGE_IN_ALLOC_SYNC_INFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+} PVRSRV_BRIDGE_IN_ALLOC_SYNC_INFO;
+
+typedef struct PVRSRV_BRIDGE_OUT_ALLOC_SYNC_INFO_TAG
+{
+ PVRSRV_ERROR eError;
+
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelSyncInfo;
+#else
+ IMG_HANDLE hKernelSyncInfo;
+#endif
+} PVRSRV_BRIDGE_OUT_ALLOC_SYNC_INFO;
+
+typedef struct PVRSRV_BRIDGE_IN_FREE_SYNC_INFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelSyncInfo;
+#else
+ IMG_HANDLE hKernelSyncInfo;
+#endif
+} PVRSRV_BRIDGE_IN_FREE_SYNC_INFO;
+
+typedef struct PVRSRV_BRIDGE_IN_CHG_DEV_MEM_ATTRIBS_TAG
+{
+ IMG_SID hKernelMemInfo;
+ IMG_UINT32 ui32Attribs;
+} PVRSRV_BRIDGE_IN_CHG_DEV_MEM_ATTRIBS;
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/pvr/pvr_bridge_k.c b/drivers/gpu/pvr/pvr_bridge_k.c
new file mode 100644
index 0000000..9185df4
--- /dev/null
+++ b/drivers/gpu/pvr/pvr_bridge_k.c
@@ -0,0 +1,464 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "img_defs.h"
+#include "services.h"
+#include "pvr_bridge.h"
+#include "perproc.h"
+#include "mutex.h"
+#include "syscommon.h"
+#include "pvr_debug.h"
+#include "proc.h"
+#include "private_data.h"
+#include "linkage.h"
+#include "pvr_bridge_km.h"
+#include "pvr_uaccess.h"
+#include "refcount.h"
+#include "buffer_manager.h"
+
+#if defined(SUPPORT_DRI_DRM)
+#include <drm/drmP.h>
+#include "pvr_drm.h"
+#if defined(PVR_SECURE_DRM_AUTH_EXPORT)
+#include "env_perproc.h"
+#endif
+#endif
+
+#if defined(SUPPORT_VGX)
+#include "vgx_bridge.h"
+#endif
+
+#if defined(SUPPORT_SGX)
+#include "sgx_bridge.h"
+#endif
+
+#include "bridged_pvr_bridge.h"
+
+#if defined(SUPPORT_DRI_DRM)
+#define PRIVATE_DATA(pFile) ((pFile)->driver_priv)
+#else
+#define PRIVATE_DATA(pFile) ((pFile)->private_data)
+#endif
+
+#if defined(DEBUG_BRIDGE_KM)
+
+static struct proc_dir_entry *g_ProcBridgeStats =0;
+static void* ProcSeqNextBridgeStats(struct seq_file *sfile,void* el,loff_t off);
+static void ProcSeqShowBridgeStats(struct seq_file *sfile,void* el);
+static void* ProcSeqOff2ElementBridgeStats(struct seq_file * sfile, loff_t off);
+static void ProcSeqStartstopBridgeStats(struct seq_file *sfile,IMG_BOOL start);
+
+#endif
+
+extern PVRSRV_LINUX_MUTEX gPVRSRVLock;
+
+#if defined(SUPPORT_MEMINFO_IDS)
+static IMG_UINT64 ui64Stamp;
+#endif
+
+PVRSRV_ERROR
+LinuxBridgeInit(IMG_VOID)
+{
+#if defined(DEBUG_BRIDGE_KM)
+ {
+ g_ProcBridgeStats = CreateProcReadEntrySeq(
+ "bridge_stats",
+ NULL,
+ ProcSeqNextBridgeStats,
+ ProcSeqShowBridgeStats,
+ ProcSeqOff2ElementBridgeStats,
+ ProcSeqStartstopBridgeStats
+ );
+ if(!g_ProcBridgeStats)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ }
+#endif
+ return CommonBridgeInit();
+}
+
+IMG_VOID
+LinuxBridgeDeInit(IMG_VOID)
+{
+#if defined(DEBUG_BRIDGE_KM)
+ RemoveProcEntrySeq(g_ProcBridgeStats);
+#endif
+}
+
+#if defined(DEBUG_BRIDGE_KM)
+
+static void ProcSeqStartstopBridgeStats(struct seq_file *sfile,IMG_BOOL start)
+{
+ if(start)
+ {
+ LinuxLockMutex(&gPVRSRVLock);
+ }
+ else
+ {
+ LinuxUnLockMutex(&gPVRSRVLock);
+ }
+}
+
+
+static void* ProcSeqOff2ElementBridgeStats(struct seq_file *sfile, loff_t off)
+{
+ if(!off)
+ {
+ return PVR_PROC_SEQ_START_TOKEN;
+ }
+
+ if(off > BRIDGE_DISPATCH_TABLE_ENTRY_COUNT)
+ {
+ return (void*)0;
+ }
+
+
+ return (void*)&g_BridgeDispatchTable[off-1];
+}
+
+static void* ProcSeqNextBridgeStats(struct seq_file *sfile,void* el,loff_t off)
+{
+ return ProcSeqOff2ElementBridgeStats(sfile,off);
+}
+
+
+static void ProcSeqShowBridgeStats(struct seq_file *sfile,void* el)
+{
+ PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY *psEntry = ( PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY*)el;
+
+ if(el == PVR_PROC_SEQ_START_TOKEN)
+ {
+ seq_printf(sfile,
+ "Total ioctl call count = %u\n"
+ "Total number of bytes copied via copy_from_user = %u\n"
+ "Total number of bytes copied via copy_to_user = %u\n"
+ "Total number of bytes copied via copy_*_user = %u\n\n"
+ "%-45s | %-40s | %10s | %20s | %10s\n",
+ g_BridgeGlobalStats.ui32IOCTLCount,
+ g_BridgeGlobalStats.ui32TotalCopyFromUserBytes,
+ g_BridgeGlobalStats.ui32TotalCopyToUserBytes,
+ g_BridgeGlobalStats.ui32TotalCopyFromUserBytes+g_BridgeGlobalStats.ui32TotalCopyToUserBytes,
+ "Bridge Name",
+ "Wrapper Function",
+ "Call Count",
+ "copy_from_user Bytes",
+ "copy_to_user Bytes"
+ );
+ return;
+ }
+
+ seq_printf(sfile,
+ "%-45s %-40s %-10u %-20u %-10u\n",
+ psEntry->pszIOCName,
+ psEntry->pszFunctionName,
+ psEntry->ui32CallCount,
+ psEntry->ui32CopyFromUserTotalBytes,
+ psEntry->ui32CopyToUserTotalBytes);
+}
+
+#endif
+
+
+#if defined(SUPPORT_DRI_DRM)
+int
+PVRSRV_BridgeDispatchKM(struct drm_device unref__ *dev, void *arg, struct drm_file *pFile)
+#else
+long
+PVRSRV_BridgeDispatchKM(struct file *pFile, unsigned int unref__ ioctlCmd, unsigned long arg)
+#endif
+{
+ IMG_UINT32 cmd;
+#if !defined(SUPPORT_DRI_DRM)
+ PVRSRV_BRIDGE_PACKAGE *psBridgePackageUM = (PVRSRV_BRIDGE_PACKAGE *)arg;
+ PVRSRV_BRIDGE_PACKAGE sBridgePackageKM;
+#endif
+ PVRSRV_BRIDGE_PACKAGE *psBridgePackageKM;
+ IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+ PVRSRV_PER_PROCESS_DATA *psPerProc;
+ IMG_INT err = -EFAULT;
+
+ LinuxLockMutex(&gPVRSRVLock);
+
+#if defined(SUPPORT_DRI_DRM)
+ psBridgePackageKM = (PVRSRV_BRIDGE_PACKAGE *)arg;
+ PVR_ASSERT(psBridgePackageKM != IMG_NULL);
+#else
+ psBridgePackageKM = &sBridgePackageKM;
+
+ if(!OSAccessOK(PVR_VERIFY_WRITE,
+ psBridgePackageUM,
+ sizeof(PVRSRV_BRIDGE_PACKAGE)))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Received invalid pointer to function arguments",
+ __FUNCTION__));
+
+ goto unlock_and_return;
+ }
+
+
+ if(OSCopyFromUser(IMG_NULL,
+ psBridgePackageKM,
+ psBridgePackageUM,
+ sizeof(PVRSRV_BRIDGE_PACKAGE))
+ != PVRSRV_OK)
+ {
+ goto unlock_and_return;
+ }
+#endif
+
+ cmd = psBridgePackageKM->ui32BridgeID;
+
+ if(cmd != PVRSRV_BRIDGE_CONNECT_SERVICES)
+ {
+ PVRSRV_ERROR eError;
+
+ eError = PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+ (IMG_PVOID *)&psPerProc,
+ psBridgePackageKM->hKernelServices,
+ PVRSRV_HANDLE_TYPE_PERPROC_DATA);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Invalid kernel services handle (%d)",
+ __FUNCTION__, eError));
+ goto unlock_and_return;
+ }
+
+ if(psPerProc->ui32PID != ui32PID)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Process %d tried to access data "
+ "belonging to process %d", __FUNCTION__, ui32PID,
+ psPerProc->ui32PID));
+ goto unlock_and_return;
+ }
+ }
+ else
+ {
+
+ psPerProc = PVRSRVPerProcessData(ui32PID);
+ if(psPerProc == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRV_BridgeDispatchKM: "
+ "Couldn't create per-process data area"));
+ goto unlock_and_return;
+ }
+ }
+
+ psBridgePackageKM->ui32BridgeID = PVRSRV_GET_BRIDGE_ID(psBridgePackageKM->ui32BridgeID);
+
+ switch(cmd)
+ {
+ case PVRSRV_BRIDGE_EXPORT_DEVICEMEM_2:
+ {
+ PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+
+ if(psPrivateData->hKernelMemInfo)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Can only export one MemInfo "
+ "per file descriptor", __FUNCTION__));
+ err = -EINVAL;
+ goto unlock_and_return;
+ }
+ break;
+ }
+
+ case PVRSRV_BRIDGE_MAP_DEV_MEMORY_2:
+ {
+ PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY *psMapDevMemIN =
+ (PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY *)psBridgePackageKM->pvParamIn;
+ PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+
+ if(!psPrivateData->hKernelMemInfo)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: File descriptor has no "
+ "associated MemInfo handle", __FUNCTION__));
+ err = -EINVAL;
+ goto unlock_and_return;
+ }
+
+ if (pvr_put_user(psPrivateData->hKernelMemInfo, &psMapDevMemIN->hKernelMemInfo) != 0)
+ {
+ err = -EFAULT;
+ goto unlock_and_return;
+ }
+ break;
+ }
+
+ default:
+ {
+ PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+
+ if(psPrivateData->hKernelMemInfo)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Import/Export handle tried "
+ "to use privileged service", __FUNCTION__));
+ goto unlock_and_return;
+ }
+ break;
+ }
+ }
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+ switch(cmd)
+ {
+ case PVRSRV_BRIDGE_MAP_DEV_MEMORY:
+ case PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY:
+ {
+ PVRSRV_FILE_PRIVATE_DATA *psPrivateData;
+ int authenticated = pFile->authenticated;
+ PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc;
+
+ if (authenticated)
+ {
+ break;
+ }
+
+
+ psEnvPerProc = (PVRSRV_ENV_PER_PROCESS_DATA *)PVRSRVProcessPrivateData(psPerProc);
+ if (psEnvPerProc == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Process private data not allocated", __FUNCTION__));
+ err = -EFAULT;
+ goto unlock_and_return;
+ }
+
+ list_for_each_entry(psPrivateData, &psEnvPerProc->sDRMAuthListHead, sDRMAuthListItem)
+ {
+ struct drm_file *psDRMFile = psPrivateData->psDRMFile;
+
+ if (pFile->master == psDRMFile->master)
+ {
+ authenticated |= psDRMFile->authenticated;
+ if (authenticated)
+ {
+ break;
+ }
+ }
+ }
+
+ if (!authenticated)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Not authenticated for mapping device or device class memory", __FUNCTION__));
+ err = -EPERM;
+ goto unlock_and_return;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+#endif
+
+ err = BridgedDispatchKM(psPerProc, psBridgePackageKM);
+ if(err != PVRSRV_OK)
+ goto unlock_and_return;
+
+ switch(cmd)
+ {
+ case PVRSRV_BRIDGE_EXPORT_DEVICEMEM_2:
+ {
+ PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM *psExportDeviceMemOUT =
+ (PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM *)psBridgePackageKM->pvParamOut;
+ PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+ IMG_HANDLE hMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+ if (pvr_get_user(hMemInfo, &psExportDeviceMemOUT->hMemInfo) != 0)
+ {
+ err = -EFAULT;
+ goto unlock_and_return;
+ }
+
+
+ if(PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+ (IMG_PVOID *)&psKernelMemInfo,
+ hMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to look up export handle", __FUNCTION__));
+ err = -EFAULT;
+ goto unlock_and_return;
+ }
+
+
+ PVRSRVKernelMemInfoIncRef(psKernelMemInfo);
+
+
+ if (psKernelMemInfo->sShareMemWorkaround.bInUse)
+ {
+ BM_XProcIndexAcquire(psKernelMemInfo->sShareMemWorkaround.ui32ShareIndex);
+ }
+
+ psPrivateData->hKernelMemInfo = hMemInfo;
+#if defined(SUPPORT_MEMINFO_IDS)
+ psPrivateData->ui64Stamp = ++ui64Stamp;
+
+ psKernelMemInfo->ui64Stamp = psPrivateData->ui64Stamp;
+ if (pvr_put_user(psPrivateData->ui64Stamp, &psExportDeviceMemOUT->ui64Stamp) != 0)
+ {
+ err = -EFAULT;
+ goto unlock_and_return;
+ }
+#endif
+ break;
+ }
+
+#if defined(SUPPORT_MEMINFO_IDS)
+ case PVRSRV_BRIDGE_MAP_DEV_MEMORY:
+ case PVRSRV_BRIDGE_MAP_DEV_MEMORY_2:
+ {
+ PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *psMapDeviceMemoryOUT =
+ (PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *)psBridgePackageKM->pvParamOut;
+ PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+ if (pvr_put_user(psPrivateData->ui64Stamp, &psMapDeviceMemoryOUT->sDstClientMemInfo.ui64Stamp) != 0)
+ {
+ err = -EFAULT;
+ goto unlock_and_return;
+ }
+ break;
+ }
+
+ case PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY:
+ {
+ PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY *psDeviceClassMemoryOUT =
+ (PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY *)psBridgePackageKM->pvParamOut;
+ if (pvr_put_user(++ui64Stamp, &psDeviceClassMemoryOUT->sClientMemInfo.ui64Stamp) != 0)
+ {
+ err = -EFAULT;
+ goto unlock_and_return;
+ }
+ break;
+ }
+#endif
+
+ default:
+ break;
+ }
+
+unlock_and_return:
+ LinuxUnLockMutex(&gPVRSRVLock);
+ return err;
+}
diff --git a/drivers/gpu/pvr/pvr_bridge_km.h b/drivers/gpu/pvr/pvr_bridge_km.h
new file mode 100644
index 0000000..e14f2fd
--- /dev/null
+++ b/drivers/gpu/pvr/pvr_bridge_km.h
@@ -0,0 +1,319 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __PVR_BRIDGE_KM_H_
+#define __PVR_BRIDGE_KM_H_
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "pvr_bridge.h"
+#include "perproc.h"
+
+#if defined(__linux__)
+PVRSRV_ERROR LinuxBridgeInit(IMG_VOID);
+IMG_VOID LinuxBridgeDeInit(IMG_VOID);
+#endif
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDevicesKM(IMG_UINT32 *pui32NumDevices,
+ PVRSRV_DEVICE_IDENTIFIER *psDevIdList);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAcquireDeviceDataKM(IMG_UINT32 uiDevIndex,
+ PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_HANDLE *phDevCookie);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateCommandQueueKM(IMG_SIZE_T ui32QueueSize,
+ PVRSRV_QUEUE_INFO **ppsQueueInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyCommandQueueKM(PVRSRV_QUEUE_INFO *psQueueInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapsKM(IMG_HANDLE hDevCookie,
+#if defined (SUPPORT_SID_INTERFACE)
+ PVRSRV_HEAP_INFO_KM *psHeapInfo);
+#else
+ PVRSRV_HEAP_INFO *psHeapInfo);
+#endif
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateDeviceMemContextKM(IMG_HANDLE hDevCookie,
+ PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE *phDevMemContext,
+ IMG_UINT32 *pui32ClientHeapCount,
+#if defined (SUPPORT_SID_INTERFACE)
+ PVRSRV_HEAP_INFO_KM *psHeapInfo,
+#else
+ PVRSRV_HEAP_INFO *psHeapInfo,
+#endif
+ IMG_BOOL *pbCreated,
+ IMG_BOOL *pbShared);
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyDeviceMemContextKM(IMG_HANDLE hDevCookie,
+ IMG_HANDLE hDevMemContext,
+ IMG_BOOL *pbDestroyed);
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapInfoKM(IMG_HANDLE hDevCookie,
+ IMG_HANDLE hDevMemContext,
+ IMG_UINT32 *pui32ClientHeapCount,
+#if defined (SUPPORT_SID_INTERFACE)
+ PVRSRV_HEAP_INFO_KM *psHeapInfo,
+#else
+ PVRSRV_HEAP_INFO *psHeapInfo,
+#endif
+ IMG_BOOL *pbShared
+ );
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV _PVRSRVAllocDeviceMemKM(IMG_HANDLE hDevCookie,
+ PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevMemHeap,
+ IMG_UINT32 ui32Flags,
+ IMG_SIZE_T ui32Size,
+ IMG_SIZE_T ui32Alignment,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfo);
+
+
+#if defined(PVRSRV_LOG_MEMORY_ALLOCS)
+ #define PVRSRVAllocDeviceMemKM(devCookie, perProc, devMemHeap, flags, size, alignment, privdata, privdatalength, memInfo, logStr) \
+ (PVR_TRACE(("PVRSRVAllocDeviceMemKM(" #devCookie ", " #perProc ", " #devMemHeap ", " #flags ", " #size \
+ ", " #alignment "," #memInfo "): " logStr " (size = 0x%x)", size)),\
+ _PVRSRVAllocDeviceMemKM(devCookie, perProc, devMemHeap, flags, size, alignment, privdata, privdatalength, memInfo))
+#else
+ #define PVRSRVAllocDeviceMemKM(devCookie, perProc, devMemHeap, flags, size, alignment, privdata, privdatalength, memInfo, logStr) \
+ _PVRSRVAllocDeviceMemKM(devCookie, perProc, devMemHeap, flags, size, alignment, privdata, privdatalength, memInfo)
+#endif
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeDeviceMemKM(IMG_HANDLE hDevCookie,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDissociateDeviceMemKM(IMG_HANDLE hDevCookie,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVReserveDeviceVirtualMemKM(IMG_HANDLE hDevMemHeap,
+ IMG_DEV_VIRTADDR *psDevVAddr,
+ IMG_SIZE_T ui32Size,
+ IMG_SIZE_T ui32Alignment,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeDeviceVirtualMemKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceMemoryKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ PVRSRV_KERNEL_MEM_INFO *psSrcMemInfo,
+ IMG_HANDLE hDstDevMemHeap,
+ PVRSRV_KERNEL_MEM_INFO **ppsDstMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceMemoryKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVWrapExtMemoryKM(IMG_HANDLE hDevCookie,
+ PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevMemContext,
+ IMG_SIZE_T ui32ByteSize,
+ IMG_SIZE_T ui32PageOffset,
+ IMG_BOOL bPhysContig,
+ IMG_SYS_PHYADDR *psSysAddr,
+ IMG_VOID *pvLinAddr,
+ IMG_UINT32 ui32Flags,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnwrapExtMemoryKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVEnumerateDCKM(PVRSRV_DEVICE_CLASS DeviceClass,
+ IMG_UINT32 *pui32DevCount,
+ IMG_UINT32 *pui32DevID );
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVOpenDCDeviceKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_UINT32 ui32DeviceID,
+ IMG_HANDLE hDevCookie,
+ IMG_HANDLE *phDeviceKM);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVCloseDCDeviceKM(IMG_HANDLE hDeviceKM, IMG_BOOL bResManCallback);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVEnumDCFormatsKM(IMG_HANDLE hDeviceKM,
+ IMG_UINT32 *pui32Count,
+ DISPLAY_FORMAT *psFormat);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVEnumDCDimsKM(IMG_HANDLE hDeviceKM,
+ DISPLAY_FORMAT *psFormat,
+ IMG_UINT32 *pui32Count,
+ DISPLAY_DIMS *psDim);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVGetDCSystemBufferKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE *phBuffer);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVGetDCInfoKM(IMG_HANDLE hDeviceKM,
+ DISPLAY_INFO *psDisplayInfo);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVCreateDCSwapChainKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDeviceKM,
+ IMG_UINT32 ui32Flags,
+ DISPLAY_SURF_ATTRIBUTES *psDstSurfAttrib,
+ DISPLAY_SURF_ATTRIBUTES *psSrcSurfAttrib,
+ IMG_UINT32 ui32BufferCount,
+ IMG_UINT32 ui32OEMFlags,
+ IMG_HANDLE *phSwapChain,
+ IMG_UINT32 *pui32SwapChainID);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVDestroyDCSwapChainKM(IMG_HANDLE hSwapChain);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetDCDstRectKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChain,
+ IMG_RECT *psRect);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetDCSrcRectKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChain,
+ IMG_RECT *psRect);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetDCDstColourKeyKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChain,
+ IMG_UINT32 ui32CKColour);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetDCSrcColourKeyKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChain,
+ IMG_UINT32 ui32CKColour);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVGetDCBuffersKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChain,
+ IMG_UINT32 *pui32BufferCount,
+ IMG_HANDLE *phBuffer,
+ IMG_SYS_PHYADDR *psPhyAddr);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSwapToDCBufferKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hBuffer,
+ IMG_UINT32 ui32SwapInterval,
+ IMG_HANDLE hPrivateTag,
+ IMG_UINT32 ui32ClipRectCount,
+ IMG_RECT *psClipRect);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSwapToDCBuffer2KM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hBuffer,
+ IMG_UINT32 ui32SwapInterval,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfos,
+ PVRSRV_KERNEL_SYNC_INFO **ppsSyncInfos,
+ IMG_UINT32 ui32NumMemSyncInfos,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSwapToDCSystemKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChain);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVOpenBCDeviceKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_UINT32 ui32DeviceID,
+ IMG_HANDLE hDevCookie,
+ IMG_HANDLE *phDeviceKM);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVCloseBCDeviceKM(IMG_HANDLE hDeviceKM, IMG_BOOL bResManCallback);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVGetBCInfoKM(IMG_HANDLE hDeviceKM,
+ BUFFER_INFO *psBufferInfo);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVGetBCBufferKM(IMG_HANDLE hDeviceKM,
+ IMG_UINT32 ui32BufferIndex,
+ IMG_HANDLE *phBuffer);
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceClassMemoryKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevMemContext,
+ IMG_HANDLE hDeviceClassBuffer,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfo,
+ IMG_HANDLE *phOSMapInfo);
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVChangeDeviceMemoryAttributesKM(IMG_HANDLE hKernelMemInfo,
+ IMG_UINT32 ui32Attribs);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceClassMemoryKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetFreeDeviceMemKM(IMG_UINT32 ui32Flags,
+ IMG_SIZE_T *pui32Total,
+ IMG_SIZE_T *pui32Free,
+ IMG_SIZE_T *pui32LargestBlock);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocSyncInfoKM(IMG_HANDLE hDevCookie,
+ IMG_HANDLE hDevMemContext,
+ PVRSRV_KERNEL_SYNC_INFO **ppsKernelSyncInfo);
+IMG_IMPORT
+IMG_VOID IMG_CALLCONV PVRSRVAcquireSyncInfoKM(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo);
+IMG_IMPORT
+IMG_VOID IMG_CALLCONV PVRSRVReleaseSyncInfoKM(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo);
+
+IMG_IMPORT
+#if defined (SUPPORT_SID_INTERFACE)
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO_KM *psMiscInfo);
+#else
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo);
+#endif
+
+IMG_IMPORT PVRSRV_ERROR
+PVRSRVAllocSharedSysMemoryKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_UINT32 ui32Flags,
+ IMG_SIZE_T ui32Size,
+ PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfo);
+
+IMG_IMPORT PVRSRV_ERROR
+PVRSRVFreeSharedSysMemoryKM(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo);
+
+IMG_IMPORT PVRSRV_ERROR
+PVRSRVDissociateMemFromResmanKM(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/pvr/pvr_debug.c b/drivers/gpu/pvr/pvr_debug.c
new file mode 100644
index 0000000..9f0016f
--- /dev/null
+++ b/drivers/gpu/pvr/pvr_debug.c
@@ -0,0 +1,453 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#endif
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <linux/kernel.h>
+#include <linux/hardirq.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <stdarg.h>
+#include "img_types.h"
+#include "servicesext.h"
+#include "pvr_debug.h"
+#include "srvkm.h"
+#include "proc.h"
+#include "mutex.h"
+#include "linkage.h"
+#include "pvr_uaccess.h"
+
+#if !defined(CONFIG_PREEMPT)
+#define PVR_DEBUG_ALWAYS_USE_SPINLOCK
+#endif
+
+static IMG_BOOL VBAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz,
+ const IMG_CHAR* pszFormat, va_list VArgs)
+ IMG_FORMAT_PRINTF(3, 0);
+
+
+#if defined(PVRSRV_NEED_PVR_DPF)
+
+#define PVR_MAX_FILEPATH_LEN 256
+
+static IMG_BOOL BAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz,
+ const IMG_CHAR *pszFormat, ...)
+ IMG_FORMAT_PRINTF(3, 4);
+
+IMG_UINT32 gPVRDebugLevel =
+ (DBGPRIV_FATAL | DBGPRIV_ERROR | DBGPRIV_WARNING);
+
+#endif
+
+#define PVR_MAX_MSG_LEN PVR_MAX_DEBUG_MESSAGE_LEN
+
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
+static IMG_CHAR gszBufferNonIRQ[PVR_MAX_MSG_LEN + 1];
+#endif
+
+static IMG_CHAR gszBufferIRQ[PVR_MAX_MSG_LEN + 1];
+
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
+static PVRSRV_LINUX_MUTEX gsDebugMutexNonIRQ;
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39))
+
+static spinlock_t gsDebugLockIRQ = SPIN_LOCK_UNLOCKED;
+#else
+static DEFINE_SPINLOCK(gsDebugLockIRQ);
+#endif
+
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
+#if !defined (USE_SPIN_LOCK)
+#define USE_SPIN_LOCK (in_interrupt() || !preemptible())
+#endif
+#endif
+
+static inline void GetBufferLock(unsigned long *pulLockFlags)
+{
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
+ if (USE_SPIN_LOCK)
+#endif
+ {
+ spin_lock_irqsave(&gsDebugLockIRQ, *pulLockFlags);
+ }
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
+ else
+ {
+ LinuxLockMutex(&gsDebugMutexNonIRQ);
+ }
+#endif
+}
+
+static inline void ReleaseBufferLock(unsigned long ulLockFlags)
+{
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
+ if (USE_SPIN_LOCK)
+#endif
+ {
+ spin_unlock_irqrestore(&gsDebugLockIRQ, ulLockFlags);
+ }
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
+ else
+ {
+ LinuxUnLockMutex(&gsDebugMutexNonIRQ);
+ }
+#endif
+}
+
+static inline void SelectBuffer(IMG_CHAR **ppszBuf, IMG_UINT32 *pui32BufSiz)
+{
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
+ if (USE_SPIN_LOCK)
+#endif
+ {
+ *ppszBuf = gszBufferIRQ;
+ *pui32BufSiz = sizeof(gszBufferIRQ);
+ }
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
+ else
+ {
+ *ppszBuf = gszBufferNonIRQ;
+ *pui32BufSiz = sizeof(gszBufferNonIRQ);
+ }
+#endif
+}
+
+static IMG_BOOL VBAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz, const IMG_CHAR* pszFormat, va_list VArgs)
+{
+ IMG_UINT32 ui32Used;
+ IMG_UINT32 ui32Space;
+ IMG_INT32 i32Len;
+
+ ui32Used = strlen(pszBuf);
+ BUG_ON(ui32Used >= ui32BufSiz);
+ ui32Space = ui32BufSiz - ui32Used;
+
+ i32Len = vsnprintf(&pszBuf[ui32Used], ui32Space, pszFormat, VArgs);
+ pszBuf[ui32BufSiz - 1] = 0;
+
+
+ return (i32Len < 0 || i32Len >= (IMG_INT32)ui32Space) ? IMG_TRUE : IMG_FALSE;
+}
+
+IMG_VOID PVRDPFInit(IMG_VOID)
+{
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
+ LinuxInitMutex(&gsDebugMutexNonIRQ);
+#endif
+}
+
+IMG_VOID PVRSRVReleasePrintf(const IMG_CHAR *pszFormat, ...)
+{
+ va_list vaArgs;
+ unsigned long ulLockFlags = 0;
+ IMG_CHAR *pszBuf;
+ IMG_UINT32 ui32BufSiz;
+
+ SelectBuffer(&pszBuf, &ui32BufSiz);
+
+ va_start(vaArgs, pszFormat);
+
+ GetBufferLock(&ulLockFlags);
+ strncpy (pszBuf, "PVR_K: ", (ui32BufSiz -1));
+
+ if (VBAppend(pszBuf, ui32BufSiz, pszFormat, vaArgs))
+ {
+ printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf);
+ }
+ else
+ {
+ printk(KERN_INFO "%s\n", pszBuf);
+ }
+
+ ReleaseBufferLock(ulLockFlags);
+ va_end(vaArgs);
+
+}
+
+#if defined(PVRSRV_NEED_PVR_ASSERT)
+
+IMG_VOID PVRSRVDebugAssertFail(const IMG_CHAR* pszFile, IMG_UINT32 uLine)
+{
+ PVRSRVDebugPrintf(DBGPRIV_FATAL, pszFile, uLine, "Debug assertion failed!");
+ BUG();
+}
+
+#endif
+
+#if defined(PVRSRV_NEED_PVR_TRACE)
+
+IMG_VOID PVRSRVTrace(const IMG_CHAR* pszFormat, ...)
+{
+ va_list VArgs;
+ unsigned long ulLockFlags = 0;
+ IMG_CHAR *pszBuf;
+ IMG_UINT32 ui32BufSiz;
+
+ SelectBuffer(&pszBuf, &ui32BufSiz);
+
+ va_start(VArgs, pszFormat);
+
+ GetBufferLock(&ulLockFlags);
+
+ strncpy(pszBuf, "PVR: ", (ui32BufSiz -1));
+
+ if (VBAppend(pszBuf, ui32BufSiz, pszFormat, VArgs))
+ {
+ printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf);
+ }
+ else
+ {
+ printk(KERN_INFO "%s\n", pszBuf);
+ }
+
+ ReleaseBufferLock(ulLockFlags);
+
+ va_end(VArgs);
+}
+
+#endif
+
+#if defined(PVRSRV_NEED_PVR_DPF)
+
+static IMG_BOOL BAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz, const IMG_CHAR *pszFormat, ...)
+{
+ va_list VArgs;
+ IMG_BOOL bTrunc;
+
+ va_start (VArgs, pszFormat);
+
+ bTrunc = VBAppend(pszBuf, ui32BufSiz, pszFormat, VArgs);
+
+ va_end (VArgs);
+
+ return bTrunc;
+}
+
+IMG_VOID PVRSRVDebugPrintf (
+ IMG_UINT32 ui32DebugLevel,
+ const IMG_CHAR* pszFullFileName,
+ IMG_UINT32 ui32Line,
+ const IMG_CHAR* pszFormat,
+ ...
+ )
+{
+ IMG_BOOL bTrace;
+ const IMG_CHAR *pszFileName = pszFullFileName;
+ IMG_CHAR *pszLeafName;
+
+
+ bTrace = (IMG_BOOL)(ui32DebugLevel & DBGPRIV_CALLTRACE) ? IMG_TRUE : IMG_FALSE;
+
+ if (gPVRDebugLevel & ui32DebugLevel)
+ {
+ va_list vaArgs;
+ unsigned long ulLockFlags = 0;
+ IMG_CHAR *pszBuf;
+ IMG_UINT32 ui32BufSiz;
+
+ SelectBuffer(&pszBuf, &ui32BufSiz);
+
+ va_start(vaArgs, pszFormat);
+
+ GetBufferLock(&ulLockFlags);
+
+
+ if (bTrace == IMG_FALSE)
+ {
+ switch(ui32DebugLevel)
+ {
+ case DBGPRIV_FATAL:
+ {
+ strncpy (pszBuf, "PVR_K:(Fatal): ", (ui32BufSiz -1));
+ break;
+ }
+ case DBGPRIV_ERROR:
+ {
+ strncpy (pszBuf, "PVR_K:(Error): ", (ui32BufSiz -1));
+ break;
+ }
+ case DBGPRIV_WARNING:
+ {
+ strncpy (pszBuf, "PVR_K:(Warning): ", (ui32BufSiz -1));
+ break;
+ }
+ case DBGPRIV_MESSAGE:
+ {
+ strncpy (pszBuf, "PVR_K:(Message): ", (ui32BufSiz -1));
+ break;
+ }
+ case DBGPRIV_VERBOSE:
+ {
+ strncpy (pszBuf, "PVR_K:(Verbose): ", (ui32BufSiz -1));
+ break;
+ }
+ default:
+ {
+ strncpy (pszBuf, "PVR_K:(Unknown message level)", (ui32BufSiz -1));
+ break;
+ }
+ }
+ }
+ else
+ {
+ strncpy (pszBuf, "PVR_K: ", (ui32BufSiz -1));
+ }
+
+ if (VBAppend(pszBuf, ui32BufSiz, pszFormat, vaArgs))
+ {
+ printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf);
+ }
+ else
+ {
+
+ if (bTrace == IMG_FALSE)
+ {
+#ifdef DEBUG_LOG_PATH_TRUNCATE
+
+ static IMG_CHAR szFileNameRewrite[PVR_MAX_FILEPATH_LEN];
+
+ IMG_CHAR* pszTruncIter;
+ IMG_CHAR* pszTruncBackInter;
+
+
+ if (strlen(pszFullFileName) > strlen(DEBUG_LOG_PATH_TRUNCATE)+1)
+ pszFileName = pszFullFileName + strlen(DEBUG_LOG_PATH_TRUNCATE)+1;
+
+
+ strncpy(szFileNameRewrite, pszFileName,PVR_MAX_FILEPATH_LEN);
+
+ if(strlen(szFileNameRewrite) == PVR_MAX_FILEPATH_LEN-1) {
+ IMG_CHAR szTruncateMassage[] = "FILENAME TRUNCATED";
+ strcpy(szFileNameRewrite + (PVR_MAX_FILEPATH_LEN - 1 - strlen(szTruncateMassage)), szTruncateMassage);
+ }
+
+ pszTruncIter = szFileNameRewrite;
+ while(*pszTruncIter++ != 0)
+ {
+ IMG_CHAR* pszNextStartPoint;
+
+ if(
+ !( ( *pszTruncIter == '/' && (pszTruncIter-4 >= szFileNameRewrite) ) &&
+ ( *(pszTruncIter-1) == '.') &&
+ ( *(pszTruncIter-2) == '.') &&
+ ( *(pszTruncIter-3) == '/') )
+ ) continue;
+
+
+ pszTruncBackInter = pszTruncIter - 3;
+ while(*(--pszTruncBackInter) != '/')
+ {
+ if(pszTruncBackInter <= szFileNameRewrite) break;
+ }
+ pszNextStartPoint = pszTruncBackInter;
+
+
+ while(*pszTruncIter != 0)
+ {
+ *pszTruncBackInter++ = *pszTruncIter++;
+ }
+ *pszTruncBackInter = 0;
+
+
+ pszTruncIter = pszNextStartPoint;
+ }
+
+ pszFileName = szFileNameRewrite;
+
+ if(*pszFileName == '/') pszFileName++;
+#endif
+
+#if !defined(__sh__)
+ pszLeafName = (IMG_CHAR *)strrchr (pszFileName, '\\');
+
+ if (pszLeafName)
+ {
+ pszFileName = pszLeafName;
+ }
+#endif
+
+ if (BAppend(pszBuf, ui32BufSiz, " [%u, %s]", ui32Line, pszFileName))
+ {
+ printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf);
+ }
+ else
+ {
+ printk(KERN_INFO "%s\n", pszBuf);
+ }
+ }
+ else
+ {
+ printk(KERN_INFO "%s\n", pszBuf);
+ }
+ }
+
+ ReleaseBufferLock(ulLockFlags);
+
+ va_end (vaArgs);
+ }
+}
+
+#endif
+
+#if defined(DEBUG)
+
+IMG_INT PVRDebugProcSetLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data)
+{
+#define _PROC_SET_BUFFER_SZ 2
+ IMG_CHAR data_buffer[_PROC_SET_BUFFER_SZ];
+
+ if (count != _PROC_SET_BUFFER_SZ)
+ {
+ return -EINVAL;
+ }
+ else
+ {
+ if (pvr_copy_from_user(data_buffer, buffer, count))
+ return -EINVAL;
+ if (data_buffer[count - 1] != '\n')
+ return -EINVAL;
+ gPVRDebugLevel = data_buffer[0] - '0';
+ }
+ return (count);
+}
+
+void ProcSeqShowDebugLevel(struct seq_file *sfile,void* el)
+{
+ seq_printf(sfile, "%u\n", gPVRDebugLevel);
+}
+
+#endif
diff --git a/drivers/gpu/pvr/pvr_debug.h b/drivers/gpu/pvr/pvr_debug.h
new file mode 100644
index 0000000..e66fdab
--- /dev/null
+++ b/drivers/gpu/pvr/pvr_debug.h
@@ -0,0 +1,184 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+******************************************************************************/
+
+#ifndef __PVR_DEBUG_H__
+#define __PVR_DEBUG_H__
+
+
+#include "img_types.h"
+
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define PVR_MAX_DEBUG_MESSAGE_LEN (512)
+
+/* These are privately used by pvr_debug, use the PVR_DBG_ defines instead */
+#define DBGPRIV_FATAL 0x01UL
+#define DBGPRIV_ERROR 0x02UL
+#define DBGPRIV_WARNING 0x04UL
+#define DBGPRIV_MESSAGE 0x08UL
+#define DBGPRIV_VERBOSE 0x10UL
+#define DBGPRIV_CALLTRACE 0x20UL
+#define DBGPRIV_ALLOC 0x40UL
+#define DBGPRIV_DBGDRV_MESSAGE 0x80UL
+
+#if !defined(PVRSRV_NEED_PVR_ASSERT) && defined(DEBUG)
+#define PVRSRV_NEED_PVR_ASSERT
+#endif
+
+#if defined(PVRSRV_NEED_PVR_ASSERT) && !defined(PVRSRV_NEED_PVR_DPF)
+#define PVRSRV_NEED_PVR_DPF
+#endif
+
+#if !defined(PVRSRV_NEED_PVR_TRACE) && (defined(DEBUG) || defined(TIMING))
+#define PVRSRV_NEED_PVR_TRACE
+#endif
+
+/* PVR_ASSERT() and PVR_DBG_BREAK handling */
+
+#if defined(PVRSRV_NEED_PVR_ASSERT)
+
+ #define PVR_ASSERT(EXPR) if (!(EXPR)) PVRSRVDebugAssertFail(__FILE__, __LINE__);
+
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVDebugAssertFail(const IMG_CHAR *pszFile,
+ IMG_UINT32 ui32Line);
+
+ #define PVR_DBG_BREAK PVRSRVDebugAssertFail(__FILE__, __LINE__)
+
+#else /* defined(PVRSRV_NEED_PVR_ASSERT) */
+
+ #define PVR_ASSERT(EXPR)
+ #define PVR_DBG_BREAK
+
+#endif /* defined(PVRSRV_NEED_PVR_ASSERT) */
+
+
+/* PVR_DPF() handling */
+
+#if defined(PVRSRV_NEED_PVR_DPF)
+
+#if defined(PVRSRV_NEW_PVR_DPF)
+
+ /* New logging mechanism */
+ #define PVR_DBG_FATAL DBGPRIV_FATAL
+ #define PVR_DBG_ERROR DBGPRIV_ERROR
+ #define PVR_DBG_WARNING DBGPRIV_WARNING
+ #define PVR_DBG_MESSAGE DBGPRIV_MESSAGE
+ #define PVR_DBG_VERBOSE DBGPRIV_VERBOSE
+ #define PVR_DBG_CALLTRACE DBGPRIV_CALLTRACE
+ #define PVR_DBG_ALLOC DBGPRIV_ALLOC
+ #define PVR_DBGDRIV_MESSAGE DBGPRIV_DBGDRV_MESSAGE
+
+ /* These levels are always on with PVRSRV_NEED_PVR_DPF */
+ #define __PVR_DPF_0x01UL(x...) PVRSRVDebugPrintf(DBGPRIV_FATAL, x)
+ #define __PVR_DPF_0x02UL(x...) PVRSRVDebugPrintf(DBGPRIV_ERROR, x)
+
+ /* Some are compiled out completely in release builds */
+#if defined(DEBUG)
+ #define __PVR_DPF_0x04UL(x...) PVRSRVDebugPrintf(DBGPRIV_WARNING, x)
+ #define __PVR_DPF_0x08UL(x...) PVRSRVDebugPrintf(DBGPRIV_MESSAGE, x)
+ #define __PVR_DPF_0x10UL(x...) PVRSRVDebugPrintf(DBGPRIV_VERBOSE, x)
+ #define __PVR_DPF_0x20UL(x...) PVRSRVDebugPrintf(DBGPRIV_CALLTRACE, x)
+ #define __PVR_DPF_0x40UL(x...) PVRSRVDebugPrintf(DBGPRIV_ALLOC, x)
+ #define __PVR_DPF_0x80UL(x...) PVRSRVDebugPrintf(DBGPRIV_DBGDRV_MESSAGE, x)
+#else
+ #define __PVR_DPF_0x04UL(x...)
+ #define __PVR_DPF_0x08UL(x...)
+ #define __PVR_DPF_0x10UL(x...)
+ #define __PVR_DPF_0x20UL(x...)
+ #define __PVR_DPF_0x40UL(x...)
+ #define __PVR_DPF_0x80UL(x...)
+#endif
+
+ /* Translate the different log levels to separate macros
+ * so they can each be compiled out.
+ */
+#if defined(DEBUG)
+ #define __PVR_DPF(lvl, x...) __PVR_DPF_ ## lvl (__FILE__, __LINE__, x)
+#else
+ #define __PVR_DPF(lvl, x...) __PVR_DPF_ ## lvl ("", 0, x)
+#endif
+
+ /* Get rid of the double bracketing */
+ #define PVR_DPF(x) __PVR_DPF x
+
+#else /* defined(PVRSRV_NEW_PVR_DPF) */
+
+ /* Old logging mechanism */
+ #define PVR_DBG_FATAL DBGPRIV_FATAL,__FILE__, __LINE__
+ #define PVR_DBG_ERROR DBGPRIV_ERROR,__FILE__, __LINE__
+ #define PVR_DBG_WARNING DBGPRIV_WARNING,__FILE__, __LINE__
+ #define PVR_DBG_MESSAGE DBGPRIV_MESSAGE,__FILE__, __LINE__
+ #define PVR_DBG_VERBOSE DBGPRIV_VERBOSE,__FILE__, __LINE__
+ #define PVR_DBG_CALLTRACE DBGPRIV_CALLTRACE,__FILE__, __LINE__
+ #define PVR_DBG_ALLOC DBGPRIV_ALLOC,__FILE__, __LINE__
+ #define PVR_DBGDRIV_MESSAGE DBGPRIV_DBGDRV_MESSAGE, "", 0
+
+ #define PVR_DPF(X) PVRSRVDebugPrintf X
+
+#endif /* defined(PVRSRV_NEW_PVR_DPF) */
+
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVDebugPrintf(IMG_UINT32 ui32DebugLevel,
+ const IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32Line,
+ const IMG_CHAR *pszFormat,
+ ...) IMG_FORMAT_PRINTF(4, 5);
+
+#else /* defined(PVRSRV_NEED_PVR_DPF) */
+
+ #define PVR_DPF(X)
+
+#endif /* defined(PVRSRV_NEED_PVR_DPF) */
+
+
+/* PVR_TRACE() handling */
+
+#if defined(PVRSRV_NEED_PVR_TRACE)
+
+ #define PVR_TRACE(X) PVRSRVTrace X
+
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVTrace(const IMG_CHAR* pszFormat, ... )
+ IMG_FORMAT_PRINTF(1, 2);
+
+#else /* defined(PVRSRV_NEED_PVR_TRACE) */
+
+ #define PVR_TRACE(X)
+
+#endif /* defined(PVRSRV_NEED_PVR_TRACE) */
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* __PVR_DEBUG_H__ */
+
+/******************************************************************************
+ End of file (pvr_debug.h)
+******************************************************************************/
+
diff --git a/drivers/gpu/pvr/pvr_uaccess.h b/drivers/gpu/pvr/pvr_uaccess.h
new file mode 100644
index 0000000..6e7f1d3
--- /dev/null
+++ b/drivers/gpu/pvr/pvr_uaccess.h
@@ -0,0 +1,71 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __PVR_UACCESS_H__
+#define __PVR_UACCESS_H__
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#endif
+
+#include <asm/uaccess.h>
+
+static inline unsigned long pvr_copy_to_user(void __user *pvTo, const void *pvFrom, unsigned long ulBytes)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
+ if (access_ok(VERIFY_WRITE, pvTo, ulBytes))
+ {
+ return __copy_to_user(pvTo, pvFrom, ulBytes);
+ }
+ return ulBytes;
+#else
+ return copy_to_user(pvTo, pvFrom, ulBytes);
+#endif
+}
+
+static inline unsigned long pvr_copy_from_user(void *pvTo, const void __user *pvFrom, unsigned long ulBytes)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
+
+ if (access_ok(VERIFY_READ, pvFrom, ulBytes))
+ {
+ return __copy_from_user(pvTo, pvFrom, ulBytes);
+ }
+ return ulBytes;
+#else
+ return copy_from_user(pvTo, pvFrom, ulBytes);
+#endif
+}
+
+#define pvr_put_user put_user
+#define pvr_get_user get_user
+
+#endif
+
diff --git a/drivers/gpu/pvr/pvrmmap.h b/drivers/gpu/pvr/pvrmmap.h
new file mode 100644
index 0000000..242d953
--- /dev/null
+++ b/drivers/gpu/pvr/pvrmmap.h
@@ -0,0 +1,44 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __PVRMMAP_H__
+#define __PVRMMAP_H__
+
+#if defined (SUPPORT_SID_INTERFACE)
+PVRSRV_ERROR PVRPMapKMem(IMG_HANDLE hModule, IMG_VOID **ppvLinAddr, IMG_VOID *pvLinAddrKM, IMG_SID *phMappingInfo, IMG_SID hMHandle);
+#else
+PVRSRV_ERROR PVRPMapKMem(IMG_HANDLE hModule, IMG_VOID **ppvLinAddr, IMG_VOID *pvLinAddrKM, IMG_HANDLE *phMappingInfo, IMG_HANDLE hMHandle);
+#endif
+
+
+#if defined (SUPPORT_SID_INTERFACE)
+IMG_BOOL PVRUnMapKMem(IMG_HANDLE hModule, IMG_SID hMappingInfo, IMG_SID hMHandle);
+#else
+IMG_BOOL PVRUnMapKMem(IMG_HANDLE hModule, IMG_HANDLE hMappingInfo, IMG_HANDLE hMHandle);
+#endif
+
+#endif
+
diff --git a/drivers/gpu/pvr/pvrmodule.h b/drivers/gpu/pvr/pvrmodule.h
new file mode 100644
index 0000000..3dd5845
--- /dev/null
+++ b/drivers/gpu/pvr/pvrmodule.h
@@ -0,0 +1,31 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef _PVRMODULE_H_
+#define _PVRMODULE_H_
+MODULE_AUTHOR("Imagination Technologies Ltd. <gpl-support@imgtec.com>");
+MODULE_LICENSE("GPL");
+#endif
diff --git a/drivers/gpu/pvr/pvrsrv.c b/drivers/gpu/pvr/pvrsrv.c
new file mode 100644
index 0000000..1b730f5
--- /dev/null
+++ b/drivers/gpu/pvr/pvrsrv.c
@@ -0,0 +1,1364 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "pvr_bridge_km.h"
+#include "handle.h"
+#include "perproc.h"
+#include "pdump_km.h"
+#include "deviceid.h"
+#include "ra.h"
+#if defined(TTRACE)
+#include "ttrace.h"
+#endif
+#include "perfkm.h"
+
+#include "pvrversion.h"
+
+#include "lists.h"
+
+IMG_UINT32 g_ui32InitFlags;
+
+#define INIT_DATA_ENABLE_PDUMPINIT 0x1U
+#define INIT_DATA_ENABLE_TTARCE 0x2U
+
+PVRSRV_ERROR AllocateDeviceID(SYS_DATA *psSysData, IMG_UINT32 *pui32DevID)
+{
+ SYS_DEVICE_ID* psDeviceWalker;
+ SYS_DEVICE_ID* psDeviceEnd;
+
+ psDeviceWalker = &psSysData->sDeviceID[0];
+ psDeviceEnd = psDeviceWalker + psSysData->ui32NumDevices;
+
+
+ while (psDeviceWalker < psDeviceEnd)
+ {
+ if (!psDeviceWalker->bInUse)
+ {
+ psDeviceWalker->bInUse = IMG_TRUE;
+ *pui32DevID = psDeviceWalker->uiID;
+ return PVRSRV_OK;
+ }
+ psDeviceWalker++;
+ }
+
+ PVR_DPF((PVR_DBG_ERROR,"AllocateDeviceID: No free and valid device IDs available!"));
+
+
+ PVR_ASSERT(psDeviceWalker < psDeviceEnd);
+
+ return PVRSRV_ERROR_NO_FREE_DEVICEIDS_AVALIABLE;
+}
+
+
+PVRSRV_ERROR FreeDeviceID(SYS_DATA *psSysData, IMG_UINT32 ui32DevID)
+{
+ SYS_DEVICE_ID* psDeviceWalker;
+ SYS_DEVICE_ID* psDeviceEnd;
+
+ psDeviceWalker = &psSysData->sDeviceID[0];
+ psDeviceEnd = psDeviceWalker + psSysData->ui32NumDevices;
+
+
+ while (psDeviceWalker < psDeviceEnd)
+ {
+
+ if (
+ (psDeviceWalker->uiID == ui32DevID) &&
+ (psDeviceWalker->bInUse)
+ )
+ {
+ psDeviceWalker->bInUse = IMG_FALSE;
+ return PVRSRV_OK;
+ }
+ psDeviceWalker++;
+ }
+
+ PVR_DPF((PVR_DBG_ERROR,"FreeDeviceID: no matching dev ID that is in use!"));
+
+
+ PVR_ASSERT(psDeviceWalker < psDeviceEnd);
+
+ return PVRSRV_ERROR_INVALID_DEVICEID;
+}
+
+
+#ifndef ReadHWReg
+IMG_EXPORT
+IMG_UINT32 ReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset)
+{
+ return *(volatile IMG_UINT32*)((IMG_UINTPTR_T)pvLinRegBaseAddr+ui32Offset);
+}
+#endif
+
+
+#ifndef WriteHWReg
+IMG_EXPORT
+IMG_VOID WriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value)
+{
+ PVR_DPF((PVR_DBG_MESSAGE,"WriteHWReg Base:%x, Offset: %x, Value %x",
+ (IMG_UINTPTR_T)pvLinRegBaseAddr,ui32Offset,ui32Value));
+
+ *(IMG_UINT32*)((IMG_UINTPTR_T)pvLinRegBaseAddr+ui32Offset) = ui32Value;
+}
+#endif
+
+
+#ifndef WriteHWRegs
+IMG_EXPORT
+IMG_VOID WriteHWRegs(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Count, PVRSRV_HWREG *psHWRegs)
+{
+ while (ui32Count)
+ {
+ WriteHWReg (pvLinRegBaseAddr, psHWRegs->ui32RegAddr, psHWRegs->ui32RegVal);
+ psHWRegs++;
+ ui32Count--;
+ }
+}
+#endif
+
+static IMG_VOID PVRSRVEnumerateDevicesKM_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+ IMG_UINT *pui32DevCount;
+ PVRSRV_DEVICE_IDENTIFIER **ppsDevIdList;
+
+ pui32DevCount = va_arg(va, IMG_UINT*);
+ ppsDevIdList = va_arg(va, PVRSRV_DEVICE_IDENTIFIER**);
+
+ if (psDeviceNode->sDevId.eDeviceType != PVRSRV_DEVICE_TYPE_EXT)
+ {
+ *(*ppsDevIdList) = psDeviceNode->sDevId;
+ (*ppsDevIdList)++;
+ (*pui32DevCount)++;
+ }
+}
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDevicesKM(IMG_UINT32 *pui32NumDevices,
+ PVRSRV_DEVICE_IDENTIFIER *psDevIdList)
+{
+ SYS_DATA *psSysData;
+ IMG_UINT32 i;
+
+ if (!pui32NumDevices || !psDevIdList)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumerateDevicesKM: Invalid params"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ SysAcquireData(&psSysData);
+
+
+
+ for (i=0; i<PVRSRV_MAX_DEVICES; i++)
+ {
+ psDevIdList[i].eDeviceType = PVRSRV_DEVICE_TYPE_UNKNOWN;
+ }
+
+
+ *pui32NumDevices = 0;
+
+
+
+
+
+ List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
+ &PVRSRVEnumerateDevicesKM_ForEachVaCb,
+ pui32NumDevices,
+ &psDevIdList);
+
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInit(PSYS_DATA psSysData)
+{
+ PVRSRV_ERROR eError;
+
+
+ eError = ResManInit();
+ if (eError != PVRSRV_OK)
+ {
+ goto Error;
+ }
+
+ eError = PVRSRVPerProcessDataInit();
+ if(eError != PVRSRV_OK)
+ {
+ goto Error;
+ }
+
+
+ eError = PVRSRVHandleInit();
+ if(eError != PVRSRV_OK)
+ {
+ goto Error;
+ }
+
+
+ eError = OSCreateResource(&psSysData->sPowerStateChangeResource);
+ if (eError != PVRSRV_OK)
+ {
+ goto Error;
+ }
+
+
+ psSysData->eCurrentPowerState = PVRSRV_SYS_POWER_STATE_D0;
+ psSysData->eFailedPowerState = PVRSRV_SYS_POWER_STATE_Unspecified;
+
+
+ if(OSAllocMem( PVRSRV_PAGEABLE_SELECT,
+ sizeof(PVRSRV_EVENTOBJECT) ,
+ (IMG_VOID **)&psSysData->psGlobalEventObject, 0,
+ "Event Object") != PVRSRV_OK)
+ {
+
+ goto Error;
+ }
+
+ if(OSEventObjectCreateKM("PVRSRV_GLOBAL_EVENTOBJECT", psSysData->psGlobalEventObject) != PVRSRV_OK)
+ {
+ goto Error;
+ }
+
+
+ psSysData->pfnHighResTimerCreate = OSFuncHighResTimerCreate;
+ psSysData->pfnHighResTimerGetus = OSFuncHighResTimerGetus;
+ psSysData->pfnHighResTimerDestroy = OSFuncHighResTimerDestroy;
+
+#if defined(TTRACE)
+ eError = PVRSRVTimeTraceInit();
+ if (eError != PVRSRV_OK)
+ goto Error;
+ g_ui32InitFlags |= INIT_DATA_ENABLE_TTARCE;
+#endif
+
+
+ PDUMPINIT();
+ g_ui32InitFlags |= INIT_DATA_ENABLE_PDUMPINIT;
+
+ PERFINIT();
+ return eError;
+
+Error:
+ PVRSRVDeInit(psSysData);
+ return eError;
+}
+
+
+
+IMG_VOID IMG_CALLCONV PVRSRVDeInit(PSYS_DATA psSysData)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_UNREFERENCED_PARAMETER(psSysData);
+
+ if (psSysData == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVHandleDeInit failed - invalid param"));
+ return;
+ }
+
+ PERFDEINIT();
+
+#if defined(TTRACE)
+
+ if ((g_ui32InitFlags & INIT_DATA_ENABLE_TTARCE) > 0)
+ {
+ PVRSRVTimeTraceDeinit();
+ }
+#endif
+
+ if( (g_ui32InitFlags & INIT_DATA_ENABLE_PDUMPINIT) > 0)
+ {
+ PDUMPDEINIT();
+ }
+
+
+ if(psSysData->psGlobalEventObject)
+ {
+ OSEventObjectDestroyKM(psSysData->psGlobalEventObject);
+ OSFreeMem( PVRSRV_PAGEABLE_SELECT,
+ sizeof(PVRSRV_EVENTOBJECT),
+ psSysData->psGlobalEventObject,
+ 0);
+ psSysData->psGlobalEventObject = IMG_NULL;
+ }
+
+ eError = PVRSRVHandleDeInit();
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVHandleDeInit failed"));
+ }
+
+ eError = PVRSRVPerProcessDataDeInit();
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVPerProcessDataDeInit failed"));
+ }
+
+ ResManDeInit();
+}
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVRegisterDevice(PSYS_DATA psSysData,
+ PVRSRV_ERROR (*pfnRegisterDevice)(PVRSRV_DEVICE_NODE*),
+ IMG_UINT32 ui32SOCInterruptBit,
+ IMG_UINT32 *pui32DeviceIndex)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+
+ if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DEVICE_NODE),
+ (IMG_VOID **)&psDeviceNode, IMG_NULL,
+ "Device Node") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to alloc memory for psDeviceNode"));
+ return (PVRSRV_ERROR_OUT_OF_MEMORY);
+ }
+ OSMemSet (psDeviceNode, 0, sizeof(PVRSRV_DEVICE_NODE));
+
+ eError = pfnRegisterDevice(psDeviceNode);
+ if (eError != PVRSRV_OK)
+ {
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL);
+
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to register device"));
+ return (PVRSRV_ERROR_DEVICE_REGISTER_FAILED);
+ }
+
+
+
+
+
+
+ psDeviceNode->ui32RefCount = 1;
+ psDeviceNode->psSysData = psSysData;
+ psDeviceNode->ui32SOCInterruptBit = ui32SOCInterruptBit;
+
+
+ AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex);
+
+
+ List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList, psDeviceNode);
+
+
+ *pui32DeviceIndex = psDeviceNode->sDevId.ui32DeviceIndex;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInitialiseDevice (IMG_UINT32 ui32DevIndex)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ SYS_DATA *psSysData;
+ PVRSRV_ERROR eError;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVInitialiseDevice"));
+
+ SysAcquireData(&psSysData);
+
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE*)
+ List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ &MatchDeviceKM_AnyVaCb,
+ ui32DevIndex,
+ IMG_TRUE);
+ if(!psDeviceNode)
+ {
+
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVInitialiseDevice: requested device is not present"));
+ return PVRSRV_ERROR_INIT_FAILURE;
+ }
+ PVR_ASSERT (psDeviceNode->ui32RefCount > 0);
+
+
+
+ eError = PVRSRVResManConnect(IMG_NULL, &psDeviceNode->hResManContext);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVInitialiseDevice: Failed PVRSRVResManConnect call"));
+ return eError;
+ }
+
+
+ if(psDeviceNode->pfnInitDevice != IMG_NULL)
+ {
+ eError = psDeviceNode->pfnInitDevice(psDeviceNode);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVInitialiseDevice: Failed InitDevice call"));
+ return eError;
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR PVRSRVFinaliseSystem_SetPowerState_AnyCb(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVRSRV_ERROR eError;
+ eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE_DEFAULT,
+ KERNEL_ID, IMG_FALSE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVSetDevicePowerStateKM call (device index: %d)", psDeviceNode->sDevId.ui32DeviceIndex));
+ }
+ return eError;
+}
+
+static PVRSRV_ERROR PVRSRVFinaliseSystem_CompatCheck_AnyCb(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVRSRV_ERROR eError;
+ eError = PVRSRVDevInitCompatCheck(psDeviceNode);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVDevInitCompatCheck call (device index: %d)", psDeviceNode->sDevId.ui32DeviceIndex));
+ }
+ return eError;
+}
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFinaliseSystem(IMG_BOOL bInitSuccessful)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_ERROR eError;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVFinaliseSystem"));
+
+ SysAcquireData(&psSysData);
+
+ if (bInitSuccessful)
+ {
+ eError = SysFinalise();
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: SysFinalise failed (%d)", eError));
+ return eError;
+ }
+
+
+ eError = List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any(psSysData->psDeviceNodeList,
+ &PVRSRVFinaliseSystem_SetPowerState_AnyCb);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+
+ eError = List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any(psSysData->psDeviceNodeList,
+ &PVRSRVFinaliseSystem_CompatCheck_AnyCb);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+
+
+
+
+
+ PDUMPENDINITPHASE();
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PVRSRVDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+
+ if (psDeviceNode->pfnInitDeviceCompatCheck)
+ return psDeviceNode->pfnInitDeviceCompatCheck(psDeviceNode);
+ else
+ return PVRSRV_OK;
+}
+
+static IMG_VOID * PVRSRVAcquireDeviceDataKM_Match_AnyVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+ PVRSRV_DEVICE_TYPE eDeviceType;
+ IMG_UINT32 ui32DevIndex;
+
+ eDeviceType = va_arg(va, PVRSRV_DEVICE_TYPE);
+ ui32DevIndex = va_arg(va, IMG_UINT32);
+
+ if ((eDeviceType != PVRSRV_DEVICE_TYPE_UNKNOWN &&
+ psDeviceNode->sDevId.eDeviceType == eDeviceType) ||
+ (eDeviceType == PVRSRV_DEVICE_TYPE_UNKNOWN &&
+ psDeviceNode->sDevId.ui32DeviceIndex == ui32DevIndex))
+ {
+ return psDeviceNode;
+ }
+ else
+ {
+ return IMG_NULL;
+ }
+}
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAcquireDeviceDataKM (IMG_UINT32 ui32DevIndex,
+ PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_HANDLE *phDevCookie)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ SYS_DATA *psSysData;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVAcquireDeviceDataKM"));
+
+ SysAcquireData(&psSysData);
+
+
+ psDeviceNode = List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ &PVRSRVAcquireDeviceDataKM_Match_AnyVaCb,
+ eDeviceType,
+ ui32DevIndex);
+
+
+ if (!psDeviceNode)
+ {
+
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVAcquireDeviceDataKM: requested device is not present"));
+ return PVRSRV_ERROR_INIT_FAILURE;
+ }
+
+ PVR_ASSERT (psDeviceNode->ui32RefCount > 0);
+
+
+ if (phDevCookie)
+ {
+ *phDevCookie = (IMG_HANDLE)psDeviceNode;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDeinitialiseDevice(IMG_UINT32 ui32DevIndex)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ SYS_DATA *psSysData;
+ PVRSRV_ERROR eError;
+
+ SysAcquireData(&psSysData);
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE*)
+ List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ &MatchDeviceKM_AnyVaCb,
+ ui32DevIndex,
+ IMG_TRUE);
+
+ if (!psDeviceNode)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: requested device %d is not present", ui32DevIndex));
+ return PVRSRV_ERROR_DEVICEID_NOT_FOUND;
+ }
+
+
+
+ eError = PVRSRVSetDevicePowerStateKM(ui32DevIndex,
+ PVRSRV_DEV_POWER_STATE_OFF,
+ KERNEL_ID,
+ IMG_FALSE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed PVRSRVSetDevicePowerStateKM call"));
+ return eError;
+ }
+
+
+
+ eError = ResManFreeResByCriteria(psDeviceNode->hResManContext,
+ RESMAN_CRITERIA_RESTYPE,
+ RESMAN_TYPE_DEVICEMEM_ALLOCATION,
+ IMG_NULL, 0);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed ResManFreeResByCriteria call"));
+ return eError;
+ }
+
+
+
+ if(psDeviceNode->pfnDeInitDevice != IMG_NULL)
+ {
+ eError = psDeviceNode->pfnDeInitDevice(psDeviceNode);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed DeInitDevice call"));
+ return eError;
+ }
+ }
+
+
+
+ PVRSRVResManDisconnect(psDeviceNode->hResManContext, IMG_TRUE);
+ psDeviceNode->hResManContext = IMG_NULL;
+
+
+ List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode);
+
+
+ (IMG_VOID)FreeDeviceID(psSysData, ui32DevIndex);
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL);
+
+
+ return (PVRSRV_OK);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PollForValueKM (volatile IMG_UINT32* pui32LinMemAddr,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ IMG_UINT32 ui32Timeoutus,
+ IMG_UINT32 ui32PollPeriodus,
+ IMG_BOOL bAllowPreemption)
+{
+#if defined (EMULATOR)
+ {
+ PVR_UNREFERENCED_PARAMETER(bAllowPreemption);
+ #if !defined(__linux__)
+ PVR_UNREFERENCED_PARAMETER(ui32PollPeriodus);
+ #endif
+
+
+
+ do
+ {
+ if((*pui32LinMemAddr & ui32Mask) == ui32Value)
+ {
+ return PVRSRV_OK;
+ }
+
+ #if defined(__linux__)
+ OSWaitus(ui32PollPeriodus);
+ #else
+ OSReleaseThreadQuanta();
+ #endif
+
+ } while (ui32Timeoutus);
+ }
+#else
+ {
+ IMG_UINT32 ui32ActualValue = 0xFFFFFFFFU;
+
+ if (bAllowPreemption)
+ {
+ PVR_ASSERT(ui32PollPeriodus >= 1000);
+ }
+
+
+ LOOP_UNTIL_TIMEOUT(ui32Timeoutus)
+ {
+ ui32ActualValue = (*pui32LinMemAddr & ui32Mask);
+ if(ui32ActualValue == ui32Value)
+ {
+ return PVRSRV_OK;
+ }
+
+ if (bAllowPreemption)
+ {
+ OSSleepms(ui32PollPeriodus / 1000);
+ }
+ else
+ {
+ OSWaitus(ui32PollPeriodus);
+ }
+ } END_LOOP_UNTIL_TIMEOUT();
+
+ PVR_DPF((PVR_DBG_ERROR,"PollForValueKM: Timeout. Expected 0x%x but found 0x%x (mask 0x%x).",
+ ui32Value, ui32ActualValue, ui32Mask));
+ }
+#endif
+
+ return PVRSRV_ERROR_TIMEOUT;
+}
+
+
+static IMG_VOID PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb(BM_HEAP *psBMHeap, va_list va)
+{
+ IMG_CHAR **ppszStr;
+ IMG_UINT32 *pui32StrLen;
+ IMG_UINT32 ui32Mode;
+ PVRSRV_ERROR (*pfnGetStats)(RA_ARENA *, IMG_CHAR **, IMG_UINT32 *);
+
+ ppszStr = va_arg(va, IMG_CHAR**);
+ pui32StrLen = va_arg(va, IMG_UINT32*);
+ ui32Mode = va_arg(va, IMG_UINT32);
+
+
+ switch(ui32Mode)
+ {
+ case PVRSRV_MISC_INFO_MEMSTATS_PRESENT:
+ pfnGetStats = &RA_GetStats;
+ break;
+ case PVRSRV_MISC_INFO_FREEMEM_PRESENT:
+ pfnGetStats = &RA_GetStatsFreeMem;
+ break;
+ default:
+ return;
+ }
+
+ if(psBMHeap->pImportArena)
+ {
+ pfnGetStats(psBMHeap->pImportArena,
+ ppszStr,
+ pui32StrLen);
+ }
+
+ if(psBMHeap->pVMArena)
+ {
+ pfnGetStats(psBMHeap->pVMArena,
+ ppszStr,
+ pui32StrLen);
+ }
+}
+
+static PVRSRV_ERROR PVRSRVGetMiscInfoKM_BMContext_AnyVaCb(BM_CONTEXT *psBMContext, va_list va)
+{
+
+ IMG_UINT32 *pui32StrLen;
+ IMG_INT32 *pi32Count;
+ IMG_CHAR **ppszStr;
+ IMG_UINT32 ui32Mode;
+
+ pui32StrLen = va_arg(va, IMG_UINT32*);
+ pi32Count = va_arg(va, IMG_INT32*);
+ ppszStr = va_arg(va, IMG_CHAR**);
+ ui32Mode = va_arg(va, IMG_UINT32);
+
+ CHECK_SPACE(*pui32StrLen);
+ *pi32Count = OSSNPrintf(*ppszStr, 100, "\nApplication Context (hDevMemContext) %p:\n",
+ (IMG_HANDLE)psBMContext);
+ UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen);
+
+ List_BM_HEAP_ForEach_va(psBMContext->psBMHeap,
+ &PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb,
+ ppszStr,
+ pui32StrLen,
+ ui32Mode);
+ return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR PVRSRVGetMiscInfoKM_Device_AnyVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+ IMG_UINT32 *pui32StrLen;
+ IMG_INT32 *pi32Count;
+ IMG_CHAR **ppszStr;
+ IMG_UINT32 ui32Mode;
+
+ pui32StrLen = va_arg(va, IMG_UINT32*);
+ pi32Count = va_arg(va, IMG_INT32*);
+ ppszStr = va_arg(va, IMG_CHAR**);
+ ui32Mode = va_arg(va, IMG_UINT32);
+
+ CHECK_SPACE(*pui32StrLen);
+ *pi32Count = OSSNPrintf(*ppszStr, 100, "\n\nDevice Type %d:\n", psDeviceNode->sDevId.eDeviceType);
+ UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen);
+
+
+ if(psDeviceNode->sDevMemoryInfo.pBMKernelContext)
+ {
+ CHECK_SPACE(*pui32StrLen);
+ *pi32Count = OSSNPrintf(*ppszStr, 100, "\nKernel Context:\n");
+ UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen);
+
+ List_BM_HEAP_ForEach_va(psDeviceNode->sDevMemoryInfo.pBMKernelContext->psBMHeap,
+ &PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb,
+ ppszStr,
+ pui32StrLen,
+ ui32Mode);
+ }
+
+
+ return List_BM_CONTEXT_PVRSRV_ERROR_Any_va(psDeviceNode->sDevMemoryInfo.pBMContext,
+ &PVRSRVGetMiscInfoKM_BMContext_AnyVaCb,
+ pui32StrLen,
+ pi32Count,
+ ppszStr,
+ ui32Mode);
+}
+
+
+IMG_EXPORT
+#if defined (SUPPORT_SID_INTERFACE)
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO_KM *psMiscInfo)
+#else
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo)
+#endif
+{
+ SYS_DATA *psSysData;
+
+ if(!psMiscInfo)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psMiscInfo->ui32StatePresent = 0;
+
+
+ if(psMiscInfo->ui32StateRequest & ~(PVRSRV_MISC_INFO_TIMER_PRESENT
+ |PVRSRV_MISC_INFO_CLOCKGATE_PRESENT
+ |PVRSRV_MISC_INFO_MEMSTATS_PRESENT
+ |PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT
+ |PVRSRV_MISC_INFO_DDKVERSION_PRESENT
+ |PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT
+ |PVRSRV_MISC_INFO_RESET_PRESENT
+ |PVRSRV_MISC_INFO_FREEMEM_PRESENT
+ |PVRSRV_MISC_INFO_GET_REF_COUNT_PRESENT))
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid state request flags"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ SysAcquireData(&psSysData);
+
+
+ if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_TIMER_PRESENT) != 0UL) &&
+ (psSysData->pvSOCTimerRegisterKM != IMG_NULL))
+ {
+ psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_TIMER_PRESENT;
+ psMiscInfo->pvSOCTimerRegisterKM = psSysData->pvSOCTimerRegisterKM;
+ psMiscInfo->hSOCTimerRegisterOSMemHandle = psSysData->hSOCTimerRegisterOSMemHandle;
+ }
+ else
+ {
+ psMiscInfo->pvSOCTimerRegisterKM = IMG_NULL;
+ psMiscInfo->hSOCTimerRegisterOSMemHandle = IMG_NULL;
+ }
+
+
+ if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CLOCKGATE_PRESENT) != 0UL) &&
+ (psSysData->pvSOCClockGateRegsBase != IMG_NULL))
+ {
+ psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_CLOCKGATE_PRESENT;
+ psMiscInfo->pvSOCClockGateRegs = psSysData->pvSOCClockGateRegsBase;
+ psMiscInfo->ui32SOCClockGateRegsSize = psSysData->ui32SOCClockGateRegsSize;
+ }
+
+
+ if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0UL) &&
+ (psMiscInfo->pszMemoryStr != IMG_NULL))
+ {
+ RA_ARENA **ppArena;
+ IMG_CHAR *pszStr;
+ IMG_UINT32 ui32StrLen;
+ IMG_INT32 i32Count;
+
+ pszStr = psMiscInfo->pszMemoryStr;
+ ui32StrLen = psMiscInfo->ui32MemoryStrLen;
+
+ psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_MEMSTATS_PRESENT;
+
+
+ ppArena = &psSysData->apsLocalDevMemArena[0];
+ while(*ppArena)
+ {
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "\nLocal Backing Store:\n");
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ RA_GetStats(*ppArena,
+ &pszStr,
+ &ui32StrLen);
+
+ ppArena++;
+ }
+
+
+
+ List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList,
+ &PVRSRVGetMiscInfoKM_Device_AnyVaCb,
+ &ui32StrLen,
+ &i32Count,
+ &pszStr,
+ PVRSRV_MISC_INFO_MEMSTATS_PRESENT);
+
+
+ i32Count = OSSNPrintf(pszStr, 100, "\n");
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+ }
+
+
+ if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_FREEMEM_PRESENT) != 0)
+ && psMiscInfo->pszMemoryStr)
+ {
+ IMG_CHAR *pszStr;
+ IMG_UINT32 ui32StrLen;
+ IMG_INT32 i32Count;
+
+ pszStr = psMiscInfo->pszMemoryStr;
+ ui32StrLen = psMiscInfo->ui32MemoryStrLen;
+
+ psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_FREEMEM_PRESENT;
+
+
+ List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList,
+ &PVRSRVGetMiscInfoKM_Device_AnyVaCb,
+ &ui32StrLen,
+ &i32Count,
+ &pszStr,
+ PVRSRV_MISC_INFO_FREEMEM_PRESENT);
+
+ i32Count = OSSNPrintf(pszStr, 100, "\n");
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+ }
+
+ if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT) != 0UL) &&
+ (psSysData->psGlobalEventObject != IMG_NULL))
+ {
+ psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT;
+ psMiscInfo->sGlobalEventObject = *psSysData->psGlobalEventObject;
+ }
+
+
+
+ if (((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0UL)
+ && ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) == 0UL)
+ && (psMiscInfo->pszMemoryStr != IMG_NULL))
+ {
+ IMG_CHAR *pszStr;
+ IMG_UINT32 ui32StrLen;
+ IMG_UINT32 ui32LenStrPerNum = 12;
+ IMG_INT32 i32Count;
+ IMG_INT i;
+ psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_DDKVERSION_PRESENT;
+
+
+ psMiscInfo->aui32DDKVersion[0] = PVRVERSION_MAJ;
+ psMiscInfo->aui32DDKVersion[1] = PVRVERSION_MIN;
+ psMiscInfo->aui32DDKVersion[2] = PVRVERSION_BUILD_HI;
+ psMiscInfo->aui32DDKVersion[3] = PVRVERSION_BUILD_LO;
+
+ pszStr = psMiscInfo->pszMemoryStr;
+ ui32StrLen = psMiscInfo->ui32MemoryStrLen;
+
+ for (i=0; i<4; i++)
+ {
+ if (ui32StrLen < ui32LenStrPerNum)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ i32Count = OSSNPrintf(pszStr, ui32LenStrPerNum, "%u", psMiscInfo->aui32DDKVersion[i]);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+ if (i != 3)
+ {
+ i32Count = OSSNPrintf(pszStr, 2, ".");
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+ }
+ }
+ }
+
+ if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT) != 0UL)
+ {
+ psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT;
+
+ if(psMiscInfo->sCacheOpCtl.bDeferOp)
+ {
+
+ psSysData->ePendingCacheOpType = psMiscInfo->sCacheOpCtl.eCacheOpType;
+ }
+ else
+ {
+#if defined (SUPPORT_SID_INTERFACE)
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = psMiscInfo->sCacheOpCtl.psKernelMemInfo;
+
+ if(!psMiscInfo->sCacheOpCtl.psKernelMemInfo)
+#else
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ PVRSRV_PER_PROCESS_DATA *psPerProc;
+
+ if(!psMiscInfo->sCacheOpCtl.u.psKernelMemInfo)
+#endif
+ {
+ PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetMiscInfoKM: "
+ "Ignoring non-deferred cache op with no meminfo"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if(psSysData->ePendingCacheOpType != PVRSRV_MISC_INFO_CPUCACHEOP_NONE)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetMiscInfoKM: "
+ "Deferred cache op is pending. It is unlikely you want "
+ "to combine deferred cache ops with immediate ones"));
+ }
+
+#if defined (SUPPORT_SID_INTERFACE)
+ PVR_DBG_BREAK
+#else
+
+ psPerProc = PVRSRVFindPerProcessData();
+
+ if(PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_PVOID *)&psKernelMemInfo,
+ psMiscInfo->sCacheOpCtl.u.psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetMiscInfoKM: "
+ "Can't find kernel meminfo"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+#endif
+
+ if(psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH)
+ {
+ if(!OSFlushCPUCacheRangeKM(psKernelMemInfo->sMemBlk.hOSMemHandle,
+ psMiscInfo->sCacheOpCtl.pvBaseVAddr,
+ psMiscInfo->sCacheOpCtl.ui32Length))
+ {
+ return PVRSRV_ERROR_CACHEOP_FAILED;
+ }
+ }
+ else if(psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN)
+ {
+ if(!OSCleanCPUCacheRangeKM(psKernelMemInfo->sMemBlk.hOSMemHandle,
+ psMiscInfo->sCacheOpCtl.pvBaseVAddr,
+ psMiscInfo->sCacheOpCtl.ui32Length))
+ {
+ return PVRSRV_ERROR_CACHEOP_FAILED;
+ }
+ }
+ }
+ }
+
+ if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GET_REF_COUNT_PRESENT) != 0UL)
+ {
+#if !defined (SUPPORT_SID_INTERFACE)
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ PVRSRV_PER_PROCESS_DATA *psPerProc;
+#endif
+
+ psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GET_REF_COUNT_PRESENT;
+
+#if defined (SUPPORT_SID_INTERFACE)
+ PVR_DBG_BREAK
+#else
+
+ psPerProc = PVRSRVFindPerProcessData();
+
+ if(PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_PVOID *)&psKernelMemInfo,
+ psMiscInfo->sGetRefCountCtl.u.psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetMiscInfoKM: "
+ "Can't find kernel meminfo"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psMiscInfo->sGetRefCountCtl.ui32RefCount = psKernelMemInfo->ui32RefCount;
+#endif
+ }
+
+#if defined(PVRSRV_RESET_ON_HWTIMEOUT)
+ if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_RESET_PRESENT) != 0UL)
+ {
+ PVR_LOG(("User requested OS reset"));
+ OSPanic();
+ }
+#endif
+
+ return PVRSRV_OK;
+}
+
+
+IMG_BOOL IMG_CALLCONV PVRSRVDeviceLISR(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ SYS_DATA *psSysData;
+ IMG_BOOL bStatus = IMG_FALSE;
+ IMG_UINT32 ui32InterruptSource;
+
+ if(!psDeviceNode)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVDeviceLISR: Invalid params\n"));
+ goto out;
+ }
+ psSysData = psDeviceNode->psSysData;
+
+
+ ui32InterruptSource = SysGetInterruptSource(psSysData, psDeviceNode);
+ if(ui32InterruptSource & psDeviceNode->ui32SOCInterruptBit)
+ {
+ if(psDeviceNode->pfnDeviceISR != IMG_NULL)
+ {
+ bStatus = (*psDeviceNode->pfnDeviceISR)(psDeviceNode->pvISRData);
+ }
+
+ SysClearInterrupts(psSysData, psDeviceNode->ui32SOCInterruptBit);
+ }
+
+out:
+ return bStatus;
+}
+
+static IMG_VOID PVRSRVSystemLISR_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+
+ IMG_BOOL *pbStatus;
+ IMG_UINT32 *pui32InterruptSource;
+ IMG_UINT32 *pui32ClearInterrupts;
+
+ pbStatus = va_arg(va, IMG_BOOL*);
+ pui32InterruptSource = va_arg(va, IMG_UINT32*);
+ pui32ClearInterrupts = va_arg(va, IMG_UINT32*);
+
+
+ if(psDeviceNode->pfnDeviceISR != IMG_NULL)
+ {
+ if(*pui32InterruptSource & psDeviceNode->ui32SOCInterruptBit)
+ {
+ if((*psDeviceNode->pfnDeviceISR)(psDeviceNode->pvISRData))
+ {
+
+ *pbStatus = IMG_TRUE;
+ }
+
+ *pui32ClearInterrupts |= psDeviceNode->ui32SOCInterruptBit;
+ }
+ }
+}
+
+IMG_BOOL IMG_CALLCONV PVRSRVSystemLISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = pvSysData;
+ IMG_BOOL bStatus = IMG_FALSE;
+ IMG_UINT32 ui32InterruptSource;
+ IMG_UINT32 ui32ClearInterrupts = 0;
+ if(!psSysData)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSystemLISR: Invalid params\n"));
+ }
+ else
+ {
+
+ ui32InterruptSource = SysGetInterruptSource(psSysData, IMG_NULL);
+
+
+ if(ui32InterruptSource)
+ {
+
+ List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
+ &PVRSRVSystemLISR_ForEachVaCb,
+ &bStatus,
+ &ui32InterruptSource,
+ &ui32ClearInterrupts);
+
+ SysClearInterrupts(psSysData, ui32ClearInterrupts);
+ }
+ }
+ return bStatus;
+}
+
+
+static IMG_VOID PVRSRVMISR_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ if(psDeviceNode->pfnDeviceMISR != IMG_NULL)
+ {
+ (*psDeviceNode->pfnDeviceMISR)(psDeviceNode->pvISRData);
+ }
+}
+
+IMG_VOID IMG_CALLCONV PVRSRVMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = pvSysData;
+ if(!psSysData)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVMISR: Invalid params\n"));
+ return;
+ }
+
+
+ List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList,
+ &PVRSRVMISR_ForEachCb);
+
+
+ if (PVRSRVProcessQueues(IMG_FALSE) == PVRSRV_ERROR_PROCESSING_BLOCKED)
+ {
+ PVRSRVProcessQueues(IMG_FALSE);
+ }
+
+
+ if (psSysData->psGlobalEventObject)
+ {
+ IMG_HANDLE hOSEventKM = psSysData->psGlobalEventObject->hOSEventKM;
+ if(hOSEventKM)
+ {
+ OSEventObjectSignalKM(hOSEventKM);
+ }
+ }
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVProcessConnect(IMG_UINT32 ui32PID, IMG_UINT32 ui32Flags)
+{
+ return PVRSRVPerProcessDataConnect(ui32PID, ui32Flags);
+}
+
+
+IMG_EXPORT
+IMG_VOID IMG_CALLCONV PVRSRVProcessDisconnect(IMG_UINT32 ui32PID)
+{
+ PVRSRVPerProcessDataDisconnect(ui32PID);
+}
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSaveRestoreLiveSegments(IMG_HANDLE hArena, IMG_PBYTE pbyBuffer,
+ IMG_SIZE_T *puiBufSize, IMG_BOOL bSave)
+{
+ IMG_SIZE_T uiBytesSaved = 0;
+ IMG_PVOID pvLocalMemCPUVAddr;
+ RA_SEGMENT_DETAILS sSegDetails;
+
+ if (hArena == IMG_NULL)
+ {
+ return (PVRSRV_ERROR_INVALID_PARAMS);
+ }
+
+ sSegDetails.uiSize = 0;
+ sSegDetails.sCpuPhyAddr.uiAddr = 0;
+ sSegDetails.hSegment = 0;
+
+
+ while (RA_GetNextLiveSegment(hArena, &sSegDetails))
+ {
+ if (pbyBuffer == IMG_NULL)
+ {
+
+ uiBytesSaved += sizeof(sSegDetails.uiSize) + sSegDetails.uiSize;
+ }
+ else
+ {
+ if ((uiBytesSaved + sizeof(sSegDetails.uiSize) + sSegDetails.uiSize) > *puiBufSize)
+ {
+ return (PVRSRV_ERROR_OUT_OF_MEMORY);
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVSaveRestoreLiveSegments: Base %08x size %08x", sSegDetails.sCpuPhyAddr.uiAddr, sSegDetails.uiSize));
+
+
+ pvLocalMemCPUVAddr = OSMapPhysToLin(sSegDetails.sCpuPhyAddr,
+ sSegDetails.uiSize,
+ PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+ IMG_NULL);
+ if (pvLocalMemCPUVAddr == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSaveRestoreLiveSegments: Failed to map local memory to host"));
+ return (PVRSRV_ERROR_OUT_OF_MEMORY);
+ }
+
+ if (bSave)
+ {
+
+ OSMemCopy(pbyBuffer, &sSegDetails.uiSize, sizeof(sSegDetails.uiSize));
+ pbyBuffer += sizeof(sSegDetails.uiSize);
+
+ OSMemCopy(pbyBuffer, pvLocalMemCPUVAddr, sSegDetails.uiSize);
+ pbyBuffer += sSegDetails.uiSize;
+ }
+ else
+ {
+ IMG_UINT32 uiSize;
+
+ OSMemCopy(&uiSize, pbyBuffer, sizeof(sSegDetails.uiSize));
+
+ if (uiSize != sSegDetails.uiSize)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSaveRestoreLiveSegments: Segment size error"));
+ }
+ else
+ {
+ pbyBuffer += sizeof(sSegDetails.uiSize);
+
+ OSMemCopy(pvLocalMemCPUVAddr, pbyBuffer, sSegDetails.uiSize);
+ pbyBuffer += sSegDetails.uiSize;
+ }
+ }
+
+
+ uiBytesSaved += sizeof(sSegDetails.uiSize) + sSegDetails.uiSize;
+
+ OSUnMapPhysToLin(pvLocalMemCPUVAddr,
+ sSegDetails.uiSize,
+ PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+ IMG_NULL);
+ }
+ }
+
+ if (pbyBuffer == IMG_NULL)
+ {
+ *puiBufSize = uiBytesSaved;
+ }
+
+ return (PVRSRV_OK);
+}
+
+
+IMG_EXPORT
+const IMG_CHAR *PVRSRVGetErrorStringKM(PVRSRV_ERROR eError)
+{
+
+#include "pvrsrv_errors.h"
+}
+
+static IMG_VOID PVRSRVCommandCompleteCallbacks_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ if(psDeviceNode->pfnDeviceCommandComplete != IMG_NULL)
+ {
+
+ (*psDeviceNode->pfnDeviceCommandComplete)(psDeviceNode);
+ }
+}
+
+IMG_VOID PVRSRVScheduleDeviceCallbacks(IMG_VOID)
+{
+ SYS_DATA *psSysData;
+ SysAcquireData(&psSysData);
+
+
+ List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList,
+ &PVRSRVCommandCompleteCallbacks_ForEachCb);
+}
+
+IMG_EXPORT
+IMG_VOID PVRSRVScheduleDevicesKM(IMG_VOID)
+{
+ PVRSRVScheduleDeviceCallbacks();
+}
+
diff --git a/drivers/gpu/pvr/pvrsrv_errors.h b/drivers/gpu/pvr/pvrsrv_errors.h
new file mode 100644
index 0000000..5474984
--- /dev/null
+++ b/drivers/gpu/pvr/pvrsrv_errors.h
@@ -0,0 +1,266 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#if !defined (__PVRSRV_ERRORS_H__)
+#define __PVRSRV_ERRORS_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+ switch (eError)
+ {
+ case PVRSRV_OK: return "No Errors";
+ case PVRSRV_ERROR_OUT_OF_MEMORY: return "PVRSRV_ERROR_OUT_OF_MEMORY - Unable to allocate required memory";
+ case PVRSRV_ERROR_TOO_FEW_BUFFERS: return "PVRSRV_ERROR_TOO_FEW_BUFFERS";
+ case PVRSRV_ERROR_INVALID_PARAMS: return "PVRSRV_ERROR_INVALID_PARAMS";
+ case PVRSRV_ERROR_INIT_FAILURE: return "PVRSRV_ERROR_INIT_FAILURE";
+ case PVRSRV_ERROR_CANT_REGISTER_CALLBACK: return "PVRSRV_ERROR_CANT_REGISTER_CALLBACK";
+ case PVRSRV_ERROR_INVALID_DEVICE: return "PVRSRV_ERROR_INVALID_DEVICE";
+ case PVRSRV_ERROR_NOT_OWNER: return "PVRSRV_ERROR_NOT_OWNER";
+ case PVRSRV_ERROR_BAD_MAPPING: return "PVRSRV_ERROR_BAD_MAPPING";
+ case PVRSRV_ERROR_TIMEOUT: return "PVRSRV_ERROR_TIMEOUT";
+ case PVRSRV_ERROR_FLIP_CHAIN_EXISTS: return "PVRSRV_ERROR_FLIP_CHAIN_EXISTS";
+ case PVRSRV_ERROR_INVALID_SWAPINTERVAL: return "PVRSRV_ERROR_INVALID_SWAPINTERVAL";
+ case PVRSRV_ERROR_SCENE_INVALID: return "PVRSRV_ERROR_SCENE_INVALID";
+ case PVRSRV_ERROR_STREAM_ERROR: return "PVRSRV_ERROR_STREAM_ERROR";
+ case PVRSRV_ERROR_FAILED_DEPENDENCIES: return "PVRSRV_ERROR_FAILED_DEPENDENCIES";
+ case PVRSRV_ERROR_CMD_NOT_PROCESSED: return "PVRSRV_ERROR_CMD_NOT_PROCESSED";
+ case PVRSRV_ERROR_CMD_TOO_BIG: return "PVRSRV_ERROR_CMD_TOO_BIG";
+ case PVRSRV_ERROR_DEVICE_REGISTER_FAILED: return "PVRSRV_ERROR_DEVICE_REGISTER_FAILED";
+ case PVRSRV_ERROR_TOOMANYBUFFERS: return "PVRSRV_ERROR_TOOMANYBUFFERS";
+ case PVRSRV_ERROR_NOT_SUPPORTED: return "PVRSRV_ERROR_NOT_SUPPORTED - fix";
+ case PVRSRV_ERROR_PROCESSING_BLOCKED: return "PVRSRV_ERROR_PROCESSING_BLOCKED";
+
+ case PVRSRV_ERROR_CANNOT_FLUSH_QUEUE: return "PVRSRV_ERROR_CANNOT_FLUSH_QUEUE";
+ case PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE: return "PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE";
+ case PVRSRV_ERROR_CANNOT_GET_RENDERDETAILS: return "PVRSRV_ERROR_CANNOT_GET_RENDERDETAILS";
+ case PVRSRV_ERROR_RETRY: return "PVRSRV_ERROR_RETRY";
+
+ case PVRSRV_ERROR_DDK_VERSION_MISMATCH: return "PVRSRV_ERROR_DDK_VERSION_MISMATCH";
+ case PVRSRV_ERROR_BUILD_MISMATCH: return "PVRSRV_ERROR_BUILD_MISMATCH";
+ case PVRSRV_ERROR_CORE_REVISION_MISMATCH: return "PVRSRV_ERROR_CORE_REVISION_MISMATCH";
+
+ case PVRSRV_ERROR_UPLOAD_TOO_BIG: return "PVRSRV_ERROR_UPLOAD_TOO_BIG";
+
+ case PVRSRV_ERROR_INVALID_FLAGS: return "PVRSRV_ERROR_INVALID_FLAGS";
+ case PVRSRV_ERROR_FAILED_TO_REGISTER_PROCESS: return "PVRSRV_ERROR_FAILED_TO_REGISTER_PROCESS";
+
+ case PVRSRV_ERROR_UNABLE_TO_LOAD_LIBRARY: return "PVRSRV_ERROR_UNABLE_TO_LOAD_LIBRARY";
+ case PVRSRV_ERROR_UNABLE_GET_FUNC_ADDR: return "PVRSRV_ERROR_UNABLE_GET_FUNC_ADDR";
+ case PVRSRV_ERROR_UNLOAD_LIBRARY_FAILED: return "PVRSRV_ERROR_UNLOAD_LIBRARY_FAILED";
+
+ case PVRSRV_ERROR_BRIDGE_CALL_FAILED: return "PVRSRV_ERROR_BRIDGE_CALL_FAILED";
+ case PVRSRV_ERROR_IOCTL_CALL_FAILED: return "PVRSRV_ERROR_IOCTL_CALL_FAILED";
+
+ case PVRSRV_ERROR_MMU_CONTEXT_NOT_FOUND: return "PVRSRV_ERROR_MMU_CONTEXT_NOT_FOUND";
+ case PVRSRV_ERROR_BUFFER_DEVICE_NOT_FOUND: return "PVRSRV_ERROR_BUFFER_DEVICE_NOT_FOUND";
+ case PVRSRV_ERROR_BUFFER_DEVICE_ALREADY_PRESENT:return "PVRSRV_ERROR_BUFFER_DEVICE_ALREADY_PRESENT";
+
+ case PVRSRV_ERROR_PCI_DEVICE_NOT_FOUND: return "PVRSRV_ERROR_PCI_DEVICE_NOT_FOUND";
+ case PVRSRV_ERROR_PCI_CALL_FAILED: return "PVRSRV_ERROR_PCI_CALL_FAILED";
+ case PVRSRV_ERROR_PCI_REGION_TOO_SMALL: return "PVRSRV_ERROR_PCI_REGION_TOO_SMALL";
+ case PVRSRV_ERROR_PCI_REGION_UNAVAILABLE: return "PVRSRV_ERROR_PCI_REGION_UNAVAILABLE";
+ case PVRSRV_ERROR_BAD_REGION_SIZE_MISMATCH: return "PVRSRV_ERROR_BAD_REGION_SIZE_MISMATCH";
+
+ case PVRSRV_ERROR_REGISTER_BASE_NOT_SET: return "PVRSRV_ERROR_REGISTER_BASE_NOT_SET";
+
+ case PVRSRV_ERROR_BM_BAD_SHAREMEM_HANDLE: return "PVRSRV_ERROR_BM_BAD_SHAREMEM_HANDLE";
+
+ case PVRSRV_ERROR_FAILED_TO_ALLOC_USER_MEM: return "PVRSRV_ERROR_FAILED_TO_ALLOC_USER_MEM";
+ case PVRSRV_ERROR_FAILED_TO_ALLOC_VP_MEMORY: return "PVRSRV_ERROR_FAILED_TO_ALLOC_VP_MEMORY";
+ case PVRSRV_ERROR_FAILED_TO_MAP_SHARED_PBDESC: return "PVRSRV_ERROR_FAILED_TO_MAP_SHARED_PBDESC";
+ case PVRSRV_ERROR_FAILED_TO_GET_PHYS_ADDR: return "PVRSRV_ERROR_FAILED_TO_GET_PHYS_ADDR";
+
+ case PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY: return "PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY";
+ case PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY: return "PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY";
+
+ case PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES: return "PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES";
+ case PVRSRV_ERROR_FAILED_TO_FREE_PAGES: return "PVRSRV_ERROR_FAILED_TO_FREE_PAGES";
+ case PVRSRV_ERROR_FAILED_TO_COPY_PAGES: return "PVRSRV_ERROR_FAILED_TO_COPY_PAGES";
+ case PVRSRV_ERROR_UNABLE_TO_LOCK_PAGES: return "PVRSRV_ERROR_UNABLE_TO_LOCK_PAGES";
+ case PVRSRV_ERROR_UNABLE_TO_UNLOCK_PAGES: return "PVRSRV_ERROR_UNABLE_TO_UNLOCK_PAGES";
+ case PVRSRV_ERROR_STILL_MAPPED: return "PVRSRV_ERROR_STILL_MAPPED";
+ case PVRSRV_ERROR_MAPPING_NOT_FOUND: return "PVRSRV_ERROR_MAPPING_NOT_FOUND";
+ case PVRSRV_ERROR_PHYS_ADDRESS_EXCEEDS_32BIT: return "PVRSRV_ERROR_PHYS_ADDRESS_EXCEEDS_32BIT";
+ case PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE: return "PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE";
+
+ case PVRSRV_ERROR_INVALID_SEGMENT_BLOCK: return "PVRSRV_ERROR_INVALID_SEGMENT_BLOCK";
+ case PVRSRV_ERROR_INVALID_SGXDEVDATA: return "PVRSRV_ERROR_INVALID_SGXDEVDATA";
+ case PVRSRV_ERROR_INVALID_DEVINFO: return "PVRSRV_ERROR_INVALID_DEVINFO";
+ case PVRSRV_ERROR_INVALID_MEMINFO: return "PVRSRV_ERROR_INVALID_MEMINFO";
+ case PVRSRV_ERROR_INVALID_MISCINFO: return "PVRSRV_ERROR_INVALID_MISCINFO";
+ case PVRSRV_ERROR_UNKNOWN_IOCTL: return "PVRSRV_ERROR_UNKNOWN_IOCTL";
+ case PVRSRV_ERROR_INVALID_CONTEXT: return "PVRSRV_ERROR_INVALID_CONTEXT";
+ case PVRSRV_ERROR_UNABLE_TO_DESTROY_CONTEXT: return "PVRSRV_ERROR_UNABLE_TO_DESTROY_CONTEXT";
+ case PVRSRV_ERROR_INVALID_HEAP: return "PVRSRV_ERROR_INVALID_HEAP";
+ case PVRSRV_ERROR_INVALID_KERNELINFO: return "PVRSRV_ERROR_INVALID_KERNELINFO";
+ case PVRSRV_ERROR_UNKNOWN_POWER_STATE: return "PVRSRV_ERROR_UNKNOWN_POWER_STATE";
+ case PVRSRV_ERROR_INVALID_HANDLE_TYPE: return "PVRSRV_ERROR_INVALID_HANDLE_TYPE";
+ case PVRSRV_ERROR_INVALID_WRAP_TYPE: return "PVRSRV_ERROR_INVALID_WRAP_TYPE";
+ case PVRSRV_ERROR_INVALID_PHYS_ADDR: return "PVRSRV_ERROR_INVALID_PHYS_ADDR";
+ case PVRSRV_ERROR_INVALID_CPU_ADDR: return "PVRSRV_ERROR_INVALID_CPU_ADDR";
+ case PVRSRV_ERROR_INVALID_HEAPINFO: return "PVRSRV_ERROR_INVALID_HEAPINFO";
+ case PVRSRV_ERROR_INVALID_PERPROC: return "PVRSRV_ERROR_INVALID_PERPROC";
+ case PVRSRV_ERROR_FAILED_TO_RETRIEVE_HEAPINFO: return "PVRSRV_ERROR_FAILED_TO_RETRIEVE_HEAPINFO";
+ case PVRSRV_ERROR_INVALID_MAP_REQUEST: return "PVRSRV_ERROR_INVALID_MAP_REQUEST";
+ case PVRSRV_ERROR_INVALID_UNMAP_REQUEST: return "PVRSRV_ERROR_INVALID_UNMAP_REQUEST";
+ case PVRSRV_ERROR_UNABLE_TO_FIND_MAPPING_HEAP: return "PVRSRV_ERROR_UNABLE_TO_FIND_MAPPING_HEAP";
+ case PVRSRV_ERROR_MAPPING_STILL_IN_USE: return "PVRSRV_ERROR_MAPPING_STILL_IN_USE";
+
+ case PVRSRV_ERROR_EXCEEDED_HW_LIMITS: return "PVRSRV_ERROR_EXCEEDED_HW_LIMITS";
+ case PVRSRV_ERROR_NO_STAGING_BUFFER_ALLOCATED: return "PVRSRV_ERROR_NO_STAGING_BUFFER_ALLOCATED";
+
+ case PVRSRV_ERROR_UNABLE_TO_CREATE_PERPROC_AREA:return "PVRSRV_ERROR_UNABLE_TO_CREATE_PERPROC_AREA";
+ case PVRSRV_ERROR_UNABLE_TO_CREATE_EVENT: return "PVRSRV_ERROR_UNABLE_TO_CREATE_EVENT";
+ case PVRSRV_ERROR_UNABLE_TO_ENABLE_EVENT: return "PVRSRV_ERROR_UNABLE_TO_ENABLE_EVENT";
+ case PVRSRV_ERROR_UNABLE_TO_REGISTER_EVENT: return "PVRSRV_ERROR_UNABLE_TO_REGISTER_EVENT";
+ case PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT: return "PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT";
+ case PVRSRV_ERROR_UNABLE_TO_CREATE_THREAD: return "PVRSRV_ERROR_UNABLE_TO_CREATE_THREAD";
+ case PVRSRV_ERROR_UNABLE_TO_CLOSE_THREAD: return "PVRSRV_ERROR_UNABLE_TO_CLOSE_THREAD";
+ case PVRSRV_ERROR_THREAD_READ_ERROR: return "PVRSRV_ERROR_THREAD_READ_ERROR";
+ case PVRSRV_ERROR_UNABLE_TO_REGISTER_ISR_HANDLER:return "PVRSRV_ERROR_UNABLE_TO_REGISTER_ISR_HANDLER";
+ case PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR: return "PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR";
+ case PVRSRV_ERROR_UNABLE_TO_UNINSTALL_ISR: return "PVRSRV_ERROR_UNABLE_TO_UNINSTALL_ISR";
+ case PVRSRV_ERROR_ISR_ALREADY_INSTALLED: return "PVRSRV_ERROR_ISR_ALREADY_INSTALLED";
+ case PVRSRV_ERROR_ISR_NOT_INSTALLED: return "PVRSRV_ERROR_ISR_NOT_INSTALLED";
+ case PVRSRV_ERROR_UNABLE_TO_INITIALISE_INTERRUPT:return "PVRSRV_ERROR_UNABLE_TO_INITIALISE_INTERRUPT";
+ case PVRSRV_ERROR_UNABLE_TO_RETRIEVE_INFO: return "PVRSRV_ERROR_UNABLE_TO_RETRIEVE_INFO";
+ case PVRSRV_ERROR_UNABLE_TO_DO_BACKWARDS_BLIT: return "PVRSRV_ERROR_UNABLE_TO_DO_BACKWARDS_BLIT";
+ case PVRSRV_ERROR_UNABLE_TO_CLOSE_SERVICES: return "PVRSRV_ERROR_UNABLE_TO_CLOSE_SERVICES";
+ case PVRSRV_ERROR_UNABLE_TO_REGISTER_CONTEXT: return "PVRSRV_ERROR_UNABLE_TO_REGISTER_CONTEXT";
+ case PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE: return "PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE";
+
+ case PVRSRV_ERROR_INVALID_CCB_COMMAND: return "PVRSRV_ERROR_INVALID_CCB_COMMAND";
+
+ case PVRSRV_ERROR_UNABLE_TO_LOCK_RESOURCE: return "PVRSRV_ERROR_UNABLE_TO_LOCK_RESOURCE";
+ case PVRSRV_ERROR_INVALID_LOCK_ID: return "PVRSRV_ERROR_INVALID_LOCK_ID";
+ case PVRSRV_ERROR_RESOURCE_NOT_LOCKED: return "PVRSRV_ERROR_RESOURCE_NOT_LOCKED";
+
+ case PVRSRV_ERROR_FLIP_FAILED: return "PVRSRV_ERROR_FLIP_FAILED";
+ case PVRSRV_ERROR_UNBLANK_DISPLAY_FAILED: return "PVRSRV_ERROR_UNBLANK_DISPLAY_FAILED";
+
+ case PVRSRV_ERROR_TIMEOUT_POLLING_FOR_VALUE: return "PVRSRV_ERROR_TIMEOUT_POLLING_FOR_VALUE";
+
+ case PVRSRV_ERROR_CREATE_RENDER_CONTEXT_FAILED: return "PVRSRV_ERROR_CREATE_RENDER_CONTEXT_FAILED";
+ case PVRSRV_ERROR_UNKNOWN_PRIMARY_FRAG: return "PVRSRV_ERROR_UNKNOWN_PRIMARY_FRAG";
+ case PVRSRV_ERROR_UNEXPECTED_SECONDARY_FRAG: return "PVRSRV_ERROR_UNEXPECTED_SECONDARY_FRAG";
+ case PVRSRV_ERROR_UNEXPECTED_PRIMARY_FRAG: return "PVRSRV_ERROR_UNEXPECTED_PRIMARY_FRAG";
+
+ case PVRSRV_ERROR_UNABLE_TO_INSERT_FENCE_ID: return "PVRSRV_ERROR_UNABLE_TO_INSERT_FENCE_ID";
+
+ case PVRSRV_ERROR_BLIT_SETUP_FAILED: return "PVRSRV_ERROR_BLIT_SETUP_FAILED";
+
+ case PVRSRV_ERROR_PDUMP_NOT_AVAILABLE: return "PVRSRV_ERROR_PDUMP_NOT_AVAILABLE";
+ case PVRSRV_ERROR_PDUMP_BUFFER_FULL: return "PVRSRV_ERROR_PDUMP_BUFFER_FULL";
+ case PVRSRV_ERROR_PDUMP_BUF_OVERFLOW: return "PVRSRV_ERROR_PDUMP_BUF_OVERFLOW";
+ case PVRSRV_ERROR_PDUMP_NOT_ACTIVE: return "PVRSRV_ERROR_PDUMP_NOT_ACTIVE";
+ case PVRSRV_ERROR_INCOMPLETE_LINE_OVERLAPS_PAGES:return "PVRSRV_ERROR_INCOMPLETE_LINE_OVERLAPS_PAGES";
+
+ case PVRSRV_ERROR_MUTEX_DESTROY_FAILED: return "PVRSRV_ERROR_MUTEX_DESTROY_FAILED";
+ case PVRSRV_ERROR_MUTEX_INTERRUPTIBLE_ERROR: return "PVRSRV_ERROR_MUTEX_INTERRUPTIBLE_ERROR";
+
+ case PVRSRV_ERROR_INSUFFICIENT_SCRIPT_SPACE: return "PVRSRV_ERROR_INSUFFICIENT_SCRIPT_SPACE";
+ case PVRSRV_ERROR_INSUFFICIENT_SPACE_FOR_COMMAND:return "PVRSRV_ERROR_INSUFFICIENT_SPACE_FOR_COMMAND";
+
+ case PVRSRV_ERROR_PROCESS_NOT_INITIALISED: return "PVRSRV_ERROR_PROCESS_NOT_INITIALISED";
+ case PVRSRV_ERROR_PROCESS_NOT_FOUND: return "PVRSRV_ERROR_PROCESS_NOT_FOUND";
+ case PVRSRV_ERROR_SRV_CONNECT_FAILED: return "PVRSRV_ERROR_SRV_CONNECT_FAILED";
+ case PVRSRV_ERROR_SRV_DISCONNECT_FAILED: return "PVRSRV_ERROR_SRV_DISCONNECT_FAILED";
+ case PVRSRV_ERROR_DEINT_PHASE_FAILED: return "PVRSRV_ERROR_DEINT_PHASE_FAILED";
+ case PVRSRV_ERROR_INIT2_PHASE_FAILED: return "PVRSRV_ERROR_INIT2_PHASE_FAILED";
+
+ case PVRSRV_ERROR_NO_DC_DEVICES_FOUND: return "PVRSRV_ERROR_NO_DC_DEVICES_FOUND";
+ case PVRSRV_ERROR_UNABLE_TO_OPEN_DC_DEVICE: return "PVRSRV_ERROR_UNABLE_TO_OPEN_DC_DEVICE";
+ case PVRSRV_ERROR_UNABLE_TO_REMOVE_DEVICE: return "PVRSRV_ERROR_UNABLE_TO_REMOVE_DEVICE";
+ case PVRSRV_ERROR_NO_DEVICEDATA_FOUND: return "PVRSRV_ERROR_NO_DEVICEDATA_FOUND";
+ case PVRSRV_ERROR_NO_DEVICENODE_FOUND: return "PVRSRV_ERROR_NO_DEVICENODE_FOUND";
+ case PVRSRV_ERROR_NO_CLIENTNODE_FOUND: return "PVRSRV_ERROR_NO_CLIENTNODE_FOUND";
+ case PVRSRV_ERROR_FAILED_TO_PROCESS_QUEUE: return "PVRSRV_ERROR_FAILED_TO_PROCESS_QUEUE";
+
+ case PVRSRV_ERROR_UNABLE_TO_INIT_TASK: return "PVRSRV_ERROR_UNABLE_TO_INIT_TASK";
+ case PVRSRV_ERROR_UNABLE_TO_SCHEDULE_TASK: return "PVRSRV_ERROR_UNABLE_TO_SCHEDULE_TASK";
+ case PVRSRV_ERROR_UNABLE_TO_KILL_TASK: return "PVRSRV_ERROR_UNABLE_TO_KILL_TASK";
+
+ case PVRSRV_ERROR_UNABLE_TO_ENABLE_TIMER: return "PVRSRV_ERROR_UNABLE_TO_ENABLE_TIMER";
+ case PVRSRV_ERROR_UNABLE_TO_DISABLE_TIMER: return "PVRSRV_ERROR_UNABLE_TO_DISABLE_TIMER";
+ case PVRSRV_ERROR_UNABLE_TO_REMOVE_TIMER: return "PVRSRV_ERROR_UNABLE_TO_REMOVE_TIMER";
+
+ case PVRSRV_ERROR_UNKNOWN_PIXEL_FORMAT: return "PVRSRV_ERROR_UNKNOWN_PIXEL_FORMAT";
+ case PVRSRV_ERROR_UNKNOWN_SCRIPT_OPERATION: return "PVRSRV_ERROR_UNKNOWN_SCRIPT_OPERATION";
+
+ case PVRSRV_ERROR_HANDLE_INDEX_OUT_OF_RANGE: return "PVRSRV_ERROR_HANDLE_INDEX_OUT_OF_RANGE";
+ case PVRSRV_ERROR_HANDLE_NOT_ALLOCATED: return "PVRSRV_ERROR_HANDLE_NOT_ALLOCATED";
+ case PVRSRV_ERROR_HANDLE_TYPE_MISMATCH: return "PVRSRV_ERROR_HANDLE_TYPE_MISMATCH";
+ case PVRSRV_ERROR_UNABLE_TO_ADD_HANDLE: return "PVRSRV_ERROR_UNABLE_TO_ADD_HANDLE";
+ case PVRSRV_ERROR_HANDLE_NOT_SHAREABLE: return "PVRSRV_ERROR_HANDLE_NOT_SHAREABLE";
+ case PVRSRV_ERROR_HANDLE_NOT_FOUND: return "PVRSRV_ERROR_HANDLE_NOT_FOUND";
+ case PVRSRV_ERROR_INVALID_SUBHANDLE: return "PVRSRV_ERROR_INVALID_SUBHANDLE";
+ case PVRSRV_ERROR_HANDLE_BATCH_IN_USE: return "PVRSRV_ERROR_HANDLE_BATCH_IN_USE";
+ case PVRSRV_ERROR_HANDLE_BATCH_COMMIT_FAILURE: return "PVRSRV_ERROR_HANDLE_BATCH_COMMIT_FAILURE";
+
+ case PVRSRV_ERROR_UNABLE_TO_CREATE_HASH_TABLE: return "PVRSRV_ERROR_UNABLE_TO_CREATE_HASH_TABLE";
+ case PVRSRV_ERROR_INSERT_HASH_TABLE_DATA_FAILED:return "PVRSRV_ERROR_INSERT_HASH_TABLE_DATA_FAILED";
+
+ case PVRSRV_ERROR_UNSUPPORTED_BACKING_STORE: return "PVRSRV_ERROR_UNSUPPORTED_BACKING_STORE";
+ case PVRSRV_ERROR_UNABLE_TO_DESTROY_BM_HEAP: return "PVRSRV_ERROR_UNABLE_TO_DESTROY_BM_HEAP";
+
+ case PVRSRV_ERROR_UNKNOWN_INIT_SERVER_STATE: return "PVRSRV_ERROR_UNKNOWN_INIT_SERVER_STATE";
+
+ case PVRSRV_ERROR_NO_FREE_DEVICEIDS_AVALIABLE: return "PVRSRV_ERROR_NO_FREE_DEVICEIDS_AVALIABLE";
+ case PVRSRV_ERROR_INVALID_DEVICEID: return "PVRSRV_ERROR_INVALID_DEVICEID";
+ case PVRSRV_ERROR_DEVICEID_NOT_FOUND: return "PVRSRV_ERROR_DEVICEID_NOT_FOUND";
+
+ case PVRSRV_ERROR_MEMORY_TEST_FAILED: return "PVRSRV_ERROR_MEMORY_TEST_FAILED";
+ case PVRSRV_ERROR_CPUPADDR_TEST_FAILED: return "PVRSRV_ERROR_CPUPADDR_TEST_FAILED";
+ case PVRSRV_ERROR_COPY_TEST_FAILED: return "PVRSRV_ERROR_COPY_TEST_FAILED";
+
+ case PVRSRV_ERROR_SEMAPHORE_NOT_INITIALISED: return "PVRSRV_ERROR_SEMAPHORE_NOT_INITIALISED";
+
+ case PVRSRV_ERROR_UNABLE_TO_RELEASE_CLOCK: return "PVRSRV_ERROR_UNABLE_TO_RELEASE_CLOCK";
+ case PVRSRV_ERROR_CLOCK_REQUEST_FAILED: return "PVRSRV_ERROR_CLOCK_REQUEST_FAILED";
+ case PVRSRV_ERROR_DISABLE_CLOCK_FAILURE: return "PVRSRV_ERROR_DISABLE_CLOCK_FAILURE";
+ case PVRSRV_ERROR_UNABLE_TO_SET_CLOCK_RATE: return "PVRSRV_ERROR_UNABLE_TO_SET_CLOCK_RATE";
+ case PVRSRV_ERROR_UNABLE_TO_ROUND_CLOCK_RATE: return "PVRSRV_ERROR_UNABLE_TO_ROUND_CLOCK_RATE";
+ case PVRSRV_ERROR_UNABLE_TO_ENABLE_CLOCK: return "PVRSRV_ERROR_UNABLE_TO_ENABLE_CLOCK";
+ case PVRSRV_ERROR_UNABLE_TO_GET_CLOCK: return "PVRSRV_ERROR_UNABLE_TO_GET_CLOCK";
+ case PVRSRV_ERROR_UNABLE_TO_GET_PARENT_CLOCK: return "PVRSRV_ERROR_UNABLE_TO_GET_PARENT_CLOCK";
+ case PVRSRV_ERROR_UNABLE_TO_GET_SYSTEM_CLOCK: return "PVRSRV_ERROR_UNABLE_TO_GET_SYSTEM_CLOCK";
+
+ case PVRSRV_ERROR_UNKNOWN_SGL_ERROR: return "PVRSRV_ERROR_UNKNOWN_SGL_ERROR";
+ case PVRSRV_ERROR_BAD_SYNC_STATE: return "PVRSRV_ERROR_BAD_SYNC_STATE";
+
+ case PVRSRV_ERROR_FORCE_I32: return "PVRSRV_ERROR_FORCE_I32";
+
+ default:
+ return "Unknown PVRSRV error number";
+ }
+
+#if defined (__cplusplus)
+}
+#endif
+#endif
+
diff --git a/drivers/gpu/pvr/pvrversion.h b/drivers/gpu/pvr/pvrversion.h
new file mode 100644
index 0000000..f282ad2
--- /dev/null
+++ b/drivers/gpu/pvr/pvrversion.h
@@ -0,0 +1,51 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+*/ /**************************************************************************/
+
+#ifndef _PVRVERSION_H_
+#define _PVRVERSION_H_
+
+#define PVR_STR(X) #X
+#define PVR_STR2(X) PVR_STR(X)
+
+#define PVRVERSION_MAJ 1
+#define PVRVERSION_MIN 8
+#define PVRVERSION_BRANCH 18
+
+#define PVRVERSION_FAMILY "sgxddk"
+#define PVRVERSION_BRANCHNAME "1.8.GOOGLENEXUS.ED945322"
+#define PVRVERSION_BUILD 2112805
+#define PVRVERSION_BSCONTROL "CustomerGoogle_Android_ogles1_ogles2_GPL"
+
+#define PVRVERSION_STRING "CustomerGoogle_Android_ogles1_ogles2_GPL sgxddk 18 1.8.GOOGLENEXUS.ED945322@" PVR_STR2(PVRVERSION_BUILD)
+#define PVRVERSION_STRING_SHORT "1.8.GOOGLENEXUS.ED945322@" PVR_STR2(PVRVERSION_BUILD)
+
+#define COPYRIGHT_TXT "Copyright (c) Imagination Technologies Ltd. All Rights Reserved."
+
+#define PVRVERSION_BUILD_HI 211
+#define PVRVERSION_BUILD_LO 2805
+#define PVRVERSION_STRING_NUMERIC PVR_STR2(PVRVERSION_MAJ) "." PVR_STR2(PVRVERSION_MIN) "." PVR_STR2(PVRVERSION_BUILD_HI) "." PVR_STR2(PVRVERSION_BUILD_LO)
+
+#endif /* _PVRVERSION_H_ */
diff --git a/drivers/gpu/pvr/queue.c b/drivers/gpu/pvr/queue.c
new file mode 100644
index 0000000..374bf7b
--- /dev/null
+++ b/drivers/gpu/pvr/queue.c
@@ -0,0 +1,1213 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "pvr_bridge_km.h"
+
+#include "lists.h"
+#include "ttrace.h"
+
+#if defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED)
+#define DC_NUM_COMMANDS_PER_TYPE 2
+#else
+#define DC_NUM_COMMANDS_PER_TYPE 1
+#endif
+
+typedef struct _DEVICE_COMMAND_DATA_
+{
+ PFN_CMD_PROC pfnCmdProc;
+ PCOMMAND_COMPLETE_DATA apsCmdCompleteData[DC_NUM_COMMANDS_PER_TYPE];
+ IMG_UINT32 ui32CCBOffset;
+ IMG_UINT32 ui32MaxDstSyncCount;
+ IMG_UINT32 ui32MaxSrcSyncCount;
+} DEVICE_COMMAND_DATA;
+
+
+#if defined(__linux__) && defined(__KERNEL__)
+
+#include "proc.h"
+
+void ProcSeqShowQueue(struct seq_file *sfile,void* el)
+{
+ PVRSRV_QUEUE_INFO *psQueue = (PVRSRV_QUEUE_INFO*)el;
+ IMG_INT cmds = 0;
+ IMG_SIZE_T ui32ReadOffset;
+ IMG_SIZE_T ui32WriteOffset;
+ PVRSRV_COMMAND *psCmd;
+
+ if(el == PVR_PROC_SEQ_START_TOKEN)
+ {
+ seq_printf( sfile,
+ "Command Queues\n"
+ "Queue CmdPtr Pid Command Size DevInd DSC SSC #Data ...\n");
+ return;
+ }
+
+ ui32ReadOffset = psQueue->ui32ReadOffset;
+ ui32WriteOffset = psQueue->ui32WriteOffset;
+
+ while (ui32ReadOffset != ui32WriteOffset)
+ {
+ psCmd= (PVRSRV_COMMAND *)((IMG_UINTPTR_T)psQueue->pvLinQueueKM + ui32ReadOffset);
+
+ seq_printf(sfile, "%x %x %5u %6u %3u %5u %2u %2u %3u \n",
+ (IMG_UINTPTR_T)psQueue,
+ (IMG_UINTPTR_T)psCmd,
+ psCmd->ui32ProcessID,
+ psCmd->CommandType,
+ psCmd->uCmdSize,
+ psCmd->ui32DevIndex,
+ psCmd->ui32DstSyncCount,
+ psCmd->ui32SrcSyncCount,
+ psCmd->uDataSize);
+ {
+ IMG_UINT32 i;
+ for (i = 0; i < psCmd->ui32SrcSyncCount; i++)
+ {
+ PVRSRV_SYNC_DATA *psSyncData = psCmd->psSrcSync[i].psKernelSyncInfoKM->psSyncData;
+ seq_printf(sfile, " Sync %u: ROP/ROC: 0x%x/0x%x WOP/WOC: 0x%x/0x%x ROC-VA: 0x%x WOC-VA: 0x%x\n",
+ i,
+ psCmd->psSrcSync[i].ui32ReadOps2Pending,
+ psSyncData->ui32ReadOps2Complete,
+ psCmd->psSrcSync[i].ui32WriteOpsPending,
+ psSyncData->ui32WriteOpsComplete,
+ psCmd->psSrcSync[i].psKernelSyncInfoKM->sReadOps2CompleteDevVAddr.uiAddr,
+ psCmd->psSrcSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr);
+ }
+ }
+
+
+ ui32ReadOffset += psCmd->uCmdSize;
+ ui32ReadOffset &= psQueue->ui32QueueSize - 1;
+ cmds++;
+ }
+
+ if (cmds == 0)
+ {
+ seq_printf(sfile, "%x <empty>\n", (IMG_UINTPTR_T)psQueue);
+ }
+}
+
+void* ProcSeqOff2ElementQueue(struct seq_file * sfile, loff_t off)
+{
+ PVRSRV_QUEUE_INFO *psQueue = IMG_NULL;
+ SYS_DATA *psSysData;
+
+ PVR_UNREFERENCED_PARAMETER(sfile);
+
+ if(!off)
+ {
+ return PVR_PROC_SEQ_START_TOKEN;
+ }
+
+
+ psSysData = SysAcquireDataNoCheck();
+ if (psSysData != IMG_NULL)
+ {
+ for (psQueue = psSysData->psQueueList; (((--off) > 0) && (psQueue != IMG_NULL)); psQueue = psQueue->psNextKM);
+ }
+
+ return psQueue;
+}
+#endif
+
+#define GET_SPACE_IN_CMDQ(psQueue) \
+ ((((psQueue)->ui32ReadOffset - (psQueue)->ui32WriteOffset) \
+ + ((psQueue)->ui32QueueSize - 1)) & ((psQueue)->ui32QueueSize - 1))
+
+#define UPDATE_QUEUE_WOFF(psQueue, ui32Size) \
+ (psQueue)->ui32WriteOffset = ((psQueue)->ui32WriteOffset + (ui32Size)) \
+ & ((psQueue)->ui32QueueSize - 1);
+
+#define SYNCOPS_STALE(ui32OpsComplete, ui32OpsPending) \
+ ((ui32OpsComplete) >= (ui32OpsPending))
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVGetWriteOpsPending)
+#endif
+static INLINE
+IMG_UINT32 PVRSRVGetWriteOpsPending(PVRSRV_KERNEL_SYNC_INFO *psSyncInfo, IMG_BOOL bIsReadOp)
+{
+ IMG_UINT32 ui32WriteOpsPending;
+
+ if(bIsReadOp)
+ {
+ ui32WriteOpsPending = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+ else
+ {
+
+
+
+ ui32WriteOpsPending = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ }
+
+ return ui32WriteOpsPending;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVGetReadOpsPending)
+#endif
+static INLINE
+IMG_UINT32 PVRSRVGetReadOpsPending(PVRSRV_KERNEL_SYNC_INFO *psSyncInfo, IMG_BOOL bIsReadOp)
+{
+ IMG_UINT32 ui32ReadOpsPending;
+
+ if(bIsReadOp)
+ {
+ ui32ReadOpsPending = psSyncInfo->psSyncData->ui32ReadOps2Pending++;
+ }
+ else
+ {
+ ui32ReadOpsPending = psSyncInfo->psSyncData->ui32ReadOps2Pending;
+ }
+
+ return ui32ReadOpsPending;
+}
+
+static IMG_VOID QueueDumpCmdComplete(COMMAND_COMPLETE_DATA *psCmdCompleteData,
+ IMG_UINT32 i,
+ IMG_BOOL bIsSrc)
+{
+ PVRSRV_SYNC_OBJECT *psSyncObject;
+
+ psSyncObject = bIsSrc ? psCmdCompleteData->psSrcSync : psCmdCompleteData->psDstSync;
+
+ if (psCmdCompleteData->bInUse)
+ {
+ PVR_LOG(("\t%s %u: ROC DevVAddr:0x%X ROP:0x%x ROC:0x%x, WOC DevVAddr:0x%X WOP:0x%x WOC:0x%x",
+ bIsSrc ? "SRC" : "DEST", i,
+ psSyncObject[i].psKernelSyncInfoKM->sReadOps2CompleteDevVAddr.uiAddr,
+ psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32ReadOps2Pending,
+ psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32ReadOps2Complete,
+ psSyncObject[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+ psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32WriteOpsPending,
+ psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32WriteOpsComplete))
+ }
+ else
+ {
+ PVR_LOG(("\t%s %u: (Not in use)", bIsSrc ? "SRC" : "DEST", i))
+ }
+}
+
+
+static IMG_VOID QueueDumpDebugInfo_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ if (psDeviceNode->sDevId.eDeviceClass == PVRSRV_DEVICE_CLASS_DISPLAY)
+ {
+ IMG_UINT32 ui32CmdCounter, ui32SyncCounter;
+ SYS_DATA *psSysData;
+ DEVICE_COMMAND_DATA *psDeviceCommandData;
+ PCOMMAND_COMPLETE_DATA psCmdCompleteData;
+
+ SysAcquireData(&psSysData);
+
+ psDeviceCommandData = psSysData->apsDeviceCommandData[psDeviceNode->sDevId.ui32DeviceIndex];
+
+ if (psDeviceCommandData != IMG_NULL)
+ {
+ for (ui32CmdCounter = 0; ui32CmdCounter < DC_NUM_COMMANDS_PER_TYPE; ui32CmdCounter++)
+ {
+ psCmdCompleteData = psDeviceCommandData[DC_FLIP_COMMAND].apsCmdCompleteData[ui32CmdCounter];
+
+ PVR_LOG(("Flip Command Complete Data %u for display device %u:",
+ ui32CmdCounter, psDeviceNode->sDevId.ui32DeviceIndex))
+
+ for (ui32SyncCounter = 0;
+ ui32SyncCounter < psCmdCompleteData->ui32SrcSyncCount;
+ ui32SyncCounter++)
+ {
+ QueueDumpCmdComplete(psCmdCompleteData, ui32SyncCounter, IMG_TRUE);
+ }
+
+ for (ui32SyncCounter = 0;
+ ui32SyncCounter < psCmdCompleteData->ui32DstSyncCount;
+ ui32SyncCounter++)
+ {
+ QueueDumpCmdComplete(psCmdCompleteData, ui32SyncCounter, IMG_FALSE);
+ }
+ }
+ }
+ else
+ {
+ PVR_LOG(("There is no Command Complete Data for display device %u", psDeviceNode->sDevId.ui32DeviceIndex))
+ }
+ }
+}
+
+
+IMG_VOID QueueDumpDebugInfo(IMG_VOID)
+{
+ SYS_DATA *psSysData;
+ SysAcquireData(&psSysData);
+ List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList, &QueueDumpDebugInfo_ForEachCb);
+}
+
+
+static IMG_SIZE_T NearestPower2(IMG_SIZE_T ui32Value)
+{
+ IMG_SIZE_T ui32Temp, ui32Result = 1;
+
+ if(!ui32Value)
+ return 0;
+
+ ui32Temp = ui32Value - 1;
+ while(ui32Temp)
+ {
+ ui32Result <<= 1;
+ ui32Temp >>= 1;
+ }
+
+ return ui32Result;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateCommandQueueKM(IMG_SIZE_T ui32QueueSize,
+ PVRSRV_QUEUE_INFO **ppsQueueInfo)
+{
+ PVRSRV_QUEUE_INFO *psQueueInfo;
+ IMG_SIZE_T ui32Power2QueueSize = NearestPower2(ui32QueueSize);
+ SYS_DATA *psSysData;
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hMemBlock;
+
+ SysAcquireData(&psSysData);
+
+
+ eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_QUEUE_INFO),
+ (IMG_VOID **)&psQueueInfo, &hMemBlock,
+ "Queue Info");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateCommandQueueKM: Failed to alloc queue struct"));
+ goto ErrorExit;
+ }
+ OSMemSet(psQueueInfo, 0, sizeof(PVRSRV_QUEUE_INFO));
+
+ psQueueInfo->hMemBlock[0] = hMemBlock;
+ psQueueInfo->ui32ProcessID = OSGetCurrentProcessIDKM();
+
+
+ eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ ui32Power2QueueSize + PVRSRV_MAX_CMD_SIZE,
+ &psQueueInfo->pvLinQueueKM, &hMemBlock,
+ "Command Queue");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateCommandQueueKM: Failed to alloc queue buffer"));
+ goto ErrorExit;
+ }
+
+ psQueueInfo->hMemBlock[1] = hMemBlock;
+ psQueueInfo->pvLinQueueUM = psQueueInfo->pvLinQueueKM;
+
+
+ PVR_ASSERT(psQueueInfo->ui32ReadOffset == 0);
+ PVR_ASSERT(psQueueInfo->ui32WriteOffset == 0);
+
+ psQueueInfo->ui32QueueSize = ui32Power2QueueSize;
+
+
+ if (psSysData->psQueueList == IMG_NULL)
+ {
+ eError = OSCreateResource(&psSysData->sQProcessResource);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+ }
+
+
+ eError = OSLockResource(&psSysData->sQProcessResource,
+ KERNEL_ID);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+
+ psQueueInfo->psNextKM = psSysData->psQueueList;
+ psSysData->psQueueList = psQueueInfo;
+
+ eError = OSUnlockResource(&psSysData->sQProcessResource, KERNEL_ID);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+
+ *ppsQueueInfo = psQueueInfo;
+
+ return PVRSRV_OK;
+
+ErrorExit:
+
+ if(psQueueInfo)
+ {
+ if(psQueueInfo->pvLinQueueKM)
+ {
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ psQueueInfo->ui32QueueSize,
+ psQueueInfo->pvLinQueueKM,
+ psQueueInfo->hMemBlock[1]);
+ psQueueInfo->pvLinQueueKM = IMG_NULL;
+ }
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_QUEUE_INFO),
+ psQueueInfo,
+ psQueueInfo->hMemBlock[0]);
+
+ }
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyCommandQueueKM(PVRSRV_QUEUE_INFO *psQueueInfo)
+{
+ PVRSRV_QUEUE_INFO *psQueue;
+ SYS_DATA *psSysData;
+ PVRSRV_ERROR eError;
+ IMG_BOOL bTimeout = IMG_TRUE;
+
+ SysAcquireData(&psSysData);
+
+ psQueue = psSysData->psQueueList;
+
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ if(psQueueInfo->ui32ReadOffset == psQueueInfo->ui32WriteOffset)
+ {
+ bTimeout = IMG_FALSE;
+ break;
+ }
+ OSSleepms(1);
+ } END_LOOP_UNTIL_TIMEOUT();
+
+ if (bTimeout)
+ {
+
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDestroyCommandQueueKM : Failed to empty queue"));
+ eError = PVRSRV_ERROR_CANNOT_FLUSH_QUEUE;
+ goto ErrorExit;
+ }
+
+
+ eError = OSLockResource(&psSysData->sQProcessResource,
+ KERNEL_ID);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+
+ if(psQueue == psQueueInfo)
+ {
+ psSysData->psQueueList = psQueueInfo->psNextKM;
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ NearestPower2(psQueueInfo->ui32QueueSize) + PVRSRV_MAX_CMD_SIZE,
+ psQueueInfo->pvLinQueueKM,
+ psQueueInfo->hMemBlock[1]);
+ psQueueInfo->pvLinQueueKM = IMG_NULL;
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_QUEUE_INFO),
+ psQueueInfo,
+ psQueueInfo->hMemBlock[0]);
+
+ psQueueInfo = IMG_NULL;
+ }
+ else
+ {
+ while(psQueue)
+ {
+ if(psQueue->psNextKM == psQueueInfo)
+ {
+ psQueue->psNextKM = psQueueInfo->psNextKM;
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ psQueueInfo->ui32QueueSize,
+ psQueueInfo->pvLinQueueKM,
+ psQueueInfo->hMemBlock[1]);
+ psQueueInfo->pvLinQueueKM = IMG_NULL;
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_QUEUE_INFO),
+ psQueueInfo,
+ psQueueInfo->hMemBlock[0]);
+
+ psQueueInfo = IMG_NULL;
+ break;
+ }
+ psQueue = psQueue->psNextKM;
+ }
+
+ if(!psQueue)
+ {
+ eError = OSUnlockResource(&psSysData->sQProcessResource, KERNEL_ID);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto ErrorExit;
+ }
+ }
+
+
+ eError = OSUnlockResource(&psSysData->sQProcessResource, KERNEL_ID);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+
+
+ if (psSysData->psQueueList == IMG_NULL)
+ {
+ eError = OSDestroyResource(&psSysData->sQProcessResource);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+ }
+
+ErrorExit:
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetQueueSpaceKM(PVRSRV_QUEUE_INFO *psQueue,
+ IMG_SIZE_T ui32ParamSize,
+ IMG_VOID **ppvSpace)
+{
+ IMG_BOOL bTimeout = IMG_TRUE;
+
+
+ ui32ParamSize = (ui32ParamSize+3) & 0xFFFFFFFC;
+
+ if (ui32ParamSize > PVRSRV_MAX_CMD_SIZE)
+ {
+ PVR_DPF((PVR_DBG_WARNING,"PVRSRVGetQueueSpace: max command size is %d bytes", PVRSRV_MAX_CMD_SIZE));
+ return PVRSRV_ERROR_CMD_TOO_BIG;
+ }
+
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ if (GET_SPACE_IN_CMDQ(psQueue) > ui32ParamSize)
+ {
+ bTimeout = IMG_FALSE;
+ break;
+ }
+ OSSleepms(1);
+ } END_LOOP_UNTIL_TIMEOUT();
+
+ if (bTimeout == IMG_TRUE)
+ {
+ *ppvSpace = IMG_NULL;
+
+ return PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE;
+ }
+ else
+ {
+ *ppvSpace = (IMG_VOID *)((IMG_UINTPTR_T)psQueue->pvLinQueueUM + psQueue->ui32WriteOffset);
+ }
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInsertCommandKM(PVRSRV_QUEUE_INFO *psQueue,
+ PVRSRV_COMMAND **ppsCommand,
+ IMG_UINT32 ui32DevIndex,
+ IMG_UINT16 CommandType,
+ IMG_UINT32 ui32DstSyncCount,
+ PVRSRV_KERNEL_SYNC_INFO *apsDstSync[],
+ IMG_UINT32 ui32SrcSyncCount,
+ PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[],
+ IMG_SIZE_T ui32DataByteSize,
+ PFN_QUEUE_COMMAND_COMPLETE pfnCommandComplete,
+ IMG_HANDLE hCallbackData)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_COMMAND *psCommand;
+ IMG_SIZE_T ui32CommandSize;
+ IMG_UINT32 i;
+ SYS_DATA *psSysData;
+ DEVICE_COMMAND_DATA *psDeviceCommandData;
+
+
+ SysAcquireData(&psSysData);
+ psDeviceCommandData = psSysData->apsDeviceCommandData[ui32DevIndex];
+
+ if ((psDeviceCommandData[CommandType].ui32MaxDstSyncCount < ui32DstSyncCount) ||
+ (psDeviceCommandData[CommandType].ui32MaxSrcSyncCount < ui32SrcSyncCount))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVInsertCommandKM: Too many syncs"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ ui32DataByteSize = (ui32DataByteSize + 3UL) & ~3UL;
+
+
+ ui32CommandSize = sizeof(PVRSRV_COMMAND)
+ + ((ui32DstSyncCount + ui32SrcSyncCount) * sizeof(PVRSRV_SYNC_OBJECT))
+ + ui32DataByteSize;
+
+
+ eError = PVRSRVGetQueueSpaceKM (psQueue, ui32CommandSize, (IMG_VOID**)&psCommand);
+ if(eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ psCommand->ui32ProcessID = OSGetCurrentProcessIDKM();
+
+
+ psCommand->uCmdSize = ui32CommandSize;
+ psCommand->ui32DevIndex = ui32DevIndex;
+ psCommand->CommandType = CommandType;
+ psCommand->ui32DstSyncCount = ui32DstSyncCount;
+ psCommand->ui32SrcSyncCount = ui32SrcSyncCount;
+
+
+ psCommand->psDstSync = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psCommand) + sizeof(PVRSRV_COMMAND));
+
+
+ psCommand->psSrcSync = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psCommand->psDstSync)
+ + (ui32DstSyncCount * sizeof(PVRSRV_SYNC_OBJECT)));
+
+ psCommand->pvData = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psCommand->psSrcSync)
+ + (ui32SrcSyncCount * sizeof(PVRSRV_SYNC_OBJECT)));
+ psCommand->uDataSize = ui32DataByteSize;
+
+ psCommand->pfnCommandComplete = pfnCommandComplete;
+ psCommand->hCallbackData = hCallbackData;
+
+ PVR_TTRACE(PVRSRV_TRACE_GROUP_QUEUE, PVRSRV_TRACE_CLASS_CMD_START, QUEUE_TOKEN_INSERTKM);
+ PVR_TTRACE_UI32(PVRSRV_TRACE_GROUP_QUEUE, PVRSRV_TRACE_CLASS_NONE,
+ QUEUE_TOKEN_COMMAND_TYPE, CommandType);
+
+
+ for (i=0; i<ui32DstSyncCount; i++)
+ {
+ PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_QUEUE, QUEUE_TOKEN_DST_SYNC,
+ apsDstSync[i], PVRSRV_SYNCOP_SAMPLE);
+
+ psCommand->psDstSync[i].psKernelSyncInfoKM = apsDstSync[i];
+ psCommand->psDstSync[i].ui32WriteOpsPending = PVRSRVGetWriteOpsPending(apsDstSync[i], IMG_FALSE);
+ psCommand->psDstSync[i].ui32ReadOps2Pending = PVRSRVGetReadOpsPending(apsDstSync[i], IMG_FALSE);
+
+ PVRSRVKernelSyncInfoIncRef(apsDstSync[i], IMG_NULL);
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVInsertCommandKM: Dst %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x",
+ i, psCommand->psDstSync[i].psKernelSyncInfoKM->sReadOps2CompleteDevVAddr.uiAddr,
+ psCommand->psDstSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+ psCommand->psDstSync[i].ui32ReadOps2Pending,
+ psCommand->psDstSync[i].ui32WriteOpsPending));
+ }
+
+
+ for (i=0; i<ui32SrcSyncCount; i++)
+ {
+ PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_QUEUE, QUEUE_TOKEN_DST_SYNC,
+ apsSrcSync[i], PVRSRV_SYNCOP_SAMPLE);
+
+ psCommand->psSrcSync[i].psKernelSyncInfoKM = apsSrcSync[i];
+ psCommand->psSrcSync[i].ui32WriteOpsPending = PVRSRVGetWriteOpsPending(apsSrcSync[i], IMG_TRUE);
+ psCommand->psSrcSync[i].ui32ReadOps2Pending = PVRSRVGetReadOpsPending(apsSrcSync[i], IMG_TRUE);
+
+ PVRSRVKernelSyncInfoIncRef(apsSrcSync[i], IMG_NULL);
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVInsertCommandKM: Src %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x",
+ i, psCommand->psSrcSync[i].psKernelSyncInfoKM->sReadOps2CompleteDevVAddr.uiAddr,
+ psCommand->psSrcSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+ psCommand->psSrcSync[i].ui32ReadOps2Pending,
+ psCommand->psSrcSync[i].ui32WriteOpsPending));
+ }
+ PVR_TTRACE(PVRSRV_TRACE_GROUP_QUEUE, PVRSRV_TRACE_CLASS_CMD_END, QUEUE_TOKEN_INSERTKM);
+
+
+ *ppsCommand = psCommand;
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSubmitCommandKM(PVRSRV_QUEUE_INFO *psQueue,
+ PVRSRV_COMMAND *psCommand)
+{
+
+
+
+ if (psCommand->ui32DstSyncCount > 0)
+ {
+ psCommand->psDstSync = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psQueue->pvLinQueueKM)
+ + psQueue->ui32WriteOffset + sizeof(PVRSRV_COMMAND));
+ }
+
+ if (psCommand->ui32SrcSyncCount > 0)
+ {
+ psCommand->psSrcSync = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psQueue->pvLinQueueKM)
+ + psQueue->ui32WriteOffset + sizeof(PVRSRV_COMMAND)
+ + (psCommand->ui32DstSyncCount * sizeof(PVRSRV_SYNC_OBJECT)));
+ }
+
+ psCommand->pvData = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psQueue->pvLinQueueKM)
+ + psQueue->ui32WriteOffset + sizeof(PVRSRV_COMMAND)
+ + (psCommand->ui32DstSyncCount * sizeof(PVRSRV_SYNC_OBJECT))
+ + (psCommand->ui32SrcSyncCount * sizeof(PVRSRV_SYNC_OBJECT)));
+
+
+ UPDATE_QUEUE_WOFF(psQueue, psCommand->uCmdSize);
+
+ return PVRSRV_OK;
+}
+
+static
+PVRSRV_ERROR CheckIfSyncIsQueued(PVRSRV_SYNC_OBJECT *psSync, COMMAND_COMPLETE_DATA *psCmdData)
+{
+ IMG_UINT32 k;
+
+ if (psCmdData->bInUse)
+ {
+ for (k=0;k<psCmdData->ui32SrcSyncCount;k++)
+ {
+ if (psSync->psKernelSyncInfoKM == psCmdData->psSrcSync[k].psKernelSyncInfoKM)
+ {
+ PVRSRV_SYNC_DATA *psSyncData = psSync->psKernelSyncInfoKM->psSyncData;
+ IMG_UINT32 ui32WriteOpsComplete = psSyncData->ui32WriteOpsComplete;
+
+
+
+
+ if (ui32WriteOpsComplete == psSync->ui32WriteOpsPending)
+ {
+ return PVRSRV_OK;
+ }
+ else
+ {
+ if (SYNCOPS_STALE(ui32WriteOpsComplete, psSync->ui32WriteOpsPending))
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "CheckIfSyncIsQueued: Stale syncops psSyncData:0x%x ui32WriteOpsComplete:0x%x ui32WriteOpsPending:0x%x",
+ (IMG_UINTPTR_T)psSyncData, ui32WriteOpsComplete, psSync->ui32WriteOpsPending));
+ return PVRSRV_OK;
+ }
+ }
+ }
+ }
+ }
+ return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+}
+
+static
+PVRSRV_ERROR PVRSRVProcessCommand(SYS_DATA *psSysData,
+ PVRSRV_COMMAND *psCommand,
+ IMG_BOOL bFlush)
+{
+ PVRSRV_SYNC_OBJECT *psWalkerObj;
+ PVRSRV_SYNC_OBJECT *psEndObj;
+ IMG_UINT32 i;
+ COMMAND_COMPLETE_DATA *psCmdCompleteData;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ IMG_UINT32 ui32WriteOpsComplete;
+ IMG_UINT32 ui32ReadOpsComplete;
+ DEVICE_COMMAND_DATA *psDeviceCommandData;
+ IMG_UINT32 ui32CCBOffset;
+
+
+ psWalkerObj = psCommand->psDstSync;
+ psEndObj = psWalkerObj + psCommand->ui32DstSyncCount;
+ while (psWalkerObj < psEndObj)
+ {
+ PVRSRV_SYNC_DATA *psSyncData = psWalkerObj->psKernelSyncInfoKM->psSyncData;
+
+ ui32WriteOpsComplete = psSyncData->ui32WriteOpsComplete;
+ ui32ReadOpsComplete = psSyncData->ui32ReadOps2Complete;
+
+ if ((ui32WriteOpsComplete != psWalkerObj->ui32WriteOpsPending)
+ || (ui32ReadOpsComplete != psWalkerObj->ui32ReadOps2Pending))
+ {
+ if (!bFlush ||
+ !SYNCOPS_STALE(ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending) ||
+ !SYNCOPS_STALE(ui32ReadOpsComplete, psWalkerObj->ui32ReadOps2Pending))
+ {
+ return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+ }
+ }
+
+ psWalkerObj++;
+ }
+
+
+ psWalkerObj = psCommand->psSrcSync;
+ psEndObj = psWalkerObj + psCommand->ui32SrcSyncCount;
+ while (psWalkerObj < psEndObj)
+ {
+ PVRSRV_SYNC_DATA *psSyncData = psWalkerObj->psKernelSyncInfoKM->psSyncData;
+
+ ui32ReadOpsComplete = psSyncData->ui32ReadOps2Complete;
+ ui32WriteOpsComplete = psSyncData->ui32WriteOpsComplete;
+
+ if ((ui32WriteOpsComplete != psWalkerObj->ui32WriteOpsPending)
+ || (ui32ReadOpsComplete != psWalkerObj->ui32ReadOps2Pending))
+ {
+ if (!bFlush &&
+ SYNCOPS_STALE(ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending) &&
+ SYNCOPS_STALE(ui32ReadOpsComplete, psWalkerObj->ui32ReadOps2Pending))
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "PVRSRVProcessCommand: Stale syncops psSyncData:0x%x ui32WriteOpsComplete:0x%x ui32WriteOpsPending:0x%x",
+ (IMG_UINTPTR_T)psSyncData, ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending));
+ }
+
+ if (!bFlush ||
+ !SYNCOPS_STALE(ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending) ||
+ !SYNCOPS_STALE(ui32ReadOpsComplete, psWalkerObj->ui32ReadOps2Pending))
+ {
+ IMG_UINT32 j;
+ PVRSRV_ERROR eError;
+ IMG_BOOL bFound = IMG_FALSE;
+
+ psDeviceCommandData = psSysData->apsDeviceCommandData[psCommand->ui32DevIndex];
+ for (j=0;j<DC_NUM_COMMANDS_PER_TYPE;j++)
+ {
+ eError = CheckIfSyncIsQueued(psWalkerObj, psDeviceCommandData[psCommand->CommandType].apsCmdCompleteData[j]);
+
+ if (eError == PVRSRV_OK)
+ {
+ bFound = IMG_TRUE;
+ }
+ }
+ if (!bFound)
+ return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+ }
+ }
+ psWalkerObj++;
+ }
+
+
+ if (psCommand->ui32DevIndex >= SYS_DEVICE_COUNT)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVProcessCommand: invalid DeviceType 0x%x",
+ psCommand->ui32DevIndex));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ psDeviceCommandData = psSysData->apsDeviceCommandData[psCommand->ui32DevIndex];
+ ui32CCBOffset = psDeviceCommandData[psCommand->CommandType].ui32CCBOffset;
+ psCmdCompleteData = psDeviceCommandData[psCommand->CommandType].apsCmdCompleteData[ui32CCBOffset];
+ if (psCmdCompleteData->bInUse)
+ {
+
+ return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+ }
+
+
+ psCmdCompleteData->bInUse = IMG_TRUE;
+
+
+ psCmdCompleteData->ui32DstSyncCount = psCommand->ui32DstSyncCount;
+ for (i=0; i<psCommand->ui32DstSyncCount; i++)
+ {
+ psCmdCompleteData->psDstSync[i] = psCommand->psDstSync[i];
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVProcessCommand: Dst %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x (CCB:%u)",
+ i, psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sReadOps2CompleteDevVAddr.uiAddr,
+ psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+ psCmdCompleteData->psDstSync[i].ui32ReadOps2Pending,
+ psCmdCompleteData->psDstSync[i].ui32WriteOpsPending,
+ ui32CCBOffset));
+ }
+
+ psCmdCompleteData->pfnCommandComplete = psCommand->pfnCommandComplete;
+ psCmdCompleteData->hCallbackData = psCommand->hCallbackData;
+
+
+ psCmdCompleteData->ui32SrcSyncCount = psCommand->ui32SrcSyncCount;
+ for (i=0; i<psCommand->ui32SrcSyncCount; i++)
+ {
+ psCmdCompleteData->psSrcSync[i] = psCommand->psSrcSync[i];
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVProcessCommand: Src %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x (CCB:%u)",
+ i, psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sReadOps2CompleteDevVAddr.uiAddr,
+ psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+ psCmdCompleteData->psSrcSync[i].ui32ReadOps2Pending,
+ psCmdCompleteData->psSrcSync[i].ui32WriteOpsPending,
+ ui32CCBOffset));
+ }
+
+
+
+
+
+
+
+
+
+
+
+ if (psDeviceCommandData[psCommand->CommandType].pfnCmdProc((IMG_HANDLE)psCmdCompleteData,
+ (IMG_UINT32)psCommand->uDataSize,
+ psCommand->pvData) == IMG_FALSE)
+ {
+
+
+
+ psCmdCompleteData->bInUse = IMG_FALSE;
+ eError = PVRSRV_ERROR_CMD_NOT_PROCESSED;
+ }
+
+
+ psDeviceCommandData[psCommand->CommandType].ui32CCBOffset = (ui32CCBOffset + 1) % DC_NUM_COMMANDS_PER_TYPE;
+
+ return eError;
+}
+
+
+static IMG_VOID PVRSRVProcessQueues_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ if (psDeviceNode->bReProcessDeviceCommandComplete &&
+ psDeviceNode->pfnDeviceCommandComplete != IMG_NULL)
+ {
+ (*psDeviceNode->pfnDeviceCommandComplete)(psDeviceNode);
+ }
+}
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVProcessQueues(IMG_BOOL bFlush)
+{
+ PVRSRV_QUEUE_INFO *psQueue;
+ SYS_DATA *psSysData;
+ PVRSRV_COMMAND *psCommand;
+ SysAcquireData(&psSysData);
+
+
+
+ while (OSLockResource(&psSysData->sQProcessResource, ISR_ID) != PVRSRV_OK)
+ {
+ OSWaitus(1);
+ };
+
+ psQueue = psSysData->psQueueList;
+
+ if(!psQueue)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"No Queues installed - cannot process commands"));
+ }
+
+ if (bFlush)
+ {
+ PVRSRVSetDCState(DC_STATE_FLUSH_COMMANDS);
+ }
+
+ while (psQueue)
+ {
+ while (psQueue->ui32ReadOffset != psQueue->ui32WriteOffset)
+ {
+ psCommand = (PVRSRV_COMMAND*)((IMG_UINTPTR_T)psQueue->pvLinQueueKM + psQueue->ui32ReadOffset);
+
+ if (PVRSRVProcessCommand(psSysData, psCommand, bFlush) == PVRSRV_OK)
+ {
+
+ UPDATE_QUEUE_ROFF(psQueue, psCommand->uCmdSize)
+ continue;
+ }
+
+ break;
+ }
+ psQueue = psQueue->psNextKM;
+ }
+
+ if (bFlush)
+ {
+ PVRSRVSetDCState(DC_STATE_NO_FLUSH_COMMANDS);
+ }
+
+
+ List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList,
+ &PVRSRVProcessQueues_ForEachCb);
+
+ OSUnlockResource(&psSysData->sQProcessResource, ISR_ID);
+
+ return PVRSRV_OK;
+}
+
+#if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS)
+IMG_INTERNAL
+IMG_VOID PVRSRVFreeCommandCompletePacketKM(IMG_HANDLE hCmdCookie,
+ IMG_BOOL bScheduleMISR)
+{
+ COMMAND_COMPLETE_DATA *psCmdCompleteData = (COMMAND_COMPLETE_DATA *)hCmdCookie;
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+
+ psCmdCompleteData->bInUse = IMG_FALSE;
+
+
+ PVRSRVScheduleDeviceCallbacks();
+
+ if(bScheduleMISR)
+ {
+ OSScheduleMISR(psSysData);
+ }
+}
+
+#endif
+
+
+IMG_EXPORT
+IMG_VOID PVRSRVCommandCompleteKM(IMG_HANDLE hCmdCookie,
+ IMG_BOOL bScheduleMISR)
+{
+ IMG_UINT32 i;
+ COMMAND_COMPLETE_DATA *psCmdCompleteData = (COMMAND_COMPLETE_DATA *)hCmdCookie;
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+ PVR_TTRACE(PVRSRV_TRACE_GROUP_QUEUE, PVRSRV_TRACE_CLASS_CMD_COMP_START,
+ QUEUE_TOKEN_COMMAND_COMPLETE);
+
+
+ for (i=0; i<psCmdCompleteData->ui32DstSyncCount; i++)
+ {
+ psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->psSyncData->ui32WriteOpsComplete++;
+
+ PVRSRVKernelSyncInfoDecRef(psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM, IMG_NULL);
+
+ PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_QUEUE, QUEUE_TOKEN_UPDATE_DST,
+ psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM,
+ PVRSRV_SYNCOP_COMPLETE);
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVCommandCompleteKM: Dst %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x",
+ i, psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sReadOps2CompleteDevVAddr.uiAddr,
+ psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+ psCmdCompleteData->psDstSync[i].ui32ReadOps2Pending,
+ psCmdCompleteData->psDstSync[i].ui32WriteOpsPending));
+ }
+
+
+ for (i=0; i<psCmdCompleteData->ui32SrcSyncCount; i++)
+ {
+ psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->psSyncData->ui32ReadOps2Complete++;
+
+ PVRSRVKernelSyncInfoDecRef(psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM, IMG_NULL);
+
+ PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_QUEUE, QUEUE_TOKEN_UPDATE_SRC,
+ psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM,
+ PVRSRV_SYNCOP_COMPLETE);
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVCommandCompleteKM: Src %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x",
+ i, psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sReadOps2CompleteDevVAddr.uiAddr,
+ psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+ psCmdCompleteData->psSrcSync[i].ui32ReadOps2Pending,
+ psCmdCompleteData->psSrcSync[i].ui32WriteOpsPending));
+ }
+
+ PVR_TTRACE(PVRSRV_TRACE_GROUP_QUEUE, PVRSRV_TRACE_CLASS_CMD_COMP_END,
+ QUEUE_TOKEN_COMMAND_COMPLETE);
+
+ if (psCmdCompleteData->pfnCommandComplete)
+ {
+ psCmdCompleteData->pfnCommandComplete(psCmdCompleteData->hCallbackData);
+ }
+
+
+ psCmdCompleteData->bInUse = IMG_FALSE;
+
+
+ PVRSRVScheduleDeviceCallbacks();
+
+ if(bScheduleMISR)
+ {
+ OSScheduleMISR(psSysData);
+ }
+}
+
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRegisterCmdProcListKM(IMG_UINT32 ui32DevIndex,
+ PFN_CMD_PROC *ppfnCmdProcList,
+ IMG_UINT32 ui32MaxSyncsPerCmd[][2],
+ IMG_UINT32 ui32CmdCount)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32CmdCounter, ui32CmdTypeCounter;
+ IMG_SIZE_T ui32AllocSize;
+ DEVICE_COMMAND_DATA *psDeviceCommandData;
+ COMMAND_COMPLETE_DATA *psCmdCompleteData;
+
+
+ if(ui32DevIndex >= SYS_DEVICE_COUNT)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVRegisterCmdProcListKM: invalid DeviceType 0x%x",
+ ui32DevIndex));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ SysAcquireData(&psSysData);
+
+
+ ui32AllocSize = ui32CmdCount * sizeof(*psDeviceCommandData);
+ eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ ui32AllocSize,
+ (IMG_VOID **)&psDeviceCommandData, IMG_NULL,
+ "Array of Pointers for Command Store");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterCmdProcListKM: Failed to alloc CC data"));
+ goto ErrorExit;
+ }
+
+ psSysData->apsDeviceCommandData[ui32DevIndex] = psDeviceCommandData;
+
+ for (ui32CmdTypeCounter = 0; ui32CmdTypeCounter < ui32CmdCount; ui32CmdTypeCounter++)
+ {
+ psDeviceCommandData[ui32CmdTypeCounter].pfnCmdProc = ppfnCmdProcList[ui32CmdTypeCounter];
+ psDeviceCommandData[ui32CmdTypeCounter].ui32CCBOffset = 0;
+ psDeviceCommandData[ui32CmdTypeCounter].ui32MaxDstSyncCount = ui32MaxSyncsPerCmd[ui32CmdTypeCounter][0];
+ psDeviceCommandData[ui32CmdTypeCounter].ui32MaxSrcSyncCount = ui32MaxSyncsPerCmd[ui32CmdTypeCounter][1];
+ for (ui32CmdCounter = 0; ui32CmdCounter < DC_NUM_COMMANDS_PER_TYPE; ui32CmdCounter++)
+ {
+
+
+ ui32AllocSize = sizeof(COMMAND_COMPLETE_DATA)
+ + ((ui32MaxSyncsPerCmd[ui32CmdTypeCounter][0]
+ + ui32MaxSyncsPerCmd[ui32CmdTypeCounter][1])
+ * sizeof(PVRSRV_SYNC_OBJECT));
+
+ eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ ui32AllocSize,
+ (IMG_VOID **)&psCmdCompleteData,
+ IMG_NULL,
+ "Command Complete Data");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterCmdProcListKM: Failed to alloc cmd %d", ui32CmdTypeCounter));
+ goto ErrorExit;
+ }
+
+ psDeviceCommandData[ui32CmdTypeCounter].apsCmdCompleteData[ui32CmdCounter] = psCmdCompleteData;
+
+
+ OSMemSet(psCmdCompleteData, 0x00, ui32AllocSize);
+
+
+ psCmdCompleteData->psDstSync = (PVRSRV_SYNC_OBJECT*)
+ (((IMG_UINTPTR_T)psCmdCompleteData)
+ + sizeof(COMMAND_COMPLETE_DATA));
+ psCmdCompleteData->psSrcSync = (PVRSRV_SYNC_OBJECT*)
+ (((IMG_UINTPTR_T)psCmdCompleteData->psDstSync)
+ + (sizeof(PVRSRV_SYNC_OBJECT) * ui32MaxSyncsPerCmd[ui32CmdTypeCounter][0]));
+
+ psCmdCompleteData->ui32AllocSize = (IMG_UINT32)ui32AllocSize;
+ }
+ }
+
+ return PVRSRV_OK;
+
+ErrorExit:
+
+
+ if (PVRSRVRemoveCmdProcListKM(ui32DevIndex, ui32CmdCount) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVRegisterCmdProcListKM: Failed to clean up after error, device 0x%x",
+ ui32DevIndex));
+ }
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRemoveCmdProcListKM(IMG_UINT32 ui32DevIndex,
+ IMG_UINT32 ui32CmdCount)
+{
+ SYS_DATA *psSysData;
+ IMG_UINT32 ui32CmdTypeCounter, ui32CmdCounter;
+ DEVICE_COMMAND_DATA *psDeviceCommandData;
+ COMMAND_COMPLETE_DATA *psCmdCompleteData;
+ IMG_SIZE_T ui32AllocSize;
+
+
+ if(ui32DevIndex >= SYS_DEVICE_COUNT)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVRemoveCmdProcListKM: invalid DeviceType 0x%x",
+ ui32DevIndex));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ SysAcquireData(&psSysData);
+
+ psDeviceCommandData = psSysData->apsDeviceCommandData[ui32DevIndex];
+ if(psDeviceCommandData != IMG_NULL)
+ {
+ for (ui32CmdTypeCounter = 0; ui32CmdTypeCounter < ui32CmdCount; ui32CmdTypeCounter++)
+ {
+ for (ui32CmdCounter = 0; ui32CmdCounter < DC_NUM_COMMANDS_PER_TYPE; ui32CmdCounter++)
+ {
+ psCmdCompleteData = psDeviceCommandData[ui32CmdTypeCounter].apsCmdCompleteData[ui32CmdCounter];
+
+
+ if (psCmdCompleteData != IMG_NULL)
+ {
+ PVR_ASSERT(psCmdCompleteData->bInUse == IMG_FALSE);
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, psCmdCompleteData->ui32AllocSize,
+ psCmdCompleteData, IMG_NULL);
+ psDeviceCommandData[ui32CmdTypeCounter].apsCmdCompleteData[ui32CmdCounter] = IMG_NULL;
+ }
+ }
+ }
+
+
+ ui32AllocSize = ui32CmdCount * sizeof(*psDeviceCommandData);
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, ui32AllocSize, psDeviceCommandData, IMG_NULL);
+ psSysData->apsDeviceCommandData[ui32DevIndex] = IMG_NULL;
+ }
+
+ return PVRSRV_OK;
+}
+
diff --git a/drivers/gpu/pvr/queue.h b/drivers/gpu/pvr/queue.h
new file mode 100644
index 0000000..d8045b1
--- /dev/null
+++ b/drivers/gpu/pvr/queue.h
@@ -0,0 +1,114 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef QUEUE_H
+#define QUEUE_H
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define UPDATE_QUEUE_ROFF(psQueue, ui32Size) \
+ (psQueue)->ui32ReadOffset = ((psQueue)->ui32ReadOffset + (ui32Size)) \
+ & ((psQueue)->ui32QueueSize - 1);
+
+ typedef struct _COMMAND_COMPLETE_DATA_
+ {
+ IMG_BOOL bInUse;
+
+ IMG_UINT32 ui32DstSyncCount;
+ IMG_UINT32 ui32SrcSyncCount;
+ PVRSRV_SYNC_OBJECT *psDstSync;
+ PVRSRV_SYNC_OBJECT *psSrcSync;
+ IMG_UINT32 ui32AllocSize;
+ PFN_QUEUE_COMMAND_COMPLETE pfnCommandComplete;
+ IMG_HANDLE hCallbackData;
+ }COMMAND_COMPLETE_DATA, *PCOMMAND_COMPLETE_DATA;
+
+#if !defined(USE_CODE)
+IMG_VOID QueueDumpDebugInfo(IMG_VOID);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVProcessQueues (IMG_BOOL bFlush);
+
+#if defined(__linux__) && defined(__KERNEL__)
+#include <linux/types.h>
+#include <linux/seq_file.h>
+void* ProcSeqOff2ElementQueue(struct seq_file * sfile, loff_t off);
+void ProcSeqShowQueue(struct seq_file *sfile,void* el);
+#endif
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateCommandQueueKM(IMG_SIZE_T ui32QueueSize,
+ PVRSRV_QUEUE_INFO **ppsQueueInfo);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyCommandQueueKM(PVRSRV_QUEUE_INFO *psQueueInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInsertCommandKM(PVRSRV_QUEUE_INFO *psQueue,
+ PVRSRV_COMMAND **ppsCommand,
+ IMG_UINT32 ui32DevIndex,
+ IMG_UINT16 CommandType,
+ IMG_UINT32 ui32DstSyncCount,
+ PVRSRV_KERNEL_SYNC_INFO *apsDstSync[],
+ IMG_UINT32 ui32SrcSyncCount,
+ PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[],
+ IMG_SIZE_T ui32DataByteSize,
+ PFN_QUEUE_COMMAND_COMPLETE pfnCommandComplete,
+ IMG_HANDLE hCallbackData);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetQueueSpaceKM(PVRSRV_QUEUE_INFO *psQueue,
+ IMG_SIZE_T ui32ParamSize,
+ IMG_VOID **ppvSpace);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSubmitCommandKM(PVRSRV_QUEUE_INFO *psQueue,
+ PVRSRV_COMMAND *psCommand);
+
+IMG_IMPORT
+IMG_VOID PVRSRVCommandCompleteKM(IMG_HANDLE hCmdCookie, IMG_BOOL bScheduleMISR);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVRegisterCmdProcListKM(IMG_UINT32 ui32DevIndex,
+ PFN_CMD_PROC *ppfnCmdProcList,
+ IMG_UINT32 ui32MaxSyncsPerCmd[][2],
+ IMG_UINT32 ui32CmdCount);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVRemoveCmdProcListKM(IMG_UINT32 ui32DevIndex,
+ IMG_UINT32 ui32CmdCount);
+
+#endif
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/pvr/ra.c b/drivers/gpu/pvr/ra.c
new file mode 100644
index 0000000..84a2162
--- /dev/null
+++ b/drivers/gpu/pvr/ra.c
@@ -0,0 +1,1736 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "hash.h"
+#include "ra.h"
+#include "buffer_manager.h"
+#include "osfunc.h"
+
+#ifdef __linux__
+#include <linux/kernel.h>
+#include "proc.h"
+#endif
+
+#ifdef USE_BM_FREESPACE_CHECK
+#include <stdio.h>
+#endif
+
+#define MINIMUM_HASH_SIZE (64)
+
+#if defined(VALIDATE_ARENA_TEST)
+
+typedef enum RESOURCE_DESCRIPTOR_TAG {
+
+ RESOURCE_SPAN_LIVE = 10,
+ RESOURCE_SPAN_FREE,
+ IMPORTED_RESOURCE_SPAN_START,
+ IMPORTED_RESOURCE_SPAN_LIVE,
+ IMPORTED_RESOURCE_SPAN_FREE,
+ IMPORTED_RESOURCE_SPAN_END,
+
+} RESOURCE_DESCRIPTOR;
+
+typedef enum RESOURCE_TYPE_TAG {
+
+ IMPORTED_RESOURCE_TYPE = 20,
+ NON_IMPORTED_RESOURCE_TYPE
+
+} RESOURCE_TYPE;
+
+
+static IMG_UINT32 ui32BoundaryTagID = 0;
+
+IMG_UINT32 ValidateArena(RA_ARENA *pArena);
+#endif
+
+struct _BT_
+{
+ enum bt_type
+ {
+ btt_span,
+ btt_free,
+ btt_live
+ } type;
+
+
+ IMG_UINTPTR_T base;
+ IMG_SIZE_T uSize;
+
+
+ struct _BT_ *pNextSegment;
+ struct _BT_ *pPrevSegment;
+
+ struct _BT_ *pNextFree;
+ struct _BT_ *pPrevFree;
+
+ BM_MAPPING *psMapping;
+
+#if defined(VALIDATE_ARENA_TEST)
+ RESOURCE_DESCRIPTOR eResourceSpan;
+ RESOURCE_TYPE eResourceType;
+
+
+ IMG_UINT32 ui32BoundaryTagID;
+#endif
+
+};
+typedef struct _BT_ BT;
+
+
+struct _RA_ARENA_
+{
+
+ IMG_CHAR *name;
+
+
+ IMG_SIZE_T uQuantum;
+
+
+ IMG_BOOL (*pImportAlloc)(IMG_VOID *,
+ IMG_SIZE_T uSize,
+ IMG_SIZE_T *pActualSize,
+ BM_MAPPING **ppsMapping,
+ IMG_UINT32 uFlags,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
+ IMG_UINTPTR_T *pBase);
+ IMG_VOID (*pImportFree) (IMG_VOID *,
+ IMG_UINTPTR_T,
+ BM_MAPPING *psMapping);
+ IMG_VOID (*pBackingStoreFree) (IMG_VOID *, IMG_SIZE_T, IMG_SIZE_T, IMG_HANDLE);
+
+
+ IMG_VOID *pImportHandle;
+
+
+#define FREE_TABLE_LIMIT 32
+
+
+ BT *aHeadFree [FREE_TABLE_LIMIT];
+
+
+ BT *pHeadSegment;
+ BT *pTailSegment;
+
+
+ HASH_TABLE *pSegmentHash;
+
+#ifdef RA_STATS
+ RA_STATISTICS sStatistics;
+#endif
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+#define PROC_NAME_SIZE 64
+
+ struct proc_dir_entry* pProcInfo;
+ struct proc_dir_entry* pProcSegs;
+
+ IMG_BOOL bInitProcEntry;
+#endif
+};
+#if defined(ENABLE_RA_DUMP)
+IMG_VOID RA_Dump (RA_ARENA *pArena);
+#endif
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+
+static void RA_ProcSeqShowInfo(struct seq_file *sfile, void* el);
+static void* RA_ProcSeqOff2ElementInfo(struct seq_file * sfile, loff_t off);
+
+static void RA_ProcSeqShowRegs(struct seq_file *sfile, void* el);
+static void* RA_ProcSeqOff2ElementRegs(struct seq_file * sfile, loff_t off);
+
+#endif
+
+#ifdef USE_BM_FREESPACE_CHECK
+IMG_VOID CheckBMFreespace(IMG_VOID);
+#endif
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+static IMG_CHAR *ReplaceSpaces(IMG_CHAR * const pS)
+{
+ IMG_CHAR *pT;
+
+ for(pT = pS; *pT != 0; pT++)
+ {
+ if (*pT == ' ' || *pT == '\t')
+ {
+ *pT = '_';
+ }
+ }
+
+ return pS;
+}
+#endif
+
+static IMG_BOOL
+_RequestAllocFail (IMG_VOID *_h,
+ IMG_SIZE_T _uSize,
+ IMG_SIZE_T *_pActualSize,
+ BM_MAPPING **_ppsMapping,
+ IMG_UINT32 _uFlags,
+ IMG_PVOID _pvPrivData,
+ IMG_UINT32 _ui32PrivDataLength,
+ IMG_UINTPTR_T *_pBase)
+{
+ PVR_UNREFERENCED_PARAMETER (_h);
+ PVR_UNREFERENCED_PARAMETER (_uSize);
+ PVR_UNREFERENCED_PARAMETER (_pActualSize);
+ PVR_UNREFERENCED_PARAMETER (_ppsMapping);
+ PVR_UNREFERENCED_PARAMETER (_uFlags);
+ PVR_UNREFERENCED_PARAMETER (_pBase);
+ PVR_UNREFERENCED_PARAMETER (_pvPrivData);
+ PVR_UNREFERENCED_PARAMETER (_ui32PrivDataLength);
+
+ return IMG_FALSE;
+}
+
+static IMG_UINT32
+pvr_log2 (IMG_SIZE_T n)
+{
+ IMG_UINT32 l = 0;
+ n>>=1;
+ while (n>0)
+ {
+ n>>=1;
+ l++;
+ }
+ return l;
+}
+
+static PVRSRV_ERROR
+_SegmentListInsertAfter (RA_ARENA *pArena,
+ BT *pInsertionPoint,
+ BT *pBT)
+{
+ PVR_ASSERT (pArena != IMG_NULL);
+ PVR_ASSERT (pInsertionPoint != IMG_NULL);
+
+ if ((pInsertionPoint == IMG_NULL) || (pArena == IMG_NULL))
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"_SegmentListInsertAfter: invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ pBT->pNextSegment = pInsertionPoint->pNextSegment;
+ pBT->pPrevSegment = pInsertionPoint;
+ if (pInsertionPoint->pNextSegment == IMG_NULL)
+ pArena->pTailSegment = pBT;
+ else
+ pInsertionPoint->pNextSegment->pPrevSegment = pBT;
+ pInsertionPoint->pNextSegment = pBT;
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR
+_SegmentListInsert (RA_ARENA *pArena, BT *pBT)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+
+ if (pArena->pHeadSegment == IMG_NULL)
+ {
+ pArena->pHeadSegment = pArena->pTailSegment = pBT;
+ pBT->pNextSegment = pBT->pPrevSegment = IMG_NULL;
+ }
+ else
+ {
+ BT *pBTScan;
+
+ if (pBT->base < pArena->pHeadSegment->base)
+ {
+
+ pBT->pNextSegment = pArena->pHeadSegment;
+ pArena->pHeadSegment->pPrevSegment = pBT;
+ pArena->pHeadSegment = pBT;
+ pBT->pPrevSegment = IMG_NULL;
+ }
+ else
+ {
+
+
+
+
+ pBTScan = pArena->pHeadSegment;
+
+ while ((pBTScan->pNextSegment != IMG_NULL) && (pBT->base >= pBTScan->pNextSegment->base))
+ {
+ pBTScan = pBTScan->pNextSegment;
+ }
+
+ eError = _SegmentListInsertAfter (pArena, pBTScan, pBT);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+ }
+ return eError;
+}
+
+static IMG_VOID
+_SegmentListRemove (RA_ARENA *pArena, BT *pBT)
+{
+ if (pBT->pPrevSegment == IMG_NULL)
+ pArena->pHeadSegment = pBT->pNextSegment;
+ else
+ pBT->pPrevSegment->pNextSegment = pBT->pNextSegment;
+
+ if (pBT->pNextSegment == IMG_NULL)
+ pArena->pTailSegment = pBT->pPrevSegment;
+ else
+ pBT->pNextSegment->pPrevSegment = pBT->pPrevSegment;
+}
+
+static BT *
+_SegmentSplit (RA_ARENA *pArena, BT *pBT, IMG_SIZE_T uSize)
+{
+ BT *pNeighbour;
+
+ PVR_ASSERT (pArena != IMG_NULL);
+
+ if (pArena == IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"_SegmentSplit: invalid parameter - pArena"));
+ return IMG_NULL;
+ }
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(BT),
+ (IMG_VOID **)&pNeighbour, IMG_NULL,
+ "Boundary Tag") != PVRSRV_OK)
+ {
+ return IMG_NULL;
+ }
+
+ OSMemSet(pNeighbour, 0, sizeof(BT));
+
+#if defined(VALIDATE_ARENA_TEST)
+ pNeighbour->ui32BoundaryTagID = ++ui32BoundaryTagID;
+#endif
+
+ pNeighbour->pPrevSegment = pBT;
+ pNeighbour->pNextSegment = pBT->pNextSegment;
+ if (pBT->pNextSegment == IMG_NULL)
+ pArena->pTailSegment = pNeighbour;
+ else
+ pBT->pNextSegment->pPrevSegment = pNeighbour;
+ pBT->pNextSegment = pNeighbour;
+
+ pNeighbour->type = btt_free;
+ pNeighbour->uSize = pBT->uSize - uSize;
+ pNeighbour->base = pBT->base + uSize;
+ pNeighbour->psMapping = pBT->psMapping;
+ pBT->uSize = uSize;
+
+#if defined(VALIDATE_ARENA_TEST)
+ if (pNeighbour->pPrevSegment->eResourceType == IMPORTED_RESOURCE_TYPE)
+ {
+ pNeighbour->eResourceType = IMPORTED_RESOURCE_TYPE;
+ pNeighbour->eResourceSpan = IMPORTED_RESOURCE_SPAN_FREE;
+ }
+ else if (pNeighbour->pPrevSegment->eResourceType == NON_IMPORTED_RESOURCE_TYPE)
+ {
+ pNeighbour->eResourceType = NON_IMPORTED_RESOURCE_TYPE;
+ pNeighbour->eResourceSpan = RESOURCE_SPAN_FREE;
+ }
+ else
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"_SegmentSplit: pNeighbour->pPrevSegment->eResourceType unrecognized"));
+ PVR_DBG_BREAK;
+ }
+#endif
+
+ return pNeighbour;
+}
+
+static IMG_VOID
+_FreeListInsert (RA_ARENA *pArena, BT *pBT)
+{
+ IMG_UINT32 uIndex;
+ uIndex = pvr_log2 (pBT->uSize);
+ pBT->type = btt_free;
+ pBT->pNextFree = pArena->aHeadFree [uIndex];
+ pBT->pPrevFree = IMG_NULL;
+ if (pArena->aHeadFree[uIndex] != IMG_NULL)
+ pArena->aHeadFree[uIndex]->pPrevFree = pBT;
+ pArena->aHeadFree [uIndex] = pBT;
+}
+
+static IMG_VOID
+_FreeListRemove (RA_ARENA *pArena, BT *pBT)
+{
+ IMG_UINT32 uIndex;
+ uIndex = pvr_log2 (pBT->uSize);
+ if (pBT->pNextFree != IMG_NULL)
+ pBT->pNextFree->pPrevFree = pBT->pPrevFree;
+ if (pBT->pPrevFree == IMG_NULL)
+ pArena->aHeadFree[uIndex] = pBT->pNextFree;
+ else
+ pBT->pPrevFree->pNextFree = pBT->pNextFree;
+}
+
+static BT *
+_BuildSpanMarker (IMG_UINTPTR_T base, IMG_SIZE_T uSize)
+{
+ BT *pBT;
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(BT),
+ (IMG_VOID **)&pBT, IMG_NULL,
+ "Boundary Tag") != PVRSRV_OK)
+ {
+ return IMG_NULL;
+ }
+
+ OSMemSet(pBT, 0, sizeof(BT));
+
+#if defined(VALIDATE_ARENA_TEST)
+ pBT->ui32BoundaryTagID = ++ui32BoundaryTagID;
+#endif
+
+ pBT->type = btt_span;
+ pBT->base = base;
+ pBT->uSize = uSize;
+ pBT->psMapping = IMG_NULL;
+
+ return pBT;
+}
+
+static BT *
+_BuildBT (IMG_UINTPTR_T base, IMG_SIZE_T uSize)
+{
+ BT *pBT;
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(BT),
+ (IMG_VOID **)&pBT, IMG_NULL,
+ "Boundary Tag") != PVRSRV_OK)
+ {
+ return IMG_NULL;
+ }
+
+ OSMemSet(pBT, 0, sizeof(BT));
+
+#if defined(VALIDATE_ARENA_TEST)
+ pBT->ui32BoundaryTagID = ++ui32BoundaryTagID;
+#endif
+
+ pBT->type = btt_free;
+ pBT->base = base;
+ pBT->uSize = uSize;
+
+ return pBT;
+}
+
+static BT *
+_InsertResource (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
+{
+ BT *pBT;
+ PVR_ASSERT (pArena!=IMG_NULL);
+ if (pArena == IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"_InsertResource: invalid parameter - pArena"));
+ return IMG_NULL;
+ }
+
+ pBT = _BuildBT (base, uSize);
+ if (pBT != IMG_NULL)
+ {
+
+#if defined(VALIDATE_ARENA_TEST)
+ pBT->eResourceSpan = RESOURCE_SPAN_FREE;
+ pBT->eResourceType = NON_IMPORTED_RESOURCE_TYPE;
+#endif
+
+ if (_SegmentListInsert (pArena, pBT) != PVRSRV_OK)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"_InsertResource: call to _SegmentListInsert failed"));
+ return IMG_NULL;
+ }
+ _FreeListInsert (pArena, pBT);
+#ifdef RA_STATS
+ pArena->sStatistics.uTotalResourceCount+=uSize;
+ pArena->sStatistics.uFreeResourceCount+=uSize;
+ pArena->sStatistics.uSpanCount++;
+#endif
+ }
+ return pBT;
+}
+
+static BT *
+_InsertResourceSpan (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
+{
+ PVRSRV_ERROR eError;
+ BT *pSpanStart;
+ BT *pSpanEnd;
+ BT *pBT;
+
+ PVR_ASSERT (pArena != IMG_NULL);
+ if (pArena == IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"_InsertResourceSpan: invalid parameter - pArena"));
+ return IMG_NULL;
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "RA_InsertResourceSpan: arena='%s', base=0x%x, size=0x%x",
+ pArena->name, base, uSize));
+
+ pSpanStart = _BuildSpanMarker (base, uSize);
+ if (pSpanStart == IMG_NULL)
+ {
+ goto fail_start;
+ }
+
+#if defined(VALIDATE_ARENA_TEST)
+ pSpanStart->eResourceSpan = IMPORTED_RESOURCE_SPAN_START;
+ pSpanStart->eResourceType = IMPORTED_RESOURCE_TYPE;
+#endif
+
+ pSpanEnd = _BuildSpanMarker (base + uSize, 0);
+ if (pSpanEnd == IMG_NULL)
+ {
+ goto fail_end;
+ }
+
+#if defined(VALIDATE_ARENA_TEST)
+ pSpanEnd->eResourceSpan = IMPORTED_RESOURCE_SPAN_END;
+ pSpanEnd->eResourceType = IMPORTED_RESOURCE_TYPE;
+#endif
+
+ pBT = _BuildBT (base, uSize);
+ if (pBT == IMG_NULL)
+ {
+ goto fail_bt;
+ }
+
+#if defined(VALIDATE_ARENA_TEST)
+ pBT->eResourceSpan = IMPORTED_RESOURCE_SPAN_FREE;
+ pBT->eResourceType = IMPORTED_RESOURCE_TYPE;
+#endif
+
+ eError = _SegmentListInsert (pArena, pSpanStart);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_SegListInsert;
+ }
+
+ eError = _SegmentListInsertAfter (pArena, pSpanStart, pBT);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_SegListInsert;
+ }
+
+ _FreeListInsert (pArena, pBT);
+
+ eError = _SegmentListInsertAfter (pArena, pBT, pSpanEnd);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_SegListInsert;
+ }
+
+#ifdef RA_STATS
+ pArena->sStatistics.uTotalResourceCount+=uSize;
+#endif
+ return pBT;
+
+ fail_SegListInsert:
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, IMG_NULL);
+
+ fail_bt:
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pSpanEnd, IMG_NULL);
+
+ fail_end:
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pSpanStart, IMG_NULL);
+
+ fail_start:
+ return IMG_NULL;
+}
+
+static IMG_VOID
+_FreeBT (RA_ARENA *pArena, BT *pBT, IMG_BOOL bFreeBackingStore)
+{
+ BT *pNeighbour;
+ IMG_UINTPTR_T uOrigBase;
+ IMG_SIZE_T uOrigSize;
+
+ PVR_ASSERT (pArena!=IMG_NULL);
+ PVR_ASSERT (pBT!=IMG_NULL);
+
+ if ((pArena == IMG_NULL) || (pBT == IMG_NULL))
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"_FreeBT: invalid parameter"));
+ return;
+ }
+
+#ifdef RA_STATS
+ pArena->sStatistics.uLiveSegmentCount--;
+ pArena->sStatistics.uFreeSegmentCount++;
+ pArena->sStatistics.uFreeResourceCount+=pBT->uSize;
+#endif
+
+ uOrigBase = pBT->base;
+ uOrigSize = pBT->uSize;
+
+
+ pNeighbour = pBT->pPrevSegment;
+ if (pNeighbour!=IMG_NULL
+ && pNeighbour->type == btt_free
+ && pNeighbour->base + pNeighbour->uSize == pBT->base)
+ {
+ _FreeListRemove (pArena, pNeighbour);
+ _SegmentListRemove (pArena, pNeighbour);
+ pBT->base = pNeighbour->base;
+ pBT->uSize += pNeighbour->uSize;
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pNeighbour, IMG_NULL);
+
+#ifdef RA_STATS
+ pArena->sStatistics.uFreeSegmentCount--;
+#endif
+ }
+
+
+ pNeighbour = pBT->pNextSegment;
+ if (pNeighbour!=IMG_NULL
+ && pNeighbour->type == btt_free
+ && pBT->base + pBT->uSize == pNeighbour->base)
+ {
+ _FreeListRemove (pArena, pNeighbour);
+ _SegmentListRemove (pArena, pNeighbour);
+ pBT->uSize += pNeighbour->uSize;
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pNeighbour, IMG_NULL);
+
+#ifdef RA_STATS
+ pArena->sStatistics.uFreeSegmentCount--;
+#endif
+ }
+
+
+ if (pArena->pBackingStoreFree != IMG_NULL && bFreeBackingStore)
+ {
+ IMG_UINTPTR_T uRoundedStart, uRoundedEnd;
+
+
+ uRoundedStart = (uOrigBase / pArena->uQuantum) * pArena->uQuantum;
+
+ if (uRoundedStart < pBT->base)
+ {
+ uRoundedStart += pArena->uQuantum;
+ }
+
+
+ uRoundedEnd = ((uOrigBase + uOrigSize + pArena->uQuantum - 1) / pArena->uQuantum) * pArena->uQuantum;
+
+ if (uRoundedEnd > (pBT->base + pBT->uSize))
+ {
+ uRoundedEnd -= pArena->uQuantum;
+ }
+
+ if (uRoundedStart < uRoundedEnd)
+ {
+ pArena->pBackingStoreFree(pArena->pImportHandle, (IMG_SIZE_T)uRoundedStart, (IMG_SIZE_T)uRoundedEnd, (IMG_HANDLE)0);
+ }
+ }
+
+ if (pBT->pNextSegment!=IMG_NULL && pBT->pNextSegment->type == btt_span
+ && pBT->pPrevSegment!=IMG_NULL && pBT->pPrevSegment->type == btt_span)
+ {
+ BT *next = pBT->pNextSegment;
+ BT *prev = pBT->pPrevSegment;
+ _SegmentListRemove (pArena, next);
+ _SegmentListRemove (pArena, prev);
+ _SegmentListRemove (pArena, pBT);
+ pArena->pImportFree (pArena->pImportHandle, pBT->base, pBT->psMapping);
+#ifdef RA_STATS
+ pArena->sStatistics.uSpanCount--;
+ pArena->sStatistics.uExportCount++;
+ pArena->sStatistics.uFreeSegmentCount--;
+ pArena->sStatistics.uFreeResourceCount-=pBT->uSize;
+ pArena->sStatistics.uTotalResourceCount-=pBT->uSize;
+#endif
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), next, IMG_NULL);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), prev, IMG_NULL);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, IMG_NULL);
+
+ }
+ else
+ _FreeListInsert (pArena, pBT);
+}
+
+
+static IMG_BOOL
+_AttemptAllocAligned (RA_ARENA *pArena,
+ IMG_SIZE_T uSize,
+ BM_MAPPING **ppsMapping,
+ IMG_UINT32 uFlags,
+ IMG_UINT32 uAlignment,
+ IMG_UINT32 uAlignmentOffset,
+ IMG_UINTPTR_T *base)
+{
+ IMG_UINT32 uIndex;
+ PVR_ASSERT (pArena!=IMG_NULL);
+ if (pArena == IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned: invalid parameter - pArena"));
+ return IMG_FALSE;
+ }
+
+ if (uAlignment>1)
+ uAlignmentOffset %= uAlignment;
+
+
+
+ uIndex = pvr_log2 (uSize);
+
+#if 0
+
+ if (1u<<uIndex < uSize)
+ uIndex++;
+#endif
+
+ while (uIndex < FREE_TABLE_LIMIT && pArena->aHeadFree[uIndex]==IMG_NULL)
+ uIndex++;
+
+ while (uIndex < FREE_TABLE_LIMIT)
+ {
+ if (pArena->aHeadFree[uIndex]!=IMG_NULL)
+ {
+
+ BT *pBT;
+
+ pBT = pArena->aHeadFree [uIndex];
+ while (pBT!=IMG_NULL)
+ {
+ IMG_UINTPTR_T aligned_base;
+
+ if (uAlignment>1)
+ aligned_base = (pBT->base + uAlignmentOffset + uAlignment - 1) / uAlignment * uAlignment - uAlignmentOffset;
+ else
+ aligned_base = pBT->base;
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "RA_AttemptAllocAligned: pBT-base=0x%x "
+ "pBT-size=0x%x alignedbase=0x%x size=0x%x",
+ pBT->base, pBT->uSize, aligned_base, uSize));
+
+ if (pBT->base + pBT->uSize >= aligned_base + uSize)
+ {
+ if(!pBT->psMapping || pBT->psMapping->ui32Flags == uFlags)
+ {
+ _FreeListRemove (pArena, pBT);
+
+ PVR_ASSERT (pBT->type == btt_free);
+
+#ifdef RA_STATS
+ pArena->sStatistics.uLiveSegmentCount++;
+ pArena->sStatistics.uFreeSegmentCount--;
+ pArena->sStatistics.uFreeResourceCount-=pBT->uSize;
+#endif
+
+
+ if (aligned_base > pBT->base)
+ {
+ BT *pNeighbour;
+ pNeighbour = _SegmentSplit (pArena, pBT, (IMG_SIZE_T)(aligned_base - pBT->base));
+
+ if (pNeighbour==IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned: Front split failed"));
+
+ _FreeListInsert (pArena, pBT);
+ return IMG_FALSE;
+ }
+
+ _FreeListInsert (pArena, pBT);
+ #ifdef RA_STATS
+ pArena->sStatistics.uFreeSegmentCount++;
+ pArena->sStatistics.uFreeResourceCount+=pBT->uSize;
+ #endif
+ pBT = pNeighbour;
+ }
+
+
+ if (pBT->uSize > uSize)
+ {
+ BT *pNeighbour;
+ pNeighbour = _SegmentSplit (pArena, pBT, uSize);
+
+ if (pNeighbour==IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned: Back split failed"));
+
+ _FreeListInsert (pArena, pBT);
+ return IMG_FALSE;
+ }
+
+ _FreeListInsert (pArena, pNeighbour);
+ #ifdef RA_STATS
+ pArena->sStatistics.uFreeSegmentCount++;
+ pArena->sStatistics.uFreeResourceCount+=pNeighbour->uSize;
+ #endif
+ }
+
+ pBT->type = btt_live;
+
+#if defined(VALIDATE_ARENA_TEST)
+ if (pBT->eResourceType == IMPORTED_RESOURCE_TYPE)
+ {
+ pBT->eResourceSpan = IMPORTED_RESOURCE_SPAN_LIVE;
+ }
+ else if (pBT->eResourceType == NON_IMPORTED_RESOURCE_TYPE)
+ {
+ pBT->eResourceSpan = RESOURCE_SPAN_LIVE;
+ }
+ else
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned ERROR: pBT->eResourceType unrecognized"));
+ PVR_DBG_BREAK;
+ }
+#endif
+ if (!HASH_Insert (pArena->pSegmentHash, pBT->base, (IMG_UINTPTR_T) pBT))
+ {
+ _FreeBT (pArena, pBT, IMG_FALSE);
+ return IMG_FALSE;
+ }
+
+ if (ppsMapping!=IMG_NULL)
+ *ppsMapping = pBT->psMapping;
+
+ *base = pBT->base;
+
+ return IMG_TRUE;
+ }
+ else
+ {
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "AttemptAllocAligned: mismatch in flags. Import has %x, request was %x", pBT->psMapping->ui32Flags, uFlags));
+
+ }
+ }
+ pBT = pBT->pNextFree;
+ }
+
+ }
+ uIndex++;
+ }
+
+ return IMG_FALSE;
+}
+
+
+
+RA_ARENA *
+RA_Create (IMG_CHAR *name,
+ IMG_UINTPTR_T base,
+ IMG_SIZE_T uSize,
+ BM_MAPPING *psMapping,
+ IMG_SIZE_T uQuantum,
+ IMG_BOOL (*imp_alloc)(IMG_VOID *, IMG_SIZE_T uSize, IMG_SIZE_T *pActualSize,
+ BM_MAPPING **ppsMapping, IMG_UINT32 _flags,
+ IMG_PVOID pvPrivData, IMG_UINT32 ui32PrivDataLength,
+ IMG_UINTPTR_T *pBase),
+ IMG_VOID (*imp_free) (IMG_VOID *, IMG_UINTPTR_T, BM_MAPPING *),
+ IMG_VOID (*backingstore_free) (IMG_VOID*, IMG_SIZE_T, IMG_SIZE_T, IMG_HANDLE),
+ IMG_VOID *pImportHandle)
+{
+ RA_ARENA *pArena;
+ BT *pBT;
+ IMG_INT i;
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "RA_Create: name='%s', base=0x%x, uSize=0x%x, alloc=0x%x, free=0x%x",
+ name, base, uSize, (IMG_UINTPTR_T)imp_alloc, (IMG_UINTPTR_T)imp_free));
+
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof (*pArena),
+ (IMG_VOID **)&pArena, IMG_NULL,
+ "Resource Arena") != PVRSRV_OK)
+ {
+ goto arena_fail;
+ }
+
+ pArena->name = name;
+ pArena->pImportAlloc = (imp_alloc!=IMG_NULL) ? imp_alloc : &_RequestAllocFail;
+ pArena->pImportFree = imp_free;
+ pArena->pBackingStoreFree = backingstore_free;
+ pArena->pImportHandle = pImportHandle;
+ for (i=0; i<FREE_TABLE_LIMIT; i++)
+ pArena->aHeadFree[i] = IMG_NULL;
+ pArena->pHeadSegment = IMG_NULL;
+ pArena->pTailSegment = IMG_NULL;
+ pArena->uQuantum = uQuantum;
+
+#ifdef RA_STATS
+ pArena->sStatistics.uSpanCount = 0;
+ pArena->sStatistics.uLiveSegmentCount = 0;
+ pArena->sStatistics.uFreeSegmentCount = 0;
+ pArena->sStatistics.uFreeResourceCount = 0;
+ pArena->sStatistics.uTotalResourceCount = 0;
+ pArena->sStatistics.uCumulativeAllocs = 0;
+ pArena->sStatistics.uCumulativeFrees = 0;
+ pArena->sStatistics.uImportCount = 0;
+ pArena->sStatistics.uExportCount = 0;
+#endif
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+ if(strcmp(pArena->name,"") != 0)
+ {
+ IMG_INT ret;
+ IMG_CHAR szProcInfoName[PROC_NAME_SIZE];
+ IMG_CHAR szProcSegsName[PROC_NAME_SIZE];
+ struct proc_dir_entry* (*pfnCreateProcEntrySeq)(const IMG_CHAR *,
+ IMG_VOID*,
+ pvr_next_proc_seq_t,
+ pvr_show_proc_seq_t,
+ pvr_off2element_proc_seq_t,
+ pvr_startstop_proc_seq_t,
+ write_proc_t);
+
+ pArena->bInitProcEntry = !PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL);
+
+
+ pfnCreateProcEntrySeq = pArena->bInitProcEntry ? CreateProcEntrySeq : CreatePerProcessProcEntrySeq;
+
+ ret = snprintf(szProcInfoName, sizeof(szProcInfoName), "ra_info_%s", pArena->name);
+ if (ret > 0 && ret < sizeof(szProcInfoName))
+ {
+ pArena->pProcInfo = pfnCreateProcEntrySeq(ReplaceSpaces(szProcInfoName), pArena, NULL,
+ RA_ProcSeqShowInfo, RA_ProcSeqOff2ElementInfo, NULL, NULL);
+ }
+ else
+ {
+ pArena->pProcInfo = 0;
+ PVR_DPF((PVR_DBG_ERROR, "RA_Create: couldn't create ra_info proc entry for arena %s", pArena->name));
+ }
+
+ ret = snprintf(szProcSegsName, sizeof(szProcSegsName), "ra_segs_%s", pArena->name);
+ if (ret > 0 && ret < sizeof(szProcInfoName))
+ {
+ pArena->pProcSegs = pfnCreateProcEntrySeq(ReplaceSpaces(szProcSegsName), pArena, NULL,
+ RA_ProcSeqShowRegs, RA_ProcSeqOff2ElementRegs, NULL, NULL);
+ }
+ else
+ {
+ pArena->pProcSegs = 0;
+ PVR_DPF((PVR_DBG_ERROR, "RA_Create: couldn't create ra_segs proc entry for arena %s", pArena->name));
+ }
+ }
+#endif
+
+ pArena->pSegmentHash = HASH_Create (MINIMUM_HASH_SIZE);
+ if (pArena->pSegmentHash==IMG_NULL)
+ {
+ goto hash_fail;
+ }
+ if (uSize>0)
+ {
+ uSize = (uSize + uQuantum - 1) / uQuantum * uQuantum;
+ pBT = _InsertResource (pArena, base, uSize);
+ if (pBT == IMG_NULL)
+ {
+ goto insert_fail;
+ }
+ pBT->psMapping = psMapping;
+
+ }
+ return pArena;
+
+insert_fail:
+ HASH_Delete (pArena->pSegmentHash);
+hash_fail:
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RA_ARENA), pArena, IMG_NULL);
+
+arena_fail:
+ return IMG_NULL;
+}
+
+IMG_VOID
+RA_Delete (RA_ARENA *pArena)
+{
+ IMG_UINT32 uIndex;
+
+ PVR_ASSERT(pArena != IMG_NULL);
+
+ if (pArena == IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"RA_Delete: invalid parameter - pArena"));
+ return;
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "RA_Delete: name='%s'", pArena->name));
+
+ for (uIndex=0; uIndex<FREE_TABLE_LIMIT; uIndex++)
+ pArena->aHeadFree[uIndex] = IMG_NULL;
+
+ while (pArena->pHeadSegment != IMG_NULL)
+ {
+ BT *pBT = pArena->pHeadSegment;
+
+ if (pBT->type != btt_free)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"RA_Delete: allocations still exist in the arena that is being destroyed"));
+ PVR_DPF ((PVR_DBG_ERROR,"Likely Cause: client drivers not freeing alocations before destroying devmemcontext"));
+ PVR_DPF ((PVR_DBG_ERROR,"RA_Delete: base = 0x%x size=0x%x", pBT->base, pBT->uSize));
+ }
+
+ _SegmentListRemove (pArena, pBT);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, IMG_NULL);
+
+#ifdef RA_STATS
+ pArena->sStatistics.uSpanCount--;
+#endif
+ }
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+ {
+ IMG_VOID (*pfnRemoveProcEntrySeq)(struct proc_dir_entry*);
+
+ pfnRemoveProcEntrySeq = pArena->bInitProcEntry ? RemoveProcEntrySeq : RemovePerProcessProcEntrySeq;
+
+ if (pArena->pProcInfo != 0)
+ {
+ pfnRemoveProcEntrySeq( pArena->pProcInfo );
+ }
+
+ if (pArena->pProcSegs != 0)
+ {
+ pfnRemoveProcEntrySeq( pArena->pProcSegs );
+ }
+ }
+#endif
+ HASH_Delete (pArena->pSegmentHash);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RA_ARENA), pArena, IMG_NULL);
+
+}
+
+IMG_BOOL
+RA_TestDelete (RA_ARENA *pArena)
+{
+ PVR_ASSERT(pArena != IMG_NULL);
+
+ if (pArena != IMG_NULL)
+ {
+ while (pArena->pHeadSegment != IMG_NULL)
+ {
+ BT *pBT = pArena->pHeadSegment;
+ if (pBT->type != btt_free)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"RA_TestDelete: detected resource leak!"));
+ PVR_DPF ((PVR_DBG_ERROR,"RA_TestDelete: base = 0x%x size=0x%x", pBT->base, pBT->uSize));
+ return IMG_FALSE;
+ }
+ }
+ }
+
+ return IMG_TRUE;
+}
+
+IMG_BOOL
+RA_Add (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
+{
+ PVR_ASSERT (pArena != IMG_NULL);
+
+ if (pArena == IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"RA_Add: invalid parameter - pArena"));
+ return IMG_FALSE;
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "RA_Add: name='%s', base=0x%x, size=0x%x", pArena->name, base, uSize));
+
+ uSize = (uSize + pArena->uQuantum - 1) / pArena->uQuantum * pArena->uQuantum;
+ return ((IMG_BOOL)(_InsertResource (pArena, base, uSize) != IMG_NULL));
+}
+
+IMG_BOOL
+RA_Alloc (RA_ARENA *pArena,
+ IMG_SIZE_T uRequestSize,
+ IMG_SIZE_T *pActualSize,
+ BM_MAPPING **ppsMapping,
+ IMG_UINT32 uFlags,
+ IMG_UINT32 uAlignment,
+ IMG_UINT32 uAlignmentOffset,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
+ IMG_UINTPTR_T *base)
+{
+ IMG_BOOL bResult;
+ IMG_SIZE_T uSize = uRequestSize;
+
+ PVR_ASSERT (pArena!=IMG_NULL);
+
+ if (pArena == IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"RA_Alloc: invalid parameter - pArena"));
+ return IMG_FALSE;
+ }
+
+#if defined(VALIDATE_ARENA_TEST)
+ ValidateArena(pArena);
+#endif
+
+#ifdef USE_BM_FREESPACE_CHECK
+ CheckBMFreespace();
+#endif
+
+ if (pActualSize != IMG_NULL)
+ {
+ *pActualSize = uSize;
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "RA_Alloc: arena='%s', size=0x%x(0x%x), alignment=0x%x, offset=0x%x",
+ pArena->name, uSize, uRequestSize, uAlignment, uAlignmentOffset));
+
+
+
+ bResult = _AttemptAllocAligned (pArena, uSize, ppsMapping, uFlags,
+ uAlignment, uAlignmentOffset, base);
+ if (!bResult)
+ {
+ BM_MAPPING *psImportMapping;
+ IMG_UINTPTR_T import_base;
+ IMG_SIZE_T uImportSize = uSize;
+
+
+
+
+ if (uAlignment > pArena->uQuantum)
+ {
+ uImportSize += (uAlignment - 1);
+ }
+
+
+ uImportSize = ((uImportSize + pArena->uQuantum - 1)/pArena->uQuantum)*pArena->uQuantum;
+
+ bResult =
+ pArena->pImportAlloc (pArena->pImportHandle, uImportSize, &uImportSize,
+ &psImportMapping, uFlags,
+ pvPrivData, ui32PrivDataLength, &import_base);
+ if (bResult)
+ {
+ BT *pBT;
+ pBT = _InsertResourceSpan (pArena, import_base, uImportSize);
+
+ if (pBT == IMG_NULL)
+ {
+
+ pArena->pImportFree(pArena->pImportHandle, import_base,
+ psImportMapping);
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "RA_Alloc: name='%s', size=0x%x failed!",
+ pArena->name, uSize));
+
+ return IMG_FALSE;
+ }
+ pBT->psMapping = psImportMapping;
+#ifdef RA_STATS
+ pArena->sStatistics.uFreeSegmentCount++;
+ pArena->sStatistics.uFreeResourceCount += uImportSize;
+ pArena->sStatistics.uImportCount++;
+ pArena->sStatistics.uSpanCount++;
+#endif
+ bResult = _AttemptAllocAligned(pArena, uSize, ppsMapping, uFlags,
+ uAlignment, uAlignmentOffset,
+ base);
+ if (!bResult)
+ {
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "RA_Alloc: name='%s' uAlignment failed!",
+ pArena->name));
+ }
+ }
+ }
+#ifdef RA_STATS
+ if (bResult)
+ pArena->sStatistics.uCumulativeAllocs++;
+#endif
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "RA_Alloc: name='%s', size=0x%x, *base=0x%x = %d",
+ pArena->name, uSize, *base, bResult));
+
+
+
+#if defined(VALIDATE_ARENA_TEST)
+ ValidateArena(pArena);
+#endif
+
+ return bResult;
+}
+
+
+#if defined(VALIDATE_ARENA_TEST)
+
+IMG_UINT32 ValidateArena(RA_ARENA *pArena)
+{
+ BT* pSegment;
+ RESOURCE_DESCRIPTOR eNextSpan;
+
+ pSegment = pArena->pHeadSegment;
+
+ if (pSegment == IMG_NULL)
+ {
+ return 0;
+ }
+
+ if (pSegment->eResourceType == IMPORTED_RESOURCE_TYPE)
+ {
+ PVR_ASSERT(pSegment->eResourceSpan == IMPORTED_RESOURCE_SPAN_START);
+
+ while (pSegment->pNextSegment)
+ {
+ eNextSpan = pSegment->pNextSegment->eResourceSpan;
+
+ switch (pSegment->eResourceSpan)
+ {
+ case IMPORTED_RESOURCE_SPAN_LIVE:
+
+ if (!((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) ||
+ (eNextSpan == IMPORTED_RESOURCE_SPAN_FREE) ||
+ (eNextSpan == IMPORTED_RESOURCE_SPAN_END)))
+ {
+
+ PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+ pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+ PVR_DBG_BREAK;
+ }
+ break;
+
+ case IMPORTED_RESOURCE_SPAN_FREE:
+
+ if (!((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) ||
+ (eNextSpan == IMPORTED_RESOURCE_SPAN_END)))
+ {
+
+ PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+ pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+ PVR_DBG_BREAK;
+ }
+ break;
+
+ case IMPORTED_RESOURCE_SPAN_END:
+
+ if ((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) ||
+ (eNextSpan == IMPORTED_RESOURCE_SPAN_FREE) ||
+ (eNextSpan == IMPORTED_RESOURCE_SPAN_END))
+ {
+
+ PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+ pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+ PVR_DBG_BREAK;
+ }
+ break;
+
+
+ case IMPORTED_RESOURCE_SPAN_START:
+
+ if (!((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) ||
+ (eNextSpan == IMPORTED_RESOURCE_SPAN_FREE)))
+ {
+
+ PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+ pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+ PVR_DBG_BREAK;
+ }
+ break;
+
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+ pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+ PVR_DBG_BREAK;
+ break;
+ }
+ pSegment = pSegment->pNextSegment;
+ }
+ }
+ else if (pSegment->eResourceType == NON_IMPORTED_RESOURCE_TYPE)
+ {
+ PVR_ASSERT((pSegment->eResourceSpan == RESOURCE_SPAN_FREE) || (pSegment->eResourceSpan == RESOURCE_SPAN_LIVE));
+
+ while (pSegment->pNextSegment)
+ {
+ eNextSpan = pSegment->pNextSegment->eResourceSpan;
+
+ switch (pSegment->eResourceSpan)
+ {
+ case RESOURCE_SPAN_LIVE:
+
+ if (!((eNextSpan == RESOURCE_SPAN_FREE) ||
+ (eNextSpan == RESOURCE_SPAN_LIVE)))
+ {
+
+ PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+ pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+ PVR_DBG_BREAK;
+ }
+ break;
+
+ case RESOURCE_SPAN_FREE:
+
+ if (!((eNextSpan == RESOURCE_SPAN_FREE) ||
+ (eNextSpan == RESOURCE_SPAN_LIVE)))
+ {
+
+ PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+ pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+ PVR_DBG_BREAK;
+ }
+ break;
+
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+ pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+ PVR_DBG_BREAK;
+ break;
+ }
+ pSegment = pSegment->pNextSegment;
+ }
+
+ }
+ else
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"ValidateArena ERROR: pSegment->eResourceType unrecognized"));
+
+ PVR_DBG_BREAK;
+ }
+
+ return 0;
+}
+
+#endif
+
+
+IMG_VOID
+RA_Free (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_BOOL bFreeBackingStore)
+{
+ BT *pBT;
+
+ PVR_ASSERT (pArena != IMG_NULL);
+
+ if (pArena == IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"RA_Free: invalid parameter - pArena"));
+ return;
+ }
+
+#ifdef USE_BM_FREESPACE_CHECK
+ CheckBMFreespace();
+#endif
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "RA_Free: name='%s', base=0x%x", pArena->name, base));
+
+ pBT = (BT *) HASH_Remove (pArena->pSegmentHash, base);
+ PVR_ASSERT (pBT != IMG_NULL);
+
+ if (pBT)
+ {
+ PVR_ASSERT (pBT->base == base);
+
+#ifdef RA_STATS
+ pArena->sStatistics.uCumulativeFrees++;
+#endif
+
+#ifdef USE_BM_FREESPACE_CHECK
+{
+ IMG_BYTE* p;
+ IMG_BYTE* endp;
+
+ p = (IMG_BYTE*)pBT->base + SysGetDevicePhysOffset();
+ endp = (IMG_BYTE*)((IMG_UINT32)(p + pBT->uSize));
+ while ((IMG_UINT32)p & 3)
+ {
+ *p++ = 0xAA;
+ }
+ while (p < (IMG_BYTE*)((IMG_UINT32)endp & 0xfffffffc))
+ {
+ *(IMG_UINT32*)p = 0xAAAAAAAA;
+ p += sizeof(IMG_UINT32);
+ }
+ while (p < endp)
+ {
+ *p++ = 0xAA;
+ }
+ PVR_DPF((PVR_DBG_MESSAGE,"BM_FREESPACE_CHECK: RA_Free Cleared %08X to %08X (size=0x%x)",(IMG_BYTE*)pBT->base + SysGetDevicePhysOffset(),endp-1,pBT->uSize));
+}
+#endif
+ _FreeBT (pArena, pBT, bFreeBackingStore);
+ }
+}
+
+
+IMG_BOOL RA_GetNextLiveSegment(IMG_HANDLE hArena, RA_SEGMENT_DETAILS *psSegDetails)
+{
+ BT *pBT;
+
+ if (psSegDetails->hSegment)
+ {
+ pBT = (BT *)psSegDetails->hSegment;
+ }
+ else
+ {
+ RA_ARENA *pArena = (RA_ARENA *)hArena;
+
+ pBT = pArena->pHeadSegment;
+ }
+
+ while (pBT != IMG_NULL)
+ {
+ if (pBT->type == btt_live)
+ {
+ psSegDetails->uiSize = pBT->uSize;
+ psSegDetails->sCpuPhyAddr.uiAddr = pBT->base;
+ psSegDetails->hSegment = (IMG_HANDLE)pBT->pNextSegment;
+
+ return IMG_TRUE;
+ }
+
+ pBT = pBT->pNextSegment;
+ }
+
+ psSegDetails->uiSize = 0;
+ psSegDetails->sCpuPhyAddr.uiAddr = 0;
+ psSegDetails->hSegment = (IMG_HANDLE)IMG_UNDEF;
+
+ return IMG_FALSE;
+}
+
+
+#ifdef USE_BM_FREESPACE_CHECK
+RA_ARENA* pJFSavedArena = IMG_NULL;
+
+IMG_VOID CheckBMFreespace(IMG_VOID)
+{
+ BT *pBT;
+ IMG_BYTE* p;
+ IMG_BYTE* endp;
+
+ if (pJFSavedArena != IMG_NULL)
+ {
+ for (pBT=pJFSavedArena->pHeadSegment; pBT!=IMG_NULL; pBT=pBT->pNextSegment)
+ {
+ if (pBT->type == btt_free)
+ {
+ p = (IMG_BYTE*)pBT->base + SysGetDevicePhysOffset();
+ endp = (IMG_BYTE*)((IMG_UINT32)(p + pBT->uSize) & 0xfffffffc);
+
+ while ((IMG_UINT32)p & 3)
+ {
+ if (*p++ != 0xAA)
+ {
+ fprintf(stderr,"BM_FREESPACE_CHECK: Blank space at %08X has changed to 0x%x\n",p,*(IMG_UINT32*)p);
+ for (;;);
+ break;
+ }
+ }
+ while (p < endp)
+ {
+ if (*(IMG_UINT32*)p != 0xAAAAAAAA)
+ {
+ fprintf(stderr,"BM_FREESPACE_CHECK: Blank space at %08X has changed to 0x%x\n",p,*(IMG_UINT32*)p);
+ for (;;);
+ break;
+ }
+ p += 4;
+ }
+ }
+ }
+ }
+}
+#endif
+
+
+#if (defined(CONFIG_PROC_FS) && defined(DEBUG)) || defined (RA_STATS)
+static IMG_CHAR *
+_BTType (IMG_INT eType)
+{
+ switch (eType)
+ {
+ case btt_span: return "span";
+ case btt_free: return "free";
+ case btt_live: return "live";
+ }
+ return "junk";
+}
+#endif
+
+#if defined(ENABLE_RA_DUMP)
+IMG_VOID
+RA_Dump (RA_ARENA *pArena)
+{
+ BT *pBT;
+ PVR_ASSERT (pArena != IMG_NULL);
+ PVR_DPF ((PVR_DBG_MESSAGE,"Arena '%s':", pArena->name));
+ PVR_DPF ((PVR_DBG_MESSAGE," alloc=%08X free=%08X handle=%08X quantum=%d",
+ pArena->pImportAlloc, pArena->pImportFree, pArena->pImportHandle,
+ pArena->uQuantum));
+ PVR_DPF ((PVR_DBG_MESSAGE," segment Chain:"));
+ if (pArena->pHeadSegment != IMG_NULL &&
+ pArena->pHeadSegment->pPrevSegment != IMG_NULL)
+ PVR_DPF ((PVR_DBG_MESSAGE," error: head boundary tag has invalid pPrevSegment"));
+ if (pArena->pTailSegment != IMG_NULL &&
+ pArena->pTailSegment->pNextSegment != IMG_NULL)
+ PVR_DPF ((PVR_DBG_MESSAGE," error: tail boundary tag has invalid pNextSegment"));
+
+ for (pBT=pArena->pHeadSegment; pBT!=IMG_NULL; pBT=pBT->pNextSegment)
+ {
+ PVR_DPF ((PVR_DBG_MESSAGE,"\tbase=0x%x size=0x%x type=%s ref=%08X",
+ (IMG_UINT32) pBT->base, pBT->uSize, _BTType (pBT->type),
+ pBT->pRef));
+ }
+
+#ifdef HASH_TRACE
+ HASH_Dump (pArena->pSegmentHash);
+#endif
+}
+#endif
+
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+
+
+static void RA_ProcSeqShowInfo(struct seq_file *sfile, void* el)
+{
+ PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)sfile->private;
+ RA_ARENA *pArena = (RA_ARENA *)handlers->data;
+ IMG_INT off = (IMG_INT)el;
+
+ switch (off)
+ {
+ case 1:
+ seq_printf(sfile, "quantum\t\t\t%u\n", pArena->uQuantum);
+ break;
+ case 2:
+ seq_printf(sfile, "import_handle\t\t%08X\n", (IMG_UINT)pArena->pImportHandle);
+ break;
+#ifdef RA_STATS
+ case 3:
+ seq_printf(sfile,"span count\t\t%u\n", pArena->sStatistics.uSpanCount);
+ break;
+ case 4:
+ seq_printf(sfile, "live segment count\t%u\n", pArena->sStatistics.uLiveSegmentCount);
+ break;
+ case 5:
+ seq_printf(sfile, "free segment count\t%u\n", pArena->sStatistics.uFreeSegmentCount);
+ break;
+ case 6:
+ seq_printf(sfile, "free resource count\t%u (0x%x)\n",
+ pArena->sStatistics.uFreeResourceCount,
+ (IMG_UINT)pArena->sStatistics.uFreeResourceCount);
+ break;
+ case 7:
+ seq_printf(sfile, "total allocs\t\t%u\n", pArena->sStatistics.uCumulativeAllocs);
+ break;
+ case 8:
+ seq_printf(sfile, "total frees\t\t%u\n", pArena->sStatistics.uCumulativeFrees);
+ break;
+ case 9:
+ seq_printf(sfile, "import count\t\t%u\n", pArena->sStatistics.uImportCount);
+ break;
+ case 10:
+ seq_printf(sfile, "export count\t\t%u\n", pArena->sStatistics.uExportCount);
+ break;
+#endif
+ }
+
+}
+
+static void* RA_ProcSeqOff2ElementInfo(struct seq_file * sfile, loff_t off)
+{
+#ifdef RA_STATS
+ if(off <= 9)
+#else
+ if(off <= 1)
+#endif
+ return (void*)(IMG_INT)(off+1);
+ return 0;
+}
+
+static void RA_ProcSeqShowRegs(struct seq_file *sfile, void* el)
+{
+ PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)sfile->private;
+ RA_ARENA *pArena = (RA_ARENA *)handlers->data;
+ BT *pBT = (BT*)el;
+
+ if (el == PVR_PROC_SEQ_START_TOKEN)
+ {
+ seq_printf(sfile, "Arena \"%s\"\nBase Size Type Ref\n", pArena->name);
+ return;
+ }
+
+ if (pBT)
+ {
+ seq_printf(sfile, "%08x %8x %4s %08x\n",
+ (IMG_UINT)pBT->base, (IMG_UINT)pBT->uSize, _BTType (pBT->type),
+ (IMG_UINT)pBT->psMapping);
+ }
+}
+
+static void* RA_ProcSeqOff2ElementRegs(struct seq_file * sfile, loff_t off)
+{
+ PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)sfile->private;
+ RA_ARENA *pArena = (RA_ARENA *)handlers->data;
+ BT *pBT = 0;
+
+ if(off == 0)
+ return PVR_PROC_SEQ_START_TOKEN;
+
+ for (pBT=pArena->pHeadSegment; --off && pBT; pBT=pBT->pNextSegment);
+
+ return (void*)pBT;
+}
+
+#endif
+
+
+#ifdef RA_STATS
+PVRSRV_ERROR RA_GetStats(RA_ARENA *pArena,
+ IMG_CHAR **ppszStr,
+ IMG_UINT32 *pui32StrLen)
+{
+ IMG_CHAR *pszStr = *ppszStr;
+ IMG_UINT32 ui32StrLen = *pui32StrLen;
+ IMG_INT32 i32Count;
+ BT *pBT;
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "\nArena '%s':\n", pArena->name);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, " allocCB=%p freeCB=%p handle=%p quantum=%d\n",
+ pArena->pImportAlloc,
+ pArena->pImportFree,
+ pArena->pImportHandle,
+ pArena->uQuantum);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "span count\t\t%u\n", pArena->sStatistics.uSpanCount);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "live segment count\t%u\n", pArena->sStatistics.uLiveSegmentCount);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "free segment count\t%u\n", pArena->sStatistics.uFreeSegmentCount);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "free resource count\t%u (0x%x)\n",
+ pArena->sStatistics.uFreeResourceCount,
+ (IMG_UINT)pArena->sStatistics.uFreeResourceCount);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "total allocs\t\t%u\n", pArena->sStatistics.uCumulativeAllocs);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "total frees\t\t%u\n", pArena->sStatistics.uCumulativeFrees);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "import count\t\t%u\n", pArena->sStatistics.uImportCount);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "export count\t\t%u\n", pArena->sStatistics.uExportCount);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, " segment Chain:\n");
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ if (pArena->pHeadSegment != IMG_NULL &&
+ pArena->pHeadSegment->pPrevSegment != IMG_NULL)
+ {
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, " error: head boundary tag has invalid pPrevSegment\n");
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+ }
+
+ if (pArena->pTailSegment != IMG_NULL &&
+ pArena->pTailSegment->pNextSegment != IMG_NULL)
+ {
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, " error: tail boundary tag has invalid pNextSegment\n");
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+ }
+
+ for (pBT=pArena->pHeadSegment; pBT!=IMG_NULL; pBT=pBT->pNextSegment)
+ {
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "\tbase=0x%x size=0x%x type=%s ref=%p\n",
+ (IMG_UINT32) pBT->base,
+ pBT->uSize,
+ _BTType(pBT->type),
+ pBT->psMapping);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+ }
+
+ *ppszStr = pszStr;
+ *pui32StrLen = ui32StrLen;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR RA_GetStatsFreeMem(RA_ARENA *pArena,
+ IMG_CHAR **ppszStr,
+ IMG_UINT32 *pui32StrLen)
+{
+ IMG_CHAR *pszStr = *ppszStr;
+ IMG_UINT32 ui32StrLen = *pui32StrLen;
+ IMG_INT32 i32Count;
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "Bytes free: Arena %-30s: %u (0x%x)\n", pArena->name,
+ pArena->sStatistics.uFreeResourceCount,
+ pArena->sStatistics.uFreeResourceCount);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+ *ppszStr = pszStr;
+ *pui32StrLen = ui32StrLen;
+
+ return PVRSRV_OK;
+}
+#endif
+
diff --git a/drivers/gpu/pvr/ra.h b/drivers/gpu/pvr/ra.h
new file mode 100644
index 0000000..d836215
--- /dev/null
+++ b/drivers/gpu/pvr/ra.h
@@ -0,0 +1,163 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef _RA_H_
+#define _RA_H_
+
+#include "img_types.h"
+#include "hash.h"
+#include "osfunc.h"
+
+typedef struct _RA_ARENA_ RA_ARENA;
+typedef struct _BM_MAPPING_ BM_MAPPING;
+
+
+
+#define RA_STATS
+
+
+struct _RA_STATISTICS_
+{
+
+ IMG_SIZE_T uSpanCount;
+
+
+ IMG_SIZE_T uLiveSegmentCount;
+
+
+ IMG_SIZE_T uFreeSegmentCount;
+
+
+ IMG_SIZE_T uTotalResourceCount;
+
+
+ IMG_SIZE_T uFreeResourceCount;
+
+
+ IMG_SIZE_T uCumulativeAllocs;
+
+
+ IMG_SIZE_T uCumulativeFrees;
+
+
+ IMG_SIZE_T uImportCount;
+
+
+ IMG_SIZE_T uExportCount;
+};
+typedef struct _RA_STATISTICS_ RA_STATISTICS;
+
+struct _RA_SEGMENT_DETAILS_
+{
+ IMG_SIZE_T uiSize;
+ IMG_CPU_PHYADDR sCpuPhyAddr;
+ IMG_HANDLE hSegment;
+};
+typedef struct _RA_SEGMENT_DETAILS_ RA_SEGMENT_DETAILS;
+
+RA_ARENA *
+RA_Create (IMG_CHAR *name,
+ IMG_UINTPTR_T base,
+ IMG_SIZE_T uSize,
+ BM_MAPPING *psMapping,
+ IMG_SIZE_T uQuantum,
+ IMG_BOOL (*imp_alloc)(IMG_VOID *_h,
+ IMG_SIZE_T uSize,
+ IMG_SIZE_T *pActualSize,
+ BM_MAPPING **ppsMapping,
+ IMG_UINT32 uFlags,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
+ IMG_UINTPTR_T *pBase),
+ IMG_VOID (*imp_free) (IMG_VOID *,
+ IMG_UINTPTR_T,
+ BM_MAPPING *),
+ IMG_VOID (*backingstore_free) (IMG_VOID *,
+ IMG_SIZE_T,
+ IMG_SIZE_T,
+ IMG_HANDLE),
+ IMG_VOID *import_handle);
+
+IMG_VOID
+RA_Delete (RA_ARENA *pArena);
+
+IMG_BOOL
+RA_TestDelete (RA_ARENA *pArena);
+
+IMG_BOOL
+RA_Add (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize);
+
+IMG_BOOL
+RA_Alloc (RA_ARENA *pArena,
+ IMG_SIZE_T uSize,
+ IMG_SIZE_T *pActualSize,
+ BM_MAPPING **ppsMapping,
+ IMG_UINT32 uFlags,
+ IMG_UINT32 uAlignment,
+ IMG_UINT32 uAlignmentOffset,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
+ IMG_UINTPTR_T *pBase);
+
+IMG_VOID
+RA_Free (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_BOOL bFreeBackingStore);
+
+
+#ifdef RA_STATS
+
+#define CHECK_SPACE(total) \
+{ \
+ if((total)<100) \
+ return PVRSRV_ERROR_INVALID_PARAMS; \
+}
+
+#define UPDATE_SPACE(str, count, total) \
+{ \
+ if((count) == -1) \
+ return PVRSRV_ERROR_INVALID_PARAMS; \
+ else \
+ { \
+ (str) += (count); \
+ (total) -= (count); \
+ } \
+}
+
+
+IMG_BOOL RA_GetNextLiveSegment(IMG_HANDLE hArena, RA_SEGMENT_DETAILS *psSegDetails);
+
+
+PVRSRV_ERROR RA_GetStats(RA_ARENA *pArena,
+ IMG_CHAR **ppszStr,
+ IMG_UINT32 *pui32StrLen);
+
+PVRSRV_ERROR RA_GetStatsFreeMem(RA_ARENA *pArena,
+ IMG_CHAR **ppszStr,
+ IMG_UINT32 *pui32StrLen);
+
+#endif
+
+#endif
+
diff --git a/drivers/gpu/pvr/refcount.c b/drivers/gpu/pvr/refcount.c
new file mode 100644
index 0000000..5bc9b4a
--- /dev/null
+++ b/drivers/gpu/pvr/refcount.c
@@ -0,0 +1,568 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+*/ /**************************************************************************/
+
+#if defined(PVRSRV_REFCOUNT_DEBUG)
+
+#include "services_headers.h"
+
+#ifndef __linux__
+#warning Reference count debugging is not thread-safe on this platform
+#define PVRSRV_LOCK_CCB()
+#define PVRSRV_UNLOCK_CCB()
+#else /* __linux__ */
+#include <linux/mutex.h>
+static DEFINE_MUTEX(gsCCBLock);
+#define PVRSRV_LOCK_CCB() mutex_lock(&gsCCBLock)
+#define PVRSRV_UNLOCK_CCB() mutex_unlock(&gsCCBLock)
+#endif /* __linux__ */
+
+#define PVRSRV_REFCOUNT_CCB_MAX 512
+#define PVRSRV_REFCOUNT_CCB_MESG_MAX 80
+
+#define PVRSRV_REFCOUNT_CCB_DEBUG_SYNCINFO (1U << 0)
+#define PVRSRV_REFCOUNT_CCB_DEBUG_MEMINFO (1U << 1)
+#define PVRSRV_REFCOUNT_CCB_DEBUG_BM_BUF (1U << 2)
+#define PVRSRV_REFCOUNT_CCB_DEBUG_BM_BUF2 (1U << 3)
+#define PVRSRV_REFCOUNT_CCB_DEBUG_BM_XPROC (1U << 4)
+
+#if defined(__linux__)
+#define PVRSRV_REFCOUNT_CCB_DEBUG_MMAP (1U << 16)
+#define PVRSRV_REFCOUNT_CCB_DEBUG_MMAP2 (1U << 17)
+#else
+#define PVRSRV_REFCOUNT_CCB_DEBUG_MMAP 0
+#define PVRSRV_REFCOUNT_CCB_DEBUG_MMAP2 0
+#endif
+
+#define PVRSRV_REFCOUNT_CCB_DEBUG_ALL ~0U
+
+/*static const IMG_UINT guiDebugMask = PVRSRV_REFCOUNT_CCB_DEBUG_ALL;*/
+static const IMG_UINT guiDebugMask =
+ PVRSRV_REFCOUNT_CCB_DEBUG_SYNCINFO |
+ PVRSRV_REFCOUNT_CCB_DEBUG_MMAP2;
+
+typedef struct
+{
+ const IMG_CHAR *pszFile;
+ IMG_INT iLine;
+ IMG_UINT32 ui32PID;
+ IMG_CHAR pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX];
+}
+PVRSRV_REFCOUNT_CCB;
+
+static PVRSRV_REFCOUNT_CCB gsRefCountCCB[PVRSRV_REFCOUNT_CCB_MAX];
+static IMG_UINT giOffset;
+
+static const IMG_CHAR gszHeader[] =
+ /* 10 20 30 40 50 60 70
+ * 345678901234567890123456789012345678901234567890123456789012345678901
+ */
+ "TYPE SYNCINFO MEMINFO MEMHANDLE OTHER REF REF' SIZE PID";
+ /* NCINFO deadbeef deadbeef deadbeef deadbeef 1234 1234 deadbeef */
+
+#define PVRSRV_REFCOUNT_CCB_FMT_STRING "%8.8s %8p %8p %8p %8p %.4d %.4d %.8x"
+
+IMG_INTERNAL
+void PVRSRVDumpRefCountCCB(void)
+{
+ int i;
+
+ PVRSRV_LOCK_CCB();
+
+ PVR_LOG(("%s", gszHeader));
+
+ for(i = 0; i < PVRSRV_REFCOUNT_CCB_MAX; i++)
+ {
+ PVRSRV_REFCOUNT_CCB *psRefCountCCBEntry =
+ &gsRefCountCCB[(giOffset + i) % PVRSRV_REFCOUNT_CCB_MAX];
+
+ /* Early on, we won't have MAX_REFCOUNT_CCB_SIZE messages */
+ if(!psRefCountCCBEntry->pszFile)
+ break;
+
+ PVR_LOG(("%s %d %s:%d", psRefCountCCBEntry->pcMesg,
+ psRefCountCCBEntry->ui32PID,
+ psRefCountCCBEntry->pszFile,
+ psRefCountCCBEntry->iLine));
+ }
+
+ PVRSRV_UNLOCK_CCB();
+}
+
+IMG_INTERNAL
+void PVRSRVKernelSyncInfoIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo,
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ IMG_UINT32 ui32RefValue = OSAtomicRead(psKernelSyncInfo->pvRefCount);
+
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_SYNCINFO))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "SYNCINFO",
+ psKernelSyncInfo,
+ psKernelMemInfo,
+ NULL,
+ (psKernelMemInfo) ? psKernelMemInfo->sMemBlk.hOSMemHandle : NULL,
+ ui32RefValue,
+ ui32RefValue + 1,
+ (psKernelMemInfo) ? psKernelMemInfo->uAllocSize : 0);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ PVRSRVAcquireSyncInfoKM(psKernelSyncInfo);
+}
+
+IMG_INTERNAL
+void PVRSRVKernelSyncInfoDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo,
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ IMG_UINT32 ui32RefValue = OSAtomicRead(psKernelSyncInfo->pvRefCount);
+
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_SYNCINFO))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "SYNCINFO",
+ psKernelSyncInfo,
+ psKernelMemInfo,
+ (psKernelMemInfo) ? psKernelMemInfo->sMemBlk.hOSMemHandle : NULL,
+ NULL,
+ ui32RefValue,
+ ui32RefValue - 1,
+ (psKernelMemInfo) ? psKernelMemInfo->uAllocSize : 0);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ PVRSRVReleaseSyncInfoKM(psKernelSyncInfo);
+}
+
+IMG_INTERNAL
+void PVRSRVKernelMemInfoIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_MEMINFO))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "MEMINFO",
+ psKernelMemInfo->psKernelSyncInfo,
+ psKernelMemInfo,
+ psKernelMemInfo->sMemBlk.hOSMemHandle,
+ NULL,
+ psKernelMemInfo->ui32RefCount,
+ psKernelMemInfo->ui32RefCount + 1,
+ psKernelMemInfo->uAllocSize);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ psKernelMemInfo->ui32RefCount++;
+}
+
+IMG_INTERNAL
+void PVRSRVKernelMemInfoDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_MEMINFO))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "MEMINFO",
+ psKernelMemInfo->psKernelSyncInfo,
+ psKernelMemInfo,
+ psKernelMemInfo->sMemBlk.hOSMemHandle,
+ NULL,
+ psKernelMemInfo->ui32RefCount,
+ psKernelMemInfo->ui32RefCount - 1,
+ psKernelMemInfo->uAllocSize);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ psKernelMemInfo->ui32RefCount--;
+}
+
+IMG_INTERNAL
+void PVRSRVBMBufIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine, BM_BUF *pBuf)
+{
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_BM_BUF))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "BM_BUF",
+ NULL,
+ NULL,
+ BM_HandleToOSMemHandle(pBuf),
+ pBuf,
+ pBuf->ui32RefCount,
+ pBuf->ui32RefCount + 1,
+ (pBuf->pMapping) ? pBuf->pMapping->uSize : 0);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ pBuf->ui32RefCount++;
+}
+
+IMG_INTERNAL
+void PVRSRVBMBufDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine, BM_BUF *pBuf)
+{
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_BM_BUF))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "BM_BUF",
+ NULL,
+ NULL,
+ BM_HandleToOSMemHandle(pBuf),
+ pBuf,
+ pBuf->ui32RefCount,
+ pBuf->ui32RefCount - 1,
+ (pBuf->pMapping) ? pBuf->pMapping->uSize : 0);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ pBuf->ui32RefCount--;
+}
+
+IMG_INTERNAL
+void PVRSRVBMBufIncExport2(const IMG_CHAR *pszFile, IMG_INT iLine, BM_BUF *pBuf)
+{
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_BM_BUF2))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "BM_BUF2",
+ NULL,
+ NULL,
+ BM_HandleToOSMemHandle(pBuf),
+ pBuf,
+ pBuf->ui32ExportCount,
+ pBuf->ui32ExportCount + 1,
+ (pBuf->pMapping) ? pBuf->pMapping->uSize : 0);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ pBuf->ui32ExportCount++;
+}
+
+IMG_INTERNAL
+void PVRSRVBMBufDecExport2(const IMG_CHAR *pszFile, IMG_INT iLine, BM_BUF *pBuf)
+{
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_BM_BUF2))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "BM_BUF2",
+ NULL,
+ NULL,
+ BM_HandleToOSMemHandle(pBuf),
+ pBuf,
+ pBuf->ui32ExportCount,
+ pBuf->ui32ExportCount - 1,
+ (pBuf->pMapping) ? pBuf->pMapping->uSize : 0);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ pBuf->ui32ExportCount--;
+}
+
+IMG_INTERNAL
+void PVRSRVBMXProcIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine, IMG_UINT32 ui32Index)
+{
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_BM_XPROC))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "BM_XPROC",
+ NULL,
+ NULL,
+ gXProcWorkaroundShareData[ui32Index].hOSMemHandle,
+ (IMG_VOID *) ui32Index,
+ gXProcWorkaroundShareData[ui32Index].ui32RefCount,
+ gXProcWorkaroundShareData[ui32Index].ui32RefCount + 1,
+ gXProcWorkaroundShareData[ui32Index].ui32Size);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ gXProcWorkaroundShareData[ui32Index].ui32RefCount++;
+}
+
+IMG_INTERNAL
+void PVRSRVBMXProcDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine, IMG_UINT32 ui32Index)
+{
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_BM_XPROC))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "BM_XPROC",
+ NULL,
+ NULL,
+ gXProcWorkaroundShareData[ui32Index].hOSMemHandle,
+ (IMG_VOID *) ui32Index,
+ gXProcWorkaroundShareData[ui32Index].ui32RefCount,
+ gXProcWorkaroundShareData[ui32Index].ui32RefCount - 1,
+ gXProcWorkaroundShareData[ui32Index].ui32Size);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ gXProcWorkaroundShareData[ui32Index].ui32RefCount--;
+}
+
+#if defined(__linux__)
+
+/* mmap refcounting is Linux specific */
+
+IMG_INTERNAL
+void PVRSRVOffsetStructIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PKV_OFFSET_STRUCT psOffsetStruct)
+{
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_MMAP))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "MMAP",
+ NULL,
+ NULL,
+ psOffsetStruct->psLinuxMemArea,
+ psOffsetStruct,
+ psOffsetStruct->ui32RefCount,
+ psOffsetStruct->ui32RefCount + 1,
+ psOffsetStruct->ui32RealByteSize);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ psOffsetStruct->ui32RefCount++;
+}
+
+IMG_INTERNAL
+void PVRSRVOffsetStructDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PKV_OFFSET_STRUCT psOffsetStruct)
+{
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_MMAP))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "MMAP",
+ NULL,
+ NULL,
+ psOffsetStruct->psLinuxMemArea,
+ psOffsetStruct,
+ psOffsetStruct->ui32RefCount,
+ psOffsetStruct->ui32RefCount - 1,
+ psOffsetStruct->ui32RealByteSize);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ psOffsetStruct->ui32RefCount--;
+}
+
+IMG_INTERNAL
+void PVRSRVOffsetStructIncMapped2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PKV_OFFSET_STRUCT psOffsetStruct)
+{
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_MMAP2))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "MMAP2",
+ NULL,
+ NULL,
+ psOffsetStruct->psLinuxMemArea,
+ psOffsetStruct,
+ psOffsetStruct->ui32Mapped,
+ psOffsetStruct->ui32Mapped + 1,
+ psOffsetStruct->ui32RealByteSize);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ psOffsetStruct->ui32Mapped++;
+}
+
+IMG_INTERNAL
+void PVRSRVOffsetStructDecMapped2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PKV_OFFSET_STRUCT psOffsetStruct)
+{
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_MMAP2))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "MMAP2",
+ NULL,
+ NULL,
+ psOffsetStruct->psLinuxMemArea,
+ psOffsetStruct,
+ psOffsetStruct->ui32Mapped,
+ psOffsetStruct->ui32Mapped - 1,
+ psOffsetStruct->ui32RealByteSize);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ psOffsetStruct->ui32Mapped--;
+}
+
+#endif /* defined(__linux__) */
+
+#endif /* defined(PVRSRV_REFCOUNT_DEBUG) */
diff --git a/drivers/gpu/pvr/refcount.h b/drivers/gpu/pvr/refcount.h
new file mode 100644
index 0000000..92de65c
--- /dev/null
+++ b/drivers/gpu/pvr/refcount.h
@@ -0,0 +1,188 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+*/ /**************************************************************************/
+
+#ifndef __REFCOUNT_H__
+#define __REFCOUNT_H__
+
+#include "pvr_bridge_km.h"
+
+#if defined(PVRSRV_REFCOUNT_DEBUG)
+
+void PVRSRVDumpRefCountCCB(void);
+
+#define PVRSRVKernelSyncInfoIncRef(x...) \
+ PVRSRVKernelSyncInfoIncRef2(__FILE__, __LINE__, x)
+#define PVRSRVKernelSyncInfoDecRef(x...) \
+ PVRSRVKernelSyncInfoDecRef2(__FILE__, __LINE__, x)
+#define PVRSRVKernelMemInfoIncRef(x...) \
+ PVRSRVKernelMemInfoIncRef2(__FILE__, __LINE__, x)
+#define PVRSRVKernelMemInfoDecRef(x...) \
+ PVRSRVKernelMemInfoDecRef2(__FILE__, __LINE__, x)
+#define PVRSRVBMBufIncRef(x...) \
+ PVRSRVBMBufIncRef2(__FILE__, __LINE__, x)
+#define PVRSRVBMBufDecRef(x...) \
+ PVRSRVBMBufDecRef2(__FILE__, __LINE__, x)
+#define PVRSRVBMBufIncExport(x...) \
+ PVRSRVBMBufIncExport2(__FILE__, __LINE__, x)
+#define PVRSRVBMBufDecExport(x...) \
+ PVRSRVBMBufDecExport2(__FILE__, __LINE__, x)
+
+void PVRSRVKernelSyncInfoIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo,
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo);
+void PVRSRVKernelSyncInfoDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo,
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo);
+void PVRSRVKernelMemInfoIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo);
+void PVRSRVKernelMemInfoDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo);
+void PVRSRVBMBufIncRef2(const IMG_CHAR *pszFile,
+ IMG_INT iLine, BM_BUF *pBuf);
+void PVRSRVBMBufDecRef2(const IMG_CHAR *pszFile,
+ IMG_INT iLine, BM_BUF *pBuf);
+void PVRSRVBMBufIncExport2(const IMG_CHAR *pszFile,
+ IMG_INT iLine, BM_BUF *pBuf);
+void PVRSRVBMBufDecExport2(const IMG_CHAR *pszFile,
+ IMG_INT iLine, BM_BUF *pBuf);
+void PVRSRVBMXProcIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ IMG_UINT32 ui32Index);
+void PVRSRVBMXProcDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ IMG_UINT32 ui32Index);
+
+#if defined(__linux__)
+
+/* mmap refcounting is Linux specific */
+#include "mmap.h"
+
+#define PVRSRVOffsetStructIncRef(x...) \
+ PVRSRVOffsetStructIncRef2(__FILE__, __LINE__, x)
+#define PVRSRVOffsetStructDecRef(x...) \
+ PVRSRVOffsetStructDecRef2(__FILE__, __LINE__, x)
+#define PVRSRVOffsetStructIncMapped(x...) \
+ PVRSRVOffsetStructIncMapped2(__FILE__, __LINE__, x)
+#define PVRSRVOffsetStructDecMapped(x...) \
+ PVRSRVOffsetStructDecMapped2(__FILE__, __LINE__, x)
+
+void PVRSRVOffsetStructIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PKV_OFFSET_STRUCT psOffsetStruct);
+void PVRSRVOffsetStructDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PKV_OFFSET_STRUCT psOffsetStruct);
+void PVRSRVOffsetStructIncMapped2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PKV_OFFSET_STRUCT psOffsetStruct);
+void PVRSRVOffsetStructDecMapped2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PKV_OFFSET_STRUCT psOffsetStruct);
+
+#endif /* defined(__linux__) */
+
+#else /* defined(PVRSRV_REFCOUNT_DEBUG) */
+
+static INLINE void PVRSRVDumpRefCountCCB(void) { }
+
+static INLINE void PVRSRVKernelSyncInfoIncRef(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo,
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ PVR_UNREFERENCED_PARAMETER(psKernelMemInfo);
+ PVRSRVAcquireSyncInfoKM(psKernelSyncInfo);
+}
+
+static INLINE void PVRSRVKernelSyncInfoDecRef(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo,
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ PVR_UNREFERENCED_PARAMETER(psKernelMemInfo);
+ PVRSRVReleaseSyncInfoKM(psKernelSyncInfo);
+}
+
+static INLINE void PVRSRVKernelMemInfoIncRef(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ psKernelMemInfo->ui32RefCount++;
+}
+
+static INLINE void PVRSRVKernelMemInfoDecRef(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ psKernelMemInfo->ui32RefCount--;
+}
+
+static INLINE void PVRSRVBMBufIncRef(BM_BUF *pBuf)
+{
+ pBuf->ui32RefCount++;
+}
+
+static INLINE void PVRSRVBMBufDecRef(BM_BUF *pBuf)
+{
+ pBuf->ui32RefCount--;
+}
+
+static INLINE void PVRSRVBMBufIncExport(BM_BUF *pBuf)
+{
+ pBuf->ui32ExportCount++;
+}
+
+static INLINE void PVRSRVBMBufDecExport(BM_BUF *pBuf)
+{
+ pBuf->ui32ExportCount--;
+}
+
+static INLINE void PVRSRVBMXProcIncRef(IMG_UINT32 ui32Index)
+{
+ gXProcWorkaroundShareData[ui32Index].ui32RefCount++;
+}
+
+static INLINE void PVRSRVBMXProcDecRef(IMG_UINT32 ui32Index)
+{
+ gXProcWorkaroundShareData[ui32Index].ui32RefCount--;
+}
+
+#if defined(__linux__)
+
+/* mmap refcounting is Linux specific */
+#include "mmap.h"
+
+static INLINE void PVRSRVOffsetStructIncRef(PKV_OFFSET_STRUCT psOffsetStruct)
+{
+ psOffsetStruct->ui32RefCount++;
+}
+
+static INLINE void PVRSRVOffsetStructDecRef(PKV_OFFSET_STRUCT psOffsetStruct)
+{
+ psOffsetStruct->ui32RefCount--;
+}
+
+static INLINE void PVRSRVOffsetStructIncMapped(PKV_OFFSET_STRUCT psOffsetStruct)
+{
+ psOffsetStruct->ui32Mapped++;
+}
+
+static INLINE void PVRSRVOffsetStructDecMapped(PKV_OFFSET_STRUCT psOffsetStruct)
+{
+ psOffsetStruct->ui32Mapped--;
+}
+
+#endif /* defined(__linux__) */
+
+#endif /* defined(PVRSRV_REFCOUNT_DEBUG) */
+
+#endif /* __REFCOUNT_H__ */
diff --git a/drivers/gpu/pvr/regpaths.h b/drivers/gpu/pvr/regpaths.h
new file mode 100644
index 0000000..9193737
--- /dev/null
+++ b/drivers/gpu/pvr/regpaths.h
@@ -0,0 +1,43 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __REGPATHS_H__
+#define __REGPATHS_H__
+
+#define POWERVR_REG_ROOT "Drivers\\Display\\PowerVR"
+#define POWERVR_CHIP_KEY "\\SGX1\\"
+
+#define POWERVR_EURASIA_KEY "PowerVREurasia\\"
+
+#define POWERVR_SERVICES_KEY "\\Registry\\Machine\\System\\CurrentControlSet\\Services\\PowerVR\\"
+
+#define PVRSRV_REGISTRY_ROOT POWERVR_EURASIA_KEY "HWSettings\\PVRSRVKM"
+
+
+#define MAX_REG_STRING_SIZE 128
+
+
+#endif
diff --git a/drivers/gpu/pvr/resman.c b/drivers/gpu/pvr/resman.c
new file mode 100644
index 0000000..8eddf77
--- /dev/null
+++ b/drivers/gpu/pvr/resman.c
@@ -0,0 +1,765 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "resman.h"
+
+#ifdef __linux__
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#endif
+
+#include <linux/sched.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9)
+#include <linux/hardirq.h>
+#else
+#include <asm/hardirq.h>
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+#include <linux/mutex.h>
+#else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+#include <linux/semaphore.h>
+#else
+#include <asm/semaphore.h>
+#endif
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+static DEFINE_MUTEX(lock);
+#define DOWN(m) mutex_lock(m)
+#define UP(m) mutex_unlock(m)
+#else
+static DECLARE_MUTEX(lock);
+#define DOWN(m) down(m)
+#define UP(m) up(m)
+#endif
+
+#define ACQUIRE_SYNC_OBJ do { \
+ if (in_interrupt()) { \
+ printk("ISR cannot take RESMAN mutex\n"); \
+ BUG(); \
+ } \
+ else DOWN(&lock); \
+} while (0)
+#define RELEASE_SYNC_OBJ UP(&lock)
+
+#else
+
+#define ACQUIRE_SYNC_OBJ
+#define RELEASE_SYNC_OBJ
+
+#endif
+
+#define RESMAN_SIGNATURE 0x12345678
+
+typedef struct _RESMAN_ITEM_
+{
+#ifdef DEBUG
+ IMG_UINT32 ui32Signature;
+#endif
+ struct _RESMAN_ITEM_ **ppsThis;
+ struct _RESMAN_ITEM_ *psNext;
+
+ IMG_UINT32 ui32Flags;
+ IMG_UINT32 ui32ResType;
+
+ IMG_PVOID pvParam;
+ IMG_UINT32 ui32Param;
+
+ RESMAN_FREE_FN pfnFreeResource;
+} RESMAN_ITEM;
+
+
+typedef struct _RESMAN_CONTEXT_
+{
+#ifdef DEBUG
+ IMG_UINT32 ui32Signature;
+#endif
+ struct _RESMAN_CONTEXT_ **ppsThis;
+ struct _RESMAN_CONTEXT_ *psNext;
+
+ PVRSRV_PER_PROCESS_DATA *psPerProc;
+
+ RESMAN_ITEM *psResItemList;
+
+} RESMAN_CONTEXT;
+
+
+typedef struct
+{
+ RESMAN_CONTEXT *psContextList;
+
+} RESMAN_LIST, *PRESMAN_LIST;
+
+
+PRESMAN_LIST gpsResList = IMG_NULL;
+
+#include "lists.h"
+
+static IMPLEMENT_LIST_ANY_VA(RESMAN_ITEM)
+static IMPLEMENT_LIST_ANY_VA_2(RESMAN_ITEM, IMG_BOOL, IMG_FALSE)
+static IMPLEMENT_LIST_INSERT(RESMAN_ITEM)
+static IMPLEMENT_LIST_REMOVE(RESMAN_ITEM)
+static IMPLEMENT_LIST_REVERSE(RESMAN_ITEM)
+
+static IMPLEMENT_LIST_REMOVE(RESMAN_CONTEXT)
+static IMPLEMENT_LIST_INSERT(RESMAN_CONTEXT)
+
+
+#define PRINT_RESLIST(x, y, z)
+
+static PVRSRV_ERROR FreeResourceByPtr(RESMAN_ITEM *psItem, IMG_BOOL bExecuteCallback, IMG_BOOL bForceCleanup);
+
+static PVRSRV_ERROR FreeResourceByCriteria(PRESMAN_CONTEXT psContext,
+ IMG_UINT32 ui32SearchCriteria,
+ IMG_UINT32 ui32ResType,
+ IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param,
+ IMG_BOOL bExecuteCallback);
+
+
+#ifdef DEBUG
+ static IMG_VOID ValidateResList(PRESMAN_LIST psResList);
+ #define VALIDATERESLIST() ValidateResList(gpsResList)
+#else
+ #define VALIDATERESLIST()
+#endif
+
+
+
+
+
+
+PVRSRV_ERROR ResManInit(IMG_VOID)
+{
+ if (gpsResList == IMG_NULL)
+ {
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*gpsResList),
+ (IMG_VOID **)&gpsResList, IMG_NULL,
+ "Resource Manager List") != PVRSRV_OK)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+
+ gpsResList->psContextList = IMG_NULL;
+
+
+ VALIDATERESLIST();
+ }
+
+ return PVRSRV_OK;
+}
+
+
+IMG_VOID ResManDeInit(IMG_VOID)
+{
+ if (gpsResList != IMG_NULL)
+ {
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*gpsResList), gpsResList, IMG_NULL);
+ gpsResList = IMG_NULL;
+ }
+}
+
+
+PVRSRV_ERROR PVRSRVResManConnect(IMG_HANDLE hPerProc,
+ PRESMAN_CONTEXT *phResManContext)
+{
+ PVRSRV_ERROR eError;
+ PRESMAN_CONTEXT psResManContext;
+
+
+ ACQUIRE_SYNC_OBJ;
+
+
+ VALIDATERESLIST();
+
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psResManContext),
+ (IMG_VOID **)&psResManContext, IMG_NULL,
+ "Resource Manager Context");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVResManConnect: ERROR allocating new RESMAN context struct"));
+
+
+ VALIDATERESLIST();
+
+
+ RELEASE_SYNC_OBJ;
+
+ return eError;
+ }
+
+#ifdef DEBUG
+ psResManContext->ui32Signature = RESMAN_SIGNATURE;
+#endif
+ psResManContext->psResItemList = IMG_NULL;
+ psResManContext->psPerProc = hPerProc;
+
+
+ List_RESMAN_CONTEXT_Insert(&gpsResList->psContextList, psResManContext);
+
+
+ VALIDATERESLIST();
+
+
+ RELEASE_SYNC_OBJ;
+
+ *phResManContext = psResManContext;
+
+ return PVRSRV_OK;
+}
+
+
+IMG_VOID PVRSRVResManDisconnect(PRESMAN_CONTEXT psResManContext,
+ IMG_BOOL bKernelContext)
+{
+
+ ACQUIRE_SYNC_OBJ;
+
+
+ VALIDATERESLIST();
+
+
+ PRINT_RESLIST(gpsResList, psResManContext, IMG_TRUE);
+
+
+
+ if (!bKernelContext)
+ {
+
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_OS_USERMODE_MAPPING, 0, 0, IMG_TRUE);
+
+
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DMA_CLIENT_FIFO_DATA, 0, 0, IMG_TRUE);
+
+
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_EVENT_OBJECT, 0, 0, IMG_TRUE);
+
+
+
+ List_RESMAN_ITEM_Reverse(&psResManContext->psResItemList);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_MODIFY_SYNC_OPS, 0, 0, IMG_TRUE);
+ List_RESMAN_ITEM_Reverse(&psResManContext->psResItemList);
+
+
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_HW_RENDER_CONTEXT, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_HW_TRANSFER_CONTEXT, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_HW_2D_CONTEXT, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_TRANSFER_CONTEXT, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_SHARED_PB_DESC_CREATE_LOCK, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_SHARED_PB_DESC, 0, 0, IMG_TRUE);
+
+
+
+
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_SYNC_INFO, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICECLASSMEM_MAPPING, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_WRAP, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_MAPPING, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_KERNEL_DEVICEMEM_ALLOCATION, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_ALLOCATION, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_CONTEXT, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_SHARED_MEM_INFO, 0, 0, IMG_TRUE);
+
+
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN_REF, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DISPLAYCLASS_DEVICE, 0, 0, IMG_TRUE);
+
+
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_BUFFERCLASS_DEVICE, 0, 0, IMG_TRUE);
+ }
+
+
+ PVR_ASSERT(psResManContext->psResItemList == IMG_NULL);
+
+
+ List_RESMAN_CONTEXT_Remove(psResManContext);
+
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_CONTEXT), psResManContext, IMG_NULL);
+
+
+
+
+ VALIDATERESLIST();
+
+
+ PRINT_RESLIST(gpsResList, psResManContext, IMG_FALSE);
+
+
+ RELEASE_SYNC_OBJ;
+}
+
+
+PRESMAN_ITEM ResManRegisterRes(PRESMAN_CONTEXT psResManContext,
+ IMG_UINT32 ui32ResType,
+ IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param,
+ RESMAN_FREE_FN pfnFreeResource)
+{
+ PRESMAN_ITEM psNewResItem;
+
+ PVR_ASSERT(psResManContext != IMG_NULL);
+ PVR_ASSERT(ui32ResType != 0);
+
+ if (psResManContext == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ResManRegisterRes: invalid parameter - psResManContext"));
+ return (PRESMAN_ITEM) IMG_NULL;
+ }
+
+
+ ACQUIRE_SYNC_OBJ;
+
+
+ VALIDATERESLIST();
+
+ PVR_DPF((PVR_DBG_MESSAGE, "ResManRegisterRes: register resource "
+ "Context 0x%x, ResType 0x%x, pvParam 0x%x, ui32Param 0x%x, "
+ "FreeFunc %08X",
+ (IMG_UINTPTR_T)psResManContext,
+ ui32ResType,
+ (IMG_UINTPTR_T)pvParam,
+ ui32Param,
+ (IMG_UINTPTR_T)pfnFreeResource));
+
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(RESMAN_ITEM), (IMG_VOID **)&psNewResItem,
+ IMG_NULL,
+ "Resource Manager Item") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ResManRegisterRes: "
+ "ERROR allocating new resource item"));
+
+
+ RELEASE_SYNC_OBJ;
+
+ return((PRESMAN_ITEM)IMG_NULL);
+ }
+
+
+#ifdef DEBUG
+ psNewResItem->ui32Signature = RESMAN_SIGNATURE;
+#endif
+ psNewResItem->ui32ResType = ui32ResType;
+ psNewResItem->pvParam = pvParam;
+ psNewResItem->ui32Param = ui32Param;
+ psNewResItem->pfnFreeResource = pfnFreeResource;
+ psNewResItem->ui32Flags = 0;
+
+
+ List_RESMAN_ITEM_Insert(&psResManContext->psResItemList, psNewResItem);
+
+
+ VALIDATERESLIST();
+
+
+ RELEASE_SYNC_OBJ;
+
+ return(psNewResItem);
+}
+
+PVRSRV_ERROR ResManFreeResByPtr(RESMAN_ITEM *psResItem, IMG_BOOL bForceCleanup)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(psResItem != IMG_NULL);
+
+ if (psResItem == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "ResManFreeResByPtr: NULL ptr - nothing to do"));
+ return PVRSRV_OK;
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE, "ResManFreeResByPtr: freeing resource at %08X",
+ (IMG_UINTPTR_T)psResItem));
+
+
+ ACQUIRE_SYNC_OBJ;
+
+
+ VALIDATERESLIST();
+
+
+ eError = FreeResourceByPtr(psResItem, IMG_TRUE, bForceCleanup);
+
+
+ VALIDATERESLIST();
+
+
+ RELEASE_SYNC_OBJ;
+
+ return(eError);
+}
+
+
+PVRSRV_ERROR ResManFreeResByCriteria(PRESMAN_CONTEXT psResManContext,
+ IMG_UINT32 ui32SearchCriteria,
+ IMG_UINT32 ui32ResType,
+ IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(psResManContext != IMG_NULL);
+
+
+ ACQUIRE_SYNC_OBJ;
+
+
+ VALIDATERESLIST();
+
+ PVR_DPF((PVR_DBG_MESSAGE, "ResManFreeResByCriteria: "
+ "Context 0x%x, Criteria 0x%x, Type 0x%x, Addr 0x%x, Param 0x%x",
+ (IMG_UINTPTR_T)psResManContext, ui32SearchCriteria, ui32ResType,
+ (IMG_UINTPTR_T)pvParam, ui32Param));
+
+
+ eError = FreeResourceByCriteria(psResManContext, ui32SearchCriteria,
+ ui32ResType, pvParam, ui32Param,
+ IMG_TRUE);
+
+
+ VALIDATERESLIST();
+
+
+ RELEASE_SYNC_OBJ;
+
+ return eError;
+}
+
+
+PVRSRV_ERROR ResManDissociateRes(RESMAN_ITEM *psResItem,
+ PRESMAN_CONTEXT psNewResManContext)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ PVR_ASSERT(psResItem != IMG_NULL);
+
+ if (psResItem == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ResManDissociateRes: invalid parameter - psResItem"));
+ PVR_DBG_BREAK;
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+#ifdef DEBUG
+ PVR_ASSERT(psResItem->ui32Signature == RESMAN_SIGNATURE);
+#endif
+
+ if (psNewResManContext != IMG_NULL)
+ {
+
+ List_RESMAN_ITEM_Remove(psResItem);
+
+
+ List_RESMAN_ITEM_Insert(&psNewResManContext->psResItemList, psResItem);
+
+ }
+ else
+ {
+ eError = FreeResourceByPtr(psResItem, IMG_FALSE, CLEANUP_WITH_POLL);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ResManDissociateRes: failed to free resource by pointer"));
+ return eError;
+ }
+ }
+
+ return eError;
+}
+
+static IMG_BOOL ResManFindResourceByPtr_AnyVaCb(RESMAN_ITEM *psCurItem, va_list va)
+{
+ RESMAN_ITEM *psItem;
+
+ psItem = va_arg(va, RESMAN_ITEM*);
+
+ return (IMG_BOOL)(psCurItem == psItem);
+}
+
+
+IMG_INTERNAL PVRSRV_ERROR ResManFindResourceByPtr(PRESMAN_CONTEXT psResManContext,
+ RESMAN_ITEM *psItem)
+{
+ PVRSRV_ERROR eResult;
+
+ PVR_ASSERT(psResManContext != IMG_NULL);
+ PVR_ASSERT(psItem != IMG_NULL);
+
+ if ((psItem == IMG_NULL) || (psResManContext == IMG_NULL))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ResManFindResourceByPtr: invalid parameter"));
+ PVR_DBG_BREAK;
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+#ifdef DEBUG
+ PVR_ASSERT(psItem->ui32Signature == RESMAN_SIGNATURE);
+#endif
+
+
+ ACQUIRE_SYNC_OBJ;
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "FindResourceByPtr: psItem=%08X, psItem->psNext=%08X",
+ (IMG_UINTPTR_T)psItem, (IMG_UINTPTR_T)psItem->psNext));
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "FindResourceByPtr: Resource Ctx 0x%x, Type 0x%x, Addr 0x%x, "
+ "Param 0x%x, FnCall %08X, Flags 0x%x",
+ (IMG_UINTPTR_T)psResManContext,
+ psItem->ui32ResType,
+ (IMG_UINTPTR_T)psItem->pvParam,
+ psItem->ui32Param,
+ (IMG_UINTPTR_T)psItem->pfnFreeResource,
+ psItem->ui32Flags));
+
+
+ if(List_RESMAN_ITEM_IMG_BOOL_Any_va(psResManContext->psResItemList,
+ &ResManFindResourceByPtr_AnyVaCb,
+ psItem))
+ {
+ eResult = PVRSRV_OK;
+ }
+ else
+ {
+ eResult = PVRSRV_ERROR_NOT_OWNER;
+ }
+
+
+ RELEASE_SYNC_OBJ;
+
+ return eResult;
+}
+
+static PVRSRV_ERROR FreeResourceByPtr(RESMAN_ITEM *psItem,
+ IMG_BOOL bExecuteCallback,
+ IMG_BOOL bForceCleanup)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ PVR_ASSERT(psItem != IMG_NULL);
+
+ if (psItem == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeResourceByPtr: invalid parameter"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+#ifdef DEBUG
+ PVR_ASSERT(psItem->ui32Signature == RESMAN_SIGNATURE);
+#endif
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "FreeResourceByPtr: psItem=%08X, psItem->psNext=%08X",
+ (IMG_UINTPTR_T)psItem, (IMG_UINTPTR_T)psItem->psNext));
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "FreeResourceByPtr: Type 0x%x, Addr 0x%x, "
+ "Param 0x%x, FnCall %08X, Flags 0x%x",
+ psItem->ui32ResType,
+ (IMG_UINTPTR_T)psItem->pvParam, psItem->ui32Param,
+ (IMG_UINTPTR_T)psItem->pfnFreeResource, psItem->ui32Flags));
+
+
+ RELEASE_SYNC_OBJ;
+
+
+ if (bExecuteCallback)
+ {
+ eError = psItem->pfnFreeResource(psItem->pvParam, psItem->ui32Param, bForceCleanup);
+ if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_RETRY))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeResourceByPtr: ERROR calling FreeResource function"));
+ }
+ }
+
+
+ ACQUIRE_SYNC_OBJ;
+
+ if (eError != PVRSRV_ERROR_RETRY)
+ {
+
+ List_RESMAN_ITEM_Remove(psItem);
+
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_ITEM), psItem, IMG_NULL);
+ }
+
+ return(eError);
+}
+
+static IMG_VOID* FreeResourceByCriteria_AnyVaCb(RESMAN_ITEM *psCurItem, va_list va)
+{
+ IMG_UINT32 ui32SearchCriteria;
+ IMG_UINT32 ui32ResType;
+ IMG_PVOID pvParam;
+ IMG_UINT32 ui32Param;
+
+ ui32SearchCriteria = va_arg(va, IMG_UINT32);
+ ui32ResType = va_arg(va, IMG_UINT32);
+ pvParam = va_arg(va, IMG_PVOID);
+ ui32Param = va_arg(va, IMG_UINT32);
+
+
+ if(
+
+ (((ui32SearchCriteria & RESMAN_CRITERIA_RESTYPE) == 0UL) ||
+ (psCurItem->ui32ResType == ui32ResType))
+ &&
+
+ (((ui32SearchCriteria & RESMAN_CRITERIA_PVOID_PARAM) == 0UL) ||
+ (psCurItem->pvParam == pvParam))
+ &&
+
+ (((ui32SearchCriteria & RESMAN_CRITERIA_UI32_PARAM) == 0UL) ||
+ (psCurItem->ui32Param == ui32Param))
+ )
+ {
+ return psCurItem;
+ }
+ else
+ {
+ return IMG_NULL;
+ }
+}
+
+static PVRSRV_ERROR FreeResourceByCriteria(PRESMAN_CONTEXT psResManContext,
+ IMG_UINT32 ui32SearchCriteria,
+ IMG_UINT32 ui32ResType,
+ IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param,
+ IMG_BOOL bExecuteCallback)
+{
+ PRESMAN_ITEM psCurItem;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+
+
+ while((psCurItem = (PRESMAN_ITEM)
+ List_RESMAN_ITEM_Any_va(psResManContext->psResItemList,
+ &FreeResourceByCriteria_AnyVaCb,
+ ui32SearchCriteria,
+ ui32ResType,
+ pvParam,
+ ui32Param)) != IMG_NULL
+ && eError == PVRSRV_OK)
+ {
+ do
+ {
+ eError = FreeResourceByPtr(psCurItem, bExecuteCallback, CLEANUP_WITH_POLL);
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+ RELEASE_SYNC_OBJ;
+ OSReleaseBridgeLock();
+
+ OSSleepms(MAX_CLEANUP_TIME_WAIT_US/1000);
+ OSReacquireBridgeLock();
+ ACQUIRE_SYNC_OBJ;
+ }
+ } while (eError == PVRSRV_ERROR_RETRY);
+ }
+
+ return eError;
+}
+
+
+#ifdef DEBUG
+static IMG_VOID ValidateResList(PRESMAN_LIST psResList)
+{
+ PRESMAN_ITEM psCurItem, *ppsThisItem;
+ PRESMAN_CONTEXT psCurContext, *ppsThisContext;
+
+
+ if (psResList == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "ValidateResList: resman not initialised yet"));
+ return;
+ }
+
+ psCurContext = psResList->psContextList;
+ ppsThisContext = &psResList->psContextList;
+
+
+ while(psCurContext != IMG_NULL)
+ {
+
+ PVR_ASSERT(psCurContext->ui32Signature == RESMAN_SIGNATURE);
+ if (psCurContext->ppsThis != ppsThisContext)
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "psCC=%08X psCC->ppsThis=%08X psCC->psNext=%08X ppsTC=%08X",
+ (IMG_UINTPTR_T)psCurContext,
+ (IMG_UINTPTR_T)psCurContext->ppsThis,
+ (IMG_UINTPTR_T)psCurContext->psNext,
+ (IMG_UINTPTR_T)ppsThisContext));
+ PVR_ASSERT(psCurContext->ppsThis == ppsThisContext);
+ }
+
+
+ psCurItem = psCurContext->psResItemList;
+ ppsThisItem = &psCurContext->psResItemList;
+ while(psCurItem != IMG_NULL)
+ {
+
+ PVR_ASSERT(psCurItem->ui32Signature == RESMAN_SIGNATURE);
+ if (psCurItem->ppsThis != ppsThisItem)
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "psCurItem=%08X psCurItem->ppsThis=%08X psCurItem->psNext=%08X ppsThisItem=%08X",
+ (IMG_UINTPTR_T)psCurItem,
+ (IMG_UINTPTR_T)psCurItem->ppsThis,
+ (IMG_UINTPTR_T)psCurItem->psNext,
+ (IMG_UINTPTR_T)ppsThisItem));
+ PVR_ASSERT(psCurItem->ppsThis == ppsThisItem);
+ }
+
+
+ ppsThisItem = &psCurItem->psNext;
+ psCurItem = psCurItem->psNext;
+ }
+
+
+ ppsThisContext = &psCurContext->psNext;
+ psCurContext = psCurContext->psNext;
+ }
+}
+#endif
+
+
diff --git a/drivers/gpu/pvr/resman.h b/drivers/gpu/pvr/resman.h
new file mode 100644
index 0000000..648e490
--- /dev/null
+++ b/drivers/gpu/pvr/resman.h
@@ -0,0 +1,118 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __RESMAN_H__
+#define __RESMAN_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+enum {
+
+ RESMAN_TYPE_SHARED_PB_DESC = 1,
+ RESMAN_TYPE_SHARED_PB_DESC_CREATE_LOCK,
+ RESMAN_TYPE_HW_RENDER_CONTEXT,
+ RESMAN_TYPE_HW_TRANSFER_CONTEXT,
+ RESMAN_TYPE_HW_2D_CONTEXT,
+ RESMAN_TYPE_TRANSFER_CONTEXT,
+
+
+ RESMAN_TYPE_DMA_CLIENT_FIFO_DATA,
+
+
+
+
+
+ RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN_REF,
+ RESMAN_TYPE_DISPLAYCLASS_DEVICE,
+
+
+ RESMAN_TYPE_BUFFERCLASS_DEVICE,
+
+
+ RESMAN_TYPE_OS_USERMODE_MAPPING,
+
+
+ RESMAN_TYPE_DEVICEMEM_CONTEXT,
+ RESMAN_TYPE_DEVICECLASSMEM_MAPPING,
+ RESMAN_TYPE_DEVICEMEM_MAPPING,
+ RESMAN_TYPE_DEVICEMEM_WRAP,
+ RESMAN_TYPE_DEVICEMEM_ALLOCATION,
+ RESMAN_TYPE_EVENT_OBJECT,
+ RESMAN_TYPE_SHARED_MEM_INFO,
+ RESMAN_TYPE_MODIFY_SYNC_OPS,
+ RESMAN_TYPE_SYNC_INFO,
+
+
+ RESMAN_TYPE_KERNEL_DEVICEMEM_ALLOCATION
+};
+
+#define RESMAN_CRITERIA_ALL 0x00000000
+#define RESMAN_CRITERIA_RESTYPE 0x00000001
+#define RESMAN_CRITERIA_PVOID_PARAM 0x00000002
+#define RESMAN_CRITERIA_UI32_PARAM 0x00000004
+
+typedef PVRSRV_ERROR (*RESMAN_FREE_FN)(IMG_PVOID pvParam, IMG_UINT32 ui32Param, IMG_BOOL bForceCleanup);
+
+typedef struct _RESMAN_ITEM_ *PRESMAN_ITEM;
+typedef struct _RESMAN_CONTEXT_ *PRESMAN_CONTEXT;
+
+PVRSRV_ERROR ResManInit(IMG_VOID);
+IMG_VOID ResManDeInit(IMG_VOID);
+
+PRESMAN_ITEM ResManRegisterRes(PRESMAN_CONTEXT hResManContext,
+ IMG_UINT32 ui32ResType,
+ IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param,
+ RESMAN_FREE_FN pfnFreeResource);
+
+PVRSRV_ERROR ResManFreeResByPtr(PRESMAN_ITEM psResItem,
+ IMG_BOOL bForceCleanup);
+
+PVRSRV_ERROR ResManFreeResByCriteria(PRESMAN_CONTEXT hResManContext,
+ IMG_UINT32 ui32SearchCriteria,
+ IMG_UINT32 ui32ResType,
+ IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param);
+
+PVRSRV_ERROR ResManDissociateRes(PRESMAN_ITEM psResItem,
+ PRESMAN_CONTEXT psNewResManContext);
+
+PVRSRV_ERROR ResManFindResourceByPtr(PRESMAN_CONTEXT hResManContext,
+ PRESMAN_ITEM psItem);
+
+PVRSRV_ERROR PVRSRVResManConnect(IMG_HANDLE hPerProc,
+ PRESMAN_CONTEXT *phResManContext);
+IMG_VOID PVRSRVResManDisconnect(PRESMAN_CONTEXT hResManContext,
+ IMG_BOOL bKernelContext);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/pvr/s3c_lcd/s3c_displayclass.c b/drivers/gpu/pvr/s3c_lcd/s3c_displayclass.c
new file mode 100644
index 0000000..ff65c20
--- /dev/null
+++ b/drivers/gpu/pvr/s3c_lcd/s3c_displayclass.c
@@ -0,0 +1,1388 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ */
+
+/* Copyright (C) Samsung Electronics System LSI. */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/fb.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <asm/hardirq.h>
+#include <asm/uaccess.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/memory.h>
+#include <plat/regs-fb.h>
+#include <linux/console.h>
+#include <linux/workqueue.h>
+#include <linux/version.h>
+
+#include "img_defs.h"
+#include "servicesext.h"
+#include "kerneldisplay.h"
+
+#include "s3c_lcd.h"
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+#define S3C_CONSOLE_LOCK() console_lock()
+#define S3C_CONSOLE_UNLOCK() console_unlock()
+#else
+#define S3C_CONSOLE_LOCK() acquire_console_sem()
+#define S3C_CONSOLE_UNLOCK() release_console_sem()
+#endif
+
+static int fb_idx = 0;
+
+#define S3C_MAX_BACKBUFFERS 2
+#define S3C_MAX_BUFFERS (S3C_MAX_BACKBUFFERS+1)
+
+#define S3C_DISPLAY_FORMAT_NUM 1
+#define S3C_DISPLAY_DIM_NUM 1
+
+#define VSYNC_IRQ 0x61
+
+#define DC_S3C_LCD_COMMAND_COUNT 1
+
+typedef struct S3C_FRAME_BUFFER_TAG
+{
+ IMG_CPU_VIRTADDR bufferVAddr;
+ IMG_SYS_PHYADDR bufferPAddr;
+ IMG_UINT32 byteSize;
+ IMG_UINT32 yoffset; //y offset from SysBuffer
+
+} S3C_FRAME_BUFFER;
+
+typedef void * S3C_HANDLE;
+
+typedef enum tag_s3c_bool
+{
+ S3C_FALSE = 0,
+ S3C_TRUE = 1,
+
+} S3C_BOOL, *S3C_PBOOL;
+
+typedef struct S3C_SWAPCHAIN_TAG
+{
+ unsigned long ulBufferCount;
+ S3C_FRAME_BUFFER *psBuffer;
+
+} S3C_SWAPCHAIN;
+
+typedef struct S3C_VSYNC_FLIP_ITEM_TAG
+{
+ S3C_HANDLE hCmdComplete;
+ S3C_FRAME_BUFFER *psFb;
+ unsigned long ulSwapInterval;
+ S3C_BOOL bValid;
+ S3C_BOOL bFlipped;
+ S3C_BOOL bCmdCompleted;
+
+} S3C_VSYNC_FLIP_ITEM;
+
+typedef struct fb_info S3C_FB_INFO;
+
+typedef struct S3C_LCD_DEVINFO_TAG
+{
+ IMG_UINT32 ui32DeviceID;
+ DISPLAY_INFO sDisplayInfo;
+ S3C_FB_INFO *psFBInfo;
+
+ // sys surface info
+ S3C_FRAME_BUFFER sSysBuffer;
+
+ // number of supported format
+ IMG_UINT32 ui32NumFormats;
+ IMG_UINT32 ui32NumFrameBuffers;
+
+ // list of supported display format
+ DISPLAY_FORMAT asDisplayFormatList[S3C_DISPLAY_FORMAT_NUM];
+
+ IMG_UINT32 ui32NumDims;
+ DISPLAY_DIMS asDisplayDimList[S3C_DISPLAY_DIM_NUM];
+
+ // jump table into DC
+ PVRSRV_DC_SRV2DISP_KMJTABLE sDCJTable;
+
+ // backbuffer info
+ S3C_FRAME_BUFFER asBackBuffers[S3C_MAX_BACKBUFFERS];
+
+ S3C_SWAPCHAIN *psSwapChain;
+
+ S3C_VSYNC_FLIP_ITEM asVSyncFlips[S3C_MAX_BUFFERS];
+
+ unsigned long ulInsertIndex;
+ unsigned long ulRemoveIndex;
+ S3C_BOOL bFlushCommands;
+
+ struct workqueue_struct *psWorkQueue;
+ struct work_struct sWork;
+ struct mutex sVsyncFlipItemMutex;
+
+} S3C_LCD_DEVINFO;
+
+// jump table into pvr services
+static PVRSRV_DC_DISP2SRV_KMJTABLE gsPVRJTable;
+
+static S3C_LCD_DEVINFO *gpsLCDInfo;
+
+/*****************************************************************************
+ * Video-decode carveout decls
+ */
+
+#define S3C_MAX_VIDEO_BUFFERS 3
+
+/* Y planes + UV planes @ max resolution, page aligned */
+#define S3C_VIDEO_Y_SIZE ALIGN(1280 * 720, PAGE_SIZE)
+#define S3C_VIDEO_UV_SIZE ALIGN(1280 * 360, PAGE_SIZE)
+#define S3C_VIDEO_CARVEOUT_SIZE \
+ S3C_MAX_VIDEO_BUFFERS * (S3C_VIDEO_Y_SIZE + S3C_VIDEO_UV_SIZE)
+
+typedef struct S3C_VIDBUF_DEVINFO_TAG
+{
+ IMG_UINT32 ui32DeviceID;
+ S3C_SWAPCHAIN *psSwapChain;
+ DISPLAY_INFO sDisplayInfo;
+ S3C_FRAME_BUFFER asVideoBuffers[S3C_MAX_VIDEO_BUFFERS];
+
+} S3C_VIDBUF_DEVINFO;
+
+static S3C_VIDBUF_DEVINFO gsYBufInfo =
+{
+ .sDisplayInfo.ui32MaxSwapInterval = 1,
+ .sDisplayInfo.ui32MaxSwapChains = 1,
+ .sDisplayInfo.ui32MaxSwapChainBuffers = S3C_MAX_VIDEO_BUFFERS,
+ .sDisplayInfo.szDisplayName = "s3c_lcd_y",
+};
+
+static S3C_VIDBUF_DEVINFO gsUVBufInfo =
+{
+ .sDisplayInfo.ui32MaxSwapInterval = 1,
+ .sDisplayInfo.ui32MaxSwapChains = 1,
+ .sDisplayInfo.ui32MaxSwapChainBuffers = S3C_MAX_VIDEO_BUFFERS,
+ .sDisplayInfo.szDisplayName = "s3c_lcd_uv",
+};
+
+static int InitVidBufs(IMG_UINT32 ui32FBOffset);
+static void DeinitVidBufs(void);
+
+/****************************************************************************/
+
+extern IMG_BOOL IMG_IMPORT PVRGetDisplayClassJTable(PVRSRV_DC_DISP2SRV_KMJTABLE *psJTable);
+
+static void AdvanceFlipIndex(S3C_LCD_DEVINFO *psDevInfo,
+ unsigned long *pulIndex)
+{
+ unsigned long ulMaxFlipIndex;
+
+ ulMaxFlipIndex = psDevInfo->psSwapChain->ulBufferCount - 1;
+ if (ulMaxFlipIndex >= psDevInfo->ui32NumFrameBuffers)
+ {
+ ulMaxFlipIndex = psDevInfo->ui32NumFrameBuffers -1;
+ }
+
+ (*pulIndex)++;
+
+ if (*pulIndex > ulMaxFlipIndex )
+ {
+ *pulIndex = 0;
+ }
+}
+
+static IMG_VOID ResetVSyncFlipItems(S3C_LCD_DEVINFO* psDevInfo)
+{
+ unsigned long i;
+
+ psDevInfo->ulInsertIndex = 0;
+ psDevInfo->ulRemoveIndex = 0;
+
+ for(i=0; i < psDevInfo->ui32NumFrameBuffers; i++)
+ {
+ psDevInfo->asVSyncFlips[i].bValid = S3C_FALSE;
+ psDevInfo->asVSyncFlips[i].bFlipped = S3C_FALSE;
+ psDevInfo->asVSyncFlips[i].bCmdCompleted = S3C_FALSE;
+ }
+}
+
+static IMG_VOID S3C_Flip(S3C_LCD_DEVINFO *psDevInfo,
+ S3C_FRAME_BUFFER *fb)
+{
+ struct fb_var_screeninfo sFBVar;
+ int res;
+ unsigned long ulYResVirtual;
+
+ S3C_CONSOLE_LOCK();
+
+ sFBVar = psDevInfo->psFBInfo->var;
+
+ sFBVar.xoffset = 0;
+ sFBVar.yoffset = fb->yoffset;
+
+ ulYResVirtual = fb->yoffset + sFBVar.yres;
+
+ if (sFBVar.xres_virtual != sFBVar.xres || sFBVar.yres_virtual < ulYResVirtual)
+ {
+ sFBVar.xres_virtual = sFBVar.xres;
+ sFBVar.yres_virtual = ulYResVirtual;
+
+ sFBVar.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;
+
+ res = fb_set_var(psDevInfo->psFBInfo, &sFBVar);
+ if (res != 0)
+ {
+ printk("%s: fb_set_var failed (Y Offset: %d, Error: %d)\n", __FUNCTION__, fb->yoffset, res);
+ }
+ }
+ else
+ {
+ res = fb_pan_display(psDevInfo->psFBInfo, &sFBVar);
+ if (res != 0)
+ {
+ printk( "%s: fb_pan_display failed (Y Offset: %d, Error: %d)\n", __FUNCTION__, fb->yoffset, res);
+ }
+ }
+
+ S3C_CONSOLE_UNLOCK();
+}
+
+static void FlushInternalVSyncQueue(S3C_LCD_DEVINFO*psDevInfo)
+{
+ S3C_VSYNC_FLIP_ITEM* psFlipItem;
+
+ mutex_lock(&psDevInfo->sVsyncFlipItemMutex);
+
+ psFlipItem = &psDevInfo->asVSyncFlips[psDevInfo->ulRemoveIndex];
+
+ while(psFlipItem->bValid)
+ {
+ if(psFlipItem->bFlipped == S3C_FALSE)
+ {
+ S3C_Flip (psDevInfo, psFlipItem->psFb);
+ }
+
+ if(psFlipItem->bCmdCompleted == S3C_FALSE)
+ {
+ gsPVRJTable.pfnPVRSRVCmdComplete((IMG_HANDLE)psFlipItem->hCmdComplete, IMG_TRUE);
+ }
+
+ AdvanceFlipIndex(psDevInfo, &psDevInfo->ulRemoveIndex);
+
+ psFlipItem->bFlipped = S3C_FALSE;
+ psFlipItem->bCmdCompleted = S3C_FALSE;
+ psFlipItem->bValid = S3C_FALSE;
+
+ psFlipItem = &psDevInfo->asVSyncFlips[psDevInfo->ulRemoveIndex];
+ }
+
+ psDevInfo->ulInsertIndex = 0;
+ psDevInfo->ulRemoveIndex = 0;
+
+ mutex_unlock(&psDevInfo->sVsyncFlipItemMutex);
+}
+
+static void VsyncWorkqueueFunc(struct work_struct *psWork)
+{
+ S3C_VSYNC_FLIP_ITEM *psFlipItem;
+ S3C_LCD_DEVINFO *psDevInfo = container_of(psWork, S3C_LCD_DEVINFO, sWork);
+
+ if(psDevInfo == NULL)
+ {
+ return;
+ }
+
+ mutex_lock(&psDevInfo->sVsyncFlipItemMutex);
+
+ psFlipItem = &psDevInfo->asVSyncFlips[psDevInfo->ulRemoveIndex];
+
+ while(psFlipItem->bValid)
+ {
+ if(psFlipItem->bFlipped)
+ {
+ if(!psFlipItem->bCmdCompleted)
+ {
+ gsPVRJTable.pfnPVRSRVCmdComplete((IMG_HANDLE)psFlipItem->hCmdComplete, IMG_TRUE);
+ psFlipItem->bCmdCompleted = S3C_TRUE;
+ }
+
+ psFlipItem->ulSwapInterval--;
+
+ if(psFlipItem->ulSwapInterval == 0)
+ {
+ AdvanceFlipIndex(psDevInfo, &psDevInfo->ulRemoveIndex);
+ psFlipItem->bCmdCompleted = S3C_FALSE;
+ psFlipItem->bFlipped = S3C_FALSE;
+ psFlipItem->bValid = S3C_FALSE;
+ }
+ else
+ {
+ break;
+ }
+ }
+ else
+ {
+ S3C_Flip (psDevInfo, psFlipItem->psFb);
+ psFlipItem->bFlipped = S3C_TRUE;
+ break;
+ }
+
+ psFlipItem = &psDevInfo->asVSyncFlips[psDevInfo->ulRemoveIndex];
+ }
+
+ mutex_unlock(&psDevInfo->sVsyncFlipItemMutex);
+}
+
+static S3C_BOOL CreateVsyncWorkQueue(S3C_LCD_DEVINFO *psDevInfo)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36))
+ psDevInfo->psWorkQueue = alloc_workqueue("vsync_workqueue",
+ WQ_UNBOUND | WQ_HIGHPRI, 1);
+#else
+ psDevInfo->psWorkQueue = create_rt_workqueue("vsync_workqueue");
+#endif
+
+ if (psDevInfo->psWorkQueue == IMG_NULL)
+ {
+ printk("fail to create vsync_handler workqueue\n");
+ return S3C_FALSE;
+ }
+
+ INIT_WORK(&psDevInfo->sWork, VsyncWorkqueueFunc);
+ mutex_init(&psDevInfo->sVsyncFlipItemMutex);
+
+ return S3C_TRUE;
+}
+
+static void destroyVsyncWorkQueue(S3C_LCD_DEVINFO *psDevInfo)
+{
+ destroy_workqueue(psDevInfo->psWorkQueue);
+ mutex_destroy(&psDevInfo->sVsyncFlipItemMutex);
+}
+
+static irqreturn_t S3C_VSyncISR(int irq, void *dev_id)
+{
+ if( dev_id != gpsLCDInfo)
+ {
+ return IRQ_NONE;
+ }
+
+ queue_work(gpsLCDInfo->psWorkQueue, &gpsLCDInfo->sWork);
+
+ return IRQ_HANDLED;
+}
+
+static IMG_VOID S3C_InstallVsyncISR(void)
+{
+ if(request_irq(VSYNC_IRQ, S3C_VSyncISR, IRQF_SHARED , "s3cfb", gpsLCDInfo))
+ {
+ printk("S3C_InstallVsyncISR: Couldn't install system LISR on IRQ %d", VSYNC_IRQ);
+ return;
+ }
+}
+
+static IMG_VOID S3C_UninstallVsyncISR(void)
+{
+ free_irq(VSYNC_IRQ, gpsLCDInfo);
+}
+
+static PVRSRV_ERROR OpenDCDevice(IMG_UINT32 ui32DeviceID,
+ IMG_HANDLE *phDevice,
+ PVRSRV_SYNC_DATA* psSystemBufferSyncData)
+{
+ PVR_UNREFERENCED_PARAMETER(psSystemBufferSyncData);
+
+ if(ui32DeviceID == gpsLCDInfo->ui32DeviceID)
+ {
+ *phDevice = (IMG_HANDLE)gpsLCDInfo;
+ }
+ else if(ui32DeviceID == gsYBufInfo.ui32DeviceID)
+ {
+ *phDevice = (IMG_HANDLE)&gsYBufInfo;
+ }
+ else if(ui32DeviceID == gsUVBufInfo.ui32DeviceID)
+ {
+ *phDevice = (IMG_HANDLE)&gsUVBufInfo;
+ }
+ else
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR CloseDCDevice(IMG_HANDLE hDevice)
+{
+ PVR_UNREFERENCED_PARAMETER(hDevice);
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR EnumDCFormats(IMG_HANDLE hDevice,
+ IMG_UINT32 *pui32NumFormats,
+ DISPLAY_FORMAT *psFormat)
+{
+ S3C_LCD_DEVINFO *psLCDInfo = (S3C_LCD_DEVINFO*)hDevice;
+ int i;
+
+ if(!hDevice || !pui32NumFormats)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ *pui32NumFormats = S3C_DISPLAY_FORMAT_NUM;
+
+ if(psFormat)
+ {
+ for (i = 0 ; i < S3C_DISPLAY_FORMAT_NUM ; i++)
+ psFormat[i] = psLCDInfo->asDisplayFormatList[i];
+ }
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR EnumDCDims(IMG_HANDLE hDevice,
+ DISPLAY_FORMAT *psFormat,
+ IMG_UINT32 *pui32NumDims,
+ DISPLAY_DIMS *psDim)
+{
+ int i;
+
+ S3C_LCD_DEVINFO *psLCDInfo = (S3C_LCD_DEVINFO*)hDevice;
+
+ if(!hDevice || !psFormat || !pui32NumDims)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ *pui32NumDims = S3C_DISPLAY_DIM_NUM;
+
+ if(psDim)
+ {
+ for (i = 0 ; i < S3C_DISPLAY_DIM_NUM ; i++)
+ psDim[i] = psLCDInfo->asDisplayDimList[i];
+ }
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR GetDCSystemBuffer(IMG_HANDLE hDevice, IMG_HANDLE *phBuffer)
+{
+ S3C_LCD_DEVINFO *psDevInfo = (S3C_LCD_DEVINFO*)hDevice;
+
+ if(!hDevice || !phBuffer)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ *phBuffer = (IMG_HANDLE)&psDevInfo->sSysBuffer;
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR GetDCInfo(IMG_HANDLE hDevice, DISPLAY_INFO *psDCInfo)
+{
+ S3C_LCD_DEVINFO *psDevInfo = (S3C_LCD_DEVINFO*)hDevice;
+
+ if(!hDevice || !psDCInfo)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ *psDCInfo = psDevInfo->sDisplayInfo;
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR GetDCBufferAddr(IMG_HANDLE hDevice,
+ IMG_HANDLE hBuffer,
+ IMG_SYS_PHYADDR **ppsSysAddr,
+ IMG_UINT32 *pui32ByteSize,
+ IMG_VOID **ppvCpuVAddr,
+ IMG_HANDLE *phOSMapInfo,
+ IMG_BOOL *pbIsContiguous,
+ IMG_UINT32 *pui32TilingStride)
+{
+ S3C_FRAME_BUFFER *psBuffer = (S3C_FRAME_BUFFER *)hBuffer;
+
+ PVR_UNREFERENCED_PARAMETER(pui32TilingStride);
+ PVR_UNREFERENCED_PARAMETER(hDevice);
+
+ if(!hDevice || !hBuffer || !ppsSysAddr || !pui32ByteSize)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ *phOSMapInfo = IMG_NULL;
+ *pbIsContiguous = IMG_TRUE;
+
+ *ppvCpuVAddr = (IMG_VOID *)psBuffer->bufferVAddr;
+ *ppsSysAddr = &psBuffer->bufferPAddr;
+ *pui32ByteSize = psBuffer->byteSize;
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR CreateDCSwapChain(IMG_HANDLE hDevice,
+ IMG_UINT32 ui32Flags,
+ DISPLAY_SURF_ATTRIBUTES *psDstSurfAttrib,
+ DISPLAY_SURF_ATTRIBUTES *psSrcSurfAttrib,
+ IMG_UINT32 ui32BufferCount,
+ PVRSRV_SYNC_DATA **ppsSyncData,
+ IMG_UINT32 ui32OEMFlags,
+ IMG_HANDLE *phSwapChain,
+ IMG_UINT32 *pui32SwapChainID)
+{
+ IMG_UINT32 i;
+
+ S3C_FRAME_BUFFER *psBuffer;
+ S3C_SWAPCHAIN *psSwapChain;
+ S3C_LCD_DEVINFO *psDevInfo = (S3C_LCD_DEVINFO*)hDevice;
+
+ PVR_UNREFERENCED_PARAMETER(ui32OEMFlags);
+ PVR_UNREFERENCED_PARAMETER(pui32SwapChainID);
+
+ if(!hDevice || !psDstSurfAttrib || !psSrcSurfAttrib || !ppsSyncData || !phSwapChain)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if(ui32BufferCount > psDevInfo->ui32NumFrameBuffers)
+ {
+ return PVRSRV_ERROR_TOOMANYBUFFERS;
+ }
+
+ if(psDevInfo->psSwapChain)
+ {
+ return (PVRSRV_ERROR_FLIP_CHAIN_EXISTS);
+ }
+
+ psSwapChain = (S3C_SWAPCHAIN *)kmalloc(sizeof(S3C_SWAPCHAIN),GFP_KERNEL);
+ if(!psSwapChain)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ psBuffer = (S3C_FRAME_BUFFER*)kmalloc(sizeof(S3C_FRAME_BUFFER) * ui32BufferCount, GFP_KERNEL);
+ if(!psBuffer)
+ {
+ kfree(psSwapChain);
+ return (PVRSRV_ERROR_OUT_OF_MEMORY);
+ }
+
+ psSwapChain->ulBufferCount = (unsigned long)ui32BufferCount;
+ psSwapChain->psBuffer = psBuffer;
+
+ psBuffer[0].bufferPAddr = psDevInfo->sSysBuffer.bufferPAddr;
+ psBuffer[0].bufferVAddr = psDevInfo->sSysBuffer.bufferVAddr;
+ psBuffer[0].byteSize = psDevInfo->sSysBuffer.byteSize;
+ psBuffer[0].yoffset = psDevInfo->sSysBuffer.yoffset;
+
+ for (i=1; i<ui32BufferCount; i++)
+ {
+ psBuffer[i].bufferPAddr = psDevInfo->asBackBuffers[i-1].bufferPAddr;
+ psBuffer[i].bufferVAddr = psDevInfo->asBackBuffers[i-1].bufferVAddr;
+ psBuffer[i].byteSize = psDevInfo->asBackBuffers[i-1].byteSize;
+ psBuffer[i].yoffset = psDevInfo->asBackBuffers[i-1].yoffset;
+ }
+
+ *phSwapChain = (IMG_HANDLE)psSwapChain;
+ *pui32SwapChainID =(IMG_UINT32)psSwapChain;
+
+ psDevInfo->psSwapChain = psSwapChain;
+
+ ResetVSyncFlipItems(psDevInfo);
+ S3C_InstallVsyncISR();
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR DestroyDCSwapChain(IMG_HANDLE hDevice,
+ IMG_HANDLE hSwapChain)
+{
+ S3C_SWAPCHAIN *sc = (S3C_SWAPCHAIN *)hSwapChain;
+ S3C_LCD_DEVINFO *psLCDInfo = (S3C_LCD_DEVINFO*)hDevice;
+
+ if(!hDevice || !hSwapChain)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ FlushInternalVSyncQueue(psLCDInfo);
+
+ S3C_Flip(psLCDInfo, &psLCDInfo->sSysBuffer);
+
+ kfree(sc->psBuffer);
+ kfree(sc);
+
+ if (psLCDInfo->psSwapChain == sc)
+ psLCDInfo->psSwapChain = NULL;
+
+ ResetVSyncFlipItems(psLCDInfo);
+
+ S3C_UninstallVsyncISR();
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR SetDCDstRect(IMG_HANDLE hDevice,
+ IMG_HANDLE hSwapChain,
+ IMG_RECT *psRect)
+{
+ PVR_UNREFERENCED_PARAMETER(hDevice);
+ PVR_UNREFERENCED_PARAMETER(hSwapChain);
+ PVR_UNREFERENCED_PARAMETER(psRect);
+
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+
+static PVRSRV_ERROR SetDCSrcRect(IMG_HANDLE hDevice,
+ IMG_HANDLE hSwapChain,
+ IMG_RECT *psRect)
+{
+
+ PVR_UNREFERENCED_PARAMETER(hDevice);
+ PVR_UNREFERENCED_PARAMETER(hSwapChain);
+ PVR_UNREFERENCED_PARAMETER(psRect);
+
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+
+static PVRSRV_ERROR SetDCDstColourKey(IMG_HANDLE hDevice,
+ IMG_HANDLE hSwapChain,
+ IMG_UINT32 ui32CKColour)
+{
+ PVR_UNREFERENCED_PARAMETER(hDevice);
+ PVR_UNREFERENCED_PARAMETER(hSwapChain);
+ PVR_UNREFERENCED_PARAMETER(ui32CKColour);
+
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+static PVRSRV_ERROR SetDCSrcColourKey(IMG_HANDLE hDevice,
+ IMG_HANDLE hSwapChain,
+ IMG_UINT32 ui32CKColour)
+{
+ PVR_UNREFERENCED_PARAMETER(hDevice);
+ PVR_UNREFERENCED_PARAMETER(hSwapChain);
+ PVR_UNREFERENCED_PARAMETER(ui32CKColour);
+
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+static IMG_VOID S3CSetState(IMG_HANDLE hDevice, IMG_UINT32 ui32State)
+{
+ S3C_LCD_DEVINFO *psDevInfo;
+
+ psDevInfo = (S3C_LCD_DEVINFO*)hDevice;
+
+ if (ui32State == DC_STATE_FLUSH_COMMANDS)
+ {
+ if (psDevInfo->psSwapChain != 0)
+ {
+ FlushInternalVSyncQueue(psDevInfo);
+ }
+
+ psDevInfo->bFlushCommands =S3C_TRUE;
+ }
+ else if (ui32State == DC_STATE_NO_FLUSH_COMMANDS)
+ {
+ psDevInfo->bFlushCommands = S3C_FALSE;
+ }
+}
+
+static PVRSRV_ERROR GetDCBuffers(IMG_HANDLE hDevice,
+ IMG_HANDLE hSwapChain,
+ IMG_UINT32 *pui32BufferCount,
+ IMG_HANDLE *phBuffer)
+{
+ S3C_LCD_DEVINFO *psLCDInfo = (S3C_LCD_DEVINFO*)hDevice;
+ int i;
+
+ if(!hDevice || !hSwapChain || !pui32BufferCount || !phBuffer)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ *pui32BufferCount = psLCDInfo->psSwapChain->ulBufferCount;
+
+ phBuffer[0] = (IMG_HANDLE)(&(psLCDInfo->sSysBuffer));
+ for (i=0; i < (*pui32BufferCount) - 1; i++)
+ {
+ phBuffer[i+1] = (IMG_HANDLE)&psLCDInfo->asBackBuffers[i];
+ }
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR SwapToDCBuffer(IMG_HANDLE hDevice,
+ IMG_HANDLE hBuffer,
+ IMG_UINT32 ui32SwapInterval,
+ IMG_HANDLE hPrivateTag,
+ IMG_UINT32 ui32ClipRectCount,
+ IMG_RECT *psClipRect)
+{
+ PVR_UNREFERENCED_PARAMETER(ui32SwapInterval);
+ PVR_UNREFERENCED_PARAMETER(hPrivateTag);
+ PVR_UNREFERENCED_PARAMETER(psClipRect);
+
+ if(!hDevice || !hBuffer || ui32ClipRectCount != 0)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR SwapToDCSystem(IMG_HANDLE hDevice,
+ IMG_HANDLE hSwapChain)
+{
+
+ if(!hDevice || !hSwapChain)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return PVRSRV_OK;
+}
+
+static IMG_BOOL ProcessFlipV1(IMG_HANDLE hCmdCookie,
+ S3C_LCD_DEVINFO *psDevInfo,
+ S3C_FRAME_BUFFER *psFb,
+ IMG_UINT32 ui32SwapInterval)
+{
+ S3C_VSYNC_FLIP_ITEM *psFlipItem;
+
+ if(ui32SwapInterval == 0)
+ {
+ S3C_Flip(psDevInfo, psFb);
+ gsPVRJTable.pfnPVRSRVCmdComplete(hCmdCookie, IMG_FALSE);
+ return IMG_TRUE;
+ }
+
+ mutex_lock(&psDevInfo->sVsyncFlipItemMutex);
+
+ psFlipItem = &psDevInfo->asVSyncFlips[psDevInfo->ulInsertIndex];
+
+ if(psFlipItem->bValid)
+ {
+ mutex_unlock(&psDevInfo->sVsyncFlipItemMutex);
+ return IMG_FALSE;
+ }
+
+ if(psDevInfo->ulInsertIndex == psDevInfo->ulRemoveIndex)
+ {
+ S3C_Flip(psDevInfo, psFb);
+ psFlipItem->bFlipped = S3C_TRUE;
+ }
+ else
+ {
+ psFlipItem->bFlipped = S3C_FALSE;
+ }
+
+ psFlipItem->hCmdComplete = hCmdCookie;
+ psFlipItem->psFb = psFb;
+ psFlipItem->ulSwapInterval = (unsigned long)ui32SwapInterval;
+
+ psFlipItem->bValid = S3C_TRUE;
+
+ AdvanceFlipIndex(psDevInfo, &psDevInfo->ulInsertIndex);
+
+ mutex_unlock(&psDevInfo->sVsyncFlipItemMutex);
+ return IMG_TRUE;
+}
+
+static IMG_BOOL ProcessFlip(IMG_HANDLE hCmdCookie,
+ IMG_UINT32 ui32DataSize,
+ IMG_VOID *pvData)
+{
+ DISPLAYCLASS_FLIP_COMMAND *psFlipCmd;
+ S3C_LCD_DEVINFO *psDevInfo;
+
+ /* Check parameters */
+ if(!hCmdCookie || !pvData)
+ {
+ return IMG_FALSE;
+ }
+
+ /* Validate data packet */
+ psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND*)pvData;
+
+ if (psFlipCmd == IMG_NULL)
+ {
+ return IMG_FALSE;
+ }
+
+ psDevInfo = (S3C_LCD_DEVINFO*)psFlipCmd->hExtDevice;
+
+ if (psDevInfo->bFlushCommands)
+ {
+ gsPVRJTable.pfnPVRSRVCmdComplete(hCmdCookie, IMG_FALSE);
+ return IMG_TRUE;
+ }
+
+ return ProcessFlipV1(hCmdCookie,
+ psDevInfo,
+ psFlipCmd->hExtBuffer,
+ psFlipCmd->ui32SwapInterval);
+}
+
+static S3C_BOOL InitDev(struct fb_info **s3c_fb_Info)
+{
+ struct fb_info *psLINFBInfo;
+ struct module *psLINFBOwner;
+ S3C_BOOL eError = S3C_TRUE;
+
+ S3C_CONSOLE_LOCK();
+
+ if (fb_idx < 0 || fb_idx >= num_registered_fb)
+ {
+ eError = S3C_FALSE;
+ goto errRelSem;
+ }
+
+ psLINFBInfo = registered_fb[fb_idx];
+
+ psLINFBOwner = psLINFBInfo->fbops->owner;
+ if (!try_module_get(psLINFBOwner))
+ {
+ printk("Couldn't get framebuffer module\n");
+ eError = S3C_FALSE;
+ goto errRelSem;
+ }
+
+ if (psLINFBInfo->fbops->fb_open != NULL)
+ {
+ int res;
+
+ res = psLINFBInfo->fbops->fb_open(psLINFBInfo, 0);
+ if (res != 0)
+ {
+ printk("Couldn't open framebuffer: %d\n", res);
+ eError = S3C_FALSE;
+ goto errModPut;
+ }
+ }
+
+ *s3c_fb_Info = psLINFBInfo;
+
+errModPut:
+ module_put(psLINFBOwner);
+errRelSem:
+ S3C_CONSOLE_UNLOCK();
+
+ return eError;
+}
+
+static void DeInitDev(S3C_LCD_DEVINFO *psDevInfo)
+{
+ struct fb_info *psLINFBInfo = psDevInfo->psFBInfo;
+ struct module *psLINFBOwner;
+
+ S3C_CONSOLE_LOCK();
+
+ psLINFBOwner = psLINFBInfo->fbops->owner;
+
+ if (psLINFBInfo->fbops->fb_release != NULL)
+ {
+ (void) psLINFBInfo->fbops->fb_release(psLINFBInfo, 0);
+ }
+
+ module_put(psLINFBOwner);
+
+ S3C_CONSOLE_UNLOCK();
+}
+
+int s3c_displayclass_init(void)
+{
+ IMG_UINT32 aui32SyncCountList[DC_S3C_LCD_COMMAND_COUNT][2];
+ PFN_CMD_PROC pfnCmdProcList[DC_S3C_LCD_COMMAND_COUNT];
+ int rgb_format, bytes_per_pixel, bits_per_pixel;
+ IMG_UINT32 num_of_fb, num_of_backbuffer;
+ IMG_UINT32 byteSize, ui32FBOffset = 0;
+ IMG_UINT32 pa_fb, va_fb, fb_size;
+ struct fb_info *psLINFBInfo = 0;
+ IMG_UINT32 screen_w, screen_h;
+ int i;
+
+ if(InitDev(&psLINFBInfo) == S3C_FALSE)
+ {
+ return 0;
+ }
+
+ pa_fb = psLINFBInfo->fix.smem_start;
+ va_fb = (unsigned long)phys_to_virt(psLINFBInfo->fix.smem_start);
+ screen_w = psLINFBInfo->var.xres;
+ screen_h = psLINFBInfo->var.yres;
+ bits_per_pixel = psLINFBInfo->var.bits_per_pixel;
+ fb_size = psLINFBInfo->fix.smem_len;
+
+ switch (bits_per_pixel)
+ {
+ case 16:
+ rgb_format = PVRSRV_PIXEL_FORMAT_RGB565;
+ bytes_per_pixel = 2;
+ break;
+ case 32:
+ rgb_format = PVRSRV_PIXEL_FORMAT_ARGB8888;
+ bytes_per_pixel = 4;
+ break;
+ default:
+ rgb_format = PVRSRV_PIXEL_FORMAT_ARGB8888;
+ bytes_per_pixel = 4;
+ break;
+ }
+
+ printk("PA FB = 0x%X, bits per pixel = %d\n", (unsigned int)pa_fb, (unsigned int)bits_per_pixel);
+ printk("screen width=%d height=%d va=0x%x pa=0x%x\n", (int)screen_w, (int)screen_h, (unsigned int)va_fb, (unsigned int)pa_fb);
+ printk("xres_virtual = %d, yres_virtual = %d, xoffset = %d, yoffset = %d\n", psLINFBInfo->var.xres_virtual, psLINFBInfo->var.yres_virtual, psLINFBInfo->var.xoffset, psLINFBInfo->var.yoffset);
+ printk("fb_size=%d\n", (int)fb_size);
+
+ /* We'll share the framebuffer region with video decode buffers,
+ * so we need to make sure all the frame buffers are page aligned.
+ */
+ BUG_ON(pa_fb != ALIGN(pa_fb, PAGE_SIZE));
+ byteSize = ALIGN(screen_w * screen_h * bytes_per_pixel, PAGE_SIZE);
+
+ num_of_fb = fb_size / byteSize;
+ if(num_of_fb > S3C_MAX_BUFFERS)
+ num_of_fb = S3C_MAX_BUFFERS;
+
+ num_of_backbuffer = num_of_fb - 1;
+
+ if (gpsLCDInfo != NULL)
+ goto exit_out;
+
+ gpsLCDInfo = (S3C_LCD_DEVINFO*)kmalloc(sizeof(S3C_LCD_DEVINFO),GFP_KERNEL);
+
+ gpsLCDInfo->psFBInfo = psLINFBInfo;
+ gpsLCDInfo->ui32NumFrameBuffers = num_of_fb;
+
+ gpsLCDInfo->ui32NumFormats = S3C_DISPLAY_FORMAT_NUM;
+
+ gpsLCDInfo->asDisplayFormatList[0].pixelformat = rgb_format;
+ gpsLCDInfo->ui32NumDims = S3C_DISPLAY_DIM_NUM;
+ gpsLCDInfo->asDisplayDimList[0].ui32ByteStride = (bytes_per_pixel) * screen_w;
+ gpsLCDInfo->asDisplayDimList[0].ui32Height = screen_h;
+ gpsLCDInfo->asDisplayDimList[0].ui32Width = screen_w;
+
+ gpsLCDInfo->sSysBuffer.bufferPAddr.uiAddr = pa_fb;
+ gpsLCDInfo->sSysBuffer.bufferVAddr = (IMG_CPU_VIRTADDR)va_fb;
+ gpsLCDInfo->sSysBuffer.yoffset = 0;
+ gpsLCDInfo->sSysBuffer.byteSize = (IMG_UINT32)byteSize;
+ ui32FBOffset += byteSize;
+
+ for (i=0 ; i < num_of_backbuffer; i++)
+ {
+ gpsLCDInfo->asBackBuffers[i].byteSize = gpsLCDInfo->sSysBuffer.byteSize;
+ gpsLCDInfo->asBackBuffers[i].bufferPAddr.uiAddr = pa_fb + byteSize * (i+1);
+ gpsLCDInfo->asBackBuffers[i].bufferVAddr = (IMG_CPU_VIRTADDR)phys_to_virt(gpsLCDInfo->asBackBuffers[i].bufferPAddr.uiAddr);
+ gpsLCDInfo->asBackBuffers[i].yoffset = screen_h * (i + 1);
+ ui32FBOffset += byteSize;
+
+ printk("Back frameBuffer[%d].VAddr=%p PAddr=%p size=%d\n",
+ i,
+ (void*)gpsLCDInfo->asBackBuffers[i].bufferVAddr,
+ (void*)gpsLCDInfo->asBackBuffers[i].bufferPAddr.uiAddr,
+ (int)gpsLCDInfo->asBackBuffers[i].byteSize);
+ }
+
+ gpsLCDInfo->bFlushCommands = S3C_FALSE;
+ gpsLCDInfo->psSwapChain = NULL;
+
+ PVRGetDisplayClassJTable(&gsPVRJTable);
+
+ gpsLCDInfo->sDCJTable.ui32TableSize = sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE);
+ gpsLCDInfo->sDCJTable.pfnOpenDCDevice = OpenDCDevice;
+ gpsLCDInfo->sDCJTable.pfnCloseDCDevice = CloseDCDevice;
+ gpsLCDInfo->sDCJTable.pfnEnumDCFormats = EnumDCFormats;
+ gpsLCDInfo->sDCJTable.pfnEnumDCDims = EnumDCDims;
+ gpsLCDInfo->sDCJTable.pfnGetDCSystemBuffer = GetDCSystemBuffer;
+ gpsLCDInfo->sDCJTable.pfnGetDCInfo = GetDCInfo;
+ gpsLCDInfo->sDCJTable.pfnGetBufferAddr = GetDCBufferAddr;
+ gpsLCDInfo->sDCJTable.pfnCreateDCSwapChain = CreateDCSwapChain;
+ gpsLCDInfo->sDCJTable.pfnDestroyDCSwapChain = DestroyDCSwapChain;
+ gpsLCDInfo->sDCJTable.pfnSetDCDstRect = SetDCDstRect;
+ gpsLCDInfo->sDCJTable.pfnSetDCSrcRect = SetDCSrcRect;
+ gpsLCDInfo->sDCJTable.pfnSetDCDstColourKey = SetDCDstColourKey;
+ gpsLCDInfo->sDCJTable.pfnSetDCSrcColourKey = SetDCSrcColourKey;
+ gpsLCDInfo->sDCJTable.pfnGetDCBuffers = GetDCBuffers;
+ gpsLCDInfo->sDCJTable.pfnSwapToDCBuffer = SwapToDCBuffer;
+ gpsLCDInfo->sDCJTable.pfnSwapToDCSystem = SwapToDCSystem;
+ gpsLCDInfo->sDCJTable.pfnSetDCState = S3CSetState;
+
+ gpsLCDInfo->sDisplayInfo.ui32MinSwapInterval=0;
+ gpsLCDInfo->sDisplayInfo.ui32MaxSwapInterval=1;
+ gpsLCDInfo->sDisplayInfo.ui32MaxSwapChains=1;
+ gpsLCDInfo->sDisplayInfo.ui32MaxSwapChainBuffers = num_of_fb;
+ gpsLCDInfo->sDisplayInfo.ui32PhysicalWidthmm= psLINFBInfo->var.width;// width of lcd in mm
+ gpsLCDInfo->sDisplayInfo.ui32PhysicalHeightmm= psLINFBInfo->var.height;// height of lcd in mm
+
+ strncpy(gpsLCDInfo->sDisplayInfo.szDisplayName, "s3c_lcd", MAX_DISPLAY_NAME_SIZE);
+
+ if(ui32FBOffset + S3C_VIDEO_CARVEOUT_SIZE <= fb_size)
+ {
+ if(InitVidBufs(ui32FBOffset))
+ return 1;
+ }
+ else
+ {
+ printk("No space for NV12 video carveout\n");
+ }
+
+ if(gsPVRJTable.pfnPVRSRVRegisterDCDevice(&gpsLCDInfo->sDCJTable,
+ &gpsLCDInfo->ui32DeviceID) != PVRSRV_OK)
+ {
+ return 1;
+ }
+
+ pfnCmdProcList[DC_FLIP_COMMAND] = ProcessFlip;
+ aui32SyncCountList[DC_FLIP_COMMAND][0] = 0;
+ aui32SyncCountList[DC_FLIP_COMMAND][1] = 2;
+
+ if (gsPVRJTable.pfnPVRSRVRegisterCmdProcList(gpsLCDInfo->ui32DeviceID,
+ &pfnCmdProcList[0], aui32SyncCountList, DC_S3C_LCD_COMMAND_COUNT) != PVRSRV_OK)
+ {
+ printk("failing register commmand proc list deviceID:%d\n",(int)gpsLCDInfo->ui32DeviceID);
+ return PVRSRV_ERROR_CANT_REGISTER_CALLBACK;
+ }
+
+ if(CreateVsyncWorkQueue(gpsLCDInfo) == S3C_FALSE)
+ {
+ printk("fail to CreateVsyncWorkQueue\n");
+ return 1;
+ }
+
+exit_out:
+ return 0;
+}
+
+void s3c_displayclass_deinit(void)
+{
+ destroyVsyncWorkQueue(gpsLCDInfo);
+ DeInitDev(gpsLCDInfo);
+
+ gsPVRJTable.pfnPVRSRVRemoveCmdProcList(gpsLCDInfo->ui32DeviceID,
+ DC_S3C_LCD_COMMAND_COUNT);
+
+ DeinitVidBufs();
+
+ gsPVRJTable.pfnPVRSRVRemoveDCDevice(gpsLCDInfo->ui32DeviceID);
+
+ kfree(gpsLCDInfo);
+ gpsLCDInfo = NULL;
+}
+
+/*****************************************************************************
+ * Video-decode carveout workaround starts here
+ */
+
+static PVRSRV_ERROR EnumVidBufFormats(IMG_HANDLE hDevice,
+ IMG_UINT32 *pui32NumFormats,
+ DISPLAY_FORMAT *psFormat)
+{
+ DISPLAY_FORMAT sVidBufFormat = {
+ /* Fake format to keep PVR2D happy */
+ .pixelformat = PVRSRV_PIXEL_FORMAT_ARGB8888,
+ };
+
+ PVR_UNREFERENCED_PARAMETER(hDevice);
+
+ if(pui32NumFormats)
+ *pui32NumFormats = 1;
+
+ if(psFormat)
+ *psFormat = sVidBufFormat;
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR EnumVidBufDims(IMG_HANDLE hDevice,
+ DISPLAY_FORMAT *psFormat,
+ IMG_UINT32 *pui32NumDims,
+ DISPLAY_DIMS *psDim)
+{
+ DISPLAY_DIMS sVidBufDim = {
+ .ui32Width = 1280,
+ .ui32Height = 720,
+ .ui32ByteStride = 1280,
+ };
+
+ PVR_UNREFERENCED_PARAMETER(hDevice);
+ PVR_UNREFERENCED_PARAMETER(psFormat);
+
+ if((S3C_VIDBUF_DEVINFO *)hDevice == &gsUVBufInfo)
+ sVidBufDim.ui32Height /= 2;
+
+ if(pui32NumDims)
+ *pui32NumDims = 1;
+
+ if(psDim)
+ psDim[0] = sVidBufDim;
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR GetVidBufSystemBuffer(IMG_HANDLE hDevice,
+ IMG_HANDLE *phBuffer)
+{
+ S3C_VIDBUF_DEVINFO *psDevInfo = (S3C_VIDBUF_DEVINFO *)hDevice;
+
+ if(!hDevice || !phBuffer)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ /* FIXME: Is this really necessary? */
+ *phBuffer = (IMG_HANDLE)&psDevInfo->asVideoBuffers[0];
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR GetVidBufInfo(IMG_HANDLE hDevice, DISPLAY_INFO *psDCInfo)
+{
+ S3C_VIDBUF_DEVINFO *psDevInfo = (S3C_VIDBUF_DEVINFO*)hDevice;
+
+ if(!hDevice || !psDCInfo)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ *psDCInfo = psDevInfo->sDisplayInfo;
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR
+CreateVidBufSwapChain(IMG_HANDLE hDevice,
+ IMG_UINT32 ui32Flags,
+ DISPLAY_SURF_ATTRIBUTES *psDstSurfAttrib,
+ DISPLAY_SURF_ATTRIBUTES *psSrcSurfAttrib,
+ IMG_UINT32 ui32BufferCount,
+ PVRSRV_SYNC_DATA **ppsSyncData,
+ IMG_UINT32 ui32OEMFlags,
+ IMG_HANDLE *phSwapChain,
+ IMG_UINT32 *pui32SwapChainID)
+{
+ S3C_VIDBUF_DEVINFO *psDevInfo = (S3C_VIDBUF_DEVINFO*)hDevice;
+ S3C_FRAME_BUFFER *psBuffer;
+ S3C_SWAPCHAIN *psSwapChain;
+ IMG_UINT32 i;
+
+ PVR_UNREFERENCED_PARAMETER(pui32SwapChainID);
+ PVR_UNREFERENCED_PARAMETER(psDstSurfAttrib);
+ PVR_UNREFERENCED_PARAMETER(psSrcSurfAttrib);
+ PVR_UNREFERENCED_PARAMETER(ui32OEMFlags);
+ PVR_UNREFERENCED_PARAMETER(ppsSyncData);
+
+ if(!hDevice || !phSwapChain || (psDevInfo != &gsYBufInfo &&
+ psDevInfo != &gsUVBufInfo))
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if(ui32BufferCount > S3C_MAX_VIDEO_BUFFERS)
+ {
+ return PVRSRV_ERROR_TOOMANYBUFFERS;
+ }
+
+ if(psDevInfo->psSwapChain)
+ {
+ return PVRSRV_ERROR_FLIP_CHAIN_EXISTS;
+ }
+
+ psSwapChain = (S3C_SWAPCHAIN *)kmalloc(sizeof(S3C_SWAPCHAIN), GFP_KERNEL);
+ if(!psSwapChain)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ psBuffer = (S3C_FRAME_BUFFER *)kmalloc(sizeof(S3C_FRAME_BUFFER) * ui32BufferCount, GFP_KERNEL);
+ if(!psBuffer)
+ {
+ kfree(psSwapChain);
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ psSwapChain->ulBufferCount = (unsigned long)ui32BufferCount;
+ psSwapChain->psBuffer = psBuffer;
+
+ for (i = 0; i < ui32BufferCount; i++)
+ {
+ psBuffer[i] = psDevInfo->asVideoBuffers[i];
+ }
+
+ *phSwapChain = (IMG_HANDLE)psSwapChain;
+ *pui32SwapChainID =(IMG_UINT32)psSwapChain;
+ psDevInfo->psSwapChain = psSwapChain;
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR DestroyVidBufSwapChain(IMG_HANDLE hDevice,
+ IMG_HANDLE hSwapChain)
+{
+ S3C_VIDBUF_DEVINFO *psDevInfo = (S3C_VIDBUF_DEVINFO*)hDevice;
+
+ if(!psDevInfo || hSwapChain != (IMG_HANDLE)psDevInfo->psSwapChain)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ kfree(psDevInfo->psSwapChain->psBuffer);
+
+ kfree(psDevInfo->psSwapChain);
+ psDevInfo->psSwapChain = NULL;
+
+ return PVRSRV_OK;
+}
+
+static IMG_VOID SetVidBufState(IMG_HANDLE hDevice, IMG_UINT32 ui32State)
+{
+ PVR_UNREFERENCED_PARAMETER(hDevice);
+ PVR_UNREFERENCED_PARAMETER(ui32State);
+}
+
+static PVRSRV_ERROR GetVidBufBuffers(IMG_HANDLE hDevice,
+ IMG_HANDLE hSwapChain,
+ IMG_UINT32 *pui32BufferCount,
+ IMG_HANDLE *phBuffer)
+{
+ S3C_VIDBUF_DEVINFO *psDevInfo = (S3C_VIDBUF_DEVINFO*)hDevice;
+ int i;
+
+ if(!hDevice || !hSwapChain || !pui32BufferCount || !phBuffer)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ *pui32BufferCount = psDevInfo->psSwapChain->ulBufferCount;
+
+ for (i = 0; i < *pui32BufferCount; i++)
+ {
+ phBuffer[i] = (IMG_HANDLE)&psDevInfo->asVideoBuffers[i];
+ }
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_DC_SRV2DISP_KMJTABLE gsYUVDCJTable =
+{
+ .ui32TableSize = sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE),
+
+ /* These understand video buffers, or are no-ops */
+ .pfnOpenDCDevice = OpenDCDevice,
+ .pfnCloseDCDevice = CloseDCDevice,
+ .pfnSetDCDstRect = SetDCDstRect,
+ .pfnSetDCSrcRect = SetDCSrcRect,
+ .pfnSetDCDstColourKey = SetDCDstColourKey,
+ .pfnSetDCSrcColourKey = SetDCSrcColourKey,
+ .pfnSwapToDCBuffer = SwapToDCBuffer,
+ .pfnSwapToDCSystem = SwapToDCSystem,
+ .pfnGetBufferAddr = GetDCBufferAddr,
+
+ /* These return PVRSRV_ERROR_NOT_SUPPORTED */
+ .pfnGetDCSystemBuffer = GetVidBufSystemBuffer,
+ .pfnGetDCInfo = GetVidBufInfo,
+
+ /* These work as documented */
+ .pfnEnumDCFormats = EnumVidBufFormats,
+ .pfnEnumDCDims = EnumVidBufDims,
+ .pfnCreateDCSwapChain = CreateVidBufSwapChain,
+ .pfnDestroyDCSwapChain = DestroyVidBufSwapChain,
+ .pfnGetDCBuffers = GetVidBufBuffers,
+ .pfnSetDCState = SetVidBufState,
+};
+
+static int InitVidBufs(IMG_UINT32 ui32FBOffset)
+{
+ int i;
+
+ if(gsPVRJTable.pfnPVRSRVRegisterDCDevice(&gsYUVDCJTable,
+ &gsYBufInfo.ui32DeviceID) != PVRSRV_OK)
+ {
+ printk("Failed to register YBuf device!\n");
+ return 1;
+ }
+
+ if(gsPVRJTable.pfnPVRSRVRegisterDCDevice(&gsYUVDCJTable,
+ &gsUVBufInfo.ui32DeviceID) != PVRSRV_OK)
+ {
+ printk("Failed to register UVBuf device!\n");
+ return 1;
+ }
+
+ for (i = 0; i < S3C_MAX_VIDEO_BUFFERS; i++)
+ {
+ gsYBufInfo.asVideoBuffers[i].bufferPAddr.uiAddr =
+ gpsLCDInfo->sSysBuffer.bufferPAddr.uiAddr + ui32FBOffset +
+ (i * S3C_VIDEO_Y_SIZE);
+ gsYBufInfo.asVideoBuffers[i].bufferVAddr =
+ gpsLCDInfo->sSysBuffer.bufferVAddr + ui32FBOffset +
+ (i * S3C_VIDEO_Y_SIZE);
+ gsYBufInfo.asVideoBuffers[i].byteSize = S3C_VIDEO_Y_SIZE;
+ gsYBufInfo.asVideoBuffers[i].yoffset = 0;
+
+ printk("Video Y Buffer[%d].VAddr=%p PAddr=%p size=%d\n",
+ i,
+ (void*)gsYBufInfo.asVideoBuffers[i].bufferVAddr,
+ (void*)gsYBufInfo.asVideoBuffers[i].bufferPAddr.uiAddr,
+ (int)gsYBufInfo.asVideoBuffers[i].byteSize);
+ }
+
+ for (i = 0; i < S3C_MAX_VIDEO_BUFFERS; i++)
+ {
+ gsUVBufInfo.asVideoBuffers[i].bufferPAddr.uiAddr =
+ gpsLCDInfo->sSysBuffer.bufferPAddr.uiAddr + ui32FBOffset +
+ (S3C_MAX_VIDEO_BUFFERS * S3C_VIDEO_Y_SIZE) +
+ (i * S3C_VIDEO_UV_SIZE);
+ gsUVBufInfo.asVideoBuffers[i].bufferVAddr =
+ gpsLCDInfo->sSysBuffer.bufferVAddr + ui32FBOffset +
+ (S3C_MAX_VIDEO_BUFFERS * S3C_VIDEO_Y_SIZE) +
+ (i * S3C_VIDEO_UV_SIZE);
+ gsUVBufInfo.asVideoBuffers[i].byteSize = S3C_VIDEO_UV_SIZE;
+ gsUVBufInfo.asVideoBuffers[i].yoffset = 0;
+
+ printk("Video UV Buffer[%d].VAddr=%p PAddr=%p size=%d\n",
+ i,
+ (void*)gsUVBufInfo.asVideoBuffers[i].bufferVAddr,
+ (void*)gsUVBufInfo.asVideoBuffers[i].bufferPAddr.uiAddr,
+ (int)gsUVBufInfo.asVideoBuffers[i].byteSize);
+ }
+
+ return 0;
+}
+
+static void DeinitVidBufs(void)
+{
+ if(gsUVBufInfo.ui32DeviceID)
+ {
+ gsPVRJTable.pfnPVRSRVRemoveDCDevice(gsUVBufInfo.ui32DeviceID);
+ }
+
+ if(gsYBufInfo.ui32DeviceID)
+ {
+ gsPVRJTable.pfnPVRSRVRemoveDCDevice(gsYBufInfo.ui32DeviceID);
+ }
+}
diff --git a/drivers/gpu/pvr/s3c_lcd/s3c_lcd.c b/drivers/gpu/pvr/s3c_lcd/s3c_lcd.c
new file mode 100644
index 0000000..e9cb9bb
--- /dev/null
+++ b/drivers/gpu/pvr/s3c_lcd/s3c_lcd.c
@@ -0,0 +1,58 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ */
+
+/* Copyright (C) Samsung Electronics System LSI. */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+
+#include <asm/uaccess.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include "img_defs.h"
+#include "servicesext.h"
+#include "kerneldisplay.h"
+#include "pvrmodule.h"
+
+#include "s3c_lcd.h"
+
+static int __init S3cLcdBridgeInit(void)
+{
+ if(s3c_displayclass_init())
+ return -1;
+ return 0;
+}
+
+static void __exit S3cLcdBridgeExit (void)
+{
+ s3c_displayclass_deinit();
+}
+
+module_init(S3cLcdBridgeInit);
+module_exit(S3cLcdBridgeExit);
diff --git a/drivers/gpu/pvr/s3c_lcd/s3c_lcd.h b/drivers/gpu/pvr/s3c_lcd/s3c_lcd.h
new file mode 100644
index 0000000..70b4103
--- /dev/null
+++ b/drivers/gpu/pvr/s3c_lcd/s3c_lcd.h
@@ -0,0 +1,42 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ */
+
+/* Copyright (C) Samsung Electronics System LSI. */
+
+#ifndef __S3C_LCD_H__
+#define __S3C_LCD_H__
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+int s3c_displayclass_init(void);
+void s3c_displayclass_deinit(void);
+
+#if defined(__cplusplus)
+}
+#endif
+#endif
diff --git a/drivers/gpu/pvr/s5pc110/oemfuncs.h b/drivers/gpu/pvr/s5pc110/oemfuncs.h
new file mode 100644
index 0000000..a4c7cd8
--- /dev/null
+++ b/drivers/gpu/pvr/s5pc110/oemfuncs.h
@@ -0,0 +1,81 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+******************************************************************************/
+
+#if !defined(__OEMFUNCS_H__)
+#define __OEMFUNCS_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/* function identifiers: */
+#define OEM_EXCHANGE_POWER_STATE (1<<0)
+#define OEM_DEVICE_MEMORY_POWER (1<<1)
+#define OEM_DISPLAY_POWER (1<<2)
+#define OEM_GET_EXT_FUNCS (1<<3)
+
+typedef struct OEM_ACCESS_INFO_TAG
+{
+ IMG_UINT32 ui32Size;
+ IMG_UINT32 ui32FBPhysBaseAddress;
+ IMG_UINT32 ui32FBMemAvailable; /* size of usable FB memory */
+ IMG_UINT32 ui32SysPhysBaseAddress;
+ IMG_UINT32 ui32SysSize;
+ IMG_UINT32 ui32DevIRQ;
+} OEM_ACCESS_INFO, *POEM_ACCESS_INFO;
+
+/* function in/out data structures: */
+typedef IMG_UINT32 (*PFN_SRV_BRIDGEDISPATCH)( IMG_UINT32 Ioctl,
+ IMG_BYTE *pInBuf,
+ IMG_UINT32 InBufLen,
+ IMG_BYTE *pOutBuf,
+ IMG_UINT32 OutBufLen,
+ IMG_UINT32 *pdwBytesTransferred);
+
+
+typedef PVRSRV_ERROR (*PFN_SRV_READREGSTRING)(PPVRSRV_REGISTRY_INFO psRegInfo);
+
+/*
+ Function table for kernel 3rd party driver to kernel services
+*/
+typedef struct PVRSRV_DC_OEM_JTABLE_TAG
+{
+ PFN_SRV_BRIDGEDISPATCH pfnOEMBridgeDispatch;
+ PFN_SRV_READREGSTRING pfnOEMReadRegistryString;
+ PFN_SRV_READREGSTRING pfnOEMWriteRegistryString;
+
+} PVRSRV_DC_OEM_JTABLE;
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __OEMFUNCS_H__ */
+
+/*****************************************************************************
+ End of file (oemfuncs.h)
+*****************************************************************************/
+
+
diff --git a/drivers/gpu/pvr/s5pc110/sysconfig.c b/drivers/gpu/pvr/s5pc110/sysconfig.c
new file mode 100644
index 0000000..bc675bd
--- /dev/null
+++ b/drivers/gpu/pvr/s5pc110/sysconfig.c
@@ -0,0 +1,1031 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+******************************************************************************/
+
+#include "sgxdefs.h"
+#include "services_headers.h"
+#include "kerneldisplay.h"
+#include "oemfuncs.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/cpufreq.h>
+
+#define REAL_HARDWARE 1
+#define SGX540_BASEADDR 0xf3000000
+#define MAPPING_SIZE 0x10000
+#define SGX540_IRQ IRQ_3D
+
+#define SYS_SGX_CLOCK_SPEED (200000000)
+#define SYS_SGX_HWRECOVERY_TIMEOUT_FREQ (100) // 10ms (100hz)
+#define SYS_SGX_PDS_TIMER_FREQ (1000) // 1ms (1000hz)
+#ifndef SYS_SGX_ACTIVE_POWER_LATENCY_MS
+#define SYS_SGX_ACTIVE_POWER_LATENCY_MS (500)
+#endif
+
+typedef struct _SYS_SPECIFIC_DATA_TAG_
+{
+ IMG_UINT32 ui32SysSpecificData;
+
+} SYS_SPECIFIC_DATA;
+
+#define SYS_SPECIFIC_DATA_ENABLE_IRQ 0x00000001UL
+#define SYS_SPECIFIC_DATA_ENABLE_LISR 0x00000002UL
+#define SYS_SPECIFIC_DATA_ENABLE_MISR 0x00000004UL
+
+SYS_SPECIFIC_DATA gsSysSpecificData;
+
+/* top level system data anchor point*/
+SYS_DATA* gpsSysData = (SYS_DATA*)IMG_NULL;
+SYS_DATA gsSysData;
+
+/* SGX structures */
+static IMG_UINT32 gui32SGXDeviceID;
+static SGX_DEVICE_MAP gsSGXDeviceMap;
+
+/* mimic slaveport and register block with contiguous memory */
+IMG_CPU_VIRTADDR gsSGXRegsCPUVAddr;
+IMG_CPU_VIRTADDR gsSGXSPCPUVAddr;
+
+static char gszVersionString[] = "SGX540 S5PC110";
+
+IMG_UINT32 PVRSRV_BridgeDispatchKM( IMG_UINT32 Ioctl,
+ IMG_BYTE *pInBuf,
+ IMG_UINT32 InBufLen,
+ IMG_BYTE *pOutBuf,
+ IMG_UINT32 OutBufLen,
+ IMG_UINT32 *pdwBytesTransferred);
+
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+/*
+ * We need to keep the memory bus speed up when the GPU is active.
+ * On the S5PV210, it is bound to the CPU freq.
+ * In arch/arm/mach-s5pv210/cpufreq.c, the bus speed is only lowered when the
+ * CPU freq is below 200MHz.
+ */
+#define MIN_CPU_KHZ_FREQ 200000
+
+static struct clk *g3d_clock;
+static struct regulator *g3d_pd_regulator;
+
+static int limit_adjust_cpufreq_notifier(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ struct cpufreq_policy *policy = data;
+
+ if (event != CPUFREQ_ADJUST)
+ return 0;
+
+ /* This is our indicator of GPU activity */
+ if (regulator_is_enabled(g3d_pd_regulator))
+ cpufreq_verify_within_limits(policy, MIN_CPU_KHZ_FREQ,
+ policy->cpuinfo.max_freq);
+
+ return 0;
+}
+
+static struct notifier_block cpufreq_limit_notifier = {
+ .notifier_call = limit_adjust_cpufreq_notifier,
+};
+
+static PVRSRV_ERROR EnableSGXClocks(void)
+{
+ regulator_enable(g3d_pd_regulator);
+ clk_enable(g3d_clock);
+ cpufreq_update_policy(current_thread_info()->cpu);
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR DisableSGXClocks(void)
+{
+ clk_disable(g3d_clock);
+ regulator_disable(g3d_pd_regulator);
+ cpufreq_update_policy(current_thread_info()->cpu);
+
+ return PVRSRV_OK;
+}
+
+#endif /* defined(SUPPORT_ACTIVE_POWER_MANAGEMENT) */
+
+/*!
+******************************************************************************
+
+ @Function SysLocateDevices
+
+ @Description specifies devices in the systems memory map
+
+ @Input psSysData - sys data
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
+static PVRSRV_ERROR SysLocateDevices(SYS_DATA *psSysData)
+{
+ PVR_UNREFERENCED_PARAMETER(psSysData);
+
+ gsSGXDeviceMap.sRegsSysPBase.uiAddr = SGX540_BASEADDR;
+ gsSGXDeviceMap.sRegsCpuPBase = SysSysPAddrToCpuPAddr(gsSGXDeviceMap.sRegsSysPBase);
+ gsSGXDeviceMap.ui32RegsSize = SGX_REG_SIZE;
+ gsSGXDeviceMap.ui32IRQ = SGX540_IRQ;
+
+#if defined(SGX_FEATURE_HOST_PORT)
+ /* HostPort: */
+ gsSGXDeviceMap.sHPSysPBase.uiAddr = 0;
+ gsSGXDeviceMap.sHPCpuPBase.uiAddr = 0;
+ gsSGXDeviceMap.ui32HPSize = 0;
+#endif
+
+ /*
+ Local Device Memory Region: (not present)
+ Note: the device doesn't need to know about its memory
+ but keep info here for now
+ */
+ gsSGXDeviceMap.sLocalMemSysPBase.uiAddr = 0;
+ gsSGXDeviceMap.sLocalMemDevPBase.uiAddr = 0;
+ gsSGXDeviceMap.sLocalMemCpuPBase.uiAddr = 0;
+ gsSGXDeviceMap.ui32LocalMemSize = 0;
+
+ /*
+ device interrupt IRQ
+ Note: no interrupts available on No HW system
+ */
+ gsSGXDeviceMap.ui32IRQ = SGX540_IRQ;
+
+#if defined(PDUMP)
+ {
+ /* initialise memory region name for pdumping */
+ static IMG_CHAR pszPDumpDevName[] = "SGXMEM";
+ gsSGXDeviceMap.pszPDumpDevName = pszPDumpDevName;
+ }
+#endif
+
+ /* add other devices here: */
+
+ return PVRSRV_OK;
+}
+
+
+
+/*!
+******************************************************************************
+
+ @Function SysInitialise
+
+ @Description Initialises kernel services at 'driver load' time
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
+PVRSRV_ERROR SysInitialise(IMG_VOID)
+{
+ IMG_UINT32 i;
+ PVRSRV_ERROR eError;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ SGX_TIMING_INFORMATION* psTimingInfo;
+
+ gpsSysData = &gsSysData;
+ OSMemSet(gpsSysData, 0, sizeof(SYS_DATA));
+
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+ {
+ extern struct platform_device *gpsPVRLDMDev;
+
+ g3d_pd_regulator = regulator_get(&gpsPVRLDMDev->dev, "pd");
+
+ if (IS_ERR(g3d_pd_regulator))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "G3D failed to find g3d power domain"));
+ return PVRSRV_ERROR_INIT_FAILURE;
+ }
+
+ g3d_clock = clk_get(&gpsPVRLDMDev->dev, "sclk");
+ if (IS_ERR(g3d_clock))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "G3D failed to find g3d clock source-enable"));
+ return PVRSRV_ERROR_INIT_FAILURE;
+ }
+
+ EnableSGXClocks();
+ }
+#endif
+
+ eError = OSInitEnvData(&gpsSysData->pvEnvSpecificData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to setup env structure"));
+ SysDeinitialise(gpsSysData);
+ gpsSysData = IMG_NULL;
+ return eError;
+ }
+
+ gpsSysData->pvSysSpecificData = (IMG_PVOID)&gsSysSpecificData;
+ OSMemSet(&gsSGXDeviceMap, 0, sizeof(SGX_DEVICE_MAP));
+
+ /* Set up timing information*/
+ psTimingInfo = &gsSGXDeviceMap.sTimingInfo;
+ psTimingInfo->ui32CoreClockSpeed = SYS_SGX_CLOCK_SPEED;
+ psTimingInfo->ui32HWRecoveryFreq = SYS_SGX_HWRECOVERY_TIMEOUT_FREQ;
+ psTimingInfo->ui32ActivePowManLatencyms = SYS_SGX_ACTIVE_POWER_LATENCY_MS;
+ psTimingInfo->ui32uKernelFreq = SYS_SGX_PDS_TIMER_FREQ;
+
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+ psTimingInfo->bEnableActivePM = IMG_TRUE;
+#else
+ psTimingInfo->bEnableActivePM = IMG_FALSE;
+#endif
+
+ gpsSysData->ui32NumDevices = SYS_DEVICE_COUNT;
+
+ /* init device ID's */
+ for(i=0; i<SYS_DEVICE_COUNT; i++)
+ {
+ gpsSysData->sDeviceID[i].uiID = i;
+ gpsSysData->sDeviceID[i].bInUse = IMG_FALSE;
+ }
+
+ gpsSysData->psDeviceNodeList = IMG_NULL;
+ gpsSysData->psQueueList = IMG_NULL;
+
+ eError = SysInitialiseCommon(gpsSysData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed in SysInitialiseCommon"));
+ SysDeinitialise(gpsSysData);
+ gpsSysData = IMG_NULL;
+ return eError;
+ }
+
+ /*
+ Locate the devices within the system, specifying
+ the physical addresses of each devices components
+ (regs, mem, ports etc.)
+ */
+ eError = SysLocateDevices(gpsSysData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to locate devices"));
+ SysDeinitialise(gpsSysData);
+ gpsSysData = IMG_NULL;
+ return eError;
+ }
+
+ /*
+ Register devices with the system
+ This also sets up their memory maps/heaps
+ */
+ eError = PVRSRVRegisterDevice(gpsSysData, SGXRegisterDevice, 1, &gui32SGXDeviceID);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to register device!"));
+ SysDeinitialise(gpsSysData);
+ gpsSysData = IMG_NULL;
+ return eError;
+ }
+
+ /*
+ Once all devices are registered, specify the backing store
+ and, if required, customise the memory heap config
+ */
+ psDeviceNode = gpsSysData->psDeviceNodeList;
+ while(psDeviceNode)
+ {
+ /* perform any OEM SOC address space customisations here */
+ switch(psDeviceNode->sDevId.eDeviceType)
+ {
+ case PVRSRV_DEVICE_TYPE_SGX:
+ {
+ DEVICE_MEMORY_INFO *psDevMemoryInfo;
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+ IMG_UINT32 ui32MemConfig;
+
+ if(gpsSysData->apsLocalDevMemArena[0] != IMG_NULL)
+ {
+ /* specify the backing store to use for the device's MMU PT/PDs */
+ psDeviceNode->psLocalDevMemArena = gpsSysData->apsLocalDevMemArena[0];
+ ui32MemConfig = PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG;
+ }
+ else
+ {
+ /*
+ specify the backing store to use for the devices MMU PT/PDs
+ - the PT/PDs are always UMA in this system
+ */
+ psDeviceNode->psLocalDevMemArena = IMG_NULL;
+ ui32MemConfig = PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG;
+ }
+
+ /* useful pointers */
+ psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+ psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
+
+ /* specify the backing store for all SGX heaps */
+ for(i=0; i<psDevMemoryInfo->ui32HeapCount; i++)
+ {
+#if defined(SGX_FEATURE_VARIABLE_MMU_PAGE_SIZE)
+ IMG_CHAR *pStr;
+
+ switch(psDeviceMemoryHeap[i].ui32HeapID)
+ {
+ case HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_GENERAL_HEAP_ID):
+ {
+ pStr = "GeneralHeapPageSize";
+ break;
+ }
+ case HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_GENERAL_MAPPING_HEAP_ID):
+ {
+ pStr = "GeneralMappingHeapPageSize";
+ break;
+ }
+ case HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_TADATA_HEAP_ID):
+ {
+ pStr = "TADataHeapPageSize";
+ break;
+ }
+ case HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_KERNEL_CODE_HEAP_ID):
+ {
+ pStr = "KernelCodeHeapPageSize";
+ break;
+ }
+ case HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_KERNEL_DATA_HEAP_ID):
+ {
+ pStr = "KernelDataHeapPageSize";
+ break;
+ }
+ case HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_PIXELSHADER_HEAP_ID):
+ {
+ pStr = "PixelShaderHeapPageSize";
+ break;
+ }
+ case HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_VERTEXSHADER_HEAP_ID):
+ {
+ pStr = "VertexShaderHeapPageSize";
+ break;
+ }
+ case HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_PDSPIXEL_CODEDATA_HEAP_ID):
+ {
+ pStr = "PDSPixelHeapPageSize";
+ break;
+ }
+ case HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_PDSVERTEX_CODEDATA_HEAP_ID):
+ {
+ pStr = "PDSVertexHeapPageSize";
+ break;
+ }
+ case HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_SYNCINFO_HEAP_ID):
+ {
+ pStr = "SyncInfoHeapPageSize";
+ break;
+ }
+ case HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_3DPARAMETERS_HEAP_ID):
+ {
+ pStr = "3DParametersHeapPageSize";
+ break;
+ }
+ default:
+ {
+ /* not interested in other heaps */
+ pStr = IMG_NULL;
+ break;
+ }
+ }
+ if (pStr
+ && OSReadRegistryDWORDFromString(0,
+ PVRSRV_REGISTRY_ROOT,
+ pStr,
+ &psDeviceMemoryHeap[i].ui32DataPageSize) == IMG_TRUE)
+ {
+ PVR_DPF((PVR_DBG_VERBOSE,"SysInitialise: set Heap %s page size to %d", pStr, psDeviceMemoryHeap[i].ui32DataPageSize));
+ }
+#endif
+ /*
+ map the device memory allocator(s) onto
+ the device memory heaps as required
+ */
+ psDeviceMemoryHeap[i].psLocalDevMemArena = gpsSysData->apsLocalDevMemArena[0];
+
+ /* set the memory config (uma | non-uma) */
+ psDeviceMemoryHeap[i].ui32Attribs |= ui32MemConfig;
+ }
+
+ break;
+ }
+ default:
+ PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to find SGX device node!"));
+ return PVRSRV_ERROR_INIT_FAILURE;
+ }
+
+ /* advance to next device */
+ psDeviceNode = psDeviceNode->psNext;
+ }
+
+ /*
+ Initialise all devices 'managed' by services:
+ */
+ eError = PVRSRVInitialiseDevice (gui32SGXDeviceID);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to initialise device!"));
+ SysDeinitialise(gpsSysData);
+ gpsSysData = IMG_NULL;
+ return eError;
+ }
+
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+ DisableSGXClocks();
+#endif
+
+ return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function SysFinalise
+
+ @Description Final part of initialisation
+
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
+PVRSRV_ERROR SysFinalise(IMG_VOID)
+{
+ PVRSRV_ERROR eError;
+
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+ eError = EnableSGXClocks();
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to Enable SGX clocks (%d)", eError));
+ (IMG_VOID)SysDeinitialise(gpsSysData);
+ gpsSysData = IMG_NULL;
+ return eError;
+ }
+#endif
+
+ eError = OSInstallMISR(gpsSysData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"OSInstallMISR: Failed to install MISR"));
+ SysDeinitialise(gpsSysData);
+ gpsSysData = IMG_NULL;
+ return eError;
+ }
+ gsSysSpecificData.ui32SysSpecificData |= SYS_SPECIFIC_DATA_ENABLE_MISR;
+
+#if defined(SYS_USING_INTERRUPTS)
+ /* install a system ISR */
+ eError = OSInstallSystemLISR(gpsSysData, gsSGXDeviceMap.ui32IRQ);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"OSInstallSystemLISR: Failed to install ISR"));
+ OSUninstallMISR(gpsSysData);
+ SysDeinitialise(gpsSysData);
+ gpsSysData = IMG_NULL;
+ return eError;
+ }
+
+ gsSysSpecificData.ui32SysSpecificData |= SYS_SPECIFIC_DATA_ENABLE_LISR;
+ gsSysSpecificData.ui32SysSpecificData |= SYS_SPECIFIC_DATA_ENABLE_IRQ;
+#endif /* defined(SYS_USING_INTERRUPTS) */
+
+ /* Create a human readable version string for this system */
+ gpsSysData->pszVersionString = gszVersionString;
+
+ if (!gpsSysData->pszVersionString)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysFinalise: Failed to create a system version string"));
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_WARNING, "SysFinalise: Version string: %s", gpsSysData->pszVersionString));
+ }
+
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+ DisableSGXClocks();
+ cpufreq_register_notifier(&cpufreq_limit_notifier,
+ CPUFREQ_POLICY_NOTIFIER);
+#endif
+
+ return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function SysDeinitialise
+
+ @Description De-initialises kernel services at 'driver unload' time
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
+PVRSRV_ERROR SysDeinitialise (SYS_DATA *psSysData)
+{
+ SYS_SPECIFIC_DATA * psSysSpecData;
+ PVRSRV_ERROR eError;
+
+ if (psSysData == IMG_NULL) {
+ PVR_DPF((PVR_DBG_ERROR, "SysDeinitialise: Called with NULL SYS_DATA pointer. Probably called before."));
+ return PVRSRV_OK;
+ }
+
+ psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
+
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+ /* TODO: regulator and clk put. */
+ cpufreq_unregister_notifier(&cpufreq_limit_notifier,
+ CPUFREQ_POLICY_NOTIFIER);
+ cpufreq_update_policy(current_thread_info()->cpu);
+#endif
+
+#if defined(SYS_USING_INTERRUPTS)
+ if (psSysSpecData->ui32SysSpecificData & SYS_SPECIFIC_DATA_ENABLE_LISR)
+ {
+ eError = OSUninstallSystemLISR(psSysData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: OSUninstallSystemLISR failed"));
+ return eError;
+ }
+ }
+#endif
+
+ if (psSysSpecData->ui32SysSpecificData & SYS_SPECIFIC_DATA_ENABLE_MISR)
+ {
+ eError = OSUninstallMISR(psSysData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: OSUninstallMISR failed"));
+ return eError;
+ }
+ }
+
+ /* de-initialise all services managed devices */
+ eError = PVRSRVDeinitialiseDevice (gui32SGXDeviceID);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: failed to de-init the device"));
+ return eError;
+ }
+
+ eError = OSDeInitEnvData(gpsSysData->pvEnvSpecificData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: failed to de-init env structure"));
+ return eError;
+ }
+
+ SysDeinitialiseCommon(gpsSysData);
+
+ gpsSysData = IMG_NULL;
+
+ return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function SysGetDeviceMemoryMap
+
+ @Description returns a device address map for the specified device
+
+ @Input eDeviceType - device type
+ @Input ppvDeviceMap - void ptr to receive device specific info.
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_VOID **ppvDeviceMap)
+{
+
+ switch(eDeviceType)
+ {
+ case PVRSRV_DEVICE_TYPE_SGX:
+ {
+ /* just return a pointer to the structure */
+ *ppvDeviceMap = (IMG_VOID*)&gsSGXDeviceMap;
+
+ break;
+ }
+ default:
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysGetDeviceMemoryMap: unsupported device type"));
+ }
+ }
+ return PVRSRV_OK;
+}
+
+
+/*----------------------------------------------------------------------------
+<function>
+ FUNCTION: SysCpuPAddrToDevPAddr
+
+ PURPOSE: Compute a device physical address from a cpu physical
+ address. Relevant when
+
+ PARAMETERS: In: cpu_paddr - cpu physical address.
+ In: eDeviceType - device type required if DevPAddr
+ address spaces vary across devices
+ in the same system
+ RETURNS: device physical address.
+
+</function>
+------------------------------------------------------------------------------*/
+IMG_DEV_PHYADDR SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_CPU_PHYADDR CpuPAddr)
+{
+ IMG_DEV_PHYADDR DevPAddr;
+
+ PVR_UNREFERENCED_PARAMETER(eDeviceType);
+
+ /* Note: for no HW UMA system we assume DevP == CpuP */
+ DevPAddr.uiAddr = CpuPAddr.uiAddr;
+
+ return DevPAddr;
+}
+
+/*----------------------------------------------------------------------------
+<function>
+ FUNCTION: SysSysPAddrToCpuPAddr
+
+ PURPOSE: Compute a cpu physical address from a system physical
+ address.
+
+ PARAMETERS: In: sys_paddr - system physical address.
+ RETURNS: cpu physical address.
+
+</function>
+------------------------------------------------------------------------------*/
+IMG_CPU_PHYADDR SysSysPAddrToCpuPAddr (IMG_SYS_PHYADDR sys_paddr)
+{
+ IMG_CPU_PHYADDR cpu_paddr;
+
+ /* This would only be an inequality if the CPU's MMU did not point to sys address 0,
+ ie. multi CPU system */
+ cpu_paddr.uiAddr = sys_paddr.uiAddr;
+ return cpu_paddr;
+}
+
+/*----------------------------------------------------------------------------
+<function>
+ FUNCTION: SysCpuPAddrToSysPAddr
+
+ PURPOSE: Compute a system physical address from a cpu physical
+ address.
+
+ PARAMETERS: In: cpu_paddr - cpu physical address.
+ RETURNS: device physical address.
+
+</function>
+------------------------------------------------------------------------------*/
+IMG_SYS_PHYADDR SysCpuPAddrToSysPAddr (IMG_CPU_PHYADDR cpu_paddr)
+{
+ IMG_SYS_PHYADDR sys_paddr;
+
+ /* This would only be an inequality if the CPU's MMU did not point to sys address 0,
+ ie. multi CPU system */
+ sys_paddr.uiAddr = cpu_paddr.uiAddr;
+ return sys_paddr;
+}
+
+
+/*----------------------------------------------------------------------------
+<function>
+ FUNCTION: SysSysPAddrToDevPAddr
+
+ PURPOSE: Compute a device physical address from a system physical
+ address.
+
+ PARAMETERS: In: SysPAddr - system physical address.
+ In: eDeviceType - device type required if DevPAddr
+ address spaces vary across devices
+ in the same system
+
+ RETURNS: Device physical address.
+
+</function>
+-----------------------------------------------------------------------------*/
+IMG_DEV_PHYADDR SysSysPAddrToDevPAddr (PVRSRV_DEVICE_TYPE eDeviceType, IMG_SYS_PHYADDR SysPAddr)
+{
+ IMG_DEV_PHYADDR DevPAddr;
+
+ PVR_UNREFERENCED_PARAMETER(eDeviceType);
+
+ /* Note: for no HW UMA system we assume DevP == CpuP */
+ DevPAddr.uiAddr = SysPAddr.uiAddr;
+
+ return DevPAddr;
+}
+
+
+/*----------------------------------------------------------------------------
+<function>
+ FUNCTION: SysDevPAddrToSysPAddr
+
+ PURPOSE: Compute a device physical address from a system physical
+ address.
+
+ PARAMETERS: In: DevPAddr - device physical address.
+ In: eDeviceType - device type required if DevPAddr
+ address spaces vary across devices
+ in the same system
+
+ RETURNS: System physical address.
+
+</function>
+-----------------------------------------------------------------------------*/
+IMG_SYS_PHYADDR SysDevPAddrToSysPAddr (PVRSRV_DEVICE_TYPE eDeviceType, IMG_DEV_PHYADDR DevPAddr)
+{
+ IMG_SYS_PHYADDR SysPAddr;
+
+ PVR_UNREFERENCED_PARAMETER(eDeviceType);
+
+ /* Note: for no HW UMA system we assume DevP == SysP */
+ SysPAddr.uiAddr = DevPAddr.uiAddr;
+
+ return SysPAddr;
+}
+
+
+/*****************************************************************************
+ FUNCTION : SysRegisterExternalDevice
+
+ PURPOSE : Called when a 3rd party device registers with services
+
+ PARAMETERS: In: psDeviceNode - the new device node.
+
+ RETURNS : IMG_VOID
+*****************************************************************************/
+IMG_VOID SysRegisterExternalDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+}
+
+
+/*****************************************************************************
+ FUNCTION : SysRemoveExternalDevice
+
+ PURPOSE : Called when a 3rd party device unregisters from services
+
+ PARAMETERS: In: psDeviceNode - the device node being removed.
+
+ RETURNS : IMG_VOID
+*****************************************************************************/
+IMG_VOID SysRemoveExternalDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+}
+
+
+/*----------------------------------------------------------------------------
+<function>
+ FUNCTION: SysGetInterruptSource
+
+ PURPOSE: Returns System specific information about the device(s) that
+ generated the interrupt in the system
+
+ PARAMETERS: In: psSysData
+ In: psDeviceNode
+
+ RETURNS: System specific information indicating which device(s)
+ generated the interrupt
+
+</function>
+-----------------------------------------------------------------------------*/
+IMG_UINT32 SysGetInterruptSource(SYS_DATA* psSysData,
+ PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVR_UNREFERENCED_PARAMETER(psSysData);
+ PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+
+#if defined(NO_HARDWARE)
+ /* no interrupts in no_hw system just return all bits */
+ return 0xFFFFFFFF;
+#else
+ return 0x1;
+#endif
+}
+
+
+/*----------------------------------------------------------------------------
+<function>
+ FUNCTION: SysGetInterruptSource
+
+ PURPOSE: Clears specified system interrupts
+
+ PARAMETERS: psSysData
+ ui32ClearBits
+
+ RETURNS: IMG_VOID
+
+</function>
+-----------------------------------------------------------------------------*/
+IMG_VOID SysClearInterrupts(SYS_DATA* psSysData, IMG_UINT32 ui32ClearBits)
+{
+ PVR_UNREFERENCED_PARAMETER(psSysData);
+ PVR_UNREFERENCED_PARAMETER(ui32ClearBits);
+
+ /* no interrupts in no_hw system, nothing to do */
+}
+
+
+/*!
+******************************************************************************
+
+ @Function SysSystemPrePowerState
+
+ @Description Perform system-level processing required before a power transition
+
+ @Input eNewPowerState :
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
+PVRSRV_ERROR SysSystemPrePowerState(PVRSRV_SYS_POWER_STATE eNewPowerState)
+{
+ PVR_UNREFERENCED_PARAMETER(eNewPowerState);
+ return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function SysSystemPostPowerState
+
+ @Description Perform system-level processing required after a power transition
+
+ @Input eNewPowerState :
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
+PVRSRV_ERROR SysSystemPostPowerState(PVRSRV_SYS_POWER_STATE eNewPowerState)
+{
+ PVR_UNREFERENCED_PARAMETER(eNewPowerState);
+ return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function SysDevicePrePowerState
+
+ @Description Perform system-level processing required before a device power
+ transition
+
+ @Input ui32DeviceIndex :
+ @Input eNewPowerState :
+ @Input eCurrentPowerState :
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR SysDevicePrePowerState(IMG_UINT32 ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+ PVR_UNREFERENCED_PARAMETER(eCurrentPowerState);
+
+ if (ui32DeviceIndex != gui32SGXDeviceID)
+ {
+ return PVRSRV_OK;
+ }
+
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+ if (eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF)
+ {
+ PVRSRVSetDCState(DC_STATE_FLUSH_COMMANDS);
+ PVR_DPF((PVR_DBG_MESSAGE, "SysDevicePrePowerState: SGX Entering state D3"));
+ DisableSGXClocks();
+ PVRSRVSetDCState(DC_STATE_NO_FLUSH_COMMANDS);
+ }
+#else
+ PVR_UNREFERENCED_PARAMETER(eNewPowerState);
+#endif
+
+ return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function SysDevicePostPowerState
+
+ @Description Perform system-level processing required after a device power
+ transition
+
+ @Input ui32DeviceIndex :
+ @Input eNewPowerState :
+ @Input eCurrentPowerState :
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR SysDevicePostPowerState(IMG_UINT32 ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ PVR_UNREFERENCED_PARAMETER(eCurrentPowerState);
+
+ if (ui32DeviceIndex != gui32SGXDeviceID)
+ {
+ return eError;
+ }
+
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+ if (eNewPowerState == PVRSRV_DEV_POWER_STATE_ON)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "SysDevicePostPowerState: SGX Leaving state D3"));
+ eError = EnableSGXClocks();
+ }
+#else
+ PVR_UNREFERENCED_PARAMETER(eNewPowerState);
+#endif
+
+ return eError;
+}
+
+
+/*****************************************************************************
+ FUNCTION : SysOEMFunction
+
+ PURPOSE : marshalling function for custom OEM functions
+
+ PARAMETERS : ui32ID - function ID
+ pvIn - in data
+ pvOut - out data
+
+ RETURNS : PVRSRV_ERROR
+*****************************************************************************/
+PVRSRV_ERROR SysOEMFunction(IMG_UINT32 ui32ID,
+ IMG_VOID *pvIn,
+ IMG_UINT32 ulInSize,
+ IMG_VOID *pvOut,
+ IMG_UINT32 ulOutSize)
+{
+ PVR_UNREFERENCED_PARAMETER(ulInSize);
+ PVR_UNREFERENCED_PARAMETER(pvIn);
+
+ if ((ui32ID == OEM_GET_EXT_FUNCS) &&
+ (ulOutSize == sizeof(PVRSRV_DC_OEM_JTABLE)))
+ {
+ PVRSRV_DC_OEM_JTABLE *psOEMJTable = (PVRSRV_DC_OEM_JTABLE*)pvOut;
+ psOEMJTable->pfnOEMBridgeDispatch = &PVRSRV_BridgeDispatchKM;
+
+ return PVRSRV_OK;
+ }
+
+ return PVRSRV_ERROR_INVALID_PARAMS;
+}
+
+PVRSRV_ERROR SysPowerLockWrap(IMG_BOOL bTryLock)
+{
+ /* FIXME: This should not be empty */
+ PVR_UNREFERENCED_PARAMETER(bTryLock);
+ return PVRSRV_OK;
+}
+
+IMG_VOID SysPowerLockUnwrap(IMG_VOID)
+{
+ /* FIXME: This should not be empty */
+}
+
+/******************************************************************************
+ End of file (sysconfig.c)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/s5pc110/sysconfig.h b/drivers/gpu/pvr/s5pc110/sysconfig.h
new file mode 100644
index 0000000..af49316
--- /dev/null
+++ b/drivers/gpu/pvr/s5pc110/sysconfig.h
@@ -0,0 +1,59 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+*****************************************************************************/
+
+#if !defined(__SOCCONFIG_H__)
+#define __SOCCONFIG_H__
+
+#define VS_PRODUCT_NAME "s5pc110"
+
+#define SYS_SGX_USSE_COUNT (1)
+
+#define SGX_REG_SIZE 0x4000
+#define SGX_SP_SIZE (0x10000-SGX_REG_SIZE)
+
+/* Set PCI vendor ID, device ID to 0, the device is not a PCI device ! */
+#define SYS_SGX_DEV_VENDOR_ID 0
+#define SYS_SGX_DEV_DEVICE_ID 0
+
+#if defined(SGX_FEATURE_HOST_PORT)
+ /* FIXME: change these dummy values if host port is needed */
+ #define SYS_SGX_HP_SIZE 0x0
+ /* device virtual address of host port base */
+ #define SYS_SGX_HOSTPORT_BASE_DEVVADDR 0x0
+ #if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030)
+ /*
+ SYS_SGX_HOSTPORT_BASE_DEVVADDR + SYS_SGX_HOSTPORT_BRN23030_OFFSET
+ has to be an invalid SGX virtual address
+ */
+ #define SYS_SGX_HOSTPORT_BRN23030_OFFSET 0x0
+ #endif
+#endif
+
+/*****************************************************************************
+ * system specific data structures
+ *****************************************************************************/
+
+#endif /* __SOCCONFIG_H__ */
diff --git a/drivers/gpu/pvr/s5pc110/sysinfo.h b/drivers/gpu/pvr/s5pc110/sysinfo.h
new file mode 100644
index 0000000..6743401
--- /dev/null
+++ b/drivers/gpu/pvr/s5pc110/sysinfo.h
@@ -0,0 +1,68 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+*****************************************************************************/
+
+#if !defined(__SYSINFO_H__)
+#define __SYSINFO_H__
+
+/*!< System specific poll/timeout details */
+#define MAX_HW_TIME_US (500000)
+#define WAIT_TRY_COUNT (10000)
+
+/*!
+ List of device types present in this system
+*/
+typedef enum _SYS_DEVICE_TYPE_
+{
+ SYS_DEVICE_SGX = 0,
+
+ SYS_DEVICE_FORCE_I16 = 0x7fff
+
+} SYS_DEVICE_TYPE;
+
+/* SGX, DISPLAY (external), VIDEO Y (external), VIDEO UV (external) */
+#define SYS_DEVICE_COUNT 4
+
+
+/*
+ SGX Slave Port FIFO Size
+ (in units of `Bits per Write Bus Width')
+ Includes 5 slot safety factor for fullness register latency
+*/
+#define SGX_SP_FIFO_DWSIZE 123
+
+/*
+ Set the amount to reserve - currently taken as a 1/4 of the FIFO
+ (The value in DWORDs is 1/4 the value in BYTEs, rounded down)
+*/
+#define SGX_SP_FIFO_RESERVEBYTES (SGX_SP_FIFO_DWSIZE & -4)
+#define SGX_SP_FIFO_MAXALLOWEDBYTES (SGX_SP_FIFO_DWSIZE * 4) - SGX_SP_FIFO_RESERVEBYTES
+
+#define SGX_EXTRACT_FIFO_COUNT(x) (((x) & SGX_INT_TA_FREEVCOUNT_MASK) >> SGX_INT_TA_FREEVCOUNT_SHIFT)
+/*!<
+ Macro to extract FIFO space from HW register value
+*/
+
+#endif /* __SYSINFO_H__ */
diff --git a/drivers/gpu/pvr/s5pc110/sysutils.c b/drivers/gpu/pvr/s5pc110/sysutils.c
new file mode 100644
index 0000000..2adff3f
--- /dev/null
+++ b/drivers/gpu/pvr/s5pc110/sysutils.c
@@ -0,0 +1,36 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+*****************************************************************************/
+
+#include "services_headers.h"
+#include "sysinfo.h"
+
+
+
+/* SYSTEM SPECIFIC FUNCTIONS */
+
+
+
+
diff --git a/drivers/gpu/pvr/services.h b/drivers/gpu/pvr/services.h
new file mode 100644
index 0000000..1619aef
--- /dev/null
+++ b/drivers/gpu/pvr/services.h
@@ -0,0 +1,1322 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __SERVICES_H__
+#define __SERVICES_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "img_defs.h"
+#include "servicesext.h"
+#include "pdumpdefs.h"
+
+
+#define PVRSRV_4K_PAGE_SIZE 4096UL
+
+#define PVRSRV_MAX_CMD_SIZE 1024
+
+#define PVRSRV_MAX_DEVICES 16
+
+#define EVENTOBJNAME_MAXLENGTH (50)
+
+#define PVRSRV_MEM_READ (1U<<0)
+#define PVRSRV_MEM_WRITE (1U<<1)
+#define PVRSRV_MEM_CACHE_CONSISTENT (1U<<2)
+#define PVRSRV_MEM_NO_SYNCOBJ (1U<<3)
+#define PVRSRV_MEM_INTERLEAVED (1U<<4)
+#define PVRSRV_MEM_DUMMY (1U<<5)
+#define PVRSRV_MEM_EDM_PROTECT (1U<<6)
+#define PVRSRV_MEM_ZERO (1U<<7)
+#define PVRSRV_MEM_USER_SUPPLIED_DEVVADDR (1U<<8)
+#define PVRSRV_MEM_RAM_BACKED_ALLOCATION (1U<<9)
+#define PVRSRV_MEM_NO_RESMAN (1U<<10)
+#define PVRSRV_MEM_EXPORTED (1U<<11)
+
+
+#define PVRSRV_HAP_CACHED (1U<<12)
+#define PVRSRV_HAP_UNCACHED (1U<<13)
+#define PVRSRV_HAP_WRITECOMBINE (1U<<14)
+#define PVRSRV_HAP_CACHETYPE_MASK (PVRSRV_HAP_CACHED|PVRSRV_HAP_UNCACHED|PVRSRV_HAP_WRITECOMBINE)
+#define PVRSRV_HAP_KERNEL_ONLY (1U<<15)
+#define PVRSRV_HAP_SINGLE_PROCESS (1U<<16)
+#define PVRSRV_HAP_MULTI_PROCESS (1U<<17)
+#define PVRSRV_HAP_FROM_EXISTING_PROCESS (1U<<18)
+#define PVRSRV_HAP_NO_CPU_VIRTUAL (1U<<19)
+#define PVRSRV_HAP_MAPTYPE_MASK (PVRSRV_HAP_KERNEL_ONLY \
+ |PVRSRV_HAP_SINGLE_PROCESS \
+ |PVRSRV_HAP_MULTI_PROCESS \
+ |PVRSRV_HAP_FROM_EXISTING_PROCESS \
+ |PVRSRV_HAP_NO_CPU_VIRTUAL)
+
+#define PVRSRV_MEM_CACHED PVRSRV_HAP_CACHED
+#define PVRSRV_MEM_UNCACHED PVRSRV_HAP_UNCACHED
+#define PVRSRV_MEM_WRITECOMBINE PVRSRV_HAP_WRITECOMBINE
+
+#define PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT (24)
+
+#define PVRSRV_MAP_NOUSERVIRTUAL (1UL<<27)
+#define PVRSRV_MEM_XPROC (1U<<28)
+#define PVRSRV_MEM_ION (1U<<29)
+#define PVRSRV_MEM_ALLOCATENONCACHEDMEM (1UL<<30)
+
+#define PVRSRV_NO_CONTEXT_LOSS 0
+#define PVRSRV_SEVERE_LOSS_OF_CONTEXT 1
+#define PVRSRV_PRE_STATE_CHANGE_MASK 0x80
+
+
+#define PVRSRV_DEFAULT_DEV_COOKIE (1)
+
+
+#define PVRSRV_MISC_INFO_TIMER_PRESENT (1U<<0)
+#define PVRSRV_MISC_INFO_CLOCKGATE_PRESENT (1U<<1)
+#define PVRSRV_MISC_INFO_MEMSTATS_PRESENT (1U<<2)
+#define PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT (1U<<3)
+#define PVRSRV_MISC_INFO_DDKVERSION_PRESENT (1U<<4)
+#define PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT (1U<<5)
+#define PVRSRV_MISC_INFO_FREEMEM_PRESENT (1U<<6)
+#define PVRSRV_MISC_INFO_GET_REF_COUNT_PRESENT (1U<<7)
+
+#define PVRSRV_MISC_INFO_RESET_PRESENT (1U<<31)
+
+#define PVRSRV_PDUMP_MAX_FILENAME_SIZE 20
+#define PVRSRV_PDUMP_MAX_COMMENT_SIZE 200
+
+
+#define PVRSRV_CHANGEDEVMEM_ATTRIBS_CACHECOHERENT 0x00000001
+
+#define PVRSRV_MAPEXTMEMORY_FLAGS_ALTERNATEVA 0x00000001
+#define PVRSRV_MAPEXTMEMORY_FLAGS_PHYSCONTIG 0x00000002
+
+#define PVRSRV_MODIFYSYNCOPS_FLAGS_WO_INC 0x00000001
+#define PVRSRV_MODIFYSYNCOPS_FLAGS_RO_INC 0x00000002
+
+#define SRV_FLAGS_PERSIST 0x1
+#define SRV_FLAGS_PDUMP_ACTIVE 0x2
+
+#define PVRSRV_PDUMP_FLAGS_CONTINUOUS 0x1
+
+
+typedef enum _PVRSRV_DEVICE_TYPE_
+{
+ PVRSRV_DEVICE_TYPE_UNKNOWN = 0 ,
+ PVRSRV_DEVICE_TYPE_MBX1 = 1 ,
+ PVRSRV_DEVICE_TYPE_MBX1_LITE = 2 ,
+
+ PVRSRV_DEVICE_TYPE_M24VA = 3,
+ PVRSRV_DEVICE_TYPE_MVDA2 = 4,
+ PVRSRV_DEVICE_TYPE_MVED1 = 5,
+ PVRSRV_DEVICE_TYPE_MSVDX = 6,
+
+ PVRSRV_DEVICE_TYPE_SGX = 7,
+
+ PVRSRV_DEVICE_TYPE_VGX = 8,
+
+
+ PVRSRV_DEVICE_TYPE_EXT = 9,
+
+ PVRSRV_DEVICE_TYPE_LAST = 9,
+
+ PVRSRV_DEVICE_TYPE_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_DEVICE_TYPE;
+
+#define HEAP_ID( _dev_ , _dev_heap_idx_ ) ( ((_dev_)<<24) | ((_dev_heap_idx_)&((1<<24)-1)) )
+#define HEAP_IDX( _heap_id_ ) ( (_heap_id_)&((1<<24) - 1 ) )
+#define HEAP_DEV( _heap_id_ ) ( (_heap_id_)>>24 )
+
+#define PVRSRV_UNDEFINED_HEAP_ID (~0LU)
+
+typedef enum
+{
+ IMG_EGL = 0x00000001,
+ IMG_OPENGLES1 = 0x00000002,
+ IMG_OPENGLES2 = 0x00000003,
+ IMG_D3DM = 0x00000004,
+ IMG_SRV_UM = 0x00000005,
+ IMG_OPENVG = 0x00000006,
+ IMG_SRVCLIENT = 0x00000007,
+ IMG_VISTAKMD = 0x00000008,
+ IMG_VISTA3DNODE = 0x00000009,
+ IMG_VISTAMVIDEONODE = 0x0000000A,
+ IMG_VISTAVPBNODE = 0x0000000B,
+ IMG_OPENGL = 0x0000000C,
+ IMG_D3D = 0x0000000D,
+#if defined(SUPPORT_GRAPHICS_HAL) || defined(SUPPORT_COMPOSER_HAL)
+ IMG_ANDROID_HAL = 0x0000000E,
+#endif
+#if defined(SUPPORT_OPENCL)
+ IMG_OPENCL = 0x0000000F,
+#endif
+
+} IMG_MODULE_ID;
+
+
+#define APPHINT_MAX_STRING_SIZE 256
+
+typedef enum
+{
+ IMG_STRING_TYPE = 1,
+ IMG_FLOAT_TYPE ,
+ IMG_UINT_TYPE ,
+ IMG_INT_TYPE ,
+ IMG_FLAG_TYPE
+}IMG_DATA_TYPE;
+
+
+typedef struct _PVRSRV_DEV_DATA_ *PPVRSRV_DEV_DATA;
+
+typedef struct _PVRSRV_DEVICE_IDENTIFIER_
+{
+ PVRSRV_DEVICE_TYPE eDeviceType;
+ PVRSRV_DEVICE_CLASS eDeviceClass;
+ IMG_UINT32 ui32DeviceIndex;
+ IMG_CHAR *pszPDumpDevName;
+ IMG_CHAR *pszPDumpRegName;
+
+} PVRSRV_DEVICE_IDENTIFIER;
+
+
+typedef struct _PVRSRV_CLIENT_DEV_DATA_
+{
+ IMG_UINT32 ui32NumDevices;
+ PVRSRV_DEVICE_IDENTIFIER asDevID[PVRSRV_MAX_DEVICES];
+ PVRSRV_ERROR (*apfnDevConnect[PVRSRV_MAX_DEVICES])(PPVRSRV_DEV_DATA);
+ PVRSRV_ERROR (*apfnDumpTrace[PVRSRV_MAX_DEVICES])(PPVRSRV_DEV_DATA);
+
+} PVRSRV_CLIENT_DEV_DATA;
+
+
+typedef struct _PVRSRV_CONNECTION_
+{
+ IMG_HANDLE hServices;
+ IMG_UINT32 ui32ProcessID;
+ PVRSRV_CLIENT_DEV_DATA sClientDevData;
+ IMG_UINT32 ui32SrvFlags;
+}PVRSRV_CONNECTION;
+
+
+typedef struct _PVRSRV_DEV_DATA_
+{
+ IMG_CONST PVRSRV_CONNECTION *psConnection;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+
+} PVRSRV_DEV_DATA;
+
+typedef struct _PVRSRV_MEMUPDATE_
+{
+ IMG_UINT32 ui32UpdateAddr;
+ IMG_UINT32 ui32UpdateVal;
+} PVRSRV_MEMUPDATE;
+
+typedef struct _PVRSRV_HWREG_
+{
+ IMG_UINT32 ui32RegAddr;
+ IMG_UINT32 ui32RegVal;
+} PVRSRV_HWREG;
+
+typedef struct _PVRSRV_MEMBLK_
+{
+ IMG_DEV_VIRTADDR sDevVirtAddr;
+ IMG_HANDLE hOSMemHandle;
+ IMG_HANDLE hOSWrapMem;
+ IMG_HANDLE hBuffer;
+ IMG_HANDLE hResItem;
+ IMG_SYS_PHYADDR *psIntSysPAddr;
+
+} PVRSRV_MEMBLK;
+
+typedef struct _PVRSRV_KERNEL_MEM_INFO_ *PPVRSRV_KERNEL_MEM_INFO;
+
+typedef struct _PVRSRV_CLIENT_MEM_INFO_
+{
+
+ IMG_PVOID pvLinAddr;
+
+
+ IMG_PVOID pvLinAddrKM;
+
+
+ IMG_DEV_VIRTADDR sDevVAddr;
+
+
+
+
+
+
+ IMG_CPU_PHYADDR sCpuPAddr;
+
+
+ IMG_UINT32 ui32Flags;
+
+
+
+
+ IMG_UINT32 ui32ClientFlags;
+
+
+ IMG_SIZE_T uAllocSize;
+
+
+
+ struct _PVRSRV_CLIENT_SYNC_INFO_ *psClientSyncInfo;
+
+#if defined (SUPPORT_SID_INTERFACE)
+
+ IMG_SID hMappingInfo;
+
+
+ IMG_SID hKernelMemInfo;
+
+
+ IMG_SID hResItem;
+#else
+
+ IMG_HANDLE hMappingInfo;
+
+
+ IMG_HANDLE hKernelMemInfo;
+
+
+ IMG_HANDLE hResItem;
+#endif
+
+#if defined(SUPPORT_MEMINFO_IDS)
+ #if !defined(USE_CODE)
+
+ IMG_UINT64 ui64Stamp;
+ #else
+ IMG_UINT32 dummy1;
+ IMG_UINT32 dummy2;
+ #endif
+#endif
+
+
+
+
+ struct _PVRSRV_CLIENT_MEM_INFO_ *psNext;
+
+} PVRSRV_CLIENT_MEM_INFO, *PPVRSRV_CLIENT_MEM_INFO;
+
+
+#define PVRSRV_MAX_CLIENT_HEAPS (32)
+typedef struct _PVRSRV_HEAP_INFO_
+{
+ IMG_UINT32 ui32HeapID;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevMemHeap;
+#else
+ IMG_HANDLE hDevMemHeap;
+#endif
+ IMG_DEV_VIRTADDR sDevVAddrBase;
+ IMG_UINT32 ui32HeapByteSize;
+ IMG_UINT32 ui32Attribs;
+ IMG_UINT32 ui32XTileStride;
+}PVRSRV_HEAP_INFO;
+
+
+
+
+typedef struct _PVRSRV_EVENTOBJECT_
+{
+
+ IMG_CHAR szName[EVENTOBJNAME_MAXLENGTH];
+
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hOSEventKM;
+#else
+ IMG_HANDLE hOSEventKM;
+#endif
+
+} PVRSRV_EVENTOBJECT;
+
+typedef enum
+{
+ PVRSRV_MISC_INFO_CPUCACHEOP_NONE = 0,
+ PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN,
+ PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH
+} PVRSRV_MISC_INFO_CPUCACHEOP_TYPE;
+
+typedef struct _PVRSRV_MISC_INFO_
+{
+ IMG_UINT32 ui32StateRequest;
+ IMG_UINT32 ui32StatePresent;
+
+
+ IMG_VOID *pvSOCTimerRegisterKM;
+ IMG_VOID *pvSOCTimerRegisterUM;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hSOCTimerRegisterOSMemHandle;
+ IMG_SID hSOCTimerRegisterMappingInfo;
+#else
+ IMG_HANDLE hSOCTimerRegisterOSMemHandle;
+ IMG_HANDLE hSOCTimerRegisterMappingInfo;
+#endif
+
+
+ IMG_VOID *pvSOCClockGateRegs;
+ IMG_UINT32 ui32SOCClockGateRegsSize;
+
+
+ IMG_CHAR *pszMemoryStr;
+ IMG_UINT32 ui32MemoryStrLen;
+
+
+ PVRSRV_EVENTOBJECT sGlobalEventObject;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_EVENTSID hOSGlobalEvent;
+#else
+ IMG_HANDLE hOSGlobalEvent;
+#endif
+
+
+ IMG_UINT32 aui32DDKVersion[4];
+
+
+ struct
+ {
+
+ IMG_BOOL bDeferOp;
+
+
+ PVRSRV_MISC_INFO_CPUCACHEOP_TYPE eCacheOpType;
+
+
+#if !defined (SUPPORT_SID_INTERFACE)
+ union
+ {
+
+ PVRSRV_CLIENT_MEM_INFO *psClientMemInfo;
+
+
+ struct _PVRSRV_KERNEL_MEM_INFO_ *psKernelMemInfo;
+ } u;
+#endif
+
+
+ IMG_VOID *pvBaseVAddr;
+
+
+ IMG_UINT32 ui32Length;
+ } sCacheOpCtl;
+
+
+ struct
+ {
+
+#if !defined(SUPPORT_SID_INTERFACE)
+ union
+ {
+
+ PVRSRV_CLIENT_MEM_INFO *psClientMemInfo;
+
+
+ struct _PVRSRV_KERNEL_MEM_INFO_ *psKernelMemInfo;
+ } u;
+#endif
+
+
+ IMG_UINT32 ui32RefCount;
+ } sGetRefCountCtl;
+} PVRSRV_MISC_INFO;
+
+typedef struct _PVRSRV_SYNC_TOKEN_
+{
+
+
+ struct
+ {
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelSyncInfo;
+#else
+ IMG_HANDLE hKernelSyncInfo;
+#endif
+ IMG_UINT32 ui32ReadOpsPendingSnapshot;
+ IMG_UINT32 ui32WriteOpsPendingSnapshot;
+ IMG_UINT32 ui32ReadOps2PendingSnapshot;
+ } sPrivate;
+} PVRSRV_SYNC_TOKEN;
+
+
+typedef enum _PVRSRV_CLIENT_EVENT_
+{
+ PVRSRV_CLIENT_EVENT_HWTIMEOUT = 0,
+} PVRSRV_CLIENT_EVENT;
+
+typedef IMG_VOID (*PFN_QUEUE_COMMAND_COMPLETE)(IMG_HANDLE hCallbackData);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVClientEvent(IMG_CONST PVRSRV_CLIENT_EVENT eEvent,
+ PVRSRV_DEV_DATA *psDevData,
+ IMG_PVOID pvData);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVConnect(PVRSRV_CONNECTION **ppsConnection, IMG_UINT32 ui32SrvFlags);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDisconnect(IMG_CONST PVRSRV_CONNECTION *psConnection);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDevices(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_UINT32 *puiNumDevices,
+ PVRSRV_DEVICE_IDENTIFIER *puiDevIDs);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAcquireDeviceData(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_UINT32 uiDevIndex,
+ PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_DEVICE_TYPE eDeviceType);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfo (IMG_CONST PVRSRV_CONNECTION *psConnection, PVRSRV_MISC_INFO *psMiscInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVReleaseMiscInfo (IMG_CONST PVRSRV_CONNECTION *psConnection, PVRSRV_MISC_INFO *psMiscInfo);
+
+#if 1
+IMG_IMPORT
+IMG_UINT32 ReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset);
+
+IMG_IMPORT
+IMG_VOID WriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value);
+
+IMG_IMPORT IMG_VOID WriteHWRegs(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Count, PVRSRV_HWREG *psHWRegs);
+#endif
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVPollForValue ( const PVRSRV_CONNECTION *psConnection,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hOSEvent,
+#else
+ IMG_HANDLE hOSEvent,
+#endif
+ volatile IMG_UINT32 *pui32LinMemAddr,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ IMG_UINT32 ui32Waitus,
+ IMG_UINT32 ui32Tries);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateDeviceMemContext(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID *phDevMemContext,
+#else
+ IMG_HANDLE *phDevMemContext,
+#endif
+ IMG_UINT32 *pui32SharedHeapCount,
+ PVRSRV_HEAP_INFO *psHeapInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyDeviceMemContext(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevMemContext
+#else
+ IMG_HANDLE hDevMemContext
+#endif
+ );
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapInfo(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevMemContext,
+#else
+ IMG_HANDLE hDevMemContext,
+#endif
+ IMG_UINT32 *pui32SharedHeapCount,
+ PVRSRV_HEAP_INFO *psHeapInfo);
+
+#if defined(PVRSRV_LOG_MEMORY_ALLOCS)
+ #define PVRSRVAllocDeviceMem_log(psDevData, hDevMemHeap, ui32Attribs, ui32Size, ui32Alignment, ppsMemInfo, logStr) \
+ (PVR_TRACE(("PVRSRVAllocDeviceMem(" #psDevData "," #hDevMemHeap "," #ui32Attribs "," #ui32Size "," #ui32Alignment "," #ppsMemInfo ")" \
+ ": " logStr " (size = 0x%lx)", ui32Size)), \
+ PVRSRVAllocDeviceMem(psDevData, hDevMemHeap, ui32Attribs, ui32Size, ui32Alignment, ppsMemInfo))
+#else
+ #define PVRSRVAllocDeviceMem_log(psDevData, hDevMemHeap, ui32Attribs, ui32Size, ui32Alignment, ppsMemInfo, logStr) \
+ PVRSRVAllocDeviceMem(psDevData, hDevMemHeap, ui32Attribs, ui32Size, ui32Alignment, ppsMemInfo)
+#endif
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocDeviceMem2(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevMemHeap,
+#else
+ IMG_HANDLE hDevMemHeap,
+#endif
+ IMG_UINT32 ui32Attribs,
+ IMG_SIZE_T ui32Size,
+ IMG_SIZE_T ui32Alignment,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
+ PVRSRV_CLIENT_MEM_INFO **ppsMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocDeviceMem(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevMemHeap,
+#else
+ IMG_HANDLE hDevMemHeap,
+#endif
+ IMG_UINT32 ui32Attribs,
+ IMG_SIZE_T ui32Size,
+ IMG_SIZE_T ui32Alignment,
+ PVRSRV_CLIENT_MEM_INFO **ppsMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeDeviceMem(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_CLIENT_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVExportDeviceMem(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_CLIENT_MEM_INFO *psMemInfo,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID *phMemInfo
+#else
+ IMG_HANDLE *phMemInfo
+#endif
+ );
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVReserveDeviceVirtualMem(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevMemHeap,
+#else
+ IMG_HANDLE hDevMemHeap,
+#endif
+ IMG_DEV_VIRTADDR *psDevVAddr,
+ IMG_SIZE_T ui32Size,
+ IMG_SIZE_T ui32Alignment,
+ PVRSRV_CLIENT_MEM_INFO **ppsMemInfo);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeDeviceVirtualMem(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_CLIENT_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelMemInfo,
+ IMG_SID hDstDevMemHeap,
+#else
+ IMG_HANDLE hKernelMemInfo,
+ IMG_HANDLE hDstDevMemHeap,
+#endif
+ PVRSRV_CLIENT_MEM_INFO **ppsDstMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_CLIENT_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapExtMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_CLIENT_MEM_INFO *psMemInfo,
+ IMG_SYS_PHYADDR *psSysPAddr,
+ IMG_UINT32 ui32Flags);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapExtMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_CLIENT_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Flags);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVWrapExtMemory(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevMemContext,
+#else
+ IMG_HANDLE hDevMemContext,
+#endif
+ IMG_SIZE_T ui32ByteSize,
+ IMG_SIZE_T ui32PageOffset,
+ IMG_BOOL bPhysContig,
+ IMG_SYS_PHYADDR *psSysPAddr,
+ IMG_VOID *pvLinAddr,
+ IMG_UINT32 ui32Flags,
+ PVRSRV_CLIENT_MEM_INFO **ppsMemInfo);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnwrapExtMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_CLIENT_MEM_INFO *psMemInfo);
+
+PVRSRV_ERROR PVRSRVChangeDeviceMemoryAttributes(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_CLIENT_MEM_INFO *psClientMemInfo,
+ IMG_UINT32 ui32Attribs);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceClassMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevMemContext,
+ IMG_SID hDeviceClassBuffer,
+#else
+ IMG_HANDLE hDevMemContext,
+ IMG_HANDLE hDeviceClassBuffer,
+#endif
+ PVRSRV_CLIENT_MEM_INFO **ppsMemInfo);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceClassMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_CLIENT_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapPhysToUserSpace(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_SYS_PHYADDR sSysPhysAddr,
+ IMG_UINT32 uiSizeInBytes,
+ IMG_PVOID *ppvUserAddr,
+ IMG_UINT32 *puiActualSize,
+ IMG_PVOID *ppvProcess);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapPhysToUserSpace(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_PVOID pvUserAddr,
+ IMG_PVOID pvProcess);
+
+#if defined(LINUX)
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVExportDeviceMem2(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_CLIENT_MEM_INFO *psMemInfo,
+ IMG_INT *iFd);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceMemory2(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_INT iFd,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDstDevMemHeap,
+#else
+ IMG_HANDLE hDstDevMemHeap,
+#endif
+ PVRSRV_CLIENT_MEM_INFO **ppsDstMemInfo);
+#endif
+
+#if defined(SUPPORT_ION)
+PVRSRV_ERROR PVRSRVMapIonHandle(const PVRSRV_DEV_DATA *psDevData,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevMemContext,
+#else
+ IMG_HANDLE hDevMemContext,
+#endif
+ IMG_INT32 uiFD,
+ IMG_UINT32 uiSize,
+ IMG_UINT32 ui32Attribs,
+ PVRSRV_CLIENT_MEM_INFO **ppsMemInfo);
+
+PVRSRV_ERROR PVRSRVUnmapIonHandle(const PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_CLIENT_MEM_INFO *psMemInfo);
+#endif
+
+typedef enum _PVRSRV_SYNCVAL_MODE_
+{
+ PVRSRV_SYNCVAL_READ = IMG_TRUE,
+ PVRSRV_SYNCVAL_WRITE = IMG_FALSE,
+
+} PVRSRV_SYNCVAL_MODE, *PPVRSRV_SYNCVAL_MODE;
+
+typedef IMG_UINT32 PVRSRV_SYNCVAL;
+
+IMG_IMPORT PVRSRV_ERROR PVRSRVWaitForOpsComplete(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+ PVRSRV_SYNCVAL_MODE eMode, PVRSRV_SYNCVAL OpRequired);
+
+IMG_IMPORT PVRSRV_ERROR PVRSRVWaitForAllOpsComplete(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+ PVRSRV_SYNCVAL_MODE eMode);
+
+IMG_IMPORT IMG_BOOL PVRSRVTestOpsComplete(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+ PVRSRV_SYNCVAL_MODE eMode, PVRSRV_SYNCVAL OpRequired);
+
+IMG_IMPORT IMG_BOOL PVRSRVTestAllOpsComplete(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+ PVRSRV_SYNCVAL_MODE eMode);
+
+IMG_IMPORT IMG_BOOL PVRSRVTestOpsNotComplete(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+ PVRSRV_SYNCVAL_MODE eMode, PVRSRV_SYNCVAL OpRequired);
+
+IMG_IMPORT IMG_BOOL PVRSRVTestAllOpsNotComplete(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+ PVRSRV_SYNCVAL_MODE eMode);
+
+IMG_IMPORT PVRSRV_SYNCVAL PVRSRVGetPendingOpSyncVal(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+ PVRSRV_SYNCVAL_MODE eMode);
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDeviceClass(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ PVRSRV_DEVICE_CLASS DeviceClass,
+ IMG_UINT32 *pui32DevCount,
+ IMG_UINT32 *pui32DevID);
+
+IMG_IMPORT
+IMG_HANDLE IMG_CALLCONV PVRSRVOpenDCDevice(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_UINT32 ui32DeviceID);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCloseDCDevice(IMG_CONST PVRSRV_CONNECTION *psConnection, IMG_HANDLE hDevice);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumDCFormats (IMG_HANDLE hDevice,
+ IMG_UINT32 *pui32Count,
+ DISPLAY_FORMAT *psFormat);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumDCDims (IMG_HANDLE hDevice,
+ IMG_UINT32 *pui32Count,
+ DISPLAY_FORMAT *psFormat,
+ DISPLAY_DIMS *psDims);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDCSystemBuffer(IMG_HANDLE hDevice,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID *phBuffer
+#else
+ IMG_HANDLE *phBuffer
+#endif
+ );
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDCInfo(IMG_HANDLE hDevice,
+ DISPLAY_INFO* psDisplayInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateDCSwapChain (IMG_HANDLE hDevice,
+ IMG_UINT32 ui32Flags,
+ DISPLAY_SURF_ATTRIBUTES *psDstSurfAttrib,
+ DISPLAY_SURF_ATTRIBUTES *psSrcSurfAttrib,
+ IMG_UINT32 ui32BufferCount,
+ IMG_UINT32 ui32OEMFlags,
+ IMG_UINT32 *pui32SwapChainID,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID *phSwapChain
+#else
+ IMG_HANDLE *phSwapChain
+#endif
+ );
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyDCSwapChain (IMG_HANDLE hDevice,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hSwapChain
+#else
+ IMG_HANDLE hSwapChain
+#endif
+ );
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSetDCDstRect (IMG_HANDLE hDevice,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hSwapChain,
+#else
+ IMG_HANDLE hSwapChain,
+#endif
+ IMG_RECT *psDstRect);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSetDCSrcRect (IMG_HANDLE hDevice,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hSwapChain,
+#else
+ IMG_HANDLE hSwapChain,
+#endif
+ IMG_RECT *psSrcRect);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSetDCDstColourKey (IMG_HANDLE hDevice,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hSwapChain,
+#else
+ IMG_HANDLE hSwapChain,
+#endif
+ IMG_UINT32 ui32CKColour);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSetDCSrcColourKey (IMG_HANDLE hDevice,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hSwapChain,
+#else
+ IMG_HANDLE hSwapChain,
+#endif
+ IMG_UINT32 ui32CKColour);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDCBuffers(IMG_HANDLE hDevice,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hSwapChain,
+ IMG_SID *phBuffer
+#else
+ IMG_HANDLE hSwapChain,
+ IMG_HANDLE *phBuffer
+#endif
+ );
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDCBuffers2(IMG_HANDLE hDevice,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hSwapChain,
+ IMG_SID *phBuffer,
+#else
+ IMG_HANDLE hSwapChain,
+ IMG_HANDLE *phBuffer,
+#endif
+ IMG_SYS_PHYADDR *psPhyAddr);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSwapToDCBuffer (IMG_HANDLE hDevice,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hBuffer,
+#else
+ IMG_HANDLE hBuffer,
+#endif
+ IMG_UINT32 ui32ClipRectCount,
+ IMG_RECT *psClipRect,
+ IMG_UINT32 ui32SwapInterval,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hPrivateTag
+#else
+ IMG_HANDLE hPrivateTag
+#endif
+ );
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSwapToDCBuffer2 (IMG_HANDLE hDevice,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hBuffer,
+#else
+ IMG_HANDLE hBuffer,
+#endif
+ IMG_UINT32 ui32SwapInterval,
+ PVRSRV_CLIENT_MEM_INFO **ppsMemInfos,
+ IMG_UINT32 ui32NumMemInfos,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSwapToDCSystem (IMG_HANDLE hDevice,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hSwapChain
+#else
+ IMG_HANDLE hSwapChain
+#endif
+ );
+
+IMG_IMPORT
+IMG_HANDLE IMG_CALLCONV PVRSRVOpenBCDevice(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_UINT32 ui32DeviceID);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCloseBCDevice(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_HANDLE hDevice);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetBCBufferInfo(IMG_HANDLE hDevice,
+ BUFFER_INFO *psBuffer);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetBCBuffer(IMG_HANDLE hDevice,
+ IMG_UINT32 ui32BufferIndex,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID *phBuffer
+#else
+ IMG_HANDLE *phBuffer
+#endif
+ );
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpInit(IMG_CONST PVRSRV_CONNECTION *psConnection);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpStartInitPhase(IMG_CONST PVRSRV_CONNECTION *psConnection);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpStopInitPhase(IMG_CONST PVRSRV_CONNECTION *psConnection);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpMemPol(IMG_CONST PVRSRV_CONNECTION *psConnection,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelMemInfo,
+#else
+ PVRSRV_CLIENT_MEM_INFO *psMemInfo,
+#endif
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ PDUMP_POLL_OPERATOR eOperator,
+ IMG_UINT32 ui32Flags);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpSyncPol(IMG_CONST PVRSRV_CONNECTION *psConnection,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelSyncInfo,
+#else
+ PVRSRV_CLIENT_SYNC_INFO *psClientSyncInfo,
+#endif
+ IMG_BOOL bIsRead,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpSyncPol2(IMG_CONST PVRSRV_CONNECTION *psConnection,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelSyncInfo,
+#else
+ PVRSRV_CLIENT_SYNC_INFO *psClientSyncInfo,
+#endif
+ IMG_BOOL bIsRead);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpMem(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_PVOID pvAltLinAddr,
+ PVRSRV_CLIENT_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32Flags);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpSync(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_PVOID pvAltLinAddr,
+ PVRSRV_CLIENT_SYNC_INFO *psClientSyncInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Bytes);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpReg(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_CHAR *pszRegRegion,
+ IMG_UINT32 ui32RegAddr,
+ IMG_UINT32 ui32RegValue,
+ IMG_UINT32 ui32Flags);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpRegPolWithFlags(const PVRSRV_DEV_DATA *psDevData,
+ IMG_CHAR *pszRegRegion,
+ IMG_UINT32 ui32RegAddr,
+ IMG_UINT32 ui32RegValue,
+ IMG_UINT32 ui32Mask,
+ IMG_UINT32 ui32Flags);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpRegPol(const PVRSRV_DEV_DATA *psDevData,
+ IMG_CHAR *pszRegRegion,
+ IMG_UINT32 ui32RegAddr,
+ IMG_UINT32 ui32RegValue,
+ IMG_UINT32 ui32Mask);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpPDReg(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_UINT32 ui32RegAddr,
+ IMG_UINT32 ui32RegValue);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpPDDevPAddr(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ PVRSRV_CLIENT_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_DEV_PHYADDR sPDDevPAddr);
+
+#if !defined(USE_CODE)
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpMemPages(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelMemInfo,
+#else
+ IMG_HANDLE hKernelMemInfo,
+#endif
+ IMG_DEV_PHYADDR *pPages,
+ IMG_UINT32 ui32NumPages,
+ IMG_DEV_VIRTADDR sDevVAddr,
+ IMG_UINT32 ui32Start,
+ IMG_UINT32 ui32Length,
+ IMG_UINT32 ui32Flags);
+#endif
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpSetFrame(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_UINT32 ui32Frame);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpComment(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_CONST IMG_CHAR *pszComment,
+ IMG_BOOL bContinuous);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpCommentf(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_BOOL bContinuous,
+ IMG_CONST IMG_CHAR *pszFormat, ...)
+#if !defined(USE_CODE)
+ IMG_FORMAT_PRINTF(3, 4)
+#endif
+;
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpCommentWithFlagsf(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_UINT32 ui32Flags,
+ IMG_CONST IMG_CHAR *pszFormat, ...)
+#if !defined(USE_CODE)
+ IMG_FORMAT_PRINTF(3, 4)
+#endif
+;
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpDriverInfo(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_CHAR *pszString,
+ IMG_BOOL bContinuous);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpIsCapturing(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_BOOL *pbIsCapturing);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpBitmap(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ IMG_UINT32 ui32Width,
+ IMG_UINT32 ui32Height,
+ IMG_UINT32 ui32StrideInBytes,
+ IMG_DEV_VIRTADDR sDevBaseAddr,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevMemContext,
+#else
+ IMG_HANDLE hDevMemContext,
+#endif
+ IMG_UINT32 ui32Size,
+ PDUMP_PIXEL_FORMAT ePixelFormat,
+ PDUMP_MEM_FORMAT eMemFormat,
+ IMG_UINT32 ui32PDumpFlags);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpRegRead(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_CONST IMG_CHAR *pszRegRegion,
+ IMG_CONST IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ IMG_UINT32 ui32Address,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32PDumpFlags);
+
+
+IMG_IMPORT
+IMG_BOOL IMG_CALLCONV PVRSRVPDumpIsCapturingTest(IMG_CONST PVRSRV_CONNECTION *psConnection);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpCycleCountRegRead(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_UINT32 ui32RegOffset,
+ IMG_BOOL bLastFrame);
+
+IMG_IMPORT IMG_HANDLE PVRSRVLoadLibrary(const IMG_CHAR *pszLibraryName);
+IMG_IMPORT PVRSRV_ERROR PVRSRVUnloadLibrary(IMG_HANDLE hExtDrv);
+IMG_IMPORT PVRSRV_ERROR PVRSRVGetLibFuncAddr(IMG_HANDLE hExtDrv, const IMG_CHAR *pszFunctionName, IMG_VOID **ppvFuncAddr);
+
+IMG_IMPORT IMG_UINT32 PVRSRVClockus (void);
+IMG_IMPORT IMG_VOID PVRSRVWaitus (IMG_UINT32 ui32Timeus);
+IMG_IMPORT IMG_VOID PVRSRVReleaseThreadQuanta (void);
+IMG_IMPORT IMG_UINT32 IMG_CALLCONV PVRSRVGetCurrentProcessID(void);
+IMG_IMPORT IMG_CHAR * IMG_CALLCONV PVRSRVSetLocale(const IMG_CHAR *pszLocale);
+
+
+
+
+
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVCreateAppHintState(IMG_MODULE_ID eModuleID,
+ const IMG_CHAR *pszAppName,
+ IMG_VOID **ppvState);
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVFreeAppHintState(IMG_MODULE_ID eModuleID,
+ IMG_VOID *pvHintState);
+
+IMG_IMPORT IMG_BOOL IMG_CALLCONV PVRSRVGetAppHint(IMG_VOID *pvHintState,
+ const IMG_CHAR *pszHintName,
+ IMG_DATA_TYPE eDataType,
+ const IMG_VOID *pvDefault,
+ IMG_VOID *pvReturn);
+
+IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVAllocUserModeMem (IMG_SIZE_T ui32Size);
+IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVCallocUserModeMem (IMG_SIZE_T ui32Size);
+IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVReallocUserModeMem (IMG_PVOID pvBase, IMG_SIZE_T uNewSize);
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVFreeUserModeMem (IMG_PVOID pvMem);
+IMG_IMPORT IMG_VOID PVRSRVMemCopy(IMG_VOID *pvDst, const IMG_VOID *pvSrc, IMG_SIZE_T ui32Size);
+IMG_IMPORT IMG_VOID PVRSRVMemSet(IMG_VOID *pvDest, IMG_UINT8 ui8Value, IMG_SIZE_T ui32Size);
+
+struct _PVRSRV_MUTEX_OPAQUE_STRUCT_;
+typedef struct _PVRSRV_MUTEX_OPAQUE_STRUCT_ *PVRSRV_MUTEX_HANDLE;
+
+
+
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateMutex(PVRSRV_MUTEX_HANDLE *phMutex);
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyMutex(PVRSRV_MUTEX_HANDLE hMutex);
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVLockMutex(PVRSRV_MUTEX_HANDLE hMutex);
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVUnlockMutex(PVRSRV_MUTEX_HANDLE hMutex);
+
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVLockProcessGlobalMutex(void);
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVUnlockProcessGlobalMutex(void);
+
+
+struct _PVRSRV_SEMAPHORE_OPAQUE_STRUCT_;
+typedef struct _PVRSRV_SEMAPHORE_OPAQUE_STRUCT_ *PVRSRV_SEMAPHORE_HANDLE;
+
+
+ #define IMG_SEMAPHORE_WAIT_INFINITE ((IMG_UINT64)0xFFFFFFFFFFFFFFFFull)
+
+
+#if !defined(USE_CODE)
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVCreateSemaphore)
+#endif
+static INLINE PVRSRV_ERROR PVRSRVCreateSemaphore(PVRSRV_SEMAPHORE_HANDLE *phSemaphore, IMG_INT iInitialCount)
+{
+ PVR_UNREFERENCED_PARAMETER(iInitialCount);
+ *phSemaphore = 0;
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVDestroySemaphore)
+#endif
+static INLINE PVRSRV_ERROR PVRSRVDestroySemaphore(PVRSRV_SEMAPHORE_HANDLE hSemaphore)
+{
+ PVR_UNREFERENCED_PARAMETER(hSemaphore);
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVWaitSemaphore)
+#endif
+static INLINE PVRSRV_ERROR PVRSRVWaitSemaphore(PVRSRV_SEMAPHORE_HANDLE hSemaphore, IMG_UINT64 ui64TimeoutMicroSeconds)
+{
+ PVR_UNREFERENCED_PARAMETER(hSemaphore);
+ PVR_UNREFERENCED_PARAMETER(ui64TimeoutMicroSeconds);
+ return PVRSRV_ERROR_INVALID_PARAMS;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVPostSemaphore)
+#endif
+static INLINE IMG_VOID PVRSRVPostSemaphore(PVRSRV_SEMAPHORE_HANDLE hSemaphore, IMG_INT iPostCount)
+{
+ PVR_UNREFERENCED_PARAMETER(hSemaphore);
+ PVR_UNREFERENCED_PARAMETER(iPostCount);
+}
+
+#endif
+
+
+#if (defined(DEBUG) && defined(__linux__))
+IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVAllocUserModeMemTracking(IMG_SIZE_T ui32Size, IMG_CHAR *pszFileName, IMG_UINT32 ui32LineNumber);
+
+IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVCallocUserModeMemTracking(IMG_SIZE_T ui32Size, IMG_CHAR *pszFileName, IMG_UINT32 ui32LineNumber);
+
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVFreeUserModeMemTracking(IMG_VOID *pvMem);
+
+IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVReallocUserModeMemTracking(IMG_VOID *pvMem, IMG_SIZE_T ui32NewSize,
+ IMG_CHAR *pszFileName, IMG_UINT32 ui32LineNumber);
+#endif
+
+IMG_IMPORT PVRSRV_ERROR PVRSRVEventObjectWait(const PVRSRV_CONNECTION *psConnection,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_EVENTSID hOSEvent
+#else
+ IMG_HANDLE hOSEvent
+#endif
+ );
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateSyncInfoModObj(const PVRSRV_CONNECTION *psConnection,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID *phKernelSyncInfoModObj
+#else
+ IMG_HANDLE *phKernelSyncInfoModObj
+#endif
+ );
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroySyncInfoModObj(const PVRSRV_CONNECTION *psConnection,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelSyncInfoModObj
+#else
+ IMG_HANDLE hKernelSyncInfoModObj
+#endif
+ );
+
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVModifyPendingSyncOps(const PVRSRV_CONNECTION *psConnection,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelSyncInfoModObj,
+#else
+ IMG_HANDLE hKernelSyncInfoModObj,
+#endif
+ PVRSRV_CLIENT_SYNC_INFO *psSyncInfo,
+ IMG_UINT32 ui32ModifyFlags,
+ IMG_UINT32 *pui32ReadOpsPending,
+ IMG_UINT32 *pui32WriteOpsPending);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVModifyCompleteSyncOps(const PVRSRV_CONNECTION *psConnection,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelSyncInfoModObj
+#else
+ IMG_HANDLE hKernelSyncInfoModObj
+#endif
+ );
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSyncOpsTakeToken(const PVRSRV_CONNECTION *psConnection,
+#if defined (SUPPORT_SID_INTERFACE)
+ const IMG_SID hKernelSyncInfo,
+#else
+ const PVRSRV_CLIENT_SYNC_INFO *psSyncInfo,
+#endif
+ PVRSRV_SYNC_TOKEN *psSyncToken);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSyncOpsFlushToToken(const PVRSRV_CONNECTION *psConnection,
+#if defined (SUPPORT_SID_INTERFACE)
+ const IMG_SID hKernelSyncInfo,
+#else
+ const PVRSRV_CLIENT_SYNC_INFO *psSyncInfo,
+#endif
+ const PVRSRV_SYNC_TOKEN *psSyncToken,
+ IMG_BOOL bWait);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSyncOpsFlushToModObj(const PVRSRV_CONNECTION *psConnection,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelSyncInfoModObj,
+#else
+ IMG_HANDLE hKernelSyncInfoModObj,
+#endif
+ IMG_BOOL bWait);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSyncOpsFlushToDelta(const PVRSRV_CONNECTION *psConnection,
+ PVRSRV_CLIENT_SYNC_INFO *psClientSyncInfo,
+ IMG_UINT32 ui32Delta,
+ IMG_BOOL bWait);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocSyncInfo(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_CLIENT_SYNC_INFO **ppsSyncInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeSyncInfo(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_CLIENT_SYNC_INFO *psSyncInfo);
+
+IMG_IMPORT
+const IMG_CHAR *PVRSRVGetErrorString(PVRSRV_ERROR eError);
+
+
+#define TIME_NOT_PASSED_UINT32(a,b,c) (((a) - (b)) < (c))
+
+#if defined (__cplusplus)
+}
+#endif
+#endif
+
diff --git a/drivers/gpu/pvr/services_headers.h b/drivers/gpu/pvr/services_headers.h
new file mode 100644
index 0000000..09ed87e
--- /dev/null
+++ b/drivers/gpu/pvr/services_headers.h
@@ -0,0 +1,50 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef SERVICES_HEADERS_H
+#define SERVICES_HEADERS_H
+
+#ifdef DEBUG_RELEASE_BUILD
+#pragma optimize( "", off )
+#define DEBUG 1
+#endif
+
+#include "img_defs.h"
+#include "services.h"
+#include "servicesint.h"
+#include "power.h"
+#include "resman.h"
+#include "queue.h"
+#include "srvkm.h"
+#include "kerneldisplay.h"
+#include "syscommon.h"
+#include "pvr_debug.h"
+#include "metrics.h"
+#include "osfunc.h"
+#include "refcount.h"
+
+#endif
+
diff --git a/drivers/gpu/pvr/servicesext.h b/drivers/gpu/pvr/servicesext.h
new file mode 100644
index 0000000..42558b9
--- /dev/null
+++ b/drivers/gpu/pvr/servicesext.h
@@ -0,0 +1,854 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#if !defined (__SERVICESEXT_H__)
+#define __SERVICESEXT_H__
+
+#define PVRSRV_LOCKFLG_READONLY (1)
+
+typedef enum _PVRSRV_ERROR_
+{
+ PVRSRV_OK = 0,
+ PVRSRV_ERROR_OUT_OF_MEMORY,
+ PVRSRV_ERROR_TOO_FEW_BUFFERS,
+ PVRSRV_ERROR_INVALID_PARAMS,
+ PVRSRV_ERROR_INIT_FAILURE,
+ PVRSRV_ERROR_CANT_REGISTER_CALLBACK,
+ PVRSRV_ERROR_INVALID_DEVICE,
+ PVRSRV_ERROR_NOT_OWNER,
+ PVRSRV_ERROR_BAD_MAPPING,
+ PVRSRV_ERROR_TIMEOUT,
+ PVRSRV_ERROR_FLIP_CHAIN_EXISTS,
+ PVRSRV_ERROR_INVALID_SWAPINTERVAL,
+ PVRSRV_ERROR_SCENE_INVALID,
+ PVRSRV_ERROR_STREAM_ERROR,
+ PVRSRV_ERROR_FAILED_DEPENDENCIES,
+ PVRSRV_ERROR_CMD_NOT_PROCESSED,
+ PVRSRV_ERROR_CMD_TOO_BIG,
+ PVRSRV_ERROR_DEVICE_REGISTER_FAILED,
+ PVRSRV_ERROR_TOOMANYBUFFERS,
+ PVRSRV_ERROR_NOT_SUPPORTED,
+ PVRSRV_ERROR_PROCESSING_BLOCKED,
+
+ PVRSRV_ERROR_CANNOT_FLUSH_QUEUE,
+ PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE,
+ PVRSRV_ERROR_CANNOT_GET_RENDERDETAILS,
+ PVRSRV_ERROR_RETRY,
+
+ PVRSRV_ERROR_DDK_VERSION_MISMATCH,
+ PVRSRV_ERROR_BUILD_MISMATCH,
+ PVRSRV_ERROR_CORE_REVISION_MISMATCH,
+
+ PVRSRV_ERROR_UPLOAD_TOO_BIG,
+
+ PVRSRV_ERROR_INVALID_FLAGS,
+ PVRSRV_ERROR_FAILED_TO_REGISTER_PROCESS,
+
+ PVRSRV_ERROR_UNABLE_TO_LOAD_LIBRARY,
+ PVRSRV_ERROR_UNABLE_GET_FUNC_ADDR,
+ PVRSRV_ERROR_UNLOAD_LIBRARY_FAILED,
+
+ PVRSRV_ERROR_BRIDGE_CALL_FAILED,
+ PVRSRV_ERROR_IOCTL_CALL_FAILED,
+
+ PVRSRV_ERROR_MMU_CONTEXT_NOT_FOUND,
+ PVRSRV_ERROR_BUFFER_DEVICE_NOT_FOUND,
+ PVRSRV_ERROR_BUFFER_DEVICE_ALREADY_PRESENT,
+
+ PVRSRV_ERROR_PCI_DEVICE_NOT_FOUND,
+ PVRSRV_ERROR_PCI_CALL_FAILED,
+ PVRSRV_ERROR_PCI_REGION_TOO_SMALL,
+ PVRSRV_ERROR_PCI_REGION_UNAVAILABLE,
+ PVRSRV_ERROR_BAD_REGION_SIZE_MISMATCH,
+
+ PVRSRV_ERROR_REGISTER_BASE_NOT_SET,
+
+ PVRSRV_ERROR_BM_BAD_SHAREMEM_HANDLE,
+
+ PVRSRV_ERROR_FAILED_TO_ALLOC_USER_MEM,
+ PVRSRV_ERROR_FAILED_TO_ALLOC_VP_MEMORY,
+ PVRSRV_ERROR_FAILED_TO_MAP_SHARED_PBDESC,
+ PVRSRV_ERROR_FAILED_TO_GET_PHYS_ADDR,
+
+ PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY,
+ PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY,
+
+ PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES,
+ PVRSRV_ERROR_FAILED_TO_FREE_PAGES,
+ PVRSRV_ERROR_FAILED_TO_COPY_PAGES,
+ PVRSRV_ERROR_UNABLE_TO_LOCK_PAGES,
+ PVRSRV_ERROR_UNABLE_TO_UNLOCK_PAGES,
+ PVRSRV_ERROR_STILL_MAPPED,
+ PVRSRV_ERROR_MAPPING_NOT_FOUND,
+ PVRSRV_ERROR_PHYS_ADDRESS_EXCEEDS_32BIT,
+ PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE,
+
+ PVRSRV_ERROR_INVALID_SEGMENT_BLOCK,
+ PVRSRV_ERROR_INVALID_SGXDEVDATA,
+ PVRSRV_ERROR_INVALID_DEVINFO,
+ PVRSRV_ERROR_INVALID_MEMINFO,
+ PVRSRV_ERROR_INVALID_MISCINFO,
+ PVRSRV_ERROR_UNKNOWN_IOCTL,
+ PVRSRV_ERROR_INVALID_CONTEXT,
+ PVRSRV_ERROR_UNABLE_TO_DESTROY_CONTEXT,
+ PVRSRV_ERROR_INVALID_HEAP,
+ PVRSRV_ERROR_INVALID_KERNELINFO,
+ PVRSRV_ERROR_UNKNOWN_POWER_STATE,
+ PVRSRV_ERROR_INVALID_HANDLE_TYPE,
+ PVRSRV_ERROR_INVALID_WRAP_TYPE,
+ PVRSRV_ERROR_INVALID_PHYS_ADDR,
+ PVRSRV_ERROR_INVALID_CPU_ADDR,
+ PVRSRV_ERROR_INVALID_HEAPINFO,
+ PVRSRV_ERROR_INVALID_PERPROC,
+ PVRSRV_ERROR_FAILED_TO_RETRIEVE_HEAPINFO,
+ PVRSRV_ERROR_INVALID_MAP_REQUEST,
+ PVRSRV_ERROR_INVALID_UNMAP_REQUEST,
+ PVRSRV_ERROR_UNABLE_TO_FIND_MAPPING_HEAP,
+ PVRSRV_ERROR_MAPPING_STILL_IN_USE,
+
+ PVRSRV_ERROR_EXCEEDED_HW_LIMITS,
+ PVRSRV_ERROR_NO_STAGING_BUFFER_ALLOCATED,
+
+ PVRSRV_ERROR_UNABLE_TO_CREATE_PERPROC_AREA,
+ PVRSRV_ERROR_UNABLE_TO_CREATE_EVENT,
+ PVRSRV_ERROR_UNABLE_TO_ENABLE_EVENT,
+ PVRSRV_ERROR_UNABLE_TO_REGISTER_EVENT,
+ PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT,
+ PVRSRV_ERROR_UNABLE_TO_CREATE_THREAD,
+ PVRSRV_ERROR_UNABLE_TO_CLOSE_THREAD,
+ PVRSRV_ERROR_THREAD_READ_ERROR,
+ PVRSRV_ERROR_UNABLE_TO_REGISTER_ISR_HANDLER,
+ PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR,
+ PVRSRV_ERROR_UNABLE_TO_UNINSTALL_ISR,
+ PVRSRV_ERROR_ISR_ALREADY_INSTALLED,
+ PVRSRV_ERROR_ISR_NOT_INSTALLED,
+ PVRSRV_ERROR_UNABLE_TO_INITIALISE_INTERRUPT,
+ PVRSRV_ERROR_UNABLE_TO_RETRIEVE_INFO,
+ PVRSRV_ERROR_UNABLE_TO_DO_BACKWARDS_BLIT,
+ PVRSRV_ERROR_UNABLE_TO_CLOSE_SERVICES,
+ PVRSRV_ERROR_UNABLE_TO_REGISTER_CONTEXT,
+ PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE,
+ PVRSRV_ERROR_UNABLE_TO_CLOSE_HANDLE,
+
+ PVRSRV_ERROR_INVALID_CCB_COMMAND,
+
+ PVRSRV_ERROR_UNABLE_TO_LOCK_RESOURCE,
+ PVRSRV_ERROR_INVALID_LOCK_ID,
+ PVRSRV_ERROR_RESOURCE_NOT_LOCKED,
+
+ PVRSRV_ERROR_FLIP_FAILED,
+ PVRSRV_ERROR_UNBLANK_DISPLAY_FAILED,
+
+ PVRSRV_ERROR_TIMEOUT_POLLING_FOR_VALUE,
+
+ PVRSRV_ERROR_CREATE_RENDER_CONTEXT_FAILED,
+ PVRSRV_ERROR_UNKNOWN_PRIMARY_FRAG,
+ PVRSRV_ERROR_UNEXPECTED_SECONDARY_FRAG,
+ PVRSRV_ERROR_UNEXPECTED_PRIMARY_FRAG,
+
+ PVRSRV_ERROR_UNABLE_TO_INSERT_FENCE_ID,
+
+ PVRSRV_ERROR_BLIT_SETUP_FAILED,
+
+ PVRSRV_ERROR_PDUMP_NOT_AVAILABLE,
+ PVRSRV_ERROR_PDUMP_BUFFER_FULL,
+ PVRSRV_ERROR_PDUMP_BUF_OVERFLOW,
+ PVRSRV_ERROR_PDUMP_NOT_ACTIVE,
+ PVRSRV_ERROR_INCOMPLETE_LINE_OVERLAPS_PAGES,
+
+ PVRSRV_ERROR_MUTEX_DESTROY_FAILED,
+ PVRSRV_ERROR_MUTEX_INTERRUPTIBLE_ERROR,
+
+ PVRSRV_ERROR_INSUFFICIENT_SCRIPT_SPACE,
+ PVRSRV_ERROR_INSUFFICIENT_SPACE_FOR_COMMAND,
+
+ PVRSRV_ERROR_PROCESS_NOT_INITIALISED,
+ PVRSRV_ERROR_PROCESS_NOT_FOUND,
+ PVRSRV_ERROR_SRV_CONNECT_FAILED,
+ PVRSRV_ERROR_SRV_DISCONNECT_FAILED,
+ PVRSRV_ERROR_DEINT_PHASE_FAILED,
+ PVRSRV_ERROR_INIT2_PHASE_FAILED,
+
+ PVRSRV_ERROR_UNABLE_TO_FIND_RESOURCE,
+
+ PVRSRV_ERROR_NO_DC_DEVICES_FOUND,
+ PVRSRV_ERROR_UNABLE_TO_OPEN_DC_DEVICE,
+ PVRSRV_ERROR_UNABLE_TO_REMOVE_DEVICE,
+ PVRSRV_ERROR_NO_DEVICEDATA_FOUND,
+ PVRSRV_ERROR_NO_DEVICENODE_FOUND,
+ PVRSRV_ERROR_NO_CLIENTNODE_FOUND,
+ PVRSRV_ERROR_FAILED_TO_PROCESS_QUEUE,
+
+ PVRSRV_ERROR_UNABLE_TO_INIT_TASK,
+ PVRSRV_ERROR_UNABLE_TO_SCHEDULE_TASK,
+ PVRSRV_ERROR_UNABLE_TO_KILL_TASK,
+
+ PVRSRV_ERROR_UNABLE_TO_ENABLE_TIMER,
+ PVRSRV_ERROR_UNABLE_TO_DISABLE_TIMER,
+ PVRSRV_ERROR_UNABLE_TO_REMOVE_TIMER,
+
+ PVRSRV_ERROR_UNKNOWN_PIXEL_FORMAT,
+ PVRSRV_ERROR_UNKNOWN_SCRIPT_OPERATION,
+
+ PVRSRV_ERROR_HANDLE_INDEX_OUT_OF_RANGE,
+ PVRSRV_ERROR_HANDLE_NOT_ALLOCATED,
+ PVRSRV_ERROR_HANDLE_TYPE_MISMATCH,
+ PVRSRV_ERROR_UNABLE_TO_ADD_HANDLE,
+ PVRSRV_ERROR_HANDLE_NOT_SHAREABLE,
+ PVRSRV_ERROR_HANDLE_NOT_FOUND,
+ PVRSRV_ERROR_INVALID_SUBHANDLE,
+ PVRSRV_ERROR_HANDLE_BATCH_IN_USE,
+ PVRSRV_ERROR_HANDLE_BATCH_COMMIT_FAILURE,
+
+ PVRSRV_ERROR_UNABLE_TO_CREATE_HASH_TABLE,
+ PVRSRV_ERROR_INSERT_HASH_TABLE_DATA_FAILED,
+
+ PVRSRV_ERROR_UNSUPPORTED_BACKING_STORE,
+ PVRSRV_ERROR_UNABLE_TO_DESTROY_BM_HEAP,
+
+ PVRSRV_ERROR_UNKNOWN_INIT_SERVER_STATE,
+
+ PVRSRV_ERROR_NO_FREE_DEVICEIDS_AVALIABLE,
+ PVRSRV_ERROR_INVALID_DEVICEID,
+ PVRSRV_ERROR_DEVICEID_NOT_FOUND,
+
+ PVRSRV_ERROR_MEMORY_TEST_FAILED,
+ PVRSRV_ERROR_CPUPADDR_TEST_FAILED,
+ PVRSRV_ERROR_COPY_TEST_FAILED,
+
+ PVRSRV_ERROR_SEMAPHORE_NOT_INITIALISED,
+
+ PVRSRV_ERROR_UNABLE_TO_RELEASE_CLOCK,
+ PVRSRV_ERROR_CLOCK_REQUEST_FAILED,
+ PVRSRV_ERROR_DISABLE_CLOCK_FAILURE,
+ PVRSRV_ERROR_UNABLE_TO_SET_CLOCK_RATE,
+ PVRSRV_ERROR_UNABLE_TO_ROUND_CLOCK_RATE,
+ PVRSRV_ERROR_UNABLE_TO_ENABLE_CLOCK,
+ PVRSRV_ERROR_UNABLE_TO_GET_CLOCK,
+ PVRSRV_ERROR_UNABLE_TO_GET_PARENT_CLOCK,
+ PVRSRV_ERROR_UNABLE_TO_GET_SYSTEM_CLOCK,
+
+ PVRSRV_ERROR_UNKNOWN_SGL_ERROR,
+
+ PVRSRV_ERROR_SYSTEM_POWER_CHANGE_FAILURE,
+ PVRSRV_ERROR_DEVICE_POWER_CHANGE_FAILURE,
+
+ PVRSRV_ERROR_BAD_SYNC_STATE,
+
+ PVRSRV_ERROR_CACHEOP_FAILED,
+
+ PVRSRV_ERROR_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_ERROR;
+
+
+typedef enum _PVRSRV_DEVICE_CLASS_
+{
+ PVRSRV_DEVICE_CLASS_3D = 0 ,
+ PVRSRV_DEVICE_CLASS_DISPLAY = 1 ,
+ PVRSRV_DEVICE_CLASS_BUFFER = 2 ,
+ PVRSRV_DEVICE_CLASS_VIDEO = 3 ,
+
+ PVRSRV_DEVICE_CLASS_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_DEVICE_CLASS;
+
+
+typedef enum _PVRSRV_SYS_POWER_STATE_
+{
+ PVRSRV_SYS_POWER_STATE_Unspecified = -1,
+ PVRSRV_SYS_POWER_STATE_D0 = 0,
+ PVRSRV_SYS_POWER_STATE_D1 = 1,
+ PVRSRV_SYS_POWER_STATE_D2 = 2,
+ PVRSRV_SYS_POWER_STATE_D3 = 3,
+ PVRSRV_SYS_POWER_STATE_D4 = 4,
+
+ PVRSRV_SYS_POWER_STATE_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_SYS_POWER_STATE, *PPVRSRV_SYS_POWER_STATE;
+
+
+typedef enum _PVRSRV_DEV_POWER_STATE_
+{
+ PVRSRV_DEV_POWER_STATE_DEFAULT = -1,
+ PVRSRV_DEV_POWER_STATE_ON = 0,
+ PVRSRV_DEV_POWER_STATE_IDLE = 1,
+ PVRSRV_DEV_POWER_STATE_OFF = 2,
+
+ PVRSRV_DEV_POWER_STATE_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_DEV_POWER_STATE, *PPVRSRV_DEV_POWER_STATE;
+
+
+typedef PVRSRV_ERROR (*PFN_PRE_POWER) (IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+typedef PVRSRV_ERROR (*PFN_POST_POWER) (IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+
+typedef PVRSRV_ERROR (*PFN_PRE_CLOCKSPEED_CHANGE) (IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+typedef PVRSRV_ERROR (*PFN_POST_CLOCKSPEED_CHANGE) (IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+
+
+typedef enum _PVRSRV_PIXEL_FORMAT_ {
+
+ PVRSRV_PIXEL_FORMAT_UNKNOWN = 0,
+ PVRSRV_PIXEL_FORMAT_RGB565 = 1,
+ PVRSRV_PIXEL_FORMAT_RGB555 = 2,
+ PVRSRV_PIXEL_FORMAT_RGB888 = 3,
+ PVRSRV_PIXEL_FORMAT_BGR888 = 4,
+ PVRSRV_PIXEL_FORMAT_GREY_SCALE = 8,
+ PVRSRV_PIXEL_FORMAT_PAL12 = 13,
+ PVRSRV_PIXEL_FORMAT_PAL8 = 14,
+ PVRSRV_PIXEL_FORMAT_PAL4 = 15,
+ PVRSRV_PIXEL_FORMAT_PAL2 = 16,
+ PVRSRV_PIXEL_FORMAT_PAL1 = 17,
+ PVRSRV_PIXEL_FORMAT_ARGB1555 = 18,
+ PVRSRV_PIXEL_FORMAT_ARGB4444 = 19,
+ PVRSRV_PIXEL_FORMAT_ARGB8888 = 20,
+ PVRSRV_PIXEL_FORMAT_ABGR8888 = 21,
+ PVRSRV_PIXEL_FORMAT_YV12 = 22,
+ PVRSRV_PIXEL_FORMAT_I420 = 23,
+ PVRSRV_PIXEL_FORMAT_IMC2 = 25,
+ PVRSRV_PIXEL_FORMAT_XRGB8888 = 26,
+ PVRSRV_PIXEL_FORMAT_XBGR8888 = 27,
+ PVRSRV_PIXEL_FORMAT_BGRA8888 = 28,
+ PVRSRV_PIXEL_FORMAT_XRGB4444 = 29,
+ PVRSRV_PIXEL_FORMAT_ARGB8332 = 30,
+ PVRSRV_PIXEL_FORMAT_A2RGB10 = 31,
+ PVRSRV_PIXEL_FORMAT_A2BGR10 = 32,
+ PVRSRV_PIXEL_FORMAT_P8 = 33,
+ PVRSRV_PIXEL_FORMAT_L8 = 34,
+ PVRSRV_PIXEL_FORMAT_A8L8 = 35,
+ PVRSRV_PIXEL_FORMAT_A4L4 = 36,
+ PVRSRV_PIXEL_FORMAT_L16 = 37,
+ PVRSRV_PIXEL_FORMAT_L6V5U5 = 38,
+ PVRSRV_PIXEL_FORMAT_V8U8 = 39,
+ PVRSRV_PIXEL_FORMAT_V16U16 = 40,
+ PVRSRV_PIXEL_FORMAT_QWVU8888 = 41,
+ PVRSRV_PIXEL_FORMAT_XLVU8888 = 42,
+ PVRSRV_PIXEL_FORMAT_QWVU16 = 43,
+ PVRSRV_PIXEL_FORMAT_D16 = 44,
+ PVRSRV_PIXEL_FORMAT_D24S8 = 45,
+ PVRSRV_PIXEL_FORMAT_D24X8 = 46,
+
+
+ PVRSRV_PIXEL_FORMAT_ABGR16 = 47,
+ PVRSRV_PIXEL_FORMAT_ABGR16F = 48,
+ PVRSRV_PIXEL_FORMAT_ABGR32 = 49,
+ PVRSRV_PIXEL_FORMAT_ABGR32F = 50,
+ PVRSRV_PIXEL_FORMAT_B10GR11 = 51,
+ PVRSRV_PIXEL_FORMAT_GR88 = 52,
+ PVRSRV_PIXEL_FORMAT_BGR32 = 53,
+ PVRSRV_PIXEL_FORMAT_GR32 = 54,
+ PVRSRV_PIXEL_FORMAT_E5BGR9 = 55,
+
+
+ PVRSRV_PIXEL_FORMAT_RESERVED1 = 56,
+ PVRSRV_PIXEL_FORMAT_RESERVED2 = 57,
+ PVRSRV_PIXEL_FORMAT_RESERVED3 = 58,
+ PVRSRV_PIXEL_FORMAT_RESERVED4 = 59,
+ PVRSRV_PIXEL_FORMAT_RESERVED5 = 60,
+
+
+ PVRSRV_PIXEL_FORMAT_R8G8_B8G8 = 61,
+ PVRSRV_PIXEL_FORMAT_G8R8_G8B8 = 62,
+
+
+ PVRSRV_PIXEL_FORMAT_NV11 = 63,
+ PVRSRV_PIXEL_FORMAT_NV12 = 64,
+
+
+ PVRSRV_PIXEL_FORMAT_YUY2 = 65,
+ PVRSRV_PIXEL_FORMAT_YUV420 = 66,
+ PVRSRV_PIXEL_FORMAT_YUV444 = 67,
+ PVRSRV_PIXEL_FORMAT_VUY444 = 68,
+ PVRSRV_PIXEL_FORMAT_YUYV = 69,
+ PVRSRV_PIXEL_FORMAT_YVYU = 70,
+ PVRSRV_PIXEL_FORMAT_UYVY = 71,
+ PVRSRV_PIXEL_FORMAT_VYUY = 72,
+
+ PVRSRV_PIXEL_FORMAT_FOURCC_ORG_UYVY = 73,
+ PVRSRV_PIXEL_FORMAT_FOURCC_ORG_YUYV = 74,
+ PVRSRV_PIXEL_FORMAT_FOURCC_ORG_YVYU = 75,
+ PVRSRV_PIXEL_FORMAT_FOURCC_ORG_VYUY = 76,
+ PVRSRV_PIXEL_FORMAT_FOURCC_ORG_AYUV = 77,
+
+
+ PVRSRV_PIXEL_FORMAT_A32B32G32R32 = 78,
+ PVRSRV_PIXEL_FORMAT_A32B32G32R32F = 79,
+ PVRSRV_PIXEL_FORMAT_A32B32G32R32_UINT = 80,
+ PVRSRV_PIXEL_FORMAT_A32B32G32R32_SINT = 81,
+
+
+ PVRSRV_PIXEL_FORMAT_B32G32R32 = 82,
+ PVRSRV_PIXEL_FORMAT_B32G32R32F = 83,
+ PVRSRV_PIXEL_FORMAT_B32G32R32_UINT = 84,
+ PVRSRV_PIXEL_FORMAT_B32G32R32_SINT = 85,
+
+
+ PVRSRV_PIXEL_FORMAT_G32R32 = 86,
+ PVRSRV_PIXEL_FORMAT_G32R32F = 87,
+ PVRSRV_PIXEL_FORMAT_G32R32_UINT = 88,
+ PVRSRV_PIXEL_FORMAT_G32R32_SINT = 89,
+
+
+ PVRSRV_PIXEL_FORMAT_D32F = 90,
+ PVRSRV_PIXEL_FORMAT_R32 = 91,
+ PVRSRV_PIXEL_FORMAT_R32F = 92,
+ PVRSRV_PIXEL_FORMAT_R32_UINT = 93,
+ PVRSRV_PIXEL_FORMAT_R32_SINT = 94,
+
+
+ PVRSRV_PIXEL_FORMAT_A16B16G16R16 = 95,
+ PVRSRV_PIXEL_FORMAT_A16B16G16R16F = 96,
+ PVRSRV_PIXEL_FORMAT_A16B16G16R16_SINT = 97,
+ PVRSRV_PIXEL_FORMAT_A16B16G16R16_SNORM = 98,
+ PVRSRV_PIXEL_FORMAT_A16B16G16R16_UINT = 99,
+ PVRSRV_PIXEL_FORMAT_A16B16G16R16_UNORM = 100,
+
+
+ PVRSRV_PIXEL_FORMAT_G16R16 = 101,
+ PVRSRV_PIXEL_FORMAT_G16R16F = 102,
+ PVRSRV_PIXEL_FORMAT_G16R16_UINT = 103,
+ PVRSRV_PIXEL_FORMAT_G16R16_UNORM = 104,
+ PVRSRV_PIXEL_FORMAT_G16R16_SINT = 105,
+ PVRSRV_PIXEL_FORMAT_G16R16_SNORM = 106,
+
+
+ PVRSRV_PIXEL_FORMAT_R16 = 107,
+ PVRSRV_PIXEL_FORMAT_R16F = 108,
+ PVRSRV_PIXEL_FORMAT_R16_UINT = 109,
+ PVRSRV_PIXEL_FORMAT_R16_UNORM = 110,
+ PVRSRV_PIXEL_FORMAT_R16_SINT = 111,
+ PVRSRV_PIXEL_FORMAT_R16_SNORM = 112,
+
+
+ PVRSRV_PIXEL_FORMAT_X8R8G8B8 = 113,
+ PVRSRV_PIXEL_FORMAT_X8R8G8B8_UNORM = 114,
+ PVRSRV_PIXEL_FORMAT_X8R8G8B8_UNORM_SRGB = 115,
+
+ PVRSRV_PIXEL_FORMAT_A8R8G8B8 = 116,
+ PVRSRV_PIXEL_FORMAT_A8R8G8B8_UNORM = 117,
+ PVRSRV_PIXEL_FORMAT_A8R8G8B8_UNORM_SRGB = 118,
+
+ PVRSRV_PIXEL_FORMAT_A8B8G8R8 = 119,
+ PVRSRV_PIXEL_FORMAT_A8B8G8R8_UINT = 120,
+ PVRSRV_PIXEL_FORMAT_A8B8G8R8_UNORM = 121,
+ PVRSRV_PIXEL_FORMAT_A8B8G8R8_UNORM_SRGB = 122,
+ PVRSRV_PIXEL_FORMAT_A8B8G8R8_SINT = 123,
+ PVRSRV_PIXEL_FORMAT_A8B8G8R8_SNORM = 124,
+
+
+ PVRSRV_PIXEL_FORMAT_G8R8 = 125,
+ PVRSRV_PIXEL_FORMAT_G8R8_UINT = 126,
+ PVRSRV_PIXEL_FORMAT_G8R8_UNORM = 127,
+ PVRSRV_PIXEL_FORMAT_G8R8_SINT = 128,
+ PVRSRV_PIXEL_FORMAT_G8R8_SNORM = 129,
+
+
+ PVRSRV_PIXEL_FORMAT_A8 = 130,
+ PVRSRV_PIXEL_FORMAT_R8 = 131,
+ PVRSRV_PIXEL_FORMAT_R8_UINT = 132,
+ PVRSRV_PIXEL_FORMAT_R8_UNORM = 133,
+ PVRSRV_PIXEL_FORMAT_R8_SINT = 134,
+ PVRSRV_PIXEL_FORMAT_R8_SNORM = 135,
+
+
+ PVRSRV_PIXEL_FORMAT_A2B10G10R10 = 136,
+ PVRSRV_PIXEL_FORMAT_A2B10G10R10_UNORM = 137,
+ PVRSRV_PIXEL_FORMAT_A2B10G10R10_UINT = 138,
+
+
+ PVRSRV_PIXEL_FORMAT_B10G11R11 = 139,
+ PVRSRV_PIXEL_FORMAT_B10G11R11F = 140,
+
+
+ PVRSRV_PIXEL_FORMAT_X24G8R32 = 141,
+ PVRSRV_PIXEL_FORMAT_G8R24 = 142,
+ PVRSRV_PIXEL_FORMAT_X8R24 = 143,
+ PVRSRV_PIXEL_FORMAT_E5B9G9R9 = 144,
+ PVRSRV_PIXEL_FORMAT_R1 = 145,
+
+ PVRSRV_PIXEL_FORMAT_RESERVED6 = 146,
+ PVRSRV_PIXEL_FORMAT_RESERVED7 = 147,
+ PVRSRV_PIXEL_FORMAT_RESERVED8 = 148,
+ PVRSRV_PIXEL_FORMAT_RESERVED9 = 149,
+ PVRSRV_PIXEL_FORMAT_RESERVED10 = 150,
+ PVRSRV_PIXEL_FORMAT_RESERVED11 = 151,
+ PVRSRV_PIXEL_FORMAT_RESERVED12 = 152,
+ PVRSRV_PIXEL_FORMAT_RESERVED13 = 153,
+ PVRSRV_PIXEL_FORMAT_RESERVED14 = 154,
+ PVRSRV_PIXEL_FORMAT_RESERVED15 = 155,
+ PVRSRV_PIXEL_FORMAT_RESERVED16 = 156,
+ PVRSRV_PIXEL_FORMAT_RESERVED17 = 157,
+ PVRSRV_PIXEL_FORMAT_RESERVED18 = 158,
+ PVRSRV_PIXEL_FORMAT_RESERVED19 = 159,
+ PVRSRV_PIXEL_FORMAT_RESERVED20 = 160,
+
+
+ PVRSRV_PIXEL_FORMAT_UBYTE4 = 161,
+ PVRSRV_PIXEL_FORMAT_SHORT4 = 162,
+ PVRSRV_PIXEL_FORMAT_SHORT4N = 163,
+ PVRSRV_PIXEL_FORMAT_USHORT4N = 164,
+ PVRSRV_PIXEL_FORMAT_SHORT2N = 165,
+ PVRSRV_PIXEL_FORMAT_SHORT2 = 166,
+ PVRSRV_PIXEL_FORMAT_USHORT2N = 167,
+ PVRSRV_PIXEL_FORMAT_UDEC3 = 168,
+ PVRSRV_PIXEL_FORMAT_DEC3N = 169,
+ PVRSRV_PIXEL_FORMAT_F16_2 = 170,
+ PVRSRV_PIXEL_FORMAT_F16_4 = 171,
+
+
+ PVRSRV_PIXEL_FORMAT_L_F16 = 172,
+ PVRSRV_PIXEL_FORMAT_L_F16_REP = 173,
+ PVRSRV_PIXEL_FORMAT_L_F16_A_F16 = 174,
+ PVRSRV_PIXEL_FORMAT_A_F16 = 175,
+ PVRSRV_PIXEL_FORMAT_B16G16R16F = 176,
+
+ PVRSRV_PIXEL_FORMAT_L_F32 = 177,
+ PVRSRV_PIXEL_FORMAT_A_F32 = 178,
+ PVRSRV_PIXEL_FORMAT_L_F32_A_F32 = 179,
+
+
+ PVRSRV_PIXEL_FORMAT_PVRTC2 = 180,
+ PVRSRV_PIXEL_FORMAT_PVRTC4 = 181,
+ PVRSRV_PIXEL_FORMAT_PVRTCII2 = 182,
+ PVRSRV_PIXEL_FORMAT_PVRTCII4 = 183,
+ PVRSRV_PIXEL_FORMAT_PVRTCIII = 184,
+ PVRSRV_PIXEL_FORMAT_PVRO8 = 185,
+ PVRSRV_PIXEL_FORMAT_PVRO88 = 186,
+ PVRSRV_PIXEL_FORMAT_PT1 = 187,
+ PVRSRV_PIXEL_FORMAT_PT2 = 188,
+ PVRSRV_PIXEL_FORMAT_PT4 = 189,
+ PVRSRV_PIXEL_FORMAT_PT8 = 190,
+ PVRSRV_PIXEL_FORMAT_PTW = 191,
+ PVRSRV_PIXEL_FORMAT_PTB = 192,
+ PVRSRV_PIXEL_FORMAT_MONO8 = 193,
+ PVRSRV_PIXEL_FORMAT_MONO16 = 194,
+
+
+ PVRSRV_PIXEL_FORMAT_C0_YUYV = 195,
+ PVRSRV_PIXEL_FORMAT_C0_UYVY = 196,
+ PVRSRV_PIXEL_FORMAT_C0_YVYU = 197,
+ PVRSRV_PIXEL_FORMAT_C0_VYUY = 198,
+ PVRSRV_PIXEL_FORMAT_C1_YUYV = 199,
+ PVRSRV_PIXEL_FORMAT_C1_UYVY = 200,
+ PVRSRV_PIXEL_FORMAT_C1_YVYU = 201,
+ PVRSRV_PIXEL_FORMAT_C1_VYUY = 202,
+
+
+ PVRSRV_PIXEL_FORMAT_C0_YUV420_2P_UV = 203,
+ PVRSRV_PIXEL_FORMAT_C0_YUV420_2P_VU = 204,
+ PVRSRV_PIXEL_FORMAT_C0_YUV420_3P = 205,
+ PVRSRV_PIXEL_FORMAT_C1_YUV420_2P_UV = 206,
+ PVRSRV_PIXEL_FORMAT_C1_YUV420_2P_VU = 207,
+ PVRSRV_PIXEL_FORMAT_C1_YUV420_3P = 208,
+
+ PVRSRV_PIXEL_FORMAT_A2B10G10R10F = 209,
+ PVRSRV_PIXEL_FORMAT_B8G8R8_SINT = 210,
+ PVRSRV_PIXEL_FORMAT_PVRF32SIGNMASK = 211,
+
+ PVRSRV_PIXEL_FORMAT_ABGR4444 = 212,
+ PVRSRV_PIXEL_FORMAT_ABGR1555 = 213,
+ PVRSRV_PIXEL_FORMAT_BGR565 = 214,
+
+
+ PVRSRV_PIXEL_FORMAT_C0_4KYUV420_2P_UV = 215,
+ PVRSRV_PIXEL_FORMAT_C0_4KYUV420_2P_VU = 216,
+ PVRSRV_PIXEL_FORMAT_C1_4KYUV420_2P_UV = 217,
+ PVRSRV_PIXEL_FORMAT_C1_4KYUV420_2P_VU = 218,
+ PVRSRV_PIXEL_FORMAT_P208 = 219,
+ PVRSRV_PIXEL_FORMAT_A8P8 = 220,
+
+ PVRSRV_PIXEL_FORMAT_A4 = 221,
+ PVRSRV_PIXEL_FORMAT_AYUV8888 = 222,
+ PVRSRV_PIXEL_FORMAT_RAW256 = 223,
+ PVRSRV_PIXEL_FORMAT_RAW512 = 224,
+ PVRSRV_PIXEL_FORMAT_RAW1024 = 225,
+
+ PVRSRV_PIXEL_FORMAT_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_PIXEL_FORMAT;
+
+typedef enum _PVRSRV_ALPHA_FORMAT_ {
+ PVRSRV_ALPHA_FORMAT_UNKNOWN = 0x00000000,
+ PVRSRV_ALPHA_FORMAT_PRE = 0x00000001,
+ PVRSRV_ALPHA_FORMAT_NONPRE = 0x00000002,
+ PVRSRV_ALPHA_FORMAT_MASK = 0x0000000F,
+} PVRSRV_ALPHA_FORMAT;
+
+typedef enum _PVRSRV_COLOURSPACE_FORMAT_ {
+ PVRSRV_COLOURSPACE_FORMAT_UNKNOWN = 0x00000000,
+ PVRSRV_COLOURSPACE_FORMAT_LINEAR = 0x00010000,
+ PVRSRV_COLOURSPACE_FORMAT_NONLINEAR = 0x00020000,
+ PVRSRV_COLOURSPACE_FORMAT_MASK = 0x000F0000,
+} PVRSRV_COLOURSPACE_FORMAT;
+
+
+typedef enum _PVRSRV_ROTATION_ {
+ PVRSRV_ROTATE_0 = 0,
+ PVRSRV_ROTATE_90 = 1,
+ PVRSRV_ROTATE_180 = 2,
+ PVRSRV_ROTATE_270 = 3,
+ PVRSRV_FLIP_Y
+
+} PVRSRV_ROTATION;
+
+#define PVRSRV_CREATE_SWAPCHAIN_SHARED (1<<0)
+#define PVRSRV_CREATE_SWAPCHAIN_QUERY (1<<1)
+#define PVRSRV_CREATE_SWAPCHAIN_OEMOVERLAY (1<<2)
+
+typedef struct _PVRSRV_SYNC_DATA_
+{
+
+ IMG_UINT32 ui32WriteOpsPending;
+ volatile IMG_UINT32 ui32WriteOpsComplete;
+
+
+ IMG_UINT32 ui32ReadOpsPending;
+ volatile IMG_UINT32 ui32ReadOpsComplete;
+
+
+ IMG_UINT32 ui32ReadOps2Pending;
+ volatile IMG_UINT32 ui32ReadOps2Complete;
+
+
+ IMG_UINT32 ui32LastOpDumpVal;
+ IMG_UINT32 ui32LastReadOpDumpVal;
+
+
+ IMG_UINT64 ui64LastWrite;
+
+} PVRSRV_SYNC_DATA;
+
+typedef struct _PVRSRV_CLIENT_SYNC_INFO_
+{
+
+ PVRSRV_SYNC_DATA *psSyncData;
+
+
+
+
+
+ IMG_DEV_VIRTADDR sWriteOpsCompleteDevVAddr;
+
+
+ IMG_DEV_VIRTADDR sReadOpsCompleteDevVAddr;
+
+
+ IMG_DEV_VIRTADDR sReadOps2CompleteDevVAddr;
+
+
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hMappingInfo;
+
+
+ IMG_SID hKernelSyncInfo;
+#else
+ IMG_HANDLE hMappingInfo;
+
+
+ IMG_HANDLE hKernelSyncInfo;
+#endif
+
+} PVRSRV_CLIENT_SYNC_INFO, *PPVRSRV_CLIENT_SYNC_INFO;
+
+typedef struct PVRSRV_RESOURCE_TAG
+{
+ volatile IMG_UINT32 ui32Lock;
+ IMG_UINT32 ui32ID;
+}PVRSRV_RESOURCE;
+typedef PVRSRV_RESOURCE PVRSRV_RES_HANDLE;
+
+
+typedef IMG_VOID (*PFN_CMD_COMPLETE) (IMG_HANDLE);
+typedef IMG_VOID (**PPFN_CMD_COMPLETE) (IMG_HANDLE);
+
+typedef IMG_BOOL (*PFN_CMD_PROC) (IMG_HANDLE, IMG_UINT32, IMG_VOID*);
+typedef IMG_BOOL (**PPFN_CMD_PROC) (IMG_HANDLE, IMG_UINT32, IMG_VOID*);
+
+
+typedef struct _IMG_RECT_
+{
+ IMG_INT32 x0;
+ IMG_INT32 y0;
+ IMG_INT32 x1;
+ IMG_INT32 y1;
+}IMG_RECT;
+
+typedef struct _IMG_RECT_16_
+{
+ IMG_INT16 x0;
+ IMG_INT16 y0;
+ IMG_INT16 x1;
+ IMG_INT16 y1;
+}IMG_RECT_16;
+
+
+typedef PVRSRV_ERROR (*PFN_GET_BUFFER_ADDR)(IMG_HANDLE,
+ IMG_HANDLE,
+ IMG_SYS_PHYADDR**,
+ IMG_SIZE_T*,
+ IMG_VOID**,
+ IMG_HANDLE*,
+ IMG_BOOL*,
+ IMG_UINT32*);
+
+
+typedef struct DISPLAY_DIMS_TAG
+{
+ IMG_UINT32 ui32ByteStride;
+ IMG_UINT32 ui32Width;
+ IMG_UINT32 ui32Height;
+} DISPLAY_DIMS;
+
+
+typedef struct DISPLAY_FORMAT_TAG
+{
+
+ PVRSRV_PIXEL_FORMAT pixelformat;
+} DISPLAY_FORMAT;
+
+typedef struct DISPLAY_SURF_ATTRIBUTES_TAG
+{
+
+ PVRSRV_PIXEL_FORMAT pixelformat;
+
+ DISPLAY_DIMS sDims;
+} DISPLAY_SURF_ATTRIBUTES;
+
+
+typedef struct DISPLAY_MODE_INFO_TAG
+{
+
+ PVRSRV_PIXEL_FORMAT pixelformat;
+
+ DISPLAY_DIMS sDims;
+
+ IMG_UINT32 ui32RefreshHZ;
+
+ IMG_UINT32 ui32OEMFlags;
+} DISPLAY_MODE_INFO;
+
+
+
+#define MAX_DISPLAY_NAME_SIZE (50)
+
+typedef struct DISPLAY_INFO_TAG
+{
+
+ IMG_UINT32 ui32MaxSwapChains;
+
+ IMG_UINT32 ui32MaxSwapChainBuffers;
+
+ IMG_UINT32 ui32MinSwapInterval;
+
+ IMG_UINT32 ui32MaxSwapInterval;
+
+ IMG_UINT32 ui32PhysicalWidthmm;
+ IMG_UINT32 ui32PhysicalHeightmm;
+
+ IMG_CHAR szDisplayName[MAX_DISPLAY_NAME_SIZE];
+#if defined(SUPPORT_HW_CURSOR)
+
+ IMG_UINT16 ui32CursorWidth;
+ IMG_UINT16 ui32CursorHeight;
+#endif
+} DISPLAY_INFO;
+
+typedef struct ACCESS_INFO_TAG
+{
+ IMG_UINT32 ui32Size;
+ IMG_UINT32 ui32FBPhysBaseAddress;
+ IMG_UINT32 ui32FBMemAvailable;
+ IMG_UINT32 ui32SysPhysBaseAddress;
+ IMG_UINT32 ui32SysSize;
+ IMG_UINT32 ui32DevIRQ;
+}ACCESS_INFO;
+
+
+
+#if defined(PDUMP_SUSPEND_IS_PER_THREAD)
+typedef struct {
+ IMG_UINT32 threadId;
+ IMG_INT suspendCount;
+} PVRSRV_THREAD_SUSPEND_COUNT;
+
+#define PVRSRV_PDUMP_SUSPEND_Q_NAME "PVRSRVPDumpSuspendMsgQ"
+#define PVRSRV_PDUMP_SUSPEND_Q_LENGTH 8
+
+#endif
+
+
+typedef struct _PVRSRV_REGISTRY_INFO_
+{
+ IMG_UINT32 ui32DevCookie;
+ IMG_PCHAR pszKey;
+ IMG_PCHAR pszValue;
+ IMG_PCHAR pszBuf;
+ IMG_UINT32 ui32BufSize;
+} PVRSRV_REGISTRY_INFO, *PPVRSRV_REGISTRY_INFO;
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVReadRegistryString (PPVRSRV_REGISTRY_INFO psRegInfo);
+PVRSRV_ERROR IMG_CALLCONV PVRSRVWriteRegistryString (PPVRSRV_REGISTRY_INFO psRegInfo);
+
+
+#define PVRSRV_BC_FLAGS_YUVCSC_CONFORMANT_RANGE (0 << 0)
+#define PVRSRV_BC_FLAGS_YUVCSC_FULL_RANGE (1 << 0)
+
+#define PVRSRV_BC_FLAGS_YUVCSC_BT601 (0 << 1)
+#define PVRSRV_BC_FLAGS_YUVCSC_BT709 (1 << 1)
+
+#define MAX_BUFFER_DEVICE_NAME_SIZE (50)
+
+typedef struct BUFFER_INFO_TAG
+{
+ IMG_UINT32 ui32BufferCount;
+ IMG_UINT32 ui32BufferDeviceID;
+ PVRSRV_PIXEL_FORMAT pixelformat;
+ IMG_UINT32 ui32ByteStride;
+ IMG_UINT32 ui32Width;
+ IMG_UINT32 ui32Height;
+ IMG_UINT32 ui32Flags;
+ IMG_CHAR szDeviceName[MAX_BUFFER_DEVICE_NAME_SIZE];
+} BUFFER_INFO;
+
+typedef enum _OVERLAY_DEINTERLACE_MODE_
+{
+ WEAVE=0x0,
+ BOB_ODD,
+ BOB_EVEN,
+ BOB_EVEN_NONINTERLEAVED
+} OVERLAY_DEINTERLACE_MODE;
+
+#endif
diff --git a/drivers/gpu/pvr/servicesint.h b/drivers/gpu/pvr/servicesint.h
new file mode 100644
index 0000000..afe2bcf
--- /dev/null
+++ b/drivers/gpu/pvr/servicesint.h
@@ -0,0 +1,377 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#if !defined (__SERVICESINT_H__)
+#define __SERVICESINT_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "services.h"
+#include "sysinfo.h"
+#include "sysconfig.h"
+
+#define HWREC_DEFAULT_TIMEOUT (500)
+
+#define DRIVERNAME_MAXLENGTH (100)
+
+#define ALIGNSIZE(size, alignshift) (((size) + ((1UL << (alignshift))-1)) & ~((1UL << (alignshift))-1))
+
+#ifndef MAX
+#define MAX(a,b) (((a) > (b)) ? (a) : (b))
+#endif
+#ifndef MIN
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#define MAX_CLEANUP_TIME_US (MAX_HW_TIME_US * 4)
+#define MAX_CLEANUP_TRYS 100
+#define MAX_CLEANUP_TIME_WAIT_US (MAX_CLEANUP_TIME_US/MAX_CLEANUP_TRYS)
+
+typedef enum _PVRSRV_MEMTYPE_
+{
+ PVRSRV_MEMTYPE_UNKNOWN = 0,
+ PVRSRV_MEMTYPE_DEVICE = 1,
+ PVRSRV_MEMTYPE_DEVICECLASS = 2,
+ PVRSRV_MEMTYPE_WRAPPED = 3,
+ PVRSRV_MEMTYPE_MAPPED = 4,
+} PVRSRV_MEMTYPE;
+
+typedef struct _PVRSRV_KERNEL_MEM_INFO_
+{
+
+ IMG_PVOID pvLinAddrKM;
+
+
+ IMG_DEV_VIRTADDR sDevVAddr;
+
+
+ IMG_UINT32 ui32Flags;
+
+
+ IMG_SIZE_T uAllocSize;
+
+
+ PVRSRV_MEMBLK sMemBlk;
+
+
+ IMG_PVOID pvSysBackupBuffer;
+
+
+ IMG_UINT32 ui32RefCount;
+
+
+ IMG_BOOL bPendingFree;
+
+
+#if defined(SUPPORT_MEMINFO_IDS)
+ #if !defined(USE_CODE)
+
+ IMG_UINT64 ui64Stamp;
+ #else
+ IMG_UINT32 dummy1;
+ IMG_UINT32 dummy2;
+ #endif
+#endif
+
+
+ struct _PVRSRV_KERNEL_SYNC_INFO_ *psKernelSyncInfo;
+
+ PVRSRV_MEMTYPE memType;
+
+
+
+
+
+
+
+
+ struct {
+
+
+ IMG_BOOL bInUse;
+
+
+ IMG_HANDLE hDevCookieInt;
+
+
+ IMG_UINT32 ui32ShareIndex;
+
+
+
+ IMG_UINT32 ui32OrigReqAttribs;
+ IMG_UINT32 ui32OrigReqSize;
+ IMG_UINT32 ui32OrigReqAlignment;
+ } sShareMemWorkaround;
+} PVRSRV_KERNEL_MEM_INFO;
+
+
+typedef struct _PVRSRV_KERNEL_SYNC_INFO_
+{
+
+ PVRSRV_SYNC_DATA *psSyncData;
+
+
+ IMG_DEV_VIRTADDR sWriteOpsCompleteDevVAddr;
+
+
+ IMG_DEV_VIRTADDR sReadOpsCompleteDevVAddr;
+
+
+ IMG_DEV_VIRTADDR sReadOps2CompleteDevVAddr;
+
+
+ PVRSRV_KERNEL_MEM_INFO *psSyncDataMemInfoKM;
+
+
+
+ IMG_PVOID pvRefCount;
+
+
+ IMG_HANDLE hResItem;
+
+
+ IMG_UINT32 ui32UID;
+} PVRSRV_KERNEL_SYNC_INFO;
+
+typedef struct _PVRSRV_DEVICE_SYNC_OBJECT_
+{
+
+ IMG_UINT32 ui32ReadOpsPendingVal;
+ IMG_DEV_VIRTADDR sReadOpsCompleteDevVAddr;
+ IMG_UINT32 ui32WriteOpsPendingVal;
+ IMG_DEV_VIRTADDR sWriteOpsCompleteDevVAddr;
+ IMG_UINT32 ui32ReadOps2PendingVal;
+ IMG_DEV_VIRTADDR sReadOps2CompleteDevVAddr;
+} PVRSRV_DEVICE_SYNC_OBJECT;
+
+typedef struct _PVRSRV_SYNC_OBJECT
+{
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfoKM;
+ IMG_UINT32 ui32WriteOpsPending;
+ IMG_UINT32 ui32ReadOpsPending;
+ IMG_UINT32 ui32ReadOps2Pending;
+
+}PVRSRV_SYNC_OBJECT, *PPVRSRV_SYNC_OBJECT;
+
+typedef struct _PVRSRV_COMMAND
+{
+ IMG_SIZE_T uCmdSize;
+ IMG_UINT32 ui32DevIndex;
+ IMG_UINT32 CommandType;
+ IMG_UINT32 ui32DstSyncCount;
+ IMG_UINT32 ui32SrcSyncCount;
+ PVRSRV_SYNC_OBJECT *psDstSync;
+ PVRSRV_SYNC_OBJECT *psSrcSync;
+ IMG_SIZE_T uDataSize;
+ IMG_UINT32 ui32ProcessID;
+ IMG_VOID *pvData;
+ PFN_QUEUE_COMMAND_COMPLETE pfnCommandComplete;
+ IMG_HANDLE hCallbackData;
+}PVRSRV_COMMAND, *PPVRSRV_COMMAND;
+
+
+typedef struct _PVRSRV_QUEUE_INFO_
+{
+ IMG_VOID *pvLinQueueKM;
+ IMG_VOID *pvLinQueueUM;
+ volatile IMG_SIZE_T ui32ReadOffset;
+ volatile IMG_SIZE_T ui32WriteOffset;
+ IMG_UINT32 *pui32KickerAddrKM;
+ IMG_UINT32 *pui32KickerAddrUM;
+ IMG_SIZE_T ui32QueueSize;
+
+ IMG_UINT32 ui32ProcessID;
+
+ IMG_HANDLE hMemBlock[2];
+
+ struct _PVRSRV_QUEUE_INFO_ *psNextKM;
+}PVRSRV_QUEUE_INFO;
+
+
+typedef struct _PVRSRV_HEAP_INFO_KM_
+{
+ IMG_UINT32 ui32HeapID;
+ IMG_DEV_VIRTADDR sDevVAddrBase;
+
+ IMG_HANDLE hDevMemHeap;
+ IMG_UINT32 ui32HeapByteSize;
+ IMG_UINT32 ui32Attribs;
+ IMG_UINT32 ui32XTileStride;
+}PVRSRV_HEAP_INFO_KM;
+
+
+typedef struct _PVRSRV_EVENTOBJECT_KM_
+{
+
+ IMG_CHAR szName[EVENTOBJNAME_MAXLENGTH];
+
+ IMG_HANDLE hOSEventKM;
+
+} PVRSRV_EVENTOBJECT_KM;
+
+
+typedef struct _PVRSRV_MISC_INFO_KM_
+{
+ IMG_UINT32 ui32StateRequest;
+ IMG_UINT32 ui32StatePresent;
+
+
+ IMG_VOID *pvSOCTimerRegisterKM;
+ IMG_VOID *pvSOCTimerRegisterUM;
+ IMG_HANDLE hSOCTimerRegisterOSMemHandle;
+ IMG_HANDLE hSOCTimerRegisterMappingInfo;
+
+
+ IMG_VOID *pvSOCClockGateRegs;
+ IMG_UINT32 ui32SOCClockGateRegsSize;
+
+
+ IMG_CHAR *pszMemoryStr;
+ IMG_UINT32 ui32MemoryStrLen;
+
+
+ PVRSRV_EVENTOBJECT_KM sGlobalEventObject;
+ IMG_HANDLE hOSGlobalEvent;
+
+
+ IMG_UINT32 aui32DDKVersion[4];
+
+
+ struct
+ {
+
+ IMG_BOOL bDeferOp;
+
+
+ PVRSRV_MISC_INFO_CPUCACHEOP_TYPE eCacheOpType;
+
+
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+
+ IMG_VOID *pvBaseVAddr;
+
+
+ IMG_UINT32 ui32Length;
+ } sCacheOpCtl;
+
+
+ struct
+ {
+
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+
+ IMG_UINT32 ui32RefCount;
+ } sGetRefCountCtl;
+} PVRSRV_MISC_INFO_KM;
+
+
+typedef PVRSRV_ERROR (*PFN_INSERT_CMD) (PVRSRV_QUEUE_INFO*,
+ PVRSRV_COMMAND**,
+ IMG_UINT32,
+ IMG_UINT16,
+ IMG_UINT32,
+ PVRSRV_KERNEL_SYNC_INFO*[],
+ IMG_UINT32,
+ PVRSRV_KERNEL_SYNC_INFO*[],
+ IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_SUBMIT_CMD) (PVRSRV_QUEUE_INFO*, PVRSRV_COMMAND*, IMG_BOOL);
+
+
+typedef struct PVRSRV_DEVICECLASS_BUFFER_TAG
+{
+ PFN_GET_BUFFER_ADDR pfnGetBufferAddr;
+ IMG_HANDLE hDevMemContext;
+ IMG_HANDLE hExtDevice;
+ IMG_HANDLE hExtBuffer;
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+ IMG_UINT32 ui32MemMapRefCount;
+} PVRSRV_DEVICECLASS_BUFFER;
+
+
+typedef struct PVRSRV_CLIENT_DEVICECLASS_INFO_TAG
+{
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDeviceKM;
+#else
+ IMG_HANDLE hDeviceKM;
+#endif
+ IMG_HANDLE hServices;
+} PVRSRV_CLIENT_DEVICECLASS_INFO;
+
+
+typedef enum
+{
+ PVRSRV_FREE_CALLBACK_ORIGIN_ALLOCATOR,
+ PVRSRV_FREE_CALLBACK_ORIGIN_IMPORTER,
+ PVRSRV_FREE_CALLBACK_ORIGIN_EXTERNAL,
+}
+PVRSRV_FREE_CALLBACK_ORIGIN;
+
+
+IMG_IMPORT
+PVRSRV_ERROR FreeMemCallBackCommon(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Param,
+ PVRSRV_FREE_CALLBACK_ORIGIN eCallbackOrigin);
+
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVQueueCommand(IMG_HANDLE hQueueInfo,
+ PVRSRV_COMMAND *psCommand);
+
+
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV
+PVRSRVAllocSharedSysMem(const PVRSRV_CONNECTION *psConnection,
+ IMG_UINT32 ui32Flags,
+ IMG_SIZE_T ui32Size,
+ PVRSRV_CLIENT_MEM_INFO **ppsClientMemInfo);
+
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV
+PVRSRVFreeSharedSysMem(const PVRSRV_CONNECTION *psConnection,
+ PVRSRV_CLIENT_MEM_INFO *psClientMemInfo);
+
+IMG_IMPORT PVRSRV_ERROR
+PVRSRVUnrefSharedSysMem(const PVRSRV_CONNECTION *psConnection,
+ PVRSRV_CLIENT_MEM_INFO *psClientMemInfo);
+
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV
+PVRSRVMapMemInfoMem(const PVRSRV_CONNECTION *psConnection,
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelMemInfo,
+#else
+ IMG_HANDLE hKernelMemInfo,
+#endif
+ PVRSRV_CLIENT_MEM_INFO **ppsClientMemInfo);
+
+
+#if defined (__cplusplus)
+}
+#endif
+#endif
+
diff --git a/drivers/gpu/pvr/sgx/bridged_sgx_bridge.c b/drivers/gpu/pvr/sgx/bridged_sgx_bridge.c
new file mode 100644
index 0000000..4e4cf24
--- /dev/null
+++ b/drivers/gpu/pvr/sgx/bridged_sgx_bridge.c
@@ -0,0 +1,3764 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+
+
+#include <stddef.h>
+
+#include "img_defs.h"
+
+#if defined(SUPPORT_SGX)
+
+#include "services.h"
+#include "pvr_debug.h"
+#include "pvr_bridge.h"
+#include "sgx_bridge.h"
+#include "perproc.h"
+#include "power.h"
+#include "pvr_bridge_km.h"
+#include "sgx_bridge_km.h"
+#include "sgx_options.h"
+
+#if defined(SUPPORT_MSVDX)
+ #include "msvdx_bridge.h"
+#endif
+
+#include "bridged_pvr_bridge.h"
+#include "bridged_sgx_bridge.h"
+#include "sgxutils.h"
+#include "buffer_manager.h"
+#include "pdump_km.h"
+
+static IMG_INT
+SGXGetClientInfoBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GETCLIENTINFO *psGetClientInfoIN,
+ PVRSRV_BRIDGE_OUT_GETCLIENTINFO *psGetClientInfoOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_GETCLIENTINFO);
+
+ psGetClientInfoOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psGetClientInfoIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psGetClientInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psGetClientInfoOUT->eError =
+ SGXGetClientInfoKM(hDevCookieInt,
+ &psGetClientInfoOUT->sClientInfo);
+ return 0;
+}
+
+static IMG_INT
+SGXReleaseClientInfoBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RELEASECLIENTINFO *psReleaseClientInfoIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+ IMG_HANDLE hDevCookieInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_RELEASECLIENTINFO);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psReleaseClientInfoIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookieInt)->pvDevice;
+
+ PVR_ASSERT(psDevInfo->ui32ClientRefCount > 0);
+
+
+ if (psDevInfo->ui32ClientRefCount > 0)
+ {
+ psDevInfo->ui32ClientRefCount--;
+ }
+
+ psRetOUT->eError = PVRSRV_OK;
+
+ return 0;
+}
+
+
+static IMG_INT
+SGXGetInternalDevInfoBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GETINTERNALDEVINFO *psSGXGetInternalDevInfoIN,
+ PVRSRV_BRIDGE_OUT_GETINTERNALDEVINFO *psSGXGetInternalDevInfoOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+#if defined (SUPPORT_SID_INTERFACE)
+ SGX_INTERNAL_DEVINFO_KM sSGXInternalDevInfo;
+#endif
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_GETINTERNALDEVINFO);
+
+ psSGXGetInternalDevInfoOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXGetInternalDevInfoIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psSGXGetInternalDevInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psSGXGetInternalDevInfoOUT->eError =
+ SGXGetInternalDevInfoKM(hDevCookieInt,
+#if defined (SUPPORT_SID_INTERFACE)
+ &sSGXInternalDevInfo);
+#else
+ &psSGXGetInternalDevInfoOUT->sSGXInternalDevInfo);
+#endif
+
+
+ psSGXGetInternalDevInfoOUT->eError =
+ PVRSRVAllocHandle(psPerProc->psHandleBase,
+ &psSGXGetInternalDevInfoOUT->sSGXInternalDevInfo.hHostCtlKernelMemInfoHandle,
+#if defined (SUPPORT_SID_INTERFACE)
+ sSGXInternalDevInfo.hHostCtlKernelMemInfoHandle,
+#else
+ psSGXGetInternalDevInfoOUT->sSGXInternalDevInfo.hHostCtlKernelMemInfoHandle,
+#endif
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+
+ return 0;
+}
+
+
+static IMG_INT
+SGXDoKickBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DOKICK *psDoKickIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_UINT32 i;
+ IMG_INT ret = 0;
+ IMG_UINT32 ui32NumDstSyncs;
+#if defined (SUPPORT_SID_INTERFACE)
+ SGX_CCB_KICK_KM sCCBKickKM = {{0}};
+ IMG_HANDLE ahSyncInfoHandles[16];
+#else
+ IMG_HANDLE *phKernelSyncInfoHandles = IMG_NULL;
+#endif
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_DOKICK);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psDoKickIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &sCCBKickKM.hCCBKernelMemInfo,
+#else
+ &psDoKickIN->sCCBKick.hCCBKernelMemInfo,
+#endif
+ psDoKickIN->sCCBKick.hCCBKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+#if defined (SUPPORT_SID_INTERFACE)
+ if (psDoKickIN->sCCBKick.ui32NumDstSyncObjects > 16)
+ {
+ return 0;
+ }
+
+ if(psDoKickIN->sCCBKick.hTA3DSyncInfo != 0)
+#else
+ if(psDoKickIN->sCCBKick.hTA3DSyncInfo != IMG_NULL)
+#endif
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &sCCBKickKM.hTA3DSyncInfo,
+#else
+ &psDoKickIN->sCCBKick.hTA3DSyncInfo,
+#endif
+ psDoKickIN->sCCBKick.hTA3DSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+#if defined (SUPPORT_SID_INTERFACE)
+ if(psDoKickIN->sCCBKick.hTASyncInfo != 0)
+#else
+ if(psDoKickIN->sCCBKick.hTASyncInfo != IMG_NULL)
+#endif
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &sCCBKickKM.hTASyncInfo,
+#else
+ &psDoKickIN->sCCBKick.hTASyncInfo,
+#endif
+ psDoKickIN->sCCBKick.hTASyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+#if defined(FIX_HW_BRN_31620)
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.hDevMemContext,
+ psDoKickIN->sCCBKick.hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+#endif
+
+#if defined (SUPPORT_SID_INTERFACE)
+ if(psDoKickIN->sCCBKick.h3DSyncInfo != 0)
+#else
+ if(psDoKickIN->sCCBKick.h3DSyncInfo != IMG_NULL)
+#endif
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &sCCBKickKM.h3DSyncInfo,
+#else
+ &psDoKickIN->sCCBKick.h3DSyncInfo,
+#endif
+ psDoKickIN->sCCBKick.h3DSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+
+ if (psDoKickIN->sCCBKick.ui32NumTASrcSyncs > SGX_MAX_TA_SRC_SYNCS)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+
+#if defined (SUPPORT_SID_INTERFACE)
+ sCCBKickKM.ui32NumTASrcSyncs = psDoKickIN->sCCBKick.ui32NumTASrcSyncs;
+#endif
+ for(i=0; i<psDoKickIN->sCCBKick.ui32NumTASrcSyncs; i++)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &sCCBKickKM.ahTASrcKernelSyncInfo[i],
+#else
+ &psDoKickIN->sCCBKick.ahTASrcKernelSyncInfo[i],
+#endif
+ psDoKickIN->sCCBKick.ahTASrcKernelSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if (psDoKickIN->sCCBKick.ui32NumTADstSyncs > SGX_MAX_TA_DST_SYNCS)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+
+#if defined (SUPPORT_SID_INTERFACE)
+ sCCBKickKM.ui32NumTADstSyncs = psDoKickIN->sCCBKick.ui32NumTADstSyncs;
+#endif
+ for(i=0; i<psDoKickIN->sCCBKick.ui32NumTADstSyncs; i++)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &sCCBKickKM.ahTADstKernelSyncInfo[i],
+#else
+ &psDoKickIN->sCCBKick.ahTADstKernelSyncInfo[i],
+#endif
+ psDoKickIN->sCCBKick.ahTADstKernelSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if (psDoKickIN->sCCBKick.ui32Num3DSrcSyncs > SGX_MAX_3D_SRC_SYNCS)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+
+#if defined (SUPPORT_SID_INTERFACE)
+ sCCBKickKM.ui32Num3DSrcSyncs = psDoKickIN->sCCBKick.ui32Num3DSrcSyncs;
+#endif
+ for(i=0; i<psDoKickIN->sCCBKick.ui32Num3DSrcSyncs; i++)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &sCCBKickKM.ah3DSrcKernelSyncInfo[i],
+#else
+ &psDoKickIN->sCCBKick.ah3DSrcKernelSyncInfo[i],
+#endif
+ psDoKickIN->sCCBKick.ah3DSrcKernelSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+#else
+
+ if (psDoKickIN->sCCBKick.ui32NumSrcSyncs > SGX_MAX_SRC_SYNCS_TA)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+
+#if defined (SUPPORT_SID_INTERFACE)
+ sCCBKickKM.ui32NumSrcSyncs = psDoKickIN->sCCBKick.ui32NumSrcSyncs;
+#endif
+ for(i=0; i<psDoKickIN->sCCBKick.ui32NumSrcSyncs; i++)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &sCCBKickKM.ahSrcKernelSyncInfo[i],
+#else
+ &psDoKickIN->sCCBKick.ahSrcKernelSyncInfo[i],
+#endif
+ psDoKickIN->sCCBKick.ahSrcKernelSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+#endif
+
+ if (psDoKickIN->sCCBKick.ui32NumTAStatusVals > SGX_MAX_TA_STATUS_VALS)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+ for (i = 0; i < psDoKickIN->sCCBKick.ui32NumTAStatusVals; i++)
+ {
+ psRetOUT->eError =
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &sCCBKickKM.asTAStatusUpdate[i].hKernelMemInfo,
+#else
+ &psDoKickIN->sCCBKick.asTAStatusUpdate[i].hKernelMemInfo,
+#endif
+ psDoKickIN->sCCBKick.asTAStatusUpdate[i].hKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+#if defined (SUPPORT_SID_INTERFACE)
+ sCCBKickKM.asTAStatusUpdate[i].sCtlStatus = psDoKickIN->sCCBKick.asTAStatusUpdate[i].sCtlStatus;
+#endif
+
+#else
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &sCCBKickKM.ahTAStatusSyncInfo[i],
+#else
+ &psDoKickIN->sCCBKick.ahTAStatusSyncInfo[i],
+#endif
+ psDoKickIN->sCCBKick.ahTAStatusSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+#endif
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if (psDoKickIN->sCCBKick.ui32Num3DStatusVals > SGX_MAX_3D_STATUS_VALS)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+ for(i = 0; i < psDoKickIN->sCCBKick.ui32Num3DStatusVals; i++)
+ {
+ psRetOUT->eError =
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &sCCBKickKM.as3DStatusUpdate[i].hKernelMemInfo,
+#else
+ &psDoKickIN->sCCBKick.as3DStatusUpdate[i].hKernelMemInfo,
+#endif
+ psDoKickIN->sCCBKick.as3DStatusUpdate[i].hKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+#if defined (SUPPORT_SID_INTERFACE)
+ sCCBKickKM.as3DStatusUpdate[i].sCtlStatus = psDoKickIN->sCCBKick.as3DStatusUpdate[i].sCtlStatus;
+#endif
+#else
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &sCCBKickKM.ah3DStatusSyncInfo[i],
+#else
+ &psDoKickIN->sCCBKick.ah3DStatusSyncInfo[i],
+#endif
+ psDoKickIN->sCCBKick.ah3DStatusSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+#endif
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ ui32NumDstSyncs = psDoKickIN->sCCBKick.ui32NumDstSyncObjects;
+
+ if(ui32NumDstSyncs > 0)
+ {
+ if(!OSAccessOK(PVR_VERIFY_READ,
+ psDoKickIN->sCCBKick.pahDstSyncHandles,
+ ui32NumDstSyncs * sizeof(IMG_HANDLE)))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: SGXDoKickBW:"
+ " Invalid pasDstSyncHandles pointer", __FUNCTION__));
+ return -EFAULT;
+ }
+
+ psRetOUT->eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32NumDstSyncs * sizeof(IMG_HANDLE),
+ (IMG_VOID **)&phKernelSyncInfoHandles,
+ 0,
+ "Array of Synchronization Info Handles");
+ if (psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+#if defined (SUPPORT_SID_INTERFACE)
+ sCCBKickKM.pahDstSyncHandles = phKernelSyncInfoHandles;
+#else
+ if(CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ phKernelSyncInfoHandles,
+ psDoKickIN->sCCBKick.pahDstSyncHandles,
+ ui32NumDstSyncs * sizeof(IMG_HANDLE)) != PVRSRV_OK)
+ {
+ ret = -EFAULT;
+ goto PVRSRV_BRIDGE_SGX_DOKICK_RETURN_RESULT;
+ }
+
+
+ psDoKickIN->sCCBKick.pahDstSyncHandles = phKernelSyncInfoHandles;
+#endif
+
+ for( i = 0; i < ui32NumDstSyncs; i++)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &sCCBKickKM.pahDstSyncHandles[i],
+#else
+ &psDoKickIN->sCCBKick.pahDstSyncHandles[i],
+#endif
+ psDoKickIN->sCCBKick.pahDstSyncHandles[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_DOKICK_RETURN_RESULT;
+ }
+
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &sCCBKickKM.hKernelHWSyncListMemInfo,
+#else
+ &psDoKickIN->sCCBKick.hKernelHWSyncListMemInfo,
+#endif
+ psDoKickIN->sCCBKick.hKernelHWSyncListMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_DOKICK_RETURN_RESULT;
+ }
+ }
+
+#if defined (SUPPORT_SID_INTERFACE)
+ OSMemCopy(&sCCBKickKM.sCommand, &psDoKickIN->sCCBKick.sCommand, sizeof(sCCBKickKM.sCommand));
+
+ sCCBKickKM.ui32NumDstSyncObjects = psDoKickIN->sCCBKick.ui32NumDstSyncObjects;
+ sCCBKickKM.ui32NumTAStatusVals = psDoKickIN->sCCBKick.ui32NumTAStatusVals;
+ sCCBKickKM.ui32Num3DStatusVals = psDoKickIN->sCCBKick.ui32Num3DStatusVals;
+ sCCBKickKM.bFirstKickOrResume = psDoKickIN->sCCBKick.bFirstKickOrResume;
+ sCCBKickKM.ui32CCBOffset = psDoKickIN->sCCBKick.ui32CCBOffset;
+ sCCBKickKM.bTADependency = psDoKickIN->sCCBKick.bTADependency;
+
+#if (defined(NO_HARDWARE) || defined(PDUMP))
+ sCCBKickKM.bTerminateOrAbort = psDoKickIN->sCCBKick.bTerminateOrAbort;
+#endif
+#if defined(PDUMP)
+ sCCBKickKM.ui32CCBDumpWOff = psDoKickIN->sCCBKick.ui32CCBDumpWOff;
+#endif
+
+#if defined(NO_HARDWARE)
+ sCCBKickKM.ui32WriteOpsPendingVal = psDoKickIN->sCCBKick.ui32WriteOpsPendingVal;
+#endif
+#endif
+ psRetOUT->eError =
+ SGXDoKickKM(hDevCookieInt,
+#if defined (SUPPORT_SID_INTERFACE)
+ &sCCBKickKM);
+#else
+ &psDoKickIN->sCCBKick);
+#endif
+
+PVRSRV_BRIDGE_SGX_DOKICK_RETURN_RESULT:
+
+ if(phKernelSyncInfoHandles)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32NumDstSyncs * sizeof(IMG_HANDLE),
+ (IMG_VOID *)phKernelSyncInfoHandles,
+ 0);
+
+ }
+ return ret;
+}
+
+
+static IMG_INT
+SGXScheduleProcessQueuesBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_SCHEDULE_PROCESS_QUEUES *psScheduleProcQIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_SCHEDULE_PROCESS_QUEUES);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psScheduleProcQIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = SGXScheduleProcessQueuesKM(hDevCookieInt);
+
+ return 0;
+}
+
+
+#if defined(TRANSFER_QUEUE)
+static IMG_INT
+SGXSubmitTransferBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SUBMITTRANSFER *psSubmitTransferIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ PVRSRV_TRANSFER_SGX_KICK *psKick;
+#if defined (SUPPORT_SID_INTERFACE)
+ PVRSRV_TRANSFER_SGX_KICK_KM sKickKM = {0};
+#endif
+ IMG_UINT32 i;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_SUBMITTRANSFER);
+ PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+
+ psKick = &psSubmitTransferIN->sKick;
+
+#if defined(FIX_HW_BRN_31620)
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psKick->hDevMemContext,
+ psKick->hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+#endif
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSubmitTransferIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &sKickKM.hCCBMemInfo,
+#else
+ &psKick->hCCBMemInfo,
+#endif
+ psKick->hCCBMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ if (psKick->hTASyncInfo != IMG_NULL)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &sKickKM.hTASyncInfo,
+#else
+ &psKick->hTASyncInfo,
+#endif
+ psKick->hTASyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if (psKick->h3DSyncInfo != IMG_NULL)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &sKickKM.h3DSyncInfo,
+#else
+ &psKick->h3DSyncInfo,
+#endif
+ psKick->h3DSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if (psKick->ui32NumSrcSync > SGX_MAX_TRANSFER_SYNC_OPS)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+ for (i = 0; i < psKick->ui32NumSrcSync; i++)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &sKickKM.ahSrcSyncInfo[i],
+#else
+ &psKick->ahSrcSyncInfo[i],
+#endif
+ psKick->ahSrcSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if (psKick->ui32NumDstSync > SGX_MAX_TRANSFER_SYNC_OPS)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+ for (i = 0; i < psKick->ui32NumDstSync; i++)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &sKickKM.ahDstSyncInfo[i],
+#else
+ &psKick->ahDstSyncInfo[i],
+#endif
+ psKick->ahDstSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+#if defined (SUPPORT_SID_INTERFACE)
+ sKickKM.sHWTransferContextDevVAddr = psKick->sHWTransferContextDevVAddr;
+ sKickKM.ui32SharedCmdCCBOffset = psKick->ui32SharedCmdCCBOffset;
+ sKickKM.ui32NumSrcSync = psKick->ui32NumSrcSync;
+ sKickKM.ui32NumDstSync = psKick->ui32NumDstSync;
+ sKickKM.ui32Flags = psKick->ui32Flags;
+ sKickKM.ui32PDumpFlags = psKick->ui32PDumpFlags;
+#if defined(PDUMP)
+ sKickKM.ui32CCBDumpWOff = psKick->ui32CCBDumpWOff;
+#endif
+
+ psRetOUT->eError = SGXSubmitTransferKM(hDevCookieInt, &sKickKM);
+#else
+ psRetOUT->eError = SGXSubmitTransferKM(hDevCookieInt, psKick);
+#endif
+
+ return 0;
+}
+
+static IMG_INT
+SGXSetTransferContextPriorityBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_SET_TRANSFER_CONTEXT_PRIORITY *psSGXSetTransferContextPriorityIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_HANDLE hTransferContextInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_SET_TRANSFER_CONTEXT_PRIORITY);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXSetTransferContextPriorityIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hTransferContextInt,
+ psSGXSetTransferContextPriorityIN->hHWTransferContext,
+ PVRSRV_HANDLE_TYPE_SGX_HW_TRANSFER_CONTEXT);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = SGXSetTransferContextPriorityKM(
+ hDevCookieInt,
+ hTransferContextInt,
+ psSGXSetTransferContextPriorityIN->ui32Priority,
+ psSGXSetTransferContextPriorityIN->ui32OffsetOfPriorityField);
+
+ return 0;
+}
+
+static IMG_INT
+SGXSetRenderContextPriorityBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_SET_RENDER_CONTEXT_PRIORITY *psSGXSetRenderContextPriorityIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_HANDLE hRenderContextInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_SET_RENDER_CONTEXT_PRIORITY);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXSetRenderContextPriorityIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hRenderContextInt,
+ psSGXSetRenderContextPriorityIN->hHWRenderContext,
+ PVRSRV_HANDLE_TYPE_SGX_HW_RENDER_CONTEXT);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = SGXSetRenderContextPriorityKM(
+ hDevCookieInt,
+ hRenderContextInt,
+ psSGXSetRenderContextPriorityIN->ui32Priority,
+ psSGXSetRenderContextPriorityIN->ui32OffsetOfPriorityField);
+
+ return 0;
+}
+
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+static IMG_INT
+SGXSubmit2DBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SUBMIT2D *psSubmit2DIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ PVRSRV_2D_SGX_KICK *psKick;
+#if defined (SUPPORT_SID_INTERFACE)
+ PVRSRV_2D_SGX_KICK_KM sKickKM;
+#endif
+ IMG_UINT32 i;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_SUBMIT2D);
+ PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+
+ psKick = &psSubmit2DIN->sKick;
+
+#if defined(FIX_HW_BRN_31620)
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psKick->hDevMemContext,
+ psKick->hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+#endif
+
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSubmit2DIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &sKickKM.hCCBMemInfo,
+#else
+ &psKick->hCCBMemInfo,
+#endif
+ psKick->hCCBMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+#if defined (SUPPORT_SID_INTERFACE)
+ if (psKick->hTASyncInfo != 0)
+#else
+ if (psKick->hTASyncInfo != IMG_NULL)
+#endif
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &sKickKM.hTASyncInfo,
+#else
+ &psKick->hTASyncInfo,
+#endif
+ psKick->hTASyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+#if defined (SUPPORT_SID_INTERFACE)
+ else
+ {
+ sKickKM.hTASyncInfo = IMG_NULL;
+ }
+#endif
+
+ if (psKick->h3DSyncInfo != IMG_NULL)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &sKickKM.h3DSyncInfo,
+#else
+ &psKick->h3DSyncInfo,
+#endif
+ psKick->h3DSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+#if defined (SUPPORT_SID_INTERFACE)
+ else
+ {
+ sKickKM.h3DSyncInfo = IMG_NULL;
+ }
+#endif
+
+ if (psKick->ui32NumSrcSync > SGX_MAX_2D_SRC_SYNC_OPS)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+#if defined (SUPPORT_SID_INTERFACE)
+ for (i = 0; i < SGX_MAX_2D_SRC_SYNC_OPS; i++)
+ {
+ if (i < psKick->ui32NumSrcSync)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &sKickKM.ahSrcSyncInfo[i],
+ psKick->ahSrcSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+ else
+ {
+ sKickKM.ahSrcSyncInfo[i] = IMG_NULL;
+ }
+ }
+#else
+ for (i = 0; i < psKick->ui32NumSrcSync; i++)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psKick->ahSrcSyncInfo[i],
+ psKick->ahSrcSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+#endif
+
+ if (psKick->hDstSyncInfo != IMG_NULL)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &sKickKM.hDstSyncInfo,
+#else
+ &psKick->hDstSyncInfo,
+#endif
+ psKick->hDstSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+#if defined (SUPPORT_SID_INTERFACE)
+ else
+ {
+ sKickKM.hDstSyncInfo = IMG_NULL;
+ }
+
+
+ sKickKM.ui32SharedCmdCCBOffset = psKick->ui32SharedCmdCCBOffset;
+ sKickKM.ui32NumSrcSync = psKick->ui32NumSrcSync;
+ sKickKM.ui32PDumpFlags = psKick->ui32PDumpFlags;
+ sKickKM.sHW2DContextDevVAddr = psKick->sHW2DContextDevVAddr;
+#if defined(PDUMP)
+ sKickKM.ui32CCBDumpWOff = psKick->ui32CCBDumpWOff;
+#endif
+#endif
+
+ psRetOUT->eError =
+#if defined (SUPPORT_SID_INTERFACE)
+ SGXSubmit2DKM(hDevCookieInt, &sKickKM);
+#else
+ SGXSubmit2DKM(hDevCookieInt, psKick);
+#endif
+
+ return 0;
+}
+#endif
+#endif
+
+
+static IMG_INT
+SGXGetMiscInfoBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGXGETMISCINFO *psSGXGetMiscInfoIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_HANDLE hDevMemContextInt = 0;
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+ SGX_MISC_INFO sMiscInfo;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_SGX_GETMISCINFO);
+
+ psRetOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXGetMiscInfoIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+
+ if (psSGXGetMiscInfoIN->psMiscInfo->eRequest == SGX_MISC_INFO_REQUEST_MEMREAD)
+ {
+ psRetOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevMemContextInt,
+ psSGXGetMiscInfoIN->psMiscInfo->hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+#endif
+
+ psDeviceNode = hDevCookieInt;
+ PVR_ASSERT(psDeviceNode != IMG_NULL);
+ if (psDeviceNode == IMG_NULL)
+ {
+ return -EFAULT;
+ }
+
+ psDevInfo = psDeviceNode->pvDevice;
+
+
+ psRetOUT->eError = CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ &sMiscInfo,
+ psSGXGetMiscInfoIN->psMiscInfo,
+ sizeof(SGX_MISC_INFO));
+ if (psRetOUT->eError != PVRSRV_OK)
+ {
+ return -EFAULT;
+ }
+
+ {
+ psRetOUT->eError = SGXGetMiscInfoKM(psDevInfo, &sMiscInfo, psDeviceNode, hDevMemContextInt);
+
+ if (psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+
+ psRetOUT->eError = CopyToUserWrapper(psPerProc,
+ ui32BridgeID,
+ psSGXGetMiscInfoIN->psMiscInfo,
+ &sMiscInfo,
+ sizeof(SGX_MISC_INFO));
+ if (psRetOUT->eError != PVRSRV_OK)
+ {
+ return -EFAULT;
+ }
+ return 0;
+}
+
+
+static IMG_INT
+SGXReadHWPerfCBBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_READ_HWPERF_CB *psSGXReadHWPerfCBIN,
+ PVRSRV_BRIDGE_OUT_SGX_READ_HWPERF_CB *psSGXReadHWPerfCBOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ PVRSRV_SGX_HWPERF_CB_ENTRY *psAllocated;
+ IMG_HANDLE hAllocatedHandle;
+ IMG_UINT32 ui32AllocatedSize;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_READ_HWPERF_CB);
+
+ psSGXReadHWPerfCBOUT->eError =PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXReadHWPerfCBIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psSGXReadHWPerfCBOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ ui32AllocatedSize = psSGXReadHWPerfCBIN->ui32ArraySize *
+ sizeof(psSGXReadHWPerfCBIN->psHWPerfCBData[0]);
+ ASSIGN_AND_EXIT_ON_ERROR(psSGXReadHWPerfCBOUT->eError,
+ OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32AllocatedSize,
+ (IMG_VOID **)&psAllocated,
+ &hAllocatedHandle,
+ "Array of Hardware Performance Circular Buffer Data"));
+
+ psSGXReadHWPerfCBOUT->eError = SGXReadHWPerfCBKM(hDevCookieInt,
+ psSGXReadHWPerfCBIN->ui32ArraySize,
+ psAllocated,
+ &psSGXReadHWPerfCBOUT->ui32DataCount,
+ &psSGXReadHWPerfCBOUT->ui32ClockSpeed,
+ &psSGXReadHWPerfCBOUT->ui32HostTimeStamp);
+ if (psSGXReadHWPerfCBOUT->eError == PVRSRV_OK)
+ {
+ psSGXReadHWPerfCBOUT->eError = CopyToUserWrapper(psPerProc,
+ ui32BridgeID,
+ psSGXReadHWPerfCBIN->psHWPerfCBData,
+ psAllocated,
+ ui32AllocatedSize);
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32AllocatedSize,
+ psAllocated,
+ hAllocatedHandle);
+
+
+ return 0;
+}
+
+
+static IMG_INT
+SGXDevInitPart2BW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGXDEVINITPART2 *psSGXDevInitPart2IN,
+ PVRSRV_BRIDGE_OUT_SGXDEVINITPART2 *psSGXDevInitPart2OUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+#if defined (SUPPORT_SID_INTERFACE)
+ PVRSRV_ERROR eError = PVRSRV_OK;
+#else
+ PVRSRV_ERROR eError;
+#endif
+ IMG_BOOL bDissociateFailed = IMG_FALSE;
+ IMG_BOOL bLookupFailed = IMG_FALSE;
+ IMG_BOOL bReleaseFailed = IMG_FALSE;
+ IMG_HANDLE hDummy;
+ IMG_UINT32 i;
+#if defined (SUPPORT_SID_INTERFACE)
+ SGX_BRIDGE_INIT_INFO_KM asInitInfoKM = {0};
+#endif
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_DEVINITPART2);
+
+
+ psSGXDevInitPart2OUT->ui32KMBuildOptions = SGX_BUILD_OPTIONS;
+
+ if(!psPerProc->bInitProcess)
+ {
+ psSGXDevInitPart2OUT->eError = PVRSRV_ERROR_PROCESS_NOT_INITIALISED;
+ return 0;
+ }
+
+ psSGXDevInitPart2OUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXDevInitPart2IN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psSGXDevInitPart2OUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelCCBEventKickerMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+
+#if defined(FIX_HW_BRN_31272) || defined(FIX_HW_BRN_31780) || defined(FIX_HW_BRN_33920)
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelSGXPTLAWriteBackMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+#endif
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+
+#if defined(SGX_SUPPORT_HWPROFILING)
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelHWProfilingMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+#endif
+
+#if defined(SUPPORT_SGX_HWPERF)
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelHWPerfCBMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+#endif
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelTASigBufferMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernel3DSigBufferMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+
+#if defined(FIX_HW_BRN_29702)
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelCFIMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+#endif
+
+#if defined(FIX_HW_BRN_29823)
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelDummyTermStreamMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+#endif
+
+
+#if defined(FIX_HW_BRN_31542) || defined(FIX_HW_BRN_36513)
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAVDMStreamMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAIndexStreamMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAPDSMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAUSEMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAParamMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAPMPTMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWATPCMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAPSGRgnHdrMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+#endif
+
+#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && defined(FIX_HW_BRN_31559)
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelVDMSnapShotBufferMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelVDMCtrlStreamBufferMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+#endif
+#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && \
+ defined(FIX_HW_BRN_33657) && defined(SUPPORT_SECURE_33657_FIX)
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelVDMStateUpdateBufferMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+#endif
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelEDMStatusBufferMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+#endif
+
+ for (i = 0; i < SGX_MAX_INIT_MEM_HANDLES; i++)
+ {
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hHandle = psSGXDevInitPart2IN->sInitInfo.asInitMemHandles[i];
+#else
+ IMG_HANDLE hHandle = psSGXDevInitPart2IN->sInitInfo.asInitMemHandles[i];
+#endif
+
+#if defined (SUPPORT_SID_INTERFACE)
+ if (hHandle == 0)
+#else
+ if (hHandle == IMG_NULL)
+#endif
+ {
+ continue;
+ }
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ hHandle,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+ }
+
+ if (bLookupFailed)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DevInitSGXPart2BW: A handle lookup failed"));
+ psSGXDevInitPart2OUT->eError = PVRSRV_ERROR_INIT2_PHASE_FAILED;
+ return 0;
+ }
+
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &asInitInfoKM.hKernelCCBMemInfo,
+#else
+ &psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo,
+#endif
+ psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &asInitInfoKM.hKernelCCBCtlMemInfo,
+#else
+ &psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo,
+#endif
+ psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &asInitInfoKM.hKernelCCBEventKickerMemInfo,
+#else
+ &psSGXDevInitPart2IN->sInitInfo.hKernelCCBEventKickerMemInfo,
+#endif
+ psSGXDevInitPart2IN->sInitInfo.hKernelCCBEventKickerMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &asInitInfoKM.hKernelSGXHostCtlMemInfo,
+#else
+ &psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo,
+#endif
+ psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &asInitInfoKM.hKernelSGXTA3DCtlMemInfo,
+#else
+ &psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo,
+#endif
+ psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+
+#if defined(FIX_HW_BRN_31272) || defined(FIX_HW_BRN_31780) || defined(FIX_HW_BRN_33920)
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &asInitInfoKM.hKernelSGXPTLAWriteBackMemInfo,
+#else
+ &psSGXDevInitPart2IN->sInitInfo.hKernelSGXPTLAWriteBackMemInfo,
+#endif
+ psSGXDevInitPart2IN->sInitInfo.hKernelSGXPTLAWriteBackMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+#endif
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &asInitInfoKM.hKernelSGXMiscMemInfo,
+#else
+ &psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo,
+#endif
+ psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+
+
+#if defined(SGX_SUPPORT_HWPROFILING)
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &asInitInfoKM.hKernelHWProfilingMemInfo,
+#else
+ &psSGXDevInitPart2IN->sInitInfo.hKernelHWProfilingMemInfo,
+#endif
+ psSGXDevInitPart2IN->sInitInfo.hKernelHWProfilingMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+#endif
+
+#if defined(SUPPORT_SGX_HWPERF)
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &asInitInfoKM.hKernelHWPerfCBMemInfo,
+#else
+ &psSGXDevInitPart2IN->sInitInfo.hKernelHWPerfCBMemInfo,
+#endif
+ psSGXDevInitPart2IN->sInitInfo.hKernelHWPerfCBMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+#endif
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &asInitInfoKM.hKernelTASigBufferMemInfo,
+#else
+ &psSGXDevInitPart2IN->sInitInfo.hKernelTASigBufferMemInfo,
+#endif
+ psSGXDevInitPart2IN->sInitInfo.hKernelTASigBufferMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &asInitInfoKM.hKernel3DSigBufferMemInfo,
+#else
+ &psSGXDevInitPart2IN->sInitInfo.hKernel3DSigBufferMemInfo,
+#endif
+ psSGXDevInitPart2IN->sInitInfo.hKernel3DSigBufferMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+
+#if defined(FIX_HW_BRN_29702)
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &asInitInfoKM.hKernelCFIMemInfo,
+#else
+ &psSGXDevInitPart2IN->sInitInfo.hKernelCFIMemInfo,
+#endif
+ psSGXDevInitPart2IN->sInitInfo.hKernelCFIMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+#endif
+
+#if defined(FIX_HW_BRN_29823)
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &asInitInfoKM.hKernelDummyTermStreamMemInfo,
+#else
+ &psSGXDevInitPart2IN->sInitInfo.hKernelDummyTermStreamMemInfo,
+#endif
+ psSGXDevInitPart2IN->sInitInfo.hKernelDummyTermStreamMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+#endif
+
+
+#if defined(FIX_HW_BRN_31542) || defined(FIX_HW_BRN_36513)
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &asInitInfoKM.hKernelClearClipWAVDMStreamMemInfo,
+#else
+ &psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAVDMStreamMemInfo,
+#endif
+ psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAVDMStreamMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &asInitInfoKM.hKernelClearClipWAIndexStreamMemInfo,
+#else
+ &psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAIndexStreamMemInfo,
+#endif
+ psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAIndexStreamMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &asInitInfoKM.hKernelClearClipWAPDSMemInfo,
+#else
+ &psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAPDSMemInfo,
+#endif
+ psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAPDSMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &asInitInfoKM.hKernelClearClipWAUSEMemInfo,
+#else
+ &psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAUSEMemInfo,
+#endif
+ psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAUSEMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &asInitInfoKM.hKernelClearClipWAParamMemInfo,
+#else
+ &psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAParamMemInfo,
+#endif
+ psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAParamMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &asInitInfoKM.hKernelClearClipWAPMPTMemInfo,
+#else
+ &psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAPMPTMemInfo,
+#endif
+ psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAPMPTMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &asInitInfoKM.hKernelClearClipWATPCMemInfo,
+#else
+ &psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWATPCMemInfo,
+#endif
+ psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWATPCMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &asInitInfoKM.hKernelClearClipWAPSGRgnHdrMemInfo,
+#else
+ &psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAPSGRgnHdrMemInfo,
+#endif
+ psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAPSGRgnHdrMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+#endif
+#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && defined(FIX_HW_BRN_31559)
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernelVDMSnapShotBufferMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernelVDMSnapShotBufferMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernelVDMCtrlStreamBufferMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernelVDMCtrlStreamBufferMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+#endif
+#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && \
+ defined(FIX_HW_BRN_33657) && defined(SUPPORT_SECURE_33657_FIX)
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernelVDMStateUpdateBufferMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernelVDMStateUpdateBufferMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+#endif
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ &asInitInfoKM.hKernelEDMStatusBufferMemInfo,
+#else
+ &psSGXDevInitPart2IN->sInitInfo.hKernelEDMStatusBufferMemInfo,
+#endif
+ psSGXDevInitPart2IN->sInitInfo.hKernelEDMStatusBufferMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+#endif
+
+ for (i = 0; i < SGX_MAX_INIT_MEM_HANDLES; i++)
+ {
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hHandle = psSGXDevInitPart2IN->sInitInfo.asInitMemHandles[i];
+ IMG_HANDLE *phHandleKM = &asInitInfoKM.asInitMemHandles[i];
+
+ if (hHandle == 0)
+#else
+ IMG_HANDLE *phHandle = &psSGXDevInitPart2IN->sInitInfo.asInitMemHandles[i];
+
+ if (*phHandle == IMG_NULL)
+#endif
+ continue;
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ phHandleKM,
+ hHandle,
+#else
+ phHandle,
+ *phHandle,
+#endif
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+ }
+
+ if (bReleaseFailed)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DevInitSGXPart2BW: A handle release failed"));
+ psSGXDevInitPart2OUT->eError = PVRSRV_ERROR_INIT2_PHASE_FAILED;
+
+ PVR_DBG_BREAK;
+ return 0;
+ }
+
+
+#if defined (SUPPORT_SID_INTERFACE)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, asInitInfoKM.hKernelCCBMemInfo);
+#else
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo);
+#endif
+ if (eError != PVRSRV_OK)
+ {
+ bDissociateFailed = IMG_TRUE;
+ }
+
+#if defined (SUPPORT_SID_INTERFACE)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, asInitInfoKM.hKernelCCBCtlMemInfo);
+#else
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo);
+#endif
+ if (eError != PVRSRV_OK)
+ {
+ bDissociateFailed = IMG_TRUE;
+ }
+
+#if defined (SUPPORT_SID_INTERFACE)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, asInitInfoKM.hKernelCCBEventKickerMemInfo);
+#else
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBEventKickerMemInfo);
+#endif
+ if (eError != PVRSRV_OK)
+ {
+ bDissociateFailed = IMG_TRUE;
+ }
+
+#if defined (SUPPORT_SID_INTERFACE)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, asInitInfoKM.hKernelSGXHostCtlMemInfo);
+#else
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo);
+#endif
+ if (eError != PVRSRV_OK)
+ {
+ bDissociateFailed = IMG_TRUE;
+ }
+
+#if defined (SUPPORT_SID_INTERFACE)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, asInitInfoKM.hKernelSGXTA3DCtlMemInfo);
+#else
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo);
+#endif
+ if (eError != PVRSRV_OK)
+ {
+ bDissociateFailed = IMG_TRUE;
+ }
+
+#if defined(FIX_HW_BRN_31272) || defined(FIX_HW_BRN_31780) || defined(FIX_HW_BRN_33920)
+#if defined (SUPPORT_SID_INTERFACE)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, asInitInfoKM.hKernelSGXPTLAWriteBackMemInfo);
+#else
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXPTLAWriteBackMemInfo);
+#endif
+ if (eError != PVRSRV_OK)
+ {
+ bDissociateFailed = IMG_TRUE;
+ }
+#endif
+
+
+#if defined (SUPPORT_SID_INTERFACE)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, asInitInfoKM.hKernelSGXMiscMemInfo);
+#else
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo);
+#endif
+ if (eError != PVRSRV_OK)
+ {
+ bDissociateFailed = IMG_TRUE;
+ }
+
+
+#if defined(SGX_SUPPORT_HWPROFILING)
+#if defined (SUPPORT_SID_INTERFACE)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, asInitInfoKM.hKernelHWProfilingMemInfo);
+ if (eError != PVRSRV_OK)
+ {
+ bDissociateFailed = IMG_TRUE;
+ }
+#else
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelHWProfilingMemInfo);
+ bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+#endif
+
+#if defined(SUPPORT_SGX_HWPERF)
+#if defined (SUPPORT_SID_INTERFACE)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, asInitInfoKM.hKernelHWPerfCBMemInfo);
+#else
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelHWPerfCBMemInfo);
+#endif
+ if (eError != PVRSRV_OK)
+ {
+ bDissociateFailed = IMG_TRUE;
+ }
+#endif
+
+#if defined (SUPPORT_SID_INTERFACE)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, asInitInfoKM.hKernelTASigBufferMemInfo);
+#else
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelTASigBufferMemInfo);
+#endif
+ if (eError != PVRSRV_OK)
+ {
+ bDissociateFailed = IMG_TRUE;
+ }
+
+#if defined (SUPPORT_SID_INTERFACE)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, asInitInfoKM.hKernel3DSigBufferMemInfo);
+#else
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernel3DSigBufferMemInfo);
+#endif
+ if (eError != PVRSRV_OK)
+ {
+ bDissociateFailed = IMG_TRUE;
+ }
+
+#if defined(FIX_HW_BRN_29702)
+#if defined (SUPPORT_SID_INTERFACE)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, asInitInfoKM.hKernelCFIMemInfo);
+ if (eError != PVRSRV_OK)
+ {
+ bDissociateFailed = IMG_TRUE;
+ }
+#else
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCFIMemInfo);
+ bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+#endif
+
+#if defined(FIX_HW_BRN_29823)
+#if defined (SUPPORT_SID_INTERFACE)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, asInitInfoKM.hKernelDummyTermStreamMemInfo);
+ if (eError != PVRSRV_OK)
+ {
+ bDissociateFailed = IMG_TRUE;
+ }
+#else
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelDummyTermStreamMemInfo);
+ bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+#endif
+
+#if defined(FIX_HW_BRN_31542) || defined(FIX_HW_BRN_36513)
+#if defined (SUPPORT_SID_INTERFACE)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, asInitInfoKM.hKernelClearClipWAVDMStreamMemInfo);
+ if (eError != PVRSRV_OK)
+ {
+ bDissociateFailed = IMG_TRUE;
+ }
+#else
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAVDMStreamMemInfo);
+ bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+#if defined (SUPPORT_SID_INTERFACE)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, asInitInfoKM.hKernelClearClipWAIndexStreamMemInfo);
+ if (eError != PVRSRV_OK)
+ {
+ bDissociateFailed = IMG_TRUE;
+ }
+#else
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAIndexStreamMemInfo);
+ bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+#if defined (SUPPORT_SID_INTERFACE)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, asInitInfoKM.hKernelClearClipWAPDSMemInfo);
+ if (eError != PVRSRV_OK)
+ {
+ bDissociateFailed = IMG_TRUE;
+ }
+#else
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAPDSMemInfo);
+ bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+#if defined (SUPPORT_SID_INTERFACE)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, asInitInfoKM.hKernelClearClipWAUSEMemInfo);
+ if (eError != PVRSRV_OK)
+ {
+ bDissociateFailed = IMG_TRUE;
+ }
+#else
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAUSEMemInfo);
+ bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+#if defined (SUPPORT_SID_INTERFACE)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, asInitInfoKM.hKernelClearClipWAParamMemInfo);
+ if (eError != PVRSRV_OK)
+ {
+ bDissociateFailed = IMG_TRUE;
+ }
+#else
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAParamMemInfo);
+ bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+#if defined (SUPPORT_SID_INTERFACE)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, asInitInfoKM.hKernelClearClipWAPMPTMemInfo);
+ if (eError != PVRSRV_OK)
+ {
+ bDissociateFailed = IMG_TRUE;
+ }
+#else
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAPMPTMemInfo);
+ bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+#if defined (SUPPORT_SID_INTERFACE)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, asInitInfoKM.hKernelClearClipWATPCMemInfo);
+ if (eError != PVRSRV_OK)
+ {
+ bDissociateFailed = IMG_TRUE;
+ }
+#else
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWATPCMemInfo);
+ bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+#if defined (SUPPORT_SID_INTERFACE)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, asInitInfoKM.hKernelClearClipWAPSGRgnHdrMemInfo);
+ if (eError != PVRSRV_OK)
+ {
+ bDissociateFailed = IMG_TRUE;
+ }
+#else
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAPSGRgnHdrMemInfo);
+ bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+#endif
+
+#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && defined(FIX_HW_BRN_31559)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelVDMSnapShotBufferMemInfo);
+ bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelVDMCtrlStreamBufferMemInfo);
+ bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && \
+ defined(FIX_HW_BRN_33657) && defined(SUPPORT_SECURE_33657_FIX)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelVDMStateUpdateBufferMemInfo);
+ bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+#if defined (SUPPORT_SID_INTERFACE)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, asInitInfoKM.hKernelEDMStatusBufferMemInfo);
+ if (eError != PVRSRV_OK)
+ {
+ bDissociateFailed = IMG_TRUE;
+ }
+#else
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelEDMStatusBufferMemInfo);
+ bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+#endif
+
+ for (i = 0; i < SGX_MAX_INIT_MEM_HANDLES; i++)
+ {
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_HANDLE hHandle = asInitInfoKM.asInitMemHandles[i];
+#else
+ IMG_HANDLE hHandle = psSGXDevInitPart2IN->sInitInfo.asInitMemHandles[i];
+#endif
+
+ if (hHandle == IMG_NULL)
+ continue;
+
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, hHandle);
+ if (eError != PVRSRV_OK)
+ {
+ bDissociateFailed = IMG_TRUE;
+ }
+ }
+
+
+ if(bDissociateFailed)
+ {
+#if defined (SUPPORT_SID_INTERFACE)
+ PVRSRVFreeDeviceMemKM(hDevCookieInt, asInitInfoKM.hKernelCCBMemInfo);
+ PVRSRVFreeDeviceMemKM(hDevCookieInt, asInitInfoKM.hKernelCCBCtlMemInfo);
+ PVRSRVFreeDeviceMemKM(hDevCookieInt, asInitInfoKM.hKernelSGXHostCtlMemInfo);
+ PVRSRVFreeDeviceMemKM(hDevCookieInt, asInitInfoKM.hKernelSGXTA3DCtlMemInfo);
+#if defined(FIX_HW_BRN_31272) || defined(FIX_HW_BRN_31780) || defined(FIX_HW_BRN_33920)
+ PVRSRVFreeDeviceMemKM(hDevCookieInt, asInitInfoKM.hKernelSGXPTLAWriteBackMemInfo);
+#endif
+ PVRSRVFreeDeviceMemKM(hDevCookieInt, asInitInfoKM.hKernelSGXMiscMemInfo);
+#else
+ PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo);
+ PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo);
+ PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo);
+ PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo);
+#if defined(FIX_HW_BRN_31272) || defined(FIX_HW_BRN_31780) || defined(FIX_HW_BRN_33920)
+ PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXPTLAWriteBackMemInfo);
+#endif
+ PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo);
+#endif
+
+ for (i = 0; i < SGX_MAX_INIT_MEM_HANDLES; i++)
+ {
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_HANDLE hHandle = asInitInfoKM.asInitMemHandles[i];
+
+ if (hHandle == 0)
+#else
+ IMG_HANDLE hHandle = psSGXDevInitPart2IN->sInitInfo.asInitMemHandles[i];
+
+ if (hHandle == IMG_NULL)
+#endif
+ continue;
+
+ PVRSRVFreeDeviceMemKM(hDevCookieInt, (PVRSRV_KERNEL_MEM_INFO *)hHandle);
+
+ }
+
+ PVR_DPF((PVR_DBG_ERROR, "DevInitSGXPart2BW: A dissociate failed"));
+
+ psSGXDevInitPart2OUT->eError = PVRSRV_ERROR_INIT2_PHASE_FAILED;
+
+
+ PVR_DBG_BREAK;
+ return 0;
+ }
+
+#if defined (SUPPORT_SID_INTERFACE)
+ asInitInfoKM.sScripts = psSGXDevInitPart2IN->sInitInfo.sScripts;
+ asInitInfoKM.ui32ClientBuildOptions = psSGXDevInitPart2IN->sInitInfo.ui32ClientBuildOptions;
+ asInitInfoKM.sSGXStructSizes = psSGXDevInitPart2IN->sInitInfo.sSGXStructSizes;
+ asInitInfoKM.ui32CacheControl = psSGXDevInitPart2IN->sInitInfo.ui32CacheControl;
+ asInitInfoKM.ui32EDMTaskReg0 = psSGXDevInitPart2IN->sInitInfo.ui32EDMTaskReg0;
+ asInitInfoKM.ui32EDMTaskReg1 = psSGXDevInitPart2IN->sInitInfo.ui32EDMTaskReg1;
+ asInitInfoKM.ui32ClkGateStatusReg = psSGXDevInitPart2IN->sInitInfo.ui32ClkGateStatusReg;
+ asInitInfoKM.ui32ClkGateStatusMask = psSGXDevInitPart2IN->sInitInfo.ui32ClkGateStatusMask;
+
+ OSMemCopy(&asInitInfoKM.asInitDevData ,
+ &psSGXDevInitPart2IN->sInitInfo.asInitDevData,
+ sizeof(asInitInfoKM.asInitDevData));
+ OSMemCopy(&asInitInfoKM.aui32HostKickAddr,
+ &psSGXDevInitPart2IN->sInitInfo.aui32HostKickAddr,
+ sizeof(asInitInfoKM.aui32HostKickAddr));
+
+ psSGXDevInitPart2OUT->eError =
+ DevInitSGXPart2KM(psPerProc,
+ hDevCookieInt,
+ &asInitInfoKM);
+#else
+ psSGXDevInitPart2OUT->eError =
+ DevInitSGXPart2KM(psPerProc,
+ hDevCookieInt,
+ &psSGXDevInitPart2IN->sInitInfo);
+#endif
+
+ return 0;
+}
+
+
+static IMG_INT
+SGXRegisterHWRenderContextBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_RENDER_CONTEXT *psSGXRegHWRenderContextIN,
+ PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_RENDER_CONTEXT *psSGXRegHWRenderContextOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_HANDLE hHWRenderContextInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_REGISTER_HW_RENDER_CONTEXT);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psSGXRegHWRenderContextOUT->eError, psPerProc, 1);
+
+ psSGXRegHWRenderContextOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXRegHWRenderContextIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psSGXRegHWRenderContextOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ hHWRenderContextInt =
+ SGXRegisterHWRenderContextKM(hDevCookieInt,
+ psSGXRegHWRenderContextIN->pHWRenderContextCpuVAddr,
+ psSGXRegHWRenderContextIN->ui32HWRenderContextSize,
+ psSGXRegHWRenderContextIN->ui32OffsetToPDDevPAddr,
+ psSGXRegHWRenderContextIN->hDevMemContext,
+ &psSGXRegHWRenderContextOUT->sHWRenderContextDevVAddr,
+ psPerProc);
+
+ if (hHWRenderContextInt == IMG_NULL)
+ {
+ psSGXRegHWRenderContextOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_CONTEXT;
+ return 0;
+ }
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psSGXRegHWRenderContextOUT->hHWRenderContext,
+ hHWRenderContextInt,
+ PVRSRV_HANDLE_TYPE_SGX_HW_RENDER_CONTEXT,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psSGXRegHWRenderContextOUT->eError, psPerProc);
+
+ return 0;
+}
+
+
+static IMG_INT
+SGXUnregisterHWRenderContextBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_RENDER_CONTEXT *psSGXUnregHWRenderContextIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hHWRenderContextInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_UNREGISTER_HW_RENDER_CONTEXT);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hHWRenderContextInt,
+ psSGXUnregHWRenderContextIN->hHWRenderContext,
+ PVRSRV_HANDLE_TYPE_SGX_HW_RENDER_CONTEXT);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = SGXUnregisterHWRenderContextKM(hHWRenderContextInt,
+ psSGXUnregHWRenderContextIN->bForceCleanup);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psSGXUnregHWRenderContextIN->hHWRenderContext,
+ PVRSRV_HANDLE_TYPE_SGX_HW_RENDER_CONTEXT);
+
+ return 0;
+}
+
+
+static IMG_INT
+SGXRegisterHWTransferContextBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_TRANSFER_CONTEXT *psSGXRegHWTransferContextIN,
+ PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_TRANSFER_CONTEXT *psSGXRegHWTransferContextOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_HANDLE hHWTransferContextInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_REGISTER_HW_TRANSFER_CONTEXT);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psSGXRegHWTransferContextOUT->eError, psPerProc, 1);
+
+ psSGXRegHWTransferContextOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXRegHWTransferContextIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psSGXRegHWTransferContextOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ hHWTransferContextInt =
+ SGXRegisterHWTransferContextKM(hDevCookieInt,
+ psSGXRegHWTransferContextIN->pHWTransferContextCpuVAddr,
+ psSGXRegHWTransferContextIN->ui32HWTransferContextSize,
+ psSGXRegHWTransferContextIN->ui32OffsetToPDDevPAddr,
+ psSGXRegHWTransferContextIN->hDevMemContext,
+ &psSGXRegHWTransferContextOUT->sHWTransferContextDevVAddr,
+ psPerProc);
+
+ if (hHWTransferContextInt == IMG_NULL)
+ {
+ psSGXRegHWTransferContextOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_CONTEXT;
+ return 0;
+ }
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psSGXRegHWTransferContextOUT->hHWTransferContext,
+ hHWTransferContextInt,
+ PVRSRV_HANDLE_TYPE_SGX_HW_TRANSFER_CONTEXT,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psSGXRegHWTransferContextOUT->eError, psPerProc);
+
+ return 0;
+}
+
+
+static IMG_INT
+SGXUnregisterHWTransferContextBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_TRANSFER_CONTEXT *psSGXUnregHWTransferContextIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_HANDLE hHWTransferContextInt = 0;
+#else
+ IMG_HANDLE hHWTransferContextInt;
+#endif
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_UNREGISTER_HW_TRANSFER_CONTEXT);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hHWTransferContextInt,
+ psSGXUnregHWTransferContextIN->hHWTransferContext,
+ PVRSRV_HANDLE_TYPE_SGX_HW_TRANSFER_CONTEXT);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = SGXUnregisterHWTransferContextKM(hHWTransferContextInt,
+ psSGXUnregHWTransferContextIN->bForceCleanup);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psSGXUnregHWTransferContextIN->hHWTransferContext,
+ PVRSRV_HANDLE_TYPE_SGX_HW_TRANSFER_CONTEXT);
+
+ return 0;
+}
+
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+static IMG_INT
+SGXRegisterHW2DContextBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_2D_CONTEXT *psSGXRegHW2DContextIN,
+ PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_2D_CONTEXT *psSGXRegHW2DContextOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_HANDLE hHW2DContextInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_REGISTER_HW_2D_CONTEXT);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psSGXRegHW2DContextOUT->eError, psPerProc, 1);
+
+ psSGXRegHW2DContextOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXRegHW2DContextIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psSGXRegHW2DContextOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ hHW2DContextInt =
+ SGXRegisterHW2DContextKM(hDevCookieInt,
+ psSGXRegHW2DContextIN->pHW2DContextCpuVAddr,
+ psSGXRegHW2DContextIN->ui32HW2DContextSize,
+ psSGXRegHW2DContextIN->ui32OffsetToPDDevPAddr,
+ psSGXRegHW2DContextIN->hDevMemContext,
+ &psSGXRegHW2DContextOUT->sHW2DContextDevVAddr,
+ psPerProc);
+
+ if (hHW2DContextInt == IMG_NULL)
+ {
+ psSGXRegHW2DContextOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_CONTEXT;
+ return 0;
+ }
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psSGXRegHW2DContextOUT->hHW2DContext,
+ hHW2DContextInt,
+ PVRSRV_HANDLE_TYPE_SGX_HW_2D_CONTEXT,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psSGXRegHW2DContextOUT->eError, psPerProc);
+
+ return 0;
+}
+
+
+static IMG_INT
+SGXUnregisterHW2DContextBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_2D_CONTEXT *psSGXUnregHW2DContextIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hHW2DContextInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_UNREGISTER_HW_2D_CONTEXT);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hHW2DContextInt,
+ psSGXUnregHW2DContextIN->hHW2DContext,
+ PVRSRV_HANDLE_TYPE_SGX_HW_2D_CONTEXT);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = SGXUnregisterHW2DContextKM(hHW2DContextInt,
+ psSGXUnregHW2DContextIN->bForceCleanup);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psSGXUnregHW2DContextIN->hHW2DContext,
+ PVRSRV_HANDLE_TYPE_SGX_HW_2D_CONTEXT);
+
+ return 0;
+}
+#endif
+
+static IMG_INT
+SGXFlushHWRenderTargetBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_FLUSH_HW_RENDER_TARGET *psSGXFlushHWRenderTargetIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_FLUSH_HW_RENDER_TARGET);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXFlushHWRenderTargetIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = SGXFlushHWRenderTargetKM(hDevCookieInt, psSGXFlushHWRenderTargetIN->sHWRTDataSetDevVAddr, IMG_FALSE);
+
+ return 0;
+}
+
+
+static IMG_INT
+SGX2DQueryBlitsCompleteBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_2DQUERYBLTSCOMPLETE *ps2DQueryBltsCompleteIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_VOID *pvSyncInfo;
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_2DQUERYBLTSCOMPLETE);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ ps2DQueryBltsCompleteIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvSyncInfo,
+ ps2DQueryBltsCompleteIN->hKernSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookieInt)->pvDevice;
+
+ psRetOUT->eError =
+ SGX2DQueryBlitsCompleteKM(psDevInfo,
+ (PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo,
+ ps2DQueryBltsCompleteIN->bWaitForComplete);
+
+ return 0;
+}
+
+
+static IMG_INT
+SGXFindSharedPBDescBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGXFINDSHAREDPBDESC *psSGXFindSharedPBDescIN,
+ PVRSRV_BRIDGE_OUT_SGXFINDSHAREDPBDESC *psSGXFindSharedPBDescOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psHWBlockKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescSubKernelMemInfos = IMG_NULL;
+ IMG_UINT32 ui32SharedPBDescSubKernelMemInfosCount = 0;
+ IMG_UINT32 i;
+ IMG_HANDLE hSharedPBDesc = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psSGXFindSharedPBDescOUT->eError, psPerProc, PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS + 4);
+
+ psSGXFindSharedPBDescOUT->hSharedPBDesc = IMG_NULL;
+
+ psSGXFindSharedPBDescOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXFindSharedPBDescIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psSGXFindSharedPBDescOUT->eError != PVRSRV_OK)
+ goto PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC_EXIT;
+
+ psSGXFindSharedPBDescOUT->eError =
+ SGXFindSharedPBDescKM(psPerProc, hDevCookieInt,
+ psSGXFindSharedPBDescIN->bLockOnFailure,
+ psSGXFindSharedPBDescIN->ui32TotalPBSize,
+ &hSharedPBDesc,
+ &psSharedPBDescKernelMemInfo,
+ &psHWPBDescKernelMemInfo,
+ &psBlockKernelMemInfo,
+ &psHWBlockKernelMemInfo,
+ &ppsSharedPBDescSubKernelMemInfos,
+ &ui32SharedPBDescSubKernelMemInfosCount);
+ if(psSGXFindSharedPBDescOUT->eError != PVRSRV_OK)
+ goto PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC_EXIT;
+
+ PVR_ASSERT(ui32SharedPBDescSubKernelMemInfosCount
+ <= PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS);
+
+ psSGXFindSharedPBDescOUT->ui32SharedPBDescSubKernelMemInfoHandlesCount =
+ ui32SharedPBDescSubKernelMemInfosCount;
+
+ if(hSharedPBDesc == IMG_NULL)
+ {
+ psSGXFindSharedPBDescOUT->hSharedPBDescKernelMemInfoHandle = 0;
+
+ goto PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC_EXIT;
+ }
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psSGXFindSharedPBDescOUT->hSharedPBDesc,
+ hSharedPBDesc,
+ PVRSRV_HANDLE_TYPE_SHARED_PB_DESC,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psSGXFindSharedPBDescOUT->hSharedPBDescKernelMemInfoHandle,
+ psSharedPBDescKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ psSGXFindSharedPBDescOUT->hSharedPBDesc);
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psSGXFindSharedPBDescOUT->hHWPBDescKernelMemInfoHandle,
+ psHWPBDescKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ psSGXFindSharedPBDescOUT->hSharedPBDesc);
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psSGXFindSharedPBDescOUT->hBlockKernelMemInfoHandle,
+ psBlockKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ psSGXFindSharedPBDescOUT->hSharedPBDesc);
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psSGXFindSharedPBDescOUT->hHWBlockKernelMemInfoHandle,
+ psHWBlockKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ psSGXFindSharedPBDescOUT->hSharedPBDesc);
+
+
+ for(i=0; i<ui32SharedPBDescSubKernelMemInfosCount; i++)
+ {
+ PVRSRV_BRIDGE_OUT_SGXFINDSHAREDPBDESC *psSGXFindSharedPBDescOut =
+ psSGXFindSharedPBDescOUT;
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psSGXFindSharedPBDescOut->ahSharedPBDescSubKernelMemInfoHandles[i],
+ ppsSharedPBDescSubKernelMemInfos[i],
+ PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ psSGXFindSharedPBDescOUT->hSharedPBDescKernelMemInfoHandle);
+ }
+
+PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC_EXIT:
+ if (ppsSharedPBDescSubKernelMemInfos != IMG_NULL)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO *) * ui32SharedPBDescSubKernelMemInfosCount,
+ ppsSharedPBDescSubKernelMemInfos,
+ IMG_NULL);
+ }
+
+ if(psSGXFindSharedPBDescOUT->eError != PVRSRV_OK)
+ {
+ if(hSharedPBDesc != IMG_NULL)
+ {
+ SGXUnrefSharedPBDescKM(hSharedPBDesc);
+ }
+ }
+ else
+ {
+ COMMIT_HANDLE_BATCH_OR_ERROR(psSGXFindSharedPBDescOUT->eError, psPerProc);
+ }
+
+ return 0;
+}
+
+
+static IMG_INT
+SGXUnrefSharedPBDescBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGXUNREFSHAREDPBDESC *psSGXUnrefSharedPBDescIN,
+ PVRSRV_BRIDGE_OUT_SGXUNREFSHAREDPBDESC *psSGXUnrefSharedPBDescOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hSharedPBDesc;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_UNREFSHAREDPBDESC);
+
+ psSGXUnrefSharedPBDescOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hSharedPBDesc,
+ psSGXUnrefSharedPBDescIN->hSharedPBDesc,
+ PVRSRV_HANDLE_TYPE_SHARED_PB_DESC);
+ if(psSGXUnrefSharedPBDescOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psSGXUnrefSharedPBDescOUT->eError =
+ SGXUnrefSharedPBDescKM(hSharedPBDesc);
+
+ if(psSGXUnrefSharedPBDescOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psSGXUnrefSharedPBDescOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psSGXUnrefSharedPBDescIN->hSharedPBDesc,
+ PVRSRV_HANDLE_TYPE_SHARED_PB_DESC);
+
+ return 0;
+}
+
+
+static IMG_INT
+SGXAddSharedPBDescBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGXADDSHAREDPBDESC *psSGXAddSharedPBDescIN,
+ PVRSRV_BRIDGE_OUT_SGXADDSHAREDPBDESC *psSGXAddSharedPBDescOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psHWBlockKernelMemInfo;
+ IMG_UINT32 ui32KernelMemInfoHandlesCount =
+ psSGXAddSharedPBDescIN->ui32KernelMemInfoHandlesCount;
+ IMG_INT ret = 0;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID *phKernelMemInfoHandles = 0;
+#else
+ IMG_HANDLE *phKernelMemInfoHandles = IMG_NULL;
+#endif
+ PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfos = IMG_NULL;
+ IMG_UINT32 i;
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hSharedPBDesc = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psSGXAddSharedPBDescOUT->eError, psPerProc, 1);
+
+ psSGXAddSharedPBDescOUT->hSharedPBDesc = IMG_NULL;
+
+ PVR_ASSERT(ui32KernelMemInfoHandlesCount
+ <= PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS);
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXAddSharedPBDescIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID **)&psSharedPBDescKernelMemInfo,
+ psSGXAddSharedPBDescIN->hSharedPBDescKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+ if(eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID **)&psHWPBDescKernelMemInfo,
+ psSGXAddSharedPBDescIN->hHWPBDescKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID **)&psBlockKernelMemInfo,
+ psSGXAddSharedPBDescIN->hBlockKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+ if(eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID **)&psHWBlockKernelMemInfo,
+ psSGXAddSharedPBDescIN->hHWBlockKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+
+ if(!OSAccessOK(PVR_VERIFY_READ,
+ psSGXAddSharedPBDescIN->phKernelMemInfoHandles,
+ ui32KernelMemInfoHandlesCount * sizeof(IMG_HANDLE)))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC:"
+ " Invalid phKernelMemInfos pointer", __FUNCTION__));
+ ret = -EFAULT;
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32KernelMemInfoHandlesCount * sizeof(IMG_HANDLE),
+ (IMG_VOID **)&phKernelMemInfoHandles,
+ 0,
+ "Array of Handles");
+ if (eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ if(CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ phKernelMemInfoHandles,
+ psSGXAddSharedPBDescIN->phKernelMemInfoHandles,
+ ui32KernelMemInfoHandlesCount * sizeof(IMG_HANDLE))
+ != PVRSRV_OK)
+ {
+ ret = -EFAULT;
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32KernelMemInfoHandlesCount * sizeof(PVRSRV_KERNEL_MEM_INFO *),
+ (IMG_VOID **)&ppsKernelMemInfos,
+ 0,
+ "Array of pointers to Kernel Memory Info");
+ if (eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ for(i=0; i<ui32KernelMemInfoHandlesCount; i++)
+ {
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID **)&ppsKernelMemInfos[i],
+ phKernelMemInfoHandles[i],
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+ }
+
+
+
+ eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psSGXAddSharedPBDescIN->hSharedPBDescKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+
+ eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psSGXAddSharedPBDescIN->hHWPBDescKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+
+ eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psSGXAddSharedPBDescIN->hBlockKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+
+ eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psSGXAddSharedPBDescIN->hHWBlockKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ for(i=0; i<ui32KernelMemInfoHandlesCount; i++)
+ {
+
+ eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ phKernelMemInfoHandles[i],
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ PVR_ASSERT(eError == PVRSRV_OK);
+ }
+
+ eError = SGXAddSharedPBDescKM(psPerProc, hDevCookieInt,
+ psSharedPBDescKernelMemInfo,
+ psHWPBDescKernelMemInfo,
+ psBlockKernelMemInfo,
+ psHWBlockKernelMemInfo,
+ psSGXAddSharedPBDescIN->ui32TotalPBSize,
+ &hSharedPBDesc,
+ ppsKernelMemInfos,
+ ui32KernelMemInfoHandlesCount,
+ psSGXAddSharedPBDescIN->sHWPBDescDevVAddr);
+
+
+ if (eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psSGXAddSharedPBDescOUT->hSharedPBDesc,
+ hSharedPBDesc,
+ PVRSRV_HANDLE_TYPE_SHARED_PB_DESC,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT:
+
+ if(phKernelMemInfoHandles)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ psSGXAddSharedPBDescIN->ui32KernelMemInfoHandlesCount * sizeof(IMG_HANDLE),
+ (IMG_VOID *)phKernelMemInfoHandles,
+ 0);
+ }
+ if(ppsKernelMemInfos)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ psSGXAddSharedPBDescIN->ui32KernelMemInfoHandlesCount * sizeof(PVRSRV_KERNEL_MEM_INFO *),
+ (IMG_VOID *)ppsKernelMemInfos,
+ 0);
+ }
+
+ if(ret == 0 && eError == PVRSRV_OK)
+ {
+ COMMIT_HANDLE_BATCH_OR_ERROR(psSGXAddSharedPBDescOUT->eError, psPerProc);
+ }
+
+ psSGXAddSharedPBDescOUT->eError = eError;
+
+ return ret;
+}
+
+static IMG_INT
+SGXGetInfoForSrvinitBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGXINFO_FOR_SRVINIT *psSGXInfoForSrvinitIN,
+ PVRSRV_BRIDGE_OUT_SGXINFO_FOR_SRVINIT *psSGXInfoForSrvinitOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_UINT32 i;
+#if defined (SUPPORT_SID_INTERFACE)
+ PVRSRV_HEAP_INFO_KM asHeapInfo[PVRSRV_MAX_CLIENT_HEAPS];
+#endif
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGXINFO_FOR_SRVINIT);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psSGXInfoForSrvinitOUT->eError, psPerProc, PVRSRV_MAX_CLIENT_HEAPS);
+
+ if(!psPerProc->bInitProcess)
+ {
+ psSGXInfoForSrvinitOUT->eError = PVRSRV_ERROR_PROCESS_NOT_INITIALISED;
+ return 0;
+ }
+
+ psSGXInfoForSrvinitOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psSGXInfoForSrvinitIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psSGXInfoForSrvinitOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psSGXInfoForSrvinitOUT->eError =
+ SGXGetInfoForSrvinitKM(hDevCookieInt,
+#if defined (SUPPORT_SID_INTERFACE)
+ &asHeapInfo[0],
+ &psSGXInfoForSrvinitOUT->sInitInfo.sPDDevPAddr);
+#else
+ &psSGXInfoForSrvinitOUT->sInitInfo);
+#endif
+
+ if(psSGXInfoForSrvinitOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ for(i = 0; i < PVRSRV_MAX_CLIENT_HEAPS; i++)
+ {
+ PVRSRV_HEAP_INFO *psHeapInfo;
+
+ psHeapInfo = &psSGXInfoForSrvinitOUT->sInitInfo.asHeapInfo[i];
+
+#if defined (SUPPORT_SID_INTERFACE)
+ if ((asHeapInfo[i].ui32HeapID != (IMG_UINT32)SGX_UNDEFINED_HEAP_ID) &&
+ (asHeapInfo[i].hDevMemHeap != IMG_NULL))
+ {
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psHeapInfo->hDevMemHeap,
+ asHeapInfo[i].hDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+ }
+ else
+ {
+ psHeapInfo->hDevMemHeap = 0;
+ }
+
+ psHeapInfo->ui32HeapID = asHeapInfo[i].ui32HeapID;
+ psHeapInfo->sDevVAddrBase = asHeapInfo[i].sDevVAddrBase;
+ psHeapInfo->ui32HeapByteSize = asHeapInfo[i].ui32HeapByteSize;
+ psHeapInfo->ui32Attribs = asHeapInfo[i].ui32Attribs;
+ psHeapInfo->ui32XTileStride = asHeapInfo[i].ui32XTileStride;
+#else
+ if (psHeapInfo->ui32HeapID != (IMG_UINT32)SGX_UNDEFINED_HEAP_ID)
+ {
+ IMG_HANDLE hDevMemHeapExt;
+
+ if (psHeapInfo->hDevMemHeap != IMG_NULL)
+ {
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &hDevMemHeapExt,
+ psHeapInfo->hDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+ psHeapInfo->hDevMemHeap = hDevMemHeapExt;
+ }
+ }
+#endif
+ }
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psSGXInfoForSrvinitOUT->eError, psPerProc);
+
+ return 0;
+}
+
+#if defined(PDUMP)
+static IMG_VOID
+DumpBufferArray(PVRSRV_PER_PROCESS_DATA *psPerProc,
+#if defined (SUPPORT_SID_INTERFACE)
+ PSGX_KICKTA_DUMP_BUFFER_KM psBufferArray,
+#else
+ PSGX_KICKTA_DUMP_BUFFER psBufferArray,
+#endif
+ IMG_UINT32 ui32BufferArrayLength,
+ IMG_BOOL bDumpPolls)
+{
+ IMG_UINT32 i;
+
+ for (i=0; i<ui32BufferArrayLength; i++)
+ {
+#if defined (SUPPORT_SID_INTERFACE)
+ PSGX_KICKTA_DUMP_BUFFER_KM psBuffer;
+#else
+ PSGX_KICKTA_DUMP_BUFFER psBuffer;
+#endif
+ PVRSRV_KERNEL_MEM_INFO *psCtrlMemInfoKM;
+ IMG_CHAR * pszName;
+ IMG_HANDLE hUniqueTag;
+ IMG_UINT32 ui32Offset;
+
+ psBuffer = &psBufferArray[i];
+ pszName = psBuffer->pszName;
+ if (!pszName)
+ {
+ pszName = "Nameless buffer";
+ }
+
+ hUniqueTag = MAKEUNIQUETAG((PVRSRV_KERNEL_MEM_INFO *)psBuffer->hKernelMemInfo);
+
+ #if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ psCtrlMemInfoKM = ((PVRSRV_KERNEL_MEM_INFO *)psBuffer->hCtrlKernelMemInfo);
+ ui32Offset = psBuffer->sCtrlDevVAddr.uiAddr - psCtrlMemInfoKM->sDevVAddr.uiAddr;
+ #else
+ psCtrlMemInfoKM = ((PVRSRV_KERNEL_MEM_INFO *)psBuffer->hKernelMemInfo)->psKernelSyncInfo->psSyncDataMemInfoKM;
+ ui32Offset = offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete);
+ #endif
+
+ if (psBuffer->ui32Start <= psBuffer->ui32End)
+ {
+ if (bDumpPolls)
+ {
+ PDUMPCOMMENTWITHFLAGS(0, "Wait for %s space\r\n", pszName);
+ PDUMPCBP(psCtrlMemInfoKM,
+ ui32Offset,
+ psBuffer->ui32Start,
+ psBuffer->ui32SpaceUsed,
+ psBuffer->ui32BufferSize,
+ 0,
+ MAKEUNIQUETAG(psCtrlMemInfoKM));
+ }
+
+ PDUMPCOMMENTWITHFLAGS(0, "%s\r\n", pszName);
+ PDUMPMEMUM(psPerProc,
+ IMG_NULL,
+ psBuffer->pvLinAddr,
+ (PVRSRV_KERNEL_MEM_INFO*)psBuffer->hKernelMemInfo,
+ psBuffer->ui32Start,
+ psBuffer->ui32End - psBuffer->ui32Start,
+ 0,
+ hUniqueTag);
+ }
+ else
+ {
+
+
+ if (bDumpPolls)
+ {
+ PDUMPCOMMENTWITHFLAGS(0, "Wait for %s space\r\n", pszName);
+ PDUMPCBP(psCtrlMemInfoKM,
+ ui32Offset,
+ psBuffer->ui32Start,
+ psBuffer->ui32BackEndLength,
+ psBuffer->ui32BufferSize,
+ 0,
+ MAKEUNIQUETAG(psCtrlMemInfoKM));
+ }
+ PDUMPCOMMENTWITHFLAGS(0, "%s (part 1)\r\n", pszName);
+ PDUMPMEMUM(psPerProc,
+ IMG_NULL,
+ psBuffer->pvLinAddr,
+ (PVRSRV_KERNEL_MEM_INFO*)psBuffer->hKernelMemInfo,
+ psBuffer->ui32Start,
+ psBuffer->ui32BackEndLength,
+ 0,
+ hUniqueTag);
+
+ if (bDumpPolls)
+ {
+ PDUMPMEMPOL(psCtrlMemInfoKM,
+ ui32Offset,
+ 0,
+ 0xFFFFFFFF,
+ PDUMP_POLL_OPERATOR_NOTEQUAL,
+ 0,
+ MAKEUNIQUETAG(psCtrlMemInfoKM));
+
+ PDUMPCOMMENTWITHFLAGS(0, "Wait for %s space\r\n", pszName);
+ PDUMPCBP(psCtrlMemInfoKM,
+ ui32Offset,
+ 0,
+ psBuffer->ui32End,
+ psBuffer->ui32BufferSize,
+ 0,
+ MAKEUNIQUETAG(psCtrlMemInfoKM));
+ }
+ PDUMPCOMMENTWITHFLAGS(0, "%s (part 2)\r\n", pszName);
+ PDUMPMEMUM(psPerProc,
+ IMG_NULL,
+ psBuffer->pvLinAddr,
+ (PVRSRV_KERNEL_MEM_INFO*)psBuffer->hKernelMemInfo,
+ 0,
+ psBuffer->ui32End,
+ 0,
+ hUniqueTag);
+ }
+ }
+}
+static IMG_INT
+SGXPDumpBufferArrayBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_BUFFER_ARRAY *psPDumpBufferArrayIN,
+ IMG_VOID *psBridgeOut,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_UINT32 i;
+#if defined (SUPPORT_SID_INTERFACE)
+ SGX_KICKTA_DUMP_BUFFER *psUMPtr;
+ SGX_KICKTA_DUMP_BUFFER_KM *psKickTADumpBufferKM, *psKMPtr;
+#else
+ SGX_KICKTA_DUMP_BUFFER *psKickTADumpBuffer;
+#endif
+ IMG_UINT32 ui32BufferArrayLength =
+ psPDumpBufferArrayIN->ui32BufferArrayLength;
+ IMG_UINT32 ui32BufferArraySize =
+ ui32BufferArrayLength * sizeof(SGX_KICKTA_DUMP_BUFFER);
+ PVRSRV_ERROR eError = PVRSRV_ERROR_TOO_FEW_BUFFERS;
+
+ PVR_UNREFERENCED_PARAMETER(psBridgeOut);
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY);
+
+#if defined (SUPPORT_SID_INTERFACE)
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32BufferArraySize,
+ (IMG_PVOID *)&psKickTADumpBufferKM, 0,
+ "Array of Kick Tile Accelerator Dump Buffer") != PVRSRV_OK)
+#else
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32BufferArraySize,
+ (IMG_PVOID *)&psKickTADumpBuffer, 0,
+ "Array of Kick Tile Accelerator Dump Buffer") != PVRSRV_OK)
+#endif
+ {
+ return -ENOMEM;
+ }
+
+#if !defined (SUPPORT_SID_INTERFACE)
+ if(CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ psKickTADumpBuffer,
+ psPDumpBufferArrayIN->psBufferArray,
+ ui32BufferArraySize) != PVRSRV_OK)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32BufferArraySize, psKickTADumpBuffer, 0);
+
+ return -EFAULT;
+ }
+#endif
+
+ for(i = 0; i < ui32BufferArrayLength; i++)
+ {
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_VOID *pvMemInfo = IMG_NULL;
+ psUMPtr = &psPDumpBufferArrayIN->psBufferArray[i];
+ psKMPtr = &psKickTADumpBufferKM[i];
+#else
+ IMG_VOID *pvMemInfo;
+#endif
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvMemInfo,
+#if defined (SUPPORT_SID_INTERFACE)
+ psUMPtr->hKernelMemInfo,
+#else
+ psKickTADumpBuffer[i].hKernelMemInfo,
+#endif
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY: "
+ "PVRSRVLookupHandle failed (%d)", eError));
+ break;
+ }
+#if defined (SUPPORT_SID_INTERFACE)
+ psKMPtr->hKernelMemInfo = pvMemInfo;
+#else
+ psKickTADumpBuffer[i].hKernelMemInfo = pvMemInfo;
+#endif
+
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvMemInfo,
+#if defined (SUPPORT_SID_INTERFACE)
+ psUMPtr->hCtrlKernelMemInfo,
+#else
+ psKickTADumpBuffer[i].hCtrlKernelMemInfo,
+#endif
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY: "
+ "PVRSRVLookupHandle failed (%d)", eError));
+ break;
+ }
+#if defined (SUPPORT_SID_INTERFACE)
+ psKMPtr->hCtrlKernelMemInfo = pvMemInfo;
+ psKMPtr->sCtrlDevVAddr = psUMPtr->sCtrlDevVAddr;
+#else
+ psKickTADumpBuffer[i].hCtrlKernelMemInfo = pvMemInfo;
+#endif
+#endif
+
+#if defined (SUPPORT_SID_INTERFACE)
+ psKMPtr->ui32SpaceUsed = psUMPtr->ui32SpaceUsed;
+ psKMPtr->ui32Start = psUMPtr->ui32Start;
+ psKMPtr->ui32End = psUMPtr->ui32End;
+ psKMPtr->ui32BufferSize = psUMPtr->ui32BufferSize;
+ psKMPtr->ui32BackEndLength = psUMPtr->ui32BackEndLength;
+ psKMPtr->uiAllocIndex = psUMPtr->uiAllocIndex;
+ psKMPtr->pvLinAddr = psUMPtr->pvLinAddr;
+ psKMPtr->pszName = psUMPtr->pszName;
+#endif
+ }
+
+ if(eError == PVRSRV_OK)
+ {
+ DumpBufferArray(psPerProc,
+#if defined (SUPPORT_SID_INTERFACE)
+ psKickTADumpBufferKM,
+#else
+ psKickTADumpBuffer,
+#endif
+ ui32BufferArrayLength,
+ psPDumpBufferArrayIN->bDumpPolls);
+ }
+
+#if defined (SUPPORT_SID_INTERFACE)
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32BufferArraySize, psKickTADumpBufferKM, 0);
+#else
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32BufferArraySize, psKickTADumpBuffer, 0);
+#endif
+
+
+ return 0;
+}
+
+static IMG_INT
+SGXPDump3DSignatureRegistersBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_3D_SIGNATURE_REGISTERS *psPDump3DSignatureRegistersIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_UINT32 ui32RegisterArraySize = psPDump3DSignatureRegistersIN->ui32NumRegisters * sizeof(IMG_UINT32);
+ IMG_UINT32 *pui32Registers = IMG_NULL;
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+#if defined(SGX_FEATURE_MP) && defined(FIX_HW_BRN_27270)
+ IMG_UINT32 ui32RegVal = 0;
+#endif
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_HANDLE hDevMemContextInt = 0;
+ IMG_UINT32 ui32MMUContextID;
+ IMG_INT ret = -EFAULT;
+
+ PVR_UNREFERENCED_PARAMETER(psRetOUT);
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_3D_SIGNATURE_REGISTERS);
+
+ if (ui32RegisterArraySize == 0)
+ {
+ goto ExitNoError;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID**)&psDeviceNode,
+ psPDump3DSignatureRegistersIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpTASignatureRegistersBW: hDevCookie lookup failed"));
+ goto Exit;
+ }
+
+ psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+
+#if defined(SGX_FEATURE_MP) && defined(FIX_HW_BRN_27270)
+
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE, (SGX_FEATURE_MP_CORE_COUNT - 1) << EUR_CR_MASTER_CORE_ENABLE_SHIFT);
+#if defined(PDUMP)
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_CORE, (SGX_FEATURE_MP_CORE_COUNT - 1) << EUR_CR_MASTER_CORE_ENABLE_SHIFT,
+ psPDump3DSignatureRegistersIN->bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+#endif
+#endif
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32RegisterArraySize,
+ (IMG_PVOID *)&pui32Registers, 0,
+ "Array of Registers") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDump3DSignatureRegistersBW: OSAllocMem failed"));
+ goto Exit;
+ }
+
+ if(CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ pui32Registers,
+ psPDump3DSignatureRegistersIN->pui32Registers,
+ ui32RegisterArraySize) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDump3DSignatureRegistersBW: CopyFromUserWrapper failed"));
+ goto Exit;
+ }
+
+ PDump3DSignatureRegisters(&psDeviceNode->sDevId,
+ psPDump3DSignatureRegistersIN->ui32DumpFrameNum,
+ psPDump3DSignatureRegistersIN->bLastFrame,
+ pui32Registers,
+ psPDump3DSignatureRegistersIN->ui32NumRegisters);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle( psPerProc->psHandleBase,
+ &hDevMemContextInt,
+ psPDump3DSignatureRegistersIN->hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ PVR_ASSERT(psDeviceNode->pfnMMUGetContextID != IMG_NULL)
+ ui32MMUContextID = psDeviceNode->pfnMMUGetContextID((IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext);
+
+ PDumpSignatureBuffer(&psDeviceNode->sDevId,
+ "out.tasig", "TA", 0,
+ psDevInfo->psKernelTASigBufferMemInfo->sDevVAddr,
+ (IMG_UINT32)psDevInfo->psKernelTASigBufferMemInfo->uAllocSize,
+ ui32MMUContextID,
+ 0 );
+ PDumpSignatureBuffer(&psDeviceNode->sDevId,
+ "out.3dsig", "3D", 0,
+ psDevInfo->psKernel3DSigBufferMemInfo->sDevVAddr,
+ (IMG_UINT32)psDevInfo->psKernel3DSigBufferMemInfo->uAllocSize,
+ ui32MMUContextID,
+ 0 );
+
+ExitNoError:
+ psRetOUT->eError = PVRSRV_OK;
+ ret = 0;
+Exit:
+ if (pui32Registers != IMG_NULL)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32RegisterArraySize, pui32Registers, 0);
+ }
+
+#if defined(SGX_FEATURE_MP) && defined(FIX_HW_BRN_27270)
+ if (psDevInfo != IMG_NULL)
+ {
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE, ui32RegVal);
+#if defined(PDUMP)
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_CORE, ui32RegVal,
+ psPDump3DSignatureRegistersIN->bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+#endif
+ }
+#endif
+
+ return ret;
+}
+
+static IMG_INT
+SGXPDumpCounterRegistersBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_COUNTER_REGISTERS *psPDumpCounterRegistersIN,
+ IMG_VOID *psBridgeOut,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_UINT32 ui32RegisterArraySize = psPDumpCounterRegistersIN->ui32NumRegisters * sizeof(IMG_UINT32);
+ IMG_UINT32 *pui32Registers = IMG_NULL;
+ PVRSRV_DEVICE_NODE *psDeviceNode ;
+ IMG_INT ret = -EFAULT;
+
+ PVR_UNREFERENCED_PARAMETER(psBridgeOut);
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_COUNTER_REGISTERS);
+
+ if (ui32RegisterArraySize == 0)
+ {
+ goto ExitNoError;
+ }
+
+ if(PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID**)&psDeviceNode,
+ psPDumpCounterRegistersIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXPDumpCounterRegistersBW: hDevCookie lookup failed"));
+ ret = -ENOMEM;
+ goto Exit;
+ }
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32RegisterArraySize,
+ (IMG_PVOID *)&pui32Registers, 0,
+ "Array of Registers") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpCounterRegistersBW: OSAllocMem failed"));
+ ret = -ENOMEM;
+ goto Exit;
+ }
+
+ if(CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ pui32Registers,
+ psPDumpCounterRegistersIN->pui32Registers,
+ ui32RegisterArraySize) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpCounterRegistersBW: CopyFromUserWrapper failed"));
+ goto Exit;
+ }
+
+ PDumpCounterRegisters(&psDeviceNode->sDevId,
+ psPDumpCounterRegistersIN->ui32DumpFrameNum,
+ psPDumpCounterRegistersIN->bLastFrame,
+ pui32Registers,
+ psPDumpCounterRegistersIN->ui32NumRegisters);
+
+ExitNoError:
+ ret = 0;
+Exit:
+ if (pui32Registers != IMG_NULL)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32RegisterArraySize, pui32Registers, 0);
+ }
+
+ return ret;
+}
+
+static IMG_INT
+SGXPDumpTASignatureRegistersBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_TA_SIGNATURE_REGISTERS *psPDumpTASignatureRegistersIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_UINT32 ui32RegisterArraySize = psPDumpTASignatureRegistersIN->ui32NumRegisters * sizeof(IMG_UINT32);
+ IMG_UINT32 *pui32Registers = IMG_NULL;
+#if defined(SGX_FEATURE_MP) && defined(FIX_HW_BRN_27270)
+ PVRSRV_SGXDEV_INFO *psDevInfo = IMG_NULL;
+ IMG_UINT32 ui32RegVal = 0;
+#endif
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_INT ret = -EFAULT;
+
+ PVR_UNREFERENCED_PARAMETER(psRetOUT);
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_TA_SIGNATURE_REGISTERS);
+
+ if (ui32RegisterArraySize == 0)
+ {
+ goto ExitNoError;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_VOID**)&psDeviceNode,
+ psPDumpTASignatureRegistersIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpTASignatureRegistersBW: hDevCookie lookup failed"));
+ goto Exit;
+ }
+
+#if defined(SGX_FEATURE_MP) && defined(FIX_HW_BRN_27270)
+
+ psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+
+
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE, (SGX_FEATURE_MP_CORE_COUNT - 1) << EUR_CR_MASTER_CORE_ENABLE_SHIFT);
+#if defined(PDUMP)
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_CORE, (SGX_FEATURE_MP_CORE_COUNT - 1) << EUR_CR_MASTER_CORE_ENABLE_SHIFT,
+ psPDumpTASignatureRegistersIN->bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+#endif
+#endif
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32RegisterArraySize,
+ (IMG_PVOID *)&pui32Registers, 0,
+ "Array of Registers") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpTASignatureRegistersBW: OSAllocMem failed"));
+ ret = -ENOMEM;
+ goto Exit;
+ }
+
+ if(CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ pui32Registers,
+ psPDumpTASignatureRegistersIN->pui32Registers,
+ ui32RegisterArraySize) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpTASignatureRegistersBW: CopyFromUserWrapper failed"));
+ goto Exit;
+ }
+
+ PDumpTASignatureRegisters(&psDeviceNode->sDevId,
+ psPDumpTASignatureRegistersIN->ui32DumpFrameNum,
+ psPDumpTASignatureRegistersIN->ui32TAKickCount,
+ psPDumpTASignatureRegistersIN->bLastFrame,
+ pui32Registers,
+ psPDumpTASignatureRegistersIN->ui32NumRegisters);
+
+ExitNoError:
+ psRetOUT->eError = PVRSRV_OK;
+ ret = 0;
+Exit:
+ if (pui32Registers != IMG_NULL)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32RegisterArraySize, pui32Registers, 0);
+ }
+
+#if defined(SGX_FEATURE_MP) && defined(FIX_HW_BRN_27270)
+ if (psDevInfo != IMG_NULL)
+ {
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE, ui32RegVal);
+#if defined(PDUMP)
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_CORE, ui32RegVal,
+ psPDumpTASignatureRegistersIN->bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+#endif
+ }
+#endif
+
+ return ret;
+}
+static IMG_INT
+SGXPDumpHWPerfCBBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_HWPERFCB *psPDumpHWPerfCBIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+#if defined(SUPPORT_SGX_HWPERF)
+#if defined(__linux__)
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_HANDLE hDevMemContextInt = 0;
+ IMG_UINT32 ui32MMUContextID = 0;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_HWPERFCB);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_VOID**)&psDeviceNode,
+ psPDumpHWPerfCBIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psDevInfo = psDeviceNode->pvDevice;
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle( psPerProc->psHandleBase,
+ &hDevMemContextInt,
+ psPDumpHWPerfCBIN->hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ PVR_ASSERT(psDeviceNode->pfnMMUGetContextID != IMG_NULL)
+ ui32MMUContextID = psDeviceNode->pfnMMUGetContextID(hDevMemContextInt);
+
+ PDumpHWPerfCBKM(&psDeviceNode->sDevId,
+ &psPDumpHWPerfCBIN->szFileName[0],
+ psPDumpHWPerfCBIN->ui32FileOffset,
+ psDevInfo->psKernelHWPerfCBMemInfo->sDevVAddr,
+ psDevInfo->psKernelHWPerfCBMemInfo->uAllocSize,
+ ui32MMUContextID,
+ psPDumpHWPerfCBIN->ui32PDumpFlags);
+
+ return 0;
+#else
+ PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+ PVR_UNREFERENCED_PARAMETER(psPDumpHWPerfCBIN);
+ PVR_UNREFERENCED_PARAMETER(psRetOUT);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+ return 0;
+#endif
+#else
+ PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+ PVR_UNREFERENCED_PARAMETER(psPDumpHWPerfCBIN);
+ PVR_UNREFERENCED_PARAMETER(psRetOUT);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+ return -EFAULT;
+#endif
+}
+
+
+static IMG_INT
+SGXPDumpSaveMemBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_SAVEMEM *psPDumpSaveMem,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_HANDLE hDevMemContextInt = 0;
+ IMG_UINT32 ui32MMUContextID;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_SAVEMEM);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID**)&psDeviceNode,
+ psPDumpSaveMem->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle( psPerProc->psHandleBase,
+ &hDevMemContextInt,
+ psPDumpSaveMem->hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ PVR_ASSERT(psDeviceNode->pfnMMUGetContextID != IMG_NULL)
+ ui32MMUContextID = psDeviceNode->pfnMMUGetContextID(hDevMemContextInt);
+
+ PDumpSaveMemKM(&psDeviceNode->sDevId,
+ &psPDumpSaveMem->szFileName[0],
+ psPDumpSaveMem->ui32FileOffset,
+ psPDumpSaveMem->sDevVAddr,
+ psPDumpSaveMem->ui32Size,
+ ui32MMUContextID,
+ psPDumpSaveMem->ui32PDumpFlags);
+ return 0;
+}
+
+#endif
+
+
+
+IMG_VOID SetSGXDispatchTableEntry(IMG_VOID)
+{
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_GETCLIENTINFO, SGXGetClientInfoBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_RELEASECLIENTINFO, SGXReleaseClientInfoBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_GETINTERNALDEVINFO, SGXGetInternalDevInfoBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_DOKICK, SGXDoKickBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_GETPHYSPAGEADDR, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_READREGISTRYDWORD, DummyBW);
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_2DQUERYBLTSCOMPLETE, SGX2DQueryBlitsCompleteBW);
+
+#if defined(TRANSFER_QUEUE)
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_SUBMITTRANSFER, SGXSubmitTransferBW);
+#endif
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_GETMISCINFO, SGXGetMiscInfoBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGXINFO_FOR_SRVINIT , SGXGetInfoForSrvinitBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_DEVINITPART2, SGXDevInitPart2BW);
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC, SGXFindSharedPBDescBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_UNREFSHAREDPBDESC, SGXUnrefSharedPBDescBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC, SGXAddSharedPBDescBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_REGISTER_HW_RENDER_CONTEXT, SGXRegisterHWRenderContextBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_FLUSH_HW_RENDER_TARGET, SGXFlushHWRenderTargetBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_UNREGISTER_HW_RENDER_CONTEXT, SGXUnregisterHWRenderContextBW);
+#if defined(SGX_FEATURE_2D_HARDWARE)
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_SUBMIT2D, SGXSubmit2DBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_REGISTER_HW_2D_CONTEXT, SGXRegisterHW2DContextBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_UNREGISTER_HW_2D_CONTEXT, SGXUnregisterHW2DContextBW);
+#endif
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_REGISTER_HW_TRANSFER_CONTEXT, SGXRegisterHWTransferContextBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_UNREGISTER_HW_TRANSFER_CONTEXT, SGXUnregisterHWTransferContextBW);
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_SCHEDULE_PROCESS_QUEUES, SGXScheduleProcessQueuesBW);
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_READ_HWPERF_CB, SGXReadHWPerfCBBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_SET_RENDER_CONTEXT_PRIORITY, SGXSetRenderContextPriorityBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_SET_TRANSFER_CONTEXT_PRIORITY, SGXSetTransferContextPriorityBW);
+
+#if defined(PDUMP)
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY, SGXPDumpBufferArrayBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_PDUMP_3D_SIGNATURE_REGISTERS, SGXPDump3DSignatureRegistersBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_PDUMP_COUNTER_REGISTERS, SGXPDumpCounterRegistersBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_PDUMP_TA_SIGNATURE_REGISTERS, SGXPDumpTASignatureRegistersBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_PDUMP_HWPERFCB, SGXPDumpHWPerfCBBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_PDUMP_SAVEMEM, SGXPDumpSaveMemBW);
+#endif
+}
+
+
+#endif
diff --git a/drivers/gpu/pvr/sgx/bridged_sgx_bridge.h b/drivers/gpu/pvr/sgx/bridged_sgx_bridge.h
new file mode 100644
index 0000000..204450c
--- /dev/null
+++ b/drivers/gpu/pvr/sgx/bridged_sgx_bridge.h
@@ -0,0 +1,42 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __BRIDGED_SGX_BRIDGE_H__
+#define __BRIDGED_SGX_BRIDGE_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+
+IMG_VOID SetSGXDispatchTableEntry(IMG_VOID);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/pvr/sgx/mmu.c b/drivers/gpu/pvr/sgx/mmu.c
new file mode 100644
index 0000000..cde8307
--- /dev/null
+++ b/drivers/gpu/pvr/sgx/mmu.c
@@ -0,0 +1,3935 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "sgxdefs.h"
+#include "sgxmmu.h"
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "hash.h"
+#include "ra.h"
+#include "pdump_km.h"
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+#include "mmu.h"
+#include "sgxconfig.h"
+#include "sgx_bridge_km.h"
+#include "pdump_osfunc.h"
+
+#define UINT32_MAX_VALUE 0xFFFFFFFFUL
+
+#define SGX_MAX_PD_ENTRIES (1<<(SGX_FEATURE_ADDRESS_SPACE_SIZE - SGX_MMU_PT_SHIFT - SGX_MMU_PAGE_SHIFT))
+
+#if defined(FIX_HW_BRN_31620)
+#define SGX_MMU_PDE_DUMMY_PAGE (0)
+#define SGX_MMU_PTE_DUMMY_PAGE (0)
+
+#define BRN31620_PT_ADDRESS_RANGE_SHIFT 22
+#define BRN31620_PT_ADDRESS_RANGE_SIZE (1 << BRN31620_PT_ADDRESS_RANGE_SHIFT)
+
+#define BRN31620_PDE_CACHE_FILL_SHIFT 26
+#define BRN31620_PDE_CACHE_FILL_SIZE (1 << BRN31620_PDE_CACHE_FILL_SHIFT)
+#define BRN31620_PDE_CACHE_FILL_MASK (BRN31620_PDE_CACHE_FILL_SIZE - 1)
+
+#define BRN31620_PDES_PER_CACHE_LINE_SHIFT (BRN31620_PDE_CACHE_FILL_SHIFT - BRN31620_PT_ADDRESS_RANGE_SHIFT)
+#define BRN31620_PDES_PER_CACHE_LINE_SIZE (1 << BRN31620_PDES_PER_CACHE_LINE_SHIFT)
+#define BRN31620_PDES_PER_CACHE_LINE_MASK (BRN31620_PDES_PER_CACHE_LINE_SIZE - 1)
+
+#define BRN31620_DUMMY_PAGE_OFFSET (1 * SGX_MMU_PAGE_SIZE)
+#define BRN31620_DUMMY_PDE_INDEX (BRN31620_DUMMY_PAGE_OFFSET / BRN31620_PT_ADDRESS_RANGE_SIZE)
+#define BRN31620_DUMMY_PTE_INDEX ((BRN31620_DUMMY_PAGE_OFFSET - (BRN31620_DUMMY_PDE_INDEX * BRN31620_PT_ADDRESS_RANGE_SIZE))/SGX_MMU_PAGE_SIZE)
+
+#define BRN31620_CACHE_FLUSH_SHIFT (32 - BRN31620_PDE_CACHE_FILL_SHIFT)
+#define BRN31620_CACHE_FLUSH_SIZE (1 << BRN31620_CACHE_FLUSH_SHIFT)
+
+#define BRN31620_CACHE_FLUSH_BITS_SHIFT 5
+#define BRN31620_CACHE_FLUSH_BITS_SIZE (1 << BRN31620_CACHE_FLUSH_BITS_SHIFT)
+#define BRN31620_CACHE_FLUSH_BITS_MASK (BRN31620_CACHE_FLUSH_BITS_SIZE - 1)
+
+#define BRN31620_CACHE_FLUSH_INDEX_BITS (BRN31620_CACHE_FLUSH_SHIFT - BRN31620_CACHE_FLUSH_BITS_SHIFT)
+#define BRN31620_CACHE_FLUSH_INDEX_SIZE (1 << BRN31620_CACHE_FLUSH_INDEX_BITS)
+
+#define BRN31620_DUMMY_PAGE_SIGNATURE 0xFEEBEE01
+#endif
+
+typedef struct _MMU_PT_INFO_
+{
+
+ IMG_VOID *hPTPageOSMemHandle;
+ IMG_CPU_VIRTADDR PTPageCpuVAddr;
+
+
+ IMG_UINT32 ui32ValidPTECount;
+} MMU_PT_INFO;
+
+struct _MMU_CONTEXT_
+{
+
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+
+ IMG_CPU_VIRTADDR pvPDCpuVAddr;
+ IMG_DEV_PHYADDR sPDDevPAddr;
+
+ IMG_VOID *hPDOSMemHandle;
+
+
+ MMU_PT_INFO *apsPTInfoList[SGX_MAX_PD_ENTRIES];
+
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+
+#if defined(PDUMP)
+ IMG_UINT32 ui32PDumpMMUContextID;
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+ IMG_BOOL bPDumpActive;
+#endif
+#endif
+
+#if defined (FIX_HW_BRN_31620)
+ IMG_UINT32 ui32PDChangeMask[BRN31620_CACHE_FLUSH_INDEX_SIZE];
+ IMG_UINT32 ui32PDCacheRangeRefCount[BRN31620_CACHE_FLUSH_SIZE];
+ MMU_PT_INFO *apsPTInfoListSave[SGX_MAX_PD_ENTRIES];
+#endif
+ struct _MMU_CONTEXT_ *psNext;
+};
+
+struct _MMU_HEAP_
+{
+
+ MMU_CONTEXT *psMMUContext;
+
+
+
+
+ IMG_UINT32 ui32PDBaseIndex;
+
+ IMG_UINT32 ui32PageTableCount;
+
+ IMG_UINT32 ui32PTETotalUsable;
+
+ IMG_UINT32 ui32PDEPageSizeCtrl;
+
+
+
+
+ IMG_UINT32 ui32DataPageSize;
+
+ IMG_UINT32 ui32DataPageBitWidth;
+
+ IMG_UINT32 ui32DataPageMask;
+
+
+
+
+ IMG_UINT32 ui32PTShift;
+
+ IMG_UINT32 ui32PTBitWidth;
+
+ IMG_UINT32 ui32PTMask;
+
+ IMG_UINT32 ui32PTSize;
+
+ IMG_UINT32 ui32PTNumEntriesAllocated;
+
+ IMG_UINT32 ui32PTNumEntriesUsable;
+
+
+
+
+ IMG_UINT32 ui32PDShift;
+
+ IMG_UINT32 ui32PDBitWidth;
+
+ IMG_UINT32 ui32PDMask;
+
+
+
+ RA_ARENA *psVMArena;
+ DEV_ARENA_DESCRIPTOR *psDevArena;
+#if defined(PDUMP)
+ PDUMP_MMU_ATTRIB sMMUAttrib;
+#endif
+};
+
+
+
+#if defined (SUPPORT_SGX_MMU_DUMMY_PAGE)
+#define DUMMY_DATA_PAGE_SIGNATURE 0xDEADBEEF
+#endif
+
+static IMG_VOID
+_DeferredFreePageTable (MMU_HEAP *pMMUHeap, IMG_UINT32 ui32PTIndex, IMG_BOOL bOSFreePT);
+
+#if defined(PDUMP)
+static IMG_VOID
+MMU_PDumpPageTables (MMU_HEAP *pMMUHeap,
+ IMG_DEV_VIRTADDR DevVAddr,
+ IMG_SIZE_T uSize,
+ IMG_BOOL bForUnmap,
+ IMG_HANDLE hUniqueTag);
+#endif
+
+#define PAGE_TEST 0
+#if PAGE_TEST
+static IMG_VOID PageTest(IMG_VOID* pMem, IMG_DEV_PHYADDR sDevPAddr);
+#endif
+
+#define PT_DUMP 1
+
+#define PT_DEBUG 0
+#if (PT_DEBUG || PT_DUMP) && defined(PVRSRV_NEED_PVR_DPF)
+static IMG_VOID DumpPT(MMU_PT_INFO *psPTInfoList)
+{
+ IMG_UINT32 *p = (IMG_UINT32*)psPTInfoList->PTPageCpuVAddr;
+ IMG_UINT32 i;
+
+
+ for(i = 0; i < 1024; i += 8)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%08X %08X %08X %08X %08X %08X %08X %08X\n",
+ p[i + 0], p[i + 1], p[i + 2], p[i + 3],
+ p[i + 4], p[i + 5], p[i + 6], p[i + 7]));
+ }
+}
+#else
+static INLINE IMG_VOID DumpPT(MMU_PT_INFO *psPTInfoList)
+{
+ PVR_UNREFERENCED_PARAMETER(psPTInfoList);
+}
+#endif
+
+#if PT_DEBUG
+static IMG_VOID CheckPT(MMU_PT_INFO *psPTInfoList)
+{
+ IMG_UINT32 *p = (IMG_UINT32*) psPTInfoList->PTPageCpuVAddr;
+ IMG_UINT32 i, ui32Count = 0;
+
+
+ for(i = 0; i < 1024; i++)
+ if(p[i] & SGX_MMU_PTE_VALID)
+ ui32Count++;
+
+ if(psPTInfoList->ui32ValidPTECount != ui32Count)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ui32ValidPTECount: %u ui32Count: %u\n",
+ psPTInfoList->ui32ValidPTECount, ui32Count));
+ DumpPT(psPTInfoList);
+ BUG();
+ }
+}
+#else
+static INLINE IMG_VOID CheckPT(MMU_PT_INFO *psPTInfoList)
+{
+ PVR_UNREFERENCED_PARAMETER(psPTInfoList);
+}
+#endif
+
+#if defined(PVRSRV_MMU_MAKE_READWRITE_ON_DEMAND)
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#else
+#include <generated/autoconf.h>
+#endif
+
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/highmem.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
+
+static IMG_VOID MakeKernelPageReadWrite(IMG_PVOID ulCPUVAddr)
+{
+ pgd_t *psPGD;
+ pud_t *psPUD;
+ pmd_t *psPMD;
+ pte_t *psPTE;
+ pte_t ptent;
+ IMG_UINT32 ui32CPUVAddr = (IMG_UINT32) ulCPUVAddr;
+
+ psPGD = pgd_offset_k(ui32CPUVAddr);
+ if (pgd_none(*psPGD) || pgd_bad(*psPGD))
+ {
+ PVR_ASSERT(0);
+ }
+
+ psPUD = pud_offset(psPGD, ui32CPUVAddr);
+ if (pud_none(*psPUD) || pud_bad(*psPUD))
+ {
+ PVR_ASSERT(0);
+ }
+
+ psPMD = pmd_offset(psPUD, ui32CPUVAddr);
+ if (pmd_none(*psPMD) || pmd_bad(*psPMD))
+ {
+ PVR_ASSERT(0);
+ }
+ psPTE = (pte_t *)pte_offset_kernel(psPMD, ui32CPUVAddr);
+
+ ptent = ptep_modify_prot_start(&init_mm, ui32CPUVAddr, psPTE);
+ ptent = pte_mkwrite(ptent);
+ ptep_modify_prot_commit(&init_mm, ui32CPUVAddr, psPTE, ptent);
+
+ flush_tlb_all();
+}
+
+static IMG_VOID MakeKernelPageReadOnly(IMG_PVOID ulCPUVAddr)
+{
+ pgd_t *psPGD;
+ pud_t *psPUD;
+ pmd_t *psPMD;
+ pte_t *psPTE;
+ pte_t ptent;
+ IMG_UINT32 ui32CPUVAddr = (IMG_UINT32) ulCPUVAddr;
+
+ OSWriteMemoryBarrier();
+
+ psPGD = pgd_offset_k(ui32CPUVAddr);
+ if (pgd_none(*psPGD) || pgd_bad(*psPGD))
+ {
+ PVR_ASSERT(0);
+ }
+
+ psPUD = pud_offset(psPGD, ui32CPUVAddr);
+ if (pud_none(*psPUD) || pud_bad(*psPUD))
+ {
+ PVR_ASSERT(0);
+ }
+
+ psPMD = pmd_offset(psPUD, ui32CPUVAddr);
+ if (pmd_none(*psPMD) || pmd_bad(*psPMD))
+ {
+ PVR_ASSERT(0);
+ }
+
+ psPTE = (pte_t *)pte_offset_kernel(psPMD, ui32CPUVAddr);
+
+ ptent = ptep_modify_prot_start(&init_mm, ui32CPUVAddr, psPTE);
+ ptent = pte_wrprotect(ptent);
+ ptep_modify_prot_commit(&init_mm, ui32CPUVAddr, psPTE, ptent);
+
+ flush_tlb_all();
+
+}
+
+#else
+
+static INLINE IMG_VOID MakeKernelPageReadWrite(IMG_PVOID ulCPUVAddr)
+{
+ PVR_UNREFERENCED_PARAMETER(ulCPUVAddr);
+}
+
+static INLINE IMG_VOID MakeKernelPageReadOnly(IMG_PVOID ulCPUVAddr)
+{
+ PVR_UNREFERENCED_PARAMETER(ulCPUVAddr);
+}
+
+#endif
+
+IMG_BOOL MMU_IsHeapShared(MMU_HEAP* pMMUHeap)
+{
+ switch(pMMUHeap->psDevArena->DevMemHeapType)
+ {
+ case DEVICE_MEMORY_HEAP_SHARED :
+ case DEVICE_MEMORY_HEAP_SHARED_EXPORTED :
+ return IMG_TRUE;
+ case DEVICE_MEMORY_HEAP_PERCONTEXT :
+ case DEVICE_MEMORY_HEAP_KERNEL :
+ return IMG_FALSE;
+ default:
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_IsHeapShared: ERROR invalid heap type"));
+ return IMG_FALSE;
+ }
+ }
+}
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+IMG_VOID
+EnableHostAccess (MMU_CONTEXT *psMMUContext)
+{
+ IMG_UINT32 ui32RegVal;
+ IMG_VOID *pvRegsBaseKM = psMMUContext->psDevInfo->pvRegsBaseKM;
+
+
+
+
+ ui32RegVal = OSReadHWReg(pvRegsBaseKM, EUR_CR_BIF_CTRL);
+
+ OSWriteHWReg(pvRegsBaseKM,
+ EUR_CR_BIF_CTRL,
+ ui32RegVal | EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_MASK);
+
+ PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_MASK);
+}
+
+IMG_VOID
+DisableHostAccess (MMU_CONTEXT *psMMUContext)
+{
+ IMG_UINT32 ui32RegVal;
+ IMG_VOID *pvRegsBaseKM = psMMUContext->psDevInfo->pvRegsBaseKM;
+
+
+
+
+
+ OSWriteHWReg(pvRegsBaseKM,
+ EUR_CR_BIF_CTRL,
+ ui32RegVal & ~EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_MASK);
+
+ PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, 0);
+}
+#endif
+
+
+#if defined(SGX_FEATURE_SYSTEM_CACHE)
+static IMG_VOID MMU_InvalidateSystemLevelCache(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ #if defined(SGX_FEATURE_MP)
+ psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_BIF_SL;
+ #else
+
+ PVR_UNREFERENCED_PARAMETER(psDevInfo);
+ #endif
+}
+#endif
+
+IMG_VOID MMU_InvalidateDirectoryCache(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_BIF_PD;
+ #if defined(SGX_FEATURE_SYSTEM_CACHE)
+ MMU_InvalidateSystemLevelCache(psDevInfo);
+ #endif
+}
+
+
+static IMG_VOID MMU_InvalidatePageTableCache(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_BIF_PT;
+ #if defined(SGX_FEATURE_SYSTEM_CACHE)
+ MMU_InvalidateSystemLevelCache(psDevInfo);
+ #endif
+}
+
+#if defined(FIX_HW_BRN_31620)
+static IMG_VOID BRN31620InvalidatePageTableEntry(MMU_CONTEXT *psMMUContext, IMG_UINT32 ui32PDIndex, IMG_UINT32 ui32PTIndex, IMG_UINT32 *pui32PTE)
+{
+ PVRSRV_SGXDEV_INFO *psDevInfo = psMMUContext->psDevInfo;
+
+
+ if (((ui32PDIndex % (BRN31620_PDE_CACHE_FILL_SIZE/BRN31620_PT_ADDRESS_RANGE_SIZE)) == BRN31620_DUMMY_PDE_INDEX)
+ && (ui32PTIndex == BRN31620_DUMMY_PTE_INDEX))
+ {
+ *pui32PTE = (psDevInfo->sBRN31620DummyPageDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PTE_DUMMY_PAGE
+ | SGX_MMU_PTE_READONLY
+ | SGX_MMU_PTE_VALID;
+ }
+ else
+ {
+ *pui32PTE = 0;
+ }
+}
+
+static IMG_BOOL BRN31620FreePageTable(MMU_HEAP *psMMUHeap, IMG_UINT32 ui32PDIndex)
+{
+ MMU_CONTEXT *psMMUContext = psMMUHeap->psMMUContext;
+ PVRSRV_SGXDEV_INFO *psDevInfo = psMMUContext->psDevInfo;
+ IMG_UINT32 ui32PDCacheLine = ui32PDIndex >> BRN31620_PDES_PER_CACHE_LINE_SHIFT;
+ IMG_UINT32 bFreePTs = IMG_FALSE;
+ IMG_UINT32 *pui32Tmp;
+
+ PVR_ASSERT(psMMUHeap != IMG_NULL);
+
+
+ PVR_ASSERT(psMMUContext->apsPTInfoListSave[ui32PDIndex] == IMG_NULL);
+
+ psMMUContext->apsPTInfoListSave[ui32PDIndex] = psMMUContext->apsPTInfoList[ui32PDIndex];
+ psMMUContext->apsPTInfoList[ui32PDIndex] = IMG_NULL;
+
+
+ if (--psMMUContext->ui32PDCacheRangeRefCount[ui32PDCacheLine] == 0)
+ {
+ IMG_UINT32 i;
+ IMG_UINT32 ui32PDIndexStart = ui32PDCacheLine * BRN31620_PDES_PER_CACHE_LINE_SIZE;
+ IMG_UINT32 ui32PDIndexEnd = ui32PDIndexStart + BRN31620_PDES_PER_CACHE_LINE_SIZE;
+ IMG_UINT32 ui32PDBitMaskIndex, ui32PDBitMaskShift;
+
+
+ for (i=ui32PDIndexStart;i<ui32PDIndexEnd;i++)
+ {
+
+ psMMUContext->apsPTInfoList[i] = psMMUContext->apsPTInfoListSave[i];
+ psMMUContext->apsPTInfoListSave[i] = IMG_NULL;
+ _DeferredFreePageTable(psMMUHeap, i - psMMUHeap->ui32PDBaseIndex, IMG_TRUE);
+ }
+
+ ui32PDBitMaskIndex = ui32PDCacheLine >> BRN31620_CACHE_FLUSH_BITS_SHIFT;
+ ui32PDBitMaskShift = ui32PDCacheLine & BRN31620_CACHE_FLUSH_BITS_MASK;
+
+
+ if (MMU_IsHeapShared(psMMUHeap))
+ {
+
+ MMU_CONTEXT *psMMUContextWalker = (MMU_CONTEXT*) psMMUHeap->psMMUContext->psDevInfo->pvMMUContextList;
+
+ while(psMMUContextWalker)
+ {
+ psMMUContextWalker->ui32PDChangeMask[ui32PDBitMaskIndex] |= 1 << ui32PDBitMaskShift;
+
+
+ MakeKernelPageReadWrite(psMMUContextWalker->pvPDCpuVAddr);
+ pui32Tmp = (IMG_UINT32 *) psMMUContextWalker->pvPDCpuVAddr;
+ pui32Tmp[ui32PDIndexStart + BRN31620_DUMMY_PDE_INDEX] = (psDevInfo->sBRN31620DummyPTDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PDE_PAGE_SIZE_4K
+ | SGX_MMU_PDE_DUMMY_PAGE
+ | SGX_MMU_PDE_VALID;
+ MakeKernelPageReadOnly(psMMUContextWalker->pvPDCpuVAddr);
+
+ PDUMPCOMMENT("BRN31620 Re-wire dummy PT due to releasing PT allocation block");
+ PDUMPPDENTRIES(&psMMUHeap->sMMUAttrib, psMMUContextWalker->hPDOSMemHandle, (IMG_VOID*)&pui32Tmp[ui32PDIndexStart + BRN31620_DUMMY_PDE_INDEX], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ psMMUContextWalker = psMMUContextWalker->psNext;
+ }
+ }
+ else
+ {
+ psMMUContext->ui32PDChangeMask[ui32PDBitMaskIndex] |= 1 << ui32PDBitMaskShift;
+
+
+ MakeKernelPageReadWrite(psMMUContext->pvPDCpuVAddr);
+ pui32Tmp = (IMG_UINT32 *) psMMUContext->pvPDCpuVAddr;
+ pui32Tmp[ui32PDIndexStart + BRN31620_DUMMY_PDE_INDEX] = (psDevInfo->sBRN31620DummyPTDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PDE_PAGE_SIZE_4K
+ | SGX_MMU_PDE_DUMMY_PAGE
+ | SGX_MMU_PDE_VALID;
+ MakeKernelPageReadOnly(psMMUContext->pvPDCpuVAddr);
+
+ PDUMPCOMMENT("BRN31620 Re-wire dummy PT due to releasing PT allocation block");
+ PDUMPPDENTRIES(&psMMUHeap->sMMUAttrib, psMMUContext->hPDOSMemHandle, (IMG_VOID*)&pui32Tmp[ui32PDIndexStart + BRN31620_DUMMY_PDE_INDEX], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ }
+
+ bFreePTs = IMG_TRUE;
+ }
+
+ return bFreePTs;
+}
+#endif
+
+static IMG_BOOL
+_AllocPageTableMemory (MMU_HEAP *pMMUHeap,
+ MMU_PT_INFO *psPTInfoList,
+ IMG_DEV_PHYADDR *psDevPAddr)
+{
+ IMG_DEV_PHYADDR sDevPAddr;
+ IMG_CPU_PHYADDR sCpuPAddr;
+
+
+
+
+ if(pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->psLocalDevMemArena == IMG_NULL)
+ {
+
+ if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ pMMUHeap->ui32PTSize,
+ SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ 0,
+ (IMG_VOID **)&psPTInfoList->PTPageCpuVAddr,
+ &psPTInfoList->hPTPageOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "_AllocPageTableMemory: ERROR call to OSAllocPages failed"));
+ return IMG_FALSE;
+ }
+
+
+
+
+ MakeKernelPageReadOnly(psPTInfoList->PTPageCpuVAddr);
+
+
+ if(psPTInfoList->PTPageCpuVAddr)
+ {
+ sCpuPAddr = OSMapLinToCPUPhys(psPTInfoList->hPTPageOSMemHandle,
+ psPTInfoList->PTPageCpuVAddr);
+ }
+ else
+ {
+
+ sCpuPAddr = OSMemHandleToCpuPAddr(psPTInfoList->hPTPageOSMemHandle, 0);
+ }
+
+ sDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+ }
+ else
+ {
+ IMG_SYS_PHYADDR sSysPAddr;
+
+
+
+
+
+ if(RA_Alloc(pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->psLocalDevMemArena,
+ SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ IMG_NULL,
+ 0,
+ SGX_MMU_PAGE_SIZE,
+ 0,
+ IMG_NULL,
+ 0,
+ &(sSysPAddr.uiAddr))!= IMG_TRUE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "_AllocPageTableMemory: ERROR call to RA_Alloc failed"));
+ return IMG_FALSE;
+ }
+
+
+ sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+
+ psPTInfoList->PTPageCpuVAddr = OSMapPhysToLin(sCpuPAddr,
+ SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ &psPTInfoList->hPTPageOSMemHandle);
+ if(!psPTInfoList->PTPageCpuVAddr)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "_AllocPageTableMemory: ERROR failed to map page tables"));
+ return IMG_FALSE;
+ }
+
+
+ sDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+
+ #if PAGE_TEST
+ PageTest(psPTInfoList->PTPageCpuVAddr, sDevPAddr);
+ #endif
+ }
+
+ MakeKernelPageReadWrite(psPTInfoList->PTPageCpuVAddr);
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+ {
+ IMG_UINT32 *pui32Tmp;
+ IMG_UINT32 i;
+
+ pui32Tmp = (IMG_UINT32*)psPTInfoList->PTPageCpuVAddr;
+
+ for(i=0; i<pMMUHeap->ui32PTNumEntriesUsable; i++)
+ {
+ pui32Tmp[i] = (pMMUHeap->psMMUContext->psDevInfo->sDummyDataDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PTE_VALID;
+ }
+
+ for(; i<pMMUHeap->ui32PTNumEntriesAllocated; i++)
+ {
+ pui32Tmp[i] = 0;
+ }
+ }
+#else
+
+ OSMemSet(psPTInfoList->PTPageCpuVAddr, 0, pMMUHeap->ui32PTSize);
+#endif
+ MakeKernelPageReadOnly(psPTInfoList->PTPageCpuVAddr);
+
+#if defined(PDUMP)
+ {
+ IMG_UINT32 ui32Flags = 0;
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+
+ ui32Flags |= ( MMU_IsHeapShared(pMMUHeap) ) ? PDUMP_FLAGS_PERSISTENT : 0;
+#endif
+
+ PDUMPMALLOCPAGETABLE(&pMMUHeap->psMMUContext->psDeviceNode->sDevId, psPTInfoList->hPTPageOSMemHandle, 0, psPTInfoList->PTPageCpuVAddr, pMMUHeap->ui32PTSize, ui32Flags, PDUMP_PT_UNIQUETAG);
+
+ PDUMPMEMPTENTRIES(&pMMUHeap->sMMUAttrib, psPTInfoList->hPTPageOSMemHandle, psPTInfoList->PTPageCpuVAddr, pMMUHeap->ui32PTSize, ui32Flags, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ }
+#endif
+
+
+ *psDevPAddr = sDevPAddr;
+
+ return IMG_TRUE;
+}
+
+
+static IMG_VOID
+_FreePageTableMemory (MMU_HEAP *pMMUHeap, MMU_PT_INFO *psPTInfoList)
+{
+
+
+
+
+ if(pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->psLocalDevMemArena == IMG_NULL)
+ {
+
+ MakeKernelPageReadWrite(psPTInfoList->PTPageCpuVAddr);
+
+
+ OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ pMMUHeap->ui32PTSize,
+ psPTInfoList->PTPageCpuVAddr,
+ psPTInfoList->hPTPageOSMemHandle);
+ }
+ else
+ {
+ IMG_SYS_PHYADDR sSysPAddr;
+ IMG_CPU_PHYADDR sCpuPAddr;
+
+
+ sCpuPAddr = OSMapLinToCPUPhys(psPTInfoList->hPTPageOSMemHandle,
+ psPTInfoList->PTPageCpuVAddr);
+ sSysPAddr = SysCpuPAddrToSysPAddr (sCpuPAddr);
+
+
+
+ OSUnMapPhysToLin(psPTInfoList->PTPageCpuVAddr,
+ SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ psPTInfoList->hPTPageOSMemHandle);
+
+
+
+
+ RA_Free (pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
+ }
+}
+
+
+
+static IMG_VOID
+_DeferredFreePageTable (MMU_HEAP *pMMUHeap, IMG_UINT32 ui32PTIndex, IMG_BOOL bOSFreePT)
+{
+ IMG_UINT32 *pui32PDEntry;
+ IMG_UINT32 i;
+ IMG_UINT32 ui32PDIndex;
+ SYS_DATA *psSysData;
+ MMU_PT_INFO **ppsPTInfoList;
+
+ SysAcquireData(&psSysData);
+
+
+ ui32PDIndex = pMMUHeap->psDevArena->BaseDevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+
+ ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+ {
+#if PT_DEBUG
+ if(ppsPTInfoList[ui32PTIndex] && ppsPTInfoList[ui32PTIndex]->ui32ValidPTECount > 0)
+ {
+ DumpPT(ppsPTInfoList[ui32PTIndex]);
+
+ }
+#endif
+
+
+ PVR_ASSERT(ppsPTInfoList[ui32PTIndex] == IMG_NULL || ppsPTInfoList[ui32PTIndex]->ui32ValidPTECount == 0);
+ }
+
+#if defined(PDUMP)
+ {
+ IMG_UINT32 ui32Flags = 0;
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+ ui32Flags |= ( MMU_IsHeapShared(pMMUHeap) ) ? PDUMP_FLAGS_PERSISTENT : 0;
+#endif
+
+ PDUMPCOMMENT("Free page table (page count == %08X)", pMMUHeap->ui32PageTableCount);
+ if(ppsPTInfoList[ui32PTIndex] && ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr)
+ {
+ PDUMPFREEPAGETABLE(&pMMUHeap->psMMUContext->psDeviceNode->sDevId, ppsPTInfoList[ui32PTIndex]->hPTPageOSMemHandle, ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr, pMMUHeap->ui32PTSize, ui32Flags, PDUMP_PT_UNIQUETAG);
+ }
+ }
+#endif
+
+ switch(pMMUHeap->psDevArena->DevMemHeapType)
+ {
+ case DEVICE_MEMORY_HEAP_SHARED :
+ case DEVICE_MEMORY_HEAP_SHARED_EXPORTED :
+ {
+
+ MMU_CONTEXT *psMMUContext = (MMU_CONTEXT*)pMMUHeap->psMMUContext->psDevInfo->pvMMUContextList;
+
+ while(psMMUContext)
+ {
+
+ MakeKernelPageReadWrite(psMMUContext->pvPDCpuVAddr);
+ pui32PDEntry = (IMG_UINT32*)psMMUContext->pvPDCpuVAddr;
+ pui32PDEntry += ui32PDIndex;
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+ pui32PDEntry[ui32PTIndex] = (psMMUContext->psDevInfo->sDummyPTDevPAddr.uiAddr
+ >>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PDE_PAGE_SIZE_4K
+ | SGX_MMU_PDE_VALID;
+#else
+
+ if(bOSFreePT)
+ {
+ pui32PDEntry[ui32PTIndex] = 0;
+ }
+#endif
+ MakeKernelPageReadOnly(psMMUContext->pvPDCpuVAddr);
+ #if defined(PDUMP)
+
+ #if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+ if(psMMUContext->bPDumpActive)
+ #endif
+ {
+ PDUMPPDENTRIES(&pMMUHeap->sMMUAttrib, psMMUContext->hPDOSMemHandle, (IMG_VOID*)&pui32PDEntry[ui32PTIndex], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ }
+ #endif
+
+ psMMUContext = psMMUContext->psNext;
+ }
+ break;
+ }
+ case DEVICE_MEMORY_HEAP_PERCONTEXT :
+ case DEVICE_MEMORY_HEAP_KERNEL :
+ {
+ MakeKernelPageReadWrite(pMMUHeap->psMMUContext->pvPDCpuVAddr);
+
+ pui32PDEntry = (IMG_UINT32*)pMMUHeap->psMMUContext->pvPDCpuVAddr;
+ pui32PDEntry += ui32PDIndex;
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+ pui32PDEntry[ui32PTIndex] = (pMMUHeap->psMMUContext->psDevInfo->sDummyPTDevPAddr.uiAddr
+ >>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PDE_PAGE_SIZE_4K
+ | SGX_MMU_PDE_VALID;
+#else
+
+ if(bOSFreePT)
+ {
+ pui32PDEntry[ui32PTIndex] = 0;
+ }
+#endif
+ MakeKernelPageReadOnly(pMMUHeap->psMMUContext->pvPDCpuVAddr);
+
+
+ PDUMPPDENTRIES(&pMMUHeap->sMMUAttrib, pMMUHeap->psMMUContext->hPDOSMemHandle, (IMG_VOID*)&pui32PDEntry[ui32PTIndex], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ break;
+ }
+ default:
+ {
+ PVR_DPF((PVR_DBG_ERROR, "_DeferredFreePagetable: ERROR invalid heap type"));
+ return;
+ }
+ }
+
+
+ if(ppsPTInfoList[ui32PTIndex] != IMG_NULL)
+ {
+ if(ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr != IMG_NULL)
+ {
+ IMG_PUINT32 pui32Tmp;
+
+ MakeKernelPageReadWrite(ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr);
+ pui32Tmp = (IMG_UINT32*)ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr;
+
+
+ for(i=0;
+ (i<pMMUHeap->ui32PTETotalUsable) && (i<pMMUHeap->ui32PTNumEntriesUsable);
+ i++)
+ {
+
+ pui32Tmp[i] = 0;
+ }
+ MakeKernelPageReadOnly(ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr);
+
+
+
+ if(bOSFreePT)
+ {
+ _FreePageTableMemory(pMMUHeap, ppsPTInfoList[ui32PTIndex]);
+ }
+
+
+
+
+ pMMUHeap->ui32PTETotalUsable -= i;
+ }
+ else
+ {
+
+ pMMUHeap->ui32PTETotalUsable -= pMMUHeap->ui32PTNumEntriesUsable;
+ }
+
+ if(bOSFreePT)
+ {
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(MMU_PT_INFO),
+ ppsPTInfoList[ui32PTIndex],
+ IMG_NULL);
+ ppsPTInfoList[ui32PTIndex] = IMG_NULL;
+ }
+ }
+ else
+ {
+
+ pMMUHeap->ui32PTETotalUsable -= pMMUHeap->ui32PTNumEntriesUsable;
+ }
+
+ PDUMPCOMMENT("Finished free page table (page count == %08X)", pMMUHeap->ui32PageTableCount);
+}
+
+static IMG_VOID
+_DeferredFreePageTables (MMU_HEAP *pMMUHeap)
+{
+ IMG_UINT32 i;
+#if defined(FIX_HW_BRN_31620)
+ MMU_CONTEXT *psMMUContext = pMMUHeap->psMMUContext;
+ IMG_BOOL bInvalidateDirectoryCache = IMG_FALSE;
+ IMG_UINT32 ui32PDIndex;
+ IMG_UINT32 *pui32Tmp;
+ IMG_UINT32 j;
+#endif
+#if defined(PDUMP)
+ PDUMPCOMMENT("Free PTs (MMU Context ID == %u, PDBaseIndex == %u, PT count == 0x%x)",
+ pMMUHeap->psMMUContext->ui32PDumpMMUContextID,
+ pMMUHeap->ui32PDBaseIndex,
+ pMMUHeap->ui32PageTableCount);
+#endif
+#if defined(FIX_HW_BRN_31620)
+ for(i=0; i<pMMUHeap->ui32PageTableCount; i++)
+ {
+ ui32PDIndex = (pMMUHeap->ui32PDBaseIndex + i);
+
+ if (psMMUContext->apsPTInfoList[ui32PDIndex])
+ {
+ if (psMMUContext->apsPTInfoList[ui32PDIndex]->PTPageCpuVAddr)
+ {
+
+ for (j=0;j<SGX_MMU_PT_SIZE;j++)
+ {
+ pui32Tmp = (IMG_UINT32 *) psMMUContext->apsPTInfoList[ui32PDIndex]->PTPageCpuVAddr;
+ BRN31620InvalidatePageTableEntry(psMMUContext, ui32PDIndex, j, &pui32Tmp[j]);
+ }
+ }
+
+ if (BRN31620FreePageTable(pMMUHeap, ui32PDIndex) == IMG_TRUE)
+ {
+ bInvalidateDirectoryCache = IMG_TRUE;
+ }
+ }
+ }
+
+
+ if (bInvalidateDirectoryCache)
+ {
+ MMU_InvalidateDirectoryCache(pMMUHeap->psMMUContext->psDevInfo);
+ }
+ else
+ {
+ MMU_InvalidatePageTableCache(pMMUHeap->psMMUContext->psDevInfo);
+ }
+#else
+ for(i=0; i<pMMUHeap->ui32PageTableCount; i++)
+ {
+ _DeferredFreePageTable(pMMUHeap, i, IMG_TRUE);
+ }
+ MMU_InvalidateDirectoryCache(pMMUHeap->psMMUContext->psDevInfo);
+#endif
+}
+
+
+static IMG_BOOL
+_DeferredAllocPagetables(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT32 ui32Size)
+{
+ IMG_UINT32 ui32PageTableCount;
+ IMG_UINT32 ui32PDIndex;
+ IMG_UINT32 i;
+ IMG_UINT32 *pui32PDEntry;
+ MMU_PT_INFO **ppsPTInfoList;
+ SYS_DATA *psSysData;
+ IMG_DEV_VIRTADDR sHighDevVAddr;
+#if defined(FIX_HW_BRN_31620)
+ IMG_BOOL bFlushSystemCache = IMG_FALSE;
+ IMG_BOOL bSharedPT = IMG_FALSE;
+ IMG_DEV_VIRTADDR sDevVAddrRequestStart;
+ IMG_DEV_VIRTADDR sDevVAddrRequestEnd;
+ IMG_UINT32 ui32PDRequestStart;
+ IMG_UINT32 ui32PDRequestEnd;
+ IMG_UINT32 ui32ModifiedCachelines[BRN31620_CACHE_FLUSH_INDEX_SIZE];
+#endif
+
+
+#if SGX_FEATURE_ADDRESS_SPACE_SIZE < 32
+ PVR_ASSERT(DevVAddr.uiAddr < (1<<SGX_FEATURE_ADDRESS_SPACE_SIZE));
+#endif
+
+
+ SysAcquireData(&psSysData);
+
+
+ ui32PDIndex = DevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+
+
+ if((UINT32_MAX_VALUE - DevVAddr.uiAddr)
+ < (ui32Size + pMMUHeap->ui32DataPageMask + pMMUHeap->ui32PTMask))
+ {
+
+ sHighDevVAddr.uiAddr = UINT32_MAX_VALUE;
+ }
+ else
+ {
+ sHighDevVAddr.uiAddr = DevVAddr.uiAddr
+ + ui32Size
+ + pMMUHeap->ui32DataPageMask
+ + pMMUHeap->ui32PTMask;
+ }
+
+ ui32PageTableCount = sHighDevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+
+ if (ui32PageTableCount == 0)
+ ui32PageTableCount = 1024;
+
+#if defined(FIX_HW_BRN_31620)
+ for (i=0;i<BRN31620_CACHE_FLUSH_INDEX_SIZE;i++)
+ {
+ ui32ModifiedCachelines[i] = 0;
+ }
+
+
+
+
+ sDevVAddrRequestStart = DevVAddr;
+ ui32PDRequestStart = ui32PDIndex;
+ sDevVAddrRequestEnd = sHighDevVAddr;
+ ui32PDRequestEnd = ui32PageTableCount - 1;
+
+
+ DevVAddr.uiAddr = DevVAddr.uiAddr & (~BRN31620_PDE_CACHE_FILL_MASK);
+
+
+ sHighDevVAddr.uiAddr = ((sHighDevVAddr.uiAddr + (BRN31620_PDE_CACHE_FILL_SIZE - 1)) & (~BRN31620_PDE_CACHE_FILL_MASK));
+
+ ui32PDIndex = DevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
+ ui32PageTableCount = sHighDevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+
+ if (ui32PageTableCount == 0)
+ ui32PageTableCount = 1024;
+#endif
+
+ ui32PageTableCount -= ui32PDIndex;
+
+
+ pui32PDEntry = (IMG_UINT32*)pMMUHeap->psMMUContext->pvPDCpuVAddr;
+ pui32PDEntry += ui32PDIndex;
+
+
+ ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+#if defined(PDUMP)
+ {
+ IMG_UINT32 ui32Flags = 0;
+
+
+ if( MMU_IsHeapShared(pMMUHeap) )
+ {
+ ui32Flags |= PDUMP_FLAGS_CONTINUOUS;
+ }
+ PDUMPCOMMENTWITHFLAGS(ui32Flags, "Alloc PTs (MMU Context ID == %u, PDBaseIndex == %u, Size == 0x%x)",
+ pMMUHeap->psMMUContext->ui32PDumpMMUContextID,
+ pMMUHeap->ui32PDBaseIndex,
+ ui32Size);
+ PDUMPCOMMENTWITHFLAGS(ui32Flags, "Alloc page table (page count == %08X)", ui32PageTableCount);
+ PDUMPCOMMENTWITHFLAGS(ui32Flags, "Page directory mods (page count == %08X)", ui32PageTableCount);
+ }
+#endif
+
+ for(i=0; i<ui32PageTableCount; i++)
+ {
+ if(ppsPTInfoList[i] == IMG_NULL)
+ {
+#if defined(FIX_HW_BRN_31620)
+
+ if (pMMUHeap->psMMUContext->apsPTInfoListSave[ui32PDIndex + i])
+ {
+
+ if (((ui32PDIndex + i) >= ui32PDRequestStart) && ((ui32PDIndex + i) <= ui32PDRequestEnd))
+ {
+ IMG_UINT32 ui32PDCacheLine = (ui32PDIndex + i) >> BRN31620_PDES_PER_CACHE_LINE_SHIFT;
+
+ ppsPTInfoList[i] = pMMUHeap->psMMUContext->apsPTInfoListSave[ui32PDIndex + i];
+ pMMUHeap->psMMUContext->apsPTInfoListSave[ui32PDIndex + i] = IMG_NULL;
+
+ pMMUHeap->psMMUContext->ui32PDCacheRangeRefCount[ui32PDCacheLine]++;
+ }
+ }
+ else
+ {
+#endif
+ OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof (MMU_PT_INFO),
+ (IMG_VOID **)&ppsPTInfoList[i], IMG_NULL,
+ "MMU Page Table Info");
+ if (ppsPTInfoList[i] == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "_DeferredAllocPagetables: ERROR call to OSAllocMem failed"));
+ return IMG_FALSE;
+ }
+ OSMemSet (ppsPTInfoList[i], 0, sizeof(MMU_PT_INFO));
+#if defined(FIX_HW_BRN_31620)
+ }
+#endif
+ }
+#if defined(FIX_HW_BRN_31620)
+
+ if (ppsPTInfoList[i])
+ {
+#endif
+ if(ppsPTInfoList[i]->hPTPageOSMemHandle == IMG_NULL
+ && ppsPTInfoList[i]->PTPageCpuVAddr == IMG_NULL)
+ {
+ IMG_DEV_PHYADDR sDevPAddr;
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+ IMG_UINT32 *pui32Tmp;
+ IMG_UINT32 j;
+#else
+#if !defined(FIX_HW_BRN_31620)
+
+ PVR_ASSERT(pui32PDEntry[i] == 0);
+#endif
+#endif
+ if(_AllocPageTableMemory (pMMUHeap, ppsPTInfoList[i], &sDevPAddr) != IMG_TRUE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "_DeferredAllocPagetables: ERROR call to _AllocPageTableMemory failed"));
+ return IMG_FALSE;
+ }
+#if defined(FIX_HW_BRN_31620)
+ bFlushSystemCache = IMG_TRUE;
+
+ {
+ IMG_UINT32 ui32PD;
+ IMG_UINT32 ui32PDCacheLine;
+ IMG_UINT32 ui32PDBitMaskIndex;
+ IMG_UINT32 ui32PDBitMaskShift;
+
+ ui32PD = ui32PDIndex + i;
+ ui32PDCacheLine = ui32PD >> BRN31620_PDES_PER_CACHE_LINE_SHIFT;
+ ui32PDBitMaskIndex = ui32PDCacheLine >> BRN31620_CACHE_FLUSH_BITS_SHIFT;
+ ui32PDBitMaskShift = ui32PDCacheLine & BRN31620_CACHE_FLUSH_BITS_MASK;
+ ui32ModifiedCachelines[ui32PDBitMaskIndex] |= 1 << ui32PDBitMaskShift;
+
+
+ if ((pMMUHeap->ui32PDBaseIndex + pMMUHeap->ui32PageTableCount) < (ui32PD + 1))
+ {
+ pMMUHeap->ui32PageTableCount = (ui32PD + 1) - pMMUHeap->ui32PDBaseIndex;
+ }
+
+ if (((ui32PDIndex + i) >= ui32PDRequestStart) && ((ui32PDIndex + i) <= ui32PDRequestEnd))
+ {
+ pMMUHeap->psMMUContext->ui32PDCacheRangeRefCount[ui32PDCacheLine]++;
+ }
+ }
+#endif
+ switch(pMMUHeap->psDevArena->DevMemHeapType)
+ {
+ case DEVICE_MEMORY_HEAP_SHARED :
+ case DEVICE_MEMORY_HEAP_SHARED_EXPORTED :
+ {
+
+ MMU_CONTEXT *psMMUContext = (MMU_CONTEXT*)pMMUHeap->psMMUContext->psDevInfo->pvMMUContextList;
+
+ while(psMMUContext)
+ {
+ MakeKernelPageReadWrite(psMMUContext->pvPDCpuVAddr);
+
+ pui32PDEntry = (IMG_UINT32*)psMMUContext->pvPDCpuVAddr;
+ pui32PDEntry += ui32PDIndex;
+
+
+ pui32PDEntry[i] = (sDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+ | pMMUHeap->ui32PDEPageSizeCtrl
+ | SGX_MMU_PDE_VALID;
+ MakeKernelPageReadOnly(psMMUContext->pvPDCpuVAddr);
+ #if defined(PDUMP)
+
+ #if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+ if(psMMUContext->bPDumpActive)
+ #endif
+ {
+
+ PDUMPPDENTRIES(&pMMUHeap->sMMUAttrib, psMMUContext->hPDOSMemHandle, (IMG_VOID*)&pui32PDEntry[i], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ }
+ #endif
+
+ psMMUContext = psMMUContext->psNext;
+ }
+#if defined(FIX_HW_BRN_31620)
+ bSharedPT = IMG_TRUE;
+#endif
+ break;
+ }
+ case DEVICE_MEMORY_HEAP_PERCONTEXT :
+ case DEVICE_MEMORY_HEAP_KERNEL :
+ {
+ MakeKernelPageReadWrite(pMMUHeap->psMMUContext->pvPDCpuVAddr);
+
+ pui32PDEntry[i] = (sDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+ | pMMUHeap->ui32PDEPageSizeCtrl
+ | SGX_MMU_PDE_VALID;
+ MakeKernelPageReadOnly(pMMUHeap->psMMUContext->pvPDCpuVAddr);
+
+
+ PDUMPPDENTRIES(&pMMUHeap->sMMUAttrib, pMMUHeap->psMMUContext->hPDOSMemHandle, (IMG_VOID*)&pui32PDEntry[i], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ break;
+ }
+ default:
+ {
+ PVR_DPF((PVR_DBG_ERROR, "_DeferredAllocPagetables: ERROR invalid heap type"));
+ return IMG_FALSE;
+ }
+ }
+
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+
+
+
+
+ MMU_InvalidateDirectoryCache(pMMUHeap->psMMUContext->psDevInfo);
+#endif
+#if defined(FIX_HW_BRN_31620)
+
+ if (((ui32PDIndex + i) < ui32PDRequestStart) || ((ui32PDIndex + i) > ui32PDRequestEnd))
+ {
+ pMMUHeap->psMMUContext->apsPTInfoListSave[ui32PDIndex + i] = ppsPTInfoList[i];
+ ppsPTInfoList[i] = IMG_NULL;
+ }
+#endif
+ }
+ else
+ {
+#if !defined(FIX_HW_BRN_31620)
+
+ PVR_ASSERT(pui32PDEntry[i] != 0);
+#endif
+ }
+#if defined(FIX_HW_BRN_31620)
+ }
+#endif
+ }
+
+ #if defined(SGX_FEATURE_SYSTEM_CACHE)
+ #if defined(FIX_HW_BRN_31620)
+
+ if (bFlushSystemCache)
+ {
+ #endif
+
+ MMU_InvalidateSystemLevelCache(pMMUHeap->psMMUContext->psDevInfo);
+ #endif
+ #if defined(FIX_HW_BRN_31620)
+ }
+
+
+ sHighDevVAddr.uiAddr = sHighDevVAddr.uiAddr - 1;
+
+
+ if (bFlushSystemCache)
+ {
+ MMU_CONTEXT *psMMUContext;
+
+ if (bSharedPT)
+ {
+ MMU_CONTEXT *psMMUContext = (MMU_CONTEXT*)pMMUHeap->psMMUContext->psDevInfo->pvMMUContextList;
+
+ while(psMMUContext)
+ {
+ for (i=0;i<BRN31620_CACHE_FLUSH_INDEX_SIZE;i++)
+ {
+ psMMUContext->ui32PDChangeMask[i] |= ui32ModifiedCachelines[i];
+ }
+
+
+ psMMUContext = psMMUContext->psNext;
+ }
+ }
+ else
+ {
+ for (i=0;i<BRN31620_CACHE_FLUSH_INDEX_SIZE;i++)
+ {
+ pMMUHeap->psMMUContext->ui32PDChangeMask[i] |= ui32ModifiedCachelines[i];
+ }
+ }
+
+
+ psMMUContext = pMMUHeap->psMMUContext;
+ for (i=0;i<BRN31620_CACHE_FLUSH_INDEX_SIZE;i++)
+ {
+ IMG_UINT32 j;
+
+ for(j=0;j<BRN31620_CACHE_FLUSH_BITS_SIZE;j++)
+ {
+ if (ui32ModifiedCachelines[i] & (1 << j))
+ {
+ PVRSRV_SGXDEV_INFO *psDevInfo = psMMUContext->psDevInfo;
+ MMU_PT_INFO *psTempPTInfo = IMG_NULL;
+ IMG_UINT32 *pui32Tmp;
+
+ ui32PDIndex = (((i * BRN31620_CACHE_FLUSH_BITS_SIZE) + j) * BRN31620_PDES_PER_CACHE_LINE_SIZE) + BRN31620_DUMMY_PDE_INDEX;
+
+
+ if (psMMUContext->apsPTInfoList[ui32PDIndex])
+ {
+ psTempPTInfo = psMMUContext->apsPTInfoList[ui32PDIndex];
+ }
+ else
+ {
+ psTempPTInfo = psMMUContext->apsPTInfoListSave[ui32PDIndex];
+ }
+
+ PVR_ASSERT(psTempPTInfo != IMG_NULL);
+
+ MakeKernelPageReadWrite(psTempPTInfo->PTPageCpuVAddr);
+ pui32Tmp = (IMG_UINT32 *) psTempPTInfo->PTPageCpuVAddr;
+ PVR_ASSERT(pui32Tmp != IMG_NULL);
+ pui32Tmp[BRN31620_DUMMY_PTE_INDEX] = (psDevInfo->sBRN31620DummyPageDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PTE_DUMMY_PAGE
+ | SGX_MMU_PTE_READONLY
+ | SGX_MMU_PTE_VALID;
+ MakeKernelPageReadOnly(psTempPTInfo->PTPageCpuVAddr);
+ PDUMPCOMMENT("BRN31620 Dump PTE for dummy page after wireing up new PT");
+ PDUMPMEMPTENTRIES(&pMMUHeap->sMMUAttrib, psTempPTInfo->hPTPageOSMemHandle, (IMG_VOID *) &pui32Tmp[BRN31620_DUMMY_PTE_INDEX], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ }
+ }
+ }
+ }
+ #endif
+
+ return IMG_TRUE;
+}
+
+
+#if defined(PDUMP)
+IMG_UINT32 MMU_GetPDumpContextID(IMG_HANDLE hDevMemContext)
+{
+ BM_CONTEXT *pBMContext = hDevMemContext;
+ PVR_ASSERT(pBMContext);
+
+ return pBMContext->psMMUContext->ui32PDumpMMUContextID;
+}
+
+static IMG_VOID MMU_SetPDumpAttribs(PDUMP_MMU_ATTRIB *psMMUAttrib,
+ PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 ui32DataPageMask,
+ IMG_UINT32 ui32PTSize)
+{
+
+ psMMUAttrib->sDevId = psDeviceNode->sDevId;
+
+ psMMUAttrib->pszPDRegRegion = IMG_NULL;
+ psMMUAttrib->ui32DataPageMask = ui32DataPageMask;
+
+ psMMUAttrib->ui32PTEValid = SGX_MMU_PTE_VALID;
+ psMMUAttrib->ui32PTSize = ui32PTSize;
+ psMMUAttrib->ui32PTEAlignShift = SGX_MMU_PTE_ADDR_ALIGNSHIFT;
+
+ psMMUAttrib->ui32PDEMask = SGX_MMU_PDE_ADDR_MASK;
+ psMMUAttrib->ui32PDEAlignShift = SGX_MMU_PDE_ADDR_ALIGNSHIFT;
+}
+#endif
+
+PVRSRV_ERROR
+MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, IMG_DEV_PHYADDR *psPDDevPAddr)
+{
+ IMG_UINT32 *pui32Tmp;
+ IMG_UINT32 i;
+ IMG_CPU_VIRTADDR pvPDCpuVAddr;
+ IMG_DEV_PHYADDR sPDDevPAddr;
+ IMG_CPU_PHYADDR sCpuPAddr;
+ MMU_CONTEXT *psMMUContext;
+ IMG_HANDLE hPDOSMemHandle;
+ SYS_DATA *psSysData;
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+#if defined(PDUMP)
+ PDUMP_MMU_ATTRIB sMMUAttrib;
+#endif
+ PVR_DPF ((PVR_DBG_MESSAGE, "MMU_Initialise"));
+
+ SysAcquireData(&psSysData);
+#if defined(PDUMP)
+
+
+ MMU_SetPDumpAttribs(&sMMUAttrib, psDeviceNode,
+ SGX_MMU_PAGE_MASK,
+ SGX_MMU_PT_SIZE * sizeof(IMG_UINT32));
+#endif
+
+ OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof (MMU_CONTEXT),
+ (IMG_VOID **)&psMMUContext, IMG_NULL,
+ "MMU Context");
+ if (psMMUContext == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocMem failed"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OSMemSet (psMMUContext, 0, sizeof(MMU_CONTEXT));
+
+
+ psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+ psMMUContext->psDevInfo = psDevInfo;
+
+
+ psMMUContext->psDeviceNode = psDeviceNode;
+
+
+ if(psDeviceNode->psLocalDevMemArena == IMG_NULL)
+ {
+ if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ 0,
+ &pvPDCpuVAddr,
+ &hPDOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocPages failed"));
+ return PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES;
+ }
+
+ if(pvPDCpuVAddr)
+ {
+ sCpuPAddr = OSMapLinToCPUPhys(hPDOSMemHandle,
+ pvPDCpuVAddr);
+ }
+ else
+ {
+
+ sCpuPAddr = OSMemHandleToCpuPAddr(hPDOSMemHandle, 0);
+ }
+ sPDDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+
+ #if PAGE_TEST
+ PageTest(pvPDCpuVAddr, sPDDevPAddr);
+ #endif
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+ if(!psDevInfo->pvMMUContextList)
+ {
+
+ if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ 0,
+ &psDevInfo->pvDummyPTPageCpuVAddr,
+ &psDevInfo->hDummyPTPageOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocPages failed"));
+ return PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES;
+ }
+
+ if(psDevInfo->pvDummyPTPageCpuVAddr)
+ {
+ sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hDummyPTPageOSMemHandle,
+ psDevInfo->pvDummyPTPageCpuVAddr);
+ }
+ else
+ {
+
+ sCpuPAddr = OSMemHandleToCpuPAddr(psDevInfo->hDummyPTPageOSMemHandle, 0);
+ }
+ psDevInfo->sDummyPTDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+
+
+ if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ 0,
+ &psDevInfo->pvDummyDataPageCpuVAddr,
+ &psDevInfo->hDummyDataPageOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocPages failed"));
+ return PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES;
+ }
+
+ if(psDevInfo->pvDummyDataPageCpuVAddr)
+ {
+ sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hDummyPTPageOSMemHandle,
+ psDevInfo->pvDummyDataPageCpuVAddr);
+ }
+ else
+ {
+ sCpuPAddr = OSMemHandleToCpuPAddr(psDevInfo->hDummyDataPageOSMemHandle, 0);
+ }
+ psDevInfo->sDummyDataDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+ }
+#endif
+#if defined(FIX_HW_BRN_31620)
+
+ if(!psDevInfo->pvMMUContextList)
+ {
+ IMG_UINT32 j;
+
+ if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ 0,
+ &psDevInfo->pvBRN31620DummyPageCpuVAddr,
+ &psDevInfo->hBRN31620DummyPageOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocPages failed"));
+ return PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES;
+ }
+
+
+ if(psDevInfo->pvBRN31620DummyPageCpuVAddr)
+ {
+ sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hBRN31620DummyPageOSMemHandle,
+ psDevInfo->pvBRN31620DummyPageCpuVAddr);
+ }
+ else
+ {
+ sCpuPAddr = OSMemHandleToCpuPAddr(psDevInfo->hBRN31620DummyPageOSMemHandle, 0);
+ }
+
+ pui32Tmp = (IMG_UINT32 *)psDevInfo->pvBRN31620DummyPageCpuVAddr;
+ for(j=0; j<(SGX_MMU_PAGE_SIZE/4); j++)
+ {
+ pui32Tmp[j] = BRN31620_DUMMY_PAGE_SIGNATURE;
+ }
+
+ psDevInfo->sBRN31620DummyPageDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+ PDUMPMALLOCPAGETABLE(&psDeviceNode->sDevId, psDevInfo->hBRN31620DummyPageOSMemHandle, 0, psDevInfo->pvBRN31620DummyPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
+
+
+ if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ 0,
+ &psDevInfo->pvBRN31620DummyPTCpuVAddr,
+ &psDevInfo->hBRN31620DummyPTOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocPages failed"));
+ return PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES;
+ }
+
+
+ if(psDevInfo->pvBRN31620DummyPTCpuVAddr)
+ {
+ sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hBRN31620DummyPTOSMemHandle,
+ psDevInfo->pvBRN31620DummyPTCpuVAddr);
+ }
+ else
+ {
+ sCpuPAddr = OSMemHandleToCpuPAddr(psDevInfo->hBRN31620DummyPTOSMemHandle, 0);
+ }
+
+ OSMemSet(psDevInfo->pvBRN31620DummyPTCpuVAddr,0,SGX_MMU_PAGE_SIZE);
+ psDevInfo->sBRN31620DummyPTDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+ PDUMPMALLOCPAGETABLE(&psDeviceNode->sDevId, psDevInfo->hBRN31620DummyPTOSMemHandle, 0, psDevInfo->pvBRN31620DummyPTCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
+ }
+#endif
+ }
+ else
+ {
+ IMG_SYS_PHYADDR sSysPAddr;
+
+
+ if(RA_Alloc(psDeviceNode->psLocalDevMemArena,
+ SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ IMG_NULL,
+ 0,
+ SGX_MMU_PAGE_SIZE,
+ 0,
+ IMG_NULL,
+ 0,
+ &(sSysPAddr.uiAddr))!= IMG_TRUE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to RA_Alloc failed"));
+ return PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY;
+ }
+
+
+ sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+ sPDDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr);
+ pvPDCpuVAddr = OSMapPhysToLin(sCpuPAddr,
+ SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ &hPDOSMemHandle);
+ if(!pvPDCpuVAddr)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR failed to map page tables"));
+ return PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE;
+ }
+
+ #if PAGE_TEST
+ PageTest(pvPDCpuVAddr, sPDDevPAddr);
+ #endif
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+ if(!psDevInfo->pvMMUContextList)
+ {
+
+ if(RA_Alloc(psDeviceNode->psLocalDevMemArena,
+ SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ IMG_NULL,
+ 0,
+ SGX_MMU_PAGE_SIZE,
+ 0,
+ IMG_NULL,
+ 0,
+ &(sSysPAddr.uiAddr))!= IMG_TRUE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to RA_Alloc failed"));
+ return PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY;
+ }
+
+
+ sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+ psDevInfo->sDummyPTDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr);
+ psDevInfo->pvDummyPTPageCpuVAddr = OSMapPhysToLin(sCpuPAddr,
+ SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ &psDevInfo->hDummyPTPageOSMemHandle);
+ if(!psDevInfo->pvDummyPTPageCpuVAddr)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR failed to map page tables"));
+ return PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE;
+ }
+
+
+ if(RA_Alloc(psDeviceNode->psLocalDevMemArena,
+ SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ IMG_NULL,
+ 0,
+ SGX_MMU_PAGE_SIZE,
+ 0,
+ IMG_NULL,
+ 0,
+ &(sSysPAddr.uiAddr))!= IMG_TRUE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to RA_Alloc failed"));
+ return PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY;
+ }
+
+
+ sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+ psDevInfo->sDummyDataDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr);
+ psDevInfo->pvDummyDataPageCpuVAddr = OSMapPhysToLin(sCpuPAddr,
+ SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ &psDevInfo->hDummyDataPageOSMemHandle);
+ if(!psDevInfo->pvDummyDataPageCpuVAddr)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR failed to map page tables"));
+ return PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE;
+ }
+ }
+#endif
+#if defined(FIX_HW_BRN_31620)
+
+ if(!psDevInfo->pvMMUContextList)
+ {
+ IMG_UINT32 j;
+
+ if(RA_Alloc(psDeviceNode->psLocalDevMemArena,
+ SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ IMG_NULL,
+ 0,
+ SGX_MMU_PAGE_SIZE,
+ 0,
+ IMG_NULL,
+ 0,
+ &(sSysPAddr.uiAddr))!= IMG_TRUE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to RA_Alloc failed"));
+ return PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY;
+ }
+
+
+ sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+ psDevInfo->sBRN31620DummyPageDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr);
+ psDevInfo->pvBRN31620DummyPageCpuVAddr = OSMapPhysToLin(sCpuPAddr,
+ SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ &psDevInfo->hBRN31620DummyPageOSMemHandle);
+ if(!psDevInfo->pvBRN31620DummyPageCpuVAddr)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR failed to map page tables"));
+ return PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE;
+ }
+
+ MakeKernelPageReadWrite(psDevInfo->pvBRN31620DummyPageCpuVAddr);
+ pui32Tmp = (IMG_UINT32 *)psDevInfo->pvBRN31620DummyPageCpuVAddr;
+ for(j=0; j<(SGX_MMU_PAGE_SIZE/4); j++)
+ {
+ pui32Tmp[j] = BRN31620_DUMMY_PAGE_SIGNATURE;
+ }
+ MakeKernelPageReadOnly(psDevInfo->pvBRN31620DummyPageCpuVAddr);
+ PDUMPMALLOCPAGETABLE(&psDeviceNode->sDevId, psDevInfo->hBRN31620DummyPageOSMemHandle, 0, psDevInfo->pvBRN31620DummyPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
+
+
+ if(RA_Alloc(psDeviceNode->psLocalDevMemArena,
+ SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ IMG_NULL,
+ 0,
+ SGX_MMU_PAGE_SIZE,
+ 0,
+ IMG_NULL,
+ 0,
+ &(sSysPAddr.uiAddr))!= IMG_TRUE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to RA_Alloc failed"));
+ return PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY;
+ }
+
+
+ sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+ psDevInfo->sBRN31620DummyPTDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr);
+ psDevInfo->pvBRN31620DummyPTCpuVAddr = OSMapPhysToLin(sCpuPAddr,
+ SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ &psDevInfo->hBRN31620DummyPTOSMemHandle);
+
+ if(!psDevInfo->pvBRN31620DummyPTCpuVAddr)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR failed to map page tables"));
+ return PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE;
+ }
+
+ OSMemSet(psDevInfo->pvBRN31620DummyPTCpuVAddr,0,SGX_MMU_PAGE_SIZE);
+ PDUMPMALLOCPAGETABLE(&psDeviceNode->sDevId, psDevInfo->hBRN31620DummyPTOSMemHandle, 0, psDevInfo->pvBRN31620DummyPTCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
+ }
+#endif
+ }
+
+#if defined(FIX_HW_BRN_31620)
+ if (!psDevInfo->pvMMUContextList)
+ {
+
+ psDevInfo->hKernelMMUContext = psMMUContext;
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: saving kernel mmu context: %p", psMMUContext));
+ }
+#endif
+
+#if defined(PDUMP)
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+
+ {
+ PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData();
+ if(psPerProc == IMG_NULL)
+ {
+
+ psMMUContext->bPDumpActive = IMG_TRUE;
+ }
+ else
+ {
+ psMMUContext->bPDumpActive = psPerProc->bPDumpActive;
+ }
+ }
+#endif
+
+#if IMG_ADDRSPACE_PHYSADDR_BITS == 32
+ PDUMPCOMMENT("Alloc page directory for new MMU context (PDDevPAddr == 0x%08x)",
+ sPDDevPAddr.uiAddr);
+#else
+ PDUMPCOMMENT("Alloc page directory for new MMU context, 64-bit arch detected (PDDevPAddr == 0x%08x%08x)",
+ sPDDevPAddr.uiHighAddr, sPDDevPAddr.uiAddr);
+#endif
+ PDUMPMALLOCPAGETABLE(&psDeviceNode->sDevId, hPDOSMemHandle, 0, pvPDCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PD_UNIQUETAG);
+#endif
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+ EnableHostAccess(psMMUContext);
+#endif
+
+ if (pvPDCpuVAddr)
+ {
+ pui32Tmp = (IMG_UINT32 *)pvPDCpuVAddr;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: pvPDCpuVAddr invalid"));
+ return PVRSRV_ERROR_INVALID_CPU_ADDR;
+ }
+
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+ MakeKernelPageReadWrite(pvPDCpuVAddr);
+
+ for(i=0; i<SGX_MMU_PD_SIZE; i++)
+ {
+ pui32Tmp[i] = (psDevInfo->sDummyPTDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PDE_PAGE_SIZE_4K
+ | SGX_MMU_PDE_VALID;
+ }
+ MakeKernelPageReadOnly(pvPDCpuVAddr);
+
+ if(!psDevInfo->pvMMUContextList)
+ {
+
+
+
+ MakeKernelPageReadWrite(psDevInfo->pvDummyPTPageCpuVAddr);
+ pui32Tmp = (IMG_UINT32 *)psDevInfo->pvDummyPTPageCpuVAddr;
+ for(i=0; i<SGX_MMU_PT_SIZE; i++)
+ {
+ pui32Tmp[i] = (psDevInfo->sDummyDataDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PTE_VALID;
+ }
+ MakeKernelPageReadOnly(psDevInfo->pvDummyPTPageCpuVAddr);
+
+ PDUMPCOMMENT("Dummy Page table contents");
+ PDUMPMEMPTENTRIES(&sMMUAttrib, psDevInfo->hDummyPTOSMemHandle, psDevInfo->pvDummyPTPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+
+
+
+ MakeKernelPageReadWrite(psDevInfo->pvDummyDataPageCpuVAddr);
+ pui32Tmp = (IMG_UINT32 *)psDevInfo->pvDummyDataPageCpuVAddr;
+ for(i=0; i<(SGX_MMU_PAGE_SIZE/4); i++)
+ {
+ pui32Tmp[i] = DUMMY_DATA_PAGE_SIGNATURE;
+ }
+ MakeKernelPageReadOnly(psDevInfo->pvDummyDataPageCpuVAddr);
+
+ PDUMPCOMMENT("Dummy Data Page contents");
+ PDUMPMEMPTENTRIES(PVRSRV_DEVICE_TYPE_SGX, psDevInfo->hDummyDataPageOSMemHandle, psDevInfo->pvDummyDataPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ }
+#else
+
+ MakeKernelPageReadWrite(pvPDCpuVAddr);
+ for(i=0; i<SGX_MMU_PD_SIZE; i++)
+ {
+
+ pui32Tmp[i] = 0;
+ }
+ MakeKernelPageReadOnly(pvPDCpuVAddr);
+#endif
+
+#if defined(PDUMP)
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+ if(psMMUContext->bPDumpActive)
+#endif
+ {
+
+ PDUMPCOMMENT("Page directory contents");
+ PDUMPPDENTRIES(&sMMUAttrib, hPDOSMemHandle, pvPDCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ }
+#endif
+#if defined(FIX_HW_BRN_31620)
+ {
+ IMG_UINT32 i;
+ IMG_UINT32 ui32PDCount = 0;
+ IMG_UINT32 *pui32PT;
+ pui32Tmp = (IMG_UINT32 *)pvPDCpuVAddr;
+
+ PDUMPCOMMENT("BRN31620 Set up dummy PT");
+
+ MakeKernelPageReadWrite(psDevInfo->pvBRN31620DummyPTCpuVAddr);
+ pui32PT = (IMG_UINT32 *) psDevInfo->pvBRN31620DummyPTCpuVAddr;
+ pui32PT[BRN31620_DUMMY_PTE_INDEX] = (psDevInfo->sBRN31620DummyPageDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PTE_DUMMY_PAGE
+ | SGX_MMU_PTE_READONLY
+ | SGX_MMU_PTE_VALID;
+ MakeKernelPageReadOnly(psDevInfo->pvBRN31620DummyPTCpuVAddr);
+
+#if defined(PDUMP)
+
+ PDUMPCOMMENT("BRN31620 Dump dummy PT contents");
+ PDUMPMEMPTENTRIES(&sMMUAttrib, psDevInfo->hBRN31620DummyPTOSMemHandle, psDevInfo->pvBRN31620DummyPTCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ PDUMPCOMMENT("BRN31620 Dump dummy page contents");
+ PDUMPMEMPTENTRIES(&sMMUAttrib, psDevInfo->hBRN31620DummyPageOSMemHandle, psDevInfo->pvBRN31620DummyPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+
+
+ for(i=0;i<SGX_MMU_PT_SIZE;i++)
+ {
+ PDUMPMEMPTENTRIES(&sMMUAttrib, psDevInfo->hBRN31620DummyPTOSMemHandle, &pui32PT[i], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ }
+#endif
+ PDUMPCOMMENT("BRN31620 Dump PDE wire up");
+
+ for(i=0;i<SGX_MMU_PD_SIZE;i++)
+ {
+ pui32Tmp[i] = 0;
+
+ if (ui32PDCount == BRN31620_DUMMY_PDE_INDEX)
+ {
+ MakeKernelPageReadWrite(pvPDCpuVAddr);
+ pui32Tmp[i] = (psDevInfo->sBRN31620DummyPTDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PDE_PAGE_SIZE_4K
+ | SGX_MMU_PDE_DUMMY_PAGE
+ | SGX_MMU_PDE_VALID;
+ MakeKernelPageReadOnly(pvPDCpuVAddr);
+ }
+ PDUMPMEMPTENTRIES(&sMMUAttrib, hPDOSMemHandle, (IMG_VOID *) &pui32Tmp[i], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ ui32PDCount++;
+ if (ui32PDCount == BRN31620_PDES_PER_CACHE_LINE_SIZE)
+ {
+
+ ui32PDCount = 0;
+ }
+ }
+
+
+
+ PDUMPCOMMENT("BRN31620 dummy Page table contents");
+ PDUMPMEMPTENTRIES(&sMMUAttrib, psDevInfo->hBRN31620DummyPageOSMemHandle, psDevInfo->pvBRN31620DummyPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ }
+#endif
+#if defined(PDUMP)
+
+ {
+ PVRSRV_ERROR eError;
+
+ IMG_UINT32 ui32MMUType = 1;
+
+ #if defined(SGX_FEATURE_36BIT_MMU)
+ ui32MMUType = 3;
+ #else
+ #if defined(SGX_FEATURE_VARIABLE_MMU_PAGE_SIZE)
+ ui32MMUType = 2;
+ #endif
+ #endif
+
+ eError = PDumpSetMMUContext(PVRSRV_DEVICE_TYPE_SGX,
+ psDeviceNode->sDevId.pszPDumpDevName,
+ &psMMUContext->ui32PDumpMMUContextID,
+ ui32MMUType,
+ PDUMP_PT_UNIQUETAG,
+ hPDOSMemHandle,
+ pvPDCpuVAddr);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to PDumpSetMMUContext failed"));
+ return eError;
+ }
+ }
+
+
+ PDUMPCOMMENT("Set MMU context complete (MMU Context ID == %u)", psMMUContext->ui32PDumpMMUContextID);
+#endif
+
+#if defined(FIX_HW_BRN_31620)
+ for(i=0;i<BRN31620_CACHE_FLUSH_INDEX_SIZE;i++)
+ {
+ psMMUContext->ui32PDChangeMask[i] = 0;
+ }
+
+ for(i=0;i<BRN31620_CACHE_FLUSH_SIZE;i++)
+ {
+ psMMUContext->ui32PDCacheRangeRefCount[i] = 0;
+ }
+
+ for(i=0;i<SGX_MAX_PD_ENTRIES;i++)
+ {
+ psMMUContext->apsPTInfoListSave[i] = IMG_NULL;
+ }
+#endif
+
+ psMMUContext->pvPDCpuVAddr = pvPDCpuVAddr;
+ psMMUContext->sPDDevPAddr = sPDDevPAddr;
+ psMMUContext->hPDOSMemHandle = hPDOSMemHandle;
+
+
+ *ppsMMUContext = psMMUContext;
+
+
+ *psPDDevPAddr = sPDDevPAddr;
+
+
+ psMMUContext->psNext = (MMU_CONTEXT*)psDevInfo->pvMMUContextList;
+ psDevInfo->pvMMUContextList = (IMG_VOID*)psMMUContext;
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+ DisableHostAccess(psMMUContext);
+#endif
+
+ return PVRSRV_OK;
+}
+
+IMG_VOID
+MMU_Finalise (MMU_CONTEXT *psMMUContext)
+{
+ IMG_UINT32 *pui32Tmp, i;
+ SYS_DATA *psSysData;
+ MMU_CONTEXT **ppsMMUContext;
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE) || defined(FIX_HW_BRN_31620)
+ PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO*)psMMUContext->psDevInfo;
+ MMU_CONTEXT *psMMUContextList = (MMU_CONTEXT*)psDevInfo->pvMMUContextList;
+#endif
+
+ SysAcquireData(&psSysData);
+
+#if defined(PDUMP)
+
+ PDUMPCOMMENT("Clear MMU context (MMU Context ID == %u)", psMMUContext->ui32PDumpMMUContextID);
+ PDUMPCLEARMMUCONTEXT(PVRSRV_DEVICE_TYPE_SGX, psMMUContext->psDeviceNode->sDevId.pszPDumpDevName, psMMUContext->ui32PDumpMMUContextID, 2);
+
+
+#if IMG_ADDRSPACE_PHYSADDR_BITS == 32
+ PDUMPCOMMENT("Free page directory (PDDevPAddr == 0x%08x)",
+ psMMUContext->sPDDevPAddr.uiAddr);
+#else
+ PDUMPCOMMENT("Free page directory, 64-bit arch detected (PDDevPAddr == 0x%08x%08x)",
+ psMMUContext->sPDDevPAddr.uiHighAddr, psMMUContext->sPDDevPAddr.uiAddr);
+#endif
+#endif
+
+ PDUMPFREEPAGETABLE(&psMMUContext->psDeviceNode->sDevId, psMMUContext->hPDOSMemHandle, psMMUContext->pvPDCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+ PDUMPFREEPAGETABLE(&psMMUContext->psDeviceNode->sDevId, psDevInfo->hDummyPTPageOSMemHandle, psDevInfo->pvDummyPTPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
+ PDUMPFREEPAGETABLE(&psMMUContext->psDeviceNode->sDevId, psDevInfo->hDummyDataPageOSMemHandle, psDevInfo->pvDummyDataPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
+#endif
+
+ pui32Tmp = (IMG_UINT32 *)psMMUContext->pvPDCpuVAddr;
+
+ MakeKernelPageReadWrite(psMMUContext->pvPDCpuVAddr);
+
+ for(i=0; i<SGX_MMU_PD_SIZE; i++)
+ {
+
+ pui32Tmp[i] = 0;
+ }
+ MakeKernelPageReadOnly(psMMUContext->pvPDCpuVAddr);
+
+
+
+
+
+ if(psMMUContext->psDeviceNode->psLocalDevMemArena == IMG_NULL)
+ {
+#if defined(FIX_HW_BRN_31620)
+ PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO*)psMMUContext->psDevInfo;
+#endif
+ MakeKernelPageReadWrite(psMMUContext->pvPDCpuVAddr);
+ OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ psMMUContext->pvPDCpuVAddr,
+ psMMUContext->hPDOSMemHandle);
+
+#if defined(FIX_HW_BRN_31620)
+
+ if (!psMMUContextList->psNext)
+ {
+ PDUMPFREEPAGETABLE(&psMMUContext->psDeviceNode->sDevId, psDevInfo->hBRN31620DummyPageOSMemHandle, psDevInfo->pvBRN31620DummyPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
+ OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ psDevInfo->pvBRN31620DummyPageCpuVAddr,
+ psDevInfo->hBRN31620DummyPageOSMemHandle);
+
+ PDUMPFREEPAGETABLE(&psMMUContext->psDeviceNode->sDevId, psDevInfo->hBRN31620DummyPTOSMemHandle, psDevInfo->pvBRN31620DummyPTCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
+ OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ psDevInfo->pvBRN31620DummyPTCpuVAddr,
+ psDevInfo->hBRN31620DummyPTOSMemHandle);
+
+ }
+#endif
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+ if(!psMMUContextList->psNext)
+ {
+ OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ psDevInfo->pvDummyPTPageCpuVAddr,
+ psDevInfo->hDummyPTPageOSMemHandle);
+ OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ psDevInfo->pvDummyDataPageCpuVAddr,
+ psDevInfo->hDummyDataPageOSMemHandle);
+ }
+#endif
+ }
+ else
+ {
+ IMG_SYS_PHYADDR sSysPAddr;
+ IMG_CPU_PHYADDR sCpuPAddr;
+
+
+ sCpuPAddr = OSMapLinToCPUPhys(psMMUContext->hPDOSMemHandle,
+ psMMUContext->pvPDCpuVAddr);
+ sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr);
+
+
+ OSUnMapPhysToLin(psMMUContext->pvPDCpuVAddr,
+ SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ psMMUContext->hPDOSMemHandle);
+
+ RA_Free (psMMUContext->psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+ if(!psMMUContextList->psNext)
+ {
+
+ sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hDummyPTPageOSMemHandle,
+ psDevInfo->pvDummyPTPageCpuVAddr);
+ sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr);
+
+
+ OSUnMapPhysToLin(psDevInfo->pvDummyPTPageCpuVAddr,
+ SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ psDevInfo->hDummyPTPageOSMemHandle);
+
+ RA_Free (psMMUContext->psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
+
+
+ sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hDummyDataPageOSMemHandle,
+ psDevInfo->pvDummyDataPageCpuVAddr);
+ sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr);
+
+
+ OSUnMapPhysToLin(psDevInfo->pvDummyDataPageCpuVAddr,
+ SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ psDevInfo->hDummyDataPageOSMemHandle);
+
+ RA_Free (psMMUContext->psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
+ }
+#endif
+#if defined(FIX_HW_BRN_31620)
+
+ if(!psMMUContextList->psNext)
+ {
+
+ PDUMPFREEPAGETABLE(&psMMUContext->psDeviceNode->sDevId, psDevInfo->hBRN31620DummyPageOSMemHandle, psDevInfo->pvBRN31620DummyPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
+
+ sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hBRN31620DummyPageOSMemHandle,
+ psDevInfo->pvBRN31620DummyPageCpuVAddr);
+ sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr);
+
+
+ OSUnMapPhysToLin(psDevInfo->pvBRN31620DummyPageCpuVAddr,
+ SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ psDevInfo->hBRN31620DummyPageOSMemHandle);
+
+ RA_Free (psMMUContext->psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
+
+
+ PDUMPFREEPAGETABLE(&psMMUContext->psDeviceNode->sDevId, psDevInfo->hBRN31620DummyPTOSMemHandle, psDevInfo->pvBRN31620DummyPTCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
+
+ sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hBRN31620DummyPTOSMemHandle,
+ psDevInfo->pvBRN31620DummyPTCpuVAddr);
+ sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr);
+
+
+ OSUnMapPhysToLin(psDevInfo->pvBRN31620DummyPTCpuVAddr,
+ SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ psDevInfo->hBRN31620DummyPTOSMemHandle);
+
+ RA_Free (psMMUContext->psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
+ }
+#endif
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "MMU_Finalise"));
+
+
+ ppsMMUContext = (MMU_CONTEXT**)&psMMUContext->psDevInfo->pvMMUContextList;
+ while(*ppsMMUContext)
+ {
+ if(*ppsMMUContext == psMMUContext)
+ {
+
+ *ppsMMUContext = psMMUContext->psNext;
+ break;
+ }
+
+
+ ppsMMUContext = &((*ppsMMUContext)->psNext);
+ }
+
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(MMU_CONTEXT), psMMUContext, IMG_NULL);
+
+}
+
+
+IMG_VOID
+MMU_InsertHeap(MMU_CONTEXT *psMMUContext, MMU_HEAP *psMMUHeap)
+{
+ IMG_UINT32 *pui32PDCpuVAddr = (IMG_UINT32 *) psMMUContext->pvPDCpuVAddr;
+ IMG_UINT32 *pui32KernelPDCpuVAddr = (IMG_UINT32 *) psMMUHeap->psMMUContext->pvPDCpuVAddr;
+ IMG_UINT32 ui32PDEntry;
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+ IMG_BOOL bInvalidateDirectoryCache = IMG_FALSE;
+#endif
+
+
+ pui32PDCpuVAddr += psMMUHeap->psDevArena->BaseDevVAddr.uiAddr >> psMMUHeap->ui32PDShift;
+ pui32KernelPDCpuVAddr += psMMUHeap->psDevArena->BaseDevVAddr.uiAddr >> psMMUHeap->ui32PDShift;
+
+
+
+
+#if defined(PDUMP)
+ PDUMPCOMMENT("Page directory shared heap range copy");
+ PDUMPCOMMENT(" (Source heap MMU Context ID == %u, PT count == 0x%x)",
+ psMMUHeap->psMMUContext->ui32PDumpMMUContextID,
+ psMMUHeap->ui32PageTableCount);
+ PDUMPCOMMENT(" (Destination MMU Context ID == %u)", psMMUContext->ui32PDumpMMUContextID);
+#endif
+#ifdef SUPPORT_SGX_MMU_BYPASS
+ EnableHostAccess(psMMUContext);
+#endif
+
+ for (ui32PDEntry = 0; ui32PDEntry < psMMUHeap->ui32PageTableCount; ui32PDEntry++)
+ {
+#if (!defined(SUPPORT_SGX_MMU_DUMMY_PAGE)) && (!defined(FIX_HW_BRN_31620))
+
+ PVR_ASSERT(pui32PDCpuVAddr[ui32PDEntry] == 0);
+#endif
+ MakeKernelPageReadWrite(psMMUContext->pvPDCpuVAddr);
+
+ pui32PDCpuVAddr[ui32PDEntry] = pui32KernelPDCpuVAddr[ui32PDEntry];
+ MakeKernelPageReadOnly(psMMUContext->pvPDCpuVAddr);
+ if (pui32PDCpuVAddr[ui32PDEntry])
+ {
+
+ #if defined(PDUMP)
+
+ #if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+ if(psMMUContext->bPDumpActive)
+ #endif
+ {
+ PDUMPPDENTRIES(&psMMUHeap->sMMUAttrib, psMMUContext->hPDOSMemHandle, (IMG_VOID *) &pui32PDCpuVAddr[ui32PDEntry], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ }
+ #endif
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+ bInvalidateDirectoryCache = IMG_TRUE;
+#endif
+ }
+ }
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+ DisableHostAccess(psMMUContext);
+#endif
+
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+ if (bInvalidateDirectoryCache)
+ {
+
+
+
+
+ MMU_InvalidateDirectoryCache(psMMUContext->psDevInfo);
+ }
+#endif
+}
+
+
+static IMG_VOID
+MMU_UnmapPagesAndFreePTs (MMU_HEAP *psMMUHeap,
+ IMG_DEV_VIRTADDR sDevVAddr,
+ IMG_UINT32 ui32PageCount,
+ IMG_HANDLE hUniqueTag)
+{
+ IMG_DEV_VIRTADDR sTmpDevVAddr;
+ IMG_UINT32 i;
+ IMG_UINT32 ui32PDIndex;
+ IMG_UINT32 ui32PTIndex;
+ IMG_UINT32 *pui32Tmp;
+ IMG_BOOL bInvalidateDirectoryCache = IMG_FALSE;
+
+#if !defined (PDUMP)
+ PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif
+
+ sTmpDevVAddr = sDevVAddr;
+
+ for(i=0; i<ui32PageCount; i++)
+ {
+ MMU_PT_INFO **ppsPTInfoList;
+
+
+ ui32PDIndex = sTmpDevVAddr.uiAddr >> psMMUHeap->ui32PDShift;
+
+
+ ppsPTInfoList = &psMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+ {
+
+ ui32PTIndex = (sTmpDevVAddr.uiAddr & psMMUHeap->ui32PTMask) >> psMMUHeap->ui32PTShift;
+
+
+ if (!ppsPTInfoList[0])
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "MMU_UnmapPagesAndFreePTs: Invalid PT for alloc at VAddr:0x%08X (VaddrIni:0x%08X AllocPage:%u) PDIdx:%u PTIdx:%u",sTmpDevVAddr.uiAddr, sDevVAddr.uiAddr,i, ui32PDIndex, ui32PTIndex ));
+
+
+ sTmpDevVAddr.uiAddr += psMMUHeap->ui32DataPageSize;
+
+
+ continue;
+ }
+
+
+ pui32Tmp = (IMG_UINT32*)ppsPTInfoList[0]->PTPageCpuVAddr;
+
+
+ if (!pui32Tmp)
+ {
+ continue;
+ }
+
+ CheckPT(ppsPTInfoList[0]);
+
+
+ if (pui32Tmp[ui32PTIndex] & SGX_MMU_PTE_VALID)
+ {
+ ppsPTInfoList[0]->ui32ValidPTECount--;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "MMU_UnmapPagesAndFreePTs: Page is already invalid for alloc at VAddr:0x%08X (VAddrIni:0x%08X AllocPage:%u) PDIdx:%u PTIdx:%u",sTmpDevVAddr.uiAddr, sDevVAddr.uiAddr,i, ui32PDIndex, ui32PTIndex ));
+ }
+
+
+ PVR_ASSERT((IMG_INT32)ppsPTInfoList[0]->ui32ValidPTECount >= 0);
+ MakeKernelPageReadWrite(ppsPTInfoList[0]->PTPageCpuVAddr);
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+ pui32Tmp[ui32PTIndex] = (psMMUHeap->psMMUContext->psDevInfo->sDummyDataDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PTE_VALID;
+#else
+
+#if defined(FIX_HW_BRN_31620)
+ BRN31620InvalidatePageTableEntry(psMMUHeap->psMMUContext, ui32PDIndex, ui32PTIndex, &pui32Tmp[ui32PTIndex]);
+#else
+ pui32Tmp[ui32PTIndex] = 0;
+#endif
+#endif
+ MakeKernelPageReadOnly(ppsPTInfoList[0]->PTPageCpuVAddr);
+ CheckPT(ppsPTInfoList[0]);
+ }
+
+
+
+ if (ppsPTInfoList[0] && (ppsPTInfoList[0]->ui32ValidPTECount == 0)
+ )
+ {
+#if defined(FIX_HW_BRN_31620)
+ if (BRN31620FreePageTable(psMMUHeap, ui32PDIndex) == IMG_TRUE)
+ {
+ bInvalidateDirectoryCache = IMG_TRUE;
+ }
+#else
+ _DeferredFreePageTable(psMMUHeap, ui32PDIndex - psMMUHeap->ui32PDBaseIndex, IMG_TRUE);
+ bInvalidateDirectoryCache = IMG_TRUE;
+#endif
+ }
+
+
+ sTmpDevVAddr.uiAddr += psMMUHeap->ui32DataPageSize;
+ }
+
+ if(bInvalidateDirectoryCache)
+ {
+ MMU_InvalidateDirectoryCache(psMMUHeap->psMMUContext->psDevInfo);
+ }
+ else
+ {
+ MMU_InvalidatePageTableCache(psMMUHeap->psMMUContext->psDevInfo);
+ }
+
+#if defined(PDUMP)
+ MMU_PDumpPageTables(psMMUHeap,
+ sDevVAddr,
+ psMMUHeap->ui32DataPageSize * ui32PageCount,
+ IMG_TRUE,
+ hUniqueTag);
+#endif
+}
+
+
+static IMG_VOID MMU_FreePageTables(IMG_PVOID pvMMUHeap,
+ IMG_SIZE_T ui32Start,
+ IMG_SIZE_T ui32End,
+ IMG_HANDLE hUniqueTag)
+{
+ MMU_HEAP *pMMUHeap = (MMU_HEAP*)pvMMUHeap;
+ IMG_DEV_VIRTADDR Start;
+
+ Start.uiAddr = (IMG_UINT32)ui32Start;
+
+ MMU_UnmapPagesAndFreePTs(pMMUHeap, Start, (IMG_UINT32)((ui32End - ui32Start) >> pMMUHeap->ui32PTShift), hUniqueTag);
+}
+
+MMU_HEAP *
+MMU_Create (MMU_CONTEXT *psMMUContext,
+ DEV_ARENA_DESCRIPTOR *psDevArena,
+ RA_ARENA **ppsVMArena,
+ PDUMP_MMU_ATTRIB **ppsMMUAttrib)
+{
+ MMU_HEAP *pMMUHeap;
+ IMG_UINT32 ui32ScaleSize;
+
+ PVR_UNREFERENCED_PARAMETER(ppsMMUAttrib);
+
+ PVR_ASSERT (psDevArena != IMG_NULL);
+
+ if (psDevArena == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Create: invalid parameter"));
+ return IMG_NULL;
+ }
+
+ OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof (MMU_HEAP),
+ (IMG_VOID **)&pMMUHeap, IMG_NULL,
+ "MMU Heap");
+ if (pMMUHeap == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Create: ERROR call to OSAllocMem failed"));
+ return IMG_NULL;
+ }
+
+ pMMUHeap->psMMUContext = psMMUContext;
+ pMMUHeap->psDevArena = psDevArena;
+
+
+
+
+ switch(pMMUHeap->psDevArena->ui32DataPageSize)
+ {
+ case 0x1000:
+ ui32ScaleSize = 0;
+ pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_4K;
+ break;
+#if defined(SGX_FEATURE_VARIABLE_MMU_PAGE_SIZE)
+ case 0x4000:
+ ui32ScaleSize = 2;
+ pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_16K;
+ break;
+ case 0x10000:
+ ui32ScaleSize = 4;
+ pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_64K;
+ break;
+ case 0x40000:
+ ui32ScaleSize = 6;
+ pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_256K;
+ break;
+ case 0x100000:
+ ui32ScaleSize = 8;
+ pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_1M;
+ break;
+ case 0x400000:
+ ui32ScaleSize = 10;
+ pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_4M;
+ break;
+#endif
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Create: invalid data page size"));
+ goto ErrorFreeHeap;
+ }
+
+
+ pMMUHeap->ui32DataPageSize = psDevArena->ui32DataPageSize;
+ pMMUHeap->ui32DataPageBitWidth = SGX_MMU_PAGE_SHIFT + ui32ScaleSize;
+ pMMUHeap->ui32DataPageMask = pMMUHeap->ui32DataPageSize - 1;
+
+ pMMUHeap->ui32PTShift = pMMUHeap->ui32DataPageBitWidth;
+ pMMUHeap->ui32PTBitWidth = SGX_MMU_PT_SHIFT - ui32ScaleSize;
+ pMMUHeap->ui32PTMask = SGX_MMU_PT_MASK & (SGX_MMU_PT_MASK<<ui32ScaleSize);
+ pMMUHeap->ui32PTSize = (IMG_UINT32)(1UL<<pMMUHeap->ui32PTBitWidth) * sizeof(IMG_UINT32);
+
+
+ if(pMMUHeap->ui32PTSize < 4 * sizeof(IMG_UINT32))
+ {
+ pMMUHeap->ui32PTSize = 4 * sizeof(IMG_UINT32);
+ }
+ pMMUHeap->ui32PTNumEntriesAllocated = pMMUHeap->ui32PTSize >> 2;
+
+
+ pMMUHeap->ui32PTNumEntriesUsable = (IMG_UINT32)(1UL << pMMUHeap->ui32PTBitWidth);
+
+
+ pMMUHeap->ui32PDShift = pMMUHeap->ui32PTBitWidth + pMMUHeap->ui32PTShift;
+ pMMUHeap->ui32PDBitWidth = SGX_FEATURE_ADDRESS_SPACE_SIZE - pMMUHeap->ui32PTBitWidth - pMMUHeap->ui32DataPageBitWidth;
+ pMMUHeap->ui32PDMask = SGX_MMU_PD_MASK & (SGX_MMU_PD_MASK>>(32-SGX_FEATURE_ADDRESS_SPACE_SIZE));
+
+
+#if !defined (SUPPORT_EXTERNAL_SYSTEM_CACHE)
+
+
+
+
+ if(psDevArena->BaseDevVAddr.uiAddr > (pMMUHeap->ui32DataPageMask | pMMUHeap->ui32PTMask))
+ {
+
+
+
+ PVR_ASSERT ((psDevArena->BaseDevVAddr.uiAddr
+ & (pMMUHeap->ui32DataPageMask
+ | pMMUHeap->ui32PTMask)) == 0);
+ }
+#endif
+
+ pMMUHeap->ui32PTETotalUsable = pMMUHeap->psDevArena->ui32Size >> pMMUHeap->ui32PTShift;
+
+
+ pMMUHeap->ui32PDBaseIndex = (pMMUHeap->psDevArena->BaseDevVAddr.uiAddr & pMMUHeap->ui32PDMask) >> pMMUHeap->ui32PDShift;
+
+
+
+
+ pMMUHeap->ui32PageTableCount = (pMMUHeap->ui32PTETotalUsable + pMMUHeap->ui32PTNumEntriesUsable - 1)
+ >> pMMUHeap->ui32PTBitWidth;
+ PVR_ASSERT(pMMUHeap->ui32PageTableCount > 0);
+
+
+ pMMUHeap->psVMArena = RA_Create(psDevArena->pszName,
+ psDevArena->BaseDevVAddr.uiAddr,
+ psDevArena->ui32Size,
+ IMG_NULL,
+ MAX(HOST_PAGESIZE(), pMMUHeap->ui32DataPageSize),
+ IMG_NULL,
+ IMG_NULL,
+ &MMU_FreePageTables,
+ pMMUHeap);
+
+ if (pMMUHeap->psVMArena == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Create: ERROR call to RA_Create failed"));
+ goto ErrorFreePagetables;
+ }
+
+#if defined(PDUMP)
+
+ MMU_SetPDumpAttribs(&pMMUHeap->sMMUAttrib,
+ psMMUContext->psDeviceNode,
+ pMMUHeap->ui32DataPageMask,
+ pMMUHeap->ui32PTSize);
+ *ppsMMUAttrib = &pMMUHeap->sMMUAttrib;
+
+ PDUMPCOMMENT("Create MMU device from arena %s (Size == 0x%x, DataPageSize == 0x%x, BaseDevVAddr == 0x%x)",
+ psDevArena->pszName,
+ psDevArena->ui32Size,
+ pMMUHeap->ui32DataPageSize,
+ psDevArena->BaseDevVAddr.uiAddr);
+#endif
+
+#if 0
+
+ if(psDevArena->ui32HeapID == SGX_TILED_HEAP_ID)
+ {
+ IMG_UINT32 ui32RegVal;
+ IMG_UINT32 ui32XTileStride;
+
+
+
+
+
+
+ ui32XTileStride = 2;
+
+ ui32RegVal = (EUR_CR_BIF_TILE0_MIN_ADDRESS_MASK
+ & ((psDevArena->BaseDevVAddr.uiAddr>>20)
+ << EUR_CR_BIF_TILE0_MIN_ADDRESS_SHIFT))
+ |(EUR_CR_BIF_TILE0_MAX_ADDRESS_MASK
+ & (((psDevArena->BaseDevVAddr.uiAddr+psDevArena->ui32Size)>>20)
+ << EUR_CR_BIF_TILE0_MAX_ADDRESS_SHIFT))
+ |(EUR_CR_BIF_TILE0_CFG_MASK
+ & (((ui32XTileStride<<1)|8) << EUR_CR_BIF_TILE0_CFG_SHIFT));
+ PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_TILE0, ui32RegVal);
+ }
+#endif
+
+
+
+ *ppsVMArena = pMMUHeap->psVMArena;
+
+ return pMMUHeap;
+
+
+ErrorFreePagetables:
+ _DeferredFreePageTables (pMMUHeap);
+
+ErrorFreeHeap:
+ OSFreeMem (PVRSRV_OS_PAGEABLE_HEAP, sizeof(MMU_HEAP), pMMUHeap, IMG_NULL);
+
+
+ return IMG_NULL;
+}
+
+IMG_VOID
+MMU_Delete (MMU_HEAP *pMMUHeap)
+{
+ if (pMMUHeap != IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_MESSAGE, "MMU_Delete"));
+
+ if(pMMUHeap->psVMArena)
+ {
+ RA_Delete (pMMUHeap->psVMArena);
+ }
+
+#if defined(PDUMP)
+ PDUMPCOMMENT("Delete MMU device from arena %s (BaseDevVAddr == 0x%x, PT count for deferred free == 0x%x)",
+ pMMUHeap->psDevArena->pszName,
+ pMMUHeap->psDevArena->BaseDevVAddr.uiAddr,
+ pMMUHeap->ui32PageTableCount);
+#endif
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+ EnableHostAccess(pMMUHeap->psMMUContext);
+#endif
+ _DeferredFreePageTables (pMMUHeap);
+#ifdef SUPPORT_SGX_MMU_BYPASS
+ DisableHostAccess(pMMUHeap->psMMUContext);
+#endif
+
+ OSFreeMem (PVRSRV_OS_PAGEABLE_HEAP, sizeof(MMU_HEAP), pMMUHeap, IMG_NULL);
+
+ }
+}
+
+IMG_BOOL
+MMU_Alloc (MMU_HEAP *pMMUHeap,
+ IMG_SIZE_T uSize,
+ IMG_SIZE_T *pActualSize,
+ IMG_UINT32 uFlags,
+ IMG_UINT32 uDevVAddrAlignment,
+ IMG_DEV_VIRTADDR *psDevVAddr)
+{
+ IMG_BOOL bStatus;
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "MMU_Alloc: uSize=0x%x, flags=0x%x, align=0x%x",
+ uSize, uFlags, uDevVAddrAlignment));
+
+
+
+ if((uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR) == 0)
+ {
+ IMG_UINTPTR_T uiAddr;
+
+ bStatus = RA_Alloc (pMMUHeap->psVMArena,
+ uSize,
+ pActualSize,
+ IMG_NULL,
+ 0,
+ uDevVAddrAlignment,
+ 0,
+ IMG_NULL,
+ 0,
+ &uiAddr);
+ if(!bStatus)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"MMU_Alloc: RA_Alloc of VMArena failed"));
+ PVR_DPF((PVR_DBG_ERROR,"MMU_Alloc: Alloc of DevVAddr failed from heap %s ID%d",
+ pMMUHeap->psDevArena->pszName,
+ pMMUHeap->psDevArena->ui32HeapID));
+ return bStatus;
+ }
+
+ psDevVAddr->uiAddr = IMG_CAST_TO_DEVVADDR_UINT(uiAddr);
+ }
+
+ #ifdef SUPPORT_SGX_MMU_BYPASS
+ EnableHostAccess(pMMUHeap->psMMUContext);
+ #endif
+
+
+ bStatus = _DeferredAllocPagetables(pMMUHeap, *psDevVAddr, (IMG_UINT32)uSize);
+
+ #ifdef SUPPORT_SGX_MMU_BYPASS
+ DisableHostAccess(pMMUHeap->psMMUContext);
+ #endif
+
+ if (!bStatus)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"MMU_Alloc: _DeferredAllocPagetables failed"));
+ PVR_DPF((PVR_DBG_ERROR,"MMU_Alloc: Failed to alloc pagetable(s) for DevVAddr 0x%8.8x from heap %s ID%d",
+ psDevVAddr->uiAddr,
+ pMMUHeap->psDevArena->pszName,
+ pMMUHeap->psDevArena->ui32HeapID));
+ if((uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR) == 0)
+ {
+
+ RA_Free (pMMUHeap->psVMArena, psDevVAddr->uiAddr, IMG_FALSE);
+ }
+ }
+
+ return bStatus;
+}
+
+IMG_VOID
+MMU_Free (MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT32 ui32Size)
+{
+ PVR_ASSERT (pMMUHeap != IMG_NULL);
+
+ if (pMMUHeap == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Free: invalid parameter"));
+ return;
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE, "MMU_Free: Freeing DevVAddr 0x%08X from heap %s ID%d",
+ DevVAddr.uiAddr,
+ pMMUHeap->psDevArena->pszName,
+ pMMUHeap->psDevArena->ui32HeapID));
+
+ if((DevVAddr.uiAddr >= pMMUHeap->psDevArena->BaseDevVAddr.uiAddr) &&
+ (DevVAddr.uiAddr + ui32Size <= pMMUHeap->psDevArena->BaseDevVAddr.uiAddr + pMMUHeap->psDevArena->ui32Size))
+ {
+ RA_Free (pMMUHeap->psVMArena, DevVAddr.uiAddr, IMG_TRUE);
+ return;
+ }
+
+ PVR_DPF((PVR_DBG_ERROR,"MMU_Free: Couldn't free DevVAddr %08X from heap %s ID%d (not in range of heap))",
+ DevVAddr.uiAddr,
+ pMMUHeap->psDevArena->pszName,
+ pMMUHeap->psDevArena->ui32HeapID));
+}
+
+IMG_VOID
+MMU_Enable (MMU_HEAP *pMMUHeap)
+{
+ PVR_UNREFERENCED_PARAMETER(pMMUHeap);
+
+}
+
+IMG_VOID
+MMU_Disable (MMU_HEAP *pMMUHeap)
+{
+ PVR_UNREFERENCED_PARAMETER(pMMUHeap);
+
+}
+
+#if defined(FIX_HW_BRN_31620)
+IMG_VOID MMU_GetCacheFlushRange(MMU_CONTEXT *pMMUContext, IMG_UINT32 *pui32RangeMask)
+{
+ IMG_UINT32 i;
+
+ for (i=0;i<BRN31620_CACHE_FLUSH_INDEX_SIZE;i++)
+ {
+ pui32RangeMask[i] = pMMUContext->ui32PDChangeMask[i];
+
+
+ pMMUContext->ui32PDChangeMask[i] = 0;
+ }
+}
+
+IMG_VOID MMU_GetPDPhysAddr(MMU_CONTEXT *pMMUContext, IMG_DEV_PHYADDR *psDevPAddr)
+{
+ *psDevPAddr = pMMUContext->sPDDevPAddr;
+}
+
+#endif
+#if defined(PDUMP)
+static IMG_VOID
+MMU_PDumpPageTables (MMU_HEAP *pMMUHeap,
+ IMG_DEV_VIRTADDR DevVAddr,
+ IMG_SIZE_T uSize,
+ IMG_BOOL bForUnmap,
+ IMG_HANDLE hUniqueTag)
+{
+ IMG_UINT32 ui32NumPTEntries;
+ IMG_UINT32 ui32PTIndex;
+ IMG_UINT32 *pui32PTEntry;
+
+ MMU_PT_INFO **ppsPTInfoList;
+ IMG_UINT32 ui32PDIndex;
+ IMG_UINT32 ui32PTDumpCount;
+
+
+ ui32NumPTEntries = (IMG_UINT32)((uSize + pMMUHeap->ui32DataPageMask) >> pMMUHeap->ui32PTShift);
+
+
+ ui32PDIndex = DevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+
+ ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+
+ ui32PTIndex = (DevVAddr.uiAddr & pMMUHeap->ui32PTMask) >> pMMUHeap->ui32PTShift;
+
+
+ PDUMPCOMMENT("Page table mods (num entries == %08X) %s", ui32NumPTEntries, bForUnmap ? "(for unmap)" : "");
+
+
+ while(ui32NumPTEntries > 0)
+ {
+ MMU_PT_INFO* psPTInfo = *ppsPTInfoList++;
+
+ if(ui32NumPTEntries <= pMMUHeap->ui32PTNumEntriesUsable - ui32PTIndex)
+ {
+ ui32PTDumpCount = ui32NumPTEntries;
+ }
+ else
+ {
+ ui32PTDumpCount = pMMUHeap->ui32PTNumEntriesUsable - ui32PTIndex;
+ }
+
+ if (psPTInfo)
+ {
+ IMG_UINT32 ui32Flags = 0;
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+ ui32Flags |= ( MMU_IsHeapShared(pMMUHeap) ) ? PDUMP_FLAGS_PERSISTENT : 0;
+#endif
+ pui32PTEntry = (IMG_UINT32*)psPTInfo->PTPageCpuVAddr;
+ PDUMPMEMPTENTRIES(&pMMUHeap->sMMUAttrib, psPTInfo->hPTPageOSMemHandle, (IMG_VOID *) &pui32PTEntry[ui32PTIndex], ui32PTDumpCount * sizeof(IMG_UINT32), ui32Flags, IMG_FALSE, PDUMP_PT_UNIQUETAG, hUniqueTag);
+ }
+
+
+ ui32NumPTEntries -= ui32PTDumpCount;
+
+
+ ui32PTIndex = 0;
+ }
+
+ PDUMPCOMMENT("Finished page table mods %s", bForUnmap ? "(for unmap)" : "");
+}
+#endif
+
+
+static IMG_VOID
+MMU_MapPage (MMU_HEAP *pMMUHeap,
+ IMG_DEV_VIRTADDR DevVAddr,
+ IMG_DEV_PHYADDR DevPAddr,
+ IMG_UINT32 ui32MemFlags)
+{
+ IMG_UINT32 ui32Index;
+ IMG_UINT32 *pui32Tmp;
+ IMG_UINT32 ui32MMUFlags = 0;
+ MMU_PT_INFO **ppsPTInfoList;
+
+
+ PVR_ASSERT((DevPAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
+
+
+
+ if(((PVRSRV_MEM_READ|PVRSRV_MEM_WRITE) & ui32MemFlags) == (PVRSRV_MEM_READ|PVRSRV_MEM_WRITE))
+ {
+
+ ui32MMUFlags = 0;
+ }
+ else if(PVRSRV_MEM_READ & ui32MemFlags)
+ {
+
+ ui32MMUFlags |= SGX_MMU_PTE_READONLY;
+ }
+ else if(PVRSRV_MEM_WRITE & ui32MemFlags)
+ {
+
+ ui32MMUFlags |= SGX_MMU_PTE_WRITEONLY;
+ }
+
+
+ if(PVRSRV_MEM_CACHE_CONSISTENT & ui32MemFlags)
+ {
+ ui32MMUFlags |= SGX_MMU_PTE_CACHECONSISTENT;
+ }
+
+#if !defined(FIX_HW_BRN_25503)
+
+ if(PVRSRV_MEM_EDM_PROTECT & ui32MemFlags)
+ {
+ ui32MMUFlags |= SGX_MMU_PTE_EDMPROTECT;
+ }
+#endif
+
+
+
+
+
+ ui32Index = DevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+
+ ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32Index];
+
+ CheckPT(ppsPTInfoList[0]);
+
+
+ ui32Index = (DevVAddr.uiAddr & pMMUHeap->ui32PTMask) >> pMMUHeap->ui32PTShift;
+
+
+ pui32Tmp = (IMG_UINT32*)ppsPTInfoList[0]->PTPageCpuVAddr;
+
+#if !defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+ {
+ IMG_UINT32 uTmp = pui32Tmp[ui32Index];
+
+
+#if defined(FIX_HW_BRN_31620)
+ if ((uTmp & SGX_MMU_PTE_VALID) && ((DevVAddr.uiAddr & BRN31620_PDE_CACHE_FILL_MASK) != BRN31620_DUMMY_PAGE_OFFSET))
+#else
+ if ((uTmp & SGX_MMU_PTE_VALID) != 0)
+#endif
+
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_MapPage: Page is already valid for alloc at VAddr:0x%08X PDIdx:%u PTIdx:%u",
+ DevVAddr.uiAddr,
+ DevVAddr.uiAddr >> pMMUHeap->ui32PDShift,
+ ui32Index ));
+ PVR_DPF((PVR_DBG_ERROR, "MMU_MapPage: Page table entry value: 0x%08X", uTmp));
+ PVR_DPF((PVR_DBG_ERROR, "MMU_MapPage: Physical page to map: 0x%08X", DevPAddr.uiAddr));
+#if PT_DUMP
+ DumpPT(ppsPTInfoList[0]);
+#endif
+ }
+#if !defined(FIX_HW_BRN_31620)
+ PVR_ASSERT((uTmp & SGX_MMU_PTE_VALID) == 0);
+#endif
+ }
+#endif
+
+
+ ppsPTInfoList[0]->ui32ValidPTECount++;
+
+ MakeKernelPageReadWrite(ppsPTInfoList[0]->PTPageCpuVAddr);
+
+ pui32Tmp[ui32Index] = ((DevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+ & ((~pMMUHeap->ui32DataPageMask)>>SGX_MMU_PTE_ADDR_ALIGNSHIFT))
+ | SGX_MMU_PTE_VALID
+ | ui32MMUFlags;
+ MakeKernelPageReadOnly(ppsPTInfoList[0]->PTPageCpuVAddr);
+ CheckPT(ppsPTInfoList[0]);
+}
+
+
+IMG_VOID
+MMU_MapScatter (MMU_HEAP *pMMUHeap,
+ IMG_DEV_VIRTADDR DevVAddr,
+ IMG_SYS_PHYADDR *psSysAddr,
+ IMG_SIZE_T uSize,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag)
+{
+#if defined(PDUMP)
+ IMG_DEV_VIRTADDR MapBaseDevVAddr;
+#endif
+ IMG_UINT32 uCount, i;
+ IMG_DEV_PHYADDR DevPAddr;
+
+ PVR_ASSERT (pMMUHeap != IMG_NULL);
+
+#if defined(PDUMP)
+ MapBaseDevVAddr = DevVAddr;
+#else
+ PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif
+
+ for (i=0, uCount=0; uCount<uSize; i++, uCount+=pMMUHeap->ui32DataPageSize)
+ {
+ IMG_SYS_PHYADDR sSysAddr;
+
+ sSysAddr = psSysAddr[i];
+
+
+
+ PVR_ASSERT((sSysAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
+
+ DevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysAddr);
+
+ MMU_MapPage (pMMUHeap, DevVAddr, DevPAddr, ui32MemFlags);
+ DevVAddr.uiAddr += pMMUHeap->ui32DataPageSize;
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "MMU_MapScatter: devVAddr=%08X, SysAddr=%08X, size=0x%x/0x%x",
+ DevVAddr.uiAddr, sSysAddr.uiAddr, uCount, uSize));
+ }
+
+#if defined(PDUMP)
+ MMU_PDumpPageTables (pMMUHeap, MapBaseDevVAddr, uSize, IMG_FALSE, hUniqueTag);
+#endif
+}
+
+IMG_VOID
+MMU_MapPages (MMU_HEAP *pMMUHeap,
+ IMG_DEV_VIRTADDR DevVAddr,
+ IMG_SYS_PHYADDR SysPAddr,
+ IMG_SIZE_T uSize,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag)
+{
+ IMG_DEV_PHYADDR DevPAddr;
+#if defined(PDUMP)
+ IMG_DEV_VIRTADDR MapBaseDevVAddr;
+#endif
+ IMG_UINT32 uCount;
+ IMG_UINT32 ui32VAdvance;
+ IMG_UINT32 ui32PAdvance;
+
+ PVR_ASSERT (pMMUHeap != IMG_NULL);
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "MMU_MapPages: heap:%s, heap_id:%d devVAddr=%08X, SysPAddr=%08X, size=0x%x",
+ pMMUHeap->psDevArena->pszName,
+ pMMUHeap->psDevArena->ui32HeapID,
+ DevVAddr.uiAddr,
+ SysPAddr.uiAddr,
+ uSize));
+
+
+ ui32VAdvance = pMMUHeap->ui32DataPageSize;
+ ui32PAdvance = pMMUHeap->ui32DataPageSize;
+
+#if defined(PDUMP)
+ MapBaseDevVAddr = DevVAddr;
+#else
+ PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif
+
+ DevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, SysPAddr);
+
+
+ PVR_ASSERT((DevPAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
+
+#if defined(FIX_HW_BRN_23281)
+ if(ui32MemFlags & PVRSRV_MEM_INTERLEAVED)
+ {
+ ui32VAdvance *= 2;
+ }
+#endif
+
+
+
+
+ if(ui32MemFlags & PVRSRV_MEM_DUMMY)
+ {
+ ui32PAdvance = 0;
+ }
+
+ for (uCount=0; uCount<uSize; uCount+=ui32VAdvance)
+ {
+ MMU_MapPage (pMMUHeap, DevVAddr, DevPAddr, ui32MemFlags);
+ DevVAddr.uiAddr += ui32VAdvance;
+ DevPAddr.uiAddr += ui32PAdvance;
+ }
+
+#if defined(PDUMP)
+ MMU_PDumpPageTables (pMMUHeap, MapBaseDevVAddr, uSize, IMG_FALSE, hUniqueTag);
+#endif
+}
+
+IMG_VOID
+MMU_MapShadow (MMU_HEAP *pMMUHeap,
+ IMG_DEV_VIRTADDR MapBaseDevVAddr,
+ IMG_SIZE_T uByteSize,
+ IMG_CPU_VIRTADDR CpuVAddr,
+ IMG_HANDLE hOSMemHandle,
+ IMG_DEV_VIRTADDR *pDevVAddr,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag)
+{
+ IMG_UINT32 i;
+ IMG_UINT32 uOffset = 0;
+ IMG_DEV_VIRTADDR MapDevVAddr;
+ IMG_UINT32 ui32VAdvance;
+ IMG_UINT32 ui32PAdvance;
+
+#if !defined (PDUMP)
+ PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "MMU_MapShadow: DevVAddr:%08X, Bytes:0x%x, CPUVAddr:%08X",
+ MapBaseDevVAddr.uiAddr,
+ uByteSize,
+ (IMG_UINTPTR_T)CpuVAddr));
+
+
+ ui32VAdvance = pMMUHeap->ui32DataPageSize;
+ ui32PAdvance = pMMUHeap->ui32DataPageSize;
+
+
+ PVR_ASSERT(((IMG_UINTPTR_T)CpuVAddr & (SGX_MMU_PAGE_SIZE - 1)) == 0);
+ PVR_ASSERT(((IMG_UINT32)uByteSize & pMMUHeap->ui32DataPageMask) == 0);
+ pDevVAddr->uiAddr = MapBaseDevVAddr.uiAddr;
+
+#if defined(FIX_HW_BRN_23281)
+ if(ui32MemFlags & PVRSRV_MEM_INTERLEAVED)
+ {
+ ui32VAdvance *= 2;
+ }
+#endif
+
+
+
+
+ if(ui32MemFlags & PVRSRV_MEM_DUMMY)
+ {
+ ui32PAdvance = 0;
+ }
+
+
+ MapDevVAddr = MapBaseDevVAddr;
+ for (i=0; i<uByteSize; i+=ui32VAdvance)
+ {
+ IMG_CPU_PHYADDR CpuPAddr;
+ IMG_DEV_PHYADDR DevPAddr;
+
+ if(CpuVAddr)
+ {
+ CpuPAddr = OSMapLinToCPUPhys (hOSMemHandle,
+ (IMG_VOID *)((IMG_UINTPTR_T)CpuVAddr + uOffset));
+ }
+ else
+ {
+ CpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, uOffset);
+ }
+ DevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, CpuPAddr);
+
+
+ PVR_ASSERT((DevPAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "Offset=0x%x: CpuVAddr=%08X, CpuPAddr=%08X, DevVAddr=%08X, DevPAddr=%08X",
+ uOffset,
+ (IMG_UINTPTR_T)CpuVAddr + uOffset,
+ CpuPAddr.uiAddr,
+ MapDevVAddr.uiAddr,
+ DevPAddr.uiAddr));
+
+ MMU_MapPage (pMMUHeap, MapDevVAddr, DevPAddr, ui32MemFlags);
+
+
+ MapDevVAddr.uiAddr += ui32VAdvance;
+ uOffset += ui32PAdvance;
+ }
+
+#if defined(PDUMP)
+ MMU_PDumpPageTables (pMMUHeap, MapBaseDevVAddr, uByteSize, IMG_FALSE, hUniqueTag);
+#endif
+}
+
+
+IMG_VOID
+MMU_UnmapPages (MMU_HEAP *psMMUHeap,
+ IMG_DEV_VIRTADDR sDevVAddr,
+ IMG_UINT32 ui32PageCount,
+ IMG_HANDLE hUniqueTag)
+{
+ IMG_UINT32 uPageSize = psMMUHeap->ui32DataPageSize;
+ IMG_DEV_VIRTADDR sTmpDevVAddr;
+ IMG_UINT32 i;
+ IMG_UINT32 ui32PDIndex;
+ IMG_UINT32 ui32PTIndex;
+ IMG_UINT32 *pui32Tmp;
+
+#if !defined (PDUMP)
+ PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif
+
+
+ sTmpDevVAddr = sDevVAddr;
+
+ for(i=0; i<ui32PageCount; i++)
+ {
+ MMU_PT_INFO **ppsPTInfoList;
+
+
+ ui32PDIndex = sTmpDevVAddr.uiAddr >> psMMUHeap->ui32PDShift;
+
+
+ ppsPTInfoList = &psMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+
+ ui32PTIndex = (sTmpDevVAddr.uiAddr & psMMUHeap->ui32PTMask) >> psMMUHeap->ui32PTShift;
+
+
+ if (!ppsPTInfoList[0])
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_UnmapPages: ERROR Invalid PT for alloc at VAddr:0x%08X (VaddrIni:0x%08X AllocPage:%u) PDIdx:%u PTIdx:%u",
+ sTmpDevVAddr.uiAddr,
+ sDevVAddr.uiAddr,
+ i,
+ ui32PDIndex,
+ ui32PTIndex));
+
+
+ sTmpDevVAddr.uiAddr += uPageSize;
+
+
+ continue;
+ }
+
+ CheckPT(ppsPTInfoList[0]);
+
+
+ pui32Tmp = (IMG_UINT32*)ppsPTInfoList[0]->PTPageCpuVAddr;
+
+
+ if (pui32Tmp[ui32PTIndex] & SGX_MMU_PTE_VALID)
+ {
+ ppsPTInfoList[0]->ui32ValidPTECount--;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_UnmapPages: Page is already invalid for alloc at VAddr:0x%08X (VAddrIni:0x%08X AllocPage:%u) PDIdx:%u PTIdx:%u",
+ sTmpDevVAddr.uiAddr,
+ sDevVAddr.uiAddr,
+ i,
+ ui32PDIndex,
+ ui32PTIndex));
+ PVR_DPF((PVR_DBG_ERROR, "MMU_UnmapPages: Page table entry value: 0x%08X", pui32Tmp[ui32PTIndex]));
+ }
+
+
+ PVR_ASSERT((IMG_INT32)ppsPTInfoList[0]->ui32ValidPTECount >= 0);
+
+ MakeKernelPageReadWrite(ppsPTInfoList[0]->PTPageCpuVAddr);
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+ pui32Tmp[ui32PTIndex] = (psMMUHeap->psMMUContext->psDevInfo->sDummyDataDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PTE_VALID;
+#else
+
+#if defined(FIX_HW_BRN_31620)
+ BRN31620InvalidatePageTableEntry(psMMUHeap->psMMUContext, ui32PDIndex, ui32PTIndex, &pui32Tmp[ui32PTIndex]);
+#else
+ pui32Tmp[ui32PTIndex] = 0;
+#endif
+#endif
+ MakeKernelPageReadOnly(ppsPTInfoList[0]->PTPageCpuVAddr);
+
+ CheckPT(ppsPTInfoList[0]);
+
+
+ sTmpDevVAddr.uiAddr += uPageSize;
+ }
+
+ MMU_InvalidatePageTableCache(psMMUHeap->psMMUContext->psDevInfo);
+
+#if defined(PDUMP)
+ MMU_PDumpPageTables (psMMUHeap, sDevVAddr, uPageSize*ui32PageCount, IMG_TRUE, hUniqueTag);
+#endif
+}
+
+
+IMG_DEV_PHYADDR
+MMU_GetPhysPageAddr(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR sDevVPageAddr)
+{
+ IMG_UINT32 *pui32PageTable;
+ IMG_UINT32 ui32Index;
+ IMG_DEV_PHYADDR sDevPAddr;
+ MMU_PT_INFO **ppsPTInfoList;
+
+
+ ui32Index = sDevVPageAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+
+ ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32Index];
+ if (!ppsPTInfoList[0])
+ {
+ PVR_DPF((PVR_DBG_ERROR,"MMU_GetPhysPageAddr: Not mapped in at 0x%08x", sDevVPageAddr.uiAddr));
+ sDevPAddr.uiAddr = 0;
+ return sDevPAddr;
+ }
+
+
+ ui32Index = (sDevVPageAddr.uiAddr & pMMUHeap->ui32PTMask) >> pMMUHeap->ui32PTShift;
+
+
+ pui32PageTable = (IMG_UINT32*)ppsPTInfoList[0]->PTPageCpuVAddr;
+
+
+ sDevPAddr.uiAddr = pui32PageTable[ui32Index];
+
+
+ sDevPAddr.uiAddr &= ~(pMMUHeap->ui32DataPageMask>>SGX_MMU_PTE_ADDR_ALIGNSHIFT);
+
+
+ sDevPAddr.uiAddr <<= SGX_MMU_PTE_ADDR_ALIGNSHIFT;
+
+ return sDevPAddr;
+}
+
+
+IMG_DEV_PHYADDR MMU_GetPDDevPAddr(MMU_CONTEXT *pMMUContext)
+{
+ return (pMMUContext->sPDDevPAddr);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR SGXGetPhysPageAddrKM (IMG_HANDLE hDevMemHeap,
+ IMG_DEV_VIRTADDR sDevVAddr,
+ IMG_DEV_PHYADDR *pDevPAddr,
+ IMG_CPU_PHYADDR *pCpuPAddr)
+{
+ MMU_HEAP *pMMUHeap;
+ IMG_DEV_PHYADDR DevPAddr;
+
+
+
+ pMMUHeap = (MMU_HEAP*)BM_GetMMUHeap(hDevMemHeap);
+
+ DevPAddr = MMU_GetPhysPageAddr(pMMUHeap, sDevVAddr);
+ pCpuPAddr->uiAddr = DevPAddr.uiAddr;
+ pDevPAddr->uiAddr = DevPAddr.uiAddr;
+
+ return (pDevPAddr->uiAddr != 0) ? PVRSRV_OK : PVRSRV_ERROR_INVALID_PARAMS;
+}
+
+
+PVRSRV_ERROR SGXGetMMUPDAddrKM(IMG_HANDLE hDevCookie,
+ IMG_HANDLE hDevMemContext,
+ IMG_DEV_PHYADDR *psPDDevPAddr)
+{
+ if (!hDevCookie || !hDevMemContext || !psPDDevPAddr)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ *psPDDevPAddr = ((BM_CONTEXT*)hDevMemContext)->psMMUContext->sPDDevPAddr;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR MMU_BIFResetPDAlloc(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+ RA_ARENA *psLocalDevMemArena;
+ IMG_HANDLE hOSMemHandle = IMG_NULL;
+ IMG_BYTE *pui8MemBlock = IMG_NULL;
+ IMG_SYS_PHYADDR sMemBlockSysPAddr;
+ IMG_CPU_PHYADDR sMemBlockCpuPAddr;
+
+ SysAcquireData(&psSysData);
+
+ psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
+
+
+ if(psLocalDevMemArena == IMG_NULL)
+ {
+
+ eError = OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ 3 * SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ 0,
+ (IMG_VOID **)&pui8MemBlock,
+ &hOSMemHandle);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_BIFResetPDAlloc: ERROR call to OSAllocPages failed"));
+ return eError;
+ }
+
+
+ if(pui8MemBlock)
+ {
+ sMemBlockCpuPAddr = OSMapLinToCPUPhys(hOSMemHandle,
+ pui8MemBlock);
+ }
+ else
+ {
+
+ sMemBlockCpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, 0);
+ }
+ }
+ else
+ {
+
+
+ if(RA_Alloc(psLocalDevMemArena,
+ 3 * SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ IMG_NULL,
+ 0,
+ SGX_MMU_PAGE_SIZE,
+ 0,
+ IMG_NULL,
+ 0,
+ &(sMemBlockSysPAddr.uiAddr)) != IMG_TRUE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_BIFResetPDAlloc: ERROR call to RA_Alloc failed"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+
+ sMemBlockCpuPAddr = SysSysPAddrToCpuPAddr(sMemBlockSysPAddr);
+ pui8MemBlock = OSMapPhysToLin(sMemBlockCpuPAddr,
+ SGX_MMU_PAGE_SIZE * 3,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ &hOSMemHandle);
+ if(!pui8MemBlock)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_BIFResetPDAlloc: ERROR failed to map page tables"));
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+ }
+
+ psDevInfo->hBIFResetPDOSMemHandle = hOSMemHandle;
+ psDevInfo->sBIFResetPDDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sMemBlockCpuPAddr);
+ psDevInfo->sBIFResetPTDevPAddr.uiAddr = psDevInfo->sBIFResetPDDevPAddr.uiAddr + SGX_MMU_PAGE_SIZE;
+ psDevInfo->sBIFResetPageDevPAddr.uiAddr = psDevInfo->sBIFResetPTDevPAddr.uiAddr + SGX_MMU_PAGE_SIZE;
+
+
+ psDevInfo->pui32BIFResetPD = (IMG_UINT32 *)pui8MemBlock;
+ psDevInfo->pui32BIFResetPT = (IMG_UINT32 *)(pui8MemBlock + SGX_MMU_PAGE_SIZE);
+
+
+ OSMemSet(psDevInfo->pui32BIFResetPD, 0, SGX_MMU_PAGE_SIZE);
+ OSMemSet(psDevInfo->pui32BIFResetPT, 0, SGX_MMU_PAGE_SIZE);
+
+ OSMemSet(pui8MemBlock + (2 * SGX_MMU_PAGE_SIZE), 0xDB, SGX_MMU_PAGE_SIZE);
+
+ return PVRSRV_OK;
+}
+
+IMG_VOID MMU_BIFResetPDFree(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ SYS_DATA *psSysData;
+ RA_ARENA *psLocalDevMemArena;
+ IMG_SYS_PHYADDR sPDSysPAddr;
+
+ SysAcquireData(&psSysData);
+
+ psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
+
+
+ if(psLocalDevMemArena == IMG_NULL)
+ {
+ OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ 3 * SGX_MMU_PAGE_SIZE,
+ psDevInfo->pui32BIFResetPD,
+ psDevInfo->hBIFResetPDOSMemHandle);
+ }
+ else
+ {
+ OSUnMapPhysToLin(psDevInfo->pui32BIFResetPD,
+ 3 * SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ psDevInfo->hBIFResetPDOSMemHandle);
+
+ sPDSysPAddr = SysDevPAddrToSysPAddr(PVRSRV_DEVICE_TYPE_SGX, psDevInfo->sBIFResetPDDevPAddr);
+ RA_Free(psLocalDevMemArena, sPDSysPAddr.uiAddr, IMG_FALSE);
+ }
+}
+
+IMG_VOID MMU_CheckFaultAddr(PVRSRV_SGXDEV_INFO *psDevInfo, IMG_UINT32 ui32PDDevPAddr, IMG_UINT32 ui32FaultAddr)
+{
+ MMU_CONTEXT *psMMUContext = psDevInfo->pvMMUContextList;
+
+ while (psMMUContext && (psMMUContext->sPDDevPAddr.uiAddr != ui32PDDevPAddr))
+ {
+ psMMUContext = psMMUContext->psNext;
+ }
+
+ if (psMMUContext)
+ {
+ IMG_UINT32 ui32PTIndex;
+ IMG_UINT32 ui32PDIndex;
+
+ PVR_LOG(("Found MMU context for page fault 0x%08x", ui32FaultAddr));
+
+ ui32PTIndex = (ui32FaultAddr & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
+ ui32PDIndex = (ui32FaultAddr & SGX_MMU_PD_MASK) >> (SGX_MMU_PT_SHIFT + SGX_MMU_PAGE_SHIFT);
+
+ if (psMMUContext->apsPTInfoList[ui32PDIndex])
+ {
+ if (psMMUContext->apsPTInfoList[ui32PDIndex]->PTPageCpuVAddr)
+ {
+ IMG_UINT32 *pui32Ptr = psMMUContext->apsPTInfoList[ui32PDIndex]->PTPageCpuVAddr;
+ IMG_UINT32 ui32PTE = pui32Ptr[ui32PTIndex];
+
+ PVR_LOG(("PDE valid: PTE = 0x%08x (PhysAddr = 0x%08x, %s)",
+ ui32PTE,
+ ui32PTE & SGX_MMU_PTE_ADDR_MASK,
+ ui32PTE & SGX_MMU_PTE_VALID?"valid":"Invalid"));
+
+ DumpPT(psMMUContext->apsPTInfoList[ui32PDIndex]);
+ }
+ else
+ {
+ PVR_LOG(("Found PT info but no CPU address"));
+ }
+ }
+ else
+ {
+ PVR_LOG(("No PDE found"));
+ }
+ }
+}
+
+#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
+PVRSRV_ERROR WorkaroundBRN22997Alloc(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+ RA_ARENA *psLocalDevMemArena;
+ IMG_HANDLE hPTPageOSMemHandle = IMG_NULL;
+ IMG_HANDLE hPDPageOSMemHandle = IMG_NULL;
+ IMG_UINT32 *pui32PD = IMG_NULL;
+ IMG_UINT32 *pui32PT = IMG_NULL;
+ IMG_CPU_PHYADDR sCpuPAddr;
+ IMG_DEV_PHYADDR sPTDevPAddr;
+ IMG_DEV_PHYADDR sPDDevPAddr;
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+ IMG_UINT32 ui32PDOffset;
+ IMG_UINT32 ui32PTOffset;
+
+ psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+
+ SysAcquireData(&psSysData);
+
+ psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
+
+
+ if(psLocalDevMemArena == IMG_NULL)
+ {
+
+ eError = OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ 0,
+ (IMG_VOID **)&pui32PT,
+ &hPTPageOSMemHandle);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "WorkaroundBRN22997: ERROR call to OSAllocPages failed"));
+ return eError;
+ }
+ ui32PTOffset = 0;
+
+ eError = OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ 0,
+ (IMG_VOID **)&pui32PD,
+ &hPDPageOSMemHandle);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "WorkaroundBRN22997: ERROR call to OSAllocPages failed"));
+ return eError;
+ }
+ ui32PDOffset = 0;
+
+
+ if(pui32PT)
+ {
+ sCpuPAddr = OSMapLinToCPUPhys(hPTPageOSMemHandle,
+ pui32PT);
+ }
+ else
+ {
+
+ sCpuPAddr = OSMemHandleToCpuPAddr(hPTPageOSMemHandle, 0);
+ }
+ sPTDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+
+ if(pui32PD)
+ {
+ sCpuPAddr = OSMapLinToCPUPhys(hPDPageOSMemHandle,
+ pui32PD);
+ }
+ else
+ {
+
+ sCpuPAddr = OSMemHandleToCpuPAddr(hPDPageOSMemHandle, 0);
+ }
+ sPDDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+
+ }
+ else
+ {
+
+
+ if(RA_Alloc(psLocalDevMemArena,
+ SGX_MMU_PAGE_SIZE * 2,
+ IMG_NULL,
+ IMG_NULL,
+ 0,
+ SGX_MMU_PAGE_SIZE,
+ 0,
+ IMG_NULL,
+ 0,
+ &(psDevInfo->sBRN22997SysPAddr.uiAddr))!= IMG_TRUE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "WorkaroundBRN22997: ERROR call to RA_Alloc failed"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+
+ sCpuPAddr = SysSysPAddrToCpuPAddr(psDevInfo->sBRN22997SysPAddr);
+ pui32PT = OSMapPhysToLin(sCpuPAddr,
+ SGX_MMU_PAGE_SIZE * 2,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ &hPTPageOSMemHandle);
+ if(!pui32PT)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "WorkaroundBRN22997: ERROR failed to map page tables"));
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+ ui32PTOffset = 0;
+
+
+ sPTDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+
+ pui32PD = pui32PT + SGX_MMU_PAGE_SIZE/sizeof(IMG_UINT32);
+ ui32PDOffset = SGX_MMU_PAGE_SIZE;
+ hPDPageOSMemHandle = hPTPageOSMemHandle;
+ sPDDevPAddr.uiAddr = sPTDevPAddr.uiAddr + SGX_MMU_PAGE_SIZE;
+ }
+
+ OSMemSet(pui32PD, 0, SGX_MMU_PAGE_SIZE);
+ OSMemSet(pui32PT, 0, SGX_MMU_PAGE_SIZE);
+
+
+ PDUMPMALLOCPAGETABLE(&psDeviceNode->sDevId, hPDPageOSMemHandle, ui32PDOffset, pui32PD, SGX_MMU_PAGE_SIZE, 0, PDUMP_PD_UNIQUETAG);
+ PDUMPMALLOCPAGETABLE(&psDeviceNode->sDevId, hPTPageOSMemHandle, ui32PTOffset, pui32PT, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
+ PDUMPMEMPTENTRIES(&psDevInfo->sMMUAttrib, hPDPageOSMemHandle, pui32PD, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ PDUMPMEMPTENTRIES(&psDevInfo->sMMUAttrib, hPTPageOSMemHandle, pui32PT, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PD_UNIQUETAG);
+
+ psDevInfo->hBRN22997PTPageOSMemHandle = hPTPageOSMemHandle;
+ psDevInfo->hBRN22997PDPageOSMemHandle = hPDPageOSMemHandle;
+ psDevInfo->sBRN22997PTDevPAddr = sPTDevPAddr;
+ psDevInfo->sBRN22997PDDevPAddr = sPDDevPAddr;
+ psDevInfo->pui32BRN22997PD = pui32PD;
+ psDevInfo->pui32BRN22997PT = pui32PT;
+
+ return PVRSRV_OK;
+}
+
+
+IMG_VOID WorkaroundBRN22997ReadHostPort(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ IMG_UINT32 *pui32PD = psDevInfo->pui32BRN22997PD;
+ IMG_UINT32 *pui32PT = psDevInfo->pui32BRN22997PT;
+ IMG_UINT32 ui32PDIndex;
+ IMG_UINT32 ui32PTIndex;
+ IMG_DEV_VIRTADDR sDevVAddr;
+ volatile IMG_UINT32 *pui32HostPort;
+ IMG_UINT32 ui32BIFCtrl;
+
+
+
+
+ pui32HostPort = (volatile IMG_UINT32*)(((IMG_UINT8*)psDevInfo->pvHostPortBaseKM) + SYS_SGX_HOSTPORT_BRN23030_OFFSET);
+
+
+ sDevVAddr.uiAddr = SYS_SGX_HOSTPORT_BASE_DEVVADDR + SYS_SGX_HOSTPORT_BRN23030_OFFSET;
+
+ ui32PDIndex = (sDevVAddr.uiAddr & SGX_MMU_PD_MASK) >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
+ ui32PTIndex = (sDevVAddr.uiAddr & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
+
+
+ pui32PD[ui32PDIndex] = (psDevInfo->sBRN22997PTDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PDE_VALID;
+
+ pui32PT[ui32PTIndex] = (psDevInfo->sBRN22997PTDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PTE_VALID;
+
+ PDUMPMEMPTENTRIES(&psDevInfo->sMMUAttrib, psDevInfo->hBRN22997PDPageOSMemHandle, pui32PD, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ PDUMPMEMPTENTRIES(&psDevInfo->sMMUAttrib, psDevInfo->hBRN22997PTPageOSMemHandle, pui32PT, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PD_UNIQUETAG);
+
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0,
+ psDevInfo->sBRN22997PDDevPAddr.uiAddr);
+ PDUMPPDREG(&psDevInfo->sMMUAttrib, EUR_CR_BIF_DIR_LIST_BASE0, psDevInfo->sBRN22997PDDevPAddr.uiAddr, PDUMP_PD_UNIQUETAG);
+
+
+ ui32BIFCtrl = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_INVALDC_MASK);
+ PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_INVALDC_MASK);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl);
+ PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32BIFCtrl);
+
+
+ if (pui32HostPort)
+ {
+
+ IMG_UINT32 ui32Tmp;
+ ui32Tmp = *pui32HostPort;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,"Host Port not present for BRN22997 workaround"));
+ }
+
+
+
+
+
+
+
+ PDUMPCOMMENT("RDW :SGXMEM:v4:%08X\r\n", sDevVAddr.uiAddr);
+
+ PDUMPCOMMENT("SAB :SGXMEM:v4:%08X 4 0 hostport.bin", sDevVAddr.uiAddr);
+
+
+ pui32PD[ui32PDIndex] = 0;
+ pui32PT[ui32PTIndex] = 0;
+
+
+ PDUMPMEMPTENTRIES(&psDevInfo->sMMUAttrib, psDevInfo->hBRN22997PDPageOSMemHandle, pui32PD, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ PDUMPMEMPTENTRIES(&psDevInfo->sMMUAttrib, psDevInfo->hBRN22997PTPageOSMemHandle, pui32PT, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PD_UNIQUETAG);
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_INVALDC_MASK);
+ PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_INVALDC_MASK);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl);
+ PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32BIFCtrl);
+}
+
+
+IMG_VOID WorkaroundBRN22997Free(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ SYS_DATA *psSysData;
+ RA_ARENA *psLocalDevMemArena;
+ PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+
+
+ SysAcquireData(&psSysData);
+
+ psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
+
+ PDUMPFREEPAGETABLE(&psDeviceNode->sDevId, psDevInfo->hBRN22997PDPageOSMemHandle, psDevInfo->pui32BRN22997PD, SGX_MMU_PAGE_SIZE, 0, PDUMP_PD_UNIQUETAG);
+ PDUMPFREEPAGETABLE(&psDeviceNode->sDevId, psDevInfo->hBRN22997PTPageOSMemHandle, psDevInfo->pui32BRN22997PT, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
+
+
+ if(psLocalDevMemArena == IMG_NULL)
+ {
+ if (psDevInfo->pui32BRN22997PD != IMG_NULL)
+ {
+ OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ psDevInfo->pui32BRN22997PD,
+ psDevInfo->hBRN22997PDPageOSMemHandle);
+ }
+
+ if (psDevInfo->pui32BRN22997PT != IMG_NULL)
+ {
+ OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ psDevInfo->pui32BRN22997PT,
+ psDevInfo->hBRN22997PTPageOSMemHandle);
+ }
+ }
+ else
+ {
+ if (psDevInfo->pui32BRN22997PT != IMG_NULL)
+ {
+ OSUnMapPhysToLin(psDevInfo->pui32BRN22997PT,
+ SGX_MMU_PAGE_SIZE * 2,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ psDevInfo->hBRN22997PTPageOSMemHandle);
+
+
+ RA_Free(psLocalDevMemArena, psDevInfo->sBRN22997SysPAddr.uiAddr, IMG_FALSE);
+ }
+ }
+}
+#endif
+
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+PVRSRV_ERROR MMU_MapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ IMG_UINT32 *pui32PT;
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+ IMG_UINT32 ui32PDIndex;
+ IMG_UINT32 ui32PTIndex;
+ PDUMP_MMU_ATTRIB sMMUAttrib;
+
+ psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+
+ sMMUAttrib = psDevInfo->sMMUAttrib;
+#if defined(PDUMP)
+ MMU_SetPDumpAttribs(&sMMUAttrib, psDeviceNode,
+ SGX_MMU_PAGE_MASK,
+ SGX_MMU_PT_SIZE * sizeof(IMG_UINT32));
+#endif
+
+#if defined(PDUMP)
+ {
+ IMG_CHAR szScript[128];
+
+ sprintf(szScript, "MALLOC :EXTSYSCACHE:PA_%08X%08X %u %u 0x%08X\r\n", 0, psDevInfo->sExtSysCacheRegsDevPBase.uiAddr, SGX_MMU_PAGE_SIZE, SGX_MMU_PAGE_SIZE, psDevInfo->sExtSysCacheRegsDevPBase.uiAddr);
+ PDumpOSWriteString2(szScript, PDUMP_FLAGS_CONTINUOUS);
+ }
+#endif
+
+ ui32PDIndex = (SGX_EXT_SYSTEM_CACHE_REGS_DEVVADDR_BASE & SGX_MMU_PD_MASK) >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
+ ui32PTIndex = (SGX_EXT_SYSTEM_CACHE_REGS_DEVVADDR_BASE & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
+
+ pui32PT = (IMG_UINT32 *) psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->apsPTInfoList[ui32PDIndex]->PTPageCpuVAddr;
+
+ MakeKernelPageReadWrite(pui32PT);
+
+ pui32PT[ui32PTIndex] = (psDevInfo->sExtSysCacheRegsDevPBase.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PTE_VALID;
+ MakeKernelPageReadOnly(pui32PT);
+#if defined(PDUMP)
+
+ {
+ IMG_DEV_PHYADDR sDevPAddr;
+ IMG_CPU_PHYADDR sCpuPAddr;
+ IMG_UINT32 ui32PageMask;
+ IMG_UINT32 ui32PTE;
+ PVRSRV_ERROR eErr;
+
+ PDUMP_GET_SCRIPT_AND_FILE_STRING();
+
+ ui32PageMask = sMMUAttrib.ui32PTSize - 1;
+ sCpuPAddr = OSMapLinToCPUPhys(psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->apsPTInfoList[ui32PDIndex]->hPTPageOSMemHandle, &pui32PT[ui32PTIndex]);
+ sDevPAddr = SysCpuPAddrToDevPAddr(sMMUAttrib.sDevId.eDeviceType, sCpuPAddr);
+ ui32PTE = *((IMG_UINT32 *) (&pui32PT[ui32PTIndex]));
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "WRW :%s:PA_%08X%08X:0x%08X :%s:PA_%08X%08X:0x%08X\r\n",
+ sMMUAttrib.sDevId.pszPDumpDevName,
+ (IMG_UINT32)(IMG_UINTPTR_T)PDUMP_PT_UNIQUETAG,
+ (sDevPAddr.uiAddr) & ~ui32PageMask,
+ (sDevPAddr.uiAddr) & ui32PageMask,
+ "EXTSYSCACHE",
+ (IMG_UINT32)(IMG_UINTPTR_T)PDUMP_PD_UNIQUETAG,
+ (ui32PTE & sMMUAttrib.ui32PDEMask) << sMMUAttrib.ui32PTEAlignShift,
+ ui32PTE & ~sMMUAttrib.ui32PDEMask);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+ }
+#endif
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR MMU_UnmapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ SYS_DATA *psSysData;
+ RA_ARENA *psLocalDevMemArena;
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+ IMG_UINT32 ui32PDIndex;
+ IMG_UINT32 ui32PTIndex;
+ IMG_UINT32 *pui32PT;
+ PDUMP_MMU_ATTRIB sMMUAttrib;
+
+ psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+
+ sMMUAttrib = psDevInfo->sMMUAttrib;
+
+#if defined(PDUMP)
+ MMU_SetPDumpAttribs(&sMMUAttrib, psDeviceNode,
+ SGX_MMU_PAGE_MASK,
+ SGX_MMU_PT_SIZE * sizeof(IMG_UINT32));
+#endif
+ SysAcquireData(&psSysData);
+
+ psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
+
+
+ ui32PDIndex = (SGX_EXT_SYSTEM_CACHE_REGS_DEVVADDR_BASE & SGX_MMU_PD_MASK) >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
+ ui32PTIndex = (SGX_EXT_SYSTEM_CACHE_REGS_DEVVADDR_BASE & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
+
+
+ if (psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->apsPTInfoList[ui32PDIndex])
+ {
+ if (psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->apsPTInfoList[ui32PDIndex]->PTPageCpuVAddr)
+ {
+ pui32PT = (IMG_UINT32 *) psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->apsPTInfoList[ui32PDIndex]->PTPageCpuVAddr;
+ }
+ }
+
+ MakeKernelPageReadWrite(pui32PT);
+ pui32PT[ui32PTIndex] = 0;
+ MakeKernelPageReadOnly(pui32PT);
+
+ PDUMPMEMPTENTRIES(&sMMUAttrib, psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->hPDOSMemHandle, &pui32PT[ui32PTIndex], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+
+ return PVRSRV_OK;
+}
+#endif
+
+
+#if PAGE_TEST
+static IMG_VOID PageTest(IMG_VOID* pMem, IMG_DEV_PHYADDR sDevPAddr)
+{
+ volatile IMG_UINT32 ui32WriteData;
+ volatile IMG_UINT32 ui32ReadData;
+ volatile IMG_UINT32 *pMem32 = (volatile IMG_UINT32 *)pMem;
+ IMG_INT n;
+ IMG_BOOL bOK=IMG_TRUE;
+
+ ui32WriteData = 0xffffffff;
+
+ for (n=0; n<1024; n++)
+ {
+ pMem32[n] = ui32WriteData;
+ ui32ReadData = pMem32[n];
+
+ if (ui32WriteData != ui32ReadData)
+ {
+
+ PVR_DPF ((PVR_DBG_ERROR, "Error - memory page test failed at device phys address 0x%08X", sDevPAddr.uiAddr + (n<<2) ));
+ PVR_DBG_BREAK;
+ bOK = IMG_FALSE;
+ }
+ }
+
+ ui32WriteData = 0;
+
+ for (n=0; n<1024; n++)
+ {
+ pMem32[n] = ui32WriteData;
+ ui32ReadData = pMem32[n];
+
+ if (ui32WriteData != ui32ReadData)
+ {
+
+ PVR_DPF ((PVR_DBG_ERROR, "Error - memory page test failed at device phys address 0x%08X", sDevPAddr.uiAddr + (n<<2) ));
+ PVR_DBG_BREAK;
+ bOK = IMG_FALSE;
+ }
+ }
+
+ if (bOK)
+ {
+ PVR_DPF ((PVR_DBG_VERBOSE, "MMU Page 0x%08X is OK", sDevPAddr.uiAddr));
+ }
+ else
+ {
+ PVR_DPF ((PVR_DBG_VERBOSE, "MMU Page 0x%08X *** FAILED ***", sDevPAddr.uiAddr));
+ }
+}
+#endif
+
diff --git a/drivers/gpu/pvr/sgx/mmu.h b/drivers/gpu/pvr/sgx/mmu.h
new file mode 100644
index 0000000..dd92bf0
--- /dev/null
+++ b/drivers/gpu/pvr/sgx/mmu.h
@@ -0,0 +1,156 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef _MMU_H_
+#define _MMU_H_
+
+#include "sgxinfokm.h"
+
+PVRSRV_ERROR
+MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, IMG_DEV_PHYADDR *psPDDevPAddr);
+
+IMG_VOID
+MMU_Finalise (MMU_CONTEXT *psMMUContext);
+
+
+IMG_VOID
+MMU_InsertHeap(MMU_CONTEXT *psMMUContext, MMU_HEAP *psMMUHeap);
+
+MMU_HEAP *
+MMU_Create (MMU_CONTEXT *psMMUContext,
+ DEV_ARENA_DESCRIPTOR *psDevArena,
+ RA_ARENA **ppsVMArena,
+ PDUMP_MMU_ATTRIB **ppsMMUAttrib);
+
+IMG_VOID
+MMU_Delete (MMU_HEAP *pMMUHeap);
+
+IMG_BOOL
+MMU_Alloc (MMU_HEAP *pMMUHeap,
+ IMG_SIZE_T uSize,
+ IMG_SIZE_T *pActualSize,
+ IMG_UINT32 uFlags,
+ IMG_UINT32 uDevVAddrAlignment,
+ IMG_DEV_VIRTADDR *pDevVAddr);
+
+IMG_VOID
+MMU_Free (MMU_HEAP *pMMUHeap,
+ IMG_DEV_VIRTADDR DevVAddr,
+ IMG_UINT32 ui32Size);
+
+IMG_VOID
+MMU_Enable (MMU_HEAP *pMMUHeap);
+
+IMG_VOID
+MMU_Disable (MMU_HEAP *pMMUHeap);
+
+IMG_VOID
+MMU_MapPages (MMU_HEAP *pMMUHeap,
+ IMG_DEV_VIRTADDR DevVAddr,
+ IMG_SYS_PHYADDR SysPAddr,
+ IMG_SIZE_T uSize,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag);
+
+IMG_VOID
+MMU_MapShadow (MMU_HEAP * pMMUHeap,
+ IMG_DEV_VIRTADDR MapBaseDevVAddr,
+ IMG_SIZE_T uByteSize,
+ IMG_CPU_VIRTADDR CpuVAddr,
+ IMG_HANDLE hOSMemHandle,
+ IMG_DEV_VIRTADDR * pDevVAddr,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag);
+
+IMG_VOID
+MMU_UnmapPages (MMU_HEAP *psMMUHeap,
+ IMG_DEV_VIRTADDR sDevVAddr,
+ IMG_UINT32 ui32PageCount,
+ IMG_HANDLE hUniqueTag);
+
+IMG_VOID
+MMU_MapScatter (MMU_HEAP *pMMUHeap,
+ IMG_DEV_VIRTADDR DevVAddr,
+ IMG_SYS_PHYADDR *psSysAddr,
+ IMG_SIZE_T uSize,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag);
+
+
+IMG_DEV_PHYADDR
+MMU_GetPhysPageAddr(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR sDevVPageAddr);
+
+
+IMG_DEV_PHYADDR
+MMU_GetPDDevPAddr(MMU_CONTEXT *pMMUContext);
+
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+IMG_VOID
+EnableHostAccess (MMU_CONTEXT *psMMUContext);
+
+
+IMG_VOID
+DisableHostAccess (MMU_CONTEXT *psMMUContext);
+#endif
+
+IMG_VOID MMU_InvalidateDirectoryCache(PVRSRV_SGXDEV_INFO *psDevInfo);
+
+PVRSRV_ERROR MMU_BIFResetPDAlloc(PVRSRV_SGXDEV_INFO *psDevInfo);
+
+IMG_VOID MMU_BIFResetPDFree(PVRSRV_SGXDEV_INFO *psDevInfo);
+
+#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
+PVRSRV_ERROR WorkaroundBRN22997Alloc(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_VOID WorkaroundBRN22997ReadHostPort(PVRSRV_SGXDEV_INFO *psDevInfo);
+
+IMG_VOID WorkaroundBRN22997Free(PVRSRV_DEVICE_NODE *psDeviceNode);
+#endif
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+PVRSRV_ERROR MMU_MapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+PVRSRV_ERROR MMU_UnmapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode);
+#endif
+
+IMG_BOOL MMU_IsHeapShared(MMU_HEAP* pMMU_Heap);
+
+#if defined(FIX_HW_BRN_31620)
+IMG_VOID MMU_GetCacheFlushRange(MMU_CONTEXT *pMMUContext, IMG_UINT32 *pui32RangeMask);
+
+IMG_VOID MMU_GetPDPhysAddr(MMU_CONTEXT *pMMUContext, IMG_DEV_PHYADDR *psDevPAddr);
+
+#endif
+
+
+IMG_VOID MMU_CheckFaultAddr(PVRSRV_SGXDEV_INFO *psDevInfo, IMG_UINT32 ui32PDDevPAddr, IMG_UINT32 ui32RegVal);
+
+#if defined(PDUMP)
+IMG_UINT32 MMU_GetPDumpContextID(IMG_HANDLE hDevMemContext);
+#endif
+
+#endif
diff --git a/drivers/gpu/pvr/sgx/pb.c b/drivers/gpu/pvr/sgx/pb.c
new file mode 100644
index 0000000..ab6523a
--- /dev/null
+++ b/drivers/gpu/pvr/sgx/pb.c
@@ -0,0 +1,466 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include <stddef.h>
+
+#include "services_headers.h"
+#include "sgx_bridge_km.h"
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+#include "pvr_bridge_km.h"
+#include "pdump_km.h"
+#include "sgxutils.h"
+
+#ifndef __linux__
+#pragma message("TODO: Review use of OS_PAGEABLE vs OS_NON_PAGEABLE")
+#endif
+
+#include "lists.h"
+
+static IMPLEMENT_LIST_INSERT(PVRSRV_STUB_PBDESC)
+static IMPLEMENT_LIST_REMOVE(PVRSRV_STUB_PBDESC)
+
+static PRESMAN_ITEM psResItemCreateSharedPB = IMG_NULL;
+static PVRSRV_PER_PROCESS_DATA *psPerProcCreateSharedPB = IMG_NULL;
+
+static PVRSRV_ERROR SGXCleanupSharedPBDescCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param, IMG_BOOL bDummy);
+static PVRSRV_ERROR SGXCleanupSharedPBDescCreateLockCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param, IMG_BOOL bDummy);
+
+IMG_EXPORT PVRSRV_ERROR
+SGXFindSharedPBDescKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevCookie,
+ IMG_BOOL bLockOnFailure,
+ IMG_UINT32 ui32TotalPBSize,
+ IMG_HANDLE *phSharedPBDesc,
+ PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO **ppsHWPBDescKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO **ppsBlockKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO **ppsHWBlockKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO ***pppsSharedPBDescSubKernelMemInfos,
+ IMG_UINT32 *ui32SharedPBDescSubKernelMemInfosCount)
+{
+ PVRSRV_STUB_PBDESC *psStubPBDesc;
+ PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescSubKernelMemInfos=IMG_NULL;
+ PVRSRV_SGXDEV_INFO *psSGXDevInfo;
+ PVRSRV_ERROR eError;
+
+ psSGXDevInfo = ((PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
+
+ psStubPBDesc = psSGXDevInfo->psStubPBDescListKM;
+ if (psStubPBDesc != IMG_NULL)
+ {
+ IMG_UINT32 i;
+ PRESMAN_ITEM psResItem;
+
+ if(psStubPBDesc->ui32TotalPBSize != ui32TotalPBSize)
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "SGXFindSharedPBDescKM: Shared PB requested with different size (0x%x) from existing shared PB (0x%x) - requested size ignored",
+ ui32TotalPBSize, psStubPBDesc->ui32TotalPBSize));
+ }
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO *)
+ * psStubPBDesc->ui32SubKernelMemInfosCount,
+ (IMG_VOID **)&ppsSharedPBDescSubKernelMemInfos,
+ IMG_NULL,
+ "Array of Kernel Memory Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXFindSharedPBDescKM: OSAllocMem failed"));
+
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ExitNotFound;
+ }
+
+ psResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_SHARED_PB_DESC,
+ psStubPBDesc,
+ 0,
+ &SGXCleanupSharedPBDescCallback);
+
+ if (psResItem == IMG_NULL)
+ {
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO *) * psStubPBDesc->ui32SubKernelMemInfosCount,
+ ppsSharedPBDescSubKernelMemInfos,
+ 0);
+
+
+ PVR_DPF((PVR_DBG_ERROR, "SGXFindSharedPBDescKM: ResManRegisterRes failed"));
+
+ eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto ExitNotFound;
+ }
+
+ *ppsSharedPBDescKernelMemInfo = psStubPBDesc->psSharedPBDescKernelMemInfo;
+ *ppsHWPBDescKernelMemInfo = psStubPBDesc->psHWPBDescKernelMemInfo;
+ *ppsBlockKernelMemInfo = psStubPBDesc->psBlockKernelMemInfo;
+ *ppsHWBlockKernelMemInfo = psStubPBDesc->psHWBlockKernelMemInfo;
+
+ *ui32SharedPBDescSubKernelMemInfosCount =
+ psStubPBDesc->ui32SubKernelMemInfosCount;
+
+ *pppsSharedPBDescSubKernelMemInfos = ppsSharedPBDescSubKernelMemInfos;
+
+ for(i=0; i<psStubPBDesc->ui32SubKernelMemInfosCount; i++)
+ {
+ ppsSharedPBDescSubKernelMemInfos[i] =
+ psStubPBDesc->ppsSubKernelMemInfos[i];
+ }
+
+ psStubPBDesc->ui32RefCount++;
+ *phSharedPBDesc = (IMG_HANDLE)psResItem;
+ return PVRSRV_OK;
+ }
+
+ eError = PVRSRV_OK;
+ if (bLockOnFailure)
+ {
+ if (psResItemCreateSharedPB == IMG_NULL)
+ {
+ psResItemCreateSharedPB = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_SHARED_PB_DESC_CREATE_LOCK,
+ psPerProc,
+ 0,
+ &SGXCleanupSharedPBDescCreateLockCallback);
+
+ if (psResItemCreateSharedPB == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXFindSharedPBDescKM: ResManRegisterRes failed"));
+
+ eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto ExitNotFound;
+ }
+ PVR_ASSERT(psPerProcCreateSharedPB == IMG_NULL);
+ psPerProcCreateSharedPB = psPerProc;
+ }
+ else
+ {
+ eError = PVRSRV_ERROR_PROCESSING_BLOCKED;
+ }
+ }
+ExitNotFound:
+ *phSharedPBDesc = IMG_NULL;
+
+ return eError;
+}
+
+
+static PVRSRV_ERROR
+SGXCleanupSharedPBDescKM(PVRSRV_STUB_PBDESC *psStubPBDescIn)
+{
+
+ IMG_UINT32 i;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE*)psStubPBDescIn->hDevCookie;
+
+
+
+
+ psStubPBDescIn->ui32RefCount--;
+ if (psStubPBDescIn->ui32RefCount == 0)
+ {
+ IMG_DEV_VIRTADDR sHWPBDescDevVAddr = psStubPBDescIn->sHWPBDescDevVAddr;
+ List_PVRSRV_STUB_PBDESC_Remove(psStubPBDescIn);
+ for(i=0 ; i<psStubPBDescIn->ui32SubKernelMemInfosCount; i++)
+ {
+
+ PVRSRVFreeDeviceMemKM(psStubPBDescIn->hDevCookie,
+ psStubPBDescIn->ppsSubKernelMemInfos[i]);
+ }
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO *) * psStubPBDescIn->ui32SubKernelMemInfosCount,
+ psStubPBDescIn->ppsSubKernelMemInfos,
+ 0);
+ psStubPBDescIn->ppsSubKernelMemInfos = IMG_NULL;
+
+ PVRSRVFreeSharedSysMemoryKM(psStubPBDescIn->psBlockKernelMemInfo);
+
+ PVRSRVFreeDeviceMemKM(psStubPBDescIn->hDevCookie, psStubPBDescIn->psHWBlockKernelMemInfo);
+
+ PVRSRVFreeDeviceMemKM(psStubPBDescIn->hDevCookie, psStubPBDescIn->psHWPBDescKernelMemInfo);
+
+ PVRSRVFreeSharedSysMemoryKM(psStubPBDescIn->psSharedPBDescKernelMemInfo);
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_STUB_PBDESC),
+ psStubPBDescIn,
+ 0);
+
+
+
+ SGXCleanupRequest(psDeviceNode,
+ &sHWPBDescDevVAddr,
+ PVRSRV_CLEANUPCMD_PB,
+ CLEANUP_WITH_POLL);
+ }
+ return PVRSRV_OK;
+
+}
+
+static PVRSRV_ERROR SGXCleanupSharedPBDescCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param, IMG_BOOL bDummy)
+{
+ PVRSRV_STUB_PBDESC *psStubPBDesc = (PVRSRV_STUB_PBDESC *)pvParam;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+ PVR_UNREFERENCED_PARAMETER(bDummy);
+
+ return SGXCleanupSharedPBDescKM(psStubPBDesc);
+}
+
+static PVRSRV_ERROR SGXCleanupSharedPBDescCreateLockCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param, IMG_BOOL bDummy)
+{
+#ifdef DEBUG
+ PVRSRV_PER_PROCESS_DATA *psPerProc = (PVRSRV_PER_PROCESS_DATA *)pvParam;
+ PVR_ASSERT(psPerProc == psPerProcCreateSharedPB);
+#else
+ PVR_UNREFERENCED_PARAMETER(pvParam);
+#endif
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+ PVR_UNREFERENCED_PARAMETER(bDummy);
+
+ psPerProcCreateSharedPB = IMG_NULL;
+ psResItemCreateSharedPB = IMG_NULL;
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT PVRSRV_ERROR
+SGXUnrefSharedPBDescKM(IMG_HANDLE hSharedPBDesc)
+{
+ PVR_ASSERT(hSharedPBDesc != IMG_NULL);
+
+ return ResManFreeResByPtr(hSharedPBDesc, CLEANUP_WITH_POLL);
+}
+
+
+IMG_EXPORT PVRSRV_ERROR
+SGXAddSharedPBDescKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevCookie,
+ PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO *psHWBlockKernelMemInfo,
+ IMG_UINT32 ui32TotalPBSize,
+ IMG_HANDLE *phSharedPBDesc,
+ PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescSubKernelMemInfos,
+ IMG_UINT32 ui32SharedPBDescSubKernelMemInfosCount,
+ IMG_DEV_VIRTADDR sHWPBDescDevVAddr)
+{
+ PVRSRV_STUB_PBDESC *psStubPBDesc=IMG_NULL;
+ PVRSRV_ERROR eRet = PVRSRV_ERROR_INVALID_PERPROC;
+ IMG_UINT32 i;
+ PVRSRV_SGXDEV_INFO *psSGXDevInfo;
+ PRESMAN_ITEM psResItem;
+
+
+ if (psPerProcCreateSharedPB != psPerProc)
+ {
+ goto NoAdd;
+ }
+ else
+ {
+ PVR_ASSERT(psResItemCreateSharedPB != IMG_NULL);
+
+ ResManFreeResByPtr(psResItemCreateSharedPB, CLEANUP_WITH_POLL);
+
+ PVR_ASSERT(psResItemCreateSharedPB == IMG_NULL);
+ PVR_ASSERT(psPerProcCreateSharedPB == IMG_NULL);
+ }
+
+ psSGXDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
+
+ psStubPBDesc = psSGXDevInfo->psStubPBDescListKM;
+ if (psStubPBDesc != IMG_NULL)
+ {
+ if(psStubPBDesc->ui32TotalPBSize != ui32TotalPBSize)
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "SGXAddSharedPBDescKM: Shared PB requested with different size (0x%x) from existing shared PB (0x%x) - requested size ignored",
+ ui32TotalPBSize, psStubPBDesc->ui32TotalPBSize));
+
+ }
+
+
+ psResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_SHARED_PB_DESC,
+ psStubPBDesc,
+ 0,
+ &SGXCleanupSharedPBDescCallback);
+ if (psResItem == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "SGXAddSharedPBDescKM: "
+ "Failed to register existing shared "
+ "PBDesc with the resource manager"));
+ goto NoAddKeepPB;
+ }
+
+
+ psStubPBDesc->ui32RefCount++;
+
+ *phSharedPBDesc = (IMG_HANDLE)psResItem;
+ eRet = PVRSRV_OK;
+ goto NoAddKeepPB;
+ }
+
+ if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_STUB_PBDESC),
+ (IMG_VOID **)&psStubPBDesc,
+ 0,
+ "Stub Parameter Buffer Description") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: Failed to alloc "
+ "StubPBDesc"));
+ eRet = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto NoAdd;
+ }
+
+
+ psStubPBDesc->ppsSubKernelMemInfos = IMG_NULL;
+
+ if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO *)
+ * ui32SharedPBDescSubKernelMemInfosCount,
+ (IMG_VOID **)&psStubPBDesc->ppsSubKernelMemInfos,
+ 0,
+ "Array of Kernel Memory Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: "
+ "Failed to alloc "
+ "StubPBDesc->ppsSubKernelMemInfos"));
+ eRet = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto NoAdd;
+ }
+
+ if(PVRSRVDissociateMemFromResmanKM(psSharedPBDescKernelMemInfo)
+ != PVRSRV_OK)
+ {
+ goto NoAdd;
+ }
+
+ if(PVRSRVDissociateMemFromResmanKM(psHWPBDescKernelMemInfo)
+ != PVRSRV_OK)
+ {
+ goto NoAdd;
+ }
+
+ if(PVRSRVDissociateMemFromResmanKM(psBlockKernelMemInfo)
+ != PVRSRV_OK)
+ {
+ goto NoAdd;
+ }
+
+ if(PVRSRVDissociateMemFromResmanKM(psHWBlockKernelMemInfo)
+ != PVRSRV_OK)
+ {
+ goto NoAdd;
+ }
+
+ psStubPBDesc->ui32RefCount = 1;
+ psStubPBDesc->ui32TotalPBSize = ui32TotalPBSize;
+ psStubPBDesc->psSharedPBDescKernelMemInfo = psSharedPBDescKernelMemInfo;
+ psStubPBDesc->psHWPBDescKernelMemInfo = psHWPBDescKernelMemInfo;
+ psStubPBDesc->psBlockKernelMemInfo = psBlockKernelMemInfo;
+ psStubPBDesc->psHWBlockKernelMemInfo = psHWBlockKernelMemInfo;
+
+ psStubPBDesc->ui32SubKernelMemInfosCount =
+ ui32SharedPBDescSubKernelMemInfosCount;
+ for(i=0; i<ui32SharedPBDescSubKernelMemInfosCount; i++)
+ {
+ psStubPBDesc->ppsSubKernelMemInfos[i] = ppsSharedPBDescSubKernelMemInfos[i];
+ if(PVRSRVDissociateMemFromResmanKM(ppsSharedPBDescSubKernelMemInfos[i])
+ != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: "
+ "Failed to dissociate shared PBDesc "
+ "from process"));
+ goto NoAdd;
+ }
+ }
+
+ psStubPBDesc->sHWPBDescDevVAddr = sHWPBDescDevVAddr;
+
+ psResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_SHARED_PB_DESC,
+ psStubPBDesc,
+ 0,
+ &SGXCleanupSharedPBDescCallback);
+ if (psResItem == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: "
+ "Failed to register shared PBDesc "
+ " with the resource manager"));
+ goto NoAdd;
+ }
+ psStubPBDesc->hDevCookie = hDevCookie;
+
+
+ List_PVRSRV_STUB_PBDESC_Insert(&(psSGXDevInfo->psStubPBDescListKM),
+ psStubPBDesc);
+
+ *phSharedPBDesc = (IMG_HANDLE)psResItem;
+
+ return PVRSRV_OK;
+
+NoAdd:
+ if(psStubPBDesc)
+ {
+ if(psStubPBDesc->ppsSubKernelMemInfos)
+ {
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO *) * ui32SharedPBDescSubKernelMemInfosCount,
+ psStubPBDesc->ppsSubKernelMemInfos,
+ 0);
+ psStubPBDesc->ppsSubKernelMemInfos = IMG_NULL;
+ }
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_STUB_PBDESC),
+ psStubPBDesc,
+ 0);
+
+ }
+
+NoAddKeepPB:
+ for (i = 0; i < ui32SharedPBDescSubKernelMemInfosCount; i++)
+ {
+ PVRSRVFreeDeviceMemKM(hDevCookie, ppsSharedPBDescSubKernelMemInfos[i]);
+ }
+
+ PVRSRVFreeSharedSysMemoryKM(psSharedPBDescKernelMemInfo);
+ PVRSRVFreeDeviceMemKM(hDevCookie, psHWPBDescKernelMemInfo);
+
+ PVRSRVFreeSharedSysMemoryKM(psBlockKernelMemInfo);
+ PVRSRVFreeDeviceMemKM(hDevCookie, psHWBlockKernelMemInfo);
+
+ return eRet;
+}
+
diff --git a/drivers/gpu/pvr/sgx/sgx_bridge_km.h b/drivers/gpu/pvr/sgx/sgx_bridge_km.h
new file mode 100644
index 0000000..8fb3002
--- /dev/null
+++ b/drivers/gpu/pvr/sgx/sgx_bridge_km.h
@@ -0,0 +1,160 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#if !defined(__SGX_BRIDGE_KM_H__)
+#define __SGX_BRIDGE_KM_H__
+
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+#include "sgx_bridge.h"
+#include "pvr_bridge.h"
+#include "perproc.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+IMG_IMPORT
+#if defined (SUPPORT_SID_INTERFACE)
+PVRSRV_ERROR SGXSubmitTransferKM(IMG_HANDLE hDevHandle, PVRSRV_TRANSFER_SGX_KICK_KM *psKick);
+#else
+PVRSRV_ERROR SGXSubmitTransferKM(IMG_HANDLE hDevHandle, PVRSRV_TRANSFER_SGX_KICK *psKick);
+#endif
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+IMG_IMPORT
+#if defined (SUPPORT_SID_INTERFACE)
+PVRSRV_ERROR SGXSubmit2DKM(IMG_HANDLE hDevHandle, PVRSRV_2D_SGX_KICK_KM *psKick);
+#else
+PVRSRV_ERROR SGXSubmit2DKM(IMG_HANDLE hDevHandle, PVRSRV_2D_SGX_KICK *psKick);
+#endif
+#endif
+
+IMG_IMPORT
+PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle,
+#if defined (SUPPORT_SID_INTERFACE)
+ SGX_CCB_KICK_KM *psCCBKick);
+#else
+ SGX_CCB_KICK *psCCBKick);
+#endif
+
+IMG_IMPORT
+PVRSRV_ERROR SGXGetPhysPageAddrKM(IMG_HANDLE hDevMemHeap,
+ IMG_DEV_VIRTADDR sDevVAddr,
+ IMG_DEV_PHYADDR *pDevPAddr,
+ IMG_CPU_PHYADDR *pCpuPAddr);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV SGXGetMMUPDAddrKM(IMG_HANDLE hDevCookie,
+ IMG_HANDLE hDevMemContext,
+ IMG_DEV_PHYADDR *psPDDevPAddr);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXGetClientInfoKM(IMG_HANDLE hDevCookie,
+ SGX_CLIENT_INFO* psClientInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
+ SGX_MISC_INFO *psMiscInfo,
+ PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_HANDLE hDevMemContext);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXReadHWPerfCBKM(IMG_HANDLE hDevHandle,
+ IMG_UINT32 ui32ArraySize,
+ PVRSRV_SGX_HWPERF_CB_ENTRY *psHWPerfCBData,
+ IMG_UINT32 *pui32DataCount,
+ IMG_UINT32 *pui32ClockSpeed,
+ IMG_UINT32 *pui32HostTimeStamp);
+
+IMG_IMPORT
+PVRSRV_ERROR SGX2DQueryBlitsCompleteKM(PVRSRV_SGXDEV_INFO *psDevInfo,
+ PVRSRV_KERNEL_SYNC_INFO *psSyncInfo,
+ IMG_BOOL bWaitForComplete);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXGetInfoForSrvinitKM(IMG_HANDLE hDevHandle,
+#if defined (SUPPORT_SID_INTERFACE)
+ PVRSRV_HEAP_INFO_KM *pasHeapInfo,
+ IMG_DEV_PHYADDR *psPDDevPAddr);
+#else
+ SGX_BRIDGE_INFO_FOR_SRVINIT *psInitInfo);
+#endif
+
+IMG_IMPORT
+PVRSRV_ERROR DevInitSGXPart2KM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevHandle,
+#if defined (SUPPORT_SID_INTERFACE)
+ SGX_BRIDGE_INIT_INFO_KM *psInitInfo);
+#else
+ SGX_BRIDGE_INIT_INFO *psInitInfo);
+#endif
+
+IMG_IMPORT PVRSRV_ERROR
+SGXFindSharedPBDescKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevCookie,
+ IMG_BOOL bLockOnFailure,
+ IMG_UINT32 ui32TotalPBSize,
+ IMG_HANDLE *phSharedPBDesc,
+ PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO **ppsHWPBDescKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO **ppsBlockKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO **ppsHWBlockKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO ***pppsSharedPBDescSubKernelMemInfos,
+ IMG_UINT32 *ui32SharedPBDescSubKernelMemInfosCount);
+
+IMG_IMPORT PVRSRV_ERROR
+SGXUnrefSharedPBDescKM(IMG_HANDLE hSharedPBDesc);
+
+IMG_IMPORT PVRSRV_ERROR
+SGXAddSharedPBDescKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevCookie,
+ PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO *psHWBlockKernelMemInfo,
+ IMG_UINT32 ui32TotalPBSize,
+ IMG_HANDLE *phSharedPBDesc,
+ PVRSRV_KERNEL_MEM_INFO **psSharedPBDescSubKernelMemInfos,
+ IMG_UINT32 ui32SharedPBDescSubKernelMemInfosCount,
+ IMG_DEV_VIRTADDR sHWPBDescDevVAddr);
+
+
+IMG_IMPORT PVRSRV_ERROR
+SGXGetInternalDevInfoKM(IMG_HANDLE hDevCookie,
+#if defined (SUPPORT_SID_INTERFACE)
+ SGX_INTERNAL_DEVINFO_KM *psSGXInternalDevInfo);
+#else
+ SGX_INTERNAL_DEVINFO *psSGXInternalDevInfo);
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/pvr/sgx/sgxconfig.h b/drivers/gpu/pvr/sgx/sgxconfig.h
new file mode 100644
index 0000000..c5cb093
--- /dev/null
+++ b/drivers/gpu/pvr/sgx/sgxconfig.h
@@ -0,0 +1,401 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __SGXCONFIG_H__
+#define __SGXCONFIG_H__
+
+#include "sgxdefs.h"
+
+#define DEV_DEVICE_TYPE PVRSRV_DEVICE_TYPE_SGX
+#define DEV_DEVICE_CLASS PVRSRV_DEVICE_CLASS_3D
+
+#define DEV_MAJOR_VERSION 1
+#define DEV_MINOR_VERSION 0
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+#define SGX_KERNEL_DATA_HEAP_OFFSET 0x00001000
+#else
+#define SGX_KERNEL_DATA_HEAP_OFFSET 0x00000000
+#endif
+
+#if SGX_FEATURE_ADDRESS_SPACE_SIZE == 32
+#if defined(FIX_HW_BRN_31620)
+ #if defined(SGX_FEATURE_2D_HARDWARE)
+ #define SGX_2D_HEAP_BASE 0x04000000
+ #define SGX_2D_HEAP_SIZE (0x08000000-0x04000000-0x00001000)
+ #endif
+
+ #define SGX_GENERAL_HEAP_BASE 0x08000000
+ #define SGX_GENERAL_HEAP_SIZE (0xB8000000-0x00001000)
+
+
+ #define SGX_3DPARAMETERS_HEAP_SIZE 0x10000000
+
+
+#if !defined(HYBRID_SHARED_PB_SIZE)
+ #define HYBRID_SHARED_PB_SIZE (SGX_3DPARAMETERS_HEAP_SIZE >> 1)
+#endif
+#if defined(SUPPORT_HYBRID_PB)
+ #define SGX_SHARED_3DPARAMETERS_SIZE (HYBRID_SHARED_PB_SIZE)
+ #define SGX_SHARED_3DPARAMETERS_HEAP_SIZE (HYBRID_SHARED_PB_SIZE-0x00001000)
+ #define SGX_PERCONTEXT_3DPARAMETERS_HEAP_SIZE (SGX_3DPARAMETERS_HEAP_SIZE - SGX_SHARED_3DPARAMETERS_SIZE - 0x00001000)
+#else
+#if defined(SUPPORT_PERCONTEXT_PB)
+ #define SGX_SHARED_3DPARAMETERS_SIZE 0
+ #define SGX_SHARED_3DPARAMETERS_HEAP_SIZE 0
+ #define SGX_PERCONTEXT_3DPARAMETERS_HEAP_SIZE (SGX_3DPARAMETERS_HEAP_SIZE - 0x00001000)
+#endif
+#if defined(SUPPORT_SHARED_PB)
+ #define SGX_SHARED_3DPARAMETERS_SIZE SGX_3DPARAMETERS_HEAP_SIZE
+ #define SGX_SHARED_3DPARAMETERS_HEAP_SIZE (SGX_3DPARAMETERS_HEAP_SIZE - 0x00001000)
+ #define SGX_PERCONTEXT_3DPARAMETERS_HEAP_SIZE 0
+#endif
+#endif
+
+ #define SGX_SHARED_3DPARAMETERS_HEAP_BASE 0xC0000000
+
+
+ #define SGX_PERCONTEXT_3DPARAMETERS_HEAP_BASE (SGX_SHARED_3DPARAMETERS_HEAP_BASE + SGX_SHARED_3DPARAMETERS_SIZE)
+
+
+ #define SGX_TADATA_HEAP_BASE 0xD0000000
+ #define SGX_TADATA_HEAP_SIZE (0x0D000000-0x00001000)
+
+ #define SGX_SYNCINFO_HEAP_BASE 0xE0000000
+ #define SGX_SYNCINFO_HEAP_SIZE (0x01000000-0x00001000)
+
+ #define SGX_PDSPIXEL_CODEDATA_HEAP_BASE 0xE4000000
+ #define SGX_PDSPIXEL_CODEDATA_HEAP_SIZE (0x02000000-0x00001000)
+
+ #define SGX_KERNEL_CODE_HEAP_BASE 0xE8000000
+ #define SGX_KERNEL_CODE_HEAP_SIZE (0x00080000-0x00001000)
+
+ #define SGX_PDSVERTEX_CODEDATA_HEAP_BASE 0xEC000000
+ #define SGX_PDSVERTEX_CODEDATA_HEAP_SIZE (0x01C00000-0x00001000)
+
+ #define SGX_KERNEL_DATA_HEAP_BASE (0xF0000000+SGX_KERNEL_DATA_HEAP_OFFSET)
+ #define SGX_KERNEL_DATA_HEAP_SIZE (0x03000000-(0x00001000+SGX_KERNEL_DATA_HEAP_OFFSET))
+
+
+ #define SGX_PIXELSHADER_HEAP_BASE 0xF4000000
+ #define SGX_PIXELSHADER_HEAP_SIZE (0x05000000-0x00001000)
+
+ #define SGX_VERTEXSHADER_HEAP_BASE 0xFC000000
+ #define SGX_VERTEXSHADER_HEAP_SIZE (0x02000000-0x00001000)
+#else
+ #if defined(SGX_FEATURE_2D_HARDWARE)
+ #define SGX_2D_HEAP_BASE 0x00100000
+ #define SGX_2D_HEAP_SIZE (0x08000000-0x00100000-0x00001000)
+ #else
+ #if defined(FIX_HW_BRN_26915)
+ #define SGX_CGBUFFER_HEAP_BASE 0x00100000
+ #define SGX_CGBUFFER_HEAP_SIZE (0x08000000-0x00100000-0x00001000)
+ #endif
+ #endif
+
+ #if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+ #define SGX_GENERAL_MAPPING_HEAP_BASE 0x08000000
+ #define SGX_GENERAL_MAPPING_HEAP_SIZE (0x08000000-0x00001000)
+ #endif
+
+ #if !defined(SUPPORT_MEMORY_TILING)
+ #define SGX_GENERAL_HEAP_BASE 0x10000000
+ #define SGX_GENERAL_HEAP_SIZE (0xC2000000-0x00001000)
+ #else
+ #include <sgx_msvdx_defs.h>
+
+
+ #define SGX_GENERAL_HEAP_BASE 0x10000000
+ #define SGX_GENERAL_HEAP_SIZE (0xB5000000-0x00001000)
+
+ #define SGX_VPB_TILED_HEAP_STRIDE TILING_TILE_STRIDE_2K
+ #define SGX_VPB_TILED_HEAP_BASE 0xC5000000
+ #define SGX_VPB_TILED_HEAP_SIZE (0x0D000000-0x00001000)
+
+
+ #if((SGX_VPB_TILED_HEAP_BASE & SGX_BIF_TILING_ADDR_INV_MASK) != 0)
+ #error "sgxconfig.h: SGX_VPB_TILED_HEAP has insufficient alignment"
+ #endif
+
+ #endif
+
+
+ #define SGX_3DPARAMETERS_HEAP_SIZE 0x10000000
+
+
+#if !defined(HYBRID_SHARED_PB_SIZE)
+ #define HYBRID_SHARED_PB_SIZE (SGX_3DPARAMETERS_HEAP_SIZE >> 1)
+#endif
+#if defined(SUPPORT_HYBRID_PB)
+ #define SGX_SHARED_3DPARAMETERS_SIZE (HYBRID_SHARED_PB_SIZE)
+ #define SGX_SHARED_3DPARAMETERS_HEAP_SIZE (HYBRID_SHARED_PB_SIZE-0x00001000)
+ #define SGX_PERCONTEXT_3DPARAMETERS_HEAP_SIZE (SGX_3DPARAMETERS_HEAP_SIZE - SGX_SHARED_3DPARAMETERS_SIZE - 0x00001000)
+#else
+#if defined(SUPPORT_PERCONTEXT_PB)
+ #define SGX_SHARED_3DPARAMETERS_SIZE 0
+ #define SGX_SHARED_3DPARAMETERS_HEAP_SIZE 0
+ #define SGX_PERCONTEXT_3DPARAMETERS_HEAP_SIZE (SGX_3DPARAMETERS_HEAP_SIZE - 0x00001000)
+#endif
+#if defined(SUPPORT_SHARED_PB)
+ #define SGX_SHARED_3DPARAMETERS_SIZE SGX_3DPARAMETERS_HEAP_SIZE
+ #define SGX_SHARED_3DPARAMETERS_HEAP_SIZE (SGX_3DPARAMETERS_HEAP_SIZE - 0x00001000)
+ #define SGX_PERCONTEXT_3DPARAMETERS_HEAP_SIZE 0
+#endif
+#endif
+
+ #define SGX_SHARED_3DPARAMETERS_HEAP_BASE 0xD2000000
+
+
+ #define SGX_PERCONTEXT_3DPARAMETERS_HEAP_BASE (SGX_SHARED_3DPARAMETERS_HEAP_BASE + SGX_SHARED_3DPARAMETERS_SIZE)
+
+
+ #define SGX_TADATA_HEAP_BASE 0xE2000000
+ #define SGX_TADATA_HEAP_SIZE (0x0D000000-0x00001000)
+
+ #define SGX_SYNCINFO_HEAP_BASE 0xEF000000
+ #define SGX_SYNCINFO_HEAP_SIZE (0x01000000-0x00001000)
+
+ #define SGX_PDSPIXEL_CODEDATA_HEAP_BASE 0xF0000000
+ #define SGX_PDSPIXEL_CODEDATA_HEAP_SIZE (0x02000000-0x00001000)
+
+ #define SGX_KERNEL_CODE_HEAP_BASE 0xF2000000
+ #define SGX_KERNEL_CODE_HEAP_SIZE (0x00080000-0x00001000)
+
+ #define SGX_PDSVERTEX_CODEDATA_HEAP_BASE 0xF2400000
+ #define SGX_PDSVERTEX_CODEDATA_HEAP_SIZE (0x01C00000-0x00001000)
+
+ #define SGX_KERNEL_DATA_HEAP_BASE (0xF4000000+SGX_KERNEL_DATA_HEAP_OFFSET)
+ #define SGX_KERNEL_DATA_HEAP_SIZE (0x05000000-(0x00001000+SGX_KERNEL_DATA_HEAP_OFFSET))
+
+
+ #define SGX_PIXELSHADER_HEAP_BASE 0xF9000000
+ #define SGX_PIXELSHADER_HEAP_SIZE (0x05000000-0x00001000)
+
+ #define SGX_VERTEXSHADER_HEAP_BASE 0xFE000000
+ #define SGX_VERTEXSHADER_HEAP_SIZE (0x02000000-0x00001000)
+#endif
+
+ #define SGX_CORE_IDENTIFIED
+#endif
+
+#if SGX_FEATURE_ADDRESS_SPACE_SIZE == 28
+
+#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+ #define SGX_GENERAL_MAPPING_HEAP_BASE 0x00001000
+ #define SGX_GENERAL_MAPPING_HEAP_SIZE (0x01800000-0x00001000-0x00001000)
+
+ #define SGX_GENERAL_HEAP_BASE 0x01800000
+ #define SGX_GENERAL_HEAP_SIZE (0x07000000-0x00001000)
+
+#else
+ #define SGX_GENERAL_HEAP_BASE 0x00001000
+#if defined(SUPPORT_LARGE_GENERAL_HEAP)
+ #define SGX_GENERAL_HEAP_SIZE (0x0B800000-0x00001000-0x00001000)
+#else
+ #define SGX_GENERAL_HEAP_SIZE (0x08800000-0x00001000-0x00001000)
+#endif
+#endif
+
+#if defined(SUPPORT_LARGE_GENERAL_HEAP)
+ #define SGX_3DPARAMETERS_HEAP_SIZE 0x01000000
+#else
+ #define SGX_3DPARAMETERS_HEAP_SIZE 0x04000000
+#endif
+
+
+#if !defined(HYBRID_SHARED_PB_SIZE)
+ #define HYBRID_SHARED_PB_SIZE (SGX_3DPARAMETERS_HEAP_SIZE >> 1)
+#endif
+#if defined(SUPPORT_HYBRID_PB)
+ #define SGX_SHARED_3DPARAMETERS_SIZE (HYBRID_SHARED_PB_SIZE)
+ #define SGX_SHARED_3DPARAMETERS_HEAP_SIZE (HYBRID_SHARED_PB_SIZE-0x00001000)
+ #define SGX_PERCONTEXT_3DPARAMETERS_HEAP_SIZE (SGX_3DPARAMETERS_HEAP_SIZE - SGX_SHARED_3DPARAMETERS_SIZE - 0x00001000)
+#else
+#if defined(SUPPORT_PERCONTEXT_PB)
+ #define SGX_SHARED_3DPARAMETERS_SIZE 0
+ #define SGX_SHARED_3DPARAMETERS_HEAP_SIZE 0
+ #define SGX_PERCONTEXT_3DPARAMETERS_HEAP_SIZE (SGX_3DPARAMETERS_HEAP_SIZE - 0x00001000)
+#endif
+#if defined(SUPPORT_SHARED_PB)
+ #define SGX_SHARED_3DPARAMETERS_SIZE SGX_3DPARAMETERS_HEAP_SIZE
+ #define SGX_SHARED_3DPARAMETERS_HEAP_SIZE (SGX_3DPARAMETERS_HEAP_SIZE - 0x00001000)
+ #define SGX_PERCONTEXT_3DPARAMETERS_HEAP_SIZE 0
+#endif
+#endif
+
+#if defined(SUPPORT_LARGE_GENERAL_HEAP)
+ #define SGX_SHARED_3DPARAMETERS_HEAP_BASE 0x0B800000
+#else
+ #define SGX_SHARED_3DPARAMETERS_HEAP_BASE 0x08800000
+#endif
+
+
+
+ #define SGX_PERCONTEXT_3DPARAMETERS_HEAP_BASE (SGX_SHARED_3DPARAMETERS_HEAP_BASE + SGX_SHARED_3DPARAMETERS_SIZE)
+
+
+ #define SGX_TADATA_HEAP_BASE 0x0C800000
+ #define SGX_TADATA_HEAP_SIZE (0x01000000-0x00001000)
+
+ #define SGX_SYNCINFO_HEAP_BASE 0x0D800000
+ #define SGX_SYNCINFO_HEAP_SIZE (0x00400000-0x00001000)
+
+ #define SGX_PDSPIXEL_CODEDATA_HEAP_BASE 0x0DC00000
+ #define SGX_PDSPIXEL_CODEDATA_HEAP_SIZE (0x00800000-0x00001000)
+
+ #define SGX_KERNEL_CODE_HEAP_BASE 0x0E400000
+ #define SGX_KERNEL_CODE_HEAP_SIZE (0x00080000-0x00001000)
+
+ #define SGX_PDSVERTEX_CODEDATA_HEAP_BASE 0x0E800000
+ #define SGX_PDSVERTEX_CODEDATA_HEAP_SIZE (0x00800000-0x00001000)
+
+ #define SGX_KERNEL_DATA_HEAP_BASE (0x0F000000+SGX_KERNEL_DATA_HEAP_OFFSET)
+ #define SGX_KERNEL_DATA_HEAP_SIZE (0x00400000-(0x00001000+SGX_KERNEL_DATA_HEAP_OFFSET))
+
+ #define SGX_PIXELSHADER_HEAP_BASE 0x0F400000
+ #define SGX_PIXELSHADER_HEAP_SIZE (0x00500000-0x00001000)
+
+ #define SGX_VERTEXSHADER_HEAP_BASE 0x0FC00000
+ #define SGX_VERTEXSHADER_HEAP_SIZE (0x00200000-0x00001000)
+
+
+ #define SGX_CORE_IDENTIFIED
+
+#endif
+
+#if !defined(SGX_CORE_IDENTIFIED)
+ #error "sgxconfig.h: ERROR: unspecified SGX Core version"
+#endif
+
+#if !defined (SGX_FEATURE_EDM_VERTEX_PDSADDR_FULL_RANGE)
+ #if ((SGX_KERNEL_CODE_HEAP_BASE + SGX_KERNEL_CODE_HEAP_SIZE - SGX_PDSPIXEL_CODEDATA_HEAP_BASE) > 0x4000000)
+ #error "sgxconfig.h: ERROR: SGX_KERNEL_CODE_HEAP_BASE out of range of SGX_PDSPIXEL_CODEDATA_HEAP_BASE"
+ #endif
+
+ #if ((SGX_PDSVERTEX_CODEDATA_HEAP_BASE + SGX_PDSVERTEX_CODEDATA_HEAP_SIZE - SGX_PDSPIXEL_CODEDATA_HEAP_BASE) > 0x4000000)
+ #error "sgxconfig.h: ERROR: SGX_PDSVERTEX_CODEDATA_HEAP_BASE out of range of SGX_PDSPIXEL_CODEDATA_HEAP_BASE"
+ #endif
+#endif
+
+#if defined(SGX_FEATURE_2D_HARDWARE) && defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+ #if ((SGX_GENERAL_MAPPING_HEAP_BASE + SGX_GENERAL_MAPPING_HEAP_SIZE - SGX_2D_HEAP_BASE) >= EUR_CR_BIF_TWOD_REQ_BASE_ADDR_MASK)
+ #error "sgxconfig.h: ERROR: SGX_GENERAL_MAPPING_HEAP inaccessable by 2D requestor"
+ #endif
+#endif
+
+#if defined (EURASIA_USE_CODE_PAGE_SIZE)
+ #if ((SGX_KERNEL_CODE_HEAP_BASE & (EURASIA_USE_CODE_PAGE_SIZE - 1)) != 0)
+ #error "sgxconfig.h: ERROR: Kernel code heap base misalignment"
+ #endif
+#endif
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+ #if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+ #if ((SGX_2D_HEAP_BASE + SGX_2D_HEAP_SIZE) >= SGX_GENERAL_MAPPING_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_2D_HEAP overlaps SGX_GENERAL_MAPPING_HEAP"
+ #endif
+ #else
+ #if ((SGX_2D_HEAP_BASE + SGX_2D_HEAP_SIZE) >= SGX_GENERAL_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_2D_HEAP overlaps SGX_GENERAL_HEAP_BASE"
+ #endif
+ #endif
+#else
+ #if defined(FIX_HW_BRN_26915)
+ #if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+ #if ((SGX_CGBUFFER_HEAP_BASE + SGX_CGBUFFER_HEAP_SIZE) >= SGX_GENERAL_MAPPING_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_CGBUFFER_HEAP overlaps SGX_GENERAL_MAPPING_HEAP"
+ #endif
+ #else
+ #if ((SGX_CGBUFFER_HEAP_BASE + SGX_CGBUFFER_HEAP_SIZE) >= SGX_GENERAL_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_CGBUFFER_HEAP overlaps SGX_GENERAL_HEAP_BASE"
+ #endif
+ #endif
+ #endif
+#endif
+
+#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+ #if ((SGX_GENERAL_MAPPING_HEAP_BASE + SGX_GENERAL_MAPPING_HEAP_SIZE) >= SGX_GENERAL_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_GENERAL_MAPPING_HEAP overlaps SGX_GENERAL_HEAP"
+ #endif
+#endif
+
+#if defined(SUPPORT_HYBRID_PB)
+ #if ((HYBRID_SHARED_PB_SIZE + 0x000001000) > SGX_3DPARAMETERS_HEAP_SIZE)
+ #error "sgxconfig.h: ERROR: HYBRID_SHARED_PB_SIZE too large"
+ #endif
+#endif
+
+#if defined(SUPPORT_MEMORY_TILING)
+ #if ((SGX_GENERAL_HEAP_BASE + SGX_GENERAL_HEAP_SIZE) >= SGX_VPB_TILED_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_GENERAL_HEAP overlaps SGX_VPB_TILED_HEAP"
+ #endif
+ #if ((SGX_VPB_TILED_HEAP_BASE + SGX_VPB_TILED_HEAP_SIZE) >= SGX_SHARED_3DPARAMETERS_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_VPB_TILED_HEAP overlaps SGX_3DPARAMETERS_HEAP"
+ #endif
+#else
+ #if ((SGX_GENERAL_HEAP_BASE + SGX_GENERAL_HEAP_SIZE) >= SGX_SHARED_3DPARAMETERS_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_GENERAL_HEAP overlaps SGX_3DPARAMETERS_HEAP"
+ #endif
+#endif
+
+#if (((SGX_PERCONTEXT_3DPARAMETERS_HEAP_BASE + SGX_PERCONTEXT_3DPARAMETERS_HEAP_SIZE) >= SGX_TADATA_HEAP_BASE) && (SGX_PERCONTEXT_3DPARAMETERS_HEAP_SIZE > 0))
+ #error "sgxconfig.h: ERROR: SGX_PERCONTEXT_3DPARAMETERS_HEAP_BASE overlaps SGX_TADATA_HEAP"
+#endif
+
+#if ((SGX_TADATA_HEAP_BASE + SGX_TADATA_HEAP_SIZE) >= SGX_SYNCINFO_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_TADATA_HEAP overlaps SGX_SYNCINFO_HEAP"
+#endif
+
+#if ((SGX_SYNCINFO_HEAP_BASE + SGX_SYNCINFO_HEAP_SIZE) >= SGX_PDSPIXEL_CODEDATA_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_SYNCINFO_HEAP overlaps SGX_PDSPIXEL_CODEDATA_HEAP"
+#endif
+
+#if ((SGX_PDSPIXEL_CODEDATA_HEAP_BASE + SGX_PDSPIXEL_CODEDATA_HEAP_SIZE) >= SGX_KERNEL_CODE_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_PDSPIXEL_CODEDATA_HEAP overlaps SGX_KERNEL_CODE_HEAP"
+#endif
+
+#if ((SGX_KERNEL_CODE_HEAP_BASE + SGX_KERNEL_CODE_HEAP_SIZE) >= SGX_PDSVERTEX_CODEDATA_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_KERNEL_CODE_HEAP overlaps SGX_PDSVERTEX_CODEDATA_HEAP"
+#endif
+
+#if ((SGX_PDSVERTEX_CODEDATA_HEAP_BASE + SGX_PDSVERTEX_CODEDATA_HEAP_SIZE) >= SGX_KERNEL_DATA_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_PDSVERTEX_CODEDATA_HEAP overlaps SGX_KERNEL_DATA_HEAP"
+#endif
+
+#if ((SGX_KERNEL_DATA_HEAP_BASE + SGX_KERNEL_DATA_HEAP_SIZE) >= SGX_PIXELSHADER_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_KERNEL_DATA_HEAP overlaps SGX_PIXELSHADER_HEAP"
+#endif
+
+#if ((SGX_PIXELSHADER_HEAP_BASE + SGX_PIXELSHADER_HEAP_SIZE) >= SGX_VERTEXSHADER_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_PIXELSHADER_HEAP overlaps SGX_VERTEXSHADER_HEAP"
+#endif
+
+#if ((SGX_VERTEXSHADER_HEAP_BASE + SGX_VERTEXSHADER_HEAP_SIZE) < SGX_VERTEXSHADER_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_VERTEXSHADER_HEAP_BASE size cause wraparound"
+#endif
+
+#endif
+
diff --git a/drivers/gpu/pvr/sgx/sgxinfokm.h b/drivers/gpu/pvr/sgx/sgxinfokm.h
new file mode 100644
index 0000000..44a48be
--- /dev/null
+++ b/drivers/gpu/pvr/sgx/sgxinfokm.h
@@ -0,0 +1,573 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __SGXINFOKM_H__
+#define __SGXINFOKM_H__
+
+#include "sgxdefs.h"
+#include "device.h"
+#include "power.h"
+#include "sysconfig.h"
+#include "sgxscript.h"
+#include "sgxinfo.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define SGX_HOSTPORT_PRESENT 0x00000001UL
+
+
+#define SGX_PDUMPREG_NAME "SGXREG"
+
+typedef struct _PVRSRV_STUB_PBDESC_ PVRSRV_STUB_PBDESC;
+
+
+typedef struct _PVRSRV_SGX_CCB_INFO_ *PPVRSRV_SGX_CCB_INFO;
+
+typedef struct _PVRSRV_SGXDEV_INFO_
+{
+ PVRSRV_DEVICE_TYPE eDeviceType;
+ PVRSRV_DEVICE_CLASS eDeviceClass;
+
+ IMG_UINT8 ui8VersionMajor;
+ IMG_UINT8 ui8VersionMinor;
+ IMG_UINT32 ui32CoreConfig;
+ IMG_UINT32 ui32CoreFlags;
+
+
+ IMG_PVOID pvRegsBaseKM;
+
+#if defined(SGX_FEATURE_HOST_PORT)
+
+ IMG_PVOID pvHostPortBaseKM;
+
+ IMG_UINT32 ui32HPSize;
+
+ IMG_SYS_PHYADDR sHPSysPAddr;
+#endif
+
+
+ IMG_HANDLE hRegMapping;
+
+
+ IMG_SYS_PHYADDR sRegsPhysBase;
+
+ IMG_UINT32 ui32RegSize;
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+
+ IMG_UINT32 ui32ExtSysCacheRegsSize;
+
+ IMG_DEV_PHYADDR sExtSysCacheRegsDevPBase;
+
+ IMG_UINT32 *pui32ExtSystemCacheRegsPT;
+
+ IMG_HANDLE hExtSystemCacheRegsPTPageOSMemHandle;
+
+ IMG_SYS_PHYADDR sExtSystemCacheRegsPTSysPAddr;
+#endif
+
+
+ IMG_UINT32 ui32CoreClockSpeed;
+ IMG_UINT32 ui32uKernelTimerClock;
+ IMG_BOOL bSGXIdle;
+
+ PVRSRV_STUB_PBDESC *psStubPBDescListKM;
+
+
+
+ IMG_DEV_PHYADDR sKernelPDDevPAddr;
+
+ IMG_UINT32 ui32HeapCount;
+ IMG_VOID *pvDeviceMemoryHeap;
+ PPVRSRV_KERNEL_MEM_INFO psKernelCCBMemInfo;
+ PVRSRV_SGX_KERNEL_CCB *psKernelCCB;
+ PPVRSRV_SGX_CCB_INFO psKernelCCBInfo;
+ PPVRSRV_KERNEL_MEM_INFO psKernelCCBCtlMemInfo;
+ PVRSRV_SGX_CCB_CTL *psKernelCCBCtl;
+ PPVRSRV_KERNEL_MEM_INFO psKernelCCBEventKickerMemInfo;
+ IMG_UINT32 *pui32KernelCCBEventKicker;
+#if defined(PDUMP)
+ IMG_UINT32 ui32KernelCCBEventKickerDumpVal;
+#endif
+ PVRSRV_KERNEL_MEM_INFO *psKernelSGXMiscMemInfo;
+ IMG_UINT32 aui32HostKickAddr[SGXMKIF_CMD_MAX];
+#if defined(SGX_SUPPORT_HWPROFILING)
+ PPVRSRV_KERNEL_MEM_INFO psKernelHWProfilingMemInfo;
+#endif
+ PPVRSRV_KERNEL_MEM_INFO psKernelHWPerfCBMemInfo;
+ PPVRSRV_KERNEL_MEM_INFO psKernelTASigBufferMemInfo;
+ PPVRSRV_KERNEL_MEM_INFO psKernel3DSigBufferMemInfo;
+#if defined(FIX_HW_BRN_29702)
+ PPVRSRV_KERNEL_MEM_INFO psKernelCFIMemInfo;
+#endif
+#if defined(FIX_HW_BRN_29823)
+ PPVRSRV_KERNEL_MEM_INFO psKernelDummyTermStreamMemInfo;
+#endif
+#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && defined(FIX_HW_BRN_31559)
+ PPVRSRV_KERNEL_MEM_INFO psKernelVDMSnapShotBufferMemInfo;
+ PPVRSRV_KERNEL_MEM_INFO psKernelVDMCtrlStreamBufferMemInfo;
+#endif
+#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && \
+ defined(FIX_HW_BRN_33657) && defined(SUPPORT_SECURE_33657_FIX)
+ PPVRSRV_KERNEL_MEM_INFO psKernelVDMStateUpdateBufferMemInfo;
+#endif
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+ PPVRSRV_KERNEL_MEM_INFO psKernelEDMStatusBufferMemInfo;
+#endif
+
+ IMG_UINT32 ui32ClientRefCount;
+
+
+ IMG_UINT32 ui32CacheControl;
+
+
+ IMG_UINT32 ui32ClientBuildOptions;
+
+
+ SGX_MISCINFO_STRUCT_SIZES sSGXStructSizes;
+
+
+
+
+ IMG_VOID *pvMMUContextList;
+
+
+ IMG_BOOL bForcePTOff;
+
+ IMG_UINT32 ui32EDMTaskReg0;
+ IMG_UINT32 ui32EDMTaskReg1;
+
+ IMG_UINT32 ui32ClkGateCtl;
+ IMG_UINT32 ui32ClkGateCtl2;
+ IMG_UINT32 ui32ClkGateStatusReg;
+ IMG_UINT32 ui32ClkGateStatusMask;
+#if defined(SGX_FEATURE_MP)
+ IMG_UINT32 ui32MasterClkGateStatusReg;
+ IMG_UINT32 ui32MasterClkGateStatusMask;
+ IMG_UINT32 ui32MasterClkGateStatus2Reg;
+ IMG_UINT32 ui32MasterClkGateStatus2Mask;
+#endif
+ SGX_INIT_SCRIPTS sScripts;
+
+
+ IMG_HANDLE hBIFResetPDOSMemHandle;
+ IMG_DEV_PHYADDR sBIFResetPDDevPAddr;
+ IMG_DEV_PHYADDR sBIFResetPTDevPAddr;
+ IMG_DEV_PHYADDR sBIFResetPageDevPAddr;
+ IMG_UINT32 *pui32BIFResetPD;
+ IMG_UINT32 *pui32BIFResetPT;
+
+#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
+
+ IMG_HANDLE hBRN22997PTPageOSMemHandle;
+ IMG_HANDLE hBRN22997PDPageOSMemHandle;
+ IMG_DEV_PHYADDR sBRN22997PTDevPAddr;
+ IMG_DEV_PHYADDR sBRN22997PDDevPAddr;
+ IMG_UINT32 *pui32BRN22997PT;
+ IMG_UINT32 *pui32BRN22997PD;
+ IMG_SYS_PHYADDR sBRN22997SysPAddr;
+#endif
+
+#if defined(SUPPORT_HW_RECOVERY)
+
+ IMG_HANDLE hTimer;
+
+ IMG_UINT32 ui32TimeStamp;
+#endif
+
+
+ IMG_UINT32 ui32NumResets;
+
+
+ PVRSRV_KERNEL_MEM_INFO *psKernelSGXHostCtlMemInfo;
+ SGXMKIF_HOST_CTL *psSGXHostCtl;
+
+
+ PVRSRV_KERNEL_MEM_INFO *psKernelSGXTA3DCtlMemInfo;
+
+#if defined(FIX_HW_BRN_31272) || defined(FIX_HW_BRN_31780) || defined(FIX_HW_BRN_33920)
+ PVRSRV_KERNEL_MEM_INFO *psKernelSGXPTLAWriteBackMemInfo;
+#endif
+
+ IMG_UINT32 ui32Flags;
+
+
+ IMG_UINT32 ui32MemTilingUsage;
+
+ #if defined(PDUMP)
+ PVRSRV_SGX_PDUMP_CONTEXT sPDContext;
+ #endif
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+ IMG_VOID *pvDummyPTPageCpuVAddr;
+ IMG_DEV_PHYADDR sDummyPTDevPAddr;
+ IMG_HANDLE hDummyPTPageOSMemHandle;
+ IMG_VOID *pvDummyDataPageCpuVAddr;
+ IMG_DEV_PHYADDR sDummyDataDevPAddr;
+ IMG_HANDLE hDummyDataPageOSMemHandle;
+#endif
+#if defined(PDUMP)
+ PDUMP_MMU_ATTRIB sMMUAttrib;
+#endif
+ IMG_UINT32 asSGXDevData[SGX_MAX_DEV_DATA];
+
+#if defined(FIX_HW_BRN_31620)
+
+ IMG_VOID *pvBRN31620DummyPageCpuVAddr;
+ IMG_HANDLE hBRN31620DummyPageOSMemHandle;
+ IMG_DEV_PHYADDR sBRN31620DummyPageDevPAddr;
+
+
+ IMG_VOID *pvBRN31620DummyPTCpuVAddr;
+ IMG_HANDLE hBRN31620DummyPTOSMemHandle;
+ IMG_DEV_PHYADDR sBRN31620DummyPTDevPAddr;
+
+ IMG_HANDLE hKernelMMUContext;
+#endif
+
+} PVRSRV_SGXDEV_INFO;
+
+
+typedef struct _SGX_TIMING_INFORMATION_
+{
+ IMG_UINT32 ui32CoreClockSpeed;
+ IMG_UINT32 ui32HWRecoveryFreq;
+ IMG_BOOL bEnableActivePM;
+ IMG_UINT32 ui32ActivePowManLatencyms;
+ IMG_UINT32 ui32uKernelFreq;
+} SGX_TIMING_INFORMATION;
+
+typedef struct _SGX_DEVICE_MAP_
+{
+ IMG_UINT32 ui32Flags;
+
+
+ IMG_SYS_PHYADDR sRegsSysPBase;
+ IMG_CPU_PHYADDR sRegsCpuPBase;
+ IMG_CPU_VIRTADDR pvRegsCpuVBase;
+ IMG_UINT32 ui32RegsSize;
+
+#if defined(SGX_FEATURE_HOST_PORT)
+ IMG_SYS_PHYADDR sHPSysPBase;
+ IMG_CPU_PHYADDR sHPCpuPBase;
+ IMG_UINT32 ui32HPSize;
+#endif
+
+
+ IMG_SYS_PHYADDR sLocalMemSysPBase;
+ IMG_DEV_PHYADDR sLocalMemDevPBase;
+ IMG_CPU_PHYADDR sLocalMemCpuPBase;
+ IMG_UINT32 ui32LocalMemSize;
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+ IMG_UINT32 ui32ExtSysCacheRegsSize;
+ IMG_DEV_PHYADDR sExtSysCacheRegsDevPBase;
+#endif
+
+
+ IMG_UINT32 ui32IRQ;
+
+#if !defined(SGX_DYNAMIC_TIMING_INFO)
+
+ SGX_TIMING_INFORMATION sTimingInfo;
+#endif
+#if defined(PDUMP)
+
+ IMG_CHAR *pszPDumpDevName;
+#endif
+} SGX_DEVICE_MAP;
+
+
+struct _PVRSRV_STUB_PBDESC_
+{
+ IMG_UINT32 ui32RefCount;
+ IMG_UINT32 ui32TotalPBSize;
+ PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO **ppsSubKernelMemInfos;
+ IMG_UINT32 ui32SubKernelMemInfosCount;
+ IMG_HANDLE hDevCookie;
+ PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psHWBlockKernelMemInfo;
+ IMG_DEV_VIRTADDR sHWPBDescDevVAddr;
+ PVRSRV_STUB_PBDESC *psNext;
+ PVRSRV_STUB_PBDESC **ppsThis;
+};
+
+typedef struct _PVRSRV_SGX_CCB_INFO_
+{
+ PVRSRV_KERNEL_MEM_INFO *psCCBMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psCCBCtlMemInfo;
+ SGXMKIF_COMMAND *psCommands;
+ IMG_UINT32 *pui32WriteOffset;
+ volatile IMG_UINT32 *pui32ReadOffset;
+#if defined(PDUMP)
+ IMG_UINT32 ui32CCBDumpWOff;
+#endif
+} PVRSRV_SGX_CCB_INFO;
+
+
+typedef struct _SGX_BRIDGE_INIT_INFO_KM_
+{
+ IMG_HANDLE hKernelCCBMemInfo;
+ IMG_HANDLE hKernelCCBCtlMemInfo;
+ IMG_HANDLE hKernelCCBEventKickerMemInfo;
+ IMG_HANDLE hKernelSGXHostCtlMemInfo;
+ IMG_HANDLE hKernelSGXTA3DCtlMemInfo;
+#if defined(FIX_HW_BRN_31272) || defined(FIX_HW_BRN_31780) || defined(FIX_HW_BRN_33920)
+ IMG_HANDLE hKernelSGXPTLAWriteBackMemInfo;
+#endif
+ IMG_HANDLE hKernelSGXMiscMemInfo;
+
+ IMG_UINT32 aui32HostKickAddr[SGXMKIF_CMD_MAX];
+
+ SGX_INIT_SCRIPTS sScripts;
+
+ IMG_UINT32 ui32ClientBuildOptions;
+ SGX_MISCINFO_STRUCT_SIZES sSGXStructSizes;
+
+#if defined(SGX_SUPPORT_HWPROFILING)
+ IMG_HANDLE hKernelHWProfilingMemInfo;
+#endif
+#if defined(SUPPORT_SGX_HWPERF)
+ IMG_HANDLE hKernelHWPerfCBMemInfo;
+#endif
+ IMG_HANDLE hKernelTASigBufferMemInfo;
+ IMG_HANDLE hKernel3DSigBufferMemInfo;
+
+#if defined(FIX_HW_BRN_29702)
+ IMG_HANDLE hKernelCFIMemInfo;
+#endif
+#if defined(FIX_HW_BRN_29823)
+ IMG_HANDLE hKernelDummyTermStreamMemInfo;
+#endif
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+ IMG_HANDLE hKernelEDMStatusBufferMemInfo;
+#endif
+
+ IMG_UINT32 ui32EDMTaskReg0;
+ IMG_UINT32 ui32EDMTaskReg1;
+
+ IMG_UINT32 ui32ClkGateStatusReg;
+ IMG_UINT32 ui32ClkGateStatusMask;
+#if defined(SGX_FEATURE_MP)
+#endif
+
+ IMG_UINT32 ui32CacheControl;
+
+ IMG_UINT32 asInitDevData[SGX_MAX_DEV_DATA];
+ IMG_HANDLE asInitMemHandles[SGX_MAX_INIT_MEM_HANDLES];
+
+} SGX_BRIDGE_INIT_INFO_KM;
+
+
+typedef struct _SGX_INTERNEL_STATUS_UPDATE_KM_
+{
+ CTL_STATUS sCtlStatus;
+ IMG_HANDLE hKernelMemInfo;
+} SGX_INTERNEL_STATUS_UPDATE_KM;
+
+
+typedef struct _SGX_CCB_KICK_KM_
+{
+ SGXMKIF_COMMAND sCommand;
+ IMG_HANDLE hCCBKernelMemInfo;
+
+ IMG_UINT32 ui32NumDstSyncObjects;
+ IMG_HANDLE hKernelHWSyncListMemInfo;
+
+
+ IMG_HANDLE *pahDstSyncHandles;
+
+ IMG_UINT32 ui32NumTAStatusVals;
+ IMG_UINT32 ui32Num3DStatusVals;
+
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ SGX_INTERNEL_STATUS_UPDATE_KM asTAStatusUpdate[SGX_MAX_TA_STATUS_VALS];
+ SGX_INTERNEL_STATUS_UPDATE_KM as3DStatusUpdate[SGX_MAX_3D_STATUS_VALS];
+#else
+ IMG_HANDLE ahTAStatusSyncInfo[SGX_MAX_TA_STATUS_VALS];
+ IMG_HANDLE ah3DStatusSyncInfo[SGX_MAX_3D_STATUS_VALS];
+#endif
+
+ IMG_BOOL bFirstKickOrResume;
+#if (defined(NO_HARDWARE) || defined(PDUMP))
+ IMG_BOOL bTerminateOrAbort;
+#endif
+
+
+ IMG_UINT32 ui32CCBOffset;
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+
+ IMG_UINT32 ui32NumTASrcSyncs;
+ IMG_HANDLE ahTASrcKernelSyncInfo[SGX_MAX_TA_SRC_SYNCS];
+ IMG_UINT32 ui32NumTADstSyncs;
+ IMG_HANDLE ahTADstKernelSyncInfo[SGX_MAX_TA_DST_SYNCS];
+ IMG_UINT32 ui32Num3DSrcSyncs;
+ IMG_HANDLE ah3DSrcKernelSyncInfo[SGX_MAX_3D_SRC_SYNCS];
+#else
+
+ IMG_UINT32 ui32NumSrcSyncs;
+ IMG_HANDLE ahSrcKernelSyncInfo[SGX_MAX_SRC_SYNCS_TA];
+#endif
+
+
+ IMG_BOOL bTADependency;
+ IMG_HANDLE hTA3DSyncInfo;
+
+ IMG_HANDLE hTASyncInfo;
+ IMG_HANDLE h3DSyncInfo;
+#if defined(PDUMP)
+ IMG_UINT32 ui32CCBDumpWOff;
+#endif
+#if defined(NO_HARDWARE)
+ IMG_UINT32 ui32WriteOpsPendingVal;
+#endif
+} SGX_CCB_KICK_KM;
+
+
+#if defined(TRANSFER_QUEUE)
+typedef struct _PVRSRV_TRANSFER_SGX_KICK_KM_
+{
+ IMG_HANDLE hCCBMemInfo;
+ IMG_UINT32 ui32SharedCmdCCBOffset;
+
+ IMG_DEV_VIRTADDR sHWTransferContextDevVAddr;
+
+ IMG_HANDLE hTASyncInfo;
+ IMG_HANDLE h3DSyncInfo;
+
+ IMG_UINT32 ui32NumSrcSync;
+ IMG_HANDLE ahSrcSyncInfo[SGX_MAX_TRANSFER_SYNC_OPS];
+
+ IMG_UINT32 ui32NumDstSync;
+ IMG_HANDLE ahDstSyncInfo[SGX_MAX_TRANSFER_SYNC_OPS];
+
+ IMG_UINT32 ui32Flags;
+
+ IMG_UINT32 ui32PDumpFlags;
+#if defined(PDUMP)
+ IMG_UINT32 ui32CCBDumpWOff;
+#endif
+} PVRSRV_TRANSFER_SGX_KICK_KM, *PPVRSRV_TRANSFER_SGX_KICK_KM;
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+typedef struct _PVRSRV_2D_SGX_KICK_KM_
+{
+ IMG_HANDLE hCCBMemInfo;
+ IMG_UINT32 ui32SharedCmdCCBOffset;
+
+ IMG_DEV_VIRTADDR sHW2DContextDevVAddr;
+
+ IMG_UINT32 ui32NumSrcSync;
+ IMG_HANDLE ahSrcSyncInfo[SGX_MAX_2D_SRC_SYNC_OPS];
+
+
+ IMG_HANDLE hDstSyncInfo;
+
+
+ IMG_HANDLE hTASyncInfo;
+
+
+ IMG_HANDLE h3DSyncInfo;
+
+ IMG_UINT32 ui32PDumpFlags;
+#if defined(PDUMP)
+ IMG_UINT32 ui32CCBDumpWOff;
+#endif
+} PVRSRV_2D_SGX_KICK_KM, *PPVRSRV_2D_SGX_KICK_KM;
+#endif
+#endif
+
+PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_VOID SGXOSTimer(IMG_VOID *pvData);
+
+IMG_VOID SGXReset(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_BOOL bHardwareRecovery,
+ IMG_UINT32 ui32PDUMPFlags);
+
+IMG_VOID SGXInitClocks(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32PDUMPFlags);
+
+PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_BOOL bHardwareRecovery);
+PVRSRV_ERROR SGXDeinitialise(IMG_HANDLE hDevCookie);
+
+PVRSRV_ERROR SGXPrePowerState(IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+
+PVRSRV_ERROR SGXPostPowerState(IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+
+PVRSRV_ERROR SGXPreClockSpeedChange(IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+
+PVRSRV_ERROR SGXPostClockSpeedChange(IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+
+IMG_VOID SGXPanic(PVRSRV_SGXDEV_INFO *psDevInfo);
+
+IMG_VOID SGXDumpDebugInfo (PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_BOOL bDumpSGXRegs);
+
+PVRSRV_ERROR SGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+#if defined(SGX_DYNAMIC_TIMING_INFO)
+IMG_VOID SysGetSGXTimingInformation(SGX_TIMING_INFORMATION *psSGXTimingInfo);
+#endif
+
+#if defined(NO_HARDWARE)
+static INLINE IMG_VOID NoHardwareGenerateEvent(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32StatusRegister,
+ IMG_UINT32 ui32StatusValue,
+ IMG_UINT32 ui32StatusMask)
+{
+ IMG_UINT32 ui32RegVal;
+
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, ui32StatusRegister);
+
+ ui32RegVal &= ~ui32StatusMask;
+ ui32RegVal |= (ui32StatusValue & ui32StatusMask);
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32StatusRegister, ui32RegVal);
+}
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/pvr/sgx/sgxinit.c b/drivers/gpu/pvr/sgx/sgxinit.c
new file mode 100644
index 0000000..846035a
--- /dev/null
+++ b/drivers/gpu/pvr/sgx/sgxinit.c
@@ -0,0 +1,2873 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include <stddef.h>
+
+#include "sgxdefs.h"
+#include "sgxmmu.h"
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgx_mkif_km.h"
+#include "sgxconfig.h"
+#include "sysconfig.h"
+#include "pvr_bridge_km.h"
+
+#include "sgx_bridge_km.h"
+
+#include "pdump_km.h"
+#include "ra.h"
+#include "mmu.h"
+#include "handle.h"
+#include "perproc.h"
+
+#include "sgxutils.h"
+#include "pvrversion.h"
+#include "sgx_options.h"
+
+#include "lists.h"
+#include "srvkm.h"
+#include "ttrace.h"
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+
+static const IMG_CHAR *SGXUKernelStatusString(IMG_UINT32 code)
+{
+ switch(code)
+ {
+#define MKTC_ST(x) \
+ case x: \
+ return #x;
+#include "sgx_ukernel_status_codes.h"
+ default:
+ return "(Unknown)";
+ }
+}
+
+#endif
+
+#define VAR(x) #x
+
+
+#define CHECK_SIZE(NAME) \
+{ \
+ if (psSGXStructSizes->ui32Sizeof_##NAME != psDevInfo->sSGXStructSizes.ui32Sizeof_##NAME) \
+ { \
+ PVR_DPF((PVR_DBG_ERROR, "SGXDevInitCompatCheck: Size check failed for SGXMKIF_%s (client) = %d bytes, (ukernel) = %d bytes\n", \
+ VAR(NAME), \
+ psDevInfo->sSGXStructSizes.ui32Sizeof_##NAME, \
+ psSGXStructSizes->ui32Sizeof_##NAME )); \
+ bStructSizesFailed = IMG_TRUE; \
+ } \
+}
+
+#if defined (SYS_USING_INTERRUPTS)
+IMG_BOOL SGX_ISRHandler(IMG_VOID *pvData);
+#endif
+
+
+static
+PVRSRV_ERROR SGXGetMiscInfoUkernel(PVRSRV_SGXDEV_INFO *psDevInfo,
+ PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_HANDLE hDevMemContext);
+#if defined(PDUMP)
+static
+PVRSRV_ERROR SGXResetPDump(PVRSRV_DEVICE_NODE *psDeviceNode);
+#endif
+
+static IMG_VOID SGXCommandComplete(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+#if defined(OS_SUPPORTS_IN_LISR)
+ if (OSInLISR(psDeviceNode->psSysData))
+ {
+
+ psDeviceNode->bReProcessDeviceCommandComplete = IMG_TRUE;
+ }
+ else
+ {
+ SGXScheduleProcessQueuesKM(psDeviceNode);
+ }
+#else
+ SGXScheduleProcessQueuesKM(psDeviceNode);
+#endif
+}
+
+static IMG_UINT32 DeinitDevInfo(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ if (psDevInfo->psKernelCCBInfo != IMG_NULL)
+ {
+
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_SGX_CCB_INFO), psDevInfo->psKernelCCBInfo, IMG_NULL);
+ }
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR InitDevInfo(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ PVRSRV_DEVICE_NODE *psDeviceNode,
+#if defined (SUPPORT_SID_INTERFACE)
+ SGX_BRIDGE_INIT_INFO_KM *psInitInfo)
+#else
+ SGX_BRIDGE_INIT_INFO *psInitInfo)
+#endif
+{
+ PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+ PVRSRV_ERROR eError;
+
+ PVRSRV_SGX_CCB_INFO *psKernelCCBInfo = IMG_NULL;
+
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+ psDevInfo->sScripts = psInitInfo->sScripts;
+
+ psDevInfo->psKernelCCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelCCBMemInfo;
+ psDevInfo->psKernelCCB = (PVRSRV_SGX_KERNEL_CCB *) psDevInfo->psKernelCCBMemInfo->pvLinAddrKM;
+
+ psDevInfo->psKernelCCBCtlMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelCCBCtlMemInfo;
+ psDevInfo->psKernelCCBCtl = (PVRSRV_SGX_CCB_CTL *) psDevInfo->psKernelCCBCtlMemInfo->pvLinAddrKM;
+
+ psDevInfo->psKernelCCBEventKickerMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelCCBEventKickerMemInfo;
+ psDevInfo->pui32KernelCCBEventKicker = (IMG_UINT32 *)psDevInfo->psKernelCCBEventKickerMemInfo->pvLinAddrKM;
+
+ psDevInfo->psKernelSGXHostCtlMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelSGXHostCtlMemInfo;
+ psDevInfo->psSGXHostCtl = (SGXMKIF_HOST_CTL *)psDevInfo->psKernelSGXHostCtlMemInfo->pvLinAddrKM;
+
+ psDevInfo->psKernelSGXTA3DCtlMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelSGXTA3DCtlMemInfo;
+
+#if defined(FIX_HW_BRN_31272) || defined(FIX_HW_BRN_31780) || defined(FIX_HW_BRN_33920)
+ psDevInfo->psKernelSGXPTLAWriteBackMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelSGXPTLAWriteBackMemInfo;
+#endif
+
+ psDevInfo->psKernelSGXMiscMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelSGXMiscMemInfo;
+
+#if defined(SGX_SUPPORT_HWPROFILING)
+ psDevInfo->psKernelHWProfilingMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelHWProfilingMemInfo;
+#endif
+#if defined(SUPPORT_SGX_HWPERF)
+ psDevInfo->psKernelHWPerfCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelHWPerfCBMemInfo;
+#endif
+ psDevInfo->psKernelTASigBufferMemInfo = psInitInfo->hKernelTASigBufferMemInfo;
+ psDevInfo->psKernel3DSigBufferMemInfo = psInitInfo->hKernel3DSigBufferMemInfo;
+#if defined(FIX_HW_BRN_29702)
+ psDevInfo->psKernelCFIMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelCFIMemInfo;
+#endif
+#if defined(FIX_HW_BRN_29823)
+ psDevInfo->psKernelDummyTermStreamMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelDummyTermStreamMemInfo;
+#endif
+#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && defined(FIX_HW_BRN_31559)
+ psDevInfo->psKernelVDMSnapShotBufferMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelVDMSnapShotBufferMemInfo;
+ psDevInfo->psKernelVDMCtrlStreamBufferMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelVDMCtrlStreamBufferMemInfo;
+#endif
+#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && \
+ defined(FIX_HW_BRN_33657) && defined(SUPPORT_SECURE_33657_FIX)
+ psDevInfo->psKernelVDMStateUpdateBufferMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelVDMStateUpdateBufferMemInfo;
+#endif
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+ psDevInfo->psKernelEDMStatusBufferMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelEDMStatusBufferMemInfo;
+#endif
+
+ psDevInfo->ui32ClientBuildOptions = psInitInfo->ui32ClientBuildOptions;
+
+
+ psDevInfo->sSGXStructSizes = psInitInfo->sSGXStructSizes;
+
+
+
+ eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_SGX_CCB_INFO),
+ (IMG_VOID **)&psKernelCCBInfo, 0,
+ "SGX Circular Command Buffer Info");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"InitDevInfo: Failed to alloc memory"));
+ goto failed_allockernelccb;
+ }
+
+
+ OSMemSet(psKernelCCBInfo, 0, sizeof(PVRSRV_SGX_CCB_INFO));
+ psKernelCCBInfo->psCCBMemInfo = psDevInfo->psKernelCCBMemInfo;
+ psKernelCCBInfo->psCCBCtlMemInfo = psDevInfo->psKernelCCBCtlMemInfo;
+ psKernelCCBInfo->psCommands = psDevInfo->psKernelCCB->asCommands;
+ psKernelCCBInfo->pui32WriteOffset = &psDevInfo->psKernelCCBCtl->ui32WriteOffset;
+ psKernelCCBInfo->pui32ReadOffset = &psDevInfo->psKernelCCBCtl->ui32ReadOffset;
+ psDevInfo->psKernelCCBInfo = psKernelCCBInfo;
+
+
+
+ OSMemCopy(psDevInfo->aui32HostKickAddr, psInitInfo->aui32HostKickAddr,
+ SGXMKIF_CMD_MAX * sizeof(psDevInfo->aui32HostKickAddr[0]));
+
+ psDevInfo->bForcePTOff = IMG_FALSE;
+
+ psDevInfo->ui32CacheControl = psInitInfo->ui32CacheControl;
+
+ psDevInfo->ui32EDMTaskReg0 = psInitInfo->ui32EDMTaskReg0;
+ psDevInfo->ui32EDMTaskReg1 = psInitInfo->ui32EDMTaskReg1;
+ psDevInfo->ui32ClkGateCtl = psInitInfo->ui32ClkGateCtl;
+ psDevInfo->ui32ClkGateCtl2 = psInitInfo->ui32ClkGateCtl2;
+ psDevInfo->ui32ClkGateStatusReg = psInitInfo->ui32ClkGateStatusReg;
+ psDevInfo->ui32ClkGateStatusMask = psInitInfo->ui32ClkGateStatusMask;
+#if defined(SGX_FEATURE_MP)
+ psDevInfo->ui32MasterClkGateStatusReg = psInitInfo->ui32MasterClkGateStatusReg;
+ psDevInfo->ui32MasterClkGateStatusMask = psInitInfo->ui32MasterClkGateStatusMask;
+ psDevInfo->ui32MasterClkGateStatus2Reg = psInitInfo->ui32MasterClkGateStatus2Reg;
+ psDevInfo->ui32MasterClkGateStatus2Mask = psInitInfo->ui32MasterClkGateStatus2Mask;
+#endif
+
+
+
+ OSMemCopy(&psDevInfo->asSGXDevData, &psInitInfo->asInitDevData, sizeof(psDevInfo->asSGXDevData));
+
+ return PVRSRV_OK;
+
+failed_allockernelccb:
+ DeinitDevInfo(psDevInfo);
+
+ return eError;
+}
+
+
+
+
+static PVRSRV_ERROR SGXRunScript(PVRSRV_SGXDEV_INFO *psDevInfo, SGX_INIT_COMMAND *psScript, IMG_UINT32 ui32NumInitCommands)
+{
+ IMG_UINT32 ui32PC;
+ SGX_INIT_COMMAND *psComm;
+
+ for (ui32PC = 0, psComm = psScript;
+ ui32PC < ui32NumInitCommands;
+ ui32PC++, psComm++)
+ {
+ switch (psComm->eOp)
+ {
+ case SGX_INIT_OP_WRITE_HW_REG:
+ {
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, psComm->sWriteHWReg.ui32Offset, psComm->sWriteHWReg.ui32Value);
+ PDUMPCOMMENT("SGXRunScript: Write HW reg operation");
+ PDUMPREG(SGX_PDUMPREG_NAME, psComm->sWriteHWReg.ui32Offset, psComm->sWriteHWReg.ui32Value);
+ break;
+ }
+#if defined(PDUMP)
+ case SGX_INIT_OP_PDUMP_HW_REG:
+ {
+ PDUMPCOMMENT("SGXRunScript: Dump HW reg operation");
+ PDUMPREG(SGX_PDUMPREG_NAME, psComm->sPDumpHWReg.ui32Offset, psComm->sPDumpHWReg.ui32Value);
+ break;
+ }
+#endif
+ case SGX_INIT_OP_HALT:
+ {
+ return PVRSRV_OK;
+ }
+ case SGX_INIT_OP_ILLEGAL:
+
+ default:
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXRunScript: PC %d: Illegal command: %d", ui32PC, psComm->eOp));
+ return PVRSRV_ERROR_UNKNOWN_SCRIPT_OPERATION;
+ }
+ }
+
+ }
+
+ return PVRSRV_ERROR_UNKNOWN_SCRIPT_OPERATION;
+}
+
+#if defined(SUPPORT_MEMORY_TILING)
+static PVRSRV_ERROR SGX_AllocMemTilingRangeInt(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32Start,
+ IMG_UINT32 ui32End,
+ IMG_UINT32 ui32TilingStride,
+ IMG_UINT32 *pui32RangeIndex)
+{
+ IMG_UINT32 i;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT32 ui32Val;
+
+
+ for(i=0; i < SGX_BIF_NUM_TILING_RANGES; i++)
+ {
+ if((psDevInfo->ui32MemTilingUsage & (1U << i)) == 0)
+ {
+
+ psDevInfo->ui32MemTilingUsage |= 1U << i;
+
+ if(pui32RangeIndex != IMG_NULL)
+ {
+ *pui32RangeIndex = i;
+ }
+ goto RangeAllocated;
+ }
+ }
+
+ PVR_DPF((PVR_DBG_ERROR,"SGX_AllocMemTilingRange: all tiling ranges in use"));
+ return PVRSRV_ERROR_EXCEEDED_HW_LIMITS;
+
+RangeAllocated:
+
+
+ if(ui32Start & ~SGX_BIF_TILING_ADDR_MASK)
+ {
+ PVR_DPF((PVR_DBG_WARNING,"SGX_AllocMemTilingRangeInt: Tiling range start (0x%08X) fails"
+ "alignment test", ui32Start));
+ }
+ if((ui32End + 0x00001000) & ~SGX_BIF_TILING_ADDR_MASK)
+ {
+ PVR_DPF((PVR_DBG_WARNING,"SGX_AllocMemTilingRangeInt: Tiling range end (0x%08X) fails"
+ "alignment test", ui32End));
+ }
+
+ ui32Offset = EUR_CR_BIF_TILE0 + (i<<2);
+
+ ui32Val = ((ui32TilingStride << EUR_CR_BIF_TILE0_CFG_SHIFT) & EUR_CR_BIF_TILE0_CFG_MASK)
+ | (((ui32End>>SGX_BIF_TILING_ADDR_LSB) << EUR_CR_BIF_TILE0_MAX_ADDRESS_SHIFT) & EUR_CR_BIF_TILE0_MAX_ADDRESS_MASK)
+ | (((ui32Start>>SGX_BIF_TILING_ADDR_LSB) << EUR_CR_BIF_TILE0_MIN_ADDRESS_SHIFT) & EUR_CR_BIF_TILE0_MIN_ADDRESS_MASK)
+ | (EUR_CR_BIF_TILE0_ENABLE << EUR_CR_BIF_TILE0_CFG_SHIFT);
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Offset, ui32Val);
+ PDUMPREG(SGX_PDUMPREG_NAME, ui32Offset, ui32Val);
+
+#if defined(SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS)
+ ui32Offset = EUR_CR_BIF_TILE0_ADDR_EXT + (i<<2);
+
+ ui32Val = (((ui32End>>SGX_BIF_TILING_EXT_ADDR_LSB) << EUR_CR_BIF_TILE0_ADDR_EXT_MAX_SHIFT) & EUR_CR_BIF_TILE0_ADDR_EXT_MAX_MASK)
+ | (((ui32Start>>SGX_BIF_TILING_EXT_ADDR_LSB) << EUR_CR_BIF_TILE0_ADDR_EXT_MIN_SHIFT) & EUR_CR_BIF_TILE0_ADDR_EXT_MIN_MASK);
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Offset, ui32Val);
+ PDUMPREG(SGX_PDUMPREG_NAME, ui32Offset, ui32Val);
+#endif
+
+ return PVRSRV_OK;
+}
+
+#endif
+
+PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_BOOL bHardwareRecovery)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_KERNEL_MEM_INFO *psSGXHostCtlMemInfo = psDevInfo->psKernelSGXHostCtlMemInfo;
+ SGXMKIF_HOST_CTL *psSGXHostCtl = psSGXHostCtlMemInfo->pvLinAddrKM;
+ static IMG_BOOL bFirstTime = IMG_TRUE;
+#if defined(PDUMP)
+ IMG_BOOL bPDumpIsSuspended = PDumpIsSuspended();
+#endif
+
+#if defined(SGX_FEATURE_MP)
+
+#else
+ SGXInitClocks(psDevInfo, PDUMP_FLAGS_CONTINUOUS);
+#endif
+
+
+
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "SGX initialisation script part 1\n");
+ eError = SGXRunScript(psDevInfo, psDevInfo->sScripts.asInitCommandsPart1, SGX_MAX_INIT_COMMANDS);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXInitialise: SGXRunScript (part 1) failed (%d)", eError));
+ return eError;
+ }
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "End of SGX initialisation script part 1\n");
+
+
+ psDevInfo->ui32NumResets++;
+ SGXReset(psDevInfo, bFirstTime || bHardwareRecovery, PDUMP_FLAGS_CONTINUOUS);
+
+#if defined(EUR_CR_POWER)
+#if defined(SGX531)
+
+
+
+
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_POWER, 1);
+ PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_POWER, 1);
+#else
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_POWER, 0);
+ PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_POWER, 0);
+#endif
+#endif
+
+
+ *psDevInfo->pui32KernelCCBEventKicker = 0;
+#if defined(PDUMP)
+ if (!bPDumpIsSuspended)
+ {
+ psDevInfo->ui32KernelCCBEventKickerDumpVal = 0;
+ PDUMPMEM(&psDevInfo->ui32KernelCCBEventKickerDumpVal,
+ psDevInfo->psKernelCCBEventKickerMemInfo, 0,
+ sizeof(*psDevInfo->pui32KernelCCBEventKicker), PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
+ }
+#endif
+
+#if defined(SUPPORT_MEMORY_TILING)
+ {
+
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap = psDevInfo->pvDeviceMemoryHeap;
+ IMG_UINT32 i;
+
+ psDevInfo->ui32MemTilingUsage = 0;
+
+ for(i=0; i<psDevInfo->ui32HeapCount; i++)
+ {
+ if(psDeviceMemoryHeap[i].ui32XTileStride > 0)
+ {
+
+ eError = SGX_AllocMemTilingRangeInt(
+ psDevInfo,
+ psDeviceMemoryHeap[i].sDevVAddrBase.uiAddr,
+ psDeviceMemoryHeap[i].sDevVAddrBase.uiAddr
+ + psDeviceMemoryHeap[i].ui32HeapSize,
+ psDeviceMemoryHeap[i].ui32XTileStride,
+ NULL);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Unable to allocate SGX BIF tiling range for heap: %s",
+ psDeviceMemoryHeap[i].pszName));
+ break;
+ }
+ }
+ }
+ }
+#endif
+
+
+
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "SGX initialisation script part 2\n");
+ eError = SGXRunScript(psDevInfo, psDevInfo->sScripts.asInitCommandsPart2, SGX_MAX_INIT_COMMANDS);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXInitialise: SGXRunScript (part 2) failed (%d)", eError));
+ return eError;
+ }
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "End of SGX initialisation script part 2\n");
+
+
+ psSGXHostCtl->ui32HostClock = OSClockus();
+
+ psSGXHostCtl->ui32InitStatus = 0;
+#if defined(PDUMP)
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+ "Reset the SGX microkernel initialisation status\n");
+ PDUMPMEM(IMG_NULL, psSGXHostCtlMemInfo,
+ offsetof(SGXMKIF_HOST_CTL, ui32InitStatus),
+ sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psSGXHostCtlMemInfo));
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+ "Initialise the microkernel\n");
+#endif
+
+#if defined(SGX_FEATURE_MULTI_EVENT_KICK)
+ OSWriteMemoryBarrier();
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM,
+ SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK2, 0),
+ EUR_CR_EVENT_KICK2_NOW_MASK);
+#else
+ *psDevInfo->pui32KernelCCBEventKicker = (*psDevInfo->pui32KernelCCBEventKicker + 1) & 0xFF;
+ OSWriteMemoryBarrier();
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM,
+ SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0),
+ EUR_CR_EVENT_KICK_NOW_MASK);
+#endif
+
+ OSMemoryBarrier();
+
+#if defined(PDUMP)
+
+
+ if (!bPDumpIsSuspended)
+ {
+#if defined(SGX_FEATURE_MULTI_EVENT_KICK)
+ PDUMPREG(SGX_PDUMPREG_NAME, SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK2, 0), EUR_CR_EVENT_KICK2_NOW_MASK);
+#else
+ psDevInfo->ui32KernelCCBEventKickerDumpVal = 1;
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+ "First increment of the SGX event kicker value\n");
+ PDUMPMEM(&psDevInfo->ui32KernelCCBEventKickerDumpVal,
+ psDevInfo->psKernelCCBEventKickerMemInfo,
+ 0,
+ sizeof(IMG_UINT32),
+ PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
+ PDUMPREG(SGX_PDUMPREG_NAME, SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0), EUR_CR_EVENT_KICK_NOW_MASK);
+#endif
+ }
+#endif
+
+#if !defined(NO_HARDWARE)
+
+
+ if (PollForValueKM(&psSGXHostCtl->ui32InitStatus,
+ PVRSRV_USSE_EDM_INIT_COMPLETE,
+ PVRSRV_USSE_EDM_INIT_COMPLETE,
+ MAX_HW_TIME_US,
+ MAX_HW_TIME_US/WAIT_TRY_COUNT,
+ IMG_FALSE) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXInitialise: Wait for uKernel initialisation failed"));
+ #if !defined(FIX_HW_BRN_23281)
+ SGXDumpDebugInfo(psDevInfo, IMG_FALSE);
+ PVR_DBG_BREAK;
+ #endif
+ return PVRSRV_ERROR_RETRY;
+ }
+#endif
+
+#if defined(PDUMP)
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+ "Wait for the SGX microkernel initialisation to complete");
+ PDUMPMEMPOL(psSGXHostCtlMemInfo,
+ offsetof(SGXMKIF_HOST_CTL, ui32InitStatus),
+ PVRSRV_USSE_EDM_INIT_COMPLETE,
+ PVRSRV_USSE_EDM_INIT_COMPLETE,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psSGXHostCtlMemInfo));
+#endif
+
+#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
+
+
+
+ WorkaroundBRN22997ReadHostPort(psDevInfo);
+#endif
+
+ PVR_ASSERT(psDevInfo->psKernelCCBCtl->ui32ReadOffset == psDevInfo->psKernelCCBCtl->ui32WriteOffset);
+
+ bFirstTime = IMG_FALSE;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR SGXDeinitialise(IMG_HANDLE hDevCookie)
+
+{
+ PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *) hDevCookie;
+ PVRSRV_ERROR eError;
+
+
+ if (psDevInfo->pvRegsBaseKM == IMG_NULL)
+ {
+ return PVRSRV_OK;
+ }
+
+ eError = SGXRunScript(psDevInfo, psDevInfo->sScripts.asDeinitCommands, SGX_MAX_DEINIT_COMMANDS);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXDeinitialise: SGXRunScript failed (%d)", eError));
+ return eError;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR DevInitSGXPart1 (IMG_VOID *pvDeviceNode)
+{
+ IMG_HANDLE hDevMemHeap = IMG_NULL;
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+ IMG_HANDLE hKernelDevMemContext;
+ IMG_DEV_PHYADDR sPDDevPAddr;
+ IMG_UINT32 i;
+ PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvDeviceNode;
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
+ PVRSRV_ERROR eError;
+
+
+ PDUMPCOMMENT("SGX Core Version Information: %s", SGX_CORE_FRIENDLY_NAME);
+
+ #if defined(SGX_FEATURE_MP)
+ #if !defined(SGX_FEATURE_MP_PLUS)
+ PDUMPCOMMENT("SGX Multi-processor: %d cores", SGX_FEATURE_MP_CORE_COUNT);
+ #else
+ PDUMPCOMMENT("SGX Multi-processor: %d TA cores, %d 3D cores", SGX_FEATURE_MP_CORE_COUNT_TA, SGX_FEATURE_MP_CORE_COUNT_3D);
+ #endif
+ #endif
+
+#if (SGX_CORE_REV == 0)
+ PDUMPCOMMENT("SGX Core Revision Information: head RTL");
+#else
+ PDUMPCOMMENT("SGX Core Revision Information: %d", SGX_CORE_REV);
+#endif
+
+ #if defined(SGX_FEATURE_SYSTEM_CACHE)
+ PDUMPCOMMENT("SGX System Level Cache is present\r\n");
+ #if defined(SGX_BYPASS_SYSTEM_CACHE)
+ PDUMPCOMMENT("SGX System Level Cache is bypassed\r\n");
+ #endif
+ #endif
+
+ PDUMPCOMMENT("SGX Initialisation Part 1");
+
+
+ if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_SGXDEV_INFO),
+ (IMG_VOID **)&psDevInfo, IMG_NULL,
+ "SGX Device Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart1 : Failed to alloc memory for DevInfo"));
+ return (PVRSRV_ERROR_OUT_OF_MEMORY);
+ }
+ OSMemSet (psDevInfo, 0, sizeof(PVRSRV_SGXDEV_INFO));
+
+
+ psDevInfo->eDeviceType = DEV_DEVICE_TYPE;
+ psDevInfo->eDeviceClass = DEV_DEVICE_CLASS;
+
+
+ psDeviceNode->pvDevice = (IMG_PVOID)psDevInfo;
+
+
+ psDevInfo->ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount;
+ psDevInfo->pvDeviceMemoryHeap = (IMG_VOID*)psDeviceMemoryHeap;
+
+
+ hKernelDevMemContext = BM_CreateContext(psDeviceNode,
+ &sPDDevPAddr,
+ IMG_NULL,
+ IMG_NULL);
+ if (hKernelDevMemContext == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart1: Failed BM_CreateContext"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ psDevInfo->sKernelPDDevPAddr = sPDDevPAddr;
+
+
+ for(i=0; i<psDeviceNode->sDevMemoryInfo.ui32HeapCount; i++)
+ {
+ switch(psDeviceMemoryHeap[i].DevMemHeapType)
+ {
+ case DEVICE_MEMORY_HEAP_KERNEL:
+ case DEVICE_MEMORY_HEAP_SHARED:
+ case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+ {
+
+ if (psDeviceMemoryHeap[i].ui32HeapSize > 0)
+ {
+ hDevMemHeap = BM_CreateHeap (hKernelDevMemContext,
+ &psDeviceMemoryHeap[i]);
+
+
+
+ psDeviceMemoryHeap[i].hDevMemHeap = hDevMemHeap;
+ }
+ break;
+ }
+ }
+ }
+#if defined(PDUMP)
+ if(hDevMemHeap)
+ {
+
+ psDevInfo->sMMUAttrib = *((BM_HEAP*)hDevMemHeap)->psMMUAttrib;
+ }
+#endif
+ eError = MMU_BIFResetPDAlloc(psDevInfo);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevInitSGX : Failed to alloc memory for BIF reset"));
+ return eError;
+ }
+
+ return PVRSRV_OK;
+}
+
+IMG_EXPORT
+#if defined (SUPPORT_SID_INTERFACE)
+PVRSRV_ERROR SGXGetInfoForSrvinitKM(IMG_HANDLE hDevHandle, PVRSRV_HEAP_INFO_KM *pasHeapInfo, IMG_DEV_PHYADDR *psPDDevPAddr)
+#else
+PVRSRV_ERROR SGXGetInfoForSrvinitKM(IMG_HANDLE hDevHandle, SGX_BRIDGE_INFO_FOR_SRVINIT *psInitInfo)
+#endif
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+ PVRSRV_ERROR eError;
+
+ PDUMPCOMMENT("SGXGetInfoForSrvinit");
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevHandle;
+ psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+
+#if defined (SUPPORT_SID_INTERFACE)
+ *psPDDevPAddr = psDevInfo->sKernelPDDevPAddr;
+
+ eError = PVRSRVGetDeviceMemHeapsKM(hDevHandle, pasHeapInfo);
+#else
+ psInitInfo->sPDDevPAddr = psDevInfo->sKernelPDDevPAddr;
+
+ eError = PVRSRVGetDeviceMemHeapsKM(hDevHandle, &psInitInfo->asHeapInfo[0]);
+#endif
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXGetInfoForSrvinit: PVRSRVGetDeviceMemHeapsKM failed (%d)", eError));
+ return eError;
+ }
+
+ return eError;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR DevInitSGXPart2KM (PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevHandle,
+#if defined (SUPPORT_SID_INTERFACE)
+ SGX_BRIDGE_INIT_INFO_KM *psInitInfo)
+#else
+ SGX_BRIDGE_INIT_INFO *psInitInfo)
+#endif
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+ PVRSRV_ERROR eError;
+ SGX_DEVICE_MAP *psSGXDeviceMap;
+ PVRSRV_DEV_POWER_STATE eDefaultPowerState;
+
+ PDUMPCOMMENT("SGX Initialisation Part 2");
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevHandle;
+ psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+
+
+
+ eError = InitDevInfo(psPerProc, psDeviceNode, psInitInfo);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart2KM: Failed to load EDM program"));
+ goto failed_init_dev_info;
+ }
+
+
+ eError = SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
+ (IMG_VOID**)&psSGXDeviceMap);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart2KM: Failed to get device memory map!"));
+ return PVRSRV_ERROR_INIT_FAILURE;
+ }
+
+
+ if (psSGXDeviceMap->pvRegsCpuVBase)
+ {
+ psDevInfo->pvRegsBaseKM = psSGXDeviceMap->pvRegsCpuVBase;
+ }
+ else
+ {
+
+ psDevInfo->pvRegsBaseKM = OSMapPhysToLin(psSGXDeviceMap->sRegsCpuPBase,
+ psSGXDeviceMap->ui32RegsSize,
+ PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+ IMG_NULL);
+ if (!psDevInfo->pvRegsBaseKM)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart2KM: Failed to map in regs\n"));
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+ }
+ psDevInfo->ui32RegSize = psSGXDeviceMap->ui32RegsSize;
+ psDevInfo->sRegsPhysBase = psSGXDeviceMap->sRegsSysPBase;
+
+
+#if defined(SGX_FEATURE_HOST_PORT)
+ if (psSGXDeviceMap->ui32Flags & SGX_HOSTPORT_PRESENT)
+ {
+
+ psDevInfo->pvHostPortBaseKM = OSMapPhysToLin(psSGXDeviceMap->sHPCpuPBase,
+ psSGXDeviceMap->ui32HPSize,
+ PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+ IMG_NULL);
+ if (!psDevInfo->pvHostPortBaseKM)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart2KM: Failed to map in host port\n"));
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+ psDevInfo->ui32HPSize = psSGXDeviceMap->ui32HPSize;
+ psDevInfo->sHPSysPAddr = psSGXDeviceMap->sHPSysPBase;
+ }
+#endif
+
+#if defined (SYS_USING_INTERRUPTS)
+
+
+ psDeviceNode->pvISRData = psDeviceNode;
+
+ PVR_ASSERT(psDeviceNode->pfnDeviceISR == SGX_ISRHandler);
+
+#endif
+
+
+ psDevInfo->psSGXHostCtl->ui32PowerStatus |= PVRSRV_USSE_EDM_POWMAN_NO_WORK;
+ eDefaultPowerState = PVRSRV_DEV_POWER_STATE_OFF;
+
+ eError = PVRSRVRegisterPowerDevice (psDeviceNode->sDevId.ui32DeviceIndex,
+ &SGXPrePowerState, &SGXPostPowerState,
+ &SGXPreClockSpeedChange, &SGXPostClockSpeedChange,
+ (IMG_HANDLE)psDeviceNode,
+ PVRSRV_DEV_POWER_STATE_OFF,
+ eDefaultPowerState);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart2KM: failed to register device with power manager"));
+ return eError;
+ }
+
+#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
+ eError = WorkaroundBRN22997Alloc(psDeviceNode);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXInitialise : Failed to alloc memory for BRN22997 workaround"));
+ return eError;
+ }
+#endif
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+
+ psDevInfo->ui32ExtSysCacheRegsSize = psSGXDeviceMap->ui32ExtSysCacheRegsSize;
+ psDevInfo->sExtSysCacheRegsDevPBase = psSGXDeviceMap->sExtSysCacheRegsDevPBase;
+ eError = MMU_MapExtSystemCacheRegs(psDeviceNode);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXInitialise : Failed to map external system cache registers"));
+ return eError;
+ }
+#endif
+
+
+
+ OSMemSet(psDevInfo->psKernelCCB, 0, sizeof(PVRSRV_SGX_KERNEL_CCB));
+ OSMemSet(psDevInfo->psKernelCCBCtl, 0, sizeof(PVRSRV_SGX_CCB_CTL));
+ OSMemSet(psDevInfo->pui32KernelCCBEventKicker, 0, sizeof(*psDevInfo->pui32KernelCCBEventKicker));
+ PDUMPCOMMENT("Initialise Kernel CCB");
+ PDUMPMEM(IMG_NULL, psDevInfo->psKernelCCBMemInfo, 0, sizeof(PVRSRV_SGX_KERNEL_CCB), PDUMP_FLAGS_CONTINUOUS, MAKEUNIQUETAG(psDevInfo->psKernelCCBMemInfo));
+ PDUMPCOMMENT("Initialise Kernel CCB Control");
+ PDUMPMEM(IMG_NULL, psDevInfo->psKernelCCBCtlMemInfo, 0, sizeof(PVRSRV_SGX_CCB_CTL), PDUMP_FLAGS_CONTINUOUS, MAKEUNIQUETAG(psDevInfo->psKernelCCBCtlMemInfo));
+ PDUMPCOMMENT("Initialise Kernel CCB Event Kicker");
+ PDUMPMEM(IMG_NULL, psDevInfo->psKernelCCBEventKickerMemInfo, 0, sizeof(*psDevInfo->pui32KernelCCBEventKicker), PDUMP_FLAGS_CONTINUOUS, MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
+
+ return PVRSRV_OK;
+
+failed_init_dev_info:
+ return eError;
+}
+
+static PVRSRV_ERROR DevDeInitSGX (IMG_VOID *pvDeviceNode)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvDeviceNode;
+ PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32Heap;
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+ SGX_DEVICE_MAP *psSGXDeviceMap;
+
+ if (!psDevInfo)
+ {
+
+ PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX: Null DevInfo"));
+ return PVRSRV_OK;
+ }
+
+#if defined(SUPPORT_HW_RECOVERY)
+ if (psDevInfo->hTimer)
+ {
+ eError = OSRemoveTimer(psDevInfo->hTimer);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX: Failed to remove timer"));
+ return eError;
+ }
+ psDevInfo->hTimer = IMG_NULL;
+ }
+#endif
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+
+ eError = MMU_UnmapExtSystemCacheRegs(psDeviceNode);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX: Failed to unmap ext system cache registers"));
+ return eError;
+ }
+#endif
+
+#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
+ WorkaroundBRN22997Free(psDeviceNode);
+#endif
+
+ MMU_BIFResetPDFree(psDevInfo);
+
+
+
+ DeinitDevInfo(psDevInfo);
+
+
+ psDeviceMemoryHeap = (DEVICE_MEMORY_HEAP_INFO *)psDevInfo->pvDeviceMemoryHeap;
+ for(ui32Heap=0; ui32Heap<psDeviceNode->sDevMemoryInfo.ui32HeapCount; ui32Heap++)
+ {
+ switch(psDeviceMemoryHeap[ui32Heap].DevMemHeapType)
+ {
+ case DEVICE_MEMORY_HEAP_KERNEL:
+ case DEVICE_MEMORY_HEAP_SHARED:
+ case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+ {
+ if (psDeviceMemoryHeap[ui32Heap].hDevMemHeap != IMG_NULL)
+ {
+ BM_DestroyHeap(psDeviceMemoryHeap[ui32Heap].hDevMemHeap);
+ }
+ break;
+ }
+ }
+ }
+
+
+ eError = BM_DestroyContext(psDeviceNode->sDevMemoryInfo.pBMKernelContext, IMG_NULL);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX : Failed to destroy kernel context"));
+ return eError;
+ }
+
+
+ eError = PVRSRVRemovePowerDevice (((PVRSRV_DEVICE_NODE*)pvDeviceNode)->sDevId.ui32DeviceIndex);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ eError = SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
+ (IMG_VOID**)&psSGXDeviceMap);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX: Failed to get device memory map!"));
+ return eError;
+ }
+
+
+ if (!psSGXDeviceMap->pvRegsCpuVBase)
+ {
+
+ if (psDevInfo->pvRegsBaseKM != IMG_NULL)
+ {
+ OSUnMapPhysToLin(psDevInfo->pvRegsBaseKM,
+ psDevInfo->ui32RegSize,
+ PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+ IMG_NULL);
+ }
+ }
+
+#if defined(SGX_FEATURE_HOST_PORT)
+ if (psSGXDeviceMap->ui32Flags & SGX_HOSTPORT_PRESENT)
+ {
+
+ if (psDevInfo->pvHostPortBaseKM != IMG_NULL)
+ {
+ OSUnMapPhysToLin(psDevInfo->pvHostPortBaseKM,
+ psDevInfo->ui32HPSize,
+ PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+ IMG_NULL);
+ }
+ }
+#endif
+
+
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_SGXDEV_INFO),
+ psDevInfo,
+ 0);
+
+ psDeviceNode->pvDevice = IMG_NULL;
+
+ if (psDeviceMemoryHeap != IMG_NULL)
+ {
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(DEVICE_MEMORY_HEAP_INFO) * SGX_MAX_HEAP_ID,
+ psDeviceMemoryHeap,
+ 0);
+ }
+
+ return PVRSRV_OK;
+}
+
+
+#if defined(RESTRICTED_REGISTERS) && defined(SGX_FEATURE_MP)
+
+static IMG_VOID SGXDumpMasterDebugReg (PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_CHAR *pszName,
+ IMG_UINT32 ui32RegAddr)
+{
+ IMG_UINT32 ui32RegVal;
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, ui32RegAddr);
+ PVR_LOG(("(HYD) %s%08X", pszName, ui32RegVal));
+}
+
+#endif
+
+static IMG_VOID SGXDumpDebugReg (PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32CoreNum,
+ IMG_CHAR *pszName,
+ IMG_UINT32 ui32RegAddr)
+{
+ IMG_UINT32 ui32RegVal;
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(ui32RegAddr, ui32CoreNum));
+ PVR_LOG(("(P%u) %s%08X", ui32CoreNum, pszName, ui32RegVal));
+}
+
+IMG_VOID SGXDumpDebugInfo (PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_BOOL bDumpSGXRegs)
+{
+ IMG_UINT32 ui32CoreNum;
+
+ PVR_LOG(("SGX debug (%s)", PVRVERSION_STRING));
+
+ if (bDumpSGXRegs)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGX Register Base Address (Linear): 0x%08X", (IMG_UINTPTR_T)psDevInfo->pvRegsBaseKM));
+ PVR_DPF((PVR_DBG_ERROR,"SGX Register Base Address (Physical): 0x%08X", psDevInfo->sRegsPhysBase.uiAddr));
+
+ SGXDumpDebugReg(psDevInfo, 0, "EUR_CR_CORE_ID: ", EUR_CR_CORE_ID);
+ SGXDumpDebugReg(psDevInfo, 0, "EUR_CR_CORE_REVISION: ", EUR_CR_CORE_REVISION);
+#if defined(RESTRICTED_REGISTERS) && defined(SGX_FEATURE_MP)
+ SGXDumpMasterDebugReg(psDevInfo, "EUR_CR_MASTER_BIF_INT_STAT: ", EUR_CR_MASTER_BIF_INT_STAT);
+ SGXDumpMasterDebugReg(psDevInfo, "EUR_CR_MASTER_BIF_FAULT: ",EUR_CR_MASTER_BIF_FAULT);
+ SGXDumpMasterDebugReg(psDevInfo, "EUR_CR_MASTER_CLKGATESTATUS2: ",EUR_CR_MASTER_CLKGATESTATUS2 );
+ SGXDumpMasterDebugReg(psDevInfo, "EUR_CR_MASTER_VDM_PIM_STATUS: ",EUR_CR_MASTER_VDM_PIM_STATUS);
+ SGXDumpMasterDebugReg(psDevInfo, "EUR_CR_MASTER_BIF_BANK_SET: ",EUR_CR_MASTER_BIF_BANK_SET);
+
+ SGXDumpMasterDebugReg(psDevInfo, "EUR_CR_MASTER_EVENT_STATUS: ",EUR_CR_MASTER_EVENT_STATUS);
+ SGXDumpMasterDebugReg(psDevInfo, "EUR_CR_MASTER_EVENT_STATUS2: ",EUR_CR_MASTER_EVENT_STATUS2);
+ SGXDumpMasterDebugReg(psDevInfo, "EUR_CR_MASTER_MP_PRIMITIVE: ",EUR_CR_MASTER_MP_PRIMITIVE);
+ SGXDumpMasterDebugReg(psDevInfo, "EUR_CR_MASTER_DPM_DPLIST_STATUS: ",EUR_CR_MASTER_DPM_DPLIST_STATUS);
+ SGXDumpMasterDebugReg(psDevInfo, "EUR_CR_MASTER_DPM_PROACTIVE_PIM_SPEC: ",EUR_CR_MASTER_DPM_PROACTIVE_PIM_SPEC);
+ SGXDumpMasterDebugReg(psDevInfo, "EUR_CR_MASTER_PAGE_MANAGEOP: ",EUR_CR_MASTER_DPM_PAGE_MANAGEOP);
+ SGXDumpMasterDebugReg(psDevInfo, "EUR_CR_MASTER_VDM_CONTEXT_STORE_SNAPSHOT: ",EUR_CR_MASTER_VDM_CONTEXT_STORE_SNAPSHOT);
+ SGXDumpMasterDebugReg(psDevInfo, "EUR_CR_MASTER_VDM_CONTEXT_LOAD_STATUS: ",EUR_CR_MASTER_VDM_CONTEXT_LOAD_STATUS);
+ SGXDumpMasterDebugReg(psDevInfo, "EUR_CR_MASTER_VDM_CONTEXT_STORE_STREAM: ",EUR_CR_MASTER_VDM_CONTEXT_STORE_STREAM);
+ SGXDumpMasterDebugReg(psDevInfo, "EUR_CR_MASTER_VDM_CONTEXT_STORE_STATUS: ",EUR_CR_MASTER_VDM_CONTEXT_STORE_STATUS);
+ SGXDumpMasterDebugReg(psDevInfo, "EUR_CR_MASTER_VDM_CONTEXT_STORE_STATE0: ",EUR_CR_MASTER_VDM_CONTEXT_STORE_STATE0);
+ SGXDumpMasterDebugReg(psDevInfo, "EUR_CR_MASTER_VDM_CONTEXT_STORE_STATE1: ",EUR_CR_MASTER_VDM_CONTEXT_STORE_STATE1);
+ SGXDumpMasterDebugReg(psDevInfo, "EUR_CR_MASTER_VDM_WAIT_FOR_KICK: ",EUR_CR_MASTER_VDM_WAIT_FOR_KICK);
+#endif
+ for (ui32CoreNum = 0; ui32CoreNum < SGX_FEATURE_MP_CORE_COUNT_3D; ui32CoreNum++)
+ {
+
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_EVENT_STATUS: ", EUR_CR_EVENT_STATUS);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_EVENT_STATUS2: ", EUR_CR_EVENT_STATUS2);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_BIF_CTRL: ", EUR_CR_BIF_CTRL);
+ #if defined(EUR_CR_BIF_BANK0)
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_BIF_BANK0: ", EUR_CR_BIF_BANK0);
+ #endif
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_BIF_INT_STAT: ", EUR_CR_BIF_INT_STAT);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_BIF_FAULT: ", EUR_CR_BIF_FAULT);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_BIF_MEM_REQ_STAT: ", EUR_CR_BIF_MEM_REQ_STAT);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_CLKGATECTL: ", EUR_CR_CLKGATECTL);
+ #if defined(EUR_CR_PDS_PC_BASE)
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_PDS_PC_BASE: ", EUR_CR_PDS_PC_BASE);
+ #endif
+ }
+
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) && !defined(FIX_HW_BRN_31620)
+ {
+ IMG_UINT32 ui32RegVal;
+ IMG_UINT32 ui32PDDevPAddr;
+
+
+
+
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_INT_STAT);
+ if (ui32RegVal & EUR_CR_BIF_INT_STAT_PF_N_RW_MASK)
+ {
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_FAULT);
+ ui32RegVal &= EUR_CR_BIF_FAULT_ADDR_MASK;
+ ui32PDDevPAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0);
+ ui32PDDevPAddr &= EUR_CR_BIF_DIR_LIST_BASE0_ADDR_MASK;
+ MMU_CheckFaultAddr(psDevInfo, ui32PDDevPAddr, ui32RegVal);
+ }
+ }
+#endif
+ }
+
+
+
+ QueueDumpDebugInfo();
+
+ {
+
+
+ SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl;
+ IMG_UINT32 *pui32HostCtlBuffer = (IMG_UINT32 *)psSGXHostCtl;
+ IMG_UINT32 ui32LoopCounter;
+
+ if (psSGXHostCtl->ui32AssertFail != 0)
+ {
+ PVR_LOG(("SGX Microkernel assert fail: 0x%08X", psSGXHostCtl->ui32AssertFail));
+ psSGXHostCtl->ui32AssertFail = 0;
+ }
+
+ PVR_LOG(("SGX Host control:"));
+
+ for (ui32LoopCounter = 0;
+ ui32LoopCounter < sizeof(*psDevInfo->psSGXHostCtl) / sizeof(*pui32HostCtlBuffer);
+ ui32LoopCounter += 4)
+ {
+ PVR_LOG(("\t(HC-%X) 0x%08X 0x%08X 0x%08X 0x%08X", ui32LoopCounter * sizeof(*pui32HostCtlBuffer),
+ pui32HostCtlBuffer[ui32LoopCounter + 0], pui32HostCtlBuffer[ui32LoopCounter + 1],
+ pui32HostCtlBuffer[ui32LoopCounter + 2], pui32HostCtlBuffer[ui32LoopCounter + 3]));
+ }
+ }
+
+ {
+
+
+ IMG_UINT32 *pui32TA3DCtlBuffer = psDevInfo->psKernelSGXTA3DCtlMemInfo->pvLinAddrKM;
+ IMG_UINT32 ui32LoopCounter;
+
+ PVR_LOG(("SGX TA/3D control:"));
+
+ for (ui32LoopCounter = 0;
+ ui32LoopCounter < psDevInfo->psKernelSGXTA3DCtlMemInfo->uAllocSize / sizeof(*pui32TA3DCtlBuffer);
+ ui32LoopCounter += 4)
+ {
+ PVR_LOG(("\t(T3C-%X) 0x%08X 0x%08X 0x%08X 0x%08X", ui32LoopCounter * sizeof(*pui32TA3DCtlBuffer),
+ pui32TA3DCtlBuffer[ui32LoopCounter + 0], pui32TA3DCtlBuffer[ui32LoopCounter + 1],
+ pui32TA3DCtlBuffer[ui32LoopCounter + 2], pui32TA3DCtlBuffer[ui32LoopCounter + 3]));
+ }
+ }
+
+ #if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+ {
+ IMG_UINT32 *pui32MKTraceBuffer = psDevInfo->psKernelEDMStatusBufferMemInfo->pvLinAddrKM;
+ IMG_UINT32 ui32LastStatusCode, ui32WriteOffset;
+
+ ui32LastStatusCode = *pui32MKTraceBuffer;
+ pui32MKTraceBuffer++;
+ ui32WriteOffset = *pui32MKTraceBuffer;
+ pui32MKTraceBuffer++;
+
+ PVR_LOG(("Last SGX microkernel status code: %08X %s",
+ ui32LastStatusCode, SGXUKernelStatusString(ui32LastStatusCode)));
+
+ #if defined(PVRSRV_DUMP_MK_TRACE)
+
+
+ {
+ IMG_UINT32 ui32LoopCounter;
+
+ for (ui32LoopCounter = 0;
+ ui32LoopCounter < SGXMK_TRACE_BUFFER_SIZE;
+ ui32LoopCounter++)
+ {
+ IMG_UINT32 *pui32BufPtr;
+ pui32BufPtr = pui32MKTraceBuffer +
+ (((ui32WriteOffset + ui32LoopCounter) % SGXMK_TRACE_BUFFER_SIZE) * 4);
+ PVR_LOG(("\t(MKT-%X) %08X %08X %08X %08X %s", ui32LoopCounter,
+ pui32BufPtr[2], pui32BufPtr[3], pui32BufPtr[1], pui32BufPtr[0],
+ SGXUKernelStatusString(pui32BufPtr[0])));
+ }
+ }
+ #endif
+ }
+ #endif
+
+ {
+
+
+ PVR_LOG(("SGX Kernel CCB WO:0x%X RO:0x%X",
+ psDevInfo->psKernelCCBCtl->ui32WriteOffset,
+ psDevInfo->psKernelCCBCtl->ui32ReadOffset));
+
+ #if defined(PVRSRV_DUMP_KERNEL_CCB)
+ {
+ IMG_UINT32 ui32LoopCounter;
+
+ for (ui32LoopCounter = 0;
+ ui32LoopCounter < sizeof(psDevInfo->psKernelCCB->asCommands) /
+ sizeof(psDevInfo->psKernelCCB->asCommands[0]);
+ ui32LoopCounter++)
+ {
+ SGXMKIF_COMMAND *psCommand = &psDevInfo->psKernelCCB->asCommands[ui32LoopCounter];
+
+ PVR_LOG(("\t(KCCB-%X) %08X %08X - %08X %08X %08X %08X", ui32LoopCounter,
+ psCommand->ui32ServiceAddress, psCommand->ui32CacheControl,
+ psCommand->ui32Data[0], psCommand->ui32Data[1],
+ psCommand->ui32Data[2], psCommand->ui32Data[3]));
+ }
+ }
+ #endif
+ }
+ #if defined (TTRACE)
+ PVRSRVDumpTimeTraceBuffers();
+ #endif
+
+}
+
+
+#if defined(SYS_USING_INTERRUPTS) || defined(SUPPORT_HW_RECOVERY)
+static
+IMG_VOID HWRecoveryResetSGX (PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 ui32Component,
+ IMG_UINT32 ui32CallerID)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+ SGXMKIF_HOST_CTL *psSGXHostCtl = (SGXMKIF_HOST_CTL *)psDevInfo->psSGXHostCtl;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Component);
+
+
+
+ eError = PVRSRVPowerLock(ui32CallerID, IMG_FALSE);
+ if(eError != PVRSRV_OK)
+ {
+
+
+
+ PVR_DPF((PVR_DBG_WARNING,"HWRecoveryResetSGX: Power transition in progress"));
+ return;
+ }
+
+ psSGXHostCtl->ui32InterruptClearFlags |= PVRSRV_USSE_EDM_INTERRUPT_HWR;
+
+ PVR_LOG(("HWRecoveryResetSGX: SGX Hardware Recovery triggered"));
+
+ SGXDumpDebugInfo(psDeviceNode->pvDevice, IMG_TRUE);
+
+
+ PDUMPSUSPEND();
+
+
+#if defined(FIX_HW_BRN_23281)
+
+ for (eError = PVRSRV_ERROR_RETRY; eError == PVRSRV_ERROR_RETRY;)
+#endif
+ {
+ eError = SGXInitialise(psDevInfo, IMG_TRUE);
+ }
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"HWRecoveryResetSGX: SGXInitialise failed (%d)", eError));
+ }
+
+
+ PDUMPRESUME();
+
+ PVRSRVPowerUnlock(ui32CallerID);
+
+
+ SGXScheduleProcessQueuesKM(psDeviceNode);
+
+
+
+ PVRSRVProcessQueues(IMG_TRUE);
+}
+#endif
+
+
+#if defined(SUPPORT_HW_RECOVERY)
+IMG_VOID SGXOSTimer(IMG_VOID *pvData)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode = pvData;
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ static IMG_UINT32 ui32EDMTasks = 0;
+ static IMG_UINT32 ui32LockupCounter = 0;
+ static IMG_UINT32 ui32OpenCLDelayCounter = 0;
+ static IMG_UINT32 ui32NumResets = 0;
+#if defined(FIX_HW_BRN_31093)
+ static IMG_BOOL bBRN31093Inval = IMG_FALSE;
+#endif
+ IMG_UINT32 ui32CurrentEDMTasks;
+ IMG_UINT32 ui32CurrentOpenCLDelayCounter=0;
+ IMG_BOOL bLockup = IMG_FALSE;
+ IMG_BOOL bPoweredDown;
+
+
+ psDevInfo->ui32TimeStamp++;
+
+#if defined(NO_HARDWARE)
+ bPoweredDown = IMG_TRUE;
+#else
+ bPoweredDown = (SGXIsDevicePowered(psDeviceNode)) ? IMG_FALSE : IMG_TRUE;
+#endif
+
+
+
+ if (bPoweredDown)
+ {
+ ui32LockupCounter = 0;
+ #if defined(FIX_HW_BRN_31093)
+ bBRN31093Inval = IMG_FALSE;
+ #endif
+ }
+ else
+ {
+
+ ui32CurrentEDMTasks = OSReadHWReg(psDevInfo->pvRegsBaseKM, psDevInfo->ui32EDMTaskReg0);
+ if (psDevInfo->ui32EDMTaskReg1 != 0)
+ {
+ ui32CurrentEDMTasks ^= OSReadHWReg(psDevInfo->pvRegsBaseKM, psDevInfo->ui32EDMTaskReg1);
+ }
+ if ((ui32CurrentEDMTasks == ui32EDMTasks) &&
+ (psDevInfo->ui32NumResets == ui32NumResets))
+ {
+ ui32LockupCounter++;
+ if (ui32LockupCounter == 3)
+ {
+ ui32LockupCounter = 0;
+ ui32CurrentOpenCLDelayCounter = (psDevInfo->psSGXHostCtl)->ui32OpenCLDelayCount;
+ if(0 != ui32CurrentOpenCLDelayCounter)
+ {
+ if(ui32OpenCLDelayCounter != ui32CurrentOpenCLDelayCounter){
+ ui32OpenCLDelayCounter = ui32CurrentOpenCLDelayCounter;
+ }else{
+ ui32OpenCLDelayCounter -= 1;
+ (psDevInfo->psSGXHostCtl)->ui32OpenCLDelayCount = ui32OpenCLDelayCounter;
+ }
+ goto SGX_NoUKernel_LockUp;
+ }
+
+
+ #if defined(FIX_HW_BRN_31093)
+ if (bBRN31093Inval == IMG_FALSE)
+ {
+
+ #if defined(FIX_HW_BRN_29997)
+ IMG_UINT32 ui32BIFCtrl;
+
+ ui32BIFCtrl = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_PAUSE_MASK);
+
+ SGXWaitClocks(psDevInfo, 200);
+ #endif
+
+ bBRN31093Inval = IMG_TRUE;
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL_INVAL, EUR_CR_BIF_CTRL_INVAL_PTE_MASK);
+
+ SGXWaitClocks(psDevInfo, 200);
+
+ #if defined(FIX_HW_BRN_29997)
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl);
+ #endif
+ }
+ else
+ #endif
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXOSTimer() detected SGX lockup (0x%x tasks)", ui32EDMTasks));
+
+ bLockup = IMG_TRUE;
+ (psDevInfo->psSGXHostCtl)->ui32OpenCLDelayCount = 0;
+ }
+ }
+ }
+ else
+ {
+ #if defined(FIX_HW_BRN_31093)
+ bBRN31093Inval = IMG_FALSE;
+ #endif
+ ui32LockupCounter = 0;
+ ui32EDMTasks = ui32CurrentEDMTasks;
+ ui32NumResets = psDevInfo->ui32NumResets;
+ }
+ }
+SGX_NoUKernel_LockUp:
+
+ if (bLockup)
+ {
+ SGXMKIF_HOST_CTL *psSGXHostCtl = (SGXMKIF_HOST_CTL *)psDevInfo->psSGXHostCtl;
+
+
+ psSGXHostCtl->ui32HostDetectedLockups ++;
+
+
+ HWRecoveryResetSGX(psDeviceNode, 0, ISR_ID);
+ }
+}
+#endif
+
+
+
+#if defined(SYS_USING_INTERRUPTS)
+
+IMG_BOOL SGX_ISRHandler (IMG_VOID *pvData)
+{
+ IMG_BOOL bInterruptProcessed = IMG_FALSE;
+
+
+
+ {
+ IMG_UINT32 ui32EventStatus, ui32EventEnable;
+ IMG_UINT32 ui32EventClear = 0;
+#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+ IMG_UINT32 ui32EventStatus2, ui32EventEnable2;
+#endif
+ IMG_UINT32 ui32EventClear2 = 0;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+
+
+ if(pvData == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGX_ISRHandler: Invalid params\n"));
+ return bInterruptProcessed;
+ }
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *)pvData;
+ psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+
+ ui32EventStatus = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS);
+ ui32EventEnable = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_ENABLE);
+
+
+ ui32EventStatus &= ui32EventEnable;
+
+#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+ ui32EventStatus2 = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS2);
+ ui32EventEnable2 = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_ENABLE2);
+
+
+ ui32EventStatus2 &= ui32EventEnable2;
+#endif
+
+
+
+ if (ui32EventStatus & EUR_CR_EVENT_STATUS_SW_EVENT_MASK)
+ {
+ ui32EventClear |= EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK;
+ }
+
+#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+ if (ui32EventStatus2 & EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_UNTRAPPED_MASK)
+ {
+ ui32EventClear2 |= EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_UNTRAPPED_MASK;
+ }
+
+ if (ui32EventStatus2 & EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_TRAPPED_MASK)
+ {
+ ui32EventClear2 |= EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_TRAPPED_MASK;
+ }
+#endif
+
+ if (ui32EventClear || ui32EventClear2)
+ {
+ bInterruptProcessed = IMG_TRUE;
+
+
+ ui32EventClear |= EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK;
+
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR, ui32EventClear);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR2, ui32EventClear2);
+ }
+ }
+
+ return bInterruptProcessed;
+}
+
+
+static IMG_VOID SGX_MISRHandler (IMG_VOID *pvData)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvData;
+ PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+ SGXMKIF_HOST_CTL *psSGXHostCtl = (SGXMKIF_HOST_CTL *)psDevInfo->psSGXHostCtl;
+
+ if (((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_HWR) != 0UL) &&
+ ((psSGXHostCtl->ui32InterruptClearFlags & PVRSRV_USSE_EDM_INTERRUPT_HWR) == 0UL))
+ {
+ HWRecoveryResetSGX(psDeviceNode, 0, ISR_ID);
+ }
+
+#if defined(OS_SUPPORTS_IN_LISR)
+ if (psDeviceNode->bReProcessDeviceCommandComplete)
+ {
+ SGXScheduleProcessQueuesKM(psDeviceNode);
+ }
+#endif
+
+ SGXTestActivePowerEvent(psDeviceNode, ISR_ID);
+}
+#endif
+
+#if defined(SUPPORT_MEMORY_TILING)
+
+IMG_INTERNAL
+PVRSRV_ERROR SGX_AllocMemTilingRange(PVRSRV_DEVICE_NODE *psDeviceNode,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32XTileStride,
+ IMG_UINT32 *pui32RangeIndex)
+{
+ return SGX_AllocMemTilingRangeInt(psDeviceNode->pvDevice,
+ psMemInfo->sDevVAddr.uiAddr,
+ psMemInfo->sDevVAddr.uiAddr + ((IMG_UINT32) psMemInfo->uAllocSize) + SGX_MMU_PAGE_SIZE - 1,
+ ui32XTileStride,
+ pui32RangeIndex);
+}
+
+IMG_INTERNAL
+PVRSRV_ERROR SGX_FreeMemTilingRange(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 ui32RangeIndex)
+{
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT32 ui32Val;
+
+ if(ui32RangeIndex >= 10)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGX_FreeMemTilingRange: invalid Range index "));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ psDevInfo->ui32MemTilingUsage &= ~(1<<ui32RangeIndex);
+
+
+ ui32Offset = EUR_CR_BIF_TILE0 + (ui32RangeIndex<<2);
+ ui32Val = 0;
+
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Offset, ui32Val);
+ PDUMPREG(SGX_PDUMPREG_NAME, ui32Offset, ui32Val);
+
+ return PVRSRV_OK;
+}
+
+#endif
+
+
+static IMG_VOID SGXCacheInvalidate(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
+ #if defined(SGX_FEATURE_MP)
+ psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_BIF_SL;
+ #else
+ PVR_UNREFERENCED_PARAMETER(psDevInfo);
+ #endif
+}
+
+PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ DEVICE_MEMORY_INFO *psDevMemoryInfo;
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+
+
+ psDeviceNode->sDevId.eDeviceType = DEV_DEVICE_TYPE;
+ psDeviceNode->sDevId.eDeviceClass = DEV_DEVICE_CLASS;
+#if defined(PDUMP)
+ {
+
+ SGX_DEVICE_MAP *psSGXDeviceMemMap;
+ SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
+ (IMG_VOID**)&psSGXDeviceMemMap);
+
+ psDeviceNode->sDevId.pszPDumpDevName = psSGXDeviceMemMap->pszPDumpDevName;
+ PVR_ASSERT(psDeviceNode->sDevId.pszPDumpDevName != IMG_NULL);
+ }
+
+ psDeviceNode->sDevId.pszPDumpRegName = SGX_PDUMPREG_NAME;
+#endif
+
+ psDeviceNode->pfnInitDevice = &DevInitSGXPart1;
+ psDeviceNode->pfnDeInitDevice = &DevDeInitSGX;
+
+ psDeviceNode->pfnInitDeviceCompatCheck = &SGXDevInitCompatCheck;
+#if defined(PDUMP)
+ psDeviceNode->pfnPDumpInitDevice = &SGXResetPDump;
+ psDeviceNode->pfnMMUGetContextID = &MMU_GetPDumpContextID;
+#endif
+
+
+ psDeviceNode->pfnMMUInitialise = &MMU_Initialise;
+ psDeviceNode->pfnMMUFinalise = &MMU_Finalise;
+ psDeviceNode->pfnMMUInsertHeap = &MMU_InsertHeap;
+ psDeviceNode->pfnMMUCreate = &MMU_Create;
+ psDeviceNode->pfnMMUDelete = &MMU_Delete;
+ psDeviceNode->pfnMMUAlloc = &MMU_Alloc;
+ psDeviceNode->pfnMMUFree = &MMU_Free;
+ psDeviceNode->pfnMMUMapPages = &MMU_MapPages;
+ psDeviceNode->pfnMMUMapShadow = &MMU_MapShadow;
+ psDeviceNode->pfnMMUUnmapPages = &MMU_UnmapPages;
+ psDeviceNode->pfnMMUMapScatter = &MMU_MapScatter;
+ psDeviceNode->pfnMMUGetPhysPageAddr = &MMU_GetPhysPageAddr;
+ psDeviceNode->pfnMMUGetPDDevPAddr = &MMU_GetPDDevPAddr;
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+ psDeviceNode->pfnMMUIsHeapShared = &MMU_IsHeapShared;
+#endif
+#if defined(FIX_HW_BRN_31620)
+ psDeviceNode->pfnMMUGetCacheFlushRange = &MMU_GetCacheFlushRange;
+ psDeviceNode->pfnMMUGetPDPhysAddr = &MMU_GetPDPhysAddr;
+#else
+ psDeviceNode->pfnMMUGetCacheFlushRange = IMG_NULL;
+ psDeviceNode->pfnMMUGetPDPhysAddr = IMG_NULL;
+#endif
+#if defined (SYS_USING_INTERRUPTS)
+
+
+ psDeviceNode->pfnDeviceISR = SGX_ISRHandler;
+ psDeviceNode->pfnDeviceMISR = SGX_MISRHandler;
+#endif
+
+#if defined(SUPPORT_MEMORY_TILING)
+ psDeviceNode->pfnAllocMemTilingRange = SGX_AllocMemTilingRange;
+ psDeviceNode->pfnFreeMemTilingRange = SGX_FreeMemTilingRange;
+#endif
+
+
+
+ psDeviceNode->pfnDeviceCommandComplete = &SGXCommandComplete;
+
+ psDeviceNode->pfnCacheInvalidate = SGXCacheInvalidate;
+
+
+
+ psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+
+ psDevMemoryInfo->ui32AddressSpaceSizeLog2 = SGX_FEATURE_ADDRESS_SPACE_SIZE;
+
+
+ psDevMemoryInfo->ui32Flags = 0;
+
+
+ if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(DEVICE_MEMORY_HEAP_INFO) * SGX_MAX_HEAP_ID,
+ (IMG_VOID **)&psDevMemoryInfo->psDeviceMemoryHeap, 0,
+ "Array of Device Memory Heap Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXRegisterDevice : Failed to alloc memory for DEVICE_MEMORY_HEAP_INFO"));
+ return (PVRSRV_ERROR_OUT_OF_MEMORY);
+ }
+ OSMemSet(psDevMemoryInfo->psDeviceMemoryHeap, 0, sizeof(DEVICE_MEMORY_HEAP_INFO) * SGX_MAX_HEAP_ID);
+
+ psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
+
+
+
+
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_GENERAL_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_GENERAL_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_GENERAL_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_SINGLE_PROCESS;
+ psDeviceMemoryHeap->pszName = "General";
+ psDeviceMemoryHeap->pszBSName = "General BS";
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+#if !defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+
+ psDevMemoryInfo->ui32MappingHeapID = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap);
+#endif
+ psDeviceMemoryHeap++;
+
+#if defined(SUPPORT_MEMORY_TILING)
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_VPB_TILED_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_VPB_TILED_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_VPB_TILED_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_SINGLE_PROCESS;
+ psDeviceMemoryHeap->pszName = "VPB Tiled";
+ psDeviceMemoryHeap->pszBSName = "VPB Tiled BS";
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap->ui32XTileStride = SGX_VPB_TILED_HEAP_STRIDE;
+ PVR_DPF((PVR_DBG_WARNING, "VPB tiling heap tiling stride = 0x%x", psDeviceMemoryHeap->ui32XTileStride));
+ psDeviceMemoryHeap++;
+#endif
+
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_TADATA_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_TADATA_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_TADATA_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_MULTI_PROCESS;
+ psDeviceMemoryHeap->pszName = "TA Data";
+ psDeviceMemoryHeap->pszBSName = "TA Data BS";
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap++;
+
+
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_KERNEL_CODE_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_KERNEL_CODE_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_KERNEL_CODE_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_MULTI_PROCESS;
+ psDeviceMemoryHeap->pszName = "Kernel Code";
+ psDeviceMemoryHeap->pszBSName = "Kernel Code BS";
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap++;
+
+
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_KERNEL_DATA_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_KERNEL_DATA_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_KERNEL_DATA_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_MULTI_PROCESS;
+ psDeviceMemoryHeap->pszName = "KernelData";
+ psDeviceMemoryHeap->pszBSName = "KernelData BS";
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap++;
+
+
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_PIXELSHADER_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_PIXELSHADER_HEAP_BASE;
+
+
+
+
+
+
+ psDeviceMemoryHeap->ui32HeapSize = ((10 << SGX_USE_CODE_SEGMENT_RANGE_BITS) - 0x00001000);
+ PVR_ASSERT(psDeviceMemoryHeap->ui32HeapSize <= SGX_PIXELSHADER_HEAP_SIZE);
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_SINGLE_PROCESS;
+ psDeviceMemoryHeap->pszName = "PixelShaderUSSE";
+ psDeviceMemoryHeap->pszBSName = "PixelShaderUSSE BS";
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap++;
+
+
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_VERTEXSHADER_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_VERTEXSHADER_HEAP_BASE;
+
+ psDeviceMemoryHeap->ui32HeapSize = ((4 << SGX_USE_CODE_SEGMENT_RANGE_BITS) - 0x00001000);
+ PVR_ASSERT(psDeviceMemoryHeap->ui32HeapSize <= SGX_VERTEXSHADER_HEAP_SIZE);
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_SINGLE_PROCESS;
+ psDeviceMemoryHeap->pszName = "VertexShaderUSSE";
+ psDeviceMemoryHeap->pszBSName = "VertexShaderUSSE BS";
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap++;
+
+
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_PDSPIXEL_CODEDATA_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_PDSPIXEL_CODEDATA_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_PDSPIXEL_CODEDATA_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_SINGLE_PROCESS;
+ psDeviceMemoryHeap->pszName = "PDSPixelCodeData";
+ psDeviceMemoryHeap->pszBSName = "PDSPixelCodeData BS";
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap++;
+
+
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_PDSVERTEX_CODEDATA_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_PDSVERTEX_CODEDATA_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_PDSVERTEX_CODEDATA_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_SINGLE_PROCESS;
+ psDeviceMemoryHeap->pszName = "PDSVertexCodeData";
+ psDeviceMemoryHeap->pszBSName = "PDSVertexCodeData BS";
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap++;
+
+
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_SYNCINFO_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_SYNCINFO_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_SYNCINFO_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_MULTI_PROCESS;
+ psDeviceMemoryHeap->pszName = "CacheCoherent";
+ psDeviceMemoryHeap->pszBSName = "CacheCoherent BS";
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+
+ psDevMemoryInfo->ui32SyncHeapID = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap);
+ psDeviceMemoryHeap++;
+
+
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_SHARED_3DPARAMETERS_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_SHARED_3DPARAMETERS_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_SHARED_3DPARAMETERS_HEAP_SIZE;
+ psDeviceMemoryHeap->pszName = "Shared 3DParameters";
+ psDeviceMemoryHeap->pszBSName = "Shared 3DParameters BS";
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_MULTI_PROCESS;
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap++;
+
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_PERCONTEXT_3DPARAMETERS_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_PERCONTEXT_3DPARAMETERS_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_PERCONTEXT_3DPARAMETERS_HEAP_SIZE;
+ psDeviceMemoryHeap->pszName = "Percontext 3DParameters";
+ psDeviceMemoryHeap->pszBSName = "Percontext 3DParameters BS";
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_SINGLE_PROCESS;
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap++;
+
+
+#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_GENERAL_MAPPING_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_GENERAL_MAPPING_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_GENERAL_MAPPING_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_MULTI_PROCESS;
+ psDeviceMemoryHeap->pszName = "GeneralMapping";
+ psDeviceMemoryHeap->pszBSName = "GeneralMapping BS";
+ #if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) && defined(FIX_HW_BRN_23410)
+
+
+
+
+
+
+
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+ #else
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+ #endif
+
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+
+ psDevMemoryInfo->ui32MappingHeapID = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap);
+ psDeviceMemoryHeap++;
+#endif
+
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_2D_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_2D_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_2D_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_SINGLE_PROCESS;
+ psDeviceMemoryHeap->pszName = "2D";
+ psDeviceMemoryHeap->pszBSName = "2D BS";
+
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap++;
+#endif
+
+
+#if defined(FIX_HW_BRN_26915)
+
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_CGBUFFER_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_CGBUFFER_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_CGBUFFER_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_SINGLE_PROCESS;
+ psDeviceMemoryHeap->pszName = "CGBuffer";
+ psDeviceMemoryHeap->pszBSName = "CGBuffer BS";
+
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap++;
+#endif
+
+
+ psDevMemoryInfo->ui32HeapCount = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap);
+
+ return PVRSRV_OK;
+}
+
+#if defined(PDUMP)
+static
+PVRSRV_ERROR SGXResetPDump(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)(psDeviceNode->pvDevice);
+ psDevInfo->psKernelCCBInfo->ui32CCBDumpWOff = 0;
+ PVR_DPF((PVR_DBG_MESSAGE, "Reset pdump CCB write offset."));
+
+ return PVRSRV_OK;
+}
+#endif
+
+
+IMG_EXPORT
+PVRSRV_ERROR SGXGetClientInfoKM(IMG_HANDLE hDevCookie,
+ SGX_CLIENT_INFO* psClientInfo)
+{
+ PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
+
+
+
+ psDevInfo->ui32ClientRefCount++;
+
+
+
+ psClientInfo->ui32ProcessID = OSGetCurrentProcessIDKM();
+
+
+
+ OSMemCopy(&psClientInfo->asDevData, &psDevInfo->asSGXDevData, sizeof(psClientInfo->asDevData));
+
+
+ return PVRSRV_OK;
+}
+
+
+IMG_VOID SGXPanic(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ PVR_LOG(("SGX panic"));
+ SGXDumpDebugInfo(psDevInfo, IMG_FALSE);
+ OSPanic();
+}
+
+
+PVRSRV_ERROR SGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+ IMG_UINT32 ui32BuildOptions, ui32BuildOptionsMismatch;
+#if !defined(NO_HARDWARE)
+ PPVRSRV_KERNEL_MEM_INFO psMemInfo;
+ PVRSRV_SGX_MISCINFO_INFO *psSGXMiscInfoInt;
+ PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
+ SGX_MISCINFO_STRUCT_SIZES *psSGXStructSizes;
+ IMG_BOOL bStructSizesFailed;
+
+
+ IMG_BOOL bCheckCoreRev;
+ const IMG_UINT32 aui32CoreRevExceptions[] =
+ {
+ 0x10100, 0x10101
+ };
+ const IMG_UINT32 ui32NumCoreExceptions = sizeof(aui32CoreRevExceptions) / (2*sizeof(IMG_UINT32));
+ IMG_UINT i;
+#endif
+
+
+ if(psDeviceNode->sDevId.eDeviceType != PVRSRV_DEVICE_TYPE_SGX)
+ {
+ PVR_LOG(("(FAIL) SGXInit: Device not of type SGX"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto chk_exit;
+ }
+
+ psDevInfo = psDeviceNode->pvDevice;
+
+
+
+ ui32BuildOptions = (SGX_BUILD_OPTIONS);
+ if (ui32BuildOptions != psDevInfo->ui32ClientBuildOptions)
+ {
+ ui32BuildOptionsMismatch = ui32BuildOptions ^ psDevInfo->ui32ClientBuildOptions;
+ if ( (psDevInfo->ui32ClientBuildOptions & ui32BuildOptionsMismatch) != 0)
+ {
+ PVR_LOG(("(FAIL) SGXInit: Mismatch in client-side and KM driver build options; "
+ "extra options present in client-side driver: (0x%x). Please check sgx_options.h",
+ psDevInfo->ui32ClientBuildOptions & ui32BuildOptionsMismatch ));
+ }
+
+ if ( (ui32BuildOptions & ui32BuildOptionsMismatch) != 0)
+ {
+ PVR_LOG(("(FAIL) SGXInit: Mismatch in client-side and KM driver build options; "
+ "extra options present in KM: (0x%x). Please check sgx_options.h",
+ ui32BuildOptions & ui32BuildOptionsMismatch ));
+ }
+ eError = PVRSRV_ERROR_BUILD_MISMATCH;
+ goto chk_exit;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "SGXInit: Client-side and KM driver build options match. [ OK ]"));
+ }
+
+#if !defined (NO_HARDWARE)
+ psMemInfo = psDevInfo->psKernelSGXMiscMemInfo;
+
+
+ psSGXMiscInfoInt = psMemInfo->pvLinAddrKM;
+ psSGXMiscInfoInt->ui32MiscInfoFlags = 0;
+ psSGXMiscInfoInt->ui32MiscInfoFlags |= PVRSRV_USSE_MISCINFO_GET_STRUCT_SIZES;
+ eError = SGXGetMiscInfoUkernel(psDevInfo, psDeviceNode, IMG_NULL);
+
+
+ if(eError != PVRSRV_OK)
+ {
+ PVR_LOG(("(FAIL) SGXInit: Unable to validate device DDK version"));
+ goto chk_exit;
+ }
+ psSGXFeatures = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXFeatures;
+ if( (psSGXFeatures->ui32DDKVersion !=
+ ((PVRVERSION_MAJ << 16) |
+ (PVRVERSION_MIN << 8) |
+ PVRVERSION_BRANCH) ) ||
+ (psSGXFeatures->ui32DDKBuild != PVRVERSION_BUILD) )
+ {
+ PVR_LOG(("(FAIL) SGXInit: Incompatible driver DDK revision (%d)/device DDK revision (%d).",
+ PVRVERSION_BUILD, psSGXFeatures->ui32DDKBuild));
+ eError = PVRSRV_ERROR_DDK_VERSION_MISMATCH;
+ goto chk_exit;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "SGXInit: driver DDK (%d) and device DDK (%d) match. [ OK ]",
+ PVRVERSION_BUILD, psSGXFeatures->ui32DDKBuild));
+ }
+
+
+ if (psSGXFeatures->ui32CoreRevSW == 0)
+ {
+
+
+ PVR_LOG(("SGXInit: HW core rev (%x) check skipped.",
+ psSGXFeatures->ui32CoreRev));
+ }
+ else
+ {
+
+ bCheckCoreRev = IMG_TRUE;
+ for(i=0; i<ui32NumCoreExceptions; i+=2)
+ {
+ if( (psSGXFeatures->ui32CoreRev==aui32CoreRevExceptions[i]) &&
+ (psSGXFeatures->ui32CoreRevSW==aui32CoreRevExceptions[i+1]) )
+ {
+ PVR_LOG(("SGXInit: HW core rev (%x), SW core rev (%x) check skipped.",
+ psSGXFeatures->ui32CoreRev,
+ psSGXFeatures->ui32CoreRevSW));
+ bCheckCoreRev = IMG_FALSE;
+ }
+ }
+
+ if (bCheckCoreRev)
+ {
+ if (psSGXFeatures->ui32CoreRev != psSGXFeatures->ui32CoreRevSW)
+ {
+ PVR_LOG(("(FAIL) SGXInit: Incompatible HW core rev (%x) and SW core rev (%x).",
+ psSGXFeatures->ui32CoreRev, psSGXFeatures->ui32CoreRevSW));
+ eError = PVRSRV_ERROR_BUILD_MISMATCH;
+ goto chk_exit;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "SGXInit: HW core rev (%x) and SW core rev (%x) match. [ OK ]",
+ psSGXFeatures->ui32CoreRev, psSGXFeatures->ui32CoreRevSW));
+ }
+ }
+ }
+
+
+ psSGXStructSizes = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXStructSizes;
+
+ bStructSizesFailed = IMG_FALSE;
+
+ CHECK_SIZE(HOST_CTL);
+ CHECK_SIZE(COMMAND);
+#if defined(SGX_FEATURE_2D_HARDWARE)
+ CHECK_SIZE(2DCMD);
+ CHECK_SIZE(2DCMD_SHARED);
+#endif
+ CHECK_SIZE(CMDTA);
+ CHECK_SIZE(CMDTA_SHARED);
+ CHECK_SIZE(TRANSFERCMD);
+ CHECK_SIZE(TRANSFERCMD_SHARED);
+
+ CHECK_SIZE(3DREGISTERS);
+ CHECK_SIZE(HWPBDESC);
+ CHECK_SIZE(HWRENDERCONTEXT);
+ CHECK_SIZE(HWRENDERDETAILS);
+ CHECK_SIZE(HWRTDATA);
+ CHECK_SIZE(HWRTDATASET);
+ CHECK_SIZE(HWTRANSFERCONTEXT);
+
+ if (bStructSizesFailed == IMG_TRUE)
+ {
+ PVR_LOG(("(FAIL) SGXInit: Mismatch in SGXMKIF structure sizes."));
+ eError = PVRSRV_ERROR_BUILD_MISMATCH;
+ goto chk_exit;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "SGXInit: SGXMKIF structure sizes match. [ OK ]"));
+ }
+
+
+ ui32BuildOptions = psSGXFeatures->ui32BuildOptions;
+ if (ui32BuildOptions != (SGX_BUILD_OPTIONS))
+ {
+ ui32BuildOptionsMismatch = ui32BuildOptions ^ (SGX_BUILD_OPTIONS);
+ if ( ((SGX_BUILD_OPTIONS) & ui32BuildOptionsMismatch) != 0)
+ {
+ PVR_LOG(("(FAIL) SGXInit: Mismatch in driver and microkernel build options; "
+ "extra options present in driver: (0x%x). Please check sgx_options.h",
+ (SGX_BUILD_OPTIONS) & ui32BuildOptionsMismatch ));
+ }
+
+ if ( (ui32BuildOptions & ui32BuildOptionsMismatch) != 0)
+ {
+ PVR_LOG(("(FAIL) SGXInit: Mismatch in driver and microkernel build options; "
+ "extra options present in microkernel: (0x%x). Please check sgx_options.h",
+ ui32BuildOptions & ui32BuildOptionsMismatch ));
+ }
+ eError = PVRSRV_ERROR_BUILD_MISMATCH;
+ goto chk_exit;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "SGXInit: Driver and microkernel build options match. [ OK ]"));
+ }
+#endif
+
+ eError = PVRSRV_OK;
+chk_exit:
+#if defined(IGNORE_SGX_INIT_COMPATIBILITY_CHECK)
+ return PVRSRV_OK;
+#else
+ return eError;
+#endif
+}
+
+static
+PVRSRV_ERROR SGXGetMiscInfoUkernel(PVRSRV_SGXDEV_INFO *psDevInfo,
+ PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_HANDLE hDevMemContext)
+{
+ PVRSRV_ERROR eError;
+ SGXMKIF_COMMAND sCommandData;
+ PVRSRV_SGX_MISCINFO_INFO *psSGXMiscInfoInt;
+ PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
+ SGX_MISCINFO_STRUCT_SIZES *psSGXStructSizes;
+
+ PPVRSRV_KERNEL_MEM_INFO psMemInfo = psDevInfo->psKernelSGXMiscMemInfo;
+
+ if (! psMemInfo->pvLinAddrKM)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoUkernel: Invalid address."));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ psSGXMiscInfoInt = psMemInfo->pvLinAddrKM;
+ psSGXFeatures = &psSGXMiscInfoInt->sSGXFeatures;
+ psSGXStructSizes = &psSGXMiscInfoInt->sSGXStructSizes;
+
+ psSGXMiscInfoInt->ui32MiscInfoFlags &= ~PVRSRV_USSE_MISCINFO_READY;
+
+
+ OSMemSet(psSGXFeatures, 0, sizeof(*psSGXFeatures));
+ OSMemSet(psSGXStructSizes, 0, sizeof(*psSGXStructSizes));
+
+
+ sCommandData.ui32Data[1] = psMemInfo->sDevVAddr.uiAddr;
+
+ PDUMPCOMMENT("Microkernel kick for SGXGetMiscInfo");
+ eError = SGXScheduleCCBCommandKM(psDeviceNode,
+ SGXMKIF_CMD_GETMISCINFO,
+ &sCommandData,
+ KERNEL_ID,
+ 0,
+ hDevMemContext,
+ IMG_FALSE);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoUkernel: SGXScheduleCCBCommandKM failed."));
+ return eError;
+ }
+
+
+#if !defined(NO_HARDWARE)
+ {
+ IMG_BOOL bExit;
+
+ bExit = IMG_FALSE;
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ if ((psSGXMiscInfoInt->ui32MiscInfoFlags & PVRSRV_USSE_MISCINFO_READY) != 0)
+ {
+ bExit = IMG_TRUE;
+ break;
+ }
+ } END_LOOP_UNTIL_TIMEOUT();
+
+
+ if (!bExit)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoUkernel: Timeout occurred waiting for misc info."));
+ return PVRSRV_ERROR_TIMEOUT;
+ }
+ }
+#endif
+
+ return PVRSRV_OK;
+}
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
+ SGX_MISC_INFO *psMiscInfo,
+ PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_HANDLE hDevMemContext)
+{
+ PVRSRV_ERROR eError;
+ PPVRSRV_KERNEL_MEM_INFO psMemInfo = psDevInfo->psKernelSGXMiscMemInfo;
+ IMG_UINT32 *pui32MiscInfoFlags = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->ui32MiscInfoFlags;
+
+
+ *pui32MiscInfoFlags = 0;
+
+#if !defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+ PVR_UNREFERENCED_PARAMETER(hDevMemContext);
+#endif
+
+ switch(psMiscInfo->eRequest)
+ {
+#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+ case SGX_MISC_INFO_REQUEST_SET_BREAKPOINT:
+ {
+ IMG_UINT32 ui32MaskDM;
+ IMG_UINT32 ui32CtrlWEnable;
+ IMG_UINT32 ui32CtrlREnable;
+ IMG_UINT32 ui32CtrlTrapEnable;
+ IMG_UINT32 ui32RegVal;
+ IMG_UINT32 ui32StartRegVal;
+ IMG_UINT32 ui32EndRegVal;
+ SGXMKIF_COMMAND sCommandData;
+
+
+ if(psMiscInfo->uData.sSGXBreakpointInfo.bBPEnable)
+ {
+
+ IMG_DEV_VIRTADDR sBPDevVAddr = psMiscInfo->uData.sSGXBreakpointInfo.sBPDevVAddr;
+ IMG_DEV_VIRTADDR sBPDevVAddrEnd = psMiscInfo->uData.sSGXBreakpointInfo.sBPDevVAddrEnd;
+
+
+ ui32StartRegVal = sBPDevVAddr.uiAddr & EUR_CR_BREAKPOINT0_START_ADDRESS_MASK;
+ ui32EndRegVal = sBPDevVAddrEnd.uiAddr & EUR_CR_BREAKPOINT0_END_ADDRESS_MASK;
+
+ ui32MaskDM = psMiscInfo->uData.sSGXBreakpointInfo.ui32DataMasterMask;
+ ui32CtrlWEnable = psMiscInfo->uData.sSGXBreakpointInfo.bWrite;
+ ui32CtrlREnable = psMiscInfo->uData.sSGXBreakpointInfo.bRead;
+ ui32CtrlTrapEnable = psMiscInfo->uData.sSGXBreakpointInfo.bTrapped;
+
+
+ ui32RegVal = ((ui32MaskDM<<EUR_CR_BREAKPOINT0_MASK_DM_SHIFT) & EUR_CR_BREAKPOINT0_MASK_DM_MASK) |
+ ((ui32CtrlWEnable<<EUR_CR_BREAKPOINT0_CTRL_WENABLE_SHIFT) & EUR_CR_BREAKPOINT0_CTRL_WENABLE_MASK) |
+ ((ui32CtrlREnable<<EUR_CR_BREAKPOINT0_CTRL_RENABLE_SHIFT) & EUR_CR_BREAKPOINT0_CTRL_RENABLE_MASK) |
+ ((ui32CtrlTrapEnable<<EUR_CR_BREAKPOINT0_CTRL_TRAPENABLE_SHIFT) & EUR_CR_BREAKPOINT0_CTRL_TRAPENABLE_MASK);
+ }
+ else
+ {
+
+ ui32RegVal = ui32StartRegVal = ui32EndRegVal = 0;
+ }
+
+
+ sCommandData.ui32Data[0] = psMiscInfo->uData.sSGXBreakpointInfo.ui32BPIndex;
+ sCommandData.ui32Data[1] = ui32StartRegVal;
+ sCommandData.ui32Data[2] = ui32EndRegVal;
+ sCommandData.ui32Data[3] = ui32RegVal;
+
+
+ psDevInfo->psSGXHostCtl->ui32BPSetClearSignal = 0;
+
+ PDUMPCOMMENT("Microkernel kick for setting a data breakpoint");
+ eError = SGXScheduleCCBCommandKM(psDeviceNode,
+ SGXMKIF_CMD_DATABREAKPOINT,
+ &sCommandData,
+ KERNEL_ID,
+ 0,
+ hDevMemContext,
+ IMG_FALSE);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoKM: SGXScheduleCCBCommandKM failed."));
+ return eError;
+ }
+
+#if defined(NO_HARDWARE)
+
+ psDevInfo->psSGXHostCtl->ui32BPSetClearSignal = 0;
+#else
+ {
+ IMG_BOOL bExit;
+
+ bExit = IMG_FALSE;
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ if (psDevInfo->psSGXHostCtl->ui32BPSetClearSignal != 0)
+ {
+ bExit = IMG_TRUE;
+
+ psDevInfo->psSGXHostCtl->ui32BPSetClearSignal = 0;
+ break;
+ }
+ } END_LOOP_UNTIL_TIMEOUT();
+
+
+ if (!bExit)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoKM: Timeout occurred waiting BP set/clear"));
+ return PVRSRV_ERROR_TIMEOUT;
+ }
+ }
+#endif
+
+ return PVRSRV_OK;
+ }
+
+ case SGX_MISC_INFO_REQUEST_POLL_BREAKPOINT:
+ {
+
+
+
+
+
+
+
+#if !defined(NO_HARDWARE)
+#if defined(SGX_FEATURE_MP)
+ IMG_BOOL bTrappedBPMaster;
+ IMG_UINT32 ui32CoreNum, ui32TrappedBPCoreNum;
+#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
+ IMG_UINT32 ui32PipeNum, ui32TrappedBPPipeNum;
+#define NUM_PIPES_PLUS_ONE (SGX_FEATURE_PERPIPE_BKPT_REGS_NUMPIPES+1)
+#endif
+ IMG_BOOL bTrappedBPAny;
+#endif
+ IMG_BOOL bFoundOne;
+
+#if defined(SGX_FEATURE_MP)
+ ui32TrappedBPCoreNum = 0;
+ bTrappedBPMaster = !!(EUR_CR_MASTER_BREAKPOINT_TRAPPED_MASK & OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BREAKPOINT));
+ bTrappedBPAny = bTrappedBPMaster;
+#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
+ ui32TrappedBPPipeNum = 0;
+#endif
+ for (ui32CoreNum = 0; ui32CoreNum < SGX_FEATURE_MP_CORE_COUNT_3D; ui32CoreNum++)
+ {
+#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
+
+
+
+#define SGX_MP_CORE_PIPE_SELECT(r,c,p) \
+ ((SGX_MP_CORE_SELECT(EUR_CR_PARTITION_##r,c) + p*(EUR_CR_PIPE0_##r-EUR_CR_PARTITION_##r)))
+ for (ui32PipeNum = 0; ui32PipeNum < NUM_PIPES_PLUS_ONE; ui32PipeNum++)
+ {
+ bFoundOne =
+ 0 != (EUR_CR_PARTITION_BREAKPOINT_TRAPPED_MASK &
+ OSReadHWReg(psDevInfo->pvRegsBaseKM,
+ SGX_MP_CORE_PIPE_SELECT(BREAKPOINT,
+ ui32CoreNum,
+ ui32PipeNum)));
+ if (bFoundOne)
+ {
+ bTrappedBPAny = IMG_TRUE;
+ ui32TrappedBPCoreNum = ui32CoreNum;
+ ui32TrappedBPPipeNum = ui32PipeNum;
+ }
+ }
+#else
+ bFoundOne = !!(EUR_CR_BREAKPOINT_TRAPPED_MASK & OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT, ui32CoreNum)));
+ if (bFoundOne)
+ {
+ bTrappedBPAny = IMG_TRUE;
+ ui32TrappedBPCoreNum = ui32CoreNum;
+ }
+#endif
+ }
+
+ psMiscInfo->uData.sSGXBreakpointInfo.bTrappedBP = bTrappedBPAny;
+#else
+#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
+ #error Not yet considered the case for per-pipe regs in non-mp case
+#endif
+ psMiscInfo->uData.sSGXBreakpointInfo.bTrappedBP = 0 != (EUR_CR_BREAKPOINT_TRAPPED_MASK & OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BREAKPOINT));
+#endif
+
+ if (psMiscInfo->uData.sSGXBreakpointInfo.bTrappedBP)
+ {
+ IMG_UINT32 ui32Info0, ui32Info1;
+
+#if defined(SGX_FEATURE_MP)
+#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
+ ui32Info0 = OSReadHWReg(psDevInfo->pvRegsBaseKM, bTrappedBPMaster?EUR_CR_MASTER_BREAKPOINT_TRAP_INFO0:SGX_MP_CORE_PIPE_SELECT(BREAKPOINT_TRAP_INFO0, ui32TrappedBPCoreNum, ui32TrappedBPPipeNum));
+ ui32Info1 = OSReadHWReg(psDevInfo->pvRegsBaseKM, bTrappedBPMaster?EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1:SGX_MP_CORE_PIPE_SELECT(BREAKPOINT_TRAP_INFO1, ui32TrappedBPCoreNum, ui32TrappedBPPipeNum));
+#else
+ ui32Info0 = OSReadHWReg(psDevInfo->pvRegsBaseKM, bTrappedBPMaster?EUR_CR_MASTER_BREAKPOINT_TRAP_INFO0:SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT_TRAP_INFO0, ui32TrappedBPCoreNum));
+ ui32Info1 = OSReadHWReg(psDevInfo->pvRegsBaseKM, bTrappedBPMaster?EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1:SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT_TRAP_INFO1, ui32TrappedBPCoreNum));
+#endif
+#else
+ ui32Info0 = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BREAKPOINT_TRAP_INFO0);
+ ui32Info1 = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BREAKPOINT_TRAP_INFO1);
+#endif
+
+#ifdef SGX_FEATURE_PERPIPE_BKPT_REGS
+ psMiscInfo->uData.sSGXBreakpointInfo.ui32BPIndex = (ui32Info1 & EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_NUMBER_MASK) >> EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_NUMBER_SHIFT;
+ psMiscInfo->uData.sSGXBreakpointInfo.sTrappedBPDevVAddr.uiAddr = ui32Info0 & EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO0_ADDRESS_MASK;
+ psMiscInfo->uData.sSGXBreakpointInfo.ui32TrappedBPBurstLength = (ui32Info1 & EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_SIZE_MASK) >> EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_SIZE_SHIFT;
+ psMiscInfo->uData.sSGXBreakpointInfo.bTrappedBPRead = !!(ui32Info1 & EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_RNW_MASK);
+ psMiscInfo->uData.sSGXBreakpointInfo.ui32TrappedBPDataMaster = (ui32Info1 & EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_DATA_MASTER_MASK) >> EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_DATA_MASTER_SHIFT;
+ psMiscInfo->uData.sSGXBreakpointInfo.ui32TrappedBPTag = (ui32Info1 & EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_TAG_MASK) >> EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_TAG_SHIFT;
+#else
+ psMiscInfo->uData.sSGXBreakpointInfo.ui32BPIndex = (ui32Info1 & EUR_CR_BREAKPOINT_TRAP_INFO1_NUMBER_MASK) >> EUR_CR_BREAKPOINT_TRAP_INFO1_NUMBER_SHIFT;
+ psMiscInfo->uData.sSGXBreakpointInfo.sTrappedBPDevVAddr.uiAddr = ui32Info0 & EUR_CR_BREAKPOINT_TRAP_INFO0_ADDRESS_MASK;
+ psMiscInfo->uData.sSGXBreakpointInfo.ui32TrappedBPBurstLength = (ui32Info1 & EUR_CR_BREAKPOINT_TRAP_INFO1_SIZE_MASK) >> EUR_CR_BREAKPOINT_TRAP_INFO1_SIZE_SHIFT;
+ psMiscInfo->uData.sSGXBreakpointInfo.bTrappedBPRead = !!(ui32Info1 & EUR_CR_BREAKPOINT_TRAP_INFO1_RNW_MASK);
+ psMiscInfo->uData.sSGXBreakpointInfo.ui32TrappedBPDataMaster = (ui32Info1 & EUR_CR_BREAKPOINT_TRAP_INFO1_DATA_MASTER_MASK) >> EUR_CR_BREAKPOINT_TRAP_INFO1_DATA_MASTER_SHIFT;
+ psMiscInfo->uData.sSGXBreakpointInfo.ui32TrappedBPTag = (ui32Info1 & EUR_CR_BREAKPOINT_TRAP_INFO1_TAG_MASK) >> EUR_CR_BREAKPOINT_TRAP_INFO1_TAG_SHIFT;
+#endif
+#if defined(SGX_FEATURE_MP)
+#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
+
+ psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum = bTrappedBPMaster?65535:(ui32TrappedBPCoreNum + (ui32TrappedBPPipeNum<<10));
+#else
+
+ psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum = bTrappedBPMaster?65535:ui32TrappedBPCoreNum;
+#endif
+#else
+#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
+
+#error non-mp perpipe regs not yet supported
+#else
+
+ psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum = 65534;
+#endif
+#endif
+ }
+#endif
+ return PVRSRV_OK;
+ }
+
+ case SGX_MISC_INFO_REQUEST_RESUME_BREAKPOINT:
+ {
+
+
+
+#if !defined(NO_HARDWARE)
+#if defined(SGX_FEATURE_MP)
+ IMG_UINT32 ui32CoreNum;
+ IMG_BOOL bMaster;
+#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
+ IMG_UINT32 ui32PipeNum;
+#endif
+#endif
+ IMG_UINT32 ui32OldSeqNum, ui32NewSeqNum;
+
+#if defined(SGX_FEATURE_MP)
+#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
+ ui32PipeNum = psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum >> 10;
+ ui32CoreNum = psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum & 1023;
+ bMaster = psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum > 32767;
+#else
+ ui32CoreNum = psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum;
+ bMaster = ui32CoreNum > SGX_FEATURE_MP_CORE_COUNT_3D;
+#endif
+ if (bMaster)
+ {
+
+
+ ui32OldSeqNum = 0x1c & OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BREAKPOINT);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BREAKPOINT_TRAP, EUR_CR_MASTER_BREAKPOINT_TRAP_WRNOTIFY_MASK | EUR_CR_MASTER_BREAKPOINT_TRAP_CONTINUE_MASK);
+ do
+ {
+ ui32NewSeqNum = 0x1c & OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BREAKPOINT);
+ }
+ while (ui32OldSeqNum == ui32NewSeqNum);
+ }
+ else
+#endif
+ {
+
+#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
+ ui32OldSeqNum = 0x1c & OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_PIPE_SELECT(BREAKPOINT, ui32CoreNum, ui32PipeNum));
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_PIPE_SELECT(BREAKPOINT_TRAP, ui32CoreNum, ui32PipeNum), EUR_CR_PARTITION_BREAKPOINT_TRAP_WRNOTIFY_MASK | EUR_CR_PARTITION_BREAKPOINT_TRAP_CONTINUE_MASK);
+ do
+ {
+ ui32NewSeqNum = 0x1c & OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_PIPE_SELECT(BREAKPOINT, ui32CoreNum, ui32PipeNum));
+ }
+ while (ui32OldSeqNum == ui32NewSeqNum);
+#else
+ ui32OldSeqNum = 0x1c & OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT, ui32CoreNum));
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT_TRAP, ui32CoreNum), EUR_CR_BREAKPOINT_TRAP_WRNOTIFY_MASK | EUR_CR_BREAKPOINT_TRAP_CONTINUE_MASK);
+ do
+ {
+ ui32NewSeqNum = 0x1c & OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT, ui32CoreNum));
+ }
+ while (ui32OldSeqNum == ui32NewSeqNum);
+#endif
+ }
+#endif
+ return PVRSRV_OK;
+ }
+#endif
+
+ case SGX_MISC_INFO_REQUEST_CLOCKSPEED:
+ {
+ psMiscInfo->uData.ui32SGXClockSpeed = psDevInfo->ui32CoreClockSpeed;
+ return PVRSRV_OK;
+ }
+
+ case SGX_MISC_INFO_REQUEST_ACTIVEPOWER:
+ {
+ psMiscInfo->uData.sActivePower.ui32NumActivePowerEvents = psDevInfo->psSGXHostCtl->ui32NumActivePowerEvents;
+ return PVRSRV_OK;
+ }
+
+ case SGX_MISC_INFO_REQUEST_LOCKUPS:
+ {
+#if defined(SUPPORT_HW_RECOVERY)
+ psMiscInfo->uData.sLockups.ui32uKernelDetectedLockups = psDevInfo->psSGXHostCtl->ui32uKernelDetectedLockups;
+ psMiscInfo->uData.sLockups.ui32HostDetectedLockups = psDevInfo->psSGXHostCtl->ui32HostDetectedLockups;
+#else
+ psMiscInfo->uData.sLockups.ui32uKernelDetectedLockups = 0;
+ psMiscInfo->uData.sLockups.ui32HostDetectedLockups = 0;
+#endif
+ return PVRSRV_OK;
+ }
+
+ case SGX_MISC_INFO_REQUEST_SPM:
+ {
+
+ return PVRSRV_OK;
+ }
+
+ case SGX_MISC_INFO_REQUEST_SGXREV:
+ {
+ PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
+ eError = SGXGetMiscInfoUkernel(psDevInfo, psDeviceNode, hDevMemContext);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "An error occurred in SGXGetMiscInfoUkernel: %d\n",
+ eError));
+ return eError;
+ }
+ psSGXFeatures = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXFeatures;
+
+
+ psMiscInfo->uData.sSGXFeatures = *psSGXFeatures;
+
+
+ PVR_DPF((PVR_DBG_MESSAGE, "SGXGetMiscInfoKM: Core 0x%x, sw ID 0x%x, sw Rev 0x%x\n",
+ psSGXFeatures->ui32CoreRev,
+ psSGXFeatures->ui32CoreIdSW,
+ psSGXFeatures->ui32CoreRevSW));
+ PVR_DPF((PVR_DBG_MESSAGE, "SGXGetMiscInfoKM: DDK version 0x%x, DDK build 0x%x\n",
+ psSGXFeatures->ui32DDKVersion,
+ psSGXFeatures->ui32DDKBuild));
+
+
+ return PVRSRV_OK;
+ }
+
+ case SGX_MISC_INFO_REQUEST_DRIVER_SGXREV:
+ {
+ PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
+
+ psSGXFeatures = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXFeatures;
+
+
+ OSMemSet(psMemInfo->pvLinAddrKM, 0,
+ sizeof(PVRSRV_SGX_MISCINFO_INFO));
+
+ psSGXFeatures->ui32DDKVersion =
+ (PVRVERSION_MAJ << 16) |
+ (PVRVERSION_MIN << 8) |
+ PVRVERSION_BRANCH;
+ psSGXFeatures->ui32DDKBuild = PVRVERSION_BUILD;
+
+
+ psSGXFeatures->ui32BuildOptions = (SGX_BUILD_OPTIONS);
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+
+ psSGXFeatures->sDevVAEDMStatusBuffer = psDevInfo->psKernelEDMStatusBufferMemInfo->sDevVAddr;
+ psSGXFeatures->pvEDMStatusBuffer = psDevInfo->psKernelEDMStatusBufferMemInfo->pvLinAddrKM;
+#endif
+
+
+ psMiscInfo->uData.sSGXFeatures = *psSGXFeatures;
+ return PVRSRV_OK;
+ }
+
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+ case SGX_MISC_INFO_REQUEST_MEMREAD:
+ case SGX_MISC_INFO_REQUEST_MEMCOPY:
+ {
+ PVRSRV_ERROR eError;
+ PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
+ PVRSRV_SGX_MISCINFO_MEMACCESS *psSGXMemSrc;
+ PVRSRV_SGX_MISCINFO_MEMACCESS *psSGXMemDest;
+
+ {
+
+ *pui32MiscInfoFlags |= PVRSRV_USSE_MISCINFO_MEMREAD;
+ psSGXMemSrc = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXMemAccessSrc;
+
+ if(psMiscInfo->sDevVAddrSrc.uiAddr != 0)
+ {
+ psSGXMemSrc->sDevVAddr = psMiscInfo->sDevVAddrSrc;
+ }
+ else
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ }
+
+ if( psMiscInfo->eRequest == SGX_MISC_INFO_REQUEST_MEMCOPY)
+ {
+
+ *pui32MiscInfoFlags |= PVRSRV_USSE_MISCINFO_MEMWRITE;
+ psSGXMemDest = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXMemAccessDest;
+
+ if(psMiscInfo->sDevVAddrDest.uiAddr != 0)
+ {
+ psSGXMemDest->sDevVAddr = psMiscInfo->sDevVAddrDest;
+ }
+ else
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ }
+
+
+ if(psMiscInfo->hDevMemContext != IMG_NULL)
+ {
+ SGXGetMMUPDAddrKM( (IMG_HANDLE)psDeviceNode, hDevMemContext, &psSGXMemSrc->sPDDevPAddr);
+
+
+ psSGXMemDest->sPDDevPAddr = psSGXMemSrc->sPDDevPAddr;
+ }
+ else
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ eError = SGXGetMiscInfoUkernel(psDevInfo, psDeviceNode);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "An error occurred in SGXGetMiscInfoUkernel: %d\n",
+ eError));
+ return eError;
+ }
+ psSGXFeatures = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXFeatures;
+
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+ if(*pui32MiscInfoFlags & PVRSRV_USSE_MISCINFO_MEMREAD_FAIL)
+ {
+ return PVRSRV_ERROR_INVALID_MISCINFO;
+ }
+#endif
+
+ psMiscInfo->uData.sSGXFeatures = *psSGXFeatures;
+ return PVRSRV_OK;
+ }
+#endif
+
+#if defined(SUPPORT_SGX_HWPERF)
+ case SGX_MISC_INFO_REQUEST_SET_HWPERF_STATUS:
+ {
+ PVRSRV_SGX_MISCINFO_SET_HWPERF_STATUS *psSetHWPerfStatus = &psMiscInfo->uData.sSetHWPerfStatus;
+ const IMG_UINT32 ui32ValidFlags = PVRSRV_SGX_HWPERF_STATUS_RESET_COUNTERS |
+ PVRSRV_SGX_HWPERF_STATUS_GRAPHICS_ON |
+ PVRSRV_SGX_HWPERF_STATUS_PERIODIC_ON |
+ PVRSRV_SGX_HWPERF_STATUS_MK_EXECUTION_ON;
+ SGXMKIF_COMMAND sCommandData = {0};
+
+
+ if ((psSetHWPerfStatus->ui32NewHWPerfStatus & ~ui32ValidFlags) != 0)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ #if defined(PDUMP)
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+ "SGX ukernel HWPerf status %u\n",
+ psSetHWPerfStatus->ui32NewHWPerfStatus);
+ #endif
+
+
+ #if defined(SGX_FEATURE_EXTENDED_PERF_COUNTERS)
+ OSMemCopy(&psDevInfo->psSGXHostCtl->aui32PerfGroup[0],
+ &psSetHWPerfStatus->aui32PerfGroup[0],
+ sizeof(psDevInfo->psSGXHostCtl->aui32PerfGroup));
+ OSMemCopy(&psDevInfo->psSGXHostCtl->aui32PerfBit[0],
+ &psSetHWPerfStatus->aui32PerfBit[0],
+ sizeof(psDevInfo->psSGXHostCtl->aui32PerfBit));
+ #if defined(PDUMP)
+ PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+ offsetof(SGXMKIF_HOST_CTL, aui32PerfGroup),
+ sizeof(psDevInfo->psSGXHostCtl->aui32PerfGroup),
+ PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+ PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+ offsetof(SGXMKIF_HOST_CTL, aui32PerfBit),
+ sizeof(psDevInfo->psSGXHostCtl->aui32PerfBit),
+ PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+ #endif
+ #else
+ psDevInfo->psSGXHostCtl->ui32PerfGroup = psSetHWPerfStatus->ui32PerfGroup;
+ #if defined(PDUMP)
+ PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+ offsetof(SGXMKIF_HOST_CTL, ui32PerfGroup),
+ sizeof(psDevInfo->psSGXHostCtl->ui32PerfGroup),
+ PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+ #endif
+ #endif
+
+
+ sCommandData.ui32Data[0] = psSetHWPerfStatus->ui32NewHWPerfStatus;
+ eError = SGXScheduleCCBCommandKM(psDeviceNode,
+ SGXMKIF_CMD_SETHWPERFSTATUS,
+ &sCommandData,
+ KERNEL_ID,
+ 0,
+ hDevMemContext,
+ IMG_FALSE);
+ return eError;
+ }
+#endif
+
+ case SGX_MISC_INFO_DUMP_DEBUG_INFO:
+ {
+ PVR_LOG(("User requested SGX debug info"));
+
+
+ SGXDumpDebugInfo(psDeviceNode->pvDevice, IMG_FALSE);
+
+ return PVRSRV_OK;
+ }
+
+#if defined(DEBUG)
+
+ case SGX_MISC_INFO_PANIC:
+ {
+ PVR_LOG(("User requested SGX panic"));
+
+ SGXPanic(psDeviceNode->pvDevice);
+
+ return PVRSRV_OK;
+ }
+#endif
+
+ default:
+ {
+
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ }
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR SGXReadHWPerfCBKM(IMG_HANDLE hDevHandle,
+ IMG_UINT32 ui32ArraySize,
+ PVRSRV_SGX_HWPERF_CB_ENTRY *psClientHWPerfEntry,
+ IMG_UINT32 *pui32DataCount,
+ IMG_UINT32 *pui32ClockSpeed,
+ IMG_UINT32 *pui32HostTimeStamp)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ SGXMKIF_HWPERF_CB *psHWPerfCB = psDevInfo->psKernelHWPerfCBMemInfo->pvLinAddrKM;
+ IMG_UINT i;
+
+ for (i = 0;
+ psHWPerfCB->ui32Woff != psHWPerfCB->ui32Roff && i < ui32ArraySize;
+ i++)
+ {
+ SGXMKIF_HWPERF_CB_ENTRY *psMKPerfEntry = &psHWPerfCB->psHWPerfCBData[psHWPerfCB->ui32Roff];
+
+ psClientHWPerfEntry[i].ui32FrameNo = psMKPerfEntry->ui32FrameNo;
+ psClientHWPerfEntry[i].ui32PID = psMKPerfEntry->ui32PID;
+ psClientHWPerfEntry[i].ui32RTData = psMKPerfEntry->ui32RTData;
+ psClientHWPerfEntry[i].ui32Type = psMKPerfEntry->ui32Type;
+ psClientHWPerfEntry[i].ui32Ordinal = psMKPerfEntry->ui32Ordinal;
+ psClientHWPerfEntry[i].ui32Info = psMKPerfEntry->ui32Info;
+ psClientHWPerfEntry[i].ui32Clocksx16 = SGXConvertTimeStamp(psDevInfo,
+ psMKPerfEntry->ui32TimeWraps,
+ psMKPerfEntry->ui32Time);
+ OSMemCopy(&psClientHWPerfEntry[i].ui32Counters[0][0],
+ &psMKPerfEntry->ui32Counters[0][0],
+ sizeof(psMKPerfEntry->ui32Counters));
+
+ OSMemCopy(&psClientHWPerfEntry[i].ui32MiscCounters[0][0],
+ &psMKPerfEntry->ui32MiscCounters[0][0],
+ sizeof(psMKPerfEntry->ui32MiscCounters));
+
+ psHWPerfCB->ui32Roff = (psHWPerfCB->ui32Roff + 1) & (SGXMKIF_HWPERF_CB_SIZE - 1);
+ }
+
+ *pui32DataCount = i;
+ *pui32ClockSpeed = psDevInfo->ui32CoreClockSpeed;
+ *pui32HostTimeStamp = OSClockus();
+
+ return eError;
+}
+
+
diff --git a/drivers/gpu/pvr/sgx/sgxkick.c b/drivers/gpu/pvr/sgx/sgxkick.c
new file mode 100644
index 0000000..d5441b2
--- /dev/null
+++ b/drivers/gpu/pvr/sgx/sgxkick.c
@@ -0,0 +1,808 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include <stddef.h>
+#include "services_headers.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+#if defined (PDUMP)
+#include "sgxapi_km.h"
+#include "pdump_km.h"
+#endif
+#include "sgx_bridge_km.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+#include "sgxutils.h"
+#include "ttrace.h"
+
+IMG_EXPORT
+#if defined (SUPPORT_SID_INTERFACE)
+PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK_KM *psCCBKick)
+#else
+PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
+#endif
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+ PVRSRV_KERNEL_MEM_INFO *psCCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *) psCCBKick->hCCBKernelMemInfo;
+ SGXMKIF_CMDTA_SHARED *psTACmd;
+ IMG_UINT32 i;
+ IMG_HANDLE hDevMemContext = IMG_NULL;
+#if defined(FIX_HW_BRN_31620)
+ hDevMemContext = psCCBKick->hDevMemContext;
+#endif
+ PVR_TTRACE(PVRSRV_TRACE_GROUP_KICK, PVRSRV_TRACE_CLASS_FUNCTION_ENTER, KICK_TOKEN_DOKICK);
+
+ if (!CCB_OFFSET_IS_VALID(SGXMKIF_CMDTA_SHARED, psCCBMemInfo, psCCBKick, ui32CCBOffset))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXDoKickKM: Invalid CCB offset"));
+ PVR_TTRACE(PVRSRV_TRACE_GROUP_KICK, PVRSRV_TRACE_CLASS_FUNCTION_EXIT, KICK_TOKEN_DOKICK);
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ psTACmd = CCB_DATA_FROM_OFFSET(SGXMKIF_CMDTA_SHARED, psCCBMemInfo, psCCBKick, ui32CCBOffset);
+
+ PVR_TTRACE(PVRSRV_TRACE_GROUP_KICK, PVRSRV_TRACE_CLASS_CMD_START, KICK_TOKEN_DOKICK);
+ PVR_TTRACE_UI32(PVRSRV_TRACE_GROUP_KICK, PVRSRV_TRACE_CLASS_CCB,
+ KICK_TOKEN_CCB_OFFSET, psCCBKick->ui32CCBOffset);
+
+
+ if (psCCBKick->hTA3DSyncInfo)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTA3DSyncInfo;
+
+ PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_KICK, KICK_TOKEN_TA3D_SYNC,
+ psSyncInfo, PVRSRV_SYNCOP_SAMPLE);
+
+ psTACmd->sTA3DDependency.sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+
+ psTACmd->sTA3DDependency.ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+
+ if (psCCBKick->bTADependency)
+ {
+ psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ }
+ }
+
+ if (psCCBKick->hTASyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTASyncInfo;
+
+ PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_KICK, KICK_TOKEN_TA_SYNC,
+ psSyncInfo, PVRSRV_SYNCOP_SAMPLE);
+
+ psTACmd->sTATQSyncReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ psTACmd->sTATQSyncWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+
+ psTACmd->ui32TATQSyncReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending++;
+ psTACmd->ui32TATQSyncWriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+
+ if (psCCBKick->h3DSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->h3DSyncInfo;
+
+ PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_KICK, KICK_TOKEN_3D_SYNC,
+ psSyncInfo, PVRSRV_SYNCOP_SAMPLE);
+
+ psTACmd->s3DTQSyncReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ psTACmd->s3DTQSyncWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+
+ psTACmd->ui323DTQSyncReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending++;
+ psTACmd->ui323DTQSyncWriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+
+ psTACmd->ui32NumTAStatusVals = psCCBKick->ui32NumTAStatusVals;
+ if (psCCBKick->ui32NumTAStatusVals != 0)
+ {
+
+ for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++)
+ {
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ psTACmd->sCtlTAStatusInfo[i] = psCCBKick->asTAStatusUpdate[i].sCtlStatus;
+#else
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ahTAStatusSyncInfo[i];
+ psTACmd->sCtlTAStatusInfo[i].sStatusDevAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ psTACmd->sCtlTAStatusInfo[i].ui32StatusValue = psSyncInfo->psSyncData->ui32ReadOpsPending;
+#endif
+ }
+ }
+
+ psTACmd->ui32Num3DStatusVals = psCCBKick->ui32Num3DStatusVals;
+ if (psCCBKick->ui32Num3DStatusVals != 0)
+ {
+
+ for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++)
+ {
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ psTACmd->sCtl3DStatusInfo[i] = psCCBKick->as3DStatusUpdate[i].sCtlStatus;
+#else
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ah3DStatusSyncInfo[i];
+ psTACmd->sCtl3DStatusInfo[i].sStatusDevAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ psTACmd->sCtl3DStatusInfo[i].ui32StatusValue = psSyncInfo->psSyncData->ui32ReadOpsPending;
+#endif
+ }
+ }
+
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+
+ psTACmd->ui32NumTASrcSyncs = psCCBKick->ui32NumTASrcSyncs;
+ for (i=0; i<psCCBKick->ui32NumTASrcSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTASrcKernelSyncInfo[i];
+
+ psTACmd->asTASrcSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psTACmd->asTASrcSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+
+ psTACmd->asTASrcSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending++;
+
+ psTACmd->asTASrcSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+
+ psTACmd->ui32NumTADstSyncs = psCCBKick->ui32NumTADstSyncs;
+ for (i=0; i<psCCBKick->ui32NumTADstSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTADstKernelSyncInfo[i];
+
+ psTACmd->asTADstSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psTACmd->asTADstSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+
+ psTACmd->asTADstSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+ psTACmd->asTADstSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ }
+
+ psTACmd->ui32Num3DSrcSyncs = psCCBKick->ui32Num3DSrcSyncs;
+ for (i=0; i<psCCBKick->ui32Num3DSrcSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ah3DSrcKernelSyncInfo[i];
+
+ psTACmd->as3DSrcSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psTACmd->as3DSrcSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+
+ psTACmd->as3DSrcSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending++;
+
+ psTACmd->as3DSrcSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+#else
+
+ psTACmd->ui32NumSrcSyncs = psCCBKick->ui32NumSrcSyncs;
+ for (i=0; i<psCCBKick->ui32NumSrcSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahSrcKernelSyncInfo[i];
+
+ PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_KICK, KICK_TOKEN_SRC_SYNC,
+ psSyncInfo, PVRSRV_SYNCOP_SAMPLE);
+
+ psTACmd->asSrcSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psTACmd->asSrcSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+
+ psTACmd->asSrcSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending++;
+
+ psTACmd->asSrcSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+#endif
+
+ if (psCCBKick->bFirstKickOrResume && psCCBKick->ui32NumDstSyncObjects > 0)
+ {
+ PVRSRV_KERNEL_MEM_INFO *psHWDstSyncListMemInfo =
+ (PVRSRV_KERNEL_MEM_INFO *)psCCBKick->hKernelHWSyncListMemInfo;
+ SGXMKIF_HWDEVICE_SYNC_LIST *psHWDeviceSyncList = psHWDstSyncListMemInfo->pvLinAddrKM;
+ IMG_UINT32 ui32NumDstSyncs = psCCBKick->ui32NumDstSyncObjects;
+
+ PVR_ASSERT(((PVRSRV_KERNEL_MEM_INFO *)psCCBKick->hKernelHWSyncListMemInfo)->uAllocSize >= (sizeof(SGXMKIF_HWDEVICE_SYNC_LIST) +
+ (sizeof(PVRSRV_DEVICE_SYNC_OBJECT) * ui32NumDstSyncs)));
+
+ psHWDeviceSyncList->ui32NumSyncObjects = ui32NumDstSyncs;
+#if defined(PDUMP)
+ if (PDumpIsCaptureFrameKM())
+ {
+ PDUMPCOMMENT("HWDeviceSyncList for TACmd\r\n");
+ PDUMPMEM(IMG_NULL,
+ psHWDstSyncListMemInfo,
+ 0,
+ sizeof(SGXMKIF_HWDEVICE_SYNC_LIST),
+ 0,
+ MAKEUNIQUETAG(psHWDstSyncListMemInfo));
+ }
+#endif
+
+ for (i=0; i<ui32NumDstSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->pahDstSyncHandles[i];
+
+ if (psSyncInfo)
+ {
+ psSyncInfo->psSyncData->ui64LastWrite = ui64KickCount;
+
+ PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_KICK, KICK_TOKEN_DST_SYNC,
+ psSyncInfo, PVRSRV_SYNCOP_SAMPLE);
+
+ psHWDeviceSyncList->asSyncData[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psHWDeviceSyncList->asSyncData[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ psHWDeviceSyncList->asSyncData[i].sReadOps2CompleteDevVAddr = psSyncInfo->sReadOps2CompleteDevVAddr;
+
+ psHWDeviceSyncList->asSyncData[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ psHWDeviceSyncList->asSyncData[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ psHWDeviceSyncList->asSyncData[i].ui32ReadOps2PendingVal = psSyncInfo->psSyncData->ui32ReadOps2Pending;
+
+ #if defined(PDUMP)
+ if (PDumpIsCaptureFrameKM())
+ {
+ IMG_UINT32 ui32ModifiedValue;
+ IMG_UINT32 ui32SyncOffset = offsetof(SGXMKIF_HWDEVICE_SYNC_LIST, asSyncData)
+ + (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT));
+ IMG_UINT32 ui32WOpsOffset = ui32SyncOffset
+ + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal);
+ IMG_UINT32 ui32ROpsOffset = ui32SyncOffset
+ + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal);
+ IMG_UINT32 ui32ROps2Offset = ui32SyncOffset
+ + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOps2PendingVal);
+
+ PDUMPCOMMENT("HWDeviceSyncObject for RT: %i\r\n", i);
+
+ PDUMPMEM(IMG_NULL,
+ psHWDstSyncListMemInfo,
+ ui32SyncOffset,
+ sizeof(PVRSRV_DEVICE_SYNC_OBJECT),
+ 0,
+ MAKEUNIQUETAG(psHWDstSyncListMemInfo));
+
+ if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
+ (psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0))
+ {
+
+ PDUMPCOMMENT("Init RT ROpsComplete\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete),
+ sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete),
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+
+ PDUMPCOMMENT("Init RT WOpsComplete\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete),
+ sizeof(psSyncInfo->psSyncData->ui32WriteOpsComplete),
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+ }
+
+ psSyncInfo->psSyncData->ui32LastOpDumpVal++;
+
+ ui32ModifiedValue = psSyncInfo->psSyncData->ui32LastOpDumpVal - 1;
+
+ PDUMPCOMMENT("Modify RT %d WOpPendingVal in HWDevSyncList\r\n", i);
+
+ PDUMPMEM(&ui32ModifiedValue,
+ psHWDstSyncListMemInfo,
+ ui32WOpsOffset,
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psHWDstSyncListMemInfo));
+
+ ui32ModifiedValue = 0;
+ PDUMPCOMMENT("Modify RT %d ROpsPendingVal in HWDevSyncList\r\n", i);
+
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psHWDstSyncListMemInfo,
+ ui32ROpsOffset,
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psHWDstSyncListMemInfo));
+
+
+ PDUMPCOMMENT("Modify RT %d ROps2PendingVal in HWDevSyncList\r\n", i);
+ PDUMPMEM(&ui32ModifiedValue,
+ psHWDstSyncListMemInfo,
+ ui32ROps2Offset,
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psHWDstSyncListMemInfo));
+ }
+ #endif
+ }
+ else
+ {
+ psHWDeviceSyncList->asSyncData[i].sWriteOpsCompleteDevVAddr.uiAddr = 0;
+ psHWDeviceSyncList->asSyncData[i].sReadOpsCompleteDevVAddr.uiAddr = 0;
+ psHWDeviceSyncList->asSyncData[i].sReadOps2CompleteDevVAddr.uiAddr = 0;
+
+ psHWDeviceSyncList->asSyncData[i].ui32ReadOpsPendingVal = 0;
+ psHWDeviceSyncList->asSyncData[i].ui32ReadOps2PendingVal = 0;
+ psHWDeviceSyncList->asSyncData[i].ui32WriteOpsPendingVal = 0;
+ }
+ }
+ }
+
+
+
+
+ psTACmd->ui32CtrlFlags |= SGXMKIF_CMDTA_CTRLFLAGS_READY;
+
+#if defined(PDUMP)
+ if (PDumpIsCaptureFrameKM())
+ {
+ PDUMPCOMMENT("Shared part of TA command\r\n");
+
+ PDUMPMEM(psTACmd,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff,
+ sizeof(SGXMKIF_CMDTA_SHARED),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+ for (i=0; i<psCCBKick->ui32NumTASrcSyncs; i++)
+ {
+ IMG_UINT32 ui32ModifiedValue;
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTASrcKernelSyncInfo[i];
+
+ if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
+ (psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0))
+ {
+
+ PDUMPCOMMENT("Init RT TA-SRC ROpsComplete\r\n", i);
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete),
+ sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete),
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+
+ PDUMPCOMMENT("Init RT TA-SRC WOpsComplete\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete),
+ sizeof(psSyncInfo->psSyncData->ui32WriteOpsComplete),
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+ }
+
+ psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
+
+ ui32ModifiedValue = psSyncInfo->psSyncData->ui32LastReadOpDumpVal - 1;
+
+ PDUMPCOMMENT("Modify TA SrcSync %d ROpsPendingVal\r\n", i);
+
+ PDUMPMEM(&ui32ModifiedValue,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asTASrcSyncs) +
+ (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal),
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ PDUMPCOMMENT("Modify TA SrcSync %d WOpPendingVal\r\n", i);
+
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asTASrcSyncs) +
+ (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal),
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+ }
+
+ for (i=0; i<psCCBKick->ui32NumTADstSyncs; i++)
+ {
+ IMG_UINT32 ui32ModifiedValue;
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTADstKernelSyncInfo[i];
+
+ if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
+ (psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0))
+ {
+
+ PDUMPCOMMENT("Init RT TA-DST ROpsComplete\r\n", i);
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete),
+ sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete),
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+
+ PDUMPCOMMENT("Init RT TA-DST WOpsComplete\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete),
+ sizeof(psSyncInfo->psSyncData->ui32WriteOpsComplete),
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+ }
+
+ psSyncInfo->psSyncData->ui32LastOpDumpVal++;
+
+ ui32ModifiedValue = psSyncInfo->psSyncData->ui32LastOpDumpVal - 1;
+
+ PDUMPCOMMENT("Modify TA DstSync %d WOpPendingVal\r\n", i);
+
+ PDUMPMEM(&ui32ModifiedValue,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asTADstSyncs) +
+ (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal),
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ PDUMPCOMMENT("Modify TA DstSync %d ROpsPendingVal\r\n", i);
+
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asTADstSyncs) +
+ (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal),
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+ }
+
+ for (i=0; i<psCCBKick->ui32Num3DSrcSyncs; i++)
+ {
+ IMG_UINT32 ui32ModifiedValue;
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ah3DSrcKernelSyncInfo[i];
+
+ if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
+ (psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0))
+ {
+
+ PDUMPCOMMENT("Init RT 3D-SRC ROpsComplete\r\n", i);
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete),
+ sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete),
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+
+ PDUMPCOMMENT("Init RT 3D-SRC WOpsComplete\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete),
+ sizeof(psSyncInfo->psSyncData->ui32WriteOpsComplete),
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+ }
+
+ psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
+
+ ui32ModifiedValue = psSyncInfo->psSyncData->ui32LastReadOpDumpVal - 1;
+
+ PDUMPCOMMENT("Modify 3D SrcSync %d ROpsPendingVal\r\n", i);
+
+ PDUMPMEM(&ui32ModifiedValue,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, as3DSrcSyncs) +
+ (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal),
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ PDUMPCOMMENT("Modify 3D SrcSync %d WOpPendingVal\r\n", i);
+
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, as3DSrcSyncs) +
+ (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal),
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+ }
+#else
+ for (i=0; i<psCCBKick->ui32NumSrcSyncs; i++)
+ {
+ IMG_UINT32 ui32ModifiedValue;
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahSrcKernelSyncInfo[i];
+
+ if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
+ (psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0))
+ {
+
+ PDUMPCOMMENT("Init RT ROpsComplete\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete),
+ sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete),
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+
+ PDUMPCOMMENT("Init RT WOpsComplete\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete),
+ sizeof(psSyncInfo->psSyncData->ui32WriteOpsComplete),
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+
+ PDUMPCOMMENT("Init RT WOpsComplete\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32ReadOps2Complete),
+ sizeof(psSyncInfo->psSyncData->ui32ReadOps2Complete),
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+ }
+
+ psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
+
+ ui32ModifiedValue = psSyncInfo->psSyncData->ui32LastReadOpDumpVal - 1;
+
+ PDUMPCOMMENT("Modify SrcSync %d ROpsPendingVal\r\n", i);
+
+ PDUMPMEM(&ui32ModifiedValue,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asSrcSyncs) +
+ (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal),
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ PDUMPCOMMENT("Modify SrcSync %d WOpPendingVal\r\n", i);
+
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asSrcSyncs) +
+ (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal),
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+ }
+
+ if (psCCBKick->hTASyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTASyncInfo;
+
+ PDUMPCOMMENT("Modify TA/TQ ROpPendingVal\r\n");
+
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, ui32TATQSyncReadOpsPendingVal),
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+ psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
+ }
+
+ if (psCCBKick->h3DSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->h3DSyncInfo;
+
+ PDUMPCOMMENT("Modify 3D/TQ ROpPendingVal\r\n");
+
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, ui323DTQSyncReadOpsPendingVal),
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+ psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
+ }
+
+#endif
+
+ for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++)
+ {
+#if !defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ahTAStatusSyncInfo[i];
+ PDUMPCOMMENT("Modify TA status value in TA cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff + (IMG_UINT32)offsetof(SGXMKIF_CMDTA_SHARED, sCtlTAStatusInfo[i].ui32StatusValue),
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+#endif
+ }
+
+ for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++)
+ {
+#if !defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ah3DStatusSyncInfo[i];
+ PDUMPCOMMENT("Modify 3D status value in TA cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff + (IMG_UINT32)offsetof(SGXMKIF_CMDTA_SHARED, sCtl3DStatusInfo[i].ui32StatusValue),
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+#endif
+ }
+ }
+#endif
+
+ PVR_TTRACE(PVRSRV_TRACE_GROUP_KICK, PVRSRV_TRACE_CLASS_CMD_END,
+ KICK_TOKEN_DOKICK);
+
+ eError = SGXScheduleCCBCommandKM(hDevHandle, SGXMKIF_CMD_TA, &psCCBKick->sCommand, KERNEL_ID, 0, hDevMemContext, psCCBKick->bLastInScene);
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+ if (psCCBKick->bFirstKickOrResume && psCCBKick->ui32NumDstSyncObjects > 0)
+ {
+ for (i=0; i < psCCBKick->ui32NumDstSyncObjects; i++)
+ {
+
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->pahDstSyncHandles[i];
+
+ if (psSyncInfo)
+ {
+ psSyncInfo->psSyncData->ui32WriteOpsPending--;
+#if defined(PDUMP)
+ if (PDumpIsCaptureFrameKM())
+ {
+ psSyncInfo->psSyncData->ui32LastOpDumpVal--;
+ }
+#endif
+ }
+ }
+ }
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+ for (i=0; i<psCCBKick->ui32NumTASrcSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTASrcKernelSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsPending--;
+ }
+ for (i=0; i<psCCBKick->ui32NumTADstSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTADstKernelSyncInfo[i];
+ psSyncInfo->psSyncData->ui32WriteOpsPending--;
+ }
+ for (i=0; i<psCCBKick->ui32Num3DSrcSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ah3DSrcKernelSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsPending--;
+ }
+#else
+ for (i=0; i<psCCBKick->ui32NumSrcSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahSrcKernelSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsPending--;
+ }
+#endif
+
+ PVR_TTRACE(PVRSRV_TRACE_GROUP_KICK, PVRSRV_TRACE_CLASS_FUNCTION_EXIT,
+ KICK_TOKEN_DOKICK);
+ return eError;
+ }
+ else if (PVRSRV_OK != eError)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXDoKickKM: SGXScheduleCCBCommandKM failed."));
+ PVR_TTRACE(PVRSRV_TRACE_GROUP_KICK, PVRSRV_TRACE_CLASS_FUNCTION_EXIT,
+ KICK_TOKEN_DOKICK);
+ return eError;
+ }
+
+
+#if defined(NO_HARDWARE)
+
+
+
+ if (psCCBKick->hTA3DSyncInfo)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTA3DSyncInfo;
+
+ if (psCCBKick->bTADependency)
+ {
+ psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+ }
+
+ if (psCCBKick->hTASyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTASyncInfo;
+
+ psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ }
+
+ if (psCCBKick->h3DSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->h3DSyncInfo;
+
+ psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ }
+
+
+ for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++)
+ {
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = (PVRSRV_KERNEL_MEM_INFO*)psCCBKick->asTAStatusUpdate[i].hKernelMemInfo;
+
+ *(IMG_UINT32*)((IMG_UINTPTR_T)psKernelMemInfo->pvLinAddrKM
+ + (psTACmd->sCtlTAStatusInfo[i].sStatusDevAddr.uiAddr
+ - psKernelMemInfo->sDevVAddr.uiAddr)) = psTACmd->sCtlTAStatusInfo[i].ui32StatusValue;
+#else
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ahTAStatusSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsComplete = psTACmd->sCtlTAStatusInfo[i].ui32StatusValue;
+#endif
+ }
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+
+ for (i=0; i<psCCBKick->ui32NumTASrcSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTASrcKernelSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ }
+ for (i=0; i<psCCBKick->ui32NumTADstSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTADstKernelSyncInfo[i];
+ psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+ for (i=0; i<psCCBKick->ui32Num3DSrcSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ah3DSrcKernelSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ }
+#else
+
+ for (i=0; i<psCCBKick->ui32NumSrcSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahSrcKernelSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ }
+#endif
+
+ if (psCCBKick->bTerminateOrAbort)
+ {
+ if (psCCBKick->ui32NumDstSyncObjects > 0)
+ {
+ PVRSRV_KERNEL_MEM_INFO *psHWDstSyncListMemInfo =
+ (PVRSRV_KERNEL_MEM_INFO *)psCCBKick->hKernelHWSyncListMemInfo;
+ SGXMKIF_HWDEVICE_SYNC_LIST *psHWDeviceSyncList = psHWDstSyncListMemInfo->pvLinAddrKM;
+
+ for (i=0; i<psCCBKick->ui32NumDstSyncObjects; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->pahDstSyncHandles[i];
+ if (psSyncInfo)
+ psSyncInfo->psSyncData->ui32WriteOpsComplete = psHWDeviceSyncList->asSyncData[i].ui32WriteOpsPendingVal+1;
+ }
+ }
+
+
+ for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++)
+ {
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = (PVRSRV_KERNEL_MEM_INFO*)psCCBKick->as3DStatusUpdate[i].hKernelMemInfo;
+
+ *(IMG_UINT32*)((IMG_UINTPTR_T)psKernelMemInfo->pvLinAddrKM
+ + (psTACmd->sCtl3DStatusInfo[i].sStatusDevAddr.uiAddr
+ - psKernelMemInfo->sDevVAddr.uiAddr)) = psTACmd->sCtl3DStatusInfo[i].ui32StatusValue;
+#else
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ah3DStatusSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsComplete = psTACmd->sCtl3DStatusInfo[i].ui32StatusValue;
+#endif
+ }
+ }
+#endif
+ PVR_TTRACE(PVRSRV_TRACE_GROUP_KICK, PVRSRV_TRACE_CLASS_FUNCTION_EXIT,
+ KICK_TOKEN_DOKICK);
+ return eError;
+}
+
diff --git a/drivers/gpu/pvr/sgx/sgxpower.c b/drivers/gpu/pvr/sgx/sgxpower.c
new file mode 100644
index 0000000..b647b68
--- /dev/null
+++ b/drivers/gpu/pvr/sgx/sgxpower.c
@@ -0,0 +1,483 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include <stddef.h>
+
+#include "sgxdefs.h"
+#include "services_headers.h"
+#include "sgxapi_km.h"
+#include "sgx_mkif_km.h"
+#include "sgxutils.h"
+#include "pdump_km.h"
+
+
+#if defined(SUPPORT_HW_RECOVERY)
+static PVRSRV_ERROR SGXAddTimer(PVRSRV_DEVICE_NODE *psDeviceNode,
+ SGX_TIMING_INFORMATION *psSGXTimingInfo,
+ IMG_HANDLE *phTimer)
+{
+
+
+
+ *phTimer = OSAddTimer(SGXOSTimer, psDeviceNode,
+ 1000 * 50 / psSGXTimingInfo->ui32uKernelFreq);
+ if(*phTimer == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXAddTimer : Failed to register timer callback function"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ return PVRSRV_OK;
+}
+#endif
+
+
+static PVRSRV_ERROR SGXUpdateTimingInfo(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+#if defined(SGX_DYNAMIC_TIMING_INFO)
+ SGX_TIMING_INFORMATION sSGXTimingInfo = {0};
+#else
+ SGX_DEVICE_MAP *psSGXDeviceMap;
+#endif
+ IMG_UINT32 ui32ActivePowManSampleRate;
+ SGX_TIMING_INFORMATION *psSGXTimingInfo;
+
+
+#if defined(SGX_DYNAMIC_TIMING_INFO)
+ psSGXTimingInfo = &sSGXTimingInfo;
+ SysGetSGXTimingInformation(psSGXTimingInfo);
+#else
+ SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
+ (IMG_VOID**)&psSGXDeviceMap);
+ psSGXTimingInfo = &psSGXDeviceMap->sTimingInfo;
+#endif
+
+#if defined(SUPPORT_HW_RECOVERY)
+ {
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32OlduKernelFreq;
+
+ if (psDevInfo->hTimer != IMG_NULL)
+ {
+ ui32OlduKernelFreq = psDevInfo->ui32CoreClockSpeed / psDevInfo->ui32uKernelTimerClock;
+ if (ui32OlduKernelFreq != psSGXTimingInfo->ui32uKernelFreq)
+ {
+
+
+ IMG_HANDLE hNewTimer;
+
+ eError = SGXAddTimer(psDeviceNode, psSGXTimingInfo, &hNewTimer);
+ if (eError == PVRSRV_OK)
+ {
+ eError = OSRemoveTimer(psDevInfo->hTimer);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXUpdateTimingInfo: Failed to remove timer"));
+ }
+ psDevInfo->hTimer = hNewTimer;
+ }
+ else
+ {
+
+ }
+ }
+ }
+ else
+ {
+ eError = SGXAddTimer(psDeviceNode, psSGXTimingInfo, &psDevInfo->hTimer);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+
+ psDevInfo->psSGXHostCtl->ui32HWRecoverySampleRate =
+ psSGXTimingInfo->ui32uKernelFreq / psSGXTimingInfo->ui32HWRecoveryFreq;
+ }
+#endif
+
+
+ psDevInfo->ui32CoreClockSpeed = psSGXTimingInfo->ui32CoreClockSpeed;
+ psDevInfo->ui32uKernelTimerClock = psSGXTimingInfo->ui32CoreClockSpeed / psSGXTimingInfo->ui32uKernelFreq;
+
+
+ psDevInfo->psSGXHostCtl->ui32uKernelTimerClock = psDevInfo->ui32uKernelTimerClock;
+#if defined(PDUMP)
+ PDUMPCOMMENT("Host Control - Microkernel clock");
+ PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+ offsetof(SGXMKIF_HOST_CTL, ui32uKernelTimerClock),
+ sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+#endif
+
+ if (psSGXTimingInfo->bEnableActivePM)
+ {
+ ui32ActivePowManSampleRate =
+ psSGXTimingInfo->ui32uKernelFreq * psSGXTimingInfo->ui32ActivePowManLatencyms / 1000;
+
+
+
+
+
+
+
+ ui32ActivePowManSampleRate += 1;
+ }
+ else
+ {
+ ui32ActivePowManSampleRate = 0;
+ }
+
+ psDevInfo->psSGXHostCtl->ui32ActivePowManSampleRate = ui32ActivePowManSampleRate;
+#if defined(PDUMP)
+ PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+ offsetof(SGXMKIF_HOST_CTL, ui32ActivePowManSampleRate),
+ sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+#endif
+
+ return PVRSRV_OK;
+}
+
+
+static IMG_VOID SGXStartTimer(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ #if defined(SUPPORT_HW_RECOVERY)
+ PVRSRV_ERROR eError;
+
+ eError = OSEnableTimer(psDevInfo->hTimer);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXStartTimer : Failed to enable host timer"));
+ }
+ #else
+ PVR_UNREFERENCED_PARAMETER(psDevInfo);
+ #endif
+}
+
+
+static IMG_VOID SGXPollForClockGating (PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32Register,
+ IMG_UINT32 ui32RegisterValue,
+ IMG_CHAR *pszComment)
+{
+ PVR_UNREFERENCED_PARAMETER(psDevInfo);
+ PVR_UNREFERENCED_PARAMETER(ui32Register);
+ PVR_UNREFERENCED_PARAMETER(ui32RegisterValue);
+ PVR_UNREFERENCED_PARAMETER(pszComment);
+
+ #if !defined(NO_HARDWARE)
+ PVR_ASSERT(psDevInfo != IMG_NULL);
+
+
+ if (PollForValueKM((IMG_UINT32 *)psDevInfo->pvRegsBaseKM + (ui32Register >> 2),
+ 0,
+ ui32RegisterValue,
+ MAX_HW_TIME_US,
+ MAX_HW_TIME_US/WAIT_TRY_COUNT,
+ IMG_FALSE) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXPollForClockGating: %s failed.", pszComment));
+ SGXDumpDebugInfo(psDevInfo, IMG_FALSE);
+ PVR_DBG_BREAK;
+ }
+ #endif
+
+ PDUMPCOMMENT("%s", pszComment);
+ PDUMPREGPOL(SGX_PDUMPREG_NAME, ui32Register, 0, ui32RegisterValue, PDUMP_POLL_OPERATOR_EQUAL);
+}
+
+
+PVRSRV_ERROR SGXPrePowerState (IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+ if ((eNewPowerState != eCurrentPowerState) &&
+ (eNewPowerState != PVRSRV_DEV_POWER_STATE_ON))
+ {
+ PVRSRV_ERROR eError;
+ PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ IMG_UINT32 ui32PowerCmd, ui32CompleteStatus;
+ SGXMKIF_COMMAND sCommand = {0};
+ IMG_UINT32 ui32Core;
+ IMG_UINT32 ui32CoresEnabled;
+
+ #if defined(SUPPORT_HW_RECOVERY)
+
+ eError = OSDisableTimer(psDevInfo->hTimer);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: Failed to disable timer"));
+ return eError;
+ }
+ #endif
+
+ if (eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF)
+ {
+
+ ui32PowerCmd = PVRSRV_POWERCMD_POWEROFF;
+ ui32CompleteStatus = PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE;
+ PDUMPCOMMENT("SGX power off request");
+ }
+ else
+ {
+
+ ui32PowerCmd = PVRSRV_POWERCMD_IDLE;
+ ui32CompleteStatus = PVRSRV_USSE_EDM_POWMAN_IDLE_COMPLETE;
+ PDUMPCOMMENT("SGX idle request");
+ }
+
+ sCommand.ui32Data[1] = ui32PowerCmd;
+
+ eError = SGXScheduleCCBCommand(psDeviceNode, SGXMKIF_CMD_POWER, &sCommand, KERNEL_ID, 0, IMG_NULL, IMG_FALSE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: Failed to submit power down command"));
+ return eError;
+ }
+
+
+ #if !defined(NO_HARDWARE)
+ if (PollForValueKM(&psDevInfo->psSGXHostCtl->ui32PowerStatus,
+ ui32CompleteStatus,
+ ui32CompleteStatus,
+ MAX_HW_TIME_US,
+ MAX_HW_TIME_US/WAIT_TRY_COUNT,
+ IMG_FALSE) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: Wait for SGX ukernel power transition failed."));
+ SGXDumpDebugInfo(psDevInfo, IMG_FALSE);
+ PVR_DBG_BREAK;
+ }
+ #endif
+
+ #if defined(PDUMP)
+ PDUMPCOMMENT("TA/3D CCB Control - Wait for power event on uKernel.");
+ PDUMPMEMPOL(psDevInfo->psKernelSGXHostCtlMemInfo,
+ offsetof(SGXMKIF_HOST_CTL, ui32PowerStatus),
+ ui32CompleteStatus,
+ ui32CompleteStatus,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ 0,
+ MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+ #endif
+
+#if defined(SGX_FEATURE_MP)
+ ui32CoresEnabled = ((OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE) & EUR_CR_MASTER_CORE_ENABLE_MASK) >> EUR_CR_MASTER_CORE_ENABLE_SHIFT) + 1;
+#else
+ ui32CoresEnabled = 1;
+#endif
+
+ for (ui32Core = 0; ui32Core < ui32CoresEnabled; ui32Core++)
+ {
+
+ SGXPollForClockGating(psDevInfo,
+ SGX_MP_CORE_SELECT(psDevInfo->ui32ClkGateStatusReg, ui32Core),
+ psDevInfo->ui32ClkGateStatusMask,
+ "Wait for SGX clock gating");
+ }
+
+ #if defined(SGX_FEATURE_MP)
+
+ SGXPollForClockGating(psDevInfo,
+ psDevInfo->ui32MasterClkGateStatusReg,
+ psDevInfo->ui32MasterClkGateStatusMask,
+ "Wait for SGX master clock gating");
+
+ SGXPollForClockGating(psDevInfo,
+ psDevInfo->ui32MasterClkGateStatus2Reg,
+ psDevInfo->ui32MasterClkGateStatus2Mask,
+ "Wait for SGX master clock gating (2)");
+ #endif
+
+ if (eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF)
+ {
+
+ eError = SGXDeinitialise(psDevInfo);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: SGXDeinitialise failed: %u", eError));
+ return eError;
+ }
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR SGXPostPowerState (IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+ if ((eNewPowerState != eCurrentPowerState) &&
+ (eCurrentPowerState != PVRSRV_DEV_POWER_STATE_ON))
+ {
+ PVRSRV_ERROR eError;
+ PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl;
+
+
+ psSGXHostCtl->ui32PowerStatus = 0;
+ #if defined(PDUMP)
+ PDUMPCOMMENT("Host Control - Reset power status");
+ PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+ offsetof(SGXMKIF_HOST_CTL, ui32PowerStatus),
+ sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+ #endif
+
+ if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_OFF)
+ {
+
+
+
+
+ eError = SGXUpdateTimingInfo(psDeviceNode);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXPostPowerState: SGXUpdateTimingInfo failed"));
+ return eError;
+ }
+
+
+
+ eError = SGXInitialise(psDevInfo, IMG_FALSE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXPostPowerState: SGXInitialise failed"));
+ return eError;
+ }
+ }
+ else
+ {
+
+
+ SGXMKIF_COMMAND sCommand = {0};
+
+ sCommand.ui32Data[1] = PVRSRV_POWERCMD_RESUME;
+ eError = SGXScheduleCCBCommand(psDeviceNode, SGXMKIF_CMD_POWER, &sCommand, ISR_ID, 0, IMG_NULL, IMG_FALSE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXPostPowerState failed to schedule CCB command: %u", eError));
+ return eError;
+ }
+ }
+
+ SGXStartTimer(psDevInfo);
+ }
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR SGXPreClockSpeedChange (IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
+ PVR_UNREFERENCED_PARAMETER(psDevInfo);
+
+ if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_ON)
+ {
+ if (bIdleDevice)
+ {
+
+ PDUMPSUSPEND();
+
+ eError = SGXPrePowerState(hDevHandle, PVRSRV_DEV_POWER_STATE_IDLE,
+ PVRSRV_DEV_POWER_STATE_ON);
+
+ if (eError != PVRSRV_OK)
+ {
+ PDUMPRESUME();
+ return eError;
+ }
+ }
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE,"SGXPreClockSpeedChange: SGX clock speed was %uHz",
+ psDevInfo->ui32CoreClockSpeed));
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR SGXPostClockSpeedChange (IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ IMG_UINT32 ui32OldClockSpeed = psDevInfo->ui32CoreClockSpeed;
+
+ PVR_UNREFERENCED_PARAMETER(ui32OldClockSpeed);
+
+ if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_ON)
+ {
+ PVRSRV_ERROR eError;
+
+
+
+ eError = SGXUpdateTimingInfo(psDeviceNode);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXPostPowerState: SGXUpdateTimingInfo failed"));
+ return eError;
+ }
+
+ if (bIdleDevice)
+ {
+
+ eError = SGXPostPowerState(hDevHandle, PVRSRV_DEV_POWER_STATE_ON,
+ PVRSRV_DEV_POWER_STATE_IDLE);
+
+ PDUMPRESUME();
+
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+ else
+ {
+ SGXStartTimer(psDevInfo);
+ }
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE,"SGXPostClockSpeedChange: SGX clock speed changed from %uHz to %uHz",
+ ui32OldClockSpeed, psDevInfo->ui32CoreClockSpeed));
+
+ return PVRSRV_OK;
+}
+
+
diff --git a/drivers/gpu/pvr/sgx/sgxreset.c b/drivers/gpu/pvr/sgx/sgxreset.c
new file mode 100644
index 0000000..45e6d79
--- /dev/null
+++ b/drivers/gpu/pvr/sgx/sgxreset.c
@@ -0,0 +1,671 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "sgxdefs.h"
+#include "sgxmmu.h"
+#include "services_headers.h"
+#include "sgxinfokm.h"
+#include "sgxconfig.h"
+#include "sgxutils.h"
+
+#include "pdump_km.h"
+
+
+IMG_VOID SGXInitClocks(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32PDUMPFlags)
+{
+ IMG_UINT32 ui32RegVal;
+
+#if !defined(PDUMP)
+ PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
+#endif
+
+ ui32RegVal = psDevInfo->ui32ClkGateCtl;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_CLKGATECTL, ui32RegVal);
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_CLKGATECTL, ui32RegVal, ui32PDUMPFlags);
+
+#if defined(EUR_CR_CLKGATECTL2)
+ ui32RegVal = psDevInfo->ui32ClkGateCtl2;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_CLKGATECTL2, ui32RegVal);
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_CLKGATECTL2, ui32RegVal, ui32PDUMPFlags);
+#endif
+}
+
+
+static IMG_VOID SGXResetInitBIFContexts(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32PDUMPFlags)
+{
+ IMG_UINT32 ui32RegVal;
+
+#if !defined(PDUMP)
+ PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
+#endif
+
+ ui32RegVal = 0;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+
+#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+ PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Initialise the BIF bank settings\r\n");
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_BANK_SET, ui32RegVal);
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_BANK_SET, ui32RegVal, ui32PDUMPFlags);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_BANK0, ui32RegVal);
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_BANK0, ui32RegVal, ui32PDUMPFlags);
+#endif
+
+ PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Initialise the BIF directory list\r\n");
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0, ui32RegVal);
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_DIR_LIST_BASE0, ui32RegVal, ui32PDUMPFlags);
+
+#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+ {
+ IMG_UINT32 ui32DirList, ui32DirListReg;
+
+ for (ui32DirList = 1;
+ ui32DirList < SGX_FEATURE_BIF_NUM_DIRLISTS;
+ ui32DirList++)
+ {
+ ui32DirListReg = EUR_CR_BIF_DIR_LIST_BASE1 + 4 * (ui32DirList - 1);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32DirListReg, ui32RegVal);
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, ui32DirListReg, ui32RegVal, ui32PDUMPFlags);
+ }
+ }
+#endif
+}
+
+
+static IMG_VOID SGXResetSetupBIFContexts(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32PDUMPFlags)
+{
+ IMG_UINT32 ui32RegVal;
+
+#if !defined(PDUMP)
+ PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
+#endif
+
+ #if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+
+ ui32RegVal = (SGX_BIF_DIR_LIST_INDEX_EDM << EUR_CR_BIF_BANK0_INDEX_EDM_SHIFT);
+
+ #if defined(SGX_FEATURE_2D_HARDWARE) && !defined(SGX_FEATURE_PTLA)
+
+ ui32RegVal |= (SGX_BIF_DIR_LIST_INDEX_EDM << EUR_CR_BIF_BANK0_INDEX_2D_SHIFT);
+ #endif
+
+ #if defined(FIX_HW_BRN_23410)
+
+ ui32RegVal |= (SGX_BIF_DIR_LIST_INDEX_EDM << EUR_CR_BIF_BANK0_INDEX_TA_SHIFT);
+ #endif
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_BANK0, ui32RegVal);
+ PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Set up EDM requestor page table in BIF\r\n");
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_BANK0, ui32RegVal, ui32PDUMPFlags);
+ #endif
+
+ {
+ IMG_UINT32 ui32EDMDirListReg;
+
+
+ #if (SGX_BIF_DIR_LIST_INDEX_EDM == 0)
+ ui32EDMDirListReg = EUR_CR_BIF_DIR_LIST_BASE0;
+ #else
+
+ ui32EDMDirListReg = EUR_CR_BIF_DIR_LIST_BASE1 + 4 * (SGX_BIF_DIR_LIST_INDEX_EDM - 1);
+ #endif
+
+ ui32RegVal = psDevInfo->sKernelPDDevPAddr.uiAddr >> SGX_MMU_PDE_ADDR_ALIGNSHIFT;
+
+#if defined(FIX_HW_BRN_28011)
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0, ui32RegVal);
+ PDUMPPDREGWITHFLAGS(&psDevInfo->sMMUAttrib, EUR_CR_BIF_DIR_LIST_BASE0, ui32RegVal, ui32PDUMPFlags, PDUMP_PD_UNIQUETAG);
+#endif
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32EDMDirListReg, ui32RegVal);
+ PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Initialise the EDM's directory list base\r\n");
+ PDUMPPDREGWITHFLAGS(&psDevInfo->sMMUAttrib, ui32EDMDirListReg, ui32RegVal, ui32PDUMPFlags, PDUMP_PD_UNIQUETAG);
+ }
+}
+
+
+static IMG_VOID SGXResetSleep(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32PDUMPFlags,
+ IMG_BOOL bPDump)
+{
+#if defined(PDUMP) || defined(EMULATOR)
+ IMG_UINT32 ui32ReadRegister;
+
+ #if defined(SGX_FEATURE_MP)
+ ui32ReadRegister = EUR_CR_MASTER_SOFT_RESET;
+ #else
+ ui32ReadRegister = EUR_CR_SOFT_RESET;
+ #endif
+#endif
+
+#if !defined(PDUMP)
+ PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
+#endif
+
+
+ SGXWaitClocks(psDevInfo, 100);
+ if (bPDump)
+ {
+ PDUMPIDLWITHFLAGS(30, ui32PDUMPFlags);
+#if defined(PDUMP)
+ PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Read back to flush the register writes\r\n");
+ PDumpRegRead(SGX_PDUMPREG_NAME, ui32ReadRegister, ui32PDUMPFlags);
+#endif
+ }
+
+#if defined(EMULATOR)
+
+
+ OSReadHWReg(psDevInfo->pvRegsBaseKM, ui32ReadRegister);
+#endif
+}
+
+
+#if !defined(SGX_FEATURE_MP)
+static IMG_VOID SGXResetSoftReset(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_BOOL bResetBIF,
+ IMG_UINT32 ui32PDUMPFlags,
+ IMG_BOOL bPDump)
+{
+ IMG_UINT32 ui32SoftResetRegVal;
+
+ ui32SoftResetRegVal =
+
+ EUR_CR_SOFT_RESET_DPM_RESET_MASK |
+ EUR_CR_SOFT_RESET_TA_RESET_MASK |
+ EUR_CR_SOFT_RESET_USE_RESET_MASK |
+ EUR_CR_SOFT_RESET_ISP_RESET_MASK |
+ EUR_CR_SOFT_RESET_TSP_RESET_MASK;
+
+#ifdef EUR_CR_SOFT_RESET_TWOD_RESET_MASK
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_TWOD_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_TE_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_TE_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_MTE_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_MTE_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_ISP2_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_ISP2_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_PDS_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_PDS_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_PBE_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_PBE_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_CACHEL2_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_CACHEL2_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_TCU_L2_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_TCU_L2_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_UCACHEL2_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_UCACHEL2_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_MADD_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_MADD_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_ITR_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_ITR_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_TEX_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_TEX_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_IDXFIFO_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_IDXFIFO_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_VDM_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_VDM_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_DCU_L2_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_DCU_L2_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_DCU_L0L1_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_DCU_L0L1_RESET_MASK;
+#endif
+
+#if !defined(PDUMP)
+ PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
+#endif
+
+ if (bResetBIF)
+ {
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_BIF_RESET_MASK;
+ }
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_SOFT_RESET, ui32SoftResetRegVal);
+ if (bPDump)
+ {
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_SOFT_RESET, ui32SoftResetRegVal, ui32PDUMPFlags);
+ }
+}
+
+
+static IMG_VOID SGXResetInvalDC(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32PDUMPFlags,
+ IMG_BOOL bPDump)
+{
+ IMG_UINT32 ui32RegVal;
+
+
+#if defined(EUR_CR_BIF_CTRL_INVAL)
+ ui32RegVal = EUR_CR_BIF_CTRL_INVAL_ALL_MASK;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL_INVAL, ui32RegVal);
+ if (bPDump)
+ {
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL_INVAL, ui32RegVal, ui32PDUMPFlags);
+ }
+#else
+ ui32RegVal = EUR_CR_BIF_CTRL_INVALDC_MASK;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+ if (bPDump)
+ {
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+ }
+
+ ui32RegVal = 0;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+ if (bPDump)
+ {
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+ }
+#endif
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, bPDump);
+
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+ {
+
+
+
+ if (PollForValueKM((IMG_UINT32 *)((IMG_UINT8*)psDevInfo->pvRegsBaseKM + EUR_CR_BIF_MEM_REQ_STAT),
+ 0,
+ EUR_CR_BIF_MEM_REQ_STAT_READS_MASK,
+ MAX_HW_TIME_US,
+ MAX_HW_TIME_US/WAIT_TRY_COUNT,
+ IMG_FALSE) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"Wait for DC invalidate failed."));
+ PVR_DBG_BREAK;
+ }
+
+ if (bPDump)
+ {
+ PDUMPREGPOLWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_MEM_REQ_STAT, 0, EUR_CR_BIF_MEM_REQ_STAT_READS_MASK, ui32PDUMPFlags, PDUMP_POLL_OPERATOR_EQUAL);
+ }
+ }
+#endif
+}
+#endif
+
+
+IMG_VOID SGXReset(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_BOOL bHardwareRecovery,
+ IMG_UINT32 ui32PDUMPFlags)
+#if !defined(SGX_FEATURE_MP)
+{
+ IMG_UINT32 ui32RegVal;
+#if defined(EUR_CR_BIF_INT_STAT_FAULT_REQ_MASK)
+ const IMG_UINT32 ui32BifFaultMask = EUR_CR_BIF_INT_STAT_FAULT_REQ_MASK;
+#else
+ const IMG_UINT32 ui32BifFaultMask = EUR_CR_BIF_INT_STAT_FAULT_MASK;
+#endif
+
+#if !defined(PDUMP)
+ PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
+#endif
+
+ PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Start of SGX reset sequence\r\n");
+
+#if defined(FIX_HW_BRN_23944)
+
+ ui32RegVal = EUR_CR_BIF_CTRL_PAUSE_MASK;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_INT_STAT);
+ if (ui32RegVal & ui32BifFaultMask)
+ {
+
+ ui32RegVal = EUR_CR_BIF_CTRL_PAUSE_MASK | EUR_CR_BIF_CTRL_CLEAR_FAULT_MASK;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+ ui32RegVal = EUR_CR_BIF_CTRL_PAUSE_MASK;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+ }
+#endif
+
+
+ SGXResetSoftReset(psDevInfo, IMG_TRUE, ui32PDUMPFlags, IMG_TRUE);
+
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+
+
+#if defined(SGX_FEATURE_36BIT_MMU)
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_36BIT_ADDRESSING, EUR_CR_BIF_36BIT_ADDRESSING_ENABLE_MASK);
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_36BIT_ADDRESSING, EUR_CR_BIF_36BIT_ADDRESSING_ENABLE_MASK, ui32PDUMPFlags);
+#endif
+
+ SGXResetInitBIFContexts(psDevInfo, ui32PDUMPFlags);
+
+#if defined(EUR_CR_BIF_MEM_ARB_CONFIG)
+
+
+ ui32RegVal = (12UL << EUR_CR_BIF_MEM_ARB_CONFIG_PAGE_SIZE_SHIFT) |
+ (7UL << EUR_CR_BIF_MEM_ARB_CONFIG_BEST_CNT_SHIFT) |
+ (12UL << EUR_CR_BIF_MEM_ARB_CONFIG_TTE_THRESH_SHIFT);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_MEM_ARB_CONFIG, ui32RegVal);
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_MEM_ARB_CONFIG, ui32RegVal, ui32PDUMPFlags);
+#endif
+
+#if defined(SGX_FEATURE_SYSTEM_CACHE)
+ #if defined(SGX_BYPASS_SYSTEM_CACHE)
+
+ ui32RegVal = MNE_CR_CTRL_BYPASS_ALL_MASK;
+ #else
+ #if defined(FIX_HW_BRN_26620)
+ ui32RegVal = 0;
+ #else
+
+ ui32RegVal = MNE_CR_CTRL_BYP_CC_MASK;
+ #endif
+ #if defined(FIX_HW_BRN_34028)
+
+ ui32RegVal |= (8 << MNE_CR_CTRL_BYPASS_SHIFT);
+ #endif
+ #endif
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, MNE_CR_CTRL, ui32RegVal);
+ PDUMPREG(SGX_PDUMPREG_NAME, MNE_CR_CTRL, ui32RegVal);
+#endif
+
+ if (bHardwareRecovery)
+ {
+
+
+
+
+
+
+
+ ui32RegVal = (IMG_UINT32)psDevInfo->sBIFResetPDDevPAddr.uiAddr;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0, ui32RegVal);
+
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+
+ SGXResetSoftReset(psDevInfo, IMG_FALSE, ui32PDUMPFlags, IMG_TRUE);
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+ SGXResetInvalDC(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+
+
+ for (;;)
+ {
+ IMG_UINT32 ui32BifIntStat = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_INT_STAT);
+ IMG_DEV_VIRTADDR sBifFault;
+ IMG_UINT32 ui32PDIndex, ui32PTIndex;
+
+ if ((ui32BifIntStat & ui32BifFaultMask) == 0)
+ {
+ break;
+ }
+
+
+
+
+ sBifFault.uiAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_FAULT);
+ PVR_DPF((PVR_DBG_WARNING, "SGXReset: Page fault 0x%x/0x%x", ui32BifIntStat, sBifFault.uiAddr));
+ ui32PDIndex = sBifFault.uiAddr >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
+ ui32PTIndex = (sBifFault.uiAddr & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
+
+
+ SGXResetSoftReset(psDevInfo, IMG_TRUE, ui32PDUMPFlags, IMG_FALSE);
+
+
+ psDevInfo->pui32BIFResetPD[ui32PDIndex] = (psDevInfo->sBIFResetPTDevPAddr.uiAddr
+ >>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PDE_PAGE_SIZE_4K
+ | SGX_MMU_PDE_VALID;
+ psDevInfo->pui32BIFResetPT[ui32PTIndex] = (psDevInfo->sBIFResetPageDevPAddr.uiAddr
+ >>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PTE_VALID;
+
+
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR, ui32RegVal);
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS2);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR2, ui32RegVal);
+
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+
+ SGXResetSoftReset(psDevInfo, IMG_FALSE, ui32PDUMPFlags, IMG_FALSE);
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+
+ SGXResetInvalDC(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+
+ psDevInfo->pui32BIFResetPD[ui32PDIndex] = 0;
+ psDevInfo->pui32BIFResetPT[ui32PTIndex] = 0;
+ }
+ }
+ else
+ {
+
+ SGXResetSoftReset(psDevInfo, IMG_FALSE, ui32PDUMPFlags, IMG_TRUE);
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+ }
+
+
+
+ SGXResetSetupBIFContexts(psDevInfo, ui32PDUMPFlags);
+
+#if defined(SGX_FEATURE_2D_HARDWARE) && !defined(SGX_FEATURE_PTLA)
+
+ #if ((SGX_2D_HEAP_BASE & ~EUR_CR_BIF_TWOD_REQ_BASE_ADDR_MASK) != 0)
+ #error "SGXReset: SGX_2D_HEAP_BASE doesn't match EUR_CR_BIF_TWOD_REQ_BASE_ADDR_MASK alignment"
+ #endif
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_TWOD_REQ_BASE, SGX_2D_HEAP_BASE);
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_TWOD_REQ_BASE, SGX_2D_HEAP_BASE, ui32PDUMPFlags);
+#endif
+
+
+ SGXResetInvalDC(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+ PVR_DPF((PVR_DBG_MESSAGE,"Soft Reset of SGX"));
+
+
+ ui32RegVal = 0;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_SOFT_RESET, ui32RegVal);
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_SOFT_RESET, ui32RegVal, ui32PDUMPFlags);
+
+
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+ PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "End of SGX reset sequence\r\n");
+}
+
+#else
+
+{
+ IMG_UINT32 ui32RegVal;
+
+ PVR_UNREFERENCED_PARAMETER(bHardwareRecovery);
+
+#if !defined(PDUMP)
+ PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
+#endif
+
+ PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Start of SGX MP reset sequence\r\n");
+
+
+ ui32RegVal = EUR_CR_MASTER_SOFT_RESET_BIF_RESET_MASK |
+ EUR_CR_MASTER_SOFT_RESET_IPF_RESET_MASK |
+ EUR_CR_MASTER_SOFT_RESET_DPM_RESET_MASK |
+ EUR_CR_MASTER_SOFT_RESET_MCI_RESET_MASK |
+ EUR_CR_MASTER_SOFT_RESET_VDM_RESET_MASK;
+
+#if defined(SGX_FEATURE_PTLA)
+ ui32RegVal |= EUR_CR_MASTER_SOFT_RESET_PTLA_RESET_MASK;
+#endif
+#if defined(SGX_FEATURE_SYSTEM_CACHE)
+ ui32RegVal |= EUR_CR_MASTER_SOFT_RESET_SLC_RESET_MASK;
+#endif
+
+
+ ui32RegVal |= EUR_CR_MASTER_SOFT_RESET_CORE_RESET_MASK(0) |
+ EUR_CR_MASTER_SOFT_RESET_CORE_RESET_MASK(1) |
+ EUR_CR_MASTER_SOFT_RESET_CORE_RESET_MASK(2) |
+ EUR_CR_MASTER_SOFT_RESET_CORE_RESET_MASK(3);
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_SOFT_RESET, ui32RegVal);
+ PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Soft reset hydra partition, hard reset the cores\r\n");
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_SOFT_RESET, ui32RegVal, ui32PDUMPFlags);
+
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+ ui32RegVal = 0;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BIF_CTRL, ui32RegVal);
+ PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Initialise the hydra BIF control\r\n");
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+
+#if defined(SGX_FEATURE_SYSTEM_CACHE)
+ #if defined(SGX_BYPASS_SYSTEM_CACHE)
+ ui32RegVal = EUR_CR_MASTER_SLC_CTRL_BYPASS_ALL_MASK;
+ #else
+ ui32RegVal = EUR_CR_MASTER_SLC_CTRL_USSE_INVAL_REQ0_MASK |
+ #if defined(FIX_HW_BRN_30954)
+ EUR_CR_MASTER_SLC_CTRL_DISABLE_REORDERING_MASK |
+ #endif
+ #if defined(PVR_SLC_8KB_ADDRESS_MODE)
+ (4 << EUR_CR_MASTER_SLC_CTRL_ADDR_DECODE_MODE_SHIFT) |
+ #endif
+ #if defined(FIX_HW_BRN_33809)
+ (2 << EUR_CR_MASTER_SLC_CTRL_ADDR_DECODE_MODE_SHIFT) |
+ #endif
+ (0xC << EUR_CR_MASTER_SLC_CTRL_ARB_PAGE_SIZE_SHIFT);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_SLC_CTRL, ui32RegVal);
+ PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Initialise the hydra SLC control\r\n");
+ PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_MASTER_SLC_CTRL, ui32RegVal);
+
+ ui32RegVal = EUR_CR_MASTER_SLC_CTRL_BYPASS_BYP_CC_MASK;
+ #if defined(FIX_HW_BRN_31620)
+ ui32RegVal |= EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_MMU_MASK;
+ #endif
+ #if defined(FIX_HW_BRN_31195)
+ ui32RegVal |= EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USE0_MASK |
+ EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USE1_MASK |
+ EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USE2_MASK |
+ EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USE3_MASK |
+ EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_TA_MASK;
+ #endif
+ #endif
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_SLC_CTRL_BYPASS, ui32RegVal);
+ PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Initialise the hydra SLC bypass control\r\n");
+ PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_MASTER_SLC_CTRL_BYPASS, ui32RegVal);
+#endif
+
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+
+ ui32RegVal = 0;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_SOFT_RESET, ui32RegVal);
+ PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Remove the resets from all of SGX\r\n");
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_SOFT_RESET, ui32RegVal, ui32PDUMPFlags);
+
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+ PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Turn on the slave cores' clock gating\r\n");
+ SGXInitClocks(psDevInfo, ui32PDUMPFlags);
+
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+ PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Initialise the slave BIFs\r\n");
+
+#if defined(FIX_HW_BRN_31278) || defined(FIX_HW_BRN_31620) || defined(FIX_HW_BRN_31671) || defined(FIX_HW_BRN_32085)
+ #if defined(FIX_HW_BRN_31278) || defined(FIX_HW_BRN_32085)
+
+ ui32RegVal = (1<<EUR_CR_MASTER_BIF_MMU_CTRL_ADDR_HASH_MODE_SHIFT);
+ #else
+ ui32RegVal = (1<<EUR_CR_MASTER_BIF_MMU_CTRL_ADDR_HASH_MODE_SHIFT) | EUR_CR_MASTER_BIF_MMU_CTRL_PREFETCHING_ON_MASK;
+ #endif
+ #if !defined(FIX_HW_BRN_31620) && !defined(FIX_HW_BRN_31671)
+
+ ui32RegVal |= EUR_CR_MASTER_BIF_MMU_CTRL_ENABLE_DC_TLB_MASK;
+ #endif
+
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BIF_MMU_CTRL, ui32RegVal);
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_BIF_MMU_CTRL, ui32RegVal, ui32PDUMPFlags);
+
+ #if defined(FIX_HW_BRN_31278) || defined(FIX_HW_BRN_32085)
+
+ ui32RegVal = (1<<EUR_CR_BIF_MMU_CTRL_ADDR_HASH_MODE_SHIFT);
+ #else
+ ui32RegVal = (1<<EUR_CR_BIF_MMU_CTRL_ADDR_HASH_MODE_SHIFT) | EUR_CR_BIF_MMU_CTRL_PREFETCHING_ON_MASK;
+ #endif
+ #if !defined(FIX_HW_BRN_31620) && !defined(FIX_HW_BRN_31671)
+
+ ui32RegVal |= EUR_CR_BIF_MMU_CTRL_ENABLE_DC_TLB_MASK;
+ #endif
+
+
+ {
+ IMG_UINT32 ui32Core;
+
+ for (ui32Core=0;ui32Core<SGX_FEATURE_MP_CORE_COUNT;ui32Core++)
+ {
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_BIF_MMU_CTRL, ui32Core), ui32RegVal);
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, SGX_MP_CORE_SELECT(EUR_CR_BIF_MMU_CTRL, ui32Core), ui32RegVal, ui32PDUMPFlags);
+ }
+ }
+#endif
+
+ SGXResetInitBIFContexts(psDevInfo, ui32PDUMPFlags);
+ SGXResetSetupBIFContexts(psDevInfo, ui32PDUMPFlags);
+
+ PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "End of SGX MP reset sequence\r\n");
+}
+#endif
+
+
diff --git a/drivers/gpu/pvr/sgx/sgxtransfer.c b/drivers/gpu/pvr/sgx/sgxtransfer.c
new file mode 100644
index 0000000..f0ce1b5
--- /dev/null
+++ b/drivers/gpu/pvr/sgx/sgxtransfer.c
@@ -0,0 +1,773 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#if defined(TRANSFER_QUEUE)
+
+#include <stddef.h>
+
+#include "sgxdefs.h"
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "sgxinfo.h"
+#include "sysconfig.h"
+#include "pdump_km.h"
+#include "mmu.h"
+#include "pvr_bridge.h"
+#include "sgx_bridge_km.h"
+#include "sgxinfokm.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+#include "sgxutils.h"
+#include "ttrace.h"
+
+#if defined (SUPPORT_SID_INTERFACE)
+IMG_EXPORT PVRSRV_ERROR SGXSubmitTransferKM(IMG_HANDLE hDevHandle, PVRSRV_TRANSFER_SGX_KICK_KM *psKick)
+#else
+IMG_EXPORT PVRSRV_ERROR SGXSubmitTransferKM(IMG_HANDLE hDevHandle, PVRSRV_TRANSFER_SGX_KICK *psKick)
+#endif
+{
+ PVRSRV_KERNEL_MEM_INFO *psCCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psKick->hCCBMemInfo;
+ SGXMKIF_COMMAND sCommand = {0};
+ SGXMKIF_TRANSFERCMD_SHARED *psSharedTransferCmd;
+ PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+ PVRSRV_ERROR eError;
+ IMG_UINT32 loop;
+ IMG_HANDLE hDevMemContext = IMG_NULL;
+ IMG_BOOL abSrcSyncEnable[SGX_MAX_TRANSFER_SYNC_OPS];
+ IMG_UINT32 ui32RealSrcSyncNum = 0;
+ IMG_BOOL abDstSyncEnable[SGX_MAX_TRANSFER_SYNC_OPS];
+ IMG_UINT32 ui32RealDstSyncNum = 0;
+
+
+#if defined(PDUMP)
+ IMG_BOOL bPersistentProcess = IMG_FALSE;
+
+ {
+ PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData();
+ if(psPerProc != IMG_NULL)
+ {
+ bPersistentProcess = psPerProc->bPDumpPersistent;
+ }
+ }
+#endif
+#if defined(FIX_HW_BRN_31620)
+ hDevMemContext = psKick->hDevMemContext;
+#endif
+ PVR_TTRACE(PVRSRV_TRACE_GROUP_TRANSFER, PVRSRV_TRACE_CLASS_FUNCTION_ENTER, TRANSFER_TOKEN_SUBMIT);
+
+ for (loop = 0; loop < SGX_MAX_TRANSFER_SYNC_OPS; loop++)
+ {
+ abSrcSyncEnable[loop] = IMG_TRUE;
+ abDstSyncEnable[loop] = IMG_TRUE;
+ }
+
+ if (!CCB_OFFSET_IS_VALID(SGXMKIF_TRANSFERCMD_SHARED, psCCBMemInfo, psKick, ui32SharedCmdCCBOffset))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXSubmitTransferKM: Invalid CCB offset"));
+ PVR_TTRACE(PVRSRV_TRACE_GROUP_TRANSFER, PVRSRV_TRACE_CLASS_FUNCTION_EXIT,
+ TRANSFER_TOKEN_SUBMIT);
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ psSharedTransferCmd = CCB_DATA_FROM_OFFSET(SGXMKIF_TRANSFERCMD_SHARED, psCCBMemInfo, psKick, ui32SharedCmdCCBOffset);
+
+ PVR_TTRACE(PVRSRV_TRACE_GROUP_TRANSFER, PVRSRV_TRACE_CLASS_CMD_START, TRANSFER_TOKEN_SUBMIT);
+ PVR_TTRACE_UI32(PVRSRV_TRACE_GROUP_TRANSFER, PVRSRV_TRACE_CLASS_CCB,
+ TRANSFER_TOKEN_CCB_OFFSET, psKick->ui32SharedCmdCCBOffset);
+
+ if (psKick->hTASyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+
+ PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_TRANSFER, TRANSFER_TOKEN_TA_SYNC,
+ psSyncInfo, PVRSRV_SYNCOP_SAMPLE);
+
+ psSharedTransferCmd->ui32TASyncWriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ psSharedTransferCmd->ui32TASyncReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+ psSharedTransferCmd->sTASyncWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psSharedTransferCmd->sTASyncReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ }
+ else
+ {
+ psSharedTransferCmd->sTASyncWriteOpsCompleteDevVAddr.uiAddr = 0;
+ psSharedTransferCmd->sTASyncReadOpsCompleteDevVAddr.uiAddr = 0;
+ }
+
+ if (psKick->h3DSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+
+ PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_TRANSFER, TRANSFER_TOKEN_3D_SYNC,
+ psSyncInfo, PVRSRV_SYNCOP_SAMPLE);
+
+ psSharedTransferCmd->ui323DSyncWriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ psSharedTransferCmd->ui323DSyncReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+ psSharedTransferCmd->s3DSyncWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psSharedTransferCmd->s3DSyncReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ }
+ else
+ {
+ psSharedTransferCmd->s3DSyncWriteOpsCompleteDevVAddr.uiAddr = 0;
+ psSharedTransferCmd->s3DSyncReadOpsCompleteDevVAddr.uiAddr = 0;
+ }
+
+
+ for (loop = 0; loop < MIN(SGX_MAX_TRANSFER_SYNC_OPS, psKick->ui32NumSrcSync); loop++)
+ {
+ IMG_UINT32 i;
+
+ PVRSRV_KERNEL_SYNC_INFO * psMySyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[loop];
+
+ for (i = 0; i < loop; i++)
+ {
+ if (abSrcSyncEnable[i])
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[i];
+
+ if (psSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr == psMySyncInfo->sWriteOpsCompleteDevVAddr.uiAddr)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "SGXSubmitTransferKM : Same src synchronized multiple times!"));
+ abSrcSyncEnable[loop] = IMG_FALSE;
+ break;
+ }
+ }
+ }
+ if (abSrcSyncEnable[loop])
+ {
+ ui32RealSrcSyncNum++;
+ }
+ }
+ for (loop = 0; loop < MIN(SGX_MAX_TRANSFER_SYNC_OPS, psKick->ui32NumDstSync); loop++)
+ {
+ IMG_UINT32 i;
+
+ PVRSRV_KERNEL_SYNC_INFO * psMySyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[loop];
+
+ for (i = 0; i < loop; i++)
+ {
+ if (abDstSyncEnable[i])
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[i];
+
+ if (psSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr == psMySyncInfo->sWriteOpsCompleteDevVAddr.uiAddr)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "SGXSubmitTransferKM : Same dst synchronized multiple times!"));
+ abDstSyncEnable[loop] = IMG_FALSE;
+ break;
+ }
+ }
+ }
+ if (abDstSyncEnable[loop])
+ {
+ ui32RealDstSyncNum++;
+ }
+ }
+
+ psSharedTransferCmd->ui32NumSrcSyncs = ui32RealSrcSyncNum;
+ psSharedTransferCmd->ui32NumDstSyncs = ui32RealDstSyncNum;
+
+ if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL)
+ {
+ IMG_UINT32 i = 0;
+
+ for (loop = 0; loop < psKick->ui32NumSrcSync; loop++)
+ {
+ if (abSrcSyncEnable[loop])
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[loop];
+
+ PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_TRANSFER, TRANSFER_TOKEN_SRC_SYNC,
+ psSyncInfo, PVRSRV_SYNCOP_SAMPLE);
+
+ psSharedTransferCmd->asSrcSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ psSharedTransferCmd->asSrcSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+ psSharedTransferCmd->asSrcSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psSharedTransferCmd->asSrcSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ i++;
+ }
+ }
+ PVR_ASSERT(i == ui32RealSrcSyncNum);
+
+ i = 0;
+ for (loop = 0; loop < psKick->ui32NumDstSync; loop++)
+ {
+ if (abDstSyncEnable[loop])
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[loop];
+
+ psSyncInfo->psSyncData->ui64LastWrite = ui64KickCount;
+
+ PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_TRANSFER, TRANSFER_TOKEN_DST_SYNC,
+ psSyncInfo, PVRSRV_SYNCOP_SAMPLE);
+
+ psSharedTransferCmd->asDstSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ psSharedTransferCmd->asDstSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ psSharedTransferCmd->asDstSyncs[i].ui32ReadOps2PendingVal = psSyncInfo->psSyncData->ui32ReadOps2Pending;
+
+ psSharedTransferCmd->asDstSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psSharedTransferCmd->asDstSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ psSharedTransferCmd->asDstSyncs[i].sReadOps2CompleteDevVAddr = psSyncInfo->sReadOps2CompleteDevVAddr;
+ i++;
+ }
+ }
+ PVR_ASSERT(i == ui32RealDstSyncNum);
+
+
+ for (loop = 0; loop < psKick->ui32NumSrcSync; loop++)
+ {
+ if (abSrcSyncEnable[loop])
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[loop];
+ psSyncInfo->psSyncData->ui32ReadOpsPending++;
+ }
+ }
+ for (loop = 0; loop < psKick->ui32NumDstSync; loop++)
+ {
+ if (abDstSyncEnable[loop])
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[loop];
+ psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ }
+ }
+ }
+
+#if defined(PDUMP)
+ if ((PDumpIsCaptureFrameKM()
+ || ((psKick->ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
+ && (bPersistentProcess == IMG_FALSE) )
+ {
+ PDUMPCOMMENT("Shared part of transfer command\r\n");
+ PDUMPMEM(psSharedTransferCmd,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff,
+ sizeof(SGXMKIF_TRANSFERCMD_SHARED),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL)
+ {
+ IMG_UINT32 i = 0;
+
+ for (loop = 0; loop < psKick->ui32NumSrcSync; loop++)
+ {
+ if (abSrcSyncEnable[loop])
+ {
+ psSyncInfo = psKick->ahSrcSyncInfo[loop];
+
+ PDUMPCOMMENT("Hack src surface write op in transfer cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff + (IMG_UINT32)(offsetof(SGXMKIF_TRANSFERCMD_SHARED, asSrcSyncs) + i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal)),
+ sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ PDUMPCOMMENT("Hack src surface read op in transfer cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff + (IMG_UINT32)(offsetof(SGXMKIF_TRANSFERCMD_SHARED, asSrcSyncs) + i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal)),
+ sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+ i++;
+ }
+ }
+
+ i = 0;
+ for (loop = 0; loop < psKick->ui32NumDstSync; loop++)
+ {
+ if (abDstSyncEnable[i])
+ {
+ IMG_UINT32 ui32PDumpReadOp2 = 0;
+ psSyncInfo = psKick->ahDstSyncInfo[loop];
+
+ PDUMPCOMMENT("Hack dest surface write op in transfer cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff + (IMG_UINT32)(offsetof(SGXMKIF_TRANSFERCMD_SHARED, asDstSyncs) + i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal)),
+ sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ PDUMPCOMMENT("Hack dest surface read op in transfer cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff + (IMG_UINT32)(offsetof(SGXMKIF_TRANSFERCMD_SHARED, asDstSyncs) + i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal)),
+ sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ PDUMPCOMMENT("Hack dest surface read op2 in transfer cmd\r\n");
+ PDUMPMEM(&ui32PDumpReadOp2,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff + (IMG_UINT32)(offsetof(SGXMKIF_TRANSFERCMD_SHARED, asDstSyncs) + i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOps2PendingVal)),
+ sizeof(ui32PDumpReadOp2),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+ i++;
+ }
+ }
+
+
+ for (loop = 0; loop < (psKick->ui32NumSrcSync); loop++)
+ {
+ if (abSrcSyncEnable[loop])
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[loop];
+ psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
+ }
+ }
+
+ for (loop = 0; loop < (psKick->ui32NumDstSync); loop++)
+ {
+ if (abDstSyncEnable[loop])
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[0];
+ psSyncInfo->psSyncData->ui32LastOpDumpVal++;
+ }
+ }
+ }
+
+ if (psKick->hTASyncInfo != IMG_NULL)
+ {
+ psSyncInfo = psKick->hTASyncInfo;
+
+ PDUMPCOMMENT("Tweak TA/TQ surface write op in transfer cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff + (IMG_UINT32)(offsetof(SGXMKIF_TRANSFERCMD_SHARED, ui32TASyncWriteOpsPendingVal)),
+ sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ psSyncInfo->psSyncData->ui32LastOpDumpVal++;
+ }
+
+ if (psKick->h3DSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = psKick->h3DSyncInfo;
+
+ PDUMPCOMMENT("Tweak 3D/TQ surface write op in transfer cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff + (IMG_UINT32)(offsetof(SGXMKIF_TRANSFERCMD_SHARED, ui323DSyncWriteOpsPendingVal)),
+ sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ psSyncInfo->psSyncData->ui32LastOpDumpVal++;
+ }
+ }
+#endif
+
+ sCommand.ui32Data[1] = psKick->sHWTransferContextDevVAddr.uiAddr;
+
+ PVR_TTRACE(PVRSRV_TRACE_GROUP_TRANSFER, PVRSRV_TRACE_CLASS_CMD_END,
+ TRANSFER_TOKEN_SUBMIT);
+
+ eError = SGXScheduleCCBCommandKM(hDevHandle, SGXMKIF_CMD_TRANSFER, &sCommand, KERNEL_ID, psKick->ui32PDumpFlags, hDevMemContext, IMG_FALSE);
+
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+
+ if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL)
+ {
+ for (loop = 0; loop < psKick->ui32NumSrcSync; loop++)
+ {
+ if (abSrcSyncEnable[loop])
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[loop];
+ psSyncInfo->psSyncData->ui32ReadOpsPending--;
+#if defined(PDUMP)
+ if (PDumpIsCaptureFrameKM()
+ || ((psKick->ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
+ {
+ psSyncInfo->psSyncData->ui32LastReadOpDumpVal--;
+ }
+#endif
+ }
+ }
+ for (loop = 0; loop < psKick->ui32NumDstSync; loop++)
+ {
+ if (abDstSyncEnable[loop])
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[loop];
+ psSyncInfo->psSyncData->ui32WriteOpsPending--;
+#if defined(PDUMP)
+ if (PDumpIsCaptureFrameKM()
+ || ((psKick->ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
+ {
+ psSyncInfo->psSyncData->ui32LastOpDumpVal--;
+ }
+#endif
+ }
+ }
+ }
+
+
+ if (psKick->hTASyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+ psSyncInfo->psSyncData->ui32WriteOpsPending--;
+ }
+
+
+ if (psKick->h3DSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+ psSyncInfo->psSyncData->ui32WriteOpsPending--;
+ }
+ }
+
+ else if (PVRSRV_OK != eError)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXSubmitTransferKM: SGXScheduleCCBCommandKM failed."));
+ PVR_TTRACE(PVRSRV_TRACE_GROUP_TRANSFER, PVRSRV_TRACE_CLASS_FUNCTION_EXIT,
+ TRANSFER_TOKEN_SUBMIT);
+ return eError;
+ }
+
+
+#if defined(NO_HARDWARE)
+ if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_NOSYNCUPDATE) == 0)
+ {
+
+ for (loop = 0; loop < psKick->ui32NumSrcSync; loop++)
+ {
+ if (abSrcSyncEnable[loop])
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[loop];
+ psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ }
+ }
+
+ for (loop = 0; loop < psKick->ui32NumDstSync; loop++)
+ {
+ if (abDstSyncEnable[loop])
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[loop];
+ psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+ }
+
+ if (psKick->hTASyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+
+ psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+
+ if (psKick->h3DSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+
+ psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+ }
+#endif
+ PVR_TTRACE(PVRSRV_TRACE_GROUP_TRANSFER, PVRSRV_TRACE_CLASS_FUNCTION_EXIT,
+ TRANSFER_TOKEN_SUBMIT);
+ return eError;
+}
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+#if defined (SUPPORT_SID_INTERFACE)
+IMG_EXPORT PVRSRV_ERROR SGXSubmit2DKM(IMG_HANDLE hDevHandle, PVRSRV_2D_SGX_KICK_KM *psKick)
+#else
+IMG_EXPORT PVRSRV_ERROR SGXSubmit2DKM(IMG_HANDLE hDevHandle, PVRSRV_2D_SGX_KICK *psKick)
+#endif
+
+{
+ PVRSRV_KERNEL_MEM_INFO *psCCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psKick->hCCBMemInfo;
+ SGXMKIF_COMMAND sCommand = {0};
+ SGXMKIF_2DCMD_SHARED *ps2DCmd;
+ PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+ PVRSRV_ERROR eError;
+ IMG_UINT32 i;
+ IMG_HANDLE hDevMemContext = IMG_NULL;
+#if defined(PDUMP)
+ IMG_BOOL bPersistentProcess = IMG_FALSE;
+
+ {
+ PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData();
+ if(psPerProc != IMG_NULL)
+ {
+ bPersistentProcess = psPerProc->bPDumpPersistent;
+ }
+ }
+#endif
+#if defined(FIX_HW_BRN_31620)
+ hDevMemContext = psKick->hDevMemContext;
+#endif
+
+ if (!CCB_OFFSET_IS_VALID(SGXMKIF_2DCMD_SHARED, psCCBMemInfo, psKick, ui32SharedCmdCCBOffset))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXSubmit2DKM: Invalid CCB offset"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ ps2DCmd = CCB_DATA_FROM_OFFSET(SGXMKIF_2DCMD_SHARED, psCCBMemInfo, psKick, ui32SharedCmdCCBOffset);
+
+ OSMemSet(ps2DCmd, 0, sizeof(*ps2DCmd));
+
+
+ if (psKick->hTASyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+
+ ps2DCmd->sTASyncData.ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ ps2DCmd->sTASyncData.ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+ ps2DCmd->sTASyncData.sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ ps2DCmd->sTASyncData.sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ }
+
+
+ if (psKick->h3DSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+
+ ps2DCmd->s3DSyncData.ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ ps2DCmd->s3DSyncData.ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+ ps2DCmd->s3DSyncData.sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ ps2DCmd->s3DSyncData.sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ }
+
+
+ ps2DCmd->ui32NumSrcSync = psKick->ui32NumSrcSync;
+ for (i = 0; i < psKick->ui32NumSrcSync; i++)
+ {
+ psSyncInfo = psKick->ahSrcSyncInfo[i];
+
+ ps2DCmd->sSrcSyncData[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ ps2DCmd->sSrcSyncData[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+ ps2DCmd->sSrcSyncData[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ ps2DCmd->sSrcSyncData[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ }
+
+ if (psKick->hDstSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = psKick->hDstSyncInfo;
+
+ ps2DCmd->sDstSyncData.ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ ps2DCmd->sDstSyncData.ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ ps2DCmd->sDstSyncData.ui32ReadOps2PendingVal = psSyncInfo->psSyncData->ui32ReadOps2Pending;
+
+ ps2DCmd->sDstSyncData.sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ ps2DCmd->sDstSyncData.sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ ps2DCmd->sDstSyncData.sReadOps2CompleteDevVAddr = psSyncInfo->sReadOps2CompleteDevVAddr;
+ }
+
+
+ for (i = 0; i < psKick->ui32NumSrcSync; i++)
+ {
+ psSyncInfo = psKick->ahSrcSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsPending++;
+ }
+
+ if (psKick->hDstSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = psKick->hDstSyncInfo;
+ psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ }
+
+#if defined(PDUMP)
+ if ((PDumpIsCaptureFrameKM()
+ || ((psKick->ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
+ && (bPersistentProcess == IMG_FALSE) )
+ {
+
+ PDUMPCOMMENT("Shared part of 2D command\r\n");
+ PDUMPMEM(ps2DCmd,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff,
+ sizeof(SGXMKIF_2DCMD_SHARED),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ for (i = 0; i < psKick->ui32NumSrcSync; i++)
+ {
+ psSyncInfo = psKick->ahSrcSyncInfo[i];
+
+ PDUMPCOMMENT("Hack src surface write op in 2D cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff + (IMG_UINT32)offsetof(SGXMKIF_2DCMD_SHARED, sSrcSyncData[i].ui32WriteOpsPendingVal),
+ sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ PDUMPCOMMENT("Hack src surface read op in 2D cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff + (IMG_UINT32)offsetof(SGXMKIF_2DCMD_SHARED, sSrcSyncData[i].ui32ReadOpsPendingVal),
+ sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+ }
+
+ if (psKick->hDstSyncInfo != IMG_NULL)
+ {
+ IMG_UINT32 ui32PDumpReadOp2 = 0;
+ psSyncInfo = psKick->hDstSyncInfo;
+
+ PDUMPCOMMENT("Hack dest surface write op in 2D cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff + (IMG_UINT32)offsetof(SGXMKIF_2DCMD_SHARED, sDstSyncData.ui32WriteOpsPendingVal),
+ sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ PDUMPCOMMENT("Hack dest surface read op in 2D cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff + (IMG_UINT32)offsetof(SGXMKIF_2DCMD_SHARED, sDstSyncData.ui32ReadOpsPendingVal),
+ sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+ PDUMPCOMMENT("Hack dest surface read op2 in 2D cmd\r\n");
+ PDUMPMEM(&ui32PDumpReadOp2,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff + (IMG_UINT32)offsetof(SGXMKIF_2DCMD_SHARED, sDstSyncData.ui32ReadOps2PendingVal),
+ sizeof(ui32PDumpReadOp2),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+ }
+
+
+ for (i = 0; i < psKick->ui32NumSrcSync; i++)
+ {
+ psSyncInfo = psKick->ahSrcSyncInfo[i];
+ psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
+ }
+
+ if (psKick->hDstSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = psKick->hDstSyncInfo;
+ psSyncInfo->psSyncData->ui32LastOpDumpVal++;
+ }
+ }
+#endif
+
+ sCommand.ui32Data[1] = psKick->sHW2DContextDevVAddr.uiAddr;
+
+ eError = SGXScheduleCCBCommandKM(hDevHandle, SGXMKIF_CMD_2D, &sCommand, KERNEL_ID, psKick->ui32PDumpFlags, hDevMemContext, IMG_FALSE);
+
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+
+
+#if defined(PDUMP)
+ if (PDumpIsCaptureFrameKM())
+ {
+ for (i = 0; i < psKick->ui32NumSrcSync; i++)
+ {
+ psSyncInfo = psKick->ahSrcSyncInfo[i];
+ psSyncInfo->psSyncData->ui32LastReadOpDumpVal--;
+ }
+
+ if (psKick->hDstSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = psKick->hDstSyncInfo;
+ psSyncInfo->psSyncData->ui32LastOpDumpVal--;
+ }
+ }
+#endif
+
+ for (i = 0; i < psKick->ui32NumSrcSync; i++)
+ {
+ psSyncInfo = psKick->ahSrcSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsPending--;
+ }
+
+ if (psKick->hDstSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = psKick->hDstSyncInfo;
+ psSyncInfo->psSyncData->ui32WriteOpsPending--;
+ }
+
+
+ if (psKick->hTASyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+
+ psSyncInfo->psSyncData->ui32WriteOpsPending--;
+ }
+
+
+ if (psKick->h3DSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+
+ psSyncInfo->psSyncData->ui32WriteOpsPending--;
+ }
+ }
+
+
+
+
+#if defined(NO_HARDWARE)
+
+ for(i = 0; i < psKick->ui32NumSrcSync; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ }
+
+ if (psKick->hDstSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hDstSyncInfo;
+
+ psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+
+ if (psKick->hTASyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+
+ psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+
+ if (psKick->h3DSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+
+ psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+#endif
+
+ return eError;
+}
+#endif
+#endif
diff --git a/drivers/gpu/pvr/sgx/sgxutils.c b/drivers/gpu/pvr/sgx/sgxutils.c
new file mode 100644
index 0000000..528490b
--- /dev/null
+++ b/drivers/gpu/pvr/sgx/sgxutils.c
@@ -0,0 +1,1725 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include <stddef.h>
+
+#include "sgxdefs.h"
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "sgx_bridge_km.h"
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgx_mkif_km.h"
+#include "sysconfig.h"
+#include "pdump_km.h"
+#include "mmu.h"
+#include "pvr_bridge_km.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+#include "sgxutils.h"
+#include "ttrace.h"
+
+#ifdef __linux__
+#include <linux/kernel.h>
+#include <linux/string.h>
+#else
+#include <stdio.h>
+#endif
+
+IMG_UINT64 ui64KickCount;
+
+
+#if defined(SYS_CUSTOM_POWERDOWN)
+PVRSRV_ERROR SysPowerDownMISR(PVRSRV_DEVICE_NODE * psDeviceNode, IMG_UINT32 ui32CallerID);
+#endif
+
+
+
+static IMG_VOID SGXPostActivePowerEvent(PVRSRV_DEVICE_NODE * psDeviceNode,
+ IMG_UINT32 ui32CallerID)
+{
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl;
+
+
+ psSGXHostCtl->ui32NumActivePowerEvents++;
+
+ if ((psSGXHostCtl->ui32PowerStatus & PVRSRV_USSE_EDM_POWMAN_POWEROFF_RESTART_IMMEDIATE) != 0)
+ {
+
+
+
+ if (ui32CallerID == ISR_ID)
+ {
+ psDeviceNode->bReProcessDeviceCommandComplete = IMG_TRUE;
+ }
+ else
+ {
+ SGXScheduleProcessQueuesKM(psDeviceNode);
+ }
+ }
+}
+
+
+IMG_VOID SGXTestActivePowerEvent (PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 ui32CallerID)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl;
+
+#if defined(SYS_SUPPORTS_SGX_IDLE_CALLBACK)
+ if (!psDevInfo->bSGXIdle &&
+ ((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_IDLE) != 0))
+ {
+ psDevInfo->bSGXIdle = IMG_TRUE;
+ SysSGXIdleTransition(psDevInfo->bSGXIdle);
+ }
+ else if (psDevInfo->bSGXIdle &&
+ ((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_IDLE) == 0))
+ {
+ psDevInfo->bSGXIdle = IMG_FALSE;
+ SysSGXIdleTransition(psDevInfo->bSGXIdle);
+ }
+#endif
+
+ if (((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER) != 0) &&
+ ((psSGXHostCtl->ui32InterruptClearFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER) == 0))
+ {
+
+ psSGXHostCtl->ui32InterruptClearFlags |= PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER;
+
+
+ PDUMPSUSPEND();
+
+#if defined(SYS_CUSTOM_POWERDOWN)
+
+
+
+ eError = SysPowerDownMISR(psDeviceNode, ui32CallerID);
+#else
+ eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE_OFF,
+ ui32CallerID, IMG_FALSE);
+ if (eError == PVRSRV_OK)
+ {
+ SGXPostActivePowerEvent(psDeviceNode, ui32CallerID);
+ }
+#endif
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+
+
+ psSGXHostCtl->ui32InterruptClearFlags &= ~PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER;
+ eError = PVRSRV_OK;
+ }
+
+
+ PDUMPRESUME();
+ }
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXTestActivePowerEvent error:%u", eError));
+ }
+}
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SGXAcquireKernelCCBSlot)
+#endif
+static INLINE SGXMKIF_COMMAND * SGXAcquireKernelCCBSlot(PVRSRV_SGX_CCB_INFO *psCCB)
+{
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ if(((*psCCB->pui32WriteOffset + 1) & 255) != *psCCB->pui32ReadOffset)
+ {
+ return &psCCB->psCommands[*psCCB->pui32WriteOffset];
+ }
+
+ OSSleepms(1);
+ } END_LOOP_UNTIL_TIMEOUT();
+
+
+ return IMG_NULL;
+}
+
+PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_DEVICE_NODE *psDeviceNode,
+ SGXMKIF_CMD_TYPE eCmdType,
+ SGXMKIF_COMMAND *psCommandData,
+ IMG_UINT32 ui32CallerID,
+ IMG_UINT32 ui32PDumpFlags,
+ IMG_HANDLE hDevMemContext,
+ IMG_BOOL bLastInScene)
+{
+ PVRSRV_SGX_CCB_INFO *psKernelCCB;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ SGXMKIF_COMMAND *psSGXCommand;
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+#if defined(FIX_HW_BRN_31620)
+ IMG_UINT32 ui32CacheMasks[4];
+ IMG_UINT32 i;
+ MMU_CONTEXT *psMMUContext;
+#endif
+#if defined(PDUMP)
+ IMG_VOID *pvDumpCommand;
+ IMG_BOOL bPDumpIsSuspended = PDumpIsSuspended();
+ IMG_BOOL bPersistentProcess = IMG_FALSE;
+#else
+ PVR_UNREFERENCED_PARAMETER(ui32CallerID);
+ PVR_UNREFERENCED_PARAMETER(ui32PDumpFlags);
+#endif
+
+#if defined(FIX_HW_BRN_31620)
+ for(i=0;i<4;i++)
+ {
+ ui32CacheMasks[i] = 0;
+ }
+
+ psMMUContext = psDevInfo->hKernelMMUContext;
+ psDeviceNode->pfnMMUGetCacheFlushRange(psMMUContext, &ui32CacheMasks[0]);
+
+
+ if (hDevMemContext)
+ {
+ BM_CONTEXT *psBMContext = (BM_CONTEXT *) hDevMemContext;
+
+ psMMUContext = psBMContext->psMMUContext;
+ psDeviceNode->pfnMMUGetCacheFlushRange(psMMUContext, &ui32CacheMasks[2]);
+ }
+
+
+ if (ui32CacheMasks[0] || ui32CacheMasks[1] || ui32CacheMasks[2] || ui32CacheMasks[3])
+ {
+ psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_BIF_PD;
+ }
+#endif
+
+#if defined(FIX_HW_BRN_28889)
+
+
+
+
+ if ( (eCmdType != SGXMKIF_CMD_PROCESS_QUEUES) &&
+ ((psDevInfo->ui32CacheControl & SGXMKIF_CC_INVAL_DATA) != 0) &&
+ ((psDevInfo->ui32CacheControl & (SGXMKIF_CC_INVAL_BIF_PT | SGXMKIF_CC_INVAL_BIF_PD)) != 0))
+ {
+ #if defined(PDUMP)
+ PVRSRV_KERNEL_MEM_INFO *psSGXHostCtlMemInfo = psDevInfo->psKernelSGXHostCtlMemInfo;
+ #endif
+ SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl;
+ SGXMKIF_COMMAND sCacheCommand = {0};
+
+ eError = SGXScheduleCCBCommand(psDeviceNode,
+ SGXMKIF_CMD_PROCESS_QUEUES,
+ &sCacheCommand,
+ ui32CallerID,
+ ui32PDumpFlags,
+ hDevMemContext,
+ bLastInScene);
+ if (eError != PVRSRV_OK)
+ {
+ goto Exit;
+ }
+
+
+ #if !defined(NO_HARDWARE)
+ if(PollForValueKM(&psSGXHostCtl->ui32InvalStatus,
+ PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE,
+ PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE,
+ 2 * MAX_HW_TIME_US,
+ MAX_HW_TIME_US/WAIT_TRY_COUNT,
+ IMG_FALSE) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXScheduleCCBCommand: Wait for uKernel to Invalidate BIF cache failed"));
+ PVR_DBG_BREAK;
+ }
+ #endif
+
+ #if defined(PDUMP)
+
+ PDUMPCOMMENTWITHFLAGS(0, "Host Control - Poll for BIF cache invalidate request to complete");
+ PDUMPMEMPOL(psSGXHostCtlMemInfo,
+ offsetof(SGXMKIF_HOST_CTL, ui32InvalStatus),
+ PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE,
+ PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ 0,
+ MAKEUNIQUETAG(psSGXHostCtlMemInfo));
+ #endif
+
+ psSGXHostCtl->ui32InvalStatus &= ~(PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE);
+ PDUMPMEM(IMG_NULL, psSGXHostCtlMemInfo, offsetof(SGXMKIF_HOST_CTL, ui32CleanupStatus), sizeof(IMG_UINT32), 0, MAKEUNIQUETAG(psSGXHostCtlMemInfo));
+ }
+#else
+ PVR_UNREFERENCED_PARAMETER(hDevMemContext);
+#endif
+
+#if defined(FIX_HW_BRN_31620)
+ if ((eCmdType != SGXMKIF_CMD_FLUSHPDCACHE) && (psDevInfo->ui32CacheControl & SGXMKIF_CC_INVAL_BIF_PD))
+ {
+ SGXMKIF_COMMAND sPDECacheCommand = {0};
+ IMG_DEV_PHYADDR sDevPAddr;
+
+
+ psMMUContext = psDevInfo->hKernelMMUContext;
+
+ psDeviceNode->pfnMMUGetPDPhysAddr(psMMUContext, &sDevPAddr);
+ sPDECacheCommand.ui32Data[0] = sDevPAddr.uiAddr | 1;
+ sPDECacheCommand.ui32Data[1] = ui32CacheMasks[0];
+ sPDECacheCommand.ui32Data[2] = ui32CacheMasks[1];
+
+
+ if (hDevMemContext)
+ {
+ BM_CONTEXT *psBMContext = (BM_CONTEXT *) hDevMemContext;
+
+ psMMUContext = psBMContext->psMMUContext;
+
+ psDeviceNode->pfnMMUGetPDPhysAddr(psMMUContext, &sDevPAddr);
+
+ sPDECacheCommand.ui32Data[3] = sDevPAddr.uiAddr | 1;
+ sPDECacheCommand.ui32Data[4] = ui32CacheMasks[2];
+ sPDECacheCommand.ui32Data[5] = ui32CacheMasks[3];
+ }
+
+
+ if (sPDECacheCommand.ui32Data[1] | sPDECacheCommand.ui32Data[2] | sPDECacheCommand.ui32Data[4] |
+ sPDECacheCommand.ui32Data[5])
+ {
+ eError = SGXScheduleCCBCommand(psDeviceNode,
+ SGXMKIF_CMD_FLUSHPDCACHE,
+ &sPDECacheCommand,
+ ui32CallerID,
+ ui32PDumpFlags,
+ hDevMemContext,
+ bLastInScene);
+ if (eError != PVRSRV_OK)
+ {
+ goto Exit;
+ }
+ }
+ }
+#endif
+#if defined(PDUMP)
+
+ {
+ PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData();
+ if(psPerProc != IMG_NULL)
+ {
+ bPersistentProcess = psPerProc->bPDumpPersistent;
+ }
+ }
+#endif
+ psKernelCCB = psDevInfo->psKernelCCBInfo;
+
+ psSGXCommand = SGXAcquireKernelCCBSlot(psKernelCCB);
+
+
+ if(!psSGXCommand)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXScheduleCCBCommand: Wait for CCB space timed out")) ;
+ eError = PVRSRV_ERROR_TIMEOUT;
+ goto Exit;
+ }
+
+
+ psCommandData->ui32CacheControl = psDevInfo->ui32CacheControl;
+
+#if defined(PDUMP)
+
+ psDevInfo->sPDContext.ui32CacheControl |= psDevInfo->ui32CacheControl;
+#endif
+
+
+ psDevInfo->ui32CacheControl = 0;
+
+
+ *psSGXCommand = *psCommandData;
+
+ if (eCmdType >= SGXMKIF_CMD_MAX)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXScheduleCCBCommand: Unknown command type: %d", eCmdType)) ;
+ eError = PVRSRV_ERROR_INVALID_CCB_COMMAND;
+ goto Exit;
+ }
+
+ if (eCmdType == SGXMKIF_CMD_2D ||
+ eCmdType == SGXMKIF_CMD_TRANSFER ||
+ ((eCmdType == SGXMKIF_CMD_TA) && bLastInScene))
+ {
+ SYS_DATA *psSysData;
+
+
+ SysAcquireData(&psSysData);
+
+ if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH)
+ {
+ OSFlushCPUCacheKM();
+ }
+ else if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN)
+ {
+ OSCleanCPUCacheKM();
+ }
+
+
+ psSysData->ePendingCacheOpType = PVRSRV_MISC_INFO_CPUCACHEOP_NONE;
+ }
+
+ PVR_ASSERT(eCmdType < SGXMKIF_CMD_MAX);
+ psSGXCommand->ui32ServiceAddress = psDevInfo->aui32HostKickAddr[eCmdType];
+
+#if defined(PDUMP)
+ if ((ui32CallerID != ISR_ID) && (bPDumpIsSuspended == IMG_FALSE) &&
+ (bPersistentProcess == IMG_FALSE) )
+ {
+
+ PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Poll for space in the Kernel CCB\r\n");
+ PDUMPMEMPOL(psKernelCCB->psCCBCtlMemInfo,
+ offsetof(PVRSRV_SGX_CCB_CTL, ui32ReadOffset),
+ (psKernelCCB->ui32CCBDumpWOff + 1) & 0xff,
+ 0xff,
+ PDUMP_POLL_OPERATOR_NOTEQUAL,
+ ui32PDumpFlags,
+ MAKEUNIQUETAG(psKernelCCB->psCCBCtlMemInfo));
+
+ PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Kernel CCB command (type == %d)\r\n", eCmdType);
+ pvDumpCommand = (IMG_VOID *)((IMG_UINT8 *)psKernelCCB->psCCBMemInfo->pvLinAddrKM + (*psKernelCCB->pui32WriteOffset * sizeof(SGXMKIF_COMMAND)));
+
+ PDUMPMEM(pvDumpCommand,
+ psKernelCCB->psCCBMemInfo,
+ psKernelCCB->ui32CCBDumpWOff * sizeof(SGXMKIF_COMMAND),
+ sizeof(SGXMKIF_COMMAND),
+ ui32PDumpFlags,
+ MAKEUNIQUETAG(psKernelCCB->psCCBMemInfo));
+
+
+ PDUMPMEM(&psDevInfo->sPDContext.ui32CacheControl,
+ psKernelCCB->psCCBMemInfo,
+ psKernelCCB->ui32CCBDumpWOff * sizeof(SGXMKIF_COMMAND) +
+ offsetof(SGXMKIF_COMMAND, ui32CacheControl),
+ sizeof(IMG_UINT32),
+ ui32PDumpFlags,
+ MAKEUNIQUETAG(psKernelCCB->psCCBMemInfo));
+
+ if (PDumpIsCaptureFrameKM()
+ || ((ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
+ {
+
+ psDevInfo->sPDContext.ui32CacheControl = 0;
+ }
+ }
+#endif
+
+#if defined(FIX_HW_BRN_26620) && defined(SGX_FEATURE_SYSTEM_CACHE) && !defined(SGX_BYPASS_SYSTEM_CACHE)
+
+ eError = PollForValueKM (psKernelCCB->pui32ReadOffset,
+ *psKernelCCB->pui32WriteOffset,
+ 0xFF,
+ MAX_HW_TIME_US,
+ MAX_HW_TIME_US/WAIT_TRY_COUNT,
+ IMG_FALSE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXScheduleCCBCommand: Timeout waiting for previous command to be read")) ;
+ eError = PVRSRV_ERROR_TIMEOUT;
+ goto Exit;
+ }
+#endif
+
+
+
+ *psKernelCCB->pui32WriteOffset = (*psKernelCCB->pui32WriteOffset + 1) & 255;
+
+#if defined(PDUMP)
+ if ((ui32CallerID != ISR_ID) && (bPDumpIsSuspended == IMG_FALSE) &&
+ (bPersistentProcess == IMG_FALSE) )
+ {
+ #if defined(FIX_HW_BRN_26620) && defined(SGX_FEATURE_SYSTEM_CACHE) && !defined(SGX_BYPASS_SYSTEM_CACHE)
+ PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Poll for previous Kernel CCB CMD to be read\r\n");
+ PDUMPMEMPOL(psKernelCCB->psCCBCtlMemInfo,
+ offsetof(PVRSRV_SGX_CCB_CTL, ui32ReadOffset),
+ (psKernelCCB->ui32CCBDumpWOff),
+ 0xFF,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ ui32PDumpFlags,
+ MAKEUNIQUETAG(psKernelCCB->psCCBCtlMemInfo));
+ #endif
+
+ if (PDumpIsCaptureFrameKM()
+ || ((ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
+ {
+ psKernelCCB->ui32CCBDumpWOff = (psKernelCCB->ui32CCBDumpWOff + 1) & 0xFF;
+ psDevInfo->ui32KernelCCBEventKickerDumpVal = (psDevInfo->ui32KernelCCBEventKickerDumpVal + 1) & 0xFF;
+ }
+
+ PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Kernel CCB write offset\r\n");
+ PDUMPMEM(&psKernelCCB->ui32CCBDumpWOff,
+ psKernelCCB->psCCBCtlMemInfo,
+ offsetof(PVRSRV_SGX_CCB_CTL, ui32WriteOffset),
+ sizeof(IMG_UINT32),
+ ui32PDumpFlags,
+ MAKEUNIQUETAG(psKernelCCB->psCCBCtlMemInfo));
+ PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Kernel CCB event kicker\r\n");
+ PDUMPMEM(&psDevInfo->ui32KernelCCBEventKickerDumpVal,
+ psDevInfo->psKernelCCBEventKickerMemInfo,
+ 0,
+ sizeof(IMG_UINT32),
+ ui32PDumpFlags,
+ MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
+ PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Kick the SGX microkernel\r\n");
+ #if defined(FIX_HW_BRN_26620) && defined(SGX_FEATURE_SYSTEM_CACHE) && !defined(SGX_BYPASS_SYSTEM_CACHE)
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK2, 0), EUR_CR_EVENT_KICK2_NOW_MASK, ui32PDumpFlags);
+ #else
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0), EUR_CR_EVENT_KICK_NOW_MASK, ui32PDumpFlags);
+ #endif
+ }
+#endif
+
+ *psDevInfo->pui32KernelCCBEventKicker = (*psDevInfo->pui32KernelCCBEventKicker + 1) & 0xFF;
+
+ OSWriteMemoryBarrier();
+
+
+ PVR_TTRACE_UI32(PVRSRV_TRACE_GROUP_MKSYNC, PVRSRV_TRACE_CLASS_NONE,
+ MKSYNC_TOKEN_KERNEL_CCB_OFFSET, *psKernelCCB->pui32WriteOffset);
+ PVR_TTRACE_UI32(PVRSRV_TRACE_GROUP_MKSYNC, PVRSRV_TRACE_CLASS_NONE,
+ MKSYNC_TOKEN_CORE_CLK, psDevInfo->ui32CoreClockSpeed);
+ PVR_TTRACE_UI32(PVRSRV_TRACE_GROUP_MKSYNC, PVRSRV_TRACE_CLASS_NONE,
+ MKSYNC_TOKEN_UKERNEL_CLK, psDevInfo->ui32uKernelTimerClock);
+
+
+#if defined(FIX_HW_BRN_26620) && defined(SGX_FEATURE_SYSTEM_CACHE) && !defined(SGX_BYPASS_SYSTEM_CACHE)
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM,
+ SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK2, 0),
+ EUR_CR_EVENT_KICK2_NOW_MASK);
+#else
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM,
+ SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0),
+ EUR_CR_EVENT_KICK_NOW_MASK);
+#endif
+
+ OSMemoryBarrier();
+
+#if defined(NO_HARDWARE)
+
+ *psKernelCCB->pui32ReadOffset = (*psKernelCCB->pui32ReadOffset + 1) & 255;
+#endif
+
+ ui64KickCount++;
+Exit:
+ return eError;
+}
+
+
+PVRSRV_ERROR SGXScheduleCCBCommandKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ SGXMKIF_CMD_TYPE eCmdType,
+ SGXMKIF_COMMAND *psCommandData,
+ IMG_UINT32 ui32CallerID,
+ IMG_UINT32 ui32PDumpFlags,
+ IMG_HANDLE hDevMemContext,
+ IMG_BOOL bLastInScene)
+{
+ PVRSRV_ERROR eError;
+
+
+ PDUMPSUSPEND();
+
+
+ eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE_ON,
+ ui32CallerID,
+ IMG_TRUE);
+
+ PDUMPRESUME();
+
+ if (eError == PVRSRV_OK)
+ {
+ psDeviceNode->bReProcessDeviceCommandComplete = IMG_FALSE;
+ }
+ else
+ {
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+ if (ui32CallerID == ISR_ID)
+ {
+ SYS_DATA *psSysData;
+
+
+
+
+ psDeviceNode->bReProcessDeviceCommandComplete = IMG_TRUE;
+ eError = PVRSRV_OK;
+
+ SysAcquireData(&psSysData);
+ OSScheduleMISR(psSysData);
+ }
+ else
+ {
+
+
+ }
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXScheduleCCBCommandKM failed to acquire lock - "
+ "ui32CallerID:%d eError:%u", ui32CallerID, eError));
+ }
+
+ return eError;
+ }
+
+ eError = SGXScheduleCCBCommand(psDeviceNode, eCmdType, psCommandData, ui32CallerID, ui32PDumpFlags, hDevMemContext, bLastInScene);
+
+ PVRSRVPowerUnlock(ui32CallerID);
+ return eError;
+}
+
+
+PVRSRV_ERROR SGXScheduleProcessQueuesKM(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ SGXMKIF_HOST_CTL *psHostCtl = psDevInfo->psKernelSGXHostCtlMemInfo->pvLinAddrKM;
+ IMG_UINT32 ui32PowerStatus;
+ SGXMKIF_COMMAND sCommand = {0};
+
+ ui32PowerStatus = psHostCtl->ui32PowerStatus;
+ if ((ui32PowerStatus & PVRSRV_USSE_EDM_POWMAN_NO_WORK) != 0)
+ {
+
+ return PVRSRV_OK;
+ }
+
+ eError = SGXScheduleCCBCommandKM(psDeviceNode, SGXMKIF_CMD_PROCESS_QUEUES, &sCommand, ISR_ID, 0, IMG_NULL, IMG_FALSE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXScheduleProcessQueuesKM failed to schedule CCB command: %u", eError));
+ return eError;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+IMG_BOOL SGXIsDevicePowered(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ return PVRSRVIsDevicePowered(psDeviceNode->sDevId.ui32DeviceIndex);
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGXGetInternalDevInfoKM(IMG_HANDLE hDevCookie,
+#if defined (SUPPORT_SID_INTERFACE)
+ SGX_INTERNAL_DEVINFO_KM *psSGXInternalDevInfo)
+#else
+ SGX_INTERNAL_DEVINFO *psSGXInternalDevInfo)
+#endif
+{
+ PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
+
+ psSGXInternalDevInfo->ui32Flags = psDevInfo->ui32Flags;
+ psSGXInternalDevInfo->bForcePTOff = (IMG_BOOL)psDevInfo->bForcePTOff;
+
+
+ psSGXInternalDevInfo->hHostCtlKernelMemInfoHandle =
+ (IMG_HANDLE)psDevInfo->psKernelSGXHostCtlMemInfo;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR SGXCleanupRequest(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_DEV_VIRTADDR *psHWDataDevVAddr,
+ IMG_UINT32 ui32CleanupType,
+ IMG_BOOL bForceCleanup)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ PVRSRV_KERNEL_MEM_INFO *psHostCtlMemInfo = psDevInfo->psKernelSGXHostCtlMemInfo;
+ SGXMKIF_HOST_CTL *psHostCtl = psHostCtlMemInfo->pvLinAddrKM;
+
+ SGXMKIF_COMMAND sCommand = {0};
+
+
+ if (bForceCleanup != FORCE_CLEANUP)
+ {
+ sCommand.ui32Data[0] = ui32CleanupType;
+ sCommand.ui32Data[1] = (psHWDataDevVAddr == IMG_NULL) ? 0 : psHWDataDevVAddr->uiAddr;
+ PDUMPCOMMENTWITHFLAGS(0, "Request ukernel resource clean-up, Type %u, Data 0x%X", sCommand.ui32Data[0], sCommand.ui32Data[1]);
+
+ eError = SGXScheduleCCBCommandKM(psDeviceNode, SGXMKIF_CMD_CLEANUP, &sCommand, KERNEL_ID, 0, IMG_NULL, IMG_FALSE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXCleanupRequest: Failed to submit clean-up command"));
+ SGXDumpDebugInfo(psDevInfo, IMG_FALSE);
+ PVR_DBG_BREAK;
+ return eError;
+ }
+
+
+ #if !defined(NO_HARDWARE)
+ if(PollForValueKM(&psHostCtl->ui32CleanupStatus,
+ PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE,
+ PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE,
+ 10 * MAX_HW_TIME_US,
+ 1000,
+ IMG_TRUE) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXCleanupRequest: Wait for uKernel to clean up (%u) failed", ui32CleanupType));
+ eError = PVRSRV_ERROR_TIMEOUT;
+ SGXDumpDebugInfo(psDevInfo, IMG_FALSE);
+ PVR_DBG_BREAK;
+ }
+ #endif
+
+ #if defined(PDUMP)
+
+
+
+
+
+
+
+
+ PDUMPCOMMENTWITHFLAGS(0, "Host Control - Poll for clean-up request to complete");
+ PDUMPMEMPOL(psHostCtlMemInfo,
+ offsetof(SGXMKIF_HOST_CTL, ui32CleanupStatus),
+ PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE | PVRSRV_USSE_EDM_CLEANUPCMD_DONE,
+ PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE | PVRSRV_USSE_EDM_CLEANUPCMD_DONE,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ 0,
+ MAKEUNIQUETAG(psHostCtlMemInfo));
+ #endif
+
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+
+ if (psHostCtl->ui32CleanupStatus & PVRSRV_USSE_EDM_CLEANUPCMD_BUSY)
+ {
+
+ PVR_ASSERT((psHostCtl->ui32CleanupStatus & PVRSRV_USSE_EDM_CLEANUPCMD_DONE) == 0);
+ eError = PVRSRV_ERROR_RETRY;
+ psHostCtl->ui32CleanupStatus &= ~(PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE | PVRSRV_USSE_EDM_CLEANUPCMD_BUSY);
+ }
+ else
+ {
+ eError = PVRSRV_OK;
+ psHostCtl->ui32CleanupStatus &= ~(PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE | PVRSRV_USSE_EDM_CLEANUPCMD_DONE);
+ }
+
+ PDUMPMEM(IMG_NULL, psHostCtlMemInfo, offsetof(SGXMKIF_HOST_CTL, ui32CleanupStatus), sizeof(IMG_UINT32), 0, MAKEUNIQUETAG(psHostCtlMemInfo));
+
+
+#if defined(SGX_FEATURE_SYSTEM_CACHE)
+ psDevInfo->ui32CacheControl |= (SGXMKIF_CC_INVAL_BIF_SL | SGXMKIF_CC_INVAL_DATA);
+#else
+ psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_DATA;
+#endif
+ return eError;
+}
+
+
+typedef struct _SGX_HW_RENDER_CONTEXT_CLEANUP_
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ PVRSRV_KERNEL_MEM_INFO *psHWRenderContextMemInfo;
+ IMG_HANDLE hBlockAlloc;
+ PRESMAN_ITEM psResItem;
+ IMG_BOOL bCleanupTimerRunning;
+ IMG_PVOID pvTimeData;
+} SGX_HW_RENDER_CONTEXT_CLEANUP;
+
+
+static PVRSRV_ERROR SGXCleanupHWRenderContextCallback(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param,
+ IMG_BOOL bForceCleanup)
+{
+ PVRSRV_ERROR eError;
+ SGX_HW_RENDER_CONTEXT_CLEANUP *psCleanup = pvParam;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ eError = SGXCleanupRequest(psCleanup->psDeviceNode,
+ &psCleanup->psHWRenderContextMemInfo->sDevVAddr,
+ PVRSRV_CLEANUPCMD_RC,
+ bForceCleanup);
+
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+ if (!psCleanup->bCleanupTimerRunning)
+ {
+ OSTimeCreateWithUSOffset(&psCleanup->pvTimeData, MAX_CLEANUP_TIME_US);
+ psCleanup->bCleanupTimerRunning = IMG_TRUE;
+ }
+ else
+ {
+ if (OSTimeHasTimePassed(psCleanup->pvTimeData))
+ {
+ eError = PVRSRV_ERROR_TIMEOUT_POLLING_FOR_VALUE;
+ psCleanup->bCleanupTimerRunning = IMG_FALSE;
+ OSTimeDestroy(psCleanup->pvTimeData);
+ }
+ }
+ }
+ else
+ {
+ if (psCleanup->bCleanupTimerRunning)
+ {
+ OSTimeDestroy(psCleanup->pvTimeData);
+ }
+ }
+
+ if (eError != PVRSRV_ERROR_RETRY)
+ {
+
+ PVRSRVFreeDeviceMemKM(psCleanup->psDeviceNode,
+ psCleanup->psHWRenderContextMemInfo);
+
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(SGX_HW_RENDER_CONTEXT_CLEANUP),
+ psCleanup,
+ psCleanup->hBlockAlloc);
+
+ }
+
+ return eError;
+}
+
+typedef struct _SGX_HW_TRANSFER_CONTEXT_CLEANUP_
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ PVRSRV_KERNEL_MEM_INFO *psHWTransferContextMemInfo;
+ IMG_HANDLE hBlockAlloc;
+ PRESMAN_ITEM psResItem;
+ IMG_BOOL bCleanupTimerRunning;
+ IMG_PVOID pvTimeData;
+} SGX_HW_TRANSFER_CONTEXT_CLEANUP;
+
+
+static PVRSRV_ERROR SGXCleanupHWTransferContextCallback(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param,
+ IMG_BOOL bForceCleanup)
+{
+ PVRSRV_ERROR eError;
+ SGX_HW_TRANSFER_CONTEXT_CLEANUP *psCleanup = (SGX_HW_TRANSFER_CONTEXT_CLEANUP *)pvParam;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ eError = SGXCleanupRequest(psCleanup->psDeviceNode,
+ &psCleanup->psHWTransferContextMemInfo->sDevVAddr,
+ PVRSRV_CLEANUPCMD_TC,
+ bForceCleanup);
+
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+ if (!psCleanup->bCleanupTimerRunning)
+ {
+ OSTimeCreateWithUSOffset(&psCleanup->pvTimeData, MAX_CLEANUP_TIME_US);
+ psCleanup->bCleanupTimerRunning = IMG_TRUE;
+ }
+ else
+ {
+ if (OSTimeHasTimePassed(psCleanup->pvTimeData))
+ {
+ eError = PVRSRV_ERROR_TIMEOUT_POLLING_FOR_VALUE;
+ psCleanup->bCleanupTimerRunning = IMG_FALSE;
+ OSTimeDestroy(psCleanup->pvTimeData);
+ }
+ }
+ }
+ else
+ {
+ if (psCleanup->bCleanupTimerRunning)
+ {
+ OSTimeDestroy(psCleanup->pvTimeData);
+ }
+ }
+
+ if (eError != PVRSRV_ERROR_RETRY)
+ {
+
+ PVRSRVFreeDeviceMemKM(psCleanup->psDeviceNode,
+ psCleanup->psHWTransferContextMemInfo);
+
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(SGX_HW_TRANSFER_CONTEXT_CLEANUP),
+ psCleanup,
+ psCleanup->hBlockAlloc);
+
+ }
+
+ return eError;
+}
+
+IMG_EXPORT
+IMG_HANDLE SGXRegisterHWRenderContextKM(IMG_HANDLE hDeviceNode,
+ IMG_CPU_VIRTADDR *psHWRenderContextCpuVAddr,
+ IMG_UINT32 ui32HWRenderContextSize,
+ IMG_UINT32 ui32OffsetToPDDevPAddr,
+ IMG_HANDLE hDevMemContext,
+ IMG_DEV_VIRTADDR *psHWRenderContextDevVAddr,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hBlockAlloc;
+ SGX_HW_RENDER_CONTEXT_CLEANUP *psCleanup;
+ PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)hDeviceNode;
+ DEVICE_MEMORY_INFO *psDevMemoryInfo;
+ DEVICE_MEMORY_HEAP_INFO *psHeapInfo;
+ IMG_HANDLE hDevMemContextInt;
+ MMU_CONTEXT *psMMUContext;
+ IMG_DEV_PHYADDR sPDDevPAddr;
+ int iPtrByte;
+ IMG_UINT8 *pSrc;
+ IMG_UINT8 *pDst;
+ PRESMAN_ITEM psResItem;
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(SGX_HW_RENDER_CONTEXT_CLEANUP),
+ (IMG_VOID **)&psCleanup,
+ &hBlockAlloc,
+ "SGX Hardware Render Context Cleanup");
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWRenderContextKM: Couldn't allocate memory for SGX_HW_RENDER_CONTEXT_CLEANUP structure"));
+ goto exit0;
+ }
+
+ psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+ psHeapInfo = &psDevMemoryInfo->psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID];
+
+ eError = PVRSRVAllocDeviceMemKM(hDeviceNode,
+ psPerProc,
+ psHeapInfo->hDevMemHeap,
+ PVRSRV_MEM_READ | PVRSRV_MEM_WRITE
+ | PVRSRV_MEM_NO_SYNCOBJ | PVRSRV_MEM_EDM_PROTECT
+ | PVRSRV_MEM_CACHE_CONSISTENT,
+ ui32HWRenderContextSize,
+ 32,
+ IMG_NULL,
+ 0,
+ &psCleanup->psHWRenderContextMemInfo,
+ "HW Render Context");
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWRenderContextKM: Couldn't allocate device memory for HW Render Context"));
+ goto exit1;
+ }
+
+ eError = OSCopyFromUser(psPerProc,
+ psCleanup->psHWRenderContextMemInfo->pvLinAddrKM,
+ psHWRenderContextCpuVAddr,
+ ui32HWRenderContextSize);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWRenderContextKM: Couldn't copy user-mode copy of HWContext into device memory"));
+ goto exit2;
+ }
+
+
+ psHWRenderContextDevVAddr->uiAddr = psCleanup->psHWRenderContextMemInfo->sDevVAddr.uiAddr;
+
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevMemContextInt,
+ hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWRenderContextKM: Can't lookup DevMem Context"));
+ goto exit2;
+ }
+
+ psMMUContext = BM_GetMMUContextFromMemContext(hDevMemContextInt);
+ sPDDevPAddr = psDeviceNode->pfnMMUGetPDDevPAddr(psMMUContext);
+
+
+
+
+
+
+ pSrc = (IMG_UINT8 *)&sPDDevPAddr;
+ pDst = (IMG_UINT8 *)psCleanup->psHWRenderContextMemInfo->pvLinAddrKM;
+ pDst += ui32OffsetToPDDevPAddr;
+
+ for (iPtrByte = 0; iPtrByte < sizeof(IMG_DEV_PHYADDR); iPtrByte++)
+ {
+ pDst[iPtrByte] = pSrc[iPtrByte];
+ }
+
+#if defined(PDUMP)
+
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "HW Render context struct");
+
+ PDUMPMEM(
+ IMG_NULL,
+ psCleanup->psHWRenderContextMemInfo,
+ 0,
+ ui32HWRenderContextSize,
+ PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psCleanup->psHWRenderContextMemInfo));
+
+
+ PDUMPCOMMENT("Page directory address in HW render context");
+ PDUMPPDDEVPADDR(
+ psCleanup->psHWRenderContextMemInfo,
+ ui32OffsetToPDDevPAddr,
+ sPDDevPAddr,
+ MAKEUNIQUETAG(psCleanup->psHWRenderContextMemInfo),
+ PDUMP_PD_UNIQUETAG);
+#endif
+
+ psCleanup->hBlockAlloc = hBlockAlloc;
+ psCleanup->psDeviceNode = psDeviceNode;
+ psCleanup->bCleanupTimerRunning = IMG_FALSE;
+
+ psResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_HW_RENDER_CONTEXT,
+ (IMG_VOID *)psCleanup,
+ 0,
+ &SGXCleanupHWRenderContextCallback);
+
+ if (psResItem == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWRenderContextKM: ResManRegisterRes failed"));
+ goto exit2;
+ }
+
+ psCleanup->psResItem = psResItem;
+
+ return (IMG_HANDLE)psCleanup;
+
+exit2:
+ PVRSRVFreeDeviceMemKM(hDeviceNode,
+ psCleanup->psHWRenderContextMemInfo);
+exit1:
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(SGX_HW_RENDER_CONTEXT_CLEANUP),
+ psCleanup,
+ psCleanup->hBlockAlloc);
+
+exit0:
+ return IMG_NULL;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGXUnregisterHWRenderContextKM(IMG_HANDLE hHWRenderContext, IMG_BOOL bForceCleanup)
+{
+ PVRSRV_ERROR eError;
+ SGX_HW_RENDER_CONTEXT_CLEANUP *psCleanup;
+
+ PVR_ASSERT(hHWRenderContext != IMG_NULL);
+
+ psCleanup = (SGX_HW_RENDER_CONTEXT_CLEANUP *)hHWRenderContext;
+
+ if (psCleanup == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXUnregisterHWRenderContextKM: invalid parameter"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ eError = ResManFreeResByPtr(psCleanup->psResItem, bForceCleanup);
+
+ return eError;
+}
+
+
+IMG_EXPORT
+IMG_HANDLE SGXRegisterHWTransferContextKM(IMG_HANDLE hDeviceNode,
+ IMG_CPU_VIRTADDR *psHWTransferContextCpuVAddr,
+ IMG_UINT32 ui32HWTransferContextSize,
+ IMG_UINT32 ui32OffsetToPDDevPAddr,
+ IMG_HANDLE hDevMemContext,
+ IMG_DEV_VIRTADDR *psHWTransferContextDevVAddr,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hBlockAlloc;
+ SGX_HW_TRANSFER_CONTEXT_CLEANUP *psCleanup;
+ PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)hDeviceNode;
+ DEVICE_MEMORY_INFO *psDevMemoryInfo;
+ DEVICE_MEMORY_HEAP_INFO *psHeapInfo;
+ IMG_HANDLE hDevMemContextInt;
+ MMU_CONTEXT *psMMUContext;
+ IMG_DEV_PHYADDR sPDDevPAddr;
+ int iPtrByte;
+ IMG_UINT8 *pSrc;
+ IMG_UINT8 *pDst;
+ PRESMAN_ITEM psResItem;
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(SGX_HW_TRANSFER_CONTEXT_CLEANUP),
+ (IMG_VOID **)&psCleanup,
+ &hBlockAlloc,
+ "SGX Hardware Transfer Context Cleanup");
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWTransferContextKM: Couldn't allocate memory for SGX_HW_TRANSFER_CONTEXT_CLEANUP structure"));
+ goto exit0;
+ }
+
+ psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+ psHeapInfo = &psDevMemoryInfo->psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID];
+
+ eError = PVRSRVAllocDeviceMemKM(hDeviceNode,
+ psPerProc,
+ psHeapInfo->hDevMemHeap,
+ PVRSRV_MEM_READ | PVRSRV_MEM_WRITE
+ | PVRSRV_MEM_NO_SYNCOBJ | PVRSRV_MEM_EDM_PROTECT
+ | PVRSRV_MEM_CACHE_CONSISTENT,
+ ui32HWTransferContextSize,
+ 32,
+ IMG_NULL,
+ 0,
+ &psCleanup->psHWTransferContextMemInfo,
+ "HW Render Context");
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWTransferContextKM: Couldn't allocate device memory for HW Render Context"));
+ goto exit1;
+ }
+
+ eError = OSCopyFromUser(psPerProc,
+ psCleanup->psHWTransferContextMemInfo->pvLinAddrKM,
+ psHWTransferContextCpuVAddr,
+ ui32HWTransferContextSize);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWTransferContextKM: Couldn't copy user-mode copy of HWContext into device memory"));
+ goto exit2;
+ }
+
+
+ psHWTransferContextDevVAddr->uiAddr = psCleanup->psHWTransferContextMemInfo->sDevVAddr.uiAddr;
+
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevMemContextInt,
+ hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWTransferContextKM: Can't lookup DevMem Context"));
+ goto exit2;
+ }
+
+ psMMUContext = BM_GetMMUContextFromMemContext(hDevMemContextInt);
+ sPDDevPAddr = psDeviceNode->pfnMMUGetPDDevPAddr(psMMUContext);
+
+
+
+
+
+
+ pSrc = (IMG_UINT8 *)&sPDDevPAddr;
+ pDst = (IMG_UINT8 *)psCleanup->psHWTransferContextMemInfo->pvLinAddrKM;
+ pDst += ui32OffsetToPDDevPAddr;
+
+ for (iPtrByte = 0; iPtrByte < sizeof(IMG_DEV_PHYADDR); iPtrByte++)
+ {
+ pDst[iPtrByte] = pSrc[iPtrByte];
+ }
+
+#if defined(PDUMP)
+
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "HW Transfer context struct");
+
+ PDUMPMEM(
+ IMG_NULL,
+ psCleanup->psHWTransferContextMemInfo,
+ 0,
+ ui32HWTransferContextSize,
+ PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psCleanup->psHWTransferContextMemInfo));
+
+
+ PDUMPCOMMENT("Page directory address in HW transfer context");
+
+ PDUMPPDDEVPADDR(
+ psCleanup->psHWTransferContextMemInfo,
+ ui32OffsetToPDDevPAddr,
+ sPDDevPAddr,
+ MAKEUNIQUETAG(psCleanup->psHWTransferContextMemInfo),
+ PDUMP_PD_UNIQUETAG);
+#endif
+
+ psCleanup->hBlockAlloc = hBlockAlloc;
+ psCleanup->psDeviceNode = psDeviceNode;
+ psCleanup->bCleanupTimerRunning = IMG_FALSE;
+
+ psResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_HW_TRANSFER_CONTEXT,
+ psCleanup,
+ 0,
+ &SGXCleanupHWTransferContextCallback);
+
+ if (psResItem == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWTransferContextKM: ResManRegisterRes failed"));
+ goto exit2;
+ }
+
+ psCleanup->psResItem = psResItem;
+
+ return (IMG_HANDLE)psCleanup;
+
+exit2:
+ PVRSRVFreeDeviceMemKM(hDeviceNode,
+ psCleanup->psHWTransferContextMemInfo);
+exit1:
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(SGX_HW_TRANSFER_CONTEXT_CLEANUP),
+ psCleanup,
+ psCleanup->hBlockAlloc);
+
+
+exit0:
+ return IMG_NULL;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGXUnregisterHWTransferContextKM(IMG_HANDLE hHWTransferContext, IMG_BOOL bForceCleanup)
+{
+ PVRSRV_ERROR eError;
+ SGX_HW_TRANSFER_CONTEXT_CLEANUP *psCleanup;
+
+ PVR_ASSERT(hHWTransferContext != IMG_NULL);
+
+ psCleanup = (SGX_HW_TRANSFER_CONTEXT_CLEANUP *)hHWTransferContext;
+
+ if (psCleanup == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXUnregisterHWTransferContextKM: invalid parameter"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ eError = ResManFreeResByPtr(psCleanup->psResItem, bForceCleanup);
+
+ return eError;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGXSetTransferContextPriorityKM(
+ IMG_HANDLE hDeviceNode,
+ IMG_HANDLE hHWTransferContext,
+ IMG_UINT32 ui32Priority,
+ IMG_UINT32 ui32OffsetOfPriorityField)
+{
+ SGX_HW_TRANSFER_CONTEXT_CLEANUP *psCleanup;
+ IMG_UINT8 *pSrc;
+ IMG_UINT8 *pDst;
+ int iPtrByte;
+ PVR_UNREFERENCED_PARAMETER(hDeviceNode);
+
+ if (hHWTransferContext != IMG_NULL)
+ {
+ psCleanup = (SGX_HW_TRANSFER_CONTEXT_CLEANUP *)hHWTransferContext;
+
+ if ((ui32OffsetOfPriorityField + sizeof(ui32Priority))
+ >= psCleanup->psHWTransferContextMemInfo->uAllocSize)
+ {
+ PVR_DPF((
+ PVR_DBG_ERROR,
+ "SGXSetTransferContextPriorityKM: invalid context prioirty offset"));
+
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+
+
+ pDst = (IMG_UINT8 *)psCleanup->psHWTransferContextMemInfo->pvLinAddrKM;
+ pDst += ui32OffsetOfPriorityField;
+ pSrc = (IMG_UINT8 *)&ui32Priority;
+
+ for (iPtrByte = 0; iPtrByte < sizeof(ui32Priority); iPtrByte++)
+ {
+ pDst[iPtrByte] = pSrc[iPtrByte];
+ }
+ }
+ return PVRSRV_OK;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGXSetRenderContextPriorityKM(
+ IMG_HANDLE hDeviceNode,
+ IMG_HANDLE hHWRenderContext,
+ IMG_UINT32 ui32Priority,
+ IMG_UINT32 ui32OffsetOfPriorityField)
+{
+ SGX_HW_RENDER_CONTEXT_CLEANUP *psCleanup;
+ IMG_UINT8 *pSrc;
+ IMG_UINT8 *pDst;
+ int iPtrByte;
+ PVR_UNREFERENCED_PARAMETER(hDeviceNode);
+
+ if (hHWRenderContext != IMG_NULL)
+ {
+ psCleanup = (SGX_HW_RENDER_CONTEXT_CLEANUP *)hHWRenderContext;
+ if ((ui32OffsetOfPriorityField + sizeof(ui32Priority))
+ >= psCleanup->psHWRenderContextMemInfo->uAllocSize)
+ {
+ PVR_DPF((
+ PVR_DBG_ERROR,
+ "SGXSetContextPriorityKM: invalid HWRenderContext prioirty offset"));
+
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+
+
+ pDst = (IMG_UINT8 *)psCleanup->psHWRenderContextMemInfo->pvLinAddrKM;
+ pDst += ui32OffsetOfPriorityField;
+
+ pSrc = (IMG_UINT8 *)&ui32Priority;
+
+ for (iPtrByte = 0; iPtrByte < sizeof(ui32Priority); iPtrByte++)
+ {
+ pDst[iPtrByte] = pSrc[iPtrByte];
+ }
+ }
+ return PVRSRV_OK;
+}
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+typedef struct _SGX_HW_2D_CONTEXT_CLEANUP_
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ PVRSRV_KERNEL_MEM_INFO *psHW2DContextMemInfo;
+ IMG_HANDLE hBlockAlloc;
+ PRESMAN_ITEM psResItem;
+ IMG_BOOL bCleanupTimerRunning;
+ IMG_PVOID pvTimeData;
+} SGX_HW_2D_CONTEXT_CLEANUP;
+
+static PVRSRV_ERROR SGXCleanupHW2DContextCallback(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param,
+ IMG_BOOL bForceCleanup)
+{
+ PVRSRV_ERROR eError;
+ SGX_HW_2D_CONTEXT_CLEANUP *psCleanup = (SGX_HW_2D_CONTEXT_CLEANUP *)pvParam;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+
+ eError = SGXCleanupRequest(psCleanup->psDeviceNode,
+ &psCleanup->psHW2DContextMemInfo->sDevVAddr,
+ PVRSRV_CLEANUPCMD_2DC,
+ bForceCleanup);
+
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+ if (!psCleanup->bCleanupTimerRunning)
+ {
+ OSTimeCreateWithUSOffset(&psCleanup->pvTimeData, MAX_CLEANUP_TIME_US);
+ psCleanup->bCleanupTimerRunning = IMG_TRUE;
+ }
+ else
+ {
+ if (OSTimeHasTimePassed(psCleanup->pvTimeData))
+ {
+ eError = PVRSRV_ERROR_TIMEOUT_POLLING_FOR_VALUE;
+ psCleanup->bCleanupTimerRunning = IMG_FALSE;
+ OSTimeDestroy(psCleanup->pvTimeData);
+ }
+ }
+ }
+ else
+ {
+ if (psCleanup->bCleanupTimerRunning)
+ {
+ OSTimeDestroy(psCleanup->pvTimeData);
+ }
+ }
+
+ if (eError != PVRSRV_ERROR_RETRY)
+ {
+
+ PVRSRVFreeDeviceMemKM(psCleanup->psDeviceNode,
+ psCleanup->psHW2DContextMemInfo);
+
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(SGX_HW_2D_CONTEXT_CLEANUP),
+ psCleanup,
+ psCleanup->hBlockAlloc);
+
+ }
+ return eError;
+}
+
+IMG_HANDLE SGXRegisterHW2DContextKM(IMG_HANDLE hDeviceNode,
+ IMG_CPU_VIRTADDR *psHW2DContextCpuVAddr,
+ IMG_UINT32 ui32HW2DContextSize,
+ IMG_UINT32 ui32OffsetToPDDevPAddr,
+ IMG_HANDLE hDevMemContext,
+ IMG_DEV_VIRTADDR *psHW2DContextDevVAddr,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hBlockAlloc;
+ SGX_HW_2D_CONTEXT_CLEANUP *psCleanup;
+ PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)hDeviceNode;
+ DEVICE_MEMORY_INFO *psDevMemoryInfo;
+ DEVICE_MEMORY_HEAP_INFO *psHeapInfo;
+ IMG_HANDLE hDevMemContextInt;
+ MMU_CONTEXT *psMMUContext;
+ IMG_DEV_PHYADDR sPDDevPAddr;
+ int iPtrByte;
+ IMG_UINT8 *pSrc;
+ IMG_UINT8 *pDst;
+ PRESMAN_ITEM psResItem;
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(SGX_HW_2D_CONTEXT_CLEANUP),
+ (IMG_VOID **)&psCleanup,
+ &hBlockAlloc,
+ "SGX Hardware 2D Context Cleanup");
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHW2DContextKM: Couldn't allocate memory for SGX_HW_2D_CONTEXT_CLEANUP structure"));
+ goto exit0;
+ }
+
+ psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+ psHeapInfo = &psDevMemoryInfo->psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID];
+
+ eError = PVRSRVAllocDeviceMemKM(hDeviceNode,
+ psPerProc,
+ psHeapInfo->hDevMemHeap,
+ PVRSRV_MEM_READ | PVRSRV_MEM_WRITE
+ | PVRSRV_MEM_NO_SYNCOBJ | PVRSRV_MEM_EDM_PROTECT
+ | PVRSRV_MEM_CACHE_CONSISTENT,
+ ui32HW2DContextSize,
+ 32,
+ IMG_NULL,
+ 0,
+ &psCleanup->psHW2DContextMemInfo,
+ "HW 2D Context");
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHW2DContextKM: Couldn't allocate device memory for HW Render Context"));
+ goto exit1;
+ }
+
+ eError = OSCopyFromUser(psPerProc,
+ psCleanup->psHW2DContextMemInfo->pvLinAddrKM,
+ psHW2DContextCpuVAddr,
+ ui32HW2DContextSize);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHW2DContextKM: Couldn't copy user-mode copy of HWContext into device memory"));
+ goto exit2;
+ }
+
+
+ psHW2DContextDevVAddr->uiAddr = psCleanup->psHW2DContextMemInfo->sDevVAddr.uiAddr;
+
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevMemContextInt,
+ hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHW2DContextKM: Can't lookup DevMem Context"));
+ goto exit2;
+ }
+
+ psMMUContext = BM_GetMMUContextFromMemContext(hDevMemContextInt);
+ sPDDevPAddr = psDeviceNode->pfnMMUGetPDDevPAddr(psMMUContext);
+
+
+
+
+
+
+ pSrc = (IMG_UINT8 *)&sPDDevPAddr;
+ pDst = (IMG_UINT8 *)psCleanup->psHW2DContextMemInfo->pvLinAddrKM;
+ pDst += ui32OffsetToPDDevPAddr;
+
+ for (iPtrByte = 0; iPtrByte < sizeof(IMG_DEV_PHYADDR); iPtrByte++)
+ {
+ pDst[iPtrByte] = pSrc[iPtrByte];
+ }
+
+#if defined(PDUMP)
+
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "HW 2D context struct");
+
+ PDUMPMEM(
+ IMG_NULL,
+ psCleanup->psHW2DContextMemInfo,
+ 0,
+ ui32HW2DContextSize,
+ PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psCleanup->psHW2DContextMemInfo));
+
+
+ PDUMPCOMMENT("Page directory address in HW 2D transfer context");
+ PDUMPPDDEVPADDR(
+ psCleanup->psHW2DContextMemInfo,
+ ui32OffsetToPDDevPAddr,
+ sPDDevPAddr,
+ MAKEUNIQUETAG(psCleanup->psHW2DContextMemInfo),
+ PDUMP_PD_UNIQUETAG);
+#endif
+
+ psCleanup->hBlockAlloc = hBlockAlloc;
+ psCleanup->psDeviceNode = psDeviceNode;
+ psCleanup->bCleanupTimerRunning = IMG_FALSE;
+
+ psResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_HW_2D_CONTEXT,
+ psCleanup,
+ 0,
+ &SGXCleanupHW2DContextCallback);
+
+ if (psResItem == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHW2DContextKM: ResManRegisterRes failed"));
+ goto exit2;
+ }
+
+ psCleanup->psResItem = psResItem;
+
+ return (IMG_HANDLE)psCleanup;
+
+exit2:
+ PVRSRVFreeDeviceMemKM(hDeviceNode,
+ psCleanup->psHW2DContextMemInfo);
+exit1:
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(SGX_HW_2D_CONTEXT_CLEANUP),
+ psCleanup,
+ psCleanup->hBlockAlloc);
+
+exit0:
+ return IMG_NULL;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGXUnregisterHW2DContextKM(IMG_HANDLE hHW2DContext, IMG_BOOL bForceCleanup)
+{
+ PVRSRV_ERROR eError;
+ SGX_HW_2D_CONTEXT_CLEANUP *psCleanup;
+
+ PVR_ASSERT(hHW2DContext != IMG_NULL);
+
+ if (hHW2DContext == IMG_NULL)
+ {
+ return (PVRSRV_ERROR_INVALID_PARAMS);
+ }
+
+ psCleanup = (SGX_HW_2D_CONTEXT_CLEANUP *)hHW2DContext;
+
+ eError = ResManFreeResByPtr(psCleanup->psResItem, bForceCleanup);
+
+ return eError;
+}
+#endif
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SGX2DQuerySyncOpsComplete)
+#endif
+static INLINE
+IMG_BOOL SGX2DQuerySyncOpsComplete(PVRSRV_KERNEL_SYNC_INFO *psSyncInfo,
+ IMG_UINT32 ui32ReadOpsPending,
+ IMG_UINT32 ui32WriteOpsPending)
+{
+ PVRSRV_SYNC_DATA *psSyncData = psSyncInfo->psSyncData;
+
+ return (IMG_BOOL)(
+ (psSyncData->ui32ReadOpsComplete >= ui32ReadOpsPending) &&
+ (psSyncData->ui32WriteOpsComplete >= ui32WriteOpsPending)
+ );
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGX2DQueryBlitsCompleteKM(PVRSRV_SGXDEV_INFO *psDevInfo,
+ PVRSRV_KERNEL_SYNC_INFO *psSyncInfo,
+ IMG_BOOL bWaitForComplete)
+{
+ IMG_UINT32 ui32ReadOpsPending, ui32WriteOpsPending;
+
+ PVR_UNREFERENCED_PARAMETER(psDevInfo);
+
+ PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: Start"));
+
+ ui32ReadOpsPending = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ ui32WriteOpsPending = psSyncInfo->psSyncData->ui32WriteOpsPending;
+
+ if(SGX2DQuerySyncOpsComplete(psSyncInfo, ui32ReadOpsPending, ui32WriteOpsPending))
+ {
+
+ PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: No wait. Blits complete."));
+ return PVRSRV_OK;
+ }
+
+
+ if (!bWaitForComplete)
+ {
+
+ PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: No wait. Ops pending."));
+ return PVRSRV_ERROR_CMD_NOT_PROCESSED;
+ }
+
+
+ PVR_DPF((PVR_DBG_MESSAGE, "SGX2DQueryBlitsCompleteKM: Ops pending. Start polling."));
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ OSSleepms(1);
+
+ if(SGX2DQuerySyncOpsComplete(psSyncInfo, ui32ReadOpsPending, ui32WriteOpsPending))
+ {
+
+ PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: Wait over. Blits complete."));
+ return PVRSRV_OK;
+ }
+
+ OSSleepms(1);
+ } END_LOOP_UNTIL_TIMEOUT();
+
+
+ PVR_DPF((PVR_DBG_ERROR,"SGX2DQueryBlitsCompleteKM: Timed out. Ops pending."));
+
+#if defined(DEBUG)
+ {
+ PVRSRV_SYNC_DATA *psSyncData = psSyncInfo->psSyncData;
+
+ PVR_TRACE(("SGX2DQueryBlitsCompleteKM: Syncinfo: 0x%x, Syncdata: 0x%x",
+ (IMG_UINTPTR_T)psSyncInfo, (IMG_UINTPTR_T)psSyncData));
+
+ PVR_TRACE(("SGX2DQueryBlitsCompleteKM: Read ops complete: %d, Read ops pending: %d", psSyncData->ui32ReadOpsComplete, psSyncData->ui32ReadOpsPending));
+ PVR_TRACE(("SGX2DQueryBlitsCompleteKM: Write ops complete: %d, Write ops pending: %d", psSyncData->ui32WriteOpsComplete, psSyncData->ui32WriteOpsPending));
+
+ }
+#endif
+
+ return PVRSRV_ERROR_TIMEOUT;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR SGXFlushHWRenderTargetKM(IMG_HANDLE psDeviceNode,
+ IMG_DEV_VIRTADDR sHWRTDataSetDevVAddr,
+ IMG_BOOL bForceCleanup)
+{
+ PVR_ASSERT(sHWRTDataSetDevVAddr.uiAddr != IMG_NULL);
+
+ return SGXCleanupRequest(psDeviceNode,
+ &sHWRTDataSetDevVAddr,
+ PVRSRV_CLEANUPCMD_RT,
+ bForceCleanup);
+}
+
+
+IMG_UINT32 SGXConvertTimeStamp(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32TimeWraps,
+ IMG_UINT32 ui32Time)
+{
+#if defined(EUR_CR_TIMER)
+ PVR_UNREFERENCED_PARAMETER(psDevInfo);
+ PVR_UNREFERENCED_PARAMETER(ui32TimeWraps);
+ return ui32Time;
+#else
+ IMG_UINT64 ui64Clocks;
+ IMG_UINT32 ui32Clocksx16;
+
+ ui64Clocks = ((IMG_UINT64)ui32TimeWraps * psDevInfo->ui32uKernelTimerClock) +
+ (psDevInfo->ui32uKernelTimerClock - (ui32Time & EUR_CR_EVENT_TIMER_VALUE_MASK));
+ ui32Clocksx16 = (IMG_UINT32)(ui64Clocks / 16);
+
+ return ui32Clocksx16;
+#endif
+}
+
+
+IMG_VOID SGXWaitClocks(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32SGXClocks)
+{
+
+
+ OSWaitus(1 + (ui32SGXClocks * 1000000 / psDevInfo->ui32CoreClockSpeed));
+}
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVGetSGXRevDataKM(PVRSRV_DEVICE_NODE* psDeviceNode, IMG_UINT32 *pui32SGXCoreRev,
+ IMG_UINT32 *pui32SGXCoreID)
+{
+ PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+ SGX_MISC_INFO sMiscInfo;
+ PVRSRV_ERROR eError;
+
+ sMiscInfo.eRequest = SGX_MISC_INFO_REQUEST_SGXREV;
+ eError = SGXGetMiscInfoKM(psDevInfo, &sMiscInfo, psDeviceNode, NULL);
+
+ *pui32SGXCoreRev = sMiscInfo.uData.sSGXFeatures.ui32CoreRev;
+ *pui32SGXCoreID = sMiscInfo.uData.sSGXFeatures.ui32CoreID;
+ return eError;
+}
+
+
+PVRSRV_ERROR SGXContextSuspend(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_DEV_VIRTADDR *psHWContextDevVAddr,
+ IMG_BOOL bResume)
+{
+ PVRSRV_ERROR eError;
+ SGXMKIF_COMMAND sCommand = {0};
+
+ sCommand.ui32Data[0] = psHWContextDevVAddr->uiAddr;
+ sCommand.ui32Data[1] = bResume ? PVRSRV_CTXSUSPCMD_RESUME : PVRSRV_CTXSUSPCMD_SUSPEND;
+
+ eError = SGXScheduleCCBCommandKM(psDeviceNode, SGXMKIF_CMD_CONTEXTSUSPEND, &sCommand, KERNEL_ID, 0, IMG_NULL, IMG_FALSE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXContextSuspend: Failed to submit context suspend command"));
+ return eError;
+ }
+
+ return eError;
+}
+
diff --git a/drivers/gpu/pvr/sgx/sgxutils.h b/drivers/gpu/pvr/sgx/sgxutils.h
new file mode 100644
index 0000000..9017acf
--- /dev/null
+++ b/drivers/gpu/pvr/sgx/sgxutils.h
@@ -0,0 +1,143 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "perproc.h"
+#include "sgxinfokm.h"
+
+
+#define CCB_OFFSET_IS_VALID(type, psCCBMemInfo, psCCBKick, offset) \
+ ((sizeof(type) <= (psCCBMemInfo)->uAllocSize) && \
+ ((psCCBKick)->offset <= (psCCBMemInfo)->uAllocSize - sizeof(type)))
+
+#define CCB_DATA_FROM_OFFSET(type, psCCBMemInfo, psCCBKick, offset) \
+ ((type *)(((IMG_CHAR *)(psCCBMemInfo)->pvLinAddrKM) + \
+ (psCCBKick)->offset))
+
+extern IMG_UINT64 ui64KickCount;
+
+
+IMG_IMPORT
+IMG_VOID SGXTestActivePowerEvent(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 ui32CallerID);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_DEVICE_NODE *psDeviceNode,
+ SGXMKIF_CMD_TYPE eCommandType,
+ SGXMKIF_COMMAND *psCommandData,
+ IMG_UINT32 ui32CallerID,
+ IMG_UINT32 ui32PDumpFlags,
+ IMG_HANDLE hDevMemContext,
+ IMG_BOOL bLastInScene);
+IMG_IMPORT
+PVRSRV_ERROR SGXScheduleCCBCommandKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ SGXMKIF_CMD_TYPE eCommandType,
+ SGXMKIF_COMMAND *psCommandData,
+ IMG_UINT32 ui32CallerID,
+ IMG_UINT32 ui32PDumpFlags,
+ IMG_HANDLE hDevMemContext,
+ IMG_BOOL bLastInScene);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXScheduleProcessQueuesKM(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_IMPORT
+IMG_BOOL SGXIsDevicePowered(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_IMPORT
+IMG_HANDLE SGXRegisterHWRenderContextKM(IMG_HANDLE psDeviceNode,
+ IMG_CPU_VIRTADDR *psHWRenderContextCpuVAddr,
+ IMG_UINT32 ui32HWRenderContextSize,
+ IMG_UINT32 ui32OffsetToPDDevPAddr,
+ IMG_HANDLE hDevMemContext,
+ IMG_DEV_VIRTADDR *psHWRenderContextDevVAddr,
+ PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+IMG_IMPORT
+IMG_HANDLE SGXRegisterHWTransferContextKM(IMG_HANDLE psDeviceNode,
+ IMG_CPU_VIRTADDR *psHWTransferContextCpuVAddr,
+ IMG_UINT32 ui32HWTransferContextSize,
+ IMG_UINT32 ui32OffsetToPDDevPAddr,
+ IMG_HANDLE hDevMemContext,
+ IMG_DEV_VIRTADDR *psHWTransferContextDevVAddr,
+ PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXFlushHWRenderTargetKM(IMG_HANDLE psSGXDevInfo,
+ IMG_DEV_VIRTADDR psHWRTDataSetDevVAddr,
+ IMG_BOOL bForceCleanup);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXUnregisterHWRenderContextKM(IMG_HANDLE hHWRenderContext, IMG_BOOL bForceCleanup);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXUnregisterHWTransferContextKM(IMG_HANDLE hHWTransferContext, IMG_BOOL bForceCleanup);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXSetRenderContextPriorityKM(IMG_HANDLE hDeviceNode,
+ IMG_HANDLE hHWRenderContext,
+ IMG_UINT32 ui32Priority,
+ IMG_UINT32 ui32OffsetOfPriorityField);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXSetTransferContextPriorityKM(IMG_HANDLE hDeviceNode,
+ IMG_HANDLE hHWTransferContext,
+ IMG_UINT32 ui32Priority,
+ IMG_UINT32 ui32OffsetOfPriorityField);
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+IMG_IMPORT
+IMG_HANDLE SGXRegisterHW2DContextKM(IMG_HANDLE psDeviceNode,
+ IMG_CPU_VIRTADDR *psHW2DContextCpuVAddr,
+ IMG_UINT32 ui32HW2DContextSize,
+ IMG_UINT32 ui32OffsetToPDDevPAddr,
+ IMG_HANDLE hDevMemContext,
+ IMG_DEV_VIRTADDR *psHW2DContextDevVAddr,
+ PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXUnregisterHW2DContextKM(IMG_HANDLE hHW2DContext, IMG_BOOL bForceCleanup);
+#endif
+
+IMG_UINT32 SGXConvertTimeStamp(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32TimeWraps,
+ IMG_UINT32 ui32Time);
+
+IMG_VOID SGXWaitClocks(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32SGXClocks);
+
+PVRSRV_ERROR SGXCleanupRequest(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_DEV_VIRTADDR *psHWDataDevVAddr,
+ IMG_UINT32 ui32CleanupType,
+ IMG_BOOL bForceCleanup);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVGetSGXRevDataKM(PVRSRV_DEVICE_NODE* psDeviceNode, IMG_UINT32 *pui32SGXCoreRev,
+ IMG_UINT32 *pui32SGXCoreID);
+
+PVRSRV_ERROR SGXContextSuspend(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_DEV_VIRTADDR *psHWContextDevVAddr,
+ IMG_BOOL bResume);
+
diff --git a/drivers/gpu/pvr/sgx530defs.h b/drivers/gpu/pvr/sgx530defs.h
new file mode 100644
index 0000000..810cb81
--- /dev/null
+++ b/drivers/gpu/pvr/sgx530defs.h
@@ -0,0 +1,488 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef _SGX530DEFS_KM_H_
+#define _SGX530DEFS_KM_H_
+
+#define EUR_CR_CLKGATECTL 0x0000
+#define EUR_CR_CLKGATECTL_2D_CLKG_MASK 0x00000003U
+#define EUR_CR_CLKGATECTL_2D_CLKG_SHIFT 0
+#define EUR_CR_CLKGATECTL_ISP_CLKG_MASK 0x00000030U
+#define EUR_CR_CLKGATECTL_ISP_CLKG_SHIFT 4
+#define EUR_CR_CLKGATECTL_TSP_CLKG_MASK 0x00000300U
+#define EUR_CR_CLKGATECTL_TSP_CLKG_SHIFT 8
+#define EUR_CR_CLKGATECTL_TA_CLKG_MASK 0x00003000U
+#define EUR_CR_CLKGATECTL_TA_CLKG_SHIFT 12
+#define EUR_CR_CLKGATECTL_DPM_CLKG_MASK 0x00030000U
+#define EUR_CR_CLKGATECTL_DPM_CLKG_SHIFT 16
+#define EUR_CR_CLKGATECTL_USE_CLKG_MASK 0x00300000U
+#define EUR_CR_CLKGATECTL_USE_CLKG_SHIFT 20
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_MASK 0x01000000U
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_SHIFT 24
+#define EUR_CR_CLKGATESTATUS 0x0004
+#define EUR_CR_CLKGATESTATUS_2D_CLKS_MASK 0x00000001U
+#define EUR_CR_CLKGATESTATUS_2D_CLKS_SHIFT 0
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_MASK 0x00000010U
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_SHIFT 4
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_MASK 0x00000100U
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_SHIFT 8
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_MASK 0x00001000U
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_SHIFT 12
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_MASK 0x00010000U
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_SHIFT 16
+#define EUR_CR_CLKGATESTATUS_USE_CLKS_MASK 0x00100000U
+#define EUR_CR_CLKGATESTATUS_USE_CLKS_SHIFT 20
+#define EUR_CR_CLKGATECTLOVR 0x0008
+#define EUR_CR_CLKGATECTLOVR_2D_CLKO_MASK 0x00000003U
+#define EUR_CR_CLKGATECTLOVR_2D_CLKO_SHIFT 0
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_MASK 0x00000030U
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_SHIFT 4
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_MASK 0x00000300U
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_SHIFT 8
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_MASK 0x00003000U
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_SHIFT 12
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_MASK 0x00030000U
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_SHIFT 16
+#define EUR_CR_CLKGATECTLOVR_USE_CLKO_MASK 0x00300000U
+#define EUR_CR_CLKGATECTLOVR_USE_CLKO_SHIFT 20
+#define EUR_CR_CORE_ID 0x0010
+#define EUR_CR_CORE_ID_CONFIG_MASK 0x0000FFFFU
+#define EUR_CR_CORE_ID_CONFIG_SHIFT 0
+#define EUR_CR_CORE_ID_ID_MASK 0xFFFF0000U
+#define EUR_CR_CORE_ID_ID_SHIFT 16
+#define EUR_CR_CORE_REVISION 0x0014
+#define EUR_CR_CORE_REVISION_MAINTENANCE_MASK 0x000000FFU
+#define EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT 0
+#define EUR_CR_CORE_REVISION_MINOR_MASK 0x0000FF00U
+#define EUR_CR_CORE_REVISION_MINOR_SHIFT 8
+#define EUR_CR_CORE_REVISION_MAJOR_MASK 0x00FF0000U
+#define EUR_CR_CORE_REVISION_MAJOR_SHIFT 16
+#define EUR_CR_CORE_REVISION_DESIGNER_MASK 0xFF000000U
+#define EUR_CR_CORE_REVISION_DESIGNER_SHIFT 24
+#define EUR_CR_DESIGNER_REV_FIELD1 0x0018
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_MASK 0xFFFFFFFFU
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SHIFT 0
+#define EUR_CR_DESIGNER_REV_FIELD2 0x001C
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_MASK 0xFFFFFFFFU
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SHIFT 0
+#define EUR_CR_SOFT_RESET 0x0080
+#define EUR_CR_SOFT_RESET_BIF_RESET_MASK 0x00000001U
+#define EUR_CR_SOFT_RESET_BIF_RESET_SHIFT 0
+#define EUR_CR_SOFT_RESET_TWOD_RESET_MASK 0x00000002U
+#define EUR_CR_SOFT_RESET_TWOD_RESET_SHIFT 1
+#define EUR_CR_SOFT_RESET_DPM_RESET_MASK 0x00000004U
+#define EUR_CR_SOFT_RESET_DPM_RESET_SHIFT 2
+#define EUR_CR_SOFT_RESET_TA_RESET_MASK 0x00000008U
+#define EUR_CR_SOFT_RESET_TA_RESET_SHIFT 3
+#define EUR_CR_SOFT_RESET_USE_RESET_MASK 0x00000010U
+#define EUR_CR_SOFT_RESET_USE_RESET_SHIFT 4
+#define EUR_CR_SOFT_RESET_ISP_RESET_MASK 0x00000020U
+#define EUR_CR_SOFT_RESET_ISP_RESET_SHIFT 5
+#define EUR_CR_SOFT_RESET_TSP_RESET_MASK 0x00000040U
+#define EUR_CR_SOFT_RESET_TSP_RESET_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE2 0x0110
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_HOST_CLEAR2 0x0114
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_STATUS2 0x0118
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_MASK 0x00000010U
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_SHIFT 4
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_MASK 0x00000008U
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_SHIFT 3
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_MASK 0x00000004U
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_SHIFT 2
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_STATUS 0x012CU
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_STATUS_TIMER_MASK 0x20000000U
+#define EUR_CR_EVENT_STATUS_TIMER_SHIFT 29
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_STATUS_TWOD_COMPLETE_MASK 0x08000000U
+#define EUR_CR_EVENT_STATUS_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_STATUS_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_STATUS_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_STATUS_ISP_HALT_MASK 0x00020000U
+#define EUR_CR_EVENT_STATUS_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_STATUS_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_STATUS_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_HOST_ENABLE 0x0130
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_MASK 0x20000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_ENABLE_TWOD_COMPLETE_MASK 0x08000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_MASK 0x00020000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_HOST_CLEAR 0x0134
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_MASK 0x20000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_CLEAR_TWOD_COMPLETE_MASK 0x08000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_MASK 0x00020000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_PDS_EXEC_BASE 0x0AB8
+#define EUR_CR_PDS_EXEC_BASE_ADDR_MASK 0x0FF00000U
+#define EUR_CR_PDS_EXEC_BASE_ADDR_SHIFT 20
+#define EUR_CR_EVENT_KICKER 0x0AC4
+#define EUR_CR_EVENT_KICKER_ADDRESS_MASK 0x0FFFFFF0U
+#define EUR_CR_EVENT_KICKER_ADDRESS_SHIFT 4
+#define EUR_CR_EVENT_KICK 0x0AC8
+#define EUR_CR_EVENT_KICK_NOW_MASK 0x00000001U
+#define EUR_CR_EVENT_KICK_NOW_SHIFT 0
+#define EUR_CR_EVENT_TIMER 0x0ACC
+#define EUR_CR_EVENT_TIMER_ENABLE_MASK 0x01000000U
+#define EUR_CR_EVENT_TIMER_ENABLE_SHIFT 24
+#define EUR_CR_EVENT_TIMER_VALUE_MASK 0x00FFFFFFU
+#define EUR_CR_EVENT_TIMER_VALUE_SHIFT 0
+#define EUR_CR_PDS_INV0 0x0AD0
+#define EUR_CR_PDS_INV0_DSC_MASK 0x00000001U
+#define EUR_CR_PDS_INV0_DSC_SHIFT 0
+#define EUR_CR_PDS_INV1 0x0AD4
+#define EUR_CR_PDS_INV1_DSC_MASK 0x00000001U
+#define EUR_CR_PDS_INV1_DSC_SHIFT 0
+#define EUR_CR_PDS_INV2 0x0AD8
+#define EUR_CR_PDS_INV2_DSC_MASK 0x00000001U
+#define EUR_CR_PDS_INV2_DSC_SHIFT 0
+#define EUR_CR_PDS_INV3 0x0ADC
+#define EUR_CR_PDS_INV3_DSC_MASK 0x00000001U
+#define EUR_CR_PDS_INV3_DSC_SHIFT 0
+#define EUR_CR_PDS_INV_CSC 0x0AE0
+#define EUR_CR_PDS_INV_CSC_KICK_MASK 0x00000001U
+#define EUR_CR_PDS_INV_CSC_KICK_SHIFT 0
+#define EUR_CR_PDS_PC_BASE 0x0B2C
+#define EUR_CR_PDS_PC_BASE_ADDRESS_MASK 0x3FFFFFFFU
+#define EUR_CR_PDS_PC_BASE_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_CTRL 0x0C00
+#define EUR_CR_BIF_CTRL_NOREORDER_MASK 0x00000001U
+#define EUR_CR_BIF_CTRL_NOREORDER_SHIFT 0
+#define EUR_CR_BIF_CTRL_PAUSE_MASK 0x00000002U
+#define EUR_CR_BIF_CTRL_PAUSE_SHIFT 1
+#define EUR_CR_BIF_CTRL_FLUSH_MASK 0x00000004U
+#define EUR_CR_BIF_CTRL_FLUSH_SHIFT 2
+#define EUR_CR_BIF_CTRL_INVALDC_MASK 0x00000008U
+#define EUR_CR_BIF_CTRL_INVALDC_SHIFT 3
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_MASK 0x00000010U
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_SHIFT 4
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_MASK 0x00000100U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_SHIFT 8
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_MASK 0x00000200U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_SHIFT 9
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_MASK 0x00000400U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_SHIFT 10
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TWOD_MASK 0x00000800U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TWOD_SHIFT 11
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_MASK 0x00001000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_SHIFT 12
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_MASK 0x00002000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_SHIFT 13
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_MASK 0x00004000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_SHIFT 14
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_MASK 0x00008000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_SHIFT 15
+#define EUR_CR_BIF_INT_STAT 0x0C04
+#define EUR_CR_BIF_INT_STAT_FAULT_MASK 0x00003FFFU
+#define EUR_CR_BIF_INT_STAT_FAULT_SHIFT 0
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_MASK 0x00004000U
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_SHIFT 14
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_MASK 0x00008000U
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_SHIFT 15
+#define EUR_CR_BIF_FAULT 0x0C08
+#define EUR_CR_BIF_FAULT_ADDR_MASK 0x0FFFF000U
+#define EUR_CR_BIF_FAULT_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE0 0x0C84
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_SHIFT 12
+#define EUR_CR_BIF_TWOD_REQ_BASE 0x0C88
+#define EUR_CR_BIF_TWOD_REQ_BASE_ADDR_MASK 0x0FF00000U
+#define EUR_CR_BIF_TWOD_REQ_BASE_ADDR_SHIFT 20
+#define EUR_CR_BIF_TA_REQ_BASE 0x0C90
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_MASK 0x0FF00000U
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_SHIFT 20
+#define EUR_CR_BIF_MEM_REQ_STAT 0x0CA8
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_MASK 0x000000FFU
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_SHIFT 0
+#define EUR_CR_BIF_3D_REQ_BASE 0x0CAC
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_MASK 0x0FF00000U
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_SHIFT 20
+#define EUR_CR_BIF_ZLS_REQ_BASE 0x0CB0
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_MASK 0x0FF00000U
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_SHIFT 20
+#define EUR_CR_2D_BLIT_STATUS 0x0E04
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_MASK 0x00FFFFFFU
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_SHIFT 0
+#define EUR_CR_2D_BLIT_STATUS_BUSY_MASK 0x01000000U
+#define EUR_CR_2D_BLIT_STATUS_BUSY_SHIFT 24
+#define EUR_CR_2D_VIRTUAL_FIFO_0 0x0E10
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_MASK 0x00000001U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MASK 0x0000000EU
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_SHIFT 1
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_MASK 0x00000FF0U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_SHIFT 4
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_MASK 0x0000F000U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_SHIFT 12
+#define EUR_CR_2D_VIRTUAL_FIFO_1 0x0E14
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_MASK 0x00000FFFU
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_MASK 0x00FFF000U
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_SHIFT 12
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_MASK 0xFF000000U
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_SHIFT 24
+#define EUR_CR_USE_CODE_BASE(X) (0x0A0C + (4 * (X)))
+#define EUR_CR_USE_CODE_BASE_ADDR_MASK 0x00FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_SHIFT 0
+#define EUR_CR_USE_CODE_BASE_DM_MASK 0x03000000U
+#define EUR_CR_USE_CODE_BASE_DM_SHIFT 24
+#define EUR_CR_USE_CODE_BASE_SIZE_UINT32 16
+#define EUR_CR_USE_CODE_BASE_NUM_ENTRIES 16
+#define EUR_CR_MNE_CR_CTRL 0x0D00
+#define EUR_CR_MNE_CR_CTRL_BYP_CC_N_MASK 0x00010000U
+#define EUR_CR_MNE_CR_CTRL_BYP_CC_N_SHIFT 16
+#define EUR_CR_MNE_CR_CTRL_BYP_CC_MASK 0x00008000U
+#define EUR_CR_MNE_CR_CTRL_BYP_CC_SHIFT 15
+#define EUR_CR_MNE_CR_CTRL_USE_INVAL_ADDR_MASK 0x00007800U
+#define EUR_CR_MNE_CR_CTRL_USE_INVAL_ADDR_SHIFT 11
+#define EUR_CR_MNE_CR_CTRL_BYPASS_ALL_MASK 0x00000400U
+#define EUR_CR_MNE_CR_CTRL_BYPASS_ALL_SHIFT 10
+#define EUR_CR_MNE_CR_CTRL_BYPASS_MASK 0x000003E0U
+#define EUR_CR_MNE_CR_CTRL_BYPASS_SHIFT 5
+#define EUR_CR_MNE_CR_CTRL_PAUSE_MASK 0x00000010U
+#define EUR_CR_MNE_CR_CTRL_PAUSE_SHIFT 4
+#define EUR_CR_MNE_CR_CTRL_INVAL_PREQ_MASK 0x0000000EU
+#define EUR_CR_MNE_CR_CTRL_INVAL_PREQ_SHIFT 1
+#define EUR_CR_MNE_CR_CTRL_INVAL_PREQ_PDS_MASK (1UL<<EUR_CR_MNE_CR_CTRL_INVAL_PREQ_SHIFT+2)
+#define EUR_CR_MNE_CR_CTRL_INVAL_PREQ_USEC_MASK (1UL<<EUR_CR_MNE_CR_CTRL_INVAL_PREQ_SHIFT+1)
+#define EUR_CR_MNE_CR_CTRL_INVAL_PREQ_CACHE_MASK (1UL<<EUR_CR_MNE_CR_CTRL_INVAL_PREQ_SHIFT)
+#define EUR_CR_MNE_CR_CTRL_INVAL_ALL_MASK 0x00000001U
+#define EUR_CR_MNE_CR_CTRL_INVAL_ALL_SHIFT 0
+#define EUR_CR_MNE_CR_USE_INVAL 0x0D04
+#define EUR_CR_MNE_CR_USE_INVAL_ADDR_MASK 0xFFFFFFFFU
+#define EUR_CR_MNE_CR_USE_INVAL_ADDR_SHIFT 0
+#define EUR_CR_MNE_CR_STAT 0x0D08
+#define EUR_CR_MNE_CR_STAT_PAUSED_MASK 0x00000400U
+#define EUR_CR_MNE_CR_STAT_PAUSED_SHIFT 10
+#define EUR_CR_MNE_CR_STAT_READS_MASK 0x000003FFU
+#define EUR_CR_MNE_CR_STAT_READS_SHIFT 0
+#define EUR_CR_MNE_CR_STAT_STATS 0x0D0C
+#define EUR_CR_MNE_CR_STAT_STATS_RST_MASK 0x000FFFF0U
+#define EUR_CR_MNE_CR_STAT_STATS_RST_SHIFT 4
+#define EUR_CR_MNE_CR_STAT_STATS_SEL_MASK 0x0000000FU
+#define EUR_CR_MNE_CR_STAT_STATS_SEL_SHIFT 0
+#define EUR_CR_MNE_CR_STAT_STATS_OUT 0x0D10
+#define EUR_CR_MNE_CR_STAT_STATS_OUT_VALUE_MASK 0xFFFFFFFFU
+#define EUR_CR_MNE_CR_STAT_STATS_OUT_VALUE_SHIFT 0
+#define EUR_CR_MNE_CR_EVENT_STATUS 0x0D14
+#define EUR_CR_MNE_CR_EVENT_STATUS_INVAL_MASK 0x00000001U
+#define EUR_CR_MNE_CR_EVENT_STATUS_INVAL_SHIFT 0
+#define EUR_CR_MNE_CR_EVENT_CLEAR 0x0D18
+#define EUR_CR_MNE_CR_EVENT_CLEAR_INVAL_MASK 0x00000001U
+#define EUR_CR_MNE_CR_EVENT_CLEAR_INVAL_SHIFT 0
+#define EUR_CR_MNE_CR_CTRL_INVAL 0x0D20
+
+#endif
+
diff --git a/drivers/gpu/pvr/sgx531defs.h b/drivers/gpu/pvr/sgx531defs.h
new file mode 100644
index 0000000..c9f2899
--- /dev/null
+++ b/drivers/gpu/pvr/sgx531defs.h
@@ -0,0 +1,544 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef _SGX531DEFS_KM_H_
+#define _SGX531DEFS_KM_H_
+
+#define EUR_CR_CLKGATECTL 0x0000
+#define EUR_CR_CLKGATECTL_ISP_CLKG_MASK 0x00000003U
+#define EUR_CR_CLKGATECTL_ISP_CLKG_SHIFT 0
+#define EUR_CR_CLKGATECTL_ISP2_CLKG_MASK 0x0000000CU
+#define EUR_CR_CLKGATECTL_ISP2_CLKG_SHIFT 2
+#define EUR_CR_CLKGATECTL_TSP_CLKG_MASK 0x00000030U
+#define EUR_CR_CLKGATECTL_TSP_CLKG_SHIFT 4
+#define EUR_CR_CLKGATECTL_TE_CLKG_MASK 0x000000C0U
+#define EUR_CR_CLKGATECTL_TE_CLKG_SHIFT 6
+#define EUR_CR_CLKGATECTL_MTE_CLKG_MASK 0x00000300U
+#define EUR_CR_CLKGATECTL_MTE_CLKG_SHIFT 8
+#define EUR_CR_CLKGATECTL_DPM_CLKG_MASK 0x00000C00U
+#define EUR_CR_CLKGATECTL_DPM_CLKG_SHIFT 10
+#define EUR_CR_CLKGATECTL_VDM_CLKG_MASK 0x00003000U
+#define EUR_CR_CLKGATECTL_VDM_CLKG_SHIFT 12
+#define EUR_CR_CLKGATECTL_PDS_CLKG_MASK 0x0000C000U
+#define EUR_CR_CLKGATECTL_PDS_CLKG_SHIFT 14
+#define EUR_CR_CLKGATECTL_IDXFIFO_CLKG_MASK 0x00030000U
+#define EUR_CR_CLKGATECTL_IDXFIFO_CLKG_SHIFT 16
+#define EUR_CR_CLKGATECTL_TA_CLKG_MASK 0x000C0000U
+#define EUR_CR_CLKGATECTL_TA_CLKG_SHIFT 18
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_MASK 0x01000000U
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_SHIFT 24
+#define EUR_CR_CLKGATECTL_SYSTEM_CLKG_MASK 0x10000000U
+#define EUR_CR_CLKGATECTL_SYSTEM_CLKG_SHIFT 28
+#define EUR_CR_CLKGATECTL2 0x0004
+#define EUR_CR_CLKGATECTL2_PBE_CLKG_MASK 0x00000003U
+#define EUR_CR_CLKGATECTL2_PBE_CLKG_SHIFT 0
+#define EUR_CR_CLKGATECTL2_CACHEL2_CLKG_MASK 0x0000000CU
+#define EUR_CR_CLKGATECTL2_CACHEL2_CLKG_SHIFT 2
+#define EUR_CR_CLKGATECTL2_UCACHEL2_CLKG_MASK 0x00000030U
+#define EUR_CR_CLKGATECTL2_UCACHEL2_CLKG_SHIFT 4
+#define EUR_CR_CLKGATECTL2_USE0_CLKG_MASK 0x000000C0U
+#define EUR_CR_CLKGATECTL2_USE0_CLKG_SHIFT 6
+#define EUR_CR_CLKGATECTL2_ITR0_CLKG_MASK 0x00000300U
+#define EUR_CR_CLKGATECTL2_ITR0_CLKG_SHIFT 8
+#define EUR_CR_CLKGATECTL2_TEX0_CLKG_MASK 0x00000C00U
+#define EUR_CR_CLKGATECTL2_TEX0_CLKG_SHIFT 10
+#define EUR_CR_CLKGATECTL2_MADD0_CLKG_MASK 0x00003000U
+#define EUR_CR_CLKGATECTL2_MADD0_CLKG_SHIFT 12
+#define EUR_CR_CLKGATECTL2_USE1_CLKG_MASK 0x0000C000U
+#define EUR_CR_CLKGATECTL2_USE1_CLKG_SHIFT 14
+#define EUR_CR_CLKGATECTL2_ITR1_CLKG_MASK 0x00030000U
+#define EUR_CR_CLKGATECTL2_ITR1_CLKG_SHIFT 16
+#define EUR_CR_CLKGATECTL2_TEX1_CLKG_MASK 0x000C0000U
+#define EUR_CR_CLKGATECTL2_TEX1_CLKG_SHIFT 18
+#define EUR_CR_CLKGATECTL2_MADD1_CLKG_MASK 0x00300000U
+#define EUR_CR_CLKGATECTL2_MADD1_CLKG_SHIFT 20
+#define EUR_CR_CLKGATESTATUS 0x0008
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_MASK 0x00000001U
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_SHIFT 0
+#define EUR_CR_CLKGATESTATUS_ISP2_CLKS_MASK 0x00000002U
+#define EUR_CR_CLKGATESTATUS_ISP2_CLKS_SHIFT 1
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_MASK 0x00000004U
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_SHIFT 2
+#define EUR_CR_CLKGATESTATUS_TE_CLKS_MASK 0x00000008U
+#define EUR_CR_CLKGATESTATUS_TE_CLKS_SHIFT 3
+#define EUR_CR_CLKGATESTATUS_MTE_CLKS_MASK 0x00000010U
+#define EUR_CR_CLKGATESTATUS_MTE_CLKS_SHIFT 4
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_MASK 0x00000020U
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_SHIFT 5
+#define EUR_CR_CLKGATESTATUS_VDM_CLKS_MASK 0x00000040U
+#define EUR_CR_CLKGATESTATUS_VDM_CLKS_SHIFT 6
+#define EUR_CR_CLKGATESTATUS_PDS_CLKS_MASK 0x00000080U
+#define EUR_CR_CLKGATESTATUS_PDS_CLKS_SHIFT 7
+#define EUR_CR_CLKGATESTATUS_PBE_CLKS_MASK 0x00000100U
+#define EUR_CR_CLKGATESTATUS_PBE_CLKS_SHIFT 8
+#define EUR_CR_CLKGATESTATUS_CACHEL2_CLKS_MASK 0x00000200U
+#define EUR_CR_CLKGATESTATUS_CACHEL2_CLKS_SHIFT 9
+#define EUR_CR_CLKGATESTATUS_UCACHEL2_CLKS_MASK 0x00000400U
+#define EUR_CR_CLKGATESTATUS_UCACHEL2_CLKS_SHIFT 10
+#define EUR_CR_CLKGATESTATUS_USE0_CLKS_MASK 0x00000800U
+#define EUR_CR_CLKGATESTATUS_USE0_CLKS_SHIFT 11
+#define EUR_CR_CLKGATESTATUS_ITR0_CLKS_MASK 0x00001000U
+#define EUR_CR_CLKGATESTATUS_ITR0_CLKS_SHIFT 12
+#define EUR_CR_CLKGATESTATUS_TEX0_CLKS_MASK 0x00002000U
+#define EUR_CR_CLKGATESTATUS_TEX0_CLKS_SHIFT 13
+#define EUR_CR_CLKGATESTATUS_MADD0_CLKS_MASK 0x00004000U
+#define EUR_CR_CLKGATESTATUS_MADD0_CLKS_SHIFT 14
+#define EUR_CR_CLKGATESTATUS_USE1_CLKS_MASK 0x00008000U
+#define EUR_CR_CLKGATESTATUS_USE1_CLKS_SHIFT 15
+#define EUR_CR_CLKGATESTATUS_ITR1_CLKS_MASK 0x00010000U
+#define EUR_CR_CLKGATESTATUS_ITR1_CLKS_SHIFT 16
+#define EUR_CR_CLKGATESTATUS_TEX1_CLKS_MASK 0x00020000U
+#define EUR_CR_CLKGATESTATUS_TEX1_CLKS_SHIFT 17
+#define EUR_CR_CLKGATESTATUS_MADD1_CLKS_MASK 0x00040000U
+#define EUR_CR_CLKGATESTATUS_MADD1_CLKS_SHIFT 18
+#define EUR_CR_CLKGATESTATUS_IDXFIFO_CLKS_MASK 0x00080000U
+#define EUR_CR_CLKGATESTATUS_IDXFIFO_CLKS_SHIFT 19
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_MASK 0x00100000U
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_SHIFT 20
+#define EUR_CR_CLKGATECTLOVR 0x000C
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_MASK 0x00000003U
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_SHIFT 0
+#define EUR_CR_CLKGATECTLOVR_ISP2_CLKO_MASK 0x0000000CU
+#define EUR_CR_CLKGATECTLOVR_ISP2_CLKO_SHIFT 2
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_MASK 0x00000030U
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_SHIFT 4
+#define EUR_CR_CLKGATECTLOVR_TE_CLKO_MASK 0x000000C0U
+#define EUR_CR_CLKGATECTLOVR_TE_CLKO_SHIFT 6
+#define EUR_CR_CLKGATECTLOVR_MTE_CLKO_MASK 0x00000300U
+#define EUR_CR_CLKGATECTLOVR_MTE_CLKO_SHIFT 8
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_MASK 0x00000C00U
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_SHIFT 10
+#define EUR_CR_CLKGATECTLOVR_VDM_CLKO_MASK 0x00003000U
+#define EUR_CR_CLKGATECTLOVR_VDM_CLKO_SHIFT 12
+#define EUR_CR_CLKGATECTLOVR_PDS_CLKO_MASK 0x0000C000U
+#define EUR_CR_CLKGATECTLOVR_PDS_CLKO_SHIFT 14
+#define EUR_CR_CLKGATECTLOVR_IDXFIFO_CLKO_MASK 0x00030000U
+#define EUR_CR_CLKGATECTLOVR_IDXFIFO_CLKO_SHIFT 16
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_MASK 0x000C0000U
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_SHIFT 18
+#define EUR_CR_CORE_ID 0x0020
+#define EUR_CR_CORE_ID_CONFIG_MASK 0x0000FFFFU
+#define EUR_CR_CORE_ID_CONFIG_SHIFT 0
+#define EUR_CR_CORE_ID_ID_MASK 0xFFFF0000U
+#define EUR_CR_CORE_ID_ID_SHIFT 16
+#define EUR_CR_CORE_REVISION 0x0024
+#define EUR_CR_CORE_REVISION_MAINTENANCE_MASK 0x000000FFU
+#define EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT 0
+#define EUR_CR_CORE_REVISION_MINOR_MASK 0x0000FF00U
+#define EUR_CR_CORE_REVISION_MINOR_SHIFT 8
+#define EUR_CR_CORE_REVISION_MAJOR_MASK 0x00FF0000U
+#define EUR_CR_CORE_REVISION_MAJOR_SHIFT 16
+#define EUR_CR_CORE_REVISION_DESIGNER_MASK 0xFF000000U
+#define EUR_CR_CORE_REVISION_DESIGNER_SHIFT 24
+#define EUR_CR_DESIGNER_REV_FIELD1 0x0028
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_MASK 0xFFFFFFFFU
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SHIFT 0
+#define EUR_CR_DESIGNER_REV_FIELD2 0x002C
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_MASK 0xFFFFFFFFU
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SHIFT 0
+#define EUR_CR_SOFT_RESET 0x0080
+#define EUR_CR_SOFT_RESET_BIF_RESET_MASK 0x00000001U
+#define EUR_CR_SOFT_RESET_BIF_RESET_SHIFT 0
+#define EUR_CR_SOFT_RESET_VDM_RESET_MASK 0x00000002U
+#define EUR_CR_SOFT_RESET_VDM_RESET_SHIFT 1
+#define EUR_CR_SOFT_RESET_DPM_RESET_MASK 0x00000004U
+#define EUR_CR_SOFT_RESET_DPM_RESET_SHIFT 2
+#define EUR_CR_SOFT_RESET_TE_RESET_MASK 0x00000008U
+#define EUR_CR_SOFT_RESET_TE_RESET_SHIFT 3
+#define EUR_CR_SOFT_RESET_MTE_RESET_MASK 0x00000010U
+#define EUR_CR_SOFT_RESET_MTE_RESET_SHIFT 4
+#define EUR_CR_SOFT_RESET_ISP_RESET_MASK 0x00000020U
+#define EUR_CR_SOFT_RESET_ISP_RESET_SHIFT 5
+#define EUR_CR_SOFT_RESET_ISP2_RESET_MASK 0x00000040U
+#define EUR_CR_SOFT_RESET_ISP2_RESET_SHIFT 6
+#define EUR_CR_SOFT_RESET_TSP_RESET_MASK 0x00000080U
+#define EUR_CR_SOFT_RESET_TSP_RESET_SHIFT 7
+#define EUR_CR_SOFT_RESET_PDS_RESET_MASK 0x00000100U
+#define EUR_CR_SOFT_RESET_PDS_RESET_SHIFT 8
+#define EUR_CR_SOFT_RESET_PBE_RESET_MASK 0x00000200U
+#define EUR_CR_SOFT_RESET_PBE_RESET_SHIFT 9
+#define EUR_CR_SOFT_RESET_CACHEL2_RESET_MASK 0x00000400U
+#define EUR_CR_SOFT_RESET_CACHEL2_RESET_SHIFT 10
+#define EUR_CR_SOFT_RESET_UCACHEL2_RESET_MASK 0x00000800U
+#define EUR_CR_SOFT_RESET_UCACHEL2_RESET_SHIFT 11
+#define EUR_CR_SOFT_RESET_MADD_RESET_MASK 0x00001000U
+#define EUR_CR_SOFT_RESET_MADD_RESET_SHIFT 12
+#define EUR_CR_SOFT_RESET_ITR_RESET_MASK 0x00002000U
+#define EUR_CR_SOFT_RESET_ITR_RESET_SHIFT 13
+#define EUR_CR_SOFT_RESET_TEX_RESET_MASK 0x00004000U
+#define EUR_CR_SOFT_RESET_TEX_RESET_SHIFT 14
+#define EUR_CR_SOFT_RESET_USE_RESET_MASK 0x00008000U
+#define EUR_CR_SOFT_RESET_USE_RESET_SHIFT 15
+#define EUR_CR_SOFT_RESET_IDXFIFO_RESET_MASK 0x00010000U
+#define EUR_CR_SOFT_RESET_IDXFIFO_RESET_SHIFT 16
+#define EUR_CR_SOFT_RESET_TA_RESET_MASK 0x00020000U
+#define EUR_CR_SOFT_RESET_TA_RESET_SHIFT 17
+#define EUR_CR_EVENT_HOST_ENABLE2 0x0110
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_HOST_CLEAR2 0x0114
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_STATUS2 0x0118
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_MASK 0x00000010U
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_SHIFT 4
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_MASK 0x00000008U
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_SHIFT 3
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_MASK 0x00000004U
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_SHIFT 2
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_STATUS 0x012CU
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_STATUS_TIMER_MASK 0x20000000U
+#define EUR_CR_EVENT_STATUS_TIMER_SHIFT 29
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_STATUS_TWOD_COMPLETE_MASK 0x08000000U
+#define EUR_CR_EVENT_STATUS_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_STATUS_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_STATUS_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_STATUS_ISP_HALT_MASK 0x00020000U
+#define EUR_CR_EVENT_STATUS_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_STATUS_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_STATUS_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_HOST_ENABLE 0x0130
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_MASK 0x20000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_ENABLE_TWOD_COMPLETE_MASK 0x08000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_MASK 0x00020000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_HOST_CLEAR 0x0134
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_MASK 0x20000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_CLEAR_TWOD_COMPLETE_MASK 0x08000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_MASK 0x00020000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_TIMER 0x0144
+#define EUR_CR_TIMER_VALUE_MASK 0xFFFFFFFFU
+#define EUR_CR_TIMER_VALUE_SHIFT 0
+#define EUR_CR_EVENT_KICK1 0x0AB0
+#define EUR_CR_EVENT_KICK1_NOW_MASK 0x000000FFU
+#define EUR_CR_EVENT_KICK1_NOW_SHIFT 0
+#define EUR_CR_PDS_EXEC_BASE 0x0AB8
+#define EUR_CR_PDS_EXEC_BASE_ADDR_MASK 0x0FF00000U
+#define EUR_CR_PDS_EXEC_BASE_ADDR_SHIFT 20
+#define EUR_CR_EVENT_KICK2 0x0AC0
+#define EUR_CR_EVENT_KICK2_NOW_MASK 0x00000001U
+#define EUR_CR_EVENT_KICK2_NOW_SHIFT 0
+#define EUR_CR_EVENT_KICKER 0x0AC4
+#define EUR_CR_EVENT_KICKER_ADDRESS_MASK 0x0FFFFFF0U
+#define EUR_CR_EVENT_KICKER_ADDRESS_SHIFT 4
+#define EUR_CR_EVENT_KICK 0x0AC8
+#define EUR_CR_EVENT_KICK_NOW_MASK 0x00000001U
+#define EUR_CR_EVENT_KICK_NOW_SHIFT 0
+#define EUR_CR_EVENT_TIMER 0x0ACC
+#define EUR_CR_EVENT_TIMER_ENABLE_MASK 0x01000000U
+#define EUR_CR_EVENT_TIMER_ENABLE_SHIFT 24
+#define EUR_CR_EVENT_TIMER_VALUE_MASK 0x00FFFFFFU
+#define EUR_CR_EVENT_TIMER_VALUE_SHIFT 0
+#define EUR_CR_PDS_INV0 0x0AD0
+#define EUR_CR_PDS_INV0_DSC_MASK 0x00000001U
+#define EUR_CR_PDS_INV0_DSC_SHIFT 0
+#define EUR_CR_PDS_INV1 0x0AD4
+#define EUR_CR_PDS_INV1_DSC_MASK 0x00000001U
+#define EUR_CR_PDS_INV1_DSC_SHIFT 0
+#define EUR_CR_EVENT_KICK3 0x0AD8
+#define EUR_CR_EVENT_KICK3_NOW_MASK 0x00000001U
+#define EUR_CR_EVENT_KICK3_NOW_SHIFT 0
+#define EUR_CR_PDS_INV3 0x0ADC
+#define EUR_CR_PDS_INV3_DSC_MASK 0x00000001U
+#define EUR_CR_PDS_INV3_DSC_SHIFT 0
+#define EUR_CR_PDS_INV_CSC 0x0AE0
+#define EUR_CR_PDS_INV_CSC_KICK_MASK 0x00000001U
+#define EUR_CR_PDS_INV_CSC_KICK_SHIFT 0
+#define EUR_CR_PDS_PC_BASE 0x0B2C
+#define EUR_CR_PDS_PC_BASE_ADDRESS_MASK 0x00FFFFFFU
+#define EUR_CR_PDS_PC_BASE_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_CTRL 0x0C00
+#define EUR_CR_BIF_CTRL_NOREORDER_MASK 0x00000001U
+#define EUR_CR_BIF_CTRL_NOREORDER_SHIFT 0
+#define EUR_CR_BIF_CTRL_PAUSE_MASK 0x00000002U
+#define EUR_CR_BIF_CTRL_PAUSE_SHIFT 1
+#define EUR_CR_BIF_CTRL_FLUSH_MASK 0x00000004U
+#define EUR_CR_BIF_CTRL_FLUSH_SHIFT 2
+#define EUR_CR_BIF_CTRL_INVALDC_MASK 0x00000008U
+#define EUR_CR_BIF_CTRL_INVALDC_SHIFT 3
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_MASK 0x00000010U
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_SHIFT 4
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_MASK 0x00000100U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_SHIFT 8
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_MASK 0x00000200U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_SHIFT 9
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_MASK 0x00000400U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_SHIFT 10
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_MASK 0x00001000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_SHIFT 12
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_MASK 0x00002000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_SHIFT 13
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_MASK 0x00004000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_SHIFT 14
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_MASK 0x00008000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_SHIFT 15
+#define EUR_CR_BIF_INT_STAT 0x0C04
+#define EUR_CR_BIF_INT_STAT_FAULT_MASK 0x00003FFFU
+#define EUR_CR_BIF_INT_STAT_FAULT_SHIFT 0
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_MASK 0x00004000U
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_SHIFT 14
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_MASK 0x00008000U
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_SHIFT 15
+#define EUR_CR_BIF_FAULT 0x0C08
+#define EUR_CR_BIF_FAULT_SB_MASK 0x000001F0U
+#define EUR_CR_BIF_FAULT_SB_SHIFT 4
+#define EUR_CR_BIF_FAULT_ADDR_MASK 0x0FFFF000U
+#define EUR_CR_BIF_FAULT_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE0 0x0C84
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_SHIFT 12
+#define EUR_CR_BIF_TA_REQ_BASE 0x0C90
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_MASK 0x0FF00000U
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_SHIFT 20
+#define EUR_CR_BIF_MEM_REQ_STAT 0x0CA8
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_MASK 0x000000FFU
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_SHIFT 0
+#define EUR_CR_BIF_3D_REQ_BASE 0x0CAC
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_MASK 0x0FF00000U
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_SHIFT 20
+#define EUR_CR_BIF_ZLS_REQ_BASE 0x0CB0
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_MASK 0x0FF00000U
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_SHIFT 20
+#define EUR_CR_2D_BLIT_STATUS 0x0E04
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_MASK 0x00FFFFFFU
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_SHIFT 0
+#define EUR_CR_2D_BLIT_STATUS_BUSY_MASK 0x01000000U
+#define EUR_CR_2D_BLIT_STATUS_BUSY_SHIFT 24
+#define EUR_CR_2D_VIRTUAL_FIFO_0 0x0E10
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_MASK 0x00000001U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MASK 0x0000000EU
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_SHIFT 1
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_MASK 0x00000FF0U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_SHIFT 4
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_MASK 0x0000F000U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_SHIFT 12
+#define EUR_CR_2D_VIRTUAL_FIFO_1 0x0E14
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_MASK 0x00000FFFU
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_MASK 0x00FFF000U
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_SHIFT 12
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_MASK 0xFF000000U
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_SHIFT 24
+#define EUR_CR_USE_CODE_BASE(X) (0x0A0C + (4 * (X)))
+#define EUR_CR_USE_CODE_BASE_ADDR_MASK 0x00FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_SHIFT 0
+#define EUR_CR_USE_CODE_BASE_DM_MASK 0x03000000U
+#define EUR_CR_USE_CODE_BASE_DM_SHIFT 24
+#define EUR_CR_USE_CODE_BASE_SIZE_UINT32 16
+#define EUR_CR_USE_CODE_BASE_NUM_ENTRIES 16
+
+#endif
+
diff --git a/drivers/gpu/pvr/sgx535defs.h b/drivers/gpu/pvr/sgx535defs.h
new file mode 100644
index 0000000..04f43be
--- /dev/null
+++ b/drivers/gpu/pvr/sgx535defs.h
@@ -0,0 +1,650 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef _SGX535DEFS_KM_H_
+#define _SGX535DEFS_KM_H_
+
+#define EUR_CR_CLKGATECTL 0x0000
+#define EUR_CR_CLKGATECTL_2D_CLKG_MASK 0x00000003U
+#define EUR_CR_CLKGATECTL_2D_CLKG_SHIFT 0
+#define EUR_CR_CLKGATECTL_ISP_CLKG_MASK 0x00000030U
+#define EUR_CR_CLKGATECTL_ISP_CLKG_SHIFT 4
+#define EUR_CR_CLKGATECTL_TSP_CLKG_MASK 0x00000300U
+#define EUR_CR_CLKGATECTL_TSP_CLKG_SHIFT 8
+#define EUR_CR_CLKGATECTL_TA_CLKG_MASK 0x00003000U
+#define EUR_CR_CLKGATECTL_TA_CLKG_SHIFT 12
+#define EUR_CR_CLKGATECTL_DPM_CLKG_MASK 0x00030000U
+#define EUR_CR_CLKGATECTL_DPM_CLKG_SHIFT 16
+#define EUR_CR_CLKGATECTL_USE_CLKG_MASK 0x00300000U
+#define EUR_CR_CLKGATECTL_USE_CLKG_SHIFT 20
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_MASK 0x01000000U
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_SHIFT 24
+#define EUR_CR_CLKGATESTATUS 0x0004
+#define EUR_CR_CLKGATESTATUS_2D_CLKS_MASK 0x00000001
+#define EUR_CR_CLKGATESTATUS_2D_CLKS_SHIFT 0
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_MASK 0x00000010U
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_SHIFT 4
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_MASK 0x00000100U
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_SHIFT 8
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_MASK 0x00001000U
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_SHIFT 12
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_MASK 0x00010000U
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_SHIFT 16
+#define EUR_CR_CLKGATESTATUS_USE_CLKS_MASK 0x00100000U
+#define EUR_CR_CLKGATESTATUS_USE_CLKS_SHIFT 20
+#define EUR_CR_CLKGATECTLOVR 0x0008
+#define EUR_CR_CLKGATECTLOVR_2D_CLKO_MASK 0x00000003U
+#define EUR_CR_CLKGATECTLOVR_2D_CLKO_SHIFT 0
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_MASK 0x00000030U
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_SHIFT 4
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_MASK 0x00000300U
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_SHIFT 8
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_MASK 0x00003000U
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_SHIFT 12
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_MASK 0x00030000U
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_SHIFT 16
+#define EUR_CR_CLKGATECTLOVR_USE_CLKO_MASK 0x00300000U
+#define EUR_CR_CLKGATECTLOVR_USE_CLKO_SHIFT 20
+#define EUR_CR_CORE_ID 0x0010
+#define EUR_CR_CORE_ID_CONFIG_MASK 0x0000FFFFU
+#define EUR_CR_CORE_ID_CONFIG_SHIFT 0
+#define EUR_CR_CORE_ID_ID_MASK 0xFFFF0000U
+#define EUR_CR_CORE_ID_ID_SHIFT 16
+#define EUR_CR_CORE_REVISION 0x0014
+#define EUR_CR_CORE_REVISION_MAINTENANCE_MASK 0x000000FFU
+#define EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT 0
+#define EUR_CR_CORE_REVISION_MINOR_MASK 0x0000FF00U
+#define EUR_CR_CORE_REVISION_MINOR_SHIFT 8
+#define EUR_CR_CORE_REVISION_MAJOR_MASK 0x00FF0000U
+#define EUR_CR_CORE_REVISION_MAJOR_SHIFT 16
+#define EUR_CR_CORE_REVISION_DESIGNER_MASK 0xFF000000U
+#define EUR_CR_CORE_REVISION_DESIGNER_SHIFT 24
+#define EUR_CR_DESIGNER_REV_FIELD1 0x0018
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_MASK 0xFFFFFFFFU
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SHIFT 0
+#define EUR_CR_DESIGNER_REV_FIELD2 0x001C
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_MASK 0xFFFFFFFFU
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SHIFT 0
+#define EUR_CR_SOFT_RESET 0x0080
+#define EUR_CR_SOFT_RESET_BIF_RESET_MASK 0x00000001U
+#define EUR_CR_SOFT_RESET_BIF_RESET_SHIFT 0
+#define EUR_CR_SOFT_RESET_TWOD_RESET_MASK 0x00000002U
+#define EUR_CR_SOFT_RESET_TWOD_RESET_SHIFT 1
+#define EUR_CR_SOFT_RESET_DPM_RESET_MASK 0x00000004U
+#define EUR_CR_SOFT_RESET_DPM_RESET_SHIFT 2
+#define EUR_CR_SOFT_RESET_TA_RESET_MASK 0x00000008U
+#define EUR_CR_SOFT_RESET_TA_RESET_SHIFT 3
+#define EUR_CR_SOFT_RESET_USE_RESET_MASK 0x00000010U
+#define EUR_CR_SOFT_RESET_USE_RESET_SHIFT 4
+#define EUR_CR_SOFT_RESET_ISP_RESET_MASK 0x00000020U
+#define EUR_CR_SOFT_RESET_ISP_RESET_SHIFT 5
+#define EUR_CR_SOFT_RESET_TSP_RESET_MASK 0x00000040U
+#define EUR_CR_SOFT_RESET_TSP_RESET_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE2 0x0110
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_SHIFT 7
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_SHIFT 5
+#define EUR_CR_EVENT_HOST_ENABLE2_BIF_REQUESTER_FAULT_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_ENABLE2_BIF_REQUESTER_FAULT_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_DHOST_FREE_LOAD_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_DHOST_FREE_LOAD_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_HOST_FREE_LOAD_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_HOST_FREE_LOAD_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_HOST_CLEAR2 0x0114
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_SHIFT 7
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_SHIFT 6
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_SHIFT 5
+#define EUR_CR_EVENT_HOST_CLEAR2_BIF_REQUESTER_FAULT_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_CLEAR2_BIF_REQUESTER_FAULT_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_DHOST_FREE_LOAD_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_DHOST_FREE_LOAD_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_HOST_FREE_LOAD_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_HOST_FREE_LOAD_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_STATUS2 0x0118U
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_MASK 0x00000080U
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_SHIFT 7
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_MASK 0x00000040U
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_SHIFT 6
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_MASK 0x00000020U
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_SHIFT 5
+#define EUR_CR_EVENT_STATUS2_BIF_REQUESTER_FAULT_MASK 0x00000010U
+#define EUR_CR_EVENT_STATUS2_BIF_REQUESTER_FAULT_SHIFT 4
+#define EUR_CR_EVENT_STATUS2_DPM_DHOST_FREE_LOAD_MASK 0x00000008U
+#define EUR_CR_EVENT_STATUS2_DPM_DHOST_FREE_LOAD_SHIFT 3
+#define EUR_CR_EVENT_STATUS2_DPM_HOST_FREE_LOAD_MASK 0x00000004U
+#define EUR_CR_EVENT_STATUS2_DPM_HOST_FREE_LOAD_SHIFT 2
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_STATUS 0x012CU
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_STATUS_TIMER_MASK 0x20000000U
+#define EUR_CR_EVENT_STATUS_TIMER_SHIFT 29
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_STATUS_TWOD_COMPLETE_MASK 0x08000000U
+#define EUR_CR_EVENT_STATUS_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_STATUS_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_STATUS_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_STATUS_ISP_HALT_MASK 0x00020000U
+#define EUR_CR_EVENT_STATUS_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_STATUS_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_STATUS_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_HOST_ENABLE 0x0130
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_MASK 0x20000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_ENABLE_TWOD_COMPLETE_MASK 0x08000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_MASK 0x00020000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_HOST_CLEAR 0x0134
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_MASK 0x20000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_CLEAR_TWOD_COMPLETE_MASK 0x08000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_MASK 0x00020000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_PDS_EXEC_BASE 0x0AB8
+#define EUR_CR_PDS_EXEC_BASE_ADDR_MASK 0xFFF00000U
+#define EUR_CR_PDS_EXEC_BASE_ADDR_SHIFT 20
+#define EUR_CR_EVENT_KICKER 0x0AC4
+#define EUR_CR_EVENT_KICKER_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_EVENT_KICKER_ADDRESS_SHIFT 4
+#define EUR_CR_EVENT_KICK 0x0AC8
+#define EUR_CR_EVENT_KICK_NOW_MASK 0x00000001U
+#define EUR_CR_EVENT_KICK_NOW_SHIFT 0
+#define EUR_CR_EVENT_TIMER 0x0ACC
+#define EUR_CR_EVENT_TIMER_ENABLE_MASK 0x01000000U
+#define EUR_CR_EVENT_TIMER_ENABLE_SHIFT 24
+#define EUR_CR_EVENT_TIMER_VALUE_MASK 0x00FFFFFFU
+#define EUR_CR_EVENT_TIMER_VALUE_SHIFT 0
+#define EUR_CR_PDS_INV0 0x0AD0
+#define EUR_CR_PDS_INV0_DSC_MASK 0x00000001U
+#define EUR_CR_PDS_INV0_DSC_SHIFT 0
+#define EUR_CR_PDS_INV1 0x0AD4
+#define EUR_CR_PDS_INV1_DSC_MASK 0x00000001U
+#define EUR_CR_PDS_INV1_DSC_SHIFT 0
+#define EUR_CR_PDS_INV2 0x0AD8
+#define EUR_CR_PDS_INV2_DSC_MASK 0x00000001U
+#define EUR_CR_PDS_INV2_DSC_SHIFT 0
+#define EUR_CR_PDS_INV3 0x0ADC
+#define EUR_CR_PDS_INV3_DSC_MASK 0x00000001U
+#define EUR_CR_PDS_INV3_DSC_SHIFT 0
+#define EUR_CR_PDS_INV_CSC 0x0AE0
+#define EUR_CR_PDS_INV_CSC_KICK_MASK 0x00000001U
+#define EUR_CR_PDS_INV_CSC_KICK_SHIFT 0
+#define EUR_CR_PDS_PC_BASE 0x0B2C
+#define EUR_CR_PDS_PC_BASE_ADDRESS_MASK 0x3FFFFFFFU
+#define EUR_CR_PDS_PC_BASE_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_CTRL 0x0C00
+#define EUR_CR_BIF_CTRL_NOREORDER_MASK 0x00000001U
+#define EUR_CR_BIF_CTRL_NOREORDER_SHIFT 0
+#define EUR_CR_BIF_CTRL_PAUSE_MASK 0x00000002U
+#define EUR_CR_BIF_CTRL_PAUSE_SHIFT 1
+#define EUR_CR_BIF_CTRL_FLUSH_MASK 0x00000004U
+#define EUR_CR_BIF_CTRL_FLUSH_SHIFT 2
+#define EUR_CR_BIF_CTRL_INVALDC_MASK 0x00000008U
+#define EUR_CR_BIF_CTRL_INVALDC_SHIFT 3
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_MASK 0x00000010U
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_SHIFT 4
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_MASK 0x00000100U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_SHIFT 8
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_MASK 0x00000200U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_SHIFT 9
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_MASK 0x00000400U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_SHIFT 10
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TWOD_MASK 0x00000800U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TWOD_SHIFT 11
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_MASK 0x00001000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_SHIFT 12
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_MASK 0x00002000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_SHIFT 13
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_MASK 0x00004000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_SHIFT 14
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_MASK 0x00008000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_SHIFT 15
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_MASK 0x00010000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_SHIFT 16
+#define EUR_CR_BIF_INT_STAT 0x0C04
+#define EUR_CR_BIF_INT_STAT_FAULT_MASK 0x00003FFFU
+#define EUR_CR_BIF_INT_STAT_FAULT_SHIFT 0
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_MASK 0x00004000U
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_SHIFT 14
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_MASK 0x00008000U
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_SHIFT 15
+#define EUR_CR_BIF_FAULT 0x0C08
+#define EUR_CR_BIF_FAULT_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_FAULT_ADDR_SHIFT 12
+#define EUR_CR_BIF_TILE0 0x0C0C
+#define EUR_CR_BIF_TILE0_MIN_ADDRESS_MASK 0x00000FFFU
+#define EUR_CR_BIF_TILE0_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE0_MAX_ADDRESS_MASK 0x00FFF000U
+#define EUR_CR_BIF_TILE0_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE0_CFG_MASK 0x0F000000U
+#define EUR_CR_BIF_TILE0_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE1 0x0C10
+#define EUR_CR_BIF_TILE1_MIN_ADDRESS_MASK 0x00000FFFU
+#define EUR_CR_BIF_TILE1_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE1_MAX_ADDRESS_MASK 0x00FFF000U
+#define EUR_CR_BIF_TILE1_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE1_CFG_MASK 0x0F000000U
+#define EUR_CR_BIF_TILE1_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE2 0x0C14
+#define EUR_CR_BIF_TILE2_MIN_ADDRESS_MASK 0x00000FFFU
+#define EUR_CR_BIF_TILE2_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE2_MAX_ADDRESS_MASK 0x00FFF000U
+#define EUR_CR_BIF_TILE2_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE2_CFG_MASK 0x0F000000U
+#define EUR_CR_BIF_TILE2_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE3 0x0C18
+#define EUR_CR_BIF_TILE3_MIN_ADDRESS_MASK 0x00000FFFU
+#define EUR_CR_BIF_TILE3_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE3_MAX_ADDRESS_MASK 0x00FFF000U
+#define EUR_CR_BIF_TILE3_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE3_CFG_MASK 0x0F000000U
+#define EUR_CR_BIF_TILE3_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE4 0x0C1C
+#define EUR_CR_BIF_TILE4_MIN_ADDRESS_MASK 0x00000FFFU
+#define EUR_CR_BIF_TILE4_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE4_MAX_ADDRESS_MASK 0x00FFF000U
+#define EUR_CR_BIF_TILE4_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE4_CFG_MASK 0x0F000000U
+#define EUR_CR_BIF_TILE4_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE5 0x0C20
+#define EUR_CR_BIF_TILE5_MIN_ADDRESS_MASK 0x00000FFFU
+#define EUR_CR_BIF_TILE5_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE5_MAX_ADDRESS_MASK 0x00FFF000U
+#define EUR_CR_BIF_TILE5_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE5_CFG_MASK 0x0F000000U
+#define EUR_CR_BIF_TILE5_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE6 0x0C24
+#define EUR_CR_BIF_TILE6_MIN_ADDRESS_MASK 0x00000FFFU
+#define EUR_CR_BIF_TILE6_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE6_MAX_ADDRESS_MASK 0x00FFF000U
+#define EUR_CR_BIF_TILE6_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE6_CFG_MASK 0x0F000000U
+#define EUR_CR_BIF_TILE6_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE7 0x0C28
+#define EUR_CR_BIF_TILE7_MIN_ADDRESS_MASK 0x00000FFFU
+#define EUR_CR_BIF_TILE7_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE7_MAX_ADDRESS_MASK 0x00FFF000U
+#define EUR_CR_BIF_TILE7_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE7_CFG_MASK 0x0F000000U
+#define EUR_CR_BIF_TILE7_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE8 0x0C2C
+#define EUR_CR_BIF_TILE8_MIN_ADDRESS_MASK 0x00000FFFU
+#define EUR_CR_BIF_TILE8_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE8_MAX_ADDRESS_MASK 0x00FFF000U
+#define EUR_CR_BIF_TILE8_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE8_CFG_MASK 0x0F000000U
+#define EUR_CR_BIF_TILE8_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE9 0x0C30
+#define EUR_CR_BIF_TILE9_MIN_ADDRESS_MASK 0x00000FFFU
+#define EUR_CR_BIF_TILE9_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE9_MAX_ADDRESS_MASK 0x00FFF000U
+#define EUR_CR_BIF_TILE9_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE9_CFG_MASK 0x0F000000U
+#define EUR_CR_BIF_TILE9_CFG_SHIFT 24
+#define EUR_CR_BIF_DIR_LIST_BASE1 0x0C38
+#define EUR_CR_BIF_DIR_LIST_BASE1_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE1_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE2 0x0C3C
+#define EUR_CR_BIF_DIR_LIST_BASE2_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE2_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE3 0x0C40
+#define EUR_CR_BIF_DIR_LIST_BASE3_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE3_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE4 0x0C44
+#define EUR_CR_BIF_DIR_LIST_BASE4_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE4_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE5 0x0C48
+#define EUR_CR_BIF_DIR_LIST_BASE5_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE5_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE6 0x0C4C
+#define EUR_CR_BIF_DIR_LIST_BASE6_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE6_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE7 0x0C50
+#define EUR_CR_BIF_DIR_LIST_BASE7_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE7_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE8 0x0C54
+#define EUR_CR_BIF_DIR_LIST_BASE8_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE8_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE9 0x0C58
+#define EUR_CR_BIF_DIR_LIST_BASE9_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE9_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE10 0x0C5C
+#define EUR_CR_BIF_DIR_LIST_BASE10_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE10_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE11 0x0C60
+#define EUR_CR_BIF_DIR_LIST_BASE11_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE11_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE12 0x0C64
+#define EUR_CR_BIF_DIR_LIST_BASE12_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE12_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE13 0x0C68
+#define EUR_CR_BIF_DIR_LIST_BASE13_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE13_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE14 0x0C6C
+#define EUR_CR_BIF_DIR_LIST_BASE14_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE14_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE15 0x0C70
+#define EUR_CR_BIF_DIR_LIST_BASE15_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE15_ADDR_SHIFT 12
+#define EUR_CR_BIF_BANK_SET 0x0C74
+#define EUR_CR_BIF_BANK_SET_SELECT_MASK 0x000003FFU
+#define EUR_CR_BIF_BANK_SET_SELECT_SHIFT 0
+#define EUR_CR_BIF_BANK0 0x0C78
+#define EUR_CR_BIF_BANK0_INDEX_EDM_MASK 0x0000000FU
+#define EUR_CR_BIF_BANK0_INDEX_EDM_SHIFT 0
+#define EUR_CR_BIF_BANK0_INDEX_TA_MASK 0x000000F0U
+#define EUR_CR_BIF_BANK0_INDEX_TA_SHIFT 4
+#define EUR_CR_BIF_BANK0_INDEX_HOST_MASK 0x00000F00U
+#define EUR_CR_BIF_BANK0_INDEX_HOST_SHIFT 8
+#define EUR_CR_BIF_BANK0_INDEX_3D_MASK 0x0000F000U
+#define EUR_CR_BIF_BANK0_INDEX_3D_SHIFT 12
+#define EUR_CR_BIF_BANK0_INDEX_2D_MASK 0x000F0000U
+#define EUR_CR_BIF_BANK0_INDEX_2D_SHIFT 16
+#define EUR_CR_BIF_BANK1 0x0C7C
+#define EUR_CR_BIF_BANK1_INDEX_EDM_MASK 0x0000000FU
+#define EUR_CR_BIF_BANK1_INDEX_EDM_SHIFT 0
+#define EUR_CR_BIF_BANK1_INDEX_TA_MASK 0x000000F0U
+#define EUR_CR_BIF_BANK1_INDEX_TA_SHIFT 4
+#define EUR_CR_BIF_BANK1_INDEX_HOST_MASK 0x00000F00U
+#define EUR_CR_BIF_BANK1_INDEX_HOST_SHIFT 8
+#define EUR_CR_BIF_BANK1_INDEX_3D_MASK 0x0000F000U
+#define EUR_CR_BIF_BANK1_INDEX_3D_SHIFT 12
+#define EUR_CR_BIF_BANK1_INDEX_2D_MASK 0x000F0000U
+#define EUR_CR_BIF_BANK1_INDEX_2D_SHIFT 16
+#define EUR_CR_BIF_ADT_TTE 0x0C80
+#define EUR_CR_BIF_ADT_TTE_VALUE_MASK 0x000000FFU
+#define EUR_CR_BIF_ADT_TTE_VALUE_SHIFT 0
+#define EUR_CR_BIF_DIR_LIST_BASE0 0x0C84
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_SHIFT 12
+#define EUR_CR_BIF_TWOD_REQ_BASE 0x0C88
+#define EUR_CR_BIF_TWOD_REQ_BASE_ADDR_MASK 0xFFF00000U
+#define EUR_CR_BIF_TWOD_REQ_BASE_ADDR_SHIFT 20
+#define EUR_CR_BIF_TA_REQ_BASE 0x0C90
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_MASK 0xFFF00000U
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_SHIFT 20
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1 0x0C94
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_MMU_MASK 0x00000007U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_MMU_SHIFT 0
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_CACHE_MASK 0x00000038U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_CACHE_SHIFT 3
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_VDM_MASK 0x000001C0U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_VDM_SHIFT 6
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_TE_MASK 0x00000E00U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_TE_SHIFT 9
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_TWOD_MASK 0x00007000U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_TWOD_SHIFT 12
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_PBE_MASK 0x00038000U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_PBE_SHIFT 15
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2 0x0C98
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_HOST_MASK 0x00000007U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_HOST_SHIFT 0
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_USE_MASK 0x00000038U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_USE_SHIFT 3
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_ISP_MASK 0x000001C0U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_ISP_SHIFT 6
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_TSPP_MASK 0x00000E00U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_TSPP_SHIFT 9
+#define EUR_CR_BIF_MEM_ARB_CONFIG 0x0CA0
+#define EUR_CR_BIF_MEM_ARB_CONFIG_PAGE_SIZE_MASK 0x0000000FU
+#define EUR_CR_BIF_MEM_ARB_CONFIG_PAGE_SIZE_SHIFT 0
+#define EUR_CR_BIF_MEM_ARB_CONFIG_BEST_CNT_MASK 0x00000FF0U
+#define EUR_CR_BIF_MEM_ARB_CONFIG_BEST_CNT_SHIFT 4
+#define EUR_CR_BIF_MEM_ARB_CONFIG_TTE_THRESH_MASK 0x00FFF000U
+#define EUR_CR_BIF_MEM_ARB_CONFIG_TTE_THRESH_SHIFT 12
+#define EUR_CR_BIF_MEM_REQ_STAT 0x0CA8
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_MASK 0x000000FFU
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_SHIFT 0
+#define EUR_CR_BIF_3D_REQ_BASE 0x0CAC
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_MASK 0xFFF00000U
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_SHIFT 20
+#define EUR_CR_BIF_ZLS_REQ_BASE 0x0CB0
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_MASK 0xFFF00000U
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_SHIFT 20
+#define EUR_CR_BIF_BANK_STATUS 0x0CB4
+#define EUR_CR_BIF_BANK_STATUS_3D_CURRENT_BANK_MASK 0x00000001U
+#define EUR_CR_BIF_BANK_STATUS_3D_CURRENT_BANK_SHIFT 0
+#define EUR_CR_BIF_BANK_STATUS_TA_CURRENT_BANK_MASK 0x00000002U
+#define EUR_CR_BIF_BANK_STATUS_TA_CURRENT_BANK_SHIFT 1
+#define EUR_CR_2D_BLIT_STATUS 0x0E04
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_MASK 0x00FFFFFFU
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_SHIFT 0
+#define EUR_CR_2D_BLIT_STATUS_BUSY_MASK 0x01000000U
+#define EUR_CR_2D_BLIT_STATUS_BUSY_SHIFT 24
+#define EUR_CR_2D_VIRTUAL_FIFO_0 0x0E10
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_MASK 0x00000001U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MASK 0x0000000EU
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_SHIFT 1
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_MASK 0x00000FF0U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_SHIFT 4
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_MASK 0x0000F000U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_SHIFT 12
+#define EUR_CR_2D_VIRTUAL_FIFO_1 0x0E14
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_MASK 0x00000FFFU
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_MASK 0x00FFF000U
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_SHIFT 12
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_MASK 0xFF000000U
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_SHIFT 24
+#define EUR_CR_2D_SOCIF 0x0E18
+#define EUR_CR_2D_SOCIF_FREESPACE_MASK 0x000000FFU
+#define EUR_CR_2D_SOCIF_FREESPACE_SHIFT 0
+#define EUR_CR_2D_ALPHA 0x0E1C
+#define EUR_CR_2D_ALPHA_COMPONENT_ONE_MASK 0x0000FF00U
+#define EUR_CR_2D_ALPHA_COMPONENT_ONE_SHIFT 8
+#define EUR_CR_2D_ALPHA_COMPONENT_ZERO_MASK 0x000000FFU
+#define EUR_CR_2D_ALPHA_COMPONENT_ZERO_SHIFT 0
+#define EUR_CR_USE_CODE_BASE(X) (0x0A0C + (4 * (X)))
+#define EUR_CR_USE_CODE_BASE_ADDR_MASK 0x01FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_SHIFT 0
+#define EUR_CR_USE_CODE_BASE_DM_MASK 0x06000000U
+#define EUR_CR_USE_CODE_BASE_DM_SHIFT 25
+#define EUR_CR_USE_CODE_BASE_SIZE_UINT32 16
+#define EUR_CR_USE_CODE_BASE_NUM_ENTRIES 16
+
+#endif
+
diff --git a/drivers/gpu/pvr/sgx540defs.h b/drivers/gpu/pvr/sgx540defs.h
new file mode 100644
index 0000000..c09aa26
--- /dev/null
+++ b/drivers/gpu/pvr/sgx540defs.h
@@ -0,0 +1,547 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef _SGX540DEFS_KM_H_
+#define _SGX540DEFS_KM_H_
+
+#define EUR_CR_CLKGATECTL 0x0000
+#define EUR_CR_CLKGATECTL_ISP_CLKG_MASK 0x00000003U
+#define EUR_CR_CLKGATECTL_ISP_CLKG_SHIFT 0
+#define EUR_CR_CLKGATECTL_ISP2_CLKG_MASK 0x0000000CU
+#define EUR_CR_CLKGATECTL_ISP2_CLKG_SHIFT 2
+#define EUR_CR_CLKGATECTL_TSP_CLKG_MASK 0x00000030U
+#define EUR_CR_CLKGATECTL_TSP_CLKG_SHIFT 4
+#define EUR_CR_CLKGATECTL_TE_CLKG_MASK 0x000000C0U
+#define EUR_CR_CLKGATECTL_TE_CLKG_SHIFT 6
+#define EUR_CR_CLKGATECTL_MTE_CLKG_MASK 0x00000300U
+#define EUR_CR_CLKGATECTL_MTE_CLKG_SHIFT 8
+#define EUR_CR_CLKGATECTL_DPM_CLKG_MASK 0x00000C00U
+#define EUR_CR_CLKGATECTL_DPM_CLKG_SHIFT 10
+#define EUR_CR_CLKGATECTL_VDM_CLKG_MASK 0x00003000U
+#define EUR_CR_CLKGATECTL_VDM_CLKG_SHIFT 12
+#define EUR_CR_CLKGATECTL_PDS_CLKG_MASK 0x0000C000U
+#define EUR_CR_CLKGATECTL_PDS_CLKG_SHIFT 14
+#define EUR_CR_CLKGATECTL_IDXFIFO_CLKG_MASK 0x00030000U
+#define EUR_CR_CLKGATECTL_IDXFIFO_CLKG_SHIFT 16
+#define EUR_CR_CLKGATECTL_TA_CLKG_MASK 0x000C0000U
+#define EUR_CR_CLKGATECTL_TA_CLKG_SHIFT 18
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_MASK 0x01000000U
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_SHIFT 24
+#define EUR_CR_CLKGATECTL_SYSTEM_CLKG_MASK 0x10000000U
+#define EUR_CR_CLKGATECTL_SYSTEM_CLKG_SHIFT 28
+#define EUR_CR_CLKGATECTL2 0x0004
+#define EUR_CR_CLKGATECTL2_PBE_CLKG_MASK 0x00000003U
+#define EUR_CR_CLKGATECTL2_PBE_CLKG_SHIFT 0
+#define EUR_CR_CLKGATECTL2_CACHEL2_CLKG_MASK 0x0000000CU
+#define EUR_CR_CLKGATECTL2_CACHEL2_CLKG_SHIFT 2
+#define EUR_CR_CLKGATECTL2_UCACHEL2_CLKG_MASK 0x00000030U
+#define EUR_CR_CLKGATECTL2_UCACHEL2_CLKG_SHIFT 4
+#define EUR_CR_CLKGATECTL2_USE0_CLKG_MASK 0x000000C0U
+#define EUR_CR_CLKGATECTL2_USE0_CLKG_SHIFT 6
+#define EUR_CR_CLKGATECTL2_ITR0_CLKG_MASK 0x00000300U
+#define EUR_CR_CLKGATECTL2_ITR0_CLKG_SHIFT 8
+#define EUR_CR_CLKGATECTL2_TEX0_CLKG_MASK 0x00000C00U
+#define EUR_CR_CLKGATECTL2_TEX0_CLKG_SHIFT 10
+#define EUR_CR_CLKGATECTL2_MADD0_CLKG_MASK 0x00003000U
+#define EUR_CR_CLKGATECTL2_MADD0_CLKG_SHIFT 12
+#define EUR_CR_CLKGATECTL2_USE1_CLKG_MASK 0x0000C000U
+#define EUR_CR_CLKGATECTL2_USE1_CLKG_SHIFT 14
+#define EUR_CR_CLKGATECTL2_ITR1_CLKG_MASK 0x00030000U
+#define EUR_CR_CLKGATECTL2_ITR1_CLKG_SHIFT 16
+#define EUR_CR_CLKGATECTL2_TEX1_CLKG_MASK 0x000C0000U
+#define EUR_CR_CLKGATECTL2_TEX1_CLKG_SHIFT 18
+#define EUR_CR_CLKGATECTL2_MADD1_CLKG_MASK 0x00300000U
+#define EUR_CR_CLKGATECTL2_MADD1_CLKG_SHIFT 20
+#define EUR_CR_CLKGATESTATUS 0x0008
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_MASK 0x00000001U
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_SHIFT 0
+#define EUR_CR_CLKGATESTATUS_ISP2_CLKS_MASK 0x00000002U
+#define EUR_CR_CLKGATESTATUS_ISP2_CLKS_SHIFT 1
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_MASK 0x00000004U
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_SHIFT 2
+#define EUR_CR_CLKGATESTATUS_TE_CLKS_MASK 0x00000008U
+#define EUR_CR_CLKGATESTATUS_TE_CLKS_SHIFT 3
+#define EUR_CR_CLKGATESTATUS_MTE_CLKS_MASK 0x00000010U
+#define EUR_CR_CLKGATESTATUS_MTE_CLKS_SHIFT 4
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_MASK 0x00000020U
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_SHIFT 5
+#define EUR_CR_CLKGATESTATUS_VDM_CLKS_MASK 0x00000040U
+#define EUR_CR_CLKGATESTATUS_VDM_CLKS_SHIFT 6
+#define EUR_CR_CLKGATESTATUS_PDS_CLKS_MASK 0x00000080U
+#define EUR_CR_CLKGATESTATUS_PDS_CLKS_SHIFT 7
+#define EUR_CR_CLKGATESTATUS_PBE_CLKS_MASK 0x00000100U
+#define EUR_CR_CLKGATESTATUS_PBE_CLKS_SHIFT 8
+#define EUR_CR_CLKGATESTATUS_CACHEL2_CLKS_MASK 0x00000200U
+#define EUR_CR_CLKGATESTATUS_CACHEL2_CLKS_SHIFT 9
+#define EUR_CR_CLKGATESTATUS_UCACHEL2_CLKS_MASK 0x00000400U
+#define EUR_CR_CLKGATESTATUS_UCACHEL2_CLKS_SHIFT 10
+#define EUR_CR_CLKGATESTATUS_USE0_CLKS_MASK 0x00000800U
+#define EUR_CR_CLKGATESTATUS_USE0_CLKS_SHIFT 11
+#define EUR_CR_CLKGATESTATUS_ITR0_CLKS_MASK 0x00001000U
+#define EUR_CR_CLKGATESTATUS_ITR0_CLKS_SHIFT 12
+#define EUR_CR_CLKGATESTATUS_TEX0_CLKS_MASK 0x00002000U
+#define EUR_CR_CLKGATESTATUS_TEX0_CLKS_SHIFT 13
+#define EUR_CR_CLKGATESTATUS_MADD0_CLKS_MASK 0x00004000U
+#define EUR_CR_CLKGATESTATUS_MADD0_CLKS_SHIFT 14
+#define EUR_CR_CLKGATESTATUS_USE1_CLKS_MASK 0x00008000U
+#define EUR_CR_CLKGATESTATUS_USE1_CLKS_SHIFT 15
+#define EUR_CR_CLKGATESTATUS_ITR1_CLKS_MASK 0x00010000U
+#define EUR_CR_CLKGATESTATUS_ITR1_CLKS_SHIFT 16
+#define EUR_CR_CLKGATESTATUS_TEX1_CLKS_MASK 0x00020000U
+#define EUR_CR_CLKGATESTATUS_TEX1_CLKS_SHIFT 17
+#define EUR_CR_CLKGATESTATUS_MADD1_CLKS_MASK 0x00040000U
+#define EUR_CR_CLKGATESTATUS_MADD1_CLKS_SHIFT 18
+#define EUR_CR_CLKGATESTATUS_IDXFIFO_CLKS_MASK 0x00080000U
+#define EUR_CR_CLKGATESTATUS_IDXFIFO_CLKS_SHIFT 19
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_MASK 0x00100000U
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_SHIFT 20
+#define EUR_CR_CLKGATECTLOVR 0x000C
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_MASK 0x00000003U
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_SHIFT 0
+#define EUR_CR_CLKGATECTLOVR_ISP2_CLKO_MASK 0x0000000CU
+#define EUR_CR_CLKGATECTLOVR_ISP2_CLKO_SHIFT 2
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_MASK 0x00000030U
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_SHIFT 4
+#define EUR_CR_CLKGATECTLOVR_TE_CLKO_MASK 0x000000C0U
+#define EUR_CR_CLKGATECTLOVR_TE_CLKO_SHIFT 6
+#define EUR_CR_CLKGATECTLOVR_MTE_CLKO_MASK 0x00000300U
+#define EUR_CR_CLKGATECTLOVR_MTE_CLKO_SHIFT 8
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_MASK 0x00000C00U
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_SHIFT 10
+#define EUR_CR_CLKGATECTLOVR_VDM_CLKO_MASK 0x00003000U
+#define EUR_CR_CLKGATECTLOVR_VDM_CLKO_SHIFT 12
+#define EUR_CR_CLKGATECTLOVR_PDS_CLKO_MASK 0x0000C000U
+#define EUR_CR_CLKGATECTLOVR_PDS_CLKO_SHIFT 14
+#define EUR_CR_CLKGATECTLOVR_IDXFIFO_CLKO_MASK 0x00030000U
+#define EUR_CR_CLKGATECTLOVR_IDXFIFO_CLKO_SHIFT 16
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_MASK 0x000C0000U
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_SHIFT 18
+#define EUR_CR_POWER 0x001C
+#define EUR_CR_POWER_PIPE_DISABLE_MASK 0x00000001U
+#define EUR_CR_POWER_PIPE_DISABLE_SHIFT 0
+#define EUR_CR_CORE_ID 0x0020
+#define EUR_CR_CORE_ID_CONFIG_MASK 0x0000FFFFU
+#define EUR_CR_CORE_ID_CONFIG_SHIFT 0
+#define EUR_CR_CORE_ID_ID_MASK 0xFFFF0000U
+#define EUR_CR_CORE_ID_ID_SHIFT 16
+#define EUR_CR_CORE_REVISION 0x0024
+#define EUR_CR_CORE_REVISION_MAINTENANCE_MASK 0x000000FFU
+#define EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT 0
+#define EUR_CR_CORE_REVISION_MINOR_MASK 0x0000FF00U
+#define EUR_CR_CORE_REVISION_MINOR_SHIFT 8
+#define EUR_CR_CORE_REVISION_MAJOR_MASK 0x00FF0000U
+#define EUR_CR_CORE_REVISION_MAJOR_SHIFT 16
+#define EUR_CR_CORE_REVISION_DESIGNER_MASK 0xFF000000U
+#define EUR_CR_CORE_REVISION_DESIGNER_SHIFT 24
+#define EUR_CR_DESIGNER_REV_FIELD1 0x0028
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_MASK 0xFFFFFFFFU
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SHIFT 0
+#define EUR_CR_DESIGNER_REV_FIELD2 0x002C
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_MASK 0xFFFFFFFFU
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SHIFT 0
+#define EUR_CR_SOFT_RESET 0x0080
+#define EUR_CR_SOFT_RESET_BIF_RESET_MASK 0x00000001U
+#define EUR_CR_SOFT_RESET_BIF_RESET_SHIFT 0
+#define EUR_CR_SOFT_RESET_VDM_RESET_MASK 0x00000002U
+#define EUR_CR_SOFT_RESET_VDM_RESET_SHIFT 1
+#define EUR_CR_SOFT_RESET_DPM_RESET_MASK 0x00000004U
+#define EUR_CR_SOFT_RESET_DPM_RESET_SHIFT 2
+#define EUR_CR_SOFT_RESET_TE_RESET_MASK 0x00000008U
+#define EUR_CR_SOFT_RESET_TE_RESET_SHIFT 3
+#define EUR_CR_SOFT_RESET_MTE_RESET_MASK 0x00000010U
+#define EUR_CR_SOFT_RESET_MTE_RESET_SHIFT 4
+#define EUR_CR_SOFT_RESET_ISP_RESET_MASK 0x00000020U
+#define EUR_CR_SOFT_RESET_ISP_RESET_SHIFT 5
+#define EUR_CR_SOFT_RESET_ISP2_RESET_MASK 0x00000040U
+#define EUR_CR_SOFT_RESET_ISP2_RESET_SHIFT 6
+#define EUR_CR_SOFT_RESET_TSP_RESET_MASK 0x00000080U
+#define EUR_CR_SOFT_RESET_TSP_RESET_SHIFT 7
+#define EUR_CR_SOFT_RESET_PDS_RESET_MASK 0x00000100U
+#define EUR_CR_SOFT_RESET_PDS_RESET_SHIFT 8
+#define EUR_CR_SOFT_RESET_PBE_RESET_MASK 0x00000200U
+#define EUR_CR_SOFT_RESET_PBE_RESET_SHIFT 9
+#define EUR_CR_SOFT_RESET_CACHEL2_RESET_MASK 0x00000400U
+#define EUR_CR_SOFT_RESET_CACHEL2_RESET_SHIFT 10
+#define EUR_CR_SOFT_RESET_UCACHEL2_RESET_MASK 0x00000800U
+#define EUR_CR_SOFT_RESET_UCACHEL2_RESET_SHIFT 11
+#define EUR_CR_SOFT_RESET_MADD_RESET_MASK 0x00001000U
+#define EUR_CR_SOFT_RESET_MADD_RESET_SHIFT 12
+#define EUR_CR_SOFT_RESET_ITR_RESET_MASK 0x00002000U
+#define EUR_CR_SOFT_RESET_ITR_RESET_SHIFT 13
+#define EUR_CR_SOFT_RESET_TEX_RESET_MASK 0x00004000U
+#define EUR_CR_SOFT_RESET_TEX_RESET_SHIFT 14
+#define EUR_CR_SOFT_RESET_USE_RESET_MASK 0x00008000U
+#define EUR_CR_SOFT_RESET_USE_RESET_SHIFT 15
+#define EUR_CR_SOFT_RESET_IDXFIFO_RESET_MASK 0x00010000U
+#define EUR_CR_SOFT_RESET_IDXFIFO_RESET_SHIFT 16
+#define EUR_CR_SOFT_RESET_TA_RESET_MASK 0x00020000U
+#define EUR_CR_SOFT_RESET_TA_RESET_SHIFT 17
+#define EUR_CR_EVENT_HOST_ENABLE2 0x0110
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_HOST_CLEAR2 0x0114
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_STATUS2 0x0118
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_MASK 0x00000010U
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_SHIFT 4
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_MASK 0x00000008U
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_SHIFT 3
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_MASK 0x00000004U
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_SHIFT 2
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_STATUS 0x012CU
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_STATUS_TIMER_MASK 0x20000000U
+#define EUR_CR_EVENT_STATUS_TIMER_SHIFT 29
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_STATUS_TWOD_COMPLETE_MASK 0x08000000U
+#define EUR_CR_EVENT_STATUS_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_STATUS_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_STATUS_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_STATUS_ISP_HALT_MASK 0x00020000U
+#define EUR_CR_EVENT_STATUS_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_STATUS_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_STATUS_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_HOST_ENABLE 0x0130
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_MASK 0x20000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_ENABLE_TWOD_COMPLETE_MASK 0x08000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_MASK 0x00020000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_HOST_CLEAR 0x0134
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_MASK 0x20000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_CLEAR_TWOD_COMPLETE_MASK 0x08000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_MASK 0x00020000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_TIMER 0x0144
+#define EUR_CR_TIMER_VALUE_MASK 0xFFFFFFFFU
+#define EUR_CR_TIMER_VALUE_SHIFT 0
+#define EUR_CR_EVENT_KICK1 0x0AB0
+#define EUR_CR_EVENT_KICK1_NOW_MASK 0x000000FFU
+#define EUR_CR_EVENT_KICK1_NOW_SHIFT 0
+#define EUR_CR_PDS_EXEC_BASE 0x0AB8
+#define EUR_CR_PDS_EXEC_BASE_ADDR_MASK 0x0FF00000U
+#define EUR_CR_PDS_EXEC_BASE_ADDR_SHIFT 20
+#define EUR_CR_EVENT_KICK2 0x0AC0
+#define EUR_CR_EVENT_KICK2_NOW_MASK 0x00000001U
+#define EUR_CR_EVENT_KICK2_NOW_SHIFT 0
+#define EUR_CR_EVENT_KICKER 0x0AC4
+#define EUR_CR_EVENT_KICKER_ADDRESS_MASK 0x0FFFFFF0U
+#define EUR_CR_EVENT_KICKER_ADDRESS_SHIFT 4
+#define EUR_CR_EVENT_KICK 0x0AC8
+#define EUR_CR_EVENT_KICK_NOW_MASK 0x00000001U
+#define EUR_CR_EVENT_KICK_NOW_SHIFT 0
+#define EUR_CR_EVENT_TIMER 0x0ACC
+#define EUR_CR_EVENT_TIMER_ENABLE_MASK 0x01000000U
+#define EUR_CR_EVENT_TIMER_ENABLE_SHIFT 24
+#define EUR_CR_EVENT_TIMER_VALUE_MASK 0x00FFFFFFU
+#define EUR_CR_EVENT_TIMER_VALUE_SHIFT 0
+#define EUR_CR_PDS_INV0 0x0AD0
+#define EUR_CR_PDS_INV0_DSC_MASK 0x00000001U
+#define EUR_CR_PDS_INV0_DSC_SHIFT 0
+#define EUR_CR_PDS_INV1 0x0AD4
+#define EUR_CR_PDS_INV1_DSC_MASK 0x00000001U
+#define EUR_CR_PDS_INV1_DSC_SHIFT 0
+#define EUR_CR_EVENT_KICK3 0x0AD8
+#define EUR_CR_EVENT_KICK3_NOW_MASK 0x00000001U
+#define EUR_CR_EVENT_KICK3_NOW_SHIFT 0
+#define EUR_CR_PDS_INV3 0x0ADC
+#define EUR_CR_PDS_INV3_DSC_MASK 0x00000001U
+#define EUR_CR_PDS_INV3_DSC_SHIFT 0
+#define EUR_CR_PDS_INV_CSC 0x0AE0
+#define EUR_CR_PDS_INV_CSC_KICK_MASK 0x00000001U
+#define EUR_CR_PDS_INV_CSC_KICK_SHIFT 0
+#define EUR_CR_PDS_PC_BASE 0x0B2C
+#define EUR_CR_PDS_PC_BASE_ADDRESS_MASK 0x00FFFFFFU
+#define EUR_CR_PDS_PC_BASE_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_CTRL 0x0C00
+#define EUR_CR_BIF_CTRL_NOREORDER_MASK 0x00000001U
+#define EUR_CR_BIF_CTRL_NOREORDER_SHIFT 0
+#define EUR_CR_BIF_CTRL_PAUSE_MASK 0x00000002U
+#define EUR_CR_BIF_CTRL_PAUSE_SHIFT 1
+#define EUR_CR_BIF_CTRL_FLUSH_MASK 0x00000004U
+#define EUR_CR_BIF_CTRL_FLUSH_SHIFT 2
+#define EUR_CR_BIF_CTRL_INVALDC_MASK 0x00000008U
+#define EUR_CR_BIF_CTRL_INVALDC_SHIFT 3
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_MASK 0x00000010U
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_SHIFT 4
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_MASK 0x00000100U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_SHIFT 8
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_MASK 0x00000200U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_SHIFT 9
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_MASK 0x00000400U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_SHIFT 10
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_MASK 0x00001000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_SHIFT 12
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_MASK 0x00002000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_SHIFT 13
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_MASK 0x00004000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_SHIFT 14
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_MASK 0x00008000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_SHIFT 15
+#define EUR_CR_BIF_INT_STAT 0x0C04
+#define EUR_CR_BIF_INT_STAT_FAULT_MASK 0x00003FFFU
+#define EUR_CR_BIF_INT_STAT_FAULT_SHIFT 0
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_MASK 0x00004000U
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_SHIFT 14
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_MASK 0x00008000U
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_SHIFT 15
+#define EUR_CR_BIF_FAULT 0x0C08
+#define EUR_CR_BIF_FAULT_SB_MASK 0x000001F0U
+#define EUR_CR_BIF_FAULT_SB_SHIFT 4
+#define EUR_CR_BIF_FAULT_ADDR_MASK 0x0FFFF000U
+#define EUR_CR_BIF_FAULT_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE0 0x0C84
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_SHIFT 12
+#define EUR_CR_BIF_TA_REQ_BASE 0x0C90
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_MASK 0x0FF00000U
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_SHIFT 20
+#define EUR_CR_BIF_MEM_REQ_STAT 0x0CA8
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_MASK 0x000000FFU
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_SHIFT 0
+#define EUR_CR_BIF_3D_REQ_BASE 0x0CAC
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_MASK 0x0FF00000U
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_SHIFT 20
+#define EUR_CR_BIF_ZLS_REQ_BASE 0x0CB0
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_MASK 0x0FF00000U
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_SHIFT 20
+#define EUR_CR_2D_BLIT_STATUS 0x0E04
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_MASK 0x00FFFFFFU
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_SHIFT 0
+#define EUR_CR_2D_BLIT_STATUS_BUSY_MASK 0x01000000U
+#define EUR_CR_2D_BLIT_STATUS_BUSY_SHIFT 24
+#define EUR_CR_2D_VIRTUAL_FIFO_0 0x0E10
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_MASK 0x00000001U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MASK 0x0000000EU
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_SHIFT 1
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_MASK 0x00000FF0U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_SHIFT 4
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_MASK 0x0000F000U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_SHIFT 12
+#define EUR_CR_2D_VIRTUAL_FIFO_1 0x0E14
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_MASK 0x00000FFFU
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_MASK 0x00FFF000U
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_SHIFT 12
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_MASK 0xFF000000U
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_SHIFT 24
+#define EUR_CR_USE_CODE_BASE(X) (0x0A0C + (4 * (X)))
+#define EUR_CR_USE_CODE_BASE_ADDR_MASK 0x00FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_SHIFT 0
+#define EUR_CR_USE_CODE_BASE_DM_MASK 0x03000000U
+#define EUR_CR_USE_CODE_BASE_DM_SHIFT 24
+#define EUR_CR_USE_CODE_BASE_SIZE_UINT32 16
+#define EUR_CR_USE_CODE_BASE_NUM_ENTRIES 16
+
+#endif
+
diff --git a/drivers/gpu/pvr/sgx_bridge.h b/drivers/gpu/pvr/sgx_bridge.h
new file mode 100644
index 0000000..ec630a5
--- /dev/null
+++ b/drivers/gpu/pvr/sgx_bridge.h
@@ -0,0 +1,666 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#if !defined(__SGX_BRIDGE_H__)
+#define __SGX_BRIDGE_H__
+
+#if defined (SUPPORT_SID_INTERFACE)
+#include "sgxapi.h"
+#else
+#include "sgxapi_km.h"
+#endif
+#include "sgxinfo.h"
+#include "pvr_bridge.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+
+#define PVRSRV_BRIDGE_SGX_CMD_BASE (PVRSRV_BRIDGE_LAST_NON_DEVICE_CMD+1)
+#define PVRSRV_BRIDGE_SGX_GETCLIENTINFO PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+0)
+#define PVRSRV_BRIDGE_SGX_RELEASECLIENTINFO PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+1)
+#define PVRSRV_BRIDGE_SGX_GETINTERNALDEVINFO PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+2)
+#define PVRSRV_BRIDGE_SGX_DOKICK PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+3)
+#define PVRSRV_BRIDGE_SGX_GETPHYSPAGEADDR PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+4)
+#define PVRSRV_BRIDGE_SGX_READREGISTRYDWORD PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+5)
+
+#define PVRSRV_BRIDGE_SGX_2DQUERYBLTSCOMPLETE PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+9)
+
+#if defined(TRANSFER_QUEUE)
+#define PVRSRV_BRIDGE_SGX_SUBMITTRANSFER PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+13)
+#endif
+#define PVRSRV_BRIDGE_SGX_GETMISCINFO PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+14)
+#define PVRSRV_BRIDGE_SGXINFO_FOR_SRVINIT PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+15)
+#define PVRSRV_BRIDGE_SGX_DEVINITPART2 PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+16)
+
+#define PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+17)
+#define PVRSRV_BRIDGE_SGX_UNREFSHAREDPBDESC PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+18)
+#define PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+19)
+#define PVRSRV_BRIDGE_SGX_REGISTER_HW_RENDER_CONTEXT PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+20)
+#define PVRSRV_BRIDGE_SGX_FLUSH_HW_RENDER_TARGET PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+21)
+#define PVRSRV_BRIDGE_SGX_UNREGISTER_HW_RENDER_CONTEXT PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+22)
+#if defined(SGX_FEATURE_2D_HARDWARE)
+#define PVRSRV_BRIDGE_SGX_SUBMIT2D PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+23)
+#define PVRSRV_BRIDGE_SGX_REGISTER_HW_2D_CONTEXT PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+24)
+#define PVRSRV_BRIDGE_SGX_UNREGISTER_HW_2D_CONTEXT PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+25)
+#endif
+#define PVRSRV_BRIDGE_SGX_REGISTER_HW_TRANSFER_CONTEXT PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+26)
+#define PVRSRV_BRIDGE_SGX_UNREGISTER_HW_TRANSFER_CONTEXT PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+27)
+
+#define PVRSRV_BRIDGE_SGX_SCHEDULE_PROCESS_QUEUES PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+28)
+
+#define PVRSRV_BRIDGE_SGX_READ_HWPERF_CB PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+29)
+#define PVRSRV_BRIDGE_SGX_SET_RENDER_CONTEXT_PRIORITY PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+30)
+#define PVRSRV_BRIDGE_SGX_SET_TRANSFER_CONTEXT_PRIORITY PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+31)
+
+#if defined(PDUMP)
+#define PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+32)
+#define PVRSRV_BRIDGE_SGX_PDUMP_3D_SIGNATURE_REGISTERS PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+33)
+#define PVRSRV_BRIDGE_SGX_PDUMP_COUNTER_REGISTERS PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+34)
+#define PVRSRV_BRIDGE_SGX_PDUMP_TA_SIGNATURE_REGISTERS PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+35)
+#define PVRSRV_BRIDGE_SGX_PDUMP_HWPERFCB PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+36)
+#define PVRSRV_BRIDGE_SGX_PDUMP_SAVEMEM PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+37)
+#endif
+
+
+
+#define PVRSRV_BRIDGE_LAST_SGX_CMD (PVRSRV_BRIDGE_SGX_CMD_BASE+37)
+
+
+typedef struct PVRSRV_BRIDGE_IN_GETPHYSPAGEADDR
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevMemHeap;
+ IMG_DEV_VIRTADDR sDevVAddr;
+}PVRSRV_BRIDGE_IN_GETPHYSPAGEADDR;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GETPHYSPAGEADDR
+{
+ PVRSRV_ERROR eError;
+ IMG_DEV_PHYADDR DevPAddr;
+ IMG_CPU_PHYADDR CpuPAddr;
+}PVRSRV_BRIDGE_OUT_GETPHYSPAGEADDR;
+
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_SET_TRANSFER_CONTEXT_PRIORITY_TAG
+ {
+ IMG_UINT32 ui32BridgeFlags;
+ #if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+ IMG_SID hHWTransferContext;
+ #else
+ IMG_HANDLE hDevCookie;
+ IMG_HANDLE hHWTransferContext;
+ #endif
+ IMG_UINT32 ui32Priority;
+ IMG_UINT32 ui32OffsetOfPriorityField;
+}PVRSRV_BRIDGE_IN_SGX_SET_TRANSFER_CONTEXT_PRIORITY;
+
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_SET_RENDER_CONTEXT_PRIORITY_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+ IMG_SID hHWRenderContext;
+#else
+ IMG_HANDLE hDevCookie;
+ IMG_HANDLE hHWRenderContext;
+#endif
+ IMG_UINT32 ui32Priority;
+ IMG_UINT32 ui32OffsetOfPriorityField;
+}PVRSRV_BRIDGE_IN_SGX_SET_RENDER_CONTEXT_PRIORITY;
+
+
+typedef struct PVRSRV_BRIDGE_IN_GETCLIENTINFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+}PVRSRV_BRIDGE_IN_GETCLIENTINFO;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GETINTERNALDEVINFO_TAG
+{
+ SGX_INTERNAL_DEVINFO sSGXInternalDevInfo;
+ PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_GETINTERNALDEVINFO;
+
+
+typedef struct PVRSRV_BRIDGE_IN_GETINTERNALDEVINFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+}PVRSRV_BRIDGE_IN_GETINTERNALDEVINFO;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GETCLIENTINFO_TAG
+{
+ SGX_CLIENT_INFO sClientInfo;
+ PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_GETCLIENTINFO;
+
+
+typedef struct PVRSRV_BRIDGE_IN_RELEASECLIENTINFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+ SGX_CLIENT_INFO sClientInfo;
+}PVRSRV_BRIDGE_IN_RELEASECLIENTINFO;
+
+
+typedef struct PVRSRV_BRIDGE_IN_ISPBREAKPOLL_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+}PVRSRV_BRIDGE_IN_ISPBREAKPOLL;
+
+
+typedef struct PVRSRV_BRIDGE_IN_DOKICK_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+ SGX_CCB_KICK sCCBKick;
+}PVRSRV_BRIDGE_IN_DOKICK;
+
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_SCHEDULE_PROCESS_QUEUES_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+}PVRSRV_BRIDGE_IN_SGX_SCHEDULE_PROCESS_QUEUES;
+
+
+#if defined(TRANSFER_QUEUE)
+
+typedef struct PVRSRV_BRIDGE_IN_SUBMITTRANSFER_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+ PVRSRV_TRANSFER_SGX_KICK sKick;
+}PVRSRV_BRIDGE_IN_SUBMITTRANSFER;
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+
+typedef struct PVRSRV_BRIDGE_IN_SUBMIT2D_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+ PVRSRV_2D_SGX_KICK sKick;
+} PVRSRV_BRIDGE_IN_SUBMIT2D;
+#endif
+#endif
+
+
+typedef struct PVRSRV_BRIDGE_IN_READREGDWORD_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+ IMG_PCHAR pszKey;
+ IMG_PCHAR pszValue;
+}PVRSRV_BRIDGE_IN_READREGDWORD;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_READREGDWORD_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32Data;
+}PVRSRV_BRIDGE_OUT_READREGDWORD;
+
+
+typedef struct PVRSRV_BRIDGE_IN_SGXGETMISCINFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+ SGX_MISC_INFO *psMiscInfo;
+}PVRSRV_BRIDGE_IN_SGXGETMISCINFO;
+
+typedef struct PVRSRV_BRIDGE_IN_SGXINFO_FOR_SRVINIT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+}PVRSRV_BRIDGE_IN_SGXINFO_FOR_SRVINIT;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGXINFO_FOR_SRVINIT_TAG
+{
+ PVRSRV_ERROR eError;
+ SGX_BRIDGE_INFO_FOR_SRVINIT sInitInfo;
+}PVRSRV_BRIDGE_OUT_SGXINFO_FOR_SRVINIT;
+
+typedef struct PVRSRV_BRIDGE_IN_SGXDEVINITPART2_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+ SGX_BRIDGE_INIT_INFO sInitInfo;
+}PVRSRV_BRIDGE_IN_SGXDEVINITPART2;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGXDEVINITPART2_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32KMBuildOptions;
+
+}PVRSRV_BRIDGE_OUT_SGXDEVINITPART2;
+
+
+typedef struct PVRSRV_BRIDGE_IN_2DQUERYBLTSCOMPLETE_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+ IMG_SID hKernSyncInfo;
+#else
+ IMG_HANDLE hDevCookie;
+ IMG_HANDLE hKernSyncInfo;
+#endif
+ IMG_BOOL bWaitForComplete;
+}PVRSRV_BRIDGE_IN_2DQUERYBLTSCOMPLETE;
+
+
+#define PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS 10
+
+typedef struct PVRSRV_BRIDGE_IN_SGXFINDSHAREDPBDESC_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+ IMG_BOOL bLockOnFailure;
+ IMG_UINT32 ui32TotalPBSize;
+}PVRSRV_BRIDGE_IN_SGXFINDSHAREDPBDESC;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGXFINDSHAREDPBDESC_TAG
+{
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelMemInfo;
+ IMG_SID hSharedPBDesc;
+ IMG_SID hSharedPBDescKernelMemInfoHandle;
+ IMG_SID hHWPBDescKernelMemInfoHandle;
+ IMG_SID hBlockKernelMemInfoHandle;
+ IMG_SID hHWBlockKernelMemInfoHandle;
+ IMG_SID ahSharedPBDescSubKernelMemInfoHandles[PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS];
+#else
+ IMG_HANDLE hKernelMemInfo;
+ IMG_HANDLE hSharedPBDesc;
+ IMG_HANDLE hSharedPBDescKernelMemInfoHandle;
+ IMG_HANDLE hHWPBDescKernelMemInfoHandle;
+ IMG_HANDLE hBlockKernelMemInfoHandle;
+ IMG_HANDLE hHWBlockKernelMemInfoHandle;
+ IMG_HANDLE ahSharedPBDescSubKernelMemInfoHandles[PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS];
+#endif
+ IMG_UINT32 ui32SharedPBDescSubKernelMemInfoHandlesCount;
+ PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_SGXFINDSHAREDPBDESC;
+
+typedef struct PVRSRV_BRIDGE_IN_SGXUNREFSHAREDPBDESC_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hSharedPBDesc;
+#else
+ IMG_HANDLE hSharedPBDesc;
+#endif
+}PVRSRV_BRIDGE_IN_SGXUNREFSHAREDPBDESC;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGXUNREFSHAREDPBDESC_TAG
+{
+ PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_SGXUNREFSHAREDPBDESC;
+
+
+typedef struct PVRSRV_BRIDGE_IN_SGXADDSHAREDPBDESC_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32TotalPBSize;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+ IMG_SID hSharedPBDescKernelMemInfo;
+ IMG_SID hHWPBDescKernelMemInfo;
+ IMG_SID hBlockKernelMemInfo;
+ IMG_SID hHWBlockKernelMemInfo;
+ IMG_SID *phKernelMemInfoHandles;
+#else
+ IMG_HANDLE hDevCookie;
+ IMG_HANDLE hSharedPBDescKernelMemInfo;
+ IMG_HANDLE hHWPBDescKernelMemInfo;
+ IMG_HANDLE hBlockKernelMemInfo;
+ IMG_HANDLE hHWBlockKernelMemInfo;
+ IMG_HANDLE *phKernelMemInfoHandles;
+#endif
+ IMG_UINT32 ui32KernelMemInfoHandlesCount;
+ IMG_DEV_VIRTADDR sHWPBDescDevVAddr;
+}PVRSRV_BRIDGE_IN_SGXADDSHAREDPBDESC;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGXADDSHAREDPBDESC_TAG
+{
+ PVRSRV_ERROR eError;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hSharedPBDesc;
+#else
+ IMG_HANDLE hSharedPBDesc;
+#endif
+}PVRSRV_BRIDGE_OUT_SGXADDSHAREDPBDESC;
+
+
+#ifdef PDUMP
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_BUFFER_ARRAY_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ SGX_KICKTA_DUMP_BUFFER *psBufferArray;
+ IMG_UINT32 ui32BufferArrayLength;
+ IMG_BOOL bDumpPolls;
+} PVRSRV_BRIDGE_IN_PDUMP_BUFFER_ARRAY;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_3D_SIGNATURE_REGISTERS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+ IMG_SID hDevMemContext;
+#else
+ IMG_HANDLE hDevCookie;
+ IMG_HANDLE hDevMemContext;
+#endif
+ IMG_UINT32 ui32DumpFrameNum;
+ IMG_BOOL bLastFrame;
+ IMG_UINT32 *pui32Registers;
+ IMG_UINT32 ui32NumRegisters;
+}PVRSRV_BRIDGE_IN_PDUMP_3D_SIGNATURE_REGISTERS;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMPCOUNTER_REGISTERS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+ IMG_UINT32 ui32DumpFrameNum;
+ IMG_BOOL bLastFrame;
+ IMG_UINT32 *pui32Registers;
+ IMG_UINT32 ui32NumRegisters;
+}PVRSRV_BRIDGE_IN_PDUMP_COUNTER_REGISTERS;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_TA_SIGNATURE_REGISTERS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+ IMG_UINT32 ui32DumpFrameNum;
+ IMG_UINT32 ui32TAKickCount;
+ IMG_BOOL bLastFrame;
+ IMG_UINT32 *pui32Registers;
+ IMG_UINT32 ui32NumRegisters;
+}PVRSRV_BRIDGE_IN_PDUMP_TA_SIGNATURE_REGISTERS;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_HWPERFCB_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+ IMG_SID hDevMemContext;
+#else
+ IMG_HANDLE hDevCookie;
+ IMG_HANDLE hDevMemContext;
+#endif
+ IMG_CHAR szFileName[PVRSRV_PDUMP_MAX_FILENAME_SIZE];
+ IMG_UINT32 ui32FileOffset;
+ IMG_UINT32 ui32PDumpFlags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_HWPERFCB;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_SAVEMEM
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+ IMG_SID hDevMemContext;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+ IMG_CHAR szFileName[PVRSRV_PDUMP_MAX_FILENAME_SIZE];
+ IMG_UINT32 ui32FileOffset;
+ IMG_DEV_VIRTADDR sDevVAddr;
+ IMG_UINT32 ui32Size;
+#if !defined (SUPPORT_SID_INTERFACE)
+ IMG_HANDLE hDevMemContext;
+#endif
+ IMG_UINT32 ui32PDumpFlags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_SAVEMEM;
+
+#endif
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_RENDER_CONTEXT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+ IMG_CPU_VIRTADDR pHWRenderContextCpuVAddr;
+ IMG_UINT32 ui32HWRenderContextSize;
+ IMG_UINT32 ui32OffsetToPDDevPAddr;
+ IMG_HANDLE hDevMemContext;
+}PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_RENDER_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_RENDER_CONTEXT_TAG
+{
+ PVRSRV_ERROR eError;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hHWRenderContext;
+#else
+ IMG_HANDLE hHWRenderContext;
+#endif
+ IMG_DEV_VIRTADDR sHWRenderContextDevVAddr;
+}PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_RENDER_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_RENDER_CONTEXT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_BOOL bForceCleanup;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+ IMG_SID hHWRenderContext;
+#else
+ IMG_HANDLE hDevCookie;
+ IMG_HANDLE hHWRenderContext;
+#endif
+}PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_RENDER_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_TRANSFER_CONTEXT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+ IMG_CPU_VIRTADDR pHWTransferContextCpuVAddr;
+ IMG_UINT32 ui32HWTransferContextSize;
+ IMG_UINT32 ui32OffsetToPDDevPAddr;
+ IMG_HANDLE hDevMemContext;
+}PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_TRANSFER_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_TRANSFER_CONTEXT_TAG
+{
+ PVRSRV_ERROR eError;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hHWTransferContext;
+#else
+ IMG_HANDLE hHWTransferContext;
+#endif
+ IMG_DEV_VIRTADDR sHWTransferContextDevVAddr;
+}PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_TRANSFER_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_TRANSFER_CONTEXT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_BOOL bForceCleanup;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+ IMG_SID hHWTransferContext;
+#else
+ IMG_HANDLE hDevCookie;
+ IMG_HANDLE hHWTransferContext;
+#endif
+}PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_TRANSFER_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_FLUSH_HW_RENDER_TARGET_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+ IMG_DEV_VIRTADDR sHWRTDataSetDevVAddr;
+}PVRSRV_BRIDGE_IN_SGX_FLUSH_HW_RENDER_TARGET;
+
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+typedef struct PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_2D_CONTEXT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+ IMG_CPU_VIRTADDR pHW2DContextCpuVAddr;
+ IMG_UINT32 ui32HW2DContextSize;
+ IMG_UINT32 ui32OffsetToPDDevPAddr;
+ IMG_HANDLE hDevMemContext;
+}PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_2D_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_2D_CONTEXT_TAG
+{
+ PVRSRV_ERROR eError;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hHW2DContext;
+#else
+ IMG_HANDLE hHW2DContext;
+#endif
+ IMG_DEV_VIRTADDR sHW2DContextDevVAddr;
+}PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_2D_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_2D_CONTEXT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_BOOL bForceCleanup;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+ IMG_SID hHW2DContext;
+#else
+ IMG_HANDLE hDevCookie;
+ IMG_HANDLE hHW2DContext;
+#endif
+}PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_2D_CONTEXT;
+
+#define SGX2D_MAX_BLT_CMD_SIZ 256
+#endif
+
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_READ_HWPERF_CB_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hDevCookie;
+#else
+ IMG_HANDLE hDevCookie;
+#endif
+ IMG_UINT32 ui32ArraySize;
+ PVRSRV_SGX_HWPERF_CB_ENTRY *psHWPerfCBData;
+} PVRSRV_BRIDGE_IN_SGX_READ_HWPERF_CB;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGX_READ_HWPERF_CB_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32DataCount;
+ IMG_UINT32 ui32ClockSpeed;
+ IMG_UINT32 ui32HostTimeStamp;
+} PVRSRV_BRIDGE_OUT_SGX_READ_HWPERF_CB;
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/gpu/pvr/sgx_mkif_km.h b/drivers/gpu/pvr/sgx_mkif_km.h
new file mode 100644
index 0000000..9f4f41f
--- /dev/null
+++ b/drivers/gpu/pvr/sgx_mkif_km.h
@@ -0,0 +1,349 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#if !defined (__SGX_MKIF_KM_H__)
+#define __SGX_MKIF_KM_H__
+
+#include "img_types.h"
+#include "servicesint.h"
+#include "sgxapi_km.h"
+
+
+#if !defined (SGX_MP_CORE_SELECT)
+#if defined(SGX_FEATURE_MP)
+ #define SGX_REG_BANK_SHIFT (14)
+ #define SGX_REG_BANK_SIZE (1 << SGX_REG_BANK_SHIFT)
+ #define SGX_REG_BANK_BASE_INDEX (2)
+ #define SGX_REG_BANK_MASTER_INDEX (1)
+ #define SGX_MP_CORE_SELECT(x,i) (x + ((i + SGX_REG_BANK_BASE_INDEX) * SGX_REG_BANK_SIZE))
+ #define SGX_MP_MASTER_SELECT(x) (x + (SGX_REG_BANK_MASTER_INDEX * SGX_REG_BANK_SIZE))
+#else
+ #define SGX_MP_CORE_SELECT(x,i) (x)
+#endif
+#endif
+
+
+typedef struct _SGXMKIF_COMMAND_
+{
+ IMG_UINT32 ui32ServiceAddress;
+ IMG_UINT32 ui32CacheControl;
+ IMG_UINT32 ui32Data[6];
+} SGXMKIF_COMMAND;
+
+
+typedef struct _PVRSRV_SGX_KERNEL_CCB_
+{
+ SGXMKIF_COMMAND asCommands[256];
+} PVRSRV_SGX_KERNEL_CCB;
+
+
+typedef struct _PVRSRV_SGX_CCB_CTL_
+{
+ IMG_UINT32 ui32WriteOffset;
+ IMG_UINT32 ui32ReadOffset;
+} PVRSRV_SGX_CCB_CTL;
+
+
+typedef struct _SGXMKIF_HOST_CTL_
+{
+#if defined(PVRSRV_USSE_EDM_BREAKPOINTS)
+ IMG_UINT32 ui32BreakpointDisable;
+ IMG_UINT32 ui32Continue;
+#endif
+
+ volatile IMG_UINT32 ui32InitStatus;
+ volatile IMG_UINT32 ui32PowerStatus;
+ volatile IMG_UINT32 ui32CleanupStatus;
+#if defined(FIX_HW_BRN_28889)
+ volatile IMG_UINT32 ui32InvalStatus;
+#endif
+#if defined(SUPPORT_HW_RECOVERY)
+ IMG_UINT32 ui32uKernelDetectedLockups;
+ IMG_UINT32 ui32HostDetectedLockups;
+ IMG_UINT32 ui32HWRecoverySampleRate;
+#endif
+ IMG_UINT32 ui32uKernelTimerClock;
+ IMG_UINT32 ui32ActivePowManSampleRate;
+ IMG_UINT32 ui32InterruptFlags;
+ IMG_UINT32 ui32InterruptClearFlags;
+ IMG_UINT32 ui32BPSetClearSignal;
+
+ IMG_UINT32 ui32NumActivePowerEvents;
+
+ IMG_UINT32 ui32TimeWraps;
+ IMG_UINT32 ui32HostClock;
+ IMG_UINT32 ui32AssertFail;
+
+#if defined(SGX_FEATURE_EXTENDED_PERF_COUNTERS)
+ IMG_UINT32 aui32PerfGroup[PVRSRV_SGX_HWPERF_NUM_COUNTERS];
+ IMG_UINT32 aui32PerfBit[PVRSRV_SGX_HWPERF_NUM_COUNTERS];
+#else
+ IMG_UINT32 ui32PerfGroup;
+#endif
+
+#if defined(FIX_HW_BRN_31939)
+ IMG_UINT32 ui32BRN31939Mem;
+#endif
+
+ IMG_UINT32 ui32OpenCLDelayCount;
+} SGXMKIF_HOST_CTL;
+
+#define SGXMKIF_CMDTA_CTRLFLAGS_READY 0x00000001
+typedef struct _SGXMKIF_CMDTA_SHARED_
+{
+ IMG_UINT32 ui32CtrlFlags;
+
+ IMG_UINT32 ui32NumTAStatusVals;
+ IMG_UINT32 ui32Num3DStatusVals;
+
+
+ IMG_UINT32 ui32TATQSyncWriteOpsPendingVal;
+ IMG_DEV_VIRTADDR sTATQSyncWriteOpsCompleteDevVAddr;
+ IMG_UINT32 ui32TATQSyncReadOpsPendingVal;
+ IMG_DEV_VIRTADDR sTATQSyncReadOpsCompleteDevVAddr;
+
+
+ IMG_UINT32 ui323DTQSyncWriteOpsPendingVal;
+ IMG_DEV_VIRTADDR s3DTQSyncWriteOpsCompleteDevVAddr;
+ IMG_UINT32 ui323DTQSyncReadOpsPendingVal;
+ IMG_DEV_VIRTADDR s3DTQSyncReadOpsCompleteDevVAddr;
+
+
+ PVRSRV_DEVICE_SYNC_OBJECT sTA3DDependency;
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+
+ IMG_UINT32 ui32NumTASrcSyncs;
+ PVRSRV_DEVICE_SYNC_OBJECT asTASrcSyncs[SGX_MAX_TA_SRC_SYNCS];
+ IMG_UINT32 ui32NumTADstSyncs;
+ PVRSRV_DEVICE_SYNC_OBJECT asTADstSyncs[SGX_MAX_TA_DST_SYNCS];
+ IMG_UINT32 ui32Num3DSrcSyncs;
+ PVRSRV_DEVICE_SYNC_OBJECT as3DSrcSyncs[SGX_MAX_3D_SRC_SYNCS];
+#else
+
+ IMG_UINT32 ui32NumSrcSyncs;
+ PVRSRV_DEVICE_SYNC_OBJECT asSrcSyncs[SGX_MAX_SRC_SYNCS_TA];
+#endif
+
+ CTL_STATUS sCtlTAStatusInfo[SGX_MAX_TA_STATUS_VALS];
+ CTL_STATUS sCtl3DStatusInfo[SGX_MAX_3D_STATUS_VALS];
+
+} SGXMKIF_CMDTA_SHARED;
+
+#define SGXTQ_MAX_STATUS SGX_MAX_TRANSFER_STATUS_VALS + 2
+
+#define SGXMKIF_TQFLAGS_NOSYNCUPDATE 0x00000001
+#define SGXMKIF_TQFLAGS_KEEPPENDING 0x00000002
+#define SGXMKIF_TQFLAGS_TATQ_SYNC 0x00000004
+#define SGXMKIF_TQFLAGS_3DTQ_SYNC 0x00000008
+#if defined(SGX_FEATURE_FAST_RENDER_CONTEXT_SWITCH)
+#define SGXMKIF_TQFLAGS_CTXSWITCH 0x00000010
+#endif
+#define SGXMKIF_TQFLAGS_DUMMYTRANSFER 0x00000020
+
+typedef struct _SGXMKIF_TRANSFERCMD_SHARED_
+{
+
+
+ IMG_UINT32 ui32NumSrcSyncs;
+ PVRSRV_DEVICE_SYNC_OBJECT asSrcSyncs[SGX_MAX_SRC_SYNCS_TQ];
+
+
+ IMG_UINT32 ui32NumDstSyncs;
+ PVRSRV_DEVICE_SYNC_OBJECT asDstSyncs[SGX_MAX_DST_SYNCS_TQ];
+
+ IMG_UINT32 ui32TASyncWriteOpsPendingVal;
+ IMG_DEV_VIRTADDR sTASyncWriteOpsCompleteDevVAddr;
+ IMG_UINT32 ui32TASyncReadOpsPendingVal;
+ IMG_DEV_VIRTADDR sTASyncReadOpsCompleteDevVAddr;
+
+
+ IMG_UINT32 ui323DSyncWriteOpsPendingVal;
+ IMG_DEV_VIRTADDR s3DSyncWriteOpsCompleteDevVAddr;
+ IMG_UINT32 ui323DSyncReadOpsPendingVal;
+ IMG_DEV_VIRTADDR s3DSyncReadOpsCompleteDevVAddr;
+
+ IMG_UINT32 ui32NumStatusVals;
+ CTL_STATUS sCtlStatusInfo[SGXTQ_MAX_STATUS];
+} SGXMKIF_TRANSFERCMD_SHARED, *PSGXMKIF_TRANSFERCMD_SHARED;
+
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+typedef struct _SGXMKIF_2DCMD_SHARED_ {
+
+ IMG_UINT32 ui32NumSrcSync;
+ PVRSRV_DEVICE_SYNC_OBJECT sSrcSyncData[SGX_MAX_2D_SRC_SYNC_OPS];
+
+
+ PVRSRV_DEVICE_SYNC_OBJECT sDstSyncData;
+
+
+ PVRSRV_DEVICE_SYNC_OBJECT sTASyncData;
+
+
+ PVRSRV_DEVICE_SYNC_OBJECT s3DSyncData;
+} SGXMKIF_2DCMD_SHARED, *PSGXMKIF_2DCMD_SHARED;
+#endif
+
+
+typedef struct _SGXMKIF_HWDEVICE_SYNC_LIST_
+{
+ IMG_DEV_VIRTADDR sAccessDevAddr;
+ IMG_UINT32 ui32NumSyncObjects;
+
+ PVRSRV_DEVICE_SYNC_OBJECT asSyncData[1];
+} SGXMKIF_HWDEVICE_SYNC_LIST, *PSGXMKIF_HWDEVICE_SYNC_LIST;
+
+
+#define PVRSRV_USSE_EDM_INIT_COMPLETE (1UL << 0)
+
+#define PVRSRV_USSE_EDM_POWMAN_IDLE_COMPLETE (1UL << 2)
+#define PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE (1UL << 3)
+#define PVRSRV_USSE_EDM_POWMAN_POWEROFF_RESTART_IMMEDIATE (1UL << 4)
+#define PVRSRV_USSE_EDM_POWMAN_NO_WORK (1UL << 5)
+
+#define PVRSRV_USSE_EDM_INTERRUPT_HWR (1UL << 0)
+#define PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER (1UL << 1)
+#define PVRSRV_USSE_EDM_INTERRUPT_IDLE (1UL << 2)
+
+#define PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE (1UL << 0)
+#define PVRSRV_USSE_EDM_CLEANUPCMD_BUSY (1UL << 1)
+#define PVRSRV_USSE_EDM_CLEANUPCMD_DONE (1UL << 2)
+
+#if defined(FIX_HW_BRN_28889)
+#define PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE (1UL << 0)
+#endif
+
+#define PVRSRV_USSE_MISCINFO_READY 0x1UL
+#define PVRSRV_USSE_MISCINFO_GET_STRUCT_SIZES 0x2UL
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+#define PVRSRV_USSE_MISCINFO_MEMREAD 0x4UL
+#define PVRSRV_USSE_MISCINFO_MEMWRITE 0x8UL
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+#define PVRSRV_USSE_MISCINFO_MEMREAD_FAIL 0x1UL << 31
+#endif
+#endif
+
+
+#define PVRSRV_CLEANUPCMD_RT 0x1U
+#define PVRSRV_CLEANUPCMD_RC 0x2U
+#define PVRSRV_CLEANUPCMD_TC 0x3U
+#define PVRSRV_CLEANUPCMD_2DC 0x4U
+#define PVRSRV_CLEANUPCMD_PB 0x5U
+
+#define PVRSRV_POWERCMD_POWEROFF 0x1U
+#define PVRSRV_POWERCMD_IDLE 0x2U
+#define PVRSRV_POWERCMD_RESUME 0x3U
+
+#define PVRSRV_CTXSUSPCMD_SUSPEND 0x1U
+#define PVRSRV_CTXSUSPCMD_RESUME 0x2U
+
+
+#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+#define SGX_BIF_DIR_LIST_INDEX_EDM (SGX_FEATURE_BIF_NUM_DIRLISTS - 1)
+#else
+#define SGX_BIF_DIR_LIST_INDEX_EDM (0)
+#endif
+
+#define SGXMKIF_CC_INVAL_BIF_PT 0x1
+#define SGXMKIF_CC_INVAL_BIF_PD 0x2
+#define SGXMKIF_CC_INVAL_BIF_SL 0x4
+#define SGXMKIF_CC_INVAL_DATA 0x8
+
+
+typedef struct _SGX_MISCINFO_STRUCT_SIZES_
+{
+#if defined (SGX_FEATURE_2D_HARDWARE)
+ IMG_UINT32 ui32Sizeof_2DCMD;
+ IMG_UINT32 ui32Sizeof_2DCMD_SHARED;
+#endif
+ IMG_UINT32 ui32Sizeof_CMDTA;
+ IMG_UINT32 ui32Sizeof_CMDTA_SHARED;
+ IMG_UINT32 ui32Sizeof_TRANSFERCMD;
+ IMG_UINT32 ui32Sizeof_TRANSFERCMD_SHARED;
+ IMG_UINT32 ui32Sizeof_3DREGISTERS;
+ IMG_UINT32 ui32Sizeof_HWPBDESC;
+ IMG_UINT32 ui32Sizeof_HWRENDERCONTEXT;
+ IMG_UINT32 ui32Sizeof_HWRENDERDETAILS;
+ IMG_UINT32 ui32Sizeof_HWRTDATA;
+ IMG_UINT32 ui32Sizeof_HWRTDATASET;
+ IMG_UINT32 ui32Sizeof_HWTRANSFERCONTEXT;
+ IMG_UINT32 ui32Sizeof_HOST_CTL;
+ IMG_UINT32 ui32Sizeof_COMMAND;
+} SGX_MISCINFO_STRUCT_SIZES;
+
+
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+typedef struct _PVRSRV_SGX_MISCINFO_MEMACCESS
+{
+ IMG_DEV_VIRTADDR sDevVAddr;
+ IMG_DEV_PHYADDR sPDDevPAddr;
+} PVRSRV_SGX_MISCINFO_MEMACCESS;
+#endif
+
+typedef struct _PVRSRV_SGX_MISCINFO_INFO
+{
+ IMG_UINT32 ui32MiscInfoFlags;
+ PVRSRV_SGX_MISCINFO_FEATURES sSGXFeatures;
+ SGX_MISCINFO_STRUCT_SIZES sSGXStructSizes;
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+ PVRSRV_SGX_MISCINFO_MEMACCESS sSGXMemAccessSrc;
+ PVRSRV_SGX_MISCINFO_MEMACCESS sSGXMemAccessDest;
+#endif
+} PVRSRV_SGX_MISCINFO_INFO;
+
+#ifdef PVRSRV_USSE_EDM_STATUS_DEBUG
+#define SGXMK_TRACE_BUFFER_SIZE 512
+#endif
+
+#define SGXMKIF_HWPERF_CB_SIZE 0x100
+
+typedef struct _SGXMKIF_HWPERF_CB_ENTRY_
+{
+ IMG_UINT32 ui32FrameNo;
+ IMG_UINT32 ui32PID;
+ IMG_UINT32 ui32RTData;
+ IMG_UINT32 ui32Type;
+ IMG_UINT32 ui32Ordinal;
+ IMG_UINT32 ui32Info;
+ IMG_UINT32 ui32TimeWraps;
+ IMG_UINT32 ui32Time;
+
+ IMG_UINT32 ui32Counters[SGX_FEATURE_MP_CORE_COUNT_3D][PVRSRV_SGX_HWPERF_NUM_COUNTERS];
+ IMG_UINT32 ui32MiscCounters[SGX_FEATURE_MP_CORE_COUNT_3D][PVRSRV_SGX_HWPERF_NUM_MISC_COUNTERS];
+} SGXMKIF_HWPERF_CB_ENTRY;
+
+typedef struct _SGXMKIF_HWPERF_CB_
+{
+ IMG_UINT32 ui32Woff;
+ IMG_UINT32 ui32Roff;
+ IMG_UINT32 ui32Ordinal;
+ SGXMKIF_HWPERF_CB_ENTRY psHWPerfCBData[SGXMKIF_HWPERF_CB_SIZE];
+} SGXMKIF_HWPERF_CB;
+
+
+#endif
+
diff --git a/drivers/gpu/pvr/sgx_options.h b/drivers/gpu/pvr/sgx_options.h
new file mode 100644
index 0000000..c70d1eb
--- /dev/null
+++ b/drivers/gpu/pvr/sgx_options.h
@@ -0,0 +1,254 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+******************************************************************************/
+
+/* Each build option listed here is packed into a dword which
+ * provides up to 32 flags (or up to 28 flags plus a numeric
+ * value in the range 0-15 which corresponds to the number of
+ * cores minus one if SGX_FEATURE_MP is defined). The corresponding
+ * bit is set if the build option was enabled at compile time.
+ *
+ * In order to extract the enabled build flags the INTERNAL_TEST
+ * switch should be enabled in a client program which includes this
+ * header. Then the client can test specific build flags by reading
+ * the bit value at ##OPTIONNAME##_SET_OFFSET in SGX_BUILD_OPTIONS.
+ *
+ * IMPORTANT: add new options to unused bits or define a new dword
+ * (e.g. SGX_BUILD_OPTIONS2) so that the bitfield remains backwards
+ * compatible.
+ */
+
+
+#if defined(DEBUG) || defined (INTERNAL_TEST)
+#define DEBUG_SET_OFFSET OPTIONS_BIT0
+#define OPTIONS_BIT0 0x1U
+#else
+#define OPTIONS_BIT0 0x0
+#endif /* DEBUG */
+
+#if defined(PDUMP) || defined (INTERNAL_TEST)
+#define PDUMP_SET_OFFSET OPTIONS_BIT1
+#define OPTIONS_BIT1 (0x1U << 1)
+#else
+#define OPTIONS_BIT1 0x0
+#endif /* PDUMP */
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG) || defined (INTERNAL_TEST)
+#define PVRSRV_USSE_EDM_STATUS_DEBUG_SET_OFFSET OPTIONS_BIT2
+#define OPTIONS_BIT2 (0x1U << 2)
+#else
+#define OPTIONS_BIT2 0x0
+#endif /* PVRSRV_USSE_EDM_STATUS_DEBUG */
+
+#if defined(SUPPORT_HW_RECOVERY) || defined (INTERNAL_TEST)
+#define SUPPORT_HW_RECOVERY_SET_OFFSET OPTIONS_BIT3
+#define OPTIONS_BIT3 (0x1U << 3)
+#else
+#define OPTIONS_BIT3 0x0
+#endif /* SUPPORT_HW_RECOVERY */
+
+
+
+#if defined (SUPPORT_SID_INTERFACE)
+#define PVR_SECURE_HANDLES_SET_OFFSET OPTIONS_BIT4
+#define OPTIONS_BIT4 (0x1U << 4)
+#else
+#if defined(PVR_SECURE_HANDLES) || defined (INTERNAL_TEST)
+#define PVR_SECURE_HANDLES_SET_OFFSET OPTIONS_BIT4
+#define OPTIONS_BIT4 (0x1U << 4)
+#else
+#define OPTIONS_BIT4 0x0
+#endif /* PVR_SECURE_HANDLES */
+#endif
+
+#if defined(SGX_BYPASS_SYSTEM_CACHE) || defined (INTERNAL_TEST)
+#define SGX_BYPASS_SYSTEM_CACHE_SET_OFFSET OPTIONS_BIT5
+#define OPTIONS_BIT5 (0x1U << 5)
+#else
+#define OPTIONS_BIT5 0x0
+#endif /* SGX_BYPASS_SYSTEM_CACHE */
+
+#if defined(SGX_DMS_AGE_ENABLE) || defined (INTERNAL_TEST)
+#define SGX_DMS_AGE_ENABLE_SET_OFFSET OPTIONS_BIT6
+#define OPTIONS_BIT6 (0x1U << 6)
+#else
+#define OPTIONS_BIT6 0x0
+#endif /* SGX_DMS_AGE_ENABLE */
+
+#if defined(SGX_FAST_DPM_INIT) || defined (INTERNAL_TEST)
+#define SGX_FAST_DPM_INIT_SET_OFFSET OPTIONS_BIT8
+#define OPTIONS_BIT8 (0x1U << 8)
+#else
+#define OPTIONS_BIT8 0x0
+#endif /* SGX_FAST_DPM_INIT */
+
+#if defined(SGX_FEATURE_WRITEBACK_DCU) || defined (INTERNAL_TEST)
+#define SGX_FEATURE_DCU_SET_OFFSET OPTIONS_BIT9
+#define OPTIONS_BIT9 (0x1U << 9)
+#else
+#define OPTIONS_BIT9 0x0
+#endif /* SGX_FEATURE_WRITEBACK_DCU */
+
+#if defined(SGX_FEATURE_MP) || defined (INTERNAL_TEST)
+#define SGX_FEATURE_MP_SET_OFFSET OPTIONS_BIT10
+#define OPTIONS_BIT10 (0x1U << 10)
+#else
+#define OPTIONS_BIT10 0x0
+#endif /* SGX_FEATURE_MP */
+
+#if defined(SGX_FEATURE_MULTITHREADED_UKERNEL) || defined (INTERNAL_TEST)
+#define SGX_FEATURE_MULTITHREADED_UKERNEL_SET_OFFSET OPTIONS_BIT11
+#define OPTIONS_BIT11 (0x1U << 11)
+#else
+#define OPTIONS_BIT11 0x0
+#endif /* SGX_FEATURE_MULTITHREADED_UKERNEL */
+
+
+
+#if defined(SGX_FEATURE_OVERLAPPED_SPM) || defined (INTERNAL_TEST)
+#define SGX_FEATURE_OVERLAPPED_SPM_SET_OFFSET OPTIONS_BIT12
+#define OPTIONS_BIT12 (0x1U << 12)
+#else
+#define OPTIONS_BIT12 0x0
+#endif /* SGX_FEATURE_RENDER_TARGET_ARRAYS */
+
+
+#if defined(SGX_FEATURE_SYSTEM_CACHE) || defined (INTERNAL_TEST)
+#define SGX_FEATURE_SYSTEM_CACHE_SET_OFFSET OPTIONS_BIT13
+#define OPTIONS_BIT13 (0x1U << 13)
+#else
+#define OPTIONS_BIT13 0x0
+#endif /* SGX_FEATURE_SYSTEM_CACHE */
+
+#if defined(SGX_SUPPORT_HWPROFILING) || defined (INTERNAL_TEST)
+#define SGX_SUPPORT_HWPROFILING_SET_OFFSET OPTIONS_BIT14
+#define OPTIONS_BIT14 (0x1U << 14)
+#else
+#define OPTIONS_BIT14 0x0
+#endif /* SGX_SUPPORT_HWPROFILING */
+
+
+
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT) || defined (INTERNAL_TEST)
+#define SUPPORT_ACTIVE_POWER_MANAGEMENT_SET_OFFSET OPTIONS_BIT15
+#define OPTIONS_BIT15 (0x1U << 15)
+#else
+#define OPTIONS_BIT15 0x0
+#endif /* SUPPORT_ACTIVE_POWER_MANAGEMENT */
+
+#if defined(SUPPORT_DISPLAYCONTROLLER_TILING) || defined (INTERNAL_TEST)
+#define SUPPORT_DISPLAYCONTROLLER_TILING_SET_OFFSET OPTIONS_BIT16
+#define OPTIONS_BIT16 (0x1U << 16)
+#else
+#define OPTIONS_BIT16 0x0
+#endif /* SUPPORT_DISPLAYCONTROLLER_TILING */
+
+#if defined(SUPPORT_PERCONTEXT_PB) || defined (INTERNAL_TEST)
+#define SUPPORT_PERCONTEXT_PB_SET_OFFSET OPTIONS_BIT17
+#define OPTIONS_BIT17 (0x1U << 17)
+#else
+#define OPTIONS_BIT17 0x0
+#endif /* SUPPORT_PERCONTEXT_PB */
+
+#if defined(SUPPORT_SGX_HWPERF) || defined (INTERNAL_TEST)
+#define SUPPORT_SGX_HWPERF_SET_OFFSET OPTIONS_BIT18
+#define OPTIONS_BIT18 (0x1U << 18)
+#else
+#define OPTIONS_BIT18 0x0
+#endif /* SUPPORT_SGX_HWPERF */
+
+
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE) || defined (INTERNAL_TEST)
+#define SUPPORT_SGX_MMU_DUMMY_PAGE_SET_OFFSET OPTIONS_BIT19
+#define OPTIONS_BIT19 (0x1U << 19)
+#else
+#define OPTIONS_BIT19 0x0
+#endif /* SUPPORT_SGX_MMU_DUMMY_PAGE */
+
+#if defined(SUPPORT_SGX_PRIORITY_SCHEDULING) || defined (INTERNAL_TEST)
+#define SUPPORT_SGX_PRIORITY_SCHEDULING_SET_OFFSET OPTIONS_BIT20
+#define OPTIONS_BIT20 (0x1U << 20)
+#else
+#define OPTIONS_BIT20 0x0
+#endif /* SUPPORT_SGX_PRIORITY_SCHEDULING */
+
+#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) || defined (INTERNAL_TEST)
+#define SUPPORT_SGX_LOW_LATENCY_SCHEDULING_SET_OFFSET OPTIONS_BIT21
+#define OPTIONS_BIT21 (0x1U << 21)
+#else
+#define OPTIONS_BIT21 0x0
+#endif /* SUPPORT_SGX_LOW_LATENCY_SCHEDULING */
+
+#if defined(USE_SUPPORT_NO_TA3D_OVERLAP) || defined (INTERNAL_TEST)
+#define USE_SUPPORT_NO_TA3D_OVERLAP_SET_OFFSET OPTIONS_BIT22
+#define OPTIONS_BIT22 (0x1U << 22)
+#else
+#define OPTIONS_BIT22 0x0
+#endif /* USE_SUPPORT_NO_TA3D_OVERLAP */
+
+#if defined(SGX_FEATURE_MP) || defined (INTERNAL_TEST)
+#if defined(SGX_FEATURE_MP_CORE_COUNT)
+#define OPTIONS_HIGHBYTE ((SGX_FEATURE_MP_CORE_COUNT-1) << SGX_FEATURE_MP_CORE_COUNT_SET_OFFSET)
+#define SGX_FEATURE_MP_CORE_COUNT_SET_OFFSET 28UL
+#define SGX_FEATURE_MP_CORE_COUNT_SET_MASK 0xFF
+#else
+#define OPTIONS_HIGHBYTE (((SGX_FEATURE_MP_CORE_COUNT_TA-1) << SGX_FEATURE_MP_CORE_COUNT_SET_OFFSET) |\
+ ((SGX_FEATURE_MP_CORE_COUNT_3D-1) << SGX_FEATURE_MP_CORE_COUNT_SET_OFFSET_3D))
+#define SGX_FEATURE_MP_CORE_COUNT_SET_OFFSET 24UL
+#define SGX_FEATURE_MP_CORE_COUNT_SET_OFFSET_3D 28UL
+#define SGX_FEATURE_MP_CORE_COUNT_SET_MASK 0xFF
+#endif
+#else /* SGX_FEATURE_MP */
+#define OPTIONS_HIGHBYTE 0x0
+#endif /* SGX_FEATURE_MP */
+
+
+
+#define SGX_BUILD_OPTIONS \
+ OPTIONS_BIT0 |\
+ OPTIONS_BIT1 |\
+ OPTIONS_BIT2 |\
+ OPTIONS_BIT3 |\
+ OPTIONS_BIT4 |\
+ OPTIONS_BIT5 |\
+ OPTIONS_BIT6 |\
+ OPTIONS_BIT8 |\
+ OPTIONS_BIT9 |\
+ OPTIONS_BIT10 |\
+ OPTIONS_BIT11 |\
+ OPTIONS_BIT12 |\
+ OPTIONS_BIT13 |\
+ OPTIONS_BIT14 |\
+ OPTIONS_BIT15 |\
+ OPTIONS_BIT16 |\
+ OPTIONS_BIT17 |\
+ OPTIONS_BIT18 |\
+ OPTIONS_BIT19 |\
+ OPTIONS_BIT20 |\
+ OPTIONS_BIT21 |\
+ OPTIONS_BIT22 |\
+ OPTIONS_HIGHBYTE
+
diff --git a/drivers/gpu/pvr/sgx_ukernel_status_codes.h b/drivers/gpu/pvr/sgx_ukernel_status_codes.h
new file mode 100644
index 0000000..4a9eaf8
--- /dev/null
+++ b/drivers/gpu/pvr/sgx_ukernel_status_codes.h
@@ -0,0 +1,940 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+
+******************************************************************************/
+
+#ifndef __SGX_UKERNEL_STATUS_CODES_H__
+#define __SGX_UKERNEL_STATUS_CODES_H__
+
+/*
+ NOTE: Do not add any conditional macros to this file! There must be
+ no use of #if defined(). This file is included in srvkm to print
+ stringified ukernel status codes, it must build identically to
+ srvinit.
+*/
+
+/*
+ Users of this header might define this macro to do something
+ clever; the primary use right now is to generate a switch/case
+ LUT for debugging in srvkm. If you add a new code, make sure it
+ has a corresponding MKTC_ST.
+*/
+#ifndef MKTC_ST
+#define MKTC_ST(x)
+#endif
+
+/*
+ It would be nice to put these definitions into an enumeration, but USEASM
+ only has access to the C preprocessor so macros are required.
+*/
+
+/*
+ Bits 24-31 of these codes (0xAD) are a magic number used to help
+ distinguish between them and other debug information which can be
+ optionally dumped into the status buffer, e.g. sync object values.
+*/
+
+/*
+ Microkernel trace codes
+*/
+#define MKTC_EHEVENT_3DMEMFREE 0xAD000001
+MKTC_ST(MKTC_EHEVENT_3DMEMFREE)
+#define MKTC_EHEVENT_PIXELENDRENDER 0xAD000002
+MKTC_ST(MKTC_EHEVENT_PIXELENDRENDER)
+#define MKTC_EHEVENT_ISPBREAKPOINT 0xAD000004
+MKTC_ST(MKTC_EHEVENT_ISPBREAKPOINT)
+#define MKTC_EHEVENT_TAFINISHED 0xAD000005
+MKTC_ST(MKTC_EHEVENT_TAFINISHED)
+#define MKTC_EHEVENT_OUTOFMEM 0xAD000007
+MKTC_ST(MKTC_EHEVENT_OUTOFMEM)
+#define MKTC_EHEVENT_TATERMINATE 0xAD000008
+MKTC_ST(MKTC_EHEVENT_TATERMINATE)
+#define MKTC_EHEVENT_TIMER 0xAD000009
+MKTC_ST(MKTC_EHEVENT_TIMER)
+#define MKTC_EHEVENT_SWEVENT 0xAD00000A
+MKTC_ST(MKTC_EHEVENT_SWEVENT)
+#define MKTC_EHEVENT_2DCOMPLETE 0xAD00000B
+MKTC_ST(MKTC_EHEVENT_2DCOMPLETE)
+
+#define MKTC_3DEVENT_3DMEMFREE 0xAD000100
+MKTC_ST(MKTC_3DEVENT_3DMEMFREE)
+#define MKTC_3DEVENT_PIXELENDRENDER 0xAD000101
+MKTC_ST(MKTC_3DEVENT_PIXELENDRENDER)
+#define MKTC_3DEVENT_ISPBREAKPOINT 0xAD000102
+MKTC_ST(MKTC_3DEVENT_ISPBREAKPOINT)
+#define MKTC_3DEVENT_END 0xAD000104
+MKTC_ST(MKTC_3DEVENT_END)
+#define MKTC_3DLB_3DMEMFREE 0xAD000180
+MKTC_ST(MKTC_3DLB_3DMEMFREE)
+#define MKTC_3DLB_PIXELENDRENDER 0xAD000181
+MKTC_ST(MKTC_3DLB_PIXELENDRENDER)
+#define MKTC_3DLB_ISPBREAKPOINT 0xAD000182
+MKTC_ST(MKTC_3DLB_ISPBREAKPOINT)
+#define MKTC_3DLB_FIND3D 0xAD000183
+MKTC_ST(MKTC_3DLB_FIND3D)
+#define MKTC_3DLB_END 0xAD000184
+MKTC_ST(MKTC_3DLB_END)
+
+#define MKTC_TAEVENT_TAFINISHED 0xAD000200
+MKTC_ST(MKTC_TAEVENT_TAFINISHED)
+#define MKTC_TAEVENT_END 0xAD000202
+MKTC_ST(MKTC_TAEVENT_END)
+#define MKTC_TALB_TAFINISHED 0xAD000280
+MKTC_ST(MKTC_TALB_TAFINISHED)
+#define MKTC_TALB_FINDTA 0xAD000281
+MKTC_ST(MKTC_TALB_FINDTA)
+#define MKTC_TALB_END 0xAD000282
+MKTC_ST(MKTC_TALB_END)
+
+#define MKTC_CRRL_WRITEOPSBLOCKED 0xAD000300
+MKTC_ST(MKTC_CRRL_WRITEOPSBLOCKED)
+#define MKTC_CRRL_READOPSBLOCKED 0xAD000301
+MKTC_ST(MKTC_CRRL_READOPSBLOCKED)
+#define MKTC_CRRL_FOUNDRENDER 0xAD000302
+MKTC_ST(MKTC_CRRL_FOUNDRENDER)
+#define MKTC_CRRL_NORENDER 0xAD000303
+MKTC_ST(MKTC_CRRL_NORENDER)
+#define MKTC_CRRL_TARC_DIFFERENT 0xAD000304
+MKTC_ST(MKTC_CRRL_TARC_DIFFERENT)
+#define MKTC_CRRL_BLOCKEDRC 0xAD000309
+MKTC_ST(MKTC_CRRL_BLOCKEDRC)
+#define MKTC_CRRL_BLOCKEDRTDATA 0xAD00030A
+MKTC_ST(MKTC_CRRL_BLOCKEDRTDATA)
+#define MKTC_CRRL_CONTEXT_SUSPENDED 0xAD00030B
+MKTC_ST(MKTC_CRRL_CONTEXT_SUSPENDED)
+#define MKTC_CRRL_TAWAITINGFORMEM 0xAD00030C
+MKTC_ST(MKTC_CRRL_TAWAITINGFORMEM)
+#define MKTC_CRRL_TAOOMBUTPRIOINV 0xAD00030D
+MKTC_ST(MKTC_CRRL_TAOOMBUTPRIOINV)
+#define MKTC_CRRL_READOPS2BLOCKED 0xAD00030E
+MKTC_ST(MKTC_CRRL_READOPS2BLOCKED)
+#define MKTC_CRRL_SRC_WRITEOPSBLOCKED 0xAD00030F
+MKTC_ST(MKTC_CRRL_SRC_WRITEOPSBLOCKED)
+#define MKTC_CRRL_SRC_READOPSBLOCKED 0xAD000310
+MKTC_ST(MKTC_CRRL_SRC_READOPSBLOCKED)
+
+#define MKTC_KICKRENDER_START 0xAD000400
+MKTC_ST(MKTC_KICKRENDER_START)
+#define MKTC_KICKRENDER_OVERLAP 0xAD000401
+MKTC_ST(MKTC_KICKRENDER_OVERLAP)
+#define MKTC_KICKRENDER_ISP_START 0xAD000402
+MKTC_ST(MKTC_KICKRENDER_ISP_START)
+#define MKTC_KICKRENDER_RESUME 0xAD000403
+MKTC_ST(MKTC_KICKRENDER_RESUME)
+#define MKTC_KICKRENDER_CONFIG_REGION_HDRS 0xAD000404
+MKTC_ST(MKTC_KICKRENDER_CONFIG_REGION_HDRS)
+#define MKTC_KICKRENDER_END 0xAD000408
+MKTC_ST(MKTC_KICKRENDER_END)
+#define MKTC_KICKRENDER_RENDERCONTEXT 0xAD000409
+MKTC_ST(MKTC_KICKRENDER_RENDERCONTEXT)
+#define MKTC_KICKRENDER_RTDATA 0xAD00040A
+MKTC_ST(MKTC_KICKRENDER_RTDATA)
+#define MKTC_KICKRENDER_PID 0xAD00040B
+MKTC_ST(MKTC_KICKRENDER_PID)
+
+#define MKTC_RENDERFINISHED_START 0xAD000500
+MKTC_ST(MKTC_RENDERFINISHED_START)
+#define MKTC_RF_START_NEXT_MT 0xAD000501
+MKTC_ST(MKTC_RF_START_NEXT_MT)
+#define MKTC_RF_ALL_MTS_DONE 0xAD000502
+MKTC_ST(MKTC_RF_ALL_MTS_DONE)
+#define MKTC_RENDERFINISHED_END 0xAD000503
+MKTC_ST(MKTC_RENDERFINISHED_END)
+#define MKTC_VISQUERY_START 0xAD000504
+MKTC_ST(MKTC_VISQUERY_START)
+#define MKTC_VISQUERY_END 0xAD000505
+MKTC_ST(MKTC_VISQUERY_END)
+#define MKTC_TRANSFERRENDERFINISHED_START 0xAD000508
+MKTC_ST(MKTC_TRANSFERRENDERFINISHED_START)
+#define MKTC_TRANSFERRENDERFINISHED_END 0xAD000509
+MKTC_ST(MKTC_TRANSFERRENDERFINISHED_END)
+#define MKTC_TRF_UPDATESTATUSVALS 0xAD00050A
+MKTC_ST(MKTC_TRF_UPDATESTATUSVALS)
+#define MKTC_TRF_UPDATESTATUSVALS_DONE 0xAD00050B
+MKTC_ST(MKTC_TRF_UPDATESTATUSVALS_DONE)
+
+#define MKTC_PIXELENDRENDER_START 0xAD000600
+MKTC_ST(MKTC_PIXELENDRENDER_START)
+#define MKTC_PIXELENDRENDER_AFTERLOCK 0xAD000601
+MKTC_ST(MKTC_PIXELENDRENDER_AFTERLOCK)
+#define MKTC_PIXELENDRENDER_END 0xAD000602
+MKTC_ST(MKTC_PIXELENDRENDER_END)
+#define MKTC_PIXELENDRENDER_TLQEND 0xAD000603
+MKTC_ST(MKTC_PIXELENDRENDER_TLQEND)
+
+#define MKTC_3DMEMFREE_START 0xAD000700
+MKTC_ST(MKTC_3DMEMFREE_START)
+#define MKTC_3DMEMFREE_AFTERLOCK 0xAD000701
+MKTC_ST(MKTC_3DMEMFREE_AFTERLOCK)
+#define MKTC_3DMEMFREE_TESTEOR 0xAD000702
+MKTC_ST(MKTC_3DMEMFREE_TESTEOR)
+#define MKTC_3DMEMFREE_END 0xAD000703
+MKTC_ST(MKTC_3DMEMFREE_END)
+
+#define MKTC_KICKTA_START 0xAD000800
+MKTC_ST(MKTC_KICKTA_START)
+#define MKTC_KICKTA_OVERLAP 0xAD000801
+MKTC_ST(MKTC_KICKTA_OVERLAP)
+#define MKTC_KICKTA_RESETCONTEXT 0xAD000802
+MKTC_ST(MKTC_KICKTA_RESETCONTEXT)
+#define MKTC_KICKTA_VDM_START 0xAD000803
+MKTC_ST(MKTC_KICKTA_VDM_START)
+#define MKTC_KICKTA_END 0xAD000804
+MKTC_ST(MKTC_KICKTA_END)
+#define MKTC_KICKTA_RENDERCONTEXT 0xAD000805
+MKTC_ST(MKTC_KICKTA_RENDERCONTEXT)
+#define MKTC_KICKTA_RTDATA 0xAD000806
+MKTC_ST(MKTC_KICKTA_RTDATA)
+#define MKTC_KICKTA_RESET_VDMCSSTATUS 0xAD000807
+MKTC_ST(MKTC_KICKTA_RESET_VDMCSSTATUS)
+#define MKTC_KICKTA_RESET_BUFFERS 0xAD000808
+MKTC_ST(MKTC_KICKTA_RESET_BUFFERS)
+#define MKTC_KICKTA_PID 0xAD000809
+MKTC_ST(MKTC_KICKTA_PID)
+#define MKTC_KICKTA_TACMD_DEBUG 0xAD00080A
+MKTC_ST(MKTC_KICKTA_TACMD_DEBUG)
+#define MKTC_KICKTA_FREECONTEXT 0xAD00080B
+MKTC_ST(MKTC_KICKTA_FREECONTEXT)
+#define MKTC_KICKTA_PIM_PATCHING 0xAD00080C
+MKTC_ST(MKTC_KICKTA_PIM_PATCHING)
+
+#define MKTC_KICKTA_CHKPT_START_DUMMY_CS 0xAD0008A1
+MKTC_ST(MKTC_KICKTA_CHKPT_START_DUMMY_CS)
+#define MKTC_KICKTA_CHKPT_START_DUMMY_TAK 0xAD0008A2
+MKTC_ST(MKTC_KICKTA_CHKPT_START_DUMMY_TAK)
+#define MKTC_KICKTA_CHKPT_WAIT_FOR_DUMMY_KICK 0xAD0008A3
+MKTC_ST(MKTC_KICKTA_CHKPT_WAIT_FOR_DUMMY_KICK)
+#define MKTC_KICKTA_CHKPT_WAIT_NEXT_CORE 0xAD0008A4
+MKTC_ST(MKTC_KICKTA_CHKPT_WAIT_NEXT_CORE)
+#define MKTC_KICKTA_CHKPT_RESET_COMPLETE 0xAD0008A5
+MKTC_ST(MKTC_KICKTA_CHKPT_RESET_COMPLETE)
+#define MKTC_KICKTA_CHKPT_CHECK_SWITCH 0xAD0008A6
+MKTC_ST(MKTC_KICKTA_CHKPT_CHECK_SWITCH)
+
+#define MKTC_HOSTKICK_START 0xAD000900
+MKTC_ST(MKTC_HOSTKICK_START)
+#define MKTC_HOSTKICK_END 0xAD000901
+MKTC_ST(MKTC_HOSTKICK_END)
+#define MKTC_HOSTKICK_PROCESS_QUEUES_END 0xAD000902
+MKTC_ST(MKTC_HOSTKICK_PROCESS_QUEUES_END)
+#define MKTC_HOSTKICK_2D 0xAD000903
+MKTC_ST(MKTC_HOSTKICK_2D)
+#define MKTC_HOSTKICK_TRANSFER 0xAD000904
+MKTC_ST(MKTC_HOSTKICK_TRANSFER)
+#define MKTC_HOSTKICK_TA 0xAD000905
+MKTC_ST(MKTC_HOSTKICK_TA)
+#define MKTC_HOSTKICK_PROCESS_QUEUES 0xAD000906
+MKTC_ST(MKTC_HOSTKICK_PROCESS_QUEUES)
+#define MKTC_HOSTKICK_RESUME 0xAD000908
+MKTC_ST(MKTC_HOSTKICK_RESUME)
+#define MKTC_HOSTKICK_POWEROFF 0xAD000909
+MKTC_ST(MKTC_HOSTKICK_POWEROFF)
+#define MKTC_HOSTKICK_IDLE 0xAD00090A
+MKTC_ST(MKTC_HOSTKICK_IDLE)
+#define MKTC_HOSTKICK_CTXSUSPEND 0xAD00090B
+MKTC_ST(MKTC_HOSTKICK_CTXSUSPEND)
+#define MKTC_HOSTKICK_CTXRESUME 0xAD00090C
+MKTC_ST(MKTC_HOSTKICK_CTXRESUME)
+
+#define MKTC_TIMER_POTENTIAL_TA_LOCKUP 0xAD000A00
+MKTC_ST(MKTC_TIMER_POTENTIAL_TA_LOCKUP)
+#define MKTC_TIMER_POTENTIAL_3D_LOCKUP 0xAD000A01
+MKTC_ST(MKTC_TIMER_POTENTIAL_3D_LOCKUP)
+#define MKTC_TIMER_CTAL_START 0xAD000A02
+MKTC_ST(MKTC_TIMER_CTAL_START)
+#define MKTC_TIMER_CTAL_END 0xAD000A03
+MKTC_ST(MKTC_TIMER_CTAL_END)
+#define MKTC_TIMER_C3DL_START 0xAD000A04
+MKTC_ST(MKTC_TIMER_C3DL_START)
+#define MKTC_TIMER_C3DL_END 0xAD000A05
+MKTC_ST(MKTC_TIMER_C3DL_END)
+#define MKTC_TIMER_LOCKUP 0xAD000A0A
+MKTC_ST(MKTC_TIMER_LOCKUP)
+#define MKTC_TIMER_NOT_TA_LOCKUP 0xAD000A0B
+MKTC_ST(MKTC_TIMER_NOT_TA_LOCKUP)
+#define MKTC_TIMER_NOT_3D_LOCKUP 0xAD000A0C
+MKTC_ST(MKTC_TIMER_NOT_3D_LOCKUP)
+#define MKTC_TIMER_2D_LOCKUP 0xAD000A0D
+MKTC_ST(MKTC_TIMER_2D_LOCKUP)
+#define MKTC_TIMER_POTENTIAL_2D_LOCKUP 0xAD000A10
+MKTC_ST(MKTC_TIMER_POTENTIAL_2D_LOCKUP)
+#define MKTC_TIMER_C2DL_START 0xAD000A11
+MKTC_ST(MKTC_TIMER_C2DL_START)
+#define MKTC_TIMER_C2DL_END 0xAD000A12
+MKTC_ST(MKTC_TIMER_C2DL_END)
+#define MKTC_TIMER_NOT_2D_LOCKUP 0xAD000A13
+MKTC_ST(MKTC_TIMER_NOT_2D_LOCKUP)
+#define MKTC_TIMER_ABORTALL 0xAD000A0E
+MKTC_ST(MKTC_TIMER_ABORTALL)
+#define MKTC_TIMER_END 0xAD000A0F
+MKTC_ST(MKTC_TIMER_END)
+
+#define MKTC_HWR_START 0xAD000B00
+MKTC_ST(MKTC_HWR_START)
+#define MKTC_HWR_END 0xAD000B01
+MKTC_ST(MKTC_HWR_END)
+#define MKTC_HWR_HKS 0xAD000B02
+MKTC_ST(MKTC_HWR_HKS)
+#define MKTC_HWR_PRL 0xAD000B03
+MKTC_ST(MKTC_HWR_PRL)
+#define MKTC_HWR_PRL_DP 0xAD000B04
+MKTC_ST(MKTC_HWR_PRL_DP)
+#define MKTC_HWR_CRL 0xAD000B05
+MKTC_ST(MKTC_HWR_CRL)
+#define MKTC_HWR_CRL_DP 0xAD000B06
+MKTC_ST(MKTC_HWR_CRL_DP)
+#define MKTC_HWR_TRL 0xAD000B07
+MKTC_ST(MKTC_HWR_TRL)
+#define MKTC_HWR_TRL_DP 0xAD000B08
+MKTC_ST(MKTC_HWR_TRL_DP)
+#define MKTC_HWR_ISC 0xAD000B09
+MKTC_ST(MKTC_HWR_ISC)
+#define MKTC_HWR_2DL 0xAD000B0A
+MKTC_ST(MKTC_HWR_2DL)
+
+#define MKTC_URSV_START 0xAD000C00
+MKTC_ST(MKTC_URSV_START)
+#define MKTC_URSV_UPDATEWRITEOPS 0xAD000C01
+MKTC_ST(MKTC_URSV_UPDATEWRITEOPS)
+#define MKTC_URSV_UPDATESTATUSVALS 0xAD000C03
+MKTC_ST(MKTC_URSV_UPDATESTATUSVALS)
+#define MKTC_URSV_UPDATESTATUSVALS_DONE 0xAD000C04
+MKTC_ST(MKTC_URSV_UPDATESTATUSVALS_DONE)
+#define MKTC_URSV_END 0xAD000C05
+MKTC_ST(MKTC_URSV_END)
+
+#define MKTC_STORETACONTEXT_START 0xAD000D00
+MKTC_ST(MKTC_STORETACONTEXT_START)
+#define MKTC_STORETACONTEXT_END 0xAD000D01
+MKTC_ST(MKTC_STORETACONTEXT_END)
+#define MKTC_LOADTACONTEXT_START 0xAD000D02
+MKTC_ST(MKTC_LOADTACONTEXT_START)
+#define MKTC_LOADTACONTEXT_END 0xAD000D03
+MKTC_ST(MKTC_LOADTACONTEXT_END)
+#define MKTC_STORE3DCONTEXT_START 0xAD000D04
+MKTC_ST(MKTC_STORE3DCONTEXT_START)
+#define MKTC_STORE3DCONTEXT_END 0xAD000D05
+MKTC_ST(MKTC_STORE3DCONTEXT_END)
+#define MKTC_LOAD3DCONTEXT_START 0xAD000D06
+MKTC_ST(MKTC_LOAD3DCONTEXT_START)
+#define MKTC_LOAD3DCONTEXT_END 0xAD000D07
+MKTC_ST(MKTC_LOAD3DCONTEXT_END)
+
+#define MKTC_FINDTA_POWERREQUEST 0xAD000E00
+MKTC_ST(MKTC_FINDTA_POWERREQUEST)
+#define MKTC_FINDTA_TA3D_OVERLAP_BLOCKED 0xAD000E01
+MKTC_ST(MKTC_FINDTA_TA3D_OVERLAP_BLOCKED)
+#define MKTC_FINDTA_RTDATA_RENDERING 0xAD000E02
+MKTC_ST(MKTC_FINDTA_RTDATA_RENDERING)
+#define MKTC_FINDTA_3DRC_DIFFERENT 0xAD000E03
+MKTC_ST(MKTC_FINDTA_3DRC_DIFFERENT)
+#define MKTC_FINDTA_WRITEOPSBLOCKED 0xAD000E04
+MKTC_ST(MKTC_FINDTA_WRITEOPSBLOCKED)
+#define MKTC_FINDTA_READOPSBLOCKED 0xAD000E05
+MKTC_ST(MKTC_FINDTA_READOPSBLOCKED)
+#define MKTC_FINDTA_RESIZE_PB 0xAD000E06
+MKTC_ST(MKTC_FINDTA_RESIZE_PB)
+#define MKTC_FINDTA_RESIZE_PB_BLOCKED 0xAD000E07
+MKTC_ST(MKTC_FINDTA_RESIZE_PB_BLOCKED)
+#define MKTC_FINDTA_SHRINK_PB 0xAD000E08
+MKTC_ST(MKTC_FINDTA_SHRINK_PB)
+#define MKTC_FINDTA_TAPB_DIFFERENT 0xAD000E09
+MKTC_ST(MKTC_FINDTA_TAPB_DIFFERENT)
+#define MKTC_FINDTA_TACONTEXT_DIFFERENT 0xAD000E0A
+MKTC_ST(MKTC_FINDTA_TACONTEXT_DIFFERENT)
+#define MKTC_FINDTA_TA2D_OVERLAP_BLOCKED 0xAD000E0B
+MKTC_ST(MKTC_FINDTA_TA2D_OVERLAP_BLOCKED)
+#define MKTC_FINDTA_CONTEXT_SUSPENDED 0xAD000E0C
+MKTC_ST(MKTC_FINDTA_CONTEXT_SUSPENDED)
+#define MKTC_FINDTA_SRC_READOPSBLOCKED 0xAD000E0D
+MKTC_ST(MKTC_FINDTA_SRC_READOPSBLOCKED)
+#define MKTC_FINDTA_SRC_WRITEOPSBLOCKED 0xAD000E0E
+MKTC_ST(MKTC_FINDTA_SRC_WRITEOPSBLOCKED)
+#define MKTC_FINDTA_READOPS2BLOCKED 0xAD000E0F
+MKTC_ST(MKTC_FINDTA_READOPS2BLOCKED)
+
+#define MKTC_CTRL_SRCREADOPSBLOCKED 0xAD000F00
+MKTC_ST(MKTC_CTRL_SRCREADOPSBLOCKED)
+#define MKTC_CTRL_SRCWRITEOPSBLOCKED 0xAD000F01
+MKTC_ST(MKTC_CTRL_SRCWRITEOPSBLOCKED)
+#define MKTC_CTRL_DSTREADOPSBLOCKED 0xAD000F02
+MKTC_ST(MKTC_CTRL_DSTREADOPSBLOCKED)
+#define MKTC_CTRL_DSTWRITEOPSBLOCKED 0xAD000F03
+MKTC_ST(MKTC_CTRL_DSTWRITEOPSBLOCKED)
+#define MKTC_CTRL_TARC_DIFFERENT 0xAD000F04
+MKTC_ST(MKTC_CTRL_TARC_DIFFERENT)
+#define MKTC_CTRL_CONTEXT_SUSPENDED 0xAD000F05
+MKTC_ST(MKTC_CTRL_CONTEXT_SUSPENDED)
+#define MKTC_CTRL_SRCREADOPS2BLOCKED 0xAD000F06
+MKTC_ST(MKTC_CTRL_SRCREADOPS2BLOCKED)
+
+#define MKTC_DPTA_START 0xAD001000
+MKTC_ST(MKTC_DPTA_START)
+#define MKTC_DPTA_UPDATESTATUSVALS 0xAD001001
+MKTC_ST(MKTC_DPTA_UPDATESTATUSVALS)
+#define MKTC_DPTA_UPDATESTATUSVALS_DONE 0xAD001002
+MKTC_ST(MKTC_DPTA_UPDATESTATUSVALS_DONE)
+#define MKTC_DPTA_NORENDER 0xAD001003
+MKTC_ST(MKTC_DPTA_NORENDER)
+#define MKTC_DPTA_MEMFREE 0xAD001004
+MKTC_ST(MKTC_DPTA_MEMFREE)
+#define MKTC_DPTA_INC_COMPLETECOUNT 0xAD001005
+MKTC_ST(MKTC_DPTA_INC_COMPLETECOUNT)
+
+#define MKTC_INVALDC 0xAD001100
+MKTC_ST(MKTC_INVALDC)
+#define MKTC_INVALPT 0xAD001101
+MKTC_ST(MKTC_INVALPT)
+#define MKTC_INVALSLC 0xAD001102
+MKTC_ST(MKTC_INVALSLC)
+#define MKTC_INVALDATA 0xAD001103
+MKTC_ST(MKTC_INVALDATA)
+
+#define MKTC_RESTARTTA 0xAD001200
+MKTC_ST(MKTC_RESTARTTA)
+#define MKTC_CSABORTNONGBL 0xAD001201
+MKTC_ST(MKTC_CSABORTNONGBL)
+#define MKTC_CSABORTALL 0xAD001202
+MKTC_ST(MKTC_CSABORTALL)
+#define MKTC_CSRENDERINPROGRESS 0xAD001203
+MKTC_ST(MKTC_CSRENDERINPROGRESS)
+#define MKTC_TATERMRENDERINPROGRESS 0xAD001204
+MKTC_ST(MKTC_TATERMRENDERINPROGRESS)
+#define MKTC_RESTARTTANORENDER 0xAD001205
+MKTC_ST(MKTC_RESTARTTANORENDER)
+#define MKTC_SPM_KICKRENDER 0xAD001206
+MKTC_ST(MKTC_SPM_KICKRENDER)
+#define MKTC_SPM_RESUME_ABORTCOMPLETE 0xAD001208
+MKTC_ST(MKTC_SPM_RESUME_ABORTCOMPLETE)
+#define MKTC_RESUMEVDM 0xAD001209
+MKTC_ST(MKTC_RESUMEVDM)
+#define MKTC_REMOVE_RESERVE_MEM 0xAD00120A
+MKTC_ST(MKTC_REMOVE_RESERVE_MEM)
+#define MKTC_INCREASEZLSTHRESHOLD 0xAD00120B
+MKTC_ST(MKTC_INCREASEZLSTHRESHOLD)
+#define MKTC_CSFORCEABORTALL 0xAD00120C
+MKTC_ST(MKTC_CSFORCEABORTALL)
+
+#define MKTC_DUMMY_DEPTH 0xAD00120D
+MKTC_ST(MKTC_DUMMY_DEPTH)
+#define MKTC_DUMMY_DEPTH_CS 0xAD00120E
+MKTC_ST(MKTC_DUMMY_DEPTH_CS)
+
+#define MKTC_MTETE_OOM 0xAD00120F
+MKTC_ST(MKTC_MTETE_OOM)
+#define MKTC_MTETE_OOM_FIRST_STORE_REF 0xAD001210
+MKTC_ST(MKTC_MTETE_OOM_FIRST_STORE_REF)
+#define MKTC_MERGE_STATE_TABLES 0xAD001211
+MKTC_ST(MKTC_MERGE_STATE_TABLES)
+#define MKTC_NO_PAGES_LEFT_FOR_23055 0xAD001212
+MKTC_ST(MKTC_NO_PAGES_LEFT_FOR_23055)
+#define MKTC_NO_STATE_MODS 0xAD001213
+MKTC_ST(MKTC_NO_STATE_MODS)
+#define MKTC_FIND_MTE_PAGE_IN_STATE 0xAD001214
+MKTC_ST(MKTC_FIND_MTE_PAGE_IN_STATE)
+#define MKTC_MTE_PAGE_FOUND 0xAD001215
+MKTC_ST(MKTC_MTE_PAGE_FOUND)
+#define MKTC_MOVE_MTE_PAGE_TO_TA_STATE 0xAD001216
+MKTC_ST(MKTC_MOVE_MTE_PAGE_TO_TA_STATE)
+#define MKTC_MOVE_MTE_PAGE_TO_TA_STATE_END 0xAD001217
+MKTC_ST(MKTC_MOVE_MTE_PAGE_TO_TA_STATE_END)
+#define MKTC_ZERO_ZLS_THRESHOLD 0xAD001218
+MKTC_ST(MKTC_ZERO_ZLS_THRESHOLD)
+#define MKTC_RESTORE_ZLS_THRESHOLD 0xAD001219
+MKTC_ST(MKTC_RESTORE_ZLS_THRESHOLD)
+#define MKTC_FIND_MTE_PAGE_IN_CSM 0xAD00121A
+MKTC_ST(MKTC_FIND_MTE_PAGE_IN_CSM)
+#define MKTC_REISSUE_MTE_PAGE 0xAD00121B
+MKTC_ST(MKTC_REISSUE_MTE_PAGE)
+#define MKTC_REISSUE_MTE_PAGE_REQUIRED 0xAD00121C
+MKTC_ST(MKTC_REISSUE_MTE_PAGE_REQUIRED)
+#define MKTC_REISSUE_MTE_PAGE_END 0xAD00121D
+MKTC_ST(MKTC_REISSUE_MTE_PAGE_END)
+#define MKTC_RESET_TE_PSG 0xAD00121E
+MKTC_ST(MKTC_RESET_TE_PSG)
+
+#define MKTC_OOM_WRITEOPSBLOCKED 0xAD00121F
+MKTC_ST(MKTC_OOM_WRITEOPSBLOCKED)
+#define MKTC_OOM_READOPSBLOCKED 0xAD001220
+MKTC_ST(MKTC_OOM_READOPSBLOCKED)
+#define MKTC_OOM_SRC_WRITEOPSBLOCKED 0xAD001221
+MKTC_ST(MKTC_OOM_SRC_WRITEOPSBLOCKED)
+#define MKTC_OOM_SRC_READOPSBLOCKED 0xAD001222
+MKTC_ST(MKTC_OOM_SRC_READOPSBLOCKED)
+#define MKTC_OOM_SPM_DEADLOCK 0xAD001223
+MKTC_ST(MKTC_OOM_SPM_DEADLOCK)
+#define MKTC_OOM_SPM_DEADLOCK_MEM_ADDED 0xAD001224
+MKTC_ST(MKTC_OOM_SPM_DEADLOCK_MEM_ADDED)
+#define MKTC_RESET 0xAD001225
+MKTC_ST(MKTC_RESET)
+#define MKTC_SPM_INVALID_ZLSCONFIG 0xAD001226
+MKTC_ST(MKTC_SPM_INVALID_ZLSCONFIG)
+
+#define MKTC_OOM_TYPE_MT 0xAD00122A
+MKTC_ST(MKTC_OOM_TYPE_MT)
+#define MKTC_OOM_TYPE_GLOBAL 0xAD001230
+MKTC_ST(MKTC_OOM_TYPE_GLOBAL)
+#define MKTC_OOM_CAUSE_GBL_OOM 0xAD001231
+MKTC_ST(MKTC_OOM_CAUSE_GBL_OOM)
+#define MKTC_OOM_RESTORE_LIST_SIZE 0xAD001232
+MKTC_ST(MKTC_OOM_RESTORE_LIST_SIZE)
+
+#define MKTC_CHECK_MTE_PAGE_REISSUE 0xAD001240
+MKTC_ST(MKTC_CHECK_MTE_PAGE_REISSUE)
+#define MKTC_CPRI_VALID_ENTRIES 0xAD001241
+MKTC_ST(MKTC_CPRI_VALID_ENTRIES)
+#define MKTC_CPRI_STORE_DPLIST 0xAD001242
+MKTC_ST(MKTC_CPRI_STORE_DPLIST)
+#define MKTC_CPRI_STORE_OTPM_CSM 0xAD001243
+MKTC_ST(MKTC_CPRI_STORE_OTPM_CSM)
+#define MKTC_CPRI_ABORT_MT_IDX 0xAD001244
+MKTC_ST(MKTC_CPRI_ABORT_MT_IDX)
+#define MKTC_CPRI_ABORT_CORE_IDX 0xAD001245
+MKTC_ST(MKTC_CPRI_ABORT_CORE_IDX)
+#define MKTC_CPRI_CSM_TABLE_DATA 0xAD001246
+MKTC_ST(MKTC_CPRI_CSM_TABLE_DATA)
+#define MKTC_CPRI_PIM_DATA 0xAD001247
+MKTC_ST(MKTC_CPRI_PIM_DATA)
+#define MKTC_CPRI_DO_CIRCULAR_TEST 0xAD001248
+MKTC_ST(MKTC_CPRI_DO_CIRCULAR_TEST)
+#define MKTC_CPRI_WRITE_ENTRIES 0xAD001249
+MKTC_ST(MKTC_CPRI_WRITE_ENTRIES)
+
+#define MKTC_MTE_ENTRY_NOT_IN_ANY_LIST 0xAD001250
+MKTC_ST(MKTC_MTE_ENTRY_NOT_IN_ANY_LIST)
+
+#define MKTC_SPMAC_IGNORE_TERMINATE 0xAD001251
+MKTC_ST(MKTC_SPMAC_IGNORE_TERMINATE)
+
+#define MKTC_SPMAC_REQUEST_3D_TIMEOUT 0xAD001252
+MKTC_ST(MKTC_SPMAC_REQUEST_3D_TIMEOUT)
+#define MKTC_SPMAC_3D_TIMEOUT_COMPLETE 0xAD001253
+MKTC_ST(MKTC_SPMAC_3D_TIMEOUT_COMPLETE)
+#define MKTC_OOM_READOPS2BLOCKED 0xAD001254
+MKTC_ST(MKTC_OOM_READOPS2BLOCKED)
+
+/* PB Load/store status */
+#define MKTC_LOADTAPB_START 0xAD001300
+MKTC_ST(MKTC_LOADTAPB_START)
+#define MKTC_LOADTAPB_END 0xAD001301
+MKTC_ST(MKTC_LOADTAPB_END)
+#define MKTC_STORETAPB_START 0xAD001302
+MKTC_ST(MKTC_STORETAPB_START)
+#define MKTC_STORETAPB_END 0xAD001303
+MKTC_ST(MKTC_STORETAPB_END)
+#define MKTC_LOAD3DPB_START 0xAD001304
+MKTC_ST(MKTC_LOAD3DPB_START)
+#define MKTC_LOAD3DPB_END 0xAD001305
+MKTC_ST(MKTC_LOAD3DPB_END)
+#define MKTC_STORE3DPB_START 0xAD001306
+MKTC_ST(MKTC_STORE3DPB_START)
+#define MKTC_STORE3DPB_END 0xAD001307
+MKTC_ST(MKTC_STORE3DPB_END)
+#define MKTC_LOADTAPB_PAGETABLE_DONE 0xAD001308
+MKTC_ST(MKTC_LOADTAPB_PAGETABLE_DONE)
+#define MKTC_LOAD3DPB_PAGETABLE_DONE 0xAD001309
+MKTC_ST(MKTC_LOAD3DPB_PAGETABLE_DONE)
+
+#define MKTC_TIMER_RC_CLEANUP 0xAD001400
+MKTC_ST(MKTC_TIMER_RC_CLEANUP)
+#define MKTC_TIMER_RC_CLEANUP_DONE 0xAD001401
+MKTC_ST(MKTC_TIMER_RC_CLEANUP_DONE)
+#define MKTC_TIMER_RC_CLEANUP_BUSY 0xAD001402
+MKTC_ST(MKTC_TIMER_RC_CLEANUP_BUSY)
+#define MKTC_TIMER_RT_CLEANUP 0xAD001410
+MKTC_ST(MKTC_TIMER_RT_CLEANUP)
+#define MKTC_TIMER_RT_CLEANUP_DONE 0xAD001411
+MKTC_ST(MKTC_TIMER_RT_CLEANUP_DONE)
+#define MKTC_TIMER_RT_CLEANUP_PENDING 0xAD001412
+MKTC_ST(MKTC_TIMER_RT_CLEANUP_PENDING)
+#define MKTC_TIMER_RT_CLEANUP_TIDYPARTIALLIST 0xAD001413
+MKTC_ST(MKTC_TIMER_RT_CLEANUP_TIDYPARTIALLIST)
+#define MKTC_TIMER_RT_CLEANUP_BUSY 0xAD001414
+MKTC_ST(MKTC_TIMER_RT_CLEANUP_BUSY)
+#define MKTC_TIMER_TC_CLEANUP 0xAD001420
+MKTC_ST(MKTC_TIMER_TC_CLEANUP)
+#define MKTC_TIMER_TC_CLEANUP_DONE 0xAD001421
+MKTC_ST(MKTC_TIMER_TC_CLEANUP_DONE)
+#define MKTC_TIMER_TC_CLEANUP_BUSY 0xAD001422
+MKTC_ST(MKTC_TIMER_TC_CLEANUP_BUSY)
+#define MKTC_TIMER_2DC_CLEANUP 0xAD001430
+MKTC_ST(MKTC_TIMER_2DC_CLEANUP)
+#define MKTC_TIMER_2DC_CLEANUP_DONE 0xAD001431
+MKTC_ST(MKTC_TIMER_2DC_CLEANUP_DONE)
+#define MKTC_TIMER_2DC_CLEANUP_BUSY 0xAD001432
+MKTC_ST(MKTC_TIMER_2DC_CLEANUP_BUSY)
+#define MKTC_TIMER_SHAREDPBDESC_CLEANUP 0xAD001440
+MKTC_ST(MKTC_TIMER_SHAREDPBDESC_CLEANUP)
+
+
+#define MKTC_TIMER_ISP_SWITCH_POTENTIAL_LOCKUP 0xAD001450
+MKTC_ST(MKTC_TIMER_ISP_SWITCH_POTENTIAL_LOCKUP)
+#define MKTC_TIMER_ISP_SWITCH_FORCE_SWITCH 0xAD001451
+MKTC_ST(MKTC_TIMER_ISP_SWITCH_FORCE_SWITCH)
+
+#define MKTC_UTSO_UPDATEREADOPS 0xAD001600
+MKTC_ST(MKTC_UTSO_UPDATEREADOPS)
+#define MKTC_UTSO_UPDATEWRITEOPS 0xAD001601
+MKTC_ST(MKTC_UTSO_UPDATEWRITEOPS)
+
+#define MKTC_TAFINISHED_UPDATESTATUSVALS 0xAD001700
+MKTC_ST(MKTC_TAFINISHED_UPDATESTATUSVALS)
+#define MKTC_TAFINISHED_UPDATESTATUSVALS_DONE 0xAD001701
+MKTC_ST(MKTC_TAFINISHED_UPDATESTATUSVALS_DONE)
+#define MKTC_TAFINISHED_NORENDER 0xAD001702
+MKTC_ST(MKTC_TAFINISHED_NORENDER)
+#define MKTC_TAFINISHED_LASTKICK 0xAD001703
+MKTC_ST(MKTC_TAFINISHED_LASTKICK)
+#define MKTC_TAFINISHED_FINDRENDER 0xAD001704
+MKTC_ST(MKTC_TAFINISHED_FINDRENDER)
+#define MKTC_TAFINISHED_FINDTA 0xAD001705
+MKTC_ST(MKTC_TAFINISHED_FINDTA)
+#define MKTC_TAFINISHED_END 0xAD001706
+MKTC_ST(MKTC_TAFINISHED_END)
+#define MKTC_TAF_SPM_DEADLOCK_MEM_REMOVED 0xAD001707
+MKTC_ST(MKTC_TAF_SPM_DEADLOCK_MEM_REMOVED)
+#define MKTC_TAF_RESERVE_MEM 0xAD001708
+MKTC_ST(MKTC_TAF_RESERVE_MEM)
+#define MKTC_TAF_RESERVE_MEM_REQUEST_RENDER 0xAD001709
+MKTC_ST(MKTC_TAF_RESERVE_MEM_REQUEST_RENDER)
+#define MKTC_TAF_RESERVE_FREE_RENDER_FINISHED 0xAD00170A
+MKTC_ST(MKTC_TAF_RESERVE_FREE_RENDER_FINISHED)
+#define MKTC_TAF_RESERVE_FREE_DUMMY_RENDER 0xAD00170B
+MKTC_ST(MKTC_TAF_RESERVE_FREE_DUMMY_RENDER)
+#define MKTC_TAF_DEBUG_SAS 0xAD00170C
+MKTC_ST(MKTC_TAF_DEBUG_SAS)
+#define MKTC_TAFINISHED_NOCONTEXTSWITCH 0xAD00170D
+MKTC_ST(MKTC_TAFINISHED_NOCONTEXTSWITCH)
+
+#define MKTC_TAFINISHED_TERM_COMPLETE_START 0xAD001710
+MKTC_ST(MKTC_TAFINISHED_TERM_COMPLETE_START)
+#define MKTC_TAFINISHED_TERM_COMPLETE_END 0xAD001711
+MKTC_ST(MKTC_TAFINISHED_TERM_COMPLETE_END)
+
+#define MKTC_TAFINISHED_DPMPAGERECYCLING 0xAD001720
+MKTC_ST(MKTC_TAFINISHED_DPMPAGERECYCLING)
+
+#define MKTC_2DEVENT_2DCOMPLETE 0xAD001800
+MKTC_ST(MKTC_2DEVENT_2DCOMPLETE)
+#define MKTC_2DEVENT_END 0xAD001801
+MKTC_ST(MKTC_2DEVENT_END)
+#define MKTC_2DLB_2DCOMPLETE 0xAD001802
+MKTC_ST(MKTC_2DLB_2DCOMPLETE)
+#define MKTC_2DLB_FIND2D 0xAD001803
+MKTC_ST(MKTC_2DLB_FIND2D)
+#define MKTC_2DLB_END 0xAD001804
+MKTC_ST(MKTC_2DLB_END)
+#define MKTC_2DCOMPLETE_START 0xAD001805
+MKTC_ST(MKTC_2DCOMPLETE_START)
+#define MKTC_2DCOMPLETE_END 0xAD001806
+MKTC_ST(MKTC_2DCOMPLETE_END)
+#define MKTC_KICK2D_START 0xAD001807
+MKTC_ST(MKTC_KICK2D_START)
+#define MKTC_KICK2D_END 0xAD001808
+MKTC_ST(MKTC_KICK2D_END)
+#define MKTC_DUMMYPROC2D 0xAD001809
+MKTC_ST(MKTC_DUMMYPROC2D)
+#define MKTC_FTD_SRCREADOPSBLOCKED 0xAD00180A
+MKTC_ST(MKTC_FTD_SRCREADOPSBLOCKED)
+#define MKTC_FTD_SRCWRITEOPSBLOCKED 0xAD00180B
+MKTC_ST(MKTC_FTD_SRCWRITEOPSBLOCKED)
+#define MKTC_FTD_DSTREADOPSBLOCKED 0xAD00180C
+MKTC_ST(MKTC_FTD_DSTREADOPSBLOCKED)
+#define MKTC_FTD_DSTWRITEOPSBLOCKED 0xAD00180D
+MKTC_ST(MKTC_FTD_DSTWRITEOPSBLOCKED)
+#define MKTC_FTD_TA2D_OVERLAP_BLOCKED 0xAD00180E
+MKTC_ST(MKTC_FTD_TA2D_OVERLAP_BLOCKED)
+#define MKTC_U2DSO_UPDATEREADOPS 0xAD00180F
+MKTC_ST(MKTC_U2DSO_UPDATEREADOPS)
+#define MKTC_U2DSO_UPDATEWRITEOPS 0xAD001810
+MKTC_ST(MKTC_U2DSO_UPDATEWRITEOPS)
+#define MKTC_FTD_TAOPSBLOCKED 0xAD001811
+MKTC_ST(MKTC_FTD_TAOPSBLOCKED)
+#define MKTC_KICK2D_2DSLAVEPORT 0xAD001812
+MKTC_ST(MKTC_KICK2D_2DSLAVEPORT)
+#define MKTC_KICK2D_2DSLAVEPORT_DONE 0xAD001813
+MKTC_ST(MKTC_KICK2D_2DSLAVEPORT_DONE)
+#define MKTC_FTD_CONTEXT_SUSPENDED 0xAD001814
+MKTC_ST(MKTC_FTD_CONTEXT_SUSPENDED)
+#define MKTC_KICK2D_PID 0xAD001815
+MKTC_ST(MKTC_KICK2D_PID)
+#define MKTC_FIND2D_ADDR_SPACE_DIFFERENT 0xAD001816
+MKTC_ST(MKTC_FIND2D_ADDR_SPACE_DIFFERENT)
+#define MKTC_FTD_3DOPSBLOCKED 0xAD001817
+MKTC_ST(MKTC_FTD_3DOPSBLOCKED)
+#define MKTC_FTD_DSTREADOPS2BLOCKED 0xAD001818
+MKTC_ST(MKTC_FTD_DSTREADOPS2BLOCKED)
+
+#define MKTC_FCM_START 0xAD001900
+MKTC_ST(MKTC_FCM_START)
+#define MKTC_FCM_END 0xAD001901
+MKTC_ST(MKTC_FCM_END)
+
+#define MKTC_TIMER_ACTIVE_POWER 0xAD001A00
+MKTC_ST(MKTC_TIMER_ACTIVE_POWER)
+#define MKTC_TIMER_POWER_3D_ACTIVE 0xAD001A01
+MKTC_ST(MKTC_TIMER_POWER_3D_ACTIVE)
+#define MKTC_TIMER_POWER_TA_ACTIVE 0xAD001A02
+MKTC_ST(MKTC_TIMER_POWER_TA_ACTIVE)
+#define MKTC_TIMER_POWER_2D_ACTIVE 0xAD001A03
+MKTC_ST(MKTC_TIMER_POWER_2D_ACTIVE)
+#define MKTC_TIMER_POWER_PENDING_EVENTS 0xAD001A04
+MKTC_ST(MKTC_TIMER_POWER_PENDING_EVENTS)
+#define MKTC_TIMER_POWER_IDLE 0xAD001A05
+MKTC_ST(MKTC_TIMER_POWER_IDLE)
+#define MKTC_TIMER_POWER_OFF 0xAD001A06
+MKTC_ST(MKTC_TIMER_POWER_OFF)
+#define MKTC_TIMER_POWER_CCB_ERROR 0xAD001A07
+MKTC_ST(MKTC_TIMER_POWER_CCB_ERROR)
+#define MKTC_TIMER_POWER_RESTART_IMMEDIATE 0xAD001A08
+MKTC_ST(MKTC_TIMER_POWER_RESTART_IMMEDIATE)
+
+#define MKTC_3DCONTEXT_SWITCH 0xAD001B00
+MKTC_ST(MKTC_3DCONTEXT_SWITCH)
+#define MKTC_3DCONTEXT_SWITCH_END 0xAD001B01
+MKTC_ST(MKTC_3DCONTEXT_SWITCH_END)
+
+#define MKTC_TACONTEXT_SWITCH 0xAD001C00
+MKTC_ST(MKTC_TACONTEXT_SWITCH)
+#define MKTC_TACONTEXT_SWITCH_END 0xAD001C02
+MKTC_ST(MKTC_TACONTEXT_SWITCH_END)
+
+#define MKTC_GETMISCINFO_MEMREAD_START 0xAD001D00
+MKTC_ST(MKTC_GETMISCINFO_MEMREAD_START)
+#define MKTC_GETMISCINFO_MEMREAD_END 0xAD001D01
+MKTC_ST(MKTC_GETMISCINFO_MEMREAD_END)
+#define MKTC_GETMISCINFO_MEMWRITE_START 0xAD001D02
+MKTC_ST(MKTC_GETMISCINFO_MEMWRITE_START)
+#define MKTC_GETMISCINFO_MEMWRITE_END 0xAD001D03
+MKTC_ST(MKTC_GETMISCINFO_MEMWRITE_END)
+
+#define MKTC_HALTTA 0xAD001E00
+MKTC_ST(MKTC_HALTTA)
+#define MKTC_HTA_SET_FLAG 0xAD001E01
+MKTC_ST(MKTC_HTA_SET_FLAG)
+#define MKTC_HTA_SAVE_COMPLEX_PTR 0xAD001E02
+MKTC_ST(MKTC_HTA_SAVE_COMPLEX_PTR)
+#define MKTC_HALTTA_END 0xAD001E03
+MKTC_ST(MKTC_HALTTA_END)
+
+#define MKTC_RESUMETA 0xAD001F00
+MKTC_ST(MKTC_RESUMETA)
+#define MKTC_RTA_CONTEXT_LOADED 0xAD001F01
+MKTC_ST(MKTC_RTA_CONTEXT_LOADED)
+#define MKTC_RTA_MTE_STATE_KICKED 0xAD001F02
+MKTC_ST(MKTC_RTA_MTE_STATE_KICKED)
+#define MKTC_RTA_CMPLX_GEOM_PRESENT 0xAD001F03
+MKTC_ST(MKTC_RTA_CMPLX_GEOM_PRESENT)
+#define MKTC_RTA_CMPLX_STATE_KICKED 0xAD001F04
+MKTC_ST(MKTC_RTA_CMPLX_STATE_KICKED)
+#define MKTC_RTA_CHECK_NEXT_SA_PROG 0xAD001F05
+MKTC_ST(MKTC_RTA_CHECK_NEXT_SA_PROG)
+#define MKTC_RTA_CORE_COMPLETED 0xAD001F06
+MKTC_ST(MKTC_RTA_CORE_COMPLETED)
+#define MKTC_RTA_DEBUG_SAS 0xAD001F07
+MKTC_ST(MKTC_RTA_DEBUG_SAS)
+#define MKTC_RESUMETA_END 0xAD001F0F
+MKTC_ST(MKTC_RESUMETA_END)
+
+#define MKTC_RENDERHALT 0xAD002000
+MKTC_ST(MKTC_RENDERHALT)
+#define MKTC_RH_CLEARFLAGS 0xAD002001
+MKTC_ST(MKTC_RH_CLEARFLAGS)
+#define MKTC_RH_CTRL_ADDR 0xAD002002
+MKTC_ST(MKTC_RH_CTRL_ADDR)
+#define MKTC_RH_RGN_ADDR 0xAD002003
+MKTC_ST(MKTC_RH_RGN_ADDR)
+#define MKTC_RH_EMPTY_TILE 0xAD002004
+MKTC_ST(MKTC_RH_EMPTY_TILE)
+#define MKTC_RH_EMPTY_LAST_TILE 0xAD002005
+MKTC_ST(MKTC_RH_EMPTY_LAST_TILE)
+#define MKTC_RH_3D_TIMEOUT 0xAD002006
+MKTC_ST(MKTC_RH_3D_TIMEOUT)
+#define MKTC_RH_NOT_EMPTY 0xAD002007
+MKTC_ST(MKTC_RH_NOT_EMPTY)
+#define MKTC_RH_OBJECT_COMPLETE 0xAD002008
+MKTC_ST(MKTC_RH_OBJECT_COMPLETE)
+#define MKTC_RH_STREAM_LINK 0xAD002009
+MKTC_ST(MKTC_RH_STREAM_LINK)
+#define MKTC_RH_OBJECT_INCOMPLETE 0xAD00200A
+MKTC_ST(MKTC_RH_OBJECT_INCOMPLETE)
+#define MKTC_RH_PRIM_MASK_PRESENT 0xAD00200B
+MKTC_ST(MKTC_RH_PRIM_MASK_PRESENT)
+#define MKTC_RH_BYTE_MASK_PRESENT 0xAD00200C
+MKTC_ST(MKTC_RH_BYTE_MASK_PRESENT)
+#define MKTC_RH_BYTE_MASK_ZERO 0xAD00200D
+MKTC_ST(MKTC_RH_BYTE_MASK_ZERO)
+#define MKTC_RH_PRIM_MASK_ZERO 0xAD00200E
+MKTC_ST(MKTC_RH_PRIM_MASK_ZERO)
+#define MKTC_RH_INVALIDATE_OBJECTS 0xAD00200F
+MKTC_ST(MKTC_RH_INVALIDATE_OBJECTS)
+#define MKTC_RH_OBJECTS_INVALIDATED 0xAD002010
+MKTC_ST(MKTC_RH_OBJECTS_INVALIDATED)
+#define MKTC_RH_DPM_RGN_PARSER_IDLE 0xAD002011
+MKTC_ST(MKTC_RH_DPM_RGN_PARSER_IDLE)
+#define MKTC_RH_NEXT_RGN_BASE 0xAD002012
+MKTC_ST(MKTC_RH_NEXT_RGN_BASE)
+#define MKTC_RH_OCC_EXIT 0xAD002013
+MKTC_ST(MKTC_RH_OCC_EXIT)
+#define MKTC_RH_STILL_RUNNING 0xAD002020
+MKTC_ST(MKTC_RH_STILL_RUNNING)
+#define MKTC_RH_CLEARMCI 0xAD002021
+MKTC_ST(MKTC_RH_CLEARMCI)
+#define MKTC_RH_EOR 0xAD002022
+MKTC_ST(MKTC_RH_EOR)
+#define MKTC_RENDERHALT_END 0xAD002030
+MKTC_ST(MKTC_RENDERHALT_END)
+
+#define MKTC_FIND3D_POWERREQUEST 0xAD002100
+MKTC_ST(MKTC_FIND3D_POWERREQUEST)
+
+#define MKTC_FIND2D_POWERREQUEST 0xAD002200
+MKTC_ST(MKTC_FIND2D_POWERREQUEST)
+
+#define MKTC_UKERNEL_INIT 0xAD002300
+MKTC_ST(MKTC_UKERNEL_INIT)
+#define MKTC_UKERNEL_INIT_DCS_COMPLETE 0xAD002301
+MKTC_ST(MKTC_UKERNEL_INIT_DCS_COMPLETE)
+#define MKTC_UKERNEL_INIT_VDMKICK_COMPLETE 0xAD002303
+MKTC_ST(MKTC_UKERNEL_INIT_VDMKICK_COMPLETE)
+
+#define MKTC_KICKTRANSFERRENDER_START 0xAD002400
+MKTC_ST(MKTC_KICKTRANSFERRENDER_START)
+#define MKTC_KICKTRANSFERRENDER_ISP_START 0xAD002401
+MKTC_ST(MKTC_KICKTRANSFERRENDER_ISP_START)
+#define MKTC_KICKTRANSFERRENDER_END 0xAD002402
+MKTC_ST(MKTC_KICKTRANSFERRENDER_END)
+#define MKTC_DUMMYPROCTRANSFER 0xAD002403
+MKTC_ST(MKTC_DUMMYPROCTRANSFER)
+#define MKTC_KTR_TQFENCE 0xAD002404
+MKTC_ST(MKTC_KTR_TQFENCE)
+#define MKTC_KICKTRANSFERRENDER_PID 0xAD002405
+MKTC_ST(MKTC_KICKTRANSFERRENDER_PID)
+
+#define MKTC_HOSTKICK_CLEANUP_RT 0xAD002500
+MKTC_ST(MKTC_HOSTKICK_CLEANUP_RT)
+#define MKTC_HOSTKICK_CLEANUP_RC 0xAD002501
+MKTC_ST(MKTC_HOSTKICK_CLEANUP_RC)
+#define MKTC_HOSTKICK_CLEANUP_TC 0xAD002502
+MKTC_ST(MKTC_HOSTKICK_CLEANUP_TC)
+#define MKTC_HOSTKICK_CLEANUP_2DC 0xAD002503
+MKTC_ST(MKTC_HOSTKICK_CLEANUP_2DC)
+#define MKTC_HOSTKICK_CLEANUP_PB 0xAD002504
+MKTC_ST(MKTC_HOSTKICK_CLEANUP_PB)
+#define MKTC_HOSTKICK_GETMISCINFO 0xAD002505
+MKTC_ST(MKTC_HOSTKICK_GETMISCINFO)
+#define MKTC_HOSTKICK_DATABREAKPOINT 0xAD002506
+MKTC_ST(MKTC_HOSTKICK_DATABREAKPOINT)
+#define MKTC_HOSTKICK_SETHWPERFSTATUS 0xAD002507
+MKTC_ST(MKTC_HOSTKICK_SETHWPERFSTATUS)
+
+#define MKTC_ZEROPC 0xAD002600
+MKTC_ST(MKTC_ZEROPC)
+
+#define MKTC_ASSERT_FAIL 0xAD002700
+MKTC_ST(MKTC_ASSERT_FAIL)
+
+#define MKTC_SDLB_ILLEGAL 0xAD002800
+MKTC_ST(MKTC_SDLB_ILLEGAL)
+
+#define MKTC_SPMEVENT_OUTOFMEM 0xAD002901
+MKTC_ST(MKTC_SPMEVENT_OUTOFMEM)
+#define MKTC_SPMEVENT_TATERMINATE 0xAD002902
+MKTC_ST(MKTC_SPMEVENT_TATERMINATE)
+#define MKTC_SPMEVENT_END 0xAD002904
+MKTC_ST(MKTC_SPMEVENT_END)
+
+#define MKTC_SPMLB_OUTOFMEM 0xAD002981
+MKTC_ST(MKTC_SPMLB_OUTOFMEM)
+#define MKTC_SPMLB_TATERMINATE 0xAD002982
+MKTC_ST(MKTC_SPMLB_TATERMINATE)
+#define MKTC_SPMLB_SPMRENDERFINSHED 0xAD002983
+MKTC_ST(MKTC_SPMLB_SPMRENDERFINSHED)
+#define MKTC_SPMLB_END 0xAD002985
+MKTC_ST(MKTC_SPMLB_END)
+
+#define MKTC_SPM_CHECK_MT_DEADLOCK 0xAD002991
+MKTC_ST(MKTC_SPM_CHECK_MT_DEADLOCK)
+#define MKTC_SPM_CHECK_GLOBAL_DEADLOCK 0xAD002992
+MKTC_ST(MKTC_SPM_CHECK_GLOBAL_DEADLOCK)
+#define MKTC_SPM_RESERVE_ADDED 0xAD002993
+MKTC_ST(MKTC_SPM_RESERVE_ADDED)
+#define MKTC_SPM_FORCE_GLOBAL_OOM_FAILED 0xAD00299E
+MKTC_ST(MKTC_SPM_FORCE_GLOBAL_OOM_FAILED)
+#define MKTC_SPM_DEADLOCK_MEM_FAILED 0xAD00299F
+MKTC_ST(MKTC_SPM_DEADLOCK_MEM_FAILED)
+
+#define MKTC_IBC_ILLEGAL 0xAD002A00
+MKTC_ST(MKTC_IBC_ILLEGAL)
+
+#define MKTC_HWP_CLEARCOUNTERS 0xAD002B00
+MKTC_ST(MKTC_HWP_CLEARCOUNTERS)
+
+#define MKTC_TA_FRAMENUM 0xAD002C00
+MKTC_ST(MKTC_TA_FRAMENUM)
+#define MKTC_3D_FRAMENUM 0xAD002C01
+MKTC_ST(MKTC_3D_FRAMENUM)
+#define MKTC_SPM3D_FRAMENUM 0xAD002C02
+MKTC_ST(MKTC_SPM3D_FRAMENUM)
+
+#define MKTC_HKTA_RENDERCONTEXT 0xAD002D00
+MKTC_ST(MKTC_HKTA_RENDERCONTEXT)
+#define MKTC_IDLECORE_REFCOUNT_FAIL 0xAD002E00
+MKTC_ST(MKTC_IDLECORE_REFCOUNT_FAIL)
+
+#define MKTC_MCISTATE_NOT_CLEARED 0xAD002F00
+MKTC_ST(MKTC_MCISTATE_NOT_CLEARED)
+
+#define MKTC_LOWERED_TO_PDS_THRESHOLD 0xAD003000
+MKTC_ST(MKTC_LOWERED_TO_PDS_THRESHOLD)
+#define MKTC_REDUCE_MAX_VTX_PARTITIONS 0xAD003001
+MKTC_ST(MKTC_REDUCE_MAX_VTX_PARTITIONS)
+#define MKTC_KTAOVERRIDE_MAX_VTX_PARTITIONS 0xAD003002
+MKTC_ST(MKTC_KTAOVERRIDE_MAX_VTX_PARTITIONS)
+#define MKTC_KTANOOVERRIDE_MAX_VTX_PARTITIONS 0xAD003003
+MKTC_ST(MKTC_KTANOOVERRIDE_MAX_VTX_PARTITIONS)
+
+#define MKTC_IPRB_NORENDERDETAILS 0xAD003010
+MKTC_ST(MKTC_IPRB_NORENDERDETAILS)
+#define MKTC_IPRB_HAVERENDERDETAILS 0xAD003011
+MKTC_ST(MKTC_IPRB_HAVERENDERDETAILS)
+
+#define MKTC_RENDER_OUT_OF_ORDER 0xAD003020
+MKTC_ST(MKTC_RENDER_OUT_OF_ORDER)
+#define MKTC_RENDER_NOT_OUT_OF_ORDER 0xAD003021
+MKTC_ST(MKTC_RENDER_NOT_OUT_OF_ORDER)
+
+#define MKTC_ZLS_IDLE_BEGIN 0xAD003030
+MKTC_ST(MKTC_ZLS_IDLE_BEGIN)
+#define MKTC_ZLS_ISP_CLK_GATING_EN 0xAD003031
+MKTC_ST(MKTC_ZLS_ISP_CLK_GATING_EN)
+#define MKTC_ZLS_IDLE_END 0xAD003032
+MKTC_ST(MKTC_ZLS_IDLE_END)
+
+#endif /* __SGX_UKERNEL_STATUS_CODES_H__ */
+
+/******************************************************************************
+ End of file (sgx_ukernel_status_codes.h)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/sgxapi_km.h b/drivers/gpu/pvr/sgxapi_km.h
new file mode 100644
index 0000000..eaf45eb
--- /dev/null
+++ b/drivers/gpu/pvr/sgxapi_km.h
@@ -0,0 +1,500 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+******************************************************************************/
+
+#ifndef __SGXAPI_KM_H__
+#define __SGXAPI_KM_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "sgxdefs.h"
+
+#if defined(__linux__) && !defined(USE_CODE)
+ #if defined(__KERNEL__)
+ #include <asm/unistd.h>
+ #else
+ #include <unistd.h>
+ #endif
+#endif
+
+/******************************************************************************
+ Some defines...
+******************************************************************************/
+
+/* SGX Heap IDs, note: not all heaps are available to clients */
+#define SGX_UNDEFINED_HEAP_ID (~0LU)
+#define SGX_GENERAL_HEAP_ID 0
+#define SGX_TADATA_HEAP_ID 1
+#define SGX_KERNEL_CODE_HEAP_ID 2
+#define SGX_KERNEL_DATA_HEAP_ID 3
+#define SGX_PIXELSHADER_HEAP_ID 4
+#define SGX_VERTEXSHADER_HEAP_ID 5
+#define SGX_PDSPIXEL_CODEDATA_HEAP_ID 6
+#define SGX_PDSVERTEX_CODEDATA_HEAP_ID 7
+#define SGX_SYNCINFO_HEAP_ID 8
+#define SGX_SHARED_3DPARAMETERS_HEAP_ID 9
+#define SGX_PERCONTEXT_3DPARAMETERS_HEAP_ID 10
+#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+#define SGX_GENERAL_MAPPING_HEAP_ID 11
+#endif
+#if defined(SGX_FEATURE_2D_HARDWARE)
+#define SGX_2D_HEAP_ID 12
+#else
+#if defined(FIX_HW_BRN_26915)
+#define SGX_CGBUFFER_HEAP_ID 13
+#endif
+#endif
+#if defined(SUPPORT_MEMORY_TILING)
+#define SGX_VPB_TILED_HEAP_ID 14
+#endif
+
+#define SGX_MAX_HEAP_ID 15
+
+/*
+ * Keep SGX_3DPARAMETERS_HEAP_ID as TQ full custom
+ * shaders need it to select which heap to write
+ * their ISP controll stream to.
+ */
+#if (defined(SUPPORT_PERCONTEXT_PB) || defined(SUPPORT_HYBRID_PB))
+#define SGX_3DPARAMETERS_HEAP_ID SGX_PERCONTEXT_3DPARAMETERS_HEAP_ID
+#else
+#define SGX_3DPARAMETERS_HEAP_ID SGX_SHARED_3DPARAMETERS_HEAP_ID
+#endif
+/* Define for number of bytes between consecutive code base registers */
+#if defined(SGX543) || defined(SGX544) || defined(SGX554)
+#define SGX_USE_CODE_SEGMENT_RANGE_BITS 23
+#else
+#define SGX_USE_CODE_SEGMENT_RANGE_BITS 19
+#endif
+
+#define SGX_MAX_TA_STATUS_VALS 32
+#define SGX_MAX_3D_STATUS_VALS 4
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+/* sync info structure array size */
+#define SGX_MAX_TA_DST_SYNCS 1
+#define SGX_MAX_TA_SRC_SYNCS 1
+#define SGX_MAX_3D_SRC_SYNCS 4
+/* note: there is implicitly 1 3D Dst Sync */
+#else
+/* sync info structure array size */
+#define SGX_MAX_SRC_SYNCS_TA 8
+#define SGX_MAX_DST_SYNCS_TA 1
+/* note: there is implicitly 1 3D Dst Sync */
+#define SGX_MAX_SRC_SYNCS_TQ 8
+#define SGX_MAX_DST_SYNCS_TQ 1
+#endif
+
+
+#if defined(SGX_FEATURE_EXTENDED_PERF_COUNTERS)
+#define PVRSRV_SGX_HWPERF_NUM_COUNTERS 8
+#define PVRSRV_SGX_HWPERF_NUM_MISC_COUNTERS 11
+#else
+#define PVRSRV_SGX_HWPERF_NUM_COUNTERS 9
+#define PVRSRV_SGX_HWPERF_NUM_MISC_COUNTERS 8
+#endif /* SGX543 */
+
+#define PVRSRV_SGX_HWPERF_INVALID 0x1
+
+#define PVRSRV_SGX_HWPERF_TRANSFER 0x2
+#define PVRSRV_SGX_HWPERF_TA 0x3
+#define PVRSRV_SGX_HWPERF_3D 0x4
+#define PVRSRV_SGX_HWPERF_2D 0x5
+#define PVRSRV_SGX_HWPERF_POWER 0x6
+#define PVRSRV_SGX_HWPERF_PERIODIC 0x7
+#define PVRSRV_SGX_HWPERF_3DSPM 0x8
+
+#define PVRSRV_SGX_HWPERF_MK_EVENT 0x101
+#define PVRSRV_SGX_HWPERF_MK_TA 0x102
+#define PVRSRV_SGX_HWPERF_MK_3D 0x103
+#define PVRSRV_SGX_HWPERF_MK_2D 0x104
+#define PVRSRV_SGX_HWPERF_MK_TRANSFER_DUMMY 0x105
+#define PVRSRV_SGX_HWPERF_MK_TA_DUMMY 0x106
+#define PVRSRV_SGX_HWPERF_MK_3D_DUMMY 0x107
+#define PVRSRV_SGX_HWPERF_MK_2D_DUMMY 0x108
+#define PVRSRV_SGX_HWPERF_MK_TA_LOCKUP 0x109
+#define PVRSRV_SGX_HWPERF_MK_3D_LOCKUP 0x10A
+#define PVRSRV_SGX_HWPERF_MK_2D_LOCKUP 0x10B
+
+#define PVRSRV_SGX_HWPERF_TYPE_STARTEND_BIT 28
+#define PVRSRV_SGX_HWPERF_TYPE_OP_MASK ((1UL << PVRSRV_SGX_HWPERF_TYPE_STARTEND_BIT) - 1)
+#define PVRSRV_SGX_HWPERF_TYPE_OP_START (0UL << PVRSRV_SGX_HWPERF_TYPE_STARTEND_BIT)
+#define PVRSRV_SGX_HWPERF_TYPE_OP_END (1Ul << PVRSRV_SGX_HWPERF_TYPE_STARTEND_BIT)
+
+#define PVRSRV_SGX_HWPERF_TYPE_TRANSFER_START (PVRSRV_SGX_HWPERF_TRANSFER | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_TRANSFER_END (PVRSRV_SGX_HWPERF_TRANSFER | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_TA_START (PVRSRV_SGX_HWPERF_TA | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_TA_END (PVRSRV_SGX_HWPERF_TA | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_3D_START (PVRSRV_SGX_HWPERF_3D | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_3D_END (PVRSRV_SGX_HWPERF_3D | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_2D_START (PVRSRV_SGX_HWPERF_2D | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_2D_END (PVRSRV_SGX_HWPERF_2D | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_POWER_START (PVRSRV_SGX_HWPERF_POWER | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_POWER_END (PVRSRV_SGX_HWPERF_POWER | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_PERIODIC (PVRSRV_SGX_HWPERF_PERIODIC)
+#define PVRSRV_SGX_HWPERF_TYPE_3DSPM_START (PVRSRV_SGX_HWPERF_3DSPM | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_3DSPM_END (PVRSRV_SGX_HWPERF_3DSPM | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_TRANSFER_DUMMY_START (PVRSRV_SGX_HWPERF_MK_TRANSFER_DUMMY | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_TRANSFER_DUMMY_END (PVRSRV_SGX_HWPERF_MK_TRANSFER_DUMMY | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_TA_DUMMY_START (PVRSRV_SGX_HWPERF_MK_TA_DUMMY | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_TA_DUMMY_END (PVRSRV_SGX_HWPERF_MK_TA_DUMMY | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_3D_DUMMY_START (PVRSRV_SGX_HWPERF_MK_3D_DUMMY | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_3D_DUMMY_END (PVRSRV_SGX_HWPERF_MK_3D_DUMMY | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_2D_DUMMY_START (PVRSRV_SGX_HWPERF_MK_2D_DUMMY | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_2D_DUMMY_END (PVRSRV_SGX_HWPERF_MK_2D_DUMMY | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_TA_LOCKUP (PVRSRV_SGX_HWPERF_MK_TA_LOCKUP)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_3D_LOCKUP (PVRSRV_SGX_HWPERF_MK_3D_LOCKUP)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_2D_LOCKUP (PVRSRV_SGX_HWPERF_MK_2D_LOCKUP)
+
+#define PVRSRV_SGX_HWPERF_TYPE_MK_EVENT_START (PVRSRV_SGX_HWPERF_MK_EVENT | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_EVENT_END (PVRSRV_SGX_HWPERF_MK_EVENT | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_TA_START (PVRSRV_SGX_HWPERF_MK_TA | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_TA_END (PVRSRV_SGX_HWPERF_MK_TA | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_3D_START (PVRSRV_SGX_HWPERF_MK_3D | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_3D_END (PVRSRV_SGX_HWPERF_MK_3D | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_2D_START (PVRSRV_SGX_HWPERF_MK_2D | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_2D_END (PVRSRV_SGX_HWPERF_MK_2D | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+
+#define PVRSRV_SGX_HWPERF_STATUS_OFF (0x0)
+#define PVRSRV_SGX_HWPERF_STATUS_RESET_COUNTERS (1UL << 0)
+#define PVRSRV_SGX_HWPERF_STATUS_GRAPHICS_ON (1UL << 1)
+#define PVRSRV_SGX_HWPERF_STATUS_PERIODIC_ON (1UL << 2)
+#define PVRSRV_SGX_HWPERF_STATUS_MK_EXECUTION_ON (1UL << 3)
+
+
+/*!
+ *****************************************************************************
+ * One entry in the HWPerf Circular Buffer.
+ *****************************************************************************/
+typedef struct _PVRSRV_SGX_HWPERF_CB_ENTRY_
+{
+ IMG_UINT32 ui32FrameNo;
+ IMG_UINT32 ui32PID;
+ IMG_UINT32 ui32RTData;
+ IMG_UINT32 ui32Type;
+ IMG_UINT32 ui32Ordinal;
+ IMG_UINT32 ui32Info;
+ IMG_UINT32 ui32Clocksx16;
+ /* NOTE: There should always be at least as many 3D cores as TA cores. */
+ IMG_UINT32 ui32Counters[SGX_FEATURE_MP_CORE_COUNT_3D][PVRSRV_SGX_HWPERF_NUM_COUNTERS];
+ IMG_UINT32 ui32MiscCounters[SGX_FEATURE_MP_CORE_COUNT_3D][PVRSRV_SGX_HWPERF_NUM_MISC_COUNTERS];
+} PVRSRV_SGX_HWPERF_CB_ENTRY;
+
+
+/*
+ Status values control structure
+*/
+typedef struct _CTL_STATUS_
+{
+ IMG_DEV_VIRTADDR sStatusDevAddr;
+ IMG_UINT32 ui32StatusValue;
+} CTL_STATUS;
+
+
+/*!
+ List of possible requests/commands to SGXGetMiscInfo()
+*/
+typedef enum _SGX_MISC_INFO_REQUEST_
+{
+ SGX_MISC_INFO_REQUEST_CLOCKSPEED = 0,
+ SGX_MISC_INFO_REQUEST_SGXREV,
+ SGX_MISC_INFO_REQUEST_DRIVER_SGXREV,
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+ SGX_MISC_INFO_REQUEST_MEMREAD,
+ SGX_MISC_INFO_REQUEST_MEMCOPY,
+#endif /* SUPPORT_SGX_EDM_MEMORY_DEBUG */
+ SGX_MISC_INFO_REQUEST_SET_HWPERF_STATUS,
+#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+ SGX_MISC_INFO_REQUEST_SET_BREAKPOINT,
+ SGX_MISC_INFO_REQUEST_POLL_BREAKPOINT,
+ SGX_MISC_INFO_REQUEST_RESUME_BREAKPOINT,
+#endif /* SGX_FEATURE_DATA_BREAKPOINTS */
+ SGX_MISC_INFO_DUMP_DEBUG_INFO,
+ SGX_MISC_INFO_PANIC,
+ SGX_MISC_INFO_REQUEST_SPM,
+ SGX_MISC_INFO_REQUEST_ACTIVEPOWER,
+ SGX_MISC_INFO_REQUEST_LOCKUPS,
+ SGX_MISC_INFO_REQUEST_FORCE_I16 = 0x7fff
+} SGX_MISC_INFO_REQUEST;
+
+
+/******************************************************************************
+ * Struct for passing SGX core rev/features from ukernel to driver.
+ * This is accessed from the kernel part of the driver and microkernel; it is
+ * only accessed in user space during buffer allocation in srvinit.
+ ******************************************************************************/
+typedef struct _PVRSRV_SGX_MISCINFO_FEATURES
+{
+ IMG_UINT32 ui32CoreRev; /*!< SGX Core revision from HW register */
+ IMG_UINT32 ui32CoreID; /*!< SGX Core ID from HW register */
+ IMG_UINT32 ui32DDKVersion; /*!< software DDK version */
+ IMG_UINT32 ui32DDKBuild; /*!< software DDK build no. */
+ IMG_UINT32 ui32CoreIdSW; /*!< software core version (ID), e.g. SGX535, SGX540 */
+ IMG_UINT32 ui32CoreRevSW; /*!< software core revision */
+ IMG_UINT32 ui32BuildOptions; /*!< build options bit-field */
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+ IMG_UINT32 ui32DeviceMemValue; /*!< device mem value read from ukernel */
+#endif
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+ IMG_DEV_VIRTADDR sDevVAEDMStatusBuffer; /*!< DevVAddr of the EDM status buffer */
+ IMG_PVOID pvEDMStatusBuffer; /*!< CPUVAddr of the EDM status buffer */
+#endif
+} PVRSRV_SGX_MISCINFO_FEATURES;
+
+
+/******************************************************************************
+ * Struct for getting lock-up stats from the kernel driver
+ ******************************************************************************/
+typedef struct _PVRSRV_SGX_MISCINFO_LOCKUPS
+{
+ IMG_UINT32 ui32HostDetectedLockups; /*!< Host timer detected lockups */
+ IMG_UINT32 ui32uKernelDetectedLockups; /*!< Microkernel detected lockups */
+} PVRSRV_SGX_MISCINFO_LOCKUPS;
+
+
+/******************************************************************************
+ * Struct for getting lock-up stats from the kernel driver
+ ******************************************************************************/
+typedef struct _PVRSRV_SGX_MISCINFO_ACTIVEPOWER
+{
+ IMG_UINT32 ui32NumActivePowerEvents; /*!< active power events */
+} PVRSRV_SGX_MISCINFO_ACTIVEPOWER;
+
+
+/******************************************************************************
+ * Struct for getting SPM stats fro the kernel driver
+ ******************************************************************************/
+typedef struct _PVRSRV_SGX_MISCINFO_SPM
+{
+ IMG_HANDLE hRTDataSet; /*!< render target data set handle returned from SGXAddRenderTarget */
+ IMG_UINT32 ui32NumOutOfMemSignals; /*!< Number of Out of Mem Signals */
+ IMG_UINT32 ui32NumSPMRenders; /*!< Number of SPM renders */
+} PVRSRV_SGX_MISCINFO_SPM;
+
+
+#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+/*!
+ ******************************************************************************
+ * Structure for SGX break points control
+ *****************************************************************************/
+typedef struct _SGX_BREAKPOINT_INFO
+{
+ /* set/clear BP boolean */
+ IMG_BOOL bBPEnable;
+ /* Index of BP to set */
+ IMG_UINT32 ui32BPIndex;
+ /* On which DataMaster(s) should the breakpoint fire? */
+ IMG_UINT32 ui32DataMasterMask;
+ /* DevVAddr of BP to set */
+ IMG_DEV_VIRTADDR sBPDevVAddr, sBPDevVAddrEnd;
+ /* Whether or not the desired breakpoint will be trapped */
+ IMG_BOOL bTrapped;
+ /* Will the requested breakpoint fire for reads? */
+ IMG_BOOL bRead;
+ /* Will the requested breakpoint fire for writes? */
+ IMG_BOOL bWrite;
+ /* Has a breakpoint been trapped? */
+ IMG_BOOL bTrappedBP;
+ /* Extra information recorded about a trapped breakpoint */
+ IMG_UINT32 ui32CoreNum;
+ IMG_DEV_VIRTADDR sTrappedBPDevVAddr;
+ IMG_UINT32 ui32TrappedBPBurstLength;
+ IMG_BOOL bTrappedBPRead;
+ IMG_UINT32 ui32TrappedBPDataMaster;
+ IMG_UINT32 ui32TrappedBPTag;
+} SGX_BREAKPOINT_INFO;
+#endif /* SGX_FEATURE_DATA_BREAKPOINTS */
+
+
+/*!
+ ******************************************************************************
+ * Structure for setting the hardware performance status
+ *****************************************************************************/
+typedef struct _PVRSRV_SGX_MISCINFO_SET_HWPERF_STATUS
+{
+ /* See PVRSRV_SGX_HWPERF_STATUS_* */
+ IMG_UINT32 ui32NewHWPerfStatus;
+
+ #if defined(SGX_FEATURE_EXTENDED_PERF_COUNTERS)
+ /* Specifies the HW's active group selectors */
+ IMG_UINT32 aui32PerfGroup[PVRSRV_SGX_HWPERF_NUM_COUNTERS];
+ /* Specifies the HW's active bit selectors */
+ IMG_UINT32 aui32PerfBit[PVRSRV_SGX_HWPERF_NUM_COUNTERS];
+ #else
+ /* Specifies the HW's active group */
+ IMG_UINT32 ui32PerfGroup;
+ #endif /* SGX_FEATURE_EXTENDED_PERF_COUNTERS */
+} PVRSRV_SGX_MISCINFO_SET_HWPERF_STATUS;
+
+
+/*!
+ ******************************************************************************
+ * Structure for misc SGX commands in services
+ *****************************************************************************/
+typedef struct _SGX_MISC_INFO_
+{
+ SGX_MISC_INFO_REQUEST eRequest; /*!< Command request to SGXGetMiscInfo() */
+ IMG_UINT32 ui32Padding;
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+ IMG_DEV_VIRTADDR sDevVAddrSrc; /*!< dev virtual addr for mem read */
+ IMG_DEV_VIRTADDR sDevVAddrDest; /*!< dev virtual addr for mem write */
+ IMG_HANDLE hDevMemContext; /*!< device memory context for mem debug */
+#endif
+ union
+ {
+ IMG_UINT32 reserved; /*!< Unused: ensures valid code in the case everything else is compiled out */
+ PVRSRV_SGX_MISCINFO_FEATURES sSGXFeatures;
+ IMG_UINT32 ui32SGXClockSpeed;
+ PVRSRV_SGX_MISCINFO_ACTIVEPOWER sActivePower;
+ PVRSRV_SGX_MISCINFO_LOCKUPS sLockups;
+ PVRSRV_SGX_MISCINFO_SPM sSPM;
+#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+ SGX_BREAKPOINT_INFO sSGXBreakpointInfo;
+#endif
+ PVRSRV_SGX_MISCINFO_SET_HWPERF_STATUS sSetHWPerfStatus;
+ } uData;
+} SGX_MISC_INFO;
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+/*
+ * The largest number of source sync objects that can be associated with a blit
+ * command. Allows for src, pattern, and mask
+ */
+#define PVRSRV_MAX_BLT_SRC_SYNCS 3
+#endif
+
+
+#define SGX_KICKTA_DUMPBITMAP_MAX_NAME_LENGTH 256
+
+/*
+ Structure for dumping bitmaps
+*/
+typedef struct _SGX_KICKTA_DUMPBITMAP_
+{
+ IMG_DEV_VIRTADDR sDevBaseAddr;
+ IMG_UINT32 ui32Flags;
+ IMG_UINT32 ui32Width;
+ IMG_UINT32 ui32Height;
+ IMG_UINT32 ui32Stride;
+ IMG_UINT32 ui32PDUMPFormat;
+ IMG_UINT32 ui32BytesPP;
+ IMG_CHAR pszName[SGX_KICKTA_DUMPBITMAP_MAX_NAME_LENGTH];
+} SGX_KICKTA_DUMPBITMAP, *PSGX_KICKTA_DUMPBITMAP;
+
+#define PVRSRV_SGX_PDUMP_CONTEXT_MAX_BITMAP_ARRAY_SIZE (16)
+
+/*!
+ ******************************************************************************
+ * Data required only when dumping parameters
+ *****************************************************************************/
+typedef struct _PVRSRV_SGX_PDUMP_CONTEXT_
+{
+ /* cache control word for micro kernel cache flush/invalidates */
+ IMG_UINT32 ui32CacheControl;
+
+} PVRSRV_SGX_PDUMP_CONTEXT;
+
+
+#if !defined (SUPPORT_SID_INTERFACE)
+typedef struct _SGX_KICKTA_DUMP_ROFF_
+{
+ IMG_HANDLE hKernelMemInfo; /*< Buffer handle */
+ IMG_UINT32 uiAllocIndex; /*< Alloc index for LDDM */
+ IMG_UINT32 ui32Offset; /*< Byte offset to value to dump */
+ IMG_UINT32 ui32Value; /*< Actual value to dump */
+ IMG_PCHAR pszName; /*< Name of buffer */
+} SGX_KICKTA_DUMP_ROFF, *PSGX_KICKTA_DUMP_ROFF;
+#endif
+
+#if defined (SUPPORT_SID_INTERFACE)
+typedef struct _SGX_KICKTA_DUMP_BUFFER_KM_
+#else
+typedef struct _SGX_KICKTA_DUMP_BUFFER_
+#endif
+{
+ IMG_UINT32 ui32SpaceUsed;
+ IMG_UINT32 ui32Start; /*< Byte offset of start to dump */
+ IMG_UINT32 ui32End; /*< Byte offset of end of dump (non-inclusive) */
+ IMG_UINT32 ui32BufferSize; /*< Size of buffer */
+ IMG_UINT32 ui32BackEndLength; /*< Size of back end portion, if End < Start */
+ IMG_UINT32 uiAllocIndex;
+ IMG_HANDLE hKernelMemInfo; /*< MemInfo handle for the circular buffer */
+ IMG_PVOID pvLinAddr;
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ IMG_HANDLE hCtrlKernelMemInfo; /*< MemInfo handle for the control structure of the
+ circular buffer */
+ IMG_DEV_VIRTADDR sCtrlDevVAddr; /*< Device virtual address of the memory in the
+ control structure to be checked */
+#endif
+ IMG_PCHAR pszName; /*< Name of buffer */
+#if defined (SUPPORT_SID_INTERFACE)
+} SGX_KICKTA_DUMP_BUFFER_KM, *PSGX_KICKTA_DUMP_BUFFER_KM;
+#else
+} SGX_KICKTA_DUMP_BUFFER, *PSGX_KICKTA_DUMP_BUFFER;
+#endif
+
+#if !defined (SUPPORT_SID_INTERFACE)
+#ifdef PDUMP
+/*
+ PDUMP version of above kick structure
+*/
+typedef struct _SGX_KICKTA_PDUMP_
+{
+ // Bitmaps to dump
+ PSGX_KICKTA_DUMPBITMAP psPDumpBitmapArray;
+ IMG_UINT32 ui32PDumpBitmapSize;
+
+ // Misc buffers to dump (e.g. TA, PDS etc..)
+ PSGX_KICKTA_DUMP_BUFFER psBufferArray;
+ IMG_UINT32 ui32BufferArraySize;
+
+ // Roffs to dump
+ PSGX_KICKTA_DUMP_ROFF psROffArray;
+ IMG_UINT32 ui32ROffArraySize;
+} SGX_KICKTA_PDUMP, *PSGX_KICKTA_PDUMP;
+#endif /* PDUMP */
+#endif /* #if !defined (SUPPORT_SID_INTERFACE) */
+
+#if defined(TRANSFER_QUEUE)
+#if defined(SGX_FEATURE_2D_HARDWARE)
+/* Maximum size of ctrl stream for 2d blit command (in 32 bit words) */
+#define SGX_MAX_2D_BLIT_CMD_SIZE 26
+#define SGX_MAX_2D_SRC_SYNC_OPS 3
+#endif
+#define SGX_MAX_TRANSFER_STATUS_VALS 2
+#define SGX_MAX_TRANSFER_SYNC_OPS 5
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* __SGXAPI_KM_H__ */
+
+/******************************************************************************
+ End of file (sgxapi_km.h)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/sgxdefs.h b/drivers/gpu/pvr/sgxdefs.h
new file mode 100644
index 0000000..b3a2583
--- /dev/null
+++ b/drivers/gpu/pvr/sgxdefs.h
@@ -0,0 +1,90 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef _SGXDEFS_H_
+#define _SGXDEFS_H_
+
+#include "sgxerrata.h"
+#include "sgxfeaturedefs.h"
+
+#if defined(SGX520)
+#include "sgx520defs.h"
+#else
+#if defined(SGX530)
+#include "sgx530defs.h"
+#else
+#if defined(SGX535)
+#include "sgx535defs.h"
+#else
+#if defined(SGX535_V1_1)
+#include "sgx535defs.h"
+#else
+#if defined(SGX540)
+#include "sgx540defs.h"
+#else
+#if defined(SGX543)
+#if defined(FIX_HW_BRN_29954)
+#include "sgx543_v1.164defs.h"
+#else
+#include "sgx543defs.h"
+#endif
+#else
+#if defined(SGX544)
+#include "sgx544defs.h"
+#else
+#if defined(SGX545)
+#include "sgx545defs.h"
+#else
+#if defined(SGX531)
+#include "sgx531defs.h"
+#else
+#if defined(SGX554)
+#include "sgx554defs.h"
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+
+#if defined(SGX_FEATURE_MP)
+#if defined(SGX554)
+#include "sgxmpplusdefs.h"
+#else
+#include "sgxmpdefs.h"
+#endif
+#else
+#if defined(SGX_FEATURE_SYSTEM_CACHE)
+#include "mnemedefs.h"
+#endif
+#endif
+
+#endif
+
diff --git a/drivers/gpu/pvr/sgxerrata.h b/drivers/gpu/pvr/sgxerrata.h
new file mode 100644
index 0000000..05fd45f
--- /dev/null
+++ b/drivers/gpu/pvr/sgxerrata.h
@@ -0,0 +1,714 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef _SGXERRATA_KM_H_
+#define _SGXERRATA_KM_H_
+
+#if defined(SGX520) && !defined(SGX_CORE_DEFINED)
+
+ #define SGX_CORE_REV_HEAD 0
+ #if defined(USE_SGX_CORE_REV_HEAD)
+
+ #define SGX_CORE_REV SGX_CORE_REV_HEAD
+ #endif
+
+ #if SGX_CORE_REV == 100
+ #define FIX_HW_BRN_28889
+ #else
+ #if SGX_CORE_REV == 111
+ #else
+ #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+ #else
+ #error "sgxerrata.h: SGX520 Core Revision unspecified"
+ #endif
+ #endif
+ #endif
+
+ #define SGX_CORE_DEFINED
+#endif
+
+#if defined(SGX530) && !defined(SGX_CORE_DEFINED)
+
+ #define SGX_CORE_REV_HEAD 0
+ #if defined(USE_SGX_CORE_REV_HEAD)
+
+ #define SGX_CORE_REV SGX_CORE_REV_HEAD
+ #endif
+
+ #if SGX_CORE_REV == 110
+ #define FIX_HW_BRN_22934
+ #define FIX_HW_BRN_28889
+ #else
+ #if SGX_CORE_REV == 111
+ #define FIX_HW_BRN_22934
+ #define FIX_HW_BRN_28889
+ #else
+ #if SGX_CORE_REV == 1111
+ #define FIX_HW_BRN_22934
+ #define FIX_HW_BRN_28889
+ #else
+ #if SGX_CORE_REV == 120
+ #define FIX_HW_BRN_22934
+ #define FIX_HW_BRN_28889
+ #else
+ #if SGX_CORE_REV == 121
+ #define FIX_HW_BRN_22934
+ #define FIX_HW_BRN_28889
+ #else
+ #if SGX_CORE_REV == 125
+ #define FIX_HW_BRN_22934
+ #define FIX_HW_BRN_28889
+ #else
+ #if SGX_CORE_REV == 130
+ #define FIX_HW_BRN_22934
+ #define FIX_HW_BRN_28889
+ #else
+ #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+ #else
+ #error "sgxerrata.h: SGX530 Core Revision unspecified"
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+#endif
+ #endif
+
+ #define SGX_CORE_DEFINED
+#endif
+
+#if defined(SGX531) && !defined(SGX_CORE_DEFINED)
+
+ #define SGX_CORE_REV_HEAD 0
+ #if defined(USE_SGX_CORE_REV_HEAD)
+
+ #define SGX_CORE_REV SGX_CORE_REV_HEAD
+ #endif
+
+ #if SGX_CORE_REV == 101
+ #define FIX_HW_BRN_26620
+ #define FIX_HW_BRN_28011
+ #define FIX_HW_BRN_34028
+ #else
+ #if SGX_CORE_REV == 110
+ #define FIX_HW_BRN_34028
+ #else
+ #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+ #else
+ #error "sgxerrata.h: SGX531 Core Revision unspecified"
+ #endif
+ #endif
+ #endif
+
+ #define SGX_CORE_DEFINED
+#endif
+
+#if (defined(SGX535) || defined(SGX535_V1_1)) && !defined(SGX_CORE_DEFINED)
+
+ #define SGX_CORE_REV_HEAD 0
+ #if defined(USE_SGX_CORE_REV_HEAD)
+
+ #define SGX_CORE_REV SGX_CORE_REV_HEAD
+ #endif
+
+ #if SGX_CORE_REV == 112
+ #define FIX_HW_BRN_23281
+ #define FIX_HW_BRN_23410
+ #define FIX_HW_BRN_22693
+ #define FIX_HW_BRN_22934
+ #define FIX_HW_BRN_22997
+ #define FIX_HW_BRN_23030
+ #else
+ #if SGX_CORE_REV == 113
+ #define FIX_HW_BRN_22934
+ #define FIX_HW_BRN_23281
+ #define FIX_HW_BRN_23944
+ #define FIX_HW_BRN_23410
+ #else
+ #if SGX_CORE_REV == 121
+ #define FIX_HW_BRN_22934
+ #define FIX_HW_BRN_23944
+ #define FIX_HW_BRN_23410
+ #else
+ #if SGX_CORE_REV == 126
+ #define FIX_HW_BRN_22934
+ #else
+ #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+ #else
+ #error "sgxerrata.h: SGX535 Core Revision unspecified"
+
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+
+ #define SGX_CORE_DEFINED
+#endif
+
+#if defined(SGX540) && !defined(SGX_CORE_DEFINED)
+
+ #define SGX_CORE_REV_HEAD 0
+ #if defined(USE_SGX_CORE_REV_HEAD)
+
+ #define SGX_CORE_REV SGX_CORE_REV_HEAD
+ #endif
+
+ #if SGX_CORE_REV == 101
+ #define FIX_HW_BRN_25499
+ #define FIX_HW_BRN_25503
+ #define FIX_HW_BRN_26620
+ #define FIX_HW_BRN_28011
+ #define FIX_HW_BRN_34028
+ #else
+ #if SGX_CORE_REV == 110
+ #define FIX_HW_BRN_25503
+ #define FIX_HW_BRN_26620
+ #define FIX_HW_BRN_28011
+ #define FIX_HW_BRN_34028
+ #else
+ #if SGX_CORE_REV == 120
+ #define FIX_HW_BRN_26620
+ #define FIX_HW_BRN_28011
+ #define FIX_HW_BRN_34028
+ #else
+ #if SGX_CORE_REV == 121
+ #define FIX_HW_BRN_28011
+ #define FIX_HW_BRN_34028
+ #else
+ #if SGX_CORE_REV == 130
+ #define FIX_HW_BRN_34028
+ #else
+ #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+ #else
+ #error "sgxerrata.h: SGX540 Core Revision unspecified"
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+
+ #define SGX_CORE_DEFINED
+#endif
+
+#if defined(SGX541) && !defined(SGX_CORE_DEFINED)
+ #if defined(SGX_FEATURE_MP)
+
+ #define SGX_CORE_REV_HEAD 0
+ #if defined(USE_SGX_CORE_REV_HEAD)
+
+ #define SGX_CORE_REV SGX_CORE_REV_HEAD
+ #endif
+
+ #if SGX_CORE_REV == 100
+ #define FIX_HW_BRN_27270
+ #define FIX_HW_BRN_28011
+ #define FIX_HW_BRN_27510
+
+ #else
+ #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+ #else
+ #error "sgxerrata.h: SGX541 Core Revision unspecified"
+ #endif
+ #endif
+
+ #define SGX_CORE_DEFINED
+ #else
+ #error "sgxerrata.h: SGX541 only supports MP configs (SGX_FEATURE_MP)"
+ #endif
+#endif
+
+#if defined(SGX543) && !defined(SGX_CORE_DEFINED)
+
+ #define SGX_CORE_REV_HEAD 0
+ #if defined(USE_SGX_CORE_REV_HEAD)
+
+ #define SGX_CORE_REV SGX_CORE_REV_HEAD
+ #endif
+
+ #if SGX_CORE_REV == 113
+ #define FIX_HW_BRN_29954
+ #define FIX_HW_BRN_29997
+ #define FIX_HW_BRN_30954
+ #define FIX_HW_BRN_31093
+ #define FIX_HW_BRN_31195
+ #define FIX_HW_BRN_31272
+ #define FIX_HW_BRN_31278
+ #if defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_31559
+ #endif
+ #define FIX_HW_BRN_31620
+ #define FIX_HW_BRN_31780
+ #define FIX_HW_BRN_31542
+ #define FIX_HW_BRN_32044
+ #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_33657
+ #endif
+ #define FIX_HW_BRN_33920
+ #define FIX_HW_BRN_36513
+ #else
+ #if SGX_CORE_REV == 122
+ #define FIX_HW_BRN_29954
+ #define FIX_HW_BRN_29997
+ #define FIX_HW_BRN_30954
+ #define FIX_HW_BRN_31093
+ #define FIX_HW_BRN_31195
+ #define FIX_HW_BRN_31272
+ #define FIX_HW_BRN_31278
+ #if defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_31559
+ #endif
+ #define FIX_HW_BRN_31620
+ #define FIX_HW_BRN_31780
+ #define FIX_HW_BRN_31542
+ #define FIX_HW_BRN_32044
+ #define FIX_HW_BRN_32085
+ #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_33657
+ #endif
+ #define FIX_HW_BRN_33920
+ #define FIX_HW_BRN_36513
+
+ #else
+ #if SGX_CORE_REV == 1221
+ #define FIX_HW_BRN_29954
+ #define FIX_HW_BRN_31195
+ #define FIX_HW_BRN_31272
+ #define FIX_HW_BRN_31278
+ #if defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_31559
+ #endif
+ #define FIX_HW_BRN_31542
+ #define FIX_HW_BRN_31671
+ #define FIX_HW_BRN_31780
+ #define FIX_HW_BRN_32044
+ #define FIX_HW_BRN_32085
+ #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_33657
+ #endif
+ #define FIX_HW_BRN_33920
+ #define FIX_HW_BRN_36513
+
+ #else
+ #if SGX_CORE_REV == 140
+ #define FIX_HW_BRN_29954
+ #define FIX_HW_BRN_30954
+ #define FIX_HW_BRN_31093
+ #define FIX_HW_BRN_31195
+ #define FIX_HW_BRN_31272
+ #define FIX_HW_BRN_31278
+ #if defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_31559
+ #endif
+ #define FIX_HW_BRN_31620
+ #define FIX_HW_BRN_31780
+ #define FIX_HW_BRN_31542
+ #define FIX_HW_BRN_32044
+ #define FIX_HW_BRN_32085
+ #define FIX_HW_BRN_33920
+ #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_33657
+ #endif
+ #define FIX_HW_BRN_36513
+
+ #else
+ #if SGX_CORE_REV == 1401
+ #define FIX_HW_BRN_29954
+ #define FIX_HW_BRN_30954
+ #define FIX_HW_BRN_31195
+ #define FIX_HW_BRN_31272
+ #define FIX_HW_BRN_31278
+ #if defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_31559
+ #endif
+ #define FIX_HW_BRN_31620
+ #define FIX_HW_BRN_31542
+ #define FIX_HW_BRN_31780
+ #define FIX_HW_BRN_32044
+ #define FIX_HW_BRN_32085
+ #define FIX_HW_BRN_33920
+ #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_33657
+ #endif
+ #define FIX_HW_BRN_36513
+
+ #else
+ #if SGX_CORE_REV == 141
+ #define FIX_HW_BRN_29954
+ #if defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_31559
+ #endif
+ #define FIX_HW_BRN_31671
+ #define FIX_HW_BRN_31780
+ #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_33657
+ #endif
+ #define FIX_HW_BRN_36513
+
+ #else
+ #if SGX_CORE_REV == 142
+ #define FIX_HW_BRN_29954
+ #if defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_31559
+ #endif
+ #define FIX_HW_BRN_31671
+ #define FIX_HW_BRN_31780
+ #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_33657
+ #endif
+ #define FIX_HW_BRN_36513
+
+ #else
+ #if SGX_CORE_REV == 211
+ #define FIX_HW_BRN_31093
+ #define FIX_HW_BRN_31195
+ #define FIX_HW_BRN_31272
+ #define FIX_HW_BRN_31278
+ #if defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_31559
+ #endif
+ #define FIX_HW_BRN_31620
+ #define FIX_HW_BRN_31780
+ #define FIX_HW_BRN_31542
+ #define FIX_HW_BRN_32044
+ #define FIX_HW_BRN_32085
+ #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_33657
+ #endif
+ #define FIX_HW_BRN_33920
+ #define FIX_HW_BRN_36513
+
+ #else
+ #if SGX_CORE_REV == 2111
+ #define FIX_HW_BRN_30982
+ #define FIX_HW_BRN_31093
+ #define FIX_HW_BRN_31195
+ #define FIX_HW_BRN_31272
+ #define FIX_HW_BRN_31278
+ #if defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_31559
+ #endif
+ #define FIX_HW_BRN_31620
+ #define FIX_HW_BRN_31780
+ #define FIX_HW_BRN_31542
+ #define FIX_HW_BRN_32044
+ #define FIX_HW_BRN_32085
+ #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_33657
+ #endif
+ #define FIX_HW_BRN_33920
+ #define FIX_HW_BRN_36513
+
+ #else
+ #if SGX_CORE_REV == 213
+ #define FIX_HW_BRN_31272
+ #if defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_31559
+ #endif
+ #define FIX_HW_BRN_31671
+ #define FIX_HW_BRN_31780
+ #define FIX_HW_BRN_32085
+ #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_33657
+ #endif
+ #define FIX_HW_BRN_33920
+ #define FIX_HW_BRN_36513
+
+ #else
+ #if SGX_CORE_REV == 216
+ #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_33657
+ #endif
+ #define FIX_HW_BRN_36513
+ #else
+ #if SGX_CORE_REV == 302
+ #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_33657
+ #endif
+ #else
+ #if SGX_CORE_REV == 303
+ #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_33657
+ #endif
+ #else
+ #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+ #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_33657
+ #endif
+ #else
+ #error "sgxerrata.h: SGX543 Core Revision unspecified"
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+
+ #define SGX_CORE_DEFINED
+#endif
+
+#if defined(SGX544) && !defined(SGX_CORE_DEFINED)
+
+ #define SGX_CORE_REV_HEAD 0
+ #if defined(USE_SGX_CORE_REV_HEAD)
+
+ #define SGX_CORE_REV SGX_CORE_REV_HEAD
+ #endif
+
+ #if SGX_CORE_REV == 100
+ #if defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_31559
+ #endif
+ #else
+ #if SGX_CORE_REV == 102
+ #define FIX_HW_BRN_29954
+ #define FIX_HW_BRN_31272
+ #if defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_31559
+ #endif
+ #define FIX_HW_BRN_31780
+ #define FIX_HW_BRN_32085
+ #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_33657
+ #endif
+ #define FIX_HW_BRN_33920
+ #if defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_36513
+ #endif
+ #else
+ #if SGX_CORE_REV == 103
+ #define FIX_HW_BRN_29954
+ #define FIX_HW_BRN_31272
+ #if defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_31559
+ #endif
+ #define FIX_HW_BRN_31780
+ #define FIX_HW_BRN_32085
+ #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_33657
+ #endif
+ #define FIX_HW_BRN_33920
+ #define FIX_HW_BRN_36513
+ #else
+ #if SGX_CORE_REV == 104
+ #define FIX_HW_BRN_29954
+ #define FIX_HW_BRN_31093
+ #define FIX_HW_BRN_31195
+ #define FIX_HW_BRN_31272
+ #define FIX_HW_BRN_31278
+ #if defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_31559
+ #endif
+ #define FIX_HW_BRN_31542
+ #define FIX_HW_BRN_31620
+ #define FIX_HW_BRN_31671
+ #define FIX_HW_BRN_31780
+ #define FIX_HW_BRN_32044
+ #define FIX_HW_BRN_32085
+ #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_33657
+ #endif
+ #define FIX_HW_BRN_33920
+ #define FIX_HW_BRN_36513
+ #else
+ #if SGX_CORE_REV == 105
+ #if defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_31559
+ #endif
+ #define FIX_HW_BRN_31780
+ #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_33657
+ #endif
+ #define FIX_HW_BRN_33920
+ #define FIX_HW_BRN_36513
+ #else
+ #if SGX_CORE_REV == 106
+ #define FIX_HW_BRN_31272
+ #define FIX_HW_BRN_31780
+ #define FIX_HW_BRN_33920
+ #else
+ #if SGX_CORE_REV == 110
+ #define FIX_HW_BRN_31272
+ #if defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_31559
+ #endif
+ #define FIX_HW_BRN_31780
+ #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_33657
+ #endif
+ #define FIX_HW_BRN_33920
+ #else
+ #if SGX_CORE_REV == 112
+ #define FIX_HW_BRN_31272
+ #define FIX_HW_BRN_33920
+ #else
+ #if SGX_CORE_REV == 114
+ #define FIX_HW_BRN_31780
+ #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_33657
+ #endif
+ #else
+ #if SGX_CORE_REV == 115
+ #define FIX_HW_BRN_31780
+ #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_33657
+ #endif
+ #if defined(SGX_FEATURE_MP)
+ #if SGX_FEATURE_MP_CORE_COUNT > 1
+ #define FIX_HW_BRN_36513
+ #endif
+ #endif
+ #else
+ #if SGX_CORE_REV == 116
+ #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_33657
+ #endif
+ #define FIX_HW_BRN_33809
+ #define FIX_HW_BRN_36513
+ #else
+ #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+ #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_33657
+ #endif
+ #else
+ #error "sgxerrata.h: SGX544 Core Revision unspecified"
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+
+ #define SGX_CORE_DEFINED
+#endif
+
+#if defined(SGX545) && !defined(SGX_CORE_DEFINED)
+
+ #define SGX_CORE_REV_HEAD 0
+ #if defined(USE_SGX_CORE_REV_HEAD)
+
+ #define SGX_CORE_REV SGX_CORE_REV_HEAD
+ #endif
+
+ #if SGX_CORE_REV == 100
+ #define FIX_HW_BRN_26620
+ #define FIX_HW_BRN_27266
+ #define FIX_HW_BRN_27456
+ #define FIX_HW_BRN_29702
+ #define FIX_HW_BRN_29823
+ #else
+ #if SGX_CORE_REV == 109
+ #define FIX_HW_BRN_29702
+ #define FIX_HW_BRN_29823
+ #define FIX_HW_BRN_31939
+ #else
+ #if SGX_CORE_REV == 1012
+ #define FIX_HW_BRN_31939
+ #else
+ #if SGX_CORE_REV == 1013
+ #define FIX_HW_BRN_31939
+ #else
+ #if SGX_CORE_REV == 10131
+ #else
+ #if SGX_CORE_REV == 1014
+ #else
+ #if SGX_CORE_REV == 10141
+ #else
+ #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+ #else
+ #error "sgxerrata.h: SGX545 Core Revision unspecified"
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+
+ #define SGX_CORE_DEFINED
+#endif
+
+#if defined(SGX554) && !defined(SGX_CORE_DEFINED)
+
+ #define SGX_CORE_REV_HEAD 0
+ #if defined(USE_SGX_CORE_REV_HEAD)
+
+ #define SGX_CORE_REV SGX_CORE_REV_HEAD
+ #endif
+
+ #if SGX_CORE_REV == 1251
+ #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_33657
+ #endif
+ #define FIX_HW_BRN_36513
+
+ #else
+ #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+ #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_33657
+ #endif
+ #else
+ #error "sgxerrata.h: SGX554 Core Revision unspecified"
+ #endif
+ #endif
+
+ #define SGX_CORE_DEFINED
+#endif
+
+#if !defined(SGX_CORE_DEFINED)
+#if defined (__GNUC__)
+ #warning "sgxerrata.h: SGX Core Version unspecified"
+#else
+ #pragma message("sgxerrata.h: SGX Core Version unspecified")
+#endif
+#endif
+
+#endif
+
diff --git a/drivers/gpu/pvr/sgxfeaturedefs.h b/drivers/gpu/pvr/sgxfeaturedefs.h
new file mode 100644
index 0000000..0679671
--- /dev/null
+++ b/drivers/gpu/pvr/sgxfeaturedefs.h
@@ -0,0 +1,247 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#if defined(SGX520)
+ #define SGX_CORE_FRIENDLY_NAME "SGX520"
+ #define SGX_CORE_ID SGX_CORE_ID_520
+ #define SGX_FEATURE_ADDRESS_SPACE_SIZE (28)
+ #define SGX_FEATURE_NUM_USE_PIPES (1)
+ #define SGX_FEATURE_AUTOCLOCKGATING
+#else
+#if defined(SGX530)
+ #define SGX_CORE_FRIENDLY_NAME "SGX530"
+ #define SGX_CORE_ID SGX_CORE_ID_530
+ #define SGX_FEATURE_ADDRESS_SPACE_SIZE (28)
+ #define SGX_FEATURE_NUM_USE_PIPES (2)
+ #define SGX_FEATURE_AUTOCLOCKGATING
+#else
+#if defined(SGX531)
+ #define SGX_CORE_FRIENDLY_NAME "SGX531"
+ #define SGX_CORE_ID SGX_CORE_ID_531
+ #define SGX_FEATURE_ADDRESS_SPACE_SIZE (28)
+ #define SGX_FEATURE_NUM_USE_PIPES (2)
+ #define SGX_FEATURE_AUTOCLOCKGATING
+ #define SGX_FEATURE_MULTI_EVENT_KICK
+#else
+#if defined(SGX535)
+ #define SGX_CORE_FRIENDLY_NAME "SGX535"
+ #define SGX_CORE_ID SGX_CORE_ID_535
+ #define SGX_FEATURE_ADDRESS_SPACE_SIZE (32)
+ #define SGX_FEATURE_MULTIPLE_MEM_CONTEXTS
+ #define SGX_FEATURE_BIF_NUM_DIRLISTS (16)
+ #define SGX_FEATURE_2D_HARDWARE
+ #define SGX_FEATURE_NUM_USE_PIPES (2)
+ #define SGX_FEATURE_AUTOCLOCKGATING
+ #define SUPPORT_SGX_GENERAL_MAPPING_HEAP
+ #define SGX_FEATURE_EDM_VERTEX_PDSADDR_FULL_RANGE
+#else
+#if defined(SGX540)
+ #define SGX_CORE_FRIENDLY_NAME "SGX540"
+ #define SGX_CORE_ID SGX_CORE_ID_540
+ #define SGX_FEATURE_ADDRESS_SPACE_SIZE (28)
+ #define SGX_FEATURE_NUM_USE_PIPES (4)
+ #define SGX_FEATURE_AUTOCLOCKGATING
+ #define SGX_FEATURE_MULTI_EVENT_KICK
+#else
+#if defined(SGX543)
+ #define SGX_CORE_FRIENDLY_NAME "SGX543"
+ #define SGX_CORE_ID SGX_CORE_ID_543
+ #define SGX_FEATURE_USE_NO_INSTRUCTION_PAIRING
+ #define SGX_FEATURE_USE_UNLIMITED_PHASES
+ #define SGX_FEATURE_ADDRESS_SPACE_SIZE (32)
+ #define SGX_FEATURE_MULTIPLE_MEM_CONTEXTS
+ #define SGX_FEATURE_BIF_NUM_DIRLISTS (8)
+ #define SGX_FEATURE_NUM_USE_PIPES (4)
+ #define SGX_FEATURE_AUTOCLOCKGATING
+ #define SGX_FEATURE_MONOLITHIC_UKERNEL
+ #define SGX_FEATURE_MULTI_EVENT_KICK
+ #define SGX_FEATURE_DATA_BREAKPOINTS
+ #define SGX_FEATURE_PERPIPE_BKPT_REGS
+ #define SGX_FEATURE_PERPIPE_BKPT_REGS_NUMPIPES (2)
+ #define SGX_FEATURE_2D_HARDWARE
+ #define SGX_FEATURE_PTLA
+ #define SGX_FEATURE_EXTENDED_PERF_COUNTERS
+ #define SGX_FEATURE_EDM_VERTEX_PDSADDR_FULL_RANGE
+ #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING)
+ #if defined(SGX_FEATURE_MP)
+ #define SGX_FEATURE_MASTER_VDM_CONTEXT_SWITCH
+ #endif
+ #define SGX_FEATURE_SLAVE_VDM_CONTEXT_SWITCH
+ #define SGX_FEATURE_SW_ISP_CONTEXT_SWITCH
+ #endif
+#else
+#if defined(SGX544)
+ #define SGX_CORE_FRIENDLY_NAME "SGX544"
+ #define SGX_CORE_ID SGX_CORE_ID_544
+ #define SGX_FEATURE_USE_NO_INSTRUCTION_PAIRING
+ #define SGX_FEATURE_USE_UNLIMITED_PHASES
+ #define SGX_FEATURE_ADDRESS_SPACE_SIZE (32)
+ #define SGX_FEATURE_MULTIPLE_MEM_CONTEXTS
+ #define SGX_FEATURE_BIF_NUM_DIRLISTS (8)
+ #define SGX_FEATURE_NUM_USE_PIPES (4)
+ #define SGX_FEATURE_AUTOCLOCKGATING
+ #define SGX_FEATURE_MONOLITHIC_UKERNEL
+ #define SGX_FEATURE_MULTI_EVENT_KICK
+ #define SGX_FEATURE_EXTENDED_PERF_COUNTERS
+ #define SGX_FEATURE_EDM_VERTEX_PDSADDR_FULL_RANGE
+ #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING)
+ #if defined(SGX_FEATURE_MP)
+ #define SGX_FEATURE_MASTER_VDM_CONTEXT_SWITCH
+ #define SGX_FEATURE_SLAVE_VDM_CONTEXT_SWITCH
+ #endif
+ #define SGX_FEATURE_SW_ISP_CONTEXT_SWITCH
+ #endif
+#else
+#if defined(SGX545)
+ #define SGX_CORE_FRIENDLY_NAME "SGX545"
+ #define SGX_CORE_ID SGX_CORE_ID_545
+ #define SGX_FEATURE_ADDRESS_SPACE_SIZE (32)
+ #define SGX_FEATURE_AUTOCLOCKGATING
+ #define SGX_FEATURE_USE_NO_INSTRUCTION_PAIRING
+ #define SGX_FEATURE_USE_UNLIMITED_PHASES
+ #define SGX_FEATURE_VOLUME_TEXTURES
+ #define SGX_FEATURE_HOST_ALLOC_FROM_DPM
+ #define SGX_FEATURE_MULTIPLE_MEM_CONTEXTS
+ #define SGX_FEATURE_BIF_NUM_DIRLISTS (16)
+ #define SGX_FEATURE_NUM_USE_PIPES (4)
+ #define SGX_FEATURE_TEXTURESTRIDE_EXTENSION
+ #define SGX_FEATURE_PDS_DATA_INTERLEAVE_2DWORDS
+ #define SGX_FEATURE_MONOLITHIC_UKERNEL
+ #define SGX_FEATURE_ZLS_EXTERNALZ
+ #define SGX_FEATURE_NUM_PDS_PIPES (2)
+ #define SGX_FEATURE_NATIVE_BACKWARD_BLIT
+ #define SGX_FEATURE_MAX_TA_RENDER_TARGETS (512)
+ #define SGX_FEATURE_SECONDARY_REQUIRES_USE_KICK
+ #define SGX_FEATURE_WRITEBACK_DCU
+
+
+ #define SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS
+ #define SGX_FEATURE_MULTI_EVENT_KICK
+ #define SGX_FEATURE_EDM_VERTEX_PDSADDR_FULL_RANGE
+ #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING)
+ #define SGX_FEATURE_SW_ISP_CONTEXT_SWITCH
+ #endif
+#else
+#if defined(SGX554)
+ #define SGX_CORE_FRIENDLY_NAME "SGX554"
+ #define SGX_CORE_ID SGX_CORE_ID_554
+ #define SGX_FEATURE_USE_NO_INSTRUCTION_PAIRING
+ #define SGX_FEATURE_USE_UNLIMITED_PHASES
+ #define SGX_FEATURE_ADDRESS_SPACE_SIZE (32)
+ #define SGX_FEATURE_MULTIPLE_MEM_CONTEXTS
+ #define SGX_FEATURE_BIF_NUM_DIRLISTS (8)
+ #define SGX_FEATURE_NUM_USE_PIPES (8)
+ #define SGX_FEATURE_AUTOCLOCKGATING
+ #define SGX_FEATURE_MONOLITHIC_UKERNEL
+ #define SGX_FEATURE_MULTI_EVENT_KICK
+ #define SGX_FEATURE_2D_HARDWARE
+ #define SGX_FEATURE_PTLA
+ #define SGX_FEATURE_EXTENDED_PERF_COUNTERS
+ #define SGX_FEATURE_EDM_VERTEX_PDSADDR_FULL_RANGE
+ #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING)
+ #if defined(SGX_FEATURE_MP)
+ #define SGX_FEATURE_MASTER_VDM_CONTEXT_SWITCH
+ #endif
+ #define SGX_FEATURE_SLAVE_VDM_CONTEXT_SWITCH
+ #define SGX_FEATURE_SW_ISP_CONTEXT_SWITCH
+ #endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+
+#if defined(SGX_FEATURE_SLAVE_VDM_CONTEXT_SWITCH) \
+ || defined(SGX_FEATURE_MASTER_VDM_CONTEXT_SWITCH)
+#define SGX_FEATURE_VDM_CONTEXT_SWITCH
+#endif
+
+#if defined(FIX_HW_BRN_22693)
+#undef SGX_FEATURE_AUTOCLOCKGATING
+#endif
+
+#if defined(FIX_HW_BRN_27266)
+#undef SGX_FEATURE_36BIT_MMU
+#endif
+
+#if defined(FIX_HW_BRN_27456)
+#undef SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS
+#endif
+
+#if defined(FIX_HW_BRN_22934) \
+ || defined(FIX_HW_BRN_25499)
+#undef SGX_FEATURE_MULTI_EVENT_KICK
+#endif
+
+#if defined(SGX_FEATURE_SYSTEM_CACHE)
+ #if defined(SGX_FEATURE_36BIT_MMU)
+ #error SGX_FEATURE_SYSTEM_CACHE is incompatible with SGX_FEATURE_36BIT_MMU
+ #endif
+ #if defined(FIX_HW_BRN_26620) && !defined(SGX_FEATURE_MULTI_EVENT_KICK)
+ #define SGX_BYPASS_SYSTEM_CACHE
+ #endif
+#endif
+
+#if defined(FIX_HW_BRN_29954)
+#undef SGX_FEATURE_PERPIPE_BKPT_REGS
+#endif
+
+#if defined(FIX_HW_BRN_31620)
+#undef SGX_FEATURE_MULTIPLE_MEM_CONTEXTS
+#undef SGX_FEATURE_BIF_NUM_DIRLISTS
+#endif
+
+#if defined(SGX_FEATURE_MP)
+#if defined(SGX_FEATURE_MP_CORE_COUNT_TA) && defined(SGX_FEATURE_MP_CORE_COUNT_3D)
+#if (SGX_FEATURE_MP_CORE_COUNT_TA > SGX_FEATURE_MP_CORE_COUNT_3D)
+#error Number of TA cores larger than number of 3D cores not supported in current driver
+#endif
+#else
+#if defined(SGX_FEATURE_MP_CORE_COUNT)
+#define SGX_FEATURE_MP_CORE_COUNT_TA (SGX_FEATURE_MP_CORE_COUNT)
+#define SGX_FEATURE_MP_CORE_COUNT_3D (SGX_FEATURE_MP_CORE_COUNT)
+#else
+#error Either SGX_FEATURE_MP_CORE_COUNT or \
+both SGX_FEATURE_MP_CORE_COUNT_TA and SGX_FEATURE_MP_CORE_COUNT_3D \
+must be defined when SGX_FEATURE_MP is defined
+#endif
+#endif
+#else
+#define SGX_FEATURE_MP_CORE_COUNT (1)
+#define SGX_FEATURE_MP_CORE_COUNT_TA (1)
+#define SGX_FEATURE_MP_CORE_COUNT_3D (1)
+#endif
+
+#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && !defined(SUPPORT_SGX_PRIORITY_SCHEDULING)
+#define SUPPORT_SGX_PRIORITY_SCHEDULING
+#endif
+
+#include "img_types.h"
+
diff --git a/drivers/gpu/pvr/sgxinfo.h b/drivers/gpu/pvr/sgxinfo.h
new file mode 100644
index 0000000..dec8577
--- /dev/null
+++ b/drivers/gpu/pvr/sgxinfo.h
@@ -0,0 +1,463 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#if !defined (__SGXINFO_H__)
+#define __SGXINFO_H__
+
+#include "sgxscript.h"
+#include "servicesint.h"
+#include "services.h"
+#if !defined (SUPPORT_SID_INTERFACE)
+#include "sgxapi_km.h"
+#endif
+#include "sgx_mkif_km.h"
+
+
+#define SGX_MAX_DEV_DATA 24
+#define SGX_MAX_INIT_MEM_HANDLES 18
+
+
+typedef struct _SGX_BRIDGE_INFO_FOR_SRVINIT
+{
+ IMG_DEV_PHYADDR sPDDevPAddr;
+ PVRSRV_HEAP_INFO asHeapInfo[PVRSRV_MAX_CLIENT_HEAPS];
+} SGX_BRIDGE_INFO_FOR_SRVINIT;
+
+
+typedef enum _SGXMKIF_CMD_TYPE_
+{
+ SGXMKIF_CMD_TA = 0,
+ SGXMKIF_CMD_TRANSFER = 1,
+ SGXMKIF_CMD_2D = 2,
+ SGXMKIF_CMD_POWER = 3,
+ SGXMKIF_CMD_CONTEXTSUSPEND = 4,
+ SGXMKIF_CMD_CLEANUP = 5,
+ SGXMKIF_CMD_GETMISCINFO = 6,
+ SGXMKIF_CMD_PROCESS_QUEUES = 7,
+ SGXMKIF_CMD_DATABREAKPOINT = 8,
+ SGXMKIF_CMD_SETHWPERFSTATUS = 9,
+ SGXMKIF_CMD_FLUSHPDCACHE = 10,
+ SGXMKIF_CMD_MAX = 11,
+
+ SGXMKIF_CMD_FORCE_I32 = -1,
+
+} SGXMKIF_CMD_TYPE;
+
+
+typedef struct _SGX_BRIDGE_INIT_INFO_
+{
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelCCBMemInfo;
+ IMG_SID hKernelCCBCtlMemInfo;
+ IMG_SID hKernelCCBEventKickerMemInfo;
+ IMG_SID hKernelSGXHostCtlMemInfo;
+ IMG_SID hKernelSGXTA3DCtlMemInfo;
+#if defined(FIX_HW_BRN_31272) || defined(FIX_HW_BRN_31780) || defined(FIX_HW_BRN_33920)
+ IMG_SID hKernelSGXPTLAWriteBackMemInfo;
+#endif
+ IMG_SID hKernelSGXMiscMemInfo;
+#else
+ IMG_HANDLE hKernelCCBMemInfo;
+ IMG_HANDLE hKernelCCBCtlMemInfo;
+ IMG_HANDLE hKernelCCBEventKickerMemInfo;
+ IMG_HANDLE hKernelSGXHostCtlMemInfo;
+ IMG_HANDLE hKernelSGXTA3DCtlMemInfo;
+#if defined(FIX_HW_BRN_31272) || defined(FIX_HW_BRN_31780) || defined(FIX_HW_BRN_33920)
+ IMG_HANDLE hKernelSGXPTLAWriteBackMemInfo;
+#endif
+ IMG_HANDLE hKernelSGXMiscMemInfo;
+#endif
+
+ IMG_UINT32 aui32HostKickAddr[SGXMKIF_CMD_MAX];
+
+ SGX_INIT_SCRIPTS sScripts;
+
+ IMG_UINT32 ui32ClientBuildOptions;
+ SGX_MISCINFO_STRUCT_SIZES sSGXStructSizes;
+
+#if defined(SGX_SUPPORT_HWPROFILING)
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelHWProfilingMemInfo;
+#else
+ IMG_HANDLE hKernelHWProfilingMemInfo;
+#endif
+#endif
+#if defined(SUPPORT_SGX_HWPERF)
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelHWPerfCBMemInfo;
+#else
+ IMG_HANDLE hKernelHWPerfCBMemInfo;
+#endif
+#endif
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelTASigBufferMemInfo;
+ IMG_SID hKernel3DSigBufferMemInfo;
+#else
+ IMG_HANDLE hKernelTASigBufferMemInfo;
+ IMG_HANDLE hKernel3DSigBufferMemInfo;
+#endif
+
+#if defined(FIX_HW_BRN_29702)
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelCFIMemInfo;
+#else
+ IMG_HANDLE hKernelCFIMemInfo;
+#endif
+#endif
+#if defined(FIX_HW_BRN_29823)
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelDummyTermStreamMemInfo;
+#else
+ IMG_HANDLE hKernelDummyTermStreamMemInfo;
+#endif
+#endif
+
+#if defined(FIX_HW_BRN_31542) || defined(FIX_HW_BRN_36513)
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelClearClipWAVDMStreamMemInfo;
+ IMG_SID hKernelClearClipWAIndexStreamMemInfo;
+ IMG_SID hKernelClearClipWAPDSMemInfo;
+ IMG_SID hKernelClearClipWAUSEMemInfo;
+ IMG_SID hKernelClearClipWAParamMemInfo;
+ IMG_SID hKernelClearClipWAPMPTMemInfo;
+ IMG_SID hKernelClearClipWATPCMemInfo;
+ IMG_SID hKernelClearClipWAPSGRgnHdrMemInfo;
+#else
+ IMG_HANDLE hKernelClearClipWAVDMStreamMemInfo;
+ IMG_HANDLE hKernelClearClipWAIndexStreamMemInfo;
+ IMG_HANDLE hKernelClearClipWAPDSMemInfo;
+ IMG_HANDLE hKernelClearClipWAUSEMemInfo;
+ IMG_HANDLE hKernelClearClipWAParamMemInfo;
+ IMG_HANDLE hKernelClearClipWAPMPTMemInfo;
+ IMG_HANDLE hKernelClearClipWATPCMemInfo;
+ IMG_HANDLE hKernelClearClipWAPSGRgnHdrMemInfo;
+#endif
+#endif
+
+#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && defined(FIX_HW_BRN_31559)
+ IMG_HANDLE hKernelVDMSnapShotBufferMemInfo;
+ IMG_HANDLE hKernelVDMCtrlStreamBufferMemInfo;
+#endif
+#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && \
+ defined(FIX_HW_BRN_33657) && defined(SUPPORT_SECURE_33657_FIX)
+ IMG_HANDLE hKernelVDMStateUpdateBufferMemInfo;
+#endif
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelEDMStatusBufferMemInfo;
+#else
+ IMG_HANDLE hKernelEDMStatusBufferMemInfo;
+#endif
+#endif
+
+ IMG_UINT32 ui32EDMTaskReg0;
+ IMG_UINT32 ui32EDMTaskReg1;
+
+ IMG_UINT32 ui32ClkGateCtl;
+ IMG_UINT32 ui32ClkGateCtl2;
+ IMG_UINT32 ui32ClkGateStatusReg;
+ IMG_UINT32 ui32ClkGateStatusMask;
+#if defined(SGX_FEATURE_MP)
+ IMG_UINT32 ui32MasterClkGateStatusReg;
+ IMG_UINT32 ui32MasterClkGateStatusMask;
+ IMG_UINT32 ui32MasterClkGateStatus2Reg;
+ IMG_UINT32 ui32MasterClkGateStatus2Mask;
+#endif
+
+ IMG_UINT32 ui32CacheControl;
+
+ IMG_UINT32 asInitDevData[SGX_MAX_DEV_DATA];
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID asInitMemHandles[SGX_MAX_INIT_MEM_HANDLES];
+#else
+ IMG_HANDLE asInitMemHandles[SGX_MAX_INIT_MEM_HANDLES];
+#endif
+
+} SGX_BRIDGE_INIT_INFO;
+
+
+typedef struct _SGX_DEVICE_SYNC_LIST_
+{
+ PSGXMKIF_HWDEVICE_SYNC_LIST psHWDeviceSyncList;
+
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelHWSyncListMemInfo;
+#else
+ IMG_HANDLE hKernelHWSyncListMemInfo;
+#endif
+ PVRSRV_CLIENT_MEM_INFO *psHWDeviceSyncListClientMemInfo;
+ PVRSRV_CLIENT_MEM_INFO *psAccessResourceClientMemInfo;
+
+ volatile IMG_UINT32 *pui32Lock;
+
+ struct _SGX_DEVICE_SYNC_LIST_ *psNext;
+
+
+ IMG_UINT32 ui32NumSyncObjects;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID ahSyncHandles[1];
+#else
+ IMG_HANDLE ahSyncHandles[1];
+#endif
+} SGX_DEVICE_SYNC_LIST, *PSGX_DEVICE_SYNC_LIST;
+
+
+typedef struct _SGX_INTERNEL_STATUS_UPDATE_
+{
+ CTL_STATUS sCtlStatus;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelMemInfo;
+#else
+ IMG_HANDLE hKernelMemInfo;
+#endif
+} SGX_INTERNEL_STATUS_UPDATE;
+
+
+typedef struct _SGX_CCB_KICK_
+{
+ SGXMKIF_COMMAND sCommand;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hCCBKernelMemInfo;
+#else
+ IMG_HANDLE hCCBKernelMemInfo;
+#endif
+
+ IMG_UINT32 ui32NumDstSyncObjects;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hKernelHWSyncListMemInfo;
+#else
+ IMG_HANDLE hKernelHWSyncListMemInfo;
+#endif
+
+
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID *pahDstSyncHandles;
+#else
+ IMG_HANDLE *pahDstSyncHandles;
+#endif
+
+ IMG_UINT32 ui32NumTAStatusVals;
+ IMG_UINT32 ui32Num3DStatusVals;
+
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ SGX_INTERNEL_STATUS_UPDATE asTAStatusUpdate[SGX_MAX_TA_STATUS_VALS];
+ SGX_INTERNEL_STATUS_UPDATE as3DStatusUpdate[SGX_MAX_3D_STATUS_VALS];
+#else
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID ahTAStatusSyncInfo[SGX_MAX_TA_STATUS_VALS];
+ IMG_SID ah3DStatusSyncInfo[SGX_MAX_3D_STATUS_VALS];
+#else
+ IMG_HANDLE ahTAStatusSyncInfo[SGX_MAX_TA_STATUS_VALS];
+ IMG_HANDLE ah3DStatusSyncInfo[SGX_MAX_3D_STATUS_VALS];
+#endif
+#endif
+
+ IMG_BOOL bFirstKickOrResume;
+#if (defined(NO_HARDWARE) || defined(PDUMP))
+ IMG_BOOL bTerminateOrAbort;
+#endif
+ IMG_BOOL bLastInScene;
+
+
+ IMG_UINT32 ui32CCBOffset;
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+
+ IMG_UINT32 ui32NumTASrcSyncs;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID ahTASrcKernelSyncInfo[SGX_MAX_TA_SRC_SYNCS];
+#else
+ IMG_HANDLE ahTASrcKernelSyncInfo[SGX_MAX_TA_SRC_SYNCS];
+#endif
+ IMG_UINT32 ui32NumTADstSyncs;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID ahTADstKernelSyncInfo[SGX_MAX_TA_DST_SYNCS];
+#else
+ IMG_HANDLE ahTADstKernelSyncInfo[SGX_MAX_TA_DST_SYNCS];
+#endif
+ IMG_UINT32 ui32Num3DSrcSyncs;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID ah3DSrcKernelSyncInfo[SGX_MAX_3D_SRC_SYNCS];
+#else
+ IMG_HANDLE ah3DSrcKernelSyncInfo[SGX_MAX_3D_SRC_SYNCS];
+#endif
+#else
+
+ IMG_UINT32 ui32NumSrcSyncs;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID ahSrcKernelSyncInfo[SGX_MAX_SRC_SYNCS_TA];
+#else
+ IMG_HANDLE ahSrcKernelSyncInfo[SGX_MAX_SRC_SYNCS_TA];
+#endif
+#endif
+
+
+ IMG_BOOL bTADependency;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hTA3DSyncInfo;
+
+ IMG_SID hTASyncInfo;
+ IMG_SID h3DSyncInfo;
+#else
+ IMG_HANDLE hTA3DSyncInfo;
+
+ IMG_HANDLE hTASyncInfo;
+ IMG_HANDLE h3DSyncInfo;
+#endif
+#if defined(PDUMP)
+ IMG_UINT32 ui32CCBDumpWOff;
+#endif
+#if defined(NO_HARDWARE)
+ IMG_UINT32 ui32WriteOpsPendingVal;
+#endif
+ IMG_HANDLE hDevMemContext;
+} SGX_CCB_KICK;
+
+
+#define SGX_KERNEL_USE_CODE_BASE_INDEX 15
+
+
+typedef struct _SGX_CLIENT_INFO_
+{
+ IMG_UINT32 ui32ProcessID;
+ IMG_VOID *pvProcess;
+ PVRSRV_MISC_INFO sMiscInfo;
+
+ IMG_UINT32 asDevData[SGX_MAX_DEV_DATA];
+
+} SGX_CLIENT_INFO;
+
+typedef struct _SGX_INTERNAL_DEVINFO_
+{
+ IMG_UINT32 ui32Flags;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hHostCtlKernelMemInfoHandle;
+#else
+ IMG_HANDLE hHostCtlKernelMemInfoHandle;
+#endif
+ IMG_BOOL bForcePTOff;
+} SGX_INTERNAL_DEVINFO;
+
+
+typedef struct _SGX_INTERNAL_DEVINFO_KM_
+{
+ IMG_UINT32 ui32Flags;
+ IMG_HANDLE hHostCtlKernelMemInfoHandle;
+ IMG_BOOL bForcePTOff;
+} SGX_INTERNAL_DEVINFO_KM;
+
+
+#if defined(TRANSFER_QUEUE)
+typedef struct _PVRSRV_TRANSFER_SGX_KICK_
+{
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hCCBMemInfo;
+#else
+ IMG_HANDLE hCCBMemInfo;
+#endif
+ IMG_UINT32 ui32SharedCmdCCBOffset;
+
+ IMG_DEV_VIRTADDR sHWTransferContextDevVAddr;
+
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hTASyncInfo;
+ IMG_SID h3DSyncInfo;
+#else
+ IMG_HANDLE hTASyncInfo;
+ IMG_HANDLE h3DSyncInfo;
+#endif
+
+ IMG_UINT32 ui32NumSrcSync;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID ahSrcSyncInfo[SGX_MAX_TRANSFER_SYNC_OPS];
+#else
+ IMG_HANDLE ahSrcSyncInfo[SGX_MAX_TRANSFER_SYNC_OPS];
+#endif
+
+ IMG_UINT32 ui32NumDstSync;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID ahDstSyncInfo[SGX_MAX_TRANSFER_SYNC_OPS];
+#else
+ IMG_HANDLE ahDstSyncInfo[SGX_MAX_TRANSFER_SYNC_OPS];
+#endif
+
+ IMG_UINT32 ui32Flags;
+
+ IMG_UINT32 ui32PDumpFlags;
+#if defined(PDUMP)
+ IMG_UINT32 ui32CCBDumpWOff;
+#endif
+ IMG_HANDLE hDevMemContext;
+} PVRSRV_TRANSFER_SGX_KICK, *PPVRSRV_TRANSFER_SGX_KICK;
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+typedef struct _PVRSRV_2D_SGX_KICK_
+{
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID hCCBMemInfo;
+#else
+ IMG_HANDLE hCCBMemInfo;
+#endif
+ IMG_UINT32 ui32SharedCmdCCBOffset;
+
+ IMG_DEV_VIRTADDR sHW2DContextDevVAddr;
+
+ IMG_UINT32 ui32NumSrcSync;
+#if defined (SUPPORT_SID_INTERFACE)
+ IMG_SID ahSrcSyncInfo[SGX_MAX_2D_SRC_SYNC_OPS];
+
+
+ IMG_SID hDstSyncInfo;
+
+
+ IMG_SID hTASyncInfo;
+
+
+ IMG_SID h3DSyncInfo;
+#else
+ IMG_HANDLE ahSrcSyncInfo[SGX_MAX_2D_SRC_SYNC_OPS];
+
+
+ IMG_HANDLE hDstSyncInfo;
+
+
+ IMG_HANDLE hTASyncInfo;
+
+
+ IMG_HANDLE h3DSyncInfo;
+#endif
+
+ IMG_UINT32 ui32PDumpFlags;
+#if defined(PDUMP)
+ IMG_UINT32 ui32CCBDumpWOff;
+#endif
+ IMG_HANDLE hDevMemContext;
+} PVRSRV_2D_SGX_KICK, *PPVRSRV_2D_SGX_KICK;
+#endif
+#endif
+
+
+#endif
diff --git a/drivers/gpu/pvr/sgxmmu.h b/drivers/gpu/pvr/sgxmmu.h
new file mode 100644
index 0000000..1b265f1
--- /dev/null
+++ b/drivers/gpu/pvr/sgxmmu.h
@@ -0,0 +1,72 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#if !defined(__SGXMMU_KM_H__)
+#define __SGXMMU_KM_H__
+
+#define SGX_MMU_PAGE_SHIFT (12)
+#define SGX_MMU_PAGE_SIZE (1U<<SGX_MMU_PAGE_SHIFT)
+#define SGX_MMU_PAGE_MASK (SGX_MMU_PAGE_SIZE - 1U)
+
+#define SGX_MMU_PD_SHIFT (10)
+#define SGX_MMU_PD_SIZE (1U<<SGX_MMU_PD_SHIFT)
+#define SGX_MMU_PD_MASK (0xFFC00000U)
+
+#if defined(SGX_FEATURE_36BIT_MMU)
+ #define SGX_MMU_PDE_ADDR_MASK (0xFFFFFF00U)
+ #define SGX_MMU_PDE_ADDR_ALIGNSHIFT (4)
+#else
+ #define SGX_MMU_PDE_ADDR_MASK (0xFFFFF000U)
+ #define SGX_MMU_PDE_ADDR_ALIGNSHIFT (0)
+#endif
+#define SGX_MMU_PDE_VALID (0x00000001U)
+#define SGX_MMU_PDE_PAGE_SIZE_4K (0x00000000U)
+#define SGX_MMU_PDE_PAGE_SIZE_16K (0x00000002U)
+#define SGX_MMU_PDE_PAGE_SIZE_64K (0x00000004U)
+#define SGX_MMU_PDE_PAGE_SIZE_256K (0x00000006U)
+#define SGX_MMU_PDE_PAGE_SIZE_1M (0x00000008U)
+#define SGX_MMU_PDE_PAGE_SIZE_4M (0x0000000AU)
+#define SGX_MMU_PDE_PAGE_SIZE_MASK (0x0000000EU)
+
+#define SGX_MMU_PT_SHIFT (10)
+#define SGX_MMU_PT_SIZE (1U<<SGX_MMU_PT_SHIFT)
+#define SGX_MMU_PT_MASK (0x003FF000U)
+
+#if defined(SGX_FEATURE_36BIT_MMU)
+ #define SGX_MMU_PTE_ADDR_MASK (0xFFFFFF00U)
+ #define SGX_MMU_PTE_ADDR_ALIGNSHIFT (4)
+#else
+ #define SGX_MMU_PTE_ADDR_MASK (0xFFFFF000U)
+ #define SGX_MMU_PTE_ADDR_ALIGNSHIFT (0)
+#endif
+#define SGX_MMU_PTE_VALID (0x00000001U)
+#define SGX_MMU_PTE_WRITEONLY (0x00000002U)
+#define SGX_MMU_PTE_READONLY (0x00000004U)
+#define SGX_MMU_PTE_CACHECONSISTENT (0x00000008U)
+#define SGX_MMU_PTE_EDMPROTECT (0x00000010U)
+
+#endif
+
diff --git a/drivers/gpu/pvr/sgxscript.h b/drivers/gpu/pvr/sgxscript.h
new file mode 100644
index 0000000..94eb453
--- /dev/null
+++ b/drivers/gpu/pvr/sgxscript.h
@@ -0,0 +1,83 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+*****************************************************************************/
+#ifndef __SGXSCRIPT_H__
+#define __SGXSCRIPT_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define SGX_MAX_INIT_COMMANDS 64
+#define SGX_MAX_DEINIT_COMMANDS 16
+
+typedef enum _SGX_INIT_OPERATION
+{
+ SGX_INIT_OP_ILLEGAL = 0,
+ SGX_INIT_OP_WRITE_HW_REG,
+#if defined(PDUMP)
+ SGX_INIT_OP_PDUMP_HW_REG,
+#endif
+ SGX_INIT_OP_HALT
+} SGX_INIT_OPERATION;
+
+typedef union _SGX_INIT_COMMAND
+{
+ SGX_INIT_OPERATION eOp;
+ struct {
+ SGX_INIT_OPERATION eOp;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT32 ui32Value;
+ } sWriteHWReg;
+#if defined(PDUMP)
+ struct {
+ SGX_INIT_OPERATION eOp;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT32 ui32Value;
+ } sPDumpHWReg;
+#endif
+#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
+ struct {
+ SGX_INIT_OPERATION eOp;
+ } sWorkaroundBRN22997;
+#endif
+} SGX_INIT_COMMAND;
+
+typedef struct _SGX_INIT_SCRIPTS_
+{
+ SGX_INIT_COMMAND asInitCommandsPart1[SGX_MAX_INIT_COMMANDS];
+ SGX_INIT_COMMAND asInitCommandsPart2[SGX_MAX_INIT_COMMANDS];
+ SGX_INIT_COMMAND asDeinitCommands[SGX_MAX_DEINIT_COMMANDS];
+} SGX_INIT_SCRIPTS;
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __SGXSCRIPT_H__ */
+
+/*****************************************************************************
+ End of file (sgxscript.h)
+*****************************************************************************/
diff --git a/drivers/gpu/pvr/srvkm.h b/drivers/gpu/pvr/srvkm.h
new file mode 100644
index 0000000..474a1ee
--- /dev/null
+++ b/drivers/gpu/pvr/srvkm.h
@@ -0,0 +1,78 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef SRVKM_H
+#define SRVKM_H
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+ #ifdef PVR_DISABLE_LOGGING
+ #define PVR_LOG(X)
+ #else
+
+ #define PVR_LOG(X) PVRSRVReleasePrintf X;
+ #endif
+
+ IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVReleasePrintf(const IMG_CHAR *pszFormat, ...) IMG_FORMAT_PRINTF(1, 2);
+
+ IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVProcessConnect(IMG_UINT32 ui32PID, IMG_UINT32 ui32Flags);
+ IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVProcessDisconnect(IMG_UINT32 ui32PID);
+
+ IMG_IMPORT IMG_VOID PVRSRVScheduleDevicesKM(IMG_VOID);
+
+ IMG_VOID IMG_CALLCONV PVRSRVSetDCState(IMG_UINT32 ui32State);
+
+ PVRSRV_ERROR IMG_CALLCONV PVRSRVSaveRestoreLiveSegments(IMG_HANDLE hArena, IMG_PBYTE pbyBuffer, IMG_SIZE_T *puiBufSize, IMG_BOOL bSave);
+
+ IMG_VOID PVRSRVScheduleDeviceCallbacks(IMG_VOID);
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+
+#define LOOP_UNTIL_TIMEOUT(TIMEOUT) \
+{\
+ IMG_UINT32 uiOffset, uiStart, uiCurrent; \
+ IMG_INT32 iNotLastLoop; \
+ for(uiOffset = 0, uiStart = OSClockus(), uiCurrent = uiStart + 1, iNotLastLoop = 1;\
+ ((uiCurrent - uiStart + uiOffset) < (TIMEOUT)) || iNotLastLoop--; \
+ uiCurrent = OSClockus(), \
+ uiOffset = uiCurrent < uiStart ? IMG_UINT32_MAX - uiStart : uiOffset, \
+ uiStart = uiCurrent < uiStart ? 0 : uiStart)
+
+#define END_LOOP_UNTIL_TIMEOUT() \
+}
+
+IMG_IMPORT
+const IMG_CHAR *PVRSRVGetErrorStringKM(PVRSRV_ERROR eError);
+
+#endif
diff --git a/drivers/gpu/pvr/staticversion.h b/drivers/gpu/pvr/staticversion.h
new file mode 100644
index 0000000..433d126
--- /dev/null
+++ b/drivers/gpu/pvr/staticversion.h
@@ -0,0 +1,33 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+*****************************************************************************/
+#ifndef _STATICVERSION_H_
+#define _STATICVERSION_H_
+
+#define PVRVERSION_MAJ 1
+#define PVRVERSION_MIN 8
+#define PVRVERSION_BRANCH 18
+
+#endif /* _STATICVERSION_H_ */
diff --git a/drivers/gpu/pvr/syscommon.h b/drivers/gpu/pvr/syscommon.h
new file mode 100644
index 0000000..d5e5eef
--- /dev/null
+++ b/drivers/gpu/pvr/syscommon.h
@@ -0,0 +1,270 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef _SYSCOMMON_H
+#define _SYSCOMMON_H
+
+#include "sysconfig.h"
+#include "sysinfo.h"
+#include "servicesint.h"
+#include "queue.h"
+#include "power.h"
+#include "resman.h"
+#include "ra.h"
+#include "device.h"
+#include "buffer_manager.h"
+#include "pvr_debug.h"
+#include "services.h"
+
+#if defined(NO_HARDWARE) && defined(__linux__) && defined(__KERNEL__)
+#include <asm/io.h>
+#endif
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+typedef struct _SYS_DEVICE_ID_TAG
+{
+ IMG_UINT32 uiID;
+ IMG_BOOL bInUse;
+
+} SYS_DEVICE_ID;
+
+
+#define SYS_MAX_LOCAL_DEVMEM_ARENAS 4
+
+typedef IMG_HANDLE (*PFN_HTIMER_CREATE) (IMG_VOID);
+typedef IMG_UINT32 (*PFN_HTIMER_GETUS) (IMG_HANDLE);
+typedef IMG_VOID (*PFN_HTIMER_DESTROY) (IMG_HANDLE);
+typedef struct _SYS_DATA_TAG_
+{
+ IMG_UINT32 ui32NumDevices;
+ SYS_DEVICE_ID sDeviceID[SYS_DEVICE_COUNT];
+ PVRSRV_DEVICE_NODE *psDeviceNodeList;
+ PVRSRV_POWER_DEV *psPowerDeviceList;
+ PVRSRV_RESOURCE sPowerStateChangeResource;
+ PVRSRV_SYS_POWER_STATE eCurrentPowerState;
+ PVRSRV_SYS_POWER_STATE eFailedPowerState;
+ IMG_UINT32 ui32CurrentOSPowerState;
+ PVRSRV_QUEUE_INFO *psQueueList;
+ PVRSRV_KERNEL_SYNC_INFO *psSharedSyncInfoList;
+ IMG_PVOID pvEnvSpecificData;
+ IMG_PVOID pvSysSpecificData;
+ PVRSRV_RESOURCE sQProcessResource;
+ IMG_VOID *pvSOCRegsBase;
+ IMG_HANDLE hSOCTimerRegisterOSMemHandle;
+ IMG_UINT32 *pvSOCTimerRegisterKM;
+ IMG_VOID *pvSOCClockGateRegsBase;
+ IMG_UINT32 ui32SOCClockGateRegsSize;
+
+ struct _DEVICE_COMMAND_DATA_ *apsDeviceCommandData[SYS_DEVICE_COUNT];
+
+
+ RA_ARENA *apsLocalDevMemArena[SYS_MAX_LOCAL_DEVMEM_ARENAS];
+
+ IMG_CHAR *pszVersionString;
+#if defined (SUPPORT_SID_INTERFACE)
+ PVRSRV_EVENTOBJECT_KM *psGlobalEventObject;
+#else
+ PVRSRV_EVENTOBJECT *psGlobalEventObject;
+#endif
+
+ PVRSRV_MISC_INFO_CPUCACHEOP_TYPE ePendingCacheOpType;
+
+ PFN_HTIMER_CREATE pfnHighResTimerCreate;
+ PFN_HTIMER_GETUS pfnHighResTimerGetus;
+ PFN_HTIMER_DESTROY pfnHighResTimerDestroy;
+} SYS_DATA;
+
+
+
+#if defined (CUSTOM_DISPLAY_SEGMENT)
+PVRSRV_ERROR SysGetDisplaySegmentAddress (IMG_VOID *pvDevInfo, IMG_VOID *pvPhysicalAddress, IMG_UINT32 *pui32Length);
+#endif
+
+PVRSRV_ERROR SysInitialise(IMG_VOID);
+PVRSRV_ERROR SysFinalise(IMG_VOID);
+
+PVRSRV_ERROR SysDeinitialise(SYS_DATA *psSysData);
+PVRSRV_ERROR SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_VOID **ppvDeviceMap);
+
+IMG_VOID SysRegisterExternalDevice(PVRSRV_DEVICE_NODE *psDeviceNode);
+IMG_VOID SysRemoveExternalDevice(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_UINT32 SysGetInterruptSource(SYS_DATA *psSysData,
+ PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_VOID SysClearInterrupts(SYS_DATA* psSysData, IMG_UINT32 ui32ClearBits);
+
+PVRSRV_ERROR SysResetDevice(IMG_UINT32 ui32DeviceIndex);
+
+PVRSRV_ERROR SysSystemPrePowerState(PVRSRV_SYS_POWER_STATE eNewPowerState);
+PVRSRV_ERROR SysSystemPostPowerState(PVRSRV_SYS_POWER_STATE eNewPowerState);
+PVRSRV_ERROR SysDevicePrePowerState(IMG_UINT32 ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+PVRSRV_ERROR SysDevicePostPowerState(IMG_UINT32 ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+
+#if defined(SYS_SUPPORTS_SGX_IDLE_CALLBACK)
+IMG_VOID SysSGXIdleTransition(IMG_BOOL bSGXIdle);
+#endif
+
+#if defined(SYS_CUSTOM_POWERLOCK_WRAP)
+PVRSRV_ERROR SysPowerLockWrap(IMG_BOOL bTryLock);
+IMG_VOID SysPowerLockUnwrap(IMG_VOID);
+#endif
+
+PVRSRV_ERROR SysOEMFunction ( IMG_UINT32 ui32ID,
+ IMG_VOID *pvIn,
+ IMG_UINT32 ulInSize,
+ IMG_VOID *pvOut,
+ IMG_UINT32 ulOutSize);
+
+
+IMG_DEV_PHYADDR SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE eDeviceType, IMG_CPU_PHYADDR cpu_paddr);
+IMG_DEV_PHYADDR SysSysPAddrToDevPAddr (PVRSRV_DEVICE_TYPE eDeviceType, IMG_SYS_PHYADDR SysPAddr);
+IMG_SYS_PHYADDR SysDevPAddrToSysPAddr (PVRSRV_DEVICE_TYPE eDeviceType, IMG_DEV_PHYADDR SysPAddr);
+IMG_CPU_PHYADDR SysSysPAddrToCpuPAddr (IMG_SYS_PHYADDR SysPAddr);
+IMG_SYS_PHYADDR SysCpuPAddrToSysPAddr (IMG_CPU_PHYADDR cpu_paddr);
+#if defined(PVR_LMA)
+IMG_BOOL SysVerifyCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE eDeviceType, IMG_CPU_PHYADDR CpuPAddr);
+IMG_BOOL SysVerifySysPAddrToDevPAddr (PVRSRV_DEVICE_TYPE eDeviceType, IMG_SYS_PHYADDR SysPAddr);
+#endif
+
+extern SYS_DATA* gpsSysData;
+
+
+#if !defined(USE_CODE)
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysAcquireData)
+#endif
+static INLINE IMG_VOID SysAcquireData(SYS_DATA **ppsSysData)
+{
+
+ *ppsSysData = gpsSysData;
+
+
+
+
+
+ PVR_ASSERT (gpsSysData != IMG_NULL);
+}
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysAcquireDataNoCheck)
+#endif
+static INLINE SYS_DATA * SysAcquireDataNoCheck(IMG_VOID)
+{
+
+ return gpsSysData;
+}
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysInitialiseCommon)
+#endif
+static INLINE PVRSRV_ERROR SysInitialiseCommon(SYS_DATA *psSysData)
+{
+ PVRSRV_ERROR eError;
+
+
+ eError = PVRSRVInit(psSysData);
+
+ return eError;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysDeinitialiseCommon)
+#endif
+static INLINE IMG_VOID SysDeinitialiseCommon(SYS_DATA *psSysData)
+{
+
+ PVRSRVDeInit(psSysData);
+
+ OSDestroyResource(&psSysData->sPowerStateChangeResource);
+}
+#endif
+
+
+#if !(defined(NO_HARDWARE) && defined(__linux__) && defined(__KERNEL__))
+#define SysReadHWReg(p, o) OSReadHWReg(p, o)
+#define SysWriteHWReg(p, o, v) OSWriteHWReg(p, o, v)
+#else
+static inline IMG_UINT32 SysReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset)
+{
+ return (IMG_UINT32) readl(pvLinRegBaseAddr + ui32Offset);
+}
+
+static inline IMG_VOID SysWriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value)
+{
+ writel(ui32Value, pvLinRegBaseAddr + ui32Offset);
+}
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysHighResTimerCreate)
+#endif
+static INLINE IMG_HANDLE SysHighResTimerCreate(IMG_VOID)
+{
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+ return psSysData->pfnHighResTimerCreate();
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysHighResTimerGetus)
+#endif
+static INLINE IMG_UINT32 SysHighResTimerGetus(IMG_HANDLE hTimer)
+{
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+ return psSysData->pfnHighResTimerGetus(hTimer);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysHighResTimerDestroy)
+#endif
+static INLINE IMG_VOID SysHighResTimerDestroy(IMG_HANDLE hTimer)
+{
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+ psSysData->pfnHighResTimerDestroy(hTimer);
+}
+#endif
+
diff --git a/drivers/gpu/pvr/ttrace.h b/drivers/gpu/pvr/ttrace.h
new file mode 100644
index 0000000..9e04b88
--- /dev/null
+++ b/drivers/gpu/pvr/ttrace.h
@@ -0,0 +1,184 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "ttrace_common.h"
+#include "ttrace_tokens.h"
+
+#ifndef __TTRACE_H__
+#define __TTRACE_H__
+
+#if defined(TTRACE)
+
+ #define PVR_TTRACE(group, class, token) \
+ PVRSRVTimeTrace(group, class, token)
+ #define PVR_TTRACE_UI8(group, class, token, val) \
+ PVRSRVTimeTraceUI8(group, class, token, val)
+ #define PVR_TTRACE_UI16(group, class, token, val) \
+ PVRSRVTimeTraceUI16(group, class, token, val)
+ #define PVR_TTRACE_UI32(group, class, token, val) \
+ PVRSRVTimeTraceUI32(group, class, token, val)
+ #define PVR_TTRACE_UI64(group, class, token, val) \
+ PVRSRVTimeTraceUI64(group, class, token, val)
+ #define PVR_TTRACE_DEV_VIRTADDR(group, class, token, val) \
+ PVRSRVTimeTraceDevVirtAddr(group, class, token, val)
+ #define PVR_TTRACE_CPU_PHYADDR(group, class, token, val) \
+ PVRSRVTimeTraceCpuPhyAddr(group, class, token, val)
+ #define PVR_TTRACE_DEV_PHYADDR(group, class, token, val) \
+ PVRSRVTimeTraceDevPhysAddr(group, class, token, val)
+ #define PVR_TTRACE_SYS_PHYADDR(group, class, token, val) \
+ PVRSRVTimeTraceSysPhysAddr(group, class, token, val)
+ #define PVR_TTRACE_SYNC_OBJECT(group, token, syncobj, op) \
+ PVRSRVTimeTraceSyncObject(group, token, syncobj, op)
+
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVTimeTraceArray(IMG_UINT32 ui32Group, IMG_UINT32 ui32Class,
+ IMG_UINT32 ui32Token, IMG_UINT32 ui32TypeSize,
+ IMG_UINT32 ui32Count, IMG_UINT8 *ui8Data);
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVTimeTrace)
+#endif
+static INLINE IMG_VOID PVRSRVTimeTrace(IMG_UINT32 ui32Group, IMG_UINT32 ui32Class,
+ IMG_UINT32 ui32Token)
+{
+ PVRSRVTimeTraceArray(ui32Group, ui32Class, ui32Token, 0, 0, NULL);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVTimeTraceUI8)
+#endif
+static INLINE IMG_VOID PVRSRVTimeTraceUI8(IMG_UINT32 ui32Group, IMG_UINT32 ui32Class,
+ IMG_UINT32 ui32Token, IMG_UINT8 ui8Value)
+{
+ PVRSRVTimeTraceArray(ui32Group, ui32Class, ui32Token, PVRSRV_TRACE_TYPE_UI8,
+ 1, &ui8Value);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVTimeTraceUI16)
+#endif
+static INLINE IMG_VOID PVRSRVTimeTraceUI16(IMG_UINT32 ui32Group, IMG_UINT32 ui32Class,
+ IMG_UINT32 ui32Token, IMG_UINT16 ui16Value)
+{
+ PVRSRVTimeTraceArray(ui32Group, ui32Class, ui32Token, PVRSRV_TRACE_TYPE_UI16,
+ 1, (IMG_UINT8 *) &ui16Value);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVTimeTraceUI32)
+#endif
+static INLINE IMG_VOID PVRSRVTimeTraceUI32(IMG_UINT32 ui32Group, IMG_UINT32 ui32Class,
+ IMG_UINT32 ui32Token, IMG_UINT32 ui32Value)
+{
+ PVRSRVTimeTraceArray(ui32Group, ui32Class, ui32Token, PVRSRV_TRACE_TYPE_UI32,
+ 1, (IMG_UINT8 *) &ui32Value);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVTimeTraceUI64)
+#endif
+static INLINE IMG_VOID PVRSRVTimeTraceUI64(IMG_UINT32 ui32Group, IMG_UINT32 ui32Class,
+ IMG_UINT32 ui32Token, IMG_UINT64 ui64Value)
+{
+ PVRSRVTimeTraceArray(ui32Group, ui32Class, ui32Token, PVRSRV_TRACE_TYPE_UI64,
+ 1, (IMG_UINT8 *) &ui64Value);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVTimeTraceDevVirtAddr)
+#endif
+static INLINE IMG_VOID PVRSRVTimeTraceDevVirtAddr(IMG_UINT32 ui32Group, IMG_UINT32 ui32Class,
+ IMG_UINT32 ui32Token, IMG_DEV_VIRTADDR psVAddr)
+{
+ PVRSRVTimeTraceArray(ui32Group, ui32Class, ui32Token, PVRSRV_TRACE_TYPE_UI32,
+ 1, (IMG_UINT8 *) &psVAddr.uiAddr);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVTimeTraceCpuPhyAddr)
+#endif
+static INLINE IMG_VOID PVRSRVTimeTraceCpuPhyAddr(IMG_UINT32 ui32Group, IMG_UINT32 ui32Class,
+ IMG_UINT32 ui32Token, IMG_CPU_PHYADDR psPAddr)
+{
+ PVRSRVTimeTraceArray(ui32Group, ui32Class, ui32Token, PVRSRV_TRACE_TYPE_UI32,
+ 1, (IMG_UINT8 *) &psPAddr.uiAddr);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVTimeTraceDevPhysAddr)
+#endif
+static INLINE IMG_VOID PVRSRVTimeTraceDevPhysAddr(IMG_UINT32 ui32Group, IMG_UINT32 ui32Class,
+ IMG_UINT32 ui32Token, IMG_DEV_PHYADDR psPAddr)
+{
+ PVRSRVTimeTraceArray(ui32Group, ui32Class, ui32Token, PVRSRV_TRACE_TYPE_UI32,
+ 1, (IMG_UINT8 *) &psPAddr.uiAddr);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVTimeTraceSysPhysAddr)
+#endif
+static INLINE IMG_VOID PVRSRVTimeTraceSysPhysAddr(IMG_UINT32 ui32Group, IMG_UINT32 ui32Class,
+ IMG_UINT32 ui32Token, IMG_SYS_PHYADDR psPAddr)
+{
+ PVRSRVTimeTraceArray(ui32Group, ui32Class, ui32Token, sizeof(psPAddr.uiAddr),
+ 1, (IMG_UINT8 *) &psPAddr.uiAddr);
+}
+
+#else
+
+ #define PVR_TTRACE(group, class, token) \
+ ((void) 0)
+ #define PVR_TTRACE_UI8(group, class, token, val) \
+ ((void) 0)
+ #define PVR_TTRACE_UI16(group, class, token, val) \
+ ((void) 0)
+ #define PVR_TTRACE_UI32(group, class, token, val) \
+ ((void) 0)
+ #define PVR_TTRACE_UI64(group, class, token, val) \
+ ((void) 0)
+ #define PVR_TTRACE_DEV_VIRTADDR(group, class, token, val) \
+ ((void) 0)
+ #define PVR_TTRACE_CPU_PHYADDR(group, class, token, val) \
+ ((void) 0)
+ #define PVR_TTRACE_DEV_PHYADDR(group, class, token, val) \
+ ((void) 0)
+ #define PVR_TTRACE_SYS_PHYADDR(group, class, token, val) \
+ ((void) 0)
+ #define PVR_TTRACE_SYNC_OBJECT(group, token, syncobj, op) \
+ ((void) 0)
+
+#endif
+
+IMG_IMPORT PVRSRV_ERROR PVRSRVTimeTraceInit(IMG_VOID);
+IMG_IMPORT IMG_VOID PVRSRVTimeTraceDeinit(IMG_VOID);
+
+IMG_IMPORT IMG_VOID PVRSRVTimeTraceSyncObject(IMG_UINT32 ui32Group, IMG_UINT32 ui32Token,
+ PVRSRV_KERNEL_SYNC_INFO *psSync, IMG_UINT8 ui8SyncOp);
+IMG_IMPORT PVRSRV_ERROR PVRSRVTimeTraceBufferCreate(IMG_UINT32 ui32PID);
+IMG_IMPORT PVRSRV_ERROR PVRSRVTimeTraceBufferDestroy(IMG_UINT32 ui32PID);
+
+IMG_IMPORT IMG_VOID PVRSRVDumpTimeTraceBuffers(IMG_VOID);
+#endif
diff --git a/drivers/gpu/pvr/ttrace_common.h b/drivers/gpu/pvr/ttrace_common.h
new file mode 100644
index 0000000..5aa6fec
--- /dev/null
+++ b/drivers/gpu/pvr/ttrace_common.h
@@ -0,0 +1,84 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "img_types.h"
+
+#ifndef __TTRACE_COMMON_H__
+#define __TTRACE_COMMON_H__
+
+#define PVRSRV_TRACE_HEADER 0
+#define PVRSRV_TRACE_TIMESTAMP 1
+#define PVRSRV_TRACE_HOSTUID 2
+#define PVRSRV_TRACE_DATA_HEADER 3
+#define PVRSRV_TRACE_DATA_PAYLOAD 4
+
+#define PVRSRV_TRACE_ITEM_SIZE 16
+
+#define PVRSRV_TRACE_GROUP_MASK 0xff
+#define PVRSRV_TRACE_CLASS_MASK 0xff
+#define PVRSRV_TRACE_TOKEN_MASK 0xffff
+
+#define PVRSRV_TRACE_GROUP_SHIFT 24
+#define PVRSRV_TRACE_CLASS_SHIFT 16
+#define PVRSRV_TRACE_TOKEN_SHIFT 0
+
+#define PVRSRV_TRACE_SIZE_MASK 0xffff
+#define PVRSRV_TRACE_TYPE_MASK 0xf
+#define PVRSRV_TRACE_COUNT_MASK 0xfff
+
+#define PVRSRV_TRACE_SIZE_SHIFT 16
+#define PVRSRV_TRACE_TYPE_SHIFT 12
+#define PVRSRV_TRACE_COUNT_SHIFT 0
+
+
+#define WRITE_HEADER(n,m) \
+ ((m & PVRSRV_TRACE_##n##_MASK) << PVRSRV_TRACE_##n##_SHIFT)
+
+#define READ_HEADER(n,m) \
+ ((m & (PVRSRV_TRACE_##n##_MASK << PVRSRV_TRACE_##n##_SHIFT)) >> PVRSRV_TRACE_##n##_SHIFT)
+
+#define TIME_TRACE_BUFFER_SIZE 4096
+
+#define PVRSRV_TRACE_TYPE_UI8 0
+#define PVRSRV_TRACE_TYPE_UI16 1
+#define PVRSRV_TRACE_TYPE_UI32 2
+#define PVRSRV_TRACE_TYPE_UI64 3
+
+#define PVRSRV_TRACE_TYPE_SYNC 15
+ #define PVRSRV_TRACE_SYNC_UID 0
+ #define PVRSRV_TRACE_SYNC_WOP 1
+ #define PVRSRV_TRACE_SYNC_WOC 2
+ #define PVRSRV_TRACE_SYNC_ROP 3
+ #define PVRSRV_TRACE_SYNC_ROC 4
+ #define PVRSRV_TRACE_SYNC_WO_DEV_VADDR 5
+ #define PVRSRV_TRACE_SYNC_RO_DEV_VADDR 6
+ #define PVRSRV_TRACE_SYNC_OP 7
+ #define PVRSRV_TRACE_SYNC_RO2P 8
+ #define PVRSRV_TRACE_SYNC_RO2C 9
+ #define PVRSRV_TRACE_SYNC_RO2_DEV_VADDR 10
+#define PVRSRV_TRACE_TYPE_SYNC_SIZE ((PVRSRV_TRACE_SYNC_RO2_DEV_VADDR + 1) * sizeof(IMG_UINT32))
+
+#endif
diff --git a/drivers/gpu/pvr/ttrace_tokens.h b/drivers/gpu/pvr/ttrace_tokens.h
new file mode 100644
index 0000000..21ea5fb
--- /dev/null
+++ b/drivers/gpu/pvr/ttrace_tokens.h
@@ -0,0 +1,84 @@
+/**********************************************************************
+ *
+ * Copyright (C) Imagination Technologies Ltd. All rights reserved.
+ *
+ * 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, except
+ * as otherwise stated in writing, 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __TTRACE_TOKENS_H__
+#define __TTRACE_TOKENS_H__
+
+#define PVRSRV_TRACE_GROUP_KICK 0
+#define PVRSRV_TRACE_GROUP_TRANSFER 1
+#define PVRSRV_TRACE_GROUP_QUEUE 2
+#define PVRSRV_TRACE_GROUP_POWER 3
+#define PVRSRV_TRACE_GROUP_MKSYNC 4
+
+#define PVRSRV_TRACE_GROUP_PADDING 255
+
+#define PVRSRV_TRACE_CLASS_FUNCTION_ENTER 0
+#define PVRSRV_TRACE_CLASS_FUNCTION_EXIT 1
+#define PVRSRV_TRACE_CLASS_SYNC 2
+#define PVRSRV_TRACE_CLASS_CCB 3
+#define PVRSRV_TRACE_CLASS_CMD_START 4
+#define PVRSRV_TRACE_CLASS_CMD_END 5
+#define PVRSRV_TRACE_CLASS_CMD_COMP_START 6
+#define PVRSRV_TRACE_CLASS_CMD_COMP_END 7
+
+#define PVRSRV_TRACE_CLASS_NONE 255
+
+#define PVRSRV_SYNCOP_SAMPLE 0
+#define PVRSRV_SYNCOP_COMPLETE 1
+#define PVRSRV_SYNCOP_DUMP 2
+
+#define KICK_TOKEN_DOKICK 0
+#define KICK_TOKEN_CCB_OFFSET 1
+#define KICK_TOKEN_TA3D_SYNC 2
+#define KICK_TOKEN_TA_SYNC 3
+#define KICK_TOKEN_3D_SYNC 4
+#define KICK_TOKEN_SRC_SYNC 5
+#define KICK_TOKEN_DST_SYNC 6
+
+#define TRANSFER_TOKEN_SUBMIT 0
+#define TRANSFER_TOKEN_TA_SYNC 1
+#define TRANSFER_TOKEN_3D_SYNC 2
+#define TRANSFER_TOKEN_SRC_SYNC 3
+#define TRANSFER_TOKEN_DST_SYNC 4
+#define TRANSFER_TOKEN_CCB_OFFSET 5
+
+#define QUEUE_TOKEN_GET_SPACE 0
+#define QUEUE_TOKEN_INSERTKM 1
+#define QUEUE_TOKEN_SUBMITKM 2
+#define QUEUE_TOKEN_PROCESS_COMMAND 3
+#define QUEUE_TOKEN_PROCESS_QUEUES 4
+#define QUEUE_TOKEN_COMMAND_COMPLETE 5
+#define QUEUE_TOKEN_UPDATE_DST 6
+#define QUEUE_TOKEN_UPDATE_SRC 7
+#define QUEUE_TOKEN_SRC_SYNC 8
+#define QUEUE_TOKEN_DST_SYNC 9
+#define QUEUE_TOKEN_COMMAND_TYPE 10
+
+#define MKSYNC_TOKEN_KERNEL_CCB_OFFSET 0
+#define MKSYNC_TOKEN_CORE_CLK 1
+#define MKSYNC_TOKEN_UKERNEL_CLK 2
+
+#endif
diff --git a/drivers/hwmon/ads7871.c b/drivers/hwmon/ads7871.c
index 5231934..a5737a5 100644
--- a/drivers/hwmon/ads7871.c
+++ b/drivers/hwmon/ads7871.c
@@ -133,6 +133,12 @@ static ssize_t show_voltage(struct device *dev,
}
}
+static ssize_t ads7871_show_name(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ return sprintf(buf, "%s\n", to_spi_device(dev)->modalias);
+}
+
static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_voltage, NULL, 0);
static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_voltage, NULL, 1);
static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_voltage, NULL, 2);
@@ -142,6 +148,8 @@ static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_voltage, NULL, 5);
static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_voltage, NULL, 6);
static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_voltage, NULL, 7);
+static DEVICE_ATTR(name, S_IRUGO, ads7871_show_name, NULL);
+
static struct attribute *ads7871_attributes[] = {
&sensor_dev_attr_in0_input.dev_attr.attr,
&sensor_dev_attr_in1_input.dev_attr.attr,
@@ -151,6 +159,7 @@ static struct attribute *ads7871_attributes[] = {
&sensor_dev_attr_in5_input.dev_attr.attr,
&sensor_dev_attr_in6_input.dev_attr.attr,
&sensor_dev_attr_in7_input.dev_attr.attr,
+ &dev_attr_name.attr,
NULL
};
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index 4c07436..d99aa84 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -215,7 +215,7 @@ static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len)
int i;
if (send_command(cmd) || send_argument(key)) {
- pr_warn("%s: read arg fail\n", key);
+ pr_warn("%.4s: read arg fail\n", key);
return -EIO;
}
@@ -223,7 +223,7 @@ static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len)
for (i = 0; i < len; i++) {
if (__wait_status(0x05)) {
- pr_warn("%s: read data fail\n", key);
+ pr_warn("%.4s: read data fail\n", key);
return -EIO;
}
buffer[i] = inb(APPLESMC_DATA_PORT);
diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c
index 00e9851..83d2fbd6 100644
--- a/drivers/hwmon/asus_atk0110.c
+++ b/drivers/hwmon/asus_atk0110.c
@@ -34,6 +34,12 @@ static const struct dmi_system_id __initconst atk_force_new_if[] = {
.matches = {
DMI_MATCH(DMI_BOARD_NAME, "SABERTOOTH X58")
}
+ }, {
+ /* Old interface reads the same sensor for fan0 and fan1 */
+ .ident = "Asus M5A78L",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "M5A78L")
+ }
},
{ }
};
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index 3cf2353..87fd034 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -47,16 +47,15 @@
#define MAX_ATTRS 5 /* Maximum no of per-core attrs */
#define MAX_CORE_DATA (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO)
-#ifdef CONFIG_SMP
#define TO_PHYS_ID(cpu) cpu_data(cpu).phys_proc_id
#define TO_CORE_ID(cpu) cpu_data(cpu).cpu_core_id
+#define TO_ATTR_NO(cpu) (TO_CORE_ID(cpu) + BASE_SYSFS_ATTR_NO)
+
+#ifdef CONFIG_SMP
#define for_each_sibling(i, cpu) for_each_cpu(i, cpu_sibling_mask(cpu))
#else
-#define TO_PHYS_ID(cpu) (cpu)
-#define TO_CORE_ID(cpu) (cpu)
#define for_each_sibling(i, cpu) for (i = 0; false; )
#endif
-#define TO_ATTR_NO(cpu) (TO_CORE_ID(cpu) + BASE_SYSFS_ATTR_NO)
/*
* Per-Core Temperature Data
@@ -709,7 +708,7 @@ static void __cpuinit get_core_online(unsigned int cpu)
* sensors. We check this bit only, all the early CPUs
* without thermal sensors will be filtered out.
*/
- if (!cpu_has(c, X86_FEATURE_DTS))
+ if (!cpu_has(c, X86_FEATURE_DTHERM))
return;
if (!pdev) {
diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c
index 9a4c3ab..ac2d6cb 100644
--- a/drivers/hwmon/fam15h_power.c
+++ b/drivers/hwmon/fam15h_power.c
@@ -61,14 +61,14 @@ static ssize_t show_power(struct device *dev,
REG_TDP_RUNNING_AVERAGE, &val);
running_avg_capture = (val >> 4) & 0x3fffff;
running_avg_capture = sign_extend32(running_avg_capture, 21);
- running_avg_range = val & 0xf;
+ running_avg_range = (val & 0xf) + 1;
pci_bus_read_config_dword(f4->bus, PCI_DEVFN(PCI_SLOT(f4->devfn), 5),
REG_TDP_LIMIT3, &val);
tdp_limit = val >> 16;
- curr_pwr_watts = tdp_limit + data->base_tdp -
- (s32)(running_avg_capture >> (running_avg_range + 1));
+ curr_pwr_watts = (tdp_limit + data->base_tdp) << running_avg_range;
+ curr_pwr_watts -= running_avg_capture;
curr_pwr_watts *= data->tdp_to_watts;
/*
@@ -78,7 +78,7 @@ static ssize_t show_power(struct device *dev,
* scaling factor 1/(2^16). For conversion we use
* (10^6)/(2^16) = 15625/(2^10)
*/
- curr_pwr_watts = (curr_pwr_watts * 15625) >> 10;
+ curr_pwr_watts = (curr_pwr_watts * 15625) >> (10 + running_avg_range);
return sprintf(buf, "%u\n", (unsigned int) curr_pwr_watts);
}
static DEVICE_ATTR(power1_input, S_IRUGO, show_power, NULL);
@@ -128,12 +128,12 @@ static bool __devinit fam15h_power_is_internal_node0(struct pci_dev *f4)
* counter saturations resulting in bogus power readings.
* We correct this value ourselves to cope with older BIOSes.
*/
-static DEFINE_PCI_DEVICE_TABLE(affected_device) = {
+static const struct pci_device_id affected_device[] = {
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) },
{ 0 }
};
-static void __devinit tweak_runavg_range(struct pci_dev *pdev)
+static void tweak_runavg_range(struct pci_dev *pdev)
{
u32 val;
@@ -157,6 +157,16 @@ static void __devinit tweak_runavg_range(struct pci_dev *pdev)
REG_TDP_RUNNING_AVERAGE, val);
}
+#ifdef CONFIG_PM
+static int fam15h_power_resume(struct pci_dev *pdev)
+{
+ tweak_runavg_range(pdev);
+ return 0;
+}
+#else
+#define fam15h_power_resume NULL
+#endif
+
static void __devinit fam15h_power_init_data(struct pci_dev *f4,
struct fam15h_power_data *data)
{
@@ -255,6 +265,7 @@ static struct pci_driver fam15h_power_driver = {
.id_table = fam15h_power_id_table,
.probe = fam15h_power_probe,
.remove = __devexit_p(fam15h_power_remove),
+ .resume = fam15h_power_resume,
};
static int __init fam15h_power_init(void)
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index 5f52477..b358c87 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -2057,7 +2057,7 @@ static void __devinit it87_init_device(struct platform_device *pdev)
/* Start monitoring */
it87_write_value(data, IT87_REG_CONFIG,
- (it87_read_value(data, IT87_REG_CONFIG) & 0x36)
+ (it87_read_value(data, IT87_REG_CONFIG) & 0x3e)
| (update_vbat ? 0x41 : 0x01));
}
diff --git a/drivers/hwmon/twl4030-madc-hwmon.c b/drivers/hwmon/twl4030-madc-hwmon.c
index 5724074..b6adfac 100644
--- a/drivers/hwmon/twl4030-madc-hwmon.c
+++ b/drivers/hwmon/twl4030-madc-hwmon.c
@@ -44,12 +44,13 @@ static ssize_t madc_read(struct device *dev,
struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct twl4030_madc_request req;
+ struct twl4030_madc_request req = {
+ .channels = 1 << attr->index,
+ .method = TWL4030_MADC_SW2,
+ .type = TWL4030_MADC_WAIT,
+ };
long val;
- req.channels = (1 << attr->index);
- req.method = TWL4030_MADC_SW2;
- req.func_cb = NULL;
val = twl4030_madc_conversion(&req);
if (val < 0)
return val;
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index a76d85f..79b4bcb 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -755,7 +755,7 @@ static int davinci_i2c_remove(struct platform_device *pdev)
dev->clk = NULL;
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, 0);
- free_irq(IRQ_I2C, dev);
+ free_irq(dev->irq, dev);
iounmap(dev->base);
kfree(dev);
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index f84a63c..61c9365 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -201,18 +201,29 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret)
{
- unsigned long iicstat = readl(i2c->regs + S3C2410_IICSTAT);
+ unsigned long iicstat;
+ unsigned long iiccon;
dev_dbg(i2c->dev, "STOP\n");
/* stop the transfer */
+
+ /* Disable irq */
+ s3c24xx_i2c_disable_irq(i2c);
+
+ /* STOP signal generation : MTx(0xD0) */
+ iicstat = readl(i2c->regs + S3C2410_IICSTAT);
iicstat &= ~S3C2410_IICSTAT_START;
writel(iicstat, i2c->regs + S3C2410_IICSTAT);
- i2c->state = STATE_STOP;
+ /* Clear pending bit */
+ iiccon = readl(i2c->regs + S3C2410_IICCON);
+ iiccon &= ~S3C2410_IICCON_IRQPEND;
+ writel(iiccon, i2c->regs + S3C2410_IICCON);
s3c24xx_i2c_master_complete(i2c, ret);
- s3c24xx_i2c_disable_irq(i2c);
+
+ i2c->state = STATE_STOP;
}
/* helper functions to determine the current state in the set of
@@ -469,6 +480,10 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c)
msleep(1);
}
+ writel(iicstat & ~S3C2410_IICSTAT_TXRXEN, i2c->regs + S3C2410_IICSTAT);
+ if (!(readl(i2c->regs + S3C2410_IICSTAT) & S3C2410_IICSTAT_BUSBUSY))
+ return 0;
+
return -ETIMEDOUT;
}
@@ -524,6 +539,7 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
/* first, try busy waiting briefly */
do {
+ cpu_relax();
iicstat = readl(i2c->regs + S3C2410_IICSTAT);
} while ((iicstat & S3C2410_IICSTAT_START) && --spins);
@@ -533,8 +549,24 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
iicstat = readl(i2c->regs + S3C2410_IICSTAT);
}
- if (iicstat & S3C2410_IICSTAT_START)
- dev_warn(i2c->dev, "timeout waiting for bus idle\n");
+ /* if still not finished, clean it up */
+ spin_lock_irq(&i2c->lock);
+
+ if (iicstat & S3C2410_IICSTAT_BUSBUSY) {
+ dev_dbg(i2c->dev, "timeout waiting for bus idle\n");
+
+ if (i2c->state != STATE_STOP) {
+ dev_dbg(i2c->dev,
+ "timeout : i2c interrupt hasn't occurred\n");
+ s3c24xx_i2c_stop(i2c, 0);
+ }
+
+ /* Disable Serial Out : To forcely terminate the connection */
+ iicstat = readl(i2c->regs + S3C2410_IICSTAT);
+ iicstat &= ~S3C2410_IICSTAT_TXRXEN;
+ writel(iicstat, i2c->regs + S3C2410_IICSTAT);
+ }
+ spin_unlock_irq(&i2c->lock);
out:
return ret;
@@ -661,23 +693,6 @@ static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got)
writel(iiccon, i2c->regs + S3C2410_IICCON);
- if (s3c24xx_i2c_is2440(i2c)) {
- unsigned long sda_delay;
-
- if (pdata->sda_delay) {
- sda_delay = clkin * pdata->sda_delay;
- sda_delay = DIV_ROUND_UP(sda_delay, 1000000);
- sda_delay = DIV_ROUND_UP(sda_delay, 5);
- if (sda_delay > 3)
- sda_delay = 3;
- sda_delay |= S3C2410_IICLC_FILTER_ON;
- } else
- sda_delay = 0;
-
- dev_dbg(i2c->dev, "IICLC=%08lx\n", sda_delay);
- writel(sda_delay, i2c->regs + S3C2440_IICLC);
- }
-
return 0;
}
@@ -694,6 +709,8 @@ static int s3c24xx_i2c_cpufreq_transition(struct notifier_block *nb,
int delta_f;
int ret;
+ clk_enable(i2c->clk);
+
delta_f = clk_get_rate(i2c->clk) - i2c->clkrate;
/* if we're post-change and the input clock has slowed down
@@ -713,6 +730,8 @@ static int s3c24xx_i2c_cpufreq_transition(struct notifier_block *nb,
dev_info(i2c->dev, "setting freq %d\n", got);
}
+ clk_disable(i2c->clk);
+
return 0;
}
@@ -765,7 +784,7 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
writeb(pdata->slave_addr, i2c->regs + S3C2410_IICADD);
- dev_info(i2c->dev, "slave address 0x%02x\n", pdata->slave_addr);
+ dev_dbg(i2c->dev, "slave address 0x%02x\n", pdata->slave_addr);
writel(iicon, i2c->regs + S3C2410_IICCON);
@@ -779,9 +798,12 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
/* todo - check that the i2c lines aren't being dragged anywhere */
- dev_info(i2c->dev, "bus frequency set to %d KHz\n", freq);
+ dev_dbg(i2c->dev, "bus frequency set to %d KHz\n", freq);
dev_dbg(i2c->dev, "S3C2410_IICCON=0x%02lx\n", iicon);
+ dev_dbg(i2c->dev, "S3C2440_IICLC=%08x\n", pdata->sda_delay);
+ writel(pdata->sda_delay, i2c->regs + S3C2440_IICLC);
+
return 0;
}
@@ -823,6 +845,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
i2c->dev = &pdev->dev;
i2c->clk = clk_get(&pdev->dev, "i2c");
+
if (IS_ERR(i2c->clk)) {
dev_err(&pdev->dev, "cannot get clock\n");
ret = -ENOENT;
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
index daa93e9..267005d 100644
--- a/drivers/infiniband/hw/cxgb4/cm.c
+++ b/drivers/infiniband/hw/cxgb4/cm.c
@@ -2316,6 +2316,12 @@ static int peer_abort_intr(struct c4iw_dev *dev, struct sk_buff *skb)
unsigned int tid = GET_TID(req);
ep = lookup_tid(t, tid);
+ if (!ep) {
+ printk(KERN_WARNING MOD
+ "Abort on non-existent endpoint, tid %d\n", tid);
+ kfree_skb(skb);
+ return 0;
+ }
if (is_neg_adv_abort(req->status)) {
PDBG("%s neg_adv_abort ep %p tid %u\n", __func__, ep,
ep->hwtid);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index b811444..6ea9600 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -148,7 +148,7 @@ static int ipoib_stop(struct net_device *dev)
netif_stop_queue(dev);
- ipoib_ib_dev_down(dev, 0);
+ ipoib_ib_dev_down(dev, 1);
ipoib_ib_dev_stop(dev, 0);
if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) {
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index 8b63506..fc04594 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -189,7 +189,9 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
mcast->mcmember = *mcmember;
- /* Set the cached Q_Key before we attach if it's the broadcast group */
+ /* Set the multicast MTU and cached Q_Key before we attach if it's
+ * the broadcast group.
+ */
if (!memcmp(mcast->mcmember.mgid.raw, priv->dev->broadcast + 4,
sizeof (union ib_gid))) {
spin_lock_irq(&priv->lock);
@@ -197,10 +199,17 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
spin_unlock_irq(&priv->lock);
return -EAGAIN;
}
+ priv->mcast_mtu = IPOIB_UD_MTU(ib_mtu_enum_to_int(priv->broadcast->mcmember.mtu));
priv->qkey = be32_to_cpu(priv->broadcast->mcmember.qkey);
spin_unlock_irq(&priv->lock);
priv->tx_wr.wr.ud.remote_qkey = priv->qkey;
set_qkey = 1;
+
+ if (!ipoib_cm_admin_enabled(dev)) {
+ rtnl_lock();
+ dev_set_mtu(dev, min(priv->mcast_mtu, priv->admin_mtu));
+ rtnl_unlock();
+ }
}
if (!test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)) {
@@ -586,14 +595,6 @@ void ipoib_mcast_join_task(struct work_struct *work)
return;
}
- priv->mcast_mtu = IPOIB_UD_MTU(ib_mtu_enum_to_int(priv->broadcast->mcmember.mtu));
-
- if (!ipoib_cm_admin_enabled(dev)) {
- rtnl_lock();
- dev_set_mtu(dev, min(priv->mcast_mtu, priv->admin_mtu));
- rtnl_unlock();
- }
-
ipoib_dbg_mcast(priv, "successfully joined all multicast groups\n");
clear_bit(IPOIB_MCAST_RUN, &priv->flags);
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 7d5109b..aa5eafa 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -568,24 +568,62 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd,
scmnd->sc_data_direction);
}
-static void srp_remove_req(struct srp_target_port *target,
- struct srp_request *req, s32 req_lim_delta)
+/**
+ * srp_claim_req - Take ownership of the scmnd associated with a request.
+ * @target: SRP target port.
+ * @req: SRP request.
+ * @scmnd: If NULL, take ownership of @req->scmnd. If not NULL, only take
+ * ownership of @req->scmnd if it equals @scmnd.
+ *
+ * Return value:
+ * Either NULL or a pointer to the SCSI command the caller became owner of.
+ */
+static struct scsi_cmnd *srp_claim_req(struct srp_target_port *target,
+ struct srp_request *req,
+ struct scsi_cmnd *scmnd)
{
unsigned long flags;
- srp_unmap_data(req->scmnd, target, req);
+ spin_lock_irqsave(&target->lock, flags);
+ if (!scmnd) {
+ scmnd = req->scmnd;
+ req->scmnd = NULL;
+ } else if (req->scmnd == scmnd) {
+ req->scmnd = NULL;
+ } else {
+ scmnd = NULL;
+ }
+ spin_unlock_irqrestore(&target->lock, flags);
+
+ return scmnd;
+}
+
+/**
+ * srp_free_req() - Unmap data and add request to the free request list.
+ */
+static void srp_free_req(struct srp_target_port *target,
+ struct srp_request *req, struct scsi_cmnd *scmnd,
+ s32 req_lim_delta)
+{
+ unsigned long flags;
+
+ srp_unmap_data(scmnd, target, req);
+
spin_lock_irqsave(&target->lock, flags);
target->req_lim += req_lim_delta;
- req->scmnd = NULL;
list_add_tail(&req->list, &target->free_reqs);
spin_unlock_irqrestore(&target->lock, flags);
}
static void srp_reset_req(struct srp_target_port *target, struct srp_request *req)
{
- req->scmnd->result = DID_RESET << 16;
- req->scmnd->scsi_done(req->scmnd);
- srp_remove_req(target, req, 0);
+ struct scsi_cmnd *scmnd = srp_claim_req(target, req, NULL);
+
+ if (scmnd) {
+ srp_free_req(target, req, scmnd, 0);
+ scmnd->result = DID_RESET << 16;
+ scmnd->scsi_done(scmnd);
+ }
}
static int srp_reconnect_target(struct srp_target_port *target)
@@ -1055,11 +1093,18 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
complete(&target->tsk_mgmt_done);
} else {
req = &target->req_ring[rsp->tag];
- scmnd = req->scmnd;
- if (!scmnd)
+ scmnd = srp_claim_req(target, req, NULL);
+ if (!scmnd) {
shost_printk(KERN_ERR, target->scsi_host,
"Null scmnd for RSP w/tag %016llx\n",
(unsigned long long) rsp->tag);
+
+ spin_lock_irqsave(&target->lock, flags);
+ target->req_lim += be32_to_cpu(rsp->req_lim_delta);
+ spin_unlock_irqrestore(&target->lock, flags);
+
+ return;
+ }
scmnd->result = rsp->status;
if (rsp->flags & SRP_RSP_FLAG_SNSVALID) {
@@ -1074,7 +1119,9 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
else if (rsp->flags & (SRP_RSP_FLAG_DIOVER | SRP_RSP_FLAG_DIUNDER))
scsi_set_resid(scmnd, be32_to_cpu(rsp->data_in_res_cnt));
- srp_remove_req(target, req, be32_to_cpu(rsp->req_lim_delta));
+ srp_free_req(target, req, scmnd,
+ be32_to_cpu(rsp->req_lim_delta));
+
scmnd->host_scribble = NULL;
scmnd->scsi_done(scmnd);
}
@@ -1613,25 +1660,18 @@ static int srp_abort(struct scsi_cmnd *scmnd)
{
struct srp_target_port *target = host_to_target(scmnd->device->host);
struct srp_request *req = (struct srp_request *) scmnd->host_scribble;
- int ret = SUCCESS;
shost_printk(KERN_ERR, target->scsi_host, "SRP abort called\n");
- if (!req || target->qp_in_error)
- return FAILED;
- if (srp_send_tsk_mgmt(target, req->index, scmnd->device->lun,
- SRP_TSK_ABORT_TASK))
+ if (!req || target->qp_in_error || !srp_claim_req(target, req, scmnd))
return FAILED;
+ srp_send_tsk_mgmt(target, req->index, scmnd->device->lun,
+ SRP_TSK_ABORT_TASK);
+ srp_free_req(target, req, scmnd, 0);
+ scmnd->result = DID_ABORT << 16;
+ scmnd->scsi_done(scmnd);
- if (req->scmnd) {
- if (!target->tsk_mgmt_status) {
- srp_remove_req(target, req, 0);
- scmnd->result = DID_ABORT << 16;
- } else
- ret = FAILED;
- }
-
- return ret;
+ return SUCCESS;
}
static int srp_reset_device(struct scsi_cmnd *scmnd)
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 56abf3d..92c7be1 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -142,6 +142,7 @@ static const struct xpad_device {
{ 0x0c12, 0x880a, "Pelican Eclipse PL-2023", 0, XTYPE_XBOX },
{ 0x0c12, 0x8810, "Zeroplus Xbox Controller", 0, XTYPE_XBOX },
{ 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", 0, XTYPE_XBOX },
+ { 0x0d2f, 0x0002, "Andamiro Pump It Up pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
{ 0x0e4c, 0x1097, "Radica Gamester Controller", 0, XTYPE_XBOX },
{ 0x0e4c, 0x2390, "Radica Games Jtech Controller", 0, XTYPE_XBOX },
{ 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", 0, XTYPE_XBOX },
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index b4dee9d..9f629bb 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -563,4 +563,13 @@ config KEYBOARD_W90P910
To compile this driver as a module, choose M here: the
module will be called w90p910_keypad.
+config KEYPAD_CYPRESS_TOUCH
+ tristate "Cypress touch keypad support"
+ default n
+ help
+ Say Y here if you want to use the Cypress touch keypad.
+
+ To compile this driver as a module, choose M here: the
+ module will be called cypress-touchkey.
+
endif
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index ddde0fd..27a47bf 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -51,3 +51,5 @@ obj-$(CONFIG_KEYBOARD_TNETV107X) += tnetv107x-keypad.o
obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o
obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o
obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o
+obj-$(CONFIG_KEYPAD_CYPRESS_TOUCH) += cypress-touchkey.o
+obj-$(CONFIG_KEYPAD_CYPRESS_TOUCH) += cypress-touchkey-firmware.o
diff --git a/drivers/input/keyboard/cypress-touchkey-firmware.c b/drivers/input/keyboard/cypress-touchkey-firmware.c
new file mode 100644
index 0000000..b1be506
--- /dev/null
+++ b/drivers/input/keyboard/cypress-touchkey-firmware.c
@@ -0,0 +1,322 @@
+/*
+ * Copyright 2010, Cypress Semiconductor Corporation.
+ * Copyright (C) 2010-2011, Samsung Electronics Co. Ltd. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/input/cypress-touchkey.h>
+#include <linux/gpio.h>
+
+#include "cypress-touchkey-firmware.h"
+
+#define WRITE_BYTE_START 0x90
+#define WRITE_BYTE_END 0xE0
+#define NUM_BLOCK_END 0xE0
+
+static void touchkey_init_gpio(struct touchkey_platform_data *pdata)
+{
+ gpio_direction_input(pdata->sda_pin);
+ gpio_direction_input(pdata->scl_pin);
+ gpio_set_value(pdata->en_pin, 1);
+ mdelay(1);
+}
+
+static void touchkey_run_clk(struct touchkey_platform_data *pdata,
+ int cycles)
+{
+ int i;
+
+ for (i = 0; i < cycles; i++) {
+ gpio_direction_output(pdata->scl_pin, 0);
+ gpio_direction_output(pdata->scl_pin, 1);
+ }
+}
+
+static u8 touchkey_get_data(struct touchkey_platform_data *pdata)
+{
+ gpio_direction_input(pdata->sda_pin);
+ return !!gpio_get_value(pdata->sda_pin);
+}
+
+static u8 touchkey_read_bit(struct touchkey_platform_data *pdata)
+{
+ touchkey_run_clk(pdata, 1);
+ return touchkey_get_data(pdata);
+}
+
+static u8 touchkey_read_byte(struct touchkey_platform_data *pdata)
+{
+ int i;
+ u8 byte = 0;
+
+ for (i = 7; i >= 0; i--)
+ byte |= touchkey_read_bit(pdata) << i;
+
+ return byte;
+}
+
+static void touchkey_send_bits(struct touchkey_platform_data *pdata,
+ u8 data, int num_bits)
+{
+ int i;
+
+ for (i = 0; i < num_bits; i++, data <<= 1) {
+ gpio_direction_output(pdata->sda_pin, !!(data & 0x80));
+ gpio_direction_output(pdata->scl_pin, 1);
+ gpio_direction_output(pdata->scl_pin, 0);
+ }
+}
+
+static void touchkey_send_vector(struct touchkey_platform_data *pdata,
+ const struct issp_vector *vector_data)
+{
+ int i;
+ u16 num_bits;
+
+ for (i = 0, num_bits = vector_data->num_bits; num_bits > 7;
+ num_bits -= 8, i++)
+ touchkey_send_bits(pdata, vector_data->data[i], 8);
+
+ if (num_bits)
+ touchkey_send_bits(pdata, vector_data->data[i], num_bits);
+ gpio_direction_output(pdata->sda_pin, 0);
+ gpio_direction_input(pdata->sda_pin);
+}
+
+static bool touchkey_wait_transaction(struct touchkey_platform_data *pdata)
+{
+ int i;
+
+ for (i = 0; i <= TRANSITION_TIMEOUT; i++) {
+ gpio_direction_output(pdata->scl_pin, 0);
+ if (touchkey_get_data(pdata))
+ break;
+ gpio_direction_output(pdata->scl_pin, 1);
+ }
+
+ if (i == TRANSITION_TIMEOUT)
+ return true;
+
+ for (i = 0; i <= TRANSITION_TIMEOUT; i++) {
+ gpio_direction_output(pdata->scl_pin, 0);
+ if (!touchkey_get_data(pdata))
+ break;
+ gpio_direction_output(pdata->scl_pin, 1);
+ }
+
+ return i == TRANSITION_TIMEOUT;
+}
+
+static int touchkey_issp_pwr_init(struct touchkey_platform_data *pdata)
+{
+ touchkey_init_gpio(pdata);
+ if (touchkey_wait_transaction(pdata))
+ return -1;
+
+ gpio_direction_output(pdata->scl_pin, 0);
+
+ touchkey_send_vector(pdata, &wait_and_poll_end);
+ touchkey_send_vector(pdata, &id_setup_1);
+ if (touchkey_wait_transaction(pdata))
+ return -1;
+
+ touchkey_send_vector(pdata, &wait_and_poll_end);
+ return 0;
+}
+
+static int touchkey_read_status(struct touchkey_platform_data *pdata)
+{
+ unsigned char target_status;
+
+ touchkey_send_vector(pdata, &tsync_enable);
+
+ touchkey_send_vector(pdata, &read_id_v1);
+ touchkey_run_clk(pdata, 2);
+ target_status = touchkey_read_byte(pdata);
+ touchkey_run_clk(pdata, 1);
+
+ touchkey_send_bits(pdata, 0, 1);
+ touchkey_send_vector(pdata, &tsync_disable);
+
+ return target_status;
+}
+
+static int touchkey_erase_target(struct touchkey_platform_data *pdata)
+{
+ touchkey_send_vector(pdata, &erase);
+ if (touchkey_wait_transaction(pdata))
+ return -1;
+
+ touchkey_send_vector(pdata, &wait_and_poll_end);
+ return 0;
+}
+
+static u16 touchkey_load_target(struct touchkey_platform_data *pdata,
+ const u8 *target_data_output, int len)
+{
+ u16 checksum_data = 0;
+ u8 addr;
+ int i;
+
+ for (i = 0, addr = 0; i < len; i++, addr += 2) {
+ checksum_data += target_data_output[i];
+ touchkey_send_bits(pdata, WRITE_BYTE_START, 4);
+ touchkey_send_bits(pdata, addr, 7);
+ touchkey_send_bits(pdata, target_data_output[i], 8);
+ touchkey_send_bits(pdata, WRITE_BYTE_END, 3);
+ }
+
+ return checksum_data;
+}
+
+static int touchkey_program_target_block(struct touchkey_platform_data *pdata,
+ u8 block)
+{
+ touchkey_send_vector(pdata, &tsync_enable);
+ touchkey_send_vector(pdata, &set_block_num);
+ touchkey_send_bits(pdata, block, 8);
+ touchkey_send_bits(pdata, NUM_BLOCK_END, 3);
+ touchkey_send_vector(pdata, &tsync_disable);
+ touchkey_send_vector(pdata, &program_and_verify);
+
+ if (touchkey_wait_transaction(pdata))
+ return -1;
+
+ touchkey_send_vector(pdata, &wait_and_poll_end);
+ return 0;
+}
+
+static int touchkey_target_bank_checksum(struct touchkey_platform_data *pdata,
+ u16 *checksum)
+{
+ touchkey_send_vector(pdata, &checksum_setup);
+ if (touchkey_wait_transaction(pdata))
+ return -1;
+
+ touchkey_send_vector(pdata, &wait_and_poll_end);
+ touchkey_send_vector(pdata, &tsync_enable);
+ touchkey_send_vector(pdata, &read_checksum_v1);
+ touchkey_run_clk(pdata, 2);
+ *checksum = touchkey_read_byte(pdata) << 8;
+
+ touchkey_run_clk(pdata, 1);
+ touchkey_send_vector(pdata, &read_checksum_v2);
+ touchkey_run_clk(pdata, 2);
+ *checksum |= touchkey_read_byte(pdata);
+ touchkey_run_clk(pdata, 1);
+ touchkey_send_bits(pdata, 0x80, 1);
+ touchkey_send_vector(pdata, &tsync_disable);
+
+ return 0;
+}
+
+static void touchkey_reset_target(struct touchkey_platform_data *pdata)
+{
+ gpio_direction_input(pdata->scl_pin);
+ gpio_direction_input(pdata->sda_pin);
+ gpio_set_value(pdata->en_pin, 0);
+ mdelay(300);
+ touchkey_init_gpio(pdata);
+}
+
+static int touchkey_secure_target_flash(struct touchkey_platform_data *pdata)
+{
+ u8 addr;
+ int i;
+
+ for (i = 0, addr = 0; i < SECURITY_BYTES_PER_BANK; i++, addr += 2) {
+ touchkey_send_bits(pdata, WRITE_BYTE_START, 4);
+ touchkey_send_bits(pdata, addr, 7);
+ touchkey_send_bits(pdata, 0xFF, 8);
+ touchkey_send_bits(pdata, WRITE_BYTE_END, 3);
+ }
+
+ touchkey_send_vector(pdata, &secure);
+ if (touchkey_wait_transaction(pdata))
+ return -1;
+
+ touchkey_send_vector(pdata, &wait_and_poll_end);
+ return 0;
+}
+
+int touchkey_flash_firmware(struct touchkey_platform_data *pdata,
+ const u8 *fw_data)
+{
+ u16 chksumtgt = 0;
+ u16 chksumdat = 0;
+ int i;
+
+ gpio_direction_output(pdata->en_pin, 0);
+
+ if (touchkey_issp_pwr_init(pdata)) {
+ pr_err("%s: error powering up\n", __func__);
+ goto error_trap;
+ }
+
+ if (touchkey_erase_target(pdata)) {
+ pr_err("%s: error erasing flash\n", __func__);
+ goto error_trap;
+ }
+
+ for (i = 0; i < BLOCKS_PER_BANK; i++) {
+ touchkey_send_vector(pdata, &tsync_enable);
+ touchkey_send_vector(pdata, &read_write_setup);
+ chksumdat += touchkey_load_target(pdata,
+ fw_data + i * BLOCK_SIZE, BLOCK_SIZE);
+
+ if (touchkey_program_target_block(pdata, i)) {
+ pr_err("%s: error programming flash\n", __func__);
+ goto error_trap;
+ }
+
+ if (touchkey_read_status(pdata)) {
+ pr_err("%s: error reading status\n", __func__);
+ goto error_trap;
+ }
+ }
+
+ /* security start */
+ touchkey_send_vector(pdata, &tsync_enable);
+ touchkey_send_vector(pdata, &read_write_setup);
+ if (touchkey_secure_target_flash(pdata)) {
+ pr_err("%s: error securing flash\n", __func__);
+ goto error_trap;
+ }
+
+ if (touchkey_target_bank_checksum(pdata, &chksumtgt)) {
+ pr_err("%s: error reading checksum\n", __func__);
+ goto error_trap;
+ }
+
+ if (chksumtgt != chksumdat) {
+ pr_err("%s: error powering up touchkey controller\n", __func__);
+ goto error_trap;
+ }
+
+ touchkey_reset_target(pdata);
+ return 0;
+
+error_trap:
+ gpio_direction_input(pdata->scl_pin);
+ gpio_direction_input(pdata->sda_pin);
+ gpio_set_value(pdata->en_pin, 0);
+ mdelay(20);
+ return -1;
+}
diff --git a/drivers/input/keyboard/cypress-touchkey-firmware.h b/drivers/input/keyboard/cypress-touchkey-firmware.h
new file mode 100644
index 0000000..cdfcea4
--- /dev/null
+++ b/drivers/input/keyboard/cypress-touchkey-firmware.h
@@ -0,0 +1,212 @@
+/*
+ * Copyright 2010, Cypress Semiconductor Corporation.
+ * Copyright (C) 2010-2011, Samsung Electronics Co. Ltd. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <linux/types.h>
+
+#ifndef _CYPRESS_TOUCHKEY_FIRMWARE_H__
+#define _CYPRESS_TOUCHKEY_FIRMWARE_H__
+
+struct issp_vector {
+ u16 num_bits;
+ u8 data[];
+};
+
+static const struct issp_vector tsync_enable = {
+ .data = {
+ 0xDE, 0xE2, 0x1F, 0x7F, 0x02, 0x7D, 0xC4, 0x09,
+ 0xF7, 0x00, 0x1F, 0xDE, 0xE0, 0x1C
+ },
+ .num_bits = 110,
+};
+
+static const struct issp_vector tsync_disable = {
+ .data = {
+ 0xDE, 0xE2, 0x1F, 0x71, 0x00, 0x7D, 0xFC, 0x01,
+ 0xF7, 0x00, 0x1F, 0xDE, 0xE0, 0x1C
+ },
+ .num_bits = 110,
+};
+
+static const struct issp_vector id_setup_1 = {
+ .data = {
+ 0xCA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0D, 0xEE, 0x21, 0xF7, 0xF0, 0x27, 0xDC, 0x40,
+ 0x9F, 0x70, 0x01, 0xFD, 0xEE, 0x01, 0xE7, 0xC1,
+ 0xD7, 0x9F, 0x20, 0x7E, 0x7D, 0x88, 0x7D, 0xEE,
+ 0x21, 0xF7, 0xF0, 0x07, 0xDC, 0x40, 0x1F, 0x70,
+ 0x01, 0xFD, 0xEE, 0x01, 0xF7, 0xA0, 0x1F, 0xDE,
+ 0xA0, 0x1F, 0x7B, 0x00, 0x7D, 0xE0, 0x13, 0xF7,
+ 0xC0, 0x07, 0xDF, 0x28, 0x1F, 0x7D, 0x18, 0x7D,
+ 0xFE, 0x25, 0xC0
+ },
+ .num_bits = 594,
+};
+
+static const struct issp_vector set_block_num = {
+ .data = {
+ 0x9f, 0x40, 0x1c
+ },
+ .num_bits = 11,
+};
+
+static const struct issp_vector read_write_setup = {
+ .data = {
+ 0xde, 0xf0, 0x1f, 0x78, 0x00, 0x7d, 0xa0, 0x03,
+ 0xc0
+ },
+ .num_bits = 66,
+};
+
+static const struct issp_vector erase = {
+ .data = {
+ 0xde, 0xe2, 0x1f, 0x7f, 0x02, 0x7d, 0xc4, 0x09,
+ 0xf7, 0x00, 0x1f, 0x9f, 0x07, 0x5e, 0x7c, 0x85,
+ 0xfd, 0xfc, 0x01, 0xf7, 0x10, 0x07, 0xdc, 0x00,
+ 0x7f, 0x7b, 0x80, 0x7d, 0xe0, 0x0b, 0xf7, 0xa0,
+ 0x1f, 0xd7, 0xa0, 0x1f, 0x7b, 0x04, 0x7d, 0xf0,
+ 0x01, 0xf7, 0xc9, 0x87, 0xdf, 0x48, 0x1f, 0x7f,
+ 0x89, 0x70
+ },
+ .num_bits = 396,
+};
+
+static const struct issp_vector secure = {
+ .data = {
+ 0xde, 0xe2, 0x1f, 0x7f, 0x02, 0x7d, 0xc4, 0x09,
+ 0xf7, 0x00, 0x1f, 0x9f, 0x07, 0x5e, 0x7c, 0x81,
+ 0xf9, 0xf7, 0x01, 0xf7, 0xf0, 0x07, 0xdc, 0x40,
+ 0x1f, 0x70, 0x01, 0xfd, 0xee, 0x01, 0xf6, 0xa0,
+ 0x0f, 0xde, 0x80, 0x7f, 0x7a, 0x80, 0x7d, 0xec,
+ 0x01, 0xf7, 0x80, 0x27, 0xdf, 0x00, 0x1f, 0x7c,
+ 0xa0, 0x7d, 0xf4, 0x61, 0xf7, 0xf8, 0x97
+ },
+ .num_bits = 440,
+};
+
+static const struct issp_vector read_security_setup = {
+ .data = {
+ 0xde, 0xe2, 0x1f, 0x60, 0x88, 0x7d, 0x84, 0x21,
+ 0xf7, 0xb8, 0x07
+ },
+ .num_bits = 88,
+};
+
+static const struct issp_vector read_security_pt1 = {
+ .data = {
+ 0xde, 0xe2, 0x1f, 0x72, 0x87, 0x7d, 0xca, 0x01,
+ 0xf7, 0x28
+ },
+ .num_bits = 78,
+};
+
+static const struct issp_vector read_security_pt1_end = {
+ .data = {
+ 0xfb, 0x94, 0x03, 0x80
+ },
+ .num_bits = 25,
+};
+
+static const struct issp_vector read_security_pt2 = {
+ .data = {
+ 0xde, 0xe0, 0x1f, 0x7a, 0x01, 0xfd, 0xea, 0x01,
+ 0xf7, 0xb0, 0x07, 0xdf, 0x0b, 0xbf, 0x7c, 0xf2,
+ 0xfd, 0xf4, 0x61, 0xf7, 0xb8, 0x87, 0xdf, 0xe2,
+ 0x5c
+ },
+ .num_bits = 198,
+};
+
+static const struct issp_vector read_security_pt3 = {
+ .data = {
+ 0xde, 0xe0, 0x1f, 0x7a, 0x01, 0xfd, 0xea, 0x01,
+ 0xf7, 0xb0, 0x07, 0xdf, 0x0a, 0x7f, 0x7c, 0xc0
+ },
+ .num_bits = 122,
+};
+
+static const struct issp_vector read_security_pt3_end = {
+ .data = {
+ 0xfb, 0xe8, 0xc3, 0xef, 0xf1, 0x2e
+ },
+ .num_bits = 47,
+};
+
+static const struct issp_vector checksum_setup = {
+ .data = {
+ 0xde, 0xe2, 0x1f, 0x7f, 0x02, 0x7d, 0xc4, 0x09,
+ 0xf7, 0x00, 0x1f, 0x9f, 0x07, 0x5e, 0x7c, 0x81,
+ 0xf9, 0xf4, 0x01, 0xf7, 0xf0, 0x07, 0xdc, 0x40,
+ 0x1f, 0x70, 0x01, 0xfd, 0xee, 0x01, 0xf7, 0xa0,
+ 0x1f, 0xde, 0xa0, 0x1f, 0x7b, 0x00, 0x7d, 0xe0,
+ 0x0f, 0xf7, 0xc0, 0x07, 0xdf, 0x28, 0x1f, 0x7d,
+ 0x18, 0x7d, 0xfe, 0x25, 0xc0
+ },
+ .num_bits = 418,
+};
+
+static const struct issp_vector program_and_verify = {
+ .data = {
+ 0xde, 0xe2, 0x1f, 0x7f, 0x02, 0x7d, 0xc4, 0x09,
+ 0xf7, 0x00, 0x1f, 0x9f, 0x07, 0x5e, 0x7c, 0x81,
+ 0xf9, 0xf7, 0x01, 0xf7, 0xf0, 0x07, 0xdc, 0x40,
+ 0x1f, 0x70, 0x01, 0xfd, 0xee, 0x01, 0xf6, 0xa0,
+ 0x0f, 0xde, 0x80, 0x7f, 0x7a, 0x80, 0x7d, 0xec,
+ 0x01, 0xf7, 0x80, 0x57, 0xdf, 0x00, 0x1f, 0x7c,
+ 0xa0, 0x7d, 0xf4, 0x61, 0xf7, 0xf8, 0x97
+ },
+ .num_bits = 440,
+};
+
+static const struct issp_vector read_id_v1 = {
+ .data = {
+ 0xBF, 0x00
+ },
+ .num_bits = 11,
+};
+
+static const struct issp_vector wait_and_poll_end = {
+ .data = {
+ 0x00, 0x00, 0x00, 0x00
+ },
+ .num_bits = 30,
+};
+
+static const struct issp_vector read_checksum_v1 = {
+ .data = {
+ 0xBF, 0x20
+ },
+ .num_bits = 11,
+};
+
+static const struct issp_vector read_checksum_v2 = {
+ .data = {
+ 0xDF, 0x80
+ },
+ .num_bits = 12,
+};
+
+#define BLOCK_SIZE 128
+#define BLOCKS_PER_BANK 64
+#define SECURITY_BYTES_PER_BANK 64
+#define TRANSITION_TIMEOUT 0x100000
+
+#endif /* _CYPRESS_TOUCHKEY_FIRMWARE_H__ */
diff --git a/drivers/input/keyboard/cypress-touchkey.c b/drivers/input/keyboard/cypress-touchkey.c
new file mode 100755
index 0000000..3e4c75d
--- /dev/null
+++ b/drivers/input/keyboard/cypress-touchkey.c
@@ -0,0 +1,632 @@
+/*
+ * Copyright 2006-2010, Cypress Semiconductor Corporation.
+ * Copyright (C) 2010, Samsung Electronics Co. Ltd. All Rights Reserved.
+ * Copyright 2011, Michael Richter (alias neldar)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/earlysuspend.h>
+#include <linux/input/cypress-touchkey.h>
+#include <linux/firmware.h>
+#include <linux/bln.h>
+
+#ifdef CONFIG_BLD
+#include <linux/bld.h>
+#endif
+
+#define SCANCODE_MASK 0x07
+#define UPDOWN_EVENT_MASK 0x08
+#define ESD_STATE_MASK 0x10
+
+#define BACKLIGHT_ON 0x10
+#define BACKLIGHT_OFF 0x20
+
+#define OLD_BACKLIGHT_ON 0x1
+#define OLD_BACKLIGHT_OFF 0x2
+
+#define DEVICE_NAME "cypress-touchkey"
+
+#define FW_SIZE 8192
+
+struct cypress_touchkey_devdata {
+ struct i2c_client *client;
+ struct input_dev *input_dev;
+ struct touchkey_platform_data *pdata;
+ struct early_suspend early_suspend;
+ u8 backlight_on;
+ u8 backlight_off;
+ bool is_dead;
+ bool is_powering_on;
+ bool has_legacy_keycode;
+};
+
+static struct cypress_touchkey_devdata *blndevdata;
+#ifdef CONFIG_BLD
+static struct cypress_touchkey_devdata *blddevdata;
+#endif
+
+static int i2c_touchkey_read_byte(struct cypress_touchkey_devdata *devdata,
+ u8 *val)
+{
+ int ret;
+ int retry = 5;
+
+ while (true) {
+ ret = i2c_smbus_read_byte(devdata->client);
+ if (ret >= 0) {
+ *val = ret;
+ return 0;
+ }
+
+ dev_err(&devdata->client->dev, "i2c read error\n");
+ if (!retry--)
+ break;
+ msleep(10);
+ }
+
+ return ret;
+}
+
+static int i2c_touchkey_write_byte(struct cypress_touchkey_devdata *devdata,
+ u8 val)
+{
+ int ret;
+ int retry = 2;
+
+ while (true) {
+ ret = i2c_smbus_write_byte(devdata->client, val);
+ if (!ret)
+ return 0;
+
+ dev_err(&devdata->client->dev, "i2c write error\n");
+ if (!retry--)
+ break;
+ msleep(10);
+ }
+
+ return ret;
+}
+
+static void all_keys_up(struct cypress_touchkey_devdata *devdata)
+{
+ int i;
+
+ for (i = 0; i < devdata->pdata->keycode_cnt; i++)
+ input_report_key(devdata->input_dev,
+ devdata->pdata->keycode[i], 0);
+
+ input_sync(devdata->input_dev);
+}
+
+static int recovery_routine(struct cypress_touchkey_devdata *devdata)
+{
+ int ret = -1;
+ int retry = 10;
+ u8 data;
+ int irq_eint;
+
+ if (unlikely(devdata->is_dead)) {
+ dev_err(&devdata->client->dev, "%s: Device is already dead, "
+ "skipping recovery\n", __func__);
+ return -ENODEV;
+ }
+
+ irq_eint = devdata->client->irq;
+
+ all_keys_up(devdata);
+
+ disable_irq_nosync(irq_eint);
+ while (retry--) {
+ devdata->pdata->touchkey_onoff(TOUCHKEY_OFF);
+ devdata->pdata->touchkey_onoff(TOUCHKEY_ON);
+ ret = i2c_touchkey_read_byte(devdata, &data);
+ if (!ret) {
+ enable_irq(irq_eint);
+ goto out;
+ }
+ dev_err(&devdata->client->dev, "%s: i2c transfer error retry = "
+ "%d\n", __func__, retry);
+ }
+ devdata->is_dead = true;
+ devdata->pdata->touchkey_onoff(TOUCHKEY_OFF);
+ dev_err(&devdata->client->dev, "%s: touchkey died\n", __func__);
+out:
+ return ret;
+}
+
+static irqreturn_t touchkey_interrupt_thread(int irq, void *touchkey_devdata)
+{
+ u8 data;
+ int i;
+ int ret;
+ int scancode;
+ struct cypress_touchkey_devdata *devdata = touchkey_devdata;
+
+ ret = i2c_touchkey_read_byte(devdata, &data);
+ if (ret || (data & ESD_STATE_MASK)) {
+ ret = recovery_routine(devdata);
+ if (ret) {
+ dev_err(&devdata->client->dev, "%s: touchkey recovery "
+ "failed!\n", __func__);
+ goto err;
+ }
+ }
+
+ if (devdata->has_legacy_keycode) {
+ scancode = (data & SCANCODE_MASK) - 1;
+ if (scancode < 0 || scancode >= devdata->pdata->keycode_cnt) {
+ dev_err(&devdata->client->dev, "%s: scancode is out of "
+ "range\n", __func__);
+ goto err;
+ }
+ input_report_key(devdata->input_dev,
+ devdata->pdata->keycode[scancode],
+ !(data & UPDOWN_EVENT_MASK));
+
+#if defined(CONFIG_TOUCH_WAKE) || defined(CONFIG_BLD)
+ if (!(data & UPDOWN_EVENT_MASK))
+ {
+#ifdef CONFIG_BLD
+ touchkey_pressed();
+#endif
+ }
+#endif
+ } else {
+ for (i = 0; i < devdata->pdata->keycode_cnt; i++)
+ input_report_key(devdata->input_dev,
+ devdata->pdata->keycode[i],
+ !!(data & (1U << i)));
+
+#if defined(CONFIG_TOUCH_WAKE) || defined(CONFIG_BLD)
+ for (i = 0; i < devdata->pdata->keycode_cnt; i++)
+ {
+ if(!!(data & (1U << i)))
+ {
+#ifdef CONFIG_BLD
+ touchkey_pressed();
+#endif
+ break;
+ }
+ }
+#endif
+ }
+
+ input_sync(devdata->input_dev);
+err:
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t touchkey_interrupt_handler(int irq, void *touchkey_devdata)
+{
+ struct cypress_touchkey_devdata *devdata = touchkey_devdata;
+
+ if (devdata->is_powering_on) {
+ dev_dbg(&devdata->client->dev, "%s: ignoring spurious boot "
+ "interrupt\n", __func__);
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_WAKE_THREAD;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void cypress_touchkey_early_suspend(struct early_suspend *h)
+{
+ struct cypress_touchkey_devdata *devdata =
+ container_of(h, struct cypress_touchkey_devdata, early_suspend);
+
+ devdata->is_powering_on = true;
+
+ if (unlikely(devdata->is_dead))
+ return;
+
+ disable_irq(devdata->client->irq);
+
+#ifdef CONFIG_GENERIC_BLN
+ /*
+ * Disallow powering off the touchkey controller
+ * while a led notification is ongoing
+ */
+ if(!bln_is_ongoing()) {
+ devdata->pdata->touchkey_onoff(TOUCHKEY_OFF);
+ devdata->pdata->touchkey_sleep_onoff(TOUCHKEY_OFF);
+ }
+#endif
+ devdata->pdata->touchkey_onoff(TOUCHKEY_OFF);
+
+ all_keys_up(devdata);
+}
+
+static void cypress_touchkey_early_resume(struct early_suspend *h)
+{
+ struct cypress_touchkey_devdata *devdata =
+ container_of(h, struct cypress_touchkey_devdata, early_suspend);
+
+ devdata->pdata->touchkey_onoff(TOUCHKEY_ON);
+ if (i2c_touchkey_write_byte(devdata, devdata->backlight_on)) {
+ devdata->is_dead = true;
+ devdata->pdata->touchkey_onoff(TOUCHKEY_OFF);
+ dev_err(&devdata->client->dev, "%s: touch keypad not responding"
+ " to commands, disabling\n", __func__);
+ return;
+ }
+ devdata->is_dead = false;
+ enable_irq(devdata->client->irq);
+ devdata->is_powering_on = false;
+}
+#endif
+
+static void set_device_params(struct cypress_touchkey_devdata *devdata,
+ u8 *data)
+{
+ if (data[1] < 0xc4 && (data[1] > 0x8 ||
+ (data[1] == 0x8 && data[2] >= 0x9))) {
+ devdata->backlight_on = BACKLIGHT_ON;
+ devdata->backlight_off = BACKLIGHT_OFF;
+ } else {
+ devdata->backlight_on = OLD_BACKLIGHT_ON;
+ devdata->backlight_off = OLD_BACKLIGHT_OFF;
+ }
+
+ devdata->has_legacy_keycode = data[1] >= 0xc4 || data[1] < 0x9 ||
+ (data[1] == 0x9 && data[2] < 0x9);
+}
+
+static int update_firmware(struct cypress_touchkey_devdata *devdata)
+{
+ int ret;
+ const struct firmware *fw = NULL;
+ struct device *dev = &devdata->input_dev->dev;
+ int retries = 10;
+
+ dev_info(dev, "%s: Updating " DEVICE_NAME " firmware\n", __func__);
+
+ if (!devdata->pdata->fw_name) {
+ dev_err(dev, "%s: Device firmware name is not set\n", __func__);
+ return -EINVAL;
+ }
+
+ ret = request_firmware(&fw, devdata->pdata->fw_name, dev);
+ if (ret) {
+ dev_err(dev, "%s: Can't open firmware file from %s\n", __func__,
+ devdata->pdata->fw_name);
+ return ret;
+ }
+
+ if (fw->size != FW_SIZE) {
+ dev_err(dev, "%s: Firmware file size invalid\n", __func__);
+ return -EINVAL;
+ }
+
+ disable_irq(devdata->client->irq);
+ /* Lock the i2c bus since the firmware updater accesses it */
+ i2c_lock_adapter(devdata->client->adapter);
+ while (retries--) {
+ ret = touchkey_flash_firmware(devdata->pdata, fw->data);
+ if (!ret)
+ break;
+ }
+ if (ret)
+ dev_err(dev, "%s: Firmware update failed\n", __func__);
+ i2c_unlock_adapter(devdata->client->adapter);
+ enable_irq(devdata->client->irq);
+
+ release_firmware(fw);
+ return ret;
+}
+
+static void enable_touchkey_backlights(void){
+ i2c_touchkey_write_byte(blndevdata, blndevdata->backlight_on);
+}
+
+static void disable_touchkey_backlights(void){
+ i2c_touchkey_write_byte(blndevdata, blndevdata->backlight_off);
+}
+
+static int cypress_touchkey_open(struct input_dev *input_dev)
+{
+ struct device *dev = &input_dev->dev;
+ struct cypress_touchkey_devdata *devdata = dev_get_drvdata(dev);
+ u8 data[3];
+ int ret;
+
+ ret = update_firmware(devdata);
+ if (ret)
+ goto done;
+
+ ret = i2c_master_recv(devdata->client, data, sizeof(data));
+ if (ret < sizeof(data)) {
+ if (ret >= 0)
+ ret = -EIO;
+ dev_err(dev, "%s: error reading hardware version\n", __func__);
+ goto done;
+ }
+
+ dev_info(dev, "%s: hardware rev1 = %#02x, rev2 = %#02x\n", __func__,
+ data[1], data[2]);
+ set_device_params(devdata, data);
+
+ devdata->pdata->touchkey_onoff(TOUCHKEY_OFF);
+ devdata->pdata->touchkey_onoff(TOUCHKEY_ON);
+
+ ret = i2c_touchkey_write_byte(devdata, devdata->backlight_on);
+ if (ret) {
+ dev_err(dev, "%s: touch keypad backlight on failed\n",
+ __func__);
+ goto done;
+ }
+
+done:
+ input_dev->open = NULL;
+ return 0;
+}
+
+static void cypress_touchkey_enable_led_notification(void){
+ /* is_powering_on signals whether touchkey lights are used for touchmode */
+ if (blndevdata->is_powering_on){
+ /* reconfigure gpio for sleep mode */
+ blndevdata->pdata->touchkey_sleep_onoff(TOUCHKEY_ON);
+
+ /*
+ * power on the touchkey controller
+ * This is actually not needed, but it is intentionally
+ * left for the case that the early_resume() function
+ * did not power on the touchkey controller for some reasons
+ */
+ blndevdata->pdata->touchkey_onoff(TOUCHKEY_ON);
+
+ /* write to i2cbus, enable backlights */
+ enable_touchkey_backlights();
+ }
+ else
+ pr_info("%s: cannot set notification led, touchkeys are enabled\n",__FUNCTION__);
+}
+
+static void cypress_touchkey_disable_led_notification(void){
+ /*
+ * reconfigure gpio for sleep mode, this has to be done
+ * independently from the power status
+ */
+ blndevdata->pdata->touchkey_sleep_onoff(TOUCHKEY_OFF);
+
+ /* if touchkeys lights are not used for touchmode */
+ if (blndevdata->is_powering_on){
+ disable_touchkey_backlights();
+
+ #if 0
+ /*
+ * power off the touchkey controller
+ * This is actually not needed, the early_suspend function
+ * should take care of powering off the touchkey controller
+ */
+ blndevdata->pdata->touchkey_onoff(TOUCHKEY_OFF);
+ #endif
+ }
+}
+
+static struct bln_implementation cypress_touchkey_bln = {
+ .enable = cypress_touchkey_enable_led_notification,
+ .disable = cypress_touchkey_disable_led_notification,
+};
+
+#ifdef CONFIG_BLD
+static void cypress_touchkey_bld_disable(void)
+{
+ i2c_touchkey_write_byte(blddevdata, blddevdata->backlight_off);
+}
+
+static void cypress_touchkey_bld_enable(void)
+{
+ i2c_touchkey_write_byte(blddevdata, blddevdata->backlight_on);
+}
+
+static struct bld_implementation cypress_touchkey_bld =
+ {
+ .enable = cypress_touchkey_bld_enable,
+ .disable = cypress_touchkey_bld_disable,
+ };
+#endif
+
+static int cypress_touchkey_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct device *dev = &client->dev;
+ struct input_dev *input_dev;
+ struct cypress_touchkey_devdata *devdata;
+ u8 data[3];
+ int err;
+ int cnt;
+
+ if (!dev->platform_data) {
+ dev_err(dev, "%s: Platform data is NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ devdata = kzalloc(sizeof(*devdata), GFP_KERNEL);
+ if (devdata == NULL) {
+ dev_err(dev, "%s: failed to create our state\n", __func__);
+ return -ENODEV;
+ }
+
+ devdata->client = client;
+ i2c_set_clientdata(client, devdata);
+
+ devdata->pdata = client->dev.platform_data;
+ if (!devdata->pdata->keycode) {
+ dev_err(dev, "%s: Invalid platform data\n", __func__);
+ err = -EINVAL;
+ goto err_null_keycodes;
+ }
+
+ strlcpy(devdata->client->name, DEVICE_NAME, I2C_NAME_SIZE);
+
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ err = -ENOMEM;
+ goto err_input_alloc_dev;
+ }
+
+ devdata->input_dev = input_dev;
+ dev_set_drvdata(&input_dev->dev, devdata);
+ input_dev->name = DEVICE_NAME;
+ input_dev->id.bustype = BUS_HOST;
+
+ for (cnt = 0; cnt < devdata->pdata->keycode_cnt; cnt++)
+ input_set_capability(input_dev, EV_KEY,
+ devdata->pdata->keycode[cnt]);
+
+ devdata->is_powering_on = true;
+
+ devdata->pdata->touchkey_onoff(TOUCHKEY_ON);
+
+ err = i2c_master_recv(client, data, sizeof(data));
+ if (err < sizeof(data)) {
+ if (err >= 0)
+ err = -EIO;
+ dev_err(dev, "%s: error reading hardware version\n", __func__);
+ goto err_read;
+ }
+
+ dev_info(dev, "%s: hardware rev1 = %#02x, rev2 = %#02x\n", __func__,
+ data[1], data[2]);
+
+ if (data[1] != 0xa || data[2] < 0x9)
+ input_dev->open = cypress_touchkey_open;
+
+ err = input_register_device(input_dev);
+ if (err)
+ goto err_input_reg_dev;
+
+ set_device_params(devdata, data);
+
+ err = i2c_touchkey_write_byte(devdata, devdata->backlight_on);
+ if (err) {
+ dev_err(dev, "%s: touch keypad backlight on failed\n",
+ __func__);
+ /* The device may not be responding because of bad firmware
+ * Allow the firmware to be reflashed if it needs to be
+ */
+ if (!input_dev->open)
+ goto err_backlight_on;
+ }
+
+ err = request_threaded_irq(client->irq, touchkey_interrupt_handler,
+ touchkey_interrupt_thread, IRQF_TRIGGER_FALLING,
+ DEVICE_NAME, devdata);
+ if (err) {
+ dev_err(dev, "%s: Can't allocate irq.\n", __func__);
+ goto err_req_irq;
+ }
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ devdata->early_suspend.suspend = cypress_touchkey_early_suspend;
+ devdata->early_suspend.resume = cypress_touchkey_early_resume;
+#endif
+ register_early_suspend(&devdata->early_suspend);
+
+ devdata->is_powering_on = false;
+
+#ifdef CONFIG_GENERIC_BLN
+ blndevdata = devdata;
+ register_bln_implementation(&cypress_touchkey_bln);
+#endif
+
+#ifdef CONFIG_BLD
+ blddevdata = devdata;
+ register_bld_implementation(&cypress_touchkey_bld);
+#endif
+
+ return 0;
+
+
+err_req_irq:
+err_backlight_on:
+ input_unregister_device(input_dev);
+ goto touchkey_off;
+err_input_reg_dev:
+err_read:
+ input_free_device(input_dev);
+touchkey_off:
+ devdata->pdata->touchkey_onoff(TOUCHKEY_OFF);
+err_input_alloc_dev:
+err_null_keycodes:
+ kfree(devdata);
+ return err;
+}
+
+static int __devexit i2c_touchkey_remove(struct i2c_client *client)
+{
+ struct cypress_touchkey_devdata *devdata = i2c_get_clientdata(client);
+
+ unregister_early_suspend(&devdata->early_suspend);
+ /* If the device is dead IRQs are disabled, we need to rebalance them */
+ if (unlikely(devdata->is_dead))
+ enable_irq(client->irq);
+ else
+ devdata->pdata->touchkey_onoff(TOUCHKEY_OFF);
+ free_irq(client->irq, devdata);
+ all_keys_up(devdata);
+ input_unregister_device(devdata->input_dev);
+ kfree(devdata);
+ return 0;
+}
+
+static const struct i2c_device_id cypress_touchkey_id[] = {
+ { CYPRESS_TOUCHKEY_DEV_NAME, 0 },
+};
+
+MODULE_DEVICE_TABLE(i2c, cypress_touchkey_id);
+
+struct i2c_driver touchkey_i2c_driver = {
+ .driver = {
+ .name = "cypress_touchkey_driver",
+ },
+ .id_table = cypress_touchkey_id,
+ .probe = cypress_touchkey_probe,
+ .remove = __devexit_p(i2c_touchkey_remove),
+};
+
+static int __init touchkey_init(void)
+{
+ int ret = 0;
+
+ ret = i2c_add_driver(&touchkey_i2c_driver);
+ if (ret)
+ pr_err("%s: cypress touch keypad registration failed. (%d)\n",
+ __func__, ret);
+
+ return ret;
+}
+
+static void __exit touchkey_exit(void)
+{
+ i2c_del_driver(&touchkey_i2c_driver);
+}
+
+late_initcall(touchkey_init);
+module_exit(touchkey_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("@@@");
+MODULE_DESCRIPTION("cypress touch keypad");
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 6f4ad1a..ad92e61 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -12,6 +12,12 @@ menuconfig INPUT_MISC
if INPUT_MISC
+config GYRO_K3G
+ tristate "K3G driver for s5pc11x"
+ default n
+ help
+ This option enables gyro sensors using K3G driver
+
config INPUT_88PM860X_ONKEY
tristate "88PM860x ONKEY support"
depends on MFD_88PM860X
@@ -494,4 +500,11 @@ config INPUT_XEN_KBDDEV_FRONTEND
To compile this driver as a module, choose M here: the
module will be called xen-kbdfront.
+config OPTICAL_GP2A
+ depends on I2C && GENERIC_GPIO
+ tristate "GP2A ambient light and proximity input device"
+ default n
+ help
+ This option enables proximity & light sensors using gp2a driver.
+
endif
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index eb73834..175d548 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -4,6 +4,7 @@
# Each configuration option enables a list of files.
+obj-$(CONFIG_GYRO_K3G) += k3g.o
obj-$(CONFIG_INPUT_88PM860X_ONKEY) += 88pm860x_onkey.o
obj-$(CONFIG_INPUT_AB8500_PONKEY) += ab8500-ponkey.o
obj-$(CONFIG_INPUT_AD714X) += ad714x.o
@@ -47,4 +48,4 @@ obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o
obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o
obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND) += xen-kbdfront.o
obj-$(CONFIG_INPUT_YEALINK) += yealink.o
-
+obj-$(CONFIG_OPTICAL_GP2A) += gp2a.o
diff --git a/drivers/input/misc/gp2a.c b/drivers/input/misc/gp2a.c
new file mode 100644
index 0000000..4dc2982
--- /dev/null
+++ b/drivers/input/misc/gp2a.c
@@ -0,0 +1,641 @@
+/* linux/driver/input/misc/gp2a.c
+ * Copyright (C) 2010 Samsung Electronics. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/i2c.h>
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/miscdevice.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <linux/gpio.h>
+#include <linux/wakelock.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/workqueue.h>
+#include <linux/uaccess.h>
+#include <linux/gp2a.h>
+
+
+/* Note about power vs enable/disable:
+ * The chip has two functions, proximity and ambient light sensing.
+ * There is no separate power enablement to the two functions (unlike
+ * the Capella CM3602/3623).
+ * This module implements two drivers: /dev/proximity and /dev/light.
+ * When either driver is enabled (via sysfs attributes), we give power
+ * to the chip. When both are disabled, we remove power from the chip.
+ * In suspend, we remove power if light is disabled but not if proximity is
+ * enabled (proximity is allowed to wakeup from suspend).
+ *
+ * There are no ioctls for either driver interfaces. Output is via
+ * input device framework and control via sysfs attributes.
+ */
+
+
+#define gp2a_dbgmsg(str, args...) pr_debug("%s: " str, __func__, ##args)
+
+/* ADDSEL is LOW */
+#define REGS_PROX 0x0 /* Read Only */
+#define REGS_GAIN 0x1 /* Write Only */
+#define REGS_HYS 0x2 /* Write Only */
+#define REGS_CYCLE 0x3 /* Write Only */
+#define REGS_OPMOD 0x4 /* Write Only */
+
+/* sensor type */
+#define LIGHT 0
+#define PROXIMITY 1
+#define ALL 2
+
+#define DELAY_LOWBOUND (5 * NSEC_PER_MSEC)
+
+/* start time delay for light sensor in nano seconds */
+#define LIGHT_SENSOR_START_TIME_DELAY 50000000
+
+static u8 reg_defaults[5] = {
+ 0x00, /* PROX: read only register */
+ 0x08, /* GAIN: large LED drive level */
+ 0xC2, /* HYS: receiver sensitivity */
+ 0x04, /* CYCLE: */
+ 0x01, /* OPMOD: normal operating mode */
+};
+
+enum {
+ LIGHT_ENABLED = BIT(0),
+ PROXIMITY_ENABLED = BIT(1),
+};
+
+/* driver data */
+struct gp2a_data {
+ struct input_dev *proximity_input_dev;
+ struct input_dev *light_input_dev;
+ struct gp2a_platform_data *pdata;
+ struct i2c_client *i2c_client;
+ int irq;
+ struct work_struct work_light;
+ struct hrtimer timer;
+ ktime_t light_poll_delay;
+ bool on;
+ u8 power_state;
+ struct mutex power_lock;
+ struct wake_lock prx_wake_lock;
+ struct workqueue_struct *wq;
+};
+
+int gp2a_i2c_write(struct gp2a_data *gp2a, u8 reg, u8 *val)
+{
+ int err = 0;
+ struct i2c_msg msg[1];
+ unsigned char data[2];
+ int retry = 10;
+ struct i2c_client *client = gp2a->i2c_client;
+
+ if ((client == NULL) || (!client->adapter))
+ return -ENODEV;
+
+ while (retry--) {
+ data[0] = reg;
+ data[1] = *val;
+
+ msg->addr = client->addr;
+ msg->flags = 0; /* write */
+ msg->len = 2;
+ msg->buf = data;
+
+ err = i2c_transfer(client->adapter, msg, 1);
+
+ if (err >= 0)
+ return 0;
+ }
+ return err;
+}
+
+static void gp2a_light_enable(struct gp2a_data *gp2a)
+{
+ gp2a_dbgmsg("starting poll timer, delay %lldns\n",
+ ktime_to_ns(gp2a->light_poll_delay));
+ /*
+ * Set far out of range ABS_MISC value, -1024, to enable real value to
+ * go through next.
+ */
+ input_abs_set_val(gp2a->light_input_dev,
+ ABS_MISC, -gp2a->pdata->light_adc_max);
+ hrtimer_start(&gp2a->timer, ktime_set(0, LIGHT_SENSOR_START_TIME_DELAY),
+ HRTIMER_MODE_REL);
+}
+
+static void gp2a_light_disable(struct gp2a_data *gp2a)
+{
+ gp2a_dbgmsg("cancelling poll timer\n");
+ hrtimer_cancel(&gp2a->timer);
+ cancel_work_sync(&gp2a->work_light);
+}
+
+static ssize_t poll_delay_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct gp2a_data *gp2a = dev_get_drvdata(dev);
+ return sprintf(buf, "%lld\n", ktime_to_ns(gp2a->light_poll_delay));
+}
+
+
+static ssize_t poll_delay_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct gp2a_data *gp2a = dev_get_drvdata(dev);
+ int64_t new_delay;
+ int err;
+
+ err = strict_strtoll(buf, 10, &new_delay);
+ if (err < 0)
+ return err;
+
+ gp2a_dbgmsg("new delay = %lldns, old delay = %lldns\n",
+ new_delay, ktime_to_ns(gp2a->light_poll_delay));
+
+ if (new_delay < DELAY_LOWBOUND) {
+ gp2a_dbgmsg("new delay less than low bound, so set delay "
+ "to %lld\n", (int64_t)DELAY_LOWBOUND);
+ new_delay = DELAY_LOWBOUND;
+ }
+
+ mutex_lock(&gp2a->power_lock);
+ if (new_delay != ktime_to_ns(gp2a->light_poll_delay)) {
+ gp2a->light_poll_delay = ns_to_ktime(new_delay);
+ if (gp2a->power_state & LIGHT_ENABLED) {
+ gp2a_light_disable(gp2a);
+ gp2a_light_enable(gp2a);
+ }
+ }
+ mutex_unlock(&gp2a->power_lock);
+
+ return size;
+}
+
+static ssize_t light_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct gp2a_data *gp2a = dev_get_drvdata(dev);
+ return sprintf(buf, "%d\n",
+ (gp2a->power_state & LIGHT_ENABLED) ? 1 : 0);
+}
+
+static ssize_t proximity_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct gp2a_data *gp2a = dev_get_drvdata(dev);
+ return sprintf(buf, "%d\n",
+ (gp2a->power_state & PROXIMITY_ENABLED) ? 1 : 0);
+}
+
+static ssize_t light_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct gp2a_data *gp2a = dev_get_drvdata(dev);
+ bool new_value;
+
+ if (sysfs_streq(buf, "1"))
+ new_value = true;
+ else if (sysfs_streq(buf, "0"))
+ new_value = false;
+ else {
+ pr_err("%s: invalid value %d\n", __func__, *buf);
+ return -EINVAL;
+ }
+
+ mutex_lock(&gp2a->power_lock);
+ gp2a_dbgmsg("new_value = %d, old state = %d\n",
+ new_value, (gp2a->power_state & LIGHT_ENABLED) ? 1 : 0);
+ if (new_value && !(gp2a->power_state & LIGHT_ENABLED)) {
+ if (!gp2a->power_state)
+ gp2a->pdata->power(true);
+ gp2a->power_state |= LIGHT_ENABLED;
+ gp2a_light_enable(gp2a);
+ } else if (!new_value && (gp2a->power_state & LIGHT_ENABLED)) {
+ gp2a_light_disable(gp2a);
+ gp2a->power_state &= ~LIGHT_ENABLED;
+ if (!gp2a->power_state)
+ gp2a->pdata->power(false);
+ }
+ mutex_unlock(&gp2a->power_lock);
+ return size;
+}
+
+static ssize_t proximity_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct gp2a_data *gp2a = dev_get_drvdata(dev);
+ bool new_value;
+
+ if (sysfs_streq(buf, "1"))
+ new_value = true;
+ else if (sysfs_streq(buf, "0"))
+ new_value = false;
+ else {
+ pr_err("%s: invalid value %d\n", __func__, *buf);
+ return -EINVAL;
+ }
+
+ mutex_lock(&gp2a->power_lock);
+ gp2a_dbgmsg("new_value = %d, old state = %d\n",
+ new_value, (gp2a->power_state & PROXIMITY_ENABLED) ? 1 : 0);
+ if (new_value && !(gp2a->power_state & PROXIMITY_ENABLED)) {
+ if (!gp2a->power_state)
+ gp2a->pdata->power(true);
+ gp2a->power_state |= PROXIMITY_ENABLED;
+ enable_irq(gp2a->irq);
+ enable_irq_wake(gp2a->irq);
+ gp2a_i2c_write(gp2a, REGS_GAIN, &reg_defaults[1]);
+ gp2a_i2c_write(gp2a, REGS_HYS, &reg_defaults[2]);
+ gp2a_i2c_write(gp2a, REGS_CYCLE, &reg_defaults[3]);
+ gp2a_i2c_write(gp2a, REGS_OPMOD, &reg_defaults[4]);
+ } else if (!new_value && (gp2a->power_state & PROXIMITY_ENABLED)) {
+ disable_irq_wake(gp2a->irq);
+ disable_irq(gp2a->irq);
+ gp2a_i2c_write(gp2a, REGS_OPMOD, &reg_defaults[0]);
+ gp2a->power_state &= ~PROXIMITY_ENABLED;
+ if (!gp2a->power_state)
+ gp2a->pdata->power(false);
+ }
+ mutex_unlock(&gp2a->power_lock);
+ return size;
+}
+
+static DEVICE_ATTR(poll_delay, S_IRUGO | S_IWUSR | S_IWGRP,
+ poll_delay_show, poll_delay_store);
+
+static struct device_attribute dev_attr_light_enable =
+ __ATTR(enable, S_IRUGO | S_IWUSR | S_IWGRP,
+ light_enable_show, light_enable_store);
+
+static struct device_attribute dev_attr_proximity_enable =
+ __ATTR(enable, S_IRUGO | S_IWUSR | S_IWGRP,
+ proximity_enable_show, proximity_enable_store);
+
+static struct attribute *light_sysfs_attrs[] = {
+ &dev_attr_light_enable.attr,
+ &dev_attr_poll_delay.attr,
+ NULL
+};
+
+static struct attribute_group light_attribute_group = {
+ .attrs = light_sysfs_attrs,
+};
+
+static struct attribute *proximity_sysfs_attrs[] = {
+ &dev_attr_proximity_enable.attr,
+ NULL
+};
+
+static struct attribute_group proximity_attribute_group = {
+ .attrs = proximity_sysfs_attrs,
+};
+
+static void gp2a_work_func_light(struct work_struct *work)
+{
+ struct gp2a_data *gp2a = container_of(work, struct gp2a_data,
+ work_light);
+ int adc = gp2a->pdata->light_adc_value();
+ if (adc < 0) {
+ pr_err("adc returned error %d\n", adc);
+ return;
+ }
+ gp2a_dbgmsg("adc returned light value %d\n", adc);
+ input_report_abs(gp2a->light_input_dev, ABS_MISC, adc);
+ input_sync(gp2a->light_input_dev);
+}
+
+/* This function is for light sensor. It operates every a few seconds.
+ * It asks for work to be done on a thread because i2c needs a thread
+ * context (slow and blocking) and then reschedules the timer to run again.
+ */
+static enum hrtimer_restart gp2a_timer_func(struct hrtimer *timer)
+{
+ struct gp2a_data *gp2a = container_of(timer, struct gp2a_data, timer);
+ queue_work(gp2a->wq, &gp2a->work_light);
+ hrtimer_forward_now(&gp2a->timer, gp2a->light_poll_delay);
+ return HRTIMER_RESTART;
+}
+
+/* interrupt happened due to transition/change of near/far proximity state */
+irqreturn_t gp2a_irq_handler(int irq, void *data)
+{
+ struct gp2a_data *ip = data;
+ int val = gpio_get_value(ip->pdata->p_out);
+ if (val < 0) {
+ pr_err("%s: gpio_get_value error %d\n", __func__, val);
+ return IRQ_HANDLED;
+ }
+
+ gp2a_dbgmsg("gp2a: proximity val=%d\n", val);
+
+ /* 0 is close, 1 is far */
+ input_report_abs(ip->proximity_input_dev, ABS_DISTANCE, val);
+ input_sync(ip->proximity_input_dev);
+ wake_lock_timeout(&ip->prx_wake_lock, 3*HZ);
+ return IRQ_HANDLED;
+}
+
+static int gp2a_setup_irq(struct gp2a_data *gp2a)
+{
+ int rc = -EIO;
+ struct gp2a_platform_data *pdata = gp2a->pdata;
+ int irq;
+
+ gp2a_dbgmsg("start\n");
+
+ rc = gpio_request(pdata->p_out, "gpio_proximity_out");
+ if (rc < 0) {
+ pr_err("%s: gpio %d request failed (%d)\n",
+ __func__, pdata->p_out, rc);
+ return rc;
+ }
+
+ rc = gpio_direction_input(pdata->p_out);
+ if (rc < 0) {
+ pr_err("%s: failed to set gpio %d as input (%d)\n",
+ __func__, pdata->p_out, rc);
+ goto err_gpio_direction_input;
+ }
+
+ irq = gpio_to_irq(pdata->p_out);
+ rc = request_irq(irq,
+ gp2a_irq_handler,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ "proximity_int",
+ gp2a);
+ if (rc < 0) {
+ pr_err("%s: request_irq(%d) failed for gpio %d (%d)\n",
+ __func__, irq,
+ pdata->p_out, rc);
+ goto err_request_irq;
+ }
+
+ /* start with interrupts disabled */
+ disable_irq(irq);
+ gp2a->irq = irq;
+
+ /* sync input device with proximity gpio pin default value */
+ gp2a_irq_handler(gp2a->irq, gp2a);
+
+ gp2a_dbgmsg("success\n");
+
+ goto done;
+
+err_request_irq:
+err_gpio_direction_input:
+ gpio_free(pdata->p_out);
+done:
+ return rc;
+}
+
+static int gp2a_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int ret = -ENODEV;
+ struct input_dev *input_dev;
+ struct gp2a_data *gp2a;
+ struct gp2a_platform_data *pdata = client->dev.platform_data;
+
+ if (!pdata) {
+ pr_err("%s: missing pdata!\n", __func__);
+ return ret;
+ }
+ if (!pdata->power || !pdata->light_adc_value) {
+ pr_err("%s: incomplete pdata!\n", __func__);
+ return ret;
+ }
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ pr_err("%s: i2c functionality check failed!\n", __func__);
+ return ret;
+ }
+
+ gp2a = kzalloc(sizeof(struct gp2a_data), GFP_KERNEL);
+ if (!gp2a) {
+ pr_err("%s: failed to alloc memory for module data\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ gp2a->pdata = pdata;
+ gp2a->i2c_client = client;
+ i2c_set_clientdata(client, gp2a);
+
+
+ wake_lock_init(&gp2a->prx_wake_lock, WAKE_LOCK_SUSPEND,
+ "prx_wake_lock");
+ mutex_init(&gp2a->power_lock);
+
+ /* allocate proximity input_device */
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ pr_err("%s: could not allocate input device\n", __func__);
+ goto err_input_allocate_device_proximity;
+ }
+ gp2a->proximity_input_dev = input_dev;
+ input_set_drvdata(input_dev, gp2a);
+ input_dev->name = "proximity";
+ input_set_capability(input_dev, EV_ABS, ABS_DISTANCE);
+ input_set_abs_params(input_dev, ABS_DISTANCE, 0, 1, 0, 0);
+
+ ret = gp2a_setup_irq(gp2a);
+ if (ret) {
+ pr_err("%s: could not setup irq\n", __func__);
+ input_free_device(input_dev);
+ goto err_setup_irq;
+ }
+
+ gp2a_dbgmsg("registering proximity input device\n");
+ ret = input_register_device(input_dev);
+ if (ret < 0) {
+ pr_err("%s: could not register input device\n", __func__);
+ input_free_device(input_dev);
+ goto err_input_register_device_proximity;
+ }
+ ret = sysfs_create_group(&input_dev->dev.kobj,
+ &proximity_attribute_group);
+ if (ret) {
+ pr_err("%s: could not create sysfs group\n", __func__);
+ goto err_sysfs_create_group_proximity;
+ }
+
+ /* hrtimer settings. we poll for light values using a timer. */
+ hrtimer_init(&gp2a->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ gp2a->light_poll_delay = ns_to_ktime(200 * NSEC_PER_MSEC);
+ gp2a->timer.function = gp2a_timer_func;
+
+ /* the timer just fires off a work queue request. we need a thread
+ * to read the i2c (can be slow and blocking)
+ */
+ gp2a->wq = create_singlethread_workqueue("gp2a_wq");
+ if (!gp2a->wq) {
+ ret = -ENOMEM;
+ pr_err("%s: could not create workqueue\n", __func__);
+ goto err_create_workqueue;
+ }
+ /* this is the thread function we run on the work queue */
+ INIT_WORK(&gp2a->work_light, gp2a_work_func_light);
+
+ /* allocate lightsensor-level input_device */
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ pr_err("%s: could not allocate input device\n", __func__);
+ ret = -ENOMEM;
+ goto err_input_allocate_device_light;
+ }
+ input_set_drvdata(input_dev, gp2a);
+ input_dev->name = "lightsensor-level";
+ input_set_capability(input_dev, EV_ABS, ABS_MISC);
+ input_set_abs_params(input_dev, ABS_MISC, 0, pdata->light_adc_max,
+ pdata->light_adc_fuzz, 0);
+
+ gp2a_dbgmsg("registering lightsensor-level input device\n");
+ ret = input_register_device(input_dev);
+ if (ret < 0) {
+ pr_err("%s: could not register input device\n", __func__);
+ input_free_device(input_dev);
+ goto err_input_register_device_light;
+ }
+ gp2a->light_input_dev = input_dev;
+ ret = sysfs_create_group(&input_dev->dev.kobj,
+ &light_attribute_group);
+ if (ret) {
+ pr_err("%s: could not create sysfs group\n", __func__);
+ goto err_sysfs_create_group_light;
+ }
+ goto done;
+
+ /* error, unwind it all */
+err_sysfs_create_group_light:
+ input_unregister_device(gp2a->light_input_dev);
+err_input_register_device_light:
+err_input_allocate_device_light:
+ destroy_workqueue(gp2a->wq);
+err_create_workqueue:
+ sysfs_remove_group(&gp2a->proximity_input_dev->dev.kobj,
+ &proximity_attribute_group);
+err_sysfs_create_group_proximity:
+ input_unregister_device(gp2a->proximity_input_dev);
+err_input_register_device_proximity:
+ free_irq(gp2a->irq, gp2a);
+ gpio_free(gp2a->pdata->p_out);
+err_setup_irq:
+err_input_allocate_device_proximity:
+ mutex_destroy(&gp2a->power_lock);
+ wake_lock_destroy(&gp2a->prx_wake_lock);
+ kfree(gp2a);
+done:
+ return ret;
+}
+
+static int gp2a_suspend(struct device *dev)
+{
+ /* We disable power only if proximity is disabled. If proximity
+ * is enabled, we leave power on because proximity is allowed
+ * to wake up device. We remove power without changing
+ * gp2a->power_state because we use that state in resume
+ */
+ struct i2c_client *client = to_i2c_client(dev);
+ struct gp2a_data *gp2a = i2c_get_clientdata(client);
+ if (gp2a->power_state & LIGHT_ENABLED)
+ gp2a_light_disable(gp2a);
+ if (gp2a->power_state == LIGHT_ENABLED)
+ gp2a->pdata->power(false);
+ return 0;
+}
+
+static int gp2a_resume(struct device *dev)
+{
+ /* Turn power back on if we were before suspend. */
+ struct i2c_client *client = to_i2c_client(dev);
+ struct gp2a_data *gp2a = i2c_get_clientdata(client);
+ if (gp2a->power_state == LIGHT_ENABLED)
+ gp2a->pdata->power(true);
+ if (gp2a->power_state & LIGHT_ENABLED)
+ gp2a_light_enable(gp2a);
+ return 0;
+}
+
+static int gp2a_i2c_remove(struct i2c_client *client)
+{
+ struct gp2a_data *gp2a = i2c_get_clientdata(client);
+ sysfs_remove_group(&gp2a->light_input_dev->dev.kobj,
+ &light_attribute_group);
+ sysfs_remove_group(&gp2a->proximity_input_dev->dev.kobj,
+ &proximity_attribute_group);
+ free_irq(gp2a->irq, gp2a);
+ destroy_workqueue(gp2a->wq);
+ input_unregister_device(gp2a->light_input_dev);
+ input_unregister_device(gp2a->proximity_input_dev);
+ gpio_free(gp2a->pdata->p_out);
+ if (gp2a->power_state) {
+ gp2a->power_state = 0;
+ if (gp2a->power_state & LIGHT_ENABLED)
+ gp2a_light_disable(gp2a);
+ gp2a->pdata->power(false);
+ }
+ mutex_destroy(&gp2a->power_lock);
+ wake_lock_destroy(&gp2a->prx_wake_lock);
+ kfree(gp2a);
+ return 0;
+}
+
+static const struct i2c_device_id gp2a_device_id[] = {
+ {"gp2a", 0},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, gp2a_device_id);
+
+static const struct dev_pm_ops gp2a_pm_ops = {
+ .suspend = gp2a_suspend,
+ .resume = gp2a_resume
+};
+
+static struct i2c_driver gp2a_i2c_driver = {
+ .driver = {
+ .name = "gp2a",
+ .owner = THIS_MODULE,
+ .pm = &gp2a_pm_ops
+ },
+ .probe = gp2a_i2c_probe,
+ .remove = gp2a_i2c_remove,
+ .id_table = gp2a_device_id,
+};
+
+
+static int __init gp2a_init(void)
+{
+ return i2c_add_driver(&gp2a_i2c_driver);
+}
+
+static void __exit gp2a_exit(void)
+{
+ i2c_del_driver(&gp2a_i2c_driver);
+}
+
+module_init(gp2a_init);
+module_exit(gp2a_exit);
+
+MODULE_AUTHOR("mjchen@sta.samsung.com");
+MODULE_DESCRIPTION("Optical Sensor driver for gp2ap002a00f");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/misc/k3g.c b/drivers/input/misc/k3g.c
new file mode 100644
index 0000000..5540628
--- /dev/null
+++ b/drivers/input/misc/k3g.c
@@ -0,0 +1,707 @@
+/*
+ * Copyright (C) 2010, Samsung Electronics Co. Ltd. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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/kernel.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/uaccess.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <asm/div64.h>
+#include <linux/input/k3g.h>
+#include <linux/delay.h>
+
+/* k3g chip id */
+#define DEVICE_ID 0xD3
+/* k3g gyroscope registers */
+#define WHO_AM_I 0x0F
+#define CTRL_REG1 0x20 /* power control reg */
+#define CTRL_REG2 0x21 /* power control reg */
+#define CTRL_REG3 0x22 /* power control reg */
+#define CTRL_REG4 0x23 /* interrupt control reg */
+#define CTRL_REG5 0x24 /* interrupt control reg */
+#define OUT_TEMP 0x26 /* Temperature data */
+#define STATUS_REG 0x27
+#define AXISDATA_REG 0x28
+#define OUT_Y_L 0x2A
+#define FIFO_CTRL_REG 0x2E
+#define FIFO_SRC_REG 0x2F
+#define PM_OFF 0x00
+#define PM_NORMAL 0x08
+#define ENABLE_ALL_AXES 0x07
+#define BYPASS_MODE 0x00
+#define FIFO_MODE 0x20
+
+#define FIFO_EMPTY 0x20
+#define FSS_MASK 0x1F
+#define ODR_MASK 0xF0
+#define ODR105_BW12_5 0x00 /* ODR = 105Hz; BW = 12.5Hz */
+#define ODR105_BW25 0x10 /* ODR = 105Hz; BW = 25Hz */
+#define ODR210_BW12_5 0x40 /* ODR = 210Hz; BW = 12.5Hz */
+#define ODR210_BW25 0x50 /* ODR = 210Hz; BW = 25Hz */
+#define ODR210_BW50 0x60 /* ODR = 210Hz; BW = 50Hz */
+#define ODR210_BW70 0x70 /* ODR = 210Hz; BW = 70Hz */
+#define ODR420_BW20 0x80 /* ODR = 420Hz; BW = 20Hz */
+#define ODR420_BW25 0x90 /* ODR = 420Hz; BW = 25Hz */
+#define ODR420_BW50 0xA0 /* ODR = 420Hz; BW = 50Hz */
+#define ODR420_BW110 0xB0 /* ODR = 420Hz; BW = 110Hz */
+#define ODR840_BW30 0xC0 /* ODR = 840Hz; BW = 30Hz */
+#define ODR840_BW35 0xD0 /* ODR = 840Hz; BW = 35Hz */
+#define ODR840_BW50 0xE0 /* ODR = 840Hz; BW = 50Hz */
+#define ODR840_BW110 0xF0 /* ODR = 840Hz; BW = 110Hz */
+
+#define MIN_ST 175
+#define MAX_ST 875
+#define AC (1 << 7) /* register auto-increment bit */
+#define MAX_ENTRY 1
+#define MAX_DELAY (MAX_ENTRY * 9523809LL)
+
+/* default register setting for device init */
+static const char default_ctrl_regs[] = {
+ 0x3F, /* 105HZ, PM-normal, xyz enable */
+ 0x00, /* normal mode */
+ 0x04, /* fifo wtm interrupt on */
+ 0xA0, /* block data update, 2000d/s */
+ 0x40, /* fifo enable */
+};
+
+static const struct odr_delay {
+ u8 odr; /* odr reg setting */
+ u32 delay_ns; /* odr in ns */
+} odr_delay_table[] = {
+ { ODR840_BW110, 1190476LL }, /* 840Hz */
+ { ODR420_BW110, 2380952LL }, /* 420Hz */
+ { ODR210_BW70, 4761904LL }, /* 210Hz */
+ { ODR105_BW25, 9523809LL }, /* 105Hz */
+};
+
+/*
+ * K3G gyroscope data
+ * brief structure containing gyroscope values for yaw, pitch and roll in
+ * signed short
+ */
+struct k3g_t {
+ s16 x;
+ s16 y;
+ s16 z;
+};
+
+struct k3g_data {
+ struct i2c_client *client;
+ struct input_dev *input_dev;
+ struct mutex lock;
+ struct workqueue_struct *k3g_wq;
+ struct work_struct work;
+ struct hrtimer timer;
+ bool enable;
+ bool drop_next_event;
+ bool interruptible; /* interrupt or polling? */
+ int entries; /* number of fifo entries */
+ u8 ctrl_regs[5]; /* saving register settings */
+ u32 time_to_read; /* time needed to read one entry */
+ ktime_t polling_delay; /* polling time for timer */
+};
+
+static int k3g_read_fifo_status(struct k3g_data *k3g_data)
+{
+ int fifo_status;
+
+ fifo_status = i2c_smbus_read_byte_data(k3g_data->client, FIFO_SRC_REG);
+ if (fifo_status < 0) {
+ pr_err("%s: failed to read fifo source register\n",
+ __func__);
+ return fifo_status;
+ }
+ return (fifo_status & FSS_MASK) + !(fifo_status & FIFO_EMPTY);
+}
+
+static int k3g_restart_fifo(struct k3g_data *k3g_data)
+{
+ int res = 0;
+
+ res = i2c_smbus_write_byte_data(k3g_data->client,
+ FIFO_CTRL_REG, BYPASS_MODE);
+ if (res < 0) {
+ pr_err("%s : failed to set bypass_mode\n", __func__);
+ return res;
+ }
+
+ res = i2c_smbus_write_byte_data(k3g_data->client,
+ FIFO_CTRL_REG, FIFO_MODE | (k3g_data->entries - 1));
+
+ if (res < 0)
+ pr_err("%s : failed to set fifo_mode\n", __func__);
+
+ return res;
+}
+
+static void set_polling_delay(struct k3g_data *k3g_data, int res)
+{
+ s64 delay_ns;
+
+ delay_ns = k3g_data->entries + 1 - res;
+ if (delay_ns < 0)
+ delay_ns = 0;
+
+ delay_ns = delay_ns * k3g_data->time_to_read;
+ k3g_data->polling_delay = ns_to_ktime(delay_ns);
+}
+
+/* gyroscope data readout */
+static int k3g_read_gyro_values(struct i2c_client *client,
+ struct k3g_t *data, int total_read)
+{
+ int err;
+ struct i2c_msg msg[2];
+ u8 reg_buf;
+ u8 gyro_data[sizeof(*data) * (total_read ? (total_read - 1) : 1)];
+
+ msg[0].addr = client->addr;
+ msg[0].buf = &reg_buf;
+ msg[0].flags = 0;
+ msg[0].len = 1;
+
+ msg[1].addr = client->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].buf = gyro_data;
+
+ if (total_read > 1) {
+ reg_buf = AXISDATA_REG | AC;
+ msg[1].len = sizeof(gyro_data);
+
+ err = i2c_transfer(client->adapter, msg, 2);
+ if (err != 2)
+ return (err < 0) ? err : -EIO;
+ }
+
+ reg_buf = AXISDATA_REG;
+ msg[1].len = 1;
+ err = i2c_transfer(client->adapter, msg, 2);
+ if (err != 2)
+ return (err < 0) ? err : -EIO;
+
+ reg_buf = OUT_Y_L | AC;
+ msg[1].len = sizeof(*data);
+ err = i2c_transfer(client->adapter, msg, 2);
+ if (err != 2)
+ return (err < 0) ? err : -EIO;
+
+ data->y = (gyro_data[1] << 8) | gyro_data[0];
+ data->z = (gyro_data[3] << 8) | gyro_data[2];
+ data->x = (gyro_data[5] << 8) | gyro_data[4];
+
+ return 0;
+}
+
+static int k3g_report_gyro_values(struct k3g_data *k3g_data)
+{
+ int res;
+ struct k3g_t data;
+
+ res = k3g_read_gyro_values(k3g_data->client, &data,
+ k3g_data->entries + k3g_data->drop_next_event);
+ if (res < 0)
+ return res;
+
+ res = k3g_read_fifo_status(k3g_data);
+
+ k3g_data->drop_next_event = !res;
+
+ if (res >= 31 - k3g_data->entries) {
+ /* reset fifo to start again - data isn't trustworthy,
+ * our locked read might not have worked and we
+ * could have done i2c read in mid register update
+ */
+ return k3g_restart_fifo(k3g_data);
+ }
+
+ input_report_rel(k3g_data->input_dev, REL_RX, data.x);
+ input_report_rel(k3g_data->input_dev, REL_RY, data.y);
+ input_report_rel(k3g_data->input_dev, REL_RZ, data.z);
+ input_sync(k3g_data->input_dev);
+
+ return res;
+}
+
+static enum hrtimer_restart k3g_timer_func(struct hrtimer *timer)
+{
+ struct k3g_data *k3g_data = container_of(timer, struct k3g_data, timer);
+ queue_work(k3g_data->k3g_wq, &k3g_data->work);
+ return HRTIMER_NORESTART;
+}
+
+static void k3g_work_func(struct work_struct *work)
+{
+ int res;
+ struct k3g_data *k3g_data = container_of(work, struct k3g_data, work);
+
+ do {
+ res = k3g_read_fifo_status(k3g_data);
+ if (res < 0)
+ return;
+
+ if (res < k3g_data->entries) {
+ pr_warn("%s: fifo entries are less than we want\n",
+ __func__);
+ goto timer_set;
+ }
+
+ res = k3g_report_gyro_values(k3g_data);
+ if (res < 0)
+ return;
+timer_set:
+ set_polling_delay(k3g_data, res);
+
+ } while (!ktime_to_ns(k3g_data->polling_delay));
+
+ hrtimer_start(&k3g_data->timer,
+ k3g_data->polling_delay, HRTIMER_MODE_REL);
+}
+
+static irqreturn_t k3g_interrupt_thread(int irq, void *k3g_data_p)
+{
+ int res;
+ struct k3g_data *k3g_data = k3g_data_p;
+ res = k3g_report_gyro_values(k3g_data);
+ if (res < 0)
+ pr_err("%s: failed to report gyro values\n", __func__);
+
+ return IRQ_HANDLED;
+}
+
+static ssize_t k3g_show_enable(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct k3g_data *k3g_data = dev_get_drvdata(dev);
+ return sprintf(buf, "%d\n", k3g_data->enable);
+}
+
+static ssize_t k3g_set_enable(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ int err = 0;
+ struct k3g_data *k3g_data = dev_get_drvdata(dev);
+ bool new_enable;
+
+ if (sysfs_streq(buf, "1"))
+ new_enable = true;
+ else if (sysfs_streq(buf, "0"))
+ new_enable = false;
+ else {
+ pr_debug("%s: invalid value %d\n", __func__, *buf);
+ return -EINVAL;
+ }
+
+ if (new_enable == k3g_data->enable)
+ return size;
+
+ mutex_lock(&k3g_data->lock);
+ if (new_enable) {
+ /* turning on */
+ err = i2c_smbus_write_i2c_block_data(k3g_data->client,
+ CTRL_REG1 | AC, sizeof(k3g_data->ctrl_regs),
+ k3g_data->ctrl_regs);
+ if (err < 0) {
+ err = -EIO;
+ goto unlock;
+ }
+
+ /* reset fifo entries */
+ err = k3g_restart_fifo(k3g_data);
+ if (err < 0) {
+ err = -EIO;
+ goto turn_off;
+ }
+
+ if (k3g_data->interruptible)
+ enable_irq(k3g_data->client->irq);
+ else {
+ set_polling_delay(k3g_data, 0);
+ hrtimer_start(&k3g_data->timer,
+ k3g_data->polling_delay, HRTIMER_MODE_REL);
+ }
+ } else {
+ if (k3g_data->interruptible)
+ disable_irq(k3g_data->client->irq);
+ else {
+ hrtimer_cancel(&k3g_data->timer);
+ cancel_work_sync(&k3g_data->work);
+ }
+ /* turning off */
+ err = i2c_smbus_write_byte_data(k3g_data->client,
+ CTRL_REG1, 0x00);
+ if (err < 0)
+ goto unlock;
+ }
+ k3g_data->enable = new_enable;
+
+turn_off:
+ if (err < 0)
+ i2c_smbus_write_byte_data(k3g_data->client,
+ CTRL_REG1, 0x00);
+unlock:
+ mutex_unlock(&k3g_data->lock);
+
+ return err ? err : size;
+}
+
+static ssize_t k3g_show_delay(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct k3g_data *k3g_data = dev_get_drvdata(dev);
+ u64 delay;
+
+ delay = k3g_data->time_to_read * k3g_data->entries;
+ delay = ktime_to_ns(ns_to_ktime(delay));
+
+ return sprintf(buf, "%lld\n", delay);
+}
+
+static ssize_t k3g_set_delay(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct k3g_data *k3g_data = dev_get_drvdata(dev);
+ int odr_value = ODR105_BW25;
+ int res = 0;
+ int i;
+ u64 delay_ns;
+ u8 ctrl;
+
+ res = strict_strtoll(buf, 10, &delay_ns);
+ if (res < 0)
+ return res;
+
+ mutex_lock(&k3g_data->lock);
+ if (!k3g_data->interruptible)
+ hrtimer_cancel(&k3g_data->timer);
+ else
+ disable_irq(k3g_data->client->irq);
+
+ /* round to the nearest supported ODR that is equal or above than
+ * the requested value
+ */
+ for (i = 0; i < ARRAY_SIZE(odr_delay_table); i++) {
+ if (delay_ns < odr_delay_table[i].delay_ns)
+ break;
+ }
+ if (i > 0)
+ i--;
+
+ odr_value = odr_delay_table[i].odr;
+ delay_ns = odr_delay_table[i].delay_ns;
+ k3g_data->time_to_read = delay_ns;
+ k3g_data->entries = 1;
+
+ if (delay_ns >= odr_delay_table[3].delay_ns) {
+ if (delay_ns >= MAX_DELAY) {
+ k3g_data->entries = MAX_ENTRY;
+ delay_ns = MAX_DELAY;
+ } else {
+ do_div(delay_ns, odr_delay_table[3].delay_ns);
+ k3g_data->entries = delay_ns;
+ }
+ k3g_data->time_to_read = odr_delay_table[3].delay_ns;
+ }
+
+ if (odr_value != (k3g_data->ctrl_regs[0] & ODR_MASK)) {
+ ctrl = (k3g_data->ctrl_regs[0] & ~ODR_MASK);
+ ctrl |= odr_value;
+ k3g_data->ctrl_regs[0] = ctrl;
+ res = i2c_smbus_write_byte_data(k3g_data->client,
+ CTRL_REG1, ctrl);
+ }
+
+ /* we see a noise in the first sample or two after we
+ * change rates. this delay helps eliminate that noise.
+ */
+ msleep((u32)delay_ns * 2 / NSEC_PER_MSEC);
+
+ /* (re)start fifo */
+ k3g_restart_fifo(k3g_data);
+
+ if (!k3g_data->interruptible) {
+ delay_ns = k3g_data->entries * k3g_data->time_to_read;
+ k3g_data->polling_delay = ns_to_ktime(delay_ns);
+ if (k3g_data->enable)
+ hrtimer_start(&k3g_data->timer,
+ k3g_data->polling_delay, HRTIMER_MODE_REL);
+ } else
+ enable_irq(k3g_data->client->irq);
+
+ mutex_unlock(&k3g_data->lock);
+
+ return size;
+}
+
+static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR | S_IWGRP,
+ k3g_show_enable, k3g_set_enable);
+static DEVICE_ATTR(poll_delay, S_IRUGO | S_IWUSR | S_IWGRP,
+ k3g_show_delay, k3g_set_delay);
+
+static int k3g_probe(struct i2c_client *client,
+ const struct i2c_device_id *devid)
+{
+ int ret;
+ int err = 0;
+ struct k3g_data *data;
+ struct input_dev *input_dev;
+
+ if (client->dev.platform_data == NULL) {
+ dev_err(&client->dev, "platform data is NULL. exiting.\n");
+ err = -ENODEV;
+ goto exit;
+ }
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (data == NULL) {
+ dev_err(&client->dev,
+ "failed to allocate memory for module data\n");
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ data->client = client;
+
+ /* read chip id */
+ ret = i2c_smbus_read_byte_data(client, WHO_AM_I);
+ if (ret != DEVICE_ID) {
+ if (ret < 0) {
+ pr_err("%s: i2c for reading chip id failed\n",
+ __func__);
+ err = ret;
+ } else {
+ pr_err("%s : Device identification failed\n",
+ __func__);
+ err = -ENODEV;
+ }
+ goto err_read_reg;
+ }
+
+ mutex_init(&data->lock);
+
+ /* allocate gyro input_device */
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ pr_err("%s: could not allocate input device\n", __func__);
+ err = -ENOMEM;
+ goto err_input_allocate_device;
+ }
+
+ data->input_dev = input_dev;
+ input_set_drvdata(input_dev, data);
+ input_dev->name = "gyro";
+ /* X */
+ input_set_capability(input_dev, EV_REL, REL_RX);
+ input_set_abs_params(input_dev, REL_RX, -2048, 2047, 0, 0);
+ /* Y */
+ input_set_capability(input_dev, EV_REL, REL_RY);
+ input_set_abs_params(input_dev, REL_RY, -2048, 2047, 0, 0);
+ /* Z */
+ input_set_capability(input_dev, EV_REL, REL_RZ);
+ input_set_abs_params(input_dev, REL_RZ, -2048, 2047, 0, 0);
+
+ err = input_register_device(input_dev);
+ if (err < 0) {
+ pr_err("%s: could not register input device\n", __func__);
+ input_free_device(data->input_dev);
+ goto err_input_register_device;
+ }
+
+ memcpy(&data->ctrl_regs, &default_ctrl_regs, sizeof(default_ctrl_regs));
+
+ if (data->client->irq >= 0) { /* interrupt */
+ data->interruptible = true;
+ err = request_threaded_irq(data->client->irq, NULL,
+ k3g_interrupt_thread, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+ "k3g", data);
+ if (err < 0) {
+ pr_err("%s: can't allocate irq.\n", __func__);
+ goto err_request_irq;
+ }
+ disable_irq(data->client->irq);
+
+ } else { /* polling */
+ u64 delay_ns;
+ data->ctrl_regs[2] = 0x00; /* disable interrupt */
+ /* hrtimer settings. we poll for gyro values using a timer. */
+ hrtimer_init(&data->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ data->polling_delay = ns_to_ktime(200 * NSEC_PER_MSEC);
+ data->time_to_read = 10000000LL;
+ delay_ns = ktime_to_ns(data->polling_delay);
+ do_div(delay_ns, data->time_to_read);
+ data->entries = delay_ns;
+ data->timer.function = k3g_timer_func;
+
+ /* the timer just fires off a work queue request.
+ We need a thread to read i2c (can be slow and blocking). */
+ data->k3g_wq = create_singlethread_workqueue("k3g_wq");
+ if (!data->k3g_wq) {
+ err = -ENOMEM;
+ pr_err("%s: could not create workqueue\n", __func__);
+ goto err_create_workqueue;
+ }
+ /* this is the thread function we run on the work queue */
+ INIT_WORK(&data->work, k3g_work_func);
+ }
+
+ if (device_create_file(&input_dev->dev,
+ &dev_attr_enable) < 0) {
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_enable.attr.name);
+ goto err_device_create_file;
+ }
+
+ if (device_create_file(&input_dev->dev,
+ &dev_attr_poll_delay) < 0) {
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_poll_delay.attr.name);
+ goto err_device_create_file2;
+ }
+
+ i2c_set_clientdata(client, data);
+ dev_set_drvdata(&input_dev->dev, data);
+
+ return 0;
+
+err_device_create_file2:
+ device_remove_file(&input_dev->dev, &dev_attr_enable);
+err_device_create_file:
+ if (data->interruptible) {
+ enable_irq(data->client->irq);
+ free_irq(data->client->irq, data);
+ } else
+ destroy_workqueue(data->k3g_wq);
+ input_unregister_device(data->input_dev);
+err_create_workqueue:
+err_request_irq:
+err_input_register_device:
+err_input_allocate_device:
+ mutex_destroy(&data->lock);
+err_read_reg:
+ kfree(data);
+exit:
+ return err;
+}
+
+static int k3g_remove(struct i2c_client *client)
+{
+ int err = 0;
+ struct k3g_data *k3g_data = i2c_get_clientdata(client);
+
+ device_remove_file(&k3g_data->input_dev->dev, &dev_attr_enable);
+ device_remove_file(&k3g_data->input_dev->dev, &dev_attr_poll_delay);
+
+ if (k3g_data->enable)
+ err = i2c_smbus_write_byte_data(k3g_data->client,
+ CTRL_REG1, 0x00);
+ if (k3g_data->interruptible) {
+ if (!k3g_data->enable) /* no disable_irq before free_irq */
+ enable_irq(k3g_data->client->irq);
+ free_irq(k3g_data->client->irq, k3g_data);
+
+ } else {
+ hrtimer_cancel(&k3g_data->timer);
+ cancel_work_sync(&k3g_data->work);
+ destroy_workqueue(k3g_data->k3g_wq);
+ }
+
+ input_unregister_device(k3g_data->input_dev);
+ mutex_destroy(&k3g_data->lock);
+ kfree(k3g_data);
+
+ return err;
+}
+
+static int k3g_suspend(struct device *dev)
+{
+ int err = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct k3g_data *k3g_data = i2c_get_clientdata(client);
+
+ if (k3g_data->enable) {
+ mutex_lock(&k3g_data->lock);
+ if (!k3g_data->interruptible) {
+ hrtimer_cancel(&k3g_data->timer);
+ cancel_work_sync(&k3g_data->work);
+ }
+ err = i2c_smbus_write_byte_data(k3g_data->client,
+ CTRL_REG1, 0x00);
+ mutex_unlock(&k3g_data->lock);
+ }
+
+ return err;
+}
+
+static int k3g_resume(struct device *dev)
+{
+ int err = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct k3g_data *k3g_data = i2c_get_clientdata(client);
+
+ if (k3g_data->enable) {
+ mutex_lock(&k3g_data->lock);
+ if (!k3g_data->interruptible)
+ hrtimer_start(&k3g_data->timer,
+ k3g_data->polling_delay, HRTIMER_MODE_REL);
+ err = i2c_smbus_write_i2c_block_data(client,
+ CTRL_REG1 | AC, sizeof(k3g_data->ctrl_regs),
+ k3g_data->ctrl_regs);
+ mutex_unlock(&k3g_data->lock);
+ }
+
+ return err;
+}
+
+static const struct dev_pm_ops k3g_pm_ops = {
+ .suspend = k3g_suspend,
+ .resume = k3g_resume
+};
+
+static const struct i2c_device_id k3g_id[] = {
+ { "k3g", 0 },
+ { }
+};
+
+MODULE_DEVICE_TABLE(i2c, k3g_id);
+
+static struct i2c_driver k3g_driver = {
+ .probe = k3g_probe,
+ .remove = __devexit_p(k3g_remove),
+ .id_table = k3g_id,
+ .driver = {
+ .pm = &k3g_pm_ops,
+ .owner = THIS_MODULE,
+ .name = "k3g"
+ },
+};
+
+static int __init k3g_init(void)
+{
+ return i2c_add_driver(&k3g_driver);
+}
+
+static void __exit k3g_exit(void)
+{
+ i2c_del_driver(&k3g_driver);
+}
+
+module_init(k3g_init);
+module_exit(k3g_exit);
+
+MODULE_DESCRIPTION("k3g digital gyroscope driver");
+MODULE_AUTHOR("Tim SK Lee Samsung Electronics <tim.sk.lee@samsung.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index bb9f5d3..e01fd4c 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -177,6 +177,20 @@ static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = {
},
},
{
+ /* Gigabyte T1005 - defines wrong chassis type ("Other") */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "T1005"),
+ },
+ },
+ {
+ /* Gigabyte T1005M/P - defines wrong chassis type ("Other") */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "T1005M/P"),
+ },
+ },
+ {
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv9700"),
@@ -321,6 +335,12 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = {
},
{
.matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE C850D"),
+ },
+ },
+ {
+ .matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ALIENWARE"),
DMI_MATCH(DMI_PRODUCT_NAME, "Sentia"),
},
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 08ba5ad..a28ebf0 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -242,7 +242,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom)
input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
if (wacom->tool[0] != BTN_TOOL_MOUSE) {
- input_report_abs(input, ABS_PRESSURE, data[6] | ((data[7] & 0x01) << 8));
+ input_report_abs(input, ABS_PRESSURE, data[6] | ((data[7] & 0x03) << 8));
input_report_key(input, BTN_TOUCH, data[1] & 0x01);
input_report_key(input, BTN_STYLUS, data[1] & 0x02);
input_report_key(input, BTN_STYLUS2, data[1] & 0x04);
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 4104103..69d8fd2 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -319,6 +319,18 @@ config TOUCHSCREEN_MK712
To compile this driver as a module, choose M here: the
module will be called mk712.
+config TOUCHSCREEN_MXT224
+ tristate "Atmel MaxTouch 224"
+ depends on I2C
+ help
+ Say Y here to enable support for the Atmel MaxTouch 224 touch
+ controller.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called mxt224.
+
config TOUCHSCREEN_HP600
tristate "HP Jornada 6xx touchscreen"
depends on SH_HP6XX && SH_ADC
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 0738f19..ae5aeaa 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -33,6 +33,7 @@ obj-$(CONFIG_TOUCHSCREEN_MCS5000) += mcs5000_ts.o
obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o
obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o
obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o
+obj-$(CONFIG_TOUCHSCREEN_MXT224) += mxt224.o
obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o
obj-$(CONFIG_TOUCHSCREEN_HP7XX) += jornada720_ts.o
obj-$(CONFIG_TOUCHSCREEN_HTCPEN) += htcpen.o
diff --git a/drivers/input/touchscreen/mxt224.c b/drivers/input/touchscreen/mxt224.c
new file mode 100644
index 0000000..0d9e132
--- /dev/null
+++ b/drivers/input/touchscreen/mxt224.c
@@ -0,0 +1,658 @@
+/*
+ * Copyright (C) 2010, Samsung Electronics Co. Ltd. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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/kernel.h>
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/earlysuspend.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/input/mxt224.h>
+#include <asm/unaligned.h>
+
+#ifdef CONFIG_BLD
+#include <linux/bld.h>
+#endif
+
+#define OBJECT_TABLE_START_ADDRESS 7
+#define OBJECT_TABLE_ELEMENT_SIZE 6
+
+#define CMD_RESET_OFFSET 0
+#define CMD_BACKUP_OFFSET 1
+
+#define DETECT_MSG_MASK 0x80
+#define PRESS_MSG_MASK 0x40
+#define RELEASE_MSG_MASK 0x20
+#define MOVE_MSG_MASK 0x10
+#define SUPPRESS_MSG_MASK 0x02
+
+#define ID_BLOCK_SIZE 7
+
+struct object_t {
+ u8 object_type;
+ u16 i2c_address;
+ u8 size;
+ u8 instances;
+ u8 num_report_ids;
+} __packed;
+
+struct finger_info {
+ s16 x;
+ s16 y;
+ s16 z;
+ u16 w;
+};
+
+struct mxt224_data {
+ struct i2c_client *client;
+ struct input_dev *input_dev;
+ struct early_suspend early_suspend;
+ u32 finger_mask;
+ int gpio_read_done;
+ struct object_t *objects;
+ u8 objects_len;
+ u8 tsp_version;
+ const u8 *power_cfg;
+ u8 finger_type;
+ u16 msg_proc;
+ u16 cmd_proc;
+ u16 msg_object_size;
+ u32 x_dropbits:2;
+ u32 y_dropbits:2;
+ void (*power_on)(void);
+ void (*power_off)(void);
+ int num_fingers;
+ struct finger_info fingers[];
+};
+
+static int read_mem(struct mxt224_data *data, u16 reg, u8 len, u8 *buf)
+{
+ int ret;
+ u16 le_reg = cpu_to_le16(reg);
+ struct i2c_msg msg[2] = {
+ {
+ .addr = data->client->addr,
+ .flags = 0,
+ .len = 2,
+ .buf = (u8 *)&le_reg,
+ },
+ {
+ .addr = data->client->addr,
+ .flags = I2C_M_RD,
+ .len = len,
+ .buf = buf,
+ },
+ };
+
+ ret = i2c_transfer(data->client->adapter, msg, 2);
+ if (ret < 0)
+ return ret;
+
+ return ret == 2 ? 0 : -EIO;
+}
+
+static int write_mem(struct mxt224_data *data, u16 reg, u8 len, const u8 *buf)
+{
+ int ret;
+ u8 tmp[len + 2];
+
+ put_unaligned_le16(cpu_to_le16(reg), tmp);
+ memcpy(tmp + 2, buf, len);
+
+ ret = i2c_master_send(data->client, tmp, sizeof(tmp));
+ if (ret < 0)
+ return ret;
+
+ return ret == sizeof(tmp) ? 0 : -EIO;
+}
+
+static int __devinit mxt224_reset(struct mxt224_data *data)
+{
+ u8 buf = 1u;
+ return write_mem(data, data->cmd_proc + CMD_RESET_OFFSET, 1, &buf);
+}
+
+static int __devinit mxt224_backup(struct mxt224_data *data)
+{
+ u8 buf = 0x55u;
+ return write_mem(data, data->cmd_proc + CMD_BACKUP_OFFSET, 1, &buf);
+}
+
+static int get_object_info(struct mxt224_data *data, u8 object_type, u16 *size,
+ u16 *address)
+{
+ int i;
+
+ for (i = 0; i < data->objects_len; i++) {
+ if (data->objects[i].object_type == object_type) {
+ *size = data->objects[i].size + 1;
+ *address = data->objects[i].i2c_address;
+ return 0;
+ }
+ }
+
+ return -ENODEV;
+}
+
+static int write_config(struct mxt224_data *data, u8 type, const u8 *cfg)
+{
+ int ret;
+ u16 address;
+ u16 size;
+
+ ret = get_object_info(data, type, &size, &address);
+
+ if (ret)
+ return ret;
+
+ return write_mem(data, address, size, cfg);
+}
+
+
+static u32 __devinit crc24(u32 crc, u8 byte1, u8 byte2)
+{
+ static const u32 crcpoly = 0x80001B;
+ u32 res;
+ u16 data_word;
+
+ data_word = (((u16)byte2) << 8) | byte1;
+ res = (crc << 1) ^ (u32)data_word;
+
+ if (res & 0x1000000)
+ res ^= crcpoly;
+
+ return res;
+}
+
+static int __devinit calculate_infoblock_crc(struct mxt224_data *data,
+ u32 *crc_pointer)
+{
+ u32 crc = 0;
+ u8 mem[7 + data->objects_len * 6];
+ int status;
+ int i;
+
+ status = read_mem(data, 0, sizeof(mem), mem);
+
+ if (status)
+ return status;
+
+ for (i = 0; i < sizeof(mem) - 1; i += 2)
+ crc = crc24(crc, mem[i], mem[i + 1]);
+
+ *crc_pointer = crc24(crc, mem[i], 0) & 0x00FFFFFF;
+
+ return 0;
+}
+
+static int __devinit mxt224_init_touch_driver(struct mxt224_data *data)
+{
+ struct object_t *object_table;
+ u32 read_crc = 0;
+ u32 calc_crc;
+ u16 crc_address;
+ u16 dummy;
+ int i;
+ u8 id[ID_BLOCK_SIZE];
+ int ret;
+ u8 type_count = 0;
+ u8 tmp;
+
+ ret = read_mem(data, 0, sizeof(id), id);
+ if (ret)
+ return ret;
+
+ dev_info(&data->client->dev, "family = %#02x, variant = %#02x, version "
+ "= %#02x, build = %d\n", id[0], id[1], id[2], id[3]);
+ dev_dbg(&data->client->dev, "matrix X size = %d\n", id[4]);
+ dev_dbg(&data->client->dev, "matrix Y size = %d\n", id[5]);
+
+ data->tsp_version = id[2];
+ data->objects_len = id[6];
+
+ object_table = kmalloc(data->objects_len * sizeof(*object_table),
+ GFP_KERNEL);
+ if (!object_table)
+ return -ENOMEM;
+
+ ret = read_mem(data, OBJECT_TABLE_START_ADDRESS,
+ data->objects_len * sizeof(*object_table),
+ (u8 *)object_table);
+ if (ret)
+ goto err;
+
+ for (i = 0; i < data->objects_len; i++) {
+ object_table[i].i2c_address =
+ le16_to_cpu(object_table[i].i2c_address);
+ tmp = 0;
+ if (object_table[i].num_report_ids) {
+ tmp = type_count + 1;
+ type_count += object_table[i].num_report_ids *
+ (object_table[i].instances + 1);
+ }
+ switch (object_table[i].object_type) {
+ case TOUCH_MULTITOUCHSCREEN_T9:
+ data->finger_type = tmp;
+ dev_dbg(&data->client->dev, "Finger type = %d\n",
+ data->finger_type);
+ break;
+ case GEN_MESSAGEPROCESSOR_T5:
+ data->msg_object_size = object_table[i].size + 1;
+ dev_dbg(&data->client->dev, "Message object size = "
+ "%d\n", data->msg_object_size);
+ break;
+ }
+ }
+
+ data->objects = object_table;
+
+ /* Verify CRC */
+ crc_address = OBJECT_TABLE_START_ADDRESS +
+ data->objects_len * OBJECT_TABLE_ELEMENT_SIZE;
+
+#ifdef __BIG_ENDIAN
+#error The following code will likely break on a big endian machine
+#endif
+ ret = read_mem(data, crc_address, 3, (u8 *)&read_crc);
+ if (ret)
+ goto err;
+
+ read_crc = le32_to_cpu(read_crc);
+
+ ret = calculate_infoblock_crc(data, &calc_crc);
+ if (ret)
+ goto err;
+
+ if (read_crc != calc_crc) {
+ dev_err(&data->client->dev, "CRC error\n");
+ ret = -EFAULT;
+ goto err;
+ }
+
+ ret = get_object_info(data, GEN_MESSAGEPROCESSOR_T5, &dummy,
+ &data->msg_proc);
+ if (ret)
+ goto err;
+
+ ret = get_object_info(data, GEN_COMMANDPROCESSOR_T6, &dummy,
+ &data->cmd_proc);
+ if (ret)
+ goto err;
+
+ return 0;
+
+err:
+ kfree(object_table);
+ return ret;
+}
+
+static void report_input_data(struct mxt224_data *data)
+{
+ int i;
+ int num_fingers_down;
+
+ num_fingers_down = 0;
+ for (i = 0; i < data->num_fingers; i++) {
+ if (data->fingers[i].z == -1)
+ continue;
+
+ input_report_abs(data->input_dev, ABS_MT_POSITION_X,
+ data->fingers[i].x);
+ input_report_abs(data->input_dev, ABS_MT_POSITION_Y,
+ data->fingers[i].y);
+ input_report_abs(data->input_dev, ABS_MT_PRESSURE,
+ data->fingers[i].z);
+ input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR,
+ data->fingers[i].w);
+ input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, i);
+ input_mt_sync(data->input_dev);
+ num_fingers_down++;
+
+#ifdef CONFIG_BLD
+ if (system_rev >= 0x30 && data->fingers[i].y > BLD_TOUCHKEYS_POSITION)
+ {
+ touchkey_pressed();
+ }
+#endif
+ }
+ data->finger_mask = 0;
+
+ if (num_fingers_down == 0)
+ input_mt_sync(data->input_dev);
+ input_sync(data->input_dev);
+}
+
+static irqreturn_t mxt224_irq_thread(int irq, void *ptr)
+{
+ struct mxt224_data *data = ptr;
+ int id;
+ u8 msg[data->msg_object_size];
+
+ do {
+ if (read_mem(data, data->msg_proc, sizeof(msg), msg))
+ return IRQ_HANDLED;
+
+ id = msg[0] - data->finger_type;
+
+ /* If not a touch event, then keep going */
+ if (id < 0 || id >= data->num_fingers)
+ continue;
+
+ if (data->finger_mask & (1U << id))
+ report_input_data(data);
+
+ if (msg[1] & RELEASE_MSG_MASK) {
+ data->fingers[id].z = -1;
+ data->fingers[id].w = msg[5];
+ data->finger_mask |= 1U << id;
+ } else if ((msg[1] & DETECT_MSG_MASK) && (msg[1] &
+ (PRESS_MSG_MASK | MOVE_MSG_MASK))) {
+ data->fingers[id].z = msg[6];
+ data->fingers[id].w = msg[5];
+ data->fingers[id].x = ((msg[2] << 4) | (msg[4] >> 4)) >>
+ data->x_dropbits;
+ data->fingers[id].y = ((msg[3] << 4) |
+ (msg[4] & 0xF)) >> data->y_dropbits;
+ data->finger_mask |= 1U << id;
+ } else if ((msg[1] & SUPPRESS_MSG_MASK) &&
+ (data->fingers[id].z != -1)) {
+ data->fingers[id].z = -1;
+ data->fingers[id].w = msg[5];
+ data->finger_mask |= 1U << id;
+ } else {
+ dev_dbg(&data->client->dev, "Unknown state %#02x %#02x"
+ "\n", msg[0], msg[1]);
+ continue;
+ }
+ } while (!gpio_get_value(data->gpio_read_done));
+
+ if (data->finger_mask)
+ report_input_data(data);
+
+ return IRQ_HANDLED;
+}
+
+static int mxt224_internal_suspend(struct mxt224_data *data)
+{
+ static const u8 sleep_power_cfg[3];
+ int ret;
+ int i;
+
+ ret = write_config(data, GEN_POWERCONFIG_T7, sleep_power_cfg);
+ if (ret)
+ return ret;
+
+
+ for (i = 0; i < data->num_fingers; i++)
+ data->fingers[i].z = -1;
+ report_input_data(data);
+
+ data->power_off();
+
+ return 0;
+}
+
+static int mxt224_internal_resume(struct mxt224_data *data)
+{
+ int ret;
+ int i;
+
+ data->power_on();
+
+ i = 0;
+ do {
+ ret = write_config(data, GEN_POWERCONFIG_T7, data->power_cfg);
+ msleep(20);
+ i++;
+ } while (ret && i < 10);
+
+ return ret;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#define mxt224_suspend NULL
+#define mxt224_resume NULL
+
+static void mxt224_early_suspend(struct early_suspend *h)
+{
+ struct mxt224_data *data = container_of(h, struct mxt224_data,
+ early_suspend);
+ disable_irq(data->client->irq);
+ mxt224_internal_suspend(data);
+}
+
+static void mxt224_late_resume(struct early_suspend *h)
+{
+ struct mxt224_data *data = container_of(h, struct mxt224_data,
+ early_suspend);
+ mxt224_internal_resume(data);
+ enable_irq(data->client->irq);
+}
+#else
+static int mxt224_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct mxt224_data *data = i2c_get_clientdata(client);
+
+ return mxt224_internal_suspend(data);
+}
+
+static int mxt224_resume(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct mxt224_data *data = i2c_get_clientdata(client);
+
+ return mxt224_internal_resume(data);
+}
+#endif
+
+static int __devinit mxt224_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct mxt224_platform_data *pdata = client->dev.platform_data;
+ struct mxt224_data *data;
+ struct input_dev *input_dev;
+ int ret;
+ int i;
+
+ if (!pdata) {
+ dev_err(&client->dev, "missing platform data\n");
+ return -ENODEV;
+ }
+
+ if (pdata->max_finger_touches <= 0)
+ return -EINVAL;
+
+ data = kzalloc(sizeof(*data) + pdata->max_finger_touches *
+ sizeof(*data->fingers), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->num_fingers = pdata->max_finger_touches;
+ data->power_on = pdata->power_on;
+ data->power_off = pdata->power_off;
+
+ data->client = client;
+ i2c_set_clientdata(client, data);
+
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ ret = -ENOMEM;
+ dev_err(&client->dev, "input device allocation failed\n");
+ goto err_alloc_dev;
+ }
+ data->input_dev = input_dev;
+ input_set_drvdata(input_dev, data);
+ input_dev->name = "mxt224_ts_input";
+
+ set_bit(EV_ABS, input_dev->evbit);
+
+ input_set_abs_params(input_dev, ABS_MT_POSITION_X, pdata->min_x,
+ pdata->max_x, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y, pdata->min_y,
+ pdata->max_y, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_PRESSURE, pdata->min_z,
+ pdata->max_z, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, pdata->min_w,
+ pdata->max_w, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0,
+ data->num_fingers - 1, 0, 0);
+
+ ret = input_register_device(input_dev);
+ if (ret) {
+ input_free_device(input_dev);
+ goto err_reg_dev;
+ }
+
+ data->gpio_read_done = pdata->gpio_read_done;
+ ret = gpio_request(data->gpio_read_done, "touch read done");
+ if (ret)
+ goto err_gpio_req;
+
+ data->power_on();
+
+ ret = mxt224_init_touch_driver(data);
+ if (ret) {
+ dev_err(&client->dev, "chip initialization failed\n");
+ goto err_init_drv;
+ }
+
+ for (i = 0; pdata->config[i][0] != RESERVED_T255; i++) {
+ ret = write_config(data, pdata->config[i][0],
+ pdata->config[i] + 1);
+ if (ret)
+ goto err_config;
+
+ if (pdata->config[i][0] == GEN_POWERCONFIG_T7)
+ data->power_cfg = pdata->config[i] + 1;
+
+ if (pdata->config[i][0] == TOUCH_MULTITOUCHSCREEN_T9) {
+ /* Are x and y inverted? */
+ if (pdata->config[i][10] & 0x1) {
+ data->x_dropbits =
+ (!(pdata->config[i][22] & 0xC)) << 1;
+ data->y_dropbits =
+ (!(pdata->config[i][20] & 0xC)) << 1;
+ } else {
+ data->x_dropbits =
+ (!(pdata->config[i][20] & 0xC)) << 1;
+ data->y_dropbits =
+ (!(pdata->config[i][22] & 0xC)) << 1;
+ }
+ }
+ }
+
+ ret = mxt224_backup(data);
+ if (ret)
+ goto err_backup;
+
+ /* reset the touch IC. */
+ ret = mxt224_reset(data);
+ if (ret)
+ goto err_reset;
+
+ msleep(60);
+
+ for (i = 0; i < data->num_fingers; i++)
+ data->fingers[i].z = -1;
+
+ ret = request_threaded_irq(client->irq, NULL, mxt224_irq_thread,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT, "mxt224_ts", data);
+ if (ret < 0)
+ goto err_irq;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+ data->early_suspend.suspend = mxt224_early_suspend;
+ data->early_suspend.resume = mxt224_late_resume;
+ register_early_suspend(&data->early_suspend);
+#endif
+
+ return 0;
+
+err_irq:
+err_reset:
+err_backup:
+err_config:
+ kfree(data->objects);
+err_init_drv:
+ gpio_free(data->gpio_read_done);
+err_gpio_req:
+ data->power_off();
+ input_unregister_device(input_dev);
+err_reg_dev:
+err_alloc_dev:
+ kfree(data);
+ return ret;
+}
+
+static int __devexit mxt224_remove(struct i2c_client *client)
+{
+ struct mxt224_data *data = i2c_get_clientdata(client);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&data->early_suspend);
+#endif
+ free_irq(client->irq, data);
+ kfree(data->objects);
+ gpio_free(data->gpio_read_done);
+ data->power_off();
+ input_unregister_device(data->input_dev);
+ kfree(data);
+
+ return 0;
+}
+
+static struct i2c_device_id mxt224_idtable[] = {
+ {MXT224_DEV_NAME, 0},
+ {},
+};
+
+MODULE_DEVICE_TABLE(i2c, mxt224_idtable);
+
+static const struct dev_pm_ops mxt224_pm_ops = {
+ .suspend = mxt224_suspend,
+ .resume = mxt224_resume,
+};
+
+static struct i2c_driver mxt224_i2c_driver = {
+ .id_table = mxt224_idtable,
+ .probe = mxt224_probe,
+ .remove = __devexit_p(mxt224_remove),
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = MXT224_DEV_NAME,
+ .pm = &mxt224_pm_ops,
+ },
+};
+
+static int __init mxt224_init(void)
+{
+ return i2c_add_driver(&mxt224_i2c_driver);
+}
+
+static void __exit mxt224_exit(void)
+{
+ i2c_del_driver(&mxt224_i2c_driver);
+}
+module_init(mxt224_init);
+module_exit(mxt224_exit);
+
+MODULE_DESCRIPTION("Atmel MaXTouch 224 driver");
+MODULE_AUTHOR("Rom Lemarchand <rlemarchand@sta.samsung.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c
index 658e75f..d1dde65 100644
--- a/drivers/isdn/gigaset/capi.c
+++ b/drivers/isdn/gigaset/capi.c
@@ -14,6 +14,7 @@
#include "gigaset.h"
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include <linux/ratelimit.h>
#include <linux/isdn/capilli.h>
#include <linux/isdn/capicmd.h>
#include <linux/isdn/capiutil.h>
@@ -222,10 +223,14 @@ get_appl(struct gigaset_capi_ctr *iif, u16 appl)
static inline void dump_cmsg(enum debuglevel level, const char *tag, _cmsg *p)
{
#ifdef CONFIG_GIGASET_DEBUG
+ /* dump at most 20 messages in 20 secs */
+ static DEFINE_RATELIMIT_STATE(msg_dump_ratelimit, 20 * HZ, 20);
_cdebbuf *cdb;
if (!(gigaset_debuglevel & level))
return;
+ if (!___ratelimit(&msg_dump_ratelimit, tag))
+ return;
cdb = capi_cmsg2str(p);
if (cdb) {
@@ -2058,12 +2063,6 @@ static void do_reset_b3_req(struct gigaset_capi_ctr *iif,
}
/*
- * dump unsupported/ignored messages at most twice per minute,
- * some apps send those very frequently
- */
-static unsigned long ignored_msg_dump_time;
-
-/*
* unsupported CAPI message handler
*/
static void do_unsupported(struct gigaset_capi_ctr *iif,
@@ -2072,8 +2071,7 @@ static void do_unsupported(struct gigaset_capi_ctr *iif,
{
/* decode message */
capi_message2cmsg(&iif->acmsg, skb->data);
- if (printk_timed_ratelimit(&ignored_msg_dump_time, 30 * 1000))
- dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg);
+ dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg);
send_conf(iif, ap, skb, CapiMessageNotSupportedInCurrentState);
}
@@ -2084,11 +2082,9 @@ static void do_nothing(struct gigaset_capi_ctr *iif,
struct gigaset_capi_appl *ap,
struct sk_buff *skb)
{
- if (printk_timed_ratelimit(&ignored_msg_dump_time, 30 * 1000)) {
- /* decode message */
- capi_message2cmsg(&iif->acmsg, skb->data);
- dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg);
- }
+ /* decode message */
+ capi_message2cmsg(&iif->acmsg, skb->data);
+ dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg);
dev_kfree_skb_any(skb);
}
diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c
index d497db0..509135f 100644
--- a/drivers/isdn/isdnloop/isdnloop.c
+++ b/drivers/isdn/isdnloop/isdnloop.c
@@ -16,7 +16,6 @@
#include <linux/sched.h>
#include "isdnloop.h"
-static char *revision = "$Revision: 1.11.6.7 $";
static char *isdnloop_id = "loop0";
MODULE_DESCRIPTION("ISDN4Linux: Pseudo Driver that simulates an ISDN card");
@@ -1494,17 +1493,6 @@ isdnloop_addcard(char *id1)
static int __init
isdnloop_init(void)
{
- char *p;
- char rev[10];
-
- if ((p = strchr(revision, ':'))) {
- strcpy(rev, p + 1);
- p = strchr(rev, '$');
- *p = 0;
- } else
- strcpy(rev, " ??? ");
- printk(KERN_NOTICE "isdnloop-ISDN-driver Rev%s\n", rev);
-
if (isdnloop_id)
return (isdnloop_addcard(isdnloop_id));
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index 9bfd057..42ef54f 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -1210,7 +1210,7 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio,
* We need to dec pending if this was a write.
*/
if (rw == WRITE) {
- if (!(bio->bi_rw & REQ_FLUSH))
+ if (!(bio->bi_rw & (REQ_FLUSH | REQ_DISCARD)))
dm_rh_dec(ms->rh, map_context->ll);
return error;
}
diff --git a/drivers/md/dm-region-hash.c b/drivers/md/dm-region-hash.c
index 7771ed2..69732e0 100644
--- a/drivers/md/dm-region-hash.c
+++ b/drivers/md/dm-region-hash.c
@@ -404,6 +404,9 @@ void dm_rh_mark_nosync(struct dm_region_hash *rh, struct bio *bio)
return;
}
+ if (bio->bi_rw & REQ_DISCARD)
+ return;
+
/* We must inform the log that the sync count has changed. */
log->type->set_region_sync(log, region, 0);
@@ -524,7 +527,7 @@ void dm_rh_inc_pending(struct dm_region_hash *rh, struct bio_list *bios)
struct bio *bio;
for (bio = bios->head; bio; bio = bio->bi_next) {
- if (bio->bi_rw & REQ_FLUSH)
+ if (bio->bi_rw & (REQ_FLUSH | REQ_DISCARD))
continue;
rh_inc(rh, dm_rh_bio_to_region(rh, bio));
}
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 41abc6d..1889b1e 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -856,10 +856,14 @@ static void dm_done(struct request *clone, int error, bool mapped)
{
int r = error;
struct dm_rq_target_io *tio = clone->end_io_data;
- dm_request_endio_fn rq_end_io = tio->ti->type->rq_end_io;
+ dm_request_endio_fn rq_end_io = NULL;
- if (mapped && rq_end_io)
- r = rq_end_io(tio->ti, clone, error, &tio->info);
+ if (tio->ti) {
+ rq_end_io = tio->ti->type->rq_end_io;
+
+ if (mapped && rq_end_io)
+ r = rq_end_io(tio->ti, clone, error, &tio->info);
+ }
if (r <= 0)
/* The target wants to complete the I/O */
@@ -1562,15 +1566,6 @@ static int map_request(struct dm_target *ti, struct request *clone,
int r, requeued = 0;
struct dm_rq_target_io *tio = clone->end_io_data;
- /*
- * Hold the md reference here for the in-flight I/O.
- * We can't rely on the reference count by device opener,
- * because the device may be closed during the request completion
- * when all bios are completed.
- * See the comment in rq_completed() too.
- */
- dm_get(md);
-
tio->ti = ti;
r = ti->type->map_rq(ti, clone, &tio->info);
switch (r) {
@@ -1602,6 +1597,26 @@ static int map_request(struct dm_target *ti, struct request *clone,
return requeued;
}
+static struct request *dm_start_request(struct mapped_device *md, struct request *orig)
+{
+ struct request *clone;
+
+ blk_start_request(orig);
+ clone = orig->special;
+ atomic_inc(&md->pending[rq_data_dir(clone)]);
+
+ /*
+ * Hold the md reference here for the in-flight I/O.
+ * We can't rely on the reference count by device opener,
+ * because the device may be closed during the request completion
+ * when all bios are completed.
+ * See the comment in rq_completed() too.
+ */
+ dm_get(md);
+
+ return clone;
+}
+
/*
* q->request_fn for request-based dm.
* Called with the queue lock held.
@@ -1631,14 +1646,21 @@ static void dm_request_fn(struct request_queue *q)
pos = blk_rq_pos(rq);
ti = dm_table_find_target(map, pos);
- BUG_ON(!dm_target_is_valid(ti));
+ if (!dm_target_is_valid(ti)) {
+ /*
+ * Must perform setup, that dm_done() requires,
+ * before calling dm_kill_unmapped_request
+ */
+ DMERR_LIMIT("request attempted access beyond the end of device");
+ clone = dm_start_request(md, rq);
+ dm_kill_unmapped_request(clone, -EIO);
+ continue;
+ }
if (ti->type->busy && ti->type->busy(ti))
goto delay_and_out;
- blk_start_request(rq);
- clone = rq->special;
- atomic_inc(&md->pending[rq_data_dir(clone)]);
+ clone = dm_start_request(md, rq);
spin_unlock(q->queue_lock);
if (map_request(ti, clone, md))
@@ -1658,8 +1680,6 @@ delay_and_out:
blk_delay_queue(q, HZ / 10);
out:
dm_table_put(map);
-
- return;
}
int dm_underlying_device_busy(struct request_queue *q)
diff --git a/drivers/md/md.c b/drivers/md/md.c
index bc83428..98262e5 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -348,6 +348,8 @@ void mddev_suspend(mddev_t *mddev)
synchronize_rcu();
wait_event(mddev->sb_wait, atomic_read(&mddev->active_io) == 0);
mddev->pers->quiesce(mddev, 1);
+
+ del_timer_sync(&mddev->safemode_timer);
}
EXPORT_SYMBOL_GPL(mddev_suspend);
@@ -407,7 +409,7 @@ static void submit_flushes(struct work_struct *ws)
atomic_inc(&rdev->nr_pending);
atomic_inc(&rdev->nr_pending);
rcu_read_unlock();
- bi = bio_alloc_mddev(GFP_KERNEL, 0, mddev);
+ bi = bio_alloc_mddev(GFP_NOIO, 0, mddev);
bi->bi_end_io = md_end_flush;
bi->bi_private = rdev;
bi->bi_bdev = rdev->bdev;
@@ -1094,8 +1096,11 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
ret = 0;
}
rdev->sectors = rdev->sb_start;
- /* Limit to 4TB as metadata cannot record more than that */
- if (rdev->sectors >= (2ULL << 32))
+ /* Limit to 4TB as metadata cannot record more than that.
+ * (not needed for Linear and RAID0 as metadata doesn't
+ * record this size)
+ */
+ if (rdev->sectors >= (2ULL << 32) && sb->level >= 1)
rdev->sectors = (2ULL << 32) - 2;
if (rdev->sectors < ((sector_t)sb->size) * 2 && sb->level >= 1)
@@ -1377,7 +1382,7 @@ super_90_rdev_size_change(mdk_rdev_t *rdev, sector_t num_sectors)
/* Limit to 4TB as metadata cannot record more than that.
* 4TB == 2^32 KB, or 2*2^32 sectors.
*/
- if (num_sectors >= (2ULL << 32))
+ if (num_sectors >= (2ULL << 32) && rdev->mddev->level >= 1)
num_sectors = (2ULL << 32) - 2;
md_super_write(rdev->mddev, rdev, rdev->sb_start, rdev->sb_size,
rdev->sb_page);
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 0d6c42f..b65a7c5 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1858,6 +1858,12 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr,
/* want to reconstruct this device */
rb2 = r10_bio;
sect = raid10_find_virt(conf, sector_nr, i);
+ if (sect >= mddev->resync_max_sectors) {
+ /* last stripe is not complete - don't
+ * try to recover this sector.
+ */
+ continue;
+ }
/* Unless we are doing a full sync, we only need
* to recover the block if it is set in the bitmap
*/
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 1f6c68d..cff955a 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -199,12 +199,14 @@ static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh)
BUG_ON(!list_empty(&sh->lru));
BUG_ON(atomic_read(&conf->active_stripes)==0);
if (test_bit(STRIPE_HANDLE, &sh->state)) {
- if (test_bit(STRIPE_DELAYED, &sh->state))
+ if (test_bit(STRIPE_DELAYED, &sh->state) &&
+ !test_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
list_add_tail(&sh->lru, &conf->delayed_list);
else if (test_bit(STRIPE_BIT_DELAY, &sh->state) &&
sh->bm_seq - conf->seq_write > 0)
list_add_tail(&sh->lru, &conf->bitmap_list);
else {
+ clear_bit(STRIPE_DELAYED, &sh->state);
clear_bit(STRIPE_BIT_DELAY, &sh->state);
list_add_tail(&sh->lru, &conf->handle_list);
}
@@ -3846,7 +3848,6 @@ static int chunk_aligned_read(mddev_t *mddev, struct bio * raid_bio)
raid_bio->bi_next = (void*)rdev;
align_bi->bi_bdev = rdev->bdev;
align_bi->bi_flags &= ~(1 << BIO_SEG_VALID);
- align_bi->bi_sector += rdev->data_offset;
if (!bio_fits_rdev(align_bi)) {
/* too big in some way */
@@ -3855,6 +3856,9 @@ static int chunk_aligned_read(mddev_t *mddev, struct bio * raid_bio)
return 0;
}
+ /* No reshape active, so we can trust rdev->data_offset */
+ align_bi->bi_sector += rdev->data_offset;
+
spin_lock_irq(&conf->device_lock);
wait_event_lock_irq(conf->wait_for_stripe,
conf->quiesce == 0,
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index f732877..d5cda35 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -243,6 +243,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
if (minor == MAX_DVB_MINORS) {
kfree(dvbdevfops);
kfree(dvbdev);
+ up_write(&minor_rwsem);
mutex_unlock(&dvbdev_register_lock);
return -EINVAL;
}
diff --git a/drivers/media/dvb/siano/smsusb.c b/drivers/media/dvb/siano/smsusb.c
index 0c8164a..3d2867d 100644
--- a/drivers/media/dvb/siano/smsusb.c
+++ b/drivers/media/dvb/siano/smsusb.c
@@ -480,7 +480,7 @@ static int smsusb_resume(struct usb_interface *intf)
return 0;
}
-static const struct usb_device_id smsusb_id_table[] __devinitconst = {
+static const struct usb_device_id smsusb_id_table[] = {
{ USB_DEVICE(0x187f, 0x0010),
.driver_info = SMS1XXX_BOARD_SIANO_STELLAR },
{ USB_DEVICE(0x187f, 0x0100),
@@ -541,6 +541,10 @@ static const struct usb_device_id smsusb_id_table[] __devinitconst = {
.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
{ USB_DEVICE(0x2040, 0xc090),
.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+ { USB_DEVICE(0x2040, 0xc0a0),
+ .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+ { USB_DEVICE(0x2040, 0xf5a0),
+ .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
{ } /* Terminating entry */
};
diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c
index a43ed6c..12b91ae 100644
--- a/drivers/media/rc/ene_ir.c
+++ b/drivers/media/rc/ene_ir.c
@@ -1017,22 +1017,6 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
spin_lock_init(&dev->hw_lock);
- /* claim the resources */
- error = -EBUSY;
- dev->hw_io = pnp_port_start(pnp_dev, 0);
- if (!request_region(dev->hw_io, ENE_IO_SIZE, ENE_DRIVER_NAME)) {
- dev->hw_io = -1;
- dev->irq = -1;
- goto error;
- }
-
- dev->irq = pnp_irq(pnp_dev, 0);
- if (request_irq(dev->irq, ene_isr,
- IRQF_SHARED, ENE_DRIVER_NAME, (void *)dev)) {
- dev->irq = -1;
- goto error;
- }
-
pnp_set_drvdata(pnp_dev, dev);
dev->pnp_dev = pnp_dev;
@@ -1085,6 +1069,22 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
device_set_wakeup_capable(&pnp_dev->dev, true);
device_set_wakeup_enable(&pnp_dev->dev, true);
+ /* claim the resources */
+ error = -EBUSY;
+ dev->hw_io = pnp_port_start(pnp_dev, 0);
+ if (!request_region(dev->hw_io, ENE_IO_SIZE, ENE_DRIVER_NAME)) {
+ dev->hw_io = -1;
+ dev->irq = -1;
+ goto error;
+ }
+
+ dev->irq = pnp_irq(pnp_dev, 0);
+ if (request_irq(dev->irq, ene_isr,
+ IRQF_SHARED, ENE_DRIVER_NAME, (void *)dev)) {
+ dev->irq = -1;
+ goto error;
+ }
+
error = rc_register_device(rdev);
if (error < 0)
goto error;
diff --git a/drivers/media/rc/fintek-cir.c b/drivers/media/rc/fintek-cir.c
index 7f7079b..4218f73 100644
--- a/drivers/media/rc/fintek-cir.c
+++ b/drivers/media/rc/fintek-cir.c
@@ -504,16 +504,6 @@ static int fintek_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id
spin_lock_init(&fintek->fintek_lock);
- ret = -EBUSY;
- /* now claim resources */
- if (!request_region(fintek->cir_addr,
- fintek->cir_port_len, FINTEK_DRIVER_NAME))
- goto failure;
-
- if (request_irq(fintek->cir_irq, fintek_cir_isr, IRQF_SHARED,
- FINTEK_DRIVER_NAME, (void *)fintek))
- goto failure;
-
pnp_set_drvdata(pdev, fintek);
fintek->pdev = pdev;
@@ -548,6 +538,16 @@ static int fintek_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id
/* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */
rdev->rx_resolution = US_TO_NS(CIR_SAMPLE_PERIOD);
+ ret = -EBUSY;
+ /* now claim resources */
+ if (!request_region(fintek->cir_addr,
+ fintek->cir_port_len, FINTEK_DRIVER_NAME))
+ goto failure;
+
+ if (request_irq(fintek->cir_irq, fintek_cir_isr, IRQF_SHARED,
+ FINTEK_DRIVER_NAME, (void *)fintek))
+ goto failure;
+
ret = rc_register_device(rdev);
if (ret)
goto failure;
diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c
index ecd3d02..d8e0b2d8 100644
--- a/drivers/media/rc/ite-cir.c
+++ b/drivers/media/rc/ite-cir.c
@@ -1477,6 +1477,7 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id
rdev = rc_allocate_device();
if (!rdev)
goto failure;
+ itdev->rdev = rdev;
ret = -ENODEV;
@@ -1519,16 +1520,6 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id
/* initialize raw event */
init_ir_raw_event(&itdev->rawir);
- ret = -EBUSY;
- /* now claim resources */
- if (!request_region(itdev->cir_addr,
- dev_desc->io_region_size, ITE_DRIVER_NAME))
- goto failure;
-
- if (request_irq(itdev->cir_irq, ite_cir_isr, IRQF_SHARED,
- ITE_DRIVER_NAME, (void *)itdev))
- goto failure;
-
/* set driver data into the pnp device */
pnp_set_drvdata(pdev, itdev);
itdev->pdev = pdev;
@@ -1604,11 +1595,20 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id
rdev->driver_name = ITE_DRIVER_NAME;
rdev->map_name = RC_MAP_RC6_MCE;
+ ret = -EBUSY;
+ /* now claim resources */
+ if (!request_region(itdev->cir_addr,
+ dev_desc->io_region_size, ITE_DRIVER_NAME))
+ goto failure;
+
+ if (request_irq(itdev->cir_irq, ite_cir_isr, IRQF_SHARED,
+ ITE_DRIVER_NAME, (void *)itdev))
+ goto failure;
+
ret = rc_register_device(rdev);
if (ret)
goto failure;
- itdev->rdev = rdev;
ite_pr(KERN_NOTICE, "driver has been successfully loaded\n");
return 0;
diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index 9fd019e..c212276 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -1027,24 +1027,6 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
spin_lock_init(&nvt->nvt_lock);
spin_lock_init(&nvt->tx.lock);
- ret = -EBUSY;
- /* now claim resources */
- if (!request_region(nvt->cir_addr,
- CIR_IOREG_LENGTH, NVT_DRIVER_NAME))
- goto failure;
-
- if (request_irq(nvt->cir_irq, nvt_cir_isr, IRQF_SHARED,
- NVT_DRIVER_NAME, (void *)nvt))
- goto failure;
-
- if (!request_region(nvt->cir_wake_addr,
- CIR_IOREG_LENGTH, NVT_DRIVER_NAME))
- goto failure;
-
- if (request_irq(nvt->cir_wake_irq, nvt_cir_wake_isr, IRQF_SHARED,
- NVT_DRIVER_NAME, (void *)nvt))
- goto failure;
-
pnp_set_drvdata(pdev, nvt);
nvt->pdev = pdev;
@@ -1091,6 +1073,24 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
rdev->tx_resolution = XYZ;
#endif
+ ret = -EBUSY;
+ /* now claim resources */
+ if (!request_region(nvt->cir_addr,
+ CIR_IOREG_LENGTH, NVT_DRIVER_NAME))
+ goto failure;
+
+ if (request_irq(nvt->cir_irq, nvt_cir_isr, IRQF_SHARED,
+ NVT_DRIVER_NAME, (void *)nvt))
+ goto failure;
+
+ if (!request_region(nvt->cir_wake_addr,
+ CIR_IOREG_LENGTH, NVT_DRIVER_NAME))
+ goto failure;
+
+ if (request_irq(nvt->cir_wake_irq, nvt_cir_wake_isr, IRQF_SHARED,
+ NVT_DRIVER_NAME, (void *)nvt))
+ goto failure;
+
ret = rc_register_device(rdev);
if (ret)
goto failure;
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 3186ac7..9cfb56d 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -772,10 +772,11 @@ static ssize_t show_protocols(struct device *device,
if (dev->driver_type == RC_DRIVER_SCANCODE) {
enabled = dev->rc_map.rc_type;
allowed = dev->allowed_protos;
- } else {
+ } else if (dev->raw) {
enabled = dev->raw->enabled_protocols;
allowed = ir_raw_get_allowed_protocols();
- }
+ } else
+ return -ENODEV;
IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n",
(long long)allowed,
diff --git a/drivers/media/rc/winbond-cir.c b/drivers/media/rc/winbond-cir.c
index 6f03846..9e55a0c 100644
--- a/drivers/media/rc/winbond-cir.c
+++ b/drivers/media/rc/winbond-cir.c
@@ -1003,39 +1003,10 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
"(w: 0x%lX, e: 0x%lX, s: 0x%lX, i: %u)\n",
data->wbase, data->ebase, data->sbase, data->irq);
- if (!request_region(data->wbase, WAKEUP_IOMEM_LEN, DRVNAME)) {
- dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
- data->wbase, data->wbase + WAKEUP_IOMEM_LEN - 1);
- err = -EBUSY;
- goto exit_free_data;
- }
-
- if (!request_region(data->ebase, EHFUNC_IOMEM_LEN, DRVNAME)) {
- dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
- data->ebase, data->ebase + EHFUNC_IOMEM_LEN - 1);
- err = -EBUSY;
- goto exit_release_wbase;
- }
-
- if (!request_region(data->sbase, SP_IOMEM_LEN, DRVNAME)) {
- dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
- data->sbase, data->sbase + SP_IOMEM_LEN - 1);
- err = -EBUSY;
- goto exit_release_ebase;
- }
-
- err = request_irq(data->irq, wbcir_irq_handler,
- IRQF_DISABLED, DRVNAME, device);
- if (err) {
- dev_err(dev, "Failed to claim IRQ %u\n", data->irq);
- err = -EBUSY;
- goto exit_release_sbase;
- }
-
led_trigger_register_simple("cir-tx", &data->txtrigger);
if (!data->txtrigger) {
err = -ENOMEM;
- goto exit_free_irq;
+ goto exit_free_data;
}
led_trigger_register_simple("cir-rx", &data->rxtrigger);
@@ -1074,9 +1045,38 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
data->dev->priv = data;
data->dev->dev.parent = &device->dev;
+ if (!request_region(data->wbase, WAKEUP_IOMEM_LEN, DRVNAME)) {
+ dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
+ data->wbase, data->wbase + WAKEUP_IOMEM_LEN - 1);
+ err = -EBUSY;
+ goto exit_free_rc;
+ }
+
+ if (!request_region(data->ebase, EHFUNC_IOMEM_LEN, DRVNAME)) {
+ dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
+ data->ebase, data->ebase + EHFUNC_IOMEM_LEN - 1);
+ err = -EBUSY;
+ goto exit_release_wbase;
+ }
+
+ if (!request_region(data->sbase, SP_IOMEM_LEN, DRVNAME)) {
+ dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
+ data->sbase, data->sbase + SP_IOMEM_LEN - 1);
+ err = -EBUSY;
+ goto exit_release_ebase;
+ }
+
+ err = request_irq(data->irq, wbcir_irq_handler,
+ IRQF_DISABLED, DRVNAME, device);
+ if (err) {
+ dev_err(dev, "Failed to claim IRQ %u\n", data->irq);
+ err = -EBUSY;
+ goto exit_release_sbase;
+ }
+
err = rc_register_device(data->dev);
if (err)
- goto exit_free_rc;
+ goto exit_free_irq;
device_init_wakeup(&device->dev, 1);
@@ -1084,14 +1084,6 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
return 0;
-exit_free_rc:
- rc_free_device(data->dev);
-exit_unregister_led:
- led_classdev_unregister(&data->led);
-exit_unregister_rxtrigger:
- led_trigger_unregister_simple(data->rxtrigger);
-exit_unregister_txtrigger:
- led_trigger_unregister_simple(data->txtrigger);
exit_free_irq:
free_irq(data->irq, device);
exit_release_sbase:
@@ -1100,6 +1092,14 @@ exit_release_ebase:
release_region(data->ebase, EHFUNC_IOMEM_LEN);
exit_release_wbase:
release_region(data->wbase, WAKEUP_IOMEM_LEN);
+exit_free_rc:
+ rc_free_device(data->dev);
+exit_unregister_led:
+ led_classdev_unregister(&data->led);
+exit_unregister_rxtrigger:
+ led_trigger_unregister_simple(data->rxtrigger);
+exit_unregister_txtrigger:
+ led_trigger_unregister_simple(data->txtrigger);
exit_free_data:
kfree(data);
pnp_set_drvdata(device, NULL);
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index bb53de7..7937b34 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -1031,6 +1031,42 @@ config USB_S2255
This driver can be compiled as a module, called s2255drv.
endif # V4L_USB_DRIVERS
+
+config VIDEO_S5KA3DFX
+ tristate "S5KA3DFX Camera Sensor"
+ depends on I2C && VIDEO_V4L2
+ ---help---
+ This driver supports S5KA3DFX SoC camera module
+
+config VIDEO_S5K4ECGX
+ tristate "S5K4ECGX Camera Sensor"
+ depends on I2C && VIDEO_V4L2
+ ---help---
+ This driver supports S5K4ECGX SoC camera module
+
+config VIDEO_S5K4ECGX_DEBUG
+ bool "S5K4ECGX Camera Sensor Debugging"
+ depends on VIDEO_S5K4ECGX
+ default n
+ ---help---
+ Enable extra debug messages for S5K4ECGX camera driver
+
+config VIDEO_S5K4ECGX_V_1_0
+ bool "S5K4ECGX Camera Sensor Version 1.0 Support"
+ depends on VIDEO_S5K4ECGX
+ default y
+ ---help---
+ Enabled support for Rev 1.0 sensor
+
+config VIDEO_S5K4ECGX_V_1_1
+ bool "S5K4ECGX Camera Sensor Version 1.1 Support"
+ depends on VIDEO_S5K4ECGX
+ default y
+ ---help---
+ Enabled support for Rev 1.1 sensor
+
+source "drivers/media/video/samsung/Kconfig"
+
endif # VIDEO_CAPTURE_DRIVERS
menuconfig V4L_MEM2MEM_DRIVERS
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index f0fecd6..c4ce996b 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -85,6 +85,8 @@ obj-$(CONFIG_SOC_CAMERA_OV9740) += ov9740.o
obj-$(CONFIG_SOC_CAMERA_RJ54N1) += rj54n1cb0c.o
obj-$(CONFIG_SOC_CAMERA_TW9910) += tw9910.o
+obj-$(CONFIG_VIDEO_S5KA3DFX) += s5ka3dfx.o
+obj-$(CONFIG_VIDEO_S5K4ECGX) += s5k4ecgx.o
# And now the v4l2 drivers:
obj-$(CONFIG_VIDEO_BT848) += bt8xx/
@@ -174,6 +176,7 @@ obj-$(CONFIG_ARCH_DAVINCI) += davinci/
obj-$(CONFIG_VIDEO_SH_VOU) += sh_vou.o
obj-$(CONFIG_VIDEO_AU0828) += au0828/
+obj-$(CONFIG_VIDEO_SAMSUNG) += samsung/
obj-$(CONFIG_USB_VIDEO_CLASS) += uvc/
obj-$(CONFIG_VIDEO_SAA7164) += saa7164/
diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c
index c03eb29..9945aaf 100644
--- a/drivers/media/video/au0828/au0828-video.c
+++ b/drivers/media/video/au0828/au0828-video.c
@@ -1697,14 +1697,18 @@ static int vidioc_streamoff(struct file *file, void *priv,
(AUVI_INPUT(i).audio_setup)(dev, 0);
}
- videobuf_streamoff(&fh->vb_vidq);
- res_free(fh, AU0828_RESOURCE_VIDEO);
+ if (res_check(fh, AU0828_RESOURCE_VIDEO)) {
+ videobuf_streamoff(&fh->vb_vidq);
+ res_free(fh, AU0828_RESOURCE_VIDEO);
+ }
} else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
dev->vbi_timeout_running = 0;
del_timer_sync(&dev->vbi_timeout);
- videobuf_streamoff(&fh->vb_vbiq);
- res_free(fh, AU0828_RESOURCE_VBI);
+ if (res_check(fh, AU0828_RESOURCE_VBI)) {
+ videobuf_streamoff(&fh->vb_vbiq);
+ res_free(fh, AU0828_RESOURCE_VBI);
+ }
}
return 0;
diff --git a/drivers/media/video/gspca/spca506.c b/drivers/media/video/gspca/spca506.c
index 89fec4c..731cd16 100644
--- a/drivers/media/video/gspca/spca506.c
+++ b/drivers/media/video/gspca/spca506.c
@@ -685,7 +685,7 @@ static const struct sd_desc sd_desc = {
};
/* -- module initialisation -- */
-static const struct usb_device_id device_table[] __devinitconst = {
+static const struct usb_device_id device_table[] = {
{USB_DEVICE(0x06e1, 0xa190)},
/*fixme: may be IntelPCCameraPro BRIDGE_SPCA505
{USB_DEVICE(0x0733, 0x0430)}, */
diff --git a/drivers/media/video/s5k4ecgx.c b/drivers/media/video/s5k4ecgx.c
new file mode 100755
index 0000000..9d9d5b4
--- /dev/null
+++ b/drivers/media/video/s5k4ecgx.c
@@ -0,0 +1,2837 @@
+/* drivers/media/video/s5k4ecgx.c
+ *
+ * Driver for s5k4ecgx (5MP Camera) from SEC
+ *
+ * Copyright (C) 2010, SAMSUNG ELECTRONICS
+ *
+ * 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/i2c.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+#include <linux/vmalloc.h>
+#include <linux/completion.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <media/s5k4ecgx.h>
+#include <linux/videodev2_samsung.h>
+
+#ifdef CONFIG_VIDEO_S5K4ECGX_V_1_0
+#include "s5k4ecgx_regs_1_0.h"
+#define S5K4ECGX_VERSION_1_0 0x00
+#endif
+
+#ifdef CONFIG_VIDEO_S5K4ECGX_V_1_1
+#include "s5k4ecgx_regs_1_1.h"
+#define S5K4ECGX_VERSION_1_1 0x11
+#endif
+
+#define FORMAT_FLAGS_COMPRESSED 0x3
+#define SENSOR_JPEG_SNAPSHOT_MEMSIZE 0x410580
+
+#define DEFAULT_PIX_FMT V4L2_PIX_FMT_UYVY /* YUV422 */
+#define DEFAULT_MCLK 24000000
+#define POLL_TIME_MS 10
+#define CAPTURE_POLL_TIME_MS 1000
+
+/* maximum time for one frame at minimum fps (15fps) in normal mode */
+#define NORMAL_MODE_MAX_ONE_FRAME_DELAY_MS 67
+/* maximum time for one frame at minimum fps (4fps) in night mode */
+#define NIGHT_MODE_MAX_ONE_FRAME_DELAY_MS 250
+
+/* time to move lens to target position before last af mode register write */
+#define LENS_MOVE_TIME_MS 100
+
+/* level at or below which we need to enable flash when in auto mode */
+#define LOW_LIGHT_LEVEL 0x1D
+
+/* level at or below which we need to use low light capture mode */
+#define HIGH_LIGHT_LEVEL 0x80
+
+#define FIRST_AF_SEARCH_COUNT 80
+#define SECOND_AF_SEARCH_COUNT 80
+#define AE_STABLE_SEARCH_COUNT 4
+
+#define FIRST_SETTING_FOCUS_MODE_DELAY_MS 100
+#define SECOND_SETTING_FOCUS_MODE_DELAY_MS 200
+
+#ifdef CONFIG_VIDEO_S5K4ECGX_DEBUG
+enum {
+ S5K4ECGX_DEBUG_I2C = 1U << 0,
+ S5K4ECGX_DEBUG_I2C_BURSTS = 1U << 1,
+};
+static uint32_t s5k4ecgx_debug_mask = S5K4ECGX_DEBUG_I2C_BURSTS;
+module_param_named(debug_mask, s5k4ecgx_debug_mask, uint, S_IWUSR | S_IRUGO);
+
+#define s5k4ecgx_debug(mask, x...) \
+ do { \
+ if (s5k4ecgx_debug_mask & mask) \
+ pr_info(x); \
+ } while (0)
+#else
+
+#define s5k4ecgx_debug(mask, x...)
+
+#endif
+
+#define S5K4ECGX_VERSION_1_1 0x11
+
+/* result values returned to HAL */
+enum {
+ AUTO_FOCUS_FAILED,
+ AUTO_FOCUS_DONE,
+ AUTO_FOCUS_CANCELLED,
+};
+
+enum af_operation_status {
+ AF_NONE = 0,
+ AF_START,
+ AF_CANCEL,
+ AF_INITIAL,
+};
+
+enum s5k4ecgx_oprmode {
+ S5K4ECGX_OPRMODE_VIDEO = 0,
+ S5K4ECGX_OPRMODE_IMAGE = 1,
+};
+
+enum s5k4ecgx_preview_frame_size {
+ S5K4ECGX_PREVIEW_QCIF = 0, /* 176x144 */
+ S5K4ECGX_PREVIEW_CIF, /* 352x288 */
+ S5K4ECGX_PREVIEW_VGA, /* 640x480 */
+ S5K4ECGX_PREVIEW_D1, /* 720x480 */
+ S5K4ECGX_PREVIEW_WVGA, /* 800x480 */
+ S5K4ECGX_PREVIEW_SVGA, /* 800x600 */
+ S5K4ECGX_PREVIEW_WSVGA, /* 1024x600*/
+ S5K4ECGX_PREVIEW_MAX,
+};
+
+enum s5k4ecgx_capture_frame_size {
+ S5K4ECGX_CAPTURE_VGA = 0, /* 640x480 */
+ S5K4ECGX_CAPTURE_WVGA, /* 800x480 */
+ S5K4ECGX_CAPTURE_SVGA, /* 800x600 */
+ S5K4ECGX_CAPTURE_WSVGA, /* 1024x600 */
+ S5K4ECGX_CAPTURE_1MP, /* 1280x960 */
+ S5K4ECGX_CAPTURE_W1MP, /* 1600x960 */
+ S5K4ECGX_CAPTURE_2MP, /* UXGA - 1600x1200 */
+ S5K4ECGX_CAPTURE_W2MP, /* 35mm Academy Offset Standard 1.66 */
+ /* 2048x1232, 2.4MP */
+ S5K4ECGX_CAPTURE_3MP, /* QXGA - 2048x1536 */
+ S5K4ECGX_CAPTURE_W4MP, /* WQXGA - 2560x1536 */
+ S5K4ECGX_CAPTURE_5MP, /* 2560x1920 */
+ S5K4ECGX_CAPTURE_MAX,
+};
+
+struct s5k4ecgx_framesize {
+ u32 index;
+ u32 width;
+ u32 height;
+};
+
+static const struct s5k4ecgx_framesize s5k4ecgx_preview_framesize_list[] = {
+ { S5K4ECGX_PREVIEW_QCIF, 176, 144 },
+ { S5K4ECGX_PREVIEW_CIF, 352, 288 },
+ { S5K4ECGX_PREVIEW_VGA, 640, 480 },
+ { S5K4ECGX_PREVIEW_D1, 720, 480 },
+};
+
+static const struct s5k4ecgx_framesize s5k4ecgx_capture_framesize_list[] = {
+ { S5K4ECGX_CAPTURE_VGA, 640, 480 },
+ { S5K4ECGX_CAPTURE_1MP, 1280, 960 },
+ { S5K4ECGX_CAPTURE_2MP, 1600, 1200 },
+ { S5K4ECGX_CAPTURE_3MP, 2048, 1536 },
+ { S5K4ECGX_CAPTURE_5MP, 2560, 1920 },
+};
+
+struct s5k4ecgx_version {
+ u32 major;
+ u32 minor;
+};
+
+struct s5k4ecgx_date_info {
+ u32 year;
+ u32 month;
+ u32 date;
+};
+
+enum s5k4ecgx_runmode {
+ S5K4ECGX_RUNMODE_NOTREADY,
+ S5K4ECGX_RUNMODE_IDLE,
+ S5K4ECGX_RUNMODE_RUNNING,
+ S5K4ECGX_RUNMODE_CAPTURE,
+};
+
+struct s5k4ecgx_firmware {
+ u32 addr;
+ u32 size;
+};
+
+struct s5k4ecgx_jpeg_param {
+ u32 enable;
+ u32 quality;
+ u32 main_size; /* Main JPEG file size */
+ u32 thumb_size; /* Thumbnail file size */
+ u32 main_offset;
+ u32 thumb_offset;
+ u32 postview_offset;
+};
+
+struct s5k4ecgx_position {
+ int x;
+ int y;
+};
+
+struct gps_info_common {
+ u32 direction;
+ u32 dgree;
+ u32 minute;
+ u32 second;
+};
+
+struct s5k4ecgx_gps_info {
+ unsigned char gps_buf[8];
+ unsigned char altitude_buf[4];
+ int gps_timeStamp;
+};
+
+struct s5k4ecgx_regset {
+ u32 size;
+ u8 *data;
+};
+
+struct s5k4ecgx_regset_table {
+ const u32 *reg;
+ int array_size;
+};
+
+#define S5K4ECGX_REGSET(x, y) \
+ [(x)] = { \
+ .reg = (y), \
+ .array_size = ARRAY_SIZE((y)), \
+}
+
+#define S5K4ECGX_REGSET_TABLE(y) \
+ { \
+ .reg = (y), \
+ .array_size = ARRAY_SIZE((y)), \
+}
+
+struct s5k4ecgx_regs {
+ struct s5k4ecgx_regset_table ev[EV_MAX];
+ struct s5k4ecgx_regset_table metering[METERING_MAX];
+ struct s5k4ecgx_regset_table iso[ISO_MAX];
+ struct s5k4ecgx_regset_table effect[IMAGE_EFFECT_MAX];
+ struct s5k4ecgx_regset_table white_balance[WHITE_BALANCE_MAX];
+ struct s5k4ecgx_regset_table preview_size[S5K4ECGX_PREVIEW_MAX];
+ struct s5k4ecgx_regset_table capture_size[S5K4ECGX_CAPTURE_MAX];
+ struct s5k4ecgx_regset_table scene_mode[SCENE_MODE_MAX];
+ struct s5k4ecgx_regset_table saturation[SATURATION_MAX];
+ struct s5k4ecgx_regset_table contrast[CONTRAST_MAX];
+ struct s5k4ecgx_regset_table sharpness[SHARPNESS_MAX];
+ struct s5k4ecgx_regset_table fps[FRAME_RATE_MAX];
+ struct s5k4ecgx_regset_table preview_return;
+ struct s5k4ecgx_regset_table jpeg_quality_high;
+ struct s5k4ecgx_regset_table jpeg_quality_normal;
+ struct s5k4ecgx_regset_table jpeg_quality_low;
+ struct s5k4ecgx_regset_table flash_start;
+ struct s5k4ecgx_regset_table flash_end;
+ struct s5k4ecgx_regset_table af_assist_flash_start;
+ struct s5k4ecgx_regset_table af_assist_flash_end;
+ struct s5k4ecgx_regset_table af_low_light_mode_on;
+ struct s5k4ecgx_regset_table af_low_light_mode_off;
+ struct s5k4ecgx_regset_table ae_awb_lock_on;
+ struct s5k4ecgx_regset_table ae_awb_lock_off;
+ struct s5k4ecgx_regset_table low_cap_on;
+ struct s5k4ecgx_regset_table low_cap_off;
+ struct s5k4ecgx_regset_table wdr_on;
+ struct s5k4ecgx_regset_table wdr_off;
+ struct s5k4ecgx_regset_table face_detection_on;
+ struct s5k4ecgx_regset_table face_detection_off;
+ struct s5k4ecgx_regset_table capture_start;
+ struct s5k4ecgx_regset_table af_macro_mode_1;
+ struct s5k4ecgx_regset_table af_macro_mode_2;
+ struct s5k4ecgx_regset_table af_macro_mode_3;
+ struct s5k4ecgx_regset_table af_normal_mode_1;
+ struct s5k4ecgx_regset_table af_normal_mode_2;
+ struct s5k4ecgx_regset_table af_normal_mode_3;
+ struct s5k4ecgx_regset_table af_return_macro_position;
+ struct s5k4ecgx_regset_table single_af_start;
+ struct s5k4ecgx_regset_table single_af_off_1;
+ struct s5k4ecgx_regset_table single_af_off_2;
+ struct s5k4ecgx_regset_table dtp_start;
+ struct s5k4ecgx_regset_table dtp_stop;
+ struct s5k4ecgx_regset_table init_reg_1;
+ struct s5k4ecgx_regset_table init_reg_2;
+ struct s5k4ecgx_regset_table flash_init;
+ struct s5k4ecgx_regset_table reset_crop;
+ struct s5k4ecgx_regset_table get_ae_stable_status;
+ struct s5k4ecgx_regset_table get_light_level;
+ struct s5k4ecgx_regset_table get_1st_af_search_status;
+ struct s5k4ecgx_regset_table get_2nd_af_search_status;
+ struct s5k4ecgx_regset_table get_capture_status;
+ struct s5k4ecgx_regset_table get_esd_status;
+ struct s5k4ecgx_regset_table get_iso;
+ struct s5k4ecgx_regset_table get_shutterspeed;
+};
+
+#ifdef CONFIG_VIDEO_S5K4ECGX_V_1_0
+static const struct s5k4ecgx_regs regs_for_fw_version_1_0 = {
+ .ev = {
+ S5K4ECGX_REGSET(EV_MINUS_4, s5k4ecgx_EV_Minus_4_v1),
+ S5K4ECGX_REGSET(EV_MINUS_3, s5k4ecgx_EV_Minus_3_v1),
+ S5K4ECGX_REGSET(EV_MINUS_2, s5k4ecgx_EV_Minus_2_v1),
+ S5K4ECGX_REGSET(EV_MINUS_1, s5k4ecgx_EV_Minus_1_v1),
+ S5K4ECGX_REGSET(EV_DEFAULT, s5k4ecgx_EV_Default_v1),
+ S5K4ECGX_REGSET(EV_PLUS_1, s5k4ecgx_EV_Plus_1_v1),
+ S5K4ECGX_REGSET(EV_PLUS_2, s5k4ecgx_EV_Plus_2_v1),
+ S5K4ECGX_REGSET(EV_PLUS_3, s5k4ecgx_EV_Plus_3_v1),
+ S5K4ECGX_REGSET(EV_PLUS_4, s5k4ecgx_EV_Plus_4_v1),
+ },
+ .metering = {
+ S5K4ECGX_REGSET(METERING_MATRIX, s5k4ecgx_Metering_Matrix_v1),
+ S5K4ECGX_REGSET(METERING_CENTER, s5k4ecgx_Metering_Center_v1),
+ S5K4ECGX_REGSET(METERING_SPOT, s5k4ecgx_Metering_Spot_v1),
+ },
+ .iso = {
+ S5K4ECGX_REGSET(ISO_AUTO, s5k4ecgx_ISO_Auto_v1),
+ S5K4ECGX_REGSET(ISO_50, s5k4ecgx_ISO_100_v1), /* use 100 */
+ S5K4ECGX_REGSET(ISO_100, s5k4ecgx_ISO_100_v1),
+ S5K4ECGX_REGSET(ISO_200, s5k4ecgx_ISO_200_v1),
+ S5K4ECGX_REGSET(ISO_400, s5k4ecgx_ISO_400_v1),
+ S5K4ECGX_REGSET(ISO_800, s5k4ecgx_ISO_400_v1), /* use 400 */
+ S5K4ECGX_REGSET(ISO_1600, s5k4ecgx_ISO_400_v1), /* use 400 */
+ S5K4ECGX_REGSET(ISO_SPORTS, s5k4ecgx_ISO_Auto_v1),/* use auto */
+ S5K4ECGX_REGSET(ISO_NIGHT, s5k4ecgx_ISO_Auto_v1), /* use auto */
+ S5K4ECGX_REGSET(ISO_MOVIE, s5k4ecgx_ISO_Auto_v1), /* use auto */
+ },
+ .effect = {
+ S5K4ECGX_REGSET(IMAGE_EFFECT_NONE, s5k4ecgx_Effect_Normal_v1),
+ S5K4ECGX_REGSET(IMAGE_EFFECT_BNW,
+ s5k4ecgx_Effect_Black_White_v1),
+ S5K4ECGX_REGSET(IMAGE_EFFECT_SEPIA, s5k4ecgx_Effect_Sepia_v1),
+ S5K4ECGX_REGSET(IMAGE_EFFECT_NEGATIVE,
+ s5k4ecgx_Effect_Negative_v1),
+ },
+ .white_balance = {
+ S5K4ECGX_REGSET(WHITE_BALANCE_AUTO, s5k4ecgx_WB_Auto_v1),
+ S5K4ECGX_REGSET(WHITE_BALANCE_SUNNY, s5k4ecgx_WB_Sunny_v1),
+ S5K4ECGX_REGSET(WHITE_BALANCE_CLOUDY, s5k4ecgx_WB_Cloudy_v1),
+ S5K4ECGX_REGSET(WHITE_BALANCE_TUNGSTEN,
+ s5k4ecgx_WB_Tungsten_v1),
+ S5K4ECGX_REGSET(WHITE_BALANCE_FLUORESCENT,
+ s5k4ecgx_WB_Fluorescent_v1),
+ },
+ .preview_size = {
+ S5K4ECGX_REGSET(S5K4ECGX_PREVIEW_QCIF, s5k4ecgx_176_Preview_v1),
+ S5K4ECGX_REGSET(S5K4ECGX_PREVIEW_CIF, s5k4ecgx_352_Preview_v1),
+ S5K4ECGX_REGSET(S5K4ECGX_PREVIEW_VGA, s5k4ecgx_640_Preview_v1),
+ S5K4ECGX_REGSET(S5K4ECGX_PREVIEW_D1, s5k4ecgx_720_Preview_v1),
+ },
+ .capture_size = {
+ S5K4ECGX_REGSET(S5K4ECGX_CAPTURE_VGA, s5k4ecgx_VGA_Capture_v1),
+ S5K4ECGX_REGSET(S5K4ECGX_CAPTURE_1MP, s5k4ecgx_1M_Capture_v1),
+ S5K4ECGX_REGSET(S5K4ECGX_CAPTURE_2MP, s5k4ecgx_2M_Capture_v1),
+ S5K4ECGX_REGSET(S5K4ECGX_CAPTURE_3MP, s5k4ecgx_3M_Capture_v1),
+ S5K4ECGX_REGSET(S5K4ECGX_CAPTURE_5MP, s5k4ecgx_5M_Capture_v1),
+ },
+ .scene_mode = {
+ S5K4ECGX_REGSET(SCENE_MODE_NONE, s5k4ecgx_Scene_Default_v1),
+ S5K4ECGX_REGSET(SCENE_MODE_PORTRAIT,
+ s5k4ecgx_Scene_Portrait_v1),
+ S5K4ECGX_REGSET(SCENE_MODE_NIGHTSHOT,
+ s5k4ecgx_Scene_Nightshot_v1),
+ S5K4ECGX_REGSET(SCENE_MODE_LANDSCAPE,
+ s5k4ecgx_Scene_Landscape_v1),
+ S5K4ECGX_REGSET(SCENE_MODE_SPORTS, s5k4ecgx_Scene_Sports_v1),
+ S5K4ECGX_REGSET(SCENE_MODE_PARTY_INDOOR,
+ s5k4ecgx_Scene_Party_Indoor_v1),
+ S5K4ECGX_REGSET(SCENE_MODE_BEACH_SNOW,
+ s5k4ecgx_Scene_Beach_Snow_v1),
+ S5K4ECGX_REGSET(SCENE_MODE_SUNSET, s5k4ecgx_Scene_Sunset_v1),
+ S5K4ECGX_REGSET(SCENE_MODE_FIREWORKS,
+ s5k4ecgx_Scene_Fireworks_v1),
+ S5K4ECGX_REGSET(SCENE_MODE_CANDLE_LIGHT,
+ s5k4ecgx_Scene_Candle_Light_v1),
+ },
+ .saturation = {
+ S5K4ECGX_REGSET(SATURATION_MINUS_2,
+ s5k4ecgx_Saturation_Minus_2_v1),
+ S5K4ECGX_REGSET(SATURATION_MINUS_1,
+ s5k4ecgx_Saturation_Minus_1_v1),
+ S5K4ECGX_REGSET(SATURATION_DEFAULT,
+ s5k4ecgx_Saturation_Default_v1),
+ S5K4ECGX_REGSET(SATURATION_PLUS_1,
+ s5k4ecgx_Saturation_Plus_1_v1),
+ S5K4ECGX_REGSET(SATURATION_PLUS_2,
+ s5k4ecgx_Saturation_Plus_2_v1),
+ },
+ .contrast = {
+ S5K4ECGX_REGSET(CONTRAST_MINUS_2, s5k4ecgx_Contrast_Minus_2_v1),
+ S5K4ECGX_REGSET(CONTRAST_MINUS_1, s5k4ecgx_Contrast_Minus_1_v1),
+ S5K4ECGX_REGSET(CONTRAST_DEFAULT, s5k4ecgx_Contrast_Default_v1),
+ S5K4ECGX_REGSET(CONTRAST_PLUS_1, s5k4ecgx_Contrast_Plus_1_v1),
+ S5K4ECGX_REGSET(CONTRAST_PLUS_2, s5k4ecgx_Contrast_Plus_2_v1),
+ },
+ .sharpness = {
+ S5K4ECGX_REGSET(SHARPNESS_MINUS_2,
+ s5k4ecgx_Sharpness_Minus_2_v1),
+ S5K4ECGX_REGSET(SHARPNESS_MINUS_1,
+ s5k4ecgx_Sharpness_Minus_1_v1),
+ S5K4ECGX_REGSET(SHARPNESS_DEFAULT,
+ s5k4ecgx_Sharpness_Default_v1),
+ S5K4ECGX_REGSET(SHARPNESS_PLUS_1, s5k4ecgx_Sharpness_Plus_1_v1),
+ S5K4ECGX_REGSET(SHARPNESS_PLUS_2, s5k4ecgx_Sharpness_Plus_2_v1),
+ },
+ .preview_return = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Preview_Return_v1),
+ .jpeg_quality_high =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_Jpeg_Quality_High_v1),
+ .jpeg_quality_normal =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_Jpeg_Quality_Normal_v1),
+ .jpeg_quality_low = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Jpeg_Quality_Low_v1),
+ .flash_start = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Flash_Start_v1),
+ .flash_end = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Flash_End_v1),
+ .af_assist_flash_start =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_Pre_Flash_Start_v1),
+ .af_assist_flash_end =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_Pre_Flash_End_v1),
+ .af_low_light_mode_on =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Low_Light_Mode_On_v1),
+ .af_low_light_mode_off =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Low_Light_Mode_Off_v1),
+ .ae_awb_lock_on =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_AE_AWB_Lock_On_v1),
+ .ae_awb_lock_off =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_AE_AWB_Lock_Off_v1),
+ .low_cap_on = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Low_Cap_On_v1),
+ .low_cap_off = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Low_Cap_Off_v1),
+ .wdr_on = S5K4ECGX_REGSET_TABLE(s5k4ecgx_WDR_on_v1),
+ .wdr_off = S5K4ECGX_REGSET_TABLE(s5k4ecgx_WDR_off_v1),
+ .face_detection_on =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_Face_Detection_On_v1),
+ .face_detection_off =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_Face_Detection_Off_v1),
+ .capture_start = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Capture_Start_v1),
+ .af_macro_mode_1 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Macro_mode_1_v1),
+ .af_macro_mode_2 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Macro_mode_2_v1),
+ .af_macro_mode_3 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Macro_mode_3_v1),
+ .af_normal_mode_1 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Normal_mode_1_v1),
+ .af_normal_mode_2 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Normal_mode_2_v1),
+ .af_normal_mode_3 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Normal_mode_3_v1),
+ .af_return_macro_position =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Return_Macro_pos_v1),
+ .single_af_start = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Single_AF_Start_v1),
+ .single_af_off_1 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Single_AF_Off_1_v1),
+ .single_af_off_2 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Single_AF_Off_2_v1),
+ .dtp_start = S5K4ECGX_REGSET_TABLE(s5k4ecgx_DTP_init_v1),
+ .dtp_stop = S5K4ECGX_REGSET_TABLE(s5k4ecgx_DTP_stop_v1),
+ .init_reg_1 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_init_reg1_v1),
+ .init_reg_2 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_init_reg2_v1),
+ .flash_init = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Flash_init_v1),
+ .reset_crop = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Reset_Crop_v1),
+ .get_ae_stable_status =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_Get_AE_Stable_Status_v1),
+ .get_light_level = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Get_Light_Level_v1),
+ .get_1st_af_search_status =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_get_1st_af_search_status_v1),
+ .get_2nd_af_search_status =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_get_2nd_af_search_status_v1),
+ .get_capture_status =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_get_capture_status_v1),
+ .get_esd_status = S5K4ECGX_REGSET_TABLE(s5k4ecgx_get_esd_status_v1),
+ .get_iso = S5K4ECGX_REGSET_TABLE(s5k4ecgx_get_iso_reg_v1),
+ .get_shutterspeed =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_get_shutterspeed_reg_v1),
+};
+#endif
+
+#ifdef CONFIG_VIDEO_S5K4ECGX_V_1_1
+static const struct s5k4ecgx_regs regs_for_fw_version_1_1 = {
+ .ev = {
+ S5K4ECGX_REGSET(EV_MINUS_4, s5k4ecgx_EV_Minus_4),
+ S5K4ECGX_REGSET(EV_MINUS_3, s5k4ecgx_EV_Minus_3),
+ S5K4ECGX_REGSET(EV_MINUS_2, s5k4ecgx_EV_Minus_2),
+ S5K4ECGX_REGSET(EV_MINUS_1, s5k4ecgx_EV_Minus_1),
+ S5K4ECGX_REGSET(EV_DEFAULT, s5k4ecgx_EV_Default),
+ S5K4ECGX_REGSET(EV_PLUS_1, s5k4ecgx_EV_Plus_1),
+ S5K4ECGX_REGSET(EV_PLUS_2, s5k4ecgx_EV_Plus_2),
+ S5K4ECGX_REGSET(EV_PLUS_3, s5k4ecgx_EV_Plus_3),
+ S5K4ECGX_REGSET(EV_PLUS_4, s5k4ecgx_EV_Plus_4),
+ },
+ .metering = {
+ S5K4ECGX_REGSET(METERING_MATRIX, s5k4ecgx_Metering_Matrix),
+ S5K4ECGX_REGSET(METERING_CENTER, s5k4ecgx_Metering_Center),
+ S5K4ECGX_REGSET(METERING_SPOT, s5k4ecgx_Metering_Spot),
+ },
+ .iso = {
+ S5K4ECGX_REGSET(ISO_AUTO, s5k4ecgx_ISO_Auto),
+ S5K4ECGX_REGSET(ISO_50, s5k4ecgx_ISO_100), /* map to 100 */
+ S5K4ECGX_REGSET(ISO_100, s5k4ecgx_ISO_100),
+ S5K4ECGX_REGSET(ISO_200, s5k4ecgx_ISO_200),
+ S5K4ECGX_REGSET(ISO_400, s5k4ecgx_ISO_400),
+ S5K4ECGX_REGSET(ISO_800, s5k4ecgx_ISO_400), /* map to 400 */
+ S5K4ECGX_REGSET(ISO_1600, s5k4ecgx_ISO_400), /* map to 400 */
+ S5K4ECGX_REGSET(ISO_SPORTS, s5k4ecgx_ISO_Auto),/* map to auto */
+ S5K4ECGX_REGSET(ISO_NIGHT, s5k4ecgx_ISO_Auto), /* map to auto */
+ S5K4ECGX_REGSET(ISO_MOVIE, s5k4ecgx_ISO_Auto), /* map to auto */
+ },
+ .effect = {
+ S5K4ECGX_REGSET(IMAGE_EFFECT_NONE, s5k4ecgx_Effect_Normal),
+ S5K4ECGX_REGSET(IMAGE_EFFECT_BNW, s5k4ecgx_Effect_Black_White),
+ S5K4ECGX_REGSET(IMAGE_EFFECT_SEPIA, s5k4ecgx_Effect_Sepia),
+ S5K4ECGX_REGSET(IMAGE_EFFECT_NEGATIVE,
+ s5k4ecgx_Effect_Negative),
+ },
+ .white_balance = {
+ S5K4ECGX_REGSET(WHITE_BALANCE_AUTO, s5k4ecgx_WB_Auto),
+ S5K4ECGX_REGSET(WHITE_BALANCE_SUNNY, s5k4ecgx_WB_Sunny),
+ S5K4ECGX_REGSET(WHITE_BALANCE_CLOUDY, s5k4ecgx_WB_Cloudy),
+ S5K4ECGX_REGSET(WHITE_BALANCE_TUNGSTEN, s5k4ecgx_WB_Tungsten),
+ S5K4ECGX_REGSET(WHITE_BALANCE_FLUORESCENT,
+ s5k4ecgx_WB_Fluorescent),
+ },
+ .preview_size = {
+ S5K4ECGX_REGSET(S5K4ECGX_PREVIEW_QCIF, s5k4ecgx_176_Preview),
+ S5K4ECGX_REGSET(S5K4ECGX_PREVIEW_CIF, s5k4ecgx_352_Preview),
+ S5K4ECGX_REGSET(S5K4ECGX_PREVIEW_VGA, s5k4ecgx_640_Preview),
+ S5K4ECGX_REGSET(S5K4ECGX_PREVIEW_D1, s5k4ecgx_720_Preview),
+ },
+ .capture_size = {
+ S5K4ECGX_REGSET(S5K4ECGX_CAPTURE_VGA, s5k4ecgx_VGA_Capture),
+ S5K4ECGX_REGSET(S5K4ECGX_CAPTURE_1MP, s5k4ecgx_1M_Capture),
+ S5K4ECGX_REGSET(S5K4ECGX_CAPTURE_2MP, s5k4ecgx_2M_Capture),
+ S5K4ECGX_REGSET(S5K4ECGX_CAPTURE_3MP, s5k4ecgx_3M_Capture),
+ S5K4ECGX_REGSET(S5K4ECGX_CAPTURE_5MP, s5k4ecgx_5M_Capture),
+ },
+ .scene_mode = {
+ S5K4ECGX_REGSET(SCENE_MODE_NONE, s5k4ecgx_Scene_Default),
+ S5K4ECGX_REGSET(SCENE_MODE_PORTRAIT, s5k4ecgx_Scene_Portrait),
+ S5K4ECGX_REGSET(SCENE_MODE_NIGHTSHOT, s5k4ecgx_Scene_Nightshot),
+ S5K4ECGX_REGSET(SCENE_MODE_LANDSCAPE, s5k4ecgx_Scene_Landscape),
+ S5K4ECGX_REGSET(SCENE_MODE_SPORTS, s5k4ecgx_Scene_Sports),
+ S5K4ECGX_REGSET(SCENE_MODE_PARTY_INDOOR,
+ s5k4ecgx_Scene_Party_Indoor),
+ S5K4ECGX_REGSET(SCENE_MODE_BEACH_SNOW,
+ s5k4ecgx_Scene_Beach_Snow),
+ S5K4ECGX_REGSET(SCENE_MODE_SUNSET, s5k4ecgx_Scene_Sunset),
+ S5K4ECGX_REGSET(SCENE_MODE_FIREWORKS, s5k4ecgx_Scene_Fireworks),
+ S5K4ECGX_REGSET(SCENE_MODE_CANDLE_LIGHT,
+ s5k4ecgx_Scene_Candle_Light),
+ },
+ .saturation = {
+ S5K4ECGX_REGSET(SATURATION_MINUS_2,
+ s5k4ecgx_Saturation_Minus_2),
+ S5K4ECGX_REGSET(SATURATION_MINUS_1,
+ s5k4ecgx_Saturation_Minus_1),
+ S5K4ECGX_REGSET(SATURATION_DEFAULT,
+ s5k4ecgx_Saturation_Default),
+ S5K4ECGX_REGSET(SATURATION_PLUS_1, s5k4ecgx_Saturation_Plus_1),
+ S5K4ECGX_REGSET(SATURATION_PLUS_2, s5k4ecgx_Saturation_Plus_2),
+ },
+ .contrast = {
+ S5K4ECGX_REGSET(CONTRAST_MINUS_2, s5k4ecgx_Contrast_Minus_2),
+ S5K4ECGX_REGSET(CONTRAST_MINUS_1, s5k4ecgx_Contrast_Minus_1),
+ S5K4ECGX_REGSET(CONTRAST_DEFAULT, s5k4ecgx_Contrast_Default),
+ S5K4ECGX_REGSET(CONTRAST_PLUS_1, s5k4ecgx_Contrast_Plus_1),
+ S5K4ECGX_REGSET(CONTRAST_PLUS_2, s5k4ecgx_Contrast_Plus_2),
+ },
+ .sharpness = {
+ S5K4ECGX_REGSET(SHARPNESS_MINUS_2, s5k4ecgx_Sharpness_Minus_2),
+ S5K4ECGX_REGSET(SHARPNESS_MINUS_1, s5k4ecgx_Sharpness_Minus_1),
+ S5K4ECGX_REGSET(SHARPNESS_DEFAULT, s5k4ecgx_Sharpness_Default),
+ S5K4ECGX_REGSET(SHARPNESS_PLUS_1, s5k4ecgx_Sharpness_Plus_1),
+ S5K4ECGX_REGSET(SHARPNESS_PLUS_2, s5k4ecgx_Sharpness_Plus_2),
+ },
+ .fps = {
+ S5K4ECGX_REGSET(FRAME_RATE_AUTO, s5k4ecgx_FPS_Auto),
+ S5K4ECGX_REGSET(FRAME_RATE_7, s5k4ecgx_FPS_7),
+ S5K4ECGX_REGSET(FRAME_RATE_15, s5k4ecgx_FPS_15),
+ S5K4ECGX_REGSET(FRAME_RATE_30, s5k4ecgx_FPS_30),
+ },
+ .preview_return = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Preview_Return),
+ .jpeg_quality_high = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Jpeg_Quality_High),
+ .jpeg_quality_normal =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_Jpeg_Quality_Normal),
+ .jpeg_quality_low = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Jpeg_Quality_Low),
+ .flash_start = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Flash_Start),
+ .flash_end = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Flash_End),
+ .af_assist_flash_start =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_Pre_Flash_Start),
+ .af_assist_flash_end =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_Pre_Flash_End),
+ .af_low_light_mode_on =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Low_Light_Mode_On),
+ .af_low_light_mode_off =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Low_Light_Mode_Off),
+ .ae_awb_lock_on =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_AE_AWB_Lock_On),
+ .ae_awb_lock_off =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_AE_AWB_Lock_Off),
+ .low_cap_on = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Low_Cap_On),
+ .low_cap_off = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Low_Cap_Off),
+ .wdr_on = S5K4ECGX_REGSET_TABLE(s5k4ecgx_WDR_on),
+ .wdr_off = S5K4ECGX_REGSET_TABLE(s5k4ecgx_WDR_off),
+ .face_detection_on = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Face_Detection_On),
+ .face_detection_off =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_Face_Detection_Off),
+ .capture_start = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Capture_Start),
+ .af_macro_mode_1 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Macro_mode_1),
+ .af_macro_mode_2 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Macro_mode_2),
+ .af_macro_mode_3 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Macro_mode_3),
+ .af_normal_mode_1 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Normal_mode_1),
+ .af_normal_mode_2 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Normal_mode_2),
+ .af_normal_mode_3 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Normal_mode_3),
+ .af_return_macro_position =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Return_Macro_pos),
+ .single_af_start = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Single_AF_Start),
+ .single_af_off_1 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Single_AF_Off_1),
+ .single_af_off_2 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Single_AF_Off_2),
+ .dtp_start = S5K4ECGX_REGSET_TABLE(s5k4ecgx_DTP_init),
+ .dtp_stop = S5K4ECGX_REGSET_TABLE(s5k4ecgx_DTP_stop),
+ .init_reg_1 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_init_reg1),
+ .init_reg_2 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_init_reg2),
+ .flash_init = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Flash_init),
+ .reset_crop = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Reset_Crop),
+ .get_ae_stable_status =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_Get_AE_Stable_Status),
+ .get_light_level = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Get_Light_Level),
+ .get_1st_af_search_status =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_get_1st_af_search_status),
+ .get_2nd_af_search_status =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_get_2nd_af_search_status),
+ .get_capture_status =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_get_capture_status),
+ .get_esd_status = S5K4ECGX_REGSET_TABLE(s5k4ecgx_get_esd_status),
+ .get_iso = S5K4ECGX_REGSET_TABLE(s5k4ecgx_get_iso_reg),
+ .get_shutterspeed =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_get_shutterspeed_reg),
+};
+#endif
+
+struct s5k4ecgx_state {
+ struct s5k4ecgx_platform_data *pdata;
+ struct v4l2_subdev sd;
+ struct v4l2_pix_format pix;
+ struct v4l2_fract timeperframe;
+ struct s5k4ecgx_jpeg_param jpeg;
+ struct s5k4ecgx_version fw;
+ struct s5k4ecgx_version prm;
+ struct s5k4ecgx_date_info dateinfo;
+ struct s5k4ecgx_position position;
+ struct v4l2_streamparm strm;
+ struct s5k4ecgx_gps_info gps_info;
+ struct mutex ctrl_lock;
+ enum s5k4ecgx_runmode runmode;
+ enum s5k4ecgx_oprmode oprmode;
+ enum af_operation_status af_status;
+ int preview_framesize_index;
+ int capture_framesize_index;
+ int sensor_version;
+ int freq; /* MCLK in Hz */
+ int check_dataline;
+ int check_previewdata;
+ bool flash_on;
+ bool torch_on;
+ bool sensor_af_in_low_light_mode;
+ bool flash_state_on_previous_capture;
+ bool initialized;
+ bool restore_preview_size_needed;
+ int one_frame_delay_ms;
+ const struct s5k4ecgx_regs *regs;
+};
+
+static const struct v4l2_mbus_framefmt capture_fmts[] = {
+ {
+ .code = V4L2_MBUS_FMT_FIXED,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ },
+};
+
+/**
+ * s5k4ecgx_i2c_read_twobyte: Read 2 bytes from sensor
+ */
+static int s5k4ecgx_i2c_read_twobyte(struct i2c_client *client,
+ u16 subaddr, u16 *data)
+{
+ int err;
+ unsigned char buf[2];
+ struct i2c_msg msg[2];
+
+ cpu_to_be16s(&subaddr);
+
+ msg[0].addr = client->addr;
+ msg[0].flags = 0;
+ msg[0].len = 2;
+ msg[0].buf = (u8 *)&subaddr;
+
+ msg[1].addr = client->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = 2;
+ msg[1].buf = buf;
+
+ err = i2c_transfer(client->adapter, msg, 2);
+ if (unlikely(err != 2)) {
+ dev_err(&client->dev,
+ "%s: register read fail\n", __func__);
+ return -EIO;
+ }
+
+ *data = ((buf[0] << 8) | buf[1]);
+
+ return 0;
+}
+
+/**
+ * s5k4ecgx_i2c_write_twobyte: Write (I2C) multiple bytes to the camera sensor
+ * @client: pointer to i2c_client
+ * @cmd: command register
+ * @w_data: data to be written
+ * @w_len: length of data to be written
+ *
+ * Returns 0 on success, <0 on error
+ */
+static int s5k4ecgx_i2c_write_twobyte(struct i2c_client *client,
+ u16 addr, u16 w_data)
+{
+ int retry_count = 5;
+ unsigned char buf[4];
+ struct i2c_msg msg = {client->addr, 0, 4, buf};
+ int ret = 0;
+
+ buf[0] = addr >> 8;
+ buf[1] = addr;
+ buf[2] = w_data >> 8;
+ buf[3] = w_data & 0xff;
+
+ s5k4ecgx_debug(S5K4ECGX_DEBUG_I2C, "%s : W(0x%02X%02X%02X%02X)\n",
+ __func__, buf[0], buf[1], buf[2], buf[3]);
+
+ do {
+ ret = i2c_transfer(client->adapter, &msg, 1);
+ if (likely(ret == 1))
+ break;
+ msleep(POLL_TIME_MS);
+ dev_err(&client->dev, "%s: I2C err %d, retry %d.\n",
+ __func__, ret, retry_count);
+ } while (retry_count-- > 0);
+ if (ret != 1) {
+ dev_err(&client->dev, "%s: I2C is not working.\n", __func__);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int s5k4ecgx_write_regs(struct v4l2_subdev *sd, const u32 regs[],
+ int size)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ int i, err;
+
+ for (i = 0; i < size; i++) {
+ err = s5k4ecgx_i2c_write_twobyte(client,
+ (regs[i] >> 16), regs[i]);
+ if (unlikely(err != 0)) {
+ dev_err(&client->dev,
+ "%s: register write failed\n", __func__);
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+static int s5k4ecgx_set_from_table(struct v4l2_subdev *sd,
+ const char *setting_name,
+ const struct s5k4ecgx_regset_table *table,
+ int table_size, int index)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ dev_dbg(&client->dev, "%s: set %s index %d\n",
+ __func__, setting_name, index);
+ if ((index < 0) || (index >= table_size)) {
+ dev_err(&client->dev,
+ "%s: index(%d) out of range[0:%d] for table for %s\n",
+ __func__, index, table_size, setting_name);
+ return -EINVAL;
+ }
+ table += index;
+ if (table->reg == NULL)
+ return -EINVAL;
+ return s5k4ecgx_write_regs(sd, table->reg, table->array_size);
+}
+
+static int s5k4ecgx_set_parameter(struct v4l2_subdev *sd,
+ int *current_value_ptr,
+ int new_value,
+ const char *setting_name,
+ const struct s5k4ecgx_regset_table *table,
+ int table_size)
+{
+ int err;
+
+ if (*current_value_ptr == new_value)
+ return 0;
+
+ err = s5k4ecgx_set_from_table(sd, setting_name, table,
+ table_size, new_value);
+
+ if (!err)
+ *current_value_ptr = new_value;
+ return err;
+}
+
+static int s5k4ecgx_set_preview_stop(struct v4l2_subdev *sd)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+
+ if (state->runmode == S5K4ECGX_RUNMODE_RUNNING)
+ state->runmode = S5K4ECGX_RUNMODE_IDLE;
+
+ dev_dbg(&client->dev, "%s:\n", __func__);
+
+ return 0;
+}
+
+static int s5k4ecgx_set_preview_start(struct v4l2_subdev *sd)
+{
+ int err;
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ bool set_size = true;
+
+ dev_dbg(&client->dev, "%s: runmode = %d\n",
+ __func__, state->runmode);
+
+ if (!state->pix.width || !state->pix.height ||
+ !state->strm.parm.capture.timeperframe.denominator)
+ return -EINVAL;
+
+ if (state->runmode == S5K4ECGX_RUNMODE_CAPTURE) {
+ dev_dbg(&client->dev, "%s: sending Preview_Return cmd\n",
+ __func__);
+ err = s5k4ecgx_set_from_table(sd, "preview return",
+ &state->regs->preview_return, 1, 0);
+ if (err < 0) {
+ dev_err(&client->dev,
+ "%s: failed: s5k4ecgx_Preview_Return\n",
+ __func__);
+ return -EIO;
+ }
+ set_size = state->restore_preview_size_needed;
+ }
+
+ if (set_size) {
+ err = s5k4ecgx_set_from_table(sd, "preview_size",
+ state->regs->preview_size,
+ ARRAY_SIZE(state->regs->preview_size),
+ state->preview_framesize_index);
+ if (err < 0) {
+ dev_err(&client->dev,
+ "%s: failed: Could not set preview size\n",
+ __func__);
+ return -EIO;
+ }
+ }
+
+ dev_dbg(&client->dev, "%s: runmode now RUNNING\n", __func__);
+ state->runmode = S5K4ECGX_RUNMODE_RUNNING;
+
+ return 0;
+}
+
+static int s5k4ecgx_set_capture_size(struct v4l2_subdev *sd)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ int err;
+
+ dev_dbg(&client->dev, "%s: index:%d\n", __func__,
+ state->capture_framesize_index);
+
+ err = s5k4ecgx_set_from_table(sd, "capture_size",
+ state->regs->capture_size,
+ ARRAY_SIZE(state->regs->capture_size),
+ state->capture_framesize_index);
+ if (err < 0) {
+ dev_err(&client->dev,
+ "%s: failed: i2c_write for capture_size index %d\n",
+ __func__, state->capture_framesize_index);
+ }
+ state->runmode = S5K4ECGX_RUNMODE_CAPTURE;
+
+ return err;
+}
+
+static int s5k4ecgx_set_jpeg_quality(struct v4l2_subdev *sd)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+
+ dev_dbg(&client->dev,
+ "%s: jpeg.quality %d\n", __func__, state->jpeg.quality);
+ if (state->jpeg.quality < 0)
+ state->jpeg.quality = 0;
+ if (state->jpeg.quality > 100)
+ state->jpeg.quality = 100;
+
+ switch (state->jpeg.quality) {
+ case 90 ... 100:
+ dev_dbg(&client->dev,
+ "%s: setting to high jpeg quality\n", __func__);
+ return s5k4ecgx_set_from_table(sd, "jpeg quality high",
+ &state->regs->jpeg_quality_high, 1, 0);
+ case 80 ... 89:
+ dev_dbg(&client->dev,
+ "%s: setting to normal jpeg quality\n", __func__);
+ return s5k4ecgx_set_from_table(sd, "jpeg quality normal",
+ &state->regs->jpeg_quality_normal, 1, 0);
+ default:
+ dev_dbg(&client->dev,
+ "%s: setting to low jpeg quality\n", __func__);
+ return s5k4ecgx_set_from_table(sd, "jpeg quality low",
+ &state->regs->jpeg_quality_low, 1, 0);
+ }
+}
+
+static u16 s5k4ecgx_get_light_level(struct v4l2_subdev *sd)
+{
+ int err;
+ u16 read_value = 0;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+
+ err = s5k4ecgx_set_from_table(sd, "get light level",
+ &state->regs->get_light_level, 1, 0);
+ if (err) {
+ dev_err(&client->dev,
+ "%s: write cmd failed, returning 0\n", __func__);
+ goto out;
+ }
+ err = s5k4ecgx_i2c_read_twobyte(client, 0x0F12, &read_value);
+ if (err) {
+ dev_err(&client->dev,
+ "%s: read cmd failed, returning 0\n", __func__);
+ goto out;
+ }
+
+ dev_dbg(&client->dev, "%s: read_value = %d (0x%X)\n",
+ __func__, read_value, read_value);
+
+out:
+ /* restore write mode */
+ s5k4ecgx_i2c_write_twobyte(client, 0x0028, 0x7000);
+ return read_value;
+}
+
+static int s5k4ecgx_start_capture(struct v4l2_subdev *sd)
+{
+ int err;
+ u16 read_value;
+ u16 light_level;
+ int poll_time_ms;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ struct sec_cam_parm *parms =
+ (struct sec_cam_parm *)&state->strm.parm.raw_data;
+ struct s5k4ecgx_platform_data *pdata = client->dev.platform_data;
+
+ /* reset cropping if our current preview is not 640x480,
+ * otherwise the capture will be wrong because of the cropping
+ */
+ if (state->preview_framesize_index != S5K4ECGX_PREVIEW_VGA) {
+ int err = s5k4ecgx_set_from_table(sd, "reset crop",
+ &state->regs->reset_crop, 1, 0);
+ if (err < 0) {
+ dev_err(&client->dev,
+ "%s: failed: Could not set preview size\n",
+ __func__);
+ return -EIO;
+ }
+ state->restore_preview_size_needed = true;
+ } else
+ state->restore_preview_size_needed = false;
+
+ msleep(50);
+ light_level = s5k4ecgx_get_light_level(sd);
+
+ dev_dbg(&client->dev, "%s: light_level = %d\n", __func__,
+ light_level);
+
+ state->flash_state_on_previous_capture = false;
+ if (parms->scene_mode != SCENE_MODE_NIGHTSHOT) {
+ switch (parms->flash_mode) {
+ case FLASH_MODE_AUTO:
+ if (light_level > LOW_LIGHT_LEVEL) {
+ /* light level bright enough
+ * that we don't need flash
+ */
+ break;
+ }
+ /* fall through to flash start */
+ case FLASH_MODE_ON:
+ if (parms->focus_mode == FOCUS_MODE_INFINITY) {
+ s5k4ecgx_set_from_table(sd,
+ "AF assist flash start",
+ &state->regs->af_assist_flash_start,
+ 1, 0);
+ s5k4ecgx_set_from_table(sd,
+ "AF assist flash end",
+ &state->regs->af_assist_flash_end,
+ 1, 0);
+ msleep(10);
+ }
+ s5k4ecgx_set_from_table(sd, "flash start",
+ &state->regs->flash_start, 1, 0);
+ state->flash_on = true;
+ state->flash_state_on_previous_capture = true;
+ pdata->flash_onoff(1);
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* if light is low, use low light capture settings, EXCEPT
+ * if scene mode set to NIGHTSHOT or SPORTS because they
+ * have their own settings (though a low light sport setting
+ * could be useful)
+ */
+ if ((light_level <= HIGH_LIGHT_LEVEL) &&
+ (parms->scene_mode != SCENE_MODE_NIGHTSHOT) &&
+ (parms->scene_mode != SCENE_MODE_SPORTS)) {
+ s5k4ecgx_set_from_table(sd, "low cap on",
+ &state->regs->low_cap_on, 1, 0);
+ }
+
+ err = s5k4ecgx_set_capture_size(sd);
+ if (err < 0) {
+ dev_err(&client->dev,
+ "%s: failed: i2c_write for capture_resolution\n",
+ __func__);
+ return -EIO;
+ }
+
+ dev_dbg(&client->dev, "%s: send Capture_Start cmd\n", __func__);
+ s5k4ecgx_set_from_table(sd, "capture start",
+ &state->regs->capture_start, 1, 0);
+
+ /* a shot takes takes at least 50ms so sleep that amount first
+ * and then start polling for completion.
+ */
+ msleep(50);
+ /* Enter read mode */
+ s5k4ecgx_i2c_write_twobyte(client, 0x002C, 0x7000);
+ poll_time_ms = 50;
+ do {
+ s5k4ecgx_set_from_table(sd, "get capture status",
+ &state->regs->get_capture_status, 1, 0);
+ s5k4ecgx_i2c_read_twobyte(client, 0x0F12, &read_value);
+ dev_dbg(&client->dev,
+ "%s: s5k4ecgx_Capture_Start check = %#x\n",
+ __func__, read_value);
+ if (read_value != 0x00)
+ break;
+ msleep(POLL_TIME_MS);
+ poll_time_ms += POLL_TIME_MS;
+ } while (poll_time_ms < CAPTURE_POLL_TIME_MS);
+
+ dev_dbg(&client->dev, "%s: capture done check finished after %d ms\n",
+ __func__, poll_time_ms);
+
+ /* restore write mode */
+ s5k4ecgx_i2c_write_twobyte(client, 0x0028, 0x7000);
+
+ s5k4ecgx_set_from_table(sd, "ae awb lock off",
+ &state->regs->ae_awb_lock_off, 1, 0);
+
+ if ((light_level <= HIGH_LIGHT_LEVEL) &&
+ (parms->scene_mode != SCENE_MODE_NIGHTSHOT) &&
+ (parms->scene_mode != SCENE_MODE_SPORTS)) {
+ s5k4ecgx_set_from_table(sd, "low cap off",
+ &state->regs->low_cap_off, 1, 0);
+ }
+
+ if ((parms->scene_mode != SCENE_MODE_NIGHTSHOT) && (state->flash_on)) {
+ state->flash_on = false;
+ pdata->flash_onoff(0);
+ s5k4ecgx_set_from_table(sd, "flash end",
+ &state->regs->flash_end, 1, 0);
+ }
+
+ return 0;
+}
+
+/* wide dynamic range support */
+static int s5k4ecgx_set_wdr(struct v4l2_subdev *sd, int value)
+{
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+
+ if (value == WDR_ON)
+ return s5k4ecgx_set_from_table(sd, "wdr on",
+ &state->regs->wdr_on, 1, 0);
+ return s5k4ecgx_set_from_table(sd, "wdr off",
+ &state->regs->wdr_off, 1, 0);
+}
+
+static int s5k4ecgx_set_face_detection(struct v4l2_subdev *sd, int value)
+{
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+
+ if (value == FACE_DETECTION_ON)
+ return s5k4ecgx_set_from_table(sd, "face detection on",
+ &state->regs->face_detection_on, 1, 0);
+ return s5k4ecgx_set_from_table(sd, "face detection off",
+ &state->regs->face_detection_off, 1, 0);
+}
+
+static int s5k4ecgx_return_focus(struct v4l2_subdev *sd)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+
+ err = s5k4ecgx_set_from_table(sd,
+ "af normal mode 1",
+ &state->regs->af_normal_mode_1, 1, 0);
+ if (err < 0)
+ goto fail;
+ msleep(FIRST_SETTING_FOCUS_MODE_DELAY_MS);
+ err = s5k4ecgx_set_from_table(sd,
+ "af normal mode 2",
+ &state->regs->af_normal_mode_2, 1, 0);
+ if (err < 0)
+ goto fail;
+ msleep(SECOND_SETTING_FOCUS_MODE_DELAY_MS);
+ err = s5k4ecgx_set_from_table(sd,
+ "af normal mode 3",
+ &state->regs->af_normal_mode_3, 1, 0);
+ if (err < 0)
+ goto fail;
+
+ return 0;
+fail:
+ dev_err(&client->dev,
+ "%s: i2c_write failed\n", __func__);
+ return -EIO;
+}
+
+static int s5k4ecgx_set_focus_mode(struct v4l2_subdev *sd, int value)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ struct sec_cam_parm *parms =
+ (struct sec_cam_parm *)&state->strm.parm.raw_data;
+ int err;
+
+ if (parms->focus_mode == value)
+ return 0;
+
+ dev_dbg(&client->dev, "%s value(%d)\n", __func__, value);
+
+ switch (value) {
+ case FOCUS_MODE_MACRO:
+ dev_dbg(&client->dev,
+ "%s: FOCUS_MODE_MACRO\n", __func__);
+ err = s5k4ecgx_set_from_table(sd, "af macro mode 1",
+ &state->regs->af_macro_mode_1, 1, 0);
+ if (err < 0)
+ goto fail;
+ msleep(FIRST_SETTING_FOCUS_MODE_DELAY_MS);
+ err = s5k4ecgx_set_from_table(sd, "af macro mode 2",
+ &state->regs->af_macro_mode_2, 1, 0);
+ if (err < 0)
+ goto fail;
+ msleep(SECOND_SETTING_FOCUS_MODE_DELAY_MS);
+ err = s5k4ecgx_set_from_table(sd, "af macro mode 3",
+ &state->regs->af_macro_mode_3, 1, 0);
+ if (err < 0)
+ goto fail;
+ parms->focus_mode = FOCUS_MODE_MACRO;
+ break;
+
+ case FOCUS_MODE_INFINITY:
+ case FOCUS_MODE_AUTO:
+ err = s5k4ecgx_set_from_table(sd,
+ "af normal mode 1",
+ &state->regs->af_normal_mode_1, 1, 0);
+ if (err < 0)
+ goto fail;
+ msleep(FIRST_SETTING_FOCUS_MODE_DELAY_MS);
+ err = s5k4ecgx_set_from_table(sd,
+ "af normal mode 2",
+ &state->regs->af_normal_mode_2, 1, 0);
+ if (err < 0)
+ goto fail;
+ msleep(SECOND_SETTING_FOCUS_MODE_DELAY_MS);
+ err = s5k4ecgx_set_from_table(sd,
+ "af normal mode 3",
+ &state->regs->af_normal_mode_3, 1, 0);
+ if (err < 0)
+ goto fail;
+ parms->focus_mode = value;
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+
+ return 0;
+fail:
+ dev_err(&client->dev,
+ "%s: i2c_write failed\n", __func__);
+ return -EIO;
+}
+
+static void s5k4ecgx_auto_focus_flash_start(struct v4l2_subdev *sd)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ struct s5k4ecgx_platform_data *pdata = client->dev.platform_data;
+ int count;
+ u16 read_value;
+
+ s5k4ecgx_set_from_table(sd, "AF assist flash start",
+ &state->regs->af_assist_flash_start, 1, 0);
+ state->flash_on = true;
+ pdata->af_assist_onoff(1);
+
+ /* delay 200ms (SLSI value) and then poll to see if AE is stable.
+ * once it is stable, lock it and then return to do AF
+ */
+ msleep(200);
+
+ /* enter read mode */
+ s5k4ecgx_i2c_write_twobyte(client, 0x002C, 0x7000);
+ for (count = 0; count < AE_STABLE_SEARCH_COUNT; count++) {
+ if (state->af_status == AF_CANCEL)
+ break;
+ s5k4ecgx_set_from_table(sd, "get ae stable status",
+ &state->regs->get_ae_stable_status, 1, 0);
+ s5k4ecgx_i2c_read_twobyte(client, 0x0F12, &read_value);
+ dev_dbg(&client->dev, "%s: ae stable status = %#x\n",
+ __func__, read_value);
+ if (read_value == 0x1)
+ break;
+ msleep(state->one_frame_delay_ms);
+ }
+
+ /* restore write mode */
+ s5k4ecgx_i2c_write_twobyte(client, 0x0028, 0x7000);
+
+ /* if we were cancelled, turn off flash */
+ if (state->af_status == AF_CANCEL) {
+ dev_dbg(&client->dev,
+ "%s: AF cancelled\n", __func__);
+ s5k4ecgx_set_from_table(sd, "AF assist flash end",
+ &state->regs->af_assist_flash_end, 1, 0);
+ state->flash_on = false;
+ pdata->af_assist_onoff(0);
+ }
+}
+
+static int s5k4ecgx_start_auto_focus(struct v4l2_subdev *sd)
+{
+ int light_level;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ struct sec_cam_parm *parms =
+ (struct sec_cam_parm *)&state->strm.parm.raw_data;
+
+ dev_dbg(&client->dev, "%s: start SINGLE AF operation, flash mode %d\n",
+ __func__, parms->flash_mode);
+
+ /* in case user calls auto_focus repeatedly without a cancel
+ * or a capture, we need to cancel here to allow ae_awb
+ * to work again, or else we could be locked forever while
+ * that app is running, which is not the expected behavior.
+ */
+ s5k4ecgx_set_from_table(sd, "ae awb lock off",
+ &state->regs->ae_awb_lock_off, 1, 0);
+
+ if (parms->scene_mode == SCENE_MODE_NIGHTSHOT) {
+ /* user selected night shot mode, assume we need low light
+ * af mode. flash is always off in night shot mode
+ */
+ goto enable_af_low_light_mode;
+ }
+
+ light_level = s5k4ecgx_get_light_level(sd);
+
+ switch (parms->flash_mode) {
+ case FLASH_MODE_AUTO:
+ if (light_level > LOW_LIGHT_LEVEL) {
+ /* flash not needed */
+ break;
+ }
+ /* fall through to turn on flash for AF assist */
+ case FLASH_MODE_ON:
+ s5k4ecgx_auto_focus_flash_start(sd);
+ if (state->af_status == AF_CANCEL)
+ return 0;
+ break;
+ case FLASH_MODE_OFF:
+ break;
+ default:
+ dev_err(&client->dev,
+ "%s: Unknown Flash mode 0x%x\n",
+ __func__, parms->flash_mode);
+ break;
+ }
+
+ if (light_level > LOW_LIGHT_LEVEL) {
+ if (state->sensor_af_in_low_light_mode) {
+ state->sensor_af_in_low_light_mode = false;
+ s5k4ecgx_set_from_table(sd, "af low light mode off",
+ &state->regs->af_low_light_mode_off, 1, 0);
+ }
+ } else {
+enable_af_low_light_mode:
+ if (!state->sensor_af_in_low_light_mode) {
+ state->sensor_af_in_low_light_mode = true;
+ s5k4ecgx_set_from_table(sd, "af low light mode on",
+ &state->regs->af_low_light_mode_on, 1, 0);
+ }
+ }
+
+ s5k4ecgx_set_from_table(sd, "single af start",
+ &state->regs->single_af_start, 1, 0);
+ state->af_status = AF_INITIAL;
+ dev_dbg(&client->dev, "%s: af_status set to start\n", __func__);
+
+ return 0;
+}
+
+/* called by HAL after auto focus was finished.
+ * it might off the assist flash
+ */
+static int s5k4ecgx_finish_auto_focus(struct v4l2_subdev *sd)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+
+ /* restore write mode */
+ s5k4ecgx_i2c_write_twobyte(client, 0x0028, 0x7000);
+
+ if (state->flash_on) {
+ struct s5k4ecgx_platform_data *pd = client->dev.platform_data;
+ s5k4ecgx_set_from_table(sd, "AF assist flash end",
+ &state->regs->af_assist_flash_end, 1, 0);
+ state->flash_on = false;
+ pd->af_assist_onoff(0);
+ }
+
+ dev_dbg(&client->dev, "%s: single AF finished\n", __func__);
+ state->af_status = AF_NONE;
+ return 0;
+}
+
+static int s5k4ecgx_stop_auto_focus(struct v4l2_subdev *sd)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ struct sec_cam_parm *parms =
+ (struct sec_cam_parm *)&state->strm.parm.raw_data;
+ int focus_mode = parms->focus_mode;
+
+ dev_dbg(&client->dev, "%s: single AF Off command Setting\n", __func__);
+
+ /* always cancel ae_awb, in case AF already finished before
+ * we got called.
+ */
+ /* restore write mode */
+ s5k4ecgx_i2c_write_twobyte(client, 0x0028, 0x7000);
+
+ s5k4ecgx_set_from_table(sd, "ae awb lock off",
+ &state->regs->ae_awb_lock_off, 1, 0);
+ if (state->flash_on)
+ s5k4ecgx_finish_auto_focus(sd);
+
+ if (state->af_status != AF_START) {
+ /* we weren't in the middle auto focus operation, we're done */
+ dev_dbg(&client->dev,
+ "%s: auto focus not in progress, done\n", __func__);
+
+ if (focus_mode == FOCUS_MODE_MACRO) {
+ /* for change focus mode forcely */
+ parms->focus_mode = -1;
+ s5k4ecgx_set_focus_mode(sd, FOCUS_MODE_MACRO);
+ } else if (focus_mode == FOCUS_MODE_AUTO) {
+ /* for change focus mode forcely */
+ parms->focus_mode = -1;
+ s5k4ecgx_set_focus_mode(sd, FOCUS_MODE_AUTO);
+ }
+
+ return 0;
+ }
+
+ /* auto focus was in progress. the other thread
+ * is either in the middle of s5k4ecgx_get_auto_focus_result_first(),
+ * s5k4ecgx_get_auto_focus_result_second()
+ * or will call it shortly. set a flag to have
+ * it abort it's polling. that thread will
+ * also do cleanup like restore focus position.
+ *
+ * it might be enough to just send sensor commands
+ * to abort auto focus and the other thread would get
+ * that state from it's polling calls, but I'm not sure.
+ */
+ state->af_status = AF_CANCEL;
+ dev_dbg(&client->dev,
+ "%s: sending Single_AF_Off commands to sensor\n", __func__);
+
+ s5k4ecgx_set_from_table(sd, "single af off 1",
+ &state->regs->single_af_off_1, 1, 0);
+
+ msleep(state->one_frame_delay_ms);
+
+ s5k4ecgx_set_from_table(sd, "single af off 2",
+ &state->regs->single_af_off_2, 1, 0);
+
+ return 0;
+}
+
+/* called by HAL after auto focus was started to get the first search result*/
+static int s5k4ecgx_get_auto_focus_result_first(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ u16 read_value;
+
+ if (state->af_status == AF_INITIAL) {
+ dev_dbg(&client->dev, "%s: Check AF Result\n", __func__);
+ if (state->af_status == AF_NONE) {
+ dev_dbg(&client->dev,
+ "%s: auto focus never started, returning 0x2\n",
+ __func__);
+ ctrl->value = AUTO_FOCUS_CANCELLED;
+ return 0;
+ }
+
+ /* must delay 2 frame times before checking result of 1st phase */
+ mutex_unlock(&state->ctrl_lock);
+ msleep(state->one_frame_delay_ms*2);
+ mutex_lock(&state->ctrl_lock);
+
+ /* lock AE and AWB after first AF search */
+ s5k4ecgx_set_from_table(sd, "ae awb lock on",
+ &state->regs->ae_awb_lock_on, 1, 0);
+
+ dev_dbg(&client->dev, "%s: 1st AF search\n", __func__);
+ /* enter read mode */
+ s5k4ecgx_i2c_write_twobyte(client, 0x002C, 0x7000);
+ state->af_status = AF_START;
+ } else if (state->af_status == AF_CANCEL) {
+ dev_dbg(&client->dev,
+ "%s: AF is cancelled while doing\n", __func__);
+ ctrl->value = AUTO_FOCUS_CANCELLED;
+ s5k4ecgx_finish_auto_focus(sd);
+ return 0;
+ }
+ s5k4ecgx_set_from_table(sd, "get 1st af search status",
+ &state->regs->get_1st_af_search_status,
+ 1, 0);
+ s5k4ecgx_i2c_read_twobyte(client, 0x0F12, &read_value);
+ dev_dbg(&client->dev,
+ "%s: 1st i2c_read --- read_value == 0x%x\n",
+ __func__, read_value);
+ ctrl->value = read_value;
+ return 0;
+}
+
+/* called by HAL after first search was succeed to get the second search result*/
+static int s5k4ecgx_get_auto_focus_result_second(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ u16 read_value;
+
+ if (state->af_status == AF_CANCEL) {
+ dev_dbg(&client->dev,
+ "%s: AF is cancelled while doing\n", __func__);
+ ctrl->value = AUTO_FOCUS_CANCELLED;
+ s5k4ecgx_finish_auto_focus(sd);
+ return 0;
+ }
+ s5k4ecgx_set_from_table(sd, "get 2nd af search status",
+ &state->regs->get_2nd_af_search_status,
+ 1, 0);
+ s5k4ecgx_i2c_read_twobyte(client, 0x0F12, &read_value);
+ dev_dbg(&client->dev,
+ "%s: 2nd i2c_read --- read_value == 0x%x\n",
+ __func__, read_value);
+ ctrl->value = read_value;
+ return 0;
+}
+
+static void s5k4ecgx_init_parameters(struct v4l2_subdev *sd)
+{
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ struct sec_cam_parm *parms =
+ (struct sec_cam_parm *)&state->strm.parm.raw_data;
+
+ state->strm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ parms->capture.capturemode = 0;
+ parms->capture.timeperframe.numerator = 1;
+ parms->capture.timeperframe.denominator = 30;
+ parms->contrast = CONTRAST_DEFAULT;
+ parms->effects = IMAGE_EFFECT_NONE;
+ parms->brightness = EV_DEFAULT;
+ parms->flash_mode = FLASH_MODE_AUTO;
+ parms->focus_mode = FOCUS_MODE_AUTO;
+ parms->iso = ISO_AUTO;
+ parms->metering = METERING_CENTER;
+ parms->saturation = SATURATION_DEFAULT;
+ parms->scene_mode = SCENE_MODE_NONE;
+ parms->sharpness = SHARPNESS_DEFAULT;
+ parms->white_balance = WHITE_BALANCE_AUTO;
+
+ state->jpeg.enable = 0;
+ state->jpeg.quality = 100;
+ state->jpeg.main_offset = 0;
+ state->jpeg.main_size = 0;
+ state->jpeg.thumb_offset = 0;
+ state->jpeg.thumb_size = 0;
+ state->jpeg.postview_offset = 0;
+
+ state->fw.major = 1;
+
+ state->one_frame_delay_ms = NORMAL_MODE_MAX_ONE_FRAME_DELAY_MS;
+}
+
+static void s5k4ecgx_set_framesize(struct v4l2_subdev *sd,
+ const struct s5k4ecgx_framesize *frmsize,
+ int frmsize_count, bool exact_match);
+static int s5k4ecgx_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
+{
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ dev_dbg(&client->dev, "%s: code = 0x%x, field = 0x%x,"
+ " colorspace = 0x%x, width = %d, height = %d\n",
+ __func__, fmt->code, fmt->field,
+ fmt->colorspace,
+ fmt->width, fmt->height);
+
+ if (fmt->code == V4L2_MBUS_FMT_FIXED &&
+ fmt->colorspace != V4L2_COLORSPACE_JPEG) {
+ dev_err(&client->dev,
+ "%s: mismatch in pixelformat and colorspace\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ state->pix.width = fmt->width;
+ state->pix.height = fmt->height;
+ if (fmt->colorspace == V4L2_COLORSPACE_JPEG)
+ state->pix.pixelformat = V4L2_PIX_FMT_JPEG;
+ else
+ state->pix.pixelformat = 0; /* is this used anywhere? */
+
+ if (fmt->colorspace == V4L2_COLORSPACE_JPEG) {
+ state->oprmode = S5K4ECGX_OPRMODE_IMAGE;
+ /*
+ * In case of image capture mode,
+ * if the given image resolution is not supported,
+ * use the next higher image resolution. */
+ s5k4ecgx_set_framesize(sd, s5k4ecgx_capture_framesize_list,
+ ARRAY_SIZE(s5k4ecgx_capture_framesize_list),
+ false);
+
+ } else {
+ state->oprmode = S5K4ECGX_OPRMODE_VIDEO;
+ /*
+ * In case of video mode,
+ * if the given video resolution is not matching, use
+ * the default rate (currently S5K4ECGX_PREVIEW_WVGA).
+ */
+ s5k4ecgx_set_framesize(sd, s5k4ecgx_preview_framesize_list,
+ ARRAY_SIZE(s5k4ecgx_preview_framesize_list),
+ true);
+ }
+
+ state->jpeg.enable = state->pix.pixelformat == V4L2_PIX_FMT_JPEG;
+
+ return 0;
+}
+
+static int s5k4ecgx_enum_framesizes(struct v4l2_subdev *sd,
+ struct v4l2_frmsizeenum *fsize)
+{
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+
+ /* The camera interface should read this value, this is the resolution
+ * at which the sensor would provide framedata to the camera i/f
+ *
+ * In case of image capture,
+ * this returns the default camera resolution (SVGA)
+ */
+ fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+ fsize->discrete.width = state->pix.width;
+ fsize->discrete.height = state->pix.height;
+ return 0;
+}
+
+static int s5k4ecgx_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
+ enum v4l2_mbus_pixelcode *code)
+{
+ pr_debug("%s: index = %d\n", __func__, index);
+
+ if (index >= ARRAY_SIZE(capture_fmts))
+ return -EINVAL;
+
+ *code = capture_fmts[index].code;
+
+ return 0;
+}
+
+static int s5k4ecgx_try_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
+{
+ int num_entries;
+ int i;
+
+ num_entries = ARRAY_SIZE(capture_fmts);
+
+ pr_debug("%s: code = 0x%x, colorspace = 0x%x, num_entries = %d\n",
+ __func__, fmt->code, fmt->colorspace, num_entries);
+
+ for (i = 0; i < num_entries; i++) {
+ if (capture_fmts[i].code == fmt->code &&
+ capture_fmts[i].colorspace == fmt->colorspace) {
+ pr_debug("%s: match found, returning 0\n", __func__);
+ return 0;
+ }
+ }
+
+ pr_debug("%s: no match found, returning -EINVAL\n", __func__);
+ return -EINVAL;
+}
+
+static void s5k4ecgx_enable_torch(struct v4l2_subdev *sd)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ struct s5k4ecgx_platform_data *pdata = client->dev.platform_data;
+
+ s5k4ecgx_set_from_table(sd, "torch start",
+ &state->regs->flash_start, 1, 0);
+ state->torch_on = true;
+ pdata->torch_onoff(1);
+}
+
+static void s5k4ecgx_disable_torch(struct v4l2_subdev *sd)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ struct s5k4ecgx_platform_data *pdata = client->dev.platform_data;
+
+ if (state->torch_on) {
+ state->torch_on = false;
+ pdata->torch_onoff(0);
+ s5k4ecgx_set_from_table(sd, "torch end",
+ &state->regs->flash_end, 1, 0);
+ }
+}
+static int s5k4ecgx_set_flash_mode(struct v4l2_subdev *sd, int value)
+{
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ struct sec_cam_parm *parms =
+ (struct sec_cam_parm *)&state->strm.parm.raw_data;
+
+ if (parms->flash_mode == value)
+ return 0;
+
+ if ((value >= FLASH_MODE_OFF) && (value <= FLASH_MODE_TORCH)) {
+ pr_debug("%s: setting flash mode to %d\n",
+ __func__, value);
+ parms->flash_mode = value;
+ if (parms->flash_mode == FLASH_MODE_TORCH)
+ s5k4ecgx_enable_torch(sd);
+ else
+ s5k4ecgx_disable_torch(sd);
+ return 0;
+ }
+ pr_debug("%s: trying to set invalid flash mode %d\n",
+ __func__, value);
+ return -EINVAL;
+}
+
+static int s5k4ecgx_g_parm(struct v4l2_subdev *sd,
+ struct v4l2_streamparm *param)
+{
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+
+ memcpy(param, &state->strm, sizeof(param));
+ return 0;
+}
+
+static int s5k4ecgx_s_parm(struct v4l2_subdev *sd,
+ struct v4l2_streamparm *param)
+{
+ int err = 0;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ struct sec_cam_parm *new_parms =
+ (struct sec_cam_parm *)&param->parm.raw_data;
+ struct sec_cam_parm *parms =
+ (struct sec_cam_parm *)&state->strm.parm.raw_data;
+
+ dev_dbg(&client->dev, "%s: start\n", __func__);
+
+ if (param->parm.capture.timeperframe.numerator !=
+ parms->capture.timeperframe.numerator ||
+ param->parm.capture.timeperframe.denominator !=
+ parms->capture.timeperframe.denominator) {
+
+ int fps = 0;
+ int fps_max = 30;
+
+ if (param->parm.capture.timeperframe.numerator &&
+ param->parm.capture.timeperframe.denominator)
+ fps =
+ (int)(param->parm.capture.timeperframe.denominator /
+ param->parm.capture.timeperframe.numerator);
+ else
+ fps = 0;
+
+ if (fps <= 0 || fps > fps_max) {
+ dev_err(&client->dev,
+ "%s: Framerate %d not supported,"
+ " setting it to %d fps.\n",
+ __func__, fps, fps_max);
+ fps = fps_max;
+ }
+
+ /*
+ * Don't set the fps value, just update it in the state
+ * We will set the resolution and
+ * fps in the start operation (preview/capture) call
+ */
+ parms->capture.timeperframe.numerator = 1;
+ parms->capture.timeperframe.denominator = fps;
+ }
+
+ /* we return an error if one happened but don't stop trying to
+ * set all parameters passed
+ */
+ err = s5k4ecgx_set_parameter(sd, &parms->contrast, new_parms->contrast,
+ "contrast", state->regs->contrast,
+ ARRAY_SIZE(state->regs->contrast));
+ err |= s5k4ecgx_set_parameter(sd, &parms->effects, new_parms->effects,
+ "effect", state->regs->effect,
+ ARRAY_SIZE(state->regs->effect));
+ err |= s5k4ecgx_set_parameter(sd, &parms->brightness,
+ new_parms->brightness, "brightness",
+ state->regs->ev, ARRAY_SIZE(state->regs->ev));
+ err |= s5k4ecgx_set_flash_mode(sd, new_parms->flash_mode);
+ /* Must delay 150ms before setting macro mode due to a camera
+ * sensor requirement */
+ if ((new_parms->focus_mode == FOCUS_MODE_MACRO) &&
+ (parms->focus_mode != FOCUS_MODE_MACRO))
+ msleep(150);
+ err |= s5k4ecgx_set_focus_mode(sd, new_parms->focus_mode);
+ err |= s5k4ecgx_set_parameter(sd, &parms->iso, new_parms->iso,
+ "iso", state->regs->iso,
+ ARRAY_SIZE(state->regs->iso));
+ err |= s5k4ecgx_set_parameter(sd, &parms->metering, new_parms->metering,
+ "metering", state->regs->metering,
+ ARRAY_SIZE(state->regs->metering));
+ err |= s5k4ecgx_set_parameter(sd, &parms->saturation,
+ new_parms->saturation, "saturation",
+ state->regs->saturation,
+ ARRAY_SIZE(state->regs->saturation));
+ err |= s5k4ecgx_set_parameter(sd, &parms->scene_mode,
+ new_parms->scene_mode, "scene_mode",
+ state->regs->scene_mode,
+ ARRAY_SIZE(state->regs->scene_mode));
+ err |= s5k4ecgx_set_parameter(sd, &parms->sharpness,
+ new_parms->sharpness, "sharpness",
+ state->regs->sharpness,
+ ARRAY_SIZE(state->regs->sharpness));
+ err |= s5k4ecgx_set_parameter(sd, &parms->white_balance,
+ new_parms->white_balance, "white balance",
+ state->regs->white_balance,
+ ARRAY_SIZE(state->regs->white_balance));
+ err |= s5k4ecgx_set_parameter(sd, &parms->fps,
+ new_parms->fps, "fps",
+ state->regs->fps,
+ ARRAY_SIZE(state->regs->fps));
+
+ if (parms->scene_mode == SCENE_MODE_NIGHTSHOT)
+ state->one_frame_delay_ms = NIGHT_MODE_MAX_ONE_FRAME_DELAY_MS;
+ else
+ state->one_frame_delay_ms = NORMAL_MODE_MAX_ONE_FRAME_DELAY_MS;
+
+ dev_dbg(&client->dev, "%s: returning %d\n", __func__, err);
+ return err;
+}
+
+/* This function is called from the g_ctrl api
+ *
+ * This function should be called only after the s_fmt call,
+ * which sets the required width/height value.
+ *
+ * It checks a list of available frame sizes and sets the
+ * most appropriate frame size.
+ *
+ * The list is stored in an increasing order (as far as possible).
+ * Hence the first entry (searching from the beginning) where both the
+ * width and height is more than the required value is returned.
+ * In case of no perfect match, we set the last entry (which is supposed
+ * to be the largest resolution supported.)
+ */
+static void s5k4ecgx_set_framesize(struct v4l2_subdev *sd,
+ const struct s5k4ecgx_framesize *frmsize,
+ int frmsize_count, bool preview)
+{
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ const struct s5k4ecgx_framesize *last_frmsize =
+ &frmsize[frmsize_count - 1];
+
+ dev_dbg(&client->dev, "%s: Requested Res: %dx%d\n", __func__,
+ state->pix.width, state->pix.height);
+
+ do {
+ /*
+ * In case of image capture mode,
+ * if the given image resolution is not supported,
+ * return the next higher image resolution. */
+ if (preview) {
+ if (frmsize->width == state->pix.width &&
+ frmsize->height == state->pix.height) {
+ break;
+ }
+ } else {
+ dev_dbg(&client->dev,
+ "%s: compare frmsize %dx%d to %dx%d\n",
+ __func__,
+ frmsize->width, frmsize->height,
+ state->pix.width, state->pix.height);
+ if (frmsize->width >= state->pix.width &&
+ frmsize->height >= state->pix.height) {
+ dev_dbg(&client->dev,
+ "%s: select frmsize %dx%d, index=%d\n",
+ __func__,
+ frmsize->width, frmsize->height,
+ frmsize->index);
+ break;
+ }
+ }
+
+ frmsize++;
+ } while (frmsize <= last_frmsize);
+
+ if (frmsize > last_frmsize)
+ frmsize = last_frmsize;
+
+ state->pix.width = frmsize->width;
+ state->pix.height = frmsize->height;
+ if (preview) {
+ state->preview_framesize_index = frmsize->index;
+ dev_dbg(&client->dev, "%s: Preview Res Set: %dx%d, index %d\n",
+ __func__, state->pix.width, state->pix.height,
+ state->preview_framesize_index);
+ } else {
+ state->capture_framesize_index = frmsize->index;
+ dev_dbg(&client->dev, "%s: Capture Res Set: %dx%d, index %d\n",
+ __func__, state->pix.width, state->pix.height,
+ state->capture_framesize_index);
+ }
+}
+
+static int s5k4ecgx_check_dataline_stop(struct v4l2_subdev *sd)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ int err;
+
+ dev_dbg(&client->dev, "%s\n", __func__);
+
+ err = s5k4ecgx_set_from_table(sd, "DTP stop",
+ &state->regs->dtp_stop, 1, 0);
+ if (err < 0) {
+ v4l_info(client, "%s: register set failed\n", __func__);
+ return -EIO;
+ }
+
+ state->check_dataline = 0;
+
+ return err;
+}
+
+static void s5k4ecgx_get_esd_int(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ u16 read_value;
+ int err;
+
+ if ((S5K4ECGX_RUNMODE_RUNNING == state->runmode) &&
+ (state->af_status != AF_START)) {
+ err = s5k4ecgx_set_from_table(sd, "get esd status",
+ &state->regs->get_esd_status,
+ 1, 0);
+ err |= s5k4ecgx_i2c_read_twobyte(client, 0x0F12, &read_value);
+ dev_dbg(&client->dev,
+ "%s: read_value == 0x%x\n", __func__, read_value);
+ /* return to write mode */
+ err |= s5k4ecgx_i2c_write_twobyte(client, 0x0028, 0x7000);
+
+ if (err < 0) {
+ v4l_info(client,
+ "Failed I2C for getting ESD information\n");
+ ctrl->value = 0x01;
+ } else {
+ if (read_value != 0x0000) {
+ v4l_info(client, "ESD interrupt happened!!\n");
+ ctrl->value = 0x01;
+ } else {
+ dev_dbg(&client->dev,
+ "%s: No ESD interrupt!!\n", __func__);
+ ctrl->value = 0x00;
+ }
+ }
+ } else
+ ctrl->value = 0x00;
+}
+
+/* returns the real iso currently used by sensor due to lighting
+ * conditions, not the requested iso we sent using s_ctrl.
+ */
+static int s5k4ecgx_get_iso(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ u16 read_value1 = 0;
+ u16 read_value2 = 0;
+ int read_value;
+
+ err = s5k4ecgx_set_from_table(sd, "get iso",
+ &state->regs->get_iso, 1, 0);
+ err |= s5k4ecgx_i2c_read_twobyte(client, 0x0F12, &read_value1);
+ err |= s5k4ecgx_i2c_read_twobyte(client, 0x0F12, &read_value2);
+
+ /* restore write mode */
+ s5k4ecgx_i2c_write_twobyte(client, 0x0028, 0x7000);
+
+ read_value = read_value1 * read_value2 / 384;
+
+ if (read_value > 0x400)
+ ctrl->value = ISO_400;
+ else if (read_value > 0x200)
+ ctrl->value = ISO_200;
+ else if (read_value > 0x100)
+ ctrl->value = ISO_100;
+ else
+ ctrl->value = ISO_50;
+
+ dev_dbg(&client->dev, "%s: get iso == %d (0x%x, 0x%x)\n",
+ __func__, ctrl->value, read_value1, read_value2);
+
+ return err;
+}
+
+static int s5k4ecgx_get_shutterspeed(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ u16 read_value_1;
+ u16 read_value_2;
+ u32 read_value;
+
+ err = s5k4ecgx_set_from_table(sd, "get shutterspeed",
+ &state->regs->get_shutterspeed, 1, 0);
+ err |= s5k4ecgx_i2c_read_twobyte(client, 0x0F12, &read_value_1);
+ err |= s5k4ecgx_i2c_read_twobyte(client, 0x0F12, &read_value_2);
+
+ read_value = (read_value_2 << 16) | (read_value_1 & 0xffff);
+ /* restore write mode */
+ s5k4ecgx_i2c_write_twobyte(client, 0x0028, 0x7000);
+
+ ctrl->value = read_value * 1000 / 400;
+ dev_dbg(&client->dev,
+ "%s: get shutterspeed == %d\n", __func__, ctrl->value);
+
+ return err;
+}
+
+static int s5k4ecgx_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ struct sec_cam_parm *parms =
+ (struct sec_cam_parm *)&state->strm.parm.raw_data;
+ int err = 0;
+
+ if (!state->initialized) {
+ dev_err(&client->dev,
+ "%s: return error because uninitialized\n", __func__);
+ return -ENODEV;
+ }
+
+ mutex_lock(&state->ctrl_lock);
+
+ switch (ctrl->id) {
+ case V4L2_CID_CAMERA_WHITE_BALANCE:
+ ctrl->value = parms->white_balance;
+ break;
+ case V4L2_CID_CAMERA_EFFECT:
+ ctrl->value = parms->effects;
+ break;
+ case V4L2_CID_CAMERA_CONTRAST:
+ ctrl->value = parms->contrast;
+ break;
+ case V4L2_CID_CAMERA_SATURATION:
+ ctrl->value = parms->saturation;
+ break;
+ case V4L2_CID_CAMERA_SHARPNESS:
+ ctrl->value = parms->sharpness;
+ break;
+ case V4L2_CID_CAM_JPEG_MAIN_SIZE:
+ ctrl->value = state->jpeg.main_size;
+ break;
+ case V4L2_CID_CAM_JPEG_MAIN_OFFSET:
+ ctrl->value = state->jpeg.main_offset;
+ break;
+ case V4L2_CID_CAM_JPEG_THUMB_SIZE:
+ ctrl->value = state->jpeg.thumb_size;
+ break;
+ case V4L2_CID_CAM_JPEG_THUMB_OFFSET:
+ ctrl->value = state->jpeg.thumb_offset;
+ break;
+ case V4L2_CID_CAM_JPEG_POSTVIEW_OFFSET:
+ ctrl->value = state->jpeg.postview_offset;
+ break;
+ case V4L2_CID_CAM_JPEG_MEMSIZE:
+ ctrl->value = SENSOR_JPEG_SNAPSHOT_MEMSIZE;
+ break;
+ case V4L2_CID_CAM_JPEG_QUALITY:
+ ctrl->value = state->jpeg.quality;
+ break;
+ case V4L2_CID_CAMERA_AUTO_FOCUS_RESULT_FIRST:
+ err = s5k4ecgx_get_auto_focus_result_first(sd, ctrl);
+ break;
+ case V4L2_CID_CAMERA_AUTO_FOCUS_RESULT_SECOND:
+ err = s5k4ecgx_get_auto_focus_result_second(sd, ctrl);
+ break;
+ case V4L2_CID_CAM_DATE_INFO_YEAR:
+ ctrl->value = 2010;
+ break;
+ case V4L2_CID_CAM_DATE_INFO_MONTH:
+ ctrl->value = 2;
+ break;
+ case V4L2_CID_CAM_DATE_INFO_DATE:
+ ctrl->value = 25;
+ break;
+ case V4L2_CID_CAM_SENSOR_VER:
+ ctrl->value = 1;
+ break;
+ case V4L2_CID_CAM_FW_MINOR_VER:
+ ctrl->value = state->fw.minor;
+ break;
+ case V4L2_CID_CAM_FW_MAJOR_VER:
+ ctrl->value = state->fw.major;
+ break;
+ case V4L2_CID_CAM_PRM_MINOR_VER:
+ ctrl->value = state->prm.minor;
+ break;
+ case V4L2_CID_CAM_PRM_MAJOR_VER:
+ ctrl->value = state->prm.major;
+ break;
+ case V4L2_CID_ESD_INT:
+ s5k4ecgx_get_esd_int(sd, ctrl);
+ break;
+ case V4L2_CID_CAMERA_GET_ISO:
+ err = s5k4ecgx_get_iso(sd, ctrl);
+ break;
+ case V4L2_CID_CAMERA_GET_SHT_TIME:
+ err = s5k4ecgx_get_shutterspeed(sd, ctrl);
+ break;
+ case V4L2_CID_CAMERA_GET_FLASH_ONOFF:
+ ctrl->value = state->flash_state_on_previous_capture;
+ break;
+ case V4L2_CID_CAMERA_OBJ_TRACKING_STATUS:
+ case V4L2_CID_CAMERA_SMART_AUTO_STATUS:
+ break;
+ default:
+ err = -ENOIOCTLCMD;
+ dev_err(&client->dev, "%s: unknown ctrl id 0x%x\n",
+ __func__, ctrl->id);
+ break;
+ }
+
+ mutex_unlock(&state->ctrl_lock);
+
+ return err;
+}
+
+static int s5k4ecgx_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ struct sec_cam_parm *parms =
+ (struct sec_cam_parm *)&state->strm.parm.raw_data;
+ int err = 0;
+ int value = ctrl->value;
+
+ if (!state->initialized &&
+ (ctrl->id != V4L2_CID_CAMERA_CHECK_DATALINE)) {
+ dev_err(&client->dev,
+ "%s: return error because uninitialized\n", __func__);
+ return -ENODEV;
+ }
+
+ dev_dbg(&client->dev, "%s: V4l2 control ID =%d, val = %d\n",
+ __func__, ctrl->id - V4L2_CID_PRIVATE_BASE, value);
+
+ mutex_lock(&state->ctrl_lock);
+
+ switch (ctrl->id) {
+ case V4L2_CID_CAMERA_FLASH_MODE:
+ err = s5k4ecgx_set_flash_mode(sd, value);
+ break;
+ case V4L2_CID_CAMERA_BRIGHTNESS:
+ if (state->runmode == S5K4ECGX_RUNMODE_RUNNING) {
+ err = s5k4ecgx_set_parameter(sd, &parms->brightness,
+ value, "brightness",
+ state->regs->ev,
+ ARRAY_SIZE(state->regs->ev));
+ } else {
+ dev_err(&client->dev,
+ "%s: trying to set brightness when not "
+ "in preview mode\n",
+ __func__);
+ err = -EINVAL;
+ }
+ break;
+ case V4L2_CID_CAMERA_WHITE_BALANCE:
+ if (state->runmode == S5K4ECGX_RUNMODE_RUNNING) {
+ err = s5k4ecgx_set_parameter(sd, &parms->white_balance,
+ value, "white balance",
+ state->regs->white_balance,
+ ARRAY_SIZE(state->regs->white_balance));
+ } else {
+ dev_err(&client->dev,
+ "%s: trying to set white balance when not "
+ "in preview mode\n",
+ __func__);
+ err = -EINVAL;
+ }
+ break;
+ case V4L2_CID_CAMERA_EFFECT:
+ if (state->runmode == S5K4ECGX_RUNMODE_RUNNING) {
+ err = s5k4ecgx_set_parameter(sd, &parms->effects,
+ value, "effects", state->regs->effect,
+ ARRAY_SIZE(state->regs->effect));
+ } else {
+ dev_err(&client->dev,
+ "%s: trying to set effect when not "
+ "in preview mode\n",
+ __func__);
+ err = -EINVAL;
+ }
+ break;
+ case V4L2_CID_CAMERA_ISO:
+ if (state->runmode == S5K4ECGX_RUNMODE_RUNNING) {
+ err = s5k4ecgx_set_parameter(sd, &parms->iso,
+ value, "iso",
+ state->regs->iso,
+ ARRAY_SIZE(state->regs->iso));
+ } else {
+ dev_err(&client->dev,
+ "%s: trying to set iso when not "
+ "in preview mode\n",
+ __func__);
+ err = -EINVAL;
+ }
+ break;
+ case V4L2_CID_CAMERA_METERING:
+ if (state->runmode == S5K4ECGX_RUNMODE_RUNNING) {
+ err = s5k4ecgx_set_parameter(sd, &parms->metering,
+ value, "metering",
+ state->regs->metering,
+ ARRAY_SIZE(state->regs->metering));
+ } else {
+ dev_err(&client->dev,
+ "%s: trying to set metering when not "
+ "in preview mode\n",
+ __func__);
+ err = -EINVAL;
+ }
+ break;
+ case V4L2_CID_CAMERA_CONTRAST:
+ err = s5k4ecgx_set_parameter(sd, &parms->contrast,
+ value, "contrast",
+ state->regs->contrast,
+ ARRAY_SIZE(state->regs->contrast));
+ break;
+ case V4L2_CID_CAMERA_SATURATION:
+ err = s5k4ecgx_set_parameter(sd, &parms->saturation,
+ value, "saturation",
+ state->regs->saturation,
+ ARRAY_SIZE(state->regs->saturation));
+ break;
+ case V4L2_CID_CAMERA_SHARPNESS:
+ err = s5k4ecgx_set_parameter(sd, &parms->sharpness,
+ value, "sharpness",
+ state->regs->sharpness,
+ ARRAY_SIZE(state->regs->sharpness));
+ break;
+ case V4L2_CID_CAMERA_WDR:
+ err = s5k4ecgx_set_wdr(sd, value);
+ break;
+ case V4L2_CID_CAMERA_FACE_DETECTION:
+ err = s5k4ecgx_set_face_detection(sd, value);
+ break;
+ case V4L2_CID_CAMERA_FOCUS_MODE:
+ err = s5k4ecgx_set_focus_mode(sd, value);
+ break;
+ case V4L2_CID_CAM_JPEG_QUALITY:
+ if (state->runmode == S5K4ECGX_RUNMODE_RUNNING) {
+ state->jpeg.quality = value;
+ err = s5k4ecgx_set_jpeg_quality(sd);
+ } else {
+ dev_err(&client->dev,
+ "%s: trying to set jpeg quality when not "
+ "in preview mode\n",
+ __func__);
+ err = -EINVAL;
+ }
+ break;
+ case V4L2_CID_CAMERA_SCENE_MODE:
+ err = s5k4ecgx_set_parameter(sd, &parms->scene_mode,
+ SCENE_MODE_NONE, "scene_mode",
+ state->regs->scene_mode,
+ ARRAY_SIZE(state->regs->scene_mode));
+ if (err < 0) {
+ dev_err(&client->dev,
+ "%s: failed to set scene-mode default value\n",
+ __func__);
+ break;
+ }
+ if (value != SCENE_MODE_NONE) {
+ err = s5k4ecgx_set_parameter(sd, &parms->scene_mode,
+ value, "scene_mode",
+ state->regs->scene_mode,
+ ARRAY_SIZE(state->regs->scene_mode));
+ }
+ if (parms->scene_mode == SCENE_MODE_NIGHTSHOT) {
+ state->one_frame_delay_ms =
+ NIGHT_MODE_MAX_ONE_FRAME_DELAY_MS;
+ } else {
+ state->one_frame_delay_ms =
+ NORMAL_MODE_MAX_ONE_FRAME_DELAY_MS;
+ }
+
+ break;
+ case V4L2_CID_CAMERA_GPS_LATITUDE:
+ dev_err(&client->dev,
+ "%s: V4L2_CID_CAMERA_GPS_LATITUDE: not implemented\n",
+ __func__);
+ break;
+ case V4L2_CID_CAMERA_GPS_LONGITUDE:
+ dev_err(&client->dev,
+ "%s: V4L2_CID_CAMERA_GPS_LONGITUDE: not implemented\n",
+ __func__);
+ break;
+ case V4L2_CID_CAMERA_GPS_TIMESTAMP:
+ dev_err(&client->dev,
+ "%s: V4L2_CID_CAMERA_GPS_TIMESTAMP: not implemented\n",
+ __func__);
+ break;
+ case V4L2_CID_CAMERA_GPS_ALTITUDE:
+ dev_err(&client->dev,
+ "%s: V4L2_CID_CAMERA_GPS_ALTITUDE: not implemented\n",
+ __func__);
+ break;
+ case V4L2_CID_CAMERA_OBJECT_POSITION_X:
+ state->position.x = value;
+ break;
+ case V4L2_CID_CAMERA_OBJECT_POSITION_Y:
+ state->position.y = value;
+ break;
+ case V4L2_CID_CAMERA_SET_AUTO_FOCUS:
+ if (value == AUTO_FOCUS_ON)
+ err = s5k4ecgx_start_auto_focus(sd);
+ else if (value == AUTO_FOCUS_OFF)
+ err = s5k4ecgx_stop_auto_focus(sd);
+ else {
+ err = -EINVAL;
+ dev_err(&client->dev,
+ "%s: bad focus value requestion %d\n",
+ __func__, value);
+ }
+ break;
+ case V4L2_CID_CAMERA_FRAME_RATE:
+ dev_dbg(&client->dev,
+ "%s: camera frame rate request for %d fps\n",
+ __func__, value);
+ err = s5k4ecgx_set_parameter(sd, &parms->fps,
+ value, "fps",
+ state->regs->fps,
+ ARRAY_SIZE(state->regs->fps));
+ break;
+ case V4L2_CID_CAM_CAPTURE:
+ err = s5k4ecgx_start_capture(sd);
+ break;
+
+ /* Used to start / stop preview operation.
+ * This call can be modified to START/STOP operation,
+ * which can be used in image capture also
+ */
+ case V4L2_CID_CAM_PREVIEW_ONOFF:
+ if (value)
+ err = s5k4ecgx_set_preview_start(sd);
+ else
+ err = s5k4ecgx_set_preview_stop(sd);
+ break;
+ case V4L2_CID_CAMERA_CHECK_DATALINE:
+ dev_dbg(&client->dev, "%s: check_dataline set to %d\n",
+ __func__, value);
+ state->check_dataline = value;
+ break;
+ case V4L2_CID_CAMERA_CHECK_DATALINE_STOP:
+ err = s5k4ecgx_check_dataline_stop(sd);
+ break;
+ case V4L2_CID_CAMERA_RETURN_FOCUS:
+ if (parms->focus_mode != FOCUS_MODE_MACRO)
+ err = s5k4ecgx_return_focus(sd);
+ break;
+ case V4L2_CID_CAMERA_FINISH_AUTO_FOCUS:
+ err = s5k4ecgx_finish_auto_focus(sd);
+ break;
+ default:
+ dev_err(&client->dev, "%s: unknown set ctrl id 0x%x\n",
+ __func__, ctrl->id);
+ err = -ENOIOCTLCMD;
+ break;
+ }
+
+ if (err < 0)
+ dev_err(&client->dev, "%s: videoc_s_ctrl failed %d\n", __func__,
+ err);
+
+ mutex_unlock(&state->ctrl_lock);
+
+ dev_dbg(&client->dev, "%s: videoc_s_ctrl returning %d\n",
+ __func__, err);
+
+ return err;
+}
+
+static int s5k4ecgx_s_ext_ctrl(struct v4l2_subdev *sd,
+ struct v4l2_ext_control *ctrl)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ int err = 0;
+ struct gps_info_common *tempGPSType = NULL;
+
+ switch (ctrl->id) {
+
+ case V4L2_CID_CAMERA_GPS_LATITUDE:
+ tempGPSType = (struct gps_info_common *)ctrl->reserved2[1];
+ state->gps_info.gps_buf[0] = tempGPSType->direction;
+ state->gps_info.gps_buf[1] = tempGPSType->dgree;
+ state->gps_info.gps_buf[2] = tempGPSType->minute;
+ state->gps_info.gps_buf[3] = tempGPSType->second;
+ break;
+ case V4L2_CID_CAMERA_GPS_LONGITUDE:
+ tempGPSType = (struct gps_info_common *)ctrl->reserved2[1];
+ state->gps_info.gps_buf[4] = tempGPSType->direction;
+ state->gps_info.gps_buf[5] = tempGPSType->dgree;
+ state->gps_info.gps_buf[6] = tempGPSType->minute;
+ state->gps_info.gps_buf[7] = tempGPSType->second;
+ break;
+ case V4L2_CID_CAMERA_GPS_ALTITUDE:
+ tempGPSType = (struct gps_info_common *)ctrl->reserved2[1];
+ state->gps_info.altitude_buf[0] = tempGPSType->direction;
+ state->gps_info.altitude_buf[1] =
+ (tempGPSType->dgree) & 0x00ff;
+ state->gps_info.altitude_buf[2] =
+ ((tempGPSType->dgree) & 0xff00) >> 8;
+ state->gps_info.altitude_buf[3] = tempGPSType->minute;
+ break;
+ case V4L2_CID_CAMERA_GPS_TIMESTAMP:
+ state->gps_info.gps_timeStamp = *((int *)ctrl->reserved2[1]);
+ err = 0;
+ break;
+ default:
+ dev_err(&client->dev, "%s: unknown ctrl->id %d\n",
+ __func__, ctrl->id);
+ err = -ENOIOCTLCMD;
+ break;
+ }
+
+ if (err < 0)
+ dev_err(&client->dev, "%s: vidioc_s_ext_ctrl failed %d\n",
+ __func__, err);
+
+ return err;
+}
+
+static int s5k4ecgx_s_ext_ctrls(struct v4l2_subdev *sd,
+ struct v4l2_ext_controls *ctrls)
+{
+ struct v4l2_ext_control *ctrl = ctrls->controls;
+ int ret;
+ int i;
+
+ for (i = 0; i < ctrls->count; i++, ctrl++) {
+ ret = s5k4ecgx_s_ext_ctrl(sd, ctrl);
+
+ if (ret) {
+ ctrls->error_idx = i;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+#ifdef CONFIG_VIDEO_S5K4ECGX_DEBUG
+static void s5k4ecgx_dump_regset(struct s5k4ecgx_regset *regset)
+{
+ if ((regset->data[0] == 0x00) && (regset->data[1] == 0x2A)) {
+ if (regset->size <= 6)
+ pr_err("odd regset size %d\n", regset->size);
+ pr_info("regset: addr = 0x%02X%02X, data[0,1] = 0x%02X%02X,"
+ " total data size = %d\n",
+ regset->data[2], regset->data[3],
+ regset->data[6], regset->data[7],
+ regset->size-6);
+ } else {
+ pr_info("regset: 0x%02X%02X%02X%02X\n",
+ regset->data[0], regset->data[1],
+ regset->data[2], regset->data[3]);
+ if (regset->size != 4)
+ pr_err("odd regset size %d\n", regset->size);
+ }
+}
+#endif
+
+static int s5k4ecgx_i2c_write_block(struct v4l2_subdev *sd, u8 *buf, int size)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ int retry_count = 5;
+ int ret;
+ struct i2c_msg msg = {client->addr, 0, size, buf};
+
+#ifdef CONFIG_VIDEO_S5K4ECGX_DEBUG
+ if (s5k4ecgx_debug_mask & S5K4ECGX_DEBUG_I2C_BURSTS) {
+ if ((buf[0] == 0x0F) && (buf[1] == 0x12))
+ pr_info("%s : data[0,1] = 0x%02X%02X,"
+ " total data size = %d\n",
+ __func__, buf[2], buf[3], size-2);
+ else
+ pr_info("%s : 0x%02X%02X%02X%02X\n",
+ __func__, buf[0], buf[1], buf[2], buf[3]);
+ }
+#endif
+
+ do {
+ ret = i2c_transfer(client->adapter, &msg, 1);
+ if (likely(ret == 1))
+ break;
+ msleep(POLL_TIME_MS);
+ } while (retry_count-- > 0);
+ if (ret != 1) {
+ dev_err(&client->dev, "%s: I2C is not working.\n", __func__);
+ return -EIO;
+ }
+
+#ifdef CONFIG_VIDEO_S5K4ECGX_V_1_0
+ {
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ if (state->fw.minor == 0) {
+ /* v1.0 sensor have problems sometimes if we write
+ * too much data too fast, so add a sleep. I've
+ * tried various combinations of size/delay. Checking
+ * for a larger size doesn't seem to work reliably, and
+ * a delay of 1ms sometimes isn't enough either.
+ */
+ if (size > 16)
+ msleep(2);
+ }
+ }
+#endif
+ return 0;
+}
+
+/*
+ * Parse the init_reg2 array into a number of register sets that
+ * we can send over as i2c burst writes instead of writing each
+ * entry of init_reg2 as a single 4 byte write. Write the
+ * new data structures and then free them.
+ */
+static int s5k4ecgx_write_init_reg2_burst(struct v4l2_subdev *sd)
+{
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ struct s5k4ecgx_regset *regset_table;
+ struct s5k4ecgx_regset *regset;
+ struct s5k4ecgx_regset *end_regset;
+ u8 *regset_data;
+ u8 *dst_ptr;
+ const u32 *end_src_ptr;
+ bool flag_copied;
+ int init_reg_2_array_size = state->regs->init_reg_2.array_size;
+ int init_reg_2_size = init_reg_2_array_size * sizeof(u32);
+ const u32 *src_ptr = state->regs->init_reg_2.reg;
+ u32 src_value;
+ int err;
+
+ pr_debug("%s : start\n", __func__);
+
+ regset_data = vmalloc(init_reg_2_size);
+ if (regset_data == NULL)
+ return -ENOMEM;
+ regset_table = vmalloc(sizeof(struct s5k4ecgx_regset) *
+ init_reg_2_size);
+ if (regset_table == NULL) {
+ kfree(regset_data);
+ return -ENOMEM;
+ }
+
+ dst_ptr = regset_data;
+ regset = regset_table;
+ end_src_ptr = &state->regs->init_reg_2.reg[init_reg_2_array_size];
+
+ src_value = *src_ptr++;
+ while (src_ptr <= end_src_ptr) {
+ /* initial value for a regset */
+ regset->data = dst_ptr;
+ flag_copied = false;
+ *dst_ptr++ = src_value >> 24;
+ *dst_ptr++ = src_value >> 16;
+ *dst_ptr++ = src_value >> 8;
+ *dst_ptr++ = src_value;
+
+ /* check subsequent values for a data flag (starts with
+ 0x0F12) or something else */
+ do {
+ src_value = *src_ptr++;
+ if ((src_value & 0xFFFF0000) != 0x0F120000) {
+ /* src_value is start of next regset */
+ regset->size = dst_ptr - regset->data;
+ regset++;
+ break;
+ }
+ /* copy the 0x0F12 flag if not done already */
+ if (!flag_copied) {
+ *dst_ptr++ = src_value >> 24;
+ *dst_ptr++ = src_value >> 16;
+ flag_copied = true;
+ }
+ /* copy the data part */
+ *dst_ptr++ = src_value >> 8;
+ *dst_ptr++ = src_value;
+ } while (src_ptr < end_src_ptr);
+ }
+ pr_debug("%s : finished creating table\n", __func__);
+
+ end_regset = regset;
+ pr_debug("%s : first regset = %p, last regset = %p, count = %d\n",
+ __func__, regset_table, regset, end_regset - regset_table);
+ pr_debug("%s : regset_data = %p, end = %p, dst_ptr = %p\n", __func__,
+ regset_data, regset_data + (init_reg_2_size * sizeof(u32)),
+ dst_ptr);
+
+#ifdef CONFIG_VIDEO_S5K4ECGX_DEBUG
+ if (s5k4ecgx_debug_mask & S5K4ECGX_DEBUG_I2C_BURSTS) {
+ int last_regset_end_addr = 0;
+ regset = regset_table;
+ do {
+ s5k4ecgx_dump_regset(regset);
+ if (regset->size > 4) {
+ int regset_addr = (regset->data[2] << 8 |
+ regset->data[3]);
+ if (last_regset_end_addr == regset_addr)
+ pr_info("%s : this regset can be"
+ " combined with previous\n",
+ __func__);
+ last_regset_end_addr = (regset_addr +
+ regset->size - 6);
+ }
+ regset++;
+ } while (regset < end_regset);
+ }
+#endif
+ regset = regset_table;
+ pr_debug("%s : start writing init reg 2 bursts\n", __func__);
+ do {
+ if (regset->size > 4) {
+ /* write the address packet */
+ err = s5k4ecgx_i2c_write_block(sd, regset->data, 4);
+ if (err)
+ break;
+ /* write the data in a burst */
+ err = s5k4ecgx_i2c_write_block(sd, regset->data+4,
+ regset->size-4);
+
+ } else
+ err = s5k4ecgx_i2c_write_block(sd, regset->data,
+ regset->size);
+ if (err)
+ break;
+ regset++;
+ } while (regset < end_regset);
+
+ pr_debug("%s : finished writing init reg 2 bursts\n", __func__);
+
+ vfree(regset_data);
+ vfree(regset_table);
+
+ return err;
+}
+
+static int s5k4ecgx_init_regs(struct v4l2_subdev *sd)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ u16 read_value;
+
+ /* we'd prefer to do this in probe, but the framework hasn't
+ * turned on the camera yet so our i2c operations would fail
+ * if we tried to do it in probe, so we have to do it here
+ * and keep track if we succeeded or not.
+ */
+
+ /* enter read mode */
+ s5k4ecgx_i2c_write_twobyte(client, 0x002C, 0x7000);
+
+ s5k4ecgx_i2c_write_twobyte(client, 0x002E, 0x01A6);
+ s5k4ecgx_i2c_read_twobyte(client, 0x0F12, &read_value);
+
+ pr_info("%s : revision %08X\n", __func__, read_value);
+
+ /* restore write mode */
+ s5k4ecgx_i2c_write_twobyte(client, 0x0028, 0x7000);
+
+#ifdef CONFIG_VIDEO_S5K4ECGX_V_1_0
+ if (read_value == S5K4ECGX_VERSION_1_0) {
+ state->regs = &regs_for_fw_version_1_0;
+ state->initialized = true;
+ return 0;
+ }
+#endif
+#ifdef CONFIG_VIDEO_S5K4ECGX_V_1_1
+ if (read_value == S5K4ECGX_VERSION_1_1) {
+ state->fw.minor = 1;
+ state->regs = &regs_for_fw_version_1_1;
+ state->initialized = true;
+ return 0;
+ }
+#endif
+
+ dev_err(&client->dev, "%s: unknown fw version 0x%x\n",
+ __func__, read_value);
+ return -ENODEV;
+}
+
+static int s5k4ecgx_init(struct v4l2_subdev *sd, u32 val)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+
+ dev_dbg(&client->dev, "%s: start\n", __func__);
+
+ s5k4ecgx_init_parameters(sd);
+
+ if (s5k4ecgx_init_regs(&state->sd) < 0)
+ return -ENODEV;
+
+ dev_dbg(&client->dev, "%s: state->check_dataline : %d\n",
+ __func__, state->check_dataline);
+
+ if (s5k4ecgx_set_from_table(sd, "init reg 1",
+ &state->regs->init_reg_1, 1, 0) < 0)
+ return -EIO;
+
+ /* delay 10ms after wakeup of SOC processor */
+ msleep(10);
+
+ if (s5k4ecgx_write_init_reg2_burst(sd) < 0)
+ return -EIO;
+
+ if (s5k4ecgx_set_from_table(sd, "flash init",
+ &state->regs->flash_init, 1, 0) < 0)
+ return -EIO;
+
+ if (state->check_dataline) {
+ if (s5k4ecgx_set_from_table(sd, "dtp start",
+ &state->regs->dtp_start, 1, 0) < 0)
+ return -EIO;
+ }
+
+ dev_dbg(&client->dev, "%s: end\n", __func__);
+
+ return 0;
+}
+
+static const struct v4l2_subdev_core_ops s5k4ecgx_core_ops = {
+ .init = s5k4ecgx_init, /* initializing API */
+ .g_ctrl = s5k4ecgx_g_ctrl,
+ .s_ctrl = s5k4ecgx_s_ctrl,
+ .s_ext_ctrls = s5k4ecgx_s_ext_ctrls,
+};
+
+static const struct v4l2_subdev_video_ops s5k4ecgx_video_ops = {
+ .s_mbus_fmt = s5k4ecgx_s_mbus_fmt,
+ .enum_framesizes = s5k4ecgx_enum_framesizes,
+ .enum_mbus_fmt = s5k4ecgx_enum_mbus_fmt,
+ .try_mbus_fmt = s5k4ecgx_try_mbus_fmt,
+ .g_parm = s5k4ecgx_g_parm,
+ .s_parm = s5k4ecgx_s_parm,
+};
+
+static const struct v4l2_subdev_ops s5k4ecgx_ops = {
+ .core = &s5k4ecgx_core_ops,
+ .video = &s5k4ecgx_video_ops,
+};
+
+
+/*
+ * s5k4ecgx_probe
+ * Fetching platform data is being done with s_config subdev call.
+ * In probe routine, we just register subdev device
+ */
+static int s5k4ecgx_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct v4l2_subdev *sd;
+ struct s5k4ecgx_state *state;
+ struct s5k4ecgx_platform_data *pdata = client->dev.platform_data;
+
+ if ((pdata == NULL) || (pdata->flash_onoff == NULL)) {
+ dev_err(&client->dev, "%s: bad platform data\n", __func__);
+ return -ENODEV;
+ }
+
+ state = kzalloc(sizeof(struct s5k4ecgx_state), GFP_KERNEL);
+ if (state == NULL)
+ return -ENOMEM;
+
+ mutex_init(&state->ctrl_lock);
+
+ state->runmode = S5K4ECGX_RUNMODE_NOTREADY;
+ sd = &state->sd;
+ strcpy(sd->name, S5K4ECGX_DRIVER_NAME);
+
+ /*
+ * Assign default format and resolution
+ * Use configured default information in platform data
+ * or without them, use default information in driver
+ */
+ state->pix.width = pdata->default_width;
+ state->pix.height = pdata->default_height;
+
+ if (!pdata->pixelformat)
+ state->pix.pixelformat = DEFAULT_PIX_FMT;
+ else
+ state->pix.pixelformat = pdata->pixelformat;
+
+ if (!pdata->freq)
+ state->freq = DEFAULT_MCLK; /* 24MHz default */
+ else
+ state->freq = pdata->freq;
+
+ /* Registering subdev */
+ v4l2_i2c_subdev_init(sd, client, &s5k4ecgx_ops);
+
+ dev_dbg(&client->dev, "5MP camera S5K4ECGX loaded.\n");
+
+ return 0;
+}
+
+static int s5k4ecgx_remove(struct i2c_client *client)
+{
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+
+ v4l2_device_unregister_subdev(sd);
+ mutex_destroy(&state->ctrl_lock);
+ kfree(state);
+
+ dev_dbg(&client->dev, "Unloaded camera sensor S5K4ECGX.\n");
+
+ return 0;
+}
+
+static const struct i2c_device_id s5k4ecgx_id[] = {
+ { S5K4ECGX_DRIVER_NAME, 0 },
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, s5k4ecgx_id);
+
+static struct i2c_driver v4l2_i2c_driver = {
+ .driver.name = S5K4ECGX_DRIVER_NAME,
+ .probe = s5k4ecgx_probe,
+ .remove = s5k4ecgx_remove,
+ .id_table = s5k4ecgx_id,
+};
+
+static int __init v4l2_i2c_drv_init(void)
+{
+ return i2c_add_driver(&v4l2_i2c_driver);
+}
+
+static void __exit v4l2_i2c_drv_cleanup(void)
+{
+ i2c_del_driver(&v4l2_i2c_driver);
+}
+
+module_init(v4l2_i2c_drv_init);
+module_exit(v4l2_i2c_drv_cleanup);
+
+MODULE_DESCRIPTION("LSI S5K4ECGX 5MP SOC camera driver");
+MODULE_AUTHOR("Seok-Young Jang <quartz.jang@samsung.com>");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/media/video/s5k4ecgx_regs_1_0.h b/drivers/media/video/s5k4ecgx_regs_1_0.h
new file mode 100755
index 0000000..afafe7f
--- /dev/null
+++ b/drivers/media/video/s5k4ecgx_regs_1_0.h
@@ -0,0 +1,4797 @@
+/* drivers/media/video/s5k4ecgx_regs_1_0.h
+ *
+ * Driver for s5k4ecgx (5MP Camera) from SEC(LSI), firmware EVT1.0
+ *
+ * Copyright (C) 2010, SAMSUNG ELECTRONICS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+
+#ifndef __S5K4ECGX_REGS_1_0_H__
+#define __S5K4ECGX_REGS_1_0_H__
+
+/* ARM initialization */
+static const u32 s5k4ecgx_init_reg1_v1[] = {
+ /* direct addressing, hw addresses */
+ 0xFCFCD000,
+ 0x00040000,
+ 0xFCFCD000,
+ 0x00100001,
+ 0xFCFCD000,
+ 0x10300000,
+ 0x00140001,
+};
+
+static const u32 s5k4ecgx_init_reg2_v1[] = {
+ /* start analog settings, indirect addressing mode */
+ 0x0028D000,
+
+ 0x002A007A,
+ 0x0F120000,
+
+ 0x002AE406,
+ 0x0F120092,
+
+ 0x002AE410,
+ 0x0F123804,
+
+ 0x002AE420,
+ 0x0F120003,
+ 0x0F120060,
+
+ 0x002AE42E,
+ 0x0F120004,
+
+ 0x002AF400,
+ 0x0F125A3C,
+ 0x0F120023,
+ 0x0F128080,
+ 0x0F1203AF,
+ 0x0F12000A,
+ 0x0F12AA54,
+ 0x0F120040,
+ 0x0F12464E,
+ 0x0F120240,
+ 0x0F120240,
+ 0x0F120040,
+ 0x0F121000,
+ 0x0F125558,
+ 0x0F12D000,
+ 0x0F120010,
+ 0x0F120202,
+ 0x0F120401,
+ 0x0F120022,
+ 0x0F120088,
+ 0x0F12009F,
+ 0x0F120000,
+ 0x0F121800,
+ 0x0F120088,
+ 0x0F120000,
+ 0x0F122428,
+ 0x0F120000,
+ 0x0F1203EE,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x002AF480,
+ 0x0F120004,
+ 0x0F1205B6,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F1205BA,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120007,
+ 0x0F1205BA,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1201F4,
+ 0x0F12024E,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1201F4,
+ 0x0F1205B6,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1201F4,
+ 0x0F1205BA,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1201F4,
+ 0x0F12024F,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120075,
+ 0x0F1200CF,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120075,
+ 0x0F1200D6,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120004,
+ 0x0F1201F4,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1200F0,
+ 0x0F1201F4,
+ 0x0F12029E,
+ 0x0F1205B2,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1201F8,
+ 0x0F120228,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120208,
+ 0x0F120238,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x002AF590,
+ 0x0F120000,
+
+ 0x002AF500,
+ 0x0F120218,
+ 0x0F120238,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F120009,
+ 0x0F1200DE,
+ 0x0F1205C0,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1200DF,
+ 0x0F1200E4,
+ 0x0F1201F8,
+ 0x0F1201FD,
+ 0x0F1205B6,
+ 0x0F1205BB,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1201F8,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120077,
+ 0x0F12007E,
+ 0x0F12024F,
+ 0x0F12025E,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120708,
+ 0x0F12080C,
+
+ 0x002A1082,
+ 0x0F125555,
+ 0x0F125555,
+
+ 0x002A1088,
+ 0x0F12055D,
+
+ 0x002A100E,
+ 0x0F120000,
+
+ /* switch to sw address bank */
+ 0x00287000,
+
+ 0x002A0716,
+ 0x0F120100,
+
+ /* Start of Patch Data for firmware */
+ 0x002A3A10,
+ 0x0F12B5F8,
+ 0x0F124A3E,
+ 0x0F12493E,
+ 0x0F12483F,
+ 0x0F12C004,
+ 0x0F126001,
+ 0x0F124C3E,
+ 0x0F122500,
+ 0x0F128265,
+ 0x0F128025,
+ 0x0F12493D,
+ 0x0F12483E,
+ 0x0F122701,
+ 0x0F12002A,
+ 0x0F12F000,
+ 0x0F12FC38,
+ 0x0F12493C,
+ 0x0F12483D,
+ 0x0F122602,
+ 0x0F12003A,
+ 0x0F12F000,
+ 0x0F12FC32,
+ 0x0F12493B,
+ 0x0F12483C,
+ 0x0F120032,
+ 0x0F122703,
+ 0x0F12F000,
+ 0x0F12FC2C,
+ 0x0F128225,
+ 0x0F12493A,
+ 0x0F12483A,
+ 0x0F122604,
+ 0x0F12003A,
+ 0x0F12F000,
+ 0x0F12FC25,
+ 0x0F12200E,
+ 0x0F128420,
+ 0x0F122701,
+ 0x0F1283E7,
+ 0x0F124937,
+ 0x0F124837,
+ 0x0F120032,
+ 0x0F122405,
+ 0x0F12F000,
+ 0x0F12FC1B,
+ 0x0F124936,
+ 0x0F124836,
+ 0x0F122606,
+ 0x0F120022,
+ 0x0F12F000,
+ 0x0F12FC15,
+ 0x0F124C28,
+ 0x0F123460,
+ 0x0F1281E7,
+ 0x0F124825,
+ 0x0F123824,
+ 0x0F1286C5,
+ 0x0F124932,
+ 0x0F124832,
+ 0x0F120032,
+ 0x0F122707,
+ 0x0F12F000,
+ 0x0F12FC09,
+ 0x0F124931,
+ 0x0F124831,
+ 0x0F122608,
+ 0x0F12003A,
+ 0x0F12F000,
+ 0x0F12FC03,
+ 0x0F124930,
+ 0x0F124830,
+ 0x0F120032,
+ 0x0F122709,
+ 0x0F12F000,
+ 0x0F12FBFD,
+ 0x0F122005,
+ 0x0F128160,
+ 0x0F12492E,
+ 0x0F12482E,
+ 0x0F126281,
+ 0x0F128225,
+ 0x0F128265,
+ 0x0F12482D,
+ 0x0F128320,
+ 0x0F12482D,
+ 0x0F128360,
+ 0x0F120270,
+ 0x0F1283A0,
+ 0x0F122005,
+ 0x0F120300,
+ 0x0F1283E0,
+ 0x0F124828,
+ 0x0F12492A,
+ 0x0F123840,
+ 0x0F126001,
+ 0x0F12492A,
+ 0x0F12482A,
+ 0x0F12240A,
+ 0x0F12003A,
+ 0x0F12F000,
+ 0x0F12FBE3,
+ 0x0F124929,
+ 0x0F124829,
+ 0x0F120022,
+ 0x0F12250B,
+ 0x0F12F000,
+ 0x0F12FBDD,
+ 0x0F124820,
+ 0x0F124927,
+ 0x0F123080,
+ 0x0F126381,
+ 0x0F124927,
+ 0x0F124827,
+ 0x0F12240C,
+ 0x0F12002A,
+ 0x0F12F000,
+ 0x0F12FBD3,
+ 0x0F124926,
+ 0x0F124826,
+ 0x0F120022,
+ 0x0F12F000,
+ 0x0F12FBCE,
+ 0x0F12BCF8,
+ 0x0F12BC08,
+ 0x0F124718,
+ 0x0F120000,
+ 0x0F120174,
+ 0x0F124EC1,
+ 0x0F12FFFE,
+ 0x0F120000,
+ 0x0F121EF0,
+ 0x0F127000,
+ 0x0F124780,
+ 0x0F127000,
+ 0x0F123BF3,
+ 0x0F127000,
+ 0x0F12A1D9,
+ 0x0F120000,
+ 0x0F123B9D,
+ 0x0F127000,
+ 0x0F12A0BD,
+ 0x0F120000,
+ 0x0F123C8D,
+ 0x0F127000,
+ 0x0F12217B,
+ 0x0F120000,
+ 0x0F123CE9,
+ 0x0F127000,
+ 0x0F12E0DF,
+ 0x0F120000,
+ 0x0F123E73,
+ 0x0F127000,
+ 0x0F12053B,
+ 0x0F120000,
+ 0x0F123D71,
+ 0x0F127000,
+ 0x0F12509B,
+ 0x0F120000,
+ 0x0F123FF9,
+ 0x0F127000,
+ 0x0F12D42F,
+ 0x0F120000,
+ 0x0F123EB5,
+ 0x0F127000,
+ 0x0F1249D1,
+ 0x0F120000,
+ 0x0F123F4F,
+ 0x0F127000,
+ 0x0F121E57,
+ 0x0F120000,
+ 0x0F124033,
+ 0x0F127000,
+ 0x0F1200C0,
+ 0x0F127000,
+ 0x0F124E34,
+ 0x0F120000,
+ 0x0F127C53,
+ 0x0F120000,
+ 0x0F1240BF,
+ 0x0F127000,
+ 0x0F1240FB,
+ 0x0F127000,
+ 0x0F12F5D7,
+ 0x0F120000,
+ 0x0F12406F,
+ 0x0F127000,
+ 0x0F12BAB1,
+ 0x0F120000,
+ 0x0F124187,
+ 0x0F127000,
+ 0x0F124129,
+ 0x0F127000,
+ 0x0F12C10D,
+ 0x0F120000,
+ 0x0F124203,
+ 0x0F127000,
+ 0x0F12B231,
+ 0x0F120000,
+ 0x0F12B570,
+ 0x0F12000C,
+ 0x0F126820,
+ 0x0F126865,
+ 0x0F12F000,
+ 0x0F12FB84,
+ 0x0F124BFC,
+ 0x0F120402,
+ 0x0F120C12,
+ 0x0F12819A,
+ 0x0F1248FB,
+ 0x0F1289C1,
+ 0x0F12428A,
+ 0x0F12D305,
+ 0x0F124AFA,
+ 0x0F128986,
+ 0x0F128852,
+ 0x0F1242B2,
+ 0x0F12D300,
+ 0x0F128199,
+ 0x0F128801,
+ 0x0F122900,
+ 0x0F12D008,
+ 0x0F1249F7,
+ 0x0F12002B,
+ 0x0F126E0A,
+ 0x0F122105,
+ 0x0F121C80,
+ 0x0F12F000,
+ 0x0F12FB74,
+ 0x0F126020,
+ 0x0F12E006,
+ 0x0F12899A,
+ 0x0F1248F3,
+ 0x0F12002B,
+ 0x0F122105,
+ 0x0F12F000,
+ 0x0F12FB6C,
+ 0x0F126020,
+ 0x0F126820,
+ 0x0F12BC70,
+ 0x0F12BC08,
+ 0x0F124718,
+ 0x0F12B5F8,
+ 0x0F120004,
+ 0x0F122000,
+ 0x0F129000,
+ 0x0F120020,
+ 0x0F122501,
+ 0x0F123810,
+ 0x0F122601,
+ 0x0F1240A5,
+ 0x0F124086,
+ 0x0F124FEA,
+ 0x0F122C10,
+ 0x0F12DA03,
+ 0x0F128838,
+ 0x0F1243A8,
+ 0x0F128038,
+ 0x0F12E002,
+ 0x0F128878,
+ 0x0F1243B0,
+ 0x0F128078,
+ 0x0F12F000,
+ 0x0F12FB59,
+ 0x0F122C10,
+ 0x0F12DA03,
+ 0x0F128838,
+ 0x0F124328,
+ 0x0F128038,
+ 0x0F12E002,
+ 0x0F128878,
+ 0x0F124330,
+ 0x0F128078,
+ 0x0F1248DA,
+ 0x0F122105,
+ 0x0F128982,
+ 0x0F1248DD,
+ 0x0F12466B,
+ 0x0F12F000,
+ 0x0F12FB41,
+ 0x0F121C41,
+ 0x0F124CD7,
+ 0x0F120049,
+ 0x0F120040,
+ 0x0F121909,
+ 0x0F121900,
+ 0x0F12466B,
+ 0x0F128A89,
+ 0x0F128A80,
+ 0x0F12881A,
+ 0x0F12F000,
+ 0x0F12FB45,
+ 0x0F128A61,
+ 0x0F120540,
+ 0x0F1202C9,
+ 0x0F120D40,
+ 0x0F124301,
+ 0x0F1248D4,
+ 0x0F128081,
+ 0x0F1249D4,
+ 0x0F1248D4,
+ 0x0F123120,
+ 0x0F128BC0,
+ 0x0F128809,
+ 0x0F121841,
+ 0x0F120020,
+ 0x0F123060,
+ 0x0F128A82,
+ 0x0F124291,
+ 0x0F12D205,
+ 0x0F128AC0,
+ 0x0F1249CF,
+ 0x0F127388,
+ 0x0F122001,
+ 0x0F1231A0,
+ 0x0F1270C8,
+ 0x0F12BCF8,
+ 0x0F12BC08,
+ 0x0F124718,
+ 0x0F12B5F8,
+ 0x0F1248C6,
+ 0x0F122200,
+ 0x0F1230A0,
+ 0x0F1281C2,
+ 0x0F126808,
+ 0x0F124669,
+ 0x0F12F000,
+ 0x0F12FB29,
+ 0x0F12466B,
+ 0x0F128818,
+ 0x0F12F000,
+ 0x0F12FB2D,
+ 0x0F120005,
+ 0x0F12466B,
+ 0x0F128858,
+ 0x0F12F000,
+ 0x0F12FB30,
+ 0x0F120004,
+ 0x0F122101,
+ 0x0F121928,
+ 0x0F1202C9,
+ 0x0F121A08,
+ 0x0F120286,
+ 0x0F120029,
+ 0x0F120030,
+ 0x0F12F000,
+ 0x0F12FB2E,
+ 0x0F120005,
+ 0x0F122701,
+ 0x0F1202BF,
+ 0x0F120021,
+ 0x0F120030,
+ 0x0F12F000,
+ 0x0F12FB27,
+ 0x0F1249B5,
+ 0x0F124AB8,
+ 0x0F123140,
+ 0x0F123220,
+ 0x0F12808D,
+ 0x0F128295,
+ 0x0F1280CF,
+ 0x0F1282D7,
+ 0x0F128108,
+ 0x0F128310,
+ 0x0F12E7CE,
+ 0x0F126808,
+ 0x0F120400,
+ 0x0F120C00,
+ 0x0F126849,
+ 0x0F120409,
+ 0x0F120C09,
+ 0x0F124AAA,
+ 0x0F128A12,
+ 0x0F122A00,
+ 0x0F12D00D,
+ 0x0F122300,
+ 0x0F121A89,
+ 0x0F12D400,
+ 0x0F12000B,
+ 0x0F120419,
+ 0x0F120C09,
+ 0x0F1223FF,
+ 0x0F1233C1,
+ 0x0F121810,
+ 0x0F124298,
+ 0x0F12D800,
+ 0x0F120003,
+ 0x0F120418,
+ 0x0F120C00,
+ 0x0F124AA9,
+ 0x0F128150,
+ 0x0F128191,
+ 0x0F124770,
+ 0x0F12B5F8,
+ 0x0F122400,
+ 0x0F124DA7,
+ 0x0F124F9E,
+ 0x0F1248A7,
+ 0x0F128C39,
+ 0x0F128041,
+ 0x0F122101,
+ 0x0F128001,
+ 0x0F12F000,
+ 0x0F12FAFB,
+ 0x0F1248A5,
+ 0x0F128BC0,
+ 0x0F12F000,
+ 0x0F12FAFF,
+ 0x0F12260D,
+ 0x0F120736,
+ 0x0F122000,
+ 0x0F1200E1,
+ 0x0F1219CA,
+ 0x0F120041,
+ 0x0F12194B,
+ 0x0F12199B,
+ 0x0F12881B,
+ 0x0F121851,
+ 0x0F12844B,
+ 0x0F121C40,
+ 0x0F120400,
+ 0x0F120C00,
+ 0x0F122804,
+ 0x0F12D3F4,
+ 0x0F123508,
+ 0x0F12042D,
+ 0x0F120C2D,
+ 0x0F121C64,
+ 0x0F120424,
+ 0x0F120C24,
+ 0x0F122C07,
+ 0x0F12D3E9,
+ 0x0F12E78A,
+ 0x0F12B5F0,
+ 0x0F12B087,
+ 0x0F126808,
+ 0x0F129006,
+ 0x0F126848,
+ 0x0F120405,
+ 0x0F120C2D,
+ 0x0F126888,
+ 0x0F120403,
+ 0x0F120C1B,
+ 0x0F124892,
+ 0x0F128B80,
+ 0x0F122800,
+ 0x0F12D100,
+ 0x0F122300,
+ 0x0F12001C,
+ 0x0F124A90,
+ 0x0F12466E,
+ 0x0F121E91,
+ 0x0F121E88,
+ 0x0F12C607,
+ 0x0F12498F,
+ 0x0F120023,
+ 0x0F122207,
+ 0x0F120028,
+ 0x0F12F000,
+ 0x0F12FAD3,
+ 0x0F12487E,
+ 0x0F128BC1,
+ 0x0F122900,
+ 0x0F12D030,
+ 0x0F122100,
+ 0x0F124888,
+ 0x0F124A7B,
+ 0x0F12380A,
+ 0x0F1288C0,
+ 0x0F1200C3,
+ 0x0F12189A,
+ 0x0F124696,
+ 0x0F124A86,
+ 0x0F121C40,
+ 0x0F12189B,
+ 0x0F12469C,
+ 0x0F124B76,
+ 0x0F1200C0,
+ 0x0F1218C6,
+ 0x0F121887,
+ 0x0F120048,
+ 0x0F124672,
+ 0x0F124663,
+ 0x0F121812,
+ 0x0F12181B,
+ 0x0F128C52,
+ 0x0F128EDB,
+ 0x0F12435A,
+ 0x0F120092,
+ 0x0F120C15,
+ 0x0F124A6F,
+ 0x0F121882,
+ 0x0F12235A,
+ 0x0F12529D,
+ 0x0F121833,
+ 0x0F121838,
+ 0x0F128C5B,
+ 0x0F128EC0,
+ 0x0F124343,
+ 0x0F120098,
+ 0x0F120C00,
+ 0x0F123260,
+ 0x0F128050,
+ 0x0F121C49,
+ 0x0F120409,
+ 0x0F120C09,
+ 0x0F122904,
+ 0x0F12D3E3,
+ 0x0F124A66,
+ 0x0F12325A,
+ 0x0F120013,
+ 0x0F123308,
+ 0x0F12E00A,
+ 0x0F124870,
+ 0x0F124971,
+ 0x0F12380A,
+ 0x0F1288C0,
+ 0x0F1200C2,
+ 0x0F121852,
+ 0x0F123236,
+ 0x0F121C40,
+ 0x0F1200C0,
+ 0x0F121843,
+ 0x0F123336,
+ 0x0F122100,
+ 0x0F124864,
+ 0x0F123020,
+ 0x0F124684,
+ 0x0F124E69,
+ 0x0F120048,
+ 0x0F123E0A,
+ 0x0F128937,
+ 0x0F125A15,
+ 0x0F128976,
+ 0x0F12437D,
+ 0x0F125A1F,
+ 0x0F124377,
+ 0x0F124E65,
+ 0x0F1219ED,
+ 0x0F121986,
+ 0x0F123660,
+ 0x0F1289F6,
+ 0x0F124366,
+ 0x0F1219AD,
+ 0x0F12022D,
+ 0x0F120C2D,
+ 0x0F12AE04,
+ 0x0F125235,
+ 0x0F124666,
+ 0x0F127C76,
+ 0x0F124375,
+ 0x0F129E06,
+ 0x0F12026D,
+ 0x0F120C2D,
+ 0x0F125235,
+ 0x0F121C49,
+ 0x0F122904,
+ 0x0F12D3E1,
+ 0x0F12B007,
+ 0x0F12BCF0,
+ 0x0F12BC08,
+ 0x0F124718,
+ 0x0F12B5F8,
+ 0x0F120004,
+ 0x0F12F7FF,
+ 0x0F12FF53,
+ 0x0F122101,
+ 0x0F12000D,
+ 0x0F120020,
+ 0x0F123810,
+ 0x0F124081,
+ 0x0F1240A5,
+ 0x0F124F4A,
+ 0x0F12000E,
+ 0x0F122C10,
+ 0x0F12DA03,
+ 0x0F128838,
+ 0x0F1243A8,
+ 0x0F128038,
+ 0x0F12E002,
+ 0x0F128878,
+ 0x0F1243B0,
+ 0x0F128078,
+ 0x0F12F000,
+ 0x0F12FA5E,
+ 0x0F122C10,
+ 0x0F12DA03,
+ 0x0F128838,
+ 0x0F124328,
+ 0x0F128038,
+ 0x0F12E6EC,
+ 0x0F128878,
+ 0x0F124330,
+ 0x0F128078,
+ 0x0F12E6E8,
+ 0x0F12B5F8,
+ 0x0F120004,
+ 0x0F124F48,
+ 0x0F124949,
+ 0x0F1278FA,
+ 0x0F122001,
+ 0x0F122A00,
+ 0x0F12D102,
+ 0x0F122000,
+ 0x0F1286C8,
+ 0x0F12E003,
+ 0x0F127AFA,
+ 0x0F122A00,
+ 0x0F12D000,
+ 0x0F1286C8,
+ 0x0F122101,
+ 0x0F12000D,
+ 0x0F120020,
+ 0x0F123810,
+ 0x0F124081,
+ 0x0F1240A5,
+ 0x0F12000E,
+ 0x0F122C10,
+ 0x0F12DA04,
+ 0x0F124932,
+ 0x0F128808,
+ 0x0F1243A8,
+ 0x0F128008,
+ 0x0F12E003,
+ 0x0F124930,
+ 0x0F128848,
+ 0x0F1243B0,
+ 0x0F128048,
+ 0x0F12F000,
+ 0x0F12FA39,
+ 0x0F122C10,
+ 0x0F12DA04,
+ 0x0F12482C,
+ 0x0F128801,
+ 0x0F124329,
+ 0x0F128001,
+ 0x0F12E003,
+ 0x0F124829,
+ 0x0F128841,
+ 0x0F124331,
+ 0x0F128041,
+ 0x0F124934,
+ 0x0F128B08,
+ 0x0F1206C2,
+ 0x0F12D50A,
+ 0x0F127ABA,
+ 0x0F120652,
+ 0x0F12D507,
+ 0x0F122210,
+ 0x0F124390,
+ 0x0F128308,
+ 0x0F124830,
+ 0x0F127AF9,
+ 0x0F126B00,
+ 0x0F12F000,
+ 0x0F12FA27,
+ 0x0F12481C,
+ 0x0F123060,
+ 0x0F1289C0,
+ 0x0F122800,
+ 0x0F12D009,
+ 0x0F1278F8,
+ 0x0F122800,
+ 0x0F12D006,
+ 0x0F127AF8,
+ 0x0F122800,
+ 0x0F12D003,
+ 0x0F127AB8,
+ 0x0F122140,
+ 0x0F124308,
+ 0x0F1272B8,
+ 0x0F12E69B,
+ 0x0F12B5F8,
+ 0x0F120004,
+ 0x0F124826,
+ 0x0F128981,
+ 0x0F122900,
+ 0x0F12D007,
+ 0x0F128940,
+ 0x0F122800,
+ 0x0F12D104,
+ 0x0F12481E,
+ 0x0F1222BF,
+ 0x0F127A81,
+ 0x0F124011,
+ 0x0F127281,
+ 0x0F122101,
+ 0x0F12000D,
+ 0x0F120020,
+ 0x0F123810,
+ 0x0F124081,
+ 0x0F1240A5,
+ 0x0F124F0E,
+ 0x0F12000E,
+ 0x0F122C10,
+ 0x0F12DA03,
+ 0x0F128838,
+ 0x0F1243A8,
+ 0x0F128038,
+ 0x0F12E002,
+ 0x0F128878,
+ 0x0F1243B0,
+ 0x0F128078,
+ 0x0F12F000,
+ 0x0F12F9FE,
+ 0x0F122C10,
+ 0x0F12DA2D,
+ 0x0F128838,
+ 0x0F124328,
+ 0x0F128038,
+ 0x0F12E674,
+ 0x0F1221C0,
+ 0x0F127000,
+ 0x0F124780,
+ 0x0F127000,
+ 0x0F122D00,
+ 0x0F127000,
+ 0x0F122AD0,
+ 0x0F127000,
+ 0x0F120924,
+ 0x0F127000,
+ 0x0F121100,
+ 0x0F12D000,
+ 0x0F12E300,
+ 0x0F12D000,
+ 0x0F1229D0,
+ 0x0F127000,
+ 0x0F122C30,
+ 0x0F127000,
+ 0x0F125000,
+ 0x0F12D000,
+ 0x0F12A006,
+ 0x0F120000,
+ 0x0F12A000,
+ 0x0F12D000,
+ 0x0F1206F8,
+ 0x0F127000,
+ 0x0F120888,
+ 0x0F127000,
+ 0x0F1221DA,
+ 0x0F127000,
+ 0x0F1208AC,
+ 0x0F127000,
+ 0x0F1220BC,
+ 0x0F127000,
+ 0x0F121ECC,
+ 0x0F127000,
+ 0x0F122FA4,
+ 0x0F127000,
+ 0x0F12235C,
+ 0x0F127000,
+ 0x0F120234,
+ 0x0F127000,
+ 0x0F128878,
+ 0x0F124330,
+ 0x0F128078,
+ 0x0F12E646,
+ 0x0F12B570,
+ 0x0F124D99,
+ 0x0F124C99,
+ 0x0F128B28,
+ 0x0F120701,
+ 0x0F12D507,
+ 0x0F122108,
+ 0x0F124388,
+ 0x0F128328,
+ 0x0F124997,
+ 0x0F126B20,
+ 0x0F1268C9,
+ 0x0F12F000,
+ 0x0F12F9C4,
+ 0x0F128B28,
+ 0x0F1206C1,
+ 0x0F12D50A,
+ 0x0F124994,
+ 0x0F127A8A,
+ 0x0F120652,
+ 0x0F12D406,
+ 0x0F122210,
+ 0x0F124390,
+ 0x0F128328,
+ 0x0F127AC9,
+ 0x0F126B20,
+ 0x0F12F000,
+ 0x0F12F9A6,
+ 0x0F12E5DC,
+ 0x0F12B570,
+ 0x0F124D8E,
+ 0x0F124C8F,
+ 0x0F1288EA,
+ 0x0F122A14,
+ 0x0F12D101,
+ 0x0F122200,
+ 0x0F1281A2,
+ 0x0F12F000,
+ 0x0F12F9B3,
+ 0x0F1288E8,
+ 0x0F122821,
+ 0x0F12D10F,
+ 0x0F128B28,
+ 0x0F122800,
+ 0x0F12D10C,
+ 0x0F12200C,
+ 0x0F125E20,
+ 0x0F128961,
+ 0x0F124288,
+ 0x0F12DC07,
+ 0x0F124882,
+ 0x0F123880,
+ 0x0F126B80,
+ 0x0F12F000,
+ 0x0F12F9AB,
+ 0x0F1289A0,
+ 0x0F121C40,
+ 0x0F1281A0,
+ 0x0F12E5BE,
+ 0x0F12B5F8,
+ 0x0F120004,
+ 0x0F122101,
+ 0x0F12000D,
+ 0x0F120020,
+ 0x0F123810,
+ 0x0F124081,
+ 0x0F1240A5,
+ 0x0F124F7E,
+ 0x0F12000E,
+ 0x0F122C10,
+ 0x0F12DA03,
+ 0x0F128838,
+ 0x0F1243A8,
+ 0x0F128038,
+ 0x0F12E002,
+ 0x0F128878,
+ 0x0F1243B0,
+ 0x0F128078,
+ 0x0F12F000,
+ 0x0F12F99A,
+ 0x0F122C10,
+ 0x0F12DA03,
+ 0x0F128838,
+ 0x0F124328,
+ 0x0F128038,
+ 0x0F12E002,
+ 0x0F128878,
+ 0x0F124330,
+ 0x0F128078,
+ 0x0F124874,
+ 0x0F128800,
+ 0x0F120400,
+ 0x0F12D504,
+ 0x0F12F000,
+ 0x0F12F993,
+ 0x0F12496E,
+ 0x0F122012,
+ 0x0F1280C8,
+ 0x0F12E5E3,
+ 0x0F12B570,
+ 0x0F124E6A,
+ 0x0F128881,
+ 0x0F1278F2,
+ 0x0F124D6E,
+ 0x0F124C6A,
+ 0x0F122A00,
+ 0x0F12D005,
+ 0x0F128A62,
+ 0x0F121889,
+ 0x0F128081,
+ 0x0F128B61,
+ 0x0F128029,
+ 0x0F12E004,
+ 0x0F128A22,
+ 0x0F121889,
+ 0x0F128081,
+ 0x0F128B21,
+ 0x0F128029,
+ 0x0F12F000,
+ 0x0F12F982,
+ 0x0F1278F0,
+ 0x0F122800,
+ 0x0F12D002,
+ 0x0F128BE0,
+ 0x0F1282E8,
+ 0x0F12E57B,
+ 0x0F128BA0,
+ 0x0F1282E8,
+ 0x0F12E578,
+ 0x0F12B430,
+ 0x0F12680B,
+ 0x0F12684D,
+ 0x0F12688C,
+ 0x0F1268C8,
+ 0x0F124A5F,
+ 0x0F128054,
+ 0x0F124958,
+ 0x0F1278CC,
+ 0x0F124959,
+ 0x0F122C00,
+ 0x0F12D003,
+ 0x0F128A49,
+ 0x0F121808,
+ 0x0F128090,
+ 0x0F12E002,
+ 0x0F128A09,
+ 0x0F121808,
+ 0x0F128090,
+ 0x0F1280D3,
+ 0x0F128115,
+ 0x0F12BC30,
+ 0x0F124770,
+ 0x0F12B5F3,
+ 0x0F120004,
+ 0x0F12B081,
+ 0x0F129802,
+ 0x0F126800,
+ 0x0F120600,
+ 0x0F120E00,
+ 0x0F122201,
+ 0x0F120015,
+ 0x0F120021,
+ 0x0F123910,
+ 0x0F12408A,
+ 0x0F1240A5,
+ 0x0F124F4D,
+ 0x0F120016,
+ 0x0F122C10,
+ 0x0F12DA03,
+ 0x0F128839,
+ 0x0F1243A9,
+ 0x0F128039,
+ 0x0F12E002,
+ 0x0F128879,
+ 0x0F1243B1,
+ 0x0F128079,
+ 0x0F12F000,
+ 0x0F12F950,
+ 0x0F122C10,
+ 0x0F12DA03,
+ 0x0F128839,
+ 0x0F124329,
+ 0x0F128039,
+ 0x0F12E002,
+ 0x0F128879,
+ 0x0F124331,
+ 0x0F128079,
+ 0x0F124946,
+ 0x0F128809,
+ 0x0F122900,
+ 0x0F12D102,
+ 0x0F12F000,
+ 0x0F12F949,
+ 0x0F122000,
+ 0x0F129902,
+ 0x0F126008,
+ 0x0F12BCFE,
+ 0x0F12BC08,
+ 0x0F124718,
+ 0x0F12B538,
+ 0x0F124C40,
+ 0x0F1289E5,
+ 0x0F12F000,
+ 0x0F12F946,
+ 0x0F121FE8,
+ 0x0F1238FD,
+ 0x0F12D132,
+ 0x0F1289E0,
+ 0x0F121FC1,
+ 0x0F1239FF,
+ 0x0F12D12E,
+ 0x0F12483C,
+ 0x0F1269E1,
+ 0x0F126840,
+ 0x0F121809,
+ 0x0F120200,
+ 0x0F12F000,
+ 0x0F12F8BA,
+ 0x0F120400,
+ 0x0F120C00,
+ 0x0F124A38,
+ 0x0F122305,
+ 0x0F120011,
+ 0x0F123114,
+ 0x0F12F000,
+ 0x0F12F938,
+ 0x0F120002,
+ 0x0F1266E0,
+ 0x0F124D34,
+ 0x0F128CE0,
+ 0x0F123D14,
+ 0x0F1289E9,
+ 0x0F12F000,
+ 0x0F12F88A,
+ 0x0F12466B,
+ 0x0F128018,
+ 0x0F128A29,
+ 0x0F128D20,
+ 0x0F126EE2,
+ 0x0F12F000,
+ 0x0F12F883,
+ 0x0F12466B,
+ 0x0F128058,
+ 0x0F120021,
+ 0x0F129800,
+ 0x0F123170,
+ 0x0F12F000,
+ 0x0F12F92A,
+ 0x0F120020,
+ 0x0F123060,
+ 0x0F128A02,
+ 0x0F124928,
+ 0x0F123980,
+ 0x0F12808A,
+ 0x0F128A42,
+ 0x0F1280CA,
+ 0x0F128A80,
+ 0x0F128108,
+ 0x0F12BC38,
+ 0x0F12BC08,
+ 0x0F124718,
+ 0x0F12B5F8,
+ 0x0F120004,
+ 0x0F126808,
+ 0x0F120400,
+ 0x0F120C00,
+ 0x0F122201,
+ 0x0F120015,
+ 0x0F120021,
+ 0x0F123910,
+ 0x0F12408A,
+ 0x0F1240A5,
+ 0x0F124F17,
+ 0x0F120016,
+ 0x0F122C10,
+ 0x0F12DA03,
+ 0x0F128839,
+ 0x0F1243A9,
+ 0x0F128039,
+ 0x0F12E002,
+ 0x0F128879,
+ 0x0F1243B1,
+ 0x0F128079,
+ 0x0F12F000,
+ 0x0F12F90D,
+ 0x0F122C10,
+ 0x0F12DA03,
+ 0x0F128838,
+ 0x0F124328,
+ 0x0F128038,
+ 0x0F12E002,
+ 0x0F128878,
+ 0x0F124330,
+ 0x0F128078,
+ 0x0F12480D,
+ 0x0F128800,
+ 0x0F120400,
+ 0x0F12D507,
+ 0x0F124B12,
+ 0x0F127819,
+ 0x0F124A12,
+ 0x0F127810,
+ 0x0F127018,
+ 0x0F127011,
+ 0x0F124905,
+ 0x0F128188,
+ 0x0F12E513,
+ 0x0F120000,
+ 0x0F122FA4,
+ 0x0F127000,
+ 0x0F12235C,
+ 0x0F127000,
+ 0x0F120140,
+ 0x0F127000,
+ 0x0F1220BC,
+ 0x0F127000,
+ 0x0F122DF0,
+ 0x0F127000,
+ 0x0F1247E0,
+ 0x0F127000,
+ 0x0F121100,
+ 0x0F12D000,
+ 0x0F122EE2,
+ 0x0F127000,
+ 0x0F12F400,
+ 0x0F12D000,
+ 0x0F123200,
+ 0x0F12D000,
+ 0x0F1216DE,
+ 0x0F127000,
+ 0x0F1236F8,
+ 0x0F127000,
+ 0x0F122B90,
+ 0x0F127000,
+ 0x0F1217B4,
+ 0x0F127000,
+ 0x0F122EDD,
+ 0x0F127000,
+ 0x0F122EDE,
+ 0x0F127000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F1213D5,
+ 0x0F120001,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F12A083,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F12A035,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F12A1D9,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F122D27,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F127D47,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F127AB1,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F127ACB,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12F004,
+ 0x0F12E51F,
+ 0x0F122630,
+ 0x0F120001,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F12ED4D,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F12EDDB,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F124EB5,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F12053B,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F1249D1,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F12D411,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F121E57,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F122603,
+ 0x0F120001,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F12BC3D,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F122601,
+ 0x0F120001,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F12BAB1,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F12B89F,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F12F077,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F12C10D,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F12C0C9,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F12EAF9,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F122E61,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F12E86B,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F12B231,
+ 0x0F120000,
+ /* End of Patch Data*/
+
+ /* switch to firmware address bank */
+ 0x0028D000,
+ 0x002A1000,
+ 0x0F120001,
+ /* End of factory settings*/
+
+ /* Switch to sw address bank */
+ 0x00287000,
+
+ 0x002A479E,
+ 0x0F120001,
+
+ 0x002A1432,
+ 0x0F120000,
+
+ 0x002A47EE,
+ 0x0F120001,
+ 0x0F12000A,
+ 0x0F120014,
+ 0x0F120070,
+ 0x0F120005,
+ 0x0F125A3C,
+
+ 0x002A4780,
+ 0x0F120000,
+ 0x0F120014,
+ 0x0F1200D2,
+ 0x0F120384,
+ 0x0F1207D0,
+ 0x0F121388,
+ 0x0F120180,
+ 0x0F120196,
+ 0x0F120054,
+ 0x0F120001,
+ 0x0F1201CC,
+ 0x0F1201CC,
+ 0x0F1201CC,
+ 0x0F1201CC,
+ 0x0F1201CC,
+
+ 0x002A0EF0,
+ 0x0F120001,
+
+ 0x002A0EF6,
+ 0x0F120002,
+
+ 0x002A1A84,
+ 0x0F12001C,
+
+ 0x002A01F8,
+ 0x0F120000,
+
+ 0x002A16E4,
+ 0x0F120100,
+
+ 0x002A01FA,
+ 0x0F120003,
+ 0x0F120000,
+
+ 0x002A0200,
+ 0x0F120061,
+
+ 0x002A0208,
+ 0x0F122F0C,
+ 0x0F120190,
+
+ 0x002A028E,
+ 0x0F120100,
+ 0x0F1200E3,
+ 0x0F120200,
+ 0x0F120238,
+ 0x0F1201C6,
+ 0x0F120166,
+ 0x0F120074,
+ 0x0F120132,
+ 0x0F120001,
+
+ 0x002A0702,
+ 0x0F1200FF,
+
+ 0x002A1600,
+ 0x0F120000,
+
+ 0x002A0712,
+ 0x0F120001,
+
+ 0x002A160C,
+ 0x0F129002,
+
+ 0x002A1616,
+ 0x0F120003,
+
+ 0x002A15A4,
+ 0x0F120902,
+
+ 0x002A1618,
+ 0x0F120000,
+
+ 0x002A1610,
+ 0x0F120003,
+
+ 0x002A1602,
+ 0x0F1200E5,
+ 0x0F120098,
+
+ 0x002A1598,
+ 0x0F120000,
+ 0x0F12D000,
+
+ 0x002A165E,
+ 0x0F12FF95,
+
+ 0x002A162E,
+ 0x0F120280,
+
+ 0x002A163A,
+ 0x0F1203A0,
+ 0x0F120320,
+
+ 0x002A1680,
+ 0x0F120030,
+
+ 0x002A16A4,
+ 0x0F120060,
+
+ 0x002A1698,
+ 0x0F120010,
+
+ 0x002A161A,
+ 0x0F120000,
+
+ 0x002A15AA,
+ 0x0F12003C,
+ 0x0F120018,
+ 0x0F12002A,
+ 0x0F120030,
+ 0x0F120036,
+ 0x0F12003C,
+ 0x0F120042,
+ 0x0F120048,
+ 0x0F12004E,
+ 0x0F120054,
+ 0x0F12005A,
+ 0x0F120060,
+ 0x0F120066,
+ 0x0F12006C,
+ 0x0F120072,
+ 0x0F120078,
+ 0x0F12007E,
+ 0x0F120084,
+ 0x0F12008A,
+ 0x0F120090,
+ 0x0F120096,
+ 0x0F12009C,
+ 0x0F1200A2,
+ 0x0F1200A8,
+ 0x0F1200AE,
+ 0x0F1200B4,
+ 0x0F1200BA,
+
+ 0x002A16E6,
+ 0x0F128000,
+ 0x0F120006,
+ 0x0F123FF0,
+ 0x0F1203E8,
+ 0x0F120000,
+ 0x0F120080,
+ 0x0F120009,
+ 0x0F120020,
+ 0x0F120040,
+ 0x0F120080,
+ 0x0F1200C0,
+ 0x0F1200E0,
+
+ 0x002A0286,
+ 0x0F120003,
+
+ 0x002A11B4,
+ 0x0F12012C,
+ 0x0F120121,
+
+ 0x002A1A00,
+ 0x0F12192E,
+ 0x0F127000,
+
+ 0x002A185C,
+ 0x0F120004,
+ 0x0F1209D1,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F1209D5,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120008,
+ 0x0F1209D5,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1202AA,
+ 0x0F120326,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1202AA,
+ 0x0F1209D1,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1202AA,
+ 0x0F1209D5,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1202AA,
+ 0x0F120327,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120008,
+ 0x0F120084,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120008,
+ 0x0F12008D,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120008,
+ 0x0F1202AA,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1200AA,
+ 0x0F1202AA,
+ 0x0F1203AD,
+ 0x0F1209CD,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1202AE,
+ 0x0F1202DE,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1202BE,
+ 0x0F1202EE,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1202CE,
+ 0x0F1202EE,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F120009,
+ 0x0F120095,
+ 0x0F1209DB,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120096,
+ 0x0F12009B,
+ 0x0F1202AE,
+ 0x0F1202B3,
+ 0x0F1209D1,
+ 0x0F1209D6,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1202AE,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120009,
+ 0x0F120010,
+ 0x0F120327,
+ 0x0F120336,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120004,
+ 0x0F1205B6,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F1205BA,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120007,
+ 0x0F1205BA,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1201F4,
+ 0x0F12024E,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1201F4,
+ 0x0F1205B6,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1201F4,
+ 0x0F1205BA,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1201F4,
+ 0x0F12024F,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120075,
+ 0x0F1200CF,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120075,
+ 0x0F1200D6,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120004,
+ 0x0F1201F4,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1200F0,
+ 0x0F1201F4,
+ 0x0F12029E,
+ 0x0F1205B2,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1201F8,
+ 0x0F120228,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120208,
+ 0x0F120238,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120218,
+ 0x0F120238,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F120009,
+ 0x0F1200DE,
+ 0x0F1205C0,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1200DF,
+ 0x0F1200E4,
+ 0x0F1201F8,
+ 0x0F1201FD,
+ 0x0F1205B6,
+ 0x0F1205BB,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1201F8,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120077,
+ 0x0F12007E,
+ 0x0F12024F,
+ 0x0F12025E,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x002A1836,
+ 0x0F120002,
+ 0x0F120000,
+ 0x0F120003,
+
+ 0x002A183E,
+ 0x0F120FB0,
+
+ 0x002A184C,
+ 0x0F120060,
+ 0x0F120060,
+ 0x0F1205C0,
+ 0x0F1205C0,
+
+ 0x002A1A8A,
+ 0x0F128080,
+ 0x0F120080,
+
+ 0x002A1A80,
+ 0x0F120000,
+
+ 0x002A1A12,
+ 0x0F120000,
+
+ 0x002A1842,
+ 0x0F120004,
+
+ 0x002A1A0A,
+ 0x0F12009A,
+
+ 0x002A3776,
+ 0x0F12024C,
+
+ 0x002A0EB2,
+ 0x0F120000,
+
+ 0x002A08C6,
+ 0x0F120001,
+
+ 0x002A08A4,
+ 0x0F120001,
+
+ 0x002A08E2,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124500,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+
+ 0x002A08E0,
+ 0x0F120001,
+
+ 0x002A1456,
+ 0x0F120000,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120000,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120201,
+ 0x0F120303,
+ 0x0F120303,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120403,
+ 0x0F120304,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120403,
+ 0x0F120304,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120403,
+ 0x0F120304,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120303,
+ 0x0F120303,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120202,
+ 0x0F120202,
+ 0x0F120102,
+
+ 0x002A1448,
+ 0x0F12003C,
+
+ 0x002A144E,
+ 0x0F12000F,
+
+ 0x002A0580,
+ 0x0F123520,
+ 0x0F120000,
+ 0x0F12C350,
+ 0x0F120000,
+ 0x0F123520,
+ 0x0F120000,
+ 0x0F12C350,
+ 0x0F120000,
+ 0x0F120470,
+ 0x0F120C00,
+ 0x0F120100,
+ 0x0F121000,
+
+ 0x002A0538,
+ 0x0F120111,
+ 0x0F1200EF,
+
+ 0x002A05FC,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F120600,
+ 0x0F120100,
+ 0x0F120001,
+ 0x0F120000,
+ 0x0F120A3C,
+ 0x0F120000,
+ 0x0F120D04,
+ 0x0F120000,
+ 0x0F124008,
+ 0x0F120000,
+ 0x0F127000,
+ 0x0F120000,
+ 0x0F129C00,
+ 0x0F120000,
+ 0x0F12AD00,
+ 0x0F120001,
+ 0x0F12F1D4,
+ 0x0F120002,
+ 0x0F12DC00,
+ 0x0F120005,
+ 0x0F12DC00,
+ 0x0F120005,
+ 0x0F120001,
+ 0x0F120000,
+ 0x0F120A3C,
+ 0x0F120000,
+ 0x0F120D05,
+ 0x0F120000,
+ 0x0F123408,
+ 0x0F120000,
+ 0x0F123408,
+ 0x0F120000,
+ 0x0F126810,
+ 0x0F120000,
+ 0x0F128214,
+ 0x0F120000,
+ 0x0F12C350,
+ 0x0F120000,
+ 0x0F12C350,
+ 0x0F120000,
+ 0x0F12C350,
+ 0x0F120000,
+ 0x0F120650,
+ 0x0F120100,
+
+ 0x002A06AC,
+ 0x0F12452C,
+ 0x0F120004,
+
+ 0x002A0280,
+ 0x0F120001,
+
+ 0x002A05C4,
+ 0x0F120000,
+
+ 0x002A0476,
+ 0x0F120001,
+ 0x0F120280,
+ 0x0F1201E0,
+ 0x0F120005,
+
+ 0x002A01F4,
+ 0x0F125DC0,
+
+ 0x002A020E,
+ 0x0F120002,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x002A0216,
+ 0x0F123A98,
+ 0x0F124F1A,
+ 0x0F124F1A,
+ 0x0F124F1A,
+ 0x0F124F1A,
+ 0x0F124F1A,
+
+ 0x002A0228,
+ 0x0F120001,
+
+ 0x002A02A0,
+ 0x0F120280,
+ 0x0F1201E0,
+ 0x0F120005,
+ 0x0F124F1A,
+ 0x0F124F1A,
+
+ 0x002A02AE,
+ 0x0F120052,
+
+ 0x002A02B6,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F12029A,
+ 0x0F12014D,
+
+ 0x002A02AA,
+ 0x0F120080,
+
+ 0x002A024C,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120010,
+ 0x0F12000C,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120010,
+ 0x0F12000C,
+
+ 0x002A048E,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x002A025E,
+ 0x0F120001,
+ 0x0F120001,
+
+ 0x002A0392,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120009,
+ 0x0F124F1A,
+ 0x0F124F1A,
+
+ 0x002A03A0,
+ 0x0F120002,
+
+ 0x002A03A8,
+ 0x0F120001,
+ 0x0F120000,
+ 0x0F120002,
+ 0x0F120535,
+ 0x0F12029A,
+
+ 0x002A039C,
+ 0x0F120080,
+
+ 0x002A0476,
+ 0x0F120001,
+ 0x0F120280,
+ 0x0F1201E0,
+ 0x0F120005,
+
+ 0x002A0262,
+ 0x0F120000,
+
+ 0x002A0266,
+ 0x0F120001,
+
+ 0x002A024A,
+ 0x0F120001,
+
+ 0x002A0264,
+ 0x0F120001,
+
+ 0x002A026C,
+ 0x0F120001,
+
+ 0x002A023A,
+ 0x0F120001,
+ 0x0F120001,
+
+ 0x002A0472,
+ 0x0F12005F,
+ 0x0F12005F,
+
+ 0x002A0FE0,
+ 0x0F1203B8,
+ 0x0F1203CE,
+ 0x0F120350,
+ 0x0F1203C4,
+ 0x0F1202F2,
+ 0x0F120394,
+ 0x0F1202C0,
+ 0x0F120364,
+ 0x0F12029E,
+ 0x0F120334,
+ 0x0F12027C,
+ 0x0F120312,
+ 0x0F12025E,
+ 0x0F1202F2,
+ 0x0F120246,
+ 0x0F1202D0,
+ 0x0F120230,
+ 0x0F1202B0,
+ 0x0F120218,
+ 0x0F12029E,
+ 0x0F120208,
+ 0x0F120290,
+ 0x0F1201F8,
+ 0x0F120284,
+ 0x0F1201E8,
+ 0x0F120276,
+ 0x0F1201DA,
+ 0x0F12026A,
+ 0x0F1201CE,
+ 0x0F12025E,
+ 0x0F1201EC,
+ 0x0F12022E,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120005,
+
+ 0x002A1034,
+ 0x0F120010,
+
+ 0x002A1038,
+ 0x0F120126,
+
+ 0x002A103C,
+ 0x0F12026C,
+ 0x0F12029A,
+ 0x0F12025C,
+ 0x0F1202B6,
+ 0x0F12024E,
+ 0x0F1202C0,
+ 0x0F120240,
+ 0x0F1202BE,
+ 0x0F12023A,
+ 0x0F1202B4,
+ 0x0F12023A,
+ 0x0F1202AA,
+ 0x0F120240,
+ 0x0F12029E,
+ 0x0F12025C,
+ 0x0F120294,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120004,
+
+ 0x002A1070,
+ 0x0F120008,
+
+ 0x002A1074,
+ 0x0F1201E2,
+
+ 0x002A1078,
+ 0x0F120350,
+ 0x0F120422,
+ 0x0F1202C4,
+ 0x0F120452,
+ 0x0F120278,
+ 0x0F12041C,
+ 0x0F120230,
+ 0x0F1203EE,
+ 0x0F1201F0,
+ 0x0F120392,
+ 0x0F1201C0,
+ 0x0F120340,
+ 0x0F120194,
+ 0x0F120302,
+ 0x0F12016E,
+ 0x0F1202C2,
+ 0x0F120148,
+ 0x0F120286,
+ 0x0F12018A,
+ 0x0F120242,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120006,
+
+ 0x002A10AC,
+ 0x0F12000A,
+
+ 0x002A10B0,
+ 0x0F120106,
+
+ 0x002A10B4,
+ 0x0F120380,
+ 0x0F120000,
+ 0x0F120168,
+ 0x0F120000,
+ 0x0F122D90,
+ 0x0F120000,
+
+ 0x002A1428,
+ 0x0F120008,
+ 0x0F120190,
+ 0x0F1200A0,
+
+ 0x002A11EC,
+ 0x0F1200C0,
+
+ 0x002A11F0,
+ 0x0F120010,
+
+ 0x002A11EE,
+ 0x0F120010,
+
+ 0x002A11CE,
+ 0x0F1205D5,
+
+ 0x002A11D2,
+ 0x0F120000,
+ 0x0F120771,
+ 0x0F1203A4,
+ 0x0F120036,
+ 0x0F12002A,
+
+ 0x002A08AC,
+ 0x0F1200C0,
+ 0x0F1200DF,
+ 0x0F120100,
+ 0x0F120125,
+ 0x0F12015F,
+ 0x0F12017C,
+ 0x0F120194,
+
+ 0x002A123C,
+ 0x0F12FEF7,
+ 0x0F120021,
+ 0x0F120E74,
+ 0x0F120E74,
+ 0x0F12018F,
+ 0x0F120096,
+ 0x0F12000E,
+
+ 0x002A11E8,
+ 0x0F120032,
+ 0x0F12001E,
+
+ 0x002A2ABC,
+ 0x0F120006,
+
+ 0x002A1430,
+ 0x0F120002,
+
+ 0x002A140A,
+ 0x0F1200AB,
+ 0x0F1200BF,
+ 0x0F1200D2,
+ 0x0F120093,
+
+ 0x002A13F8,
+ 0x0F120300,
+ 0x0F12036E,
+ 0x0F1203C2,
+ 0x0F121015,
+ 0x0F1210E1,
+ 0x0F121154,
+ 0x0F1211A8,
+ 0x0F1211BB,
+ 0x0F12123B,
+
+ 0x002A1368,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120008,
+ 0x0F120030,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120008,
+ 0x0F120030,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120008,
+ 0x0F120030,
+ 0x0F12FFE0,
+ 0x0F12FFE0,
+ 0x0F12FFC0,
+ 0x0F12FFC0,
+ 0x0F12FFA0,
+ 0x0F12FE36,
+ 0x0F12FFE0,
+ 0x0F12FFE0,
+ 0x0F12FFC0,
+ 0x0F12FFC0,
+ 0x0F12FFA0,
+ 0x0F12FE36,
+ 0x0F12FFE0,
+ 0x0F12FFE0,
+ 0x0F12FFC0,
+ 0x0F12FFC0,
+ 0x0F12FFA0,
+ 0x0F12FE36,
+ 0x0F12FFEA,
+ 0x0F12FFEA,
+ 0x0F12FFC8,
+ 0x0F12FFC8,
+ 0x0F12FFC8,
+ 0x0F12FFC8,
+ 0x0F12FFEA,
+ 0x0F12FFEA,
+ 0x0F12FFC8,
+ 0x0F12FFC8,
+ 0x0F12FFC8,
+ 0x0F12FFC8,
+ 0x0F12FFEA,
+ 0x0F12FFEA,
+ 0x0F12FFC8,
+ 0x0F12FFC8,
+ 0x0F12FFC8,
+ 0x0F12FFC8,
+ 0x0F120014,
+ 0x0F120014,
+ 0x0F120014,
+ 0x0F12FDA0,
+ 0x0F12FCF0,
+ 0x0F12FCD0,
+ 0x0F120014,
+ 0x0F120014,
+ 0x0F120014,
+ 0x0F12FDA0,
+ 0x0F12FCF0,
+ 0x0F12FCD0,
+ 0x0F120014,
+ 0x0F120014,
+ 0x0F120014,
+ 0x0F12FDA0,
+ 0x0F12FCF0,
+ 0x0F12FCD0,
+
+ 0x002A13FE,
+ 0x0F121015,
+ 0x0F12106C,
+ 0x0F1210CA,
+ 0x0F121142,
+ 0x0F1211BB,
+ 0x0F12123B,
+ 0x0F1200AB,
+ 0x0F1200BF,
+ 0x0F1200D2,
+ 0x0F120093,
+
+ 0x002A11CC,
+ 0x0F120020,
+
+ 0x002A1412,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x002A0724,
+ 0x0F120001,
+ 0x0F120007,
+ 0x0F120010,
+ 0x0F120028,
+ 0x0F120062,
+ 0x0F1200D3,
+ 0x0F120130,
+ 0x0F120158,
+ 0x0F12017D,
+ 0x0F1201BE,
+ 0x0F1201F8,
+ 0x0F12022C,
+ 0x0F12025B,
+ 0x0F1202AA,
+ 0x0F1202EC,
+ 0x0F12034E,
+ 0x0F120396,
+ 0x0F1203C6,
+ 0x0F1203E9,
+ 0x0F1203F9,
+ 0x0F120001,
+ 0x0F120007,
+ 0x0F120010,
+ 0x0F120028,
+ 0x0F120062,
+ 0x0F1200D3,
+ 0x0F120130,
+ 0x0F120158,
+ 0x0F12017D,
+ 0x0F1201BE,
+ 0x0F1201F8,
+ 0x0F12022C,
+ 0x0F12025B,
+ 0x0F1202AA,
+ 0x0F1202EC,
+ 0x0F12034E,
+ 0x0F120396,
+ 0x0F1203C6,
+ 0x0F1203E9,
+ 0x0F1203F9,
+ 0x0F120001,
+ 0x0F120007,
+ 0x0F120010,
+ 0x0F120028,
+ 0x0F120062,
+ 0x0F1200D3,
+ 0x0F120130,
+ 0x0F120158,
+ 0x0F12017D,
+ 0x0F1201BE,
+ 0x0F1201F8,
+ 0x0F12022C,
+ 0x0F12025B,
+ 0x0F1202AA,
+ 0x0F1202EC,
+ 0x0F12034E,
+ 0x0F120396,
+ 0x0F1203C6,
+ 0x0F1203E9,
+ 0x0F1203F9,
+ 0x0F120000,
+ 0x0F12000F,
+ 0x0F120020,
+ 0x0F120043,
+ 0x0F120086,
+ 0x0F1200ED,
+ 0x0F12013E,
+ 0x0F120163,
+ 0x0F120185,
+ 0x0F1201BF,
+ 0x0F1201F2,
+ 0x0F120221,
+ 0x0F12024A,
+ 0x0F120294,
+ 0x0F1202D0,
+ 0x0F12032A,
+ 0x0F12036A,
+ 0x0F12039F,
+ 0x0F1203CC,
+ 0x0F1203F9,
+ 0x0F120000,
+ 0x0F12000F,
+ 0x0F120020,
+ 0x0F120043,
+ 0x0F120086,
+ 0x0F1200ED,
+ 0x0F12013E,
+ 0x0F120163,
+ 0x0F120185,
+ 0x0F1201BF,
+ 0x0F1201F2,
+ 0x0F120221,
+ 0x0F12024A,
+ 0x0F120294,
+ 0x0F1202D0,
+ 0x0F12032A,
+ 0x0F12036A,
+ 0x0F12039F,
+ 0x0F1203CC,
+ 0x0F1203F9,
+ 0x0F120000,
+ 0x0F12000F,
+ 0x0F120020,
+ 0x0F120043,
+ 0x0F120086,
+ 0x0F1200ED,
+ 0x0F12013E,
+ 0x0F120163,
+ 0x0F120185,
+ 0x0F1201BF,
+ 0x0F1201F2,
+ 0x0F120221,
+ 0x0F12024A,
+ 0x0F120294,
+ 0x0F1202D0,
+ 0x0F12032A,
+ 0x0F12036A,
+ 0x0F12039F,
+ 0x0F1203CC,
+ 0x0F1203F9,
+
+ 0x002A0896,
+ 0x0F1200C0,
+ 0x0F120100,
+ 0x0F120125,
+ 0x0F12015F,
+ 0x0F12017C,
+ 0x0F120194,
+ 0x0F120001,
+
+ 0x002A0888,
+ 0x0F124800,
+ 0x0F127000,
+
+ 0x002A4800,
+ 0x0F12016C,
+ 0x0F12FF94,
+ 0x0F12FFCE,
+ 0x0F12FF20,
+ 0x0F1201BF,
+ 0x0F12FF53,
+ 0x0F12003F,
+ 0x0F120007,
+ 0x0F1201DF,
+ 0x0F120110,
+ 0x0F1200DF,
+ 0x0F12FF47,
+ 0x0F120206,
+ 0x0F12FF7F,
+ 0x0F120191,
+ 0x0F12FF06,
+ 0x0F1201BA,
+ 0x0F120108,
+ 0x0F12016C,
+ 0x0F12FF94,
+ 0x0F12FFCE,
+ 0x0F12FF20,
+ 0x0F1201BF,
+ 0x0F12FF53,
+ 0x0F12003F,
+ 0x0F120007,
+ 0x0F1201DF,
+ 0x0F120110,
+ 0x0F1200DF,
+ 0x0F12FF47,
+ 0x0F120206,
+ 0x0F12FF7F,
+ 0x0F120191,
+ 0x0F12FF06,
+ 0x0F1201BA,
+ 0x0F120108,
+ 0x0F12016C,
+ 0x0F12FF94,
+ 0x0F12FFCE,
+ 0x0F12FF20,
+ 0x0F1201BF,
+ 0x0F12FF53,
+ 0x0F12003F,
+ 0x0F120007,
+ 0x0F1201DF,
+ 0x0F120110,
+ 0x0F1200DF,
+ 0x0F12FF47,
+ 0x0F120206,
+ 0x0F12FF7F,
+ 0x0F120191,
+ 0x0F12FF06,
+ 0x0F1201BA,
+ 0x0F120108,
+ 0x0F120208,
+ 0x0F12FFD3,
+ 0x0F12FFE9,
+ 0x0F12FF5B,
+ 0x0F12025A,
+ 0x0F12FF80,
+ 0x0F12FFC8,
+ 0x0F12FFC1,
+ 0x0F12013A,
+ 0x0F120112,
+ 0x0F1200EE,
+ 0x0F12FF99,
+ 0x0F12009E,
+ 0x0F12FF5F,
+ 0x0F1201A8,
+ 0x0F12FF75,
+ 0x0F120187,
+ 0x0F1201BF,
+ 0x0F120208,
+ 0x0F12FFD3,
+ 0x0F12FFE9,
+ 0x0F12FF5B,
+ 0x0F12025A,
+ 0x0F12FF80,
+ 0x0F12FFC8,
+ 0x0F12FFC1,
+ 0x0F12013A,
+ 0x0F120112,
+ 0x0F1200EE,
+ 0x0F12FF99,
+ 0x0F12009E,
+ 0x0F12FF5F,
+ 0x0F1201A8,
+ 0x0F12FF75,
+ 0x0F120187,
+ 0x0F1201BF,
+ 0x0F120208,
+ 0x0F12FFD3,
+ 0x0F12FFE9,
+ 0x0F12FF5B,
+ 0x0F12025A,
+ 0x0F12FF80,
+ 0x0F12FFC8,
+ 0x0F12FFC1,
+ 0x0F12013A,
+ 0x0F120112,
+ 0x0F1200EE,
+ 0x0F12FF99,
+ 0x0F12009E,
+ 0x0F12FF5F,
+ 0x0F1201A8,
+ 0x0F12FF75,
+ 0x0F120187,
+ 0x0F1201BF,
+
+ 0x002A0890,
+ 0x0F1248D8,
+ 0x0F127000,
+
+ 0x002A48D8,
+ 0x0F1201AA,
+ 0x0F12FFB6,
+ 0x0F12FFD4,
+ 0x0F12FF6C,
+ 0x0F1201E8,
+ 0x0F12FF79,
+ 0x0F120000,
+ 0x0F12FFF5,
+ 0x0F12023C,
+ 0x0F1200BF,
+ 0x0F1200E0,
+ 0x0F12FF5B,
+ 0x0F12022D,
+ 0x0F12FF9B,
+ 0x0F1201E1,
+ 0x0F12FF34,
+ 0x0F12014B,
+ 0x0F1201B6,
+
+ 0x002A0924,
+ 0x0F120050,
+ 0x0F1200B0,
+ 0x0F120196,
+ 0x0F120245,
+ 0x0F120300,
+
+ 0x002A0958,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1200C0,
+ 0x0F120064,
+ 0x0F120384,
+ 0x0F120032,
+ 0x0F1201F4,
+ 0x0F120070,
+ 0x0F120040,
+ 0x0F1200A0,
+ 0x0F120100,
+ 0x0F120010,
+ 0x0F120040,
+ 0x0F1200A0,
+ 0x0F121430,
+ 0x0F120201,
+ 0x0F120204,
+ 0x0F123604,
+ 0x0F12032A,
+ 0x0F120403,
+ 0x0F121B06,
+ 0x0F126015,
+ 0x0F1200C0,
+ 0x0F126080,
+ 0x0F124080,
+ 0x0F120640,
+ 0x0F120306,
+ 0x0F122003,
+ 0x0F12FF01,
+ 0x0F120000,
+ 0x0F120400,
+ 0x0F12365A,
+ 0x0F12102A,
+ 0x0F12000B,
+ 0x0F120600,
+ 0x0F125A0F,
+ 0x0F120505,
+ 0x0F121802,
+ 0x0F120000,
+ 0x0F122006,
+ 0x0F123028,
+ 0x0F120418,
+ 0x0F120101,
+ 0x0F120800,
+ 0x0F121804,
+ 0x0F124008,
+ 0x0F120540,
+ 0x0F128006,
+ 0x0F120020,
+ 0x0F120000,
+ 0x0F121800,
+ 0x0F120000,
+ 0x0F121E10,
+ 0x0F12000B,
+ 0x0F120607,
+ 0x0F120005,
+ 0x0F120607,
+ 0x0F120405,
+ 0x0F120205,
+ 0x0F120304,
+ 0x0F120409,
+ 0x0F120306,
+ 0x0F120407,
+ 0x0F121C04,
+ 0x0F120214,
+ 0x0F121002,
+ 0x0F120610,
+ 0x0F120F02,
+ 0x0F124A18,
+ 0x0F120080,
+ 0x0F120040,
+ 0x0F120180,
+ 0x0F120A0A,
+ 0x0F120101,
+ 0x0F122A36,
+ 0x0F126024,
+ 0x0F122A36,
+ 0x0F12FFFF,
+ 0x0F120808,
+ 0x0F120A01,
+ 0x0F12010A,
+ 0x0F123601,
+ 0x0F12242A,
+ 0x0F123660,
+ 0x0F12FF2A,
+ 0x0F1208FF,
+ 0x0F120008,
+ 0x0F120001,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1200C0,
+ 0x0F120064,
+ 0x0F120384,
+ 0x0F120032,
+ 0x0F1201F4,
+ 0x0F120070,
+ 0x0F120040,
+ 0x0F1200A0,
+ 0x0F120100,
+ 0x0F120010,
+ 0x0F120060,
+ 0x0F120100,
+ 0x0F121430,
+ 0x0F120201,
+ 0x0F120204,
+ 0x0F122404,
+ 0x0F12031B,
+ 0x0F120103,
+ 0x0F121205,
+ 0x0F12400D,
+ 0x0F120080,
+ 0x0F122080,
+ 0x0F123040,
+ 0x0F120630,
+ 0x0F120306,
+ 0x0F122003,
+ 0x0F12FF01,
+ 0x0F120404,
+ 0x0F120300,
+ 0x0F12245A,
+ 0x0F121018,
+ 0x0F12000B,
+ 0x0F120B00,
+ 0x0F125A0F,
+ 0x0F120505,
+ 0x0F121802,
+ 0x0F120000,
+ 0x0F122006,
+ 0x0F123428,
+ 0x0F12041C,
+ 0x0F120101,
+ 0x0F120800,
+ 0x0F121004,
+ 0x0F124008,
+ 0x0F120540,
+ 0x0F128006,
+ 0x0F120020,
+ 0x0F120000,
+ 0x0F121800,
+ 0x0F120000,
+ 0x0F121E10,
+ 0x0F12000B,
+ 0x0F120607,
+ 0x0F120005,
+ 0x0F120607,
+ 0x0F120405,
+ 0x0F120205,
+ 0x0F120304,
+ 0x0F120409,
+ 0x0F120306,
+ 0x0F120407,
+ 0x0F121F04,
+ 0x0F120218,
+ 0x0F121102,
+ 0x0F120611,
+ 0x0F121002,
+ 0x0F128018,
+ 0x0F120080,
+ 0x0F120080,
+ 0x0F120180,
+ 0x0F120A0A,
+ 0x0F120101,
+ 0x0F121B24,
+ 0x0F126024,
+ 0x0F121010,
+ 0x0F12FFFF,
+ 0x0F120808,
+ 0x0F120A01,
+ 0x0F12010A,
+ 0x0F122401,
+ 0x0F12241B,
+ 0x0F121E60,
+ 0x0F12FF18,
+ 0x0F1208FF,
+ 0x0F120008,
+ 0x0F120001,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1200C0,
+ 0x0F120064,
+ 0x0F120384,
+ 0x0F120032,
+ 0x0F1201F4,
+ 0x0F120070,
+ 0x0F120040,
+ 0x0F1200A0,
+ 0x0F120100,
+ 0x0F120010,
+ 0x0F120060,
+ 0x0F120100,
+ 0x0F121430,
+ 0x0F120201,
+ 0x0F120204,
+ 0x0F121B04,
+ 0x0F120312,
+ 0x0F120003,
+ 0x0F120C03,
+ 0x0F122806,
+ 0x0F120060,
+ 0x0F121580,
+ 0x0F122020,
+ 0x0F120620,
+ 0x0F120306,
+ 0x0F122003,
+ 0x0F12FF01,
+ 0x0F120404,
+ 0x0F120300,
+ 0x0F12145A,
+ 0x0F121010,
+ 0x0F12000B,
+ 0x0F120E00,
+ 0x0F125A0F,
+ 0x0F120504,
+ 0x0F121802,
+ 0x0F120000,
+ 0x0F122006,
+ 0x0F123828,
+ 0x0F120428,
+ 0x0F120101,
+ 0x0F128000,
+ 0x0F120A04,
+ 0x0F124008,
+ 0x0F120540,
+ 0x0F128006,
+ 0x0F120020,
+ 0x0F120000,
+ 0x0F121800,
+ 0x0F120000,
+ 0x0F121E10,
+ 0x0F12000B,
+ 0x0F120607,
+ 0x0F120005,
+ 0x0F120607,
+ 0x0F120405,
+ 0x0F120207,
+ 0x0F120304,
+ 0x0F120409,
+ 0x0F120306,
+ 0x0F120407,
+ 0x0F122404,
+ 0x0F120221,
+ 0x0F121202,
+ 0x0F120613,
+ 0x0F121202,
+ 0x0F128018,
+ 0x0F120080,
+ 0x0F120080,
+ 0x0F120180,
+ 0x0F120A0A,
+ 0x0F120101,
+ 0x0F12121B,
+ 0x0F126024,
+ 0x0F120C0C,
+ 0x0F12FFFF,
+ 0x0F120808,
+ 0x0F120A01,
+ 0x0F12010A,
+ 0x0F121B01,
+ 0x0F122412,
+ 0x0F120C60,
+ 0x0F12FF0C,
+ 0x0F1208FF,
+ 0x0F120008,
+ 0x0F120001,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1200C0,
+ 0x0F120064,
+ 0x0F120384,
+ 0x0F120032,
+ 0x0F1201F4,
+ 0x0F120070,
+ 0x0F120040,
+ 0x0F1200A0,
+ 0x0F120100,
+ 0x0F120010,
+ 0x0F120060,
+ 0x0F120100,
+ 0x0F121430,
+ 0x0F120201,
+ 0x0F120204,
+ 0x0F121504,
+ 0x0F12030F,
+ 0x0F120003,
+ 0x0F120902,
+ 0x0F122004,
+ 0x0F120050,
+ 0x0F121140,
+ 0x0F12201C,
+ 0x0F120620,
+ 0x0F120306,
+ 0x0F122003,
+ 0x0F12FF01,
+ 0x0F120404,
+ 0x0F120300,
+ 0x0F12145A,
+ 0x0F121010,
+ 0x0F12000B,
+ 0x0F121000,
+ 0x0F125A0F,
+ 0x0F120503,
+ 0x0F121802,
+ 0x0F120000,
+ 0x0F122006,
+ 0x0F123C28,
+ 0x0F12042C,
+ 0x0F120101,
+ 0x0F12FF00,
+ 0x0F120904,
+ 0x0F124008,
+ 0x0F120540,
+ 0x0F128006,
+ 0x0F120020,
+ 0x0F120000,
+ 0x0F121800,
+ 0x0F120000,
+ 0x0F121E10,
+ 0x0F12000B,
+ 0x0F120607,
+ 0x0F120005,
+ 0x0F120607,
+ 0x0F120405,
+ 0x0F120206,
+ 0x0F120304,
+ 0x0F120409,
+ 0x0F120305,
+ 0x0F120406,
+ 0x0F122804,
+ 0x0F120228,
+ 0x0F121402,
+ 0x0F120618,
+ 0x0F121402,
+ 0x0F128018,
+ 0x0F120080,
+ 0x0F120080,
+ 0x0F120180,
+ 0x0F120A0A,
+ 0x0F120101,
+ 0x0F120F15,
+ 0x0F126024,
+ 0x0F120A0A,
+ 0x0F12FFFF,
+ 0x0F120808,
+ 0x0F120A01,
+ 0x0F12010A,
+ 0x0F121501,
+ 0x0F12240F,
+ 0x0F120A60,
+ 0x0F12FF0A,
+ 0x0F1208FF,
+ 0x0F120008,
+ 0x0F120001,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1200C0,
+ 0x0F120064,
+ 0x0F120384,
+ 0x0F120032,
+ 0x0F1201F4,
+ 0x0F120070,
+ 0x0F120040,
+ 0x0F1200A0,
+ 0x0F120100,
+ 0x0F120010,
+ 0x0F120060,
+ 0x0F120100,
+ 0x0F121430,
+ 0x0F120201,
+ 0x0F120204,
+ 0x0F120F04,
+ 0x0F12030C,
+ 0x0F120003,
+ 0x0F120602,
+ 0x0F121803,
+ 0x0F120040,
+ 0x0F120E20,
+ 0x0F122018,
+ 0x0F120620,
+ 0x0F120306,
+ 0x0F122003,
+ 0x0F12FF01,
+ 0x0F120404,
+ 0x0F120200,
+ 0x0F12145A,
+ 0x0F121010,
+ 0x0F12000B,
+ 0x0F121200,
+ 0x0F125A0F,
+ 0x0F120502,
+ 0x0F121802,
+ 0x0F120000,
+ 0x0F122006,
+ 0x0F124028,
+ 0x0F120430,
+ 0x0F120101,
+ 0x0F12FF00,
+ 0x0F120804,
+ 0x0F124008,
+ 0x0F120540,
+ 0x0F128006,
+ 0x0F120020,
+ 0x0F120000,
+ 0x0F121800,
+ 0x0F120000,
+ 0x0F121E10,
+ 0x0F12000B,
+ 0x0F120607,
+ 0x0F120005,
+ 0x0F120607,
+ 0x0F120405,
+ 0x0F120205,
+ 0x0F120304,
+ 0x0F120409,
+ 0x0F120306,
+ 0x0F120407,
+ 0x0F122C04,
+ 0x0F12022C,
+ 0x0F121402,
+ 0x0F120618,
+ 0x0F121402,
+ 0x0F128018,
+ 0x0F120080,
+ 0x0F120080,
+ 0x0F120180,
+ 0x0F120A0A,
+ 0x0F120101,
+ 0x0F120C0F,
+ 0x0F126024,
+ 0x0F120808,
+ 0x0F12FFFF,
+ 0x0F120808,
+ 0x0F120A01,
+ 0x0F12010A,
+ 0x0F120F01,
+ 0x0F12240C,
+ 0x0F120860,
+ 0x0F12FF08,
+ 0x0F1208FF,
+ 0x0F120008,
+ 0x0F120001,
+ 0x0F1223CE,
+ 0x0F12FDC8,
+ 0x0F12112E,
+ 0x0F1293A5,
+ 0x0F12FE67,
+ 0x0F120000,
+
+ 0xFCFCD000,
+ 0x00287000,
+ 0x002A01A2,
+ 0x0F120A0A,
+
+ 0xFCFCD000,
+ 0x00040001,
+};
+
+static const u32 s5k4ecgx_DTP_init_v1[] = {
+ 0x0028D000,
+ 0x002AB054,
+ 0x0F120001,
+ 0x00287000,
+};
+
+static const u32 s5k4ecgx_DTP_stop_v1[] = {
+ 0x0028D000,
+ 0x002AB054,
+ 0x0F120000,
+ 0x00287000,
+};
+
+static const u32 s5k4ecgx_Effect_Normal_v1[] = {
+ 0x002A0238,
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_Effect_Negative_v1[] = {
+ 0x002A0238,
+ 0x0F120003,
+};
+
+static const u32 s5k4ecgx_Effect_Sepia_v1[] = {
+ 0x002A0238,
+ 0x0F120004,
+};
+
+static const u32 s5k4ecgx_Effect_Black_White_v1[] = {
+ 0x002A0238,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_WB_Auto_v1[] = {
+ 0x002a04E0,
+ 0x0f12077F,
+};
+
+static const u32 s5k4ecgx_WB_Sunny_v1[] = {
+ 0x002a04E0,
+ 0x0f120777,
+ 0x002a04B4,
+ 0x0f1205E0,
+ 0x0f120001,
+ 0x0f120400,
+ 0x0f120001,
+ 0x0f120530,
+ 0x0f120001,
+ 0x0f120001,
+};
+
+static const u32 s5k4ecgx_WB_Cloudy_v1[] = {
+ 0x002a04E0,
+ 0x0f120777,
+ 0x002a04B4,/* USER RGB Gain */
+ 0x0f120710,/* R */
+ 0x0f120001,/* Changed */
+ 0x0f120400,/* G */
+ 0x0f120001,
+ 0x0f120420,/* B 480-reference */
+ 0x0f120001,
+ 0x0f120001,
+};
+
+static const u32 s5k4ecgx_WB_Tungsten_v1[] = {
+ 0x002a04E0,
+ 0x0f120777,
+ 0x002a04B4,
+ 0x0f120390,
+ 0x0f120001,
+ 0x0f120400,
+ 0x0f120001,
+ 0x0f120920,
+ 0x0f120001,
+ 0x0f120001,
+};
+
+static const u32 s5k4ecgx_WB_Fluorescent_v1[] = {
+ 0x002a04E0,
+ 0x0f120777,
+ 0x002a04B4,
+ 0x0f120505,
+ 0x0f120001,
+ 0x0f120400,
+ 0x0f120001,
+ 0x0f120875,
+ 0x0f120001,
+ 0x0f120001,
+};
+
+static const u32 s5k4ecgx_WDR_on_v1[] = {
+ 0x002A1B4A,
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_WDR_off_v1[] = {
+ 0x002A1B4A,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_ISO_Auto_v1[] = {
+ 0x002A4780,
+ 0x0F120000,
+
+ 0x002A0EF0,
+ 0x0F120001,
+ 0x002A04E0,
+ 0x0F12077F,
+ 0x002A04CA,
+ 0x0F120000,
+
+ 0x002A04CA,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120001,
+ 0x002A06B6,
+ 0x0F120200,
+};
+
+static const u32 s5k4ecgx_ISO_100_v1[] = {
+ 0x002A04E0,
+ 0x0F12065F,
+ 0x002A04D0,
+ 0x0F120000,
+ 0x0F120001,
+
+ 0x002A04CA,
+ 0x0F120001,
+ 0x0F1201A0,
+ 0x0F120001,
+ 0x002A06B6,
+ 0x0F120100,
+
+ 0x002A4780,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_ISO_200_v1[] = {
+ 0x002A04E0,
+ 0x0F12065F,
+ 0x002A04D0,
+ 0x0F120000,
+ 0x0F120001,
+
+ 0x002A04CA,
+ 0x0F120001,
+ 0x0F120340,
+ 0x0F120001,
+ 0x002A06B6,
+ 0x0F120100,
+
+ 0x002A4780,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_ISO_400_v1[] = {
+ 0x002A04E0,
+ 0x0F12065F,
+ 0x002A04D0,
+ 0x0F120000,
+ 0x0F120001,
+
+ 0x002A04CA,
+ 0x0F120001,
+ 0x0F120680,
+ 0x0F120001,
+ 0x002A06B6,
+ 0x0F120100,
+
+ 0x002A4780,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Metering_Matrix_v1[] = {
+ 0x002A1456,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+};
+
+static const u32 s5k4ecgx_Metering_Center_v1[] = {
+ 0x002A1456,
+ 0x0F120000,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120000,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120201,
+ 0x0F120303,
+ 0x0F120303,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120403,
+ 0x0F120304,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120403,
+ 0x0F120304,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120403,
+ 0x0F120304,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120303,
+ 0x0F120303,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120202,
+ 0x0F120202,
+ 0x0F120102,
+};
+
+static const u32 s5k4ecgx_Metering_Spot_v1[] = {
+ 0x002A1456,
+ 0x0f120000,
+ 0x0f120000,
+ 0x0f120000,
+ 0x0f120000,
+ 0x0f120000,
+ 0x0f120000,
+ 0x0f120000,
+ 0x0f120000,
+ 0x0f120000,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120000,
+ 0x0f120000,
+ 0x0f12010f,
+ 0x0f120f01,
+ 0x0f120000,
+ 0x0f120000,
+ 0x0f12010f,
+ 0x0f120f01,
+ 0x0f120000,
+ 0x0f120000,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120000,
+ 0x0f120000,
+ 0x0f120000,
+ 0x0f120000,
+ 0x0f120000,
+ 0x0f120000,
+ 0x0f120000,
+ 0x0f120000,
+ 0x0f120000,
+};
+
+static const u32 s5k4ecgx_EV_Minus_4_v1[] = {
+ 0x002A022C,
+ 0x0F12FF30,
+};
+
+static const u32 s5k4ecgx_EV_Minus_3_v1[] = {
+ 0x002A022C,
+ 0x0F12FFA0,
+};
+
+static const u32 s5k4ecgx_EV_Minus_2_v1[] = {
+ 0x002A022C,
+ 0x0F12FFC8,
+};
+
+static const u32 s5k4ecgx_EV_Minus_1_v1[] = {
+ 0x002A022C,
+ 0x0F12FFE0,
+};
+
+static const u32 s5k4ecgx_EV_Default_v1[] = {
+ 0x002A022C,
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_EV_Plus_1_v1[] = {
+ 0x002A022C,
+ 0x0F120020,
+};
+
+static const u32 s5k4ecgx_EV_Plus_2_v1[] = {
+ 0x002A022C,
+ 0x0F120038,
+};
+
+static const u32 s5k4ecgx_EV_Plus_3_v1[] = {
+ 0x002A022C,
+ 0x0F120060,
+};
+
+static const u32 s5k4ecgx_EV_Plus_4_v1[] = {
+ 0x002A022C,
+ 0x0F12007F,
+};
+
+static const u32 s5k4ecgx_Contrast_Minus_4_v1[] = {
+ 0x002A022E,
+ 0x0F12FF81,
+};
+
+static const u32 s5k4ecgx_Contrast_Minus_3_v1[] = {
+ 0x002A022E,
+ 0x0F12FFA0,
+};
+
+static const u32 s5k4ecgx_Contrast_Minus_2_v1[] = {
+ 0x002A022E,
+ 0x0F12FFC0,
+};
+
+static const u32 s5k4ecgx_Contrast_Minus_1_v1[] = {
+ 0x002A022E,
+ 0x0F12FFE0,
+};
+
+static const u32 s5k4ecgx_Contrast_Default_v1[] = {
+ 0x002A022E,
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_Contrast_Plus_1_v1[] = {
+ 0x002A022E,
+ 0x0F120020,
+};
+
+static const u32 s5k4ecgx_Contrast_Plus_2_v1[] = {
+ 0x002A022E,
+ 0x0F120040,
+};
+
+static const u32 s5k4ecgx_Contrast_Plus_3_v1[] = {
+ 0x002A022E,
+ 0x0F120060,
+};
+
+static const u32 s5k4ecgx_Contrast_Plus_4_v1[] = {
+ 0x002A022E,
+ 0x0F12007F,
+};
+
+static const u32 s5k4ecgx_Sharpness_Minus_3_v1[] = {
+ 0x002A09F4,
+ 0x0F120000,
+ 0x002A0AAA,
+ 0x0F120000,
+ 0x002A0B60,
+ 0x0F120000,
+ 0x002A0C16,
+ 0x0F120000,
+ 0x002A0CCC,
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_Sharpness_Minus_2_v1[] = {
+ 0x002A09F4,
+ 0x0F122010,
+ 0x002A0AAA,
+ 0x0F122010,
+ 0x002A0B60,
+ 0x0F122010,
+ 0x002A0C16,
+ 0x0F122010,
+ 0x002A0CCC,
+ 0x0F122010,
+};
+
+static const u32 s5k4ecgx_Sharpness_Minus_1_v1[] = {
+ 0x002A09F4,
+ 0x0F124020,
+ 0x002A0AAA,
+ 0x0F124020,
+ 0x002A0B60,
+ 0x0F124020,
+ 0x002A0C16,
+ 0x0F124020,
+ 0x002A0CCC,
+ 0x0F124020,
+};
+
+static const u32 s5k4ecgx_Sharpness_Default_v1[] = {
+ 0x002A09F4,
+ 0x0F126024,
+ 0x002A0AAA,
+ 0x0F126024,
+ 0x002A0B60,
+ 0x0F126024,
+ 0x002A0C16,
+ 0x0F126024,
+ 0x002A0CCC,
+ 0x0F126024,
+};
+
+static const u32 s5k4ecgx_Sharpness_Plus_1_v1[] = {
+ 0x002A09F4,
+ 0x0F128040,
+ 0x002A0AAA,
+ 0x0F128040,
+ 0x002A0B60,
+ 0x0F128040,
+ 0x002A0C16,
+ 0x0F128040,
+ 0x002A0CCC,
+ 0x0F128040,
+};
+
+static const u32 s5k4ecgx_Sharpness_Plus_2_v1[] = {
+ 0x002A09F4,
+ 0x0F12A060,
+ 0x002A0AAA,
+ 0x0F12A060,
+ 0x002A0B60,
+ 0x0F12A060,
+ 0x002A0C16,
+ 0x0F12A060,
+ 0x002A0CCC,
+ 0x0F12A060,
+};
+
+static const u32 s5k4ecgx_Sharpness_Plus_3_v1[] = {
+ 0x002A09F4,
+ 0x0F12C080,
+ 0x002A0AAA,
+ 0x0F12C080,
+ 0x002A0B60,
+ 0x0F12C080,
+ 0x002A0C16,
+ 0x0F12C080,
+ 0x002A0CCC,
+ 0x0F12C080,
+};
+
+static const u32 s5k4ecgx_Saturation_Minus_2_v1[] = {
+ 0x002A0230,
+ 0x0F12FF81,
+};
+
+static const u32 s5k4ecgx_Saturation_Minus_1_v1[] = {
+ 0x002A0230,
+ 0x0F12FFC0,
+};
+
+static const u32 s5k4ecgx_Saturation_Default_v1[] = {
+ 0x002A0230,
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_Saturation_Plus_1_v1[] = {
+ 0x002A0230,
+ 0x0F120040,
+};
+
+static const u32 s5k4ecgx_Saturation_Plus_2_v1[] = {
+ 0x002A0230,
+ 0x0F12007F,
+};
+
+static const u32 s5k4ecgx_Jpeg_Quality_High_v1[] = {
+ 0x002A0472,
+ 0x0F12005F,
+ 0x0F12005F,
+};
+
+static const u32 s5k4ecgx_Jpeg_Quality_Normal_v1[] = {
+ 0x002A0472,
+ 0x0F120050,
+ 0x0F120050,
+};
+
+static const u32 s5k4ecgx_Jpeg_Quality_Low_v1[] = {
+ 0x002A0472,
+ 0x0F12004B,
+ 0x0F12004B,
+};
+
+static const u32 s5k4ecgx_Scene_Default_v1[] = {
+ 0x002A1456,
+ 0x0F120000,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120000,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120201,
+ 0x0F120303,
+ 0x0F120303,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120403,
+ 0x0F120304,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120403,
+ 0x0F120304,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120403,
+ 0x0F120304,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120303,
+ 0x0F120303,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120202,
+ 0x0F120202,
+ 0x0F120102,
+
+ 0x002A4780,
+ 0x0F120000,
+
+ 0x002A06AC,
+ 0x0F12452C,
+ 0x0F120004,
+
+ 0x002A0EF0,
+ 0x0F120001,
+ 0x002A0EF6,
+ 0x0F120001,
+ 0x002A04E0,
+ 0x0F12077F,
+ 0x002A04CA,
+ 0x0F120000,
+
+ 0x002A04CA,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120001,
+ 0x002A06B6,
+ 0x0F120200,
+
+ 0x002a2B7E,
+ 0x0f120001,
+
+
+ 0x002A1448,
+ 0x0F12003C,
+ 0x002A144E,
+ 0x0F12000F,
+ 0x002A0580,
+ 0x0F123520,
+ 0x0F120000,
+ 0x0F12C350,
+ 0x0F120000,
+ 0x0F123520,
+ 0x0F120000,
+ 0x0F12C350,
+ 0x0F120000,
+ 0x0F120470,
+ 0x0F120C00,
+ 0x0F120100,
+ 0x0F121000,
+
+ 0x002A0538,
+ 0x0F120111,
+ 0x0F1200EF,
+
+
+ 0x002A05FC,
+ 0x0F120000,
+ 0x0F120001,
+
+ 0x002A09F4,
+ 0x0F126024,
+ 0x002A0AAA,
+ 0x0F126024,
+ 0x002A0B60,
+ 0x0F126024,
+ 0x002A0C16,
+ 0x0F126024,
+ 0x002A0CCC,
+ 0x0F126024,
+
+ 0x002A0230,
+ 0x0F120000,
+
+ 0x002A062C,
+ 0x0F120001,
+ 0x0F120000,
+ 0x002A0630,
+ 0x0F120A3C,
+ 0x0F120000,
+ 0x002A0634,
+ 0x0F120D05,
+ 0x0F120000,
+ 0x002A0638,
+ 0x0F123408,
+ 0x0F120000,
+ 0x002A063C,
+ 0x0F123408,
+ 0x0F120000,
+ 0x002A0640,
+ 0x0F126810,
+ 0x0F120000,
+ 0x002A0644,
+ 0x0F128214,
+ 0x0F120000,
+ 0x002A0648,
+ 0x0F12C350,
+ 0x0F120000,
+ 0x002A064C,
+ 0x0F12C350,
+ 0x0F120000,
+ 0x002A0650,
+ 0x0F12C350,
+ 0x0F120000,
+
+ 0x002A03AE,
+ 0x0F120535,
+ 0x0F12029A,
+
+
+ 0x002A0262,
+ 0x0F120000,
+ 0x002A0266,
+ 0x0F120001,
+ 0x002A024A,
+ 0x0F120001,
+ 0x002A0264,
+ 0x0F120001,
+ 0x002A026C,
+ 0x0F120001,
+ 0x002A023A,
+ 0x0F120001,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Scene_Portrait_v1[] = {
+ 0x002A09F4,
+ 0x0F124020,
+ 0x002A0AAA,
+ 0x0F124020,
+ 0x002A0B60,
+ 0x0F124020,
+ 0x002A0C16,
+ 0x0F124020,
+ 0x002A0CCC,
+ 0x0F124020,
+};
+
+static const u32 s5k4ecgx_Scene_Nightshot_v1[] = {
+ 0x002A06AC,
+ 0x0F12FFFF,
+ 0x0F1200FF,
+
+ 0x002A05FC,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x002A0580,
+ 0x0F12F424,
+ 0x0F120001,
+ 0x0F12F424,
+ 0x0F120001,
+ 0x0F12F424,
+ 0x0F120001,
+ 0x0F12F424,
+ 0x0F120001,
+ 0x0F120100,
+ 0x0F120700,
+ 0x0F120100,
+ 0x0F122000,
+
+ 0x002A03AE,
+ 0x0F121388,
+ 0x0F121388,
+
+ 0x002A02BC,
+ 0x0F1209C4,
+ 0x0F12014D,
+
+ 0x002A0262,
+ 0x0F120000,
+
+ 0x002A0266,
+ 0x0F120001,
+
+ 0x002A024A,
+ 0x0F120001,
+
+ 0x002A0264,
+ 0x0F120001,
+
+ 0x002A026C,
+ 0x0F120001,
+
+ 0x002A023A,
+ 0x0F120001,
+ 0x0F120001,
+
+ 0x002A09EA,
+ 0x0F121580,
+};
+
+static const u32 s5k4ecgx_Scene_Landscape_v1[] = {
+ 0x002A1456,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x002A09F4,
+ 0x0F128040,
+ 0x002A0AAA,
+ 0x0F128040,
+ 0x002A0B60,
+ 0x0F128040,
+ 0x002A0C16,
+ 0x0F128040,
+ 0x002A0CCC,
+ 0x0F128040,
+ 0x002A0230,
+ 0x0F120040,
+};
+
+static const u32 s5k4ecgx_Scene_Sports_v1[] = {
+ 0x002A05FC,
+
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x002A0580,
+ 0x0F123520,
+ 0x0F120000,
+ 0x0F123520,
+ 0x0F120000,
+ 0x0F123520,
+ 0x0F120000,
+ 0x0F123520,
+ 0x0F120000,
+ 0x0F120200,
+ 0x0F120200,
+ 0x0F120200,
+ 0x0F120200,
+
+ 0x002A0262,
+ 0x0F120000,
+ 0x002A0266,
+ 0x0F120001,
+ 0x002A024A,
+ 0x0F120001,
+ 0x002A0264,
+ 0x0F120001,
+ 0x002A026C,
+ 0x0F120001,
+ 0x002A023A,
+ 0x0F120001,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Scene_Party_Indoor_v1[] = {
+ 0x002A04E0,
+ 0x0F12065F,
+ 0x002A04D0,
+ 0x0F120000,
+ 0x0F120001,
+
+ 0x002A04CA,
+ 0x0F120001,
+ 0x0F120340,
+ 0x0F120001,
+ 0x002A06B6,
+ 0x0F120100,
+
+
+ 0x002A4780,
+ 0x0F120001,
+
+ 0x002A0230,
+ 0x0F120031,
+};
+
+static const u32 s5k4ecgx_Scene_Beach_Snow_v1[] = {
+ 0x002A04E0,
+ 0x0F12065F,
+ 0x002A04D0,
+ 0x0F120000,
+ 0x0F120001,
+ 0x002A04CA,
+ 0x0F120001,
+ 0x0F1200D0,
+ 0x0F120001,
+ 0x002A06B6,
+ 0x0F120100,
+
+
+ 0x002A4780,
+ 0x0F120001,
+
+ 0x002A0230,
+ 0x0F120031,
+};
+
+static const u32 s5k4ecgx_Scene_Sunset_v1[] = {
+ 0x002a2B7E,
+ 0x0f120000,
+
+ 0x002a04B4,
+ 0x0f1205E0,
+ 0x0f120001,
+ 0x0f120400,
+ 0x0f120001,
+ 0x0f120520,
+ 0x0f120001,
+};
+
+static const u32 s5k4ecgx_Scene_Duskdawn_v1[] = {
+ 0x002a2B7E,
+ 0x0f120000,
+
+ 0x002a04B4,
+ 0x0f120575,
+ 0x0f120001,
+ 0x0f120400,
+ 0x0f120001,
+ 0x0f120835,
+ 0x0f120001,
+};
+
+static const u32 s5k4ecgx_Scene_Fireworks_v1[] = {
+ 0x002A062C,
+ 0x0F120001,
+ 0x0F120000,
+ 0x002A0630,
+ 0x0F121478,
+ 0x0F120000,
+ 0x002A0634,
+ 0x0F121A0A,
+ 0x0F120000,
+ 0x002A0638,
+ 0x0F126810,
+ 0x0F120000,
+ 0x002A063C,
+ 0x0F126810,
+ 0x0F120000,
+ 0x002A0640,
+ 0x0F12D020,
+ 0x0F120000,
+ 0x002A0644,
+ 0x0F120428,
+ 0x0F120001,
+ 0x002A0648,
+ 0x0F121A80,
+ 0x0F120006,
+ 0x002A064C,
+ 0x0F121A80,
+ 0x0F120006,
+ 0x002A0650,
+ 0x0F121A80,
+ 0x0F120006,
+
+ 0x002A03AE,
+ 0x0F122710,
+ 0x0F122710,
+
+ 0x002A0262,
+ 0x0F120000,
+ 0x002A0266,
+ 0x0F120001,
+ 0x002A024A,
+ 0x0F120001,
+ 0x002A0264,
+ 0x0F120001,
+ 0x002A026C,
+ 0x0F120001,
+ 0x002A023A,
+ 0x0F120001,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Scene_Candle_Light_v1[] = {
+ 0x002a04E0,
+ 0x0f120777,
+ 0x002a04B4,
+ 0x0f1205E0,
+ 0x0f120001,
+ 0x0f120400,
+ 0x0f120001,
+ 0x0f120530,
+ 0x0f120001,
+};
+
+static const u32 s5k4ecgx_Night_Capture_v1[] = {
+ 0x002A09EA,
+ 0x0F120AAA,
+ 0x002A0AA0,
+ 0x0F120AAA,
+};
+
+static const u32 s5k4ecgx_AF_Return_Macro_pos_v1[] = {
+ 0x002A15AC,
+ 0x0F120018,
+ 0x0F12002A,
+ 0x0F120030,
+ 0x0F120036,
+ 0x0F12003C,
+ 0x0F120042,
+ 0x0F120048,
+ 0x0F12004E,
+ 0x0F120054,
+ 0x0F12005A,
+ 0x0F120060,
+ 0x0F120066,
+ 0x0F12006C,
+ 0x0F120072,
+ 0x0F120078,
+ 0x0F12007E,
+ 0x0F120084,
+ 0x0F12008A,
+ 0x0F120090,
+ 0x0F120096,
+ 0x0F12009C,
+ 0x0F1200A2,
+ 0x0F1200A8,
+ 0x0F1200AE,
+ 0x0F1200B4,
+ 0x0F1200BA,
+};
+
+static const u32 s5k4ecgx_AF_Normal_mode_1_v1[] = {
+ 0x002A0288,
+ 0x0F12002A,
+};
+
+static const u32 s5k4ecgx_AF_Normal_mode_2_v1[] = {
+ 0x002A0286,
+ 0x0F120004,
+};
+
+
+static const u32 s5k4ecgx_AF_Normal_mode_3_v1[] = {
+ 0x002A160C,
+ 0x0F129002,
+};
+
+static const u32 s5k4ecgx_AF_Macro_mode_1_v1[] = {
+ 0x002A0288,
+ 0x0F1200D0,
+};
+
+static const u32 s5k4ecgx_AF_Macro_mode_2_v1[] = {
+ 0x002A0286,
+ 0x0F120004,
+};
+
+static const u32 s5k4ecgx_AF_Macro_mode_3_v1[] = {
+ 0x002A160C,
+ 0x0F129042,
+ 0x002A159E,
+ 0x0F121800,
+};
+
+static const u32 s5k4ecgx_AF_Low_Light_Mode_On_v1[] = {
+ 0x002A1616,
+ 0x0F120003,
+
+ 0x002A15A4,
+ 0x0F120902,
+
+ 0x002A159E,
+ 0x0F120C00,
+
+ 0x002A15AC,
+ 0x0F12002A,
+ 0x0F120033,
+ 0x0F12003C,
+ 0x0F120045,
+ 0x0F12004E,
+ 0x0F120057,
+ 0x0F120063,
+ 0x0F12006F,
+ 0x0F12007B,
+ 0x0F120087,
+ 0x0F120093,
+ 0x0F1200A2,
+ 0x0F1200B1,
+};
+
+static const u32 s5k4ecgx_AF_Low_Light_Mode_Off_v1[] = {
+ 0x002A1616,
+ 0x0F120003,
+
+ 0x002A15A4,
+ 0x0F120902,
+
+ 0x002A159E,
+ 0x0F121800,
+
+ 0x002A15AC,
+ 0x0F120018,
+ 0x0F12002A,
+ 0x0F120030,
+ 0x0F120036,
+ 0x0F12003C,
+ 0x0F120042,
+ 0x0F120048,
+ 0x0F12004E,
+ 0x0F120054,
+ 0x0F12005A,
+ 0x0F120060,
+ 0x0F120066,
+ 0x0F12006C,
+ 0x0F120072,
+ 0x0F120078,
+ 0x0F12007E,
+ 0x0F120084,
+ 0x0F12008A,
+ 0x0F120090,
+ 0x0F120096,
+ 0x0F12009C,
+ 0x0F1200A2,
+ 0x0F1200A8,
+ 0x0F1200AE,
+ 0x0F1200B4,
+ 0x0F1200BA,
+};
+
+static const u32 s5k4ecgx_Single_AF_Start_v1[] = {
+ 0x002A0286,
+ 0x0F120005,
+};
+
+static const u32 s5k4ecgx_Single_AF_Off_1_v1[] = {
+ 0x002A0288,
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_Single_AF_Off_2_v1[] = {
+ 0x002A0286,
+ 0x0F120004,
+};
+
+static const u32 s5k4ecgx_Face_Detection_On_v1[] = {
+ 0x002A028E,
+ 0x0F120100,
+ 0x0F1200E3,
+ 0x0F120200,
+ 0x0F120238,
+ 0x0F1201C6,
+ 0x0F120166,
+ 0x0F120074,
+ 0x0F120132,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Face_Detection_Off_v1[] = {
+ 0x002A028E,
+ 0x0F120100,
+ 0x0F1200E3,
+ 0x0F120200,
+ 0x0F120238,
+ 0x0F1201C6,
+ 0x0F120166,
+ 0x0F120074,
+ 0x0F120132,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Low_Cap_On_v1[] = {
+ 0x002A09EA,
+ 0x0F120D58,
+ 0x002A0AA0,
+ 0x0F120A53,
+};
+
+static const u32 s5k4ecgx_Low_Cap_Off_v1[] = {
+ 0x002A09EA,
+ 0x0F120040,
+ 0x002A0AA0,
+ 0x0F120080,
+};
+
+/* restores crop settings to full resolution */
+static const u32 s5k4ecgx_Reset_Crop_v1[] = {
+ 0x002A024C,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120010,
+ 0x0F12000C,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120010,
+ 0x0F12000C,
+ 0x002A048E,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x002A025E,
+ 0x0F120001,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Capture_Start_v1[] = {
+ 0x002A1A00,
+ 0x0F12185C,
+ 0x0F127000,
+ 0x002A023E,
+ 0x0F120001,
+ 0x002A024A,
+ 0x0F120001,
+ 0x002A0240,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Preview_Return_v1[] = {
+ 0x002A05C4,
+ 0x0F120000,
+ 0x002A1A00,
+ 0x0F12192E,
+ 0x0F127000,
+ 0x002A0952,
+ 0x0F120000,
+ 0x002A023E,
+ 0x0F120000,
+ 0x002A024A,
+ 0x0F120001,
+ 0x002A0240,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Flash_init_v1[] = {
+ 0x002A17DC,
+ 0x0F120001, /* one frame AE */
+
+ 0x002A17AE,
+ 0x0F120270, /* AWB R point */
+
+ 0x002A17B0,
+ 0x0F120210, /* AWB B point */
+
+ 0x002A17E2,
+ 0x0F120001, /* Flash AE tune start*/
+ 0x0F120030, /* 0x100 for Rin output */
+ 0x0F120040,
+ 0x0F120050,
+ 0x0F120060,
+ 0x0F120070,
+ 0x0F120080,
+ 0x0F120090,
+ 0x0F1200A0,
+ 0x0F120050, /* 0x100 for Rout output-20 */
+ 0x0F120014,
+ 0x0F12000A,
+ 0x0F120008,
+ 0x0F120005,
+ 0x0F120004,
+ 0x0F120002,
+ 0x0F120001,
+
+ 0x002A1824,
+ 0x0F120100, /* 0x100 for NB output */
+ 0x0F120100,
+ 0x0F120100,
+ 0x0F120100,
+ 0x0F120100,
+ 0x0F120100,
+ 0x0F120100,
+ 0x0F120100,
+
+ 0x002A17B4,
+ 0x0F120100,
+ 0x0F1200A0,
+ 0x0F120080,
+ 0x0F120020,
+ 0x0F120001,
+
+ 0x002A17C8,
+ 0x0F120025,
+ 0x0F120030,
+ 0x0F120050,
+ 0x0F120070,
+ 0x0F120080,
+};
+
+static const u32 s5k4ecgx_Pre_Flash_Start_v1[] = {
+ 0x002A057C, /* set AE speed to fast */
+ 0x0F120000,
+
+ 0x002A1F06, /* fls_afl_FlashWP_Weight_0_ Pre_Flash_Start */
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Pre_Flash_End_v1[] = {
+ 0x002A057C, /* set AE speed to normal */
+ 0x0F120002,
+
+ 0x002A1F08, /* fls_afl_FlashWP_Weight_0_ Pre_Flash_end */
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Flash_Start_v1[] = {
+ 0x002A17A8,
+ 0x0F120001,
+
+ 0x002A047E,
+ 0x0F120002,
+
+ 0x002A1448,
+ 0x0F120027,
+};
+
+static const u32 s5k4ecgx_Flash_End_v1[] = {
+ 0x002A17A8,
+ 0x0F120000,
+
+ 0x002A047E,
+ 0x0F120000,
+
+ 0x002A1448,
+ 0x0F12003C,
+};
+
+static const u32 s5k4ecgx_5M_Capture_v1[] = { /* 2560 x 1920 */
+ 0x002A0392,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120009,
+
+ 0x002A03AC,
+ 0x0F120002,
+
+ 0x002A03AA,
+ 0x0F120000,
+
+ 0x002A026C,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_3M_Capture_v1[] = { /* 2048 x 1536 */
+ 0x002A0392,
+ 0x0F120800,
+ 0x0F120600,
+ 0x0F120009,
+
+ 0x002A03AC,
+ 0x0F120002,
+
+ 0x002A03AA,
+ 0x0F120000,
+
+ 0x002A024A,
+ 0x0F120001,
+
+ 0x002A026C,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_2M_Capture_v1[] = { /* 1600 x 1200 */
+ 0x002A0392,
+ 0x0F120640,
+ 0x0F1204B0,
+ 0x0F120009,
+
+ 0x002A03AC,
+ 0x0F120002,
+
+ 0x002A03AA,
+ 0x0F120000,
+
+ 0x002A024A,
+ 0x0F120001,
+
+ 0x002A026C,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_1M_Capture_v1[] = { /* 1280 x 960 */
+ 0x002A0392,
+ 0x0F120500,
+ 0x0F1203C0,
+ 0x0F120009,
+
+ 0x002A03AC,
+ 0x0F120002,
+
+ 0x002A03AA,
+ 0x0F120000,
+
+ 0x002A024A,
+ 0x0F120001,
+
+ 0x002A026C,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_VGA_Capture_v1[] = { /* 640 x 480 */
+ 0x002A0392,
+ 0x0F120280,
+ 0x0F1201E0,
+ 0x0F120009,
+
+ 0x002A03AC,
+ 0x0F120002,
+
+ 0x002A03AA,
+ 0x0F120000,
+
+ 0x002A024A,
+ 0x0F120001,
+
+ 0x002A026C,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_720_Preview_v1[] = { /* 720 x 480 */
+ 0x002A02A0,
+ 0x0F1202D0,
+ 0x0F1201E0,
+ 0x0F120005,
+ 0x002A02AE,
+ 0x0F120052,
+ 0x002A02B8,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F12029A,
+ 0x0F12014D,
+ 0x002A02CA,
+ 0x0F120000,
+ 0x0F120000,
+ 0x002A0262,
+ 0x0F120000,
+ 0x002A0266,
+ 0x0F120001,
+ 0x002A024A,
+ 0x0F120001,
+ 0x002A0264,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_640_Preview_v1[] = { /* 640 x 480 */
+ 0x002A02A0,
+ 0x0F120280,
+ 0x0F1201E0,
+ 0x0F120005,
+ 0x002A02AE,
+ 0x0F120052,
+ 0x002A02B8,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F12029A,
+ 0x0F12014D,
+ 0x002A02CA,
+ 0x0F120000,
+ 0x0F120000,
+ 0x002A0262,
+ 0x0F120000,
+ 0x002A0266,
+ 0x0F120001,
+ 0x002A024A,
+ 0x0F120001,
+ 0x002A0264,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_352_Preview_v1[] = { /* 352 x 288 */
+ 0x002A02A0,
+ 0x0F120160,
+ 0x0F120120,
+ 0x0F120005,
+ 0x002A02AE,
+ 0x0F120052,
+ 0x002A02B8,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F12029A,
+ 0x0F12014D,
+ 0x002A02CA,
+ 0x0F120000,
+ 0x0F120000,
+ 0x002A0262,
+ 0x0F120000,
+ 0x002A0266,
+ 0x0F120001,
+ 0x002A024A,
+ 0x0F120001,
+ 0x002A0264,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_176_Preview_v1[] = { /* 176 x 144 */
+ 0x002A02A0,
+ 0x0F1200B0,
+ 0x0F120090,
+ 0x0F120005,
+ 0x002A02AE,
+ 0x0F120052,
+ 0x002A02B8,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F12029A,
+ 0x0F12014D,
+ 0x002A02CA,
+ 0x0F120000,
+ 0x0F120000,
+ 0x002A0262,
+ 0x0F120000,
+ 0x002A0266,
+ 0x0F120001,
+ 0x002A024A,
+ 0x0F120001,
+ 0x002A0264,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_AE_AWB_Lock_On_v1[] = {
+ 0x002A2B76, /* AE Lock On */
+ 0x0F120000,
+ 0x002A2B7E, /* AWB Lock On */
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_AE_AWB_Lock_Off_v1[] = {
+ 0x002A2B76, /* AE Lock Off */
+ 0x0F120001,
+ 0x002A2B7E, /* AWB Lock Off */
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Get_AE_Stable_Status_v1[] = {
+ 0x002E2B8C,
+};
+
+static const u32 s5k4ecgx_Get_Light_Level_v1[] = {
+ 0x002C7000,
+ 0x002E2B30,
+};
+
+static const u32 s5k4ecgx_get_1st_af_search_status_v1[] = {
+ 0x002E2E06,
+};
+
+static const u32 s5k4ecgx_get_2nd_af_search_status_v1[] = {
+ 0x002E2167,
+};
+
+static const u32 s5k4ecgx_get_capture_status_v1[] = {
+ 0x002E1F02,
+};
+
+static const u32 s5k4ecgx_get_esd_status_v1[] = {
+ 0xFCFCD000,
+ 0x002CD000,
+ 0x002E0060,
+};
+
+static const u32 s5k4ecgx_get_iso_reg_v1[] = {
+ 0x002C7000,
+ 0x002E2ADC,
+};
+
+static const u32 s5k4ecgx_get_shutterspeed_reg_v1[] = {
+ 0x002C7000,
+ 0x002E2AD8,
+};
+
+#endif /* __S5K4ECGX_REGS_1_0_H__ */
diff --git a/drivers/media/video/s5k4ecgx_regs_1_1.h b/drivers/media/video/s5k4ecgx_regs_1_1.h
new file mode 100755
index 0000000..4001d36
--- /dev/null
+++ b/drivers/media/video/s5k4ecgx_regs_1_1.h
@@ -0,0 +1,4783 @@
+/* drivers/media/video/s5k4ecgx_regs_1_1.h
+ *
+ * Driver for s5k4ecgx (5MP Camera) from SEC(LSI), firmware EVT1.1
+ *
+ * Copyright (C) 2010, SAMSUNG ELECTRONICS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+
+#ifndef __S5K4ECGX_REGS_1_1_H__
+#define __S5K4ECGX_REGS_1_1_H__
+
+/* ARM Initiation */
+static const u32 s5k4ecgx_init_reg1[] = {
+ 0xFCFCD000,
+ 0x00100001,
+ 0x10300000,
+ 0x00140001,
+};
+
+static const u32 s5k4ecgx_init_reg2[] = {
+ /* Drive current setting */
+ 0x0028D000,
+ 0x002A1082,
+ 0x0F120155, /*d0_d4_cd10, d0_d4_cd10 9:0*/
+ 0x0F120155, /*d5_d9_cd10, d5_d9_cd10 9:0*/
+ 0x0F120055, /*gpio_cd10, gpio_cd10*/
+ 0x0F120555, /*clks_output_cd10, clks_output_cd10 11:0*/
+ 0x002A100E,
+ 0x0F120000, /*pclk_delay_r*/
+
+ 0x002A007A,
+ 0x0F120000,
+
+ /* ISP FE(ADLC) */
+ 0x002AE406,
+ 0x0F120092,
+ 0x002AE410,
+ 0x0F123804,
+ 0x002AE41A,
+ 0x0F120010, /*101022 ADD adlcptune_total */
+ 0x002AE420,
+ 0x0F120003,
+ 0x0F120060,
+ 0x002AE42E,
+ 0x0F120004,
+ 0x002AF400,
+ 0x0F125A3C,
+ 0x0F120023,
+ 0x0F128080,
+ 0x0F1203AF,
+ 0x0F12000A,
+ 0x0F12AA54,
+ 0x0F120040,
+ 0x0F12464E,
+ 0x0F120240,
+ 0x0F120240,
+ 0x0F120040,
+ 0x0F121000,
+ 0x0F12555C,
+ 0x0F12D000,
+ 0x0F120010,
+ 0x0F120202,
+ 0x0F120401,
+ 0x0F120022,
+ 0x0F120088,
+ 0x0F12009F,
+ 0x0F120000,
+ 0x0F121800,
+ 0x0F120088,
+ 0x0F120000,
+ 0x0F122428,
+ 0x0F120000,
+ 0x0F1203EE,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x002AF552,
+ 0x0F120708,
+ 0x0F12080C,
+
+ /* For subsampling Size */
+ 0x00287000,
+ 0x002A18BC,
+ 0x0F120004,
+ 0x0F1205B6,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F1205BA,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120007,
+ 0x0F1205BA,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1201F4,
+ 0x0F12024E,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1201F4,
+ 0x0F1205B6,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1201F4,
+ 0x0F1205BA,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1201F4,
+ 0x0F12024F,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120075,
+ 0x0F1200CF,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120075,
+ 0x0F1200D6,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120004,
+ 0x0F1201F4,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1200F0,
+ 0x0F1201F4,
+ 0x0F12029E,
+ 0x0F1205B2,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1201F8,
+ 0x0F120228,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120208,
+ 0x0F120238,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120218,
+ 0x0F120238,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F120009,
+ 0x0F1200DE,
+ 0x0F1205C0,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1200DF,
+ 0x0F1200E4,
+ 0x0F1201F8,
+ 0x0F1201FD,
+ 0x0F1205B6,
+ 0x0F1205BB,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1201F8,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120077,
+ 0x0F12007E,
+ 0x0F12024F,
+ 0x0F12025E,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+
+ /* For Capture */
+ 0x0F120004,
+ 0x0F1209D1,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F1209D5,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120008,
+ 0x0F1209D5,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1202AA,
+ 0x0F120326,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1202AA,
+ 0x0F1209D1,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1202AA,
+ 0x0F1209D5,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1202AA,
+ 0x0F120327,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120008,
+ 0x0F120084,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120008,
+ 0x0F12008D,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120008,
+ 0x0F1202AA,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1200AA,
+ 0x0F1202AA,
+ 0x0F1203AD,
+ 0x0F1209CD,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1202AE,
+ 0x0F1202DE,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1202BE,
+ 0x0F1202EE,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1202CE,
+ 0x0F1202EE,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F120009,
+ 0x0F120095,
+ 0x0F1209DB,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120096,
+ 0x0F12009B,
+ 0x0F1202AE,
+ 0x0F1202B3,
+ 0x0F1209D1,
+ 0x0F1209D6,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1202AE,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120009,
+ 0x0F120010,
+ 0x0F120327,
+ 0x0F120336,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x002A1AF8,
+ 0x0F125A3C, /*#senHal_TuneStr_AngTuneData1_2_D000F400
+ register at subsampling*/
+
+ 0x002A1896,
+ 0x0F120002, /*#senHal_SamplingType 0002 03EE: PLA setting*/
+ 0x0F120000, /*#senHal_SamplingMode 0 : 2 PLA / 1 : 4PLA*/
+ 0x0F120003, /*#senHal_PLAOption
+ [0] VPLA enable , [1] HPLA enable*/
+
+ 0x002A189E,
+ 0x0F120FB0, /*#senHal_ExpMinPixels*/
+
+ 0x002A18AC,
+ 0x0F120060, /*#senHal_uAddColsBin*/
+ 0x0F120060, /*#senHal_uAddColsNoBin*/
+ 0x0F1205C0, /*#senHal_uMinColsBin*/
+ 0x0F1205C0, /*#senHal_uMinColsNoBin*/
+
+ 0x002A1AEA,
+ 0x0F128080, /*#senHal_SubF404Tune*/
+ 0x0F120080, /*#senHal_FullF404Tune*/
+ 0x002A1AE0,
+ 0x0F120000, /*#senHal_bSenAAC*/
+
+ 0x002A1A72,
+ 0x0F120000, /*#senHal_bSRX SRX off*/
+ 0x002A18A2,
+ 0x0F120004, /*#senHal_NExpLinesCheckFine,
+ extend Forbidden area line*/
+ 0x002A1A6A,
+ 0x0F12009A, /*#senHal_usForbiddenRightOfs,
+ extend right Forbidden area line*/
+ 0x002A385E,
+ 0x0F12024C, /*#Mon_Sen_uExpPixelsOfs*/
+
+ 0x002A0EE6,
+ 0x0F120000, /*#setot_bUseDigitalHbin*/
+ 0x002A1B2A,
+ 0x0F120300, /*#senHal_TuneStr2_usAngTuneGainTh 2 70001B2A*/
+ 0x0F1200D6, /*#senHal_TuneStr2_AngTuneF4CA_0_ 2 70001B2C*/
+ 0x0F12008D, /*#senHal_TuneStr2_AngTuneF4CA_1_ 2 70001B2E*/
+ 0x0F1200CF, /*#senHal_TuneStr2_AngTuneF4C2_0_ 2 70001B30*/
+ 0x0F120084, /*#senHal_TuneStr2_AngTuneF4C2_1_ 2 70001B32*/
+
+ /* OTP setting */
+
+ 0x002A0722,
+ 0x0F120100, /*#skl_OTP_usWaitTime,
+ This register should be positioned in
+ front of D0001000*/
+ 0x002A0726,
+ 0x0F120001, /*#skl_bUseOTPfunc, This is OTP on/off function*/
+ 0x002A08D6,
+ 0x0F120001, /*#ash_bUseOTPData*/
+ 0x002A146E,
+ 0x0F120000, /*#awbb_otp_disable*/
+ 0x002A08DC,
+ 0x0F120001, /*#ash_bUseGasAlphaOTP*/
+
+ /* TnP setting */
+ /* Start of Patch data */
+ 0x002A3AF8, /* TnP */
+ 0x0F12B570, /* 70003AF8 */
+ 0x0F124B36, /* 70003AFA */
+ 0x0F12216F, /* 70003AFC */
+ 0x0F124836, /* 70003AFE */
+ 0x0F128C80, /* 70003B00 */
+ 0x0F122200, /* 70003B02 */
+ 0x0F12C008, /* 70003B04 */
+ 0x0F126001, /* 70003B06 */
+ 0x0F124934, /* 70003B08 */
+ 0x0F124835, /* 70003B0A */
+ 0x0F122501, /* 70003B0C */
+ 0x0F12F000, /* 70003B0E */
+ 0x0F12FB77, /* 70003B10 */
+ 0x0F124934, /* 70003B12 */
+ 0x0F124834, /* 70003B14 */
+ 0x0F122402, /* 70003B16 */
+ 0x0F12002A, /* 70003B18 */
+ 0x0F12F000, /* 70003B1A */
+ 0x0F12FB71, /* 70003B1C */
+ 0x0F124833, /* 70003B1E */
+ 0x0F120221, /* 70003B20 */
+ 0x0F128001, /* 70003B22 */
+ 0x0F122100, /* 70003B24 */
+ 0x0F128041, /* 70003B26 */
+ 0x0F124931, /* 70003B28 */
+ 0x0F124832, /* 70003B2A */
+ 0x0F126041, /* 70003B2C */
+ 0x0F124932, /* 70003B2E */
+ 0x0F124832, /* 70003B30 */
+ 0x0F120022, /* 70003B32 */
+ 0x0F122503, /* 70003B34 */
+ 0x0F12F000, /* 70003B36 */
+ 0x0F12FB63, /* 70003B38 */
+ 0x0F12482E, /* 70003B3A */
+ 0x0F124930, /* 70003B3C */
+ 0x0F1230C0, /* 70003B3E */
+ 0x0F1263C1, /* 70003B40 */
+ 0x0F12492C, /* 70003B42 */
+ 0x0F12482F, /* 70003B44 */
+ 0x0F123980, /* 70003B46 */
+ 0x0F126408, /* 70003B48 */
+ 0x0F12482F, /* 70003B4A */
+ 0x0F12492F, /* 70003B4C */
+ 0x0F126388, /* 70003B4E */
+ 0x0F12492F, /* 70003B50 */
+ 0x0F124830, /* 70003B52 */
+ 0x0F122404, /* 70003B54 */
+ 0x0F12002A, /* 70003B56 */
+ 0x0F12F000, /* 70003B58 */
+ 0x0F12FB52, /* 70003B5A */
+ 0x0F12492E, /* 70003B5C */
+ 0x0F12482F, /* 70003B5E */
+ 0x0F120022, /* 70003B60 */
+ 0x0F122505, /* 70003B62 */
+ 0x0F12F000, /* 70003B64 */
+ 0x0F12F876, /* 70003B66 */
+ 0x0F12482C, /* 70003B68 */
+ 0x0F12492D, /* 70003B6A */
+ 0x0F122406, /* 70003B6C */
+ 0x0F12002A, /* 70003B6E */
+ 0x0F121D80, /* 70003B70 */
+ 0x0F12F000, /* 70003B72 */
+ 0x0F12F86F, /* 70003B74 */
+ 0x0F124829, /* 70003B76 */
+ 0x0F12492A, /* 70003B78 */
+ 0x0F120022, /* 70003B7A */
+ 0x0F122507, /* 70003B7C */
+ 0x0F12300C, /* 70003B7E */
+ 0x0F12F000, /* 70003B80 */
+ 0x0F12F868, /* 70003B82 */
+ 0x0F124825, /* 70003B84 */
+ 0x0F124928, /* 70003B86 */
+ 0x0F122408, /* 70003B88 */
+ 0x0F12002A, /* 70003B8A */
+ 0x0F123010, /* 70003B8C */
+ 0x0F12F000, /* 70003B8E */
+ 0x0F12F861, /* 70003B90 */
+ 0x0F124926, /* 70003B92 */
+ 0x0F124826, /* 70003B94 */
+ 0x0F120022, /* 70003B96 */
+ 0x0F122509, /* 70003B98 */
+ 0x0F12F000, /* 70003B9A */
+ 0x0F12FB31, /* 70003B9C */
+ 0x0F124925, /* 70003B9E */
+ 0x0F124825, /* 70003BA0 */
+ 0x0F12240A, /* 70003BA2 */
+ 0x0F12002A, /* 70003BA4 */
+ 0x0F12F000, /* 70003BA6 */
+ 0x0F12FB2B, /* 70003BA8 */
+ 0x0F124924, /* 70003BAA */
+ 0x0F124824, /* 70003BAC */
+ 0x0F12250B, /* 70003BAE */
+ 0x0F120022, /* 70003BB0 */
+ 0x0F12F000, /* 70003BB2 */
+ 0x0F12FB25, /* 70003BB4 */
+ 0x0F124923, /* 70003BB6 */
+ 0x0F124823, /* 70003BB8 */
+ 0x0F12002A, /* 70003BBA */
+ 0x0F12240C, /* 70003BBC */
+ 0x0F12F000, /* 70003BBE */
+ 0x0F12FB1F, /* 70003BC0 */
+ 0x0F124922, /* 70003BC2 */
+ 0x0F124822, /* 70003BC4 */
+ 0x0F120022, /* 70003BC6 */
+ 0x0F12F000, /* 70003BC8 */
+ 0x0F12FB1A, /* 70003BCA */
+ 0x0F12BC70, /* 70003BCC */
+ 0x0F12BC08, /* 70003BCE */
+ 0x0F124718, /* 70003BD0 */
+ 0x0F120000, /* 70003BD2 */
+ 0x0F120185, /* 70003BD4 */
+ 0x0F124EC2, /* 70003BD6 */
+ 0x0F121F6C, /* 70003BD8 */
+ 0x0F127000, /* 70003BDA */
+ 0x0F123C6D, /* 70003BDC */
+ 0x0F127000, /* 70003BDE */
+ 0x0F12E38B, /* 70003BE0 */
+ 0x0F120000, /* 70003BE2 */
+ 0x0F123CA5, /* 70003BE4 */
+ 0x0F127000, /* 70003BE6 */
+ 0x0F12C3B1, /* 70003BE8 */
+ 0x0F120000, /* 70003BEA */
+ 0x0F124780, /* 70003BEC */
+ 0x0F127000, /* 70003BEE */
+ 0x0F123D03, /* 70003BF0 */
+ 0x0F127000, /* 70003BF2 */
+ 0x0F120080, /* 70003BF4 */
+ 0x0F127000, /* 70003BF6 */
+ 0x0F123D3F, /* 70003BF8 */
+ 0x0F127000, /* 70003BFA */
+ 0x0F12B49D, /* 70003BFC */
+ 0x0F120000, /* 70003BFE */
+ 0x0F123DEB, /* 70003C00 */
+ 0x0F127000, /* 70003C02 */
+ 0x0F123D9F, /* 70003C04 */
+ 0x0F127000, /* 70003C06 */
+ 0x0F12FFFF, /* 70003C08 */
+ 0x0F1200FF, /* 70003C0A */
+ 0x0F1217E0, /* 70003C0C */
+ 0x0F127000, /* 70003C0E */
+ 0x0F123F67, /* 70003C10 */
+ 0x0F127000, /* 70003C12 */
+ 0x0F12053D, /* 70003C14 */
+ 0x0F120000, /* 70003C16 */
+ 0x0F120000, /* 70003C18 */
+ 0x0F120A89, /* 70003C1A */
+ 0x0F126CD2, /* 70003C1C */
+ 0x0F120000, /* 70003C1E */
+ 0x0F1202C9, /* 70003C20 */
+ 0x0F120000, /* 70003C22 */
+ 0x0F120000, /* 70003C24 */
+ 0x0F120A9A, /* 70003C26 */
+ 0x0F120000, /* 70003C28 */
+ 0x0F1202D2, /* 70003C2A */
+ 0x0F123FB5, /* 70003C2C */
+ 0x0F127000, /* 70003C2E */
+ 0x0F129E65, /* 70003C30 */
+ 0x0F120000, /* 70003C32 */
+ 0x0F124029, /* 70003C34 */
+ 0x0F127000, /* 70003C36 */
+ 0x0F127C49, /* 70003C38 */
+ 0x0F120000, /* 70003C3A */
+ 0x0F12409D, /* 70003C3C */
+ 0x0F127000, /* 70003C3E */
+ 0x0F127C63, /* 70003C40 */
+ 0x0F120000, /* 70003C42 */
+ 0x0F1240B9, /* 70003C44 */
+ 0x0F127000, /* 70003C46 */
+ 0x0F128F01, /* 70003C48 */
+ 0x0F120000, /* 70003C4A */
+ 0x0F12415B, /* 70003C4C */
+ 0x0F127000, /* 70003C4E */
+ 0x0F127F3F, /* 70003C50 */
+ 0x0F120000, /* 70003C52 */
+ 0x0F12B570, /* 70003C54 */
+ 0x0F12000C, /* 70003C56 */
+ 0x0F120015, /* 70003C58 */
+ 0x0F120029, /* 70003C5A */
+ 0x0F12F000, /* 70003C5C */
+ 0x0F12FAD8, /* 70003C5E */
+ 0x0F1249F8, /* 70003C60 */
+ 0x0F1200A8, /* 70003C62 */
+ 0x0F12500C, /* 70003C64 */
+ 0x0F12BC70, /* 70003C66 */
+ 0x0F12BC08, /* 70003C68 */
+ 0x0F124718, /* 70003C6A */
+ 0x0F126808, /* 70003C6C */
+ 0x0F120400, /* 70003C6E */
+ 0x0F120C00, /* 70003C70 */
+ 0x0F126849, /* 70003C72 */
+ 0x0F120409, /* 70003C74 */
+ 0x0F120C09, /* 70003C76 */
+ 0x0F124AF3, /* 70003C78 */
+ 0x0F128992, /* 70003C7A */
+ 0x0F122A00, /* 70003C7C */
+ 0x0F12D00D, /* 70003C7E */
+ 0x0F122300, /* 70003C80 */
+ 0x0F121A89, /* 70003C82 */
+ 0x0F12D400, /* 70003C84 */
+ 0x0F12000B, /* 70003C86 */
+ 0x0F120419, /* 70003C88 */
+ 0x0F120C09, /* 70003C8A */
+ 0x0F1223FF, /* 70003C8C */
+ 0x0F1233C1, /* 70003C8E */
+ 0x0F121810, /* 70003C90 */
+ 0x0F124298, /* 70003C92 */
+ 0x0F12D800, /* 70003C94 */
+ 0x0F120003, /* 70003C96 */
+ 0x0F120418, /* 70003C98 */
+ 0x0F120C00, /* 70003C9A */
+ 0x0F124AEB, /* 70003C9C */
+ 0x0F128150, /* 70003C9E */
+ 0x0F128191, /* 70003CA0 */
+ 0x0F124770, /* 70003CA2 */
+ 0x0F12B5F3, /* 70003CA4 */
+ 0x0F120004, /* 70003CA6 */
+ 0x0F12B081, /* 70003CA8 */
+ 0x0F129802, /* 70003CAA */
+ 0x0F126800, /* 70003CAC */
+ 0x0F120600, /* 70003CAE */
+ 0x0F120E00, /* 70003CB0 */
+ 0x0F122201, /* 70003CB2 */
+ 0x0F120015, /* 70003CB4 */
+ 0x0F120021, /* 70003CB6 */
+ 0x0F123910, /* 70003CB8 */
+ 0x0F12408A, /* 70003CBA */
+ 0x0F1240A5, /* 70003CBC */
+ 0x0F124FE4, /* 70003CBE */
+ 0x0F120016, /* 70003CC0 */
+ 0x0F122C10, /* 70003CC2 */
+ 0x0F12DA03, /* 70003CC4 */
+ 0x0F128839, /* 70003CC6 */
+ 0x0F1243A9, /* 70003CC8 */
+ 0x0F128039, /* 70003CCA */
+ 0x0F12E002, /* 70003CCC */
+ 0x0F128879, /* 70003CCE */
+ 0x0F1243B1, /* 70003CD0 */
+ 0x0F128079, /* 70003CD2 */
+ 0x0F12F000, /* 70003CD4 */
+ 0x0F12FAA4, /* 70003CD6 */
+ 0x0F122C10, /* 70003CD8 */
+ 0x0F12DA03, /* 70003CDA */
+ 0x0F128839, /* 70003CDC */
+ 0x0F124329, /* 70003CDE */
+ 0x0F128039, /* 70003CE0 */
+ 0x0F12E002, /* 70003CE2 */
+ 0x0F128879, /* 70003CE4 */
+ 0x0F124331, /* 70003CE6 */
+ 0x0F128079, /* 70003CE8 */
+ 0x0F1249DA, /* 70003CEA */
+ 0x0F128809, /* 70003CEC */
+ 0x0F122900, /* 70003CEE */
+ 0x0F12D102, /* 70003CF0 */
+ 0x0F12F000, /* 70003CF2 */
+ 0x0F12FA9D, /* 70003CF4 */
+ 0x0F122000, /* 70003CF6 */
+ 0x0F129902, /* 70003CF8 */
+ 0x0F126008, /* 70003CFA */
+ 0x0F12BCFE, /* 70003CFC */
+ 0x0F12BC08, /* 70003CFE */
+ 0x0F124718, /* 70003D00 */
+ 0x0F12B538, /* 70003D02 */
+ 0x0F129C04, /* 70003D04 */
+ 0x0F120015, /* 70003D06 */
+ 0x0F12002A, /* 70003D08 */
+ 0x0F129400, /* 70003D0A */
+ 0x0F12F000, /* 70003D0C */
+ 0x0F12FA98, /* 70003D0E */
+ 0x0F124AD1, /* 70003D10 */
+ 0x0F128811, /* 70003D12 */
+ 0x0F122900, /* 70003D14 */
+ 0x0F12D00F, /* 70003D16 */
+ 0x0F128820, /* 70003D18 */
+ 0x0F124281, /* 70003D1A */
+ 0x0F12D20C, /* 70003D1C */
+ 0x0F128861, /* 70003D1E */
+ 0x0F128853, /* 70003D20 */
+ 0x0F124299, /* 70003D22 */
+ 0x0F12D200, /* 70003D24 */
+ 0x0F121E40, /* 70003D26 */
+ 0x0F120400, /* 70003D28 */
+ 0x0F120C00, /* 70003D2A */
+ 0x0F128020, /* 70003D2C */
+ 0x0F128851, /* 70003D2E */
+ 0x0F128061, /* 70003D30 */
+ 0x0F124368, /* 70003D32 */
+ 0x0F121840, /* 70003D34 */
+ 0x0F126060, /* 70003D36 */
+ 0x0F12BC38, /* 70003D38 */
+ 0x0F12BC08, /* 70003D3A */
+ 0x0F124718, /* 70003D3C */
+ 0x0F12B5F8, /* 70003D3E */
+ 0x0F120004, /* 70003D40 */
+ 0x0F126808, /* 70003D42 */
+ 0x0F120400, /* 70003D44 */
+ 0x0F120C00, /* 70003D46 */
+ 0x0F122201, /* 70003D48 */
+ 0x0F120015, /* 70003D4A */
+ 0x0F120021, /* 70003D4C */
+ 0x0F123910, /* 70003D4E */
+ 0x0F12408A, /* 70003D50 */
+ 0x0F1240A5, /* 70003D52 */
+ 0x0F124FBE, /* 70003D54 */
+ 0x0F120016, /* 70003D56 */
+ 0x0F122C10, /* 70003D58 */
+ 0x0F12DA03, /* 70003D5A */
+ 0x0F128839, /* 70003D5C */
+ 0x0F1243A9, /* 70003D5E */
+ 0x0F128039, /* 70003D60 */
+ 0x0F12E002, /* 70003D62 */
+ 0x0F128879, /* 70003D64 */
+ 0x0F1243B1, /* 70003D66 */
+ 0x0F128079, /* 70003D68 */
+ 0x0F12F000, /* 70003D6A */
+ 0x0F12FA71, /* 70003D6C */
+ 0x0F122C10, /* 70003D6E */
+ 0x0F12DA03, /* 70003D70 */
+ 0x0F128838, /* 70003D72 */
+ 0x0F124328, /* 70003D74 */
+ 0x0F128038, /* 70003D76 */
+ 0x0F12E002, /* 70003D78 */
+ 0x0F128878, /* 70003D7A */
+ 0x0F124330, /* 70003D7C */
+ 0x0F128078, /* 70003D7E */
+ 0x0F1248B6, /* 70003D80 */
+ 0x0F128800, /* 70003D82 */
+ 0x0F120400, /* 70003D84 */
+ 0x0F12D507, /* 70003D86 */
+ 0x0F124BB5, /* 70003D88 */
+ 0x0F127819, /* 70003D8A */
+ 0x0F124AB5, /* 70003D8C */
+ 0x0F127810, /* 70003D8E */
+ 0x0F127018, /* 70003D90 */
+ 0x0F127011, /* 70003D92 */
+ 0x0F1249B4, /* 70003D94 */
+ 0x0F128188, /* 70003D96 */
+ 0x0F12BCF8, /* 70003D98 */
+ 0x0F12BC08, /* 70003D9A */
+ 0x0F124718, /* 70003D9C */
+ 0x0F12B538, /* 70003D9E */
+ 0x0F1248B2, /* 70003DA0 */
+ 0x0F124669, /* 70003DA2 */
+ 0x0F12F000, /* 70003DA4 */
+ 0x0F12FA5C, /* 70003DA6 */
+ 0x0F1248B1, /* 70003DA8 */
+ 0x0F1249B0, /* 70003DAA */
+ 0x0F1269C2, /* 70003DAC */
+ 0x0F122400, /* 70003DAE */
+ 0x0F1231A8, /* 70003DB0 */
+ 0x0F122A00, /* 70003DB2 */
+ 0x0F12D008, /* 70003DB4 */
+ 0x0F1261C4, /* 70003DB6 */
+ 0x0F12684A, /* 70003DB8 */
+ 0x0F126242, /* 70003DBA */
+ 0x0F126282, /* 70003DBC */
+ 0x0F12466B, /* 70003DBE */
+ 0x0F12881A, /* 70003DC0 */
+ 0x0F126302, /* 70003DC2 */
+ 0x0F12885A, /* 70003DC4 */
+ 0x0F126342, /* 70003DC6 */
+ 0x0F126A02, /* 70003DC8 */
+ 0x0F122A00, /* 70003DCA */
+ 0x0F12D00A, /* 70003DCC */
+ 0x0F126204, /* 70003DCE */
+ 0x0F126849, /* 70003DD0 */
+ 0x0F126281, /* 70003DD2 */
+ 0x0F12466B, /* 70003DD4 */
+ 0x0F128819, /* 70003DD6 */
+ 0x0F126301, /* 70003DD8 */
+ 0x0F128859, /* 70003DDA */
+ 0x0F126341, /* 70003DDC */
+ 0x0F1249A5, /* 70003DDE */
+ 0x0F1288C9, /* 70003DE0 */
+ 0x0F1263C1, /* 70003DE2 */
+ 0x0F12F000, /* 70003DE4 */
+ 0x0F12FA44, /* 70003DE6 */
+ 0x0F12E7A6, /* 70003DE8 */
+ 0x0F12B5F0, /* 70003DEA */
+ 0x0F12B08B, /* 70003DEC */
+ 0x0F1220FF, /* 70003DEE */
+ 0x0F121C40, /* 70003DF0 */
+ 0x0F1249A1, /* 70003DF2 */
+ 0x0F1289CC, /* 70003DF4 */
+ 0x0F124E9E, /* 70003DF6 */
+ 0x0F126AB1, /* 70003DF8 */
+ 0x0F124284, /* 70003DFA */
+ 0x0F12D101, /* 70003DFC */
+ 0x0F12489F, /* 70003DFE */
+ 0x0F126081, /* 70003E00 */
+ 0x0F126A70, /* 70003E02 */
+ 0x0F120200, /* 70003E04 */
+ 0x0F12F000, /* 70003E06 */
+ 0x0F12FA3B, /* 70003E08 */
+ 0x0F120400, /* 70003E0A */
+ 0x0F120C00, /* 70003E0C */
+ 0x0F124A96, /* 70003E0E */
+ 0x0F128A11, /* 70003E10 */
+ 0x0F129109, /* 70003E12 */
+ 0x0F122101, /* 70003E14 */
+ 0x0F120349, /* 70003E16 */
+ 0x0F124288, /* 70003E18 */
+ 0x0F12D200, /* 70003E1A */
+ 0x0F120001, /* 70003E1C */
+ 0x0F124A92, /* 70003E1E */
+ 0x0F128211, /* 70003E20 */
+ 0x0F124D97, /* 70003E22 */
+ 0x0F128829, /* 70003E24 */
+ 0x0F129108, /* 70003E26 */
+ 0x0F124A8B, /* 70003E28 */
+ 0x0F122303, /* 70003E2A */
+ 0x0F123222, /* 70003E2C */
+ 0x0F121F91, /* 70003E2E */
+ 0x0F12F000, /* 70003E30 */
+ 0x0F12FA2C, /* 70003E32 */
+ 0x0F128028, /* 70003E34 */
+ 0x0F12488E, /* 70003E36 */
+ 0x0F124987, /* 70003E38 */
+ 0x0F126BC2, /* 70003E3A */
+ 0x0F126AC0, /* 70003E3C */
+ 0x0F124282, /* 70003E3E */
+ 0x0F12D201, /* 70003E40 */
+ 0x0F128CC8, /* 70003E42 */
+ 0x0F128028, /* 70003E44 */
+ 0x0F1288E8, /* 70003E46 */
+ 0x0F129007, /* 70003E48 */
+ 0x0F122240, /* 70003E4A */
+ 0x0F124310, /* 70003E4C */
+ 0x0F1280E8, /* 70003E4E */
+ 0x0F122000, /* 70003E50 */
+ 0x0F120041, /* 70003E52 */
+ 0x0F12194B, /* 70003E54 */
+ 0x0F12001E, /* 70003E56 */
+ 0x0F123680, /* 70003E58 */
+ 0x0F128BB2, /* 70003E5A */
+ 0x0F12AF04, /* 70003E5C */
+ 0x0F12527A, /* 70003E5E */
+ 0x0F124A7D, /* 70003E60 */
+ 0x0F12188A, /* 70003E62 */
+ 0x0F128897, /* 70003E64 */
+ 0x0F1283B7, /* 70003E66 */
+ 0x0F1233A0, /* 70003E68 */
+ 0x0F12891F, /* 70003E6A */
+ 0x0F12AE01, /* 70003E6C */
+ 0x0F125277, /* 70003E6E */
+ 0x0F128A11, /* 70003E70 */
+ 0x0F128119, /* 70003E72 */
+ 0x0F121C40, /* 70003E74 */
+ 0x0F120400, /* 70003E76 */
+ 0x0F120C00, /* 70003E78 */
+ 0x0F122806, /* 70003E7A */
+ 0x0F12D3E9, /* 70003E7C */
+ 0x0F12F000, /* 70003E7E */
+ 0x0F12FA0D, /* 70003E80 */
+ 0x0F12F000, /* 70003E82 */
+ 0x0F12FA13, /* 70003E84 */
+ 0x0F124F79, /* 70003E86 */
+ 0x0F1237A8, /* 70003E88 */
+ 0x0F122800, /* 70003E8A */
+ 0x0F12D10A, /* 70003E8C */
+ 0x0F121FE0, /* 70003E8E */
+ 0x0F1238FD, /* 70003E90 */
+ 0x0F12D001, /* 70003E92 */
+ 0x0F121CC0, /* 70003E94 */
+ 0x0F12D105, /* 70003E96 */
+ 0x0F124874, /* 70003E98 */
+ 0x0F128829, /* 70003E9A */
+ 0x0F123818, /* 70003E9C */
+ 0x0F126840, /* 70003E9E */
+ 0x0F124348, /* 70003EA0 */
+ 0x0F126078, /* 70003EA2 */
+ 0x0F124972, /* 70003EA4 */
+ 0x0F126878, /* 70003EA6 */
+ 0x0F126B89, /* 70003EA8 */
+ 0x0F124288, /* 70003EAA */
+ 0x0F12D300, /* 70003EAC */
+ 0x0F120008, /* 70003EAE */
+ 0x0F126078, /* 70003EB0 */
+ 0x0F122000, /* 70003EB2 */
+ 0x0F120041, /* 70003EB4 */
+ 0x0F12AA04, /* 70003EB6 */
+ 0x0F125A53, /* 70003EB8 */
+ 0x0F12194A, /* 70003EBA */
+ 0x0F12269C, /* 70003EBC */
+ 0x0F1252B3, /* 70003EBE */
+ 0x0F12AB01, /* 70003EC0 */
+ 0x0F125A59, /* 70003EC2 */
+ 0x0F1232A0, /* 70003EC4 */
+ 0x0F128111, /* 70003EC6 */
+ 0x0F121C40, /* 70003EC8 */
+ 0x0F120400, /* 70003ECA */
+ 0x0F120C00, /* 70003ECC */
+ 0x0F122806, /* 70003ECE */
+ 0x0F12D3F0, /* 70003ED0 */
+ 0x0F124965, /* 70003ED2 */
+ 0x0F129809, /* 70003ED4 */
+ 0x0F128208, /* 70003ED6 */
+ 0x0F129808, /* 70003ED8 */
+ 0x0F128028, /* 70003EDA */
+ 0x0F129807, /* 70003EDC */
+ 0x0F1280E8, /* 70003EDE */
+ 0x0F121FE0, /* 70003EE0 */
+ 0x0F1238FD, /* 70003EE2 */
+ 0x0F12D13B, /* 70003EE4 */
+ 0x0F124D64, /* 70003EE6 */
+ 0x0F1289E8, /* 70003EE8 */
+ 0x0F121FC1, /* 70003EEA */
+ 0x0F1239FF, /* 70003EEC */
+ 0x0F12D136, /* 70003EEE */
+ 0x0F124C5F, /* 70003EF0 */
+ 0x0F128AE0, /* 70003EF2 */
+ 0x0F12F000, /* 70003EF4 */
+ 0x0F12F9E2, /* 70003EF6 */
+ 0x0F120006, /* 70003EF8 */
+ 0x0F128B20, /* 70003EFA */
+ 0x0F12F000, /* 70003EFC */
+ 0x0F12F9E6, /* 70003EFE */
+ 0x0F129000, /* 70003F00 */
+ 0x0F126AA1, /* 70003F02 */
+ 0x0F126878, /* 70003F04 */
+ 0x0F121809, /* 70003F06 */
+ 0x0F120200, /* 70003F08 */
+ 0x0F12F000, /* 70003F0A */
+ 0x0F12F9B9, /* 70003F0C */
+ 0x0F120400, /* 70003F0E */
+ 0x0F120C00, /* 70003F10 */
+ 0x0F120022, /* 70003F12 */
+ 0x0F123246, /* 70003F14 */
+ 0x0F120011, /* 70003F16 */
+ 0x0F12310A, /* 70003F18 */
+ 0x0F122305, /* 70003F1A */
+ 0x0F12F000, /* 70003F1C */
+ 0x0F12F9B6, /* 70003F1E */
+ 0x0F1266E8, /* 70003F20 */
+ 0x0F126B23, /* 70003F22 */
+ 0x0F120002, /* 70003F24 */
+ 0x0F120031, /* 70003F26 */
+ 0x0F120018, /* 70003F28 */
+ 0x0F12F000, /* 70003F2A */
+ 0x0F12F9D7, /* 70003F2C */
+ 0x0F12466B, /* 70003F2E */
+ 0x0F128518, /* 70003F30 */
+ 0x0F126EEA, /* 70003F32 */
+ 0x0F126B60, /* 70003F34 */
+ 0x0F129900, /* 70003F36 */
+ 0x0F12F000, /* 70003F38 */
+ 0x0F12F9D0, /* 70003F3A */
+ 0x0F12466B, /* 70003F3C */
+ 0x0F128558, /* 70003F3E */
+ 0x0F120029, /* 70003F40 */
+ 0x0F12980A, /* 70003F42 */
+ 0x0F123170, /* 70003F44 */
+ 0x0F12F000, /* 70003F46 */
+ 0x0F12F9D1, /* 70003F48 */
+ 0x0F120028, /* 70003F4A */
+ 0x0F123060, /* 70003F4C */
+ 0x0F128A02, /* 70003F4E */
+ 0x0F124946, /* 70003F50 */
+ 0x0F123128, /* 70003F52 */
+ 0x0F12808A, /* 70003F54 */
+ 0x0F128A42, /* 70003F56 */
+ 0x0F1280CA, /* 70003F58 */
+ 0x0F128A80, /* 70003F5A */
+ 0x0F128108, /* 70003F5C */
+ 0x0F12B00B, /* 70003F5E */
+ 0x0F12BCF0, /* 70003F60 */
+ 0x0F12BC08, /* 70003F62 */
+ 0x0F124718, /* 70003F64 */
+ 0x0F12B570, /* 70003F66 */
+ 0x0F122400, /* 70003F68 */
+ 0x0F124D46, /* 70003F6A */
+ 0x0F124846, /* 70003F6C */
+ 0x0F128881, /* 70003F6E */
+ 0x0F124846, /* 70003F70 */
+ 0x0F128041, /* 70003F72 */
+ 0x0F122101, /* 70003F74 */
+ 0x0F128001, /* 70003F76 */
+ 0x0F12F000, /* 70003F78 */
+ 0x0F12F9C0, /* 70003F7A */
+ 0x0F124842, /* 70003F7C */
+ 0x0F123820, /* 70003F7E */
+ 0x0F128BC0, /* 70003F80 */
+ 0x0F12F000, /* 70003F82 */
+ 0x0F12F9C3, /* 70003F84 */
+ 0x0F124B42, /* 70003F86 */
+ 0x0F12220D, /* 70003F88 */
+ 0x0F120712, /* 70003F8A */
+ 0x0F1218A8, /* 70003F8C */
+ 0x0F128806, /* 70003F8E */
+ 0x0F1200E1, /* 70003F90 */
+ 0x0F1218C9, /* 70003F92 */
+ 0x0F1281CE, /* 70003F94 */
+ 0x0F128846, /* 70003F96 */
+ 0x0F12818E, /* 70003F98 */
+ 0x0F128886, /* 70003F9A */
+ 0x0F12824E, /* 70003F9C */
+ 0x0F1288C0, /* 70003F9E */
+ 0x0F128208, /* 70003FA0 */
+ 0x0F123508, /* 70003FA2 */
+ 0x0F12042D, /* 70003FA4 */
+ 0x0F120C2D, /* 70003FA6 */
+ 0x0F121C64, /* 70003FA8 */
+ 0x0F120424, /* 70003FAA */
+ 0x0F120C24, /* 70003FAC */
+ 0x0F122C07, /* 70003FAE */
+ 0x0F12D3EC, /* 70003FB0 */
+ 0x0F12E658, /* 70003FB2 */
+ 0x0F12B510, /* 70003FB4 */
+ 0x0F124834, /* 70003FB6 */
+ 0x0F124C34, /* 70003FB8 */
+ 0x0F1288C0, /* 70003FBA */
+ 0x0F128060, /* 70003FBC */
+ 0x0F122001, /* 70003FBE */
+ 0x0F128020, /* 70003FC0 */
+ 0x0F124831, /* 70003FC2 */
+ 0x0F123820, /* 70003FC4 */
+ 0x0F128BC0, /* 70003FC6 */
+ 0x0F12F000, /* 70003FC8 */
+ 0x0F12F9A0, /* 70003FCA */
+ 0x0F1288E0, /* 70003FCC */
+ 0x0F124A31, /* 70003FCE */
+ 0x0F122800, /* 70003FD0 */
+ 0x0F12D003, /* 70003FD2 */
+ 0x0F124930, /* 70003FD4 */
+ 0x0F128849, /* 70003FD6 */
+ 0x0F122900, /* 70003FD8 */
+ 0x0F12D009, /* 70003FDA */
+ 0x0F122001, /* 70003FDC */
+ 0x0F1203C0, /* 70003FDE */
+ 0x0F128050, /* 70003FE0 */
+ 0x0F1280D0, /* 70003FE2 */
+ 0x0F122000, /* 70003FE4 */
+ 0x0F128090, /* 70003FE6 */
+ 0x0F128110, /* 70003FE8 */
+ 0x0F12BC10, /* 70003FEA */
+ 0x0F12BC08, /* 70003FEC */
+ 0x0F124718, /* 70003FEE */
+ 0x0F128050, /* 70003FF0 */
+ 0x0F128920, /* 70003FF2 */
+ 0x0F1280D0, /* 70003FF4 */
+ 0x0F128960, /* 70003FF6 */
+ 0x0F120400, /* 70003FF8 */
+ 0x0F121400, /* 70003FFA */
+ 0x0F128090, /* 70003FFC */
+ 0x0F1289A1, /* 70003FFE */
+ 0x0F120409, /* 70004000 */
+ 0x0F121409, /* 70004002 */
+ 0x0F128111, /* 70004004 */
+ 0x0F1289E3, /* 70004006 */
+ 0x0F128A24, /* 70004008 */
+ 0x0F122B00, /* 7000400A */
+ 0x0F12D104, /* 7000400C */
+ 0x0F1217C3, /* 7000400E */
+ 0x0F120F5B, /* 70004010 */
+ 0x0F121818, /* 70004012 */
+ 0x0F1210C0, /* 70004014 */
+ 0x0F128090, /* 70004016 */
+ 0x0F122C00, /* 70004018 */
+ 0x0F12D1E6, /* 7000401A */
+ 0x0F1217C8, /* 7000401C */
+ 0x0F120F40, /* 7000401E */
+ 0x0F121840, /* 70004020 */
+ 0x0F1210C0, /* 70004022 */
+ 0x0F128110, /* 70004024 */
+ 0x0F12E7E0, /* 70004026 */
+ 0x0F12B510, /* 70004028 */
+ 0x0F12000C, /* 7000402A */
+ 0x0F124919, /* 7000402C */
+ 0x0F122204, /* 7000402E */
+ 0x0F126820, /* 70004030 */
+ 0x0F125E8A, /* 70004032 */
+ 0x0F120140, /* 70004034 */
+ 0x0F121A80, /* 70004036 */
+ 0x0F120280, /* 70004038 */
+ 0x0F128849, /* 7000403A */
+ 0x0F12F000, /* 7000403C */
+ 0x0F12F96E, /* 7000403E */
+ 0x0F126020, /* 70004040 */
+ 0x0F12E7D2, /* 70004042 */
+ 0x0F1238D4, /* 70004044 */
+ 0x0F127000, /* 70004046 */
+ 0x0F1217D0, /* 70004048 */
+ 0x0F127000, /* 7000404A */
+ 0x0F125000, /* 7000404C */
+ 0x0F12D000, /* 7000404E */
+ 0x0F121100, /* 70004050 */
+ 0x0F12D000, /* 70004052 */
+ 0x0F12171A, /* 70004054 */
+ 0x0F127000, /* 70004056 */
+ 0x0F124780, /* 70004058 */
+ 0x0F127000, /* 7000405A */
+ 0x0F122FCA, /* 7000405C */
+ 0x0F127000, /* 7000405E */
+ 0x0F122FC5, /* 70004060 */
+ 0x0F127000, /* 70004062 */
+ 0x0F122FC6, /* 70004064 */
+ 0x0F127000, /* 70004066 */
+ 0x0F122ED8, /* 70004068 */
+ 0x0F127000, /* 7000406A */
+ 0x0F122BD0, /* 7000406C */
+ 0x0F127000, /* 7000406E */
+ 0x0F1217E0, /* 70004070 */
+ 0x0F127000, /* 70004072 */
+ 0x0F122DE8, /* 70004074 */
+ 0x0F127000, /* 70004076 */
+ 0x0F1237E0, /* 70004078 */
+ 0x0F127000, /* 7000407A */
+ 0x0F12210C, /* 7000407C */
+ 0x0F127000, /* 7000407E */
+ 0x0F121484, /* 70004080 */
+ 0x0F127000, /* 70004082 */
+ 0x0F12A006, /* 70004084 */
+ 0x0F120000, /* 70004086 */
+ 0x0F120724, /* 70004088 */
+ 0x0F127000, /* 7000408A */
+ 0x0F12A000, /* 7000408C */
+ 0x0F12D000, /* 7000408E */
+ 0x0F122270, /* 70004090 */
+ 0x0F127000, /* 70004092 */
+ 0x0F122558, /* 70004094 */
+ 0x0F127000, /* 70004096 */
+ 0x0F12146C, /* 70004098 */
+ 0x0F127000, /* 7000409A */
+ 0x0F12B510, /* 7000409C */
+ 0x0F12000C, /* 7000409E */
+ 0x0F124951, /* 700040A0 */
+ 0x0F122208, /* 700040A2 */
+ 0x0F126820, /* 700040A4 */
+ 0x0F125E8A, /* 700040A6 */
+ 0x0F120140, /* 700040A8 */
+ 0x0F121A80, /* 700040AA */
+ 0x0F120280, /* 700040AC */
+ 0x0F1288C9, /* 700040AE */
+ 0x0F12F000, /* 700040B0 */
+ 0x0F12F934, /* 700040B2 */
+ 0x0F126020, /* 700040B4 */
+ 0x0F12E798, /* 700040B6 */
+ 0x0F12B5FE, /* 700040B8 */
+ 0x0F12000C, /* 700040BA */
+ 0x0F126825, /* 700040BC */
+ 0x0F126866, /* 700040BE */
+ 0x0F1268A0, /* 700040C0 */
+ 0x0F129001, /* 700040C2 */
+ 0x0F1268E7, /* 700040C4 */
+ 0x0F121BA8, /* 700040C6 */
+ 0x0F1242B5, /* 700040C8 */
+ 0x0F12DA00, /* 700040CA */
+ 0x0F121B70, /* 700040CC */
+ 0x0F129000, /* 700040CE */
+ 0x0F124945, /* 700040D0 */
+ 0x0F124846, /* 700040D2 */
+ 0x0F12884A, /* 700040D4 */
+ 0x0F128843, /* 700040D6 */
+ 0x0F12435A, /* 700040D8 */
+ 0x0F122304, /* 700040DA */
+ 0x0F125ECB, /* 700040DC */
+ 0x0F120A92, /* 700040DE */
+ 0x0F1218D2, /* 700040E0 */
+ 0x0F1202D2, /* 700040E2 */
+ 0x0F120C12, /* 700040E4 */
+ 0x0F1288CB, /* 700040E6 */
+ 0x0F128880, /* 700040E8 */
+ 0x0F124343, /* 700040EA */
+ 0x0F120A98, /* 700040EC */
+ 0x0F122308, /* 700040EE */
+ 0x0F125ECB, /* 700040F0 */
+ 0x0F1218C0, /* 700040F2 */
+ 0x0F1202C0, /* 700040F4 */
+ 0x0F120C00, /* 700040F6 */
+ 0x0F120411, /* 700040F8 */
+ 0x0F120400, /* 700040FA */
+ 0x0F121409, /* 700040FC */
+ 0x0F121400, /* 700040FE */
+ 0x0F121A08, /* 70004100 */
+ 0x0F12493A, /* 70004102 */
+ 0x0F1239E0, /* 70004104 */
+ 0x0F126148, /* 70004106 */
+ 0x0F129801, /* 70004108 */
+ 0x0F123040, /* 7000410A */
+ 0x0F127880, /* 7000410C */
+ 0x0F122800, /* 7000410E */
+ 0x0F12D103, /* 70004110 */
+ 0x0F129801, /* 70004112 */
+ 0x0F120029, /* 70004114 */
+ 0x0F12F000, /* 70004116 */
+ 0x0F12F907, /* 70004118 */
+ 0x0F128839, /* 7000411A */
+ 0x0F129800, /* 7000411C */
+ 0x0F124281, /* 7000411E */
+ 0x0F12D814, /* 70004120 */
+ 0x0F128879, /* 70004122 */
+ 0x0F129800, /* 70004124 */
+ 0x0F124281, /* 70004126 */
+ 0x0F12D20C, /* 70004128 */
+ 0x0F129801, /* 7000412A */
+ 0x0F120029, /* 7000412C */
+ 0x0F12F000, /* 7000412E */
+ 0x0F12F903, /* 70004130 */
+ 0x0F129801, /* 70004132 */
+ 0x0F120029, /* 70004134 */
+ 0x0F12F000, /* 70004136 */
+ 0x0F12F8FF, /* 70004138 */
+ 0x0F129801, /* 7000413A */
+ 0x0F120029, /* 7000413C */
+ 0x0F12F000, /* 7000413E */
+ 0x0F12F8FB, /* 70004140 */
+ 0x0F12E003, /* 70004142 */
+ 0x0F129801, /* 70004144 */
+ 0x0F120029, /* 70004146 */
+ 0x0F12F000, /* 70004148 */
+ 0x0F12F8F6, /* 7000414A */
+ 0x0F129801, /* 7000414C */
+ 0x0F120032, /* 7000414E */
+ 0x0F120039, /* 70004150 */
+ 0x0F12F000, /* 70004152 */
+ 0x0F12F8F9, /* 70004154 */
+ 0x0F126020, /* 70004156 */
+ 0x0F12E5D0, /* 70004158 */
+ 0x0F12B57C, /* 7000415A */
+ 0x0F124824, /* 7000415C */
+ 0x0F12A901, /* 7000415E */
+ 0x0F120004, /* 70004160 */
+ 0x0F12F000, /* 70004162 */
+ 0x0F12F87D, /* 70004164 */
+ 0x0F12466B, /* 70004166 */
+ 0x0F1288D9, /* 70004168 */
+ 0x0F128898, /* 7000416A */
+ 0x0F124B1F, /* 7000416C */
+ 0x0F123346, /* 7000416E */
+ 0x0F121E9A, /* 70004170 */
+ 0x0F12F000, /* 70004172 */
+ 0x0F12F8F1, /* 70004174 */
+ 0x0F12481E, /* 70004176 */
+ 0x0F12491C, /* 70004178 */
+ 0x0F123812, /* 7000417A */
+ 0x0F123140, /* 7000417C */
+ 0x0F128A42, /* 7000417E */
+ 0x0F12888B, /* 70004180 */
+ 0x0F1218D2, /* 70004182 */
+ 0x0F128242, /* 70004184 */
+ 0x0F128AC2, /* 70004186 */
+ 0x0F1288C9, /* 70004188 */
+ 0x0F121851, /* 7000418A */
+ 0x0F1282C1, /* 7000418C */
+ 0x0F120020, /* 7000418E */
+ 0x0F124669, /* 70004190 */
+ 0x0F12F000, /* 70004192 */
+ 0x0F12F865, /* 70004194 */
+ 0x0F124817, /* 70004196 */
+ 0x0F12214D, /* 70004198 */
+ 0x0F128301, /* 7000419A */
+ 0x0F122196, /* 7000419C */
+ 0x0F128381, /* 7000419E */
+ 0x0F12211D, /* 700041A0 */
+ 0x0F123020, /* 700041A2 */
+ 0x0F128001, /* 700041A4 */
+ 0x0F12F000, /* 700041A6 */
+ 0x0F12F8DF, /* 700041A8 */
+ 0x0F12F000, /* 700041AA */
+ 0x0F12F8E5, /* 700041AC */
+ 0x0F124812, /* 700041AE */
+ 0x0F124C12, /* 700041B0 */
+ 0x0F126E00, /* 700041B2 */
+ 0x0F1260E0, /* 700041B4 */
+ 0x0F12466B, /* 700041B6 */
+ 0x0F128818, /* 700041B8 */
+ 0x0F128859, /* 700041BA */
+ 0x0F120025, /* 700041BC */
+ 0x0F121A40, /* 700041BE */
+ 0x0F123540, /* 700041C0 */
+ 0x0F1261A8, /* 700041C2 */
+ 0x0F124809, /* 700041C4 */
+ 0x0F129900, /* 700041C6 */
+ 0x0F123060, /* 700041C8 */
+ 0x0F12F000, /* 700041CA */
+ 0x0F12F8DD, /* 700041CC */
+ 0x0F12466B, /* 700041CE */
+ 0x0F128819, /* 700041D0 */
+ 0x0F121DE0, /* 700041D2 */
+ 0x0F1230F9, /* 700041D4 */
+ 0x0F128741, /* 700041D6 */
+ 0x0F128859, /* 700041D8 */
+ 0x0F128781, /* 700041DA */
+ 0x0F122000, /* 700041DC */
+ 0x0F1271A0, /* 700041DE */
+ 0x0F1274A8, /* 700041E0 */
+ 0x0F12BC7C, /* 700041E2 */
+ 0x0F12BC08, /* 700041E4 */
+ 0x0F124718, /* 700041E6 */
+ 0x0F122558, /* 700041E8 */
+ 0x0F127000, /* 700041EA */
+ 0x0F122AB8, /* 700041EC */
+ 0x0F127000, /* 700041EE */
+ 0x0F12145E, /* 700041F0 */
+ 0x0F127000, /* 700041F2 */
+ 0x0F122698, /* 700041F4 */
+ 0x0F127000, /* 700041F6 */
+ 0x0F122BB8, /* 700041F8 */
+ 0x0F127000, /* 700041FA */
+ 0x0F122998, /* 700041FC */
+ 0x0F127000, /* 700041FE */
+ 0x0F124778, /* 70004200 */
+ 0x0F1246C0, /* 70004202 */
+ 0x0F12C000, /* 70004204 */
+ 0x0F12E59F, /* 70004206 */
+ 0x0F12FF1C, /* 70004208 */
+ 0x0F12E12F, /* 7000420A */
+ 0x0F121789, /* 7000420C */
+ 0x0F120001, /* 7000420E */
+ 0x0F124778, /* 70004210 */
+ 0x0F1246C0, /* 70004212 */
+ 0x0F12C000, /* 70004214 */
+ 0x0F12E59F, /* 70004216 */
+ 0x0F12FF1C, /* 70004218 */
+ 0x0F12E12F, /* 7000421A */
+ 0x0F1216F1, /* 7000421C */
+ 0x0F120001, /* 7000421E */
+ 0x0F124778, /* 70004220 */
+ 0x0F1246C0, /* 70004222 */
+ 0x0F12C000, /* 70004224 */
+ 0x0F12E59F, /* 70004226 */
+ 0x0F12FF1C, /* 70004228 */
+ 0x0F12E12F, /* 7000422A */
+ 0x0F12C3B1, /* 7000422C */
+ 0x0F120000, /* 7000422E */
+ 0x0F124778, /* 70004230 */
+ 0x0F1246C0, /* 70004232 */
+ 0x0F12C000, /* 70004234 */
+ 0x0F12E59F, /* 70004236 */
+ 0x0F12FF1C, /* 70004238 */
+ 0x0F12E12F, /* 7000423A */
+ 0x0F12C36D, /* 7000423C */
+ 0x0F120000, /* 7000423E */
+ 0x0F124778, /* 70004240 */
+ 0x0F1246C0, /* 70004242 */
+ 0x0F12C000, /* 70004244 */
+ 0x0F12E59F, /* 70004246 */
+ 0x0F12FF1C, /* 70004248 */
+ 0x0F12E12F, /* 7000424A */
+ 0x0F12F6D7, /* 7000424C */
+ 0x0F120000, /* 7000424E */
+ 0x0F124778, /* 70004250 */
+ 0x0F1246C0, /* 70004252 */
+ 0x0F12C000, /* 70004254 */
+ 0x0F12E59F, /* 70004256 */
+ 0x0F12FF1C, /* 70004258 */
+ 0x0F12E12F, /* 7000425A */
+ 0x0F12B49D, /* 7000425C */
+ 0x0F120000, /* 7000425E */
+ 0x0F124778, /* 70004260 */
+ 0x0F1246C0, /* 70004262 */
+ 0x0F12C000, /* 70004264 */
+ 0x0F12E59F, /* 70004266 */
+ 0x0F12FF1C, /* 70004268 */
+ 0x0F12E12F, /* 7000426A */
+ 0x0F127EDF, /* 7000426C */
+ 0x0F120000, /* 7000426E */
+ 0x0F124778, /* 70004270 */
+ 0x0F1246C0, /* 70004272 */
+ 0x0F12C000, /* 70004274 */
+ 0x0F12E59F, /* 70004276 */
+ 0x0F12FF1C, /* 70004278 */
+ 0x0F12E12F, /* 7000427A */
+ 0x0F12448D, /* 7000427C */
+ 0x0F120000, /* 7000427E */
+ 0x0F124778, /* 70004280 */
+ 0x0F1246C0, /* 70004282 */
+ 0x0F12F004, /* 70004284 */
+ 0x0F12E51F, /* 70004286 */
+ 0x0F1229EC, /* 70004288 */
+ 0x0F120001, /* 7000428A */
+ 0x0F124778, /* 7000428C */
+ 0x0F1246C0, /* 7000428E */
+ 0x0F12C000, /* 70004290 */
+ 0x0F12E59F, /* 70004292 */
+ 0x0F12FF1C, /* 70004294 */
+ 0x0F12E12F, /* 70004296 */
+ 0x0F122EF1, /* 70004298 */
+ 0x0F120000, /* 7000429A */
+ 0x0F124778, /* 7000429C */
+ 0x0F1246C0, /* 7000429E */
+ 0x0F12C000, /* 700042A0 */
+ 0x0F12E59F, /* 700042A2 */
+ 0x0F12FF1C, /* 700042A4 */
+ 0x0F12E12F, /* 700042A6 */
+ 0x0F12EE03, /* 700042A8 */
+ 0x0F120000, /* 700042AA */
+ 0x0F124778, /* 700042AC */
+ 0x0F1246C0, /* 700042AE */
+ 0x0F12C000, /* 700042B0 */
+ 0x0F12E59F, /* 700042B2 */
+ 0x0F12FF1C, /* 700042B4 */
+ 0x0F12E12F, /* 700042B6 */
+ 0x0F12A58B, /* 700042B8 */
+ 0x0F120000, /* 700042BA */
+ 0x0F124778, /* 700042BC */
+ 0x0F1246C0, /* 700042BE */
+ 0x0F12C000, /* 700042C0 */
+ 0x0F12E59F, /* 700042C2 */
+ 0x0F12FF1C, /* 700042C4 */
+ 0x0F12E12F, /* 700042C6 */
+ 0x0F127C49, /* 700042C8 */
+ 0x0F120000, /* 700042CA */
+ 0x0F124778, /* 700042CC */
+ 0x0F1246C0, /* 700042CE */
+ 0x0F12C000, /* 700042D0 */
+ 0x0F12E59F, /* 700042D2 */
+ 0x0F12FF1C, /* 700042D4 */
+ 0x0F12E12F, /* 700042D6 */
+ 0x0F127C63, /* 700042D8 */
+ 0x0F120000, /* 700042DA */
+ 0x0F124778, /* 700042DC */
+ 0x0F1246C0, /* 700042DE */
+ 0x0F12C000, /* 700042E0 */
+ 0x0F12E59F, /* 700042E2 */
+ 0x0F12FF1C, /* 700042E4 */
+ 0x0F12E12F, /* 700042E6 */
+ 0x0F122DB7, /* 700042E8 */
+ 0x0F120000, /* 700042EA */
+ 0x0F124778, /* 700042EC */
+ 0x0F1246C0, /* 700042EE */
+ 0x0F12C000, /* 700042F0 */
+ 0x0F12E59F, /* 700042F2 */
+ 0x0F12FF1C, /* 700042F4 */
+ 0x0F12E12F, /* 700042F6 */
+ 0x0F12EB3D, /* 700042F8 */
+ 0x0F120000, /* 700042FA */
+ 0x0F124778, /* 700042FC */
+ 0x0F1246C0, /* 700042FE */
+ 0x0F12C000, /* 70004300 */
+ 0x0F12E59F, /* 70004302 */
+ 0x0F12FF1C, /* 70004304 */
+ 0x0F12E12F, /* 70004306 */
+ 0x0F12F061, /* 70004308 */
+ 0x0F120000, /* 7000430A */
+ 0x0F124778, /* 7000430C */
+ 0x0F1246C0, /* 7000430E */
+ 0x0F12C000, /* 70004310 */
+ 0x0F12E59F, /* 70004312 */
+ 0x0F12FF1C, /* 70004314 */
+ 0x0F12E12F, /* 70004316 */
+ 0x0F12F0EF, /* 70004318 */
+ 0x0F120000, /* 7000431A */
+ 0x0F124778, /* 7000431C */
+ 0x0F1246C0, /* 7000431E */
+ 0x0F12F004, /* 70004320 */
+ 0x0F12E51F, /* 70004322 */
+ 0x0F122824, /* 70004324 */
+ 0x0F120001, /* 70004326 */
+ 0x0F124778, /* 70004328 */
+ 0x0F1246C0, /* 7000432A */
+ 0x0F12C000, /* 7000432C */
+ 0x0F12E59F, /* 7000432E */
+ 0x0F12FF1C, /* 70004330 */
+ 0x0F12E12F, /* 70004332 */
+ 0x0F128EDD, /* 70004334 */
+ 0x0F120000, /* 70004336 */
+ 0x0F124778, /* 70004338 */
+ 0x0F1246C0, /* 7000433A */
+ 0x0F12C000, /* 7000433C */
+ 0x0F12E59F, /* 7000433E */
+ 0x0F12FF1C, /* 70004340 */
+ 0x0F12E12F, /* 70004342 */
+ 0x0F128DCB, /* 70004344 */
+ 0x0F120000, /* 70004346 */
+ 0x0F124778, /* 70004348 */
+ 0x0F1246C0, /* 7000434A */
+ 0x0F12C000, /* 7000434C */
+ 0x0F12E59F, /* 7000434E */
+ 0x0F12FF1C, /* 70004350 */
+ 0x0F12E12F, /* 70004352 */
+ 0x0F128E17, /* 70004354 */
+ 0x0F120000, /* 70004356 */
+ 0x0F124778, /* 70004358 */
+ 0x0F1246C0, /* 7000435A */
+ 0x0F12C000, /* 7000435C */
+ 0x0F12E59F, /* 7000435E */
+ 0x0F12FF1C, /* 70004360 */
+ 0x0F12E12F, /* 70004362 */
+ 0x0F1298C5, /* 70004364 */
+ 0x0F120000, /* 70004366 */
+ 0x0F124778, /* 70004368 */
+ 0x0F1246C0, /* 7000436A */
+ 0x0F12C000, /* 7000436C */
+ 0x0F12E59F, /* 7000436E */
+ 0x0F12FF1C, /* 70004370 */
+ 0x0F12E12F, /* 70004372 */
+ 0x0F127C7D, /* 70004374 */
+ 0x0F120000, /* 70004376 */
+ 0x0F124778, /* 70004378 */
+ 0x0F1246C0, /* 7000437A */
+ 0x0F12C000, /* 7000437C */
+ 0x0F12E59F, /* 7000437E */
+ 0x0F12FF1C, /* 70004380 */
+ 0x0F12E12F, /* 70004382 */
+ 0x0F127E31, /* 70004384 */
+ 0x0F120000, /* 70004386 */
+ 0x0F124778, /* 70004388 */
+ 0x0F1246C0, /* 7000438A */
+ 0x0F12C000, /* 7000438C */
+ 0x0F12E59F, /* 7000438E */
+ 0x0F12FF1C, /* 70004390 */
+ 0x0F12E12F, /* 70004392 */
+ 0x0F127EAB, /* 70004394 */
+ 0x0F120000, /* 70004396 */
+ /* End of Patch Data(Last : 70004396h)*/
+ /* Total Size 2208 (08A0) */
+ /* Addr : 3AF8 , Size : 2206(89Eh) */
+
+ /*#define TNP_USER_MBCV_CONTROL */
+ /*#define TNP_4EC_MBR_TUNE */
+ /*#define TNP_4EC_FORBIDDEN_TUNE */
+ /*#define TNP_AF_FINESEARCH_DRIVEBACK */
+ /*#define TNP_FLASH_ALG */
+ /*#define TNP_GAS_ALPHA_OTP */
+ /*#define TNP_AWB_MODUL_COMP */
+ /*#define TNP_AWB_INIT_QUEUE */
+
+ /*TNP_Regs_usCintrTh 2 70004780 */
+ /*TNP_Regs_usFixedCintc 2 70004782 */
+ /*TNP_Regs_FlsWeightRIn_0_ 2 70004784 */
+ /*TNP_Regs_FlsWeightRIn_1_ 2 70004786 */
+ /*TNP_Regs_FlsWeightRIn_2_ 2 70004788 */
+ /*TNP_Regs_FlsWeightRIn_3_ 2 7000478A */
+ /*TNP_Regs_FlsWeightRIn_4_ 2 7000478C */
+ /*TNP_Regs_FlsWeightRIn_5_ 2 7000478E */
+ /*TNP_Regs_FlsWeightROut_0_ 2 70004790 */
+ /*TNP_Regs_FlsWeightROut_1_ 2 70004792 */
+ /*TNP_Regs_FlsWeightROut_2_ 2 70004794 */
+ /*TNP_Regs_FlsWeightROut_3_ 2 70004796 */
+ /*TNP_Regs_FlsWeightROut_4_ 2 70004798 */
+ /*TNP_Regs_FlsWeightROut_5_ 2 7000479A */
+
+ /*TNP_Regs_FlBRIn_0_ 2 7000479C */
+ /*TNP_Regs_FlBRIn_1_ 2 7000479E */
+ /*TNP_Regs_FlBRIn_2_ 2 700047A0 */
+ /*TNP_Regs_FlBRInOut_0_ 2 700047A2 */
+ /*TNP_Regs_FlBRInOut_1_ 2 700047A4 */
+ /*TNP_Regs_FlBRInOut_2_ 2 700047A6 */
+
+ 0x0028D000,
+ 0x002A1000,
+ 0x0F120001,
+
+ /* AF setting */
+ 0x00287000,
+ 0x002A01FC,
+ 0x0F120001, /* #REG_TC_IPRM_LedGpio */
+ 0x002A1720,
+ 0x0F120100,
+ 0x002A01FE,
+ 0x0F120003,
+ 0x0F120000,
+ 0x002A0204,
+ 0x0F120061,
+ 0x002A020C,
+ 0x0F122F0C,
+ 0x0F120190,
+ 0x002A0294,
+ 0x0F120100,
+ 0x0F1200E3,
+ 0x0F120200,
+ 0x0F120238,
+ 0x0F1201C6,
+ 0x0F120166,
+ 0x0F120074,
+ 0x0F120132,
+ 0x0F120001,
+
+ 0x002A070E,
+ 0x0F1200C0,
+ 0x002A071E,
+ 0x0F120001,
+ 0x002A163C,
+ 0x0F120000,
+ 0x002A1648,
+ 0x0F129002,
+ 0x002A1652,
+ 0x0F120002,
+ 0x0F120000,
+ 0x002A15E0,
+ 0x0F120902,
+
+ 0x002A164C,
+ 0x0F120003,
+ 0x002A163E,
+ 0x0F1200D5,
+ 0x0F120098,
+ 0x002A15D4,
+ 0x0F120000,
+ 0x0F12D000,
+ 0x002A169A,
+ 0x0F12FF95,
+ 0x002A166A,
+ 0x0F120280,
+ 0x002A1676,
+ 0x0F1203A0,
+ 0x0F120320,
+ 0x002A16BC,
+ 0x0F120030,
+ 0x002A16E0,
+ 0x0F120060,
+ 0x002A16D4,
+ 0x0F120010,
+ 0x002A1656,
+ 0x0F120000,
+ 0x002A15E6,
+ 0x0F12003C,
+
+ 0x0F120018, /*#af_pos_usTableLastInd*/
+ 0x0F12002A,
+ 0x0F120030,
+ 0x0F120036,
+ 0x0F12003C,
+ 0x0F120042,
+ 0x0F120048,
+ 0x0F12004E,
+ 0x0F120054,
+ 0x0F12005A,
+ 0x0F120060,
+ 0x0F120066,
+ 0x0F12006C,
+ 0x0F120072,
+ 0x0F120078,
+ 0x0F12007E,
+ 0x0F120084,
+ 0x0F12008A,
+ 0x0F120090,
+ 0x0F120096,
+ 0x0F12009C,
+ 0x0F1200A2,
+ 0x0F1200A8,
+ 0x0F1200AE,
+ 0x0F1200B4,
+ 0x0F1200BA, /*#af_pos_usTable_24_*/
+
+ 0x002A1722,
+ 0x0F128000,
+ 0x0F120006,
+ 0x0F123FF0,
+ 0x0F1203E8,
+ 0x0F120000,
+ 0x0F120020,
+ 0x0F120010,
+ 0x0F120008,
+ 0x0F120040,
+ 0x0F120080,
+ 0x0F1200C0,
+ 0x0F1200E0,
+
+ 0x002A028C,
+ 0x0F120003, /*#REG_TC_AF_AfCmd*/
+
+ /* GAS TBL setting */
+ 0x002A08B4,
+ 0x0F120001, /*#wbt_bUseOutdoorASH*/
+
+ /*TVAR_ash_AwbAshCord, Refer Mon_AWB_RotGain*/
+ 0x002A08BC,
+ 0x0F1200C0, /*#TVAR_ash_AwbAshCord_0_ 2300K*/
+ 0x0F1200DF, /*#TVAR_ash_AwbAshCord_1_ 2750K*/
+ 0x0F120100, /*#TVAR_ash_AwbAshCord_2_ 3300K*/
+ 0x0F120125, /*#TVAR_ash_AwbAshCord_3_ 4150K*/
+ 0x0F12015F, /*#TVAR_ash_AwbAshCord_4_ 5250K*/
+ 0x0F12017C, /*#TVAR_ash_AwbAshCord_5_ 6400K*/
+ 0x0F120194, /*#TVAR_ash_AwbAshCord_6_ 7500K*/
+
+
+ 0x002A08F6,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+
+ 0x0F124500,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+
+ 0x002A08F4,
+ 0x0F120001, /*#ash_bUseGasAlpha*/
+
+ /* AE START */
+
+ /*AE WEIGHT */
+ 0x002A1492,
+ 0x0F120000,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120000,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120201,
+ 0x0F120303,
+ 0x0F120303,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120403,
+ 0x0F120304,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120403,
+ 0x0F120304,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120403,
+ 0x0F120304,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120303,
+ 0x0F120303,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120202,
+ 0x0F120202,
+ 0x0F120102,
+
+ 0x002A1484,
+ 0x0F12003C, /*#TVAR_ae_BrAve*/
+ 0x002A148A,
+ 0x0F12000F, /*#ae_StatMode*/
+ 0x002A058C,
+ 0x0F123520,
+ 0x0F120000, /*#lt_uMaxExp1*/
+ 0x0F12C350,
+ 0x0F120000, /*#lt_uMaxExp2*/
+ 0x0F123520,
+ 0x0F120000, /*#lt_uCapMaxExp1*/
+ 0x0F12C350,
+ 0x0F120000, /*#lt_uCapMaxExp2*/
+ 0x0F120470, /*#lt_uMaxAnGain1*/
+ 0x0F120C00, /*#lt_uMaxAnGain2*/
+ 0x0F120100, /*#lt_uMaxDigGain*/
+ 0x0F121000, /*#lt_uMaxTotGain*/
+
+ 0x002A0544,
+ 0x0F120111, /*#lt_uLimitHigh*/
+ 0x0F1200EF, /*#lt_uLimitLow*/
+
+ 0x002A0F2A,
+ 0x0F120001, /*#AFC_Default60Hz*/
+ 0x002A0F30,
+ 0x0F120002, /*#AFC_D_ConvAccelerPower*/
+
+ 0x002A0588, /*#lt_uInitPostToleranceCnt*/
+ 0x0F120000, /*AE Speed-up*/
+
+ 0x002A0600, /*#lt_uleiInit*/
+ 0x0F12D000,
+
+ 0x002A0608,
+ 0x0F120001, /*#lt_ExpGain_uSubsamplingmode*/
+ 0x0F120001, /*#lt_ExpGain_uNonSubsampling*/
+ 0x0F120C00, /*#lt_ExpGain_ExpCurveGainMaxStr*/
+ 0x0F120100, /*#lt_ExpGain_ExpCurveGainMaxStr_0__uMaxDigGain*/
+ 0x0F120001,
+ 0x0F120000, /*#lt_ExpGain_ExpCurveGainMaxStr_0__ulExpIn_0_*/
+ 0x0F120A3C,
+ 0x0F120000,
+ 0x0F120D04,
+ 0x0F120000,
+ 0x0F124008,
+ 0x0F120000,
+ 0x0F127000,
+ 0x0F120000,
+ 0x0F129C00,
+ 0x0F120000,
+ 0x0F12AD00,
+ 0x0F120001,
+ 0x0F12F1D4,
+ 0x0F120002,
+ 0x0F12DC00,
+ 0x0F120005,
+ 0x0F12DC00,
+ 0x0F120005,
+ 0x0F120001,
+ 0x0F120000, /*#lt_ExpGain_ExpCurveGainMaxStr_0__ulExpOut_0_*/
+ 0x0F120A3C,
+ 0x0F120000,
+ 0x0F120D05,
+ 0x0F120000,
+ 0x0F123408,
+ 0x0F120000,
+ 0x0F123408,
+ 0x0F120000,
+ 0x0F126810,
+ 0x0F120000,
+ 0x0F128214,
+ 0x0F120000,
+ 0x0F12C350,
+ 0x0F120000,
+ 0x0F12C350,
+ 0x0F120000,
+ 0x0F12C350,
+ 0x0F120000,
+ 0x0F120650, /*#lt_ExpGain_ExpCurveGainMaxStr_1_*/
+ 0x0F120100, /*#lt_ExpGain_ExpCurveGainMaxStr_1__uMaxDigGain*/
+
+ 0x002A06B8,
+ 0x0F12452C,
+ 0x0F12000C, /*#lt_uMaxLei*/
+
+ 0x002A05D0,
+ 0x0F120000, /*#lt_mbr_Peak_behind*/
+
+ /* AWB init Start point */
+ 0x002A145E,
+ 0x0F120470, /* 0400 */
+ 0x0F120400, /* 0428 */
+ 0x0F1209F0, /* 9B3 */
+
+ /* AWB Init */
+ /*White Locus */
+ 0x002A11F0,
+ 0x0F12012C, /*#awbb_IntcR*/
+ 0x0F120121, /*#awbb_IntcB*/
+
+ /* IndoorZone*/
+ 0x002A101C,
+ 0x0F12039A,
+ 0x0F1203E8,
+ 0x0F12033C,
+ 0x0F1203AE,
+ 0x0F1202DE,
+ 0x0F120376,
+ 0x0F12029C,
+ 0x0F12033C,
+ 0x0F12027E,
+ 0x0F120312,
+ 0x0F12025E,
+ 0x0F1202F6,
+ 0x0F12023E,
+ 0x0F1202DA,
+ 0x0F12022A,
+ 0x0F1202BC,
+ 0x0F120214,
+ 0x0F1202A2,
+ 0x0F1201FE,
+ 0x0F120292,
+ 0x0F1201F0,
+ 0x0F120284,
+ 0x0F1201E0,
+ 0x0F120276,
+ 0x0F1201D2,
+ 0x0F120266,
+ 0x0F1201C4,
+ 0x0F120258,
+ 0x0F1201D8,
+ 0x0F120216,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x0F120005, /*#awbb_IndoorGrZones_m_GridStep*/
+ 0x002A1070,
+ 0x0F12000F, /*#awbb_IndoorGrZones_ZInfo_m_GridSz*/
+ 0x002A1074,
+ 0x0F12013C, /*#awbb_IndoorGrZones_m_Boffs*/
+
+ /*Outdoor Zone*/
+ 0x002A1078,
+ 0x0F120254,
+ 0x0F120296,
+ 0x0F120246,
+ 0x0F1202B4,
+ 0x0F120238,
+ 0x0F1202B8,
+ 0x0F12022A,
+ 0x0F1202B0,
+ 0x0F12021C,
+ 0x0F1202A6,
+ 0x0F12021A,
+ 0x0F12029C,
+ 0x0F12021A,
+ 0x0F120292,
+ 0x0F120220,
+ 0x0F120288,
+ 0x0F120226,
+ 0x0F12027E,
+ 0x0F120244,
+ 0x0F120274,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x0F120004, /*#awbb_OutdoorGrZones_m_GridStep*/
+ 0x002A10AC,
+ 0x0F12000A, /*#awbb_OutdoorGrZones_ZInfo_m_GridSz*/
+ 0x002A10B0,
+ 0x0F1201EE, /*#awbb_OutdoorGrZones_m_Boffs*/
+
+ /*LowBR Zone*/
+ 0x002A10B4,
+ 0x0F120350,
+ 0x0F120422,
+ 0x0F1202C4,
+ 0x0F120452,
+ 0x0F120278,
+ 0x0F12041C,
+ 0x0F120230,
+ 0x0F1203EE,
+ 0x0F1201F0,
+ 0x0F120392,
+ 0x0F1201C0,
+ 0x0F120340,
+ 0x0F120194,
+ 0x0F120302,
+ 0x0F12016E,
+ 0x0F1202C2,
+ 0x0F120148,
+ 0x0F120286,
+ 0x0F12018A,
+ 0x0F120242,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x0F120006, /*#awbb_LowBrGrZones_m_GridStep*/
+ 0x002A10E8,
+ 0x0F12000A, /*#awbb_LowBrGrZones_ZInfo_m_GridSz*/
+ 0x002A10EC,
+ 0x0F120106, /*#awbb_LowBrGrZones_m_Boffs*/
+
+ /*LowTemp Zone*/
+ 0x002A10F0,
+ 0x0F120380,
+ 0x0F120000, /*#awbb_CrclLowT_R_c*/
+ 0x0F120168,
+ 0x0F120000, /*#awbb_CrclLowT_B_c*/
+ 0x0F122D90,
+ 0x0F120000, /*#awbb_CrclLowT_Rad_c*/
+
+ /*AWB Convergence Speed*/
+ 0x002A1464,
+ 0x0F120008,
+ 0x0F120190,
+ 0x0F1200A0,
+
+ 0x002A1228,
+ 0x0F1200C0,
+ 0x002A122C,
+ 0x0F120010,
+ 0x002A122A,
+ 0x0F120010,
+
+ 0x002A120A,
+ 0x0F1205D5, /*#awbb_MvEq_RBthresh*/
+ 0x002A120E,
+ 0x0F120000,
+
+ 0x0F120771,
+ 0x0F1203A4,
+ 0x0F120036,
+ 0x0F12002A,
+
+ 0x002A1278,
+ 0x0F12FEF7,
+ 0x0F120021,
+ 0x0F120E74,
+ 0x0F120E74,
+ 0x0F12018F,
+ 0x0F120096,
+ 0x0F12000E,
+ 0x002A1224,
+ 0x0F120032,
+ 0x0F12001E,
+ 0x0F1200C0,
+ 0x0F120010,
+ 0x0F120002, /*awbb_YThreshLow_Low */
+ 0x002A2BA4,
+ 0x0F120006, /*#Mon_AWB_ByPassMode*/
+
+ 0x002A146C,
+ 0x0F120002, /*#awbb_GridEnable*/
+
+ /*Grid*/
+ 0x002A1434,
+ 0x0F120300, /* awbb_GridConst_1 */
+ 0x0F12036E, /* awbb_GridConst_1_1_ */
+ 0x0F1203C2, /* awbb_GridConst_1_2_ */
+ 0x0F121074, /* awbb_GridConst_2 */
+ 0x0F1210C2, /* awbb_GridConst_2_1_ */
+ 0x0F121104, /* awbb_GridConst_2_2_ */
+ 0x0F121142, /* awbb_GridConst_2_3_ */
+ 0x0F1211BB, /* awbb_GridConst_2_4_ */
+ 0x0F12123B, /* awbb_GridConst_2_5_ */
+ 0x0F1200AB, /* awbb_GridCoeff_R_1 */
+ 0x0F1200BF, /* awbb_GridCoeff_B_1 */
+ 0x0F1200D2, /* awbb_GridCoeff_R_2 */
+ 0x0F120093, /* awbb_GridCoeff_B_2 */
+
+ /*Indoor Grid Offset*/
+ 0x002A13A4,
+ 0x0F120000,
+ 0x0F12FFD0,
+ 0x0F12FFD0,
+ 0x0F120000,
+ 0x0F120008,
+ 0x0F120018,
+ 0x0F120000,
+ 0x0F12FFD0,
+ 0x0F12FFD0,
+ 0x0F120000,
+ 0x0F120008,
+ 0x0F120018,
+ 0x0F120000,
+ 0x0F12FFD0,
+ 0x0F12FFD0,
+ 0x0F120000,
+ 0x0F120008,
+ 0x0F120018,
+ 0x0F12FFE0,
+ 0x0F12FFE0,
+ 0x0F12FFC0,
+ 0x0F12FFC0,
+ 0x0F12FFB0,
+ 0x0F12FFB0,
+ 0x0F12FFE0,
+ 0x0F12FFE0,
+ 0x0F12FFC0,
+ 0x0F12FFC0,
+ 0x0F12FFB0,
+ 0x0F12FFB0,
+ 0x0F12FFE0,
+ 0x0F12FFE0,
+ 0x0F12FFC0,
+ 0x0F12FFC0,
+ 0x0F12FFB0,
+ 0x0F12FFB0,
+
+ /*Outdoor Grid Offset*/
+ 0x0F12FFB0,
+ 0x0F12FFD0,
+ 0x0F12FFD0,
+ 0x0F12FFD0,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F12FFB0,
+ 0x0F12FFD0,
+ 0x0F12FFD0,
+ 0x0F12FFD0,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F12FFB0,
+ 0x0F12FFD0,
+ 0x0F12FFD0,
+ 0x0F12FFD0,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F12FFC8,
+ 0x0F12FFB8,
+ 0x0F12FFB8,
+ 0x0F12FFB8,
+ 0x0F12FFB8,
+ 0x0F120000,
+ 0x0F12FFC8,
+ 0x0F12FFB8,
+ 0x0F12FFB8,
+ 0x0F12FFB8,
+ 0x0F12FFB8,
+ 0x0F120000,
+ 0x0F12FFC8,
+ 0x0F12FFB8,
+ 0x0F12FFB8,
+ 0x0F12FFB8,
+ 0x0F12FFB8,
+
+ 0x002A1208,
+ 0x0F120020,
+
+ 0x002A144E,
+ 0x0F120000, /*#awbb_RGainOff*/
+ 0x0F120000, /*#awbb_BGainOff*/
+ 0x0F120000, /*#awbb_GGainOff*/
+
+ /*RGB Indoor Gamma*/
+ 0x002A0734,
+ 0x0F120001,
+ 0x0F120007,
+ 0x0F120011,
+ 0x0F12002D,
+ 0x0F12006B,
+ 0x0F1200DC,
+ 0x0F12013B,
+ 0x0F120166,
+ 0x0F12018D,
+ 0x0F1201CD,
+ 0x0F120204,
+ 0x0F120235,
+ 0x0F120260,
+ 0x0F1202AA,
+ 0x0F1202EC,
+ 0x0F12034E,
+ 0x0F120396,
+ 0x0F1203C6,
+ 0x0F1203E9,
+ 0x0F1203F9,
+ 0x0F120001,
+ 0x0F120007,
+ 0x0F120011,
+ 0x0F12002D,
+ 0x0F12006B,
+ 0x0F1200DC,
+ 0x0F12013B,
+ 0x0F120166,
+ 0x0F12018D,
+ 0x0F1201CD,
+ 0x0F120204,
+ 0x0F120235,
+ 0x0F120260,
+ 0x0F1202AA,
+ 0x0F1202EC,
+ 0x0F12034E,
+ 0x0F120396,
+ 0x0F1203C6,
+ 0x0F1203E9,
+ 0x0F1203F9,
+ 0x0F120001,
+ 0x0F120007,
+ 0x0F120011,
+ 0x0F12002D,
+ 0x0F12006B,
+ 0x0F1200DC,
+ 0x0F12013B,
+ 0x0F120166,
+ 0x0F12018D,
+ 0x0F1201CD,
+ 0x0F120204,
+ 0x0F120235,
+ 0x0F120260,
+ 0x0F1202AA,
+ 0x0F1202EC,
+ 0x0F12034E,
+ 0x0F120396,
+ 0x0F1203C6,
+ 0x0F1203E9,
+ 0x0F1203F9,
+
+ /*RGB Outdoor Gamma*/
+ 0x0F120001,
+ 0x0F120007,
+ 0x0F120011,
+ 0x0F12002D,
+ 0x0F12006B,
+ 0x0F1200DC,
+ 0x0F12013B,
+ 0x0F120166,
+ 0x0F12018D,
+ 0x0F1201CD,
+ 0x0F120204,
+ 0x0F120235,
+ 0x0F120260,
+ 0x0F1202AA,
+ 0x0F1202EC,
+ 0x0F12034E,
+ 0x0F120396,
+ 0x0F1203C6,
+ 0x0F1203E9,
+ 0x0F1203F9,
+ 0x0F120001,
+ 0x0F120007,
+ 0x0F120011,
+ 0x0F12002D,
+ 0x0F12006B,
+ 0x0F1200DC,
+ 0x0F12013B,
+ 0x0F120166,
+ 0x0F12018D,
+ 0x0F1201CD,
+ 0x0F120204,
+ 0x0F120235,
+ 0x0F120260,
+ 0x0F1202AA,
+ 0x0F1202EC,
+ 0x0F12034E,
+ 0x0F120396,
+ 0x0F1203C6,
+ 0x0F1203E9,
+ 0x0F1203F9,
+ 0x0F120001,
+ 0x0F120007,
+ 0x0F120011,
+ 0x0F12002D,
+ 0x0F12006B,
+ 0x0F1200DC,
+ 0x0F12013B,
+ 0x0F120166,
+ 0x0F12018D,
+ 0x0F1201CD,
+ 0x0F120204,
+ 0x0F120235,
+ 0x0F120260,
+ 0x0F1202AA,
+ 0x0F1202EC,
+ 0x0F12034E,
+ 0x0F120396,
+ 0x0F1203C6,
+ 0x0F1203E9,
+ 0x0F1203F9,
+
+ /*CCM*/
+ 0x002A08A6,
+ 0x0F1200C0,
+ 0x0F1200D0,
+ 0x0F1200E0,
+ 0x0F120110,
+ 0x0F12017C,
+ 0x0F120194,
+
+ 0x0F120001,
+
+ 0x002A0898,
+ 0x0F124800,
+ 0x0F127000,
+ 0x002A08A0,
+ 0x0F1248D8,
+ 0x0F127000,
+
+ 0x002A4800,
+ 0x0F12010F, /*hor*/
+ 0x0F12FF90,
+ 0x0F12FF7D,
+ 0x0F12FEF1,
+ 0x0F120137,
+ 0x0F12FF68,
+ 0x0F12FFEE,
+ 0x0F12FF8A,
+ 0x0F12013A,
+ 0x0F12006E,
+ 0x0F120089,
+ 0x0F12FEFE,
+ 0x0F120175,
+ 0x0F12FF4A,
+ 0x0F1200D6,
+ 0x0F12FEFE,
+ 0x0F120113,
+ 0x0F1200E6,
+ 0x0F12010F, /*incaA*/
+ 0x0F12FF90,
+ 0x0F12FF7D,
+ 0x0F12FEF1,
+ 0x0F120137,
+ 0x0F12FF68,
+ 0x0F12FFEE,
+ 0x0F12FF8A,
+ 0x0F12013A,
+ 0x0F12006E,
+ 0x0F120089,
+ 0x0F12FEFE,
+ 0x0F120175,
+ 0x0F12FF4A,
+ 0x0F1200D6,
+ 0x0F12FEFE,
+ 0x0F120113,
+ 0x0F1200E6,
+ 0x0F12010F, /*WW*/
+ 0x0F12FF90,
+ 0x0F12FF7D,
+ 0x0F12FEF1,
+ 0x0F120137,
+ 0x0F12FF68,
+ 0x0F12FFEE,
+ 0x0F12FF8A,
+ 0x0F12013A,
+ 0x0F12006E,
+ 0x0F120089,
+ 0x0F12FEFE,
+ 0x0F120175,
+ 0x0F12FF4A,
+ 0x0F1200D6,
+ 0x0F12FEFE,
+ 0x0F120113,
+ 0x0F1200E6,
+ 0x0F12017B, /*CW*/
+ 0x0F12FFB5,
+ 0x0F12FFF9,
+ 0x0F12FF5E,
+ 0x0F12019D,
+ 0x0F12FFA2,
+ 0x0F12FFD9,
+ 0x0F12FFCB,
+ 0x0F12012C,
+ 0x0F1200C9,
+ 0x0F1200B0,
+ 0x0F12FF2F,
+ 0x0F1200CA,
+ 0x0F12FF91,
+ 0x0F12015E,
+ 0x0F12FF47,
+ 0x0F120129,
+ 0x0F120125,
+ 0x0F1201AF, /*D50*/
+ 0x0F12FFBA,
+ 0x0F12FFF1,
+ 0x0F12FF27,
+ 0x0F1201DE,
+ 0x0F12FF77,
+ 0x0F12FFCB,
+ 0x0F12FFC5,
+ 0x0F120136,
+ 0x0F120110,
+ 0x0F1200EF,
+ 0x0F12FFA0,
+ 0x0F1200A3,
+ 0x0F12FF7B,
+ 0x0F12018C,
+ 0x0F12FF1D,
+ 0x0F120138,
+ 0x0F120138,
+ 0x0F1201AF, /*D65*/
+ 0x0F12FFBA,
+ 0x0F12FFF1,
+ 0x0F12FF27,
+ 0x0F1201DE,
+ 0x0F12FF77,
+ 0x0F12FFCB,
+ 0x0F12FFC5,
+ 0x0F120136,
+ 0x0F120110,
+ 0x0F1200EF,
+ 0x0F12FFA0,
+ 0x0F1200A3,
+ 0x0F12FF7B,
+ 0x0F12018C,
+ 0x0F12FF1D,
+ 0x0F120138,
+ 0x0F120138,
+
+ 0x0F12019F, /*#TVAR_wbt_pOutdoorCcm[0]*/
+ 0x0F12FFBF,
+ 0x0F12FFFD,
+ 0x0F12FF10,
+ 0x0F1201D4,
+ 0x0F12FFA4,
+ 0x0F12FFE8,
+ 0x0F12FFE0,
+ 0x0F1201C2,
+ 0x0F120087,
+ 0x0F1200A5,
+ 0x0F12FF17,
+ 0x0F1201DD,
+ 0x0F12FF0E,
+ 0x0F12010B,
+ 0x0F12FF24,
+ 0x0F1200F0,
+ 0x0F1201DB,
+
+
+ /*System Setting*/
+ 0x002A01F8,
+ 0x0F125DC0, /*#REG_TC_IPRM_InClockLSBs, MCLK: 24Mhz*/
+ 0x002A0212,
+ 0x0F120002, /*#REG_TC_IPRM_UseNPviClocks*/
+ 0x0F120000, /*#REG_TC_IPRM_UseNMipiClocks*/
+ 0x0F120000, /*#REG_TC_IPRM_NumberOfMipiLanes*/
+ 0x002A021A,
+ 0x0F123A98, /*#REG_TC_IPRM_OpClk4KHz_0, SCLK: 60Mhz*/
+ 0x0F124F1A, /*#REG_TC_IPRM_MinOutRate4KHz_0 PCLK Min : 81Mhz*/
+ 0x0F124F1A, /*#REG_TC_IPRM_MaxOutRate4KHz_0 PCLK Max : 81Mhz*/
+ 0x0F124F1A, /*#REG_TC_IPRM_OpClk4KHz_1 SCLK : 81Mhz*/
+ 0x0F124F1A, /*#REG_TC_IPRM_MinOutRate4KHz_1 PCLK Min : 81Mhz*/
+ 0x0F124F1A, /*#REG_TC_IPRM_MaxOutRate4KHz_1 PCLK Max : 81Mhz*/
+ 0x002A022C,
+ 0x0F120001, /*#REG_TC_IPRM_InitParamsUpdated*/
+
+ /*ETC.. Setting*/
+ 0x002A0478,
+ 0x0F12005F, /*#REG_TC_BRC_usPrevQuality*/
+ 0x0F12005F, /*#REG_TC_BRC_usCaptureQuality*/
+
+ 0x0F120001, /*#REG_TC_THUMB_Thumb_bActive*/
+ 0x0F120280, /*#REG_TC_THUMB_Thumb_uWidth*/
+ 0x0F1201E0, /*#REG_TC_THUMB_Thumb_uHeight*/
+ 0x0F120005, /*#REG_TC_THUMB_Thumb_Format*/
+
+ 0x002A17DC,
+ 0x0F120054, /*#jpeg_ManualMBCV*/
+ 0x002A1AE4,
+ 0x0F12001C, /*#senHal_bExtraAddLine*/
+ 0x002A0284,
+ 0x0F120001, /*#REG_TC_GP_bBypassScalerJpg*/
+ 0x002A028A,
+ 0x0F120001, /*#REG_TC_GP_bUse1FrameCaptureMode*/
+ /*0 : Continuous mode,1 : Single frame mode*/
+
+ /*Configuration Setting*/
+ 0x002A02A6,
+ 0x0F120280, /*#REG_0TC_PCFG_usWidth : 640*/
+ 0x0F1201E0, /*#REG_0TC_PCFG_usHeight : 480*/
+ 0x0F120005, /*#REG_0TC_PCFG_Format 5 : YUV 7 : Raw 9 : JPG*/
+ 0x0F124F1A, /*#REG_0TC_PCFG_usMaxOut4KHzRate*/
+ 0x0F124F1A, /*#REG_0TC_PCFG_usMinOut4KHzRate*/
+ 0x0F120100, /*#REG_0TC_PCFG_OutClkPerPix88*/
+ 0x0F120300, /*#REG_0TC_PCFG_uBpp88*/
+ 0x0F120052, /*#REG_0TC_PCFG_PVIMask*/
+ 0x0F120000, /*#REG_0TC_PCFG_OIFMask*/
+ 0x0F1201E0, /*#REG_0TC_PCFG_usJpegPacketSize*/
+ 0x0F120000, /*#REG_0TC_PCFG_usJpegTotalPackets*/
+ 0x0F120000, /*#REG_0TC_PCFG_uClockInd*/
+ 0x0F120000, /*#REG_0TC_PCFG_usFrTimeType*/
+ 0x0F120001, /*#REG_0TC_PCFG_FrRateQualityType*/
+ 0x0F12029A, /*#REG_0TC_PCFG_usMaxFrTimeMsecMult10*/
+ 0x0F12014A, /*#REG_0TC_PCFG_usMinFrTimeMsecMult10*/
+ 0x002A02D0,
+ 0x0F120000, /*#REG_0TC_PCFG_uPrevMirror*/
+ 0x0F120000, /*#REG_0TC_PCFG_uCaptureMirror*/
+ 0x0F120000, /*#REG_0TC_PCFG_uRotation*/
+
+ 0x002A0396,
+ 0x0F120000, /*#REG_0TC_CCFG_uCaptureMode*/
+ 0x0F120A00, /*#REG_0TC_CCFG_usWidth*/
+ 0x0F120780, /*#REG_0TC_CCFG_usHeight*/
+ 0x0F120009, /*#REG_0TC_CCFG_Format*/
+ 0x0F124F1A, /*#REG_0TC_CCFG_usMaxOut4KHzRate*/
+ 0x0F124F1A, /*#REG_0TC_CCFG_usMinOut4KHzRate*/
+ 0x0F120100, /*#REG_0TC_CCFG_OutClkPerPix88*/
+ 0x0F120300, /*#REG_0TC_CCFG_uBpp88*/
+ 0x0F120042, /*#REG_0TC_CCFG_PVIMask*/
+ 0x0F120000, /*#REG_0TC_CCFG_OIFMask*/
+ 0x0F1201E0, /*#REG_0TC_CCFG_usJpegPacketSize*/
+ 0x0F120000, /*#REG_0TC_CCFG_usJpegTotalPackets*/
+ 0x0F120001, /*#REG_0TC_CCFG_uClockInd*/
+ 0x0F120000, /*#REG_0TC_CCFG_usFrTimeType*/
+ 0x0F120002, /*#REG_0TC_CCFG_FrRateQualityType*/
+ 0x0F120535, /*#REG_0TC_CCFG_usMaxFrTimeMsecMult10*/
+ 0x0F12029A, /*#REG_0TC_CCFG_usMinFrTimeMsecMult10*/
+
+ 0x002A0250,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120010,
+ 0x0F12000C,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120010,
+ 0x0F12000C,
+ 0x002A0494,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x002A0262,
+ 0x0F120001,
+ 0x0F120001,
+ 0x0F120000, /*#REG_TC_GP_ActivePrevConfig*/
+ 0x002A026A,
+ 0x0F120001, /*#REG_TC_GP_PrevOpenAfterChange*/
+ 0x002A024E,
+ 0x0F120001, /*#REG_TC_GP_NewConfigSync*/
+ 0x002A0268,
+ 0x0F120001, /*#REG_TC_GP_PrevConfigChanged*/
+ 0x002A0270,
+ 0x0F120001, /*#REG_TC_GP_CapConfigChanged*/
+ 0x002A023E,
+ 0x0F120001, /*#REG_TC_GP_EnablePreview*/
+ 0x0F120001, /*#REG_TC_GP_EnablePreviewChanged*/
+
+
+ /*AFIT*/
+ 0x002A0944,
+ 0x0F120050, /*#afit_uNoiseIndInDoor_0_*/
+ 0x0F120103, /*#afit_uNoiseIndInDoor_1_*/
+ 0x0F120196, /*#afit_uNoiseIndInDoor_2_*/
+ 0x0F120245, /*#afit_uNoiseIndInDoor_3_*/
+ 0x0F120300, /*#afit_uNoiseIndInDoor_4_*/
+
+ 0x002A097A,
+ 0x0F120001, /*#afit_bUseSenBpr*/
+ 0x0F1201CC, /*#afit_usBprThr_0_*/
+ 0x0F1201CC, /*#afit_usBprThr_1_*/
+ 0x0F1201CC, /*#afit_usBprThr_2_*/
+ 0x0F1201CC, /*#afit_usBprThr_3_*/
+ 0x0F1201CC, /*#afit_usBprThr_4_*/
+ 0x0F120180, /*#afit_NIContrastAFITValue*/
+ 0x0F120196, /*#afit_NIContrastTh*/
+
+ 0x002A0976,
+ 0x0F120070,
+ 0x0F120005,
+
+ 0x002A0938,
+ 0x0F120000,
+ 0x0F120014, /*#SARR_uNormBrInDoor_0_*/
+ 0x0F1200D2, /*#SARR_uNormBrInDoor_1_*/
+ 0x0F120384, /*#SARR_uNormBrInDoor_2_*/
+ 0x0F1207D0, /*#SARR_uNormBrInDoor_3_*/
+ 0x0F121388, /*#SARR_uNormBrInDoor_4_*/
+
+ 0x002A098C,
+ 0x0F120000, /*AFIT 0*/
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1200C0,
+ 0x0F120064,
+ 0x0F120384,
+ 0x0F12005F,
+ 0x0F1201F4,
+ 0x0F120070,
+ 0x0F120040,
+ 0x0F1200A0,
+ 0x0F120100,
+ 0x0F120010,
+ 0x0F120040,
+ 0x0F1200A0,
+ 0x0F121430,
+ 0x0F120201,
+ 0x0F120204,
+ 0x0F123604,
+ 0x0F12032A,
+ 0x0F120403,
+ 0x0F121B06,
+ 0x0F126015,
+ 0x0F1200C0,
+ 0x0F126080,
+ 0x0F124080,
+ 0x0F120640,
+ 0x0F120306,
+ 0x0F122003,
+ 0x0F12FF01,
+ 0x0F120000,
+ 0x0F120400,
+ 0x0F12365A,
+ 0x0F12102A,
+ 0x0F12000B,
+ 0x0F120600,
+ 0x0F125A0F,
+ 0x0F120505,
+ 0x0F121802,
+ 0x0F120000,
+ 0x0F122006,
+ 0x0F123028,
+ 0x0F120418,
+ 0x0F120101,
+ 0x0F120800,
+ 0x0F121804,
+ 0x0F124008,
+ 0x0F120540,
+ 0x0F128006,
+ 0x0F120020,
+ 0x0F120000,
+ 0x0F121800,
+ 0x0F120000,
+ 0x0F121E10,
+ 0x0F12000B,
+ 0x0F120607,
+ 0x0F120005,
+ 0x0F120607,
+ 0x0F120705,
+ 0x0F120206,
+ 0x0F120304,
+ 0x0F120309,
+ 0x0F120305,
+ 0x0F122006,
+ 0x0F121320,
+ 0x0F121014,
+ 0x0F121010,
+ 0x0F120C10,
+ 0x0F121A0C,
+ 0x0F124A18,
+ 0x0F120080,
+ 0x0F120050,
+ 0x0F120180,
+ 0x0F120A0A,
+ 0x0F120101,
+ 0x0F122A36,
+ 0x0F126024,
+ 0x0F122A36,
+ 0x0F12FFFF,
+ 0x0F120808,
+ 0x0F120A01,
+ 0x0F12010A,
+ 0x0F123601,
+ 0x0F12242A,
+ 0x0F123660,
+ 0x0F12FF2A,
+ 0x0F1208FF,
+ 0x0F120008,
+ 0x0F120001,
+ 0x0F120000, /*AFIT 1*/
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1200C0,
+ 0x0F120064,
+ 0x0F120384,
+ 0x0F120051,
+ 0x0F1201F4,
+ 0x0F120070,
+ 0x0F120040,
+ 0x0F1200A0,
+ 0x0F120100,
+ 0x0F120010,
+ 0x0F120060,
+ 0x0F120100,
+ 0x0F121430,
+ 0x0F120201,
+ 0x0F120204,
+ 0x0F122404,
+ 0x0F12031B,
+ 0x0F120103,
+ 0x0F121205,
+ 0x0F12400D,
+ 0x0F120080,
+ 0x0F121980,
+ 0x0F12272E,
+ 0x0F120629,
+ 0x0F120306,
+ 0x0F122003,
+ 0x0F12FF01,
+ 0x0F120404,
+ 0x0F120300,
+ 0x0F12245A,
+ 0x0F121018,
+ 0x0F12000B,
+ 0x0F120B00,
+ 0x0F125A0F,
+ 0x0F120505,
+ 0x0F121802,
+ 0x0F120000,
+ 0x0F122006,
+ 0x0F123828,
+ 0x0F120425,
+ 0x0F120101,
+ 0x0F120800,
+ 0x0F121004,
+ 0x0F124008,
+ 0x0F120540,
+ 0x0F128006,
+ 0x0F120020,
+ 0x0F120000,
+ 0x0F121800,
+ 0x0F120000,
+ 0x0F121E10,
+ 0x0F12000B,
+ 0x0F120607,
+ 0x0F120005,
+ 0x0F120607,
+ 0x0F120405,
+ 0x0F120205,
+ 0x0F120304,
+ 0x0F120409,
+ 0x0F120306,
+ 0x0F120407,
+ 0x0F122204,
+ 0x0F12021C,
+ 0x0F121102,
+ 0x0F120611,
+ 0x0F121A02,
+ 0x0F128018,
+ 0x0F120080,
+ 0x0F120074,
+ 0x0F120180,
+ 0x0F120A0A,
+ 0x0F120101,
+ 0x0F12141D,
+ 0x0F126024,
+ 0x0F121217,
+ 0x0F12FFFF,
+ 0x0F120808,
+ 0x0F120A01,
+ 0x0F12010A,
+ 0x0F122401,
+ 0x0F12241B,
+ 0x0F121E60,
+ 0x0F12FF18,
+ 0x0F1208FF,
+ 0x0F120008,
+ 0x0F120001,
+ 0x0F120000, /*AFIT 2*/
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1200C0,
+ 0x0F120064,
+ 0x0F120384,
+ 0x0F120043,
+ 0x0F1201F4,
+ 0x0F120070,
+ 0x0F120040,
+ 0x0F1200A0,
+ 0x0F120100,
+ 0x0F120010,
+ 0x0F120060,
+ 0x0F120100,
+ 0x0F121430,
+ 0x0F120201,
+ 0x0F120204,
+ 0x0F121B04,
+ 0x0F120312,
+ 0x0F120003,
+ 0x0F120C03,
+ 0x0F122806,
+ 0x0F120060,
+ 0x0F121580,
+ 0x0F122020,
+ 0x0F120620,
+ 0x0F120306,
+ 0x0F122003,
+ 0x0F12FF01,
+ 0x0F120404,
+ 0x0F120300,
+ 0x0F12145A,
+ 0x0F121010,
+ 0x0F12000B,
+ 0x0F120E00,
+ 0x0F125A0F,
+ 0x0F120504,
+ 0x0F121802,
+ 0x0F120000,
+ 0x0F122006,
+ 0x0F123828,
+ 0x0F120428,
+ 0x0F120101,
+ 0x0F128000,
+ 0x0F120A04,
+ 0x0F124008,
+ 0x0F120540,
+ 0x0F128006,
+ 0x0F120020,
+ 0x0F120000,
+ 0x0F121800,
+ 0x0F120000,
+ 0x0F121E10,
+ 0x0F12000B,
+ 0x0F120607,
+ 0x0F120005,
+ 0x0F120607,
+ 0x0F120405,
+ 0x0F120207,
+ 0x0F120304,
+ 0x0F120409,
+ 0x0F120306,
+ 0x0F120407,
+ 0x0F122404,
+ 0x0F120221,
+ 0x0F121202,
+ 0x0F120613,
+ 0x0F121A02,
+ 0x0F128018,
+ 0x0F120080,
+ 0x0F120080,
+ 0x0F120180,
+ 0x0F120A0A,
+ 0x0F120101,
+ 0x0F12121B,
+ 0x0F126024,
+ 0x0F120C0C,
+ 0x0F12FFFF,
+ 0x0F120808,
+ 0x0F120A01,
+ 0x0F12010A,
+ 0x0F121B01,
+ 0x0F122412,
+ 0x0F120C60,
+ 0x0F12FF0C,
+ 0x0F1208FF,
+ 0x0F120008,
+ 0x0F120001,
+ 0x0F120000, /*AFIT 3*/
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1200C0,
+ 0x0F120064,
+ 0x0F120384,
+ 0x0F120032,
+ 0x0F1201F4,
+ 0x0F120070,
+ 0x0F120040,
+ 0x0F1200A0,
+ 0x0F120100,
+ 0x0F120010,
+ 0x0F120060,
+ 0x0F120100,
+ 0x0F121430,
+ 0x0F120201,
+ 0x0F120204,
+ 0x0F121504,
+ 0x0F12030F,
+ 0x0F120003,
+ 0x0F120902,
+ 0x0F122004,
+ 0x0F120050,
+ 0x0F121140,
+ 0x0F12201C,
+ 0x0F120620,
+ 0x0F120306,
+ 0x0F122003,
+ 0x0F12FF01,
+ 0x0F120404,
+ 0x0F120300,
+ 0x0F12145A,
+ 0x0F121010,
+ 0x0F12000B,
+ 0x0F121000,
+ 0x0F125A0F,
+ 0x0F120503,
+ 0x0F121802,
+ 0x0F120000,
+ 0x0F122006,
+ 0x0F123C28,
+ 0x0F12042C,
+ 0x0F120101,
+ 0x0F12FF00,
+ 0x0F120904,
+ 0x0F124008,
+ 0x0F120540,
+ 0x0F128006,
+ 0x0F120020,
+ 0x0F120000,
+ 0x0F121800,
+ 0x0F120000,
+ 0x0F121E10,
+ 0x0F12000B,
+ 0x0F120607,
+ 0x0F120005,
+ 0x0F120607,
+ 0x0F120405,
+ 0x0F120206,
+ 0x0F120304,
+ 0x0F120409,
+ 0x0F120305,
+ 0x0F120406,
+ 0x0F122804,
+ 0x0F120228,
+ 0x0F121402,
+ 0x0F120618,
+ 0x0F121A02,
+ 0x0F128018,
+ 0x0F120080,
+ 0x0F120080,
+ 0x0F120180,
+ 0x0F120A0A,
+ 0x0F120101,
+ 0x0F120F15,
+ 0x0F126024,
+ 0x0F120A0A,
+ 0x0F12FFFF,
+ 0x0F120808,
+ 0x0F120A01,
+ 0x0F12010A,
+ 0x0F121501,
+ 0x0F12240F,
+ 0x0F120A60,
+ 0x0F12FF0A,
+ 0x0F1208FF,
+ 0x0F120008,
+ 0x0F120001,
+ 0x0F120000, /*AFIT 4*/
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1200C0,
+ 0x0F120064,
+ 0x0F120384,
+ 0x0F120032,
+ 0x0F1201F4,
+ 0x0F120070,
+ 0x0F120040,
+ 0x0F1200A0,
+ 0x0F120100,
+ 0x0F120010,
+ 0x0F120060,
+ 0x0F120100,
+ 0x0F121430,
+ 0x0F120201,
+ 0x0F120204,
+ 0x0F120F04,
+ 0x0F12030C,
+ 0x0F120003,
+ 0x0F120602,
+ 0x0F121803,
+ 0x0F120040,
+ 0x0F120E20,
+ 0x0F122018,
+ 0x0F120620,
+ 0x0F120306,
+ 0x0F122003,
+ 0x0F12FF01,
+ 0x0F120404,
+ 0x0F120200,
+ 0x0F12145A,
+ 0x0F121010,
+ 0x0F12000B,
+ 0x0F121200,
+ 0x0F125A0F,
+ 0x0F120502,
+ 0x0F121802,
+ 0x0F120000,
+ 0x0F122006,
+ 0x0F124028,
+ 0x0F120430,
+ 0x0F120101,
+ 0x0F12FF00,
+ 0x0F120804,
+ 0x0F124008,
+ 0x0F120540,
+ 0x0F128006,
+ 0x0F120020,
+ 0x0F120000,
+ 0x0F121800,
+ 0x0F120000,
+ 0x0F121E10,
+ 0x0F12000B,
+ 0x0F120607,
+ 0x0F120005,
+ 0x0F120607,
+ 0x0F120405,
+ 0x0F120205,
+ 0x0F120304,
+ 0x0F120409,
+ 0x0F120306,
+ 0x0F120407,
+ 0x0F122C04,
+ 0x0F12022C,
+ 0x0F121402,
+ 0x0F120618,
+ 0x0F121A02,
+ 0x0F128018,
+ 0x0F120080,
+ 0x0F120080,
+ 0x0F120180,
+ 0x0F120A0A,
+ 0x0F120101,
+ 0x0F120C0F,
+ 0x0F126024,
+ 0x0F120808,
+ 0x0F12FFFF,
+ 0x0F120808,
+ 0x0F120A01,
+ 0x0F12010A,
+ 0x0F120F01,
+ 0x0F12240C,
+ 0x0F120860,
+ 0x0F12FF08,
+ 0x0F1208FF,
+ 0x0F120008,
+ 0x0F120001,
+ 0x0F1223CE,
+ 0x0F12FDC8,
+ 0x0F12112E,
+ 0x0F1283A5,
+ 0x0F12FE67,
+ 0x0F120000,
+
+ 0x002A0588, /*lt_uInitPostToleranceCnt*/
+ 0x0F120002, /*AE Speed Normal*/
+
+};
+
+static const u32 s5k4ecgx_DTP_init[] = {
+ 0x0028D000,
+ 0x002AB054,
+ 0x0F120001,
+ 0x00287000,
+};
+
+static const u32 s5k4ecgx_DTP_stop[] = {
+ 0x0028D000,
+ 0x002AB054,
+ 0x0F120000,
+ 0x00287000,
+};
+
+static const u32 s5k4ecgx_FPS_Auto[] = {
+ 0x002A02B4,
+ 0x0F120052,
+ 0x002A02BE,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F12029A,
+ 0x0F12014A,
+ 0x002A02D0,
+ 0x0F120000,
+ 0x0F120000,
+ 0x002A0266,
+ 0x0F120000,
+ 0x002A026A,
+ 0x0F120001,
+ 0x002A024E,
+ 0x0F120001,
+ 0x002A0268,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_FPS_5[] = {
+
+};
+
+static const u32 s5k4ecgx_FPS_7[] = {
+ 0x002A02B4,
+ 0x0F120052,
+ 0x002A02BE,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F120535,
+ 0x0F120535,
+ 0x002A02D0,
+ 0x0F120000,
+ 0x0F120000,
+ 0x002A0266,
+ 0x0F120000,
+ 0x002A026A,
+ 0x0F120001,
+ 0x002A024E,
+ 0x0F120001,
+ 0x002A0268,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_FPS_10[] = {
+
+};
+
+static const u32 s5k4ecgx_FPS_15[] = {
+ 0x002A02B4,
+ 0x0F120052,
+ 0x002A02BE,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F12029A,
+ 0x0F12029A,
+ 0x002A02D0,
+ 0x0F120000,
+ 0x0F120000,
+ 0x002A0266,
+ 0x0F120000,
+ 0x002A026A,
+ 0x0F120001,
+ 0x002A024E,
+ 0x0F120001,
+ 0x002A0268,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_FPS_30[] = {
+ 0x002A02B4,
+ 0x0F120052,
+ 0x002A02BE,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F12014D,
+ 0x0F12014D,
+ 0x002A02D0,
+ 0x0F120000,
+ 0x0F120000,
+ 0x002A0266,
+ 0x0F120000,
+ 0x002A026A,
+ 0x0F120001,
+ 0x002A024E,
+ 0x0F120001,
+ 0x002A0268,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_FPS_60[] = {
+
+};
+
+static const u32 s5k4ecgx_FPS_120[] = {
+
+};
+
+static const u32 s5k4ecgx_Effect_Normal[] = {
+ 0x002A023C,
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_Effect_Solarization[] = {
+ 0x002A023C,
+ 0x0F120002,
+};
+
+static const u32 s5k4ecgx_Effect_Negative[] = {
+ 0x002A023C,
+ 0x0F120003,
+};
+
+static const u32 s5k4ecgx_Effect_Sepia[] = {
+ 0x002A023C,
+ 0x0F120004,
+};
+
+static const u32 s5k4ecgx_Effect_Black_White[] = {
+ 0x002A023C,
+ 0x0F120001,
+};
+
+
+static const u32 s5k4ecgx_WB_Auto[] = {
+ 0x002A04E6,
+ 0x0F12077F,
+};
+
+static const u32 s5k4ecgx_WB_Sunny[] = {
+ 0x002A04E6,
+ 0x0F120777,
+ 0x002A04BA,
+ 0x0F1205E0,
+ 0x0F120001,
+ 0x0F120400,
+ 0x0F120001,
+ 0x0F120530,
+ 0x0F120001,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_WB_Cloudy[] = {
+ 0x002A04E6,
+ 0x0F120777,
+ 0x002A04BA,
+ 0x0F120710,
+ 0x0F120001,
+ 0x0F120400,
+ 0x0F120001,
+ 0x0F120420,
+ 0x0F120001,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_WB_Tungsten[] = {
+ 0x002A04E6,
+ 0x0F120777,
+ 0x002A04BA,
+ 0x0F120390,
+ 0x0F120001,
+ 0x0F120400,
+ 0x0F120001,
+ 0x0F120920,
+ 0x0F120001,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_WB_Fluorescent[] = {
+ 0x002A04E6,
+ 0x0F120777,
+ 0x002A04BA,
+ 0x0F120505,
+ 0x0F120001,
+ 0x0F120400,
+ 0x0F120001,
+ 0x0F120875,
+ 0x0F120001,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_WDR_on[] = {
+ 0x002A1BEA,
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_WDR_off[] = {
+ 0x002A1BEA,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_ISO_Auto[] = {
+ 0x002A0938,
+ 0x0F120000,
+
+ 0x002A0F2A,
+ 0x0F120001,
+ 0x002A04E6,
+ 0x0F12077F,
+
+ 0x002A04D0,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120001,
+ 0x002A06C2,
+ 0x0F120200,
+};
+
+static const u32 s5k4ecgx_ISO_100[] = {
+ 0x002A04E6,
+ 0x0F12065F,
+ 0x002A04D6,
+ 0x0F120000,
+ 0x0F120001,
+
+ 0x002A04D0,
+ 0x0F120001,
+ 0x0F1201A0,
+ 0x0F120001,
+ 0x002A06C2,
+ 0x0F120100,
+
+ 0x002A0938,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_ISO_200[] = {
+ 0x002A04E6,
+ 0x0F12065F,
+ 0x002A04D6,
+ 0x0F120000,
+ 0x0F120001,
+
+ 0x002A04D0,
+ 0x0F120001,
+ 0x0F120340,
+ 0x0F120001,
+ 0x002A06C2,
+ 0x0F120100,
+
+ 0x002A0938,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_ISO_400[] = {
+ 0x002A04E6,
+ 0x0F12065F,
+ 0x002A04D6,
+ 0x0F120000,
+ 0x0F120001,
+
+ 0x002A04D0,
+ 0x0F120001,
+ 0x0F120680,
+ 0x0F120001,
+ 0x002A06C2,
+ 0x0F120100,
+
+ 0x002A0938,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Metering_Matrix[] = {
+ 0x002A1492,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+};
+
+static const u32 s5k4ecgx_Metering_Center[] = {
+ 0x002A1492,
+ 0x0F120000,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120000,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120201,
+ 0x0F120303,
+ 0x0F120303,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120403,
+ 0x0F120304,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120403,
+ 0x0F120304,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120403,
+ 0x0F120304,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120303,
+ 0x0F120303,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120202,
+ 0x0F120202,
+ 0x0F120102,
+};
+
+static const u32 s5k4ecgx_Metering_Spot[] = {
+ 0x002A1492,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F12010F,
+ 0x0F120F01,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F12010F,
+ 0x0F120F01,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_EV_Minus_4[] = {
+ 0x002A0230,
+ 0x0F12FF30,
+};
+
+static const u32 s5k4ecgx_EV_Minus_3[] = {
+ 0x002A0230,
+ 0x0F12FFA0,
+};
+
+static const u32 s5k4ecgx_EV_Minus_2[] = {
+ 0x002A0230,
+ 0x0F12FFC8,
+};
+
+static const u32 s5k4ecgx_EV_Minus_1[] = {
+ 0x002A0230,
+ 0x0F12FFE0,
+};
+
+static const u32 s5k4ecgx_EV_Default[] = {
+ 0x002A0230,
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_EV_Plus_1[] = {
+ 0x002A0230,
+ 0x0F120020,
+};
+
+static const u32 s5k4ecgx_EV_Plus_2[] = {
+ 0x002A0230,
+ 0x0F120038,
+};
+
+static const u32 s5k4ecgx_EV_Plus_3[] = {
+ 0x002A0230,
+ 0x0F120060,
+};
+
+static const u32 s5k4ecgx_EV_Plus_4[] = {
+ 0x002A0230,
+ 0x0F12007F,
+};
+
+static const u32 s5k4ecgx_Contrast_Minus_4[] = {
+ 0x002A0232,
+ 0x0F12FF81,
+};
+
+static const u32 s5k4ecgx_Contrast_Minus_3[] = {
+ 0x002A0232,
+ 0x0F12FFA0,
+};
+
+static const u32 s5k4ecgx_Contrast_Minus_2[] = {
+ 0x002A0232,
+ 0x0F12FFC0,
+};
+
+static const u32 s5k4ecgx_Contrast_Minus_1[] = {
+ 0x002A0232,
+ 0x0F12FFE0,
+};
+
+static const u32 s5k4ecgx_Contrast_Default[] = {
+ 0x002A0232,
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_Contrast_Plus_1[] = {
+ 0x002A0232,
+ 0x0F120020,
+};
+
+static const u32 s5k4ecgx_Contrast_Plus_2[] = {
+ 0x002A0232,
+ 0x0F120040,
+};
+
+static const u32 s5k4ecgx_Contrast_Plus_3[] = {
+ 0x002A0232,
+ 0x0F120060,
+};
+
+static const u32 s5k4ecgx_Contrast_Plus_4[] = {
+ 0x002A0232,
+ 0x0F12007F,
+};
+
+static const u32 s5k4ecgx_Sharpness_Minus_3[] = {
+ 0x002A0A28,
+ 0x0F120000,
+ 0x002A0ADE,
+ 0x0F120000,
+ 0x002A0B94,
+ 0x0F120000,
+ 0x002A0C4A,
+ 0x0F120000,
+ 0x002A0D00,
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_Sharpness_Minus_2[] = {
+ 0x002A0A28,
+ 0x0F122010,
+ 0x002A0ADE,
+ 0x0F122010,
+ 0x002A0B94,
+ 0x0F122010,
+ 0x002A0C4A,
+ 0x0F122010,
+ 0x002A0D00,
+ 0x0F122010,
+};
+
+static const u32 s5k4ecgx_Sharpness_Minus_1[] = {
+ 0x002A0A28,
+ 0x0F124020,
+ 0x002A0ADE,
+ 0x0F124020,
+ 0x002A0B94,
+ 0x0F124020,
+ 0x002A0C4A,
+ 0x0F124020,
+ 0x002A0D00,
+ 0x0F124020,
+};
+
+static const u32 s5k4ecgx_Sharpness_Default[] = {
+ 0x002A0A28,
+ 0x0F126024,
+ 0x002A0ADE,
+ 0x0F126024,
+ 0x002A0B94,
+ 0x0F126024,
+ 0x002A0C4A,
+ 0x0F126024,
+ 0x002A0D00,
+ 0x0F126024,
+};
+
+static const u32 s5k4ecgx_Sharpness_Plus_1[] = {
+ 0x002A0A28,
+ 0x0F128040,
+ 0x002A0ADE,
+ 0x0F128040,
+ 0x002A0B94,
+ 0x0F128040,
+ 0x002A0C4A,
+ 0x0F128040,
+ 0x002A0D00,
+ 0x0F128040,
+};
+
+static const u32 s5k4ecgx_Sharpness_Plus_2[] = {
+ 0x002A0A28,
+ 0x0F12A060,
+ 0x002A0ADE,
+ 0x0F12A060,
+ 0x002A0B94,
+ 0x0F12A060,
+ 0x002A0C4A,
+ 0x0F12A060,
+ 0x002A0D00,
+ 0x0F12A060,
+};
+
+static const u32 s5k4ecgx_Sharpness_Plus_3[] = {
+ 0x002A0A28,
+ 0x0F12C080,
+ 0x002A0ADE,
+ 0x0F12C080,
+ 0x002A0B94,
+ 0x0F12C080,
+ 0x002A0C4A,
+ 0x0F12C080,
+ 0x002A0D00,
+ 0x0F12C080,
+};
+
+static const u32 s5k4ecgx_Saturation_Minus_2[] = {
+ 0x002A0234,
+ 0x0F12FF81,
+};
+
+static const u32 s5k4ecgx_Saturation_Minus_1[] = {
+ 0x002A0234,
+ 0x0F12FFC0,
+};
+
+static const u32 s5k4ecgx_Saturation_Default[] = {
+ 0x002A0234,
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_Saturation_Plus_1[] = {
+ 0x002A0234,
+ 0x0F120040,
+};
+
+static const u32 s5k4ecgx_Saturation_Plus_2[] = {
+ 0x002A0234,
+ 0x0F12007F,
+};
+
+static const u32 s5k4ecgx_Jpeg_Quality_High[] = {
+ 0x002A0478,
+ 0x0F12005F,
+ 0x0F12005F,
+};
+
+static const u32 s5k4ecgx_Jpeg_Quality_Normal[] = {
+ 0x002A0478,
+ 0x0F12005A,
+ 0x0F12005A,
+};
+
+static const u32 s5k4ecgx_Jpeg_Quality_Low[] = {
+ 0x002A0478,
+ 0x0F120054,
+ 0x0F120054,
+};
+
+static const u32 s5k4ecgx_Scene_Default[] = {
+ 0x002A1492,
+ 0x0F120000,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120000,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120201,
+ 0x0F120303,
+ 0x0F120303,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120403,
+ 0x0F120304,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120403,
+ 0x0F120304,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120403,
+ 0x0F120304,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120303,
+ 0x0F120303,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120202,
+ 0x0F120202,
+ 0x0F120102,
+
+ 0x002A0938,
+ 0x0F120000,
+
+ 0x002A06B8,
+ 0x0F12452C,
+ 0x0F12000C,
+
+ 0x002A0F2A,
+ 0x0F120001,
+ 0x002A0F30,
+ 0x0F120001,
+ 0x002A04E6,
+ 0x0F12077F,
+
+ 0x002A04D0,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120001,
+ 0x002A06C2,
+ 0x0F120200,
+
+ 0x002A2C66,
+ 0x0F120001,
+
+ 0x002A1484,
+ 0x0F12003C,
+ 0x002A148A,
+ 0x0F12000F,
+ 0x002A058C,
+ 0x0F123520,
+ 0x0F120000,
+ 0x0F12C350,
+ 0x0F120000,
+ 0x0F123520,
+ 0x0F120000,
+ 0x0F12C350,
+ 0x0F120000,
+ 0x0F120470,
+ 0x0F120C00,
+ 0x0F120100,
+ 0x0F121000,
+
+ 0x002A0544,
+ 0x0F120111,
+ 0x0F1200EF,
+
+ 0x002A0608,
+ 0x0F120001,
+ 0x0F120001,
+
+ 0x002A0A28,
+ 0x0F126024,
+ 0x002A0ADE,
+ 0x0F126024,
+ 0x002A0B94,
+ 0x0F126024,
+ 0x002A0C4A,
+ 0x0F126024,
+ 0x002A0D00,
+ 0x0F126024,
+
+ 0x002A0234,
+ 0x0F120000,
+
+ 0x002A0638,
+ 0x0F120001,
+ 0x0F120000,
+ 0x002A063C,
+ 0x0F120A3C,
+ 0x0F120000,
+ 0x002A0640,
+ 0x0F120D05,
+ 0x0F120000,
+ 0x002A0644,
+ 0x0F123408,
+ 0x0F120000,
+ 0x002A0648,
+ 0x0F123408,
+ 0x0F120000,
+ 0x002A064C,
+ 0x0F126810,
+ 0x0F120000,
+ 0x002A0650,
+ 0x0F128214,
+ 0x0F120000,
+ 0x002A0654,
+ 0x0F12C350,
+ 0x0F120000,
+ 0x002A0658,
+ 0x0F12C350,
+ 0x0F120000,
+ 0x002A065C,
+ 0x0F12C350,
+ 0x0F120000,
+
+ 0x002A02C2,
+ 0x0F12029A, /*#REG_0TC_PCFG_usMaxFrTimeMsecMult10*/
+ 0x0F12014A, /*#REG_0TC_PCFG_usMinFrTimeMsecMult10*/
+
+ 0x002A03B4,
+ 0x0F120535,
+ 0x0F12029A,
+
+ 0x002A0266,
+ 0x0F120000,
+ 0x002A026A,
+ 0x0F120001,
+ 0x002A024E,
+ 0x0F120001,
+ 0x002A0268,
+ 0x0F120001,
+ 0x002A0270,
+ 0x0F120001,
+ 0x002A023E,
+ 0x0F120001,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Scene_Portrait[] = {
+ 0x002A0A28,
+ 0x0F122010,
+ 0x002A0ADE,
+ 0x0F122010,
+ 0x002A0B94,
+ 0x0F122010,
+ 0x002A0C4A,
+ 0x0F122010,
+ 0x002A0D00,
+ 0x0F122010,
+};
+
+static const u32 s5k4ecgx_Scene_Nightshot[] = {
+ 0x002A06B8,
+ 0x0F12FFFF,
+ 0x0F1200FF,
+
+ 0x002A0608,
+ 0x0F120001, /*#lt_ExpGain_uSubsamplingmode*/
+ 0x0F120001, /*#lt_ExpGain_uNonSubsampling*/
+ 0x0F120900, /*#lt_ExpGain_ExpCurveGainMaxStr*/
+
+ 0x002A0658,
+ 0x0F12D090,
+ 0x0F120007,
+ 0x0F12D090,
+ 0x0F120007,
+
+ 0x002A03B4,
+ 0x0F121388,
+ 0x0F121388,
+ 0x002A02C2,
+ 0x0F1209C4,
+ 0x0F12014A,
+ 0x002A0266,
+ 0x0F120000,
+ 0x002A026A,
+ 0x0F120001,
+ 0x002A024E,
+ 0x0F120001,
+ 0x002A0268,
+ 0x0F120001,
+ 0x002A0270,
+ 0x0F120001,
+ 0x002A023E,
+ 0x0F120001,
+ 0x0F120001,
+
+ 0x002A0A1E,
+ 0x0F121580,
+};
+
+static const u32 s5k4ecgx_Scene_Backlight[] = {
+ 0x002A1492,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F12010F,
+ 0x0F120F01,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F12010F,
+ 0x0F120F01,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_Scene_Landscape[] = {
+ 0x002A1492,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x002A0A28,
+ 0x0F12E082,
+ 0x002A0ADE,
+ 0x0F12E082,
+ 0x002A0B94,
+ 0x0F12E082,
+ 0x002A0C4A,
+ 0x0F12E082,
+ 0x002A0D00,
+ 0x0F12E082,
+ 0x002A0234,
+ 0x0F120030,
+};
+
+static const u32 s5k4ecgx_Scene_Sports[] = {
+ 0x002A0608,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x002A058C,
+ 0x0F123520,
+ 0x0F120000,
+ 0x0F123520,
+ 0x0F120000,
+ 0x0F123520,
+ 0x0F120000,
+ 0x0F123520,
+ 0x0F120000,
+ 0x0F120200,
+ 0x0F120200,
+ 0x0F120200,
+ 0x0F120200,
+
+ 0x002A0266,
+ 0x0F120000,
+ 0x002A026A,
+ 0x0F120001,
+ 0x002A024E,
+ 0x0F120001,
+ 0x002A0268,
+ 0x0F120001,
+ 0x002A0270,
+ 0x0F120001,
+ 0x002A023E,
+ 0x0F120001,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Scene_Party_Indoor[] = {
+ 0x002A04E6,
+ 0x0F12065F,
+ 0x002A04D6,
+ 0x0F120000,
+ 0x0F120001,
+
+ 0x002A04D0,
+ 0x0F120001,
+ 0x0F120340,
+ 0x0F120001,
+ 0x002A06C2,
+ 0x0F120100,
+
+ 0x002A0938,
+ 0x0F120001,
+
+ 0x002A0234,
+ 0x0F120030,
+};
+
+static const u32 s5k4ecgx_Scene_Beach_Snow[] = {
+ 0x002A1484,
+ 0x0F120045, /*#TVAR_ae_BrAve*/
+ 0x002A04E6,
+ 0x0F12065F,
+ 0x002A04D6,
+ 0x0F120000,
+ 0x0F120001,
+ 0x002A04D0,
+ 0x0F120001,
+ 0x0F1200D0,
+ 0x0F120001,
+ 0x002A06C2,
+ 0x0F120100,
+
+ 0x002A0938,
+ 0x0F120001,
+
+ 0x002A0234,
+ 0x0F120030,
+};
+
+static const u32 s5k4ecgx_Scene_Sunset[] = {
+ 0x002A04E6,
+ 0x0F120777,
+
+ 0x002A04BA,
+ 0x0F1205E0,
+ 0x0F120001,
+ 0x0F120400,
+ 0x0F120001,
+ 0x0F120530,
+ 0x0F120001,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Scene_Duskdawn[] = {
+ 0x002A04E6,
+ 0x0F120777,
+ 0x002A04BA,
+ 0x0F120505,
+ 0x0F120001,
+ 0x0F120400,
+ 0x0F120001,
+ 0x0F120875,
+ 0x0F120001,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Scene_Fall_Color[] = {
+ 0x002A0234,
+ 0x0F120060,
+};
+
+static const u32 s5k4ecgx_Scene_Fireworks[] = {
+ 0x002A0638,
+ 0x0F120001,
+ 0x0F120000,
+ 0x002A063C,
+ 0x0F121478,
+ 0x0F120000,
+ 0x002A0640,
+ 0x0F121A0A,
+ 0x0F120000,
+ 0x002A0644,
+ 0x0F126810,
+ 0x0F120000,
+ 0x002A0648,
+ 0x0F126810,
+ 0x0F120000,
+ 0x002A064C,
+ 0x0F12D020,
+ 0x0F120000,
+ 0x002A0650,
+ 0x0F120428,
+ 0x0F120001,
+ 0x002A0654,
+ 0x0F121A80,
+ 0x0F120006,
+ 0x002A0658,
+ 0x0F121A80,
+ 0x0F120006,
+ 0x002A065C,
+ 0x0F121A80,
+ 0x0F120006,
+
+ 0x002A03B4,
+ 0x0F122710,
+ 0x0F122710,
+
+ 0x002A0266,
+ 0x0F120000,
+ 0x002A026A,
+ 0x0F120001,
+ 0x002A024E,
+ 0x0F120001,
+ 0x002A0268,
+ 0x0F120001,
+ 0x002A0270,
+ 0x0F120001,
+ 0x002A023E,
+ 0x0F120001,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Scene_Text[] = {
+ 0x002A0A28,
+ 0x0F12A060,
+ 0x002A0ADE,
+ 0x0F12A060,
+ 0x002A0B94,
+ 0x0F12A060,
+ 0x002A0C4A,
+ 0x0F12A060,
+ 0x002A0D00,
+ 0x0F12A060,
+};
+
+static const u32 s5k4ecgx_Scene_Candle_Light[] = {
+ 0x002A04E6,
+ 0x0F120777,
+ 0x002A04BA,
+ 0x0F1205E0,
+ 0x0F120001,
+ 0x0F120400,
+ 0x0F120001,
+ 0x0F120530,
+ 0x0F120001,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Night_Capture[] = {
+ 0x002A0608,
+ 0x0F120001, /*#lt_ExpGain_uSubsamplingmode*/
+ 0x0F120001, /*#lt_ExpGain_uNonSubsampling*/
+ 0x0F120900, /*#lt_ExpGain_ExpCurveGainMaxStr*/
+};
+
+static const u32 s5k4ecgx_AF_Return_Macro_pos[] = {
+ 0x002A15E8,
+ 0x0F120018,
+ 0x0F12002A,
+ 0x0F120030,
+ 0x0F120036,
+ 0x0F12003C,
+ 0x0F120042,
+ 0x0F120048,
+ 0x0F12004E,
+ 0x0F120054,
+ 0x0F12005A,
+ 0x0F120060,
+ 0x0F120066,
+ 0x0F12006C,
+ 0x0F120072,
+ 0x0F120078,
+ 0x0F12007E,
+ 0x0F120084,
+ 0x0F12008A,
+ 0x0F120090,
+ 0x0F120096,
+ 0x0F12009C,
+ 0x0F1200A2,
+ 0x0F1200A8,
+ 0x0F1200AE,
+ 0x0F1200B4,
+ 0x0F1200BA,
+};
+
+static const u32 s5k4ecgx_AF_Normal_mode_1[] = {
+ 0x002A028E,
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_AF_Normal_mode_2[] = {
+ 0x002A028C,
+ 0x0F120004,
+};
+
+static const u32 s5k4ecgx_AF_Normal_mode_3[] = {
+ 0x002A1648,
+ 0x0F129002,
+};
+
+static const u32 s5k4ecgx_AF_Macro_mode_1[] = {
+ 0x002A028E,
+ 0x0F1200D0,
+};
+
+static const u32 s5k4ecgx_AF_Macro_mode_2[] = {
+ 0x002A028C,
+ 0x0F120004,
+};
+
+static const u32 s5k4ecgx_AF_Macro_mode_3[] = {
+ 0x002A1648,
+ 0x0F129042,
+ 0x002A15DA,
+ 0x0F121800,
+};
+
+static const u32 s5k4ecgx_AF_Low_Light_Mode_On[] = {
+ 0x002A15DA,
+ 0x0F120C00,
+
+ 0x002A15E8,
+ 0x0F12000C,
+ 0x0F12002A,
+ 0x0F120033,
+ 0x0F12003C,
+ 0x0F120045,
+ 0x0F12004E,
+ 0x0F120057,
+ 0x0F120063,
+ 0x0F12006F,
+ 0x0F12007B,
+ 0x0F120087,
+ 0x0F120093,
+ 0x0F1200A2,
+ 0x0F1200B1,
+};
+
+static const u32 s5k4ecgx_AF_Low_Light_Mode_Off[] = {
+ 0x002A15DA,
+ 0x0F121800,
+
+ 0x002A15E8,
+ 0x0F120018,
+ 0x0F12002A,
+ 0x0F120030,
+ 0x0F120036,
+ 0x0F12003C,
+ 0x0F120042,
+ 0x0F120048,
+ 0x0F12004E,
+ 0x0F120054,
+ 0x0F12005A,
+ 0x0F120060,
+ 0x0F120066,
+ 0x0F12006C,
+ 0x0F120072,
+ 0x0F120078,
+ 0x0F12007E,
+ 0x0F120084,
+ 0x0F12008A,
+ 0x0F120090,
+ 0x0F120096,
+ 0x0F12009C,
+ 0x0F1200A2,
+ 0x0F1200A8,
+ 0x0F1200AE,
+ 0x0F1200B4,
+ 0x0F1200BA,
+};
+
+static const u32 s5k4ecgx_Single_AF_Start[] = {
+ 0x002A028C,
+ 0x0F120005,
+};
+
+static const u32 s5k4ecgx_Single_AF_Off_1[] = {
+ 0x002A028E,
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_Single_AF_Off_2[] = {
+ 0x002A028C,
+ 0x0F120004,
+};
+
+static const u32 s5k4ecgx_Single_AF_Off_3[] = {
+
+};
+
+
+static const u32 s5k4ecgx_Face_Detection_On[] = {
+ 0x002A0294,
+ 0x0F120100,
+ 0x0F1200E3,
+ 0x0F120200,
+ 0x0F120238,
+ 0x0F1201C6,
+ 0x0F120166,
+ 0x0F120074,
+ 0x0F120132,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Face_Detection_Off[] = {
+ 0x002A0294,
+ 0x0F120100,
+ 0x0F1200E3,
+ 0x0F120200,
+ 0x0F120238,
+ 0x0F1201C6,
+ 0x0F120166,
+ 0x0F120074,
+ 0x0F120132,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Low_Cap_On[] = {
+ 0x002A06B8,
+ 0x0F12FFFF,
+ 0x0F1200FF, /*#lt_uMaxLei*/
+
+ 0x002A0A1A,
+ 0x0F124A18, /*#Gamma linearity*/
+
+
+ 0x002A0608,
+ 0x0F120001, /*#lt_ExpGain_uSubsamplingmode*/
+ 0x0F120001, /*#lt_ExpGain_uNonSubsampling*/
+ 0x0F120850, /*#lt_ExpGain_ExpCurveGainMaxStr*/
+
+ 0x002A0938,
+ 0x0F120001,
+ 0x0F120012, /*#SARR_uNormBrInDoor_0_*/
+ 0x0F120022, /*#SARR_uNormBrInDoor_1_*/
+ 0x0F120384, /*#SARR_uNormBrInDoor_2_*/
+ 0x0F1207D0, /*#SARR_uNormBrInDoor_3_*/
+ 0x0F121388, /*#SARR_uNormBrInDoor_4_*/
+};
+
+static const u32 s5k4ecgx_Low_Cap_Off[] = {
+ 0x002A06B8,
+ 0x0F12452C,
+ 0x0F12000C, /*#lt_uMaxLei*/
+
+ 0x002A0A1A,
+ 0x0F128F18, /*#Gamma linearity*/
+
+
+ 0x002A0608,
+ 0x0F120001, /*#lt_ExpGain_uSubsamplingmode*/
+ 0x0F120001, /*#lt_ExpGain_uNonSubsampling*/
+ 0x0F120C00, /*#lt_ExpGain_ExpCurveGainMaxStr*/
+
+ 0x002A0938,
+ 0x0F120000,
+ 0x0F120014, /*#SARR_uNormBrInDoor_0_*/
+ 0x0F1200D2, /*#SARR_uNormBrInDoor_1_*/
+ 0x0F120384, /*#SARR_uNormBrInDoor_2_*/
+ 0x0F1207D0, /*#SARR_uNormBrInDoor_3_*/
+ 0x0F121388, /*#SARR_uNormBrInDoor_4_*/
+};
+
+/* restores crop settings to full resolution */
+static const u32 s5k4ecgx_Reset_Crop[] = {
+ 0x002A0250,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120010,
+ 0x0F12000C,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120010,
+ 0x0F12000C,
+ 0x002A0494,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x002A0262,
+ 0x0F120001,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Capture_Start[] = {
+ 0x002A0A1E,
+ 0x0F120050,
+
+ 0x002A0AD4,
+ 0x0F120074,
+
+ 0x002A0608,
+ 0x0F120001, /*#lt_ExpGain_uSubsamplingmode*/
+ 0x0F120001, /*#lt_ExpGain_uNonSubsampling*/
+ 0x0F120850, /*#lt_ExpGain_ExpCurveGainMaxStr*/
+
+ 0x002A0242,
+ 0x0F120001,
+
+ 0x002A024E,
+ 0x0F120001,
+
+ 0x002A0244,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Preview_Return[] = {
+ 0x002A0A1E,
+ 0x0F120028,
+
+ 0x002A0AD4,
+ 0x0F12003C,
+
+ 0x002A0608,
+ 0x0F120001, /*#lt_ExpGain_uSubsamplingmode*/
+ 0x0F120001, /*#lt_ExpGain_uNonSubsampling*/
+ 0x0F120C00, /*#lt_ExpGain_ExpCurveGainMaxStr*/
+
+ 0x002A05D0,
+ 0x0F120000,
+
+ 0x002A0972,
+ 0x0F120000,
+
+ 0x002A0242,
+ 0x0F120000,
+
+ 0x002A024E,
+ 0x0F120001,
+
+ 0x002A0244,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Flash_init[] = {
+ 0x002A0484,
+ 0x0F120002, /* capture flash on */
+
+ 0x002A183A,
+ 0x0F120001, /* one frame AE*/
+
+ 0x002A17F6,
+ 0x0F120258, /* AWB R point */
+ 0x0F120248, /* AWB B point */
+
+ 0x002A1840,
+ 0x0F120001, /* Fls AE tune start */
+
+ 0x0F120100, /* fls_afl_FlsAFIn Rin */
+ 0x0F120120,
+ 0x0F120180,
+ 0x0F120200,
+ 0x0F120400,
+ 0x0F120800,
+ 0x0F120A00,
+ 0x0F121000,
+
+ 0x0F120100, /* fls_afl_FlsAFOut Rout */
+ 0x0F1200A0,
+ 0x0F120090,
+ 0x0F120080,
+ 0x0F120070,
+ 0x0F120045,
+ 0x0F120030,
+ 0x0F120010,
+
+ 0x002A1884,
+ 0x0F120100, /* fls_afl_FlsNBOut flash NB default */
+ 0x0F120100,
+ 0x0F120100,
+ 0x0F120100,
+ 0x0F120100,
+ 0x0F120100,
+ 0x0F120100,
+ 0x0F120100,
+
+ 0x002A1826,
+
+ 0x0F120100, /* fls_afl_FlashWP_Weight flash NB default */
+ 0x0F1200C0,
+ 0x0F120080,
+ 0x0F12000A,
+ 0x0F120000,
+
+ 0x0F120030, /* fls_afl_FlashWP_Weight flash NB default */
+ 0x0F120040,
+ 0x0F120048,
+ 0x0F120050,
+ 0x0F120060,
+
+ 0x002A4784,
+ 0x0F1200A0, /* TNP_Regs_FlsWeightRIn weight tune start in*/
+ 0x0F1200C0,
+ 0x0F1200D0,
+ 0x0F120100,
+ 0x0F120200,
+ 0x0F120300,
+
+ 0x0F120088, /* TNP_Regs_FlsWeightROut weight tune start out*/
+ 0x0F1200B0,
+ 0x0F1200C0,
+ 0x0F120100,
+ 0x0F120200,
+ 0x0F120300,
+
+ 0x002A479C,
+
+ 0x0F120120, /*Fls BRIn */
+ 0x0F120150,
+ 0x0F120200,
+
+ 0x0F12003C, /* Fls BROut*/
+ 0x0F12003B,
+ 0x0F120030,
+
+};
+
+static const u32 s5k4ecgx_Pre_Flash_Start[] = {
+ 0x002A0588, /* set AE speed to fast */
+ 0x0F120000,
+
+ 0x002A17FC, /* fls_afl_FlashWP_Weight_0_ Pre_Flash_Start */
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Pre_Flash_End[] = {
+ 0x002A0588, /* set AE speed to normal */
+ 0x0F120002,
+
+ 0x002A1800, /* fls_afl_FlashWP_Weight_0_ Pre_Flash_end */
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Flash_Start[] = {
+ 0x002A17E8, /* fls_afl_FlashMode : Flash alg start */
+ 0x0F120001,
+
+ 0x002A180C, /* fls_afl_FlashWP_Weight_4_ flash br avg */
+ 0x0F120027,
+};
+
+static const u32 s5k4ecgx_Flash_End[] = {
+ 0x002A17E8, /* fls_afl_FlashMode Flash alg end */
+ 0x0F120000,
+};
+
+/* 2560 x 1920 */
+static const u32 s5k4ecgx_5M_Capture[] = {
+ 0x002A0398,
+ 0x0F120A00, /* #REG_0TC_CCFG_usWidth */
+ 0x0F120780, /* #REG_0TC_CCFG_usHeight */
+ 0x0F120009,
+
+ 0x002A03B2,
+ 0x0F120002,
+ 0x002A03B0,
+ 0x0F120002,
+ 0x002A0270,
+ 0x0F120001,
+};
+/* 2048 x 1536 */
+static const u32 s5k4ecgx_3M_Capture[] = {
+ 0x002A0398,
+ 0x0F120800, /* REG_0TC_CCFG_usWidth */
+ 0x0F120600, /* REG_0TC_CCFG_usWidth */
+ 0x0F120009, /* REG_0TC_CCFG_Format */
+
+ 0x002A03B2,
+ 0x0F120002, /* REG_0TC_CCFG_FrRateQualityType */
+ 0x002A03B0,
+ 0x0F120002, /* REG_0TC_CCFG_usFrTimeType */
+ 0x002A024E,
+ 0x0F120001, /* REG_TC_GP_NewConfigSync */
+ 0x002A0270,
+ 0x0F120001, /* REG_TC_GP_CapConfigChanged */
+};
+/* 1600 x 1200 */
+static const u32 s5k4ecgx_2M_Capture[] = {
+ 0x002A0398,
+ 0x0F120640, /* #REG_0TC_CCFG_usWidth */
+ 0x0F1204B0, /* #REG_0TC_CCFG_usHeight */
+ 0x0F120009,
+ 0x002A03B2,
+ 0x0F120002,
+ 0x002A03B0,
+ 0x0F120002,
+ 0x002A024E,
+ 0x0F120001,
+ 0x002A0270,
+ 0x0F120001,
+};
+/* 1280 x 960 */
+static const u32 s5k4ecgx_1M_Capture[] = {
+ 0x002A0398,
+ 0x0F120500, /* #REG_0TC_CCFG_usWidth */
+ 0x0F1203C0, /* #REG_0TC_CCFG_usHeight */
+ 0x0F120009,
+ 0x002A03B2,
+ 0x0F120002,
+ 0x002A03B0,
+ 0x0F120002,
+ 0x002A024E,
+ 0x0F120001,
+ 0x002A0270,
+ 0x0F120001,
+};
+/* 640 x 480 */
+static const u32 s5k4ecgx_VGA_Capture[] = {
+ 0x002A0398,
+ 0x0F120280, /* #REG_0TC_CCFG_usWidth */
+ 0x0F1201E0, /* #REG_0TC_CCFG_usHeight */
+ 0x0F120009,
+ 0x002A03B2,
+ 0x0F120002,
+ 0x002A03B0,
+ 0x0F120002,
+ 0x002A024E,
+ 0x0F120001,
+ 0x002A0270,
+ 0x0F120001,
+};
+/* 720 x 480 */
+static const u32 s5k4ecgx_720_Preview[] = {
+ 0x002A0250,
+ 0x0F120A00,
+ 0x0F1206A8,
+ 0x0F120010,
+ 0x0F120078,
+ 0x0F120A00,
+ 0x0F1206A8,
+ 0x0F120010,
+ 0x0F120078,
+ 0x002A0494,
+ 0x0F120A00,
+ 0x0F1206A8,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120A00,
+ 0x0F1206A8,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x002A0262,
+ 0x0F120001, /* #REG_TC_GP_bUseReqInputInPre */
+ 0x002A0A1E,
+ 0x0F120028,
+ 0x002A0AD4,
+ 0x0F12003C,
+
+ 0x002A02A6,
+ 0x0F1202D0,
+ 0x0F1201E0,
+ 0x0F120005,
+ 0x002A02B4,
+ 0x0F120052,
+ 0x002A02BE,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F12029A,
+ 0x0F12014D,
+ 0x002A02D0,
+ 0x0F120000,
+ 0x0F120000,
+ 0x002A0266,
+ 0x0F120000,
+ 0x002A026A,
+ 0x0F120001,
+ 0x002A024E,
+ 0x0F120001, /* #REG_TC_GP_NewConfigSync */
+ 0x002A0268,
+ 0x0F120001, /* #REG_TC_GP_CapConfigChanged */
+};
+/* 640 x 480 */
+static const u32 s5k4ecgx_640_Preview[] = {
+ 0x002A0250,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120010,
+ 0x0F12000C,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120010,
+ 0x0F12000C,
+ 0x002A0494,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x002A0262,
+ 0x0F120001, /* #REG_TC_GP_bUseReqInputInPre */
+ 0x002A0A1E,
+ 0x0F120028,
+ 0x002A0AD4,
+ 0x0F12003C,
+
+ 0x002A02A6,
+ 0x0F120280,
+ 0x0F1201E0,
+ 0x0F120005,
+ 0x002A02B4,
+ 0x0F120052,
+ 0x002A02BE,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F12029A,
+ 0x0F12014A,
+ 0x002A02D0,
+ 0x0F120000,
+ 0x0F120000,
+ 0x002A0266,
+ 0x0F120000,
+ 0x002A026A,
+ 0x0F120001,
+ 0x002A024E,
+ 0x0F120001, /* #REG_TC_GP_NewConfigSync */
+ 0x002A0268,
+ 0x0F120001, /* #REG_TC_GP_CapConfigChanged */
+};
+/* 352 x 288 */
+static const u32 s5k4ecgx_352_Preview[] = {
+ 0x002A0250,
+ 0x0F120928,
+ 0x0F120780,
+ 0x0F12007C,
+ 0x0F12000C,
+ 0x0F120928,
+ 0x0F120780,
+ 0x0F12007C,
+ 0x0F12000C,
+ 0x002A0494,
+ 0x0F120928,
+ 0x0F120780,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120928,
+ 0x0F120780,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x002A0262,
+ 0x0F120001, /* #REG_TC_GP_bUseReqInputInPre */
+ 0x002A0A1E,
+ 0x0F120028,
+ 0x002A0AD4,
+ 0x0F12003C,
+
+ 0x002A02A6,
+ 0x0F120160,
+ 0x0F120120,
+ 0x0F120005,
+ 0x002A02B4,
+ 0x0F120052,
+ 0x002A02BE,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F12029A,
+ 0x0F12014D,
+ 0x002A02D0,
+ 0x0F120000,
+ 0x0F120000,
+ 0x002A0266,
+ 0x0F120000,
+ 0x002A026A,
+ 0x0F120001,
+ 0x002A024E,
+ 0x0F120001, /* #REG_TC_GP_NewConfigSync */
+ 0x002A0268,
+ 0x0F120001, /* #REG_TC_GP_CapConfigChanged */
+};
+/* 176 x 144 */
+static const u32 s5k4ecgx_176_Preview[] = {
+ 0x002A0250,
+ 0x0F120928,
+ 0x0F120780,
+ 0x0F12007C,
+ 0x0F12000C,
+ 0x0F120928,
+ 0x0F120780,
+ 0x0F12007C,
+ 0x0F12000C,
+ 0x002A0494,
+ 0x0F120928,
+ 0x0F120780,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120928,
+ 0x0F120780,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x002A0262,
+ 0x0F120001, /* #REG_TC_GP_bUseReqInputInPre */
+ 0x002A0A1E,
+ 0x0F120028,
+ 0x002A0AD4,
+ 0x0F12003C,
+
+ 0x002A02A6,
+ 0x0F1200B0,
+ 0x0F120090,
+ 0x0F120005,
+ 0x002A02B4,
+ 0x0F120052,
+ 0x002A02BE,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F12029A,
+ 0x0F12014D,
+ 0x002A02D0,
+ 0x0F120000,
+ 0x0F120000,
+ 0x002A0266,
+ 0x0F120000,
+ 0x002A026A,
+ 0x0F120001,
+ 0x002A024E,
+ 0x0F120001, /* #REG_TC_GP_NewConfigSync */
+ 0x002A0268,
+ 0x0F120001, /* #REG_TC_GP_CapConfigChanged */
+};
+
+static const u32 s5k4ecgx_AE_AWB_Lock_On[] = {
+ 0x002A2C5E,
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_AE_AWB_Lock_Off[] = {
+ 0x002A2C5E,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Get_AE_Stable_Status[] = {
+ 0x002E2C74,
+};
+
+static const u32 s5k4ecgx_Get_Light_Level[] = {
+ 0x002C7000,
+ 0x002E2C18,
+};
+
+static const u32 s5k4ecgx_get_1st_af_search_status[] = {
+ 0x002E2EEE,
+};
+
+static const u32 s5k4ecgx_get_2nd_af_search_status[] = {
+ 0x002E2207,
+};
+
+static const u32 s5k4ecgx_get_capture_status[] = {
+ 0x002E0530,
+};
+
+static const u32 s5k4ecgx_get_esd_status[] = {
+ 0xFCFCD000,
+ 0x002CD000,
+ 0x002E0060,
+};
+
+static const u32 s5k4ecgx_get_iso_reg[] = {
+ 0x002C7000,
+ 0x002E2BC4,
+};
+
+static const u32 s5k4ecgx_get_shutterspeed_reg[] = {
+ 0x002C7000,
+ 0x002E2BC0,
+};
+
+#endif /* __S5K4ECGX_REGS_1_0_H__ */
diff --git a/drivers/media/video/s5ka3dfx.c b/drivers/media/video/s5ka3dfx.c
new file mode 100755
index 0000000..e4ca5f0
--- /dev/null
+++ b/drivers/media/video/s5ka3dfx.c
@@ -0,0 +1,1229 @@
+/*
+ * Driver for S5KA3DFX (UXGA camera) from Samsung Electronics
+ *
+ * 1/4" 2.0Mp CMOS Image Sensor SoC with an Embedded Image Processor
+ *
+ * Copyright (C) 2009, Jinsung Yang <jsgood.yang@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/i2c.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <media/s5ka3dfx_platform.h>
+
+#ifdef CONFIG_VIDEO_SAMSUNG_V4L2
+#include <linux/videodev2_samsung.h>
+#endif
+
+#include "s5ka3dfx.h"
+
+#define S5KA3DFX_DRIVER_NAME "S5KA3DFX"
+
+/* #define VGA_CAM_DEBUG */
+
+#ifdef VGA_CAM_DEBUG
+#define dev_dbg dev_err
+#endif
+
+/* Default resolution & pixelformat. plz ref s5ka3dfx_platform.h */
+#define DEFAULT_RESOLUTION WVGA /* Index of resoultion */
+#define DEFAUT_FPS_INDEX S5KA3DFX_15FPS
+#define DEFUALT_MCLK 24000000 /* 24MHz default */
+#define DEFAULT_FMT V4L2_PIX_FMT_UYVY /* YUV422 */
+#define POLL_TIME_MS 10
+
+/*
+ * Specification
+ * Parallel : ITU-R. 656/601 YUV422, RGB565, RGB888 (Up to VGA), RAW10
+ * Serial : MIPI CSI2 (single lane) YUV422, RGB565, RGB888 (Up to VGA), RAW10
+ * Resolution : 1280 (H) x 1024 (V)
+ * Image control : Brightness, Contrast, Saturation, Sharpness, Glamour
+ * Effect : Mono, Negative, Sepia, Aqua, Sketch
+ * FPS : 15fps @full resolution, 30fps @VGA, 24fps @720p
+ * Max. pixel clock frequency : 48MHz(upto)
+ * Internal PLL (6MHz to 27MHz input frequency)
+ */
+
+static int s5ka3dfx_init(struct v4l2_subdev *sd, u32 val);
+
+/* Camera functional setting values configured by user concept */
+struct s5ka3dfx_userset {
+ int exposure_bias; /* V4L2_CID_EXPOSURE */
+ unsigned int ae_lock;
+ unsigned int awb_lock;
+ unsigned int auto_wb; /* V4L2_CID_AUTO_WHITE_BALANCE */
+ unsigned int manual_wb; /* V4L2_CID_WHITE_BALANCE_PRESET */
+ unsigned int wb_temp; /* V4L2_CID_WHITE_BALANCE_TEMPERATURE */
+ unsigned int effect; /* Color FX (AKA Color tone) */
+ unsigned int contrast; /* V4L2_CID_CONTRAST */
+ unsigned int saturation; /* V4L2_CID_SATURATION */
+ unsigned int sharpness; /* V4L2_CID_SHARPNESS */
+ unsigned int glamour;
+};
+
+struct s5ka3dfx_state {
+ struct s5ka3dfx_platform_data *pdata;
+ struct v4l2_subdev sd;
+ struct v4l2_pix_format pix;
+ struct v4l2_fract timeperframe;
+ struct s5ka3dfx_userset userset;
+ struct v4l2_streamparm strm;
+ int framesize_index;
+ int freq; /* MCLK in KHz */
+ int is_mipi;
+ int isize;
+ int ver;
+ int fps;
+ int vt_mode; /*For VT camera */
+ int check_dataline;
+ int check_previewdata;
+};
+
+enum {
+ S5KA3DFX_PREVIEW_QCIF,
+ S5KA3DFX_PREVIEW_QVGA,
+ S5KA3DFX_PREVIEW_VGA,
+};
+
+struct s5ka3dfx_enum_framesize {
+ unsigned int index;
+ unsigned int width;
+ unsigned int height;
+};
+
+struct s5ka3dfx_enum_framesize s5ka3dfx_framesize_list[] = {
+ { S5KA3DFX_PREVIEW_QCIF, 176, 144 },
+ { S5KA3DFX_PREVIEW_QVGA, 320, 240 },
+ { S5KA3DFX_PREVIEW_VGA, 640, 480 }
+};
+
+static inline struct s5ka3dfx_state *to_state(struct v4l2_subdev *sd)
+{
+ return container_of(sd, struct s5ka3dfx_state, sd);
+}
+
+struct s5ka3dfx_regset_table {
+ struct s5ka3dfx_reg *regset;
+ int array_size;
+};
+
+#define S5KA3DFX_REGSET_TABLE_ELEMENT(x, y) \
+ [(x)] = { \
+ .regset = (y), \
+ .array_size = ARRAY_SIZE((y)), \
+ }
+
+static struct s5ka3dfx_regset_table brightness_vt[] = {
+ S5KA3DFX_REGSET_TABLE_ELEMENT(EV_MINUS_4, s5ka3dfx_ev_vt_m4),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(EV_MINUS_3, s5ka3dfx_ev_vt_m3),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(EV_MINUS_2, s5ka3dfx_ev_vt_m2),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(EV_MINUS_1, s5ka3dfx_ev_vt_m1),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(EV_DEFAULT, s5ka3dfx_ev_vt_default),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(EV_PLUS_1, s5ka3dfx_ev_vt_p1),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(EV_PLUS_2, s5ka3dfx_ev_vt_p2),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(EV_PLUS_3, s5ka3dfx_ev_vt_p3),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(EV_PLUS_4, s5ka3dfx_ev_vt_p4),
+};
+
+static struct s5ka3dfx_regset_table brightness[] = {
+ S5KA3DFX_REGSET_TABLE_ELEMENT(EV_MINUS_4, s5ka3dfx_ev_m4),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(EV_MINUS_3, s5ka3dfx_ev_m3),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(EV_MINUS_2, s5ka3dfx_ev_m2),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(EV_MINUS_1, s5ka3dfx_ev_m1),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(EV_DEFAULT, s5ka3dfx_ev_default),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(EV_PLUS_1, s5ka3dfx_ev_p1),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(EV_PLUS_2, s5ka3dfx_ev_p2),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(EV_PLUS_3, s5ka3dfx_ev_p3),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(EV_PLUS_4, s5ka3dfx_ev_p4),
+};
+
+static struct s5ka3dfx_regset_table white_balance[] = {
+ S5KA3DFX_REGSET_TABLE_ELEMENT(WHITE_BALANCE_AUTO,
+ s5ka3dfx_wb_auto),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(WHITE_BALANCE_SUNNY,
+ s5ka3dfx_wb_sunny),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(WHITE_BALANCE_CLOUDY,
+ s5ka3dfx_wb_cloudy),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(WHITE_BALANCE_TUNGSTEN,
+ s5ka3dfx_wb_tungsten),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(WHITE_BALANCE_FLUORESCENT,
+ s5ka3dfx_wb_fluorescent),
+};
+
+static struct s5ka3dfx_regset_table effects[] = {
+ S5KA3DFX_REGSET_TABLE_ELEMENT(IMAGE_EFFECT_NONE,
+ s5ka3dfx_effect_none),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(IMAGE_EFFECT_BNW,
+ s5ka3dfx_effect_gray),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(IMAGE_EFFECT_SEPIA,
+ s5ka3dfx_effect_sepia),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(IMAGE_EFFECT_NEGATIVE,
+ s5ka3dfx_effect_negative),
+};
+
+static struct s5ka3dfx_regset_table fps_vt_table[] = {
+ S5KA3DFX_REGSET_TABLE_ELEMENT(0, s5ka3dfx_vt_fps_7),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(1, s5ka3dfx_vt_fps_10),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(2, s5ka3dfx_vt_fps_15),
+};
+
+static struct s5ka3dfx_regset_table fps_table[] = {
+ S5KA3DFX_REGSET_TABLE_ELEMENT(0, s5ka3dfx_fps_7),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(1, s5ka3dfx_fps_10),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(2, s5ka3dfx_fps_15),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(3, s5ka3dfx_fps_auto),
+};
+
+static struct s5ka3dfx_regset_table blur_vt[] = {
+ S5KA3DFX_REGSET_TABLE_ELEMENT(BLUR_LEVEL_0, s5ka3dfx_blur_vt_none),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(BLUR_LEVEL_1, s5ka3dfx_blur_vt_p1),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(BLUR_LEVEL_2, s5ka3dfx_blur_vt_p2),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(BLUR_LEVEL_3, s5ka3dfx_blur_vt_p3),
+};
+
+static struct s5ka3dfx_regset_table blur[] = {
+ S5KA3DFX_REGSET_TABLE_ELEMENT(BLUR_LEVEL_0, s5ka3dfx_blur_none),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(BLUR_LEVEL_1, s5ka3dfx_blur_p1),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(BLUR_LEVEL_2, s5ka3dfx_blur_p2),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(BLUR_LEVEL_3, s5ka3dfx_blur_p3),
+};
+
+static struct s5ka3dfx_regset_table dataline[] = {
+ S5KA3DFX_REGSET_TABLE_ELEMENT(0, s5ka3dfx_dataline),
+};
+
+static struct s5ka3dfx_regset_table dataline_stop[] = {
+ S5KA3DFX_REGSET_TABLE_ELEMENT(0, s5ka3dfx_dataline_stop),
+};
+
+static struct s5ka3dfx_regset_table init_reg[] = {
+ S5KA3DFX_REGSET_TABLE_ELEMENT(0, s5ka3dfx_init_reg),
+};
+
+static struct s5ka3dfx_regset_table init_vt_reg[] = {
+ S5KA3DFX_REGSET_TABLE_ELEMENT(0, s5ka3dfx_init_vt_reg),
+};
+
+static struct s5ka3dfx_regset_table frame_size[] = {
+ S5KA3DFX_REGSET_TABLE_ELEMENT(0, s5ka3dfx_QCIF),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(1, s5ka3dfx_QVGA),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(2, s5ka3dfx_Return_VGA),
+};
+static int s5ka3dfx_reset(struct v4l2_subdev *sd)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5ka3dfx_platform_data *pdata;
+
+ pdata = client->dev.platform_data;
+
+ if (pdata->cam_power) {
+ pdata->cam_power(0);
+ msleep(5);
+ pdata->cam_power(1);
+ msleep(5);
+ s5ka3dfx_init(sd, 0);
+ }
+
+ return 0;
+}
+
+static int s5ka3dfx_i2c_write_multi(struct i2c_client *client,
+ unsigned short addr, unsigned int w_data)
+{
+ int retry_count = 4;
+ unsigned char buf[2];
+ struct i2c_msg msg = { client->addr, 0, 2, buf };
+ int ret;
+
+ buf[0] = addr;
+ buf[1] = w_data;
+
+#ifdef VGA_CAM_DEBUG
+ int i;
+ for (i = 0; i < 2; i++) {
+ dev_err(&client->dev, "buf[%d] = %x ", i, buf[i]);
+ if (i == 1)
+ dev_err(&client->dev, "\n");
+ }
+#endif
+
+ do {
+ ret = i2c_transfer(client->adapter, &msg, 1);
+ if (likely(ret == 1))
+ break;
+ msleep(POLL_TIME_MS);
+ } while (retry_count--);
+
+ if (ret != 1)
+ dev_err(&client->dev, "I2C is not working.\n");
+
+ return (ret == 1) ? 0 : -EIO;
+}
+
+static int s5ka3dfx_write_regs(struct v4l2_subdev *sd,
+ struct s5ka3dfx_reg regs[], int size)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ int i, err;
+
+ for (i = 0; i < size; i++) {
+ err = s5ka3dfx_i2c_write_multi(client,
+ regs[i].addr, regs[i].val);
+ if (err < 0) {
+ v4l_info(client, "%s: register set failed\n", __func__);
+ break;
+ }
+ }
+ if (err < 0)
+ return -EIO;
+
+ return 0;
+}
+
+static int s5ka3dfx_write_regset_table(struct v4l2_subdev *sd,
+ const struct s5ka3dfx_regset_table *regset_table)
+{
+ int err;
+
+ if (regset_table->regset)
+ err = s5ka3dfx_write_regs(sd, regset_table->regset,
+ regset_table->array_size);
+ else
+ err = -EINVAL;
+
+ return err;
+}
+
+static int s5ka3dfx_set_from_table(struct v4l2_subdev *sd,
+ const char *setting_name,
+ const struct s5ka3dfx_regset_table *table,
+ int table_size, int index)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ dev_dbg(&client->dev, "%s: set %s index %d\n",
+ __func__, setting_name, index);
+
+ if ((index < 0) || (index >= table_size)) {
+ dev_err(&client->dev,
+ "%s: index(%d) out of range[0:%d] for table for %s\n",
+ __func__, index, table_size, setting_name);
+ return -EINVAL;
+ }
+ table += index;
+ if (table == NULL)
+ return -EINVAL;
+ return s5ka3dfx_write_regset_table(sd, table);
+}
+
+static int s5ka3dfx_set_parameter(struct v4l2_subdev *sd,
+ int *current_value_ptr,
+ int new_value,
+ const char *setting_name,
+ const struct s5ka3dfx_regset_table *table,
+ int table_size)
+{
+ int err;
+
+ if (*current_value_ptr == new_value)
+ return 0;
+
+ err = s5ka3dfx_set_from_table(sd, setting_name, table,
+ table_size, new_value);
+
+ if (!err)
+ *current_value_ptr = new_value;
+
+ return err;
+}
+static int s5ka3dfx_set_preview_start(struct v4l2_subdev *sd)
+{
+ int err;
+ struct s5ka3dfx_state *state =
+ container_of(sd, struct s5ka3dfx_state, sd);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ if (!state->pix.width || !state->pix.height)
+ return -EINVAL;
+
+ err = s5ka3dfx_set_from_table(sd, "frame_size", frame_size,
+ ARRAY_SIZE(frame_size), state->framesize_index);
+ if (err < 0) {
+ dev_err(&client->dev,
+ "%s: failed: Could not set preview size\n",
+ __func__);
+ return -EIO;
+ }
+
+ return 0;
+}
+static struct v4l2_queryctrl s5ka3dfx_controls[] = {
+ /* Add here if needed */
+};
+
+const char * const *s5ka3dfx_ctrl_get_menu(u32 id)
+{
+ pr_debug("%s is called... id : %d\n", __func__, id);
+
+ switch (id) {
+ default:
+ return v4l2_ctrl_get_menu(id);
+ }
+}
+
+static inline struct v4l2_queryctrl const *s5ka3dfx_find_qctrl(int id)
+{
+ int i;
+
+ pr_debug("%s is called... id : %d\n", __func__, id);
+
+ for (i = 0; i < ARRAY_SIZE(s5ka3dfx_controls); i++)
+ if (s5ka3dfx_controls[i].id == id)
+ return &s5ka3dfx_controls[i];
+
+ return NULL;
+}
+
+static int s5ka3dfx_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
+{
+ int i;
+
+ pr_debug("%s is called...\n", __func__);
+
+ for (i = 0; i < ARRAY_SIZE(s5ka3dfx_controls); i++) {
+ if (s5ka3dfx_controls[i].id == qc->id) {
+ memcpy(qc, &s5ka3dfx_controls[i],
+ sizeof(struct v4l2_queryctrl));
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int s5ka3dfx_querymenu(struct v4l2_subdev *sd, struct v4l2_querymenu *qm)
+{
+ struct v4l2_queryctrl qctrl;
+
+ pr_debug("%s is called...\n", __func__);
+
+ qctrl.id = qm->id;
+ s5ka3dfx_queryctrl(sd, &qctrl);
+
+ return v4l2_ctrl_query_menu(qm, &qctrl, s5ka3dfx_ctrl_get_menu(qm->id));
+}
+
+/*
+ * Clock configuration
+ * Configure expected MCLK from host and return EINVAL if not supported clock
+ * frequency is expected
+ * freq : in Hz
+ * flag : not supported for now
+ */
+static int s5ka3dfx_s_crystal_freq(struct v4l2_subdev *sd, u32 freq, u32 flags)
+{
+ int err = -EINVAL;
+
+ pr_debug("%s is called...\n", __func__);
+
+ return err;
+}
+
+static int s5ka3dfx_g_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
+{
+ int err = 0;
+
+ pr_debug("%s is called...\n", __func__);
+
+ return err;
+}
+
+static void s5ka3dfx_set_framesize(struct v4l2_subdev *sd,
+ const struct s5ka3dfx_enum_framesize *frmsize,
+ int frmsize_count)
+{
+ struct s5ka3dfx_state *state =
+ container_of(sd, struct s5ka3dfx_state, sd);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ const struct s5ka3dfx_enum_framesize *last_frmsize =
+ &frmsize[frmsize_count - 1];
+
+ dev_dbg(&client->dev, "%s: Requested Res: %dx%d\n", __func__,
+ state->pix.width, state->pix.height);
+
+ do {
+ if (frmsize->width == state->pix.width &&
+ frmsize->height == state->pix.height) {
+ break;
+ }
+
+ frmsize++;
+ } while (frmsize <= last_frmsize);
+
+ if (frmsize > last_frmsize)
+ frmsize = last_frmsize;
+
+ state->pix.width = frmsize->width;
+ state->pix.height = frmsize->height;
+ state->framesize_index = frmsize->index;
+
+ dev_dbg(&client->dev, "%s: Preview Res Set: %dx%d, index %d\n",
+ __func__, state->pix.width, state->pix.height,
+ state->framesize_index);
+}
+static int s5ka3dfx_s_mbus_fmt(struct v4l2_subdev *sd,
+ struct v4l2_mbus_framefmt *fmt)
+{
+ struct s5ka3dfx_state *state =
+ container_of(sd, struct s5ka3dfx_state, sd);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ int err = 0;
+
+ if (fmt->code == V4L2_MBUS_FMT_FIXED &&
+ fmt->colorspace != V4L2_COLORSPACE_JPEG) {
+ dev_dbg(&client->dev,
+ "%s: mismatch in pixelformat and colorspace\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ state->pix.width = fmt->width;
+ state->pix.height = fmt->height;
+ if (fmt->colorspace == V4L2_COLORSPACE_JPEG)
+ state->pix.pixelformat = V4L2_PIX_FMT_JPEG;
+ else
+ state->pix.pixelformat = 0; /* is this used anywhere? */
+
+ s5ka3dfx_set_framesize(sd, s5ka3dfx_framesize_list,
+ ARRAY_SIZE(s5ka3dfx_framesize_list));
+
+ return err;
+}
+
+static int s5ka3dfx_enum_framesizes(struct v4l2_subdev *sd,
+ struct v4l2_frmsizeenum *fsize)
+{
+ struct s5ka3dfx_state *state =
+ container_of(sd, struct s5ka3dfx_state, sd);
+ int num_entries = sizeof(s5ka3dfx_framesize_list) /
+ sizeof(struct s5ka3dfx_enum_framesize);
+ struct s5ka3dfx_enum_framesize *elem;
+ int index = 0;
+ int i = 0;
+
+ pr_debug("%s is called...\n", __func__);
+
+ /* The camera interface should read this value, this is the resolution
+ * at which the sensor would provide framedata to the camera i/f
+ *
+ * In case of image capture,
+ * this returns the default camera resolution (WVGA)
+ */
+ fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+
+ index = state->framesize_index;
+
+ for (i = 0; i < num_entries; i++) {
+ elem = &s5ka3dfx_framesize_list[i];
+ if (elem->index == index) {
+ fsize->discrete.width =
+ s5ka3dfx_framesize_list[index].width;
+ fsize->discrete.height =
+ s5ka3dfx_framesize_list[index].height;
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int s5ka3dfx_enum_frameintervals(struct v4l2_subdev *sd,
+ struct v4l2_frmivalenum *fival)
+{
+ int err = 0;
+
+ pr_debug("%s is called...\n", __func__);
+
+ return err;
+}
+
+static int s5ka3dfx_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
+ enum v4l2_mbus_pixelcode *code)
+{
+ int err = 0;
+
+ pr_debug("%s is called...\n", __func__);
+
+ return err;
+}
+
+static int s5ka3dfx_try_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
+{
+ int err = 0;
+
+ pr_debug("%s is called...\n", __func__);
+
+ return err;
+}
+
+static int s5ka3dfx_g_parm(struct v4l2_subdev *sd,
+ struct v4l2_streamparm *param)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ int err = 0;
+
+ dev_dbg(&client->dev, "%s\n", __func__);
+
+ return err;
+}
+
+static int s5ka3dfx_s_parm(struct v4l2_subdev *sd,
+ struct v4l2_streamparm *param)
+{
+ int err = 0;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5ka3dfx_state *state =
+ container_of(sd, struct s5ka3dfx_state, sd);
+ struct sec_cam_parm *new_parms =
+ (struct sec_cam_parm *)&param->parm.raw_data;
+ struct sec_cam_parm *parms =
+ (struct sec_cam_parm *)&state->strm.parm.raw_data;
+
+ dev_dbg(&client->dev, "%s: start\n", __func__);
+
+ /* we return an error if one happened but don't stop trying to
+ * set all parameters passed
+ */
+
+ err = s5ka3dfx_set_parameter(sd, &parms->brightness,
+ new_parms->brightness, "brightness",
+ brightness, ARRAY_SIZE(brightness));
+ err |= s5ka3dfx_set_parameter(sd, &parms->effects, new_parms->effects,
+ "effects", effects,
+ ARRAY_SIZE(effects));
+ err |= s5ka3dfx_set_parameter(sd, &parms->white_balance,
+ new_parms->white_balance,
+ "white_balance", white_balance,
+ ARRAY_SIZE(white_balance));
+
+ dev_dbg(&client->dev, "%s: returning %d\n", __func__, err);
+
+ return err;
+}
+
+/* set sensor register values for adjusting brightness */
+static int s5ka3dfx_set_brightness(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5ka3dfx_state *state =
+ container_of(sd, struct s5ka3dfx_state, sd);
+ struct s5ka3dfx_regset_table *ev;
+ int err = -EINVAL;
+ int ev_index;
+ int array_size;
+
+ dev_dbg(&client->dev, "%s: value : %d state->vt_mode %d\n",
+ __func__, ctrl->value, state->vt_mode);
+
+ pr_debug("state->vt_mode : %d\n", state->vt_mode);
+
+ if ((ctrl->value < 0) || (ctrl->value >= EV_MAX))
+ ev_index = EV_DEFAULT;
+ else
+ ev_index = ctrl->value;
+
+ if (state->vt_mode == 1) {
+ ev = brightness_vt;
+ array_size = ARRAY_SIZE(brightness_vt);
+ } else {
+ ev = brightness;
+ array_size = ARRAY_SIZE(brightness);
+ }
+
+ if (ev_index >= array_size)
+ ev_index = EV_DEFAULT;
+
+ ev += ev_index;
+
+ err = s5ka3dfx_write_regset_table(sd, ev);
+
+ if (err)
+ dev_dbg(&client->dev, "%s: register set failed\n", __func__);
+
+ return err;
+}
+
+/*
+ * set sensor register values for
+ * adjusting whitebalance, both auto and manual
+ */
+static int s5ka3dfx_set_wb(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5ka3dfx_regset_table *wb = white_balance;
+ int err = -EINVAL;
+
+ dev_dbg(&client->dev, "%s: value : %d\n", __func__, ctrl->value);
+
+ if ((ctrl->value < WHITE_BALANCE_BASE) ||
+ (ctrl->value > WHITE_BALANCE_MAX) ||
+ (ctrl->value >= ARRAY_SIZE(white_balance))) {
+ dev_dbg(&client->dev, "%s: Value(%d) out of range([%d:%d])\n",
+ __func__, ctrl->value,
+ WHITE_BALANCE_BASE, WHITE_BALANCE_MAX);
+ dev_dbg(&client->dev, "%s: Value out of range\n", __func__);
+ goto out;
+ }
+
+ wb += ctrl->value;
+
+ err = s5ka3dfx_write_regset_table(sd, wb);
+
+ if (err)
+ dev_dbg(&client->dev, "%s: register set failed\n", __func__);
+out:
+ return err;
+}
+
+/* set sensor register values for adjusting color effect */
+static int s5ka3dfx_set_effect(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5ka3dfx_regset_table *effect = effects;
+ int err = -EINVAL;
+
+ dev_dbg(&client->dev, "%s: value : %d\n", __func__, ctrl->value);
+
+ if ((ctrl->value < IMAGE_EFFECT_BASE) ||
+ (ctrl->value > IMAGE_EFFECT_MAX) ||
+ (ctrl->value >= ARRAY_SIZE(effects))) {
+ dev_dbg(&client->dev, "%s: Value(%d) out of range([%d:%d])\n",
+ __func__, ctrl->value,
+ IMAGE_EFFECT_BASE, IMAGE_EFFECT_MAX);
+ goto out;
+ }
+
+ effect += ctrl->value;
+
+ err = s5ka3dfx_write_regset_table(sd, effect);
+
+ if (err)
+ dev_dbg(&client->dev, "%s: register set failed\n", __func__);
+out:
+ return err;
+}
+
+/* set sensor register values for frame rate(fps) setting */
+static int s5ka3dfx_set_frame_rate(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5ka3dfx_state *state =
+ container_of(sd, struct s5ka3dfx_state, sd);
+ struct s5ka3dfx_regset_table *fps;
+
+ int err = -EINVAL;
+ int fps_index;
+
+ dev_dbg(&client->dev, "%s: value : %d\n", __func__, ctrl->value);
+
+ pr_debug("state->vt_mode : %d\n", state->vt_mode);
+
+ switch (ctrl->value) {
+ case 0:
+ fps_index = 3;
+ break;
+
+ case 7:
+ fps_index = 0;
+ break;
+
+ case 10:
+ fps_index = 1;
+ break;
+
+ case 15:
+ fps_index = 2;
+ break;
+
+ default:
+ dev_dbg(&client->dev, "%s: Value(%d) is not supported\n",
+ __func__, ctrl->value);
+ goto out;
+ }
+
+ if (state->vt_mode == 1)
+ fps = fps_vt_table;
+ else
+ fps = fps_table;
+
+ fps += fps_index;
+ state->fps = fps_index;
+
+ err = s5ka3dfx_write_regset_table(sd, fps);
+out:
+ return err;
+}
+
+/* set sensor register values for adjusting blur effect */
+static int s5ka3dfx_set_blur(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5ka3dfx_state *state =
+ container_of(sd, struct s5ka3dfx_state, sd);
+ struct s5ka3dfx_regset_table *bl;
+ int err = -EINVAL;
+ int array_size;
+
+ dev_dbg(&client->dev, "%s: value : %d\n", __func__, ctrl->value);
+
+ pr_debug("state->vt_mode : %d\n", state->vt_mode);
+
+ if ((ctrl->value < BLUR_LEVEL_0) || (ctrl->value > BLUR_LEVEL_MAX)) {
+ dev_dbg(&client->dev, "%s: Value(%d) out of range([%d:%d])\n",
+ __func__, ctrl->value,
+ BLUR_LEVEL_0, BLUR_LEVEL_MAX);
+ goto out;
+ }
+
+ if (state->vt_mode == 1) {
+ bl = blur_vt;
+ array_size = ARRAY_SIZE(blur_vt);
+ } else {
+ bl = blur;
+ array_size = ARRAY_SIZE(blur);
+ }
+
+ if (ctrl->value >= array_size) {
+ dev_dbg(&client->dev, "%s: Value(%d) out of range([%d:%d))\n",
+ __func__, ctrl->value,
+ BLUR_LEVEL_0, array_size);
+ goto out;
+ }
+
+ bl += ctrl->value;
+
+ err = s5ka3dfx_write_regset_table(sd, bl);
+out:
+ return err;
+}
+
+static int s5ka3dfx_check_dataline_stop(struct v4l2_subdev *sd)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5ka3dfx_state *state =
+ container_of(sd, struct s5ka3dfx_state, sd);
+ int err = -EINVAL;
+
+ dev_dbg(&client->dev, "%s\n", __func__);
+
+ err = s5ka3dfx_write_regset_table(sd, dataline_stop);
+ if (err < 0) {
+ v4l_info(client, "%s: register set failed\n", __func__);
+ return -EIO;
+ }
+
+ state->check_dataline = 0;
+ err = s5ka3dfx_reset(sd);
+ if (err < 0) {
+ v4l_info(client, "%s: register set failed\n", __func__);
+ return -EIO;
+ }
+ return err;
+}
+
+/* returns the real iso currently used by sensor due to lighting
+ * conditions, not the requested iso we sent using s_ctrl.
+ */
+static int s5ka3dfx_get_iso(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ s32 read_value;
+ int gain;
+
+ err = s5ka3dfx_i2c_write_multi(client, 0xEF, 0x02);
+ if (err < 0)
+ return err;
+
+ read_value = i2c_smbus_read_byte_data(client, 0x1D);
+ if (read_value < 0)
+ return read_value;
+
+ read_value &= 0x7F;
+ gain = (128 * 100) / (128 - read_value);
+
+ if (gain > 280)
+ ctrl->value = ISO_400;
+ else if (gain > 230)
+ ctrl->value = ISO_200;
+ else if (gain > 190)
+ ctrl->value = ISO_100;
+ else if (gain > 100)
+ ctrl->value = ISO_50;
+ else
+ ctrl->value = gain;
+
+ dev_dbg(&client->dev, "%s: get iso == %d (0x%x)\n",
+ __func__, ctrl->value, read_value);
+
+ return err;
+}
+
+static int s5ka3dfx_get_shutterspeed(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5ka3dfx_state *state = to_state(sd);
+ s32 read_value;
+ int cintr;
+ int err;
+
+ err = s5ka3dfx_i2c_write_multi(client, 0xEF, 0x02);
+ if (err < 0)
+ return err;
+
+ read_value = i2c_smbus_read_byte_data(client, 0x0E);
+ if (read_value < 0)
+ return read_value;
+ cintr = (read_value & 0x1F) << 8;
+
+ read_value = i2c_smbus_read_byte_data(client, 0x0F);
+ if (read_value < 0)
+ return read_value;
+ cintr |= read_value & 0xFF;
+
+ /* A3D Shutter Speed (Micro Sec.) =
+ (2 * (cintr - 1) * 814) / MCLK * 1000 */
+ ctrl->value = ((cintr - 1) * 1628) / (state->freq / 1000) * 1000;
+
+ dev_dbg(&client->dev,
+ "%s: get shutterspeed == %d\n", __func__, ctrl->value);
+
+ return err;
+}
+
+static int s5ka3dfx_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5ka3dfx_state *state =
+ container_of(sd, struct s5ka3dfx_state, sd);
+ struct s5ka3dfx_userset userset = state->userset;
+ int err = 0;
+
+ dev_dbg(&client->dev, "%s: id : 0x%08x\n", __func__, ctrl->id);
+
+ switch (ctrl->id) {
+ case V4L2_CID_EXPOSURE:
+ ctrl->value = userset.exposure_bias;
+ break;
+
+ case V4L2_CID_AUTO_WHITE_BALANCE:
+ ctrl->value = userset.auto_wb;
+ break;
+
+ case V4L2_CID_WHITE_BALANCE_PRESET:
+ ctrl->value = userset.manual_wb;
+ break;
+
+ case V4L2_CID_COLORFX:
+ ctrl->value = userset.effect;
+ break;
+
+ case V4L2_CID_CONTRAST:
+ ctrl->value = userset.contrast;
+ break;
+
+ case V4L2_CID_SATURATION:
+ ctrl->value = userset.saturation;
+ break;
+
+ case V4L2_CID_SHARPNESS:
+ ctrl->value = userset.saturation;
+ break;
+
+ case V4L2_CID_CAMERA_GET_ISO:
+ err = s5ka3dfx_get_iso(sd, ctrl);
+ break;
+
+ case V4L2_CID_CAMERA_GET_SHT_TIME:
+ err = s5ka3dfx_get_shutterspeed(sd, ctrl);
+ break;
+
+ case V4L2_CID_ESD_INT:
+ ctrl->value = 0;
+ break;
+
+ default:
+ dev_dbg(&client->dev, "%s: no such ctrl\n", __func__);
+ err = -EINVAL;
+ break;
+ }
+
+ return err;
+}
+
+static int s5ka3dfx_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5ka3dfx_state *state =
+ container_of(sd, struct s5ka3dfx_state, sd);
+
+ int err = -EINVAL;
+
+ pr_debug("%s : ctrl->id 0x%08x, ctrl->value %d\n", __func__,
+ ctrl->id, ctrl->value);
+
+ switch (ctrl->id) {
+
+ case V4L2_CID_CAMERA_BRIGHTNESS:
+ dev_dbg(&client->dev, "%s: "
+ "V4L2_CID_CAMERA_BRIGHTNESS\n", __func__);
+ err = s5ka3dfx_set_brightness(sd, ctrl);
+ break;
+
+ case V4L2_CID_CAMERA_WHITE_BALANCE:
+ dev_dbg(&client->dev, "%s: "
+ "V4L2_CID_AUTO_WHITE_BALANCE\n", __func__);
+ err = s5ka3dfx_set_wb(sd, ctrl);
+ break;
+
+ case V4L2_CID_CAMERA_EFFECT:
+ dev_dbg(&client->dev, "%s: "
+ "V4L2_CID_CAMERA_EFFECT\n", __func__);
+ err = s5ka3dfx_set_effect(sd, ctrl);
+ break;
+
+ case V4L2_CID_CAMERA_FRAME_RATE:
+ dev_dbg(&client->dev, "%s: "
+ "V4L2_CID_CAMERA_FRAME_RATE\n", __func__);
+ err = s5ka3dfx_set_frame_rate(sd, ctrl);
+ break;
+
+ case V4L2_CID_CAMERA_VGA_BLUR:
+ dev_dbg(&client->dev, "%s: "
+ "V4L2_CID_CAMERA_VGA_BLUR\n", __func__);
+ err = s5ka3dfx_set_blur(sd, ctrl);
+ break;
+
+ case V4L2_CID_CAMERA_VT_MODE:
+ state->vt_mode = ctrl->value;
+ dev_dbg(&client->dev, "%s: V4L2_CID_CAMERA_VT_MODE : "
+ "state->vt_mode %d\n",
+ __func__, state->vt_mode);
+ err = 0;
+ break;
+
+ case V4L2_CID_CAMERA_CHECK_DATALINE:
+ state->check_dataline = ctrl->value;
+ err = 0;
+ break;
+
+ case V4L2_CID_CAMERA_CHECK_DATALINE_STOP:
+ err = s5ka3dfx_check_dataline_stop(sd);
+ break;
+
+ case V4L2_CID_CAM_PREVIEW_ONOFF:
+ if (state->check_previewdata == 0)
+ err = s5ka3dfx_set_preview_start(sd);
+ else
+ err = -EIO;
+ break;
+
+ case V4L2_CID_CAMERA_RESET:
+ dev_dbg(&client->dev, "%s: V4L2_CID_CAMERA_RESET\n", __func__);
+ err = s5ka3dfx_reset(sd);
+ break;
+
+ default:
+ dev_dbg(&client->dev, "%s: no support control "
+ "in camera sensor, S5KA3DFX\n", __func__);
+ err = 0;
+ break;
+ }
+
+ if (err < 0)
+ goto out;
+ else
+ return 0;
+
+ out:
+ dev_dbg(&client->dev, "%s: vidioc_s_ctrl failed\n", __func__);
+ return err;
+}
+
+static void s5ka3dfx_init_parameters(struct v4l2_subdev *sd)
+{
+ struct s5ka3dfx_state *state =
+ container_of(sd, struct s5ka3dfx_state, sd);
+ struct sec_cam_parm *parms =
+ (struct sec_cam_parm *)&state->strm.parm.raw_data;
+
+ parms->effects = IMAGE_EFFECT_NONE;
+ parms->brightness = EV_DEFAULT;
+ parms->white_balance = WHITE_BALANCE_AUTO;
+
+}
+
+static int s5ka3dfx_init(struct v4l2_subdev *sd, u32 val)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5ka3dfx_state *state =
+ container_of(sd, struct s5ka3dfx_state, sd);
+ int err = -EINVAL;
+
+ pr_debug("camera initialization start, state->vt_mode : %d\n",
+ state->vt_mode);
+ pr_debug("state->check_dataline : %d\n", state->check_dataline);
+
+ s5ka3dfx_init_parameters(sd);
+ if (state->vt_mode == 0) {
+ if (state->check_dataline)
+ err = s5ka3dfx_write_regset_table(sd, dataline);
+ else
+ err = s5ka3dfx_write_regset_table(sd, init_reg);
+ } else
+ err = s5ka3dfx_write_regset_table(sd, init_vt_reg);
+
+ if (err < 0) {
+ /* This is preview fail */
+ state->check_previewdata = 100;
+ v4l_err(client,
+ "%s: camera initialization failed. err(%d)\n",
+ __func__, state->check_previewdata);
+ return -EIO;
+ }
+
+ /* This is preview success */
+ state->check_previewdata = 0;
+ return 0;
+}
+
+static const struct v4l2_subdev_core_ops s5ka3dfx_core_ops = {
+ .init = s5ka3dfx_init, /* initializing API */
+ .queryctrl = s5ka3dfx_queryctrl,
+ .querymenu = s5ka3dfx_querymenu,
+ .g_ctrl = s5ka3dfx_g_ctrl,
+ .s_ctrl = s5ka3dfx_s_ctrl,
+};
+
+static const struct v4l2_subdev_video_ops s5ka3dfx_video_ops = {
+ .s_crystal_freq = s5ka3dfx_s_crystal_freq,
+ .g_mbus_fmt = s5ka3dfx_g_mbus_fmt,
+ .s_mbus_fmt = s5ka3dfx_s_mbus_fmt,
+ .enum_framesizes = s5ka3dfx_enum_framesizes,
+ .enum_frameintervals = s5ka3dfx_enum_frameintervals,
+ .enum_mbus_fmt = s5ka3dfx_enum_mbus_fmt,
+ .try_mbus_fmt = s5ka3dfx_try_mbus_fmt,
+ .g_parm = s5ka3dfx_g_parm,
+ .s_parm = s5ka3dfx_s_parm,
+};
+
+static const struct v4l2_subdev_ops s5ka3dfx_ops = {
+ .core = &s5ka3dfx_core_ops,
+ .video = &s5ka3dfx_video_ops,
+};
+
+/*
+ * s5ka3dfx_probe
+ * Fetching platform data is being done with s_config subdev call.
+ * In probe routine, we just register subdev device
+ */
+static int s5ka3dfx_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct s5ka3dfx_state *state;
+ struct v4l2_subdev *sd;
+ struct s5ka3dfx_platform_data *pdata = client->dev.platform_data;
+
+ state = kzalloc(sizeof(struct s5ka3dfx_state), GFP_KERNEL);
+ if (state == NULL)
+ return -ENOMEM;
+
+ sd = &state->sd;
+ strcpy(sd->name, S5KA3DFX_DRIVER_NAME);
+
+ /*
+ * Assign default format and resolution
+ * Use configured default information in platform data
+ * or without them, use default information in driver
+ */
+ if (!(pdata->default_width && pdata->default_height)) {
+ /* TODO: assign driver default resolution */
+ } else {
+ state->pix.width = pdata->default_width;
+ state->pix.height = pdata->default_height;
+ }
+
+ if (!pdata->pixelformat)
+ state->pix.pixelformat = DEFAULT_FMT;
+ else
+ state->pix.pixelformat = pdata->pixelformat;
+
+ if (pdata->freq == 0)
+ state->freq = DEFUALT_MCLK;
+ else
+ state->freq = pdata->freq;
+
+ if (!pdata->is_mipi) {
+ state->is_mipi = 0;
+ dev_dbg(&client->dev, "parallel mode\n");
+ } else
+ state->is_mipi = pdata->is_mipi;
+
+ /* Registering subdev */
+ v4l2_i2c_subdev_init(sd, client, &s5ka3dfx_ops);
+
+ dev_dbg(&client->dev, "s5ka3dfx has been probed\n");
+ return 0;
+}
+
+static int s5ka3dfx_remove(struct i2c_client *client)
+{
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct s5ka3dfx_state *state =
+ container_of(sd, struct s5ka3dfx_state, sd);
+
+ v4l2_device_unregister_subdev(sd);
+ kfree(state);
+ return 0;
+}
+
+static const struct i2c_device_id s5ka3dfx_id[] = {
+ { S5KA3DFX_DRIVER_NAME, 0 },
+ { },
+};
+
+MODULE_DEVICE_TABLE(i2c, s5ka3dfx_id);
+
+static struct i2c_driver v4l2_i2c_driver = {
+ .driver.name = S5KA3DFX_DRIVER_NAME,
+ .probe = s5ka3dfx_probe,
+ .remove = s5ka3dfx_remove,
+ .id_table = s5ka3dfx_id,
+};
+
+static int __init v4l2_i2c_drv_init(void)
+{
+ return i2c_add_driver(&v4l2_i2c_driver);
+}
+
+static void __exit v4l2_i2c_drv_cleanup(void)
+{
+ i2c_del_driver(&v4l2_i2c_driver);
+}
+
+module_init(v4l2_i2c_drv_init);
+module_exit(v4l2_i2c_drv_cleanup);
+
+MODULE_DESCRIPTION("Samsung Electronics S5KA3DFX UXGA camera driver");
+MODULE_AUTHOR("Jinsung Yang <jsgood.yang@samsung.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/s5ka3dfx.h b/drivers/media/video/s5ka3dfx.h
new file mode 100755
index 0000000..7bf2a8e
--- /dev/null
+++ b/drivers/media/video/s5ka3dfx.h
@@ -0,0 +1,1691 @@
+/*
+ * Driver for S5KA3DFX (VGA camera) from Samsung Electronics
+ *
+ * 1/4" 2.0Mp CMOS Image Sensor SoC with an Embedded Image Processor
+ *
+ * Copyright (C) 2009, Jinsung Yang <jsgood.yang@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.
+ */
+#ifndef __S5KA3DFX_H__
+#define __S5KA3DFX_H__
+
+struct s5ka3dfx_reg {
+ unsigned char addr;
+ unsigned char val;
+};
+
+struct s5ka3dfx_regset_type {
+ unsigned char *regset;
+ int len;
+};
+
+/*
+ * Macro
+ */
+#define REGSET_LENGTH(x) (sizeof(x) / sizeof(s5ka3dfx_reg))
+
+/*
+ * User defined commands
+ */
+/* S/W defined features for tune */
+#define REG_DELAY 0xFF00 /* in ms */
+#define REG_CMD 0xFFFF /* Followed by command */
+
+/* Following order should not be changed */
+enum image_size_s5ka3dfx {
+ SVGA, /* 800*600 */
+};
+
+/*
+ * Following values describe controls of camera
+ * in user aspect and must be match with index of s5ka3dfx_regset[]
+ * These values indicates each controls and should be used
+ * to control each control
+ */
+enum s5ka3dfx_control {
+ S5KA3DFX_INIT,
+ S5KA3DFX_EV,
+ S5KA3DFX_AWB,
+ S5KA3DFX_MWB,
+ S5KA3DFX_EFFECT,
+ S5KA3DFX_CONTRAST,
+ S5KA3DFX_SATURATION,
+ S5KA3DFX_SHARPNESS,
+};
+
+#define S5KA3DFX_REGSET(x) { \
+ .regset = (x), \
+ .len = sizeof((x))/sizeof(s5ka3dfx_reg),}
+
+/*
+ * VGA Self shot init setting
+ */
+struct s5ka3dfx_reg s5ka3dfx_init_reg[] = {
+ { 0xef, 0x02 },
+ { 0x13, 0xa0 },
+ { 0x23, 0x53 },
+ { 0x26, 0x24 },
+ { 0x2c, 0x05 },
+ { 0x05, 0x00 },
+ { 0x03, 0x58 },
+ { 0x24, 0x0a },
+ { 0x0b, 0x84 },
+ { 0x1e, 0xb7 },
+ { 0x56, 0x05 },
+ { 0x28, 0x96 },
+ { 0x67, 0x3c },
+
+ { 0xef, 0x03 },
+ { 0x50, 0xd2 },
+ { 0x0f, 0x31 },
+ { 0xef, 0x03 },
+ { 0x70, 0x00 }, /*un-mirrored*/
+ { 0x5F, 0x03 },
+ { 0x60, 0x02 },
+ { 0x61, 0x0F },
+ { 0x62, 0x0C },
+ { 0x63, 0x01 },
+ { 0x64, 0xE7 },
+ { 0x65, 0x01 },
+ { 0x66, 0xE7 },
+
+ { 0x6d, 0x56 },
+ { 0x6e, 0xC0 },
+ { 0x6f, 0xC0 },
+
+ { 0x4c, 0x00 },
+ { 0x4d, 0x9e },
+
+ { 0xef, 0x03 },
+ { 0x00, 0x07 },
+ { 0x01, 0x80 },
+ { 0x02, 0x7f },
+ { 0x2b, 0x41 },
+ { 0x31, 0x00 },
+ { 0x32, 0x09 },
+
+ { 0x33, 0x80 },
+ { 0x34, 0x79 },
+
+ { 0x36, 0x3A }, /*39, 3a, N.L. ST */
+ { 0x37, 0x38 },
+
+ { 0x6a, 0x00 },
+ { 0x7b, 0x05 },
+ { 0x38, 0x05 },
+ { 0x39, 0x03 },
+
+ { 0x2d, 0x08 },
+ { 0x2e, 0x20 },
+ { 0x2f, 0x30 },
+ { 0x30, 0xff },
+ { 0x7c, 0x06 },
+ { 0x7d, 0x20 },
+ { 0x7e, 0x0c },
+ { 0x7f, 0x20 },
+
+ { 0x28, 0x02 },
+ { 0x29, 0x9f },
+ { 0x2a, 0x00 },
+
+ { 0x13, 0x00 },
+ { 0x14, 0xa0 },
+
+ { 0x1a, 0x5d },
+ { 0x1b, 0x58 },
+ { 0x1c, 0x60 },
+ { 0x1d, 0x4f },
+
+ { 0x1e, 0x68 },
+ { 0x1f, 0x42 }, /*44, Indoor Rgain Min */
+ { 0x20, 0x7A }, /*75 82, 8a, Indoor Bgain Max */
+ { 0x21, 0x4D }, /* 4Indoor Bgain Min */
+
+ { 0x3a, 0x13 },
+ { 0x3b, 0x3c },
+ { 0x3c, 0x00 },
+ { 0x3d, 0x18 },
+
+ { 0x23, 0x80 },
+
+ { 0x15, 0x0b },
+ { 0x16, 0xd2 },
+ { 0x17, 0x64 },
+ { 0x18, 0x78 },
+
+ { 0xef, 0x00 },
+ { 0xde, 0x00 },
+ { 0xdf, 0x1f },
+ { 0xe0, 0x00 },
+ { 0xe1, 0x37 },
+ { 0xe2, 0x08 },
+ { 0xe3, 0x42 },
+ { 0xe4, 0x00 },
+ { 0xe5, 0x12 },
+ { 0xe6, 0x9e },
+ { 0xe9, 0x00 },
+ { 0xe7, 0x01 },
+ { 0xe8, 0x13 },
+ { 0xe9, 0x01 },
+ { 0xe7, 0x01 },
+ { 0xe8, 0x06 },
+ { 0xe9, 0x02 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0xef },
+ { 0xe9, 0x03 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0xe0 },
+ { 0xe9, 0x04 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0xc3 },
+ { 0xe9, 0x05 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0xab },
+ { 0xe9, 0x06 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x91 },
+ { 0xe9, 0x07 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0xbd },
+ { 0xe9, 0x08 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0xab },
+ { 0xe9, 0x09 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x9a },
+ { 0xe9, 0x0a },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x8f },
+ { 0xe9, 0x0b },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x78 },
+ { 0xe9, 0x0c },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x69 },
+ { 0xe9, 0x0d },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x55 },
+ { 0xe9, 0x0e },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x4c },
+ { 0xe9, 0x0f },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x4d },
+ { 0xe9, 0x10 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x43 },
+ { 0xe9, 0x11 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x39 },
+ { 0xe9, 0x12 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x26 },
+ { 0xe9, 0x13 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x1e },
+ { 0xe9, 0x14 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x0d },
+ { 0xe9, 0x15 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0xd8 },
+ { 0xe9, 0x16 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0xd8 },
+ { 0xe9, 0x17 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0xe1 },
+ { 0xe9, 0x18 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0xdc },
+ { 0xe9, 0x19 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0xd3 },
+ { 0xe9, 0x1a },
+ { 0xe7, 0x07 },
+ { 0xe8, 0xcb },
+ { 0xe9, 0x1b },
+ { 0xe7, 0x07 },
+ { 0xe8, 0xbe },
+ { 0xe9, 0x1c },
+ { 0xe7, 0x07 },
+ { 0xe8, 0x62 },
+ { 0xe9, 0x1d },
+ { 0xe7, 0x07 },
+ { 0xe8, 0x66 },
+ { 0xe9, 0x1e },
+ { 0xe7, 0x07 },
+ { 0xe8, 0x71 },
+ { 0xe9, 0x1f },
+ { 0xe7, 0x07 },
+ { 0xe8, 0x80 },
+ { 0xe9, 0x20 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0x75 },
+ { 0xe9, 0x21 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0x67 },
+ { 0xe9, 0x22 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0x85 },
+ { 0xe9, 0x40 },
+
+
+ { 0xd1, 0x08 },
+ { 0xdd, 0x03 },
+
+ { 0x23, 0x17 },
+ { 0x24, 0x17 },
+ { 0x25, 0x17 },
+ { 0x27, 0x18 },
+ { 0x29, 0x60 },
+ { 0x2a, 0x22 },
+
+ { 0x2f, 0x01 },
+
+ { 0x36, 0x01 },
+ { 0x37, 0xc2 },
+ { 0x38, 0xa8 },
+ { 0x39, 0x98 },
+ { 0x3a, 0x00 },
+ { 0x3b, 0xf0 },
+ { 0x3c, 0x01 },
+ { 0x3d, 0x5e },
+ { 0xb9, 0x02 },
+ { 0xbb, 0xb0 },
+ { 0xbc, 0x18 },
+ { 0xbd, 0x30 },
+ { 0xbf, 0x38 },
+ { 0xc1, 0x88 },
+ { 0xc8, 0x11 },
+ { 0xeb, 0x81 },
+ { 0xed, 0x05 },
+ { 0xb1, 0x00 },
+ { 0xb2, 0x62 },
+ { 0xb3, 0x00 },
+ { 0xb4, 0x00 },
+ { 0xb5, 0x01 },
+ { 0xb6, 0xa3 },
+ { 0xb7, 0x02 },
+ { 0xb8, 0x80 },
+ { 0x77, 0x00 },
+ { 0x78, 0x00 },
+ { 0xef, 0x00 },
+ { 0x93, 0x40 },
+ { 0x94, 0x80 },
+ { 0x95, 0xc0 },
+ { 0x96, 0xc0 },
+ { 0x97, 0x20 },
+ { 0x98, 0x20 },
+ { 0x99, 0x30 },
+ { 0xA0, 0x00 },
+ { 0xA1, 0x00 },
+ { 0xA2, 0x1c },
+ { 0xA3, 0x16 },
+ { 0xA4, 0x03 },
+ { 0xA5, 0x07 },
+ { 0xA6, 0x00 },
+ { 0xef, 0x00 },
+ { 0xad, 0xd0 },
+ { 0xaf, 0x10 },
+ { 0xef, 0x00 },
+ { 0x42, 0x65 },
+ { 0x44, 0x61 },
+
+ { 0x57, 0x00 },
+
+ { 0xef, 0x03 },
+ { 0x01, 0x3C },
+ { 0x02, 0x05 },
+ { 0x03, 0x21 },
+ { 0x04, 0x60 },
+ { 0x06, 0x1c },
+ { 0x07, 0x01 },
+ { 0x08, 0x01 },
+ { 0x0b, 0x01 },
+ { 0x51, 0x10 },
+ { 0x52, 0x00 },
+ { 0x53, 0x00 },
+ { 0x54, 0x00 },
+ { 0x55, 0x22 },
+ { 0x56, 0x01 },
+ { 0x57, 0x61 },
+ { 0x58, 0x25 },
+ { 0x67, 0xcf },
+ { 0x69, 0x17 },
+ { 0xef, 0x00 },
+ { 0x58, 0x00 },
+ { 0x59, 0x00 },
+ { 0x5a, 0x02 },
+ { 0x5b, 0x73 },
+ { 0x5c, 0x00 },
+ { 0x5d, 0x00 },
+ { 0x5e, 0x01 },
+ { 0x5f, 0xe0 },
+ { 0x60, 0x00 },
+ { 0x61, 0xEA },
+ { 0x62, 0x01 },
+ { 0x63, 0x80 },
+ { 0x64, 0x00 },
+ { 0x65, 0xAF },
+ { 0x66, 0x01 },
+ { 0x67, 0x2D },
+ { 0xef, 0x00 },
+ { 0x6a, 0x01 },
+ { 0x6b, 0xe0 },
+ { 0x6c, 0x05 },
+ { 0x6d, 0x00 },
+ { 0x6e, 0x0e },
+ { 0x6f, 0x00 },
+ { 0x70, 0x10 },
+ { 0xef, 0x03 },
+ { 0x22, 0x24 },
+ { 0x3e, 0x23 },
+ { 0x3f, 0x23 },
+ { 0x40, 0x00 },
+ { 0x41, 0x09 },
+ { 0x4a, 0x09 },
+ { 0x4b, 0x04 },
+ { 0x5b, 0x20 },
+ { 0x5d, 0x35 },
+ { 0x5e, 0x13 },
+ { 0x78, 0x0f },
+ { 0xef, 0x00 },
+ { 0x4c, 0x80 },
+ { 0x4d, 0xbb },
+ { 0x4e, 0x84 },
+ { 0x4f, 0x91 },
+ { 0x50, 0x64 },
+ { 0x51, 0x93 },
+ { 0x52, 0x03 },
+ { 0x53, 0xc7 },
+ { 0x54, 0x83 },
+ { 0xef, 0x03 },
+ { 0x6e, 0x40 },
+ { 0x6f, 0x50 }, /* dgain for shutter 700lux*/
+
+ { 0xef, 0x00 },
+ { 0x48, 0x00 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x03 },
+ { 0x48, 0x01 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x06 },
+ { 0x48, 0x02 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x24 },
+ { 0x48, 0x03 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x8a },
+ { 0x48, 0x04 },
+ { 0x49, 0x01 },
+ { 0x4A, 0x20 },
+ { 0x48, 0x05 },
+ { 0x49, 0x01 },
+ { 0x4A, 0xB4 },
+ { 0x48, 0x06 },
+ { 0x49, 0x02 },
+ { 0x4A, 0x23 },
+ { 0x48, 0x07 },
+ { 0x49, 0x02 },
+ { 0x4A, 0x72 },
+ { 0x48, 0x08 },
+ { 0x49, 0x02 },
+ { 0x4A, 0xBE },
+ { 0x48, 0x09 },
+ { 0x49, 0x02 },
+ { 0x4A, 0xFA },
+ { 0x48, 0x0A },
+ { 0x49, 0x03 },
+ { 0x4A, 0x27 },
+ { 0x48, 0x0B },
+ { 0x49, 0x03 },
+ { 0x4A, 0x55 },
+ { 0x48, 0x0C },
+ { 0x49, 0x03 },
+ { 0x4A, 0x81 },
+ { 0x48, 0x0D },
+ { 0x49, 0x03 },
+ { 0x4A, 0xA2 },
+ { 0x48, 0x0E },
+ { 0x49, 0x03 },
+ { 0x4A, 0xBC },
+ { 0x48, 0x0F },
+ { 0x49, 0x03 },
+ { 0x4A, 0xD4 },
+ { 0x48, 0x10 },
+ { 0x49, 0x03 },
+ { 0x4A, 0xE8 },
+ { 0x48, 0x11 },
+ { 0x49, 0x03 },
+ { 0x4A, 0xF4 },
+ { 0x48, 0x12 },
+ { 0x49, 0x03 },
+ { 0x4A, 0xFF },
+ { 0x48, 0x20 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x03 },
+ { 0x48, 0x21 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x06 },
+ { 0x48, 0x22 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x24 },
+ { 0x48, 0x23 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x8a },
+ { 0x48, 0x24 },
+ { 0x49, 0x01 },
+ { 0x4A, 0x20 },
+ { 0x48, 0x25 },
+ { 0x49, 0x01 },
+ { 0x4A, 0xB4 },
+ { 0x48, 0x26 },
+ { 0x49, 0x02 },
+ { 0x4A, 0x23 },
+ { 0x48, 0x27 },
+ { 0x49, 0x02 },
+ { 0x4A, 0x72 },
+ { 0x48, 0x28 },
+ { 0x49, 0x02 },
+ { 0x4A, 0xBE },
+ { 0x48, 0x29 },
+ { 0x49, 0x02 },
+ { 0x4A, 0xFA },
+ { 0x48, 0x2A },
+ { 0x49, 0x03 },
+ { 0x4A, 0x27 },
+ { 0x48, 0x2B },
+ { 0x49, 0x03 },
+ { 0x4A, 0x55 },
+ { 0x48, 0x2C },
+ { 0x49, 0x03 },
+ { 0x4A, 0x81 },
+ { 0x48, 0x2D },
+ { 0x49, 0x03 },
+ { 0x4A, 0xA2 },
+ { 0x48, 0x2E },
+ { 0x49, 0x03 },
+ { 0x4A, 0xBC },
+ { 0x48, 0x2F },
+ { 0x49, 0x03 },
+ { 0x4A, 0xD4 },
+ { 0x48, 0x30 },
+ { 0x49, 0x03 },
+ { 0x4A, 0xE8 },
+ { 0x48, 0x31 },
+ { 0x49, 0x03 },
+ { 0x4A, 0xF4 },
+ { 0x48, 0x32 },
+ { 0x49, 0x03 },
+ { 0x4A, 0xFF },
+ { 0x48, 0x40 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x03 },
+ { 0x48, 0x41 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x06 },
+ { 0x48, 0x42 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x24 },
+ { 0x48, 0x43 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x8a },
+ { 0x48, 0x44 },
+ { 0x49, 0x01 },
+ { 0x4A, 0x20 },
+ { 0x48, 0x45 },
+ { 0x49, 0x01 },
+ { 0x4A, 0xB4 },
+ { 0x48, 0x46 },
+ { 0x49, 0x02 },
+ { 0x4A, 0x23 },
+ { 0x48, 0x47 },
+ { 0x49, 0x02 },
+ { 0x4A, 0x72 },
+ { 0x48, 0x48 },
+ { 0x49, 0x02 },
+ { 0x4A, 0xBE },
+ { 0x48, 0x49 },
+ { 0x49, 0x02 },
+ { 0x4A, 0xFA },
+ { 0x48, 0x4A },
+ { 0x49, 0x03 },
+ { 0x4A, 0x27 },
+ { 0x48, 0x4B },
+ { 0x49, 0x03 },
+ { 0x4A, 0x55 },
+ { 0x48, 0x4C },
+ { 0x49, 0x03 },
+ { 0x4A, 0x81 },
+ { 0x48, 0x4D },
+ { 0x49, 0x03 },
+ { 0x4A, 0xA2 },
+ { 0x48, 0x4E },
+ { 0x49, 0x03 },
+ { 0x4A, 0xBC },
+ { 0x48, 0x4F },
+ { 0x49, 0x03 },
+ { 0x4A, 0xD4 },
+ { 0x48, 0x50 },
+ { 0x49, 0x03 },
+ { 0x4A, 0xE8 },
+ { 0x48, 0x51 },
+ { 0x49, 0x03 },
+ { 0x4A, 0xF4 },
+ { 0x48, 0x52 },
+ { 0x49, 0x03 },
+ { 0x4A, 0xFF },
+ { 0xEF, 0x03 },
+ { 0x00, 0x03 },
+};
+
+/*
+ * VT init setting
+ */
+struct s5ka3dfx_reg s5ka3dfx_init_vt_reg[] = {
+ { 0xef, 0x02 },
+ { 0x13, 0xa0 },
+ { 0x23, 0x53 },
+ { 0x26, 0x24 },
+ { 0x2c, 0x05 },
+ { 0x05, 0x00 },
+ { 0x03, 0x58 },
+ { 0x24, 0x0a },
+ { 0x0b, 0x82 },
+ { 0x1e, 0xb7 },
+ { 0x56, 0x05 },
+ { 0x28, 0x96 },
+ { 0x67, 0x3c },
+ { 0x4b, 0x5e },
+ { 0xef, 0x03 },
+ { 0x50, 0xd2 },
+ { 0x0f, 0x31 },
+ { 0xef, 0x03 },
+ { 0x5F, 0x03 },
+ { 0x60, 0x02 },
+ { 0x61, 0x0f },
+ { 0x62, 0x0c },
+ { 0x63, 0x05 },
+ { 0x64, 0x43 },
+ { 0x65, 0x05 },
+ { 0x66, 0x43 },
+ { 0x6d, 0x5a },
+ { 0x6e, 0x40 },
+ { 0x6f, 0x70 },
+ { 0x4c, 0x00 },
+ { 0x4d, 0x9e },
+ { 0xef, 0x03 },
+ { 0x00, 0x87 },
+ { 0x01, 0x80 },
+ { 0x02, 0x7f },
+ { 0x2b, 0x41 },
+ { 0x31, 0x07 },
+ { 0x32, 0x18 },
+ { 0x33, 0x80 },
+ { 0x34, 0x79 },
+ { 0x36, 0x36 },
+ { 0x37, 0x27 },
+ { 0x6a, 0x00 },
+ { 0x7b, 0x05 },
+ { 0x38, 0x05 },
+ { 0x39, 0x03 },
+ { 0x2d, 0x08 },
+ { 0x2e, 0x20 },
+ { 0x2f, 0x30 },
+ { 0x30, 0xff },
+ { 0x7c, 0x06 },
+ { 0x7d, 0x20 },
+ { 0x7e, 0x0c },
+ { 0x7f, 0x20 },
+ { 0x28, 0x02 },
+ { 0x29, 0xa8 },
+ { 0x2a, 0x00 },
+ { 0x13, 0x00 },
+ { 0x14, 0xa0 },
+ { 0x1a, 0x6a },
+ { 0x1b, 0x50 },
+ { 0x1c, 0x63 },
+ { 0x1d, 0x4b },
+ { 0x1e, 0x6a },
+ { 0x1f, 0x3c },
+ { 0x20, 0x9a },
+ { 0x21, 0x4b },
+ { 0x3a, 0x13 },
+ { 0x3b, 0x3e },
+ { 0x3c, 0x00 },
+ { 0x3d, 0x18 },
+ { 0x23, 0x80 },
+ { 0x15, 0x0b },
+ { 0x16, 0xd2 },
+ { 0x17, 0x64 },
+ { 0x18, 0x78 },
+ { 0xef, 0x00 },
+ { 0xde, 0x00 },
+ { 0xdf, 0x1F },
+ { 0xe0, 0x00 },
+ { 0xe1, 0x37 },
+ { 0xe2, 0x08 },
+ { 0xe3, 0x42 },
+ { 0xe4, 0x00 },
+ { 0xe5, 0x12 },
+ { 0xe6, 0x9E },
+ { 0xe9, 0x00 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0xA8 },
+ { 0xe9, 0x01 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0xB1 },
+ { 0xe9, 0x02 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0xC4 },
+ { 0xe9, 0x03 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0xBA },
+ { 0xe9, 0x04 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0xC4 },
+ { 0xe9, 0x05 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0xE5 },
+ { 0xe9, 0x06 },
+ { 0xe7, 0x01 },
+ { 0xe8, 0x13 },
+ { 0xe9, 0x07 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x4B },
+ { 0xe9, 0x08 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x4B },
+ { 0xe9, 0x09 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x4E },
+ { 0xe9, 0x0A },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x4F },
+ { 0xe9, 0x0B },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x42 },
+ { 0xe9, 0x0C },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x6A },
+ { 0xe9, 0x0D },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x89 },
+ { 0xe9, 0x0E },
+ { 0xe7, 0x07 },
+ { 0xe8, 0xD9 },
+ { 0xe9, 0x0F },
+ { 0xe7, 0x07 },
+ { 0xe8, 0xD8 },
+ { 0xe9, 0x10 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0xDD },
+ { 0xe9, 0x11 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0xD1 },
+ { 0xe9, 0x12 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0xCA },
+ { 0xe9, 0x13 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0xCE },
+ { 0xe9, 0x14 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0xFA },
+ { 0xe9, 0x15 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0x6A },
+ { 0xe9, 0x16 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0x71 },
+ { 0xe9, 0x17 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0x70 },
+ { 0xe9, 0x18 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0x5E },
+ { 0xe9, 0x19 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0x50 },
+ { 0xe9, 0x1A },
+ { 0xe7, 0x07 },
+ { 0xe8, 0x55 },
+ { 0xe9, 0x1B },
+ { 0xe7, 0x07 },
+ { 0xe8, 0x6D },
+ { 0xe9, 0x1C },
+ { 0xe7, 0x07 },
+ { 0xe8, 0x1C },
+ { 0xe9, 0x1D },
+ { 0xe7, 0x07 },
+ { 0xe8, 0x12 },
+ { 0xe9, 0x1E },
+ { 0xe7, 0x07 },
+ { 0xe8, 0x07 },
+ { 0xe9, 0x1F },
+ { 0xe7, 0x06 },
+ { 0xe8, 0xFA },
+ { 0xe9, 0x20 },
+ { 0xe7, 0x06 },
+ { 0xe8, 0xE5 },
+ { 0xe9, 0x21 },
+ { 0xe7, 0x06 },
+ { 0xe8, 0xF0 },
+ { 0xe9, 0x22 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0x0A },
+ { 0xe9, 0x40 },
+ { 0xd1, 0x08 },
+ { 0xdd, 0x03 },
+ { 0x23, 0x10 },
+ { 0x24, 0x10 },
+ { 0x25, 0x10 },
+ { 0x27, 0x18 },
+ { 0x29, 0x60 },
+ { 0x2a, 0x22 },
+ { 0x2f, 0x01 },
+ { 0x36, 0x01 },
+ { 0x37, 0xe1 },
+ { 0x38, 0xc7 },
+ { 0x39, 0xb1 },
+ { 0x3a, 0x01 },
+ { 0x3b, 0x04 },
+ { 0x3c, 0x01 },
+ { 0x3d, 0x54 },
+ { 0xb9, 0x02 },
+ { 0xbb, 0xb0 },
+ { 0xbc, 0x18 },
+ { 0xbd, 0x30 },
+ { 0xbf, 0x38 },
+ { 0xc1, 0x88 },
+ { 0xc8, 0x11 },
+ { 0xeb, 0x81 },
+ { 0xed, 0x05 },
+ { 0xb1, 0x00 },
+ { 0xb2, 0x62 },
+ { 0xb3, 0x00 },
+ { 0xb4, 0x00 },
+ { 0xb5, 0x01 },
+ { 0xb6, 0xa3 },
+ { 0xb7, 0x02 },
+ { 0xb8, 0x80 },
+ { 0x77, 0x00 },
+ { 0x78, 0x10 },
+ { 0xef, 0x00 },
+ { 0x93, 0x40 },
+ { 0x94, 0x80 },
+ { 0x95, 0xc0 },
+ { 0x96, 0xc0 },
+ { 0x97, 0x20 },
+ { 0x98, 0x20 },
+ { 0x99, 0x30 },
+ { 0xA0, 0x00 },
+ { 0xA1, 0x00 },
+ { 0xA2, 0x1c },
+ { 0xA3, 0x16 },
+ { 0xA4, 0x03 },
+ { 0xA5, 0x07 },
+ { 0xA6, 0x00 },
+ { 0xef, 0x00 },
+ { 0xad, 0xd0 },
+ { 0xaf, 0x10 },
+ { 0xef, 0x00 },
+ { 0x42, 0x5f },
+ { 0x44, 0x61 },
+ { 0x57, 0x00 },
+ { 0xef, 0x03 },
+ { 0x00, 0x87 },
+ { 0x01, 0x3c },
+ { 0x02, 0x05 },
+ { 0x03, 0x21 },
+ { 0x04, 0x6c },
+ { 0x06, 0x1c },
+ { 0x07, 0x01 },
+ { 0x08, 0x01 },
+ { 0x0b, 0x01 },
+ { 0x51, 0x10 },
+ { 0x52, 0x00 },
+ { 0x53, 0x00 },
+ { 0x54, 0x00 },
+ { 0x55, 0x22 },
+ { 0x56, 0x01 },
+ { 0x57, 0x61 },
+ { 0x58, 0x25 },
+ { 0x67, 0xcf },
+ { 0x69, 0x17 },
+ { 0xef, 0x00 },
+ { 0x58, 0x00 },
+ { 0x59, 0x00 },
+ { 0x5a, 0x02 },
+ { 0x5b, 0x73 },
+ { 0x5c, 0x00 },
+ { 0x5d, 0x00 },
+ { 0x5e, 0x01 },
+ { 0x5f, 0xe0 },
+ { 0x60, 0x00 },
+ { 0x61, 0xae },
+ { 0x62, 0x01 },
+ { 0x63, 0xbb },
+ { 0x64, 0x00 },
+ { 0x65, 0x7e },
+ { 0x66, 0x01 },
+ { 0x67, 0x8e },
+ { 0xef, 0x00 },
+ { 0x6a, 0x01 },
+ { 0x6b, 0xe0 },
+ { 0x6c, 0x05 },
+ { 0x6d, 0x00 },
+ { 0x6e, 0x0e },
+ { 0x6f, 0x00 },
+ { 0x70, 0x10 },
+ { 0xef, 0x03 },
+ { 0x22, 0x24 },
+ { 0x3e, 0x23 },
+ { 0x3f, 0x23 },
+ { 0x40, 0x00 },
+ { 0x41, 0x09 },
+ { 0x4a, 0x09 },
+ { 0x4b, 0x04 },
+ { 0x5b, 0x20 },
+ { 0x5d, 0x35 },
+ { 0x5e, 0x13 },
+ { 0x78, 0x0f },
+ { 0xef, 0x00 },
+ { 0x4c, 0x79 },
+ { 0x4d, 0xbe },
+ { 0x4e, 0x08 },
+ { 0x4f, 0x9c },
+ { 0x50, 0x7a },
+ { 0x51, 0x9e },
+ { 0x52, 0x8f },
+ { 0x53, 0xbb },
+ { 0x54, 0x8a },
+ { 0xef, 0x03 },
+ { 0x70, 0x00 },
+ { 0xef, 0x00 },
+ { 0x48, 0x00 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x03 },
+ { 0x48, 0x01 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x08 },
+ { 0x48, 0x02 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x4A },
+ { 0x48, 0x03 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x96 },
+ { 0x48, 0x04 },
+ { 0x49, 0x01 },
+ { 0x4A, 0x24 },
+ { 0x48, 0x05 },
+ { 0x49, 0x01 },
+ { 0x4A, 0xB4 },
+ { 0x48, 0x06 },
+ { 0x49, 0x02 },
+ { 0x4A, 0x23 },
+ { 0x48, 0x07 },
+ { 0x49, 0x02 },
+ { 0x4A, 0x72 },
+ { 0x48, 0x08 },
+ { 0x49, 0x02 },
+ { 0x4A, 0xBE },
+ { 0x48, 0x09 },
+ { 0x49, 0x02 },
+ { 0x4A, 0xFA },
+ { 0x48, 0x0A },
+ { 0x49, 0x03 },
+ { 0x4A, 0x27 },
+ { 0x48, 0x0B },
+ { 0x49, 0x03 },
+ { 0x4A, 0x55 },
+ { 0x48, 0x0C },
+ { 0x49, 0x03 },
+ { 0x4A, 0x81 },
+ { 0x48, 0x0D },
+ { 0x49, 0x03 },
+ { 0x4A, 0xA2 },
+ { 0x48, 0x0E },
+ { 0x49, 0x03 },
+ { 0x4A, 0xBC },
+ { 0x48, 0x0F },
+ { 0x49, 0x03 },
+ { 0x4A, 0xD4 },
+ { 0x48, 0x10 },
+ { 0x49, 0x03 },
+ { 0x4A, 0xE8 },
+ { 0x48, 0x11 },
+ { 0x49, 0x03 },
+ { 0x4A, 0xF4 },
+ { 0x48, 0x12 },
+ { 0x49, 0x03 },
+ { 0x4A, 0xFF },
+ { 0x48, 0x20 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x03 },
+ { 0x48, 0x21 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x08 },
+ { 0x48, 0x22 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x4A },
+ { 0x48, 0x23 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x96 },
+ { 0x48, 0x24 },
+ { 0x49, 0x01 },
+ { 0x4A, 0x24 },
+ { 0x48, 0x25 },
+ { 0x49, 0x01 },
+ { 0x4A, 0xB4 },
+ { 0x48, 0x26 },
+ { 0x49, 0x02 },
+ { 0x4A, 0x23 },
+ { 0x48, 0x27 },
+ { 0x49, 0x02 },
+ { 0x4A, 0x72 },
+ { 0x48, 0x28 },
+ { 0x49, 0x02 },
+ { 0x4A, 0xBE },
+ { 0x48, 0x29 },
+ { 0x49, 0x02 },
+ { 0x4A, 0xFA },
+ { 0x48, 0x2A },
+ { 0x49, 0x03 },
+ { 0x4A, 0x27 },
+ { 0x48, 0x2B },
+ { 0x49, 0x03 },
+ { 0x4A, 0x55 },
+ { 0x48, 0x2C },
+ { 0x49, 0x03 },
+ { 0x4A, 0x81 },
+ { 0x48, 0x2D },
+ { 0x49, 0x03 },
+ { 0x4A, 0xA2 },
+ { 0x48, 0x2E },
+ { 0x49, 0x03 },
+ { 0x4A, 0xBC },
+ { 0x48, 0x2F },
+ { 0x49, 0x03 },
+ { 0x4A, 0xD4 },
+ { 0x48, 0x30 },
+ { 0x49, 0x03 },
+ { 0x4A, 0xE8 },
+ { 0x48, 0x31 },
+ { 0x49, 0x03 },
+ { 0x4A, 0xF4 },
+ { 0x48, 0x32 },
+ { 0x49, 0x03 },
+ { 0x4A, 0xFF },
+ { 0x48, 0x40 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x03 },
+ { 0x48, 0x41 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x08 },
+ { 0x48, 0x42 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x4A },
+ { 0x48, 0x43 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x96 },
+ { 0x48, 0x44 },
+ { 0x49, 0x01 },
+ { 0x4A, 0x24 },
+ { 0x48, 0x45 },
+ { 0x49, 0x01 },
+ { 0x4A, 0xB4 },
+ { 0x48, 0x46 },
+ { 0x49, 0x02 },
+ { 0x4A, 0x23 },
+ { 0x48, 0x47 },
+ { 0x49, 0x02 },
+ { 0x4A, 0x72 },
+ { 0x48, 0x48 },
+ { 0x49, 0x02 },
+ { 0x4A, 0xBE },
+ { 0x48, 0x49 },
+ { 0x49, 0x02 },
+ { 0x4A, 0xFA },
+ { 0x48, 0x4A },
+ { 0x49, 0x03 },
+ { 0x4A, 0x27 },
+ { 0x48, 0x4B },
+ { 0x49, 0x03 },
+ { 0x4A, 0x55 },
+ { 0x48, 0x4C },
+ { 0x49, 0x03 },
+ { 0x4A, 0x81 },
+ { 0x48, 0x4D },
+ { 0x49, 0x03 },
+ { 0x4A, 0xA2 },
+ { 0x48, 0x4E },
+ { 0x49, 0x03 },
+ { 0x4A, 0xBC },
+ { 0x48, 0x4F },
+ { 0x49, 0x03 },
+ { 0x4A, 0xD4 },
+ { 0x48, 0x50 },
+ { 0x49, 0x03 },
+ { 0x4A, 0xE8 },
+ { 0x48, 0x51 },
+ { 0x49, 0x03 },
+ { 0x4A, 0xF4 },
+ { 0x48, 0x52 },
+ { 0x49, 0x03 },
+ { 0x4A, 0xFF },
+};
+
+/* Exposure Value Setting */
+/* EV bias */
+struct s5ka3dfx_reg s5ka3dfx_ev_m5[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0xc0 },
+ { 0x32, 0x98 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_m4[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0xA5 },
+ { 0x32, 0x90 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_m3[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x9E },
+ { 0x32, 0x88 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_m2[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x90 },
+ { 0x32, 0x00 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_m1[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x8A },
+ { 0x32, 0x08 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_default[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x00 },
+ { 0x32, 0x09 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_p1[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x0A },
+ { 0x32, 0x20 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_p2[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x14 },
+ { 0x32, 0x30 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_p3[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x1E },
+ { 0x32, 0x38 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_p4[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x28 },
+ { 0x32, 0x40 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_p5[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x30 },
+ { 0x32, 0x48 },
+};
+
+/* EV bias for VT */
+struct s5ka3dfx_reg s5ka3dfx_ev_vt_m5[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0xa9 },
+ { 0x32, 0xa4 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_vt_m4[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x99 },
+ { 0x32, 0x9c },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_vt_m3[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x91 },
+ { 0x32, 0x94 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_vt_m2[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x89 },
+ { 0x32, 0x08 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_vt_m1[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x81 },
+ { 0x32, 0x10 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_vt_default[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x07 },
+ { 0x32, 0x18 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_vt_p1[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x0e },
+ { 0x32, 0x28 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_vt_p2[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x17 },
+ { 0x32, 0x38 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_vt_p3[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x27 },
+ { 0x32, 0x40 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_vt_p4[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x2a },
+ { 0x32, 0x3e },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_vt_p5[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x32 },
+ { 0x32, 0x46 },
+};
+
+/* White Balance Setting */
+struct s5ka3dfx_reg s5ka3dfx_wb_auto[] = {
+ { 0xef, 0x03 },
+ { 0x00, 0x87 },
+ { 0xef, 0x00 },
+ { 0x42, 0x6f },
+ { 0x43, 0x40 },
+ { 0x44, 0x5a },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_wb_tungsten[] = {
+ { 0xef, 0x03 },
+ { 0x00, 0x85 },
+ { 0xef, 0x00 },
+ { 0x42, 0x48 },
+ { 0x43, 0x43 },
+ { 0x44, 0x7e },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_wb_fluorescent[] = {
+ { 0xef, 0x03 },
+ { 0x00, 0x85 },
+ { 0xef, 0x00 },
+ { 0x42, 0x5c },
+ { 0x43, 0x40 },
+ { 0x44, 0x6d },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_wb_sunny[] = {
+ { 0xef, 0x03 },
+ { 0x00, 0x85 },
+ { 0xef, 0x00 },
+ { 0x42, 0x67 },
+ { 0x43, 0x40 },
+ { 0x44, 0x4c },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_wb_cloudy[] = {
+ { 0xef, 0x03 },
+ { 0x00, 0x85 },
+ { 0xef, 0x00 },
+ { 0x42, 0x75 },
+ { 0x43, 0x3d },
+ { 0x44, 0x42 },
+};
+
+/* Effect Setting */
+struct s5ka3dfx_reg s5ka3dfx_effect_none[] = {
+ { 0xef, 0x00 },
+ { 0xd3, 0x00 },
+ { 0xd4, 0x00 },
+ { 0xd5, 0x01 },
+ { 0xd6, 0xa3 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_effect_gray[] = {
+ { 0xef, 0x00 },
+ { 0xd3, 0x00 },
+ { 0xd4, 0x03 },
+ { 0xd5, 0x80 },
+ { 0xd6, 0x80 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_effect_sepia[] = {
+ { 0xef, 0x00 },
+ { 0xd3, 0x00 },
+ { 0xd4, 0x03 },
+ { 0xd5, 0x60 },
+ { 0xd6, 0x8c },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_effect_negative[] = {
+ { 0xef, 0x00 },
+ { 0xd3, 0x01 },
+ { 0xd4, 0x00 },
+ { 0xd5, 0x2c },
+ { 0xd6, 0x81 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_effect_aqua[] = {
+ { 0xef, 0x00 },
+ { 0xd3, 0x00 },
+ { 0xd4, 0x03 },
+ { 0xd5, 0xdc },
+ { 0xd6, 0x00 },
+};
+
+/* Blur Setting */
+/*Self shot*/
+struct s5ka3dfx_reg s5ka3dfx_blur_none[] = {
+ { 0xef, 0x03 },
+ { 0x01, 0x3c },
+ { 0x29, 0x8f },
+ { 0x34, 0x79 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_blur_p1[] = {
+ { 0xef, 0x03 },
+ { 0x01, 0x4a },
+ { 0x29, 0x5f },
+ { 0x34, 0x89 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_blur_p2[] = {
+ { 0xef, 0x03 },
+ { 0x01, 0x58 },
+ { 0x29, 0x2f },
+ { 0x34, 0x99 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_blur_p3[] = {
+ { 0xef, 0x03 },
+ { 0x01, 0x66 },
+ { 0x29, 0x00 },
+ { 0x34, 0xa9 },
+};
+
+/*vt call*/
+struct s5ka3dfx_reg s5ka3dfx_blur_vt_none[] = {
+ { 0xef, 0x03 },
+ { 0x01, 0x3c },
+ { 0x29, 0xa8 },
+ { 0x34, 0x79 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_blur_vt_p1[] = {
+ { 0xef, 0x03 },
+ { 0x01, 0x4a },
+ { 0x29, 0x68 },
+ { 0x34, 0x89 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_blur_vt_p2[] = {
+ { 0xef, 0x03 },
+ { 0x01, 0x58 },
+ { 0x29, 0x38 },
+ { 0x34, 0x99 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_blur_vt_p3[] = {
+ { 0xef, 0x03 },
+ { 0x01, 0x66 },
+ { 0x29, 0x18 },
+ { 0x34, 0xa9 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_dataline[] = {
+ { 0xef, 0x00 },
+ { 0x0a, 0x01 }, /* s/w reset */
+ { 0x04, 0x01 },
+ { 0xcb, 0x01 },
+ { 0xd1, 0x08 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_dataline_stop[] = {
+ { 0xef, 0x00 },
+ { 0xcb, 0x00 },
+};
+
+/* FPS */
+struct s5ka3dfx_reg s5ka3dfx_fps_7[] = {
+ { 0xEF, 0x03 },
+ { 0x5F, 0x03 },
+ { 0x60, 0x02 },
+ { 0x61, 0x11 },
+ { 0x62, 0x0E },
+ { 0x63, 0x06 },
+ { 0x64, 0x4B },
+ { 0x65, 0x06 },
+ { 0x66, 0x4B },
+ { 0x48, 0x00 },
+ { 0x49, 0x9E },
+ { 0x4C, 0x00 },
+ { 0x4D, 0x9E },
+ { 0xEF, 0x03 },
+ { 0x51, 0x10 },
+ { 0x52, 0x00 },
+ { 0x53, 0x00 },
+ { 0x54, 0x00 },
+ { 0x56, 0x01 },
+ { 0x57, 0x61 },
+ { 0x58, 0x25 },
+ { 0x67, 0xCF },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_fps_10[] = {
+ { 0xEF, 0x03 },
+ { 0x5F, 0x03 },
+ { 0x60, 0x02 },
+ { 0x61, 0x0C },
+ { 0x62, 0x0A },
+ { 0x63, 0x03 },
+ { 0x64, 0xD3 },
+ { 0x65, 0x03 },
+ { 0x66, 0xD3 },
+ { 0x48, 0x00 },
+ { 0x49, 0x9E },
+ { 0x4C, 0x00 },
+ { 0x4D, 0x9E },
+ { 0xEF, 0x03 },
+ { 0x51, 0x10 },
+ { 0x52, 0x00 },
+ { 0x53, 0x00 },
+ { 0x54, 0x00 },
+ { 0x56, 0x01 },
+ { 0x57, 0x61 },
+ { 0x58, 0x25 },
+ { 0x67, 0xCF },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_fps_15[] = {
+ { 0xEF, 0x03 },
+ { 0x5F, 0x03 },
+ { 0x60, 0x02 },
+ { 0x61, 0x08 },
+ { 0x62, 0x06 },
+ { 0x63, 0x01 },
+ { 0x64, 0xE7 },
+ { 0x65, 0x01 },
+ { 0x66, 0xE7 },
+ { 0x48, 0x00 },
+ { 0x49, 0x9E },
+ { 0x4C, 0x00 },
+ { 0x4D, 0x9E },
+ { 0xEF, 0x03 },
+ { 0x51, 0x10 },
+ { 0x52, 0x00 },
+ { 0x53, 0x00 },
+ { 0x54, 0x00 },
+ { 0x56, 0x01 },
+ { 0x57, 0x61 },
+ { 0x58, 0x25 },
+ { 0x67, 0xCF },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_fps_auto[] = {
+ { 0xEF, 0x03 },
+ { 0x5F, 0x03 },
+ { 0x60, 0x02 },
+ { 0x61, 0x0F },
+ { 0x62, 0x0C },
+ { 0x63, 0x01 },
+ { 0x64, 0xE7 },
+ { 0x65, 0x01 },
+ { 0x66, 0xE7 },
+ { 0x48, 0x00 },
+ { 0x49, 0x9E },
+ { 0x4C, 0x00 },
+ { 0x4D, 0x9E },
+ { 0xEF, 0x03 },
+ { 0x51, 0x10 },
+ { 0x52, 0x00 },
+ { 0x53, 0x00 },
+ { 0x54, 0x00 },
+ { 0x56, 0x01 },
+ { 0x57, 0x61 },
+ { 0x58, 0x25 },
+ { 0x67, 0xCF },
+};
+struct s5ka3dfx_reg s5ka3dfx_vt_fps_7[] = {
+ { 0xef, 0x03 },
+ { 0x50, 0xd2 },
+ { 0x0f, 0x31 },
+ { 0xef, 0x03 },
+ { 0x5f, 0x11 },
+ { 0x60, 0x0e },
+ { 0x61, 0x11 },
+ { 0x62, 0x0e },
+ { 0x63, 0x06 },
+ { 0x64, 0x4b },
+ { 0x65, 0x06 },
+ { 0x66, 0x4b },
+ { 0x6d, 0x6c },
+ { 0x6E, 0x40 },
+ { 0x6f, 0x40 },
+ { 0x4c, 0x00 },
+ { 0x4d, 0x9E },
+ { 0x51, 0x10 },
+ { 0x52, 0x00 },
+ { 0x53, 0x00 },
+ { 0x54, 0x00 },
+ { 0x55, 0x22 },
+ { 0x56, 0x01 },
+ { 0x57, 0x61 },
+ { 0x58, 0x25 },
+ { 0x67, 0xcf },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_vt_fps_10[] = {
+ { 0xef, 0x03 },
+ { 0x50, 0xd2 },
+ { 0x0f, 0x31 },
+ { 0xef, 0x03 },
+ { 0x5f, 0x0c },
+ { 0x60, 0x0a },
+ { 0x61, 0x0c },
+ { 0x62, 0x0a },
+ { 0x63, 0x03 },
+ { 0x64, 0xd3 },
+ { 0x65, 0x03 },
+ { 0x66, 0xd3 },
+ { 0x6d, 0x6C },
+ { 0x6E, 0x40 },
+ { 0x6f, 0x40 },
+ { 0x4c, 0x00 },
+ { 0x4d, 0x9E },
+ { 0x51, 0x10 },
+ { 0x52, 0x00 },
+ { 0x53, 0x00 },
+ { 0x54, 0x00 },
+ { 0x55, 0x22 },
+ { 0x56, 0x01 },
+ { 0x57, 0x61 },
+ { 0x58, 0x25 },
+ { 0x67, 0xcf },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_vt_fps_15[] = {
+ { 0xef, 0x03 },
+ { 0x50, 0xd2 },
+ { 0x0f, 0x31 },
+ { 0xef, 0x03 },
+ { 0x5f, 0x08 },
+ { 0x60, 0x06 },
+ { 0x61, 0x08 },
+ { 0x62, 0x06 },
+ { 0x63, 0x01 },
+ { 0x64, 0xE7 },
+ { 0x65, 0x01 },
+ { 0x66, 0xE7 },
+ { 0x6d, 0x6C },
+ { 0x6E, 0x40 },
+ { 0x6f, 0x40 },
+ { 0x4c, 0x00 },
+ { 0x4d, 0x9E },
+ { 0x51, 0x10 },
+ { 0x52, 0x00 },
+ { 0x53, 0x00 },
+ { 0x54, 0x00 },
+ { 0x55, 0x22 },
+ { 0x56, 0x01 },
+ { 0x57, 0x61 },
+ { 0x58, 0x25 },
+ { 0x67, 0xcf },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_vt_fps_auto[] = {
+ { 0xef, 0x03 },
+ { 0x50, 0xd2 },
+ { 0x0f, 0x31 },
+ { 0xef, 0x03 },
+ { 0x5f, 0x03 },
+ { 0x60, 0x02 },
+ { 0x61, 0x0f },
+ { 0x62, 0x0c },
+ { 0x63, 0x05 },
+ { 0x64, 0x43 },
+ { 0x65, 0x05 },
+ { 0x66, 0x43 },
+ { 0x6d, 0x5a },
+ { 0x6E, 0x40 },
+ { 0x6f, 0x70 },
+ { 0x4c, 0x00 },
+ { 0x4d, 0x9E },
+ { 0x51, 0x10 },
+ { 0x52, 0x00 },
+ { 0x53, 0x00 },
+ { 0x54, 0x00 },
+ { 0x55, 0x22 },
+ { 0x56, 0x01 },
+ { 0x57, 0x61 },
+ { 0x58, 0x25 },
+ { 0x67, 0xcf },
+
+};
+
+struct s5ka3dfx_reg s5ka3dfx_Return_VGA[] = {
+ { 0xef, 0x00 },
+ { 0x7a, 0x00 },
+ { 0x11, 0x00 },
+ { 0x12, 0x00 },
+ { 0x15, 0x02 },
+ { 0x16, 0x90 },
+ { 0x13, 0x01 },
+ { 0x14, 0xF0 },
+ { 0x31, 0x04 },
+ { 0x30, 0x06 },
+ { 0x34, 0x02 },
+ { 0x35, 0x88 },
+ { 0x32, 0x01 },
+ { 0x33, 0xE8 },
+ { 0x7d, 0x02 },
+ { 0x7e, 0x88 },
+ { 0x7b, 0x01 },
+ { 0x7C, 0xe8 },
+ { 0x81, 0x02 },
+ { 0x82, 0x01 },
+ { 0x7f, 0x01 },
+ { 0x80, 0xe8 },
+ { 0xc3, 0x04 },
+ { 0xc2, 0x04 },
+ { 0xc6, 0x02 },
+ { 0xc7, 0x80 },
+ { 0xc4, 0x01 },
+ { 0xc5, 0xe0 },
+ { 0x7a, 0x01 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_QVGA[] = { /* 320 x 240 */
+ { 0xef, 0x00 },
+ { 0x7a, 0x00 },
+ { 0x11, 0x00 },
+ { 0x12, 0x00 },
+ { 0x15, 0x02 },
+ { 0x16, 0x90 },
+ { 0x13, 0x01 },
+ { 0x14, 0xF0 },
+ { 0x31, 0x04 },
+ { 0x30, 0x06 },
+ { 0x34, 0x02 },
+ { 0x35, 0x88 },
+ { 0x32, 0x01 },
+ { 0x33, 0xE8 },
+ { 0x7d, 0x02 },
+ { 0x7e, 0x88 },
+ { 0x7b, 0x01 },
+ { 0x7c, 0xe8 },
+ { 0x81, 0x01 },
+ { 0x82, 0x48 },
+ { 0x7f, 0x00 },
+ { 0x80, 0xf8 },
+ { 0xc3, 0x04 },
+ { 0xc2, 0x04 },
+ { 0xc6, 0x01 },
+ { 0xc7, 0x40 },
+ { 0xc4, 0x00 },
+ { 0xc5, 0xf0 },
+ { 0x7a, 0x03 },
+};
+
+
+struct s5ka3dfx_reg s5ka3dfx_QCIF[] = { /* 176 x 144 */
+ { 0xef, 0x00 },
+ { 0x7a, 0x00 },
+ { 0x11, 0x00 },
+ { 0x12, 0x00 },
+ { 0x15, 0x02 },
+ { 0x16, 0x90 },
+ { 0x13, 0x01 },
+ { 0x14, 0xF0 },
+ { 0x31, 0x04 },
+ { 0x30, 0x06 },
+ { 0x34, 0x02 },
+ { 0x35, 0x88 },
+ { 0x32, 0x01 },
+ { 0x33, 0xE8 },
+ { 0x7d, 0x02 },
+ { 0x7e, 0x88 },
+ { 0x7b, 0x01 },
+ { 0x7c, 0xe8 },
+ { 0x81, 0x00 },
+ { 0x82, 0xc0 },
+ { 0x7f, 0x00 },
+ { 0x80, 0x98 },
+ { 0xc3, 0x08 },
+ { 0xc2, 0x04 },
+ { 0xc6, 0x00 },
+ { 0xc7, 0xb0 },
+ { 0xc4, 0x00 },
+ { 0xc5, 0x90 },
+ { 0x7a, 0x03 },
+};
+#endif
diff --git a/drivers/media/video/samsung/Kconfig b/drivers/media/video/samsung/Kconfig
new file mode 100644
index 0000000..39ef521
--- /dev/null
+++ b/drivers/media/video/samsung/Kconfig
@@ -0,0 +1,26 @@
+config VIDEO_SAMSUNG
+ bool "Samsung Multimedia Devices"
+ depends on VIDEO_CAPTURE_DRIVERS && VIDEO_V4L2
+ select VIDEO_FIXED_MINOR_RANGES
+ default n
+ ---help---
+ This is a representative video4linux configuration for Samsung multimedia devices.
+
+config VIDEO_SAMSUNG_V4L2
+ bool "V4L2 API for digital camera to be contributed by samsung"
+ depends on VIDEO_DEV && VIDEO_SAMSUNG
+ default n
+ ---help---
+ This feature is for new V4L2 APIs all about digital camera
+
+if CPU_S5PV210
+source "drivers/media/video/samsung/fimc/Kconfig"
+source "drivers/media/video/samsung/mfc50/Kconfig"
+source "drivers/media/video/samsung/jpeg_v2/Kconfig"
+#source "drivers/media/video/samsung/tv20/Kconfig"
+#source "drivers/media/video/samsung/tsi/Kconfig"
+if CPU_S5PV210_EVT1
+#source "drivers/media/video/samsung/rotator/Kconfig"
+#source "drivers/media/video/samsung/g2d/Kconfig"
+endif
+endif
diff --git a/drivers/media/video/samsung/Makefile b/drivers/media/video/samsung/Makefile
new file mode 100644
index 0000000..b363793
--- /dev/null
+++ b/drivers/media/video/samsung/Makefile
@@ -0,0 +1,10 @@
+obj-$(CONFIG_VIDEO_FIMC) += fimc/
+obj-$(CONFIG_VIDEO_MFC50) += mfc50/
+obj-$(CONFIG_VIDEO_JPEG_V2) += jpeg_v2/
+#obj-$(CONFIG_VIDEO_ROTATOR) += rotator/
+#obj-$(CONFIG_VIDEO_TV20) += tv20/
+#obj-$(CONFIG_VIDEO_G2D) += g2d/
+#obj-$(CONFIG_VIDEO_TSI) += tsi/
+
+EXTRA_CFLAGS += -Idrivers/media/video
+
diff --git a/drivers/media/video/samsung/fimc/Kconfig b/drivers/media/video/samsung/fimc/Kconfig
new file mode 100644
index 0000000..c9eae69
--- /dev/null
+++ b/drivers/media/video/samsung/fimc/Kconfig
@@ -0,0 +1,32 @@
+config VIDEO_FIMC
+ bool "Samsung Camera Interface (FIMC) driver"
+ depends on VIDEO_SAMSUNG && ARCH_S5PV210
+ default n
+ help
+ This is a video4linux driver for Samsung FIMC device.
+
+choice
+depends on VIDEO_FIMC
+prompt "Select CSC Range config"
+default VIDEO_FIMC_RANGE_NARROW
+config VIDEO_FIMC_RANGE_NARROW
+ bool "Narrow"
+ depends on VIDEO_FIMC && ARCH_S5PV210
+ ---help---
+ RGB <-> YUV Color Conversion Narrow Range Equation
+
+config VIDEO_FIMC_RANGE_WIDE
+ bool "Wide"
+ depends on VIDEO_FIMC && ARCH_S5PV210
+ ---help---
+ RGB <-> YUV Color Conversion Wide Range Equation
+endchoice
+
+config VIDEO_FIMC_DEBUG
+ bool "FIMC driver debug messages"
+ depends on VIDEO_FIMC
+
+config VIDEO_FIMC_MIPI
+ bool "MIPI-CSI2 Slave Interface support"
+ depends on VIDEO_FIMC && ARCH_S5PV210
+ default y
diff --git a/drivers/media/video/samsung/fimc/Makefile b/drivers/media/video/samsung/fimc/Makefile
new file mode 100644
index 0000000..4f6e5c9
--- /dev/null
+++ b/drivers/media/video/samsung/fimc/Makefile
@@ -0,0 +1,12 @@
+obj-$(CONFIG_VIDEO_FIMC) += fimc_dev.o fimc_v4l2.o fimc_capture.o fimc_output.o fimc_overlay.o fimc_regs.o
+obj-$(CONFIG_VIDEO_FIMC_MIPI) += csis.o
+
+ifeq ($(CONFIG_CPU_S5PV210),y)
+EXTRA_CFLAGS += -DCONFIG_MIPI_CSI_ADV_FEATURE
+endif
+
+EXTRA_CFLAGS += -Idrivers/media/video
+
+ifeq ($(CONFIG_VIDEO_FIMC_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
diff --git a/drivers/media/video/samsung/fimc/csis.c b/drivers/media/video/samsung/fimc/csis.c
new file mode 100644
index 0000000..f512d10
--- /dev/null
+++ b/drivers/media/video/samsung/fimc/csis.c
@@ -0,0 +1,431 @@
+/* linux/drivers/media/video/samsung/csis.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co,. Ltd.
+ * http://www.samsung.com/
+ *
+ * MIPI-CSI2 Support file for FIMC driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/clk.h>
+#include <linux/fs.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/videodev2.h>
+#include <linux/slab.h>
+
+#include <linux/io.h>
+#include <linux/memory.h>
+#include <plat/clock.h>
+#include <plat/regs-csis.h>
+#include <plat/csis.h>
+#include "csis.h"
+
+static struct s3c_csis_info *s3c_csis;
+
+static struct s3c_platform_csis *to_csis_plat(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+
+ return (struct s3c_platform_csis *) pdev->dev.platform_data;
+}
+
+static int s3c_csis_set_info(void)
+{
+ s3c_csis = (struct s3c_csis_info *) \
+ kmalloc(sizeof(struct s3c_csis_info), GFP_KERNEL);
+ if (!s3c_csis) {
+ err("no memory for configuration\n");
+ return -ENOMEM;
+ }
+
+ strcpy(s3c_csis->name, S3C_CSIS_NAME);
+ s3c_csis->nr_lanes = S3C_CSIS_NR_LANES;
+
+ return 0;
+}
+
+static void s3c_csis_reset(void)
+{
+ u32 cfg;
+
+ cfg = readl(s3c_csis->regs + S3C_CSIS_CONTROL);
+ cfg |= S3C_CSIS_CONTROL_RESET;
+ writel(cfg, s3c_csis->regs + S3C_CSIS_CONTROL);
+}
+
+static void s3c_csis_set_nr_lanes(int lanes)
+{
+ u32 cfg;
+
+ cfg = readl(s3c_csis->regs + S3C_CSIS_CONFIG);
+ cfg &= ~S3C_CSIS_CONFIG_NR_LANE_MASK;
+
+ if (lanes == 1)
+ cfg |= S3C_CSIS_CONFIG_NR_LANE_1;
+ else
+ cfg |= S3C_CSIS_CONFIG_NR_LANE_2;
+
+ writel(cfg, s3c_csis->regs + S3C_CSIS_CONFIG);
+}
+
+static void s3c_csis_enable_interrupt(void)
+{
+ u32 cfg = 0;
+
+ /* enable all interrupts */
+ cfg |= S3C_CSIS_INTMSK_EVEN_BEFORE_ENABLE | \
+ S3C_CSIS_INTMSK_EVEN_AFTER_ENABLE | \
+ S3C_CSIS_INTMSK_ODD_BEFORE_ENABLE | \
+ S3C_CSIS_INTMSK_ODD_AFTER_ENABLE | \
+ S3C_CSIS_INTMSK_ERR_SOT_HS_ENABLE | \
+ S3C_CSIS_INTMSK_ERR_ESC_ENABLE | \
+ S3C_CSIS_INTMSK_ERR_CTRL_ENABLE | \
+ S3C_CSIS_INTMSK_ERR_ECC_ENABLE | \
+ S3C_CSIS_INTMSK_ERR_CRC_ENABLE | \
+ S3C_CSIS_INTMSK_ERR_ID_ENABLE;
+
+ writel(cfg, s3c_csis->regs + S3C_CSIS_INTMSK);
+}
+
+static void s3c_csis_disable_interrupt(void)
+{
+ /* disable all interrupts */
+ writel(0, s3c_csis->regs + S3C_CSIS_INTMSK);
+}
+
+static void s3c_csis_system_on(void)
+{
+ u32 cfg;
+
+ cfg = readl(s3c_csis->regs + S3C_CSIS_CONTROL);
+ cfg |= S3C_CSIS_CONTROL_ENABLE;
+ writel(cfg, s3c_csis->regs + S3C_CSIS_CONTROL);
+}
+
+static void s3c_csis_system_off(void)
+{
+ u32 cfg;
+
+ cfg = readl(s3c_csis->regs + S3C_CSIS_CONTROL);
+ cfg &= ~S3C_CSIS_CONTROL_ENABLE;
+ writel(cfg, s3c_csis->regs + S3C_CSIS_CONTROL);
+}
+
+static void s3c_csis_phy_on(void)
+{
+ u32 cfg;
+ cfg = readl(s3c_csis->regs + S3C_CSIS_DPHYCTRL);
+ cfg |= S3C_CSIS_DPHYCTRL_ENABLE;
+ writel(cfg, s3c_csis->regs + S3C_CSIS_DPHYCTRL);
+}
+
+static void s3c_csis_phy_off(void)
+{
+ u32 cfg;
+
+ cfg = readl(s3c_csis->regs + S3C_CSIS_DPHYCTRL);
+ cfg &= ~S3C_CSIS_DPHYCTRL_ENABLE;
+ writel(cfg, s3c_csis->regs + S3C_CSIS_DPHYCTRL);
+}
+
+#ifdef CONFIG_MIPI_CSI_ADV_FEATURE
+static void s3c_csis_update_shadow(void)
+{
+ u32 cfg;
+
+ cfg = readl(s3c_csis->regs + S3C_CSIS_CONTROL);
+ cfg |= S3C_CSIS_CONTROL_UPDATE_SHADOW;
+ writel(cfg, s3c_csis->regs + S3C_CSIS_CONTROL);
+}
+
+static void s3c_csis_set_data_align(int align)
+{
+ u32 cfg;
+
+ cfg = readl(s3c_csis->regs + S3C_CSIS_CONTROL);
+ cfg &= ~S3C_CSIS_CONTROL_ALIGN_MASK;
+
+ if (align == 24)
+ cfg |= S3C_CSIS_CONTROL_ALIGN_24BIT;
+ else
+ cfg |= S3C_CSIS_CONTROL_ALIGN_32BIT;
+
+ writel(cfg, s3c_csis->regs + S3C_CSIS_CONTROL);
+}
+
+static void s3c_csis_set_wclk(int extclk)
+{
+ u32 cfg;
+
+ cfg = readl(s3c_csis->regs + S3C_CSIS_CONTROL);
+ cfg &= ~S3C_CSIS_CONTROL_WCLK_MASK;
+
+ if (extclk)
+ cfg |= S3C_CSIS_CONTROL_WCLK_EXTCLK;
+ else
+ cfg |= S3C_CSIS_CONTROL_WCLK_PCLK;
+
+ writel(cfg, s3c_csis->regs + S3C_CSIS_CONTROL);
+}
+
+static void s3c_csis_set_format(enum mipi_format fmt)
+{
+ u32 cfg;
+
+ cfg = readl(s3c_csis->regs + S3C_CSIS_CONFIG);
+ cfg &= ~S3C_CSIS_CONFIG_FORMAT_MASK;
+ cfg |= (fmt << S3C_CSIS_CONFIG_FORMAT_SHIFT);
+
+ writel(cfg, s3c_csis->regs + S3C_CSIS_CONFIG);
+}
+
+static void s3c_csis_set_resol(int width, int height)
+{
+ u32 cfg = 0;
+
+ cfg |= width << S3C_CSIS_RESOL_HOR_SHIFT;
+ cfg |= height << S3C_CSIS_RESOL_VER_SHIFT;
+
+ writel(cfg, s3c_csis->regs + S3C_CSIS_RESOL);
+}
+
+static void s3c_csis_set_hs_settle(int settle)
+{
+ u32 cfg;
+
+ cfg = readl(s3c_csis->regs + S3C_CSIS_DPHYCTRL);
+ cfg &= ~S3C_CSIS_DPHYCTRL_HS_SETTLE_MASK;
+ cfg |= (settle << S3C_CSIS_DPHYCTRL_HS_SETTLE_SHIFT);
+
+ writel(cfg, s3c_csis->regs + S3C_CSIS_DPHYCTRL);
+}
+#endif
+
+void s3c_csis_start(int lanes, int settle, int align, int width,
+ int height, int pixel_format)
+{
+ struct platform_device *pdev = to_platform_device(s3c_csis->dev);
+ struct s3c_platform_csis *pdata;
+
+ pdata = to_csis_plat(s3c_csis->dev);
+ if (pdata->cfg_phy_global)
+ pdata->cfg_phy_global(pdev, 1);
+
+ s3c_csis_reset();
+ s3c_csis_set_nr_lanes(lanes);
+
+#ifdef CONFIG_MIPI_CSI_ADV_FEATURE
+ /* FIXME: how configure the followings with FIMC dynamically? */
+ s3c_csis_set_hs_settle(settle); /* s5k6aa */
+ s3c_csis_set_data_align(align);
+ s3c_csis_set_wclk(0);
+ if (pixel_format == V4L2_PIX_FMT_JPEG)
+ s3c_csis_set_format(MIPI_USER_DEF_PACKET_1);
+ else
+ s3c_csis_set_format(MIPI_CSI_YCBCR422_8BIT);
+ s3c_csis_set_resol(width, height);
+ s3c_csis_update_shadow();
+#endif
+
+ s3c_csis_enable_interrupt();
+ s3c_csis_system_on();
+ s3c_csis_phy_on();
+
+ info("Samsung MIPI-CSI2 operation started\n");
+}
+
+static void s3c_csis_stop(struct platform_device *pdev)
+{
+ struct s3c_platform_csis *plat;
+
+ s3c_csis_disable_interrupt();
+ s3c_csis_system_off();
+ s3c_csis_phy_off();
+
+ plat = to_csis_plat(&pdev->dev);
+ if (plat->cfg_phy_global)
+ plat->cfg_phy_global(pdev, 0);
+}
+
+static irqreturn_t s3c_csis_irq(int irq, void *dev_id)
+{
+ u32 cfg;
+
+ /* just clearing the pends */
+ cfg = readl(s3c_csis->regs + S3C_CSIS_INTSRC);
+ writel(cfg, s3c_csis->regs + S3C_CSIS_INTSRC);
+
+ return IRQ_HANDLED;
+}
+
+static int s3c_csis_clk_on(struct platform_device *pdev)
+{
+ struct s3c_platform_csis *pdata;
+ struct clk *parent, *mout_csis;
+
+ pdata = to_csis_plat(&pdev->dev);
+
+ /* mout_mpll */
+ parent = clk_get(&pdev->dev, pdata->srclk_name);
+ if (IS_ERR(parent)) {
+ err("failed to get parent clock for csis\n");
+ return -EINVAL;
+ }
+
+ /* mout_csis */
+ mout_csis = clk_get(&pdev->dev, "mout_csis");
+
+ /* sclk_csis */
+ s3c_csis->clock = clk_get(&pdev->dev, pdata->clk_name);
+ if (IS_ERR(s3c_csis->clock)) {
+ err("failed to get csis clock source\n");
+ return -EINVAL;
+ }
+
+ clk_set_parent(mout_csis, parent);
+ clk_set_parent(s3c_csis->clock, mout_csis);
+
+ /* Turn on csis power domain regulator */
+ regulator_enable(s3c_csis->regulator);
+ /* clock enable for csis */
+ clk_enable(s3c_csis->clock);
+
+ return 0;
+}
+
+static int s3c_csis_clk_off(struct platform_device *pdev)
+{
+ struct s3c_platform_csis *plat;
+
+ plat = to_csis_plat(&pdev->dev);
+
+ /* sclk_csis */
+ s3c_csis->clock = clk_get(&pdev->dev, plat->clk_name);
+ if (IS_ERR(s3c_csis->clock)) {
+ err("failed to get csis clock source\n");
+ return -EINVAL;
+ }
+
+ /* clock disable for csis */
+ clk_disable(s3c_csis->clock);
+ /* Turn off csis power domain regulator */
+ regulator_disable(s3c_csis->regulator);
+
+ return 0;
+}
+
+static int s3c_csis_probe(struct platform_device *pdev)
+{
+ struct s3c_platform_csis *pdata;
+ struct resource *res;
+
+ s3c_csis_set_info();
+
+ s3c_csis->dev = &pdev->dev;
+
+ pdata = to_csis_plat(&pdev->dev);
+ if (pdata->cfg_gpio)
+ pdata->cfg_gpio();
+
+ /* Get csis power domain regulator */
+ s3c_csis->regulator = regulator_get(&pdev->dev, "pd");
+ if (IS_ERR(s3c_csis->regulator)) {
+ err("%s: failed to get resource %s\n",
+ __func__, "s3c-csis");
+ return PTR_ERR(s3c_csis->regulator);
+ }
+ /* clock & power on */
+ s3c_csis_clk_on(pdev);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ err("failed to get io memory region\n");
+ return -EINVAL;
+ }
+
+ res = request_mem_region(res->start,
+ res->end - res->start + 1, pdev->name);
+ if (!res) {
+ err("failed to request io memory region\n");
+ return -EINVAL;
+ }
+
+ /* ioremap for register block */
+ s3c_csis->regs = ioremap(res->start, res->end - res->start + 1);
+ if (!s3c_csis->regs) {
+ err("failed to remap io region\n");
+ return -EINVAL;
+ }
+
+ /* irq */
+ s3c_csis->irq = platform_get_irq(pdev, 0);
+ if (request_irq(s3c_csis->irq, s3c_csis_irq, IRQF_DISABLED, \
+ s3c_csis->name, s3c_csis))
+ err("request_irq failed\n");
+
+ info("Samsung MIPI-CSI2 driver probed successfully\n");
+
+ return 0;
+}
+
+static int s3c_csis_remove(struct platform_device *pdev)
+{
+ s3c_csis_stop(pdev);
+ kfree(s3c_csis);
+
+ return 0;
+}
+
+/* sleep */
+int s3c_csis_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ s3c_csis_clk_off(pdev);
+ return 0;
+}
+
+/* wakeup */
+int s3c_csis_resume(struct platform_device *pdev)
+{
+ s3c_csis_clk_on(pdev);
+ return 0;
+}
+
+static struct platform_driver s3c_csis_driver = {
+ .probe = s3c_csis_probe,
+ .remove = s3c_csis_remove,
+ .suspend = s3c_csis_suspend,
+ .resume = s3c_csis_resume,
+ .driver = {
+ .name = "s5p-mipi-csis",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int s3c_csis_register(void)
+{
+ platform_driver_register(&s3c_csis_driver);
+
+ return 0;
+}
+
+static void s3c_csis_unregister(void)
+{
+ platform_driver_unregister(&s3c_csis_driver);
+}
+
+module_init(s3c_csis_register);
+module_exit(s3c_csis_unregister);
+
+MODULE_AUTHOR("Jinsung, Yang <jsgood.yang@samsung.com>");
+MODULE_AUTHOR("Sewoon, Park <seuni.park@samsung.com>");
+MODULE_DESCRIPTION("MIPI-CSI2 support for FIMC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/samsung/fimc/csis.h b/drivers/media/video/samsung/fimc/csis.h
new file mode 100644
index 0000000..4943c8f
--- /dev/null
+++ b/drivers/media/video/samsung/fimc/csis.h
@@ -0,0 +1,42 @@
+/* linux/drivers/media/video/samsung/csis.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co,. Ltd.
+ * http://www.samsung.com/
+ *
+ * Header file for Samsung MIPI-CSI2 driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __CSIS_H
+#define __CSIS_H __FILE__
+
+#define S3C_CSIS_NAME "s5p-mipi-csis"
+#define S3C_CSIS_NR_LANES 1
+
+#define info(args...) \
+ do { printk(KERN_INFO S3C_CSIS_NAME ": " args); } while (0)
+#define err(args...) \
+ do { printk(KERN_ERR S3C_CSIS_NAME ": " args); } while (0)
+
+enum mipi_format {
+ MIPI_CSI_YCBCR422_8BIT = 0x1e,
+ MIPI_CSI_RAW8 = 0x2a,
+ MIPI_CSI_RAW10 = 0x2b,
+ MIPI_CSI_RAW12 = 0x2c,
+ MIPI_USER_DEF_PACKET_1 = 0x30, /* User defined Byte-based packet 1 */
+};
+
+struct s3c_csis_info {
+ char name[16];
+ struct device *dev;
+ struct clk *clock;
+ struct regulator *regulator;
+ void __iomem *regs;
+ int irq;
+ int nr_lanes;
+};
+
+#endif /* __CSIS_H */
diff --git a/drivers/media/video/samsung/fimc/fimc.h b/drivers/media/video/samsung/fimc/fimc.h
new file mode 100644
index 0000000..de137c2
--- /dev/null
+++ b/drivers/media/video/samsung/fimc/fimc.h
@@ -0,0 +1,707 @@
+/* linux/drivers/media/video/samsung/fimc/fimc.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Header file for Samsung Camera Interface (FIMC) driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+
+#ifndef __FIMC_H
+#define __FIMC_H __FILE__
+
+#ifdef __KERNEL__
+#include <linux/wait.h>
+#include <linux/mutex.h>
+#include <linux/i2c.h>
+#include <linux/fb.h>
+#include <linux/videodev2.h>
+#include <linux/platform_device.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/videobuf-core.h>
+#include <plat/media.h>
+#include <plat/fimc.h>
+#endif
+
+#define FIMC_NAME "s3c-fimc"
+
+#define FIMC_DEVICES 3
+#define FIMC_SUBDEVS 3
+#define FIMC_MAXCAMS 5 /* added 1 because of WriteBack */
+#define FIMC_PHYBUFS 4
+#define FIMC_OUTBUFS 3
+#define FIMC_INQUEUES 10
+#define FIMC_MAX_CTXS 1
+#define FIMC_TPID 3
+#define FIMC_CAPBUFS 16
+#define FIMC_ONESHOT_TIMEOUT 200
+#define FIMC_DQUEUE_TIMEOUT 200
+#define FIMC_FIFOOFF_CNT 1000000 /* Sufficiently big value for stop */
+
+#define FORMAT_FLAGS_PACKED 0x1
+#define FORMAT_FLAGS_PLANAR 0x2
+#define FORMAT_FLAGS_ENCODED 0x3
+
+#define FIMC_ADDR_Y 0
+#define FIMC_ADDR_CB 1
+#define FIMC_ADDR_CR 2
+
+#define FIMC_HD_WIDTH 1280
+#define FIMC_HD_HEIGHT 720
+
+#define FIMC_FHD_WIDTH 1920
+#define FIMC_FHD_HEIGHT 1080
+
+#define FIMC_MMAP_IDX -1
+#define FIMC_USERPTR_IDX -2
+
+#define FIMC_HCLK 0
+#define FIMC_SCLK 1
+#define FIMC_OVLY_MODE FIMC_OVLY_DMA_AUTO
+
+#define FIMC_PINGPONG 2
+
+/*
+ * ENUMERATIONS
+*/
+enum fimc_status {
+ FIMC_READY_OFF = 0x00,
+ FIMC_STREAMOFF = 0x01,
+ FIMC_READY_ON = 0x02,
+ FIMC_STREAMON = 0x03,
+ FIMC_STREAMON_IDLE = 0x04, /* oneshot mode */
+ FIMC_OFF_SLEEP = 0x05,
+ FIMC_ON_SLEEP = 0x06,
+ FIMC_ON_IDLE_SLEEP = 0x07, /* oneshot mode */
+ FIMC_READY_RESUME = 0x08,
+};
+
+enum fimc_fifo_state {
+ FIFO_CLOSE,
+ FIFO_SLEEP,
+};
+
+enum fimc_fimd_state {
+ FIMD_OFF,
+ FIMD_ON,
+};
+
+enum fimc_rot_flip {
+ FIMC_XFLIP = 0x01,
+ FIMC_YFLIP = 0x02,
+ FIMC_ROT = 0x10,
+};
+
+enum fimc_input {
+ FIMC_SRC_CAM,
+ FIMC_SRC_MSDMA,
+};
+
+enum fimc_overlay_mode {
+ /* Overlay mode isn't fixed. */
+ FIMC_OVLY_NOT_FIXED = 0x0,
+ /* Non-destructive Overlay with DMA */
+ FIMC_OVLY_DMA_AUTO = 0x1,
+ /* Non-destructive Overlay with DMA */
+ FIMC_OVLY_DMA_MANUAL = 0x2,
+ /* Destructive Overlay with DMA single destination buffer */
+ FIMC_OVLY_NONE_SINGLE_BUF = 0x3,
+ /* Destructive Overlay with DMA multiple dstination buffer */
+ FIMC_OVLY_NONE_MULTI_BUF = 0x4,
+};
+
+enum fimc_autoload {
+ FIMC_AUTO_LOAD,
+ FIMC_ONE_SHOT,
+};
+
+enum fimc_log {
+ FIMC_LOG_DEBUG = 0x1000,
+ FIMC_LOG_INFO_L2 = 0x0200,
+ FIMC_LOG_INFO_L1 = 0x0100,
+ FIMC_LOG_WARN = 0x0010,
+ FIMC_LOG_ERR = 0x0001,
+};
+
+enum fimc_pixel_format_type{
+ FIMC_RGB,
+ FIMC_YUV420,
+ FIMC_YUV422,
+ FIMC_YUV444,
+};
+
+/*
+ * STRUCTURES
+*/
+
+/* for reserved memory */
+struct fimc_meminfo {
+ dma_addr_t base; /* buffer base */
+ size_t size; /* total length */
+ dma_addr_t curr; /* current addr */
+};
+
+struct fimc_buf {
+ dma_addr_t base[3];
+ size_t length[3];
+};
+
+struct fimc_overlay_buf {
+ u32 vir_addr[3];
+ size_t size[3];
+ u32 phy_addr[3];
+};
+
+struct fimc_overlay {
+ enum fimc_overlay_mode mode;
+ struct fimc_overlay_buf buf;
+ s32 req_idx;
+ int fb_id;
+};
+
+/* general buffer */
+struct fimc_buf_set {
+ int id;
+ /* Plane 0/1/2 for raw data, Plane 3 for padding buffer (if required) */
+ dma_addr_t base[4];
+ size_t length[4];
+ size_t garbage[4];
+ enum videobuf_state state;
+ u32 flags;
+ atomic_t mapped_cnt;
+ struct list_head list;
+};
+
+/* for capture device */
+struct fimc_capinfo {
+ struct v4l2_cropcap cropcap;
+ struct v4l2_rect crop;
+ struct v4l2_pix_format fmt;
+ struct fimc_buf_set bufs[FIMC_CAPBUFS];
+ struct list_head inq;
+ int outq[FIMC_PHYBUFS];
+ int nr_bufs;
+ int irq;
+ int lastirq;
+
+ /* flip: V4L2_CID_xFLIP, rotate: 90, 180, 270 */
+ u32 flip;
+ u32 rotate;
+};
+
+/* for output overlay device */
+struct fimc_idx {
+ int ctx;
+ int idx;
+};
+
+struct fimc_ctx_idx {
+ struct fimc_idx prev;
+ struct fimc_idx active;
+ struct fimc_idx next;
+};
+
+/* scaler abstraction: local use recommended */
+struct fimc_scaler {
+ u32 bypass;
+ u32 hfactor;
+ u32 vfactor;
+ u32 pre_hratio;
+ u32 pre_vratio;
+ u32 pre_dst_width;
+ u32 pre_dst_height;
+ u32 scaleup_h;
+ u32 scaleup_v;
+ u32 main_hratio;
+ u32 main_vratio;
+ u32 real_width;
+ u32 real_height;
+ u32 shfactor;
+ u32 skipline;
+};
+
+struct fimc_ctx {
+ u32 ctx_num;
+ struct v4l2_cropcap cropcap;
+ struct v4l2_rect crop;
+ struct v4l2_pix_format pix;
+ struct v4l2_window win;
+ struct v4l2_framebuffer fbuf;
+ struct fimc_scaler sc;
+ struct fimc_overlay overlay;
+
+ u32 buf_num;
+ u32 is_requested;
+ struct fimc_buf_set src[FIMC_OUTBUFS];
+ struct fimc_buf_set dst[FIMC_OUTBUFS];
+ s32 inq[FIMC_OUTBUFS];
+ s32 outq[FIMC_OUTBUFS];
+
+ u32 flip;
+ u32 rotate;
+ enum fimc_status status;
+};
+
+struct fimc_outinfo {
+ int last_ctx;
+ spinlock_t lock_in;
+ spinlock_t lock_out;
+ struct fimc_idx inq[FIMC_INQUEUES];
+ struct fimc_ctx ctx[FIMC_MAX_CTXS];
+ struct fimc_ctx_idx idxs;
+};
+
+struct s3cfb_user_window {
+ int x;
+ int y;
+};
+
+enum s3cfb_data_path_t {
+ DATA_PATH_FIFO = 0,
+ DATA_PATH_DMA = 1,
+ DATA_PATH_IPC = 2,
+};
+
+enum s3cfb_mem_owner_t {
+ DMA_MEM_NONE = 0,
+ DMA_MEM_FIMD = 1,
+ DMA_MEM_OTHER = 2,
+};
+
+enum s3cfb_alpha_t {
+ PLANE_BLENDING,
+ PIXEL_BLENDING,
+};
+
+enum s3cfb_chroma_dir_t {
+ CHROMA_FG,
+ CHROMA_BG,
+};
+
+struct s3cfb_alpha {
+ enum s3cfb_alpha_t mode;
+ int channel;
+ unsigned int value;
+};
+
+
+struct s3cfb_chroma {
+ int enabled;
+ int blended;
+ unsigned int key;
+ unsigned int comp_key;
+ unsigned int alpha;
+ enum s3cfb_chroma_dir_t dir;
+};
+
+struct s3cfb_window {
+ int id;
+ int enabled;
+ atomic_t in_use;
+ int x;
+ int y;
+ enum s3cfb_data_path_t path;
+ enum s3cfb_mem_owner_t owner;
+ unsigned int other_mem_addr;
+ unsigned int other_mem_size;
+ int local_channel;
+ int dma_burst;
+ unsigned int pseudo_pal[16];
+ struct s3cfb_alpha alpha;
+ struct s3cfb_chroma chroma;
+};
+
+#define S3CFB_WIN_OFF_ALL _IO('F', 202)
+#define S3CFB_WIN_POSITION _IOW('F', 203, struct s3cfb_user_window)
+#define S3CFB_GET_LCD_WIDTH _IOR('F', 302, int)
+#define S3CFB_GET_LCD_HEIGHT _IOR('F', 303, int)
+#define S3CFB_SET_WRITEBACK _IOW('F', 304, u32)
+#define S3CFB_SET_WIN_ON _IOW('F', 306, u32)
+#define S3CFB_SET_WIN_OFF _IOW('F', 307, u32)
+#define S3CFB_SET_WIN_PATH _IOW('F', 308, enum s3cfb_data_path_t)
+#define S3CFB_SET_WIN_ADDR _IOW('F', 309, unsigned long)
+#define S3CFB_SET_WIN_MEM _IOW('F', 310, enum s3cfb_mem_owner_t)
+/* ------------------------------------------------------------------------ */
+
+struct fimc_fbinfo {
+ struct fb_fix_screeninfo *fix;
+ struct fb_var_screeninfo *var;
+ int lcd_hres;
+ int lcd_vres;
+ u32 is_enable;
+};
+
+struct fimc_limit {
+ u32 pre_dst_w;
+ u32 bypass_w;
+ u32 trg_h_no_rot;
+ u32 trg_h_rot;
+ u32 real_w_no_rot;
+ u32 real_h_rot;
+};
+
+enum FIMC_EFFECT_FIN {
+ FIMC_EFFECT_FIN_BYPASS = 0,
+ FIMC_EFFECT_FIN_ARBITRARY_CBCR,
+ FIMC_EFFECT_FIN_NEGATIVE,
+ FIMC_EFFECT_FIN_ART_FREEZE,
+ FIMC_EFFECT_FIN_EMBOSSING,
+ FIMC_EFFECT_FIN_SILHOUETTE,
+};
+
+
+struct fimc_effect {
+ int ie_on;
+ int ie_after_sc;
+ enum FIMC_EFFECT_FIN fin;
+ int pat_cb;
+ int pat_cr;
+};
+
+/* fimc controller abstration */
+struct fimc_control {
+ int id; /* controller id */
+ char name[16];
+ atomic_t in_use;
+ void __iomem *regs; /* register i/o */
+ struct clk *clk; /* interface clock */
+ struct regulator *regulator; /* pd regulator */
+ struct fimc_meminfo mem; /* for reserved mem */
+
+ /* kernel helpers */
+ struct mutex lock; /* controller lock */
+ struct mutex alloc_lock;
+ struct mutex v4l2_lock;
+ wait_queue_head_t wq;
+ struct device *dev;
+ int irq;
+
+ /* v4l2 related */
+ struct video_device *vd;
+ struct v4l2_device v4l2_dev;
+
+ /* fimc specific */
+ struct fimc_limit *limit; /* H/W limitation */
+ struct s3c_platform_camera *cam; /* activated camera */
+ struct fimc_capinfo *cap; /* capture dev info */
+ struct fimc_outinfo *out; /* output dev info */
+ struct fimc_fbinfo fb; /* fimd info */
+ struct fimc_scaler sc; /* scaler info */
+ struct fimc_effect fe; /* fimc effect info */
+
+ enum fimc_status status;
+ enum fimc_log log;
+
+ u32 ctx_busy[FIMC_MAX_CTXS];
+};
+
+/* global */
+struct fimc_global {
+ struct fimc_control ctrl[FIMC_DEVICES];
+ struct s3c_platform_camera camera[FIMC_MAXCAMS];
+ int camera_isvalid[FIMC_MAXCAMS];
+ int active_camera;
+ int initialized;
+};
+
+struct fimc_prv_data {
+ struct fimc_control *ctrl;
+ int ctx_id;
+};
+
+/* debug macro */
+#define FIMC_LOG_DEFAULT (FIMC_LOG_WARN | FIMC_LOG_ERR)
+
+#define FIMC_DEBUG(fmt, ...) \
+ do { \
+ if (ctrl->log & FIMC_LOG_DEBUG) \
+ printk(KERN_DEBUG FIMC_NAME "-%d : " \
+ fmt, ctrl->id, ##__VA_ARGS__); \
+ } while (0)
+
+#define FIMC_INFO_L2(fmt, ...) \
+ do { \
+ if (ctrl->log & FIMC_LOG_INFO_L2) \
+ printk(KERN_INFO FIMC_NAME "-%d : " \
+ fmt, ctrl->id, ##__VA_ARGS__); \
+ } while (0)
+
+#define FIMC_INFO_L1(fmt, ...) \
+ do { \
+ if (ctrl->log & FIMC_LOG_INFO_L1) \
+ printk(KERN_INFO FIMC_NAME "-%d : " \
+ fmt, ctrl->id, ##__VA_ARGS__); \
+ } while (0)
+
+#define FIMC_WARN(fmt, ...) \
+ do { \
+ if (ctrl->log & FIMC_LOG_WARN) \
+ printk(KERN_WARNING FIMC_NAME "-%d : " \
+ fmt, ctrl->id, ##__VA_ARGS__); \
+ } while (0)
+
+
+#define FIMC_ERROR(fmt, ...) \
+ do { \
+ if (ctrl->log & FIMC_LOG_ERR) \
+ printk(KERN_ERR FIMC_NAME "-%d : " \
+ fmt, ctrl->id, ##__VA_ARGS__); \
+ } while (0)
+
+
+#define fimc_dbg(fmt, ...) FIMC_DEBUG(fmt, ##__VA_ARGS__)
+#define fimc_info2(fmt, ...) FIMC_INFO_L2(fmt, ##__VA_ARGS__)
+#define fimc_info1(fmt, ...) FIMC_INFO_L1(fmt, ##__VA_ARGS__)
+#define fimc_warn(fmt, ...) FIMC_WARN(fmt, ##__VA_ARGS__)
+#define fimc_err(fmt, ...) FIMC_ERROR(fmt, ##__VA_ARGS__)
+
+/*
+ * EXTERNS
+*/
+extern struct fimc_global *fimc_dev;
+extern struct video_device fimc_video_device[FIMC_DEVICES];
+extern const struct v4l2_ioctl_ops fimc_v4l2_ops;
+extern struct fimc_limit fimc40_limits[FIMC_DEVICES];
+extern struct fimc_limit fimc43_limits[FIMC_DEVICES];
+extern struct fimc_limit fimc50_limits[FIMC_DEVICES];
+
+/* general */
+extern void s3c_csis_start(int lanes, int settle, int align,
+ int width, int height,
+ int pixel_format);
+extern int fimc_dma_alloc(struct fimc_control *ctrl,
+ struct fimc_buf_set *bs,
+ int i, int align);
+extern void fimc_dma_free(struct fimc_control *ctrl,
+ struct fimc_buf_set *bs, int i);
+extern u32 fimc_mapping_rot_flip(u32 rot, u32 flip);
+extern int fimc_get_scaler_factor(u32 src, u32 tar, u32 *ratio, u32 *shift);
+extern void fimc_get_nv12t_size(int img_hres, int img_vres,
+ int *y_size, int *cb_size);
+extern void fimc_clk_en(struct fimc_control *ctrl, bool on);
+
+/* camera */
+extern int fimc_select_camera(struct fimc_control *ctrl);
+
+/* capture device */
+extern int fimc_enum_input(struct file *file, void *fh,
+ struct v4l2_input *inp);
+extern int fimc_g_input(struct file *file, void *fh, unsigned int *i);
+extern int fimc_s_input(struct file *file, void *fh, unsigned int i);
+extern int fimc_enum_fmt_vid_capture(struct file *file, void *fh,
+ struct v4l2_fmtdesc *f);
+extern int fimc_g_fmt_vid_capture(struct file *file, void *fh,
+ struct v4l2_format *f);
+extern int fimc_s_fmt_vid_capture(struct file *file, void *fh,
+ struct v4l2_format *f);
+extern int fimc_try_fmt_vid_capture(struct file *file, void *fh,
+ struct v4l2_format *f);
+extern int fimc_reqbufs_capture(void *fh, struct v4l2_requestbuffers *b);
+extern int fimc_querybuf_capture(void *fh, struct v4l2_buffer *b);
+extern int fimc_g_ctrl_capture(void *fh, struct v4l2_control *c);
+extern int fimc_s_ctrl_capture(void *fh, struct v4l2_control *c);
+extern int fimc_s_ext_ctrls_capture(void *fh, struct v4l2_ext_controls *c);
+extern int fimc_cropcap_capture(void *fh, struct v4l2_cropcap *a);
+extern int fimc_g_crop_capture(void *fh, struct v4l2_crop *a);
+extern int fimc_s_crop_capture(void *fh, struct v4l2_crop *a);
+extern int fimc_streamon_capture(void *fh);
+extern int fimc_streamoff_capture(void *fh);
+extern int fimc_qbuf_capture(void *fh, struct v4l2_buffer *b);
+extern int fimc_dqbuf_capture(void *fh, struct v4l2_buffer *b);
+extern int fimc_g_parm(struct file *file, void *fh,
+ struct v4l2_streamparm *a);
+extern int fimc_s_parm(struct file *file, void *fh,
+ struct v4l2_streamparm *a);
+extern int fimc_queryctrl(struct file *file, void *fh,
+ struct v4l2_queryctrl *qc);
+extern int fimc_querymenu(struct file *file, void *fh,
+ struct v4l2_querymenu *qm);
+
+#if defined(CONFIG_CPU_S5PV210)
+extern int fimc_change_clksrc(struct fimc_control *ctrl, int fimc_clk);
+#endif
+extern int fimc_release_subdev(struct fimc_control *ctrl);
+
+/* output device */
+extern void fimc_outdev_set_src_addr(struct fimc_control *ctrl,
+ dma_addr_t *base);
+extern int fimc_outdev_set_ctx_param(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx);
+extern int fimc_start_fifo(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx);
+extern int fimc_fimd_rect(const struct fimc_control *ctrl,
+ const struct fimc_ctx *ctx,
+ struct v4l2_rect *fimd_rect);
+extern int fimc_outdev_stop_streaming(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx);
+extern int fimc_outdev_resume_dma(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx);
+extern int fimc_outdev_start_camif(void *param);
+extern int fimc_reqbufs_output(void *fh, struct v4l2_requestbuffers *b);
+extern int fimc_querybuf_output(void *fh, struct v4l2_buffer *b);
+extern int fimc_g_ctrl_output(void *fh, struct v4l2_control *c);
+extern int fimc_s_ctrl_output(struct file *filp, void *fh,
+ struct v4l2_control *c);
+extern int fimc_cropcap_output(void *fh, struct v4l2_cropcap *a);
+extern int fimc_g_crop_output(void *fh, struct v4l2_crop *a);
+extern int fimc_s_crop_output(void *fh, struct v4l2_crop *a);
+extern int fimc_streamon_output(void *fh);
+extern int fimc_streamoff_output(void *fh);
+extern int fimc_qbuf_output(void *fh, struct v4l2_buffer *b);
+extern int fimc_dqbuf_output(void *fh, struct v4l2_buffer *b);
+extern int fimc_g_fmt_vid_out(struct file *filp, void *fh,
+ struct v4l2_format *f);
+extern int fimc_s_fmt_vid_out(struct file *filp, void *fh,
+ struct v4l2_format *f);
+extern int fimc_try_fmt_vid_out(struct file *filp, void *fh,
+ struct v4l2_format *f);
+extern int fimc_output_set_dst_addr(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx, int idx);
+extern int fimc_init_in_queue(struct fimc_control *ctrl, struct fimc_ctx *ctx);
+extern int fimc_push_inq(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx, int idx);
+extern int fimc_pop_inq(struct fimc_control *ctrl, int *ctx_num, int *idx);
+extern int fimc_push_outq(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx, int idx);
+extern int fimc_pop_outq(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx, int *idx);
+extern int fimc_init_out_queue(struct fimc_control *ctrl, struct fimc_ctx *ctx);
+extern void fimc_outdev_init_idxs(struct fimc_control *ctrl);
+
+extern void fimc_dump_context(struct fimc_control *ctrl, struct fimc_ctx *ctx);
+extern void fimc_print_signal(struct fimc_control *ctrl);
+
+/* overlay device */
+extern int fimc_try_fmt_overlay(struct file *filp, void *fh,
+ struct v4l2_format *f);
+extern int fimc_g_fmt_vid_overlay(struct file *filp, void *fh,
+ struct v4l2_format *f);
+extern int fimc_s_fmt_vid_overlay(struct file *filp, void *fh,
+ struct v4l2_format *f);
+extern int fimc_g_fbuf(struct file *filp, void *fh,
+ struct v4l2_framebuffer *fb);
+extern int fimc_s_fbuf(struct file *filp, void *fh,
+ struct v4l2_framebuffer *fb);
+
+/* Register access file */
+extern void fimc_reset(struct fimc_control *ctrl);
+extern int fimc_hwset_camera_source(struct fimc_control *ctrl);
+extern int fimc_hwset_enable_irq(struct fimc_control *ctrl,
+ int overflow, int level);
+extern int fimc_hwset_disable_irq(struct fimc_control *ctrl);
+extern int fimc_hwset_clear_irq(struct fimc_control *ctrl);
+extern int fimc_hwset_reset(struct fimc_control *ctrl);
+extern int fimc_hwset_sw_reset(struct fimc_control *ctrl);
+extern int fimc_hwset_clksrc(struct fimc_control *ctrl, int src_clk);
+extern int fimc_hwget_overflow_state(struct fimc_control *ctrl);
+extern int fimc_hwset_camera_offset(struct fimc_control *ctrl);
+extern int fimc_hwset_camera_polarity(struct fimc_control *ctrl);
+extern int fimc_hwset_camera_type(struct fimc_control *ctrl);
+extern int fimc_hwset_output_size(struct fimc_control *ctrl,
+ int width, int height);
+extern int fimc_hwset_output_colorspace(struct fimc_control *ctrl,
+ u32 pixelformat);
+extern int fimc_hwset_output_rot_flip(struct fimc_control *ctrl,
+ u32 rot, u32 flip);
+extern int fimc_hwset_output_area(struct fimc_control *ctrl,
+ u32 width, u32 height);
+extern int fimc_hwset_output_area_size(struct fimc_control *ctrl, u32 size);
+extern int fimc_hwset_output_scan(struct fimc_control *ctrl,
+ struct v4l2_pix_format *fmt);
+extern int fimc_hwset_enable_lastirq(struct fimc_control *ctrl);
+extern int fimc_hwset_disable_lastirq(struct fimc_control *ctrl);
+extern int fimc_hwset_prescaler(struct fimc_control *ctrl,
+ struct fimc_scaler *sc);
+extern int fimc_hwset_output_yuv(struct fimc_control *ctrl, u32 pixelformat);
+extern int fimc_hwset_output_address(struct fimc_control *ctrl,
+ struct fimc_buf_set *bs,
+ int id);
+extern int fimc_hwset_input_rot(struct fimc_control *ctrl, u32 rot, u32 flip);
+extern int fimc_hwset_scaler(struct fimc_control *ctrl, struct fimc_scaler *sc);
+extern int fimc_hwset_scaler_bypass(struct fimc_control *ctrl);
+extern int fimc_hwset_enable_lcdfifo(struct fimc_control *ctrl);
+extern int fimc_hwset_disable_lcdfifo(struct fimc_control *ctrl);
+extern int fimc_hwset_start_scaler(struct fimc_control *ctrl);
+extern int fimc_hwset_stop_scaler(struct fimc_control *ctrl);
+extern int fimc_hwset_input_rgb(struct fimc_control *ctrl, u32 pixelformat);
+extern int fimc_hwset_intput_field(struct fimc_control *ctrl,
+ enum v4l2_field field);
+extern int fimc_hwset_output_rgb(struct fimc_control *ctrl, u32 pixelformat);
+extern int fimc_hwset_ext_rgb(struct fimc_control *ctrl, int enable);
+extern int fimc_hwset_enable_capture(struct fimc_control *ctrl,
+ u32 bypass);
+extern int fimc_hwset_disable_capture(struct fimc_control *ctrl);
+extern void fimc_wait_disable_capture(struct fimc_control *ctrl);
+extern int fimc_hwset_input_address(struct fimc_control *ctrl,
+ dma_addr_t *base);
+extern int fimc_hwset_enable_autoload(struct fimc_control *ctrl);
+extern int fimc_hwset_disable_autoload(struct fimc_control *ctrl);
+extern int fimc_hwset_real_input_size(struct fimc_control *ctrl,
+ u32 width, u32 height);
+extern int fimc_hwset_addr_change_enable(struct fimc_control *ctrl);
+extern int fimc_hwset_addr_change_disable(struct fimc_control *ctrl);
+extern int fimc_hwset_input_burst_cnt(struct fimc_control *ctrl, u32 cnt);
+extern int fimc_hwset_input_colorspace(struct fimc_control *ctrl,
+ u32 pixelformat);
+extern int fimc_hwset_input_yuv(struct fimc_control *ctrl, u32 pixelformat);
+extern int fimc_hwset_input_flip(struct fimc_control *ctrl, u32 rot, u32 flip);
+extern int fimc_hwset_input_source(struct fimc_control *ctrl,
+ enum fimc_input path);
+extern int fimc_hwset_start_input_dma(struct fimc_control *ctrl);
+extern int fimc_hwset_stop_input_dma(struct fimc_control *ctrl);
+extern int fimc_hwset_output_offset(struct fimc_control *ctrl,
+ u32 pixelformat,
+ struct v4l2_rect *bound,
+ struct v4l2_rect *crop);
+extern int fimc_hwset_input_offset(struct fimc_control *ctrl,
+ u32 pixelformat,
+ struct v4l2_rect *bound,
+ struct v4l2_rect *crop);
+extern int fimc_hwset_org_input_size(struct fimc_control *ctrl,
+ u32 width, u32 height);
+extern int fimc_hwset_org_output_size(struct fimc_control *ctrl,
+ u32 width, u32 height);
+extern int fimc_hwset_ext_output_size(struct fimc_control *ctrl,
+ u32 width, u32 height);
+extern int fimc_hwset_input_addr_style(struct fimc_control *ctrl,
+ u32 pixelformat);
+extern int fimc_hwset_output_addr_style(struct fimc_control *ctrl,
+ u32 pixelformat);
+extern int fimc_hwset_jpeg_mode(struct fimc_control *ctrl, bool enable);
+extern int fimc_hwget_frame_count(struct fimc_control *ctrl);
+extern int fimc_hw_wait_winoff(struct fimc_control *ctrl);
+extern int fimc_hw_wait_stop_input_dma(struct fimc_control *ctrl);
+extern int fimc_hwset_input_lineskip(struct fimc_control *ctrl);
+extern int fimc_hw_reset_camera(struct fimc_control *ctrl);
+extern void fimc_hwset_stop_processing(struct fimc_control *ctrl);
+extern int fimc_hwset_image_effect(struct fimc_control *ctrl);
+extern int fimc_hwset_shadow_enable(struct fimc_control *ctrl);
+extern int fimc_hwset_shadow_disable(struct fimc_control *ctrl);
+extern void fimc_save_regs(struct fimc_control *ctrl);
+extern void fimc_load_regs(struct fimc_control *ctrl);
+extern void fimc_dump_regs(struct fimc_control *ctrl);
+
+/*
+ * D R I V E R H E L P E R S
+ *
+*/
+#define to_fimc_plat(d) (to_platform_device(d)->dev.platform_data)
+
+static inline struct fimc_global *get_fimc_dev(void)
+{
+ return fimc_dev;
+}
+
+static inline struct fimc_control *get_fimc_ctrl(int id)
+{
+ return &fimc_dev->ctrl[id];
+}
+
+#endif /* _FIMC_H */
+
diff --git a/drivers/media/video/samsung/fimc/fimc_capture.c b/drivers/media/video/samsung/fimc/fimc_capture.c
new file mode 100644
index 0000000..2028bf9
--- /dev/null
+++ b/drivers/media/video/samsung/fimc/fimc_capture.c
@@ -0,0 +1,1733 @@
+/* linux/drivers/media/video/samsung/fimc/fimc_capture.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * V4L2 Capture device support file for Samsung Camera Interface (FIMC) driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/slab.h>
+#include <linux/bootmem.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_samsung.h>
+#include <linux/clk.h>
+#include <linux/mm.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <plat/media.h>
+#include <plat/clock.h>
+#include <plat/fimc.h>
+#include <linux/delay.h>
+
+#include "fimc.h"
+
+/* subdev handling macro */
+#define subdev_call(ctrl, o, f, args...) \
+ v4l2_subdev_call(ctrl->cam->sd, o, f, ##args)
+
+/* #define FIMC_CAP_DEBUG */
+
+#ifdef FIMC_CAP_DEBUG
+#ifdef fimc_dbg
+#undef fimc_dbg
+#endif
+#define fimc_dbg fimc_err
+#endif
+
+static const struct v4l2_fmtdesc capture_fmts[] = {
+ {
+ .index = 0,
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ .flags = FORMAT_FLAGS_PACKED,
+ .description = "RGB-5-6-5",
+ .pixelformat = V4L2_PIX_FMT_RGB565,
+ }, {
+ .index = 1,
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ .flags = FORMAT_FLAGS_PACKED,
+ .description = "RGB-8-8-8, unpacked 24 bpp",
+ .pixelformat = V4L2_PIX_FMT_RGB32,
+ }, {
+ .index = 2,
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ .flags = FORMAT_FLAGS_PACKED,
+ .description = "YUV 4:2:2 packed, YCbYCr",
+ .pixelformat = V4L2_PIX_FMT_YUYV,
+ }, {
+ .index = 3,
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ .flags = FORMAT_FLAGS_PACKED,
+ .description = "YUV 4:2:2 packed, CbYCrY",
+ .pixelformat = V4L2_PIX_FMT_UYVY,
+ }, {
+ .index = 4,
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ .flags = FORMAT_FLAGS_PACKED,
+ .description = "YUV 4:2:2 packed, CrYCbY",
+ .pixelformat = V4L2_PIX_FMT_VYUY,
+ }, {
+ .index = 5,
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ .flags = FORMAT_FLAGS_PACKED,
+ .description = "YUV 4:2:2 packed, YCrYCb",
+ .pixelformat = V4L2_PIX_FMT_YVYU,
+ }, {
+ .index = 6,
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ .flags = FORMAT_FLAGS_PLANAR,
+ .description = "YUV 4:2:2 planar, Y/Cb/Cr",
+ .pixelformat = V4L2_PIX_FMT_YUV422P,
+ }, {
+ .index = 7,
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ .flags = FORMAT_FLAGS_PLANAR,
+ .description = "YUV 4:2:0 planar, Y/CbCr",
+ .pixelformat = V4L2_PIX_FMT_NV12,
+ }, {
+ .index = 8,
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ .flags = FORMAT_FLAGS_PLANAR,
+ .description = "YUV 4:2:0 planar, Y/CbCr, Tiled",
+ .pixelformat = V4L2_PIX_FMT_NV12T,
+ }, {
+ .index = 9,
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ .flags = FORMAT_FLAGS_PLANAR,
+ .description = "YUV 4:2:0 planar, Y/CrCb",
+ .pixelformat = V4L2_PIX_FMT_NV21,
+ }, {
+ .index = 10,
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ .flags = FORMAT_FLAGS_PLANAR,
+ .description = "YUV 4:2:2 planar, Y/CbCr",
+ .pixelformat = V4L2_PIX_FMT_NV16,
+ }, {
+ .index = 11,
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ .flags = FORMAT_FLAGS_PLANAR,
+ .description = "YUV 4:2:2 planar, Y/CrCb",
+ .pixelformat = V4L2_PIX_FMT_NV61,
+ }, {
+ .index = 12,
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ .flags = FORMAT_FLAGS_PLANAR,
+ .description = "YUV 4:2:0 planar, Y/Cb/Cr",
+ .pixelformat = V4L2_PIX_FMT_YUV420,
+ }, {
+ .index = 13,
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ .flags = FORMAT_FLAGS_ENCODED,
+ .description = "Encoded JPEG bitstream",
+ .pixelformat = V4L2_PIX_FMT_JPEG,
+ },
+};
+
+static const struct v4l2_queryctrl fimc_controls[] = {
+ {
+ .id = V4L2_CID_ROTATION,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Roataion",
+ .minimum = 0,
+ .maximum = 270,
+ .step = 90,
+ .default_value = 0,
+ }, {
+ .id = V4L2_CID_HFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Horizontal Flip",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ }, {
+ .id = V4L2_CID_VFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Vertical Flip",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ }, {
+ .id = V4L2_CID_PADDR_Y,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Physical address Y",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ .flags = V4L2_CTRL_FLAG_READ_ONLY,
+ }, {
+ .id = V4L2_CID_PADDR_CB,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Physical address Cb",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ .flags = V4L2_CTRL_FLAG_READ_ONLY,
+ }, {
+ .id = V4L2_CID_PADDR_CR,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Physical address Cr",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ .flags = V4L2_CTRL_FLAG_READ_ONLY,
+ }, {
+ .id = V4L2_CID_PADDR_CBCR,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Physical address CbCr",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ .flags = V4L2_CTRL_FLAG_READ_ONLY,
+ },
+};
+
+#ifndef CONFIG_VIDEO_FIMC_MIPI
+void s3c_csis_start(int lanes, int settle, int align, int width, int height,
+ int pixel_format) {}
+#endif
+
+static int fimc_camera_init(struct fimc_control *ctrl)
+{
+ int ret;
+
+ fimc_dbg("%s\n", __func__);
+
+ /* do nothing if already initialized */
+ if (ctrl->cam->initialized)
+ return 0;
+
+ /* enable camera power if needed */
+ if (ctrl->cam->cam_power)
+ ctrl->cam->cam_power(1);
+
+ /* subdev call for init */
+ ret = subdev_call(ctrl, core, init, 0);
+ if (ret == -ENOIOCTLCMD) {
+ fimc_err("%s: init subdev api not supported\n",
+ __func__);
+ return ret;
+ }
+
+ if (ctrl->cam->type == CAM_TYPE_MIPI) {
+ /* subdev call for sleep/wakeup:
+ * no error although no s_stream api support
+ */
+ u32 pixelformat;
+ if (ctrl->cap->fmt.pixelformat == V4L2_PIX_FMT_JPEG)
+ pixelformat = V4L2_PIX_FMT_JPEG;
+ else
+ pixelformat = ctrl->cam->pixelformat;
+
+ subdev_call(ctrl, video, s_stream, 0);
+ s3c_csis_start(ctrl->cam->mipi_lanes, ctrl->cam->mipi_settle, \
+ ctrl->cam->mipi_align, ctrl->cam->width, \
+ ctrl->cam->height, pixelformat);
+ subdev_call(ctrl, video, s_stream, 1);
+ }
+
+ ctrl->cam->initialized = 1;
+
+ return 0;
+}
+
+
+/* This function must be called after s_fmt and s_parm call to the subdev
+ * has already been made.
+ *
+ * - obtains the camera output (input to FIMC) resolution.
+ * - sets the preview size (aka camera output resolution) and framerate.
+ * - starts the preview operation.
+ *
+ * On success, returns 0.
+ * On failure, returns the error code of the call that failed.
+ */
+static int fimc_camera_start(struct fimc_control *ctrl)
+{
+ struct v4l2_frmsizeenum cam_frmsize;
+ struct v4l2_control cam_ctrl;
+ int ret;
+
+ ret = subdev_call(ctrl, video, enum_framesizes, &cam_frmsize);
+ if (ret < 0) {
+ fimc_err("%s: enum_framesizes failed\n", __func__);
+ if (ret != -ENOIOCTLCMD)
+ return ret;
+ } else {
+ ctrl->cam->width = cam_frmsize.discrete.width;
+ ctrl->cam->height = cam_frmsize.discrete.height;
+
+ ctrl->cam->window.left = 0;
+ ctrl->cam->window.top = 0;
+ ctrl->cam->window.width = ctrl->cam->width;
+ ctrl->cam->window.height = ctrl->cam->height;
+ }
+
+ cam_ctrl.id = V4L2_CID_CAM_PREVIEW_ONOFF;
+ cam_ctrl.value = 1;
+ ret = subdev_call(ctrl, core, s_ctrl, &cam_ctrl);
+
+ /* When the device is waking up from sleep, this call may fail. In
+ * that case, it is better to reset the camera sensor and start again.
+ * If the preview fails again, the reason might be something else and
+ * we should return the error.
+ */
+ if (ret < 0 && ret != -ENOIOCTLCMD) {
+ ctrl->cam->initialized = 0;
+ fimc_camera_init(ctrl);
+ ret = subdev_call(ctrl, core, s_ctrl, &cam_ctrl);
+ if (ret < 0 && ret != -ENOIOCTLCMD) {
+ fimc_err("%s: Error in V4L2_CID_CAM_PREVIEW_ONOFF"
+ " - start\n", __func__);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int fimc_camera_get_jpeg_memsize(struct fimc_control *ctrl)
+{
+ int ret;
+ struct v4l2_control cam_ctrl;
+ cam_ctrl.id = V4L2_CID_CAM_JPEG_MEMSIZE;
+
+ ret = subdev_call(ctrl, core, g_ctrl, &cam_ctrl);
+ if (ret < 0) {
+ fimc_err("%s: Subdev doesn't support JEPG encoding.\n", \
+ __func__);
+ return 0;
+ }
+
+ return cam_ctrl.value;
+}
+
+
+static int fimc_capture_scaler_info(struct fimc_control *ctrl)
+{
+ struct fimc_scaler *sc = &ctrl->sc;
+ struct v4l2_rect *window = &ctrl->cam->window;
+ int tx, ty, sx, sy;
+
+ sx = window->width;
+ sy = window->height;
+ tx = ctrl->cap->fmt.width;
+ ty = ctrl->cap->fmt.height;
+
+ sc->real_width = sx;
+ sc->real_height = sy;
+
+ fimc_dbg("%s: CamOut (%d, %d), TargetOut (%d, %d)\n", \
+ __func__, sx, sy, tx, ty);
+
+ if (sx <= 0 || sy <= 0) {
+ fimc_err("%s: invalid source size\n", __func__);
+ return -EINVAL;
+ }
+
+ if (tx <= 0 || ty <= 0) {
+ fimc_err("%s: invalid target size\n", __func__);
+ return -EINVAL;
+ }
+
+ fimc_get_scaler_factor(sx, tx, &sc->pre_hratio, &sc->hfactor);
+ fimc_get_scaler_factor(sy, ty, &sc->pre_vratio, &sc->vfactor);
+
+ /* Tushar - sx and sy should be multiple of pre_hratio and pre_vratio */
+ sc->pre_dst_width = sx / sc->pre_hratio;
+ sc->pre_dst_height = sy / sc->pre_vratio;
+
+ sc->main_hratio = (sx << 8) / (tx << sc->hfactor);
+ sc->main_vratio = (sy << 8) / (ty << sc->vfactor);
+
+ sc->scaleup_h = (tx >= sx) ? 1 : 0;
+ sc->scaleup_v = (ty >= sy) ? 1 : 0;
+
+ return 0;
+}
+
+/**
+ * fimc_add_inqueue: used to add the buffer at given index to inqueue
+ *
+ * Called from qbuf().
+ *
+ * Returns error if buffer is already in queue or buffer index is out of range.
+ */
+static int fimc_add_inqueue(struct fimc_control *ctrl, int i)
+{
+ struct fimc_capinfo *cap = ctrl->cap;
+
+ struct fimc_buf_set *buf;
+
+ if (i >= cap->nr_bufs)
+ return -EINVAL;
+
+ list_for_each_entry(buf, &cap->inq, list) {
+ if (buf->id == i) {
+ fimc_dbg("%s: buffer %d already in inqueue.\n", \
+ __func__, i);
+ return -EINVAL;
+ }
+ }
+ list_add_tail(&cap->bufs[i].list, &cap->inq);
+
+ return 0;
+}
+
+static int fimc_add_outqueue(struct fimc_control *ctrl, int i)
+{
+ struct fimc_capinfo *cap = ctrl->cap;
+ struct fimc_buf_set *buf;
+
+ unsigned int mask = 0x2;
+
+ /* PINGPONG_2ADDR_MODE Only */
+ /* pair_buf_index stands for pair index of i. (0<->2) (1<->3) */
+
+ int pair_buf_index = (i^mask);
+
+ /* FIMC have 4 h/w registers */
+ if (i < 0 || i >= FIMC_PHYBUFS) {
+ fimc_err("%s: invalid queue index : %d\n", __func__, i);
+ return -ENOENT;
+ }
+
+ if (list_empty(&cap->inq))
+ return -ENOENT;
+
+ buf = list_first_entry(&cap->inq, struct fimc_buf_set, list);
+
+ /* pair index buffer should be allocated first */
+ cap->outq[pair_buf_index] = buf->id;
+ fimc_hwset_output_address(ctrl, buf, pair_buf_index);
+
+ cap->outq[i] = buf->id;
+ fimc_hwset_output_address(ctrl, buf, i);
+
+ if (cap->nr_bufs != 1)
+ list_del(&buf->list);
+
+ return 0;
+}
+
+static int fimc_update_hwaddr(struct fimc_control *ctrl)
+{
+ int i;
+
+ for (i = 0; i < FIMC_PINGPONG; i++)
+ fimc_add_outqueue(ctrl, i);
+
+ return 0;
+}
+
+int fimc_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ret;
+
+ fimc_dbg("%s\n", __func__);
+
+ if (!ctrl->cam || !ctrl->cam->sd) {
+ fimc_err("%s: No capture device.\n", __func__);
+ return -ENODEV;
+ }
+
+ mutex_lock(&ctrl->v4l2_lock);
+ ret = subdev_call(ctrl, video, g_parm, a);
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ return ret;
+}
+
+int fimc_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ret = 0;
+
+ fimc_dbg("%s\n", __func__);
+
+ if (!ctrl->cam || !ctrl->cam->sd) {
+ fimc_err("%s: No capture device.\n", __func__);
+ return -ENODEV;
+ }
+
+ mutex_lock(&ctrl->v4l2_lock);
+ if (ctrl->id != 2)
+ ret = subdev_call(ctrl, video, s_parm, a);
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ return ret;
+}
+
+/* Enumerate controls */
+int fimc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qc)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int i, ret;
+
+ fimc_dbg("%s\n", __func__);
+
+ for (i = 0; i < ARRAY_SIZE(fimc_controls); i++) {
+ if (fimc_controls[i].id == qc->id) {
+ memcpy(qc, &fimc_controls[i], \
+ sizeof(struct v4l2_queryctrl));
+ return 0;
+ }
+ }
+
+ mutex_lock(&ctrl->v4l2_lock);
+ ret = subdev_call(ctrl, core, queryctrl, qc);
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ return ret;
+}
+
+/* Menu control items */
+int fimc_querymenu(struct file *file, void *fh, struct v4l2_querymenu *qm)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ret;
+
+ fimc_dbg("%s\n", __func__);
+
+ mutex_lock(&ctrl->v4l2_lock);
+ ret = subdev_call(ctrl, core, querymenu, qm);
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ return ret;
+}
+
+
+/* Given the index, we will return the camera name if there is any camera
+ * present at the given id.
+ */
+int fimc_enum_input(struct file *file, void *fh, struct v4l2_input *inp)
+{
+ struct fimc_global *fimc = get_fimc_dev();
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+
+ fimc_dbg("%s: index %d\n", __func__, inp->index);
+
+ if (inp->index < 0 || inp->index >= FIMC_MAXCAMS) {
+ fimc_err("%s: invalid input index, received = %d\n", \
+ __func__, inp->index);
+ return -EINVAL;
+ }
+
+ if (!fimc->camera_isvalid[inp->index])
+ return -EINVAL;
+
+ strcpy(inp->name, fimc->camera[inp->index].info->type);
+ inp->type = V4L2_INPUT_TYPE_CAMERA;
+
+ return 0;
+}
+
+int fimc_g_input(struct file *file, void *fh, unsigned int *i)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ struct fimc_global *fimc = get_fimc_dev();
+
+ /* In case of isueing g_input before s_input */
+ if (!ctrl->cam) {
+ fimc_err("no camera device selected yet!" \
+ "do VIDIOC_S_INPUT first\n");
+ return -ENODEV;
+ }
+
+ *i = (unsigned int) fimc->active_camera;
+
+ fimc_dbg("%s: index %d\n", __func__, *i);
+
+ return 0;
+}
+
+int fimc_release_subdev(struct fimc_control *ctrl)
+{
+ struct fimc_global *fimc = get_fimc_dev();
+ struct i2c_client *client;
+
+ if (ctrl && ctrl->cam && ctrl->cam->sd) {
+ fimc_dbg("%s called\n", __func__);
+ client = v4l2_get_subdevdata(ctrl->cam->sd);
+ i2c_unregister_device(client);
+ ctrl->cam->sd = NULL;
+ if (ctrl->cam->cam_power)
+ ctrl->cam->cam_power(0);
+ ctrl->cam->initialized = 0;
+ ctrl->cam = NULL;
+ fimc->active_camera = -1;
+ }
+ return 0;
+}
+
+static int fimc_configure_subdev(struct fimc_control *ctrl)
+{
+ struct i2c_adapter *i2c_adap;
+ struct i2c_board_info *i2c_info;
+ struct v4l2_subdev *sd;
+ unsigned short addr;
+ char *name;
+
+ /* set parent for mclk */
+ if (clk_get_parent(ctrl->cam->clk->parent))
+ clk_set_parent(ctrl->cam->clk->parent, ctrl->cam->srclk);
+
+ /* set rate for mclk */
+ if (clk_get_rate(ctrl->cam->clk))
+ clk_set_rate(ctrl->cam->clk, ctrl->cam->clk_rate);
+
+ i2c_adap = i2c_get_adapter(ctrl->cam->i2c_busnum);
+ if (!i2c_adap)
+ fimc_err("subdev i2c_adapter missing-skip registration\n");
+
+ i2c_info = ctrl->cam->info;
+ if (!i2c_info) {
+ fimc_err("%s: subdev i2c board info missing\n", __func__);
+ return -ENODEV;
+ }
+
+ name = i2c_info->type;
+ if (!name) {
+ fimc_err("subdev i2c driver name missing-skip registration\n");
+ return -ENODEV;
+ }
+
+ addr = i2c_info->addr;
+ if (!addr) {
+ fimc_err("subdev i2c address missing-skip registration\n");
+ return -ENODEV;
+ }
+ /*
+ * NOTE: first time subdev being registered,
+ * s_config is called and try to initialize subdev device
+ * but in this point, we are not giving MCLK and power to subdev
+ * so nothing happens but pass platform data through
+ */
+ sd = v4l2_i2c_new_subdev_board(&ctrl->v4l2_dev, i2c_adap,
+ i2c_info, &addr);
+ if (!sd) {
+ fimc_err("%s: v4l2 subdev board registering failed\n",
+ __func__);
+ }
+
+ /* Assign subdev to proper camera device pointer */
+ ctrl->cam->sd = sd;
+
+ return 0;
+}
+
+int fimc_s_input(struct file *file, void *fh, unsigned int i)
+{
+ struct fimc_global *fimc = get_fimc_dev();
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ret = 0;
+
+ fimc_dbg("%s: index %d\n", __func__, i);
+
+ if (i < 0 || i >= FIMC_MAXCAMS) {
+ fimc_err("%s: invalid input index\n", __func__);
+ return -EINVAL;
+ }
+
+ if (!fimc->camera_isvalid[i])
+ return -EINVAL;
+
+ if (fimc->camera[i].sd && ctrl->id != 2) {
+ fimc_err("%s: Camera already in use.\n", __func__);
+ return -EBUSY;
+ }
+
+ mutex_lock(&ctrl->v4l2_lock);
+ /* If ctrl->cam is not NULL, there is one subdev already registered.
+ * We need to unregister that subdev first.
+ */
+ if (i != fimc->active_camera) {
+ fimc_release_subdev(ctrl);
+ ctrl->cam = &fimc->camera[i];
+ ret = fimc_configure_subdev(ctrl);
+ if (ret < 0) {
+ mutex_unlock(&ctrl->v4l2_lock);
+ fimc_err("%s: Could not register camera sensor "
+ "with V4L2.\n", __func__);
+ return -ENODEV;
+ }
+ fimc->active_camera = i;
+ }
+
+ if (ctrl->id == 2) {
+ if (i == fimc->active_camera) {
+ ctrl->cam = &fimc->camera[i];
+ } else {
+ mutex_unlock(&ctrl->v4l2_lock);
+ return -EINVAL;
+ }
+ }
+
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ return 0;
+}
+
+int fimc_enum_fmt_vid_capture(struct file *file, void *fh,
+ struct v4l2_fmtdesc *f)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int i = f->index;
+ int num_entries = 0;
+ int ret = 0;
+ enum v4l2_mbus_pixelcode code;
+
+ fimc_dbg("%s\n", __func__);
+
+ if (ctrl->out) {
+ fimc_err("%s: fimc is already used for output mode\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if (!ctrl->cam || !ctrl->cam->sd) {
+ fimc_err("%s: No capture device.\n", __func__);
+ return -ENODEV;
+ }
+
+ num_entries = sizeof(capture_fmts)/sizeof(struct v4l2_fmtdesc);
+
+ if (i >= num_entries) {
+ mutex_lock(&ctrl->v4l2_lock);
+ ret = subdev_call(ctrl, video, enum_mbus_fmt,
+ f->index - num_entries, &code);
+ mutex_unlock(&ctrl->v4l2_lock);
+ return ret;
+ }
+
+ memcpy(f, &capture_fmts[i], sizeof(*f));
+
+ return 0;
+}
+
+int fimc_g_fmt_vid_capture(struct file *file, void *fh, struct v4l2_format *f)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+
+ fimc_dbg("%s\n", __func__);
+
+ if (!ctrl->cap) {
+ fimc_err("%s: no capture device info\n", __func__);
+ return -EINVAL;
+ }
+
+ mutex_lock(&ctrl->v4l2_lock);
+
+ memcpy(&f->fmt.pix, &ctrl->cap->fmt, sizeof(f->fmt.pix));
+
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ return 0;
+}
+
+/*
+ * Check for whether the requested format
+ * can be streamed out from FIMC
+ * depends on FIMC node
+ */
+static int fimc_fmt_avail(struct fimc_control *ctrl,
+ struct v4l2_format *f)
+{
+ int i;
+
+ /*
+ * TODO: check for which FIMC is used.
+ * Available fmt should be varied for each FIMC
+ */
+
+ for (i = 0; i < sizeof(capture_fmts); i++) {
+ if (capture_fmts[i].pixelformat == f->fmt.pix.pixelformat)
+ return 0;
+ }
+
+ fimc_err("Not supported pixelformat requested\n");
+
+ return -1;
+}
+
+/*
+ * figures out the depth of requested format
+ */
+static int fimc_fmt_depth(struct fimc_control *ctrl, struct v4l2_format *f)
+{
+ int err, depth = 0;
+
+ /* First check for available format or not */
+ err = fimc_fmt_avail(ctrl, f);
+ if (err < 0)
+ return -EINVAL;
+
+ /* handles only supported pixelformats */
+ switch (f->fmt.pix.pixelformat) {
+ case V4L2_PIX_FMT_RGB32:
+ depth = 32;
+ fimc_dbg("32bpp\n");
+ break;
+ case V4L2_PIX_FMT_RGB565:
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_VYUY:
+ case V4L2_PIX_FMT_YVYU:
+ case V4L2_PIX_FMT_YUV422P:
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_NV61:
+ depth = 16;
+ fimc_dbg("16bpp\n");
+ break;
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV12T:
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_YUV420:
+ depth = 12;
+ fimc_dbg("12bpp\n");
+ break;
+ case V4L2_PIX_FMT_JPEG:
+ depth = -1;
+ fimc_dbg("Compressed format.\n");
+ break;
+ default:
+ fimc_dbg("why am I here? - received %x\n",
+ f->fmt.pix.pixelformat);
+ break;
+ }
+
+ return depth;
+}
+
+int fimc_s_fmt_vid_capture(struct file *file, void *fh, struct v4l2_format *f)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ struct fimc_capinfo *cap;
+ struct v4l2_mbus_framefmt mbus_fmt;
+ int ret = 0;
+ int depth;
+
+ fimc_dbg("%s\n", __func__);
+
+ if (!ctrl->cam || !ctrl->cam->sd) {
+ fimc_err("%s: No capture device.\n", __func__);
+ return -ENODEV;
+ }
+ /*
+ * The first time alloc for struct cap_info, and will be
+ * released at the file close.
+ * Anyone has better idea to do this?
+ */
+ mutex_lock(&ctrl->v4l2_lock);
+
+ if (!ctrl->cap) {
+ ctrl->cap = kmalloc(sizeof(*cap), GFP_KERNEL);
+ if (!ctrl->cap) {
+ mutex_unlock(&ctrl->v4l2_lock);
+ fimc_err("%s: no memory for "
+ "capture device info\n", __func__);
+ return -ENOMEM;
+ }
+
+ }
+ cap = ctrl->cap;
+ memset(cap, 0, sizeof(*cap));
+ memcpy(&cap->fmt, &f->fmt.pix, sizeof(cap->fmt));
+ v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, 0);
+
+ /*
+ * Note that expecting format only can be with
+ * available output format from FIMC
+ * Following items should be handled in driver
+ * bytesperline = width * depth / 8
+ * sizeimage = bytesperline * height
+ */
+ /* This function may return 0 or -1 in case of error, hence need to
+ * check here.
+ */
+ depth = fimc_fmt_depth(ctrl, f);
+ if (depth == 0) {
+ mutex_unlock(&ctrl->v4l2_lock);
+ fimc_err("%s: Invalid pixel format\n", __func__);
+ return -EINVAL;
+ } else if (depth < 0) {
+ /*
+ * When the pixelformat is JPEG, the application is requesting
+ * for data in JPEG compressed format.
+ */
+ mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
+ ret = subdev_call(ctrl, video, try_mbus_fmt, &mbus_fmt);
+ if (ret < 0) {
+ mutex_unlock(&ctrl->v4l2_lock);
+ return -EINVAL;
+ }
+ cap->fmt.colorspace = V4L2_COLORSPACE_JPEG;
+ } else {
+ cap->fmt.bytesperline = (cap->fmt.width * depth) >> 3;
+ cap->fmt.sizeimage = (cap->fmt.bytesperline * cap->fmt.height);
+ }
+
+ if (cap->fmt.colorspace == V4L2_COLORSPACE_JPEG) {
+ ctrl->sc.bypass = 1;
+ cap->lastirq = 1;
+ }
+
+ if (ctrl->id != 2) {
+ ret = subdev_call(ctrl, video, s_mbus_fmt, &mbus_fmt);
+ }
+
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ return ret;
+}
+
+int fimc_try_fmt_vid_capture(struct file *file, void *fh, struct v4l2_format *f)
+{
+ return 0;
+}
+
+static int fimc_alloc_buffers(struct fimc_control *ctrl, int size[], int align)
+{
+ struct fimc_capinfo *cap = ctrl->cap;
+ int i, plane;
+
+ for (i = 0; i < cap->nr_bufs; i++) {
+ for (plane = 0; plane < 4; plane++) {
+ cap->bufs[i].length[plane] = size[plane];
+ if (!cap->bufs[i].length[plane])
+ continue;
+
+ fimc_dma_alloc(ctrl, &cap->bufs[i], plane, align);
+
+ if (!cap->bufs[i].base[plane])
+ goto err_alloc;
+ }
+
+ cap->bufs[i].state = VIDEOBUF_PREPARED;
+ cap->bufs[i].id = i;
+ }
+
+ return 0;
+
+err_alloc:
+ for (i = 0; i < cap->nr_bufs; i++) {
+ if (cap->bufs[i].base[plane])
+ fimc_dma_free(ctrl, &cap->bufs[i], plane);
+
+ memset(&cap->bufs[i], 0, sizeof(cap->bufs[i]));
+ }
+
+ return -ENOMEM;
+}
+
+static void fimc_free_buffers(struct fimc_control *ctrl)
+{
+ struct fimc_capinfo *cap;
+ int i;
+
+ if (ctrl && ctrl->cap)
+ cap = ctrl->cap;
+ else
+ return;
+
+
+ for (i = 0; i < cap->nr_bufs; i++) {
+ memset(&cap->bufs[i], 0, sizeof(cap->bufs[i]));
+ cap->bufs[i].state = VIDEOBUF_NEEDS_INIT;
+ }
+
+ ctrl->mem.curr = ctrl->mem.base;
+}
+
+int fimc_reqbufs_capture(void *fh, struct v4l2_requestbuffers *b)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ struct fimc_capinfo *cap = ctrl->cap;
+ int ret = 0, i;
+ int size[4] = { 0, 0, 0, 0};
+ int align = 0;
+
+ if (b->memory != V4L2_MEMORY_MMAP) {
+ fimc_err("%s: invalid memory type\n", __func__);
+ return -EINVAL;
+ }
+
+ if (!cap) {
+ fimc_err("%s: no capture device info\n", __func__);
+ return -ENODEV;
+ }
+
+ if (!ctrl->cam || !ctrl->cam->sd) {
+ fimc_err("%s: No capture device.\n", __func__);
+ return -ENODEV;
+ }
+
+ mutex_lock(&ctrl->v4l2_lock);
+
+ if (b->count < 1 || b->count > FIMC_CAPBUFS)
+ return -EINVAL;
+
+ /* It causes flickering as buf_0 and buf_3 refer to same hardware
+ * address.
+ */
+ if (b->count == 3)
+ b->count = 4;
+
+ cap->nr_bufs = b->count;
+
+ fimc_dbg("%s: requested %d buffers\n", __func__, b->count);
+
+ INIT_LIST_HEAD(&cap->inq);
+ fimc_free_buffers(ctrl);
+
+ switch (cap->fmt.pixelformat) {
+ case V4L2_PIX_FMT_RGB32: /* fall through */
+ case V4L2_PIX_FMT_RGB565: /* fall through */
+ case V4L2_PIX_FMT_YUYV: /* fall through */
+ case V4L2_PIX_FMT_UYVY: /* fall through */
+ case V4L2_PIX_FMT_VYUY: /* fall through */
+ case V4L2_PIX_FMT_YVYU: /* fall through */
+ case V4L2_PIX_FMT_YUV422P: /* fall through */
+ size[0] = cap->fmt.sizeimage;
+ break;
+
+ case V4L2_PIX_FMT_NV16: /* fall through */
+ case V4L2_PIX_FMT_NV61:
+ size[0] = cap->fmt.width * cap->fmt.height;
+ size[1] = cap->fmt.width * cap->fmt.height;
+ break;
+ case V4L2_PIX_FMT_NV12:
+ size[0] = cap->fmt.width * cap->fmt.height;
+ size[1] = cap->fmt.width * cap->fmt.height/2;
+ break;
+ case V4L2_PIX_FMT_NV21:
+ size[0] = cap->fmt.width * cap->fmt.height;
+ size[1] = cap->fmt.width * cap->fmt.height/2;
+ break;
+ case V4L2_PIX_FMT_NV12T:
+ /* Tiled frame size calculations as per 4x2 tiles
+ * - Width: Has to be aligned to 2 times the tile width
+ * - Height: Has to be aligned to the tile height
+ * - Alignment: Has to be aligned to the size of the
+ * macrotile (size of 4 tiles)
+ *
+ * NOTE: In case of rotation, we need modified calculation as
+ * width and height are aligned to different values.
+ */
+ if (cap->rotate == 90 || cap->rotate == 270) {
+ size[0] = ALIGN(ALIGN(cap->fmt.height, 128) *
+ ALIGN(cap->fmt.width, 32),
+ SZ_8K);
+ size[1] = ALIGN(ALIGN(cap->fmt.height, 128) *
+ ALIGN(cap->fmt.width/2, 32),
+ SZ_8K);
+ } else {
+ size[0] = ALIGN(ALIGN(cap->fmt.width, 128) *
+ ALIGN(cap->fmt.height, 32),
+ SZ_8K);
+ size[1] = ALIGN(ALIGN(cap->fmt.width, 128) *
+ ALIGN(cap->fmt.height/2, 32),
+ SZ_8K);
+ }
+ align = SZ_8K;
+ break;
+
+ case V4L2_PIX_FMT_YUV420:
+ size[0] = cap->fmt.width * cap->fmt.height;
+ size[1] = cap->fmt.width * cap->fmt.height >> 2;
+ size[2] = cap->fmt.width * cap->fmt.height >> 2;
+ break;
+
+ case V4L2_PIX_FMT_JPEG:
+ size[0] = fimc_camera_get_jpeg_memsize(ctrl);
+ default:
+ break;
+ }
+
+ ret = fimc_alloc_buffers(ctrl, size, align);
+ if (ret) {
+ fimc_err("%s: no memory for "
+ "capture buffer\n", __func__);
+ mutex_unlock(&ctrl->v4l2_lock);
+ return -ENOMEM;
+ }
+
+ for (i = cap->nr_bufs; i < FIMC_PHYBUFS; i++) {
+ memcpy(&cap->bufs[i], \
+ &cap->bufs[i - cap->nr_bufs], sizeof(cap->bufs[i]));
+ }
+
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ return 0;
+}
+
+int fimc_querybuf_capture(void *fh, struct v4l2_buffer *b)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+
+ if (!ctrl->cap || !ctrl->cap->bufs) {
+ fimc_err("%s: no capture device info\n", __func__);
+ return -ENODEV;
+ }
+
+ if (ctrl->status != FIMC_STREAMOFF) {
+ fimc_err("fimc is running\n");
+ return -EBUSY;
+ }
+
+ mutex_lock(&ctrl->v4l2_lock);
+
+ b->length = ctrl->cap->bufs[b->index].length[FIMC_ADDR_Y]
+ + ctrl->cap->bufs[b->index].length[FIMC_ADDR_CB]
+ + ctrl->cap->bufs[b->index].length[FIMC_ADDR_CR];
+
+ b->m.offset = b->index * PAGE_SIZE;
+
+ ctrl->cap->bufs[b->index].state = VIDEOBUF_IDLE;
+
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ fimc_dbg("%s: %d bytes at index: %d\n", __func__, b->length, b->index);
+
+ return 0;
+}
+
+int fimc_g_ctrl_capture(void *fh, struct v4l2_control *c)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ret = 0;
+
+ fimc_dbg("%s\n", __func__);
+
+ if (!ctrl->cam || !ctrl->cam->sd || !ctrl->cap) {
+ fimc_err("%s: No capture device.\n", __func__);
+ return -ENODEV;
+ }
+
+ mutex_lock(&ctrl->v4l2_lock);
+
+ switch (c->id) {
+ case V4L2_CID_ROTATION:
+ c->value = ctrl->cap->rotate;
+ break;
+
+ case V4L2_CID_HFLIP:
+ c->value = (ctrl->cap->flip & FIMC_XFLIP) ? 1 : 0;
+ break;
+
+ case V4L2_CID_VFLIP:
+ c->value = (ctrl->cap->flip & FIMC_YFLIP) ? 1 : 0;
+ break;
+
+ default:
+ /* get ctrl supported by subdev */
+ mutex_unlock(&ctrl->v4l2_lock);
+ ret = subdev_call(ctrl, core, g_ctrl, c);
+ mutex_lock(&ctrl->v4l2_lock);
+ break;
+ }
+
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ return ret;
+}
+
+/**
+ * We used s_ctrl API to get the physical address of the buffers.
+ * In g_ctrl, we can pass only one parameter, thus we cannot pass
+ * the index of the buffer.
+ * In order to use g_ctrl for obtaining the physical address, we
+ * will have to create CID ids for all values (4 ids for Y0~Y3 and 4 ids
+ * for C0~C3). Currently, we will continue with the existing
+ * implementation till we get any better idea to implement.
+ */
+int fimc_s_ctrl_capture(void *fh, struct v4l2_control *c)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ret = 0;
+
+ fimc_info2("%s\n", __func__);
+
+ if (!ctrl->cam || !ctrl->cam->sd || !ctrl->cap || !ctrl->cap->bufs) {
+ fimc_err("%s: No capture device.\n", __func__);
+ return -ENODEV;
+ }
+
+ mutex_lock(&ctrl->v4l2_lock);
+
+ switch (c->id) {
+ case V4L2_CID_ROTATION:
+ ctrl->cap->rotate = c->value;
+ break;
+
+ case V4L2_CID_HFLIP: /* fall through */
+ ctrl->cap->flip |= FIMC_XFLIP;
+ break;
+ case V4L2_CID_VFLIP:
+ ctrl->cap->flip |= FIMC_YFLIP;
+ break;
+
+ case V4L2_CID_PADDR_Y:
+ c->value = ctrl->cap->bufs[c->value].base[FIMC_ADDR_Y];
+ break;
+
+ case V4L2_CID_PADDR_CB: /* fall through */
+ case V4L2_CID_PADDR_CBCR:
+ c->value = ctrl->cap->bufs[c->value].base[FIMC_ADDR_CB];
+ break;
+
+ case V4L2_CID_PADDR_CR:
+ c->value = ctrl->cap->bufs[c->value].base[FIMC_ADDR_CR];
+ break;
+
+ /* Implementation as per C100 FIMC driver */
+ case V4L2_CID_STREAM_PAUSE:
+ fimc_hwset_stop_processing(ctrl);
+ break;
+
+ case V4L2_CID_IMAGE_EFFECT_APPLY:
+ ctrl->fe.ie_on = c->value ? 1 : 0;
+ ctrl->fe.ie_after_sc = 0;
+ ret = fimc_hwset_image_effect(ctrl);
+ break;
+
+ case V4L2_CID_IMAGE_EFFECT_FN:
+ if (c->value < 0 || c->value > FIMC_EFFECT_FIN_SILHOUETTE)
+ return -EINVAL;
+ ctrl->fe.fin = c->value;
+ ret = 0;
+ break;
+
+ case V4L2_CID_IMAGE_EFFECT_CB:
+ ctrl->fe.pat_cb = c->value & 0xFF;
+ ret = 0;
+ break;
+
+ case V4L2_CID_IMAGE_EFFECT_CR:
+ ctrl->fe.pat_cr = c->value & 0xFF;
+ ret = 0;
+ break;
+
+ default:
+ /* try on subdev */
+ mutex_unlock(&ctrl->v4l2_lock);
+ if (2 != ctrl->id)
+ ret = subdev_call(ctrl, core, s_ctrl, c);
+ else
+ ret = 0;
+ mutex_lock(&ctrl->v4l2_lock);
+ break;
+ }
+
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ return ret;
+}
+
+int fimc_s_ext_ctrls_capture(void *fh, struct v4l2_ext_controls *c)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ret = 0;
+
+ mutex_lock(&ctrl->v4l2_lock);
+
+ /* try on subdev */
+ ret = subdev_call(ctrl, core, s_ext_ctrls, c);
+
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ return ret;
+}
+
+int fimc_cropcap_capture(void *fh, struct v4l2_cropcap *a)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ struct fimc_capinfo *cap = ctrl->cap;
+
+ fimc_dbg("%s\n", __func__);
+
+ if (!ctrl->cam || !ctrl->cam->sd || !ctrl->cap) {
+ fimc_err("%s: No capture device.\n", __func__);
+ return -ENODEV;
+ }
+
+ mutex_lock(&ctrl->v4l2_lock);
+
+ /* crop limitations */
+ cap->cropcap.bounds.left = 0;
+ cap->cropcap.bounds.top = 0;
+ cap->cropcap.bounds.width = ctrl->cam->width;
+ cap->cropcap.bounds.height = ctrl->cam->height;
+
+ /* crop default values */
+ cap->cropcap.defrect.left = 0;
+ cap->cropcap.defrect.top = 0;
+ cap->cropcap.defrect.width = ctrl->cam->width;
+ cap->cropcap.defrect.height = ctrl->cam->height;
+
+ a->bounds = cap->cropcap.bounds;
+ a->defrect = cap->cropcap.defrect;
+
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ return 0;
+}
+
+int fimc_g_crop_capture(void *fh, struct v4l2_crop *a)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+
+ fimc_dbg("%s\n", __func__);
+
+ if (!ctrl->cap) {
+ fimc_err("%s: No capture device.\n", __func__);
+ return -ENODEV;
+ }
+
+ mutex_lock(&ctrl->v4l2_lock);
+ a->c = ctrl->cap->crop;
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ return 0;
+}
+
+static int fimc_capture_crop_size_check(struct fimc_control *ctrl)
+{
+ struct fimc_capinfo *cap = ctrl->cap;
+ int win_hor_offset = 0, win_hor_offset2 = 0;
+ int win_ver_offset = 0, win_ver_offset2 = 0;
+ int crop_width = 0, crop_height = 0;
+
+ /* check win_hor_offset, win_hor_offset2 */
+ win_hor_offset = ctrl->cam->window.left;
+ win_hor_offset2 = ctrl->cam->width - ctrl->cam->window.left -
+ ctrl->cam->window.width;
+
+ win_ver_offset = ctrl->cam->window.top;
+ win_ver_offset2 = ctrl->cam->height - ctrl->cam->window.top -
+ ctrl->cam->window.height;
+
+ if (win_hor_offset < 0 || win_hor_offset2 < 0) {
+ fimc_err("%s: Offset (left-side(%d) or right-side(%d) "
+ "is negative.\n", __func__, \
+ win_hor_offset, win_hor_offset2);
+ return -1;
+ }
+
+ if (win_ver_offset < 0 || win_ver_offset2 < 0) {
+ fimc_err("%s: Offset (top-side(%d) or bottom-side(%d)) "
+ "is negative.\n", __func__, \
+ win_ver_offset, win_ver_offset2);
+ return -1;
+ }
+
+ if ((win_hor_offset % 2) || (win_hor_offset2 % 2)) {
+ fimc_err("%s: win_hor_offset must be multiple of 2\n", \
+ __func__);
+ return -1;
+ }
+
+ /* check crop_width, crop_height */
+ crop_width = ctrl->cam->window.width;
+ crop_height = ctrl->cam->window.height;
+
+ if (crop_width % 16) {
+ fimc_err("%s: crop_width must be multiple of 16\n", __func__);
+ return -1;
+ }
+
+ switch (cap->fmt.pixelformat) {
+ case V4L2_PIX_FMT_YUV420: /* fall through */
+ case V4L2_PIX_FMT_NV12: /* fall through */
+ case V4L2_PIX_FMT_NV21: /* fall through */
+ case V4L2_PIX_FMT_NV12T: /* fall through */
+ if ((crop_height % 2) || (crop_height < 8)) {
+ fimc_err("%s: crop_height error!\n", __func__);
+ return -1;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/** Given crop parameters are w.r.t. target resolution. Scale
+ * it w.r.t. camera source resolution.
+ *
+ * Steps:
+ * 1. Scale as camera resolution with fixed-point calculation
+ * 2. Check for overflow condition
+ * 3. Apply FIMC constrainsts
+ */
+static void fimc_capture_update_crop_window(struct fimc_control *ctrl)
+{
+ unsigned int zoom_hor = 0;
+ unsigned int zoom_ver = 0;
+ unsigned int multiplier = 1024;
+
+ if (!ctrl->cam->width || !ctrl->cam->height)
+ return;
+
+ zoom_hor = ctrl->cap->fmt.width * multiplier / ctrl->cam->width;
+ zoom_ver = ctrl->cap->fmt.height * multiplier / ctrl->cam->height;
+
+ if (!zoom_hor || !zoom_ver)
+ return;
+
+ /* Width */
+ ctrl->cam->window.width = ctrl->cap->crop.width * multiplier / zoom_hor;
+ if (ctrl->cam->window.width > ctrl->cam->width)
+ ctrl->cam->window.width = ctrl->cam->width;
+ if (ctrl->cam->window.width % 16)
+ ctrl->cam->window.width =
+ (ctrl->cam->window.width + 0xF) & ~0xF;
+
+ /* Left offset */
+ ctrl->cam->window.left = ctrl->cap->crop.left * multiplier / zoom_hor;
+ if (ctrl->cam->window.width + ctrl->cam->window.left > ctrl->cam->width)
+ ctrl->cam->window.left =
+ (ctrl->cam->width - ctrl->cam->window.width)/2;
+ if (ctrl->cam->window.left % 2)
+ ctrl->cam->window.left--;
+
+ /* Height */
+ ctrl->cam->window.height =
+ (ctrl->cap->crop.height * multiplier) / zoom_ver;
+ if (ctrl->cam->window.top > ctrl->cam->height)
+ ctrl->cam->window.height = ctrl->cam->height;
+ if (ctrl->cam->window.height % 2)
+ ctrl->cam->window.height--;
+
+ /* Top offset */
+ ctrl->cam->window.top = ctrl->cap->crop.top * multiplier / zoom_ver;
+ if (ctrl->cam->window.height + ctrl->cam->window.top >
+ ctrl->cam->height)
+ ctrl->cam->window.top =
+ (ctrl->cam->height - ctrl->cam->window.height)/2;
+ if (ctrl->cam->window.top % 2)
+ ctrl->cam->window.top--;
+
+ fimc_dbg("Cam (%dx%d) Crop: (%d %d %d %d) Win: (%d %d %d %d)\n", \
+ ctrl->cam->width, ctrl->cam->height, \
+ ctrl->cap->crop.left, ctrl->cap->crop.top, \
+ ctrl->cap->crop.width, ctrl->cap->crop.height, \
+ ctrl->cam->window.left, ctrl->cam->window.top, \
+ ctrl->cam->window.width, ctrl->cam->window.height);
+
+}
+
+int fimc_s_crop_capture(void *fh, struct v4l2_crop *a)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ret = 0;
+
+ fimc_dbg("%s\n", __func__);
+
+ if (!ctrl->cap) {
+ fimc_err("%s: No capture device.\n", __func__);
+ return -ENODEV;
+ }
+
+ mutex_lock(&ctrl->v4l2_lock);
+ ctrl->cap->crop = a->c;
+
+ fimc_capture_update_crop_window(ctrl);
+
+ ret = fimc_capture_crop_size_check(ctrl);
+ if (ret < 0) {
+ mutex_unlock(&ctrl->v4l2_lock);
+ fimc_err("%s: Invalid crop parameters.\n", __func__);
+ return -EINVAL;
+ }
+
+ if (ctrl->status == FIMC_STREAMON &&
+ ctrl->cap->fmt.pixelformat != V4L2_PIX_FMT_JPEG) {
+ fimc_hwset_shadow_disable(ctrl);
+ fimc_hwset_camera_offset(ctrl);
+ fimc_capture_scaler_info(ctrl);
+ fimc_hwset_prescaler(ctrl, &ctrl->sc);
+ fimc_hwset_scaler(ctrl, &ctrl->sc);
+ fimc_hwset_shadow_enable(ctrl);
+ }
+
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ return 0;
+}
+
+int fimc_start_capture(struct fimc_control *ctrl)
+{
+ fimc_dbg("%s\n", __func__);
+
+ if (!ctrl->sc.bypass)
+ fimc_hwset_start_scaler(ctrl);
+
+ fimc_hwset_enable_capture(ctrl, ctrl->sc.bypass);
+
+ return 0;
+}
+
+int fimc_stop_capture(struct fimc_control *ctrl)
+{
+ fimc_dbg("%s\n", __func__);
+
+ if (ctrl->cap->lastirq) {
+ fimc_hwset_enable_lastirq(ctrl);
+ fimc_hwset_disable_capture(ctrl);
+ fimc_hwset_disable_lastirq(ctrl);
+ ctrl->cap->lastirq = 0;
+ } else {
+ fimc_hwset_disable_capture(ctrl);
+ }
+
+ fimc_hwset_disable_irq(ctrl);
+ fimc_hwset_clear_irq(ctrl);
+
+ if (!ctrl->sc.bypass)
+ fimc_hwset_stop_scaler(ctrl);
+ else
+ ctrl->sc.bypass = 0;
+
+ fimc_wait_disable_capture(ctrl);
+
+ return 0;
+}
+
+static void fimc_reset_capture(struct fimc_control *ctrl)
+{
+ int i;
+
+ ctrl->status = FIMC_READY_OFF;
+
+ fimc_stop_capture(ctrl);
+
+ for (i = 0; i < FIMC_PINGPONG; i++)
+ fimc_add_inqueue(ctrl, ctrl->cap->outq[i]);
+
+ fimc_hwset_reset(ctrl);
+
+ if (0 != ctrl->id)
+ fimc_clk_en(ctrl, false);
+
+ ctrl->status = FIMC_STREAMOFF;
+}
+
+
+int fimc_streamon_capture(void *fh)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ struct fimc_capinfo *cap = ctrl->cap;
+ int rot;
+ int ret;
+
+ fimc_dbg("%s\n", __func__);
+
+ if (!ctrl->cam || !ctrl->cam->sd) {
+ fimc_err("%s: No capture device.\n", __func__);
+ return -ENODEV;
+ }
+
+ if (ctrl->status == FIMC_STREAMON) {
+ fimc_err("%s: Camera already running.\n", __func__);
+ return -EBUSY;
+ }
+
+ mutex_lock(&ctrl->v4l2_lock);
+
+ if (0 != ctrl->id)
+ fimc_clk_en(ctrl, true);
+
+ ctrl->status = FIMC_READY_ON;
+ cap->irq = 0;
+
+ fimc_hwset_enable_irq(ctrl, 0, 1);
+
+ if (!ctrl->cam->initialized)
+ fimc_camera_init(ctrl);
+
+ if (ctrl->id != 2 &&
+ ctrl->cap->fmt.colorspace != V4L2_COLORSPACE_JPEG) {
+ ret = fimc_camera_start(ctrl);
+ if (ret < 0) {
+ fimc_reset_capture(ctrl);
+ mutex_unlock(&ctrl->v4l2_lock);
+ return ret;
+ }
+ }
+
+ fimc_hwset_camera_type(ctrl);
+ fimc_hwset_camera_polarity(ctrl);
+ fimc_update_hwaddr(ctrl);
+
+ if (cap->fmt.pixelformat != V4L2_PIX_FMT_JPEG) {
+ fimc_hwset_camera_source(ctrl);
+ fimc_hwset_camera_offset(ctrl);
+
+ fimc_capture_scaler_info(ctrl);
+ fimc_hwset_prescaler(ctrl, &ctrl->sc);
+ fimc_hwset_scaler(ctrl, &ctrl->sc);
+
+ fimc_hwset_output_colorspace(ctrl, cap->fmt.pixelformat);
+ fimc_hwset_output_addr_style(ctrl, cap->fmt.pixelformat);
+ fimc_hwset_output_area(ctrl, cap->fmt.width, cap->fmt.height);
+
+ if (cap->fmt.pixelformat == V4L2_PIX_FMT_RGB32 ||
+ cap->fmt.pixelformat == V4L2_PIX_FMT_RGB565)
+ fimc_hwset_output_rgb(ctrl, cap->fmt.pixelformat);
+ else
+ fimc_hwset_output_yuv(ctrl, cap->fmt.pixelformat);
+
+ fimc_hwset_output_size(ctrl, cap->fmt.width, cap->fmt.height);
+
+ fimc_hwset_output_scan(ctrl, &cap->fmt);
+ fimc_hwset_output_rot_flip(ctrl, cap->rotate, cap->flip);
+ rot = fimc_mapping_rot_flip(cap->rotate, cap->flip);
+
+ if (rot & FIMC_ROT) {
+ fimc_hwset_org_output_size(ctrl, cap->fmt.height,
+ cap->fmt.width);
+ } else {
+ fimc_hwset_org_output_size(ctrl, cap->fmt.width,
+ cap->fmt.height);
+ }
+ fimc_hwset_jpeg_mode(ctrl, false);
+ } else {
+ fimc_hwset_output_area_size(ctrl, \
+ fimc_camera_get_jpeg_memsize(ctrl)/2);
+ fimc_hwset_jpeg_mode(ctrl, true);
+ }
+
+ if (ctrl->cap->fmt.colorspace == V4L2_COLORSPACE_JPEG)
+ fimc_hwset_scaler_bypass(ctrl);
+
+ fimc_start_capture(ctrl);
+
+ if (ctrl->cap->fmt.colorspace == V4L2_COLORSPACE_JPEG &&
+ ctrl->id != 2) {
+ struct v4l2_control cam_ctrl;
+
+ cam_ctrl.id = V4L2_CID_CAM_CAPTURE;
+ ret = subdev_call(ctrl, core, s_ctrl, &cam_ctrl);
+ if (ret < 0 && ret != -ENOIOCTLCMD) {
+ fimc_reset_capture(ctrl);
+ mutex_unlock(&ctrl->v4l2_lock);
+ fimc_err("%s: Error in V4L2_CID_CAM_CAPTURE\n", \
+ __func__);
+ return -EPERM;
+ }
+ }
+
+ ctrl->status = FIMC_STREAMON;
+
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ return 0;
+}
+
+int fimc_streamoff_capture(void *fh)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+
+ fimc_dbg("%s\n", __func__);
+
+ if (!ctrl->cap || !ctrl->cam || !ctrl->cam->sd) {
+ fimc_err("%s: No capture info.\n", __func__);
+ return -ENODEV;
+ }
+
+ mutex_lock(&ctrl->v4l2_lock);
+ fimc_reset_capture(ctrl);
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ return 0;
+}
+
+int fimc_qbuf_capture(void *fh, struct v4l2_buffer *b)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+
+ if (!ctrl->cap || !ctrl->cap->nr_bufs) {
+ fimc_err("%s: Invalid capture setting.\n", __func__);
+ return -EINVAL;
+ }
+
+ if (b->memory != V4L2_MEMORY_MMAP) {
+ fimc_err("%s: invalid memory type\n", __func__);
+ return -EINVAL;
+ }
+
+ mutex_lock(&ctrl->v4l2_lock);
+ fimc_add_inqueue(ctrl, b->index);
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ return 0;
+}
+
+int fimc_dqbuf_capture(void *fh, struct v4l2_buffer *b)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ struct fimc_capinfo *cap;
+ int pp, ret = 0;
+
+ if (!ctrl->cap || !ctrl->cap->nr_bufs) {
+ fimc_err("%s: Invalid capture setting.\n", __func__);
+ return -EINVAL;
+ }
+
+ if (b->memory != V4L2_MEMORY_MMAP) {
+ fimc_err("%s: invalid memory type\n", __func__);
+ return -EINVAL;
+ }
+
+ cap = ctrl->cap;
+
+ mutex_lock(&ctrl->v4l2_lock);
+
+ if (ctrl->status != FIMC_STREAMON) {
+ mutex_unlock(&ctrl->v4l2_lock);
+ fimc_dbg("%s: FIMC is not active.\n", __func__);
+ return -EINVAL;
+ }
+
+ /* find out the real index */
+ pp = ((fimc_hwget_frame_count(ctrl) + 2) % 4);
+
+ /* We have read the latest frame, hence should reset availability
+ * flag
+ */
+ cap->irq = 0;
+
+ /* skip even frame: no data */
+ if (cap->fmt.field == V4L2_FIELD_INTERLACED_TB)
+ pp &= ~0x1;
+
+ b->index = cap->outq[pp];
+ fimc_dbg("%s: buffer(%d) outq[%d]\n", __func__, b->index, pp);
+
+ ret = fimc_add_outqueue(ctrl, pp);
+ if (ret) {
+ b->index = -1;
+ fimc_err("%s: no inqueue buffer\n", __func__);
+ }
+
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ /* fimc_dbg("%s: buf_index = %d\n", __func__, b->index); */
+
+ return ret;
+}
+
diff --git a/drivers/media/video/samsung/fimc/fimc_dev.c b/drivers/media/video/samsung/fimc/fimc_dev.c
new file mode 100644
index 0000000..17945d4
--- /dev/null
+++ b/drivers/media/video/samsung/fimc/fimc_dev.c
@@ -0,0 +1,1688 @@
+/* linux/drivers/media/video/samsung/fimc/fimc_dev.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Core file for Samsung Camera Interface (FIMC) driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/clk.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/poll.h>
+#include <linux/wait.h>
+#include <linux/fs.h>
+#include <linux/irq.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <media/v4l2-device.h>
+#include <linux/io.h>
+#include <linux/memory.h>
+#include <linux/ctype.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <plat/clock.h>
+#include <plat/media.h>
+#include <mach/media.h>
+#include <plat/fimc.h>
+#include <linux/videodev2_samsung.h>
+#include <linux/delay.h>
+#include <plat/regs-fimc.h>
+
+#include "fimc.h"
+
+struct fimc_global *fimc_dev;
+
+int fimc_dma_alloc(struct fimc_control *ctrl, struct fimc_buf_set *bs,
+ int i, int align)
+{
+ dma_addr_t end, *curr;
+
+ mutex_lock(&ctrl->alloc_lock);
+
+ end = ctrl->mem.base + ctrl->mem.size;
+ curr = &ctrl->mem.curr;
+
+ if (!bs->length[i])
+ return -EINVAL;
+
+ if (!align) {
+ if (*curr + bs->length[i] > end) {
+ goto overflow;
+ } else {
+ bs->base[i] = *curr;
+ bs->garbage[i] = 0;
+ *curr += bs->length[i];
+ }
+ } else {
+ if (ALIGN(*curr, align) + bs->length[i] > end)
+ goto overflow;
+ else {
+ bs->base[i] = ALIGN(*curr, align);
+ bs->garbage[i] = ALIGN(*curr, align) - *curr;
+ *curr += (bs->length[i] + bs->garbage[i]);
+ }
+ }
+
+ mutex_unlock(&ctrl->alloc_lock);
+
+ return 0;
+
+overflow:
+ bs->base[i] = 0;
+ bs->length[i] = 0;
+ bs->garbage[i] = 0;
+
+ mutex_unlock(&ctrl->alloc_lock);
+
+ return -ENOMEM;
+}
+
+void fimc_dma_free(struct fimc_control *ctrl, struct fimc_buf_set *bs, int i)
+{
+ int total = bs->length[i] + bs->garbage[i];
+ mutex_lock(&ctrl->alloc_lock);
+
+ if (bs->base[i]) {
+ if (ctrl->mem.curr - total >= ctrl->mem.base)
+ ctrl->mem.curr -= total;
+
+ bs->base[i] = 0;
+ bs->length[i] = 0;
+ bs->garbage[i] = 0;
+ }
+
+ mutex_unlock(&ctrl->alloc_lock);
+}
+
+void fimc_clk_en(struct fimc_control *ctrl, bool on)
+{
+ struct platform_device *pdev;
+ struct s3c_platform_fimc *pdata;
+ struct clk *lclk;
+
+ pdev = to_platform_device(ctrl->dev);
+ pdata = to_fimc_plat(ctrl->dev);
+ lclk = clk_get(&pdev->dev, pdata->lclk_name);
+
+ if (on) {
+ if (!lclk->usage) {
+ if (!ctrl->out)
+ fimc_info1("(%d) Clock %s(%d) enabled.\n",
+ ctrl->id, ctrl->clk->name,
+ ctrl->clk->id);
+
+ /* Turn on fimc power domain regulator */
+ regulator_enable(ctrl->regulator);
+ clk_enable(lclk);
+ }
+ } else {
+ while (lclk->usage > 0) {
+ if (!ctrl->out)
+ fimc_info1("(%d) Clock %s(%d) disabled.\n",
+ ctrl->id, ctrl->clk->name,
+ ctrl->clk->id);
+ clk_disable(lclk);
+ /* Turn off fimc power domain regulator */
+ regulator_disable(ctrl->regulator);
+ }
+ }
+
+}
+
+static inline u32 fimc_irq_out_single_buf(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ int ret = -1, ctx_num, next;
+ u32 wakeup = 1;
+
+ if (ctx->status == FIMC_READY_OFF) {
+ ctrl->out->idxs.active.ctx = -1;
+ ctrl->out->idxs.active.idx = -1;
+ ctx->status = FIMC_STREAMOFF;
+ ctrl->status = FIMC_STREAMOFF;
+
+ return wakeup;
+ }
+
+ ctx->status = FIMC_STREAMON_IDLE;
+
+ /* Attach done buffer to outgoing queue. */
+ ret = fimc_push_outq(ctrl, ctx, ctrl->out->idxs.active.idx);
+ if (ret < 0)
+ fimc_err("Failed: fimc_push_outq\n");
+
+ /* Detach buffer from incomming queue. */
+ ret = fimc_pop_inq(ctrl, &ctx_num, &next);
+ if (ret == 0) { /* There is a buffer in incomming queue. */
+ if (ctx_num != ctrl->out->last_ctx) {
+ ctx = &ctrl->out->ctx[ctx_num];
+ ctrl->out->last_ctx = ctx->ctx_num;
+ fimc_outdev_set_ctx_param(ctrl, ctx);
+ }
+
+ fimc_outdev_set_src_addr(ctrl, ctx->src[next].base);
+
+ fimc_output_set_dst_addr(ctrl, ctx, next);
+
+ ret = fimc_outdev_start_camif(ctrl);
+ if (ret < 0)
+ fimc_err("Fail: fimc_start_camif\n");
+
+ ctrl->out->idxs.active.ctx = ctx_num;
+ ctrl->out->idxs.active.idx = next;
+ ctx->status = FIMC_STREAMON;
+ ctrl->status = FIMC_STREAMON;
+ } else { /* There is no buffer in incomming queue. */
+ ctrl->out->idxs.active.ctx = -1;
+ ctrl->out->idxs.active.idx = -1;
+ ctx->status = FIMC_STREAMON_IDLE;
+ ctrl->status = FIMC_STREAMON_IDLE;
+ }
+
+ return wakeup;
+}
+
+static inline u32 fimc_irq_out_multi_buf(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ int ret = -1, ctx_num, next;
+ u32 wakeup = 1;
+
+ if (ctx->status == FIMC_READY_OFF) {
+ if (ctrl->out->idxs.active.ctx == ctx->ctx_num) {
+ ctrl->out->idxs.active.ctx = -1;
+ ctrl->out->idxs.active.idx = -1;
+ }
+
+ ctx->status = FIMC_STREAMOFF;
+
+ return wakeup;
+ }
+
+ /* Attach done buffer to outgoing queue. */
+ ret = fimc_push_outq(ctrl, ctx, ctrl->out->idxs.active.idx);
+ if (ret < 0)
+ fimc_err("Failed: fimc_push_outq\n");
+
+ /* Detach buffer from incomming queue. */
+ ret = fimc_pop_inq(ctrl, &ctx_num, &next);
+ if (ret == 0) { /* There is a buffer in incomming queue. */
+ if (ctx_num != ctrl->out->last_ctx) {
+ ctx = &ctrl->out->ctx[ctx_num];
+ ctrl->out->last_ctx = ctx->ctx_num;
+ fimc_outdev_set_ctx_param(ctrl, ctx);
+ }
+
+ fimc_outdev_set_src_addr(ctrl, ctx->src[next].base);
+
+ fimc_output_set_dst_addr(ctrl, ctx, next);
+
+ ret = fimc_outdev_start_camif(ctrl);
+ if (ret < 0)
+ fimc_err("Fail: fimc_start_camif\n");
+
+ ctrl->out->idxs.active.ctx = ctx_num;
+ ctrl->out->idxs.active.idx = next;
+ ctx->status = FIMC_STREAMON;
+ ctrl->status = FIMC_STREAMON;
+ } else { /* There is no buffer in incomming queue. */
+ ctrl->out->idxs.active.ctx = -1;
+ ctrl->out->idxs.active.idx = -1;
+ ctx->status = FIMC_STREAMON_IDLE;
+ ctrl->status = FIMC_STREAMON_IDLE;
+ }
+
+ return wakeup;
+}
+
+static inline u32 fimc_irq_out_dma(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ struct fimc_buf_set buf_set;
+ int idx = ctrl->out->idxs.active.idx;
+ int ret = -1, i, ctx_num, next;
+ u32 wakeup = 1;
+
+ if (ctx->status == FIMC_READY_OFF) {
+ ctrl->out->idxs.active.ctx = -1;
+ ctrl->out->idxs.active.idx = -1;
+ ctx->status = FIMC_STREAMOFF;
+ ctrl->status = FIMC_STREAMOFF;
+ return wakeup;
+ }
+
+ /* Attach done buffer to outgoing queue. */
+ ret = fimc_push_outq(ctrl, ctx, idx);
+ if (ret < 0)
+ fimc_err("Failed: fimc_push_outq\n");
+
+ if (ctx->overlay.mode == FIMC_OVLY_DMA_AUTO) {
+ struct s3cfb_window *win;
+ struct fb_info *fbinfo;
+
+ fbinfo = registered_fb[ctx->overlay.fb_id];
+ win = (struct s3cfb_window *)fbinfo->par;
+
+ win->other_mem_addr = ctx->dst[idx].base[FIMC_ADDR_Y];
+
+ ret = fb_pan_display(fbinfo, &fbinfo->var);
+ if (ret < 0) {
+ fimc_err("%s: fb_pan_display fail (ret=%d)\n",
+ __func__, ret);
+ return -EINVAL;
+ }
+ }
+
+ /* Detach buffer from incomming queue. */
+ ret = fimc_pop_inq(ctrl, &ctx_num, &next);
+ if (ret == 0) { /* There is a buffer in incomming queue. */
+ ctx = &ctrl->out->ctx[ctx_num];
+ fimc_outdev_set_src_addr(ctrl, ctx->src[next].base);
+
+ memset(&buf_set, 0x00, sizeof(buf_set));
+ buf_set.base[FIMC_ADDR_Y] = ctx->dst[next].base[FIMC_ADDR_Y];
+
+ for (i = 0; i < FIMC_PHYBUFS; i++)
+ fimc_hwset_output_address(ctrl, &buf_set, i);
+
+ ret = fimc_outdev_start_camif(ctrl);
+ if (ret < 0)
+ fimc_err("Fail: fimc_start_camif\n");
+
+ ctrl->out->idxs.active.ctx = ctx_num;
+ ctrl->out->idxs.active.idx = next;
+
+ ctx->status = FIMC_STREAMON;
+ ctrl->status = FIMC_STREAMON;
+ } else { /* There is no buffer in incomming queue. */
+ ctrl->out->idxs.active.ctx = -1;
+ ctrl->out->idxs.active.idx = -1;
+
+ ctx->status = FIMC_STREAMON_IDLE;
+ ctrl->status = FIMC_STREAMON_IDLE;
+ }
+
+ return wakeup;
+}
+
+static inline u32 fimc_irq_out_fimd(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ struct fimc_idx prev;
+ int ret = -1, ctx_num, next;
+ u32 wakeup = 0;
+
+ /* Attach done buffer to outgoing queue. */
+ if (ctrl->out->idxs.prev.idx != -1) {
+ ret = fimc_push_outq(ctrl, ctx, ctrl->out->idxs.prev.idx);
+ if (ret < 0) {
+ fimc_err("Failed: fimc_push_outq\n");
+ } else {
+ ctrl->out->idxs.prev.ctx = -1;
+ ctrl->out->idxs.prev.idx = -1;
+ wakeup = 1; /* To wake up fimc_v4l2_dqbuf */
+ }
+ }
+
+ /* Update index structure. */
+ if (ctrl->out->idxs.next.idx != -1) {
+ ctrl->out->idxs.active.ctx = ctrl->out->idxs.next.ctx;
+ ctrl->out->idxs.active.idx = ctrl->out->idxs.next.idx;
+ ctrl->out->idxs.next.idx = -1;
+ ctrl->out->idxs.next.ctx = -1;
+ }
+
+ /* Detach buffer from incomming queue. */
+ ret = fimc_pop_inq(ctrl, &ctx_num, &next);
+ if (ret == 0) { /* There is a buffer in incomming queue. */
+ prev.ctx = ctrl->out->idxs.active.ctx;
+ prev.idx = ctrl->out->idxs.active.idx;
+
+ ctrl->out->idxs.prev.ctx = prev.ctx;
+ ctrl->out->idxs.prev.idx = prev.idx;
+
+ ctrl->out->idxs.next.ctx = ctx_num;
+ ctrl->out->idxs.next.idx = next;
+
+ /* set source address */
+ fimc_outdev_set_src_addr(ctrl, ctx->src[next].base);
+ }
+
+ return wakeup;
+}
+
+static inline void fimc_irq_out(struct fimc_control *ctrl)
+{
+ struct fimc_ctx *ctx;
+ u32 wakeup = 1;
+ int ctx_num = ctrl->out->idxs.active.ctx;
+
+ /* Interrupt pendding clear */
+ fimc_hwset_clear_irq(ctrl);
+
+ /* check context num */
+ if (ctx_num < 0 || ctx_num >= FIMC_MAX_CTXS) {
+ fimc_err("fimc_irq_out: invalid ctx (ctx=%d)\n", ctx_num);
+ wake_up(&ctrl->wq);
+ return;
+ }
+
+ ctx = &ctrl->out->ctx[ctx_num];
+
+ switch (ctx->overlay.mode) {
+ case FIMC_OVLY_NONE_SINGLE_BUF:
+ wakeup = fimc_irq_out_single_buf(ctrl, ctx);
+ break;
+ case FIMC_OVLY_NONE_MULTI_BUF:
+ wakeup = fimc_irq_out_multi_buf(ctrl, ctx);
+ break;
+ case FIMC_OVLY_DMA_AUTO: /* fall through */
+ case FIMC_OVLY_DMA_MANUAL:
+ wakeup = fimc_irq_out_dma(ctrl, ctx);
+ break;
+ default:
+ fimc_err("[ctx=%d] fimc_irq_out: wrong overlay.mode (%d)\n",
+ ctx_num, ctx->overlay.mode);
+ break;
+ }
+
+ if (wakeup == 1)
+ wake_up(&ctrl->wq);
+}
+
+static inline void fimc_irq_cap(struct fimc_control *ctrl)
+{
+ struct fimc_capinfo *cap = ctrl->cap;
+ int pp;
+ u32 cfg;
+
+ fimc_hwset_clear_irq(ctrl);
+ if (fimc_hwget_overflow_state(ctrl)) {
+ /* s/w reset -- added for recovering module in ESD state*/
+ cfg = readl(ctrl->regs + S3C_CIGCTRL);
+ cfg |= (S3C_CIGCTRL_SWRST);
+ writel(cfg, ctrl->regs + S3C_CIGCTRL);
+ msleep(1);
+
+ cfg = readl(ctrl->regs + S3C_CIGCTRL);
+ cfg &= ~S3C_CIGCTRL_SWRST;
+ writel(cfg, ctrl->regs + S3C_CIGCTRL);
+ }
+ pp = ((fimc_hwget_frame_count(ctrl) + 2) % 4);
+ if (cap->fmt.field == V4L2_FIELD_INTERLACED_TB) {
+ /* odd value of pp means one frame is made with top/bottom */
+ if (pp & 0x1) {
+ cap->irq = 1;
+ wake_up(&ctrl->wq);
+ }
+ } else {
+ cap->irq = 1;
+ wake_up(&ctrl->wq);
+ }
+}
+
+static irqreturn_t fimc_irq(int irq, void *dev_id)
+{
+ struct fimc_control *ctrl = (struct fimc_control *) dev_id;
+
+ if (ctrl->cap)
+ fimc_irq_cap(ctrl);
+ else if (ctrl->out)
+ fimc_irq_out(ctrl);
+
+ return IRQ_HANDLED;
+}
+
+static
+struct fimc_control *fimc_register_controller(struct platform_device *pdev)
+{
+ struct s3c_platform_fimc *pdata;
+ struct fimc_control *ctrl;
+ struct resource *res;
+ int id, mdev_id;
+
+ id = pdev->id;
+ mdev_id = S5P_MDEV_FIMC0 + id;
+ pdata = to_fimc_plat(&pdev->dev);
+
+ ctrl = get_fimc_ctrl(id);
+ ctrl->id = id;
+ ctrl->dev = &pdev->dev;
+ ctrl->vd = &fimc_video_device[id];
+ ctrl->vd->minor = id;
+
+ /* alloc from bank1 as default */
+ ctrl->mem.base = pdata->pmem_start;
+ ctrl->mem.size = pdata->pmem_size;
+ ctrl->mem.curr = ctrl->mem.base;
+
+ ctrl->status = FIMC_STREAMOFF;
+ switch (pdata->hw_ver) {
+ case 0x40:
+ ctrl->limit = &fimc40_limits[id];
+ break;
+ case 0x43:
+ case 0x45:
+ ctrl->limit = &fimc43_limits[id];
+ break;
+ case 0x50:
+ ctrl->limit = &fimc50_limits[id];
+ break;
+ }
+
+ ctrl->log = FIMC_LOG_DEFAULT;
+
+ sprintf(ctrl->name, "%s%d", FIMC_NAME, id);
+ strcpy(ctrl->vd->name, ctrl->name);
+
+ atomic_set(&ctrl->in_use, 0);
+ mutex_init(&ctrl->lock);
+ mutex_init(&ctrl->alloc_lock);
+ mutex_init(&ctrl->v4l2_lock);
+ init_waitqueue_head(&ctrl->wq);
+
+ /* get resource for io memory */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ fimc_err("%s: failed to get io memory region\n", __func__);
+ return NULL;
+ }
+
+ /* request mem region */
+ res = request_mem_region(res->start, res->end - res->start + 1,
+ pdev->name);
+ if (!res) {
+ fimc_err("%s: failed to request io memory region\n", __func__);
+ return NULL;
+ }
+
+ /* ioremap for register block */
+ ctrl->regs = ioremap(res->start, res->end - res->start + 1);
+ if (!ctrl->regs) {
+ fimc_err("%s: failed to remap io region\n", __func__);
+ return NULL;
+ }
+
+ /* irq */
+ ctrl->irq = platform_get_irq(pdev, 0);
+ if (request_irq(ctrl->irq, fimc_irq, IRQF_DISABLED, ctrl->name, ctrl))
+ fimc_err("%s: request_irq failed\n", __func__);
+
+ fimc_hwset_reset(ctrl);
+
+ return ctrl;
+}
+
+static int fimc_unregister_controller(struct platform_device *pdev)
+{
+ struct s3c_platform_fimc *pdata;
+ struct fimc_control *ctrl;
+ int id = pdev->id;
+
+ pdata = to_fimc_plat(&pdev->dev);
+ ctrl = get_fimc_ctrl(id);
+
+ free_irq(ctrl->irq, ctrl);
+ mutex_destroy(&ctrl->lock);
+ mutex_destroy(&ctrl->alloc_lock);
+ mutex_destroy(&ctrl->v4l2_lock);
+
+ fimc_clk_en(ctrl, false);
+
+ iounmap(ctrl->regs);
+ memset(ctrl, 0, sizeof(*ctrl));
+
+ return 0;
+}
+
+static void fimc_mmap_open(struct vm_area_struct *vma)
+{
+ struct fimc_global *dev = fimc_dev;
+ int pri_data = (int)vma->vm_private_data;
+ u32 id = pri_data / 0x100;
+ u32 ctx = (pri_data - (id * 0x100)) / 0x10;
+ u32 idx = pri_data % 0x10;
+
+ atomic_inc(&dev->ctrl[id].out->ctx[ctx].src[idx].mapped_cnt);
+}
+
+static void fimc_mmap_close(struct vm_area_struct *vma)
+{
+ struct fimc_global *dev = fimc_dev;
+ int pri_data = (int)vma->vm_private_data;
+ u32 id = pri_data / 0x100;
+ u32 ctx = (pri_data - (id * 0x100)) / 0x10;
+ u32 idx = pri_data % 0x10;
+
+ atomic_dec(&dev->ctrl[id].out->ctx[ctx].src[idx].mapped_cnt);
+}
+
+static struct vm_operations_struct fimc_mmap_ops = {
+ .open = fimc_mmap_open,
+ .close = fimc_mmap_close,
+};
+
+static inline
+int fimc_mmap_out_src(struct file *filp, struct vm_area_struct *vma)
+{
+ struct fimc_prv_data *prv_data =
+ (struct fimc_prv_data *)filp->private_data;
+ struct fimc_control *ctrl = prv_data->ctrl;
+ int ctx_id = prv_data->ctx_id;
+ struct fimc_ctx *ctx = &ctrl->out->ctx[ctx_id];
+ u32 start_phy_addr = 0;
+ u32 size = vma->vm_end - vma->vm_start;
+ u32 pfn, idx = vma->vm_pgoff;
+ u32 buf_length = 0;
+ int pri_data = 0;
+
+ buf_length = PAGE_ALIGN(ctx->src[idx].length[FIMC_ADDR_Y] +
+ ctx->src[idx].length[FIMC_ADDR_CB] +
+ ctx->src[idx].length[FIMC_ADDR_CR]);
+ if (size > PAGE_ALIGN(buf_length)) {
+ fimc_err("Requested mmap size is too big\n");
+ return -EINVAL;
+ }
+
+ pri_data = (ctrl->id * 0x100) + (ctx_id * 0x10) + idx;
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ vma->vm_flags |= VM_RESERVED;
+ vma->vm_ops = &fimc_mmap_ops;
+ vma->vm_private_data = (void *)pri_data;
+
+ if ((vma->vm_flags & VM_WRITE) && !(vma->vm_flags & VM_SHARED)) {
+ fimc_err("writable mapping must be shared\n");
+ return -EINVAL;
+ }
+
+ start_phy_addr = ctx->src[idx].base[FIMC_ADDR_Y];
+ pfn = __phys_to_pfn(start_phy_addr);
+
+ if (remap_pfn_range(vma, vma->vm_start, pfn, size, vma->vm_page_prot)) {
+ fimc_err("mmap fail\n");
+ return -EINVAL;
+ }
+
+ vma->vm_ops->open(vma);
+
+ ctx->src[idx].flags |= V4L2_BUF_FLAG_MAPPED;
+
+ return 0;
+}
+
+static inline
+int fimc_mmap_out_dst(struct file *filp, struct vm_area_struct *vma, u32 idx)
+{
+ struct fimc_prv_data *prv_data =
+ (struct fimc_prv_data *)filp->private_data;
+ struct fimc_control *ctrl = prv_data->ctrl;
+ int ctx_id = prv_data->ctx_id;
+ unsigned long pfn = 0, size;
+ int ret = 0;
+
+ size = vma->vm_end - vma->vm_start;
+
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ vma->vm_flags |= VM_RESERVED;
+
+ pfn = __phys_to_pfn(ctrl->out->ctx[ctx_id].dst[idx].base[0]);
+ ret = remap_pfn_range(vma, vma->vm_start, pfn, size, vma->vm_page_prot);
+ if (ret != 0)
+ fimc_err("remap_pfn_range fail.\n");
+
+ return ret;
+}
+
+static inline int fimc_mmap_out(struct file *filp, struct vm_area_struct *vma)
+{
+ struct fimc_prv_data *prv_data =
+ (struct fimc_prv_data *)filp->private_data;
+ struct fimc_control *ctrl = prv_data->ctrl;
+ int ctx_id = prv_data->ctx_id;
+ int idx = ctrl->out->ctx[ctx_id].overlay.req_idx;
+ int ret = -1;
+
+ if (idx >= 0)
+ ret = fimc_mmap_out_dst(filp, vma, idx);
+ else if (idx == FIMC_MMAP_IDX)
+ ret = fimc_mmap_out_src(filp, vma);
+
+ return ret;
+}
+
+static inline int fimc_mmap_cap(struct file *filp, struct vm_area_struct *vma)
+{
+ struct fimc_prv_data *prv_data =
+ (struct fimc_prv_data *)filp->private_data;
+ struct fimc_control *ctrl = prv_data->ctrl;
+ u32 size = vma->vm_end - vma->vm_start;
+ u32 pfn, idx = vma->vm_pgoff;
+
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ vma->vm_flags |= VM_RESERVED;
+
+ /*
+ * page frame number of the address for a source frame
+ * to be stored at.
+ */
+ pfn = __phys_to_pfn(ctrl->cap->bufs[idx].base[0]);
+
+ if ((vma->vm_flags & VM_WRITE) && !(vma->vm_flags & VM_SHARED)) {
+ fimc_err("%s: writable mapping must be shared\n", __func__);
+ return -EINVAL;
+ }
+
+ if (remap_pfn_range(vma, vma->vm_start, pfn, size, vma->vm_page_prot)) {
+ fimc_err("%s: mmap fail\n", __func__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int fimc_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ struct fimc_prv_data *prv_data =
+ (struct fimc_prv_data *)filp->private_data;
+ struct fimc_control *ctrl = prv_data->ctrl;
+ int ret;
+
+ if (ctrl->cap)
+ ret = fimc_mmap_cap(filp, vma);
+ else
+ ret = fimc_mmap_out(filp, vma);
+
+ return ret;
+}
+
+static u32 fimc_poll(struct file *filp, poll_table *wait)
+{
+ struct fimc_prv_data *prv_data =
+ (struct fimc_prv_data *)filp->private_data;
+ struct fimc_control *ctrl = prv_data->ctrl;
+ struct fimc_capinfo *cap = ctrl->cap;
+ u32 mask = 0;
+
+ if (cap) {
+ if (cap->irq || (ctrl->status != FIMC_STREAMON)) {
+ mask = POLLIN | POLLRDNORM;
+ cap->irq = 0;
+ } else {
+ poll_wait(filp, &ctrl->wq, wait);
+ }
+ }
+
+ return mask;
+}
+
+static
+ssize_t fimc_read(struct file *filp, char *buf, size_t count, loff_t *pos)
+{
+ return 0;
+}
+
+static
+ssize_t fimc_write(struct file *filp, const char *b, size_t c, loff_t *offset)
+{
+ return 0;
+}
+
+u32 fimc_mapping_rot_flip(u32 rot, u32 flip)
+{
+ u32 ret = 0;
+
+ switch (rot) {
+ case 0:
+ if (flip & FIMC_XFLIP)
+ ret |= FIMC_XFLIP;
+
+ if (flip & FIMC_YFLIP)
+ ret |= FIMC_YFLIP;
+ break;
+
+ case 90:
+ ret = FIMC_ROT;
+ if (flip & FIMC_XFLIP)
+ ret |= FIMC_XFLIP;
+
+ if (flip & FIMC_YFLIP)
+ ret |= FIMC_YFLIP;
+ break;
+
+ case 180:
+ ret = (FIMC_XFLIP | FIMC_YFLIP);
+ if (flip & FIMC_XFLIP)
+ ret &= ~FIMC_XFLIP;
+
+ if (flip & FIMC_YFLIP)
+ ret &= ~FIMC_YFLIP;
+ break;
+
+ case 270:
+ ret = (FIMC_XFLIP | FIMC_YFLIP | FIMC_ROT);
+ if (flip & FIMC_XFLIP)
+ ret &= ~FIMC_XFLIP;
+
+ if (flip & FIMC_YFLIP)
+ ret &= ~FIMC_YFLIP;
+ break;
+ }
+
+ return ret;
+}
+
+int fimc_get_scaler_factor(u32 src, u32 tar, u32 *ratio, u32 *shift)
+{
+ if (src >= tar * 64) {
+ return -EINVAL;
+ } else if (src >= tar * 32) {
+ *ratio = 32;
+ *shift = 5;
+ } else if (src >= tar * 16) {
+ *ratio = 16;
+ *shift = 4;
+ } else if (src >= tar * 8) {
+ *ratio = 8;
+ *shift = 3;
+ } else if (src >= tar * 4) {
+ *ratio = 4;
+ *shift = 2;
+ } else if (src >= tar * 2) {
+ *ratio = 2;
+ *shift = 1;
+ } else {
+ *ratio = 1;
+ *shift = 0;
+ }
+
+ return 0;
+}
+
+void fimc_get_nv12t_size(int img_hres, int img_vres,
+ int *y_size, int *cb_size)
+{
+ int remain;
+ int y_hres_byte, y_vres_byte;
+ int cb_hres_byte, cb_vres_byte;
+ int y_hres_roundup, y_vres_roundup;
+ int cb_hres_roundup, cb_vres_roundup;
+
+ /* to make 'img_hres and img_vres' be 16 multiple */
+ remain = img_hres % 16;
+ if (remain != 0) {
+ remain = 16 - remain;
+ img_hres = img_hres + remain;
+ }
+ remain = img_vres % 16;
+ if (remain != 0) {
+ remain = 16 - remain;
+ img_vres = img_vres + remain;
+ }
+
+ cb_hres_byte = img_hres;
+ cb_vres_byte = img_vres;
+
+ y_hres_byte = img_hres - 1;
+ y_vres_byte = img_vres - 1;
+ y_hres_roundup = ((y_hres_byte >> 4) >> 3) + 1;
+ y_vres_roundup = ((y_vres_byte >> 4) >> 2) + 1;
+ if ((y_vres_byte & 0x20) == 0) {
+ y_hres_byte = y_hres_byte & 0x7f00;
+ y_hres_byte = y_hres_byte >> 8;
+ y_hres_byte = y_hres_byte & 0x7f;
+
+ y_vres_byte = y_vres_byte & 0x7fc0;
+ y_vres_byte = y_vres_byte >> 6;
+ y_vres_byte = y_vres_byte & 0x1ff;
+
+ *y_size = y_hres_byte +\
+ (y_vres_byte * y_hres_roundup) + 1;
+ } else {
+ *y_size = y_hres_roundup * y_vres_roundup;
+ }
+
+ *y_size = *(y_size) << 13;
+
+ cb_hres_byte = img_hres - 1;
+ cb_vres_byte = (img_vres >> 1) - 1;
+ cb_hres_roundup = ((cb_hres_byte >> 4) >> 3) + 1;
+ cb_vres_roundup = ((cb_vres_byte >> 4) >> 2) + 1;
+ if ((cb_vres_byte & 0x20) == 0) {
+ cb_hres_byte = cb_hres_byte & 0x7f00;
+ cb_hres_byte = cb_hres_byte >> 8;
+ cb_hres_byte = cb_hres_byte & 0x7f;
+
+ cb_vres_byte = cb_vres_byte & 0x7fc0;
+ cb_vres_byte = cb_vres_byte >> 6;
+ cb_vres_byte = cb_vres_byte & 0x1ff;
+
+ *cb_size = cb_hres_byte + (cb_vres_byte * cb_hres_roundup) + 1;
+ } else {
+ *cb_size = cb_hres_roundup * cb_vres_roundup;
+ }
+ *cb_size = (*cb_size) << 13;
+
+}
+
+static int fimc_get_free_ctx(struct fimc_control *ctrl)
+{
+ int i;
+
+ if (1 != ctrl->id)
+ return 0;
+
+ for (i = 0; i < FIMC_MAX_CTXS; i++) {
+ if (ctrl->ctx_busy[i] == 0) {
+ ctrl->ctx_busy[i] = 1;
+ fimc_info1("Current context is %d\n", i);
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+static int fimc_open(struct file *filp)
+{
+ struct fimc_control *ctrl;
+ struct s3c_platform_fimc *pdata;
+ struct fimc_prv_data *prv_data;
+ int in_use;
+ int ret;
+
+ ctrl = video_get_drvdata(video_devdata(filp));
+ pdata = to_fimc_plat(ctrl->dev);
+
+ mutex_lock(&ctrl->lock);
+
+ in_use = atomic_read(&ctrl->in_use);
+ if (in_use >= FIMC_MAX_CTXS || (in_use && 1 != ctrl->id)) {
+ fimc_err("%s: Device busy.\n", __func__);
+ ret = -EBUSY;
+ goto resource_busy;
+ } else {
+ atomic_inc(&ctrl->in_use);
+ }
+ in_use = atomic_read(&ctrl->in_use);
+
+ prv_data = kzalloc(sizeof(struct fimc_prv_data), GFP_KERNEL);
+ if (!prv_data) {
+ fimc_err("%s: not enough memory\n", __func__);
+ ret = -ENOMEM;
+ goto kzalloc_err;
+ }
+
+ prv_data->ctx_id = fimc_get_free_ctx(ctrl);
+ if (prv_data->ctx_id < 0) {
+ fimc_err("%s: Context busy flag not reset.\n", __func__);
+ ret = -EBUSY;
+ goto ctx_err;
+ }
+ prv_data->ctrl = ctrl;
+ filp->private_data = prv_data;
+
+ if (in_use == 1) {
+ fimc_clk_en(ctrl, true);
+
+ if (pdata->hw_ver == 0x40)
+ fimc_hw_reset_camera(ctrl);
+
+ /* Apply things to interface register */
+ fimc_hwset_reset(ctrl);
+
+ if (num_registered_fb > 0) {
+ struct fb_info *fbinfo = registered_fb[0];
+ ctrl->fb.lcd_hres = (int)fbinfo->var.xres;
+ ctrl->fb.lcd_vres = (int)fbinfo->var.yres;
+ fimc_info1("%s: fd.lcd_hres=%d fd.lcd_vres=%d\n",
+ __func__, ctrl->fb.lcd_hres,
+ ctrl->fb.lcd_vres);
+ }
+
+ ctrl->mem.curr = ctrl->mem.base;
+ ctrl->status = FIMC_STREAMOFF;
+
+ if (0 != ctrl->id)
+ fimc_clk_en(ctrl, false);
+ }
+
+ mutex_unlock(&ctrl->lock);
+
+ fimc_info1("%s opened.\n", ctrl->name);
+
+ return 0;
+
+ctx_err:
+ kfree(prv_data);
+
+kzalloc_err:
+ atomic_dec(&ctrl->in_use);
+
+resource_busy:
+ mutex_unlock(&ctrl->lock);
+ return ret;
+}
+
+static int fimc_release(struct file *filp)
+{
+ struct fimc_prv_data *prv_data =
+ (struct fimc_prv_data *)filp->private_data;
+ struct fimc_control *ctrl = prv_data->ctrl;
+ int ctx_id = prv_data->ctx_id;
+ struct s3c_platform_fimc *pdata;
+ struct fimc_overlay_buf *buf;
+ struct mm_struct *mm = current->mm;
+ struct fimc_ctx *ctx;
+ int ret = 0, i;
+ ctx = &ctrl->out->ctx[ctx_id];
+
+ pdata = to_fimc_plat(ctrl->dev);
+
+ mutex_lock(&ctrl->lock);
+ atomic_dec(&ctrl->in_use);
+
+ /* FIXME: turning off actual working camera */
+ if (ctrl->cam && ctrl->id != 2) {
+ /* Unload the subdev (camera sensor) module,
+ * reset related status flags
+ */
+ fimc_release_subdev(ctrl);
+ }
+
+ if (ctrl->cap) {
+ ctrl->mem.curr = ctrl->mem.base;
+ kfree(filp->private_data);
+ filp->private_data = NULL;
+
+ for (i = 0; i < FIMC_CAPBUFS; i++) {
+ fimc_dma_free(ctrl, &ctrl->cap->bufs[i], 0);
+ fimc_dma_free(ctrl, &ctrl->cap->bufs[i], 1);
+ fimc_dma_free(ctrl, &ctrl->cap->bufs[i], 2);
+ }
+
+ fimc_clk_en(ctrl, false);
+
+ kfree(ctrl->cap);
+ ctrl->cap = NULL;
+ }
+
+ if (ctrl->out) {
+ if (ctx->status != FIMC_STREAMOFF) {
+ fimc_clk_en(ctrl, true);
+ ret = fimc_outdev_stop_streaming(ctrl, ctx);
+ fimc_clk_en(ctrl, false);
+ if (ret < 0)
+ fimc_err("Fail: fimc_stop_streaming\n");
+
+ ret = fimc_init_in_queue(ctrl, ctx);
+ if (ret < 0) {
+ fimc_err("Fail: fimc_init_in_queue\n");
+ ret = -EINVAL;
+ goto release_err;
+ }
+
+ ret = fimc_init_out_queue(ctrl, ctx);
+ if (ret < 0) {
+ fimc_err("Fail: fimc_init_out_queue\n");
+ ret = -EINVAL;
+ goto release_err;
+ }
+
+ /* Make all buffers DQUEUED state. */
+ for (i = 0; i < FIMC_OUTBUFS; i++) {
+ ctx->src[i].state = VIDEOBUF_IDLE;
+ ctx->src[i].flags = V4L2_BUF_FLAG_MAPPED;
+ }
+
+ if (ctx->overlay.mode == FIMC_OVLY_DMA_AUTO) {
+ ctrl->mem.curr = ctx->dst[0].base[FIMC_ADDR_Y];
+
+ for (i = 0; i < FIMC_OUTBUFS; i++) {
+ ctx->dst[i].base[FIMC_ADDR_Y] = 0;
+ ctx->dst[i].length[FIMC_ADDR_Y] = 0;
+
+ ctx->dst[i].base[FIMC_ADDR_CB] = 0;
+ ctx->dst[i].length[FIMC_ADDR_CB] = 0;
+
+ ctx->dst[i].base[FIMC_ADDR_CR] = 0;
+ ctx->dst[i].length[FIMC_ADDR_CR] = 0;
+ }
+ }
+
+ ctx->status = FIMC_STREAMOFF;
+ }
+
+ buf = &ctx->overlay.buf;
+ for (i = 0; i < FIMC_OUTBUFS; i++) {
+ if (buf->vir_addr[i]) {
+ ret = do_munmap(mm, buf->vir_addr[i],
+ buf->size[i]);
+ if (ret < 0)
+ fimc_err("%s: do_munmap fail\n", \
+ __func__);
+ }
+ }
+
+ ctrl->ctx_busy[ctx_id] = 0;
+ memset(ctx, 0x00, sizeof(struct fimc_ctx));
+
+ if (atomic_read(&ctrl->in_use) == 0) {
+ ctrl->status = FIMC_STREAMOFF;
+ fimc_outdev_init_idxs(ctrl);
+
+ fimc_clk_en(ctrl, false);
+
+ ctrl->mem.curr = ctrl->mem.base;
+
+ kfree(ctrl->out);
+ ctrl->out = NULL;
+
+ kfree(filp->private_data);
+ filp->private_data = NULL;
+ }
+ }
+
+ /*
+ * it remain afterimage when I play movie using overlay and exit
+ */
+ if (ctrl->fb.is_enable == 1) {
+ fimc_info2("WIN_OFF for FIMC%d\n", ctrl->id);
+ ret = fb_blank(registered_fb[ctx->overlay.fb_id],
+ FB_BLANK_POWERDOWN);
+ if (ret < 0) {
+ fimc_err("%s: fb_blank: fb[%d] " \
+ "mode=FB_BLANK_POWERDOWN\n",
+ __func__, ctx->overlay.fb_id);
+ ret = -EINVAL;
+ goto release_err;
+ }
+
+ ctrl->fb.is_enable = 0;
+ }
+
+ mutex_unlock(&ctrl->lock);
+
+ fimc_info1("%s released.\n", ctrl->name);
+
+ return 0;
+
+release_err:
+ mutex_unlock(&ctrl->lock);
+ return ret;
+
+}
+
+static const struct v4l2_file_operations fimc_fops = {
+ .owner = THIS_MODULE,
+ .open = fimc_open,
+ .release = fimc_release,
+ .ioctl = video_ioctl2,
+ .read = fimc_read,
+ .write = fimc_write,
+ .mmap = fimc_mmap,
+ .poll = fimc_poll,
+};
+
+static void fimc_vdev_release(struct video_device *vdev)
+{
+ kfree(vdev);
+}
+
+struct video_device fimc_video_device[FIMC_DEVICES] = {
+ [0] = {
+ .fops = &fimc_fops,
+ .ioctl_ops = &fimc_v4l2_ops,
+ .release = fimc_vdev_release,
+ },
+ [1] = {
+ .fops = &fimc_fops,
+ .ioctl_ops = &fimc_v4l2_ops,
+ .release = fimc_vdev_release,
+ },
+ [2] = {
+ .fops = &fimc_fops,
+ .ioctl_ops = &fimc_v4l2_ops,
+ .release = fimc_vdev_release,
+ },
+};
+
+static int fimc_init_global(struct platform_device *pdev)
+{
+ struct s3c_platform_fimc *pdata;
+ struct s3c_platform_camera *cam;
+ int i;
+
+ pdata = to_fimc_plat(&pdev->dev);
+
+ /* Registering external camera modules. re-arrange order to be sure */
+ for (i = 0; i < FIMC_MAXCAMS; i++) {
+ cam = pdata->camera[i];
+ if (!cam)
+ break;
+
+ cam->srclk = clk_get(&pdev->dev, cam->srclk_name);
+ if (IS_ERR(cam->srclk)) {
+ dev_err(&pdev->dev, "%s: failed to get mclk source\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ /* mclk */
+ cam->clk = clk_get(&pdev->dev, cam->clk_name);
+ if (IS_ERR(cam->clk)) {
+ dev_err(&pdev->dev, "%s: failed to get mclk source\n",
+ __func__);
+ clk_put(cam->srclk);
+ return -EINVAL;
+ }
+
+ clk_put(cam->clk);
+ clk_put(cam->srclk);
+
+ /* Assign camera device to fimc */
+ memcpy(&fimc_dev->camera[i], cam, sizeof(*cam));
+ fimc_dev->camera_isvalid[i] = 1;
+ fimc_dev->camera[i].initialized = 0;
+ }
+
+ fimc_dev->active_camera = -1;
+ fimc_dev->initialized = 1;
+
+ return 0;
+}
+
+static int fimc_show_log_level(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fimc_control *ctrl;
+ struct platform_device *pdev;
+ int id = -1;
+
+ char temp[150];
+
+ pdev = to_platform_device(dev);
+ id = pdev->id;
+ ctrl = get_fimc_ctrl(id);
+
+ sprintf(temp, "\t");
+ strcat(buf, temp);
+ if (ctrl->log & FIMC_LOG_DEBUG) {
+ sprintf(temp, "FIMC_LOG_DEBUG | ");
+ strcat(buf, temp);
+ }
+
+ if (ctrl->log & FIMC_LOG_INFO_L2) {
+ sprintf(temp, "FIMC_LOG_INFO_L2 | ");
+ strcat(buf, temp);
+ }
+
+ if (ctrl->log & FIMC_LOG_INFO_L1) {
+ sprintf(temp, "FIMC_LOG_INFO_L1 | ");
+ strcat(buf, temp);
+ }
+
+ if (ctrl->log & FIMC_LOG_WARN) {
+ sprintf(temp, "FIMC_LOG_WARN | ");
+ strcat(buf, temp);
+ }
+
+ if (ctrl->log & FIMC_LOG_ERR) {
+ sprintf(temp, "FIMC_LOG_ERR\n");
+ strcat(buf, temp);
+ }
+
+ return strlen(buf);
+}
+
+static int fimc_store_log_level(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t len)
+{
+ struct fimc_control *ctrl;
+ struct platform_device *pdev;
+
+ const char *p = buf;
+ char msg[150] = {0, };
+ int id = -1;
+ u32 match = 0;
+
+ pdev = to_platform_device(dev);
+ id = pdev->id;
+ ctrl = get_fimc_ctrl(id);
+
+ while (*p != '\0') {
+ if (!isspace(*p))
+ strncat(msg, p, 1);
+ p++;
+ }
+
+ ctrl->log = 0;
+ printk(KERN_INFO "FIMC.%d log level is set as below.\n", id);
+
+ if (strstr(msg, "FIMC_LOG_ERR") != NULL) {
+ ctrl->log |= FIMC_LOG_ERR;
+ match = 1;
+ printk(KERN_INFO "\tFIMC_LOG_ERR\n");
+ }
+
+ if (strstr(msg, "FIMC_LOG_WARN") != NULL) {
+ ctrl->log |= FIMC_LOG_WARN;
+ match = 1;
+ printk(KERN_INFO "\tFIMC_LOG_WARN\n");
+ }
+
+ if (strstr(msg, "FIMC_LOG_INFO_L1") != NULL) {
+ ctrl->log |= FIMC_LOG_INFO_L1;
+ match = 1;
+ printk(KERN_INFO "\tFIMC_LOG_INFO_L1\n");
+ }
+
+ if (strstr(msg, "FIMC_LOG_INFO_L2") != NULL) {
+ ctrl->log |= FIMC_LOG_INFO_L2;
+ match = 1;
+ printk(KERN_INFO "\tFIMC_LOG_INFO_L2\n");
+ }
+
+ if (strstr(msg, "FIMC_LOG_DEBUG") != NULL) {
+ ctrl->log |= FIMC_LOG_DEBUG;
+ match = 1;
+ printk(KERN_INFO "\tFIMC_LOG_DEBUG\n");
+ }
+
+ if (!match) {
+ printk(KERN_INFO "FIMC_LOG_ERR \t: Error condition.\n");
+ printk(KERN_INFO "FIMC_LOG_WARN \t: WARNING condition.\n");
+ printk(KERN_INFO "FIMC_LOG_INFO_L1 \t: V4L2 API without QBUF, DQBUF.\n");
+ printk(KERN_INFO "FIMC_LOG_INFO_L2 \t: V4L2 API QBUF, DQBUF.\n");
+ printk(KERN_INFO "FIMC_LOG_DEBUG \t: Queue status report.\n");
+ }
+
+ return len;
+}
+
+static DEVICE_ATTR(log_level, 0644, \
+ fimc_show_log_level,
+ fimc_store_log_level);
+
+static int __devinit fimc_probe(struct platform_device *pdev)
+{
+ struct s3c_platform_fimc *pdata;
+ struct fimc_control *ctrl;
+ struct clk *srclk;
+ int ret;
+
+ if (!fimc_dev) {
+ fimc_dev = kzalloc(sizeof(*fimc_dev), GFP_KERNEL);
+ if (!fimc_dev) {
+ dev_err(&pdev->dev, "%s: not enough memory\n",
+ __func__);
+ return -ENOMEM;
+ }
+ }
+
+ ctrl = fimc_register_controller(pdev);
+ if (!ctrl) {
+ printk(KERN_ERR "%s: cannot register fimc\n", __func__);
+ goto err_alloc;
+ }
+
+ pdata = to_fimc_plat(&pdev->dev);
+ if (pdata->cfg_gpio)
+ pdata->cfg_gpio(pdev);
+
+ /* Get fimc power domain regulator */
+ ctrl->regulator = regulator_get(&pdev->dev, "pd");
+ if (IS_ERR(ctrl->regulator)) {
+ fimc_err("%s: failed to get resource %s\n",
+ __func__, "s3c-fimc");
+ return PTR_ERR(ctrl->regulator);
+ }
+
+ /* fimc source clock */
+ srclk = clk_get(&pdev->dev, pdata->srclk_name);
+ if (IS_ERR(srclk)) {
+ fimc_err("%s: failed to get source clock of fimc\n",
+ __func__);
+ goto err_v4l2;
+ }
+
+ /* fimc clock */
+ ctrl->clk = clk_get(&pdev->dev, pdata->clk_name);
+ if (IS_ERR(ctrl->clk)) {
+ fimc_err("%s: failed to get fimc clock source\n",
+ __func__);
+ goto err_v4l2;
+ }
+
+ /* set parent for mclk */
+ clk_set_parent(ctrl->clk, srclk);
+
+ /* set rate for mclk */
+ clk_set_rate(ctrl->clk, pdata->clk_rate);
+
+ /* V4L2 device-subdev registration */
+ ret = v4l2_device_register(&pdev->dev, &ctrl->v4l2_dev);
+ if (ret) {
+ fimc_err("%s: v4l2 device register failed\n", __func__);
+ goto err_fimc;
+ }
+
+ /* things to initialize once */
+ if (!fimc_dev->initialized) {
+ ret = fimc_init_global(pdev);
+ if (ret)
+ goto err_v4l2;
+ }
+
+ /* video device register */
+ ret = video_register_device(ctrl->vd, VFL_TYPE_GRABBER, ctrl->id);
+ if (ret) {
+ fimc_err("%s: cannot register video driver\n", __func__);
+ goto err_v4l2;
+ }
+
+ video_set_drvdata(ctrl->vd, ctrl);
+
+ ret = device_create_file(&(pdev->dev), &dev_attr_log_level);
+ if (ret < 0) {
+ fimc_err("failed to add sysfs entries\n");
+ goto err_global;
+ }
+ printk(KERN_INFO "FIMC%d registered successfully\n", ctrl->id);
+
+ return 0;
+
+err_global:
+ video_unregister_device(ctrl->vd);
+
+err_v4l2:
+ v4l2_device_unregister(&ctrl->v4l2_dev);
+
+err_fimc:
+ fimc_unregister_controller(pdev);
+
+err_alloc:
+ kfree(fimc_dev);
+ return -EINVAL;
+
+}
+
+static int fimc_remove(struct platform_device *pdev)
+{
+ fimc_unregister_controller(pdev);
+
+ device_remove_file(&(pdev->dev), &dev_attr_log_level);
+
+ kfree(fimc_dev);
+ fimc_dev = NULL;
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static inline void fimc_suspend_out_ctx(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ switch (ctx->overlay.mode) {
+ case FIMC_OVLY_DMA_AUTO: /* fall through */
+ case FIMC_OVLY_DMA_MANUAL: /* fall through */
+ case FIMC_OVLY_NONE_MULTI_BUF: /* fall through */
+ case FIMC_OVLY_NONE_SINGLE_BUF:
+ if (ctx->status == FIMC_STREAMON) {
+ if (ctx->inq[0] != -1)
+ fimc_err("%s : %d in queue unstable\n",
+ __func__, __LINE__);
+
+ fimc_outdev_stop_streaming(ctrl, ctx);
+ ctx->status = FIMC_ON_SLEEP;
+ } else if (ctx->status == FIMC_STREAMON_IDLE) {
+ fimc_outdev_stop_streaming(ctrl, ctx);
+ ctx->status = FIMC_ON_IDLE_SLEEP;
+ } else {
+ ctx->status = FIMC_OFF_SLEEP;
+ }
+
+ break;
+ case FIMC_OVLY_NOT_FIXED:
+ ctx->status = FIMC_OFF_SLEEP;
+ break;
+ }
+}
+
+static inline int fimc_suspend_out(struct fimc_control *ctrl)
+{
+ struct fimc_ctx *ctx;
+ int i, on_sleep = 0, idle_sleep = 0, off_sleep = 0;
+
+ for (i = 0; i < FIMC_MAX_CTXS; i++) {
+ ctx = &ctrl->out->ctx[i];
+ fimc_suspend_out_ctx(ctrl, ctx);
+
+ switch (ctx->status) {
+ case FIMC_ON_SLEEP:
+ on_sleep++;
+ break;
+ case FIMC_ON_IDLE_SLEEP:
+ idle_sleep++;
+ break;
+ case FIMC_OFF_SLEEP:
+ off_sleep++;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (on_sleep)
+ ctrl->status = FIMC_ON_SLEEP;
+ else if (idle_sleep)
+ ctrl->status = FIMC_ON_IDLE_SLEEP;
+ else
+ ctrl->status = FIMC_OFF_SLEEP;
+
+ ctrl->out->last_ctx = -1;
+
+ return 0;
+}
+
+static inline int fimc_suspend_cap(struct fimc_control *ctrl)
+{
+ if (ctrl->cam->id == CAMERA_WB && ctrl->status == FIMC_STREAMON)
+ fimc_streamoff_capture((void *)ctrl);
+ ctrl->status = FIMC_ON_SLEEP;
+
+ return 0;
+}
+
+int fimc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct fimc_control *ctrl;
+ struct s3c_platform_fimc *pdata;
+ int id;
+
+ id = pdev->id;
+ ctrl = get_fimc_ctrl(id);
+ pdata = to_fimc_plat(ctrl->dev);
+
+ if (ctrl->out)
+ fimc_suspend_out(ctrl);
+ else if (ctrl->cap)
+ fimc_suspend_cap(ctrl);
+ else
+ ctrl->status = FIMC_OFF_SLEEP;
+
+ if (atomic_read(&ctrl->in_use) && ctrl->status != FIMC_OFF_SLEEP)
+ fimc_clk_en(ctrl, false);
+
+ return 0;
+}
+
+static inline void fimc_resume_out_ctx(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ int ret = -1;
+
+ switch (ctx->overlay.mode) {
+ case FIMC_OVLY_DMA_AUTO:
+ if (ctx->status == FIMC_ON_IDLE_SLEEP) {
+ fimc_outdev_resume_dma(ctrl, ctx);
+ ret = fimc_outdev_set_ctx_param(ctrl, ctx);
+ if (ret < 0)
+ fimc_err("Fail: fimc_outdev_set_ctx_param\n");
+
+ ctx->status = FIMC_STREAMON_IDLE;
+ } else if (ctx->status == FIMC_OFF_SLEEP) {
+ ctx->status = FIMC_STREAMOFF;
+ } else {
+ fimc_err("%s: Abnormal (%d)\n", __func__, ctx->status);
+ }
+
+ break;
+ case FIMC_OVLY_DMA_MANUAL:
+ if (ctx->status == FIMC_ON_IDLE_SLEEP) {
+ ret = fimc_outdev_set_ctx_param(ctrl, ctx);
+ if (ret < 0)
+ fimc_err("Fail: fimc_outdev_set_ctx_param\n");
+
+ ctx->status = FIMC_STREAMON_IDLE;
+
+ } else if (ctx->status == FIMC_OFF_SLEEP) {
+ ctx->status = FIMC_STREAMOFF;
+ } else {
+ fimc_err("%s: Abnormal (%d)\n", __func__, ctx->status);
+ }
+
+ break;
+ case FIMC_OVLY_NONE_SINGLE_BUF: /* fall through */
+ case FIMC_OVLY_NONE_MULTI_BUF:
+ if (ctx->status == FIMC_ON_IDLE_SLEEP) {
+ ret = fimc_outdev_set_ctx_param(ctrl, ctx);
+ if (ret < 0)
+ fimc_err("Fail: fimc_outdev_set_ctx_param\n");
+
+ ctx->status = FIMC_STREAMON_IDLE;
+ } else if (ctx->status == FIMC_OFF_SLEEP) {
+ ctx->status = FIMC_STREAMOFF;
+ } else {
+ fimc_err("%s: Abnormal (%d)\n", __func__, ctx->status);
+ }
+
+ break;
+ default:
+ ctx->status = FIMC_STREAMOFF;
+ break;
+ }
+}
+
+static inline int fimc_resume_out(struct fimc_control *ctrl)
+{
+ struct fimc_ctx *ctx;
+ int i;
+ u32 state = 0;
+
+ for (i = 0; i < FIMC_MAX_CTXS; i++) {
+ ctx = &ctrl->out->ctx[i];
+ fimc_resume_out_ctx(ctrl, ctx);
+
+ switch (ctx->status) {
+ case FIMC_STREAMON:
+ state |= FIMC_STREAMON;
+ break;
+ case FIMC_STREAMON_IDLE:
+ state |= FIMC_STREAMON_IDLE;
+ break;
+ case FIMC_STREAMOFF:
+ state |= FIMC_STREAMOFF;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if ((state & FIMC_STREAMON) == FIMC_STREAMON)
+ ctrl->status = FIMC_STREAMON;
+ else if ((state & FIMC_STREAMON_IDLE) == FIMC_STREAMON_IDLE)
+ ctrl->status = FIMC_STREAMON_IDLE;
+ else
+ ctrl->status = FIMC_STREAMOFF;
+
+ return 0;
+}
+
+static inline int fimc_resume_cap(struct fimc_control *ctrl)
+{
+ if (ctrl->cam->id == CAMERA_WB)
+ fimc_streamon_capture((void *)ctrl);
+
+ return 0;
+}
+
+int fimc_resume(struct platform_device *pdev)
+{
+ struct fimc_control *ctrl;
+ struct s3c_platform_fimc *pdata;
+ int in_use, id = pdev->id;
+
+ ctrl = get_fimc_ctrl(id);
+ pdata = to_fimc_plat(ctrl->dev);
+
+ in_use = atomic_read(&ctrl->in_use);
+
+ if (in_use && ctrl->status != FIMC_OFF_SLEEP)
+ fimc_clk_en(ctrl, true);
+
+ if (ctrl->out)
+ fimc_resume_out(ctrl);
+ else if (ctrl->cap)
+ fimc_resume_cap(ctrl);
+ else
+ ctrl->status = FIMC_STREAMOFF;
+
+ if (in_use && 0 != ctrl->id)
+ fimc_clk_en(ctrl, false);
+
+ return 0;
+}
+#else
+#define fimc_suspend NULL
+#define fimc_resume NULL
+#endif
+
+static struct platform_driver fimc_driver = {
+ .probe = fimc_probe,
+ .remove = fimc_remove,
+ .suspend = fimc_suspend,
+ .resume = fimc_resume,
+ .driver = {
+ .name = FIMC_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int fimc_register(void)
+{
+ platform_driver_register(&fimc_driver);
+
+ return 0;
+}
+
+static void fimc_unregister(void)
+{
+ platform_driver_unregister(&fimc_driver);
+}
+
+late_initcall(fimc_register);
+module_exit(fimc_unregister);
+
+MODULE_AUTHOR("Dongsoo, Kim <dongsoo45.kim@samsung.com>");
+MODULE_AUTHOR("Jinsung, Yang <jsgood.yang@samsung.com>");
+MODULE_AUTHOR("Jonghun, Han <jonghun.han@samsung.com>");
+MODULE_DESCRIPTION("Samsung Camera Interface (FIMC) driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/samsung/fimc/fimc_output.c b/drivers/media/video/samsung/fimc/fimc_output.c
new file mode 100644
index 0000000..2269d6a
--- /dev/null
+++ b/drivers/media/video/samsung/fimc/fimc_output.c
@@ -0,0 +1,2563 @@
+/* linux/drivers/media/video/samsung/fimc/fimc_output.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * V4L2 Output device support file for Samsung Camera Interface (FIMC) driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/slab.h>
+#include <linux/bootmem.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/mm.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_samsung.h>
+#include <media/videobuf-core.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/mman.h>
+#include <plat/media.h>
+#include <linux/clk.h>
+
+#include "fimc.h"
+
+static __u32 fimc_get_pixel_format_type(__u32 pixelformat)
+{
+ switch (pixelformat) {
+ case V4L2_PIX_FMT_RGB32:
+ case V4L2_PIX_FMT_RGB565:
+ return FIMC_RGB;
+
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV12T:
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_YUV420:
+ return FIMC_YUV420;
+
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_YVYU:
+ case V4L2_PIX_FMT_VYUY:
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_NV61:
+ case V4L2_PIX_FMT_YUV422P:
+ return FIMC_YUV422;
+
+ default:
+ return FIMC_YUV444;
+ }
+}
+
+void fimc_outdev_set_src_addr(struct fimc_control *ctrl, dma_addr_t *base)
+{
+ fimc_hwset_addr_change_disable(ctrl);
+ fimc_hwset_input_address(ctrl, base);
+ fimc_hwset_addr_change_enable(ctrl);
+}
+
+int fimc_outdev_start_camif(void *param)
+{
+ struct fimc_control *ctrl = (struct fimc_control *)param;
+
+ fimc_hwset_start_scaler(ctrl);
+ fimc_hwset_enable_capture(ctrl, 0); /* bypass disable */
+ fimc_hwset_start_input_dma(ctrl);
+
+ return 0;
+}
+
+static int fimc_outdev_stop_camif(void *param)
+{
+ struct fimc_control *ctrl = (struct fimc_control *)param;
+
+ fimc_hwset_stop_input_dma(ctrl);
+ fimc_hwset_disable_autoload(ctrl);
+ fimc_hwset_stop_scaler(ctrl);
+ fimc_hwset_disable_capture(ctrl);
+ fimc_hwset_sw_reset(ctrl);
+
+ fimc_clk_en(ctrl, false);
+ return 0;
+}
+
+int fimc_outdev_stop_streaming(struct fimc_control *ctrl, struct fimc_ctx *ctx)
+{
+ int ret = 0;
+
+ fimc_dbg("%s: called\n", __func__);
+
+ switch (ctx->overlay.mode) {
+ case FIMC_OVLY_DMA_AUTO: /* fall through */
+ case FIMC_OVLY_DMA_MANUAL:
+ if (ctx->status == FIMC_STREAMON_IDLE)
+ ctx->status = FIMC_STREAMOFF;
+ else
+ ctx->status = FIMC_READY_OFF;
+ break;
+ case FIMC_OVLY_NONE_SINGLE_BUF: /* fall through */
+ case FIMC_OVLY_NONE_MULTI_BUF:
+ if (ctx->status == FIMC_STREAMON_IDLE)
+ ctx->status = FIMC_STREAMOFF;
+ else
+ ctx->status = FIMC_READY_OFF;
+ ret = wait_event_timeout(ctrl->wq,
+ (ctx->status == FIMC_STREAMOFF),
+ FIMC_ONESHOT_TIMEOUT);
+ if (ret == 0) {
+ fimc_dump_context(ctrl, ctx);
+ fimc_err("fail %s: %d\n", __func__, ctx->ctx_num);
+ }
+
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+int fimc_outdev_resume_dma(struct fimc_control *ctrl, struct fimc_ctx *ctx)
+{
+ struct v4l2_rect fimd_rect;
+ struct fb_var_screeninfo var;
+ struct fb_info *fbinfo;
+ struct s3cfb_window *win;
+ int ret = -1, idx;
+
+ fbinfo = registered_fb[ctx->overlay.fb_id];
+ win = (struct s3cfb_window *)fbinfo->par;
+
+ memcpy(&var, &fbinfo->var, sizeof(struct fb_var_screeninfo));
+ memset(&fimd_rect, 0, sizeof(struct v4l2_rect));
+ ret = fimc_fimd_rect(ctrl, ctx, &fimd_rect);
+ if (ret < 0) {
+ fimc_err("fimc_fimd_rect fail\n");
+ return -EINVAL;
+ }
+
+ /* set window path & owner */
+ win->path = DATA_PATH_DMA;
+ win->owner = DMA_MEM_OTHER;
+ win->other_mem_addr = ctx->dst[1].base[FIMC_ADDR_Y];
+ win->other_mem_size = ctx->dst[1].length[FIMC_ADDR_Y];
+
+ /* Update WIN size */
+ var.xres_virtual = fimd_rect.width;
+ var.yres_virtual = fimd_rect.height;
+ var.xres = fimd_rect.width;
+ var.yres = fimd_rect.height;
+
+ /* Update WIN position */
+ win->x = fimd_rect.left;
+ win->y = fimd_rect.top;
+
+ var.activate = FB_ACTIVATE_FORCE;
+ ret = fb_set_var(fbinfo, &var);
+ if (ret < 0) {
+ fimc_err("fb_set_var fail (ret=%d)\n", ret);
+ return -EINVAL;
+ }
+
+ idx = ctx->outq[0];
+ if (idx == -1) {
+ fimc_err("out going queue is empty.\n");
+ return -EINVAL;
+ }
+
+ win->other_mem_addr = ctx->dst[idx].base[FIMC_ADDR_Y];
+ ret = fb_pan_display(fbinfo, &fbinfo->var);
+ if (ret < 0) {
+ fimc_err("%s: fb_pan_display fail (ret=%d)\n", __func__, ret);
+ return -EINVAL;
+ }
+
+ ctrl->fb.is_enable = 1;
+
+ return 0;
+}
+
+static void fimc_init_out_buf(struct fimc_ctx *ctx)
+{
+ int i;
+
+ for (i = 0; i < FIMC_OUTBUFS; i++) {
+ ctx->src[i].state = VIDEOBUF_IDLE;
+ ctx->src[i].flags = 0x0;
+
+ ctx->inq[i] = -1;
+ ctx->outq[i] = -1;
+ }
+}
+
+static int fimc_outdev_set_src_buf(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ u32 width = ctx->pix.width;
+ u32 height = ctx->pix.height;
+ u32 format = ctx->pix.pixelformat;
+ u32 y_size = width * height;
+ u32 cb_size = 0, cr_size = 0;
+ u32 i, size;
+ dma_addr_t *curr = &ctrl->mem.curr;
+
+ switch (format) {
+ case V4L2_PIX_FMT_RGB32:
+ size = PAGE_ALIGN(y_size << 2);
+ break;
+ case V4L2_PIX_FMT_RGB565: /* fall through */
+ case V4L2_PIX_FMT_UYVY: /* fall through */
+ case V4L2_PIX_FMT_YVYU: /* fall through */
+ case V4L2_PIX_FMT_VYUY: /* fall through */
+ case V4L2_PIX_FMT_YUYV:
+ size = PAGE_ALIGN(y_size << 1);
+ break;
+ case V4L2_PIX_FMT_YUV420:
+ cb_size = y_size >> 2;
+ cr_size = y_size >> 2;
+ size = PAGE_ALIGN(y_size + cb_size + cr_size);
+ break;
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ cb_size = y_size >> 1;
+ size = PAGE_ALIGN(y_size + cb_size);
+ break;
+ case V4L2_PIX_FMT_NV12T:
+ fimc_get_nv12t_size(width, height, &y_size, &cb_size);
+ size = PAGE_ALIGN(y_size + cb_size);
+ break;
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_NV61:
+ cb_size = y_size;
+ size = PAGE_ALIGN(y_size + cb_size);
+ break;
+ default:
+ fimc_err("%s: Invalid pixelformt : %d\n", __func__, format);
+ return -EINVAL;
+ }
+
+ if ((*curr + size * FIMC_OUTBUFS) > (ctrl->mem.base + ctrl->mem.size)) {
+ fimc_err("%s: Reserved memory is not sufficient\n", __func__);
+ return -EINVAL;
+ }
+
+ /* Initialize source buffer addr */
+ switch (format) {
+ case V4L2_PIX_FMT_RGB565: /* fall through */
+ case V4L2_PIX_FMT_RGB32: /* fall through */
+ case V4L2_PIX_FMT_UYVY: /* fall through */
+ case V4L2_PIX_FMT_YVYU: /* fall through */
+ case V4L2_PIX_FMT_VYUY: /* fall through */
+ case V4L2_PIX_FMT_YUYV:
+ for (i = 0; i < FIMC_OUTBUFS; i++) {
+ ctx->src[i].base[FIMC_ADDR_Y] = *curr;
+ ctx->src[i].length[FIMC_ADDR_Y] = size;
+ ctx->src[i].base[FIMC_ADDR_CB] = 0;
+ ctx->src[i].length[FIMC_ADDR_CB] = 0;
+ ctx->src[i].base[FIMC_ADDR_CR] = 0;
+ ctx->src[i].length[FIMC_ADDR_CR] = 0;
+ *curr += size;
+ }
+ break;
+ case V4L2_PIX_FMT_NV12: /* fall through */
+ case V4L2_PIX_FMT_NV21: /* fall through */
+ case V4L2_PIX_FMT_NV16: /* fall through */
+ case V4L2_PIX_FMT_NV61: /* fall through */
+ case V4L2_PIX_FMT_NV12T:
+ for (i = 0; i < FIMC_OUTBUFS; i++) {
+ ctx->src[i].base[FIMC_ADDR_Y] = *curr;
+ ctx->src[i].length[FIMC_ADDR_Y] = y_size;
+ ctx->src[i].base[FIMC_ADDR_CB] = *curr + y_size;
+ ctx->src[i].length[FIMC_ADDR_CB] = cb_size;
+ ctx->src[i].base[FIMC_ADDR_CR] = 0;
+ ctx->src[i].length[FIMC_ADDR_CR] = 0;
+ *curr += size;
+ }
+ break;
+ case V4L2_PIX_FMT_YUV420:
+ for (i = 0; i < FIMC_OUTBUFS; i++) {
+ ctx->src[i].base[FIMC_ADDR_Y] = *curr;
+ ctx->src[i].base[FIMC_ADDR_CB] = *curr + y_size;
+ ctx->src[i].base[FIMC_ADDR_CR] = *curr + y_size +
+ cb_size;
+ ctx->src[i].length[FIMC_ADDR_Y] = y_size;
+ ctx->src[i].length[FIMC_ADDR_CB] = cb_size;
+ ctx->src[i].length[FIMC_ADDR_CR] = cr_size;
+ *curr += size;
+ }
+ break;
+
+ default:
+ fimc_err("%s: Invalid pixelformt : %d\n", __func__, format);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int fimc_outdev_set_dst_buf(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ dma_addr_t *curr = &ctrl->mem.curr;
+ dma_addr_t end;
+ u32 width = ctrl->fb.lcd_hres;
+ u32 height = ctrl->fb.lcd_vres;
+ u32 i, size;
+
+ end = ctrl->mem.base + ctrl->mem.size;
+ size = PAGE_ALIGN(width * height * 4);
+
+ if ((*curr + (size * FIMC_OUTBUFS)) > end) {
+ fimc_err("%s: Reserved memory is not sufficient\n", __func__);
+ return -EINVAL;
+ }
+
+ /* Initialize destination buffer addr */
+ for (i = 0; i < FIMC_OUTBUFS; i++) {
+ ctx->dst[i].base[FIMC_ADDR_Y] = *curr;
+ ctx->dst[i].length[FIMC_ADDR_Y] = size;
+ ctx->dst[i].base[FIMC_ADDR_CB] = 0;
+ ctx->dst[i].length[FIMC_ADDR_CB] = 0;
+ ctx->dst[i].base[FIMC_ADDR_CR] = 0;
+ ctx->dst[i].length[FIMC_ADDR_CR] = 0;
+ *curr += size;
+ }
+
+ return 0;
+}
+
+static int fimc_set_rot_degree(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx,
+ int degree)
+{
+ switch (degree) {
+ case 0: /* fall through */
+ case 90: /* fall through */
+ case 180: /* fall through */
+ case 270:
+ ctx->rotate = degree;
+ break;
+
+ default:
+ fimc_err("Invalid rotate value : %d\n", degree);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int fimc_outdev_check_param(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ struct v4l2_rect dst, bound;
+ u32 rot = 0;
+ int ret = 0, i, exclusive = 0;
+
+ rot = fimc_mapping_rot_flip(ctx->rotate, ctx->flip);
+ dst.top = ctx->win.w.top;
+ dst.left = ctx->win.w.left;
+ dst.width = ctx->win.w.width;
+ dst.height = ctx->win.w.height;
+
+ switch (ctx->overlay.mode) {
+ case FIMC_OVLY_DMA_AUTO: /* fall through */
+ case FIMC_OVLY_DMA_MANUAL:
+ if (rot & FIMC_ROT) {
+ bound.width = ctrl->fb.lcd_vres;
+ bound.height = ctrl->fb.lcd_hres;
+ } else {
+ bound.width = ctrl->fb.lcd_hres;
+ bound.height = ctrl->fb.lcd_vres;
+ }
+ break;
+ case FIMC_OVLY_NONE_SINGLE_BUF: /* fall through */
+ case FIMC_OVLY_NONE_MULTI_BUF:
+ bound.width = ctx->fbuf.fmt.width;
+ bound.height = ctx->fbuf.fmt.height;
+ break;
+
+ default:
+ fimc_err("%s: invalid ovelay mode.\n", __func__);
+ return -EINVAL;
+ }
+
+ if ((dst.left + dst.width) > bound.width) {
+ fimc_err("Horizontal position setting is failed\n");
+ fimc_err("\tleft = %d, width = %d, bound width = %d,\n",
+ dst.left, dst.width, bound.width);
+ ret = -EINVAL;
+ } else if ((dst.top + dst.height) > bound.height) {
+ fimc_err("Vertical position setting is failed\n");
+ fimc_err("\ttop = %d, height = %d, bound height = %d,\n",
+ dst.top, dst.height, bound.height);
+ ret = -EINVAL;
+ }
+
+ if ((ctx->status != FIMC_STREAMOFF) &&
+ (ctx->status != FIMC_READY_ON) &&
+ (ctx->status != FIMC_ON_IDLE_SLEEP)) {
+ fimc_err("FIMC is running\n");
+ return -EBUSY;
+ }
+
+ /* check other open instance */
+ for (i = 0; i < FIMC_MAX_CTXS; i++) {
+ switch (ctrl->out->ctx[i].overlay.mode) {
+ case FIMC_OVLY_DMA_AUTO: /* fall through */
+ case FIMC_OVLY_DMA_MANUAL:
+ exclusive++;
+ break;
+ case FIMC_OVLY_NONE_SINGLE_BUF: /* fall through */
+ case FIMC_OVLY_NONE_MULTI_BUF: /* fall through */
+ case FIMC_OVLY_NOT_FIXED:
+ break;
+ }
+ }
+
+ if (exclusive > 1) {
+ for (i = 0; i < FIMC_MAX_CTXS; i++)
+ fimc_err("%s: ctx %d mode = %d", __func__, i,
+ ctrl->out->ctx[i].overlay.mode);
+ return -EBUSY;
+ }
+
+ return ret;
+}
+
+static void fimc_outdev_set_src_format(struct fimc_control *ctrl,
+ u32 pixfmt, enum v4l2_field field)
+{
+ fimc_hwset_input_burst_cnt(ctrl, 4);
+ fimc_hwset_input_colorspace(ctrl, pixfmt);
+ fimc_hwset_input_yuv(ctrl, pixfmt);
+ fimc_hwset_input_rgb(ctrl, pixfmt);
+ fimc_hwset_intput_field(ctrl, field);
+ fimc_hwset_ext_rgb(ctrl, 1);
+ fimc_hwset_input_addr_style(ctrl, pixfmt);
+}
+
+static void fimc_outdev_set_dst_format(struct fimc_control *ctrl,
+ struct v4l2_pix_format *pixfmt)
+{
+ fimc_hwset_output_colorspace(ctrl, pixfmt->pixelformat);
+ fimc_hwset_output_yuv(ctrl, pixfmt->pixelformat);
+ fimc_hwset_output_rgb(ctrl, pixfmt->pixelformat);
+ fimc_hwset_output_scan(ctrl, pixfmt);
+ fimc_hwset_output_addr_style(ctrl, pixfmt->pixelformat);
+}
+
+static void fimc_outdev_set_format(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ struct v4l2_pix_format pixfmt;
+ memset(&pixfmt, 0, sizeof(pixfmt));
+
+ fimc_outdev_set_src_format(ctrl, ctx->pix.pixelformat, ctx->pix.field);
+
+ switch (ctx->overlay.mode) {
+ case FIMC_OVLY_DMA_AUTO: /* fall through */
+ case FIMC_OVLY_DMA_MANUAL: /* Non-destructive overlay mode */
+ if (ctx->pix.field == V4L2_FIELD_NONE) {
+ pixfmt.pixelformat = V4L2_PIX_FMT_RGB32;
+ pixfmt.field = V4L2_FIELD_NONE;
+ } else if (ctx->pix.field == V4L2_FIELD_INTERLACED_TB) {
+ pixfmt.pixelformat = V4L2_PIX_FMT_YUV444;
+ pixfmt.field = V4L2_FIELD_INTERLACED_TB;
+ } else if (ctx->pix.field == V4L2_FIELD_ANY) {
+ pixfmt.pixelformat = V4L2_PIX_FMT_RGB32;
+ pixfmt.field = V4L2_FIELD_NONE;
+ }
+
+ break;
+ case FIMC_OVLY_NONE_SINGLE_BUF: /* fall through */
+ case FIMC_OVLY_NONE_MULTI_BUF: /* Destructive overlay mode */
+ pixfmt.pixelformat = ctx->fbuf.fmt.pixelformat;
+ pixfmt.field = V4L2_FIELD_NONE;
+
+ break;
+ default:
+ fimc_err("Invalid overlay mode %d\n", ctx->overlay.mode);
+ break;
+ }
+
+ fimc_outdev_set_dst_format(ctrl, &pixfmt);
+}
+
+static void fimc_outdev_set_path(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ /* source path */
+ fimc_hwset_input_source(ctrl, FIMC_SRC_MSDMA);
+
+ fimc_hwset_disable_lcdfifo(ctrl);
+ fimc_hwset_disable_autoload(ctrl);
+}
+
+static void fimc_outdev_set_rot(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ u32 rot = ctx->rotate;
+ u32 flip = ctx->flip;
+
+ fimc_hwset_input_rot(ctrl, 0, 0);
+ fimc_hwset_input_flip(ctrl, 0, 0);
+ fimc_hwset_output_rot_flip(ctrl, rot, flip);
+}
+
+static void fimc_outdev_set_src_dma_offset(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ struct v4l2_rect bound, crop;
+ u32 pixfmt = ctx->pix.pixelformat;
+
+ bound.width = ctx->pix.width;
+ bound.height = ctx->pix.height;
+
+ crop.left = ctx->crop.left;
+ crop.top = ctx->crop.top;
+ crop.width = ctx->crop.width;
+ crop.height = ctx->crop.height;
+
+ fimc_hwset_input_offset(ctrl, pixfmt, &bound, &crop);
+}
+
+static int fimc4x_outdev_check_src_size(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx,
+ struct v4l2_rect *real,
+ struct v4l2_rect *org)
+{
+ /* No Input Rotator */
+ if (real->height < 8) {
+ fimc_err("SRC Real_H: Min 8\n");
+ return -EINVAL;
+ }
+
+ if (real->width < 16) {
+ fimc_err("SRC Real_W: Min 16\n");
+ return -EINVAL;
+ }
+
+ if (real->width > ctrl->limit->real_w_no_rot) {
+ fimc_err("SRC REAL_W: Real_W <= %d\n",
+ ctrl->limit->real_w_no_rot);
+ return -EINVAL;
+ }
+
+ if (org->height < real->height) {
+ fimc_err("SRC Org_H: larger than Real_H\n");
+ return -EINVAL;
+ }
+
+ if (org->width < real->width) {
+ fimc_err("SRC Org_W: Org_W >= Real_W\n");
+ return -EINVAL;
+ }
+
+ if (ctx->sc.pre_vratio) {
+ if (real->height % ctx->sc.pre_vratio) {
+ fimc_err("SRC Real_H: multiple of pre_vratio!\n");
+ return -EINVAL;
+ }
+ }
+
+ if (real->width % 16) {
+ fimc_err("SRC Real_W: multiple of 16 !\n");
+ return -EINVAL;
+ }
+
+ if (ctx->sc.pre_hratio) {
+ if (real->width % (ctx->sc.pre_hratio * 4)) {
+ fimc_err("SRC Real_W: multiple of 4 * pre_hratio!\n");
+ return -EINVAL;
+ }
+ }
+
+ if (org->width % 16) {
+ fimc_err("SRC Org_W: multiple of 16\n");
+ return -EINVAL;
+ }
+
+ if (org->height < 8) {
+ fimc_err("SRC Org_H: Min 8\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int fimc50_outdev_check_src_size(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx,
+ struct v4l2_rect *real,
+ struct v4l2_rect *org)
+{
+ u32 pixelformat = ctx->pix.pixelformat;
+
+ /* No Input Rotator */
+ if (real->height < 8) {
+ fimc_err("SRC Real_H: Min 8\n");
+ return -EINVAL;
+ }
+
+ if (real->width < 16) {
+ fimc_err("SRC Real_W: Min 16\n");
+ return -EINVAL;
+ }
+
+ if (real->width > ctrl->limit->real_w_no_rot) {
+ fimc_err("SRC REAL_W: Real_W <= %d\n",
+ ctrl->limit->real_w_no_rot);
+ return -EINVAL;
+ }
+
+ if (org->height < real->height) {
+ fimc_err("SRC Org_H: larger than Real_H\n");
+ return -EINVAL;
+ }
+
+ if (org->width < real->width) {
+ fimc_err("SRC Org_W: Org_W >= Real_W\n");
+ return -EINVAL;
+ }
+
+ if (ctx->pix.field == V4L2_FIELD_INTERLACED_TB) {
+ switch (pixelformat) {
+ case V4L2_PIX_FMT_YUV444: /* fall through */
+ case V4L2_PIX_FMT_RGB32:
+ if (real->height % 2) {
+ fimc_err("SRC Real_H: multiple of 2\n");
+ return -EINVAL;
+ }
+ case V4L2_PIX_FMT_YUV422P:
+ if (real->height % 2) {
+ fimc_err("SRC Real_H: multiple of 2\n");
+ return -EINVAL;
+ } else if (real->width % 2) {
+ fimc_err("SRC Real_H: multiple of 2\n");
+ return -EINVAL;
+ }
+ case V4L2_PIX_FMT_YVU420:
+ if (real->height % 4) {
+ fimc_err("SRC Real_H: multiple of 4\n");
+ return -EINVAL;
+ } else if (real->width % 2) {
+ fimc_err("SRC Real_H: multiple of 2\n");
+ return -EINVAL;
+ }
+ }
+ } else if (ctx->pix.field == V4L2_FIELD_NONE) {
+ if (pixelformat == V4L2_PIX_FMT_YUV422P) {
+ if (real->height % 2) {
+ fimc_err("SRC Real_H: multiple of 2\n");
+ return -EINVAL;
+ } else if (real->width % 2) {
+ fimc_err("SRC Real_H: multiple of 2\n");
+ return -EINVAL;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int fimc_outdev_set_src_dma_size(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
+ struct v4l2_rect real, org;
+ int ret = 0;
+
+ real.width = ctx->crop.width;
+ real.height = ctx->crop.height;
+ org.width = ctx->pix.width;
+ org.height = ctx->pix.height;
+
+ if (pdata->hw_ver == 0x50)
+ ret = fimc50_outdev_check_src_size(ctrl, ctx, &real, &org);
+ else
+ ret = fimc4x_outdev_check_src_size(ctrl, ctx, &real, &org);
+
+ if (ret < 0)
+ return ret;
+
+ fimc_hwset_org_input_size(ctrl, org.width, org.height);
+ fimc_hwset_real_input_size(ctrl, real.width, real.height);
+
+ return 0;
+}
+
+static void fimc_outdev_set_dst_dma_offset(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ struct v4l2_rect bound, win;
+ struct v4l2_rect *w = &ctx->win.w;
+ u32 pixfmt = ctx->fbuf.fmt.pixelformat;
+
+ memset(&bound, 0, sizeof(bound));
+ memset(&win, 0, sizeof(win));
+
+ switch (ctx->rotate) {
+ case 0:
+ bound.width = ctx->fbuf.fmt.width;
+ bound.height = ctx->fbuf.fmt.height;
+
+ win.left = w->left;
+ win.top = w->top;
+ win.width = w->width;
+ win.height = w->height;
+
+ break;
+ case 90:
+ bound.width = ctx->fbuf.fmt.height;
+ bound.height = ctx->fbuf.fmt.width;
+
+ win.left = ctx->fbuf.fmt.height - (w->height + w->top);
+ win.top = w->left;
+ win.width = w->height;
+ win.height = w->width;
+
+ break;
+ case 180:
+ bound.width = ctx->fbuf.fmt.width;
+ bound.height = ctx->fbuf.fmt.height;
+
+ win.left = ctx->fbuf.fmt.width - (w->left + w->width);
+ win.top = ctx->fbuf.fmt.height - (w->top + w->height);
+ win.width = w->width;
+ win.height = w->height;
+
+ break;
+ case 270:
+ bound.width = ctx->fbuf.fmt.height;
+ bound.height = ctx->fbuf.fmt.width;
+
+ win.left = ctx->win.w.top;
+ win.top = ctx->fbuf.fmt.width - (w->left + w->width);
+ win.width = w->height;
+ win.height = w->width;
+
+ break;
+ default:
+ fimc_err("Rotation degree is invalid\n");
+ break;
+ }
+
+ switch (ctx->overlay.mode) {
+ case FIMC_OVLY_DMA_AUTO: /* fall through */
+ case FIMC_OVLY_DMA_MANUAL:
+ memset(&bound, 0, sizeof(bound));
+ memset(&win, 0, sizeof(win));
+ fimc_hwset_output_offset(ctrl, pixfmt, &bound, &win);
+ break;
+ default:
+ fimc_hwset_output_offset(ctrl, pixfmt, &bound, &win);
+ break;
+ }
+
+ fimc_dbg("bound:width(%d), height(%d)\n", bound.width, bound.height);
+ fimc_dbg("win:width(%d), height(%d)\n", win.width, win.height);
+ fimc_dbg("win:top(%d), left(%d)\n", win.top, win.left);
+}
+
+static int fimc_outdev_check_dst_size(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx,
+ struct v4l2_rect *real,
+ struct v4l2_rect *org)
+{
+ u32 rot = ctx->rotate;
+ __u32 pixel_type;
+
+ pixel_type = fimc_get_pixel_format_type(ctx->fbuf.fmt.pixelformat);
+
+ if (FIMC_YUV420 == pixel_type && real->height % 2) {
+ fimc_err("DST Real_H: even number for YUV420 formats\n");
+ return -EINVAL;
+ }
+
+ if ((rot == 90) || (rot == 270)) {
+ /* Use Output Rotator */
+ if (org->height < real->width) {
+ fimc_err("DST Org_H: Org_H(%d) >= Real_W(%d)\n",
+ org->height, real->width);
+ return -EINVAL;
+ }
+
+ if (org->width < real->height) {
+ fimc_err("DST Org_W: Org_W(%d) >= Real_H(%d)\n",
+ org->width, real->height);
+ return -EINVAL;
+ }
+
+ if (real->height > ctrl->limit->trg_h_rot) {
+ fimc_err("DST REAL_H: Real_H <= %d\n",
+ ctrl->limit->trg_h_rot);
+ return -EINVAL;
+ }
+ } else {
+ /* No Output Rotator */
+ if (org->height < 8) {
+ fimc_err("DST Org_H: Min 8\n");
+ return -EINVAL;
+ }
+
+ if (org->height < real->height) {
+ fimc_err("DST Org_H: Org_H >= Real_H\n");
+ return -EINVAL;
+ }
+
+ if (org->width % 8) {
+ fimc_err("DST Org_W: multiple of 8\n");
+ return -EINVAL;
+ }
+
+ if (org->width < real->width) {
+ fimc_err("DST Org_W: Org_W >= Real_W\n");
+ return -EINVAL;
+ }
+
+ if (real->height > ctrl->limit->trg_h_no_rot) {
+ fimc_err("DST REAL_H: Real_H <= %d\n",
+ ctrl->limit->trg_h_no_rot);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static int fimc_outdev_set_dst_dma_size(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ struct v4l2_rect org, real;
+ int ret = -1;
+
+ memset(&org, 0, sizeof(org));
+ memset(&real, 0, sizeof(real));
+
+ switch (ctx->overlay.mode) {
+ case FIMC_OVLY_NONE_MULTI_BUF: /* fall through */
+ case FIMC_OVLY_NONE_SINGLE_BUF:
+ real.width = ctx->win.w.width;
+ real.height = ctx->win.w.height;
+
+ switch (ctx->rotate) {
+ case 0: /* fall through */
+ case 180:
+ org.width = ctx->fbuf.fmt.width;
+ org.height = ctx->fbuf.fmt.height;
+ break;
+ case 90: /* fall through */
+ case 270:
+ org.width = ctx->fbuf.fmt.height;
+ org.height = ctx->fbuf.fmt.width;
+ break;
+ default:
+ fimc_err("Rotation degree is invalid\n");
+ break;
+ }
+
+ break;
+
+ case FIMC_OVLY_DMA_MANUAL: /* fall through */
+ case FIMC_OVLY_DMA_AUTO:
+ real.width = ctx->win.w.width;
+ real.height = ctx->win.w.height;
+
+ switch (ctx->rotate) {
+ case 0: /* fall through */
+ case 180:
+ org.width = ctx->win.w.width;
+ org.height = ctx->win.w.height;
+ break;
+ case 90: /* fall through */
+ case 270:
+ org.width = ctx->win.w.height;
+ org.height = ctx->win.w.width;
+ break;
+ default:
+ fimc_err("Rotation degree is invalid\n");
+ break;
+ }
+
+ break;
+ default:
+ break;
+ }
+
+ fimc_dbg("DST org: width(%d), height(%d)\n", org.width, org.height);
+ fimc_dbg("DST real: width(%d), height(%d)\n", real.width, real.height);
+
+ ret = fimc_outdev_check_dst_size(ctrl, ctx, &real, &org);
+ if (ret < 0)
+ return ret;
+
+ fimc_hwset_output_size(ctrl, real.width, real.height);
+ fimc_hwset_output_area(ctrl, real.width, real.height);
+ fimc_hwset_org_output_size(ctrl, org.width, org.height);
+ fimc_hwset_ext_output_size(ctrl, real.width, real.height);
+
+ return 0;
+}
+
+static void fimc_outdev_calibrate_scale_info(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx,
+ struct v4l2_rect *src,
+ struct v4l2_rect *dst)
+{
+ /* OUTPUT ROTATOR */
+ src->width = ctx->crop.width;
+ src->height = ctx->crop.height;
+ dst->width = ctx->win.w.width;
+ dst->height = ctx->win.w.height;
+
+ fimc_dbg("src->width(%d), src->height(%d)\n", src->width, src->height);
+ fimc_dbg("dst->width(%d), dst->height(%d)\n", dst->width, dst->height);
+}
+
+static int fimc_outdev_check_scaler(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx,
+ struct v4l2_rect *src,
+ struct v4l2_rect *dst)
+{
+ u32 pixels = 0, dstfmt = 0;
+
+ /* Check scaler limitation */
+ if (ctx->sc.pre_dst_width > ctrl->limit->pre_dst_w) {
+ fimc_err("FIMC%d : MAX PreDstWidth is %d\n",
+ ctrl->id, ctrl->limit->pre_dst_w);
+ return -EDOM;
+ }
+
+ /* SRC width double boundary check */
+ switch (ctx->pix.pixelformat) {
+ case V4L2_PIX_FMT_RGB32:
+ pixels = 1;
+ break;
+ case V4L2_PIX_FMT_YUYV: /* fall through */
+ case V4L2_PIX_FMT_UYVY: /* fall through */
+ case V4L2_PIX_FMT_YVYU: /* fall through */
+ case V4L2_PIX_FMT_VYUY: /* fall through */
+ case V4L2_PIX_FMT_NV16: /* fall through */
+ case V4L2_PIX_FMT_NV61: /* fall through */
+ case V4L2_PIX_FMT_RGB565:
+ pixels = 2;
+ break;
+ case V4L2_PIX_FMT_YUV420: /* fall through */
+ case V4L2_PIX_FMT_NV12: /* fall through */
+ case V4L2_PIX_FMT_NV21: /* fall through */
+ case V4L2_PIX_FMT_NV12T:
+ pixels = 8;
+ break;
+ default:
+ fimc_err("Invalid color format\n");
+ return -EINVAL;
+ }
+
+ if (src->width % pixels) {
+ fimc_err("source width multiple of %d pixels\n", pixels);
+ return -EDOM;
+ }
+
+ /* DST width double boundary check */
+ switch (ctx->overlay.mode) {
+ case FIMC_OVLY_DMA_AUTO: /* fall through */
+ case FIMC_OVLY_DMA_MANUAL:
+ dstfmt = V4L2_PIX_FMT_RGB32;
+ break;
+ case FIMC_OVLY_NONE_SINGLE_BUF: /* fall through */
+ case FIMC_OVLY_NONE_MULTI_BUF:
+ dstfmt = ctx->fbuf.fmt.pixelformat;
+ break;
+ default:
+ break;
+ }
+
+ switch (dstfmt) {
+ case V4L2_PIX_FMT_RGB32:
+ pixels = 1;
+ break;
+ case V4L2_PIX_FMT_RGB565:
+ case V4L2_PIX_FMT_YUYV: /* fall through */
+ case V4L2_PIX_FMT_UYVY: /* fall through */
+ case V4L2_PIX_FMT_YVYU: /* fall through */
+ case V4L2_PIX_FMT_VYUY: /* fall through */
+ case V4L2_PIX_FMT_NV16: /* fall through */
+ case V4L2_PIX_FMT_NV61:
+ pixels = 2;
+ break;
+ case V4L2_PIX_FMT_YUV420: /* fall through */
+ case V4L2_PIX_FMT_NV12: /* fall through */
+ case V4L2_PIX_FMT_NV21: /* fall through */
+ case V4L2_PIX_FMT_NV12T:
+ pixels = 8;
+ break;
+ default:
+ fimc_err("Invalid color format\n");
+ return -EINVAL;
+ }
+
+ if (dst->width % pixels) {
+ fimc_err("source width multiple of %d pixels\n", pixels);
+ return -EDOM;
+ }
+
+ return 0;
+}
+
+static int fimc_outdev_set_scaler(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ struct v4l2_rect src, dst;
+ int ret = 0;
+ struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
+
+ memset(&src, 0, sizeof(src));
+ memset(&dst, 0, sizeof(dst));
+
+ fimc_outdev_calibrate_scale_info(ctrl, ctx, &src, &dst);
+
+ ret = fimc_get_scaler_factor(src.width, dst.width,
+ &ctx->sc.pre_hratio, &ctx->sc.hfactor);
+ if (ret < 0) {
+ fimc_err("Fail : Out of Width scale range\n");
+ return ret;
+ }
+
+ ret = fimc_get_scaler_factor(src.height, dst.height,
+ &ctx->sc.pre_vratio, &ctx->sc.vfactor);
+ if (ret < 0) {
+ fimc_err("Fail : Out of Height scale range\n");
+ return ret;
+ }
+
+ ctx->sc.pre_dst_width = src.width / ctx->sc.pre_hratio;
+ ctx->sc.pre_dst_height = src.height / ctx->sc.pre_vratio;
+
+ if (pdata->hw_ver == 0x50) {
+ ctx->sc.main_hratio = (src.width << 14) /
+ (dst.width << ctx->sc.hfactor);
+ ctx->sc.main_vratio = (src.height << 14) /
+ (dst.height << ctx->sc.vfactor);
+ } else {
+ ctx->sc.main_hratio = (src.width << 8) /
+ (dst.width << ctx->sc.hfactor);
+ ctx->sc.main_vratio = (src.height << 8) /
+ (dst.height << ctx->sc.vfactor);
+ }
+
+ fimc_dbg("pre_hratio(%d), hfactor(%d), pre_vratio(%d), vfactor(%d)\n",
+ ctx->sc.pre_hratio, ctx->sc.hfactor,
+ ctx->sc.pre_vratio, ctx->sc.vfactor);
+
+
+ fimc_dbg("pre_dst_width(%d), main_hratio(%d), "
+ "pre_dst_height(%d), main_vratio(%d)\n",
+ ctx->sc.pre_dst_width, ctx->sc.main_hratio,
+ ctx->sc.pre_dst_height, ctx->sc.main_vratio);
+
+ ctx->sc.bypass = 0; /* Input DMA cannot support scaler bypass. */
+ ctx->sc.scaleup_h = (dst.width >= src.width) ? 1 : 0;
+ ctx->sc.scaleup_v = (dst.height >= src.height) ? 1 : 0;
+ ctx->sc.shfactor = 10 - (ctx->sc.hfactor + ctx->sc.vfactor);
+
+ if (pdata->hw_ver != 0x50) {
+ ret = fimc_outdev_check_scaler(ctrl, ctx, &src, &dst);
+ if (ret < 0)
+ return ret;
+ }
+
+ fimc_hwset_prescaler(ctrl, &ctx->sc);
+ fimc_hwset_scaler(ctrl, &ctx->sc);
+
+ return 0;
+}
+
+int fimc_outdev_set_ctx_param(struct fimc_control *ctrl, struct fimc_ctx *ctx)
+{
+ int ret;
+
+ if (ctrl->status == FIMC_READY_ON || ctrl->status == FIMC_STREAMON_IDLE)
+ fimc_hwset_enable_irq(ctrl, 0, 1);
+
+ fimc_outdev_set_format(ctrl, ctx);
+ fimc_outdev_set_path(ctrl, ctx);
+ fimc_outdev_set_rot(ctrl, ctx);
+
+ fimc_outdev_set_src_dma_offset(ctrl, ctx);
+ ret = fimc_outdev_set_src_dma_size(ctrl, ctx);
+ if (ret < 0)
+ return ret;
+
+ fimc_outdev_set_dst_dma_offset(ctrl, ctx);
+
+ ret = fimc_outdev_set_dst_dma_size(ctrl, ctx);
+ if (ret < 0)
+ return ret;
+
+ ret = fimc_outdev_set_scaler(ctrl, ctx);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+int fimc_fimd_rect(const struct fimc_control *ctrl,
+ const struct fimc_ctx *ctx,
+ struct v4l2_rect *fimd_rect)
+{
+ switch (ctx->rotate) {
+ case 0:
+ fimd_rect->left = ctx->win.w.left;
+ fimd_rect->top = ctx->win.w.top;
+ fimd_rect->width = ctx->win.w.width;
+ fimd_rect->height = ctx->win.w.height;
+
+ break;
+
+ case 90:
+ fimd_rect->left = ctrl->fb.lcd_hres -
+ (ctx->win.w.top + ctx->win.w.height);
+ fimd_rect->top = ctx->win.w.left;
+ fimd_rect->width = ctx->win.w.height;
+ fimd_rect->height = ctx->win.w.width;
+
+ break;
+
+ case 180:
+ fimd_rect->left = ctrl->fb.lcd_hres -
+ (ctx->win.w.left + ctx->win.w.width);
+ fimd_rect->top = ctrl->fb.lcd_vres -
+ (ctx->win.w.top + ctx->win.w.height);
+ fimd_rect->width = ctx->win.w.width;
+ fimd_rect->height = ctx->win.w.height;
+
+ break;
+
+ case 270:
+ fimd_rect->left = ctx->win.w.top;
+ fimd_rect->top = ctrl->fb.lcd_vres -
+ (ctx->win.w.left + ctx->win.w.width);
+ fimd_rect->width = ctx->win.w.height;
+ fimd_rect->height = ctx->win.w.width;
+
+ break;
+
+ default:
+ fimc_err("Rotation degree is invalid\n");
+ return -EINVAL;
+
+ break;
+ }
+
+ return 0;
+}
+
+int fimc_outdev_overlay_buf(struct file *filp,
+ struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ int ret = 0, i;
+ struct fimc_overlay_buf *buf;
+
+ buf = &ctx->overlay.buf;
+
+ for (i = 0; i < FIMC_OUTBUFS; i++) {
+ ctx->overlay.req_idx = i;
+ buf->size[i] = ctx->dst[i].length[0];
+ buf->phy_addr[i] = ctx->dst[i].base[0];
+ buf->vir_addr[i] = do_mmap(filp, 0, buf->size[i],
+ PROT_READ|PROT_WRITE, MAP_SHARED, 0);
+ if (buf->vir_addr[i] == -EINVAL) {
+ fimc_err("%s: fail\n", __func__);
+ return -EINVAL;
+ }
+
+ fimc_dbg("idx : %d, size(0x%08x), phy_addr(0x%08x), "
+ "vir_addr(0x%08x)\n", i, buf->size[i],
+ buf->phy_addr[i], buf->vir_addr[i]);
+ }
+
+ ctx->overlay.req_idx = -1;
+
+ return ret;
+}
+
+int fimc_reqbufs_output(void *fh, struct v4l2_requestbuffers *b)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ struct fimc_ctx *ctx;
+ struct fimc_overlay_buf *buf;
+ struct mm_struct *mm = current->mm;
+ enum fimc_overlay_mode mode;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+ int ret = -1, i;
+
+ ctx = &ctrl->out->ctx[ctx_id];
+ buf = &ctx->overlay.buf;
+ mode = ctx->overlay.mode;
+
+ fimc_info1("%s: called\n", __func__);
+
+ if (ctx->status != FIMC_STREAMOFF) {
+ fimc_err("FIMC is running\n");
+ return -EBUSY;
+ }
+
+ if (ctx->is_requested == 1 && b->count != 0) {
+ fimc_err("Buffers were already requested\n");
+ return -EBUSY;
+ }
+
+ if (b->count > FIMC_OUTBUFS) {
+ fimc_warn("The buffer count is modified by driver "
+ "from %d to %d\n", b->count, FIMC_OUTBUFS);
+ b->count = FIMC_OUTBUFS;
+ }
+
+ fimc_init_out_buf(ctx);
+ ctx->is_requested = 0;
+
+ if (b->count == 0) {
+ ctrl->mem.curr = ctrl->mem.base;
+
+ switch (ctx->overlay.mode) {
+ case FIMC_OVLY_DMA_AUTO: /* fall through */
+ case FIMC_OVLY_DMA_MANUAL:
+ for (i = 0; i < FIMC_OUTBUFS; i++) {
+ if (buf->vir_addr[i]) {
+ ret = do_munmap(mm,
+ buf->vir_addr[i],
+ buf->size[i]);
+ if (ret < 0)
+ fimc_err("%s: do_munmap fail. "
+ "vir_addr[%d](0x%08x)\n",
+ __func__, i, buf->vir_addr[i]);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ } else {
+ /* initialize source buffers */
+ if (b->memory == V4L2_MEMORY_MMAP) {
+ ret = fimc_outdev_set_src_buf(ctrl, ctx);
+ ctx->overlay.req_idx = FIMC_MMAP_IDX;
+ if (ret)
+ return ret;
+ } else if (b->memory == V4L2_MEMORY_USERPTR) {
+ if (mode == FIMC_OVLY_DMA_AUTO)
+ ctx->overlay.req_idx = FIMC_USERPTR_IDX;
+ }
+ ctx->is_requested = 1;
+ }
+
+ ctx->buf_num = b->count;
+
+ return 0;
+}
+
+int fimc_querybuf_output(void *fh, struct v4l2_buffer *b)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ struct fimc_ctx *ctx;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+ u32 buf_length = 0;
+
+ fimc_info1("%s: called\n", __func__);
+
+ ctx = &ctrl->out->ctx[ctx_id];
+ if (ctx->status != FIMC_STREAMOFF) {
+ fimc_err("FIMC is running\n");
+ return -EBUSY;
+ }
+
+ if (b->index >= ctx->buf_num) {
+ fimc_err("The index is out of bounds. You requested %d buffers."
+ "But requested index is %d\n", ctx->buf_num, b->index);
+ return -EINVAL;
+ }
+
+ b->flags = ctx->src[b->index].flags;
+ b->m.offset = b->index * PAGE_SIZE;
+ buf_length = ctx->src[b->index].length[FIMC_ADDR_Y] +
+ ctx->src[b->index].length[FIMC_ADDR_CB] +
+ ctx->src[b->index].length[FIMC_ADDR_CR];
+ b->length = PAGE_ALIGN(buf_length);
+
+ return 0;
+}
+
+int fimc_g_ctrl_output(void *fh, struct v4l2_control *c)
+{
+ struct fimc_ctx *ctx;
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+ struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
+ ctx = &ctrl->out->ctx[ctx_id];
+
+ if (ctx->status != FIMC_STREAMOFF) {
+ fimc_err("FIMC is running\n");
+ return -EBUSY;
+ }
+
+ switch (c->id) {
+ case V4L2_CID_ROTATION:
+ c->value = ctx->rotate;
+ break;
+
+ case V4L2_CID_HFLIP:
+ if (ctx->flip & V4L2_CID_HFLIP)
+ c->value = 1;
+ else
+ c->value = 0;
+ break;
+
+ case V4L2_CID_VFLIP:
+ if (ctx->flip & V4L2_CID_VFLIP)
+ c->value = 1;
+ else
+ c->value = 0;
+ break;
+
+ case V4L2_CID_OVERLAY_VADDR0:
+ c->value = ctx->overlay.buf.vir_addr[0];
+ break;
+
+ case V4L2_CID_OVERLAY_VADDR1:
+ c->value = ctx->overlay.buf.vir_addr[1];
+ break;
+
+ case V4L2_CID_OVERLAY_VADDR2:
+ c->value = ctx->overlay.buf.vir_addr[2];
+ break;
+
+ case V4L2_CID_OVERLAY_AUTO:
+ if (ctx->overlay.mode == FIMC_OVLY_DMA_AUTO)
+ c->value = 1;
+ else
+ c->value = 0;
+ break;
+
+ case V4L2_CID_RESERVED_MEM_BASE_ADDR:
+ c->value = ctrl->mem.base;
+ if (2 == ctrl->id) {
+ /* Clearing the buffer for FIMC-2
+ * This is required because the same buffer is used
+ * for both Camcorder recording and HDMI display.
+ */
+ char *fimc_mem = NULL;
+ fimc_mem = (char *) ioremap(ctrl->mem.base, \
+ ctrl->mem.size);
+ if (fimc_mem) {
+ memset(fimc_mem, 0x00, ctrl->mem.size);
+ iounmap(fimc_mem);
+ }
+ }
+ break;
+
+ case V4L2_CID_FIMC_VERSION:
+ c->value = pdata->hw_ver;
+ break;
+
+ default:
+ fimc_err("Invalid control id: %d\n", c->id);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int fimc_set_dst_info(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx,
+ struct fimc_buf *fimc_buf)
+{
+ struct fimc_buf *buf;
+ int i;
+
+ for (i = 0; i < ctx->buf_num; i++) {
+ buf = &fimc_buf[i];
+
+ ctx->dst[i].base[FIMC_ADDR_Y] = buf->base[FIMC_ADDR_Y];
+ ctx->dst[i].length[FIMC_ADDR_Y] = buf->length[FIMC_ADDR_Y];
+
+ ctx->dst[i].base[FIMC_ADDR_CB] = buf->base[FIMC_ADDR_CB];
+ ctx->dst[i].length[FIMC_ADDR_CB] = buf->length[FIMC_ADDR_CB];
+
+ ctx->dst[i].base[FIMC_ADDR_CR] = buf->base[FIMC_ADDR_CR];
+ ctx->dst[i].length[FIMC_ADDR_CR] = buf->length[FIMC_ADDR_CR];
+ }
+
+ for (i = ctx->buf_num; i < FIMC_OUTBUFS; i++) {
+ ctx->dst[i].base[FIMC_ADDR_Y] = 0;
+ ctx->dst[i].length[FIMC_ADDR_Y] = 0;
+
+ ctx->dst[i].base[FIMC_ADDR_CB] = 0;
+ ctx->dst[i].length[FIMC_ADDR_CB] = 0;
+
+ ctx->dst[i].base[FIMC_ADDR_CR] = 0;
+ ctx->dst[i].length[FIMC_ADDR_CR] = 0;
+ }
+
+ /* for debugging */
+ for (i = 0; i < FIMC_OUTBUFS; i++) {
+ fimc_dbg("dst[%d]: base[0]=0x%08x, size[0]=0x%08x\n",
+ i, ctx->dst[i].base[0], ctx->dst[i].length[0]);
+
+ fimc_dbg("dst[%d]: base[1]=0x%08x, size[1]=0x%08x\n",
+ i, ctx->dst[i].base[1], ctx->dst[i].length[2]);
+
+ fimc_dbg("dst[%d]: base[2]=0x%08x, size[2]=0x%08x\n",
+ i, ctx->dst[i].base[1], ctx->dst[i].length[2]);
+ }
+
+ return 0;
+}
+int fimc_s_ctrl_output(struct file *filp, void *fh, struct v4l2_control *c)
+{
+ struct fimc_ctx *ctx;
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+ int ret = 0;
+
+ ctx = &ctrl->out->ctx[ctx_id];
+ if (ctx->status != FIMC_STREAMOFF) {
+ fimc_err("FIMC is running\n");
+ return -EBUSY;
+ }
+
+ switch (c->id) {
+ case V4L2_CID_ROTATION:
+ ret = fimc_set_rot_degree(ctrl, ctx, c->value);
+
+ break;
+ case V4L2_CID_HFLIP:
+ if (c->value)
+ ctx->flip |= FIMC_XFLIP;
+ else
+ ctx->flip &= ~FIMC_XFLIP;
+
+ break;
+ case V4L2_CID_VFLIP:
+ if (c->value)
+ ctx->flip |= FIMC_YFLIP;
+ else
+ ctx->flip &= ~FIMC_YFLIP;
+
+ break;
+ case V4L2_CID_OVERLAY_AUTO:
+ if (c->value == 1) {
+ ctx->overlay.mode = FIMC_OVLY_DMA_AUTO;
+ } else {
+ ctx->overlay.mode = FIMC_OVLY_DMA_MANUAL;
+ ret = fimc_outdev_set_dst_buf(ctrl, ctx);
+ fimc_outdev_overlay_buf(filp, ctrl, ctx);
+ }
+
+ break;
+ case V4L2_CID_OVLY_MODE:
+ ctx->overlay.mode = c->value;
+
+ break;
+ case V4L2_CID_DST_INFO:
+ ret = fimc_set_dst_info(ctrl, ctx,
+ (struct fimc_buf *)c->value);
+ break;
+ default:
+ fimc_err("Invalid control id: %d\n", c->id);
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+int fimc_cropcap_output(void *fh, struct v4l2_cropcap *a)
+{
+ struct fimc_ctx *ctx;
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+ u32 is_rotate = 0, max_w = 0, max_h = 0, pixelformat;
+
+ fimc_info1("%s: called\n", __func__);
+
+ ctx = &ctrl->out->ctx[ctx_id];
+ pixelformat = ctx->pix.pixelformat;
+ if (ctx->status != FIMC_STREAMOFF) {
+ fimc_err("FIMC is running\n");
+ return -EBUSY;
+ }
+
+ is_rotate = fimc_mapping_rot_flip(ctx->rotate, ctx->flip);
+ switch (pixelformat) {
+ case V4L2_PIX_FMT_NV12: /* fall through */
+ case V4L2_PIX_FMT_NV21: /* fall through */
+ case V4L2_PIX_FMT_NV12T: /* fall through */
+ case V4L2_PIX_FMT_YUYV: /* fall through */
+ case V4L2_PIX_FMT_UYVY: /* fall through */
+ case V4L2_PIX_FMT_YVYU: /* fall through */
+ case V4L2_PIX_FMT_VYUY: /* fall through */
+ case V4L2_PIX_FMT_NV16: /* fall through */
+ case V4L2_PIX_FMT_NV61: /* fall through */
+ case V4L2_PIX_FMT_YUV420:
+ max_w = FIMC_SRC_MAX_W;
+ max_h = FIMC_SRC_MAX_H;
+ case V4L2_PIX_FMT_RGB32: /* fall through */
+ case V4L2_PIX_FMT_RGB565: /* fall through */
+ if (is_rotate & FIMC_ROT) { /* Landscape mode */
+ max_w = ctrl->fb.lcd_vres;
+ max_h = ctrl->fb.lcd_hres;
+ } else { /* Portrait */
+ max_w = ctrl->fb.lcd_hres;
+ max_h = ctrl->fb.lcd_vres;
+ }
+
+ break;
+ default:
+ fimc_warn("Supported format : \
+ V4L2_PIX_FMT_YUYV, V4L2_PIX_FMT_UYVY, \
+ V4L2_PIX_FMT_YVYU, V4L2_PIX_FMT_VYUY, \
+ V4L2_PIX_FMT_NV12, V4L2_PIX_FMT_NV12T, \
+ V4L2_PIX_FMT_NV21, V4L2_PIX_FMT_RGB32, \
+ V4L2_PIX_FMT_RGB565\n");
+ fimc_warn("%s: Received pixel format = %x\n",
+ __func__, pixelformat);
+ return -EINVAL;
+ }
+
+ /* crop bounds */
+ ctx->cropcap.bounds.left = 0;
+ ctx->cropcap.bounds.top = 0;
+ ctx->cropcap.bounds.width = max_w;
+ ctx->cropcap.bounds.height = max_h;
+
+ /* crop default values */
+ ctx->cropcap.defrect.left = 0;
+ ctx->cropcap.defrect.top = 0;
+ ctx->cropcap.defrect.width = max_w;
+ ctx->cropcap.defrect.height = max_h;
+
+ /* crop pixel aspec values */
+ /* To Do : Have to modify but I don't know the meaning. */
+ ctx->cropcap.pixelaspect.numerator = 16;
+ ctx->cropcap.pixelaspect.denominator = 9;
+
+ a->bounds = ctx->cropcap.bounds;
+ a->defrect = ctx->cropcap.defrect;
+ a->pixelaspect = ctx->cropcap.pixelaspect;
+
+ return 0;
+}
+
+int fimc_g_crop_output(void *fh, struct v4l2_crop *a)
+{
+ struct fimc_ctx *ctx;
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+
+ ctx = &ctrl->out->ctx[ctx_id];
+
+ fimc_info1("%s: called\n", __func__);
+
+ mutex_lock(&ctrl->v4l2_lock);
+ a->c.left = ctx->crop.left;
+ a->c.top = ctx->crop.top;
+ a->c.width = ctx->crop.width;
+ a->c.height = ctx->crop.height;
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ return 0;
+}
+
+int fimc_s_crop_output(void *fh, struct v4l2_crop *a)
+{
+ struct fimc_ctx *ctx;
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+
+ fimc_info1("%s: called: left(%d), top(%d), width(%d), height(%d),\n",
+ __func__, a->c.left, a->c.top, a->c.width, a->c.height);
+
+ ctx = &ctrl->out->ctx[ctx_id];
+ if (ctx->status != FIMC_STREAMOFF) {
+ fimc_err("FIMC is running\n");
+ return -EBUSY;
+ }
+
+ /* Check arguments : widht and height */
+ if ((a->c.width < 0) || (a->c.height < 0)) {
+ fimc_err("The crop rect must be bigger than 0\n");
+ return -EINVAL;
+ }
+
+ if ((a->c.width > FIMC_SRC_MAX_W) || (a->c.height > FIMC_SRC_MAX_H)) {
+ fimc_err("The crop width/height must be smaller than "
+ "%d and %d\n", FIMC_SRC_MAX_W, FIMC_SRC_MAX_H);
+ return -EINVAL;
+ }
+
+ /* Check arguments : left and top */
+ if ((a->c.left < 0) || (a->c.top < 0)) {
+ fimc_err("The crop left, top must be bigger than 0\n");
+ return -EINVAL;
+ }
+
+ if ((a->c.left > FIMC_SRC_MAX_W) || (a->c.top > FIMC_SRC_MAX_H)) {
+ fimc_err("The crop left, top must be smaller than %d, %d\n",
+ FIMC_SRC_MAX_W, FIMC_SRC_MAX_H);
+ return -EINVAL;
+ }
+
+ if ((a->c.left + a->c.width) > FIMC_SRC_MAX_W) {
+ fimc_err("The crop rect must be in bound rect\n");
+ return -EINVAL;
+ }
+
+ if ((a->c.top + a->c.height) > FIMC_SRC_MAX_H) {
+ fimc_err("The crop rect must be in bound rect\n");
+ return -EINVAL;
+ }
+
+ ctx->crop.left = a->c.left;
+ ctx->crop.top = a->c.top;
+ ctx->crop.width = a->c.width;
+ ctx->crop.height = a->c.height;
+
+ return 0;
+}
+
+int fimc_streamon_output(void *fh)
+{
+ struct fimc_ctx *ctx;
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+ int ret = -1;
+
+ fimc_info1("%s: called\n", __func__);
+
+ ctx = &ctrl->out->ctx[ctx_id];
+ if (ctx->overlay.mode == FIMC_OVLY_NOT_FIXED)
+ ctx->overlay.mode = FIMC_OVLY_MODE;
+
+ /* initialize destination buffers */
+ if (ctx->overlay.mode == FIMC_OVLY_DMA_AUTO) {
+ ret = fimc_outdev_set_dst_buf(ctrl, ctx);
+ if (ret)
+ return ret;
+ }
+
+ ret = fimc_outdev_check_param(ctrl, ctx);
+ if (ret < 0) {
+ fimc_err("Fail: fimc_outdev_check_param\n");
+ return ret;
+ }
+
+ ctx->status = FIMC_READY_ON;
+ if (ctrl->status == FIMC_STREAMOFF)
+ ctrl->status = FIMC_READY_ON;
+
+ return ret;
+}
+
+void fimc_outdev_init_idxs(struct fimc_control *ctrl)
+{
+ ctrl->out->idxs.prev.ctx = -1;
+ ctrl->out->idxs.prev.idx = -1;
+ ctrl->out->idxs.active.ctx = -1;
+ ctrl->out->idxs.active.idx = -1;
+ ctrl->out->idxs.next.ctx = -1;
+ ctrl->out->idxs.next.idx = -1;
+}
+
+int fimc_streamoff_output(void *fh)
+{
+ struct fimc_ctx *ctx;
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+ int ret = -1, i = 0, off_cnt = 0;
+
+ fimc_info1("%s: called\n", __func__);
+
+ ctx = &ctrl->out->ctx[ctx_id];
+ ret = fimc_outdev_stop_streaming(ctrl, ctx);
+ if (ret < 0) {
+ fimc_err("Fail: fimc_outdev_stop_streaming\n");
+ return -EINVAL;
+ }
+
+ ret = fimc_init_in_queue(ctrl, ctx);
+ if (ret < 0) {
+ fimc_err("Fail: fimc_init_in_queue\n");
+ return -EINVAL;
+ }
+
+ ret = fimc_init_out_queue(ctrl, ctx);
+ if (ret < 0) {
+ fimc_err("Fail: fimc_init_out_queue\n");
+ return -EINVAL;
+ }
+
+ /* Make all buffers DQUEUED state. */
+ for (i = 0; i < FIMC_OUTBUFS; i++) {
+ ctx->src[i].state = VIDEOBUF_IDLE;
+ ctx->src[i].flags = V4L2_BUF_FLAG_MAPPED;
+ }
+
+ ctx->status = FIMC_STREAMOFF;
+
+ if (ctrl->out->last_ctx == ctx->ctx_num)
+ ctrl->out->last_ctx = -1;
+
+ if (ctx->overlay.mode == FIMC_OVLY_DMA_AUTO) {
+ ctrl->mem.curr = ctx->dst[0].base[FIMC_ADDR_Y];
+
+ for (i = 0; i < FIMC_OUTBUFS; i++) {
+ ctx->dst[i].base[FIMC_ADDR_Y] = 0;
+ ctx->dst[i].length[FIMC_ADDR_Y] = 0;
+
+ ctx->dst[i].base[FIMC_ADDR_CB] = 0;
+ ctx->dst[i].length[FIMC_ADDR_CB] = 0;
+
+ ctx->dst[i].base[FIMC_ADDR_CR] = 0;
+ ctx->dst[i].length[FIMC_ADDR_CR] = 0;
+ }
+ }
+
+ /* check all ctx to change ctrl->status from streamon to streamoff */
+ for (i = 0; i < FIMC_MAX_CTXS; i++) {
+ if (ctrl->out->ctx[i].status == FIMC_STREAMOFF)
+ off_cnt++;
+ }
+
+ if (off_cnt == FIMC_MAX_CTXS) {
+ ctrl->status = FIMC_STREAMOFF;
+ fimc_outdev_init_idxs(ctrl);
+ fimc_outdev_stop_camif(ctrl);
+ }
+
+ if (ctx_id == ctrl->out->last_ctx)
+ ctrl->out->last_ctx = -1;
+
+ mutex_lock(&ctrl->lock);
+ if (ctx->overlay.mode == FIMC_OVLY_DMA_AUTO && ctrl->fb.is_enable == 1) {
+ fimc_info2("WIN_OFF for FIMC%d\n", ctrl->id);
+ ret = fb_blank(registered_fb[ctx->overlay.fb_id],
+ FB_BLANK_POWERDOWN);
+ if (ret < 0) {
+ fimc_err("%s: fb_blank: fb[%d] " \
+ "mode=FB_BLANK_POWERDOWN\n",
+ __func__, ctx->overlay.fb_id);
+ mutex_unlock(&ctrl->lock);
+ return -EINVAL;
+ }
+
+ ctrl->fb.is_enable = 0;
+ }
+ mutex_unlock(&ctrl->lock);
+
+ return 0;
+}
+
+
+int fimc_output_set_dst_addr(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx, int idx)
+{
+ struct fimc_buf_set buf_set; /* destination addr */
+ u32 format = ctx->fbuf.fmt.pixelformat;
+ u32 width = ctx->fbuf.fmt.width;
+ u32 height = ctx->fbuf.fmt.height;
+ u32 y_size = width * height;
+ u32 c_size = y_size >> 2;
+ int i;
+
+ memset(&buf_set, 0x00, sizeof(buf_set));
+
+ if (V4L2_PIX_FMT_NV12T == format)
+ fimc_get_nv12t_size(width, height, &y_size, &c_size);
+
+ switch (format) {
+ case V4L2_PIX_FMT_RGB32:
+ case V4L2_PIX_FMT_RGB565:
+ case V4L2_PIX_FMT_YUYV: /* fall through */
+ case V4L2_PIX_FMT_UYVY: /* fall through */
+ case V4L2_PIX_FMT_YVYU: /* fall through */
+ case V4L2_PIX_FMT_VYUY: /* fall through */
+ if (ctx->overlay.mode == FIMC_OVLY_NONE_SINGLE_BUF)
+ buf_set.base[FIMC_ADDR_Y] =
+ (dma_addr_t)ctx->fbuf.base;
+ else
+ buf_set.base[FIMC_ADDR_Y] =
+ ctx->dst[idx].base[FIMC_ADDR_Y];
+ break;
+ case V4L2_PIX_FMT_YUV420:
+ if (ctx->overlay.mode == FIMC_OVLY_NONE_SINGLE_BUF) {
+ buf_set.base[FIMC_ADDR_Y] =
+ (dma_addr_t)ctx->fbuf.base;
+ buf_set.base[FIMC_ADDR_CB] =
+ buf_set.base[FIMC_ADDR_Y] + y_size;
+ buf_set.base[FIMC_ADDR_CR] =
+ buf_set.base[FIMC_ADDR_CB] + c_size;
+ } else {
+ buf_set.base[FIMC_ADDR_Y] =
+ ctx->dst[idx].base[FIMC_ADDR_Y];
+ buf_set.base[FIMC_ADDR_CB] =
+ ctx->dst[idx].base[FIMC_ADDR_CB];
+ buf_set.base[FIMC_ADDR_CR] =
+ ctx->dst[idx].base[FIMC_ADDR_CR];
+ }
+ break;
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_NV61:
+ case V4L2_PIX_FMT_NV12T:
+ if (ctx->overlay.mode == FIMC_OVLY_NONE_SINGLE_BUF) {
+ buf_set.base[FIMC_ADDR_Y] =
+ (dma_addr_t)ctx->fbuf.base;
+ buf_set.base[FIMC_ADDR_CB] =
+ buf_set.base[FIMC_ADDR_Y] + y_size;
+ } else {
+ buf_set.base[FIMC_ADDR_Y] =
+ ctx->dst[idx].base[FIMC_ADDR_Y];
+ buf_set.base[FIMC_ADDR_CB] =
+ ctx->dst[idx].base[FIMC_ADDR_CB];
+ }
+ break;
+ default:
+ fimc_err("%s: Invalid pixelformt : %d\n", \
+ __func__, format);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < FIMC_PHYBUFS; i++)
+ fimc_hwset_output_address(ctrl, &buf_set, i);
+
+ return 0;
+}
+
+
+static int fimc_qbuf_output_single_buf(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx,
+ int idx)
+{
+ int ret = -1;
+
+ fimc_outdev_set_src_addr(ctrl, ctx->src[idx].base);
+
+ ret = fimc_output_set_dst_addr(ctrl, ctx, idx);
+ if (ret < 0) {
+ fimc_err("%s: Fail: fimc_output_set_dst_addr\n", __func__);
+ return -EINVAL;
+ }
+
+ ctrl->out->idxs.active.idx = idx;
+ ctrl->out->idxs.active.ctx = ctx->ctx_num;
+
+ ctrl->status = FIMC_STREAMON;
+ ctx->status = FIMC_STREAMON;
+
+ ret = fimc_outdev_start_camif(ctrl);
+ if (ret < 0) {
+ fimc_err("Fail: fimc_start_camif\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int fimc_qbuf_output_multi_buf(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx,
+ int idx)
+{
+ int ret = -1;
+
+ fimc_outdev_set_src_addr(ctrl, ctx->src[idx].base);
+
+ fimc_output_set_dst_addr(ctrl, ctx, idx);
+ if (ret < 0) {
+ fimc_err("%s: Fail: fimc_output_set_dst_addr\n", __func__);
+ return -EINVAL;
+ }
+
+ ret = fimc_outdev_start_camif(ctrl);
+ if (ret < 0) {
+ fimc_err("Fail: fimc_start_camif\n");
+ return -EINVAL;
+ }
+
+ ctrl->out->idxs.active.idx = idx;
+ ctrl->out->idxs.active.ctx = ctx->ctx_num;
+
+ ctrl->status = FIMC_STREAMON;
+ ctx->status = FIMC_STREAMON;
+
+ return 0;
+}
+
+static int fimc_qbuf_output_dma_auto(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx,
+ int idx)
+{
+ struct fb_var_screeninfo var;
+ struct fb_info *fbinfo;
+ struct s3cfb_window *win;
+ struct v4l2_rect fimd_rect;
+ struct fimc_buf_set buf_set; /* destination addr */
+ int ret = -1, i;
+
+ switch (ctx->status) {
+ case FIMC_READY_ON:
+ fbinfo = registered_fb[ctx->overlay.fb_id];
+ win = (struct s3cfb_window *)fbinfo->par;
+
+ memcpy(&var, &fbinfo->var, sizeof(struct fb_var_screeninfo));
+ memset(&fimd_rect, 0, sizeof(struct v4l2_rect));
+ ret = fimc_fimd_rect(ctrl, ctx, &fimd_rect);
+ if (ret < 0) {
+ fimc_err("fimc_fimd_rect fail\n");
+ return -EINVAL;
+ }
+
+ /* set window path & owner */
+ win->path = DATA_PATH_DMA;
+ win->owner = DMA_MEM_OTHER;
+ win->other_mem_addr = ctx->dst[1].base[FIMC_ADDR_Y];
+ win->other_mem_size = ctx->dst[1].length[FIMC_ADDR_Y];
+
+ /* Update WIN size */
+ var.xres_virtual = fimd_rect.width;
+ var.yres_virtual = fimd_rect.height;
+ var.xres = fimd_rect.width;
+ var.yres = fimd_rect.height;
+
+ /* Update WIN position */
+ win->x = fimd_rect.left;
+ win->y = fimd_rect.top;
+
+ var.activate = FB_ACTIVATE_FORCE;
+ ret = fb_set_var(fbinfo, &var);
+ if (ret < 0) {
+ fimc_err("fb_set_var fail (ret=%d)\n", ret);
+ return -EINVAL;
+ }
+
+ /* fall through */
+
+ case FIMC_STREAMON_IDLE:
+ fimc_outdev_set_src_addr(ctrl, ctx->src[idx].base);
+
+ memset(&buf_set, 0x00, sizeof(buf_set));
+ buf_set.base[FIMC_ADDR_Y] = ctx->dst[idx].base[FIMC_ADDR_Y];
+
+ for (i = 0; i < FIMC_PHYBUFS; i++)
+ fimc_hwset_output_address(ctrl, &buf_set, i);
+
+ ret = fimc_outdev_start_camif(ctrl);
+ if (ret < 0) {
+ fimc_err("Fail: fimc_start_camif\n");
+ return -EINVAL;
+ }
+
+ ctrl->out->idxs.active.idx = idx;
+ ctrl->out->idxs.active.ctx = ctx->ctx_num;
+
+ ctrl->status = FIMC_STREAMON;
+ ctx->status = FIMC_STREAMON;
+
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int fimc_qbuf_output_dma_manual(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx,
+ int idx)
+{
+ struct fimc_buf_set buf_set; /* destination addr */
+ int ret = -1, i;
+
+ fimc_outdev_set_src_addr(ctrl, ctx->src[idx].base);
+
+ memset(&buf_set, 0x00, sizeof(buf_set));
+ buf_set.base[FIMC_ADDR_Y] = ctx->dst[idx].base[FIMC_ADDR_Y];
+
+ for (i = 0; i < FIMC_PHYBUFS; i++)
+ fimc_hwset_output_address(ctrl, &buf_set, i);
+
+ ret = fimc_outdev_start_camif(ctrl);
+ if (ret < 0) {
+ fimc_err("Fail: fimc_start_camif\n");
+ return -EINVAL;
+ }
+
+ ctrl->out->idxs.active.idx = idx;
+ ctrl->out->idxs.active.ctx = ctx->ctx_num;
+
+ ctrl->status = FIMC_STREAMON;
+ ctx->status = FIMC_STREAMON;
+
+ return 0;
+}
+
+static int fimc_update_in_queue_addr(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx,
+ u32 idx, dma_addr_t *addr)
+{
+ if (idx >= FIMC_OUTBUFS) {
+ fimc_err("%s: Failed\n", __func__);
+ return -EINVAL;
+ }
+
+ ctx->src[idx].base[FIMC_ADDR_Y] = addr[FIMC_ADDR_Y];
+ ctx->src[idx].base[FIMC_ADDR_CB] = addr[FIMC_ADDR_CB];
+ ctx->src[idx].base[FIMC_ADDR_CR] = addr[FIMC_ADDR_CR];
+
+ return 0;
+}
+
+int fimc_qbuf_output(void *fh, struct v4l2_buffer *b)
+{
+ struct fimc_buf *buf = (struct fimc_buf *)b->m.userptr;
+ struct fimc_ctx *ctx;
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+ int idx, ctx_num;
+ int ret = -1;
+
+ ctx = &ctrl->out->ctx[ctx_id];
+ fimc_info2("ctx(%d) queued idx = %d\n", ctx->ctx_num, b->index);
+
+ if (b->index >= ctx->buf_num) {
+ fimc_err("The index is out of bounds. "
+ "You requested %d buffers. "
+ "But you set the index as %d\n",
+ ctx->buf_num, b->index);
+ return -EINVAL;
+ }
+
+ /* Check the buffer state if the state is VIDEOBUF_IDLE. */
+ if (ctx->src[b->index].state != VIDEOBUF_IDLE) {
+ fimc_err("The index(%d) buffer must be dequeued state(%d)\n",
+ b->index, ctx->src[b->index].state);
+ return -EINVAL;
+ }
+
+ if (b->memory == V4L2_MEMORY_USERPTR) {
+ ret = fimc_update_in_queue_addr(ctrl, ctx, b->index, buf->base);
+ if (ret < 0)
+ return ret;
+ }
+
+ /* Attach the buffer to the incoming queue. */
+ ret = fimc_push_inq(ctrl, ctx, b->index);
+ if (ret < 0) {
+ fimc_err("Fail: fimc_push_inq\n");
+ return -EINVAL;
+ }
+
+ if ((ctrl->status == FIMC_READY_ON) ||
+ (ctrl->status == FIMC_STREAMON_IDLE)) {
+ ret = fimc_pop_inq(ctrl, &ctx_num, &idx);
+ if (ret < 0) {
+ fimc_err("Fail: fimc_pop_inq\n");
+ return -EINVAL;
+ }
+
+ fimc_clk_en(ctrl, true);
+
+ ctx = &ctrl->out->ctx[ctx_num];
+ if (ctx_num != ctrl->out->last_ctx) {
+ ctrl->out->last_ctx = ctx->ctx_num;
+ fimc_outdev_set_ctx_param(ctrl, ctx);
+ }
+
+ switch (ctx->overlay.mode) {
+ case FIMC_OVLY_DMA_AUTO:
+ ret = fimc_qbuf_output_dma_auto(ctrl, ctx, idx);
+ break;
+ case FIMC_OVLY_DMA_MANUAL:
+ ret = fimc_qbuf_output_dma_manual(ctrl, ctx, idx);
+ break;
+ case FIMC_OVLY_NONE_SINGLE_BUF:
+ ret = fimc_qbuf_output_single_buf(ctrl, ctx, idx);
+ break;
+ case FIMC_OVLY_NONE_MULTI_BUF:
+ ret = fimc_qbuf_output_multi_buf(ctrl, ctx, idx);
+ break;
+ default:
+ break;
+ }
+ }
+
+ return ret;
+}
+
+int fimc_dqbuf_output(void *fh, struct v4l2_buffer *b)
+{
+ struct fimc_ctx *ctx;
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+ int idx = -1, ret = -1;
+
+ ctx = &ctrl->out->ctx[ctx_id];
+ ret = fimc_pop_outq(ctrl, ctx, &idx);
+ if (ret < 0) {
+ ret = wait_event_timeout(ctrl->wq, (ctx->outq[0] != -1),
+ FIMC_DQUEUE_TIMEOUT);
+ if (ret == 0) {
+ fimc_dump_context(ctrl, ctx);
+ fimc_err("[0] out_queue is empty\n");
+ ctx->status = FIMC_STREAMON_IDLE;
+ return -EAGAIN;
+ } else if (ret == -ERESTARTSYS) {
+ fimc_print_signal(ctrl);
+ } else {
+ /* Normal case */
+ ret = fimc_pop_outq(ctrl, ctx, &idx);
+ if (ret < 0) {
+ fimc_err("[1] out_queue is empty\n");
+ fimc_dump_context(ctrl, ctx);
+ return -EINVAL;
+ }
+ }
+ }
+
+ mutex_lock(&ctrl->lock);
+ if (ctx->overlay.mode == FIMC_OVLY_DMA_AUTO && ctrl->fb.is_enable == 0) {
+ ret = fb_blank(registered_fb[ctx->overlay.fb_id],
+ FB_BLANK_UNBLANK);
+ if (ret < 0) {
+ fimc_err("%s: fb_blank: fb[%d] " \
+ "mode=FB_BLANK_UNBLANK\n",
+ __func__, ctx->overlay.fb_id);
+ mutex_unlock(&ctrl->lock);
+ return -EINVAL;
+ }
+ ctrl->fb.is_enable = 1;
+ }
+ mutex_unlock(&ctrl->lock);
+
+ b->index = idx;
+
+ fimc_info2("ctx(%d) dqueued idx = %d\n", ctx->ctx_num, b->index);
+
+ return ret;
+}
+
+int fimc_g_fmt_vid_out(struct file *filp, void *fh, struct v4l2_format *f)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ struct fimc_outinfo *out = ctrl->out;
+ struct fimc_ctx *ctx;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+ int i, j;
+
+ fimc_info1("%s: called\n", __func__);
+
+ if (ctrl->cap) {
+ fimc_err("%s: fimc is already used for capture mode\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if (!out) {
+ out = kzalloc(sizeof(*out), GFP_KERNEL);
+ if (!out) {
+ fimc_err("%s: no memory for outdev info\n", __func__);
+ return -ENOMEM;
+ }
+ ctrl->out = out;
+
+ /* init: struct fimc_outinfo */
+ out->last_ctx = -1;
+
+ spin_lock_init(&ctrl->out->lock_in);
+ spin_lock_init(&ctrl->out->lock_out);
+
+ for (i = 0; i < FIMC_INQUEUES; i++) {
+ ctrl->out->inq[i].ctx = -1;
+ ctrl->out->inq[i].idx = -1;
+ }
+
+ for (i = 0; i < FIMC_MAX_CTXS; i++) {
+ ctx = &ctrl->out->ctx[i];
+ ctx->ctx_num = i;
+ ctx->overlay.mode = FIMC_OVLY_NOT_FIXED;
+ ctx->status = FIMC_STREAMOFF;
+
+ for (j = 0; j < FIMC_OUTBUFS; j++) {
+ ctx->inq[j] = -1;
+ ctx->outq[j] = -1;
+ }
+ }
+
+ ctrl->out->idxs.prev.ctx = -1;
+ ctrl->out->idxs.prev.idx = -1;
+ ctrl->out->idxs.active.ctx = -1;
+ ctrl->out->idxs.active.idx = -1;
+ ctrl->out->idxs.next.ctx = -1;
+ ctrl->out->idxs.next.idx = -1;
+ }
+
+ f->fmt.pix = ctrl->out->ctx[ctx_id].pix;
+
+ return 0;
+}
+
+int fimc_try_fmt_vid_out(struct file *filp, void *fh, struct v4l2_format *f)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+ struct fimc_ctx *ctx;
+ u32 format = f->fmt.pix.pixelformat;
+
+ fimc_info1("%s: called. width(%d), height(%d)\n", __func__,
+ f->fmt.pix.width, f->fmt.pix.height);
+
+ ctx = &ctrl->out->ctx[ctx_id];
+ if (ctx->status != FIMC_STREAMOFF) {
+ fimc_err("FIMC is running\n");
+ return -EBUSY;
+ }
+
+ /* Check pixel format */
+ switch (format) {
+ case V4L2_PIX_FMT_NV16: /* fall through */
+ case V4L2_PIX_FMT_NV61: /* fall through */
+ case V4L2_PIX_FMT_NV12: /* fall through */
+ case V4L2_PIX_FMT_NV12T: /* fall through */
+ case V4L2_PIX_FMT_NV21: /* fall through */
+ case V4L2_PIX_FMT_YUYV: /* fall through */
+ case V4L2_PIX_FMT_UYVY: /* fall through */
+ case V4L2_PIX_FMT_YVYU: /* fall through */
+ case V4L2_PIX_FMT_VYUY: /* fall through */
+ case V4L2_PIX_FMT_RGB32: /* fall through */
+ case V4L2_PIX_FMT_RGB565: /* fall through */
+ case V4L2_PIX_FMT_YUV420:
+ break;
+ default:
+ fimc_warn("Supported format : \
+ V4L2_PIX_FMT_YUYV, V4L2_PIX_FMT_UYVY, \
+ V4L2_PIX_FMT_YVYU, V4L2_PIX_FMT_VYUY, \
+ V4L2_PIX_FMT_NV12, V4L2_PIX_FMT_NV12T, \
+ V4L2_PIX_FMT_NV21, V4L2_PIX_FMT_RGB32, \
+ V4L2_PIX_FMT_RGB565\n");
+ fimc_warn("Changed format : V4L2_PIX_FMT_RGB32\n");
+ f->fmt.pix.pixelformat = V4L2_PIX_FMT_RGB32;
+ return -EINVAL;
+ }
+
+ /* Fill the return value. */
+ switch (format) {
+ case V4L2_PIX_FMT_RGB32:
+ f->fmt.pix.bytesperline = f->fmt.pix.width << 2;
+ break;
+ case V4L2_PIX_FMT_NV16: /* fall through */
+ case V4L2_PIX_FMT_NV61: /* fall through */
+ case V4L2_PIX_FMT_YUYV: /* fall through */
+ case V4L2_PIX_FMT_UYVY: /* fall through */
+ case V4L2_PIX_FMT_YVYU: /* fall through */
+ case V4L2_PIX_FMT_VYUY: /* fall through */
+ case V4L2_PIX_FMT_RGB565:
+ f->fmt.pix.bytesperline = f->fmt.pix.width << 1;
+ break;
+ case V4L2_PIX_FMT_YUV420: /* fall through */
+ case V4L2_PIX_FMT_NV12: /* fall through */
+ case V4L2_PIX_FMT_NV21: /* fall through */
+ case V4L2_PIX_FMT_NV12T:
+ f->fmt.pix.bytesperline = (f->fmt.pix.width * 3) >> 1;
+ break;
+
+ default:
+ /* dummy value*/
+ f->fmt.pix.bytesperline = f->fmt.pix.width;
+ }
+
+ f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height;
+
+ return 0;
+}
+
+int fimc_s_fmt_vid_out(struct file *filp, void *fh, struct v4l2_format *f)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+ struct fimc_ctx *ctx;
+ int ret = -1;
+
+ fimc_info1("%s: called\n", __func__);
+
+ /* Check stream status */
+ ctx = &ctrl->out->ctx[ctx_id];
+ if (ctx->status != FIMC_STREAMOFF) {
+ fimc_err("FIMC is running\n");
+ return -EBUSY;
+ }
+
+ ret = fimc_try_fmt_vid_out(filp, fh, f);
+ if (ret < 0)
+ return ret;
+
+ ctx->pix = f->fmt.pix;
+
+ return ret;
+}
+
+int fimc_init_in_queue(struct fimc_control *ctrl, struct fimc_ctx *ctx)
+{
+ struct fimc_idx swap_queue[FIMC_INQUEUES];
+ int swap_cnt = 0, i;
+ unsigned long spin_flags;
+
+ spin_lock_irqsave(&ctrl->out->lock_in, spin_flags);
+
+ /* init incoming queue */
+ for (i = 0; i < FIMC_OUTBUFS; i++)
+ ctx->inq[i] = -1;
+
+ /* init common incoming queue */
+ for (i = 0; i < FIMC_INQUEUES; i++) {
+ if (ctrl->out->inq[i].ctx != ctx->ctx_num) {
+ swap_queue[swap_cnt].ctx = ctrl->out->inq[i].ctx;
+ swap_queue[swap_cnt].idx = ctrl->out->inq[i].idx;
+ swap_cnt++;
+ }
+
+ ctrl->out->inq[i].ctx = -1;
+ ctrl->out->inq[i].idx = -1;
+ }
+
+ /* restore common incoming queue */
+ for (i = 0; i < swap_cnt; i++) {
+ ctrl->out->inq[i].ctx = swap_queue[i].ctx;
+ ctrl->out->inq[i].idx = swap_queue[i].idx;
+ }
+
+ spin_unlock_irqrestore(&ctrl->out->lock_in, spin_flags);
+
+ return 0;
+}
+
+int fimc_init_out_queue(struct fimc_control *ctrl, struct fimc_ctx *ctx)
+{
+ unsigned long spin_flags;
+ int i;
+
+ spin_lock_irqsave(&ctrl->out->lock_out, spin_flags);
+
+ /* Init incoming queue */
+ for (i = 0; i < FIMC_OUTBUFS; i++)
+ ctx->outq[i] = -1;
+
+ spin_unlock_irqrestore(&ctrl->out->lock_out, spin_flags);
+
+ return 0;
+}
+
+int fimc_push_inq(struct fimc_control *ctrl, struct fimc_ctx *ctx, int idx)
+{
+ struct fimc_idx swap_common_inq[FIMC_INQUEUES];
+ int swap_queue[FIMC_OUTBUFS];
+ int i;
+ unsigned long spin_flags;
+
+ fimc_dbg("%s: idx = %d\n", __func__, idx);
+
+ if (ctrl->out->inq[FIMC_INQUEUES-1].idx != -1) {
+ fimc_err("FULL: common incoming queue\n");
+ return -EBUSY;
+ }
+
+ spin_lock_irqsave(&ctrl->out->lock_in, spin_flags);
+
+ /* ctx own incoming queue */
+ /* Backup original queue */
+ for (i = 0; i < FIMC_OUTBUFS; i++)
+ swap_queue[i] = ctx->inq[i];
+
+ /* Attach new idx */
+ ctx->inq[0] = idx;
+ ctx->src[idx].state = VIDEOBUF_QUEUED;
+ ctx->src[idx].flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED;
+
+ /* Shift the origonal queue */
+ for (i = 1; i < FIMC_OUTBUFS; i++)
+ ctx->inq[i] = swap_queue[i-1];
+
+ /* Common incoming queue */
+ /* Backup original queue */
+ for (i = 0; i < FIMC_INQUEUES; i++) {
+ swap_common_inq[i].ctx = ctrl->out->inq[i].ctx;
+ swap_common_inq[i].idx = ctrl->out->inq[i].idx;
+ }
+
+ /* Attach new idx */
+ ctrl->out->inq[0].ctx = ctx->ctx_num;
+ ctrl->out->inq[0].idx = idx;
+
+ /* Shift the origonal queue */
+ for (i = 1; i < FIMC_INQUEUES; i++) {
+ ctrl->out->inq[i].ctx = swap_common_inq[i-1].ctx;
+ ctrl->out->inq[i].idx = swap_common_inq[i-1].idx;
+ }
+
+ spin_unlock_irqrestore(&ctrl->out->lock_in, spin_flags);
+
+ return 0;
+}
+
+int fimc_pop_inq(struct fimc_control *ctrl, int *ctx_num, int *idx)
+{
+ struct fimc_ctx *ctx;
+ unsigned long spin_flags;
+ int i, ret = 0;
+ int ctx_idx = -1;
+
+ spin_lock_irqsave(&ctrl->out->lock_in, spin_flags);
+
+ /* find valid index from common incoming queue */
+ for (i = (FIMC_INQUEUES-1); i >= 0; i--) {
+ if (ctrl->out->inq[i].ctx != -1) {
+ *ctx_num = ctrl->out->inq[i].ctx;
+ *idx = ctrl->out->inq[i].idx;
+ ctrl->out->inq[i].ctx = -1;
+ ctrl->out->inq[i].idx = -1;
+ break;
+ }
+ }
+
+ /* common incoming queue is empty. */
+ if (i < 0) {
+ spin_unlock_irqrestore(&ctrl->out->lock_in, spin_flags);
+ return -EINVAL;
+ }
+
+ /* find valid index from incoming queue. */
+ ctx = &ctrl->out->ctx[*ctx_num];
+ for (i = (FIMC_OUTBUFS-1); i >= 0; i--) {
+ if (ctx->inq[i] != -1) {
+ ctx_idx = ctx->inq[i];
+ ctx->inq[i] = -1;
+ ctx->src[ctx_idx].state = VIDEOBUF_ACTIVE;
+ ctx->src[ctx_idx].flags = V4L2_BUF_FLAG_MAPPED;
+ break;
+ }
+ }
+
+ if (*idx != ctx_idx)
+ fimc_err("common inq(%d) vs inq(%d) mismatch\n", *idx, ctx_idx);
+
+ /* incoming queue is empty. */
+ if (i < 0)
+ ret = -EINVAL;
+ else
+ fimc_dbg("%s: index = %d\n", __func__, *idx);
+
+ spin_unlock_irqrestore(&ctrl->out->lock_in, spin_flags);
+
+ return ret;
+}
+
+int fimc_push_outq(struct fimc_control *ctrl, struct fimc_ctx *ctx, int idx)
+{
+ unsigned long spin_flags;
+ int swap_queue[FIMC_OUTBUFS];
+ int i;
+
+ fimc_dbg("%s: index = %d\n", __func__, idx);
+
+ spin_lock_irqsave(&ctrl->out->lock_out, spin_flags);
+
+ /* Backup original queue */
+ for (i = 0; i < FIMC_OUTBUFS; i++)
+ swap_queue[i] = ctx->outq[i];
+
+ /* Attach new index */
+ ctx->outq[0] = idx;
+ ctx->src[idx].state = VIDEOBUF_DONE;
+ ctx->src[idx].flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE;
+
+ /* Shift the origonal queue */
+ for (i = 1; i < FIMC_OUTBUFS; i++)
+ ctx->outq[i] = swap_queue[i-1];
+
+ spin_unlock_irqrestore(&ctrl->out->lock_out, spin_flags);
+
+ return 0;
+}
+
+int fimc_pop_outq(struct fimc_control *ctrl, struct fimc_ctx *ctx, int *idx)
+{
+ unsigned long spin_flags;
+ int i, ret = 0;
+
+ spin_lock_irqsave(&ctrl->out->lock_out, spin_flags);
+
+ /* Find last valid idx in outgoing queue. */
+ for (i = (FIMC_OUTBUFS-1); i >= 0; i--) {
+ if (ctx->outq[i] != -1) {
+ *idx = ctx->outq[i];
+ ctx->outq[i] = -1;
+ ctx->src[*idx].state = VIDEOBUF_IDLE;
+ ctx->src[*idx].flags = V4L2_BUF_FLAG_MAPPED;
+ break;
+ }
+ }
+
+ /* outgoing queue is empty. */
+ if (i < 0) {
+ ret = -EINVAL;
+ fimc_dbg("%s: outgoing queue : %d, %d, %d\n", __func__,
+ ctx->outq[0], ctx->outq[1], ctx->outq[2]);
+ } else
+ fimc_dbg("%s: idx = %d\n", __func__, *idx);
+
+
+ spin_unlock_irqrestore(&ctrl->out->lock_out, spin_flags);
+
+ return ret;
+}
+
+void fimc_dump_context(struct fimc_control *ctrl, struct fimc_ctx *ctx)
+{
+ int i = 0;
+
+ fimc_err("ctx%d, ctrl->status: %d, ctx->status: %d\n",
+ ctx->ctx_num, ctrl->status, ctx->status);
+
+ for (i = 0; i < FIMC_INQUEUES; i++)
+ fimc_err("ctrl->inq[%d]: ctx(%d) idx(%d)\n",
+ i, ctrl->out->inq[i].ctx, ctrl->out->inq[i].idx);
+
+ for (i = 0; i < FIMC_OUTBUFS; i++)
+ fimc_err("inq[%d] = %d\n", i, ctx->inq[i]);
+
+ for (i = 0; i < FIMC_OUTBUFS; i++)
+ fimc_err("outq[%d] = %d\n", i, ctx->outq[i]);
+
+ fimc_err("state : prev.ctx(%d), prev.idx(%d) "
+ "active.ctx(%d), active.idx(%d) "
+ "next.ctx(%d), next.idx(%d)\n",
+ ctrl->out->idxs.prev.ctx, ctrl->out->idxs.prev.idx,
+ ctrl->out->idxs.active.ctx, ctrl->out->idxs.active.idx,
+ ctrl->out->idxs.next.ctx, ctrl->out->idxs.next.idx);
+}
+
+void fimc_print_signal(struct fimc_control *ctrl)
+{
+ if (signal_pending(current)) {
+ fimc_dbg(".pend=%.8lx shpend=%.8lx\n",
+ current->pending.signal.sig[0],
+ current->signal->shared_pending.signal.sig[0]);
+ } else {
+ fimc_dbg(":pend=%.8lx shpend=%.8lx\n",
+ current->pending.signal.sig[0],
+ current->signal->shared_pending.signal.sig[0]);
+ }
+}
diff --git a/drivers/media/video/samsung/fimc/fimc_overlay.c b/drivers/media/video/samsung/fimc/fimc_overlay.c
new file mode 100644
index 0000000..ff43c2e
--- /dev/null
+++ b/drivers/media/video/samsung/fimc/fimc_overlay.c
@@ -0,0 +1,312 @@
+/* linux/drivers/media/video/samsung/fimc/fimc_overlay.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * V4L2 Overlay device support file for Samsung Camera Interface (FIMC) driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/slab.h>
+#include <linux/bootmem.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <plat/media.h>
+
+#include "fimc.h"
+
+int fimc_try_fmt_overlay(struct file *filp, void *fh, struct v4l2_format *f)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+ struct fimc_ctx *ctx;
+
+ u32 is_rotate = 0;
+ ctx = &ctrl->out->ctx[ctx_id];
+
+ fimc_info1("%s: top(%d) left(%d) width(%d) height(%d)\n", __func__,
+ f->fmt.win.w.top, f->fmt.win.w.left,
+ f->fmt.win.w.width, f->fmt.win.w.height);
+
+ if (ctx->overlay.mode == FIMC_OVLY_NONE_SINGLE_BUF ||
+ (ctx->overlay.mode == FIMC_OVLY_NONE_MULTI_BUF))
+ return 0;
+
+ /* Check Overlay Size : Overlay size must be smaller than LCD size. */
+ is_rotate = fimc_mapping_rot_flip(ctx->rotate, ctx->flip);
+ if (is_rotate & FIMC_ROT) { /* Landscape mode */
+ if (f->fmt.win.w.width > ctrl->fb.lcd_vres) {
+ fimc_warn("The width is changed %d -> %d\n",
+ f->fmt.win.w.width, ctrl->fb.lcd_vres);
+ f->fmt.win.w.width = ctrl->fb.lcd_vres;
+ }
+
+ if (f->fmt.win.w.height > ctrl->fb.lcd_hres) {
+ fimc_warn("The height is changed %d -> %d\n",
+ f->fmt.win.w.height, ctrl->fb.lcd_hres);
+ f->fmt.win.w.height = ctrl->fb.lcd_hres;
+ }
+ } else { /* Portrait mode */
+ if (f->fmt.win.w.width > ctrl->fb.lcd_hres) {
+ fimc_warn("The width is changed %d -> %d\n",
+ f->fmt.win.w.width, ctrl->fb.lcd_hres);
+ f->fmt.win.w.width = ctrl->fb.lcd_hres;
+ }
+
+ if (f->fmt.win.w.height > ctrl->fb.lcd_vres) {
+ fimc_warn("The height is changed %d -> %d\n",
+ f->fmt.win.w.height, ctrl->fb.lcd_vres);
+ f->fmt.win.w.height = ctrl->fb.lcd_vres;
+ }
+ }
+
+ return 0;
+}
+
+int fimc_g_fmt_vid_overlay(struct file *filp, void *fh, struct v4l2_format *f)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+ struct fimc_ctx *ctx;
+
+ ctx = &ctrl->out->ctx[ctx_id];
+
+ fimc_info1("%s: called\n", __func__);
+
+ f->fmt.win = ctx->win;
+
+ return 0;
+}
+
+static int fimc_check_pos(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx,
+ struct v4l2_format *f)
+{
+ if (ctx->win.w.width != f->fmt.win.w.width) {
+ fimc_err("%s: cannot change width\n", __func__);
+ return -EINVAL;
+ } else if (ctx->win.w.height != f->fmt.win.w.height) {
+ fimc_err("%s: cannot change height\n", __func__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int fimc_change_fifo_position(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx) {
+ struct v4l2_rect fimd_rect;
+ struct fb_info *fbinfo;
+ struct s3cfb_window *win;
+ int ret = -1;
+
+ fbinfo = registered_fb[ctx->overlay.fb_id];
+
+ memset(&fimd_rect, 0, sizeof(struct v4l2_rect));
+
+ ret = fimc_fimd_rect(ctrl, ctx, &fimd_rect);
+ if (ret < 0) {
+ fimc_err("fimc_fimd_rect fail\n");
+ return -EINVAL;
+ }
+
+ /* Update WIN position */
+ win->x = fimd_rect.left;
+ win->y = fimd_rect.top;
+
+ fbinfo->var.activate = FB_ACTIVATE_FORCE;
+ ret = fb_set_var(fbinfo, &fbinfo->var);
+ if (ret < 0) {
+ fimc_err("fb_set_var fail (ret=%d)\n", ret);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int fimc_s_fmt_vid_overlay(struct file *filp, void *fh, struct v4l2_format *f)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+ struct fimc_ctx *ctx;
+ int ret = -1;
+ ctx = &ctrl->out->ctx[ctx_id];
+
+ fimc_info1("%s: called\n", __func__);
+
+ switch (ctx->status) {
+ case FIMC_STREAMON:
+ ret = fimc_check_pos(ctrl, ctx, f);
+ if (ret < 0) {
+ fimc_err("When FIMC is running, "
+ "you can only move the position.\n");
+ return -EBUSY;
+ }
+
+ ret = fimc_try_fmt_overlay(filp, fh, f);
+ if (ret < 0)
+ return ret;
+
+ ctx->win = f->fmt.win;
+ fimc_change_fifo_position(ctrl, ctx);
+
+ break;
+ case FIMC_STREAMOFF:
+ ret = fimc_try_fmt_overlay(filp, fh, f);
+ if (ret < 0)
+ return ret;
+ ctx->win = f->fmt.win;
+
+ break;
+
+ default:
+ fimc_err("FIMC is running\n");
+ return -EBUSY;
+ }
+
+ return ret;
+}
+
+int fimc_g_fbuf(struct file *filp, void *fh, struct v4l2_framebuffer *fb)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+ struct fimc_ctx *ctx;
+ u32 bpp = 1, format;
+
+ ctx = &ctrl->out->ctx[ctx_id];
+
+ fimc_info1("%s: called\n", __func__);
+
+ fb->capability = ctx->fbuf.capability;
+ fb->flags = 0;
+ fb->base = ctx->fbuf.base;
+
+ fb->fmt.width = ctx->fbuf.fmt.width;
+ fb->fmt.height = ctx->fbuf.fmt.height;
+ fb->fmt.pixelformat = ctx->fbuf.fmt.pixelformat;
+ format = ctx->fbuf.fmt.pixelformat;
+
+ switch (format) {
+ case V4L2_PIX_FMT_YUV420: /* fall through */
+ case V4L2_PIX_FMT_NV12:
+ bpp = 1;
+ break;
+ case V4L2_PIX_FMT_RGB565:
+ bpp = 2;
+ break;
+ case V4L2_PIX_FMT_RGB32:
+ bpp = 4;
+ break;
+ }
+
+ ctx->fbuf.fmt.bytesperline = fb->fmt.width * bpp;
+ fb->fmt.bytesperline = ctx->fbuf.fmt.bytesperline;
+ fb->fmt.sizeimage = ctx->fbuf.fmt.sizeimage;
+ fb->fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;
+ fb->fmt.priv = 0;
+
+ return 0;
+}
+
+int fimc_s_fbuf(struct file *filp, void *fh, struct v4l2_framebuffer *fb)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+ struct fimc_ctx *ctx;
+ u32 bpp = 1;
+ u32 format = fb->fmt.pixelformat;
+ ctx = &ctrl->out->ctx[ctx_id];
+
+ fimc_info1("%s: called. width(%d), height(%d)\n",
+ __func__, fb->fmt.width, fb->fmt.height);
+
+ ctx->fbuf.capability = V4L2_FBUF_CAP_EXTERNOVERLAY;
+ ctx->fbuf.flags = 0;
+ ctx->fbuf.base = fb->base;
+
+ if (ctx->overlay.mode == FIMC_OVLY_NONE_MULTI_BUF) {
+ ctx->fbuf.fmt.width = fb->fmt.width;
+ ctx->fbuf.fmt.height = fb->fmt.height;
+ ctx->fbuf.fmt.pixelformat = fb->fmt.pixelformat;
+
+ switch (format) {
+ case V4L2_PIX_FMT_YUV420: /* fall through */
+ case V4L2_PIX_FMT_NV12:
+ bpp = 1;
+ break;
+ case V4L2_PIX_FMT_RGB565:
+ bpp = 2;
+ break;
+ case V4L2_PIX_FMT_RGB32:
+ bpp = 4;
+ break;
+ }
+
+ ctx->fbuf.fmt.bytesperline = fb->fmt.width * bpp;
+ ctx->fbuf.fmt.sizeimage = fb->fmt.sizeimage;
+ ctx->fbuf.fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;
+ ctx->fbuf.fmt.priv = 0;
+ } else if (fb->base) {
+ ctx->fbuf.fmt.width = fb->fmt.width;
+ ctx->fbuf.fmt.height = fb->fmt.height;
+ ctx->fbuf.fmt.pixelformat = fb->fmt.pixelformat;
+
+ switch (format) {
+ case V4L2_PIX_FMT_YUV420: /* fall through */
+ case V4L2_PIX_FMT_NV12:
+ bpp = 1;
+ break;
+ case V4L2_PIX_FMT_RGB565:
+ bpp = 2;
+ break;
+ case V4L2_PIX_FMT_RGB32:
+ bpp = 4;
+ break;
+ }
+
+ ctx->fbuf.fmt.bytesperline = fb->fmt.width * bpp;
+ ctx->fbuf.fmt.sizeimage = fb->fmt.sizeimage;
+ ctx->fbuf.fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;
+ ctx->fbuf.fmt.priv = 0;
+
+ ctx->overlay.mode = FIMC_OVLY_NONE_SINGLE_BUF;
+ } else {
+ int i;
+ struct s3cfb_window *win = NULL;
+ ctx->overlay.fb_id = -1;
+
+ for (i = 0; i < num_registered_fb; i++) {
+ win = (struct s3cfb_window *)registered_fb[i]->par;
+ if (win->id == ctrl->id) {
+ ctx->overlay.fb_id = i;
+ fimc_info2("%s: overlay.fb_id = %d\n",
+ __func__, ctx->overlay.fb_id);
+ break;
+ }
+ }
+
+ if (-1 == ctx->overlay.fb_id) {
+ fimc_err("%s: fb[%d] is not registered. " \
+ "must be registered for overlay\n",
+ __func__, ctrl->id);
+ return -1;
+ }
+
+ if (1 == win->enabled) {
+ fimc_err("%s: fb[%d] is already being used. " \
+ "must be not used for overlay\n",
+ __func__, ctrl->id);
+ return -1;
+ }
+
+ ctx->overlay.mode = FIMC_OVLY_NOT_FIXED;
+ }
+
+ return 0;
+}
diff --git a/drivers/media/video/samsung/fimc/fimc_regs.c b/drivers/media/video/samsung/fimc/fimc_regs.c
new file mode 100644
index 0000000..227945a
--- /dev/null
+++ b/drivers/media/video/samsung/fimc/fimc_regs.c
@@ -0,0 +1,1801 @@
+/* linux/drivers/media/video/samsung/fimc/fimc_regs.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Register interface file for Samsung Camera Interface (FIMC) driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_samsung.h>
+#include <linux/io.h>
+#include <mach/map.h>
+#include <plat/regs-fimc.h>
+#include <plat/fimc.h>
+
+#include "fimc.h"
+
+/* struct fimc_limit: Limits for FIMC */
+struct fimc_limit fimc40_limits[FIMC_DEVICES] = {
+ {
+ .pre_dst_w = 3264,
+ .bypass_w = 8192,
+ .trg_h_no_rot = 3264,
+ .trg_h_rot = 1280,
+ .real_w_no_rot = 8192,
+ .real_h_rot = 1280,
+ }, {
+ .pre_dst_w = 1280,
+ .bypass_w = 8192,
+ .trg_h_no_rot = 1280,
+ .trg_h_rot = 8192,
+ .real_w_no_rot = 8192,
+ .real_h_rot = 768,
+ }, {
+ .pre_dst_w = 1440,
+ .bypass_w = 8192,
+ .trg_h_no_rot = 1440,
+ .trg_h_rot = 0,
+ .real_w_no_rot = 8192,
+ .real_h_rot = 0,
+ },
+};
+
+struct fimc_limit fimc43_limits[FIMC_DEVICES] = {
+ {
+ .pre_dst_w = 4224,
+ .bypass_w = 8192,
+ .trg_h_no_rot = 4224,
+ .trg_h_rot = 1920,
+ .real_w_no_rot = 8192,
+ .real_h_rot = 1920,
+ }, {
+ .pre_dst_w = 4224,
+ .bypass_w = 8192,
+ .trg_h_no_rot = 4224,
+ .trg_h_rot = 1920,
+ .real_w_no_rot = 8192,
+ .real_h_rot = 1920,
+ }, {
+ .pre_dst_w = 1920,
+ .bypass_w = 8192,
+ .trg_h_no_rot = 1920,
+ .trg_h_rot = 1280,
+ .real_w_no_rot = 8192,
+ .real_h_rot = 1280,
+ },
+};
+
+struct fimc_limit fimc50_limits[FIMC_DEVICES] = {
+ {
+ .pre_dst_w = 4224,
+ .bypass_w = 8192,
+ .trg_h_no_rot = 4224,
+ .trg_h_rot = 1920,
+ .real_w_no_rot = 8192,
+ .real_h_rot = 1920,
+ }, {
+ .pre_dst_w = 4224,
+ .bypass_w = 8192,
+ .trg_h_no_rot = 4224,
+ .trg_h_rot = 1920,
+ .real_w_no_rot = 8192,
+ .real_h_rot = 1920,
+ }, {
+ .pre_dst_w = 1920,
+ .bypass_w = 8192,
+ .trg_h_no_rot = 1920,
+ .trg_h_rot = 1280,
+ .real_w_no_rot = 8192,
+ .real_h_rot = 1280,
+ },
+};
+
+int fimc_hwset_camera_source(struct fimc_control *ctrl)
+{
+ struct s3c_platform_camera *cam = ctrl->cam;
+ u32 cfg = 0;
+
+ /* for now, we support only ITU601 8 bit mode */
+ cfg |= S3C_CISRCFMT_ITU601_8BIT;
+ cfg |= cam->order422;
+
+ if (cam->type == CAM_TYPE_ITU)
+ cfg |= cam->fmt;
+
+ cfg |= S3C_CISRCFMT_SOURCEHSIZE(cam->width);
+ cfg |= S3C_CISRCFMT_SOURCEVSIZE(cam->height);
+
+ writel(cfg, ctrl->regs + S3C_CISRCFMT);
+
+ return 0;
+}
+
+int fimc_hwset_enable_irq(struct fimc_control *ctrl, int overflow, int level)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CIGCTRL);
+
+ cfg &= ~(S3C_CIGCTRL_IRQ_OVFEN | S3C_CIGCTRL_IRQ_LEVEL);
+ cfg |= S3C_CIGCTRL_IRQ_ENABLE;
+
+ if (overflow)
+ cfg |= S3C_CIGCTRL_IRQ_OVFEN;
+
+ if (level)
+ cfg |= S3C_CIGCTRL_IRQ_LEVEL;
+
+ writel(cfg, ctrl->regs + S3C_CIGCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_disable_irq(struct fimc_control *ctrl)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CIGCTRL);
+
+ cfg &= ~(S3C_CIGCTRL_IRQ_OVFEN | S3C_CIGCTRL_IRQ_ENABLE);
+ writel(cfg, ctrl->regs + S3C_CIGCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_clear_irq(struct fimc_control *ctrl)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CIGCTRL);
+
+ cfg |= S3C_CIGCTRL_IRQ_CLR;
+
+ writel(cfg, ctrl->regs + S3C_CIGCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_output_area_size(struct fimc_control *ctrl, u32 size)
+{
+ u32 cfg = 0;
+
+ cfg = S3C_CITAREA_TARGET_AREA(size);
+
+ writel(cfg, ctrl->regs + S3C_CITAREA);
+
+ return 0;
+}
+
+void fimc_wait_disable_capture(struct fimc_control *ctrl)
+{
+ unsigned long timeo = jiffies + 20; /* timeout of 100 ms */
+ u32 cfg;
+
+ if (!ctrl || !ctrl->cap ||
+ ctrl->cap->fmt.colorspace == V4L2_COLORSPACE_JPEG)
+ return;
+
+ while (time_before(jiffies, timeo)) {
+ cfg = readl(ctrl->regs + S3C_CISTATUS);
+
+ if (0 == (cfg & S3C_CISTATUS_IMGCPTEN))
+ break;
+
+ msleep(10);
+ }
+
+ dev_dbg(ctrl->dev, "IMGCPTEN: Wait time = %d ms\n",
+ jiffies_to_msecs(jiffies - timeo + 20));
+
+ return;
+}
+
+int fimc_hwset_image_effect(struct fimc_control *ctrl)
+{
+ u32 cfg = 0;
+
+ if (ctrl->fe.ie_on) {
+ if (ctrl->fe.ie_after_sc)
+ cfg |= S3C_CIIMGEFF_IE_SC_AFTER;
+
+ cfg |= S3C_CIIMGEFF_FIN(ctrl->fe.fin);
+
+ if (ctrl->fe.fin == FIMC_EFFECT_FIN_ARBITRARY_CBCR)
+ cfg |= S3C_CIIMGEFF_PAT_CB(ctrl->fe.pat_cb) |
+ S3C_CIIMGEFF_PAT_CR(ctrl->fe.pat_cr);
+
+ cfg |= S3C_CIIMGEFF_IE_ENABLE;
+ }
+
+ writel(cfg, ctrl->regs + S3C_CIIMGEFF);
+
+ return 0;
+}
+
+int fimc_hwset_shadow_enable(struct fimc_control *ctrl)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CIGCTRL);
+
+ cfg &= ~S3C_CIGCTRL_SHADOW_DISABLE;
+
+ writel(cfg, ctrl->regs + S3C_CIGCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_shadow_disable(struct fimc_control *ctrl)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CIGCTRL);
+
+ cfg |= S3C_CIGCTRL_SHADOW_DISABLE;
+
+ writel(cfg, ctrl->regs + S3C_CIGCTRL);
+
+ return 0;
+}
+
+static void fimc_reset_cfg(struct fimc_control *ctrl)
+{
+ int i;
+ u32 cfg[][2] = {
+ { 0x018, 0x00000000 }, { 0x01c, 0x00000000 },
+ { 0x020, 0x00000000 }, { 0x024, 0x00000000 },
+ { 0x028, 0x00000000 }, { 0x02c, 0x00000000 },
+ { 0x030, 0x00000000 }, { 0x034, 0x00000000 },
+ { 0x038, 0x00000000 }, { 0x03c, 0x00000000 },
+ { 0x040, 0x00000000 }, { 0x044, 0x00000000 },
+ { 0x048, 0x00000000 }, { 0x04c, 0x00000000 },
+ { 0x050, 0x00000000 }, { 0x054, 0x00000000 },
+ { 0x058, 0x18000000 }, { 0x05c, 0x00000000 },
+ { 0x0c0, 0x00000000 }, { 0x0c4, 0xffffffff },
+ { 0x0d0, 0x00100080 }, { 0x0d4, 0x00000000 },
+ { 0x0d8, 0x00000000 }, { 0x0dc, 0x00000000 },
+ { 0x0f8, 0x00000000 }, { 0x0fc, 0x04000000 },
+ { 0x168, 0x00000000 }, { 0x16c, 0x00000000 },
+ { 0x170, 0x00000000 }, { 0x174, 0x00000000 },
+ { 0x178, 0x00000000 }, { 0x17c, 0x00000000 },
+ { 0x180, 0x00000000 }, { 0x184, 0x00000000 },
+ { 0x188, 0x00000000 }, { 0x18c, 0x00000000 },
+ { 0x194, 0x0000001e },
+ };
+
+ for (i = 0; i < sizeof(cfg) / 8; i++)
+ writel(cfg[i][1], ctrl->regs + cfg[i][0]);
+}
+
+int fimc_hwset_reset(struct fimc_control *ctrl)
+{
+ u32 cfg = 0;
+
+ cfg = readl(ctrl->regs + S3C_CISRCFMT);
+ cfg |= S3C_CISRCFMT_ITU601_8BIT;
+ writel(cfg, ctrl->regs + S3C_CISRCFMT);
+
+ /* s/w reset */
+ cfg = readl(ctrl->regs + S3C_CIGCTRL);
+ cfg |= (S3C_CIGCTRL_SWRST);
+ writel(cfg, ctrl->regs + S3C_CIGCTRL);
+ mdelay(1);
+
+ cfg = readl(ctrl->regs + S3C_CIGCTRL);
+ cfg &= ~S3C_CIGCTRL_SWRST;
+ writel(cfg, ctrl->regs + S3C_CIGCTRL);
+
+ /* in case of ITU656, CISRCFMT[31] should be 0 */
+ if ((ctrl->cap != NULL) && (ctrl->cam->fmt == ITU_656_YCBCR422_8BIT)) {
+ cfg = readl(ctrl->regs + S3C_CISRCFMT);
+ cfg &= ~S3C_CISRCFMT_ITU601_8BIT;
+ writel(cfg, ctrl->regs + S3C_CISRCFMT);
+ }
+
+ fimc_reset_cfg(ctrl);
+
+ return 0;
+}
+
+int fimc_hwset_sw_reset(struct fimc_control *ctrl)
+{
+ u32 cfg = 0;
+
+ /* s/w reset */
+ cfg = readl(ctrl->regs + S3C_CIGCTRL);
+ cfg |= (S3C_CIGCTRL_SWRST);
+ writel(cfg, ctrl->regs + S3C_CIGCTRL);
+
+ cfg = readl(ctrl->regs + S3C_CIGCTRL);
+ cfg &= ~S3C_CIGCTRL_SWRST;
+ writel(cfg, ctrl->regs + S3C_CIGCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_clksrc(struct fimc_control *ctrl, int src_clk)
+{
+ u32 cfg = readl(ctrl->regs + S3C_MISC_FIMC);
+ cfg &= ~S3C_CLKSRC_HCLK_MASK;
+
+ if (src_clk == FIMC_HCLK)
+ cfg |= S3C_CLKSRC_HCLK;
+ else if (src_clk == FIMC_SCLK)
+ cfg |= S3C_CLKSRC_SCLK;
+
+ writel(cfg, ctrl->regs + S3C_MISC_FIMC);
+ return 0;
+}
+
+int fimc_hwget_overflow_state(struct fimc_control *ctrl)
+{
+ u32 cfg, status, flag;
+
+ status = readl(ctrl->regs + S3C_CISTATUS);
+ flag = S3C_CISTATUS_OVFIY | S3C_CISTATUS_OVFICB | S3C_CISTATUS_OVFICR;
+
+ if (status & flag) {
+ cfg = readl(ctrl->regs + S3C_CIWDOFST);
+ cfg |= (S3C_CIWDOFST_CLROVFIY | S3C_CIWDOFST_CLROVFICB |
+ S3C_CIWDOFST_CLROVFICR);
+ writel(cfg, ctrl->regs + S3C_CIWDOFST);
+
+ cfg = readl(ctrl->regs + S3C_CIWDOFST);
+ cfg &= ~(S3C_CIWDOFST_CLROVFIY | S3C_CIWDOFST_CLROVFICB |
+ S3C_CIWDOFST_CLROVFICR);
+ writel(cfg, ctrl->regs + S3C_CIWDOFST);
+
+ return 1;
+ }
+
+ return 0;
+}
+
+int fimc_hwset_camera_offset(struct fimc_control *ctrl)
+{
+ struct s3c_platform_camera *cam = ctrl->cam;
+ struct v4l2_rect *rect = &cam->window;
+ u32 cfg, h1, h2, v1, v2;
+
+ if (!cam) {
+ fimc_err("%s: no active camera\n", __func__);
+ return -ENODEV;
+ }
+
+ h1 = rect->left;
+ h2 = cam->width - rect->width - rect->left;
+ v1 = rect->top;
+ v2 = cam->height - rect->height - rect->top;
+
+ cfg = readl(ctrl->regs + S3C_CIWDOFST);
+ cfg &= ~(S3C_CIWDOFST_WINHOROFST_MASK | S3C_CIWDOFST_WINVEROFST_MASK);
+ cfg |= S3C_CIWDOFST_WINHOROFST(h1);
+ cfg |= S3C_CIWDOFST_WINVEROFST(v1);
+ cfg |= S3C_CIWDOFST_WINOFSEN;
+ writel(cfg, ctrl->regs + S3C_CIWDOFST);
+
+ cfg = 0;
+ cfg |= S3C_CIWDOFST2_WINHOROFST2(h2);
+ cfg |= S3C_CIWDOFST2_WINVEROFST2(v2);
+ writel(cfg, ctrl->regs + S3C_CIWDOFST2);
+
+ return 0;
+}
+
+int fimc_hwset_camera_polarity(struct fimc_control *ctrl)
+{
+ struct s3c_platform_camera *cam = ctrl->cam;
+ u32 cfg;
+
+ if (!cam) {
+ fimc_err("%s: no active camera\n", __func__);
+ return -ENODEV;
+ }
+
+ cfg = readl(ctrl->regs + S3C_CIGCTRL);
+
+ cfg &= ~(S3C_CIGCTRL_INVPOLPCLK | S3C_CIGCTRL_INVPOLVSYNC |
+ S3C_CIGCTRL_INVPOLHREF | S3C_CIGCTRL_INVPOLHSYNC);
+
+ if (cam->inv_pclk)
+ cfg |= S3C_CIGCTRL_INVPOLPCLK;
+
+ if (cam->inv_vsync)
+ cfg |= S3C_CIGCTRL_INVPOLVSYNC;
+
+ if (cam->inv_href)
+ cfg |= S3C_CIGCTRL_INVPOLHREF;
+
+ if (cam->inv_hsync)
+ cfg |= S3C_CIGCTRL_INVPOLHSYNC;
+
+ writel(cfg, ctrl->regs + S3C_CIGCTRL);
+
+ return 0;
+}
+
+int fimc40_hwset_camera_type(struct fimc_control *ctrl)
+{
+ struct s3c_platform_camera *cam = ctrl->cam;
+ u32 cfg;
+
+ if (!cam) {
+ fimc_err("%s: no active camera\n", __func__);
+ return -ENODEV;
+ }
+
+ cfg = readl(ctrl->regs + S3C_CIGCTRL);
+ cfg &= ~(S3C_CIGCTRL_TESTPATTERN_MASK | S3C_CIGCTRL_SELCAM_ITU_MASK |
+ S3C_CIGCTRL_SELCAM_FIMC_MASK);
+
+ /* Interface selection */
+ if (cam->type == CAM_TYPE_MIPI) {
+ cfg |= S3C_CIGCTRL_SELCAM_FIMC_MIPI;
+ writel(cam->fmt, ctrl->regs + S3C_CSIIMGFMT);
+ } else if (cam->type == CAM_TYPE_ITU) {
+ if (cam->id == CAMERA_PAR_A)
+ cfg |= S3C_CIGCTRL_SELCAM_ITU_A;
+ else
+ cfg |= S3C_CIGCTRL_SELCAM_ITU_B;
+ /* switch to ITU interface */
+ cfg |= S3C_CIGCTRL_SELCAM_FIMC_ITU;
+ } else {
+ fimc_err("%s: invalid camera bus type selected\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ writel(cfg, ctrl->regs + S3C_CIGCTRL);
+
+ return 0;
+}
+
+int fimc43_hwset_camera_type(struct fimc_control *ctrl)
+{
+ struct s3c_platform_camera *cam = ctrl->cam;
+ u32 cfg;
+
+ if (!cam) {
+ fimc_err("%s: no active camera\n", __func__);
+ return -ENODEV;
+ }
+
+ cfg = readl(ctrl->regs + S3C_CIGCTRL);
+ cfg &= ~(S3C_CIGCTRL_TESTPATTERN_MASK | S3C_CIGCTRL_SELCAM_ITU_MASK |
+ S3C_CIGCTRL_SELCAM_MIPI_MASK | S3C_CIGCTRL_SELCAM_FIMC_MASK |
+ S3C_CIGCTRL_SELWB_CAMIF_MASK);
+
+ /* Interface selection */
+ if (cam->id == CAMERA_WB) {
+ cfg |= S3C_CIGCTRL_SELWB_CAMIF_WRITEBACK;
+ } else if (cam->type == CAM_TYPE_MIPI) {
+ cfg |= S3C_CIGCTRL_SELCAM_FIMC_MIPI;
+
+ /* C110/V210 Support only MIPI A support */
+ cfg |= S3C_CIGCTRL_SELCAM_MIPI_A;
+
+ /* FIXME: Temporary MIPI CSIS Data 32 bit aligned */
+ if (ctrl->cap->fmt.pixelformat == V4L2_PIX_FMT_JPEG)
+ writel((MIPI_USER_DEF_PACKET_1 | (0x1 << 8)),
+ ctrl->regs + S3C_CSIIMGFMT);
+ else
+ writel(cam->fmt | (0x1 << 8),
+ ctrl->regs + S3C_CSIIMGFMT);
+ } else if (cam->type == CAM_TYPE_ITU) {
+ if (cam->id == CAMERA_PAR_A)
+ cfg |= S3C_CIGCTRL_SELCAM_ITU_A;
+ else
+ cfg |= S3C_CIGCTRL_SELCAM_ITU_B;
+ /* switch to ITU interface */
+ cfg |= S3C_CIGCTRL_SELCAM_FIMC_ITU;
+ } else {
+ fimc_err("%s: invalid camera bus type selected\n", __func__);
+ return -EINVAL;
+ }
+
+ writel(cfg, ctrl->regs + S3C_CIGCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_camera_type(struct fimc_control *ctrl)
+{
+ struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
+
+ switch (pdata->hw_ver) {
+ case 0x40:
+ fimc40_hwset_camera_type(ctrl);
+ break;
+ case 0x43:
+ case 0x45:
+ fimc43_hwset_camera_type(ctrl);
+ break;
+ default:
+ fimc43_hwset_camera_type(ctrl);
+ break;
+ }
+
+ return 0;
+}
+
+
+int fimc_hwset_jpeg_mode(struct fimc_control *ctrl, bool enable)
+{
+ u32 cfg;
+ cfg = readl(ctrl->regs + S3C_CIGCTRL);
+
+ if (enable)
+ cfg |= S3C_CIGCTRL_CAM_JPEG;
+ else
+ cfg &= ~S3C_CIGCTRL_CAM_JPEG;
+
+ writel(cfg, ctrl->regs + S3C_CIGCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_output_size(struct fimc_control *ctrl, int width, int height)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CITRGFMT);
+
+ cfg &= ~(S3C_CITRGFMT_TARGETH_MASK | S3C_CITRGFMT_TARGETV_MASK);
+
+ cfg |= S3C_CITRGFMT_TARGETHSIZE(width);
+ cfg |= S3C_CITRGFMT_TARGETVSIZE(height);
+
+ writel(cfg, ctrl->regs + S3C_CITRGFMT);
+
+ return 0;
+}
+
+int fimc_hwset_output_colorspace(struct fimc_control *ctrl, u32 pixelformat)
+{
+ struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
+ u32 cfg;
+
+ if (pdata->hw_ver != 0x40) {
+ if (pixelformat == V4L2_PIX_FMT_YUV444) {
+ cfg = readl(ctrl->regs + S3C_CIEXTEN);
+ cfg |= S3C_CIEXTEN_YUV444_OUT;
+ writel(cfg, ctrl->regs + S3C_CIEXTEN);
+
+ return 0;
+ } else {
+ cfg = readl(ctrl->regs + S3C_CIEXTEN);
+ cfg &= ~S3C_CIEXTEN_YUV444_OUT;
+ writel(cfg, ctrl->regs + S3C_CIEXTEN);
+ }
+ }
+
+ cfg = readl(ctrl->regs + S3C_CITRGFMT);
+ cfg &= ~S3C_CITRGFMT_OUTFORMAT_MASK;
+
+ switch (pixelformat) {
+ case V4L2_PIX_FMT_JPEG:
+ break;
+ case V4L2_PIX_FMT_RGB565: /* fall through */
+ case V4L2_PIX_FMT_RGB32:
+ cfg |= S3C_CITRGFMT_OUTFORMAT_RGB;
+ break;
+
+ case V4L2_PIX_FMT_YUYV: /* fall through */
+ case V4L2_PIX_FMT_UYVY: /* fall through */
+ case V4L2_PIX_FMT_VYUY: /* fall through */
+ case V4L2_PIX_FMT_YVYU:
+ cfg |= S3C_CITRGFMT_OUTFORMAT_YCBCR422_1PLANE;
+ break;
+
+ case V4L2_PIX_FMT_NV16: /* fall through */
+ case V4L2_PIX_FMT_NV61: /* fall through */
+ case V4L2_PIX_FMT_YUV422P:
+ cfg |= S3C_CITRGFMT_OUTFORMAT_YCBCR422;
+ break;
+
+ case V4L2_PIX_FMT_YUV420: /* fall through */
+ case V4L2_PIX_FMT_NV12: /* fall through */
+ case V4L2_PIX_FMT_NV12T: /* fall through */
+ case V4L2_PIX_FMT_NV21:
+ cfg |= S3C_CITRGFMT_OUTFORMAT_YCBCR420;
+ break;
+
+ default:
+ fimc_err("%s: invalid pixel format\n", __func__);
+ break;
+ }
+
+ writel(cfg, ctrl->regs + S3C_CITRGFMT);
+
+ return 0;
+}
+
+int fimc_hwset_output_rot_flip(struct fimc_control *ctrl, u32 rot, u32 flip)
+{
+ u32 cfg, val;
+
+ cfg = readl(ctrl->regs + S3C_CITRGFMT);
+ cfg &= ~S3C_CITRGFMT_FLIP_MASK;
+ cfg &= ~S3C_CITRGFMT_OUTROT90_CLOCKWISE;
+
+ val = fimc_mapping_rot_flip(rot, flip);
+
+ if (val & FIMC_ROT)
+ cfg |= S3C_CITRGFMT_OUTROT90_CLOCKWISE;
+
+ if (val & FIMC_XFLIP)
+ cfg |= S3C_CITRGFMT_FLIP_X_MIRROR;
+
+ if (val & FIMC_YFLIP)
+ cfg |= S3C_CITRGFMT_FLIP_Y_MIRROR;
+
+ writel(cfg, ctrl->regs + S3C_CITRGFMT);
+
+ return 0;
+}
+
+int fimc_hwset_output_area(struct fimc_control *ctrl, u32 width, u32 height)
+{
+ u32 cfg = 0;
+
+ cfg = S3C_CITAREA_TARGET_AREA(width * height);
+ writel(cfg, ctrl->regs + S3C_CITAREA);
+
+ return 0;
+}
+
+int fimc_hwset_enable_lastirq(struct fimc_control *ctrl)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CIOCTRL);
+
+ cfg |= S3C_CIOCTRL_LASTIRQ_ENABLE;
+ writel(cfg, ctrl->regs + S3C_CIOCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_disable_lastirq(struct fimc_control *ctrl)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CIOCTRL);
+
+ cfg &= ~S3C_CIOCTRL_LASTIRQ_ENABLE;
+ writel(cfg, ctrl->regs + S3C_CIOCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_prescaler(struct fimc_control *ctrl, struct fimc_scaler *sc)
+{
+ u32 cfg = 0, shfactor;
+
+ shfactor = 10 - (sc->hfactor + sc->vfactor);
+
+ cfg |= S3C_CISCPRERATIO_SHFACTOR(shfactor);
+ cfg |= S3C_CISCPRERATIO_PREHORRATIO(sc->pre_hratio);
+ cfg |= S3C_CISCPRERATIO_PREVERRATIO(sc->pre_vratio);
+
+ writel(cfg, ctrl->regs + S3C_CISCPRERATIO);
+
+ cfg = 0;
+ cfg |= S3C_CISCPREDST_PREDSTWIDTH(sc->pre_dst_width);
+ cfg |= S3C_CISCPREDST_PREDSTHEIGHT(sc->pre_dst_height);
+
+ writel(cfg, ctrl->regs + S3C_CISCPREDST);
+
+ return 0;
+}
+
+int fimc_hwset_output_address(struct fimc_control *ctrl,
+ struct fimc_buf_set *bs, int id)
+{
+ writel(bs->base[FIMC_ADDR_Y], ctrl->regs + S3C_CIOYSA(id));
+ writel(bs->base[FIMC_ADDR_CB], ctrl->regs + S3C_CIOCBSA(id));
+ writel(bs->base[FIMC_ADDR_CR], ctrl->regs + S3C_CIOCRSA(id));
+
+ return 0;
+}
+
+int fimc_hwset_output_yuv(struct fimc_control *ctrl, u32 pixelformat)
+{
+ u32 cfg;
+
+ cfg = readl(ctrl->regs + S3C_CIOCTRL);
+ cfg &= ~(S3C_CIOCTRL_ORDER2P_MASK | S3C_CIOCTRL_ORDER422_MASK |
+ S3C_CIOCTRL_YCBCR_PLANE_MASK);
+
+ switch (pixelformat) {
+ /* 1 plane formats */
+ case V4L2_PIX_FMT_YUYV:
+ cfg |= S3C_CIOCTRL_ORDER422_YCBYCR;
+ break;
+
+ case V4L2_PIX_FMT_UYVY:
+ cfg |= S3C_CIOCTRL_ORDER422_CBYCRY;
+ break;
+
+ case V4L2_PIX_FMT_VYUY:
+ cfg |= S3C_CIOCTRL_ORDER422_CRYCBY;
+ break;
+
+ case V4L2_PIX_FMT_YVYU:
+ cfg |= S3C_CIOCTRL_ORDER422_YCRYCB;
+ break;
+
+ /* 2 plane formats */
+ case V4L2_PIX_FMT_NV12: /* fall through */
+ case V4L2_PIX_FMT_NV12T: /* fall through */
+ case V4L2_PIX_FMT_NV16:
+ cfg |= S3C_CIOCTRL_ORDER2P_LSB_CBCR;
+ cfg |= S3C_CIOCTRL_YCBCR_2PLANE;
+ break;
+
+ case V4L2_PIX_FMT_NV21: /* fall through */
+ case V4L2_PIX_FMT_NV61:
+ cfg |= S3C_CIOCTRL_ORDER2P_LSB_CRCB;
+ cfg |= S3C_CIOCTRL_YCBCR_2PLANE;
+ break;
+
+ /* 3 plane formats */
+ case V4L2_PIX_FMT_YUV422P: /* fall through */
+ case V4L2_PIX_FMT_YUV420:
+ cfg |= S3C_CIOCTRL_YCBCR_3PLANE;
+ break;
+ }
+
+ writel(cfg, ctrl->regs + S3C_CIOCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_output_scan(struct fimc_control *ctrl,
+ struct v4l2_pix_format *fmt)
+{
+ struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
+ u32 cfg;
+
+ /* nothing to do: FIMC40 not supported interlaced and weave output */
+ if (pdata->hw_ver == 0x40)
+ return 0;
+
+ cfg = readl(ctrl->regs + S3C_CISCCTRL);
+ cfg &= ~S3C_CISCCTRL_SCAN_MASK;
+
+ if (fmt->field == V4L2_FIELD_INTERLACED ||
+ fmt->field == V4L2_FIELD_INTERLACED_TB)
+ cfg |= S3C_CISCCTRL_INTERLACE;
+ else
+ cfg |= S3C_CISCCTRL_PROGRESSIVE;
+
+ writel(cfg, ctrl->regs + S3C_CISCCTRL);
+
+ cfg = readl(ctrl->regs + S3C_CIOCTRL);
+ cfg &= ~S3C_CIOCTRL_WEAVE_MASK;
+
+ if ((ctrl->cap) && (fmt->field == V4L2_FIELD_INTERLACED_TB))
+ cfg |= S3C_CIOCTRL_WEAVE_OUT;
+
+ writel(cfg, ctrl->regs + S3C_CIOCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_input_rot(struct fimc_control *ctrl, u32 rot, u32 flip)
+{
+ u32 cfg, val;
+
+ cfg = readl(ctrl->regs + S3C_CITRGFMT);
+ cfg &= ~S3C_CITRGFMT_INROT90_CLOCKWISE;
+
+ val = fimc_mapping_rot_flip(rot, flip);
+
+ if (val & FIMC_ROT)
+ cfg |= S3C_CITRGFMT_INROT90_CLOCKWISE;
+
+ writel(cfg, ctrl->regs + S3C_CITRGFMT);
+
+ return 0;
+}
+
+int fimc40_hwset_scaler(struct fimc_control *ctrl, struct fimc_scaler *sc)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CISCCTRL);
+
+ cfg &= ~(S3C_CISCCTRL_SCALERBYPASS |
+ S3C_CISCCTRL_SCALEUP_H | S3C_CISCCTRL_SCALEUP_V |
+ S3C_CISCCTRL_MAIN_V_RATIO_MASK |
+ S3C_CISCCTRL_MAIN_H_RATIO_MASK |
+ S3C_CISCCTRL_CSCR2Y_WIDE |
+ S3C_CISCCTRL_CSCY2R_WIDE);
+
+#ifdef CONFIG_VIDEO_FIMC_RANGE_WIDE
+ cfg |= (S3C_CISCCTRL_CSCR2Y_WIDE | S3C_CISCCTRL_CSCY2R_WIDE);
+#endif
+
+ if (sc->bypass)
+ cfg |= S3C_CISCCTRL_SCALERBYPASS;
+
+ if (sc->scaleup_h)
+ cfg |= S3C_CISCCTRL_SCALEUP_H;
+
+ if (sc->scaleup_v)
+ cfg |= S3C_CISCCTRL_SCALEUP_V;
+
+ cfg |= S3C_CISCCTRL_MAINHORRATIO(sc->main_hratio);
+ cfg |= S3C_CISCCTRL_MAINVERRATIO(sc->main_vratio);
+
+ writel(cfg, ctrl->regs + S3C_CISCCTRL);
+
+ return 0;
+}
+
+int fimc43_hwset_scaler(struct fimc_control *ctrl, struct fimc_scaler *sc)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CISCCTRL);
+ u32 cfg_ext = readl(ctrl->regs + S3C_CIEXTEN);
+
+ cfg &= ~(S3C_CISCCTRL_SCALERBYPASS |
+ S3C_CISCCTRL_SCALEUP_H | S3C_CISCCTRL_SCALEUP_V |
+ S3C_CISCCTRL_MAIN_V_RATIO_MASK |
+ S3C_CISCCTRL_MAIN_H_RATIO_MASK |
+ S3C_CISCCTRL_CSCR2Y_WIDE |
+ S3C_CISCCTRL_CSCY2R_WIDE);
+
+#ifdef CONFIG_VIDEO_FIMC_RANGE_WIDE
+ cfg |= (S3C_CISCCTRL_CSCR2Y_WIDE | S3C_CISCCTRL_CSCY2R_WIDE);
+#endif
+
+ if (sc->bypass)
+ cfg |= S3C_CISCCTRL_SCALERBYPASS;
+
+ if (sc->scaleup_h)
+ cfg |= S3C_CISCCTRL_SCALEUP_H;
+
+ if (sc->scaleup_v)
+ cfg |= S3C_CISCCTRL_SCALEUP_V;
+
+ cfg |= S3C_CISCCTRL_MAINHORRATIO(sc->main_hratio);
+ cfg |= S3C_CISCCTRL_MAINVERRATIO(sc->main_vratio);
+
+ writel(cfg, ctrl->regs + S3C_CISCCTRL);
+
+ cfg_ext &= ~S3C_CIEXTEN_MAINHORRATIO_EXT_MASK;
+ cfg_ext &= ~S3C_CIEXTEN_MAINVERRATIO_EXT_MASK;
+
+ cfg_ext |= S3C_CIEXTEN_MAINHORRATIO_EXT(sc->main_hratio);
+ cfg_ext |= S3C_CIEXTEN_MAINVERRATIO_EXT(sc->main_vratio);
+
+ writel(cfg_ext, ctrl->regs + S3C_CIEXTEN);
+
+ return 0;
+}
+
+int fimc50_hwset_scaler(struct fimc_control *ctrl, struct fimc_scaler *sc)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CISCCTRL);
+ u32 cfg_ext = readl(ctrl->regs + S3C_CIEXTEN);
+
+ cfg &= ~(S3C_CISCCTRL_SCALERBYPASS |
+ S3C_CISCCTRL_SCALEUP_H | S3C_CISCCTRL_SCALEUP_V |
+ S3C_CISCCTRL_MAIN_V_RATIO_MASK |
+ S3C_CISCCTRL_MAIN_H_RATIO_MASK |
+ S3C_CISCCTRL_CSCR2Y_WIDE |
+ S3C_CISCCTRL_CSCY2R_WIDE);
+
+#ifdef CONFIG_VIDEO_FIMC_RANGE_WIDE
+ cfg |= (S3C_CISCCTRL_CSCR2Y_WIDE | S3C_CISCCTRL_CSCY2R_WIDE);
+#endif
+
+ if (sc->bypass)
+ cfg |= S3C_CISCCTRL_SCALERBYPASS;
+
+ if (sc->scaleup_h)
+ cfg |= S3C_CISCCTRL_SCALEUP_H;
+
+ if (sc->scaleup_v)
+ cfg |= S3C_CISCCTRL_SCALEUP_V;
+
+ cfg |= S3C_CISCCTRL_MAINHORRATIO((sc->main_hratio >> 6));
+ cfg |= S3C_CISCCTRL_MAINVERRATIO((sc->main_vratio >> 6));
+
+ writel(cfg, ctrl->regs + S3C_CISCCTRL);
+
+ cfg_ext &= ~S3C_CIEXTEN_MAINHORRATIO_EXT_MASK;
+ cfg_ext &= ~S3C_CIEXTEN_MAINVERRATIO_EXT_MASK;
+
+ cfg_ext |= S3C_CIEXTEN_MAINHORRATIO_EXT(sc->main_hratio);
+ cfg_ext |= S3C_CIEXTEN_MAINVERRATIO_EXT(sc->main_vratio);
+
+ writel(cfg_ext, ctrl->regs + S3C_CIEXTEN);
+
+ return 0;
+}
+
+int fimc_hwset_scaler(struct fimc_control *ctrl, struct fimc_scaler *sc)
+{
+ struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
+
+ switch (pdata->hw_ver) {
+ case 0x40:
+ fimc40_hwset_scaler(ctrl, sc);
+ break;
+ case 0x43:
+ case 0x45:
+ fimc43_hwset_scaler(ctrl, sc);
+ break;
+ case 0x50:
+ fimc50_hwset_scaler(ctrl, sc);
+ break;
+ default:
+ fimc43_hwset_scaler(ctrl, sc);
+ break;
+ }
+
+ return 0;
+}
+
+
+int fimc_hwset_scaler_bypass(struct fimc_control *ctrl)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CISCCTRL);
+
+ cfg |= S3C_CISCCTRL_SCALERBYPASS;
+
+ writel(cfg, ctrl->regs + S3C_CISCCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_enable_lcdfifo(struct fimc_control *ctrl)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CISCCTRL);
+
+ cfg |= S3C_CISCCTRL_LCDPATHEN_FIFO;
+ writel(cfg, ctrl->regs + S3C_CISCCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_disable_lcdfifo(struct fimc_control *ctrl)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CISCCTRL);
+
+ cfg &= ~S3C_CISCCTRL_LCDPATHEN_FIFO;
+ writel(cfg, ctrl->regs + S3C_CISCCTRL);
+
+ return 0;
+}
+
+int fimc_hwget_frame_count(struct fimc_control *ctrl)
+{
+ return S3C_CISTATUS_GET_FRAME_COUNT(readl(ctrl->regs + S3C_CISTATUS));
+}
+
+int fimc_hwget_frame_end(struct fimc_control *ctrl)
+{
+ unsigned long timeo = jiffies;
+ u32 cfg;
+
+ timeo += 20; /* waiting for 100ms */
+ while (time_before(jiffies, timeo)) {
+ cfg = readl(ctrl->regs + S3C_CISTATUS);
+
+ if (S3C_CISTATUS_GET_FRAME_END(cfg)) {
+ cfg &= ~S3C_CISTATUS_FRAMEEND;
+ writel(cfg, ctrl->regs + S3C_CISTATUS);
+ break;
+ }
+ cond_resched();
+ }
+
+ return 0;
+}
+
+int fimc_hwget_last_frame_end(struct fimc_control *ctrl)
+{
+ unsigned long timeo = jiffies;
+ u32 cfg;
+
+ timeo += 20; /* waiting for 100ms */
+ while (time_before(jiffies, timeo)) {
+ cfg = readl(ctrl->regs + S3C_CISTATUS);
+
+ if (S3C_CISTATUS_GET_LAST_CAPTURE_END(cfg)) {
+ cfg &= ~S3C_CISTATUS_LASTCAPTUREEND;
+ writel(cfg, ctrl->regs + S3C_CISTATUS);
+ break;
+ }
+ cond_resched();
+ }
+
+ return 0;
+}
+
+int fimc_hwset_start_scaler(struct fimc_control *ctrl)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CISCCTRL);
+
+ cfg |= S3C_CISCCTRL_SCALERSTART;
+ writel(cfg, ctrl->regs + S3C_CISCCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_stop_scaler(struct fimc_control *ctrl)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CISCCTRL);
+
+ cfg &= ~S3C_CISCCTRL_SCALERSTART;
+ writel(cfg, ctrl->regs + S3C_CISCCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_input_rgb(struct fimc_control *ctrl, u32 pixelformat)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CISCCTRL);
+ cfg &= ~S3C_CISCCTRL_INRGB_FMT_RGB_MASK;
+
+ if (pixelformat == V4L2_PIX_FMT_RGB32)
+ cfg |= S3C_CISCCTRL_INRGB_FMT_RGB888;
+ else if (pixelformat == V4L2_PIX_FMT_RGB565)
+ cfg |= S3C_CISCCTRL_INRGB_FMT_RGB565;
+
+ writel(cfg, ctrl->regs + S3C_CISCCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_intput_field(struct fimc_control *ctrl, enum v4l2_field field)
+{
+ struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
+ u32 cfg;
+
+ if (pdata->hw_ver == 0x40)
+ return 0;
+
+ cfg = readl(ctrl->regs + S3C_MSCTRL);
+ cfg &= ~S3C_MSCTRL_FIELD_MASK;
+
+ if (field == V4L2_FIELD_NONE)
+ cfg |= S3C_MSCTRL_FIELD_NORMAL;
+ else if (field == V4L2_FIELD_INTERLACED_TB)
+ cfg |= S3C_MSCTRL_FIELD_WEAVE;
+
+ writel(cfg, ctrl->regs + S3C_MSCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_output_rgb(struct fimc_control *ctrl, u32 pixelformat)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CISCCTRL);
+ cfg &= ~S3C_CISCCTRL_OUTRGB_FMT_RGB_MASK;
+
+ if (pixelformat == V4L2_PIX_FMT_RGB32)
+ cfg |= S3C_CISCCTRL_OUTRGB_FMT_RGB888;
+ else if (pixelformat == V4L2_PIX_FMT_RGB565)
+ cfg |= S3C_CISCCTRL_OUTRGB_FMT_RGB565;
+
+ writel(cfg, ctrl->regs + S3C_CISCCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_ext_rgb(struct fimc_control *ctrl, int enable)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CISCCTRL);
+ cfg &= ~S3C_CISCCTRL_EXTRGB_EXTENSION;
+
+ if (enable)
+ cfg |= S3C_CISCCTRL_EXTRGB_EXTENSION;
+
+ writel(cfg, ctrl->regs + S3C_CISCCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_enable_capture(struct fimc_control *ctrl, u32 bypass)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CIIMGCPT);
+ cfg &= ~S3C_CIIMGCPT_IMGCPTEN_SC;
+ cfg |= S3C_CIIMGCPT_IMGCPTEN;
+
+ if (!bypass)
+ cfg |= S3C_CIIMGCPT_IMGCPTEN_SC;
+
+ writel(cfg, ctrl->regs + S3C_CIIMGCPT);
+
+ return 0;
+}
+
+int fimc_hwset_disable_capture(struct fimc_control *ctrl)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CIIMGCPT);
+
+ cfg &= ~(S3C_CIIMGCPT_IMGCPTEN_SC | S3C_CIIMGCPT_IMGCPTEN);
+
+ writel(cfg, ctrl->regs + S3C_CIIMGCPT);
+
+ return 0;
+}
+
+int fimc_hwset_input_address(struct fimc_control *ctrl, dma_addr_t *base)
+{
+ writel(base[FIMC_ADDR_Y], ctrl->regs + S3C_CIIYSA0);
+ writel(base[FIMC_ADDR_CB], ctrl->regs + S3C_CIICBSA0);
+ writel(base[FIMC_ADDR_CR], ctrl->regs + S3C_CIICRSA0);
+
+ return 0;
+}
+
+int fimc_hwset_enable_autoload(struct fimc_control *ctrl)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CIREAL_ISIZE);
+
+ cfg |= S3C_CIREAL_ISIZE_AUTOLOAD_ENABLE;
+
+ writel(cfg, ctrl->regs + S3C_CIREAL_ISIZE);
+
+ return 0;
+}
+
+int fimc_hwset_disable_autoload(struct fimc_control *ctrl)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CIREAL_ISIZE);
+
+ cfg &= ~S3C_CIREAL_ISIZE_AUTOLOAD_ENABLE;
+
+ writel(cfg, ctrl->regs + S3C_CIREAL_ISIZE);
+
+ return 0;
+}
+
+int fimc_hwset_real_input_size(struct fimc_control *ctrl, u32 width, u32 height)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CIREAL_ISIZE);
+ cfg &= ~(S3C_CIREAL_ISIZE_HEIGHT_MASK | S3C_CIREAL_ISIZE_WIDTH_MASK);
+
+ cfg |= S3C_CIREAL_ISIZE_WIDTH(width);
+ cfg |= S3C_CIREAL_ISIZE_HEIGHT(height);
+
+ writel(cfg, ctrl->regs + S3C_CIREAL_ISIZE);
+
+ return 0;
+}
+
+int fimc_hwset_addr_change_enable(struct fimc_control *ctrl)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CIREAL_ISIZE);
+
+ cfg &= ~S3C_CIREAL_ISIZE_ADDR_CH_DISABLE;
+
+ writel(cfg, ctrl->regs + S3C_CIREAL_ISIZE);
+
+ return 0;
+}
+
+int fimc_hwset_addr_change_disable(struct fimc_control *ctrl)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CIREAL_ISIZE);
+
+ cfg |= S3C_CIREAL_ISIZE_ADDR_CH_DISABLE;
+
+ writel(cfg, ctrl->regs + S3C_CIREAL_ISIZE);
+
+ return 0;
+}
+
+int fimc_hwset_input_burst_cnt(struct fimc_control *ctrl, u32 cnt)
+{
+ u32 cfg = readl(ctrl->regs + S3C_MSCTRL);
+ cfg &= ~S3C_MSCTRL_BURST_CNT_MASK;
+
+ if (cnt > 4)
+ cnt = 4;
+ else if (cnt == 0)
+ cnt = 4;
+
+ cfg |= S3C_MSCTRL_SUCCESSIVE_COUNT(cnt);
+ writel(cfg, ctrl->regs + S3C_MSCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_input_colorspace(struct fimc_control *ctrl, u32 pixelformat)
+{
+ u32 cfg = readl(ctrl->regs + S3C_MSCTRL);
+ cfg &= ~S3C_MSCTRL_INFORMAT_RGB;
+
+ /* Color format setting */
+ switch (pixelformat) {
+ case V4L2_PIX_FMT_YUV420: /* fall through */
+ case V4L2_PIX_FMT_NV12: /* fall through */
+ case V4L2_PIX_FMT_NV21: /* fall through */
+ case V4L2_PIX_FMT_NV12T:
+ cfg |= S3C_MSCTRL_INFORMAT_YCBCR420;
+ break;
+ case V4L2_PIX_FMT_YUYV: /* fall through */
+ case V4L2_PIX_FMT_UYVY: /* fall through */
+ case V4L2_PIX_FMT_YVYU: /* fall through */
+ case V4L2_PIX_FMT_VYUY:
+ cfg |= S3C_MSCTRL_INFORMAT_YCBCR422_1PLANE;
+ break;
+ case V4L2_PIX_FMT_NV16: /* fall through */
+ case V4L2_PIX_FMT_NV61:
+ cfg |= S3C_MSCTRL_INFORMAT_YCBCR422;
+ break;
+ case V4L2_PIX_FMT_RGB565: /* fall through */
+ case V4L2_PIX_FMT_RGB32:
+ cfg |= S3C_MSCTRL_INFORMAT_RGB;
+ break;
+ default:
+ fimc_err("%s: Invalid pixelformt : %d\n",
+ __func__, pixelformat);
+ return -EINVAL;
+ }
+
+ writel(cfg, ctrl->regs + S3C_MSCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_input_yuv(struct fimc_control *ctrl, u32 pixelformat)
+{
+ u32 cfg = readl(ctrl->regs + S3C_MSCTRL);
+ cfg &= ~(S3C_MSCTRL_ORDER2P_SHIFT_MASK | S3C_MSCTRL_C_INT_IN_2PLANE |
+ S3C_MSCTRL_ORDER422_YCBYCR);
+
+ switch (pixelformat) {
+ case V4L2_PIX_FMT_YUV420:
+ cfg |= S3C_MSCTRL_C_INT_IN_3PLANE;
+ break;
+ case V4L2_PIX_FMT_YUYV: /* fall through */
+ cfg |= S3C_MSCTRL_ORDER422_YCBYCR;
+ break;
+ case V4L2_PIX_FMT_UYVY:
+ cfg |= S3C_MSCTRL_ORDER422_CBYCRY;
+ break;
+ case V4L2_PIX_FMT_YVYU:
+ cfg |= S3C_MSCTRL_ORDER422_YCRYCB;
+ break;
+ case V4L2_PIX_FMT_VYUY:
+ cfg |= S3C_MSCTRL_ORDER422_CRYCBY;
+ break;
+ case V4L2_PIX_FMT_NV12: /* fall through */
+ case V4L2_PIX_FMT_NV12T:
+ cfg |= S3C_MSCTRL_ORDER2P_LSB_CBCR;
+ cfg |= S3C_MSCTRL_C_INT_IN_2PLANE;
+ break;
+ case V4L2_PIX_FMT_NV21:
+ cfg |= S3C_MSCTRL_ORDER2P_LSB_CRCB;
+ cfg |= S3C_MSCTRL_C_INT_IN_2PLANE;
+ break;
+ case V4L2_PIX_FMT_NV16:
+ cfg |= S3C_MSCTRL_ORDER2P_LSB_CBCR;
+ cfg |= S3C_MSCTRL_C_INT_IN_2PLANE;
+ break;
+ case V4L2_PIX_FMT_NV61:
+ cfg |= S3C_MSCTRL_ORDER2P_LSB_CRCB;
+ cfg |= S3C_MSCTRL_C_INT_IN_2PLANE;
+ break;
+ case V4L2_PIX_FMT_RGB565: /* fall through */
+ case V4L2_PIX_FMT_RGB32:
+ break;
+ default:
+ fimc_err("%s: Invalid pixelformt : %d\n",
+ __func__, pixelformat);
+ }
+
+ writel(cfg, ctrl->regs + S3C_MSCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_input_flip(struct fimc_control *ctrl, u32 rot, u32 flip)
+{
+ u32 cfg, val;
+
+ cfg = readl(ctrl->regs + S3C_MSCTRL);
+ cfg &= ~(S3C_MSCTRL_FLIP_X_MIRROR | S3C_MSCTRL_FLIP_Y_MIRROR);
+ val = fimc_mapping_rot_flip(rot, flip);
+
+ if (val & FIMC_XFLIP)
+ cfg |= S3C_MSCTRL_FLIP_X_MIRROR;
+
+ if (val & FIMC_YFLIP)
+ cfg |= S3C_MSCTRL_FLIP_Y_MIRROR;
+
+ writel(cfg, ctrl->regs + S3C_MSCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_input_source(struct fimc_control *ctrl, enum fimc_input path)
+{
+ u32 cfg = readl(ctrl->regs + S3C_MSCTRL);
+ cfg &= ~S3C_MSCTRL_INPUT_MASK;
+
+ if (path == FIMC_SRC_MSDMA)
+ cfg |= S3C_MSCTRL_INPUT_MEMORY;
+ else if (path == FIMC_SRC_CAM)
+ cfg |= S3C_MSCTRL_INPUT_EXTCAM;
+
+ writel(cfg, ctrl->regs + S3C_MSCTRL);
+
+ return 0;
+
+}
+
+int fimc_hwset_start_input_dma(struct fimc_control *ctrl)
+{
+ u32 cfg = readl(ctrl->regs + S3C_MSCTRL);
+ cfg |= S3C_MSCTRL_ENVID;
+
+ writel(cfg, ctrl->regs + S3C_MSCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_stop_input_dma(struct fimc_control *ctrl)
+{
+ u32 cfg = readl(ctrl->regs + S3C_MSCTRL);
+ cfg &= ~S3C_MSCTRL_ENVID;
+
+ writel(cfg, ctrl->regs + S3C_MSCTRL);
+
+ return 0;
+}
+
+void fimc_wait_stop_processing(struct fimc_control *ctrl)
+{
+ fimc_hwget_frame_end(ctrl);
+ fimc_hwget_last_frame_end(ctrl);
+}
+
+void fimc_hwset_stop_processing(struct fimc_control *ctrl)
+{
+ fimc_wait_stop_processing(ctrl);
+
+ fimc_hwset_stop_scaler(ctrl);
+ fimc_hwset_disable_capture(ctrl);
+ fimc_hwset_stop_input_dma(ctrl);
+
+ /* We need to wait for sometime after processing is stopped.
+ * This is required for obtaining clean buffer for DMA processing. */
+ fimc_wait_stop_processing(ctrl);
+}
+
+int fimc40_hwset_output_offset(struct fimc_control *ctrl, u32 pixelformat,
+ struct v4l2_rect *bounds,
+ struct v4l2_rect *crop)
+{
+ u32 cfg_y = 0, cfg_cb = 0, cfg_cr = 0;
+
+ if (!crop->left && !crop->top && (bounds->width == crop->width) &&
+ (bounds->height == crop->height))
+ return -EINVAL;
+
+ fimc_dbg("%s: left: %d, top: %d, width: %d, height: %d\n",
+ __func__, crop->left, crop->top, crop->width, crop->height);
+
+ switch (pixelformat) {
+ /* 1 plane, 32 bits per pixel */
+ case V4L2_PIX_FMT_RGB32:
+ cfg_y |= S3C_CIOYOFF_HORIZONTAL(crop->left * 4);
+ cfg_y |= S3C_CIOYOFF_VERTICAL(crop->top);
+ break;
+
+ /* 1 plane, 16 bits per pixel */
+ case V4L2_PIX_FMT_YUYV: /* fall through */
+ case V4L2_PIX_FMT_UYVY: /* fall through */
+ case V4L2_PIX_FMT_VYUY: /* fall through */
+ case V4L2_PIX_FMT_YVYU: /* fall through */
+ case V4L2_PIX_FMT_RGB565:
+ cfg_y |= S3C_CIOYOFF_HORIZONTAL(crop->left * 2);
+ cfg_y |= S3C_CIOYOFF_VERTICAL(crop->top);
+ break;
+
+ /* 2 planes, 16 bits per pixel */
+ case V4L2_PIX_FMT_NV16: /* fall through */
+ case V4L2_PIX_FMT_NV61:
+ cfg_y |= S3C_CIOYOFF_HORIZONTAL(crop->left);
+ cfg_y |= S3C_CIOYOFF_VERTICAL(crop->top);
+ cfg_cb |= S3C_CIOCBOFF_HORIZONTAL(crop->left / 2);
+ cfg_cb |= S3C_CIOCBOFF_VERTICAL(crop->top / 2);
+ break;
+
+ /* 2 planes, 12 bits per pixel */
+ case V4L2_PIX_FMT_NV12: /* fall through */
+ case V4L2_PIX_FMT_NV12T: /* fall through */
+ case V4L2_PIX_FMT_NV21:
+ cfg_y |= S3C_CIOYOFF_HORIZONTAL(crop->left);
+ cfg_y |= S3C_CIOYOFF_VERTICAL(crop->top);
+ cfg_cb |= S3C_CIOCBOFF_HORIZONTAL(crop->left / 4);
+ cfg_cb |= S3C_CIOCBOFF_VERTICAL(crop->top / 4);
+ break;
+
+ /* 3 planes, 16 bits per pixel */
+ case V4L2_PIX_FMT_YUV422P:
+ cfg_y |= S3C_CIOYOFF_HORIZONTAL(crop->left);
+ cfg_y |= S3C_CIOYOFF_VERTICAL(crop->top);
+ cfg_cb |= S3C_CIOCBOFF_HORIZONTAL(crop->left / 2);
+ cfg_cb |= S3C_CIOCBOFF_VERTICAL(crop->top / 2);
+ cfg_cr |= S3C_CIOCROFF_HORIZONTAL(crop->left / 2);
+ cfg_cr |= S3C_CIOCROFF_VERTICAL(crop->top / 2);
+ break;
+
+ /* 3 planes, 12 bits per pixel */
+ case V4L2_PIX_FMT_YUV420:
+ cfg_y |= S3C_CIOYOFF_HORIZONTAL(crop->left);
+ cfg_y |= S3C_CIOYOFF_VERTICAL(crop->top);
+ cfg_cb |= S3C_CIOCBOFF_HORIZONTAL(crop->left / 4);
+ cfg_cb |= S3C_CIOCBOFF_VERTICAL(crop->top / 4);
+ cfg_cr |= S3C_CIOCROFF_HORIZONTAL(crop->left / 4);
+ cfg_cr |= S3C_CIOCROFF_VERTICAL(crop->top / 4);
+ break;
+
+ default:
+ break;
+ }
+
+ writel(cfg_y, ctrl->regs + S3C_CIOYOFF);
+ writel(cfg_cb, ctrl->regs + S3C_CIOCBOFF);
+ writel(cfg_cr, ctrl->regs + S3C_CIOCROFF);
+
+ return 0;
+}
+
+int fimc50_hwset_output_offset(struct fimc_control *ctrl, u32 pixelformat,
+ struct v4l2_rect *bounds,
+ struct v4l2_rect *crop)
+{
+ u32 cfg_y = 0, cfg_cb = 0, cfg_cr = 0;
+
+ if (!crop->left && !crop->top && (bounds->width == crop->width) &&
+ (bounds->height == crop->height))
+ return -EINVAL;
+
+ fimc_dbg("%s: left: %d, top: %d, width: %d, height: %d\n",
+ __func__, crop->left, crop->top, crop->width, crop->height);
+
+ switch (pixelformat) {
+ /* 1 plane, 32 bits per pixel */
+ case V4L2_PIX_FMT_RGB32:
+ cfg_y |= S3C_CIOYOFF_HORIZONTAL(crop->left);
+ cfg_y |= S3C_CIOYOFF_VERTICAL(crop->top);
+ break;
+
+ /* 1 plane, 16 bits per pixel */
+ case V4L2_PIX_FMT_YUYV: /* fall through */
+ case V4L2_PIX_FMT_UYVY: /* fall through */
+ case V4L2_PIX_FMT_VYUY: /* fall through */
+ case V4L2_PIX_FMT_YVYU: /* fall through */
+ case V4L2_PIX_FMT_RGB565:
+ cfg_y |= S3C_CIOYOFF_HORIZONTAL(crop->left);
+ cfg_y |= S3C_CIOYOFF_VERTICAL(crop->top);
+ break;
+
+ /* 2 planes, 16 bits per pixel */
+ case V4L2_PIX_FMT_NV16: /* fall through */
+ case V4L2_PIX_FMT_NV61:
+ cfg_y |= S3C_CIOYOFF_HORIZONTAL(crop->left);
+ cfg_y |= S3C_CIOYOFF_VERTICAL(crop->top);
+ cfg_cb |= S3C_CIOCBOFF_HORIZONTAL(crop->left);
+ cfg_cb |= S3C_CIOCBOFF_VERTICAL(crop->top);
+ break;
+
+ /* 2 planes, 12 bits per pixel */
+ case V4L2_PIX_FMT_NV12: /* fall through */
+ case V4L2_PIX_FMT_NV12T: /* fall through */
+ case V4L2_PIX_FMT_NV21:
+ cfg_y |= S3C_CIOYOFF_HORIZONTAL(crop->left);
+ cfg_y |= S3C_CIOYOFF_VERTICAL(crop->top);
+ cfg_cb |= S3C_CIOCBOFF_HORIZONTAL(crop->left);
+ cfg_cb |= S3C_CIOCBOFF_VERTICAL(crop->top);
+ break;
+
+ /* 3 planes, 16 bits per pixel */
+ case V4L2_PIX_FMT_YUV422P:
+ cfg_y |= S3C_CIOYOFF_HORIZONTAL(crop->left);
+ cfg_y |= S3C_CIOYOFF_VERTICAL(crop->top);
+ cfg_cb |= S3C_CIOCBOFF_HORIZONTAL(crop->left);
+ cfg_cb |= S3C_CIOCBOFF_VERTICAL(crop->top);
+ cfg_cr |= S3C_CIOCROFF_HORIZONTAL(crop->left);
+ cfg_cr |= S3C_CIOCROFF_VERTICAL(crop->top);
+ break;
+
+ /* 3 planes, 12 bits per pixel */
+ case V4L2_PIX_FMT_YUV420:
+ cfg_y |= S3C_CIOYOFF_HORIZONTAL(crop->left);
+ cfg_y |= S3C_CIOYOFF_VERTICAL(crop->top);
+ cfg_cb |= S3C_CIOCBOFF_HORIZONTAL(crop->left);
+ cfg_cb |= S3C_CIOCBOFF_VERTICAL(crop->top);
+ cfg_cr |= S3C_CIOCROFF_HORIZONTAL(crop->left);
+ cfg_cr |= S3C_CIOCROFF_VERTICAL(crop->top);
+ break;
+
+ default:
+ break;
+ }
+
+ writel(cfg_y, ctrl->regs + S3C_CIOYOFF);
+ writel(cfg_cb, ctrl->regs + S3C_CIOCBOFF);
+ writel(cfg_cr, ctrl->regs + S3C_CIOCROFF);
+
+ return 0;
+}
+
+int fimc_hwset_output_offset(struct fimc_control *ctrl, u32 pixelformat,
+ struct v4l2_rect *bounds,
+ struct v4l2_rect *crop)
+{
+ struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
+
+ if (pdata->hw_ver == 0x50 || pdata->hw_ver == 0x45)
+ fimc50_hwset_output_offset(ctrl, pixelformat, bounds, crop);
+ else
+ fimc40_hwset_output_offset(ctrl, pixelformat, bounds, crop);
+
+ return 0;
+}
+
+int fimc40_hwset_input_offset(struct fimc_control *ctrl, u32 pixelformat,
+ struct v4l2_rect *bounds,
+ struct v4l2_rect *crop)
+{
+ u32 cfg_y = 0, cfg_cb = 0;
+
+ if (crop->left || crop->top ||
+ (bounds->width != crop->width) ||
+ (bounds->height != crop->height)) {
+ switch (pixelformat) {
+ case V4L2_PIX_FMT_YUYV: /* fall through */
+ case V4L2_PIX_FMT_RGB565:
+ cfg_y |= S3C_CIIYOFF_HORIZONTAL(crop->left * 2);
+ cfg_y |= S3C_CIIYOFF_VERTICAL(crop->top);
+ break;
+ case V4L2_PIX_FMT_RGB32:
+ cfg_y |= S3C_CIIYOFF_HORIZONTAL(crop->left * 4);
+ cfg_y |= S3C_CIIYOFF_VERTICAL(crop->top);
+ break;
+ case V4L2_PIX_FMT_NV12: /* fall through */
+ case V4L2_PIX_FMT_NV12T:
+ cfg_y |= S3C_CIIYOFF_HORIZONTAL(crop->left);
+ cfg_y |= S3C_CIIYOFF_VERTICAL(crop->top);
+ cfg_cb |= S3C_CIICBOFF_HORIZONTAL(crop->left);
+ cfg_cb |= S3C_CIICBOFF_VERTICAL(crop->top / 2);
+
+ break;
+ default:
+ fimc_err("%s: Invalid pixelformt : %d\n",
+ __func__, pixelformat);
+ }
+ }
+
+ writel(cfg_y, ctrl->regs + S3C_CIIYOFF);
+ writel(cfg_cb, ctrl->regs + S3C_CIICBOFF);
+
+ return 0;
+}
+
+int fimc50_hwset_input_offset(struct fimc_control *ctrl, u32 pixelformat,
+ struct v4l2_rect *bounds,
+ struct v4l2_rect *crop)
+{
+ u32 cfg_y = 0, cfg_cb = 0, cfg_cr = 0;
+
+ if (crop->left || crop->top ||
+ (bounds->width != crop->width) ||
+ (bounds->height != crop->height)) {
+ switch (pixelformat) {
+ case V4L2_PIX_FMT_YUYV: /* fall through */
+ case V4L2_PIX_FMT_UYVY: /* fall through */
+ case V4L2_PIX_FMT_YVYU: /* fall through */
+ case V4L2_PIX_FMT_VYUY: /* fall through */
+ case V4L2_PIX_FMT_RGB565:
+ cfg_y |= S3C_CIIYOFF_HORIZONTAL(crop->left);
+ cfg_y |= S3C_CIIYOFF_VERTICAL(crop->top);
+ break;
+ case V4L2_PIX_FMT_RGB32:
+ cfg_y |= S3C_CIIYOFF_HORIZONTAL(crop->left);
+ cfg_y |= S3C_CIIYOFF_VERTICAL(crop->top);
+ break;
+ case V4L2_PIX_FMT_NV12: /* fall through*/
+ case V4L2_PIX_FMT_NV21: /* fall through*/
+ case V4L2_PIX_FMT_NV12T:
+ cfg_y |= S3C_CIIYOFF_HORIZONTAL(crop->left);
+ cfg_y |= S3C_CIIYOFF_VERTICAL(crop->top);
+ cfg_cb |= S3C_CIICBOFF_HORIZONTAL(crop->left);
+ cfg_cb |= S3C_CIICBOFF_VERTICAL(crop->top);
+ break;
+ case V4L2_PIX_FMT_NV16: /* fall through */
+ case V4L2_PIX_FMT_NV61:
+ cfg_y |= S3C_CIIYOFF_HORIZONTAL(crop->left);
+ cfg_y |= S3C_CIIYOFF_VERTICAL(crop->top);
+ cfg_cb |= S3C_CIICBOFF_HORIZONTAL(crop->left);
+ cfg_cb |= S3C_CIICBOFF_VERTICAL(crop->top);
+ break;
+ case V4L2_PIX_FMT_YUV420:
+ cfg_y |= S3C_CIIYOFF_HORIZONTAL(crop->left);
+ cfg_y |= S3C_CIIYOFF_VERTICAL(crop->top);
+ cfg_cb |= S3C_CIICBOFF_HORIZONTAL(crop->left);
+ cfg_cb |= S3C_CIICBOFF_VERTICAL(crop->top);
+ cfg_cr |= S3C_CIICROFF_HORIZONTAL(crop->left);
+ cfg_cr |= S3C_CIICROFF_VERTICAL(crop->top);
+ break;
+ default:
+ fimc_err("%s: Invalid pixelformt : %d\n",
+ __func__, pixelformat);
+ }
+ }
+
+ writel(cfg_y, ctrl->regs + S3C_CIIYOFF);
+ writel(cfg_cb, ctrl->regs + S3C_CIICBOFF);
+ writel(cfg_cr, ctrl->regs + S3C_CIICROFF);
+
+ return 0;
+}
+
+int fimc_hwset_input_offset(struct fimc_control *ctrl, u32 pixelformat,
+ struct v4l2_rect *bounds,
+ struct v4l2_rect *crop)
+{
+ struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
+
+ if (pdata->hw_ver == 0x50)
+ fimc50_hwset_input_offset(ctrl, pixelformat, bounds, crop);
+ else
+ fimc40_hwset_input_offset(ctrl, pixelformat, bounds, crop);
+
+ return 0;
+}
+
+int fimc_hwset_org_input_size(struct fimc_control *ctrl, u32 width, u32 height)
+{
+ u32 cfg = 0;
+
+ cfg |= S3C_ORGISIZE_HORIZONTAL(width);
+ cfg |= S3C_ORGISIZE_VERTICAL(height);
+
+ writel(cfg, ctrl->regs + S3C_ORGISIZE);
+
+ return 0;
+}
+
+int fimc_hwset_org_output_size(struct fimc_control *ctrl, u32 width, u32 height)
+{
+ struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
+ u32 cfg = 0;
+
+ cfg |= S3C_ORGOSIZE_HORIZONTAL(width);
+ cfg |= S3C_ORGOSIZE_VERTICAL(height);
+
+ writel(cfg, ctrl->regs + S3C_ORGOSIZE);
+
+ if (pdata->hw_ver != 0x40) {
+ cfg = readl(ctrl->regs + S3C_CIGCTRL);
+ cfg &= ~S3C_CIGCTRL_CSC_MASK;
+
+ if (width >= FIMC_HD_WIDTH)
+ cfg |= S3C_CIGCTRL_CSC_ITU709;
+ else
+ cfg |= S3C_CIGCTRL_CSC_ITU601;
+
+ writel(cfg, ctrl->regs + S3C_CIGCTRL);
+ }
+
+ return 0;
+}
+
+int fimc_hwset_ext_output_size(struct fimc_control *ctrl, u32 width, u32 height)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CIEXTEN);
+
+ cfg &= ~S3C_CIEXTEN_TARGETH_EXT_MASK;
+ cfg &= ~S3C_CIEXTEN_TARGETV_EXT_MASK;
+ cfg |= S3C_CIEXTEN_TARGETH_EXT(width);
+ cfg |= S3C_CIEXTEN_TARGETV_EXT(height);
+
+ writel(cfg, ctrl->regs + S3C_CIEXTEN);
+
+ return 0;
+}
+
+int fimc_hwset_input_addr_style(struct fimc_control *ctrl, u32 pixelformat)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CIDMAPARAM);
+ cfg &= ~S3C_CIDMAPARAM_R_MODE_MASK;
+
+ if (pixelformat == V4L2_PIX_FMT_NV12T)
+ cfg |= S3C_CIDMAPARAM_R_MODE_64X32;
+ else
+ cfg |= S3C_CIDMAPARAM_R_MODE_LINEAR;
+
+ writel(cfg, ctrl->regs + S3C_CIDMAPARAM);
+
+ return 0;
+}
+
+int fimc_hwset_output_addr_style(struct fimc_control *ctrl, u32 pixelformat)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CIDMAPARAM);
+ cfg &= ~S3C_CIDMAPARAM_W_MODE_MASK;
+
+ if (pixelformat == V4L2_PIX_FMT_NV12T)
+ cfg |= S3C_CIDMAPARAM_W_MODE_64X32;
+ else
+ cfg |= S3C_CIDMAPARAM_W_MODE_LINEAR;
+
+ writel(cfg, ctrl->regs + S3C_CIDMAPARAM);
+
+ return 0;
+}
+
+int fimc_hw_wait_winoff(struct fimc_control *ctrl)
+{
+ struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
+ u32 cfg = readl(ctrl->regs + S3C_CISTATUS);
+ u32 status = S3C_CISTATUS_GET_LCD_STATUS(cfg);
+ int i = FIMC_FIFOOFF_CNT;
+
+ if (pdata->hw_ver == 0x40)
+ return 0;
+
+ while (status && i--) {
+ cfg = readl(ctrl->regs + S3C_CISTATUS);
+ status = S3C_CISTATUS_GET_LCD_STATUS(cfg);
+ }
+
+ if (i < 1) {
+ fimc_err("Fail : %s\n", __func__);
+ return -EBUSY;
+ } else
+ return 0;
+}
+
+int fimc_hw_wait_stop_input_dma(struct fimc_control *ctrl)
+{
+ struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
+ u32 cfg = readl(ctrl->regs + S3C_MSCTRL);
+ u32 status = S3C_MSCTRL_GET_INDMA_STATUS(cfg);
+ int i = FIMC_FIFOOFF_CNT, j = FIMC_FIFOOFF_CNT;
+
+ if (pdata->hw_ver == 0x40)
+ return 0;
+
+ while (status && i--) {
+ cfg = readl(ctrl->regs + S3C_MSCTRL);
+ status = S3C_MSCTRL_GET_INDMA_STATUS(cfg);
+ }
+
+ cfg = readl(ctrl->regs + S3C_CISTATUS);
+ status = S3C_CISTATUS_GET_ENVID_STATUS(cfg);
+ while (status && j--) {
+ cfg = readl(ctrl->regs + S3C_CISTATUS);
+ status = S3C_CISTATUS_GET_ENVID_STATUS(cfg);
+ }
+
+ if ((i < 1) || (j < 1)) {
+ fimc_err("Fail : %s\n", __func__);
+ return -EBUSY;
+ } else {
+ return 0;
+ }
+}
+
+int fimc_hwset_input_lineskip(struct fimc_control *ctrl)
+{
+ struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
+ u32 cfg = 0;
+
+ if (pdata->hw_ver == 0x40)
+ return 0;
+
+ cfg = S3C_CIILINESKIP(ctrl->sc.skipline);
+
+ writel(cfg, ctrl->regs + S3C_CIILINESKIP_Y);
+ writel(cfg, ctrl->regs + S3C_CIILINESKIP_CB);
+ writel(cfg, ctrl->regs + S3C_CIILINESKIP_CR);
+
+ return 0;
+}
+
+int fimc_hw_reset_camera(struct fimc_control *ctrl)
+{
+ return 0;
+}
diff --git a/drivers/media/video/samsung/fimc/fimc_v4l2.c b/drivers/media/video/samsung/fimc/fimc_v4l2.c
new file mode 100644
index 0000000..3632ded
--- /dev/null
+++ b/drivers/media/video/samsung/fimc/fimc_v4l2.c
@@ -0,0 +1,296 @@
+/* linux/drivers/media/video/samsung/fimc/fimc_v4l2.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * V4L2 interface support file for Samsung Camera Interface (FIMC) driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_samsung.h>
+#include <media/v4l2-ioctl.h>
+#include <plat/fimc.h>
+#include <linux/clk.h>
+
+#include "fimc.h"
+
+static int fimc_querycap(struct file *filp, void *fh,
+ struct v4l2_capability *cap)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+
+ fimc_info1("%s: called\n", __func__);
+
+ strcpy(cap->driver, "Samsung FIMC Driver");
+ strlcpy(cap->card, ctrl->vd->name, sizeof(cap->card));
+ sprintf(cap->bus_info, "FIMC AHB-bus");
+
+ cap->version = 0;
+ cap->capabilities = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT |
+ V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_STREAMING);
+
+ return 0;
+}
+
+static int fimc_reqbufs(struct file *filp, void *fh,
+ struct v4l2_requestbuffers *b)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ret = -1;
+
+ if (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ ret = fimc_reqbufs_capture(fh, b);
+ } else if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+ ret = fimc_reqbufs_output(fh, b);
+ } else {
+ fimc_err("V4L2_BUF_TYPE_VIDEO_CAPTURE and "
+ "V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int fimc_querybuf(struct file *filp, void *fh, struct v4l2_buffer *b)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ret = -1;
+
+ if (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ ret = fimc_querybuf_capture(fh, b);
+ } else if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+ ret = fimc_querybuf_output(fh, b);
+ } else {
+ fimc_err("V4L2_BUF_TYPE_VIDEO_CAPTURE and "
+ "V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int fimc_g_ctrl(struct file *filp, void *fh, struct v4l2_control *c)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ret = -1;
+
+ if (ctrl->cap != NULL) {
+ ret = fimc_g_ctrl_capture(fh, c);
+ } else if (ctrl->out != NULL) {
+ ret = fimc_g_ctrl_output(fh, c);
+ } else {
+ fimc_err("%s: Invalid case\n", __func__);
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static int fimc_s_ctrl(struct file *filp, void *fh, struct v4l2_control *c)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ret = -1;
+
+ if (ctrl->cap != NULL) {
+ ret = fimc_s_ctrl_capture(fh, c);
+ } else if (ctrl->out != NULL) {
+ ret = fimc_s_ctrl_output(filp, fh, c);
+ } else {
+ fimc_err("%s: Invalid case\n", __func__);
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static int fimc_s_ext_ctrls(struct file *filp, void *fh,
+ struct v4l2_ext_controls *c)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ret = -1;
+
+ if (ctrl->cap != NULL) {
+ ret = fimc_s_ext_ctrls_capture(fh, c);
+ } else {
+ fimc_err("%s: Invalid case\n", __func__);
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static int fimc_cropcap(struct file *filp, void *fh, struct v4l2_cropcap *a)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ret = -1;
+
+ if (a->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ ret = fimc_cropcap_capture(fh, a);
+ } else if (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+ ret = fimc_cropcap_output(fh, a);
+ } else {
+ fimc_err("V4L2_BUF_TYPE_VIDEO_CAPTURE and "
+ "V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int fimc_g_crop(struct file *filp, void *fh, struct v4l2_crop *a)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ret = -1;
+
+ if (a->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ ret = fimc_g_crop_capture(fh, a);
+ } else if (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+ ret = fimc_g_crop_output(fh, a);
+ } else {
+ fimc_err("V4L2_BUF_TYPE_VIDEO_CAPTURE and "
+ "V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int fimc_s_crop(struct file *filp, void *fh, struct v4l2_crop *a)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ret = -1;
+
+ if (a->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ ret = fimc_s_crop_capture(fh, a);
+ } else if (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+ ret = fimc_s_crop_output(fh, a);
+ } else {
+ fimc_err("V4L2_BUF_TYPE_VIDEO_CAPTURE and "
+ "V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int fimc_streamon(struct file *filp, void *fh, enum v4l2_buf_type i)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ struct s3c_platform_fimc *pdata;
+ int ret = -1;
+
+ pdata = to_fimc_plat(ctrl->dev);
+
+ if (i == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ ret = fimc_streamon_capture(fh);
+ } else if (i == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+ ret = fimc_streamon_output(fh);
+ } else {
+ fimc_err("V4L2_BUF_TYPE_VIDEO_CAPTURE and "
+ "V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int fimc_streamoff(struct file *filp, void *fh, enum v4l2_buf_type i)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ struct s3c_platform_fimc *pdata;
+ int ret = -1;
+
+ pdata = to_fimc_plat(ctrl->dev);
+
+ if (i == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ ret = fimc_streamoff_capture(fh);
+ } else if (i == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+ ret = fimc_streamoff_output(fh);
+ } else {
+ fimc_err("V4L2_BUF_TYPE_VIDEO_CAPTURE and "
+ "V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int fimc_qbuf(struct file *filp, void *fh, struct v4l2_buffer *b)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ret = -1;
+
+ if (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ ret = fimc_qbuf_capture(fh, b);
+ } else if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+ ret = fimc_qbuf_output(fh, b);
+ } else {
+ fimc_err("V4L2_BUF_TYPE_VIDEO_CAPTURE and "
+ "V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int fimc_dqbuf(struct file *filp, void *fh, struct v4l2_buffer *b)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ret = -1;
+
+ if (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ ret = fimc_dqbuf_capture(fh, b);
+ } else if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+ ret = fimc_dqbuf_output(fh, b);
+ } else {
+ fimc_err("V4L2_BUF_TYPE_VIDEO_CAPTURE and "
+ "V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+const struct v4l2_ioctl_ops fimc_v4l2_ops = {
+ .vidioc_querycap = fimc_querycap,
+ .vidioc_reqbufs = fimc_reqbufs,
+ .vidioc_querybuf = fimc_querybuf,
+ .vidioc_g_ctrl = fimc_g_ctrl,
+ .vidioc_s_ctrl = fimc_s_ctrl,
+ .vidioc_s_ext_ctrls = fimc_s_ext_ctrls,
+ .vidioc_cropcap = fimc_cropcap,
+ .vidioc_g_crop = fimc_g_crop,
+ .vidioc_s_crop = fimc_s_crop,
+ .vidioc_streamon = fimc_streamon,
+ .vidioc_streamoff = fimc_streamoff,
+ .vidioc_qbuf = fimc_qbuf,
+ .vidioc_dqbuf = fimc_dqbuf,
+ .vidioc_enum_fmt_vid_cap = fimc_enum_fmt_vid_capture,
+ .vidioc_g_fmt_vid_cap = fimc_g_fmt_vid_capture,
+ .vidioc_s_fmt_vid_cap = fimc_s_fmt_vid_capture,
+ .vidioc_try_fmt_vid_cap = fimc_try_fmt_vid_capture,
+ .vidioc_enum_input = fimc_enum_input,
+ .vidioc_g_input = fimc_g_input,
+ .vidioc_s_input = fimc_s_input,
+ .vidioc_g_parm = fimc_g_parm,
+ .vidioc_s_parm = fimc_s_parm,
+ .vidioc_queryctrl = fimc_queryctrl,
+ .vidioc_querymenu = fimc_querymenu,
+ .vidioc_g_fmt_vid_out = fimc_g_fmt_vid_out,
+ .vidioc_s_fmt_vid_out = fimc_s_fmt_vid_out,
+ .vidioc_try_fmt_vid_out = fimc_try_fmt_vid_out,
+ .vidioc_g_fbuf = fimc_g_fbuf,
+ .vidioc_s_fbuf = fimc_s_fbuf,
+ .vidioc_try_fmt_vid_overlay = fimc_try_fmt_overlay,
+ .vidioc_g_fmt_vid_overlay = fimc_g_fmt_vid_overlay,
+ .vidioc_s_fmt_vid_overlay = fimc_s_fmt_vid_overlay,
+};
diff --git a/drivers/media/video/samsung/jpeg_v2/Kconfig b/drivers/media/video/samsung/jpeg_v2/Kconfig
new file mode 100644
index 0000000..291aa90
--- /dev/null
+++ b/drivers/media/video/samsung/jpeg_v2/Kconfig
@@ -0,0 +1,15 @@
+#
+# Configuration for JPEG
+#
+
+config VIDEO_JPEG_V2
+ bool "Samsung JPEG driver"
+ depends on VIDEO_SAMSUNG
+ default n
+ ---help---
+ This is a JPEG for Samsung S5PV210
+
+config VIDEO_JPEG_DEBUG
+ bool "print JPEG debug message"
+ depends on VIDEO_JPEG_V2
+ default n
diff --git a/drivers/media/video/samsung/jpeg_v2/Makefile b/drivers/media/video/samsung/jpeg_v2/Makefile
new file mode 100644
index 0000000..b7db901
--- /dev/null
+++ b/drivers/media/video/samsung/jpeg_v2/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_VIDEO_JPEG_V2) += jpg_mem.o jpg_misc.o jpg_opr.o s3c-jpeg.o
+EXTRA_CFLAGS += -Idrivers/media/video
+
diff --git a/drivers/media/video/samsung/jpeg_v2/jpg_conf.h b/drivers/media/video/samsung/jpeg_v2/jpg_conf.h
new file mode 100644
index 0000000..99fcb0d
--- /dev/null
+++ b/drivers/media/video/samsung/jpeg_v2/jpg_conf.h
@@ -0,0 +1,282 @@
+/* linux/drivers/media/video/samsung/jpeg_v2/jpg-conf.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Definition Quantization Table for Jpeg encoder/docoder
+ *
+ * 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 __JPG_CONF_H__
+#define __JPG_CONF_H__
+
+
+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
+ }
+
+
+};
+
+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
+
+ }
+
+};
+
+const unsigned char qtbl0[64] = {
+ 0x10, 0x0B, 0x0A, 0x10, 0x18, 0x28, 0x33, 0x3D,
+ 0x0C, 0x0C, 0x0E, 0x13, 0x1A, 0x3A, 0x3C, 0x37,
+ 0x0E, 0x0D, 0x10, 0x18, 0x28, 0x39, 0x45, 0x38,
+ 0x0E, 0x11, 0x16, 0x1D, 0x33, 0x57, 0x50, 0x3E,
+ 0x12, 0x16, 0x25, 0x38, 0x44, 0x6D, 0x67, 0x4D,
+ 0x18, 0x23, 0x37, 0x40, 0x51, 0x68, 0x71, 0x5C,
+ 0x31, 0x40, 0x4E, 0x57, 0x67, 0x79, 0x78, 0x65,
+ 0x48, 0x5C, 0x5F, 0x62, 0x70, 0x64, 0x67, 0x63
+};
+
+/* Added Quantization Table */
+const unsigned char std_chrominance_quant_tbl_plus[64] = {
+ 0x11, 0x12, 0x18, 0x2F, 0x63, 0x63, 0x63, 0x63,
+ 0x12, 0x15, 0x1A, 0x42, 0x63, 0x63, 0x63, 0x63,
+ 0x18, 0x1A, 0x38, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x2F, 0x42, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63
+};
+
+/* Quantization Table0 */
+unsigned char std_luminance_quant_tbl[64] = {
+ 1, 1, 2, 1, 1, 2, 2, 2,
+ 2, 3, 2, 2, 3, 3, 6, 4,
+ 3, 3, 3, 3, 7, 5, 8, 4,
+ 6, 8, 8, 10, 9, 8, 7, 11,
+ 8, 10, 14, 13, 11, 10, 10, 12,
+ 10, 8, 8, 11, 16, 12, 12, 13,
+ 15, 15, 15, 15, 9, 11, 16, 17,
+ 15, 14, 17, 13, 14, 14, 14, 1
+};
+
+/* Quantization Table1 */
+unsigned char std_chrominance_quant_tbl[64] = {
+ 4, 4, 4, 5, 4, 5, 9, 5,
+ 5, 9, 15, 10, 8, 10, 15, 26,
+ 19, 9, 9, 19, 26, 26, 26, 26,
+ 13, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26
+};
+
+/* Huffman Table */
+unsigned char hdctbl0[16] = {
+ 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0
+};
+
+unsigned char hdctblg0[12] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb
+};
+
+unsigned char hactbl0[16] = {
+ 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d
+};
+
+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
+};
+
+/* Huffman Table0 */
+unsigned char len_dc_luminance[16] = {
+ 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0
+};
+
+unsigned char val_dc_luminance[12] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
+
+unsigned char len_ac_luminance[16] = {
+ 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d
+};
+
+unsigned char val_ac_luminance[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
+};
+
+/* Huffman Table1 */
+unsigned char len_dc_chrominance[16] = {
+ 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0
+};
+
+unsigned char val_dc_chrominance[12] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
+};
+
+unsigned char len_ac_chrominance[16] = {
+ 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77
+};
+
+unsigned char val_ac_chrominance[162] = {
+ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
+ 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
+ 0x13, 0x22, 0x32, 0x81, 0x81, 0x08, 0x14, 0x42,
+ 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52,
+ 0xf0, 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24,
+ 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a,
+ 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86,
+ 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95,
+ 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4,
+ 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3,
+ 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2,
+ 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca,
+ 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
+ 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
+ 0xe9, 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9
+};
+
+#endif
diff --git a/drivers/media/video/samsung/jpeg_v2/jpg_mem.c b/drivers/media/video/samsung/jpeg_v2/jpg_mem.c
new file mode 100644
index 0000000..5f46b8d
--- /dev/null
+++ b/drivers/media/video/samsung/jpeg_v2/jpg_mem.c
@@ -0,0 +1,61 @@
+/* linux/drivers/media/video/samsung/jpeg_v2/jpg_mem.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Operation for Jpeg encoder/docoder with memory
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/io.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/types.h>
+
+#include "jpg_mem.h"
+#include "jpg_misc.h"
+#include "jpg_opr.h"
+
+/*
+ * Function: phy_to_vir_addr
+ * Parameters: phy_addr, mem_size
+ * Return Value: vir_addr
+ * Implementation Notes: memory mapping from physical addr to virtual addr
+ */
+void *phy_to_vir_addr(unsigned int phy_addr, int mem_size)
+{
+ void *reserved_mem;
+
+ reserved_mem = (void *)ioremap((unsigned long)phy_addr, (int)mem_size);
+
+ if (reserved_mem == NULL) {
+ jpg_err("phyical to virtual memory mapping was failed!\r\n");
+ return NULL;
+ }
+
+ return reserved_mem;
+}
+
+void *mem_move(void *dst, const void *src, unsigned int size)
+{
+ return memmove(dst, src, size);
+}
+
+void *mem_alloc(unsigned int size)
+{
+ void *alloc_mem;
+
+ alloc_mem = kmalloc((int)size, GFP_KERNEL);
+
+ if (alloc_mem == NULL) {
+ jpg_err("memory allocation failed!\r\n");
+ return NULL;
+ }
+
+ return alloc_mem;
+}
diff --git a/drivers/media/video/samsung/jpeg_v2/jpg_mem.h b/drivers/media/video/samsung/jpeg_v2/jpg_mem.h
new file mode 100644
index 0000000..3beb549
--- /dev/null
+++ b/drivers/media/video/samsung/jpeg_v2/jpg_mem.h
@@ -0,0 +1,111 @@
+/* linux/drivers/media/video/samsung/jpeg_v2/jpg_mem.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Definition for Operation of Jpeg encoder/docoder with memory
+ *
+ * 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 __JPG_MEM_H__
+#define __JPG_MEM_H__
+
+#include "jpg_misc.h"
+
+#include <linux/version.h>
+#include <plat/media.h>
+#include <mach/media.h>
+
+#define JPG_REG_BASE_ADDR (0xFB600000)
+
+#define jpg_data_base_addr \
+ (unsigned int)s5p_get_media_memory_bank(S5P_MDEV_JPEG, 0)
+#define jpg_reserved_mem_size \
+ ((unsigned int)s5p_get_media_memsize_bank(S5P_MDEV_JPEG, 0))
+
+#define COEF1_RGB_2_YUV 0x4d971e
+#define COEF2_RGB_2_YUV 0x2c5783
+#define COEF3_RGB_2_YUV 0x836e13
+
+/*
+ * JPEG HW Register Macro Definition
+ */
+#define JPG_1BIT_MASK 1
+#define JPG_4BIT_MASK 0xF
+
+/* SubSampling_Mode Mask is JPGMOD Register [2:0] bits mask */
+#define JPG_SMPL_MODE_MASK 0x07
+
+/* Restart Interval value in JPGDRI Register is 2*/
+#define JPG_RESTART_INTRAVEL 2
+
+/* HCLK_JPEG is CLK_GATE_D1_1 Register 5th bit */
+#define JPG_HCLK_JPEG_BIT 5
+/* SubSampling_Mode is JPGMOD Register 0th bit */
+#define JPG_SMPL_MODE_BIT 0
+/* Quantization Table #1 is JPGQHNO Register 8th bit */
+#define JPG_QUANT_TABLE1_BIT 8
+/* Quantization Table #2 is JPGQHNO Register 10th bit */
+#define JPG_QUANT_TABLE2_BIT 10
+/* Quantization Table #3 is JPGQHNO Register 12th bit */
+#define JPG_QUANT_TABLE3_BIT 12
+/* Mode Sel is JPGCMOD Register 5th bit */
+#define JPG_MODE_SEL_BIT 5
+
+#define JPG_DECODE (0x1 << 3)
+#define JPG_ENCODE (0x0 << 3)
+
+#define JPG_RESERVE_ZERO (0b000 << 2)
+
+#define ENABLE_MOTION_ENC (0x1<<3)
+#define DISABLE_MOTION_ENC (0x0<<3)
+
+#define ENABLE_MOTION_DEC (0x1<<0)
+#define DISABLE_MOTION_DEC (0x0<<0)
+
+#define ENABLE_HW_DEC (0x1<<2)
+#define DISABLE_HW_DEC (0x0<<2)
+
+#define INCREMENTAL_DEC (0x1<<3)
+#define NORMAL_DEC (0x0<<3)
+#define YCBCR_MEMORY (0x1<<5)
+
+#define ENABLE_IRQ (0xf<<3)
+
+struct jpegv2_limits {
+ unsigned int max_main_width;
+ unsigned int max_main_height;
+ unsigned int max_thumb_width;
+ unsigned int max_thumb_height;
+};
+
+struct jpegv2_buf {
+ unsigned int main_stream_start;
+ unsigned int main_stream_size;
+ unsigned int main_frame_start;
+ unsigned int main_frame_size;
+ unsigned int thumb_stream_start;
+ unsigned int thumb_stream_size;
+ unsigned int thumb_frame_start;
+ unsigned int thumb_frame_size;
+ unsigned int total_buf_size;
+};
+
+struct s5pc110_jpg_ctx {
+ unsigned int jpg_data_addr;
+ unsigned int img_data_addr;
+ unsigned int jpg_thumb_data_addr;
+ unsigned int img_thumb_data_addr;
+ int caller_process;
+ struct jpegv2_limits *limits;
+ struct jpegv2_buf *bufinfo;
+};
+
+void *phy_to_vir_addr(unsigned int phy_addr, int mem_size);
+void *mem_move(void *dst, const void *src, unsigned int size);
+void *mem_alloc(unsigned int size);
+#endif
+
diff --git a/drivers/media/video/samsung/jpeg_v2/jpg_misc.c b/drivers/media/video/samsung/jpeg_v2/jpg_misc.c
new file mode 100644
index 0000000..964baf6
--- /dev/null
+++ b/drivers/media/video/samsung/jpeg_v2/jpg_misc.c
@@ -0,0 +1,81 @@
+/* linux/drivers/media/video/samsung/jpeg_v2/jpg_misc.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Operation for Jpeg encoder/docoder with mutex
+ *
+ * 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 <stdarg.h>
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+
+#include <linux/version.h>
+
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+
+#include "jpg_misc.h"
+#include "jpg_mem.h"
+
+static struct mutex *h_mutex;
+
+/*
+ * Function: create_jpg_mutex
+ * Implementation Notes: Create Mutex handle
+ */
+struct mutex *create_jpg_mutex(void)
+{
+ h_mutex = kmalloc(sizeof(struct mutex), GFP_KERNEL);
+
+ if (h_mutex == NULL)
+ return NULL;
+
+ mutex_init(h_mutex);
+
+ return h_mutex;
+}
+
+/*
+ * Function: lock_jpg_mutex
+ * Implementation Notes: lock mutex
+ */
+unsigned long lock_jpg_mutex(void)
+{
+ mutex_lock(h_mutex);
+ return 1;
+}
+
+/*
+ * Function: unlock_jpg_mutex
+ * Implementation Notes: unlock mutex
+*/
+unsigned long unlock_jpg_mutex(void)
+{
+ mutex_unlock(h_mutex);
+
+ return 1;
+}
+
+
+/*
+ * Function: delete_jpg_mutex
+ * Implementation Notes: delete mutex handle
+ */
+void delete_jpg_mutex(void)
+{
+ if (h_mutex == NULL)
+ return;
+
+ mutex_destroy(h_mutex);
+}
+
diff --git a/drivers/media/video/samsung/jpeg_v2/jpg_misc.h b/drivers/media/video/samsung/jpeg_v2/jpg_misc.h
new file mode 100644
index 0000000..31422d2
--- /dev/null
+++ b/drivers/media/video/samsung/jpeg_v2/jpg_misc.h
@@ -0,0 +1,27 @@
+/* linux/drivers/media/video/samsung/jpeg_v2/jpg_misc.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Definition for Operation of Jpeg encoder/docoder with mutex
+ *
+ * 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 __JPG_MISC_H__
+#define __JPG_MISC_H__
+
+#include <linux/types.h>
+
+enum BOOL {FALSE, TRUE};
+
+#define INT_TIMEOUT 1000
+
+struct mutex *create_jpg_mutex(void);
+unsigned long lock_jpg_mutex(void);
+unsigned long unlock_jpg_mutex(void);
+void delete_jpg_mutex(void);
+
+#endif
diff --git a/drivers/media/video/samsung/jpeg_v2/jpg_opr.c b/drivers/media/video/samsung/jpeg_v2/jpg_opr.c
new file mode 100644
index 0000000..51a7979
--- /dev/null
+++ b/drivers/media/video/samsung/jpeg_v2/jpg_opr.c
@@ -0,0 +1,320 @@
+/* linux/drivers/media/video/samsung/jpeg_v2/jpg_opr.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Operation for Jpeg encoder/docoder
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include "jpg_mem.h"
+#include "jpg_misc.h"
+#include "jpg_opr.h"
+#include "jpg_conf.h"
+
+#include "regs-jpeg.h"
+
+enum {
+ UNKNOWN,
+ BASELINE = 0xC0,
+ EXTENDED_SEQ = 0xC1,
+ PROGRESSIVE = 0xC2
+} jpg_sof_marker;
+
+enum jpg_return_status wait_for_interrupt(void)
+{
+ if (interruptible_sleep_on_timeout(&wait_queue_jpeg, \
+ INT_TIMEOUT) == 0) {
+ jpg_err("waiting for interrupt is timeout\n");
+ }
+
+ return jpg_irq_reason;
+}
+
+enum jpg_return_status decode_jpg(struct s5pc110_jpg_ctx *jpg_ctx,
+ struct jpg_dec_proc_param *dec_param)
+{
+ int ret;
+ enum sample_mode sample_mode;
+ unsigned int width, height;
+ jpg_dbg("enter decode_jpg function\n");
+
+ if (jpg_ctx)
+ reset_jpg(jpg_ctx);
+ else {
+ jpg_err("jpg ctx is NULL\n");
+ return JPG_FAIL;
+ }
+
+/* set jpeg clock register : power on */
+ writel(readl(s3c_jpeg_base + S3C_JPEG_CLKCON_REG) |
+ (S3C_JPEG_CLKCON_REG_POWER_ON_ACTIVATE),
+ s3c_jpeg_base + S3C_JPEG_CLKCON_REG);
+ /* set jpeg mod register : decode */
+ writel(readl(s3c_jpeg_base + S3C_JPEG_MOD_REG) |
+ (S3C_JPEG_MOD_REG_PROC_DEC),
+ s3c_jpeg_base + S3C_JPEG_MOD_REG);
+ /* set jpeg interrupt setting register */
+ writel(readl(s3c_jpeg_base + S3C_JPEG_INTSE_REG) |
+ (S3C_JPEG_INTSE_REG_RSTM_INT_EN |
+ S3C_JPEG_INTSE_REG_DATA_NUM_INT_EN |
+ S3C_JPEG_INTSE_REG_FINAL_MCU_NUM_INT_EN),
+ s3c_jpeg_base + S3C_JPEG_INTSE_REG);
+ /* set jpeg deocde ouput format register */
+ writel(readl(s3c_jpeg_base + S3C_JPEG_OUTFORM_REG) &
+ ~(S3C_JPEG_OUTFORM_REG_YCBCY420),
+ s3c_jpeg_base + S3C_JPEG_OUTFORM_REG);
+ writel(readl(s3c_jpeg_base + S3C_JPEG_OUTFORM_REG) |
+ (dec_param->out_format << 0),
+ s3c_jpeg_base + S3C_JPEG_OUTFORM_REG);
+
+ /* set the address of compressed input data */
+ writel(jpg_ctx->img_data_addr, s3c_jpeg_base + S3C_JPEG_IMGADR_REG);
+
+ /* set the address of decompressed image */
+ writel(jpg_ctx->jpg_data_addr, s3c_jpeg_base + S3C_JPEG_JPGADR_REG);
+
+ /* start decoding */
+ writel(readl(s3c_jpeg_base + S3C_JPEG_JRSTART_REG) |
+ S3C_JPEG_JRSTART_REG_ENABLE,
+ s3c_jpeg_base + S3C_JPEG_JSTART_REG);
+
+ ret = wait_for_interrupt();
+
+ if (ret != OK_ENC_OR_DEC) {
+ jpg_err("jpg decode error(%d)\n", ret);
+ return JPG_FAIL;
+ }
+
+ sample_mode = get_sample_type(jpg_ctx);
+ jpg_dbg("sample_mode : %d\n", sample_mode);
+
+ if (sample_mode == JPG_SAMPLE_UNKNOWN) {
+ jpg_err("jpg has invalid sample_mode\r\n");
+ return JPG_FAIL;
+ }
+
+ dec_param->sample_mode = sample_mode;
+
+ get_xy(jpg_ctx, &width, &height);
+ jpg_dbg("decode size:: width : %d height : %d\n", width, height);
+
+ dec_param->data_size = get_yuv_size(dec_param->out_format,
+ width, height);
+ dec_param->width = width;
+ dec_param->height = height;
+
+ return JPG_SUCCESS;
+}
+
+void reset_jpg(struct s5pc110_jpg_ctx *jpg_ctx)
+{
+ jpg_dbg("s3c_jpeg_base %p\n", s3c_jpeg_base);
+ writel(S3C_JPEG_SW_RESET_REG_ENABLE,
+ s3c_jpeg_base + S3C_JPEG_SW_RESET_REG);
+
+ do {
+ writel(S3C_JPEG_SW_RESET_REG_ENABLE,
+ s3c_jpeg_base + S3C_JPEG_SW_RESET_REG);
+ } while (((readl(s3c_jpeg_base + S3C_JPEG_SW_RESET_REG))
+ & S3C_JPEG_SW_RESET_REG_ENABLE)
+ == S3C_JPEG_SW_RESET_REG_ENABLE);
+}
+
+enum sample_mode get_sample_type(struct s5pc110_jpg_ctx *jpg_ctx)
+{
+ unsigned long jpgMode;
+ enum sample_mode sample_mode = JPG_SAMPLE_UNKNOWN;
+
+ jpgMode = readl(s3c_jpeg_base + S3C_JPEG_MOD_REG);
+
+ sample_mode =
+ ((jpgMode & JPG_SMPL_MODE_MASK) == JPG_444) ? JPG_444 :
+ ((jpgMode & JPG_SMPL_MODE_MASK) == JPG_422) ? JPG_422 :
+ ((jpgMode & JPG_SMPL_MODE_MASK) == JPG_420) ? JPG_420 :
+ ((jpgMode & JPG_SMPL_MODE_MASK) == JPG_400) ? JPG_400 :
+ ((jpgMode & JPG_SMPL_MODE_MASK) == JPG_411) ? JPG_411 :
+ JPG_SAMPLE_UNKNOWN;
+
+ return sample_mode;
+}
+
+void get_xy(struct s5pc110_jpg_ctx *jpg_ctx, unsigned int *x, unsigned int *y)
+{
+ *x = (readl(s3c_jpeg_base + S3C_JPEG_X_U_REG)<<8)|
+ readl(s3c_jpeg_base + S3C_JPEG_X_L_REG);
+ *y = (readl(s3c_jpeg_base + S3C_JPEG_Y_U_REG)<<8)|
+ readl(s3c_jpeg_base + S3C_JPEG_Y_L_REG);
+}
+
+unsigned int get_yuv_size(enum out_mode out_format,
+ unsigned int width, unsigned int height)
+{
+ switch (out_format) {
+ case YCBCR_422:
+
+ if (width % 16 != 0)
+ width += 16 - (width % 16);
+
+ if (height % 8 != 0)
+ height += 8 - (height % 8);
+
+ break;
+
+ case YCBCR_420:
+
+ if (width % 16 != 0)
+ width += 16 - (width % 16);
+
+ if (height % 16 != 0)
+ height += 16 - (height % 16);
+
+ break;
+
+ case YCBCR_SAMPLE_UNKNOWN:
+ break;
+ }
+
+ jpg_dbg("get_yuv_size width(%d) height(%d)\n", width, height);
+
+ switch (out_format) {
+ case YCBCR_422:
+ return width * height * 2;
+ case YCBCR_420:
+ return (width * height) + (width * height >> 1);
+ default:
+ return 0;
+ }
+}
+
+enum jpg_return_status encode_jpg(struct s5pc110_jpg_ctx *jpg_ctx,
+ struct jpg_enc_proc_param *enc_param)
+{
+
+ unsigned int i, ret;
+ unsigned int cmd_val;
+
+ if (enc_param->width <= 0
+ || enc_param->width > jpg_ctx->limits->max_main_width
+ || enc_param->height <= 0
+ || enc_param->height > jpg_ctx->limits->max_main_height) {
+ jpg_err("::encoder : width: %d, height: %d\n",
+ enc_param->width, enc_param->height);
+ jpg_err("::encoder : invalid width/height\n");
+ return JPG_FAIL;
+ }
+
+ /* SW reset */
+ if (jpg_ctx)
+ reset_jpg(jpg_ctx);
+ else {
+ jpg_err("::jpg ctx is NULL\n");
+ return JPG_FAIL;
+ }
+ /* set jpeg clock register : power on */
+ writel(readl(s3c_jpeg_base + S3C_JPEG_CLKCON_REG) |
+ (S3C_JPEG_CLKCON_REG_POWER_ON_ACTIVATE),
+ s3c_jpeg_base + S3C_JPEG_CLKCON_REG);
+ /* set jpeg mod register : encode */
+ writel(readl(s3c_jpeg_base + S3C_JPEG_CMOD_REG) |
+ (enc_param->in_format << JPG_MODE_SEL_BIT),
+ s3c_jpeg_base + S3C_JPEG_CMOD_REG);
+ cmd_val = (enc_param->sample_mode == JPG_422) ?
+ (S3C_JPEG_MOD_REG_SUBSAMPLE_422) :
+ (S3C_JPEG_MOD_REG_SUBSAMPLE_420);
+
+ writel(cmd_val | S3C_JPEG_MOD_REG_PROC_ENC,
+ s3c_jpeg_base + S3C_JPEG_MOD_REG);
+
+ /* set DRI(Define Restart Interval) */
+ writel(JPG_RESTART_INTRAVEL, s3c_jpeg_base + S3C_JPEG_DRI_L_REG);
+ writel((JPG_RESTART_INTRAVEL>>8), s3c_jpeg_base + S3C_JPEG_DRI_U_REG);
+
+ writel(S3C_JPEG_QHTBL_REG_QT_NUM1, s3c_jpeg_base + S3C_JPEG_QTBL_REG);
+ writel(0x00, s3c_jpeg_base + S3C_JPEG_HTBL_REG);
+
+ /* Horizontal resolution */
+ writel((enc_param->width>>8), s3c_jpeg_base + S3C_JPEG_X_U_REG);
+ writel(enc_param->width, s3c_jpeg_base + S3C_JPEG_X_L_REG);
+
+ /* Vertical resolution */
+ writel((enc_param->height>>8), s3c_jpeg_base + S3C_JPEG_Y_U_REG);
+ writel(enc_param->height, s3c_jpeg_base + S3C_JPEG_Y_L_REG);
+
+ jpg_dbg("enc_param->enc_type : %d\n", enc_param->enc_type);
+
+ if (enc_param->enc_type == JPG_MAIN) {
+ jpg_dbg("encode image size width: %d, height: %d\n",
+ enc_param->width, enc_param->height);
+ writel(jpg_ctx->img_data_addr,
+ s3c_jpeg_base + S3C_JPEG_IMGADR_REG);
+ writel(jpg_ctx->jpg_data_addr,
+ s3c_jpeg_base + S3C_JPEG_JPGADR_REG);
+ } else { /* thumbnail encoding */
+ jpg_dbg("thumb image size width: %d, height: %d\n",
+ enc_param->width, enc_param->height);
+ writel(jpg_ctx->img_thumb_data_addr,
+ s3c_jpeg_base + S3C_JPEG_IMGADR_REG);
+ writel(jpg_ctx->jpg_thumb_data_addr,
+ s3c_jpeg_base + S3C_JPEG_JPGADR_REG);
+ }
+
+ /* Coefficient value 1~3 for RGB to YCbCr */
+ writel(COEF1_RGB_2_YUV, s3c_jpeg_base + S3C_JPEG_COEF1_REG);
+ writel(COEF2_RGB_2_YUV, s3c_jpeg_base + S3C_JPEG_COEF2_REG);
+ writel(COEF3_RGB_2_YUV, s3c_jpeg_base + S3C_JPEG_COEF3_REG);
+
+ /* Quantiazation and Huffman Table setting */
+ for (i = 0; i < 64; i++) {
+ writel((unsigned int)qtbl_luminance[enc_param->quality][i],
+ s3c_jpeg_base + S3C_JPEG_QTBL0_REG + (i*0x04));
+ }
+ for (i = 0; i < 64; i++) {
+ writel((unsigned int)qtbl_chrominance[enc_param->quality][i],
+ s3c_jpeg_base + S3C_JPEG_QTBL1_REG + (i*0x04));
+ }
+ for (i = 0; i < 16; i++) {
+ writel((unsigned int)hdctbl0[i],
+ s3c_jpeg_base + S3C_JPEG_HDCTBL0_REG + (i*0x04));
+ }
+ for (i = 0; i < 12; i++) {
+ writel((unsigned int)hdctblg0[i],
+ s3c_jpeg_base + S3C_JPEG_HDCTBLG0_REG + (i*0x04));
+ }
+ for (i = 0; i < 16; i++) {
+ writel((unsigned int)hactbl0[i],
+ s3c_jpeg_base + S3C_JPEG_HACTBL0_REG + (i*0x04));
+ }
+ for (i = 0; i < 162; i++) {
+ writel((unsigned int)hactblg0[i],
+ s3c_jpeg_base + S3C_JPEG_HACTBLG0_REG + (i*0x04));
+ }
+ writel(readl(s3c_jpeg_base + S3C_JPEG_INTSE_REG) |
+ (S3C_JPEG_INTSE_REG_RSTM_INT_EN |
+ S3C_JPEG_INTSE_REG_DATA_NUM_INT_EN |
+ S3C_JPEG_INTSE_REG_FINAL_MCU_NUM_INT_EN),
+ s3c_jpeg_base + S3C_JPEG_INTSE_REG);
+
+ writel(readl(s3c_jpeg_base + S3C_JPEG_JSTART_REG) |
+ S3C_JPEG_JSTART_REG_ENABLE,
+ s3c_jpeg_base + S3C_JPEG_JSTART_REG);
+ ret = wait_for_interrupt();
+
+ if (ret != OK_ENC_OR_DEC) {
+ jpg_err("jpeg encoding error(%d)\n", ret);
+ return JPG_FAIL;
+ }
+
+ enc_param->file_size = readl(s3c_jpeg_base + S3C_JPEG_CNT_U_REG) << 16;
+ enc_param->file_size |= readl(s3c_jpeg_base + S3C_JPEG_CNT_M_REG) << 8;
+ enc_param->file_size |= readl(s3c_jpeg_base + S3C_JPEG_CNT_L_REG);
+
+ return JPG_SUCCESS;
+
+}
diff --git a/drivers/media/video/samsung/jpeg_v2/jpg_opr.h b/drivers/media/video/samsung/jpeg_v2/jpg_opr.h
new file mode 100644
index 0000000..b8c21d0
--- /dev/null
+++ b/drivers/media/video/samsung/jpeg_v2/jpg_opr.h
@@ -0,0 +1,158 @@
+/* linux/drivers/media/video/samsung/jpeg_v2/jpg_opr.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Definition for Operation of Jpeg encoder/docoder
+ *
+ * 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 __JPG_OPR_H__
+#define __JPG_OPR_H__
+
+#include <linux/interrupt.h>
+
+extern void __iomem *s3c_jpeg_base;
+extern int jpg_irq_reason;
+
+/* debug macro */
+#define JPG_DEBUG(fmt, ...) \
+ do { \
+ printk(KERN_DEBUG \
+ "%s: " fmt, __func__, ##__VA_ARGS__); \
+ } while (0)
+
+
+#define JPG_WARN(fmt, ...) \
+ do { \
+ printk(KERN_WARNING \
+ fmt, ##__VA_ARGS__); \
+ } while (0)
+
+
+
+#define JPG_ERROR(fmt, ...) \
+ do { \
+ printk(KERN_ERR \
+ "%s: " fmt, __func__, ##__VA_ARGS__); \
+ } while (0)
+
+
+
+#ifdef CONFIG_VIDEO_JPEG_DEBUG
+#define jpg_dbg(fmt, ...) JPG_DEBUG(fmt, ##__VA_ARGS__)
+#else
+#define jpg_dbg(fmt, ...)
+#endif
+
+#define jpg_warn(fmt, ...) JPG_WARN(fmt, ##__VA_ARGS__)
+#define jpg_err(fmt, ...) JPG_ERROR(fmt, ##__VA_ARGS__)
+
+extern wait_queue_head_t wait_queue_jpeg;
+
+enum jpg_return_status {
+ JPG_FAIL,
+ JPG_SUCCESS,
+ OK_HD_PARSING,
+ ERR_HD_PARSING,
+ OK_ENC_OR_DEC,
+ ERR_ENC_OR_DEC,
+ ERR_UNKNOWN
+};
+
+enum image_type {
+ JPG_RGB16,
+ JPG_YCBYCR,
+ JPG_TYPE_UNKNOWN
+};
+
+enum sample_mode {
+ JPG_444,
+ JPG_422,
+ JPG_420,
+ JPG_400,
+ RESERVED1,
+ RESERVED2,
+ JPG_411,
+ JPG_SAMPLE_UNKNOWN
+};
+
+enum out_mode {
+ YCBCR_422,
+ YCBCR_420,
+ YCBCR_SAMPLE_UNKNOWN
+};
+
+enum in_mode {
+ JPG_MODESEL_YCBCR = 1,
+ JPG_MODESEL_RGB,
+ JPG_MODESEL_UNKNOWN
+};
+
+enum encode_type {
+ JPG_MAIN,
+ JPG_THUMBNAIL
+};
+
+enum image_quality_type {
+ JPG_QUALITY_LEVEL_1 = 0, /*high quality*/
+ JPG_QUALITY_LEVEL_2,
+ JPG_QUALITY_LEVEL_3,
+ JPG_QUALITY_LEVEL_4 /*low quality*/
+};
+
+struct jpg_dec_proc_param {
+ enum sample_mode sample_mode;
+ enum encode_type dec_type;
+ enum out_mode out_format;
+ unsigned int width;
+ unsigned int height;
+ unsigned int data_size;
+ unsigned int file_size;
+};
+
+struct jpg_enc_proc_param {
+ enum sample_mode sample_mode;
+ enum encode_type enc_type;
+ enum in_mode in_format;
+ enum image_quality_type quality;
+ unsigned int width;
+ unsigned int height;
+ unsigned int data_size;
+ unsigned int file_size;
+};
+
+struct jpg_args {
+ char *in_buf;
+ char *phy_in_buf;
+ int in_buf_size;
+ char *out_buf;
+ char *phy_out_buf;
+ int out_buf_size;
+ char *in_thumb_buf;
+ char *phy_in_thumb_buf;
+ int in_thumb_buf_size;
+ char *out_thumb_buf;
+ char *phy_out_thumb_buf;
+ int out_thumb_buf_size;
+ char *mapped_addr;
+ struct jpg_dec_proc_param *dec_param;
+ struct jpg_enc_proc_param *enc_param;
+ struct jpg_enc_proc_param *thumb_enc_param;
+};
+
+void reset_jpg(struct s5pc110_jpg_ctx *jpg_ctx);
+enum jpg_return_status decode_jpg(struct s5pc110_jpg_ctx *jpg_ctx, \
+ struct jpg_dec_proc_param *dec_param);
+enum jpg_return_status encode_jpg(struct s5pc110_jpg_ctx *jpg_ctx, \
+ struct jpg_enc_proc_param *enc_param);
+enum jpg_return_status wait_for_interrupt(void);
+enum sample_mode get_sample_type(struct s5pc110_jpg_ctx *jpg_ctx);
+void get_xy(struct s5pc110_jpg_ctx *jpg_ctx, unsigned int *x, unsigned int *y);
+unsigned int get_yuv_size(enum out_mode out_format, \
+ unsigned int width, unsigned int height);
+
+#endif
diff --git a/drivers/media/video/samsung/jpeg_v2/regs-jpeg.h b/drivers/media/video/samsung/jpeg_v2/regs-jpeg.h
new file mode 100644
index 0000000..55bd2eb
--- /dev/null
+++ b/drivers/media/video/samsung/jpeg_v2/regs-jpeg.h
@@ -0,0 +1,143 @@
+/* linux/drivers/media/video/samsung/jpeg/regs-jpeg.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Register definition file for Samsung JPEG Encoder/Decoder
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARM_REGS_S3C_JPEG_H
+#define __ASM_ARM_REGS_S3C_JPEG_H
+
+/* JPEG Registers part */
+#define S3C_JPEG_REG(x) ((x))
+
+/* Sub-sampling Mode Register */
+#define S3C_JPEG_MOD_REG S3C_JPEG_REG(0x00)
+/* Operation Status Register */
+#define S3C_JPEG_OPR_REG S3C_JPEG_REG(0x04)
+/* Quantization Table Number Register and Huffman Table Number Register */
+#define S3C_JPEG_QTBL_REG S3C_JPEG_REG(0x08)
+/* Huffman Table Number Register */
+#define S3C_JPEG_HTBL_REG S3C_JPEG_REG(0x0c)
+#define S3C_JPEG_DRI_U_REG S3C_JPEG_REG(0x10) /* MCU, which inserts RST marker(upper 8bit) */
+#define S3C_JPEG_DRI_L_REG S3C_JPEG_REG(0x14) /* MCU, which inserts RST marker(lower 8bit) */
+#define S3C_JPEG_Y_U_REG S3C_JPEG_REG(0x18) /* Vertical Resolution (upper 8bit) */
+#define S3C_JPEG_Y_L_REG S3C_JPEG_REG(0x1c) /* Vertical Resolution (lower 8bit) */
+#define S3C_JPEG_X_U_REG S3C_JPEG_REG(0x20) /* Horizontal Resolution (upper 8bit) */
+#define S3C_JPEG_X_L_REG S3C_JPEG_REG(0x24) /* Horizontal Resolution (lower 8bit) */
+#define S3C_JPEG_CNT_U_REG S3C_JPEG_REG(0x28) /* The amount of the compressed data in bytes (upper 8bit) */
+#define S3C_JPEG_CNT_M_REG S3C_JPEG_REG(0x2c) /* The amount of the compressed data in bytes (middle 8bit) */
+#define S3C_JPEG_CNT_L_REG S3C_JPEG_REG(0x30) /* The amount of the compressed data in bytes (lowerz 8bit) */
+#define S3C_JPEG_INTSE_REG S3C_JPEG_REG(0x34) /* Interrupt setting register */
+#define S3C_JPEG_INTST_REG S3C_JPEG_REG(0x38) /* Interrupt status */
+
+#define S3C_JPEG_COM_REG S3C_JPEG_REG(0x4c) /* Command register */
+
+#define S3C_JPEG_IMGADR_REG S3C_JPEG_REG(0x50) /* Source or destination image addresss */
+
+#define S3C_JPEG_JPGADR_REG S3C_JPEG_REG(0x58) /* Source or destination JPEG file address */
+#define S3C_JPEG_COEF1_REG S3C_JPEG_REG(0x5c) /* Coefficient values for RGB <-> YCbCr converter */
+#define S3C_JPEG_COEF2_REG S3C_JPEG_REG(0x60) /* Coefficient values for RGB <-> YCbCr converter */
+#define S3C_JPEG_COEF3_REG S3C_JPEG_REG(0x64) /* Coefficient values for RGB <-> YCbCr converter */
+
+#define S3C_JPEG_CMOD_REG S3C_JPEG_REG(0x68) /* Mode selection and core clock setting */
+#define S3C_JPEG_CLKCON_REG S3C_JPEG_REG(0x6c) /* Power on/off and clock down control */
+
+#define S3C_JPEG_JSTART_REG S3C_JPEG_REG(0x70) /* Start compression or decompression */
+#define S3C_JPEG_JRSTART_REG S3C_JPEG_REG(0x74) /* Restart decompression after header analysis */
+#define S3C_JPEG_SW_RESET_REG S3C_JPEG_REG(0x78) /* S/W reset */
+
+#define S3C_JPEG_TIMER_SE_REG S3C_JPEG_REG(0x7c) /* Internal timer setting register */
+#define S3C_JPEG_TIMER_ST_REG S3C_JPEG_REG(0x80) /* Internal timer status register */
+#define S3C_JPEG_COMSTAT_REG S3C_JPEG_REG(0x84) /* Command status register */
+#define S3C_JPEG_OUTFORM_REG S3C_JPEG_REG(0x88) /* Output color format of decompression */
+#define S3C_JPEG_VERSION_REG S3C_JPEG_REG(0x8c) /* Version register */
+
+#define S3C_JPEG_ENC_STREAM_INTSE_REG S3C_JPEG_REG(0x98) /* Compressed stream size interrupt setting register */
+#define S3C_JPEG_ENC_STREAM_INTST_REG S3C_JPEG_REG(0x9c) /* Compressed stream size interrupt status register */
+
+#define S3C_JPEG_QTBL0_REG S3C_JPEG_REG(0x400) /* Quantization table 0 */
+#define S3C_JPEG_QTBL1_REG S3C_JPEG_REG(0x500) /* Quantization table 1 */
+#define S3C_JPEG_QTBL2_REG S3C_JPEG_REG(0x600) /* Quantization table 2 */
+#define S3C_JPEG_QTBL3_REG S3C_JPEG_REG(0x700) /* Quantization table 3 */
+
+#define S3C_JPEG_HDCTBL0_REG S3C_JPEG_REG(0x800) /* DC huffman table 0 */
+#define S3C_JPEG_HDCTBLG0_REG S3C_JPEG_REG(0x840) /* DC huffman table group 0 */
+#define S3C_JPEG_HACTBL0_REG S3C_JPEG_REG(0x880) /* AC huffman table 0 */
+#define S3C_JPEG_HACTBLG0_REG S3C_JPEG_REG(0x8c0) /* AC huffman table group 0 */
+#define S3C_JPEG_HDCTBL1_REG S3C_JPEG_REG(0xc00) /* DC huffman table 1 */
+#define S3C_JPEG_HDCTBLG1_REG S3C_JPEG_REG(0xc40) /* DC huffman table group 1 */
+#define S3C_JPEG_HACTBL1_REG S3C_JPEG_REG(0xc80) /* AC huffman table 1 */
+#define S3C_JPEG_HACTBLG1_REG S3C_JPEG_REG(0xcc0) /* AC huffman table group 1 */
+
+/* JPEG Mode Register bit */
+#define S3C_JPEG_MOD_REG_PROC_ENC (0<<3)
+#define S3C_JPEG_MOD_REG_PROC_DEC (1<<3)
+
+#define S3C_JPEG_MOD_REG_SUBSAMPLE_444 (0<<0)
+#define S3C_JPEG_MOD_REG_SUBSAMPLE_422 (1<<0)
+#define S3C_JPEG_MOD_REG_SUBSAMPLE_420 (2<<0)
+#define S3C_JPEG_MOD_REG_SUBSAMPLE_GRAY (3<<0)
+
+/* JPEG Operation Status Register bit */
+#define S3C_JPEG_OPR_REG_OPERATE (1<<0)
+#define S3C_JPEG_OPR_REG_NO_OPERATE (0<<0)
+
+/* Quantization Table And Huffman Table Number Register bit */
+#define S3C_JPEG_QHTBL_REG_QT_NUM4 (1<<6)
+#define S3C_JPEG_QHTBL_REG_QT_NUM3 (1<<4)
+#define S3C_JPEG_QHTBL_REG_QT_NUM2 (1<<2)
+#define S3C_JPEG_QHTBL_REG_QT_NUM1 (1<<0)
+
+#define S3C_JPEG_QHTBL_REG_HT_NUM4_AC (1<<7)
+#define S3C_JPEG_QHTBL_REG_HT_NUM4_DC (1<<6)
+#define S3C_JPEG_QHTBL_REG_HT_NUM3_AC (1<<5)
+#define S3C_JPEG_QHTBL_REG_HT_NUM3_DC (1<<4)
+#define S3C_JPEG_QHTBL_REG_HT_NUM2_AC (1<<3)
+#define S3C_JPEG_QHTBL_REG_HT_NUM2_DC (1<<2)
+#define S3C_JPEG_QHTBL_REG_HT_NUM1_AC (1<<1)
+#define S3C_JPEG_QHTBL_REG_HT_NUM1_DC (1<<0)
+
+
+/* JPEG Color Mode Register bit */
+#define S3C_JPEG_CMOD_REG_MOD_SEL_RGB (2<<5)
+#define S3C_JPEG_CMOD_REG_MOD_SEL_YCBCR422 (1<<5)
+#define S3C_JPEG_CMOD_REG_MOD_MODE_Y16 (1<<1)
+#define S3C_JPEG_CMOD_REG_MOD_MODE_0 (0<<1)
+
+/* JPEG Clock Control Register bit */
+#define S3C_JPEG_CLKCON_REG_CLK_DOWN_READY_ENABLE (0<<1)
+#define S3C_JPEG_CLKCON_REG_CLK_DOWN_READY_DISABLE (1<<1)
+#define S3C_JPEG_CLKCON_REG_POWER_ON_ACTIVATE (1<<0)
+#define S3C_JPEG_CLKCON_REG_POWER_ON_DISABLE (0<<0)
+
+/* JPEG Start Register bit */
+#define S3C_JPEG_JSTART_REG_ENABLE (1<<0)
+
+/* JPEG Rdstart Register bit */
+#define S3C_JPEG_JRSTART_REG_ENABLE (1<<0)
+
+/* JPEG SW Reset Register bit */
+#define S3C_JPEG_SW_RESET_REG_ENABLE (1<<0)
+
+/* JPEG Interrupt Setting Register bit */
+#define S3C_JPEG_INTSE_REG_RSTM_INT_EN (1<<7)
+#define S3C_JPEG_INTSE_REG_DATA_NUM_INT_EN (1<<6)
+#define S3C_JPEG_INTSE_REG_FINAL_MCU_NUM_INT_EN (1<<5)
+
+/* JPEG Decompression Output Format Register bit */
+#define S3C_JPEG_OUTFORM_REG_YCBCY422 (0<<0)
+#define S3C_JPEG_OUTFORM_REG_YCBCY420 (1<<0)
+
+/* JPEG Decompression Input Stream Size Register bit */
+#define S3C_JPEG_DEC_STREAM_SIZE_REG_PROHIBIT (0x1FFFFFFF<<0)
+
+/* JPEG Command Register bit */
+#define S3C_JPEG_COM_INT_RELEASE (1<<2)
+
+#endif /*__ASM_ARM_REGS_S3C_JPEG_H */
diff --git a/drivers/media/video/samsung/jpeg_v2/s3c-jpeg.c b/drivers/media/video/samsung/jpeg_v2/s3c-jpeg.c
new file mode 100644
index 0000000..81408b4
--- /dev/null
+++ b/drivers/media/video/samsung/jpeg_v2/s3c-jpeg.c
@@ -0,0 +1,613 @@
+/* linux/drivers/media/video/samsung/jpeg_v2/s3c-jpeg.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Core file for Samsung Jpeg Interface driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/signal.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/kmod.h>
+#include <linux/vmalloc.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <asm/page.h>
+#include <mach/irqs.h>
+#include <linux/semaphore.h>
+#include <mach/map.h>
+#include <linux/miscdevice.h>
+#include <linux/vmalloc.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+
+#include <linux/version.h>
+#include <plat/media.h>
+#include <plat/jpeg.h>
+#include <mach/media.h>
+
+#include <linux/time.h>
+#include <linux/clk.h>
+
+#include <plat/clock.h>
+
+#include "s3c-jpeg.h"
+#include "jpg_mem.h"
+#include "jpg_misc.h"
+#include "jpg_opr.h"
+#include "regs-jpeg.h"
+
+static struct jpegv2_limits s3c_jpeg_limits;
+static struct jpegv2_buf s3c_jpeg_bufinfo;
+
+static struct clk *s3c_jpeg_clk;
+static struct regulator *jpeg_pd_regulator;
+
+static struct resource *s3c_jpeg_mem;
+void __iomem *s3c_jpeg_base;
+static int irq_no;
+static int instanceNo;;
+int jpg_irq_reason;
+wait_queue_head_t wait_queue_jpeg;
+
+
+DECLARE_WAIT_QUEUE_HEAD(WaitQueue_JPEG);
+
+static void jpeg_clock_enable(void)
+{
+ /* power domain enable */
+ regulator_enable(jpeg_pd_regulator);
+
+ /* clock enable */
+ clk_enable(s3c_jpeg_clk);
+}
+
+static void jpeg_clock_disable(void)
+{
+ /* clock disable */
+ clk_disable(s3c_jpeg_clk);
+
+ /* power domain disable */
+ regulator_disable(jpeg_pd_regulator);
+}
+
+irqreturn_t s3c_jpeg_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+ unsigned int int_status;
+ unsigned int status;
+
+ jpg_dbg("=====enter s3c_jpeg_irq===== \r\n");
+
+ int_status = readl(s3c_jpeg_base + S3C_JPEG_INTST_REG);
+
+ do {
+ status = readl(s3c_jpeg_base + S3C_JPEG_OPR_REG);
+ } while (status);
+
+ writel(S3C_JPEG_COM_INT_RELEASE, s3c_jpeg_base + S3C_JPEG_COM_REG);
+ jpg_dbg("int_status : 0x%08x status : 0x%08x\n", int_status, status);
+
+ if (int_status) {
+ switch (int_status) {
+ case 0x40:
+ jpg_irq_reason = OK_ENC_OR_DEC;
+ break;
+ case 0x20:
+ jpg_irq_reason = ERR_ENC_OR_DEC;
+ break;
+ default:
+ jpg_irq_reason = ERR_UNKNOWN;
+ }
+
+ wake_up_interruptible(&wait_queue_jpeg);
+ } else {
+ jpg_irq_reason = ERR_UNKNOWN;
+ wake_up_interruptible(&wait_queue_jpeg);
+ }
+
+ return IRQ_HANDLED;
+}
+static int s3c_jpeg_open(struct inode *inode, struct file *file)
+{
+ struct s5pc110_jpg_ctx *jpg_reg_ctx;
+ unsigned long ret;
+
+ jpg_dbg("JPG_open \r\n");
+
+ jpg_reg_ctx = (struct s5pc110_jpg_ctx *)
+ mem_alloc(sizeof(struct s5pc110_jpg_ctx));
+ memset(jpg_reg_ctx, 0x00, sizeof(struct s5pc110_jpg_ctx));
+
+ ret = lock_jpg_mutex();
+
+ if (!ret) {
+ jpg_err("JPG Mutex Lock Fail\r\n");
+ unlock_jpg_mutex();
+ kfree(jpg_reg_ctx);
+ return FALSE;
+ }
+
+ if (instanceNo > MAX_INSTANCE_NUM) {
+ jpg_err("Instance Number error-JPEG is running, \
+ instance number is %d\n", instanceNo);
+ unlock_jpg_mutex();
+ kfree(jpg_reg_ctx);
+ return FALSE;
+ }
+
+ instanceNo++;
+
+ /* Initialize the limits of the driver */
+ jpg_reg_ctx->limits = &s3c_jpeg_limits;
+ jpg_reg_ctx->bufinfo = &s3c_jpeg_bufinfo;
+
+ unlock_jpg_mutex();
+
+ file->private_data = (struct s5pc110_jpg_ctx *)jpg_reg_ctx;
+
+ return 0;
+}
+
+
+static int s3c_jpeg_release(struct inode *inode, struct file *file)
+{
+ unsigned long ret;
+ struct s5pc110_jpg_ctx *jpg_reg_ctx;
+
+ jpg_dbg("JPG_Close\n");
+
+ jpg_reg_ctx = (struct s5pc110_jpg_ctx *)file->private_data;
+
+ if (!jpg_reg_ctx) {
+ jpg_err("JPG Invalid Input Handle\r\n");
+ return FALSE;
+ }
+
+ ret = lock_jpg_mutex();
+
+ if (!ret) {
+ jpg_err("JPG Mutex Lock Fail\r\n");
+ return FALSE;
+ }
+
+ if ((--instanceNo) < 0)
+ instanceNo = 0;
+
+ unlock_jpg_mutex();
+ kfree(jpg_reg_ctx);
+
+ return 0;
+}
+
+
+static ssize_t s3c_jpeg_write(struct file *file, const char *buf,
+ size_t count, loff_t *pos)
+{
+ return 0;
+}
+
+static ssize_t s3c_jpeg_read(struct file *file, char *buf,
+ size_t count, loff_t *pos)
+{
+ return 0;
+}
+
+static long s3c_jpeg_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct s5pc110_jpg_ctx *jpg_reg_ctx;
+ struct jpg_args param;
+ enum BOOL result = TRUE;
+ unsigned long ret;
+ int out;
+
+ jpg_reg_ctx = (struct s5pc110_jpg_ctx *)file->private_data;
+
+ if (!jpg_reg_ctx) {
+ jpg_err("JPG Invalid Input Handle\r\n");
+ return FALSE;
+ }
+
+ ret = lock_jpg_mutex();
+
+ if (!ret) {
+ jpg_err("JPG Mutex Lock Fail\r\n");
+ return FALSE;
+ }
+
+ switch (cmd) {
+ case IOCTL_JPG_DECODE:
+
+ jpg_dbg("IOCTL_JPEG_DECODE\n");
+
+ out = copy_from_user(&param, (struct jpg_args *)arg,
+ sizeof(struct jpg_args));
+
+ jpg_reg_ctx->jpg_data_addr = (unsigned int)jpg_data_base_addr;
+ jpg_reg_ctx->img_data_addr =
+ (unsigned int)jpg_data_base_addr
+ + jpg_reg_ctx->bufinfo->main_frame_start;
+
+ jpeg_clock_enable();
+ result = decode_jpg(jpg_reg_ctx, param.dec_param);
+ jpeg_clock_disable();
+
+ out = copy_to_user((void *)arg,
+ (void *)&param, sizeof(struct jpg_args));
+ break;
+
+ case IOCTL_JPG_ENCODE:
+
+ jpg_dbg("IOCTL_JPEG_ENCODE\n");
+
+ out = copy_from_user(&param, (struct jpg_args *)arg,
+ sizeof(struct jpg_args));
+
+ jpg_dbg("encode size :: width : %d hegiht : %d\n",
+ param.enc_param->width, param.enc_param->height);
+
+ jpeg_clock_enable();
+ if (param.enc_param->enc_type == JPG_MAIN) {
+ jpg_reg_ctx->jpg_data_addr =
+ (unsigned int)jpg_data_base_addr;
+ jpg_reg_ctx->img_data_addr =
+ (unsigned int)jpg_data_base_addr
+ + jpg_reg_ctx->bufinfo->main_frame_start;
+ jpg_dbg("enc_img_data_addr=0x%08x,"
+ "enc_jpg_data_addr=0x%08x\n",
+ jpg_reg_ctx->img_data_addr,
+ jpg_reg_ctx->jpg_data_addr);
+
+ result = encode_jpg(jpg_reg_ctx, param.enc_param);
+ } else {
+ jpg_reg_ctx->jpg_thumb_data_addr =
+ (unsigned int)jpg_data_base_addr
+ + jpg_reg_ctx->bufinfo->thumb_stream_start;
+ jpg_reg_ctx->img_thumb_data_addr =
+ (unsigned int)jpg_data_base_addr
+ + jpg_reg_ctx->bufinfo->thumb_frame_start;
+
+ result = encode_jpg(jpg_reg_ctx, param.thumb_enc_param);
+ }
+ jpeg_clock_disable();
+
+ out = copy_to_user((void *)arg, (void *)&param,
+ sizeof(struct jpg_args));
+ break;
+
+ case IOCTL_JPG_GET_STRBUF:
+ jpg_dbg("IOCTL_JPG_GET_STRBUF\n");
+ unlock_jpg_mutex();
+ return arg + jpg_reg_ctx->bufinfo->main_stream_start;
+
+ case IOCTL_JPG_GET_THUMB_STRBUF:
+ jpg_dbg("IOCTL_JPG_GET_THUMB_STRBUF\n");
+ unlock_jpg_mutex();
+ return arg + jpg_reg_ctx->bufinfo->thumb_stream_start;
+
+ case IOCTL_JPG_GET_FRMBUF:
+ jpg_dbg("IOCTL_JPG_GET_FRMBUF\n");
+ unlock_jpg_mutex();
+ return arg + jpg_reg_ctx->bufinfo->main_frame_start;
+
+ case IOCTL_JPG_GET_THUMB_FRMBUF:
+ jpg_dbg("IOCTL_JPG_GET_THUMB_FRMBUF\n");
+ unlock_jpg_mutex();
+ return arg + jpg_reg_ctx->bufinfo->thumb_frame_start;
+
+ case IOCTL_JPG_GET_PHY_FRMBUF:
+ jpg_dbg("IOCTL_JPG_GET_PHY_FRMBUF\n");
+ unlock_jpg_mutex();
+ return jpg_data_base_addr + jpg_reg_ctx->bufinfo->main_frame_start;
+
+ case IOCTL_JPG_GET_PHY_THUMB_FRMBUF:
+ jpg_dbg("IOCTL_JPG_GET_PHY_THUMB_FRMBUF\n");
+ unlock_jpg_mutex();
+ return jpg_data_base_addr + jpg_reg_ctx->bufinfo->thumb_frame_start;
+
+ default:
+ jpg_dbg("JPG Invalid ioctl : 0x%X\n", cmd);
+ }
+
+ unlock_jpg_mutex();
+
+ return result;
+}
+
+static unsigned int s3c_jpeg_poll(struct file *file, poll_table *wait)
+{
+ unsigned int mask = 0;
+
+ jpg_dbg("enter poll\n");
+ poll_wait(file, &wait_queue_jpeg, wait);
+ mask = POLLOUT | POLLWRNORM;
+ return mask;
+}
+
+int s3c_jpeg_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ unsigned long size = vma->vm_end - vma->vm_start;
+ unsigned long max_size;
+ unsigned long page_frame_no;
+
+ page_frame_no = __phys_to_pfn(jpg_data_base_addr);
+
+ max_size = jpg_reserved_mem_size;
+
+ if (size > max_size)
+ return -EINVAL;
+
+ vma->vm_flags |= VM_RESERVED | VM_IO;
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ if (remap_pfn_range(vma, vma->vm_start, page_frame_no, size,
+ vma->vm_page_prot)) {
+ jpg_err("jpeg remap error");
+ return -EAGAIN;
+ }
+
+ return 0;
+}
+
+
+static const struct file_operations jpeg_fops = {
+ .owner = THIS_MODULE,
+ .open = s3c_jpeg_open,
+ .release = s3c_jpeg_release,
+ .unlocked_ioctl = s3c_jpeg_ioctl,
+ .read = s3c_jpeg_read,
+ .write = s3c_jpeg_write,
+ .mmap = s3c_jpeg_mmap,
+ .poll = s3c_jpeg_poll,
+};
+
+
+static struct miscdevice s3c_jpeg_miscdev = {
+ .minor = 254,
+ .name = "s3c-jpg",
+ .fops = &jpeg_fops
+};
+
+void s3c_jpg_plat_init(struct s3c_platform_jpeg *pdata)
+{
+ unsigned int main_pixels;
+ unsigned int thumb_pixels;
+
+ s3c_jpeg_limits.max_main_width = pdata->max_main_width;
+ s3c_jpeg_limits.max_main_height = pdata->max_main_height;
+ s3c_jpeg_limits.max_thumb_width = pdata->max_thumb_width;
+ s3c_jpeg_limits.max_thumb_height = pdata->max_thumb_height;
+
+ main_pixels = s3c_jpeg_limits.max_main_width *
+ s3c_jpeg_limits.max_main_height;
+ thumb_pixels = s3c_jpeg_limits.max_thumb_width *
+ s3c_jpeg_limits.max_thumb_height;
+
+ s3c_jpeg_bufinfo.main_stream_size = ALIGN(main_pixels, PAGE_SIZE);
+ /* Assuming JPEG V2 uses YCBCR422 output format */
+ s3c_jpeg_bufinfo.main_frame_size = ALIGN(main_pixels * 2, PAGE_SIZE);
+
+ s3c_jpeg_bufinfo.thumb_stream_size = ALIGN(thumb_pixels, PAGE_SIZE);
+ s3c_jpeg_bufinfo.thumb_frame_size = ALIGN(thumb_pixels * 2, PAGE_SIZE);
+
+ s3c_jpeg_bufinfo.total_buf_size = s3c_jpeg_bufinfo.main_stream_size +
+ s3c_jpeg_bufinfo.thumb_stream_size +
+ s3c_jpeg_bufinfo.main_frame_size +
+ s3c_jpeg_bufinfo.thumb_frame_size;
+
+ s3c_jpeg_bufinfo.main_stream_start = 0;
+ s3c_jpeg_bufinfo.thumb_stream_start =
+ s3c_jpeg_bufinfo.main_stream_start +
+ s3c_jpeg_bufinfo.main_stream_size;
+ s3c_jpeg_bufinfo.main_frame_start =
+ s3c_jpeg_bufinfo.thumb_stream_start +
+ s3c_jpeg_bufinfo.thumb_stream_size;
+ s3c_jpeg_bufinfo.thumb_frame_start =
+ s3c_jpeg_bufinfo.main_frame_start +
+ s3c_jpeg_bufinfo.main_frame_size;
+
+ jpg_dbg("Resolution: Main (%4d x %4d), Thumb (%4d x %4d)\n", \
+ s3c_jpeg_limits.max_main_width, \
+ s3c_jpeg_limits.max_main_height, \
+ s3c_jpeg_limits.max_thumb_width, \
+ s3c_jpeg_limits.max_thumb_height);
+
+ jpg_dbg("JPG Stream: Main(%d bytes @ 0x%x), Thumb(%d bytes @ 0x%x)\n",\
+ s3c_jpeg_bufinfo.main_stream_size, \
+ s3c_jpeg_bufinfo.main_stream_start, \
+ s3c_jpeg_bufinfo.thumb_stream_size, \
+ s3c_jpeg_bufinfo.thumb_stream_start);
+
+ jpg_dbg("YUV frame: Main(%d bytes @ 0x%x), Thumb(%d bytes @ 0x%x)\n",\
+ s3c_jpeg_bufinfo.main_frame_size, \
+ s3c_jpeg_bufinfo.main_frame_start, \
+ s3c_jpeg_bufinfo.thumb_frame_size, \
+ s3c_jpeg_bufinfo.thumb_frame_start);
+
+ jpg_dbg("Total buffer size : %d bytes\n", \
+ s3c_jpeg_bufinfo.total_buf_size);
+
+}
+
+static int s3c_jpeg_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ static int size;
+ static int ret;
+ struct mutex *h_mutex;
+ struct s3c_platform_jpeg *pdata;
+
+ pdata = to_jpeg_plat(&pdev->dev);
+
+ if (!pdata) {
+ jpg_err("Err: Platform data is not setup\n");
+ return -EINVAL;
+ }
+
+ s3c_jpg_plat_init(pdata);
+
+ if (s3c_jpeg_bufinfo.total_buf_size > jpg_reserved_mem_size) {
+ jpg_err("Err: Reserved memory (%d) is less than"
+ "required memory (%d)\n", \
+ jpg_reserved_mem_size, \
+ s3c_jpeg_bufinfo.total_buf_size);
+ return -ENOMEM;
+ }
+
+ /* Get jpeg power domain regulator */
+ jpeg_pd_regulator = regulator_get(&pdev->dev, "pd");
+ if (IS_ERR(jpeg_pd_regulator)) {
+ jpg_err("%s: failed to get resource %s\n",
+ __func__, "s3c-jpg");
+ return PTR_ERR(jpeg_pd_regulator);
+ }
+
+ s3c_jpeg_clk = clk_get(&pdev->dev, "jpeg");
+
+ if (IS_ERR(s3c_jpeg_clk)) {
+ jpg_err("failed to find jpeg clock source\n");
+ return -ENOENT;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ if (res == NULL) {
+ jpg_err("failed to get memory region resouce\n");
+ return -ENOENT;
+ }
+
+ size = (res->end - res->start) + 1;
+ s3c_jpeg_mem = request_mem_region(res->start, size, pdev->name);
+
+ if (s3c_jpeg_mem == NULL) {
+ jpg_err("failed to get memory region\n");
+ return -ENOENT;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+
+ if (res == NULL) {
+ jpg_err("failed to get irq resource\n");
+ return -ENOENT;
+ }
+
+ irq_no = res->start;
+ ret = request_irq(res->start, (void *)s3c_jpeg_irq, 0,
+ pdev->name, pdev);
+
+ if (ret != 0) {
+ jpg_err("failed to install irq (%d)\n", ret);
+ return ret;
+ }
+
+ s3c_jpeg_base = ioremap(s3c_jpeg_mem->start, size);
+
+ if (s3c_jpeg_base == 0) {
+ jpg_err("failed to ioremap() region\n");
+ return -EINVAL;
+ }
+
+ init_waitqueue_head(&wait_queue_jpeg);
+
+ jpg_dbg("JPG_Init\n");
+
+ /* Mutex initialization */
+ h_mutex = create_jpg_mutex();
+
+ if (h_mutex == NULL) {
+ jpg_err("JPG Mutex Initialize error\r\n");
+ return FALSE;
+ }
+
+ ret = lock_jpg_mutex();
+
+ if (!ret) {
+ jpg_err("JPG Mutex Lock Fail\n");
+ return FALSE;
+ }
+
+ instanceNo = 0;
+
+ unlock_jpg_mutex();
+
+ ret = misc_register(&s3c_jpeg_miscdev);
+
+ return 0;
+}
+
+static int s3c_jpeg_remove(struct platform_device *dev)
+{
+ if (s3c_jpeg_mem != NULL) {
+ release_resource(s3c_jpeg_mem);
+ kfree(s3c_jpeg_mem);
+ s3c_jpeg_mem = NULL;
+ }
+
+ free_irq(irq_no, dev);
+ misc_deregister(&s3c_jpeg_miscdev);
+ return 0;
+}
+
+static struct platform_driver s3c_jpeg_driver = {
+ .probe = s3c_jpeg_probe,
+ .remove = s3c_jpeg_remove,
+ .shutdown = NULL,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "s3c-jpg",
+ },
+};
+
+static char banner[] __initdata =
+ KERN_INFO "S3C JPEG Driver, (c) 2007 Samsung Electronics\n";
+
+static int __init s3c_jpeg_init(void)
+{
+ printk(banner);
+ printk(KERN_INFO "JPEG driver for S5PV210\n");
+ return platform_driver_register(&s3c_jpeg_driver);
+}
+
+static void __exit s3c_jpeg_exit(void)
+{
+ unsigned long ret;
+
+ jpg_dbg("JPG_Deinit\n");
+
+ ret = lock_jpg_mutex();
+
+ if (!ret)
+ jpg_err("JPG Mutex Lock Fail\r\n");
+
+ unlock_jpg_mutex();
+
+ delete_jpg_mutex();
+
+ platform_driver_unregister(&s3c_jpeg_driver);
+ jpg_dbg("S3C JPEG driver module exit\n");
+}
+
+module_init(s3c_jpeg_init);
+module_exit(s3c_jpeg_exit);
+
+MODULE_AUTHOR("Peter, Oh");
+MODULE_DESCRIPTION("S3C JPEG Encoder/Decoder Device Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/samsung/jpeg_v2/s3c-jpeg.h b/drivers/media/video/samsung/jpeg_v2/s3c-jpeg.h
new file mode 100644
index 0000000..dd5bc4c
--- /dev/null
+++ b/drivers/media/video/samsung/jpeg_v2/s3c-jpeg.h
@@ -0,0 +1,36 @@
+/* linux/drivers/media/video/samsung/jpeg_v2/s3c-jpeg.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Header file for Samsung Jpeg Interface driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+
+#ifndef __JPEG_DRIVER_H__
+#define __JPEG_DRIVER_H__
+
+
+#define MAX_INSTANCE_NUM 1
+#define MAX_PROCESSING_THRESHOLD 1000 /* 1Sec */
+
+#define JPEG_IOCTL_MAGIC 'J'
+
+#define IOCTL_JPG_DECODE _IO(JPEG_IOCTL_MAGIC, 1)
+#define IOCTL_JPG_ENCODE _IO(JPEG_IOCTL_MAGIC, 2)
+#define IOCTL_JPG_GET_STRBUF _IO(JPEG_IOCTL_MAGIC, 3)
+#define IOCTL_JPG_GET_FRMBUF _IO(JPEG_IOCTL_MAGIC, 4)
+#define IOCTL_JPG_GET_THUMB_STRBUF _IO(JPEG_IOCTL_MAGIC, 5)
+#define IOCTL_JPG_GET_THUMB_FRMBUF _IO(JPEG_IOCTL_MAGIC, 6)
+#define IOCTL_JPG_GET_PHY_FRMBUF _IO(JPEG_IOCTL_MAGIC, 7)
+#define IOCTL_JPG_GET_PHY_THUMB_FRMBUF _IO(JPEG_IOCTL_MAGIC, 8)
+#define JPG_CLOCK_DIVIDER_RATIO_QUARTER 4
+
+/* Driver Helper function */
+#define to_jpeg_plat(d) (to_platform_device(d)->dev.platform_data)
+
+#endif /*__JPEG_DRIVER_H__*/
diff --git a/drivers/media/video/samsung/mfc50/Kconfig b/drivers/media/video/samsung/mfc50/Kconfig
new file mode 100644
index 0000000..11d17c2
--- /dev/null
+++ b/drivers/media/video/samsung/mfc50/Kconfig
@@ -0,0 +1,23 @@
+#
+# Configuration for Multi Format Codecs (MFC)
+#
+#
+config VIDEO_MFC50
+ bool "Samsung MFC (Multi Format Codec - FIMV 5.0) Driver"
+ depends on VIDEO_SAMSUNG && CPU_S5PV210
+ default n
+ select S5P_SETUP_MFC
+ select S5P_DEV_MFC
+ ---help---
+ This is a Samsung Multi Format Codecs (MFC) FIMV V5.0 - driver for Samsung S5PC110
+
+config VIDEO_MFC_MAX_INSTANCE
+ int "Maximum size of MFC instance (1-4)"
+ range 1 4
+ depends on VIDEO_MFC50
+ default 4
+
+config VIDEO_MFC50_DEBUG
+ bool "print MFC debug message"
+ depends on VIDEO_MFC50
+ default n
diff --git a/drivers/media/video/samsung/mfc50/Makefile b/drivers/media/video/samsung/mfc50/Makefile
new file mode 100644
index 0000000..31f0499
--- /dev/null
+++ b/drivers/media/video/samsung/mfc50/Makefile
@@ -0,0 +1,7 @@
+obj-$(CONFIG_VIDEO_MFC50) += mfc.o mfc_buffer_manager.o mfc_intr.o mfc_memory.o mfc_opr.o mfc_shared_mem.o
+
+ifeq ($(CONFIG_VIDEO_MFC50_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
+
+#EXTRA_CFLAGS += -DMFC_REQUEST_TIME
diff --git a/drivers/media/video/samsung/mfc50/mfc.c b/drivers/media/video/samsung/mfc50/mfc.c
new file mode 100755
index 0000000..17a9da8
--- /dev/null
+++ b/drivers/media/video/samsung/mfc50/mfc.c
@@ -0,0 +1,823 @@
+/*
+ * drivers/media/video/samsung/mfc50/mfc.c
+ *
+ * C file for Samsung MFC (Multi Function Codec - FIMV) driver
+ *
+ * Jaeryul Oh, Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * Change Logs
+ * 2009.09.14 - Beautify source code (Key Young, Park)
+ * 2009.09.21 - Implement clock & power gating.
+ * including suspend & resume fuction. (Key Young, Park)
+ * 2009.10.08 - Apply 9/30 firmware (Key Young, Park)
+ * 2009.10.09 - Add error handling rountine (Key Young, Park)
+ * 2009.10.13 - move mfc interrupt routine into mfc_irq.c (Key Young, Park)
+ * 2009.10.27 - Update firmware (2009.10.15) (Key Young, Park)
+ * 2009.11.04 - get physical address via mfc_allocate_buffer (Key Young, Park)
+ * 2009.11.04 - remove mfc_common.[ch]
+ * seperate buffer alloc & set (Key Young, Park)
+ * 2009.11.24 - add state check when decoding & encoding (Key Young, Park)
+ *
+ * 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/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/wait.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+
+#include <linux/sched.h>
+#include <linux/firmware.h>
+
+#include <linux/io.h>
+#include <linux/uaccess.h>
+
+#include <plat/media.h>
+#include <mach/media.h>
+#include <plat/mfc.h>
+
+#include "mfc_interface.h"
+#include "mfc_logmsg.h"
+#include "mfc_opr.h"
+#include "mfc_memory.h"
+#include "mfc_buffer_manager.h"
+#include "mfc_intr.h"
+
+#define MFC_FW_NAME "samsung_mfc_fw.bin"
+
+static struct resource *mfc_mem;
+static struct mutex mfc_mutex;
+static struct clk *mfc_sclk;
+static struct regulator *mfc_pd_regulator;
+const struct firmware *mfc_fw_info;
+
+static int mfc_open(struct inode *inode, struct file *file)
+{
+ struct mfc_inst_ctx *mfc_ctx;
+ int ret;
+
+ mutex_lock(&mfc_mutex);
+
+ if (!mfc_is_running()) {
+ /* Turn on mfc power domain regulator */
+ ret = regulator_enable(mfc_pd_regulator);
+ if (ret < 0) {
+ mfc_err("MFC_RET_POWER_ENABLE_FAIL\n");
+ ret = -EINVAL;
+ goto err_open;
+ }
+
+ clk_enable(mfc_sclk);
+
+ mfc_load_firmware(mfc_fw_info->data, mfc_fw_info->size);
+
+ if (mfc_init_hw() != true) {
+ clk_disable(mfc_sclk);
+ ret = -ENODEV;
+ goto err_regulator;
+ }
+ clk_disable(mfc_sclk);
+ }
+
+ mfc_ctx = (struct mfc_inst_ctx *)kmalloc(sizeof(struct mfc_inst_ctx), GFP_KERNEL);
+ if (mfc_ctx == NULL) {
+ mfc_err("MFCINST_MEMORY_ALLOC_FAIL\n");
+ ret = -ENOMEM;
+ goto err_regulator;
+ }
+
+ memset(mfc_ctx, 0, sizeof(struct mfc_inst_ctx));
+
+ /* get the inst no allocating some part of memory among reserved memory */
+ mfc_ctx->mem_inst_no = mfc_get_mem_inst_no();
+ mfc_ctx->InstNo = -1;
+ if (mfc_ctx->mem_inst_no < 0) {
+ mfc_err("MFCINST_INST_NUM_EXCEEDED\n");
+ ret = -EPERM;
+ goto err_mem_inst;
+ }
+
+ if (mfc_set_state(mfc_ctx, MFCINST_STATE_OPENED) < 0) {
+ mfc_err("MFCINST_ERR_STATE_INVALID\n");
+ ret = -ENODEV;
+ goto err_set_state;
+ }
+
+ /* Decoder only */
+ mfc_ctx->extraDPB = MFC_MAX_EXTRA_DPB;
+ mfc_ctx->FrameType = MFC_RET_FRAME_NOT_SET;
+
+ file->private_data = mfc_ctx;
+
+ mutex_unlock(&mfc_mutex);
+
+ return 0;
+
+err_set_state:
+ mfc_return_mem_inst_no(mfc_ctx->mem_inst_no);
+err_mem_inst:
+ kfree(mfc_ctx);
+err_regulator:
+ if (!mfc_is_running()) {
+ /* Turn off mfc power domain regulator */
+ ret = regulator_disable(mfc_pd_regulator);
+ if (ret < 0)
+ mfc_err("MFC_RET_POWER_DISABLE_FAIL\n");
+ }
+err_open:
+ mutex_unlock(&mfc_mutex);
+
+ return ret;
+}
+
+static int mfc_release(struct inode *inode, struct file *file)
+{
+ struct mfc_inst_ctx *mfc_ctx;
+ int ret;
+
+ mutex_lock(&mfc_mutex);
+
+ mfc_ctx = (struct mfc_inst_ctx *)file->private_data;
+ if (mfc_ctx == NULL) {
+ mfc_err("MFCINST_ERR_INVALID_PARAM\n");
+ ret = -EIO;
+ goto out_release;
+ }
+
+ mfc_release_all_buffer(mfc_ctx->mem_inst_no);
+ mfc_merge_fragment(mfc_ctx->mem_inst_no);
+
+ mfc_return_mem_inst_no(mfc_ctx->mem_inst_no);
+
+ /* In case of no instance, we should not release codec instance */
+ if (mfc_ctx->InstNo >= 0) {
+ clk_enable(mfc_sclk);
+ mfc_return_inst_no(mfc_ctx->InstNo, mfc_ctx->MfcCodecType);
+ clk_disable(mfc_sclk);
+ }
+
+ kfree(mfc_ctx);
+
+ ret = 0;
+
+ if (!mfc_is_running()) {
+ /* Turn off mfc power domain regulator */
+ ret = regulator_disable(mfc_pd_regulator);
+ if (ret < 0) {
+ mfc_err("MFC_RET_POWER_DISABLE_FAIL\n");
+ goto out_release;
+ }
+ }
+
+out_release:
+
+ mutex_unlock(&mfc_mutex);
+ return ret;
+}
+
+static long mfc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ int ret, ex_ret;
+ struct mfc_inst_ctx *mfc_ctx = NULL;
+ struct mfc_common_args in_param;
+
+ mutex_lock(&mfc_mutex);
+ clk_enable(mfc_sclk);
+
+ ret = copy_from_user(&in_param, (struct mfc_common_args *)arg, sizeof(struct mfc_common_args));
+ if (ret < 0) {
+ mfc_err("Inparm copy error\n");
+ ret = -EIO;
+ in_param.ret_code = MFCINST_ERR_INVALID_PARAM;
+ goto out_ioctl;
+ }
+
+ mfc_ctx = (struct mfc_inst_ctx *)file->private_data;
+ mutex_unlock(&mfc_mutex);
+
+ switch (cmd) {
+ case IOCTL_MFC_ENC_INIT:
+ mutex_lock(&mfc_mutex);
+
+ if (mfc_set_state(mfc_ctx, MFCINST_STATE_ENC_INITIALIZE) < 0) {
+ mfc_err("MFCINST_ERR_STATE_INVALID\n");
+ in_param.ret_code = MFCINST_ERR_STATE_INVALID;
+ ret = -EINVAL;
+ mutex_unlock(&mfc_mutex);
+ break;
+ }
+
+ /* MFC encode init */
+ in_param.ret_code = mfc_init_encode(mfc_ctx, &(in_param.args));
+ ret = in_param.ret_code;
+ mutex_unlock(&mfc_mutex);
+ break;
+
+ case IOCTL_MFC_ENC_EXE:
+ mutex_lock(&mfc_mutex);
+ if (mfc_ctx->MfcState < MFCINST_STATE_ENC_INITIALIZE) {
+ mfc_err("MFCINST_ERR_STATE_INVALID\n");
+ in_param.ret_code = MFCINST_ERR_STATE_INVALID;
+ ret = -EINVAL;
+ mutex_unlock(&mfc_mutex);
+ break;
+ }
+
+ if (mfc_set_state(mfc_ctx, MFCINST_STATE_ENC_EXE) < 0) {
+ mfc_err("MFCINST_ERR_STATE_INVALID\n");
+ in_param.ret_code = MFCINST_ERR_STATE_INVALID;
+ ret = -EINVAL;
+ mutex_unlock(&mfc_mutex);
+ break;
+ }
+
+ in_param.ret_code = mfc_exe_encode(mfc_ctx, &(in_param.args));
+ ret = in_param.ret_code;
+ mutex_unlock(&mfc_mutex);
+ break;
+
+ case IOCTL_MFC_DEC_INIT:
+ mutex_lock(&mfc_mutex);
+ if (mfc_set_state(mfc_ctx, MFCINST_STATE_DEC_INITIALIZE) < 0) {
+ mfc_err("MFCINST_ERR_STATE_INVALID\n");
+ in_param.ret_code = MFCINST_ERR_STATE_INVALID;
+ ret = -EINVAL;
+ mutex_unlock(&mfc_mutex);
+ break;
+ }
+
+ /* MFC decode init */
+ in_param.ret_code = mfc_init_decode(mfc_ctx, &(in_param.args));
+ if (in_param.ret_code < 0) {
+ ret = in_param.ret_code;
+ mutex_unlock(&mfc_mutex);
+ break;
+ }
+
+ if (in_param.args.dec_init.out_dpb_cnt <= 0) {
+ mfc_err("MFC out_dpb_cnt error\n");
+ mutex_unlock(&mfc_mutex);
+ break;
+ }
+
+ mutex_unlock(&mfc_mutex);
+ break;
+
+ case IOCTL_MFC_DEC_EXE:
+ mutex_lock(&mfc_mutex);
+ if (mfc_ctx->MfcState < MFCINST_STATE_DEC_INITIALIZE) {
+ mfc_err("MFCINST_ERR_STATE_INVALID\n");
+ in_param.ret_code = MFCINST_ERR_STATE_INVALID;
+ ret = -EINVAL;
+ mutex_unlock(&mfc_mutex);
+ break;
+ }
+
+ if (mfc_set_state(mfc_ctx, MFCINST_STATE_DEC_EXE) < 0) {
+ mfc_err("MFCINST_ERR_STATE_INVALID\n");
+ in_param.ret_code = MFCINST_ERR_STATE_INVALID;
+ ret = -EINVAL;
+ mutex_unlock(&mfc_mutex);
+ break;
+ }
+
+ in_param.ret_code = mfc_exe_decode(mfc_ctx, &(in_param.args));
+ ret = in_param.ret_code;
+ mutex_unlock(&mfc_mutex);
+ break;
+
+ case IOCTL_MFC_GET_CONFIG:
+ mutex_lock(&mfc_mutex);
+ if (mfc_ctx->MfcState < MFCINST_STATE_DEC_INITIALIZE) {
+ mfc_err("MFCINST_ERR_STATE_INVALID\n");
+ in_param.ret_code = MFCINST_ERR_STATE_INVALID;
+ ret = -EINVAL;
+ mutex_unlock(&mfc_mutex);
+ break;
+ }
+
+ in_param.ret_code = mfc_get_config(mfc_ctx, &(in_param.args));
+ ret = in_param.ret_code;
+ mutex_unlock(&mfc_mutex);
+ break;
+
+ case IOCTL_MFC_SET_CONFIG:
+ mutex_lock(&mfc_mutex);
+ in_param.ret_code = mfc_set_config(mfc_ctx, &(in_param.args));
+ ret = in_param.ret_code;
+ mutex_unlock(&mfc_mutex);
+ break;
+
+ case IOCTL_MFC_GET_IN_BUF:
+ mutex_lock(&mfc_mutex);
+ if (mfc_ctx->MfcState < MFCINST_STATE_OPENED) {
+ mfc_err("MFCINST_ERR_STATE_INVALID\n");
+ in_param.ret_code = MFCINST_ERR_STATE_INVALID;
+ ret = -EINVAL;
+ mutex_unlock(&mfc_mutex);
+ break;
+ }
+
+ if (in_param.args.mem_alloc.buff_size <= 0) {
+ mfc_err("MFCINST_ERR_INVALID_PARAM\n");
+ in_param.ret_code = MFCINST_ERR_INVALID_PARAM;
+ ret = -EINVAL;
+ mutex_unlock(&mfc_mutex);
+ break;
+ }
+
+ if ((is_dec_codec(in_param.args.mem_alloc.codec_type)) &&
+ (in_param.args.mem_alloc.buff_size < (CPB_BUF_SIZE + DESC_BUF_SIZE))) {
+ in_param.args.mem_alloc.buff_size = CPB_BUF_SIZE + DESC_BUF_SIZE;
+ }
+
+ /* Buffer manager should have 64KB alignment for MFC base addresses */
+ in_param.args.mem_alloc.buff_size = ALIGN_TO_8KB(in_param.args.mem_alloc.buff_size);
+
+ /* allocate stream buf for decoder & current YC buf for encoder */
+ if (is_dec_codec(in_param.args.mem_alloc.codec_type))
+ in_param.ret_code = mfc_allocate_buffer(mfc_ctx, &in_param.args, 0);
+ else
+ in_param.ret_code = mfc_allocate_buffer(mfc_ctx, &in_param.args, 1);
+
+ mfc_ctx->desc_buff_paddr = in_param.args.mem_alloc.out_paddr + CPB_BUF_SIZE;
+
+ ret = in_param.ret_code;
+ mutex_unlock(&mfc_mutex);
+ break;
+
+ case IOCTL_MFC_FREE_BUF:
+ mutex_lock(&mfc_mutex);
+ if (mfc_ctx->MfcState < MFCINST_STATE_OPENED) {
+ mfc_err("MFCINST_ERR_STATE_INVALID\n");
+ in_param.ret_code = MFCINST_ERR_STATE_INVALID;
+ ret = -EINVAL;
+ mutex_unlock(&mfc_mutex);
+ break;
+ }
+
+ in_param.ret_code = mfc_release_buffer((unsigned char *)in_param.args.mem_free.u_addr);
+ ret = in_param.ret_code;
+ mutex_unlock(&mfc_mutex);
+ break;
+
+ case IOCTL_MFC_GET_PHYS_ADDR:
+ mutex_lock(&mfc_mutex);
+ mfc_debug("IOCTL_MFC_GET_PHYS_ADDR\n");
+
+ if (mfc_ctx->MfcState < MFCINST_STATE_OPENED) {
+ mfc_err("MFCINST_ERR_STATE_INVALID\n");
+ in_param.ret_code = MFCINST_ERR_STATE_INVALID;
+ ret = -EINVAL;
+ mutex_unlock(&mfc_mutex);
+ break;
+ }
+
+ in_param.ret_code = mfc_get_phys_addr(mfc_ctx, &(in_param.args));
+ ret = in_param.ret_code;
+ mutex_unlock(&mfc_mutex);
+ break;
+
+ case IOCTL_MFC_GET_MMAP_SIZE:
+
+ if (mfc_ctx->MfcState < MFCINST_STATE_OPENED) {
+ mfc_err("MFC_RET_STATE_INVALID\n");
+ in_param.ret_code = MFCINST_ERR_STATE_INVALID;
+ ret = -EINVAL;
+
+ break;
+ }
+
+ in_param.ret_code = MFCINST_RET_OK;
+ ret = mfc_ctx->port0_mmap_size;
+
+ break;
+
+ case IOCTL_MFC_BUF_CACHE:
+ mutex_lock(&mfc_mutex);
+
+ in_param.ret_code = MFCINST_RET_OK;
+ mfc_ctx->buf_type = in_param.args.buf_type;
+
+ mutex_unlock(&mfc_mutex);
+ break;
+
+ default:
+ mfc_err("Requested ioctl command is not defined. (ioctl cmd=0x%08x)\n", cmd);
+ in_param.ret_code = MFCINST_ERR_INVALID_PARAM;
+ ret = -EINVAL;
+ }
+
+out_ioctl:
+ clk_disable(mfc_sclk);
+
+ ex_ret = copy_to_user((struct mfc_common_args *)arg, &in_param, sizeof(struct mfc_common_args));
+ if (ex_ret < 0) {
+ mfc_err("Outparm copy to user error\n");
+ ret = -EIO;
+ }
+
+ mfc_debug_L0("---------------IOCTL return = %d ---------------\n", ret);
+
+ return ret;
+}
+
+static int mfc_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ unsigned long vir_size = vma->vm_end - vma->vm_start;
+ unsigned long phy_size, firmware_size;
+ unsigned long page_frame_no = 0;
+ struct mfc_inst_ctx *mfc_ctx;
+
+ mfc_debug("vma->vm_start = 0x%08x, vma->vm_end = 0x%08x\n",
+ (unsigned int)vma->vm_start,
+ (unsigned int)vma->vm_end);
+ mfc_debug("vma->vm_end - vma->vm_start = %ld\n", vir_size);
+
+ mfc_ctx = (struct mfc_inst_ctx *)filp->private_data;
+
+ firmware_size = mfc_get_port0_buff_paddr() - mfc_get_fw_buff_paddr();
+ phy_size = (unsigned long)(mfc_port0_memsize - firmware_size + mfc_port1_memsize);
+
+ /* if memory size required from appl. mmap() is bigger than max data memory
+ * size allocated in the driver */
+ if (vir_size > phy_size) {
+ mfc_err("virtual requested mem(%ld) is bigger than physical mem(%ld)\n",
+ vir_size, phy_size);
+ return -EINVAL;
+ }
+
+ mfc_ctx->port0_mmap_size = (vir_size / 2);
+
+ vma->vm_flags |= VM_RESERVED | VM_IO;
+ if (mfc_ctx->buf_type != MFC_BUFFER_CACHE)
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ /*
+ * port0 mapping for stream buf & frame buf (chroma + MV)
+ */
+ page_frame_no = __phys_to_pfn(mfc_get_port0_buff_paddr());
+ if (remap_pfn_range(vma, vma->vm_start, page_frame_no,
+ mfc_ctx->port0_mmap_size, vma->vm_page_prot)) {
+ mfc_err("mfc remap port0 error\n");
+ return -EAGAIN;
+ }
+
+ vma->vm_flags |= VM_RESERVED | VM_IO;
+ if (mfc_ctx->buf_type != MFC_BUFFER_CACHE)
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ /*
+ * port1 mapping for frame buf (luma)
+ */
+ page_frame_no = __phys_to_pfn(mfc_get_port1_buff_paddr());
+ if (remap_pfn_range(vma, vma->vm_start + mfc_ctx->port0_mmap_size,
+ page_frame_no, vir_size - mfc_ctx->port0_mmap_size, vma->vm_page_prot)) {
+ mfc_err("mfc remap port1 error\n");
+ return -EAGAIN;
+ }
+
+ mfc_debug("virtual requested mem = %ld, physical reserved data mem = %ld\n", vir_size, phy_size);
+
+ return 0;
+}
+
+static const struct file_operations mfc_fops = {
+ .owner = THIS_MODULE,
+ .open = mfc_open,
+ .release = mfc_release,
+ .unlocked_ioctl = mfc_ioctl,
+ .mmap = mfc_mmap
+};
+
+
+static struct miscdevice mfc_miscdev = {
+ .minor = 252,
+ .name = "s3c-mfc",
+ .fops = &mfc_fops,
+};
+
+static void mfc_firmware_request_complete_handler(const struct firmware *fw,
+ void *context)
+{
+ if (fw != NULL) {
+ mfc_load_firmware(fw->data, fw->size);
+ mfc_fw_info = fw;
+ } else {
+ mfc_err("failed to load MFC F/W, MFC will not working\n");
+ }
+}
+
+static int mfc_probe(struct platform_device *pdev)
+{
+ struct s3c_platform_mfc *pdata;
+ struct resource *res;
+ size_t size;
+ int ret;
+ unsigned int mfc_port1_alloc_paddr;
+
+ if (!pdev || !pdev->dev.platform_data) {
+ dev_err(&pdev->dev, "Unable to probe mfc!\n");
+ return -1;
+ }
+
+ pdata = pdev->dev.platform_data;
+
+ /* mfc clock enable should be here */
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL) {
+ dev_err(&pdev->dev, "failed to get memory region resource\n");
+ ret = -ENOENT;
+ goto probe_out;
+ }
+
+ /* 60K is required for mfc register (0x0 ~ 0xe008) */
+ size = (res->end - res->start) + 1;
+ mfc_mem = request_mem_region(res->start, size, pdev->name);
+ if (mfc_mem == NULL) {
+ dev_err(&pdev->dev, "failed to get memory region\n");
+ ret = -ENOENT;
+ goto err_mem_req;
+ }
+
+ mfc_sfr_base_vaddr = ioremap(mfc_mem->start, mfc_mem->end - mfc_mem->start + 1);
+ if (mfc_sfr_base_vaddr == NULL) {
+ dev_err(&pdev->dev, "failed to ioremap address region\n");
+ ret = -ENOENT;
+ goto err_mem_map;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (res == NULL) {
+ dev_err(&pdev->dev, "failed to get irq resource\n");
+ ret = -ENOENT;
+ goto err_irq_res;
+ }
+
+#if !defined(MFC_POLLING)
+ ret = request_irq(res->start, mfc_irq, IRQF_DISABLED, pdev->name, pdev);
+ if (ret != 0) {
+ dev_err(&pdev->dev, "failed to install irq (%d)\n", ret);
+ goto err_irq_req;
+ }
+#endif
+
+ mutex_init(&mfc_mutex);
+
+ /*
+ * buffer memory secure
+ */
+ mfc_port0_base_paddr =(unsigned int)pdata->buf_phy_base[0];
+ mfc_port0_memsize = (unsigned int)pdata->buf_phy_size[0];
+
+ mfc_debug(" mfc_port0_base_paddr= 0x%x \n", mfc_port0_base_paddr);
+ mfc_debug(" mfc_port0_memsize = 0x%x \n", mfc_port0_memsize);
+
+ mfc_port0_base_paddr = ALIGN_TO_128KB(mfc_port0_base_paddr);
+ mfc_port0_base_vaddr = phys_to_virt(mfc_port0_base_paddr);
+
+ if (mfc_port0_base_vaddr == NULL) {
+ mfc_err("fail to mapping port0 buffer\n");
+ ret = -EPERM;
+ goto err_vaddr_map;
+ }
+
+ mfc_port1_alloc_paddr = (unsigned int)pdata->buf_phy_base[1];
+ mfc_port1_memsize = (unsigned int)pdata->buf_phy_size[1];
+
+ mfc_port1_base_paddr = (unsigned int)s5p_get_media_membase_bank(1);
+ mfc_port1_base_paddr = ALIGN_TO_128KB(mfc_port1_base_paddr);
+
+ mfc_debug(" mfc_port1_base_paddr= 0x%x \n", mfc_port1_base_paddr);
+ mfc_debug(" mfc_port1_memsize = 0x%x \n", mfc_port1_memsize);
+
+ mfc_port1_alloc_paddr = ALIGN_TO_128KB(mfc_port1_alloc_paddr);
+ mfc_port1_base_vaddr = phys_to_virt(mfc_port1_alloc_paddr);
+
+ if (mfc_port1_base_vaddr == NULL) {
+ mfc_err("fail to mapping port1 buffer\n");
+ ret = -EPERM;
+ goto err_vaddr_map;
+ }
+
+ mfc_set_port1_buff_paddr(mfc_port1_alloc_paddr);
+
+ mfc_debug("mfc_port0_base_paddr = 0x%08x, mfc_port1_base_paddr = 0x%08x <<\n",
+ (unsigned int)mfc_port0_base_paddr, (unsigned int)mfc_port1_base_paddr);
+ mfc_debug("mfc_port0_base_vaddr = 0x%08x, mfc_port1_base_vaddr = 0x%08x <<\n",
+ (unsigned int)mfc_port0_base_vaddr, (unsigned int)mfc_port1_base_vaddr);
+ mfc_debug("mfc_port1_alloc_paddr = 0x%08x <<\n", (unsigned int)mfc_port1_alloc_paddr);
+
+ /* Get mfc power domain regulator */
+ mfc_pd_regulator = regulator_get(&pdev->dev, "pd");
+ if (IS_ERR(mfc_pd_regulator)) {
+ mfc_err("failed to find mfc power domain\n");
+ ret = PTR_ERR(mfc_pd_regulator);
+ goto err_regulator_get;
+ }
+
+ mfc_sclk = clk_get(&pdev->dev, "sclk_mfc");
+ if (IS_ERR(mfc_sclk)) {
+ mfc_err("failed to find mfc clock source\n");
+ ret = PTR_ERR(mfc_sclk);
+ goto err_clk_get;
+ }
+
+ mfc_init_mem_inst_no();
+ mfc_init_buffer();
+
+ ret = misc_register(&mfc_miscdev);
+ if (ret) {
+ mfc_err("MFC can't misc register on minor\n");
+ goto err_misc_reg;
+ }
+
+ /*
+ * MFC FW downloading
+ */
+ ret = request_firmware_nowait(THIS_MODULE,
+ FW_ACTION_HOTPLUG,
+ MFC_FW_NAME,
+ &pdev->dev,
+ GFP_KERNEL,
+ pdev,
+ mfc_firmware_request_complete_handler);
+ if (ret) {
+ mfc_err("MFCINST_ERR_FW_INIT_FAIL\n");
+ ret = -EPERM;
+ goto err_req_fw;
+ }
+
+ return 0;
+
+err_req_fw:
+ misc_deregister(&mfc_miscdev);
+err_misc_reg:
+ clk_put(mfc_sclk);
+err_clk_get:
+ regulator_put(mfc_pd_regulator);
+err_regulator_get:
+err_vaddr_map:
+ free_irq(res->start, pdev);
+ mutex_destroy(&mfc_mutex);
+err_irq_req:
+err_irq_res:
+ iounmap(mfc_sfr_base_vaddr);
+err_mem_map:
+ release_mem_region(mfc_mem, size);
+err_mem_req:
+probe_out:
+ dev_err(&pdev->dev, "not found (%d).\n", ret);
+ return ret;
+}
+
+static int mfc_remove(struct platform_device *pdev)
+{
+ iounmap(mfc_sfr_base_vaddr);
+ iounmap(mfc_port0_base_vaddr);
+
+ /* remove memory region */
+ if (mfc_mem != NULL) {
+ release_resource(mfc_mem);
+ kfree(mfc_mem);
+ mfc_mem = NULL;
+ }
+
+ free_irq(IRQ_MFC, pdev);
+
+ mutex_destroy(&mfc_mutex);
+
+ clk_put(mfc_sclk);
+
+ misc_deregister(&mfc_miscdev);
+
+ if (mfc_fw_info)
+ release_firmware(mfc_fw_info);
+
+ return 0;
+}
+
+static int mfc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ int ret = 0;
+
+ mutex_lock(&mfc_mutex);
+
+ if (!mfc_is_running()) {
+ mutex_unlock(&mfc_mutex);
+ return 0;
+ }
+ clk_enable(mfc_sclk);
+
+ ret = mfc_set_sleep();
+ if (ret != MFCINST_RET_OK) {
+ clk_disable(mfc_sclk);
+ mutex_unlock(&mfc_mutex);
+ return ret;
+ }
+
+ clk_disable(mfc_sclk);
+
+ mutex_unlock(&mfc_mutex);
+
+ return 0;
+}
+
+static int mfc_resume(struct platform_device *pdev)
+{
+ int ret = 0;
+ unsigned int mc_status;
+
+ mutex_lock(&mfc_mutex);
+
+ if (!mfc_is_running()) {
+ mutex_unlock(&mfc_mutex);
+ return 0;
+ }
+
+ clk_enable(mfc_sclk);
+
+ /*
+ * 1. MFC reset
+ */
+ do {
+ mc_status = READL(MFC_MC_STATUS);
+ } while (mc_status != 0);
+
+ if (mfc_cmd_reset() == false) {
+ clk_disable(mfc_sclk);
+ mutex_unlock(&mfc_mutex);
+ mfc_err("MFCINST_ERR_INIT_FAIL\n");
+ return MFCINST_ERR_INIT_FAIL;
+ }
+
+ WRITEL(mfc_port0_base_paddr, MFC_MC_DRAMBASE_ADDR_A);
+ WRITEL(mfc_port1_base_paddr, MFC_MC_DRAMBASE_ADDR_B);
+ WRITEL(1, MFC_NUM_MASTER);
+
+ ret = mfc_set_wakeup();
+ if (ret != MFCINST_RET_OK) {
+ clk_disable(mfc_sclk);
+ mutex_unlock(&mfc_mutex);
+ return ret;
+ }
+
+ clk_disable(mfc_sclk);
+
+ mutex_unlock(&mfc_mutex);
+
+ return 0;
+}
+
+static struct platform_driver mfc_driver = {
+ .probe = mfc_probe,
+ .remove = mfc_remove,
+ .shutdown = NULL,
+ .suspend = mfc_suspend,
+ .resume = mfc_resume,
+
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "s3c-mfc",
+ },
+};
+
+static char banner[] __initdata = KERN_INFO "S5PC110 MFC Driver, (c) 2009 Samsung Electronics\n";
+
+static int __init mfc_init(void)
+{
+ mfc_info("%s\n", banner);
+
+ if (platform_driver_register(&mfc_driver) != 0) {
+ mfc_err(KERN_ERR "platform device registration failed..\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static void __exit mfc_exit(void)
+{
+ platform_driver_unregister(&mfc_driver);
+ mfc_info("S5PC110 MFC Driver exit.\n");
+}
+
+module_init(mfc_init);
+module_exit(mfc_exit);
+
+MODULE_AUTHOR("Jaeryul, Oh");
+MODULE_DESCRIPTION("S3C MFC (Multi Function Codec - FIMV5.0) Device Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/samsung/mfc50/mfc_buffer_manager.c b/drivers/media/video/samsung/mfc50/mfc_buffer_manager.c
new file mode 100644
index 0000000..327637a
--- /dev/null
+++ b/drivers/media/video/samsung/mfc50/mfc_buffer_manager.c
@@ -0,0 +1,350 @@
+/*
+ * drivers/media/video/samsung/mfc50/mfc_buffer_manager.c
+ *
+ * C file for Samsung MFC (Multi Function Codec - FIMV) driver
+ *
+ * Key-Young Park, Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * Change Logs
+ * 2009.09.14 - use struct list_head for duble linked list
+ * 2009.11.04 - get physical address via mfc_allocate_buffer (Key Young, Park)
+ * 2009.11.13 - fix free buffer fragmentation (Key Young, Park)
+ *
+ * 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/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/miscdevice.h>
+#include <linux/platform_device.h>
+#include <linux/wait.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include <linux/io.h>
+#include <linux/uaccess.h>
+
+#include <plat/media.h>
+#include <mach/media.h>
+
+#include "mfc_buffer_manager.h"
+#include "mfc_errorno.h"
+#include "mfc_logmsg.h"
+#include "mfc_memory.h"
+
+static struct list_head mfc_alloc_mem_head[MFC_MAX_PORT_NUM];
+static struct list_head mfc_free_mem_head[MFC_MAX_PORT_NUM];
+
+void mfc_print_mem_list(void)
+{
+ struct list_head *pos;
+ struct mfc_alloc_mem *alloc_node;
+ struct mfc_free_mem *free_node;
+ int port_no;
+
+ for (port_no = 0; port_no < MFC_MAX_PORT_NUM; port_no++) {
+ mfc_info("===== %s port%d list =====\n", __func__, port_no);
+ list_for_each(pos, &mfc_alloc_mem_head[port_no])
+ {
+ alloc_node = list_entry(pos, struct mfc_alloc_mem, list);
+ mfc_info("[alloc_list] inst_no: %d, p_addr: 0x%08x, "
+ "u_addr: 0x%p, size: %d\n",
+ alloc_node->inst_no,
+ alloc_node->p_addr,
+ alloc_node->u_addr,
+ alloc_node->size);
+ }
+
+ list_for_each(pos, &mfc_free_mem_head[port_no])
+ {
+ free_node = list_entry(pos, struct mfc_free_mem, list);
+ mfc_info("[free_list] start_addr: 0x%08x size:%d\n",
+ free_node->start_addr , free_node->size);
+ }
+ }
+}
+
+void mfc_merge_fragment(int inst_no)
+{
+ struct list_head *pos, *n;
+ struct mfc_free_mem *node1, *node2;
+ int port_no;
+
+ for (port_no = 0; port_no < MFC_MAX_PORT_NUM; port_no++) {
+ list_for_each_safe(pos, n, &mfc_free_mem_head[port_no])
+ {
+ node1 = list_entry(pos, struct mfc_free_mem, list);
+ node2 = list_entry(n, struct mfc_free_mem, list);
+ if ((node1->start_addr + node1->size) == node2->start_addr) {
+ node2->start_addr = node1->start_addr;
+ node2->size += node1->size;
+ list_del(&(node1->list));
+ kfree(node1);
+ }
+ }
+ }
+
+#if defined(DEBUG)
+ mfc_print_mem_list();
+#endif
+}
+
+
+
+static unsigned int mfc_get_free_mem(int alloc_size, int inst_no, int port_no)
+{
+ struct list_head *pos;
+ struct mfc_free_mem *free_node, *match_node = NULL;
+ unsigned int alloc_addr = 0;
+
+ mfc_debug("request Size : %d\n", alloc_size);
+
+ if (list_empty(&mfc_free_mem_head[port_no])) {
+ mfc_err("all memory is gone\n");
+ return alloc_addr;
+ }
+ /* find best chunk of memory */
+ list_for_each(pos, &mfc_free_mem_head[port_no])
+ {
+ free_node = list_entry(pos, struct mfc_free_mem, list);
+
+ if (match_node != NULL) {
+ if ((free_node->size >= alloc_size) &&
+ (free_node->size < match_node->size))
+ match_node = free_node;
+ } else {
+ if (free_node->size >= alloc_size)
+ match_node = free_node;
+ }
+ }
+
+
+ if (match_node != NULL) {
+ mfc_debug("match : startAddr(0x%08x) size(%d)\n", match_node->start_addr, match_node->size);
+
+ alloc_addr = match_node->start_addr;
+ match_node->start_addr += alloc_size;
+ match_node->size -= alloc_size;
+
+ if (match_node->size < 0x1) /* delete match_node. */
+ mfc_err("there is no suitable chunk...[case 0]\n");
+ } else {
+ mfc_err("there is no suitable chunk....[case 1]\n");
+ return 0;
+ }
+
+ return alloc_addr;
+}
+
+
+int mfc_init_buffer(void)
+{
+ struct mfc_free_mem *free_node;
+ int port_no;
+
+ for (port_no = 0; port_no < MFC_MAX_PORT_NUM; port_no++) {
+ INIT_LIST_HEAD(&mfc_alloc_mem_head[port_no]);
+ INIT_LIST_HEAD(&mfc_free_mem_head[port_no]);
+ /* init free head node */
+ free_node =
+ (struct mfc_free_mem *)kmalloc(sizeof(struct mfc_free_mem), GFP_KERNEL);
+ memset(free_node, 0x00, sizeof(struct mfc_free_mem));
+
+ if (port_no) {
+ free_node->start_addr = mfc_get_port1_buff_paddr();
+ free_node->size = mfc_port1_memsize;
+ } else {
+ free_node->start_addr = mfc_get_port0_buff_paddr();
+ free_node->size = mfc_port1_memsize -
+ (mfc_get_port0_buff_paddr() - mfc_get_fw_buff_paddr());
+ }
+
+ list_add_tail(&(free_node->list), &mfc_free_mem_head[port_no]);
+ }
+
+#if defined(DEBUG)
+ mfc_print_mem_list();
+#endif
+ return 0;
+}
+
+enum mfc_error_code mfc_release_buffer(unsigned char *u_addr)
+{
+ struct list_head *pos;
+ int port_no;
+ struct mfc_alloc_mem *alloc_node;
+ bool found = false;
+
+ for (port_no = 0; port_no < MFC_MAX_PORT_NUM; port_no++) {
+ list_for_each(pos, &mfc_alloc_mem_head[port_no])
+ {
+ alloc_node = list_entry(pos, struct mfc_alloc_mem, list);
+ if (alloc_node->u_addr == u_addr) {
+ mfc_free_alloc_mem(alloc_node, port_no);
+ found = true;
+ break;
+ }
+ }
+ }
+
+#if defined(DEBUG)
+ mfc_print_mem_list();
+#endif
+
+ if (found)
+ return MFCINST_RET_OK;
+ else
+ return MFCINST_MEMORY_INVALID_ADDR;
+}
+
+void mfc_release_all_buffer(int inst_no)
+{
+ struct list_head *pos, *n;
+ int port_no;
+ struct mfc_alloc_mem *alloc_node;
+
+ for (port_no = 0; port_no < MFC_MAX_PORT_NUM; port_no++) {
+ list_for_each_safe(pos, n, &mfc_alloc_mem_head[port_no]) {
+ alloc_node = list_entry(pos, struct mfc_alloc_mem, list);
+ if (alloc_node->inst_no == inst_no) {
+ mfc_free_alloc_mem(alloc_node, port_no);
+ }
+ }
+ }
+
+#if defined(DEBUG)
+ mfc_print_mem_list();
+#endif
+}
+
+void mfc_free_alloc_mem(struct mfc_alloc_mem *alloc_node, int port_no)
+{
+ struct list_head *pos;
+ struct mfc_free_mem *free_node;
+ struct mfc_free_mem *target_node;
+
+ free_node = (struct mfc_free_mem *)kmalloc(sizeof(struct mfc_free_mem), GFP_KERNEL);
+ free_node->start_addr = alloc_node->p_addr;
+ free_node->size = alloc_node->size;
+
+ list_for_each(pos, &mfc_free_mem_head[port_no])
+ {
+ target_node = list_entry(pos, struct mfc_free_mem, list);
+ if (alloc_node->p_addr < target_node->start_addr)
+ break;
+ }
+
+ if (pos == &mfc_free_mem_head[port_no])
+ list_add_tail(&(free_node->list), &(mfc_free_mem_head[port_no]));
+ else
+ list_add_tail(&(free_node->list), pos);
+
+ list_del(&(alloc_node->list));
+ kfree(alloc_node);
+}
+
+enum mfc_error_code mfc_get_phys_addr(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args)
+{
+ int ret, port_no;
+ struct list_head *pos;
+ struct mfc_alloc_mem *alloc_node;
+ struct mfc_get_phys_addr_arg *phys_addr_arg;
+
+ phys_addr_arg = (struct mfc_get_phys_addr_arg *)args;
+ for (port_no = 0; port_no < MFC_MAX_PORT_NUM; port_no++) {
+ list_for_each(pos, &mfc_alloc_mem_head[port_no])
+ {
+ alloc_node = list_entry(pos, struct mfc_alloc_mem, list);
+ if (alloc_node->u_addr == (unsigned char *)phys_addr_arg->u_addr) {
+ mfc_debug("u_addr(0x%08x), p_addr(0x%08x) is found\n",
+ alloc_node->u_addr, alloc_node->p_addr);
+ goto found;
+ }
+ }
+ }
+
+ mfc_err("invalid virtual address(0x%08x)\r\n", phys_addr_arg->u_addr);
+ ret = MFCINST_MEMORY_INVALID_ADDR;
+ goto out_getphysaddr;
+
+found:
+ phys_addr_arg->p_addr = alloc_node->p_addr;
+ ret = MFCINST_RET_OK;
+
+out_getphysaddr:
+ return ret;
+}
+
+enum mfc_error_code mfc_allocate_buffer(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args, int port_no)
+{
+ int ret;
+ int inst_no = mfc_ctx->mem_inst_no;
+ unsigned int start_paddr;
+ struct mfc_mem_alloc_arg *in_param;
+ struct mfc_alloc_mem *alloc_node;
+
+ in_param = (struct mfc_mem_alloc_arg *)args;
+
+ alloc_node = (struct mfc_alloc_mem *)kmalloc(sizeof(struct mfc_alloc_mem), GFP_KERNEL);
+ if (!alloc_node) {
+ mfc_err("There is no more kernel memory");
+ ret = MFCINST_MEMORY_ALLOC_FAIL;
+ goto out_getcodecviraddr;
+ }
+ memset(alloc_node, 0x00, sizeof(struct mfc_alloc_mem));
+
+ /* if user request area, allocate from reserved area */
+ start_paddr = mfc_get_free_mem((int)in_param->buff_size, inst_no, port_no);
+ mfc_debug("start_paddr = 0x%X\n\r", start_paddr);
+
+ if (!start_paddr) {
+ mfc_err("There is no more memory\n\r");
+ in_param->out_uaddr = -1;
+ ret = MFCINST_MEMORY_ALLOC_FAIL;
+ kfree(alloc_node);
+ goto out_getcodecviraddr;
+ }
+
+ alloc_node->p_addr = start_paddr;
+ if (port_no) {
+ alloc_node->v_addr = (unsigned char *)(mfc_get_port1_buff_vaddr() +
+ (alloc_node->p_addr - mfc_get_port1_buff_paddr()));
+ alloc_node->u_addr = (unsigned char *)(in_param->mapped_addr +
+ mfc_ctx->port0_mmap_size +
+ (alloc_node->p_addr - mfc_get_port1_buff_paddr()));
+ } else {
+ alloc_node->v_addr = (unsigned char *)(mfc_get_port0_buff_vaddr() +
+ (alloc_node->p_addr - mfc_get_port0_buff_paddr()));
+ alloc_node->u_addr = (unsigned char *)(in_param->mapped_addr +
+ (alloc_node->p_addr - mfc_get_port0_buff_paddr()));
+ }
+
+ in_param->out_uaddr = (unsigned int)alloc_node->u_addr;
+ in_param->out_paddr = (unsigned int)alloc_node->p_addr;
+ mfc_debug("u_addr : 0x%08x v_addr : 0x%08x p_addr : 0x%08x\n",
+ (unsigned int)alloc_node->u_addr,
+ (unsigned int)alloc_node->v_addr,
+ alloc_node->p_addr);
+
+ alloc_node->size = (int)in_param->buff_size;
+ alloc_node->inst_no = inst_no;
+
+ list_add(&(alloc_node->list), &mfc_alloc_mem_head[port_no]);
+ ret = MFCINST_RET_OK;
+
+#if defined(DEBUG)
+ mfc_print_mem_list();
+#endif
+
+out_getcodecviraddr:
+ return ret;
+}
diff --git a/drivers/media/video/samsung/mfc50/mfc_buffer_manager.h b/drivers/media/video/samsung/mfc50/mfc_buffer_manager.h
new file mode 100644
index 0000000..d40bc04
--- /dev/null
+++ b/drivers/media/video/samsung/mfc50/mfc_buffer_manager.h
@@ -0,0 +1,56 @@
+/*
+ * drivers/media/video/samsung/mfc50/mfc_buffer_manager.h
+ *
+ * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
+ *
+ * Key-Young Park, Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * Change Logs
+ * 2009.11.04 - remove mfc_common.[ch]
+ * seperate buffer alloc & set (Key Young, Park)
+ *
+ * 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 _MFC_BUFFER_MANAGER_H_
+#define _MFC_BUFFER_MANAGER_H_
+
+#include <linux/list.h>
+#include "mfc_interface.h"
+#include "mfc_opr.h"
+
+#define MFC_MAX_PORT_NUM 2
+
+/* Struct Definition */
+struct mfc_alloc_mem {
+ struct list_head list; /* strcut list_head for alloc mem */
+ unsigned int p_addr; /* physical address */
+ unsigned char *v_addr; /* virtual address */
+ unsigned char *u_addr; /* virtual address for user mode process */
+ int size; /* memory size */
+ int inst_no; /* instance no */
+};
+
+
+struct mfc_free_mem {
+ struct list_head list; /* struct list_head for free mem */
+ unsigned int start_addr; /* start address of free mem */
+ unsigned int size; /* size of free mem */
+};
+
+
+/* Function Prototype */
+void mfc_print_mem_list(void);
+int mfc_init_buffer(void);
+void mfc_merge_fragment(int inst_no);
+void mfc_release_all_buffer(int inst_no);
+void mfc_free_alloc_mem(struct mfc_alloc_mem *alloc_node, int port_no);
+enum mfc_error_code mfc_release_buffer(unsigned char *u_addr);
+enum mfc_error_code mfc_get_phys_addr(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args);
+enum mfc_error_code mfc_allocate_buffer(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args, int port_no);
+
+#endif /* _MFC_BUFFER_MANAGER_H_ */
diff --git a/drivers/media/video/samsung/mfc50/mfc_errorno.h b/drivers/media/video/samsung/mfc50/mfc_errorno.h
new file mode 100644
index 0000000..7f27115
--- /dev/null
+++ b/drivers/media/video/samsung/mfc50/mfc_errorno.h
@@ -0,0 +1,83 @@
+/*
+ * drivers/media/video/samsung/mfc50/mfc_errorno.h
+ *
+ * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
+ *
+ * Jaeryul Oh, Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * Change Logs
+ * 2009.09.14 - Beautify source code (Key Young, Park)
+ * 2009.09.21 - Implement clock & power gating.
+ * including suspend & resume fuction. (Key Young, Park)
+ *
+ * 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 _MFC_ERRORNO_H_
+#define _MFC_ERRORNO_H_
+
+enum mfc_error_code {
+ MFCINST_RET_OK = 1,
+ MFCINST_ERR_INVALID_PARAM = -1001,
+ MFCINST_ERR_STATE_INVALID = -1002,
+ MFCINST_ERR_POWER_OFF = -1003,
+ MFCINST_ERR_WRONG_CODEC_MODE = -1004,
+ MFCINST_ERR_INIT_FAIL = -1005,
+ MFCINST_ERR_FILE_OPEN_FAIL = -1006,
+ MFCINST_ERR_INTR_TIME_OUT = -1007,
+ MFCINST_ERR_INTR_INIT_FAIL = -1008,
+ MFCINST_ERR_OPEN_FAIL = -1009,
+ MFCINST_ERR_CLOSE_FAIL = -1010,
+
+
+ MFCINST_ERR_DEC_INIT_CMD_FAIL = -2001,
+ MFCINST_ERR_DEC_HEADER_DECODE_FAIL = -2002,
+ MFCINST_ERR_DEC_INIT_BUFFER_FAIL = -2003,
+ MFCINST_ERR_DEC_DECODE_CMD_FAIL = -2004,
+ MFCINST_ERR_DEC_DECODE_DONE_FAIL = -2005,
+ MFCINST_ERR_DEC_INVALID_STRM = -2006,
+ MFCINST_ERR_DEC_STRM_SIZE_INVALID = -2007,
+ MFCINST_ERR_DEC_SEQ_DONE_FAIL = -2008,
+ MFCINST_ERR_DEC_NON_I_FRAME_START = -2009,
+
+ MFCINST_ERR_ENC_INIT_CMD_FAIL = -3001,
+ MFCINST_ERR_ENC_HEADER_DECODE_FAIL = -3002,
+ MFCINST_ERR_ENC_ENCODE_CMD_FAIL = -3003,
+ MFCINST_ERR_ENC_ENCODE_DONE_FAIL = -3004,
+ MFCINST_ERR_ENC_PARAM_INVALID_VALUE = -3005,
+
+ MFCINST_ERR_STRM_BUF_INVALID = -4001,
+ MFCINST_ERR_FRM_BUF_INVALID = -4002,
+ MFCINST_ERR_FRM_BUF_SIZE = -4003,
+
+ MFCINST_ERR_FW_LOAD_FAIL = -5001,
+ MFCINST_ERR_FW_MEMORY_INVALID = -5002,
+ MFCINST_ERR_FW_DMA_SET_FAIL = -5003,
+ MFCINST_ERR_FW_INIT_FAIL = -5004,
+ MFCINST_ERR_SEQ_START_FAIL = -5005,
+
+ MFCINST_INST_NUM_INVALID = -6001,
+ MFCINST_INST_NUM_EXCEEDED = -6002,
+ MFCINST_ERR_SET_CONF = -6003,
+ MFCINST_ERR_GET_CONF = -6004,
+
+ MFCINST_MEMORY_ALLOC_FAIL = -8001,
+ MFCINST_MUTEX_CREATE_FAIL = -8002,
+ MFCINST_POWER_INIT_FAIL = -8003,
+ MFCINST_POWER_ON_OFF_FAIL = -8004,
+ MFCINST_POWER_STATE_INVALID = -8005,
+ MFCINST_POWER_MANAGER_ERR = -8006,
+ MFCINST_SLEEP_FAIL = -8007,
+ MFCINST_WAKEUP_FAIL = -8008,
+
+ MFCINST_MEMORY_INVALID_ADDR = -8101,
+ MFCINST_MEMORY_MAPPING_FAIL = -8102,
+
+ MFCAPI_RET_FAIL = -9001,
+};
+
+#endif /* _MFC_ERRORNO_H_ */
+
diff --git a/drivers/media/video/samsung/mfc50/mfc_interface.h b/drivers/media/video/samsung/mfc50/mfc_interface.h
new file mode 100644
index 0000000..7ef6cdc
--- /dev/null
+++ b/drivers/media/video/samsung/mfc50/mfc_interface.h
@@ -0,0 +1,340 @@
+/*
+ * drivers/media/video/samsung/mfc50/mfc_interface.h
+ *
+ * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
+ *
+ * Jaeryul Oh, Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * Change Logs
+ * 2009.09.14 - Beautify source code (Key Young, Park)
+ * 2009.10.22 - Change codec name VC1AP_DEC -> VC1_DEC (Key Young, Park)
+ * 2009.11.04 - get physical address via mfc_allocate_buffer (Key Young, Park)
+ * 2009.11.06 - Apply common MFC API (Key Young, Park)
+ *
+ * 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 _MFC_INTERFACE_H_
+#define _MFC_INTERFACE_H_
+
+#include "mfc_errorno.h"
+
+#define IOCTL_MFC_DEC_INIT 0x00800001
+#define IOCTL_MFC_ENC_INIT 0x00800002
+#define IOCTL_MFC_DEC_EXE 0x00800003
+#define IOCTL_MFC_ENC_EXE 0x00800004
+
+#define IOCTL_MFC_GET_IN_BUF 0x00800010
+#define IOCTL_MFC_FREE_BUF 0x00800011
+#define IOCTL_MFC_GET_PHYS_ADDR 0x00800012
+#define IOCTL_MFC_GET_MMAP_SIZE 0x00800014
+
+#define IOCTL_MFC_SET_CONFIG 0x00800101
+#define IOCTL_MFC_GET_CONFIG 0x00800102
+
+#define IOCTL_MFC_BUF_CACHE 0x00801000
+
+/* MFC H/W support maximum 32 extra DPB */
+#define MFC_MAX_EXTRA_DPB 5
+
+#define ENC_PROFILE_LEVEL(profile, level) ((profile) | ((level) << 8))
+
+#define ENC_PROFILE_MPEG4_SP 0
+#define ENC_PROFILE_MPEG4_ASP 1
+#define ENC_PROFILE_H264_BP 0
+#define ENC_PROFILE_H264_MAIN 1
+#define ENC_PROFILE_H264_HIGH 2
+
+#define ENC_RC_DISABLE 0
+#define ENC_RC_ENABLE_MACROBLOCK 1
+#define ENC_RC_ENABLE_FRAME 2
+
+#define ENC_RC_QBOUND(min_qp, max_qp) ((min_qp) | ((max_qp) << 8))
+#define ENC_RC_MB_CTRL_DARK_DISABLE (1 << 3)
+#define ENC_RC_MB_CTRL_SMOOTH_DISABLE (1 << 2)
+#define ENC_RC_MB_CTRL_STATIC_DISABLE (1 << 1)
+#define ENC_RC_MB_CTRL_ACTIVITY_DISABLE (1 << 0)
+
+
+enum ssbsip_mfc_codec_type {
+ H264_DEC,
+ VC1_DEC, /* VC1 advaced Profile decoding */
+ MPEG4_DEC,
+ XVID_DEC,
+ MPEG1_DEC,
+ MPEG2_DEC,
+ H263_DEC,
+ VC1RCV_DEC, /* VC1 simple/main profile decoding */
+ FIMV1_DEC,
+ FIMV2_DEC,
+ FIMV3_DEC,
+ FIMV4_DEC,
+ H264_ENC,
+ MPEG4_ENC,
+ H263_ENC,
+ UNKNOWN_TYPE
+};
+
+enum ssbsip_mfc_force_set_frame_type {
+ DONT_CARE = 0,
+ I_FRAME = 1,
+ NOT_CODED = 2
+};
+
+enum ssbsip_mfc_dec_conf {
+ MFC_DEC_SETCONF_POST_ENABLE = 1,
+ MFC_DEC_SETCONF_EXTRA_BUFFER_NUM,
+ MFC_DEC_SETCONF_DISPLAY_DELAY,
+ MFC_DEC_SETCONF_IS_LAST_FRAME,
+ MFC_DEC_SETCONF_SLICE_ENABLE,
+ MFC_DEC_SETCONF_CRC_ENABLE,
+ MFC_DEC_SETCONF_FIMV1_WIDTH_HEIGHT,
+ MFC_DEC_SETCONF_FRAME_TAG,
+ MFC_DEC_GETCONF_CRC_DATA,
+ MFC_DEC_GETCONF_BUF_WIDTH_HEIGHT,
+ FC_DEC_GETCONF_CROP_INFO,
+ MFC_DEC_GETCONF_FRAME_TAG
+};
+
+enum ssbsip_mfc_enc_conf {
+ MFC_ENC_SETCONF_FRAME_TYPE = 100,
+ MFC_ENC_SETCONF_CHANGE_FRAME_RATE,
+ MFC_ENC_SETCONF_CHANGE_BIT_RATE,
+ MFC_ENC_SETCONF_FRAME_TAG,
+ MFC_ENC_SETCONF_ALLOW_FRAME_SKIP,
+ MFC_ENC_GETCONF_FRAME_TAG
+};
+
+struct mfc_strm_ref_buf_arg {
+ unsigned int strm_ref_y;
+ unsigned int mv_ref_yc;
+};
+
+struct mfc_frame_buf_arg {
+ unsigned int luma;
+ unsigned int chroma;
+};
+
+struct mfc_enc_init_mpeg4_arg {
+ enum ssbsip_mfc_codec_type in_codec_type; /* [IN] codec type */
+ int in_width; /* [IN] width of YUV420 frame to be encoded */
+ int in_height; /* [IN] height of YUV420 frame to be encoded */
+ int in_profile_level; /* [IN] profile & level */
+ int in_gop_num; /* [IN] GOP Number (interval of I-frame) */
+ int in_frame_qp; /* [IN] the quantization parameter of the frame */
+ int in_frame_P_qp; /* [IN] the quantization parameter of the P frame */
+ int in_frame_B_qp; /* [IN] the quantization parameter of the B frame */
+
+ int in_RC_frm_enable; /* [IN] RC enable (0:disable, 1:frame level RC) */
+ int in_RC_framerate; /* [IN] RC parameter (framerate) */
+ int in_RC_bitrate; /* [IN] RC parameter (bitrate in kbps) */
+ int in_RC_qbound; /* [IN] RC parameter (Q bound) */
+ int in_RC_rpara; /* [IN] RC parameter (Reaction Coefficient) */
+
+ int in_MS_mode; /* [IN] Multi-slice mode (0:single, 1:multiple) */
+ int in_MS_size; /* [IN] Multi-slice size (in num. of mb or byte) */
+ int in_mb_refresh; /* [IN] Macroblock refresh */
+ int in_interlace_mode; /* [IN] interlace mode(0:progressive, 1:interlace) */
+ int in_BframeNum; /* [IN] B frame number */
+
+ int in_pad_ctrl_on; /* [IN] Enable (1) / Disable (0) padding */
+ int in_luma_pad_val; /* [IN] pad value if pad_ctrl_on is Enable */
+ int in_cb_pad_val;
+ int in_cr_pad_val;
+
+ int in_frame_map; /* [IN] Encoding input NV12 type linear(0) TILE(1) */
+
+ unsigned int in_mapped_addr;
+ struct mfc_strm_ref_buf_arg out_u_addr;
+ struct mfc_strm_ref_buf_arg out_p_addr;
+ struct mfc_strm_ref_buf_arg out_buf_size;
+ unsigned int out_header_size;
+
+ /* MPEG4 Only */
+ int in_qpelME_enable; /* [IN] Quarter-pel MC enable(1:enable, 0:disable) */
+ int in_time_increament_res; /* [IN] time increment resolution */
+ int in_time_vop_time_increament; /* [IN] time increment */
+};
+
+//struct mfc_enc_init_mpeg4_arg mfc_enc_init_h263_arg;
+
+struct mfc_enc_init_h264_arg {
+ enum ssbsip_mfc_codec_type in_codec_type; /* [IN] codec type */
+ int in_width; /* [IN] width of YUV420 frame to be encoded */
+ int in_height; /* [IN] height of YUV420 frame to be encoded */
+ int in_profile_level; /* [IN] profile & level */
+ int in_gop_num; /* [IN] GOP Number (interval of I-frame) */
+ int in_frame_qp; /* [IN] the quantization parameter of the frame */
+ int in_frame_P_qp; /* [IN] the quantization parameter of the P frame */
+ int in_frame_B_qp; /* [IN] the quantization parameter of the B frame */
+
+ int in_RC_frm_enable; /* [IN] RC enable (0:disable, 1:frame level RC) */
+ int in_RC_framerate; /* [IN] RC parameter (framerate) */
+ int in_RC_bitrate; /* [IN] RC parameter (bitrate in kbps) */
+ int in_RC_qbound; /* [IN] RC parameter (Q bound) */
+ int in_RC_rpara; /* [IN] RC parameter (Reaction Coefficient) */
+
+ int in_MS_mode; /* [IN] Multi-slice mode (0:single, 1:multiple) */
+ int in_MS_size; /* [IN] Multi-slice size (in num. of mb or byte) */
+ int in_mb_refresh; /* [IN] Macroblock refresh */
+ int in_interlace_mode; /* [IN] interlace mode(0:progressive, 1:interlace) */
+ int in_BframeNum;
+
+ int in_pad_ctrl_on; /* [IN] Enable padding control */
+ int in_luma_pad_val; /* [IN] Luma pel value used to fill padding area */
+ int in_cb_pad_val; /* [IN] CB pel value used to fill padding area */
+ int in_cr_pad_val; /* [IN] CR pel value used to fill padding area */
+
+ int in_frame_map; /* [IN] Encoding input NV12 type linear(0) TILE(1) */
+
+ unsigned int in_mapped_addr;
+ struct mfc_strm_ref_buf_arg out_u_addr;
+ struct mfc_strm_ref_buf_arg out_p_addr;
+ struct mfc_strm_ref_buf_arg out_buf_size;
+ unsigned int out_header_size;
+
+ /* H264 Only */
+ int in_RC_mb_enable; /* [IN] RC enable (0:disable, 1:MB level RC) */
+ int in_reference_num; /* [IN] The number of reference pictures used */
+ int in_ref_num_p; /* [IN] The number of reference pictures used for P pictures */
+ int in_RC_mb_dark_disable; /* [IN] Disable adaptive rate control on dark region */
+ int in_RC_mb_smooth_disable; /* [IN] Disable adaptive rate control on smooth region */
+ int in_RC_mb_static_disable; /* [IN] Disable adaptive rate control on static region */
+ int in_RC_mb_activity_disable; /* [IN] Disable adaptive rate control on static region */
+ int in_deblock_filt; /* [IN] disable the loop filter */
+ int in_deblock_alpha_C0; /* [IN] Alpha & C0 offset for H.264 loop filter */
+ int in_deblock_beta; /* [IN] Beta offset for H.264 loop filter */
+ int in_symbolmode; /* [IN] The mode of entropy coding(CABAC, CAVLC) */
+ int in_transform8x8_mode; /* [IN] Allow 8x8 transform(only for high profile) */
+ int in_md_interweight_pps; /* [IN] Inter weighted parameter for mode decision */
+ int in_md_intraweight_pps; /* [IN] Intra weighted parameter for mode decision */
+};
+
+struct mfc_enc_exe_arg {
+ enum ssbsip_mfc_codec_type in_codec_type; /* [IN] codec type */
+ unsigned int in_Y_addr; /* [IN] In-buffer addr of Y component */
+ unsigned int in_CbCr_addr; /* [IN] In-buffer addr of CbCr component */
+ unsigned int in_Y_addr_vir; /* [IN] In-buffer addr of Y component */
+ unsigned int in_CbCr_addr_vir; /* [IN] In-buffer addr of CbCr component */
+ unsigned int in_strm_st; /* [IN] Out-buffer start addr of encoded strm */
+ unsigned int in_strm_end; /* [IN] Out-buffer end addr of encoded strm */
+ int in_frametag; /* [IN] unique frame ID */
+
+ unsigned int out_frame_type; /* [OUT] frame type */
+ int out_encoded_size; /* [OUT] Length of Encoded video stream */
+ unsigned int out_encoded_Y_paddr; /* [OUT] physical Y address which is flushed */
+ unsigned int out_encoded_C_paddr; /* [OUT] physical C address which is flushed */
+ int out_frametag_top; /* [OUT] unique frame ID of an output frame or top field */
+ int out_frametag_bottom; /* [OUT] unique frame ID of bottom field */
+};
+
+struct mfc_dec_init_arg {
+ enum ssbsip_mfc_codec_type in_codec_type; /* [IN] codec type */
+ unsigned int in_strm_buf; /* [IN] the physical address of STRM_BUF */
+ int in_strm_size; /* [IN] size of video stream filled in STRM_BUF */
+ int in_packed_PB; /* [IN] Is packed PB frame or not, 1: packedPB 0: unpacked */
+
+ int out_img_width; /* [OUT] width of YUV420 frame */
+ int out_img_height; /* [OUT] height of YUV420 frame */
+ int out_buf_width; /* [OUT] width of YUV420 frame */
+ int out_buf_height; /* [OUT] height of YUV420 frame */
+ int out_dpb_cnt; /* [OUT] the number of buffers which is nessary during decoding */
+
+ int out_crop_top_offset; /* [OUT] crop information, top offset */
+ int out_crop_bottom_offset; /* [OUT] crop information, bottom offset */
+ int out_crop_left_offset; /* [OUT] crop information, left offset */
+ int out_crop_right_offset; /* [OUT] crop information, right offset */
+
+ struct mfc_frame_buf_arg in_frm_buf; /* [IN] the address of dpb FRAME_BUF */
+ struct mfc_frame_buf_arg in_frm_size; /* [IN] size of dpb FRAME_BUF */
+ unsigned int in_mapped_addr;
+
+ struct mfc_frame_buf_arg out_u_addr;
+ struct mfc_frame_buf_arg out_p_addr;
+ struct mfc_frame_buf_arg out_frame_buf_size;
+};
+
+struct mfc_dec_exe_arg {
+ enum ssbsip_mfc_codec_type in_codec_type; /* [IN] codec type */
+ unsigned int in_strm_buf; /* [IN] the physical address of STRM_BUF */
+ int in_strm_size; /* [IN] Size of video stream filled in STRM_BUF */
+ struct mfc_frame_buf_arg in_frm_buf; /* [IN] the address of dpb FRAME_BUF */
+ struct mfc_frame_buf_arg in_frm_size; /* [IN] size of dpb FRAME_BUF */
+ int in_frametag; /* [IN] unique frame ID */
+
+ unsigned int out_display_Y_addr; /* [OUT] the physical address of display buf */
+ unsigned int out_display_C_addr; /* [OUT] the physical address of display buf */
+ int out_display_status; /* [OUT] whether display frame exist or not. */
+ int out_timestamp_top; /* [OUT] presentation time of an output frame or top field */
+ int out_timestamp_bottom; /* [OUT] presentation time of bottom field */
+ int out_consume_bytes; /* [OUT] consumed bytes when decoding finished */
+ int out_frametag_top; /* [OUT] unique frame ID of an output frame or top field */
+ int out_frametag_bottom; /* [OUT] unique frame ID of bottom field */
+ int out_res_change; /* [OUT] whether resolution is changed or not (0, 1, 2) */
+ int out_crop_top_offset; /* [OUT] crop information, top offset */
+ int out_crop_bottom_offset; /* [OUT] crop information, bottom offset */
+ int out_crop_left_offset; /* [OUT] crop information, left offset */
+ int out_crop_right_offset; /* [OUT] crop information, right offset */
+};
+
+struct mfc_get_config_arg {
+ int in_config_param; /* [IN] Configurable parameter type */
+ int out_config_value[4]; /* [IN] Values to get for the configurable parameter. */
+};
+
+struct mfc_set_config_arg {
+ int in_config_param; /* [IN] Configurable parameter type */
+ int in_config_value[2]; /* [IN] Values to be set for the configurable parameter. */
+ int out_config_value_old[2]; /* [OUT] Old values of the configurable parameters */
+};
+
+struct mfc_get_phys_addr_arg {
+ unsigned int u_addr;
+ unsigned int p_addr;
+};
+
+struct mfc_mem_alloc_arg {
+ enum ssbsip_mfc_codec_type codec_type;
+ int buff_size;
+ unsigned int mapped_addr;
+ unsigned int out_uaddr;
+ unsigned int out_paddr;
+};
+
+struct mfc_mem_free_arg {
+ unsigned int u_addr;
+};
+
+enum mfc_buffer_type {
+ MFC_BUFFER_NO_CACHE = 0,
+ MFC_BUFFER_CACHE = 1
+};
+
+union mfc_args {
+ struct mfc_enc_init_mpeg4_arg enc_init_mpeg4;
+ struct mfc_enc_init_mpeg4_arg enc_init_h263;
+ struct mfc_enc_init_h264_arg enc_init_h264;
+ struct mfc_enc_exe_arg enc_exe;
+
+ struct mfc_dec_init_arg dec_init;
+ struct mfc_dec_exe_arg dec_exe;
+
+ struct mfc_get_config_arg get_config;
+ struct mfc_set_config_arg set_config;
+
+ struct mfc_mem_alloc_arg mem_alloc;
+ struct mfc_mem_free_arg mem_free;
+ struct mfc_get_phys_addr_arg get_phys_addr;
+
+ enum mfc_buffer_type buf_type;
+};
+
+struct mfc_common_args {
+ enum mfc_error_code ret_code; /* [OUT] error code */
+ union mfc_args args;
+};
+
+#endif /* _MFC_INTERFACE_H_ */
diff --git a/drivers/media/video/samsung/mfc50/mfc_intr.c b/drivers/media/video/samsung/mfc50/mfc_intr.c
new file mode 100644
index 0000000..035d460
--- /dev/null
+++ b/drivers/media/video/samsung/mfc50/mfc_intr.c
@@ -0,0 +1,202 @@
+/*
+ * drivers/media/video/samsung/mfc50/mfc_intr.c
+ *
+ * C file for Samsung MFC (Multi Function Codec - FIMV) driver
+ *
+ * Jaeryul Oh, Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * Change Logs
+ * 2009.09.14 - Beautify source code (Key Young, Park)
+ * 2009.09.21 - Implement clock & power gating.
+ * including suspend & resume fuction. (Key Young, Park)
+ * 2009.10.09 - Add error handling rountine (Key Young, Park)
+ * 2009.10.13 - Change wait_for_done (Key Young, Park)
+ * 2009.11.04 - remove mfc_common.[ch]
+ * seperate buffer alloc & set (Key Young, Park)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/io.h>
+
+#include <plat/regs-mfc.h>
+
+#include "mfc_logmsg.h"
+#include "mfc_opr.h"
+#include "mfc_memory.h"
+#include "mfc_intr.h"
+
+
+#define MFC_WAIT_1_TIME 100
+#define MFC_WAIT_2_TIME 200
+#define MFC_WAIT_3_TIME 400
+#define MFC_WAIT_4_TIME 600
+#define MFC_WAIT_5_TIME 800
+#define MFC_WAIT_6_TIME 1000
+
+#define ENABLE_MFC_INTERRUPT_DEBUG 0 /* 0: Disable 1: Enable */
+
+#if defined(MFC_REQUEST_TIME)
+struct timeval mfc_wakeup_before;
+struct timeval mfc_wakeup_after;
+#endif
+
+static unsigned int mfc_int_type;
+static unsigned int mfc_disp_err_status;
+static unsigned int mfc_dec_err_status;
+static bool irq_sync;
+static DECLARE_WAIT_QUEUE_HEAD(mfc_wait_queue);
+static DEFINE_SPINLOCK(mfc_irq_lock);
+
+#if !defined(MFC_POLLING)
+irqreturn_t mfc_irq(int irq, void *dev_id)
+{
+ unsigned int int_reason;
+ unsigned int err_status;
+
+ int_reason = READL(MFC_RISC2HOST_COMMAND) & 0x1FFFF;
+ err_status = READL(MFC_RISC2HOST_ARG2);
+
+ mfc_disp_err_status = err_status >> 16;
+ mfc_dec_err_status = err_status & 0xFFFF;
+
+ mfc_debug_L0("mfc_irq() : Interrupt !! : %d\n", int_reason);
+
+ if (((int_reason & R2H_CMD_FRAME_DONE_RET) == R2H_CMD_FRAME_DONE_RET) ||
+ ((int_reason & R2H_CMD_SEQ_DONE_RET) == R2H_CMD_SEQ_DONE_RET) ||
+ ((int_reason & R2H_CMD_SYS_INIT_RET) == R2H_CMD_SYS_INIT_RET) ||
+ ((int_reason & R2H_CMD_OPEN_INSTANCE_RET) == R2H_CMD_OPEN_INSTANCE_RET) ||
+ ((int_reason & R2H_CMD_CLOSE_INSTANCE_RET) == R2H_CMD_CLOSE_INSTANCE_RET) ||
+ ((int_reason & R2H_CMD_INIT_BUFFERS_RET) == R2H_CMD_INIT_BUFFERS_RET) ||
+ ((int_reason & R2H_CMD_DECODE_ERR_RET) == R2H_CMD_DECODE_ERR_RET) ||
+ ((int_reason & R2H_CMD_SLICE_DONE_RET) == R2H_CMD_SLICE_DONE_RET) ||
+ ((int_reason & R2H_CMD_ERROR_RET) == R2H_CMD_ERROR_RET)) {
+ mfc_int_type = int_reason;
+ irq_sync = true;
+ wake_up(&mfc_wait_queue);
+ } else {
+ irq_sync = false;
+ mfc_info("Strange Interrupt !! : %d\n", int_reason);
+ }
+
+
+ WRITEL(0, MFC_RISC_HOST_INT);
+ WRITEL(0, MFC_RISC2HOST_COMMAND);
+ WRITEL(0xffff, MFC_SI_RTN_CHID);
+
+ return IRQ_HANDLED;
+}
+#endif
+
+void mfc_interrupt_debug(int nCnt)
+{
+ int nn = 0;
+ for (nn = 0; nn < nCnt; nn++) {
+ mdelay(100);
+ mfc_err("[%d] Timeout (0x64: 0x%08x) (0xF4: 0x%08x)\n", nn, READL(0x64), READL(0xF4));
+ }
+}
+
+int mfc_wait_for_done(enum mfc_wait_done_type command)
+{
+ unsigned int nwait_time = 100;
+ unsigned int ret_val = 1;
+ unsigned long flags;
+
+ if ((command == R2H_CMD_CLOSE_INSTANCE_RET) ||
+ (command == R2H_CMD_OPEN_INSTANCE_RET) ||
+ (command == R2H_CMD_SYS_INIT_RET) ||
+ (command == R2H_CMD_FW_STATUS_RET))
+ nwait_time = MFC_WAIT_6_TIME;
+ else
+ nwait_time = MFC_WAIT_2_TIME;
+
+
+#if defined(MFC_REQUEST_TIME)
+ long sec, msec;
+#endif
+
+#if defined(MFC_POLLING)
+ unsigned long timeo = jiffies;
+ timeo += 20; /* waiting for 100ms */
+#endif
+
+#if defined(MFC_REQUEST_TIME)
+ do_gettimeofday(&mfc_wakeup_before);
+ if (mfc_wakeup_before.tv_usec - mfc_wakeup_after.tv_usec < 0) {
+ msec = 1000000 + mfc_wakeup_before.tv_usec - mfc_wakeup_after.tv_usec;
+ sec = mfc_wakeup_before.tv_sec - mfc_wakeup_after.tv_sec - 1;
+ } else {
+ msec = mfc_wakeup_before.tv_usec - mfc_wakeup_after.tv_usec;
+ sec = mfc_wakeup_before.tv_sec - mfc_wakeup_after.tv_sec;
+ }
+#endif
+
+#if defined(MFC_POLLING)
+ while (time_before(jiffies, timeo))
+ ret_val = READL(MFC_RISC2HOST_COMMAND) & 0x1ffff;
+ if (ret_val != 0) {
+ WRITEL(0, MFC_RISC_HOST_INT);
+ WRITEL(0, MFC_RISC2HOST_COMMAND);
+ WRITEL(0xffff, MFC_SI_RTN_CHID);
+ mfc_int_type = ret_val;
+ break;
+ }
+ msleep_interruptible(2);
+ }
+
+ if (ret_val == 0)
+ printk(KERN_INFO "MFC timeouted!\n");
+#else
+ if (wait_event_timeout(mfc_wait_queue, irq_sync, nwait_time) == 0) {
+ ret_val = 0;
+ mfc_err("Interrupt Time Out(Cmd: %d) (Ver: 0x%08x) (0x64: 0x%08x) (0xF4: 0x%08x) (0x80: 0x%08x)\n", command, READL(0x58), READL(0x64), READL(0xF4), READL(0x80));
+
+#if ENABLE_MFC_INTERRUPT_DEBUG /* For MFC Interrupt Debugging. */
+ mfc_interrupt_debug(10);
+#endif
+
+ mfc_int_type = 0;
+ return ret_val;
+ } else if (mfc_int_type == R2H_CMD_DECODE_ERR_RET) {
+ mfc_err("Decode Error Returned Disp Error Status(%d), Dec Error Status(%d)\n", mfc_disp_err_status, mfc_dec_err_status);
+ } else if (command != mfc_int_type) {
+ mfc_err("Interrupt Error Returned (%d) waiting for (%d)\n", mfc_int_type, command);
+ }
+#endif
+ spin_lock_irqsave(&mfc_irq_lock, flags);
+ irq_sync = false;
+ spin_unlock_irqrestore(&mfc_irq_lock, flags);
+
+#if defined(MFC_REQUEST_TIME)
+ do_gettimeofday(&mfc_wakeup_after);
+ if (mfc_wakeup_after.tv_usec - mfc_wakeup_before.tv_usec < 0) {
+ msec = 1000000 + mfc_wakeup_after.tv_usec - mfc_wakeup_before.tv_usec;
+ sec = mfc_wakeup_after.tv_sec - mfc_wakeup_before.tv_sec - 1;
+ } else {
+ msec = mfc_wakeup_after.tv_usec - mfc_wakeup_before.tv_usec;
+ sec = mfc_wakeup_after.tv_sec - mfc_wakeup_before.tv_sec;
+ }
+
+ mfc_info("mfc_wait_for_done: mfc request interval time is %ld(sec), %ld(msec)\n", sec, msec);
+#endif
+
+ ret_val = mfc_int_type;
+ mfc_int_type = 0;
+
+ return ret_val;
+}
+
+
+int mfc_return_code(void)
+{
+ return mfc_dec_err_status;
+}
diff --git a/drivers/media/video/samsung/mfc50/mfc_intr.h b/drivers/media/video/samsung/mfc50/mfc_intr.h
new file mode 100644
index 0000000..ed156b9
--- /dev/null
+++ b/drivers/media/video/samsung/mfc50/mfc_intr.h
@@ -0,0 +1,25 @@
+/*
+ * drivers/media/video/samsung/mfc50/mfc_intr.h
+ *
+ * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
+ *
+ * Key-Young Park, Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * Change Logs
+ * 2009.10.13 - Separate from mfc_common.h(Key Young, Park)
+ *
+ * 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 _MFC_INTR_H_
+#define _MFC_INTR_H_
+
+#include <linux/interrupt.h>
+
+irqreturn_t mfc_irq(int irq, void *dev_id);
+int mfc_wait_for_done(enum mfc_wait_done_type command);
+int mfc_return_code(void);
+#endif
diff --git a/drivers/media/video/samsung/mfc50/mfc_logmsg.h b/drivers/media/video/samsung/mfc50/mfc_logmsg.h
new file mode 100644
index 0000000..881d733
--- /dev/null
+++ b/drivers/media/video/samsung/mfc50/mfc_logmsg.h
@@ -0,0 +1,72 @@
+/*
+ * drivers/media/video/samsung/mfc50/mfc_logmsg.h
+ *
+ * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
+ *
+ * Jaeryul Oh, Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * Change Logs
+ * 2009.09.14 - Beautify source code (Key Young, Park)
+ *
+ * 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 _MFC_LOGMSG_H_
+#define _MFC_LOGMSG_H_
+
+/* debug macros */
+#define MFC_DEBUG(fmt, ...) \
+ do { \
+ printk(KERN_DEBUG \
+ "%s: " fmt, __func__, ##__VA_ARGS__); \
+ } while (0)
+
+#define MFC_ERROR(fmt, ...) \
+ do { \
+ printk(KERN_ERR \
+ "%s: " fmt, __func__, ##__VA_ARGS__); \
+ } while (0)
+
+#define MFC_NOTICE(fmt, ...) \
+ do { \
+ printk(KERN_NOTICE \
+ "%s: " fmt, __func__, ##__VA_ARGS__); \
+ } while (0)
+
+#define MFC_INFO(fmt, ...) \
+ do { \
+ printk(KERN_INFO \
+ "%s: " fmt, __func__, ##__VA_ARGS__); \
+ } while (0)
+
+#define MFC_WARN(fmt, ...) \
+ do { \
+ printk(KERN_WARNING \
+ "%s: " fmt, __func__, ##__VA_ARGS__); \
+ } while (0)
+
+
+#ifdef CONFIG_VIDEO_MFC50_DEBUG
+#define mfc_debug(fmt, ...) MFC_INFO(fmt, ##__VA_ARGS__)
+#define mfc_debug_L0(fmt, ...) MFC_INFO(fmt, ##__VA_ARGS__)
+#else
+#define mfc_debug(fmt, ...)
+#define mfc_debug_L0(fmt, ...)
+#endif
+
+#if defined(DEBUG_LEVEL_0)
+#define mfc_debug_L0(fmt, ...) MFC_INFO(fmt, ##__VA_ARGS__)
+#define mfc_debug(fmt, ...) MFC_INFO(fmt, ##__VA_ARGS__)
+#elseif define(DEBUG_LEVEL_1)
+#define mfc_debug(fmt, ...) MFC_INFO(fmt, ##__VA_ARGS__)
+#endif
+
+#define mfc_err(fmt, ...) MFC_ERROR(fmt, ##__VA_ARGS__)
+#define mfc_notice(fmt, ...) MFC_NOTICE(fmt, ##__VA_ARGS__)
+#define mfc_info(fmt, ...) MFC_INFO(fmt, ##__VA_ARGS__)
+#define mfc_warn(fmt, ...) MFC_WARN(fmt, ##__VA_ARGS__)
+
+#endif /* _MFC_LOGMSG_H_ */
diff --git a/drivers/media/video/samsung/mfc50/mfc_memory.c b/drivers/media/video/samsung/mfc50/mfc_memory.c
new file mode 100644
index 0000000..a33dd9f
--- /dev/null
+++ b/drivers/media/video/samsung/mfc50/mfc_memory.c
@@ -0,0 +1,70 @@
+/*
+ * drivers/media/video/samsung/mfc50/mfc_memory.c
+ *
+ * C file for Samsung MFC (Multi Function Codec - FIMV) driver
+ *
+ * Jaeryul Oh, Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * Change Logs
+ * 2009.09.14 - Beautify source code (Key Young, Park)
+ *
+ * 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/mm.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <mach/map.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <asm/sizes.h>
+#include <linux/memory.h>
+#include <plat/media.h>
+
+#include "mfc_memory.h"
+#include "mfc_logmsg.h"
+#include "mfc_interface.h"
+
+void __iomem *mfc_sfr_base_vaddr;
+unsigned int mfc_port0_base_paddr, mfc_port1_base_paddr;
+unsigned char *mfc_port0_base_vaddr, *mfc_port1_base_vaddr;
+unsigned int mfc_port0_memsize, mfc_port1_memsize;
+unsigned int mfc_port1_alloc_base;
+
+unsigned int mfc_get_fw_buff_paddr(void)
+{
+ return mfc_port0_base_paddr;
+}
+
+unsigned char *mfc_get_fw_buff_vaddr(void)
+{
+ return mfc_port0_base_vaddr;
+}
+
+unsigned int mfc_get_port0_buff_paddr(void)
+{
+ return mfc_port0_base_paddr + MFC_FW_MAX_SIZE;
+}
+
+unsigned char *mfc_get_port0_buff_vaddr(void)
+{
+ return mfc_port0_base_vaddr + MFC_FW_MAX_SIZE;
+}
+
+unsigned char *mfc_get_port1_buff_vaddr(void)
+{
+ return mfc_port1_base_vaddr;
+}
+
+unsigned int mfc_get_port1_buff_paddr(void)
+{
+ return mfc_port1_alloc_base;
+}
+
+void mfc_set_port1_buff_paddr(unsigned int addr)
+{
+ mfc_port1_alloc_base = addr;
+}
diff --git a/drivers/media/video/samsung/mfc50/mfc_memory.h b/drivers/media/video/samsung/mfc50/mfc_memory.h
new file mode 100644
index 0000000..3c70965
--- /dev/null
+++ b/drivers/media/video/samsung/mfc50/mfc_memory.h
@@ -0,0 +1,111 @@
+/*
+ * drivers/media/video/samsung/mfc50/mfc_memory.h
+ *
+ * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
+ *
+ * Jaeryul Oh, Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * Change Logs
+ * 2009.09.14 - Beautify source code (Key Young, Park)
+ * 2009.10.08 - Apply 9/30 firmware(Key Young, Park)
+ * 2009.11.04 - remove mfc_common.[ch]
+ * seperate buffer alloc & set (Key Young, Park)
+ *
+ * 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 _MFC_MEMORY_H_
+#define _MFC_MEMORY_H_
+
+#include "mfc_opr.h"
+
+#ifdef CONFIG_VIDEO_MFC_MAX_INSTANCE
+#define MFC_MAX_INSTANCE_NUM (CONFIG_VIDEO_MFC_MAX_INSTANCE)
+#endif
+
+#define SET_MEM_1080P 1
+#define SET_MEM_720P 0
+
+#if SET_MEM_1080P
+/*
+ * Memory Configuration for 1080P
+ * MFC_FW_TOTAL_BUF_SIZE should be aligned to 4KB (page size)
+ */
+#define MFC_FW_TOTAL_BUF_SIZE (ALIGN_TO_4KB(MFC_FW_MAX_SIZE + MFC_MAX_INSTANCE_NUM * MFC_FW_BUF_SIZE))
+#define MFC_FW_MAX_SIZE (2 * 1024 * 1024) /* 2MB : 2x1024x1024 */
+#define MFC_FW_BUF_SIZE (512 * 1024) /* 512KB : 512x1024 size per instance */
+
+#define RISC_BUF_SIZE (0x80000) /* 512KB : 512x1024 size per instance */
+#define CPB_BUF_SIZE (0x300000) /* 3MB : 3x1024x1024 for decoder */
+#define DESC_BUF_SIZE (0x20000) /* 128KB : 128x1024 */
+#define SHARED_BUF_SIZE (0x10000) /* 64KB : 64x1024 */
+#define PRED_BUF_SIZE (0x10000) /* 64KB : 64x1024 */
+#define DEC_CODEC_BUF_SIZE (0x80000) /* 512KB : 512x1024 size per instance */
+#define ENC_CODEC_BUF_SIZE (0x50000) /* 320KB : 512x1024 size per instance */
+
+#define STREAM_BUF_SIZE (0x300000) /* 3MB : 3x1024x1024 for encoder */
+#define MV_BUF_SIZE (0x10000) /* 64KB : 64x1024 for encoder */
+
+#define H264DEC_CONTEXT_SIZE (640 * 1024) /* 600KB -> 640KB for alignment */
+#define VC1DEC_CONTEXT_SIZE (64 * 1024) /* 10KB -> 64KB for alignment */
+#define MPEG2DEC_CONTEXT_SIZE (64 * 1024) /* 10KB -> 64KB for alignment */
+#define H263DEC_CONTEXT_SIZE (64 * 1024) /* 10KB -> 64KB for alignment */
+#define MPEG4DEC_CONTEXT_SIZE (64 * 1024) /* 10KB -> 64KB for alignment */
+#define H264ENC_CONTEXT_SIZE (640 * 1024) /* 64KB -> 640KB for alignment */
+#define MPEG4ENC_CONTEXT_SIZE (64 * 1024) /* 10KB -> 64KB for alignment */
+#define H263ENC_CONTEXT_SIZE (64 * 1024) /* 10KB -> 64KB for alignment */
+
+#else
+/* Memory Configuration for 720P */
+#define MFC_FW_TOTAL_BUF_SIZE (ALIGN_TO_4KB(MFC_FW_MAX_SIZE + MFC_MAX_INSTANCE_NUM * MFC_FW_BUF_SIZE))
+#define MFC_FW_MAX_SIZE (2 * 1024 * 1024) /* 2MB : 2x1024x1024 */
+#define MFC_FW_BUF_SIZE (512 * 1024) /* 512KB : 512x1024 size per instance */
+
+#define RISC_BUF_SIZE (0x80000) /* 512KB : 512x1024 size per instance */
+#define CPB_BUF_SIZE (0x300000) /* 3MB : 3x1024x1024 for decoder */
+#define DESC_BUF_SIZE (0x20000) /* 128KB : 128x1024 */
+#define SHARED_BUF_SIZE (0x10000) /* 64KB : 64x1024 */
+#define PRED_BUF_SIZE (0x10000) /* 64KB : 64x1024 */
+#define DEC_CODEC_BUF_SIZE (0x80000) /* 512KB : 512x1024 size per instance */
+#define ENC_CODEC_BUF_SIZE (0x50000) /* 320KB : 512x1024 size per instance */
+
+#define STREAM_BUF_SIZE (0x200000) /* 2MB : 2x1024x1024 for encoder */
+#define MV_BUF_SIZE (0x10000) /* 64KB : 64x1024 for encoder */
+
+#define H264DEC_CONTEXT_SIZE (640 * 1024) /* 600KB -> 640KB for alignment */
+#define VC1DEC_CONTEXT_SIZE (64 * 1024) /* 10KB -> 64KB for alignment */
+#define MPEG2DEC_CONTEXT_SIZE (64 * 1024) /* 10KB -> 64KB for alignment */
+#define H263DEC_CONTEXT_SIZE (64 * 1024) /* 10KB -> 64KB for alignment */
+#define MPEG4DEC_CONTEXT_SIZE (64 * 1024) /* 10KB -> 64KB for alignment */
+#define H264ENC_CONTEXT_SIZE (64 * 1024) /* 10KB -> 64KB for alignment */
+#define MPEG4ENC_CONTEXT_SIZE (64 * 1024) /* 10KB -> 64KB for alignment */
+#define H263ENC_CONTEXT_SIZE (64 * 1024) /* 10KB -> 64KB for alignment */
+
+#endif
+
+unsigned int mfc_get_fw_buf_phys_addr(void);
+unsigned int mfc_get_risc_buf_phys_addr(int instNo);
+
+extern unsigned char *mfc_port0_base_vaddr; /* port1 */
+extern unsigned char *mfc_port1_base_vaddr; /* port0 */
+extern unsigned int mfc_port0_base_paddr, mfc_port1_base_paddr;
+extern unsigned int mfc_port0_memsize, mfc_port1_memsize;
+
+unsigned int mfc_get_fw_buff_paddr(void);
+unsigned char *mfc_get_fw_buff_vaddr(void);
+unsigned int mfc_get_port0_buff_paddr(void);
+unsigned char *mfc_get_port0_buff_vaddr(void);
+unsigned int mfc_get_port1_buff_paddr(void);
+unsigned char *mfc_get_port1_buff_vaddr(void);
+void mfc_set_port1_buff_paddr(unsigned int addr);
+
+extern void __iomem *mfc_sfr_base_vaddr;
+
+#define READL(offset) readl(mfc_sfr_base_vaddr + (offset))
+#define WRITEL(data, offset) writel((data), mfc_sfr_base_vaddr + (offset))
+
+#endif /* _MFC_MEMORY_H_ */
diff --git a/drivers/media/video/samsung/mfc50/mfc_opr.c b/drivers/media/video/samsung/mfc50/mfc_opr.c
new file mode 100644
index 0000000..39ca126
--- /dev/null
+++ b/drivers/media/video/samsung/mfc50/mfc_opr.c
@@ -0,0 +1,2576 @@
+/*
+ * drivers/media/video/samsung/mfc50/mfc_opr.c
+ *
+ * C file for Samsung MFC (Multi Function Codec - FIMV) driver
+ *
+ * Jaeryul Oh, Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * Change Logs
+ * 2009.09.14 - Beautify source code. (Key Young, Park)
+ * 2009.09.21 - Implement clock & power gating.
+ * including suspend & resume fuction. (Key Young, Park)
+ * 2009.09.23 - Use TILE mode encoding / Move MFC reserved memory
+ * before FIMC reserved memory. (Key Young, Park)
+ * 2009.09.24 - Minor patch. (Key Young, Park)
+ * 2009.10.08 - Apply 9/30 firmware(Key Young, Park)
+ * 2009.10.13 - Change wait_for_done (Key Young, Park)
+ * 2009.10.17 - Add error handling routine for buffer allocation (Key Young, Park)
+ * 2009.10.22 - Change codec name VC1AP_DEC -> VC1_DEC (Key Young, Park)
+ * 2009.10.27 - Update firmware (2009.10.15) (Key Young, Park)
+ * 2009.11.04 - get physical address via mfc_allocate_buffer (Key Young, Park)
+ * 2009.11.04 - remove mfc_common.[ch]
+ * seperate buffer alloc & set (Key Young, Park)
+ * 2009.11.06 - Apply common MFC API (Key Young, Park)
+ * 2009.11.06 - memset shared_memory (Key Young, Park)
+ * 2009.11.09 - implement packed PB (Key Young, Park)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/dma-mapping.h>
+#include <plat/regs-mfc.h>
+#include <asm/cacheflush.h>
+#include <mach/map.h>
+#include <plat/map-s5p.h>
+
+#include "mfc_opr.h"
+#include "mfc_logmsg.h"
+#include "mfc_memory.h"
+#include "mfc_buffer_manager.h"
+#include "mfc_interface.h"
+#include "mfc_shared_mem.h"
+#include "mfc_intr.h"
+
+
+/* DEBUG_MAKE_RAW is option to dump input stream data of MFC.*/
+#define DEBUG_MAKE_RAW 0 /* Making Dec/Enc Debugging Files */
+#define ENABLE_DEBUG_MFC_INIT 0
+#define ENABLE_MFC_REGISTER_DEBUG 0 /* 0: Disable 1: Enable */
+#define ENABLE_ENC_MB 1
+
+#define ENABLE_CHECK_START_CODE 1
+#define ENABLE_CHECK_NULL_STREAM 1
+#define ENABLE_CHECK_STREAM_SIZE 1
+#define ENABLE_CHECK_SEQ_HEADER 0
+
+#if DEBUG_MAKE_RAW
+#define ENABLE_DEBUG_DEC_EXE_INTR_ERR 1 /* You must make the "dec_in" folder in data folder.*/
+#define ENABLE_DEBUG_DEC_EXE_INTR_OK 1 /* Make log about Normal Interrupts.*/
+#define ENABLE_DEBUG_ENC_EXE_INTR_ERR 1 /* You must make the "enc_in" folder in data folder.*/
+#endif
+
+#ifdef ENABLE_DEBUG_DEC_EXE_INTR_ERR
+#if ENABLE_DEBUG_DEC_EXE_INTR_ERR
+#define ENABLE_DEBUG_DEC_EXE_PARSER_ERR 1 /* Firstly, Set ENABLE_DEBUG_DEC_EXE_INTR_ERR is "1". */
+#endif
+#endif
+
+#define WRITEL_SHARED_MEM(data, address) \
+ do { \
+ writel(data, address); \
+ dmac_flush_range((void *)address, (void *)(address + 4)); \
+ } while (0)
+
+#if DEBUG_MAKE_RAW
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/fcntl.h>
+#include <linux/uaccess.h>
+#endif
+
+
+static void mfc_backup_context(struct mfc_inst_ctx *mfc_ctx);
+static void mfc_restore_context(struct mfc_inst_ctx *mfc_ctx);
+static void mfc_set_encode_init_param(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args);
+static int mfc_get_inst_no(struct mfc_inst_ctx *mfc_ctx, unsigned int context_addr, int context_size);
+static enum mfc_error_code mfc_encode_header(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args);
+static enum mfc_error_code mfc_decode_one_frame(struct mfc_inst_ctx *mfc_ctx, struct mfc_dec_exe_arg *dec_arg, unsigned int *consumed_strm_size);
+
+static void mfc_set_codec_buffer(struct mfc_inst_ctx *mfc_ctx);
+static void mfc_set_dec_frame_buffer(struct mfc_inst_ctx *mfc_ctx);
+static void mfc_set_dec_stream_buffer(struct mfc_inst_ctx *mfc_ctx, int buf_addr, unsigned int buf_size);
+static void mfc_set_enc_ref_buffer(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args);
+
+static enum mfc_error_code mfc_alloc_codec_buffer(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args);
+static enum mfc_error_code mfc_alloc_dec_frame_buffer(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args);
+static enum mfc_error_code mfc_alloc_context_buffer(struct mfc_inst_ctx *mfc_ctx, unsigned int mapped_addr, unsigned int *context_addr, int *size);
+static enum mfc_error_code mfc_alloc_stream_ref_buffer(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args);
+
+static int CheckMPEG4StartCode(unsigned char *src_mem, unsigned int remainSize);
+static int CheckDecStartCode(unsigned char *src_mem, unsigned int nstreamSize, enum ssbsip_mfc_codec_type nCodecType);
+static int CheckNullStream(unsigned char *src_mem, unsigned int streamSize);
+
+static int mfc_mem_inst_no[MFC_MAX_INSTANCE_NUM];
+static bool mCheckType;
+
+
+/*
+ * Debugging Functions Definition
+ * tile_to_linear_4x2(..)
+ * calculate_seq_size(..)
+ * printk_mfc_init_info(..)
+ */
+#if DEBUG_MAKE_RAW
+static int mframe_cnt;
+static int mImgWidth;
+static int mImgHight;
+
+static void copy16(unsigned char *p_linear_addr, unsigned char *p_tiled_addr, int mm, int nn);
+static void write_file(char *filename, unsigned char *data, unsigned int nSize);
+static int tile_4x2_read(int x_size, int y_size, int x_pos, int y_pos);
+static void tile_to_linear_4x2(unsigned char *p_linear_addr, unsigned char *p_tiled_addr, unsigned int x_size, unsigned int y_size);
+#endif
+
+#if ENABLE_CHECK_SEQ_HEADER
+static int calculate_seq_size(mfc_args *args);
+#endif
+
+#if ENABLE_DEBUG_MFC_INIT
+void printk_mfc_init_info(struct mfc_inst_ctx *mfc_ctx, struct mfc_args *args);
+#endif
+
+#ifdef ENABLE_DEBUG_DEC_EXE_INTR_ERR
+#if ENABLE_DEBUG_DEC_EXE_INTR_ERR
+void printk_mfc_dec_exe_info(struct mfc_inst_ctx *mfc_ctx, struct mfc_dec_exe_arg *dec_arg);
+void makefile_mfc_dec_err_info(struct mfc_inst_ctx *mfc_ctx, struct mfc_dec_exe_arg *dec_arg, int nReturnErrCode);
+void makefile_mfc_decinit_err_info(struct mfc_inst_ctx *mfc_ctx, struct mfc_dec_init_arg *decinit_arg, int nReturnErrCode);
+
+static unsigned int mcontext_addr;
+static int mcontext_size;
+static int mIsDangerError;
+#endif
+#endif
+
+#ifdef ENABLE_DEBUG_DEC_EXE_INTR_ERR
+#if ENABLE_DEBUG_ENC_EXE_INTR_ERR
+void makefile_mfc_enc_err_info(struct mfc_enc_exe_arg *enc_arg);
+#endif
+#endif
+
+#if ENABLE_MFC_REGISTER_DEBUG
+void mfc_fw_debug(mfc_wait_done_type command);
+#endif
+
+#ifdef ENABLE_DEBUG_DEC_EXE_INTR_ERR
+#if ENABLE_DEBUG_ENC_EXE_INTR_ERR
+static unsigned char pResLinearbuf[1280*720*3/2];
+#endif
+#endif
+
+#define MC_STATUS_TIMEOUT 1000 /* ms */
+
+bool mfc_cmd_reset(void)
+{
+ unsigned int mc_status;
+ unsigned long timeo = jiffies;
+
+ timeo += msecs_to_jiffies(MC_STATUS_TIMEOUT);
+
+ /* Stop procedure */
+ WRITEL(0x3f6, MFC_SW_RESET); /* reset RISC */
+ WRITEL(0x3e2, MFC_SW_RESET); /* All reset except for MC */
+ mdelay(10);
+
+ /* Check MC status */
+ do {
+ mc_status = (READL(MFC_MC_STATUS) & 0x3);
+
+ if (mc_status == 0)
+ break;
+
+ schedule_timeout_uninterruptible(1);
+ } while (time_before(jiffies, timeo));
+
+ if (mc_status != 0)
+ return false;
+
+ WRITEL(0x0, MFC_SW_RESET);
+ WRITEL(0x3fe, MFC_SW_RESET);
+
+ return true;
+}
+
+static bool mfc_cmd_host2risc(enum mfc_facade_cmd cmd, int arg1, int arg2, int arg3, int arg4)
+{
+ enum mfc_facade_cmd cur_cmd = 0;
+ unsigned long timeo = jiffies;
+ timeo += 20; /* waiting for 100ms */
+
+ /* wait until host to risc command register becomes 'H2R_CMD_EMPTY' */
+ while (time_before(jiffies, timeo)) {
+ cur_cmd = READL(MFC_HOST2RISC_COMMAND);
+ if (cur_cmd == H2R_CMD_EMPTY)
+ break;
+ msleep_interruptible(2);
+ }
+
+ if (cur_cmd != H2R_CMD_EMPTY)
+ return false;
+
+ WRITEL(arg1, MFC_HOST2RISC_ARG1);
+ WRITEL(arg2, MFC_HOST2RISC_ARG2);
+ WRITEL(arg3, MFC_HOST2RISC_ARG3);
+ WRITEL(arg4, MFC_HOST2RISC_ARG4);
+ WRITEL(cmd, MFC_HOST2RISC_COMMAND);
+
+ return true;
+}
+
+static void mfc_backup_context(struct mfc_inst_ctx *mfc_ctx)
+{
+}
+
+static void mfc_restore_context(struct mfc_inst_ctx *mfc_ctx)
+{
+}
+
+static void mfc_set_dec_stream_buffer(struct mfc_inst_ctx *mfc_ctx, int buf_addr, unsigned int buf_size)
+{
+ unsigned int port0_base_paddr;
+
+ mfc_debug_L0("inst_no : %d, buf_addr : 0x%08x, buf_size : 0x%08x\n", mfc_ctx->InstNo, buf_addr, buf_size);
+ if (mfc_ctx->buf_type == MFC_BUFFER_CACHE) {
+ unsigned char *in_vir;
+ in_vir = phys_to_virt(buf_addr);
+ dma_map_single(NULL, in_vir, buf_size, DMA_TO_DEVICE);
+ }
+ port0_base_paddr = mfc_port0_base_paddr;
+
+ /* release buffer */
+ WRITEL(0xffffffff, MFC_SI_CH0_RELEASE_BUFFER);
+
+ /* Set stream & desc buffer */
+ WRITEL((buf_addr - port0_base_paddr) >> 11, MFC_SI_CH0_ES_ADDR);
+ WRITEL(buf_size, MFC_SI_CH0_ES_DEC_UNIT_SIZE);
+ WRITEL(CPB_BUF_SIZE, MFC_SI_CH0_CPB_SIZE);
+ WRITEL((mfc_ctx->desc_buff_paddr - port0_base_paddr) >> 11, MFC_SI_CH0_DESC_ADDR);
+ WRITEL(DESC_BUF_SIZE, MFC_SI_CH0_DESC_SIZE);
+
+ mfc_debug_L0("stream_paddr: 0x%08x, desc_paddr: 0x%08x\n", buf_addr, buf_addr + CPB_BUF_SIZE);
+}
+
+static enum mfc_error_code mfc_alloc_dec_frame_buffer(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args)
+{
+ struct mfc_dec_init_arg *init_arg;
+ enum mfc_error_code ret_code;
+ union mfc_args local_param;
+ struct mfc_frame_buf_arg buf_size;
+ unsigned int luma_size, chroma_size;
+ unsigned int luma_plane_sz, chroma_plane_sz, mv_plane_sz;
+
+ init_arg = (struct mfc_dec_init_arg *)args;
+
+ /* width : 128B align, height : 32B align, size: 8KB align */
+ luma_plane_sz = ALIGN_TO_128B(init_arg->out_img_width) * ALIGN_TO_32B(init_arg->out_img_height);
+ luma_plane_sz = ALIGN_TO_8KB(luma_plane_sz);
+ chroma_plane_sz = ALIGN_TO_128B(init_arg->out_img_width) * ALIGN_TO_32B(init_arg->out_img_height / 2);
+ chroma_plane_sz = ALIGN_TO_8KB(chroma_plane_sz);
+ mv_plane_sz = 0;
+
+ buf_size.luma = luma_plane_sz;
+ buf_size.chroma = chroma_plane_sz;
+
+ if (mfc_ctx->MfcCodecType == H264_DEC) {
+ /* width : 128B align, height : 32B align, size: 8KB align */
+ mv_plane_sz = ALIGN_TO_128B(init_arg->out_img_width) * ALIGN_TO_32B(init_arg->out_img_height / 4);
+ mv_plane_sz = ALIGN_TO_8KB(mv_plane_sz);
+ buf_size.luma += mv_plane_sz;
+ }
+
+ mfc_ctx->shared_mem.allocated_luma_dpb_size = luma_plane_sz;
+ mfc_ctx->shared_mem.allocated_chroma_dpb_size = chroma_plane_sz;
+ mfc_ctx->shared_mem.allocated_mv_size = mv_plane_sz;
+
+ luma_size = buf_size.luma * mfc_ctx->totalDPBCnt;
+ chroma_size = buf_size.chroma * mfc_ctx->totalDPBCnt;
+
+ /*
+ * Allocate chroma & (Mv in case of H264) buf
+ */
+ init_arg->out_frame_buf_size.chroma = chroma_size;
+
+ memset(&local_param, 0, sizeof(local_param));
+ local_param.mem_alloc.buff_size = chroma_size;
+ local_param.mem_alloc.mapped_addr = init_arg->in_mapped_addr;
+
+ ret_code = mfc_allocate_buffer(mfc_ctx, &(local_param), 0);
+ if (ret_code < 0)
+ return ret_code;
+
+ init_arg->out_u_addr.chroma = local_param.mem_alloc.out_uaddr;
+ init_arg->out_p_addr.chroma = local_param.mem_alloc.out_paddr;
+
+ /*
+ * Allocate luma buf
+ */
+ init_arg->out_frame_buf_size.luma = luma_size;
+
+ memset(&local_param, 0, sizeof(local_param));
+ local_param.mem_alloc.buff_size = luma_size;
+ local_param.mem_alloc.mapped_addr = init_arg->in_mapped_addr;
+
+ ret_code = mfc_allocate_buffer(mfc_ctx, &(local_param), 1);
+ if (ret_code < 0)
+ return ret_code;
+
+ init_arg->out_u_addr.luma = local_param.mem_alloc.out_uaddr;
+ init_arg->out_p_addr.luma = local_param.mem_alloc.out_paddr;
+
+ mfc_ctx->dec_dpb_buff_paddr = init_arg->out_p_addr;
+
+ return MFCINST_RET_OK;
+}
+
+
+
+static void mfc_set_dec_frame_buffer(struct mfc_inst_ctx *mfc_ctx)
+{
+ unsigned int port0_base_paddr, port1_base_paddr, i;
+ struct mfc_frame_buf_arg dpb_buff_addr;
+ unsigned int luma_plane_sz, chroma_plane_sz, mv_plane_sz;
+
+ dpb_buff_addr = mfc_ctx->dec_dpb_buff_paddr;
+ port0_base_paddr = mfc_port0_base_paddr;
+ port1_base_paddr = mfc_port1_base_paddr;
+
+ luma_plane_sz = mfc_ctx->shared_mem.allocated_luma_dpb_size;
+ chroma_plane_sz = mfc_ctx->shared_mem.allocated_chroma_dpb_size;
+ mv_plane_sz = mfc_ctx->shared_mem.allocated_mv_size;
+
+ mfc_debug("luma_buf_addr start : 0x%08x luma_buf_size : %d\n", dpb_buff_addr.luma, (luma_plane_sz + mv_plane_sz));
+ mfc_debug("chroma_buf_addr start : 0x%08x chroma_buf_size : %d\n", dpb_buff_addr.chroma, chroma_plane_sz);
+
+ if (mfc_ctx->MfcCodecType == H264_DEC) {
+ for (i = 0; i < mfc_ctx->totalDPBCnt; i++) {
+ mfc_debug("DPB[%d] luma_buf_addr : 0x%08x luma_buf_size : %d\n", i, dpb_buff_addr.luma, luma_plane_sz);
+ mfc_debug("DPB[%d] chroma_buf_addr : 0x%08x chroma_buf_size : %d\n", i, dpb_buff_addr.chroma, chroma_plane_sz);
+ mfc_debug("DPB[%d] mv_buf_addr : 0x%08x mv_plane_sz : %d\n", i, dpb_buff_addr.luma + luma_plane_sz, mv_plane_sz);
+
+ /* set Luma address */
+ WRITEL((dpb_buff_addr.luma - port1_base_paddr) >> 11, MFC_H264DEC_LUMA + (4 * i));
+ WRITEL((dpb_buff_addr.luma + luma_plane_sz - port1_base_paddr) >> 11, MFC_H264DEC_MV + (4 * i));
+ dpb_buff_addr.luma += (luma_plane_sz + mv_plane_sz);
+
+ /* set Chroma address & set MV address */
+ WRITEL((dpb_buff_addr.chroma - port0_base_paddr) >> 11, MFC_H264DEC_CHROMA + (4 * i));
+ dpb_buff_addr.chroma += chroma_plane_sz;
+ }
+ } else {
+ for (i = 0; i < mfc_ctx->totalDPBCnt; i++) {
+ mfc_debug("DPB[%d] luma_buf_addr : 0x%08x luma_buf_size : %d\n", i, dpb_buff_addr.luma, luma_plane_sz);
+ mfc_debug("DPB[%d] chroma_buf_addr : 0x%08x chroma_buf_size : %d\n", i, dpb_buff_addr.chroma, chroma_plane_sz);
+
+ /* set Luma address */
+ WRITEL((dpb_buff_addr.luma - port1_base_paddr) >> 11, MFC_DEC_LUMA + (4 * i));
+ dpb_buff_addr.luma += luma_plane_sz;
+
+ /* set Chroma address */
+ WRITEL((dpb_buff_addr.chroma - port0_base_paddr) >> 11, MFC_DEC_CHROMA + (4 * i));
+ dpb_buff_addr.chroma += chroma_plane_sz;
+ }
+ }
+
+ mfc_debug("luma_buf_addr end : 0x%08x\n", dpb_buff_addr.luma);
+ mfc_debug("chroma_buf_addr end : 0x%08x\n", dpb_buff_addr.chroma);
+}
+
+/* Allocate buffers for encoder */
+static enum mfc_error_code mfc_alloc_stream_ref_buffer(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args)
+{
+ struct mfc_enc_init_mpeg4_arg *init_arg;
+ union mfc_args local_param;
+ unsigned int luma_plane_sz, chroma_plane_sz;
+ enum mfc_error_code ret_code = MFCINST_RET_OK;
+ struct mfc_frame_buf_arg buf_size;
+
+ init_arg = (struct mfc_enc_init_mpeg4_arg *)args;
+
+ /* width : 128B align, height : 32B align, size: 8KB align */
+ luma_plane_sz = ALIGN_TO_128B(init_arg->in_width) * ALIGN_TO_32B(init_arg->in_height);
+ luma_plane_sz = ALIGN_TO_8KB(luma_plane_sz);
+ chroma_plane_sz = ALIGN_TO_128B(init_arg->in_width) * ALIGN_TO_32B(init_arg->in_height / 2);
+ chroma_plane_sz = ALIGN_TO_8KB(chroma_plane_sz);
+
+ buf_size.luma = luma_plane_sz;
+ buf_size.chroma = chroma_plane_sz;
+
+ /*
+ * Allocate stream ref Y0, Y1 buf
+ */
+ init_arg->out_buf_size.strm_ref_y = STREAM_BUF_SIZE + (buf_size.luma * 2);
+
+ memset(&local_param, 0, sizeof(local_param));
+ local_param.mem_alloc.buff_size = init_arg->out_buf_size.strm_ref_y;
+ local_param.mem_alloc.mapped_addr = init_arg->in_mapped_addr;
+
+ ret_code = mfc_allocate_buffer(mfc_ctx, &(local_param), 0);
+ if (ret_code < 0)
+ return ret_code;
+
+ init_arg->out_u_addr.strm_ref_y = local_param.mem_alloc.out_uaddr;
+ init_arg->out_p_addr.strm_ref_y = local_param.mem_alloc.out_paddr;
+
+ /*
+ * Allocate ref C0, C1, Y2, C2, Y3, C3 buf XXX : remove MV buffer
+ */
+ init_arg->out_buf_size.mv_ref_yc = (buf_size.luma * 2) + (buf_size.chroma * 4);
+
+ memset(&local_param, 0, sizeof(local_param));
+ local_param.mem_alloc.buff_size = init_arg->out_buf_size.mv_ref_yc;
+ local_param.mem_alloc.mapped_addr = init_arg->in_mapped_addr;
+
+ ret_code = mfc_allocate_buffer(mfc_ctx, &(local_param), 1);
+ if (ret_code < 0)
+ return ret_code;
+
+ init_arg->out_u_addr.mv_ref_yc = local_param.mem_alloc.out_uaddr;
+ init_arg->out_p_addr.mv_ref_yc = local_param.mem_alloc.out_paddr;
+
+ return ret_code;
+}
+
+static void mfc_set_enc_ref_buffer(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args)
+{
+ unsigned int port0_base_paddr, port1_base_paddr, i;
+ struct mfc_strm_ref_buf_arg ref_buf_addr;
+ unsigned int luma_plane_sz, chroma_plane_sz;
+ struct mfc_enc_init_mpeg4_arg *init_arg;
+
+ init_arg = (struct mfc_enc_init_mpeg4_arg *)args;
+
+ /* width : 128B align, height : 32B align, size: 8KB align */
+ luma_plane_sz = ALIGN_TO_128B(init_arg->in_width) * ALIGN_TO_32B(init_arg->in_height);
+ luma_plane_sz = ALIGN_TO_8KB(luma_plane_sz);
+ chroma_plane_sz = ALIGN_TO_128B(init_arg->in_width) * ALIGN_TO_32B(init_arg->in_height / 2);
+ chroma_plane_sz = ALIGN_TO_8KB(chroma_plane_sz);
+
+ ref_buf_addr = init_arg->out_p_addr;
+ mfc_debug("strm_ref_y_buf_addr : 0x%08x, strm_ref_y_buf_size : %d\n",
+ ref_buf_addr.strm_ref_y, init_arg->out_buf_size.strm_ref_y);
+ mfc_debug("mv_ref_yc_buf_addr : 0x%08x, mv_ref_yc_buf_size : %d\n",
+ ref_buf_addr.mv_ref_yc, init_arg->out_buf_size.mv_ref_yc);
+
+ port0_base_paddr = mfc_port0_base_paddr;
+ port1_base_paddr = mfc_port1_base_paddr;
+
+ mfc_debug("stream_buf_addr : 0x%08x\n", ref_buf_addr.strm_ref_y);
+ ref_buf_addr.strm_ref_y += STREAM_BUF_SIZE;
+
+ /* Set Y0, Y1 ref buffer address */
+ mfc_debug("REF[0] luma_buf_addr : 0x%08x luma_buf_size : %d\n", ref_buf_addr.strm_ref_y, luma_plane_sz);
+ WRITEL((ref_buf_addr.strm_ref_y - port0_base_paddr) >> 11, MFC_ENC_DPB_Y0_ADDR);
+ ref_buf_addr.strm_ref_y += luma_plane_sz;
+ mfc_debug("REF[1] luma_buf_addr : 0x%08x luma_buf_size : %d\n", ref_buf_addr.strm_ref_y, luma_plane_sz);
+ WRITEL((ref_buf_addr.strm_ref_y - port0_base_paddr) >> 11, MFC_ENC_DPB_Y1_ADDR);
+
+ /* Set Y2, Y3 ref buffer address */
+ mfc_debug("REF[2] luma_buf_addr : 0x%08x luma_buf_size : %d\n", ref_buf_addr.mv_ref_yc, luma_plane_sz);
+ WRITEL((ref_buf_addr.mv_ref_yc - port1_base_paddr) >> 11, MFC_ENC_DPB_Y2_ADDR);
+ ref_buf_addr.mv_ref_yc += luma_plane_sz;
+ mfc_debug("REF[3] luma_buf_addr : 0x%08x luma_buf_size : %d\n", ref_buf_addr.mv_ref_yc, luma_plane_sz);
+ WRITEL((ref_buf_addr.mv_ref_yc - port1_base_paddr) >> 11, MFC_ENC_DPB_Y3_ADDR);
+ ref_buf_addr.mv_ref_yc += luma_plane_sz;
+
+ /* Set C0, C1, C2, C3 ref buffer address */
+ for (i = 0; i < 4; i++) {
+ mfc_debug("REF[%d] chroma_buf_addr : 0x%08x chroma_buf_size : %d\n", i, ref_buf_addr.mv_ref_yc, chroma_plane_sz);
+ WRITEL((ref_buf_addr.mv_ref_yc - port1_base_paddr) >> 11, MFC_ENC_DPB_C0_ADDR + (4 * i));
+ ref_buf_addr.mv_ref_yc += chroma_plane_sz;
+ }
+}
+
+static enum mfc_error_code mfc_alloc_codec_buffer(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args)
+{
+ struct mfc_dec_init_arg *init_arg;
+ enum mfc_error_code ret_code;
+ union mfc_args local_param;
+
+ init_arg = (struct mfc_dec_init_arg *)args;
+
+ memset(&local_param, 0, sizeof(local_param));
+ if (is_dec_codec(mfc_ctx->MfcCodecType))
+ local_param.mem_alloc.buff_size = DEC_CODEC_BUF_SIZE + SHARED_BUF_SIZE;
+ else
+ local_param.mem_alloc.buff_size = ENC_CODEC_BUF_SIZE + SHARED_BUF_SIZE;
+
+ local_param.mem_alloc.mapped_addr = init_arg->in_mapped_addr;
+ ret_code = mfc_allocate_buffer(mfc_ctx, &(local_param), 0);
+ if (ret_code < 0)
+ return ret_code;
+
+ mfc_ctx->codec_buff_paddr = local_param.mem_alloc.out_paddr;
+ if (is_dec_codec(mfc_ctx->MfcCodecType))
+ mfc_ctx->shared_mem_paddr = mfc_ctx->codec_buff_paddr + DEC_CODEC_BUF_SIZE;
+ else
+ mfc_ctx->shared_mem_paddr = mfc_ctx->codec_buff_paddr + ENC_CODEC_BUF_SIZE;
+
+ mfc_ctx->shared_mem_vaddr = (unsigned int)mfc_get_fw_buff_vaddr() + (mfc_ctx->shared_mem_paddr - mfc_port0_base_paddr);
+ memset((void *)mfc_ctx->shared_mem_vaddr, 0x0, SHARED_MEM_MAX);
+
+ if (mfc_ctx->MfcCodecType == H264_ENC) {
+ memset(&local_param, 0, sizeof(local_param));
+ local_param.mem_alloc.buff_size = PRED_BUF_SIZE;
+ local_param.mem_alloc.mapped_addr = init_arg->in_mapped_addr;
+ ret_code = mfc_allocate_buffer(mfc_ctx, &(local_param), 1);
+ if (ret_code < 0)
+ return ret_code;
+
+ mfc_ctx->pred_buff_paddr = local_param.mem_alloc.out_paddr;
+ }
+
+ return MFCINST_RET_OK;
+}
+
+
+
+static void mfc_set_codec_buffer(struct mfc_inst_ctx *mfc_ctx)
+{
+ unsigned int codec_buff_paddr;
+ unsigned int pred_buff_paddr;
+ unsigned int port0_base_paddr;
+ unsigned int port1_base_paddr;
+
+ port0_base_paddr = mfc_port0_base_paddr;
+ port1_base_paddr = mfc_port1_base_paddr;
+ codec_buff_paddr = mfc_ctx->codec_buff_paddr;
+ pred_buff_paddr = mfc_ctx->pred_buff_paddr;
+
+ mfc_debug("inst_no : %d, codec_buf_start: 0x%08x\n", mfc_ctx->InstNo, codec_buff_paddr);
+
+ switch (mfc_ctx->MfcCodecType) {
+ case H264_DEC:
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_H264DEC_VERT_NB_MV);
+ codec_buff_paddr += (16 << 10);
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_H264DEC_NB_IP);
+ codec_buff_paddr += (32 << 10);
+ break;
+
+ case MPEG4_DEC:
+ case H263_DEC:
+ case XVID_DEC:
+ case FIMV1_DEC:
+ case FIMV2_DEC:
+ case FIMV3_DEC:
+ case FIMV4_DEC:
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_NB_DCAC);
+ codec_buff_paddr += (16 << 10);
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_UPNB_MV);
+ codec_buff_paddr += (68 << 10);
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_SUB_ANCHOR_MV);
+ codec_buff_paddr += (136 << 10);
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_OVERLAP_TRANSFORM);
+ codec_buff_paddr += (32 << 10);
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_STX_PARSER);
+ codec_buff_paddr += (68 << 10);
+ break;
+
+ case VC1_DEC:
+ case VC1RCV_DEC:
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_NB_DCAC);
+ codec_buff_paddr += (16 << 10);
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_UPNB_MV);
+ codec_buff_paddr += (68 << 10);
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_SUB_ANCHOR_MV);
+ codec_buff_paddr += (136 << 10);
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_OVERLAP_TRANSFORM);
+ codec_buff_paddr += (32 << 10);
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_BITPLANE3);
+ codec_buff_paddr += (8 << 10);
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_BITPLANE2);
+ codec_buff_paddr += (8 << 10);
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_BITPLANE1);
+ codec_buff_paddr += (8 << 10);
+ break;
+
+ case MPEG1_DEC:
+ case MPEG2_DEC:
+ break;
+
+ case H264_ENC:
+ case MPEG4_ENC:
+ case H263_ENC:
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_UPPER_MV_ADDR);
+ codec_buff_paddr += (64 << 10);
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_DIRECT_COLZERO_FLAG_ADDR);
+ codec_buff_paddr += (64 << 10);
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_UPPER_INTRA_MD_ADDR);
+ codec_buff_paddr += (64 << 10);
+ if (mfc_ctx->MfcCodecType == H264_ENC) {
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_NBOR_INFO_MPENC_ADDR);
+ WRITEL((pred_buff_paddr - port1_base_paddr) >> 11, MFC_UPPER_INTRA_PRED_ADDR);
+ } else {
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_ACDC_COEF_BASE_ADDR);
+ }
+ codec_buff_paddr += (64 << 10);
+ break;
+
+ default:
+ break;
+ }
+
+ mfc_debug("inst_no : %d, codec_buf_end : 0x%08x\n", mfc_ctx->InstNo, codec_buff_paddr);
+}
+
+/* This function sets the MFC SFR values according to the input arguments. */
+static void mfc_set_encode_init_param(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args)
+{
+ unsigned int ms_size;
+ struct mfc_enc_init_mpeg4_arg *enc_init_mpeg4_arg;
+ struct mfc_enc_init_h264_arg *enc_init_h264_arg;
+
+ enc_init_mpeg4_arg = (struct mfc_enc_init_mpeg4_arg *)args;
+ enc_init_h264_arg = (struct mfc_enc_init_h264_arg *)args;
+
+#if DEBUG_MAKE_RAW
+ mImgHight = enc_init_mpeg4_arg->in_height;
+ mImgWidth = enc_init_mpeg4_arg->in_width;
+#endif
+
+ mfc_debug("mfc_codec_type : %d\n", mfc_ctx->MfcCodecType);
+
+ WRITEL(enc_init_mpeg4_arg->in_width, MFC_HSIZE_PX);
+ if (enc_init_mpeg4_arg->in_interlace_mode)
+ WRITEL(enc_init_mpeg4_arg->in_height >> 1, MFC_VSIZE_PX);
+ else
+ WRITEL(enc_init_mpeg4_arg->in_height, MFC_VSIZE_PX);
+
+ /* H.263 does not support field picture */
+ WRITEL(enc_init_mpeg4_arg->in_interlace_mode, MFC_PICTURE_STRUCT);
+ WRITEL(0, MFC_ENC_INT_MASK); /* mask interrupt */
+ WRITEL(1, MFC_STR_BF_MODE_CTRL); /* stream buf frame mode */
+ WRITEL((1 << 18) | (enc_init_mpeg4_arg->in_BframeNum << 16) |
+ enc_init_mpeg4_arg->in_gop_num, MFC_ENC_PIC_TYPE_CTRL);
+
+ /* Multi-slice options */
+ if (enc_init_mpeg4_arg->in_MS_mode) {
+ ms_size = (mfc_ctx->MfcCodecType == H263_ENC) ? 0 : enc_init_mpeg4_arg->in_MS_size;
+ switch (enc_init_mpeg4_arg->in_MS_mode) {
+ case 1:
+ WRITEL(0x1, MFC_ENC_MSLICE_CTRL);
+ WRITEL(ms_size, MFC_ENC_MSLICE_MB);
+ break;
+
+ case 2:
+ WRITEL(0x3, MFC_ENC_MSLICE_CTRL);
+ WRITEL(ms_size, MFC_ENC_MSLICE_BYTE);
+ break;
+
+ default:
+ mfc_err("Invalid Multi-slice mode type\n");
+ break;
+ }
+ } else {
+ WRITEL(0, MFC_ENC_MSLICE_CTRL);
+ }
+
+ /* Set circular intra refresh MB count */
+ WRITEL(enc_init_mpeg4_arg->in_mb_refresh, MFC_ENC_CIR_CTRL);
+
+ if (enc_init_mpeg4_arg->in_frame_map == 1)
+ WRITEL(MEM_STRUCT_TILE_ENC, MFC_ENC_MAP_FOR_CUR);
+ else
+ WRITEL(MEM_STRUCT_LINEAR, MFC_ENC_MAP_FOR_CUR);
+
+ /* Set padding control */
+ WRITEL((enc_init_mpeg4_arg->in_pad_ctrl_on << 31) |
+ (enc_init_mpeg4_arg->in_cr_pad_val << 16) |
+ (enc_init_mpeg4_arg->in_cb_pad_val << 8) |
+ (enc_init_mpeg4_arg->in_luma_pad_val << 0), MFC_ENC_PADDING_CTRL);
+
+ /* Set Rate Control */
+ if (enc_init_mpeg4_arg->in_RC_frm_enable) {
+ WRITEL(enc_init_mpeg4_arg->in_RC_framerate, MFC_RC_FRAME_RATE);
+ WRITEL(enc_init_mpeg4_arg->in_RC_bitrate, MFC_RC_BIT_RATE);
+ WRITEL(enc_init_mpeg4_arg->in_RC_rpara, MFC_RC_RPARA);
+ }
+
+ WRITEL(enc_init_mpeg4_arg->in_RC_qbound, MFC_RC_QBOUND);
+
+ switch (mfc_ctx->MfcCodecType) {
+ case H264_ENC:
+ WRITEL(enc_init_h264_arg->in_profile_level, MFC_PROFILE);
+ WRITEL(enc_init_h264_arg->in_transform8x8_mode, MFC_H264_ENC_TRANS_8X8_FLAG);
+ WRITEL(enc_init_h264_arg->in_deblock_filt, MFC_LF_CONTROL);
+ WRITEL(((enc_init_h264_arg->in_deblock_alpha_C0 * 2) & 0x1f), MFC_LF_ALPHA_OFF);
+ WRITEL(((enc_init_h264_arg->in_deblock_beta * 2) & 0x1f), MFC_LF_BETA_OFF);
+ WRITEL(1, MFC_EDFU_SF_EPB_ON_CTRL); /* Auto EPB insertion on, only for h264 */
+
+ /* if in_RC_mb_enable is '1' */
+#if ENABLE_ENC_MB
+ if (enc_init_h264_arg->in_RC_frm_enable != 1)
+ enc_init_h264_arg->in_RC_frm_enable = 1;
+ if (enc_init_h264_arg->in_RC_mb_enable != 1)
+ enc_init_h264_arg->in_RC_mb_enable = 1;
+#endif
+
+ WRITEL((enc_init_h264_arg->in_RC_frm_enable << 9) |
+ (enc_init_h264_arg->in_RC_mb_enable << 8) |
+ (enc_init_h264_arg->in_frame_qp & 0x3f),
+ MFC_RC_CONFIG);
+
+ if (enc_init_h264_arg->in_RC_mb_enable) {
+ WRITEL((enc_init_h264_arg->in_RC_mb_dark_disable << 3)|
+ (enc_init_h264_arg->in_RC_mb_smooth_disable << 2)|
+ (enc_init_h264_arg->in_RC_mb_static_disable << 1)|
+ (enc_init_h264_arg->in_RC_mb_activity_disable << 0),
+ MFC_RC_MB_CTRL);
+ }
+
+ WRITEL((enc_init_h264_arg->in_symbolmode & 0x1), MFC_H264_ENC_ENTRP_MODE);
+
+ if (enc_init_h264_arg->in_reference_num > 2)
+ enc_init_h264_arg->in_reference_num = 2;
+ if (enc_init_h264_arg->in_ref_num_p > enc_init_h264_arg->in_reference_num)
+ enc_init_h264_arg->in_ref_num_p = enc_init_h264_arg->in_reference_num;
+ WRITEL((enc_init_h264_arg->in_ref_num_p << 5) |
+ (enc_init_h264_arg->in_reference_num),
+ MFC_H264_ENC_NUM_OF_REF);
+
+ WRITEL(enc_init_h264_arg->in_md_interweight_pps, MFC_H264_ENC_MDINTER_WEIGHT);
+ WRITEL(enc_init_h264_arg->in_md_intraweight_pps, MFC_H264_ENC_MDINTRA_WEIGHT);
+ break;
+
+ case MPEG4_ENC:
+ WRITEL(enc_init_mpeg4_arg->in_profile_level, MFC_PROFILE);
+ WRITEL((enc_init_mpeg4_arg->in_RC_frm_enable << 9) |
+ (enc_init_mpeg4_arg->in_frame_qp & 0x3f),
+ MFC_RC_CONFIG);
+ WRITEL(enc_init_mpeg4_arg->in_qpelME_enable, MFC_MPEG4_ENC_QUART_PXL);
+ if (enc_init_mpeg4_arg->in_time_increament_res) {
+ mfc_ctx->shared_mem.vop_timing = (1 << 31) |
+ (enc_init_mpeg4_arg->in_time_increament_res << 16) |
+ (enc_init_mpeg4_arg->in_time_vop_time_increament);
+ }
+ break;
+
+ case H263_ENC:
+ WRITEL(0x20, MFC_PROFILE);
+ WRITEL((enc_init_mpeg4_arg->in_RC_frm_enable << 9) |
+ (enc_init_mpeg4_arg->in_frame_qp & 0x3f),
+ MFC_RC_CONFIG);
+ break;
+
+ default:
+ mfc_err("Invalid MFC codec type\n");
+ }
+}
+
+int mfc_load_firmware(const unsigned char *data, size_t size)
+{
+ volatile unsigned char *fw_virbuf;
+
+ mfc_debug("mfc_load_firmware : MFC F/W Loading Start.................\n");
+
+ fw_virbuf = mfc_get_fw_buff_vaddr();
+ memset((void *)fw_virbuf, 0, MFC_FW_MAX_SIZE);
+
+ invalidate_kernel_vmap_range((void *)data, size);
+ memcpy((void *)fw_virbuf, data, size);
+ flush_kernel_vmap_range((void *)fw_virbuf, size);
+
+ mfc_debug("mfc_load_firmware : MFC F/W Loading Stop.................(fw_virbuf: 0x%08x)\n", fw_virbuf);
+
+ return 0;
+}
+
+enum mfc_error_code mfc_init_hw()
+{
+ int fw_buf_size;
+ unsigned int fw_version;
+ unsigned int mc_status;
+ unsigned long idcode;
+ int nIntrRet = 0;
+
+ mfc_debug("mfc_init_hw++\n");
+
+ /*
+ * 0-1. Check Type
+ */
+ idcode = readl(S5P_VA_CHIPID);
+ if ((idcode & 0x0F) == 0x02)
+ mCheckType = false;
+ else
+ mCheckType = true;
+
+ /*
+ * 1. MFC reset
+ */
+ do {
+ mc_status = READL(MFC_MC_STATUS);
+ } while (mc_status != 0);
+
+ if (mfc_cmd_reset() == false) {
+ mfc_err("MFCINST_ERR_INIT_FAIL\n");
+ return MFCINST_ERR_INIT_FAIL;
+ }
+
+ /*
+ * 2. Set DRAM base Addr
+ */
+ WRITEL(mfc_port0_base_paddr, MFC_MC_DRAMBASE_ADDR_A);
+ WRITEL(mfc_port1_base_paddr, MFC_MC_DRAMBASE_ADDR_B);
+ WRITEL(1, MFC_NUM_MASTER);
+
+ /*
+ * 3. Initialize registers of stream I/F for decoder
+ */
+ WRITEL(0xffff, MFC_SI_CH0_INST_ID);
+ WRITEL(0xffff, MFC_SI_CH1_INST_ID);
+
+ WRITEL(0, MFC_RISC2HOST_COMMAND);
+ WRITEL(0, MFC_HOST2RISC_COMMAND);
+
+ /*
+ * 4. Release reset signal to the RISC.
+ */
+ WRITEL(0x3ff, MFC_SW_RESET);
+ nIntrRet = mfc_wait_for_done(R2H_CMD_FW_STATUS_RET);
+ if (nIntrRet != R2H_CMD_FW_STATUS_RET) {
+ /*
+ * 4-1. MFC FW downloading
+ */
+
+ mfc_err("MFCINST_ERR_FW_LOAD_MFC_SW_RESET_FAIL............(Ret = %d)", nIntrRet);
+
+
+ mfc_err("MFCINST_ERR_FW_LOAD_FAIL\n");
+ return MFCINST_ERR_FW_LOAD_FAIL;
+ }
+
+ /*
+ * 5. Initialize firmware
+ */
+ fw_buf_size = MFC_FW_MAX_SIZE;
+ if (mfc_cmd_host2risc(H2R_CMD_SYS_INIT, fw_buf_size, 0, 0, 0) == false) {
+ mfc_err("R2H_CMD_SYS_INIT FAIL\n");
+ return MFCINST_ERR_FW_INIT_FAIL;
+ }
+
+ if (mfc_wait_for_done(R2H_CMD_SYS_INIT_RET) != R2H_CMD_SYS_INIT_RET) {
+ mfc_err("R2H_CMD_SYS_INIT_RET FAIL\n");
+ return MFCINST_ERR_FW_INIT_FAIL;
+ }
+
+ fw_version = READL(MFC_FW_VERSION);
+
+
+ mfc_debug("MFC FW version : %02xyy, %02xmm, %02xdd\n",
+ (fw_version >> 16) & 0xff, (fw_version >> 8) & 0xff, fw_version & 0xff);
+
+ mfc_debug("DRAM PORT0 BASE ADDRESS: 0x%08x\n", READL(MFC_MC_DRAMBASE_ADDR_A));
+ mfc_debug("DRAM PORT1 BASE ADDRESS: 0x%08x\n", READL(MFC_MC_DRAMBASE_ADDR_B));
+ mfc_debug("mfc_init_hw-\n");
+
+ return MFCINST_RET_OK;
+}
+
+static unsigned int mfc_get_codec_arg(enum ssbsip_mfc_codec_type codec_type)
+{
+ unsigned int codec_no = 99;
+
+ switch (codec_type) {
+ case H264_DEC:
+ codec_no = 0;
+ break;
+
+ case VC1_DEC:
+ codec_no = 1;
+ break;
+
+ case MPEG4_DEC:
+ case XVID_DEC:
+ codec_no = 2;
+ break;
+
+ case MPEG1_DEC:
+ case MPEG2_DEC:
+ codec_no = 3;
+ break;
+
+ case H263_DEC:
+ codec_no = 4;
+ break;
+
+ case VC1RCV_DEC:
+ codec_no = 5;
+ break;
+
+ case FIMV1_DEC:
+ codec_no = 6;
+ break;
+
+ case FIMV2_DEC:
+ codec_no = 7;
+ break;
+
+ case FIMV3_DEC:
+ codec_no = 8;
+ break;
+
+ case FIMV4_DEC:
+ codec_no = 9;
+ break;
+
+ case H264_ENC:
+ codec_no = 16;
+ break;
+
+ case MPEG4_ENC:
+ codec_no = 17;
+ break;
+
+ case H263_ENC:
+ codec_no = 18;
+ break;
+
+ default:
+ break;
+ }
+
+ return codec_no;
+}
+
+static int mfc_get_inst_no(struct mfc_inst_ctx *mfc_ctx, unsigned int context_addr, int context_size)
+{
+ unsigned int codec_no;
+ int inst_no;
+ unsigned int port0_base_paddr;
+ int mfc_wait_ret = 0;
+ port0_base_paddr = mfc_port0_base_paddr;
+
+ codec_no = (unsigned int)mfc_get_codec_arg(mfc_ctx->MfcCodecType);
+
+ if (mfc_cmd_host2risc(H2R_CMD_OPEN_INSTANCE,
+ codec_no,
+ (mfc_ctx->crcEnable << 31) | PIXEL_CACHE_ON_ONLY_P_PICTURE,
+ (context_addr - port0_base_paddr) >> 11,
+ context_size) == false) {
+ mfc_err("R2H_CMD_OPEN_INSTANCE FAIL\n");
+ return MFCINST_ERR_OPEN_FAIL;
+ }
+
+ mfc_wait_ret = mfc_wait_for_done(R2H_CMD_OPEN_INSTANCE_RET);
+ if (mfc_wait_ret != R2H_CMD_OPEN_INSTANCE_RET) {
+ mfc_err("R2H_CMD_OPEN_INSTANCE_RET FAIL..........(ret:%d)\n", mfc_wait_ret);
+ return MFCINST_ERR_OPEN_FAIL;
+ }
+
+ inst_no = READL(MFC_RISC2HOST_ARG1);
+ if (inst_no >= MFC_MAX_INSTANCE_NUM) {
+ mfc_err("mfc_get_inst_no() - INSTANCE NO : %d, CODEC_TYPE : %d --\n", inst_no, codec_no);
+ return -1;
+ } else {
+ mfc_debug("mfc_get_inst_no() - INSTANCE NO : %d, CODEC_TYPE : %d --\n", inst_no, codec_no);
+ return inst_no;
+ }
+}
+
+int mfc_return_inst_no(int inst_no, enum ssbsip_mfc_codec_type codec_type)
+{
+ unsigned int codec_no;
+ int mfc_wait_ret = 0;
+
+ codec_no = (unsigned int)mfc_get_codec_arg(codec_type);
+
+ if (mfc_cmd_host2risc(H2R_CMD_CLOSE_INSTANCE, inst_no, 0, 0, 0) == false) {
+ mfc_err("R2H_CMD_CLOSE_INSTANCE FAIL\n");
+ return MFCINST_ERR_CLOSE_FAIL;
+ }
+
+ mfc_wait_ret = mfc_wait_for_done(R2H_CMD_CLOSE_INSTANCE_RET);
+ if (mfc_wait_ret != R2H_CMD_CLOSE_INSTANCE_RET) {
+ mfc_err("R2H_CMD_CLOSE_INSTANCE_RET FAIL\n");
+ return MFCINST_ERR_CLOSE_FAIL;
+ }
+
+ mfc_debug("mfc_return_inst_no() - INSTANCE NO : %d, CODEC_TYPE : %d --\n", READL(MFC_RISC2HOST_ARG1), codec_no);
+ return MFCINST_RET_OK;
+}
+
+enum mfc_error_code mfc_init_encode(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args)
+{
+ struct mfc_enc_init_mpeg4_arg *enc_init_mpeg4_arg;
+ enum mfc_error_code ret_code;
+ unsigned int context_addr;
+ int context_size;
+ int frame_P_qp, frame_B_qp;
+ int nSize = 0;
+
+ enc_init_mpeg4_arg = (struct mfc_enc_init_mpeg4_arg *)args;
+
+ mfc_debug("++\n");
+ mfc_ctx->MfcCodecType = enc_init_mpeg4_arg->in_codec_type;
+ mfc_ctx->img_width = (unsigned int)enc_init_mpeg4_arg->in_width;
+ mfc_ctx->img_height = (unsigned int)enc_init_mpeg4_arg->in_height;
+ mfc_ctx->interlace_mode = enc_init_mpeg4_arg->in_interlace_mode;
+
+
+ /*
+ * Set Available Type
+ */
+ if (mCheckType == false) {
+ nSize = mfc_ctx->img_width * mfc_ctx->img_height;
+ mfc_ctx->shared_mem.p720_limit_enable = 49425;
+ if (nSize > BOUND_MEMORY_SIZE)
+ return MFCINST_ERR_FRM_BUF_SIZE;
+ } else {
+ mfc_ctx->shared_mem.p720_limit_enable = 49424;
+ }
+
+
+
+
+ /* OPEN CHANNEL
+ * - set open instance using codec_type
+ * - get the instance no
+ */
+ ret_code = mfc_alloc_context_buffer(mfc_ctx, enc_init_mpeg4_arg->in_mapped_addr, &context_addr, &context_size);
+ if (ret_code != MFCINST_RET_OK)
+ return ret_code;
+
+ mfc_ctx->InstNo = mfc_get_inst_no(mfc_ctx, context_addr, context_size);
+ if (mfc_ctx->InstNo < 0) {
+ mfc_err("MFCINST_INST_NUM_EXCEEDED\n");
+ return MFCINST_INST_NUM_EXCEEDED;
+ }
+
+ /* INIT CODEC
+ * - set init parameter
+ * - set init sequence done command
+ * - set codec buffer
+ * - set input risc buffer
+ */
+
+ mfc_set_encode_init_param(mfc_ctx, args);
+
+ ret_code = mfc_alloc_codec_buffer(mfc_ctx, args);
+ if (ret_code != MFCINST_RET_OK) {
+ /* In case of no instance, we should not release codec instance */
+ if (mfc_ctx->InstNo >= 0)
+ mfc_return_inst_no(mfc_ctx->InstNo, mfc_ctx->MfcCodecType);
+
+ return ret_code;
+ }
+
+ mfc_set_codec_buffer(mfc_ctx);
+
+ /* Set Ref YC0~3 & MV */
+ ret_code = mfc_alloc_stream_ref_buffer(mfc_ctx, args);
+ if (ret_code != MFCINST_RET_OK) {
+ /* In case of no instance, we should not release codec instance */
+ if (mfc_ctx->InstNo >= 0)
+ mfc_return_inst_no(mfc_ctx->InstNo, mfc_ctx->MfcCodecType);
+
+ return ret_code;
+ }
+
+ mfc_set_enc_ref_buffer(mfc_ctx, args);
+
+ if (enc_init_mpeg4_arg->in_frame_P_qp)
+ frame_P_qp = enc_init_mpeg4_arg->in_frame_P_qp;
+ else
+ frame_P_qp = enc_init_mpeg4_arg->in_frame_qp;
+
+ if (enc_init_mpeg4_arg->in_frame_B_qp)
+ frame_B_qp = enc_init_mpeg4_arg->in_frame_B_qp;
+ else
+ frame_B_qp = enc_init_mpeg4_arg->in_frame_qp;
+ mfc_ctx->shared_mem.P_B_frame_qp = (frame_B_qp << 6 | frame_P_qp);
+
+ if (enc_init_mpeg4_arg->in_RC_frm_enable)
+ mfc_ctx->shared_mem.vop_timing = ((1 << 31) | (enc_init_mpeg4_arg->in_RC_framerate << 16) | 1);
+
+
+ mfc_write_shared_mem(mfc_ctx->shared_mem_vaddr, &(mfc_ctx->shared_mem));
+
+ ret_code = mfc_encode_header(mfc_ctx, args);
+
+ mfc_read_shared_mem(mfc_ctx->shared_mem_vaddr, &(mfc_ctx->shared_mem));
+
+ mfc_backup_context(mfc_ctx);
+
+ mfc_debug_L0("--\n");
+
+ return ret_code;
+}
+
+static enum mfc_error_code mfc_encode_header(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args)
+{
+ struct mfc_enc_init_mpeg4_arg *init_arg;
+ unsigned int port0_base_paddr;
+ int nIntrRet = 0;
+ int nReturnErrCode = 0;
+
+ init_arg = (struct mfc_enc_init_mpeg4_arg *)args;
+
+ mfc_debug("++ enc_arg->in_strm_st : 0x%08x\n", init_arg->out_p_addr.strm_ref_y);
+
+ port0_base_paddr = mfc_port0_base_paddr;
+
+ /* Set share memory */
+ WRITEL((mfc_ctx->shared_mem_paddr - port0_base_paddr), MFC_SI_CH0_HOST_WR_ADR);
+
+ /* Set stream buffer addr */
+ WRITEL((init_arg->out_p_addr.strm_ref_y - port0_base_paddr) >> 11, MFC_SI_CH0_SB_U_ADDR);
+ WRITEL((init_arg->out_p_addr.strm_ref_y - port0_base_paddr) >> 11, MFC_SI_CH0_SB_L_ADDR);
+ WRITEL(STREAM_BUF_SIZE, MFC_SI_CH0_BUFFER_SIZE);
+
+ WRITEL(1, MFC_STR_BF_U_EMPTY);
+ WRITEL(1, MFC_STR_BF_L_EMPTY);
+
+ /* buf reset command if stream buffer is frame mode */
+ WRITEL(0x1 << 1, MFC_EDFU_SF_BUF_CTRL);
+
+ WRITEL((SEQ_HEADER << 16) | (mfc_ctx->InstNo), MFC_SI_CH0_INST_ID);
+ nIntrRet = mfc_wait_for_done(R2H_CMD_SEQ_DONE_RET);
+ nReturnErrCode = mfc_return_code();
+ if (nIntrRet == 0) {
+ mfc_err("MFCINST_ERR_ENC_EXE_TIME_OUT\n");
+ return MFCINST_ERR_INTR_TIME_OUT;
+ } else if ((nIntrRet != R2H_CMD_SEQ_DONE_RET) && (nReturnErrCode < MFC_WARN_START_NO)) {
+ mfc_err("MFCINST_ERR_ENC_SEQ_HEADER_FAIL ....Intr Code (%d)\n", nIntrRet);
+ return MFCINST_ERR_ENC_HEADER_DECODE_FAIL;
+ } else if (nIntrRet != R2H_CMD_SEQ_DONE_RET) {
+ mfc_warn("MFCINST_WARN_ENC_SEQ_HEADER.........(code: %d)\n", nIntrRet);
+ }
+
+
+ init_arg->out_header_size = READL(MFC_SI_ENC_STREAM_SIZE);
+
+ if (mfc_ctx->buf_type == MFC_BUFFER_CACHE) {
+ dma_unmap_single(NULL, init_arg->out_p_addr.strm_ref_y,
+ init_arg->out_header_size, DMA_FROM_DEVICE);
+ }
+ mfc_debug("encoded header size (%d)\n", init_arg->out_header_size);
+
+ return MFCINST_RET_OK;
+}
+
+static enum mfc_error_code mfc_encode_one_frame(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args)
+{
+ struct mfc_enc_exe_arg *enc_arg;
+ unsigned int port0_base_paddr, port1_base_paddr;
+ int interrupt_flag;
+ int nReturnErrCode;
+
+
+ enc_arg = (struct mfc_enc_exe_arg *)args;
+
+ mfc_debug("++ enc_arg->in_strm_st : 0x%08x enc_arg->in_strm_end :0x%08x \r\n",
+ enc_arg->in_strm_st, enc_arg->in_strm_end);
+ mfc_debug("enc_arg->in_Y_addr : 0x%08x enc_arg->in_CbCr_addr :0x%08x \r\n",
+ enc_arg->in_Y_addr, enc_arg->in_CbCr_addr);
+
+ mfc_restore_context(mfc_ctx);
+
+ port0_base_paddr = mfc_port0_base_paddr;
+ port1_base_paddr = mfc_port1_base_paddr;
+
+#ifdef ENABLE_DEBUG_ENC_EXE_INTR_ERR
+#if ENABLE_DEBUG_ENC_EXE_INTR_ERR
+ makefile_mfc_enc_err_info(enc_arg);
+#endif
+#endif
+
+ /* Set share memory */
+ WRITEL((mfc_ctx->shared_mem_paddr - port0_base_paddr), MFC_SI_CH0_HOST_WR_ADR);
+
+ /* Set stream buffer addr */
+ WRITEL((enc_arg->in_strm_st - port0_base_paddr) >> 11, MFC_SI_CH0_SB_U_ADDR);
+ WRITEL((enc_arg->in_strm_st - port0_base_paddr) >> 11, MFC_SI_CH0_SB_L_ADDR);
+ WRITEL(STREAM_BUF_SIZE, MFC_SI_CH0_BUFFER_SIZE);
+
+ /* Set current frame buffer addr */
+ WRITEL((enc_arg->in_Y_addr - port1_base_paddr) >> 11, MFC_SI_CH0_CURRENT_Y_ADDR);
+ WRITEL((enc_arg->in_CbCr_addr - port1_base_paddr) >> 11, MFC_SI_CH0_CURRENT_C_ADDR);
+
+ WRITEL(1, MFC_STR_BF_U_EMPTY);
+ WRITEL(1, MFC_STR_BF_L_EMPTY);
+
+ /* buf reset command if stream buffer is frame mode */
+ WRITEL(0x1 << 1, MFC_EDFU_SF_BUF_CTRL);
+
+ if (mfc_ctx->forceSetFrameType == NOT_CODED)
+ WRITEL((0x1 << 1), MFC_SI_CH0_ENC_PARA);
+ else if (mfc_ctx->forceSetFrameType == I_FRAME)
+ WRITEL(0x1, MFC_SI_CH0_ENC_PARA);
+
+ mfc_ctx->forceSetFrameType = DONT_CARE;
+
+ if (mfc_ctx->buf_type == MFC_BUFFER_CACHE) {
+ unsigned char *in_vir;
+ unsigned int aligned_width;
+ unsigned int aligned_height;
+
+ in_vir = phys_to_virt(enc_arg->in_Y_addr);
+ aligned_width = ALIGN_TO_128B(mfc_ctx->img_width);
+ aligned_height = ALIGN_TO_32B(mfc_ctx->img_height);
+ dma_map_single(NULL, in_vir, aligned_width*aligned_height,
+ DMA_TO_DEVICE);
+
+ in_vir = phys_to_virt(enc_arg->in_CbCr_addr);
+ aligned_height = ALIGN_TO_32B(mfc_ctx->img_height/2);
+ dma_map_single(NULL, in_vir, aligned_width*aligned_height,
+ DMA_TO_DEVICE);
+ }
+
+ /* Try frame encoding */
+ WRITEL((FRAME << 16) | (mfc_ctx->InstNo), MFC_SI_CH0_INST_ID);
+ interrupt_flag = mfc_wait_for_done(R2H_CMD_FRAME_DONE_RET);
+ nReturnErrCode = mfc_return_code();
+ if (interrupt_flag == 0) {
+ mfc_err("MFCINST_ERR_ENC_EXE_TIME_OUT\n");
+ return MFCINST_ERR_INTR_TIME_OUT;
+ } else if ((interrupt_flag != R2H_CMD_FRAME_DONE_RET) && (nReturnErrCode < MFC_WARN_START_NO)) {
+ mfc_err("MFCINST_ERR_ENC_DONE_FAIL\n");
+ return MFCINST_ERR_ENC_ENCODE_DONE_FAIL;
+ } else if (interrupt_flag != R2H_CMD_FRAME_DONE_RET) {
+ mfc_warn("MFCINST_WARN_ENC_EXE.........(code: %d)\n", interrupt_flag);
+ }
+
+ /* Get encoded infromation */
+ enc_arg->out_frame_type = READL(MFC_SI_ENC_SLICE_TYPE);
+ enc_arg->out_encoded_size = READL(MFC_SI_ENC_STREAM_SIZE);
+ enc_arg->out_encoded_Y_paddr = READL(MFC_SI_ENCODED_Y_ADDR);
+ enc_arg->out_encoded_C_paddr = READL(MFC_SI_ENCODED_C_ADDR);
+
+ if (mfc_ctx->buf_type == MFC_BUFFER_CACHE) {
+ dma_unmap_single(NULL, enc_arg->in_strm_st,
+ enc_arg->out_encoded_size, DMA_FROM_DEVICE);
+ }
+
+ mfc_debug("-- frame type(%d) encodedSize(%d)\r\n",
+ enc_arg->out_frame_type, enc_arg->out_encoded_size);
+
+ return MFCINST_RET_OK;
+}
+
+enum mfc_error_code mfc_exe_encode(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args)
+{
+ enum mfc_error_code ret_code;
+ struct mfc_enc_exe_arg *enc_arg;
+
+ enc_arg = (struct mfc_enc_exe_arg *)args;
+
+ mfc_ctx->shared_mem.set_frame_tag = enc_arg->in_frametag;
+ mfc_write_shared_mem(mfc_ctx->shared_mem_vaddr, &(mfc_ctx->shared_mem));
+
+ /* 5. Encode Frame */
+ ret_code = mfc_encode_one_frame(mfc_ctx, args);
+
+ if (ret_code != MFCINST_RET_OK) {
+ mfc_debug("mfc_exe_encode() : Encode Fail..(%d)\n", ret_code);
+ return ret_code;
+ }
+
+ mfc_read_shared_mem(mfc_ctx->shared_mem_vaddr, &(mfc_ctx->shared_mem));
+ enc_arg->out_frametag_top = mfc_ctx->shared_mem.get_frame_tag_top;
+ enc_arg->out_frametag_bottom = mfc_ctx->shared_mem.get_frame_tag_bot;
+
+ mfc_debug_L0("--\n");
+
+ return ret_code;
+}
+
+enum mfc_error_code mfc_init_decode(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args)
+{
+ enum mfc_error_code ret_code;
+ struct mfc_dec_init_arg *init_arg;
+ unsigned int context_addr;
+ int context_size;
+ int nSize;
+ int nIntrRet = 0;
+ int nReturnErrCode = 0;
+
+
+ mfc_debug("[%d] mfc_init_decode() start\n", current->pid);
+ init_arg = (struct mfc_dec_init_arg *)args;
+
+ /* Calculate stream header size */
+#if ENABLE_CHECK_SEQ_HEADER
+ init_arg->in_strm_size = calculate_seq_size(init_arg);
+#endif
+
+ /* Context setting from input param */
+ mfc_ctx->MfcCodecType = init_arg->in_codec_type;
+ mfc_ctx->IsPackedPB = init_arg->in_packed_PB;
+
+ /* OPEN CHANNEL
+ * - set open instance using codec_type
+ * - get the instance no
+ */
+ ret_code = mfc_alloc_context_buffer(mfc_ctx, init_arg->in_mapped_addr, &context_addr, &context_size);
+ if (ret_code != MFCINST_RET_OK)
+ return ret_code;
+
+ mfc_ctx->InstNo = mfc_get_inst_no(mfc_ctx, context_addr, context_size);
+ if (mfc_ctx->InstNo < 0) {
+ mfc_err("MFCINST_INST_NUM_EXCEEDED\n");
+ return MFCINST_INST_NUM_EXCEEDED;
+ }
+
+#ifdef ENABLE_DEBUG_DEC_EXE_INTR_ERR
+#if ENABLE_DEBUG_DEC_EXE_INTR_ERR
+ mcontext_addr = context_addr;
+ mcontext_size = context_size;
+#endif
+#endif
+
+ /*
+ * MFC_LF_CONTROL used both encoding and decoding
+ * H.264 encoding, MPEG4 decoding(post filter)
+ * should disable : need more DPB for loop filter
+ */
+
+ /* INIT CODEC
+ * set input stream buffer
+ * set sequence done command
+ * set NUM_EXTRA_DPB
+ */
+ if (mfc_ctx->MfcCodecType == FIMV1_DEC) {
+ WRITEL(mfc_ctx->widthFIMV1, MFC_SI_CH0_FIMV1_HRESOL);
+ WRITEL(mfc_ctx->heightFIMV1, MFC_SI_CH0_FIMV1_VRESOL);
+ }
+
+ ret_code = mfc_alloc_codec_buffer(mfc_ctx, args);
+ if (ret_code != MFCINST_RET_OK) {
+ /* In case of no instance, we should not release codec instance */
+ if (mfc_ctx->InstNo >= 0)
+ mfc_return_inst_no(mfc_ctx->InstNo, mfc_ctx->MfcCodecType);
+
+ return ret_code;
+ }
+
+ if (nReturnErrCode < 0)
+ return MFCINST_ERR_DEC_INVALID_STRM;
+
+ mfc_set_dec_stream_buffer(mfc_ctx, init_arg->in_strm_buf, init_arg->in_strm_size);
+
+ /* Set Display Delay and SliceEnable */
+ mfc_ctx->sliceEnable = 0;
+ WRITEL(((mfc_ctx->sliceEnable << 31) |
+ (mfc_ctx->displayDelay ? ((1 << 30) |
+ (mfc_ctx->displayDelay << 16)) : 0)),
+ MFC_SI_CH0_DPB_CONFIG_CTRL);
+
+ /* Set Available Type */
+ if (mCheckType == false) {
+ nSize = mfc_ctx->img_width * mfc_ctx->img_height;
+ mfc_ctx->shared_mem.p720_limit_enable = 49425;
+ if (nSize > BOUND_MEMORY_SIZE) {
+ /* In case of no instance, we should not release codec instance */
+ if (mfc_ctx->InstNo >= 0)
+ mfc_return_inst_no(mfc_ctx->InstNo, mfc_ctx->MfcCodecType);
+
+ return MFCINST_ERR_FRM_BUF_SIZE;
+ }
+ } else {
+ mfc_ctx->shared_mem.p720_limit_enable = 49424;
+ }
+
+ WRITEL_SHARED_MEM(mfc_ctx->shared_mem.p720_limit_enable,
+ mfc_ctx->shared_mem_vaddr + P720_LIMIT_ENABLE);
+ WRITEL((mfc_ctx->shared_mem_paddr - mfc_port0_base_paddr), MFC_SI_CH0_HOST_WR_ADR);
+
+ /* Codec Command : Decode a sequence header */
+ WRITEL((SEQ_HEADER << 16) | (mfc_ctx->InstNo), MFC_SI_CH0_INST_ID);
+
+ nIntrRet = mfc_wait_for_done(R2H_CMD_SEQ_DONE_RET);
+ nReturnErrCode = mfc_return_code();
+ if (nIntrRet == 0) {
+
+#ifdef ENABLE_DEBUG_DEC_EXE_INTR_ERR
+#if ENABLE_DEBUG_DEC_EXE_INTR_ERR
+ makefile_mfc_decinit_err_info(mfc_ctx, init_arg, 300);
+#endif
+#endif
+
+ mfc_err("MFCINST_ERR_DEC_INIT_TIME_OUT..........[#1]\n");
+ /* In case of no instance, we should not release codec instance */
+ if (mfc_ctx->InstNo >= 0)
+ mfc_return_inst_no(mfc_ctx->InstNo, mfc_ctx->MfcCodecType);
+
+ return MFCINST_ERR_INTR_TIME_OUT;
+ } else if ((nIntrRet != R2H_CMD_SEQ_DONE_RET) && (nReturnErrCode < MFC_WARN_START_NO)) {
+ mfc_err("MFCINST_ERR_DEC_SEQ_HEADER_FAIL ....Intr Code (%d)\n", nIntrRet);
+ /* In case of no instance, we should not release codec instance */
+ if (mfc_ctx->InstNo >= 0)
+ mfc_return_inst_no(mfc_ctx->InstNo, mfc_ctx->MfcCodecType);
+
+ return MFCINST_ERR_DEC_SEQ_DONE_FAIL;
+ } else if (nIntrRet != R2H_CMD_SEQ_DONE_RET) {
+ mfc_warn("MFCINST_WARN_DEC_INIT.........(code: %d)\n", nIntrRet);
+ }
+
+#ifdef ENABLE_DEBUG_DEC_EXE_INTR_OK
+ #if ENABLE_DEBUG_DEC_EXE_INTR_OK
+ makefile_mfc_decinit_err_info(mfc_ctx, init_arg, 1000);
+#endif
+#endif
+
+ /* out param & context setting from header decoding result */
+ mfc_ctx->img_width = READL(MFC_SI_HOR_RESOL);
+ mfc_ctx->img_height = READL(MFC_SI_VER_RESOL);
+
+ init_arg->out_img_width = READL(MFC_SI_HOR_RESOL);
+ init_arg->out_img_height = READL(MFC_SI_VER_RESOL);
+
+ /* in the case of VC1 interlace, height will be the multiple of 32
+ * otherwise, height and width is the mupltiple of 16
+ */
+ init_arg->out_buf_width = ALIGN_TO_128B(READL(MFC_SI_HOR_RESOL));
+ init_arg->out_buf_height = ALIGN_TO_32B(READL(MFC_SI_VER_RESOL));
+
+ if (mfc_ctx->MfcCodecType == FIMV1_DEC) {
+ mfc_ctx->img_width = mfc_ctx->widthFIMV1;
+ mfc_ctx->img_height = mfc_ctx->heightFIMV1;
+
+ init_arg->out_img_width = mfc_ctx->widthFIMV1;
+ init_arg->out_img_height = mfc_ctx->heightFIMV1;
+ init_arg->out_buf_width = ALIGN_TO_128B(mfc_ctx->widthFIMV1);
+ init_arg->out_buf_height = ALIGN_TO_32B(mfc_ctx->heightFIMV1);
+ }
+
+
+ /* Set totalDPB */
+ init_arg->out_dpb_cnt = READL(MFC_SI_MIN_NUM_DPB);
+ mfc_ctx->DPBCnt = READL(MFC_SI_MIN_NUM_DPB);
+
+ mfc_ctx->totalDPBCnt = init_arg->out_dpb_cnt;
+ mfc_ctx->totalDPBCnt = init_arg->out_dpb_cnt + mfc_ctx->extraDPB;
+ if (mfc_ctx->totalDPBCnt < mfc_ctx->displayDelay)
+ mfc_ctx->totalDPBCnt = mfc_ctx->displayDelay;
+
+ WRITEL(((mfc_ctx->sliceEnable << 31) |
+ (mfc_ctx->displayDelay ? ((1 << 30) |
+ (mfc_ctx->displayDelay << 16)) : 0) |
+ mfc_ctx->totalDPBCnt), MFC_SI_CH0_DPB_CONFIG_CTRL);
+
+ mfc_debug("buf_width : %d buf_height : %d out_dpb_cnt : %d mfc_ctx->DPBCnt : %d\n",
+ init_arg->out_img_width, init_arg->out_img_height, init_arg->out_dpb_cnt, mfc_ctx->DPBCnt);
+ mfc_debug("img_width : %d img_height : %d\n",
+ init_arg->out_img_width, init_arg->out_img_height);
+
+ mfc_set_codec_buffer(mfc_ctx);
+
+ ret_code = mfc_alloc_dec_frame_buffer(mfc_ctx, args);
+ if (ret_code != MFCINST_RET_OK) {
+ /* In case of no instance, we should not release codec instance */
+ if (mfc_ctx->InstNo >= 0)
+ mfc_return_inst_no(mfc_ctx->InstNo, mfc_ctx->MfcCodecType);
+
+ return ret_code;
+ }
+
+ mfc_set_dec_frame_buffer(mfc_ctx);
+
+#ifdef ENABLE_DEBUG_MFC_INIT
+#if ENABLE_DEBUG_MFC_INIT
+ printk_mfc_init_info(mfc_ctx, init_arg);
+#endif
+#endif
+
+ mfc_write_shared_mem(mfc_ctx->shared_mem_vaddr, &(mfc_ctx->shared_mem));
+ WRITEL((mfc_ctx->shared_mem_paddr - mfc_port0_base_paddr), MFC_SI_CH0_HOST_WR_ADR);
+ WRITEL((INIT_BUFFER << 16) | (mfc_ctx->InstNo), MFC_SI_CH0_INST_ID);
+
+ nIntrRet = mfc_wait_for_done(R2H_CMD_INIT_BUFFERS_RET);
+ nReturnErrCode = mfc_return_code();
+ if (nIntrRet == 0) {
+#ifdef ENABLE_DEBUG_DEC_EXE_INTR_ERR
+#if ENABLE_DEBUG_DEC_EXE_INTR_ERR
+ makefile_mfc_decinit_err_info(mfc_ctx, init_arg, 300);
+#endif
+#endif
+
+ mfc_err("MFCINST_ERR_DEC_INIT_TIME_OUT..............[#2]\n");
+ /* In case of no instance, we should not release codec instance */
+ if (mfc_ctx->InstNo >= 0)
+ mfc_return_inst_no(mfc_ctx->InstNo, mfc_ctx->MfcCodecType);
+
+ return MFCINST_ERR_INTR_TIME_OUT;
+ } else if ((nIntrRet != R2H_CMD_INIT_BUFFERS_RET) && (nReturnErrCode < MFC_WARN_START_NO)) {
+ mfc_err("MFCINST_ERR_DEC_INIT_BUFFER_FAIL ........(Intr Code : %d)\n", nIntrRet);
+ /* In case of no instance, we should not release codec instance */
+ if (mfc_ctx->InstNo >= 0)
+ mfc_return_inst_no(mfc_ctx->InstNo, mfc_ctx->MfcCodecType);
+
+ return MFCINST_ERR_DEC_INIT_BUFFER_FAIL;
+ } else if (nIntrRet != R2H_CMD_INIT_BUFFERS_RET) {
+ mfc_warn("MFCINST_WARN_DEC_INIT_BUFFER.........(Intr code: %d)\n", nIntrRet);
+ }
+
+ mfc_ctx->IsStartedIFrame = 0;
+
+ mfc_backup_context(mfc_ctx);
+
+ mfc_debug("[%d] mfc_init_decode() end\n", current->pid);
+
+ mfc_read_shared_mem(mfc_ctx->shared_mem_vaddr, &(mfc_ctx->shared_mem));
+ init_arg->out_crop_top_offset = (mfc_ctx->shared_mem.crop_info2 & 0xffff);
+ init_arg->out_crop_bottom_offset = (mfc_ctx->shared_mem.crop_info2 >> 16);
+ init_arg->out_crop_left_offset = (mfc_ctx->shared_mem.crop_info1 & 0xffff);
+ init_arg->out_crop_right_offset = (mfc_ctx->shared_mem.crop_info1 >> 16);
+ mfc_debug("out_crop_top_offset : %d out_crop_bottom_offset : %d\n", init_arg->out_crop_top_offset, init_arg->out_crop_bottom_offset);
+
+ return MFCINST_RET_OK;
+}
+
+static enum mfc_error_code mfc_decode_one_frame(struct mfc_inst_ctx *mfc_ctx, struct mfc_dec_exe_arg *dec_arg, unsigned int *consumed_strm_size)
+{
+ unsigned int frame_type;
+ static int count;
+ int interrupt_flag;
+ int nReturnErrCode = 0;
+ int nMaxFrameSize = 0;
+ int nOffSet = 0;
+ int nSum = 0;
+ unsigned char *stream_vir;
+
+ /* Check Invalid Stream Size */
+#if ENABLE_CHECK_STREAM_SIZE
+ nMaxFrameSize = mfc_ctx->img_height * mfc_ctx->img_width;
+ if ((dec_arg->in_strm_size < 1) || (dec_arg->in_strm_size > nMaxFrameSize) || (dec_arg->in_strm_size > STREAM_BUF_SIZE)) {
+ mfc_err("MFCINST_ERR_DEC_STRM_SIZE_INVALID : (stream size : %d), (resolution : %d)\n", dec_arg->in_strm_size, nMaxFrameSize);
+ return MFCINST_ERR_DEC_STRM_SIZE_INVALID;
+ }
+#endif
+
+ /* Check Invalid Null Stream */
+#if ENABLE_CHECK_NULL_STREAM
+ if ((dec_arg->in_strm_size > 10) && (!(mfc_ctx->IsPackedPB))) {
+ stream_vir = phys_to_virt(dec_arg->in_strm_buf);
+ nSum = CheckNullStream(stream_vir, dec_arg->in_strm_size);
+
+ if (nSum != 0) {
+#ifdef ENABLE_DEBUG_DEC_EXE_INTR_ERR
+ #if ENABLE_DEBUG_DEC_EXE_INTR_ERR
+ makefile_mfc_dec_err_info(mfc_ctx, dec_arg, 500);
+#endif
+#endif
+ return MFCINST_ERR_STRM_BUF_INVALID;
+ }
+ }
+#endif
+
+ /* Check H.263 Strat Code */
+#if ENABLE_CHECK_START_CODE
+ stream_vir = phys_to_virt(dec_arg->in_strm_buf);
+ nOffSet = CheckDecStartCode(stream_vir, dec_arg->in_strm_size, dec_arg->in_codec_type);
+
+ if (nOffSet < 0) {
+#ifdef ENABLE_DEBUG_DEC_EXE_INTR_ERR
+ #if ENABLE_DEBUG_DEC_EXE_INTR_ERR
+ makefile_mfc_dec_err_info(mfc_ctx, dec_arg, 400);
+#endif
+#endif
+ return MFCINST_ERR_STRM_BUF_INVALID;
+ }
+#endif
+
+ count++;
+ mfc_debug_L0("++ IntNo%d(%d)\r\n", mfc_ctx->InstNo, count);
+
+ WRITEL((mfc_ctx->shared_mem_paddr - mfc_port0_base_paddr), MFC_SI_CH0_HOST_WR_ADR);
+ mfc_set_dec_stream_buffer(mfc_ctx, dec_arg->in_strm_buf, dec_arg->in_strm_size);
+
+ if (mfc_ctx->endOfFrame) {
+ WRITEL((LAST_FRAME<<16) | (mfc_ctx->InstNo), MFC_SI_CH0_INST_ID);
+ mfc_ctx->endOfFrame = 0;
+ } else {
+ WRITEL((FRAME<<16) | (mfc_ctx->InstNo), MFC_SI_CH0_INST_ID);
+ }
+
+ interrupt_flag = mfc_wait_for_done(R2H_CMD_FRAME_DONE_RET);
+ nReturnErrCode = mfc_return_code();
+ if (interrupt_flag == 0) {
+#ifdef ENABLE_DEBUG_DEC_EXE_INTR_ERR
+ #if ENABLE_DEBUG_DEC_EXE_INTR_ERR
+ makefile_mfc_dec_err_info(mfc_ctx, dec_arg, 300);
+#endif
+#endif
+
+
+#if ENABLE_MFC_REGISTER_DEBUG
+ mfc_fw_debug(R2H_CMD_FRAME_DONE_RET);
+#endif
+
+ mfc_err("MFCINST_ERR_DEC_EXE_TIME_OUT\n");
+ return MFCINST_ERR_INTR_TIME_OUT;
+ } else if ((interrupt_flag != R2H_CMD_FRAME_DONE_RET) && (nReturnErrCode < MFC_WARN_START_NO)) {
+
+#ifdef ENABLE_DEBUG_DEC_EXE_PARSER_ERR
+ #if ENABLE_DEBUG_DEC_EXE_PARSER_ERR
+ makefile_mfc_dec_err_info(mfc_ctx, dec_arg, nReturnErrCode);
+#endif
+#endif
+ /* Clear start_byte_num in case of error */
+ mfc_ctx->shared_mem.start_byte_num = 0x0;
+ mfc_write_shared_mem(mfc_ctx->shared_mem_vaddr, &(mfc_ctx->shared_mem));
+
+#if ENABLE_MFC_REGISTER_DEBUG
+ mfc_fw_debug(R2H_CMD_FRAME_DONE_RET);
+#endif
+
+ mfc_err("MFCINST_ERR_DEC_DONE_FAIL.......(interrupt_flag: %d), (ERR Code: %d)\n", interrupt_flag, nReturnErrCode);
+ return MFCINST_ERR_DEC_DECODE_DONE_FAIL;
+
+ } else if (interrupt_flag != R2H_CMD_FRAME_DONE_RET) {
+ mfc_warn("MFCINST_WARN_DEC_EXE.........(interrupt_flag: %d), (WARN Code: %d)\n", interrupt_flag, nReturnErrCode);
+ }
+
+ mfc_read_shared_mem(mfc_ctx->shared_mem_vaddr, &(mfc_ctx->shared_mem));
+
+ dec_arg->out_res_change = (READL(MFC_SI_DISPLAY_STATUS) >> 4) & 0x3;
+
+ if (((READL(MFC_SI_DISPLAY_STATUS) & 0x3) != DECODING_DISPLAY) &&
+ ((READL(MFC_SI_DISPLAY_STATUS) & 0x3) != DISPLAY_ONLY)) {
+ dec_arg->out_display_Y_addr = 0;
+ dec_arg->out_display_C_addr = 0;
+ mfc_debug("DECODING_ONLY frame decoded\n");
+ } else {
+ /* address shift */
+ dec_arg->out_display_Y_addr = READL(MFC_SI_DISPLAY_Y_ADR) << 11;
+ dec_arg->out_display_C_addr = READL(MFC_SI_DISPLAY_C_ADR) << 11;
+ mfc_debug("DISPLAY Able frame decoded\n");
+ }
+
+ if ((READL(MFC_SI_DISPLAY_STATUS) & 0x3) == DECODING_EMPTY)
+ dec_arg->out_display_status = 0;
+ else if ((READL(MFC_SI_DISPLAY_STATUS) & 0x3) == DECODING_DISPLAY)
+ dec_arg->out_display_status = 1;
+ else if ((READL(MFC_SI_DISPLAY_STATUS) & 0x3) == DISPLAY_ONLY)
+ dec_arg->out_display_status = 2;
+ else
+ dec_arg->out_display_status = 3;
+
+ frame_type = READL(MFC_SI_FRAME_TYPE);
+ mfc_ctx->FrameType = (enum mfc_frame_type)(frame_type & 0x3);
+
+ mfc_debug_L0("(Y_ADDR : 0x%08x C_ADDR : 0x%08x)\r\n",
+ dec_arg->out_display_Y_addr, dec_arg->out_display_C_addr);
+
+ *consumed_strm_size = READL(MFC_SI_DEC_FRM_SIZE);
+
+ return MFCINST_RET_OK;
+}
+
+enum mfc_error_code mfc_exe_decode(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args)
+{
+ enum mfc_error_code ret_code;
+ struct mfc_dec_exe_arg *dec_arg;
+ int consumed_strm_size;
+
+ /* 6. Decode Frame */
+ mfc_debug_L0("[%d] mfc_exe_decode() start\n", current->pid);
+
+ dec_arg = (struct mfc_dec_exe_arg *)args;
+
+ mfc_ctx->shared_mem.set_frame_tag = dec_arg->in_frametag;
+
+ mfc_write_shared_mem(mfc_ctx->shared_mem_vaddr, &(mfc_ctx->shared_mem));
+
+ ret_code = mfc_decode_one_frame(mfc_ctx, dec_arg, &consumed_strm_size);
+
+ if (ret_code != MFCINST_RET_OK) {
+ mfc_debug("mfc_exe_decode() : Decode Fail..(%d)\n", ret_code);
+ return ret_code;
+ }
+
+ mfc_read_shared_mem(mfc_ctx->shared_mem_vaddr, &(mfc_ctx->shared_mem));
+ dec_arg->out_frametag_top = mfc_ctx->shared_mem.get_frame_tag_top;
+ dec_arg->out_frametag_bottom = mfc_ctx->shared_mem.get_frame_tag_bot;
+ dec_arg->out_timestamp_top = mfc_ctx->shared_mem.pic_time_top;
+ dec_arg->out_timestamp_bottom = mfc_ctx->shared_mem.pic_time_bot;
+ dec_arg->out_consume_bytes = consumed_strm_size;
+ dec_arg->out_crop_top_offset = (mfc_ctx->shared_mem.crop_info2 & 0xffff);
+ dec_arg->out_crop_bottom_offset = (mfc_ctx->shared_mem.crop_info2 >> 16);
+ dec_arg->out_crop_left_offset = (mfc_ctx->shared_mem.crop_info1 & 0xffff);
+ dec_arg->out_crop_right_offset = (mfc_ctx->shared_mem.crop_info1 >> 16);
+
+
+ /* PackedPB Stream Processing */
+ if ((mfc_ctx->IsPackedPB) &&
+ (mfc_ctx->FrameType == MFC_RET_FRAME_P_FRAME) &&
+ (dec_arg->in_strm_size - consumed_strm_size > 4)) {
+
+ unsigned char *stream_vir;
+ int offset = 0;
+
+ stream_vir = phys_to_virt(dec_arg->in_strm_buf);
+
+ invalidate_kernel_vmap_range((void *)stream_vir, dec_arg->in_strm_size);
+
+ offset = CheckMPEG4StartCode(stream_vir+consumed_strm_size , dec_arg->in_strm_size - consumed_strm_size);
+ if (offset > 4)
+ consumed_strm_size += offset;
+ dec_arg->in_strm_size -= consumed_strm_size;
+
+ mfc_ctx->shared_mem.set_frame_tag = dec_arg->in_frametag;
+ mfc_ctx->shared_mem.start_byte_num = consumed_strm_size;
+ mfc_write_shared_mem(mfc_ctx->shared_mem_vaddr, &(mfc_ctx->shared_mem));
+ ret_code = mfc_decode_one_frame(mfc_ctx, dec_arg, &consumed_strm_size);
+ if (ret_code != MFCINST_RET_OK)
+ return ret_code;
+
+ mfc_read_shared_mem(mfc_ctx->shared_mem_vaddr, &(mfc_ctx->shared_mem));
+ dec_arg->out_frametag_top = mfc_ctx->shared_mem.get_frame_tag_top;
+ dec_arg->out_frametag_bottom = mfc_ctx->shared_mem.get_frame_tag_bot;
+ dec_arg->out_timestamp_top = mfc_ctx->shared_mem.pic_time_top;
+ dec_arg->out_timestamp_bottom = mfc_ctx->shared_mem.pic_time_bot;
+ dec_arg->out_consume_bytes += consumed_strm_size;
+ dec_arg->out_crop_top_offset = (mfc_ctx->shared_mem.crop_info2 & 0xffff);
+ dec_arg->out_crop_bottom_offset = (mfc_ctx->shared_mem.crop_info2 >> 16);
+ dec_arg->out_crop_left_offset = (mfc_ctx->shared_mem.crop_info1 & 0xffff);
+ dec_arg->out_crop_right_offset = (mfc_ctx->shared_mem.crop_info1 >> 16);
+
+ mfc_ctx->shared_mem.start_byte_num = 0;
+
+ }
+
+ if (mfc_ctx->buf_type == MFC_BUFFER_CACHE) {
+ if (((READL(MFC_SI_DISPLAY_STATUS) & 0x3) == DECODING_DISPLAY) ||
+ ((READL(MFC_SI_DISPLAY_STATUS) & 0x3) == DISPLAY_ONLY)) {
+ unsigned int aligned_width;
+ unsigned int aligned_height;
+
+ aligned_width = ALIGN_TO_128B(mfc_ctx->img_width);
+ aligned_height = ALIGN_TO_32B(mfc_ctx->img_height);
+ dma_unmap_single(NULL, dec_arg->out_display_Y_addr,
+ aligned_width*aligned_height, DMA_FROM_DEVICE);
+
+ aligned_height = ALIGN_TO_32B(mfc_ctx->img_height/2);
+ dma_unmap_single(NULL, dec_arg->out_display_C_addr,
+ aligned_width*aligned_height, DMA_FROM_DEVICE);
+ }
+ }
+
+ mfc_debug_L0("--\n");
+
+ return ret_code;
+}
+
+enum mfc_error_code mfc_deinit_hw(struct mfc_inst_ctx *mfc_ctx)
+{
+ mfc_restore_context(mfc_ctx);
+
+ return MFCINST_RET_OK;
+}
+
+enum mfc_error_code mfc_get_config(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args)
+{
+ struct mfc_get_config_arg *get_cnf_arg;
+ get_cnf_arg = (struct mfc_get_config_arg *)args;
+
+ switch (get_cnf_arg->in_config_param) {
+ case MFC_DEC_GETCONF_CRC_DATA:
+ if (mfc_ctx->MfcState != MFCINST_STATE_DEC_EXE) {
+ mfc_err("MFC_DEC_GETCONF_CRC_DATA : state is invalid\n");
+ return MFC_DEC_GETCONF_CRC_DATA;
+ }
+ get_cnf_arg->out_config_value[0] = READL(MFC_CRC_LUMA0);
+ get_cnf_arg->out_config_value[1] = READL(MFC_CRC_CHROMA0);
+ break;
+
+ default:
+ mfc_err("invalid config param\n");
+ return MFCINST_ERR_GET_CONF; /* peter, it should be mod. */
+ }
+
+ return MFCINST_RET_OK;
+}
+
+enum mfc_error_code mfc_set_config(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args)
+{
+ struct mfc_set_config_arg *set_cnf_arg;
+ set_cnf_arg = (struct mfc_set_config_arg *)args;
+
+ switch (set_cnf_arg->in_config_param) {
+ case MFC_DEC_SETCONF_POST_ENABLE:
+ if (mfc_ctx->MfcState >= MFCINST_STATE_DEC_INITIALIZE) {
+ mfc_err("MFC_DEC_SETCONF_POST_ENABLE : state is invalid\n");
+ return MFCINST_ERR_STATE_INVALID;
+ }
+
+ if ((set_cnf_arg->in_config_value[0] == 0) || (set_cnf_arg->in_config_value[0] == 1)) {
+ mfc_ctx->postEnable = set_cnf_arg->in_config_value[0];
+ } else {
+ mfc_warn("POST_ENABLE should be 0 or 1\n");
+ mfc_ctx->postEnable = 0;
+ }
+ break;
+
+ case MFC_DEC_SETCONF_EXTRA_BUFFER_NUM:
+ if (mfc_ctx->MfcState >= MFCINST_STATE_DEC_INITIALIZE) {
+ mfc_err("MFC_DEC_SETCONF_EXTRA_BUFFER_NUM : state is invalid\n");
+ return MFCINST_ERR_STATE_INVALID;
+ }
+ if ((set_cnf_arg->in_config_value[0] >= 0) || (set_cnf_arg->in_config_value[0] <= MFC_MAX_EXTRA_DPB)) {
+ mfc_ctx->extraDPB = set_cnf_arg->in_config_value[0];
+ } else {
+ mfc_warn("EXTRA_BUFFER_NUM should be between 0 and 5...It will be set 5 by default\n");
+ mfc_ctx->extraDPB = MFC_MAX_EXTRA_DPB;
+ }
+ break;
+
+ case MFC_DEC_SETCONF_DISPLAY_DELAY:
+ if (mfc_ctx->MfcState >= MFCINST_STATE_DEC_INITIALIZE) {
+ mfc_err("MFC_DEC_SETCONF_DISPLAY_DELAY : state is invalid\n");
+ return MFCINST_ERR_STATE_INVALID;
+ }
+
+ if ((set_cnf_arg->in_config_value[0] >= 0) || (set_cnf_arg->in_config_value[0] < 16)) {
+ mfc_ctx->displayDelay = set_cnf_arg->in_config_value[0];
+ mfc_debug("DISPLAY_DELAY Number = %d\n", mfc_ctx->displayDelay);
+ } else {
+ mfc_warn("DISPLAY_DELAY should be between 0 and 16\n");
+ mfc_ctx->displayDelay = 0;
+ }
+ break;
+
+ case MFC_DEC_SETCONF_IS_LAST_FRAME:
+ if (mfc_ctx->MfcState != MFCINST_STATE_DEC_EXE) {
+ mfc_err("MFC_DEC_SETCONF_IS_LAST_FRAME : state is invalid\n");
+ return MFCINST_ERR_STATE_INVALID;
+ }
+
+ if ((set_cnf_arg->in_config_value[0] == 0) || (set_cnf_arg->in_config_value[0] == 1)) {
+ mfc_ctx->endOfFrame = set_cnf_arg->in_config_value[0];
+ } else {
+ mfc_warn("IS_LAST_FRAME should be 0 or 1\n");
+ mfc_ctx->endOfFrame = 0;
+ }
+ break;
+
+ case MFC_DEC_SETCONF_SLICE_ENABLE:
+ if (mfc_ctx->MfcState >= MFCINST_STATE_DEC_INITIALIZE) {
+ mfc_err("MFC_DEC_SETCONF_SLICE_ENABLE : state is invalid\n");
+ return MFCINST_ERR_STATE_INVALID;
+ }
+
+ if ((set_cnf_arg->in_config_value[0] == 0) || (set_cnf_arg->in_config_value[0] == 1)) {
+ mfc_ctx->sliceEnable = set_cnf_arg->in_config_value[0];
+ } else {
+ mfc_warn("SLICE_ENABLE should be 0 or 1\n");
+ mfc_ctx->sliceEnable = 0;
+ }
+ break;
+
+ case MFC_DEC_SETCONF_CRC_ENABLE:
+ if (mfc_ctx->MfcState >= MFCINST_STATE_DEC_INITIALIZE) {
+ mfc_err("MFC_DEC_SETCONF_CRC_ENABLE : state is invalid\n");
+ return MFCINST_ERR_STATE_INVALID;
+ }
+
+ if ((set_cnf_arg->in_config_value[0] == 0) || (set_cnf_arg->in_config_value[0] == 1)) {
+ mfc_ctx->crcEnable = set_cnf_arg->in_config_value[0];
+ } else {
+ mfc_warn("CRC_ENABLE should be 0 or 1\n");
+ mfc_ctx->crcEnable = 0;
+ }
+ break;
+
+ case MFC_DEC_SETCONF_FIMV1_WIDTH_HEIGHT:
+ if (mfc_ctx->MfcState >= MFCINST_STATE_DEC_INITIALIZE) {
+ mfc_err("MFC_DEC_SETCONF_FIMV1_WIDTH_HEIGHT : state is invalid\n");
+ return MFCINST_ERR_STATE_INVALID;
+ }
+
+ mfc_ctx->widthFIMV1 = set_cnf_arg->in_config_value[0];
+ mfc_ctx->heightFIMV1 = set_cnf_arg->in_config_value[1];
+ break;
+
+ case MFC_ENC_SETCONF_FRAME_TYPE:
+ if (mfc_ctx->MfcState != MFCINST_STATE_ENC_EXE) {
+ mfc_err("MFC_ENC_SETCONF_FRAME_TYPE : state is invalid\n");
+ return MFCINST_ERR_STATE_INVALID;
+ }
+
+ if ((set_cnf_arg->in_config_value[0] >= DONT_CARE) && (set_cnf_arg->in_config_value[0] <= NOT_CODED)) {
+ mfc_ctx->forceSetFrameType = set_cnf_arg->in_config_value[0];
+ } else {
+ mfc_warn("FRAME_TYPE should be between 0 and 2\n");
+ mfc_ctx->forceSetFrameType = DONT_CARE;
+ }
+ break;
+
+ case MFC_ENC_SETCONF_ALLOW_FRAME_SKIP:
+ if (mfc_ctx->MfcState >= MFCINST_STATE_ENC_INITIALIZE) {
+ mfc_err("MFC_ENC_SETCONF_ALLOW_FRAME_SKIP : state is invalid\n");
+ return MFCINST_ERR_STATE_INVALID;
+ }
+
+ if (set_cnf_arg->in_config_value[0])
+ mfc_ctx->shared_mem.ext_enc_control = (mfc_ctx->shared_mem.ext_enc_control | (0x1 << 1));
+ break;
+
+ /* XXX: need to implement */
+ case MFC_ENC_SETCONF_CHANGE_FRAME_RATE:
+ if (mfc_ctx->MfcState != MFCINST_STATE_ENC_EXE) {
+ mfc_err("MFC_ENC_SETCONF_FRAME_TYPE : state is invalid\n");
+ return MFCINST_ERR_STATE_INVALID;
+ }
+ break;
+
+ /* XXX: need to implement */
+ case MFC_ENC_SETCONF_CHANGE_BIT_RATE:
+ if (mfc_ctx->MfcState != MFCINST_STATE_ENC_EXE) {
+ mfc_err("MFC_ENC_SETCONF_FRAME_TYPE : state is invalid\n");
+ return MFCINST_ERR_STATE_INVALID;
+ }
+ break;
+
+ default:
+ mfc_err("invalid config param\n");
+ return MFCINST_ERR_SET_CONF;
+ }
+
+ return MFCINST_RET_OK;
+}
+
+enum mfc_error_code mfc_set_sleep()
+{
+ if (mfc_cmd_host2risc(H2R_CMD_SLEEP, 0, 0, 0, 0) == false) {
+ mfc_err("R2H_CMD_SLEEP FAIL\n");
+ return MFCINST_SLEEP_FAIL;
+ }
+
+ if (mfc_wait_for_done(R2H_CMD_SLEEP_RET) != R2H_CMD_SLEEP_RET) {
+ mfc_err("R2H_CMD_SLEEP_RET FAIL\n");
+ return MFCINST_SLEEP_FAIL;
+ }
+
+ return MFCINST_RET_OK;
+}
+
+enum mfc_error_code mfc_set_wakeup()
+{
+ int ret;
+
+ if (mfc_cmd_host2risc(H2R_CMD_WAKEUP, 0, 0, 0, 0) == false) {
+ mfc_err("R2H_CMD_WAKEUP FAIL\n");
+ return MFCINST_WAKEUP_FAIL;
+ }
+
+ WRITEL(0x3ff, MFC_SW_RESET);
+
+ ret = mfc_wait_for_done(R2H_CMD_WAKEUP_RET);
+ if ((ret != R2H_CMD_WAKEUP_RET) && (ret != R2H_CMD_FW_STATUS_RET)) {
+ mfc_err("R2H_CMD_WAKEUP_RET FAIL\n");
+ return MFCINST_WAKEUP_FAIL;
+ }
+
+ return MFCINST_RET_OK;
+}
+
+static enum
+mfc_error_code mfc_alloc_context_buffer(struct mfc_inst_ctx *mfc_ctx, unsigned int mapped_addr,
+ unsigned int *context_addr, int *size)
+{
+ union mfc_args local_param;
+ enum mfc_error_code ret_code;
+ unsigned char *context_vir;
+
+ switch (mfc_ctx->MfcCodecType) {
+ case H264_ENC:
+ *size = H264ENC_CONTEXT_SIZE;
+ break;
+
+ case MPEG4_ENC:
+ *size = MPEG4ENC_CONTEXT_SIZE;
+ break;
+
+ case H263_ENC:
+ *size = H263ENC_CONTEXT_SIZE;
+ break;
+
+ case H264_DEC:
+ *size = H264DEC_CONTEXT_SIZE;
+ break;
+
+ case H263_DEC:
+ *size = H263DEC_CONTEXT_SIZE;
+ break;
+
+ case MPEG2_DEC:
+ *size = MPEG2DEC_CONTEXT_SIZE;
+ break;
+
+ case MPEG4_DEC:
+ case FIMV1_DEC:
+ case FIMV2_DEC:
+ case FIMV3_DEC:
+ case FIMV4_DEC:
+ *size = MPEG4DEC_CONTEXT_SIZE;
+ break;
+
+ case VC1_DEC:
+ case VC1RCV_DEC:
+ *size = VC1DEC_CONTEXT_SIZE;
+ break;
+
+ default:
+ return MFCINST_ERR_WRONG_CODEC_MODE;
+ }
+
+ memset(&local_param, 0, sizeof(local_param));
+ local_param.mem_alloc.buff_size = *size;
+ local_param.mem_alloc.mapped_addr = mapped_addr;
+
+ ret_code = mfc_allocate_buffer(mfc_ctx, &(local_param), 0);
+ if (ret_code < 0)
+ return ret_code;
+
+ /* Set mfc context to "0". */
+ context_vir = phys_to_virt(local_param.mem_alloc.out_paddr);
+ memset(context_vir, 0x0, local_param.mem_alloc.buff_size);
+
+ dmac_flush_range(context_vir, context_vir + local_param.mem_alloc.buff_size);
+
+ *context_addr = local_param.mem_alloc.out_paddr;
+
+ return ret_code;
+}
+
+void mfc_init_mem_inst_no(void)
+{
+ memset(&mfc_mem_inst_no, 0x00, sizeof(mfc_mem_inst_no));
+}
+
+int mfc_get_mem_inst_no(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < MFC_MAX_INSTANCE_NUM; i++) {
+ if (mfc_mem_inst_no[i] == 0) {
+ mfc_mem_inst_no[i] = 1;
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+void mfc_return_mem_inst_no(int inst_no)
+{
+ if ((inst_no >= 0) && (inst_no < MFC_MAX_INSTANCE_NUM))
+ mfc_mem_inst_no[inst_no] = 0;
+}
+
+bool mfc_is_running(void)
+{
+ unsigned int i;
+ bool ret = false;
+
+ for (i = 0; i < MFC_MAX_INSTANCE_NUM; i++) {
+ mfc_debug("mfc_mem_inst_no[%d] = %d\n", i, mfc_mem_inst_no[i]);
+ if (mfc_mem_inst_no[i] == 1)
+ ret = true;
+ }
+
+ return ret;
+}
+
+int mfc_set_state(struct mfc_inst_ctx *ctx, enum mfc_inst_state state)
+{
+ if (ctx->MfcState > state)
+ return -1;
+
+ ctx->MfcState = state;
+ return 0;
+}
+
+bool is_dec_codec(enum ssbsip_mfc_codec_type codec_type)
+{
+ switch (codec_type) {
+ case H264_DEC:
+ case VC1_DEC:
+ case MPEG4_DEC:
+ case XVID_DEC:
+ case MPEG1_DEC:
+ case MPEG2_DEC:
+ case H263_DEC:
+ case VC1RCV_DEC:
+ case FIMV1_DEC:
+ case FIMV2_DEC:
+ case FIMV3_DEC:
+ case FIMV4_DEC:
+ return true;
+
+ case H264_ENC:
+ case MPEG4_ENC:
+ case H263_ENC:
+ return false;
+
+ default:
+ return false;
+ }
+}
+
+
+
+
+
+/*
+ * Debugging Functions Definition
+ * tile_to_linear_4x2(..)
+ * calculate_seq_size(..)
+ * printk_mfc_init_info(..)
+ */
+
+
+#if DEBUG_MAKE_RAW
+static void write_file(char *filename, unsigned char *data, unsigned int nSize)
+{
+ struct file *file;
+ loff_t pos = 0;
+ int fd;
+ mm_segment_t old_fs;
+
+ invalidate_kernel_vmap_range(data, nSize);
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ fd = sys_open(filename, O_WRONLY|O_CREAT, 0644);
+ if (fd >= 0) {
+ sys_write(fd, data, nSize);
+ file = fget(fd);
+ if (file) {
+ vfs_write(file, data, nSize, &pos);
+ fput(file);
+ }
+ sys_close(fd);
+ } else {
+ mfc_err("........Open fail : %d\n", fd);
+ }
+ set_fs(old_fs);
+
+ dmac_flush_range(data, data + nSize);
+
+}
+
+static int tile_4x2_read(int x_size, int y_size, int x_pos, int y_pos)
+{
+ int pixel_x_m1, pixel_y_m1;
+ int roundup_x, roundup_y;
+ int linear_addr0, linear_addr1, bank_addr ;
+ int x_addr;
+ int trans_addr;
+
+ pixel_x_m1 = x_size - 1;
+ pixel_y_m1 = y_size - 1;
+
+ roundup_x = ((pixel_x_m1 >> 7) + 1);
+ roundup_y = ((pixel_x_m1 >> 6) + 1);
+
+ x_addr = (x_pos >> 2);
+
+ if ((y_size <= y_pos+32) && (y_pos < y_size) &&
+ (((pixel_y_m1 >> 5) & 0x1) == 0) && (((y_pos >> 5) & 0x1) == 0)) {
+ linear_addr0 = (((y_pos & 0x1f) << 4) | (x_addr & 0xf));
+ linear_addr1 = (((y_pos >> 6) & 0xff) * roundup_x + ((x_addr >> 6) & 0x3f));
+
+ if (((x_addr >> 5) & 0x1) == ((y_pos >> 5) & 0x1))
+ bank_addr = ((x_addr >> 4) & 0x1);
+ else
+ bank_addr = 0x2 | ((x_addr >> 4) & 0x1);
+ } else {
+ linear_addr0 = (((y_pos & 0x1f) << 4) | (x_addr & 0xf));
+ linear_addr1 = (((y_pos >> 6) & 0xff) * roundup_x + ((x_addr >> 5) & 0x7f));
+
+ if (((x_addr >> 5) & 0x1) == ((y_pos >> 5) & 0x1))
+ bank_addr = ((x_addr >> 4) & 0x1);
+ else
+ bank_addr = 0x2 | ((x_addr >> 4) & 0x1);
+ }
+
+ linear_addr0 = linear_addr0 << 2;
+ trans_addr = (linear_addr1 << 13) | (bank_addr << 11) | linear_addr0;
+
+ return trans_addr;
+}
+
+
+static void copy16(unsigned char *p_linear_addr, unsigned char *p_tiled_addr, int mm, int nn)
+{
+ p_linear_addr[mm] = p_tiled_addr[nn];
+ p_linear_addr[mm + 1] = p_tiled_addr[nn + 1];
+ p_linear_addr[mm + 2] = p_tiled_addr[nn + 2];
+ p_linear_addr[mm + 3] = p_tiled_addr[nn + 3];
+
+ p_linear_addr[mm + 4] = p_tiled_addr[nn + 4];
+ p_linear_addr[mm + 5] = p_tiled_addr[nn + 5];
+ p_linear_addr[mm + 6] = p_tiled_addr[nn + 6];
+ p_linear_addr[mm + 7] = p_tiled_addr[nn + 7];
+
+ p_linear_addr[mm + 8] = p_tiled_addr[nn + 8];
+ p_linear_addr[mm + 9] = p_tiled_addr[nn + 9];
+ p_linear_addr[mm + 10] = p_tiled_addr[nn + 10];
+ p_linear_addr[mm + 11] = p_tiled_addr[nn + 11];
+
+ p_linear_addr[mm + 12] = p_tiled_addr[nn + 12];
+ p_linear_addr[mm + 13] = p_tiled_addr[nn + 13];
+ p_linear_addr[mm + 14] = p_tiled_addr[nn + 14];
+ p_linear_addr[mm + 15] = p_tiled_addr[nn + 15];
+}
+
+
+static void
+tile_to_linear_4x2(unsigned char *p_linear_addr, unsigned char *p_tiled_addr,
+ unsigned int x_size, unsigned int y_size)
+{
+ int trans_addr;
+ unsigned int i, j, k, nn, mm, index;
+
+ /*. TILE 4x2 test */
+ for (i = 0; i < y_size; i = i + 16) {
+ for (j = 0; j < x_size; j = j + 16) {
+ trans_addr = tile_4x2_read(x_size, y_size, j, i);
+ index = i*x_size + j;
+
+ k = 0; nn = trans_addr + (k << 6); mm = index;
+ copy16(p_linear_addr, p_tiled_addr, mm, nn);
+
+ k = 1; nn = trans_addr + (k << 6); mm += x_size;
+ copy16(p_linear_addr, p_tiled_addr, mm, nn);
+
+ k = 2; nn = trans_addr + (k << 6); mm += x_size;
+ copy16(p_linear_addr, p_tiled_addr, mm, nn);
+
+ k = 3; nn = trans_addr + (k << 6); mm += x_size;
+ copy16(p_linear_addr, p_tiled_addr, mm, nn);
+
+ k = 4; nn = trans_addr + (k << 6); mm += x_size;
+ copy16(p_linear_addr, p_tiled_addr, mm, nn);
+
+ k = 5; nn = trans_addr + (k << 6); mm += x_size;
+ copy16(p_linear_addr, p_tiled_addr, mm, nn);
+
+ k = 6; nn = trans_addr + (k << 6); mm += x_size;
+ copy16(p_linear_addr, p_tiled_addr, mm, nn);
+
+ k = 7; nn = trans_addr + (k << 6); mm += x_size;
+ copy16(p_linear_addr, p_tiled_addr, mm, nn);
+
+ k = 8; nn = trans_addr + (k << 6); mm += x_size;
+ copy16(p_linear_addr, p_tiled_addr, mm, nn);
+
+ k = 9; nn = trans_addr + (k << 6); mm += x_size;
+ copy16(p_linear_addr, p_tiled_addr, mm, nn);
+
+ k = 10; nn = trans_addr + (k << 6); mm += x_size;
+ copy16(p_linear_addr, p_tiled_addr, mm, nn);
+
+ k = 11; nn = trans_addr + (k << 6); mm += x_size;
+ copy16(p_linear_addr, p_tiled_addr, mm, nn);
+
+ k = 12; nn = trans_addr + (k << 6); mm += x_size;
+ copy16(p_linear_addr, p_tiled_addr, mm, nn);
+
+ k = 13; nn = trans_addr + (k << 6); mm += x_size;
+ copy16(p_linear_addr, p_tiled_addr, mm, nn);
+
+ k = 14; nn = trans_addr + (k << 6); mm += x_size;
+ copy16(p_linear_addr, p_tiled_addr, mm, nn);
+
+ k = 15; nn = trans_addr + (k << 6); mm += x_size;
+ copy16(p_linear_addr, p_tiled_addr, mm, nn);
+
+ }
+ }
+}
+#endif
+
+
+
+#if ENABLE_CHECK_SEQ_HEADER
+static int calculate_seq_size(mfc_args *args)
+{
+ int nn = 0;
+ int nCnt = 0;
+ unsigned char nSum = 0;
+ unsigned char *stream_vir;
+
+ stream_vir = phys_to_virt(args->dec_init.in_strm_buf);
+ if (args->dec_init.in_strm_size > 31) {
+ for (nn = 0; nn < args->dec_init.in_strm_size - 4; nn++) {
+ nSum = (unsigned char)(((*(stream_vir + nn)) << 1) + ((*(stream_vir + nn + 1)) << 1)
+ + ((*(stream_vir + nn + 2)) << 1) + (*(stream_vir+nn+3)));
+ if (nSum == 0x1) {
+ nCnt++;
+ }
+
+ if (nCnt == 3) {
+ mfc_info("After Stream Size : %d , nCnt = %d\n", args->dec_init.in_strm_size, nCnt);
+ return nn;
+ }
+ }
+ }
+
+ return args->dec_init.in_strm_size;
+}
+#endif
+
+
+#if ENABLE_DEBUG_MFC_INIT
+void printk_mfc_init_info(mfc_inst_ctx *mfc_ctx, mfc_args *args)
+{
+ int nn = 0;
+ unsigned char *stream_vir;
+
+ mfc_info("MFC Decoder/Encoder Init Information\n");
+ mfc_info("[InstNo : %d], [DPBCnt : %d], [totalDPBCnt : %d], [extraDPB : %d], [displayDelay : %d],\n",
+ mfc_ctx->InstNo, mfc_ctx->DPBCnt, mfc_ctx->totalDPBCnt, mfc_ctx->extraDPB, mfc_ctx->displayDelay);
+ mfc_info("[img_width : %d], [img_height : %d], [MfcCodecType : %d], [MfcState : %d]\n",
+ mfc_ctx->img_width, mfc_ctx->img_height, mfc_ctx->MfcCodecType, mfc_ctx->MfcState);
+
+ mfc_info("Input Stream Buffer Information\n");
+ mfc_info("[in_strm_size : %d], [in_strm_buf : %d]\n",
+ args->dec_init.in_strm_size, args->dec_init.in_strm_buf);
+
+ stream_vir = phys_to_virt(args->dec_init.in_strm_buf);
+ if (args->dec_init.in_strm_size > 0) {
+ mfc_info("Input Stream Buffer\n");
+ for (nn = 0; nn < 40; nn++)
+ printk("%02x ", *(stream_vir+nn));
+ printk("\n");
+ }
+
+}
+#endif
+
+
+#ifdef ENABLE_DEBUG_DEC_EXE_INTR_ERR
+#if ENABLE_DEBUG_DEC_EXE_INTR_ERR
+void printk_mfc_dec_exe_info(struct mfc_inst_ctx *mfc_ctx, struct mfc_dec_exe_arg *dec_arg)
+{
+ int nn = 0;
+ unsigned char *stream_vir;
+
+ mfc_info("MFC Decoder/Encoder Exe Information\n");
+ mfc_info("[InstNo : %d], [DPBCnt : %d], [totalDPBCnt : %d], [extraDPB : %d], [displayDelay : %d],\n",
+ mfc_ctx->InstNo, mfc_ctx->DPBCnt, mfc_ctx->totalDPBCnt, mfc_ctx->extraDPB, mfc_ctx->displayDelay);
+ mfc_info("[img_width : %d], [img_height : %d], [MfcCodecType : %d], [MfcState : %d], [FrameType: %d]\n",
+ mfc_ctx->img_width, mfc_ctx->img_height, mfc_ctx->MfcCodecType, mfc_ctx->MfcState, mfc_ctx->FrameType);
+
+ mfc_info("Input Stream Buffer Information\n");
+ mfc_info("[in_strm_size : %d], [in_strm_buf : %d]\n",
+ dec_arg->in_strm_size, dec_arg->in_strm_buf);
+
+ stream_vir = phys_to_virt(dec_arg->in_strm_buf);
+ if (dec_arg->in_strm_size > 0) {
+ mfc_info("Input Stream Buffer\n");
+ for (nn = 0; nn < 50; nn++)
+ printk("%02x ", *(stream_vir+nn));
+ printk("\n");
+ }
+}
+
+void
+makefile_mfc_dec_err_info(struct mfc_inst_ctx *mfc_ctx,
+ struct mfc_dec_exe_arg *dec_arg, int nReturnErrCode)
+{
+ char fileName0[50];
+ char fileName1[50];
+ unsigned char *ctx_virbuf;
+ unsigned char *mfc_dec_in_base_vaddr;
+
+ mframe_cnt++;
+
+ if ((nReturnErrCode < 145) || (nReturnErrCode == 300)) {
+ mIsDangerError = 1;
+ printk_mfc_dec_exe_info(mfc_ctx, dec_arg);
+ }
+
+ memset(fileName0, 0, 50);
+ memset(fileName1, 0, 50);
+
+ sprintf(fileName0, "/data/dec_in/mfc_decexe_instream_%d_%d.raw", nReturnErrCode, mframe_cnt);
+ sprintf(fileName1, "/data/dec_in/mfc_decexe_mfcctx_%d_%d.bin", nReturnErrCode, mframe_cnt);
+
+ mfc_dec_in_base_vaddr = phys_to_virt(dec_arg->in_strm_buf);
+ ctx_virbuf = phys_to_virt(mcontext_addr);
+
+ write_file(fileName0, mfc_dec_in_base_vaddr, dec_arg->in_strm_size);
+ write_file(fileName1, ctx_virbuf, mcontext_size);
+
+}
+
+
+void makefile_mfc_decinit_err_info(struct mfc_inst_ctx *mfc_ctx, struct mfc_dec_init_arg *decinit_arg, int nReturnErrCode)
+{
+ char fileName0[50];
+ char fileName1[50];
+ unsigned char *ctx_virbuf;
+ unsigned char *mfc_dec_in_base_vaddr;
+
+ mframe_cnt++;
+
+ pr_info("makefile_mfc_decinit_err_info : in_strm_size(%d)\n", decinit_arg->in_strm_size);
+
+ memset(fileName0, 0, 50);
+ memset(fileName1, 0, 50);
+
+ sprintf(fileName0, "/data/dec_in/mfc_decinit_instream_%d_%d.raw", nReturnErrCode, mframe_cnt);
+ sprintf(fileName1, "/data/dec_in/mfc_decinit_mfcctx_%d_%d.bin", nReturnErrCode, mframe_cnt);
+
+ mfc_dec_in_base_vaddr = phys_to_virt(decinit_arg->in_strm_buf);
+ ctx_virbuf = phys_to_virt(mcontext_addr);
+
+ write_file(fileName0, mfc_dec_in_base_vaddr, decinit_arg->in_strm_size);
+ write_file(fileName1, ctx_virbuf, mcontext_size);
+}
+#endif
+#endif
+
+#ifdef ENABLE_DEBUG_ENC_EXE_INTR_ERR
+#if ENABLE_DEBUG_ENC_EXE_INTR_ERR
+void makefile_mfc_enc_err_info(struct mfc_enc_exe_arg *enc_arg)
+{
+ int nFrameSize = 0;
+ char fileName[50];
+ unsigned char *mfc_enc_in_base_Y_vaddr;
+ unsigned char *mfc_enc_in_base_CbCr_vaddr;
+
+ mframe_cnt++;
+
+ memset(fileName, 0, 50);
+ sprintf(fileName, "/data/enc_in/mfc_in_%04d.yuv", mframe_cnt);
+ nFrameSize = mImgHight * mImgWidth * 3/2;
+
+ mfc_enc_in_base_Y_vaddr = phys_to_virt(enc_arg->in_Y_addr);
+ mfc_enc_in_base_CbCr_vaddr = phys_to_virt(enc_arg->in_CbCr_addr);
+
+ mfc_debug("enc_arg->in_Y_addr : 0x%08x enc_arg->in_Y_addr_vir :0x%08x\r\n",
+ enc_arg->in_Y_addr, mfc_enc_in_base_Y_vaddr);
+
+ tile_to_linear_4x2(pResLinearbuf, mfc_enc_in_base_Y_vaddr,
+ mImgWidth, mImgHight);
+ tile_to_linear_4x2(pResLinearbuf + (mImgHight * mImgWidth),
+ mfc_enc_in_base_CbCr_vaddr, mImgWidth, mImgHight/2);
+ write_file(fileName, pResLinearbuf, nFrameSize);
+
+}
+#endif
+#endif
+
+
+static int CheckMPEG4StartCode(unsigned char *src_mem, unsigned int remainSize)
+{
+ unsigned int index = 0;
+
+ for (index = 0; index < remainSize-3; index++) {
+ if ((src_mem[index] == 0x00)
+ && (src_mem[index+1] == 0x00)
+ && (src_mem[index+2] == 0x01))
+ return index;
+ }
+
+ return -1;
+}
+
+#if ENABLE_CHECK_START_CODE
+static int CheckDecStartCode(unsigned char *src_mem, unsigned int nstreamSize, enum ssbsip_mfc_codec_type nCodecType)
+{
+ unsigned int index = 0;
+ /* Check Start Code within "isearchSize" bytes. */
+ unsigned int isearchSize = 20;
+ unsigned int nShift = 0;
+ unsigned char nFlag = 0xFF;
+
+ if (nCodecType == H263_DEC) {
+ nFlag = 0x08;
+ nShift = 4;
+ } else if (nCodecType == MPEG4_DEC) {
+ nFlag = 0x01;
+ nShift = 0;
+ } else if (nCodecType == H264_DEC) {
+ nFlag = 0x01;
+ nShift = 0;
+ } else {
+ nFlag = 0xFF;
+ }
+
+ if (nFlag != 0xFF) {
+ if (nstreamSize > 3) {
+ if (nstreamSize > isearchSize) {
+ for (index = 0; index < isearchSize-3; index++) {
+ if ((src_mem[index] == 0x00)
+ && (src_mem[index+1] == 0x00)
+ && ((src_mem[index+2] >> nShift) == nFlag))
+ return index;
+ }
+ } else {
+ for (index = 0; index < nstreamSize - 3; index++) {
+ if ((src_mem[index] == 0x00)
+ && (src_mem[index+1] == 0x00)
+ && ((src_mem[index+2] >> nShift) == nFlag))
+ return index;
+ }
+ }
+ } else {
+ return -1;
+ }
+ } else {
+ return 0;
+ }
+
+ return -1;
+}
+#endif
+
+#if ENABLE_CHECK_NULL_STREAM
+static int CheckNullStream(unsigned char *src_mem, unsigned int streamSize)
+{
+ unsigned int temp = 0;
+ unsigned int nn;
+
+ if (streamSize < 30) {
+ for (nn = 0; nn < streamSize; nn++)
+ temp += src_mem[nn];
+ } else {
+ for (nn = 0; nn < 10; nn++)
+ temp += src_mem[nn];
+
+ if (temp == 0) {
+ for (nn = streamSize-10; nn < streamSize; nn++)
+ temp += src_mem[nn];
+ }
+ }
+
+ if (temp == 0) {
+ mfc_debug("Null Stream......Error\n");
+ return -1;
+ }
+
+ return 0;
+
+}
+#endif
+
+#if ENABLE_MFC_REGISTER_DEBUG
+void mfc_fw_debug(mfc_wait_done_type command)
+{
+ mfc_err("=== MFC FW Debug (Cmd: %d)"
+ "(Ver: 0x%08x) ===\n", command, READL(0x58));
+ mfc_err("=== (0x64: 0x%08x) (0x68: 0x%08x)"
+ "(0xE4: 0x%08x) (0xE8: 0x%08x)\n",
+ READL(0x64), READL(0x68), READL(0xe4), READL(0xe8));
+ mfc_err("=== (0xF0: 0x%08x) (0xF4: 0x%08x)"
+ "(0xF8: 0x%08x) (0xFC: 0x%08x)\n",
+ READL(0xf0), READL(0xf4), READL(0xf8), READL(0xfc));
+}
+#endif
diff --git a/drivers/media/video/samsung/mfc50/mfc_opr.h b/drivers/media/video/samsung/mfc50/mfc_opr.h
new file mode 100644
index 0000000..18cfe53
--- /dev/null
+++ b/drivers/media/video/samsung/mfc50/mfc_opr.h
@@ -0,0 +1,204 @@
+/*
+ * drivers/media/video/samsung/mfc50/mfc_opr.h
+ *
+ * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
+ *
+ * Jaeryul Oh, Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * Change Logs
+ * 2009.09.14 - Beautify source code (Key Young, Park)
+ * 2009.09.21 - Implement clock & power gating.
+ * including suspend & resume fuction. (Key Young, Park)
+ * 2009.11.04 - remove mfc_common.[ch]
+ * seperate buffer alloc & set (Key Young, Park)
+ *
+ * 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 _MFC_OPR_H_
+#define _MFC_OPR_H_
+
+#include <plat/regs-mfc.h>
+#include "mfc_errorno.h"
+#include "mfc_interface.h"
+#include "mfc_shared_mem.h"
+
+#define MFC_WARN_START_NO 145
+#define MFC_ERR_START_NO 1
+
+
+#define INT_MFC_FW_DONE (0x1 << 5)
+#define INT_MFC_DMA_DONE (0x1 << 7)
+#define INT_MFC_FRAME_DONE (0x1 << 8)
+/* Interrupt on/off (0x500) */
+#define INT_ENABLE_BIT (0 << 0)
+#define INT_DISABLE_BIT (1 << 0)
+/* Interrupt mode (0x504) */
+#define INT_LEVEL_BIT (0 << 0)
+#define INT_PULSE_BIT (1 << 0)
+
+/* Command Types */
+#define MFC_CHANNEL_SET 0
+#define MFC_CHANNEL_READ 1
+#define MFC_CHANNEL_END 2
+#define MFC_INIT_CODEC 3
+#define MFC_FRAME_RUN 4
+#define MFC_SLEEP 6
+#define MFC_WAKEUP 7
+
+/* DPB Count */
+#define NUM_MPEG4_DPB 2
+#define NUM_POST_DPB 3
+#define NUM_VC1_DPB 4
+
+#define ALIGN_TO_16B(x) ((((x) + (1 << 4) - 1) >> 4) << 4)
+#define ALIGN_TO_32B(x) ((((x) + (1 << 5) - 1) >> 5) << 5)
+#define ALIGN_TO_64B(x) ((((x) + (1 << 6) - 1) >> 6) << 6)
+#define ALIGN_TO_128B(x) ((((x) + (1 << 7) - 1) >> 7) << 7)
+#define ALIGN_TO_2KB(x) ((((x) + (1 << 11) - 1) >> 11) << 11)
+#define ALIGN_TO_4KB(x) ((((x) + (1 << 12) - 1) >> 12) << 12)
+#define ALIGN_TO_8KB(x) ((((x) + (1 << 13) - 1) >> 13) << 13)
+#define ALIGN_TO_64KB(x) ((((x) + (1 << 16) - 1) >> 16) << 16)
+#define ALIGN_TO_128KB(x) ((((x) + (1 << 17) - 1) >> 17) << 17)
+
+#define PIXEL_CACHE_ON_ONLY_P_PICTURE 0
+#define PIXEL_CACHE_ON_ONLY_B_PICTURE 1
+#define PIXEL_CACHE_ON_BOTH_P_B_PICTURE 2
+#define PIXEL_CACHE_DISABLE 3
+
+#define BOUND_MEMORY_SIZE 921600
+
+enum mfc_inst_state {
+ MFCINST_STATE_NULL = 0,
+
+ /* Instance is created */
+ MFCINST_STATE_OPENED = 10,
+
+ /* channel_set and init_codec is completed */
+ MFCINST_STATE_DEC_INITIALIZE = 20,
+
+ MFCINST_STATE_DEC_EXE = 30,
+ MFCINST_STATE_DEC_EXE_DONE,
+
+ /* Instance is initialized for encoding */
+ MFCINST_STATE_ENC_INITIALIZE = 40,
+ MFCINST_STATE_ENC_EXE,
+ MFCINST_STATE_ENC_EXE_DONE
+};
+
+enum mfc_mem_type {
+ MEM_STRUCT_LINEAR = 0,
+ MEM_STRUCT_TILE_ENC = 3 /* 64x32 */
+};
+
+enum mfc_dec_type {
+ SEQ_HEADER = 1,
+ FRAME = 2,
+ LAST_FRAME = 3,
+ INIT_BUFFER = 4,
+ FRAME_RUN_REALLOC = 5,
+};
+
+enum mfc_facade_cmd {
+ H2R_CMD_EMPTY = 0,
+ H2R_CMD_OPEN_INSTANCE = 1,
+ H2R_CMD_CLOSE_INSTANCE = 2,
+ H2R_CMD_SYS_INIT = 3,
+ H2R_CMD_SLEEP = 5,
+ H2R_CMD_WAKEUP = 6,
+};
+
+enum mfc_wait_done_type {
+ R2H_CMD_EMPTY = 0,
+ R2H_CMD_OPEN_INSTANCE_RET = 1,
+ R2H_CMD_CLOSE_INSTANCE_RET = 2,
+ R2H_CMD_ERROR_RET = 3,
+ R2H_CMD_SEQ_DONE_RET = 4,
+ R2H_CMD_FRAME_DONE_RET = 5,
+ R2H_CMD_SLICE_DONE_RET = 6,
+ R2H_CMD_ENC_COMPLETE_RET = 6,
+ R2H_CMD_SYS_INIT_RET = 8,
+ R2H_CMD_FW_STATUS_RET = 9,
+ R2H_CMD_SLEEP_RET = 10,
+ R2H_CMD_WAKEUP_RET = 11,
+ R2H_CMD_INIT_BUFFERS_RET = 15,
+ R2H_CMD_EDFU_INT_RET = 16,
+ R2H_CMD_DECODE_ERR_RET = 32
+};
+
+enum mfc_display_status {
+ DECODING_ONLY = 0,
+ DECODING_DISPLAY = 1,
+ DISPLAY_ONLY = 2,
+ DECODING_EMPTY = 3
+};
+
+/* In case of decoder */
+enum mfc_frame_type {
+ MFC_RET_FRAME_NOT_SET = 0,
+ MFC_RET_FRAME_I_FRAME = 1,
+ MFC_RET_FRAME_P_FRAME = 2,
+ MFC_RET_FRAME_B_FRAME = 3
+};
+
+struct mfc_inst_ctx {
+ int InstNo;
+ unsigned int DPBCnt;
+ unsigned int totalDPBCnt;
+ unsigned int extraDPB;
+ unsigned int displayDelay;
+ unsigned int postEnable;
+ unsigned int endOfFrame;
+ unsigned int forceSetFrameType;
+ unsigned int img_width;
+ unsigned int img_height;
+ unsigned int dwAccess; /* for Power Management. */
+ unsigned int IsPackedPB;
+ unsigned int interlace_mode;
+ unsigned int sliceEnable;
+ unsigned int crcEnable;
+ unsigned int widthFIMV1;
+ unsigned int heightFIMV1;
+ int mem_inst_no;
+ enum mfc_frame_type FrameType;
+ enum ssbsip_mfc_codec_type MfcCodecType;
+ enum mfc_inst_state MfcState;
+ unsigned int port0_mmap_size;
+ unsigned int codec_buff_paddr;
+ unsigned int pred_buff_paddr;
+ struct mfc_frame_buf_arg dec_dpb_buff_paddr;
+ unsigned int shared_mem_paddr;
+ unsigned int shared_mem_vaddr;
+ unsigned int IsStartedIFrame;
+ struct mfc_shared_mem shared_mem;
+ enum mfc_buffer_type buf_type;
+ unsigned int desc_buff_paddr;
+};
+
+int mfc_load_firmware(const unsigned char *data, size_t size);
+bool mfc_cmd_reset(void);
+
+enum mfc_error_code mfc_init_hw(void);
+enum mfc_error_code mfc_init_encode(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args);
+enum mfc_error_code mfc_exe_encode(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args);
+enum mfc_error_code mfc_init_decode(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args);
+enum mfc_error_code mfc_exe_decode(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args);
+enum mfc_error_code mfc_get_config(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args);
+enum mfc_error_code mfc_set_config(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args);
+enum mfc_error_code mfc_deinit_hw(struct mfc_inst_ctx *mfc_ctx);
+enum mfc_error_code mfc_set_sleep(void);
+enum mfc_error_code mfc_set_wakeup(void);
+
+int mfc_return_inst_no(int inst_no, enum ssbsip_mfc_codec_type codec_type);
+int mfc_set_state(struct mfc_inst_ctx *ctx, enum mfc_inst_state state);
+void mfc_init_mem_inst_no(void);
+int mfc_get_mem_inst_no(void);
+void mfc_return_mem_inst_no(int inst_no);
+bool mfc_is_running(void);
+bool is_dec_codec(enum ssbsip_mfc_codec_type codec_type);
+
+
+#endif /* _MFC_OPR_H_ */
diff --git a/drivers/media/video/samsung/mfc50/mfc_shared_mem.c b/drivers/media/video/samsung/mfc50/mfc_shared_mem.c
new file mode 100644
index 0000000..813c2db
--- /dev/null
+++ b/drivers/media/video/samsung/mfc50/mfc_shared_mem.c
@@ -0,0 +1,123 @@
+/*
+ * drivers/media/video/samsung/mfc50/mfc_shared_mem.c
+ *
+ * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
+ *
+ * Key-Young Park, Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * Change Logs
+ * 2009.10.08 - Apply 9/30 firmware(Key Young, Park)
+ * 2009.11.06 - clean & invalidate shared mem area (Key Young, Park)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/io.h>
+#include <asm/cacheflush.h>
+
+#include "mfc_shared_mem.h"
+#include "mfc_logmsg.h"
+
+#define DEBUG_ENABLE 0
+
+static inline void mfc_write_shared_mem_item(unsigned int host_wr_addr, unsigned int addr, unsigned int value)
+{
+ MEM_WRITE(host_wr_addr + addr, value);
+}
+
+static inline unsigned int mfc_read_shared_mem_item(unsigned int host_wr_addr, unsigned int addr)
+{
+ return MEM_READ(host_wr_addr + addr);
+}
+
+void mfc_write_shared_mem(unsigned int host_wr_addr, struct mfc_shared_mem *shared_mem)
+{
+ mfc_write_shared_mem_item(host_wr_addr, RC_CONTROL_ENABLE, 1);/* RC_CONTROL_CONFIG : enable (1), disable(0) */
+
+ mfc_write_shared_mem_item(host_wr_addr, SET_FRAME_TAG, shared_mem->set_frame_tag);
+ mfc_write_shared_mem_item(host_wr_addr, START_BYTE_NUM, shared_mem->start_byte_num);
+ mfc_write_shared_mem_item(host_wr_addr, EXT_ENC_CONTROL, shared_mem->ext_enc_control);
+ mfc_write_shared_mem_item(host_wr_addr, ENC_PARAM_CHANGE, shared_mem->enc_param_change);
+ mfc_write_shared_mem_item(host_wr_addr, VOP_TIMING, shared_mem->vop_timing);
+ mfc_write_shared_mem_item(host_wr_addr, HEC_PERIOD, shared_mem->hec_period);
+ mfc_write_shared_mem_item(host_wr_addr, P_B_FRAME_QP, shared_mem->P_B_frame_qp);
+ mfc_write_shared_mem_item(host_wr_addr, METADATA_ENABLE, shared_mem->metadata_enable);
+ mfc_write_shared_mem_item(host_wr_addr, EXT_METADATA_START_ADDR, shared_mem->ext_metadata_start_addr);
+ mfc_write_shared_mem_item(host_wr_addr, PUT_EXTRADATA, shared_mem->put_extradata);
+ mfc_write_shared_mem_item(host_wr_addr, DBG_INFO_INPUT0, shared_mem->dbg_info_input0);
+ mfc_write_shared_mem_item(host_wr_addr, DBG_INFO_INPUT1, shared_mem->dbg_info_input1);
+ mfc_write_shared_mem_item(host_wr_addr, ALLOCATED_LUMA_DPB_SIZE, shared_mem->allocated_luma_dpb_size);
+ mfc_write_shared_mem_item(host_wr_addr, ALLOCATED_CHROMA_DPB_SIZE, shared_mem->allocated_chroma_dpb_size);
+ mfc_write_shared_mem_item(host_wr_addr, ALLOCATED_MV_SIZE, shared_mem->allocated_mv_size);
+ mfc_write_shared_mem_item(host_wr_addr, P720_LIMIT_ENABLE, shared_mem->p720_limit_enable);
+
+ dmac_flush_range((void *)host_wr_addr, (void *)host_wr_addr + SHARED_MEM_MAX);
+
+#if DEBUG_ENABLE
+ mfc_print_shared_mem(host_wr_addr);
+#endif
+}
+
+void mfc_read_shared_mem(unsigned int host_wr_addr, struct mfc_shared_mem *shared_mem)
+{
+ invalidate_kernel_vmap_range((void *)host_wr_addr, SHARED_MEM_MAX);
+
+ shared_mem->extended_decode_status = mfc_read_shared_mem_item(host_wr_addr, EXTENEDED_DECODE_STATUS);
+ shared_mem->get_frame_tag_top = mfc_read_shared_mem_item(host_wr_addr, GET_FRAME_TAG_TOP);
+ shared_mem->get_frame_tag_bot = mfc_read_shared_mem_item(host_wr_addr, GET_FRAME_TAG_BOT);
+ shared_mem->pic_time_top = mfc_read_shared_mem_item(host_wr_addr, PIC_TIME_TOP);
+ shared_mem->pic_time_bot = mfc_read_shared_mem_item(host_wr_addr, PIC_TIME_BOT);
+ shared_mem->start_byte_num = mfc_read_shared_mem_item(host_wr_addr, START_BYTE_NUM);
+ shared_mem->dec_frm_size = mfc_read_shared_mem_item(host_wr_addr, DEC_FRM_SIZE);
+ shared_mem->crop_info1 = mfc_read_shared_mem_item(host_wr_addr, CROP_INFO1);
+ shared_mem->crop_info2 = mfc_read_shared_mem_item(host_wr_addr, CROP_INFO2);
+ shared_mem->metadata_status = mfc_read_shared_mem_item(host_wr_addr, METADATA_STATUS);
+ shared_mem->metadata_display_index = mfc_read_shared_mem_item(host_wr_addr, METADATA_DISPLAY_INDEX);
+ shared_mem->dbg_info_output0 = mfc_read_shared_mem_item(host_wr_addr, DBG_INFO_OUTPUT0);
+ shared_mem->dbg_info_output1 = mfc_read_shared_mem_item(host_wr_addr, DBG_INFO_OUTPUT1);
+
+#if DEBUG_ENABLE
+ mfc_print_shared_mem(host_wr_addr);
+#endif
+}
+
+void mfc_print_shared_mem(unsigned int host_wr_addr)
+{
+ mfc_info("set_frame_tag = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, SET_FRAME_TAG));
+ mfc_info("start_byte_num = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, START_BYTE_NUM));
+ mfc_info("ext_enc_control = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, EXT_ENC_CONTROL));
+ mfc_info("enc_param_change = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, ENC_PARAM_CHANGE));
+ mfc_info("vop_timing = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, VOP_TIMING));
+ mfc_info("hec_period = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, HEC_PERIOD));
+ mfc_info("p_b_frame_qp = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, P_B_FRAME_QP));
+ mfc_info("metadata_enable = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, METADATA_ENABLE));
+ mfc_info("ext_metadata_start_addr= 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, EXT_METADATA_START_ADDR));
+ mfc_info("put_extradata = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, PUT_EXTRADATA));
+ mfc_info("dbg_info_input0 = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, DBG_INFO_INPUT0));
+ mfc_info("dbg_info_input1 = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, DBG_INFO_INPUT1));
+ mfc_info("luma_dpb_size = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, ALLOCATED_LUMA_DPB_SIZE));
+ mfc_info("chroma_dpb_size = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, ALLOCATED_CHROMA_DPB_SIZE));
+ mfc_info("mv_size = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, ALLOCATED_MV_SIZE));
+ mfc_info("extended_decode_status = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, EXTENEDED_DECODE_STATUS));
+ mfc_info("get_frame_tag_top = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, GET_FRAME_TAG_TOP));
+ mfc_info("get_frame_tag_bot = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, GET_FRAME_TAG_BOT));
+ mfc_info("pic_time_top = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, PIC_TIME_TOP));
+ mfc_info("pic_time_bot = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, PIC_TIME_BOT));
+ mfc_info("start_byte_num = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, START_BYTE_NUM));
+ mfc_info("dec_frm_size = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, DEC_FRM_SIZE));
+ mfc_info("crop_info1 = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, CROP_INFO1));
+ mfc_info("crop_info2 = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, CROP_INFO2));
+ mfc_info("metadata_status = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, METADATA_STATUS));
+ mfc_info("metadata_display_index = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, METADATA_DISPLAY_INDEX));
+ mfc_info("dbg_info_output0 = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, DBG_INFO_OUTPUT0));
+ mfc_info("dbg_info_output1 = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, DBG_INFO_OUTPUT1));
+ mfc_info("720p_limit_enable = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, P720_LIMIT_ENABLE));
+ mfc_info("RC_CONTROL_ENABLE = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, RC_CONTROL_ENABLE));
+}
diff --git a/drivers/media/video/samsung/mfc50/mfc_shared_mem.h b/drivers/media/video/samsung/mfc50/mfc_shared_mem.h
new file mode 100644
index 0000000..ca86876
--- /dev/null
+++ b/drivers/media/video/samsung/mfc50/mfc_shared_mem.h
@@ -0,0 +1,97 @@
+/*
+ * drivers/media/video/samsung/mfc50/mfc_shared_mem.h
+ *
+ * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
+ *
+ * Key-Young Park, Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * Change Logs
+ * 2009.10.08 - Apply 9/30 firmware(Key Young, Park)
+ * 2009.11.06 - clean & invalidate shared mem area (Key Young, Park)
+ *
+ * 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 _MFC_SHARED_MEM_H_
+#define _MFC_SHARED_MEM_H_
+
+#define MEM_WRITE(ADDR, VALUE) (*(volatile unsigned int *)(ADDR) = (VALUE))
+#define MEM_READ(ADDR) (*(volatile unsigned int *)(ADDR))
+
+enum mfc_shared {
+ EXTENEDED_DECODE_STATUS = 0x0,
+ SET_FRAME_TAG = 0x4,
+ GET_FRAME_TAG_TOP = 0x8,
+ GET_FRAME_TAG_BOT = 0xC,
+ PIC_TIME_TOP = 0x10,
+ PIC_TIME_BOT = 0x14,
+ START_BYTE_NUM = 0x18,
+ DEC_FRM_SIZE = 0x1C,
+ CROP_INFO1 = 0x20,
+ CROP_INFO2 = 0x24,
+ EXT_ENC_CONTROL = 0x28,
+ ENC_PARAM_CHANGE = 0x2C,
+ VOP_TIMING = 0x30,
+ HEC_PERIOD = 0x34,
+ METADATA_ENABLE = 0x38,
+ METADATA_STATUS = 0x3C,
+ METADATA_DISPLAY_INDEX = 0x40,
+ EXT_METADATA_START_ADDR = 0x44,
+ PUT_EXTRADATA = 0x48,
+ DBG_INFO_OUTPUT0 = 0x4C,
+ DBG_INFO_OUTPUT1 = 0x50,
+ DBG_INFO_INPUT0 = 0x54,
+ DBG_INFO_INPUT1 = 0x58,
+ REF_L0_PHY_IDX = 0x5C,
+ REF_L1_PHY_IDX = 0x60,
+ ALLOCATED_LUMA_DPB_SIZE = 0x64,
+ ALLOCATED_CHROMA_DPB_SIZE = 0x68,
+ ALLOCATED_MV_SIZE = 0x6C,
+ P_B_FRAME_QP = 0x70,
+ RC_CONTROL_ENABLE = 0xA0,
+ P720_LIMIT_ENABLE = 0xB4,
+ SHARED_MEM_MAX = 0x1000,
+};
+
+struct mfc_shared_mem {
+ unsigned int num_dpb;
+ unsigned int allocated_dpb_size;
+ unsigned int extended_decode_status;
+ unsigned int set_frame_tag;
+ unsigned int get_frame_tag_top;
+ unsigned int get_frame_tag_bot;
+ unsigned int pic_time_top;
+ unsigned int pic_time_bot;
+ unsigned int start_byte_num;
+ unsigned int dec_frm_size;
+ unsigned int crop_info1;
+ unsigned int crop_info2;
+ unsigned int ext_enc_control;
+ unsigned int enc_param_change;
+ unsigned int vop_timing;
+ unsigned int hec_period;
+ unsigned int P_B_frame_qp;
+ unsigned int metadata_enable;
+ unsigned int metadata_status;
+ unsigned int metadata_display_index;
+ unsigned int ext_metadata_start_addr;
+ unsigned int put_extradata;
+ unsigned int dbg_info_output0;
+ unsigned int dbg_info_output1;
+ unsigned int dbg_info_input0;
+ unsigned int dbg_info_input1;
+ unsigned int ref_l0_phy_idx;
+ unsigned int ref_l1_phy_idx;
+ unsigned int allocated_luma_dpb_size;
+ unsigned int allocated_chroma_dpb_size;
+ unsigned int allocated_mv_size;
+ unsigned int p720_limit_enable;
+};
+
+void mfc_write_shared_mem(unsigned int host_wr_addr, struct mfc_shared_mem *shared_mem);
+void mfc_read_shared_mem(unsigned int host_wr_addr, struct mfc_shared_mem *shared_mem);
+void mfc_print_shared_mem(unsigned int host_wr_addr);
+#endif
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c
index dbefdb0..5afdbb7 100644
--- a/drivers/media/video/uvc/uvc_v4l2.c
+++ b/drivers/media/video/uvc/uvc_v4l2.c
@@ -710,7 +710,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
break;
}
pin = iterm->id;
- } else if (pin < selector->bNrInPins) {
+ } else if (index < selector->bNrInPins) {
pin = selector->baSourceID[index];
list_for_each_entry(iterm, &chain->entities, chain) {
if (!UVC_ENTITY_IS_ITERM(iterm))
diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c
index a20e1c4..ccd81b1 100644
--- a/drivers/mfd/ab3100-core.c
+++ b/drivers/mfd/ab3100-core.c
@@ -408,8 +408,6 @@ static irqreturn_t ab3100_irq_handler(int irq, void *data)
u32 fatevent;
int err;
- add_interrupt_randomness(irq);
-
err = ab3100_get_register_page_interruptible(ab3100, AB3100_EVENTA1,
event_regs, 3);
if (err)
@@ -938,9 +936,6 @@ static int __devinit ab3100_probe(struct i2c_client *client,
err = request_threaded_irq(client->irq, NULL, ab3100_irq_handler,
IRQF_ONESHOT, "ab3100-core", ab3100);
- /* This real unpredictable IRQ is of course sampled for entropy */
- rand_initialize_irq(client->irq);
-
if (err)
goto exit_no_irq;
diff --git a/drivers/mfd/ab3550-core.c b/drivers/mfd/ab3550-core.c
index 3d7dce6..d69dc4b 100644
--- a/drivers/mfd/ab3550-core.c
+++ b/drivers/mfd/ab3550-core.c
@@ -1309,8 +1309,6 @@ static int __init ab3550_probe(struct i2c_client *client,
err = request_threaded_irq(client->irq, NULL, ab3550_irq_handler,
IRQF_ONESHOT, "ab3550-core", ab);
- /* This real unpredictable IRQ is of course sampled for entropy */
- rand_initialize_irq(client->irq);
if (err)
goto exit_no_irq;
diff --git a/drivers/mfd/ezx-pcap.c b/drivers/mfd/ezx-pcap.c
index 43a76c4..db662e2 100644
--- a/drivers/mfd/ezx-pcap.c
+++ b/drivers/mfd/ezx-pcap.c
@@ -202,7 +202,7 @@ static void pcap_isr_work(struct work_struct *work)
}
local_irq_enable();
ezx_pcap_write(pcap, PCAP_REG_MSR, pcap->msr);
- } while (gpio_get_value(irq_to_gpio(pcap->spi->irq)));
+ } while (gpio_get_value(pdata->gpio));
}
static void pcap_irq_handler(unsigned int irq, struct irq_desc *desc)
diff --git a/drivers/mfd/max8998.c b/drivers/mfd/max8998.c
index 9ec7570..c3c5fc2 100644..100755
--- a/drivers/mfd/max8998.c
+++ b/drivers/mfd/max8998.c
@@ -39,6 +39,8 @@ static struct mfd_cell max8998_devs[] = {
.name = "max8998-pmic",
}, {
.name = "max8998-rtc",
+ }, {
+ .name = "max8998-charger",
},
};
diff --git a/drivers/mfd/wm831x-otp.c b/drivers/mfd/wm831x-otp.c
index f742745..b90f3e0 100644
--- a/drivers/mfd/wm831x-otp.c
+++ b/drivers/mfd/wm831x-otp.c
@@ -18,6 +18,7 @@
#include <linux/bcd.h>
#include <linux/delay.h>
#include <linux/mfd/core.h>
+#include <linux/random.h>
#include <linux/mfd/wm831x/core.h>
#include <linux/mfd/wm831x/otp.h>
@@ -66,6 +67,7 @@ static DEVICE_ATTR(unique_id, 0444, wm831x_unique_id_show, NULL);
int wm831x_otp_init(struct wm831x *wm831x)
{
+ char uuid[WM831X_UNIQUE_ID_LEN];
int ret;
ret = device_create_file(wm831x->dev, &dev_attr_unique_id);
@@ -73,6 +75,12 @@ int wm831x_otp_init(struct wm831x *wm831x)
dev_err(wm831x->dev, "Unique ID attribute not created: %d\n",
ret);
+ ret = wm831x_unique_id_read(wm831x, uuid);
+ if (ret == 0)
+ add_device_randomness(uuid, sizeof(uuid));
+ else
+ dev_err(wm831x->dev, "Failed to read UUID: %d\n", ret);
+
return ret;
}
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 051bfe9..2149aef 100644..100755
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -391,6 +391,14 @@ config HMC6352
This driver provides support for the Honeywell HMC6352 compass,
providing configuration and heading data via sysfs.
+config SENSORS_AK8973
+ tristate "AK8973 magnetometer support"
+ default n
+ depends on I2C
+ help
+ If you say yes here you get support for Asahi Kasei's
+ orientation sensor AK8973.
+
config SENSORS_AK8975
tristate "AK8975 compass support"
default n
@@ -399,6 +407,13 @@ config SENSORS_AK8975
If you say yes here you get support for Asahi Kasei's
orientation sensor AK8975.
+config SENSORS_KR3DM
+ tristate "KR3DM acceleration sensor support"
+ depends on I2C
+ default n
+ help
+ Driver for STMicro KR3DM accelerometer - digital motion sensor.
+
config EP93XX_PWM
tristate "EP93xx PWM support"
depends on ARCH_EP93XX
@@ -525,6 +540,24 @@ config APANIC_PLABEL
If your platform uses a different flash partition label for storing
crashdumps, enter it here.
+config SAMSUNG_JACK
+ bool "3.5MM ear jack driver for Samsung devices"
+ depends on INPUT
+ default n
+ ---help---
+ This is 3.5MM ear jack driver for Samsung devices.
+
+ If unsure, say N.
+
+config USB_SWITCH_FSA9480
+ tristate "FSA9480 USB Switch"
+ depends on I2C
+ help
+ The FSA9480 is a USB port accessory detector and switch.
+ The FSA9480 is fully controlled using I2C and enables USB data,
+ stereo and mono audio, video, microphone and UART data to use
+ a common connector port.
+
source "drivers/misc/c2port/Kconfig"
source "drivers/misc/eeprom/Kconfig"
source "drivers/misc/cb710/Kconfig"
@@ -533,4 +566,25 @@ source "drivers/misc/ti-st/Kconfig"
source "drivers/misc/lis3lv02d/Kconfig"
source "drivers/misc/carma/Kconfig"
+config SAMSUNG_MODEMCTL
+ bool "Samsung Modem Control/IO Driver"
+
+config PN544
+ bool "NXP PN544 NFC Controller Driver"
+ default n
+ help
+ NXP PN544 Near Field Communication controller support.
+
+config GENERIC_BLN
+ bool "Generic BLN support for backlight notification"
+ default y
+ help
+ Say Y here to enable the backlight notification
+ for android led-notification (modified liblight needed)
+config BLD
+ bool "Support for Backlight Dimmer"
+ default y
+ help
+ Say Y here to enable Backlight Dimmer
+
endif # MISC_DEVICES
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 606b27f..b624ade 100644..100755
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -49,4 +49,14 @@ obj-y += lis3lv02d/
obj-y += carma/
obj-$(CONFIG_WL127X_RFKILL) += wl127x-rfkill.o
obj-$(CONFIG_APANIC) += apanic.o
+obj-$(CONFIG_SENSORS_AK8973) += ak8973.o
obj-$(CONFIG_SENSORS_AK8975) += akm8975.o
+obj-$(CONFIG_SENSORS_KR3DM) += kr3dm.o
+obj-$(CONFIG_PN544) += pn544.o
+obj-$(CONFIG_SAMSUNG_JACK) += sec_jack.o
+obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
+obj-$(CONFIG_SAMSUNG_MODEMCTL) += samsung_modemctl/
+obj-$(CONFIG_GENERIC_BLN) += bln.o
+obj-$(CONFIG_CPU_DIDLE) += deep_idle.o
+obj-$(CONFIG_BLD) += bld.o
+
diff --git a/drivers/misc/ak8973-reg.h b/drivers/misc/ak8973-reg.h
new file mode 100644
index 0000000..1582076
--- /dev/null
+++ b/drivers/misc/ak8973-reg.h
@@ -0,0 +1,47 @@
+/* linux/drivers/misc/ak8973-reg.h
+ *
+ * Copyright (c) 2010 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 version 2 as
+ * published by the Free Software Foundation.
+*/
+#ifndef __AK8973_REG__
+#define __AK8983_REG__
+
+/* Compass device dependent definition */
+#define AK8973_MODE_MEASURE 0x00 /* Starts measurement. */
+#define AK8973_MODE_E2P_READ 0x02 /* E2P access mode (read). */
+#define AK8973_MODE_POWERDOWN 0x03 /* Power down mode */
+
+/* Rx buffer size. i.e ST,TMPS,H1X,H1Y,H1Z*/
+#define SENSOR_DATA_SIZE 5
+
+/* Read/Write buffer size.*/
+#define RWBUF_SIZE 16
+
+/* AK8973 register address */
+#define AK8973_REG_ST 0xC0
+#define AK8973_REG_TMPS 0xC1
+#define AK8973_REG_H1X 0xC2
+#define AK8973_REG_H1Y 0xC3
+#define AK8973_REG_H1Z 0xC4
+
+#define AK8973_REG_MS1 0xE0
+#define AK8973_REG_HXDA 0xE1
+#define AK8973_REG_HYDA 0xE2
+#define AK8973_REG_HZDA 0xE3
+#define AK8973_REG_HXGA 0xE4
+#define AK8973_REG_HYGA 0xE5
+#define AK8973_REG_HZGA 0xE6
+
+#define AK8973_EEP_ETS 0x62
+#define AK8973_EEP_EVIR 0x63
+#define AK8973_EEP_EIHE 0x64
+#define AK8973_EEP_ETST 0x65
+#define AK8973_EEP_EHXGA 0x66
+#define AK8973_EEP_EHYGA 0x67
+#define AK8973_EEP_EHZGA 0x68
+
+#endif /* __AK8983_REG__ */
diff --git a/drivers/misc/ak8973.c b/drivers/misc/ak8973.c
new file mode 100644
index 0000000..967a707
--- /dev/null
+++ b/drivers/misc/ak8973.c
@@ -0,0 +1,407 @@
+/*
+ * ak8973.c - ak8973 compass driver
+ *
+ * Copyright (C) 2008-2009 HTC Corporation.
+ * Author: viral wang <viralwang@gmail.com>
+ *
+ * Copyright (C) 2010 Samsung Electronics. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/i2c/ak8973.h>
+#include <linux/completion.h>
+#include "ak8973-reg.h"
+
+#define AK8973DRV_DATA_DBG 0
+
+struct akm8973_data {
+ struct i2c_client *this_client;
+ struct akm8973_platform_data *pdata;
+ struct mutex lock;
+ struct miscdevice akmd_device;
+ int irq;
+ struct completion data_ready;
+ wait_queue_head_t state_wq;
+};
+
+static s32 akm8973_ecs_set_mode_power_down(struct akm8973_data *akm)
+{
+ s32 ret;
+
+ ret = i2c_smbus_write_byte_data(akm->this_client,
+ AK8973_REG_MS1, AK8973_MODE_POWERDOWN);
+ if (ret < 0)
+ return ret;
+
+ return i2c_smbus_read_byte_data(akm->this_client, AK8973_REG_TMPS);
+}
+
+static int akm8973_ecs_set_mode(struct akm8973_data *akm, char mode)
+{
+ s32 ret;
+
+ switch (mode) {
+ case AK8973_MODE_MEASURE:
+ ret = i2c_smbus_write_byte_data(akm->this_client,
+ AK8973_REG_MS1, AK8973_MODE_MEASURE);
+ break;
+ case AK8973_MODE_E2P_READ:
+ ret = i2c_smbus_write_byte_data(akm->this_client,
+ AK8973_REG_MS1, AK8973_MODE_E2P_READ);
+ break;
+ case AK8973_MODE_POWERDOWN:
+ ret = akm8973_ecs_set_mode_power_down(akm);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (ret < 0)
+ return ret;
+
+ /* Wait at least 300us after changing mode. */
+ udelay(300);
+
+ return 0;
+}
+
+static void akm8973_reset(struct akm8973_data *akm)
+{
+ gpio_set_value(akm->pdata->reset_line, akm->pdata->reset_asserted);
+ msleep(2);
+ gpio_set_value(akm->pdata->reset_line, !akm->pdata->reset_asserted);
+}
+
+static int akmd_copy_in(unsigned int cmd, void __user *argp,
+ void *buf, size_t buf_size)
+{
+ if (!(cmd & IOC_IN))
+ return 0;
+ if (_IOC_SIZE(cmd) > buf_size)
+ return -EINVAL;
+ if (copy_from_user(buf, argp, _IOC_SIZE(cmd)))
+ return -EFAULT;
+ return 0;
+}
+
+static int akmd_copy_out(unsigned int cmd, void __user *argp,
+ void *buf, size_t buf_size)
+{
+ if (!(cmd & IOC_OUT))
+ return 0;
+ if (_IOC_SIZE(cmd) > buf_size)
+ return -EINVAL;
+ if (copy_to_user(argp, buf, _IOC_SIZE(cmd)))
+ return -EFAULT;
+ return 0;
+}
+
+static void akm8973_disable_irq(struct akm8973_data *akm)
+{
+ disable_irq(akm->irq);
+ if (try_wait_for_completion(&akm->data_ready)) {
+ /* we actually got the interrupt before we could disable it
+ * so we need to enable again to undo our disable since the
+ * irq_handler already disabled it
+ */
+ enable_irq(akm->irq);
+ }
+}
+
+static irqreturn_t akm8973_irq_handler(int irq, void *data)
+{
+ struct akm8973_data *akm = data;
+ disable_irq_nosync(irq);
+ complete(&akm->data_ready);
+ return IRQ_HANDLED;
+}
+
+static int akm8973_wait_for_data_ready(struct akm8973_data *akm)
+{
+ int data_ready = gpio_get_value(akm->pdata->gpio_data_ready_int);
+ int err;
+
+ if (data_ready)
+ return 0;
+
+ enable_irq(akm->irq);
+
+ err = wait_for_completion_timeout(&akm->data_ready, 5*HZ);
+ if (err > 0)
+ return 0;
+
+ akm8973_disable_irq(akm);
+
+ if (err == 0) {
+ pr_err("akm: wait timed out\n");
+ return -ETIMEDOUT;
+ }
+
+ pr_err("akm: wait restart\n");
+ return err;
+}
+
+static long akmd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ struct akm8973_data *akm = container_of(file->private_data,
+ struct akm8973_data, akmd_device);
+ int ret;
+ union {
+ char raw[RWBUF_SIZE];
+ int status;
+ char mode;
+ u8 data[5];
+ } rwbuf;
+
+ ret = akmd_copy_in(cmd, argp, rwbuf.raw, sizeof(rwbuf));
+ if (ret)
+ return ret;
+
+ switch (cmd) {
+ case ECS_IOCTL_WRITE:
+ if ((rwbuf.raw[0] < 2) || (rwbuf.raw[0] > (RWBUF_SIZE - 1)))
+ return -EINVAL;
+ if (copy_from_user(&rwbuf.raw[2], argp+2, rwbuf.raw[0]-1))
+ return -EFAULT;
+
+ ret = i2c_smbus_write_i2c_block_data(akm->this_client,
+ rwbuf.raw[1],
+ rwbuf.raw[0] - 1,
+ &rwbuf.raw[2]);
+ break;
+ case ECS_IOCTL_READ:
+ if ((rwbuf.raw[0] < 1) || (rwbuf.raw[0] > (RWBUF_SIZE - 1)))
+ return -EINVAL;
+
+ ret = i2c_smbus_read_i2c_block_data(akm->this_client,
+ rwbuf.raw[1],
+ rwbuf.raw[0],
+ &rwbuf.raw[1]);
+ if (ret < 0)
+ return ret;
+ if (copy_to_user(argp+1, rwbuf.raw+1, rwbuf.raw[0]))
+ return -EFAULT;
+ return 0;
+ case ECS_IOCTL_RESET:
+ akm8973_reset(akm);
+ break;
+ case ECS_IOCTL_SET_MODE:
+ ret = akm8973_ecs_set_mode(akm, rwbuf.mode);
+ break;
+ case ECS_IOCTL_GETDATA:
+ ret = akm8973_wait_for_data_ready(akm);
+ if (ret)
+ return ret;
+ ret = i2c_smbus_read_i2c_block_data(akm->this_client,
+ AK8973_REG_ST,
+ sizeof(rwbuf.data),
+ rwbuf.data);
+ if (ret != sizeof(rwbuf.data)) {
+ pr_err("%s : failed to read %d bytes of mag data\n",
+ __func__, sizeof(rwbuf.data));
+ return -EIO;
+ }
+ break;
+ default:
+ return -ENOTTY;
+ }
+
+ if (ret < 0)
+ return ret;
+
+ return akmd_copy_out(cmd, argp, rwbuf.raw, sizeof(rwbuf));
+}
+
+static const struct file_operations akmd_fops = {
+ .owner = THIS_MODULE,
+ .open = nonseekable_open,
+ .unlocked_ioctl = akmd_ioctl,
+};
+
+static int akm8973_setup_irq(struct akm8973_data *akm)
+{
+ int rc = -EIO;
+ struct akm8973_platform_data *pdata = akm->pdata;
+ int irq;
+
+ rc = gpio_request(pdata->gpio_data_ready_int, "gpio_akm_int");
+ if (rc < 0) {
+ pr_err("%s: gpio %d request failed (%d)\n",
+ __func__, pdata->gpio_data_ready_int, rc);
+ return rc;
+ }
+
+ rc = gpio_direction_input(pdata->gpio_data_ready_int);
+ if (rc < 0) {
+ pr_err("%s: failed to set gpio %d as input (%d)\n",
+ __func__, pdata->gpio_data_ready_int, rc);
+ goto err_gpio_direction_input;
+ }
+
+ irq = gpio_to_irq(pdata->gpio_data_ready_int);
+
+ /* trigger high so we don't miss initial interrupt if it
+ * is already pending
+ */
+ rc = request_irq(irq, akm8973_irq_handler, IRQF_TRIGGER_HIGH,
+ "akm_int", akm);
+ if (rc < 0) {
+ pr_err("%s: request_irq(%d) failed for gpio %d (%d)\n",
+ __func__, irq,
+ pdata->gpio_data_ready_int, rc);
+ goto err_request_irq;
+ }
+
+ /* start with interrupt disabled until the driver is enabled */
+ akm->irq = irq;
+ akm8973_disable_irq(akm);
+
+ goto done;
+
+err_request_irq:
+err_gpio_direction_input:
+ gpio_free(pdata->gpio_data_ready_int);
+done:
+ return rc;
+}
+
+int akm8973_probe(struct i2c_client *client,
+ const struct i2c_device_id *devid)
+{
+ struct akm8973_data *akm;
+ int err;
+
+ if (client->dev.platform_data == NULL) {
+ dev_err(&client->dev, "platform data is NULL. exiting.\n");
+ err = -ENODEV;
+ goto exit_platform_data_null;
+ }
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ dev_err(&client->dev, "I2C check failed, exiting.\n");
+ err = -ENODEV;
+ goto exit_check_functionality_failed;
+ }
+
+ akm = kzalloc(sizeof(struct akm8973_data), GFP_KERNEL);
+ if (!akm) {
+ dev_err(&client->dev,
+ "failed to allocate memory for module data\n");
+ err = -ENOMEM;
+ goto exit_alloc_data_failed;
+ }
+
+ akm->pdata = client->dev.platform_data;
+ mutex_init(&akm->lock);
+ init_completion(&akm->data_ready);
+
+ i2c_set_clientdata(client, akm);
+ akm->this_client = client;
+
+ err = gpio_request(akm->pdata->reset_line, "AK8973 Reset Line");
+ if (err < 0)
+ goto exit_reset_gpio_request_failed;
+ gpio_direction_output(akm->pdata->reset_line,
+ !akm->pdata->reset_asserted);
+ akm8973_reset(akm);
+
+ err = akm8973_ecs_set_mode_power_down(akm);
+ if (err < 0)
+ goto exit_set_mode_power_down_failed;
+
+ err = akm8973_setup_irq(akm);
+ if (err) {
+ pr_err("%s: could not setup irq\n", __func__);
+ goto exit_setup_irq;
+ }
+
+ akm->akmd_device.minor = MISC_DYNAMIC_MINOR;
+ akm->akmd_device.name = "akm8973";
+ akm->akmd_device.fops = &akmd_fops;
+
+ err = misc_register(&akm->akmd_device);
+ if (err)
+ goto exit_akmd_device_register_failed;
+
+ init_waitqueue_head(&akm->state_wq);
+
+ return 0;
+
+exit_akmd_device_register_failed:
+ free_irq(akm->irq, akm);
+ gpio_free(akm->pdata->gpio_data_ready_int);
+exit_setup_irq:
+exit_set_mode_power_down_failed:
+ gpio_direction_input(akm->pdata->reset_line);
+ gpio_free(akm->pdata->reset_line);
+exit_reset_gpio_request_failed:
+ mutex_destroy(&akm->lock);
+ kfree(akm);
+exit_alloc_data_failed:
+exit_check_functionality_failed:
+exit_platform_data_null:
+ return err;
+}
+
+static int __devexit akm8973_remove(struct i2c_client *client)
+{
+ struct akm8973_data *akm = i2c_get_clientdata(client);
+
+ misc_deregister(&akm->akmd_device);
+ gpio_direction_input(akm->pdata->reset_line);
+ gpio_free(akm->pdata->reset_line);
+ free_irq(akm->irq, akm);
+ gpio_free(akm->pdata->gpio_data_ready_int);
+ mutex_destroy(&akm->lock);
+ kfree(akm);
+ return 0;
+}
+
+static const struct i2c_device_id akm8973_id[] = {
+ {AKM8973_I2C_NAME, 0 },
+ { }
+};
+
+static struct i2c_driver akm8973_driver = {
+ .probe = akm8973_probe,
+ .remove = akm8973_remove,
+ .id_table = akm8973_id,
+ .driver = {
+ .name = AKM8973_I2C_NAME,
+ },
+};
+
+static int __init akm8973_init(void)
+{
+ return i2c_add_driver(&akm8973_driver);
+}
+
+static void __exit akm8973_exit(void)
+{
+ i2c_del_driver(&akm8973_driver);
+}
+
+module_init(akm8973_init);
+module_exit(akm8973_exit);
+
+MODULE_DESCRIPTION("AKM8973 compass driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/bld.c b/drivers/misc/bld.c
new file mode 100644
index 0000000..e4c319c
--- /dev/null
+++ b/drivers/misc/bld.c
@@ -0,0 +1,272 @@
+/* drivers/misc/bld.c
+ *
+ * Copyright 2011 Ezekeel
+ *
+ * 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/init.h>
+#include <linux/device.h>
+#include <linux/miscdevice.h>
+#include <linux/bld.h>
+#include <linux/workqueue.h>
+#include <linux/earlysuspend.h>
+#include <linux/mutex.h>
+
+static bool bld_enabled = false;
+
+static bool backlight_dimmed = false;
+
+static bool device_suspended = false;
+
+static unsigned int dimmer_delay = 5000;
+
+static void bld_toggle_backlights(struct work_struct * dimmer_work);
+
+static DECLARE_DELAYED_WORK(dimmer_work, bld_toggle_backlights);
+
+static DEFINE_MUTEX(lock);
+
+static struct bld_implementation * bld_imp = NULL;
+
+#define BACKLIGHTDIMMER_VERSION 3
+
+static void bld_early_suspend(struct early_suspend * h)
+{
+ device_suspended = true;
+
+ cancel_delayed_work(&dimmer_work);
+ flush_scheduled_work();
+
+ return;
+}
+
+static void bld_late_resume(struct early_suspend * h)
+{
+ device_suspended = false;
+
+ backlight_dimmed = false;
+
+ touchkey_pressed();
+
+ return;
+}
+
+static struct early_suspend bld_suspend_data =
+ {
+ .level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1,
+ .suspend = bld_early_suspend,
+ .resume = bld_late_resume,
+ };
+
+static void bld_disable_backlights(void)
+{
+ if (bld_imp)
+ {
+ bld_imp->disable();
+ }
+
+ backlight_dimmed = true;
+
+ mutex_unlock(&lock);
+
+ return;
+}
+
+static void bld_enable_backlights(void)
+{
+ if (bld_imp)
+ {
+ bld_imp->enable();
+ }
+
+ backlight_dimmed = false;
+
+ mutex_unlock(&lock);
+
+ touchkey_pressed();
+
+ return;
+}
+
+static void bld_toggle_backlights(struct work_struct * dimmer_work)
+{
+ if (backlight_dimmed)
+ {
+ bld_enable_backlights();
+ }
+ else
+ {
+ if (mutex_trylock(&lock))
+ {
+ bld_disable_backlights();
+ }
+ }
+
+ return;
+}
+
+static ssize_t backlightdimmer_status_read(struct device * dev, struct device_attribute * attr, char * buf)
+{
+ return sprintf(buf, "%u\n", (bld_enabled ? 1 : 0));
+}
+
+static ssize_t backlightdimmer_status_write(struct device * dev, struct device_attribute * attr, const char * buf, size_t size)
+{
+ unsigned int data;
+
+ if(sscanf(buf, "%u\n", &data) == 1)
+ {
+ pr_devel("%s: %u \n", __FUNCTION__, data);
+
+ if (data == 1)
+ {
+ pr_info("%s: BLD function enabled\n", __FUNCTION__);
+
+ bld_enabled = true;
+
+ touchkey_pressed();
+ }
+ else if (data == 0)
+ {
+ pr_info("%s: BLD function disabled\n", __FUNCTION__);
+
+ bld_enabled = false;
+
+ cancel_delayed_work(&dimmer_work);
+ flush_scheduled_work();
+
+ if (backlight_dimmed)
+ {
+ bld_enable_backlights();
+ }
+ }
+ else
+ {
+ pr_info("%s: invalid input range %u\n", __FUNCTION__, data);
+ }
+ }
+ else
+ {
+ pr_info("%s: invalid input\n", __FUNCTION__);
+ }
+
+ return size;
+}
+
+static ssize_t backlightdimmer_delay_read(struct device * dev, struct device_attribute * attr, char * buf)
+{
+ return sprintf(buf, "%u\n", dimmer_delay);
+}
+
+static ssize_t backlightdimmer_delay_write(struct device * dev, struct device_attribute * attr, const char * buf, size_t size)
+{
+ unsigned int data;
+
+ if(sscanf(buf, "%u\n", &data) == 1)
+ {
+ dimmer_delay = data;
+
+ pr_info("BLD delay set to %u\n", dimmer_delay);
+
+ touchkey_pressed();
+ }
+ else
+ {
+ pr_info("%s: invalid input\n", __FUNCTION__);
+ }
+
+ return size;
+}
+
+static ssize_t backlightdimmer_version(struct device * dev, struct device_attribute * attr, char * buf)
+{
+ return sprintf(buf, "%u\n", BACKLIGHTDIMMER_VERSION);
+}
+
+static DEVICE_ATTR(enabled, S_IRUGO | S_IWUGO, backlightdimmer_status_read, backlightdimmer_status_write);
+static DEVICE_ATTR(delay, S_IRUGO | S_IWUGO, backlightdimmer_delay_read, backlightdimmer_delay_write);
+static DEVICE_ATTR(version, S_IRUGO , backlightdimmer_version, NULL);
+
+static struct attribute *bld_notification_attributes[] =
+ {
+ &dev_attr_enabled.attr,
+ &dev_attr_delay.attr,
+ &dev_attr_version.attr,
+ NULL
+ };
+
+static struct attribute_group bld_notification_group =
+ {
+ .attrs = bld_notification_attributes,
+ };
+
+static struct miscdevice bld_device =
+ {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "backlightdimmer",
+ };
+
+void touchkey_pressed(void)
+{
+ if (!device_suspended && bld_enabled)
+ {
+ if (backlight_dimmed)
+ {
+ if (mutex_trylock(&lock))
+ {
+ cancel_delayed_work(&dimmer_work);
+ schedule_delayed_work(&dimmer_work, 0);
+ }
+ }
+ else
+ {
+ if (!mutex_is_locked(&lock))
+ {
+ cancel_delayed_work(&dimmer_work);
+ schedule_delayed_work(&dimmer_work, msecs_to_jiffies(dimmer_delay));
+ }
+ }
+ }
+
+ return;
+}
+EXPORT_SYMBOL(touchkey_pressed);
+
+void register_bld_implementation(struct bld_implementation * imp)
+{
+ bld_imp = imp;
+
+ return;
+}
+EXPORT_SYMBOL(register_bld_implementation);
+
+static int __init bld_control_init(void)
+{
+ int ret;
+
+ pr_info("%s misc_register(%s)\n", __FUNCTION__, bld_device.name);
+
+ ret = misc_register(&bld_device);
+
+ if (ret)
+ {
+ pr_err("%s misc_register(%s) fail\n", __FUNCTION__, bld_device.name);
+
+ return 1;
+ }
+
+ if (sysfs_create_group(&bld_device.this_device->kobj, &bld_notification_group) < 0)
+ {
+ pr_err("%s sysfs_create_group fail\n", __FUNCTION__);
+ pr_err("Failed to create sysfs group for device (%s)!\n", bld_device.name);
+ }
+
+ register_early_suspend(&bld_suspend_data);
+
+ return 0;
+}
+
+device_initcall(bld_control_init);
diff --git a/drivers/misc/bln.c b/drivers/misc/bln.c
new file mode 100644
index 0000000..ce63bd9
--- /dev/null
+++ b/drivers/misc/bln.c
@@ -0,0 +1,208 @@
+/* drivers/misc/bln.c
+ *
+ * Copyright 2011 Michael Richter (alias neldar)
+ * Copyright 2011 Adam Kent <adam@semicircular.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/earlysuspend.h>
+#include <linux/device.h>
+#include <linux/miscdevice.h>
+#include <linux/bln.h>
+#include <linux/mutex.h>
+#include <linux/timer.h>
+#include <linux/wakelock.h>
+
+static bool bln_enabled = true; /* is BLN function is enabled */
+static bool bln_ongoing = false; /* ongoing LED Notification */
+static bool bln_suspended = false; /* is system suspended */
+static struct bln_implementation *bln_imp = NULL;
+
+static struct wake_lock bln_wake_lock;
+
+#define BACKLIGHTNOTIFICATION_VERSION 9
+
+static void bln_enable_backlights(void)
+{
+ if (bln_imp)
+ bln_imp->enable();
+}
+
+static void bln_disable_backlights(void)
+{
+ if (bln_imp)
+ bln_imp->disable();
+}
+
+static void bln_early_suspend(struct early_suspend *h)
+{
+ bln_suspended = true;
+}
+
+static void bln_late_resume(struct early_suspend *h)
+{
+ bln_suspended = false;
+}
+
+static struct early_suspend bln_suspend_data = {
+ .level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1,
+ .suspend = bln_early_suspend,
+ .resume = bln_late_resume,
+};
+
+static void enable_led_notification(void)
+{
+ if (!bln_enabled)
+ return;
+
+ bln_enable_backlights();
+ pr_info("%s: notification led enabled\n", __FUNCTION__);
+ bln_ongoing = true;
+}
+
+static void disable_led_notification(void)
+{
+ pr_info("%s: notification led disabled\n", __FUNCTION__);
+
+ bln_ongoing = false;
+
+ if (bln_suspended)
+ bln_disable_backlights();
+
+ wake_unlock(&bln_wake_lock);
+
+}
+
+static ssize_t backlightnotification_status_read(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%u\n", (bln_enabled ? 1 : 0));
+}
+
+static ssize_t backlightnotification_status_write(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ unsigned int data;
+ if(sscanf(buf, "%u\n", &data) == 1) {
+ pr_devel("%s: %u \n", __FUNCTION__, data);
+ if (data == 1) {
+ pr_info("%s: BLN function enabled\n", __FUNCTION__);
+ bln_enabled = true;
+ } else if (data == 0) {
+ pr_info("%s: BLN function disabled\n", __FUNCTION__);
+ bln_enabled = false;
+ if (bln_ongoing)
+ disable_led_notification();
+ } else {
+ pr_info("%s: invalid input range %u\n", __FUNCTION__,
+ data);
+ }
+ } else {
+ pr_info("%s: invalid input\n", __FUNCTION__);
+ }
+
+ return size;
+}
+
+static ssize_t notification_led_status_read(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf,"%u\n", (bln_ongoing ? 1 : 0));
+}
+
+static ssize_t notification_led_status_write(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ unsigned int data;
+
+ if (sscanf(buf, "%u\n", &data) == 1) {
+ if (data == 1)
+ enable_led_notification();
+ else if (data == 0)
+ disable_led_notification();
+ else
+ pr_info("%s: wrong input %u\n", __FUNCTION__, data);
+ } else {
+ pr_info("%s: input error\n", __FUNCTION__);
+ }
+
+ return size;
+}
+
+static ssize_t backlightnotification_version(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%u\n", BACKLIGHTNOTIFICATION_VERSION);
+}
+
+static DEVICE_ATTR(enabled, S_IRUGO | S_IWUGO,
+ backlightnotification_status_read,
+ backlightnotification_status_write);
+static DEVICE_ATTR(led, S_IRUGO | S_IWUGO,
+ notification_led_status_read,
+ notification_led_status_write);
+static DEVICE_ATTR(version, S_IRUGO , backlightnotification_version, NULL);
+
+static struct attribute *bln_notification_attributes[] = {
+ &dev_attr_enabled.attr,
+ &dev_attr_led.attr,
+ &dev_attr_version.attr,
+ NULL
+};
+
+static struct attribute_group bln_notification_group = {
+ .attrs = bln_notification_attributes,
+};
+
+static struct miscdevice bln_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "notification",
+};
+
+void register_bln_implementation(struct bln_implementation *imp)
+{
+ bln_imp = imp;
+}
+EXPORT_SYMBOL(register_bln_implementation);
+
+bool bln_is_ongoing()
+{
+ return bln_ongoing;
+}
+EXPORT_SYMBOL(bln_is_ongoing);
+
+
+static int __init bln_control_init(void)
+{
+ int ret;
+
+ pr_info("%s misc_register(%s)\n", __FUNCTION__, bln_device.name);
+ ret = misc_register(&bln_device);
+ if (ret) {
+ pr_err("%s misc_register(%s) fail\n", __FUNCTION__,
+ bln_device.name);
+ return 1;
+ }
+
+ /* add the bln attributes */
+ if (sysfs_create_group(&bln_device.this_device->kobj,
+ &bln_notification_group) < 0) {
+ pr_err("%s sysfs_create_group fail\n", __FUNCTION__);
+ pr_err("Failed to create sysfs group for device (%s)!\n",
+ bln_device.name);
+ }
+
+ register_early_suspend(&bln_suspend_data);
+
+ /* Initialize wake locks */
+ wake_lock_init(&bln_wake_lock, WAKE_LOCK_SUSPEND, "bln_wake");
+
+ return 0;
+}
+
+device_initcall(bln_control_init);
diff --git a/drivers/misc/deep_idle.c b/drivers/misc/deep_idle.c
new file mode 100644
index 0000000..e3064a3
--- /dev/null
+++ b/drivers/misc/deep_idle.c
@@ -0,0 +1,233 @@
+/* drivers/misc/deep_idle.c
+ *
+ * Copyright 2011 Ezekeel
+ *
+ * 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/init.h>
+#include <linux/device.h>
+#include <linux/miscdevice.h>
+#include <linux/mutex.h>
+#include <linux/deep_idle.h>
+
+#define DEEPIDLE_VERSION 2
+
+#define NUM_IDLESTATES 3
+
+static DEFINE_MUTEX(lock);
+
+static bool deepidle_enabled = false;
+
+static unsigned long long num_idlecalls[NUM_IDLESTATES], time_in_idlestate[NUM_IDLESTATES];
+
+static ssize_t deepidle_status_read(struct device * dev, struct device_attribute * attr, char * buf)
+{
+ return sprintf(buf, "%u\n", (deepidle_enabled ? 1 : 0));
+}
+
+static ssize_t deepidle_status_write(struct device * dev, struct device_attribute * attr, const char * buf, size_t size)
+{
+ unsigned int data;
+
+ if(sscanf(buf, "%u\n", &data) == 1)
+ {
+ if (data == 1)
+ {
+ pr_info("%s: DEEPIDLE enabled\n", __FUNCTION__);
+
+ deepidle_enabled = true;
+ }
+ else if (data == 0)
+ {
+ pr_info("%s: DEEPIDLE disabled\n", __FUNCTION__);
+
+ deepidle_enabled = false;
+ }
+ else
+ {
+ pr_info("%s: invalid input range %u\n", __FUNCTION__, data);
+ }
+ }
+ else
+ {
+ pr_info("%s: invalid input\n", __FUNCTION__);
+ }
+
+ return size;
+}
+
+static ssize_t show_idle_stats(struct device * dev, struct device_attribute * attr, char * buf)
+{
+ int i;
+ unsigned long long msecs_in_idlestate[NUM_IDLESTATES], avg_in_idlestate[NUM_IDLESTATES];
+
+ mutex_lock(&lock);
+
+ for (i = 0; i < NUM_IDLESTATES; i++) {
+ msecs_in_idlestate[i] = time_in_idlestate[i] + 500;
+ do_div(msecs_in_idlestate[i], 1000);
+ if (num_idlecalls[i] == 0) {
+ avg_in_idlestate[i] = 0;
+ } else {
+ avg_in_idlestate[i] = msecs_in_idlestate[i];
+ do_div(avg_in_idlestate[i], num_idlecalls[i]);
+ }
+ }
+
+ mutex_unlock(&lock);
+
+ return sprintf(buf, "idle state total (average)\n===================================================\nIDLE %llums (%llums)\nDEEP IDLE (TOP=ON) %llums (%llums)\nDEEP IDLE (TOP=OFF) %llums (%llums)\n",
+ msecs_in_idlestate[0], avg_in_idlestate[0], msecs_in_idlestate[1], avg_in_idlestate[1], msecs_in_idlestate[2], avg_in_idlestate[2]);
+}
+
+static ssize_t show_idle_stats_list(struct device * dev, struct device_attribute * attr, char * buf)
+{
+ int i;
+ unsigned long long msecs_in_idlestate[NUM_IDLESTATES], avg_in_idlestate[NUM_IDLESTATES];
+
+ mutex_lock(&lock);
+
+ for (i = 0; i < NUM_IDLESTATES; i++) {
+ msecs_in_idlestate[i] = time_in_idlestate[i] + 500;
+ do_div(msecs_in_idlestate[i], 1000);
+ if (num_idlecalls[i] == 0) {
+ avg_in_idlestate[i] = 0;
+ } else {
+ avg_in_idlestate[i] = msecs_in_idlestate[i];
+ do_div(avg_in_idlestate[i], num_idlecalls[i]);
+ }
+ }
+
+ mutex_unlock(&lock);
+
+ return sprintf(buf, "%llu %llu %llu %llu %llu %llu\n",
+ msecs_in_idlestate[0], avg_in_idlestate[0], msecs_in_idlestate[1],
+ avg_in_idlestate[1], msecs_in_idlestate[2], avg_in_idlestate[2]);
+}
+
+static void reset_stats(void)
+{
+ int i;
+
+ for (i = 0; i < NUM_IDLESTATES; i++)
+ {
+ num_idlecalls[i] = 0;
+ time_in_idlestate[i] = 0;
+ }
+
+ return;
+}
+
+static ssize_t reset_idle_stats(struct device * dev, struct device_attribute * attr, const char * buf, size_t size)
+{
+ unsigned int data;
+
+ if(sscanf(buf, "%u\n", &data) == 1)
+ {
+ if (data == 1)
+ {
+ mutex_lock(&lock);
+ reset_stats();
+ mutex_unlock(&lock);
+ }
+ else
+ {
+ pr_info("%s: invalid input range %u\n", __FUNCTION__, data);
+ }
+ }
+ else
+ {
+ pr_info("%s: invalid input\n", __FUNCTION__);
+ }
+
+ return size;
+}
+
+static ssize_t deepidle_version(struct device * dev, struct device_attribute * attr, char * buf)
+{
+ return sprintf(buf, "%u\n", DEEPIDLE_VERSION);
+}
+
+static DEVICE_ATTR(enabled, S_IRUGO | S_IWUGO, deepidle_status_read, deepidle_status_write);
+static DEVICE_ATTR(idle_stats, S_IRUGO , show_idle_stats, NULL);
+static DEVICE_ATTR(idle_stats_list, S_IRUGO , show_idle_stats_list, NULL);
+static DEVICE_ATTR(reset_stats, S_IWUGO , NULL, reset_idle_stats);
+static DEVICE_ATTR(version, S_IRUGO , deepidle_version, NULL);
+
+static struct attribute *deepidle_attributes[] =
+ {
+ &dev_attr_enabled.attr,
+ &dev_attr_idle_stats.attr,
+ &dev_attr_idle_stats_list.attr,
+ &dev_attr_reset_stats.attr,
+ &dev_attr_version.attr,
+ NULL
+ };
+
+static struct attribute_group deepidle_group =
+ {
+ .attrs = deepidle_attributes,
+ };
+
+static struct miscdevice deepidle_device =
+ {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "deepidle",
+ };
+
+bool deepidle_is_enabled(void)
+{
+ return deepidle_enabled;
+}
+EXPORT_SYMBOL(deepidle_is_enabled);
+
+void report_idle_time(int idle_state, int idle_time)
+{
+ mutex_lock(&lock);
+
+ num_idlecalls[idle_state]++;
+ time_in_idlestate[idle_state] += (unsigned long long)idle_time;
+
+ if (num_idlecalls[idle_state] == 0 || time_in_idlestate[idle_state] < (unsigned long long)idle_time)
+ {
+ reset_stats();
+ }
+
+ mutex_unlock(&lock);
+
+ return;
+}
+EXPORT_SYMBOL(report_idle_time);
+
+static int __init deepidle_init(void)
+{
+ int ret;
+
+ pr_info("%s misc_register(%s)\n", __FUNCTION__, deepidle_device.name);
+
+ ret = misc_register(&deepidle_device);
+
+ if (ret)
+ {
+ pr_err("%s misc_register(%s) fail\n", __FUNCTION__, deepidle_device.name);
+
+ return 1;
+ }
+
+ if (sysfs_create_group(&deepidle_device.this_device->kobj, &deepidle_group) < 0)
+ {
+ pr_err("%s sysfs_create_group fail\n", __FUNCTION__);
+ pr_err("Failed to create sysfs group for device (%s)!\n", deepidle_device.name);
+ }
+
+ mutex_lock(&lock);
+ reset_stats();
+ mutex_unlock(&lock);
+
+ return 0;
+}
+
+device_initcall(deepidle_init);
diff --git a/drivers/misc/fsa9480.c b/drivers/misc/fsa9480.c
new file mode 100755
index 0000000..85aefd5
--- /dev/null
+++ b/drivers/misc/fsa9480.c
@@ -0,0 +1,612 @@
+/*
+ * driver/misc/fsa9480.c - FSA9480 micro USB switch device driver
+ *
+ * Copyright (C) 2010 Samsung Electronics
+ * Minkyu Kang <mk7.kang@samsung.com>
+ * Wonguk Jeong <wonguk.jeong@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/err.h>
+#include <linux/i2c.h>
+#include <linux/fsa9480.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+/* FSA9480 I2C registers */
+#define FSA9480_REG_DEVID 0x01
+#define FSA9480_REG_CTRL 0x02
+#define FSA9480_REG_INT1 0x03
+#define FSA9480_REG_INT2 0x04
+#define FSA9480_REG_INT1_MASK 0x05
+#define FSA9480_REG_INT2_MASK 0x06
+#define FSA9480_REG_ADC 0x07
+#define FSA9480_REG_TIMING1 0x08
+#define FSA9480_REG_TIMING2 0x09
+#define FSA9480_REG_DEV_T1 0x0a
+#define FSA9480_REG_DEV_T2 0x0b
+#define FSA9480_REG_BTN1 0x0c
+#define FSA9480_REG_BTN2 0x0d
+#define FSA9480_REG_CK 0x0e
+#define FSA9480_REG_CK_INT1 0x0f
+#define FSA9480_REG_CK_INT2 0x10
+#define FSA9480_REG_CK_INTMASK1 0x11
+#define FSA9480_REG_CK_INTMASK2 0x12
+#define FSA9480_REG_MANSW1 0x13
+#define FSA9480_REG_MANSW2 0x14
+
+/* Control */
+#define CON_SWITCH_OPEN (1 << 4)
+#define CON_RAW_DATA (1 << 3)
+#define CON_MANUAL_SW (1 << 2)
+#define CON_WAIT (1 << 1)
+#define CON_INT_MASK (1 << 0)
+#define CON_MASK (CON_SWITCH_OPEN | CON_RAW_DATA | \
+ CON_MANUAL_SW | CON_WAIT)
+
+/* Device Type 1 */
+#define DEV_USB_OTG (1 << 7)
+#define DEV_DEDICATED_CHG (1 << 6)
+#define DEV_USB_CHG (1 << 5)
+#define DEV_CAR_KIT (1 << 4)
+#define DEV_UART (1 << 3)
+#define DEV_USB (1 << 2)
+#define DEV_AUDIO_2 (1 << 1)
+#define DEV_AUDIO_1 (1 << 0)
+
+#define DEV_T1_USB_MASK (DEV_USB_OTG | DEV_USB)
+#define DEV_T1_UART_MASK (DEV_UART)
+#define DEV_T1_CHARGER_MASK (DEV_DEDICATED_CHG | DEV_USB_CHG | DEV_CAR_KIT)
+
+/* Device Type 2 */
+#define DEV_AV (1 << 6)
+#define DEV_TTY (1 << 5)
+#define DEV_PPD (1 << 4)
+#define DEV_JIG_UART_OFF (1 << 3)
+#define DEV_JIG_UART_ON (1 << 2)
+#define DEV_JIG_USB_OFF (1 << 1)
+#define DEV_JIG_USB_ON (1 << 0)
+
+#define DEV_T2_USB_MASK (DEV_JIG_USB_OFF | DEV_JIG_USB_ON)
+#define DEV_T2_UART_MASK DEV_JIG_UART_OFF
+#define DEV_T2_JIG_MASK (DEV_JIG_USB_OFF | DEV_JIG_USB_ON | \
+ DEV_JIG_UART_OFF)
+
+/*
+ * Manual Switch
+ * D- [7:5] / D+ [4:2]
+ * 000: Open all / 001: USB / 010: AUDIO / 011: UART / 100: V_AUDIO
+ */
+#define SW_VAUDIO ((4 << 5) | (4 << 2))
+#define SW_UART ((3 << 5) | (3 << 2))
+#define SW_AUDIO ((2 << 5) | (2 << 2))
+#define SW_DHOST ((1 << 5) | (1 << 2))
+#define SW_AUTO ((0 << 5) | (0 << 2))
+
+/* Interrupt 1 */
+#define INT_DETACH (1 << 1)
+#define INT_ATTACH (1 << 0)
+
+#if defined CONFIG_USB_S3C_OTG_HOST || defined CONFIG_USB_DWC_OTG
+extern void set_otghost_mode(int mode);
+#endif
+
+struct fsa9480_usbsw {
+ struct i2c_client *client;
+ struct fsa9480_platform_data *pdata;
+ int dev1;
+ int dev2;
+ int mansw;
+};
+
+static ssize_t fsa9480_show_control(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct fsa9480_usbsw *usbsw = dev_get_drvdata(dev);
+ struct i2c_client *client = usbsw->client;
+ int value;
+
+ value = i2c_smbus_read_byte_data(client, FSA9480_REG_CTRL);
+ if (value < 0)
+ dev_err(&client->dev, "%s: err %d\n", __func__, value);
+
+ return sprintf(buf, "CONTROL: %02x\n", value);
+}
+
+static ssize_t fsa9480_show_device_type(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct fsa9480_usbsw *usbsw = dev_get_drvdata(dev);
+ struct i2c_client *client = usbsw->client;
+ int value;
+
+ value = i2c_smbus_read_byte_data(client, FSA9480_REG_DEV_T1);
+ if (value < 0)
+ dev_err(&client->dev, "%s: err %d\n", __func__, value);
+
+ return sprintf(buf, "DEVICE_TYPE: %02x\n", value);
+}
+
+static ssize_t fsa9480_show_manualsw(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fsa9480_usbsw *usbsw = dev_get_drvdata(dev);
+ struct i2c_client *client = usbsw->client;
+ unsigned int value;
+
+ value = i2c_smbus_read_byte_data(client, FSA9480_REG_MANSW1);
+ if (value < 0)
+ dev_err(&client->dev, "%s: err %d\n", __func__, value);
+
+ if (value == SW_VAUDIO)
+ return sprintf(buf, "VAUDIO\n");
+ else if (value == SW_UART)
+ return sprintf(buf, "UART\n");
+ else if (value == SW_AUDIO)
+ return sprintf(buf, "AUDIO\n");
+ else if (value == SW_DHOST)
+ return sprintf(buf, "DHOST\n");
+ else if (value == SW_AUTO)
+ return sprintf(buf, "AUTO\n");
+ else
+ return sprintf(buf, "%x", value);
+}
+
+static ssize_t fsa9480_set_manualsw(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fsa9480_usbsw *usbsw = dev_get_drvdata(dev);
+ struct i2c_client *client = usbsw->client;
+ unsigned int value;
+ unsigned int path = 0;
+ int ret;
+
+ value = i2c_smbus_read_byte_data(client, FSA9480_REG_CTRL);
+ if (value < 0)
+ dev_err(&client->dev, "%s: err %d\n", __func__, value);
+
+ if ((value & ~CON_MANUAL_SW) !=
+ (CON_SWITCH_OPEN | CON_RAW_DATA | CON_WAIT))
+ return 0;
+
+ if (!strncmp(buf, "VAUDIO", 6)) {
+ path = SW_VAUDIO;
+ value &= ~CON_MANUAL_SW;
+ } else if (!strncmp(buf, "UART", 4)) {
+ path = SW_UART;
+ value &= ~CON_MANUAL_SW;
+ } else if (!strncmp(buf, "AUDIO", 5)) {
+ path = SW_AUDIO;
+ value &= ~CON_MANUAL_SW;
+ } else if (!strncmp(buf, "DHOST", 5)) {
+ path = SW_DHOST;
+ value &= ~CON_MANUAL_SW;
+ } else if (!strncmp(buf, "AUTO", 4)) {
+ path = SW_AUTO;
+ value |= CON_MANUAL_SW;
+ } else {
+ dev_err(dev, "Wrong command\n");
+ return 0;
+ }
+
+ usbsw->mansw = path;
+
+ ret = i2c_smbus_write_byte_data(client, FSA9480_REG_MANSW1, path);
+ if (ret < 0)
+ dev_err(&client->dev, "%s: err %d\n", __func__, ret);
+
+ ret = i2c_smbus_write_byte_data(client, FSA9480_REG_CTRL, value);
+ if (ret < 0)
+ dev_err(&client->dev, "%s: err %d\n", __func__, ret);
+
+ return count;
+}
+
+static DEVICE_ATTR(control, S_IRUGO, fsa9480_show_control, NULL);
+static DEVICE_ATTR(device_type, S_IRUGO, fsa9480_show_device_type, NULL);
+static DEVICE_ATTR(switch, S_IRUGO | S_IWUSR,
+ fsa9480_show_manualsw, fsa9480_set_manualsw);
+
+static struct attribute *fsa9480_attributes[] = {
+ &dev_attr_control.attr,
+ &dev_attr_device_type.attr,
+ &dev_attr_switch.attr,
+ NULL
+};
+
+static const struct attribute_group fsa9480_group = {
+ .attrs = fsa9480_attributes,
+};
+
+
+static void fsa9480_detect_dev(struct fsa9480_usbsw *usbsw)
+{
+ int device_type, ret;
+ unsigned char val1, val2;
+ struct fsa9480_platform_data *pdata = usbsw->pdata;
+ struct i2c_client *client = usbsw->client;
+
+ device_type = i2c_smbus_read_word_data(client, FSA9480_REG_DEV_T1);
+ if (device_type < 0)
+ dev_err(&client->dev, "%s: err %d\n", __func__, device_type);
+
+ val1 = device_type & 0xff;
+ val2 = device_type >> 8;
+
+ dev_info(&client->dev, "dev1: 0x%x, dev2: 0x%x\n", val1, val2);
+
+ /* Attached */
+ if (val1 || val2) {
+ /* USB */
+ if (val1 & DEV_T1_USB_MASK || val2 & DEV_T2_USB_MASK) {
+ if (pdata->usb_cb)
+ pdata->usb_cb(FSA9480_ATTACHED);
+ if (usbsw->mansw) {
+ ret = i2c_smbus_write_byte_data(client,
+ FSA9480_REG_MANSW1, usbsw->mansw);
+ if (ret < 0)
+ dev_err(&client->dev,
+ "%s: err %d\n", __func__, ret);
+ }
+#if defined CONFIG_USB_S3C_OTG_HOST || defined CONFIG_USB_DWC_OTG
+// sztupy: handle automatic otg switching
+ if (val1 & DEV_USB_OTG) {
+ // otg cable detected
+ set_otghost_mode(2);
+ } else {
+ // client cable detected
+ set_otghost_mode(1);
+ }
+#endif
+ /* UART */
+ } else if (val1 & DEV_T1_UART_MASK || val2 & DEV_T2_UART_MASK) {
+ if (pdata->uart_cb)
+ pdata->uart_cb(FSA9480_ATTACHED);
+
+ if (usbsw->mansw) {
+ ret = i2c_smbus_write_byte_data(client,
+ FSA9480_REG_MANSW1, SW_UART);
+ if (ret < 0)
+ dev_err(&client->dev,
+ "%s: err %d\n", __func__, ret);
+ }
+ /* CHARGER */
+ } else if (val1 & DEV_T1_CHARGER_MASK) {
+ if (pdata->charger_cb)
+ pdata->charger_cb(FSA9480_ATTACHED);
+ /* JIG */
+ } else if (val2 & DEV_T2_JIG_MASK) {
+ if (pdata->jig_cb)
+ pdata->jig_cb(FSA9480_ATTACHED);
+ /* Desk Dock */
+ } else if (val2 & DEV_AV) {
+ if (pdata->deskdock_cb)
+ pdata->deskdock_cb(FSA9480_ATTACHED);
+
+ ret = i2c_smbus_write_byte_data(client,
+ FSA9480_REG_MANSW1, SW_DHOST);
+ if (ret < 0)
+ dev_err(&client->dev,
+ "%s: err %d\n", __func__, ret);
+
+ ret = i2c_smbus_read_byte_data(client,
+ FSA9480_REG_CTRL);
+ if (ret < 0)
+ dev_err(&client->dev,
+ "%s: err %d\n", __func__, ret);
+
+ ret = i2c_smbus_write_byte_data(client,
+ FSA9480_REG_CTRL, ret & ~CON_MANUAL_SW);
+ if (ret < 0)
+ dev_err(&client->dev,
+ "%s: err %d\n", __func__, ret);
+ /* Car Dock */
+ } else if (val2 & DEV_JIG_UART_ON) {
+ if (pdata->cardock_cb)
+ pdata->cardock_cb(FSA9480_ATTACHED);
+ }
+ /* Detached */
+ } else {
+ /* USB */
+ if (usbsw->dev1 & DEV_T1_USB_MASK ||
+ usbsw->dev2 & DEV_T2_USB_MASK) {
+ if (pdata->usb_cb)
+ pdata->usb_cb(FSA9480_DETACHED);
+#if defined CONFIG_USB_S3C_OTG_HOST || defined CONFIG_USB_DWC_OTG
+ // sztupy: also switch off otg host mode
+ set_otghost_mode(0);
+#endif
+ /* UART */
+ } else if (usbsw->dev1 & DEV_T1_UART_MASK ||
+ usbsw->dev2 & DEV_T2_UART_MASK) {
+ if (pdata->uart_cb)
+ pdata->uart_cb(FSA9480_DETACHED);
+ /* CHARGER */
+ } else if (usbsw->dev1 & DEV_T1_CHARGER_MASK) {
+ if (pdata->charger_cb)
+ pdata->charger_cb(FSA9480_DETACHED);
+ /* JIG */
+ } else if (usbsw->dev2 & DEV_T2_JIG_MASK) {
+ if (pdata->jig_cb)
+ pdata->jig_cb(FSA9480_DETACHED);
+ /* Desk Dock */
+ } else if (usbsw->dev2 & DEV_AV) {
+ if (pdata->deskdock_cb)
+ pdata->deskdock_cb(FSA9480_DETACHED);
+
+ ret = i2c_smbus_read_byte_data(client,
+ FSA9480_REG_CTRL);
+ if (ret < 0)
+ dev_err(&client->dev,
+ "%s: err %d\n", __func__, ret);
+
+ ret = i2c_smbus_write_byte_data(client,
+ FSA9480_REG_CTRL, ret | CON_MANUAL_SW);
+ if (ret < 0)
+ dev_err(&client->dev,
+ "%s: err %d\n", __func__, ret);
+ /* Car Dock */
+ } else if (usbsw->dev2 & DEV_JIG_UART_ON) {
+ if (pdata->cardock_cb)
+ pdata->cardock_cb(FSA9480_DETACHED);
+ }
+ }
+
+ usbsw->dev1 = val1;
+ usbsw->dev2 = val2;
+}
+
+static void fsa9480_reg_init(struct fsa9480_usbsw *usbsw)
+{
+ struct i2c_client *client = usbsw->client;
+ unsigned int ctrl = CON_MASK;
+ int ret;
+
+ /* mask interrupts (unmask attach/detach only) */
+ ret = i2c_smbus_write_word_data(client, FSA9480_REG_INT1_MASK, 0x1ffc);
+ if (ret < 0)
+ dev_err(&client->dev, "%s: err %d\n", __func__, ret);
+
+ /* mask all car kit interrupts */
+ ret = i2c_smbus_write_word_data(client, FSA9480_REG_CK_INTMASK1, 0x07ff);
+ if (ret < 0)
+ dev_err(&client->dev, "%s: err %d\n", __func__, ret);
+
+ /* ADC Detect Time: 500ms */
+ ret = i2c_smbus_write_byte_data(client, FSA9480_REG_TIMING1, 0x6);
+ if (ret < 0)
+ dev_err(&client->dev, "%s: err %d\n", __func__, ret);
+
+ usbsw->mansw = i2c_smbus_read_byte_data(client, FSA9480_REG_MANSW1);
+ if (usbsw->mansw < 0)
+ dev_err(&client->dev, "%s: err %d\n", __func__, usbsw->mansw);
+
+ if (usbsw->mansw)
+ ctrl &= ~CON_MANUAL_SW; /* Manual Switching Mode */
+
+ ret = i2c_smbus_write_byte_data(client, FSA9480_REG_CTRL, ctrl);
+ if (ret < 0)
+ dev_err(&client->dev, "%s: err %d\n", __func__, ret);
+}
+
+static irqreturn_t fsa9480_irq_thread(int irq, void *data)
+{
+ struct fsa9480_usbsw *usbsw = data;
+ struct i2c_client *client = usbsw->client;
+ int intr;
+ int max_events = 100;
+ int events_seen = 0;
+
+ /*
+ * the fsa could have queued up a few events if we haven't processed
+ * them promptly
+ */
+ while (max_events-- > 0) {
+ intr = i2c_smbus_read_word_data(client, FSA9480_REG_INT1);
+ if (intr < 0)
+ dev_err(&client->dev, "%s: err %d\n", __func__, intr);
+ else if (intr == 0)
+ break;
+ else if (intr > 0)
+ events_seen++;
+ }
+ if (!max_events)
+ dev_warn(&client->dev, "too many events. fsa hosed?\n");
+
+ if (!events_seen) {
+ /*
+ * interrupt was fired, but no status bits were set,
+ * so device was reset. In this case, the registers were
+ * reset to defaults so they need to be reinitialised.
+ */
+ fsa9480_reg_init(usbsw);
+ }
+
+ /*
+ * fsa may take some time to update the dev_type reg after reading
+ * the int reg.
+ */
+ usleep_range(200, 300);
+
+ /* device detection */
+ fsa9480_detect_dev(usbsw);
+
+ return IRQ_HANDLED;
+}
+
+static int fsa9480_irq_init(struct fsa9480_usbsw *usbsw)
+{
+ struct i2c_client *client = usbsw->client;
+ int ret;
+
+ if (client->irq) {
+ ret = request_threaded_irq(client->irq, NULL,
+ fsa9480_irq_thread, IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ "fsa9480 micro USB", usbsw);
+ if (ret) {
+ dev_err(&client->dev, "failed to reqeust IRQ\n");
+ return ret;
+ }
+
+ ret = enable_irq_wake(client->irq);
+ if (ret < 0)
+ dev_err(&client->dev,
+ "failed to enable wakeup src %d\n", ret);
+ }
+
+ return 0;
+}
+
+static int __devinit fsa9480_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+ struct fsa9480_usbsw *usbsw;
+ int ret = 0;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return -EIO;
+
+ usbsw = kzalloc(sizeof(struct fsa9480_usbsw), GFP_KERNEL);
+ if (!usbsw) {
+ dev_err(&client->dev, "failed to allocate driver data\n");
+ return -ENOMEM;
+ }
+
+ usbsw->client = client;
+ usbsw->pdata = client->dev.platform_data;
+ if (!usbsw->pdata)
+ goto fail1;
+
+ i2c_set_clientdata(client, usbsw);
+
+ if (usbsw->pdata->cfg_gpio)
+ usbsw->pdata->cfg_gpio();
+
+ fsa9480_reg_init(usbsw);
+
+ ret = fsa9480_irq_init(usbsw);
+ if (ret)
+ goto fail1;
+
+ ret = sysfs_create_group(&client->dev.kobj, &fsa9480_group);
+ if (ret) {
+ dev_err(&client->dev,
+ "failed to create fsa9480 attribute group\n");
+ goto fail2;
+ }
+
+ if (usbsw->pdata->reset_cb)
+ usbsw->pdata->reset_cb();
+
+ /* device detection */
+ fsa9480_detect_dev(usbsw);
+
+ return 0;
+
+fail2:
+ if (client->irq)
+ free_irq(client->irq, usbsw);
+fail1:
+ i2c_set_clientdata(client, NULL);
+ kfree(usbsw);
+ return ret;
+}
+
+static int __devexit fsa9480_remove(struct i2c_client *client)
+{
+ struct fsa9480_usbsw *usbsw = i2c_get_clientdata(client);
+
+ if (client->irq) {
+ disable_irq_wake(client->irq);
+ free_irq(client->irq, usbsw);
+ }
+ i2c_set_clientdata(client, NULL);
+
+ sysfs_remove_group(&client->dev.kobj, &fsa9480_group);
+ kfree(usbsw);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int fsa9480_resume(struct i2c_client *client)
+{
+ struct fsa9480_usbsw *usbsw = i2c_get_clientdata(client);
+
+ if (client->irq)
+ enable_irq(client->irq);
+ /* device detection */
+ fsa9480_detect_dev(usbsw);
+
+ return 0;
+}
+
+static int fsa9480_suspend(struct i2c_client *client, pm_message_t state)
+{
+ if (client->irq)
+ disable_irq(client->irq);
+
+ return 0;
+}
+
+#else
+
+#define fsa9480_suspend NULL
+#define fsa9480_resume NULL
+
+#endif /* CONFIG_PM */
+
+static const struct i2c_device_id fsa9480_id[] = {
+ {"fsa9480", 0},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, fsa9480_id);
+
+static struct i2c_driver fsa9480_i2c_driver = {
+ .driver = {
+ .name = "fsa9480",
+ },
+ .probe = fsa9480_probe,
+ .remove = __devexit_p(fsa9480_remove),
+ .resume = fsa9480_resume,
+ .suspend = fsa9480_suspend,
+ .id_table = fsa9480_id,
+};
+
+static int __init fsa9480_init(void)
+{
+ return i2c_add_driver(&fsa9480_i2c_driver);
+}
+module_init(fsa9480_init);
+
+static void __exit fsa9480_exit(void)
+{
+ i2c_del_driver(&fsa9480_i2c_driver);
+}
+module_exit(fsa9480_exit);
+
+MODULE_AUTHOR("Minkyu Kang <mk7.kang@samsung.com>");
+MODULE_DESCRIPTION("FSA9480 USB Switch driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/kr3dm.c b/drivers/misc/kr3dm.c
new file mode 100644
index 0000000..09bc945
--- /dev/null
+++ b/drivers/misc/kr3dm.c
@@ -0,0 +1,508 @@
+/*
+ * STMicroelectronics kr3dm acceleration sensor driver
+ *
+ * Copyright (C) 2010 Samsung Electronics Co.Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/kr3dm.h>
+#include <linux/delay.h>
+#include <linux/completion.h>
+#include "kr3dm_reg.h"
+
+#define kr3dm_dbgmsg(str, args...) pr_debug("%s: " str, __func__, ##args)
+
+/* The default settings when sensor is on is for all 3 axis to be enabled
+ * and output data rate set to 400Hz. Output is via a ioctl read call.
+ * The ioctl blocks on data_ready completion.
+ * The sensor generates an interrupt when the output is ready and the
+ * irq handler atomically sets the completion and wakes any
+ * blocked reader.
+ */
+#define DEFAULT_POWER_ON_SETTING (ODR400 | ENABLE_ALL_AXES)
+#define READ_REPEAT_SHIFT 3
+#define READ_REPEAT (1 << READ_REPEAT_SHIFT)
+
+static const struct odr_delay {
+ u8 odr; /* odr reg setting */
+ s64 delay_ns; /* odr in ns */
+} odr_delay_table[] = {
+ { ODR400, 2500000LL << READ_REPEAT_SHIFT }, /* 400Hz */
+ { ODR100, 10000000LL << READ_REPEAT_SHIFT }, /* 100Hz */
+ { ODR50, 20000000LL << READ_REPEAT_SHIFT }, /* 50Hz */
+ { ODR10, 100000000LL << READ_REPEAT_SHIFT }, /* 10Hz */
+ { ODR5, 200000000LL << READ_REPEAT_SHIFT }, /* 5Hz */
+ { ODR2, 500000000LL << READ_REPEAT_SHIFT }, /* 2Hz */
+ { ODR1, 1000000000LL << READ_REPEAT_SHIFT }, /* 1Hz */
+ { ODRHALF, 2000000000LL << READ_REPEAT_SHIFT }, /* 0.5Hz */
+};
+
+/* KR3DM acceleration data */
+struct kr3dm_acc {
+ s8 x;
+ s8 y;
+ s8 z;
+};
+
+struct kr3dm_data {
+ struct i2c_client *client;
+ struct miscdevice kr3dm_device;
+ struct kr3dm_platform_data *pdata;
+ int irq;
+ u8 ctrl_reg1_shadow;
+ struct completion data_ready;
+ atomic_t opened; /* opened implies enabled */
+ struct mutex read_lock;
+ struct mutex write_lock;
+};
+
+static void kr3dm_disable_irq(struct kr3dm_data *kr3dm)
+{
+ disable_irq(kr3dm->irq);
+ if (try_wait_for_completion(&kr3dm->data_ready)) {
+ /* we actually got the interrupt before we could disable it
+ * so we need to enable again to undo our disable and the
+ * one done in the irq_handler
+ */
+ enable_irq(kr3dm->irq);
+ }
+}
+
+static irqreturn_t kr3dm_irq_handler(int irq, void *data)
+{
+ struct kr3dm_data *kr3dm = data;
+ disable_irq_nosync(irq);
+ complete(&kr3dm->data_ready);
+ return IRQ_HANDLED;
+}
+
+static int kr3dm_wait_for_data_ready(struct kr3dm_data *kr3dm)
+{
+ int err;
+
+ if (gpio_get_value(kr3dm->pdata->gpio_acc_int))
+ return 0;
+
+ enable_irq(kr3dm->irq);
+
+ err = wait_for_completion_timeout(&kr3dm->data_ready, 5*HZ);
+ if (err > 0)
+ return 0;
+
+ kr3dm_disable_irq(kr3dm);
+
+ if (err == 0) {
+ pr_err("kr3dm: wait timed out\n");
+ return -ETIMEDOUT;
+ }
+
+ pr_err("kr3dm: wait restart\n");
+ return err;
+}
+
+/* Read X,Y and Z-axis acceleration data. Blocks until there is
+ * something to read, based on interrupt from chip.
+ */
+static int kr3dm_read_accel_xyz(struct kr3dm_data *kr3dm,
+ struct kr3dm_acc *acc)
+{
+ int err;
+ s8 reg = OUT_X | AC; /* read from OUT_X to OUT_Z by auto-inc */
+ s8 acc_data[5];
+
+ err = kr3dm_wait_for_data_ready(kr3dm);
+ if (err)
+ return err;
+
+ /* OUT_X, OUT_Y, and OUT_Z are single byte registers at
+ * address 0x29, 0x2B, and 0x2D respectively, with 1 dummy
+ * register in between. Rather than doing 3 separate i2c reads,
+ * we do one multi-byte read and just use the bytes we want.
+ */
+ err = i2c_smbus_read_i2c_block_data(kr3dm->client, reg,
+ sizeof(acc_data), acc_data);
+ if (err != sizeof(acc_data)) {
+ pr_err("%s : failed to read 5 bytes for getting x/y/z\n",
+ __func__);
+ return -EIO;
+ }
+
+ if (kr3dm->pdata->rotation) {
+ acc->x = acc_data[0] * kr3dm->pdata->rotation[0] +
+ acc_data[2] * kr3dm->pdata->rotation[1] +
+ acc_data[4] * kr3dm->pdata->rotation[2];
+ acc->y = acc_data[0] * kr3dm->pdata->rotation[3] +
+ acc_data[2] * kr3dm->pdata->rotation[4] +
+ acc_data[4] * kr3dm->pdata->rotation[5];
+ acc->z = acc_data[0] * kr3dm->pdata->rotation[6] +
+ acc_data[2] * kr3dm->pdata->rotation[7] +
+ acc_data[4] * kr3dm->pdata->rotation[8];
+ } else {
+ acc->x = acc_data[0];
+ acc->y = acc_data[2];
+ acc->z = acc_data[4];
+ }
+
+ return 0;
+}
+
+/* open command for KR3DM device file */
+static int kr3dm_open(struct inode *inode, struct file *file)
+{
+ int err = 0;
+ struct kr3dm_data *kr3dm = container_of(file->private_data,
+ struct kr3dm_data,
+ kr3dm_device);
+
+ if (atomic_xchg(&kr3dm->opened, 1)) {
+ pr_err("kr3dm_open() called when already open\n");
+ return -EBUSY;
+ } else {
+ file->private_data = kr3dm;
+ kr3dm->ctrl_reg1_shadow = DEFAULT_POWER_ON_SETTING;
+ err = i2c_smbus_write_byte_data(kr3dm->client, CTRL_REG1,
+ DEFAULT_POWER_ON_SETTING);
+ if (err) {
+ pr_err("kr3dm_open() i2c write ctrl_reg1 failed\n");
+ atomic_set(&kr3dm->opened, 0);
+ }
+ }
+
+ return err;
+}
+
+/* release command for KR3DM device file */
+static int kr3dm_close(struct inode *inode, struct file *file)
+{
+ int err;
+ struct kr3dm_data *kr3dm = file->private_data;
+
+ err = i2c_smbus_write_byte_data(kr3dm->client, CTRL_REG1, PM_OFF);
+ atomic_set(&kr3dm->opened, 0);
+ kr3dm->ctrl_reg1_shadow = PM_OFF;
+
+ return err;
+}
+
+static s64 kr3dm_get_delay(struct kr3dm_data *kr3dm)
+{
+ int i;
+ u8 odr;
+ s64 delay = -1;
+
+ odr = kr3dm->ctrl_reg1_shadow & ODR_MASK;
+ for (i = 0; i < ARRAY_SIZE(odr_delay_table); i++) {
+ if (odr == odr_delay_table[i].odr) {
+ delay = odr_delay_table[i].delay_ns;
+ break;
+ }
+ }
+ return delay;
+}
+
+static int kr3dm_set_delay(struct kr3dm_data *kr3dm, s64 delay_ns)
+{
+ int odr_value = ODRHALF;
+ int res = 0;
+ int i;
+ /* round to the nearest delay that is less than
+ * the requested value (next highest freq)
+ */
+ kr3dm_dbgmsg(" passed %lldns\n", delay_ns);
+ for (i = 0; i < ARRAY_SIZE(odr_delay_table); i++) {
+ if (delay_ns < odr_delay_table[i].delay_ns)
+ break;
+ }
+ if (i > 0)
+ i--;
+ kr3dm_dbgmsg("matched rate %lldns, odr = 0x%x\n",
+ odr_delay_table[i].delay_ns,
+ odr_delay_table[i].odr);
+ odr_value = odr_delay_table[i].odr;
+ delay_ns = odr_delay_table[i].delay_ns;
+ mutex_lock(&kr3dm->write_lock);
+ kr3dm_dbgmsg("old = %lldns, new = %lldns\n",
+ kr3dm_get_delay(kr3dm), delay_ns);
+ if (odr_value != (kr3dm->ctrl_reg1_shadow & ODR_MASK)) {
+ u8 ctrl = (kr3dm->ctrl_reg1_shadow & ~ODR_MASK);
+ ctrl |= odr_value;
+ kr3dm->ctrl_reg1_shadow = ctrl;
+ res = i2c_smbus_write_byte_data(kr3dm->client, CTRL_REG1, ctrl);
+ kr3dm_dbgmsg("writing odr value 0x%x\n", odr_value);
+ }
+ mutex_unlock(&kr3dm->write_lock);
+ return res;
+}
+
+/* ioctl command for KR3DM device file */
+static long kr3dm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ int err = 0;
+ struct kr3dm_data *kr3dm = file->private_data;
+ s64 delay_ns;
+ struct kr3dm_acc data;
+ int i;
+ struct kr3dm_acceldata sum = { 0, };
+
+ /* cmd mapping */
+ switch (cmd) {
+ case KR3DM_IOCTL_SET_DELAY:
+ if (copy_from_user(&delay_ns, (void __user *)arg,
+ sizeof(delay_ns)))
+ return -EFAULT;
+ err = kr3dm_set_delay(kr3dm, delay_ns);
+ break;
+ case KR3DM_IOCTL_GET_DELAY:
+ delay_ns = kr3dm_get_delay(kr3dm);
+ if (put_user(delay_ns, (s64 __user *)arg))
+ return -EFAULT;
+ break;
+ case KR3DM_IOCTL_READ_ACCEL_XYZ:
+ mutex_lock(&kr3dm->read_lock);
+ for (i = 0; i < READ_REPEAT; i++) {
+ err = kr3dm_read_accel_xyz(kr3dm, &data);
+ if (err)
+ break;
+ sum.x += data.x;
+ sum.y += data.y;
+ sum.z += data.z;
+ }
+ mutex_unlock(&kr3dm->read_lock);
+ if (err)
+ return err;
+ if (copy_to_user((void __user *)arg, &sum, sizeof(sum)))
+ return -EFAULT;
+ break;
+ default:
+ err = -EINVAL;
+ break;
+ }
+
+ return err;
+}
+
+static int kr3dm_suspend(struct device *dev)
+{
+ int res = 0;
+ struct kr3dm_data *kr3dm = dev_get_drvdata(dev);
+
+ if (atomic_read(&kr3dm->opened))
+ res = i2c_smbus_write_byte_data(kr3dm->client,
+ CTRL_REG1, PM_OFF);
+
+ return res;
+}
+
+static int kr3dm_resume(struct device *dev)
+{
+ int res = 0;
+ struct kr3dm_data *kr3dm = dev_get_drvdata(dev);
+
+ if (atomic_read(&kr3dm->opened))
+ res = i2c_smbus_write_byte_data(kr3dm->client, CTRL_REG1,
+ kr3dm->ctrl_reg1_shadow);
+
+ return res;
+}
+
+
+static const struct dev_pm_ops kr3dm_pm_ops = {
+ .suspend = kr3dm_suspend,
+ .resume = kr3dm_resume,
+};
+
+static const struct file_operations kr3dm_fops = {
+ .owner = THIS_MODULE,
+ .open = kr3dm_open,
+ .release = kr3dm_close,
+ .unlocked_ioctl = kr3dm_ioctl,
+};
+
+static int kr3dm_setup_irq(struct kr3dm_data *kr3dm)
+{
+ int rc = -EIO;
+ struct kr3dm_platform_data *pdata = kr3dm->pdata;
+ int irq;
+
+ rc = gpio_request(pdata->gpio_acc_int, "gpio_acc_int");
+ if (rc < 0) {
+ pr_err("%s: gpio %d request failed (%d)\n",
+ __func__, pdata->gpio_acc_int, rc);
+ return rc;
+ }
+
+ rc = gpio_direction_input(pdata->gpio_acc_int);
+ if (rc < 0) {
+ pr_err("%s: failed to set gpio %d as input (%d)\n",
+ __func__, pdata->gpio_acc_int, rc);
+ goto err_gpio_direction_input;
+ }
+
+ /* configure INT1 to deliver data ready interrupt */
+ rc = i2c_smbus_write_byte_data(kr3dm->client, CTRL_REG3, I1_CFG_DR);
+ if (rc) {
+ pr_err("%s: CTRL_REG3 write failed with error %d\n",
+ __func__, rc);
+ goto err_i2c_write_failed;
+ }
+
+ irq = gpio_to_irq(pdata->gpio_acc_int);
+
+ /* trigger high so we don't miss initial interrupt if it
+ * is already pending
+ */
+ rc = request_irq(irq, kr3dm_irq_handler, IRQF_TRIGGER_HIGH,
+ "acc_int", kr3dm);
+ if (rc < 0) {
+ pr_err("%s: request_irq(%d) failed for gpio %d (%d)\n",
+ __func__, irq,
+ pdata->gpio_acc_int, rc);
+ goto err_request_irq;
+ }
+
+ /* start with interrupt disabled until the driver is enabled */
+ kr3dm->irq = irq;
+ kr3dm_disable_irq(kr3dm);
+
+ goto done;
+
+err_request_irq:
+err_i2c_write_failed:
+err_gpio_direction_input:
+ gpio_free(pdata->gpio_acc_int);
+done:
+ return rc;
+}
+
+static int kr3dm_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct kr3dm_data *kr3dm;
+ int err;
+ struct kr3dm_platform_data *pdata = client->dev.platform_data;
+
+ if (!pdata) {
+ pr_err("%s: missing pdata!\n", __func__);
+ return -ENODEV;
+ }
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_WRITE_BYTE_DATA |
+ I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
+ pr_err("%s: i2c functionality check failed!\n", __func__);
+ err = -ENODEV;
+ goto exit;
+ }
+
+ kr3dm = kzalloc(sizeof(struct kr3dm_data), GFP_KERNEL);
+ if (kr3dm == NULL) {
+ dev_err(&client->dev,
+ "failed to allocate memory for module data\n");
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ kr3dm->client = client;
+ kr3dm->pdata = pdata;
+ i2c_set_clientdata(client, kr3dm);
+
+ init_completion(&kr3dm->data_ready);
+ mutex_init(&kr3dm->read_lock);
+ mutex_init(&kr3dm->write_lock);
+ atomic_set(&kr3dm->opened, 0);
+
+ err = kr3dm_setup_irq(kr3dm);
+ if (err) {
+ pr_err("%s: could not setup irq\n", __func__);
+ goto err_setup_irq;
+ }
+
+ /* sensor HAL expects to find /dev/accelerometer */
+ kr3dm->kr3dm_device.minor = MISC_DYNAMIC_MINOR;
+ kr3dm->kr3dm_device.name = "accelerometer";
+ kr3dm->kr3dm_device.fops = &kr3dm_fops;
+
+ err = misc_register(&kr3dm->kr3dm_device);
+ if (err) {
+ pr_err("%s: misc_register failed\n", __FILE__);
+ goto err_misc_register;
+ }
+
+ return 0;
+
+err_misc_register:
+ free_irq(kr3dm->irq, kr3dm);
+ gpio_free(kr3dm->pdata->gpio_acc_int);
+err_setup_irq:
+ mutex_destroy(&kr3dm->read_lock);
+ mutex_destroy(&kr3dm->write_lock);
+ kfree(kr3dm);
+exit:
+ return err;
+}
+
+static int kr3dm_remove(struct i2c_client *client)
+{
+ struct kr3dm_data *kr3dm = i2c_get_clientdata(client);
+
+ misc_deregister(&kr3dm->kr3dm_device);
+ free_irq(kr3dm->irq, kr3dm);
+ gpio_free(kr3dm->pdata->gpio_acc_int);
+ mutex_destroy(&kr3dm->read_lock);
+ mutex_destroy(&kr3dm->write_lock);
+ kfree(kr3dm);
+
+ return 0;
+}
+
+static const struct i2c_device_id kr3dm_id[] = {
+ { "kr3dm", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, kr3dm_id);
+
+static struct i2c_driver kr3dm_driver = {
+ .probe = kr3dm_probe,
+ .remove = __devexit_p(kr3dm_remove),
+ .id_table = kr3dm_id,
+ .driver = {
+ .pm = &kr3dm_pm_ops,
+ .owner = THIS_MODULE,
+ .name = "kr3dm",
+ },
+};
+
+static int __init kr3dm_init(void)
+{
+ return i2c_add_driver(&kr3dm_driver);
+}
+
+static void __exit kr3dm_exit(void)
+{
+ i2c_del_driver(&kr3dm_driver);
+}
+
+module_init(kr3dm_init);
+module_exit(kr3dm_exit);
+
+MODULE_DESCRIPTION("kr3dm accelerometer driver");
+MODULE_AUTHOR("Tim SK Lee Samsung Electronics <tim.sk.lee@samsung.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/kr3dm_reg.h b/drivers/misc/kr3dm_reg.h
new file mode 100644
index 0000000..8c57a38
--- /dev/null
+++ b/drivers/misc/kr3dm_reg.h
@@ -0,0 +1,169 @@
+/*
+ * STMicroelectronics kr3dm acceleration sensor driver
+ *
+ * Copyright (C) 2010 Samsung Electronics Co.Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ */
+
+
+/* kr3dm i2c slave address & etc */
+#define KR3DM_I2C_ADDR 0x09
+/* kr3dm registers */
+#define WHO_AM_I 0x0F
+#define CTRL_REG1 0x20 /* power control reg */
+#define CTRL_REG2 0x21 /* power control reg */
+#define CTRL_REG3 0x22 /* power control reg */
+#define CTRL_REG4 0x23 /* interrupt control reg */
+#define CTRL_REG5 0x24 /* interrupt control reg */
+#define STATUS_REG 0x27
+#define AXISDATA_REG 0x28
+#define OUT_X 0x29
+#define OUT_Y 0x2B
+#define OUT_Z 0x2D
+#define INT1_CFG 0x30
+#define INT1_SOURCE 0x31
+#define INT1_THS 0x32
+#define INT1_DURATION 0x33
+#define INT2_CFG 0x34
+#define INT2_SOURCE 0x35
+#define INT2_THS 0x36
+#define INT2_DURATION 0x37
+
+#define KR3DM_G_2G 0x00
+#define KR3DM_G_4G 0x10
+#define KR3DM_G_8G 0x30
+
+/* CTRL_REG1 */
+/* ctrl 1: pm2 pm1 pm0 dr1 dr0 x-enable y-enable z-enable */
+#define PM_OFF 0x00
+#define ENABLE_ALL_AXES 0x07
+
+#define ODRHALF 0x40 /* 0.5Hz output data rate */
+#define ODR1 0x60 /* 1Hz output data rate */
+#define ODR2 0x80 /* 2Hz output data rate */
+#define ODR5 0xA0 /* 5Hz output data rate */
+#define ODR10 0xC0 /* 10Hz output data rate */
+#define ODR50 0x20 /* 50Hz output data rate */
+#define ODR100 0x28 /* 100Hz output data rate */
+#define ODR400 0x30 /* 400Hz output data rate */
+
+#define ODR_MASK 0xf8
+
+#define CTRL_REG1_PM2 (1 << 7)
+#define CTRL_REG1_PM1 (1 << 6)
+#define CTRL_REG1_PM0 (1 << 5)
+#define CTRL_REG1_DR1 (1 << 4)
+#define CTRL_REG1_DR0 (1 << 3)
+#define CTRL_REG1_Zen (1 << 2)
+#define CTRL_REG1_Yen (1 << 1)
+#define CTRL_REG1_Xen (1 << 0)
+
+#define PM_down 0x00
+#define PM_Normal (CTRL_REG1_PM0)
+#define PM_Low05 (CTRL_REG1_PM1)
+#define PM_Low1 (CTRL_REG1_PM1|CTRL_REG1_PM0)
+#define PM_Low2 (CTRL_REG1_PM2)
+#define PM_Low5 (CTRL_REG1_PM2|CTRL_REG1_PM0)
+#define PM_Low10 (CTRL_REG1_PM2|CTRL_REG1_PM1)
+
+/* CTRL_REG2 */
+#define CTRL_REG2_BOOT (1 << 7)
+#define CTRL_REG2_HPM1 (1 << 6)
+#define CTRL_REG2_HPM0 (1 << 5)
+#define CTRL_REG2_FDS (1 << 4)
+#define CTRL_REG2_HPen2 (1 << 3)
+#define CTRL_REG2_HPen1 (1 << 2)
+#define CTRL_REG2_HPCF1 (1 << 1)
+#define CTRL_REG2_HPCF0 (1 << 0)
+
+#define HPM_Normal (CTRL_REG2_HPM1)
+#define HPM_Filter (CTRL_REG2_HPM0)
+
+#define HPCF_ft8 0x00
+#define HPCF_ft4 (CTRL_REG2_HPCF0)
+#define HPCF_ft2 (CTRL_REG2_HPCF1)
+#define HPCF_ft1 (CTRL_REG2_HPCF1|CTRL_REG2_HPCF0)
+
+/* CTRL_REG3 */
+#define CTRL_REG3_IHL (1 << 7)
+#define CTRL_REG3_PP_OD (1 << 6)
+#define CTRL_REG3_LIR2 (1 << 5)
+#define CTRL_REG3_I2_CFG1 (1 << 4)
+#define ICTRL_REG3_2_CFG0 (1 << 3)
+#define CTRL_REG3_LIR1 (1 << 2)
+#define CTRL_REG3_I1_CFG1 (1 << 1)
+#define CTRL_REG3_I1_CFG0 (1 << 0)
+
+/* Interrupt 1 (2) source */
+#define I1_CFG_SC (0x00)
+/* Interrupt 1 source OR Interrupt 2 source */
+#define I1_CFG_OR (CTRL_REG3_I1_CFG0)
+/* Data Ready */
+#define I1_CFG_DR (CTRL_REG3_I1_CFG1)
+/* Boot running */
+#define I1_CFG_BR (CTRL_REG3_I1_CFG1|CTRL_REG3_I1_CFG0)
+
+ /* Interrupt 1 (2) source */
+#define I2_CFG_SC (0x00)
+/* Interrupt 1 source OR Interrupt 2 source */
+#define I2_CFG_OR (CTRL_REG3_I2_CFG0)
+/* Data Ready */
+#define I2_CFG_DR (CTRL_REG3_I2_CFG1)
+/* Boot running */
+#define I2_CFG_BR (CTRL_REG3_I2_CFG1|CTRL_REG3_I2_CFG0)
+
+/* CTRL_REG4 */
+#define CTRL_REG4_FS1 (1 << 5)
+#define CTRL_REG4_FS0 (1 << 4)
+#define CTRL_REG4_STsign (1 << 3)
+#define CTRL_REG4_ST (1 << 1)
+#define CTRL_REG4_SIM (1 << 0)
+
+#define FS2g 0x00
+#define FS4g (CTRL_REG4_FS0)
+#define FS8g (CTRL_REG4_FS1|CTRL_REG4_FS0)
+
+/* CTRL_REG5 */
+#define CTRL_REG5_TurnOn1 (1 << 1)
+#define CTRL_REG5_TurnOn0 (1 << 0)
+
+/* STATUS_REG */
+#define ZYXOR (1 << 7)
+#define ZOR (1 << 6)
+#define YOR (1 << 5)
+#define XOR (1 << 4)
+#define ZYXDA (1 << 3)
+#define ZDA (1 << 2)
+#define YDA (1 << 1)
+#define XDA (1 << 0)
+
+/* INT1/2_CFG */
+#define INT_CFG_AOI (1 << 7)
+#define INT_CFG_6D (1 << 6)
+#define INT_CFG_ZHIE (1 << 5)
+#define INT_CFG_ZLIE (1 << 4)
+#define INT_CFG_YHIE (1 << 3)
+#define INT_CFG_YLIE (1 << 2)
+#define INT_CFG_XHIE (1 << 1)
+#define INT_CFG_XLIE (1 << 0)
+
+/* INT1/2_SRC */
+#define IA (1 << 6)
+#define ZH (1 << 5)
+#define ZL (1 << 4)
+#define YH (1 << 3)
+#define YL (1 << 2)
+#define XH (1 << 1)
+#define XL (1 << 0)
+
+/* Register Auto-increase */
+#define AC (1 << 7)
diff --git a/drivers/misc/pn544.c b/drivers/misc/pn544.c
new file mode 100755
index 0000000..b726036
--- /dev/null
+++ b/drivers/misc/pn544.c
@@ -0,0 +1,364 @@
+/*
+ * Copyright (C) 2010 Trusted Logic S.A.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/jiffies.h>
+#include <linux/uaccess.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/miscdevice.h>
+#include <linux/spinlock.h>
+#include <linux/pn544.h>
+
+#define MAX_BUFFER_SIZE 512
+
+struct pn544_dev {
+ wait_queue_head_t read_wq;
+ struct mutex read_mutex;
+ struct i2c_client *client;
+ struct miscdevice pn544_device;
+ unsigned int ven_gpio;
+ unsigned int firm_gpio;
+ unsigned int irq_gpio;
+ bool irq_enabled;
+ spinlock_t irq_enabled_lock;
+};
+
+static void pn544_disable_irq(struct pn544_dev *pn544_dev)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&pn544_dev->irq_enabled_lock, flags);
+ if (pn544_dev->irq_enabled) {
+ disable_irq_nosync(pn544_dev->client->irq);
+ pn544_dev->irq_enabled = false;
+ }
+ spin_unlock_irqrestore(&pn544_dev->irq_enabled_lock, flags);
+}
+
+static irqreturn_t pn544_dev_irq_handler(int irq, void *dev_id)
+{
+ struct pn544_dev *pn544_dev = dev_id;
+
+ pn544_disable_irq(pn544_dev);
+
+ /* Wake up waiting readers */
+ wake_up(&pn544_dev->read_wq);
+
+ return IRQ_HANDLED;
+}
+
+static ssize_t pn544_dev_read(struct file *filp, char __user *buf,
+ size_t count, loff_t *offset)
+{
+ struct pn544_dev *pn544_dev = filp->private_data;
+ char tmp[MAX_BUFFER_SIZE];
+ int ret;
+
+ if (count > MAX_BUFFER_SIZE)
+ count = MAX_BUFFER_SIZE;
+
+ pr_debug("%s : reading %zu bytes.\n", __func__, count);
+
+ mutex_lock(&pn544_dev->read_mutex);
+
+ if (!gpio_get_value(pn544_dev->irq_gpio)) {
+ if (filp->f_flags & O_NONBLOCK) {
+ ret = -EAGAIN;
+ goto fail;
+ }
+
+ pn544_dev->irq_enabled = true;
+ enable_irq(pn544_dev->client->irq);
+ ret = wait_event_interruptible(pn544_dev->read_wq,
+ gpio_get_value(pn544_dev->irq_gpio));
+
+ pn544_disable_irq(pn544_dev);
+
+ if (ret)
+ goto fail;
+
+ }
+
+ /* Read data */
+ ret = i2c_master_recv(pn544_dev->client, tmp, count);
+ mutex_unlock(&pn544_dev->read_mutex);
+
+ if (ret < 0) {
+ pr_err("%s: i2c_master_recv returned %d\n", __func__, ret);
+ return ret;
+ }
+ if (ret > count) {
+ pr_err("%s: received too many bytes from i2c (%d)\n",
+ __func__, ret);
+ return -EIO;
+ }
+ if (copy_to_user(buf, tmp, ret)) {
+ pr_warning("%s : failed to copy to user space\n", __func__);
+ return -EFAULT;
+ }
+ return ret;
+
+fail:
+ mutex_unlock(&pn544_dev->read_mutex);
+ return ret;
+}
+
+static ssize_t pn544_dev_write(struct file *filp, const char __user *buf,
+ size_t count, loff_t *offset)
+{
+ struct pn544_dev *pn544_dev;
+ char tmp[MAX_BUFFER_SIZE];
+ int ret;
+
+ pn544_dev = filp->private_data;
+
+ if (count > MAX_BUFFER_SIZE)
+ count = MAX_BUFFER_SIZE;
+
+ if (copy_from_user(tmp, buf, count)) {
+ pr_err("%s : failed to copy from user space\n", __func__);
+ return -EFAULT;
+ }
+
+ pr_debug("%s : writing %zu bytes.\n", __func__, count);
+ /* Write data */
+ ret = i2c_master_send(pn544_dev->client, tmp, count);
+ if (ret != count) {
+ pr_err("%s : i2c_master_send returned %d\n", __func__, ret);
+ ret = -EIO;
+ }
+
+ return ret;
+}
+
+static int pn544_dev_open(struct inode *inode, struct file *filp)
+{
+ struct pn544_dev *pn544_dev = container_of(filp->private_data,
+ struct pn544_dev,
+ pn544_device);
+
+ filp->private_data = pn544_dev;
+
+ pr_debug("%s : %d,%d\n", __func__, imajor(inode), iminor(inode));
+
+ return 0;
+}
+
+static long pn544_dev_ioctl(struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ struct pn544_dev *pn544_dev = filp->private_data;
+
+ switch (cmd) {
+ case PN544_SET_PWR:
+ if (arg == 2) {
+ /* power on with firmware download (requires hw reset)
+ */
+ pr_info("%s power on with firmware\n", __func__);
+ gpio_set_value(pn544_dev->ven_gpio, 1);
+ gpio_set_value(pn544_dev->firm_gpio, 1);
+ msleep(20);
+ gpio_set_value(pn544_dev->ven_gpio, 0);
+ msleep(60);
+ gpio_set_value(pn544_dev->ven_gpio, 1);
+ msleep(20);
+ } else if (arg == 1) {
+ /* power on */
+ pr_info("%s power on\n", __func__);
+ gpio_set_value(pn544_dev->firm_gpio, 0);
+ gpio_set_value(pn544_dev->ven_gpio, 1);
+ msleep(20);
+ } else if (arg == 0) {
+ /* power off */
+ pr_info("%s power off\n", __func__);
+ gpio_set_value(pn544_dev->firm_gpio, 0);
+ gpio_set_value(pn544_dev->ven_gpio, 0);
+ msleep(60);
+ } else {
+ pr_err("%s bad arg %lu\n", __func__, arg);
+ return -EINVAL;
+ }
+ break;
+ default:
+ pr_err("%s bad ioctl %u\n", __func__, cmd);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct file_operations pn544_dev_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .read = pn544_dev_read,
+ .write = pn544_dev_write,
+ .open = pn544_dev_open,
+ .unlocked_ioctl = pn544_dev_ioctl,
+};
+
+static int pn544_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int ret;
+ struct pn544_i2c_platform_data *platform_data;
+ struct pn544_dev *pn544_dev;
+
+ platform_data = client->dev.platform_data;
+
+ if (platform_data == NULL) {
+ pr_err("%s : nfc probe fail\n", __func__);
+ return -ENODEV;
+ }
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ pr_err("%s : need I2C_FUNC_I2C\n", __func__);
+ return -ENODEV;
+ }
+
+ ret = gpio_request(platform_data->irq_gpio, "nfc_int");
+ if (ret)
+ return -ENODEV;
+ ret = gpio_request(platform_data->ven_gpio, "nfc_ven");
+ if (ret)
+ goto err_ven;
+ ret = gpio_request(platform_data->firm_gpio, "nfc_firm");
+ if (ret)
+ goto err_firm;
+
+ pn544_dev = kzalloc(sizeof(*pn544_dev), GFP_KERNEL);
+ if (pn544_dev == NULL) {
+ dev_err(&client->dev,
+ "failed to allocate memory for module data\n");
+ ret = -ENOMEM;
+ goto err_exit;
+ }
+
+ pn544_dev->irq_gpio = platform_data->irq_gpio;
+ pn544_dev->ven_gpio = platform_data->ven_gpio;
+ pn544_dev->firm_gpio = platform_data->firm_gpio;
+ pn544_dev->client = client;
+
+ /* init mutex and queues */
+ init_waitqueue_head(&pn544_dev->read_wq);
+ mutex_init(&pn544_dev->read_mutex);
+ spin_lock_init(&pn544_dev->irq_enabled_lock);
+
+ pn544_dev->pn544_device.minor = MISC_DYNAMIC_MINOR;
+ pn544_dev->pn544_device.name = "pn544";
+ pn544_dev->pn544_device.fops = &pn544_dev_fops;
+
+ ret = misc_register(&pn544_dev->pn544_device);
+ if (ret) {
+ pr_err("%s : misc_register failed\n", __FILE__);
+ goto err_misc_register;
+ }
+
+ /* request irq. the irq is set whenever the chip has data available
+ * for reading. it is cleared when all data has been read.
+ */
+ pr_info("%s : requesting IRQ %d\n", __func__, client->irq);
+ pn544_dev->irq_enabled = true;
+ ret = request_irq(client->irq, pn544_dev_irq_handler,
+ IRQF_TRIGGER_HIGH, client->name, pn544_dev);
+ if (ret) {
+ dev_err(&client->dev, "request_irq failed\n");
+ goto err_request_irq_failed;
+ }
+ pn544_disable_irq(pn544_dev);
+ i2c_set_clientdata(client, pn544_dev);
+
+ return 0;
+
+err_request_irq_failed:
+ misc_deregister(&pn544_dev->pn544_device);
+err_misc_register:
+ mutex_destroy(&pn544_dev->read_mutex);
+ kfree(pn544_dev);
+err_exit:
+ gpio_free(platform_data->firm_gpio);
+err_firm:
+ gpio_free(platform_data->ven_gpio);
+err_ven:
+ gpio_free(platform_data->irq_gpio);
+ return ret;
+}
+
+static int pn544_remove(struct i2c_client *client)
+{
+ struct pn544_dev *pn544_dev;
+
+ pn544_dev = i2c_get_clientdata(client);
+ free_irq(client->irq, pn544_dev);
+ misc_deregister(&pn544_dev->pn544_device);
+ mutex_destroy(&pn544_dev->read_mutex);
+ gpio_free(pn544_dev->irq_gpio);
+ gpio_free(pn544_dev->ven_gpio);
+ gpio_free(pn544_dev->firm_gpio);
+ kfree(pn544_dev);
+
+ return 0;
+}
+
+static const struct i2c_device_id pn544_id[] = {
+ { "pn544", 0 },
+ { }
+};
+
+static struct i2c_driver pn544_driver = {
+ .id_table = pn544_id,
+ .probe = pn544_probe,
+ .remove = pn544_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "pn544",
+ },
+};
+
+/*
+ * module load/unload record keeping
+ */
+
+static int __init pn544_dev_init(void)
+{
+ pr_info("Loading pn544 driver\n");
+ return i2c_add_driver(&pn544_driver);
+}
+module_init(pn544_dev_init);
+
+static void __exit pn544_dev_exit(void)
+{
+ pr_info("Unloading pn544 driver\n");
+ i2c_del_driver(&pn544_driver);
+}
+module_exit(pn544_dev_exit);
+
+MODULE_AUTHOR("Sylvain Fonteneau");
+MODULE_DESCRIPTION("NFC PN544 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/samsung_modemctl/Makefile b/drivers/misc/samsung_modemctl/Makefile
new file mode 100644
index 0000000..31061af
--- /dev/null
+++ b/drivers/misc/samsung_modemctl/Makefile
@@ -0,0 +1 @@
+obj-y += modem_ctl.o modem_io.o modem_dbg.o
diff --git a/drivers/misc/samsung_modemctl/modem_ctl.c b/drivers/misc/samsung_modemctl/modem_ctl.c
new file mode 100755
index 0000000..f99f17c
--- /dev/null
+++ b/drivers/misc/samsung_modemctl/modem_ctl.c
@@ -0,0 +1,1195 @@
+/* modem_ctl.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ * Copyright (C) 2010 Samsung Electronics.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/miscdevice.h>
+
+#include <linux/uaccess.h>
+#include <linux/fs.h>
+#include <linux/io.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/wakelock.h>
+
+#include "modem_ctl.h"
+#include "modem_ctl_p.h"
+
+/* supports modem delta update */
+#include "modem_ctl_recovery.h"
+
+/* Defines the primitives for writing and reading from and to the oneDRAM.
+ * All these primitives are used by the functions of file operation.
+ */
+static u32 onedram_checksum(u32 org, u8 *data, u32 len)
+{
+ u32 temp = org;
+ u32 i;
+
+ for (i = 0; i < len; i++)
+ temp += *(data + i);
+
+ return temp;
+}
+
+static inline u32 read_semaphore(struct modemctl *mc)
+{
+ return ioread32(mc->mmio + OFF_SEM) & 1;
+}
+
+static void return_semaphore(struct modemctl *mc)
+{
+ iowrite32(0, mc->mmio + OFF_SEM);
+}
+
+static u32 get_mailbox_ab(struct modemctl *mc)
+{
+ return ioread32(mc->mmio + OFF_MBOX_BP);
+}
+
+static void set_mailbox_ba(struct modemctl *mc, u32 data)
+{
+ iowrite32(data, mc->mmio + OFF_MBOX_AP);
+}
+
+static void write_single_data(struct modemctl *mc, int offset, int data)
+{
+ *(u32 *)(mc->mmio + offset) = data;
+}
+
+static int read_multiple_data(struct modemctl *mc, int offset, char *buf,
+ size_t size)
+{
+ if (!read_semaphore(mc)) {
+ pr_err("Semaphore is held by modem!");
+ return -EINVAL;
+ }
+
+ if (!buf) {
+ pr_err("Invalid buffer!");
+ return -EINVAL;
+ }
+
+ memcpy(buf, mc->mmio + offset, size);
+
+ return size;
+}
+
+static int dpram_write_from_user(struct modemctl *mc, int addr,
+ const char __user *data, size_t size)
+{
+ if (!read_semaphore(mc)) {
+ pr_err("Semaphore is held by modem!");
+ return -EINVAL;
+ }
+
+ if (copy_from_user(mc->mmio + addr, data, size) < 0) {
+ pr_err("[%s:%d] Copy from user failed\n", __func__, __LINE__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+
+static int modem_pwr_status(struct modemctl *mc)
+{
+ pr_debug("%s\n", __func__);
+ return gpio_get_value(mc->gpio_phone_active);
+}
+
+
+static int dpram_modem_pwroff(struct modemctl *mc)
+{
+ pr_debug("%s\n", __func__);
+
+ gpio_set_value(mc->gpio_phone_on, 0);
+ gpio_set_value(mc->gpio_cp_reset, 0);
+ mdelay(100);
+
+ return 0;
+}
+
+static int dpram_modem_reset(struct modemctl *mc)
+{
+ pr_debug("%s\n", __func__);
+
+ gpio_set_value(mc->gpio_phone_on, 1);
+ msleep(50);
+ gpio_set_value(mc->gpio_cp_reset, 0);
+ msleep(100);
+ gpio_set_value(mc->gpio_cp_reset, 1);
+ msleep(500);
+ gpio_set_value(mc->gpio_phone_on, 0);
+
+ return 0;
+}
+
+static int dpram_modem_pwron(struct modemctl *mc)
+{
+ int err = -1;
+ int msec;
+
+ pr_debug("%s\n", __func__);
+
+ return_semaphore(mc);
+
+ dpram_modem_reset(mc);
+
+ for (msec = 0; msec < 10000; msec++) {
+ if (modem_pwr_status(mc)) {
+ err = 0;
+ break;
+ }
+ msleep(1);
+ }
+
+ return err;
+}
+
+static int acquire_semaphore(struct modemctl *mc)
+{
+ int retrycnt = 20;
+
+ while (!read_semaphore(mc)) {
+ set_mailbox_ba(mc, DPRAM_BOOT_SEM_REQ);
+ dpram_modem_reset(mc);
+
+ msleep(100);
+ if (!(retrycnt--)) {
+ pr_debug("failed to get semaphore!");
+ return -1;
+ }
+ }
+
+ pr_debug("We have Semaphore!");
+ dpram_modem_pwroff(mc);
+ set_mailbox_ba(mc, 0x0);
+ return 0;
+}
+
+static int dpram_write_delta(struct modemctl *mc,
+ char __user *firmware, int size)
+{
+ int ret = 0;
+
+ pr_debug("%s\n", __func__);
+ acquire_semaphore(mc);
+ /* write the sizeof firmware */
+ write_single_data(mc, DPRAM_FIRMWARE_SIZE_ADDR, size);
+ /* write the data of firmware */
+ dpram_write_from_user(mc, DPRAM_FIRMWARE_ADDR, firmware, size);
+ return ret;
+}
+
+static int dpram_write_full(struct modemctl *mc,
+ char __user *firmware, int size)
+{
+ struct onedram_head_t onedram;
+ u32 data_offset = ONEDRAM_DL_DATA_OFFSET;
+ u32 head_offset = ONEDRAM_DL_HEADER_OFFSET;
+ u32 checksum;
+
+ pr_debug("%s\n", __func__);
+
+ acquire_semaphore(mc);
+
+ /* write full data of firmware */
+ dpram_write_from_user(mc, data_offset, firmware, size);
+ /* check checksum */
+ checksum = onedram_checksum(0, (u8 *)(mc->mmio + data_offset), size);
+
+ onedram.signature = ONEDRAM_DL_SIGNATURE;
+ onedram.is_boot_update = 0;
+ onedram.is_nv_update = 0;
+ onedram.length = size;
+ onedram.checksum = checksum;
+
+ /* write header info */
+ memcpy(mc->mmio + head_offset, (u8 *)&onedram, sizeof(onedram));
+
+ return 0;
+}
+
+static int dpram_update_delta(struct modemctl *mc)
+{
+ int err = 0;
+ int msec = 0;
+ u32 val;
+
+ pr_debug("%s\n", __func__);
+
+ acquire_semaphore(mc);
+ /* write boot magic */
+ write_single_data(mc, DPRAM_BOOT_MAGIC_ADDR,
+ DPRAM_BOOT_MAGIC_RECOVERY_FOTA);
+ write_single_data(mc, DPRAM_BOOT_TYPE_ADDR,
+ DPRAM_BOOT_TYPE_DPRAM_DELTA);
+ /* At this point modem is powered off. So power on modem */
+ err = dpram_modem_pwron(mc);
+ if (err < 0) {
+ pr_err("modem_reset() fail : %d", modem_pwr_status(mc));
+ return err;
+ }
+ /* clear mailboxBA */
+ set_mailbox_ba(mc, 0xFFFFFFFF);
+ /* wait for job sync message */
+ while (true) {
+ val = get_mailbox_ab(mc);
+ if ((val & STATUS_JOB_MAGIC_M) == STATUS_JOB_MAGIC_CODE) {
+ err = 0;
+ break;
+ }
+ msleep(1);
+ if (++msec > 20000) {
+ err = -2;
+ pr_err("Failed to sync with modem (%x)", val);
+ return err;
+ }
+ if ((msec % 1000) == 0)
+ pr_info("Waiting for sync message... 0x%08x (pwr:%s)", \
+ val, modem_pwr_status(mc) ? "ON" : "OFF");
+ }
+ if (err == 0) {
+ pr_info("Modem ready to start the firmware update");
+ /* let modem start the job */
+ set_mailbox_ba(mc, STATUS_JOB_MAGIC_CODE);
+ /* If we have the semaphore, toss it to modem. */
+ return_semaphore(mc);
+ }
+
+ return err;
+
+}
+
+static int dpram_update_full(struct modemctl *mc)
+{
+ int err;
+
+ pr_debug("%s\n", __func__);
+
+ err = dpram_modem_pwron(mc);
+ if (err < 0) {
+ pr_err("dpram_modem_pwron() fail : %d", modem_pwr_status(mc));
+ return -1;
+ }
+ /* clear mailboxBA */
+ set_mailbox_ba(mc, 0xFFFFFFFF);
+
+ return 0;
+}
+
+static int dpram_process_modem_update(struct modemctl *mc,
+ struct dpram_firmware *pfw)
+{
+ int ret = 0;
+
+ if (pfw->is_delta) {
+ mc->is_modem_delta_update = 1;
+
+ if (dpram_write_delta(mc, pfw->firmware, pfw->size) < 0) {
+ pr_err("firmware write failed\n");
+ ret = -1;
+ } else if (dpram_update_delta(mc) < 0) {
+ pr_err("Firmware update failed\n");
+ ret = -1;
+ }
+ } else {
+ if (dpram_write_full(mc, pfw->firmware, pfw->size) < 0) {
+ pr_err("firmware full write failed\n");
+ ret = -1;
+ } else if (dpram_update_full(mc) < 0) {
+ pr_err("Firmware full update failed\n");
+ ret = -1;
+ }
+ }
+
+ return ret;
+}
+
+static int dpram_chk_delta_update(struct modemctl *mc,
+ int __user *pct, char __user *msg)
+{
+ u32 status;
+ int percent = 0;
+ int err = 0;
+ char buf[DPRAM_MODEM_MSG_SIZE];
+ int debugprint = false;
+ int wait = 0;
+ /* check mailboxAB for the modem status */
+ status = get_mailbox_ab(mc);
+
+ debugprint = (mc->dpram_prev_status != status);
+ if (debugprint)
+ pr_info("Job status : 0x%08x (pwr:%s)\n", status, \
+ modem_pwr_status(mc) ? "ON" : "OFF");
+
+ if ((status & STATUS_JOB_MAGIC_M) != STATUS_JOB_MAGIC_CODE) {
+ if (debugprint)
+ pr_info("Job not accepted yet\n");
+ err = 1;
+ percent = 0;
+ strncpy(buf, "Job not accepted yet", DPRAM_MODEM_MSG_SIZE);
+ goto out;
+ }
+ if (status & STATUS_JOB_STARTED_M) {
+ return_semaphore(mc);
+ percent = status & STATUS_JOB_PROGRESS_M;
+ if (debugprint)
+ pr_info("Job progress pct=%d\n", percent);
+ err = 3;
+ } else {
+ percent = 0;
+ if (debugprint)
+ pr_info("Job NOT started yet...\n");
+ err = 2;
+ }
+ if (status & STATUS_JOB_ENDED_M) {
+ percent = status & STATUS_JOB_PROGRESS_M;
+ /* wait till we have semaphore */
+ pr_info("Wait for semaphore");
+ while (true) {
+ msleep(10);
+ if (read_semaphore(mc)) {
+ pr_info("We have semaphore");
+ break;
+ }
+ if (wait++ > 1000) {
+ pr_info("Proceeding without semaphore");
+ break;
+ }
+ }
+ read_multiple_data(mc, DPRAM_MODEM_STRING_MSG_ADDR, buf,
+ DPRAM_MODEM_MSG_SIZE);
+ if (status & STATUS_JOB_ERROR_M) {
+ err = -1;
+ pr_err("Job ended with error msg : %s\n", buf);
+ } else if (status & STATUS_JOB_COMPLETE_M) {
+ err = 0;
+ pr_info("Job completed successfully : %s\n", buf);
+ }
+ }
+out:
+ mc->dpram_prev_status = status;
+ if (put_user(percent, pct) < 0)
+ pr_err("[%s:%d] Copy to user failed\n", __func__, __LINE__);
+ if (copy_to_user((void *)msg, (void *)buf, DPRAM_MODEM_MSG_SIZE) < 0)
+ pr_err("[%s:%d] Copy to user failed\n", __func__, __LINE__);
+ return err;
+}
+
+static int dpram_chk_full_update(struct modemctl *mc,
+ int __user *pct, char __user *msg)
+{
+ int err;
+ u32 status = 0;
+ u32 phone_active = 0;
+ bool is_reboot = 0;
+
+ err = 3;
+ mc->dpram_prev_status = 0xFFFFFFFF;
+ mc->dpram_prev_phone_active = 0xFFFFFFFF;
+
+retry:
+ phone_active = modem_pwr_status(mc);
+ status = get_mailbox_ab(mc);
+
+ pr_debug("PHONE %d Mailbox 0x%x\n", phone_active, status);
+ if ((mc->dpram_prev_phone_active != phone_active) ||
+ (mc->dpram_prev_status != status)) {
+ mc->dpram_prev_phone_active = phone_active;
+ mc->dpram_prev_status = status;
+ }
+
+ if (!phone_active) {
+ if (status == ONEDRAM_DL_COMPLETE) {
+ pr_info("*OK* ONEDRAM_DL_COMPLETE\n");
+ err = 0;
+ } else if (status == ONEDRAM_DL_DONE_AND_RESET) {
+ pr_info("*OK* ONEDRAM_DONE_AND_RESET\n");
+ dpram_modem_pwron(mc);
+ goto retry;
+ }
+ }
+
+ if (status == ONEDRAM_DL_CHECKSUM_ERR) {
+ pr_info("*ERROR* ONEDRAM_DL_CHECKSUM_ERR\n");
+ is_reboot = 1;
+ } else if (status == ONEDRAM_DL_ERASE_WRITE_ERR) {
+ pr_info("*ERROR* ONEDRAM_DL_ERASE_WRITE_ERR\n");
+ is_reboot = 1;
+ } else if (status == ONEDRAM_DL_BOOT_UPDATE_ERR) {
+ pr_info("*ERROR* ONEDRAM_DL_BOOT_UPDATE_ERR\n");
+ is_reboot = 1;
+ } else if (status == ONEDRAM_DL_REWRITE_FAIL_ERR) {
+ pr_info("*ERROR* ONEDRAM_DL_REWRITE_FAIL_ERR\n");
+ is_reboot = 1;
+ } else if (status == ONEDRAM_DL_LENGTH_CH_FAIL) {
+ pr_info("*ERROR* ONEDRAM_DL_LENGTH_CH_FAIL\n");
+ is_reboot = 1;
+ } else {
+ if (status != mc->dpram_prev_status)
+ pr_info("*ERROR* %d, 0x%x\n", phone_active, status);
+ }
+
+ if (is_reboot) {
+ pr_info("system reboot necessary\n");
+ err = -1;
+ }
+
+ if (err <= 0) {
+ pr_info("Update done.\n");
+ acquire_semaphore(mc);
+ write_single_data(mc, 0, 0xffffffff);
+ }
+
+ return err;
+}
+
+/* The modem_ctl portion of this driver handles modem lifecycle
+ * transitions (OFF -> ON -> RUNNING -> ABNORMAL), the firmware
+ * download mechanism (via /dev/modem_ctl), and interrupts from
+ * the modem (direct and via onedram mailbox interrupt).
+ *
+ * It also handles tracking the ownership of the onedram "semaphore"
+ * which governs which processor (AP or BP) has access to the 16MB
+ * shared memory region. The modem_mmio_{acquire,release,request}
+ * primitives are used by modem_io.c to obtain access to the shared
+ * memory region when necessary to do io.
+ *
+ * Further, modem_update_state() and modem_handle_io() are called
+ * when we gain control over the shared memory region (to update
+ * fifo state info) and when there may be io to process, respectively.
+ *
+ */
+
+#define WAIT_TIMEOUT (HZ*5)
+
+void modem_request_sem(struct modemctl *mc)
+{
+ writel(MB_COMMAND | MB_VALID | MBC_REQ_SEM,
+ mc->mmio + OFF_MBOX_AP);
+}
+
+static inline int mmio_sem(struct modemctl *mc)
+{
+ return readl(mc->mmio + OFF_SEM) & 1;
+}
+
+int modem_request_mmio(struct modemctl *mc)
+{
+ unsigned long flags;
+ int ret;
+ spin_lock_irqsave(&mc->lock, flags);
+ mc->mmio_req_count++;
+ ret = mc->mmio_owner;
+ if (!ret) {
+ if (mmio_sem(mc) == 1) {
+ /* surprise! we already have control */
+ ret = mc->mmio_owner = 1;
+ wake_up(&mc->wq);
+ modem_update_state(mc);
+ MODEM_COUNT(mc,request_no_wait);
+ } else {
+ /* ask the modem for mmio access */
+ if (modem_running(mc))
+ modem_request_sem(mc);
+ MODEM_COUNT(mc,request_wait);
+ }
+ } else {
+ MODEM_COUNT(mc,request_no_wait);
+ }
+ /* TODO: timer to retry? */
+ spin_unlock_irqrestore(&mc->lock, flags);
+ return ret;
+}
+
+void modem_release_mmio(struct modemctl *mc, unsigned bits)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&mc->lock, flags);
+ mc->mmio_req_count--;
+ mc->mmio_signal_bits |= bits;
+ if ((mc->mmio_req_count == 0) && modem_running(mc)) {
+ if (mc->mmio_bp_request) {
+ mc->mmio_bp_request = 0;
+ writel(0, mc->mmio + OFF_SEM);
+ writel(MB_COMMAND | MB_VALID | MBC_RES_SEM,
+ mc->mmio + OFF_MBOX_AP);
+ MODEM_COUNT(mc,release_bp_waiting);
+ } else if (mc->mmio_signal_bits) {
+ writel(0, mc->mmio + OFF_SEM);
+ writel(MB_VALID | mc->mmio_signal_bits,
+ mc->mmio + OFF_MBOX_AP);
+ MODEM_COUNT(mc,release_bp_signaled);
+ } else {
+ MODEM_COUNT(mc,release_no_action);
+ }
+ mc->mmio_owner = 0;
+ mc->mmio_signal_bits = 0;
+ }
+ spin_unlock_irqrestore(&mc->lock, flags);
+}
+
+static int mmio_owner_p(struct modemctl *mc)
+{
+ unsigned long flags;
+ int ret;
+ spin_lock_irqsave(&mc->lock, flags);
+ ret = mc->mmio_owner || modem_offline(mc);
+ spin_unlock_irqrestore(&mc->lock, flags);
+ return ret;
+}
+
+int modem_acquire_mmio(struct modemctl *mc)
+{
+ if (modem_request_mmio(mc) == 0) {
+ int ret = wait_event_interruptible_timeout(
+ mc->wq, mmio_owner_p(mc), 5 * HZ);
+ if (ret <= 0) {
+ modem_release_mmio(mc, 0);
+ if (ret == 0) {
+ pr_err("modem_acquire_mmio() TIMEOUT\n");
+ return -ENODEV;
+ } else {
+ return -ERESTARTSYS;
+ }
+ }
+ }
+ if (!modem_running(mc)) {
+ modem_release_mmio(mc, 0);
+ return -ENODEV;
+ }
+ return 0;
+}
+
+static int modemctl_open(struct inode *inode, struct file *filp)
+{
+ struct modemctl *mc = to_modemctl(filp->private_data);
+ filp->private_data = mc;
+
+ if (mc->open_count)
+ return -EBUSY;
+
+ mc->open_count++;
+ return 0;
+}
+
+static int modemctl_release(struct inode *inode, struct file *filp)
+{
+ struct modemctl *mc = filp->private_data;
+
+ mc->open_count = 0;
+ filp->private_data = NULL;
+ return 0;
+}
+
+static ssize_t modemctl_read(struct file *filp, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct modemctl *mc = filp->private_data;
+ loff_t pos;
+ int ret;
+
+ mutex_lock(&mc->ctl_lock);
+ pos = mc->ramdump_pos;
+ if (mc->status != MODEM_DUMPING) {
+ pr_err("[MODEM] not in ramdump mode\n");
+ ret = -ENODEV;
+ goto done;
+ }
+ if (pos < 0) {
+ ret = -EINVAL;
+ goto done;
+ }
+ if (pos >= mc->ramdump_size) {
+ pr_err("[MODEM] ramdump EOF\n");
+ ret = 0;
+ goto done;
+ }
+ if (count > mc->ramdump_size - pos)
+ count = mc->ramdump_size - pos;
+
+ ret = copy_to_user(buf, mc->mmio + pos, count);
+ if (ret) {
+ ret = -EFAULT;
+ goto done;
+ }
+ pos += count;
+ ret = count;
+
+ if (pos == mc->ramdump_size) {
+ if (mc->ramdump_size == RAMDUMP_LARGE_SIZE) {
+ mc->ramdump_size = 0;
+ pr_info("[MODEM] requesting more ram\n");
+ writel(0, mc->mmio + OFF_SEM);
+ writel(MODEM_CMD_RAMDUMP_MORE, mc->mmio + OFF_MBOX_AP);
+ wait_event_timeout(mc->wq, mc->ramdump_size != 0, 10 * HZ);
+ } else {
+ pr_info("[MODEM] no more ram to dump\n");
+ mc->ramdump_size = 0;
+ }
+ mc->ramdump_pos = 0;
+ } else {
+ mc->ramdump_pos = pos;
+ }
+
+done:
+ mutex_unlock(&mc->ctl_lock);
+ return ret;
+
+}
+
+static ssize_t modemctl_write(struct file *filp, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct modemctl *mc = filp->private_data;
+ u32 owner;
+ char *data;
+ loff_t pos = *ppos;
+ unsigned long ret;
+
+ mutex_lock(&mc->ctl_lock);
+ data = (char __force *)mc->mmio + pos;
+ owner = mmio_sem(mc);
+
+ if (mc->status != MODEM_POWER_ON) {
+ pr_err("modemctl_write: modem not powered on\n");
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (!owner) {
+ pr_err("modemctl_write: doesn't own semaphore\n");
+ ret = -EIO;
+ goto done;
+ }
+
+ if (pos < 0) {
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (pos >= mc->mmsize) {
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (count > mc->mmsize - pos)
+ count = mc->mmsize - pos;
+
+ ret = copy_from_user(data, buf, count);
+ if (ret) {
+ ret = -EFAULT;
+ goto done;
+ }
+ *ppos = pos + count;
+ ret = count;
+
+done:
+ mutex_unlock(&mc->ctl_lock);
+ return ret;
+}
+
+
+static int modem_start(struct modemctl *mc, int ramdump)
+{
+ int ret;
+
+ pr_info("[MODEM] modem_start() %s\n",
+ ramdump ? "ramdump" : "normal");
+
+ if (mc->status != MODEM_POWER_ON) {
+ pr_err("[MODEM] modem not powered on\n");
+ return -EINVAL;
+ }
+
+ if (!mc->is_cdma_modem &&
+ readl(mc->mmio + OFF_MBOX_BP) != MODEM_MSG_SBL_DONE) {
+ pr_err("[MODEM] bootloader not ready\n");
+ return -EIO;
+ }
+
+ writel(0, mc->mmio + OFF_SEM);
+ if (ramdump) {
+ mc->status = MODEM_BOOTING_RAMDUMP;
+ mc->ramdump_size = 0;
+ mc->ramdump_pos = 0;
+ writel(MODEM_CMD_RAMDUMP_START, mc->mmio + OFF_MBOX_AP);
+
+ ret = wait_event_timeout(mc->wq, mc->status == MODEM_DUMPING, 25 * HZ);
+ if (ret == 0)
+ return -ENODEV;
+ } else {
+ if (mc->is_cdma_modem)
+ mc->status = MODEM_RUNNING;
+ else {
+ mc->status = MODEM_BOOTING_NORMAL;
+ writel(MODEM_CMD_BINARY_LOAD, mc->mmio + OFF_MBOX_AP);
+
+ ret = wait_event_timeout(mc->wq,
+ modem_running(mc), 25 * HZ);
+ if (ret == 0)
+ return -ENODEV;
+ }
+ }
+
+ pr_info("[MODEM] modem_start() DONE\n");
+ return 0;
+}
+
+static int modem_reset(struct modemctl *mc)
+{
+ pr_info("[MODEM] modem_reset()\n");
+
+ /* ensure pda active pin set to low */
+ gpio_set_value(mc->gpio_pda_active, 0);
+
+ /* read inbound mbox to clear pending IRQ */
+ (void) readl(mc->mmio + OFF_MBOX_BP);
+
+ /* write outbound mbox to assert outbound IRQ */
+ writel(0, mc->mmio + OFF_MBOX_AP);
+
+ if (mc->is_cdma_modem) {
+ gpio_set_value(mc->gpio_phone_on, 1);
+ msleep(50);
+
+ /* ensure cp_reset pin set to low */
+ gpio_set_value(mc->gpio_cp_reset, 0);
+ msleep(100);
+
+ gpio_set_value(mc->gpio_cp_reset, 1);
+ msleep(500);
+
+ } else {
+ /* ensure cp_reset pin set to low */
+ gpio_set_value(mc->gpio_cp_reset, 0);
+ msleep(100);
+
+ gpio_set_value(mc->gpio_cp_reset, 0);
+ msleep(100);
+
+ gpio_set_value(mc->gpio_cp_reset, 1);
+
+ /* Follow RESET timming delay not Power-On timming,
+ because CP_RST & PHONE_ON have been set high already. */
+ msleep(100); /*wait modem stable */
+ }
+
+ gpio_set_value(mc->gpio_pda_active, 1);
+
+ mc->status = MODEM_POWER_ON;
+
+ return 0;
+}
+
+static int modem_off(struct modemctl *mc)
+{
+ pr_info("[MODEM] modem_off()\n");
+ gpio_set_value(mc->gpio_cp_reset, 0);
+ mc->status = MODEM_OFF;
+ return 0;
+}
+
+static long modemctl_ioctl(struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ struct modemctl *mc = filp->private_data;
+ struct dpram_firmware fw;
+ struct stat_info *pst;
+ int ret = 0;
+
+ mutex_lock(&mc->ctl_lock);
+ switch (cmd) {
+ case IOCTL_MODEM_RESET:
+ ret = modem_reset(mc);
+ MODEM_COUNT(mc,resets);
+ break;
+ case IOCTL_MODEM_START:
+ ret = modem_start(mc, 0);
+ break;
+ case IOCTL_MODEM_RAMDUMP:
+ ret = modem_start(mc, 1);
+ break;
+ case IOCTL_MODEM_OFF:
+ ret = modem_off(mc);
+ break;
+
+ /* CDMA modem update in recovery mode */
+ case IOCTL_MODEM_FW_UPDATE:
+ pr_info("IOCTL_MODEM_FW_UPDATE\n");
+ if (arg == NULL) {
+ pr_err("No firmware");
+ break;
+ }
+
+ if (copy_from_user((void *)&fw, (void *)arg, sizeof(fw)) < 0) {
+ pr_err("copy from user failed!");
+ ret = -EINVAL;
+ } else if (dpram_process_modem_update(mc, &fw) < 0) {
+ pr_err("firmware write failed\n");
+ ret = -EIO;
+ }
+ break;
+ case IOCTL_MODEM_CHK_STAT:
+ pst = (struct stat_info *)arg;
+ if (mc->is_modem_delta_update)
+ ret = dpram_chk_delta_update(mc, &(pst->pct), pst->msg);
+ else
+ ret = dpram_chk_full_update(mc, &(pst->pct), pst->msg);
+ break;
+ case IOCTL_MODEM_PWROFF:
+ pr_info("IOCTL_MODEM_PWROFF\n");
+ dpram_modem_pwroff(mc);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ mutex_unlock(&mc->ctl_lock);
+ pr_info("modemctl_ioctl() %d\n", ret);
+ return ret;
+}
+
+static const struct file_operations modemctl_fops = {
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+ .open = modemctl_open,
+ .release = modemctl_release,
+ .read = modemctl_read,
+ .write = modemctl_write,
+ .unlocked_ioctl = modemctl_ioctl,
+};
+
+static irqreturn_t modemctl_bp_irq_handler(int irq, void *_mc)
+{
+ int value = 0;
+
+ value = gpio_get_value(((struct modemctl *)_mc)->gpio_phone_active);
+ pr_info("[MODEM] bp_irq() PHONE_ACTIVE_PIN=%d\n", value);
+ return IRQ_HANDLED;
+
+}
+
+static void modemctl_handle_offline(struct modemctl *mc, unsigned cmd)
+{
+ switch (mc->status) {
+ case MODEM_BOOTING_NORMAL:
+ if (cmd == MODEM_MSG_BINARY_DONE) {
+ pr_info("[MODEM] binary load done\n");
+ mc->status = MODEM_RUNNING;
+ wake_up(&mc->wq);
+ }
+ break;
+ case MODEM_BOOTING_RAMDUMP:
+ case MODEM_DUMPING:
+ if (cmd == MODEM_MSG_RAMDUMP_LARGE) {
+ mc->status = MODEM_DUMPING;
+ mc->ramdump_size = RAMDUMP_LARGE_SIZE;
+ wake_up(&mc->wq);
+ pr_info("[MODEM] ramdump - %d bytes available\n",
+ mc->ramdump_size);
+ } else if (cmd == MODEM_MSG_RAMDUMP_SMALL) {
+ mc->status = MODEM_DUMPING;
+ mc->ramdump_size = RAMDUMP_SMALL_SIZE;
+ wake_up(&mc->wq);
+ pr_info("[MODEM] ramdump - %d bytes available\n",
+ mc->ramdump_size);
+ } else {
+ pr_err("[MODEM] unknown msg %08x in ramdump mode\n", cmd);
+ }
+ break;
+ }
+}
+
+static irqreturn_t modemctl_mbox_irq_handler(int irq, void *_mc)
+{
+ struct modemctl *mc = _mc;
+ unsigned cmd;
+ unsigned long flags;
+
+ cmd = readl(mc->mmio + OFF_MBOX_BP);
+
+ if (unlikely(mc->status != MODEM_RUNNING)) {
+ modemctl_handle_offline(mc, cmd);
+ return IRQ_HANDLED;
+ }
+
+ if (!(cmd & MB_VALID)) {
+ if (cmd == MODEM_MSG_LOGDUMP_DONE) {
+ pr_info("modem: logdump done!\n");
+ mc->logdump_data = 1;
+ wake_up(&mc->wq);
+ } else {
+ pr_info("modem: what is %08x\n",cmd);
+ }
+ return IRQ_HANDLED;
+ }
+
+ spin_lock_irqsave(&mc->lock, flags);
+
+ if (cmd & MB_COMMAND) {
+ switch (cmd & 15) {
+ case MBC_REQ_SEM:
+ if (mmio_sem(mc) == 0) {
+ /* Sometimes the modem may ask for the
+ * sem when it already owns it. Humor
+ * it and ack that request.
+ */
+ writel(MB_COMMAND | MB_VALID | MBC_RES_SEM,
+ mc->mmio + OFF_MBOX_AP);
+ MODEM_COUNT(mc,bp_req_confused);
+ } else if (mc->mmio_req_count == 0) {
+ /* No references? Give it to the modem. */
+ modem_update_state(mc);
+ mc->mmio_owner = 0;
+ writel(0, mc->mmio + OFF_SEM);
+ writel(MB_COMMAND | MB_VALID | MBC_RES_SEM,
+ mc->mmio + OFF_MBOX_AP);
+ MODEM_COUNT(mc,bp_req_instant);
+ goto done;
+ } else {
+ /* Busy now, remember the modem needs it. */
+ mc->mmio_bp_request = 1;
+ MODEM_COUNT(mc,bp_req_delayed);
+ break;
+ }
+ case MBC_RES_SEM:
+ break;
+ case MBC_PHONE_START:
+ /* TODO: should we avoid sending any other messages
+ * to the modem until this message is received and
+ * acknowledged?
+ */
+ writel(MB_COMMAND | MB_VALID |
+ MBC_INIT_END | CP_BOOT_AIRPLANE | AP_OS_ANDROID,
+ mc->mmio + OFF_MBOX_AP);
+
+ /* TODO: probably unsafe to send this back-to-back
+ * with the INIT_END message.
+ */
+ /* if somebody is waiting for mmio access... */
+ if (mc->mmio_req_count)
+ modem_request_sem(mc);
+ break;
+ case MBC_RESET:
+ pr_err("$$$ MODEM RESET $$$\n");
+ mc->status = MODEM_CRASHED;
+ wake_up(&mc->wq);
+ break;
+ case MBC_ERR_DISPLAY: {
+ char buf[SIZ_ERROR_MSG + 1];
+ int i;
+ pr_err("$$$ MODEM ERROR $$$\n");
+ mc->status = MODEM_CRASHED;
+ wake_up(&mc->wq);
+ memcpy(buf, mc->mmio + OFF_ERROR_MSG, SIZ_ERROR_MSG);
+ for (i = 0; i < SIZ_ERROR_MSG; i++)
+ if ((buf[i] < 0x20) || (buf[1] > 0x7e))
+ buf[i] = 0x20;
+ buf[i] = 0;
+ i--;
+ while ((i > 0) && (buf[i] == 0x20))
+ buf[i--] = 0;
+ pr_err("$$$ %s $$$\n", buf);
+ break;
+ }
+ case MBC_SUSPEND:
+ break;
+ case MBC_RESUME:
+ break;
+ }
+ }
+
+ /* On *any* interrupt from the modem it may have given
+ * us ownership of the mmio hw semaphore. If that
+ * happens, we should claim the semaphore if we have
+ * threads waiting for it and we should process any
+ * messages that the modem has enqueued in its fifos
+ * by calling modem_handle_io().
+ */
+ if (mmio_sem(mc) == 1) {
+ if (!mc->mmio_owner) {
+ modem_update_state(mc);
+ if (mc->mmio_req_count) {
+ mc->mmio_owner = 1;
+ wake_up(&mc->wq);
+ }
+ }
+
+ modem_handle_io(mc);
+
+ /* If we have a signal to send and we're not
+ * hanging on to the mmio hw semaphore, give
+ * it back to the modem and send the signal.
+ * Otherwise this will happen when we give up
+ * the mmio hw sem in modem_release_mmio().
+ */
+ if (mc->mmio_signal_bits && !mc->mmio_owner) {
+ writel(0, mc->mmio + OFF_SEM);
+ writel(MB_VALID | mc->mmio_signal_bits,
+ mc->mmio + OFF_MBOX_AP);
+ mc->mmio_signal_bits = 0;
+ }
+ }
+done:
+ spin_unlock_irqrestore(&mc->lock, flags);
+ return IRQ_HANDLED;
+}
+
+void modem_force_crash(struct modemctl *mc)
+{
+ unsigned long int flags;
+ pr_info("modem_force_crash() BOOM!\n");
+ spin_lock_irqsave(&mc->lock, flags);
+ mc->status = MODEM_CRASHED;
+ wake_up(&mc->wq);
+ spin_unlock_irqrestore(&mc->lock, flags);
+}
+
+static int __devinit modemctl_probe(struct platform_device *pdev)
+{
+ int r = -ENOMEM;
+ struct modemctl *mc;
+ struct modemctl_data *pdata;
+ struct resource *res;
+
+ pdata = pdev->dev.platform_data;
+
+ mc = kzalloc(sizeof(*mc), GFP_KERNEL);
+ if (!mc)
+ return -ENOMEM;
+
+ init_waitqueue_head(&mc->wq);
+ spin_lock_init(&mc->lock);
+ mutex_init(&mc->ctl_lock);
+
+ mc->irq_bp = platform_get_irq_byname(pdev, "active");
+ mc->irq_mbox = platform_get_irq_byname(pdev, "onedram");
+
+ mc->gpio_phone_active = pdata->gpio_phone_active;
+ mc->gpio_pda_active = pdata->gpio_pda_active;
+ mc->gpio_cp_reset = pdata->gpio_cp_reset;
+ mc->gpio_phone_on = pdata->gpio_phone_on;
+ mc->is_cdma_modem = pdata->is_cdma_modem;
+ if (pdata->num_pdp_contexts)
+ mc->num_pdp_contexts = pdata->num_pdp_contexts;
+ else
+ mc->num_pdp_contexts = 1;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ goto err_free;
+ mc->mmbase = res->start;
+ mc->mmsize = resource_size(res);
+
+ mc->mmio = ioremap_nocache(mc->mmbase, mc->mmsize);
+ if (!mc->mmio)
+ goto err_free;
+
+ platform_set_drvdata(pdev, mc);
+
+ mc->dev.name = "modem_ctl";
+ mc->dev.minor = MISC_DYNAMIC_MINOR;
+ mc->dev.fops = &modemctl_fops;
+ r = misc_register(&mc->dev);
+ if (r)
+ goto err_ioremap;
+
+ /* hide control registers from userspace */
+ mc->mmsize -= 0x800;
+ mc->status = MODEM_OFF;
+
+ wake_lock_init(&mc->ip_tx_wakelock,
+ WAKE_LOCK_SUSPEND, "modem_ip_tx");
+ wake_lock_init(&mc->ip_rx_wakelock,
+ WAKE_LOCK_SUSPEND, "modem_ip_rx");
+
+ modem_io_init(mc, mc->mmio);
+
+ r = request_irq(mc->irq_bp, modemctl_bp_irq_handler,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ "modemctl_bp", mc);
+ if (r)
+ goto err_ioremap;
+
+ r = request_irq(mc->irq_mbox, modemctl_mbox_irq_handler,
+ IRQF_TRIGGER_LOW, "modemctl_mbox", mc);
+ if (r)
+ goto err_irq_bp;
+
+ enable_irq_wake(mc->irq_bp);
+ enable_irq_wake(mc->irq_mbox);
+
+ modem_debugfs_init(mc);
+
+ return 0;
+
+err_irq_mbox:
+ free_irq(mc->irq_mbox, mc);
+err_irq_bp:
+ free_irq(mc->irq_bp, mc);
+err_ioremap:
+ iounmap(mc->mmio);
+err_free:
+ kfree(mc);
+ return r;
+}
+
+static int modemctl_suspend(struct device *pdev)
+{
+ struct modemctl *mc = dev_get_drvdata(pdev);
+ gpio_set_value(mc->gpio_pda_active, 0);
+ return 0;
+}
+
+static int modemctl_resume(struct device *pdev)
+{
+ struct modemctl *mc = dev_get_drvdata(pdev);
+ gpio_set_value(mc->gpio_pda_active, 1);
+ return 0;
+}
+
+static const struct dev_pm_ops modemctl_pm_ops = {
+ .suspend = modemctl_suspend,
+ .resume = modemctl_resume,
+};
+
+static struct platform_driver modemctl_driver = {
+ .probe = modemctl_probe,
+ .driver = {
+ .name = "modemctl",
+ .pm = &modemctl_pm_ops,
+ },
+};
+
+static int __init modemctl_init(void)
+{
+ return platform_driver_register(&modemctl_driver);
+}
+
+module_init(modemctl_init);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Samsung Modem Control Driver");
+
diff --git a/drivers/misc/samsung_modemctl/modem_ctl.h b/drivers/misc/samsung_modemctl/modem_ctl.h
new file mode 100644
index 0000000..b4ad920
--- /dev/null
+++ b/drivers/misc/samsung_modemctl/modem_ctl.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2010 Google, Inc.
+ * Copyright (C) 2010 Samsung Electronics.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __MODEM_CONTROL_H__
+#define __MODEM_CONTROL_H__
+
+#define IOCTL_MODEM_RAMDUMP _IO('o', 0x19)
+#define IOCTL_MODEM_RESET _IO('o', 0x20)
+#define IOCTL_MODEM_START _IO('o', 0x21)
+#define IOCTL_MODEM_OFF _IO('o', 0x22)
+
+#define IOCTL_MODEM_SEND _IO('o', 0x23)
+#define IOCTL_MODEM_RECV _IO('o', 0x24)
+
+struct modem_io {
+ uint32_t size;
+ uint32_t id;
+ uint32_t cmd;
+ void *data;
+};
+
+/* platform data */
+struct modemctl_data {
+ const char *name;
+ unsigned gpio_phone_active;
+ unsigned gpio_pda_active;
+ unsigned gpio_cp_reset;
+ unsigned gpio_phone_on;
+ bool is_cdma_modem; /* 1:CDMA Modem */
+ int num_pdp_contexts;
+};
+
+#endif
diff --git a/drivers/misc/samsung_modemctl/modem_ctl_p.h b/drivers/misc/samsung_modemctl/modem_ctl_p.h
new file mode 100644
index 0000000..6223b20
--- /dev/null
+++ b/drivers/misc/samsung_modemctl/modem_ctl_p.h
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2010 Google, Inc.
+ * Copyright (C) 2010 Samsung Electronics.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __MODEM_CONTROL_P_H__
+#define __MODEM_CONTROL_P_H__
+
+#define MODEM_OFF 0
+#define MODEM_CRASHED 1
+#define MODEM_RAMDUMP 2
+#define MODEM_POWER_ON 3
+#define MODEM_BOOTING_NORMAL 4
+#define MODEM_BOOTING_RAMDUMP 5
+#define MODEM_DUMPING 6
+#define MODEM_RUNNING 7
+
+#define modem_offline(mc) ((mc)->status < MODEM_POWER_ON)
+#define modem_running(mc) ((mc)->status == MODEM_RUNNING)
+
+#define M_PIPE_MAX_HDR 16
+
+struct net_device;
+
+struct m_pipe {
+ int (*push_header)(struct modem_io *io, void *header);
+ int (*pull_header)(struct modem_io *io, void *header);
+
+ unsigned header_size;
+
+ struct m_fifo *tx;
+ struct m_fifo *rx;
+
+ struct modemctl *mc;
+ unsigned ready;
+
+ struct miscdevice dev;
+
+ struct mutex tx_lock;
+ struct mutex rx_lock;
+
+ struct wake_lock wakelock;
+};
+#define to_m_pipe(misc) container_of(misc, struct m_pipe, dev)
+
+struct m_fifo {
+ unsigned *head;
+ unsigned *tail;
+ unsigned size;
+ void *data;
+
+ unsigned avail;
+ unsigned bits;
+ unsigned unused1;
+ unsigned unused2;
+};
+
+struct modemstats {
+ unsigned request_no_wait;
+ unsigned request_wait;
+
+ unsigned release_no_action;
+ unsigned release_bp_waiting;
+ unsigned release_bp_signaled;
+
+ unsigned bp_req_instant;
+ unsigned bp_req_delayed;
+ unsigned bp_req_confused;
+
+ unsigned rx_unknown;
+ unsigned rx_dropped;
+ unsigned rx_purged;
+ unsigned rx_received;
+
+ unsigned tx_no_delay;
+ unsigned tx_queued;
+ unsigned tx_bp_signaled;
+ unsigned tx_fifo_full;
+
+ unsigned pipe_tx;
+ unsigned pipe_rx;
+ unsigned pipe_tx_delayed;
+ unsigned pipe_rx_purged;
+
+ unsigned resets;
+};
+
+#define MODEM_COUNT(mc,s) (((mc)->stats.s)++)
+
+struct modemctl {
+ void __iomem *mmio;
+ struct modemstats stats;
+
+ /* lock and waitqueue for shared memory state */
+ spinlock_t lock;
+ wait_queue_head_t wq;
+
+ /* shared memory semaphore management */
+ unsigned mmio_req_count;
+ unsigned mmio_bp_request;
+ unsigned mmio_owner;
+ unsigned mmio_signal_bits;
+
+ struct m_fifo fmt_tx;
+ struct m_fifo fmt_rx;
+ struct m_fifo raw_tx;
+ struct m_fifo raw_rx;
+ struct m_fifo rfs_tx;
+ struct m_fifo rfs_rx;
+
+ struct wake_lock ip_tx_wakelock;
+ struct wake_lock ip_rx_wakelock;
+
+ struct net_device **ndev;
+
+ int open_count;
+ int status;
+
+ unsigned mmbase;
+ unsigned mmsize;
+
+ int irq_bp;
+ int irq_mbox;
+
+ unsigned gpio_phone_active;
+ unsigned gpio_pda_active;
+ unsigned gpio_cp_reset;
+ unsigned gpio_phone_on;
+ bool is_cdma_modem;
+ int num_pdp_contexts;
+ bool is_modem_delta_update;
+ unsigned dpram_prev_phone_active;
+ unsigned dpram_prev_status;
+
+ struct miscdevice dev;
+
+ struct m_pipe cmd_pipe;
+ struct m_pipe rfs_pipe;
+
+ struct mutex ctl_lock;
+ ktime_t mmio_t0;
+
+ /* used for ramdump mode */
+ unsigned ramdump_size;
+ loff_t ramdump_pos;
+
+ unsigned logdump;
+ unsigned logdump_data;
+};
+#define to_modemctl(misc) container_of(misc, struct modemctl, dev)
+
+
+/* called when semaphore is held and there may be io to process */
+void modem_handle_io(struct modemctl *mc);
+void modem_update_state(struct modemctl *mc);
+
+/* called once at probe() */
+int modem_io_init(struct modemctl *mc, void __iomem *mmio);
+
+/* called when modem boots and goes offline */
+void modem_io_enable(struct modemctl *mc);
+void modem_io_disable(struct modemctl *mc);
+
+
+/* Block until control of mmio area is obtained (0)
+ * or interrupt (-ERESTARTSYS) or failure (-ENODEV)
+ * occurs.
+ */
+int modem_acquire_mmio(struct modemctl *mc);
+
+/* Request control of mmio area. Returns 1 if
+ * control obtained, 0 if not (request pending).
+ * Either way, release_mmio() must be called to
+ * balance this.
+ */
+int modem_request_mmio(struct modemctl *mc);
+
+/* Return control of mmio area once requested
+ * by modem_request_mmio() or acquired by a
+ * successful modem_acquire_mmio().
+ *
+ * The onedram semaphore is only actually returned
+ * to the BP if there is an outstanding request
+ * for it from the BP, or if the bits argument
+ * to one of the release_mmio() calls was nonzero.
+ */
+void modem_release_mmio(struct modemctl *mc, unsigned bits);
+
+/* Send a request for the hw mmio sem to the modem.
+ * Used ONLY by the internals of modem_request_mmio() and
+ * some trickery in vnet_xmit(). Please do not use elsewhere.
+ */
+void modem_request_sem(struct modemctl *mc);
+
+
+/* internal glue */
+void modem_debugfs_init(struct modemctl *mc);
+void modem_force_crash(struct modemctl *mc);
+
+/* protocol definitions */
+#define MB_VALID 0x0080
+#define MB_COMMAND 0x0040
+
+/* CMD_INIT_END extended bit */
+#define CP_BOOT_ONLINE 0x0000
+#define CP_BOOT_AIRPLANE 0x1000
+#define AP_OS_ANDROID 0x0100
+#define AP_OS_WINMOBILE 0x0200
+#define AP_OS_LINUX 0x0300
+#define AP_OS_SYMBIAN 0x0400
+
+/* CMD_PHONE_START extended bit */
+#define CP_QUALCOMM 0x0100
+#define CP_INFINEON 0x0200
+#define CP_BROADCOM 0x0300
+
+#define MBC_NONE 0x0000
+#define MBC_INIT_START 0x0001
+#define MBC_INIT_END 0x0002
+#define MBC_REQ_ACTIVE 0x0003
+#define MBC_RES_ACTIVE 0x0004
+#define MBC_TIME_SYNC 0x0005
+#define MBC_POWER_OFF 0x0006
+#define MBC_RESET 0x0007
+#define MBC_PHONE_START 0x0008
+#define MBC_ERR_DISPLAY 0x0009
+#define MBC_SUSPEND 0x000A
+#define MBC_RESUME 0x000B
+#define MBC_EMER_DOWN 0x000C
+#define MBC_REQ_SEM 0x000D
+#define MBC_RES_SEM 0x000E
+#define MBC_MAX 0x000F
+
+/* data mailbox flags */
+#define MBD_SEND_FMT 0x0002
+#define MBD_SEND_RAW 0x0001
+#define MBD_SEND_RFS 0x0100
+
+#define MODEM_MSG_SBL_DONE 0x12341234
+#define MODEM_CMD_BINARY_LOAD 0x45674567
+#define MODEM_MSG_BINARY_DONE 0xabcdabcd
+
+#define MODEM_CMD_RAMDUMP_START 0xDEADDEAD
+#define MODEM_MSG_RAMDUMP_LARGE 0x0ADD0ADD // 16MB - 2KB
+#define MODEM_CMD_RAMDUMP_MORE 0xEDEDEDED
+#define MODEM_MSG_RAMDUMP_SMALL 0xFADEFADE // 5MB + 4KB
+
+#define MODEM_CMD_LOGDUMP_START 0x19732864
+//#define MODEM_MSG_LOGDUMP_DONE 0x28641973
+#define MODEM_MSG_LOGDUMP_DONE 0x00001973
+
+#define RAMDUMP_LARGE_SIZE (16*1024*1024 - 2*1024)
+#define RAMDUMP_SMALL_SIZE (5*1024*1024 + 4*1024)
+
+
+/* onedram shared memory map */
+#define OFF_MAGIC 0x00000000
+#define OFF_ACCESS 0x00000004
+
+#define OFF_FMT_TX_HEAD 0x00000010
+#define OFF_FMT_TX_TAIL 0x00000014
+#define OFF_FMT_RX_HEAD 0x00000018
+#define OFF_FMT_RX_TAIL 0x0000001C
+#define OFF_RAW_TX_HEAD 0x00000020
+#define OFF_RAW_TX_TAIL 0x00000024
+#define OFF_RAW_RX_HEAD 0x00000028
+#define OFF_RAW_RX_TAIL 0x0000002C
+#define OFF_RFS_TX_HEAD 0x00000030
+#define OFF_RFS_TX_TAIL 0x00000034
+#define OFF_RFS_RX_HEAD 0x00000038
+#define OFF_RFS_RX_TAIL 0x0000003C
+
+#define OFF_ERROR_MSG 0x00001000
+#define SIZ_ERROR_MSG 160
+
+#define OFF_FMT_TX_DATA 0x000FE000
+#define OFF_FMT_RX_DATA 0x000FF000
+#define SIZ_FMT_DATA 0x00001000
+#define OFF_RAW_TX_DATA 0x00100000
+#define OFF_RAW_RX_DATA 0x00200000
+#define SIZ_RAW_DATA 0x00100000
+#define OFF_RFS_TX_DATA 0x00300000
+#define OFF_RFS_RX_DATA 0x00400000
+#define SIZ_RFS_DATA 0x00100000
+
+#define OFF_LOGDUMP_DATA 0x00A00000
+#define SIZ_LOGDUMP_DATA 0x00300000
+
+#define INIT_M_FIFO(name, type, dir, base) \
+ name.head = base + OFF_##type##_##dir##_HEAD; \
+ name.tail = base + OFF_##type##_##dir##_TAIL; \
+ name.data = base + OFF_##type##_##dir##_DATA; \
+ name.size = SIZ_##type##_DATA;
+
+/* onedram registers */
+
+/* Mailboxes are named based on who writes to them.
+ * MBOX_BP is written to by the (B)aseband (P)rocessor
+ * and only readable by the (A)pplication (P)rocessor.
+ * MBOX_AP is the opposite.
+ */
+#define OFF_SEM 0xFFF800
+#define OFF_MBOX_BP 0xFFF820
+#define OFF_MBOX_AP 0xFFF840
+#define OFF_CHECK_BP 0xFFF8A0
+#define OFF_CHECK_AP 0xFFF8C0
+
+#endif
diff --git a/drivers/misc/samsung_modemctl/modem_ctl_recovery.h b/drivers/misc/samsung_modemctl/modem_ctl_recovery.h
new file mode 100755
index 0000000..6d62e9f
--- /dev/null
+++ b/drivers/misc/samsung_modemctl/modem_ctl_recovery.h
@@ -0,0 +1,85 @@
+#ifndef __MODEM_CTL_RECOVERY_H__
+#define __MODEM_CTL_RECOVERY_H__
+
+/* The below macros define the offsets from the base shared memory */
+#define DPRAM_BOOT_MAGIC_ADDR 0x00
+#define DPRAM_BOOT_TYPE_ADDR 0x04
+#define DPRAM_MODEM_STATUS_ADDR 0x08
+#define DPRAM_AP_STATUS_ADDR 0x0C
+#define DPRAM_FIRMWARE_SIZE_ADDR 0x10
+#define DPRAM_MODEM_STRING_MSG_ADDR 0x100
+#define DPRAM_FIRMWARE_ADDR 0x1000
+
+/* Max. length of the message from modem */
+#define DPRAM_MODEM_MSG_SIZE 0x100
+
+#define DPRAM_BOOT_MAGIC_RECOVERY_FOTA 0x56434552
+#define DPRAM_BOOT_TYPE_DPRAM_DELTA 0x41544c44
+#define DPRAM_BOOT_SEM_REQ 0x5555ffff
+
+/* ioctl commands of updating modem binary */
+#define IOCTL_MODEM_FW_UPDATE _IO('D', 0x1)
+#define IOCTL_MODEM_CHK_STAT _IO('D', 0x2)
+#define IOCTL_MODEM_PWROFF _IO('D', 0x3)
+
+/*
+* All status values are kept through out the process.
+* So the final status value for a successful job will be 0xB60x1164
+* This means that magic code is B6xxxxxx
+* Job was started xxxxx1xx
+* Job is done 100% xxxxxx64 (0x64 is 100 in hex)
+* Job is completed xxxx1xxx
+* This way we can just check the final value and know the status of the job.
+*/
+#define STATUS_JOB_MAGIC_CODE 0xB6000000
+#define STATUS_JOB_MAGIC_M 0xFF000000
+#define STATUS_JOB_STARTED_M 0x00000100
+#define STATUS_JOB_PROGRESS_M 0x000000FF
+#define STATUS_JOB_COMPLETE_M 0x00001000
+#define STATUS_JOB_DEBUG_M 0x000F0000
+#define STATUS_JOB_ERROR_M 0x00F00000
+#define STATUS_JOB_ENDED_M (0x00F00000|0x00001000)
+
+
+#define DPRAM_MEMORY_SIZE 0xFFF800
+
+/* read modem delta file to the buffer of this type */
+struct dpram_firmware {
+ char *firmware;
+ int size;
+ int is_delta;
+};
+
+/* the progress status of modem updage */
+struct stat_info {
+ int pct;
+ char msg[DPRAM_MODEM_MSG_SIZE];
+};
+
+/* Define Full modem update interface between AP and modem */
+#define ONEDRAM_DL_SIGNATURE 0x4F4E
+#define ONEDRAM_DL_SMD_SIGNATURE 0x605F
+#define ONEDRAM_DL_COMPLETE 0x56781234
+#define ONEDRAM_DL_CHECKSUM_ERR 0x4444
+#define ONEDRAM_DL_ERASE_WRITE_ERR 0x77779999
+#define ONEDRAM_DL_BOOT_UPDATE_ERR 0xBBBBEEEE
+#define ONEDRAM_DL_REWRITE_FAIL_ERR 0xDDDDFFFF
+#define ONEDRAM_DL_DONE_AND_RESET 0xDDDDAAAA
+#define ONEDRAM_DL_LENGTH_CH_FAIL 0x55FF
+
+#define ONEDRAM_DL_HEADER_OFFSET 0x0
+#define ONEDRAM_DL_DATA_OFFSET 0x400
+
+/* typedefs */
+struct onedram_head_t {
+ u16 signature;
+ u8 is_boot_update;
+ u8 is_nv_update;
+ u32 length;
+ u32 checksum;
+} __packed;
+
+
+#endif /* __MODEM_CTL_RECOVERY_H__ */
+
+
diff --git a/drivers/misc/samsung_modemctl/modem_dbg.c b/drivers/misc/samsung_modemctl/modem_dbg.c
new file mode 100644
index 0000000..8a22dad
--- /dev/null
+++ b/drivers/misc/samsung_modemctl/modem_dbg.c
@@ -0,0 +1,211 @@
+/* modem_dbg.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ * Copyright (C) 2010 Samsung Electronics.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/debugfs.h>
+#include <linux/wakelock.h>
+#include <linux/miscdevice.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+
+#include "modem_ctl.h"
+#include "modem_ctl_p.h"
+
+static int crash_open(struct inode *inode, struct file *file)
+{
+ struct modemctl *mc = inode->i_private;
+ modem_force_crash(mc);
+ return 0;
+}
+
+static const struct file_operations crash_ops = {
+ .open = crash_open,
+};
+
+#define SHOW(name) seq_printf(sf, "%-20s %d\n", #name, stats->name)
+
+static int stats_show(struct seq_file *sf, void *unused)
+{
+ struct modemstats *stats = sf->private;
+
+ SHOW(request_no_wait);
+ SHOW(request_wait);
+
+ SHOW(release_no_action);
+ SHOW(release_bp_waiting);
+ SHOW(release_bp_signaled);
+
+ SHOW(bp_req_instant);
+ SHOW(bp_req_delayed);
+ SHOW(bp_req_confused);
+
+ SHOW(rx_unknown);
+ SHOW(rx_dropped);
+ SHOW(rx_purged);
+ SHOW(rx_received);
+
+ SHOW(tx_no_delay);
+ SHOW(tx_queued);
+ SHOW(tx_bp_signaled);
+ SHOW(tx_fifo_full);
+
+ SHOW(pipe_tx);
+ SHOW(pipe_rx);
+ SHOW(pipe_tx_delayed);
+ SHOW(pipe_rx_purged);
+
+ SHOW(resets);
+
+ return 0;
+}
+
+static int stats_open(struct inode *inode, struct file *file)
+{
+ struct modemctl *mc = inode->i_private;
+ struct modemstats *stats;
+ unsigned long int flags;
+ int ret;
+
+ stats = kzalloc(sizeof(*stats), GFP_KERNEL);
+ if (!stats)
+ return -ENOMEM;
+
+ spin_lock_irqsave(&mc->lock, flags);
+ memcpy(stats, &mc->stats, sizeof(*stats));
+ memset(&mc->stats, 0, sizeof(*stats));
+ spin_unlock_irqrestore(&mc->lock, flags);
+
+ ret = single_open(file, stats_show, stats);
+ if (ret)
+ kfree(stats);
+
+ return ret;
+}
+
+static int stats_release(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq = file->private_data;
+ struct modemstats *stats = seq->private;
+ int ret;
+ ret = single_release(inode, file);
+ kfree(stats);
+ return ret;
+}
+
+static const struct file_operations stats_ops = {
+ .open = stats_open,
+ .release = stats_release,
+ .read = seq_read,
+ .llseek = seq_lseek,
+};
+
+static int log_open(struct inode *inode, struct file *file)
+{
+ struct modemctl *mc = inode->i_private;
+ unsigned long int flags;
+ int ret = 0;
+
+ file->private_data = mc;
+
+ mutex_lock(&mc->ctl_lock);
+ if (mc->logdump) {
+ mutex_unlock(&mc->ctl_lock);
+ return -EBUSY;
+ }
+ mc->logdump = 1;
+ mutex_unlock(&mc->ctl_lock);
+
+ spin_lock_irqsave(&mc->lock, flags);
+ mc->logdump_data = 0;
+ pr_err("modem: send LOGDUMP\n");
+ writel(MODEM_CMD_LOGDUMP_START, mc->mmio + OFF_MBOX_AP);
+ spin_unlock_irqrestore(&mc->lock, flags);
+
+ ret = wait_event_timeout(mc->wq, mc->logdump_data, 10 * HZ);
+ if (ret == 0) {
+ mutex_lock(&mc->ctl_lock);
+ mc->logdump = 0;
+ mutex_unlock(&mc->ctl_lock);
+ return -ETIMEDOUT;
+ } else {
+ return 0;
+ }
+}
+
+static int log_release(struct inode *inode, struct file *file)
+{
+ struct modemctl *mc = file->private_data;
+ mutex_lock(&mc->ctl_lock);
+ mc->logdump = 0;
+ mutex_unlock(&mc->ctl_lock);
+ return 0;
+}
+
+static ssize_t log_read(struct file *filp, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct modemctl *mc = filp->private_data;
+ loff_t pos = *ppos;
+ int ret;
+
+ if (pos < 0)
+ return -EINVAL;
+ if (pos >= SIZ_LOGDUMP_DATA)
+ return 0;
+
+ ret = modem_acquire_mmio(mc);
+ if (ret)
+ return ret;
+
+ mutex_lock(&mc->ctl_lock);
+ if (count > SIZ_LOGDUMP_DATA - pos)
+ count = SIZ_LOGDUMP_DATA - pos;
+ ret = copy_to_user(buf, mc->mmio + OFF_LOGDUMP_DATA + pos, count);
+ if (ret) {
+ ret = -EFAULT;
+ } else {
+ pos += count;
+ ret = count;
+ }
+ *ppos = pos;
+ mutex_unlock(&mc->ctl_lock);
+
+ modem_release_mmio(mc, 0);
+ return ret;
+}
+
+static const struct file_operations log_ops = {
+ .open = log_open,
+ .release = log_release,
+ .read = log_read,
+};
+
+void modem_debugfs_init(struct modemctl *mc)
+{
+ struct dentry *dent;
+
+ dent = debugfs_create_dir("modemctl", 0);
+ if (IS_ERR(dent))
+ return;
+
+ debugfs_create_file("crash", 0200, dent, mc, &crash_ops);
+ debugfs_create_file("stats", 0444, dent, mc, &stats_ops);
+ debugfs_create_file("log", 0440, dent, mc, &log_ops);
+}
diff --git a/drivers/misc/samsung_modemctl/modem_io.c b/drivers/misc/samsung_modemctl/modem_io.c
new file mode 100644
index 0000000..5c815ef
--- /dev/null
+++ b/drivers/misc/samsung_modemctl/modem_io.c
@@ -0,0 +1,724 @@
+/* modem_io.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ * Copyright (C) 2010 Samsung Electronics.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/* TODO
+ * - on modem crash return -ENODEV from recv/send, poll==readable
+ * - ensure all modem off/reset cases fault out io properly
+ * - request thread irq?
+ * - stats/debugfs
+ * - purge txq on restart
+ * - test, test, test
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <linux/if.h>
+#include <linux/if_arp.h>
+
+#include <linux/circ_buf.h>
+#include <linux/wakelock.h>
+
+#include "modem_ctl.h"
+#include "modem_ctl_p.h"
+
+#define RAW_CH_VNET0 10
+#define CHANNEL_TO_NETDEV_ID(id) (id - RAW_CH_VNET0)
+#define NETDEV_TO_CHANNEL_ID(id) (id + RAW_CH_VNET0)
+
+/* general purpose fifo access routines */
+
+typedef void * (*copyfunc)(void *, const void *, __kernel_size_t);
+
+static void *x_copy_to_user(void *dst, const void *src, __kernel_size_t sz)
+{
+ if (copy_to_user((void __user *) dst, src, sz) != 0)
+ pr_err("modemctl: cannot copy userdata\n");
+ return dst;
+}
+
+static void *x_copy_from_user(void *dst, const void *src, __kernel_size_t sz)
+{
+ if (copy_from_user(dst, (const void __user *) src, sz) != 0)
+ pr_err("modemctl: cannot copy userdata\n");
+ return dst;
+}
+
+static unsigned _fifo_read(struct m_fifo *q, void *dst,
+ unsigned count, copyfunc copy)
+{
+ unsigned n;
+ unsigned head = *q->head;
+ unsigned tail = *q->tail;
+ unsigned size = q->size;
+
+ if (CIRC_CNT(head, tail, size) < count)
+ return 0;
+
+ n = CIRC_CNT_TO_END(head, tail, size);
+
+ if (likely(n >= count)) {
+ copy(dst, q->data + tail, count);
+ } else {
+ copy(dst, q->data + tail, n);
+ copy(dst + n, q->data, count - n);
+ }
+ *q->tail = (tail + count) & (size - 1);
+
+ return count;
+}
+
+static unsigned _fifo_write(struct m_fifo *q, void *src,
+ unsigned count, copyfunc copy)
+{
+ unsigned n;
+ unsigned head = *q->head;
+ unsigned tail = *q->tail;
+ unsigned size = q->size;
+
+ if (CIRC_SPACE(head, tail, size) < count)
+ return 0;
+
+ n = CIRC_SPACE_TO_END(head, tail, size);
+
+ if (likely(n >= count)) {
+ copy(q->data + head, src, count);
+ } else {
+ copy(q->data + head, src, n);
+ copy(q->data, src + n, count - n);
+ }
+ *q->head = (head + count) & (size - 1);
+
+ return count;
+}
+
+static void fifo_purge(struct m_fifo *q)
+{
+ *q->head = 0;
+ *q->tail = 0;
+}
+
+static unsigned fifo_skip(struct m_fifo *q, unsigned count)
+{
+ if (CIRC_CNT(*q->head, *q->tail, q->size) < count)
+ return 0;
+ *q->tail = (*q->tail + count) & (q->size - 1);
+ return count;
+}
+
+#define fifo_read(q, dst, count) \
+ _fifo_read(q, dst, count, memcpy)
+#define fifo_read_user(q, dst, count) \
+ _fifo_read(q, dst, count, x_copy_to_user)
+
+#define fifo_write(q, src, count) \
+ _fifo_write(q, src, count, memcpy)
+#define fifo_write_user(q, src, count) \
+ _fifo_write(q, src, count, x_copy_from_user)
+
+#define fifo_count(mf) CIRC_CNT(*(mf)->head, *(mf)->tail, (mf)->size)
+#define fifo_space(mf) CIRC_SPACE(*(mf)->head, *(mf)->tail, (mf)->size)
+
+static void fifo_dump(const char *tag, struct m_fifo *q,
+ unsigned start, unsigned count)
+{
+ if (count > 64)
+ count = 64;
+
+ if ((start + count) <= q->size) {
+ print_hex_dump_bytes(tag, DUMP_PREFIX_ADDRESS,
+ q->data + start, count);
+ } else {
+ print_hex_dump_bytes(tag, DUMP_PREFIX_ADDRESS,
+ q->data + start, q->size - start);
+ print_hex_dump_bytes(tag, DUMP_PREFIX_ADDRESS,
+ q->data, count - (q->size - start));
+ }
+}
+
+
+
+/* Called with mc->lock held whenever we gain access
+ * to the mmio region.
+ */
+void modem_update_state(struct modemctl *mc)
+{
+ /* update our idea of space available in fifos */
+ mc->fmt_tx.avail = fifo_space(&mc->fmt_tx);
+ mc->fmt_rx.avail = fifo_count(&mc->fmt_rx);
+ if (mc->fmt_rx.avail)
+ wake_lock(&mc->cmd_pipe.wakelock);
+ else
+ wake_unlock(&mc->cmd_pipe.wakelock);
+
+ mc->rfs_tx.avail = fifo_space(&mc->rfs_tx);
+ mc->rfs_rx.avail = fifo_count(&mc->rfs_rx);
+ if (mc->rfs_rx.avail)
+ wake_lock(&mc->rfs_pipe.wakelock);
+ else
+ wake_unlock(&mc->rfs_pipe.wakelock);
+
+ mc->raw_tx.avail = fifo_space(&mc->raw_tx);
+ mc->raw_rx.avail = fifo_count(&mc->raw_rx);
+
+ /* wake up blocked or polling read/write operations */
+ wake_up(&mc->wq);
+}
+
+void modem_update_pipe(struct m_pipe *pipe)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&pipe->mc->lock, flags);
+ pipe->tx->avail = fifo_space(pipe->tx);
+ pipe->rx->avail = fifo_count(pipe->rx);
+ if (pipe->rx->avail)
+ wake_lock(&pipe->wakelock);
+ else
+ wake_unlock(&pipe->wakelock);
+ spin_unlock_irqrestore(&pipe->mc->lock, flags);
+}
+
+
+/* must be called with pipe->tx_lock held */
+static int modem_pipe_send(struct m_pipe *pipe, struct modem_io *io)
+{
+ char hdr[M_PIPE_MAX_HDR];
+ static char ftr = 0x7e;
+ unsigned size;
+ int ret;
+
+ ret = pipe->push_header(io, hdr);
+ if (ret)
+ return ret;
+
+ size = io->size + pipe->header_size + 1;
+
+ if (io->size > 0x10000000)
+ return -EINVAL;
+ if (size >= (pipe->tx->size - 1))
+ return -EINVAL;
+
+ for (;;) {
+ ret = modem_acquire_mmio(pipe->mc);
+ if (ret)
+ return ret;
+
+ modem_update_pipe(pipe);
+
+ if (pipe->tx->avail >= size) {
+ fifo_write(pipe->tx, hdr, pipe->header_size);
+ fifo_write_user(pipe->tx, io->data, io->size);
+ fifo_write(pipe->tx, &ftr, 1);
+ modem_update_pipe(pipe);
+ modem_release_mmio(pipe->mc, pipe->tx->bits);
+ MODEM_COUNT(pipe->mc, pipe_tx);
+ return 0;
+ }
+
+ pr_info("modem_pipe_send: wait for space\n");
+ MODEM_COUNT(pipe->mc, pipe_tx_delayed);
+ modem_release_mmio(pipe->mc, 0);
+
+ ret = wait_event_interruptible_timeout(
+ pipe->mc->wq,
+ (pipe->tx->avail >= size) || modem_offline(pipe->mc),
+ 5 * HZ);
+ if (ret == 0)
+ return -ENODEV;
+ if (ret < 0)
+ return ret;
+ }
+}
+
+static int modem_pipe_read(struct m_pipe *pipe, struct modem_io *io)
+{
+ unsigned data_size = io->size;
+ char hdr[M_PIPE_MAX_HDR];
+ int ret;
+
+ if (fifo_read(pipe->rx, hdr, pipe->header_size) == 0)
+ return -EAGAIN;
+
+ ret = pipe->pull_header(io, hdr);
+ if (ret)
+ return ret;
+
+ if (data_size < io->size) {
+ pr_info("modem_pipe_read: discarding packet (%d)\n", io->size);
+ if (fifo_skip(pipe->rx, io->size + 1) != (io->size + 1))
+ return -EIO;
+ return -EAGAIN;
+ } else {
+ if (fifo_read_user(pipe->rx, io->data, io->size) != io->size)
+ return -EIO;
+ if (fifo_skip(pipe->rx, 1) != 1)
+ return -EIO;
+ }
+ return 0;
+}
+
+/* must be called with pipe->rx_lock held */
+static int modem_pipe_recv(struct m_pipe *pipe, struct modem_io *io)
+{
+ int ret;
+
+ ret = modem_acquire_mmio(pipe->mc);
+ if (ret)
+ return ret;
+
+ ret = modem_pipe_read(pipe, io);
+
+ modem_update_pipe(pipe);
+
+ if ((ret != 0) && (ret != -EAGAIN)) {
+ pr_err("[MODEM] purging %s fifo\n", pipe->dev.name);
+ fifo_purge(pipe->rx);
+ MODEM_COUNT(pipe->mc, pipe_rx_purged);
+ } else if (ret == 0) {
+ MODEM_COUNT(pipe->mc, pipe_rx);
+ }
+
+ modem_release_mmio(pipe->mc, 0);
+
+ return ret;
+}
+
+struct raw_hdr {
+ u8 start;
+ u32 len;
+ u8 channel;
+ u8 control;
+} __attribute__ ((packed));
+
+struct vnet {
+ struct modemctl *mc;
+ struct sk_buff_head txq;
+ int rmnet_ch_id;
+};
+
+static void handle_raw_rx(struct modemctl *mc)
+{
+ struct raw_hdr raw;
+ struct sk_buff *skb = NULL;
+ int recvdata = 0;
+
+ /* process inbound packets */
+ while (fifo_read(&mc->raw_rx, &raw, sizeof(raw)) == sizeof(raw)) {
+ struct net_device *dev;
+ unsigned sz = raw.len - (sizeof(raw) - 1);
+
+ if (unlikely(!(raw.channel >= RAW_CH_VNET0 && raw.channel <
+ NETDEV_TO_CHANNEL_ID(mc->num_pdp_contexts)))) {
+
+ MODEM_COUNT(mc, rx_unknown);
+ pr_err("[VNET] unknown channel %d\n", raw.channel);
+ if (fifo_skip(&mc->raw_rx, sz + 1) != (sz + 1))
+ goto purge_raw_fifo;
+ continue;
+ }
+ dev = mc->ndev[CHANNEL_TO_NETDEV_ID(raw.channel)];
+ skb = dev_alloc_skb(sz + NET_IP_ALIGN);
+ if (skb == NULL) {
+ MODEM_COUNT(mc, rx_dropped);
+ /* TODO: consider timer + retry instead of drop? */
+ pr_err("[VNET] cannot alloc %d byte packet\n", sz);
+ if (fifo_skip(&mc->raw_rx, sz + 1) != (sz + 1))
+ goto purge_raw_fifo;
+ continue;
+ }
+ skb->dev = dev;
+ skb_reserve(skb, NET_IP_ALIGN);
+
+ if (fifo_read(&mc->raw_rx, skb_put(skb, sz), sz) != sz)
+ goto purge_raw_fifo;
+ if (fifo_skip(&mc->raw_rx, 1) != 1)
+ goto purge_raw_fifo;
+
+ /* Get the ethertype from the version in the IP header. */
+ if (skb->data[0] >> 4 == 6)
+ skb->protocol = __constant_htons(ETH_P_IPV6);
+ else
+ skb->protocol = __constant_htons(ETH_P_IP);
+ skb_reset_mac_header(skb);
+
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += skb->len;
+
+ netif_rx(skb);
+ recvdata = 1;
+ MODEM_COUNT(mc, rx_received);
+ }
+
+ if (recvdata)
+ wake_lock_timeout(&mc->ip_rx_wakelock, HZ * 2);
+ return;
+
+purge_raw_fifo:
+ if (skb)
+ dev_kfree_skb_irq(skb);
+ pr_err("[VNET] purging raw rx fifo!\n");
+ fifo_purge(&mc->raw_tx);
+ MODEM_COUNT(mc, rx_purged);
+}
+
+int handle_raw_tx(struct modemctl *mc, struct sk_buff *skb)
+{
+ struct raw_hdr raw;
+ unsigned char ftr = 0x7e;
+ unsigned sz;
+ int netdev_id;
+ struct vnet *vn = netdev_priv(skb->dev);
+
+
+ sz = skb->len + sizeof(raw) + 1;
+
+ if (fifo_space(&mc->raw_tx) < sz) {
+ MODEM_COUNT(mc, tx_fifo_full);
+ return -1;
+ }
+
+ raw.start = 0x7f;
+ raw.len = 6 + skb->len;
+ raw.channel = vn->rmnet_ch_id;
+ raw.control = 0;
+
+ fifo_write(&mc->raw_tx, &raw, sizeof(raw));
+ fifo_write(&mc->raw_tx, skb->data, skb->len);
+ fifo_write(&mc->raw_tx, &ftr, 1);
+
+ netdev_id = CHANNEL_TO_NETDEV_ID(vn->rmnet_ch_id);
+ mc->ndev[netdev_id]->stats.tx_packets++;
+ mc->ndev[netdev_id]->stats.tx_bytes += skb->len;
+
+ mc->mmio_signal_bits |= MBD_SEND_RAW;
+
+ dev_kfree_skb_irq(skb);
+ return 0;
+}
+
+void modem_handle_io(struct modemctl *mc)
+{
+ struct sk_buff *skb;
+ struct vnet *vn;
+ int i;
+ int cnt = 0;
+
+ handle_raw_rx(mc);
+
+ for (i = 0; i < mc->num_pdp_contexts; i++) {
+ vn = netdev_priv(mc->ndev[i]);
+ while ((skb = skb_dequeue(&vn->txq)))
+ if (handle_raw_tx(mc, skb)) {
+ skb_queue_head(&vn->txq, skb);
+ break;
+ }
+ if (skb == NULL)
+ cnt++;
+ }
+ if (cnt == mc->num_pdp_contexts)
+ wake_unlock(&mc->ip_tx_wakelock);
+}
+
+static int vnet_open(struct net_device *ndev)
+{
+ netif_start_queue(ndev);
+ return 0;
+}
+
+static int vnet_stop(struct net_device *ndev)
+{
+ netif_stop_queue(ndev);
+ return 0;
+}
+
+static int vnet_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+ struct vnet *vn = netdev_priv(ndev);
+ struct modemctl *mc = vn->mc;
+ unsigned long flags;
+
+ spin_lock_irqsave(&mc->lock, flags);
+ if (readl(mc->mmio + OFF_SEM) & 1) {
+ /* if we happen to hold the hw mmio sem, transmit NOW */
+ if (handle_raw_tx(mc, skb)) {
+ wake_lock(&mc->ip_tx_wakelock);
+ skb_queue_tail(&vn->txq, skb);
+ } else {
+ MODEM_COUNT(mc, tx_no_delay);
+ }
+ if (!mc->mmio_owner) {
+ /* if we don't own the semaphore, immediately
+ * give it back to the modem and signal the modem
+ * to process the packet
+ */
+ writel(0, mc->mmio + OFF_SEM);
+ writel(MB_VALID | MBD_SEND_RAW,
+ mc->mmio + OFF_MBOX_AP);
+ MODEM_COUNT(mc, tx_bp_signaled);
+ }
+ } else {
+ /* otherwise request the hw mmio sem and queue */
+ modem_request_sem(mc);
+ skb_queue_tail(&vn->txq, skb);
+ MODEM_COUNT(mc, tx_queued);
+ }
+ spin_unlock_irqrestore(&mc->lock, flags);
+
+ return NETDEV_TX_OK;
+}
+
+static struct net_device_ops vnet_ops = {
+ .ndo_open = vnet_open,
+ .ndo_stop = vnet_stop,
+ .ndo_start_xmit = vnet_xmit,
+};
+
+static void vnet_setup(struct net_device *ndev)
+{
+ ndev->netdev_ops = &vnet_ops;
+ ndev->type = ARPHRD_PPP;
+ ndev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
+ ndev->hard_header_len = 0;
+ ndev->addr_len = 0;
+ ndev->tx_queue_len = 1000;
+ ndev->mtu = ETH_DATA_LEN;
+ ndev->watchdog_timeo = 5 * HZ;
+}
+
+struct fmt_hdr {
+ u8 start;
+ u16 len;
+ u8 control;
+} __attribute__ ((packed));
+
+static int push_fmt_header(struct modem_io *io, void *header)
+{
+ struct fmt_hdr *fh = header;
+
+ if (io->id)
+ return -EINVAL;
+ if (io->cmd)
+ return -EINVAL;
+ fh->start = 0x7f;
+ fh->len = io->size + 3;
+ fh->control = 0;
+ return 0;
+}
+
+static int pull_fmt_header(struct modem_io *io, void *header)
+{
+ struct fmt_hdr *fh = header;
+
+ if (fh->start != 0x7f)
+ return -EINVAL;
+ if (fh->control != 0x00)
+ return -EINVAL;
+ if (fh->len < 3)
+ return -EINVAL;
+ io->size = fh->len - 3;
+ io->id = 0;
+ io->cmd = 0;
+ return 0;
+}
+
+struct rfs_hdr {
+ u8 start;
+ u32 len;
+ u8 cmd;
+ u8 id;
+} __attribute__ ((packed));
+
+static int push_rfs_header(struct modem_io *io, void *header)
+{
+ struct rfs_hdr *rh = header;
+
+ if (io->id > 0xFF)
+ return -EINVAL;
+ if (io->cmd > 0xFF)
+ return -EINVAL;
+ rh->start = 0x7f;
+ rh->len = io->size + 6;
+ rh->id = io->id;
+ rh->cmd = io->cmd;
+ return 0;
+}
+
+static int pull_rfs_header(struct modem_io *io, void *header)
+{
+ struct rfs_hdr *rh = header;
+
+ if (rh->start != 0x7f)
+ return -EINVAL;
+ if (rh->len < 6)
+ return -EINVAL;
+ io->size = rh->len - 6;
+ io->id = rh->id;
+ io->cmd = rh->cmd;
+ return 0;
+}
+
+static int pipe_open(struct inode *inode, struct file *filp)
+{
+ struct m_pipe *pipe = to_m_pipe(filp->private_data);
+ filp->private_data = pipe;
+ return 0;
+}
+
+static long pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long _arg)
+{
+ void __user *arg = (void *) _arg;
+ struct m_pipe *pipe = filp->private_data;
+ struct modem_io mio;
+ int ret;
+
+ switch (cmd) {
+ case IOCTL_MODEM_SEND:
+ if (copy_from_user(&mio, arg, sizeof(mio)) != 0)
+ return -EFAULT;
+ if (mutex_lock_interruptible(&pipe->tx_lock))
+ return -EINTR;
+ ret = modem_pipe_send(pipe, &mio);
+ mutex_unlock(&pipe->tx_lock);
+ return ret;
+
+ case IOCTL_MODEM_RECV:
+ if (copy_from_user(&mio, arg, sizeof(mio)) != 0)
+ return -EFAULT;
+ if (mutex_lock_interruptible(&pipe->rx_lock))
+ return -EINTR;
+ ret = modem_pipe_recv(pipe, &mio);
+ mutex_unlock(&pipe->rx_lock);
+ if (copy_to_user(arg, &mio, sizeof(mio)) != 0)
+ return -EFAULT;
+ return ret;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static unsigned int pipe_poll(struct file *filp, poll_table *wait)
+{
+ unsigned long flags;
+ struct m_pipe *pipe = filp->private_data;
+ int ret;
+
+ poll_wait(filp, &pipe->mc->wq, wait);
+
+ spin_lock_irqsave(&pipe->mc->lock, flags);
+ if (pipe->rx->avail || modem_offline(pipe->mc))
+ ret = POLLIN | POLLRDNORM;
+ else
+ ret = 0;
+ spin_unlock_irqrestore(&pipe->mc->lock, flags);
+
+ return ret;
+}
+
+static const struct file_operations modem_io_fops = {
+ .owner = THIS_MODULE,
+ .open = pipe_open,
+ .poll = pipe_poll,
+ .unlocked_ioctl = pipe_ioctl,
+};
+
+static int modem_pipe_register(struct m_pipe *pipe, const char *devname)
+{
+ pipe->dev.minor = MISC_DYNAMIC_MINOR;
+ pipe->dev.name = devname;
+ pipe->dev.fops = &modem_io_fops;
+
+ wake_lock_init(&pipe->wakelock, WAKE_LOCK_SUSPEND, devname);
+
+ mutex_init(&pipe->tx_lock);
+ mutex_init(&pipe->rx_lock);
+ return misc_register(&pipe->dev);
+}
+
+int modem_io_init(struct modemctl *mc, void __iomem *mmio)
+{
+ struct vnet *vn;
+ int r;
+ int i;
+ int ch_id;
+
+ INIT_M_FIFO(mc->fmt_tx, FMT, TX, mmio);
+ INIT_M_FIFO(mc->fmt_rx, FMT, RX, mmio);
+ INIT_M_FIFO(mc->raw_tx, RAW, TX, mmio);
+ INIT_M_FIFO(mc->raw_rx, RAW, RX, mmio);
+ INIT_M_FIFO(mc->rfs_tx, RFS, TX, mmio);
+ INIT_M_FIFO(mc->rfs_rx, RFS, RX, mmio);
+
+ mc->ndev = kmalloc(sizeof(struct net_device *) * mc->num_pdp_contexts,
+ GFP_KERNEL);
+ if (!mc->ndev) {
+ pr_err("memory allocation failed for netdev\n");
+ return -ENOMEM;
+ }
+ for (i = 0, ch_id = RAW_CH_VNET0; i < mc->num_pdp_contexts;
+ i++, ch_id++) {
+ mc->ndev[i] = alloc_netdev(0, "rmnet%d", vnet_setup);
+ if (mc->ndev[i]) {
+ vn = netdev_priv(mc->ndev[i]);
+ vn->mc = mc;
+ vn->rmnet_ch_id = ch_id;
+ skb_queue_head_init(&vn->txq);
+ r = register_netdev(mc->ndev[i]);
+ if (r) {
+ free_netdev(mc->ndev[i]);
+ pr_err("failed to register rmnet%d\n", i);
+ goto free;
+ }
+ } else {
+ pr_err("failed to alloc rmnet%d\n", i);
+ goto free;
+ }
+ }
+
+ mc->cmd_pipe.tx = &mc->fmt_tx;
+ mc->cmd_pipe.rx = &mc->fmt_rx;
+ mc->cmd_pipe.tx->bits = MBD_SEND_FMT;
+ mc->cmd_pipe.push_header = push_fmt_header;
+ mc->cmd_pipe.pull_header = pull_fmt_header;
+ mc->cmd_pipe.header_size = sizeof(struct fmt_hdr);
+ mc->cmd_pipe.mc = mc;
+ if (modem_pipe_register(&mc->cmd_pipe, "modem_fmt"))
+ pr_err("failed to register modem_fmt pipe\n");
+
+ mc->rfs_pipe.tx = &mc->rfs_tx;
+ mc->rfs_pipe.rx = &mc->rfs_rx;
+ mc->rfs_pipe.tx->bits = MBD_SEND_RFS;
+ mc->rfs_pipe.push_header = push_rfs_header;
+ mc->rfs_pipe.pull_header = pull_rfs_header;
+ mc->rfs_pipe.header_size = sizeof(struct rfs_hdr);
+ mc->rfs_pipe.mc = mc;
+ if (modem_pipe_register(&mc->rfs_pipe, "modem_rfs"))
+ pr_err("failed to register modem_rfs pipe\n");
+
+ return 0;
+
+free:
+ /* Unregister and free any alloced netdevs */
+ while (--i >= 0) {
+ unregister_netdev(mc->ndev[i]);
+ free_netdev(mc->ndev[i]);
+ }
+ return -ENOMEM;
+}
diff --git a/drivers/misc/sec_jack.c b/drivers/misc/sec_jack.c
new file mode 100755
index 0000000..c64cfb8
--- /dev/null
+++ b/drivers/misc/sec_jack.c
@@ -0,0 +1,495 @@
+/* drivers/misc/sec_jack.c
+ *
+ * Copyright (C) 2010 Samsung Electronics Co.Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/switch.h>
+#include <linux/input.h>
+#include <linux/timer.h>
+#include <linux/wakelock.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/gpio_event.h>
+#include <linux/sec_jack.h>
+
+#define MAX_ZONE_LIMIT 10
+#define SEND_KEY_CHECK_TIME_MS 30 /* 30ms */
+#define DET_CHECK_TIME_MS 200 /* 200ms */
+#define WAKE_LOCK_TIME (HZ * 5) /* 5 sec */
+
+struct sec_jack_info {
+ struct sec_jack_platform_data *pdata;
+ struct delayed_work jack_detect_work;
+ struct work_struct buttons_work;
+ struct workqueue_struct *queue;
+ struct input_dev *input_dev;
+ struct wake_lock det_wake_lock;
+ struct sec_jack_zone *zone;
+ struct input_handler handler;
+ struct input_handle handle;
+ struct input_device_id ids;
+ int det_irq;
+ int dev_id;
+ int pressed;
+ int pressed_code;
+ struct platform_device *send_key_dev;
+ unsigned int cur_jack_type;
+};
+
+/* with some modifications like moving all the gpio structs inside
+ * the platform data and getting the name for the switch and
+ * gpio_event from the platform data, the driver could support more than
+ * one headset jack, but currently user space is looking only for
+ * one key file and switch for a headset so it'd be overkill and
+ * untestable so we limit to one instantiation for now.
+ */
+static atomic_t instantiated = ATOMIC_INIT(0);
+
+/* sysfs name HeadsetObserver.java looks for to track headset state
+ */
+struct switch_dev switch_jack_detection = {
+ .name = "h2w",
+};
+
+static struct gpio_event_direct_entry sec_jack_key_map[] = {
+ {
+ .code = KEY_UNKNOWN,
+ },
+};
+
+static struct gpio_event_input_info sec_jack_key_info = {
+ .info.func = gpio_event_input_func,
+ .info.no_suspend = true,
+ .type = EV_KEY,
+ .debounce_time.tv64 = SEND_KEY_CHECK_TIME_MS * NSEC_PER_MSEC,
+ .keymap = sec_jack_key_map,
+ .keymap_size = ARRAY_SIZE(sec_jack_key_map)
+};
+
+static struct gpio_event_info *sec_jack_input_info[] = {
+ &sec_jack_key_info.info,
+};
+
+static struct gpio_event_platform_data sec_jack_input_data = {
+ .name = "sec_jack",
+ .info = sec_jack_input_info,
+ .info_count = ARRAY_SIZE(sec_jack_input_info),
+};
+
+/* gpio_input driver does not support to read adc value.
+ * We use input filter to support 3-buttons of headset
+ * without changing gpio_input driver.
+ */
+static bool sec_jack_buttons_filter(struct input_handle *handle,
+ unsigned int type, unsigned int code,
+ int value)
+{
+ struct sec_jack_info *hi = handle->handler->private;
+
+ if (type != EV_KEY || code != KEY_UNKNOWN)
+ return false;
+
+ hi->pressed = value;
+
+ /* This is called in timer handler of gpio_input driver.
+ * We use workqueue to read adc value.
+ */
+ queue_work(hi->queue, &hi->buttons_work);
+
+ return true;
+}
+
+static int sec_jack_buttons_connect(struct input_handler *handler,
+ struct input_dev *dev,
+ const struct input_device_id *id)
+{
+ struct sec_jack_info *hi;
+ struct sec_jack_platform_data *pdata;
+ struct sec_jack_buttons_zone *btn_zones;
+ int err;
+ int i;
+
+ /* bind input_handler to input device related to only sec_jack */
+ if (dev->name != sec_jack_input_data.name)
+ return -ENODEV;
+
+ hi = handler->private;
+ pdata = hi->pdata;
+ btn_zones = pdata->buttons_zones;
+
+ hi->input_dev = dev;
+ hi->handle.dev = dev;
+ hi->handle.handler = handler;
+ hi->handle.open = 0;
+ hi->handle.name = "sec_jack_buttons";
+
+ err = input_register_handle(&hi->handle);
+ if (err) {
+ pr_err("%s: Failed to register sec_jack buttons handle, "
+ "error %d\n", __func__, err);
+ goto err_register_handle;
+ }
+
+ err = input_open_device(&hi->handle);
+ if (err) {
+ pr_err("%s: Failed to open input device, error %d\n",
+ __func__, err);
+ goto err_open_device;
+ }
+
+ for (i = 0; i < pdata->num_buttons_zones; i++)
+ input_set_capability(dev, EV_KEY, btn_zones[i].code);
+
+ return 0;
+
+ err_open_device:
+ input_unregister_handle(&hi->handle);
+ err_register_handle:
+
+ return err;
+}
+
+static void sec_jack_buttons_disconnect(struct input_handle *handle)
+{
+ input_close_device(handle);
+ input_unregister_handle(handle);
+}
+
+static void sec_jack_set_type(struct sec_jack_info *hi, int jack_type)
+{
+ struct sec_jack_platform_data *pdata = hi->pdata;
+
+ /* this can happen during slow inserts where we think we identified
+ * the type but then we get another interrupt and do it again
+ */
+ if (jack_type == hi->cur_jack_type)
+ return;
+
+ if (jack_type == SEC_HEADSET_4POLE) {
+ /* for a 4 pole headset, enable detection of send/end key */
+ if (hi->send_key_dev == NULL)
+ /* enable to get events again */
+ hi->send_key_dev = platform_device_register_data(NULL,
+ GPIO_EVENT_DEV_NAME,
+ hi->dev_id,
+ &sec_jack_input_data,
+ sizeof(sec_jack_input_data));
+ } else {
+ /* for all other jacks, disable send/end key detection */
+ if (hi->send_key_dev != NULL) {
+ /* disable to prevent false events on next insert */
+ platform_device_unregister(hi->send_key_dev);
+ hi->send_key_dev = NULL;
+ }
+ /* micbias is left enabled for 4pole and disabled otherwise */
+ pdata->set_micbias_state(false);
+ }
+
+ hi->cur_jack_type = jack_type;
+ pr_info("%s : jack_type = %d\n", __func__, jack_type);
+
+ /* prevent suspend to allow user space to respond to switch */
+ wake_lock_timeout(&hi->det_wake_lock, WAKE_LOCK_TIME);
+
+ switch_set_state(&switch_jack_detection, jack_type);
+}
+
+static void handle_jack_not_inserted(struct sec_jack_info *hi)
+{
+ sec_jack_set_type(hi, SEC_JACK_NO_DEVICE);
+ hi->pdata->set_micbias_state(false);
+}
+
+static void determine_jack_type(struct sec_jack_info *hi)
+{
+ struct sec_jack_zone *zones = hi->pdata->zones;
+ int size = hi->pdata->num_zones;
+ int count[MAX_ZONE_LIMIT] = {0};
+ int adc;
+ int i;
+ unsigned npolarity = !hi->pdata->det_active_high;
+
+ while (gpio_get_value(hi->pdata->det_gpio) ^ npolarity) {
+ adc = hi->pdata->get_adc_value();
+ pr_debug("%s: adc = %d\n", __func__, adc);
+
+ /* determine the type of headset based on the
+ * adc value. An adc value can fall in various
+ * ranges or zones. Within some ranges, the type
+ * can be returned immediately. Within others, the
+ * value is considered unstable and we need to sample
+ * a few more types (up to the limit determined by
+ * the range) before we return the type for that range.
+ */
+ for (i = 0; i < size; i++) {
+ if (adc <= zones[i].adc_high) {
+ if (++count[i] > zones[i].check_count) {
+ sec_jack_set_type(hi,
+ zones[i].jack_type);
+ return;
+ }
+ msleep(zones[i].delay_ms);
+ break;
+ }
+ }
+ }
+ /* jack removed before detection complete */
+ pr_debug("%s : jack removed before detection complete\n", __func__);
+ handle_jack_not_inserted(hi);
+}
+
+/* thread run whenever the headset detect state changes (either insertion
+ * or removal).
+ */
+static irqreturn_t sec_jack_detect_irq_thread(int irq, void *dev_id)
+{
+ struct sec_jack_info *hi = dev_id;
+ struct sec_jack_platform_data *pdata = hi->pdata;
+ int time_left_ms = DET_CHECK_TIME_MS;
+ unsigned npolarity = !hi->pdata->det_active_high;
+
+ /* set mic bias to enable adc */
+ pdata->set_micbias_state(true);
+
+ /* debounce headset jack. don't try to determine the type of
+ * headset until the detect state is true for a while.
+ */
+ while (time_left_ms > 0) {
+ if (!(gpio_get_value(hi->pdata->det_gpio) ^ npolarity)) {
+ /* jack not detected. */
+ handle_jack_not_inserted(hi);
+ return IRQ_HANDLED;
+ }
+ msleep(10);
+ time_left_ms -= 10;
+ }
+ /* jack presence was detected the whole time, figure out which type */
+ determine_jack_type(hi);
+ return IRQ_HANDLED;
+}
+
+/* thread run whenever the button of headset is pressed or released */
+void sec_jack_buttons_work(struct work_struct *work)
+{
+ struct sec_jack_info *hi =
+ container_of(work, struct sec_jack_info, buttons_work);
+ struct sec_jack_platform_data *pdata = hi->pdata;
+ struct sec_jack_buttons_zone *btn_zones = pdata->buttons_zones;
+ int adc;
+ int i;
+
+ /* when button is released */
+ if (hi->pressed == 0) {
+ input_report_key(hi->input_dev, hi->pressed_code, 0);
+ input_sync(hi->input_dev);
+ pr_debug("%s: keycode=%d, is released\n", __func__,
+ hi->pressed_code);
+ return;
+ }
+
+ /* when button is pressed */
+ adc = pdata->get_adc_value();
+
+ for (i = 0; i < pdata->num_buttons_zones; i++)
+ if (adc >= btn_zones[i].adc_low &&
+ adc <= btn_zones[i].adc_high) {
+ hi->pressed_code = btn_zones[i].code;
+ input_report_key(hi->input_dev, btn_zones[i].code, 1);
+ input_sync(hi->input_dev);
+ pr_debug("%s: keycode=%d, is pressed\n", __func__,
+ btn_zones[i].code);
+ return;
+ }
+
+ pr_warn("%s: key is skipped. ADC value is %d\n", __func__, adc);
+}
+
+static int sec_jack_probe(struct platform_device *pdev)
+{
+ struct sec_jack_info *hi;
+ struct sec_jack_platform_data *pdata = pdev->dev.platform_data;
+ int ret;
+
+ pr_info("%s : Registering jack driver\n", __func__);
+ if (!pdata) {
+ pr_err("%s : pdata is NULL.\n", __func__);
+ return -ENODEV;
+ }
+
+ if (!pdata->get_adc_value || !pdata->zones ||
+ !pdata->set_micbias_state || pdata->num_zones > MAX_ZONE_LIMIT) {
+ pr_err("%s : need to check pdata\n", __func__);
+ return -ENODEV;
+ }
+
+ if (atomic_xchg(&instantiated, 1)) {
+ pr_err("%s : already instantiated, can only have one\n",
+ __func__);
+ return -ENODEV;
+ }
+
+ sec_jack_key_map[0].gpio = pdata->send_end_gpio;
+
+ /* If no other keys in pdata, make all keys default to KEY_MEDIA */
+ if (pdata->num_buttons_zones == 0)
+ sec_jack_key_map[0].code = KEY_MEDIA;
+
+ hi = kzalloc(sizeof(struct sec_jack_info), GFP_KERNEL);
+ if (hi == NULL) {
+ pr_err("%s : Failed to allocate memory.\n", __func__);
+ ret = -ENOMEM;
+ goto err_kzalloc;
+ }
+
+ hi->pdata = pdata;
+
+ /* make the id of our gpi_event device the same as our platform device,
+ * which makes it the responsiblity of the board file to make sure
+ * it is unique relative to other gpio_event devices
+ */
+ hi->dev_id = pdev->id;
+
+ ret = gpio_request(pdata->det_gpio, "ear_jack_detect");
+ if (ret) {
+ pr_err("%s : gpio_request failed for %d\n",
+ __func__, pdata->det_gpio);
+ goto err_gpio_request;
+ }
+
+ ret = switch_dev_register(&switch_jack_detection);
+ if (ret < 0) {
+ pr_err("%s : Failed to register switch device\n", __func__);
+ goto err_switch_dev_register;
+ }
+
+ wake_lock_init(&hi->det_wake_lock, WAKE_LOCK_SUSPEND, "sec_jack_det");
+
+ INIT_WORK(&hi->buttons_work, sec_jack_buttons_work);
+ hi->queue = create_singlethread_workqueue("sec_jack_wq");
+ if (hi->queue == NULL) {
+ ret = -ENOMEM;
+ pr_err("%s: Failed to create workqueue\n", __func__);
+ goto err_create_wq_failed;
+ }
+
+ hi->det_irq = gpio_to_irq(pdata->det_gpio);
+
+ set_bit(EV_KEY, hi->ids.evbit);
+ hi->ids.flags = INPUT_DEVICE_ID_MATCH_EVBIT;
+ hi->handler.filter = sec_jack_buttons_filter;
+ hi->handler.connect = sec_jack_buttons_connect;
+ hi->handler.disconnect = sec_jack_buttons_disconnect;
+ hi->handler.name = "sec_jack_buttons";
+ hi->handler.id_table = &hi->ids;
+ hi->handler.private = hi;
+
+ ret = input_register_handler(&hi->handler);
+ if (ret) {
+ pr_err("%s : Failed to register_handler\n", __func__);
+ goto err_register_input_handler;
+ }
+ ret = request_threaded_irq(hi->det_irq, NULL,
+ sec_jack_detect_irq_thread,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
+ IRQF_ONESHOT, "sec_headset_detect", hi);
+ if (ret) {
+ pr_err("%s : Failed to request_irq.\n", __func__);
+ goto err_request_detect_irq;
+ }
+
+ /* to handle insert/removal when we're sleeping in a call */
+ ret = enable_irq_wake(hi->det_irq);
+ if (ret) {
+ pr_err("%s : Failed to enable_irq_wake.\n", __func__);
+ goto err_enable_irq_wake;
+ }
+
+ dev_set_drvdata(&pdev->dev, hi);
+
+ return 0;
+
+err_enable_irq_wake:
+ free_irq(hi->det_irq, hi);
+err_request_detect_irq:
+ input_unregister_handler(&hi->handler);
+err_register_input_handler:
+ destroy_workqueue(hi->queue);
+err_create_wq_failed:
+ wake_lock_destroy(&hi->det_wake_lock);
+ switch_dev_unregister(&switch_jack_detection);
+err_switch_dev_register:
+ gpio_free(pdata->det_gpio);
+err_gpio_request:
+ kfree(hi);
+err_kzalloc:
+ atomic_set(&instantiated, 0);
+
+ return ret;
+}
+
+static int sec_jack_remove(struct platform_device *pdev)
+{
+
+ struct sec_jack_info *hi = dev_get_drvdata(&pdev->dev);
+
+ pr_info("%s :\n", __func__);
+ disable_irq_wake(hi->det_irq);
+ free_irq(hi->det_irq, hi);
+ destroy_workqueue(hi->queue);
+ if (hi->send_key_dev) {
+ platform_device_unregister(hi->send_key_dev);
+ hi->send_key_dev = NULL;
+ }
+ input_unregister_handler(&hi->handler);
+ wake_lock_destroy(&hi->det_wake_lock);
+ switch_dev_unregister(&switch_jack_detection);
+ gpio_free(hi->pdata->det_gpio);
+ kfree(hi);
+ atomic_set(&instantiated, 0);
+
+ return 0;
+}
+
+static struct platform_driver sec_jack_driver = {
+ .probe = sec_jack_probe,
+ .remove = sec_jack_remove,
+ .driver = {
+ .name = "sec_jack",
+ .owner = THIS_MODULE,
+ },
+};
+static int __init sec_jack_init(void)
+{
+ return platform_driver_register(&sec_jack_driver);
+}
+
+static void __exit sec_jack_exit(void)
+{
+ platform_driver_unregister(&sec_jack_driver);
+}
+
+module_init(sec_jack_init);
+module_exit(sec_jack_exit);
+
+MODULE_AUTHOR("ms17.kim@samsung.com");
+MODULE_DESCRIPTION("Samsung Electronics Corp Ear-Jack detection driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/sgi-xp/xpc_uv.c b/drivers/misc/sgi-xp/xpc_uv.c
index 17bbacb..cc2ae7e 100644
--- a/drivers/misc/sgi-xp/xpc_uv.c
+++ b/drivers/misc/sgi-xp/xpc_uv.c
@@ -18,6 +18,8 @@
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/device.h>
+#include <linux/cpu.h>
+#include <linux/module.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <asm/uv/uv_hub.h>
@@ -59,6 +61,8 @@ static struct xpc_heartbeat_uv *xpc_heartbeat_uv;
XPC_NOTIFY_MSG_SIZE_UV)
#define XPC_NOTIFY_IRQ_NAME "xpc_notify"
+static int xpc_mq_node = -1;
+
static struct xpc_gru_mq_uv *xpc_activate_mq_uv;
static struct xpc_gru_mq_uv *xpc_notify_mq_uv;
@@ -109,11 +113,8 @@ xpc_get_gru_mq_irq_uv(struct xpc_gru_mq_uv *mq, int cpu, char *irq_name)
#if defined CONFIG_X86_64
mq->irq = uv_setup_irq(irq_name, cpu, mq->mmr_blade, mq->mmr_offset,
UV_AFFINITY_CPU);
- if (mq->irq < 0) {
- dev_err(xpc_part, "uv_setup_irq() returned error=%d\n",
- -mq->irq);
+ if (mq->irq < 0)
return mq->irq;
- }
mq->mmr_value = uv_read_global_mmr64(mmr_pnode, mq->mmr_offset);
@@ -238,8 +239,9 @@ xpc_create_gru_mq_uv(unsigned int mq_size, int cpu, char *irq_name,
mq->mmr_blade = uv_cpu_to_blade_id(cpu);
nid = cpu_to_node(cpu);
- page = alloc_pages_exact_node(nid, GFP_KERNEL | __GFP_ZERO | GFP_THISNODE,
- pg_order);
+ page = alloc_pages_exact_node(nid,
+ GFP_KERNEL | __GFP_ZERO | GFP_THISNODE,
+ pg_order);
if (page == NULL) {
dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to alloc %d "
"bytes of memory on nid=%d for GRU mq\n", mq_size, nid);
@@ -1731,9 +1733,50 @@ static struct xpc_arch_operations xpc_arch_ops_uv = {
.notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_uv,
};
+static int
+xpc_init_mq_node(int nid)
+{
+ int cpu;
+
+ get_online_cpus();
+
+ for_each_cpu(cpu, cpumask_of_node(nid)) {
+ xpc_activate_mq_uv =
+ xpc_create_gru_mq_uv(XPC_ACTIVATE_MQ_SIZE_UV, nid,
+ XPC_ACTIVATE_IRQ_NAME,
+ xpc_handle_activate_IRQ_uv);
+ if (!IS_ERR(xpc_activate_mq_uv))
+ break;
+ }
+ if (IS_ERR(xpc_activate_mq_uv)) {
+ put_online_cpus();
+ return PTR_ERR(xpc_activate_mq_uv);
+ }
+
+ for_each_cpu(cpu, cpumask_of_node(nid)) {
+ xpc_notify_mq_uv =
+ xpc_create_gru_mq_uv(XPC_NOTIFY_MQ_SIZE_UV, nid,
+ XPC_NOTIFY_IRQ_NAME,
+ xpc_handle_notify_IRQ_uv);
+ if (!IS_ERR(xpc_notify_mq_uv))
+ break;
+ }
+ if (IS_ERR(xpc_notify_mq_uv)) {
+ xpc_destroy_gru_mq_uv(xpc_activate_mq_uv);
+ put_online_cpus();
+ return PTR_ERR(xpc_notify_mq_uv);
+ }
+
+ put_online_cpus();
+ return 0;
+}
+
int
xpc_init_uv(void)
{
+ int nid;
+ int ret = 0;
+
xpc_arch_ops = xpc_arch_ops_uv;
if (sizeof(struct xpc_notify_mq_msghdr_uv) > XPC_MSG_HDR_MAX_SIZE) {
@@ -1742,21 +1785,21 @@ xpc_init_uv(void)
return -E2BIG;
}
- xpc_activate_mq_uv = xpc_create_gru_mq_uv(XPC_ACTIVATE_MQ_SIZE_UV, 0,
- XPC_ACTIVATE_IRQ_NAME,
- xpc_handle_activate_IRQ_uv);
- if (IS_ERR(xpc_activate_mq_uv))
- return PTR_ERR(xpc_activate_mq_uv);
+ if (xpc_mq_node < 0)
+ for_each_online_node(nid) {
+ ret = xpc_init_mq_node(nid);
- xpc_notify_mq_uv = xpc_create_gru_mq_uv(XPC_NOTIFY_MQ_SIZE_UV, 0,
- XPC_NOTIFY_IRQ_NAME,
- xpc_handle_notify_IRQ_uv);
- if (IS_ERR(xpc_notify_mq_uv)) {
- xpc_destroy_gru_mq_uv(xpc_activate_mq_uv);
- return PTR_ERR(xpc_notify_mq_uv);
- }
+ if (!ret)
+ break;
+ }
+ else
+ ret = xpc_init_mq_node(xpc_mq_node);
- return 0;
+ if (ret < 0)
+ dev_err(xpc_part, "xpc_init_mq_node() returned error=%d\n",
+ -ret);
+
+ return ret;
}
void
@@ -1765,3 +1808,6 @@ xpc_exit_uv(void)
xpc_destroy_gru_mq_uv(xpc_notify_mq_uv);
xpc_destroy_gru_mq_uv(xpc_activate_mq_uv);
}
+
+module_param(xpc_mq_node, int, 0);
+MODULE_PARM_DESC(xpc_mq_node, "Node number on which to allocate message queues.");
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 0635da5..e6629b9 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -306,6 +306,9 @@ 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 (card->scr.sda_spec3) {
card->sw_caps.sd3_bus_mode = status[13];
@@ -348,9 +351,6 @@ static int mmc_read_switch(struct mmc_card *card)
}
card->sw_caps.sd3_curr_limit = status[7];
- } else {
- if (status[13] & 0x02)
- card->sw_caps.hs_max_dtr = 50000000;
}
out:
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index a2c1c4d..5d17199 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -685,7 +685,7 @@ static int mmc_sdio_resume(struct mmc_host *host)
}
if (!err && host->sdio_irqs)
- mmc_signal_sdio_irq(host);
+ wake_up_process(host->sdio_irq_thread);
mmc_release_host(host);
/*
diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c
index 03ead02..d58ae91 100644
--- a/drivers/mmc/core/sdio_irq.c
+++ b/drivers/mmc/core/sdio_irq.c
@@ -27,18 +27,20 @@
#include "sdio_ops.h"
-static int process_sdio_pending_irqs(struct mmc_card *card)
+static int process_sdio_pending_irqs(struct mmc_host *host)
{
+ struct mmc_card *card = host->card;
int i, ret, count;
unsigned char pending;
struct sdio_func *func;
/*
* Optimization, if there is only 1 function interrupt registered
- * call irq handler directly
+ * and we know an IRQ was signaled then call irq handler directly.
+ * Otherwise do the full probe.
*/
func = card->sdio_single_irq;
- if (func) {
+ if (func && host->sdio_irq_pending) {
func->irq_handler(func);
return 1;
}
@@ -115,7 +117,8 @@ static int sdio_irq_thread(void *_host)
ret = __mmc_claim_host(host, &host->sdio_irq_thread_abort);
if (ret)
break;
- ret = process_sdio_pending_irqs(host->card);
+ ret = process_sdio_pending_irqs(host);
+ host->sdio_irq_pending = false;
mmc_release_host(host);
/*
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 56dbf3f..0ff3b56 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -204,7 +204,7 @@ config MMC_SDHCI_SPEAR
config MMC_SDHCI_S3C_DMA
bool "DMA support on S3C SDHCI"
- depends on MMC_SDHCI_S3C && EXPERIMENTAL
+ depends on MMC_SDHCI_S3C
help
Enable DMA support on the Samsung S3C SDHCI glue. The DMA
has proved to be problematic if the controller encounters
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c
index d513d47..74160eb 100644
--- a/drivers/mmc/host/mxs-mmc.c
+++ b/drivers/mmc/host/mxs-mmc.c
@@ -278,11 +278,11 @@ static irqreturn_t mxs_mmc_irq_handler(int irq, void *dev_id)
writel(stat & MXS_MMC_IRQ_BITS,
host->base + HW_SSP_CTRL1 + MXS_CLR_ADDR);
+ spin_unlock(&host->lock);
+
if ((stat & BM_SSP_CTRL1_SDIO_IRQ) && (stat & BM_SSP_CTRL1_SDIO_IRQ_EN))
mmc_signal_sdio_irq(host->mmc);
- spin_unlock(&host->lock);
-
if (stat & BM_SSP_CTRL1_RESP_TIMEOUT_IRQ)
cmd->error = -ETIMEDOUT;
else if (stat & BM_SSP_CTRL1_RESP_ERR_IRQ)
diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h
index c3b08f1..62ca03a 100644
--- a/drivers/mmc/host/sdhci-esdhc.h
+++ b/drivers/mmc/host/sdhci-esdhc.h
@@ -48,14 +48,14 @@ static inline void esdhc_set_clock(struct sdhci_host *host, unsigned int clock)
int div = 1;
u32 temp;
+ if (clock == 0)
+ goto out;
+
temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
temp &= ~(ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN
| ESDHC_CLOCK_MASK);
sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
- if (clock == 0)
- goto out;
-
while (host->max_clk / pre_div / 16 > clock && pre_div < 256)
pre_div *= 2;
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index 936bbca..d3b3115 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -140,6 +140,7 @@ static const struct sdhci_pci_fixes sdhci_ene_714 = {
static const struct sdhci_pci_fixes sdhci_cafe = {
.quirks = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER |
SDHCI_QUIRK_NO_BUSY_IRQ |
+ SDHCI_QUIRK_BROKEN_CARD_DETECTION |
SDHCI_QUIRK_BROKEN_TIMEOUT_VAL,
};
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
index 8cd999f..fb3eba6 100644..100755
--- a/drivers/mmc/host/sdhci-s3c.c
+++ b/drivers/mmc/host/sdhci-s3c.c
@@ -21,6 +21,7 @@
#include <linux/gpio.h>
#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
#include <plat/sdhci.h>
#include <plat/regs-sdhci.h>
@@ -45,6 +46,7 @@ struct sdhci_s3c {
struct resource *ioarea;
struct s3c_sdhci_platdata *pdata;
unsigned int cur_clk;
+ bool cur_clk_set;
int ext_cd_irq;
int ext_cd_gpio;
@@ -79,7 +81,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);
}
}
@@ -113,6 +115,46 @@ static unsigned int sdhci_s3c_get_max_clk(struct sdhci_host *host)
return max;
}
+static void sdhci_s3c_set_ios(struct sdhci_host *host,
+ struct mmc_ios *ios)
+{
+ struct sdhci_s3c *ourhost = to_s3c(host);
+ struct s3c_sdhci_platdata *pdata = ourhost->pdata;
+ int width;
+ u8 tmp;
+
+ sdhci_s3c_check_sclk(host);
+
+ if (ios->power_mode != MMC_POWER_OFF) {
+ switch (ios->bus_width) {
+ case MMC_BUS_WIDTH_8:
+ width = 8;
+ tmp = readb(host->ioaddr + SDHCI_HOST_CONTROL);
+ writeb(tmp | SDHCI_S3C_CTRL_8BITBUS,
+ host->ioaddr + SDHCI_HOST_CONTROL);
+ break;
+ case MMC_BUS_WIDTH_4:
+ width = 4;
+ break;
+ case MMC_BUS_WIDTH_1:
+ width = 1;
+ break;
+ default:
+ BUG();
+ }
+
+ if (pdata->cfg_gpio)
+ pdata->cfg_gpio(ourhost->pdev, width);
+ }
+
+ if (pdata->cfg_card) {
+ pdata->cfg_card(ourhost->pdev, host->ioaddr,
+ ios, host->mmc->card);
+ pdata->rx_cfg = 0;
+ pdata->tx_cfg = 0;
+ }
+}
+
/**
* sdhci_s3c_consider_clock - consider one the bus clocks for current setting
* @ourhost: Our SDHCI instance.
@@ -187,13 +229,14 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock)
/* select the new clock source */
- if (ourhost->cur_clk != best_src) {
+ if (ourhost->cur_clk != best_src || !ourhost->cur_clk_set) {
struct clk *clk = ourhost->clk_bus[best_src];
/* turn clock off to card before changing clock source */
writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL);
ourhost->cur_clk = best_src;
+ ourhost->cur_clk_set = true;
host->max_clk = clk_get_rate(clk);
ctrl = readl(host->ioaddr + S3C_SDHCI_CONTROL2);
@@ -201,18 +244,15 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock)
ctrl |= best_src << S3C_SDHCI_CTRL2_SELBASECLK_SHIFT;
writel(ctrl, host->ioaddr + S3C_SDHCI_CONTROL2);
}
+}
- /* reconfigure the hardware for new clock rate */
-
- {
- struct mmc_ios ios;
-
- ios.clock = clock;
+static void sdhci_s3c_adjust_cfg(struct sdhci_host *host, int rw)
+{
+ struct sdhci_s3c *ourhost = to_s3c(host);
+ struct s3c_sdhci_platdata *pdata = ourhost->pdata;
- if (ourhost->pdata->cfg_card)
- (ourhost->pdata->cfg_card)(ourhost->pdev, host->ioaddr,
- &ios, NULL);
- }
+ if(pdata->adjust_cfg_card)
+ pdata->adjust_cfg_card(pdata, host->ioaddr, rw);
}
/**
@@ -316,6 +356,8 @@ static struct sdhci_ops sdhci_s3c_ops = {
.set_clock = sdhci_s3c_set_clock,
.get_min_clock = sdhci_s3c_get_min_clock,
.platform_8bit_width = sdhci_s3c_platform_8bit_width,
+ .set_ios = sdhci_s3c_set_ios,
+ .adjust_cfg = sdhci_s3c_adjust_cfg,
};
static void sdhci_s3c_notify_change(struct platform_device *dev, int state)
@@ -487,6 +529,9 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
/* Setup quirks for the controller */
host->quirks |= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC;
host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT;
+ host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
+ if (pdata->must_maintain_clock)
+ host->quirks |= SDHCI_QUIRK_MUST_MAINTAIN_CLOCK;
#ifndef CONFIG_MMC_SDHCI_S3C_DMA
@@ -494,6 +539,9 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
* support as well. */
host->quirks |= SDHCI_QUIRK_BROKEN_DMA;
+ /* PIO currently has problems with multi-block IO */
+ host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK;
+
#endif /* CONFIG_MMC_SDHCI_S3C_DMA */
/* It seems we do not get an DATA transfer complete on non-busy
@@ -534,6 +582,11 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
if (pdata->host_caps)
host->mmc->caps |= pdata->host_caps;
+ /* Set pm_flags for built_in device */
+ host->mmc->pm_caps = MMC_PM_KEEP_POWER | MMC_PM_IGNORE_PM_NOTIFY;
+ if (pdata->built_in)
+ host->mmc->pm_flags = MMC_PM_KEEP_POWER | MMC_PM_IGNORE_PM_NOTIFY;
+
ret = sdhci_add_host(host);
if (ret) {
dev_err(dev, "sdhci_add_host() failed\n");
@@ -557,8 +610,10 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
err_req_regs:
for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
- clk_disable(sc->clk_bus[ptr]);
- clk_put(sc->clk_bus[ptr]);
+ if (sc->clk_bus[ptr]) {
+ clk_disable(sc->clk_bus[ptr]);
+ clk_put(sc->clk_bus[ptr]);
+ }
}
err_no_busclks:
@@ -576,11 +631,16 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data;
struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_s3c *sc = sdhci_priv(host);
- int ptr;
+ int ptr, dead = 0;
+ u32 scratch;
if (pdata->cd_type == S3C_SDHCI_CD_EXTERNAL && pdata->ext_cd_cleanup)
pdata->ext_cd_cleanup(&sdhci_s3c_notify_change);
+ scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
+ if (scratch == (u32)-1)
+ dead = 1;
+
if (sc->ext_cd_irq)
free_irq(sc->ext_cd_irq, sc);
@@ -589,7 +649,7 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
sdhci_remove_host(host, 1);
- for (ptr = 0; ptr < 3; ptr++) {
+ for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
if (sc->clk_bus[ptr]) {
clk_disable(sc->clk_bus[ptr]);
clk_put(sc->clk_bus[ptr]);
@@ -614,6 +674,11 @@ static int sdhci_s3c_suspend(struct platform_device *dev, pm_message_t pm)
{
struct sdhci_host *host = platform_get_drvdata(dev);
+ struct mmc_host *mmc = host->mmc;
+
+ if (mmc->card && (mmc->card->type == MMC_TYPE_SDIO))
+ mmc->pm_flags |= MMC_PM_KEEP_POWER;
+
sdhci_suspend_host(host, pm);
return 0;
}
@@ -621,8 +686,18 @@ static int sdhci_s3c_suspend(struct platform_device *dev, pm_message_t pm)
static int sdhci_s3c_resume(struct platform_device *dev)
{
struct sdhci_host *host = platform_get_drvdata(dev);
+ struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
+ u32 ier;
sdhci_resume_host(host);
+
+ if (pdata->enable_intr_on_resume) {
+ ier = sdhci_readl(host, SDHCI_INT_ENABLE);
+ ier |= SDHCI_INT_CARD_INT;
+ sdhci_writel(host, ier, SDHCI_INT_ENABLE);
+ sdhci_writel(host, ier, SDHCI_SIGNAL_ENABLE);
+ }
+
return 0;
}
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index d517a21..572285b 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -25,6 +25,9 @@
#include <linux/mmc/mmc.h>
#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+
+#include <plat/regs-sdhci.h>
#include "sdhci.h"
@@ -104,6 +107,24 @@ static void sdhci_dumpregs(struct sdhci_host *host)
* *
\*****************************************************************************/
+static void sdhci_enable_clock_card(struct sdhci_host *host)
+{
+ u16 clk;
+
+ clk = readw(host->ioaddr + SDHCI_CLOCK_CONTROL);
+ clk |= SDHCI_CLOCK_CARD_EN;
+ writew(clk, host->ioaddr + SDHCI_CLOCK_CONTROL);
+}
+
+static void sdhci_disable_clock_card(struct sdhci_host *host)
+{
+ u16 clk;
+
+ clk = readw(host->ioaddr + SDHCI_CLOCK_CONTROL);
+ clk &= ~SDHCI_CLOCK_CARD_EN;
+ writew(clk, host->ioaddr + SDHCI_CLOCK_CONTROL);
+}
+
static void sdhci_clear_set_irqs(struct sdhci_host *host, u32 clear, u32 set)
{
u32 ier;
@@ -930,9 +951,14 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
int flags;
u32 mask;
unsigned long timeout;
+#if defined(CONFIG_MMC_SDHCI_S3C) || defined(CONFIG_MMC_SDHCI_MODULE)
+ int i;
+#endif
WARN_ON(host->cmd);
+ del_timer(&host->busy_check_timer);
+
/* Wait max 10 ms */
timeout = 10;
@@ -962,8 +988,12 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
host->cmd = cmd;
+ sdhci_enable_clock_card(host);
sdhci_prepare_data(host, cmd);
+ if(cmd->flags & MMC_RSP_BUSY)
+ sdhci_writeb(host, 0xE, SDHCI_TIMEOUT_CONTROL);
+
sdhci_writel(host, cmd->arg, SDHCI_ARGUMENT);
sdhci_set_transfer_mode(host, cmd);
@@ -994,6 +1024,17 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
if (cmd->data || (cmd->opcode == MMC_SEND_TUNING_BLOCK))
flags |= SDHCI_CMD_DATA;
+#if defined(CONFIG_MMC_SDHCI_S3C) || defined(CONFIG_MMC_SDHCI_MODULE)
+ mask = readl(host->ioaddr + SDHCI_INT_STATUS);
+ writel(mask & SDHCI_INT_DATA_MASK & SDHCI_INT_CMD_MASK, host->ioaddr + SDHCI_INT_STATUS);
+
+ for(i=0; i<0x1000000; i++) {
+ mask = readl(host->ioaddr + S3C64XX_SDHCI_CONTROL4);
+ if(!(mask & S3C64XX_SDHCI_CONTROL4_BUSY))
+ break;
+ }
+#endif
+
sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND);
}
@@ -1289,6 +1330,9 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
sdhci_reinit(host);
}
+ if (host->ops->set_ios)
+ host->ops->set_ios(host, ios);
+
sdhci_set_clock(host, ios->clock);
if (ios->power_mode == MMC_POWER_OFF)
@@ -1798,6 +1842,26 @@ static void sdhci_enable_preset_value(struct mmc_host *mmc, bool enable)
spin_unlock_irqrestore(&host->lock, flags);
}
+void sdhci_adjust_cfg(struct mmc_host *mmc, int rw)
+{
+ struct sdhci_host *host;
+ unsigned long flags;
+ struct mmc_ios *ios = &mmc->ios;
+ unsigned int clock;
+
+ host = mmc_priv(mmc);
+
+ spin_lock_irqsave(&host->lock, flags);
+
+ if(host->ops->adjust_cfg)
+ host->ops->adjust_cfg(host, rw);
+
+ sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
+
+ mmiowb();
+ spin_unlock_irqrestore(&host->lock, flags);
+}
+
static const struct mmc_host_ops sdhci_ops = {
.request = sdhci_request,
.set_ios = sdhci_set_ios,
@@ -1806,6 +1870,7 @@ static const struct mmc_host_ops sdhci_ops = {
.start_signal_voltage_switch = sdhci_start_signal_voltage_switch,
.execute_tuning = sdhci_execute_tuning,
.enable_preset_value = sdhci_enable_preset_value,
+ .adjust_cfg = sdhci_adjust_cfg,
};
/*****************************************************************************\
@@ -1851,6 +1916,9 @@ static void sdhci_tasklet_finish(unsigned long param)
host = (struct sdhci_host*)param;
+ if(host == NULL)
+ return;
+
/*
* If this tasklet gets rescheduled while running, it will
* be run again afterwards but without any active request.
@@ -1864,6 +1932,9 @@ static void sdhci_tasklet_finish(unsigned long param)
mrq = host->mrq;
+ if(mrq == NULL || mrq->cmd == NULL)
+ goto out;
+
/*
* The controller needs a reset of internal state machines
* upon error conditions.
@@ -1889,6 +1960,12 @@ static void sdhci_tasklet_finish(unsigned long param)
sdhci_reset(host, SDHCI_RESET_CMD);
sdhci_reset(host, SDHCI_RESET_DATA);
}
+out:
+ if((readl(host->ioaddr + SDHCI_PRESENT_STATE) & SDHCI_DATA_INHIBIT) ||
+ (host->quirks & SDHCI_QUIRK_MUST_MAINTAIN_CLOCK))
+ mod_timer(&host->busy_check_timer, jiffies + msecs_to_jiffies(10));
+ else
+ sdhci_disable_clock_card(host);
host->mrq = NULL;
host->cmd = NULL;
@@ -1949,6 +2026,24 @@ static void sdhci_tuning_timer(unsigned long data)
spin_unlock_irqrestore(&host->lock, flags);
}
+static void sdhci_busy_check_timer(unsigned long data)
+{
+ struct sdhci_host *host;
+ unsigned long flags;
+
+ host = (struct sdhci_host*)data;
+
+ spin_lock_irqsave(&host->lock, flags);
+
+ if((readl(host->ioaddr + SDHCI_PRESENT_STATE) & (SDHCI_CMD_INHIBIT | SDHCI_DATA_INHIBIT)) ||
+ (host->quirks & SDHCI_QUIRK_MUST_MAINTAIN_CLOCK))
+ mod_timer(&host->busy_check_timer, jiffies + msecs_to_jiffies(10));
+ else
+ sdhci_disable_clock_card(host);
+
+ spin_unlock_irqrestore(&host->lock, flags);
+}
+
/*****************************************************************************\
* *
* Interrupt handling *
@@ -1975,6 +2070,7 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
if (host->cmd->error) {
tasklet_schedule(&host->finish_tasklet);
+ host->cmd = NULL;
return;
}
@@ -2219,7 +2315,7 @@ out:
int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state)
{
- int ret;
+ int ret = 0;
sdhci_disable_card_detection(host);
@@ -2231,10 +2327,17 @@ int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state)
}
ret = mmc_suspend_host(host->mmc);
- if (ret)
+ if (ret) {
+ sdhci_enable_card_detection(host);
return ret;
+ }
- free_irq(host->irq, host);
+ sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK);
+
+ del_timer(&host->busy_check_timer);
+
+ if (host->irq)
+ disable_irq(host->irq);
if (host->vmmc)
ret = regulator_disable(host->vmmc);
@@ -2246,7 +2349,7 @@ EXPORT_SYMBOL_GPL(sdhci_suspend_host);
int sdhci_resume_host(struct sdhci_host *host)
{
- int ret;
+ int ret = 0;
if (host->vmmc) {
int ret = regulator_enable(host->vmmc);
@@ -2260,15 +2363,14 @@ int sdhci_resume_host(struct sdhci_host *host)
host->ops->enable_dma(host);
}
- ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
- mmc_hostname(host->mmc), host);
- if (ret)
- return ret;
+ if (host->irq)
+ enable_irq(host->irq);
sdhci_init(host, (host->mmc->pm_flags & MMC_PM_KEEP_POWER));
mmiowb();
ret = mmc_resume_host(host->mmc);
+
sdhci_enable_card_detection(host);
/* Set the re-tuning expiration flag */
@@ -2515,8 +2617,9 @@ int sdhci_add_host(struct sdhci_host *host)
mmc_card_is_removable(mmc))
mmc->caps |= MMC_CAP_NEEDS_POLL;
- /* UHS-I mode(s) supported by the host controller. */
- if (host->version >= SDHCI_SPEC_300)
+ /* Any UHS-I mode in caps implies SDR12 and SDR25 support. */
+ if (caps[1] & (SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 |
+ SDHCI_SUPPORT_DDR50))
mmc->caps |= MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25;
/* SDR104 supports also implies SDR50 support */
@@ -2699,6 +2802,7 @@ int sdhci_add_host(struct sdhci_host *host)
sdhci_tasklet_finish, (unsigned long)host);
setup_timer(&host->timer, sdhci_timeout_timer, (unsigned long)host);
+ setup_timer(&host->busy_check_timer, sdhci_busy_check_timer, (unsigned long)host);
if (host->version >= SDHCI_SPEC_300) {
init_waitqueue_head(&host->buf_ready_int);
@@ -2804,6 +2908,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
del_timer_sync(&host->timer);
if (host->version >= SDHCI_SPEC_300)
del_timer_sync(&host->tuning_timer);
+ del_timer_sync(&host->busy_check_timer);
tasklet_kill(&host->card_tasklet);
tasklet_kill(&host->finish_tasklet);
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 745c42f..98d0bc2 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -274,6 +274,9 @@ struct sdhci_ops {
void (*platform_reset_exit)(struct sdhci_host *host, u8 mask);
int (*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs);
+ void (*set_ios)(struct sdhci_host *host,
+ struct mmc_ios *ios);
+ void (*adjust_cfg)(struct sdhci_host *host, int rw);
};
#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
diff --git a/drivers/mtd/maps/autcpu12-nvram.c b/drivers/mtd/maps/autcpu12-nvram.c
index e5bfd0e..0598d52 100644
--- a/drivers/mtd/maps/autcpu12-nvram.c
+++ b/drivers/mtd/maps/autcpu12-nvram.c
@@ -43,7 +43,8 @@ struct map_info autcpu12_sram_map = {
static int __init init_autcpu12_sram (void)
{
- int err, save0, save1;
+ map_word tmp, save0, save1;
+ int err;
autcpu12_sram_map.virt = ioremap(0x12000000, SZ_128K);
if (!autcpu12_sram_map.virt) {
@@ -51,7 +52,7 @@ static int __init init_autcpu12_sram (void)
err = -EIO;
goto out;
}
- simple_map_init(&autcpu_sram_map);
+ simple_map_init(&autcpu12_sram_map);
/*
* Check for 32K/128K
@@ -61,20 +62,22 @@ static int __init init_autcpu12_sram (void)
* Read and check result on ofs 0x0
* Restore contents
*/
- save0 = map_read32(&autcpu12_sram_map,0);
- save1 = map_read32(&autcpu12_sram_map,0x10000);
- map_write32(&autcpu12_sram_map,~save0,0x10000);
+ save0 = map_read(&autcpu12_sram_map, 0);
+ save1 = map_read(&autcpu12_sram_map, 0x10000);
+ tmp.x[0] = ~save0.x[0];
+ map_write(&autcpu12_sram_map, tmp, 0x10000);
/* if we find this pattern on 0x0, we have 32K size
* restore contents and exit
*/
- if ( map_read32(&autcpu12_sram_map,0) != save0) {
- map_write32(&autcpu12_sram_map,save0,0x0);
+ tmp = map_read(&autcpu12_sram_map, 0);
+ if (!map_word_equal(&autcpu12_sram_map, tmp, save0)) {
+ map_write(&autcpu12_sram_map, save0, 0x0);
goto map;
}
/* We have a 128K found, restore 0x10000 and set size
* to 128K
*/
- map_write32(&autcpu12_sram_map,save1,0x10000);
+ map_write(&autcpu12_sram_map, save1, 0x10000);
autcpu12_sram_map.size = SZ_128K;
map:
diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c
index 87ebb4e..f5cdc56 100644
--- a/drivers/mtd/nand/cafe_nand.c
+++ b/drivers/mtd/nand/cafe_nand.c
@@ -102,7 +102,7 @@ static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
static int cafe_device_ready(struct mtd_info *mtd)
{
struct cafe_priv *cafe = mtd->priv;
- int result = !!(cafe_readl(cafe, NAND_STATUS) | 0x40000000);
+ int result = !!(cafe_readl(cafe, NAND_STATUS) & 0x40000000);
uint32_t irqs = cafe_readl(cafe, NAND_IRQ);
cafe_writel(cafe, irqs, NAND_IRQ);
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index ccbeaa1..c27ca6a 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -360,6 +360,7 @@ static int scan_read_raw_oob(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
buf += mtd->oobsize + mtd->writesize;
len -= mtd->writesize;
+ offs += mtd->writesize;
}
return 0;
}
@@ -428,7 +429,7 @@ static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
/* Read the mirror version, if available */
if (md && (md->options & NAND_BBT_VERSION)) {
scan_read_raw(mtd, buf, (loff_t)md->pages[0] << this->page_shift,
- mtd->writesize, td);
+ mtd->writesize, md);
md->version[0] = buf[bbt_get_ver_offs(mtd, md)];
printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n",
md->pages[0], md->version[0]);
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index 357e8c5..1f2b880 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -28,7 +28,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/vmalloc.h>
-#include <asm/div64.h>
+#include <linux/math64.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/string.h>
@@ -547,12 +547,6 @@ static char *get_partition_name(int i)
return kstrdup(buf, GFP_KERNEL);
}
-static uint64_t divide(uint64_t n, uint32_t d)
-{
- do_div(n, d);
- return n;
-}
-
/*
* Initialize the nandsim structure.
*
@@ -581,7 +575,7 @@ static int init_nandsim(struct mtd_info *mtd)
ns->geom.oobsz = mtd->oobsize;
ns->geom.secsz = mtd->erasesize;
ns->geom.pgszoob = ns->geom.pgsz + ns->geom.oobsz;
- ns->geom.pgnum = divide(ns->geom.totsz, ns->geom.pgsz);
+ ns->geom.pgnum = div_u64(ns->geom.totsz, ns->geom.pgsz);
ns->geom.totszoob = ns->geom.totsz + (uint64_t)ns->geom.pgnum * ns->geom.oobsz;
ns->geom.secshift = ffs(ns->geom.secsz) - 1;
ns->geom.pgshift = chip->page_shift;
@@ -924,7 +918,7 @@ static int setup_wear_reporting(struct mtd_info *mtd)
if (!rptwear)
return 0;
- wear_eb_count = divide(mtd->size, mtd->erasesize);
+ wear_eb_count = div_u64(mtd->size, mtd->erasesize);
mem = wear_eb_count * sizeof(unsigned long);
if (mem / sizeof(unsigned long) != wear_eb_count) {
NS_ERR("Too many erase blocks for wear reporting\n");
@@ -2361,6 +2355,7 @@ static int __init ns_init_module(void)
uint64_t new_size = (uint64_t)nsmtd->erasesize << overridesize;
if (new_size >> overridesize != nsmtd->erasesize) {
NS_ERR("overridesize is too big\n");
+ retval = -EINVAL;
goto err_exit;
}
/* N.B. This relies on nand_scan not doing anything with the size before we change it */
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 0db2c0e..0289707 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -1139,7 +1139,8 @@ static int omap_nand_remove(struct platform_device *pdev)
/* Release NAND device, its internal structures and partitions */
nand_release(&info->mtd);
iounmap(info->nand.IO_ADDR_R);
- kfree(&info->mtd);
+ release_mem_region(info->phys_base, NAND_IO_SIZE);
+ kfree(info);
return 0;
}
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index ac9e959..0b964ee 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -32,6 +32,7 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/onenand.h>
#include <linux/mtd/partitions.h>
+#include <linux/clk.h>
#include <asm/io.h>
@@ -65,11 +66,11 @@ MODULE_PARM_DESC(otp, "Corresponding behaviour of OneNAND in OTP"
" : 2 -> 1st Block lock"
" : 3 -> BOTH OTP Block and 1st Block lock");
-/*
- * flexonenand_oob_128 - oob info for Flex-Onenand with 4KB page
- * For now, we expose only 64 out of 80 ecc bytes
+/**
+ * onenand_oob_128 - oob info for Flex-Onenand with 4KB page
+ * For now, we expose only 64 out of 80 ecc bytes
*/
-static struct nand_ecclayout flexonenand_oob_128 = {
+static struct nand_ecclayout onenand_oob_128 = {
.eccbytes = 64,
.eccpos = {
6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
@@ -86,35 +87,6 @@ static struct nand_ecclayout flexonenand_oob_128 = {
}
};
-/*
- * onenand_oob_128 - oob info for OneNAND with 4KB page
- *
- * Based on specification:
- * 4Gb M-die OneNAND Flash (KFM4G16Q4M, KFN8G16Q4M). Rev. 1.3, Apr. 2010
- *
- * For eccpos we expose only 64 bytes out of 72 (see struct nand_ecclayout)
- *
- * oobfree uses the spare area fields marked as
- * "Managed by internal ECC logic for Logical Sector Number area"
- */
-static struct nand_ecclayout onenand_oob_128 = {
- .eccbytes = 64,
- .eccpos = {
- 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 55, 56, 57, 58, 59, 60, 61, 62, 63,
- 71, 72, 73, 74, 75, 76, 77, 78, 79,
- 87, 88, 89, 90, 91, 92, 93, 94, 95,
- 103, 104, 105, 106, 107, 108, 109, 110, 111,
- 119
- },
- .oobfree = {
- {2, 3}, {18, 3}, {34, 3}, {50, 3},
- {66, 3}, {82, 3}, {98, 3}, {114, 3}
- }
-};
-
/**
* onenand_oob_64 - oob info for large (2KB) page
*/
@@ -991,7 +963,8 @@ static int onenand_get_device(struct mtd_info *mtd, int new_state)
schedule();
remove_wait_queue(&this->wq, &wait);
}
-
+ if (this->clk && new_state != FL_PM_SUSPENDED)
+ clk_enable(this->clk);
return 0;
}
@@ -1005,6 +978,9 @@ static void onenand_release_device(struct mtd_info *mtd)
{
struct onenand_chip *this = mtd->priv;
+ if (this->clk && this->state != FL_PM_SUSPENDED)
+ clk_disable(this->clk);
+
if (this->state != FL_PM_SUSPENDED && this->disable)
this->disable(mtd);
/* Release the chip */
@@ -3949,11 +3925,13 @@ static void onenand_resume(struct mtd_info *mtd)
{
struct onenand_chip *this = mtd->priv;
- if (this->state == FL_PM_SUSPENDED)
+ if (this->state == FL_PM_SUSPENDED) {
+ onenand_invalidate_bufferram(mtd, 0, -1);
onenand_release_device(mtd);
- else
+ } else {
printk(KERN_ERR "%s: resume() called for the chip which is not "
"in suspended state\n", __func__);
+ }
}
/**
@@ -4047,13 +4025,8 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
*/
switch (mtd->oobsize) {
case 128:
- if (FLEXONENAND(this)) {
- this->ecclayout = &flexonenand_oob_128;
- mtd->subpage_sft = 0;
- } else {
- this->ecclayout = &onenand_oob_128;
- mtd->subpage_sft = 2;
- }
+ this->ecclayout = &onenand_oob_128;
+ mtd->subpage_sft = 0;
break;
case 64:
this->ecclayout = &onenand_oob_64;
diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c
index 3306b5b..9532cc9 100644
--- a/drivers/mtd/onenand/samsung.c
+++ b/drivers/mtd/onenand/samsung.c
@@ -23,12 +23,16 @@
#include <linux/mtd/partitions.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
+#include <linux/clk.h>
#include <asm/mach/flash.h>
#include <plat/regs-onenand.h>
#include <linux/io.h>
+#include <asm/setup.h>
+#include <linux/string.h>
+
enum soc_type {
TYPE_S3C6400,
TYPE_S3C6410,
@@ -36,6 +40,45 @@ enum soc_type {
TYPE_S5PC110,
};
+struct mtd_partition s3c_partition_info[] = {
+ {
+ .name = "misc",
+ .offset = (768*SZ_1K), /* for bootloader */
+ .size = (256*SZ_1K),
+ .mask_flags = MTD_CAP_NANDFLASH,
+ },
+ {
+ .name = "recovery",
+ .offset = MTDPART_OFS_APPEND,
+ .size = (5*SZ_1M),
+ },
+ {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = (5*SZ_1M),
+ },
+ {
+ .name = "ramdisk",
+ .offset = MTDPART_OFS_APPEND,
+ .size = (3*SZ_1M),
+ },
+ {
+ .name = "system",
+ .offset = MTDPART_OFS_APPEND,
+ .size = (90*SZ_1M),
+ },
+ {
+ .name = "cache",
+ .offset = MTDPART_OFS_APPEND,
+ .size = (80*SZ_1M),
+ },
+ {
+ .name = "userdata",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ }
+};
+
#define ONENAND_ERASE_STATUS 0x00
#define ONENAND_MULTI_ERASE_SET 0x01
#define ONENAND_ERASE_START 0x03
@@ -193,6 +236,56 @@ static void s3c_dump_reg(void)
}
#endif
+struct slsi_ptbl_entry {
+ char name[16];
+ __u32 offset;
+ __u32 size;
+ __u32 flags;
+};
+
+struct mtd_partition *partitions;
+int num_partitions;
+
+#define MAX_PARTITIONS 12
+#define ATAG_SLSI_PARTITION 0x28247574
+struct mtd_partition slsi_nand_partitions[MAX_PARTITIONS];
+char slsi_nand_names[MAX_PARTITIONS * 16];
+
+static int __init parse_tag_partition(const struct tag *tag)
+{
+ struct mtd_partition *ptn = slsi_nand_partitions;
+ char *name = slsi_nand_names;
+ struct slsi_ptbl_entry *entry = (void *) &tag->u;
+ unsigned count, n;
+
+ count = (tag->hdr.size - 2) /
+ (sizeof(struct slsi_ptbl_entry) / sizeof(__u32));
+
+ if (count > MAX_PARTITIONS)
+ count = MAX_PARTITIONS;
+
+ for (n = 0; n < count; n++) {
+ memcpy(name, entry->name, 15);
+ name[15] = 0;
+ ptn->name = name;
+ ptn->offset = entry->offset;
+ ptn->size = entry->size;
+
+ printk(KERN_INFO "Partition (from atag) %15s -- Offset:0x%08x Size:0x%08x\n",
+ entry->name, entry->offset, entry->size);
+
+ name += 16;
+ entry++;
+ ptn++;
+ }
+
+ num_partitions = count;
+ partitions = slsi_nand_partitions;
+
+ return 0;
+}
+__tagtable(ATAG_SLSI_PARTITION, parse_tag_partition);
+
static unsigned int s3c64xx_cmd_map(unsigned type, unsigned val)
{
return (type << S3C64XX_CMD_MAP_SHIFT) | val;
@@ -916,6 +1009,17 @@ static int s3c_onenand_probe(struct platform_device *pdev)
err = -EFAULT;
goto ioremap_failed;
}
+
+ this->clk = clk_get(&pdev->dev, "onenand");
+
+ if (IS_ERR(this->clk)) {
+ dev_err(&pdev->dev, "cannot get clock\n");
+ err = PTR_ERR(this->clk);
+ goto clk_failed;
+ }
+
+ clk_enable(this->clk);
+
/* Set onenand_chip also */
this->base = onenand->base;
@@ -1017,6 +1121,27 @@ static int s3c_onenand_probe(struct platform_device *pdev)
if (s3c_read_reg(MEM_CFG_OFFSET) & ONENAND_SYS_CFG1_SYNC_READ)
dev_info(&onenand->pdev->dev, "OneNAND Sync. Burst Read enabled\n");
+#ifdef CONFIG_MTD_CMDLINE_PARTS
+ err = parse_mtd_partitions(mtd, part_probes, &onenand->parts, 0);
+ if (err > 0)
+ mtd_device_register(mtd, onenand->parts, err);
+ else if (err <= 0 && pdata && pdata->parts)
+ mtd_device_register(mtd, pdata->parts, pdata->nr_parts);
+ else
+#endif
+ if (num_partitions <= 0) {
+ /* default partition table */
+ num_partitions = ARRAY_SIZE(s3c_partition_info); /* pdata->nr_parts */
+ partitions = s3c_partition_info; /* pdata->parts */
+ }
+
+ if (partitions && num_partitions > 0)
+ err = mtd_device_register(mtd, partitions, num_partitions);
+ else
+ err = mtd_device_register(mtd, NULL, 0);
+
+
+/*
err = parse_mtd_partitions(mtd, part_probes, &onenand->parts, 0);
if (err > 0)
mtd_device_register(mtd, onenand->parts, err);
@@ -1024,9 +1149,11 @@ static int s3c_onenand_probe(struct platform_device *pdev)
mtd_device_register(mtd, pdata->parts, pdata->nr_parts);
else
err = mtd_device_register(mtd, NULL, 0);
+*/
platform_set_drvdata(pdev, mtd);
+ clk_disable(this->clk);
return 0;
scan_failed:
@@ -1049,6 +1176,9 @@ ahb_ioremap_failed:
dma_resource_failed:
ahb_resource_failed:
iounmap(onenand->base);
+ clk_disable(this->clk);
+ clk_put(this->clk);
+clk_failed:
ioremap_failed:
if (onenand->base_res)
release_mem_region(onenand->base_res->start,
@@ -1063,6 +1193,7 @@ onenand_fail:
static int __devexit s3c_onenand_remove(struct platform_device *pdev)
{
struct mtd_info *mtd = platform_get_drvdata(pdev);
+ struct onenand_chip *this = mtd->priv;
onenand_release(mtd);
if (onenand->ahb_addr)
@@ -1083,33 +1214,25 @@ static int __devexit s3c_onenand_remove(struct platform_device *pdev)
platform_set_drvdata(pdev, NULL);
kfree(onenand->oob_buf);
kfree(onenand->page_buf);
+ clk_put(this->clk);
kfree(onenand);
kfree(mtd);
return 0;
}
-static int s3c_pm_ops_suspend(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct mtd_info *mtd = platform_get_drvdata(pdev);
- struct onenand_chip *this = mtd->priv;
-
- this->wait(mtd, FL_PM_SUSPENDED);
- return 0;
-}
-
static int s3c_pm_ops_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct mtd_info *mtd = platform_get_drvdata(pdev);
struct onenand_chip *this = mtd->priv;
+ clk_enable(this->clk);
this->unlock_all(mtd);
+ clk_disable(this->clk);
return 0;
}
static const struct dev_pm_ops s3c_pm_ops = {
- .suspend = s3c_pm_ops_suspend,
.resume = s3c_pm_ops_resume,
};
diff --git a/drivers/mtd/sm_ftl.c b/drivers/mtd/sm_ftl.c
index ed3d6cd..0e34d56 100644
--- a/drivers/mtd/sm_ftl.c
+++ b/drivers/mtd/sm_ftl.c
@@ -1256,7 +1256,7 @@ static void sm_remove_dev(struct mtd_blktrans_dev *dev)
static struct mtd_blktrans_ops sm_ftl_ops = {
.name = "smblk",
- .major = -1,
+ .major = 0,
.part_bits = SM_FTL_PARTN_BITS,
.blksize = SM_SECTOR_SIZE,
.getgeo = sm_getgeo,
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 65626c1..2b351d0 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -816,6 +816,11 @@ static int autoresize(struct ubi_device *ubi, int vol_id)
struct ubi_volume *vol = ubi->volumes[vol_id];
int err, old_reserved_pebs = vol->reserved_pebs;
+ if (ubi->ro_mode) {
+ ubi_warn("skip auto-resize because of R/O mode");
+ return 0;
+ }
+
/*
* Clear the auto-resize flag in the volume in-memory copy of the
* volume table, and 'ubi_resize_volume()' will propagate this change
diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c
index fd3bf77..326bd93 100644
--- a/drivers/mtd/ubi/vtbl.c
+++ b/drivers/mtd/ubi/vtbl.c
@@ -356,7 +356,7 @@ retry:
*/
err = ubi_scan_add_used(ubi, si, new_seb->pnum, new_seb->ec,
vid_hdr, 0);
- kfree(new_seb);
+ kmem_cache_free(si->scan_leb_slab, new_seb);
ubi_free_vid_hdr(ubi, vid_hdr);
return err;
@@ -369,7 +369,7 @@ write_error:
list_add(&new_seb->u.list, &si->erase);
goto retry;
}
- kfree(new_seb);
+ kmem_cache_free(si->scan_leb_slab, new_seb);
out_free:
ubi_free_vid_hdr(ubi, vid_hdr);
return err;
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 906ef8f..5a92c48 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2543,7 +2543,7 @@ config S6GMAC
source "drivers/net/stmmac/Kconfig"
config PCH_GBE
- tristate "Intel EG20T PCH / OKI SEMICONDUCTOR ML7223 IOH GbE"
+ tristate "Intel EG20T PCH/OKI SEMICONDUCTOR IOH(ML7223/ML7831) GbE"
depends on PCI
select MII
---help---
@@ -2556,10 +2556,11 @@ config PCH_GBE
This driver enables Gigabit Ethernet function.
This driver also can be used for OKI SEMICONDUCTOR IOH(Input/
- Output Hub), ML7223.
- ML7223 IOH is for MP(Media Phone) use.
- ML7223 is companion chip for Intel Atom E6xx series.
- ML7223 is completely compatible for Intel EG20T PCH.
+ Output Hub), ML7223/ML7831.
+ ML7223 IOH is for MP(Media Phone) use. ML7831 IOH is for general
+ purpose use.
+ ML7223/ML7831 is companion chip for Intel Atom E6xx series.
+ ML7223/ML7831 is completely compatible for Intel EG20T PCH.
endif # NETDEV_1000
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c
index a485f7f..2ce5db5 100644
--- a/drivers/net/benet/be_main.c
+++ b/drivers/net/benet/be_main.c
@@ -763,6 +763,8 @@ static netdev_tx_t be_xmit(struct sk_buff *skb,
copied = make_tx_wrbs(adapter, skb, wrb_cnt, dummy_wrb);
if (copied) {
+ int gso_segs = skb_shinfo(skb)->gso_segs;
+
/* record the sent skb in the sent_skb table */
BUG_ON(tx_obj->sent_skb_list[start]);
tx_obj->sent_skb_list[start] = skb;
@@ -780,8 +782,7 @@ static netdev_tx_t be_xmit(struct sk_buff *skb,
be_txq_notify(adapter, txq->id, wrb_cnt);
- be_tx_stats_update(adapter, wrb_cnt, copied,
- skb_shinfo(skb)->gso_segs, stopped);
+ be_tx_stats_update(adapter, wrb_cnt, copied, gso_segs, stopped);
} else {
txq->head = start;
dev_kfree_skb_any(skb);
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 74580bb..c9b123c 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -5310,7 +5310,7 @@ bnx2_free_tx_skbs(struct bnx2 *bp)
int k, last;
if (skb == NULL) {
- j++;
+ j = NEXT_TX_BD(j);
continue;
}
@@ -5322,8 +5322,8 @@ bnx2_free_tx_skbs(struct bnx2 *bp)
tx_buf->skb = NULL;
last = tx_buf->nr_frags;
- j++;
- for (k = 0; k < last; k++, j++) {
+ j = NEXT_TX_BD(j);
+ for (k = 0; k < last; k++, j = NEXT_TX_BD(j)) {
tx_buf = &txr->tx_buf_ring[TX_RING_IDX(j)];
dma_unmap_page(&bp->pdev->dev,
dma_unmap_addr(tx_buf, mapping),
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index e6da842..504e201 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -77,6 +77,7 @@
#include <net/route.h>
#include <net/net_namespace.h>
#include <net/netns/generic.h>
+#include <net/pkt_sched.h>
#include "bonding.h"
#include "bond_3ad.h"
#include "bond_alb.h"
@@ -388,8 +389,6 @@ struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr)
return next;
}
-#define bond_queue_mapping(skb) (*(u16 *)((skb)->cb))
-
/**
* bond_dev_queue_xmit - Prepare skb for xmit.
*
@@ -403,7 +402,9 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb,
skb->dev = slave_dev;
skb->priority = 1;
- skb->queue_mapping = bond_queue_mapping(skb);
+ BUILD_BUG_ON(sizeof(skb->queue_mapping) !=
+ sizeof(qdisc_skb_cb(skb)->bond_queue_mapping));
+ skb->queue_mapping = qdisc_skb_cb(skb)->bond_queue_mapping;
if (unlikely(netpoll_tx_running(slave_dev)))
bond_netpoll_send_skb(bond_get_slave_by_dev(bond, slave_dev), skb);
@@ -4240,7 +4241,7 @@ static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb)
/*
* Save the original txq to restore before passing to the driver
*/
- bond_queue_mapping(skb) = skb->queue_mapping;
+ qdisc_skb_cb(skb)->bond_queue_mapping = skb->queue_mapping;
if (unlikely(txq >= dev->real_num_tx_queues)) {
do {
diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c
index 3df0c0f..82b1802 100644
--- a/drivers/net/caif/caif_serial.c
+++ b/drivers/net/caif/caif_serial.c
@@ -325,6 +325,9 @@ static int ldisc_open(struct tty_struct *tty)
sprintf(name, "cf%s", tty->name);
dev = alloc_netdev(sizeof(*ser), name, caifdev_setup);
+ if (!dev)
+ return -ENOMEM;
+
ser = netdev_priv(dev);
ser->tty = tty_kref_get(tty);
ser->dev = dev;
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index 7e5cc0b..1bf8032 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -592,8 +592,8 @@ static void c_can_chip_config(struct net_device *dev)
priv->write_reg(priv, &priv->regs->control,
CONTROL_ENABLE_AR);
- if (priv->can.ctrlmode & (CAN_CTRLMODE_LISTENONLY &
- CAN_CTRLMODE_LOOPBACK)) {
+ if ((priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) &&
+ (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)) {
/* loopback + silent mode : useful for hot self-test */
priv->write_reg(priv, &priv->regs->control, CONTROL_EIE |
CONTROL_SIE | CONTROL_IE | CONTROL_TEST);
@@ -688,7 +688,7 @@ static int c_can_get_berr_counter(const struct net_device *dev,
*
* We iterate from priv->tx_echo to priv->tx_next and check if the
* packet has been transmitted, echo it back to the CAN framework.
- * If we discover a not yet transmitted package, stop looking for more.
+ * If we discover a not yet transmitted packet, stop looking for more.
*/
static void c_can_do_tx(struct net_device *dev)
{
@@ -700,7 +700,7 @@ static void c_can_do_tx(struct net_device *dev)
for (/* nix */; (priv->tx_next - priv->tx_echo) > 0; priv->tx_echo++) {
msg_obj_no = get_tx_echo_msg_obj(priv);
val = c_can_read_reg32(priv, &priv->regs->txrqst1);
- if (!(val & (1 << msg_obj_no))) {
+ if (!(val & (1 << (msg_obj_no - 1)))) {
can_get_echo_skb(dev,
msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST);
stats->tx_bytes += priv->read_reg(priv,
@@ -708,6 +708,8 @@ static void c_can_do_tx(struct net_device *dev)
& IF_MCONT_DLC_MASK;
stats->tx_packets++;
c_can_inval_msg_object(dev, 0, msg_obj_no);
+ } else {
+ break;
}
}
@@ -952,7 +954,7 @@ static int c_can_poll(struct napi_struct *napi, int quota)
struct net_device *dev = napi->dev;
struct c_can_priv *priv = netdev_priv(dev);
- irqstatus = priv->read_reg(priv, &priv->regs->interrupt);
+ irqstatus = priv->irqstatus;
if (!irqstatus)
goto end;
@@ -1030,12 +1032,11 @@ end:
static irqreturn_t c_can_isr(int irq, void *dev_id)
{
- u16 irqstatus;
struct net_device *dev = (struct net_device *)dev_id;
struct c_can_priv *priv = netdev_priv(dev);
- irqstatus = priv->read_reg(priv, &priv->regs->interrupt);
- if (!irqstatus)
+ priv->irqstatus = priv->read_reg(priv, &priv->regs->interrupt);
+ if (!priv->irqstatus)
return IRQ_NONE;
/* disable all interrupts and schedule the NAPI */
@@ -1065,10 +1066,11 @@ static int c_can_open(struct net_device *dev)
goto exit_irq_fail;
}
+ napi_enable(&priv->napi);
+
/* start the c_can controller */
c_can_start(dev);
- napi_enable(&priv->napi);
netif_start_queue(dev);
return 0;
diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h
index 9b7fbef..5f32d34 100644
--- a/drivers/net/can/c_can/c_can.h
+++ b/drivers/net/can/c_can/c_can.h
@@ -76,6 +76,7 @@ struct c_can_priv {
unsigned int tx_next;
unsigned int tx_echo;
void *priv; /* for board-specific data */
+ u16 irqstatus;
};
struct net_device *alloc_c_can_dev(void);
diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c
index f1942ca..b4159a6 100644
--- a/drivers/net/can/janz-ican3.c
+++ b/drivers/net/can/janz-ican3.c
@@ -1249,7 +1249,6 @@ static irqreturn_t ican3_irq(int irq, void *dev_id)
*/
static int ican3_reset_module(struct ican3_dev *mod)
{
- u8 val = 1 << mod->num;
unsigned long start;
u8 runold, runnew;
@@ -1263,8 +1262,7 @@ static int ican3_reset_module(struct ican3_dev *mod)
runold = ioread8(mod->dpm + TARGET_RUNNING);
/* reset the module */
- iowrite8(val, &mod->ctrl->reset_assert);
- iowrite8(val, &mod->ctrl->reset_deassert);
+ iowrite8(0x00, &mod->dpmctrl->hwreset);
/* wait until the module has finished resetting and is running */
start = jiffies;
diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c
index 330140e..9bcc39a 100644
--- a/drivers/net/can/mcp251x.c
+++ b/drivers/net/can/mcp251x.c
@@ -83,6 +83,11 @@
#define INSTRUCTION_LOAD_TXB(n) (0x40 + 2 * (n))
#define INSTRUCTION_READ_RXB(n) (((n) == 0) ? 0x90 : 0x94)
#define INSTRUCTION_RESET 0xC0
+#define RTS_TXB0 0x01
+#define RTS_TXB1 0x02
+#define RTS_TXB2 0x04
+#define INSTRUCTION_RTS(n) (0x80 | ((n) & 0x07))
+
/* MPC251x registers */
#define CANSTAT 0x0e
@@ -397,6 +402,7 @@ static void mcp251x_hw_tx_frame(struct spi_device *spi, u8 *buf,
static void mcp251x_hw_tx(struct spi_device *spi, struct can_frame *frame,
int tx_buf_idx)
{
+ struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
u32 sid, eid, exide, rtr;
u8 buf[SPI_TRANSFER_BUF_LEN];
@@ -418,7 +424,10 @@ static void mcp251x_hw_tx(struct spi_device *spi, struct can_frame *frame,
buf[TXBDLC_OFF] = (rtr << DLC_RTR_SHIFT) | frame->can_dlc;
memcpy(buf + TXBDAT_OFF, frame->data, frame->can_dlc);
mcp251x_hw_tx_frame(spi, buf, frame->can_dlc, tx_buf_idx);
- mcp251x_write_reg(spi, TXBCTRL(tx_buf_idx), TXBCTRL_TXREQ);
+
+ /* use INSTRUCTION_RTS, to avoid "repeated frame problem" */
+ priv->spi_tx_buf[0] = INSTRUCTION_RTS(1 << tx_buf_idx);
+ mcp251x_spi_trans(priv->spi, 1);
}
static void mcp251x_hw_rx_frame(struct spi_device *spi, u8 *buf,
diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index 5fedc33..d8f2b5b 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -181,7 +181,7 @@ static u32 __devinit mpc512x_can_get_clock(struct platform_device *ofdev,
if (!clock_name || !strcmp(clock_name, "sys")) {
sys_clk = clk_get(&ofdev->dev, "sys_clk");
- if (!sys_clk) {
+ if (IS_ERR(sys_clk)) {
dev_err(&ofdev->dev, "couldn't get sys_clk\n");
goto exit_unmap;
}
@@ -204,7 +204,7 @@ static u32 __devinit mpc512x_can_get_clock(struct platform_device *ofdev,
if (clocksrc < 0) {
ref_clk = clk_get(&ofdev->dev, "ref_clk");
- if (!ref_clk) {
+ if (IS_ERR(ref_clk)) {
dev_err(&ofdev->dev, "couldn't get ref_clk\n");
goto exit_unmap;
}
diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c
index f7bbde9..6ea2c09 100644
--- a/drivers/net/can/ti_hecc.c
+++ b/drivers/net/can/ti_hecc.c
@@ -969,12 +969,12 @@ static int __devexit ti_hecc_remove(struct platform_device *pdev)
struct net_device *ndev = platform_get_drvdata(pdev);
struct ti_hecc_priv *priv = netdev_priv(ndev);
+ unregister_candev(ndev);
clk_disable(priv->clk);
clk_put(priv->clk);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
iounmap(priv->base);
release_mem_region(res->start, resource_size(res));
- unregister_candev(ndev);
free_candev(ndev);
platform_set_drvdata(pdev, NULL);
diff --git a/drivers/net/davinci_cpdma.c b/drivers/net/davinci_cpdma.c
index ae47f23..6b67c52 100644
--- a/drivers/net/davinci_cpdma.c
+++ b/drivers/net/davinci_cpdma.c
@@ -849,6 +849,7 @@ int cpdma_chan_stop(struct cpdma_chan *chan)
next_dma = desc_read(desc, hw_next);
chan->head = desc_from_phys(pool, next_dma);
+ chan->count--;
chan->stats.teardown_dequeue++;
/* issue callback without locks held */
diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index 3fa19c1..098ff31 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -37,6 +37,7 @@
#include <linux/rtnetlink.h>
#include <net/rtnetlink.h>
#include <linux/u64_stats_sync.h>
+#include <linux/sched.h>
static int numdummies = 1;
@@ -186,8 +187,10 @@ static int __init dummy_init_module(void)
rtnl_lock();
err = __rtnl_link_register(&dummy_link_ops);
- for (i = 0; i < numdummies && !err; i++)
+ for (i = 0; i < numdummies && !err; i++) {
err = dummy_init_one();
+ cond_resched();
+ }
if (err < 0)
__rtnl_link_unregister(&dummy_link_ops);
rtnl_unlock();
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index 8676899..2c71884 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -150,6 +150,8 @@ struct e1000_buffer {
unsigned long time_stamp;
u16 length;
u16 next_to_watch;
+ unsigned int segs;
+ unsigned int bytecount;
u16 mapped_as_page;
};
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 76e8af0..99525f9 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -2798,7 +2798,7 @@ static int e1000_tx_map(struct e1000_adapter *adapter,
struct e1000_buffer *buffer_info;
unsigned int len = skb_headlen(skb);
unsigned int offset = 0, size, count = 0, i;
- unsigned int f;
+ unsigned int f, bytecount, segs;
i = tx_ring->next_to_use;
@@ -2899,7 +2899,13 @@ static int e1000_tx_map(struct e1000_adapter *adapter,
}
}
+ segs = skb_shinfo(skb)->gso_segs ?: 1;
+ /* multiply data chunks by size of headers */
+ bytecount = ((segs - 1) * skb_headlen(skb)) + skb->len;
+
tx_ring->buffer_info[i].skb = skb;
+ tx_ring->buffer_info[i].segs = segs;
+ tx_ring->buffer_info[i].bytecount = bytecount;
tx_ring->buffer_info[first].next_to_watch = i;
return count;
@@ -3573,14 +3579,8 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
cleaned = (i == eop);
if (cleaned) {
- struct sk_buff *skb = buffer_info->skb;
- unsigned int segs, bytecount;
- segs = skb_shinfo(skb)->gso_segs ?: 1;
- /* multiply data chunks by size of headers */
- bytecount = ((segs - 1) * skb_headlen(skb)) +
- skb->len;
- total_tx_packets += segs;
- total_tx_bytes += bytecount;
+ total_tx_packets += buffer_info->segs;
+ total_tx_bytes += buffer_info->bytecount;
}
e1000_unmap_and_free_tx_resource(adapter, buffer_info);
tx_desc->upper.data = 0;
diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c
index 8295f21..8402d19 100644
--- a/drivers/net/e1000e/82571.c
+++ b/drivers/net/e1000e/82571.c
@@ -1573,6 +1573,9 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
ctrl = er32(CTRL);
status = er32(STATUS);
rxcw = er32(RXCW);
+ /* SYNCH bit and IV bit are sticky */
+ udelay(10);
+ rxcw = er32(RXCW);
if ((rxcw & E1000_RXCW_SYNCH) && !(rxcw & E1000_RXCW_IV)) {
@@ -1599,10 +1602,8 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
* auto-negotiation in the TXCW register and disable
* forced link in the Device Control register in an
* attempt to auto-negotiate with our link partner.
- * If the partner code word is null, stop forcing
- * and restart auto negotiation.
*/
- if ((rxcw & E1000_RXCW_C) || !(rxcw & E1000_RXCW_CW)) {
+ if (rxcw & E1000_RXCW_C) {
/* Enable autoneg, and unforce link up */
ew32(TXCW, mac->txcw);
ew32(CTRL, (ctrl & ~E1000_CTRL_SLU));
@@ -2087,7 +2088,8 @@ struct e1000_info e1000_82574_info = {
| FLAG_HAS_AMT
| FLAG_HAS_CTRLEXT_ON_LOAD,
.flags2 = FLAG2_CHECK_PHY_HANG
- | FLAG2_DISABLE_ASPM_L0S,
+ | FLAG2_DISABLE_ASPM_L0S
+ | FLAG2_DISABLE_ASPM_L1,
.pba = 32,
.max_hw_frame_size = DEFAULT_JUMBO,
.get_variants = e1000_get_variants_82571,
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index ab4723d..735f726 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -247,7 +247,7 @@ static int macvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev)
xmit_world:
skb->ip_summed = ip_summed;
- skb_set_dev(skb, vlan->lowerdev);
+ skb->dev = vlan->lowerdev;
return dev_queue_xmit(skb);
}
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 4840ab7..4309296 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -652,7 +652,6 @@ static int netconsole_netdev_event(struct notifier_block *this,
flags);
dev_put(nt->np.dev);
nt->np.dev = NULL;
- netconsole_target_put(nt);
}
nt->enabled = 0;
stopped = true;
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index c0788a3..78d5b67 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -1288,6 +1288,10 @@ static void netxen_mask_aer_correctable(struct netxen_adapter *adapter)
struct pci_dev *root = pdev->bus->self;
u32 aer_pos;
+ /* root bus? */
+ if (!root)
+ return;
+
if (adapter->ahw.board_type != NETXEN_BRDTYPE_P3_4_GB_MM &&
adapter->ahw.board_type != NETXEN_BRDTYPE_P3_10G_TP)
return;
diff --git a/drivers/net/pch_gbe/pch_gbe_main.c b/drivers/net/pch_gbe/pch_gbe_main.c
index eac3c5c..236d00e 100644
--- a/drivers/net/pch_gbe/pch_gbe_main.c
+++ b/drivers/net/pch_gbe/pch_gbe_main.c
@@ -39,6 +39,9 @@ const char pch_driver_version[] = DRV_VERSION;
#define PCI_VENDOR_ID_ROHM 0x10db
#define PCI_DEVICE_ID_ROHM_ML7223_GBE 0x8013
+/* Macros for ML7831 */
+#define PCI_DEVICE_ID_ROHM_ML7831_GBE 0x8802
+
#define PCH_GBE_TX_WEIGHT 64
#define PCH_GBE_RX_WEIGHT 64
#define PCH_GBE_RX_BUFFER_WRITE 16
@@ -717,13 +720,6 @@ static void pch_gbe_configure_rx(struct pch_gbe_adapter *adapter)
iowrite32(rdba, &hw->reg->RX_DSC_BASE);
iowrite32(rdlen, &hw->reg->RX_DSC_SIZE);
iowrite32((rdba + rdlen), &hw->reg->RX_DSC_SW_P);
-
- /* Enables Receive DMA */
- rxdma = ioread32(&hw->reg->DMA_CTRL);
- rxdma |= PCH_GBE_RX_DMA_EN;
- iowrite32(rxdma, &hw->reg->DMA_CTRL);
- /* Enables Receive */
- iowrite32(PCH_GBE_MRE_MAC_RX_EN, &hw->reg->MAC_RX_EN);
}
/**
@@ -1097,6 +1093,19 @@ void pch_gbe_update_stats(struct pch_gbe_adapter *adapter)
spin_unlock_irqrestore(&adapter->stats_lock, flags);
}
+static void pch_gbe_start_receive(struct pch_gbe_hw *hw)
+{
+ u32 rxdma;
+
+ /* Enables Receive DMA */
+ rxdma = ioread32(&hw->reg->DMA_CTRL);
+ rxdma |= PCH_GBE_RX_DMA_EN;
+ iowrite32(rxdma, &hw->reg->DMA_CTRL);
+ /* Enables Receive */
+ iowrite32(PCH_GBE_MRE_MAC_RX_EN, &hw->reg->MAC_RX_EN);
+ return;
+}
+
/**
* pch_gbe_intr - Interrupt Handler
* @irq: Interrupt number
@@ -1701,6 +1710,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);
@@ -1717,6 +1732,7 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter)
pch_gbe_alloc_tx_buffers(adapter, tx_ring);
pch_gbe_alloc_rx_buffers(adapter, rx_ring, rx_ring->count);
adapter->tx_queue_len = netdev->tx_queue_len;
+ pch_gbe_start_receive(&adapter->hw);
mod_timer(&adapter->watchdog_timer, jiffies);
@@ -2118,7 +2134,7 @@ static int pch_gbe_napi_poll(struct napi_struct *napi, int budget)
/* If no Tx and not enough Rx work done,
* exit the polling mode
*/
- if ((work_done < budget) || !netif_running(netdev))
+ if (work_done < budget)
poll_end_flag = true;
}
@@ -2392,9 +2408,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);
@@ -2452,6 +2473,13 @@ static DEFINE_PCI_DEVICE_TABLE(pch_gbe_pcidev_id) = {
.class = (PCI_CLASS_NETWORK_ETHERNET << 8),
.class_mask = (0xFFFF00)
},
+ {.vendor = PCI_VENDOR_ID_ROHM,
+ .device = PCI_DEVICE_ID_ROHM_ML7831_GBE,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .class = (PCI_CLASS_NETWORK_ETHERNET << 8),
+ .class_mask = (0xFFFF00)
+ },
/* required last entry */
{0}
};
diff --git a/drivers/net/pch_gbe/pch_gbe_param.c b/drivers/net/pch_gbe/pch_gbe_param.c
index 5b5d90a..fb74ef9 100644
--- a/drivers/net/pch_gbe/pch_gbe_param.c
+++ b/drivers/net/pch_gbe/pch_gbe_param.c
@@ -320,10 +320,10 @@ static void pch_gbe_check_copper_options(struct pch_gbe_adapter *adapter)
pr_debug("AutoNeg specified along with Speed or Duplex, AutoNeg parameter ignored\n");
hw->phy.autoneg_advertised = opt.def;
} else {
- hw->phy.autoneg_advertised = AutoNeg;
- pch_gbe_validate_option(
- (int *)(&hw->phy.autoneg_advertised),
- &opt, adapter);
+ int tmp = AutoNeg;
+
+ pch_gbe_validate_option(&tmp, &opt, adapter);
+ hw->phy.autoneg_advertised = tmp;
}
}
@@ -494,9 +494,10 @@ void pch_gbe_check_options(struct pch_gbe_adapter *adapter)
.arg = { .l = { .nr = (int)ARRAY_SIZE(fc_list),
.p = fc_list } }
};
- hw->mac.fc = FlowControl;
- pch_gbe_validate_option((int *)(&hw->mac.fc),
- &opt, adapter);
+ int tmp = FlowControl;
+
+ pch_gbe_validate_option(&tmp, &opt, adapter);
+ hw->mac.fc = tmp;
}
pch_gbe_check_copper_options(adapter);
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index bc9a4bb..1161584 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -576,7 +576,7 @@ static int pppoe_release(struct socket *sock)
po = pppox_sk(sk);
- if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) {
+ if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) {
dev_put(po->pppoe_dev);
po->pppoe_dev = NULL;
}
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 5f838ef..f7a56f4 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -58,8 +58,12 @@
#define R8169_MSG_DEFAULT \
(NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN)
-#define TX_BUFFS_AVAIL(tp) \
- (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1)
+#define TX_SLOTS_AVAIL(tp) \
+ (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx)
+
+/* A skbuff with nr_frags needs nr_frags+1 entries in the tx queue */
+#define TX_FRAGS_READY_FOR(tp,nr_frags) \
+ (TX_SLOTS_AVAIL(tp) >= (nr_frags + 1))
/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
The RTL chips use a 64 element hash table based on the Ethernet CRC. */
@@ -140,82 +144,101 @@ enum rtl_tx_desc_version {
RTL_TD_1 = 1,
};
-#define _R(NAME,TD,FW) \
- { .name = NAME, .txd_version = TD, .fw_name = FW }
+#define JUMBO_1K ETH_DATA_LEN
+#define JUMBO_4K (4*1024 - ETH_HLEN - 2)
+#define JUMBO_6K (6*1024 - ETH_HLEN - 2)
+#define JUMBO_7K (7*1024 - ETH_HLEN - 2)
+#define JUMBO_9K (9*1024 - ETH_HLEN - 2)
+
+#define _R(NAME,TD,FW,SZ,B) { \
+ .name = NAME, \
+ .txd_version = TD, \
+ .fw_name = FW, \
+ .jumbo_max = SZ, \
+ .jumbo_tx_csum = B \
+}
static const struct {
const char *name;
enum rtl_tx_desc_version txd_version;
const char *fw_name;
+ u16 jumbo_max;
+ bool jumbo_tx_csum;
} rtl_chip_infos[] = {
/* PCI devices. */
[RTL_GIGA_MAC_VER_01] =
- _R("RTL8169", RTL_TD_0, NULL),
+ _R("RTL8169", RTL_TD_0, NULL, JUMBO_7K, true),
[RTL_GIGA_MAC_VER_02] =
- _R("RTL8169s", RTL_TD_0, NULL),
+ _R("RTL8169s", RTL_TD_0, NULL, JUMBO_7K, true),
[RTL_GIGA_MAC_VER_03] =
- _R("RTL8110s", RTL_TD_0, NULL),
+ _R("RTL8110s", RTL_TD_0, NULL, JUMBO_7K, true),
[RTL_GIGA_MAC_VER_04] =
- _R("RTL8169sb/8110sb", RTL_TD_0, NULL),
+ _R("RTL8169sb/8110sb", RTL_TD_0, NULL, JUMBO_7K, true),
[RTL_GIGA_MAC_VER_05] =
- _R("RTL8169sc/8110sc", RTL_TD_0, NULL),
+ _R("RTL8169sc/8110sc", RTL_TD_0, NULL, JUMBO_7K, true),
[RTL_GIGA_MAC_VER_06] =
- _R("RTL8169sc/8110sc", RTL_TD_0, NULL),
+ _R("RTL8169sc/8110sc", RTL_TD_0, NULL, JUMBO_7K, true),
/* PCI-E devices. */
[RTL_GIGA_MAC_VER_07] =
- _R("RTL8102e", RTL_TD_1, NULL),
+ _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true),
[RTL_GIGA_MAC_VER_08] =
- _R("RTL8102e", RTL_TD_1, NULL),
+ _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true),
[RTL_GIGA_MAC_VER_09] =
- _R("RTL8102e", RTL_TD_1, NULL),
+ _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true),
[RTL_GIGA_MAC_VER_10] =
- _R("RTL8101e", RTL_TD_0, NULL),
+ _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true),
[RTL_GIGA_MAC_VER_11] =
- _R("RTL8168b/8111b", RTL_TD_0, NULL),
+ _R("RTL8168b/8111b", RTL_TD_0, NULL, JUMBO_4K, false),
[RTL_GIGA_MAC_VER_12] =
- _R("RTL8168b/8111b", RTL_TD_0, NULL),
+ _R("RTL8168b/8111b", RTL_TD_0, NULL, JUMBO_4K, false),
[RTL_GIGA_MAC_VER_13] =
- _R("RTL8101e", RTL_TD_0, NULL),
+ _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true),
[RTL_GIGA_MAC_VER_14] =
- _R("RTL8100e", RTL_TD_0, NULL),
+ _R("RTL8100e", RTL_TD_0, NULL, JUMBO_1K, true),
[RTL_GIGA_MAC_VER_15] =
- _R("RTL8100e", RTL_TD_0, NULL),
+ _R("RTL8100e", RTL_TD_0, NULL, JUMBO_1K, true),
[RTL_GIGA_MAC_VER_16] =
- _R("RTL8101e", RTL_TD_0, NULL),
+ _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true),
[RTL_GIGA_MAC_VER_17] =
- _R("RTL8168b/8111b", RTL_TD_0, NULL),
+ _R("RTL8168b/8111b", RTL_TD_1, NULL, JUMBO_4K, false),
[RTL_GIGA_MAC_VER_18] =
- _R("RTL8168cp/8111cp", RTL_TD_1, NULL),
+ _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false),
[RTL_GIGA_MAC_VER_19] =
- _R("RTL8168c/8111c", RTL_TD_1, NULL),
+ _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false),
[RTL_GIGA_MAC_VER_20] =
- _R("RTL8168c/8111c", RTL_TD_1, NULL),
+ _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false),
[RTL_GIGA_MAC_VER_21] =
- _R("RTL8168c/8111c", RTL_TD_1, NULL),
+ _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false),
[RTL_GIGA_MAC_VER_22] =
- _R("RTL8168c/8111c", RTL_TD_1, NULL),
+ _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false),
[RTL_GIGA_MAC_VER_23] =
- _R("RTL8168cp/8111cp", RTL_TD_1, NULL),
+ _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false),
[RTL_GIGA_MAC_VER_24] =
- _R("RTL8168cp/8111cp", RTL_TD_1, NULL),
+ _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false),
[RTL_GIGA_MAC_VER_25] =
- _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_1),
+ _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_1,
+ JUMBO_9K, false),
[RTL_GIGA_MAC_VER_26] =
- _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_2),
+ _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_2,
+ JUMBO_9K, false),
[RTL_GIGA_MAC_VER_27] =
- _R("RTL8168dp/8111dp", RTL_TD_1, NULL),
+ _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false),
[RTL_GIGA_MAC_VER_28] =
- _R("RTL8168dp/8111dp", RTL_TD_1, NULL),
+ _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false),
[RTL_GIGA_MAC_VER_29] =
- _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1),
+ _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1,
+ JUMBO_1K, true),
[RTL_GIGA_MAC_VER_30] =
- _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1),
+ _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1,
+ JUMBO_1K, true),
[RTL_GIGA_MAC_VER_31] =
- _R("RTL8168dp/8111dp", RTL_TD_1, NULL),
+ _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false),
[RTL_GIGA_MAC_VER_32] =
- _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_1),
+ _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_1,
+ JUMBO_9K, false),
[RTL_GIGA_MAC_VER_33] =
- _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_2)
+ _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_2,
+ JUMBO_9K, false)
};
#undef _R
@@ -280,6 +303,8 @@ enum rtl_registers {
Config0 = 0x51,
Config1 = 0x52,
Config2 = 0x53,
+#define PME_SIGNAL (1 << 5) /* 8168c and later */
+
Config3 = 0x54,
Config4 = 0x55,
Config5 = 0x56,
@@ -388,6 +413,7 @@ enum rtl_register_content {
RxOK = 0x0001,
/* RxStatusDesc */
+ RxBOVF = (1 << 24),
RxFOVF = (1 << 23),
RxRWT = (1 << 22),
RxRES = (1 << 21),
@@ -428,7 +454,6 @@ enum rtl_register_content {
/* Config1 register p.24 */
LEDS1 = (1 << 7),
LEDS0 = (1 << 6),
- MSIEnable = (1 << 5), /* Enable Message Signaled Interrupt */
Speed_down = (1 << 4),
MEMMAP = (1 << 3),
IOMAP = (1 << 2),
@@ -436,14 +461,19 @@ enum rtl_register_content {
PMEnable = (1 << 0), /* Power Management Enable */
/* Config2 register p. 25 */
+ MSIEnable = (1 << 5), /* 8169 only. Reserved in the 8168. */
PCI_Clock_66MHz = 0x01,
PCI_Clock_33MHz = 0x00,
/* Config3 register p.25 */
MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */
LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */
+ Jumbo_En0 = (1 << 2), /* 8168 only. Reserved in the 8168b */
Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */
+ /* Config4 register */
+ Jumbo_En1 = (1 << 1), /* 8168 only. Reserved in the 8168b */
+
/* Config5 register p.27 */
BWF = (1 << 6), /* Accept Broadcast wakeup frame */
MWF = (1 << 5), /* Accept Multicast wakeup frame */
@@ -652,6 +682,11 @@ struct rtl8169_private {
void (*up)(struct rtl8169_private *);
} pll_power_ops;
+ struct jumbo_ops {
+ void (*enable)(struct rtl8169_private *);
+ void (*disable)(struct rtl8169_private *);
+ } jumbo_ops;
+
int (*set_speed)(struct net_device *, u8 aneg, u16 sp, u8 dpx, u32 adv);
int (*get_settings)(struct net_device *, struct ethtool_cmd *);
void (*phy_reset_enable)(struct rtl8169_private *tp);
@@ -666,6 +701,7 @@ struct rtl8169_private {
struct mii_if_info mii;
struct rtl8169_counters counters;
u32 saved_wolopts;
+ u32 opts1_mask;
const struct firmware *fw;
#define RTL_FIRMWARE_UNKNOWN ERR_PTR(-EAGAIN);
@@ -705,6 +741,21 @@ static int rtl8169_poll(struct napi_struct *napi, int budget);
static const unsigned int rtl8169_rx_config =
(RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift);
+static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct rtl8169_private *tp = netdev_priv(dev);
+ int cap = tp->pcie_cap;
+
+ if (cap) {
+ u16 ctl;
+
+ pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl);
+ ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force;
+ pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl);
+ }
+}
+
static u32 ocp_read(struct rtl8169_private *tp, u8 mask, u16 reg)
{
void __iomem *ioaddr = tp->mmio_addr;
@@ -1043,17 +1094,21 @@ static u8 rtl8168d_efuse_read(void __iomem *ioaddr, int reg_addr)
return value;
}
-static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr)
+static void rtl8169_irq_mask_and_ack(struct rtl8169_private *tp)
{
- RTL_W16(IntrMask, 0x0000);
+ void __iomem *ioaddr = tp->mmio_addr;
- RTL_W16(IntrStatus, 0xffff);
+ RTL_W16(IntrMask, 0x0000);
+ RTL_W16(IntrStatus, tp->intr_event);
+ RTL_R8(ChipCmd);
}
-static void rtl8169_asic_down(void __iomem *ioaddr)
+static void rtl8169_asic_down(struct rtl8169_private *tp)
{
+ void __iomem *ioaddr = tp->mmio_addr;
+
RTL_W8(ChipCmd, 0x00);
- rtl8169_irq_mask_and_ack(ioaddr);
+ rtl8169_irq_mask_and_ack(tp);
RTL_R16(CPlusCmd);
}
@@ -1112,7 +1167,7 @@ static void __rtl8169_check_link_status(struct net_device *dev,
netif_carrier_off(dev);
netif_info(tp, ifdown, dev, "link down\n");
if (pm)
- pm_schedule_suspend(&tp->pci_dev->dev, 100);
+ pm_schedule_suspend(&tp->pci_dev->dev, 5000);
}
spin_unlock_irqrestore(&tp->lock, flags);
}
@@ -1174,7 +1229,6 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
u16 reg;
u8 mask;
} cfg[] = {
- { WAKE_ANY, Config1, PMEnable },
{ WAKE_PHY, Config3, LinkUp },
{ WAKE_MAGIC, Config3, MagicPacket },
{ WAKE_UCAST, Config5, UWF },
@@ -1182,16 +1236,32 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
{ WAKE_MCAST, Config5, MWF },
{ WAKE_ANY, Config5, LanWake }
};
+ u8 options;
RTL_W8(Cfg9346, Cfg9346_Unlock);
for (i = 0; i < ARRAY_SIZE(cfg); i++) {
- u8 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask;
+ options = RTL_R8(cfg[i].reg) & ~cfg[i].mask;
if (wolopts & cfg[i].opt)
options |= cfg[i].mask;
RTL_W8(cfg[i].reg, options);
}
+ switch (tp->mac_version) {
+ case RTL_GIGA_MAC_VER_01 ... RTL_GIGA_MAC_VER_17:
+ options = RTL_R8(Config1) & ~PMEnable;
+ if (wolopts)
+ options |= PMEnable;
+ RTL_W8(Config1, options);
+ break;
+ default:
+ options = RTL_R8(Config2) & ~PME_SIGNAL;
+ if (wolopts)
+ options |= PME_SIGNAL;
+ RTL_W8(Config2, options);
+ break;
+ }
+
RTL_W8(Cfg9346, Cfg9346_Lock);
}
@@ -1373,9 +1443,15 @@ static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
static u32 rtl8169_fix_features(struct net_device *dev, u32 features)
{
+ struct rtl8169_private *tp = netdev_priv(dev);
+
if (dev->mtu > TD_MSS_MAX)
features &= ~NETIF_F_ALL_TSO;
+ if (dev->mtu > JUMBO_1K &&
+ !rtl_chip_infos[tp->mac_version].jumbo_tx_csum)
+ features &= ~NETIF_F_IP_CSUM;
+
return features;
}
@@ -2948,22 +3024,24 @@ static const struct rtl_cfg_info {
};
/* Cfg9346_Unlock assumed. */
-static unsigned rtl_try_msi(struct pci_dev *pdev, void __iomem *ioaddr,
+static unsigned rtl_try_msi(struct rtl8169_private *tp,
const struct rtl_cfg_info *cfg)
{
+ void __iomem *ioaddr = tp->mmio_addr;
unsigned msi = 0;
u8 cfg2;
cfg2 = RTL_R8(Config2) & ~MSIEnable;
if (cfg->features & RTL_FEATURE_MSI) {
- if (pci_enable_msi(pdev)) {
- dev_info(&pdev->dev, "no MSI. Back to INTx.\n");
+ if (pci_enable_msi(tp->pci_dev)) {
+ netif_info(tp, hw, tp->dev, "no MSI. Back to INTx.\n");
} else {
cfg2 |= MSIEnable;
msi = RTL_FEATURE_MSI;
}
}
- RTL_W8(Config2, cfg2);
+ if (tp->mac_version <= RTL_GIGA_MAC_VER_06)
+ RTL_W8(Config2, cfg2);
return msi;
}
@@ -3126,8 +3204,10 @@ static void r8168_pll_power_down(struct rtl8169_private *tp)
rtl_writephy(tp, 0x1f, 0x0000);
rtl_writephy(tp, MII_BMCR, 0x0000);
- RTL_W32(RxConfig, RTL_R32(RxConfig) |
- AcceptBroadcast | AcceptMulticast | AcceptMyPhys);
+ if (tp->mac_version == RTL_GIGA_MAC_VER_32 ||
+ tp->mac_version == RTL_GIGA_MAC_VER_33)
+ RTL_W32(RxConfig, RTL_R32(RxConfig) | AcceptBroadcast |
+ AcceptMulticast | AcceptMyPhys);
return;
}
@@ -3172,8 +3252,8 @@ static void r8168_pll_power_up(struct rtl8169_private *tp)
r8168_phy_power_up(tp);
}
-static void rtl_pll_power_op(struct rtl8169_private *tp,
- void (*op)(struct rtl8169_private *))
+static void rtl_generic_op(struct rtl8169_private *tp,
+ void (*op)(struct rtl8169_private *))
{
if (op)
op(tp);
@@ -3181,12 +3261,12 @@ static void rtl_pll_power_op(struct rtl8169_private *tp,
static void rtl_pll_power_down(struct rtl8169_private *tp)
{
- rtl_pll_power_op(tp, tp->pll_power_ops.down);
+ rtl_generic_op(tp, tp->pll_power_ops.down);
}
static void rtl_pll_power_up(struct rtl8169_private *tp)
{
- rtl_pll_power_op(tp, tp->pll_power_ops.up);
+ rtl_generic_op(tp, tp->pll_power_ops.up);
}
static void __devinit rtl_init_pll_power_ops(struct rtl8169_private *tp)
@@ -3233,6 +3313,149 @@ static void __devinit rtl_init_pll_power_ops(struct rtl8169_private *tp)
}
}
+static void rtl_hw_jumbo_enable(struct rtl8169_private *tp)
+{
+ rtl_generic_op(tp, tp->jumbo_ops.enable);
+}
+
+static void rtl_hw_jumbo_disable(struct rtl8169_private *tp)
+{
+ rtl_generic_op(tp, tp->jumbo_ops.disable);
+}
+
+static void r8168c_hw_jumbo_enable(struct rtl8169_private *tp)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+
+ RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
+ RTL_W8(Config4, RTL_R8(Config4) | Jumbo_En1);
+ rtl_tx_performance_tweak(tp->pci_dev, 0x2 << MAX_READ_REQUEST_SHIFT);
+}
+
+static void r8168c_hw_jumbo_disable(struct rtl8169_private *tp)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+
+ RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
+ RTL_W8(Config4, RTL_R8(Config4) & ~Jumbo_En1);
+ rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT);
+}
+
+static void r8168dp_hw_jumbo_enable(struct rtl8169_private *tp)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+
+ RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
+}
+
+static void r8168dp_hw_jumbo_disable(struct rtl8169_private *tp)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+
+ RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
+}
+
+static void r8168e_hw_jumbo_enable(struct rtl8169_private *tp)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+ struct pci_dev *pdev = tp->pci_dev;
+
+ RTL_W8(MaxTxPacketSize, 0x3f);
+ RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
+ RTL_W8(Config4, RTL_R8(Config4) | 0x01);
+ pci_write_config_byte(pdev, 0x79, 0x20);
+}
+
+static void r8168e_hw_jumbo_disable(struct rtl8169_private *tp)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+ struct pci_dev *pdev = tp->pci_dev;
+
+ RTL_W8(MaxTxPacketSize, 0x0c);
+ RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
+ RTL_W8(Config4, RTL_R8(Config4) & ~0x01);
+ pci_write_config_byte(pdev, 0x79, 0x50);
+}
+
+static void r8168b_0_hw_jumbo_enable(struct rtl8169_private *tp)
+{
+ rtl_tx_performance_tweak(tp->pci_dev,
+ (0x2 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
+}
+
+static void r8168b_0_hw_jumbo_disable(struct rtl8169_private *tp)
+{
+ rtl_tx_performance_tweak(tp->pci_dev,
+ (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
+}
+
+static void r8168b_1_hw_jumbo_enable(struct rtl8169_private *tp)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+
+ r8168b_0_hw_jumbo_enable(tp);
+
+ RTL_W8(Config4, RTL_R8(Config4) | (1 << 0));
+}
+
+static void r8168b_1_hw_jumbo_disable(struct rtl8169_private *tp)
+{
+ void __iomem *ioaddr = tp->mmio_addr;
+
+ r8168b_0_hw_jumbo_disable(tp);
+
+ RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0));
+}
+
+static void __devinit rtl_init_jumbo_ops(struct rtl8169_private *tp)
+{
+ struct jumbo_ops *ops = &tp->jumbo_ops;
+
+ switch (tp->mac_version) {
+ case RTL_GIGA_MAC_VER_11:
+ ops->disable = r8168b_0_hw_jumbo_disable;
+ ops->enable = r8168b_0_hw_jumbo_enable;
+ break;
+ case RTL_GIGA_MAC_VER_12:
+ case RTL_GIGA_MAC_VER_17:
+ ops->disable = r8168b_1_hw_jumbo_disable;
+ ops->enable = r8168b_1_hw_jumbo_enable;
+ break;
+ case RTL_GIGA_MAC_VER_18: /* Wild guess. Needs info from Realtek. */
+ case RTL_GIGA_MAC_VER_19:
+ case RTL_GIGA_MAC_VER_20:
+ case RTL_GIGA_MAC_VER_21: /* Wild guess. Needs info from Realtek. */
+ case RTL_GIGA_MAC_VER_22:
+ case RTL_GIGA_MAC_VER_23:
+ case RTL_GIGA_MAC_VER_24:
+ case RTL_GIGA_MAC_VER_25:
+ case RTL_GIGA_MAC_VER_26:
+ ops->disable = r8168c_hw_jumbo_disable;
+ ops->enable = r8168c_hw_jumbo_enable;
+ break;
+ case RTL_GIGA_MAC_VER_27:
+ case RTL_GIGA_MAC_VER_28:
+ ops->disable = r8168dp_hw_jumbo_disable;
+ ops->enable = r8168dp_hw_jumbo_enable;
+ break;
+ case RTL_GIGA_MAC_VER_31: /* Wild guess. Needs info from Realtek. */
+ case RTL_GIGA_MAC_VER_32:
+ case RTL_GIGA_MAC_VER_33:
+ ops->disable = r8168e_hw_jumbo_disable;
+ ops->enable = r8168e_hw_jumbo_enable;
+ break;
+
+ /*
+ * No action needed for jumbo frames with 8169.
+ * No jumbo for 810x at all.
+ */
+ default:
+ ops->disable = NULL;
+ ops->enable = NULL;
+ break;
+ }
+}
+
static void rtl_hw_reset(struct rtl8169_private *tp)
{
void __iomem *ioaddr = tp->mmio_addr;
@@ -3374,6 +3597,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
rtl_init_mdio_ops(tp);
rtl_init_pll_power_ops(tp);
+ rtl_init_jumbo_ops(tp);
rtl8169_print_mac_version(tp);
@@ -3387,7 +3611,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
tp->features |= RTL_FEATURE_WOL;
if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0)
tp->features |= RTL_FEATURE_WOL;
- tp->features |= rtl_try_msi(pdev, ioaddr, cfg);
+ tp->features |= rtl_try_msi(tp, cfg);
RTL_W8(Cfg9346, Cfg9346_Lock);
if ((tp->mac_version <= RTL_GIGA_MAC_VER_06) &&
@@ -3440,6 +3664,9 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
tp->intr_event = cfg->intr_event;
tp->napi_event = cfg->napi_event;
+ tp->opts1_mask = (tp->mac_version != RTL_GIGA_MAC_VER_01) ?
+ ~(RxBOVF | RxFOVF) : ~0;
+
init_timer(&tp->timer);
tp->timer.data = (unsigned long) dev;
tp->timer.function = rtl8169_phy_timer;
@@ -3455,6 +3682,12 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
netif_info(tp, probe, dev, "%s at 0x%lx, %pM, XID %08x IRQ %d\n",
rtl_chip_infos[chipset].name, dev->base_addr, dev->dev_addr,
(u32)(RTL_R32(TxConfig) & 0x9cf0f8ff), dev->irq);
+ if (rtl_chip_infos[chipset].jumbo_max != JUMBO_1K) {
+ netif_info(tp, probe, dev, "jumbo features [frames: %d bytes, "
+ "tx checksumming: %s]\n",
+ rtl_chip_infos[chipset].jumbo_max,
+ rtl_chip_infos[chipset].jumbo_tx_csum ? "ok" : "ko");
+ }
if (tp->mac_version == RTL_GIGA_MAC_VER_27 ||
tp->mac_version == RTL_GIGA_MAC_VER_28 ||
@@ -3473,6 +3706,7 @@ out:
return rc;
err_out_msi_4:
+ netif_napi_del(&tp->napi);
rtl_disable_msi(pdev, tp);
iounmap(ioaddr);
err_out_free_res_3:
@@ -3498,6 +3732,8 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev)
cancel_delayed_work_sync(&tp->task);
+ netif_napi_del(&tp->napi);
+
unregister_netdev(dev);
rtl_release_firmware(tp);
@@ -3611,7 +3847,7 @@ static void rtl8169_hw_reset(struct rtl8169_private *tp)
void __iomem *ioaddr = tp->mmio_addr;
/* Disable interrupts */
- rtl8169_irq_mask_and_ack(ioaddr);
+ rtl8169_irq_mask_and_ack(tp);
if (tp->mac_version == RTL_GIGA_MAC_VER_27 ||
tp->mac_version == RTL_GIGA_MAC_VER_28 ||
@@ -3779,21 +4015,6 @@ static void rtl_hw_start_8169(struct net_device *dev)
RTL_W16(IntrMask, tp->intr_event);
}
-static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force)
-{
- struct net_device *dev = pci_get_drvdata(pdev);
- struct rtl8169_private *tp = netdev_priv(dev);
- int cap = tp->pcie_cap;
-
- if (cap) {
- u16 ctl;
-
- pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl);
- ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force;
- pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl);
- }
-}
-
static void rtl_csi_access_enable(void __iomem *ioaddr, u32 bits)
{
u32 csi;
@@ -4093,8 +4314,7 @@ static void rtl_hw_start_8168(struct net_device *dev)
RTL_W16(IntrMitigate, 0x5151);
/* Work around for RxFIFO overflow. */
- if (tp->mac_version == RTL_GIGA_MAC_VER_11 ||
- tp->mac_version == RTL_GIGA_MAC_VER_22) {
+ if (tp->mac_version == RTL_GIGA_MAC_VER_11) {
tp->intr_event |= RxFIFOOver | PCSTimeout;
tp->intr_event &= ~RxOverflow;
}
@@ -4276,6 +4496,11 @@ static void rtl_hw_start_8101(struct net_device *dev)
void __iomem *ioaddr = tp->mmio_addr;
struct pci_dev *pdev = tp->pci_dev;
+ if (tp->mac_version >= RTL_GIGA_MAC_VER_30) {
+ tp->intr_event &= ~RxFIFOOver;
+ tp->napi_event &= ~RxFIFOOver;
+ }
+
if (tp->mac_version == RTL_GIGA_MAC_VER_13 ||
tp->mac_version == RTL_GIGA_MAC_VER_16) {
int cap = tp->pcie_cap;
@@ -4336,9 +4561,17 @@ static void rtl_hw_start_8101(struct net_device *dev)
static int rtl8169_change_mtu(struct net_device *dev, int new_mtu)
{
- if (new_mtu < ETH_ZLEN || new_mtu > SafeMtu)
+ struct rtl8169_private *tp = netdev_priv(dev);
+
+ if (new_mtu < ETH_ZLEN ||
+ new_mtu > rtl_chip_infos[tp->mac_version].jumbo_max)
return -EINVAL;
+ if (new_mtu > ETH_DATA_LEN)
+ rtl_hw_jumbo_enable(tp);
+ else
+ rtl_hw_jumbo_disable(tp);
+
dev->mtu = new_mtu;
netdev_update_features(dev);
@@ -4539,7 +4772,7 @@ static void rtl8169_wait_for_quiescence(struct net_device *dev)
/* Wait for any pending NAPI task to complete */
napi_disable(&tp->napi);
- rtl8169_irq_mask_and_ack(ioaddr);
+ rtl8169_irq_mask_and_ack(tp);
tp->intr_mask = 0xffff;
RTL_W16(IntrMask, tp->intr_event);
@@ -4698,7 +4931,7 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
u32 opts[2];
int frags;
- if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) {
+ if (unlikely(!TX_FRAGS_READY_FOR(tp, skb_shinfo(skb)->nr_frags))) {
netif_err(tp, drv, dev, "BUG! Tx Ring full when queue awake!\n");
goto err_stop_0;
}
@@ -4746,10 +4979,10 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
RTL_W8(TxPoll, NPQ);
- if (TX_BUFFS_AVAIL(tp) < MAX_SKB_FRAGS) {
+ if (!TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS)) {
netif_stop_queue(dev);
- smp_rmb();
- if (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS)
+ smp_mb();
+ if (TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS))
netif_wake_queue(dev);
}
@@ -4849,9 +5082,9 @@ static void rtl8169_tx_interrupt(struct net_device *dev,
if (tp->dirty_tx != dirty_tx) {
tp->dirty_tx = dirty_tx;
- smp_wmb();
+ smp_mb();
if (netif_queue_stopped(dev) &&
- (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS)) {
+ TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS)) {
netif_wake_queue(dev);
}
/*
@@ -4860,7 +5093,6 @@ static void rtl8169_tx_interrupt(struct net_device *dev,
* of start_xmit activity is detected (if it is not detected,
* it is slow enough). -- FR
*/
- smp_rmb();
if (tp->cur_tx != dirty_tx)
RTL_W8(TxPoll, NPQ);
}
@@ -4918,7 +5150,7 @@ static int rtl8169_rx_interrupt(struct net_device *dev,
u32 status;
rmb();
- status = le32_to_cpu(desc->opts1);
+ status = le32_to_cpu(desc->opts1) & tp->opts1_mask;
if (status & DescOwn)
break;
@@ -4938,7 +5170,7 @@ static int rtl8169_rx_interrupt(struct net_device *dev,
} else {
struct sk_buff *skb;
dma_addr_t addr = le64_to_cpu(desc->addr);
- int pkt_size = (status & 0x00001FFF) - 4;
+ int pkt_size = (status & 0x00003fff) - 4;
/*
* The driver does not support incoming fragmented
@@ -5001,13 +5233,17 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
*/
status = RTL_R16(IntrStatus);
while (status && status != 0xffff) {
+ status &= tp->intr_event;
+ if (!status)
+ break;
+
handled = 1;
/* Handle all of the error cases first. These will reset
* the chip, so just exit the loop.
*/
if (unlikely(!netif_running(dev))) {
- rtl8169_asic_down(ioaddr);
+ rtl8169_asic_down(tp);
break;
}
@@ -5015,27 +5251,9 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
switch (tp->mac_version) {
/* Work around for rx fifo overflow */
case RTL_GIGA_MAC_VER_11:
- case RTL_GIGA_MAC_VER_22:
- case RTL_GIGA_MAC_VER_26:
netif_stop_queue(dev);
rtl8169_tx_timeout(dev);
goto done;
- /* Testers needed. */
- case RTL_GIGA_MAC_VER_17:
- case RTL_GIGA_MAC_VER_19:
- case RTL_GIGA_MAC_VER_20:
- case RTL_GIGA_MAC_VER_21:
- case RTL_GIGA_MAC_VER_23:
- case RTL_GIGA_MAC_VER_24:
- case RTL_GIGA_MAC_VER_27:
- case RTL_GIGA_MAC_VER_28:
- case RTL_GIGA_MAC_VER_31:
- /* Experimental science. Pktgen proof. */
- case RTL_GIGA_MAC_VER_12:
- case RTL_GIGA_MAC_VER_25:
- if (status == RxFIFOOver)
- goto done;
- break;
default:
break;
}
@@ -5130,7 +5348,7 @@ static void rtl8169_down(struct net_device *dev)
spin_lock_irq(&tp->lock);
- rtl8169_asic_down(ioaddr);
+ rtl8169_asic_down(tp);
/*
* At this point device interrupts can not be enabled in any function,
* as netif_running is not true (rtl8169_interrupt, rtl8169_reset_task,
@@ -5376,6 +5594,9 @@ static void rtl_shutdown(struct pci_dev *pdev)
struct net_device *dev = pci_get_drvdata(pdev);
struct rtl8169_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr;
+ struct device *d = &pdev->dev;
+
+ pm_runtime_get_sync(d);
rtl8169_net_suspend(dev);
@@ -5384,13 +5605,16 @@ static void rtl_shutdown(struct pci_dev *pdev)
spin_lock_irq(&tp->lock);
- rtl8169_asic_down(ioaddr);
+ rtl8169_asic_down(tp);
spin_unlock_irq(&tp->lock);
if (system_state == SYSTEM_POWER_OFF) {
- /* WoL fails with some 8168 when the receiver is disabled. */
- if (tp->features & RTL_FEATURE_WOL) {
+ /* WoL fails with 8168b when the receiver is disabled. */
+ if ((tp->mac_version == RTL_GIGA_MAC_VER_11 ||
+ tp->mac_version == RTL_GIGA_MAC_VER_12 ||
+ tp->mac_version == RTL_GIGA_MAC_VER_17) &&
+ (tp->features & RTL_FEATURE_WOL)) {
pci_clear_master(pdev);
RTL_W8(ChipCmd, CmdRxEnb);
@@ -5401,6 +5625,8 @@ static void rtl_shutdown(struct pci_dev *pdev)
pci_wake_from_d3(pdev, true);
pci_set_power_state(pdev, PCI_D3hot);
}
+
+ pm_runtime_put_noidle(d);
}
static struct pci_driver rtl8169_pci_driver = {
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 7d1651b..be3cade 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -1383,6 +1383,11 @@ static int efx_probe_all(struct efx_nic *efx)
goto fail2;
}
+ BUILD_BUG_ON(EFX_DEFAULT_DMAQ_SIZE < EFX_RXQ_MIN_ENT);
+ if (WARN_ON(EFX_DEFAULT_DMAQ_SIZE < EFX_TXQ_MIN_ENT(efx))) {
+ rc = -EINVAL;
+ goto fail3;
+ }
efx->rxq_entries = efx->txq_entries = EFX_DEFAULT_DMAQ_SIZE;
rc = efx_probe_channels(efx);
if (rc)
@@ -1942,6 +1947,7 @@ static int efx_register_netdev(struct efx_nic *efx)
net_dev->irq = efx->pci_dev->irq;
net_dev->netdev_ops = &efx_netdev_ops;
SET_ETHTOOL_OPS(net_dev, &efx_ethtool_ops);
+ net_dev->gso_max_segs = EFX_TSO_MAX_SEGS;
/* Clear MAC statistics */
efx->mac_op->update_stats(efx);
diff --git a/drivers/net/sfc/efx.h b/drivers/net/sfc/efx.h
index b0d1209..a5d1c60 100644
--- a/drivers/net/sfc/efx.h
+++ b/drivers/net/sfc/efx.h
@@ -38,6 +38,7 @@ extern netdev_tx_t
efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb);
extern void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index);
extern int efx_setup_tc(struct net_device *net_dev, u8 num_tc);
+extern unsigned int efx_tx_max_skb_descs(struct efx_nic *efx);
/* RX */
extern int efx_probe_rx_queue(struct efx_rx_queue *rx_queue);
@@ -60,10 +61,15 @@ extern void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue);
#define EFX_MAX_EVQ_SIZE 16384UL
#define EFX_MIN_EVQ_SIZE 512UL
-/* The smallest [rt]xq_entries that the driver supports. Callers of
- * efx_wake_queue() assume that they can subsequently send at least one
- * skb. Falcon/A1 may require up to three descriptors per skb_frag. */
-#define EFX_MIN_RING_SIZE (roundup_pow_of_two(2 * 3 * MAX_SKB_FRAGS))
+/* Maximum number of TCP segments we support for soft-TSO */
+#define EFX_TSO_MAX_SEGS 100
+
+/* The smallest [rt]xq_entries that the driver supports. RX minimum
+ * is a bit arbitrary. For TX, we must have space for at least 2
+ * TSO skbs.
+ */
+#define EFX_RXQ_MIN_ENT 128U
+#define EFX_TXQ_MIN_ENT(efx) (2 * efx_tx_max_skb_descs(efx))
/* Filters */
extern int efx_probe_filters(struct efx_nic *efx);
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c
index d229027..cfaf801 100644
--- a/drivers/net/sfc/ethtool.c
+++ b/drivers/net/sfc/ethtool.c
@@ -677,21 +677,27 @@ static int efx_ethtool_set_ringparam(struct net_device *net_dev,
struct ethtool_ringparam *ring)
{
struct efx_nic *efx = netdev_priv(net_dev);
+ u32 txq_entries;
if (ring->rx_mini_pending || ring->rx_jumbo_pending ||
ring->rx_pending > EFX_MAX_DMAQ_SIZE ||
ring->tx_pending > EFX_MAX_DMAQ_SIZE)
return -EINVAL;
- if (ring->rx_pending < EFX_MIN_RING_SIZE ||
- ring->tx_pending < EFX_MIN_RING_SIZE) {
+ if (ring->rx_pending < EFX_RXQ_MIN_ENT) {
netif_err(efx, drv, efx->net_dev,
- "TX and RX queues cannot be smaller than %ld\n",
- EFX_MIN_RING_SIZE);
+ "RX queues cannot be smaller than %u\n",
+ EFX_RXQ_MIN_ENT);
return -EINVAL;
}
- return efx_realloc_channels(efx, ring->rx_pending, ring->tx_pending);
+ txq_entries = max(ring->tx_pending, EFX_TXQ_MIN_ENT(efx));
+ if (txq_entries != ring->tx_pending)
+ netif_warn(efx, drv, efx->net_dev,
+ "increasing TX queue size to minimum of %u\n",
+ txq_entries);
+
+ return efx_realloc_channels(efx, ring->rx_pending, txq_entries);
}
static int efx_ethtool_set_pauseparam(struct net_device *net_dev,
diff --git a/drivers/net/sfc/nic.h b/drivers/net/sfc/nic.h
index 7443f99..d2405ce 100644
--- a/drivers/net/sfc/nic.h
+++ b/drivers/net/sfc/nic.h
@@ -65,6 +65,11 @@ enum {
#define FALCON_GMAC_LOOPBACKS \
(1 << LOOPBACK_GMAC)
+/* Alignment of PCIe DMA boundaries (4KB) */
+#define EFX_PAGE_SIZE 4096
+/* Size and alignment of buffer table entries (same) */
+#define EFX_BUF_SIZE EFX_PAGE_SIZE
+
/**
* struct falcon_board_type - board operations and type information
* @id: Board type id, as found in NVRAM
diff --git a/drivers/net/sfc/tx.c b/drivers/net/sfc/tx.c
index 84eb99e..6d3b68a 100644
--- a/drivers/net/sfc/tx.c
+++ b/drivers/net/sfc/tx.c
@@ -115,6 +115,25 @@ efx_max_tx_len(struct efx_nic *efx, dma_addr_t dma_addr)
return len;
}
+unsigned int efx_tx_max_skb_descs(struct efx_nic *efx)
+{
+ /* Header and payload descriptor for each output segment, plus
+ * one for every input fragment boundary within a segment
+ */
+ unsigned int max_descs = EFX_TSO_MAX_SEGS * 2 + MAX_SKB_FRAGS;
+
+ /* Possibly one more per segment for the alignment workaround */
+ if (EFX_WORKAROUND_5391(efx))
+ max_descs += EFX_TSO_MAX_SEGS;
+
+ /* Possibly more for PCIe page boundaries within input fragments */
+ if (PAGE_SIZE > EFX_PAGE_SIZE)
+ max_descs += max_t(unsigned int, MAX_SKB_FRAGS,
+ DIV_ROUND_UP(GSO_MAX_SIZE, EFX_PAGE_SIZE));
+
+ return max_descs;
+}
+
/*
* Add a socket buffer to a TX queue
*
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index f4be5c7..b446e7e 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -4097,6 +4097,13 @@ static struct dmi_system_id skge_32bit_dma_boards[] = {
DMI_MATCH(DMI_BOARD_NAME, "nForce"),
},
},
+ {
+ .ident = "ASUS P5NSLI",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+ DMI_MATCH(DMI_BOARD_NAME, "P5NSLI")
+ },
+ },
{}
};
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 80df3a8..9d4a2a3 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -2344,8 +2344,13 @@ static struct sk_buff *receive_copy(struct sky2_port *sky2,
skb_copy_from_linear_data(re->skb, skb->data, length);
skb->ip_summed = re->skb->ip_summed;
skb->csum = re->skb->csum;
+ skb->rxhash = re->skb->rxhash;
+ skb->vlan_tci = re->skb->vlan_tci;
+
pci_dma_sync_single_for_device(sky2->hw->pdev, re->data_addr,
length, PCI_DMA_FROMDEVICE);
+ re->skb->vlan_tci = 0;
+ re->skb->rxhash = 0;
re->skb->ip_summed = CHECKSUM_NONE;
skb_put(skb, length);
}
@@ -2430,9 +2435,6 @@ static struct sk_buff *sky2_receive(struct net_device *dev,
struct sk_buff *skb = NULL;
u16 count = (status & GMR_FS_LEN) >> 16;
- if (status & GMR_FS_VLAN)
- count -= VLAN_HLEN; /* Account for vlan tag */
-
netif_printk(sky2, rx_status, KERN_DEBUG, dev,
"rx slot %u status 0x%x len %d\n",
sky2->rx_next, status, length);
@@ -2440,6 +2442,9 @@ static struct sk_buff *sky2_receive(struct net_device *dev,
sky2->rx_next = (sky2->rx_next + 1) % sky2->rx_pending;
prefetch(sky2->rx_ring + sky2->rx_next);
+ if (vlan_tx_tag_present(re->skb))
+ count -= VLAN_HLEN; /* Account for vlan tag */
+
/* This chip has hardware problems that generates bogus status.
* So do only marginal checking and expect higher level protocols
* to handle crap frames.
@@ -2497,11 +2502,8 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last)
}
static inline void sky2_skb_rx(const struct sky2_port *sky2,
- u32 status, struct sk_buff *skb)
+ struct sk_buff *skb)
{
- if (status & GMR_FS_VLAN)
- __vlan_hwaccel_put_tag(skb, be16_to_cpu(sky2->rx_tag));
-
if (skb->ip_summed == CHECKSUM_NONE)
netif_receive_skb(skb);
else
@@ -2555,6 +2557,14 @@ static void sky2_rx_checksum(struct sky2_port *sky2, u32 status)
}
}
+static void sky2_rx_tag(struct sky2_port *sky2, u16 length)
+{
+ struct sk_buff *skb;
+
+ skb = sky2->rx_ring[sky2->rx_next].skb;
+ __vlan_hwaccel_put_tag(skb, be16_to_cpu(length));
+}
+
static void sky2_rx_hash(struct sky2_port *sky2, u32 status)
{
struct sk_buff *skb;
@@ -2613,8 +2623,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx)
}
skb->protocol = eth_type_trans(skb, dev);
-
- sky2_skb_rx(sky2, status, skb);
+ sky2_skb_rx(sky2, skb);
/* Stop after net poll weight */
if (++work_done >= to_do)
@@ -2622,11 +2631,11 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx)
break;
case OP_RXVLAN:
- sky2->rx_tag = length;
+ sky2_rx_tag(sky2, length);
break;
case OP_RXCHKSVLAN:
- sky2->rx_tag = length;
+ sky2_rx_tag(sky2, length);
/* fall through */
case OP_RXCHKS:
if (likely(dev->features & NETIF_F_RXCSUM))
@@ -4197,10 +4206,12 @@ static int sky2_set_features(struct net_device *dev, u32 features)
struct sky2_port *sky2 = netdev_priv(dev);
u32 changed = dev->features ^ features;
- if (changed & NETIF_F_RXCSUM) {
- u32 on = features & NETIF_F_RXCSUM;
- sky2_write32(sky2->hw, Q_ADDR(rxqaddr[sky2->port], Q_CSR),
- on ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
+ if ((changed & NETIF_F_RXCSUM) &&
+ !(sky2->hw->flags & SKY2_HW_NEW_LE)) {
+ sky2_write32(sky2->hw,
+ Q_ADDR(rxqaddr[sky2->port], Q_CSR),
+ (features & NETIF_F_RXCSUM)
+ ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
}
if (changed & NETIF_F_RXHASH)
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
index 318c9ae..a79a166 100644
--- a/drivers/net/sky2.h
+++ b/drivers/net/sky2.h
@@ -2236,7 +2236,6 @@ struct sky2_port {
u16 rx_pending;
u16 rx_data_size;
u16 rx_nfrags;
- u16 rx_tag;
struct {
unsigned long last;
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index ab59300..361beb7 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -2363,7 +2363,7 @@ static int gem_suspend(struct pci_dev *pdev, pm_message_t state)
netif_device_detach(dev);
/* Switch off MAC, remember WOL setting */
- gp->asleep_wol = gp->wake_on_lan;
+ gp->asleep_wol = !!gp->wake_on_lan;
gem_do_stop(dev, gp->asleep_wol);
} else
gp->asleep_wol = 0;
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index bc8c183..10a99e4 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -740,8 +740,13 @@ static inline unsigned int tg3_has_work(struct tg3_napi *tnapi)
if (sblk->status & SD_STATUS_LINK_CHG)
work_exists = 1;
}
- /* check for RX/TX work to do */
- if (sblk->idx[0].tx_consumer != tnapi->tx_cons ||
+
+ /* check for TX work to do */
+ if (sblk->idx[0].tx_consumer != tnapi->tx_cons)
+ work_exists = 1;
+
+ /* check for RX work to do */
+ if (tnapi->rx_rcb_prod_idx &&
*(tnapi->rx_rcb_prod_idx) != tnapi->rx_rcb_ptr)
work_exists = 1;
@@ -5216,6 +5221,9 @@ static int tg3_poll_work(struct tg3_napi *tnapi, int work_done, int budget)
return work_done;
}
+ if (!tnapi->rx_rcb_prod_idx)
+ return work_done;
+
/* run RX thread, within the bounds set by NAPI.
* All RX "locking" is done by ensuring outside
* code synchronizes with tg3->napi.poll()
@@ -6626,6 +6634,12 @@ static int tg3_alloc_consistent(struct tg3 *tp)
*/
switch (i) {
default:
+ if (tg3_flag(tp, ENABLE_RSS)) {
+ tnapi->rx_rcb_prod_idx = NULL;
+ break;
+ }
+ /* Fall through */
+ case 1:
tnapi->rx_rcb_prod_idx = &sblk->idx[0].rx_producer;
break;
case 2:
@@ -13633,9 +13647,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
if (tg3_flag(tp, HW_TSO_1) ||
tg3_flag(tp, HW_TSO_2) ||
tg3_flag(tp, HW_TSO_3) ||
- (tp->fw_needed && !tg3_flag(tp, ENABLE_ASF)))
+ tp->fw_needed) {
+ /* For firmware TSO, assume ASF is disabled.
+ * We'll disable TSO later if we discover ASF
+ * is enabled in tg3_get_eeprom_hw_cfg().
+ */
tg3_flag_set(tp, TSO_CAPABLE);
- else {
+ } else {
tg3_flag_clear(tp, TSO_CAPABLE);
tg3_flag_clear(tp, TSO_BUG);
tp->fw_needed = NULL;
@@ -13671,8 +13689,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
*/
tg3_flag_set(tp, 4G_DMA_BNDRY_BUG);
- if (tg3_flag(tp, 5755_PLUS))
- tg3_flag_set(tp, SHORT_DMA_BUG);
+ if (tg3_flag(tp, 5755_PLUS) ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+ tg3_flag_set(tp, SHORT_DMA_BUG);
else
tg3_flag_set(tp, 40BIT_DMA_LIMIT_BUG);
@@ -13873,6 +13892,12 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
*/
tg3_get_eeprom_hw_cfg(tp);
+ if (tp->fw_needed && tg3_flag(tp, ENABLE_ASF)) {
+ tg3_flag_clear(tp, TSO_CAPABLE);
+ tg3_flag_clear(tp, TSO_BUG);
+ tp->fw_needed = NULL;
+ }
+
if (tg3_flag(tp, ENABLE_APE)) {
/* Allow reads and writes to the
* APE register and memory space.
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 76b8650..3cc22b9 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1245,10 +1245,12 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
}
#endif
- if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89)
+ if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89) {
if (copy_from_user(&ifr, argp, ifreq_len))
return -EFAULT;
-
+ } else {
+ memset(&ifr, 0, sizeof(ifr));
+ }
if (cmd == TUNGETFEATURES) {
/* Currently this just means: "what IFF flags are valid?".
* This is needed because we never checked for invalid flags on
diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c
index 3e33573..e2a988c 100644
--- a/drivers/net/usb/asix.c
+++ b/drivers/net/usb/asix.c
@@ -398,7 +398,7 @@ static struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
u32 packet_len;
u32 padbytes = 0xffff0000;
- padlen = ((skb->len + 4) % 512) ? 0 : 4;
+ padlen = ((skb->len + 4) & (dev->maxpacket - 1)) ? 0 : 4;
if ((!skb_cloned(skb)) &&
((headroom + tailroom) >= (4 + padlen))) {
@@ -420,7 +420,7 @@ static struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
cpu_to_le32s(&packet_len);
skb_copy_to_linear_data(skb, &packet_len, sizeof(packet_len));
- if ((skb->len % 512) == 0) {
+ if (padlen) {
cpu_to_le32s(&padbytes);
memcpy(skb_tail_pointer(skb), &padbytes, sizeof(padbytes));
skb_put(skb, sizeof(padbytes));
@@ -1537,6 +1537,10 @@ static const struct usb_device_id products [] = {
USB_DEVICE (0x2001, 0x3c05),
.driver_info = (unsigned long) &ax88772_info,
}, {
+ // DLink DUB-E100 H/W Ver C1
+ USB_DEVICE (0x2001, 0x1a02),
+ .driver_info = (unsigned long) &ax88772_info,
+}, {
// Linksys USB1000
USB_DEVICE (0x1737, 0x0039),
.driver_info = (unsigned long) &ax88178_info,
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
index 13919dd..544c309 100644
--- a/drivers/net/usb/cdc_ether.c
+++ b/drivers/net/usb/cdc_ether.c
@@ -83,6 +83,7 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
struct cdc_state *info = (void *) &dev->data;
int status;
int rndis;
+ bool android_rndis_quirk = false;
struct usb_driver *driver = driver_of(intf);
struct usb_cdc_mdlm_desc *desc = NULL;
struct usb_cdc_mdlm_detail_desc *detail = NULL;
@@ -195,6 +196,11 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
info->control,
info->u->bSlaveInterface0,
info->data);
+ /* fall back to hard-wiring for RNDIS */
+ if (rndis) {
+ android_rndis_quirk = true;
+ goto next_desc;
+ }
goto bad_desc;
}
if (info->control != intf) {
@@ -271,11 +277,15 @@ next_desc:
/* Microsoft ActiveSync based and some regular RNDIS devices lack the
* CDC descriptors, so we'll hard-wire the interfaces and not check
* for descriptors.
+ *
+ * Some Android RNDIS devices have a CDC Union descriptor pointing
+ * to non-existing interfaces. Ignore that and attempt the same
+ * hard-wired 0 and 1 interfaces.
*/
- if (rndis && !info->u) {
+ if (rndis && (!info->u || android_rndis_quirk)) {
info->control = usb_ifnum_to_if(dev->udev, 0);
info->data = usb_ifnum_to_if(dev->udev, 1);
- if (!info->control || !info->data) {
+ if (!info->control || !info->data || info->control != intf) {
dev_dbg(&intf->dev,
"rndis: master #0/%p slave #1/%p\n",
info->control,
@@ -472,6 +482,7 @@ static const struct driver_info wwan_info = {
/*-------------------------------------------------------------------------*/
#define HUAWEI_VENDOR_ID 0x12D1
+#define NOVATEL_VENDOR_ID 0x1410
static const struct usb_device_id products [] = {
/*
@@ -589,6 +600,21 @@ static const struct usb_device_id products [] = {
* because of bugs/quirks in a given product (like Zaurus, above).
*/
{
+ /* Novatel USB551L */
+ /* This match must come *before* the generic CDC-ETHER match so that
+ * we get FLAG_WWAN set on the device, since it's descriptors are
+ * generic CDC-ETHER.
+ */
+ .match_flags = USB_DEVICE_ID_MATCH_VENDOR
+ | USB_DEVICE_ID_MATCH_PRODUCT
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = NOVATEL_VENDOR_ID,
+ .idProduct = 0xB001,
+ .bInterfaceClass = USB_CLASS_COMM,
+ .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET,
+ .bInterfaceProtocol = USB_CDC_PROTO_NONE,
+ .driver_info = (unsigned long)&wwan_info,
+}, {
USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET,
USB_CDC_PROTO_NONE),
.driver_info = (unsigned long) &cdc_info,
diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c
index 9cf4e47..db9b212 100644
--- a/drivers/net/usb/ipheth.c
+++ b/drivers/net/usb/ipheth.c
@@ -59,6 +59,7 @@
#define USB_PRODUCT_IPHONE_3G 0x1292
#define USB_PRODUCT_IPHONE_3GS 0x1294
#define USB_PRODUCT_IPHONE_4 0x1297
+#define USB_PRODUCT_IPAD 0x129a
#define USB_PRODUCT_IPHONE_4_VZW 0x129c
#define USB_PRODUCT_IPHONE_4S 0x12a0
@@ -101,6 +102,10 @@ static struct usb_device_id ipheth_table[] = {
IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
IPHETH_USBINTF_PROTO) },
{ USB_DEVICE_AND_INTERFACE_INFO(
+ USB_VENDOR_APPLE, USB_PRODUCT_IPAD,
+ IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
+ IPHETH_USBINTF_PROTO) },
+ { USB_DEVICE_AND_INTERFACE_INFO(
USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4_VZW,
IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
IPHETH_USBINTF_PROTO) },
diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c
index ad0298f..3362449 100644
--- a/drivers/net/usb/kaweth.c
+++ b/drivers/net/usb/kaweth.c
@@ -1308,7 +1308,7 @@ static int kaweth_internal_control_msg(struct usb_device *usb_dev,
int retv;
int length = 0; /* shut up GCC */
- urb = usb_alloc_urb(0, GFP_NOIO);
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb)
return -ENOMEM;
diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c
index ed1b432..e773250 100644
--- a/drivers/net/usb/sierra_net.c
+++ b/drivers/net/usb/sierra_net.c
@@ -678,7 +678,7 @@ static int sierra_net_get_fw_attr(struct usbnet *dev, u16 *datap)
return -EIO;
}
- *datap = *attrdata;
+ *datap = le16_to_cpu(*attrdata);
kfree(attrdata);
return result;
@@ -943,7 +943,7 @@ struct sk_buff *sierra_net_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
}
static const u8 sierra_net_ifnum_list[] = { 7, 10, 11 };
-static const struct sierra_net_info_data sierra_net_info_data_68A3 = {
+static const struct sierra_net_info_data sierra_net_info_data_direct_ip = {
.rx_urb_size = 8 * 1024,
.whitelist = {
.infolen = ARRAY_SIZE(sierra_net_ifnum_list),
@@ -951,7 +951,7 @@ static const struct sierra_net_info_data sierra_net_info_data_68A3 = {
}
};
-static const struct driver_info sierra_net_info_68A3 = {
+static const struct driver_info sierra_net_info_direct_ip = {
.description = "Sierra Wireless USB-to-WWAN Modem",
.flags = FLAG_WWAN | FLAG_SEND_ZLP,
.bind = sierra_net_bind,
@@ -959,12 +959,18 @@ static const struct driver_info sierra_net_info_68A3 = {
.status = sierra_net_status,
.rx_fixup = sierra_net_rx_fixup,
.tx_fixup = sierra_net_tx_fixup,
- .data = (unsigned long)&sierra_net_info_data_68A3,
+ .data = (unsigned long)&sierra_net_info_data_direct_ip,
};
static const struct usb_device_id products[] = {
{USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless USB-to-WWAN modem */
- .driver_info = (unsigned long) &sierra_net_info_68A3},
+ .driver_info = (unsigned long) &sierra_net_info_direct_ip},
+ {USB_DEVICE(0x0F3D, 0x68A3), /* AT&T Direct IP modem */
+ .driver_info = (unsigned long) &sierra_net_info_direct_ip},
+ {USB_DEVICE(0x1199, 0x68AA), /* Sierra Wireless Direct IP LTE modem */
+ .driver_info = (unsigned long) &sierra_net_info_direct_ip},
+ {USB_DEVICE(0x0F3D, 0x68AA), /* AT&T Direct IP LTE modem */
+ .driver_info = (unsigned long) &sierra_net_info_direct_ip},
{}, /* last item */
};
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index f74f3ce..e5c15bb 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -1190,7 +1190,7 @@ static const struct driver_info smsc95xx_info = {
.rx_fixup = smsc95xx_rx_fixup,
.tx_fixup = smsc95xx_tx_fixup,
.status = smsc95xx_status,
- .flags = FLAG_ETHER | FLAG_SEND_ZLP,
+ .flags = FLAG_ETHER | FLAG_SEND_ZLP | FLAG_LINK_INTR,
};
static const struct usb_device_id products[] = {
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 46a6b67..dd225fc 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -277,17 +277,32 @@ int usbnet_change_mtu (struct net_device *net, int new_mtu)
}
EXPORT_SYMBOL_GPL(usbnet_change_mtu);
+/* The caller must hold list->lock */
+static void __usbnet_queue_skb(struct sk_buff_head *list,
+ struct sk_buff *newsk, enum skb_state state)
+{
+ struct skb_data *entry = (struct skb_data *) newsk->cb;
+
+ __skb_queue_tail(list, newsk);
+ entry->state = state;
+}
+
/*-------------------------------------------------------------------------*/
/* some LK 2.4 HCDs oopsed if we freed or resubmitted urbs from
* completion callbacks. 2.5 should have fixed those bugs...
*/
-static void defer_bh(struct usbnet *dev, struct sk_buff *skb, struct sk_buff_head *list)
+static enum skb_state defer_bh(struct usbnet *dev, struct sk_buff *skb,
+ struct sk_buff_head *list, enum skb_state state)
{
unsigned long flags;
+ enum skb_state old_state;
+ struct skb_data *entry = (struct skb_data *) skb->cb;
spin_lock_irqsave(&list->lock, flags);
+ old_state = entry->state;
+ entry->state = state;
__skb_unlink(skb, list);
spin_unlock(&list->lock);
spin_lock(&dev->done.lock);
@@ -295,6 +310,7 @@ static void defer_bh(struct usbnet *dev, struct sk_buff *skb, struct sk_buff_hea
if (dev->done.qlen == 1)
tasklet_schedule(&dev->bh);
spin_unlock_irqrestore(&dev->done.lock, flags);
+ return old_state;
}
/* some work can't be done in tasklets, so we use keventd
@@ -335,7 +351,6 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
entry = (struct skb_data *) skb->cb;
entry->urb = urb;
entry->dev = dev;
- entry->state = rx_start;
entry->length = 0;
usb_fill_bulk_urb (urb, dev->udev, dev->in,
@@ -367,7 +382,7 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
tasklet_schedule (&dev->bh);
break;
case 0:
- __skb_queue_tail (&dev->rxq, skb);
+ __usbnet_queue_skb(&dev->rxq, skb, rx_start);
}
} else {
netif_dbg(dev, ifdown, dev->net, "rx: stopped\n");
@@ -418,16 +433,17 @@ static void rx_complete (struct urb *urb)
struct skb_data *entry = (struct skb_data *) skb->cb;
struct usbnet *dev = entry->dev;
int urb_status = urb->status;
+ enum skb_state state;
skb_put (skb, urb->actual_length);
- entry->state = rx_done;
+ state = rx_done;
entry->urb = NULL;
switch (urb_status) {
/* success */
case 0:
if (skb->len < dev->net->hard_header_len) {
- entry->state = rx_cleanup;
+ state = rx_cleanup;
dev->net->stats.rx_errors++;
dev->net->stats.rx_length_errors++;
netif_dbg(dev, rx_err, dev->net,
@@ -466,7 +482,7 @@ static void rx_complete (struct urb *urb)
"rx throttle %d\n", urb_status);
}
block:
- entry->state = rx_cleanup;
+ state = rx_cleanup;
entry->urb = urb;
urb = NULL;
break;
@@ -477,17 +493,18 @@ block:
// FALLTHROUGH
default:
- entry->state = rx_cleanup;
+ state = rx_cleanup;
dev->net->stats.rx_errors++;
netif_dbg(dev, rx_err, dev->net, "rx status %d\n", urb_status);
break;
}
- defer_bh(dev, skb, &dev->rxq);
+ state = defer_bh(dev, skb, &dev->rxq, state);
if (urb) {
if (netif_running (dev->net) &&
- !test_bit (EVENT_RX_HALT, &dev->flags)) {
+ !test_bit (EVENT_RX_HALT, &dev->flags) &&
+ state != unlink_start) {
rx_submit (dev, urb, GFP_ATOMIC);
return;
}
@@ -573,16 +590,23 @@ EXPORT_SYMBOL_GPL(usbnet_purge_paused_rxq);
static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q)
{
unsigned long flags;
- struct sk_buff *skb, *skbnext;
+ struct sk_buff *skb;
int count = 0;
spin_lock_irqsave (&q->lock, flags);
- skb_queue_walk_safe(q, skb, skbnext) {
+ while (!skb_queue_empty(q)) {
struct skb_data *entry;
struct urb *urb;
int retval;
- entry = (struct skb_data *) skb->cb;
+ skb_queue_walk(q, skb) {
+ entry = (struct skb_data *) skb->cb;
+ if (entry->state != unlink_start)
+ goto found;
+ }
+ break;
+found:
+ entry->state = unlink_start;
urb = entry->urb;
/*
@@ -1033,8 +1057,7 @@ static void tx_complete (struct urb *urb)
}
usb_autopm_put_interface_async(dev->intf);
- entry->state = tx_done;
- defer_bh(dev, skb, &dev->txq);
+ (void) defer_bh(dev, skb, &dev->txq, tx_done);
}
/*-------------------------------------------------------------------------*/
@@ -1087,7 +1110,6 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
entry = (struct skb_data *) skb->cb;
entry->urb = urb;
entry->dev = dev;
- entry->state = tx_start;
entry->length = length;
usb_fill_bulk_urb (urb, dev->udev, dev->out,
@@ -1146,7 +1168,7 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
break;
case 0:
net->trans_start = jiffies;
- __skb_queue_tail (&dev->txq, skb);
+ __usbnet_queue_skb(&dev->txq, skb, tx_start);
if (dev->txq.qlen >= TX_QLEN (dev))
netif_stop_queue (net);
}
diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c
index f1e1643..78c51ab 100644
--- a/drivers/net/wan/ixp4xx_hss.c
+++ b/drivers/net/wan/ixp4xx_hss.c
@@ -8,6 +8,7 @@
* as published by the Free Software Foundation.
*/
+#include <linux/module.h>
#include <linux/bitops.h>
#include <linux/cdev.h>
#include <linux/dma-mapping.h>
diff --git a/drivers/net/wimax/Kconfig b/drivers/net/wimax/Kconfig
index 565018e..a7d6e03 100644
--- a/drivers/net/wimax/Kconfig
+++ b/drivers/net/wimax/Kconfig
@@ -11,6 +11,7 @@ if WIMAX
menu "WiMAX Wireless Broadband devices"
source "drivers/net/wimax/i2400m/Kconfig"
+source "drivers/net/wimax/cmc7xx/Kconfig"
endmenu
diff --git a/drivers/net/wimax/Makefile b/drivers/net/wimax/Makefile
index 992bc02..57bc1bd 100644
--- a/drivers/net/wimax/Makefile
+++ b/drivers/net/wimax/Makefile
@@ -1,5 +1,6 @@
obj-$(CONFIG_WIMAX_I2400M) += i2400m/
+obj-$(CONFIG_WIMAX_CMC7XX) += cmc7xx/
# (from Sam Ravnborg) force kbuild to create built-in.o
obj- := dummy.o
diff --git a/drivers/net/wimax/cmc7xx/Kconfig b/drivers/net/wimax/cmc7xx/Kconfig
new file mode 100755
index 0000000..0a6cc66
--- /dev/null
+++ b/drivers/net/wimax/cmc7xx/Kconfig
@@ -0,0 +1,12 @@
+comment "Enable MMC support to see CMC7xx driver"
+ depends on MMC = n
+
+config WIMAX_CMC7XX
+ bool "Samsung WiMax CMC7xx chipset support"
+ depends on WIMAX && MMC
+ default n
+
+config WIMAX_CMC7XX_DEBUG
+ bool "Samsung WiMax CMC7xx debug log"
+ depends on WIMAX_CMC7XX
+ default n
diff --git a/drivers/net/wimax/cmc7xx/Makefile b/drivers/net/wimax/cmc7xx/Makefile
new file mode 100755
index 0000000..ea72fae
--- /dev/null
+++ b/drivers/net/wimax/cmc7xx/Makefile
@@ -0,0 +1,5 @@
+ifeq ($(CONFIG_WIMAX_CMC7XX_DEBUG),y)
+ EXTRA_CFLAGS += -DDEBUG
+endif
+obj-$(CONFIG_WIMAX_CMC7XX) += control.o hardware.o send.o receive.o
+obj-$(CONFIG_WIMAX_CMC7XX) += wimax_sdio.o download.o
diff --git a/drivers/net/wimax/cmc7xx/control.c b/drivers/net/wimax/cmc7xx/control.c
new file mode 100755
index 0000000..0c24daf
--- /dev/null
+++ b/drivers/net/wimax/cmc7xx/control.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include "headers.h"
+
+u32 control_init(struct net_adapter *adapter)
+{
+ INIT_LIST_HEAD(&adapter->ctl.q_received_ctrl);
+ spin_lock_init(&adapter->ctl.lock);
+
+ INIT_LIST_HEAD(&adapter->ctl.apps.process_list);
+ spin_lock_init(&adapter->ctl.apps.lock);
+
+ adapter->ctl.apps.ready = true;
+
+ return STATUS_SUCCESS;
+}
+
+void control_remove(struct net_adapter *adapter)
+{
+ struct list_head *pos, *nxt;
+ struct buffer_descriptor *bufdsc;
+ struct process_descriptor *procdsc;
+
+ /* Free the received control packets queue */
+ list_for_each_safe(pos, nxt, &adapter->ctl.q_received_ctrl) {
+ bufdsc = list_entry(pos, struct buffer_descriptor, list);
+ list_del(pos);
+ kfree(bufdsc->buffer);
+ kfree(bufdsc);
+ }
+
+ if (!adapter->ctl.apps.ready)
+ return;
+
+ list_for_each_safe(pos, nxt, &adapter->ctl.apps.process_list) {
+ procdsc = list_entry(pos,
+ struct process_descriptor, list);
+ if (procdsc->irp) {
+ procdsc->irp = false;
+ wake_up_interruptible
+ (&procdsc->read_wait);
+ }
+ }
+ /* delay for the process release */
+ msleep(100);
+ adapter->ctl.apps.ready = false;
+}
+
+/* add received packet to pending list */
+static void control_enqueue_buffer(struct net_adapter *adapter,
+ void *buffer, u32 length)
+{
+ struct buffer_descriptor *bufdsc;
+ struct process_descriptor *procdsc;
+ struct eth_header hdr;
+
+ /* get the packet type for the process check */
+ memcpy(&hdr.type, (unsigned short *)buffer, sizeof(unsigned short));
+
+ /* Queue and wake read only if process exist. */
+ procdsc = process_by_type(adapter, hdr.type);
+ if (!procdsc) {
+ pr_debug("Waiting process not found skip the packet");
+ return;
+ }
+
+ bufdsc = (struct buffer_descriptor *)
+ kmalloc(sizeof(*bufdsc), GFP_KERNEL);
+ if (bufdsc == NULL) {
+ pr_debug("bufdsc Memory Alloc Failure *****");
+ return;
+ }
+ bufdsc->buffer = kmalloc(
+ (length + (ETHERNET_ADDRESS_LENGTH * 2)), GFP_KERNEL);
+ if (bufdsc->buffer == NULL) {
+ kfree(bufdsc);
+ pr_debug("bufdsc->buffer Memory Alloc Failure *****");
+ return;
+ }
+
+ /* add ethernet header to control packet */
+ memcpy(bufdsc->buffer, adapter->hw.eth_header,
+ (ETHERNET_ADDRESS_LENGTH * 2));
+ memcpy(bufdsc->buffer + (ETHERNET_ADDRESS_LENGTH * 2),
+ buffer, length);
+
+ /* fill out descriptor */
+ bufdsc->length = length + (ETHERNET_ADDRESS_LENGTH * 2);
+ bufdsc->type = hdr.type;
+
+ /* add to pending list */
+ list_add_tail(&bufdsc->list, &adapter->ctl.q_received_ctrl);
+
+ if (procdsc->irp) {
+ procdsc->irp = false;
+ wake_up_interruptible(&procdsc->read_wait);
+ }
+}
+
+/* receive control data */
+void control_recv(struct net_adapter *adapter, void *buffer, u32 length)
+{
+ /* check halt flag */
+ if (adapter->halted)
+ return;
+
+ /* not found, add to pending buffers list */
+ spin_lock(&adapter->ctl.lock);
+ control_enqueue_buffer(adapter, buffer, length);
+ spin_unlock(&adapter->ctl.lock);
+}
+
+u32 control_send(struct net_adapter *adapter, void *buffer, u32 length)
+{
+ struct buffer_descriptor *bufdsc;
+ struct hw_packet_header *hdr;
+ u8 *ptr;
+
+ if ((length + sizeof(struct hw_packet_header)) >= WIMAX_MAX_TOTAL_SIZE)
+ return STATUS_RESOURCES;/* changed from SUCCESS return status */
+
+ bufdsc = (struct buffer_descriptor *)
+ kmalloc(sizeof(*bufdsc), GFP_ATOMIC);
+ if (bufdsc == NULL)
+ return STATUS_RESOURCES;
+ bufdsc->buffer = kmalloc(BUFFER_DATA_SIZE, GFP_ATOMIC);
+ if (bufdsc->buffer == NULL) {
+ kfree(bufdsc);
+ return STATUS_RESOURCES;
+ }
+
+ ptr = bufdsc->buffer;
+ hdr = (struct hw_packet_header *)bufdsc->buffer;
+
+ ptr += sizeof(struct hw_packet_header);
+ ptr += 2;
+
+ memcpy(ptr, buffer + (ETHERNET_ADDRESS_LENGTH * 2),
+ length - (ETHERNET_ADDRESS_LENGTH * 2));
+
+ /* add packet header */
+ hdr->id0 = 'W';
+ hdr->id1 = 'C';
+ hdr->length = (u16)length - (ETHERNET_ADDRESS_LENGTH * 2);
+
+ /* set length */
+ bufdsc->length = (u16)length - (ETHERNET_ADDRESS_LENGTH * 2)
+ + sizeof(struct hw_packet_header);
+ bufdsc->length += 2;
+
+ spin_lock(&adapter->hw.lock);
+ list_add_tail(&bufdsc->list, &adapter->hw.q_send);
+ spin_unlock(&adapter->hw.lock);
+
+ wake_up_interruptible(&adapter->send_event);
+
+ return STATUS_SUCCESS;
+}
+
+struct process_descriptor *process_by_id(struct net_adapter *adapter, u32 id)
+{
+ struct process_descriptor *procdsc;
+
+ list_for_each_entry(procdsc, &adapter->ctl.apps.process_list, list) {
+ if (procdsc->id == id) /* process found */
+ return procdsc;
+ }
+ return NULL;
+}
+
+struct process_descriptor
+ *process_by_type(struct net_adapter *adapter, u16 type)
+{
+ struct process_descriptor *procdsc;
+
+ list_for_each_entry(procdsc, &adapter->ctl.apps.process_list, list) {
+ if (procdsc->type == type) /* process found */
+ return procdsc;
+ }
+ return NULL;
+}
+
+/* find buffer by buffer type */
+struct buffer_descriptor
+*buffer_by_type(struct net_adapter *adapter, u16 type)
+{
+ struct buffer_descriptor *bufdsc;
+
+ list_for_each_entry(bufdsc, &adapter->ctl.q_received_ctrl, list) {
+ if (bufdsc->type == type) /* process found */ {
+ return bufdsc;
+ }
+ }
+ return NULL;
+}
+
+void remove_process(struct net_adapter *adapter, u32 id)
+{
+ struct process_descriptor *procdsc;
+ struct list_head *pos, *nxt;
+
+ list_for_each_safe(pos, nxt, &adapter->ctl.apps.process_list) {
+ procdsc = list_entry(pos, struct process_descriptor, list);
+ if (procdsc->id == id) {
+ list_del(pos);
+ kfree(procdsc);
+ }
+ }
+}
diff --git a/drivers/net/wimax/cmc7xx/ctl_types.h b/drivers/net/wimax/cmc7xx/ctl_types.h
new file mode 100755
index 0000000..3fbd6f2
--- /dev/null
+++ b/drivers/net/wimax/cmc7xx/ctl_types.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef _WIMAX_CTL_TYPES_H
+#define _WIMAX_CTL_TYPES_H
+
+#ifndef FILE_DEVICE_UNKNOWN
+#define FILE_DEVICE_UNKNOWN 0x89
+#endif
+
+/* Macro definition for defining IOCTL */
+#define CTL_CODE(DeviceType, Function, Method, Access) \
+( \
+ ((DeviceType) << 16) | ((Access) << 14) | \
+ ((Function) << 2) | (Method) \
+)
+/* Define the method codes for how buffers are passed for I/O and FS controls */
+#define METHOD_BUFFERED 0
+
+/*
+* Define the access check value for any access
+
+* The FILE_READ_ACCESS and FILE_WRITE_ACCESS constants are also defined in
+* ntioapi.h as FILE_READ_DATA and FILE_WRITE_DATA. The values for these
+* constants *MUST* always be in sync.
+*/
+#define FILE_ANY_ACCESS 0
+
+#define CONTROL_ETH_TYPE_WCM 0x0015
+
+#define CONTROL_IOCTL_WRITE_REQUEST \
+ CTL_CODE(FILE_DEVICE_UNKNOWN, 0x820, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define CONTROL_IOCTL_WIMAX_POWER_CTL \
+ CTL_CODE(FILE_DEVICE_UNKNOWN, 0x821, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define CONTROL_IOCTL_WIMAX_MODE_CHANGE \
+ CTL_CODE(FILE_DEVICE_UNKNOWN, 0x838, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define ETHERNET_ADDRESS_LENGTH 6
+
+/* eth types for control message */
+enum {
+ ETHERTYPE_HIM = 0x1500,
+ ETHERTYPE_MC = 0x1501,
+ ETHERTYPE_DM = 0x1502,
+ ETHERTYPE_CT = 0x1503,
+ ETHERTYPE_DL = 0x1504,
+ ETHERTYPE_VSP = 0x1510,
+ ETHERTYPE_AUTH = 0x1521
+};
+
+/* eth header structure */
+#pragma pack(1)
+struct eth_header {
+ u8 dest[ETHERNET_ADDRESS_LENGTH];
+ u8 src[ETHERNET_ADDRESS_LENGTH];
+ u16 type;
+};
+#pragma pack()
+
+/* process element managed by control type */
+struct process_descriptor {
+ struct list_head list;
+ wait_queue_head_t read_wait;
+ u32 id;
+ u16 type;
+ u16 irp; /* Used for the read thread indication */
+};
+
+/* head structure for process element */
+struct ctl_app_descriptor {
+ struct list_head process_list;/* there could be
+ undefined number of applications */
+ spinlock_t lock;
+ u8 ready;
+};
+
+struct image_data {
+ u32 size;
+ u32 address;
+ u32 offset;
+ struct mutex lock;
+ u8 *data;
+};
+
+struct ctl_info {
+ /* application device structure */
+ struct ctl_app_descriptor apps;
+ struct list_head q_received_ctrl;/* pending queue */
+ spinlock_t lock; /* protection */
+};
+
+#endif /* _WIMAX_CTL_TYPES_H */
diff --git a/drivers/net/wimax/cmc7xx/download.c b/drivers/net/wimax/cmc7xx/download.c
new file mode 100755
index 0000000..7e9e3bc
--- /dev/null
+++ b/drivers/net/wimax/cmc7xx/download.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include "headers.h"
+#include "download.h"
+
+#include <linux/firmware.h>
+#include <linux/vmalloc.h>
+
+int load_wimax_image(int mode, struct net_adapter *adapter)
+{
+ const struct firmware *fw = NULL;
+ int ret = STATUS_SUCCESS;
+ struct device *dev;
+
+ if (!adapter || !adapter->func) {
+ pr_err("%s: device is NULL, can't load firmware\n", __func__);
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ dev = &adapter->func->dev;
+
+ if (request_firmware(&fw, (mode == AUTH_MODE) ?
+ WIMAX_LOADER_PATH : WIMAX_IMAGE_PATH, dev)) {
+ dev_err(dev, "%s: Can't open firmware file\n", __func__);
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if (adapter->wimax_image.data && adapter->wimax_image.size < fw->size) {
+ vfree(adapter->wimax_image.data);
+ adapter->wimax_image.data = NULL;
+ }
+
+ if (!adapter->wimax_image.data)
+ adapter->wimax_image.data = vmalloc(fw->size);
+
+ if (!adapter->wimax_image.data) {
+ dev_err(dev, "%s: Can't allocate %d bytes of memory for "
+ "firmware\n", __func__, fw->size);
+ ret = STATUS_UNSUCCESSFUL;
+ goto err_vmalloc;
+ }
+ memcpy(adapter->wimax_image.data, fw->data, fw->size);
+
+ adapter->wimax_image.size = fw->size;
+ adapter->wimax_image.address = CMC732_WIMAX_ADDRESS;
+ adapter->wimax_image.offset = 0;
+
+err_vmalloc:
+ release_firmware(fw);
+ return ret;
+}
+
+void unload_wimax_image(struct net_adapter *adapter)
+{
+ if (adapter->wimax_image.data == NULL)
+ return;
+
+ pr_debug("Delete the Image Loaded");
+ vfree(adapter->wimax_image.data);
+ adapter->wimax_image.data = NULL;
+}
+
+u8 send_cmd_packet(struct net_adapter *adapter, u16 cmd_id)
+{
+ struct hw_packet_header *pkt_hdr;
+ struct wimax_msg_header *msg_hdr;
+ u8 tx_buf[CMD_MSG_TOTAL_LENGTH];
+ int status = 0;
+ u32 offset;
+ u32 size;
+
+ pkt_hdr = (struct hw_packet_header *)tx_buf;
+ pkt_hdr->id0 = 'W';
+ pkt_hdr->id1 = 'C';
+ pkt_hdr->length = be16_to_cpu(CMD_MSG_TOTAL_LENGTH);
+
+ offset = sizeof(struct hw_packet_header);
+ msg_hdr = (struct wimax_msg_header *)(tx_buf + offset);
+ msg_hdr->type = be16_to_cpu(ETHERTYPE_DL);
+ msg_hdr->id = be16_to_cpu(cmd_id);
+ msg_hdr->length = be32_to_cpu(CMD_MSG_LENGTH);
+
+ size = CMD_MSG_TOTAL_LENGTH;
+
+ status = sd_send(adapter, tx_buf, size);
+
+
+ if (status != STATUS_SUCCESS) {
+ /* crc error or data error -
+ set PCWRT '1' & send current type A packet again */
+ pr_debug("hwSdioWrite : crc or data error");
+ return status;
+ }
+ return status;
+}
+
+u8 send_image_info_packet(struct net_adapter *adapter, u16 cmd_id)
+{
+ struct hw_packet_header *pkt_hdr;
+ struct wimax_msg_header *msg_hdr;
+ u32 image_info[4];
+ u8 tx_buf[IMAGE_INFO_MSG_TOTAL_LENGTH];
+ int status;
+ u32 offset;
+ u32 size;
+
+ pkt_hdr = (struct hw_packet_header *)tx_buf;
+ pkt_hdr->id0 = 'W';
+ pkt_hdr->id1 = 'C';
+ pkt_hdr->length = be16_to_cpu(IMAGE_INFO_MSG_TOTAL_LENGTH);
+
+ offset = sizeof(struct hw_packet_header);
+ msg_hdr = (struct wimax_msg_header *)(tx_buf + offset);
+ msg_hdr->type = be16_to_cpu(ETHERTYPE_DL);
+ msg_hdr->id = be16_to_cpu(cmd_id);
+ msg_hdr->length = be32_to_cpu(IMAGE_INFO_MSG_LENGTH);
+
+ image_info[0] = 0;
+ image_info[1] = be32_to_cpu(adapter->wimax_image.size);
+ image_info[2] = be32_to_cpu(adapter->wimax_image.address);
+ image_info[3] = 0;
+
+ offset += sizeof(struct wimax_msg_header);
+ memcpy(&(tx_buf[offset]), image_info, sizeof(image_info));
+
+ size = IMAGE_INFO_MSG_TOTAL_LENGTH;
+
+ status = sd_send(adapter, tx_buf, size);
+
+ if (status != STATUS_SUCCESS) {
+ /*
+ * crc error or data error -
+ * set PCWRT '1' & send current type A packet again
+ */
+ pr_debug("hwSdioWrite : crc error");
+ return status;
+ }
+ return status;
+}
+
+u8 send_image_data_packet(struct net_adapter *adapter, u16 cmd_id)
+{
+ struct hw_packet_header *pkt_hdr;
+ struct image_data_payload *pImageDataPayload;
+ struct wimax_msg_header *msg_hdr;
+ u8 *tx_buf = NULL;
+ int status;
+ u32 len;
+ u32 offset;
+ u32 size;
+
+ tx_buf = kmalloc(MAX_IMAGE_DATA_MSG_LENGTH, GFP_KERNEL);
+ if (tx_buf == NULL) {
+ pr_debug("MALLOC FAIL!!");
+ return -1;
+ }
+
+ pkt_hdr = (struct hw_packet_header *)tx_buf;
+ pkt_hdr->id0 = 'W';
+ pkt_hdr->id1 = 'C';
+
+ offset = sizeof(struct hw_packet_header);
+ msg_hdr = (struct wimax_msg_header *)(tx_buf + offset);
+ msg_hdr->type = be16_to_cpu(ETHERTYPE_DL);
+ msg_hdr->id = be16_to_cpu(cmd_id);
+
+ if (adapter->wimax_image.offset <
+ (adapter->wimax_image.size - MAX_IMAGE_DATA_LENGTH))
+ len = MAX_IMAGE_DATA_LENGTH;
+ else
+ len = adapter->wimax_image.size - adapter->wimax_image.offset;
+
+ offset += sizeof(struct wimax_msg_header);
+ pImageDataPayload = (struct image_data_payload *)(tx_buf + offset);
+ pImageDataPayload->offset = be32_to_cpu(adapter->wimax_image.offset);
+ pImageDataPayload->size = be32_to_cpu(len);
+
+ memcpy(pImageDataPayload->data,
+ adapter->wimax_image.data + adapter->wimax_image.offset, len);
+
+ size = len + 8; /* length of Payload offset + length + data */
+ pkt_hdr->length = be16_to_cpu(CMD_MSG_TOTAL_LENGTH + size);
+ msg_hdr->length = be32_to_cpu(size);
+
+ size = CMD_MSG_TOTAL_LENGTH + size;
+
+ status = sd_send(adapter, tx_buf, size);
+
+ if (status != STATUS_SUCCESS) {
+ /* crc error or data error -
+ * set PCWRT '1' & send current type A packet again
+ */
+ pr_debug("hwSdioWrite : crc error");
+ kfree(tx_buf);
+ return status;
+ }
+
+ adapter->wimax_image.offset += len;
+
+ kfree(tx_buf);
+
+ return status;
+}
+
diff --git a/drivers/net/wimax/cmc7xx/download.h b/drivers/net/wimax/cmc7xx/download.h
new file mode 100755
index 0000000..34851e0
--- /dev/null
+++ b/drivers/net/wimax/cmc7xx/download.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef _WIMAX_DOWNLOAD_H__
+#define _WIMAX_DOWNLOAD_H__
+
+#define CMC732_RAM_START 0xC0000000
+#define CMC732_WIMAX_ADDRESS CMC732_RAM_START
+
+#define CMD_MSG_TOTAL_LENGTH 12
+#define IMAGE_INFO_MSG_TOTAL_LENGTH 28
+#define CMD_MSG_LENGTH 0
+#define IMAGE_INFO_MSG_LENGTH 16
+#define MAX_IMAGE_DATA_LENGTH 3564
+#define MAX_IMAGE_DATA_MSG_LENGTH 4096
+
+#define MODEM_RESP_RETRY 15
+#define FWDOWNLOAD_TIMEOUT 12
+#define MAX_WIMAXFW_SIZE 2100000
+
+/* used for host boot (firmware download) */
+enum {
+ MSG_DRIVER_OK_REQ = 0x5010,
+ MSG_DRIVER_OK_RESP = 0x6010,
+ MSG_IMAGE_INFO_REQ = 0x3021,
+ MSG_IMAGE_INFO_RESP = 0x4021,
+ MSG_IMAGE_DATA_REQ = 0x3022,
+ MSG_IMAGE_DATA_RESP = 0x4022,
+ MSG_RUN_REQ = 0x5014,
+ MSG_RUN_RESP = 0x6014
+};
+
+struct image_data_payload {
+ u32 offset;
+ u32 size;
+ u8 data[MAX_IMAGE_DATA_LENGTH];
+};
+
+int load_wimax_image(int mode, struct net_adapter *adapter);
+void unload_wimax_image(struct net_adapter *adapter);
+
+u8 send_image_info_packet(struct net_adapter *adapter, u16 cmd_id);
+u8 send_image_data_packet(struct net_adapter *adapter, u16 cmd_id);
+u8 send_cmd_packet(struct net_adapter *adapter, u16 cmd_id);
+u32 sd_send(struct net_adapter *adapter, u8 *buffer, u32 len);
+
+#endif /* _WIMAX_DOWNLOAD_H__ */
diff --git a/drivers/net/wimax/cmc7xx/hardware.c b/drivers/net/wimax/cmc7xx/hardware.c
new file mode 100755
index 0000000..87100d4
--- /dev/null
+++ b/drivers/net/wimax/cmc7xx/hardware.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include "headers.h"
+#include "download.h"
+
+static irqreturn_t wimax_hostwake_isr(int irq, void *dev)
+{
+ struct net_adapter *adapter = dev;
+ wake_lock_timeout(&adapter->pdata->g_cfg->wimax_wake_lock, 1 * HZ);
+
+ return IRQ_HANDLED;
+}
+
+static int cmc732_setup_wake_irq(struct net_adapter *adapter)
+{
+ struct wimax732_platform_data *pdata = adapter->pdata;
+ int rc;
+ int irq;
+
+ rc = gpio_request(pdata->wimax_int, "gpio_wimax_int");
+ if (rc < 0) {
+ pr_debug("%s: gpio %d request failed (%d)\n",
+ __func__, pdata->wimax_int, rc);
+ return rc;
+ }
+
+ rc = gpio_direction_input(pdata->wimax_int);
+ if (rc < 0) {
+ pr_debug("%s: failed to set gpio %d as input (%d)\n",
+ __func__, pdata->wimax_int, rc);
+ goto err_gpio_direction_input;
+ }
+
+ irq = gpio_to_irq(pdata->wimax_int);
+
+ rc = request_threaded_irq(irq, NULL, wimax_hostwake_isr,
+ IRQF_TRIGGER_FALLING, "wimax_int", adapter);
+ if (rc < 0) {
+ pr_debug("%s: request_irq(%d) failed for gpio %d (%d)\n",
+ __func__, irq,
+ pdata->wimax_int, rc);
+ goto err_request_irq;
+ }
+
+ rc = enable_irq_wake(irq);
+ if (rc < 0) {
+ pr_err("%s: enable_irq_wake(%d) failed for gpio %d (%d)\n",
+ __func__, irq, pdata->wimax_int, rc);
+ goto err_enable_irq_wake;
+ }
+
+ adapter->wake_irq = irq;
+
+ return 0;
+
+err_enable_irq_wake:
+ free_irq(irq, adapter);
+err_request_irq:
+err_gpio_direction_input:
+ gpio_free(pdata->wimax_int);
+ return rc;
+}
+
+static void cmc732_release_wake_irq(struct net_adapter *adapter)
+{
+ if (!adapter->wake_irq)
+ return;
+
+ disable_irq_wake(adapter->wake_irq);
+ free_irq(adapter->wake_irq, adapter);
+ gpio_free(adapter->pdata->wimax_int);
+}
+
+int wimax_hw_start(struct net_adapter *adapter)
+{
+ int retry = 0;
+ struct wimax732_platform_data *pdata = adapter->pdata;
+
+ pdata->g_cfg->wimax_status = WIMAX_STATE_READY;
+ adapter->download_complete = false;
+
+ adapter->rx_task = kthread_create(
+ cmc732_receive_thread, adapter, "%s",
+ "cmc732_receive_thread");
+
+ adapter->tx_task = kthread_create(
+ cmc732_send_thread, adapter, "%s",
+ "cmc732_send_thread");
+
+ init_waitqueue_head(&adapter->receive_event);
+ init_waitqueue_head(&adapter->send_event);
+
+ if (adapter->rx_task && adapter->tx_task) {
+ wake_up_process(adapter->rx_task);
+ wake_up_process(adapter->tx_task);
+ } else {
+ pr_debug("Unable to create send-receive threads");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if (load_wimax_image(pdata->g_cfg->wimax_mode, adapter))
+ return STATUS_UNSUCCESSFUL;
+
+ if (adapter->downloading) {
+
+ while (!adapter->modem_resp) {
+ send_cmd_packet(adapter, MSG_DRIVER_OK_REQ);
+ wait_event_interruptible_timeout(
+ adapter->modem_resp_event,
+ adapter->modem_resp,
+ HZ/10);
+ if (!adapter->modem_resp)
+ pr_err("no modem response");
+ if (++retry > MODEM_RESP_RETRY)
+ goto download_fail;
+ }
+
+ switch (wait_event_interruptible_timeout(
+ adapter->download_event,
+ (adapter->download_complete),
+ HZ*FWDOWNLOAD_TIMEOUT)) {
+ case 0:
+ /* timeout */
+ pr_debug("Error wimax_hw_start : \
+ F/W Download timeout failed");
+ goto download_fail;
+ case -ERESTARTSYS:
+ /* Interrupted by signal */
+ pr_debug("Error wimax_hw_start :"
+ "-ERESTARTSYS retry");
+ goto download_fail;
+ default:
+ /* normal condition check */
+ if (adapter->removed || adapter->halted) {
+ pr_debug("Error wimax_hw_start : \
+ F/W Download surprise removed");
+ goto download_fail;
+ }
+ pr_debug("wimax_hw_start : F/W Download Complete");
+ unload_wimax_image(adapter);
+
+ if (cmc732_setup_wake_irq(adapter) < 0)
+ pr_debug("wimax_hw_start :"
+ "Error setting up wimax_int");
+
+ break;
+ }
+ adapter->downloading = false;
+ }
+
+ return STATUS_SUCCESS;
+
+download_fail:
+ adapter->halted = true;
+ wake_up_interruptible(&adapter->receive_event);
+ msleep(20);
+ unload_wimax_image(adapter);
+ return STATUS_UNSUCCESSFUL;
+}
+
+int wimax_hw_stop(struct net_adapter *adapter)
+{
+ adapter->halted = true;
+
+ /*Remove wakeup interrupt*/
+ cmc732_release_wake_irq(adapter);
+
+ /* Stop Sdio Interface */
+ sdio_claim_host(adapter->func);
+ sdio_release_irq(adapter->func);
+ sdio_disable_func(adapter->func);
+ sdio_release_host(adapter->func);
+
+ return STATUS_SUCCESS;
+}
+
+int wimax_hw_init(struct net_adapter *adapter)
+{
+ struct wimax732_platform_data *pdata = adapter->pdata;
+
+ /* set pdata->wimax_wakeup & pdata->wimax_if_mode0 */
+ pdata->set_mode();
+
+ /* initilize hardware info structure */
+ memset(&adapter->hw, 0x0, sizeof(struct hardware_info));
+
+ adapter->hw.receive_buffer = kzalloc(SDIO_BANK_SIZE, GFP_KERNEL);
+ if (adapter->hw.receive_buffer == NULL) {
+ pr_debug("kmalloc fail!!");
+ return -ENOMEM;
+ }
+
+ /* For sending data and control packets */
+ INIT_LIST_HEAD(&adapter->hw.q_send);
+ spin_lock_init(&adapter->hw.lock);
+
+ init_waitqueue_head(&adapter->download_event);
+ init_waitqueue_head(&adapter->modem_resp_event);
+ init_completion(&adapter->wakeup_event);
+
+ return STATUS_SUCCESS;
+}
+
+void wimax_hw_remove(struct net_adapter *adapter)
+{
+ struct buffer_descriptor *bufdsc;
+ struct list_head *pos, *nxt;
+
+ list_for_each_safe(pos, nxt, &adapter->hw.q_send) {
+ bufdsc = list_entry(pos, struct buffer_descriptor, list);
+ list_del(pos);
+ kfree(bufdsc->buffer);
+ kfree(bufdsc);
+ }
+
+ if (adapter->hw.receive_buffer != NULL)
+ kfree(adapter->hw.receive_buffer);
+
+}
diff --git a/drivers/net/wimax/cmc7xx/headers.h b/drivers/net/wimax/cmc7xx/headers.h
new file mode 100755
index 0000000..a94e0fb
--- /dev/null
+++ b/drivers/net/wimax/cmc7xx/headers.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef _WIMAX_HEADERS_H
+#define _WIMAX_HEADERS_H
+
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/proc_fs.h>
+#include <linux/mmc/sdio_ids.h>
+#include <linux/mmc/sdio_func.h>
+#include <asm/byteorder.h>
+#include <linux/uaccess.h>
+#include <linux/wakelock.h>
+#include <linux/wimax/samsung/wimax732.h>
+
+#include "wimax_sdio.h"
+
+#define WIMAX_IMAGE_PATH "wimaxfw.bin"
+#define WIMAX_LOADER_PATH "wimaxloader.bin"
+
+#define STATUS_SUCCESS ((u_long)0x00000000L)
+/* The operation that was requested is pending completion */
+#define STATUS_PENDING ((u_long)0x00000103L)
+#define STATUS_RESOURCES ((u_long)0x00001003L)
+#define STATUS_RESET_IN_PROGRESS ((u_long)0xc001000dL)
+#define STATUS_DEVICE_FAILED ((u_long)0xc0010008L)
+#define STATUS_NOT_ACCEPTED ((u_long)0x00010003L)
+#define STATUS_FAILURE ((u_long)0xC0000001L)
+/* The requested operation was unsuccessful */
+#define STATUS_UNSUCCESSFUL ((u_long)0xC0000002L)
+#define STATUS_CANCELLED ((u_long)0xC0000003L)
+
+/* control.c functions */
+u32 control_send(struct net_adapter *adapter, void *buffer, u32 length);
+void control_recv(struct net_adapter *adapter, void *buffer, u32 length);
+u32 control_init(struct net_adapter *adapter);
+void control_remove(struct net_adapter *adapter);
+
+struct process_descriptor *process_by_id(struct net_adapter *adapter,
+ u32 id);
+struct process_descriptor *process_by_type(struct net_adapter *adapter,
+ u16 type);
+void remove_process(struct net_adapter *adapter, u32 id);
+
+u32 buffer_count(struct list_head ListHead);
+struct buffer_descriptor *buffer_by_type(struct net_adapter *adapter,
+ u16 type);
+
+/* hardware.c functions */
+
+u32 hw_send_data(struct net_adapter *adapter,
+ void *buffer, u32 length);
+void hw_return_packet(struct net_adapter *adapter, u16 type);
+
+int wimax_hw_start(struct net_adapter *adapter);
+int wimax_hw_stop(struct net_adapter *adapter);
+int wimax_hw_init(struct net_adapter *adapter);
+void wimax_hw_remove(struct net_adapter *adapter);
+int wimax_hw_get_mac_address(void *data);
+
+int cmc732_receive_thread(void *data);
+int cmc732_send_thread(void *data);
+
+#endif /* _WIMAX_HEADERS_H */
+
diff --git a/drivers/net/wimax/cmc7xx/hw_types.h b/drivers/net/wimax/cmc7xx/hw_types.h
new file mode 100755
index 0000000..401d6b1
--- /dev/null
+++ b/drivers/net/wimax/cmc7xx/hw_types.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef _WIMAX_HW_TYPES_H
+#define _WIMAX_HW_TYPES_H
+
+#include "ctl_types.h"
+
+/* private protocol defines */
+#define HW_PROT_VALUE_LINK_DOWN 0x00
+#define HW_PROT_VALUE_LINK_UP 0xff
+
+/*
+* SDIO general defines
+* size of a bank in cmc's rx and tx buffers
+*/
+#define SDIO_BANK_SIZE 4096
+/* maximum block size (SDIO) */
+#define SDIO_MAX_BLOCK_SIZE 2048
+/* maximum size in byte mode */
+#define SDIO_MAX_BYTE_SIZE 511
+#define SDIO_BUFFER_SIZE 4092
+#define CMC_BLOCK_SIZE 512
+
+/* SDIO function addresses */
+#define SDIO_TX_BANK_ADDR 0x1000
+#define SDIO_RX_BANK_ADDR 0x10000
+#define SDIO_INT_STATUS_REG 0xC0
+#define SDIO_INT_STATUS_CLR_REG 0xC4
+
+#define SDIO_C2H_WP_REG 0xE4
+#define SDIO_C2H_RP_REG 0xE8
+#define SDIO_H2C_WP_REG 0xEC
+#define SDIO_H2C_RP_REG 0xF0
+
+/* SDIO function registers */
+#define SDIO_INT_DATA_READY 0x01
+#define SDIO_INT_ERROR 0x02
+
+#define WAKEUP_MAX_TRY 6
+#define WAKEUP_TIMEOUT 2000
+
+/* packet types */
+enum {
+ HWPKTTYPENONE = 0xff00,
+ HWPKTTYPEPRIVATE,
+ HWPKTTYPECONTROL,
+ HWPKTTYPEDATA,
+ HWPKTTYPETIMEOUT
+};
+
+/* private packet opcodes */
+enum {
+ HWCODEMACREQUEST = 0x01,
+ HWCODEMACRESPONSE,
+ HWCODELINKINDICATION,
+ HWCODERXREADYINDICATION,
+ HWCODEHALTEDINDICATION,
+ HWCODEIDLENTFY,
+ HWCODEWAKEUPNTFY
+};
+
+#pragma pack(1)
+struct hw_packet_header {
+ char id0; /* packet ID */
+ char id1;
+ u16 length; /* packet length */
+};
+
+struct hw_private_packet {
+ char id0; /* packet ID */
+ char id1;
+ u8 code; /* command code */
+ u8 value; /* command value */
+};
+#pragma pack()
+
+struct wimax_msg_header {
+ u16 type;
+ u16 id;
+ u32 length;
+};
+
+struct buffer_descriptor {
+ struct list_head list; /* list node */
+ void *buffer; /* allocated buffer: */
+ u32 length; /* current data length */
+ u16 type; /* buffer type used
+ * for control
+ * buffers
+ */
+};
+
+struct hardware_info {
+ void *receive_buffer;
+ u8 eth_header[ETHERNET_ADDRESS_LENGTH * 2];
+ struct list_head q_send; /* send pending queue */
+ spinlock_t lock;
+};
+
+#endif /* _WIMAX_HW_TYPES_H */
diff --git a/drivers/net/wimax/cmc7xx/receive.c b/drivers/net/wimax/cmc7xx/receive.c
new file mode 100755
index 0000000..7126a62
--- /dev/null
+++ b/drivers/net/wimax/cmc7xx/receive.c
@@ -0,0 +1,464 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include "headers.h"
+#include "download.h"
+
+static void process_indicate_packet(struct net_adapter *adapter, u8 *buffer)
+{
+ struct wimax_msg_header *packet;
+ struct wimax_cfg *g_cfg = adapter->pdata->g_cfg;
+ char *tmp_byte;
+
+ packet = (struct wimax_msg_header *)buffer;
+
+ if (packet->type != be16_to_cpu(ETHERTYPE_DL)) {
+ pr_warn("%s: not a download packet\n", __func__);
+ return;
+ }
+
+ switch (be16_to_cpu(packet->id)) {
+ case MSG_DRIVER_OK_RESP:
+ adapter->modem_resp = true;
+ wake_up_interruptible(&adapter->modem_resp_event);
+ pr_debug("%s: MSG_DRIVER_OK_RESP\n", __func__);
+ send_image_info_packet(adapter, MSG_IMAGE_INFO_REQ);
+ break;
+ case MSG_IMAGE_INFO_RESP:
+ pr_debug("%s: MSG_IMAGE_INFO_RESP\n", __func__);
+ send_image_data_packet(adapter, MSG_IMAGE_DATA_REQ);
+ break;
+ case MSG_IMAGE_DATA_RESP:
+ if (adapter->wimax_image.offset == adapter->wimax_image.size) {
+ pr_debug("%s: Image Download Complete\n", __func__);
+ send_cmd_packet(adapter, MSG_RUN_REQ);
+ } else {
+ send_image_data_packet(adapter, MSG_IMAGE_DATA_REQ);
+ }
+ break;
+ case MSG_RUN_RESP:
+ tmp_byte = (char *)(buffer + sizeof(struct wimax_msg_header));
+
+ if (*tmp_byte != 0x01)
+ break;
+
+ adapter->download_complete = true;
+ wake_up_interruptible(&adapter->download_event);
+
+ pr_debug("%s: MSG_RUN_RESP\n", __func__);
+ if (g_cfg->wimax_mode == SDIO_MODE
+ || g_cfg->wimax_mode == DM_MODE
+ || g_cfg->wimax_mode == USB_MODE
+ || g_cfg->wimax_mode == USIM_RELAY_MODE) {
+
+ adapter->mac_task = kthread_create(
+ wimax_hw_get_mac_address, adapter,
+ "%s", "mac_request_thread");
+ if (adapter->mac_task)
+ wake_up_process(adapter->mac_task);
+
+ } else if (g_cfg->wimax_mode == WTM_MODE
+ || g_cfg->wimax_mode == AUTH_MODE) {
+ adapter->download_complete = true;
+ wake_up_interruptible(&adapter->download_event);
+ }
+ break;
+ default:
+ pr_err("%s: Unknown packet type\n", __func__);
+ break;
+ }
+}
+
+static u32 process_private_cmd(struct net_adapter *adapter, void *buffer)
+{
+ struct hw_private_packet *cmd;
+ struct wimax_cfg *g_cfg = adapter->pdata->g_cfg;
+ u8 *bufp;
+ int ret;
+
+ cmd = (struct hw_private_packet *)buffer;
+
+ switch (cmd->code) {
+ case HWCODEMACRESPONSE: {
+ u8 mac_addr[ETHERNET_ADDRESS_LENGTH];
+ bufp = (u8 *)buffer;
+
+ /* processing for mac_req request */
+ pr_debug("MAC address = %02x:%02x:%02x:%02x:%02x:%02x",
+ bufp[3], bufp[4], bufp[5],
+ bufp[6], bufp[7], bufp[8]);
+ memcpy(mac_addr, bufp + 3,
+ ETHERNET_ADDRESS_LENGTH);
+
+ /* create ethernet header */
+ memcpy(adapter->hw.eth_header,
+ mac_addr, ETHERNET_ADDRESS_LENGTH);
+ memcpy(adapter->hw.eth_header + ETHERNET_ADDRESS_LENGTH,
+ mac_addr, ETHERNET_ADDRESS_LENGTH);
+ adapter->hw.eth_header[(ETHERNET_ADDRESS_LENGTH * 2) - 1] += 1;
+
+ memcpy(adapter->net->dev_addr, bufp + 3,
+ ETHERNET_ADDRESS_LENGTH);
+ adapter->mac_ready = true;
+
+ ret = sizeof(struct hw_private_packet)
+ + ETHERNET_ADDRESS_LENGTH - sizeof(u8);
+ return ret;
+ }
+ case HWCODELINKINDICATION: {
+ if ((cmd->value == HW_PROT_VALUE_LINK_DOWN)
+ && (adapter->media_state != MEDIA_DISCONNECTED)) {
+ pr_debug("LINK_DOWN_INDICATION");
+
+ /* set values */
+ adapter->media_state = MEDIA_DISCONNECTED;
+ g_cfg->wimax_status = WIMAX_STATE_READY;
+
+ /* indicate link down */
+ netif_stop_queue(adapter->net);
+ netif_carrier_off(adapter->net);
+ } else if ((cmd->value == HW_PROT_VALUE_LINK_UP)
+ && (adapter->media_state != MEDIA_CONNECTED)) {
+ pr_debug("LINK_UP_INDICATION");
+
+ /* set values */
+ adapter->media_state = MEDIA_CONNECTED;
+ g_cfg->wimax_status = WIMAX_STATE_NORMAL;
+ adapter->net->mtu = WIMAX_MTU_SIZE;
+
+ /* indicate link up */
+ netif_start_queue(adapter->net);
+ netif_carrier_on(adapter->net);
+ }
+ break;
+ }
+ case HWCODEHALTEDINDICATION: {
+ pr_debug("Device is about to reset, stop driver");
+ adapter->halted = true;
+ break;
+ }
+ case HWCODERXREADYINDICATION: {
+ pr_debug("Device RxReady");
+ /*
+ * to start the data packet send
+ * queue again after stopping in xmit
+ */
+ if (adapter->media_state == MEDIA_CONNECTED)
+ netif_wake_queue(adapter->net);
+ break;
+ }
+ case HWCODEIDLENTFY: {
+ /* set idle / vi */
+ if (g_cfg->wimax_status == WIMAX_STATE_NORMAL
+ || g_cfg->wimax_status == WIMAX_STATE_IDLE) {
+ pr_debug("process_private_cmd: IDLE");
+ g_cfg->wimax_status = WIMAX_STATE_IDLE;
+ } else {
+ pr_debug("process_private_cmd: VIRTUAL IDLE");
+ g_cfg->wimax_status = WIMAX_STATE_VIRTUAL_IDLE;
+ }
+ break;
+ }
+ case HWCODEWAKEUPNTFY: {
+ /*
+ * IMPORTANT!! at least 4 sec
+ * is required after modem waked up
+ */
+ wake_lock_timeout(&g_cfg->wimax_wake_lock, 4 * HZ);
+
+ if (g_cfg->wimax_status ==
+ WIMAX_STATE_AWAKE_REQUESTED) {
+ complete(&adapter->wakeup_event);
+ break;
+ }
+
+ if (g_cfg->wimax_status == WIMAX_STATE_IDLE
+ || g_cfg->wimax_status == WIMAX_STATE_NORMAL) {
+ pr_debug("process_private_cmd: IDLE -> NORMAL");
+ g_cfg->wimax_status = WIMAX_STATE_NORMAL;
+ } else {
+ pr_debug("process_private_cmd: VI -> READY");
+ g_cfg->wimax_status = WIMAX_STATE_READY;
+ }
+ break;
+ }
+ default:
+ pr_debug("Command = %04x", cmd->code);
+ break;
+ }
+
+ return sizeof(struct hw_private_packet);
+}
+
+
+static void adapter_sdio_rx_packet(struct net_adapter *adapter, int len)
+{
+ struct hw_packet_header *hdr;
+ int rlen;
+ u32 type;
+ u8 *ofs;
+ struct sk_buff *rx_skb;
+
+ rlen = len;
+ ofs = (u8 *)adapter->hw.receive_buffer;
+
+ while (rlen > 0) {
+ hdr = (struct hw_packet_header *)ofs;
+ type = HWPKTTYPENONE;
+
+ /* "WD", "WC", "WP" or "WE" */
+ if (unlikely(hdr->id0 != 'W')) {
+ if (rlen > 4) {
+ pr_debug("Wrong packet \
+ ID (%02x %02x)", hdr->id0, hdr->id1);
+ }
+ /* skip rest of packets */
+ break;
+ }
+
+ /* check packet type */
+ switch (hdr->id1) {
+ case 'P': {
+ u32 l = 0;
+ type = HWPKTTYPEPRIVATE;
+
+ /* process packet */
+ l = process_private_cmd(adapter, ofs);
+
+ /* shift */
+ ofs += l;
+ rlen -= l;
+
+ /* process next packet */
+ continue;
+ }
+ case 'C':
+ type = HWPKTTYPECONTROL;
+ break;
+ case 'D':
+ type = HWPKTTYPEDATA;
+ break;
+ case 'E':
+ /* skip rest of buffer */
+ break;
+ default:
+ pr_debug("hwParseReceivedData : \
+ Wrong packet ID [%02x %02x]",
+ hdr->id0, hdr->id1);
+ /* skip rest of buffer */
+ break;
+ }
+
+ if (type == HWPKTTYPENONE)
+ break;
+
+ if (likely(!adapter->downloading)) {
+ if (unlikely(hdr->length > WIMAX_MAX_TOTAL_SIZE
+ || ((hdr->length +
+ sizeof(struct hw_packet_header)) > rlen))) {
+ pr_debug("Packet length is \
+ too big (%d)", hdr->length);
+ /* skip rest of packets */
+ break;
+ }
+ }
+
+ /* change offset */
+ ofs += sizeof(struct hw_packet_header);
+ rlen -= sizeof(struct hw_packet_header);
+
+ /* process download packet, data and control packet */
+ if (likely(!adapter->downloading)) {
+ ofs += 2;
+ rlen -= 2;
+
+ if (unlikely(type == HWPKTTYPECONTROL))
+ control_recv(adapter, (u8 *)ofs,
+ hdr->length);
+ else {
+ if (hdr->length > BUFFER_DATA_SIZE) {
+ pr_debug("Data packet too large");
+ adapter->netstats.rx_dropped++;
+ break;
+ }
+
+ rx_skb = dev_alloc_skb(hdr->length +
+ (ETHERNET_ADDRESS_LENGTH * 2));
+ if (!rx_skb) {
+ pr_debug("MEMORY PINCH: \
+ unable to allocate skb");
+ break;
+ }
+ skb_reserve(rx_skb,
+ (ETHERNET_ADDRESS_LENGTH * 2));
+
+ memcpy(skb_push(rx_skb,
+ (ETHERNET_ADDRESS_LENGTH * 2)),
+ adapter->hw.eth_header,
+ (ETHERNET_ADDRESS_LENGTH * 2));
+
+ memcpy(skb_put(rx_skb, hdr->length),
+ (u8 *)ofs,
+ hdr->length);
+
+ rx_skb->dev = adapter->net;
+ rx_skb->protocol =
+ eth_type_trans(rx_skb, adapter->net);
+ rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+ if (netif_rx_ni(rx_skb) == NET_RX_DROP) {
+ pr_debug("packet dropped!");
+ adapter->netstats.rx_dropped++;
+ }
+ adapter->netstats.rx_packets++;
+ adapter->netstats.rx_bytes +=
+ (hdr->length +
+ (ETHERNET_ADDRESS_LENGTH * 2));
+
+ }
+ } else {
+ hdr->length -= sizeof(struct hw_packet_header);
+ process_indicate_packet(adapter, ofs);
+ }
+ /*
+ * If the packet is unreasonably long,
+ * quietly drop it rather than
+ * kernel panicing by calling skb_put.
+ *
+ * shift
+ */
+ ofs += hdr->length;
+ rlen -= hdr->length;
+ }
+
+ return;
+}
+
+static int hw_sdio_read_bank_index(struct net_adapter *adapter, int *read_idx)
+{
+ int ret = 0;
+
+ *read_idx = sdio_readb(adapter->func, SDIO_C2H_RP_REG, &ret);
+ if (ret)
+ return ret;
+
+ if (*read_idx == sdio_readb(adapter->func, SDIO_C2H_WP_REG, &ret))
+ *read_idx = -1;
+
+ return ret;
+}
+
+static int hw_sdio_read_counter(struct net_adapter *adapter, u32 *len,
+ int read_idx)
+{
+ int ret = 0;
+
+ *len = sdio_readw(adapter->func, (SDIO_RX_BANK_ADDR +
+ (read_idx * SDIO_BANK_SIZE)), &ret);
+ if (ret)
+ return ret;
+
+ *len |= sdio_readw(adapter->func, (SDIO_RX_BANK_ADDR +
+ (read_idx * SDIO_BANK_SIZE) + 2), &ret) << 16;
+
+ if (*len > SDIO_BUFFER_SIZE)
+ *len = 0;
+
+ return ret;
+}
+
+int cmc732_receive_thread(void *data)
+{
+ struct net_adapter *adapter = (struct net_adapter *)data;
+ int err = 1;
+ int nReadIdx;
+ u32 len = 0;
+ u32 t_len;
+ u32 t_index;
+ u32 t_size;
+ u8 *t_buff;
+
+ do {
+
+ wait_event_interruptible(adapter->receive_event,
+ adapter->rx_data_available
+ || (!adapter) || adapter->halted);
+ adapter->rx_data_available = false;
+ if ((!adapter) || adapter->halted)
+ break;
+ sdio_claim_host(adapter->func);
+ err = hw_sdio_read_bank_index(adapter, &nReadIdx);
+
+ if (err) {
+ pr_debug("adapter_sdio_rx_packet : \
+ error occurred during fetch bank \
+ index!! err = %d, nReadIdx = %d", \
+ err, nReadIdx);
+ sdio_release_host(adapter->func);
+ continue;
+ }
+ if (nReadIdx < 0) {
+ sdio_release_host(adapter->func);
+ continue;
+ }
+ err = hw_sdio_read_counter(adapter, &len, nReadIdx);
+ if (unlikely(err || !len)) {
+ pr_debug("adapter_sdio_rx_packet : \
+ error in reading bank length!! \
+ err = %d, len = %d", err, len);
+ sdio_release_host(adapter->func);
+ continue;
+ }
+
+ if (unlikely(len > SDIO_BUFFER_SIZE)) {
+ pr_debug("ERROR RECV length (%d) > \
+ SDIO_BUFFER_SIZE", len);
+ len = SDIO_BUFFER_SIZE;
+ }
+
+ sdio_writeb(adapter->func, (nReadIdx + 1) % 16,
+ SDIO_C2H_RP_REG, NULL);
+
+ t_len = len;
+ t_index = (SDIO_RX_BANK_ADDR + (SDIO_BANK_SIZE * nReadIdx) + 4);
+ t_buff = (u8 *)adapter->hw.receive_buffer;
+
+ while (t_len) {
+ t_size = (t_len > CMC_BLOCK_SIZE) ?
+ (CMC_BLOCK_SIZE) : t_len;
+ err = sdio_memcpy_fromio(adapter->func, (void *)t_buff,
+ t_index, t_size);
+ t_len -= t_size;
+ t_buff += t_size;
+ t_index += t_size;
+ }
+
+ if (unlikely(err || !len)) {
+ pr_debug("adapter_sdio_rx_packet : \
+ error in receiving packet!!drop the \
+ packet errt = %d, len = %d", err, len);
+ sdio_release_host(adapter->func);
+ continue;
+ }
+ sdio_release_host(adapter->func);
+ adapter_sdio_rx_packet(adapter, len);
+ } while (adapter);
+
+ adapter->halted = true;
+
+ pr_debug("cmc732_receive_thread exiting");
+
+ do_exit(0);
+
+return 0;
+}
diff --git a/drivers/net/wimax/cmc7xx/send.c b/drivers/net/wimax/cmc7xx/send.c
new file mode 100755
index 0000000..46eaa5c
--- /dev/null
+++ b/drivers/net/wimax/cmc7xx/send.c
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include "headers.h"
+#include "download.h"
+#include <linux/mutex.h>
+
+static int hw_sdio_write_bank_index(struct net_adapter *adapter, int *write_idx)
+{
+ int ret = 0;
+
+ *write_idx = sdio_readb(adapter->func, SDIO_H2C_WP_REG, &ret);
+ if (ret)
+ return ret;
+
+ if (((*write_idx + 1) % 15) == sdio_readb(adapter->func,
+ SDIO_H2C_RP_REG, &ret))
+ *write_idx = -1;
+
+ return ret;
+}
+
+u32 sd_send(struct net_adapter *adapter, u8 *buffer, u32 len)
+{
+ int nRet;
+
+ int nWriteIdx;
+
+ len += (len & 1) ? 1 : 0;
+
+ if (adapter->halted || adapter->removed) {
+ pr_debug("Halted Already");
+ return STATUS_UNSUCCESSFUL;
+ }
+ sdio_claim_host(adapter->func);
+ nRet = hw_sdio_write_bank_index(adapter, &nWriteIdx);
+
+ if (nRet || (nWriteIdx < 0)) {
+ pr_debug("sd_send : error occurred during \
+ fetch bank index!! nRet = %d, nWriteIdx = %d",
+ nRet, nWriteIdx);
+ sdio_release_host(adapter->func);
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ sdio_writeb(adapter->func, (nWriteIdx + 1) % 15, SDIO_H2C_WP_REG, NULL);
+ nRet = sdio_memcpy_toio(adapter->func,
+ SDIO_TX_BANK_ADDR+(SDIO_BANK_SIZE * nWriteIdx)+4,
+ buffer, len);
+
+ if (nRet < 0)
+ pr_debug("sd_send : error in sending packet!! nRet = %d",
+ nRet);
+
+ nRet = sdio_memcpy_toio(adapter->func,
+ SDIO_TX_BANK_ADDR + (SDIO_BANK_SIZE * nWriteIdx),
+ &len, 4);
+ sdio_release_host(adapter->func);
+ if (nRet < 0)
+ pr_debug("sd_send : error in writing bank length!! nRet = %d",
+ nRet);
+
+ return nRet;
+}
+
+
+/* get MAC address from device */
+int wimax_hw_get_mac_address(void *data)
+{
+ struct net_adapter *adapter = (struct net_adapter *)data;
+ struct hw_private_packet req;
+ int nResult = 0;
+ int retry = 4;
+
+ req.id0 = 'W';
+ req.id1 = 'P';
+ req.code = HWCODEMACREQUEST;
+ req.value = 0;
+
+ pr_debug("wait for SDIO ready..");
+ msleep(1700); /*
+ * IMPORTANT! wait for cmc720 can
+ * handle mac req packet
+ */
+ do {
+
+ nResult = sd_send(adapter, (u8 *)&req,
+ sizeof(struct hw_private_packet));
+
+ if (nResult != STATUS_SUCCESS)
+ pr_debug("wimax_hw_get_mac_address: sd_send fail!!");
+ msleep(300);
+
+ }
+ while ((!adapter->mac_ready) && (adapter) && (retry--));
+
+ do_exit(0);
+
+ return 0;
+}
+
+u32 hw_send_data(struct net_adapter *adapter, void *buffer , u32 length)
+{
+ struct buffer_descriptor *bufdsc;
+ struct hw_packet_header *hdr;
+ struct net_device *net = adapter->net;
+ u8 *ptr;
+
+ bufdsc = (struct buffer_descriptor *)
+ kmalloc(sizeof(struct buffer_descriptor), GFP_ATOMIC);
+ if (bufdsc == NULL)
+ return STATUS_RESOURCES;
+
+ bufdsc->buffer = kmalloc(BUFFER_DATA_SIZE, GFP_ATOMIC);
+ if (bufdsc->buffer == NULL) {
+ kfree(bufdsc);
+ return STATUS_RESOURCES;
+ }
+
+ ptr = bufdsc->buffer;
+
+ /* shift data pointer */
+ ptr += sizeof(struct hw_packet_header);
+ ptr += 2;
+ hdr = (struct hw_packet_header *)bufdsc->buffer;
+
+ length -= (ETHERNET_ADDRESS_LENGTH * 2);
+ buffer += (ETHERNET_ADDRESS_LENGTH * 2);
+
+ memcpy(ptr, buffer, length);
+
+ hdr->id0 = 'W';
+ hdr->id1 = 'D';
+ hdr->length = (u16)length;
+
+ bufdsc->length = length + sizeof(struct hw_packet_header);
+ bufdsc->length += 2;
+
+ /* add statistics */
+ adapter->netstats.tx_packets++;
+ adapter->netstats.tx_bytes += bufdsc->length;
+
+ spin_lock(&adapter->hw.lock);
+ list_add_tail(&bufdsc->list, &adapter->hw.q_send);
+ spin_unlock(&adapter->hw.lock);
+
+ wake_up_interruptible(&adapter->send_event);
+ if (!netif_running(net))
+ pr_debug("!netif_running");
+
+ return STATUS_SUCCESS;
+}
+
+static u32 sd_send_data(struct net_adapter *adapter,
+ struct buffer_descriptor *bufdsc)
+{
+ if (bufdsc->length > SDIO_MAX_BYTE_SIZE)
+ bufdsc->length = (bufdsc->length + SDIO_MAX_BYTE_SIZE) &
+ ~(SDIO_MAX_BYTE_SIZE);
+
+ if (adapter->halted) {
+ pr_debug("Halted Already");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ return sd_send(adapter, bufdsc->buffer, bufdsc->length);
+}
+
+int hw_device_wakeup(struct net_adapter *adapter)
+{
+ struct wimax732_platform_data *pdata = adapter->pdata;
+ int rc = 0;
+ u8 retryCount = 0;
+
+ if (pdata->g_cfg->wimax_status == WIMAX_STATE_READY) {
+ pr_debug("not ready!!");
+ return 0;
+ }
+
+ adapter->prev_wimax_status = pdata->g_cfg->wimax_status;
+ pdata->g_cfg->wimax_status = WIMAX_STATE_AWAKE_REQUESTED;
+
+ /* try to wake up */
+ while (retryCount < WAKEUP_MAX_TRY) {
+ rc = wait_for_completion_interruptible_timeout(
+ &adapter->wakeup_event,
+ msecs_to_jiffies(WAKEUP_TIMEOUT));
+
+ /* received wakeup ack */
+ if (rc)
+ break;
+
+ retryCount++;
+
+ if (pdata->is_modem_awake()) {
+ pr_debug("WiMAX active pin HIGH ..");
+ break;
+ }
+ }
+
+ /* check WiMAX modem response */
+ if (!pdata->is_modem_awake()) {
+ pr_debug("FATAL ERROR!! MODEM DOES NOT WAKEUP!!");
+ adapter->halted = true;
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if (pdata->g_cfg->wimax_status == WIMAX_STATE_AWAKE_REQUESTED) {
+ if (adapter->prev_wimax_status == WIMAX_STATE_IDLE
+ ||
+ adapter->prev_wimax_status == WIMAX_STATE_NORMAL) {
+ pr_debug("hw_device_wakeup: IDLE -> NORMAL");
+ pdata->g_cfg->wimax_status = WIMAX_STATE_NORMAL;
+ } else {
+ pr_debug("hw_device_wakeup: VI -> READY");
+ pdata->g_cfg->wimax_status = WIMAX_STATE_READY;
+ }
+ }
+
+ return STATUS_SUCCESS;
+}
+
+int cmc732_send_thread(void *data)
+{
+ struct net_adapter *adapter = (struct net_adapter *)data;
+ struct wimax732_platform_data *pdata;
+ struct buffer_descriptor *bufdsc = NULL;
+ int nRet = 0;
+ bool reset_modem = false;
+
+ pdata = adapter->pdata;
+
+ do {
+ wait_event_interruptible(adapter->send_event,
+ (!list_empty(&adapter->hw.q_send))
+ || (!adapter) || adapter->halted);
+
+ if ((!adapter) || adapter->halted)
+ break;
+
+ wake_lock(&pdata->g_cfg->wimax_tx_lock);
+ mutex_lock(&pdata->g_cfg->suspend_mutex);
+ pdata->wakeup_assert(1);
+
+ if ((pdata->g_cfg->wimax_status == WIMAX_STATE_IDLE ||
+ pdata->g_cfg->wimax_status == WIMAX_STATE_VIRTUAL_IDLE)
+ && !pdata->is_modem_awake()) {
+ if (hw_device_wakeup(adapter)) {
+ reset_modem = true;
+ mutex_unlock(&pdata->g_cfg->suspend_mutex);
+ wake_unlock(&pdata->g_cfg->wimax_tx_lock);
+ break;
+ }
+ }
+
+ spin_lock(&adapter->hw.lock);
+ if (!list_empty(&adapter->hw.q_send)) {
+ bufdsc = list_first_entry(&adapter->hw.q_send,
+ struct buffer_descriptor, list);
+ list_del(&bufdsc->list);
+ }
+ spin_unlock(&adapter->hw.lock);
+
+ if (!bufdsc) {
+ pr_debug("Fail...node is null");
+ mutex_unlock(&pdata->g_cfg->suspend_mutex);
+ wake_unlock(&pdata->g_cfg->wimax_tx_lock);
+ continue;
+ }
+ nRet = sd_send_data(adapter, bufdsc);
+ pdata->wakeup_assert(0);
+ mutex_unlock(&pdata->g_cfg->suspend_mutex);
+ wake_unlock(&pdata->g_cfg->wimax_tx_lock);
+ kfree(bufdsc->buffer);
+ kfree(bufdsc);
+ if (nRet != STATUS_SUCCESS) {
+ pr_debug("SendData Fail******");
+ ++adapter->XmitErr;
+ reset_modem = true;
+ break;
+ }
+ } while (adapter);
+
+ pr_debug("cmc732_send_thread exiting");
+
+ adapter->halted = true;
+ if (reset_modem)
+ pdata->power(0);
+
+ do_exit(0);
+
+ return 0;
+}
diff --git a/drivers/net/wimax/cmc7xx/wimax_sdio.c b/drivers/net/wimax/cmc7xx/wimax_sdio.c
new file mode 100755
index 0000000..99830da
--- /dev/null
+++ b/drivers/net/wimax/cmc7xx/wimax_sdio.c
@@ -0,0 +1,823 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include "headers.h"
+#include "ctl_types.h"
+#include "download.h"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/miscdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/mmc/sdio_ids.h>
+#include <linux/mmc/pm.h>
+#include <linux/mmc/sdio_func.h>
+#include <asm/byteorder.h>
+#include <linux/uaccess.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/platform_device.h>
+
+/* driver Information */
+#define WIMAX_DRIVER_VERSION_STRING "3.0.4"
+#define DRIVER_AUTHOR "Samsung"
+#define DRIVER_DESC "Samsung WiMAX SDIO Device Driver"
+
+#define UWBRBDEVMINOR 233
+#define SWMXGPIOMINOR 234
+
+/* use ethtool to change the level for any given device */
+static int msg_level = -1;
+module_param(msg_level, int, 0);
+
+static long swmxdev_ioctl(struct file *file, u32 cmd,
+ unsigned long arg)
+{
+ int ret = 0;
+ u8 val = ((u8 *)arg)[0];
+ struct wimax732_platform_data *gpdata =
+ (struct wimax732_platform_data *)(file->private_data);
+
+ pr_debug("CMD: %x, PID: %d", cmd, current->tgid);
+
+ switch (cmd) {
+ case CONTROL_IOCTL_WIMAX_POWER_CTL: {
+ pr_debug("CONTROL_IOCTL_WIMAX_POWER_CTL..");
+ if (val == 0) {
+ pr_debug("WIMAX POWER OFF");
+ ret = gpdata->power(0);
+ } else {
+ pr_debug("WIMAX POWER ON");
+ ret = gpdata->power(1);
+ }
+ break;
+ }
+ case CONTROL_IOCTL_WIMAX_MODE_CHANGE: {
+ pr_debug("CONTROL_IOCTL_WIMAX_MODE_CHANGE to 0x%02x..", val);
+
+ if ((val < 0) || (val > AUTH_MODE)) {
+ pr_debug("Wrong mode 0x%02x", val);
+ return 0;
+ }
+
+ gpdata->power(0);
+ gpdata->g_cfg->wimax_mode = val;
+ ret = gpdata->power(1);
+ break;
+ }
+ } /* switch (cmd) */
+
+ return ret;
+}
+
+static int swmxdev_open(struct inode *inode, struct file *file)
+{
+ struct wimax732_platform_data *pdata =
+ container_of(file->private_data,
+ struct wimax732_platform_data, swmxctl_dev);
+ file->private_data = pdata;
+ return 0;
+}
+
+static const struct file_operations swmx_fops = {
+ .owner = THIS_MODULE,
+ .open = swmxdev_open,
+ .unlocked_ioctl = swmxdev_ioctl,
+};
+
+/*
+* uwibro functions
+* (send and receive control packet with WiMAX modem)
+*/
+static int uwbrdev_open(struct inode *inode, struct file *file)
+{
+ struct net_adapter *adapter = container_of(file->private_data,
+ struct net_adapter, uwibro_dev);
+ struct process_descriptor *procdsc;
+
+ if ((adapter == NULL) || adapter->halted) {
+ pr_debug("can't find adapter or Device Removed");
+ return -ENODEV;
+ }
+
+ file->private_data = adapter;
+ pr_debug("open: tgid=%d", current->tgid);
+
+ if (!adapter->mac_ready || adapter->halted) {
+ pr_debug("Device not ready Retry..");
+ return -ENXIO;
+ }
+
+ /* init new process descriptor */
+ procdsc = kmalloc(sizeof(*procdsc), GFP_KERNEL);
+ if (procdsc == NULL) {
+ pr_debug("uwbrdev_open: kmalloc fail!!");
+ return -ENOMEM;
+ }
+
+ procdsc->id = current->tgid;
+ procdsc->irp = false;
+ procdsc->type = 0;
+ init_waitqueue_head(&procdsc->read_wait);
+ spin_lock(&adapter->ctl.apps.lock);
+ list_add_tail(&procdsc->list, &adapter->ctl.apps.process_list);
+ spin_unlock(&adapter->ctl.apps.lock);
+ return 0;
+}
+
+static int uwbrdev_release(struct inode *inode, struct file *file)
+{
+ struct net_adapter *adapter;
+ struct process_descriptor *procdsc;
+ int current_tgid = 0;
+
+ pr_debug("release: tgid=%d, pid=%d", current->tgid, current->pid);
+
+ adapter = (struct net_adapter *)(file->private_data);
+ if (adapter == NULL) {
+ pr_debug("can't find adapter");
+ return -ENODEV;
+ }
+
+ current_tgid = current->tgid;
+ procdsc = process_by_id(adapter, current_tgid);
+
+ /* process is not exist. (open process != close process) */
+ if (procdsc == NULL) {
+ current_tgid = adapter->pdata->g_cfg->temp_tgid;
+ pr_debug("release: pid changed: %d", current_tgid);
+ procdsc = process_by_id(adapter, current_tgid);
+ }
+
+ if (procdsc == NULL) {
+ /*not found */
+ pr_debug("process %d not found", current_tgid);
+ return -ESRCH;
+ }
+
+ /* RELEASE READ THREAD */
+ if (procdsc->irp) {
+ procdsc->irp = false;
+ wake_up_interruptible(&procdsc->read_wait);
+ }
+ spin_lock(&adapter->ctl.apps.lock);
+ remove_process(adapter, current_tgid);
+ spin_unlock(&adapter->ctl.apps.lock);
+
+ return 0;
+}
+
+static long uwbrdev_ioctl(struct file *file, u32 cmd,
+ unsigned long arg)
+{
+ struct net_adapter *adapter;
+ struct process_descriptor *procdsc;
+ int ret = 0;
+ struct eth_header *ctlhdr;
+ u8 *tx_buffer;
+ int length;
+
+ adapter = (struct net_adapter *)(file->private_data);
+
+ if ((adapter == NULL) || adapter->halted) {
+ pr_debug("can't find adapter or Device Removed");
+ return -ENODEV;
+ }
+
+ if (cmd != CONTROL_IOCTL_WRITE_REQUEST) {
+ pr_debug("uwbrdev_ioctl: unknown ioctl cmd: 0x%x", cmd);
+ return -EINVAL;
+ }
+
+ if ((char *)arg == NULL) {
+ pr_debug("arg == NULL: return -EFAULT");
+ return -EFAULT;
+ }
+
+ length = ((int *)arg)[0];
+
+ if (length >= WIMAX_MAX_TOTAL_SIZE)
+ return -EFBIG;
+
+ tx_buffer = kmalloc(length, GFP_KERNEL);
+ if (!tx_buffer) {
+ pr_err("%s: not enough memory to allocate tx_buffer\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ if (copy_from_user(tx_buffer, (void *)(arg + sizeof(int)), length)) {
+ pr_err("%s: error copying buffer from user space\n", __func__);
+ ret = -EFAULT;
+ goto err_copy;
+ }
+
+ spin_lock(&adapter->ctl.apps.lock);
+ procdsc = process_by_id(adapter, current->tgid);
+ if (procdsc == NULL) {
+ pr_debug("process %d not found", current->tgid);
+ ret = -EFAULT;
+ goto err_process;
+ }
+ ctlhdr = (struct eth_header *)tx_buffer;
+ procdsc->type = ctlhdr->type;
+
+ control_send(adapter, tx_buffer, length);
+
+err_process:
+ spin_unlock(&adapter->ctl.apps.lock);
+err_copy:
+ kfree(tx_buffer);
+ return ret;
+}
+
+static ssize_t uwbrdev_read(struct file *file, char *buf, size_t count,
+ loff_t *ppos)
+{
+ struct buffer_descriptor *bufdsc;
+ struct net_adapter *adapter;
+ struct process_descriptor *procdsc;
+ int rlen = 0;
+
+ adapter = (struct net_adapter *)(file->private_data);
+ if ((adapter == NULL) || adapter->halted) {
+ pr_debug("can't find adapter or Device Removed");
+ return -ENODEV;
+ }
+
+ if (buf == NULL) {
+ pr_debug("BUFFER is NULL");
+ return -EFAULT; /* bad address */
+ }
+
+ procdsc = process_by_id(adapter, current->tgid);
+ if (procdsc == NULL) {
+ pr_debug("uwbrdev_read: process %d not exist", current->tgid);
+ return -ESRCH;
+ }
+
+ if (procdsc->irp == true) {
+ pr_warn("%s: Read was sent twice by process %d\n", __func__,
+ current->tgid);
+ return -EEXIST;
+ }
+
+ bufdsc = buffer_by_type(adapter, procdsc->type);
+ if (bufdsc == NULL) {
+ procdsc->irp = true;
+ if (wait_event_interruptible(procdsc->read_wait,
+ ((procdsc->irp == false) ||
+ (adapter->halted == true)))) {
+ procdsc->irp = false;
+ adapter->pdata->g_cfg->temp_tgid = current->tgid;
+ return -ERESTARTSYS;
+ }
+ if (adapter->halted) {
+ pr_debug("uwbrdev_read: Card Removed"
+ "Indicated to Appln...");
+ procdsc->irp = false;
+ adapter->pdata->g_cfg->temp_tgid = current->tgid;
+ return -ENODEV;
+ }
+ }
+
+ if (count == 1500) { /* app passes read count as 1500 */
+ spin_lock(&adapter->ctl.apps.lock);
+ bufdsc = buffer_by_type(adapter, procdsc->type);
+ if (!bufdsc) {
+ pr_debug("uwbrdev_read: Fail...node is null");
+ spin_unlock(&adapter->ctl.apps.lock);
+ return -1;
+ }
+ spin_unlock(&adapter->ctl.apps.lock);
+
+ if (copy_to_user(buf, bufdsc->buffer, bufdsc->length)) {
+ pr_debug("uwbrdev_read: copy_to_user \
+ failed len=%u !!", bufdsc->length);
+ return -EFAULT;
+ }
+
+ spin_lock(&adapter->ctl.apps.lock);
+ rlen = bufdsc->length;
+ list_del(&bufdsc->list);
+ kfree(bufdsc->buffer);
+ kfree(bufdsc);
+ spin_unlock(&adapter->ctl.apps.lock);
+ }
+
+ return rlen;
+}
+
+static const struct file_operations uwbr_fops = {
+ .owner = THIS_MODULE,
+ .open = uwbrdev_open,
+ .release = uwbrdev_release,
+ .unlocked_ioctl = uwbrdev_ioctl,
+ .read = uwbrdev_read,
+};
+
+static int netdev_ethtool_ioctl(struct net_device *dev,
+ void *useraddr)
+{
+ u32 ethcmd;
+ struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
+
+ if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
+ return -EFAULT;
+
+ if (ethcmd != ETHTOOL_GDRVINFO)
+ return -EOPNOTSUPP;
+
+ strncpy(info.driver, "C730USB", sizeof(info.driver) - 1);
+ if (copy_to_user(useraddr, &info, sizeof(info)))
+ return -EFAULT;
+
+ return 0;
+}
+
+static struct net_device_stats *adapter_netdev_stats(struct net_device *dev)
+{
+ return &((struct net_adapter *)netdev_priv(dev))->netstats;
+}
+
+static int adapter_start_xmit(struct sk_buff *skb, struct net_device *net)
+{
+ struct net_adapter *adapter = netdev_priv(net);
+
+ if (!adapter->media_state || adapter->halted) {
+ pr_debug("Driver already halted. Returning Failure...");
+ dev_kfree_skb(skb);
+ adapter->netstats.tx_dropped++;
+ net->trans_start = jiffies;
+ adapter->XmitErr += 1;
+ return 0;
+ }
+
+ hw_send_data(adapter, skb->data, skb->len);
+ dev_kfree_skb(skb);
+
+ if (!adapter->media_state)
+ netif_stop_queue(net);
+
+ return 0;
+}
+
+static int adapter_open(struct net_device *net)
+{
+ struct net_adapter *adapter;
+ int res = 0;
+
+ adapter = netdev_priv(net);
+
+ if (adapter == NULL || adapter->halted) {
+ pr_debug("can't find adapter or halted");
+ return -ENODEV;
+ }
+
+ if (adapter->media_state)
+ netif_wake_queue(net);
+ else
+ netif_stop_queue(net);
+
+ if (netif_msg_ifup(adapter))
+ pr_debug("netif msg if up");
+
+ res = 0;
+
+ pr_debug("adapter driver open success!!!!!!!");
+
+ return res;
+}
+
+static int adapter_close(struct net_device *net)
+{
+ pr_debug("adapter driver close success!!!!!!!");
+
+ netif_stop_queue(net);
+ return 0;
+}
+
+static int adapter_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
+{
+ struct net_adapter *adapter = netdev_priv(net);
+
+ if (adapter->halted) {
+ pr_debug("Driver already halted. Returning Failure...");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ switch (cmd) {
+ case SIOCETHTOOL:
+ return netdev_ethtool_ioctl(net, (void *)rq->ifr_data);
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static void adapter_interrupt(struct sdio_func *func)
+{
+ struct hw_private_packet hdr;
+ struct net_adapter *adapter = sdio_get_drvdata(func);
+ int err = 1;
+ int intrd = 0;
+
+ wake_lock_timeout(&adapter->pdata->g_cfg->wimax_rxtx_lock, 0.2 * HZ);
+
+ if (likely(!adapter->halted)) {
+ /* read interrupt identification register */
+ intrd = sdio_readb(func, SDIO_INT_STATUS_REG, NULL);
+
+ sdio_writeb(func, intrd, SDIO_INT_STATUS_CLR_REG, NULL);
+
+ if (likely(intrd & SDIO_INT_DATA_READY)) {
+ adapter->rx_data_available = true;
+ wake_up_interruptible(&adapter->receive_event);
+ } else if (intrd & SDIO_INT_ERROR) {
+ adapter->netstats.rx_errors++;
+ pr_debug("adapter_sdio_rx_packet intrd ="
+ "SDIO_INT_ERROR occurred!!");
+ }
+ } else {
+ pr_debug("adapter->halted=true in \
+ adapter_interrupt !!!!!!!!!");
+ intrd = sdio_readb(func, SDIO_INT_STATUS_REG, NULL);
+ sdio_writeb(func, intrd, SDIO_INT_STATUS_CLR_REG, NULL);
+
+ /* send stop message */
+ hdr.id0 = 'W';
+ hdr.id1 = 'P';
+ hdr.code = HWCODEHALTEDINDICATION;
+ hdr.value = 0;
+
+ err = sd_send(adapter, (unsigned char *)&hdr,
+ sizeof(struct hw_private_packet));
+ if (err < 0) {
+ pr_debug("adapter->halted=true and send"
+ "HaltIndication to FW err = (%d) !!", err);
+ return;
+ }
+ }
+}
+
+static struct net_device_ops wimax_net_ops = {
+ .ndo_open = adapter_open,
+ .ndo_stop = adapter_close,
+ .ndo_get_stats = adapter_netdev_stats,
+ .ndo_do_ioctl = adapter_ioctl,
+ .ndo_start_xmit = adapter_start_xmit,
+};
+
+static int adapter_probe(struct sdio_func *func,
+ const struct sdio_device_id *id)
+{
+ struct net_adapter *adapter = NULL;
+ struct net_device *net;
+ int err = -ENOMEM;
+ u8 node_id[ETH_ALEN];
+
+ pr_debug("probe");
+
+ net = alloc_etherdev(sizeof(*adapter));
+ if (!net) {
+ pr_debug("adapter_probe: error can't allocate device");
+ goto alloceth_fail;
+ }
+
+ adapter = netdev_priv(net);
+ memset(adapter, 0, sizeof(*adapter));
+
+ adapter->pdata = (struct wimax732_platform_data *) id->driver_data;
+ adapter->pdata->g_cfg->card_removed = false;
+
+ /* Initialize control */
+ control_init(adapter);
+
+ /* initialize hardware */
+ err = wimax_hw_init(adapter);
+ if (err) {
+ pr_debug("adapter_probe: error can't allocate"
+ "receive buffer");
+ goto hwInit_fail;
+ }
+
+ strcpy(net->name, "uwbr%d");
+
+ adapter->func = func;
+ adapter->net = net;
+ net->netdev_ops = &wimax_net_ops;
+ net->watchdog_timeo = ADAPTER_TIMEOUT;
+ net->mtu = WIMAX_MTU_SIZE;
+ adapter->msg_enable = netif_msg_init(msg_level, NETIF_MSG_DRV
+ | NETIF_MSG_PROBE | NETIF_MSG_LINK);
+
+ ether_setup(net);
+ net->flags |= IFF_NOARP;
+
+ adapter->downloading = true;
+
+ sdio_set_drvdata(func, adapter);
+
+ SET_NETDEV_DEV(net, &func->dev);
+ err = register_netdev(net);
+ if (err)
+ goto regdev_fail;
+
+ netif_carrier_off(net);
+ netif_tx_stop_all_queues(net);
+
+ sdio_claim_host(adapter->func);
+ err = sdio_enable_func(adapter->func);
+ if (err < 0) {
+ pr_debug("sdio_enable func error = %d", err);
+ goto sdioen_fail;
+ }
+
+ err = sdio_claim_irq(adapter->func, adapter_interrupt);
+ if (err < 0) {
+ pr_debug("sdio_claim_irq = %d", err);
+ goto sdioirq_fail;
+ }
+ sdio_set_block_size(adapter->func, 512);
+ sdio_release_host(adapter->func);
+
+ adapter->uwibro_dev.minor = UWBRBDEVMINOR;
+ adapter->uwibro_dev.name = "uwibro";
+ adapter->uwibro_dev.fops = &uwbr_fops;
+
+ if (misc_register(&adapter->uwibro_dev) != 0) {
+ pr_debug("adapter_probe: misc_register() failed");
+ goto regchar_fail;
+ }
+
+ /* Dummy value for "ifconfig up" for 2.6.24 */
+ random_ether_addr(node_id);
+ memcpy(net->dev_addr, node_id, sizeof(node_id));
+
+ err = wimax_hw_start(adapter);
+ if (err) {
+ /* Free the resources and stop the driver processing */
+ misc_deregister(&adapter->uwibro_dev);
+ pr_debug("wimax_hw_start failed");
+ goto regchar_fail;
+ }
+
+ return 0;
+
+regchar_fail:
+ adapter->halted = true;
+ wake_up_interruptible(&adapter->send_event);
+ wake_up_interruptible(&adapter->receive_event);
+ sdio_claim_host(adapter->func);
+ sdio_release_irq(adapter->func);
+sdioirq_fail:
+ sdio_disable_func(adapter->func);
+sdioen_fail:
+ sdio_release_host(adapter->func);
+ unregister_netdev(adapter->net);
+regdev_fail:
+ sdio_set_drvdata(func, NULL);
+ wimax_hw_remove(adapter);
+hwInit_fail:
+ free_netdev(net);
+alloceth_fail:
+ adapter->pdata->g_cfg->card_removed = true;
+ adapter->pdata->power(0);
+ return err;
+}
+
+static void adapter_remove(struct sdio_func *func)
+{
+ struct net_adapter *adapter = sdio_get_drvdata(func);
+
+ /* remove adapter from adapters array */
+
+ wake_up_interruptible(&adapter->send_event);
+ wake_up_interruptible(&adapter->receive_event);
+
+ if (!adapter) {
+ pr_debug("unregistering non-bound device?");
+ return;
+ }
+
+ if (adapter->media_state == MEDIA_CONNECTED) {
+ netif_stop_queue(adapter->net);
+ adapter->media_state = MEDIA_DISCONNECTED;
+ }
+
+ if (!adapter->removed)
+ wimax_hw_stop(adapter); /* free hw in and out buffer */
+
+ if (adapter->downloading) {
+ adapter->removed = true;
+ adapter->download_complete = true;
+ wake_up_interruptible(&adapter->download_event);
+ adapter->modem_resp = true;
+ wake_up_interruptible(&adapter->modem_resp_event);
+ }
+
+ if (!completion_done(&adapter->wakeup_event))
+ complete(&adapter->wakeup_event);
+
+ /* remove control process list */
+ control_remove(adapter);
+ /*remove hardware interface */
+ wimax_hw_remove(adapter);
+
+ misc_deregister(&adapter->uwibro_dev);
+ if (adapter->net) {
+ unregister_netdev(adapter->net);
+ free_netdev(adapter->net);
+ }
+ adapter->pdata->g_cfg->card_removed = true;
+
+ return;
+}
+
+static struct sdio_device_id adapter_table[] = {
+ { SDIO_DEVICE(0x98, 0x1) },
+ { } /* Terminating entry */
+};
+
+/* wimax suspend function */
+int wimax_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct wimax732_platform_data *pdata = pdev->dev.platform_data;
+
+ pr_debug("wimax_suspend");
+ if (pdata->g_cfg->card_removed)
+ return 0;
+
+ pdata = pdev->dev.platform_data;
+ if (!mutex_trylock(&pdata->g_cfg->suspend_mutex)) {
+ pr_debug("wimax send processing\n");
+ return -EBUSY;
+ }
+ /* AP active pin LOW */
+ pdata->signal_ap_active(0);
+
+ /*
+ * VI/Idle setting is controlled by framework.
+ * We always set the the pin for Idle
+ */
+ if (pdata->g_cfg->wimax_status == WIMAX_STATE_IDLE
+ || pdata->g_cfg->wimax_status == WIMAX_STATE_NORMAL) {
+ /* set driver status IDLE */
+ pdata->g_cfg->wimax_status = WIMAX_STATE_IDLE;
+ pr_debug("WIMAX IDLE");
+ } else
+ pr_debug("WIMAX STATE NOT CHANGED!!");
+ return 0;
+}
+
+/* wimax resume function */
+int wimax_resume(struct platform_device *pdev)
+{
+ struct wimax732_platform_data *pdata = pdev->dev.platform_data;
+
+ pr_debug("wimax_resume");
+ if (pdata->g_cfg->card_removed)
+ return 0;
+
+ /* AP active pin HIGH */
+ pdata->signal_ap_active(1);
+
+ /* wait wakeup noti for 1 sec otherwise suspend again */
+ wake_lock_timeout(&pdata->g_cfg->wimax_wake_lock, 1 * HZ);
+
+ mutex_unlock(&pdata->g_cfg->suspend_mutex);
+ return 0;
+}
+static int adapter_suspend(struct device *dev)
+{
+ pr_debug("adapter_suspend sdio");
+ return 0;
+}
+
+static int adapter_resume(struct device *dev)
+{
+ pr_debug("adapter_resume sdio");
+ return 0;
+}
+static const struct dev_pm_ops adapter_pm_ops = {
+ .suspend = adapter_suspend,
+ .resume = adapter_resume,
+};
+
+static struct sdio_driver adapter_driver = {
+ .name = "C730SDIO",
+ .probe = adapter_probe,
+ .remove = adapter_remove,
+ .id_table = adapter_table,
+ .drv = {
+ .pm = &adapter_pm_ops,
+ },
+};
+
+static int wimax_probe(struct platform_device *pdev)
+{
+ struct wimax732_platform_data *pdata = pdev->dev.platform_data;
+ int error = 0;
+ int i;
+
+ pr_debug("SDIO driver installing... " WIMAX_DRIVER_VERSION_STRING);
+
+ pdata->swmxctl_dev.minor = SWMXGPIOMINOR;
+ pdata->swmxctl_dev.name = "swmxctl";
+ pdata->swmxctl_dev.fops = &swmx_fops;
+
+ misc_register(&pdata->swmxctl_dev);
+
+ if (error < 0) {
+ pr_debug("misc_register() failed");
+ return error;
+ }
+ mutex_init(&pdata->g_cfg->suspend_mutex);
+
+ for (i = 0; i < ARRAY_SIZE(adapter_table); i++)
+ adapter_table[i].driver_data =
+ (unsigned long) pdev->dev.platform_data;
+
+ /* register SDIO driver */
+ error = sdio_register_driver(&adapter_driver);
+ if (error < 0) {
+ pr_debug("sdio_register_driver() failed");
+ return error;
+ }
+
+ pdata->g_cfg->card_removed = true;
+ pdata->power(0);
+
+ /* initialize wake locks */
+ wake_lock_init(&pdata->g_cfg->wimax_wake_lock,
+ WAKE_LOCK_SUSPEND, "wimax_wakeup");
+ wake_lock_init(&pdata->g_cfg->wimax_rxtx_lock,
+ WAKE_LOCK_SUSPEND, "wimax_rxtx");
+ wake_lock_init(&pdata->g_cfg->wimax_tx_lock,
+ WAKE_LOCK_SUSPEND, "wimax_tx");
+
+ return error;
+}
+
+static int wimax_remove(struct platform_device *pdev)
+{
+ struct wimax732_platform_data *pdata = pdev->dev.platform_data;
+ pr_debug("SDIO driver Uninstall");
+
+ /* destroy wake locks */
+ wake_lock_destroy(&pdata->g_cfg->wimax_wake_lock);
+ wake_lock_destroy(&pdata->g_cfg->wimax_rxtx_lock);
+ wake_lock_destroy(&pdata->g_cfg->wimax_tx_lock);
+
+ sdio_unregister_driver(&adapter_driver);
+ misc_deregister(&pdata->swmxctl_dev);
+ return 0;
+}
+
+static struct platform_driver wimax_driver = {
+ .probe = wimax_probe,
+ .remove = wimax_remove,
+ .suspend = wimax_suspend,
+ .resume = wimax_resume,
+ .driver = {
+ .name = "wimax732_driver",
+ }
+};
+
+static int __init adapter_init_module(void)
+{
+ return platform_driver_register(&wimax_driver);
+}
+
+static void __exit adapter_deinit_module(void)
+{
+ platform_driver_unregister(&wimax_driver);
+}
+
+
+module_init(adapter_init_module);
+module_exit(adapter_deinit_module);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_PARM_DESC(msg_level, "Override default message level");
+MODULE_DEVICE_TABLE(sdio, adapter_table);
+MODULE_VERSION(WIMAX_DRIVER_VERSION_STRING);
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/wimax/cmc7xx/wimax_sdio.h b/drivers/net/wimax/cmc7xx/wimax_sdio.h
new file mode 100755
index 0000000..b9de36a
--- /dev/null
+++ b/drivers/net/wimax/cmc7xx/wimax_sdio.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef _WIMAX_SDIO_H
+#define _WIMAX_SDIO_H
+
+#include "hw_types.h"
+#include "ctl_types.h"
+
+/* WiMAX Constants */
+#define WIMAX_MTU_SIZE 1400
+#define WIMAX_MAX_FRAMESIZE 1500
+#define WIMAX_HEADER_SIZE 14
+#define WIMAX_MAX_TOTAL_SIZE (WIMAX_MAX_FRAMESIZE + WIMAX_HEADER_SIZE)
+/* maximum allocated data size, mtu 1400 so 3 blocks max 1536 */
+#define BUFFER_DATA_SIZE 1600
+#define ADAPTER_TIMEOUT (HZ * 10)
+
+#define MEDIA_DISCONNECTED 0
+#define MEDIA_CONNECTED 1
+
+/* network adapter structure */
+struct net_adapter {
+ struct sdio_func *func;
+ struct net_device *net;
+ struct net_device_stats netstats;
+ struct miscdevice uwibro_dev;
+
+ struct task_struct *tx_task;
+ struct task_struct *rx_task;
+ struct task_struct *mac_task;
+
+ s32 wake_irq;
+
+ u32 msg_enable;
+
+ u32 XmitErr; /* packet send fails */
+
+ struct hardware_info hw;
+ struct ctl_info ctl;
+ struct image_data wimax_image;
+ struct completion wakeup_event;
+ struct wimax732_platform_data *pdata;
+ wait_queue_head_t download_event;
+ wait_queue_head_t modem_resp_event;
+ wait_queue_head_t receive_event;
+ wait_queue_head_t send_event;
+ u8 downloading; /* firmware downloading */
+ u8 download_complete;
+ u8 modem_resp;
+ u8 mac_ready;
+
+ u8 media_state;/* mac completion */
+ u8 prev_wimax_status;
+ u8 rx_data_available;
+ u8 halted; /* device halt pending flag */
+ u8 removed;
+};
+
+#endif /* _WIMAX_SDIO_H */
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 7c2f06e..9130a5a 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -530,7 +530,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)
if (ah->config.serialize_regmode == SER_REG_MODE_AUTO) {
if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI ||
- ((AR_SREV_9160(ah) || AR_SREV_9280(ah)) &&
+ ((AR_SREV_9160(ah) || AR_SREV_9280(ah) || AR_SREV_9287(ah)) &&
!ah->is_pciexpress)) {
ah->config.serialize_regmode =
SER_REG_MODE_ON;
@@ -682,13 +682,25 @@ static void ath9k_hw_init_qos(struct ath_hw *ah)
u32 ar9003_get_pll_sqsum_dvc(struct ath_hw *ah)
{
+ struct ath_common *common = ath9k_hw_common(ah);
+ int i = 0;
+
REG_CLR_BIT(ah, PLL3, PLL3_DO_MEAS_MASK);
udelay(100);
REG_SET_BIT(ah, PLL3, PLL3_DO_MEAS_MASK);
- while ((REG_READ(ah, PLL4) & PLL4_MEAS_DONE) == 0)
+ while ((REG_READ(ah, PLL4) & PLL4_MEAS_DONE) == 0) {
+
udelay(100);
+ if (WARN_ON_ONCE(i >= 100)) {
+ ath_err(common, "PLL4 meaurement not done\n");
+ break;
+ }
+
+ i++;
+ }
+
return (REG_READ(ah, PLL3) & SQSUM_DVC_MASK) >> 3;
}
EXPORT_SYMBOL(ar9003_get_pll_sqsum_dvc);
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index a126a3e..633f962 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -648,6 +648,15 @@ void ath_hw_pll_work(struct work_struct *work)
hw_pll_work.work);
u32 pll_sqsum;
+ /*
+ * ensure that the PLL WAR is executed only
+ * after the STA is associated (or) if the
+ * beaconing had started in interfaces that
+ * uses beacons.
+ */
+ if (!(sc->sc_flags & SC_OP_BEACONS))
+ return;
+
if (AR_SREV_9485(sc->sc_ah)) {
ath9k_ps_wakeup(sc);
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 3b5f9d6..932b3ab 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -1697,7 +1697,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
struct ieee80211_hw *hw = sc->hw;
struct ieee80211_hdr *hdr;
int retval;
- bool decrypt_error = false;
struct ath_rx_status rs;
enum ath9k_rx_qtype qtype;
bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
@@ -1719,6 +1718,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
tsf_lower = tsf & 0xffffffff;
do {
+ bool decrypt_error = false;
/* If handling rx interrupt and flush is in progress => exit */
if ((sc->sc_flags & SC_OP_RXFLUSH) && (flush == 0))
break;
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index 1ab8861..4e8b481 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -3843,6 +3843,8 @@ static void b43legacy_remove(struct ssb_device *dev)
cancel_work_sync(&wldev->restart_work);
B43legacy_WARN_ON(!wl);
+ if (!wldev->fw.ucode)
+ return; /* NULL if fw never loaded */
if (wl->current_dev == wldev)
ieee80211_unregister_hw(wl->hw);
diff --git a/drivers/net/wireless/bcmdhd/include/wlioctl.h b/drivers/net/wireless/bcmdhd/include/wlioctl.h
index 2038e20..122b5a4 100644
--- a/drivers/net/wireless/bcmdhd/include/wlioctl.h
+++ b/drivers/net/wireless/bcmdhd/include/wlioctl.h
@@ -132,6 +132,7 @@ typedef struct wlc_ssid {
uchar SSID[32];
} wlc_ssid_t;
+#define WL_BSS_FLAGS_FROM_BEACON 0x01
#define WL_BSSTYPE_INFRA 1
#define WL_BSSTYPE_INDEP 0
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
index b4f47d1..3b9ca46 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c
+++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
@@ -1587,6 +1587,7 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
/* Arm scan timeout timer */
mod_timer(&wl->scan_timeout, jiffies + msecs_to_jiffies(WL_SCAN_TIMER_INTERVAL_MS));
iscan_req = false;
+ wl->scan_request = request;
if (request) { /* scan bss */
ssids = request->ssids;
if (wl->iscan_on && (!ssids || !ssids->ssid_len || request->n_ssids != 1)) {
@@ -1667,7 +1668,6 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
/* we don't do iscan in ibss */
ssids = this_ssid;
}
- wl->scan_request = request;
wl_set_drv_status(wl, SCANNING, ndev);
if (iscan_req) {
err = wl_do_iscan(wl, request);
@@ -1731,9 +1731,12 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
scan_out:
wl_clr_drv_status(wl, SCANNING, ndev);
- if (timer_pending(&wl->scan_timeout))
- del_timer_sync(&wl->scan_timeout);
- wl->scan_request = NULL;
+ if (wl->scan_request) {
+ if (timer_pending(&wl->scan_timeout))
+ del_timer_sync(&wl->scan_timeout);
+ cfg80211_scan_done(wl->scan_request, true);
+ wl->scan_request = NULL;
+ }
return err;
}
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/wl_cfg80211.h
index dfb0d0d..0c0c1e5 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.h
+++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.h
@@ -475,7 +475,6 @@ typedef struct wl_priv {
struct work_struct work_scan_timeout;
} wl_priv_t;
-
static inline struct wl_bss_info *next_bss(struct wl_scan_results *list, struct wl_bss_info *bss)
{
return bss = bss ?
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 592b0cf..2aed7a0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -878,6 +878,7 @@ static void rs_bt_update_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
if ((priv->bt_traffic_load != priv->last_bt_traffic_load) ||
(priv->bt_full_concurrent != full_concurrent)) {
priv->bt_full_concurrent = full_concurrent;
+ priv->last_bt_traffic_load = priv->bt_traffic_load;
/* Update uCode's rate table. */
tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
index 0bd722c..5c9999d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
@@ -477,7 +477,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
sizeof(struct iwl_keyinfo));
priv->stations[sta_id].sta.key.key_flags =
STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID;
- priv->stations[sta_id].sta.key.key_offset = WEP_INVALID_OFFSET;
+ priv->stations[sta_id].sta.key.key_offset = keyconf->hw_key_idx;
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c
index e5dfdc3..d2358cf 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.c
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c
@@ -267,7 +267,8 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
else
last_seq = priv->rx_seq[tid];
- if (last_seq >= new_node->start_win)
+ if (last_seq != MWIFIEX_DEF_11N_RX_SEQ_NUM &&
+ last_seq >= new_node->start_win)
new_node->start_win = last_seq + 1;
new_node->win_size = win_size;
@@ -612,5 +613,5 @@ void mwifiex_11n_cleanup_reorder_tbl(struct mwifiex_private *priv)
spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr);
- memset(priv->rx_seq, 0, sizeof(priv->rx_seq));
+ mwifiex_reset_11n_rx_seq_num(priv);
}
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.h b/drivers/net/wireless/mwifiex/11n_rxreorder.h
index f3ca8c8..7576c2a 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.h
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.h
@@ -37,6 +37,13 @@
#define ADDBA_RSP_STATUS_ACCEPT 0
+#define MWIFIEX_DEF_11N_RX_SEQ_NUM 0xffff
+
+static inline void mwifiex_reset_11n_rx_seq_num(struct mwifiex_private *priv)
+{
+ memset(priv->rx_seq, 0xff, sizeof(priv->rx_seq));
+}
+
int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *,
u16 seqNum,
u16 tid, u8 *ta,
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c
index 91634da..2cdb41a 100644
--- a/drivers/net/wireless/mwifiex/wmm.c
+++ b/drivers/net/wireless/mwifiex/wmm.c
@@ -406,6 +406,8 @@ mwifiex_wmm_init(struct mwifiex_adapter *adapter)
priv->add_ba_param.tx_win_size = MWIFIEX_AMPDU_DEF_TXWINSIZE;
priv->add_ba_param.rx_win_size = MWIFIEX_AMPDU_DEF_RXWINSIZE;
+ mwifiex_reset_11n_rx_seq_num(priv);
+
atomic_set(&priv->wmm.tx_pkts_queued, 0);
atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID);
}
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c
index a8f3bc7..f44f2f3 100644
--- a/drivers/net/wireless/p54/p54usb.c
+++ b/drivers/net/wireless/p54/p54usb.c
@@ -41,7 +41,7 @@ MODULE_FIRMWARE("isl3887usb");
* whenever you add a new device.
*/
-static struct usb_device_id p54u_table[] __devinitdata = {
+static struct usb_device_id p54u_table[] = {
/* Version 1 devices (pci chip + net2280) */
{USB_DEVICE(0x0411, 0x0050)}, /* Buffalo WLI2-USB2-G54 */
{USB_DEVICE(0x045e, 0x00c2)}, /* Microsoft MN-710 */
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 937f9e8..1493171 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1618,6 +1618,7 @@ static int rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)
{
int retval;
+ u32 reg;
/*
* Allocate eeprom data.
@@ -1631,6 +1632,14 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)
return retval;
/*
+ * Enable rfkill polling by setting GPIO direction of the
+ * rfkill switch GPIO pin correctly.
+ */
+ rt2x00pci_register_read(rt2x00dev, GPIOCSR, &reg);
+ rt2x00_set_field32(&reg, GPIOCSR_BIT8, 1);
+ rt2x00pci_register_write(rt2x00dev, GPIOCSR, reg);
+
+ /*
* Initialize hw specifications.
*/
retval = rt2400pci_probe_hw_mode(rt2x00dev);
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h
index d3a4a68..7564ae9 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.h
+++ b/drivers/net/wireless/rt2x00/rt2400pci.h
@@ -670,6 +670,7 @@
#define GPIOCSR_BIT5 FIELD32(0x00000020)
#define GPIOCSR_BIT6 FIELD32(0x00000040)
#define GPIOCSR_BIT7 FIELD32(0x00000080)
+#define GPIOCSR_BIT8 FIELD32(0x00000100)
/*
* BBPPCSR: BBP Pin control register.
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index d27d7b8..cdd480f 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -1936,6 +1936,7 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
{
int retval;
+ u32 reg;
/*
* Allocate eeprom data.
@@ -1949,6 +1950,14 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
return retval;
/*
+ * Enable rfkill polling by setting GPIO direction of the
+ * rfkill switch GPIO pin correctly.
+ */
+ rt2x00pci_register_read(rt2x00dev, GPIOCSR, &reg);
+ rt2x00_set_field32(&reg, GPIOCSR_DIR0, 1);
+ rt2x00pci_register_write(rt2x00dev, GPIOCSR, reg);
+
+ /*
* Initialize hw specifications.
*/
retval = rt2500pci_probe_hw_mode(rt2x00dev);
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 15237c2..f124a1b 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -283,7 +283,7 @@ static int rt2500usb_rfkill_poll(struct rt2x00_dev *rt2x00dev)
u16 reg;
rt2500usb_register_read(rt2x00dev, MAC_CSR19, &reg);
- return rt2x00_get_field32(reg, MAC_CSR19_BIT7);
+ return rt2x00_get_field16(reg, MAC_CSR19_BIT7);
}
#ifdef CONFIG_RT2X00_LIB_LEDS
@@ -1768,6 +1768,7 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
{
int retval;
+ u16 reg;
/*
* Allocate eeprom data.
@@ -1781,6 +1782,14 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
return retval;
/*
+ * Enable rfkill polling by setting GPIO direction of the
+ * rfkill switch GPIO pin correctly.
+ */
+ rt2500usb_register_read(rt2x00dev, MAC_CSR19, &reg);
+ rt2x00_set_field16(&reg, MAC_CSR19_BIT8, 0);
+ rt2500usb_register_write(rt2x00dev, MAC_CSR19, reg);
+
+ /*
* Initialize hw specifications.
*/
retval = rt2500usb_probe_hw_mode(rt2x00dev);
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h
index b493306..196bd51 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.h
+++ b/drivers/net/wireless/rt2x00/rt2500usb.h
@@ -189,14 +189,15 @@
* MAC_CSR19: GPIO control register.
*/
#define MAC_CSR19 0x0426
-#define MAC_CSR19_BIT0 FIELD32(0x0001)
-#define MAC_CSR19_BIT1 FIELD32(0x0002)
-#define MAC_CSR19_BIT2 FIELD32(0x0004)
-#define MAC_CSR19_BIT3 FIELD32(0x0008)
-#define MAC_CSR19_BIT4 FIELD32(0x0010)
-#define MAC_CSR19_BIT5 FIELD32(0x0020)
-#define MAC_CSR19_BIT6 FIELD32(0x0040)
-#define MAC_CSR19_BIT7 FIELD32(0x0080)
+#define MAC_CSR19_BIT0 FIELD16(0x0001)
+#define MAC_CSR19_BIT1 FIELD16(0x0002)
+#define MAC_CSR19_BIT2 FIELD16(0x0004)
+#define MAC_CSR19_BIT3 FIELD16(0x0008)
+#define MAC_CSR19_BIT4 FIELD16(0x0010)
+#define MAC_CSR19_BIT5 FIELD16(0x0020)
+#define MAC_CSR19_BIT6 FIELD16(0x0040)
+#define MAC_CSR19_BIT7 FIELD16(0x0080)
+#define MAC_CSR19_BIT8 FIELD16(0x0100)
/*
* MAC_CSR20: LED control register.
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index dab7dc1..e947d3a 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -941,6 +941,7 @@ static int rt2800pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
{
int retval;
+ u32 reg;
/*
* Allocate eeprom data.
@@ -954,6 +955,14 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
return retval;
/*
+ * Enable rfkill polling by setting GPIO direction of the
+ * rfkill switch GPIO pin correctly.
+ */
+ rt2x00pci_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);
+ rt2x00_set_field32(&reg, GPIO_CTRL_CFG_GPIOD_BIT2, 1);
+ rt2x00pci_register_write(rt2x00dev, GPIO_CTRL_CFG, reg);
+
+ /*
* Initialize hw specifications.
*/
retval = rt2800_probe_hw_mode(rt2x00dev);
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 0781fb0..9366ef0 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -600,6 +600,7 @@ static int rt2800usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
{
int retval;
+ u32 reg;
/*
* Allocate eeprom data.
@@ -613,6 +614,14 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
return retval;
/*
+ * Enable rfkill polling by setting GPIO direction of the
+ * rfkill switch GPIO pin correctly.
+ */
+ rt2x00usb_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);
+ rt2x00_set_field32(&reg, GPIO_CTRL_CFG_GPIOD_BIT2, 1);
+ rt2x00usb_register_write(rt2x00dev, GPIO_CTRL_CFG, reg);
+
+ /*
* Initialize hw specifications.
*/
retval = rt2800_probe_hw_mode(rt2x00dev);
@@ -829,6 +838,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x0411, 0x015d) },
{ USB_DEVICE(0x0411, 0x016f) },
{ USB_DEVICE(0x0411, 0x01a2) },
+ { USB_DEVICE(0x0411, 0x01ee) },
/* Corega */
{ USB_DEVICE(0x07aa, 0x002f) },
{ USB_DEVICE(0x07aa, 0x003c) },
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 54f0b13..99fa416 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -426,8 +426,8 @@ void rt2x00usb_kick_queue(struct data_queue *queue)
case QID_RX:
if (!rt2x00queue_full(queue))
rt2x00queue_for_each_entry(queue,
- Q_INDEX_DONE,
Q_INDEX,
+ Q_INDEX_DONE,
NULL,
rt2x00usb_kick_rx_entry);
break;
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 9d35ec1..17de24e 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -2254,8 +2254,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
static void rt61pci_wakeup(struct rt2x00_dev *rt2x00dev)
{
- struct ieee80211_conf conf = { .flags = 0 };
- struct rt2x00lib_conf libconf = { .conf = &conf };
+ struct rt2x00lib_conf libconf = { .conf = &rt2x00dev->hw->conf };
rt61pci_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS);
}
@@ -2841,6 +2840,7 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
{
int retval;
+ u32 reg;
/*
* Disable power saving.
@@ -2859,6 +2859,14 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
return retval;
/*
+ * Enable rfkill polling by setting GPIO direction of the
+ * rfkill switch GPIO pin correctly.
+ */
+ rt2x00pci_register_read(rt2x00dev, MAC_CSR13, &reg);
+ rt2x00_set_field32(&reg, MAC_CSR13_BIT13, 1);
+ rt2x00pci_register_write(rt2x00dev, MAC_CSR13, reg);
+
+ /*
* Initialize hw specifications.
*/
retval = rt61pci_probe_hw_mode(rt2x00dev);
diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h
index e3cd6db..8f3da5a 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.h
+++ b/drivers/net/wireless/rt2x00/rt61pci.h
@@ -372,6 +372,7 @@ struct hw_pairwise_ta_entry {
#define MAC_CSR13_BIT10 FIELD32(0x00000400)
#define MAC_CSR13_BIT11 FIELD32(0x00000800)
#define MAC_CSR13_BIT12 FIELD32(0x00001000)
+#define MAC_CSR13_BIT13 FIELD32(0x00002000)
/*
* MAC_CSR14: LED control register.
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index ad20953..1a06231 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -2177,6 +2177,7 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
{
int retval;
+ u32 reg;
/*
* Allocate eeprom data.
@@ -2190,6 +2191,14 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
return retval;
/*
+ * Enable rfkill polling by setting GPIO direction of the
+ * rfkill switch GPIO pin correctly.
+ */
+ rt2x00usb_register_read(rt2x00dev, MAC_CSR13, &reg);
+ rt2x00_set_field32(&reg, MAC_CSR13_BIT15, 0);
+ rt2x00usb_register_write(rt2x00dev, MAC_CSR13, reg);
+
+ /*
* Initialize hw specifications.
*/
retval = rt73usb_probe_hw_mode(rt2x00dev);
diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h
index 9f6b470..df1cc11 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.h
+++ b/drivers/net/wireless/rt2x00/rt73usb.h
@@ -282,6 +282,9 @@ struct hw_pairwise_ta_entry {
#define MAC_CSR13_BIT10 FIELD32(0x00000400)
#define MAC_CSR13_BIT11 FIELD32(0x00000800)
#define MAC_CSR13_BIT12 FIELD32(0x00001000)
+#define MAC_CSR13_BIT13 FIELD32(0x00002000)
+#define MAC_CSR13_BIT14 FIELD32(0x00004000)
+#define MAC_CSR13_BIT15 FIELD32(0x00008000)
/*
* MAC_CSR14: LED control register.
diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/rtl818x/rtl8187/dev.c
index 1e0be14..bf01d21 100644
--- a/drivers/net/wireless/rtl818x/rtl8187/dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8187/dev.c
@@ -43,7 +43,7 @@ MODULE_AUTHOR("Larry Finger <Larry.Finger@lwfinger.net>");
MODULE_DESCRIPTION("RTL8187/RTL8187B USB wireless driver");
MODULE_LICENSE("GPL");
-static struct usb_device_id rtl8187_table[] __devinitdata = {
+static struct usb_device_id rtl8187_table[] = {
/* Asus */
{USB_DEVICE(0x0b05, 0x171d), .driver_info = DEVICE_RTL8187},
/* Belkin */
diff --git a/drivers/net/wireless/rtl818x/rtl8187/leds.c b/drivers/net/wireless/rtl818x/rtl8187/leds.c
index 2e0de2f..c2d5b49 100644
--- a/drivers/net/wireless/rtl818x/rtl8187/leds.c
+++ b/drivers/net/wireless/rtl818x/rtl8187/leds.c
@@ -117,7 +117,7 @@ static void rtl8187_led_brightness_set(struct led_classdev *led_dev,
radio_on = true;
} else if (radio_on) {
radio_on = false;
- cancel_delayed_work_sync(&priv->led_on);
+ cancel_delayed_work(&priv->led_on);
ieee80211_queue_delayed_work(hw, &priv->led_off, 0);
}
} else if (radio_on) {
diff --git a/drivers/net/wireless/wl1251/sdio.c b/drivers/net/wireless/wl1251/sdio.c
index 85a7101..4cf5c2e 100644
--- a/drivers/net/wireless/wl1251/sdio.c
+++ b/drivers/net/wireless/wl1251/sdio.c
@@ -259,6 +259,7 @@ static int wl1251_sdio_probe(struct sdio_func *func,
}
if (wl->irq) {
+ irq_set_status_flags(wl->irq, IRQ_NOAUTOEN);
ret = request_irq(wl->irq, wl1251_line_irq, 0, "wl1251", wl);
if (ret < 0) {
wl1251_error("request_irq() failed: %d", ret);
@@ -266,7 +267,6 @@ static int wl1251_sdio_probe(struct sdio_func *func,
}
irq_set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
- disable_irq(wl->irq);
wl1251_sdio_ops.enable_irq = wl1251_enable_line_irq;
wl1251_sdio_ops.disable_irq = wl1251_disable_line_irq;
diff --git a/drivers/net/wireless/wl1251/spi.c b/drivers/net/wireless/wl1251/spi.c
index af6448c..49f3651 100644
--- a/drivers/net/wireless/wl1251/spi.c
+++ b/drivers/net/wireless/wl1251/spi.c
@@ -280,6 +280,7 @@ static int __devinit wl1251_spi_probe(struct spi_device *spi)
wl->use_eeprom = pdata->use_eeprom;
+ irq_set_status_flags(wl->irq, IRQ_NOAUTOEN);
ret = request_irq(wl->irq, wl1251_irq, 0, DRIVER_NAME, wl);
if (ret < 0) {
wl1251_error("request_irq() failed: %d", ret);
@@ -288,8 +289,6 @@ static int __devinit wl1251_spi_probe(struct spi_device *spi)
irq_set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
- disable_irq(wl->irq);
-
ret = wl1251_init_ieee80211(wl);
if (ret)
goto out_irq;
diff --git a/drivers/oprofile/oprofile_perf.c b/drivers/oprofile/oprofile_perf.c
index 9046f7b..137406c 100644
--- a/drivers/oprofile/oprofile_perf.c
+++ b/drivers/oprofile/oprofile_perf.c
@@ -25,7 +25,7 @@ static int oprofile_perf_enabled;
static DEFINE_MUTEX(oprofile_perf_mutex);
static struct op_counter_config *counter_config;
-static struct perf_event **perf_events[nr_cpumask_bits];
+static struct perf_event **perf_events[NR_CPUS];
static int num_counters;
/*
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index a70fa89..7bd3694 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -131,7 +131,12 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
if (!acpi_pci_check_ejectable(pbus, handle) && !is_dock_device(handle))
return AE_OK;
- acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
+ status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
+ if (ACPI_FAILURE(status)) {
+ warn("can't evaluate _ADR (%#x)\n", status);
+ return AE_OK;
+ }
+
device = (adr >> 16) & 0xffff;
function = adr & 0xffff;
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 46767c5..5d5bdf7 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -726,6 +726,18 @@ static int pci_pm_suspend_noirq(struct device *dev)
pci_pm_set_unknown_state(pci_dev);
+ /*
+ * Some BIOSes from ASUS have a bug: If a USB EHCI host controller's
+ * PCI COMMAND register isn't 0, the BIOS assumes that the controller
+ * hasn't been quiesced and tries to turn it off. If the controller
+ * is already in D3, this can hang or cause memory corruption.
+ *
+ * Since the value of the COMMAND register doesn't matter once the
+ * device has been suspended, we can safely set it to 0 here.
+ */
+ if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI)
+ pci_write_config_word(pci_dev, PCI_COMMAND, 0);
+
return 0;
}
@@ -924,6 +936,13 @@ static int pci_pm_poweroff_noirq(struct device *dev)
if (!pci_dev->state_saved && !pci_is_bridge(pci_dev))
pci_prepare_to_sleep(pci_dev);
+ /*
+ * The reason for doing this here is the same as for the analogous code
+ * in pci_pm_suspend_noirq().
+ */
+ if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI)
+ pci_write_config_word(pci_dev, PCI_COMMAND, 0);
+
return 0;
}
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 5b3771a..0d5d0bf 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -664,8 +664,10 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
/* Check if setup is sensible at all */
if (!pass &&
- (primary != bus->number || secondary <= bus->number)) {
- dev_dbg(&dev->dev, "bus configuration invalid, reconfiguring\n");
+ (primary != bus->number || secondary <= bus->number ||
+ secondary > subordinate)) {
+ dev_info(&dev->dev, "bridge configuration invalid ([bus %02x-%02x]), reconfiguring\n",
+ secondary, subordinate);
broken = 1;
}
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 9995842..fb0d344 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -543,6 +543,20 @@ static resource_size_t calculate_memsize(resource_size_t size,
return size;
}
+static resource_size_t get_res_add_size(struct resource_list_x *add_head,
+ struct resource *res)
+{
+ struct resource_list_x *list;
+
+ /* check if it is in add_head list */
+ for (list = add_head->next; list && list->res != res;
+ list = list->next);
+ if (list)
+ return list->add_size;
+
+ return 0;
+}
+
/**
* pbus_size_io() - size the io window of a given bus
*
@@ -562,6 +576,7 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
struct pci_dev *dev;
struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO);
unsigned long size = 0, size0 = 0, size1 = 0;
+ resource_size_t children_add_size = 0;
if (!b_res)
return;
@@ -582,10 +597,15 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
size += r_size;
else
size1 += r_size;
+
+ if (add_head)
+ children_add_size += get_res_add_size(add_head, r);
}
}
size0 = calculate_iosize(size, min_size, size1,
resource_size(b_res), 4096);
+ if (children_add_size > add_size)
+ add_size = children_add_size;
size1 = (!add_head || (add_head && !add_size)) ? size0 :
calculate_iosize(size, min_size+add_size, size1,
resource_size(b_res), 4096);
@@ -627,6 +647,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
int order, max_order;
struct resource *b_res = find_free_bus_resource(bus, type);
unsigned int mem64_mask = 0;
+ resource_size_t children_add_size = 0;
if (!b_res)
return 0;
@@ -668,6 +689,9 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
if (order > max_order)
max_order = order;
mem64_mask &= r->flags & IORESOURCE_MEM_64;
+
+ if (add_head)
+ children_add_size += get_res_add_size(add_head, r);
}
}
align = 0;
@@ -684,6 +708,8 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
align += aligns[order];
}
size0 = calculate_memsize(size, min_size, 0, resource_size(b_res), min_align);
+ if (children_add_size > add_size)
+ add_size = children_add_size;
size1 = (!add_head || (add_head && !add_size)) ? size0 :
calculate_memsize(size, min_size+add_size, 0,
resource_size(b_res), min_align);
diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c
index 81af2b3..097fa00 100644
--- a/drivers/pcmcia/pxa2xx_sharpsl.c
+++ b/drivers/pcmcia/pxa2xx_sharpsl.c
@@ -222,7 +222,7 @@ static void sharpsl_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
sharpsl_pcmcia_init_reset(skt);
}
-static struct pcmcia_low_level sharpsl_pcmcia_ops __initdata = {
+static struct pcmcia_low_level sharpsl_pcmcia_ops = {
.owner = THIS_MODULE,
.hw_init = sharpsl_pcmcia_hw_init,
.hw_shutdown = sharpsl_pcmcia_hw_shutdown,
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index d65df92..26f7f01 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -646,9 +646,9 @@ static ssize_t show_infos(struct device *dev,
* The significance of others is yet to be found.
* If we don't find the method, we assume the device are present.
*/
- rv = acpi_evaluate_integer(asus->handle, "HRWS", NULL, &temp);
+ rv = acpi_evaluate_integer(asus->handle, "HWRS", NULL, &temp);
if (!ACPI_FAILURE(rv))
- len += sprintf(page + len, "HRWS value : %#x\n",
+ len += sprintf(page + len, "HWRS value : %#x\n",
(uint) temp);
/*
* Another value for userspace: the ASYM method returns 0x02 for
@@ -1340,9 +1340,9 @@ static int asus_laptop_get_info(struct asus_laptop *asus)
* The significance of others is yet to be found.
*/
status =
- acpi_evaluate_integer(asus->handle, "HRWS", NULL, &hwrs_result);
+ acpi_evaluate_integer(asus->handle, "HWRS", NULL, &hwrs_result);
if (!ACPI_FAILURE(status))
- pr_notice(" HRWS returned %x", (int)hwrs_result);
+ pr_notice(" HWRS returned %x", (int)hwrs_result);
if (!acpi_check_handle(asus->handle, METHOD_WL_STATUS, NULL))
asus->have_rsts = true;
diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c
index 0580d99..9827fe9 100644
--- a/drivers/platform/x86/asus-nb-wmi.c
+++ b/drivers/platform/x86/asus-nb-wmi.c
@@ -68,6 +68,10 @@ static const struct key_entry asus_nb_wmi_keymap[] = {
{ KE_KEY, 0x8A, { KEY_PROG1 } },
{ KE_KEY, 0x95, { KEY_MEDIA } },
{ KE_KEY, 0x99, { KEY_PHONE } },
+ { KE_KEY, 0xA0, { KEY_SWITCHVIDEOMODE } }, /* SDSP HDMI only */
+ { KE_KEY, 0xA1, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + HDMI */
+ { KE_KEY, 0xA2, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + HDMI */
+ { KE_KEY, 0xA3, { KEY_SWITCHVIDEOMODE } }, /* SDSP TV + HDMI */
{ KE_KEY, 0xb5, { KEY_CALC } },
{ KE_KEY, 0xc4, { KEY_KBDILLUMUP } },
{ KE_KEY, 0xc5, { KEY_KBDILLUMDOWN } },
diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c
index 5ffe7c3..e66bbba 100644
--- a/drivers/platform/x86/intel_ips.c
+++ b/drivers/platform/x86/intel_ips.c
@@ -72,6 +72,7 @@
#include <linux/string.h>
#include <linux/tick.h>
#include <linux/timer.h>
+#include <linux/dmi.h>
#include <drm/i915_drm.h>
#include <asm/msr.h>
#include <asm/processor.h>
@@ -1505,6 +1506,24 @@ static DEFINE_PCI_DEVICE_TABLE(ips_id_table) = {
MODULE_DEVICE_TABLE(pci, ips_id_table);
+static int ips_blacklist_callback(const struct dmi_system_id *id)
+{
+ pr_info("Blacklisted intel_ips for %s\n", id->ident);
+ return 1;
+}
+
+static const struct dmi_system_id ips_blacklist[] = {
+ {
+ .callback = ips_blacklist_callback,
+ .ident = "HP ProBook",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP ProBook"),
+ },
+ },
+ { } /* terminating entry */
+};
+
static int ips_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
u64 platform_info;
@@ -1514,6 +1533,9 @@ static int ips_probe(struct pci_dev *dev, const struct pci_device_id *id)
u16 htshi, trc, trc_required_mask;
u8 tse;
+ if (dmi_check_system(ips_blacklist))
+ return -ENODEV;
+
ips = kzalloc(sizeof(struct ips_driver), GFP_KERNEL);
if (!ips)
return -ENOMEM;
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index bbd182e..35dae41 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -127,7 +127,7 @@ MODULE_PARM_DESC(minor,
"default is -1 (automatic)");
#endif
-static int kbd_backlight; /* = 1 */
+static int kbd_backlight = 1;
module_param(kbd_backlight, int, 0444);
MODULE_PARM_DESC(kbd_backlight,
"set this to 0 to disable keyboard backlight, "
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index e57b50b..e00bf5a 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -173,12 +173,24 @@ config BATTERY_Z2
help
Say Y to include support for the battery on the Zipit Z2.
+config BATTERY_S3C
+ tristate "S3C fake battery driver"
+ depends on ARCH_S5PV210
+ help
+ Say Y to enable support for batteries with s5pc110 chip.
+
config BATTERY_S3C_ADC
tristate "Battery driver for Samsung ADC based monitoring"
depends on S3C_ADC
help
Say Y here to enable support for iPAQ h1930/h1940/rx1950 battery
+config BATTERY_S5PC110
+ tristate "Battery driver for CRESPO(S5PC110)"
+ depends on ARCH_S5PV210
+ help
+ Say Y to enable support for batteries with s5pc110 chip.
+
config CHARGER_PCF50633
tristate "NXP PCF50633 MBC"
depends on MFD_PCF50633
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 009a90f..327d490 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -28,7 +28,9 @@ obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o
obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o
obj-$(CONFIG_BATTERY_MAX17042) += max17042_battery.o
obj-$(CONFIG_BATTERY_Z2) += z2_battery.o
+obj-$(CONFIG_BATTERY_S3C) += s3c_fake_battery.o
obj-$(CONFIG_BATTERY_S3C_ADC) += s3c_adc_battery.o
+obj-$(CONFIG_BATTERY_S5PC110) += s5pc110_battery.o
obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o
obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o
obj-$(CONFIG_BATTERY_INTEL_MID) += intel_mid_battery.o
diff --git a/drivers/power/fuel_gauge.c b/drivers/power/fuel_gauge.c
new file mode 100644
index 0000000..1ca2531
--- /dev/null
+++ b/drivers/power/fuel_gauge.c
@@ -0,0 +1,204 @@
+/* Register address */
+#define VCELL_REG 0x02
+#define SOCREP_REG 0x04
+#define MISCCFG_REG 0x06
+#define RCOMP_REG 0x0C
+#define CMD_REG 0xFE
+
+#include <linux/jiffies.h>
+#include <linux/slab.h>
+
+int fuel_guage_init;
+EXPORT_SYMBOL(fuel_guage_init);
+
+static struct i2c_driver fg_i2c_driver;
+static struct i2c_client *fg_i2c_client;
+
+struct fg_state{
+ struct i2c_client *client;
+};
+
+static int fg_i2c_read(struct i2c_client *client, u8 reg, u8 *data, u8 length)
+{
+ int value = i2c_smbus_read_word_data(client, reg);
+
+ if (value < 0) {
+ pr_err("%s: Failed to fg_i2c_read\n", __func__);
+ return -1;
+ }
+
+ *data = value & 0x00ff;
+ *(data+1) = (value & 0xff00) >> 8;
+
+ return 0;
+}
+
+static int fg_i2c_write(struct i2c_client *client, u8 reg, u8 *data, u8 length)
+{
+ u16 value = (*(data+1) << 8) | (*(data)) ;
+
+ return i2c_smbus_write_word_data(client, reg, value);
+}
+
+int fg_read_vcell(void)
+{
+ struct i2c_client *client = fg_i2c_client;
+ u8 data[2];
+ u32 vcell = 0;
+
+ if (!fuel_guage_init) {
+ pr_err("%s : fuel guage IC is not initialized!!\n", __func__);
+ return -1;
+ }
+
+ if (fg_i2c_read(client, VCELL_REG, data, 2) < 0) {
+ pr_err("%s: Failed to read VCELL\n", __func__);
+ return -1;
+ }
+
+ vcell = ((((data[0] << 4) & 0xFF0) | ((data[1] >> 4) & 0xF)) * 125)/100;
+
+ return vcell;
+}
+
+int fg_read_soc(void)
+{
+ struct i2c_client *client = fg_i2c_client;
+ u8 data[2];
+ u32 soc = 0;
+ u32 temp = 0;
+ u32 temp_soc = 0;
+
+ if (!fuel_guage_init) {
+ pr_err("%s : fuel guage IC is not initialized!!\n", __func__);
+ return -1;
+ }
+
+ if (fg_i2c_read(client, SOCREP_REG, data, 2) < 0) {
+ pr_err("%s: Failed to read SOCREP\n", __func__);
+ return -1;
+ }
+
+ temp = data[0] * 100 + ((data[1] * 100) / 256);
+
+ if (temp >= 100)
+ temp_soc = temp;
+ else {
+ if (temp >= 70)
+ temp_soc = 100;
+ else
+ temp_soc = 0;
+ }
+
+ /* rounding off and Changing to percentage */
+ soc = temp_soc / 100;
+
+ if (temp_soc % 100 >= 50)
+ soc += 1;
+
+ if (soc >= 26)
+ soc += 4;
+ else
+ soc = (30 * temp_soc) / 26 / 100;
+
+ if (soc >= 100)
+ soc = 100;
+
+ return soc;
+}
+
+int fg_reset_soc(void)
+{
+ struct i2c_client *client = fg_i2c_client;
+ u8 data[2];
+ s32 ret = 0;
+
+ if (!fuel_guage_init) {
+ pr_err("%s : fuel guage IC is not initialized!!\n", __func__);
+ return -1;
+ }
+
+ /* Quick-start */
+ data[0] = 0x40;
+ data[1] = 0x00;
+
+ if (fg_i2c_write(client, MISCCFG_REG, data, 2) < 0) {
+ pr_err("%s: Failed to write MiscCFG\n", __func__);
+ return -1;
+ }
+
+ msleep(500);
+
+ return ret;
+}
+
+void fuel_gauge_rcomp(void)
+{
+ struct i2c_client *client = fg_i2c_client;
+ u8 rst_cmd[2];
+
+ if (!fuel_guage_init) {
+ pr_err("%s : fuel guage IC is not initialized!!\n", __func__);
+ return ;
+ }
+
+ rst_cmd[0] = 0xB0;
+ rst_cmd[1] = 0x00;
+
+ if (fg_i2c_write(client, RCOMP_REG, rst_cmd, 2) < 0)
+ pr_err("%s: failed fuel_gauge_rcomp\n", __func__);
+}
+
+static int fg_i2c_remove(struct i2c_client *client)
+{
+ struct fg_state *fg = i2c_get_clientdata(client);
+
+ kfree(fg);
+ return 0;
+}
+
+static int fg_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct fg_state *fg;
+
+ fuel_guage_init = 0;
+ fg_i2c_client = NULL;
+
+ fg = kzalloc(sizeof(struct fg_state), GFP_KERNEL);
+ if (fg == NULL) {
+ pr_err("failed to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ fg->client = client;
+ i2c_set_clientdata(client, fg);
+
+ /* rest of the initialisation goes here. */
+
+ pr_info("Fuel guage attach success!!!\n");
+
+ fg_i2c_client = client;
+
+ fuel_guage_init = 1;
+
+ return 0;
+}
+
+
+static const struct i2c_device_id fg_device_id[] = {
+ {"max1704x", 0},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, fg_device_id);
+
+
+static struct i2c_driver fg_i2c_driver = {
+ .driver = {
+ .name = "max1704x",
+ .owner = THIS_MODULE,
+ },
+ .probe = fg_i2c_probe,
+ .remove = fg_i2c_remove,
+ .id_table = fg_device_id,
+};
diff --git a/drivers/power/max17040_battery.c b/drivers/power/max17040_battery.c
index 2f2f9a6..aedb539 100644..100755
--- a/drivers/power/max17040_battery.c
+++ b/drivers/power/max17040_battery.c
@@ -20,6 +20,7 @@
#include <linux/power_supply.h>
#include <linux/max17040_battery.h>
#include <linux/slab.h>
+#include <linux/time.h>
#define MAX17040_VCELL_MSB 0x02
#define MAX17040_VCELL_LSB 0x03
@@ -39,9 +40,9 @@
struct max17040_chip {
struct i2c_client *client;
- struct delayed_work work;
struct power_supply battery;
struct max17040_platform_data *pdata;
+ struct timespec next_update_time;
/* State Of Connect */
int online;
@@ -53,12 +54,20 @@ struct max17040_chip {
int status;
};
+static void max17040_update_values(struct max17040_chip *chip);
+
static int max17040_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
{
struct max17040_chip *chip = container_of(psy,
struct max17040_chip, battery);
+ struct timespec now;
+
+ ktime_get_ts(&now);
+ monotonic_to_bootbased(&now);
+ if (timespec_compare(&now, &chip->next_update_time) >= 0)
+ max17040_update_values(chip);
switch (psp) {
case POWER_SUPPLY_PROP_STATUS:
@@ -68,7 +77,7 @@ static int max17040_get_property(struct power_supply *psy,
val->intval = chip->online;
break;
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
- val->intval = chip->vcell;
+ val->intval = chip->vcell * 1250;
break;
case POWER_SUPPLY_PROP_CAPACITY:
val->intval = chip->soc;
@@ -103,12 +112,6 @@ static int max17040_read_reg(struct i2c_client *client, int reg)
return ret;
}
-static void max17040_reset(struct i2c_client *client)
-{
- max17040_write_reg(client, MAX17040_CMD_MSB, 0x54);
- max17040_write_reg(client, MAX17040_CMD_LSB, 0x00);
-}
-
static void max17040_get_vcell(struct i2c_client *client)
{
struct max17040_chip *chip = i2c_get_clientdata(client);
@@ -126,11 +129,39 @@ static void max17040_get_soc(struct i2c_client *client)
struct max17040_chip *chip = i2c_get_clientdata(client);
u8 msb;
u8 lsb;
+ u32 soc = 0;
+ u32 temp = 0;
+ u32 temp_soc = 0;
msb = max17040_read_reg(client, MAX17040_SOC_MSB);
lsb = max17040_read_reg(client, MAX17040_SOC_LSB);
- chip->soc = msb;
+ temp = msb * 100 + ((lsb * 100) / 256);
+
+ if (temp >= 100)
+ temp_soc = temp;
+ else {
+ if (temp >= 70)
+ temp_soc = 100;
+ else
+ temp_soc = 0;
+ }
+
+ /* rounding off and Changing to percentage */
+ soc = temp_soc / 100;
+
+ if (temp_soc % 100 >= 50)
+ soc += 1;
+
+ if (soc >= 26)
+ soc += 4;
+ else
+ soc = (30 * temp_soc) / 26 / 100;
+
+ if (soc >= 100)
+ soc = 100;
+
+ chip->soc = soc;
}
static void max17040_get_version(struct i2c_client *client)
@@ -148,7 +179,7 @@ static void max17040_get_online(struct i2c_client *client)
{
struct max17040_chip *chip = i2c_get_clientdata(client);
- if (chip->pdata->battery_online)
+ if (chip->pdata && chip->pdata->battery_online)
chip->online = chip->pdata->battery_online();
else
chip->online = 1;
@@ -158,7 +189,8 @@ static void max17040_get_status(struct i2c_client *client)
{
struct max17040_chip *chip = i2c_get_clientdata(client);
- if (!chip->pdata->charger_online || !chip->pdata->charger_enable) {
+ if (!chip->pdata || !chip->pdata->charger_online ||
+ !chip->pdata->charger_enable) {
chip->status = POWER_SUPPLY_STATUS_UNKNOWN;
return;
}
@@ -176,18 +208,17 @@ static void max17040_get_status(struct i2c_client *client)
chip->status = POWER_SUPPLY_STATUS_FULL;
}
-static void max17040_work(struct work_struct *work)
+static void max17040_update_values(struct max17040_chip *chip)
{
- struct max17040_chip *chip;
-
- chip = container_of(work, struct max17040_chip, work.work);
-
max17040_get_vcell(chip->client);
max17040_get_soc(chip->client);
max17040_get_online(chip->client);
max17040_get_status(chip->client);
- schedule_delayed_work(&chip->work, MAX17040_DELAY);
+ /* next update must be at least 1 second later */
+ ktime_get_ts(&chip->next_update_time);
+ monotonic_to_bootbased(&chip->next_update_time);
+ chip->next_update_time.tv_sec++;
}
static enum power_supply_property max17040_battery_props[] = {
@@ -222,18 +253,23 @@ static int __devinit max17040_probe(struct i2c_client *client,
chip->battery.properties = max17040_battery_props;
chip->battery.num_properties = ARRAY_SIZE(max17040_battery_props);
- ret = power_supply_register(&client->dev, &chip->battery);
+ max17040_update_values(chip);
+
+ if (chip->pdata && chip->pdata->power_supply_register)
+ ret = chip->pdata->power_supply_register(&client->dev, &chip->battery);
+ else
+ ret = power_supply_register(&client->dev, &chip->battery);
if (ret) {
dev_err(&client->dev, "failed: power supply register\n");
kfree(chip);
return ret;
}
- max17040_reset(client);
max17040_get_version(client);
- INIT_DELAYED_WORK_DEFERRABLE(&chip->work, max17040_work);
- schedule_delayed_work(&chip->work, MAX17040_DELAY);
+ if (chip->pdata)
+ i2c_smbus_write_word_data(client, MAX17040_RCOMP_MSB,
+ swab16(chip->pdata->rcomp_value));
return 0;
}
@@ -242,38 +278,14 @@ static int __devexit max17040_remove(struct i2c_client *client)
{
struct max17040_chip *chip = i2c_get_clientdata(client);
- power_supply_unregister(&chip->battery);
- cancel_delayed_work(&chip->work);
+ if (chip->pdata && chip->pdata->power_supply_unregister)
+ chip->pdata->power_supply_unregister(&chip->battery);
+ else
+ power_supply_unregister(&chip->battery);
kfree(chip);
return 0;
}
-#ifdef CONFIG_PM
-
-static int max17040_suspend(struct i2c_client *client,
- pm_message_t state)
-{
- struct max17040_chip *chip = i2c_get_clientdata(client);
-
- cancel_delayed_work(&chip->work);
- return 0;
-}
-
-static int max17040_resume(struct i2c_client *client)
-{
- struct max17040_chip *chip = i2c_get_clientdata(client);
-
- schedule_delayed_work(&chip->work, MAX17040_DELAY);
- return 0;
-}
-
-#else
-
-#define max17040_suspend NULL
-#define max17040_resume NULL
-
-#endif /* CONFIG_PM */
-
static const struct i2c_device_id max17040_id[] = {
{ "max17040", 0 },
{ }
@@ -286,8 +298,6 @@ static struct i2c_driver max17040_i2c_driver = {
},
.probe = max17040_probe,
.remove = __devexit_p(max17040_remove),
- .suspend = max17040_suspend,
- .resume = max17040_resume,
.id_table = max17040_id,
};
diff --git a/drivers/power/s3c_fake_battery.c b/drivers/power/s3c_fake_battery.c
new file mode 100644
index 0000000..437702c
--- /dev/null
+++ b/drivers/power/s3c_fake_battery.c
@@ -0,0 +1,576 @@
+/*
+ * linux/drivers/power/s3c_fake_battery.c
+ *
+ * Battery measurement code for S3C platform.
+ *
+ * based on palmtx_battery.c
+ *
+ * Copyright (C) 2009 Samsung Electronics.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/power_supply.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/timer.h>
+#include <linux/jiffies.h>
+#include <linux/irq.h>
+#include <linux/wakelock.h>
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <plat/gpio-cfg.h>
+
+#define DRIVER_NAME "sec-fake-battery"
+
+static struct wake_lock vbus_wake_lock;
+
+/* Prototypes */
+extern int s3c_adc_get_adc_data(int channel);
+
+static ssize_t s3c_bat_show_property(struct device *dev,
+ struct device_attribute *attr,
+ char *buf);
+static ssize_t s3c_bat_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
+
+#define FAKE_BAT_LEVEL 80
+
+static struct device *dev;
+static int s3c_battery_initial;
+static int force_update;
+
+static char *status_text[] = {
+ [POWER_SUPPLY_STATUS_UNKNOWN] = "Unknown",
+ [POWER_SUPPLY_STATUS_CHARGING] = "Charging",
+ [POWER_SUPPLY_STATUS_DISCHARGING] = "Discharging",
+ [POWER_SUPPLY_STATUS_NOT_CHARGING] = "Not Charging",
+ [POWER_SUPPLY_STATUS_FULL] = "Full",
+};
+
+typedef enum {
+ CHARGER_BATTERY = 0,
+ CHARGER_USB,
+ CHARGER_AC,
+ CHARGER_DISCHARGE
+} charger_type_t;
+
+struct battery_info {
+ u32 batt_id; /* Battery ID from ADC */
+ u32 batt_vol; /* Battery voltage from ADC */
+ u32 batt_vol_adc; /* Battery ADC value */
+ u32 batt_vol_adc_cal; /* Battery ADC value (calibrated)*/
+ u32 batt_temp; /* Battery Temperature (C) from ADC */
+ u32 batt_temp_adc; /* Battery Temperature ADC value */
+ u32 batt_temp_adc_cal; /* Battery Temperature ADC value (calibrated) */
+ u32 batt_current; /* Battery current from ADC */
+ u32 level; /* formula */
+ u32 charging_source; /* 0: no cable, 1:usb, 2:AC */
+ u32 charging_enabled; /* 0: Disable, 1: Enable */
+ u32 batt_health; /* Battery Health (Authority) */
+ u32 batt_is_full; /* 0 : Not full 1: Full */
+};
+
+/* lock to protect the battery info */
+static DEFINE_MUTEX(work_lock);
+
+struct s3c_battery_info {
+ int present;
+ int polling;
+ unsigned long polling_interval;
+
+ struct battery_info bat_info;
+};
+static struct s3c_battery_info s3c_bat_info;
+
+static int s3c_get_bat_level(struct power_supply *bat_ps)
+{
+ return FAKE_BAT_LEVEL;
+}
+
+static int s3c_get_bat_vol(struct power_supply *bat_ps)
+{
+ int bat_vol = 0;
+
+ return bat_vol;
+}
+
+static u32 s3c_get_bat_health(void)
+{
+ return s3c_bat_info.bat_info.batt_health;
+}
+
+static int s3c_get_bat_temp(struct power_supply *bat_ps)
+{
+ int temp = 0;
+
+ return temp;
+}
+
+static int s3c_bat_get_charging_status(void)
+{
+ charger_type_t charger = CHARGER_BATTERY;
+ int ret = 0;
+
+ charger = s3c_bat_info.bat_info.charging_source;
+
+ switch (charger) {
+ case CHARGER_BATTERY:
+ ret = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ break;
+ case CHARGER_USB:
+ case CHARGER_AC:
+ if (s3c_bat_info.bat_info.level == 100
+ && s3c_bat_info.bat_info.batt_is_full) {
+ ret = POWER_SUPPLY_STATUS_FULL;
+ } else {
+ ret = POWER_SUPPLY_STATUS_CHARGING;
+ }
+ break;
+ case CHARGER_DISCHARGE:
+ ret = POWER_SUPPLY_STATUS_DISCHARGING;
+ break;
+ default:
+ ret = POWER_SUPPLY_STATUS_UNKNOWN;
+ }
+ dev_dbg(dev, "%s : %s\n", __func__, status_text[ret]);
+
+ return ret;
+}
+
+static int s3c_bat_get_property(struct power_supply *bat_ps,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ dev_dbg(bat_ps->dev, "%s : psp = %d\n", __func__, psp);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ val->intval = s3c_bat_get_charging_status();
+ break;
+ case POWER_SUPPLY_PROP_HEALTH:
+ val->intval = s3c_get_bat_health();
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+ val->intval = s3c_bat_info.present;
+ break;
+ case POWER_SUPPLY_PROP_TECHNOLOGY:
+ val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY:
+ val->intval = s3c_bat_info.bat_info.level;
+ dev_dbg(dev, "%s : level = %d\n", __func__,
+ val->intval);
+ break;
+ case POWER_SUPPLY_PROP_TEMP:
+ val->intval = s3c_bat_info.bat_info.batt_temp;
+ dev_dbg(bat_ps->dev, "%s : temp = %d\n", __func__,
+ val->intval);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int s3c_power_get_property(struct power_supply *bat_ps,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ charger_type_t charger;
+
+ dev_dbg(bat_ps->dev, "%s : psp = %d\n", __func__, psp);
+
+ charger = s3c_bat_info.bat_info.charging_source;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ if (bat_ps->type == POWER_SUPPLY_TYPE_MAINS)
+ val->intval = (charger == CHARGER_AC ? 1 : 0);
+ else if (bat_ps->type == POWER_SUPPLY_TYPE_USB)
+ val->intval = (charger == CHARGER_USB ? 1 : 0);
+ else
+ val->intval = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+#define SEC_BATTERY_ATTR(_name) \
+{ \
+ .attr = { .name = #_name, .mode = S_IRUGO | S_IWUGO, .owner = THIS_MODULE }, \
+ .show = s3c_bat_show_property, \
+ .store = s3c_bat_store, \
+}
+
+static struct device_attribute s3c_battery_attrs[] = {
+ SEC_BATTERY_ATTR(batt_vol),
+ SEC_BATTERY_ATTR(batt_vol_adc),
+ SEC_BATTERY_ATTR(batt_vol_adc_cal),
+ SEC_BATTERY_ATTR(batt_temp),
+ SEC_BATTERY_ATTR(batt_temp_adc),
+ SEC_BATTERY_ATTR(batt_temp_adc_cal),
+};
+
+enum {
+ BATT_VOL = 0,
+ BATT_VOL_ADC,
+ BATT_VOL_ADC_CAL,
+ BATT_TEMP,
+ BATT_TEMP_ADC,
+ BATT_TEMP_ADC_CAL,
+};
+
+static int s3c_bat_create_attrs(struct device * dev)
+{
+ int i, rc;
+
+ for (i = 0; i < ARRAY_SIZE(s3c_battery_attrs); i++) {
+ rc = device_create_file(dev, &s3c_battery_attrs[i]);
+ if (rc)
+ goto s3c_attrs_failed;
+ }
+ goto succeed;
+
+s3c_attrs_failed:
+ while (i--)
+ device_remove_file(dev, &s3c_battery_attrs[i]);
+succeed:
+ return rc;
+}
+
+static ssize_t s3c_bat_show_property(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int i = 0;
+ const ptrdiff_t off = attr - s3c_battery_attrs;
+
+ switch (off) {
+ case BATT_VOL:
+ i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n",
+ s3c_bat_info.bat_info.batt_vol);
+ break;
+ case BATT_VOL_ADC:
+ i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n",
+ s3c_bat_info.bat_info.batt_vol_adc);
+ break;
+ case BATT_VOL_ADC_CAL:
+ i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n",
+ s3c_bat_info.bat_info.batt_vol_adc_cal);
+ break;
+ case BATT_TEMP:
+ i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n",
+ s3c_bat_info.bat_info.batt_temp);
+ break;
+ case BATT_TEMP_ADC:
+ i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n",
+ s3c_bat_info.bat_info.batt_temp_adc);
+ break;
+ case BATT_TEMP_ADC_CAL:
+ i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n",
+ s3c_bat_info.bat_info.batt_temp_adc_cal);
+ break;
+ default:
+ i = -EINVAL;
+ }
+
+ return i;
+}
+
+static ssize_t s3c_bat_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int x = 0;
+ int ret = 0;
+ const ptrdiff_t off = attr - s3c_battery_attrs;
+
+ switch (off) {
+ case BATT_VOL_ADC_CAL:
+ if (sscanf(buf, "%d\n", &x) == 1) {
+ s3c_bat_info.bat_info.batt_vol_adc_cal = x;
+ ret = count;
+ }
+ dev_info(dev, "%s : batt_vol_adc_cal = %d\n", __func__, x);
+ break;
+ case BATT_TEMP_ADC_CAL:
+ if (sscanf(buf, "%d\n", &x) == 1) {
+ s3c_bat_info.bat_info.batt_temp_adc_cal = x;
+ ret = count;
+ }
+ dev_info(dev, "%s : batt_temp_adc_cal = %d\n", __func__, x);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static enum power_supply_property s3c_battery_properties[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_TECHNOLOGY,
+ POWER_SUPPLY_PROP_CAPACITY,
+};
+
+static enum power_supply_property s3c_power_properties[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+};
+
+static char *supply_list[] = {
+ "battery",
+};
+
+static struct power_supply s3c_power_supplies[] = {
+ {
+ .name = "battery",
+ .type = POWER_SUPPLY_TYPE_BATTERY,
+ .properties = s3c_battery_properties,
+ .num_properties = ARRAY_SIZE(s3c_battery_properties),
+ .get_property = s3c_bat_get_property,
+ },
+ {
+ .name = "usb",
+ .type = POWER_SUPPLY_TYPE_USB,
+ .supplied_to = supply_list,
+ .num_supplicants = ARRAY_SIZE(supply_list),
+ .properties = s3c_power_properties,
+ .num_properties = ARRAY_SIZE(s3c_power_properties),
+ .get_property = s3c_power_get_property,
+ },
+ {
+ .name = "ac",
+ .type = POWER_SUPPLY_TYPE_MAINS,
+ .supplied_to = supply_list,
+ .num_supplicants = ARRAY_SIZE(supply_list),
+ .properties = s3c_power_properties,
+ .num_properties = ARRAY_SIZE(s3c_power_properties),
+ .get_property = s3c_power_get_property,
+ },
+};
+
+static int s3c_cable_status_update(int status)
+{
+ int ret = 0;
+ charger_type_t source = CHARGER_BATTERY;
+
+ dev_dbg(dev, "%s\n", __func__);
+
+ if(!s3c_battery_initial)
+ return -EPERM;
+
+ switch(status) {
+ case CHARGER_BATTERY:
+ dev_dbg(dev, "%s : cable NOT PRESENT\n", __func__);
+ s3c_bat_info.bat_info.charging_source = CHARGER_BATTERY;
+ break;
+ case CHARGER_USB:
+ dev_dbg(dev, "%s : cable USB\n", __func__);
+ s3c_bat_info.bat_info.charging_source = CHARGER_USB;
+ break;
+ case CHARGER_AC:
+ dev_dbg(dev, "%s : cable AC\n", __func__);
+ s3c_bat_info.bat_info.charging_source = CHARGER_AC;
+ break;
+ case CHARGER_DISCHARGE:
+ dev_dbg(dev, "%s : Discharge\n", __func__);
+ s3c_bat_info.bat_info.charging_source = CHARGER_DISCHARGE;
+ break;
+ default:
+ dev_err(dev, "%s : Nat supported status\n", __func__);
+ ret = -EINVAL;
+ }
+ source = s3c_bat_info.bat_info.charging_source;
+
+ if (source == CHARGER_USB || source == CHARGER_AC) {
+ wake_lock(&vbus_wake_lock);
+ } else {
+ /* give userspace some time to see the uevent and update
+ * LED state or whatnot...
+ */
+ wake_lock_timeout(&vbus_wake_lock, HZ / 2);
+ }
+
+ /* if the power source changes, all power supplies may change state */
+ power_supply_changed(&s3c_power_supplies[CHARGER_BATTERY]);
+ /*
+ power_supply_changed(&s3c_power_supplies[CHARGER_USB]);
+ power_supply_changed(&s3c_power_supplies[CHARGER_AC]);
+ */
+ dev_dbg(dev, "%s : call power_supply_changed\n", __func__);
+ return ret;
+}
+
+static void s3c_bat_status_update(struct power_supply *bat_ps)
+{
+ int old_level, old_temp, old_is_full;
+ dev_dbg(dev, "%s ++\n", __func__);
+
+ if(!s3c_battery_initial)
+ return;
+
+ mutex_lock(&work_lock);
+ old_temp = s3c_bat_info.bat_info.batt_temp;
+ old_level = s3c_bat_info.bat_info.level;
+ old_is_full = s3c_bat_info.bat_info.batt_is_full;
+ s3c_bat_info.bat_info.batt_temp = s3c_get_bat_temp(bat_ps);
+ s3c_bat_info.bat_info.level = s3c_get_bat_level(bat_ps);
+ s3c_bat_info.bat_info.batt_vol = s3c_get_bat_vol(bat_ps);
+
+ if (old_level != s3c_bat_info.bat_info.level
+ || old_temp != s3c_bat_info.bat_info.batt_temp
+ || old_is_full != s3c_bat_info.bat_info.batt_is_full
+ || force_update) {
+ force_update = 0;
+ power_supply_changed(bat_ps);
+ dev_dbg(dev, "%s : call power_supply_changed\n", __func__);
+ }
+
+ mutex_unlock(&work_lock);
+ dev_dbg(dev, "%s --\n", __func__);
+}
+
+void s3c_cable_check_status(int flag)
+{
+ charger_type_t status = 0;
+
+ if (flag == 0) // Battery
+ status = CHARGER_BATTERY;
+ else // USB
+ status = CHARGER_USB;
+ s3c_cable_status_update(status);
+}
+EXPORT_SYMBOL(s3c_cable_check_status);
+
+#ifdef CONFIG_PM
+static int s3c_bat_suspend(struct platform_device *pdev,
+ pm_message_t state)
+{
+ dev_info(dev, "%s\n", __func__);
+
+ return 0;
+}
+
+static int s3c_bat_resume(struct platform_device *pdev)
+{
+ dev_info(dev, "%s\n", __func__);
+
+ return 0;
+}
+#else
+#define s3c_bat_suspend NULL
+#define s3c_bat_resume NULL
+#endif /* CONFIG_PM */
+
+static int __devinit s3c_bat_probe(struct platform_device *pdev)
+{
+ int i;
+ int ret = 0;
+
+ dev = &pdev->dev;
+ dev_info(dev, "%s\n", __func__);
+
+ s3c_bat_info.present = 1;
+
+ s3c_bat_info.bat_info.batt_id = 0;
+ s3c_bat_info.bat_info.batt_vol = 0;
+ s3c_bat_info.bat_info.batt_vol_adc = 0;
+ s3c_bat_info.bat_info.batt_vol_adc_cal = 0;
+ s3c_bat_info.bat_info.batt_temp = 0;
+ s3c_bat_info.bat_info.batt_temp_adc = 0;
+ s3c_bat_info.bat_info.batt_temp_adc_cal = 0;
+ s3c_bat_info.bat_info.batt_current = 0;
+ s3c_bat_info.bat_info.level = 0;
+ s3c_bat_info.bat_info.charging_source = CHARGER_BATTERY;
+ s3c_bat_info.bat_info.charging_enabled = 0;
+ s3c_bat_info.bat_info.batt_health = POWER_SUPPLY_HEALTH_GOOD;
+
+ /* init power supplier framework */
+ for (i = 0; i < ARRAY_SIZE(s3c_power_supplies); i++) {
+ ret = power_supply_register(&pdev->dev,
+ &s3c_power_supplies[i]);
+ if (ret) {
+ dev_err(dev, "Failed to register"
+ "power supply %d,%d\n", i, ret);
+ goto __end__;
+ }
+ }
+
+ /* create sec detail attributes */
+ s3c_bat_create_attrs(s3c_power_supplies[CHARGER_BATTERY].dev);
+
+ s3c_battery_initial = 1;
+ force_update = 0;
+
+ s3c_bat_status_update(
+ &s3c_power_supplies[CHARGER_BATTERY]);
+
+__end__:
+ return ret;
+}
+
+static int __devexit s3c_bat_remove(struct platform_device *pdev)
+{
+ int i;
+ dev_info(dev, "%s\n", __func__);
+
+ for (i = 0; i < ARRAY_SIZE(s3c_power_supplies); i++) {
+ power_supply_unregister(&s3c_power_supplies[i]);
+ }
+
+ return 0;
+}
+
+static struct platform_driver s3c_bat_driver = {
+ .driver.name = DRIVER_NAME,
+ .driver.owner = THIS_MODULE,
+ .probe = s3c_bat_probe,
+ .remove = __devexit_p(s3c_bat_remove),
+ .suspend = s3c_bat_suspend,
+ .resume = s3c_bat_resume,
+};
+
+/* Initailize GPIO */
+static void s3c_bat_init_hw(void)
+{
+}
+
+static int __init s3c_bat_init(void)
+{
+ pr_info("%s\n", __func__);
+
+ s3c_bat_init_hw();
+
+ wake_lock_init(&vbus_wake_lock, WAKE_LOCK_SUSPEND, "vbus_present");
+
+ return platform_driver_register(&s3c_bat_driver);
+}
+
+static void __exit s3c_bat_exit(void)
+{
+ pr_info("%s\n", __func__);
+ platform_driver_unregister(&s3c_bat_driver);
+}
+
+module_init(s3c_bat_init);
+module_exit(s3c_bat_exit);
+
+MODULE_AUTHOR("HuiSung Kang <hs1218.kang@samsung.com>");
+MODULE_DESCRIPTION("S3C battery driver for SMDK Board");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/s5pc110_battery.c b/drivers/power/s5pc110_battery.c
new file mode 100755
index 0000000..a6902a2
--- /dev/null
+++ b/drivers/power/s5pc110_battery.c
@@ -0,0 +1,990 @@
+/*
+ * linux/drivers/power/s3c6410_battery.c
+ *
+ * Battery measurement code for S3C6410 platform.
+ *
+ * based on palmtx_battery.c
+ *
+ * Copyright (C) 2009 Samsung Electronics.
+ *
+ * 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 <asm/mach-types.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/mfd/max8998.h>
+#include <linux/mfd/max8998-private.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/regulator/driver.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/wakelock.h>
+#include <linux/workqueue.h>
+#include <mach/battery.h>
+#include <mach/gpio-herring.h>
+#include <mach/hardware.h>
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/regs-gpio.h>
+#include <mach/adc.h>
+#include <plat/gpio-cfg.h>
+#include <linux/android_alarm.h>
+#include "s5pc110_battery.h"
+#include <linux/mfd/max8998.h>
+
+#define POLLING_INTERVAL 1000
+#define ADC_TOTAL_COUNT 10
+#define ADC_DATA_ARR_SIZE 6
+
+#define OFFSET_VIBRATOR_ON (0x1 << 0)
+#define OFFSET_CAMERA_ON (0x1 << 1)
+#define OFFSET_MP3_PLAY (0x1 << 2)
+#define OFFSET_VIDEO_PLAY (0x1 << 3)
+#define OFFSET_VOICE_CALL_2G (0x1 << 4)
+#define OFFSET_VOICE_CALL_3G (0x1 << 5)
+#define OFFSET_DATA_CALL (0x1 << 6)
+#define OFFSET_LCD_ON (0x1 << 7)
+#define OFFSET_TA_ATTACHED (0x1 << 8)
+#define OFFSET_CAM_FLASH (0x1 << 9)
+#define OFFSET_BOOTING (0x1 << 10)
+
+#define FAST_POLL (1 * 60)
+#define SLOW_POLL (10 * 60)
+
+#define DISCONNECT_BAT_FULL 0x1
+#define DISCONNECT_TEMP_OVERHEAT 0x2
+#define DISCONNECT_TEMP_FREEZE 0x4
+#define DISCONNECT_OVER_TIME 0x8
+
+#define ATTACH_USB 1
+#define ATTACH_TA 2
+
+#define HIGH_BLOCK_TEMP 500
+#define HIGH_RECOVER_TEMP 420
+#define LOW_BLOCK_TEMP 0
+#define LOW_RECOVER_TEMP 20
+
+struct battery_info {
+ u32 batt_temp; /* Battery Temperature (C) from ADC */
+ u32 batt_temp_adc; /* Battery Temperature ADC value */
+ u32 batt_health; /* Battery Health (Authority) */
+ u32 dis_reason;
+ u32 batt_vcell;
+ u32 batt_soc;
+ u32 charging_status;
+ bool batt_is_full; /* 0 : Not full 1: Full */
+};
+
+struct adc_sample_info {
+ unsigned int cnt;
+ int total_adc;
+ int average_adc;
+ int adc_arr[ADC_TOTAL_COUNT];
+ int index;
+};
+
+struct chg_data {
+ struct device *dev;
+ struct max8998_dev *iodev;
+ struct work_struct bat_work;
+ struct max8998_charger_data *pdata;
+
+ struct power_supply psy_bat;
+ struct power_supply psy_usb;
+ struct power_supply psy_ac;
+ struct alarm alarm;
+ struct workqueue_struct *monitor_wqueue;
+ struct wake_lock vbus_wake_lock;
+ struct wake_lock work_wake_lock;
+ struct adc_sample_info adc_sample[ENDOFADC];
+ struct battery_info bat_info;
+ struct mutex mutex;
+
+ enum cable_type_t cable_status;
+ bool charging;
+ bool set_charge_timeout;
+ int present;
+ int timestamp;
+ int set_batt_full;
+ unsigned long discharging_time;
+ unsigned int polling_interval;
+ int slow_poll;
+ ktime_t last_poll;
+ struct max8998_charger_callbacks callbacks;
+};
+
+static bool disable_charger;
+
+static char *supply_list[] = {
+ "battery",
+};
+
+static enum power_supply_property max8998_battery_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_TEMP,
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_TECHNOLOGY,
+};
+
+static enum power_supply_property s3c_power_properties[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+};
+
+static ssize_t s3c_bat_show_attrs(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t s3c_bat_store_attrs(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count);
+
+#define SEC_BATTERY_ATTR(_name) \
+{ \
+ .attr = {.name = #_name, .mode = 0664 }, \
+ .show = s3c_bat_show_attrs, \
+ .store = s3c_bat_store_attrs, \
+}
+
+static struct device_attribute s3c_battery_attrs[] = {
+ SEC_BATTERY_ATTR(disable_charger)
+};
+
+static void max8998_set_cable(struct max8998_charger_callbacks *ptr,
+ enum cable_type_t status)
+{
+ struct chg_data *chg = container_of(ptr, struct chg_data, callbacks);
+ chg->cable_status = status;
+ power_supply_changed(&chg->psy_ac);
+ power_supply_changed(&chg->psy_usb);
+ wake_lock(&chg->work_wake_lock);
+ queue_work(chg->monitor_wqueue, &chg->bat_work);
+}
+
+static bool max8998_check_vdcin(struct chg_data *chg)
+{
+ u8 data = 0;
+ int ret;
+
+ ret = max8998_read_reg(chg->iodev->i2c, MAX8998_REG_STATUS2, &data);
+
+ if (ret < 0) {
+ pr_err("max8998_read_reg error\n");
+ return ret;
+ }
+
+ return data & MAX8998_MASK_VDCIN;
+}
+
+static int s3c_bat_get_property(struct power_supply *bat_ps,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct chg_data *chg = container_of(bat_ps,
+ struct chg_data, psy_bat);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ val->intval = chg->bat_info.charging_status;
+ break;
+ case POWER_SUPPLY_PROP_HEALTH:
+ val->intval = chg->bat_info.batt_health;
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+ val->intval = chg->present;
+ break;
+ case POWER_SUPPLY_PROP_TEMP:
+ val->intval = chg->bat_info.batt_temp;
+ break;
+ case POWER_SUPPLY_PROP_ONLINE:
+ /* battery is always online */
+ val->intval = 1;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ case POWER_SUPPLY_PROP_CAPACITY:
+ if (chg->pdata &&
+ chg->pdata->psy_fuelgauge &&
+ chg->pdata->psy_fuelgauge->get_property &&
+ chg->pdata->psy_fuelgauge->get_property(
+ chg->pdata->psy_fuelgauge, psp, val) < 0)
+ return -EINVAL;
+ break;
+ case POWER_SUPPLY_PROP_TECHNOLOGY:
+ val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int s3c_usb_get_property(struct power_supply *ps,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct chg_data *chg = container_of(ps, struct chg_data, psy_usb);
+
+ if (psp != POWER_SUPPLY_PROP_ONLINE)
+ return -EINVAL;
+
+ /* Set enable=1 only if the USB charger is connected */
+ val->intval = ((chg->cable_status == CABLE_TYPE_USB) &&
+ max8998_check_vdcin(chg));
+
+ return 0;
+}
+
+static int s3c_ac_get_property(struct power_supply *ps,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct chg_data *chg = container_of(ps, struct chg_data, psy_ac);
+
+ if (psp != POWER_SUPPLY_PROP_ONLINE)
+ return -EINVAL;
+
+ /* Set enable=1 only if the AC charger is connected */
+ val->intval = (chg->cable_status == CABLE_TYPE_AC);
+
+ return 0;
+}
+
+static int s3c_bat_get_adc_data(enum adc_channel_type adc_ch)
+{
+ int adc_data;
+ int adc_max = 0;
+ int adc_min = 0;
+ int adc_total = 0;
+ int i;
+
+ for (i = 0; i < ADC_DATA_ARR_SIZE; i++) {
+ adc_data = s3c_adc_get_adc_data(adc_ch);
+
+ if (i != 0) {
+ if (adc_data > adc_max)
+ adc_max = adc_data;
+ else if (adc_data < adc_min)
+ adc_min = adc_data;
+ } else {
+ adc_max = adc_data;
+ adc_min = adc_data;
+ }
+ adc_total += adc_data;
+ }
+
+ return (adc_total - adc_max - adc_min) / (ADC_DATA_ARR_SIZE - 2);
+}
+
+static unsigned long calculate_average_adc(enum adc_channel_type channel,
+ int adc, struct chg_data *chg)
+{
+ unsigned int cnt = 0;
+ int total_adc = 0;
+ int average_adc = 0;
+ int index = 0;
+
+ cnt = chg->adc_sample[channel].cnt;
+ total_adc = chg->adc_sample[channel].total_adc;
+
+ if (adc <= 0) {
+ pr_err("%s : invalid adc : %d\n", __func__, adc);
+ adc = chg->adc_sample[channel].average_adc;
+ }
+
+ if (cnt < ADC_TOTAL_COUNT) {
+ chg->adc_sample[channel].adc_arr[cnt] = adc;
+ chg->adc_sample[channel].index = cnt;
+ chg->adc_sample[channel].cnt = ++cnt;
+
+ total_adc += adc;
+ average_adc = total_adc / cnt;
+ } else {
+ index = chg->adc_sample[channel].index;
+ if (++index >= ADC_TOTAL_COUNT)
+ index = 0;
+
+ total_adc = total_adc - chg->adc_sample[channel].adc_arr[index]
+ + adc;
+ average_adc = total_adc / ADC_TOTAL_COUNT;
+
+ chg->adc_sample[channel].adc_arr[index] = adc;
+ chg->adc_sample[channel].index = index;
+ }
+
+ chg->adc_sample[channel].total_adc = total_adc;
+ chg->adc_sample[channel].average_adc = average_adc;
+
+ chg->bat_info.batt_temp_adc = average_adc;
+
+ return average_adc;
+}
+
+static unsigned long s3c_read_temp(struct chg_data *chg)
+{
+ int adc = 0;
+
+ adc = s3c_bat_get_adc_data(S3C_ADC_TEMPERATURE);
+
+ return calculate_average_adc(S3C_ADC_TEMPERATURE, adc, chg);
+}
+
+static int s3c_get_bat_temp(struct chg_data *chg)
+{
+ int temp = 0;
+ int temp_adc = s3c_read_temp(chg);
+ int health = chg->bat_info.batt_health;
+ int left_side = 0;
+ int right_side = chg->pdata->adc_array_size - 1;
+ int mid;
+
+ while (left_side <= right_side) {
+ mid = (left_side + right_side) / 2 ;
+ if (mid == 0 || mid == chg->pdata->adc_array_size - 1 ||
+ (chg->pdata->adc_table[mid].adc_value <= temp_adc &&
+ chg->pdata->adc_table[mid+1].adc_value > temp_adc)) {
+ temp = chg->pdata->adc_table[mid].temperature;
+ break;
+ } else if (temp_adc - chg->pdata->adc_table[mid].adc_value > 0)
+ left_side = mid + 1;
+ else
+ right_side = mid - 1;
+ }
+
+ chg->bat_info.batt_temp = temp;
+ if (temp >= HIGH_BLOCK_TEMP) {
+ if (health != POWER_SUPPLY_HEALTH_OVERHEAT &&
+ health != POWER_SUPPLY_HEALTH_UNSPEC_FAILURE)
+ chg->bat_info.batt_health =
+ POWER_SUPPLY_HEALTH_OVERHEAT;
+ } else if (temp <= HIGH_RECOVER_TEMP && temp >= LOW_RECOVER_TEMP) {
+ if (health == POWER_SUPPLY_HEALTH_OVERHEAT ||
+ health == POWER_SUPPLY_HEALTH_COLD)
+ chg->bat_info.batt_health =
+ POWER_SUPPLY_HEALTH_GOOD;
+ } else if (temp <= LOW_BLOCK_TEMP) {
+ if (health != POWER_SUPPLY_HEALTH_COLD &&
+ health != POWER_SUPPLY_HEALTH_UNSPEC_FAILURE)
+ chg->bat_info.batt_health =
+ POWER_SUPPLY_HEALTH_COLD;
+ }
+
+ pr_debug("%s : temp = %d, adc = %d\n", __func__, temp, temp_adc);
+
+ return temp;
+}
+
+static void s3c_bat_discharge_reason(struct chg_data *chg)
+{
+ int discharge_reason;
+ ktime_t ktime;
+ struct timespec cur_time;
+ union power_supply_propval value;
+
+ if (chg->pdata && chg->pdata->psy_fuelgauge &&
+ chg->pdata->psy_fuelgauge->get_property) {
+ chg->pdata->psy_fuelgauge->get_property(chg->pdata->psy_fuelgauge,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW, &value);
+ chg->bat_info.batt_vcell = value.intval;
+
+ chg->pdata->psy_fuelgauge->get_property(chg->pdata->psy_fuelgauge,
+ POWER_SUPPLY_PROP_CAPACITY, &value);
+ chg->bat_info.batt_soc = value.intval;
+ }
+
+ discharge_reason = chg->bat_info.dis_reason & 0xf;
+
+ if (discharge_reason & DISCONNECT_BAT_FULL &&
+ chg->bat_info.batt_vcell < RECHARGE_COND_VOLTAGE)
+ chg->bat_info.dis_reason &= ~DISCONNECT_BAT_FULL;
+
+ if (discharge_reason & DISCONNECT_TEMP_OVERHEAT &&
+ chg->bat_info.batt_temp <=
+ HIGH_RECOVER_TEMP)
+ chg->bat_info.dis_reason &= ~DISCONNECT_TEMP_OVERHEAT;
+
+ if (discharge_reason & DISCONNECT_TEMP_FREEZE &&
+ chg->bat_info.batt_temp >=
+ LOW_RECOVER_TEMP)
+ chg->bat_info.dis_reason &= ~DISCONNECT_TEMP_FREEZE;
+
+ if (discharge_reason & DISCONNECT_OVER_TIME &&
+ chg->bat_info.batt_vcell < RECHARGE_COND_VOLTAGE)
+ chg->bat_info.dis_reason &= ~DISCONNECT_OVER_TIME;
+
+ if (chg->set_batt_full)
+ chg->bat_info.dis_reason |= DISCONNECT_BAT_FULL;
+
+ if (chg->bat_info.batt_health != POWER_SUPPLY_HEALTH_GOOD)
+ chg->bat_info.dis_reason |= chg->bat_info.batt_health ==
+ POWER_SUPPLY_HEALTH_OVERHEAT ?
+ DISCONNECT_TEMP_OVERHEAT : DISCONNECT_TEMP_FREEZE;
+
+ ktime = alarm_get_elapsed_realtime();
+ cur_time = ktime_to_timespec(ktime);
+
+ if (chg->discharging_time &&
+ cur_time.tv_sec > chg->discharging_time) {
+ chg->set_charge_timeout = true;
+ chg->bat_info.dis_reason |= DISCONNECT_OVER_TIME;
+ }
+
+ pr_debug("%s : Current Voltage : %d\n \
+ Current time : %ld discharging_time : %ld\n \
+ discharging reason : %d\n", \
+ __func__, chg->bat_info.batt_vcell, cur_time.tv_sec,
+ chg->discharging_time, chg->bat_info.dis_reason);
+}
+
+static int max8998_charging_control(struct chg_data *chg)
+{
+ int ret;
+ struct i2c_client *i2c = chg->iodev->i2c;
+
+ if (!chg->charging) {
+ /* disable charging */
+ ret = max8998_update_reg(i2c, MAX8998_REG_CHGR2,
+ (1 << MAX8998_SHIFT_CHGEN), MAX8998_MASK_CHGEN);
+ if (ret < 0)
+ goto err;
+
+ pr_debug("%s : charging disabled", __func__);
+ } else {
+ /* enable charging */
+ if (chg->cable_status == CABLE_TYPE_AC) {
+ /* ac */
+ ret = max8998_write_reg(i2c, MAX8998_REG_CHGR1,
+ (2 << MAX8998_SHIFT_TOPOFF) |
+ (3 << MAX8998_SHIFT_RSTR) |
+ (5 << MAX8998_SHIFT_ICHG));
+ if (ret < 0)
+ goto err;
+
+ pr_debug("%s : TA charging enabled", __func__);
+ } else {
+ /* usb */
+ ret = max8998_write_reg(i2c, MAX8998_REG_CHGR1,
+ (6 << MAX8998_SHIFT_TOPOFF) |
+ (3 << MAX8998_SHIFT_RSTR) |
+ (2 << MAX8998_SHIFT_ICHG));
+ if (ret < 0)
+ goto err;
+
+ pr_debug("%s : USB charging enabled", __func__);
+ }
+
+ ret = max8998_write_reg(i2c, MAX8998_REG_CHGR2,
+ (2 << MAX8998_SHIFT_ESAFEOUT) |
+ (2 << MAX8998_SHIFT_FT) |
+ (0 << MAX8998_SHIFT_CHGEN));
+ if (ret < 0)
+ goto err;
+ }
+
+ return 0;
+err:
+ pr_err("max8998_read_reg error\n");
+ return ret;
+}
+
+static int s3c_cable_status_update(struct chg_data *chg)
+{
+ int ret;
+ bool vdc_status;
+ ktime_t ktime;
+ struct timespec cur_time;
+
+ /* if max8998 has detected vdcin */
+ if (max8998_check_vdcin(chg)) {
+ vdc_status = 1;
+ if (chg->bat_info.dis_reason || disable_charger) {
+ pr_info("%s : battery status discharging : %d\n",
+ __func__, chg->bat_info.dis_reason);
+ /* have vdcin, but cannot charge */
+ chg->charging = false;
+ ret = max8998_charging_control(chg);
+ if (ret < 0)
+ goto err;
+ chg->bat_info.charging_status =
+ chg->bat_info.batt_is_full ?
+ POWER_SUPPLY_STATUS_FULL :
+ POWER_SUPPLY_STATUS_NOT_CHARGING;
+ chg->discharging_time = 0;
+ chg->set_batt_full = 0;
+ goto update;
+ } else if (chg->discharging_time == 0) {
+ ktime = alarm_get_elapsed_realtime();
+ cur_time = ktime_to_timespec(ktime);
+ chg->discharging_time =
+ chg->bat_info.batt_is_full ||
+ chg->set_charge_timeout ?
+ cur_time.tv_sec + TOTAL_RECHARGING_TIME :
+ cur_time.tv_sec + TOTAL_CHARGING_TIME;
+ }
+
+ /* able to charge */
+ chg->charging = true;
+ ret = max8998_charging_control(chg);
+ if (ret < 0)
+ goto err;
+
+ chg->bat_info.charging_status = chg->bat_info.batt_is_full ?
+ POWER_SUPPLY_STATUS_FULL : POWER_SUPPLY_STATUS_CHARGING;
+
+ } else {
+ /* no vdc in, not able to charge */
+ vdc_status = 0;
+ chg->charging = false;
+ ret = max8998_charging_control(chg);
+ if (ret < 0)
+ goto err;
+
+ chg->bat_info.charging_status = POWER_SUPPLY_STATUS_DISCHARGING;
+
+ chg->bat_info.batt_is_full = false;
+ chg->set_charge_timeout = false;
+ chg->set_batt_full = 0;
+ chg->bat_info.dis_reason = 0;
+ chg->discharging_time = 0;
+ }
+
+update:
+ if ((chg->cable_status == CABLE_TYPE_USB) && vdc_status)
+ wake_lock(&chg->vbus_wake_lock);
+ else
+ wake_lock_timeout(&chg->vbus_wake_lock, HZ / 2);
+
+ return 0;
+err:
+ return ret;
+}
+
+static void s3c_program_alarm(struct chg_data *chg, int seconds)
+{
+ ktime_t low_interval = ktime_set(seconds - 10, 0);
+ ktime_t slack = ktime_set(20, 0);
+ ktime_t next;
+
+ next = ktime_add(chg->last_poll, low_interval);
+ alarm_start_range(&chg->alarm, next, ktime_add(next, slack));
+}
+
+static void s3c_bat_work(struct work_struct *work)
+{
+ struct chg_data *chg =
+ container_of(work, struct chg_data, bat_work);
+ int ret;
+ struct timespec ts;
+ unsigned long flags;
+ mutex_lock(&chg->mutex);
+
+ s3c_get_bat_temp(chg);
+ s3c_bat_discharge_reason(chg);
+
+ ret = s3c_cable_status_update(chg);
+ if (ret < 0)
+ goto err;
+
+ mutex_unlock(&chg->mutex);
+
+ power_supply_changed(&chg->psy_bat);
+
+ chg->last_poll = alarm_get_elapsed_realtime();
+ ts = ktime_to_timespec(chg->last_poll);
+ chg->timestamp = ts.tv_sec;
+
+ /* prevent suspend before starting the alarm */
+ local_irq_save(flags);
+ wake_unlock(&chg->work_wake_lock);
+ s3c_program_alarm(chg, FAST_POLL);
+ local_irq_restore(flags);
+ return;
+err:
+ mutex_unlock(&chg->mutex);
+ wake_unlock(&chg->work_wake_lock);
+ pr_err("battery workqueue fail\n");
+}
+
+static void s3c_battery_alarm(struct alarm *alarm)
+{
+ struct chg_data *chg =
+ container_of(alarm, struct chg_data, alarm);
+
+ wake_lock(&chg->work_wake_lock);
+ queue_work(chg->monitor_wqueue, &chg->bat_work);
+}
+
+static ssize_t s3c_bat_show_attrs(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct power_supply *psy = dev_get_drvdata(dev);
+ struct chg_data *chg = container_of(psy, struct chg_data, psy_bat);
+ int i = 0;
+ const ptrdiff_t off = attr - s3c_battery_attrs;
+ union power_supply_propval value;
+
+ switch (off) {
+ case DISABLE_CHARGER:
+ i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n", disable_charger);
+ break;
+ default:
+ i = -EINVAL;
+ }
+
+ return i;
+}
+
+static ssize_t s3c_bat_store_attrs(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+// struct power_supply *psy = dev_get_drvdata(dev);
+// struct chg_data *chg = container_of(psy, struct chg_data, psy_bat);
+ int x = 0;
+ int ret = 0;
+ const ptrdiff_t off = attr - s3c_battery_attrs;
+
+ switch (off) {
+ case DISABLE_CHARGER:
+ if (sscanf(buf, "%d\n", &x) == 1) {
+ disable_charger = x;
+ ret = count;
+ }
+ break;
+
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int s3c_bat_create_attrs(struct device *dev)
+{
+ int i, rc;
+
+ for (i = 0; i < ARRAY_SIZE(s3c_battery_attrs); i++) {
+ rc = device_create_file(dev, &s3c_battery_attrs[i]);
+ if (rc)
+ goto s3c_attrs_failed;
+ }
+ goto succeed;
+
+s3c_attrs_failed:
+ while (i--)
+ device_remove_file(dev, &s3c_battery_attrs[i]);
+succeed:
+ return rc;
+}
+
+static irqreturn_t max8998_int_work_func(int irq, void *max8998_chg)
+{
+ int ret;
+ u8 data = 0;
+ struct chg_data *chg;
+ struct i2c_client *i2c;
+
+ chg = max8998_chg;
+ i2c = chg->iodev->i2c;
+
+ ret = max8998_read_reg(i2c, MAX8998_REG_IRQ1, &data);
+ if (ret < 0)
+ goto err;
+
+ ret = max8998_read_reg(i2c, MAX8998_REG_IRQ3, &data);
+ if (ret < 0)
+ goto err;
+
+ if ((data & 0x4) || (ret != 0)) {
+ pr_info("%s : pmic interrupt\n", __func__);
+ chg->set_batt_full = 1;
+ chg->bat_info.batt_is_full = true;
+ }
+
+ wake_lock(&chg->work_wake_lock);
+ queue_work(chg->monitor_wqueue, &chg->bat_work);
+
+ return IRQ_HANDLED;
+err:
+ pr_err("%s : pmic read error\n", __func__);
+ return IRQ_HANDLED;
+}
+
+static __devinit int max8998_charger_probe(struct platform_device *pdev)
+{
+ struct max8998_dev *iodev = dev_get_drvdata(pdev->dev.parent);
+ struct max8998_platform_data *pdata = dev_get_platdata(iodev->dev);
+ struct chg_data *chg;
+ struct i2c_client *i2c = iodev->i2c;
+ int ret = 0;
+
+ pr_info("%s : MAX8998 Charger Driver Loading\n", __func__);
+
+ chg = kzalloc(sizeof(*chg), GFP_KERNEL);
+ if (!chg)
+ return -ENOMEM;
+
+ chg->iodev = iodev;
+ chg->pdata = pdata->charger;
+
+ if (!chg->pdata || !chg->pdata->adc_table) {
+ pr_err("%s : No platform data & adc_table supplied\n", __func__);
+ ret = -EINVAL;
+ goto err_bat_table;
+ }
+
+ chg->psy_bat.name = "battery",
+ chg->psy_bat.type = POWER_SUPPLY_TYPE_BATTERY,
+ chg->psy_bat.properties = max8998_battery_props,
+ chg->psy_bat.num_properties = ARRAY_SIZE(max8998_battery_props),
+ chg->psy_bat.get_property = s3c_bat_get_property,
+
+ chg->psy_usb.name = "usb",
+ chg->psy_usb.type = POWER_SUPPLY_TYPE_USB,
+ chg->psy_usb.supplied_to = supply_list,
+ chg->psy_usb.num_supplicants = ARRAY_SIZE(supply_list),
+ chg->psy_usb.properties = s3c_power_properties,
+ chg->psy_usb.num_properties = ARRAY_SIZE(s3c_power_properties),
+ chg->psy_usb.get_property = s3c_usb_get_property,
+
+ chg->psy_ac.name = "ac",
+ chg->psy_ac.type = POWER_SUPPLY_TYPE_MAINS,
+ chg->psy_ac.supplied_to = supply_list,
+ chg->psy_ac.num_supplicants = ARRAY_SIZE(supply_list),
+ chg->psy_ac.properties = s3c_power_properties,
+ chg->psy_ac.num_properties = ARRAY_SIZE(s3c_power_properties),
+ chg->psy_ac.get_property = s3c_ac_get_property,
+
+ chg->present = 1;
+ chg->polling_interval = POLLING_INTERVAL;
+ chg->bat_info.batt_health = POWER_SUPPLY_HEALTH_GOOD;
+ chg->bat_info.batt_is_full = false;
+ chg->set_charge_timeout = false;
+
+ chg->cable_status = CABLE_TYPE_NONE;
+
+ mutex_init(&chg->mutex);
+
+ platform_set_drvdata(pdev, chg);
+
+ ret = max8998_update_reg(i2c, MAX8998_REG_CHGR1, /* disable */
+ (0x3 << MAX8998_SHIFT_RSTR), MAX8998_MASK_RSTR);
+ if (ret < 0)
+ goto err_kfree;
+
+ ret = max8998_update_reg(i2c, MAX8998_REG_CHGR2, /* 6 Hr */
+ (0x2 << MAX8998_SHIFT_FT), MAX8998_MASK_FT);
+ if (ret < 0)
+ goto err_kfree;
+
+ ret = max8998_update_reg(i2c, MAX8998_REG_CHGR2, /* 4.2V */
+ (0x0 << MAX8998_SHIFT_BATTSL), MAX8998_MASK_BATTSL);
+ if (ret < 0)
+ goto err_kfree;
+
+ ret = max8998_update_reg(i2c, MAX8998_REG_CHGR2, /* 105c */
+ (0x0 << MAX8998_SHIFT_TMP), MAX8998_MASK_TMP);
+ if (ret < 0)
+ goto err_kfree;
+
+ pr_info("%s : pmic interrupt registered\n", __func__);
+ ret = max8998_write_reg(i2c, MAX8998_REG_IRQM1,
+ ~(MAX8998_MASK_DCINR | MAX8998_MASK_DCINF));
+ if (ret < 0)
+ goto err_kfree;
+
+ ret = max8998_write_reg(i2c, MAX8998_REG_IRQM2, 0xFF);
+ if (ret < 0)
+ goto err_kfree;
+
+ ret = max8998_write_reg(i2c, MAX8998_REG_IRQM3, ~0x4);
+ if (ret < 0)
+ goto err_kfree;
+
+ ret = max8998_write_reg(i2c, MAX8998_REG_IRQM4, 0xFF);
+ if (ret < 0)
+ goto err_kfree;
+
+ wake_lock_init(&chg->vbus_wake_lock, WAKE_LOCK_SUSPEND,
+ "vbus_present");
+ wake_lock_init(&chg->work_wake_lock, WAKE_LOCK_SUSPEND,
+ "max8998-charger");
+
+ INIT_WORK(&chg->bat_work, s3c_bat_work);
+
+ chg->monitor_wqueue =
+ create_freezable_workqueue(dev_name(&pdev->dev));
+ if (!chg->monitor_wqueue) {
+ pr_err("Failed to create freezeable workqueue\n");
+ ret = -ENOMEM;
+ goto err_wake_lock;
+ }
+
+ chg->last_poll = alarm_get_elapsed_realtime();
+ alarm_init(&chg->alarm, ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP,
+ s3c_battery_alarm);
+
+ disable_charger = 0;
+
+ /* init power supplier framework */
+ ret = power_supply_register(&pdev->dev, &chg->psy_bat);
+ if (ret) {
+ pr_err("Failed to register power supply psy_bat\n");
+ goto err_wqueue;
+ }
+
+ ret = power_supply_register(&pdev->dev, &chg->psy_usb);
+ if (ret) {
+ pr_err("Failed to register power supply psy_usb\n");
+ goto err_supply_unreg_bat;
+ }
+
+ ret = power_supply_register(&pdev->dev, &chg->psy_ac);
+ if (ret) {
+ pr_err("Failed to register power supply psy_ac\n");
+ goto err_supply_unreg_usb;
+ }
+
+ ret = request_threaded_irq(iodev->i2c->irq, NULL,
+ max8998_int_work_func,
+ IRQF_TRIGGER_FALLING, "max8998-charger", chg);
+ if (ret) {
+ pr_err("%s : Failed to request pmic irq\n", __func__);
+ goto err_supply_unreg_ac;
+ }
+
+ ret = enable_irq_wake(iodev->i2c->irq);
+ if (ret) {
+ pr_err("Failed to enable pmic irq wake\n");
+ goto err_irq;
+ }
+
+ ret = s3c_bat_create_attrs(chg->psy_bat.dev);
+ if (ret) {
+ pr_err("%s : Failed to create_attrs\n", __func__);
+ goto err_irq;
+ }
+
+ chg->callbacks.set_cable = max8998_set_cable;
+ if (chg->pdata->register_callbacks)
+ chg->pdata->register_callbacks(&chg->callbacks);
+
+ wake_lock(&chg->work_wake_lock);
+ queue_work(chg->monitor_wqueue, &chg->bat_work);
+
+ return 0;
+
+err_irq:
+ free_irq(iodev->i2c->irq, NULL);
+err_supply_unreg_ac:
+ power_supply_unregister(&chg->psy_ac);
+err_supply_unreg_usb:
+ power_supply_unregister(&chg->psy_usb);
+err_supply_unreg_bat:
+ power_supply_unregister(&chg->psy_bat);
+err_wqueue:
+ destroy_workqueue(chg->monitor_wqueue);
+ cancel_work_sync(&chg->bat_work);
+ alarm_cancel(&chg->alarm);
+err_wake_lock:
+ wake_lock_destroy(&chg->work_wake_lock);
+ wake_lock_destroy(&chg->vbus_wake_lock);
+err_kfree:
+ mutex_destroy(&chg->mutex);
+err_bat_table:
+ kfree(chg);
+ return ret;
+}
+
+static int __devexit max8998_charger_remove(struct platform_device *pdev)
+{
+ struct chg_data *chg = platform_get_drvdata(pdev);
+
+ alarm_cancel(&chg->alarm);
+ free_irq(chg->iodev->i2c->irq, NULL);
+ flush_workqueue(chg->monitor_wqueue);
+ destroy_workqueue(chg->monitor_wqueue);
+ power_supply_unregister(&chg->psy_bat);
+ power_supply_unregister(&chg->psy_usb);
+ power_supply_unregister(&chg->psy_ac);
+
+ wake_lock_destroy(&chg->vbus_wake_lock);
+ mutex_destroy(&chg->mutex);
+ kfree(chg);
+
+ return 0;
+}
+
+static int max8998_charger_suspend(struct device *dev)
+{
+
+ struct chg_data *chg = dev_get_drvdata(dev);
+ if (!chg->charging) {
+ s3c_program_alarm(chg, SLOW_POLL);
+ chg->slow_poll = 1;
+ }
+
+ return 0;
+}
+
+static void max8998_charger_resume(struct device *dev)
+{
+
+ struct chg_data *chg = dev_get_drvdata(dev);
+ /* We might be on a slow sample cycle. If we're
+ * resuming we should resample the battery state
+ * if it's been over a minute since we last did
+ * so, and move back to sampling every minute until
+ * we suspend again.
+ */
+ if (chg->slow_poll) {
+ s3c_program_alarm(chg, FAST_POLL);
+ chg->slow_poll = 0;
+ }
+}
+
+static const struct dev_pm_ops max8998_charger_pm_ops = {
+ .prepare = max8998_charger_suspend,
+ .complete = max8998_charger_resume,
+};
+
+static struct platform_driver max8998_charger_driver = {
+ .driver = {
+ .name = "max8998-charger",
+ .owner = THIS_MODULE,
+ .pm = &max8998_charger_pm_ops,
+ },
+ .probe = max8998_charger_probe,
+ .remove = __devexit_p(max8998_charger_remove),
+};
+
+static int __init max8998_charger_init(void)
+{
+ return platform_driver_register(&max8998_charger_driver);
+}
+
+static void __exit max8998_charger_exit(void)
+{
+ platform_driver_register(&max8998_charger_driver);
+}
+
+late_initcall(max8998_charger_init);
+module_exit(max8998_charger_exit);
+
+MODULE_AUTHOR("Minsung Kim <ms925.kim@samsung.com>");
+MODULE_DESCRIPTION("S3C6410 battery driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/s5pc110_battery.h b/drivers/power/s5pc110_battery.h
new file mode 100644
index 0000000..492e047
--- /dev/null
+++ b/drivers/power/s5pc110_battery.h
@@ -0,0 +1,89 @@
+/*
+ * linux/drivers/power/s3c6410_battery.h
+ *
+ * Battery measurement code for S3C6410 platform.
+ *
+ * Copyright (C) 2009 Samsung Electronics.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#define DRIVER_NAME "sec-battery"
+
+/*
+ * Battery Table
+ */
+#define BATT_CAL 2447 /* 3.60V */
+
+#define BATT_MAXIMUM 406 /* 4.176V */
+#define BATT_FULL 353 /* 4.10V */
+#define BATT_SAFE_RECHARGE 353 /* 4.10V */
+#define BATT_ALMOST_FULL 188 /* 3.8641V */
+#define BATT_HIGH 112 /* 3.7554V */
+#define BATT_MED 66 /* 3.6907V */
+#define BATT_LOW 43 /* 3.6566V */
+#define BATT_CRITICAL 8 /* 3.6037V */
+#define BATT_MINIMUM (-28) /* 3.554V */
+#define BATT_OFF (-128) /* 3.4029V */
+
+/*
+ * ADC channel
+ */
+enum adc_channel_type{
+ S3C_ADC_VOLTAGE = 0,
+ S3C_ADC_CHG_CURRENT = 2,
+ S3C_ADC_EAR = 3,
+ S3C_ADC_TEMPERATURE = 6,
+ S3C_ADC_V_F,
+ ENDOFADC
+};
+
+enum {
+ BATT_VOL = 0,
+ BATT_VOL_ADC,
+ BATT_VOL_ADC_CAL,
+ BATT_TEMP,
+ BATT_TEMP_ADC,
+ BATT_TEMP_ADC_CAL,
+ BATT_VOL_ADC_AVER,
+ BATT_CHARGING_SOURCE,
+ BATT_VIBRATOR,
+ BATT_CAMERA,
+ BATT_MP3,
+ BATT_VIDEO,
+ BATT_VOICE_CALL_2G,
+ BATT_VOICE_CALL_3G,
+ BATT_DATA_CALL,
+ BATT_DEV_STATE,
+ BATT_COMPENSATION,
+ BATT_BOOTING,
+ BATT_FG_SOC,
+ BATT_RESET_SOC,
+};
+
+enum {
+ DISABLE_CHARGER,
+};
+
+#define TOTAL_CHARGING_TIME (6*60*60) /* 6 hours */
+#define TOTAL_RECHARGING_TIME (90*60) /* 1.5 hours */
+
+#define COMPENSATE_VIBRATOR 19
+#define COMPENSATE_CAMERA 25
+#define COMPENSATE_MP3 17
+#define COMPENSATE_VIDEO 28
+#define COMPENSATE_VOICE_CALL_2G 13
+#define COMPENSATE_VOICE_CALL_3G 14
+#define COMPENSATE_DATA_CALL 25
+#define COMPENSATE_LCD 0
+#define COMPENSATE_TA 0
+#define COMPENSATE_CAM_FALSH 0
+#define COMPENSATE_BOOTING 52
+
+#define SOC_LB_FOR_POWER_OFF 27
+
+#define RECHARGE_COND_VOLTAGE 4130000
+#define RECHARGE_COND_TIME (30*1000) /* 30 seconds */
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index d7ed20f..279db2c 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -94,6 +94,11 @@ config REGULATOR_MAX8660
This driver controls a Maxim 8660/8661 voltage output
regulator via I2C bus.
+config REGULATOR_MAX8893
+ tristate "Maxim MAX8893 Power Management IC"
+ help
+ This driver controls a Maxim 8893 PMIC.
+
config REGULATOR_MAX8925
tristate "Maxim MAX8925 Power Management IC"
depends on MFD_MAX8925
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 3932d2e..7bc20bc 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o
obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o
obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o
obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o
+obj-$(CONFIG_REGULATOR_MAX8893) += max8893.o
obj-$(CONFIG_REGULATOR_MAX8925) += max8925-regulator.o
obj-$(CONFIG_REGULATOR_MAX8952) += max8952.o
obj-$(CONFIG_REGULATOR_MAX8997) += max8997.o
diff --git a/drivers/regulator/max8893.c b/drivers/regulator/max8893.c
new file mode 100644
index 0000000..6009e89
--- /dev/null
+++ b/drivers/regulator/max8893.c
@@ -0,0 +1,349 @@
+/*
+ * max8893.c
+ *
+ * based on max8660.c
+ *
+ * Copyright (C) 2009 Wolfram Sang, Pengutronix e.K.
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/max8893.h>
+#include <linux/slab.h>
+
+#define MAX8893_STEP (100000)
+
+enum {
+ MAX8893_ONOFF = 0x00,
+ MAX8893_VOLTAGE_BASE = 0x04,
+};
+
+struct max8893 {
+ struct i2c_client *client;
+ struct mutex lock;
+ struct regulator_dev *rdev[];
+};
+
+struct max8893_desc {
+ struct regulator_desc desc;
+ int min_uV;
+ u8 mask;
+};
+
+static struct max8893_desc *rdev_get_max8893_desc(struct regulator_dev *rdev)
+{
+ return container_of(rdev->desc, struct max8893_desc, desc);
+}
+
+static int max8893_onoff(struct regulator_dev *rdev, bool enable)
+{
+ struct max8893 *max8893 = rdev_get_drvdata(rdev);
+ struct max8893_desc *desc = rdev_get_max8893_desc(rdev);
+ int ret;
+ u8 val;
+
+ mutex_lock(&max8893->lock);
+ ret = i2c_smbus_read_byte_data(max8893->client, MAX8893_ONOFF);
+ if (ret < 0) {
+ dev_err(&rdev->dev, "%s: i2c read failed\n", __func__);
+ goto err;
+ }
+ val = ret;
+
+ if (enable)
+ val |= desc->mask;
+ else
+ val &= ~desc->mask;
+
+ ret = i2c_smbus_write_byte_data(max8893->client, MAX8893_ONOFF, val);
+ if (ret) {
+ dev_err(&rdev->dev, "%s: i2c write failed\n", __func__);
+ goto err;
+ }
+ mutex_unlock(&max8893->lock);
+err:
+ return ret;
+}
+
+static int max8893_enable(struct regulator_dev *rdev)
+{
+ return max8893_onoff(rdev, true);
+}
+
+static int max8893_disable(struct regulator_dev *rdev)
+{
+ return max8893_onoff(rdev, false);
+}
+
+static int max8893_is_enabled(struct regulator_dev *rdev)
+{
+ struct max8893 *max8893 = rdev_get_drvdata(rdev);
+ struct max8893_desc *desc = rdev_get_max8893_desc(rdev);
+ int val;
+
+ val = i2c_smbus_read_byte_data(max8893->client, MAX8893_ONOFF);
+ if (val < 0) {
+ dev_err(&rdev->dev, "%s: i2c read failed\n", __func__);
+ return val;
+ }
+
+ return !!(val & desc->mask);
+}
+
+static int max8893_list(struct regulator_dev *rdev, unsigned selector)
+{
+ struct max8893_desc *desc = rdev_get_max8893_desc(rdev);
+ if (selector >= desc->desc.n_voltages)
+ return -EINVAL;
+ return desc->min_uV + selector * MAX8893_STEP;
+}
+
+static int max8893_set(struct regulator_dev *rdev, int min_uV, int max_uV,
+ unsigned *selectorp)
+{
+ struct max8893 *max8893 = rdev_get_drvdata(rdev);
+ struct max8893_desc *desc = rdev_get_max8893_desc(rdev);
+ int id = rdev_get_id(rdev);
+ int rmax_uV = desc->min_uV + (desc->desc.n_voltages - 1) * MAX8893_STEP;
+ u8 selector;
+ int ret;
+
+ if (min_uV > rmax_uV)
+ return -EINVAL;
+ if (max_uV < desc->min_uV)
+ return -EINVAL;
+
+ if (min_uV < desc->min_uV)
+ min_uV = desc->min_uV;
+ if (max_uV > rmax_uV)
+ max_uV = rmax_uV;
+
+ selector = DIV_ROUND_UP(min_uV - desc->min_uV, MAX8893_STEP);
+
+ ret = max8893_list(rdev, selector);
+ if (ret < 0 || ret > max_uV)
+ return -EINVAL;
+
+ ret = i2c_smbus_write_byte_data(max8893->client,
+ MAX8893_VOLTAGE_BASE + id, selector);
+ if (ret) {
+ dev_err(&rdev->dev, "%s: i2c write failed\n", __func__);
+ return ret;
+ }
+ *selectorp = selector;
+
+ return 0;
+}
+
+static int max8893_get(struct regulator_dev *rdev)
+{
+ struct max8893 *max8893 = rdev_get_drvdata(rdev);
+ struct max8893_desc *desc = rdev_get_max8893_desc(rdev);
+ int id = rdev_get_id(rdev);
+ int selector;
+
+ selector = i2c_smbus_read_byte_data(max8893->client,
+ MAX8893_VOLTAGE_BASE + id);
+ if (selector < 0) {
+ dev_err(&rdev->dev, "%s: i2c read failed\n", __func__);
+ return selector;
+ }
+ return desc->min_uV + selector * MAX8893_STEP;
+}
+
+static struct regulator_ops max8893_ops = {
+ .enable = max8893_enable,
+ .disable = max8893_disable,
+ .is_enabled = max8893_is_enabled,
+ .list_voltage = max8893_list,
+ .set_voltage = max8893_set,
+ .get_voltage = max8893_get,
+};
+
+static struct max8893_desc max8893_reg[] = {
+ {
+ .desc = {
+ .name = "BUCK",
+ .id = MAX8893_BUCK,
+ .ops = &max8893_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = 0x10 + 1,
+ .owner = THIS_MODULE,
+ },
+ .mask = BIT(7),
+ .min_uV = 800000,
+ },
+ {
+ .desc = {
+ .name = "LDO1",
+ .id = MAX8893_LDO1,
+ .ops = &max8893_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = 0x11 + 1,
+ .owner = THIS_MODULE,
+ },
+ .mask = BIT(5),
+ .min_uV = 1600000,
+ },
+ {
+ .desc = {
+ .name = "LDO2",
+ .id = MAX8893_LDO2,
+ .ops = &max8893_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = 0x15 + 1,
+ .owner = THIS_MODULE,
+ },
+ .mask = BIT(4),
+ .min_uV = 1200000,
+ },
+ {
+ .desc = {
+ .name = "LDO3",
+ .id = MAX8893_LDO3,
+ .ops = &max8893_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = 0x11 + 1,
+ .owner = THIS_MODULE,
+ },
+ .mask = BIT(3),
+ .min_uV = 1600000,
+ },
+ {
+ .desc = {
+ .name = "LDO4",
+ .id = MAX8893_LDO4,
+ .ops = &max8893_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = 0x19 + 1,
+ .owner = THIS_MODULE,
+ },
+ .mask = BIT(2),
+ .min_uV = 800000,
+ },
+ {
+ .desc = {
+ .name = "LDO5",
+ .id = MAX8893_LDO5,
+ .ops = &max8893_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = 0x19 + 1,
+ .owner = THIS_MODULE,
+ },
+ .mask = BIT(1),
+ .min_uV = 800000,
+ },
+};
+
+
+static int __devinit max8893_probe(struct i2c_client *client,
+ const struct i2c_device_id *i2c_id)
+{
+ struct regulator_dev **rdev;
+ struct max8893_platform_data *pdata = client->dev.platform_data;
+ struct max8893 *max8893;
+ int i, id, ret = -EINVAL;
+
+ if (pdata->num_subdevs > MAX8893_END) {
+ dev_err(&client->dev, "Too many regulators found!\n");
+ goto out;
+ }
+
+ max8893 = kzalloc(sizeof(struct max8893) +
+ sizeof(struct regulator_dev *) * MAX8893_END,
+ GFP_KERNEL);
+ if (!max8893) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ mutex_init(&max8893->lock);
+ max8893->client = client;
+ rdev = max8893->rdev;
+
+ /* Finally register devices */
+ for (i = 0; i < pdata->num_subdevs; i++) {
+
+ id = pdata->subdevs[i].id;
+
+ rdev[i] = regulator_register(&max8893_reg[id].desc,
+ &client->dev,
+ pdata->subdevs[i].initdata,
+ max8893);
+ if (IS_ERR(rdev[i])) {
+ ret = PTR_ERR(rdev[i]);
+ dev_err(&client->dev, "failed to register %s\n",
+ max8893_reg[id].desc.name);
+ goto err_unregister;
+ }
+ }
+
+ i2c_set_clientdata(client, max8893);
+ dev_info(&client->dev, "Maxim 8893 regulator driver loaded\n");
+ return 0;
+
+err_unregister:
+ while (--i >= 0)
+ regulator_unregister(rdev[i]);
+
+ kfree(max8893);
+out:
+ return ret;
+}
+
+static int __devexit max8893_remove(struct i2c_client *client)
+{
+ struct max8893 *max8893 = i2c_get_clientdata(client);
+ struct regulator_dev **rdev = max8893->rdev;
+ int i;
+
+ for (i = 0; i < MAX8893_END; i++)
+ if (rdev[i])
+ regulator_unregister(rdev[i]);
+ mutex_destroy(&max8893->lock);
+ kfree(max8893);
+
+ return 0;
+}
+
+static const struct i2c_device_id max8893_id[] = {
+ { "max8893", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, max8893_id);
+
+static struct i2c_driver max8893_driver = {
+ .probe = max8893_probe,
+ .remove = __devexit_p(max8893_remove),
+ .driver = {
+ .name = "max8893",
+ .owner = THIS_MODULE,
+ },
+ .id_table = max8893_id,
+};
+
+static int __init max8893_init(void)
+{
+ return i2c_add_driver(&max8893_driver);
+}
+subsys_initcall(max8893_init);
+
+static void __exit max8893_exit(void)
+{
+ i2c_del_driver(&max8893_driver);
+}
+module_exit(max8893_exit);
+
diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c
index ad6628c..a8fb668 100644
--- a/drivers/regulator/max8997.c
+++ b/drivers/regulator/max8997.c
@@ -688,7 +688,7 @@ static int max8997_set_voltage_buck(struct regulator_dev *rdev,
}
new_val++;
- } while (desc->min + desc->step + new_val <= desc->max);
+ } while (desc->min + desc->step * new_val <= desc->max);
new_idx = tmp_idx;
new_val = tmp_val;
diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c
index 41a1495..967e3c2 100644
--- a/drivers/regulator/max8998.c
+++ b/drivers/regulator/max8998.c
@@ -44,6 +44,7 @@ struct max8998_data {
unsigned int buck1_idx; /* index to last changed voltage */
/* value in a set */
unsigned int buck2_idx;
+ unsigned int gpio_reset_val;
};
struct voltage_map_desc {
@@ -112,6 +113,19 @@ static const struct voltage_map_desc *ldo_voltage_map[] = {
&buck4_voltage_map_desc, /* BUCK4 */
};
+/*
+ * Map ordinal values of increasing voltages to BUCK1_DVSARM registers
+ * using Gray code, to allow the 2 set GPIOs to be individually
+ * modified without temporarily lowering voltage out of spec and
+ * without temporarily moving voltage in the wrong direction. The
+ * four voltages are indexed from 0-3 in increasing voltage value,
+ * but are actually assigned to BUCK1_DVSARMn registers using
+ * ordering {0,1,3,2} when default Buck1 is 0 or 1,
+ * {1,0,2,3} when default Buck1 is 2 or 3.
+ */
+
+#define DVSARMREG(index) ((index ^ (index >> 1)) ^ ((pdata->buck1_default_idx & 0x2) >> 1))
+
static inline int max8998_get_ldo(struct regulator_dev *rdev)
{
return rdev_get_id(rdev);
@@ -342,17 +356,23 @@ static int max8998_set_voltage_ldo(struct regulator_dev *rdev,
return ret;
}
-static inline void buck1_gpio_set(int gpio1, int gpio2, int v)
+static inline void buck1_gpio_set(int gpio1, int gpio2, int v, int w)
{
- gpio_set_value(gpio1, v & 0x1);
+ if ((v & 1) == !w)
+ gpio_set_value(gpio1, !w);
+
gpio_set_value(gpio2, (v >> 1) & 0x1);
-}
+ if ((v & 1) != !w)
+ gpio_set_value(gpio1, w);
+
+}
static inline void buck2_gpio_set(int gpio, int v)
{
gpio_set_value(gpio, v & 0x1);
}
+
static int max8998_set_voltage_buck(struct regulator_dev *rdev,
int min_uV, int max_uV, unsigned *selector)
{
@@ -364,9 +384,8 @@ static int max8998_set_voltage_buck(struct regulator_dev *rdev,
const struct voltage_map_desc *desc;
int buck = max8998_get_ldo(rdev);
int reg, shift = 0, mask, ret;
- int difference = 0, i = 0, j = 0, previous_vol = 0;
+ int difference = 0, i = 0, j = 0, previous_vol = 0, previous_idx = 0;
u8 val = 0;
- static u8 buck1_last_val;
if (buck >= ARRAY_SIZE(ldo_voltage_map))
return -EINVAL;
@@ -405,10 +424,10 @@ static int max8998_set_voltage_buck(struct regulator_dev *rdev,
switch (buck) {
case MAX8998_BUCK1:
dev_dbg(max8998->dev,
- "BUCK1, i:%d, buck1_vol1:%d, buck1_vol2:%d\n"
- "buck1_vol3:%d, buck1_vol4:%d\n",
- i, max8998->buck1_vol[0], max8998->buck1_vol[1],
- max8998->buck1_vol[2], max8998->buck1_vol[3]);
+ "BUCK1, i:%d, buck1_vol1:%d, buck1_vol2:%d\n\
+ buck1_vol3:%d, buck1_vol4:%d\n",
+ i, max8998->buck1_vol[DVSARMREG(0)], max8998->buck1_vol[DVSARMREG(1)],
+ max8998->buck1_vol[DVSARMREG(2)], max8998->buck1_vol[DVSARMREG(3)]);
if (gpio_is_valid(pdata->buck1_set1) &&
gpio_is_valid(pdata->buck1_set2)) {
@@ -416,10 +435,10 @@ static int max8998_set_voltage_buck(struct regulator_dev *rdev,
/* check if requested voltage */
/* value is already defined */
for (j = 0; j < ARRAY_SIZE(max8998->buck1_vol); j++) {
- if (max8998->buck1_vol[j] == i) {
- max8998->buck1_idx = j;
- buck1_gpio_set(pdata->buck1_set1,
- pdata->buck1_set2, j);
+ if (max8998->buck1_vol[DVSARMREG(j)] == i) {
+ buck1_gpio_set(pdata->buck1_set1, pdata->buck1_set2, DVSARMREG(j), max8998->gpio_reset_val);
+ max8998->buck1_idx = DVSARMREG(j);
+ dev_dbg(max8998->dev, "buck1_level=%d, buck1_index=%d \n", j, DVSARMREG(j));
goto buck1_exit;
}
}
@@ -427,18 +446,73 @@ static int max8998_set_voltage_buck(struct regulator_dev *rdev,
if (pdata->buck_voltage_lock)
return -EINVAL;
- /* no predefine regulator found */
- max8998->buck1_idx = (buck1_last_val % 2) + 2;
+ /* No predefine regulator found
+ * Once we reach here,
+ * all remaining predefined voltage is cleared,
+ * and two buck1_idx 0 and 1 are used as now.
+ */
+ previous_idx = max8998->buck1_idx;
+ if (previous_idx == 0) {
+ max8998->buck1_idx = 1;
+ } else if (previous_idx == 1) {
+ max8998->buck1_idx = 0;
+ } else {
+ /* change possible intermediate level */
+ val = max8998->buck1_vol[max8998->buck1_idx];
+ if (previous_idx == 2) {
+ max8998->buck1_idx = 3;
+ } else if (previous_idx == 3) {
+ max8998->buck1_idx = 2;
+ }
+ ret = max8998_get_voltage_register(rdev, &reg, &shift, &mask);
+ if (ret) {
+ max8998->buck1_idx = previous_idx;
+ return ret;
+ }
+ ret = max8998_write_reg(i2c, reg, val);
+ if (ret) {
+ max8998->buck1_vol[max8998->buck1_idx] = 0;
+ max8998->buck1_idx = previous_idx;
+ return ret;
+ }
+
+ /* set index 1 with current voltage */
+ max8998->buck1_idx = 1;
+ ret = max8998_get_voltage_register(rdev, &reg, &shift, &mask);
+ if (ret) {
+ max8998->buck1_idx = previous_idx;
+ return ret;
+ }
+ ret = max8998_write_reg(i2c, reg, val);
+ if (ret) {
+ max8998->buck1_vol[max8998->buck1_idx] = 0;
+ max8998->buck1_idx = previous_idx;
+ return ret;
+ }
+ buck1_gpio_set(pdata->buck1_set1, pdata->buck1_set2, max8998->buck1_idx, max8998->gpio_reset_val);
+
+ /*Now, change to index 0*/
+ previous_idx = 1;
+ max8998->buck1_idx = 0;
+ }
dev_dbg(max8998->dev, "max8998->buck1_idx:%d\n",
max8998->buck1_idx);
max8998->buck1_vol[max8998->buck1_idx] = i;
- ret = max8998_get_voltage_register(rdev, &reg,
- &shift,
- &mask);
+ ret = max8998_get_voltage_register(rdev, &reg, &shift, &mask);
+ if (ret) {
+ max8998->buck1_idx = previous_idx;
+ return ret;
+ }
ret = max8998_write_reg(i2c, reg, i);
- buck1_gpio_set(pdata->buck1_set1,
- pdata->buck1_set2, max8998->buck1_idx);
- buck1_last_val++;
+ if (ret) {
+ max8998->buck1_vol[max8998->buck1_idx] = 0;
+ max8998->buck1_idx = previous_idx;
+ return ret;
+ }
+ buck1_gpio_set(pdata->buck1_set1, pdata->buck1_set2, max8998->buck1_idx, max8998->gpio_reset_val);
+ for (j = 2; j < 4; j++)
+ max8998->buck1_vol[j] = 0;
+
buck1_exit:
dev_dbg(max8998->dev, "%s: SET1:%d, SET2:%d\n",
i2c->name, gpio_get_value(pdata->buck1_set1),
@@ -693,7 +767,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
struct regulator_dev **rdev;
struct max8998_data *max8998;
struct i2c_client *i2c;
- int i, ret, size;
+ int i, j, ret, size;
if (!pdata) {
dev_err(pdev->dev.parent, "No platform init data supplied\n");
@@ -718,16 +792,62 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, max8998);
i2c = max8998->iodev->i2c;
- max8998->buck1_idx = pdata->buck1_default_idx;
+ max8998->buck1_idx = DVSARMREG(pdata->buck1_default_idx);
max8998->buck2_idx = pdata->buck2_default_idx;
+ max8998->gpio_reset_val = (pdata->buck1_default_idx & 0x2) >> 1;
+
- /* NOTE: */
- /* For unused GPIO NOT marked as -1 (thereof equal to 0) WARN_ON */
- /* will be displayed */
/* Check if MAX8998 voltage selection GPIOs are defined */
if (gpio_is_valid(pdata->buck1_set1) &&
gpio_is_valid(pdata->buck1_set2)) {
+ /*
+ * Calculate register value of voltage
+ */
+ for (j = 0; j < 4; j++) {
+ int buck_vol;
+ switch (j) {
+ case 3:
+ buck_vol = pdata->buck1_voltage4;
+ break;
+ case 2:
+ buck_vol = pdata->buck1_voltage3;
+ break;
+ case 1:
+ buck_vol = pdata->buck1_voltage2;
+ break;
+ default:
+ buck_vol = pdata->buck1_voltage1;
+ break;
+ }
+ /* Set predefined value for BUCK1-4 registers */
+ i = 0;
+ while (buck12_voltage_map_desc.min +
+ buck12_voltage_map_desc.step*i
+ < (buck_vol / 1000))
+ i++;
+ max8998->buck1_vol[DVSARMREG(j)] = i;
+ }
+
+ /*
+ * Reset all PMIC DVSARM1-4 registers to initial request value
+ * By this, voltage drop will not happen with garbage gpio at bootup time
+ */
+ for (j = 0; j < 4; j++) {
+ ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE1 + DVSARMREG(j),
+ max8998->buck1_vol[max8998->buck1_idx]);
+ if (ret) {
+ max8998->buck1_vol[0] = 0;
+ max8998->buck1_vol[1] = 0;
+ max8998->buck1_vol[2] = 0;
+ max8998->buck1_vol[3] = 0;
+ goto err_free_mem;
+ }
+ }
+
+ /*
+ * Set initial gpio
+ */
/* Check if SET1 is not equal to 0 */
if (!pdata->buck1_set1) {
printk(KERN_ERR "MAX8998 SET1 GPIO defined as 0 !\n");
@@ -747,61 +867,55 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
gpio_direction_output(pdata->buck1_set1,
max8998->buck1_idx & 0x1);
-
gpio_request(pdata->buck1_set2, "MAX8998 BUCK1_SET2");
gpio_direction_output(pdata->buck1_set2,
(max8998->buck1_idx >> 1) & 0x1);
- /* Set predefined value for BUCK1 register 1 */
- i = 0;
- while (buck12_voltage_map_desc.min +
- buck12_voltage_map_desc.step*i
- < (pdata->buck1_voltage1 / 1000))
- i++;
- max8998->buck1_vol[0] = i;
- ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE1, i);
- if (ret)
- goto err_free_mem;
- /* Set predefined value for BUCK1 register 2 */
- i = 0;
- while (buck12_voltage_map_desc.min +
- buck12_voltage_map_desc.step*i
- < (pdata->buck1_voltage2 / 1000))
- i++;
+ /*
+ * Write specified voltage to pmic registers
+ */
+ for (j = 0; j < 4; j++) {
+
+ ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE1 + DVSARMREG(j),
+ max8998->buck1_vol[DVSARMREG(j)]);
+ if (ret) {
+ max8998->buck1_vol[0] = 0;
+ max8998->buck1_vol[1] = 0;
+ max8998->buck1_vol[2] = 0;
+ max8998->buck1_vol[3] = 0;
+ goto err_free_mem;
+ }
+ dev_dbg(max8998->dev, "PMIC probe: index=%d, Gray coded index=%d, reg val=%d\n",
+ j, DVSARMREG(j), max8998->buck1_vol[DVSARMREG(j)]);
- max8998->buck1_vol[1] = i;
- ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE2, i);
- if (ret)
- goto err_free_mem;
+ }
+ }
+
+ if (gpio_is_valid(pdata->buck2_set3)) {
- /* Set predefined value for BUCK1 register 3 */
+ /* Calculate buck2 vol1 and vol2 register value for specified voltage */
i = 0;
while (buck12_voltage_map_desc.min +
buck12_voltage_map_desc.step*i
- < (pdata->buck1_voltage3 / 1000))
+ < (pdata->buck2_voltage1 / 1000))
i++;
-
- max8998->buck1_vol[2] = i;
- ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE3, i);
- if (ret)
- goto err_free_mem;
-
- /* Set predefined value for BUCK1 register 4 */
+ max8998->buck2_vol[0] = i;
i = 0;
while (buck12_voltage_map_desc.min +
buck12_voltage_map_desc.step*i
- < (pdata->buck1_voltage4 / 1000))
+ < (pdata->buck2_voltage2 / 1000))
i++;
+ printk(KERN_ERR "i2:%d, buck2_idx:%d\n", i, max8998->buck2_idx);
+ max8998->buck2_vol[1] = i;
- max8998->buck1_vol[3] = i;
- ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE4, i);
+ /* Reset pmic registers with default voltage */
+ ret = max8998_write_reg(i2c,
+ max8998->buck2_idx ? MAX8998_REG_BUCK2_VOLTAGE2 : MAX8998_REG_BUCK2_VOLTAGE1,
+ max8998->buck2_vol[max8998->buck2_idx]);
if (ret)
goto err_free_mem;
- }
-
- if (gpio_is_valid(pdata->buck2_set3)) {
- /* Check if SET3 is not equal to 0 */
+ /* Check if SET3 is not equal to 0 and set default gpio */
if (!pdata->buck2_set3) {
printk(KERN_ERR "MAX8998 SET3 GPIO defined as 0 !\n");
WARN_ON(!pdata->buck2_set3);
@@ -812,28 +926,18 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
gpio_direction_output(pdata->buck2_set3,
max8998->buck2_idx & 0x1);
- /* BUCK2 register 1 */
- i = 0;
- while (buck12_voltage_map_desc.min +
- buck12_voltage_map_desc.step*i
- < (pdata->buck2_voltage1 / 1000))
- i++;
- max8998->buck2_vol[0] = i;
- ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE1, i);
- if (ret)
- goto err_free_mem;
- /* BUCK2 register 2 */
- i = 0;
- while (buck12_voltage_map_desc.min +
- buck12_voltage_map_desc.step*i
- < (pdata->buck2_voltage2 / 1000))
- i++;
- printk(KERN_ERR "i2:%d, buck2_idx:%d\n", i, max8998->buck2_idx);
- max8998->buck2_vol[1] = i;
- ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE2, i);
- if (ret)
- goto err_free_mem;
+ /* Set BUCK2 pmic register with predefined value */
+ if (max8998->buck2_idx) {
+ ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE1, max8998->buck2_vol[0]);
+ if (ret)
+ goto err_free_mem;
+ } else {
+ ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE2, max8998->buck2_vol[1]);
+ if (ret)
+ goto err_free_mem;
+ }
+
}
for (i = 0; i < pdata->num_regulators; i++) {
@@ -862,7 +966,6 @@ err:
for (i = 0; i < max8998->num_regulators; i++)
if (rdev[i])
regulator_unregister(rdev[i]);
-
err_free_mem:
kfree(max8998->rdev);
kfree(max8998);
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 7d27958..d6795cd 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -91,7 +91,7 @@ obj-$(CONFIG_RTC_DRV_RV3029C2) += rtc-rv3029c2.o
obj-$(CONFIG_RTC_DRV_RX8025) += rtc-rx8025.o
obj-$(CONFIG_RTC_DRV_RX8581) += rtc-rx8581.o
obj-$(CONFIG_RTC_DRV_S35390A) += rtc-s35390a.o
-obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o
+obj-$(CONFIG_RTC_DRV_S3C) += rtc-max8998.o rtc-s3c.o
obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o
obj-$(CONFIG_RTC_DRV_SH) += rtc-sh.o
obj-$(CONFIG_RTC_DRV_SPEAR) += rtc-spear.o
diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c
index 2dd3c01..d007609 100644
--- a/drivers/rtc/rtc-imxdi.c
+++ b/drivers/rtc/rtc-imxdi.c
@@ -391,6 +391,8 @@ static int dryice_rtc_probe(struct platform_device *pdev)
if (imxdi->ioaddr == NULL)
return -ENOMEM;
+ spin_lock_init(&imxdi->irq_lock);
+
imxdi->irq = platform_get_irq(pdev, 0);
if (imxdi->irq < 0)
return imxdi->irq;
diff --git a/drivers/rtc/rtc-max8998.c b/drivers/rtc/rtc-max8998.c
index 2e48aa6..f83dfdc 100644
--- a/drivers/rtc/rtc-max8998.c
+++ b/drivers/rtc/rtc-max8998.c
@@ -90,7 +90,7 @@ static void max8998_data_to_tm(u8 *data, struct rtc_time *tm)
tm->tm_wday = data[RTC_WEEKDAY] & 0x07;
tm->tm_mday = bcd2bin(data[RTC_DATE]);
- tm->tm_mon = bcd2bin(data[RTC_MONTH]);
+ tm->tm_mon = bcd2bin(data[RTC_MONTH]) - 1;
tm->tm_year = bcd2bin(data[RTC_YEAR1]) + bcd2bin(data[RTC_YEAR2]) * 100;
tm->tm_year -= 1900;
}
@@ -102,7 +102,7 @@ static void max8998_tm_to_data(struct rtc_time *tm, u8 *data)
data[RTC_HOUR] = bin2bcd(tm->tm_hour);
data[RTC_WEEKDAY] = tm->tm_wday;
data[RTC_DATE] = bin2bcd(tm->tm_mday);
- data[RTC_MONTH] = bin2bcd(tm->tm_mon);
+ data[RTC_MONTH] = bin2bcd(tm->tm_mon + 1);
data[RTC_YEAR1] = bin2bcd(tm->tm_year % 100);
data[RTC_YEAR2] = bin2bcd((tm->tm_year + 1900) / 100);
}
@@ -232,6 +232,7 @@ static int max8998_rtc_alarm_irq_enable(struct device *dev,
return max8998_rtc_stop_alarm(info);
}
+#ifdef CONFIG_RTC_DRV_MAX8998
static irqreturn_t max8998_rtc_alarm_irq(int irq, void *data)
{
struct max8998_rtc_info *info = data;
@@ -240,6 +241,36 @@ static irqreturn_t max8998_rtc_alarm_irq(int irq, void *data)
return IRQ_HANDLED;
}
+#endif
+
+static struct device *max8998_rtc_dev;
+int max8998_rtc_read_time_hack(struct rtc_time *tm)
+{
+ int ret;
+
+ pr_debug("%s \n", __func__);
+
+ if (WARN_ON(!max8998_rtc_dev))
+ return -ENODEV;
+
+ ret = max8998_rtc_read_time(max8998_rtc_dev, tm);
+
+ pr_debug("read %s time %02d.%02d.%02d %02d/%02d/%02d\n",__func__,
+ tm->tm_year, tm->tm_mon, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+ return ret;
+}
+
+int max8998_rtc_set_time_hack(struct rtc_time *tm)
+{
+ if (WARN_ON(!max8998_rtc_dev))
+ return -ENODEV;
+
+ pr_debug("%s %02d.%02d.%02d %02d/%02d/%02d\n",__func__,
+ tm->tm_year, tm->tm_mon, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+ return max8998_rtc_set_time(max8998_rtc_dev, tm);
+}
static const struct rtc_class_ops max8998_rtc_ops = {
.read_time = max8998_rtc_read_time,
@@ -267,6 +298,11 @@ static int __devinit max8998_rtc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, info);
+ /*
+ * Hack to disable the max8998 rtc interface when used only by the
+ * s3c rtc driver.
+ */
+#ifdef CONFIG_RTC_DRV_MAX8998
info->rtc_dev = rtc_device_register("max8998-rtc", &pdev->dev,
&max8998_rtc_ops, THIS_MODULE);
@@ -282,6 +318,7 @@ static int __devinit max8998_rtc_probe(struct platform_device *pdev)
if (ret < 0)
dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
info->irq, ret);
+#endif
dev_info(&pdev->dev, "RTC CHIP NAME: %s\n", pdev->id_entry->name);
if (pdata->rtc_delay) {
@@ -290,9 +327,13 @@ static int __devinit max8998_rtc_probe(struct platform_device *pdev)
" RTC updates will be extremely slow.\n");
}
+ max8998_rtc_dev = info->dev;
+
return 0;
+#ifdef CONFIG_RTC_DRV_MAX8998
out_rtc:
+#endif
platform_set_drvdata(pdev, NULL);
kfree(info);
return ret;
@@ -303,8 +344,11 @@ static int __devexit max8998_rtc_remove(struct platform_device *pdev)
struct max8998_rtc_info *info = platform_get_drvdata(pdev);
if (info) {
+ max8998_rtc_dev = NULL;
+#ifdef CONFIG_RTC_DRV_MAX8998
free_irq(info->irq, info);
rtc_device_unregister(info->rtc_dev);
+#endif
kfree(info);
}
diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c
index 39e41fb..5160354 100644
--- a/drivers/rtc/rtc-mxc.c
+++ b/drivers/rtc/rtc-mxc.c
@@ -191,10 +191,11 @@ static irqreturn_t mxc_rtc_interrupt(int irq, void *dev_id)
struct platform_device *pdev = dev_id;
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
void __iomem *ioaddr = pdata->ioaddr;
+ unsigned long flags;
u32 status;
u32 events = 0;
- spin_lock_irq(&pdata->rtc->irq_lock);
+ spin_lock_irqsave(&pdata->rtc->irq_lock, flags);
status = readw(ioaddr + RTC_RTCISR) & readw(ioaddr + RTC_RTCIENR);
/* clear interrupt sources */
writew(status, ioaddr + RTC_RTCISR);
@@ -217,7 +218,7 @@ static irqreturn_t mxc_rtc_interrupt(int irq, void *dev_id)
rtc_update_alarm(&pdev->dev, &pdata->g_rtc_alarm);
rtc_update_irq(pdata->rtc, 1, events);
- spin_unlock_irq(&pdata->rtc->irq_lock);
+ spin_unlock_irqrestore(&pdata->rtc->irq_lock, flags);
return IRQ_HANDLED;
}
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c
index e86edfc..1e80a48 100644
--- a/drivers/rtc/rtc-pl031.c
+++ b/drivers/rtc/rtc-pl031.c
@@ -312,6 +312,7 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id)
int ret;
struct pl031_local *ldata;
struct rtc_class_ops *ops = id->data;
+ unsigned long time;
ret = amba_request_regions(adev, NULL);
if (ret)
@@ -343,6 +344,23 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id)
writel(readl(ldata->base + RTC_CR) | RTC_CR_CWEN,
ldata->base + RTC_CR);
+ /*
+ * On ST PL031 variants, the RTC reset value does not provide correct
+ * weekday for 2000-01-01. Correct the erroneous sunday to saturday.
+ */
+ if (ldata->hw_designer == AMBA_VENDOR_ST) {
+ if (readl(ldata->base + RTC_YDR) == 0x2000) {
+ time = readl(ldata->base + RTC_DR);
+ if ((time &
+ (RTC_MON_MASK | RTC_MDAY_MASK | RTC_WDAY_MASK))
+ == 0x02120000) {
+ time = time | (0x7 << RTC_WDAY_SHIFT);
+ writel(0x2000, ldata->base + RTC_YLR);
+ writel(time, ldata->base + RTC_LR);
+ }
+ }
+ }
+
ldata->rtc = rtc_device_register("pl031", &adev->dev, ops,
THIS_MODULE);
if (IS_ERR(ldata->rtc)) {
diff --git a/drivers/rtc/rtc-rs5c348.c b/drivers/rtc/rtc-rs5c348.c
index 368d0e6..15e6d5c 100644
--- a/drivers/rtc/rtc-rs5c348.c
+++ b/drivers/rtc/rtc-rs5c348.c
@@ -121,9 +121,12 @@ rs5c348_rtc_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_min = bcd2bin(rxbuf[RS5C348_REG_MINS] & RS5C348_MINS_MASK);
tm->tm_hour = bcd2bin(rxbuf[RS5C348_REG_HOURS] & RS5C348_HOURS_MASK);
if (!pdata->rtc_24h) {
- tm->tm_hour %= 12;
- if (rxbuf[RS5C348_REG_HOURS] & RS5C348_BIT_PM)
+ if (rxbuf[RS5C348_REG_HOURS] & RS5C348_BIT_PM) {
+ tm->tm_hour -= 20;
+ tm->tm_hour %= 12;
tm->tm_hour += 12;
+ } else
+ tm->tm_hour %= 12;
}
tm->tm_wday = bcd2bin(rxbuf[RS5C348_REG_WDAY] & RS5C348_WDAY_MASK);
tm->tm_mday = bcd2bin(rxbuf[RS5C348_REG_DAY] & RS5C348_DAY_MASK);
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index 16512ec..e427256 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -20,18 +20,22 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
+#include <linux/device.h>
#include <linux/rtc.h>
#include <linux/bcd.h>
#include <linux/clk.h>
#include <linux/log2.h>
#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
#include <mach/hardware.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
#include <asm/irq.h>
+#include <asm/mach/time.h>
#include <plat/regs-rtc.h>
+#include "rtc-s3c.h"
+
enum s3c_cpu_type {
TYPE_S3C2410,
TYPE_S3C64XX,
@@ -51,6 +55,9 @@ static enum s3c_cpu_type s3c_rtc_cpu_type;
static DEFINE_SPINLOCK(s3c_rtc_pie_lock);
+static void s3c_rtc_enable(struct device *dev, int en);
+
+static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm);
/* IRQ Handlers */
static irqreturn_t s3c_rtc_alarmirq(int irq, void *id)
@@ -59,23 +66,23 @@ static irqreturn_t s3c_rtc_alarmirq(int irq, void *id)
rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF);
- if (s3c_rtc_cpu_type == TYPE_S3C64XX)
- writeb(S3C2410_INTP_ALM, s3c_rtc_base + S3C2410_INTP);
+ writeb(S3C2410_INTP_ALM, s3c_rtc_base + S3C2410_INTP);
return IRQ_HANDLED;
}
+#ifndef CONFIG_HRT_RTC
static irqreturn_t s3c_rtc_tickirq(int irq, void *id)
{
struct rtc_device *rdev = id;
rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF);
- if (s3c_rtc_cpu_type == TYPE_S3C64XX)
- writeb(S3C2410_INTP_TIC, s3c_rtc_base + S3C2410_INTP);
+ writeb(S3C2410_INTP_TIC, s3c_rtc_base + S3C2410_INTP);
return IRQ_HANDLED;
}
+#endif
/* Update control registers */
static int s3c_rtc_setaie(struct device *dev, unsigned int enabled)
@@ -106,7 +113,7 @@ static int s3c_rtc_setfreq(struct device *dev, int freq)
spin_lock_irq(&s3c_rtc_pie_lock);
if (s3c_rtc_cpu_type == TYPE_S3C2410) {
- tmp = readb(s3c_rtc_base + S3C2410_TICNT);
+ tmp = readw(s3c_rtc_base + S3C2410_TICNT);
tmp &= S3C2410_TICNT_ENABLE;
}
@@ -125,13 +132,20 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
unsigned int have_retried = 0;
void __iomem *base = s3c_rtc_base;
+ s3c_rtc_enable(dev, 1);
retry_get_time:
+ rtc_tm->tm_sec = readb(base + S3C2410_RTCSEC);
rtc_tm->tm_min = readb(base + S3C2410_RTCMIN);
rtc_tm->tm_hour = readb(base + S3C2410_RTCHOUR);
rtc_tm->tm_mday = readb(base + S3C2410_RTCDATE);
rtc_tm->tm_mon = readb(base + S3C2410_RTCMON);
+
+#if defined(CONFIG_CPU_S5PV210)
+ rtc_tm->tm_year = readl(base + S3C2410_RTCYEAR);
+#else
rtc_tm->tm_year = readb(base + S3C2410_RTCYEAR);
- rtc_tm->tm_sec = readb(base + S3C2410_RTCSEC);
+#endif
+
/* the only way to work out wether the system was mid-update
* when we read it is to check the second counter, and if it
@@ -142,6 +156,7 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
have_retried = 1;
goto retry_get_time;
}
+ s3c_rtc_enable(dev, 0);
pr_debug("read time %04d.%02d.%02d %02d:%02d:%02d\n",
1900 + rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday,
@@ -152,9 +167,14 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour);
rtc_tm->tm_mday = bcd2bin(rtc_tm->tm_mday);
rtc_tm->tm_mon = bcd2bin(rtc_tm->tm_mon);
+#if defined(CONFIG_CPU_S5PV210)
+ rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year & 0xff) +
+ bcd2bin(rtc_tm->tm_year >> 8) * 100;
+#else
rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year);
-
rtc_tm->tm_year += 100;
+#endif
+
rtc_tm->tm_mon -= 1;
return rtc_valid_tm(rtc_tm);
@@ -163,7 +183,12 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
{
void __iomem *base = s3c_rtc_base;
+#if defined(CONFIG_CPU_S5PV210)
+ int year = tm->tm_year;
+ int year100;
+#else
int year = tm->tm_year - 100;
+#endif
pr_debug("set time %04d.%02d.%02d %02d:%02d:%02d\n",
1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
@@ -171,17 +196,38 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
/* we get around y2k by simply not supporting it */
+
+#if defined(CONFIG_CPU_S5PV210)
+ if (year < 0 || year >= 1000) {
+ dev_err(dev, "rtc only supports 0~999 years\n");
+#else
if (year < 0 || year >= 100) {
dev_err(dev, "rtc only supports 100 years\n");
+#endif
return -EINVAL;
}
+ s3c_rtc_enable(dev, 1);
+
writeb(bin2bcd(tm->tm_sec), base + S3C2410_RTCSEC);
writeb(bin2bcd(tm->tm_min), base + S3C2410_RTCMIN);
writeb(bin2bcd(tm->tm_hour), base + S3C2410_RTCHOUR);
writeb(bin2bcd(tm->tm_mday), base + S3C2410_RTCDATE);
writeb(bin2bcd(tm->tm_mon + 1), base + S3C2410_RTCMON);
+
+#if defined(CONFIG_CPU_S5PV210)
+ year100 = year/100;
+ year = year%100;
+ year = bin2bcd(year) | ((bin2bcd(year100)) << 8);
+ year = (0x00000fff & year);
+ pr_debug("year %x\n", year);
+ writel(year, base + S3C2410_RTCYEAR);
+#else
writeb(bin2bcd(year), base + S3C2410_RTCYEAR);
+#endif
+ s3c_rtc_enable(dev, 0);
+
+ max8998_rtc_set_time_hack(tm);
return 0;
}
@@ -192,12 +238,21 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
void __iomem *base = s3c_rtc_base;
unsigned int alm_en;
+ s3c_rtc_enable(dev, 1);
+
alm_tm->tm_sec = readb(base + S3C2410_ALMSEC);
alm_tm->tm_min = readb(base + S3C2410_ALMMIN);
alm_tm->tm_hour = readb(base + S3C2410_ALMHOUR);
alm_tm->tm_mon = readb(base + S3C2410_ALMMON);
alm_tm->tm_mday = readb(base + S3C2410_ALMDATE);
+#if defined(CONFIG_CPU_S5PV210)
+ alm_tm->tm_year = readl(base + S3C2410_ALMYEAR);
+ alm_tm->tm_year = (0x00000fff & alm_tm->tm_year);
+#else
alm_tm->tm_year = readb(base + S3C2410_ALMYEAR);
+#endif
+
+ s3c_rtc_enable(dev, 0);
alm_en = readb(base + S3C2410_RTCALM);
@@ -238,10 +293,16 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
alm_tm->tm_mon = -1;
}
- if (alm_en & S3C2410_RTCALM_YEAREN)
+ if (alm_en & S3C2410_RTCALM_YEAREN) {
+#if defined(CONFIG_CPU_S5PV210)
+ alm_tm->tm_year = bcd2bin(alm_tm->tm_year & 0xff) +
+ bcd2bin(alm_tm->tm_year >> 8) * 100;
+#else
alm_tm->tm_year = bcd2bin(alm_tm->tm_year);
- else
+#endif
+ } else {
alm_tm->tm_year = -1;
+ }
return 0;
}
@@ -252,12 +313,21 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
void __iomem *base = s3c_rtc_base;
unsigned int alrm_en;
+#if defined(CONFIG_CPU_S5PV210)
+ int year = tm->tm_year;
+ int year100;
+#else
+ int year = tm->tm_year - 100;
+#endif
+
pr_debug("s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n",
alrm->enabled,
1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
+ s3c_rtc_enable(dev, 1);
+
alrm_en = readb(base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN;
writeb(0x00, base + S3C2410_RTCALM);
@@ -276,6 +346,35 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
writeb(bin2bcd(tm->tm_hour), base + S3C2410_ALMHOUR);
}
+ if (tm->tm_mday >= 0) {
+ alrm_en |= S3C2410_RTCALM_DAYEN;
+ writeb(bin2bcd(tm->tm_mday), base + S3C2410_ALMDATE);
+ }
+
+ if (tm->tm_mon < 13 && tm->tm_mon >= 0) {
+ alrm_en |= S3C2410_RTCALM_MONEN;
+ writeb(bin2bcd(tm->tm_mon + 1), base + S3C2410_ALMMON);
+ }
+
+#if defined(CONFIG_CPU_S5PV210)
+ if (year < 1000 && year >= 0) {
+ alrm_en |= S3C2410_RTCALM_YEAREN;
+ year100 = year/100;
+ year = year%100;
+ year = bin2bcd(year) | ((bin2bcd(year100)) << 8);
+ year = (0x00000fff & year);
+ pr_debug("year %x\n", year);
+ writel(year, base + S3C2410_ALMYEAR);
+ }
+#else
+ if (year < 100 && year >= 0) {
+ alrm_en |= S3C2410_RTCALM_YEAREN;
+ writeb(bin2bcd(year), base + S3C2410_ALMYEAR);
+ }
+#endif
+
+ s3c_rtc_enable(dev, 0);
+
pr_debug("setting S3C2410_RTCALM to %08x\n", alrm_en);
writeb(alrm_en, base + S3C2410_RTCALM);
@@ -287,17 +386,10 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)
{
- unsigned int ticnt;
+ unsigned int ticnt = readw(s3c_rtc_base + S3C2410_TICNT);
- if (s3c_rtc_cpu_type == TYPE_S3C64XX) {
- ticnt = readw(s3c_rtc_base + S3C2410_RTCCON);
- ticnt &= S3C64XX_RTCCON_TICEN;
- } else {
- ticnt = readb(s3c_rtc_base + S3C2410_TICNT);
- ticnt &= S3C2410_TICNT_ENABLE;
- }
-
- seq_printf(seq, "periodic_IRQ\t: %s\n", ticnt ? "yes" : "no");
+ seq_printf(seq, "periodic_IRQ\t: %s\n",
+ (ticnt & S3C2410_TICNT_ENABLE) ? "yes" : "no");
return 0;
}
@@ -315,6 +407,7 @@ static int s3c_rtc_open(struct device *dev)
return ret;
}
+#ifndef CONFIG_HRT_RTC
ret = request_irq(s3c_rtc_tickno, s3c_rtc_tickirq,
IRQF_DISABLED, "s3c2410-rtc tick", rtc_dev);
@@ -322,12 +415,15 @@ static int s3c_rtc_open(struct device *dev)
dev_err(dev, "IRQ%d error %d\n", s3c_rtc_tickno, ret);
goto tick_err;
}
+#endif
return ret;
+#ifndef CONFIG_HRT_RTC
tick_err:
free_irq(s3c_rtc_alarmno, rtc_dev);
return ret;
+#endif
}
static void s3c_rtc_release(struct device *dev)
@@ -335,10 +431,14 @@ static void s3c_rtc_release(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
struct rtc_device *rtc_dev = platform_get_drvdata(pdev);
+#ifndef CONFIG_HRT_RTC
/* do not clear AIE here, it may be needed for wake */
free_irq(s3c_rtc_alarmno, rtc_dev);
free_irq(s3c_rtc_tickno, rtc_dev);
+#endif
+ free_irq(s3c_rtc_alarmno, rtc_dev);
+
}
static const struct rtc_class_ops s3c_rtcops = {
@@ -352,7 +452,7 @@ static const struct rtc_class_ops s3c_rtcops = {
.alarm_irq_enable = s3c_rtc_setaie,
};
-static void s3c_rtc_enable(struct platform_device *pdev, int en)
+static void s3c_rtc_enable(struct device *dev, int en)
{
void __iomem *base = s3c_rtc_base;
unsigned int tmp;
@@ -362,21 +462,17 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en)
if (!en) {
tmp = readw(base + S3C2410_RTCCON);
- if (s3c_rtc_cpu_type == TYPE_S3C64XX)
- tmp &= ~S3C64XX_RTCCON_TICEN;
- tmp &= ~S3C2410_RTCCON_RTCEN;
- writew(tmp, base + S3C2410_RTCCON);
-
- if (s3c_rtc_cpu_type == TYPE_S3C2410) {
- tmp = readb(base + S3C2410_TICNT);
- tmp &= ~S3C2410_TICNT_ENABLE;
- writeb(tmp, base + S3C2410_TICNT);
- }
+#ifdef CONFIG_HRT_RTC
+ writew(tmp & ~(S3C2410_RTCCON_RTCEN), base + S3C2410_RTCCON);
+#else
+ writew(tmp & ~(S3C2410_RTCCON_RTCEN | S3C_RTCCON_TICEN),
+ base + S3C2410_RTCCON);
+#endif /* CONFIG_HRT_RTC */
} else {
/* re-enable the device, and check it is ok */
if ((readw(base+S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0) {
- dev_info(&pdev->dev, "rtc disabled, re-enabling\n");
+ dev_info(dev, "rtc disabled, re-enabling\n");
tmp = readw(base + S3C2410_RTCCON);
writew(tmp | S3C2410_RTCCON_RTCEN,
@@ -384,7 +480,7 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en)
}
if ((readw(base + S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)) {
- dev_info(&pdev->dev, "removing RTCCON_CNTSEL\n");
+ dev_info(dev, "removing RTCCON_CNTSEL\n");
tmp = readw(base + S3C2410_RTCCON);
writew(tmp & ~S3C2410_RTCCON_CNTSEL,
@@ -392,7 +488,7 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en)
}
if ((readw(base + S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)) {
- dev_info(&pdev->dev, "removing RTCCON_CLKRST\n");
+ dev_info(dev, "removing RTCCON_CLKRST\n");
tmp = readw(base + S3C2410_RTCCON);
writew(tmp & ~S3C2410_RTCCON_CLKRST,
@@ -426,7 +522,13 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
struct rtc_device *rtc;
struct rtc_time rtc_tm;
struct resource *res;
+ unsigned char bcd_tmp, bcd_loop;
int ret;
+ struct rtc_time tm;
+ int year;
+#if defined(CONFIG_CPU_S5PV210)
+ int year100;
+#endif
pr_debug("%s: probe=%p\n", __func__, pdev);
@@ -484,41 +586,85 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
/* check to see if everything is setup correctly */
- s3c_rtc_enable(pdev, 1);
pr_debug("s3c2410_rtc: RTCCON=%02x\n",
readw(s3c_rtc_base + S3C2410_RTCCON));
+#ifdef CONFIG_PM
+ s3c_rtc_setfreq(&pdev->dev, 0);
+#else
+ s3c_rtc_setfreq(&pdev->dev, 1);
+#endif
device_init_wakeup(&pdev->dev, 1);
- /* register RTC and exit */
- rtc = rtc_device_register("s3c", &pdev->dev, &s3c_rtcops,
- THIS_MODULE);
+ s3c_rtc_cpu_type = platform_get_device_id(pdev)->driver_data;
- if (IS_ERR(rtc)) {
- dev_err(&pdev->dev, "cannot attach rtc\n");
- ret = PTR_ERR(rtc);
- goto err_nortc;
+ max8998_rtc_read_time_hack(&tm);
+
+ /* update time from pmic */
+
+
+#if defined(CONFIG_CPU_S5PV210)
+ year = tm.tm_year;
+#else
+ year = tm.tm_year - 100;
+#endif
+
+#if defined(CONFIG_CPU_S5PV210)
+ if (year < 0 || year >= 1000) {
+ dev_err(&pdev->dev, "rtc only supports 0 ~ 999 years\n");
+#else
+ if (year < 0 || year >= 100) {
+ dev_err(&pdev->dev, "rtc only supports 100 years\n");
+#endif
+ /* Set the default time. 2010:1:1:12:0:0 */
+ year = 110;
+ tm.tm_mon = 0;
+ tm.tm_mday = 1;
+ tm.tm_hour = 12;
+ tm.tm_min = 0;
+ tm.tm_sec = 0;
}
- s3c_rtc_cpu_type = platform_get_device_id(pdev)->driver_data;
+ s3c_rtc_enable(&pdev->dev, 1);
+
+ writeb(bin2bcd(tm.tm_sec), s3c_rtc_base + S3C2410_RTCSEC);
+ writeb(bin2bcd(tm.tm_min), s3c_rtc_base + S3C2410_RTCMIN);
+ writeb(bin2bcd(tm.tm_hour), s3c_rtc_base + S3C2410_RTCHOUR);
+ writeb(bin2bcd(tm.tm_mday), s3c_rtc_base + S3C2410_RTCDATE);
+ writeb(bin2bcd(tm.tm_mon + 1), s3c_rtc_base + S3C2410_RTCMON);
+
+#if defined(CONFIG_CPU_S5PV210)
+ year100 = year/100;
+ year = year%100;
+ year = bin2bcd(year) | ((bin2bcd(year100)) << 8);
+ year = (0x00000fff & year);
+ pr_debug("year %x\n", year);
+ writel(year, s3c_rtc_base + S3C2410_RTCYEAR);
+#else
+ writeb(bin2bcd(year), s3c_rtc_base + S3C2410_RTCYEAR);
+#endif
- /* Check RTC Time */
+ /* check rtc time */
+ for (bcd_loop = S3C2410_RTCSEC; bcd_loop <= S3C2410_RTCYEAR
+ ; bcd_loop += 0x4) {
+ bcd_tmp = readw(s3c_rtc_base + bcd_loop);
+ if (((bcd_tmp & 0xf) > 0x9) || ((bcd_tmp & 0xf0) > 0x90))
+ writew(0, s3c_rtc_base + bcd_loop);
+ }
- s3c_rtc_gettime(NULL, &rtc_tm);
+ s3c_rtc_enable(&pdev->dev, 0);
- if (rtc_valid_tm(&rtc_tm)) {
- rtc_tm.tm_year = 100;
- rtc_tm.tm_mon = 0;
- rtc_tm.tm_mday = 1;
- rtc_tm.tm_hour = 0;
- rtc_tm.tm_min = 0;
- rtc_tm.tm_sec = 0;
+ /* register RTC and exit */
- s3c_rtc_settime(NULL, &rtc_tm);
+ rtc = rtc_device_register("s3c", &pdev->dev, &s3c_rtcops,
+ THIS_MODULE);
- dev_warn(&pdev->dev, "warning: invalid RTC value so initializing it\n");
+ if (IS_ERR(rtc)) {
+ dev_err(&pdev->dev, "cannot attach rtc\n");
+ ret = PTR_ERR(rtc);
+ goto err_nortc;
}
if (s3c_rtc_cpu_type == TYPE_S3C64XX)
@@ -533,7 +679,6 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
return 0;
err_nortc:
- s3c_rtc_enable(pdev, 0);
clk_disable(rtc_clk);
clk_put(rtc_clk);
@@ -551,17 +696,15 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
/* RTC Power management control */
-static int ticnt_save, ticnt_en_save;
+static int ticnt_save;
static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state)
{
+ struct timespec time;
+
+ time.tv_nsec = 0;
/* save TICNT for anyone using periodic interrupts */
- ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT);
- if (s3c_rtc_cpu_type == TYPE_S3C64XX) {
- ticnt_en_save = readw(s3c_rtc_base + S3C2410_RTCCON);
- ticnt_en_save &= S3C64XX_RTCCON_TICEN;
- }
- s3c_rtc_enable(pdev, 0);
+ ticnt_save = readl(s3c_rtc_base + S3C2410_TICNT);
if (device_may_wakeup(&pdev->dev) && !wake_en) {
if (enable_irq_wake(s3c_rtc_alarmno) == 0)
@@ -575,14 +718,11 @@ static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state)
static int s3c_rtc_resume(struct platform_device *pdev)
{
- unsigned int tmp;
+ struct timespec time;
- s3c_rtc_enable(pdev, 1);
- writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT);
- if (s3c_rtc_cpu_type == TYPE_S3C64XX && ticnt_en_save) {
- tmp = readw(s3c_rtc_base + S3C2410_RTCCON);
- writew(tmp | ticnt_en_save, s3c_rtc_base + S3C2410_RTCCON);
- }
+ time.tv_nsec = 0;
+
+ writel(ticnt_save, s3c_rtc_base + S3C2410_TICNT);
if (device_may_wakeup(&pdev->dev) && wake_en) {
disable_irq_wake(s3c_rtc_alarmno);
@@ -621,7 +761,8 @@ static struct platform_driver s3c_rtc_driver = {
},
};
-static char __initdata banner[] = "S3C24XX RTC, (c) 2004,2006 Simtec Electronics\n";
+static char __initdata banner[] = "S3C24XX RTC, (c) 2004,2006 "
+ "Simtec Electronics\n";
static int __init s3c_rtc_init(void)
{
diff --git a/drivers/rtc/rtc-s3c.h b/drivers/rtc/rtc-s3c.h
new file mode 100644
index 0000000..9d86469
--- /dev/null
+++ b/drivers/rtc/rtc-s3c.h
@@ -0,0 +1,5 @@
+#ifndef _RTC_S3C_H_
+#define _RTC_S3C_H_
+extern int max8998_rtc_set_time_hack(struct rtc_time *tm);
+extern int max8998_rtc_read_time_hack(struct rtc_time *tm);
+#endif
diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c
index f9a2799..5e4e725 100644
--- a/drivers/rtc/rtc-twl.c
+++ b/drivers/rtc/rtc-twl.c
@@ -490,6 +490,11 @@ static int __devinit twl_rtc_probe(struct platform_device *pdev)
goto out2;
}
+ /* ensure interrupts are disabled, bootloaders can be strange */
+ ret = twl_rtc_write_u8(0, REG_RTC_INTERRUPTS_REG);
+ if (ret < 0)
+ dev_warn(&pdev->dev, "unable to disable interrupt\n");
+
/* init cached IRQ enable bits */
ret = twl_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG);
if (ret < 0)
diff --git a/drivers/rtc/rtc-wm831x.c b/drivers/rtc/rtc-wm831x.c
index bdc909b..f3c2110 100644
--- a/drivers/rtc/rtc-wm831x.c
+++ b/drivers/rtc/rtc-wm831x.c
@@ -24,7 +24,7 @@
#include <linux/mfd/wm831x/core.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
-
+#include <linux/random.h>
/*
* R16416 (0x4020) - RTC Write Counter
@@ -96,6 +96,26 @@ struct wm831x_rtc {
unsigned int alarm_enabled:1;
};
+static void wm831x_rtc_add_randomness(struct wm831x *wm831x)
+{
+ int ret;
+ u16 reg;
+
+ /*
+ * The write counter contains a pseudo-random number which is
+ * regenerated every time we set the RTC so it should be a
+ * useful per-system source of entropy.
+ */
+ ret = wm831x_reg_read(wm831x, WM831X_RTC_WRITE_COUNTER);
+ if (ret >= 0) {
+ reg = ret;
+ add_device_randomness(&reg, sizeof(reg));
+ } else {
+ dev_warn(wm831x->dev, "Failed to read RTC write counter: %d\n",
+ ret);
+ }
+}
+
/*
* Read current time and date in RTC
*/
@@ -449,6 +469,8 @@ static int wm831x_rtc_probe(struct platform_device *pdev)
alm_irq, ret);
}
+ wm831x_rtc_add_randomness(wm831x);
+
return 0;
err:
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 645b0fc..61da2cd 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -518,6 +518,7 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
rwlock_init(&port->unit_list_lock);
INIT_LIST_HEAD(&port->unit_list);
+ atomic_set(&port->units, 0);
INIT_WORK(&port->gid_pn_work, zfcp_fc_port_did_lookup);
INIT_WORK(&port->test_link_work, zfcp_fc_link_test_work);
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c
index e8b7cee..de1bcfa 100644
--- a/drivers/s390/scsi/zfcp_ccw.c
+++ b/drivers/s390/scsi/zfcp_ccw.c
@@ -38,17 +38,23 @@ void zfcp_ccw_adapter_put(struct zfcp_adapter *adapter)
spin_unlock_irqrestore(&zfcp_ccw_adapter_ref_lock, flags);
}
-static int zfcp_ccw_activate(struct ccw_device *cdev)
-
+/**
+ * zfcp_ccw_activate - activate adapter and wait for it to finish
+ * @cdev: pointer to belonging ccw device
+ * @clear: Status flags to clear.
+ * @tag: s390dbf trace record tag
+ */
+static int zfcp_ccw_activate(struct ccw_device *cdev, int clear, char *tag)
{
struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
if (!adapter)
return 0;
+ zfcp_erp_clear_adapter_status(adapter, clear);
zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING);
zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
- "ccresu2");
+ tag);
zfcp_erp_wait(adapter);
flush_work(&adapter->scan_work);
@@ -163,26 +169,29 @@ static int zfcp_ccw_set_online(struct ccw_device *cdev)
BUG_ON(!zfcp_reqlist_isempty(adapter->req_list));
adapter->req_no = 0;
- zfcp_ccw_activate(cdev);
+ zfcp_ccw_activate(cdev, 0, "ccsonl1");
zfcp_ccw_adapter_put(adapter);
return 0;
}
/**
- * zfcp_ccw_set_offline - set_offline function of zfcp driver
+ * zfcp_ccw_offline_sync - shut down adapter and wait for it to finish
* @cdev: pointer to belonging ccw device
+ * @set: Status flags to set.
+ * @tag: s390dbf trace record tag
*
* This function gets called by the common i/o layer and sets an adapter
* into state offline.
*/
-static int zfcp_ccw_set_offline(struct ccw_device *cdev)
+static int zfcp_ccw_offline_sync(struct ccw_device *cdev, int set, char *tag)
{
struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
if (!adapter)
return 0;
- zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1");
+ zfcp_erp_set_adapter_status(adapter, set);
+ zfcp_erp_adapter_shutdown(adapter, 0, tag);
zfcp_erp_wait(adapter);
zfcp_ccw_adapter_put(adapter);
@@ -190,6 +199,18 @@ static int zfcp_ccw_set_offline(struct ccw_device *cdev)
}
/**
+ * zfcp_ccw_set_offline - set_offline function of zfcp driver
+ * @cdev: pointer to belonging ccw device
+ *
+ * This function gets called by the common i/o layer and sets an adapter
+ * into state offline.
+ */
+static int zfcp_ccw_set_offline(struct ccw_device *cdev)
+{
+ return zfcp_ccw_offline_sync(cdev, 0, "ccsoff1");
+}
+
+/**
* zfcp_ccw_notify - ccw notify function
* @cdev: pointer to belonging ccw device
* @event: indicates if adapter was detached or attached
@@ -206,6 +227,11 @@ static int zfcp_ccw_notify(struct ccw_device *cdev, int event)
switch (event) {
case CIO_GONE:
+ if (atomic_read(&adapter->status) &
+ ZFCP_STATUS_ADAPTER_SUSPENDED) { /* notification ignore */
+ zfcp_dbf_hba_basic("ccnigo1", adapter);
+ break;
+ }
dev_warn(&cdev->dev, "The FCP device has been detached\n");
zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti1");
break;
@@ -215,6 +241,11 @@ static int zfcp_ccw_notify(struct ccw_device *cdev, int event)
zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti2");
break;
case CIO_OPER:
+ if (atomic_read(&adapter->status) &
+ ZFCP_STATUS_ADAPTER_SUSPENDED) { /* notification ignore */
+ zfcp_dbf_hba_basic("ccniop1", adapter);
+ break;
+ }
dev_info(&cdev->dev, "The FCP device is operational again\n");
zfcp_erp_set_adapter_status(adapter,
ZFCP_STATUS_COMMON_RUNNING);
@@ -250,6 +281,28 @@ static void zfcp_ccw_shutdown(struct ccw_device *cdev)
zfcp_ccw_adapter_put(adapter);
}
+static int zfcp_ccw_suspend(struct ccw_device *cdev)
+{
+ zfcp_ccw_offline_sync(cdev, ZFCP_STATUS_ADAPTER_SUSPENDED, "ccsusp1");
+ return 0;
+}
+
+static int zfcp_ccw_thaw(struct ccw_device *cdev)
+{
+ /* trace records for thaw and final shutdown during suspend
+ can only be found in system dump until the end of suspend
+ but not after resume because it's based on the memory image
+ right after the very first suspend (freeze) callback */
+ zfcp_ccw_activate(cdev, 0, "ccthaw1");
+ return 0;
+}
+
+static int zfcp_ccw_resume(struct ccw_device *cdev)
+{
+ zfcp_ccw_activate(cdev, ZFCP_STATUS_ADAPTER_SUSPENDED, "ccresu1");
+ return 0;
+}
+
struct ccw_driver zfcp_ccw_driver = {
.driver = {
.owner = THIS_MODULE,
@@ -262,7 +315,7 @@ struct ccw_driver zfcp_ccw_driver = {
.set_offline = zfcp_ccw_set_offline,
.notify = zfcp_ccw_notify,
.shutdown = zfcp_ccw_shutdown,
- .freeze = zfcp_ccw_set_offline,
- .thaw = zfcp_ccw_activate,
- .restore = zfcp_ccw_activate,
+ .freeze = zfcp_ccw_suspend,
+ .thaw = zfcp_ccw_thaw,
+ .restore = zfcp_ccw_resume,
};
diff --git a/drivers/s390/scsi/zfcp_cfdc.c b/drivers/s390/scsi/zfcp_cfdc.c
index fab2c25..8ed63aa 100644
--- a/drivers/s390/scsi/zfcp_cfdc.c
+++ b/drivers/s390/scsi/zfcp_cfdc.c
@@ -293,7 +293,7 @@ void zfcp_cfdc_adapter_access_changed(struct zfcp_adapter *adapter)
}
read_unlock_irqrestore(&adapter->port_list_lock, flags);
- shost_for_each_device(sdev, port->adapter->scsi_host) {
+ shost_for_each_device(sdev, adapter->scsi_host) {
zfcp_sdev = sdev_to_zfcp(sdev);
status = atomic_read(&zfcp_sdev->status);
if ((status & ZFCP_STATUS_COMMON_ACCESS_DENIED) ||
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index 96d1462..8b18dc0 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -163,6 +163,26 @@ void zfcp_dbf_hba_bit_err(char *tag, struct zfcp_fsf_req *req)
spin_unlock_irqrestore(&dbf->hba_lock, flags);
}
+/**
+ * zfcp_dbf_hba_basic - trace event for basic adapter events
+ * @adapter: pointer to struct zfcp_adapter
+ */
+void zfcp_dbf_hba_basic(char *tag, struct zfcp_adapter *adapter)
+{
+ struct zfcp_dbf *dbf = adapter->dbf;
+ struct zfcp_dbf_hba *rec = &dbf->hba_buf;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dbf->hba_lock, flags);
+ memset(rec, 0, sizeof(*rec));
+
+ memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN);
+ rec->id = ZFCP_DBF_HBA_BASIC;
+
+ debug_event(dbf->hba, 1, rec, sizeof(*rec));
+ spin_unlock_irqrestore(&dbf->hba_lock, flags);
+}
+
static void zfcp_dbf_set_common(struct zfcp_dbf_rec *rec,
struct zfcp_adapter *adapter,
struct zfcp_port *port,
diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h
index 714f087..3ac7a4b 100644
--- a/drivers/s390/scsi/zfcp_dbf.h
+++ b/drivers/s390/scsi/zfcp_dbf.h
@@ -154,6 +154,7 @@ enum zfcp_dbf_hba_id {
ZFCP_DBF_HBA_RES = 1,
ZFCP_DBF_HBA_USS = 2,
ZFCP_DBF_HBA_BIT = 3,
+ ZFCP_DBF_HBA_BASIC = 4,
};
/**
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index 527ba48..ebbf760 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -76,6 +76,7 @@ struct zfcp_reqlist;
#define ZFCP_STATUS_ADAPTER_SIOSL_ISSUED 0x00000004
#define ZFCP_STATUS_ADAPTER_XCONFIG_OK 0x00000008
#define ZFCP_STATUS_ADAPTER_HOST_CON_INIT 0x00000010
+#define ZFCP_STATUS_ADAPTER_SUSPENDED 0x00000040
#define ZFCP_STATUS_ADAPTER_ERP_PENDING 0x00000100
#define ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED 0x00000200
#define ZFCP_STATUS_ADAPTER_DATA_DIV_ENABLED 0x00000400
@@ -203,6 +204,7 @@ struct zfcp_port {
struct zfcp_adapter *adapter; /* adapter used to access port */
struct list_head unit_list; /* head of logical unit list */
rwlock_t unit_list_lock; /* unit list lock */
+ atomic_t units; /* zfcp_unit count */
atomic_t status; /* status of this remote port */
u64 wwnn; /* WWNN if known */
u64 wwpn; /* WWPN */
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index 03627cfd..3ad6399 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -53,6 +53,7 @@ extern void zfcp_dbf_hba_fsf_uss(char *, struct zfcp_fsf_req *);
extern void zfcp_dbf_hba_fsf_res(char *, struct zfcp_fsf_req *);
extern void zfcp_dbf_hba_bit_err(char *, struct zfcp_fsf_req *);
extern void zfcp_dbf_hba_berr(struct zfcp_dbf *, struct zfcp_fsf_req *);
+extern void zfcp_dbf_hba_basic(char *, struct zfcp_adapter *);
extern void zfcp_dbf_san_req(char *, struct zfcp_fsf_req *, u32);
extern void zfcp_dbf_san_res(char *, struct zfcp_fsf_req *);
extern void zfcp_dbf_san_in_els(char *, struct zfcp_fsf_req *);
@@ -157,6 +158,7 @@ extern void zfcp_scsi_dif_sense_error(struct scsi_cmnd *, int);
extern struct attribute_group zfcp_sysfs_unit_attrs;
extern struct attribute_group zfcp_sysfs_adapter_attrs;
extern struct attribute_group zfcp_sysfs_port_attrs;
+extern struct mutex zfcp_sysfs_port_units_mutex;
extern struct device_attribute *zfcp_sysfs_sdev_attrs[];
extern struct device_attribute *zfcp_sysfs_shost_attrs[];
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 022fb6a..6e73bfe 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -219,7 +219,7 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req)
return;
}
- zfcp_dbf_hba_fsf_uss("fssrh_2", req);
+ zfcp_dbf_hba_fsf_uss("fssrh_4", req);
switch (sr_buf->status_type) {
case FSF_STATUS_READ_PORT_CLOSED:
@@ -771,12 +771,14 @@ out:
static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req)
{
struct scsi_device *sdev = req->data;
- struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+ struct zfcp_scsi_dev *zfcp_sdev;
union fsf_status_qual *fsq = &req->qtcb->header.fsf_status_qual;
if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
return;
+ zfcp_sdev = sdev_to_zfcp(sdev);
+
switch (req->qtcb->header.fsf_status) {
case FSF_PORT_HANDLE_NOT_VALID:
if (fsq->word[0] == fsq->word[1]) {
@@ -885,7 +887,7 @@ static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req)
switch (header->fsf_status) {
case FSF_GOOD:
- zfcp_dbf_san_res("fsscth1", req);
+ zfcp_dbf_san_res("fsscth2", req);
ct->status = 0;
break;
case FSF_SERVICE_CLASS_NOT_SUPPORTED:
@@ -1730,13 +1732,15 @@ static void zfcp_fsf_open_lun_handler(struct zfcp_fsf_req *req)
{
struct zfcp_adapter *adapter = req->adapter;
struct scsi_device *sdev = req->data;
- struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+ struct zfcp_scsi_dev *zfcp_sdev;
struct fsf_qtcb_header *header = &req->qtcb->header;
struct fsf_qtcb_bottom_support *bottom = &req->qtcb->bottom.support;
if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
return;
+ zfcp_sdev = sdev_to_zfcp(sdev);
+
atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
ZFCP_STATUS_COMMON_ACCESS_BOXED |
ZFCP_STATUS_LUN_SHARED |
@@ -1847,11 +1851,13 @@ out:
static void zfcp_fsf_close_lun_handler(struct zfcp_fsf_req *req)
{
struct scsi_device *sdev = req->data;
- struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+ struct zfcp_scsi_dev *zfcp_sdev;
if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
return;
+ zfcp_sdev = sdev_to_zfcp(sdev);
+
switch (req->qtcb->header.fsf_status) {
case FSF_PORT_HANDLE_NOT_VALID:
zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fscuh_1");
@@ -1941,7 +1947,7 @@ static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi)
{
struct fsf_qual_latency_info *lat_in;
struct latency_cont *lat = NULL;
- struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scsi->device);
+ struct zfcp_scsi_dev *zfcp_sdev;
struct zfcp_blk_drv_data blktrc;
int ticks = req->adapter->timer_ticks;
@@ -1956,6 +1962,7 @@ static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi)
if (req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA &&
!(req->status & ZFCP_STATUS_FSFREQ_ERROR)) {
+ zfcp_sdev = sdev_to_zfcp(scsi->device);
blktrc.flags |= ZFCP_BLK_LAT_VALID;
blktrc.channel_lat = lat_in->channel_lat * ticks;
blktrc.fabric_lat = lat_in->fabric_lat * ticks;
@@ -1993,12 +2000,14 @@ static void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req)
{
struct scsi_cmnd *scmnd = req->data;
struct scsi_device *sdev = scmnd->device;
- struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+ struct zfcp_scsi_dev *zfcp_sdev;
struct fsf_qtcb_header *header = &req->qtcb->header;
if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR))
return;
+ zfcp_sdev = sdev_to_zfcp(sdev);
+
switch (header->fsf_status) {
case FSF_HANDLE_MISMATCH:
case FSF_PORT_HANDLE_NOT_VALID:
diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c
index cdc4ff7..9e62210 100644
--- a/drivers/s390/scsi/zfcp_sysfs.c
+++ b/drivers/s390/scsi/zfcp_sysfs.c
@@ -227,6 +227,8 @@ static ssize_t zfcp_sysfs_port_rescan_store(struct device *dev,
static ZFCP_DEV_ATTR(adapter, port_rescan, S_IWUSR, NULL,
zfcp_sysfs_port_rescan_store);
+DEFINE_MUTEX(zfcp_sysfs_port_units_mutex);
+
static ssize_t zfcp_sysfs_port_remove_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
@@ -249,6 +251,16 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev,
else
retval = 0;
+ mutex_lock(&zfcp_sysfs_port_units_mutex);
+ if (atomic_read(&port->units) > 0) {
+ retval = -EBUSY;
+ mutex_unlock(&zfcp_sysfs_port_units_mutex);
+ goto out;
+ }
+ /* port is about to be removed, so no more unit_add */
+ atomic_set(&port->units, -1);
+ mutex_unlock(&zfcp_sysfs_port_units_mutex);
+
write_lock_irq(&adapter->port_list_lock);
list_del(&port->list);
write_unlock_irq(&adapter->port_list_lock);
@@ -289,12 +301,14 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev,
{
struct zfcp_port *port = container_of(dev, struct zfcp_port, dev);
u64 fcp_lun;
+ int retval;
if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun))
return -EINVAL;
- if (zfcp_unit_add(port, fcp_lun))
- return -EINVAL;
+ retval = zfcp_unit_add(port, fcp_lun);
+ if (retval)
+ return retval;
return count;
}
diff --git a/drivers/s390/scsi/zfcp_unit.c b/drivers/s390/scsi/zfcp_unit.c
index 20796eb..4e6a535 100644
--- a/drivers/s390/scsi/zfcp_unit.c
+++ b/drivers/s390/scsi/zfcp_unit.c
@@ -104,7 +104,7 @@ static void zfcp_unit_release(struct device *dev)
{
struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev);
- put_device(&unit->port->dev);
+ atomic_dec(&unit->port->units);
kfree(unit);
}
@@ -119,16 +119,27 @@ static void zfcp_unit_release(struct device *dev)
int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun)
{
struct zfcp_unit *unit;
+ int retval = 0;
+
+ mutex_lock(&zfcp_sysfs_port_units_mutex);
+ if (atomic_read(&port->units) == -1) {
+ /* port is already gone */
+ retval = -ENODEV;
+ goto out;
+ }
unit = zfcp_unit_find(port, fcp_lun);
if (unit) {
put_device(&unit->dev);
- return -EEXIST;
+ retval = -EEXIST;
+ goto out;
}
unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL);
- if (!unit)
- return -ENOMEM;
+ if (!unit) {
+ retval = -ENOMEM;
+ goto out;
+ }
unit->port = port;
unit->fcp_lun = fcp_lun;
@@ -139,28 +150,33 @@ int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun)
if (dev_set_name(&unit->dev, "0x%016llx",
(unsigned long long) fcp_lun)) {
kfree(unit);
- return -ENOMEM;
+ retval = -ENOMEM;
+ goto out;
}
- get_device(&port->dev);
-
if (device_register(&unit->dev)) {
put_device(&unit->dev);
- return -ENOMEM;
+ retval = -ENOMEM;
+ goto out;
}
if (sysfs_create_group(&unit->dev.kobj, &zfcp_sysfs_unit_attrs)) {
device_unregister(&unit->dev);
- return -EINVAL;
+ retval = -EINVAL;
+ goto out;
}
+ atomic_inc(&port->units); /* under zfcp_sysfs_port_units_mutex ! */
+
write_lock_irq(&port->unit_list_lock);
list_add_tail(&unit->list, &port->unit_list);
write_unlock_irq(&port->unit_list_lock);
zfcp_unit_scsi_scan(unit);
- return 0;
+out:
+ mutex_unlock(&zfcp_sysfs_port_units_mutex);
+ return retval;
}
/**
diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 7e6eca4..59fc5a1 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -1174,7 +1174,16 @@ wait_io1:
outw(val, tmport);
outb(2, 0x80);
TCM_SYNC:
- udelay(0x800);
+ /*
+ * The funny division into multiple delays is to accomodate
+ * arches like ARM where udelay() multiplies its argument by
+ * a large number to initialize a loop counter. To avoid
+ * overflow, the maximum supported udelay is 2000 microseconds.
+ *
+ * XXX it would be more polite to find a way to use msleep()
+ */
+ mdelay(2);
+ udelay(48);
if ((inb(tmport) & 0x80) == 0x00) { /* bsy ? */
outw(0, tmport--);
outb(0, tmport);
diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c
index 5c54a2d..ca397f8 100644
--- a/drivers/scsi/bnx2i/bnx2i_hwi.c
+++ b/drivers/scsi/bnx2i/bnx2i_hwi.c
@@ -1260,6 +1260,9 @@ int bnx2i_send_fw_iscsi_init_msg(struct bnx2i_hba *hba)
int rc = 0;
u64 mask64;
+ memset(&iscsi_init, 0x00, sizeof(struct iscsi_kwqe_init1));
+ memset(&iscsi_init2, 0x00, sizeof(struct iscsi_kwqe_init2));
+
bnx2i_adjust_qp_size(hba);
iscsi_init.flags =
diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c
index 6fec9fe..5391e6a 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -619,8 +619,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
h->state = TPGS_STATE_STANDBY;
break;
case TPGS_STATE_OFFLINE:
- case TPGS_STATE_UNAVAILABLE:
- /* Path unusable for unavailable/offline */
+ /* Path unusable */
err = SCSI_DH_DEV_OFFLINED;
break;
default:
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 56a9f3f..1e33d39 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -1209,8 +1209,9 @@ static void complete_scsi_command(struct CommandList *cp)
}
break;
case CMD_PROTOCOL_ERR:
+ cmd->result = DID_ERROR << 16;
dev_warn(&h->pdev->dev, "cp %p has "
- "protocol error \n", cp);
+ "protocol error\n", cp);
break;
case CMD_HARDWARE_ERR:
cmd->result = DID_ERROR << 16;
@@ -1654,30 +1655,26 @@ static void figure_bus_target_lun(struct ctlr_info *h,
if (is_logical_dev_addr_mode(lunaddrbytes)) {
/* logical device */
- if (unlikely(is_scsi_rev_5(h))) {
- /* p1210m, logical drives lun assignments
- * match SCSI REPORT LUNS data.
+ lunid = le32_to_cpu(*((__le32 *) lunaddrbytes));
+ if (is_msa2xxx(h, device)) {
+ /* msa2xxx way, put logicals on bus 1
+ * and match target/lun numbers box
+ * reports.
*/
- lunid = le32_to_cpu(*((__le32 *) lunaddrbytes));
- *bus = 0;
- *target = 0;
- *lun = (lunid & 0x3fff) + 1;
+ *bus = 1;
+ *target = (lunid >> 16) & 0x3fff;
+ *lun = lunid & 0x00ff;
} else {
- /* not p1210m... */
- lunid = le32_to_cpu(*((__le32 *) lunaddrbytes));
- if (is_msa2xxx(h, device)) {
- /* msa2xxx way, put logicals on bus 1
- * and match target/lun numbers box
- * reports.
- */
- *bus = 1;
- *target = (lunid >> 16) & 0x3fff;
- *lun = lunid & 0x00ff;
+ if (likely(is_scsi_rev_5(h))) {
+ /* All current smart arrays (circa 2011) */
+ *bus = 0;
+ *target = 0;
+ *lun = (lunid & 0x3fff) + 1;
} else {
- /* Traditional smart array way. */
+ /* Traditional old smart array way. */
*bus = 0;
- *lun = 0;
*target = lunid & 0x3fff;
+ *lun = 0;
}
}
} else {
@@ -2896,7 +2893,7 @@ static void fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
c->Request.Timeout = 0; /* Don't time out */
memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB));
c->Request.CDB[0] = cmd;
- c->Request.CDB[1] = 0x03; /* Reset target above */
+ c->Request.CDB[1] = HPSA_RESET_TYPE_LUN;
/* If bytes 4-7 are zero, it means reset the */
/* LunID device */
c->Request.CDB[4] = 0x00;
@@ -4037,10 +4034,10 @@ static int hpsa_request_irq(struct ctlr_info *h,
if (h->msix_vector || h->msi_vector)
rc = request_irq(h->intr[h->intr_mode], msixhandler,
- IRQF_DISABLED, h->devname, h);
+ 0, h->devname, h);
else
rc = request_irq(h->intr[h->intr_mode], intxhandler,
- IRQF_DISABLED, h->devname, h);
+ IRQF_SHARED, h->devname, h);
if (rc) {
dev_err(&h->pdev->dev, "unable to get irq %d for %s\n",
h->intr[h->intr_mode], h->devname);
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index 3d391dc..36aca4b 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -1547,6 +1547,9 @@ static int ibmvscsi_do_host_config(struct ibmvscsi_host_data *hostdata,
host_config = &evt_struct->iu.mad.host_config;
+ /* The transport length field is only 16-bit */
+ length = min(0xffff, length);
+
/* Set up a lun reset SRP command */
memset(host_config, 0x00, sizeof(*host_config));
host_config->common.type = VIOSRP_HOST_CONFIG_TYPE;
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
index 61e0d09..0365d58 100644
--- a/drivers/scsi/isci/init.c
+++ b/drivers/scsi/isci/init.c
@@ -454,11 +454,10 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic
if (!orom)
orom = isci_request_oprom(pdev);
- for (i = 0; orom && i < ARRAY_SIZE(orom->ctrl); i++) {
+ for (i = 0; orom && i < num_controllers(pdev); i++) {
if (sci_oem_parameters_validate(&orom->ctrl[i])) {
dev_warn(&pdev->dev,
"[%d]: invalid oem parameters detected, falling back to firmware\n", i);
- devm_kfree(&pdev->dev, orom);
orom = NULL;
break;
}
diff --git a/drivers/scsi/isci/probe_roms.c b/drivers/scsi/isci/probe_roms.c
index b5f4341..7cd637d 100644
--- a/drivers/scsi/isci/probe_roms.c
+++ b/drivers/scsi/isci/probe_roms.c
@@ -104,7 +104,6 @@ struct isci_orom *isci_request_oprom(struct pci_dev *pdev)
if (i >= len) {
dev_err(&pdev->dev, "oprom parse error\n");
- devm_kfree(&pdev->dev, rom);
rom = NULL;
}
pci_unmap_biosrom(oprom);
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index e68fac6..d2f9576 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -770,7 +770,7 @@ static struct domain_device *sas_ex_discover_end_dev(
}
/* See if this phy is part of a wide port */
-static int sas_ex_join_wide_port(struct domain_device *parent, int phy_id)
+static bool sas_ex_join_wide_port(struct domain_device *parent, int phy_id)
{
struct ex_phy *phy = &parent->ex_dev.ex_phy[phy_id];
int i;
@@ -786,11 +786,11 @@ static int sas_ex_join_wide_port(struct domain_device *parent, int phy_id)
sas_port_add_phy(ephy->port, phy->phy);
phy->port = ephy->port;
phy->phy_state = PHY_DEVICE_DISCOVERED;
- return 0;
+ return true;
}
}
- return -ENODEV;
+ return false;
}
static struct domain_device *sas_ex_discover_expander(
@@ -928,8 +928,7 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id)
return res;
}
- res = sas_ex_join_wide_port(dev, phy_id);
- if (!res) {
+ if (sas_ex_join_wide_port(dev, phy_id)) {
SAS_DPRINTK("Attaching ex phy%d to wide port %016llx\n",
phy_id, SAS_ADDR(ex_phy->attached_sas_addr));
return res;
@@ -974,8 +973,7 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id)
if (SAS_ADDR(ex->ex_phy[i].attached_sas_addr) ==
SAS_ADDR(child->sas_addr)) {
ex->ex_phy[i].phy_state= PHY_DEVICE_DISCOVERED;
- res = sas_ex_join_wide_port(dev, i);
- if (!res)
+ if (sas_ex_join_wide_port(dev, i))
SAS_DPRINTK("Attaching ex phy%d to wide port %016llx\n",
i, SAS_ADDR(ex->ex_phy[i].attached_sas_addr));
@@ -1838,32 +1836,20 @@ static int sas_discover_new(struct domain_device *dev, int phy_id)
{
struct ex_phy *ex_phy = &dev->ex_dev.ex_phy[phy_id];
struct domain_device *child;
- bool found = false;
- int res, i;
+ int res;
SAS_DPRINTK("ex %016llx phy%d new device attached\n",
SAS_ADDR(dev->sas_addr), phy_id);
res = sas_ex_phy_discover(dev, phy_id);
if (res)
- goto out;
- /* to support the wide port inserted */
- for (i = 0; i < dev->ex_dev.num_phys; i++) {
- struct ex_phy *ex_phy_temp = &dev->ex_dev.ex_phy[i];
- if (i == phy_id)
- continue;
- if (SAS_ADDR(ex_phy_temp->attached_sas_addr) ==
- SAS_ADDR(ex_phy->attached_sas_addr)) {
- found = true;
- break;
- }
- }
- if (found) {
- sas_ex_join_wide_port(dev, phy_id);
+ return res;
+
+ if (sas_ex_join_wide_port(dev, phy_id))
return 0;
- }
+
res = sas_ex_discover_devices(dev, phy_id);
- if (!res)
- goto out;
+ if (res)
+ return res;
list_for_each_entry(child, &dev->ex_dev.children, siblings) {
if (SAS_ADDR(child->sas_addr) ==
SAS_ADDR(ex_phy->attached_sas_addr)) {
@@ -1873,7 +1859,6 @@ static int sas_discover_new(struct domain_device *dev, int phy_id)
break;
}
}
-out:
return res;
}
@@ -1972,9 +1957,7 @@ int sas_ex_revalidate_domain(struct domain_device *port_dev)
struct domain_device *dev = NULL;
res = sas_find_bcast_dev(port_dev, &dev);
- if (res)
- goto out;
- if (dev) {
+ while (res == 0 && dev) {
struct expander_device *ex = &dev->ex_dev;
int i = 0, phy_id;
@@ -1986,8 +1969,10 @@ int sas_ex_revalidate_domain(struct domain_device *port_dev)
res = sas_rediscover(dev, phy_id);
i = phy_id + 1;
} while (i < ex->num_phys);
+
+ dev = NULL;
+ res = sas_find_bcast_dev(port_dev, &dev);
}
-out:
return res;
}
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
index e6e30f4..931cb11 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -4052,7 +4052,6 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
spin_lock_init(&instance->cmd_pool_lock);
spin_lock_init(&instance->hba_lock);
spin_lock_init(&instance->completion_lock);
- spin_lock_init(&poll_aen_lock);
mutex_init(&instance->aen_mutex);
mutex_init(&instance->reset_mutex);
@@ -5380,6 +5379,8 @@ static int __init megasas_init(void)
printk(KERN_INFO "megasas: %s %s\n", MEGASAS_VERSION,
MEGASAS_EXT_VERSION);
+ spin_lock_init(&poll_aen_lock);
+
support_poll_for_event = 2;
support_device_change = 1;
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
index 10f16a3..679fe6a 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -1097,6 +1097,13 @@ _base_check_enable_msix(struct MPT2SAS_ADAPTER *ioc)
u16 message_control;
+ /* Check whether controller SAS2008 B0 controller,
+ if it is SAS2008 B0 controller use IO-APIC instead of MSIX */
+ if (ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2008 &&
+ ioc->pdev->revision == 0x01) {
+ return -EINVAL;
+ }
+
base = pci_find_capability(ioc->pdev, PCI_CAP_ID_MSIX);
if (!base) {
dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "msix not "
@@ -2140,10 +2147,13 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
}
/* command line tunables for max controller queue depth */
- if (max_queue_depth != -1)
- max_request_credit = (max_queue_depth < facts->RequestCredit)
- ? max_queue_depth : facts->RequestCredit;
- else
+ if (max_queue_depth != -1 && max_queue_depth != 0) {
+ max_request_credit = min_t(u16, max_queue_depth +
+ ioc->hi_priority_depth + ioc->internal_depth,
+ facts->RequestCredit);
+ if (max_request_credit > MAX_HBA_QUEUE_DEPTH)
+ max_request_credit = MAX_HBA_QUEUE_DEPTH;
+ } else
max_request_credit = min_t(u16, facts->RequestCredit,
MAX_HBA_QUEUE_DEPTH);
@@ -2218,7 +2228,7 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
/* set the scsi host can_queue depth
* with some internal commands that could be outstanding
*/
- ioc->shost->can_queue = ioc->scsiio_depth - (2);
+ ioc->shost->can_queue = ioc->scsiio_depth;
dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scsi host: "
"can_queue depth (%d)\n", ioc->name, ioc->shost->can_queue));
@@ -3056,7 +3066,7 @@ _base_get_port_facts(struct MPT2SAS_ADAPTER *ioc, int port, int sleep_flag)
}
pfacts = &ioc->pfacts[port];
- memset(pfacts, 0, sizeof(Mpi2PortFactsReply_t));
+ memset(pfacts, 0, sizeof(struct mpt2sas_port_facts));
pfacts->PortNumber = mpi_reply.PortNumber;
pfacts->VP_ID = mpi_reply.VP_ID;
pfacts->VF_ID = mpi_reply.VF_ID;
@@ -3098,7 +3108,7 @@ _base_get_ioc_facts(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
}
facts = &ioc->facts;
- memset(facts, 0, sizeof(Mpi2IOCFactsReply_t));
+ memset(facts, 0, sizeof(struct mpt2sas_facts));
facts->MsgVersion = le16_to_cpu(mpi_reply.MsgVersion);
facts->HeaderVersion = le16_to_cpu(mpi_reply.HeaderVersion);
facts->VP_ID = mpi_reply.VP_ID;
@@ -3779,7 +3789,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
goto out_free_resources;
ioc->pfacts = kcalloc(ioc->facts.NumberOfPorts,
- sizeof(Mpi2PortFactsReply_t), GFP_KERNEL);
+ sizeof(struct mpt2sas_port_facts), GFP_KERNEL);
if (!ioc->pfacts) {
r = -ENOMEM;
goto out_free_resources;
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index a4b9cdb..198e4cd 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -41,6 +41,8 @@
#include <trace/events/scsi.h>
+static void scsi_eh_done(struct scsi_cmnd *scmd);
+
#define SENSE_TIMEOUT (10*HZ)
/*
@@ -240,6 +242,14 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
if (! scsi_command_normalize_sense(scmd, &sshdr))
return FAILED; /* no valid sense data */
+ if (scmd->cmnd[0] == TEST_UNIT_READY && scmd->scsi_done != scsi_eh_done)
+ /*
+ * nasty: for mid-layer issued TURs, we need to return the
+ * actual sense data without any recovery attempt. For eh
+ * issued ones, we need to try to recover and interpret
+ */
+ return SUCCESS;
+
if (scsi_sense_is_deferred(&sshdr))
return NEEDS_RETRY;
@@ -1665,6 +1675,20 @@ static void scsi_restart_operations(struct Scsi_Host *shost)
* requests are started.
*/
scsi_run_host_queues(shost);
+
+ /*
+ * if eh is active and host_eh_scheduled is pending we need to re-run
+ * recovery. we do this check after scsi_run_host_queues() to allow
+ * everything pent up since the last eh run a chance to make forward
+ * progress before we sync again. Either we'll immediately re-run
+ * recovery or scsi_device_unbusy() will wake us again when these
+ * pending commands complete.
+ */
+ spin_lock_irqsave(shost->host_lock, flags);
+ if (shost->host_eh_scheduled)
+ if (scsi_host_set_state(shost, SHOST_RECOVERY))
+ WARN_ON(scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY));
+ spin_unlock_irqrestore(shost->host_lock, flags);
}
/**
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 72ab1e6..dd454c4 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -481,15 +481,26 @@ void scsi_requeue_run_queue(struct work_struct *work)
*/
static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd)
{
+ struct scsi_device *sdev = cmd->device;
struct request *req = cmd->request;
unsigned long flags;
+ /*
+ * We need to hold a reference on the device to avoid the queue being
+ * killed after the unlock and before scsi_run_queue is invoked which
+ * may happen because scsi_unprep_request() puts the command which
+ * releases its reference on the device.
+ */
+ get_device(&sdev->sdev_gendev);
+
spin_lock_irqsave(q->queue_lock, flags);
scsi_unprep_request(req);
blk_requeue_request(q, req);
spin_unlock_irqrestore(q->queue_lock, flags);
scsi_run_queue(q);
+
+ put_device(&sdev->sdev_gendev);
}
void scsi_next_command(struct scsi_cmnd *cmd)
@@ -1380,16 +1391,19 @@ static int scsi_lld_busy(struct request_queue *q)
{
struct scsi_device *sdev = q->queuedata;
struct Scsi_Host *shost;
- struct scsi_target *starget;
if (!sdev)
return 0;
shost = sdev->host;
- starget = scsi_target(sdev);
- if (scsi_host_in_recovery(shost) || scsi_host_is_busy(shost) ||
- scsi_target_is_busy(starget) || scsi_device_is_busy(sdev))
+ /*
+ * Ignore host/starget busy state.
+ * Since block layer does not have a concept of fairness across
+ * multiple queues, congestion of host/starget needs to be handled
+ * in SCSI layer.
+ */
+ if (scsi_host_in_recovery(shost) || scsi_device_is_busy(sdev))
return 1;
return 0;
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 6e7ea4a..c6c80c9 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -776,6 +776,16 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
sdev->model = (char *) (sdev->inquiry + 16);
sdev->rev = (char *) (sdev->inquiry + 32);
+ if (strncmp(sdev->vendor, "ATA ", 8) == 0) {
+ /*
+ * sata emulation layer device. This is a hack to work around
+ * the SATL power management specifications which state that
+ * when the SATL detects the device has gone into standby
+ * mode, it shall respond with NOT READY.
+ */
+ sdev->allow_restart = 1;
+ }
+
if (*bflags & BLIST_ISROM) {
sdev->type = TYPE_ROM;
sdev->removable = 1;
@@ -1710,6 +1720,9 @@ static void scsi_sysfs_add_devices(struct Scsi_Host *shost)
{
struct scsi_device *sdev;
shost_for_each_device(sdev, shost) {
+ /* target removed before the device could be added */
+ if (sdev->sdev_state == SDEV_DEL)
+ continue;
if (!scsi_host_scan_allowed(shost) ||
scsi_sysfs_add_sdev(sdev) != 0)
__scsi_remove_device(sdev);
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index e0bd3f7..51d823f 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -962,7 +962,6 @@ static void __scsi_remove_target(struct scsi_target *starget)
struct scsi_device *sdev;
spin_lock_irqsave(shost->host_lock, flags);
- starget->reap_ref++;
restart:
list_for_each_entry(sdev, &shost->__devices, siblings) {
if (sdev->channel != starget->channel ||
@@ -976,14 +975,6 @@ static void __scsi_remove_target(struct scsi_target *starget)
goto restart;
}
spin_unlock_irqrestore(shost->host_lock, flags);
- scsi_target_reap(starget);
-}
-
-static int __remove_child (struct device * dev, void * data)
-{
- if (scsi_is_target_device(dev))
- __scsi_remove_target(to_scsi_target(dev));
- return 0;
}
/**
@@ -996,14 +987,32 @@ static int __remove_child (struct device * dev, void * data)
*/
void scsi_remove_target(struct device *dev)
{
- if (scsi_is_target_device(dev)) {
- __scsi_remove_target(to_scsi_target(dev));
- return;
+ struct Scsi_Host *shost = dev_to_shost(dev->parent);
+ struct scsi_target *starget, *last = NULL;
+ unsigned long flags;
+
+ /* remove targets being careful to lookup next entry before
+ * deleting the last
+ */
+ spin_lock_irqsave(shost->host_lock, flags);
+ list_for_each_entry(starget, &shost->__targets, siblings) {
+ if (starget->state == STARGET_DEL)
+ continue;
+ if (starget->dev.parent == dev || &starget->dev == dev) {
+ /* assuming new targets arrive at the end */
+ starget->reap_ref++;
+ spin_unlock_irqrestore(shost->host_lock, flags);
+ if (last)
+ scsi_target_reap(last);
+ last = starget;
+ __scsi_remove_target(starget);
+ spin_lock_irqsave(shost->host_lock, flags);
+ }
}
+ spin_unlock_irqrestore(shost->host_lock, flags);
- get_device(dev);
- device_for_each_child(dev, NULL, __remove_child);
- put_device(dev);
+ if (last)
+ scsi_target_reap(last);
}
EXPORT_SYMBOL(scsi_remove_target);
diff --git a/drivers/scsi/scsi_wait_scan.c b/drivers/scsi/scsi_wait_scan.c
index 74708fc..ae78148 100644
--- a/drivers/scsi/scsi_wait_scan.c
+++ b/drivers/scsi/scsi_wait_scan.c
@@ -12,7 +12,7 @@
#include <linux/module.h>
#include <linux/device.h>
-#include <scsi/scsi_scan.h>
+#include "scsi_priv.h"
static int __init wait_scan_init(void)
{
diff --git a/drivers/spi/spi_fsl_spi.c b/drivers/spi/spi_fsl_spi.c
index 7963c9b..a725b07 100644
--- a/drivers/spi/spi_fsl_spi.c
+++ b/drivers/spi/spi_fsl_spi.c
@@ -139,10 +139,12 @@ static void fsl_spi_change_mode(struct spi_device *spi)
static void fsl_spi_chipselect(struct spi_device *spi, int value)
{
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
- struct fsl_spi_platform_data *pdata = spi->dev.parent->platform_data;
+ struct fsl_spi_platform_data *pdata;
bool pol = spi->mode & SPI_CS_HIGH;
struct spi_mpc8xxx_cs *cs = spi->controller_state;
+ pdata = spi->dev.parent->parent->platform_data;
+
if (value == BITBANG_CS_INACTIVE) {
if (pdata->cs_control)
pdata->cs_control(spi, !pol);
@@ -934,7 +936,7 @@ err:
static void fsl_spi_cs_control(struct spi_device *spi, bool on)
{
- struct device *dev = spi->dev.parent;
+ struct device *dev = spi->dev.parent->parent;
struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(dev->platform_data);
u16 cs = spi->chip_select;
int gpio = pinfo->gpios[cs];
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index 63e50f7..d80b90f 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -280,7 +280,7 @@ static int do_devconfig_ioctl(struct comedi_device *dev,
if (ret == 0) {
if (!try_module_get(dev->driver->module)) {
comedi_device_detach(dev);
- return -ENOSYS;
+ ret = -ENOSYS;
}
}
@@ -843,7 +843,7 @@ static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn,
ret = -EAGAIN;
break;
}
- ret = s->async->inttrig(dev, s, insn->data[0]);
+ ret = s->async->inttrig(dev, s, data[0]);
if (ret >= 0)
ret = 1;
break;
@@ -1088,7 +1088,6 @@ static int do_cmd_ioctl(struct comedi_device *dev,
goto cleanup;
}
- kfree(async->cmd.chanlist);
async->cmd = user_cmd;
async->cmd.data = NULL;
/* load channel/gain list */
@@ -1833,6 +1832,8 @@ void do_become_nonbusy(struct comedi_device *dev, struct comedi_subdevice *s)
if (async) {
comedi_reset_async_buf(async);
async->inttrig = NULL;
+ kfree(async->cmd.chanlist);
+ async->cmd.chanlist = NULL;
} else {
printk(KERN_ERR
"BUG: (?) do_become_nonbusy called with async=0\n");
diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c
index 48246cd..b4311bf 100644
--- a/drivers/staging/comedi/drivers/amplc_pc236.c
+++ b/drivers/staging/comedi/drivers/amplc_pc236.c
@@ -470,7 +470,7 @@ static int pc236_detach(struct comedi_device *dev)
{
printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor,
PC236_DRIVER_NAME);
- if (devpriv)
+ if (dev->iobase)
pc236_intr_disable(dev);
if (dev->irq)
diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c
index 3141dc8..966b693 100644
--- a/drivers/staging/comedi/drivers/das08.c
+++ b/drivers/staging/comedi/drivers/das08.c
@@ -655,7 +655,7 @@ static int das08jr_ao_winsn(struct comedi_device *dev,
int chan;
lsb = data[0] & 0xff;
- msb = (data[0] >> 8) & 0xf;
+ msb = (data[0] >> 8) & 0xff;
chan = CR_CHAN(insn->chanspec);
diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
index 8d98cf4..c8b7eed 100644
--- a/drivers/staging/comedi/drivers/jr3_pci.c
+++ b/drivers/staging/comedi/drivers/jr3_pci.c
@@ -913,7 +913,7 @@ static int jr3_pci_attach(struct comedi_device *dev,
}
/* Reset DSP card */
- devpriv->iobase->channel[0].reset = 0;
+ writel(0, &devpriv->iobase->channel[0].reset);
result = comedi_load_firmware(dev, "jr3pci.idm", jr3_download_firmware);
printk("Firmare load %d\n", result);
diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
index 23fc64b..c72128f 100644
--- a/drivers/staging/comedi/drivers/s626.c
+++ b/drivers/staging/comedi/drivers/s626.c
@@ -2370,7 +2370,7 @@ static int s626_enc_insn_config(struct comedi_device *dev,
/* (data==NULL) ? (Preloadvalue=0) : (Preloadvalue=data[0]); */
k->SetMode(dev, k, Setup, TRUE);
- Preload(dev, k, *(insn->data));
+ Preload(dev, k, data[0]);
k->PulseIndex(dev, k);
SetLatchSource(dev, k, valueSrclatch);
k->SetEnable(dev, k, (uint16_t) (enab != 0));
diff --git a/drivers/staging/lirc/lirc_sir.c b/drivers/staging/lirc/lirc_sir.c
index 0d38645..39bb66b 100644
--- a/drivers/staging/lirc/lirc_sir.c
+++ b/drivers/staging/lirc/lirc_sir.c
@@ -53,6 +53,7 @@
#include <linux/io.h>
#include <asm/irq.h>
#include <linux/fcntl.h>
+#include <linux/platform_device.h>
#ifdef LIRC_ON_SA1100
#include <asm/hardware.h>
#ifdef CONFIG_SA1100_COLLIE
@@ -488,9 +489,11 @@ static struct lirc_driver driver = {
.owner = THIS_MODULE,
};
+static struct platform_device *lirc_sir_dev;
static int init_chrdev(void)
{
+ driver.dev = &lirc_sir_dev->dev;
driver.minor = lirc_register_driver(&driver);
if (driver.minor < 0) {
printk(KERN_ERR LIRC_DRIVER_NAME ": init_chrdev() failed.\n");
@@ -1216,20 +1219,71 @@ static int init_lirc_sir(void)
return 0;
}
+static int __devinit lirc_sir_probe(struct platform_device *dev)
+{
+ return 0;
+}
+
+static int __devexit lirc_sir_remove(struct platform_device *dev)
+{
+ return 0;
+}
+
+static struct platform_driver lirc_sir_driver = {
+ .probe = lirc_sir_probe,
+ .remove = __devexit_p(lirc_sir_remove),
+ .driver = {
+ .name = "lirc_sir",
+ .owner = THIS_MODULE,
+ },
+};
static int __init lirc_sir_init(void)
{
int retval;
+ retval = platform_driver_register(&lirc_sir_driver);
+ if (retval) {
+ printk(KERN_ERR LIRC_DRIVER_NAME ": Platform driver register "
+ "failed!\n");
+ return -ENODEV;
+ }
+
+ lirc_sir_dev = platform_device_alloc("lirc_dev", 0);
+ if (!lirc_sir_dev) {
+ printk(KERN_ERR LIRC_DRIVER_NAME ": Platform device alloc "
+ "failed!\n");
+ retval = -ENOMEM;
+ goto pdev_alloc_fail;
+ }
+
+ retval = platform_device_add(lirc_sir_dev);
+ if (retval) {
+ printk(KERN_ERR LIRC_DRIVER_NAME ": Platform device add "
+ "failed!\n");
+ retval = -ENODEV;
+ goto pdev_add_fail;
+ }
+
retval = init_chrdev();
if (retval < 0)
- return retval;
+ goto fail;
+
retval = init_lirc_sir();
if (retval) {
drop_chrdev();
- return retval;
+ goto fail;
}
+
return 0;
+
+fail:
+ platform_device_del(lirc_sir_dev);
+pdev_add_fail:
+ platform_device_put(lirc_sir_dev);
+pdev_alloc_fail:
+ platform_driver_unregister(&lirc_sir_driver);
+ return retval;
}
static void __exit lirc_sir_exit(void)
@@ -1237,6 +1291,8 @@ static void __exit lirc_sir_exit(void)
drop_hardware();
drop_chrdev();
drop_port();
+ platform_device_unregister(lirc_sir_dev);
+ platform_driver_unregister(&lirc_sir_driver);
printk(KERN_INFO LIRC_DRIVER_NAME ": Uninstalled.\n");
}
diff --git a/drivers/staging/rtl8712/recv_linux.c b/drivers/staging/rtl8712/recv_linux.c
index 1f0949e..30a9c62 100644
--- a/drivers/staging/rtl8712/recv_linux.c
+++ b/drivers/staging/rtl8712/recv_linux.c
@@ -113,13 +113,8 @@ void r8712_recv_indicatepkt(struct _adapter *padapter,
if (skb == NULL)
goto _recv_indicatepkt_drop;
skb->data = precv_frame->u.hdr.rx_data;
-#ifdef NET_SKBUFF_DATA_USES_OFFSET
- skb->tail = (sk_buff_data_t)(precv_frame->u.hdr.rx_tail -
- precv_frame->u.hdr.rx_head);
-#else
- skb->tail = (sk_buff_data_t)precv_frame->u.hdr.rx_tail;
-#endif
skb->len = precv_frame->u.hdr.len;
+ skb_set_tail_pointer(skb, skb->len);
if ((pattrib->tcpchk_valid == 1) && (pattrib->tcp_chkrpt == 1))
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
diff --git a/drivers/staging/speakup/main.c b/drivers/staging/speakup/main.c
index 42fcf7e..59a6d4d 100644
--- a/drivers/staging/speakup/main.c
+++ b/drivers/staging/speakup/main.c
@@ -1855,7 +1855,7 @@ static void speakup_bits(struct vc_data *vc)
static int handle_goto(struct vc_data *vc, u_char type, u_char ch, u_short key)
{
- static u_char *goto_buf = "\0\0\0\0\0\0";
+ static u_char goto_buf[8];
static int num;
int maxlen, go_pos;
char *cp;
diff --git a/drivers/staging/speakup/speakup_soft.c b/drivers/staging/speakup/speakup_soft.c
index a2c3dc4..e76a882 100644
--- a/drivers/staging/speakup/speakup_soft.c
+++ b/drivers/staging/speakup/speakup_soft.c
@@ -40,7 +40,7 @@ static int softsynth_is_alive(struct spk_synth *synth);
static unsigned char get_index(void);
static struct miscdevice synth_device;
-static int initialized;
+static int init_pos;
static int misc_registered;
static struct var_t vars[] = {
@@ -194,7 +194,7 @@ static int softsynth_close(struct inode *inode, struct file *fp)
unsigned long flags;
spk_lock(flags);
synth_soft.alive = 0;
- initialized = 0;
+ init_pos = 0;
spk_unlock(flags);
/* Make sure we let applications go before leaving */
speakup_start_ttys();
@@ -239,13 +239,8 @@ static ssize_t softsynth_read(struct file *fp, char *buf, size_t count,
ch = '\x18';
} else if (synth_buffer_empty()) {
break;
- } else if (!initialized) {
- if (*init) {
- ch = *init;
- init++;
- } else {
- initialized = 1;
- }
+ } else if (init[init_pos]) {
+ ch = init[init_pos++];
} else {
ch = synth_buffer_getc();
}
diff --git a/drivers/staging/vt6656/dpc.c b/drivers/staging/vt6656/dpc.c
index cb817ce..921dae5 100644
--- a/drivers/staging/vt6656/dpc.c
+++ b/drivers/staging/vt6656/dpc.c
@@ -200,7 +200,7 @@ s_vProcessRxMACHeader (
} else if (!compare_ether_addr(pbyRxBuffer, &pDevice->abySNAP_RFC1042[0])) {
cbHeaderSize += 6;
pwType = (PWORD) (pbyRxBufferAddr + cbHeaderSize);
- if ((*pwType == cpu_to_le16(ETH_P_IPX)) ||
+ if ((*pwType == cpu_to_be16(ETH_P_IPX)) ||
(*pwType == cpu_to_le16(0xF380))) {
cbHeaderSize -= 8;
pwType = (PWORD) (pbyRxBufferAddr + cbHeaderSize);
diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c
index e18efd4..ce459d5 100644
--- a/drivers/staging/vt6656/main_usb.c
+++ b/drivers/staging/vt6656/main_usb.c
@@ -222,7 +222,7 @@ DEVICE_PARAM(b80211hEnable, "802.11h mode");
// Static vars definitions
//
-static struct usb_device_id vt6656_table[] __devinitdata = {
+static struct usb_device_id vt6656_table[] = {
{USB_DEVICE(VNT_USB_VENDOR_ID, VNT_USB_PRODUCT_ID)},
{}
};
diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c
index 9b64b10..fe21868 100644
--- a/drivers/staging/vt6656/rxtx.c
+++ b/drivers/staging/vt6656/rxtx.c
@@ -1701,7 +1701,7 @@ s_bPacketToWirelessUsb(
// 802.1H
if (ntohs(psEthHeader->wType) > ETH_DATA_LEN) {
if (pDevice->dwDiagRefCount == 0) {
- if ((psEthHeader->wType == cpu_to_le16(ETH_P_IPX)) ||
+ if ((psEthHeader->wType == cpu_to_be16(ETH_P_IPX)) ||
(psEthHeader->wType == cpu_to_le16(0xF380))) {
memcpy((PBYTE) (pbyPayloadHead),
abySNAP_Bridgetunnel, 6);
@@ -2840,10 +2840,10 @@ int nsDMA_tx_packet(PSDevice pDevice, unsigned int uDMAIdx, struct sk_buff *skb)
Packet_Type = skb->data[ETH_HLEN+1];
Descriptor_type = skb->data[ETH_HLEN+1+1+2];
Key_info = (skb->data[ETH_HLEN+1+1+2+1] << 8)|(skb->data[ETH_HLEN+1+1+2+2]);
- if (pDevice->sTxEthHeader.wType == cpu_to_le16(ETH_P_PAE)) {
- /* 802.1x OR eapol-key challenge frame transfer */
- if (((Protocol_Version == 1) || (Protocol_Version == 2)) &&
- (Packet_Type == 3)) {
+ if (pDevice->sTxEthHeader.wType == cpu_to_be16(ETH_P_PAE)) {
+ /* 802.1x OR eapol-key challenge frame transfer */
+ if (((Protocol_Version == 1) || (Protocol_Version == 2)) &&
+ (Packet_Type == 3)) {
bTxeapol_key = TRUE;
if(!(Key_info & BIT3) && //WPA or RSN group-key challenge
(Key_info & BIT8) && (Key_info & BIT9)) { //send 2/2 key
@@ -2989,19 +2989,19 @@ int nsDMA_tx_packet(PSDevice pDevice, unsigned int uDMAIdx, struct sk_buff *skb)
}
}
- if (pDevice->sTxEthHeader.wType == cpu_to_le16(ETH_P_PAE)) {
- if (pDevice->byBBType != BB_TYPE_11A) {
- pDevice->wCurrentRate = RATE_1M;
- pDevice->byACKRate = RATE_1M;
- pDevice->byTopCCKBasicRate = RATE_1M;
- pDevice->byTopOFDMBasicRate = RATE_6M;
- } else {
- pDevice->wCurrentRate = RATE_6M;
- pDevice->byACKRate = RATE_6M;
- pDevice->byTopCCKBasicRate = RATE_1M;
- pDevice->byTopOFDMBasicRate = RATE_6M;
- }
- }
+ if (pDevice->sTxEthHeader.wType == cpu_to_be16(ETH_P_PAE)) {
+ if (pDevice->byBBType != BB_TYPE_11A) {
+ pDevice->wCurrentRate = RATE_1M;
+ pDevice->byACKRate = RATE_1M;
+ pDevice->byTopCCKBasicRate = RATE_1M;
+ pDevice->byTopOFDMBasicRate = RATE_6M;
+ } else {
+ pDevice->wCurrentRate = RATE_6M;
+ pDevice->byACKRate = RATE_6M;
+ pDevice->byTopCCKBasicRate = RATE_1M;
+ pDevice->byTopOFDMBasicRate = RATE_6M;
+ }
+ }
DBG_PRT(MSG_LEVEL_DEBUG,
KERN_INFO "dma_tx: pDevice->wCurrentRate = %d\n",
@@ -3017,7 +3017,7 @@ int nsDMA_tx_packet(PSDevice pDevice, unsigned int uDMAIdx, struct sk_buff *skb)
if (bNeedEncryption == TRUE) {
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ntohs Pkt Type=%04x\n", ntohs(pDevice->sTxEthHeader.wType));
- if ((pDevice->sTxEthHeader.wType) == cpu_to_le16(ETH_P_PAE)) {
+ if ((pDevice->sTxEthHeader.wType) == cpu_to_be16(ETH_P_PAE)) {
bNeedEncryption = FALSE;
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Pkt Type=%04x\n", (pDevice->sTxEthHeader.wType));
if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pMgmt->eCurrState == WMAC_STATE_ASSOC)) {
diff --git a/drivers/staging/winbond/wbusb.c b/drivers/staging/winbond/wbusb.c
index 3724e1e..02f9eb8 100644
--- a/drivers/staging/winbond/wbusb.c
+++ b/drivers/staging/winbond/wbusb.c
@@ -24,7 +24,7 @@ MODULE_DESCRIPTION("IS89C35 802.11bg WLAN USB Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION("0.1");
-static const struct usb_device_id wb35_table[] __devinitconst = {
+static const struct usb_device_id wb35_table[] = {
{ USB_DEVICE(0x0416, 0x0035) },
{ USB_DEVICE(0x18E8, 0x6201) },
{ USB_DEVICE(0x18E8, 0x6206) },
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index d3a7342..910c8b0 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -3672,15 +3672,20 @@ static int transport_generic_cmd_sequencer(
/* Returns CHECK_CONDITION + INVALID_CDB_FIELD */
goto out_invalid_cdb_field;
}
-
+ /*
+ * For the overflow case keep the existing fabric provided
+ * ->data_length. Otherwise for the underflow case, reset
+ * ->data_length to the smaller SCSI expected data transfer
+ * length.
+ */
if (size > cmd->data_length) {
cmd->se_cmd_flags |= SCF_OVERFLOW_BIT;
cmd->residual_count = (size - cmd->data_length);
} else {
cmd->se_cmd_flags |= SCF_UNDERFLOW_BIT;
cmd->residual_count = (cmd->data_length - size);
+ cmd->data_length = size;
}
- cmd->data_length = size;
}
transport_set_supported_SAM_opcode(cmd);
diff --git a/drivers/target/tcm_fc/tfc_sess.c b/drivers/target/tcm_fc/tfc_sess.c
index 7491e21..a40541c 100644
--- a/drivers/target/tcm_fc/tfc_sess.c
+++ b/drivers/target/tcm_fc/tfc_sess.c
@@ -64,7 +64,8 @@ static struct ft_tport *ft_tport_create(struct fc_lport *lport)
struct ft_tport *tport;
int i;
- tport = rcu_dereference(lport->prov[FC_TYPE_FCP]);
+ tport = rcu_dereference_protected(lport->prov[FC_TYPE_FCP],
+ lockdep_is_held(&ft_lport_lock));
if (tport && tport->tpg)
return tport;
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index c0d34ad..fee6bed 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -842,7 +842,7 @@ static int gsm_dlci_data_output_framed(struct gsm_mux *gsm,
/* dlci->skb is locked by tx_lock */
if (dlci->skb == NULL) {
- dlci->skb = skb_dequeue(&dlci->skb_list);
+ dlci->skb = skb_dequeue_tail(&dlci->skb_list);
if (dlci->skb == NULL)
return 0;
first = 1;
@@ -866,8 +866,11 @@ static int gsm_dlci_data_output_framed(struct gsm_mux *gsm,
/* FIXME: need a timer or something to kick this so it can't
get stuck with no work outstanding and no buffer free */
- if (msg == NULL)
+ if (msg == NULL) {
+ skb_queue_tail(&dlci->skb_list, dlci->skb);
+ dlci->skb = NULL;
return -ENOMEM;
+ }
dp = msg->data;
if (dlci->adaption == 4) { /* Interruptible framed (Packetised Data) */
@@ -1152,6 +1155,8 @@ static void gsm_control_message(struct gsm_mux *gsm, unsigned int command,
u8 *data, int clen)
{
u8 buf[1];
+ unsigned long flags;
+
switch (command) {
case CMD_CLD: {
struct gsm_dlci *dlci = gsm->dlci[0];
@@ -1177,7 +1182,9 @@ static void gsm_control_message(struct gsm_mux *gsm, unsigned int command,
gsm->constipated = 0;
gsm_control_reply(gsm, CMD_FCOFF, NULL, 0);
/* Kick the link in case it is idling */
+ spin_lock_irqsave(&gsm->tx_lock, flags);
gsm_data_kick(gsm);
+ spin_unlock_irqrestore(&gsm->tx_lock, flags);
break;
case CMD_MSC:
/* Out of band modem line change indicator for a DLCI */
@@ -2269,12 +2276,12 @@ static void gsmld_write_wakeup(struct tty_struct *tty)
/* Queue poll */
clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+ spin_lock_irqsave(&gsm->tx_lock, flags);
gsm_data_kick(gsm);
if (gsm->tx_bytes < TX_THRESH_LO) {
- spin_lock_irqsave(&gsm->tx_lock, flags);
gsm_dlci_data_sweep(gsm);
- spin_unlock_irqrestore(&gsm->tx_lock, flags);
}
+ spin_unlock_irqrestore(&gsm->tx_lock, flags);
}
/**
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index c3954fb..d7164bf 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -1728,7 +1728,8 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
do_it_again:
- BUG_ON(!tty->read_buf);
+ if (WARN_ON(!tty->read_buf))
+ return -EAGAIN;
c = job_control(tty, file);
if (c < 0)
diff --git a/drivers/tty/serial/8250_pci.c b/drivers/tty/serial/8250_pci.c
index 21098ed..3411ed3 100644
--- a/drivers/tty/serial/8250_pci.c
+++ b/drivers/tty/serial/8250_pci.c
@@ -1011,6 +1011,8 @@ static int pci_eg20t_init(struct pci_dev *dev)
#define PCI_SUBDEVICE_ID_OCTPRO422 0x0208
#define PCI_SUBDEVICE_ID_POCTAL232 0x0308
#define PCI_SUBDEVICE_ID_POCTAL422 0x0408
+#define PCI_SUBDEVICE_ID_SIIG_DUAL_00 0x2500
+#define PCI_SUBDEVICE_ID_SIIG_DUAL_30 0x2530
#define PCI_VENDOR_ID_ADVANTECH 0x13fe
#define PCI_DEVICE_ID_INTEL_CE4100_UART 0x2e66
#define PCI_DEVICE_ID_ADVANTECH_PCI3620 0x3620
@@ -3009,8 +3011,11 @@ static struct pci_device_id serial_pci_tbl[] = {
* For now just used the hex ID 0x950a.
*/
{ PCI_VENDOR_ID_OXSEMI, 0x950a,
- PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_DUAL_SERIAL, 0, 0,
- pbn_b0_2_115200 },
+ PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_DUAL_00,
+ 0, 0, pbn_b0_2_115200 },
+ { PCI_VENDOR_ID_OXSEMI, 0x950a,
+ PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_DUAL_30,
+ 0, 0, pbn_b0_2_115200 },
{ PCI_VENDOR_ID_OXSEMI, 0x950a,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b0_2_1130000 },
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 21dc4b7..7cbb367 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -1620,13 +1620,26 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
old_cr &= ~ST_UART011_CR_OVSFACT;
}
+ /*
+ * Workaround for the ST Micro oversampling variants to
+ * increase the bitrate slightly, by lowering the divisor,
+ * to avoid delayed sampling of start bit at high speeds,
+ * else we see data corruption.
+ */
+ if (uap->vendor->oversampling) {
+ if ((baud >= 3000000) && (baud < 3250000) && (quot > 1))
+ quot -= 1;
+ else if ((baud > 3250000) && (quot > 2))
+ quot -= 2;
+ }
/* Set baud rate */
writew(quot & 0x3f, port->membase + UART011_FBRD);
writew(quot >> 6, port->membase + UART011_IBRD);
/*
* ----------v----------v----------v----------v-----
- * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L
+ * NOTE: lcrh_tx and lcrh_rx MUST BE WRITTEN AFTER
+ * UART011_FBRD & UART011_IBRD.
* ----------^----------^----------^----------^-----
*/
writew(lcr_h, port->membase + uap->lcrh_rx);
diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index 7e02c9c..5b3d063 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -368,6 +368,8 @@ static void mxs_auart_settermios(struct uart_port *u,
writel(ctrl, u->membase + AUART_LINECTRL);
writel(ctrl2, u->membase + AUART_CTRL2);
+
+ uart_update_timeout(u, termios->c_cflag, baud);
}
static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c
index 101eda9..73038ba 100644
--- a/drivers/tty/serial/pch_uart.c
+++ b/drivers/tty/serial/pch_uart.c
@@ -658,7 +658,8 @@ static void pch_dma_rx_complete(void *arg)
tty_flip_buffer_push(tty);
tty_kref_put(tty);
async_tx_ack(priv->desc_rx);
- pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_RX_INT);
+ pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_RX_INT |
+ PCH_UART_HAL_RX_ERR_INT);
}
static void pch_dma_tx_complete(void *arg)
@@ -713,7 +714,8 @@ static int handle_rx_to(struct eg20t_port *priv)
int rx_size;
int ret;
if (!priv->start_rx) {
- pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_RX_INT);
+ pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_RX_INT |
+ PCH_UART_HAL_RX_ERR_INT);
return 0;
}
buf = &priv->rxbuf;
@@ -975,11 +977,13 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id)
case PCH_UART_IID_RDR: /* Received Data Ready */
if (priv->use_dma) {
pch_uart_hal_disable_interrupt(priv,
- PCH_UART_HAL_RX_INT);
+ PCH_UART_HAL_RX_INT |
+ PCH_UART_HAL_RX_ERR_INT);
ret = dma_handle_rx(priv);
if (!ret)
pch_uart_hal_enable_interrupt(priv,
- PCH_UART_HAL_RX_INT);
+ PCH_UART_HAL_RX_INT |
+ PCH_UART_HAL_RX_ERR_INT);
} else {
ret = handle_rx(priv);
}
@@ -1105,7 +1109,8 @@ static void pch_uart_stop_rx(struct uart_port *port)
struct eg20t_port *priv;
priv = container_of(port, struct eg20t_port, port);
priv->start_rx = 0;
- pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_RX_INT);
+ pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_RX_INT |
+ PCH_UART_HAL_RX_ERR_INT);
priv->int_dis_flag = 1;
}
@@ -1161,6 +1166,7 @@ static int pch_uart_startup(struct uart_port *port)
break;
case 16:
fifo_size = PCH_UART_HAL_FIFO16;
+ break;
case 1:
default:
fifo_size = PCH_UART_HAL_FIFO_DIS;
@@ -1198,7 +1204,8 @@ static int pch_uart_startup(struct uart_port *port)
pch_request_dma(port);
priv->start_rx = 1;
- pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_RX_INT);
+ pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_RX_INT |
+ PCH_UART_HAL_RX_ERR_INT);
uart_update_timeout(port, CS8, default_baud);
return 0;
@@ -1256,7 +1263,7 @@ static void pch_uart_set_termios(struct uart_port *port,
stb = PCH_UART_HAL_STB1;
if (termios->c_cflag & PARENB) {
- if (!(termios->c_cflag & PARODD))
+ if (termios->c_cflag & PARODD)
parity = PCH_UART_HAL_PARITY_ODD;
else
parity = PCH_UART_HAL_PARITY_EVEN;
diff --git a/drivers/tty/serial/s5pv210.c b/drivers/tty/serial/s5pv210.c
index dd194dc..f05790b 100644
--- a/drivers/tty/serial/s5pv210.c
+++ b/drivers/tty/serial/s5pv210.c
@@ -35,7 +35,7 @@ static int s5pv210_serial_setsource(struct uart_port *port,
if (strcmp(clk->name, "pclk") == 0)
ucon &= ~S5PV210_UCON_CLKMASK;
- else if (strcmp(clk->name, "uclk1") == 0)
+ else if (strcmp(clk->name, "sclk") == 0)
ucon |= S5PV210_UCON_CLKMASK;
else {
printk(KERN_ERR "unknown clock source %s\n", clk->name);
@@ -63,7 +63,7 @@ static int s5pv210_serial_getsource(struct uart_port *port,
clk->name = "pclk";
break;
case S5PV210_UCON_UCLK:
- clk->name = "uclk1";
+ clk->name = "sclk";
break;
}
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index f66f648..c7de749 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -80,7 +80,7 @@ static inline const char *s3c24xx_serial_portname(struct uart_port *port)
static int s3c24xx_serial_txempty_nofifo(struct uart_port *port)
{
- return (rd_regl(port, S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE);
+ return rd_regl(port, S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE;
}
static void s3c24xx_serial_rx_enable(struct uart_port *port)
@@ -162,12 +162,14 @@ static void s3c24xx_serial_enable_ms(struct uart_port *port)
{
}
-static inline struct s3c24xx_uart_info *s3c24xx_port_to_info(struct uart_port *port)
+static inline struct
+s3c24xx_uart_info *s3c24xx_port_to_info(struct uart_port *port)
{
return to_ourport(port)->info;
}
-static inline struct s3c2410_uartcfg *s3c24xx_port_to_cfg(struct uart_port *port)
+static inline struct
+s3c2410_uartcfg *s3c24xx_port_to_cfg(struct uart_port *port)
{
if (port->dev == NULL)
return NULL;
@@ -242,7 +244,7 @@ s3c24xx_serial_rx_chars(int irq, void *dev_id)
dbg("break!\n");
port->icount.brk++;
if (uart_handle_break(port))
- goto ignore_char;
+ goto ignore_char;
}
if (uerstat & S3C2410_UERSTAT_FRAME)
@@ -292,7 +294,7 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
/* if there isn't anything more to transmit, or the uart is now
* stopped, disable the uart and exit
- */
+ */
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
s3c24xx_serial_stop_tx(port);
@@ -351,6 +353,14 @@ static unsigned int s3c24xx_serial_get_mctrl(struct uart_port *port)
static void s3c24xx_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
/* todo - possibly remove AFC and do manual CTS */
+ unsigned int umcon = 0;
+ umcon = rd_regl(port, S3C2410_UMCON);
+ if (mctrl & TIOCM_RTS)
+ umcon |= S3C2410_UMCOM_AFC;
+ else
+ umcon &= ~S3C2410_UMCOM_AFC;
+
+ wr_regl(port, S3C2410_UMCON, umcon);
}
static void s3c24xx_serial_break_ctl(struct uart_port *port, int break_state)
@@ -396,7 +406,7 @@ static int s3c24xx_serial_startup(struct uart_port *port)
int ret;
dbg("s3c24xx_serial_startup: port=%p (%08lx,%p)\n",
- port->mapbase, port->membase);
+ port, port->mapbase, port->membase);
rx_enabled(port) = 1;
@@ -438,6 +448,16 @@ static int s3c24xx_serial_startup(struct uart_port *port)
/* power power management control */
+#ifdef CONFIG_CPU_DIDLE
+static bool gps_running = false;
+
+bool gps_is_running(void)
+{
+ return gps_running;
+}
+EXPORT_SYMBOL(gps_is_running);
+#endif
+
static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
unsigned int old)
{
@@ -447,18 +467,31 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
switch (level) {
case 3:
+ disable_irq(ourport->tx_irq);
+ disable_irq(ourport->rx_irq);
+
if (!IS_ERR(ourport->baudclk) && ourport->baudclk != NULL)
clk_disable(ourport->baudclk);
-
+#ifdef CONFIG_CPU_DIDLE
+ if (ourport->port.irq == IRQ_S3CUART_RX1)
+ gps_running = false;
+#endif
clk_disable(ourport->clk);
+
break;
case 0:
- clk_enable(ourport->clk);
+ clk_enable(ourport->clk);
+#ifdef CONFIG_CPU_DIDLE
+ if (ourport->port.irq == IRQ_S3CUART_RX1)
+ gps_running = true;
+#endif
if (!IS_ERR(ourport->baudclk) && ourport->baudclk != NULL)
clk_enable(ourport->baudclk);
+ enable_irq(ourport->tx_irq);
+ enable_irq(ourport->rx_irq);
break;
default:
printk(KERN_ERR "s3c24xx_serial: unknown pm %d\n", level);
@@ -676,7 +709,7 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
* Ask the core to calculate the divisor for us.
*/
- baud = uart_get_baud_rate(port, termios, old, 0, 115200*8);
+ baud = uart_get_baud_rate(port, termios, old, 0, 3000000);
if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)
quot = port->custom_divisor;
@@ -777,7 +810,8 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
*/
port->read_status_mask = S3C2410_UERSTAT_OVERRUN;
if (termios->c_iflag & INPCK)
- port->read_status_mask |= S3C2410_UERSTAT_FRAME | S3C2410_UERSTAT_PARITY;
+ port->read_status_mask |= S3C2410_UERSTAT_FRAME
+ | S3C2410_UERSTAT_PARITY;
/*
* Which character status flags should we ignore?
@@ -849,12 +883,20 @@ s3c24xx_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
return 0;
}
+static void
+s3c24xx_serial_wake_peer(struct uart_port *port)
+{
+ struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port);
+
+ if (cfg->wake_peer)
+ cfg->wake_peer(port);
+}
#ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE
static struct console s3c24xx_serial_console;
-#define S3C24XX_SERIAL_CONSOLE &s3c24xx_serial_console
+#define S3C24XX_SERIAL_CONSOLE (&s3c24xx_serial_console)
#else
#define S3C24XX_SERIAL_CONSOLE NULL
#endif
@@ -877,6 +919,7 @@ static struct uart_ops s3c24xx_serial_ops = {
.request_port = s3c24xx_serial_request_port,
.config_port = s3c24xx_serial_config_port,
.verify_port = s3c24xx_serial_verify_port,
+ .wake_peer = s3c24xx_serial_wake_peer,
};
@@ -885,12 +928,13 @@ static struct uart_driver s3c24xx_uart_drv = {
.driver_name = "s3c2410_serial",
.nr = CONFIG_SERIAL_SAMSUNG_UARTS,
.cons = S3C24XX_SERIAL_CONSOLE,
- .dev_name = S3C24XX_SERIAL_NAME,
+ .dev_name = "s3c2410_serial",
.major = S3C24XX_SERIAL_MAJOR,
.minor = S3C24XX_SERIAL_MINOR,
};
-static struct s3c24xx_uart_port s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS] = {
+static struct s3c24xx_uart_port
+ s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS] = {
[0] = {
.port = {
.lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[0].port.lock),
@@ -1018,7 +1062,8 @@ static int s3c24xx_serial_cpufreq_transition(struct notifier_block *nb,
return 0;
}
-static inline int s3c24xx_serial_cpufreq_register(struct s3c24xx_uart_port *port)
+static inline int
+s3c24xx_serial_cpufreq_register(struct s3c24xx_uart_port *port)
{
port->freq_transition.notifier_call = s3c24xx_serial_cpufreq_transition;
@@ -1026,19 +1071,22 @@ static inline int s3c24xx_serial_cpufreq_register(struct s3c24xx_uart_port *port
CPUFREQ_TRANSITION_NOTIFIER);
}
-static inline void s3c24xx_serial_cpufreq_deregister(struct s3c24xx_uart_port *port)
+static inline void
+s3c24xx_serial_cpufreq_deregister(struct s3c24xx_uart_port *port)
{
cpufreq_unregister_notifier(&port->freq_transition,
CPUFREQ_TRANSITION_NOTIFIER);
}
#else
-static inline int s3c24xx_serial_cpufreq_register(struct s3c24xx_uart_port *port)
+static inline int
+s3c24xx_serial_cpufreq_register(struct s3c24xx_uart_port *port)
{
return 0;
}
-static inline void s3c24xx_serial_cpufreq_deregister(struct s3c24xx_uart_port *port)
+static inline void
+s3c24xx_serial_cpufreq_deregister(struct s3c24xx_uart_port *port)
{
}
#endif
@@ -1109,7 +1157,7 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
ourport->rx_irq = ret;
ourport->tx_irq = ret + 1;
}
-
+
ret = platform_get_irq(platdev, 1);
if (ret > 0)
ourport->tx_irq = ret;
@@ -1122,6 +1170,9 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
/* reset the fifos (and setup the uart) */
s3c24xx_serial_resetport(port, cfg);
+
+ s3c_setup_uart_cfg_gpio(cfg->hwport);
+
return 0;
}
@@ -1139,18 +1190,20 @@ static DEVICE_ATTR(clock_source, S_IRUGO, s3c24xx_serial_show_clksrc, NULL);
/* Device driver serial port probe */
-static int probe_index;
-
int s3c24xx_serial_probe(struct platform_device *dev,
struct s3c24xx_uart_info *info)
{
struct s3c24xx_uart_port *ourport;
int ret;
- dbg("s3c24xx_serial_probe(%p, %p) %d\n", dev, info, probe_index);
+ dbg("s3c24xx_serial_probe(%p, %p) %d\n", dev, info, dev->id);
- ourport = &s3c24xx_serial_ports[probe_index];
- probe_index++;
+ if (dev->id >= ARRAY_SIZE(s3c24xx_serial_ports)) {
+ dev_err(&dev->dev, "unsupported device id %d\n", dev->id);
+ return -ENODEV;
+ }
+
+ ourport = &s3c24xx_serial_ports[dev->id];
dbg("%s: initialising port %p...\n", __func__, ourport);
@@ -1175,7 +1228,6 @@ int s3c24xx_serial_probe(struct platform_device *dev,
probe_err:
return ret;
}
-
EXPORT_SYMBOL_GPL(s3c24xx_serial_probe);
int __devexit s3c24xx_serial_remove(struct platform_device *dev)
@@ -1190,19 +1242,42 @@ int __devexit s3c24xx_serial_remove(struct platform_device *dev)
return 0;
}
-
EXPORT_SYMBOL_GPL(s3c24xx_serial_remove);
/* UART power management code */
#ifdef CONFIG_PM
-static int s3c24xx_serial_suspend(struct platform_device *dev, pm_message_t state)
+#include <plat/pm.h>
+
+#define SAVE_UART(va) \
+ SAVE_ITEM((va) + S3C2410_ULCON), \
+ SAVE_ITEM((va) + S3C2410_UCON), \
+ SAVE_ITEM((va) + S3C2410_UFCON), \
+ SAVE_ITEM((va) + S3C2410_UMCON), \
+ SAVE_ITEM((va) + S3C2410_UBRDIV), \
+ SAVE_ITEM((va) + S3C2410_UDIVSLOT), \
+ SAVE_ITEM((va) + S3C2410_UINTMSK)
+
+static struct sleep_save uart_save[] = {
+ SAVE_UART(S3C_VA_UARTx(0)),
+ SAVE_UART(S3C_VA_UARTx(1)),
+ SAVE_UART(S3C_VA_UARTx(2)),
+ SAVE_UART(S3C_VA_UARTx(3)),
+};
+
+#define SAVE_UART_PORT (ARRAY_SIZE(uart_save) / 4)
+
+static int
+s3c24xx_serial_suspend(struct platform_device *dev, pm_message_t state)
{
struct uart_port *port = s3c24xx_dev_to_port(&dev->dev);
- if (port)
+ if (port) {
uart_suspend_port(&s3c24xx_uart_drv, port);
+ s3c_pm_do_save(uart_save + port->line * SAVE_UART_PORT,
+ SAVE_UART_PORT);
+ }
return 0;
}
@@ -1215,8 +1290,9 @@ static int s3c24xx_serial_resume(struct platform_device *dev)
if (port) {
clk_enable(ourport->clk);
s3c24xx_serial_resetport(port, s3c24xx_port_to_cfg(port));
+ s3c_pm_do_restore(uart_save + port->line * SAVE_UART_PORT,
+ SAVE_UART_PORT);
clk_disable(ourport->clk);
-
uart_resume_port(&s3c24xx_uart_drv, port);
}
@@ -1236,7 +1312,6 @@ int s3c24xx_serial_init(struct platform_driver *drv,
return platform_driver_register(drv);
}
-
EXPORT_SYMBOL_GPL(s3c24xx_serial_init);
/* module initialisation code */
@@ -1388,9 +1463,8 @@ static int s3c24xx_serial_init_ports(struct s3c24xx_uart_info **info)
platdev_ptr = s3c24xx_uart_devs;
- for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++, ptr++, platdev_ptr++) {
+ for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++, ptr++, platdev_ptr++)
s3c24xx_serial_init_port(ptr, info[i], *platdev_ptr);
- }
return 0;
}
diff --git a/drivers/tty/serial/samsung.h b/drivers/tty/serial/samsung.h
index 5b098cd..5226abe 100644
--- a/drivers/tty/serial/samsung.h
+++ b/drivers/tty/serial/samsung.h
@@ -56,7 +56,8 @@ struct s3c24xx_uart_port {
/* conversion functions */
#define s3c24xx_dev_to_port(__dev) (struct uart_port *)dev_get_drvdata(__dev)
-#define s3c24xx_dev_to_cfg(__dev) (struct s3c2410_uartcfg *)((__dev)->platform_data)
+#define s3c24xx_dev_to_cfg(__dev) \
+ (struct s3c2410_uartcfg *)((__dev)->platform_data)
/* register access controls */
@@ -79,6 +80,8 @@ extern int s3c24xx_serial_initconsole(struct platform_driver *drv,
extern int s3c24xx_serial_init(struct platform_driver *drv,
struct s3c24xx_uart_info *info);
+extern void s3c_setup_uart_cfg_gpio(unsigned char port);
+
#ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE
#define s3c24xx_console_init(__drv, __inf) \
@@ -95,7 +98,7 @@ static int __init s3c_serial_console_init(void) \
console_initcall(s3c_serial_console_init)
#else
-#define s3c24xx_console_init(drv, inf) extern void no_console(void)
+#define s3c24xx_console_init(drv, inf) void no_console(void) {}
#endif
#ifdef CONFIG_SERIAL_SAMSUNG_DEBUG
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 5668b3e..2a106a9 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2328,6 +2328,7 @@ void uart_unregister_driver(struct uart_driver *drv)
tty_unregister_driver(p);
put_tty_driver(p);
kfree(drv->state);
+ drv->state = NULL;
drv->tty_driver = NULL;
}
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 48f1781..e9660f1 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -120,6 +120,8 @@ source "drivers/usb/musb/Kconfig"
source "drivers/usb/renesas_usbhs/Kconfig"
+source "drivers/usb/dwc/Kconfig"
+
source "drivers/usb/class/Kconfig"
source "drivers/usb/storage/Kconfig"
@@ -168,4 +170,6 @@ source "drivers/usb/gadget/Kconfig"
source "drivers/usb/otg/Kconfig"
+source "drivers/usb/notify/Kconfig"
+
endif # USB_SUPPORT
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index 30ddf8d..5adcecf 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_USB) += core/
obj-$(CONFIG_USB_MON) += mon/
obj-$(CONFIG_PCI) += host/
+obj-$(CONFIG_USB_S3C_OTG_HOST) += host/
obj-$(CONFIG_USB_EHCI_HCD) += host/
obj-$(CONFIG_USB_ISP116X_HCD) += host/
obj-$(CONFIG_USB_OHCI_HCD) += host/
@@ -50,4 +51,7 @@ obj-$(CONFIG_USB_SPEEDTOUCH) += atm/
obj-$(CONFIG_USB_MUSB_HDRC) += musb/
obj-$(CONFIG_USB_RENESAS_USBHS) += renesas_usbhs/
obj-$(CONFIG_USB_OTG_UTILS) += otg/
+obj-$(CONFIG_USB_DWC_OTG) += dwc/
obj-$(CONFIG_USB_GADGET) += gadget/
+
+obj-$(CONFIG_USB_HOST_NOTIFY) += notify/
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 158f631..b107339 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -498,6 +498,14 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
usb_autopm_put_interface(acm->control);
+ /*
+ * Unthrottle device in case the TTY was closed while throttled.
+ */
+ spin_lock_irq(&acm->read_lock);
+ acm->throttled = 0;
+ acm->throttle_req = 0;
+ spin_unlock_irq(&acm->read_lock);
+
if (acm_submit_read_urbs(acm, GFP_KERNEL))
goto bail_out;
@@ -752,10 +760,6 @@ static const __u32 acm_tty_speed[] = {
2500000, 3000000, 3500000, 4000000
};
-static const __u8 acm_tty_size[] = {
- 5, 6, 7, 8
-};
-
static void acm_tty_set_termios(struct tty_struct *tty,
struct ktermios *termios_old)
{
@@ -772,7 +776,21 @@ static void acm_tty_set_termios(struct tty_struct *tty,
newline.bParityType = termios->c_cflag & PARENB ?
(termios->c_cflag & PARODD ? 1 : 2) +
(termios->c_cflag & CMSPAR ? 2 : 0) : 0;
- newline.bDataBits = acm_tty_size[(termios->c_cflag & CSIZE) >> 4];
+ switch (termios->c_cflag & CSIZE) {
+ case CS5:
+ newline.bDataBits = 5;
+ break;
+ case CS6:
+ newline.bDataBits = 6;
+ break;
+ case CS7:
+ newline.bDataBits = 7;
+ break;
+ case CS8:
+ default:
+ newline.bDataBits = 8;
+ break;
+ }
/* FIXME: Needs to clear unsupported bits in the termios */
acm->clocal = ((termios->c_cflag & CLOCAL) != 0);
@@ -1035,7 +1053,8 @@ skip_normal_probe:
}
- if (data_interface->cur_altsetting->desc.bNumEndpoints < 2)
+ if (data_interface->cur_altsetting->desc.bNumEndpoints < 2 ||
+ control_interface->cur_altsetting->desc.bNumEndpoints == 0)
return -EINVAL;
epctrl = &control_interface->cur_altsetting->endpoint[0].desc;
@@ -1163,7 +1182,7 @@ made_compressed_probe:
if (usb_endpoint_xfer_int(epwrite))
usb_fill_int_urb(snd->urb, usb_dev,
- usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
+ usb_sndintpipe(usb_dev, epwrite->bEndpointAddress),
NULL, acm->writesize, acm_write_bulk, snd, epwrite->bInterval);
else
usb_fill_bulk_urb(snd->urb, usb_dev,
@@ -1487,6 +1506,9 @@ static const struct usb_device_id acm_ids[] = {
Maybe we should define a new
quirk for this. */
},
+ { USB_DEVICE(0x0572, 0x1340), /* Conexant CX93010-2x UCMxx */
+ .driver_info = NO_UNION_NORMAL,
+ },
{ USB_DEVICE(0x1bbb, 0x0003), /* Alcatel OT-I650 */
.driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */
},
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 00b7bf9..8a72e05 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -457,6 +457,8 @@ retry:
goto retry;
}
if (!desc->reslength) { /* zero length read */
+ dev_dbg(&desc->intf->dev, "%s: zero length - clearing WDM_READ\n", __func__);
+ clear_bit(WDM_READ, &desc->flags);
spin_unlock_irq(&desc->iuspin);
goto retry;
}
@@ -511,7 +513,7 @@ static unsigned int wdm_poll(struct file *file, struct poll_table_struct *wait)
spin_lock_irqsave(&desc->iuspin, flags);
if (test_bit(WDM_DISCONNECTING, &desc->flags)) {
- mask = POLLERR;
+ mask = POLLHUP | POLLERR;
spin_unlock_irqrestore(&desc->iuspin, flags);
goto desc_out;
}
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index 0149c09..ca98341 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -624,7 +624,7 @@ static ssize_t usb_device_read(struct file *file, char __user *buf,
/* print devices for all busses */
list_for_each_entry(bus, &usb_bus_list, bus_list) {
/* recurse through all children of the root hub */
- if (!bus->root_hub)
+ if (!bus_to_hcd(bus)->rh_registered)
continue;
usb_lock_device(bus->root_hub);
ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos,
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 0ca54e2..4d1f996 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -292,17 +292,14 @@ static struct async *async_getcompleted(struct dev_state *ps)
static struct async *async_getpending(struct dev_state *ps,
void __user *userurb)
{
- unsigned long flags;
struct async *as;
- spin_lock_irqsave(&ps->lock, flags);
list_for_each_entry(as, &ps->async_pending, asynclist)
if (as->userurb == userurb) {
list_del_init(&as->asynclist);
- spin_unlock_irqrestore(&ps->lock, flags);
return as;
}
- spin_unlock_irqrestore(&ps->lock, flags);
+
return NULL;
}
@@ -357,6 +354,7 @@ static void cancel_bulk_urbs(struct dev_state *ps, unsigned bulk_addr)
__releases(ps->lock)
__acquires(ps->lock)
{
+ struct urb *urb;
struct async *as;
/* Mark all the pending URBs that match bulk_addr, up to but not
@@ -379,8 +377,11 @@ __acquires(ps->lock)
list_for_each_entry(as, &ps->async_pending, asynclist) {
if (as->bulk_status == AS_UNLINK) {
as->bulk_status = 0; /* Only once */
+ urb = as->urb;
+ usb_get_urb(urb);
spin_unlock(&ps->lock); /* Allow completions */
- usb_unlink_urb(as->urb);
+ usb_unlink_urb(urb);
+ usb_put_urb(urb);
spin_lock(&ps->lock);
goto rescan;
}
@@ -433,6 +434,7 @@ static void async_completed(struct urb *urb)
static void destroy_async(struct dev_state *ps, struct list_head *list)
{
+ struct urb *urb;
struct async *as;
unsigned long flags;
@@ -440,10 +442,13 @@ static void destroy_async(struct dev_state *ps, struct list_head *list)
while (!list_empty(list)) {
as = list_entry(list->next, struct async, asynclist);
list_del_init(&as->asynclist);
+ urb = as->urb;
+ usb_get_urb(urb);
/* drop the spinlock so the completion handler can run */
spin_unlock_irqrestore(&ps->lock, flags);
- usb_kill_urb(as->urb);
+ usb_kill_urb(urb);
+ usb_put_urb(urb);
spin_lock_irqsave(&ps->lock, flags);
}
spin_unlock_irqrestore(&ps->lock, flags);
@@ -1352,12 +1357,24 @@ static int proc_submiturb(struct dev_state *ps, void __user *arg)
static int proc_unlinkurb(struct dev_state *ps, void __user *arg)
{
+ struct urb *urb;
struct async *as;
+ unsigned long flags;
+ spin_lock_irqsave(&ps->lock, flags);
as = async_getpending(ps, arg);
- if (!as)
+ if (!as) {
+ spin_unlock_irqrestore(&ps->lock, flags);
return -EINVAL;
- usb_kill_urb(as->urb);
+ }
+
+ urb = as->urb;
+ usb_get_urb(urb);
+ spin_unlock_irqrestore(&ps->lock, flags);
+
+ usb_kill_urb(urb);
+ usb_put_urb(urb);
+
return 0;
}
@@ -1540,10 +1557,14 @@ static int processcompl_compat(struct async *as, void __user * __user *arg)
void __user *addr = as->userurb;
unsigned int i;
- if (as->userbuffer && urb->actual_length)
- if (copy_to_user(as->userbuffer, urb->transfer_buffer,
- urb->actual_length))
+ if (as->userbuffer && urb->actual_length) {
+ if (urb->number_of_packets > 0) /* Isochronous */
+ i = urb->transfer_buffer_length;
+ else /* Non-Isoc */
+ i = urb->actual_length;
+ if (copy_to_user(as->userbuffer, urb->transfer_buffer, i))
return -EFAULT;
+ }
if (put_user(as->status, &userurb->status))
return -EFAULT;
if (put_user(urb->actual_length, &userurb->actual_length))
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 75b4bc0..962f2b5 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1617,6 +1617,13 @@ static int autosuspend_check(struct usb_device *udev)
/* Fail if autosuspend is disabled, or any interfaces are in use, or
* any interface drivers require remote wakeup but it isn't available.
*/
+
+#if defined CONFIG_USB_S3C_OTG_HOST || defined CONFIG_USB_DWC_OTG
+ /* temporarily disabled autosuspend for otg host */
+ if (udev->bus->busnum == 2)
+ return -EOPNOTSUPP;
+#endif
+
w = 0;
if (udev->actconfig) {
for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index aa7bbbc..6c1642b 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -495,15 +495,6 @@ static int hcd_pci_suspend_noirq(struct device *dev)
pci_save_state(pci_dev);
- /*
- * Some systems crash if an EHCI controller is in D3 during
- * a sleep transition. We have to leave such controllers in D0.
- */
- if (hcd->broken_pci_sleep) {
- dev_dbg(dev, "Staying in PCI D0\n");
- return retval;
- }
-
/* If the root hub is dead rather than suspended, disallow remote
* wakeup. usb_hc_died() should ensure that both hosts are marked as
* dying, so we only need to check the primary roothub.
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 45e0908..9c24bf5 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -156,7 +156,11 @@ static const u8 usb2_rh_dev_descriptor [18] = {
0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
0x00, /* __u8 bDeviceSubClass; */
+#if defined CONFIG_USB_S3C_OTG_HOST || defined CONFIG_USB_DWC_OTG
+ 0x01, /* __u8 bDeviceProtocol; [ usb 2.0 single TT ] */
+#else
0x00, /* __u8 bDeviceProtocol; [ usb 2.0 no TT ] */
+#endif
0x40, /* __u8 bMaxPacketSize0; 64 Bytes */
0x6b, 0x1d, /* __le16 idVendor; Linux Foundation */
@@ -977,10 +981,7 @@ static int register_root_hub(struct usb_hcd *hcd)
if (retval) {
dev_err (parent_dev, "can't register root hub for %s, %d\n",
dev_name(&usb_dev->dev), retval);
- }
- mutex_unlock(&usb_bus_list_lock);
-
- if (retval == 0) {
+ } else {
spin_lock_irq (&hcd_root_hub_lock);
hcd->rh_registered = 1;
spin_unlock_irq (&hcd_root_hub_lock);
@@ -989,6 +990,7 @@ static int register_root_hub(struct usb_hcd *hcd)
if (HCD_DEAD(hcd))
usb_hc_died (hcd); /* This time clean up */
}
+ mutex_unlock(&usb_bus_list_lock);
return retval;
}
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 34bb059..b4688fa 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -24,6 +24,7 @@
#include <linux/kthread.h>
#include <linux/mutex.h>
#include <linux/freezer.h>
+#include <linux/random.h>
#include <asm/uaccess.h>
#include <asm/byteorder.h>
@@ -481,13 +482,16 @@ static void hub_tt_work(struct work_struct *work)
int limit = 100;
spin_lock_irqsave (&hub->tt.lock, flags);
- while (--limit && !list_empty (&hub->tt.clear_list)) {
+ while (!list_empty(&hub->tt.clear_list)) {
struct list_head *next;
struct usb_tt_clear *clear;
struct usb_device *hdev = hub->hdev;
const struct hc_driver *drv;
int status;
+ if (!hub->quiescing && --limit < 0)
+ break;
+
next = hub->tt.clear_list.next;
clear = list_entry (next, struct usb_tt_clear, clear_list);
list_del (&clear->clear_list);
@@ -951,7 +955,7 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type)
if (hub->has_indicators)
cancel_delayed_work_sync(&hub->leds);
if (hub->tt.hub)
- cancel_work_sync(&hub->tt.clear_work);
+ flush_work_sync(&hub->tt.clear_work);
}
/* caller has locked the hub device */
@@ -1902,6 +1906,14 @@ int usb_new_device(struct usb_device *udev)
/* Tell the world! */
announce_device(udev);
+ if (udev->serial)
+ add_device_randomness(udev->serial, strlen(udev->serial));
+ if (udev->product)
+ add_device_randomness(udev->product, strlen(udev->product));
+ if (udev->manufacturer)
+ add_device_randomness(udev->manufacturer,
+ strlen(udev->manufacturer));
+
device_enable_async_suspend(&udev->dev);
/* Register the device. The device driver is responsible
* for configuring the device and invoking the add-device
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 1eebd45..806060c 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1803,7 +1803,6 @@ free_interfaces:
intfc = cp->intf_cache[i];
intf->altsetting = intfc->altsetting;
intf->num_altsetting = intfc->num_altsetting;
- intf->intf_assoc = find_iad(dev, cp, i);
kref_get(&intfc->ref);
alt = usb_altnum_to_altsetting(intf, 0);
@@ -1816,6 +1815,8 @@ free_interfaces:
if (!alt)
alt = &intf->altsetting[0];
+ intf->intf_assoc =
+ find_iad(dev, cp, alt->desc.bInterfaceNumber);
intf->cur_altsetting = alt;
usb_enable_interface(dev, intf, true);
intf->dev.parent = &dev->dev;
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index 4c65eb6..8b2a9d8 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -96,6 +96,10 @@ static const struct usb_device_id usb_quirk_list[] = {
{ USB_DEVICE(0x04b4, 0x0526), .driver_info =
USB_QUIRK_CONFIG_INTF_STRINGS },
+ /* Microchip Joss Optical infrared touchboard device */
+ { USB_DEVICE(0x04d8, 0x000c), .driver_info =
+ USB_QUIRK_CONFIG_INTF_STRINGS },
+
/* Samsung Android phone modem - ID conflict with SPH-I500 */
{ USB_DEVICE(0x04e8, 0x6601), .driver_info =
USB_QUIRK_CONFIG_INTF_STRINGS },
@@ -123,6 +127,9 @@ static const struct usb_device_id usb_quirk_list[] = {
/* Guillemot Webcam Hercules Dualpix Exchange*/
{ USB_DEVICE(0x06f8, 0x3005), .driver_info = USB_QUIRK_RESET_RESUME },
+ /* Midiman M-Audio Keystation 88es */
+ { USB_DEVICE(0x0763, 0x0192), .driver_info = USB_QUIRK_RESET_RESUME },
+
/* M-Systems Flash Disk Pioneers */
{ USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME },
diff --git a/drivers/usb/dwc/Kconfig b/drivers/usb/dwc/Kconfig
new file mode 100644
index 0000000..4439810
--- /dev/null
+++ b/drivers/usb/dwc/Kconfig
@@ -0,0 +1,84 @@
+#
+# USB Dual Role (OTG-ready) Controller Drivers
+# for silicon based on Synopsys DesignWare IP
+#
+
+comment "Enable Host or Gadget support for DesignWare OTG controller"
+ depends on !USB && USB_GADGET=n
+
+config USB_DWC_OTG
+ tristate "Synopsys DWC OTG Controller"
+ depends on USB || USB_GADGET
+ select NOP_USB_XCEIV
+ select USB_OTG_UTILS
+ default USB_GADGET
+ help
+ This driver provides USB Device Controller support for the
+ Synopsys DesignWare USB OTG Core used on the AppliedMicro PowerPC SoC.
+
+config DWC_DEBUG
+ bool "Enable DWC Debugging"
+ depends on USB_DWC_OTG
+ default n
+ help
+ Enable DWC driver debugging
+
+choice
+ prompt "DWC Mode Selection"
+ depends on USB_DWC_OTG
+ default DWC_HOST_ONLY
+ help
+ Select the DWC Core in OTG, Host only, or Device only mode.
+
+config DWC_HOST_ONLY
+ bool "DWC Host Only Mode"
+
+config DWC_OTG_MODE
+ bool "DWC OTG Mode"
+ select USB_GADGET_SELECTED
+
+config DWC_DEVICE_ONLY
+ bool "DWC Device Only Mode"
+ select USB_GADGET_SELECTED
+
+endchoice
+
+# enable peripheral support (including with OTG)
+choice
+ prompt "DWC DMA/SlaveMode Selection"
+ depends on USB_DWC_OTG
+ default DWC_DMA_MODE
+ help
+ Select the DWC DMA or Slave Mode.
+ DMA mode uses the DWC core internal DMA engines.
+ Slave mode uses the processor PIO to tranfer data.
+ In Slave mode, processor's DMA channels can be used if available.
+
+config DWC_SLAVE
+ bool "DWC Slave Mode"
+
+config DWC_DMA_MODE
+ bool "DWC DMA Mode"
+
+endchoice
+
+config DWC_OTG_REG_LE
+ bool "DWC Little Endian Register"
+ depends on USB_DWC_OTG
+ default y
+ help
+ OTG core register access is Little-Endian.
+
+config DWC_OTG_FIFO_LE
+ bool "DWC FIFO Little Endian"
+ depends on USB_DWC_OTG
+ default y
+ help
+ OTG core FIFO access is Little-Endian.
+
+config DWC_LIMITED_XFER_SIZE
+ bool "DWC Endpoint Limited Xfer Size"
+ depends on USB_GADGET_DWC_HDRC
+ default n
+ help
+ Bit fields in the Device EP Transfer Size Register is 11 bits.
diff --git a/drivers/usb/dwc/Makefile b/drivers/usb/dwc/Makefile
new file mode 100644
index 0000000..c79d6e6
--- /dev/null
+++ b/drivers/usb/dwc/Makefile
@@ -0,0 +1,17 @@
+#
+# OTG infrastructure and transceiver drivers
+#
+obj-$(CONFIG_USB_DWC_OTG) += dwc.o
+
+dwc-objs := cil.o cil_intr.o param.o
+
+dwc-objs += apmppc.o
+
+ifneq ($(CONFIG_DWC_DEVICE_ONLY),y)
+dwc-objs += hcd.o hcd_intr.o \
+ hcd_queue.o
+endif
+
+ifneq ($(CONFIG_DWC_HOST_ONLY),y)
+dwc-objs += pcd.o pcd_intr.o
+endif
diff --git a/drivers/usb/dwc/apmppc.c b/drivers/usb/dwc/apmppc.c
new file mode 100644
index 0000000..81881d0
--- /dev/null
+++ b/drivers/usb/dwc/apmppc.c
@@ -0,0 +1,372 @@
+/*
+ * DesignWare HS OTG controller driver
+ * Copyright (C) 2006 Synopsys, Inc.
+ * Portions Copyright (C) 2010 Applied Micro Circuits Corporation.
+ *
+ * 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 version 2 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
+ * or write to the Free Software Foundation, Inc., 51 Franklin Street,
+ * Suite 500, Boston, MA 02110-1335 USA.
+ *
+ * Based on Synopsys driver version 2.60a
+ * Modified by Mark Miesfeld <mmiesfeld@apm.com>
+ * Modified by Stefan Roese <sr@denx.de>, DENX Software Engineering
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL SYNOPSYS, INC. BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * The dwc_otg module provides the initialization and cleanup entry
+ * points for the dwcotg driver. This module will be dynamically installed
+ * after Linux is booted using the insmod command. When the module is
+ * installed, the dwc_otg_driver_init function is called. When the module is
+ * removed (using rmmod), the dwc_otg_driver_cleanup function is called.
+ *
+ * This module also defines a data structure for the dwc_otg driver, which is
+ * used in conjunction with the standard device structure. These
+ * structures allow the OTG driver to comply with the standard Linux driver
+ * model in which devices and drivers are registered with a bus driver. This
+ * has the benefit that Linux can expose attributes of the driver and device
+ * in its special sysfs file system. Users can then read or write files in
+ * this file system to perform diagnostics on the driver components or the
+ * device.
+ */
+
+#include <linux/of_platform.h>
+#include <mach/map.h>
+#include <linux/platform_device.h>
+#include "driver.h"
+#include <linux/delay.h>
+
+#define DWC_DRIVER_VERSION "1.05"
+#define DWC_DRIVER_DESC "HS OTG USB Controller driver"
+static const char dwc_driver_name[] = "dwc_otg";
+
+static irqreturn_t dwc_otg_common_irq(int _irq, void *dev)
+{
+ struct dwc_otg_device *dwc_dev = dev;
+ int retval;
+ struct dwc_hcd *dwc_hcd;
+
+ dwc_hcd = dwc_dev->hcd;
+ spin_lock(&dwc_hcd->lock);
+ retval = dwc_otg_handle_common_intr(dwc_dev->core_if);
+ spin_unlock(&dwc_hcd->lock);
+ return IRQ_RETVAL(retval);
+}
+
+static irqreturn_t dwc_otg_externalchgpump_irq(int _irq, void *dev)
+{
+ struct dwc_otg_device *dwc_dev = dev;
+
+ if (dwc_otg_is_host_mode(dwc_dev->core_if)) {
+ struct dwc_hcd *dwc_hcd;
+ u32 hprt0 = 0;
+
+ dwc_hcd = dwc_dev->hcd;
+ spin_lock(&dwc_hcd->lock);
+ dwc_hcd->flags.b.port_over_current_change = 1;
+
+ hprt0 = DWC_HPRT0_PRT_PWR_RW(hprt0, 0);
+ dwc_reg_write(dwc_dev->core_if->host_if->hprt0, 0, hprt0);
+ spin_unlock(&dwc_hcd->lock);
+ } else {
+ /* Device mode - This int is n/a for device mode */
+ dev_dbg(dev, "DeviceMode: OTG OverCurrent Detected\n");
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int __devexit dwc_otg_driver_remove(struct platform_device *ofdev)
+{
+ struct device *dev = &ofdev->dev;
+ struct dwc_otg_device *dwc_dev = dev_get_drvdata(dev);
+
+ /* Memory allocation for dwc_otg_device may have failed. */
+ if (!dwc_dev)
+ return 0;
+
+ /* Free the IRQ */
+ free_irq(dwc_dev->irq, dwc_dev);
+ /* Free external charge pump irq */
+ free_irq(dwc_dev->hcd->cp_irq, dwc_dev);
+
+ if (dwc_dev->hcd)
+ dwc_otg_hcd_remove(dev);
+
+ if (dwc_dev->pcd)
+ dwc_otg_pcd_remove(dev);
+
+ if (dwc_dev->core_if)
+ dwc_otg_cil_remove(dwc_dev->core_if);
+
+ /* Return the memory. */
+ if (dwc_dev->base)
+ iounmap(dwc_dev->base);
+
+ if (dwc_dev->phys_addr)
+ release_mem_region(dwc_dev->phys_addr, dwc_dev->base_len);
+
+ otg_put_transceiver(dwc_dev->core_if->xceiv);
+ dwc_dev->core_if->xceiv = NULL;
+
+ kfree(dwc_dev);
+
+ /* Clear the drvdata pointer. */
+ dev_set_drvdata(dev, NULL);
+ return 0;
+}
+
+static int dwc_otg_driver_probe(struct platform_device *ofdev)
+{
+ int retval,reg_val;
+ struct dwc_otg_device *dwc_dev;
+ struct device *dev = &ofdev->dev;
+ struct resource res;
+ ulong gusbcfg_addr;
+ u32 usbcfg = 0;
+
+ dwc_dev = kzalloc(sizeof(*dwc_dev), GFP_KERNEL);
+ if (!dwc_dev) {
+ dev_err(dev, "kmalloc of dwc_otg_device failed\n");
+ retval = -ENOMEM;
+ goto fail_dwc_dev;
+ }
+
+ /* Retrieve the memory and IRQ resources. */
+ dwc_dev->irq = ofdev->resource[1].start;
+ if (dwc_dev->irq == NO_IRQ) {
+ dev_err(dev, "no device irq\n");
+ retval = -ENODEV;
+ goto fail_of_irq;
+ }
+
+ res = ofdev->resource[0];
+/* if (of_address_to_resource(ofdev->dev.of_node, 0, &res)) {
+ dev_err(dev, "%s: Can't get USB-OTG register address\n",
+ __func__);
+ retval = -ENOMEM;
+ goto fail_of_irq;
+ }*/
+
+ dwc_dev->phys_addr = res.start;
+ dwc_dev->base_len = res.end - res.start + 1;
+ if (!request_mem_region(dwc_dev->phys_addr,
+ dwc_dev->base_len, dwc_driver_name)) {
+ dev_err(dev, "request_mem_region failed\n");
+ retval = -EBUSY;
+ goto fail_of_irq;
+ }
+
+ /* Map the DWC_otg Core memory into virtual address space. */
+ dwc_dev->base = ioremap(dwc_dev->phys_addr, dwc_dev->base_len);
+ if (!dwc_dev->base) {
+ dev_err(dev, "ioremap() failed\n");
+ retval = -ENOMEM;
+ goto fail_ioremap;
+ }
+ dev_dbg(dev, "mapped base=0x%08x\n", (__force u32)dwc_dev->base);
+
+ /**
+ * Attempt to ensure this device is really a Synopsys USB-OTG Controller.
+ * Read and verify the SNPSID register contents. The value should be
+ * 0x45F42XXX, which corresponds to "OT2", as in "OTG version 2.XX".
+ */
+ reg_val = readl(dwc_dev->base+0x40);
+ if ((reg_val & 0xFFFFF000) != 0x4F542000) {
+ dev_err(dev,"Bad value for SNPSID: 0x%x\n", reg_val);
+ retval = -EINVAL;
+ goto fail_invalid_device;
+ }
+
+ /*
+ * Initialize driver data to point to the global DWC_otg
+ * Device structure.
+ */
+ dev_set_drvdata(dev, dwc_dev);
+
+ dwc_dev->core_if =
+ dwc_otg_cil_init(dwc_dev->base, &dwc_otg_module_params);
+ if (!dwc_dev->core_if) {
+ dev_err(dev, "CIL initialization failed!\n");
+ retval = -ENOMEM;
+ goto fail_cil_init;
+ }
+
+ /*
+ * Validate parameter values after dwc_otg_cil_init.
+ */
+ if (check_parameters(dwc_dev->core_if)) {
+ retval = -EINVAL;
+ goto fail_check_param;
+ }
+
+ usb_nop_xceiv_register();
+ dwc_dev->core_if->xceiv = otg_get_transceiver();
+ if (!dwc_dev->core_if->xceiv) {
+ retval = -ENODEV;
+ goto fail_xceiv;
+ }
+ dwc_set_feature(dwc_dev->core_if);
+
+ /* Initialize the DWC_otg core. */
+ dwc_otg_core_init(dwc_dev->core_if);
+
+ /*
+ * Disable the global interrupt until all the interrupt
+ * handlers are installed.
+ */
+ spin_lock(&dwc_dev->hcd->lock);
+ dwc_otg_disable_global_interrupts(dwc_dev->core_if);
+ spin_unlock(&dwc_dev->hcd->lock);
+
+ /*
+ * Install the interrupt handler for the common interrupts before
+ * enabling common interrupts in core_init below.
+ */
+ retval = request_irq(dwc_dev->irq, dwc_otg_common_irq,
+ IRQF_SHARED, "dwc_otg", dwc_dev);
+ if (retval) {
+ dev_err(dev, "request of irq%d failed retval: %d\n",
+ dwc_dev->irq, retval);
+ retval = -EBUSY;
+ goto fail_req_irq;
+ } else {
+ dwc_dev->common_irq_installed = 1;
+ }
+
+ if (!dwc_has_feature(dwc_dev->core_if, DWC_HOST_ONLY)) {
+ /* Initialize the PCD */
+ retval = dwc_otg_pcd_init(dev);
+ if (retval) {
+ dev_err(dev, "dwc_otg_pcd_init failed\n");
+ dwc_dev->pcd = NULL;
+ goto fail_req_irq;
+ }
+ }
+
+ gusbcfg_addr = (ulong) (dwc_dev->core_if->core_global_regs)
+ + DWC_GUSBCFG;
+ if (!dwc_has_feature(dwc_dev->core_if, DWC_DEVICE_ONLY)) {
+ /* Initialize the HCD and force_host_mode */
+ usbcfg = dwc_reg_read(gusbcfg_addr, 0);
+ usbcfg |= DWC_USBCFG_FRC_HST_MODE;
+ dwc_reg_write(gusbcfg_addr, 0, usbcfg);
+
+ retval = dwc_otg_hcd_init(dev, dwc_dev);
+ if (retval) {
+ dev_err(dev, "dwc_otg_hcd_init failed\n");
+ dwc_dev->hcd = NULL;
+ goto fail_hcd;
+ }
+ /* configure chargepump interrupt */
+ dwc_dev->hcd->cp_irq = 0;//irq_of_parse_and_map(ofdev->dev.of_node, 3);
+ if (dwc_dev->hcd->cp_irq) {
+ retval = request_irq(dwc_dev->hcd->cp_irq,
+ dwc_otg_externalchgpump_irq,
+ IRQF_SHARED,
+ "dwc_otg_ext_chg_pump", dwc_dev);
+ if (retval) {
+ dev_err(dev,
+ "request of irq failed retval: %d\n",
+ retval);
+ retval = -EBUSY;
+ goto fail_hcd;
+ } else {
+ dev_dbg(dev, "%s: ExtChgPump Detection "
+ "IRQ registered\n", dwc_driver_name);
+ }
+ }
+ }
+ /*
+ * Enable the global interrupt after all the interrupt
+ * handlers are installed.
+ */
+ dwc_otg_enable_global_interrupts(dwc_dev->core_if);
+
+ usbcfg = dwc_reg_read(gusbcfg_addr, 0);
+ usbcfg &= ~DWC_USBCFG_FRC_HST_MODE;
+ dwc_reg_write(gusbcfg_addr, 0, usbcfg);
+
+ printk("Done\n");msleep(100);
+
+ return 0;
+fail_hcd:
+ free_irq(dwc_dev->irq, dwc_dev);
+ if (!dwc_has_feature(dwc_dev->core_if, DWC_HOST_ONLY)) {
+ if (dwc_dev->pcd)
+ dwc_otg_pcd_remove(dev);
+ }
+fail_req_irq:
+ otg_put_transceiver(dwc_dev->core_if->xceiv);
+fail_xceiv:
+ usb_nop_xceiv_unregister();
+fail_check_param:
+ dwc_otg_cil_remove(dwc_dev->core_if);
+fail_cil_init:
+ dev_set_drvdata(dev, NULL);
+fail_invalid_device:
+ iounmap(dwc_dev->base);
+fail_ioremap:
+ release_mem_region(dwc_dev->phys_addr, dwc_dev->base_len);
+fail_of_irq:
+ kfree(dwc_dev);
+fail_dwc_dev:
+ return retval;
+}
+
+/* static const struct of_device_id dwc_otg_match[] = {
+ {.compatible = "amcc,dwc-otg",},
+ {}
+};
+
+MODULE_DEVICE_TABLE(of, dwc_otg_match); */
+
+struct platform_driver dwc_otg_driver = {
+ .probe = dwc_otg_driver_probe,
+ .remove = __devexit_p(dwc_otg_driver_remove),
+ .driver = {
+ .name = "dwc_otg",
+ .owner = THIS_MODULE,
+// .of_match_table = dwc_otg_match,
+ },
+};
+
+/*static int dwc_otg_driver_init(void)
+{
+
+ return platform_driver_register(&dwc_otg_driver);
+}
+
+module_init(dwc_otg_driver_init);
+
+static void __exit dwc_otg_driver_cleanup(void)
+{
+ platform_driver_unregister(&dwc_otg_driver);
+}
+
+module_exit(dwc_otg_driver_cleanup);*/
+
+MODULE_DESCRIPTION(DWC_DRIVER_DESC);
+MODULE_AUTHOR("Mark Miesfeld <mmiesfeld@apm.com");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/dwc/cil.c b/drivers/usb/dwc/cil.c
new file mode 100644
index 0000000..8d7a9e8
--- /dev/null
+++ b/drivers/usb/dwc/cil.c
@@ -0,0 +1,893 @@
+/*
+ * DesignWare HS OTG controller driver
+ * Copyright (C) 2006 Synopsys, Inc.
+ * Portions Copyright (C) 2010 Applied Micro Circuits Corporation.
+ *
+ * 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 version 2 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
+ * or write to the Free Software Foundation, Inc., 51 Franklin Street,
+ * Suite 500, Boston, MA 02110-1335 USA.
+ *
+ * Based on Synopsys driver version 2.60a
+ * Modified by Mark Miesfeld <mmiesfeld@apm.com>
+ * Modified by Stefan Roese <sr@denx.de>, DENX Software Engineering
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL SYNOPSYS, INC. BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <linux/delay.h>
+
+#include "cil.h"
+
+void dwc_otg_enable_global_interrupts(struct core_if *core_if)
+{
+ u32 ahbcfg = 0;
+
+ ahbcfg |= DWC_AHBCFG_GLBL_INT_MASK;
+ dwc_reg_modify(core_if->core_global_regs, DWC_GAHBCFG, 0,
+ ahbcfg);
+}
+
+void dwc_otg_disable_global_interrupts(struct core_if *core_if)
+{
+ u32 ahbcfg = 0;
+
+ ahbcfg |= DWC_AHBCFG_GLBL_INT_MASK;
+ dwc_reg_modify(core_if->core_global_regs, DWC_GAHBCFG,
+ ahbcfg, 0);
+}
+
+/**
+ * Tests if the current hardware is using a full speed phy.
+ */
+static inline int full_speed_phy(struct core_if *core_if)
+{
+ if ((DWC_HWCFG2_HS_PHY_TYPE_RD(core_if->hwcfg2) == 2 &&
+ DWC_HWCFG2_FS_PHY_TYPE_RD(core_if->hwcfg2) == 1 &&
+ core_if->core_params->ulpi_fs_ls) ||
+ core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)
+ return 1;
+ return 0;
+}
+
+/**
+ * Initializes the FSLSPClkSel field of the HCFG register depending on the PHY
+ * type.
+ */
+void init_fslspclksel(struct core_if *core_if)
+{
+ u32 val;
+ u32 hcfg = 0;
+
+ if (full_speed_phy(core_if))
+ val = DWC_HCFG_48_MHZ;
+ else
+ /* High speed PHY running at full speed or high speed */
+ val = DWC_HCFG_30_60_MHZ;
+
+ hcfg = dwc_reg_read(core_if->host_if->host_global_regs, DWC_HCFG);
+ hcfg = DWC_HCFG_FSLSP_CLK_RW(hcfg, val);
+ dwc_reg_write(core_if->host_if->host_global_regs, DWC_HCFG, hcfg);
+}
+
+/**
+ * Initializes the DevSpd field of the DCFG register depending on the PHY type
+ * and the enumeration speed of the device.
+ */
+static void init_devspd(struct core_if *core_if)
+{
+ u32 val;
+ u32 dcfg;
+
+ if (full_speed_phy(core_if))
+ val = 0x3;
+ else if (core_if->core_params->speed == DWC_SPEED_PARAM_FULL)
+ /* High speed PHY running at full speed */
+ val = 0x1;
+ else
+ /* High speed PHY running at high speed */
+ val = 0x0;
+
+ dcfg = dwc_reg_read(core_if->dev_if->dev_global_regs, DWC_DCFG);
+ dcfg = DWC_DCFG_DEV_SPEED_WR(dcfg, val);
+ dwc_reg_write(core_if->dev_if->dev_global_regs, DWC_DCFG, dcfg);
+}
+
+/**
+ * This function calculates the number of IN EPS using GHWCFG1 and GHWCFG2
+ * registers values
+ */
+static u32 calc_num_in_eps(struct core_if *core_if)
+{
+ u32 num_in_eps = 0;
+ u32 num_eps = DWC_HWCFG2_NO_DEV_EP_RD(core_if->hwcfg2);
+ u32 hwcfg1 = core_if->hwcfg1 >> 2;
+ u32 num_tx_fifos = DWC_HWCFG4_NUM_IN_EPS_RD(core_if->hwcfg4);
+ u32 i;
+
+ for (i = 0; i < num_eps; ++i) {
+ if (!(hwcfg1 & 0x1))
+ num_in_eps++;
+ hwcfg1 >>= 2;
+ }
+
+ if (DWC_HWCFG4_DED_FIFO_ENA_RD(core_if->hwcfg4))
+ num_in_eps = num_in_eps > num_tx_fifos ?
+ num_tx_fifos : num_in_eps;
+
+ return num_in_eps;
+}
+
+/**
+ * This function calculates the number of OUT EPS using GHWCFG1 and GHWCFG2
+ * registers values
+ */
+static u32 calc_num_out_eps(struct core_if *core_if)
+{
+ u32 num_out_eps = 0;
+ u32 num_eps = DWC_HWCFG2_NO_DEV_EP_RD(core_if->hwcfg2);
+ u32 hwcfg1 = core_if->hwcfg1 >> 2;
+ u32 i;
+
+ for (i = 0; i < num_eps; ++i) {
+ if (!(hwcfg1 & 0x2))
+ num_out_eps++;
+ hwcfg1 >>= 2;
+ }
+ return num_out_eps;
+}
+
+/**
+ * Do core a soft reset of the core. Be careful with this because it
+ * resets all the internal state machines of the core.
+ */
+extern void otg_host_phy_init(void);
+static void dwc_otg_core_reset(struct core_if *core_if)
+{
+ ulong global_regs = core_if->core_global_regs;
+ u32 greset = 0;
+ int count = 0;
+
+ otg_host_phy_init();
+
+ /* Wait for AHB master IDLE state. */
+ do {
+ udelay(10);
+ greset = dwc_reg_read(global_regs, DWC_GRSTCTL);
+ if (++count > 100000) {
+ pr_warning("%s() HANG! AHB Idle GRSTCTL=%0x\n",
+ __func__, greset);
+ return;
+ }
+ } while (!(greset & DWC_RSTCTL_AHB_IDLE));
+
+ /* Core Soft Reset */
+ count = 0;
+ greset |= DWC_RSTCTL_SFT_RST;
+ dwc_reg_write(global_regs, DWC_GRSTCTL, greset);
+
+ do {
+ greset = dwc_reg_read(global_regs, DWC_GRSTCTL);
+ if (++count > 10000) {
+ pr_warning("%s() HANG! Soft Reset "
+ "GRSTCTL=%0x\n", __func__, greset);
+ break;
+ }
+ udelay(1);
+ } while (greset & DWC_RSTCTL_SFT_RST);
+
+ /* Wait for 3 PHY Clocks */
+ msleep(100);
+}
+
+/**
+ * This function initializes the commmon interrupts, used in both
+ * device and host modes.
+ */
+void dwc_otg_enable_common_interrupts(struct core_if *core_if)
+{
+ ulong global_regs = core_if->core_global_regs;
+ u32 intr_mask = 0;
+
+ /* Clear any pending OTG Interrupts */
+ dwc_reg_write(global_regs, DWC_GOTGINT, 0xFFFFFFFF);
+
+ /* Clear any pending interrupts */
+ dwc_reg_write(global_regs, DWC_GINTSTS, 0xFFFFFFFF);
+
+ /* Enable the interrupts in the GINTMSK. */
+ intr_mask |= DWC_INTMSK_MODE_MISMTC;
+ intr_mask |= DWC_INTMSK_OTG;
+ intr_mask |= DWC_INTMSK_CON_ID_STS_CHG;
+ intr_mask |= DWC_INTMSK_WKP;
+ intr_mask |= DWC_INTMSK_SES_DISCON_DET;
+ intr_mask |= DWC_INTMSK_USB_SUSP;
+ intr_mask |= DWC_INTMSK_NEW_SES_DET;
+ if (!core_if->dma_enable)
+ intr_mask |= DWC_INTMSK_RXFIFO_NOT_EMPT;
+ dwc_reg_write(global_regs, DWC_GINTMSK, intr_mask);
+}
+
+/**
+ * This function initializes the DWC_otg controller registers and prepares the
+ * core for device mode or host mode operation.
+ */
+void dwc_otg_core_init(struct core_if *core_if)
+{
+ u32 i;
+ ulong global_reg = core_if->core_global_regs;
+ struct device_if *dev_if = core_if->dev_if;
+ u32 ahbcfg = 0;
+ u32 i2cctl = 0;
+ u32 gusbcfg;
+
+ /* Common Initialization */
+ gusbcfg = dwc_reg_read(global_reg, DWC_GUSBCFG);
+
+ /* Program the ULPI External VBUS bit if needed */
+ gusbcfg |= DWC_USBCFG_ULPI_EXT_VBUS_DRV;
+
+ /* Set external TS Dline pulsing */
+ if (core_if->core_params->ts_dline == 1)
+ gusbcfg |= DWC_USBCFG_TERM_SEL_DL_PULSE;
+ else
+ gusbcfg = gusbcfg & (~((u32) DWC_USBCFG_TERM_SEL_DL_PULSE));
+
+ dwc_reg_write(global_reg, DWC_GUSBCFG, gusbcfg);
+
+ /* Reset the Controller */
+ dwc_otg_core_reset(core_if);
+
+ /* Initialize parameters from Hardware configuration registers. */
+ dev_if->num_in_eps = calc_num_in_eps(core_if);
+ dev_if->num_out_eps = calc_num_out_eps(core_if);
+
+ for (i = 0; i < DWC_HWCFG4_NUM_DEV_PERIO_IN_EP_RD(core_if->hwcfg4);
+ i++) {
+ dev_if->perio_tx_fifo_size[i] =
+ dwc_reg_read(global_reg, DWC_DPTX_FSIZ_DIPTXF(i)) >> 16;
+ }
+ for (i = 0; i < DWC_HWCFG4_NUM_IN_EPS_RD(core_if->hwcfg4); i++) {
+ dev_if->tx_fifo_size[i] =
+ dwc_reg_read(global_reg, DWC_DPTX_FSIZ_DIPTXF(i)) >> 16;
+ }
+
+ core_if->total_fifo_size = DWC_HWCFG3_DFIFO_DEPTH_RD(core_if->hwcfg3);
+ core_if->rx_fifo_size = dwc_reg_read(global_reg, DWC_GRXFSIZ);
+ core_if->nperio_tx_fifo_size =
+ dwc_reg_read(global_reg, DWC_GRXFSIZ) >> 16;
+ /*
+ * This programming sequence needs to happen in FS mode before any
+ * other programming occurs
+ */
+ if (core_if->core_params->speed == DWC_SPEED_PARAM_FULL &&
+ core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS) {
+ /*
+ * core_init() is now called on every switch so only call the
+ * following for the first time through.
+ */
+ if (!core_if->phy_init_done) {
+ core_if->phy_init_done = 1;
+ gusbcfg = dwc_reg_read(global_reg, DWC_GUSBCFG);
+ gusbcfg |= DWC_USBCFG_ULPI_UTMI_SEL;
+ dwc_reg_write(global_reg, DWC_GUSBCFG, gusbcfg);
+
+ /* Reset after a PHY select */
+ dwc_otg_core_reset(core_if);
+ }
+
+ /*
+ * Program DCFG.DevSpd or HCFG.FSLSPclkSel to 48Mhz in FS.
+ * Also do this on HNP Dev/Host mode switches (done in dev_init
+ * and host_init).
+ */
+ if (dwc_otg_is_host_mode(core_if))
+ init_fslspclksel(core_if);
+ else
+ init_devspd(core_if);
+
+ if (core_if->core_params->i2c_enable) {
+ /* Program GUSBCFG.OtgUtmifsSel to I2C */
+ gusbcfg = dwc_reg_read(global_reg, DWC_GUSBCFG);
+ gusbcfg |= DWC_USBCFG_OTGUTMIFSSEL;
+ dwc_reg_write(global_reg, DWC_GUSBCFG, gusbcfg);
+
+ /* Program GI2CCTL.I2CEn */
+ i2cctl = dwc_reg_read(global_reg, DWC_GI2CCTL);
+ i2cctl |= DWC_I2CCTL_I2CDEVADDR(1);
+ i2cctl &= ~DWC_I2CCTL_I2CEN;
+ dwc_reg_write(global_reg, DWC_GI2CCTL, i2cctl);
+ i2cctl |= DWC_I2CCTL_I2CEN;
+ dwc_reg_write(global_reg, DWC_GI2CCTL, i2cctl);
+ }
+ } else if (!core_if->phy_init_done) {
+ gusbcfg = dwc_reg_read(global_reg, DWC_GUSBCFG);
+ core_if->phy_init_done = 1;
+ if (core_if->core_params->phy_type)
+ gusbcfg |= DWC_USBCFG_ULPI_UTMI_SEL;
+ else
+ gusbcfg &= ~((u32) DWC_USBCFG_ULPI_UTMI_SEL);
+
+ if (gusbcfg & DWC_USBCFG_ULPI_UTMI_SEL) {
+ /* ULPI interface */
+ gusbcfg |= DWC_USBCFG_PHYIF;
+ if (core_if->core_params->phy_ulpi_ddr)
+ gusbcfg |= DWC_USBCFG_DDRSEL;
+ else
+ gusbcfg &= ~((u32) DWC_USBCFG_DDRSEL);
+ } else {
+ /* UTMI+ interface */
+ if (core_if->core_params->phy_utmi_width == 16)
+ gusbcfg |= DWC_USBCFG_PHYIF;
+ else
+ gusbcfg &= ~((u32) DWC_USBCFG_PHYIF);
+ }
+ dwc_reg_write(global_reg, DWC_GUSBCFG, gusbcfg);
+
+ /* Reset after setting the PHY parameters */
+ dwc_otg_core_reset(core_if);
+ }
+
+ if (DWC_HWCFG2_HS_PHY_TYPE_RD(core_if->hwcfg2) == 2 &&
+ DWC_HWCFG2_FS_PHY_TYPE_RD(core_if->hwcfg2) == 1 &&
+ core_if->core_params->ulpi_fs_ls) {
+ gusbcfg = dwc_reg_read(global_reg, DWC_GUSBCFG);
+ gusbcfg |= DWC_USBCFG_ULPI_FSLS;
+ gusbcfg |= DWC_USBCFG_ULPI_CLK_SUS_M;
+ dwc_reg_write(global_reg, DWC_GUSBCFG, gusbcfg);
+ } else {
+ gusbcfg = dwc_reg_read(global_reg, DWC_GUSBCFG);
+ gusbcfg &= ~((u32) DWC_USBCFG_ULPI_FSLS);
+ gusbcfg &= ~((u32) DWC_USBCFG_ULPI_CLK_SUS_M);
+ dwc_reg_write(global_reg, DWC_GUSBCFG, gusbcfg);
+ }
+
+ /* Program the GAHBCFG Register. */
+ switch (DWC_HWCFG2_ARCH_RD(core_if->hwcfg2)) {
+ case DWC_SLAVE_ONLY_ARCH:
+ ahbcfg &= ~DWC_AHBCFG_NPFIFO_EMPTY; /* HALF empty */
+ ahbcfg &= ~DWC_AHBCFG_FIFO_EMPTY; /* HALF empty */
+ core_if->dma_enable = 0;
+ break;
+ case DWC_EXT_DMA_ARCH:
+ ahbcfg = (ahbcfg & ~DWC_AHBCFG_BURST_LEN(0xf)) |
+ DWC_AHBCFG_BURST_LEN(core_if->core_params->dma_burst_size);
+ core_if->dma_enable = (core_if->core_params->dma_enable != 0);
+ break;
+ case DWC_INT_DMA_ARCH:
+ ahbcfg = (ahbcfg & ~DWC_AHBCFG_BURST_LEN(0xf)) |
+ DWC_AHBCFG_BURST_LEN(DWC_GAHBCFG_INT_DMA_BURST_INCR);
+ core_if->dma_enable = (core_if->core_params->dma_enable != 0);
+ break;
+ }
+
+ if (core_if->dma_enable)
+ ahbcfg |= DWC_AHBCFG_DMA_ENA;
+ else
+ ahbcfg &= ~DWC_AHBCFG_DMA_ENA;
+ dwc_reg_write(global_reg, DWC_GAHBCFG, ahbcfg);
+ core_if->en_multiple_tx_fifo =
+ DWC_HWCFG4_DED_FIFO_ENA_RD(core_if->hwcfg4);
+
+ /* Program the GUSBCFG register. */
+ gusbcfg = dwc_reg_read(global_reg, DWC_GUSBCFG);
+ switch (DWC_HWCFG2_OP_MODE_RD(core_if->hwcfg2)) {
+ case DWC_MODE_HNP_SRP_CAPABLE:
+ if (core_if->core_params->otg_cap ==
+ DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE)
+ gusbcfg |= DWC_USBCFG_HNP_CAP;
+ else
+ gusbcfg &= ~((u32) DWC_USBCFG_HNP_CAP);
+ if (core_if->core_params->otg_cap !=
+ DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE)
+ gusbcfg |= DWC_USBCFG_SRP_CAP;
+ else
+ gusbcfg &= ~((u32) DWC_USBCFG_SRP_CAP);
+ break;
+ case DWC_MODE_SRP_ONLY_CAPABLE:
+ gusbcfg &= ~((u32) DWC_USBCFG_HNP_CAP);
+ if (core_if->core_params->otg_cap !=
+ DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE)
+ gusbcfg |= DWC_USBCFG_SRP_CAP;
+ else
+ gusbcfg &= ~((u32) DWC_USBCFG_SRP_CAP);
+ break;
+ case DWC_MODE_NO_HNP_SRP_CAPABLE:
+ gusbcfg &= ~((u32) DWC_USBCFG_HNP_CAP);
+ gusbcfg &= ~((u32) DWC_USBCFG_SRP_CAP);
+ break;
+ case DWC_MODE_SRP_CAPABLE_DEVICE:
+ gusbcfg &= ~((u32) DWC_USBCFG_HNP_CAP);
+ if (core_if->core_params->otg_cap !=
+ DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE)
+ gusbcfg |= DWC_USBCFG_SRP_CAP;
+ else
+ gusbcfg &= ~((u32) DWC_USBCFG_SRP_CAP);
+ break;
+ case DWC_MODE_NO_SRP_CAPABLE_DEVICE:
+ gusbcfg &= ~((u32) DWC_USBCFG_HNP_CAP);
+ gusbcfg &= ~((u32) DWC_USBCFG_SRP_CAP);
+ break;
+ case DWC_MODE_SRP_CAPABLE_HOST:
+ gusbcfg &= ~((u32) DWC_USBCFG_HNP_CAP);
+ if (core_if->core_params->otg_cap !=
+ DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE)
+ gusbcfg |= DWC_USBCFG_SRP_CAP;
+ else
+ gusbcfg &= ~((u32) DWC_USBCFG_SRP_CAP);
+ break;
+ case DWC_MODE_NO_SRP_CAPABLE_HOST:
+ gusbcfg &= ~((u32) DWC_USBCFG_HNP_CAP);
+ gusbcfg &= ~((u32) DWC_USBCFG_SRP_CAP);
+ break;
+ }
+ dwc_reg_write(global_reg, DWC_GUSBCFG, gusbcfg);
+
+ /* Enable common interrupts */
+ dwc_otg_enable_common_interrupts(core_if);
+
+ /*
+ * Do device or host intialization based on mode during PCD
+ * and HCD initialization
+ */
+ if (dwc_otg_is_host_mode(core_if)) {
+ core_if->xceiv->state = OTG_STATE_A_HOST;
+ } else {
+ core_if->xceiv->state = OTG_STATE_B_PERIPHERAL;
+ if (dwc_has_feature(core_if, DWC_DEVICE_ONLY))
+ dwc_otg_core_dev_init(core_if);
+ }
+}
+
+/**
+ * This function enables the Device mode interrupts.
+ *
+ * Note that the bits in the Device IN endpoint mask register are laid out
+ * exactly the same as the Device IN endpoint interrupt register.
+ */
+static void dwc_otg_enable_device_interrupts(struct core_if *core_if)
+{
+ u32 intr_mask = 0;
+ u32 msk = 0;
+ ulong global_regs = core_if->core_global_regs;
+
+ /* Disable all interrupts. */
+ dwc_reg_write(global_regs, DWC_GINTMSK, 0);
+
+ /* Clear any pending interrupts */
+ dwc_reg_write(global_regs, DWC_GINTSTS, 0xFFFFFFFF);
+
+ /* Enable the common interrupts */
+ dwc_otg_enable_common_interrupts(core_if);
+
+ /* Enable interrupts */
+ intr_mask |= DWC_INTMSK_USB_RST;
+ intr_mask |= DWC_INTMSK_ENUM_DONE;
+ intr_mask |= DWC_INTMSK_IN_ENDP;
+ intr_mask |= DWC_INTMSK_OUT_ENDP;
+ intr_mask |= DWC_INTMSK_EARLY_SUSP;
+ if (!core_if->en_multiple_tx_fifo)
+ intr_mask |= DWC_INTMSK_ENDP_MIS_MTCH;
+
+ /* Periodic EP */
+ intr_mask |= DWC_INTMSK_ISYNC_OUTPKT_DRP;
+ intr_mask |= DWC_INTMSK_END_OF_PFRM;
+ intr_mask |= DWC_INTMSK_INCMP_IN_ATX;
+ intr_mask |= DWC_INTMSK_INCMP_OUT_PTX;
+
+ dwc_reg_modify(global_regs, DWC_GINTMSK, intr_mask, intr_mask);
+
+ msk = DWC_DIEPMSK_TXFIFO_UNDERN_RW(msk, 1);
+ dwc_reg_modify(core_if->dev_if->dev_global_regs, DWC_DIEPMSK,
+ msk, msk);
+}
+
+/**
+ * Configures the device data fifo sizes when dynamic sizing is enabled.
+ */
+static void config_dev_dynamic_fifos(struct core_if *core_if)
+{
+ u32 i;
+ ulong regs = core_if->core_global_regs;
+ struct core_params *params = core_if->core_params;
+ u32 txsize = 0;
+ u32 nptxsize = 0;
+ u32 ptxsize = 0;
+
+ /* Rx FIFO */
+ dwc_reg_write(regs, DWC_GRXFSIZ, params->dev_rx_fifo_size);
+
+ /* Set Periodic and Non-periodic Tx FIFO Mask bits to all 0 */
+ core_if->p_tx_msk = 0;
+ core_if->tx_msk = 0;
+
+ if (core_if->en_multiple_tx_fifo == 0) {
+ /* Non-periodic Tx FIFO */
+ nptxsize = DWC_RX_FIFO_DEPTH_WR(nptxsize,
+ params->
+ dev_nperio_tx_fifo_size);
+ nptxsize =
+ DWC_RX_FIFO_START_ADDR_WR(nptxsize,
+ params->dev_rx_fifo_size);
+ dwc_reg_write(regs, DWC_GNPTXFSIZ, nptxsize);
+
+ ptxsize = DWC_RX_FIFO_START_ADDR_WR(ptxsize,
+ (DWC_RX_FIFO_START_ADDR_RD
+ (nptxsize) +
+ DWC_RX_FIFO_DEPTH_RD
+ (nptxsize)));
+ for (i = 0;
+ i < DWC_HWCFG4_NUM_DEV_PERIO_IN_EP_RD(core_if->hwcfg4);
+ i++) {
+ ptxsize =
+ DWC_RX_FIFO_DEPTH_WR(ptxsize,
+ params->
+ dev_perio_tx_fifo_size[i]);
+ dwc_reg_write(regs, DWC_DPTX_FSIZ_DIPTXF(i), ptxsize);
+ ptxsize = DWC_RX_FIFO_START_ADDR_WR(ptxsize,
+ (DWC_RX_FIFO_START_ADDR_RD
+ (ptxsize) +
+ DWC_RX_FIFO_DEPTH_RD
+ (ptxsize)));
+ }
+ } else {
+ nptxsize = DWC_RX_FIFO_DEPTH_WR(nptxsize,
+ params->
+ dev_nperio_tx_fifo_size);
+ nptxsize =
+ DWC_RX_FIFO_START_ADDR_WR(nptxsize,
+ params->dev_rx_fifo_size);
+ dwc_reg_write(regs, DWC_GNPTXFSIZ, nptxsize);
+
+ txsize = DWC_RX_FIFO_START_ADDR_WR(txsize,
+ (DWC_RX_FIFO_START_ADDR_RD
+ (nptxsize) +
+ DWC_RX_FIFO_DEPTH_RD
+ (nptxsize)));
+ for (i = 1;
+ i < DWC_HWCFG4_NUM_DEV_PERIO_IN_EP_RD(core_if->hwcfg4);
+ i++) {
+ txsize =
+ DWC_RX_FIFO_DEPTH_WR(txsize,
+ params->dev_tx_fifo_size[i]);
+ dwc_reg_write(regs, DWC_DPTX_FSIZ_DIPTXF(i - 1),
+ txsize);
+ txsize = DWC_RX_FIFO_START_ADDR_WR(txsize,
+ (DWC_RX_FIFO_START_ADDR_RD
+ (txsize) +
+ DWC_RX_FIFO_DEPTH_RD
+ (txsize)));
+ }
+ }
+}
+
+/**
+ * This function initializes the DWC_otg controller registers for
+ * device mode.
+ */
+void dwc_otg_core_dev_init(struct core_if *c_if)
+{
+ u32 i;
+ struct device_if *d_if = c_if->dev_if;
+ struct core_params *params = c_if->core_params;
+ u32 dcfg = 0;
+ u32 resetctl = 0;
+ u32 dthrctl = 0;
+
+ /* Restart the Phy Clock */
+ dwc_reg_write(c_if->pcgcctl, 0, 0);
+
+ /* Device configuration register */
+ init_devspd(c_if);
+ dcfg = dwc_reg_read(d_if->dev_global_regs, DWC_DCFG);
+ dcfg = DWC_DCFG_P_FRM_INTRVL_WR(dcfg, DWC_DCFG_FRAME_INTERVAL_80);
+ dwc_reg_write(d_if->dev_global_regs, DWC_DCFG, dcfg);
+
+ /* If needed configure data FIFO sizes */
+ if (DWC_HWCFG2_DYN_FIFO_RD(c_if->hwcfg2) && params->enable_dynamic_fifo)
+ config_dev_dynamic_fifos(c_if);
+
+ /* Flush the FIFOs */
+ dwc_otg_flush_tx_fifo(c_if, DWC_GRSTCTL_TXFNUM_ALL);
+ dwc_otg_flush_rx_fifo(c_if);
+
+ /* Flush the Learning Queue. */
+ resetctl |= DWC_RSTCTL_TKN_QUE_FLUSH;
+ dwc_reg_write(c_if->core_global_regs, DWC_GRSTCTL, resetctl);
+
+ /* Clear all pending Device Interrupts */
+ dwc_reg_write(d_if->dev_global_regs, DWC_DIEPMSK, 0);
+ dwc_reg_write(d_if->dev_global_regs, DWC_DOEPMSK, 0);
+ dwc_reg_write(d_if->dev_global_regs, DWC_DAINT, 0xFFFFFFFF);
+ dwc_reg_write(d_if->dev_global_regs, DWC_DAINTMSK, 0);
+
+ for (i = 0; i <= d_if->num_in_eps; i++) {
+ u32 depctl = 0;
+
+ depctl = dwc_reg_read(d_if->in_ep_regs[i], DWC_DIEPCTL);
+ if (DWC_DEPCTL_EPENA_RD(depctl)) {
+ depctl = 0;
+ depctl = DWC_DEPCTL_EPDIS_RW(depctl, 1);
+ depctl = DWC_DEPCTL_SET_NAK_RW(depctl, 1);
+ } else {
+ depctl = 0;
+ }
+
+ dwc_reg_write(d_if->in_ep_regs[i], DWC_DIEPCTL, depctl);
+ dwc_reg_write(d_if->in_ep_regs[i], DWC_DIEPTSIZ, 0);
+ dwc_reg_write(d_if->in_ep_regs[i], DWC_DIEPDMA, 0);
+ dwc_reg_write(d_if->in_ep_regs[i], DWC_DIEPINT, 0xFF);
+ }
+
+ for (i = 0; i <= d_if->num_out_eps; i++) {
+ u32 depctl = 0;
+ depctl = dwc_reg_read(d_if->out_ep_regs[i], DWC_DOEPCTL);
+ if (DWC_DEPCTL_EPENA_RD(depctl)) {
+ depctl = 0;
+ depctl = DWC_DEPCTL_EPDIS_RW(depctl, 1);
+ depctl = DWC_DEPCTL_SET_NAK_RW(depctl, 1);
+ } else {
+ depctl = 0;
+ }
+ dwc_reg_write(d_if->out_ep_regs[i], DWC_DOEPCTL, depctl);
+ dwc_reg_write(d_if->out_ep_regs[i], DWC_DOEPTSIZ, 0);
+ dwc_reg_write(d_if->out_ep_regs[i], DWC_DOEPDMA, 0);
+ dwc_reg_write(d_if->out_ep_regs[i], DWC_DOEPINT, 0xFF);
+ }
+
+ if (c_if->en_multiple_tx_fifo && c_if->dma_enable) {
+ d_if->non_iso_tx_thr_en = c_if->core_params->thr_ctl & 0x1;
+ d_if->iso_tx_thr_en = (c_if->core_params->thr_ctl >> 1) & 0x1;
+ d_if->rx_thr_en = (c_if->core_params->thr_ctl >> 2) & 0x1;
+ d_if->rx_thr_length = c_if->core_params->rx_thr_length;
+ d_if->tx_thr_length = c_if->core_params->tx_thr_length;
+
+ dthrctl = 0;
+ dthrctl = DWC_DTHCTRL_NON_ISO_THR_ENA_RW
+ (dthrctl, d_if->non_iso_tx_thr_en);
+ dthrctl = DWC_DTHCTRL_ISO_THR_EN_RW
+ (dthrctl, d_if->iso_tx_thr_en);
+ dthrctl = DWC_DTHCTRL_TX_THR_LEN_RW
+ (dthrctl, d_if->tx_thr_length);
+ dthrctl = DWC_DTHCTRL_RX_THR_EN_RW(dthrctl, d_if->rx_thr_en);
+ dthrctl = DWC_DTHCTRL_RX_THR_LEN_RW
+ (dthrctl, d_if->rx_thr_length);
+ dwc_reg_write(d_if->dev_global_regs,
+ DWC_DTKNQR3_DTHRCTL, dthrctl);
+
+ }
+
+ dwc_otg_enable_device_interrupts(c_if);
+}
+
+/**
+ * This function reads a packet from the Rx FIFO into the destination buffer.
+ * To read SETUP data use dwc_otg_read_setup_packet.
+ */
+void dwc_otg_read_packet(struct core_if *core_if, u8 * dest, u16 _bytes)
+{
+ u32 i;
+ int word_count = (_bytes + 3) / 4;
+ u32 fifo = core_if->data_fifo[0];
+ u32 *data_buff = (u32 *) dest;
+
+ /*
+ * This requires reading data from the FIFO into a u32 temp buffer,
+ * then moving it into the data buffer.
+ */
+ for (i = 0; i < word_count; i++, data_buff++)
+ *data_buff = dwc_read_fifo32(fifo);
+}
+
+/**
+ * Flush a Tx FIFO.
+ */
+void dwc_otg_flush_tx_fifo(struct core_if *core_if, const int num)
+{
+ ulong global_regs = core_if->core_global_regs;
+ u32 greset = 0;
+ int count = 0;
+
+ greset |= DWC_RSTCTL_TX_FIFO_FLUSH;
+ greset = DWC_RSTCTL_TX_FIFO_NUM(greset, num);
+ dwc_reg_write(global_regs, DWC_GRSTCTL, greset);
+
+ do {
+ greset = dwc_reg_read(global_regs, DWC_GRSTCTL);
+ if (++count > 10000) {
+ pr_warning("%s() HANG! GRSTCTL=%0x "
+ "GNPTXSTS=0x%08x\n", __func__, greset,
+ dwc_reg_read(global_regs, DWC_GNPTXSTS));
+ break;
+ }
+ udelay(1);
+ } while (greset & DWC_RSTCTL_TX_FIFO_FLUSH);
+
+ /* Wait for 3 PHY Clocks */
+ udelay(1);
+}
+
+/**
+ * Flush Rx FIFO.
+ */
+void dwc_otg_flush_rx_fifo(struct core_if *core_if)
+{
+ ulong global_regs = core_if->core_global_regs;
+ u32 greset = 0;
+ int count = 0;
+
+ greset |= DWC_RSTCTL_RX_FIFO_FLUSH;
+ dwc_reg_write(global_regs, DWC_GRSTCTL, greset);
+
+ do {
+ greset = dwc_reg_read(global_regs, DWC_GRSTCTL);
+ if (++count > 10000) {
+ pr_warning("%s() HANG! GRSTCTL=%0x\n",
+ __func__, greset);
+ break;
+ }
+ udelay(1);
+ } while (greset & DWC_RSTCTL_RX_FIFO_FLUSH);
+
+ /* Wait for 3 PHY Clocks */
+ udelay(1);
+}
+
+/**
+ * Register HCD callbacks.
+ * The callbacks are used to start and stop the HCD for interrupt processing.
+ */
+void dwc_otg_cil_register_hcd_callbacks(struct core_if *c_if,
+ struct cil_callbacks *cb,
+ void *p)
+{
+ c_if->hcd_cb = cb;
+ cb->p = p;
+}
+
+/**
+ * Register PCD callbacks.
+ * The callbacks are used to start and stop the PCD for interrupt processing.
+ */
+void dwc_otg_cil_register_pcd_callbacks(struct core_if *c_if,
+ struct cil_callbacks *cb,
+ void *p)
+{
+ c_if->pcd_cb = cb;
+ cb->p = p;
+}
+
+/**
+ * This function is called to initialize the DWC_otg CSR data structures.
+ *
+ * The register addresses in the device and host structures are initialized from
+ * the base address supplied by the caller. The calling function must make the
+ * OS calls to get the base address of the DWC_otg controller registers.
+ *
+ * The params argument holds the parameters that specify how the core should be
+ * configured.
+ */
+struct core_if *dwc_otg_cil_init(const __iomem u32 * base,
+ struct core_params *params)
+{
+ struct core_if *core_if;
+ struct device_if *dev_if;
+ struct dwc_host_if *host_if;
+ u8 *reg_base = (__force u8 *)base;
+ u32 offset;
+ u32 i;
+
+ core_if = kzalloc(sizeof(*core_if), GFP_KERNEL);
+ if (!core_if)
+ return NULL;
+
+ core_if->core_params = params;
+ core_if->core_global_regs = (ulong)reg_base;
+
+ /* Allocate the Device Mode structures. */
+ dev_if = kmalloc(sizeof(*dev_if), GFP_KERNEL);
+ if (!dev_if) {
+ kfree(core_if);
+ return NULL;
+ }
+
+ dev_if->dev_global_regs = (ulong)(reg_base + DWC_DEV_GLOBAL_REG_OFFSET);
+
+ for (i = 0; i < MAX_EPS_CHANNELS; i++) {
+ offset = i * DWC_EP_REG_OFFSET;
+
+ dev_if->in_ep_regs[i] = (ulong)(reg_base +
+ DWC_DEV_IN_EP_REG_OFFSET +
+ offset);
+
+ dev_if->out_ep_regs[i] = (ulong)(reg_base +
+ DWC_DEV_OUT_EP_REG_OFFSET +
+ offset);
+ }
+
+ dev_if->speed = 0; /* unknown */
+ core_if->dev_if = dev_if;
+
+ /* Allocate the Host Mode structures. */
+ host_if = kmalloc(sizeof(*host_if), GFP_KERNEL);
+ if (!host_if) {
+ kfree(dev_if);
+ kfree(core_if);
+ return NULL;
+ }
+
+ host_if->host_global_regs = (ulong)(reg_base +
+ DWC_OTG_HOST_GLOBAL_REG_OFFSET);
+
+ host_if->hprt0 = (ulong)(reg_base + DWC_OTG_HOST_PORT_REGS_OFFSET);
+
+ for (i = 0; i < MAX_EPS_CHANNELS; i++) {
+ offset = i * DWC_OTG_CHAN_REGS_OFFSET;
+
+ host_if->hc_regs[i] = (ulong)(reg_base +
+ DWC_OTG_HOST_CHAN_REGS_OFFSET +
+ offset);
+ }
+
+ host_if->num_host_channels = MAX_EPS_CHANNELS;
+ core_if->host_if = host_if;
+ for (i = 0; i < MAX_EPS_CHANNELS; i++) {
+ core_if->data_fifo[i] =
+ (ulong)(reg_base + DWC_OTG_DATA_FIFO_OFFSET +
+ (i * DWC_OTG_DATA_FIFO_SIZE));
+ }
+ core_if->pcgcctl = (ulong)(reg_base + DWC_OTG_PCGCCTL_OFFSET);
+
+ /*
+ * Store the contents of the hardware configuration registers here for
+ * easy access later.
+ */
+ core_if->hwcfg1 =
+ dwc_reg_read(core_if->core_global_regs, DWC_GHWCFG1);
+ core_if->hwcfg2 =
+ dwc_reg_read(core_if->core_global_regs, DWC_GHWCFG2);
+ core_if->hwcfg3 =
+ dwc_reg_read(core_if->core_global_regs, DWC_GHWCFG3);
+ core_if->hwcfg4 =
+ dwc_reg_read(core_if->core_global_regs, DWC_GHWCFG4);
+
+ /* Set the SRP sucess bit for FS-I2c */
+ core_if->srp_success = 0;
+ core_if->srp_timer_started = 0;
+ return core_if;
+}
+
+/**
+ * This function frees the structures allocated by dwc_otg_cil_init().
+ */
+void dwc_otg_cil_remove(struct core_if *core_if)
+{
+ /* Disable all interrupts */
+ dwc_reg_modify(core_if->core_global_regs, DWC_GAHBCFG, 1, 0);
+ dwc_reg_write(core_if->core_global_regs, DWC_GINTMSK, 0);
+
+ if (core_if) {
+ kfree(core_if->dev_if);
+ kfree(core_if->host_if);
+ }
+ kfree(core_if);
+}
diff --git a/drivers/usb/dwc/cil.h b/drivers/usb/dwc/cil.h
new file mode 100644
index 0000000..80c4361
--- /dev/null
+++ b/drivers/usb/dwc/cil.h
@@ -0,0 +1,1179 @@
+/*
+ * DesignWare HS OTG controller driver
+ * Copyright (C) 2006 Synopsys, Inc.
+ * Portions Copyright (C) 2010 Applied Micro Circuits Corporation.
+ *
+ * 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 version 2 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
+ * or write to the Free Software Foundation, Inc., 51 Franklin Street,
+ * Suite 500, Boston, MA 02110-1335 USA.
+ *
+ * Based on Synopsys driver version 2.60a
+ * Modified by Mark Miesfeld <mmiesfeld@apm.com>
+ * Modified by Stefan Roese <sr@denx.de>, DENX Software Engineering
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL SYNOPSYS, INC. 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.
+ *
+ */
+
+#if !defined(__DWC_CIL_H__)
+#define __DWC_CIL_H__
+#include <linux/io.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/interrupt.h>
+#include <linux/dmapool.h>
+#include <linux/spinlock.h>
+#include <linux/usb/otg.h>
+
+#include "regs.h"
+
+#ifdef CONFIG_DWC_DEBUG
+#define DEBUG
+#endif
+
+#ifdef CONFIG_ARM
+#define in_le32(x) readl(x)
+#define out_le32(x,y) writel(y,x)
+#endif
+
+/**
+ * Reads the content of a register.
+ */
+static inline u32 dwc_reg_read(ulong reg , u32 offset)
+{
+
+#ifdef CONFIG_DWC_OTG_REG_LE
+ return in_le32((unsigned __iomem *)(reg + offset));
+#else
+ return in_be32((unsigned __iomem *)(reg + offset));
+#endif
+}
+
+static inline void dwc_reg_write(ulong reg, u32 offset, const u32 value)
+{
+#ifdef CONFIG_DWC_OTG_REG_LE
+ out_le32((unsigned __iomem *)(reg + offset), value);
+#else
+ out_be32((unsigned __iomem *)(reg + offset), value);
+#endif
+};
+/**
+ * This function modifies bit values in a register. Using the
+ * algorithm: (reg_contents & ~clear_mask) | set_mask.
+ */
+static inline void dwc_reg_modify(ulong reg, u32 offset, const u32 _clear_mask,
+ const u32 _set_mask)
+{
+#ifdef CONFIG_DWC_OTG_REG_LE
+ out_le32((unsigned __iomem *)(reg + offset),
+ (in_le32((unsigned __iomem *)(reg + offset))
+ & ~_clear_mask) | _set_mask);
+#else
+ out_be32((unsigned __iomem *)(reg + offset),
+ (in_be32(((unsigned __iomem *))(reg + offset))
+ & ~_clear_mask) | _set_mask);
+#endif
+};
+
+static inline void dwc_write_fifo32(ulong reg, const u32 _value)
+{
+#ifdef CONFIG_DWC_OTG_FIFO_LE
+ out_le32((unsigned __iomem *)reg, _value);
+#else
+ out_be32((unsigned __iomem *)reg, _value);
+#endif
+};
+
+static inline u32 dwc_read_fifo32(ulong _reg)
+{
+#ifdef CONFIG_DWC_OTG_FIFO_LE
+ return in_le32((unsigned __iomem *) _reg);
+#else
+ return in_be32((unsigned __iomem *) _reg);
+#endif
+};
+
+/*
+ * Debugging support vanishes in non-debug builds.
+ */
+/* Display CIL Debug messages */
+#define dwc_dbg_cil (0x2)
+
+/* Display CIL Verbose debug messages */
+#define dwc_dbg_cilv (0x20)
+
+/* Display PCD (Device) debug messages */
+#define dwc_dbg_pcd (0x4)
+
+/* Display PCD (Device) Verbose debug messages */
+#define dwc_dbg_pcdv (0x40)
+
+/* Display Host debug messages */
+#define dwc_dbg_hcd (0x8)
+
+/* Display Verbose Host debug messages */
+#define dwc_dbg_hcdv (0x80)
+
+/* Display enqueued URBs in host mode. */
+#define dwc_dbg_hcd_urb (0x800)
+
+/* Display "special purpose" debug messages */
+#define dwc_dbg_sp (0x400)
+
+/* Display all debug messages */
+#define dwc_dbg_any (0xFF)
+
+/* All debug messages off */
+#define dwc_dbg_off 0
+
+/* Prefix string for DWC_DEBUG print macros. */
+#define usb_dwc "dwc_otg: "
+
+/*
+ * This file contains the interface to the Core Interface Layer.
+ */
+
+/*
+ * Added-sr: 2007-07-26
+ *
+ * Since the 405EZ (Ultra) only support 2047 bytes as
+ * max transfer size, we have to split up bigger transfers
+ * into multiple transfers of 1024 bytes sized messages.
+ * I happens often, that transfers of 4096 bytes are
+ * required (zero-gadget, file_storage-gadget).
+ *
+ * MAX_XFER_LEN is set to 1024 right now, but could be 2047,
+ * since the xfer-size field in the 405EZ USB device controller
+ * implementation has 11 bits. Using 1024 seems to work for now.
+ */
+#define MAX_XFER_LEN 1024
+
+/*
+ * The dwc_ep structure represents the state of a single endpoint when acting in
+ * device mode. It contains the data items needed for an endpoint to be
+ * activated and transfer packets.
+ */
+struct dwc_ep {
+ /* EP number used for register address lookup */
+ u8 num;
+ /* EP direction 0 = OUT */
+ unsigned is_in:1;
+ /* EP active. */
+ unsigned active:1;
+
+ /*
+ * Periodic Tx FIFO # for IN EPs For INTR EP set to 0 to use
+ * non-periodic Tx FIFO If dedicated Tx FIFOs are enabled for all
+ * IN Eps - Tx FIFO # FOR IN EPs
+ */
+ unsigned tx_fifo_num:4;
+ /* EP type: 0 - Control, 1 - ISOC, 2 - BULK, 3 - INTR */
+ unsigned type:2;
+#define DWC_OTG_EP_TYPE_CONTROL 0
+#define DWC_OTG_EP_TYPE_ISOC 1
+#define DWC_OTG_EP_TYPE_BULK 2
+#define DWC_OTG_EP_TYPE_INTR 3
+
+ /* DATA start PID for INTR and BULK EP */
+ unsigned data_pid_start:1;
+ /* Frame (even/odd) for ISOC EP */
+ unsigned even_odd_frame:1;
+ /* Max Packet bytes */
+ unsigned maxpacket:11;
+
+ ulong dma_addr;
+
+ /*
+ * Pointer to the beginning of the transfer buffer -- do not modify
+ * during transfer.
+ */
+ u8 *start_xfer_buff;
+ /* pointer to the transfer buffer */
+ u8 *xfer_buff;
+ /* Number of bytes to transfer */
+ unsigned xfer_len:19;
+ /* Number of bytes transferred. */
+ unsigned xfer_count:19;
+ /* Sent ZLP */
+ unsigned sent_zlp:1;
+ /* Total len for control transfer */
+ unsigned total_len:19;
+
+ /* stall clear flag */
+ unsigned stall_clear_flag:1;
+
+ /*
+ * Added-sr: 2007-07-26
+ *
+ * Since the 405EZ (Ultra) only support 2047 bytes as
+ * max transfer size, we have to split up bigger transfers
+ * into multiple transfers of 1024 bytes sized messages.
+ * I happens often, that transfers of 4096 bytes are
+ * required (zero-gadget, file_storage-gadget).
+ *
+ * "bytes_pending" will hold the amount of bytes that are
+ * still pending to be send in further messages to complete
+ * the bigger transfer.
+ */
+ u32 bytes_pending;
+};
+
+/*
+ * States of EP0.
+ */
+enum ep0_state {
+ EP0_DISCONNECT = 0, /* no host */
+ EP0_IDLE = 1,
+ EP0_IN_DATA_PHASE = 2,
+ EP0_OUT_DATA_PHASE = 3,
+ EP0_STATUS = 4,
+ EP0_STALL = 5,
+};
+
+/* Fordward declaration.*/
+struct dwc_pcd;
+
+/*
+ * This structure describes an EP, there is an array of EPs in the PCD
+ * structure.
+ */
+struct pcd_ep {
+ /* USB EP data */
+ struct usb_ep ep;
+ /* USB EP Descriptor */
+ const struct usb_endpoint_descriptor *desc;
+
+ /* queue of dwc_otg_pcd_requests. */
+ struct list_head queue;
+ unsigned stopped:1;
+ unsigned disabling:1;
+ unsigned dma:1;
+ unsigned queue_sof:1;
+ unsigned wedged:1;
+
+ /* DWC_otg ep data. */
+ struct dwc_ep dwc_ep;
+
+ /* Pointer to PCD */
+ struct dwc_pcd *pcd;
+};
+
+/*
+ * DWC_otg PCD Structure.
+ * This structure encapsulates the data for the dwc_otg PCD.
+ */
+struct dwc_pcd {
+ /* USB gadget */
+ struct usb_gadget gadget;
+ /* USB gadget driver pointer */
+ struct usb_gadget_driver *driver;
+ /* The DWC otg device pointer. */
+ struct dwc_otg_device *otg_dev;
+
+ /* State of EP0 */
+ enum ep0_state ep0state;
+ /* EP0 Request is pending */
+ unsigned ep0_pending:1;
+ /* Indicates when SET CONFIGURATION Request is in process */
+ unsigned request_config:1;
+ /* The state of the Remote Wakeup Enable. */
+ unsigned remote_wakeup_enable:1;
+ /* The state of the B-Device HNP Enable. */
+ unsigned b_hnp_enable:1;
+ /* The state of A-Device HNP Support. */
+ unsigned a_hnp_support:1;
+ /* The state of the A-Device Alt HNP support. */
+ unsigned a_alt_hnp_support:1;
+ /* Count of pending Requests */
+ unsigned request_pending;
+
+ /*
+ * SETUP packet for EP0. This structure is allocated as a DMA buffer on
+ * PCD initialization with enough space for up to 3 setup packets.
+ */
+ union {
+ struct usb_ctrlrequest req;
+ u32 d32[2];
+ } *setup_pkt;
+
+ struct dma_pool *dwc_pool;
+ dma_addr_t setup_pkt_dma_handle;
+
+ /* 2-byte dma buffer used to return status from GET_STATUS */
+ u16 *status_buf;
+ dma_addr_t status_buf_dma_handle;
+
+ /* Array of EPs. */
+ struct pcd_ep ep0;
+ /* Array of IN EPs. */
+ struct pcd_ep in_ep[MAX_EPS_CHANNELS - 1];
+ /* Array of OUT EPs. */
+ struct pcd_ep out_ep[MAX_EPS_CHANNELS - 1];
+ spinlock_t lock;
+ /*
+ * Timer for SRP. If it expires before SRP is successful clear the
+ * SRP.
+ */
+ struct timer_list srp_timer;
+
+ /*
+ * Tasklet to defer starting of TEST mode transmissions until Status
+ * Phase has been completed.
+ */
+ struct tasklet_struct test_mode_tasklet;
+
+ /* Tasklet to delay starting of xfer in DMA mode */
+ struct tasklet_struct *start_xfer_tasklet;
+
+ /* The test mode to enter when the tasklet is executed. */
+ unsigned test_mode;
+};
+
+/*
+ * This structure holds the state of the HCD, including the non-periodic and
+ * periodic schedules.
+ */
+struct dwc_hcd {
+ spinlock_t lock;
+
+ /* DWC OTG Core Interface Layer */
+ struct core_if *core_if;
+
+ /* Internal DWC HCD Flags */
+ union dwc_otg_hcd_internal_flags {
+ u32 d32;
+ struct {
+ unsigned port_connect_status_change:1;
+ unsigned port_connect_status:1;
+ unsigned port_reset_change:1;
+ unsigned port_enable_change:1;
+ unsigned port_suspend_change:1;
+ unsigned port_over_current_change:1;
+ unsigned reserved:27;
+ } b;
+ } flags;
+
+ /*
+ * Inactive items in the non-periodic schedule. This is a list of
+ * Queue Heads. Transfers associated with these Queue Heads are not
+ * currently assigned to a host channel.
+ */
+ struct list_head non_periodic_sched_inactive;
+
+ /*
+ * Deferred items in the non-periodic schedule. This is a list of
+ * Queue Heads. Transfers associated with these Queue Heads are not
+ * currently assigned to a host channel.
+ * When we get an NAK, the QH goes here.
+ */
+ struct list_head non_periodic_sched_deferred;
+
+ /*
+ * Active items in the non-periodic schedule. This is a list of
+ * Queue Heads. Transfers associated with these Queue Heads are
+ * currently assigned to a host channel.
+ */
+ struct list_head non_periodic_sched_active;
+
+ /*
+ * Pointer to the next Queue Head to process in the active
+ * non-periodic schedule.
+ */
+ struct list_head *non_periodic_qh_ptr;
+
+ /*
+ * Inactive items in the periodic schedule. This is a list of QHs for
+ * periodic transfers that are _not_ scheduled for the next frame.
+ * Each QH in the list has an interval counter that determines when it
+ * needs to be scheduled for execution. This scheduling mechanism
+ * allows only a simple calculation for periodic bandwidth used (i.e.
+ * must assume that all periodic transfers may need to execute in the
+ * same frame). However, it greatly simplifies scheduling and should
+ * be sufficient for the vast majority of OTG hosts, which need to
+ * connect to a small number of peripherals at one time.
+ *
+ * Items move from this list to periodic_sched_ready when the QH
+ * interval counter is 0 at SOF.
+ */
+ struct list_head periodic_sched_inactive;
+
+ /*
+ * List of periodic QHs that are ready for execution in the next
+ * frame, but have not yet been assigned to host channels.
+ *
+ * Items move from this list to periodic_sched_assigned as host
+ * channels become available during the current frame.
+ */
+ struct list_head periodic_sched_ready;
+
+ /*
+ * List of periodic QHs to be executed in the next frame that are
+ * assigned to host channels.
+ *
+ * Items move from this list to periodic_sched_queued as the
+ * transactions for the QH are queued to the DWC_otg controller.
+ */
+ struct list_head periodic_sched_assigned;
+
+ /*
+ * List of periodic QHs that have been queued for execution.
+ *
+ * Items move from this list to either periodic_sched_inactive or
+ * periodic_sched_ready when the channel associated with the transfer
+ * is released. If the interval for the QH is 1, the item moves to
+ * periodic_sched_ready because it must be rescheduled for the next
+ * frame. Otherwise, the item moves to periodic_sched_inactive.
+ */
+ struct list_head periodic_sched_queued;
+
+ /*
+ * Total bandwidth claimed so far for periodic transfers. This value
+ * is in microseconds per (micro)frame. The assumption is that all
+ * periodic transfers may occur in the same (micro)frame.
+ */
+ u16 periodic_usecs;
+
+ /*
+ * Total bandwidth claimed so far for all periodic transfers
+ * in a frame.
+ * This will include a mixture of HS and FS transfers.
+ * Units are microseconds per (micro)frame.
+ * We have a budget per frame and have to schedule
+ * transactions accordingly.
+ * Watch out for the fact that things are actually scheduled for the
+ * "next frame".
+ */
+ u16 frame_usecs[8];
+
+ /*
+ * Frame number read from the core at SOF. The value ranges from 0 to
+ * DWC_HFNUM_MAX_FRNUM.
+ */
+ u16 frame_number;
+
+ /*
+ * Free host channels in the controller. This is a list of
+ * struct dwc_hc items.
+ */
+ struct list_head free_hc_list;
+
+ /*
+ * Number of available host channels.
+ */
+ u32 available_host_channels;
+
+ /*
+ * Array of pointers to the host channel descriptors. Allows accessing
+ * a host channel descriptor given the host channel number. This is
+ * useful in interrupt handlers.
+ */
+ struct dwc_hc *hc_ptr_array[MAX_EPS_CHANNELS];
+
+ /*
+ * Buffer to use for any data received during the status phase of a
+ * control transfer. Normally no data is transferred during the status
+ * phase. This buffer is used as a bit bucket.
+ */
+ u8 *status_buf;
+
+ /*
+ * DMA address for status_buf.
+ */
+ dma_addr_t status_buf_dma;
+#define DWC_OTG_HCD_STATUS_BUF_SIZE 64
+
+ /*
+ * Structure to allow starting the HCD in a non-interrupt context
+ * during an OTG role change.
+ */
+ struct work_struct start_work;
+ struct usb_hcd *_p;
+
+ /*
+ * Connection timer. An OTG host must display a message if the device
+ * does not connect. Started when the VBus power is turned on via
+ * sysfs attribute "buspower".
+ */
+ struct timer_list conn_timer;
+
+ /* workqueue for port wakeup */
+ struct work_struct usb_port_reset;
+
+ /* Addition HCD interrupt */
+ int cp_irq; /* charge pump interrupt */
+ int cp_irq_installed;
+};
+
+/*
+ * Reasons for halting a host channel.
+ */
+enum dwc_halt_status {
+ DWC_OTG_HC_XFER_NO_HALT_STATUS,
+ DWC_OTG_HC_XFER_COMPLETE,
+ DWC_OTG_HC_XFER_URB_COMPLETE,
+ DWC_OTG_HC_XFER_ACK,
+ DWC_OTG_HC_XFER_NAK,
+ DWC_OTG_HC_XFER_NYET,
+ DWC_OTG_HC_XFER_STALL,
+ DWC_OTG_HC_XFER_XACT_ERR,
+ DWC_OTG_HC_XFER_FRAME_OVERRUN,
+ DWC_OTG_HC_XFER_BABBLE_ERR,
+ DWC_OTG_HC_XFER_DATA_TOGGLE_ERR,
+ DWC_OTG_HC_XFER_AHB_ERR,
+ DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE,
+ DWC_OTG_HC_XFER_URB_DEQUEUE
+};
+
+/*
+ * Host channel descriptor. This structure represents the state of a single
+ * host channel when acting in host mode. It contains the data items needed to
+ * transfer packets to an endpoint via a host channel.
+ */
+struct dwc_hc {
+ /* Host channel number used for register address lookup */
+ u8 hc_num;
+
+ /* Device to access */
+ unsigned dev_addr:7;
+
+ /* EP to access */
+ unsigned ep_num:4;
+
+ /* EP direction. 0: OUT, 1: IN */
+ unsigned ep_is_in:1;
+
+ /*
+ * EP speed.
+ * One of the following values:
+ * - DWC_OTG_EP_SPEED_LOW
+ * - DWC_OTG_EP_SPEED_FULL
+ * - DWC_OTG_EP_SPEED_HIGH
+ */
+ unsigned speed:2;
+#define DWC_OTG_EP_SPEED_LOW 0
+#define DWC_OTG_EP_SPEED_FULL 1
+#define DWC_OTG_EP_SPEED_HIGH 2
+
+ /*
+ * Endpoint type.
+ * One of the following values:
+ * - DWC_OTG_EP_TYPE_CONTROL: 0
+ * - DWC_OTG_EP_TYPE_ISOC: 1
+ * - DWC_OTG_EP_TYPE_BULK: 2
+ * - DWC_OTG_EP_TYPE_INTR: 3
+ */
+ unsigned ep_type:2;
+
+ /* Max packet size in bytes */
+ unsigned max_packet:11;
+
+ /*
+ * PID for initial transaction.
+ * 0: DATA0,
+ * 1: DATA2,
+ * 2: DATA1,
+ * 3: MDATA (non-Control EP),
+ * SETUP (Control EP)
+ */
+ unsigned data_pid_start:2;
+#define DWC_OTG_HC_PID_DATA0 0
+#define DWC_OTG_HC_PID_DATA2 1
+#define DWC_OTG_HC_PID_DATA1 2
+#define DWC_OTG_HC_PID_MDATA 3
+#define DWC_OTG_HC_PID_SETUP 3
+
+ /* Number of periodic transactions per (micro)frame */
+ unsigned multi_count:2;
+
+ /* Pointer to the current transfer buffer position. */
+ u8 *xfer_buff;
+ /* Total number of bytes to transfer. */
+ u32 xfer_len;
+ /* Number of bytes transferred so far. */
+ u32 xfer_count;
+ /* Packet count at start of transfer. */
+ u16 start_pkt_count;
+
+ /*
+ * Flag to indicate whether the transfer has been started. Set to 1 if
+ * it has been started, 0 otherwise.
+ */
+ u8 xfer_started;
+
+ /*
+ * Set to 1 to indicate that a PING request should be issued on this
+ * channel. If 0, process normally.
+ */
+ u8 do_ping;
+
+ /*
+ * Set to 1 to indicate that the error count for this transaction is
+ * non-zero. Set to 0 if the error count is 0.
+ */
+ u8 error_state;
+
+ /*
+ * Set to 1 to indicate that this channel should be halted the next
+ * time a request is queued for the channel. This is necessary in
+ * slave mode if no request queue space is available when an attempt
+ * is made to halt the channel.
+ */
+ u8 halt_on_queue;
+
+ /*
+ * Set to 1 if the host channel has been halted, but the core is not
+ * finished flushing queued requests. Otherwise 0.
+ */
+ u8 halt_pending;
+
+ /* Reason for halting the host channel. */
+ enum dwc_halt_status halt_status;
+
+ /* Split settings for the host channel */
+ u8 do_split; /* Enable split for the channel */
+ u8 complete_split; /* Enable complete split */
+ u8 hub_addr; /* Address of high speed hub */
+ u8 port_addr; /* Port of the low/full speed device */
+
+ /*
+ * Split transaction position. One of the following values:
+ * - DWC_HCSPLIT_XACTPOS_MID
+ * - DWC_HCSPLIT_XACTPOS_BEGIN
+ * - DWC_HCSPLIT_XACTPOS_END
+ * - DWC_HCSPLIT_XACTPOS_ALL */
+ u8 xact_pos;
+
+ /* Set when the host channel does a short read. */
+ u8 short_read;
+
+ /*
+ * Number of requests issued for this channel since it was assigned to
+ * the current transfer (not counting PINGs).
+ */
+ u8 requests;
+
+ /* Queue Head for the transfer being processed by this channel. */
+ struct dwc_qh *qh;
+
+ /* Entry in list of host channels. */
+ struct list_head hc_list_entry;
+};
+
+/*
+ * The following parameters may be specified when starting the module. These
+ * parameters define how the DWC_otg controller should be configured. Parameter
+ * values are passed to the CIL initialization function dwc_otg_cil_init.
+ */
+struct core_params {
+ /*
+ * Specifies the OTG capabilities. The driver will automatically
+ * detect the value for this parameter if none is specified.
+ * 0 - HNP and SRP capable (default)
+ * 1 - SRP Only capable
+ * 2 - No HNP/SRP capable
+ */
+ int otg_cap;
+#define DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE 0
+#define DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE 1
+#define DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE 2
+
+#define dwc_param_otg_cap_default DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE
+
+ /*
+ * Specifies whether to use slave or DMA mode for accessing the data
+ * FIFOs. The driver will automatically detect the value for this
+ * parameter if none is specified.
+ * 0 - Slave
+ * 1 - DMA (default, if available)
+ */
+ int dma_enable;
+#ifdef CONFIG_DWC_SLAVE
+#define dwc_param_dma_enable_default 0
+#else
+#define dwc_param_dma_enable_default 1
+#endif
+
+ /*
+ * The DMA Burst size (applicable only for External DMA Mode).
+ * 1, 4, 8 16, 32, 64, 128, 256 (default 32)
+ */
+ int dma_burst_size; /* Translate this to GAHBCFG values */
+#define dwc_param_dma_burst_size_default 32
+
+ /*
+ * Specifies the maximum speed of operation in host and device mode.
+ * The actual speed depends on the speed of the attached device and
+ * the value of phy_type. The actual speed depends on the speed of the
+ * attached device.
+ * 0 - High Speed (default)
+ * 1 - Full Speed
+ */
+ int speed;
+#define dwc_param_speed_default 0
+#define DWC_SPEED_PARAM_HIGH 0
+#define DWC_SPEED_PARAM_FULL 1
+
+ /*
+ * Specifies whether low power mode is supported when attached to a Full
+ * Speed or Low Speed device in host mode.
+ * 0 - Don't support low power mode (default)
+ * 1 - Support low power mode
+ */
+ int host_support_fs_ls_low_power;
+#define dwc_param_host_support_fs_ls_low_power_default 0
+
+ /*
+ * Specifies the PHY clock rate in low power mode when connected to a
+ * Low Speed device in host mode. This parameter is applicable only if
+ * HOST_SUPPORT_FS_LS_LOW_POWER is enabled. If PHY_TYPE is set to FS
+ * then defaults to 6 MHZ otherwise 48 MHZ.
+ *
+ * 0 - 48 MHz
+ * 1 - 6 MHz
+ */
+ int host_ls_low_power_phy_clk;
+#define dwc_param_host_ls_low_power_phy_clk_default 0
+#define DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ 0
+#define DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ 1
+
+ /*
+ * 0 - Use cC FIFO size parameters
+ * 1 - Allow dynamic FIFO sizing (default)
+ */
+ int enable_dynamic_fifo;
+#define dwc_param_enable_dynamic_fifo_default 1
+
+ /*
+ * Number of 4-byte words in the Rx FIFO in device mode when dynamic
+ * FIFO sizing is enabled. 16 to 32768 (default 1064)
+ */
+ int dev_rx_fifo_size;
+#define dwc_param_dev_rx_fifo_size_default 1064
+
+ /*
+ * Number of 4-byte words in the non-periodic Tx FIFO in device mode
+ * when dynamic FIFO sizing is enabled. 16 to 32768 (default 1024)
+ */
+ int dev_nperio_tx_fifo_size;
+#define dwc_param_dev_nperio_tx_fifo_size_default 1024
+
+ /*
+ * Number of 4-byte words in each of the periodic Tx FIFOs in device
+ * mode when dynamic FIFO sizing is enabled. 4 to 768 (default 256)
+ */
+ u32 dev_perio_tx_fifo_size[MAX_PERIO_FIFOS];
+#define dwc_param_dev_perio_tx_fifo_size_default 256
+
+ /*
+ * Number of 4-byte words in the Rx FIFO in host mode when dynamic
+ * FIFO sizing is enabled. 16 to 32768 (default 1024)
+ */
+ int host_rx_fifo_size;
+#define dwc_param_host_rx_fifo_size_default 1024
+
+ /*
+ * Number of 4-byte words in the non-periodic Tx FIFO in host mode
+ * when Dynamic FIFO sizing is enabled in the core. 16 to 32768
+ * (default 1024)
+ */
+ int host_nperio_tx_fifo_size;
+#define dwc_param_host_nperio_tx_fifo_size_default 1024
+
+ /*
+ Number of 4-byte words in the host periodic Tx FIFO when dynamic
+ * FIFO sizing is enabled. 16 to 32768 (default 1024)
+ */
+ int host_perio_tx_fifo_size;
+#define dwc_param_host_perio_tx_fifo_size_default 1024
+
+ /*
+ * The maximum transfer size supported in bytes. 2047 to 65,535
+ * (default 65,535)
+ */
+ int max_transfer_size;
+#define dwc_param_max_transfer_size_default 65535
+
+ /*
+ * The maximum number of packets in a transfer. 15 to 511 (default 511)
+ */
+ int max_packet_count;
+#define dwc_param_max_packet_count_default 511
+
+ /*
+ * The number of host channel registers to use.
+ * 1 to 16 (default 12)
+ * Note: The FPGA configuration supports a maximum of 12 host channels.
+ */
+ int host_channels;
+#define dwc_param_host_channels_default 12
+
+ /*
+ * The number of endpoints in addition to EP0 available for device
+ * mode operations.
+ * 1 to 15 (default 6 IN and OUT)
+ * Note: The FPGA configuration supports a maximum of 6 IN and OUT
+ * endpoints in addition to EP0.
+ */
+ int dev_endpoints;
+#define dwc_param_dev_endpoints_default 6
+
+ /*
+ * Specifies the type of PHY interface to use. By default, the driver
+ * will automatically detect the phy_type.
+ *
+ * 0 - Full Speed PHY
+ * 1 - UTMI+ (default)
+ * 2 - ULPI
+ */
+ int phy_type;
+#define DWC_PHY_TYPE_PARAM_FS 0
+#define DWC_PHY_TYPE_PARAM_UTMI 1
+#define DWC_PHY_TYPE_PARAM_ULPI 2
+#define dwc_param_phy_type_default DWC_PHY_TYPE_PARAM_UTMI
+
+ /*
+ * Specifies the UTMI+ Data Width. This parameter is applicable for a
+ * PHY_TYPE of UTMI+ or ULPI. (For a ULPI PHY_TYPE, this parameter
+ * indicates the data width between the MAC and the ULPI Wrapper.) Also,
+ * this parameter is applicable only if the OTG_HSPHY_WIDTH cC parameter
+ * was set to "8 and 16 bits", meaning that the core has been configured
+ * to work at either data path width.
+ *
+ * 8 or 16 bits (default 16)
+ */
+ int phy_utmi_width;
+#define dwc_param_phy_utmi_width_default 16
+
+ /*
+ * Specifies whether the ULPI operates at double or single
+ * data rate. This parameter is only applicable if PHY_TYPE is
+ * ULPI.
+ *
+ * 0 - single data rate ULPI interface with 8 bit wide data
+ * bus (default)
+ * 1 - double data rate ULPI interface with 4 bit wide data
+ * bus
+ */
+ int phy_ulpi_ddr;
+#define dwc_param_phy_ulpi_ddr_default 0
+
+ /*
+ * Specifies whether to use the internal or external supply to
+ * drive the vbus with a ULPI phy.
+ */
+ int phy_ulpi_ext_vbus;
+#define DWC_PHY_ULPI_INTERNAL_VBUS 0
+#define DWC_PHY_ULPI_EXTERNAL_VBUS 1
+#define dwc_param_phy_ulpi_ext_vbus_default DWC_PHY_ULPI_INTERNAL_VBUS
+
+ /*
+ * Specifies whether to use the I2Cinterface for full speed PHY. This
+ * parameter is only applicable if PHY_TYPE is FS.
+ * 0 - No (default)
+ * 1 - Yes
+ */
+ int i2c_enable;
+#define dwc_param_i2c_enable_default 0
+
+ int ulpi_fs_ls;
+#define dwc_param_ulpi_fs_ls_default 0
+
+ int ts_dline;
+#define dwc_param_ts_dline_default 0
+
+ /*
+ * Specifies whether dedicated transmit FIFOs are enabled for non
+ * periodic IN endpoints in device mode
+ * 0 - No
+ * 1 - Yes
+ */
+ int en_multiple_tx_fifo;
+#define dwc_param_en_multiple_tx_fifo_default 1
+
+ /*
+ * Number of 4-byte words in each of the Tx FIFOs in device
+ * mode when dynamic FIFO sizing is enabled. 4 to 768 (default 256)
+ */
+ u32 dev_tx_fifo_size[MAX_TX_FIFOS];
+#define dwc_param_dev_tx_fifo_size_default 256
+
+ /*
+ * Thresholding enable flag
+ * bit 0 - enable non-ISO Tx thresholding
+ * bit 1 - enable ISO Tx thresholding
+ * bit 2 - enable Rx thresholding
+ */
+ u32 thr_ctl;
+#define dwc_param_thr_ctl_default 0
+
+ /* Thresholding length for Tx FIFOs in 32 bit DWORDs */
+ u32 tx_thr_length;
+#define dwc_param_tx_thr_length_default 64
+
+ /* Thresholding length for Rx FIFOs in 32 bit DWORDs */
+ u32 rx_thr_length;
+#define dwc_param_rx_thr_length_default 64
+
+};
+
+/*
+ * The core_if structure contains information needed to manage the
+ * DWC_otg controller acting in either host or device mode. It represents the
+ * programming view of the controller as a whole.
+ */
+struct core_if {
+ /* Parameters that define how the core should be configured. */
+ struct core_params *core_params;
+
+ /* Core Global registers starting at offset 000h. */
+ ulong core_global_regs;
+
+ /* Device-specific information */
+ struct device_if *dev_if;
+ /* Host-specific information */
+ struct dwc_host_if *host_if;
+
+ /*
+ * Set to 1 if the core PHY interface bits in USBCFG have been
+ * initialized.
+ */
+ u8 phy_init_done;
+
+ /*
+ * SRP Success flag, set by srp success interrupt in FS I2C mode
+ */
+ u8 srp_success;
+ u8 srp_timer_started;
+
+ /* Common configuration information */
+ /* Power and Clock Gating Control Register */
+ ulong pcgcctl;
+#define DWC_OTG_PCGCCTL_OFFSET 0xE00
+
+ /* Push/pop addresses for endpoints or host channels. */
+ ulong data_fifo[MAX_EPS_CHANNELS];
+#define DWC_OTG_DATA_FIFO_OFFSET 0x1000
+#define DWC_OTG_DATA_FIFO_SIZE 0x1000
+
+ /* Total RAM for FIFOs (Bytes) */
+ u16 total_fifo_size;
+ /* Size of Rx FIFO (Bytes) */
+ u16 rx_fifo_size;
+ /* Size of Non-periodic Tx FIFO (Bytes) */
+ u16 nperio_tx_fifo_size;
+
+ /* 1 if DMA is enabled, 0 otherwise. */
+ u8 dma_enable;
+
+ /* 1 if dedicated Tx FIFOs are enabled, 0 otherwise. */
+ u8 en_multiple_tx_fifo;
+
+ /*
+ * Set to 1 if multiple packets of a high-bandwidth transfer is in
+ * process of being queued
+ */
+ u8 queuing_high_bandwidth;
+
+ /* Hardware Configuration -- stored here for convenience. */
+ ulong hwcfg1;
+ ulong hwcfg2;
+ ulong hwcfg3;
+ ulong hwcfg4;
+
+ /* HCD callbacks */
+ /* include/linux/usb/otg.h */
+
+ /* HCD callbacks */
+ struct cil_callbacks *hcd_cb;
+ /* PCD callbacks */
+ struct cil_callbacks *pcd_cb;
+
+ /* Device mode Periodic Tx FIFO Mask */
+ u32 p_tx_msk;
+ /* Device mode Periodic Tx FIFO Mask */
+ u32 tx_msk;
+
+ /* Features of various DWC implementation */
+ u32 features;
+
+ /* Added to support PLB DMA : phys-virt mapping */
+ resource_size_t phys_addr;
+
+ struct delayed_work usb_port_wakeup;
+ struct work_struct usb_port_otg;
+ struct otg_transceiver *xceiv;
+};
+
+/*
+ * The following functions support initialization of the CIL driver component
+ * and the DWC_otg controller.
+ */
+extern void dwc_otg_core_init(struct core_if *core_if);
+extern void init_fslspclksel(struct core_if *core_if);
+extern void dwc_otg_core_dev_init(struct core_if *core_if);
+extern void dwc_otg_enable_global_interrupts(struct core_if *core_if);
+extern void dwc_otg_disable_global_interrupts(struct core_if *core_if);
+extern void dwc_otg_enable_common_interrupts(struct core_if *core_if);
+
+/**
+ * This function Reads HPRT0 in preparation to modify. It keeps the WC bits 0
+ * so that if they are read as 1, they won't clear when you write it back
+ */
+static inline u32 dwc_otg_read_hprt0(struct core_if *core_if)
+{
+ u32 hprt0 = 0;
+ hprt0 = dwc_reg_read(core_if->host_if->hprt0, 0);
+ hprt0 = DWC_HPRT0_PRT_ENA_RW(hprt0, 0);
+ hprt0 = DWC_HPRT0_PRT_CONN_DET_RW(hprt0, 0);
+ hprt0 = DWC_HPRT0_PRT_ENA_DIS_CHG_RW(hprt0, 0);
+ hprt0 = DWC_HPRT0_PRT_OVRCURR_ACT_RW(hprt0, 0);
+ return hprt0;
+}
+
+/*
+ * The following functions support managing the DWC_otg controller in either
+ * device or host mode.
+ */
+extern void dwc_otg_read_packet(struct core_if *core_if, u8 * dest, u16 bytes);
+extern void dwc_otg_flush_tx_fifo(struct core_if *core_if, const int _num);
+extern void dwc_otg_flush_rx_fifo(struct core_if *core_if);
+
+#define NP_TXFIFO_EMPTY -1
+#define MAX_NP_TXREQUEST_Q_SLOTS 8
+
+/**
+ * This function returns the Core Interrupt register.
+ */
+static inline u32 dwc_otg_read_core_intr(struct core_if *core_if)
+{
+ u32 global_regs = (u32) core_if->core_global_regs;
+ return dwc_reg_read(global_regs, DWC_GINTSTS) &
+ dwc_reg_read(global_regs, DWC_GINTMSK);
+}
+
+/**
+ * This function returns the mode of the operation, host or device.
+ */
+static inline u32 dwc_otg_mode(struct core_if *core_if)
+{
+ u32 global_regs = (u32) core_if->core_global_regs;
+ return dwc_reg_read(global_regs, DWC_GINTSTS) & 0x1;
+}
+
+static inline u8 dwc_otg_is_device_mode(struct core_if *core_if)
+{
+ return dwc_otg_mode(core_if) != DWC_HOST_MODE;
+}
+static inline u8 dwc_otg_is_host_mode(struct core_if *core_if)
+{
+ return dwc_otg_mode(core_if) == DWC_HOST_MODE;
+}
+
+extern int dwc_otg_handle_common_intr(struct core_if *core_if);
+
+/*
+ * DWC_otg CIL callback structure. This structure allows the HCD and PCD to
+ * register functions used for starting and stopping the PCD and HCD for role
+ * change on for a DRD.
+ */
+struct cil_callbacks {
+ /* Start function for role change */
+ int (*start) (void *_p);
+ /* Stop Function for role change */
+ int (*stop) (void *_p);
+ /* Disconnect Function for role change */
+ int (*disconnect) (void *_p);
+ /* Resume/Remote wakeup Function */
+ int (*resume_wakeup) (void *_p);
+ /* Suspend function */
+ int (*suspend) (void *_p);
+ /* Session Start (SRP) */
+ int (*session_start) (void *_p);
+ /* Pointer passed to start() and stop() */
+ void *p;
+};
+
+extern void dwc_otg_cil_register_pcd_callbacks(struct core_if *core_if,
+ struct cil_callbacks *cb,
+ void *p);
+extern void dwc_otg_cil_register_hcd_callbacks(struct core_if *core_if,
+ struct cil_callbacks *cb,
+ void *p);
+
+#define DWC_LIMITED_XFER 0x00000000
+#define DWC_DEVICE_ONLY 0x00000000
+#define DWC_HOST_ONLY 0x00000000
+
+#ifdef DWC_LIMITED_XFER_SIZE
+#undef DWC_LIMITED_XFER
+#define DWC_LIMITED_XFER 0x00000001
+#endif
+
+#ifdef CONFIG_DWC_DEVICE_ONLY
+#undef DWC_DEVICE_ONLY
+#define DWC_DEVICE_ONLY 0x00000002
+static inline void dwc_otg_hcd_remove(struct device *dev)
+{
+}
+static inline int dwc_otg_hcd_init(struct device *_dev,
+ struct dwc_otg_device *dwc_dev)
+{
+ return 0;
+}
+#else
+extern int dwc_otg_hcd_init(struct device *_dev,
+ struct dwc_otg_device *dwc_dev);
+extern void dwc_otg_hcd_remove(struct device *_dev);
+#endif
+
+#ifdef CONFIG_DWC_HOST_ONLY
+#undef DWC_HOST_ONLY
+#define DWC_HOST_ONLY 0x00000004
+static inline void dwc_otg_pcd_remove(struct device *dev)
+{
+}
+static inline int dwc_otg_pcd_init(struct device *dev)
+{
+ return 0;
+}
+#else
+extern void dwc_otg_pcd_remove(struct device *dev);
+extern int dwc_otg_pcd_init(struct device *dev);
+#endif
+
+extern void dwc_otg_cil_remove(struct core_if *core_if);
+extern struct core_if *dwc_otg_cil_init(const __iomem u32 * base,
+ struct core_params *params);
+
+static inline void dwc_set_feature(struct core_if *core_if)
+{
+ core_if->features = DWC_LIMITED_XFER | DWC_DEVICE_ONLY | DWC_HOST_ONLY;
+}
+
+static inline int dwc_has_feature(struct core_if *core_if,
+ unsigned long feature)
+{
+ return core_if->features & feature;
+}
+extern struct core_params dwc_otg_module_params;
+extern int check_parameters(struct core_if *core_if);
+#endif
diff --git a/drivers/usb/dwc/cil_intr.c b/drivers/usb/dwc/cil_intr.c
new file mode 100644
index 0000000..a42b0e6
--- /dev/null
+++ b/drivers/usb/dwc/cil_intr.c
@@ -0,0 +1,616 @@
+/*
+ * DesignWare HS OTG controller driver
+ * Copyright (C) 2006 Synopsys, Inc.
+ * Portions Copyright (C) 2010 Applied Micro Circuits Corporation.
+ *
+ * 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 version 2 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
+ * or write to the Free Software Foundation, Inc., 51 Franklin Street,
+ * Suite 500, Boston, MA 02110-1335 USA.
+ *
+ * Based on Synopsys driver version 2.60a
+ * Modified by Mark Miesfeld <mmiesfeld@apm.com>
+ * Modified by Stefan Roese <sr@denx.de>, DENX Software Engineering
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL SYNOPSYS, INC. BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * The Core Interface Layer provides basic services for accessing and
+ * managing the DWC_otg hardware. These services are used by both the
+ * Host Controller Driver and the Peripheral Controller Driver.
+ *
+ * This file contains the Common Interrupt handlers.
+ */
+#include <linux/delay.h>
+
+#include "cil.h"
+
+/**
+ * This function will log a debug message
+ */
+static int dwc_otg_handle_mode_mismatch_intr(struct core_if *core_if)
+{
+ u32 gintsts = 0;
+ ulong global_regs = core_if->core_global_regs;
+
+ pr_warning("Mode Mismatch Interrupt: currently in %s mode\n",
+ dwc_otg_mode(core_if) ? "Host" : "Device");
+
+ /* Clear interrupt */
+ gintsts |= DWC_INTSTS_MODE_MISMTC;
+ dwc_reg_write(global_regs, DWC_GINTSTS, gintsts);
+
+ return 1;
+}
+
+/**
+ * Start the HCD. Helper function for using the HCD callbacks.
+ */
+static inline void hcd_start(struct core_if *core_if)
+{
+ if (core_if->hcd_cb && core_if->hcd_cb->start)
+ core_if->hcd_cb->start(core_if->hcd_cb->p);
+}
+
+/**
+ * Stop the HCD. Helper function for using the HCD callbacks.
+ */
+static inline void hcd_stop(struct core_if *core_if)
+{
+ if (core_if->hcd_cb && core_if->hcd_cb->stop)
+ core_if->hcd_cb->stop(core_if->hcd_cb->p);
+}
+
+/**
+ * Disconnect the HCD. Helper function for using the HCD callbacks.
+ */
+static inline void hcd_disconnect(struct core_if *core_if)
+{
+ if (core_if->hcd_cb && core_if->hcd_cb->disconnect)
+ core_if->hcd_cb->disconnect(core_if->hcd_cb->p);
+}
+
+/**
+ * Inform the HCD the a New Session has begun. Helper function for using the
+ * HCD callbacks.
+ */
+static inline void hcd_session_start(struct core_if *core_if)
+{
+ if (core_if->hcd_cb && core_if->hcd_cb->session_start)
+ core_if->hcd_cb->session_start(core_if->hcd_cb->p);
+}
+
+/**
+ * Start the PCD. Helper function for using the PCD callbacks.
+ */
+static inline void pcd_start(struct core_if *core_if)
+{
+ if (core_if->pcd_cb && core_if->pcd_cb->start) {
+ struct dwc_pcd *pcd;
+
+ pcd = (struct dwc_pcd *)core_if->pcd_cb->p;
+ spin_lock(&pcd->lock);
+ core_if->pcd_cb->start(core_if->pcd_cb->p);
+ spin_unlock(&pcd->lock);
+ }
+}
+
+/**
+ * Stop the PCD. Helper function for using the PCD callbacks.
+ */
+static inline void pcd_stop(struct core_if *core_if)
+{
+ if (core_if->pcd_cb && core_if->pcd_cb->stop) {
+ struct dwc_pcd *pcd;
+
+ pcd = (struct dwc_pcd *)core_if->pcd_cb->p;
+ spin_lock(&pcd->lock);
+ core_if->pcd_cb->stop(core_if->pcd_cb->p);
+ spin_unlock(&pcd->lock);
+ }
+}
+
+/**
+ * Suspend the PCD. Helper function for using the PCD callbacks.
+ */
+static inline void pcd_suspend(struct core_if *core_if)
+{
+ if (core_if->pcd_cb && core_if->pcd_cb->suspend) {
+ struct dwc_pcd *pcd;
+
+ pcd = (struct dwc_pcd *)core_if->pcd_cb->p;
+ spin_lock(&pcd->lock);
+ core_if->pcd_cb->suspend(core_if->pcd_cb->p);
+ spin_unlock(&pcd->lock);
+ }
+}
+
+/**
+ * Resume the PCD. Helper function for using the PCD callbacks.
+ */
+static inline void pcd_resume(struct core_if *core_if)
+{
+ if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) {
+ struct dwc_pcd *pcd;
+
+ pcd = (struct dwc_pcd *)core_if->pcd_cb->p;
+ spin_lock(&pcd->lock);
+ core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p);
+ spin_unlock(&pcd->lock);
+ }
+}
+
+/**
+ * This function handles the OTG Interrupts. It reads the OTG
+ * Interrupt Register (GOTGINT) to determine what interrupt has
+ * occurred.
+ */
+static int dwc_otg_handle_otg_intr(struct core_if *core_if)
+{
+ ulong global_regs = core_if->core_global_regs;
+ u32 gotgint;
+ u32 gotgctl;
+ u32 gintmsk;
+
+ gotgint = dwc_reg_read(global_regs, DWC_GOTGINT);
+ if (gotgint & DWC_GINT_SES_ENDDET) {
+ gotgctl = dwc_reg_read(global_regs, DWC_GOTGCTL);
+ if (core_if->xceiv->state == OTG_STATE_B_HOST) {
+ pcd_start(core_if);
+ core_if->xceiv->state = OTG_STATE_B_PERIPHERAL;
+ } else {
+ /*
+ * If not B_HOST and Device HNP still set. HNP did not
+ * succeed
+ */
+ if (gotgctl & DWC_GCTL_DEV_HNP_ENA)
+ pr_err("Device Not Connected / "
+ "Responding\n");
+ /*
+ * If Session End Detected the B-Cable has been
+ * disconnected. Reset PCD and Gadget driver to a
+ * clean state.
+ */
+ pcd_stop(core_if);
+ }
+ gotgctl = 0;
+ gotgctl |= DWC_GCTL_DEV_HNP_ENA;
+ dwc_reg_modify(global_regs, DWC_GOTGCTL, gotgctl, 0);
+ }
+ if (gotgint & DWC_GINT_SES_REQSUC) {
+ gotgctl = dwc_reg_read(global_regs, DWC_GOTGCTL);
+ if (gotgctl & DWC_GCTL_SES_REQ_SUCCESS) {
+ if (core_if->core_params->phy_type ==
+ DWC_PHY_TYPE_PARAM_FS &&
+ core_if->core_params->i2c_enable) {
+ core_if->srp_success = 1;
+ } else {
+ pcd_resume(core_if);
+
+ /* Clear Session Request */
+ gotgctl = 0;
+ gotgctl |= DWC_GCTL_SES_REQ;
+ dwc_reg_modify(global_regs, DWC_GOTGCTL,
+ gotgctl, 0);
+ }
+ }
+ }
+ if (gotgint & DWC_GINT_HST_NEGSUC) {
+ /*
+ * Print statements during the HNP interrupt handling can cause
+ * it to fail.
+ */
+ gotgctl = dwc_reg_read(global_regs, DWC_GOTGCTL);
+ if (gotgctl & DWC_GCTL_HOST_NEG_SUCCES) {
+ if (dwc_otg_is_host_mode(core_if)) {
+ core_if->xceiv->state = OTG_STATE_B_HOST;
+ /*
+ * Need to disable SOF interrupt immediately.
+ * When switching from device to host, the PCD
+ * interrupt handler won't handle the
+ * interrupt if host mode is already set. The
+ * HCD interrupt handler won't get called if
+ * the HCD state is HALT. This means that the
+ * interrupt does not get handled and Linux
+ * complains loudly.
+ */
+ gintmsk = 0;
+ gintmsk |= DWC_INTMSK_STRT_OF_FRM;
+ dwc_reg_modify(global_regs, DWC_GINTMSK,
+ gintmsk, 0);
+ pcd_stop(core_if);
+ /* Initialize the Core for Host mode. */
+ hcd_start(core_if);
+ core_if->xceiv->state = OTG_STATE_B_HOST;
+ }
+ } else {
+ gotgctl = 0;
+ gotgctl |= DWC_GCTL_HNP_REQ;
+ gotgctl |= DWC_GCTL_DEV_HNP_ENA;
+ dwc_reg_modify(global_regs, DWC_GOTGCTL, gotgctl, 0);
+
+ pr_err("Device Not Connected / Responding\n");
+ }
+ }
+ if (gotgint & DWC_GINT_HST_NEGDET) {
+ /*
+ * The disconnect interrupt is set at the same time as
+ * Host Negotiation Detected. During the mode
+ * switch all interrupts are cleared so the disconnect
+ * interrupt handler will not get executed.
+ */
+ if (dwc_otg_is_device_mode(core_if)) {
+ hcd_disconnect(core_if);
+ pcd_start(core_if);
+ core_if->xceiv->state = OTG_STATE_A_PERIPHERAL;
+ } else {
+ /*
+ * Need to disable SOF interrupt immediately. When
+ * switching from device to host, the PCD interrupt
+ * handler won't handle the interrupt if host mode is
+ * already set. The HCD interrupt handler won't get
+ * called if the HCD state is HALT. This means that
+ * the interrupt does not get handled and Linux
+ * complains loudly.
+ */
+ gintmsk = 0;
+ gintmsk |= DWC_INTMSK_STRT_OF_FRM;
+ dwc_reg_modify(global_regs, DWC_GINTMSK, gintmsk, 0);
+ pcd_stop(core_if);
+ hcd_start(core_if);
+ core_if->xceiv->state = OTG_STATE_A_HOST;
+ }
+ }
+ if (gotgint & DWC_GINT_DEVTOUT)
+ pr_info(" ++OTG Interrupt: A-Device Timeout " "Change++\n");
+ if (gotgint & DWC_GINT_DEBDONE)
+ pr_info(" ++OTG Interrupt: Debounce Done++\n");
+
+ /* Clear GOTGINT */
+ dwc_reg_write(global_regs, DWC_GOTGINT, gotgint);
+ return 1;
+}
+
+/*
+ * Wakeup Workqueue implementation
+ */
+static void port_otg_wqfunc(struct work_struct *work)
+{
+ struct core_if *core_if = container_of(work, struct core_if,
+ usb_port_otg);
+ ulong global_regs = core_if->core_global_regs;
+ u32 count = 0;
+ u32 gotgctl;
+
+ pr_info("%s\n", __func__);
+
+ gotgctl = dwc_reg_read(global_regs, DWC_GOTGCTL);
+ if (gotgctl & DWC_GCTL_CONN_ID_STATUS) {
+ /*
+ * B-Device connector (device mode) wait for switch to device
+ * mode.
+ */
+ while (!dwc_otg_is_device_mode(core_if) && ++count <= 10000) {
+ pr_info("Waiting for Peripheral Mode, "
+ "Mode=%s\n", dwc_otg_is_host_mode(core_if) ?
+ "Host" : "Peripheral");
+ msleep(100);
+ }
+ BUG_ON(count > 10000);
+ core_if->xceiv->state = OTG_STATE_B_PERIPHERAL;
+ dwc_otg_core_init(core_if);
+ dwc_otg_enable_global_interrupts(core_if);
+ pcd_start(core_if);
+ } else {
+ /*
+ * A-Device connector (host mode) wait for switch to host
+ * mode.
+ */
+ while (!dwc_otg_is_host_mode(core_if) && ++count <= 10000) {
+ pr_info("Waiting for Host Mode, Mode=%s\n",
+ dwc_otg_is_host_mode(core_if) ?
+ "Host" : "Peripheral");
+ msleep(100);
+ }
+ BUG_ON(count > 10000);
+ core_if->xceiv->state = OTG_STATE_A_HOST;
+ dwc_otg_core_init(core_if);
+ dwc_otg_enable_global_interrupts(core_if);
+ hcd_start(core_if);
+ }
+}
+
+/**
+ * This function handles the Connector ID Status Change Interrupt. It
+ * reads the OTG Interrupt Register (GOTCTL) to determine whether this
+ * is a Device to Host Mode transition or a Host Mode to Device
+ * Transition.
+ *
+ * This only occurs when the cable is connected/removed from the PHY
+ * connector.
+ */
+static int dwc_otg_handle_conn_id_status_change_intr(struct core_if *core_if)
+{
+ u32 gintsts = 0;
+ u32 gintmsk = 0;
+ ulong global_regs = core_if->core_global_regs;
+
+ /*
+ * Need to disable SOF interrupt immediately. If switching from device
+ * to host, the PCD interrupt handler won't handle the interrupt if
+ * host mode is already set. The HCD interrupt handler won't get
+ * called if the HCD state is HALT. This means that the interrupt does
+ * not get handled and Linux complains loudly.
+ */
+ gintmsk |= DWC_INTSTS_STRT_OF_FRM;
+ dwc_reg_modify(global_regs, DWC_GINTMSK, gintmsk, 0);
+
+ INIT_WORK(&core_if->usb_port_otg, port_otg_wqfunc);
+ schedule_work(&core_if->usb_port_otg);
+
+ /* Set flag and clear interrupt */
+ gintsts |= DWC_INTSTS_CON_ID_STS_CHG;
+ dwc_reg_write(global_regs, DWC_GINTSTS, gintsts);
+ return 1;
+}
+
+/**
+ * This interrupt indicates that a device is initiating the Session
+ * Request Protocol to request the host to turn on bus power so a new
+ * session can begin. The handler responds by turning on bus power. If
+ * the DWC_otg controller is in low power mode, the handler brings the
+ * controller out of low power mode before turning on bus power.
+ */
+static int dwc_otg_handle_session_req_intr(struct core_if *core_if)
+{
+ u32 gintsts = 0;
+ ulong global_regs = core_if->core_global_regs;
+
+ if (!dwc_has_feature(core_if, DWC_HOST_ONLY)) {
+ u32 hprt0;
+
+ if (dwc_otg_is_device_mode(core_if)) {
+ pr_info("SRP: Device mode\n");
+ } else {
+ pr_info("SRP: Host mode\n");
+
+ /* Turn on the port power bit. */
+ hprt0 = dwc_otg_read_hprt0(core_if);
+ hprt0 = DWC_HPRT0_PRT_PWR_RW(hprt0, 1);
+ dwc_reg_write(core_if->host_if->hprt0, 0, hprt0);
+
+ /*
+ * Start the Connection timer.
+ * A message can be displayed,
+ * if connect does not occur within 10 seconds.
+ */
+ hcd_session_start(core_if);
+ }
+ }
+ /* Clear interrupt */
+ gintsts |= DWC_INTSTS_NEW_SES_DET;
+ dwc_reg_write(global_regs, DWC_GINTSTS, gintsts);
+ return 1;
+}
+
+/**
+ * This interrupt indicates that the DWC_otg controller has detected a
+ * resume or remote wakeup sequence. If the DWC_otg controller is in
+ * low power mode, the handler must brings the controller out of low
+ * power mode. The controller automatically begins resume
+ * signaling. The handler schedules a time to stop resume signaling.
+ */
+static int dwc_otg_handle_wakeup_detected_intr(struct core_if *core_if)
+{
+ u32 gintsts = 0;
+ struct device_if *dev_if = core_if->dev_if;
+ ulong global_regs = core_if->core_global_regs;
+
+ if (dwc_otg_is_device_mode(core_if)) {
+ u32 dctl = 0;
+
+ /* Clear the Remote Wakeup Signalling */
+ dctl = DEC_DCTL_REMOTE_WAKEUP_SIG(dctl, 1);
+ dwc_reg_modify(dev_if->dev_global_regs, DWC_DCTL, dctl, 0);
+
+ if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup)
+ core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p);
+ } else {
+ u32 pcgcctl = 0;
+
+ /* Restart the Phy Clock */
+ pcgcctl = DWC_PCGCCTL_STOP_CLK_SET(pcgcctl);
+ dwc_reg_modify(core_if->pcgcctl, 0, pcgcctl, 0);
+ schedule_delayed_work(&core_if->usb_port_wakeup, 10);
+ }
+
+ /* Clear interrupt */
+ gintsts |= DWC_INTSTS_WKP;
+ dwc_reg_write(global_regs, DWC_GINTSTS, gintsts);
+ return 1;
+}
+
+/**
+ * This interrupt indicates that a device has been disconnected from
+ * the root port.
+ */
+static int dwc_otg_handle_disconnect_intr(struct core_if *core_if)
+{
+ u32 gintsts = 0;
+ ulong global_regs = core_if->core_global_regs;
+
+ if (!dwc_has_feature(core_if, DWC_HOST_ONLY)) {
+ if (core_if->xceiv->state == OTG_STATE_B_HOST) {
+ hcd_disconnect(core_if);
+ pcd_start(core_if);
+ core_if->xceiv->state = OTG_STATE_B_PERIPHERAL;
+ } else if (dwc_otg_is_device_mode(core_if)) {
+ u32 gotgctl;
+
+ gotgctl = dwc_reg_read(global_regs, DWC_GOTGCTL);
+
+ /*
+ * If HNP is in process, do nothing.
+ * The OTG "Host Negotiation Detected"
+ * interrupt will do the mode switch.
+ * Otherwise, since we are in device mode,
+ * disconnect and stop the HCD,
+ * then start the PCD.
+ */
+ if ((gotgctl) & DWC_GCTL_DEV_HNP_ENA) {
+ hcd_disconnect(core_if);
+ pcd_start(core_if);
+ core_if->xceiv->state = OTG_STATE_B_PERIPHERAL;
+ }
+ } else if (core_if->xceiv->state == OTG_STATE_A_HOST) {
+ /* A-Cable still connected but device disconnected. */
+ hcd_disconnect(core_if);
+ }
+ }
+ gintsts |= DWC_INTSTS_SES_DISCON_DET;
+ dwc_reg_write(global_regs, DWC_GINTSTS, gintsts);
+ return 1;
+}
+
+/**
+ * This interrupt indicates that SUSPEND state has been detected on
+ * the USB.
+ *
+ * For HNP the USB Suspend interrupt signals the change from
+ * "a_peripheral" to "a_host".
+ *
+ * When power management is enabled the core will be put in low power
+ * mode.
+ */
+static int dwc_otg_handle_usb_suspend_intr(struct core_if *core_if)
+{
+ u32 dsts = 0;
+ u32 gintsts = 0;
+ ulong global_regs = core_if->core_global_regs;
+ struct device_if *dev_if = core_if->dev_if;
+
+ if (dwc_otg_is_device_mode(core_if)) {
+ /*
+ * Check the Device status register to determine if the Suspend
+ * state is active.
+ */
+ dsts = dwc_reg_read(dev_if->dev_global_regs, DWC_DSTS);
+ /* PCD callback for suspend. */
+ pcd_suspend(core_if);
+ } else {
+ if (core_if->xceiv->state == OTG_STATE_A_PERIPHERAL) {
+ /* Clear the a_peripheral flag, back to a_host. */
+ pcd_stop(core_if);
+ hcd_start(core_if);
+ core_if->xceiv->state = OTG_STATE_A_HOST;
+ }
+ }
+
+ /* Clear interrupt */
+ gintsts |= DWC_INTMSK_USB_SUSP;
+ dwc_reg_write(global_regs, DWC_GINTSTS, gintsts);
+ return 1;
+}
+
+/**
+ * This function returns the Core Interrupt register.
+ *
+ * Although the Host Port interrupt (portintr) is documented as host mode
+ * only, it appears to occur in device mode when Port Enable / Disable Changed
+ * bit in HPRT0 is set. The code in dwc_otg_handle_common_intr checks if in
+ * device mode and just clears the interrupt.
+ */
+static inline u32 dwc_otg_read_common_intr(struct core_if *core_if)
+{
+ u32 gintsts;
+ u32 gintmsk;
+ u32 gintmsk_common = 0;
+ ulong global_regs = core_if->core_global_regs;
+
+ gintmsk_common |= DWC_INTMSK_WKP;
+ gintmsk_common |= DWC_INTMSK_NEW_SES_DET;
+ gintmsk_common |= DWC_INTMSK_CON_ID_STS_CHG;
+ gintmsk_common |= DWC_INTMSK_OTG;
+ gintmsk_common |= DWC_INTMSK_MODE_MISMTC;
+ gintmsk_common |= DWC_INTMSK_SES_DISCON_DET;
+ gintmsk_common |= DWC_INTMSK_USB_SUSP;
+ gintmsk_common |= DWC_INTMSK_HST_PORT;
+
+ gintsts = dwc_reg_read(global_regs, DWC_GINTSTS);
+ gintmsk = dwc_reg_read(global_regs, DWC_GINTMSK);
+
+ return (gintsts & gintmsk) & gintmsk_common;
+}
+
+/**
+ * Common interrupt handler.
+ *
+ * The common interrupts are those that occur in both Host and Device mode.
+ * This handler handles the following interrupts:
+ * - Mode Mismatch Interrupt
+ * - Disconnect Interrupt
+ * - OTG Interrupt
+ * - Connector ID Status Change Interrupt
+ * - Session Request Interrupt.
+ * - Resume / Remote Wakeup Detected Interrupt.
+ *
+ * - Host Port Interrupt. Although this interrupt is documented as only
+ * occurring in Host mode, it also occurs in Device mode when Port Enable /
+ * Disable Changed bit in HPRT0 is set. If it is seen here, while in Device
+ * mode, the interrupt is just cleared.
+ *
+ */
+int dwc_otg_handle_common_intr(struct core_if *core_if)
+{
+ int retval = 0;
+ u32 gintsts;
+ ulong global_regs = core_if->core_global_regs;
+
+ gintsts = dwc_otg_read_common_intr(core_if);
+
+ if (gintsts & DWC_INTSTS_MODE_MISMTC)
+ retval |= dwc_otg_handle_mode_mismatch_intr(core_if);
+ if (gintsts & DWC_INTSTS_OTG)
+ retval |= dwc_otg_handle_otg_intr(core_if);
+ if (gintsts & DWC_INTSTS_CON_ID_STS_CHG)
+ retval |= dwc_otg_handle_conn_id_status_change_intr(core_if);
+ if (gintsts & DWC_INTSTS_SES_DISCON_DET)
+ retval |= dwc_otg_handle_disconnect_intr(core_if);
+ if (gintsts & DWC_INTSTS_NEW_SES_DET)
+ retval |= dwc_otg_handle_session_req_intr(core_if);
+ if (gintsts & DWC_INTSTS_WKP)
+ retval |= dwc_otg_handle_wakeup_detected_intr(core_if);
+ if (gintsts & DWC_INTMSK_USB_SUSP)
+ retval |= dwc_otg_handle_usb_suspend_intr(core_if);
+
+ if ((gintsts & DWC_INTSTS_HST_PORT) &&
+ dwc_otg_is_device_mode(core_if)) {
+ gintsts = 0;
+ gintsts |= DWC_INTSTS_HST_PORT;
+ dwc_reg_write(global_regs, DWC_GINTSTS, gintsts);
+ retval |= 1;
+ pr_info("RECEIVED PORTINT while in Device mode\n");
+ }
+
+ return retval;
+}
diff --git a/drivers/usb/dwc/driver.h b/drivers/usb/dwc/driver.h
new file mode 100644
index 0000000..a86532b
--- /dev/null
+++ b/drivers/usb/dwc/driver.h
@@ -0,0 +1,76 @@
+/*
+ * DesignWare HS OTG controller driver
+ * Copyright (C) 2006 Synopsys, Inc.
+ * Portions Copyright (C) 2010 Applied Micro Circuits Corporation.
+ *
+ * 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 version 2 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
+ * or write to the Free Software Foundation, Inc., 51 Franklin Street,
+ * Suite 500, Boston, MA 02110-1335 USA.
+ *
+ * Based on Synopsys driver version 2.60a
+ * Modified by Mark Miesfeld <mmiesfeld@apm.com>
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL SYNOPSYS, INC. 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.
+ *
+ */
+
+#if !defined(__DWC_OTG_DRIVER_H__)
+#define __DWC_OTG_DRIVER_H__
+
+/*
+ * This file contains the interface to the Linux driver.
+ */
+#include "cil.h"
+
+/*
+ * This structure is a wrapper that encapsulates the driver components used to
+ * manage a single DWC_otg controller.
+ */
+struct dwc_otg_device {
+ /* Base address returned from ioremap() */
+ __iomem void *base;
+
+ /* Pointer to the core interface structure. */
+ struct core_if *core_if;
+
+ /* Pointer to the PCD structure. */
+ struct dwc_pcd *pcd;
+
+ /* Pointer to the HCD structure. */
+ struct dwc_hcd *hcd;
+
+ /* Flag to indicate whether the common IRQ handler is installed. */
+ u8 common_irq_installed;
+
+ /* Interrupt request number. */
+ unsigned int irq;
+
+ /*
+ * Physical address of Control and Status registers, used by
+ * release_mem_region().
+ */
+ resource_size_t phys_addr;
+
+ /* Length of memory region, used by release_mem_region(). */
+ unsigned long base_len;
+};
+#endif
diff --git a/drivers/usb/dwc/hcd.c b/drivers/usb/dwc/hcd.c
new file mode 100644
index 0000000..2718b95
--- /dev/null
+++ b/drivers/usb/dwc/hcd.c
@@ -0,0 +1,2473 @@
+/*
+ * DesignWare HS OTG controller driver
+ * Copyright (C) 2006 Synopsys, Inc.
+ * Portions Copyright (C) 2010 Applied Micro Circuits Corporation.
+ *
+ * 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 version 2 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
+ * or write to the Free Software Foundation, Inc., 51 Franklin Street,
+ * Suite 500, Boston, MA 02110-1335 USA.
+ *
+ * Based on Synopsys driver version 2.60a
+ * Modified by Mark Miesfeld <mmiesfeld@apm.com>
+ * Modified by Stefan Roese <sr@denx.de>, DENX Software Engineering
+ * Modified by Chuck Meade <chuck@theptrgroup.com>
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL SYNOPSYS, INC. 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.
+ *
+ */
+
+/*
+ * This file contains the implementation of the HCD. In Linux, the HCD
+ * implements the hc_driver API.
+ */
+
+#include <asm/unaligned.h>
+#include <linux/dma-mapping.h>
+
+#include "hcd.h"
+
+static const char dwc_otg_hcd_name[] = "dwc_otg_hcd";
+
+/**
+ * Clears the transfer state for a host channel. This function is normally
+ * called after a transfer is done and the host channel is being released. It
+ * clears the channel interrupt enables and any unhandled channel interrupt
+ * conditions.
+ */
+void dwc_otg_hc_cleanup(struct core_if *core_if, struct dwc_hc *hc)
+{
+ ulong regs;
+
+ hc->xfer_started = 0;
+ regs = core_if->host_if->hc_regs[hc->hc_num];
+ dwc_reg_write(regs, DWC_HCINTMSK, 0);
+ dwc_reg_write(regs, DWC_HCINT, 0xFFFFFFFF);
+}
+
+/**
+ * This function enables the Host mode interrupts.
+ */
+static void dwc_otg_enable_host_interrupts(struct core_if *core_if)
+{
+ ulong global_regs = core_if->core_global_regs;
+ u32 intr_mask = 0;
+
+ /* Disable all interrupts. */
+ dwc_reg_write(global_regs, DWC_GINTMSK, 0);
+
+ /* Clear any pending interrupts. */
+ dwc_reg_write(global_regs, DWC_GINTSTS, 0xFFFFFFFF);
+
+ /* Enable the common interrupts */
+ dwc_otg_enable_common_interrupts(core_if);
+
+ /*
+ * Enable host mode interrupts without disturbing common
+ * interrupts.
+ */
+ intr_mask |= DWC_INTMSK_STRT_OF_FRM;
+ intr_mask |= DWC_INTMSK_HST_PORT;
+ intr_mask |= DWC_INTMSK_HST_CHAN;
+ dwc_reg_modify(global_regs, DWC_GINTMSK, intr_mask, intr_mask);
+}
+
+/**
+ * This function initializes the DWC_otg controller registers for
+ * host mode.
+ *
+ * This function flushes the Tx and Rx FIFOs and it flushes any entries in the
+ * request queues. Host channels are reset to ensure that they are ready for
+ * performing transfers.
+ */
+static void dwc_otg_core_host_init(struct core_if *core_if)
+{
+ ulong global_regs = core_if->core_global_regs;
+ struct dwc_host_if *host_if = core_if->host_if;
+ struct core_params *params = core_if->core_params;
+ u32 hprt0 = 0;
+ u32 nptxfifosize = 0;
+ u32 ptxfifosize = 0;
+ u32 i;
+ u32 hcchar;
+ ulong hcfg;
+ ulong hc_regs;
+ int num_channels;
+ u32 gotgctl = 0;
+
+ /* Restart the Phy Clock */
+ dwc_reg_write(core_if->pcgcctl, 0, 0);
+
+ /* Initialize Host Configuration Register */
+ init_fslspclksel(core_if);
+ if (core_if->core_params->speed == DWC_SPEED_PARAM_FULL) {
+ hcfg = dwc_reg_read(host_if->host_global_regs, DWC_HCFG);
+ hcfg = DWC_HCFG_FSLSUPP_RW(hcfg, 1);
+ dwc_reg_write(host_if->host_global_regs, DWC_HCFG, hcfg);
+ }
+
+ /* Configure data FIFO sizes */
+ if (DWC_HWCFG2_DYN_FIFO_RD(core_if->hwcfg2)
+ && params->enable_dynamic_fifo) {
+ /* Rx FIFO */
+ dwc_reg_write(global_regs, DWC_GRXFSIZ,
+ params->host_rx_fifo_size);
+
+ /* Non-periodic Tx FIFO */
+ nptxfifosize = DWC_RX_FIFO_DEPTH_WR(nptxfifosize,
+ params->
+ host_nperio_tx_fifo_size);
+ nptxfifosize =
+ DWC_RX_FIFO_START_ADDR_WR(nptxfifosize,
+ params->host_rx_fifo_size);
+ dwc_reg_write(global_regs, DWC_GNPTXFSIZ, nptxfifosize);
+
+ /* Periodic Tx FIFO */
+ ptxfifosize = DWC_RX_FIFO_DEPTH_WR(ptxfifosize,
+ params->
+ host_perio_tx_fifo_size);
+ ptxfifosize =
+ DWC_RX_FIFO_START_ADDR_WR(ptxfifosize,
+ (DWC_RX_FIFO_START_ADDR_RD
+ (nptxfifosize) +
+ DWC_RX_FIFO_DEPTH_RD
+ (nptxfifosize)));
+ dwc_reg_write(global_regs, DWC_HPTXFSIZ, ptxfifosize);
+ }
+
+ /* Clear Host Set HNP Enable in the OTG Control Register */
+ gotgctl |= DWC_GCTL_HOST_HNP_ENA;
+ dwc_reg_modify(global_regs, DWC_GOTGCTL, gotgctl, 0);
+
+ /* Make sure the FIFOs are flushed. */
+ dwc_otg_flush_tx_fifo(core_if, DWC_GRSTCTL_TXFNUM_ALL);
+ dwc_otg_flush_rx_fifo(core_if);
+
+ /* Flush out any leftover queued requests. */
+ num_channels = core_if->core_params->host_channels;
+ for (i = 0; i < num_channels; i++) {
+ hc_regs = core_if->host_if->hc_regs[i];
+ hcchar = dwc_reg_read(hc_regs, DWC_HCCHAR);
+ hcchar = DWC_HCCHAR_ENA_RW(hcchar, 0);
+ hcchar = DWC_HCCHAR_DIS_RW(hcchar, 1);
+ hcchar = DWC_HCCHAR_EPDIR_RW(hcchar, 0);
+ dwc_reg_write(hc_regs, DWC_HCCHAR, hcchar);
+ }
+
+ /* Halt all channels to put them into a known state. */
+ for (i = 0; i < num_channels; i++) {
+ int count = 0;
+
+ hc_regs = core_if->host_if->hc_regs[i];
+ hcchar = dwc_reg_read(hc_regs, DWC_HCCHAR);
+ hcchar = DWC_HCCHAR_ENA_RW(hcchar, 1);
+ hcchar = DWC_HCCHAR_DIS_RW(hcchar, 1);
+ hcchar = DWC_HCCHAR_EPDIR_RW(hcchar, 0);
+ dwc_reg_write(hc_regs, DWC_HCCHAR, hcchar);
+
+ do {
+ hcchar = dwc_reg_read(hc_regs, DWC_HCCHAR);
+ if (++count > 200) {
+ pr_err("%s: Unable to clear halt on "
+ "channel %d\n", __func__, i);
+ break;
+ }
+ udelay(100);
+ } while (DWC_HCCHAR_ENA_RD(hcchar));
+ }
+
+ /* Turn on the vbus power. */
+ pr_info("Init: Port Power? op_state=%s\n",
+ otg_state_string(core_if->xceiv->state));
+
+ if (core_if->xceiv->state == OTG_STATE_A_HOST) {
+ hprt0 = dwc_otg_read_hprt0(core_if);
+ pr_info("Init: Power Port (%d)\n", DWC_HPRT0_PRT_PWR_RD(hprt0));
+ if (DWC_HPRT0_PRT_PWR_RD(hprt0) == 0) {
+ hprt0 = DWC_HPRT0_PRT_PWR_RW(hprt0, 1);
+ dwc_reg_write(host_if->hprt0, 0, hprt0);
+ }
+ }
+ dwc_otg_enable_host_interrupts(core_if);
+}
+
+/**
+ * Initializes dynamic portions of the DWC_otg HCD state.
+ */
+static void hcd_reinit(struct dwc_hcd *hcd)
+{
+ struct list_head *item;
+ int num_channels;
+ u32 i;
+ struct dwc_hc *channel;
+
+ hcd->flags.d32 = 0;
+ hcd->non_periodic_qh_ptr = &hcd->non_periodic_sched_active;
+ hcd->available_host_channels = hcd->core_if->core_params->host_channels;
+
+ /*
+ * Put all channels in the free channel list and clean up channel
+ * states.
+ */
+ item = hcd->free_hc_list.next;
+ while (item != &hcd->free_hc_list) {
+ list_del(item);
+ item = hcd->free_hc_list.next;
+ }
+
+ num_channels = hcd->core_if->core_params->host_channels;
+ for (i = 0; i < num_channels; i++) {
+ channel = hcd->hc_ptr_array[i];
+ list_add_tail(&channel->hc_list_entry, &hcd->free_hc_list);
+ dwc_otg_hc_cleanup(hcd->core_if, channel);
+ }
+
+ /* Initialize the DWC core for host mode operation. */
+ dwc_otg_core_host_init(hcd->core_if);
+}
+
+/* Gets the dwc_hcd from a struct usb_hcd */
+static inline struct dwc_hcd *hcd_to_dwc_otg_hcd(struct usb_hcd *hcd)
+{
+ return (struct dwc_hcd *)hcd->hcd_priv;
+}
+
+/**
+ * Initializes the DWC_otg controller and its root hub and prepares it for host
+ * mode operation. Activates the root port. Returns 0 on success and a negative
+ * error code on failure.
+*/
+static int dwc_otg_hcd_start(struct usb_hcd *hcd)
+{
+ struct dwc_hcd *dwc_hcd = hcd_to_dwc_otg_hcd(hcd);
+ struct usb_bus *bus = hcd_to_bus(hcd);
+
+ hcd->state = HC_STATE_RUNNING;
+
+ /* Inform the HUB driver to resume. */
+ if (bus->root_hub)
+ usb_hcd_resume_root_hub(hcd);
+
+ hcd_reinit(dwc_hcd);
+ return 0;
+}
+
+/**
+ * Work queue function for starting the HCD when A-Cable is connected.
+ * The dwc_otg_hcd_start() must be called in a process context.
+ */
+static void hcd_start_func(struct work_struct *work)
+{
+ struct dwc_hcd *priv = container_of(work, struct dwc_hcd, start_work);
+ struct usb_hcd *usb_hcd = (struct usb_hcd *)priv->_p;
+
+ if (usb_hcd)
+ dwc_otg_hcd_start(usb_hcd);
+}
+
+/**
+ * HCD Callback function for starting the HCD when A-Cable is
+ * connected.
+ */
+static int dwc_otg_hcd_start_cb(void *_p)
+{
+ struct dwc_hcd *dwc_hcd = hcd_to_dwc_otg_hcd(_p);
+ struct core_if *core_if = dwc_hcd->core_if;
+ u32 hprt0;
+
+ if (core_if->xceiv->state == OTG_STATE_B_HOST) {
+ /*
+ * Reset the port. During a HNP mode switch the reset
+ * needs to occur within 1ms and have a duration of at
+ * least 50ms.
+ */
+ hprt0 = dwc_otg_read_hprt0(core_if);
+ hprt0 = DWC_HPRT0_PRT_RST_RW(hprt0, 1);
+ dwc_reg_write(core_if->host_if->hprt0, 0, hprt0);
+ ((struct usb_hcd *)_p)->self.is_b_host = 1;
+ } else {
+ ((struct usb_hcd *)_p)->self.is_b_host = 0;
+ }
+
+ /* Need to start the HCD in a non-interrupt context. */
+ dwc_hcd->_p = _p;
+ schedule_work(&dwc_hcd->start_work);
+ return 1;
+}
+
+/**
+ * This function disables the Host Mode interrupts.
+ */
+static void dwc_otg_disable_host_interrupts(struct core_if *core_if)
+{
+ u32 global_regs = core_if->core_global_regs;
+ u32 intr_mask = 0;
+
+ /*
+ * Disable host mode interrupts without disturbing common
+ * interrupts.
+ */
+ intr_mask |= DWC_INTMSK_STRT_OF_FRM;
+ intr_mask |= DWC_INTMSK_HST_PORT;
+ intr_mask |= DWC_INTMSK_HST_CHAN;
+ intr_mask |= DWC_INTMSK_P_TXFIFO_EMPTY;
+ intr_mask |= DWC_INTMSK_NP_TXFIFO_EMPT;
+ dwc_reg_modify(global_regs, DWC_GINTMSK, intr_mask, 0);
+}
+
+/**
+ * Halts the DWC_otg host mode operations in a clean manner. USB transfers are
+ * stopped.
+ */
+static void dwc_otg_hcd_stop(struct usb_hcd *hcd)
+{
+ struct dwc_hcd *dwc_hcd = hcd_to_dwc_otg_hcd(hcd);
+ u32 hprt0 = 0;
+
+ /* Turn off all host-specific interrupts. */
+ spin_lock(&dwc_hcd->lock);
+ dwc_otg_disable_host_interrupts(dwc_hcd->core_if);
+ spin_unlock(&dwc_hcd->lock);
+
+ /*
+ * The root hub should be disconnected before this function is called.
+ * The disconnect will clear the QTD lists (via ..._hcd_urb_dequeue)
+ * and the QH lists (via ..._hcd_endpoint_disable).
+ */
+
+ /* Turn off the vbus power */
+ pr_info("PortPower off\n");
+ hprt0 = DWC_HPRT0_PRT_PWR_RW(hprt0, 0);
+ dwc_reg_write(dwc_hcd->core_if->host_if->hprt0, 0, hprt0);
+}
+
+/**
+ * HCD Callback function for stopping the HCD.
+ */
+static int dwc_otg_hcd_stop_cb(void *_p)
+{
+ struct usb_hcd *usb_hcd = (struct usb_hcd *)_p;
+
+ dwc_otg_hcd_stop(usb_hcd);
+ return 1;
+}
+
+static void del_timers(struct dwc_hcd *hcd)
+{
+ del_timer_sync(&hcd->conn_timer);
+}
+
+/**
+ * Processes all the URBs in a single list of QHs. Completes them with
+ * -ETIMEDOUT and frees the QTD.
+ */
+static void kill_urbs_in_qh_list(struct dwc_hcd *hcd, struct list_head *qh_list)
+{
+ struct list_head *qh_item, *q;
+
+ qh_item = qh_list->next;
+ list_for_each_safe(qh_item, q, qh_list) {
+ struct dwc_qh *qh;
+ struct list_head *qtd_item;
+ struct dwc_qtd *qtd;
+
+ qh = list_entry(qh_item, struct dwc_qh, qh_list_entry);
+ qtd_item = qh->qtd_list.next;
+ qtd = list_entry(qtd_item, struct dwc_qtd, qtd_list_entry);
+ if (qtd->urb != NULL) {
+ spin_lock(&hcd->lock);
+ dwc_otg_hcd_complete_urb(hcd, qtd->urb, -ETIMEDOUT);
+ dwc_otg_hcd_qtd_remove_and_free(qtd);
+ spin_unlock(&hcd->lock);
+ }
+ }
+}
+
+/**
+ * Responds with an error status of ETIMEDOUT to all URBs in the non-periodic
+ * and periodic schedules. The QTD associated with each URB is removed from
+ * the schedule and freed. This function may be called when a disconnect is
+ * detected or when the HCD is being stopped.
+ */
+static void kill_all_urbs(struct dwc_hcd *hcd)
+{
+ kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_deferred);
+ kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_inactive);
+ kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_active);
+ kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_inactive);
+ kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_ready);
+ kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_assigned);
+ kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_queued);
+}
+
+/**
+ * HCD Callback function for disconnect of the HCD.
+ */
+static int dwc_otg_hcd_disconnect_cb(void *_p)
+{
+ u32 intr;
+ struct dwc_hcd *hcd = hcd_to_dwc_otg_hcd(_p);
+ struct core_if *core_if = hcd->core_if;
+
+ /* Set status flags for the hub driver. */
+ hcd->flags.b.port_connect_status_change = 1;
+ hcd->flags.b.port_connect_status = 0;
+
+ /*
+ * Shutdown any transfers in process by clearing the Tx FIFO Empty
+ * interrupt mask and status bits and disabling subsequent host
+ * channel interrupts.
+ */
+ intr = 0;
+ intr |= DWC_INTMSK_NP_TXFIFO_EMPT;
+ intr |= DWC_INTMSK_P_TXFIFO_EMPTY;
+ intr |= DWC_INTMSK_HST_CHAN;
+ spin_lock(&hcd->lock);
+ dwc_reg_modify(gintmsk_reg(hcd), 0, intr, 0);
+ dwc_reg_modify(gintsts_reg(hcd), 0, intr, 0);
+ spin_unlock(&hcd->lock);
+
+ del_timers(hcd);
+
+ /*
+ * Turn off the vbus power only if the core has transitioned to device
+ * mode. If still in host mode, need to keep power on to detect a
+ * reconnection.
+ */
+ if (dwc_otg_is_device_mode(core_if)) {
+ if (core_if->xceiv->state != OTG_STATE_A_SUSPEND) {
+ u32 hprt0 = 0;
+
+ pr_info("Disconnect: PortPower off\n");
+ hprt0 = DWC_HPRT0_PRT_PWR_RW(hprt0, 0);
+ dwc_reg_write(core_if->host_if->hprt0, 0, hprt0);
+ }
+ dwc_otg_disable_host_interrupts(core_if);
+ }
+
+ /* Respond with an error status to all URBs in the schedule. */
+ kill_all_urbs(hcd);
+ if (dwc_otg_is_host_mode(core_if)) {
+ /* Clean up any host channels that were in use. */
+ int num_channels;
+ u32 i;
+ struct dwc_hc *channel;
+ ulong regs;
+ u32 hcchar;
+
+ num_channels = core_if->core_params->host_channels;
+ if (!core_if->dma_enable) {
+ /* Flush out any channel requests in slave mode. */
+ for (i = 0; i < num_channels; i++) {
+ channel = hcd->hc_ptr_array[i];
+ if (list_empty(&channel->hc_list_entry)) {
+ regs =
+ core_if->host_if->hc_regs[i];
+ hcchar = dwc_reg_read(regs, DWC_HCCHAR);
+
+ if (DWC_HCCHAR_ENA_RD(hcchar)) {
+ hcchar =
+ DWC_HCCHAR_ENA_RW(hcchar,
+ 0);
+ hcchar =
+ DWC_HCCHAR_DIS_RW(hcchar,
+ 1);
+ hcchar =
+ DWC_HCCHAR_EPDIR_RW(hcchar,
+ 0);
+ dwc_reg_write(regs, DWC_HCCHAR,
+ hcchar);
+ }
+ }
+ }
+ }
+
+ for (i = 0; i < num_channels; i++) {
+ channel = hcd->hc_ptr_array[i];
+ if (list_empty(&channel->hc_list_entry)) {
+ regs = core_if->host_if->hc_regs[i];
+ hcchar = dwc_reg_read(regs, DWC_HCCHAR);
+
+ if (DWC_HCCHAR_ENA_RD(hcchar)) {
+ /* Halt the channel. */
+ hcchar = DWC_HCCHAR_DIS_RW(hcchar, 1);
+ dwc_reg_write(regs, DWC_HCCHAR, hcchar);
+ }
+ dwc_otg_hc_cleanup(core_if, channel);
+ list_add_tail(&channel->hc_list_entry,
+ &hcd->free_hc_list);
+ }
+ }
+ }
+
+ /*
+ * A disconnect will end the session so the B-Device is no
+ * longer a B-host.
+ */
+ ((struct usb_hcd *)_p)->self.is_b_host = 0;
+ return 1;
+}
+
+/**
+ * Connection timeout function. An OTG host is required to display a
+ * message if the device does not connect within 10 seconds.
+ */
+static void dwc_otg_hcd_connect_timeout(unsigned long _ptr)
+{
+ pr_info("Connect Timeout\n");
+ pr_err("Device Not Connected/Responding\n");
+}
+
+/**
+ * Start the connection timer. An OTG host is required to display a
+ * message if the device does not connect within 10 seconds. The
+ * timer is deleted if a port connect interrupt occurs before the
+ * timer expires.
+ */
+static void dwc_otg_hcd_start_connect_timer(struct dwc_hcd *hcd)
+{
+ init_timer(&hcd->conn_timer);
+ hcd->conn_timer.function = dwc_otg_hcd_connect_timeout;
+ hcd->conn_timer.data = (unsigned long)0;
+ hcd->conn_timer.expires = jiffies + (HZ * 10);
+ add_timer(&hcd->conn_timer);
+}
+
+/**
+ * HCD Callback function for disconnect of the HCD.
+ */
+static int dwc_otg_hcd_session_start_cb(void *_p)
+{
+ struct dwc_hcd *hcd = hcd_to_dwc_otg_hcd(_p);
+
+ dwc_otg_hcd_start_connect_timer(hcd);
+ return 1;
+}
+
+/* HCD Callback structure for handling mode switching. */
+static struct cil_callbacks hcd_cil_callbacks = {
+ .start = dwc_otg_hcd_start_cb,
+ .stop = dwc_otg_hcd_stop_cb,
+ .disconnect = dwc_otg_hcd_disconnect_cb,
+ .session_start = dwc_otg_hcd_session_start_cb,
+ .p = NULL,
+};
+
+/*
+ * Reset Workqueue implementation
+ */
+static void port_reset_wqfunc(struct work_struct *work)
+{
+ struct dwc_hcd *hcd = container_of(work, struct dwc_hcd,
+ usb_port_reset);
+ struct core_if *core_if = hcd->core_if;
+ u32 hprt0 = 0;
+ unsigned long flags;
+
+ pr_info("%s\n", __func__);
+ spin_lock_irqsave(&hcd->lock, flags);
+ hprt0 = dwc_otg_read_hprt0(core_if);
+ hprt0 = DWC_HPRT0_PRT_RST_RW(hprt0, 1);
+ dwc_reg_write(core_if->host_if->hprt0, 0, hprt0);
+ spin_unlock_irqrestore(&hcd->lock, flags);
+ msleep(60);
+ spin_lock_irqsave(&hcd->lock, flags);
+ hprt0 = DWC_HPRT0_PRT_RST_RW(hprt0, 0);
+ dwc_reg_write(core_if->host_if->hprt0, 0, hprt0);
+ hcd->flags.b.port_reset_change = 1;
+ spin_unlock_irqrestore(&hcd->lock, flags);
+}
+
+/*
+ * Wakeup Workqueue implementation
+ */
+static void port_wakeup_wqfunc(struct work_struct *work)
+{
+ struct core_if *core_if = container_of(to_delayed_work(work),
+ struct core_if, usb_port_wakeup);
+ u32 hprt0;
+
+ pr_info("%s\n", __func__);
+ /* Now wait for 70 ms. */
+ hprt0 = dwc_otg_read_hprt0(core_if);
+ msleep(70);
+ hprt0 = DWC_HPRT0_PRT_RES_RW(hprt0, 0);
+ dwc_reg_write(core_if->host_if->hprt0, 0, hprt0);
+}
+
+/**
+ * Starts processing a USB transfer request specified by a USB Request Block
+ * (URB). mem_flags indicates the type of memory allocation to use while
+ * processing this URB.
+ */
+static int dwc_otg_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
+ gfp_t _mem_flags)
+{
+ int retval;
+ unsigned long flags;
+ struct dwc_hcd *dwc_hcd = hcd_to_dwc_otg_hcd(hcd);
+ struct dwc_qtd *qtd;
+
+ if (!dwc_hcd->flags.b.port_connect_status) {
+ /* No longer connected. */
+ retval = -ENODEV;
+ goto err_enq;
+ }
+
+ qtd = dwc_otg_hcd_qtd_create(urb, _mem_flags);
+ if (!qtd) {
+ pr_err("DWC OTG HCD URB Enqueue failed creating " "QTD\n");
+ retval = -ENOMEM;
+ goto err_enq;
+ }
+
+ spin_lock_irqsave(&dwc_hcd->lock, flags);
+ retval = usb_hcd_link_urb_to_ep(hcd, urb);
+ if (unlikely(retval))
+ goto fail;
+
+ retval = dwc_otg_hcd_qtd_add(qtd, dwc_hcd);
+ if (retval < 0) {
+ pr_err("DWC OTG HCD URB Enqueue failed adding QTD. "
+ "Error status %d\n", retval);
+ usb_hcd_unlink_urb_from_ep(hcd, urb);
+ goto fail;
+ }
+
+fail:
+ if (retval)
+ dwc_otg_hcd_qtd_free(qtd);
+
+ spin_unlock_irqrestore(&dwc_hcd->lock, flags);
+err_enq:
+
+ return retval;
+}
+
+/**
+ * Attempts to halt a host channel. This function should only be called in
+ * Slave mode or to abort a transfer in either Slave mode or DMA mode. Under
+ * normal circumstances in DMA mode, the controller halts the channel when the
+ * transfer is complete or a condition occurs that requires application
+ * intervention.
+ *
+ * In slave mode, checks for a free request queue entry, then sets the Channel
+ * Enable and Channel Disable bits of the Host Channel Characteristics
+ * register of the specified channel to intiate the halt. If there is no free
+ * request queue entry, sets only the Channel Disable bit of the HCCHARn
+ * register to flush requests for this channel. In the latter case, sets a
+ * flag to indicate that the host channel needs to be halted when a request
+ * queue slot is open.
+ *
+ * In DMA mode, always sets the Channel Enable and Channel Disable bits of the
+ * HCCHARn register. The controller ensures there is space in the request
+ * queue before submitting the halt request.
+ *
+ * Some time may elapse before the core flushes any posted requests for this
+ * host channel and halts. The Channel Halted interrupt handler completes the
+ * deactivation of the host channel.
+ */
+void dwc_otg_hc_halt(struct core_if *core_if, struct dwc_hc *hc,
+ enum dwc_halt_status hlt_sts)
+{
+ u32 nptxsts;
+ u32 hptxsts = 0;
+ u32 hcchar;
+ ulong hc_regs;
+ ulong global_regs = core_if->core_global_regs;
+ ulong host_global_regs;
+
+ hc_regs = core_if->host_if->hc_regs[hc->hc_num];
+ host_global_regs = core_if->host_if->host_global_regs;
+
+ WARN_ON(hlt_sts == DWC_OTG_HC_XFER_NO_HALT_STATUS);
+
+ if (hlt_sts == DWC_OTG_HC_XFER_URB_DEQUEUE ||
+ hlt_sts == DWC_OTG_HC_XFER_AHB_ERR) {
+ /*
+ * Disable all channel interrupts except Ch Halted. The QTD
+ * and QH state associated with this transfer has been cleared
+ * (in the case of URB_DEQUEUE), so the channel needs to be
+ * shut down carefully to prevent crashes.
+ */
+ u32 hcintmsk;
+ hcintmsk = 0;
+ hcintmsk = DWC_HCINTMSK_CHAN_HALTED_RW(hcintmsk, 1);
+ dwc_reg_write(hc_regs, DWC_HCINTMSK, hcintmsk);
+
+ /*
+ * Make sure no other interrupts besides halt are currently
+ * pending. Handling another interrupt could cause a crash due
+ * to the QTD and QH state.
+ */
+ dwc_reg_write(hc_regs, DWC_HCINT, ~hcintmsk);
+
+ /*
+ * Make sure the halt status is set to URB_DEQUEUE or AHB_ERR
+ * even if the channel was already halted for some other reason.
+ */
+ hc->halt_status = hlt_sts;
+
+ /*
+ * If the channel is not enabled, the channel is either already
+ * halted or it hasn't started yet. In DMA mode, the transfer
+ * may halt if it finishes normally or a condition occurs that
+ * requires driver intervention. Don't want to halt the channel
+ * again. In either Slave or DMA mode, it's possible that the
+ * transfer has been assigned to a channel, but not started yet
+ * when an URB is dequeued. Don't want to halt a channel that
+ * hasn't started yet.
+ */
+ hcchar = dwc_reg_read(hc_regs, DWC_HCCHAR);
+ if (!DWC_HCCHAR_ENA_RD(hcchar))
+ return;
+ }
+
+ if (hc->halt_pending)
+ /*
+ * A halt has already been issued for this channel. This might
+ * happen when a transfer is aborted by a higher level in
+ * the stack.
+ */
+ return;
+
+ hcchar = dwc_reg_read(hc_regs, DWC_HCCHAR);
+ hcchar = DWC_HCCHAR_ENA_RW(hcchar, 1);
+ hcchar = DWC_HCCHAR_DIS_RW(hcchar, 1);
+ if (!core_if->dma_enable) {
+ /* Check for space in the request queue to issue the halt. */
+ if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL ||
+ hc->ep_type == DWC_OTG_EP_TYPE_BULK) {
+ nptxsts = dwc_reg_read(global_regs, DWC_GNPTXSTS);
+
+ if (!DWC_GNPTXSTS_NPTXQSPCAVAIL_RD(nptxsts))
+ hcchar = DWC_HCCHAR_ENA_RW(hcchar, 0);
+ } else {
+ hptxsts =
+ dwc_reg_read(host_global_regs, DWC_HPTXSTS);
+
+ if (!DWC_HPTXSTS_PTXSPC_AVAIL_RD(hptxsts) ||
+ core_if->queuing_high_bandwidth)
+ hcchar = DWC_HCCHAR_ENA_RW(hcchar, 0);
+ }
+ }
+ dwc_reg_write(hc_regs, DWC_HCCHAR, hcchar);
+
+ hc->halt_status = hlt_sts;
+ if (DWC_HCCHAR_ENA_RD(hcchar)) {
+ hc->halt_pending = 1;
+ hc->halt_on_queue = 0;
+ } else {
+ hc->halt_on_queue = 1;
+ }
+}
+
+/**
+ * Aborts/cancels a USB transfer request. Always returns 0 to indicate
+ * success.
+ */
+static int dwc_otg_hcd_urb_dequeue(struct usb_hcd *hcd, struct urb *urb,
+ int status)
+{
+ unsigned long flags;
+ struct dwc_hcd *dwc_hcd;
+ struct dwc_qtd *urb_qtd;
+ struct dwc_qh *qh;
+ int retval;
+
+ urb_qtd = (struct dwc_qtd *)urb->hcpriv;
+ if (!urb_qtd)
+ return -EINVAL;
+ qh = (struct dwc_qh *)urb_qtd->qtd_qh_ptr;
+ if (!qh)
+ return -EINVAL;
+
+ dwc_hcd = hcd_to_dwc_otg_hcd(hcd);
+ spin_lock_irqsave(&dwc_hcd->lock, flags);
+
+ retval = usb_hcd_check_unlink_urb(hcd, urb, status);
+ if (retval) {
+ spin_unlock_irqrestore(&dwc_hcd->lock, flags);
+ return retval;
+ }
+
+ if (urb_qtd == qh->qtd_in_process) {
+ /* The QTD is in process (it has been assigned to a channel). */
+ if (dwc_hcd->flags.b.port_connect_status) {
+ /*
+ * If still connected (i.e. in host mode), halt the
+ * channel so it can be used for other transfers. If
+ * no longer connected, the host registers can't be
+ * written to halt the channel since the core is in
+ * device mode.
+ */
+ dwc_otg_hc_halt(dwc_hcd->core_if, qh->channel,
+ DWC_OTG_HC_XFER_URB_DEQUEUE);
+ }
+ }
+
+ /*
+ * Free the QTD and clean up the associated QH. Leave the QH in the
+ * schedule if it has any remaining QTDs.
+ */
+ dwc_otg_hcd_qtd_remove_and_free(urb_qtd);
+ if (qh && urb_qtd == qh->qtd_in_process) {
+ dwc_otg_hcd_qh_deactivate(dwc_hcd, qh, 0);
+ qh->channel = NULL;
+ qh->qtd_in_process = NULL;
+ } else if (qh && list_empty(&qh->qtd_list)) {
+ dwc_otg_hcd_qh_remove(dwc_hcd, qh);
+ }
+
+ urb->hcpriv = NULL;
+ usb_hcd_unlink_urb_from_ep(hcd, urb);
+ spin_unlock_irqrestore(&dwc_hcd->lock, flags);
+
+ /* Higher layer software sets URB status. */
+ usb_hcd_giveback_urb(hcd, urb, status);
+
+ return 0;
+}
+
+/* Remove and free a QH */
+static inline void dwc_otg_hcd_qh_remove_and_free(struct dwc_hcd *hcd,
+ struct dwc_qh *qh)
+{
+ dwc_otg_hcd_qh_remove(hcd, qh);
+ dwc_otg_hcd_qh_free(qh);
+}
+
+static void qh_list_free(struct dwc_hcd *hcd, struct list_head *_qh_list)
+{
+ struct list_head *item, *tmp;
+ struct dwc_qh *qh;
+
+ /* If the list hasn't been initialized yet, return. */
+ if (_qh_list->next == NULL)
+ return;
+
+ /* Ensure there are no QTDs or URBs left. */
+ kill_urbs_in_qh_list(hcd, _qh_list);
+
+ list_for_each_safe(item, tmp, _qh_list) {
+ qh = list_entry(item, struct dwc_qh, qh_list_entry);
+ dwc_otg_hcd_qh_remove_and_free(hcd, qh);
+ }
+}
+
+/**
+ * Frees resources in the DWC_otg controller related to a given endpoint. Also
+ * clears state in the HCD related to the endpoint. Any URBs for the endpoint
+ * must already be dequeued.
+ */
+static void dwc_otg_hcd_endpoint_disable(struct usb_hcd *hcd,
+ struct usb_host_endpoint *ep)
+{
+ struct dwc_qh *qh;
+ struct dwc_hcd *dwc_hcd = hcd_to_dwc_otg_hcd(hcd);
+ unsigned long flags;
+
+ spin_lock_irqsave(&dwc_hcd->lock, flags);
+ qh = (struct dwc_qh *)ep->hcpriv;
+ if (qh) {
+ dwc_otg_hcd_qh_remove_and_free(dwc_hcd, qh);
+ ep->hcpriv = NULL;
+ }
+ spin_unlock_irqrestore(&dwc_hcd->lock, flags);
+}
+
+/**
+ * Creates Status Change bitmap for the root hub and root port. The bitmap is
+ * returned in buf. Bit 0 is the status change indicator for the root hub. Bit 1
+ * is the status change indicator for the single root port. Returns 1 if either
+ * change indicator is 1, otherwise returns 0.
+ */
+static int dwc_otg_hcd_hub_status_data(struct usb_hcd *_hcd, char *buf)
+{
+ struct dwc_hcd *hcd = hcd_to_dwc_otg_hcd(_hcd);
+
+ buf[0] = 0;
+ buf[0] |= (hcd->flags.b.port_connect_status_change
+ || hcd->flags.b.port_reset_change
+ || hcd->flags.b.port_enable_change
+ || hcd->flags.b.port_suspend_change
+ || hcd->flags.b.port_over_current_change) << 1;
+
+ return (buf[0] != 0);
+}
+
+/* Handles the hub class-specific ClearPortFeature request.*/
+static int do_clear_port_feature(struct dwc_hcd *hcd, u16 val)
+{
+ struct core_if *core_if = hcd->core_if;
+ u32 hprt0 = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&hcd->lock, flags);
+ switch (val) {
+ case USB_PORT_FEAT_ENABLE:
+ hprt0 = dwc_otg_read_hprt0(core_if);
+ hprt0 = DWC_HPRT0_PRT_ENA_RW(hprt0, 1);
+ dwc_reg_write(core_if->host_if->hprt0, 0, hprt0);
+ break;
+ case USB_PORT_FEAT_SUSPEND:
+ hprt0 = dwc_otg_read_hprt0(core_if);
+ hprt0 = DWC_HPRT0_PRT_RES_RW(hprt0, 1);
+ dwc_reg_write(core_if->host_if->hprt0, 0, hprt0);
+
+ /* Clear Resume bit */
+ spin_unlock_irqrestore(&hcd->lock, flags);
+ msleep(100);
+ spin_lock_irqsave(&hcd->lock, flags);
+ hprt0 = DWC_HPRT0_PRT_RES_RW(hprt0, 0);
+ dwc_reg_write(core_if->host_if->hprt0, 0, hprt0);
+ break;
+ case USB_PORT_FEAT_POWER:
+ hprt0 = dwc_otg_read_hprt0(core_if);
+ hprt0 = DWC_HPRT0_PRT_PWR_RW(hprt0, 0);
+ dwc_reg_write(core_if->host_if->hprt0, 0, hprt0);
+ break;
+ case USB_PORT_FEAT_INDICATOR:
+ /* Port inidicator not supported */
+ break;
+ case USB_PORT_FEAT_C_CONNECTION:
+ /* Clears drivers internal connect status change flag */
+ hcd->flags.b.port_connect_status_change = 0;
+ break;
+ case USB_PORT_FEAT_C_RESET:
+ /* Clears driver's internal Port Reset Change flag */
+ hcd->flags.b.port_reset_change = 0;
+ break;
+ case USB_PORT_FEAT_C_ENABLE:
+ /* Clears driver's internal Port Enable/Disable Change flag */
+ hcd->flags.b.port_enable_change = 0;
+ break;
+ case USB_PORT_FEAT_C_SUSPEND:
+ /*
+ * Clears the driver's internal Port Suspend
+ * Change flag, which is set when resume signaling on
+ * the host port is complete
+ */
+ hcd->flags.b.port_suspend_change = 0;
+ break;
+ case USB_PORT_FEAT_C_OVER_CURRENT:
+ hcd->flags.b.port_over_current_change = 0;
+ break;
+ default:
+ pr_err("DWC OTG HCD - ClearPortFeature request %xh "
+ "unknown or unsupported\n", val);
+ spin_unlock_irqrestore(&hcd->lock, flags);
+ return -EINVAL;
+ }
+ spin_unlock_irqrestore(&hcd->lock, flags);
+ return 0;
+}
+
+/* Handles the hub class-specific SetPortFeature request.*/
+static int do_set_port_feature(struct usb_hcd *hcd, u16 val, u16 index)
+{
+ struct core_if *core_if = hcd_to_dwc_otg_hcd(hcd)->core_if;
+ u32 hprt0 = 0;
+ struct dwc_hcd *dwc_hcd = hcd_to_dwc_otg_hcd(hcd);
+ unsigned long flags;
+ u32 pcgcctl = 0;
+
+ spin_lock_irqsave(&dwc_hcd->lock, flags);
+
+ switch (val) {
+ case USB_PORT_FEAT_SUSPEND:
+ if (hcd->self.otg_port == index && hcd->self.b_hnp_enable) {
+ u32 gotgctl = 0;
+ gotgctl |= DWC_GCTL_HOST_HNP_ENA;
+ dwc_reg_modify(core_if->core_global_regs,
+ DWC_GOTGCTL, 0, gotgctl);
+ core_if->xceiv->state = OTG_STATE_A_SUSPEND;
+ }
+
+ hprt0 = dwc_otg_read_hprt0(core_if);
+ hprt0 = DWC_HPRT0_PRT_SUS_RW(hprt0, 1);
+ dwc_reg_write(core_if->host_if->hprt0, 0, hprt0);
+
+ /* Suspend the Phy Clock */
+ pcgcctl = DWC_PCGCCTL_STOP_CLK_SET(pcgcctl);
+ dwc_reg_write(core_if->pcgcctl, 0, pcgcctl);
+
+ /* For HNP the bus must be suspended for at least 200ms. */
+ if (hcd->self.b_hnp_enable) {
+ spin_unlock_irqrestore(&dwc_hcd->lock, flags);
+ msleep(200);
+ spin_lock_irqsave(&dwc_hcd->lock, flags);
+ }
+ break;
+ case USB_PORT_FEAT_POWER:
+ hprt0 = dwc_otg_read_hprt0(core_if);
+ hprt0 = DWC_HPRT0_PRT_PWR_RW(hprt0, 1);
+ dwc_reg_write(core_if->host_if->hprt0, 0, hprt0);
+ break;
+ case USB_PORT_FEAT_RESET:
+ hprt0 = dwc_otg_read_hprt0(core_if);
+
+ /*
+ * When B-Host the Port reset bit is set in the Start HCD
+ * Callback function, so that the reset is started within 1ms
+ * of the HNP success interrupt.
+ */
+ if (!hcd->self.is_b_host) {
+ hprt0 = DWC_HPRT0_PRT_RST_RW(hprt0, 1);
+ dwc_reg_write(core_if->host_if->hprt0, 0, hprt0);
+ }
+
+ /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */
+ spin_unlock_irqrestore(&dwc_hcd->lock, flags);
+ msleep(60);
+ spin_lock_irqsave(&dwc_hcd->lock, flags);
+ hprt0 = DWC_HPRT0_PRT_RST_RW(hprt0, 0);
+ dwc_reg_write(core_if->host_if->hprt0, 0, hprt0);
+ break;
+ case USB_PORT_FEAT_INDICATOR:
+ /* Not supported */
+ break;
+ default:
+ pr_err("DWC OTG HCD - "
+ "SetPortFeature request %xh "
+ "unknown or unsupported\n", val);
+ spin_unlock_irqrestore(&dwc_hcd->lock, flags);
+ return -EINVAL;
+ }
+ spin_unlock_irqrestore(&dwc_hcd->lock, flags);
+ return 0;
+}
+
+/* Handles hub class-specific requests.*/
+static int dwc_otg_hcd_hub_control(struct usb_hcd *hcd, u16 req_type, u16 val,
+ u16 index, char *buf, u16 len)
+{
+ int retval = 0;
+ struct dwc_hcd *dwc_hcd = hcd_to_dwc_otg_hcd(hcd);
+ struct core_if *core_if = hcd_to_dwc_otg_hcd(hcd)->core_if;
+ struct usb_hub_descriptor *desc;
+ u32 hprt0 = 0;
+ u32 port_status;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dwc_hcd->lock, flags);
+ switch (req_type) {
+ case ClearHubFeature:
+ switch (val) {
+ case C_HUB_LOCAL_POWER:
+ case C_HUB_OVER_CURRENT:
+ /* Nothing required here */
+ break;
+ default:
+ retval = -EINVAL;
+ pr_err("DWC OTG HCD - ClearHubFeature request"
+ " %xh unknown\n", val);
+ }
+ break;
+ case ClearPortFeature:
+ if (!index || index > 1)
+ goto error;
+ spin_unlock_irqrestore(&dwc_hcd->lock, flags);
+ retval = do_clear_port_feature(dwc_hcd, val);
+ spin_lock_irqsave(&dwc_hcd->lock, flags);
+ break;
+ case GetHubDescriptor:
+ desc = (struct usb_hub_descriptor *)buf;
+ desc->bDescLength = 9;
+ desc->bDescriptorType = 0x29;
+ desc->bNbrPorts = 1;
+ desc->wHubCharacteristics = 0x08;
+ desc->bPwrOn2PwrGood = 1;
+ desc->bHubContrCurrent = 0;
+ break;
+ case GetHubStatus:
+ memset(buf, 0, 4);
+ break;
+ case GetPortStatus:
+ if (!index || index > 1)
+ goto error;
+
+ port_status = 0;
+ if (dwc_hcd->flags.b.port_connect_status_change)
+ port_status |= (1 << USB_PORT_FEAT_C_CONNECTION);
+ if (dwc_hcd->flags.b.port_enable_change)
+ port_status |= (1 << USB_PORT_FEAT_C_ENABLE);
+ if (dwc_hcd->flags.b.port_suspend_change)
+ port_status |= (1 << USB_PORT_FEAT_C_SUSPEND);
+ if (dwc_hcd->flags.b.port_reset_change)
+ port_status |= (1 << USB_PORT_FEAT_C_RESET);
+ if (dwc_hcd->flags.b.port_over_current_change) {
+ pr_err("Device Not Supported\n");
+ port_status |= (1 << USB_PORT_FEAT_C_OVER_CURRENT);
+ }
+ if (!dwc_hcd->flags.b.port_connect_status) {
+ /*
+ * The port is disconnected, which means the core is
+ * either in device mode or it soon will be. Just
+ * return 0's for the remainder of the port status
+ * since the port register can't be read if the core
+ * is in device mode.
+ */
+ *((__le32 *) buf) = cpu_to_le32(port_status);
+ break;
+ }
+
+ hprt0 = dwc_reg_read(core_if->host_if->hprt0, 0);
+
+ if (DWC_HPRT0_PRT_STS_RD(hprt0))
+ port_status |= USB_PORT_STAT_CONNECTION;
+ if (DWC_HPRT0_PRT_ENA_RD(hprt0))
+ port_status |= USB_PORT_STAT_ENABLE;
+ if (DWC_HPRT0_PRT_SUS_RD(hprt0))
+ port_status |= USB_PORT_STAT_SUSPEND;
+ if (DWC_HPRT0_PRT_OVRCURR_ACT_RD(hprt0))
+ port_status |= USB_PORT_STAT_OVERCURRENT;
+ if (DWC_HPRT0_PRT_RST_RD(hprt0))
+ port_status |= USB_PORT_STAT_RESET;
+ if (DWC_HPRT0_PRT_PWR_RD(hprt0))
+ port_status |= USB_PORT_STAT_POWER;
+
+ if (DWC_HPRT0_PRT_SPD_RD(hprt0) == DWC_HPRT0_PRTSPD_HIGH_SPEED)
+ port_status |= USB_PORT_STAT_HIGH_SPEED;
+ else if (DWC_HPRT0_PRT_SPD_RD(hprt0) ==
+ DWC_HPRT0_PRTSPD_LOW_SPEED)
+ port_status |= USB_PORT_STAT_LOW_SPEED;
+
+ if (DWC_HPRT0_PRT_TST_CTL_RD(hprt0))
+ port_status |= (1 << USB_PORT_FEAT_TEST);
+
+ /* USB_PORT_FEAT_INDICATOR unsupported always 0 */
+ *((__le32 *) buf) = cpu_to_le32(port_status);
+ break;
+ case SetHubFeature:
+ /* No HUB features supported */
+ break;
+ case SetPortFeature:
+ if (val != USB_PORT_FEAT_TEST && (!index || index > 1))
+ goto error;
+
+ if (!dwc_hcd->flags.b.port_connect_status) {
+ /*
+ * The port is disconnected, which means the core is
+ * either in device mode or it soon will be. Just
+ * return without doing anything since the port
+ * register can't be written if the core is in device
+ * mode.
+ */
+ break;
+ }
+ spin_unlock_irqrestore(&dwc_hcd->lock, flags);
+ retval = do_set_port_feature(hcd, val, index);
+ spin_lock_irqsave(&dwc_hcd->lock, flags);
+ break;
+ default:
+error:
+ retval = -EINVAL;
+ pr_warning("DWC OTG HCD - Unknown hub control request"
+ " type or invalid req_type: %xh index: %xh "
+ "val: %xh\n", req_type, index, val);
+ break;
+ }
+ spin_unlock_irqrestore(&dwc_hcd->lock, flags);
+ return retval;
+}
+
+/**
+ * Handles host mode interrupts for the DWC_otg controller. Returns IRQ_NONE if
+ * there was no interrupt to handle. Returns IRQ_HANDLED if there was a valid
+ * interrupt.
+ *
+ * This function is called by the USB core when an interrupt occurs
+ */
+static irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd)
+{
+ struct dwc_hcd *dwc_hcd = hcd_to_dwc_otg_hcd(hcd);
+
+ return IRQ_RETVAL(dwc_otg_hcd_handle_intr(dwc_hcd));
+}
+
+static const struct hc_driver dwc_otg_hc_driver = {
+ .description = dwc_otg_hcd_name,
+ .product_desc = "DWC OTG Controller",
+ .hcd_priv_size = sizeof(struct dwc_hcd),
+ .irq = dwc_otg_hcd_irq,
+ .flags = HCD_MEMORY | HCD_USB2,
+ .start = dwc_otg_hcd_start,
+ .stop = dwc_otg_hcd_stop,
+ .urb_enqueue = dwc_otg_hcd_urb_enqueue,
+ .urb_dequeue = dwc_otg_hcd_urb_dequeue,
+ .endpoint_disable = dwc_otg_hcd_endpoint_disable,
+ .get_frame_number = dwc_otg_hcd_get_frame_number,
+ .hub_status_data = dwc_otg_hcd_hub_status_data,
+ .hub_control = dwc_otg_hcd_hub_control,
+};
+
+/**
+ * Frees secondary storage associated with the dwc_hcd structure contained
+ * in the struct usb_hcd field.
+ */
+static void dwc_otg_hcd_free(struct usb_hcd *hcd)
+{
+ struct dwc_hcd *dwc_hcd = hcd_to_dwc_otg_hcd(hcd);
+ u32 i;
+
+ del_timers(dwc_hcd);
+
+ /* Free memory for QH/QTD lists */
+ qh_list_free(dwc_hcd, &dwc_hcd->non_periodic_sched_inactive);
+ qh_list_free(dwc_hcd, &dwc_hcd->non_periodic_sched_deferred);
+ qh_list_free(dwc_hcd, &dwc_hcd->non_periodic_sched_active);
+ qh_list_free(dwc_hcd, &dwc_hcd->periodic_sched_inactive);
+ qh_list_free(dwc_hcd, &dwc_hcd->periodic_sched_ready);
+ qh_list_free(dwc_hcd, &dwc_hcd->periodic_sched_assigned);
+ qh_list_free(dwc_hcd, &dwc_hcd->periodic_sched_queued);
+
+ /* Free memory for the host channels. */
+ for (i = 0; i < MAX_EPS_CHANNELS; i++) {
+ struct dwc_hc *hc = dwc_hcd->hc_ptr_array[i];
+
+ kfree(hc);
+ }
+ if (dwc_hcd->core_if->dma_enable) {
+ if (dwc_hcd->status_buf_dma)
+ dma_free_coherent(hcd->self.controller,
+ DWC_OTG_HCD_STATUS_BUF_SIZE,
+ dwc_hcd->status_buf,
+ dwc_hcd->status_buf_dma);
+ } else {
+ kfree(dwc_hcd->status_buf);
+ }
+
+}
+
+/**
+ * Initializes the HCD. This function allocates memory for and initializes the
+ * static parts of the usb_hcd and dwc_hcd structures. It also registers the
+ * USB bus with the core and calls the hc_driver->start() function. It returns
+ * a negative error on failure.
+ */
+int dwc_otg_hcd_init(struct device *_dev,
+ struct dwc_otg_device *dwc_otg_device)
+{
+ struct usb_hcd *hcd;
+ struct dwc_hcd *dwc_hcd;
+ struct dwc_otg_device *otg_dev = dev_get_drvdata(_dev);
+ int num_channels;
+ u32 i;
+ struct dwc_hc *channel;
+ int retval = 0;
+
+ /*
+ * Allocate memory for the base HCD plus the DWC OTG HCD.
+ * Initialize the base HCD.
+ */
+ hcd = usb_create_hcd(&dwc_otg_hc_driver, _dev, dwc_otg_hcd_name);
+ if (!hcd) {
+ retval = -ENOMEM;
+ goto error1;
+ }
+ dev_set_drvdata(_dev, dwc_otg_device);
+ hcd->regs = otg_dev->base;
+ hcd->rsrc_start = otg_dev->phys_addr;
+ hcd->rsrc_len = otg_dev->base_len;
+ hcd->self.otg_port = 1;
+
+ /* Initialize the DWC OTG HCD. */
+ dwc_hcd = hcd_to_dwc_otg_hcd(hcd);
+ dwc_hcd->core_if = otg_dev->core_if;
+ spin_lock_init(&dwc_hcd->lock);
+ otg_dev->hcd = dwc_hcd;
+
+ /* Register the HCD CIL Callbacks */
+ dwc_otg_cil_register_hcd_callbacks(otg_dev->core_if, &hcd_cil_callbacks,
+ hcd);
+
+ /* Initialize the non-periodic schedule. */
+ INIT_LIST_HEAD(&dwc_hcd->non_periodic_sched_inactive);
+ INIT_LIST_HEAD(&dwc_hcd->non_periodic_sched_active);
+ INIT_LIST_HEAD(&dwc_hcd->non_periodic_sched_deferred);
+
+ /* Initialize the periodic schedule. */
+ INIT_LIST_HEAD(&dwc_hcd->periodic_sched_inactive);
+ INIT_LIST_HEAD(&dwc_hcd->periodic_sched_ready);
+ INIT_LIST_HEAD(&dwc_hcd->periodic_sched_assigned);
+ INIT_LIST_HEAD(&dwc_hcd->periodic_sched_queued);
+
+ /*
+ * Create a host channel descriptor for each host channel implemented
+ * in the controller. Initialize the channel descriptor array.
+ */
+ INIT_LIST_HEAD(&dwc_hcd->free_hc_list);
+ num_channels = dwc_hcd->core_if->core_params->host_channels;
+
+ for (i = 0; i < num_channels; i++) {
+ channel = kzalloc(sizeof(struct dwc_hc), GFP_KERNEL);
+ if (!channel) {
+ retval = -ENOMEM;
+ pr_err("%s: host channel allocation failed\n",
+ __func__);
+ goto error2;
+ }
+
+ channel->hc_num = i;
+ dwc_hcd->hc_ptr_array[i] = channel;
+ }
+
+ /* Initialize the Connection timeout timer. */
+ init_timer(&dwc_hcd->conn_timer);
+
+ /* Initialize workqueue */
+ INIT_WORK(&dwc_hcd->usb_port_reset, port_reset_wqfunc);
+ INIT_WORK(&dwc_hcd->start_work, hcd_start_func);
+ INIT_WORK(&dwc_hcd->core_if->usb_port_otg, NULL);
+ INIT_DELAYED_WORK(&dwc_hcd->core_if->usb_port_wakeup,
+ port_wakeup_wqfunc);
+
+ /* Set device flags indicating whether the HCD supports DMA. */
+ if (otg_dev->core_if->dma_enable) {
+ static u64 dummy_mask = DMA_BIT_MASK(32);
+
+ pr_info("Using DMA mode\n");
+ _dev->dma_mask = (void *)&dummy_mask;
+ _dev->coherent_dma_mask = ~0;
+ } else {
+ pr_info("Using Slave mode\n");
+ _dev->dma_mask = (void *)0;
+ _dev->coherent_dma_mask = 0;
+ }
+
+ init_hcd_usecs(dwc_hcd);
+ /*
+ * Finish generic HCD initialization and start the HCD. This function
+ * allocates the DMA buffer pool, registers the USB bus, requests the
+ * IRQ line, and calls dwc_otg_hcd_start method.
+ */
+ printk("before hcd\n");msleep(100);
+ retval = usb_add_hcd(hcd, otg_dev->irq, IRQF_SHARED);
+ printk("after hcd\n");msleep(100);
+ if (retval < 0)
+ goto error2;
+ hcd->rsrc_start = otg_dev->phys_addr;
+ hcd->rsrc_len = otg_dev->base_len;
+
+ /*
+ * Allocate space for storing data on status transactions. Normally no
+ * data is sent, but this space acts as a bit bucket. This must be
+ * done after usb_add_hcd since that function allocates the DMA buffer
+ * pool.
+ */
+ if (otg_dev->core_if->dma_enable) {
+ dwc_hcd->status_buf =
+ dma_alloc_coherent(_dev, DWC_OTG_HCD_STATUS_BUF_SIZE,
+ &dwc_hcd->status_buf_dma,
+ GFP_KERNEL | GFP_DMA);
+ } else {
+ dwc_hcd->status_buf = kmalloc(DWC_OTG_HCD_STATUS_BUF_SIZE,
+ GFP_KERNEL);
+ }
+ if (!dwc_hcd->status_buf) {
+ retval = -ENOMEM;
+ pr_err("%s: status_buf allocation failed\n", __func__);
+ goto error3;
+ }
+ return 0;
+
+error3:
+ usb_remove_hcd(hcd);
+error2:
+ dwc_otg_hcd_free(hcd);
+ usb_put_hcd(hcd);
+error1:
+ return retval;
+}
+
+/**
+ * Removes the HCD.
+ * Frees memory and resources associated with the HCD and deregisters the bus.
+ */
+void __devexit dwc_otg_hcd_remove(struct device *_dev)
+{
+ struct dwc_otg_device *otg_dev = dev_get_drvdata(_dev);
+ struct dwc_hcd *dwc_hcd = otg_dev->hcd;
+ struct usb_hcd *hcd = dwc_otg_hcd_to_hcd(dwc_hcd);
+
+ /* Turn off all interrupts */
+ dwc_reg_write(gintmsk_reg(dwc_hcd), 0, 0);
+ spin_lock(&dwc_hcd->lock);
+ dwc_reg_modify(gahbcfg_reg(dwc_hcd), 0, 1, 0);
+ spin_unlock(&dwc_hcd->lock);
+
+ cancel_work_sync(&dwc_hcd->start_work);
+ cancel_work_sync(&dwc_hcd->usb_port_reset);
+ cancel_work_sync(&dwc_hcd->core_if->usb_port_otg);
+
+ usb_remove_hcd(hcd);
+ dwc_otg_hcd_free(hcd);
+ usb_put_hcd(hcd);
+}
+
+/** Returns the current frame number. */
+int dwc_otg_hcd_get_frame_number(struct usb_hcd *hcd)
+{
+ struct dwc_hcd *dwc_hcd = hcd_to_dwc_otg_hcd(hcd);
+ u32 hfnum = 0;
+
+ hfnum = dwc_reg_read(dwc_hcd->core_if->host_if->
+ host_global_regs, DWC_HFNUM);
+
+ return DWC_HFNUM_FRNUM_RD(hfnum);
+}
+
+/**
+ * Prepares a host channel for transferring packets to/from a specific
+ * endpoint. The HCCHARn register is set up with the characteristics specified
+ * in _hc. Host channel interrupts that may need to be serviced while this
+ * transfer is in progress are enabled.
+ */
+static void dwc_otg_hc_init(struct core_if *core_if, struct dwc_hc *hc)
+{
+ u32 intr_enable;
+ ulong global_regs = core_if->core_global_regs;
+ u32 hc_intr_mask = 0;
+ u32 gintmsk = 0;
+ u32 hcchar;
+ u32 hcsplt;
+ u8 hc_num = hc->hc_num;
+ struct dwc_host_if *host_if = core_if->host_if;
+ ulong hc_regs = host_if->hc_regs[hc_num];
+
+ /* Clear old interrupt conditions for this host channel. */
+ hc_intr_mask = 0x3FF;
+ dwc_reg_write(hc_regs, DWC_HCINT, hc_intr_mask);
+
+ /* Enable channel interrupts required for this transfer. */
+ hc_intr_mask = 0;
+ hc_intr_mask = DWC_HCINTMSK_CHAN_HALTED_RW(hc_intr_mask, 1);
+ if (core_if->dma_enable) {
+ hc_intr_mask = DWC_HCINTMSK_AHB_ERR_RW(hc_intr_mask, 1);
+
+ if (hc->error_state && !hc->do_split &&
+ hc->ep_type != DWC_OTG_EP_TYPE_ISOC) {
+ hc_intr_mask =
+ DWC_HCINTMSK_ACK_RESP_REC_RW(hc_intr_mask, 1);
+ if (hc->ep_is_in) {
+ hc_intr_mask =
+ DWC_HCINTMSK_DATA_TOG_ERR_RW(hc_intr_mask,
+ 1);
+ if (hc->ep_type != DWC_OTG_EP_TYPE_INTR)
+ hc_intr_mask =
+ DWC_HCINTMSK_NAK_RESP_REC_RW
+ (hc_intr_mask, 1);
+ }
+ }
+ } else {
+ switch (hc->ep_type) {
+ case DWC_OTG_EP_TYPE_CONTROL:
+ case DWC_OTG_EP_TYPE_BULK:
+ hc_intr_mask =
+ DWC_HCINTMSK_TXFER_CMPL_RW(hc_intr_mask, 1);
+ hc_intr_mask =
+ DWC_HCINTMSK_STALL_RESP_REC_RW(hc_intr_mask, 1);
+ hc_intr_mask =
+ DWC_HCINTMSK_TRANS_ERR_RW(hc_intr_mask, 1);
+ hc_intr_mask =
+ DWC_HCINTMSK_DATA_TOG_ERR_RW(hc_intr_mask, 1);
+
+ if (hc->ep_is_in) {
+ hc_intr_mask =
+ DWC_HCINTMSK_BBL_ERR_RW(hc_intr_mask, 1);
+ } else {
+ hc_intr_mask =
+ DWC_HCINTMSK_NAK_RESP_REC_RW(hc_intr_mask,
+ 1);
+ hc_intr_mask =
+ DWC_HCINTMSK_NYET_RESP_REC_RW(hc_intr_mask,
+ 1);
+ if (hc->do_ping)
+ hc_intr_mask =
+ DWC_HCINTMSK_ACK_RESP_REC_RW
+ (hc_intr_mask, 1);
+ }
+
+ if (hc->do_split) {
+ hc_intr_mask =
+ DWC_HCINTMSK_NAK_RESP_REC_RW(hc_intr_mask,
+ 1);
+ if (hc->complete_split)
+ hc_intr_mask =
+ DWC_HCINTMSK_NYET_RESP_REC_RW
+ (hc_intr_mask, 1);
+ else
+ hc_intr_mask =
+ DWC_HCINTMSK_ACK_RESP_REC_RW
+ (hc_intr_mask, 1);
+ }
+
+ if (hc->error_state)
+ hc_intr_mask =
+ DWC_HCINTMSK_ACK_RESP_REC_RW(hc_intr_mask,
+ 1);
+ break;
+ case DWC_OTG_EP_TYPE_INTR:
+ hc_intr_mask =
+ DWC_HCINTMSK_TXFER_CMPL_RW(hc_intr_mask, 1);
+ hc_intr_mask =
+ DWC_HCINTMSK_NAK_RESP_REC_RW(hc_intr_mask, 1);
+ hc_intr_mask =
+ DWC_HCINTMSK_STALL_RESP_REC_RW(hc_intr_mask, 1);
+ hc_intr_mask =
+ DWC_HCINTMSK_TRANS_ERR_RW(hc_intr_mask, 1);
+ hc_intr_mask =
+ DWC_HCINTMSK_DATA_TOG_ERR_RW(hc_intr_mask, 1);
+ hc_intr_mask =
+ DWC_HCINTMSK_FRAME_OVERN_ERR_RW(hc_intr_mask, 1);
+
+ if (hc->ep_is_in)
+ hc_intr_mask =
+ DWC_HCINTMSK_BBL_ERR_RW(hc_intr_mask, 1);
+ if (hc->error_state)
+ hc_intr_mask =
+ DWC_HCINTMSK_ACK_RESP_REC_RW(hc_intr_mask,
+ 1);
+
+ if (hc->do_split) {
+ if (hc->complete_split)
+ hc_intr_mask =
+ DWC_HCINTMSK_NYET_RESP_REC_RW
+ (hc_intr_mask, 1);
+ else
+ hc_intr_mask =
+ DWC_HCINTMSK_ACK_RESP_REC_RW
+ (hc_intr_mask, 1);
+ }
+ break;
+ case DWC_OTG_EP_TYPE_ISOC:
+ hc_intr_mask =
+ DWC_HCINTMSK_TXFER_CMPL_RW(hc_intr_mask, 1);
+ hc_intr_mask =
+ DWC_HCINTMSK_FRAME_OVERN_ERR_RW(hc_intr_mask, 1);
+ hc_intr_mask =
+ DWC_HCINTMSK_ACK_RESP_REC_RW(hc_intr_mask, 1);
+
+ if (hc->ep_is_in) {
+ hc_intr_mask =
+ DWC_HCINTMSK_TRANS_ERR_RW(hc_intr_mask, 1);
+ hc_intr_mask =
+ DWC_HCINTMSK_BBL_ERR_RW(hc_intr_mask, 1);
+ }
+ break;
+ }
+ }
+ dwc_reg_write(hc_regs, DWC_HCINTMSK, hc_intr_mask);
+
+ /* Enable the top level host channel interrupt. */
+ intr_enable = (1 << hc_num);
+ dwc_reg_modify(host_if->host_global_regs, DWC_HAINTMSK, 0,
+ intr_enable);
+
+ /* Make sure host channel interrupts are enabled. */
+ gintmsk |= DWC_INTMSK_HST_CHAN;
+ dwc_reg_modify(global_regs, DWC_GINTMSK, 0, gintmsk);
+
+ /*
+ * Program the HCCHARn register with the endpoint characteristics for
+ * the current transfer.
+ */
+ hcchar = 0;
+ hcchar = DWC_HCCHAR_DEV_ADDR_RW(hcchar, hc->dev_addr);
+ hcchar = DWC_HCCHAR_EP_NUM_RW(hcchar, hc->ep_num);
+ hcchar = DWC_HCCHAR_EPDIR_RW(hcchar, hc->ep_is_in);
+ hcchar = DWC_HCCHAR_LSP_DEV_RW(hcchar, (hc->speed ==
+ DWC_OTG_EP_SPEED_LOW));
+ hcchar = DWC_HCCHAR_EPTYPE_RW(hcchar, hc->ep_type);
+ hcchar = DWC_HCCHAR_MPS_RW(hcchar, hc->max_packet);
+ dwc_reg_write(host_if->hc_regs[hc_num], DWC_HCCHAR, hcchar);
+
+ /* Program the HCSPLIT register for SPLITs */
+ hcsplt = 0;
+ if (hc->do_split) {
+ hcsplt = DWC_HCSPLT_COMP_SPLT_RW(hcsplt, hc->complete_split);
+ hcsplt = DWC_HCSPLT_TRANS_POS_RW(hcsplt, hc->xact_pos);
+ hcsplt = DWC_HCSPLT_HUB_ADDR_RW(hcsplt, hc->hub_addr);
+ hcsplt = DWC_HCSPLT_PRT_ADDR_RW(hcsplt, hc->port_addr);
+ }
+ dwc_reg_write(host_if->hc_regs[hc_num], DWC_HCSPLT, hcsplt);
+}
+
+/**
+ * Assigns transactions from a QTD to a free host channel and initializes the
+ * host channel to perform the transactions. The host channel is removed from
+ * the free list.
+ */
+static void assign_and_init_hc(struct dwc_hcd *hcd, struct dwc_qh *qh)
+{
+ struct dwc_hc *hc;
+ struct dwc_qtd *qtd;
+ struct urb *urb;
+ struct usb_iso_packet_descriptor *frame_desc;
+
+ hc = list_entry(hcd->free_hc_list.next, struct dwc_hc, hc_list_entry);
+
+ /* Remove the host channel from the free list. */
+ list_del_init(&hc->hc_list_entry);
+ qtd = list_entry(qh->qtd_list.next, struct dwc_qtd, qtd_list_entry);
+ urb = qtd->urb;
+ qh->channel = hc;
+ qh->qtd_in_process = qtd;
+
+ /*
+ * Use usb_pipedevice to determine device address. This address is
+ * 0 before the SET_ADDRESS command and the correct address afterward.
+ */
+ hc->dev_addr = usb_pipedevice(urb->pipe);
+ hc->ep_num = usb_pipeendpoint(urb->pipe);
+
+ if (urb->dev->speed == USB_SPEED_LOW)
+ hc->speed = DWC_OTG_EP_SPEED_LOW;
+ else if (urb->dev->speed == USB_SPEED_FULL)
+ hc->speed = DWC_OTG_EP_SPEED_FULL;
+ else
+ hc->speed = DWC_OTG_EP_SPEED_HIGH;
+
+ hc->max_packet = dwc_max_packet(qh->maxp);
+ hc->xfer_started = 0;
+ hc->halt_status = DWC_OTG_HC_XFER_NO_HALT_STATUS;
+ hc->error_state = (qtd->error_count > 0);
+ hc->halt_on_queue = 0;
+ hc->halt_pending = 0;
+ hc->requests = 0;
+
+ /*
+ * The following values may be modified in the transfer type section
+ * below. The xfer_len value may be reduced when the transfer is
+ * started to accommodate the max widths of the XferSize and PktCnt
+ * fields in the HCTSIZn register.
+ */
+ hc->do_ping = qh->ping_state;
+ hc->ep_is_in = (usb_pipein(urb->pipe) != 0);
+ hc->data_pid_start = qh->data_toggle;
+ hc->multi_count = 1;
+
+ if (hcd->core_if->dma_enable)
+ hc->xfer_buff = urb->transfer_dma + (u8 *) urb->actual_length;
+ else
+ hc->xfer_buff = (u8 *) urb->transfer_buffer +
+ urb->actual_length;
+
+ hc->xfer_len = urb->transfer_buffer_length - urb->actual_length;
+ hc->xfer_count = 0;
+
+ /*
+ * Set the split attributes
+ */
+ hc->do_split = 0;
+ if (qh->do_split) {
+ hc->do_split = 1;
+ hc->xact_pos = qtd->isoc_split_pos;
+ hc->complete_split = qtd->complete_split;
+ hc->hub_addr = urb->dev->tt->hub->devnum;
+ hc->port_addr = urb->dev->ttport;
+ }
+
+ switch (usb_pipetype(urb->pipe)) {
+ case PIPE_CONTROL:
+ hc->ep_type = DWC_OTG_EP_TYPE_CONTROL;
+
+ switch (qtd->control_phase) {
+ case DWC_OTG_CONTROL_SETUP:
+ hc->do_ping = 0;
+ hc->ep_is_in = 0;
+ hc->data_pid_start = DWC_OTG_HC_PID_SETUP;
+
+ if (hcd->core_if->dma_enable)
+ hc->xfer_buff = (u8 *) (u32) urb->setup_dma;
+ else
+ hc->xfer_buff = (u8 *) urb->setup_packet;
+
+ hc->xfer_len = 8;
+ break;
+ case DWC_OTG_CONTROL_DATA:
+ hc->data_pid_start = qtd->data_toggle;
+ break;
+ case DWC_OTG_CONTROL_STATUS:
+ /*
+ * Direction is opposite of data direction or IN if no
+ * data.
+ */
+ if (urb->transfer_buffer_length == 0)
+ hc->ep_is_in = 1;
+ else
+ hc->ep_is_in = (usb_pipein(urb->pipe) !=
+ USB_DIR_IN);
+
+ if (hc->ep_is_in)
+ hc->do_ping = 0;
+
+ hc->data_pid_start = DWC_OTG_HC_PID_DATA1;
+ hc->xfer_len = 0;
+ if (hcd->core_if->dma_enable)
+ hc->xfer_buff =
+ (u8 *) (u32) hcd->status_buf_dma;
+ else
+ hc->xfer_buff = (u8 *) hcd->status_buf;
+ break;
+ }
+ break;
+ case PIPE_BULK:
+ hc->ep_type = DWC_OTG_EP_TYPE_BULK;
+ break;
+ case PIPE_INTERRUPT:
+ hc->ep_type = DWC_OTG_EP_TYPE_INTR;
+ break;
+ case PIPE_ISOCHRONOUS:
+ frame_desc = &urb->iso_frame_desc[qtd->isoc_frame_index];
+ hc->ep_type = DWC_OTG_EP_TYPE_ISOC;
+
+ if (hcd->core_if->dma_enable)
+ hc->xfer_buff = (u8 *) (u32) urb->transfer_dma;
+ else
+ hc->xfer_buff = (u8 *) urb->transfer_buffer;
+
+ hc->xfer_buff += frame_desc->offset + qtd->isoc_split_offset;
+ hc->xfer_len = frame_desc->length - qtd->isoc_split_offset;
+
+ if (hc->xact_pos == DWC_HCSPLIT_XACTPOS_ALL) {
+ if (hc->xfer_len <= 188)
+ hc->xact_pos = DWC_HCSPLIT_XACTPOS_ALL;
+ else
+ hc->xact_pos = DWC_HCSPLIT_XACTPOS_BEGIN;
+ }
+ break;
+ }
+
+ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
+ hc->ep_type == DWC_OTG_EP_TYPE_ISOC)
+ /*
+ * This value may be modified when the transfer is started to
+ * reflect the actual transfer length.
+ */
+ hc->multi_count = dwc_hb_mult(qh->maxp);
+
+ dwc_otg_hc_init(hcd->core_if, hc);
+ hc->qh = qh;
+}
+
+/**
+ * This function selects transactions from the HCD transfer schedule and
+ * assigns them to available host channels. It is called from HCD interrupt
+ * handler functions.
+ */
+enum dwc_transaction_type dwc_otg_hcd_select_transactions(struct dwc_hcd *hcd)
+{
+ struct list_head *qh_ptr;
+ struct dwc_qh *qh;
+ int num_channels;
+ enum dwc_transaction_type ret_val = DWC_OTG_TRANSACTION_NONE;
+
+ /* Process entries in the periodic ready list. */
+ num_channels = hcd->core_if->core_params->host_channels;
+ qh_ptr = hcd->periodic_sched_ready.next;
+ while (qh_ptr != &hcd->periodic_sched_ready &&
+ !list_empty(&hcd->free_hc_list)) {
+ /* Leave one channel for non periodic transactions. */
+ if (hcd->available_host_channels <= 1)
+ break;
+ hcd->available_host_channels--;
+ qh = list_entry(qh_ptr, struct dwc_qh, qh_list_entry);
+ assign_and_init_hc(hcd, qh);
+ /*
+ * Move the QH from the periodic ready schedule to the
+ * periodic assigned schedule.
+ */
+ qh_ptr = qh_ptr->next;
+ list_move(&qh->qh_list_entry, &hcd->periodic_sched_assigned);
+ ret_val = DWC_OTG_TRANSACTION_PERIODIC;
+ }
+
+ /*
+ * Process entries in the deferred portion of the non-periodic list.
+ * A NAK put them here and, at the right time, they need to be
+ * placed on the sched_inactive list.
+ */
+ qh_ptr = hcd->non_periodic_sched_deferred.next;
+ while (qh_ptr != &hcd->non_periodic_sched_deferred) {
+ u16 frame_number =
+ dwc_otg_hcd_get_frame_number(dwc_otg_hcd_to_hcd(hcd));
+ qh = list_entry(qh_ptr, struct dwc_qh, qh_list_entry);
+ qh_ptr = qh_ptr->next;
+
+ if (dwc_frame_num_le(qh->sched_frame, frame_number))
+ /*
+ * Move the QH from the non periodic deferred schedule
+ * to the non periodic inactive schedule.
+ */
+ list_move(&qh->qh_list_entry,
+ &hcd->non_periodic_sched_inactive);
+ }
+
+ /*
+ * Process entries in the inactive portion of the non-periodic
+ * schedule. Some free host channels may not be used if they are
+ * reserved for periodic transfers.
+ */
+ qh_ptr = hcd->non_periodic_sched_inactive.next;
+ num_channels = hcd->core_if->core_params->host_channels;
+
+ while (qh_ptr != &hcd->non_periodic_sched_inactive
+ && !list_empty(&hcd->free_hc_list)) {
+ if (hcd->available_host_channels < 1)
+ break;
+ hcd->available_host_channels--;
+ qh = list_entry(qh_ptr, struct dwc_qh, qh_list_entry);
+ assign_and_init_hc(hcd, qh);
+ /*
+ * Move the QH from the non-periodic inactive schedule to the
+ * non-periodic active schedule.
+ */
+ qh_ptr = qh_ptr->next;
+ list_move(&qh->qh_list_entry, &hcd->non_periodic_sched_active);
+ if (ret_val == DWC_OTG_TRANSACTION_NONE)
+ ret_val = DWC_OTG_TRANSACTION_NON_PERIODIC;
+ else
+ ret_val = DWC_OTG_TRANSACTION_ALL;
+
+ }
+ return ret_val;
+}
+
+/**
+ * Sets the channel property that indicates in which frame a periodic transfer
+ * should occur. This is always set to the _next_ frame. This function has no
+ * effect on non-periodic transfers.
+ */
+static inline void hc_set_even_odd_frame(struct core_if *core_if,
+ struct dwc_hc *hc, u32 * hcchar)
+{
+ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
+ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
+ u32 hfnum = 0;
+
+ hfnum = dwc_reg_read(core_if->host_if->host_global_regs,
+ DWC_HFNUM);
+
+ /* 1 if _next_ frame is odd, 0 if it's even */
+ *hcchar = DWC_HCCHAR_ODD_FRAME_RW(*hcchar,
+ ((DWC_HFNUM_FRNUM_RD(hfnum) &
+ 0x1) ? 0 : 1));
+ }
+}
+
+static void set_initial_xfer_pid(struct dwc_hc *hc)
+{
+ if (hc->speed == DWC_OTG_EP_SPEED_HIGH) {
+ if (hc->ep_is_in) {
+ if (hc->multi_count == 1)
+ hc->data_pid_start = DWC_OTG_HC_PID_DATA0;
+ else if (hc->multi_count == 2)
+ hc->data_pid_start = DWC_OTG_HC_PID_DATA1;
+ else
+ hc->data_pid_start = DWC_OTG_HC_PID_DATA2;
+ } else {
+ if (hc->multi_count == 1)
+ hc->data_pid_start = DWC_OTG_HC_PID_DATA0;
+ else
+ hc->data_pid_start = DWC_OTG_HC_PID_MDATA;
+ }
+ } else {
+ hc->data_pid_start = DWC_OTG_HC_PID_DATA0;
+ }
+}
+
+/**
+ * Starts a PING transfer. This function should only be called in Slave mode.
+ * The Do Ping bit is set in the HCTSIZ register, then the channel is enabled.
+ */
+static void dwc_otg_hc_do_ping(struct core_if *core_if, struct dwc_hc *hc)
+{
+ u32 hcchar;
+ u32 hctsiz = 0;
+
+ ulong hc_regs = core_if->host_if->hc_regs[hc->hc_num];
+
+ hctsiz = 0;
+ hctsiz = DWC_HCTSIZ_DO_PING_PROTO_RW(hctsiz, 1);
+ hctsiz = DWC_HCTSIZ_PKT_CNT_RW(hctsiz, 1);
+ dwc_reg_write(hc_regs, DWC_HCTSIZ, hctsiz);
+
+ hcchar = dwc_reg_read(hc_regs, DWC_HCCHAR);
+ hcchar = DWC_HCCHAR_ENA_RW(hcchar, 1);
+ hcchar = DWC_HCCHAR_DIS_RW(hcchar, 0);
+ dwc_reg_write(hc_regs, DWC_HCCHAR, hcchar);
+}
+
+/**
+ * This function writes a packet into the Tx FIFO associated with the Host
+ * Channel. For a channel associated with a non-periodic EP, the non-periodic
+ * Tx FIFO is written. For a channel associated with a periodic EP, the
+ * periodic Tx FIFO is written. This function should only be called in Slave
+ * mode.
+ *
+ * Upon return the xfer_buff and xfer_count fields in hc are incremented by
+ * then number of bytes written to the Tx FIFO.
+ */
+static void dwc_otg_hc_write_packet(struct core_if *core_if, struct dwc_hc *hc)
+{
+ u32 i;
+ u32 remaining_count;
+ u32 byte_count;
+ u32 dword_count;
+ u32 *data_buff = (u32 *) (hc->xfer_buff);
+ u32 data_fifo = core_if->data_fifo[hc->hc_num];
+
+ remaining_count = hc->xfer_len - hc->xfer_count;
+ if (remaining_count > hc->max_packet)
+ byte_count = hc->max_packet;
+ else
+ byte_count = remaining_count;
+
+ dword_count = (byte_count + 3) / 4;
+
+ if (((unsigned long)data_buff) & 0x3)
+ /* xfer_buff is not DWORD aligned. */
+ for (i = 0; i < dword_count; i++, data_buff++)
+ dwc_write_fifo32(data_fifo,
+ get_unaligned(data_buff));
+ else
+ /* xfer_buff is DWORD aligned. */
+ for (i = 0; i < dword_count; i++, data_buff++)
+ dwc_write_fifo32(data_fifo, *data_buff);
+
+ hc->xfer_count += byte_count;
+ hc->xfer_buff += byte_count;
+}
+
+/**
+ * This function does the setup for a data transfer for a host channel and
+ * starts the transfer. May be called in either Slave mode or DMA mode. In
+ * Slave mode, the caller must ensure that there is sufficient space in the
+ * request queue and Tx Data FIFO.
+ *
+ * For an OUT transfer in Slave mode, it loads a data packet into the
+ * appropriate FIFO. If necessary, additional data packets will be loaded in
+ * the Host ISR.
+ *
+ * For an IN transfer in Slave mode, a data packet is requested. The data
+ * packets are unloaded from the Rx FIFO in the Host ISR. If necessary,
+ * additional data packets are requested in the Host ISR.
+ *
+ * For a PING transfer in Slave mode, the Do Ping bit is set in the HCTSIZ
+ * register along with a packet count of 1 and the channel is enabled. This
+ * causes a single PING transaction to occur. Other fields in HCTSIZ are
+ * simply set to 0 since no data transfer occurs in this case.
+ *
+ * For a PING transfer in DMA mode, the HCTSIZ register is initialized with
+ * all the information required to perform the subsequent data transfer. In
+ * addition, the Do Ping bit is set in the HCTSIZ register. In this case, the
+ * controller performs the entire PING protocol, then starts the data
+ * transfer.
+ */
+static void dwc_otg_hc_start_transfer(struct core_if *core_if,
+ struct dwc_hc *hc)
+{
+ u32 hcchar;
+ u32 hctsiz = 0;
+ u16 num_packets;
+ u32 max_hc_xfer_size = core_if->core_params->max_transfer_size;
+ u16 max_hc_pkt_count = core_if->core_params->max_packet_count;
+ ulong hc_regs = core_if->host_if->hc_regs[hc->hc_num];
+ hctsiz = 0;
+
+ if (hc->do_ping) {
+ if (!core_if->dma_enable) {
+ dwc_otg_hc_do_ping(core_if, hc);
+ hc->xfer_started = 1;
+ return;
+ } else {
+ hctsiz = DWC_HCTSIZ_DO_PING_PROTO_RW(hctsiz, 1);
+ }
+ }
+
+ if (hc->do_split) {
+ num_packets = 1;
+
+ if (hc->complete_split && !hc->ep_is_in)
+ /*
+ * For CSPLIT OUT Transfer, set the size to 0 so the
+ * core doesn't expect any data written to the FIFO
+ */
+ hc->xfer_len = 0;
+ else if (hc->ep_is_in || (hc->xfer_len > hc->max_packet))
+ hc->xfer_len = hc->max_packet;
+ else if (!hc->ep_is_in && (hc->xfer_len > 188))
+ hc->xfer_len = 188;
+
+ hctsiz = DWC_HCTSIZ_XFER_SIZE_RW(hctsiz, hc->xfer_len);
+ } else {
+ /*
+ * Ensure that the transfer length and packet count will fit
+ * in the widths allocated for them in the HCTSIZn register.
+ */
+ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
+ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
+ u32 max_len = hc->multi_count * hc->max_packet;
+
+ /*
+ * Make sure the transfer size is no larger than one
+ * (micro)frame's worth of data. (A check was done
+ * when the periodic transfer was accepted to ensure
+ * that a (micro)frame's worth of data can be
+ * programmed into a channel.)
+ */
+ if (hc->xfer_len > max_len)
+ hc->xfer_len = max_len;
+ } else if (hc->xfer_len > max_hc_xfer_size) {
+ /*
+ * Make sure that xfer_len is a multiple of max packet
+ * size.
+ */
+ hc->xfer_len = max_hc_xfer_size - hc->max_packet + 1;
+ }
+ if (hc->xfer_len > 0) {
+ num_packets = (hc->xfer_len + hc->max_packet - 1) /
+ hc->max_packet;
+ if (num_packets > max_hc_pkt_count) {
+ num_packets = max_hc_pkt_count;
+ hc->xfer_len = num_packets * hc->max_packet;
+ }
+ } else {
+ /* Need 1 packet for transfer length of 0. */
+ num_packets = 1;
+ }
+
+ if (hc->ep_is_in)
+ /*
+ * Always program an integral # of max packets for IN
+ * transfers.
+ */
+ hc->xfer_len = num_packets * hc->max_packet;
+
+ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
+ hc->ep_type == DWC_OTG_EP_TYPE_ISOC)
+ /*
+ * Make sure that the multi_count field matches the
+ * actual transfer length.
+ */
+ hc->multi_count = num_packets;
+
+ /* Set up the initial PID for the transfer. */
+ if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)
+ set_initial_xfer_pid(hc);
+
+ hctsiz = DWC_HCTSIZ_XFER_SIZE_RW(hctsiz, hc->xfer_len);
+ }
+
+ hc->start_pkt_count = num_packets;
+ hctsiz = DWC_HCTSIZ_PKT_CNT_RW(hctsiz, num_packets);
+ hctsiz = DWC_HCTSIZ_PKT_PID_RW(hctsiz, hc->data_pid_start);
+ dwc_reg_write(hc_regs, DWC_HCTSIZ, hctsiz);
+
+ if (core_if->dma_enable)
+ dwc_reg_write(hc_regs, DWC_HCDMA, (u32) hc->xfer_buff);
+
+ /* Start the split */
+ if (hc->do_split) {
+ u32 hcsplt;
+
+ hcsplt = dwc_reg_read(hc_regs, DWC_HCSPLT);
+ hcsplt = DWC_HCSPLT_COMP_SPLT_RW(hcsplt, 1);
+ dwc_reg_write(hc_regs, DWC_HCSPLT, hcsplt);
+ }
+
+ hcchar = dwc_reg_read(hc_regs, DWC_HCCHAR);
+ hcchar = DWC_HCCHAR_MULTI_CNT_RW(hcchar, hc->multi_count);
+ hc_set_even_odd_frame(core_if, hc, &hcchar);
+
+ /* Set host channel enable after all other setup is complete. */
+ hcchar = DWC_HCCHAR_ENA_RW(hcchar, 1);
+ hcchar = DWC_HCCHAR_DIS_RW(hcchar, 0);
+ dwc_reg_write(hc_regs, DWC_HCCHAR, hcchar);
+
+ hc->xfer_started = 1;
+ hc->requests++;
+ if (!core_if->dma_enable && !hc->ep_is_in && hc->xfer_len > 0)
+ /* Load OUT packet into the appropriate Tx FIFO. */
+ dwc_otg_hc_write_packet(core_if, hc);
+}
+
+/**
+ * This function continues a data transfer that was started by previous call
+ * to dwc_otg_hc_start_transfer</code>. The caller must ensure there is
+ * sufficient space in the request queue and Tx Data FIFO. This function
+ * should only be called in Slave mode. In DMA mode, the controller acts
+ * autonomously to complete transfers programmed to a host channel.
+ *
+ * For an OUT transfer, a new data packet is loaded into the appropriate FIFO
+ * if there is any data remaining to be queued. For an IN transfer, another
+ * data packet is always requested. For the SETUP phase of a control transfer,
+ * this function does nothing.
+ */
+static int dwc_otg_hc_continue_transfer(struct core_if *core_if,
+ struct dwc_hc *hc)
+{
+ if (hc->do_split) {
+ /* SPLITs always queue just once per channel */
+ return 0;
+ } else if (hc->data_pid_start == DWC_OTG_HC_PID_SETUP) {
+ /* SETUPs are queued only once since they can't be NAKed. */
+ return 0;
+ } else if (hc->ep_is_in) {
+ /*
+ * Always queue another request for other IN transfers. If
+ * back-to-back INs are issued and NAKs are received for both,
+ * the driver may still be processing the first NAK when the
+ * second NAK is received. When the interrupt handler clears
+ * the NAK interrupt for the first NAK, the second NAK will
+ * not be seen. So we can't depend on the NAK interrupt
+ * handler to requeue a NAKed request. Instead, IN requests
+ * are issued each time this function is called. When the
+ * transfer completes, the extra requests for the channel will
+ * be flushed.
+ */
+ u32 hcchar;
+ ulong hc_regs = core_if->host_if->hc_regs[hc->hc_num];
+
+ hcchar = dwc_reg_read(hc_regs, DWC_HCCHAR);
+ hc_set_even_odd_frame(core_if, hc, &hcchar);
+
+ hcchar = DWC_HCCHAR_ENA_RW(hcchar, 1);
+ hcchar = DWC_HCCHAR_DIS_RW(hcchar, 0);
+ dwc_reg_write(hc_regs, DWC_HCCHAR, hcchar);
+
+ hc->requests++;
+ return 1;
+ } else {
+ /* OUT transfers. */
+ if (hc->xfer_count < hc->xfer_len) {
+ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
+ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
+ u32 hcchar;
+ u32 hc_regs;
+
+ hc_regs =
+ core_if->host_if->hc_regs[hc->hc_num];
+ hcchar = dwc_reg_read(hc_regs, DWC_HCCHAR);
+ hc_set_even_odd_frame(core_if, hc, &hcchar);
+ }
+
+ /* Load OUT packet into the appropriate Tx FIFO. */
+ dwc_otg_hc_write_packet(core_if, hc);
+ hc->requests++;
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+}
+
+/**
+ * This function writes a packet into the Tx FIFO associated with the Host
+ * Channel. For a channel associated with a non-periodic EP, the non-periodic
+ * Tx FIFO is written. For a channel associated with a periodic EP, the
+ * periodic Tx FIFO is written. This function should only be called in Slave
+ * mode.
+ *
+ * Upon return the xfer_buff and xfer_count fields in hc are incremented by
+ * then number of bytes written to the Tx FIFO.
+ */
+
+/**
+ * Attempts to queue a single transaction request for a host channel
+ * associated with either a periodic or non-periodic transfer. This function
+ * assumes that there is space available in the appropriate request queue. For
+ * an OUT transfer or SETUP transaction in Slave mode, it checks whether space
+ * is available in the appropriate Tx FIFO.
+ */
+static int queue_transaction(struct dwc_hcd *hcd, struct dwc_hc *hc,
+ u16 _fifo_dwords_avail)
+{
+ int retval;
+
+ if (hcd->core_if->dma_enable) {
+ if (!hc->xfer_started) {
+ dwc_otg_hc_start_transfer(hcd->core_if, hc);
+ hc->qh->ping_state = 0;
+ }
+ retval = 0;
+ } else if (hc->halt_pending) {
+ /* Don't queue a request if the channel has been halted. */
+ retval = 0;
+ } else if (hc->halt_on_queue) {
+ dwc_otg_hc_halt(hcd->core_if, hc, hc->halt_status);
+ retval = 0;
+ } else if (hc->do_ping) {
+ if (!hc->xfer_started)
+ dwc_otg_hc_start_transfer(hcd->core_if, hc);
+ retval = 0;
+ } else if (!hc->ep_is_in || hc->data_pid_start ==
+ DWC_OTG_HC_PID_SETUP) {
+ if ((_fifo_dwords_avail * 4) >= hc->max_packet) {
+ if (!hc->xfer_started) {
+ dwc_otg_hc_start_transfer(hcd->core_if, hc);
+ retval = 1;
+ } else {
+ retval =
+ dwc_otg_hc_continue_transfer(hcd->core_if,
+ hc);
+ }
+ } else {
+ retval = -1;
+ }
+ } else {
+ if (!hc->xfer_started) {
+ dwc_otg_hc_start_transfer(hcd->core_if, hc);
+ retval = 1;
+ } else {
+ retval = dwc_otg_hc_continue_transfer(hcd->core_if, hc);
+ }
+ }
+ return retval;
+}
+
+/**
+ * Processes active non-periodic channels and queues transactions for these
+ * channels to the DWC_otg controller. After queueing transactions, the NP Tx
+ * FIFO Empty interrupt is enabled if there are more transactions to queue as
+ * NP Tx FIFO or request queue space becomes available. Otherwise, the NP Tx
+ * FIFO Empty interrupt is disabled.
+ */
+static void process_non_periodic_channels(struct dwc_hcd *hcd)
+{
+ u32 tx_status = 0;
+ struct list_head *orig_qh_ptr;
+ struct dwc_qh *qh;
+ int status;
+ int no_queue_space = 0;
+ int no_fifo_space = 0;
+ int more_to_do = 0;
+ ulong regs = hcd->core_if->core_global_regs;
+
+ /*
+ * Keep track of the starting point. Skip over the start-of-list
+ * entry.
+ */
+ if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active)
+ hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next;
+ orig_qh_ptr = hcd->non_periodic_qh_ptr;
+
+ /*
+ * Process once through the active list or until no more space is
+ * available in the request queue or the Tx FIFO.
+ */
+ do {
+ tx_status = dwc_reg_read(regs, DWC_GNPTXSTS);
+ if (!hcd->core_if->dma_enable &&
+ DWC_GNPTXSTS_NPTXQSPCAVAIL_RD(tx_status) == 0) {
+ no_queue_space = 1;
+ break;
+ }
+
+ qh = list_entry(hcd->non_periodic_qh_ptr, struct dwc_qh,
+ qh_list_entry);
+ status = queue_transaction(hcd, qh->channel,
+ DWC_GNPTXSTS_NPTXFSPCAVAIL_RD
+ (tx_status));
+
+ if (status > 0) {
+ more_to_do = 1;
+ } else if (status < 0) {
+ no_fifo_space = 1;
+ break;
+ }
+
+ /* Advance to next QH, skipping start-of-list entry. */
+ hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next;
+ if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active)
+ hcd->non_periodic_qh_ptr =
+ hcd->non_periodic_qh_ptr->next;
+ } while (hcd->non_periodic_qh_ptr != orig_qh_ptr);
+
+ if (!hcd->core_if->dma_enable) {
+ u32 intr_mask = 0;
+
+ intr_mask |= DWC_INTMSK_NP_TXFIFO_EMPT;
+ if (more_to_do || no_queue_space || no_fifo_space) {
+ /*
+ * May need to queue more transactions as the request
+ * queue or Tx FIFO empties. Enable the non-periodic
+ * Tx FIFO empty interrupt. (Always use the half-empty
+ * level to ensure that new requests are loaded as
+ * soon as possible.)
+ */
+ dwc_reg_modify(gintmsk_reg(hcd), 0, 0, intr_mask);
+ } else {
+ /*
+ * Disable the Tx FIFO empty interrupt since there are
+ * no more transactions that need to be queued right
+ * now. This function is called from interrupt
+ * handlers to queue more transactions as transfer
+ * states change.
+ */
+ dwc_reg_modify(gintmsk_reg(hcd), 0, intr_mask, 0);
+ }
+ }
+}
+
+/**
+ * Processes periodic channels for the next frame and queues transactions for
+ * these channels to the DWC_otg controller. After queueing transactions, the
+ * Periodic Tx FIFO Empty interrupt is enabled if there are more transactions
+ * to queue as Periodic Tx FIFO or request queue space becomes available.
+ * Otherwise, the Periodic Tx FIFO Empty interrupt is disabled.
+ */
+static void process_periodic_channels(struct dwc_hcd *hcd)
+{
+ u32 tx_status = 0;
+ struct list_head *qh_ptr;
+ struct dwc_qh *qh;
+ int status;
+ int no_queue_space = 0;
+ int no_fifo_space = 0;
+ ulong host_regs;
+
+ host_regs = hcd->core_if->host_if->host_global_regs;
+
+ qh_ptr = hcd->periodic_sched_assigned.next;
+ while (qh_ptr != &hcd->periodic_sched_assigned) {
+ tx_status = dwc_reg_read(host_regs, DWC_HPTXSTS);
+ if (DWC_HPTXSTS_PTXSPC_AVAIL_RD(tx_status) == 0) {
+ no_queue_space = 1;
+ break;
+ }
+
+ qh = list_entry(qh_ptr, struct dwc_qh, qh_list_entry);
+
+ /*
+ * Set a flag if we're queuing high-bandwidth in slave mode.
+ * The flag prevents any halts to get into the request queue in
+ * the middle of multiple high-bandwidth packets getting queued.
+ */
+ if (!hcd->core_if->dma_enable && qh->channel->multi_count > 1)
+ hcd->core_if->queuing_high_bandwidth = 1;
+
+ status = queue_transaction(hcd, qh->channel,
+ DWC_HPTXSTS_PTXFSPC_AVAIL_RD
+ (tx_status));
+ if (status < 0) {
+ no_fifo_space = 1;
+ break;
+ }
+
+ /*
+ * In Slave mode, stay on the current transfer until there is
+ * nothing more to do or the high-bandwidth request count is
+ * reached. In DMA mode, only need to queue one request. The
+ * controller automatically handles multiple packets for
+ * high-bandwidth transfers.
+ */
+ if (hcd->core_if->dma_enable || (status == 0 ||
+ qh->channel->requests ==
+ qh->channel->multi_count)) {
+ qh_ptr = qh_ptr->next;
+
+ /*
+ * Move the QH from the periodic assigned schedule to
+ * the periodic queued schedule.
+ */
+ list_move(&qh->qh_list_entry,
+ &hcd->periodic_sched_queued);
+
+ /* done queuing high bandwidth */
+ hcd->core_if->queuing_high_bandwidth = 0;
+ }
+ }
+
+ if (!hcd->core_if->dma_enable) {
+ u32 intr_mask = 0;
+
+ intr_mask |= DWC_INTMSK_NP_TXFIFO_EMPT;
+
+ if (!list_empty(&hcd->periodic_sched_assigned) ||
+ no_queue_space || no_fifo_space)
+ /*
+ * May need to queue more transactions as the request
+ * queue or Tx FIFO empties. Enable the periodic Tx
+ * FIFO empty interrupt. (Always use the half-empty
+ * level to ensure that new requests are loaded as
+ * soon as possible.)
+ */
+ dwc_reg_modify(gintmsk_reg(hcd), 0, 0, intr_mask);
+ else
+ /*
+ * Disable the Tx FIFO empty interrupt since there are
+ * no more transactions that need to be queued right
+ * now. This function is called from interrupt
+ * handlers to queue more transactions as transfer
+ * states change.
+ */
+ dwc_reg_modify(gintmsk_reg(hcd), 0, intr_mask, 0);
+ }
+}
+
+/**
+ * This function processes the currently active host channels and queues
+ * transactions for these channels to the DWC_otg controller. It is called
+ * from HCD interrupt handler functions.
+ */
+void dwc_otg_hcd_queue_transactions(struct dwc_hcd *hcd,
+ enum dwc_transaction_type tr_type)
+{
+ /* Process host channels associated with periodic transfers. */
+ if ((tr_type == DWC_OTG_TRANSACTION_PERIODIC ||
+ tr_type == DWC_OTG_TRANSACTION_ALL) &&
+ !list_empty(&hcd->periodic_sched_assigned))
+ process_periodic_channels(hcd);
+
+ /* Process host channels associated with non-periodic transfers. */
+ if (tr_type == DWC_OTG_TRANSACTION_NON_PERIODIC ||
+ tr_type == DWC_OTG_TRANSACTION_ALL) {
+ if (!list_empty(&hcd->non_periodic_sched_active)) {
+ process_non_periodic_channels(hcd);
+ } else {
+ /*
+ * Ensure NP Tx FIFO empty interrupt is disabled when
+ * there are no non-periodic transfers to process.
+ */
+ u32 gintmsk = 0;
+ gintmsk |= DWC_INTMSK_NP_TXFIFO_EMPT;
+ dwc_reg_modify(gintmsk_reg(hcd), 0, gintmsk, 0);
+ }
+ }
+}
+
+/**
+ * Sets the final status of an URB and returns it to the device driver. Any
+ * required cleanup of the URB is performed.
+ */
+void dwc_otg_hcd_complete_urb(struct dwc_hcd *hcd, struct urb *urb, int status)
+__releases(hcd->lock) __acquires(hcd->lock)
+{
+ urb->hcpriv = NULL;
+ usb_hcd_unlink_urb_from_ep(dwc_otg_hcd_to_hcd(hcd), urb);
+
+ spin_unlock(&hcd->lock);
+ usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb, status);
+ spin_lock(&hcd->lock);
+}
diff --git a/drivers/usb/dwc/hcd.h b/drivers/usb/dwc/hcd.h
new file mode 100644
index 0000000..2d25abc
--- /dev/null
+++ b/drivers/usb/dwc/hcd.h
@@ -0,0 +1,416 @@
+/*
+ * DesignWare HS OTG controller driver
+ * Copyright (C) 2006 Synopsys, Inc.
+ * Portions Copyright (C) 2010 Applied Micro Circuits Corporation.
+ *
+ * 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 version 2 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
+ * or write to the Free Software Foundation, Inc., 51 Franklin Street,
+ * Suite 500, Boston, MA 02110-1335 USA.
+ *
+ * Based on Synopsys driver version 2.60a
+ * Modified by Mark Miesfeld <mmiesfeld@apm.com>
+ * Modified by Stefan Roese <sr@denx.de>, DENX Software Engineering
+ * Modified by Chuck Meade <chuck@theptrgroup.com>
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL SYNOPSYS, INC. 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.
+ *
+ */
+
+#if !defined(__DWC_HCD_H__)
+#define __DWC_HCD_H__
+
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+
+#include "driver.h"
+
+/*
+ * This file contains the structures, constants, and interfaces for
+ * the Host Contoller Driver (HCD).
+ *
+ * The Host Controller Driver (HCD) is responsible for translating requests
+ * from the USB Driver into the appropriate actions on the DWC_otg controller.
+ * It isolates the USBD from the specifics of the controller by providing an
+ * API to the USBD.
+ */
+
+/* Phases for control transfers. */
+enum dwc_control_phase {
+ DWC_OTG_CONTROL_SETUP,
+ DWC_OTG_CONTROL_DATA,
+ DWC_OTG_CONTROL_STATUS
+};
+
+/* Transaction types. */
+enum dwc_transaction_type {
+ DWC_OTG_TRANSACTION_NONE,
+ DWC_OTG_TRANSACTION_PERIODIC,
+ DWC_OTG_TRANSACTION_NON_PERIODIC,
+ DWC_OTG_TRANSACTION_ALL
+};
+
+/*
+ * A Queue Transfer Descriptor (QTD) holds the state of a bulk, control,
+ * interrupt, or isochronous transfer. A single QTD is created for each URB
+ * (of one of these types) submitted to the HCD. The transfer associated with
+ * a QTD may require one or multiple transactions.
+ *
+ * A QTD is linked to a Queue Head, which is entered in either the
+ * non-periodic or periodic schedule for execution. When a QTD is chosen for
+ * execution, some or all of its transactions may be executed. After
+ * execution, the state of the QTD is updated. The QTD may be retired if all
+ * its transactions are complete or if an error occurred. Otherwise, it
+ * remains in the schedule so more transactions can be executed later.
+ */
+struct dwc_qtd {
+ /*
+ * Determines the PID of the next data packet for the data phase of
+ * control transfers. Ignored for other transfer types.
+ * One of the following values:
+ * - DWC_OTG_HC_PID_DATA0
+ * - DWC_OTG_HC_PID_DATA1
+ */
+ u8 data_toggle;
+
+ /* Current phase for control transfers (Setup, Data, or Status). */
+ enum dwc_control_phase control_phase;
+
+ /*
+ * Keep track of the current split type
+ * for FS/LS endpoints on a HS Hub
+ */
+ u8 complete_split;
+
+ /* How many bytes transferred during SSPLIT OUT */
+ u32 ssplit_out_xfer_count;
+
+ /*
+ * Holds the number of bus errors that have occurred for a transaction
+ * within this transfer.
+ */
+ u8 error_count;
+
+ /*
+ * Index of the next frame descriptor for an isochronous transfer. A
+ * frame descriptor describes the buffer position and length of the
+ * data to be transferred in the next scheduled (micro)frame of an
+ * isochronous transfer. It also holds status for that transaction.
+ * The frame index starts at 0.
+ */
+ int isoc_frame_index;
+
+ /* Position of the ISOC split on full/low speed */
+ u8 isoc_split_pos;
+
+ /* Position of the ISOC split in the buffer for the current frame */
+ u16 isoc_split_offset;
+
+ /* URB for this transfer */
+ struct urb *urb;
+
+ /* This list of QTDs */
+ struct list_head qtd_list_entry;
+
+ /* Field to track the qh pointer */
+ struct dwc_qh *qtd_qh_ptr;
+};
+
+/*
+ * A Queue Head (QH) holds the static characteristics of an endpoint and
+ * maintains a list of transfers (QTDs) for that endpoint. A QH structure may
+ * be entered in either the non-periodic or periodic schedule.
+ */
+struct dwc_qh {
+ /*
+ * Endpoint type.
+ * One of the following values:
+ * - USB_ENDPOINT_XFER_CONTROL
+ * - USB_ENDPOINT_XFER_ISOC
+ * - USB_ENDPOINT_XFER_BULK
+ * - USB_ENDPOINT_XFER_INT
+ */
+ u8 ep_type;
+ u8 ep_is_in;
+
+ /* wMaxPacketSize Field of Endpoint Descriptor. */
+ u16 maxp;
+
+ /*
+ * Determines the PID of the next data packet for non-control
+ * transfers. Ignored for control transfers.
+ * One of the following values:
+ * - DWC_OTG_HC_PID_DATA0
+ * - DWC_OTG_HC_PID_DATA1
+ */
+ u8 data_toggle;
+
+ /* Ping state if 1. */
+ u8 ping_state;
+
+ /* List of QTDs for this QH. */
+ struct list_head qtd_list;
+
+ /* Host channel currently processing transfers for this QH. */
+ struct dwc_hc *channel;
+
+ /* QTD currently assigned to a host channel for this QH. */
+ struct dwc_qtd *qtd_in_process;
+
+ /* Full/low speed endpoint on high-speed hub requires split. */
+ u8 do_split;
+
+ /* Periodic schedule information */
+
+ /* Bandwidth in microseconds per (micro)frame. */
+ u8 usecs;
+
+ /* Interval between transfers in (micro)frames. */
+ u16 interval;
+
+ /*
+ * (micro)frame to initialize a periodic transfer. The transfer
+ * executes in the following (micro)frame.
+ */
+ u16 sched_frame;
+
+ /* (micro)frame at which last start split was initialized. */
+ u16 start_split_frame;
+
+ u16 speed;
+ u16 frame_usecs[8];
+
+ /* Entry for QH in either the periodic or non-periodic schedule. */
+ struct list_head qh_list_entry;
+};
+
+/* Gets the struct usb_hcd that contains a struct dwc_hcd. */
+static inline struct usb_hcd *dwc_otg_hcd_to_hcd(struct dwc_hcd *dwc_hcd)
+{
+ return container_of((void *)dwc_hcd, struct usb_hcd, hcd_priv);
+}
+
+/* HCD Create/Destroy Functions */
+extern int dwc_otg_hcd_init(struct device *_dev,
+ struct dwc_otg_device *dwc_dev);
+extern void dwc_otg_hcd_remove(struct device *_dev);
+
+/*
+ * The following functions support managing the DWC_otg controller in host
+ * mode.
+ */
+extern int dwc_otg_hcd_get_frame_number(struct usb_hcd *hcd);
+extern void dwc_otg_hc_cleanup(struct core_if *core_if, struct dwc_hc *hc);
+extern void dwc_otg_hc_halt(struct core_if *core_if, struct dwc_hc *hc,
+ enum dwc_halt_status _halt_status);
+
+/* Transaction Execution Functions */
+extern enum dwc_transaction_type dwc_otg_hcd_select_transactions(struct dwc_hcd
+ *hcd);
+extern void dwc_otg_hcd_queue_transactions(struct dwc_hcd *hcd,
+ enum dwc_transaction_type tr_type);
+extern void dwc_otg_hcd_complete_urb(struct dwc_hcd *_hcd, struct urb *urb,
+ int status);
+
+/* Interrupt Handler Functions */
+extern int dwc_otg_hcd_handle_intr(struct dwc_hcd *hcd);
+
+/* Schedule Queue Functions */
+extern int init_hcd_usecs(struct dwc_hcd *hcd);
+extern void dwc_otg_hcd_qh_free(struct dwc_qh *qh);
+extern void dwc_otg_hcd_qh_remove(struct dwc_hcd *hcd, struct dwc_qh *qh);
+extern void dwc_otg_hcd_qh_deactivate(struct dwc_hcd *hcd, struct dwc_qh *qh,
+ int sched_csplit);
+extern int dwc_otg_hcd_qh_deferr(struct dwc_hcd *hcd, struct dwc_qh *qh,
+ int delay);
+extern struct dwc_qtd *dwc_otg_hcd_qtd_create(struct urb *urb,
+ gfp_t _mem_flags);
+extern int dwc_otg_hcd_qtd_add(struct dwc_qtd *qtd, struct dwc_hcd *dwc_hcd);
+
+/*
+ * Frees the memory for a QTD structure. QTD should already be removed from
+ * list.
+ */
+static inline void dwc_otg_hcd_qtd_free(struct dwc_qtd *_qtd)
+{
+ kfree(_qtd);
+}
+
+/* Removes a QTD from list. */
+static inline void dwc_otg_hcd_qtd_remove(struct dwc_qtd *_qtd)
+{
+ list_del(&_qtd->qtd_list_entry);
+}
+
+/* Remove and free a QTD */
+static inline void dwc_otg_hcd_qtd_remove_and_free(struct dwc_qtd *_qtd)
+{
+ dwc_otg_hcd_qtd_remove(_qtd);
+ dwc_otg_hcd_qtd_free(_qtd);
+}
+
+struct dwc_qh *dwc_urb_to_qh(struct urb *_urb);
+
+/* Gets the usb_host_endpoint associated with an URB. */
+static inline struct usb_host_endpoint *dwc_urb_to_endpoint(struct urb *_urb)
+{
+ struct usb_device *dev = _urb->dev;
+ int ep_num = usb_pipeendpoint(_urb->pipe);
+
+ if (usb_pipein(_urb->pipe))
+ return dev->ep_in[ep_num];
+ else
+ return dev->ep_out[ep_num];
+}
+
+/*
+ * Gets the endpoint number from a _bEndpointAddress argument. The endpoint is
+ * qualified with its direction (possible 32 endpoints per device).
+ */
+#define dwc_ep_addr_to_endpoint(_bEndpointAddress_) \
+ ((_bEndpointAddress_ & USB_ENDPOINT_NUMBER_MASK) | \
+ ((_bEndpointAddress_ & USB_DIR_IN) != 0) << 4)
+
+/* Gets the QH that contains the list_head */
+#define dwc_list_to_qh(_list_head_ptr_) \
+ (container_of(_list_head_ptr_, struct dwc_qh, qh_list_entry))
+
+/* Gets the QTD that contains the list_head */
+#define dwc_list_to_qtd(_list_head_ptr_) \
+ (container_of(_list_head_ptr_, struct dwc_qtd, qtd_list_entry))
+
+/* Check if QH is non-periodic */
+#define dwc_qh_is_non_per(_qh_ptr_) \
+ ((_qh_ptr_->ep_type == USB_ENDPOINT_XFER_BULK) || \
+ (_qh_ptr_->ep_type == USB_ENDPOINT_XFER_CONTROL))
+
+/* High bandwidth multiplier as encoded in highspeed endpoint descriptors */
+#define dwc_hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
+
+/* Packet size for any kind of endpoint descriptor */
+#define dwc_max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff)
+
+/*
+ * Returns true if _frame1 is less than or equal to _frame2. The comparison is
+ * done modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the
+ * frame number when the max frame number is reached.
+ */
+static inline int dwc_frame_num_le(u16 _frame1, u16 _frame2)
+{
+ return ((_frame2 - _frame1) & DWC_HFNUM_MAX_FRNUM) <=
+ (DWC_HFNUM_MAX_FRNUM >> 1);
+}
+
+/*
+ * Returns true if _frame1 is greater than _frame2. The comparison is done
+ * modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the frame
+ * number when the max frame number is reached.
+ */
+static inline int dwc_frame_num_gt(u16 _frame1, u16 _frame2)
+{
+ return (_frame1 != _frame2) &&
+ (((_frame1 - _frame2) &
+ DWC_HFNUM_MAX_FRNUM) < (DWC_HFNUM_MAX_FRNUM >> 1));
+}
+
+/*
+ * Increments _frame by the amount specified by _inc. The addition is done
+ * modulo DWC_HFNUM_MAX_FRNUM. Returns the incremented value.
+ */
+static inline u16 dwc_frame_num_inc(u16 _frame, u16 _inc)
+{
+ return (_frame + _inc) & DWC_HFNUM_MAX_FRNUM;
+}
+
+static inline u16 dwc_full_frame_num(u16 _frame)
+{
+ return ((_frame) & DWC_HFNUM_MAX_FRNUM) >> 3;
+}
+
+static inline u16 dwc_micro_frame_num(u16 _frame)
+{
+ return (_frame) & 0x7;
+}
+
+static inline ulong gintsts_reg(struct dwc_hcd *hcd)
+{
+ ulong global_regs = hcd->core_if->core_global_regs;
+ return global_regs + DWC_GINTSTS;
+}
+
+static inline ulong gintmsk_reg(struct dwc_hcd *hcd)
+{
+ ulong global_regs = hcd->core_if->core_global_regs;
+ return global_regs + DWC_GINTMSK;
+}
+
+static inline ulong gahbcfg_reg(struct dwc_hcd *hcd)
+{
+ ulong global_regs = hcd->core_if->core_global_regs;
+ return global_regs + DWC_GAHBCFG;
+}
+
+static inline const char *pipetype_str(unsigned int pipe)
+{
+ switch (usb_pipetype(pipe)) {
+ case PIPE_CONTROL:
+ return "control";
+ case PIPE_BULK:
+ return "bulk";
+ case PIPE_INTERRUPT:
+ return "interrupt";
+ case PIPE_ISOCHRONOUS:
+ return "isochronous";
+ default:
+ return "unknown";
+ }
+}
+
+static inline const char *dev_speed_str(enum usb_device_speed speed)
+{
+ switch (speed) {
+ case USB_SPEED_HIGH:
+ return "high";
+ case USB_SPEED_FULL:
+ return "full";
+ case USB_SPEED_LOW:
+ return "low";
+ default:
+ return "unknown";
+ }
+}
+
+static inline const char *ep_type_str(u8 type)
+{
+ switch (type) {
+ case USB_ENDPOINT_XFER_ISOC:
+ return "isochronous";
+ case USB_ENDPOINT_XFER_INT:
+ return "interrupt";
+ case USB_ENDPOINT_XFER_CONTROL:
+ return "control";
+ case USB_ENDPOINT_XFER_BULK:
+ return "bulk";
+ default:
+ return "?";
+ }
+}
+#endif
diff --git a/drivers/usb/dwc/hcd_intr.c b/drivers/usb/dwc/hcd_intr.c
new file mode 100644
index 0000000..b16934d
--- /dev/null
+++ b/drivers/usb/dwc/hcd_intr.c
@@ -0,0 +1,1477 @@
+/*
+ * DesignWare HS OTG controller driver
+ * Copyright (C) 2006 Synopsys, Inc.
+ * Portions Copyright (C) 2010 Applied Micro Circuits Corporation.
+ *
+ * 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 version 2 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
+ * or write to the Free Software Foundation, Inc., 51 Franklin Street,
+ * Suite 500, Boston, MA 02110-1335 USA.
+ *
+ * Based on Synopsys driver version 2.60a
+ * Modified by Mark Miesfeld <mmiesfeld@apm.com>
+ * Modified by Stefan Roese <sr@denx.de>, DENX Software Engineering
+ * Modified by Chuck Meade <chuck@theptrgroup.com>
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL SYNOPSYS, INC. BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "hcd.h"
+
+/* This file contains the implementation of the HCD Interrupt handlers. */
+static const int erratum_usb09_patched;
+static const int deferral_on = 1;
+static const int nak_deferral_delay = 8;
+static const int nyet_deferral_delay = 1;
+
+/**
+ * Handles the start-of-frame interrupt in host mode. Non-periodic
+ * transactions may be queued to the DWC_otg controller for the current
+ * (micro)frame. Periodic transactions may be queued to the controller for the
+ * next (micro)frame.
+ */
+static int dwc_otg_hcd_handle_sof_intr(struct dwc_hcd *hcd)
+{
+ u32 hfnum = 0;
+ struct list_head *qh_entry;
+ struct dwc_qh *qh;
+ enum dwc_transaction_type tr_type;
+ u32 gintsts = 0;
+
+ hfnum =
+ dwc_reg_read(hcd->core_if->host_if->host_global_regs,
+ DWC_HFNUM);
+
+ hcd->frame_number = DWC_HFNUM_FRNUM_RD(hfnum);
+
+ /* Determine whether any periodic QHs should be executed. */
+ qh_entry = hcd->periodic_sched_inactive.next;
+ while (qh_entry != &hcd->periodic_sched_inactive) {
+ qh = list_entry(qh_entry, struct dwc_qh, qh_list_entry);
+ qh_entry = qh_entry->next;
+
+ /*
+ * If needed, move QH to the ready list to be executed next
+ * (micro)frame.
+ */
+ if (dwc_frame_num_le(qh->sched_frame, hcd->frame_number))
+ list_move(&qh->qh_list_entry,
+ &hcd->periodic_sched_ready);
+ }
+
+ tr_type = dwc_otg_hcd_select_transactions(hcd);
+ if (tr_type != DWC_OTG_TRANSACTION_NONE)
+ dwc_otg_hcd_queue_transactions(hcd, tr_type);
+
+ /* Clear interrupt */
+ gintsts |= DWC_INTMSK_STRT_OF_FRM;
+ dwc_reg_write(gintsts_reg(hcd), 0, gintsts);
+ return 1;
+}
+
+/**
+ * Handles the Rx Status Queue Level Interrupt, which indicates that there is at
+ * least one packet in the Rx FIFO. The packets are moved from the FIFO to
+ * memory if the DWC_otg controller is operating in Slave mode.
+ */
+static int dwc_otg_hcd_handle_rx_status_q_level_intr(struct dwc_hcd *hcd)
+{
+ u32 grxsts;
+ struct dwc_hc *hc;
+
+ grxsts = dwc_reg_read(hcd->core_if->core_global_regs, DWC_GRXSTSP);
+ hc = hcd->hc_ptr_array[grxsts & DWC_HM_RXSTS_CHAN_NUM_RD(grxsts)];
+
+ /* Packet Status */
+ switch (DWC_HM_RXSTS_PKT_STS_RD(grxsts)) {
+ case DWC_GRXSTS_PKTSTS_IN:
+ /* Read the data into the host buffer. */
+ if (DWC_HM_RXSTS_BYTE_CNT_RD(grxsts) > 0) {
+ dwc_otg_read_packet(hcd->core_if, hc->xfer_buff,
+ DWC_HM_RXSTS_BYTE_CNT_RD(grxsts));
+ /* Update the HC fields for the next packet received. */
+ hc->xfer_count += DWC_HM_RXSTS_BYTE_CNT_RD(grxsts);
+ hc->xfer_buff += DWC_HM_RXSTS_BYTE_CNT_RD(grxsts);
+ }
+ case DWC_GRXSTS_PKTSTS_IN_XFER_COMP:
+ case DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
+ case DWC_GRXSTS_PKTSTS_CH_HALTED:
+ /* Handled in interrupt, just ignore data */
+ break;
+ default:
+ pr_err("RX_STS_Q Interrupt: Unknown status %d\n",
+ DWC_HM_RXSTS_PKT_STS_RD(grxsts));
+ break;
+ }
+ return 1;
+}
+
+/**
+ * This interrupt occurs when the non-periodic Tx FIFO is half-empty. More
+ * data packets may be written to the FIFO for OUT transfers. More requests
+ * may be written to the non-periodic request queue for IN transfers. This
+ * interrupt is enabled only in Slave mode.
+ */
+static int dwc_otg_hcd_handle_np_tx_fifo_empty_intr(struct dwc_hcd *hcd)
+{
+ dwc_otg_hcd_queue_transactions(hcd, DWC_OTG_TRANSACTION_NON_PERIODIC);
+ return 1;
+}
+
+/**
+ * This interrupt occurs when the periodic Tx FIFO is half-empty. More data
+ * packets may be written to the FIFO for OUT transfers. More requests may be
+ * written to the periodic request queue for IN transfers. This interrupt is
+ * enabled only in Slave mode.
+ */
+static int dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(struct dwc_hcd *hcd)
+{
+ dwc_otg_hcd_queue_transactions(hcd, DWC_OTG_TRANSACTION_PERIODIC);
+ return 1;
+}
+
+/**
+ * When the port changes to enabled it may be necessary to adjust the phy clock
+ * speed.
+ */
+static int adjusted_phy_clock_speed(struct dwc_hcd *hcd, u32 hprt0)
+{
+ int adjusted = 0;
+ u32 usbcfg;
+ ulong global_regs = hcd->core_if->core_global_regs;
+ struct core_params *params = hcd->core_if->core_params;
+ ulong h_regs = hcd->core_if->host_if->host_global_regs;
+
+ usbcfg = dwc_reg_read(global_regs, DWC_GUSBCFG);
+
+ if (DWC_HPRT0_PRT_SPD_RD(hprt0) == DWC_HPRT0_PRTSPD_LOW_SPEED ||
+ DWC_HPRT0_PRT_SPD_RD(hprt0) == DWC_HPRT0_PRTSPD_FULL_SPEED) {
+ /* Low power */
+ u32 hcfg;
+
+ if (!(usbcfg & DWC_USBCFG_PHYLPWRCLKSEL)) {
+ /* Set PHY low power clock select for FS/LS devices */
+ usbcfg |= DWC_USBCFG_PHYLPWRCLKSEL;
+ dwc_reg_write(global_regs, DWC_GUSBCFG, usbcfg);
+ adjusted = 1;
+ }
+
+ hcfg = dwc_reg_read(h_regs, DWC_HCFG);
+ if (DWC_HPRT0_PRT_SPD_RD(hprt0) == DWC_HPRT0_PRTSPD_LOW_SPEED &&
+ params->host_ls_low_power_phy_clk ==
+ DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ) {
+ /* 6 MHZ, check for 6 MHZ clock select */
+ if (DWC_HCFG_FSLSP_CLK_RD(hcfg) != DWC_HCFG_6_MHZ) {
+ hcfg = DWC_HCFG_FSLSP_CLK_RW(hcfg,
+ DWC_HCFG_6_MHZ);
+ dwc_reg_write(h_regs, DWC_HCFG, hcfg);
+ adjusted = 1;
+ }
+ } else if (DWC_HCFG_FSLSP_CLK_RD(hcfg) != DWC_HCFG_48_MHZ) {
+ /* 48 MHZ and clock select is not 48 MHZ */
+ hcfg = DWC_HCFG_FSLSP_CLK_RW(hcfg, DWC_HCFG_48_MHZ);
+ dwc_reg_write(h_regs, DWC_HCFG, hcfg);
+ adjusted = 1;
+ }
+ } else if (usbcfg & DWC_USBCFG_PHYLPWRCLKSEL) {
+ usbcfg &= ~((u32) DWC_USBCFG_PHYLPWRCLKSEL);
+ dwc_reg_write(global_regs, DWC_GUSBCFG, usbcfg);
+ adjusted = 1;
+ }
+ if (adjusted)
+ schedule_work(&hcd->usb_port_reset);
+
+ return adjusted;
+}
+
+/**
+ * Helper function to handle the port enable changed interrupt when the port
+ * becomes enabled. Checks if we need to adjust the PHY clock speed for low
+ * power and adjusts it if needed.
+ */
+static void port_enabled(struct dwc_hcd *hcd, u32 hprt0)
+{
+ if (hcd->core_if->core_params->host_support_fs_ls_low_power)
+ if (!adjusted_phy_clock_speed(hcd, hprt0))
+ hcd->flags.b.port_reset_change = 1;
+}
+
+/**
+ * There are multiple conditions that can cause a port interrupt. This function
+ * determines which interrupt conditions have occurred and handles them
+ * appropriately.
+ */
+static int dwc_otg_hcd_handle_port_intr(struct dwc_hcd *hcd)
+{
+ int retval = 0;
+ u32 hprt0;
+ u32 hprt0_modify;
+
+ hprt0 = dwc_reg_read(hcd->core_if->host_if->hprt0, 0);
+ hprt0_modify = dwc_reg_read(hcd->core_if->host_if->hprt0, 0);
+
+ /*
+ * Clear appropriate bits in HPRT0 to clear the interrupt bit in
+ * GINTSTS
+ */
+ hprt0_modify = DWC_HPRT0_PRT_ENA_RW(hprt0_modify, 0);
+ hprt0_modify = DWC_HPRT0_PRT_CONN_DET_RW(hprt0_modify, 0);
+ hprt0_modify = DWC_HPRT0_PRT_ENA_DIS_CHG_RW(hprt0_modify, 0);
+ hprt0_modify = DWC_HPRT0_PRT_OVRCURR_CHG_RW(hprt0_modify, 0);
+
+ /* Port connect detected interrupt */
+ if (DWC_HPRT0_PRT_CONN_DET_RD(hprt0)) {
+ /* Set the status flags and clear interrupt */
+ hcd->flags.b.port_connect_status_change = 1;
+ hcd->flags.b.port_connect_status = 1;
+ hprt0_modify = DWC_HPRT0_PRT_CONN_DET_RW(hprt0_modify, 1);
+
+ /* B-Device has connected, Delete the connection timer. */
+ del_timer_sync(&hcd->conn_timer);
+
+ /*
+ * The Hub driver asserts a reset when it sees port connect
+ * status change flag
+ */
+ retval |= 1;
+ }
+
+ /* Port enable changed interrupt */
+ if (DWC_HPRT0_PRT_ENA_DIS_CHG_RD(hprt0)) {
+ /* Set the internal flag if the port was disabled */
+ if (DWC_HPRT0_PRT_ENA_RD(hprt0))
+ port_enabled(hcd, hprt0);
+ else
+ hcd->flags.b.port_enable_change = 1;
+
+ /* Clear the interrupt */
+ hprt0_modify = DWC_HPRT0_PRT_ENA_DIS_CHG_RW(hprt0_modify, 1);
+ retval |= 1;
+ }
+
+ /* Overcurrent change interrupt */
+ if (DWC_HPRT0_PRT_OVRCURR_CHG_RD(hprt0)) {
+ hcd->flags.b.port_over_current_change = 1;
+ hprt0_modify = DWC_HPRT0_PRT_OVRCURR_CHG_RW(hprt0_modify, 1);
+ retval |= 1;
+ }
+
+ /* Clear the port interrupts */
+ dwc_reg_write(hcd->core_if->host_if->hprt0, 0, hprt0_modify);
+ return retval;
+}
+
+/**
+ * Gets the actual length of a transfer after the transfer halts. halt_status
+ * holds the reason for the halt.
+ *
+ * For IN transfers where halt_status is DWC_OTG_HC_XFER_COMPLETE, _short_read
+ * is set to 1 upon return if less than the requested number of bytes were
+ * transferred. Otherwise, _short_read is set to 0 upon return. _short_read may
+ * also be NULL on entry, in which case it remains unchanged.
+ */
+static u32 get_actual_xfer_length(struct dwc_hc *hc, ulong regs,
+ struct dwc_qtd *qtd,
+ enum dwc_halt_status halt_status,
+ int *_short_read)
+{
+ u32 hctsiz = 0;
+ u32 length;
+
+ if (_short_read)
+ *_short_read = 0;
+
+ hctsiz = dwc_reg_read(regs, DWC_HCTSIZ);
+ if (halt_status == DWC_OTG_HC_XFER_COMPLETE) {
+ if (hc->ep_is_in) {
+ length = hc->xfer_len - DWC_HCTSIZ_XFER_SIZE_RD(hctsiz);
+ if (_short_read)
+ *_short_read =
+ (DWC_HCTSIZ_XFER_SIZE_RD(hctsiz) != 0);
+ } else if (hc->qh->do_split) {
+ length = qtd->ssplit_out_xfer_count;
+ } else {
+ length = hc->xfer_len;
+ }
+ } else {
+ /*
+ * Must use the hctsiz.pktcnt field to determine how much data
+ * has been transferred. This field reflects the number of
+ * packets that have been transferred via the USB. This is
+ * always an integral number of packets if the transfer was
+ * halted before its normal completion. (Can't use the
+ * hctsiz.xfersize field because that reflects the number of
+ * bytes transferred via the AHB, not the USB).
+ */
+ length = (hc->start_pkt_count - DWC_HCTSIZ_PKT_CNT_RD(hctsiz)) *
+ hc->max_packet;
+ }
+ return length;
+}
+
+/**
+ * Updates the state of the URB after a Transfer Complete interrupt on the
+ * host channel. Updates the actual_length field of the URB based on the
+ * number of bytes transferred via the host channel. Sets the URB status
+ * if the data transfer is finished.
+ */
+static int update_urb_state_xfer_comp(struct dwc_hc *hc,
+ ulong regs, struct urb *urb,
+ struct dwc_qtd *qtd, int *status)
+{
+ int xfer_done = 0;
+ int short_read = 0;
+
+ urb->actual_length += get_actual_xfer_length(hc, regs, qtd,
+ DWC_OTG_HC_XFER_COMPLETE,
+ &short_read);
+
+ if (short_read || urb->actual_length == urb->transfer_buffer_length) {
+ xfer_done = 1;
+ if (short_read && (urb->transfer_flags & URB_SHORT_NOT_OK))
+ *status = -EREMOTEIO;
+ else
+ *status = 0;
+ }
+ return xfer_done;
+}
+
+/*
+ * Save the starting data toggle for the next transfer. The data toggle is
+ * saved in the QH for non-control transfers and it's saved in the QTD for
+ * control transfers.
+ */
+static void save_data_toggle(struct dwc_hc *hc, ulong regs, struct dwc_qtd *qtd)
+{
+ u32 hctsiz = 0;
+ hctsiz = dwc_reg_read(regs, DWC_HCTSIZ);
+
+ if (hc->ep_type != DWC_OTG_EP_TYPE_CONTROL) {
+ struct dwc_qh *qh = hc->qh;
+
+ if (DWC_HCTSIZ_PKT_PID_RD(hctsiz) == DWC_HCTSIZ_DATA0)
+ qh->data_toggle = DWC_OTG_HC_PID_DATA0;
+ else
+ qh->data_toggle = DWC_OTG_HC_PID_DATA1;
+ } else {
+ if (DWC_HCTSIZ_PKT_PID_RD(hctsiz) == DWC_HCTSIZ_DATA0)
+ qtd->data_toggle = DWC_OTG_HC_PID_DATA0;
+ else
+ qtd->data_toggle = DWC_OTG_HC_PID_DATA1;
+ }
+}
+
+/**
+ * Frees the first QTD in the QH's list if free_qtd is 1. For non-periodic
+ * QHs, removes the QH from the active non-periodic schedule. If any QTDs are
+ * still linked to the QH, the QH is added to the end of the inactive
+ * non-periodic schedule. For periodic QHs, removes the QH from the periodic
+ * schedule if no more QTDs are linked to the QH.
+ */
+static void deactivate_qh(struct dwc_hcd *hcd, struct dwc_qh *qh, int free_qtd)
+{
+ int continue_split = 0;
+ struct dwc_qtd *qtd;
+
+ qtd = list_entry(qh->qtd_list.next, struct dwc_qtd, qtd_list_entry);
+ if (qtd->complete_split)
+ continue_split = 1;
+ else if (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_MID ||
+ qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_END)
+ continue_split = 1;
+
+ if (free_qtd) {
+ dwc_otg_hcd_qtd_remove(qtd);
+ continue_split = 0;
+ }
+
+ qh->channel = NULL;
+ qh->qtd_in_process = NULL;
+ dwc_otg_hcd_qh_deactivate(hcd, qh, continue_split);
+}
+
+/**
+ * Updates the state of an Isochronous URB when the transfer is stopped for
+ * any reason. The fields of the current entry in the frame descriptor array
+ * are set based on the transfer state and the input status. Completes the
+ * Isochronous URB if all the URB frames have been completed.
+ */
+static enum dwc_halt_status update_isoc_urb_state(struct dwc_hcd *hcd,
+ struct dwc_hc *hc, u32 regs,
+ struct dwc_qtd *qtd,
+ enum dwc_halt_status status)
+{
+ struct urb *urb = qtd->urb;
+ enum dwc_halt_status ret_val = status;
+ struct usb_iso_packet_descriptor *frame_desc;
+ frame_desc = &urb->iso_frame_desc[qtd->isoc_frame_index];
+
+ switch (status) {
+ case DWC_OTG_HC_XFER_COMPLETE:
+ frame_desc->status = 0;
+ frame_desc->actual_length =
+ get_actual_xfer_length(hc, regs, qtd, status, NULL);
+ break;
+ case DWC_OTG_HC_XFER_FRAME_OVERRUN:
+ urb->error_count++;
+ if (hc->ep_is_in)
+ frame_desc->status = -ENOSR;
+ else
+ frame_desc->status = -ECOMM;
+
+ frame_desc->actual_length = 0;
+ break;
+ case DWC_OTG_HC_XFER_BABBLE_ERR:
+ /* Don't need to update actual_length in this case. */
+ urb->error_count++;
+ frame_desc->status = -EOVERFLOW;
+ break;
+ case DWC_OTG_HC_XFER_XACT_ERR:
+ urb->error_count++;
+ frame_desc->status = -EPROTO;
+ frame_desc->actual_length =
+ get_actual_xfer_length(hc, regs, qtd, status, NULL);
+ default:
+ pr_err("%s: Unhandled halt_status (%d)\n", __func__, status);
+ BUG();
+ break;
+ }
+
+ if (++qtd->isoc_frame_index == urb->number_of_packets) {
+ /*
+ * urb->status is not used for isoc transfers.
+ * The individual frame_desc statuses are used instead.
+ */
+ dwc_otg_hcd_complete_urb(hcd, urb, 0);
+ ret_val = DWC_OTG_HC_XFER_URB_COMPLETE;
+ } else {
+ ret_val = DWC_OTG_HC_XFER_COMPLETE;
+ }
+ return ret_val;
+}
+
+/**
+ * Releases a host channel for use by other transfers. Attempts to select and
+ * queue more transactions since at least one host channel is available.
+ */
+static void release_channel(struct dwc_hcd *hcd, struct dwc_hc *hc,
+ struct dwc_qtd *qtd,
+ enum dwc_halt_status halt_status, int *must_free)
+{
+ enum dwc_transaction_type tr_type;
+ int free_qtd;
+ int deact = 1;
+ struct dwc_qh *qh;
+ int retry_delay = 1;
+
+ switch (halt_status) {
+ case DWC_OTG_HC_XFER_NYET:
+ case DWC_OTG_HC_XFER_NAK:
+ if (halt_status == DWC_OTG_HC_XFER_NYET)
+ retry_delay = nyet_deferral_delay;
+ else
+ retry_delay = nak_deferral_delay;
+ free_qtd = 0;
+ if (deferral_on && hc->do_split) {
+ qh = hc->qh;
+ if (qh)
+ deact = dwc_otg_hcd_qh_deferr(hcd, qh,
+ retry_delay);
+ }
+ break;
+ case DWC_OTG_HC_XFER_URB_COMPLETE:
+ free_qtd = 1;
+ break;
+ case DWC_OTG_HC_XFER_AHB_ERR:
+ case DWC_OTG_HC_XFER_STALL:
+ case DWC_OTG_HC_XFER_BABBLE_ERR:
+ free_qtd = 1;
+ break;
+ case DWC_OTG_HC_XFER_XACT_ERR:
+ if (qtd->error_count >= 3) {
+ free_qtd = 1;
+ dwc_otg_hcd_complete_urb(hcd, qtd->urb, -EPROTO);
+ } else {
+ free_qtd = 0;
+ }
+ break;
+ case DWC_OTG_HC_XFER_URB_DEQUEUE:
+ /*
+ * The QTD has already been removed and the QH has been
+ * deactivated. Don't want to do anything except release the
+ * host channel and try to queue more transfers.
+ */
+ goto cleanup;
+ case DWC_OTG_HC_XFER_NO_HALT_STATUS:
+ pr_err("%s: No halt_status, channel %d\n", __func__,
+ hc->hc_num);
+ free_qtd = 0;
+ break;
+ default:
+ free_qtd = 0;
+ break;
+ }
+ if (free_qtd)
+ /* must_free pre-initialized to zero */
+ *must_free = 1;
+ if (deact)
+ deactivate_qh(hcd, hc->qh, free_qtd);
+
+cleanup:
+ /*
+ * Release the host channel for use by other transfers. The cleanup
+ * function clears the channel interrupt enables and conditions, so
+ * there's no need to clear the Channel Halted interrupt separately.
+ */
+ dwc_otg_hc_cleanup(hcd->core_if, hc);
+ list_add_tail(&hc->hc_list_entry, &hcd->free_hc_list);
+ hcd->available_host_channels++;
+ /* Try to queue more transfers now that there's a free channel. */
+ if (!erratum_usb09_patched) {
+ tr_type = dwc_otg_hcd_select_transactions(hcd);
+ if (tr_type != DWC_OTG_TRANSACTION_NONE)
+ dwc_otg_hcd_queue_transactions(hcd, tr_type);
+ }
+}
+
+/**
+ * Halts a host channel. If the channel cannot be halted immediately because
+ * the request queue is full, this function ensures that the FIFO empty
+ * interrupt for the appropriate queue is enabled so that the halt request can
+ * be queued when there is space in the request queue.
+ *
+ * This function may also be called in DMA mode. In that case, the channel is
+ * simply released since the core always halts the channel automatically in
+ * DMA mode.
+ */
+static void halt_channel(struct dwc_hcd *hcd, struct dwc_hc *hc,
+ struct dwc_qtd *qtd, enum dwc_halt_status halt_status,
+ int *must_free)
+{
+ if (hcd->core_if->dma_enable) {
+ release_channel(hcd, hc, qtd, halt_status, must_free);
+ return;
+ }
+
+ /* Slave mode processing... */
+ dwc_otg_hc_halt(hcd->core_if, hc, halt_status);
+ if (hc->halt_on_queue) {
+ u32 gintmsk = 0;
+
+ if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL ||
+ hc->ep_type == DWC_OTG_EP_TYPE_BULK) {
+ /*
+ * Make sure the Non-periodic Tx FIFO empty interrupt
+ * is enabled so that the non-periodic schedule will
+ * be processed.
+ */
+ gintmsk |= DWC_INTMSK_NP_TXFIFO_EMPT;
+ dwc_reg_modify(gintmsk_reg(hcd), 0, 0, gintmsk);
+ } else {
+ /*
+ * Move the QH from the periodic queued schedule to
+ * the periodic assigned schedule. This allows the
+ * halt to be queued when the periodic schedule is
+ * processed.
+ */
+ list_move(&hc->qh->qh_list_entry,
+ &hcd->periodic_sched_assigned);
+
+ /*
+ * Make sure the Periodic Tx FIFO Empty interrupt is
+ * enabled so that the periodic schedule will be
+ * processed.
+ */
+ gintmsk |= DWC_INTMSK_P_TXFIFO_EMPTY;
+ dwc_reg_modify(gintmsk_reg(hcd), 0, 0, gintmsk);
+ }
+ }
+}
+
+/**
+ * Performs common cleanup for non-periodic transfers after a Transfer
+ * Complete interrupt. This function should be called after any endpoint type
+ * specific handling is finished to release the host channel.
+ */
+static void complete_non_periodic_xfer(struct dwc_hcd *hcd, struct dwc_hc *hc,
+ ulong regs, struct dwc_qtd *qtd,
+ enum dwc_halt_status halt_status,
+ int *must_free)
+{
+ u32 hcint;
+
+ qtd->error_count = 0;
+ hcint = dwc_reg_read(regs, DWC_HCINT);
+ if (DWC_HCINT_NYET_RESP_REC_RD(hcint)) {
+ u32 hcint_clear = 0;
+
+ hcint_clear = DWC_HCINT_NYET_RESP_REC_RW(hcint_clear, 1);
+ /*
+ * Got a NYET on the last transaction of the transfer. This
+ * means that the endpoint should be in the PING state at the
+ * beginning of the next transfer.
+ */
+ hc->qh->ping_state = 1;
+ dwc_reg_write(regs, DWC_HCINT, hcint_clear);
+ }
+
+ /*
+ * Always halt and release the host channel to make it available for
+ * more transfers. There may still be more phases for a control
+ * transfer or more data packets for a bulk transfer at this point,
+ * but the host channel is still halted. A channel will be reassigned
+ * to the transfer when the non-periodic schedule is processed after
+ * the channel is released. This allows transactions to be queued
+ * properly via dwc_otg_hcd_queue_transactions, which also enables the
+ * Tx FIFO Empty interrupt if necessary.
+ *
+ * IN transfers in Slave mode require an explicit disable to
+ * halt the channel. (In DMA mode, this call simply releases
+ * the channel.)
+ *
+ * The channel is automatically disabled by the core for OUT
+ * transfers in Slave mode.
+ */
+ if (hc->ep_is_in)
+ halt_channel(hcd, hc, qtd, halt_status, must_free);
+ else
+ release_channel(hcd, hc, qtd, halt_status, must_free);
+}
+
+/**
+ * Performs common cleanup for periodic transfers after a Transfer Complete
+ * interrupt. This function should be called after any endpoint type specific
+ * handling is finished to release the host channel.
+ */
+static void complete_periodic_xfer(struct dwc_hcd *hcd, struct dwc_hc *hc,
+ ulong regs, struct dwc_qtd *qtd,
+ enum dwc_halt_status halt_status,
+ int *must_free)
+{
+ u32 hctsiz = 0;
+
+ hctsiz = dwc_reg_read(regs, DWC_HCTSIZ);
+ qtd->error_count = 0;
+
+ /*
+ * For OUT transfers and 0 packet count, the Core halts the channel,
+ * otherwise, Flush any outstanding requests from the Tx queue.
+ */
+ if (!hc->ep_is_in || (DWC_HCTSIZ_PKT_CNT_RD(hctsiz) == 0))
+ release_channel(hcd, hc, qtd, halt_status, must_free);
+ else
+ halt_channel(hcd, hc, qtd, halt_status, must_free);
+}
+
+/**
+ * Handles a host channel Transfer Complete interrupt. This handler may be
+ * called in either DMA mode or Slave mode.
+ */
+static int handle_hc_xfercomp_intr(struct dwc_hcd *hcd, struct dwc_hc *hc,
+ ulong regs, struct dwc_qtd *qtd,
+ int *must_free)
+{
+ int urb_xfer_done;
+ enum dwc_halt_status halt_status = DWC_OTG_HC_XFER_COMPLETE;
+ struct urb *urb = qtd->urb;
+ int pipe_type = usb_pipetype(urb->pipe);
+ int status = -EINPROGRESS;
+ u32 hcintmsk = 0;
+
+ /* Handle xfer complete on CSPLIT. */
+ if (hc->qh->do_split)
+ qtd->complete_split = 0;
+
+ /* Update the QTD and URB states. */
+ switch (pipe_type) {
+ case PIPE_CONTROL:
+ switch (qtd->control_phase) {
+ case DWC_OTG_CONTROL_SETUP:
+ if (urb->transfer_buffer_length > 0)
+ qtd->control_phase = DWC_OTG_CONTROL_DATA;
+ else
+ qtd->control_phase = DWC_OTG_CONTROL_STATUS;
+ halt_status = DWC_OTG_HC_XFER_COMPLETE;
+ break;
+ case DWC_OTG_CONTROL_DATA:
+ urb_xfer_done = update_urb_state_xfer_comp(hc, regs,
+ urb, qtd,
+ &status);
+ if (urb_xfer_done)
+ qtd->control_phase = DWC_OTG_CONTROL_STATUS;
+ else
+ save_data_toggle(hc, regs, qtd);
+ halt_status = DWC_OTG_HC_XFER_COMPLETE;
+ break;
+ case DWC_OTG_CONTROL_STATUS:
+ if (status == -EINPROGRESS)
+ status = 0;
+ dwc_otg_hcd_complete_urb(hcd, urb, status);
+ halt_status = DWC_OTG_HC_XFER_URB_COMPLETE;
+ break;
+ }
+ complete_non_periodic_xfer(hcd, hc, regs, qtd,
+ halt_status, must_free);
+ break;
+ case PIPE_BULK:
+ urb_xfer_done = update_urb_state_xfer_comp(hc, regs, urb, qtd,
+ &status);
+ if (urb_xfer_done) {
+ dwc_otg_hcd_complete_urb(hcd, urb, status);
+ halt_status = DWC_OTG_HC_XFER_URB_COMPLETE;
+ } else {
+ halt_status = DWC_OTG_HC_XFER_COMPLETE;
+ }
+
+ save_data_toggle(hc, regs, qtd);
+ complete_non_periodic_xfer(hcd, hc, regs, qtd,
+ halt_status, must_free);
+ break;
+ case PIPE_INTERRUPT:
+ update_urb_state_xfer_comp(hc, regs, urb, qtd, &status);
+ /*
+ * Interrupt URB is done on the first transfer complete
+ * interrupt.
+ */
+ dwc_otg_hcd_complete_urb(hcd, urb, status);
+ save_data_toggle(hc, regs, qtd);
+ complete_periodic_xfer(hcd, hc, regs, qtd,
+ DWC_OTG_HC_XFER_URB_COMPLETE, must_free);
+ break;
+ case PIPE_ISOCHRONOUS:
+ if (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_ALL) {
+ halt_status = update_isoc_urb_state(hcd, hc, regs, qtd,
+ DWC_OTG_HC_XFER_COMPLETE);
+ }
+ complete_periodic_xfer(hcd, hc, regs, qtd,
+ halt_status, must_free);
+ break;
+ }
+
+ /* disable xfercompl */
+ hcintmsk = DWC_HCINTMSK_TXFER_CMPL_RW(hcintmsk, 1);
+ dwc_reg_modify(regs, DWC_HCINTMSK, hcintmsk, 0);
+
+ return 1;
+}
+
+/**
+ * Handles a host channel STALL interrupt. This handler may be called in
+ * either DMA mode or Slave mode.
+ */
+static int handle_hc_stall_intr(struct dwc_hcd *hcd, struct dwc_hc *hc,
+ u32 regs, struct dwc_qtd *qtd, int *must_free)
+{
+ struct urb *urb = qtd->urb;
+ int pipe_type = usb_pipetype(urb->pipe);
+ u32 hcintmsk = 0;
+
+ if (pipe_type == PIPE_CONTROL)
+ dwc_otg_hcd_complete_urb(hcd, qtd->urb, -EPIPE);
+
+ if (pipe_type == PIPE_BULK || pipe_type == PIPE_INTERRUPT) {
+ dwc_otg_hcd_complete_urb(hcd, qtd->urb, -EPIPE);
+ /*
+ * USB protocol requires resetting the data toggle for bulk
+ * and interrupt endpoints when a CLEAR_FEATURE(ENDPOINT_HALT)
+ * setup command is issued to the endpoint. Anticipate the
+ * CLEAR_FEATURE command since a STALL has occurred and reset
+ * the data toggle now.
+ */
+ hc->qh->data_toggle = 0;
+ }
+
+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_STALL, must_free);
+ /* disable stall */
+ hcintmsk = DWC_HCINTMSK_STALL_RESP_REC_RW(hcintmsk, 1);
+ dwc_reg_modify(regs, DWC_HCINTMSK, hcintmsk, 0);
+
+ return 1;
+}
+
+/**
+ * Updates the state of the URB when a transfer has been stopped due to an
+ * abnormal condition before the transfer completes. Modifies the
+ * actual_length field of the URB to reflect the number of bytes that have
+ * actually been transferred via the host channel.
+ */
+static void update_urb_state_xfer_intr(struct dwc_hc *hc,
+ u32 regs, struct urb *urb,
+ struct dwc_qtd *qtd,
+ enum dwc_halt_status sts)
+{
+ u32 xfr_len = get_actual_xfer_length(hc, regs, qtd, sts, NULL);
+ urb->actual_length += xfr_len;
+}
+
+/**
+ * Handles a host channel NAK interrupt. This handler may be called in either
+ * DMA mode or Slave mode.
+ */
+static int handle_hc_nak_intr(struct dwc_hcd *hcd, struct dwc_hc *hc,
+ u32 regs, struct dwc_qtd *qtd, int *must_free)
+{
+ u32 hcintmsk = 0;
+
+ /*
+ * Handle NAK for IN/OUT SSPLIT/CSPLIT transfers, bulk, control, and
+ * interrupt. Re-start the SSPLIT transfer.
+ */
+ if (hc->do_split) {
+ if (hc->complete_split)
+ qtd->error_count = 0;
+
+ qtd->complete_split = 0;
+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK, must_free);
+ goto handle_nak_done;
+ }
+ switch (usb_pipetype(qtd->urb->pipe)) {
+ case PIPE_CONTROL:
+ case PIPE_BULK:
+ if (hcd->core_if->dma_enable && hc->ep_is_in) {
+ /*
+ * NAK interrupts are enabled on bulk/control IN
+ * transfers in DMA mode for the sole purpose of
+ * resetting the error count after a transaction error
+ * occurs. The core will continue transferring data.
+ */
+ qtd->error_count = 0;
+ goto handle_nak_done;
+ }
+
+ /*
+ * NAK interrupts normally occur during OUT transfers in DMA
+ * or Slave mode. For IN transfers, more requests will be
+ * queued as request queue space is available.
+ */
+ qtd->error_count = 0;
+ if (!hc->qh->ping_state) {
+ update_urb_state_xfer_intr(hc, regs, qtd->urb, qtd,
+ DWC_OTG_HC_XFER_NAK);
+
+ save_data_toggle(hc, regs, qtd);
+ if (qtd->urb->dev->speed == USB_SPEED_HIGH)
+ hc->qh->ping_state = 1;
+ }
+
+ /*
+ * Halt the channel so the transfer can be re-started from
+ * the appropriate point or the PING protocol will
+ * start/continue.
+ */
+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK, must_free);
+ break;
+ case PIPE_INTERRUPT:
+ qtd->error_count = 0;
+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK, must_free);
+ break;
+ case PIPE_ISOCHRONOUS:
+ /* Should never get called for isochronous transfers. */
+ BUG();
+ break;
+ }
+
+handle_nak_done:
+ /* disable nak */
+ hcintmsk = DWC_HCINTMSK_NAK_RESP_REC_RW(hcintmsk, 1);
+ dwc_reg_modify(regs, DWC_HCINTMSK, hcintmsk, 0);
+
+ return 1;
+}
+
+/**
+ * Helper function for handle_hc_ack_intr(). Sets the split values for an ACK
+ * on SSPLIT for ISOC OUT.
+ */
+static void set_isoc_out_vals(struct dwc_hc *hc, struct dwc_qtd *qtd)
+{
+ struct usb_iso_packet_descriptor *frame_desc;
+
+ switch (hc->xact_pos) {
+ case DWC_HCSPLIT_XACTPOS_ALL:
+ break;
+ case DWC_HCSPLIT_XACTPOS_END:
+ qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL;
+ qtd->isoc_split_offset = 0;
+ break;
+ case DWC_HCSPLIT_XACTPOS_BEGIN:
+ case DWC_HCSPLIT_XACTPOS_MID:
+ /*
+ * For BEGIN or MID, calculate the length for the next
+ * microframe to determine the correct SSPLIT token, either MID
+ * or END.
+ */
+ frame_desc = &qtd->urb->iso_frame_desc[qtd->isoc_frame_index];
+ qtd->isoc_split_offset += 188;
+
+ if ((frame_desc->length - qtd->isoc_split_offset) <= 188)
+ qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_END;
+ else
+ qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_MID;
+
+ break;
+ }
+}
+
+/**
+ * Handles a host channel ACK interrupt. This interrupt is enabled when
+ * performing the PING protocol in Slave mode, when errors occur during
+ * either Slave mode or DMA mode, and during Start Split transactions.
+ */
+static int handle_hc_ack_intr(struct dwc_hcd *hcd, struct dwc_hc *hc,
+ u32 regs, struct dwc_qtd *qtd, int *must_free)
+{
+ u32 hcintmsk = 0;
+
+ if (hc->do_split) {
+ /* Handle ACK on SSPLIT. ACK should not occur in CSPLIT. */
+ if (!hc->ep_is_in && hc->data_pid_start != DWC_OTG_HC_PID_SETUP)
+ qtd->ssplit_out_xfer_count = hc->xfer_len;
+
+ /* Don't need complete for isochronous out transfers. */
+ if (!(hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in))
+ qtd->complete_split = 1;
+
+ if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in)
+ set_isoc_out_vals(hc, qtd);
+ else
+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK,
+ must_free);
+ } else {
+ qtd->error_count = 0;
+ if (hc->qh->ping_state) {
+ hc->qh->ping_state = 0;
+
+ /*
+ * Halt the channel so the transfer can be re-started
+ * from the appropriate point. This only happens in
+ * Slave mode. In DMA mode, the ping_state is cleared
+ * when the transfer is started because the core
+ * automatically executes the PING, then the transfer.
+ */
+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK,
+ must_free);
+ }
+ }
+
+ /*
+ * If the ACK occurred when _not_ in the PING state, let the channel
+ * continue transferring data after clearing the error count.
+ */
+ /* disable ack */
+ hcintmsk = DWC_HCINTMSK_ACK_RESP_REC_RW(hcintmsk, 1);
+ dwc_reg_modify(regs, DWC_HCINTMSK, hcintmsk, 0);
+
+ return 1;
+}
+
+/**
+ * Handles a host channel NYET interrupt. This interrupt should only occur on
+ * Bulk and Control OUT endpoints and for complete split transactions. If a
+ * NYET occurs at the same time as a Transfer Complete interrupt, it is
+ * handled in the xfercomp interrupt handler, not here. This handler may be
+ * called in either DMA mode or Slave mode.
+ */
+static int handle_hc_nyet_intr(struct dwc_hcd *hcd, struct dwc_hc *hc,
+ u32 regs, struct dwc_qtd *qtd, int *must_free)
+{
+ u32 hcintmsk = 0;
+ u32 hcint_clear = 0;
+
+ /*
+ * NYET on CSPLIT
+ * re-do the CSPLIT immediately on non-periodic
+ */
+ if (hc->do_split && hc->complete_split) {
+ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
+ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
+ int frnum =
+ dwc_otg_hcd_get_frame_number(dwc_otg_hcd_to_hcd
+ (hcd));
+ if (dwc_full_frame_num(frnum) !=
+ dwc_full_frame_num(hc->qh->sched_frame)) {
+ qtd->complete_split = 0;
+ halt_channel(hcd, hc, qtd,
+ DWC_OTG_HC_XFER_XACT_ERR,
+ must_free);
+ goto handle_nyet_done;
+ }
+ }
+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET, must_free);
+ goto handle_nyet_done;
+ }
+ hc->qh->ping_state = 1;
+ qtd->error_count = 0;
+ update_urb_state_xfer_intr(hc, regs, qtd->urb, qtd,
+ DWC_OTG_HC_XFER_NYET);
+ save_data_toggle(hc, regs, qtd);
+ /*
+ * Halt the channel and re-start the transfer so the PING
+ * protocol will start.
+ */
+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET, must_free);
+
+handle_nyet_done:
+ /* disable nyet */
+ hcintmsk = DWC_HCINTMSK_NYET_RESP_REC_RW(hcintmsk, 1);
+ dwc_reg_modify(regs, DWC_HCINTMSK, hcintmsk, 0);
+ /* clear nyet */
+ hcint_clear = DWC_HCINT_NYET_RESP_REC_RW(hcint_clear, 1);
+ dwc_reg_write(regs, DWC_HCINT, hcint_clear);
+ return 1;
+}
+
+/**
+ * Handles a host channel babble interrupt. This handler may be called in
+ * either DMA mode or Slave mode.
+ */
+static int handle_hc_babble_intr(struct dwc_hcd *hcd, struct dwc_hc *hc,
+ u32 regs, struct dwc_qtd *qtd, int *must_free)
+{
+ u32 hcintmsk = 0;
+
+ if (hc->ep_type != DWC_OTG_EP_TYPE_ISOC) {
+ dwc_otg_hcd_complete_urb(hcd, qtd->urb, -EOVERFLOW);
+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_BABBLE_ERR,
+ must_free);
+ } else {
+ enum dwc_halt_status halt_status;
+ halt_status = update_isoc_urb_state(hcd, hc, regs, qtd,
+ DWC_OTG_HC_XFER_BABBLE_ERR);
+ halt_channel(hcd, hc, qtd, halt_status, must_free);
+ }
+ /* disable bblerr */
+ hcintmsk = DWC_HCINTMSK_BBL_ERR_RW(hcintmsk, 1);
+ dwc_reg_modify(regs, DWC_HCINTMSK, hcintmsk, 0);
+ return 1;
+}
+
+/**
+ * Handles a host channel AHB error interrupt. This handler is only called in
+ * DMA mode.
+ */
+static int handle_hc_ahberr_intr(struct dwc_hcd *hcd, struct dwc_hc *hc,
+ u32 regs, struct dwc_qtd *qtd)
+{
+ u32 hcchar;
+ u32 hcsplt;
+ u32 hctsiz = 0;
+ u32 hcdma;
+ struct urb *urb = qtd->urb;
+ u32 hcintmsk = 0;
+
+ hcchar = dwc_reg_read(regs, DWC_HCCHAR);
+ hcsplt = dwc_reg_read(regs, DWC_HCSPLT);
+ hctsiz = dwc_reg_read(regs, DWC_HCTSIZ);
+ hcdma = dwc_reg_read(regs, DWC_HCDMA);
+
+ pr_err("AHB ERROR, Channel %d\n", hc->hc_num);
+ pr_err(" hcchar 0x%08x, hcsplt 0x%08x\n", hcchar, hcsplt);
+ pr_err(" hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz, hcdma);
+
+ pr_err(" Device address: %d\n", usb_pipedevice(urb->pipe));
+ pr_err(" Endpoint: %d, %s\n", usb_pipeendpoint(urb->pipe),
+ (usb_pipein(urb->pipe) ? "IN" : "OUT"));
+
+ pr_err(" Endpoint type: %s\n", pipetype_str(urb->pipe));
+ pr_err(" Speed: %s\n", dev_speed_str(urb->dev->speed));
+ pr_err(" Max packet size: %d\n",
+ usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)));
+ pr_err(" Data buffer length: %d\n", urb->transfer_buffer_length);
+ pr_err(" Transfer buffer: %p, Transfer DMA: %p\n",
+ urb->transfer_buffer, (void *)(u32) urb->transfer_dma);
+ pr_err(" Setup buffer: %p, Setup DMA: %p\n",
+ urb->setup_packet, (void *)(u32) urb->setup_dma);
+ pr_err(" Interval: %d\n", urb->interval);
+
+ dwc_otg_hcd_complete_urb(hcd, urb, -EIO);
+
+ /*
+ * Force a channel halt. Don't call halt_channel because that won't
+ * write to the HCCHARn register in DMA mode to force the halt.
+ */
+ dwc_otg_hc_halt(hcd->core_if, hc, DWC_OTG_HC_XFER_AHB_ERR);
+ /* disable ahberr */
+ hcintmsk = DWC_HCINTMSK_AHB_ERR_RW(hcintmsk, 1);
+ dwc_reg_modify(regs, DWC_HCINTMSK, hcintmsk, 0);
+
+ return 1;
+}
+
+/**
+ * Handles a host channel transaction error interrupt. This handler may be
+ * called in either DMA mode or Slave mode.
+ */
+static int handle_hc_xacterr_intr(struct dwc_hcd *hcd, struct dwc_hc *hc,
+ u32 regs, struct dwc_qtd *qtd, int *must_free)
+{
+ enum dwc_halt_status status = DWC_OTG_HC_XFER_XACT_ERR;
+ u32 hcintmsk = 0;
+
+ switch (usb_pipetype(qtd->urb->pipe)) {
+ case PIPE_CONTROL:
+ case PIPE_BULK:
+ qtd->error_count++;
+ if (!hc->qh->ping_state) {
+ update_urb_state_xfer_intr(hc, regs, qtd->urb, qtd,
+ status);
+ save_data_toggle(hc, regs, qtd);
+
+ if (!hc->ep_is_in && qtd->urb->dev->speed ==
+ USB_SPEED_HIGH)
+ hc->qh->ping_state = 1;
+ }
+ /*
+ * Halt the channel so the transfer can be re-started from
+ * the appropriate point or the PING protocol will start.
+ */
+ halt_channel(hcd, hc, qtd, status, must_free);
+ break;
+ case PIPE_INTERRUPT:
+ qtd->error_count++;
+ if (hc->do_split && hc->complete_split)
+ qtd->complete_split = 0;
+
+ halt_channel(hcd, hc, qtd, status, must_free);
+ break;
+ case PIPE_ISOCHRONOUS:
+ status = update_isoc_urb_state(hcd, hc, regs, qtd, status);
+ halt_channel(hcd, hc, qtd, status, must_free);
+ break;
+ }
+ /* Disable xacterr */
+ hcintmsk = DWC_HCINTMSK_TRANS_ERR_RW(hcintmsk, 1);
+ dwc_reg_modify(regs, DWC_HCINTMSK, hcintmsk, 0);
+
+ return 1;
+}
+
+/**
+ * Handles a host channel frame overrun interrupt. This handler may be called
+ * in either DMA mode or Slave mode.
+ */
+static int handle_hc_frmovrun_intr(struct dwc_hcd *hcd, struct dwc_hc *hc,
+ u32 regs, struct dwc_qtd *qtd,
+ int *must_free)
+{
+ enum dwc_halt_status status = DWC_OTG_HC_XFER_FRAME_OVERRUN;
+ u32 hcintmsk = 0;
+
+ switch (usb_pipetype(qtd->urb->pipe)) {
+ case PIPE_CONTROL:
+ case PIPE_BULK:
+ break;
+ case PIPE_INTERRUPT:
+ halt_channel(hcd, hc, qtd, status, must_free);
+ break;
+ case PIPE_ISOCHRONOUS:
+ status = update_isoc_urb_state(hcd, hc, regs, qtd, status);
+ halt_channel(hcd, hc, qtd, status, must_free);
+ break;
+ }
+ /* Disable frmovrun */
+ hcintmsk = DWC_HCINTMSK_FRAME_OVERN_ERR_RW(hcintmsk, 1);
+ dwc_reg_modify(regs, DWC_HCINTMSK, hcintmsk, 0);
+
+ return 1;
+}
+
+/**
+ * Handles a host channel data toggle error interrupt. This handler may be
+ * called in either DMA mode or Slave mode.
+ */
+static int handle_hc_datatglerr_intr(struct dwc_hcd *hcd, struct dwc_hc *hc,
+ u32 regs, struct dwc_qtd *qtd)
+{
+ u32 hcintmsk = 0;
+
+ if (hc->ep_is_in)
+ qtd->error_count = 0;
+ else
+ pr_err("Data Toggle Error on OUT transfer, channel "
+ "%d\n", hc->hc_num);
+
+ /* disable datatglerr */
+ hcintmsk = DWC_HCINTMSK_DATA_TOG_ERR_RW(hcintmsk, 1);
+ dwc_reg_modify(regs, DWC_HCINTMSK, hcintmsk, 0);
+
+ return 1;
+}
+
+/**
+ * Handles a host Channel Halted interrupt in DMA mode. This handler
+ * determines the reason the channel halted and proceeds accordingly.
+ */
+static void handle_hc_chhltd_intr_dma(struct dwc_hcd *hcd, struct dwc_hc *hc,
+ ulong regs, struct dwc_qtd *qtd,
+ int *must_free)
+{
+ u32 hcint;
+ u32 hcintmsk = 0;
+
+ if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE ||
+ hc->halt_status == DWC_OTG_HC_XFER_AHB_ERR) {
+ /*
+ * Just release the channel. A dequeue can happen on a
+ * transfer timeout. In the case of an AHB Error, the channel
+ * was forced to halt because there's no way to gracefully
+ * recover.
+ */
+ release_channel(hcd, hc, qtd, hc->halt_status, must_free);
+ return;
+ }
+
+ /* Read the HCINTn register to determine the cause for the halt. */
+ hcint = dwc_reg_read(regs, DWC_HCINT);
+ hcintmsk = dwc_reg_read(regs, DWC_HCINTMSK);
+ if (DWC_HCINT_TXFER_CMPL_RD(hcint)) {
+ /*
+ * This is here because of a possible hardware bug. Spec
+ * says that on SPLIT-ISOC OUT transfers in DMA mode that a HALT
+ * interrupt w/ACK bit set should occur, but I only see the
+ * XFERCOMP bit, even with it masked out. This is a workaround
+ * for that behavior. Should fix this when hardware is fixed.
+ */
+ if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in)
+ handle_hc_ack_intr(hcd, hc, regs, qtd, must_free);
+
+ handle_hc_xfercomp_intr(hcd, hc, regs, qtd, must_free);
+ } else if (DWC_HCINT_STALL_RESP_REC_RD(hcint)) {
+ handle_hc_stall_intr(hcd, hc, regs, qtd, must_free);
+ } else if (DWC_HCINT_TRANS_ERR_RD(hcint)) {
+ /*
+ * Must handle xacterr before nak or ack. Could get a xacterr
+ * at the same time as either of these on a BULK/CONTROL OUT
+ * that started with a PING. The xacterr takes precedence.
+ */
+ handle_hc_xacterr_intr(hcd, hc, regs, qtd, must_free);
+ } else if (DWC_HCINT_NYET_RESP_REC_RD(hcint)) {
+ /*
+ * Must handle nyet before nak or ack. Could get a nyet at the
+ * same time as either of those on a BULK/CONTROL OUT that
+ * started with a PING. The nyet takes precedence.
+ */
+ handle_hc_nyet_intr(hcd, hc, regs, qtd, must_free);
+ } else if (DWC_HCINT_BBL_ERR_RD(hcint)) {
+ handle_hc_babble_intr(hcd, hc, regs, qtd, must_free);
+ } else if (DWC_HCINT_FRAME_OVERN_ERR_RD(hcint)) {
+ handle_hc_frmovrun_intr(hcd, hc, regs, qtd, must_free);
+ } else if (DWC_HCINT_DATA_TOG_ERR_RD(hcint)) {
+ handle_hc_datatglerr_intr(hcd, hc, regs, qtd);
+ hc->qh->data_toggle = 0;
+ halt_channel(hcd, hc, qtd, hc->halt_status, must_free);
+ } else if (DWC_HCINT_NAK_RESP_REC_RD(hcint) &&
+ !DWC_HCINTMSK_NAK_RESP_REC_RD(hcintmsk)) {
+ /*
+ * If nak is not masked, it's because a non-split IN transfer
+ * is in an error state. In that case, the nak is handled by
+ * the nak interrupt handler, not here. Handle nak here for
+ * BULK/CONTROL OUT transfers, which halt on a NAK to allow
+ * rewinding the buffer pointer.
+ */
+ handle_hc_nak_intr(hcd, hc, regs, qtd, must_free);
+ } else if (DWC_HCINT_ACK_RESP_REC_RD(hcint) &&
+ !DWC_HCINTMSK_ACK_RESP_REC_RD(hcintmsk)) {
+ /*
+ * If ack is not masked, it's because a non-split IN transfer
+ * is in an error state. In that case, the ack is handled by
+ * the ack interrupt handler, not here. Handle ack here for
+ * split transfers. Start splits halt on ACK.
+ */
+ handle_hc_ack_intr(hcd, hc, regs, qtd, must_free);
+ } else {
+ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
+ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
+ /*
+ * A periodic transfer halted with no other channel
+ * interrupts set. Assume it was halted by the core
+ * because it could not be completed in its scheduled
+ * (micro)frame.
+ */
+ halt_channel(hcd, hc, qtd,
+ DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE,
+ must_free);
+ } else {
+ pr_err("%s: Channel %d, DMA Mode -- ChHltd "
+ "set, but reason for halting is unknown, "
+ "hcint 0x%08x, intsts 0x%08x\n",
+ __func__, hc->hc_num, hcint,
+ dwc_reg_read(gintsts_reg(hcd), 0));
+ }
+ }
+}
+
+/**
+ * Handles a host channel Channel Halted interrupt.
+ *
+ * In slave mode, this handler is called only when the driver specifically
+ * requests a halt. This occurs during handling other host channel interrupts
+ * (e.g. nak, xacterr, stall, nyet, etc.).
+ *
+ * In DMA mode, this is the interrupt that occurs when the core has finished
+ * processing a transfer on a channel. Other host channel interrupts (except
+ * ahberr) are disabled in DMA mode.
+ */
+static int handle_hc_chhltd_intr(struct dwc_hcd *hcd, struct dwc_hc *hc,
+ ulong regs, struct dwc_qtd *qtd, int *must_free)
+{
+ if (hcd->core_if->dma_enable)
+ handle_hc_chhltd_intr_dma(hcd, hc, regs, qtd, must_free);
+ else
+ release_channel(hcd, hc, qtd, hc->halt_status, must_free);
+
+ return 1;
+}
+
+/* Handles interrupt for a specific Host Channel */
+static int dwc_otg_hcd_handle_hc_n_intr(struct dwc_hcd *hcd, u32 num)
+{
+ int must_free = 0;
+ int retval = 0;
+ u32 hcint;
+ u32 hcintmsk = 0;
+ struct dwc_hc *hc;
+ ulong hc_regs;
+ struct dwc_qtd *qtd;
+
+ hc = hcd->hc_ptr_array[num];
+ hc_regs = hcd->core_if->host_if->hc_regs[num];
+ qtd = list_entry(hc->qh->qtd_list.next, struct dwc_qtd, qtd_list_entry);
+
+ hcint = dwc_reg_read(hc_regs, DWC_HCINT);
+ hcintmsk = dwc_reg_read(hc_regs, DWC_HCINTMSK);
+
+ hcint = hcint & hcintmsk;
+ if (!hcd->core_if->dma_enable && DWC_HCINT_CHAN_HALTED_RD(hcint)
+ && hcint != 0x2)
+ hcint = DWC_HCINT_CHAN_HALTED_RW(hcint, 0);
+
+ if (DWC_HCINT_TXFER_CMPL_RD(hcint)) {
+ retval |= handle_hc_xfercomp_intr(hcd, hc, hc_regs,
+ qtd, &must_free);
+ /*
+ * If NYET occurred at same time as Xfer Complete, the NYET is
+ * handled by the Xfer Complete interrupt handler. Don't want
+ * to call the NYET interrupt handler in this case.
+ */
+ hcint = DWC_HCINT_NYET_RESP_REC_RW(hcint, 0);
+ }
+
+ if (DWC_HCINT_CHAN_HALTED_RD(hcint))
+ retval |= handle_hc_chhltd_intr(hcd, hc, hc_regs,
+ qtd, &must_free);
+ if (DWC_HCINT_AHB_ERR_RD(hcint))
+ retval |= handle_hc_ahberr_intr(hcd, hc, hc_regs, qtd);
+ if (DWC_HCINT_STALL_RESP_REC_RD(hcint))
+ retval |= handle_hc_stall_intr(hcd, hc, hc_regs,
+ qtd, &must_free);
+ if (DWC_HCINT_NAK_RESP_REC_RD(hcint))
+ retval |= handle_hc_nak_intr(hcd, hc, hc_regs, qtd, &must_free);
+ if (DWC_HCINT_ACK_RESP_REC_RD(hcint))
+ retval |= handle_hc_ack_intr(hcd, hc, hc_regs, qtd, &must_free);
+ if (DWC_HCINT_NYET_RESP_REC_RD(hcint))
+ retval |= handle_hc_nyet_intr(hcd, hc, hc_regs,
+ qtd, &must_free);
+ if (DWC_HCINT_TRANS_ERR_RD(hcint))
+ retval |= handle_hc_xacterr_intr(hcd, hc, hc_regs,
+ qtd, &must_free);
+ if (DWC_HCINT_BBL_ERR_RD(hcint))
+ retval |= handle_hc_babble_intr(hcd, hc, hc_regs,
+ qtd, &must_free);
+ if (DWC_HCINT_FRAME_OVERN_ERR_RD(hcint))
+ retval |= handle_hc_frmovrun_intr(hcd, hc, hc_regs,
+ qtd, &must_free);
+ if (DWC_HCINT_DATA_TOG_ERR_RD(hcint))
+ retval |= handle_hc_datatglerr_intr(hcd, hc, hc_regs, qtd);
+
+ if (must_free)
+ /* Free the qtd here now that we are done using it. */
+ dwc_otg_hcd_qtd_free(qtd);
+ return retval;
+}
+
+/**
+ * This function returns the Host All Channel Interrupt register
+ */
+static inline u32 dwc_otg_read_host_all_channels_intr(struct core_if
+ *core_if)
+{
+ return dwc_reg_read(core_if->host_if->host_global_regs, DWC_HAINT);
+}
+
+/**
+ * This interrupt indicates that one or more host channels has a pending
+ * interrupt. There are multiple conditions that can cause each host channel
+ * interrupt. This function determines which conditions have occurred for each
+ * host channel interrupt and handles them appropriately.
+ */
+static int dwc_otg_hcd_handle_hc_intr(struct dwc_hcd *hcd)
+{
+ u32 i;
+ int retval = 0;
+ u32 haint;
+
+ /*
+ * Clear appropriate bits in HCINTn to clear the interrupt bit in
+ * GINTSTS
+ */
+ haint = dwc_otg_read_host_all_channels_intr(hcd->core_if);
+ for (i = 0; i < hcd->core_if->core_params->host_channels; i++)
+ if (DWC_HAINT_RD(haint) & (1 << i))
+ retval |= dwc_otg_hcd_handle_hc_n_intr(hcd, i);
+
+ return retval;
+}
+
+/* This function handles interrupts for the HCD.*/
+int dwc_otg_hcd_handle_intr(struct dwc_hcd *hcd)
+{
+ int ret = 0;
+ struct core_if *core_if = hcd->core_if;
+ u32 gintsts;
+
+ /* Check if HOST Mode */
+ if (dwc_otg_is_host_mode(core_if)) {
+ spin_lock(&hcd->lock);
+ gintsts = dwc_otg_read_core_intr(core_if);
+ if (!gintsts) {
+ spin_unlock(&hcd->lock);
+ return IRQ_NONE;
+ }
+
+ if (gintsts & DWC_INTMSK_STRT_OF_FRM)
+ ret |= dwc_otg_hcd_handle_sof_intr(hcd);
+ if (gintsts & DWC_INTMSK_RXFIFO_NOT_EMPT)
+ ret |= dwc_otg_hcd_handle_rx_status_q_level_intr(hcd);
+ if (gintsts & DWC_INTMSK_NP_TXFIFO_EMPT)
+ ret |= dwc_otg_hcd_handle_np_tx_fifo_empty_intr(hcd);
+ if (gintsts & DWC_INTMSK_HST_PORT)
+ ret |= dwc_otg_hcd_handle_port_intr(hcd);
+ if (gintsts & DWC_INTMSK_HST_CHAN)
+ ret |= dwc_otg_hcd_handle_hc_intr(hcd);
+ if (gintsts & DWC_INTMSK_P_TXFIFO_EMPTY)
+ ret |= dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(hcd);
+
+ spin_unlock(&hcd->lock);
+ }
+ return ret;
+}
diff --git a/drivers/usb/dwc/hcd_queue.c b/drivers/usb/dwc/hcd_queue.c
new file mode 100644
index 0000000..67f0409
--- /dev/null
+++ b/drivers/usb/dwc/hcd_queue.c
@@ -0,0 +1,696 @@
+/*
+ * DesignWare HS OTG controller driver
+ * Copyright (C) 2006 Synopsys, Inc.
+ * Portions Copyright (C) 2010 Applied Micro Circuits Corporation.
+ *
+ * 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 version 2 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
+ * or write to the Free Software Foundation, Inc., 51 Franklin Street,
+ * Suite 500, Boston, MA 02110-1335 USA.
+ *
+ * Based on Synopsys driver version 2.60a
+ * Modified by Mark Miesfeld <mmiesfeld@apm.com>
+ * Modified by Stefan Roese <sr@denx.de>, DENX Software Engineering
+ * Modified by Chuck Meade <chuck@theptrgroup.com>
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL SYNOPSYS, INC. 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.
+ *
+ */
+
+/*
+ * This file contains the functions to manage Queue Heads and Queue
+ * Transfer Descriptors.
+ */
+
+#include "hcd.h"
+
+static inline int is_fs_ls(enum usb_device_speed speed)
+{
+ return speed == USB_SPEED_FULL || speed == USB_SPEED_LOW;
+}
+
+/* Allocates memory for a QH structure. */
+static inline struct dwc_qh *dwc_otg_hcd_qh_alloc(void)
+{
+ return kmalloc(sizeof(struct dwc_qh), GFP_ATOMIC);
+}
+
+/**
+ * Initializes a QH structure to initialize the QH.
+ */
+#define SCHEDULE_SLOP 10
+static void dwc_otg_hcd_qh_init(struct dwc_hcd *hcd, struct dwc_qh *qh,
+ struct urb *urb)
+{
+ memset(qh, 0, sizeof(struct dwc_qh));
+
+ /* Initialize QH */
+ switch (usb_pipetype(urb->pipe)) {
+ case PIPE_CONTROL:
+ qh->ep_type = USB_ENDPOINT_XFER_CONTROL;
+ break;
+ case PIPE_BULK:
+ qh->ep_type = USB_ENDPOINT_XFER_BULK;
+ break;
+ case PIPE_ISOCHRONOUS:
+ qh->ep_type = USB_ENDPOINT_XFER_ISOC;
+ break;
+ case PIPE_INTERRUPT:
+ qh->ep_type = USB_ENDPOINT_XFER_INT;
+ break;
+ }
+
+ qh->ep_is_in = usb_pipein(urb->pipe) ? 1 : 0;
+ qh->data_toggle = DWC_OTG_HC_PID_DATA0;
+ qh->maxp = usb_maxpacket(urb->dev, urb->pipe, !(usb_pipein(urb->pipe)));
+
+ INIT_LIST_HEAD(&qh->qtd_list);
+ INIT_LIST_HEAD(&qh->qh_list_entry);
+
+ qh->channel = NULL;
+ qh->speed = urb->dev->speed;
+
+ /*
+ * FS/LS Enpoint on HS Hub NOT virtual root hub
+ */
+ qh->do_split = 0;
+ if (is_fs_ls(urb->dev->speed) && urb->dev->tt && urb->dev->tt->hub &&
+ urb->dev->tt->hub->devnum != 1)
+ qh->do_split = 1;
+
+ if (qh->ep_type == USB_ENDPOINT_XFER_INT ||
+ qh->ep_type == USB_ENDPOINT_XFER_ISOC) {
+ /* Compute scheduling parameters once and save them. */
+ u32 hprt;
+ int bytecount = dwc_hb_mult(qh->maxp) *
+ dwc_max_packet(qh->maxp);
+
+ qh->usecs = NS_TO_US(usb_calc_bus_time(urb->dev->speed,
+ usb_pipein(urb->pipe),
+ (qh->ep_type ==
+ USB_ENDPOINT_XFER_ISOC),
+ bytecount));
+
+ /* Start in a slightly future (micro)frame. */
+ qh->sched_frame = dwc_frame_num_inc(hcd->frame_number,
+ SCHEDULE_SLOP);
+ qh->interval = urb->interval;
+
+ hprt = dwc_reg_read(hcd->core_if->host_if->hprt0, 0);
+ if (DWC_HPRT0_PRT_SPD_RD(hprt) == DWC_HPRT0_PRTSPD_HIGH_SPEED &&
+ is_fs_ls(urb->dev->speed)) {
+ qh->interval *= 8;
+ qh->sched_frame |= 0x7;
+ qh->start_split_frame = qh->sched_frame;
+ }
+ }
+}
+
+/**
+ * This function allocates and initializes a QH.
+ */
+static struct dwc_qh *dwc_otg_hcd_qh_create(struct dwc_hcd *hcd,
+ struct urb *urb)
+{
+ struct dwc_qh *qh;
+
+ /* Allocate memory */
+ qh = dwc_otg_hcd_qh_alloc();
+ if (qh == NULL)
+ return NULL;
+
+ dwc_otg_hcd_qh_init(hcd, qh, urb);
+ return qh;
+}
+
+/**
+ * Free each QTD in the QH's QTD-list then free the QH. QH should already be
+ * removed from a list. QTD list should already be empty if called from URB
+ * Dequeue.
+ */
+void dwc_otg_hcd_qh_free(struct dwc_qh *qh)
+{
+ struct dwc_qtd *qtd;
+ struct list_head *pos, *temp;
+
+ /* Free each QTD in the QTD list */
+ list_for_each_safe(pos, temp, &qh->qtd_list) {
+ list_del(pos);
+ qtd = dwc_list_to_qtd(pos);
+ dwc_otg_hcd_qtd_free(qtd);
+ }
+ kfree(qh);
+}
+
+/**
+ * Microframe scheduler
+ * track the total use in hcd->frame_usecs
+ * keep each qh use in qh->frame_usecs
+ * when surrendering the qh then donate the time back
+ */
+static const u16 max_uframe_usecs[] = { 100, 100, 100, 100, 100, 100, 30, 0 };
+
+/*
+ * called from dwc_otg_hcd.c:dwc_otg_hcd_init
+ */
+int init_hcd_usecs(struct dwc_hcd *hcd)
+{
+ int i;
+
+ for (i = 0; i < 8; i++)
+ hcd->frame_usecs[i] = max_uframe_usecs[i];
+
+ return 0;
+}
+
+static int find_single_uframe(struct dwc_hcd *hcd, struct dwc_qh *qh)
+{
+ int i;
+ u16 utime;
+ int t_left;
+ int ret;
+ int done;
+
+ ret = -1;
+ utime = qh->usecs;
+ t_left = utime;
+ i = 0;
+ done = 0;
+ while (done == 0) {
+ /* At the start hcd->frame_usecs[i] = max_uframe_usecs[i]; */
+ if (utime <= hcd->frame_usecs[i]) {
+ hcd->frame_usecs[i] -= utime;
+ qh->frame_usecs[i] += utime;
+ t_left -= utime;
+ ret = i;
+ done = 1;
+ return ret;
+ } else {
+ i++;
+ if (i == 8) {
+ done = 1;
+ ret = -1;
+ }
+ }
+ }
+ return ret;
+}
+
+/*
+ * use this for FS apps that can span multiple uframes
+ */
+static int find_multi_uframe(struct dwc_hcd *hcd, struct dwc_qh *qh)
+{
+ int i;
+ int j;
+ u16 utime;
+ int t_left;
+ int ret;
+ int done;
+ u16 xtime;
+
+ ret = -1;
+ utime = qh->usecs;
+ t_left = utime;
+ i = 0;
+ done = 0;
+loop:
+ while (done == 0) {
+ if (hcd->frame_usecs[i] <= 0) {
+ i++;
+ if (i == 8) {
+ done = 1;
+ ret = -1;
+ }
+ goto loop;
+ }
+
+ /*
+ * We need n consequtive slots so use j as a start slot.
+ * j plus j+1 must be enough time (for now)
+ */
+ xtime = hcd->frame_usecs[i];
+ for (j = i + 1; j < 8; j++) {
+ /*
+ * if we add this frame remaining time to xtime we may
+ * be OK, if not we need to test j for a complete frame.
+ */
+ if ((xtime + hcd->frame_usecs[j]) < utime) {
+ if (hcd->frame_usecs[j] < max_uframe_usecs[j]) {
+ j = 8;
+ ret = -1;
+ continue;
+ }
+ }
+ if (xtime >= utime) {
+ ret = i;
+ j = 8; /* stop loop with a good value ret */
+ continue;
+ }
+ /* add the frame time to x time */
+ xtime += hcd->frame_usecs[j];
+ /* we must have a fully available next frame or break */
+ if ((xtime < utime) &&
+ (hcd->frame_usecs[j] == max_uframe_usecs[j])) {
+ ret = -1;
+ j = 8; /* stop loop with a bad value ret */
+ continue;
+ }
+ }
+ if (ret >= 0) {
+ t_left = utime;
+ for (j = i; (t_left > 0) && (j < 8); j++) {
+ t_left -= hcd->frame_usecs[j];
+ if (t_left <= 0) {
+ qh->frame_usecs[j] +=
+ hcd->frame_usecs[j] + t_left;
+ hcd->frame_usecs[j] = -t_left;
+ ret = i;
+ done = 1;
+ } else {
+ qh->frame_usecs[j] +=
+ hcd->frame_usecs[j];
+ hcd->frame_usecs[j] = 0;
+ }
+ }
+ } else {
+ i++;
+ if (i == 8) {
+ done = 1;
+ ret = -1;
+ }
+ }
+ }
+ return ret;
+}
+
+static int find_uframe(struct dwc_hcd *hcd, struct dwc_qh *qh)
+{
+ int ret = -1;
+
+ if (qh->speed == USB_SPEED_HIGH)
+ /* if this is a hs transaction we need a full frame */
+ ret = find_single_uframe(hcd, qh);
+ else
+ /* FS transaction may need a sequence of frames */
+ ret = find_multi_uframe(hcd, qh);
+
+ return ret;
+}
+
+/**
+ * Checks that the max transfer size allowed in a host channel is large enough
+ * to handle the maximum data transfer in a single (micro)frame for a periodic
+ * transfer.
+ */
+static int check_max_xfer_size(struct dwc_hcd *hcd, struct dwc_qh *qh)
+{
+ int status = 0;
+ u32 max_xfer_size;
+ u32 max_channel_xfer_size;
+
+ max_xfer_size = dwc_max_packet(qh->maxp) * dwc_hb_mult(qh->maxp);
+ max_channel_xfer_size = hcd->core_if->core_params->max_transfer_size;
+
+ if (max_xfer_size > max_channel_xfer_size) {
+ pr_notice("%s: Periodic xfer length %d > max xfer "
+ "length for channel %d\n", __func__, max_xfer_size,
+ max_channel_xfer_size);
+ status = -ENOSPC;
+ }
+
+ return status;
+}
+
+/**
+ * Schedules an interrupt or isochronous transfer in the periodic schedule.
+ */
+static int schedule_periodic(struct dwc_hcd *hcd, struct dwc_qh *qh)
+{
+ int status;
+ struct usb_bus *bus = hcd_to_bus(dwc_otg_hcd_to_hcd(hcd));
+ int frame;
+
+ status = find_uframe(hcd, qh);
+ frame = -1;
+ if (status == 0) {
+ frame = 7;
+ } else {
+ if (status > 0)
+ frame = status - 1;
+ }
+ /* Set the new frame up */
+ if (frame > -1) {
+ qh->sched_frame &= ~0x7;
+ qh->sched_frame |= (frame & 7);
+ }
+ if (status != -1)
+ status = 0;
+ if (status) {
+ pr_notice("%s: Insufficient periodic bandwidth for "
+ "periodic transfer.\n", __func__);
+ return status;
+ }
+ status = check_max_xfer_size(hcd, qh);
+ if (status) {
+ pr_notice("%s: Channel max transfer size too small "
+ "for periodic transfer.\n", __func__);
+ return status;
+ }
+ /* Always start in the inactive schedule. */
+ list_add_tail(&qh->qh_list_entry, &hcd->periodic_sched_inactive);
+
+ /* Update claimed usecs per (micro)frame. */
+ hcd->periodic_usecs += qh->usecs;
+
+ /*
+ * Update average periodic bandwidth claimed and # periodic reqs for
+ * usbfs.
+ */
+ bus->bandwidth_allocated += qh->usecs / qh->interval;
+
+ if (qh->ep_type == USB_ENDPOINT_XFER_INT)
+ bus->bandwidth_int_reqs++;
+ else
+ bus->bandwidth_isoc_reqs++;
+
+ return status;
+}
+
+/**
+ * This function adds a QH to either the non periodic or periodic schedule if
+ * it is not already in the schedule. If the QH is already in the schedule, no
+ * action is taken.
+ */
+static int dwc_otg_hcd_qh_add(struct dwc_hcd *hcd, struct dwc_qh *qh)
+{
+ int status = 0;
+
+ /* QH may already be in a schedule. */
+ if (!list_empty(&qh->qh_list_entry))
+ goto done;
+ /*
+ * Add the new QH to the appropriate schedule. For non-periodic, always
+ * start in the inactive schedule.
+ */
+ if (dwc_qh_is_non_per(qh))
+ list_add_tail(&qh->qh_list_entry,
+ &hcd->non_periodic_sched_inactive);
+ else
+ status = schedule_periodic(hcd, qh);
+
+done:
+ return status;
+}
+
+/**
+ * This function adds a QH to the non periodic deferred schedule.
+ *
+ * @return 0 if successful, negative error code otherwise.
+ */
+static int dwc_otg_hcd_qh_add_deferred(struct dwc_hcd *hcd, struct dwc_qh *qh)
+{
+ if (!list_empty(&qh->qh_list_entry))
+ /* QH already in a schedule. */
+ goto done;
+
+ /* Add the new QH to the non periodic deferred schedule */
+ if (dwc_qh_is_non_per(qh))
+ list_add_tail(&qh->qh_list_entry,
+ &hcd->non_periodic_sched_deferred);
+done:
+ return 0;
+}
+
+/**
+ * Removes an interrupt or isochronous transfer from the periodic schedule.
+ */
+static void deschedule_periodic(struct dwc_hcd *hcd, struct dwc_qh *qh)
+{
+ struct usb_bus *bus = hcd_to_bus(dwc_otg_hcd_to_hcd(hcd));
+ int i;
+
+ list_del_init(&qh->qh_list_entry);
+ /* Update claimed usecs per (micro)frame. */
+ hcd->periodic_usecs -= qh->usecs;
+ for (i = 0; i < 8; i++) {
+ hcd->frame_usecs[i] += qh->frame_usecs[i];
+ qh->frame_usecs[i] = 0;
+ }
+ /*
+ * Update average periodic bandwidth claimed and # periodic reqs for
+ * usbfs.
+ */
+ bus->bandwidth_allocated -= qh->usecs / qh->interval;
+
+ if (qh->ep_type == USB_ENDPOINT_XFER_INT)
+ bus->bandwidth_int_reqs--;
+ else
+ bus->bandwidth_isoc_reqs--;
+}
+
+/**
+ * Removes a QH from either the non-periodic or periodic schedule. Memory is
+ * not freed.
+ */
+void dwc_otg_hcd_qh_remove(struct dwc_hcd *hcd, struct dwc_qh *qh)
+{
+ /* Do nothing if QH is not in a schedule */
+ if (list_empty(&qh->qh_list_entry))
+ return;
+
+ if (dwc_qh_is_non_per(qh)) {
+ if (hcd->non_periodic_qh_ptr == &qh->qh_list_entry)
+ hcd->non_periodic_qh_ptr =
+ hcd->non_periodic_qh_ptr->next;
+ list_del_init(&qh->qh_list_entry);
+ } else {
+ deschedule_periodic(hcd, qh);
+ }
+}
+
+/**
+ * Defers a QH. For non-periodic QHs, removes the QH from the active
+ * non-periodic schedule. The QH is added to the deferred non-periodic
+ * schedule if any QTDs are still attached to the QH.
+ */
+int dwc_otg_hcd_qh_deferr(struct dwc_hcd *hcd, struct dwc_qh *qh, int delay)
+{
+ int deact = 1;
+
+ if (dwc_qh_is_non_per(qh)) {
+ qh->sched_frame = dwc_frame_num_inc(hcd->frame_number, delay);
+ qh->channel = NULL;
+ qh->qtd_in_process = NULL;
+ deact = 0;
+ dwc_otg_hcd_qh_remove(hcd, qh);
+ if (!list_empty(&qh->qtd_list))
+ /* Add back to deferred non-periodic schedule. */
+ dwc_otg_hcd_qh_add_deferred(hcd, qh);
+ }
+ return deact;
+}
+
+/**
+ * Schedule the next continuing periodic split transfer
+ */
+static void sched_next_per_split_xfr(struct dwc_qh *qh, u16 fr_num,
+ int sched_split)
+{
+ if (sched_split) {
+ qh->sched_frame = fr_num;
+ if (dwc_frame_num_le(fr_num,
+ dwc_frame_num_inc(qh->start_split_frame,
+ 1))) {
+ /*
+ * Allow one frame to elapse after start split
+ * microframe before scheduling complete split, but DONT
+ * if we are doing the next start split in the
+ * same frame for an ISOC out.
+ */
+ if (qh->ep_type != USB_ENDPOINT_XFER_ISOC ||
+ qh->ep_is_in)
+ qh->sched_frame =
+ dwc_frame_num_inc(qh->sched_frame, 1);
+ }
+ } else {
+ qh->sched_frame = dwc_frame_num_inc(qh->start_split_frame,
+ qh->interval);
+
+ if (dwc_frame_num_le(qh->sched_frame, fr_num))
+ qh->sched_frame = fr_num;
+ qh->sched_frame |= 0x7;
+ qh->start_split_frame = qh->sched_frame;
+ }
+}
+
+/**
+ * Deactivates a periodic QH. The QH is removed from the periodic queued
+ * schedule. If there are any QTDs still attached to the QH, the QH is added to
+ * either the periodic inactive schedule or the periodic ready schedule and its
+ * next scheduled frame is calculated. The QH is placed in the ready schedule if
+ * the scheduled frame has been reached already. Otherwise it's placed in the
+ * inactive schedule. If there are no QTDs attached to the QH, the QH is
+ * completely removed from the periodic schedule.
+ */
+static void deactivate_periodic_qh(struct dwc_hcd *hcd, struct dwc_qh *qh,
+ int sched_next_split)
+{
+ /* unsigned long flags; */
+ u16 fr_num = dwc_otg_hcd_get_frame_number(dwc_otg_hcd_to_hcd(hcd));
+
+ if (qh->do_split) {
+ sched_next_per_split_xfr(qh, fr_num, sched_next_split);
+ } else {
+ qh->sched_frame = dwc_frame_num_inc(qh->sched_frame,
+ qh->interval);
+ if (dwc_frame_num_le(qh->sched_frame, fr_num))
+ qh->sched_frame = fr_num;
+ }
+
+ if (list_empty(&qh->qtd_list)) {
+ dwc_otg_hcd_qh_remove(hcd, qh);
+ } else {
+ /*
+ * Remove from periodic_sched_queued and move to appropriate
+ * queue.
+ */
+ if (qh->sched_frame == fr_num)
+ list_move(&qh->qh_list_entry,
+ &hcd->periodic_sched_ready);
+ else
+ list_move(&qh->qh_list_entry,
+ &hcd->periodic_sched_inactive);
+ }
+}
+
+/**
+ * Deactivates a non-periodic QH. Removes the QH from the active non-periodic
+ * schedule. The QH is added to the inactive non-periodic schedule if any QTDs
+ * are still attached to the QH.
+ */
+static void deactivate_non_periodic_qh(struct dwc_hcd *hcd, struct dwc_qh *qh)
+{
+ dwc_otg_hcd_qh_remove(hcd, qh);
+ if (!list_empty(&qh->qtd_list))
+ dwc_otg_hcd_qh_add(hcd, qh);
+}
+
+/**
+ * Deactivates a QH. Determines if the QH is periodic or non-periodic and takes
+ * the appropriate action.
+ */
+void dwc_otg_hcd_qh_deactivate(struct dwc_hcd *hcd, struct dwc_qh *qh,
+ int sched_next_periodic_split)
+{
+ if (dwc_qh_is_non_per(qh))
+ deactivate_non_periodic_qh(hcd, qh);
+ else
+ deactivate_periodic_qh(hcd, qh, sched_next_periodic_split);
+}
+
+/**
+ * Initializes a QTD structure.
+ */
+static void dwc_otg_hcd_qtd_init(struct dwc_qtd *qtd, struct urb *urb)
+{
+ memset(qtd, 0, sizeof(struct dwc_qtd));
+ qtd->urb = urb;
+
+ if (usb_pipecontrol(urb->pipe)) {
+ /*
+ * The only time the QTD data toggle is used is on the data
+ * phase of control transfers. This phase always starts with
+ * DATA1.
+ */
+ qtd->data_toggle = DWC_OTG_HC_PID_DATA1;
+ qtd->control_phase = DWC_OTG_CONTROL_SETUP;
+ }
+
+ /* start split */
+ qtd->complete_split = 0;
+ qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL;
+ qtd->isoc_split_offset = 0;
+
+ /* Store the qtd ptr in the urb to reference what QTD. */
+ urb->hcpriv = qtd;
+
+ INIT_LIST_HEAD(&qtd->qtd_list_entry);
+ return;
+}
+
+/* Allocates memory for a QTD structure. */
+static inline struct dwc_qtd *dwc_otg_hcd_qtd_alloc(gfp_t _mem_flags)
+{
+ return kmalloc(sizeof(struct dwc_qtd), _mem_flags);
+}
+
+/**
+ * This function allocates and initializes a QTD.
+ */
+struct dwc_qtd *dwc_otg_hcd_qtd_create(struct urb *urb, gfp_t _mem_flags)
+{
+ struct dwc_qtd *qtd = dwc_otg_hcd_qtd_alloc(_mem_flags);
+
+ if (!qtd)
+ return NULL;
+
+ dwc_otg_hcd_qtd_init(qtd, urb);
+ return qtd;
+}
+
+/**
+ * This function adds a QTD to the QTD-list of a QH. It will find the correct
+ * QH to place the QTD into. If it does not find a QH, then it will create a
+ * new QH. If the QH to which the QTD is added is not currently scheduled, it
+ * is placed into the proper schedule based on its EP type.
+ *
+ */
+int dwc_otg_hcd_qtd_add(struct dwc_qtd *qtd, struct dwc_hcd *hcd)
+{
+ struct usb_host_endpoint *ep;
+ struct dwc_qh *qh;
+ int retval = 0;
+ struct urb *urb = qtd->urb;
+
+ /*
+ * Get the QH which holds the QTD-list to insert to. Create QH if it
+ * doesn't exist.
+ */
+ ep = dwc_urb_to_endpoint(urb);
+
+ qh = (struct dwc_qh *)ep->hcpriv;
+ if (!qh) {
+ qh = dwc_otg_hcd_qh_create(hcd, urb);
+ if (!qh) {
+ retval = -1;
+ goto done;
+ }
+ ep->hcpriv = qh;
+ }
+ qtd->qtd_qh_ptr = qh;
+ retval = dwc_otg_hcd_qh_add(hcd, qh);
+ if (!retval)
+ list_add_tail(&qtd->qtd_list_entry, &qh->qtd_list);
+
+done:
+ return retval;
+}
diff --git a/drivers/usb/dwc/param.c b/drivers/usb/dwc/param.c
new file mode 100644
index 0000000..0dc73d2
--- /dev/null
+++ b/drivers/usb/dwc/param.c
@@ -0,0 +1,180 @@
+/*
+ * DesignWare HS OTG controller driver
+ * Copyright (C) 2006 Synopsys, Inc.
+ * Portions Copyright (C) 2010 Applied Micro Circuits Corporation.
+ *
+ * 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 version 2 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
+ * or write to the Free Software Foundation, Inc., 51 Franklin Street,
+ * Suite 500, Boston, MA 02110-1335 USA.
+ *
+ * Based on Synopsys driver version 2.60a
+ * Modified by Mark Miesfeld <mmiesfeld@apm.com>
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL SYNOPSYS, INC. 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.
+ *
+ */
+
+/*
+ * This file provides dwc_otg driver parameter and parameter checking.
+ */
+
+#include "cil.h"
+
+/*
+ * Encapsulate the module parameter settings
+ */
+struct core_params dwc_otg_module_params = {
+ .otg_cap = -1,
+ .dma_enable = -1,
+ .dma_burst_size = -1,
+ .speed = -1,
+ .host_support_fs_ls_low_power = -1,
+ .host_ls_low_power_phy_clk = -1,
+ .enable_dynamic_fifo = -1,
+ .dev_rx_fifo_size = -1,
+ .dev_nperio_tx_fifo_size = -1,
+ .dev_perio_tx_fifo_size = {-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1}, /* 15 */
+ .host_rx_fifo_size = -1,
+ .host_nperio_tx_fifo_size = -1,
+ .host_perio_tx_fifo_size = -1,
+ .max_transfer_size = -1,
+ .max_packet_count = -1,
+ .host_channels = -1,
+ .dev_endpoints = -1,
+ .phy_type = -1,
+ .phy_utmi_width = -1,
+ .phy_ulpi_ddr = -1,
+ .phy_ulpi_ext_vbus = -1,
+ .i2c_enable = -1,
+ .ulpi_fs_ls = -1,
+ .ts_dline = -1,
+ .en_multiple_tx_fifo = -1,
+ .dev_tx_fifo_size = {-1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1}, /* 15 */
+ .thr_ctl = -1,
+ .tx_thr_length = -1,
+ .rx_thr_length = -1,
+};
+
+/**
+ * Checks that parameter settings for the periodic Tx FIFO sizes are correct
+ * according to the hardware configuration. Sets the size to the hardware
+ * configuration if an incorrect size is detected.
+ */
+static int set_valid_perio_tx_fifo_sizes(struct core_if *core_if)
+{
+ ulong regs = (u32) core_if->core_global_regs;
+ u32 *param_size = &dwc_otg_module_params.dev_perio_tx_fifo_size[0];
+ u32 i, size;
+
+ for (i = 0; i < MAX_PERIO_FIFOS; i++, param_size++) {
+ size = dwc_reg_read(regs, DWC_DPTX_FSIZ_DIPTXF(i));
+ *param_size = size;
+ }
+ return 0;
+}
+
+/**
+ * Checks that parameter settings for the Tx FIFO sizes are correct according to
+ * the hardware configuration. Sets the size to the hardware configuration if
+ * an incorrect size is detected.
+ */
+static int set_valid_tx_fifo_sizes(struct core_if *core_if)
+{
+ ulong regs = (u32) core_if->core_global_regs;
+ u32 *param_size = &dwc_otg_module_params.dev_tx_fifo_size[0];
+ u32 i, size;
+
+ for (i = 0; i < MAX_TX_FIFOS; i++, param_size) {
+ size = dwc_reg_read(regs, DWC_DPTX_FSIZ_DIPTXF(i));
+ *param_size = size;
+ }
+ return 0;
+}
+
+/**
+ * This function is called during module intialization to verify that
+ * the module parameters are in a valid state.
+ */
+int check_parameters(struct core_if *core_if)
+{
+ /* Default values */
+ dwc_otg_module_params.otg_cap = dwc_param_otg_cap_default;
+ dwc_otg_module_params.dma_enable = dwc_param_dma_enable_default;
+ dwc_otg_module_params.speed = dwc_param_speed_default;
+ dwc_otg_module_params.host_support_fs_ls_low_power =
+ dwc_param_host_support_fs_ls_low_power_default;
+ dwc_otg_module_params.host_ls_low_power_phy_clk =
+ dwc_param_host_ls_low_power_phy_clk_default;
+ dwc_otg_module_params.phy_type = dwc_param_phy_type_default;
+ dwc_otg_module_params.phy_ulpi_ddr = dwc_param_phy_ulpi_ddr_default;
+ dwc_otg_module_params.phy_ulpi_ext_vbus =
+ dwc_param_phy_ulpi_ext_vbus_default;
+ dwc_otg_module_params.i2c_enable = dwc_param_i2c_enable_default;
+ dwc_otg_module_params.ulpi_fs_ls = dwc_param_ulpi_fs_ls_default;
+ dwc_otg_module_params.ts_dline = dwc_param_ts_dline_default;
+
+ dwc_otg_module_params.dma_burst_size = dwc_param_dma_burst_size_default;
+ dwc_otg_module_params.phy_utmi_width = dwc_param_phy_utmi_width_default;
+ dwc_otg_module_params.thr_ctl = dwc_param_thr_ctl_default;
+ dwc_otg_module_params.tx_thr_length = dwc_param_tx_thr_length_default;
+ dwc_otg_module_params.rx_thr_length = dwc_param_rx_thr_length_default;
+
+ /*
+ * Hardware configurations of the OTG core.
+ */
+ dwc_otg_module_params.enable_dynamic_fifo =
+ DWC_HWCFG2_DYN_FIFO_RD(core_if->hwcfg2);
+ dwc_otg_module_params.dev_rx_fifo_size =
+ dwc_reg_read(core_if->core_global_regs, DWC_GRXFSIZ);
+ dwc_otg_module_params.dev_nperio_tx_fifo_size =
+ dwc_reg_read(core_if->core_global_regs, DWC_GNPTXFSIZ) >> 16;
+
+ dwc_otg_module_params.host_rx_fifo_size =
+ dwc_reg_read(core_if->core_global_regs, DWC_GRXFSIZ);
+ dwc_otg_module_params.host_nperio_tx_fifo_size =
+ dwc_reg_read(core_if->core_global_regs, DWC_GNPTXFSIZ) >> 16;
+ dwc_otg_module_params.host_perio_tx_fifo_size =
+ dwc_reg_read(core_if->core_global_regs, DWC_HPTXFSIZ) >> 16;
+ dwc_otg_module_params.max_transfer_size =
+ (1 << (DWC_HWCFG3_XFERSIZE_CTR_WIDTH_RD(core_if->hwcfg3) + 11))
+ - 1;
+ dwc_otg_module_params.max_packet_count =
+ (1 << (DWC_HWCFG3_PKTSIZE_CTR_WIDTH_RD(core_if->hwcfg3) + 4))
+ - 1;
+
+ dwc_otg_module_params.host_channels =
+ DWC_HWCFG2_NO_HST_CHAN_RD(core_if->hwcfg2) + 1;
+ dwc_otg_module_params.dev_endpoints =
+ DWC_HWCFG2_NO_DEV_EP_RD(core_if->hwcfg2);
+ dwc_otg_module_params.en_multiple_tx_fifo =
+ (DWC_HWCFG4_DED_FIFO_ENA_RD(core_if->hwcfg4) == 0)
+ ? 0 : 1, 0;
+ set_valid_perio_tx_fifo_sizes(core_if);
+ set_valid_tx_fifo_sizes(core_if);
+
+ return 0;
+}
+
+module_param_named(dma_enable, dwc_otg_module_params.dma_enable, bool, 0444);
+MODULE_PARM_DESC(dma_enable, "DMA Mode 0=Slave 1=DMA enabled");
diff --git a/drivers/usb/dwc/pcd.c b/drivers/usb/dwc/pcd.c
new file mode 100644
index 0000000..cfcb0ba
--- /dev/null
+++ b/drivers/usb/dwc/pcd.c
@@ -0,0 +1,1791 @@
+/*
+ * DesignWare HS OTG controller driver
+ * Copyright (C) 2006 Synopsys, Inc.
+ * Portions Copyright (C) 2010 Applied Micro Circuits Corporation.
+ *
+ * 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 version 2 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
+ * or write to the Free Software Foundation, Inc., 51 Franklin Street,
+ * Suite 500, Boston, MA 02110-1335 USA.
+ *
+ * Based on Synopsys driver version 2.60a
+ * Modified by Mark Miesfeld <mmiesfeld@apm.com>
+ * Modified by Stefan Roese <sr@denx.de>, DENX Software Engineering
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL SYNOPSYS, INC. 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.
+ *
+ */
+
+/*
+ * This file implements the Peripheral Controller Driver.
+ *
+ * The Peripheral Controller Driver (PCD) is responsible for
+ * translating requests from the Function Driver into the appropriate
+ * actions on the DWC_otg controller. It isolates the Function Driver
+ * from the specifics of the controller by providing an API to the
+ * Function Driver.
+ *
+ * The Peripheral Controller Driver for Linux will implement the
+ * Gadget API, so that the existing Gadget drivers can be used.
+ * (Gadget Driver is the Linux terminology for a Function Driver.)
+ *
+ * The Linux Gadget API is defined in the header file linux/usb/gadget.h. The
+ * USB EP operations API is defined in the structure usb_ep_ops and the USB
+ * Controller API is defined in the structure usb_gadget_ops
+ *
+ * An important function of the PCD is managing interrupts generated
+ * by the DWC_otg controller. The implementation of the DWC_otg device
+ * mode interrupt service routines is in dwc_otg_pcd_intr.c.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+
+#include "pcd.h"
+
+/*
+ * Static PCD pointer for use in usb_gadget_register_driver and
+ * usb_gadget_unregister_driver. Initialized in dwc_otg_pcd_init.
+ */
+static struct dwc_pcd *s_pcd;
+
+static inline int need_stop_srp_timer(struct core_if *core_if)
+{
+ if (core_if->core_params->phy_type != DWC_PHY_TYPE_PARAM_FS ||
+ !core_if->core_params->i2c_enable)
+ return core_if->srp_timer_started ? 1 : 0;
+ return 0;
+}
+
+/**
+ * Tests if the module is set to FS or if the PHY_TYPE is FS. If so, then the
+ * gadget should not report as dual-speed capable.
+ */
+static inline int check_is_dual_speed(struct core_if *core_if)
+{
+ if (core_if->core_params->speed == DWC_SPEED_PARAM_FULL ||
+ (DWC_HWCFG2_HS_PHY_TYPE_RD(core_if->hwcfg2) == 2 &&
+ DWC_HWCFG2_P_2_P_RD(core_if->hwcfg2) == 1 &&
+ core_if->core_params->ulpi_fs_ls))
+ return 0;
+ return 1;
+}
+
+/**
+ * Tests if driver is OTG capable.
+ */
+static inline int check_is_otg(struct core_if *core_if)
+{
+ if (DWC_HWCFG2_OP_MODE_RD(core_if->hwcfg2) ==
+ DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE ||
+ DWC_HWCFG2_OP_MODE_RD(core_if->hwcfg2) ==
+ DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST ||
+ DWC_HWCFG2_OP_MODE_RD(core_if->hwcfg2) ==
+ DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE ||
+ DWC_HWCFG2_OP_MODE_RD(core_if->hwcfg2) ==
+ DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)
+ return 0;
+ return 1;
+}
+
+/**
+ * This function completes a request. It calls the request call back.
+ */
+void request_done(struct pcd_ep *ep, struct pcd_request *req, int status)
+{
+ unsigned stopped = ep->stopped;
+
+ list_del_init(&req->queue);
+ if (req->req.status == -EINPROGRESS)
+ req->req.status = status;
+ else
+ status = req->req.status;
+
+ if (GET_CORE_IF(ep->pcd)->dma_enable) {
+ if (req->mapped) {
+ dma_unmap_single(ep->pcd->gadget.dev.parent,
+ req->req.dma, req->req.length,
+ ep->dwc_ep.is_in ? DMA_TO_DEVICE :
+ DMA_FROM_DEVICE);
+ req->req.dma = DMA_ADDR_INVALID;
+ req->mapped = 0;
+ } else {
+ dma_sync_single_for_cpu(ep->pcd->gadget.dev.parent,
+ req->req.dma, req->req.length,
+ ep->dwc_ep.
+ is_in ? DMA_TO_DEVICE :
+ DMA_FROM_DEVICE);
+ }
+ }
+
+ /* don't modify queue heads during completion callback */
+ ep->stopped = 1;
+ spin_unlock(&ep->pcd->lock);
+ req->req.complete(&ep->ep, &req->req);
+ spin_lock(&ep->pcd->lock);
+
+ if (ep->pcd->request_pending > 0)
+ --ep->pcd->request_pending;
+ ep->stopped = stopped;
+
+ /*
+ * Added-sr: 2007-07-26
+ *
+ * Finally, when the current request is done, mark this endpoint
+ * as not active, so that new requests can be processed.
+ */
+ if (dwc_has_feature(GET_CORE_IF(ep->pcd), DWC_LIMITED_XFER))
+ ep->dwc_ep.active = 0;
+}
+
+/**
+ * This function terminates all the requsts in the EP request queue.
+ */
+void request_nuke(struct pcd_ep *ep)
+{
+ struct pcd_request *req;
+
+ ep->stopped = 1;
+
+ /* called with irqs blocked?? */
+ while (!list_empty(&ep->queue)) {
+ req = list_entry(ep->queue.next, struct pcd_request, queue);
+ request_done(ep, req, -ESHUTDOWN);
+ }
+}
+
+/*
+ * The following sections briefly describe the behavior of the Gadget
+ * API endpoint operations implemented in the DWC_otg driver
+ * software. Detailed descriptions of the generic behavior of each of
+ * these functions can be found in the Linux header file
+ * include/linux/usb_gadget.h.
+ *
+ * The Gadget API provides wrapper functions for each of the function
+ * pointers defined in usb_ep_ops. The Gadget Driver calls the wrapper
+ * function, which then calls the underlying PCD function. The
+ * following sections are named according to the wrapper
+ * functions. Within each section, the corresponding DWC_otg PCD
+ * function name is specified.
+ *
+ */
+
+/**
+ * This function assigns periodic Tx FIFO to an periodic EP in shared Tx FIFO
+ * mode
+ */
+static u32 assign_perio_tx_fifo(struct core_if *core_if)
+{
+ u32 mask = 1;
+ u32 i;
+
+ for (i = 0; i < DWC_HWCFG4_NUM_DEV_PERIO_IN_EP_RD(core_if->hwcfg4);
+ ++i) {
+ if (!(mask & core_if->p_tx_msk)) {
+ core_if->p_tx_msk |= mask;
+ return i + 1;
+ }
+ mask <<= 1;
+ }
+ return 0;
+}
+
+/**
+ * This function releases periodic Tx FIFO in shared Tx FIFO mode
+ */
+static void release_perio_tx_fifo(struct core_if *core_if, u32 fifo_num)
+{
+ core_if->p_tx_msk = (core_if->p_tx_msk & (1 << (fifo_num - 1)))
+ ^ core_if->p_tx_msk;
+}
+
+/**
+ * This function assigns periodic Tx FIFO to an periodic EP in shared Tx FIFO
+ * mode
+ */
+static u32 assign_tx_fifo(struct core_if *core_if)
+{
+ u32 mask = 1;
+ u32 i;
+
+ for (i = 0; i < DWC_HWCFG4_NUM_IN_EPS_RD(core_if->hwcfg4); ++i) {
+ if (!(mask & core_if->tx_msk)) {
+ core_if->tx_msk |= mask;
+ return i + 1;
+ }
+ mask <<= 1;
+ }
+ return 0;
+}
+
+/**
+ * This function releases periodic Tx FIFO in shared Tx FIFO mode
+ */
+static void release_tx_fifo(struct core_if *core_if, u32 fifo_num)
+{
+ core_if->tx_msk = (core_if->tx_msk & (1 << (fifo_num - 1)))
+ ^ core_if->tx_msk;
+}
+
+/**
+ * Sets an in endpoint's tx fifo based on the hardware configuration.
+ */
+static void set_in_ep_tx_fifo(struct dwc_pcd *pcd, struct pcd_ep *ep,
+ const struct usb_endpoint_descriptor *desc)
+{
+ if (pcd->otg_dev->core_if->en_multiple_tx_fifo) {
+ ep->dwc_ep.tx_fifo_num = assign_tx_fifo(pcd->otg_dev->core_if);
+ } else {
+ ep->dwc_ep.tx_fifo_num = 0;
+
+ /* If ISOC EP then assign a Periodic Tx FIFO. */
+ if ((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+ USB_ENDPOINT_XFER_ISOC)
+ ep->dwc_ep.tx_fifo_num =
+ assign_perio_tx_fifo(pcd->otg_dev->core_if);
+ }
+}
+
+/**
+ * This function activates an EP. The Device EP control register for
+ * the EP is configured as defined in the ep structure. Note: This function is
+ * not used for EP0.
+ */
+void dwc_otg_ep_activate(struct core_if *core_if, struct dwc_ep *ep)
+{
+ struct device_if *dev_if = core_if->dev_if;
+ u32 depctl = 0;
+ ulong addr;
+ u32 daintmsk = 0;
+
+ /* Read DEPCTLn register */
+ if (ep->is_in == 1) {
+ addr = dev_if->in_ep_regs[ep->num] + DWC_DIEPCTL;
+ daintmsk = DWC_DAINTMSK_IN_EP_RW(daintmsk, ep->num);
+ } else {
+ addr = dev_if->out_ep_regs[ep->num] + DWC_DOEPCTL;
+ daintmsk = DWC_DAINTMSK_OUT_EP_RW(daintmsk, ep->num);
+ }
+
+ /* If the EP is already active don't change the EP Control register */
+ depctl = dwc_reg_read(addr, 0);
+ if (!DWC_DEPCTL_ACT_EP_RD(depctl)) {
+ depctl = DWC_DEPCTL_MPS_RW(depctl, ep->maxpacket);
+ depctl = DWC_DEPCTL_EP_TYPE_RW(depctl, ep->type);
+ depctl = DWC_DEPCTL_TX_FIFO_NUM_RW(depctl, ep->tx_fifo_num);
+ depctl = DWC_DEPCTL_SET_DATA0_PID_RW(depctl, 1);
+ depctl = DWC_DEPCTL_ACT_EP_RW(depctl, 1);
+ dwc_reg_write(addr, 0, depctl);
+ }
+
+ /* Enable the Interrupt for this EP */
+ dwc_reg_modify(dev_if->dev_global_regs, DWC_DAINTMSK, 0, daintmsk);
+
+ ep->stall_clear_flag = 0;
+}
+
+/**
+ * This function is called by the Gadget Driver for each EP to be
+ * configured for the current configuration (SET_CONFIGURATION).
+ *
+ * This function initializes the dwc_otg_ep_t data structure, and then
+ * calls dwc_otg_ep_activate.
+ */
+static int dwc_otg_pcd_ep_enable(struct usb_ep *_ep,
+ const struct usb_endpoint_descriptor *desc)
+{
+ struct pcd_ep *ep;
+ struct dwc_pcd *pcd;
+ unsigned long flags;
+
+ ep = container_of(_ep, struct pcd_ep, ep);
+ if (!_ep || !desc || ep->desc || desc->bDescriptorType !=
+ USB_DT_ENDPOINT) {
+ pr_warning("%s, bad ep or descriptor\n", __func__);
+ return -EINVAL;
+ }
+
+ if (ep == &ep->pcd->ep0) {
+ pr_warning("%s, bad ep(0)\n", __func__);
+ return -EINVAL;
+ }
+
+ /* Check FIFO size */
+ if (!desc->wMaxPacketSize) {
+ pr_warning("%s, bad %s maxpacket\n", __func__, _ep->name);
+ return -ERANGE;
+ }
+
+ pcd = ep->pcd;
+ if (!pcd->driver || pcd->gadget.speed == USB_SPEED_UNKNOWN) {
+ pr_warning("%s, bogus device state\n", __func__);
+ return -ESHUTDOWN;
+ }
+
+ spin_lock_irqsave(&pcd->lock, flags);
+ ep->desc = desc;
+ ep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize);
+
+ /* Activate the EP */
+ ep->stopped = 0;
+ ep->wedged = 0;
+ ep->dwc_ep.is_in = (USB_DIR_IN & desc->bEndpointAddress) != 0;
+ ep->dwc_ep.maxpacket = ep->ep.maxpacket;
+ ep->dwc_ep.type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+
+ if (ep->dwc_ep.is_in)
+ set_in_ep_tx_fifo(pcd, ep, desc);
+
+ /* Set initial data PID. */
+ if ((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+ USB_ENDPOINT_XFER_BULK)
+ ep->dwc_ep.data_pid_start = 0;
+
+ dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep);
+ spin_unlock_irqrestore(&pcd->lock, flags);
+ return 0;
+}
+
+/**
+ * This function deactivates an EP. This is done by clearing the USB Active EP
+ * bit in the Device EP control register. Note: This function is not used for
+ * EP0. EP0 cannot be deactivated.
+ */
+static void dwc_otg_ep_deactivate(struct core_if *core_if, struct dwc_ep *ep)
+{
+ u32 depctl = 0;
+ ulong addr;
+ u32 daintmsk = 0;
+
+ /* Read DEPCTLn register */
+ if (ep->is_in == 1) {
+ addr = core_if->dev_if->in_ep_regs[ep->num] + DWC_DIEPCTL;
+ daintmsk = DWC_DAINTMSK_IN_EP_RW(daintmsk, ep->num);
+ } else {
+ addr =
+ core_if->dev_if->out_ep_regs[ep->num] + DWC_DOEPCTL;
+ daintmsk = DWC_DAINTMSK_OUT_EP_RW(daintmsk, ep->num);
+ }
+
+ depctl = DWC_DEPCTL_ACT_EP_RW(depctl, 0);
+ dwc_reg_write(addr, 0, depctl);
+
+ /* Disable the Interrupt for this EP */
+ dwc_reg_modify(core_if->dev_if->dev_global_regs, DWC_DAINTMSK,
+ daintmsk, 0);
+}
+
+/**
+ * This function is called when an EP is disabled due to disconnect or
+ * change in configuration. Any pending requests will terminate with a
+ * status of -ESHUTDOWN.
+ *
+ * This function modifies the dwc_otg_ep_t data structure for this EP,
+ * and then calls dwc_otg_ep_deactivate.
+ */
+static int dwc_otg_pcd_ep_disable(struct usb_ep *_ep)
+{
+ struct pcd_ep *ep;
+ struct core_if *core_if;
+ unsigned long flags;
+
+ ep = container_of(_ep, struct pcd_ep, ep);
+ if (!_ep || !ep->desc)
+ return -EINVAL;
+
+ core_if = ep->pcd->otg_dev->core_if;
+
+ spin_lock_irqsave(&ep->pcd->lock, flags);
+
+ request_nuke(ep);
+ dwc_otg_ep_deactivate(core_if, &ep->dwc_ep);
+
+ ep->desc = NULL;
+ ep->stopped = 1;
+ if (ep->dwc_ep.is_in) {
+ release_perio_tx_fifo(core_if, ep->dwc_ep.tx_fifo_num);
+ release_tx_fifo(core_if, ep->dwc_ep.tx_fifo_num);
+ }
+
+ spin_unlock_irqrestore(&ep->pcd->lock, flags);
+
+ return 0;
+}
+
+/**
+ * This function allocates a request object to use with the specified
+ * endpoint.
+ */
+static struct usb_request *dwc_otg_pcd_alloc_request(struct usb_ep *_ep,
+ gfp_t gfp_flags)
+{
+ struct pcd_request *req;
+
+ if (!_ep) {
+ pr_warning("%s() Invalid EP\n", __func__);
+ return NULL;
+ }
+
+ req = kzalloc(sizeof(struct pcd_request), gfp_flags);
+ if (!req) {
+ pr_warning("%s() request allocation failed\n", __func__);
+ return NULL;
+ }
+
+ req->req.dma = DMA_ADDR_INVALID;
+ INIT_LIST_HEAD(&req->queue);
+
+ return &req->req;
+}
+
+/**
+ * This function frees a request object.
+ */
+static void dwc_otg_pcd_free_request(struct usb_ep *_ep,
+ struct usb_request *_req)
+{
+ struct pcd_request *req;
+
+ if (!_ep || !_req) {
+ pr_warning("%s() nvalid ep or req argument\n", __func__);
+ return;
+ }
+
+ req = container_of(_req, struct pcd_request, req);
+ kfree(req);
+}
+
+/*
+ * In dedicated Tx FIFO mode, enable the Non-Periodic Tx FIFO empty interrupt.
+ * Otherwise, enable the Tx FIFO epmty interrupt. The data will be written into
+ * the fifo by the ISR.
+ */
+static void enable_tx_fifo_empty_intr(struct core_if *c_if, struct dwc_ep *ep)
+{
+ u32 intr_mask = 0;
+ struct device_if *d_if = c_if->dev_if;
+ ulong global_regs = c_if->core_global_regs;
+
+ if (!c_if->en_multiple_tx_fifo) {
+ intr_mask |= DWC_INTMSK_NP_TXFIFO_EMPT;
+ dwc_reg_modify(global_regs, DWC_GINTSTS, intr_mask, 0);
+ dwc_reg_modify(global_regs, DWC_GINTMSK, intr_mask, intr_mask);
+ } else if (ep->xfer_len) {
+ /* Enable the Tx FIFO Empty Interrupt for this EP */
+ u32 fifoemptymsk = 1 << ep->num;
+ dwc_reg_modify(d_if->dev_global_regs,
+ DWC_DTKNQR4FIFOEMPTYMSK, 0, fifoemptymsk);
+ }
+}
+
+static void set_next_ep(struct device_if *dev_if, u8 num)
+{
+ u32 depctl = 0;
+
+ depctl = dwc_reg_read(dev_if->in_ep_regs[0], 0) + DWC_DIEPCTL;
+ depctl = DWC_DEPCTL_NXT_EP_RW(depctl, num);
+
+ dwc_reg_write((dev_if->in_ep_regs[0]), DWC_DIEPCTL, depctl);
+}
+
+/**
+ * This function does the setup for a data transfer for an EP and
+ * starts the transfer. For an IN transfer, the packets will be loaded into the
+ * appropriate Tx FIFO in the ISR. For OUT transfers, the packets are unloaded
+ * from the Rx FIFO in the ISR.
+ *
+ */
+void dwc_otg_ep_start_transfer(struct core_if *c_if, struct dwc_ep *ep)
+{
+ u32 depctl = 0;
+ u32 deptsiz = 0;
+ struct device_if *d_if = c_if->dev_if;
+ ulong glbl_regs = c_if->core_global_regs;
+
+ if (ep->is_in) {
+ ulong in_regs = d_if->in_ep_regs[ep->num];
+ u32 gtxstatus;
+
+ gtxstatus = dwc_reg_read(glbl_regs, DWC_GNPTXSTS);
+ if (!c_if->en_multiple_tx_fifo
+ && !DWC_GNPTXSTS_NPTXQSPCAVAIL_RD(gtxstatus))
+ return;
+
+ depctl = dwc_reg_read(in_regs, DWC_DIEPCTL);
+ deptsiz = dwc_reg_read(in_regs, DWC_DIEPTSIZ);
+
+ /* Zero Length Packet? */
+ if (!ep->xfer_len) {
+ deptsiz = DWC_DEPTSIZ_XFER_SIZ_RW(deptsiz, 0);
+ deptsiz = DWC_DEPTSIZ_PKT_CNT_RW(deptsiz, 1);
+ } else {
+ /*
+ * Program the transfer size and packet count as
+ * follows:
+ *
+ * xfersize = N * maxpacket + short_packet
+ * pktcnt = N + (short_packet exist ? 1 : 0)
+ */
+
+ /*
+ * Added-sr: 2007-07-26
+ *
+ * Since the 405EZ (Ultra) only support 2047 bytes as
+ * max transfer size, we have to split up bigger
+ * transfers into multiple transfers of 1024 bytes sized
+ * messages. I happens often, that transfers of 4096
+ * bytes are required (zero-gadget,
+ * file_storage-gadget).
+ */
+ if (dwc_has_feature(c_if, DWC_LIMITED_XFER)) {
+ if (ep->xfer_len > MAX_XFER_LEN) {
+ ep->bytes_pending = ep->xfer_len
+ - MAX_XFER_LEN;
+ ep->xfer_len = MAX_XFER_LEN;
+ }
+ }
+
+ deptsiz =
+ DWC_DEPTSIZ_XFER_SIZ_RW(deptsiz, ep->xfer_len);
+ deptsiz =
+ DWC_DEPTSIZ_PKT_CNT_RW(deptsiz,
+ ((ep->xfer_len - 1 +
+ ep->maxpacket) /
+ ep->maxpacket));
+ }
+ dwc_reg_write(in_regs, DWC_DIEPTSIZ, deptsiz);
+
+ if (c_if->dma_enable)
+ dwc_reg_write(in_regs, DWC_DIEPDMA, ep->dma_addr);
+ else if (ep->type != DWC_OTG_EP_TYPE_ISOC)
+ enable_tx_fifo_empty_intr(c_if, ep);
+
+ /* EP enable, IN data in FIFO */
+ depctl = DWC_DEPCTL_CLR_NAK_RW(depctl, 1);
+ depctl = DWC_DEPCTL_EPENA_RW(depctl, 1);
+ dwc_reg_write(in_regs, DWC_DIEPCTL, depctl);
+
+ if (c_if->dma_enable)
+ set_next_ep(d_if, ep->num);
+ } else {
+ u32 out_regs = d_if->out_ep_regs[ep->num];
+
+ depctl = dwc_reg_read(out_regs, DWC_DOEPCTL);
+ deptsiz = dwc_reg_read(out_regs, DWC_DOEPTSIZ);
+
+ /*
+ * Program the transfer size and packet count as follows:
+ *
+ * pktcnt = N
+ * xfersize = N * maxpacket
+ */
+ if (!ep->xfer_len) {
+ deptsiz =
+ DWC_DEPTSIZ_XFER_SIZ_RW(deptsiz, ep->maxpacket);
+ deptsiz = DWC_DEPTSIZ_PKT_CNT_RW(deptsiz, 1);
+ } else {
+ deptsiz = DWC_DEPTSIZ_PKT_CNT_RW(deptsiz,
+ ((ep->xfer_len +
+ ep->maxpacket -
+ 1) / ep->maxpacket));
+ deptsiz =
+ DWC_DEPTSIZ_XFER_SIZ_RW(deptsiz,
+ DWC_DEPTSIZ_PKT_CNT_RD
+ (deptsiz) * ep->maxpacket);
+ }
+ dwc_reg_write(out_regs, DWC_DOEPTSIZ, deptsiz);
+
+ if (c_if->dma_enable)
+ dwc_reg_write(out_regs, DWC_DOEPDMA, ep->dma_addr);
+
+ if (ep->type == DWC_OTG_EP_TYPE_ISOC) {
+ if (ep->even_odd_frame)
+ depctl = DWC_DEPCTL_SET_DATA1_PID_RW(depctl, 1);
+ else
+ depctl = DWC_DEPCTL_SET_DATA0_PID_RW(depctl, 1);
+ }
+
+ /* EP enable */
+ depctl = DWC_DEPCTL_CLR_NAK_RW(depctl, 1);
+ depctl = DWC_DEPCTL_EPENA_RW(depctl, 1);
+ dwc_reg_write(out_regs, DWC_DOEPCTL, depctl);
+ }
+}
+
+/**
+ * This function does the setup for a data transfer for EP0 and starts
+ * the transfer. For an IN transfer, the packets will be loaded into
+ * the appropriate Tx FIFO in the ISR. For OUT transfers, the packets are
+ * unloaded from the Rx FIFO in the ISR.
+ */
+void dwc_otg_ep0_start_transfer(struct core_if *c_if, struct dwc_ep *ep)
+{
+ u32 depctl = 0;
+ u32 deptsiz = 0;
+ struct device_if *d_if = c_if->dev_if;
+ ulong glbl_regs = c_if->core_global_regs;
+
+ ep->total_len = ep->xfer_len;
+
+ if (ep->is_in) {
+ ulong in_regs = d_if->in_ep_regs[0];
+ u32 gtxstatus;
+
+ gtxstatus = dwc_reg_read(glbl_regs, DWC_GNPTXSTS);
+
+ if (!c_if->en_multiple_tx_fifo
+ && !DWC_GNPTXSTS_NPTXQSPCAVAIL_RD(gtxstatus))
+ return;
+
+ depctl = dwc_reg_read(in_regs, DWC_DIEPCTL);
+ deptsiz = dwc_reg_read(in_regs, DWC_DIEPTSIZ);
+
+ /* Zero Length Packet? */
+ if (!ep->xfer_len) {
+ deptsiz = DWC_DEPTSIZ0_XFER_SIZ_RW(deptsiz, 0);
+ deptsiz = DWC_DEPTSIZ0_PKT_CNT_RW(deptsiz, 1);
+ } else {
+ /*
+ * Program the transfer size and packet count as
+ * follows:
+ *
+ * xfersize = N * maxpacket + short_packet
+ * pktcnt = N + (short_packet exist ? 1 : 0)
+ */
+ if (ep->xfer_len > ep->maxpacket) {
+ ep->xfer_len = ep->maxpacket;
+ deptsiz = DWC_DEPTSIZ0_XFER_SIZ_RW(deptsiz,
+ ep->
+ maxpacket);
+ } else {
+ deptsiz = DWC_DEPTSIZ0_XFER_SIZ_RW(deptsiz,
+ ep->
+ xfer_len);
+ }
+ deptsiz = DWC_DEPTSIZ0_PKT_CNT_RW(deptsiz, 1);
+ }
+ dwc_reg_write(in_regs, DWC_DIEPTSIZ, deptsiz);
+
+ if (c_if->dma_enable)
+ dwc_reg_write(in_regs, DWC_DIEPDMA, ep->dma_addr);
+
+ /* EP enable, IN data in FIFO */
+ depctl = DWC_DEPCTL_CLR_NAK_RW(depctl, 1);
+ depctl = DWC_DEPCTL_EPENA_RW(depctl, 1);
+ dwc_reg_write(in_regs, DWC_DIEPCTL, depctl);
+
+ if (!c_if->dma_enable)
+ enable_tx_fifo_empty_intr(c_if, ep);
+ } else {
+ ulong out_regs = d_if->out_ep_regs[ep->num];
+
+ depctl = dwc_reg_read(out_regs, DWC_DOEPCTL);
+ deptsiz = dwc_reg_read(out_regs, DWC_DOEPTSIZ);
+
+ /*
+ * Program the transfer size and packet count as follows:
+ *
+ * xfersize = N * (maxpacket + 4 - (maxpacket % 4))
+ * pktcnt = N
+ */
+ if (!ep->xfer_len) {
+ deptsiz = DWC_DEPTSIZ0_XFER_SIZ_RW(deptsiz,
+ ep->maxpacket);
+ deptsiz = DWC_DEPTSIZ0_PKT_CNT_RW(deptsiz, 1);
+ } else {
+ deptsiz = DWC_DEPTSIZ0_PKT_CNT_RW(deptsiz,
+ (ep->xfer_len +
+ ep->maxpacket -
+ 1) / ep->maxpacket);
+ deptsiz =
+ DWC_DEPTSIZ0_XFER_SIZ_RW(deptsiz,
+ DWC_DEPTSIZ_PKT_CNT_RD
+ (deptsiz) * ep->maxpacket);
+ }
+ dwc_reg_write(out_regs, DWC_DOEPTSIZ, deptsiz);
+
+ if (c_if->dma_enable)
+ dwc_reg_write(out_regs, DWC_DOEPDMA, ep->dma_addr);
+
+ /* EP enable */
+ depctl = DWC_DEPCTL_CLR_NAK_RW(depctl, 1);
+ depctl = DWC_DEPCTL_EPENA_RW(depctl, 1);
+ dwc_reg_write(out_regs, DWC_DOEPCTL, depctl);
+ }
+}
+
+/**
+ * This function is used to submit an I/O Request to an EP.
+ *
+ * - When the request completes the request's completion callback
+ * is called to return the request to the driver.
+ * - An EP, except control EPs, may have multiple requests
+ * pending.
+ * - Once submitted the request cannot be examined or modified.
+ * - Each request is turned into one or more packets.
+ * - A BULK EP can queue any amount of data; the transfer is
+ * packetized.
+ * - Zero length Packets are specified with the request 'zero'
+ * flag.
+ */
+static int dwc_otg_pcd_ep_queue(struct usb_ep *_ep, struct usb_request *_req,
+ gfp_t gfp_flags)
+{
+ int prevented = 0;
+ struct pcd_request *req;
+ struct pcd_ep *ep;
+ struct dwc_pcd *pcd;
+ struct core_if *core_if;
+ unsigned long flags = 0;
+
+ req = container_of(_req, struct pcd_request, req);
+ if (!_req || !_req->complete || !_req->buf ||
+ !list_empty(&req->queue)) {
+ pr_warning("%s, bad params\n", __func__);
+ return -EINVAL;
+ }
+
+ ep = container_of(_ep, struct pcd_ep, ep);
+ if (!_ep || (!ep->desc && ep->dwc_ep.num != 0)) {
+ pr_warning("%s, bad ep\n", __func__);
+ return -EINVAL;
+ }
+
+ pcd = ep->pcd;
+ if (!pcd->driver || pcd->gadget.speed == USB_SPEED_UNKNOWN) {
+ pr_warning("%s, bogus device state\n", __func__);
+ return -ESHUTDOWN;
+ }
+ core_if = pcd->otg_dev->core_if;
+
+ if (GET_CORE_IF(pcd)->dma_enable) {
+ if (_req->dma == DMA_ADDR_INVALID) {
+ _req->dma = dma_map_single(pcd->gadget.dev.parent,
+ _req->buf, _req->length,
+ ep->dwc_ep.
+ is_in ? DMA_TO_DEVICE :
+ DMA_FROM_DEVICE);
+ req->mapped = 1;
+ } else {
+ dma_sync_single_for_device(pcd->gadget.dev.parent,
+ _req->dma, _req->length,
+ ep->dwc_ep.
+ is_in ? DMA_TO_DEVICE :
+ DMA_FROM_DEVICE);
+ req->mapped = 0;
+ }
+ }
+
+ spin_lock_irqsave(&ep->pcd->lock, flags);
+
+ _req->status = -EINPROGRESS;
+ _req->actual = 0;
+
+ /* Start the transfer */
+ if (list_empty(&ep->queue) && !ep->stopped) {
+ /* EP0 Transfer? */
+ if (ep->dwc_ep.num == 0) {
+ switch (pcd->ep0state) {
+ case EP0_IN_DATA_PHASE:
+ break;
+ case EP0_OUT_DATA_PHASE:
+ if (pcd->request_config) {
+ /* Complete STATUS PHASE */
+ ep->dwc_ep.is_in = 1;
+ pcd->ep0state = EP0_STATUS;
+ }
+ break;
+ default:
+ spin_unlock_irqrestore(&pcd->lock, flags);
+ return -EL2HLT;
+ }
+
+ ep->dwc_ep.dma_addr = _req->dma;
+ ep->dwc_ep.start_xfer_buff = _req->buf;
+ ep->dwc_ep.xfer_buff = _req->buf;
+ ep->dwc_ep.xfer_len = _req->length;
+ ep->dwc_ep.xfer_count = 0;
+ ep->dwc_ep.sent_zlp = 0;
+ ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
+
+ dwc_otg_ep0_start_transfer(core_if, &ep->dwc_ep);
+ } else {
+ /* Setup and start the Transfer */
+ ep->dwc_ep.dma_addr = _req->dma;
+ ep->dwc_ep.start_xfer_buff = _req->buf;
+ ep->dwc_ep.xfer_buff = _req->buf;
+ ep->dwc_ep.xfer_len = _req->length;
+ ep->dwc_ep.xfer_count = 0;
+ ep->dwc_ep.sent_zlp = 0;
+ ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
+
+ dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep);
+ }
+ }
+
+ if (req || prevented) {
+ ++pcd->request_pending;
+ list_add_tail(&req->queue, &ep->queue);
+
+ if (ep->dwc_ep.is_in && ep->stopped && !core_if->dma_enable) {
+ /*
+ * Device IN endpoint interrupt mask register is laid
+ * out exactly the same as the device IN endpoint
+ * interrupt register.
+ */
+ u32 diepmsk = 0;
+ diepmsk = DWC_DIEPMSK_IN_TKN_TX_EMPTY_RW(diepmsk, 1);
+
+ dwc_reg_modify(core_if->dev_if->dev_global_regs,
+ DWC_DIEPMSK, 0, diepmsk);
+ }
+ }
+
+ spin_unlock_irqrestore(&pcd->lock, flags);
+ return 0;
+}
+
+/**
+ * This function cancels an I/O request from an EP.
+ */
+static int dwc_otg_pcd_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+ struct pcd_request *req;
+ struct pcd_ep *ep;
+ struct dwc_pcd *pcd;
+ unsigned long flags;
+
+ ep = container_of(_ep, struct pcd_ep, ep);
+ if (!_ep || !_req || (!ep->desc && ep->dwc_ep.num != 0)) {
+ pr_warning("%s, bad argument\n", __func__);
+ return -EINVAL;
+ }
+
+ pcd = ep->pcd;
+ if (!pcd->driver || pcd->gadget.speed == USB_SPEED_UNKNOWN) {
+ pr_warning("%s, bogus device state\n", __func__);
+ return -ESHUTDOWN;
+ }
+
+ spin_lock_irqsave(&pcd->lock, flags);
+
+ /* make sure it's actually queued on this endpoint */
+ list_for_each_entry(req, &ep->queue, queue)
+ if (&req->req == _req)
+ break;
+
+ if (&req->req != _req) {
+ spin_unlock_irqrestore(&pcd->lock, flags);
+ return -EINVAL;
+ }
+
+ if (!list_empty(&req->queue))
+ request_done(ep, req, -ECONNRESET);
+ else
+ req = NULL;
+
+ spin_unlock_irqrestore(&pcd->lock, flags);
+
+ return req ? 0 : -EOPNOTSUPP;
+}
+
+/**
+ * Set the EP STALL.
+ */
+void dwc_otg_ep_set_stall(struct core_if *core_if, struct dwc_ep *ep)
+{
+ u32 depctl = 0;
+ ulong depctl_addr;
+
+ if (ep->is_in) {
+ depctl_addr =
+ (core_if->dev_if->in_ep_regs[ep->num]) + DWC_DIEPCTL;
+ depctl = dwc_reg_read(depctl_addr, 0);
+
+ /* set the disable and stall bits */
+ if (DWC_DEPCTL_EPENA_RD(depctl))
+ depctl = DWC_DEPCTL_EPDIS_RW(depctl, 1);
+ depctl = DWC_DEPCTL_STALL_HNDSHK_RW(depctl, 1);
+ dwc_reg_write(depctl_addr, 0, depctl);
+ } else {
+ depctl_addr =
+ (core_if->dev_if->out_ep_regs[ep->num] + DWC_DOEPCTL);
+ depctl = dwc_reg_read(depctl_addr, 0);
+
+ /* set the stall bit */
+ depctl = DWC_DEPCTL_STALL_HNDSHK_RW(depctl, 1);
+ dwc_reg_write(depctl_addr, 0, depctl);
+ }
+}
+
+/**
+ * Clear the EP STALL.
+ */
+void dwc_otg_ep_clear_stall(struct core_if *core_if, struct dwc_ep *ep)
+{
+ u32 depctl = 0;
+ ulong depctl_addr;
+
+ if (ep->is_in == 1)
+ depctl_addr =
+ (core_if->dev_if->in_ep_regs[ep->num]) + DWC_DIEPCTL;
+ else
+ depctl_addr =
+ (core_if->dev_if->out_ep_regs[ep->num]) + DWC_DOEPCTL;
+
+ depctl = dwc_reg_read(depctl_addr, 0);
+
+ /* clear the stall bits */
+ depctl = DWC_DEPCTL_STALL_HNDSHK_RW(depctl, 0);
+
+ /*
+ * USB Spec 9.4.5: For endpoints using data toggle, regardless
+ * of whether an endpoint has the Halt feature set, a
+ * ClearFeature(ENDPOINT_HALT) request always results in the
+ * data toggle being reinitialized to DATA0.
+ */
+ if (ep->type == DWC_OTG_EP_TYPE_INTR ||
+ ep->type == DWC_OTG_EP_TYPE_BULK)
+ depctl = DWC_DEPCTL_SET_DATA0_PID_RW(depctl, 1);
+
+ dwc_reg_write(depctl_addr, 0, depctl);
+}
+
+/**
+ * usb_ep_set_halt stalls an endpoint.
+ *
+ * usb_ep_clear_halt clears an endpoint halt and resets its data
+ * toggle.
+ *
+ * Both of these functions are implemented with the same underlying
+ * function. The behavior depends on the val argument:
+ * - 0 means clear_halt.
+ * - 1 means set_halt,
+ * - 2 means clear stall lock flag.
+ * - 3 means set stall lock flag.
+ */
+static int dwc_otg_pcd_ep_set_halt_wedge(struct usb_ep *_ep,
+ int val, int wedged)
+{
+ int retval = 0;
+ unsigned long flags;
+ struct pcd_ep *ep;
+
+ ep = container_of(_ep, struct pcd_ep, ep);
+ if (!_ep || (!ep->desc && ep != &ep->pcd->ep0) ||
+ ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
+ pr_warning("%s, bad ep\n", __func__);
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&ep->pcd->lock, flags);
+
+ if (ep->dwc_ep.is_in && !list_empty(&ep->queue)) {
+ pr_warning("%s() %s XFer In process\n", __func__, _ep->name);
+ retval = -EAGAIN;
+ } else if (val == 0) {
+ ep->wedged = 0;
+ dwc_otg_ep_clear_stall(ep->pcd->otg_dev->core_if, &ep->dwc_ep);
+ } else if (val == 1) {
+ if (ep->dwc_ep.num == 0)
+ ep->pcd->ep0state = EP0_STALL;
+ if (wedged)
+ ep->wedged = 1;
+
+ ep->stopped = 1;
+ dwc_otg_ep_set_stall(ep->pcd->otg_dev->core_if, &ep->dwc_ep);
+ } else if (val == 2) {
+ ep->dwc_ep.stall_clear_flag = 0;
+ } else if (val == 3) {
+ ep->dwc_ep.stall_clear_flag = 1;
+ }
+
+ spin_unlock_irqrestore(&ep->pcd->lock, flags);
+ return retval;
+}
+static int dwc_otg_pcd_ep_set_halt(struct usb_ep *_ep, int val)
+{
+ return dwc_otg_pcd_ep_set_halt_wedge(_ep, val, 0);
+}
+static int dwc_otg_pcd_ep_set_wedge(struct usb_ep *_ep)
+{
+ return dwc_otg_pcd_ep_set_halt_wedge(_ep, 1, 1);
+}
+
+static struct usb_ep_ops dwc_otg_pcd_ep_ops = {
+ .enable = dwc_otg_pcd_ep_enable,
+ .disable = dwc_otg_pcd_ep_disable,
+ .alloc_request = dwc_otg_pcd_alloc_request,
+ .free_request = dwc_otg_pcd_free_request,
+ .queue = dwc_otg_pcd_ep_queue,
+ .dequeue = dwc_otg_pcd_ep_dequeue,
+ .set_halt = dwc_otg_pcd_ep_set_halt,
+ .set_wedge = dwc_otg_pcd_ep_set_wedge,
+ .fifo_status = NULL,
+ .fifo_flush = NULL,
+};
+
+/**
+ * Gets the current USB frame number from the DTS register. This is the frame
+ * number from the last SOF packet.
+ */
+static u32 dwc_otg_get_frame_number(struct core_if *core_if)
+{
+ u32 dsts;
+
+ dsts = dwc_reg_read(core_if->dev_if->dev_global_regs, DWC_DSTS);
+ return DWC_DSTS_SOFFN_RD(dsts);
+}
+
+/**
+ * The following gadget operations will be implemented in the DWC_otg
+ * PCD. Functions in the API that are not described below are not
+ * implemented.
+ *
+ * The Gadget API provides wrapper functions for each of the function
+ * pointers defined in usb_gadget_ops. The Gadget Driver calls the
+ * wrapper function, which then calls the underlying PCD function. The
+ * following sections are named according to the wrapper functions
+ * (except for ioctl, which doesn't have a wrapper function). Within
+ * each section, the corresponding DWC_otg PCD function name is
+ * specified.
+ *
+ */
+
+/**
+ *Gets the USB Frame number of the last SOF.
+ */
+static int dwc_otg_pcd_get_frame(struct usb_gadget *_gadget)
+{
+ if (!_gadget) {
+ return -ENODEV;
+ } else {
+ struct dwc_pcd *pcd;
+
+ pcd = container_of(_gadget, struct dwc_pcd, gadget);
+ dwc_otg_get_frame_number(GET_CORE_IF(pcd));
+ }
+
+ return 0;
+}
+
+/**
+ * This function is called when the SRP timer expires. The SRP should complete
+ * within 6 seconds.
+ */
+static void srp_timeout(unsigned long data)
+{
+ u32 gotgctl;
+ struct dwc_pcd *pcd = (struct dwc_pcd *)data;
+ struct core_if *core_if = pcd->otg_dev->core_if;
+ ulong addr = otg_ctl_reg(pcd);
+
+ gotgctl = dwc_reg_read(addr, 0);
+ core_if->srp_timer_started = 0;
+
+ if (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS &&
+ core_if->core_params->i2c_enable) {
+ pr_info("SRP Timeout\n");
+
+ if (core_if->srp_success && (gotgctl &
+ DWC_GCTL_BSESSION_VALID)) {
+ if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup)
+ core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->
+ p);
+
+ /* Clear Session Request */
+ gotgctl = 0;
+ gotgctl |= DWC_GCTL_SES_REQ;
+ dwc_reg_modify(addr, 0, gotgctl, 0);
+
+ core_if->srp_success = 0;
+ } else {
+ pr_err("Device not connected/responding\n");
+ gotgctl &= ~DWC_GCTL_SES_REQ;
+ dwc_reg_write(addr, 0, gotgctl);
+ }
+ } else if (gotgctl & DWC_GCTL_SES_REQ) {
+ pr_info("SRP Timeout\n");
+ pr_err("Device not connected/responding\n");
+
+ gotgctl &= ~DWC_GCTL_SES_REQ;
+ dwc_reg_write(addr, 0, gotgctl);
+ } else {
+ pr_info(" SRP GOTGCTL=%0x\n", gotgctl);
+ }
+}
+
+/**
+ * Start the SRP timer to detect when the SRP does not complete within
+ * 6 seconds.
+ */
+static void dwc_otg_pcd_start_srp_timer(struct dwc_pcd *pcd)
+{
+ struct timer_list *srp_timer = &pcd->srp_timer;
+
+ GET_CORE_IF(pcd)->srp_timer_started = 1;
+ init_timer(srp_timer);
+ srp_timer->function = srp_timeout;
+ srp_timer->data = (unsigned long)pcd;
+ srp_timer->expires = jiffies + (HZ * 6);
+
+ add_timer(srp_timer);
+}
+
+static void dwc_otg_pcd_initiate_srp(struct dwc_pcd *pcd)
+{
+ u32 mem;
+ u32 val;
+ ulong addr = otg_ctl_reg(pcd);
+
+ val = dwc_reg_read(addr, 0);
+ if (val & DWC_GCTL_SES_REQ) {
+ pr_err("Session Request Already active!\n");
+ return;
+ }
+
+ pr_notice("Session Request Initated\n");
+ mem = dwc_reg_read(addr, 0);
+ mem |= DWC_GCTL_SES_REQ;
+ dwc_reg_write(addr, 0, mem);
+
+ /* Start the SRP timer */
+ dwc_otg_pcd_start_srp_timer(pcd);
+ return;
+}
+
+static void dwc_otg_pcd_remote_wakeup(struct dwc_pcd *pcd, int set)
+{
+ u32 dctl = 0;
+ ulong addr = dev_ctl_reg(pcd);
+
+ if (dwc_otg_is_device_mode(GET_CORE_IF(pcd))) {
+ if (pcd->remote_wakeup_enable) {
+ if (set) {
+ dctl = DEC_DCTL_REMOTE_WAKEUP_SIG(dctl, 1);
+ dwc_reg_modify(addr, 0, 0, dctl);
+ msleep(20);
+ dwc_reg_modify(addr, 0, dctl, 0);
+ }
+ }
+ }
+}
+
+/**
+ * Initiates Session Request Protocol (SRP) to wakeup the host if no
+ * session is in progress. If a session is already in progress, but
+ * the device is suspended, remote wakeup signaling is started.
+ *
+ */
+static int dwc_otg_pcd_wakeup(struct usb_gadget *_gadget)
+{
+ unsigned long flags;
+ struct dwc_pcd *pcd;
+ u32 dsts;
+ u32 gotgctl;
+
+ if (!_gadget)
+ return -ENODEV;
+ else
+ pcd = container_of(_gadget, struct dwc_pcd, gadget);
+
+ spin_lock_irqsave(&pcd->lock, flags);
+
+ /*
+ * This function starts the Protocol if no session is in progress. If
+ * a session is already in progress, but the device is suspended,
+ * remote wakeup signaling is started.
+ */
+
+ /* Check if valid session */
+ gotgctl = dwc_reg_read(otg_ctl_reg(pcd), 0);
+ if (gotgctl & DWC_GCTL_BSESSION_VALID) {
+ /* Check if suspend state */
+ dsts = dwc_reg_read(dev_sts_reg(pcd), 0);
+ if (DWC_DSTS_SUSP_STS_RD(dsts))
+ dwc_otg_pcd_remote_wakeup(pcd, 1);
+ } else {
+ dwc_otg_pcd_initiate_srp(pcd);
+ }
+
+ spin_unlock_irqrestore(&pcd->lock, flags);
+ return 0;
+}
+
+static int dwc_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA)
+{
+ struct dwc_pcd *pcd = container_of(gadget, struct dwc_pcd, gadget);
+
+ if (pcd->otg_dev->core_if->xceiv)
+ return -EOPNOTSUPP;
+
+ return otg_set_power(pcd->otg_dev->core_if->xceiv, mA);
+
+}
+static int dwc_gadget_start(struct usb_gadget_driver *driver,
+ int (*bind) (struct usb_gadget *));
+static int dwc_gadget_stop(struct usb_gadget_driver *driver);
+
+static const struct usb_gadget_ops dwc_otg_pcd_ops = {
+ .get_frame = dwc_otg_pcd_get_frame,
+ .wakeup = dwc_otg_pcd_wakeup,
+ .start = dwc_gadget_start,
+ .stop = dwc_gadget_stop,
+ .vbus_draw = dwc_gadget_vbus_draw,
+};
+
+/**
+ * This function updates the otg values in the gadget structure.
+ */
+void dwc_otg_pcd_update_otg(struct dwc_pcd *pcd, const unsigned reset)
+{
+ if (!pcd->gadget.is_otg)
+ return;
+
+ if (reset) {
+ pcd->b_hnp_enable = 0;
+ pcd->a_hnp_support = 0;
+ pcd->a_alt_hnp_support = 0;
+ }
+
+ pcd->gadget.b_hnp_enable = pcd->b_hnp_enable;
+ pcd->gadget.a_hnp_support = pcd->a_hnp_support;
+ pcd->gadget.a_alt_hnp_support = pcd->a_alt_hnp_support;
+}
+
+/**
+ * This function is the top level PCD interrupt handler.
+ */
+static irqreturn_t dwc_otg_pcd_irq(int _irq, void *dev)
+{
+ struct dwc_pcd *pcd = dev;
+ int retval;
+
+ retval = dwc_otg_pcd_handle_intr(pcd);
+ return IRQ_RETVAL(retval);
+}
+
+/**
+ * PCD Callback function for initializing the PCD when switching to
+ * device mode.
+ */
+static int dwc_otg_pcd_start_cb(void *_p)
+{
+ struct dwc_pcd *pcd = (struct dwc_pcd *)_p;
+
+ /* Initialize the Core for Device mode. */
+ if (dwc_otg_is_device_mode(GET_CORE_IF(pcd)))
+ dwc_otg_core_dev_init(GET_CORE_IF(pcd));
+
+ return 1;
+}
+
+/**
+ * PCD Callback function for stopping the PCD when switching to Host
+ * mode.
+ */
+static int dwc_otg_pcd_stop_cb(void *_p)
+{
+ dwc_otg_pcd_stop((struct dwc_pcd *)_p);
+ return 1;
+}
+
+/**
+ * PCD Callback function for notifying the PCD when resuming from
+ * suspend.
+ *
+ * @param _p void pointer to the <code>struct dwc_pcd</code>
+ */
+static int dwc_otg_pcd_suspend_cb(void *_p)
+{
+ struct dwc_pcd *pcd = (struct dwc_pcd *)_p;
+
+ if (pcd->driver && pcd->driver->suspend) {
+ spin_unlock(&pcd->lock);
+ pcd->driver->suspend(&pcd->gadget);
+ spin_lock(&pcd->lock);
+ }
+ return 1;
+}
+
+/**
+ * PCD Callback function for notifying the PCD when resuming from
+ * suspend.
+ */
+static int dwc_otg_pcd_resume_cb(void *_p)
+{
+ struct dwc_pcd *pcd = (struct dwc_pcd *)_p;
+ struct core_if *core_if = pcd->otg_dev->core_if;
+
+ if (pcd->driver && pcd->driver->resume) {
+ spin_unlock(&pcd->lock);
+ pcd->driver->resume(&pcd->gadget);
+ spin_lock(&pcd->lock);
+ }
+
+ /* Maybe stop the SRP timeout timer. */
+ if (need_stop_srp_timer(core_if)) {
+ core_if->srp_timer_started = 0;
+ del_timer_sync(&pcd->srp_timer);
+ }
+ return 1;
+}
+
+/**
+ * PCD Callback structure for handling mode switching.
+ */
+static struct cil_callbacks pcd_callbacks = {
+ .start = dwc_otg_pcd_start_cb,
+ .stop = dwc_otg_pcd_stop_cb,
+ .suspend = dwc_otg_pcd_suspend_cb,
+ .resume_wakeup = dwc_otg_pcd_resume_cb,
+ .p = NULL, /* Set at registration */
+};
+
+/**
+ * Tasklet
+ *
+ */
+static void start_xfer_tasklet_func(unsigned long data)
+{
+ struct dwc_pcd *pcd = (struct dwc_pcd *)data;
+ u32 diepctl = 0;
+ int num = pcd->otg_dev->core_if->dev_if->num_in_eps;
+ u32 i;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pcd->lock, flags);
+ diepctl = dwc_reg_read(in_ep_ctl_reg(pcd, 0), 0);
+
+ if (pcd->ep0.queue_sof) {
+ pcd->ep0.queue_sof = 0;
+ dwc_start_next_request(&pcd->ep0);
+ }
+
+ for (i = 0; i < num; i++) {
+ u32 diepctl = 0;
+
+ diepctl = dwc_reg_read(in_ep_ctl_reg(pcd, i), 0);
+ if (pcd->in_ep[i].queue_sof) {
+ pcd->in_ep[i].queue_sof = 0;
+ dwc_start_next_request(&pcd->in_ep[i]);
+ }
+ }
+ spin_unlock_irqrestore(&pcd->lock, flags);
+}
+
+static struct tasklet_struct start_xfer_tasklet = {
+ .next = NULL,
+ .state = 0,
+ .count = ATOMIC_INIT(0),
+ .func = start_xfer_tasklet_func,
+ .data = 0,
+};
+
+/**
+ * This function initialized the pcd Dp structures to there default
+ * state.
+ */
+static void dwc_otg_pcd_reinit(struct dwc_pcd *pcd)
+{
+ static const char *names[] = {
+ "ep0", "ep1in", "ep2in", "ep3in", "ep4in", "ep5in",
+ "ep6in", "ep7in", "ep8in", "ep9in", "ep10in", "ep11in",
+ "ep12in", "ep13in", "ep14in", "ep15in", "ep1out", "ep2out",
+ "ep3out", "ep4out", "ep5out", "ep6out", "ep7out", "ep8out",
+ "ep9out", "ep10out", "ep11out", "ep12out", "ep13out",
+ "ep14out", "ep15out"
+ };
+ u32 i;
+ int in_ep_cntr, out_ep_cntr;
+ u32 hwcfg1;
+ u32 num_in_eps = (GET_CORE_IF(pcd))->dev_if->num_in_eps;
+ u32 num_out_eps = (GET_CORE_IF(pcd))->dev_if->num_out_eps;
+ struct pcd_ep *ep;
+
+ INIT_LIST_HEAD(&pcd->gadget.ep_list);
+ pcd->gadget.ep0 = &pcd->ep0.ep;
+ pcd->gadget.speed = USB_SPEED_UNKNOWN;
+ INIT_LIST_HEAD(&pcd->gadget.ep0->ep_list);
+
+ /* Initialize the EP0 structure. */
+ ep = &pcd->ep0;
+
+ /* Init EP structure */
+ ep->desc = NULL;
+ ep->pcd = pcd;
+ ep->stopped = 1;
+
+ /* Init DWC ep structure */
+ ep->dwc_ep.num = 0;
+ ep->dwc_ep.active = 0;
+ ep->dwc_ep.tx_fifo_num = 0;
+
+ /* Control until ep is actvated */
+ ep->dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL;
+ ep->dwc_ep.maxpacket = MAX_PACKET_SIZE;
+ ep->dwc_ep.dma_addr = 0;
+ ep->dwc_ep.start_xfer_buff = NULL;
+ ep->dwc_ep.xfer_buff = NULL;
+ ep->dwc_ep.xfer_len = 0;
+ ep->dwc_ep.xfer_count = 0;
+ ep->dwc_ep.sent_zlp = 0;
+ ep->dwc_ep.total_len = 0;
+ ep->queue_sof = 0;
+
+ /* Init the usb_ep structure. */
+ ep->ep.name = names[0];
+ ep->ep.ops = &dwc_otg_pcd_ep_ops;
+
+ ep->ep.maxpacket = MAX_PACKET_SIZE;
+ list_add_tail(&ep->ep.ep_list, &pcd->gadget.ep_list);
+ INIT_LIST_HEAD(&ep->queue);
+
+ /* Initialize the EP structures. */
+ in_ep_cntr = 0;
+ hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1 >> 3;
+
+ for (i = 1; in_ep_cntr < num_in_eps; i++) {
+ if (!(hwcfg1 & 0x1)) {
+ struct pcd_ep *ep = &pcd->in_ep[in_ep_cntr];
+
+ in_ep_cntr++;
+ /* Init EP structure */
+ ep->desc = NULL;
+ ep->pcd = pcd;
+ ep->stopped = 1;
+
+ /* Init DWC ep structure */
+ ep->dwc_ep.is_in = 1;
+ ep->dwc_ep.num = i;
+ ep->dwc_ep.active = 0;
+ ep->dwc_ep.tx_fifo_num = 0;
+
+ /* Control until ep is actvated */
+ ep->dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL;
+ ep->dwc_ep.maxpacket = MAX_PACKET_SIZE;
+ ep->dwc_ep.dma_addr = 0;
+ ep->dwc_ep.start_xfer_buff = NULL;
+ ep->dwc_ep.xfer_buff = NULL;
+ ep->dwc_ep.xfer_len = 0;
+ ep->dwc_ep.xfer_count = 0;
+ ep->dwc_ep.sent_zlp = 0;
+ ep->dwc_ep.total_len = 0;
+ ep->queue_sof = 0;
+
+ ep->ep.name = names[i];
+ ep->ep.ops = &dwc_otg_pcd_ep_ops;
+
+ ep->ep.maxpacket = MAX_PACKET_SIZE;
+ list_add_tail(&ep->ep.ep_list, &pcd->gadget.ep_list);
+ INIT_LIST_HEAD(&ep->queue);
+ }
+ hwcfg1 >>= 2;
+ }
+
+ out_ep_cntr = 0;
+ hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1 >> 2;
+ for (i = 1; out_ep_cntr < num_out_eps; i++) {
+ if (!(hwcfg1 & 0x1)) {
+ struct pcd_ep *ep = &pcd->out_ep[out_ep_cntr];
+
+ out_ep_cntr++;
+ /* Init EP structure */
+ ep->desc = NULL;
+ ep->pcd = pcd;
+ ep->stopped = 1;
+
+ /* Init DWC ep structure */
+ ep->dwc_ep.is_in = 0;
+ ep->dwc_ep.num = i;
+ ep->dwc_ep.active = 0;
+ ep->dwc_ep.tx_fifo_num = 0;
+
+ /* Control until ep is actvated */
+ ep->dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL;
+ ep->dwc_ep.maxpacket = MAX_PACKET_SIZE;
+ ep->dwc_ep.dma_addr = 0;
+ ep->dwc_ep.start_xfer_buff = NULL;
+ ep->dwc_ep.xfer_buff = NULL;
+ ep->dwc_ep.xfer_len = 0;
+ ep->dwc_ep.xfer_count = 0;
+ ep->dwc_ep.sent_zlp = 0;
+ ep->dwc_ep.total_len = 0;
+ ep->queue_sof = 0;
+
+ ep->ep.name = names[15 + i];
+ ep->ep.ops = &dwc_otg_pcd_ep_ops;
+
+ ep->ep.maxpacket = MAX_PACKET_SIZE;
+ list_add_tail(&ep->ep.ep_list, &pcd->gadget.ep_list);
+ INIT_LIST_HEAD(&ep->queue);
+ }
+ hwcfg1 >>= 2;
+ }
+
+ /* remove ep0 from the list. There is a ep0 pointer. */
+ list_del_init(&pcd->ep0.ep.ep_list);
+
+ pcd->ep0state = EP0_DISCONNECT;
+ pcd->ep0.ep.maxpacket = MAX_EP0_SIZE;
+ pcd->ep0.dwc_ep.maxpacket = MAX_EP0_SIZE;
+ pcd->ep0.dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL;
+}
+
+/**
+ * This function releases the Gadget device.
+ * required by device_unregister().
+ */
+static void dwc_otg_pcd_gadget_release(struct device *dev)
+{
+ pr_info("%s(%p)\n", __func__, dev);
+}
+
+/**
+ * Allocates the buffers for the setup packets when the PCD portion of the
+ * driver is first initialized.
+ */
+static int init_pkt_buffs(struct device *dev, struct dwc_pcd *pcd)
+{
+ if (pcd->otg_dev->core_if->dma_enable) {
+ pcd->dwc_pool = dma_pool_create("dwc_otg_pcd", dev,
+ sizeof(*pcd->setup_pkt) * 5, 32,
+ 0);
+ if (!pcd->dwc_pool)
+ return -ENOMEM;
+ pcd->setup_pkt = dma_pool_alloc(pcd->dwc_pool, GFP_KERNEL,
+ &pcd->setup_pkt_dma_handle);
+ if (!pcd->setup_pkt)
+ goto error;
+ pcd->status_buf = dma_pool_alloc(pcd->dwc_pool, GFP_KERNEL,
+ &pcd->status_buf_dma_handle);
+ if (!pcd->status_buf)
+ goto error1;
+ } else {
+ pcd->setup_pkt = kmalloc(sizeof(*pcd->setup_pkt) * 5,
+ GFP_KERNEL);
+ if (!pcd->setup_pkt)
+ return -ENOMEM;
+ pcd->status_buf = kmalloc(sizeof(u16), GFP_KERNEL);
+ if (!pcd->status_buf) {
+ kfree(pcd->setup_pkt);
+ return -ENOMEM;
+ }
+ }
+ return 0;
+
+error1:
+ dma_pool_free(pcd->dwc_pool, pcd->setup_pkt, pcd->setup_pkt_dma_handle);
+error:
+ dma_pool_destroy(pcd->dwc_pool);
+ return -ENOMEM;
+}
+
+/**
+ * This function initializes the PCD portion of the driver.
+ */
+int dwc_otg_pcd_init(struct device *dev)
+{
+ static const char pcd_name[] = "dwc_otg_pcd";
+ struct dwc_pcd *pcd;
+ struct dwc_otg_device *otg_dev = dev_get_drvdata(dev);
+ struct core_if *core_if = otg_dev->core_if;
+ int retval;
+
+ /* Allocate PCD structure */
+ pcd = kzalloc(sizeof(*pcd), GFP_KERNEL);
+ if (!pcd) {
+ retval = -ENOMEM;
+ goto err;
+ }
+
+ spin_lock_init(&pcd->lock);
+
+ otg_dev->pcd = pcd;
+ s_pcd = pcd;
+ pcd->gadget.name = pcd_name;
+
+ dev_set_name(&pcd->gadget.dev, "gadget");
+ pcd->otg_dev = otg_dev;
+ pcd->gadget.dev.parent = dev;
+ pcd->gadget.dev.release = dwc_otg_pcd_gadget_release;
+ pcd->gadget.ops = &dwc_otg_pcd_ops;
+
+ if (DWC_HWCFG4_DED_FIFO_ENA_RD(core_if->hwcfg4))
+ pr_info("Dedicated Tx FIFOs mode\n");
+ else
+ pr_info("Shared Tx FIFO mode\n");
+
+ pcd->gadget.is_dualspeed = check_is_dual_speed(core_if);
+ pcd->gadget.is_otg = check_is_otg(core_if);
+
+ /* Register the gadget device */
+ retval = device_register(&pcd->gadget.dev);
+ if (retval)
+ goto unreg_device;
+
+
+ /* hook up the gadget*/
+ retval = usb_add_gadget_udc(dev, &pcd->gadget);
+ if (retval)
+ goto unreg_device;
+
+ /* Initialized the Core for Device mode. */
+ if (dwc_otg_is_device_mode(core_if))
+ dwc_otg_core_dev_init(core_if);
+
+ /* Initialize EP structures */
+ dwc_otg_pcd_reinit(pcd);
+
+ /* Register the PCD Callbacks. */
+ dwc_otg_cil_register_pcd_callbacks(core_if, &pcd_callbacks, pcd);
+
+ /* Setup interupt handler */
+ retval = request_irq(otg_dev->irq, dwc_otg_pcd_irq, IRQF_SHARED,
+ pcd->gadget.name, pcd);
+ if (retval) {
+ pr_err("request of irq%d failed\n", otg_dev->irq);
+ retval = -EBUSY;
+ goto err_cleanup;
+ }
+
+ /* Initialize the DMA buffer for SETUP packets */
+ retval = init_pkt_buffs(dev, pcd);
+ if (retval)
+ goto err_cleanup;
+
+ /* Initialize tasklet */
+ start_xfer_tasklet.data = (unsigned long)pcd;
+ pcd->start_xfer_tasklet = &start_xfer_tasklet;
+ return 0;
+
+err_cleanup:
+ kfree(pcd);
+ otg_dev->pcd = NULL;
+ s_pcd = NULL;
+
+unreg_device:
+ device_unregister(&pcd->gadget.dev);
+
+err:
+ return retval;
+}
+
+/**
+ * Cleanup the PCD.
+ */
+void __devexit dwc_otg_pcd_remove(struct device *dev)
+{
+ struct dwc_otg_device *otg_dev = dev_get_drvdata(dev);
+ struct dwc_pcd *pcd = otg_dev->pcd;
+
+ /* Free the IRQ */
+ free_irq(otg_dev->irq, pcd);
+
+ /* start with the driver above us */
+ if (pcd->driver) {
+ /* should have been done already by driver model core */
+ pr_warning("driver '%s' is still registered\n",
+ pcd->driver->driver.name);
+ usb_gadget_unregister_driver(pcd->driver);
+ }
+ if (pcd->start_xfer_tasklet)
+ tasklet_kill(pcd->start_xfer_tasklet);
+ tasklet_kill(&pcd->test_mode_tasklet);
+
+ device_unregister(&pcd->gadget.dev);
+ if (GET_CORE_IF(pcd)->dma_enable) {
+ dma_pool_free(pcd->dwc_pool, pcd->setup_pkt,
+ pcd->setup_pkt_dma_handle);
+ dma_pool_free(pcd->dwc_pool, pcd->status_buf,
+ pcd->status_buf_dma_handle);
+ dma_pool_destroy(pcd->dwc_pool);
+ } else {
+ kfree(pcd->setup_pkt);
+ kfree(pcd->status_buf);
+ }
+ kfree(pcd);
+ otg_dev->pcd = NULL;
+}
+
+/**
+ * This function registers a gadget driver with the PCD.
+ *
+ * When a driver is successfully registered, it will receive control
+ * requests including set_configuration(), which enables non-control
+ * requests. then usb traffic follows until a disconnect is reported.
+ * then a host may connect again, or the driver might get unbound.
+ */
+static int dwc_gadget_start(struct usb_gadget_driver *driver,
+ int (*bind) (struct usb_gadget *))
+{
+ int retval;
+
+ if (!driver || driver->speed == USB_SPEED_UNKNOWN || !bind ||
+ !driver->unbind || !driver->disconnect || !driver->setup)
+ return -EINVAL;
+
+ if (s_pcd == NULL)
+ return -ENODEV;
+
+ if (s_pcd->driver != NULL)
+ return -EBUSY;
+
+ /* hook up the driver */
+ s_pcd->driver = driver;
+ s_pcd->gadget.dev.driver = &driver->driver;
+
+ retval = bind(&s_pcd->gadget);
+ if (retval) {
+ struct core_if *core_if;
+
+ pr_err("bind to driver %s --> error %d\n",
+ driver->driver.name, retval);
+ core_if = s_pcd->otg_dev->core_if;
+ otg_set_peripheral(core_if->xceiv, &s_pcd->gadget);
+ s_pcd->driver = NULL;
+ s_pcd->gadget.dev.driver = NULL;
+ return retval;
+ }
+ return 0;
+}
+
+/**
+ * This function unregisters a gadget driver
+ */
+static int dwc_gadget_stop(struct usb_gadget_driver *driver)
+{
+ struct core_if *core_if;
+
+ if (!s_pcd)
+ return -ENODEV;
+ if (!driver || driver != s_pcd->driver)
+ return -EINVAL;
+
+ core_if = s_pcd->otg_dev->core_if;
+ core_if->xceiv->state = OTG_STATE_UNDEFINED;
+ otg_set_peripheral(core_if->xceiv, NULL);
+
+ driver->unbind(&s_pcd->gadget);
+ s_pcd->driver = NULL;
+
+ return 0;
+}
diff --git a/drivers/usb/dwc/pcd.h b/drivers/usb/dwc/pcd.h
new file mode 100644
index 0000000..0000446
--- /dev/null
+++ b/drivers/usb/dwc/pcd.h
@@ -0,0 +1,139 @@
+/*
+ * DesignWare HS OTG controller driver
+ * Copyright (C) 2006 Synopsys, Inc.
+ * Portions Copyright (C) 2010 Applied Micro Circuits Corporation.
+ *
+ * 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 version 2 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
+ * or write to the Free Software Foundation, Inc., 51 Franklin Street,
+ * Suite 500, Boston, MA 02110-1335 USA.
+ *
+ * Based on Synopsys driver version 2.60a
+ * Modified by Mark Miesfeld <mmiesfeld@apm.com>
+ * Modified by Stefan Roese <sr@denx.de>, DENX Software Engineering
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL SYNOPSYS, INC. 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.
+ *
+ */
+
+#if !defined(__DWC_PCD_H__)
+#define __DWC_PCD_H__
+
+#include "driver.h"
+
+/*
+ * This file contains the structures, constants, and interfaces for
+ * the Perpherial Contoller Driver (PCD).
+ *
+ * The Peripheral Controller Driver (PCD) for Linux will implement the
+ * Gadget API, so that the existing Gadget drivers can be used. For
+ * the Mass Storage Function driver the File-backed USB Storage Gadget
+ * (FBS) driver will be used. The FBS driver supports the
+ * Control-Bulk (CB), Control-Bulk-Interrupt (CBI), and Bulk-Only
+ * transports.
+ *
+ */
+
+/* Invalid DMA Address */
+#define DMA_ADDR_INVALID (~(dma_addr_t) 0)
+/* Maxpacket size for EP0 */
+#define MAX_EP0_SIZE 64
+/* Maxpacket size for any EP */
+#define MAX_PACKET_SIZE 1024
+
+/*
+ * Get the pointer to the core_if from the pcd pointer.
+ */
+#define GET_CORE_IF(_pcd) (_pcd->otg_dev->core_if)
+
+/*
+ * DWC_otg request structure.
+ * This structure is a list of requests.
+ */
+struct pcd_request {
+ struct usb_request req; /* USB Request. */
+ struct list_head queue; /* queue of these requests. */
+ unsigned mapped:1;
+};
+
+static inline ulong in_ep_int_reg(struct dwc_pcd *pd, int i)
+{
+ return GET_CORE_IF(pd)->dev_if->in_ep_regs[i] + DWC_DIEPINT;
+}
+static inline ulong out_ep_int_reg(struct dwc_pcd *pd, int i)
+{
+ return GET_CORE_IF(pd)->dev_if->out_ep_regs[i] + DWC_DOEPINT;
+}
+static inline ulong in_ep_ctl_reg(struct dwc_pcd *pd, int i)
+{
+ return GET_CORE_IF(pd)->dev_if->in_ep_regs[i] + DWC_DIEPCTL;
+}
+
+static inline ulong out_ep_ctl_reg(struct dwc_pcd *pd, int i)
+{
+ return GET_CORE_IF(pd)->dev_if->out_ep_regs[i] + DWC_DOEPCTL;
+}
+
+static inline ulong dev_ctl_reg(struct dwc_pcd *pd)
+{
+ return GET_CORE_IF(pd)->dev_if->dev_global_regs +
+ DWC_DCTL;
+}
+
+static inline ulong dev_diepmsk_reg(struct dwc_pcd *pd)
+{
+ return GET_CORE_IF(pd)->dev_if->dev_global_regs +
+ DWC_DIEPMSK;
+}
+
+static inline ulong dev_sts_reg(struct dwc_pcd *pd)
+{
+ return GET_CORE_IF(pd)->dev_if->dev_global_regs +
+ DWC_DSTS;
+}
+
+static inline ulong otg_ctl_reg(struct dwc_pcd *pd)
+{
+ return GET_CORE_IF(pd)->core_global_regs + DWC_GOTGCTL;
+}
+
+extern int dwc_otg_pcd_init(struct device *dev);
+
+/*
+ * The following functions support managing the DWC_otg controller in device
+ * mode.
+ */
+extern void dwc_otg_ep_activate(struct core_if *core_if, struct dwc_ep *ep);
+extern void dwc_otg_ep_start_transfer(struct core_if *_if, struct dwc_ep *ep);
+extern void dwc_otg_ep_set_stall(struct core_if *core_if, struct dwc_ep *ep);
+extern void dwc_otg_ep_clear_stall(struct core_if *core_if, struct dwc_ep *ep);
+extern void dwc_otg_pcd_remove(struct device *dev);
+extern int dwc_otg_pcd_handle_intr(struct dwc_pcd *pcd);
+extern void dwc_otg_pcd_stop(struct dwc_pcd *pcd);
+extern void request_nuke(struct pcd_ep *ep);
+extern void dwc_otg_pcd_update_otg(struct dwc_pcd *pcd, const unsigned reset);
+extern void dwc_otg_ep0_start_transfer(struct core_if *_if, struct dwc_ep *ep);
+
+extern void request_done(struct pcd_ep *ep, struct pcd_request *req,
+ int _status);
+
+extern void dwc_start_next_request(struct pcd_ep *ep);
+#endif
diff --git a/drivers/usb/dwc/pcd_intr.c b/drivers/usb/dwc/pcd_intr.c
new file mode 100644
index 0000000..ea0ce78
--- /dev/null
+++ b/drivers/usb/dwc/pcd_intr.c
@@ -0,0 +1,2312 @@
+/*
+ * DesignWare HS OTG controller driver
+ * Copyright (C) 2006 Synopsys, Inc.
+ * Portions Copyright (C) 2010 Applied Micro Circuits Corporation.
+ *
+ * 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 version 2 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
+ * or write to the Free Software Foundation, Inc., 51 Franklin Street,
+ * Suite 500, Boston, MA 02110-1335 USA.
+ *
+ * Based on Synopsys driver version 2.60a
+ * Modified by Mark Miesfeld <mmiesfeld@apm.com>
+ * Modified by Stefan Roese <sr@denx.de>, DENX Software Engineering
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL SYNOPSYS, INC. BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "driver.h"
+#include "pcd.h"
+
+/**
+ * This function returns pointer to in ep struct with number num
+ */
+static struct pcd_ep *get_in_ep(struct dwc_pcd *pcd, u32 num)
+{
+ if (num == 0) {
+ return &pcd->ep0;
+ } else {
+ u32 i;
+ int num_in_eps = GET_CORE_IF(pcd)->dev_if->num_in_eps;
+
+ for (i = 0; i < num_in_eps; ++i) {
+ if (pcd->in_ep[i].dwc_ep.num == num)
+ return &pcd->in_ep[i];
+ }
+ }
+ return NULL;
+}
+
+/**
+ * This function returns pointer to out ep struct with number num
+ */
+static struct pcd_ep *get_out_ep(struct dwc_pcd *pcd, u32 num)
+{
+ if (num == 0) {
+ return &pcd->ep0;
+ } else {
+ u32 i;
+ int num_out_eps = GET_CORE_IF(pcd)->dev_if->num_out_eps;
+
+ for (i = 0; i < num_out_eps; ++i) {
+ if (pcd->out_ep[i].dwc_ep.num == num)
+ return &pcd->out_ep[i];
+ }
+ }
+ return NULL;
+}
+
+/**
+ * This functions gets a pointer to an EP from the wIndex address
+ * value of the control request.
+ */
+static struct pcd_ep *get_ep_by_addr(struct dwc_pcd *pcd, u16 index)
+{
+ struct pcd_ep *ep;
+
+ if (!(index & USB_ENDPOINT_NUMBER_MASK))
+ return &pcd->ep0;
+
+ list_for_each_entry(ep, &pcd->gadget.ep_list, ep.ep_list) {
+ u8 bEndpointAddress;
+
+ if (!ep->desc)
+ continue;
+
+ bEndpointAddress = ep->desc->bEndpointAddress;
+ if ((index ^ bEndpointAddress) & USB_DIR_IN)
+ continue;
+
+ if ((index & 0x0f) == (bEndpointAddress & 0x0f))
+ return ep;
+ }
+ return NULL;
+}
+
+/**
+ * This function checks the EP request queue, if the queue is not
+ * empty the next request is started.
+ */
+void dwc_start_next_request(struct pcd_ep *ep)
+{
+ if (!list_empty(&ep->queue)) {
+ struct pcd_request *req;
+
+ req = list_entry(ep->queue.next, struct pcd_request, queue);
+
+ /* Setup and start the Transfer */
+ ep->dwc_ep.start_xfer_buff = req->req.buf;
+ ep->dwc_ep.xfer_buff = req->req.buf;
+ ep->dwc_ep.xfer_len = req->req.length;
+ ep->dwc_ep.xfer_count = 0;
+ ep->dwc_ep.dma_addr = req->req.dma;
+ ep->dwc_ep.sent_zlp = 0;
+ ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
+
+ /*
+ * Added-sr: 2007-07-26
+ *
+ * When a new transfer will be started, mark this
+ * endpoint as active. This way it will be blocked
+ * for further transfers, until the current transfer
+ * is finished.
+ */
+ if (dwc_has_feature(GET_CORE_IF(ep->pcd), DWC_LIMITED_XFER))
+ ep->dwc_ep.active = 1;
+
+ dwc_otg_ep_start_transfer(GET_CORE_IF(ep->pcd), &ep->dwc_ep);
+ }
+}
+
+/**
+ * This function handles the SOF Interrupts. At this time the SOF
+ * Interrupt is disabled.
+ */
+static int dwc_otg_pcd_handle_sof_intr(struct dwc_pcd *pcd)
+{
+ struct core_if *core_if = GET_CORE_IF(pcd);
+ u32 gintsts;
+
+ /* Clear interrupt */
+ gintsts = 0;
+ gintsts |= DWC_INTMSK_STRT_OF_FRM;
+ dwc_reg_write((core_if->core_global_regs), DWC_GINTSTS, gintsts);
+ return 1;
+}
+
+/**
+ * This function reads the 8 bytes of the setup packet from the Rx FIFO into the
+ * destination buffer. It is called from the Rx Status Queue Level (RxStsQLvl)
+ * interrupt routine when a SETUP packet has been received in Slave mode.
+ */
+static void dwc_otg_read_setup_packet(struct core_if *core_if, u32 * dest)
+{
+ dest[0] = dwc_read_fifo32(core_if->data_fifo[0]);
+ dest[1] = dwc_read_fifo32(core_if->data_fifo[0]);
+}
+
+/**
+ * This function handles the Rx Status Queue Level Interrupt, which
+ * indicates that there is a least one packet in the Rx FIFO. The
+ * packets are moved from the FIFO to memory, where they will be
+ * processed when the Endpoint Interrupt Register indicates Transfer
+ * Complete or SETUP Phase Done.
+ *
+ * Repeat the following until the Rx Status Queue is empty:
+ * -# Read the Receive Status Pop Register (GRXSTSP) to get Packet
+ * info
+ * -# If Receive FIFO is empty then skip to step Clear the interrupt
+ * and exit
+ * -# If SETUP Packet call dwc_otg_read_setup_packet to copy the
+ * SETUP data to the buffer
+ * -# If OUT Data Packet call dwc_otg_read_packet to copy the data
+ * to the destination buffer
+ */
+static int dwc_otg_pcd_handle_rx_status_q_level_intr(struct dwc_pcd *pcd)
+{
+ struct core_if *core_if = GET_CORE_IF(pcd);
+ ulong global_regs = core_if->core_global_regs;
+ u32 gintmask = 0;
+ u32 grxsts;
+ struct pcd_ep *ep;
+ u32 gintsts;
+
+ /* Disable the Rx Status Queue Level interrupt */
+ gintmask |= DWC_INTMSK_RXFIFO_NOT_EMPT;
+ dwc_reg_modify(global_regs, DWC_GINTMSK, gintmask, 0);
+
+ /* Get the Status from the top of the FIFO */
+ grxsts = dwc_reg_read(global_regs, DWC_GRXSTSP);
+
+ /* Get pointer to EP structure */
+ ep = get_out_ep(pcd, DWC_DM_RXSTS_CHAN_NUM_RD(grxsts));
+
+ switch (DWC_DM_RXSTS_PKT_STS_RD(grxsts)) {
+ case DWC_DSTS_GOUT_NAK:
+ break;
+ case DWC_STS_DATA_UPDT:
+ if ((grxsts & DWC_DM_RXSTS_BYTE_CNT) && ep->dwc_ep.xfer_buff) {
+ dwc_otg_read_packet(core_if, ep->dwc_ep.xfer_buff,
+ DWC_DM_RXSTS_BYTE_CNT_RD(grxsts));
+ ep->dwc_ep.xfer_count +=
+ DWC_DM_RXSTS_BYTE_CNT_RD(grxsts);
+ ep->dwc_ep.xfer_buff +=
+ DWC_DM_RXSTS_BYTE_CNT_RD(grxsts);
+ }
+ break;
+ case DWC_STS_XFER_COMP:
+ break;
+ case DWC_DSTS_SETUP_COMP:
+ break;
+ case DWC_DSTS_SETUP_UPDT:
+ dwc_otg_read_setup_packet(core_if, pcd->setup_pkt->d32);
+ ep->dwc_ep.xfer_count += DWC_DM_RXSTS_BYTE_CNT_RD(grxsts);
+ break;
+ default:
+ pr_err("RX_STS_Q Interrupt: Unknown status %d\n",
+ DWC_HM_RXSTS_PKT_STS_RD(grxsts));
+ break;
+ }
+
+ /* Enable the Rx Status Queue Level interrupt */
+ dwc_reg_modify(global_regs, DWC_GINTMSK, 0, gintmask);
+
+ /* Clear interrupt */
+ gintsts = 0;
+ gintsts |= DWC_INTSTS_RXFIFO_NOT_EMPT;
+ dwc_reg_write(global_regs, DWC_GINTSTS, gintsts);
+
+ return 1;
+}
+
+/**
+ * This function examines the Device IN Token Learning Queue to
+ * determine the EP number of the last IN token received. This
+ * implementation is for the Mass Storage device where there are only
+ * 2 IN EPs (Control-IN and BULK-IN).
+ *
+ * The EP numbers for the first six IN Tokens are in DTKNQR1 and there
+ * are 8 EP Numbers in each of the other possible DTKNQ Registers.
+ */
+static int get_ep_of_last_in_token(struct core_if *core_if)
+{
+ ulong regs = core_if->dev_if->dev_global_regs;
+ const u32 TOKEN_Q_DEPTH =
+ DWC_HWCFG2_DEV_TKN_Q_DEPTH_RD(core_if->hwcfg2);
+ /* Number of Token Queue Registers */
+ const int DTKNQ_REG_CNT = (TOKEN_Q_DEPTH + 7) / 8;
+ u32 dtknqr1 = 0;
+ u32 in_tkn_epnums[4];
+ int ndx;
+ u32 i;
+ u32 addr = regs + DWC_DTKNQR1;
+ int epnum = 0;
+
+ /* Read the DTKNQ Registers */
+ for (i = 0; i <= DTKNQ_REG_CNT; i++) {
+ in_tkn_epnums[i] = dwc_reg_read(addr, 0);
+
+ if (addr == (regs + DWC_DVBUSDIS))
+ addr = regs + DWC_DTKNQR3_DTHRCTL;
+ else
+ ++addr;
+ }
+
+ /* Copy the DTKNQR1 data to the bit field. */
+ dtknqr1 = in_tkn_epnums[0];
+
+ /* Get the EP numbers */
+ in_tkn_epnums[0] = DWC_DTKNQR1_EP_TKN_NO_RD(dtknqr1);
+ ndx = DWC_DTKNQR1_INT_TKN_Q_WR_PTR_RD(dtknqr1) - 1;
+
+ if (ndx == -1) {
+ /*
+ * Calculate the max queue position.
+ */
+ int cnt = TOKEN_Q_DEPTH;
+
+ if (TOKEN_Q_DEPTH <= 6)
+ cnt = TOKEN_Q_DEPTH - 1;
+ else if (TOKEN_Q_DEPTH <= 14)
+ cnt = TOKEN_Q_DEPTH - 7;
+ else if (TOKEN_Q_DEPTH <= 22)
+ cnt = TOKEN_Q_DEPTH - 15;
+ else
+ cnt = TOKEN_Q_DEPTH - 23;
+
+ epnum = (in_tkn_epnums[DTKNQ_REG_CNT - 1] >> (cnt * 4)) & 0xF;
+ } else {
+ if (ndx <= 5) {
+ epnum = (in_tkn_epnums[0] >> (ndx * 4)) & 0xF;
+ } else if (ndx <= 13) {
+ ndx -= 6;
+ epnum = (in_tkn_epnums[1] >> (ndx * 4)) & 0xF;
+ } else if (ndx <= 21) {
+ ndx -= 14;
+ epnum = (in_tkn_epnums[2] >> (ndx * 4)) & 0xF;
+ } else if (ndx <= 29) {
+ ndx -= 22;
+ epnum = (in_tkn_epnums[3] >> (ndx * 4)) & 0xF;
+ }
+ }
+
+ return epnum;
+}
+
+static inline int count_dwords(struct pcd_ep *ep, u32 len)
+{
+ if (len > ep->dwc_ep.maxpacket)
+ len = ep->dwc_ep.maxpacket;
+ return (len + 3) / 4;
+}
+
+/**
+ * This function writes a packet into the Tx FIFO associated with the EP. For
+ * non-periodic EPs the non-periodic Tx FIFO is written. For periodic EPs the
+ * periodic Tx FIFO associated with the EP is written with all packets for the
+ * next micro-frame.
+ *
+ * The buffer is padded to DWORD on a per packet basis in
+ * slave/dma mode if the MPS is not DWORD aligned. The last packet, if
+ * short, is also padded to a multiple of DWORD.
+ *
+ * ep->xfer_buff always starts DWORD aligned in memory and is a
+ * multiple of DWORD in length
+ *
+ * ep->xfer_len can be any number of bytes
+ *
+ * ep->xfer_count is a multiple of ep->maxpacket until the last packet
+ *
+ * FIFO access is DWORD
+ */
+static void dwc_otg_ep_write_packet(struct core_if *core_if, struct dwc_ep *ep,
+ int dma)
+{
+ u32 i;
+ u32 byte_count;
+ u32 dword_count;
+ u32 fifo;
+ u32 *data_buff = (u32 *) ep->xfer_buff;
+
+ if (ep->xfer_count >= ep->xfer_len)
+ return;
+
+ /* Find the byte length of the packet either short packet or MPS */
+ if ((ep->xfer_len - ep->xfer_count) < ep->maxpacket)
+ byte_count = ep->xfer_len - ep->xfer_count;
+ else
+ byte_count = ep->maxpacket;
+
+ /*
+ * Find the DWORD length, padded by extra bytes as neccessary if MPS
+ * is not a multiple of DWORD
+ */
+ dword_count = (byte_count + 3) / 4;
+
+ fifo = core_if->data_fifo[ep->num];
+
+ if (!dma)
+ for (i = 0; i < dword_count; i++, data_buff++)
+ dwc_write_fifo32(fifo, *data_buff);
+
+ ep->xfer_count += byte_count;
+ ep->xfer_buff += byte_count;
+ ep->dma_addr += byte_count;
+}
+
+/**
+ * This interrupt occurs when the non-periodic Tx FIFO is half-empty.
+ * The active request is checked for the next packet to be loaded into
+ * the non-periodic Tx FIFO.
+ */
+static int dwc_otg_pcd_handle_np_tx_fifo_empty_intr(struct dwc_pcd *pcd)
+{
+ struct core_if *core_if = GET_CORE_IF(pcd);
+ ulong global_regs = core_if->core_global_regs;
+ u32 txstatus = 0;
+ u32 gintsts = 0;
+ int epnum;
+ struct pcd_ep *ep;
+ u32 len;
+ int dwords;
+
+ /* Get the epnum from the IN Token Learning Queue. */
+ epnum = get_ep_of_last_in_token(core_if);
+ ep = get_in_ep(pcd, epnum);
+
+ txstatus = dwc_reg_read(global_regs, DWC_GNPTXSTS);
+
+ /*
+ * While there is space in the queue, space in the FIFO, and data to
+ * tranfer, write packets to the Tx FIFO
+ */
+ len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
+ dwords = count_dwords(ep, len);
+ while ((DWC_GNPTXSTS_NPTXQSPCAVAIL_RD(txstatus) > 0) &&
+ (DWC_GNPTXSTS_NPTXFSPCAVAIL_RD(txstatus) > dwords) &&
+ ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len) {
+ /*
+ * Added-sr: 2007-07-26
+ *
+ * When a new transfer will be started, mark this
+ * endpoint as active. This way it will be blocked
+ * for further transfers, until the current transfer
+ * is finished.
+ */
+ if (dwc_has_feature(core_if, DWC_LIMITED_XFER))
+ ep->dwc_ep.active = 1;
+
+ dwc_otg_ep_write_packet(core_if, &ep->dwc_ep, 0);
+ len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
+ dwords = count_dwords(ep, len);
+ txstatus = dwc_reg_read(global_regs, DWC_GNPTXSTS);
+ }
+
+ /* Clear nptxfempty interrupt */
+ gintsts |= DWC_INTMSK_RXFIFO_NOT_EMPT;
+ dwc_reg_write(global_regs, DWC_GINTSTS, gintsts);
+
+ /* Re-enable tx-fifo empty interrupt, if packets are stil pending */
+ if (len)
+ dwc_reg_modify(global_regs, DWC_GINTSTS, 0, gintsts);
+ return 1;
+}
+
+/**
+ * This function is called when dedicated Tx FIFO Empty interrupt occurs.
+ * The active request is checked for the next packet to be loaded into
+ * apropriate Tx FIFO.
+ */
+static int write_empty_tx_fifo(struct dwc_pcd *pcd, u32 epnum)
+{
+ struct core_if *core_if = GET_CORE_IF(pcd);
+ ulong regs;
+ u32 txstatus = 0;
+ struct pcd_ep *ep;
+ u32 len;
+ int dwords;
+ u32 diepint = 0;
+
+ ep = get_in_ep(pcd, epnum);
+ regs = core_if->dev_if->in_ep_regs[epnum];
+ txstatus = dwc_reg_read(regs, DWC_DTXFSTS);
+
+ /*
+ * While there is space in the queue, space in the FIFO and data to
+ * tranfer, write packets to the Tx FIFO
+ */
+ len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
+ dwords = count_dwords(ep, len);
+ while (DWC_DTXFSTS_TXFSSPC_AVAI_RD(txstatus) > dwords
+ && ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len
+ && ep->dwc_ep.xfer_len != 0) {
+ dwc_otg_ep_write_packet(core_if, &ep->dwc_ep, 0);
+ len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
+ dwords = count_dwords(ep, len);
+ txstatus = dwc_reg_read(regs, DWC_DTXFSTS);
+ }
+ /* Clear emptyintr */
+ diepint = DWC_DIEPINT_TXFIFO_EMPTY_RW(diepint, 1);
+ dwc_reg_write(in_ep_int_reg(pcd, epnum), 0, diepint);
+ return 1;
+}
+
+/**
+ * This function is called when the Device is disconnected. It stops any active
+ * requests and informs the Gadget driver of the disconnect.
+ */
+void dwc_otg_pcd_stop(struct dwc_pcd *pcd)
+{
+ int i, num_in_eps, num_out_eps;
+ struct pcd_ep *ep;
+ u32 intr_mask = 0;
+ ulong global_regs = GET_CORE_IF(pcd)->core_global_regs;
+
+ num_in_eps = GET_CORE_IF(pcd)->dev_if->num_in_eps;
+ num_out_eps = GET_CORE_IF(pcd)->dev_if->num_out_eps;
+
+ /* Don't disconnect drivers more than once */
+ if (pcd->ep0state == EP0_DISCONNECT)
+ return;
+ pcd->ep0state = EP0_DISCONNECT;
+
+ /* Reset the OTG state. */
+ dwc_otg_pcd_update_otg(pcd, 1);
+
+ /* Disable the NP Tx Fifo Empty Interrupt. */
+ intr_mask |= DWC_INTMSK_NP_TXFIFO_EMPT;
+ dwc_reg_modify(global_regs, DWC_GINTMSK, intr_mask, 0);
+
+ /* Flush the FIFOs */
+ dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd), 0);
+ dwc_otg_flush_rx_fifo(GET_CORE_IF(pcd));
+
+ /* Prevent new request submissions, kill any outstanding requests */
+ ep = &pcd->ep0;
+ request_nuke(ep);
+
+ /* Prevent new request submissions, kill any outstanding requests */
+ for (i = 0; i < num_in_eps; i++)
+ request_nuke((struct pcd_ep *)&pcd->in_ep[i]);
+
+ /* Prevent new request submissions, kill any outstanding requests */
+ for (i = 0; i < num_out_eps; i++)
+ request_nuke((struct pcd_ep *)&pcd->out_ep[i]);
+
+ /* Report disconnect; the driver is already quiesced */
+ if (pcd->driver && pcd->driver->disconnect) {
+ spin_unlock(&pcd->lock);
+ pcd->driver->disconnect(&pcd->gadget);
+ spin_lock(&pcd->lock);
+ }
+}
+
+/**
+ * This interrupt indicates that ...
+ */
+static int dwc_otg_pcd_handle_i2c_intr(struct dwc_pcd *pcd)
+{
+ u32 intr_mask = 0;
+ u32 gintsts;
+
+ pr_info("Interrupt handler not implemented for i2cintr\n");
+
+ /* Turn off and clean the interrupt */
+ intr_mask |= DWC_INTMSK_I2C_INTR;
+ dwc_reg_modify((GET_CORE_IF(pcd)->core_global_regs), DWC_GINTMSK,
+ intr_mask, 0);
+
+ gintsts = 0;
+ gintsts |= DWC_INTSTS_I2C_INTR;
+ dwc_reg_write((GET_CORE_IF(pcd)->core_global_regs), DWC_GINTSTS,
+ gintsts);
+
+ return 1;
+}
+
+/**
+ * This interrupt indicates that ...
+ */
+static int dwc_otg_pcd_handle_early_suspend_intr(struct dwc_pcd *pcd)
+{
+ u32 intr_mask = 0;
+ u32 gintsts;
+
+ pr_info("Early Suspend Detected\n");
+
+ /* Turn off and clean the interrupt */
+ intr_mask |= DWC_INTMSK_EARLY_SUSP;
+ dwc_reg_modify((GET_CORE_IF(pcd)->core_global_regs), DWC_GINTMSK,
+ intr_mask, 0);
+
+ gintsts = 0;
+ gintsts |= DWC_INTSTS_EARLY_SUSP;
+ dwc_reg_write((GET_CORE_IF(pcd)->core_global_regs), DWC_GINTSTS,
+ gintsts);
+
+ return 1;
+}
+
+/**
+ * This function configures EPO to receive SETUP packets.
+ *
+ * Program the following fields in the endpoint specific registers for Control
+ * OUT EP 0, in order to receive a setup packet:
+ *
+ * - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back setup packets)
+ *
+ * - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back to back setup
+ * packets)
+ *
+ * In DMA mode, DOEPDMA0 Register with a memory address to store any setup
+ * packets received
+ */
+static void ep0_out_start(struct core_if *core_if, struct dwc_pcd *pcd)
+{
+ struct device_if *dev_if = core_if->dev_if;
+ u32 doeptsize0 = 0;
+
+ doeptsize0 = DWC_DEPTSIZ0_SUPCNT_RW(doeptsize0, 3);
+ doeptsize0 = DWC_DEPTSIZ0_PKT_CNT_RW(doeptsize0, 1);
+ doeptsize0 = DWC_DEPTSIZ0_XFER_SIZ_RW(doeptsize0, 8 * 3);
+ dwc_reg_write(dev_if->out_ep_regs[0], DWC_DOEPTSIZ, doeptsize0);
+
+ if (core_if->dma_enable) {
+ u32 doepctl = 0;
+
+ dwc_reg_write(dev_if->out_ep_regs[0], DWC_DOEPDMA,
+ pcd->setup_pkt_dma_handle);
+ doepctl = DWC_DEPCTL_EPENA_RW(doepctl, 1);
+ doepctl = DWC_DEPCTL_ACT_EP_RW(doepctl, 1);
+ dwc_reg_write(out_ep_ctl_reg(pcd, 0), 0, doepctl);
+ }
+}
+
+/**
+ * This interrupt occurs when a USB Reset is detected. When the USB Reset
+ * Interrupt occurs the device state is set to DEFAULT and the EP0 state is set
+ * to IDLE.
+ *
+ * Set the NAK bit for all OUT endpoints (DOEPCTLn.SNAK = 1)
+ *
+ * Unmask the following interrupt bits:
+ * - DAINTMSK.INEP0 = 1 (Control 0 IN endpoint)
+ * - DAINTMSK.OUTEP0 = 1 (Control 0 OUT endpoint)
+ * - DOEPMSK.SETUP = 1
+ * - DOEPMSK.XferCompl = 1
+ * - DIEPMSK.XferCompl = 1
+ * - DIEPMSK.TimeOut = 1
+ *
+ * Program the following fields in the endpoint specific registers for Control
+ * OUT EP 0, in order to receive a setup packet
+ * - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back setup packets)
+ * - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back to back setup
+ * packets)
+ *
+ * - In DMA mode, DOEPDMA0 Register with a memory address to store any setup
+ * packets received
+ *
+ * At this point, all the required initialization, except for enabling
+ * the control 0 OUT endpoint is done, for receiving SETUP packets.
+ *
+ * Note that the bits in the Device IN endpoint mask register (diepmsk) are laid
+ * out exactly the same as the Device IN endpoint interrupt register (diepint.)
+ * Likewise for Device OUT endpoint mask / interrupt registers (doepmsk /
+ * doepint.)
+ */
+static int dwc_otg_pcd_handle_usb_reset_intr(struct dwc_pcd *pcd)
+{
+ struct core_if *core_if = GET_CORE_IF(pcd);
+ struct device_if *dev_if = core_if->dev_if;
+ u32 doepctl = 0;
+ u32 daintmsk = 0;
+ u32 doepmsk = 0;
+ u32 diepmsk = 0;
+ u32 dcfg = 0;
+ u32 resetctl = 0;
+ u32 dctl = 0;
+ u32 i;
+ u32 gintsts = 0;
+
+ pr_info("USB RESET\n");
+
+ /* reset the HNP settings */
+ dwc_otg_pcd_update_otg(pcd, 1);
+
+ /* Clear the Remote Wakeup Signalling */
+ dctl = DEC_DCTL_REMOTE_WAKEUP_SIG(dctl, 1);
+ dwc_reg_modify(dev_ctl_reg(pcd), 0, dctl, 0);
+
+ /* Set NAK for all OUT EPs */
+ doepctl = DWC_DEPCTL_SET_NAK_RW(doepctl, 1);
+ for (i = 0; i <= dev_if->num_out_eps; i++)
+ dwc_reg_write(out_ep_ctl_reg(pcd, i), 0, doepctl);
+
+ /* Flush the NP Tx FIFO */
+ dwc_otg_flush_tx_fifo(core_if, 0);
+
+ /* Flush the Learning Queue */
+ resetctl |= DWC_RSTCTL_TKN_QUE_FLUSH;
+ dwc_reg_write(core_if->core_global_regs, DWC_GRSTCTL, resetctl);
+
+ daintmsk |= DWC_DAINT_INEP00;
+ daintmsk |= DWC_DAINT_OUTEP00;
+ dwc_reg_write(dev_if->dev_global_regs, DWC_DAINTMSK, daintmsk);
+
+ doepmsk = DWC_DOEPMSK_SETUP_DONE_RW(doepmsk, 1);
+ doepmsk = DWC_DOEPMSK_AHB_ERROR_RW(doepmsk, 1);
+ doepmsk = DWC_DOEPMSK_EP_DISA_RW(doepmsk, 1);
+ doepmsk = DWC_DOEPMSK_TX_COMPL_RW(doepmsk, 1);
+ dwc_reg_write(dev_if->dev_global_regs, DWC_DOEPMSK, doepmsk);
+
+ diepmsk = DWC_DIEPMSK_TX_CMPL_RW(diepmsk, 1);
+ diepmsk = DWC_DIEPMSK_TOUT_COND_RW(diepmsk, 1);
+ diepmsk = DWC_DIEPMSK_EP_DISA_RW(diepmsk, 1);
+ diepmsk = DWC_DIEPMSK_AHB_ERROR_RW(diepmsk, 1);
+ diepmsk = DWC_DIEPMSK_IN_TKN_TX_EMPTY_RW(diepmsk, 1);
+ dwc_reg_write(dev_if->dev_global_regs, DWC_DIEPMSK, diepmsk);
+
+ /* Reset Device Address */
+ dcfg = dwc_reg_read(dev_if->dev_global_regs, DWC_DCFG);
+ dcfg = DWC_DCFG_DEV_ADDR_WR(dcfg, 0);
+ dwc_reg_write(dev_if->dev_global_regs, DWC_DCFG, dcfg);
+
+ /* setup EP0 to receive SETUP packets */
+ ep0_out_start(core_if, pcd);
+
+ /* Clear interrupt */
+ gintsts = 0;
+ gintsts |= DWC_INTSTS_USB_RST;
+ dwc_reg_write((core_if->core_global_regs), DWC_GINTSTS, gintsts);
+
+ return 1;
+}
+
+/**
+ * Get the device speed from the device status register and convert it
+ * to USB speed constant.
+ */
+static int get_device_speed(struct dwc_pcd *pcd)
+{
+ u32 dsts = 0;
+ enum usb_device_speed speed = USB_SPEED_UNKNOWN;
+
+ dsts = dwc_reg_read(dev_sts_reg(pcd), 0);
+
+ switch (DWC_DSTS_ENUM_SPEED_RD(dsts)) {
+ case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ:
+ speed = USB_SPEED_HIGH;
+ break;
+ case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ:
+ case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ:
+ speed = USB_SPEED_FULL;
+ break;
+ case DWC_DSTS_ENUMSPD_LS_PHY_6MHZ:
+ speed = USB_SPEED_LOW;
+ break;
+ }
+ return speed;
+}
+
+/**
+ * This function enables EP0 OUT to receive SETUP packets and configures EP0
+ * IN for transmitting packets. It is normally called when the "Enumeration
+ * Done" interrupt occurs.
+ */
+static void dwc_otg_ep0_activate(struct core_if *core_if, struct dwc_ep *ep)
+{
+ struct device_if *dev_if = core_if->dev_if;
+ u32 dsts;
+ u32 diepctl = 0;
+ u32 doepctl = 0;
+ u32 dctl = 0;
+
+ /* Read the Device Status and Endpoint 0 Control registers */
+ dsts = dwc_reg_read(dev_if->dev_global_regs, DWC_DSTS);
+ diepctl = dwc_reg_read(dev_if->in_ep_regs[0], DWC_DIEPCTL);
+ doepctl = dwc_reg_read(dev_if->out_ep_regs[0], DWC_DOEPCTL);
+
+ /* Set the MPS of the IN EP based on the enumeration speed */
+ switch (DWC_DSTS_ENUM_SPEED_RD(dsts)) {
+ case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ:
+ case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ:
+ case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ:
+ diepctl = DWC_DEPCTL_MPS_RW(diepctl, DWC_DEP0CTL_MPS_64);
+ break;
+ case DWC_DSTS_ENUMSPD_LS_PHY_6MHZ:
+ diepctl = DWC_DEPCTL_MPS_RW(diepctl, DWC_DEP0CTL_MPS_8);
+ break;
+ }
+ dwc_reg_write(dev_if->in_ep_regs[0], DWC_DIEPCTL, diepctl);
+
+ /* Enable OUT EP for receive */
+ doepctl = DWC_DEPCTL_EPENA_RW(doepctl, 1);
+ dwc_reg_write(dev_if->out_ep_regs[0], DWC_DOEPCTL, doepctl);
+
+ dctl = DWC_DCTL_CLR_CLBL_NP_IN_NAK(dctl, 1);
+ dwc_reg_modify(dev_if->dev_global_regs, DWC_DCTL, dctl, dctl);
+}
+
+/**
+ * Read the device status register and set the device speed in the
+ * data structure.
+ * Set up EP0 to receive SETUP packets by calling dwc_ep0_activate.
+ */
+static int dwc_otg_pcd_handle_enum_done_intr(struct dwc_pcd *pcd)
+{
+ struct pcd_ep *ep0 = &pcd->ep0;
+ u32 gintsts;
+ u32 gusbcfg;
+ struct core_if *core_if = GET_CORE_IF(pcd);
+ ulong global_regs = core_if->core_global_regs;
+ u32 gsnpsid = global_regs + DWC_GSNPSID;
+ u8 utmi16b, utmi8b;
+
+ if (gsnpsid >= (u32) 0x4f54260a) {
+ utmi16b = 5;
+ utmi8b = 9;
+ } else {
+ utmi16b = 4;
+ utmi8b = 8;
+ }
+ dwc_otg_ep0_activate(GET_CORE_IF(pcd), &ep0->dwc_ep);
+
+ pcd->ep0state = EP0_IDLE;
+ ep0->stopped = 0;
+ pcd->gadget.speed = get_device_speed(pcd);
+
+ gusbcfg = dwc_reg_read(global_regs, DWC_GUSBCFG);
+
+ /* Set USB turnaround time based on device speed and PHY interface. */
+ if (pcd->gadget.speed == USB_SPEED_HIGH) {
+ switch (DWC_HWCFG2_HS_PHY_TYPE_RD(core_if->hwcfg2)) {
+ case DWC_HWCFG2_HS_PHY_TYPE_ULPI:
+ gusbcfg =
+ (gusbcfg & (~((u32) DWC_USBCFG_TRN_TIME(0xf)))) |
+ DWC_USBCFG_TRN_TIME(9);
+ break;
+ case DWC_HWCFG2_HS_PHY_TYPE_UTMI:
+ if (DWC_HWCFG4_UTMI_PHY_DATA_WIDTH_RD(core_if->hwcfg4)
+ == 0)
+ gusbcfg =
+ (gusbcfg &
+ (~((u32) DWC_USBCFG_TRN_TIME(0xf)))) |
+ DWC_USBCFG_TRN_TIME(utmi8b);
+ else if (DWC_HWCFG4_UTMI_PHY_DATA_WIDTH_RD
+ (core_if->hwcfg4) == 1)
+ gusbcfg =
+ (gusbcfg &
+ (~((u32) DWC_USBCFG_TRN_TIME(0xf)))) |
+ DWC_USBCFG_TRN_TIME(utmi16b);
+ else if (core_if->core_params->phy_utmi_width == 8)
+ gusbcfg =
+ (gusbcfg &
+ (~((u32) DWC_USBCFG_TRN_TIME(0xf)))) |
+ DWC_USBCFG_TRN_TIME(utmi8b);
+ else
+ gusbcfg =
+ (gusbcfg &
+ (~((u32) DWC_USBCFG_TRN_TIME(0xf)))) |
+ DWC_USBCFG_TRN_TIME(utmi16b);
+ break;
+ case DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI:
+ if (gusbcfg & DWC_USBCFG_ULPI_UTMI_SEL) {
+ gusbcfg =
+ (gusbcfg &
+ (~((u32) DWC_USBCFG_TRN_TIME(0xf)))) |
+ DWC_USBCFG_TRN_TIME(9);
+ } else {
+ if (core_if->core_params->phy_utmi_width == 16)
+ gusbcfg =
+ (gusbcfg &
+ (~
+ ((u32) DWC_USBCFG_TRN_TIME(0xf))))
+ | DWC_USBCFG_TRN_TIME(utmi16b);
+ else
+ gusbcfg =
+ (gusbcfg &
+ (~
+ ((u32) DWC_USBCFG_TRN_TIME(0xf))))
+ | DWC_USBCFG_TRN_TIME(utmi8b);
+ }
+ break;
+ }
+ } else {
+ /* Full or low speed */
+ gusbcfg = (gusbcfg & (~((u32) DWC_USBCFG_TRN_TIME(0xf)))) |
+ DWC_USBCFG_TRN_TIME(9);
+ }
+ dwc_reg_write(global_regs, DWC_GUSBCFG, gusbcfg);
+
+ /* Clear interrupt */
+ gintsts = 0;
+ gintsts |= DWC_INTSTS_ENUM_DONE;
+ dwc_reg_write((GET_CORE_IF(pcd)->core_global_regs), DWC_GINTSTS,
+ gintsts);
+
+ return 1;
+}
+
+/**
+ * This interrupt indicates that the ISO OUT Packet was dropped due to
+ * Rx FIFO full or Rx Status Queue Full. If this interrupt occurs
+ * read all the data from the Rx FIFO.
+ */
+static int dwc_otg_pcd_handle_isoc_out_packet_dropped_intr(struct dwc_pcd *pcd)
+{
+ u32 intr_mask = 0;
+ u32 gintsts;
+
+ pr_info("Interrupt Handler not implemented for ISOC Out " "Dropped\n");
+
+ /* Turn off and clear the interrupt */
+ intr_mask |= DWC_INTMSK_ISYNC_OUTPKT_DRP;
+ dwc_reg_modify((GET_CORE_IF(pcd)->core_global_regs), DWC_GINTMSK,
+ intr_mask, 0);
+
+ gintsts = 0;
+ gintsts |= DWC_INTSTS_ISYNC_OUTPKT_DRP;
+ dwc_reg_write((GET_CORE_IF(pcd)->core_global_regs), DWC_GINTSTS,
+ gintsts);
+
+ return 1;
+}
+
+/**
+ * This interrupt indicates the end of the portion of the micro-frame
+ * for periodic transactions. If there is a periodic transaction for
+ * the next frame, load the packets into the EP periodic Tx FIFO.
+ */
+static int dwc_otg_pcd_handle_end_periodic_frame_intr(struct dwc_pcd *pcd)
+{
+ u32 intr_mask = 0;
+ u32 gintsts;
+
+ pr_info("Interrupt handler not implemented for End of "
+ "Periodic Portion of Micro-Frame Interrupt");
+
+ /* Turn off and clear the interrupt */
+ intr_mask |= DWC_INTMSK_END_OF_PFRM;
+ dwc_reg_modify((GET_CORE_IF(pcd)->core_global_regs), DWC_GINTMSK,
+ intr_mask, 0);
+
+ gintsts = 0;
+ gintsts |= DWC_INTSTS_END_OF_PFRM;
+ dwc_reg_write((GET_CORE_IF(pcd)->core_global_regs), DWC_GINTSTS,
+ gintsts);
+
+ return 1;
+}
+
+/**
+ * This interrupt indicates that EP of the packet on the top of the
+ * non-periodic Tx FIFO does not match EP of the IN Token received.
+ *
+ * The "Device IN Token Queue" Registers are read to determine the
+ * order the IN Tokens have been received. The non-periodic Tx FIFO is flushed,
+ * so it can be reloaded in the order seen in the IN Token Queue.
+ */
+static int dwc_otg_pcd_handle_ep_mismatch_intr(struct core_if *core_if)
+{
+ u32 intr_mask = 0;
+ u32 gintsts;
+
+ pr_info("Interrupt handler not implemented for End Point "
+ "Mismatch\n");
+
+ /* Turn off and clear the interrupt */
+ intr_mask |= DWC_INTMSK_ENDP_MIS_MTCH;
+ dwc_reg_modify((core_if->core_global_regs), DWC_GINTMSK,
+ intr_mask, 0);
+
+ gintsts = 0;
+ gintsts |= DWC_INTSTS_ENDP_MIS_MTCH;
+ dwc_reg_write((core_if->core_global_regs), DWC_GINTSTS, gintsts);
+ return 1;
+}
+
+/**
+ * This funcion stalls EP0.
+ */
+static void ep0_do_stall(struct dwc_pcd *pcd, const int val)
+{
+ struct pcd_ep *ep0 = &pcd->ep0;
+ struct usb_ctrlrequest *ctrl = &pcd->setup_pkt->req;
+
+ pr_warning("req %02x.%02x protocol STALL; err %d\n",
+ ctrl->bRequestType, ctrl->bRequest, val);
+
+ ep0->dwc_ep.is_in = 1;
+ dwc_otg_ep_set_stall(pcd->otg_dev->core_if, &ep0->dwc_ep);
+
+ pcd->ep0.stopped = 1;
+ pcd->ep0state = EP0_IDLE;
+ ep0_out_start(GET_CORE_IF(pcd), pcd);
+}
+
+/**
+ * This functions delegates the setup command to the gadget driver.
+ */
+static void do_gadget_setup(struct dwc_pcd *pcd, struct usb_ctrlrequest *ctrl)
+{
+ if (pcd->driver && pcd->driver->setup) {
+ int ret;
+
+ spin_unlock(&pcd->lock);
+ ret = pcd->driver->setup(&pcd->gadget, ctrl);
+ spin_lock(&pcd->lock);
+
+ if (ret < 0)
+ ep0_do_stall(pcd, ret);
+
+ /** This is a g_file_storage gadget driver specific
+ * workaround: a DELAYED_STATUS result from the fsg_setup
+ * routine will result in the gadget queueing a EP0 IN status
+ * phase for a two-stage control transfer.
+ *
+ * Exactly the same as a SET_CONFIGURATION/SET_INTERFACE except
+ * that this is a class specific request. Need a generic way to
+ * know when the gadget driver will queue the status phase.
+ *
+ * Can we assume when we call the gadget driver setup() function
+ * that it will always queue and require the following flag?
+ * Need to look into this.
+ */
+ if (ret == 256 + 999)
+ pcd->request_config = 1;
+ }
+}
+
+/**
+ * This function starts the Zero-Length Packet for the IN status phase
+ * of a 2 stage control transfer.
+ */
+static void do_setup_in_status_phase(struct dwc_pcd *pcd)
+{
+ struct pcd_ep *ep0 = &pcd->ep0;
+
+ if (pcd->ep0state == EP0_STALL)
+ return;
+
+ pcd->ep0state = EP0_STATUS;
+
+ ep0->dwc_ep.xfer_len = 0;
+ ep0->dwc_ep.xfer_count = 0;
+ ep0->dwc_ep.is_in = 1;
+ ep0->dwc_ep.dma_addr = pcd->setup_pkt_dma_handle;
+ dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
+
+ /* Prepare for more SETUP Packets */
+ ep0_out_start(GET_CORE_IF(pcd), pcd);
+}
+
+/**
+ * This function starts the Zero-Length Packet for the OUT status phase
+ * of a 2 stage control transfer.
+ */
+static void do_setup_out_status_phase(struct dwc_pcd *pcd)
+{
+ struct pcd_ep *ep0 = &pcd->ep0;
+
+ if (pcd->ep0state == EP0_STALL)
+ return;
+ pcd->ep0state = EP0_STATUS;
+
+ ep0->dwc_ep.xfer_len = 0;
+ ep0->dwc_ep.xfer_count = 0;
+ ep0->dwc_ep.is_in = 0;
+ ep0->dwc_ep.dma_addr = pcd->setup_pkt_dma_handle;
+ dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
+
+ /* Prepare for more SETUP Packets */
+ ep0_out_start(GET_CORE_IF(pcd), pcd);
+}
+
+/**
+ * Clear the EP halt (STALL) and if pending requests start the
+ * transfer.
+ */
+static void pcd_clear_halt(struct dwc_pcd *pcd, struct pcd_ep *ep)
+{
+ struct core_if *core_if = GET_CORE_IF(pcd);
+
+ if (!ep->dwc_ep.stall_clear_flag)
+ dwc_otg_ep_clear_stall(core_if, &ep->dwc_ep);
+
+ /* Reactive the EP */
+ dwc_otg_ep_activate(core_if, &ep->dwc_ep);
+
+ if (ep->stopped) {
+ ep->stopped = 0;
+ /* If there is a request in the EP queue start it */
+
+ /*
+ * dwc_start_next_request(), outside of interpt contxt at some
+ * time after the current time, after a clear-halt setup packet.
+ * Still need to implement ep mismatch in the future if a gadget
+ * ever uses more than one endpoint at once
+ */
+ if (core_if->dma_enable) {
+ ep->queue_sof = 1;
+ tasklet_schedule(pcd->start_xfer_tasklet);
+ } else {
+ /*
+ * Added-sr: 2007-07-26
+ *
+ * To re-enable this endpoint it's important to
+ * set this next_ep number. Otherwise the endpoint
+ * will not get active again after stalling.
+ */
+ if (dwc_has_feature(core_if, DWC_LIMITED_XFER))
+ dwc_start_next_request(ep);
+ }
+ }
+
+ /* Start Control Status Phase */
+ do_setup_in_status_phase(pcd);
+}
+
+/**
+ * This function is called when the SET_FEATURE TEST_MODE Setup packet is sent
+ * from the host. The Device Control register is written with the Test Mode
+ * bits set to the specified Test Mode. This is done as a tasklet so that the
+ * "Status" phase of the control transfer completes before transmitting the TEST
+ * packets.
+ *
+ */
+static void do_test_mode(unsigned long data)
+{
+ u32 dctl = 0;
+ struct dwc_pcd *pcd = (struct dwc_pcd *)data;
+ int test_mode = pcd->test_mode;
+
+ dctl = dwc_reg_read(dev_ctl_reg(pcd), 0);
+ switch (test_mode) {
+ case 1: /* TEST_J */
+ dctl = DWC_DCTL_TST_CTL(dctl, 1);
+ break;
+ case 2: /* TEST_K */
+ dctl = DWC_DCTL_TST_CTL(dctl, 2);
+ break;
+ case 3: /* TEST_SE0_NAK */
+ dctl = DWC_DCTL_TST_CTL(dctl, 3);
+ break;
+ case 4: /* TEST_PACKET */
+ dctl = DWC_DCTL_TST_CTL(dctl, 4);
+ break;
+ case 5: /* TEST_FORCE_ENABLE */
+ dctl = DWC_DCTL_TST_CTL(dctl, 5);
+ break;
+ }
+ dwc_reg_write(dev_ctl_reg(pcd), 0, dctl);
+}
+
+/**
+ * This function process the SET_FEATURE Setup Commands.
+ */
+static void do_set_feature(struct dwc_pcd *pcd)
+{
+ struct core_if *core_if = GET_CORE_IF(pcd);
+ ulong regs = core_if->core_global_regs;
+ struct usb_ctrlrequest ctrl = pcd->setup_pkt->req;
+ int otg_cap = core_if->core_params->otg_cap;
+ u32 gotgctl = 0;
+
+ switch (ctrl.bRequestType & USB_RECIP_MASK) {
+ case USB_RECIP_DEVICE:
+ switch (__le16_to_cpu(ctrl.wValue)) {
+ case USB_DEVICE_REMOTE_WAKEUP:
+ pcd->remote_wakeup_enable = 1;
+ break;
+ case USB_DEVICE_TEST_MODE:
+ /*
+ * Setup the Test Mode tasklet to do the Test
+ * Packet generation after the SETUP Status
+ * phase has completed.
+ */
+
+ pcd->test_mode_tasklet.next = NULL;
+ pcd->test_mode_tasklet.state = 0;
+ atomic_set(&pcd->test_mode_tasklet.count, 0);
+
+ pcd->test_mode_tasklet.func = do_test_mode;
+ pcd->test_mode_tasklet.data = (unsigned long)pcd;
+ pcd->test_mode = __le16_to_cpu(ctrl.wIndex) >> 8;
+ tasklet_schedule(&pcd->test_mode_tasklet);
+
+ break;
+ case USB_DEVICE_B_HNP_ENABLE:
+ /* dev may initiate HNP */
+ if (otg_cap == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
+ pcd->b_hnp_enable = 1;
+ dwc_otg_pcd_update_otg(pcd, 0);
+ /*
+ * gotgctl.devhnpen cleared by a
+ * USB Reset?
+ */
+ gotgctl |= DWC_GCTL_DEV_HNP_ENA;
+ gotgctl |= DWC_GCTL_HNP_REQ;
+ dwc_reg_write(regs, DWC_GOTGCTL, gotgctl);
+ } else {
+ ep0_do_stall(pcd, -EOPNOTSUPP);
+ }
+ break;
+ case USB_DEVICE_A_HNP_SUPPORT:
+ /* RH port supports HNP */
+ if (otg_cap == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
+ pcd->a_hnp_support = 1;
+ dwc_otg_pcd_update_otg(pcd, 0);
+ } else {
+ ep0_do_stall(pcd, -EOPNOTSUPP);
+ }
+ break;
+ case USB_DEVICE_A_ALT_HNP_SUPPORT:
+ /* other RH port does */
+ if (otg_cap == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
+ pcd->a_alt_hnp_support = 1;
+ dwc_otg_pcd_update_otg(pcd, 0);
+ } else {
+ ep0_do_stall(pcd, -EOPNOTSUPP);
+ }
+ break;
+ }
+ do_setup_in_status_phase(pcd);
+ break;
+ case USB_RECIP_INTERFACE:
+ do_gadget_setup(pcd, &ctrl);
+ break;
+ case USB_RECIP_ENDPOINT:
+ if (__le16_to_cpu(ctrl.wValue) == USB_ENDPOINT_HALT) {
+ struct pcd_ep *ep;
+
+ ep = get_ep_by_addr(pcd, __le16_to_cpu(ctrl.wIndex));
+
+ if (ep == NULL) {
+ ep0_do_stall(pcd, -EOPNOTSUPP);
+ return;
+ }
+
+ ep->stopped = 1;
+ dwc_otg_ep_set_stall(core_if, &ep->dwc_ep);
+ }
+ do_setup_in_status_phase(pcd);
+ break;
+ }
+}
+
+/**
+ * This function process the CLEAR_FEATURE Setup Commands.
+ */
+static void do_clear_feature(struct dwc_pcd *pcd)
+{
+ struct usb_ctrlrequest ctrl = pcd->setup_pkt->req;
+ struct pcd_ep *ep;
+
+ switch (ctrl.bRequestType & USB_RECIP_MASK) {
+ case USB_RECIP_DEVICE:
+ switch (__le16_to_cpu(ctrl.wValue)) {
+ case USB_DEVICE_REMOTE_WAKEUP:
+ pcd->remote_wakeup_enable = 0;
+ break;
+ case USB_DEVICE_TEST_MODE:
+ /* Add CLEAR_FEATURE for TEST modes. */
+ break;
+ }
+ do_setup_in_status_phase(pcd);
+ break;
+ case USB_RECIP_ENDPOINT:
+ ep = get_ep_by_addr(pcd, __le16_to_cpu(ctrl.wIndex));
+ if (ep == NULL) {
+ ep0_do_stall(pcd, -EOPNOTSUPP);
+ return;
+ }
+
+ pcd_clear_halt(pcd, ep);
+ break;
+ }
+}
+
+/**
+ * This function processes SETUP commands. In Linux, the USB Command processing
+ * is done in two places - the first being the PCD and the second in the Gadget
+ * Driver (for example, the File-Backed Storage Gadget Driver).
+ *
+ * GET_STATUS: Command is processed as defined in chapter 9 of the USB 2.0
+ * Specification chapter 9
+ *
+ * CLEAR_FEATURE: The Device and Endpoint requests are the ENDPOINT_HALT feature
+ * is procesed, all others the interface requests are ignored.
+ *
+ * SET_FEATURE: The Device and Endpoint requests are processed by the PCD.
+ * Interface requests are passed to the Gadget Driver.
+ *
+ * SET_ADDRESS: PCD, Program the DCFG reg, with device address received
+ *
+ * GET_DESCRIPTOR: Gadget Driver, Return the requested descriptor
+ *
+ * SET_DESCRIPTOR: Gadget Driver, Optional - not implemented by any of the
+ * existing Gadget Drivers.
+ *
+ * SET_CONFIGURATION: Gadget Driver, Disable all EPs and enable EPs for new
+ * configuration.
+ *
+ * GET_CONFIGURATION: Gadget Driver, Return the current configuration
+ *
+ * SET_INTERFACE: Gadget Driver, Disable all EPs and enable EPs for new
+ * configuration.
+ *
+ * GET_INTERFACE: Gadget Driver, Return the current interface.
+ *
+ * SYNC_FRAME: Display debug message.
+ *
+ * When the SETUP Phase Done interrupt occurs, the PCD SETUP commands are
+ * processed by pcd_setup. Calling the Function Driver's setup function from
+ * pcd_setup processes the gadget SETUP commands.
+ */
+static void pcd_setup(struct dwc_pcd *pcd)
+{
+ struct core_if *core_if = GET_CORE_IF(pcd);
+ struct device_if *dev_if = core_if->dev_if;
+ struct usb_ctrlrequest ctrl = pcd->setup_pkt->req;
+ struct pcd_ep *ep;
+ struct pcd_ep *ep0 = &pcd->ep0;
+ u16 *status = pcd->status_buf;
+ u32 doeptsize0 = 0;
+
+ doeptsize0 = dwc_reg_read(dev_if->out_ep_regs[0], DWC_DOEPTSIZ);
+
+ /* handle > 1 setup packet , assert error for now */
+ if (core_if->dma_enable && (DWC_DEPTSIZ0_SUPCNT_RD(doeptsize0) < 2))
+ pr_err("\n\n CANNOT handle > 1 setup packet in "
+ "DMA mode\n\n");
+
+ /* Clean up the request queue */
+ request_nuke(ep0);
+ ep0->stopped = 0;
+
+ if (ctrl.bRequestType & USB_DIR_IN) {
+ ep0->dwc_ep.is_in = 1;
+ pcd->ep0state = EP0_IN_DATA_PHASE;
+ } else {
+ ep0->dwc_ep.is_in = 0;
+ pcd->ep0state = EP0_OUT_DATA_PHASE;
+ }
+
+ if ((ctrl.bRequestType & USB_TYPE_MASK) != USB_TYPE_STANDARD) {
+ /*
+ * Handle non-standard (class/vendor) requests in the gadget
+ * driver
+ */
+ do_gadget_setup(pcd, &ctrl);
+ return;
+ }
+
+ switch (ctrl.bRequest) {
+ case USB_REQ_GET_STATUS:
+ switch (ctrl.bRequestType & USB_RECIP_MASK) {
+ case USB_RECIP_DEVICE:
+ *status = 0x1; /* Self powered */
+ *status |= pcd->remote_wakeup_enable << 1;
+ break;
+ case USB_RECIP_INTERFACE:
+ *status = 0;
+ break;
+ case USB_RECIP_ENDPOINT:
+ ep = get_ep_by_addr(pcd, __le16_to_cpu(ctrl.wIndex));
+ if (ep == NULL || __le16_to_cpu(ctrl.wLength) > 2) {
+ ep0_do_stall(pcd, -EOPNOTSUPP);
+ return;
+ }
+ *status = ep->stopped;
+ break;
+ }
+
+ *status = __cpu_to_le16(*status);
+
+ pcd->ep0_pending = 1;
+ ep0->dwc_ep.start_xfer_buff = (u8 *) status;
+ ep0->dwc_ep.xfer_buff = (u8 *) status;
+ ep0->dwc_ep.dma_addr = pcd->status_buf_dma_handle;
+ ep0->dwc_ep.xfer_len = 2;
+ ep0->dwc_ep.xfer_count = 0;
+ ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len;
+ dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
+ break;
+ case USB_REQ_CLEAR_FEATURE:
+ do_clear_feature(pcd);
+ break;
+ case USB_REQ_SET_FEATURE:
+ do_set_feature(pcd);
+ break;
+ case USB_REQ_SET_ADDRESS:
+ if (ctrl.bRequestType == USB_RECIP_DEVICE) {
+ u32 dcfg = 0;
+
+ dcfg = DWC_DCFG_DEV_ADDR_WR(dcfg,
+ __le16_to_cpu(ctrl.wValue));
+ dwc_reg_modify(dev_if->dev_global_regs, DWC_DCFG,
+ 0, dcfg);
+ do_setup_in_status_phase(pcd);
+ return;
+ }
+ break;
+ case USB_REQ_SET_INTERFACE:
+ case USB_REQ_SET_CONFIGURATION:
+ pcd->request_config = 1; /* Configuration changed */
+ do_gadget_setup(pcd, &ctrl);
+ break;
+ case USB_REQ_SYNCH_FRAME:
+ do_gadget_setup(pcd, &ctrl);
+ break;
+ default:
+ /* Call the Gadget Driver's setup functions */
+ do_gadget_setup(pcd, &ctrl);
+ break;
+ }
+}
+
+/**
+ * This function completes the ep0 control transfer.
+ */
+static int ep0_complete_request(struct pcd_ep *ep)
+{
+ struct core_if *core_if = GET_CORE_IF(ep->pcd);
+ struct device_if *dev_if = core_if->dev_if;
+ ulong in_regs = dev_if->in_ep_regs[ep->dwc_ep.num];
+ u32 deptsiz = 0;
+ struct pcd_request *req;
+ int is_last = 0;
+ struct dwc_pcd *pcd = ep->pcd;
+
+ if (pcd->ep0_pending && list_empty(&ep->queue)) {
+ if (ep->dwc_ep.is_in)
+ do_setup_out_status_phase(pcd);
+ else
+ do_setup_in_status_phase(pcd);
+
+ pcd->ep0_pending = 0;
+ pcd->ep0state = EP0_STATUS;
+ return 1;
+ }
+
+ if (list_empty(&ep->queue))
+ return 0;
+
+ req = list_entry(ep->queue.next, struct pcd_request, queue);
+
+ if (pcd->ep0state == EP0_STATUS) {
+ is_last = 1;
+ } else if (ep->dwc_ep.is_in) {
+ deptsiz = dwc_reg_read(in_regs, DWC_DIEPTSIZ);
+
+ if (DWC_DEPTSIZ0_XFER_SIZ_RD(deptsiz) == 0) {
+ req->req.actual = ep->dwc_ep.xfer_count;
+ do_setup_out_status_phase(pcd);
+ }
+ } else {
+ /* This is ep0-OUT */
+ req->req.actual = ep->dwc_ep.xfer_count;
+ do_setup_in_status_phase(pcd);
+ }
+
+ /* Complete the request */
+ if (is_last) {
+ request_done(ep, req, 0);
+ ep->dwc_ep.start_xfer_buff = NULL;
+ ep->dwc_ep.xfer_buff = NULL;
+ ep->dwc_ep.xfer_len = 0;
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * This function completes the request for the EP. If there are additional
+ * requests for the EP in the queue they will be started.
+ */
+static void complete_ep(struct pcd_ep *ep)
+{
+ struct core_if *core_if = GET_CORE_IF(ep->pcd);
+ struct device_if *dev_if = core_if->dev_if;
+ ulong in_ep_regs = dev_if->in_ep_regs[ep->dwc_ep.num];
+ u32 deptsiz = 0;
+ struct pcd_request *req = NULL;
+ int is_last = 0;
+
+ /* Get any pending requests */
+ if (!list_empty(&ep->queue))
+ req = list_entry(ep->queue.next, struct pcd_request, queue);
+
+ if (ep->dwc_ep.is_in) {
+ deptsiz = dwc_reg_read(in_ep_regs, DWC_DIEPTSIZ);
+
+ if (core_if->dma_enable && !DWC_DEPTSIZ_XFER_SIZ_RD(deptsiz))
+ ep->dwc_ep.xfer_count = ep->dwc_ep.xfer_len;
+
+ if (DWC_DEPTSIZ_XFER_SIZ_RD(deptsiz) == 0 &&
+ DWC_DEPTSIZ_PKT_CNT_RD(deptsiz) == 0 &&
+ ep->dwc_ep.xfer_count == ep->dwc_ep.xfer_len)
+ is_last = 1;
+ else
+ pr_warning("Incomplete transfer (%s-%s "
+ "[siz=%d pkt=%d])\n", ep->ep.name,
+ ep->dwc_ep.is_in ? "IN" : "OUT",
+ DWC_DEPTSIZ_XFER_SIZ_RD(deptsiz),
+ DWC_DEPTSIZ_PKT_CNT_RD(deptsiz));
+ } else {
+ ulong out_ep_regs = dev_if->out_ep_regs[ep->dwc_ep.num];
+
+ deptsiz = dwc_reg_read(out_ep_regs, DWC_DOEPTSIZ);
+ is_last = 1;
+ }
+
+ /* Complete the request */
+ if (is_last) {
+ /*
+ * Added-sr: 2007-07-26
+ *
+ * Since the 405EZ (Ultra) only support 2047 bytes as
+ * max transfer size, we have to split up bigger transfers
+ * into multiple transfers of 1024 bytes sized messages.
+ * I happens often, that transfers of 4096 bytes are
+ * required (zero-gadget, file_storage-gadget).
+ */
+ if ((dwc_has_feature(core_if, DWC_LIMITED_XFER)) &&
+ ep->dwc_ep.bytes_pending) {
+ ulong in_regs =
+ core_if->dev_if->in_ep_regs[ep->dwc_ep.num];
+ u32 intr_mask = 0;
+
+ ep->dwc_ep.xfer_len = ep->dwc_ep.bytes_pending;
+ if (ep->dwc_ep.xfer_len > MAX_XFER_LEN) {
+ ep->dwc_ep.bytes_pending = ep->dwc_ep.xfer_len -
+ MAX_XFER_LEN;
+ ep->dwc_ep.xfer_len = MAX_XFER_LEN;
+ } else {
+ ep->dwc_ep.bytes_pending = 0;
+ }
+
+ /*
+ * Restart the current transfer with the next "chunk"
+ * of data.
+ */
+ ep->dwc_ep.xfer_count = 0;
+
+ deptsiz = dwc_reg_read(in_regs, DWC_DIEPTSIZ);
+ deptsiz =
+ DWC_DEPTSIZ_XFER_SIZ_RW(deptsiz,
+ ep->dwc_ep.xfer_len);
+ deptsiz =
+ DWC_DEPTSIZ_PKT_CNT_RW(deptsiz,
+ ((ep->dwc_ep.xfer_len - 1 +
+ ep->dwc_ep.maxpacket) /
+ ep->dwc_ep.maxpacket));
+ dwc_reg_write(in_regs, DWC_DIEPTSIZ, deptsiz);
+
+ intr_mask |= DWC_INTSTS_NP_TXFIFO_EMPT;
+ dwc_reg_modify((core_if->core_global_regs),
+ DWC_GINTSTS, intr_mask, 0);
+ dwc_reg_modify((core_if->core_global_regs),
+ DWC_GINTMSK, intr_mask, intr_mask);
+
+ /*
+ * Just return here if message was not completely
+ * transferred.
+ */
+ return;
+ }
+ if (core_if->dma_enable)
+ req->req.actual = ep->dwc_ep.xfer_len -
+ DWC_DEPTSIZ_XFER_SIZ_RD(deptsiz);
+ else
+ req->req.actual = ep->dwc_ep.xfer_count;
+
+ request_done(ep, req, 0);
+ ep->dwc_ep.start_xfer_buff = NULL;
+ ep->dwc_ep.xfer_buff = NULL;
+ ep->dwc_ep.xfer_len = 0;
+
+ /* If there is a request in the queue start it. */
+ dwc_start_next_request(ep);
+ }
+}
+
+/**
+ * This function continues control IN transfers started by
+ * dwc_otg_ep0_start_transfer, when the transfer does not fit in a
+ * single packet. NOTE: The DIEPCTL0/DOEPCTL0 registers only have one
+ * bit for the packet count.
+ */
+static void dwc_otg_ep0_continue_transfer(struct core_if *c_if,
+ struct dwc_ep *ep)
+{
+ if (ep->is_in) {
+ u32 depctl = 0;
+ u32 deptsiz = 0;
+ struct device_if *d_if = c_if->dev_if;
+ ulong in_regs = d_if->in_ep_regs[0];
+ u32 tx_status = 0;
+ ulong glbl_regs = c_if->core_global_regs;
+
+ tx_status = dwc_reg_read(glbl_regs, DWC_GNPTXSTS);
+
+ depctl = dwc_reg_read(in_regs, DWC_DIEPCTL);
+ deptsiz = dwc_reg_read(in_regs, DWC_DIEPTSIZ);
+
+ /*
+ * Program the transfer size and packet count as follows:
+ * xfersize = N * maxpacket + short_packet
+ * pktcnt = N + (short_packet exist ? 1 : 0)
+ */
+ if (ep->total_len - ep->xfer_count > ep->maxpacket)
+ deptsiz = DWC_DEPTSIZ0_XFER_SIZ_RW(deptsiz,
+ ep->maxpacket);
+ else
+ deptsiz = DWC_DEPTSIZ0_XFER_SIZ_RW(deptsiz,
+ (ep->total_len -
+ ep->xfer_count));
+
+ deptsiz = DWC_DEPTSIZ0_PKT_CNT_RW(deptsiz, 1);
+ ep->xfer_len += DWC_DEPTSIZ0_XFER_SIZ_RD(deptsiz);
+ dwc_reg_write(in_regs, DWC_DIEPTSIZ, deptsiz);
+
+ /* Write the DMA register */
+ if (DWC_HWCFG2_ARCH_RD(c_if->hwcfg2) == DWC_INT_DMA_ARCH)
+ dwc_reg_write(in_regs, DWC_DIEPDMA, ep->dma_addr);
+
+ /* EP enable, IN data in FIFO */
+ depctl = DWC_DEPCTL_CLR_NAK_RW(depctl, 1);
+ depctl = DWC_DEPCTL_EPENA_RW(depctl, 1);
+ dwc_reg_write(in_regs, DWC_DIEPCTL, depctl);
+
+ /*
+ * Enable the Non-Periodic Tx FIFO empty interrupt, the
+ * data will be written into the fifo by the ISR.
+ */
+ if (!c_if->dma_enable) {
+ u32 intr_mask = 0;
+
+ /* First clear it from GINTSTS */
+ intr_mask |= DWC_INTMSK_NP_TXFIFO_EMPT;
+ dwc_reg_write(glbl_regs, DWC_GINTSTS, intr_mask);
+
+ /* To avoid spurious NPTxFEmp intr */
+ dwc_reg_modify(glbl_regs, DWC_GINTMSK, intr_mask,
+ intr_mask);
+ }
+ }
+}
+
+/**
+ * This function handles EP0 Control transfers.
+ *
+ * The state of the control tranfers are tracked in ep0state
+ */
+static void handle_ep0(struct dwc_pcd *pcd)
+{
+ struct core_if *core_if = GET_CORE_IF(pcd);
+ struct pcd_ep *ep0 = &pcd->ep0;
+
+ switch (pcd->ep0state) {
+ case EP0_DISCONNECT:
+ break;
+ case EP0_IDLE:
+ pcd->request_config = 0;
+ pcd_setup(pcd);
+ break;
+ case EP0_IN_DATA_PHASE:
+ if (core_if->dma_enable)
+ /*
+ * For EP0 we can only program 1 packet at a time so we
+ * need to do the calculations after each complete.
+ * Call write_packet to make the calculations, as in
+ * slave mode, and use those values to determine if we
+ * can complete.
+ */
+ dwc_otg_ep_write_packet(core_if, &ep0->dwc_ep, 1);
+ else
+ dwc_otg_ep_write_packet(core_if, &ep0->dwc_ep, 0);
+
+ if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len)
+ dwc_otg_ep0_continue_transfer(core_if, &ep0->dwc_ep);
+ else
+ ep0_complete_request(ep0);
+ break;
+ case EP0_OUT_DATA_PHASE:
+ ep0_complete_request(ep0);
+ break;
+ case EP0_STATUS:
+ ep0_complete_request(ep0);
+ pcd->ep0state = EP0_IDLE;
+ ep0->stopped = 1;
+ ep0->dwc_ep.is_in = 0; /* OUT for next SETUP */
+
+ /* Prepare for more SETUP Packets */
+ if (core_if->dma_enable) {
+ ep0_out_start(core_if, pcd);
+ } else {
+ int i;
+ u32 diepctl = 0;
+
+ diepctl = dwc_reg_read(in_ep_ctl_reg(pcd, 0), 0);
+ if (pcd->ep0.queue_sof) {
+ pcd->ep0.queue_sof = 0;
+ dwc_start_next_request(&pcd->ep0);
+ }
+
+ diepctl = dwc_reg_read(in_ep_ctl_reg(pcd, 0), 0);
+ if (pcd->ep0.queue_sof) {
+ pcd->ep0.queue_sof = 0;
+ dwc_start_next_request(&pcd->ep0);
+ }
+
+ for (i = 0; i < core_if->dev_if->num_in_eps; i++) {
+ diepctl = dwc_reg_read(in_ep_ctl_reg(pcd, i),
+ 0);
+
+ if (pcd->in_ep[i].queue_sof) {
+ pcd->in_ep[i].queue_sof = 0;
+ dwc_start_next_request(&pcd->in_ep[i]);
+ }
+ }
+ }
+ break;
+ case EP0_STALL:
+ pr_err("EP0 STALLed, should not get here handle_ep0()\n");
+ break;
+ }
+}
+
+/**
+ * Restart transfer
+ */
+static void restart_transfer(struct dwc_pcd *pcd, const u32 ep_num)
+{
+ struct core_if *core_if = GET_CORE_IF(pcd);
+ struct device_if *dev_if = core_if->dev_if;
+ u32 dieptsiz = 0;
+ struct pcd_ep *ep;
+
+ dieptsiz = dwc_reg_read(dev_if->in_ep_regs[ep_num], DWC_DIEPTSIZ);
+ ep = get_in_ep(pcd, ep_num);
+
+ /*
+ * If pktcnt is not 0, and xfersize is 0, and there is a buffer,
+ * resend the last packet.
+ */
+ if (DWC_DEPTSIZ_PKT_CNT_RD(dieptsiz) &&
+ !DWC_DEPTSIZ_XFER_SIZ_RD(dieptsiz) && ep->dwc_ep.start_xfer_buff) {
+ if (ep->dwc_ep.xfer_len <= ep->dwc_ep.maxpacket) {
+ ep->dwc_ep.xfer_count = 0;
+ ep->dwc_ep.xfer_buff = ep->dwc_ep.start_xfer_buff;
+ } else {
+ ep->dwc_ep.xfer_count -= ep->dwc_ep.maxpacket;
+
+ /* convert packet size to dwords. */
+ ep->dwc_ep.xfer_buff -= ep->dwc_ep.maxpacket;
+ }
+ ep->stopped = 0;
+
+ if (!ep_num)
+ dwc_otg_ep0_start_transfer(core_if, &ep->dwc_ep);
+ else
+ dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep);
+ }
+}
+
+/**
+ * Handle the IN EP Transfer Complete interrupt.
+ *
+ * If dedicated fifos are enabled, then the Tx FIFO empty interrupt for the EP
+ * is disabled. Otherwise the NP Tx FIFO empty interrupt is disabled.
+ */
+static void handle_in_ep_xfr_complete_intr(struct dwc_pcd *pcd,
+ struct pcd_ep *ep, u32 num)
+{
+ struct core_if *c_if = GET_CORE_IF(pcd);
+ struct device_if *d_if = c_if->dev_if;
+ struct dwc_ep *dwc_ep = &ep->dwc_ep;
+ u32 diepint = 0;
+
+ if (c_if->en_multiple_tx_fifo) {
+ u32 fifoemptymsk = 0x1 << dwc_ep->num;
+ dwc_reg_modify(d_if->dev_global_regs,
+ DWC_DTKNQR4FIFOEMPTYMSK, fifoemptymsk, 0);
+ } else {
+ u32 intr_mask = 0;
+
+ intr_mask |= DWC_INTMSK_NP_TXFIFO_EMPT;
+ dwc_reg_modify((c_if->core_global_regs), DWC_GINTMSK,
+ intr_mask, 0);
+ }
+
+ /* Clear the interrupt, then complete the transfer */
+ diepint = DWC_DIEPINT_TX_CMPL_RW(diepint, 1);
+ dwc_reg_write(d_if->in_ep_regs[num], DWC_DIEPINT, diepint);
+
+ if (!num)
+ handle_ep0(pcd);
+ else
+ complete_ep(ep);
+}
+
+/**
+ * Handle the IN EP disable interrupt.
+ */
+static void handle_in_ep_disable_intr(struct dwc_pcd *pcd, const u32 ep_num)
+{
+ struct core_if *core_if = GET_CORE_IF(pcd);
+ struct device_if *dev_if = core_if->dev_if;
+ u32 dieptsiz = 0;
+ u32 dctl = 0;
+ struct pcd_ep *ep;
+ struct dwc_ep *dwc_ep;
+ u32 diepint = 0;
+
+ ep = get_in_ep(pcd, ep_num);
+ dwc_ep = &ep->dwc_ep;
+
+ dieptsiz = dwc_reg_read(dev_if->in_ep_regs[ep_num], DWC_DIEPTSIZ);
+
+ if (ep->stopped) {
+ /* Flush the Tx FIFO */
+ dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num);
+
+ /* Clear the Global IN NP NAK */
+ dctl = 0;
+ dctl = DWC_DCTL_CLR_CLBL_NP_IN_NAK(dctl, 1);
+ dwc_reg_modify(dev_ctl_reg(pcd), 0, dctl, 0);
+
+ if (DWC_DEPTSIZ_PKT_CNT_RD(dieptsiz) ||
+ DWC_DEPTSIZ_XFER_SIZ_RD(dieptsiz))
+ restart_transfer(pcd, ep_num);
+ } else {
+ if (DWC_DEPTSIZ_PKT_CNT_RD(dieptsiz) ||
+ DWC_DEPTSIZ_XFER_SIZ_RD(dieptsiz))
+ restart_transfer(pcd, ep_num);
+ }
+ /* Clear epdisabled */
+ diepint = DWC_DIEPINT_EP_DISA_RW(diepint, 1);
+ dwc_reg_write(in_ep_int_reg(pcd, ep_num), 0, diepint);
+
+}
+
+/**
+ * Handler for the IN EP timeout handshake interrupt.
+ */
+static void handle_in_ep_timeout_intr(struct dwc_pcd *pcd, const u32 ep_num)
+{
+ struct core_if *core_if = GET_CORE_IF(pcd);
+ struct pcd_ep *ep;
+ u32 dctl = 0;
+ u32 intr_mask = 0;
+ u32 diepint = 0;
+
+ ep = get_in_ep(pcd, ep_num);
+
+ /* Disable the NP Tx Fifo Empty Interrrupt */
+ if (!core_if->dma_enable) {
+ intr_mask |= DWC_INTMSK_NP_TXFIFO_EMPT;
+ dwc_reg_modify((core_if->core_global_regs), DWC_GINTMSK,
+ intr_mask, 0);
+ }
+
+ /* Non-periodic EP */
+ /* Enable the Global IN NAK Effective Interrupt */
+ intr_mask |= DWC_INTMSK_GLBL_IN_NAK;
+ dwc_reg_modify((core_if->core_global_regs), DWC_GINTMSK, 0,
+ intr_mask);
+
+ /* Set Global IN NAK */
+ dctl = DWC_DCTL_CLR_CLBL_NP_IN_NAK(dctl, 1);
+ dwc_reg_modify(dev_ctl_reg(pcd), 0, dctl, dctl);
+ ep->stopped = 1;
+
+ /* Clear timeout */
+ diepint = DWC_DIEPINT_TOUT_COND_RW(diepint, 1);
+ dwc_reg_write(in_ep_int_reg(pcd, ep_num), 0, diepint);
+}
+
+/**
+ * Handles the IN Token received with TxF Empty interrupt.
+ *
+ * For the 405EZ, only start the next transfer, when currently no other transfer
+ * is active on this endpoint.
+ *
+ * Note that the bits in the Device IN endpoint mask register are laid out
+ * exactly the same as the Device IN endpoint interrupt register.
+ */
+static void handle_in_ep_tx_fifo_empty_intr(struct dwc_pcd *pcd,
+ struct pcd_ep *ep, u32 num)
+{
+ u32 diepint = 0;
+
+ if (!ep->stopped && num) {
+ u32 diepmsk = 0;
+
+ diepmsk = DWC_DIEPMSK_IN_TKN_TX_EMPTY_RW(diepmsk, 1);
+ dwc_reg_modify(dev_diepmsk_reg(pcd), 0, diepmsk, 0);
+
+ if (dwc_has_feature(GET_CORE_IF(pcd), DWC_LIMITED_XFER)) {
+ if (!ep->dwc_ep.active)
+ dwc_start_next_request(ep);
+ } else {
+ dwc_start_next_request(ep);
+ }
+ }
+ /* Clear intktxfemp */
+ diepint = DWC_DIEPMSK_IN_TKN_TX_EMPTY_RW(diepint, 1);
+ dwc_reg_write(in_ep_int_reg(pcd, num), 0, diepint);
+}
+
+static void handle_in_ep_nak_effective_intr(struct dwc_pcd *pcd,
+ struct pcd_ep *ep, u32 num)
+{
+ u32 diepctl = 0;
+ u32 diepint = 0;
+
+ /* Periodic EP */
+ if (ep->disabling) {
+ diepctl = 0;
+ diepctl = DWC_DEPCTL_SET_NAK_RW(diepctl, 1);
+ diepctl = DWC_DEPCTL_DPID_RW(diepctl, 1);
+ dwc_reg_modify(in_ep_ctl_reg(pcd, num), 0, diepctl, diepctl);
+ }
+ /* Clear inepnakeff */
+ diepint = DWC_DIEPINT_IN_EP_NAK_RW(diepint, 1);
+ dwc_reg_write(in_ep_int_reg(pcd, num), 0, diepint);
+
+}
+
+/**
+ * This function returns the Device IN EP Interrupt register
+ */
+static inline u32 dwc_otg_read_diep_intr(struct core_if *core_if,
+ struct dwc_ep *ep)
+{
+ struct device_if *dev_if = core_if->dev_if;
+ u32 v, msk, emp;
+
+ msk = dwc_reg_read(dev_if->dev_global_regs, DWC_DIEPMSK);
+ emp =
+ dwc_reg_read(dev_if->dev_global_regs, DWC_DTKNQR4FIFOEMPTYMSK);
+ msk |= ((emp >> ep->num) & 0x1) << 7;
+ v = dwc_reg_read(dev_if->in_ep_regs[ep->num], DWC_DIEPINT) & msk;
+ return v;
+}
+
+/**
+ * This function reads the Device All Endpoints Interrupt register and
+ * returns the IN endpoint interrupt bits.
+ */
+static inline u32 dwc_otg_read_dev_all_in_ep_intr(struct core_if *_if)
+{
+ u32 v;
+
+ v = dwc_reg_read(_if->dev_if->dev_global_regs, DWC_DAINT) &
+ dwc_reg_read(_if->dev_if->dev_global_regs, DWC_DAINTMSK);
+ return v & 0xffff;
+}
+
+/**
+ * This interrupt indicates that an IN EP has a pending Interrupt.
+ * The sequence for handling the IN EP interrupt is shown below:
+ *
+ * - Read the Device All Endpoint Interrupt register
+ * - Repeat the following for each IN EP interrupt bit set (from LSB to MSB).
+ *
+ * - Read the Device Endpoint Interrupt (DIEPINTn) register
+ * - If "Transfer Complete" call the request complete function
+ * - If "Endpoint Disabled" complete the EP disable procedure.
+ * - If "AHB Error Interrupt" log error
+ * - If "Time-out Handshake" log error
+ * - If "IN Token Received when TxFIFO Empty" write packet to Tx FIFO.
+ * - If "IN Token EP Mismatch" (disable, this is handled by EP Mismatch
+ * Interrupt)
+ */
+static int dwc_otg_pcd_handle_in_ep_intr(struct dwc_pcd *pcd)
+{
+ struct core_if *core_if = GET_CORE_IF(pcd);
+ u32 diepint = 0;
+ u32 ep_intr;
+ u32 epnum = 0;
+ struct pcd_ep *ep;
+ struct dwc_ep *dwc_ep;
+
+ /* Read in the device interrupt bits */
+ ep_intr = dwc_otg_read_dev_all_in_ep_intr(core_if);
+
+ /* Service the Device IN interrupts for each endpoint */
+ while (ep_intr) {
+ if (ep_intr & 0x1) {
+ u32 c_diepint;
+
+ /* Get EP pointer */
+ ep = get_in_ep(pcd, epnum);
+ dwc_ep = &ep->dwc_ep;
+
+ diepint = dwc_otg_read_diep_intr(core_if, dwc_ep);
+
+ /* Transfer complete */
+ if (DWC_DIEPINT_TX_CMPL_RD(diepint))
+ handle_in_ep_xfr_complete_intr(pcd, ep, epnum);
+
+ /* Endpoint disable */
+ if (DWC_DIEPINT_EP_DISA_RD(diepint))
+ handle_in_ep_disable_intr(pcd, epnum);
+
+ /* AHB Error */
+ if (DWC_DIEPINT_AHB_ERROR_RD(diepint)) {
+ /* Clear ahberr */
+ c_diepint = 0;
+ c_diepint =
+ DWC_DIEPINT_AHB_ERROR_RW(c_diepint, 1);
+ dwc_reg_write(in_ep_int_reg(pcd, epnum), 0,
+ c_diepint);
+ }
+
+ /* TimeOUT Handshake (non-ISOC IN EPs) */
+ if (DWC_DIEPINT_TOUT_COND_RD(diepint))
+ handle_in_ep_timeout_intr(pcd, epnum);
+
+ /* IN Token received with TxF Empty */
+ if (DWC_DIEPINT_IN_TKN_TX_EMPTY_RD(diepint))
+ handle_in_ep_tx_fifo_empty_intr(pcd, ep, epnum);
+
+ /* IN Token Received with EP mismatch */
+ if (DWC_DIEPINT_IN_TKN_EP_MISS_RD(diepint)) {
+ /* Clear intknepmis */
+ c_diepint = 0;
+ c_diepint =
+ DWC_DIEPINT_IN_TKN_EP_MISS_RW(c_diepint, 1);
+ dwc_reg_write(in_ep_int_reg(pcd, epnum), 0,
+ c_diepint);
+ }
+
+ /* IN Endpoint NAK Effective */
+ if (DWC_DIEPINT_IN_EP_NAK_RD(diepint))
+ handle_in_ep_nak_effective_intr(pcd, ep, epnum);
+
+ /* IN EP Tx FIFO Empty Intr */
+ if (DWC_DIEPINT_TXFIFO_EMPTY_RD(diepint))
+ write_empty_tx_fifo(pcd, epnum);
+ }
+ epnum++;
+ ep_intr >>= 1;
+ }
+ return 1;
+}
+
+/**
+ * This function reads the Device All Endpoints Interrupt register and
+ * returns the OUT endpoint interrupt bits.
+ */
+static inline u32 dwc_otg_read_dev_all_out_ep_intr(struct core_if *_if)
+{
+ u32 v;
+
+ v = dwc_reg_read(_if->dev_if->dev_global_regs, DWC_DAINT) &
+ dwc_reg_read(_if->dev_if->dev_global_regs, DWC_DAINTMSK);
+ return (v & 0xffff0000) >> 16;
+}
+
+/**
+ * This function returns the Device OUT EP Interrupt register
+ */
+static inline u32 dwc_otg_read_doep_intr(struct core_if *core_if,
+ struct dwc_ep *ep)
+{
+ struct device_if *dev_if = core_if->dev_if;
+ u32 v;
+
+ v = dwc_reg_read(dev_if->out_ep_regs[ep->num], DWC_DOEPINT) &
+ dwc_reg_read(dev_if->dev_global_regs, DWC_DOEPMSK);
+ return v;
+}
+
+/**
+ * This interrupt indicates that an OUT EP has a pending Interrupt.
+ * The sequence for handling the OUT EP interrupt is shown below:
+ *
+ * - Read the Device All Endpoint Interrupt register.
+ * - Repeat the following for each OUT EP interrupt bit set (from LSB to MSB).
+ *
+ * - Read the Device Endpoint Interrupt (DOEPINTn) register
+ * - If "Transfer Complete" call the request complete function
+ * - If "Endpoint Disabled" complete the EP disable procedure.
+ * - If "AHB Error Interrupt" log error
+ * - If "Setup Phase Done" process Setup Packet (See Standard USB Command
+ * Processing)
+ */
+static int dwc_otg_pcd_handle_out_ep_intr(struct dwc_pcd *pcd)
+{
+ struct core_if *core_if = GET_CORE_IF(pcd);
+ u32 ep_intr;
+ u32 doepint = 0;
+ u32 epnum = 0;
+ struct dwc_ep *dwc_ep;
+
+ /* Read in the device interrupt bits */
+ ep_intr = dwc_otg_read_dev_all_out_ep_intr(core_if);
+ while (ep_intr) {
+ if (ep_intr & 0x1) {
+ u32 c_doepint = 0;
+
+ dwc_ep = &((get_out_ep(pcd, epnum))->dwc_ep);
+ doepint = dwc_otg_read_doep_intr(core_if, dwc_ep);
+
+ /* Transfer complete */
+ if (DWC_DOEPINT_TX_COMPL_RD(doepint)) {
+ /* Clear xfercompl */
+ c_doepint = 0;
+ c_doepint =
+ DWC_DOEPMSK_TX_COMPL_RW(c_doepint, 1);
+ dwc_reg_write(out_ep_int_reg(pcd, epnum), 0,
+ c_doepint);
+ if (epnum == 0)
+ handle_ep0(pcd);
+ else
+ complete_ep(get_out_ep(pcd, epnum));
+ }
+
+ /* Endpoint disable */
+ if (DWC_DOEPINT_EP_DISA_RD(doepint)) {
+ /* Clear epdisabled */
+ c_doepint = 0;
+ c_doepint =
+ DWC_DOEPMSK_EP_DISA_RW(c_doepint, 1);
+ dwc_reg_write(out_ep_int_reg(pcd, epnum), 0,
+ c_doepint);
+ }
+
+ /* AHB Error */
+ if (DWC_DOEPINT_AHB_ERROR_RD(doepint)) {
+ c_doepint = 0;
+ c_doepint =
+ DWC_DOEPMSK_AHB_ERROR_RW(c_doepint, 1);
+ dwc_reg_write(out_ep_int_reg(pcd, epnum), 0,
+ c_doepint);
+ }
+
+ /* Setup Phase Done (control EPs) */
+ if (DWC_DOEPINT_SETUP_DONE_RD(doepint)) {
+ c_doepint = 0;
+ c_doepint =
+ DWC_DOEPMSK_SETUP_DONE_RW(c_doepint, 1);
+ dwc_reg_write(out_ep_int_reg(pcd, epnum), 0,
+ c_doepint);
+ handle_ep0(pcd);
+ }
+ }
+ epnum++;
+ ep_intr >>= 1;
+ }
+ return 1;
+}
+
+/**
+ * Incomplete ISO IN Transfer Interrupt. This interrupt indicates one of the
+ * following conditions occurred while transmitting an ISOC transaction.
+ *
+ * - Corrupted IN Token for ISOC EP.
+ * - Packet not complete in FIFO.
+ *
+ * The follow actions should be taken:
+ * - Determine the EP
+ * - Set incomplete flag in dwc_ep structure
+ * - Disable EP. When "Endpoint Disabled" interrupt is received Flush FIFO
+ */
+static int dwc_otg_pcd_handle_incomplete_isoc_in_intr(struct dwc_pcd *pcd)
+{
+ u32 intr_mask = 0;
+ u32 gintsts = 0;
+
+ pr_info("Interrupt handler not implemented for IN ISOC "
+ "Incomplete\n");
+
+ /* Turn off and clear the interrupt */
+ intr_mask |= DWC_INTMSK_INCMP_IN_ATX;
+ dwc_reg_modify((GET_CORE_IF(pcd)->core_global_regs), DWC_GINTMSK,
+ intr_mask, 0);
+
+ gintsts |= DWC_INTSTS_INCMP_IN_ATX;
+ dwc_reg_write((GET_CORE_IF(pcd)->core_global_regs), DWC_GINTSTS,
+ gintsts);
+ return 1;
+}
+
+/**
+ * Incomplete ISO OUT Transfer Interrupt. This interrupt indicates that the
+ * core has dropped an ISO OUT packet. The following conditions can be the
+ * cause:
+ *
+ * - FIFO Full, the entire packet would not fit in the FIFO.
+ * - CRC Error
+ * - Corrupted Token
+ *
+ * The follow actions should be taken:
+ * - Determine the EP
+ * - Set incomplete flag in dwc_ep structure
+ * - Read any data from the FIFO
+ * - Disable EP. When "Endpoint Disabled" interrupt is received re-enable EP.
+ */
+static int dwc_otg_pcd_handle_incomplete_isoc_out_intr(struct dwc_pcd *pcd)
+{
+ u32 intr_mask = 0;
+ u32 gintsts = 0;
+
+ pr_info("Interrupt handler not implemented for OUT ISOC "
+ "Incomplete\n");
+
+ /* Turn off and clear the interrupt */
+ intr_mask |= DWC_INTMSK_INCMP_OUT_PTX;
+ dwc_reg_modify((GET_CORE_IF(pcd)->core_global_regs), DWC_GINTMSK,
+ intr_mask, 0);
+
+ gintsts |= DWC_INTSTS_INCMP_OUT_PTX;
+ dwc_reg_write((GET_CORE_IF(pcd)->core_global_regs), DWC_GINTSTS,
+ gintsts);
+ return 1;
+}
+
+/**
+ * This function handles the Global IN NAK Effective interrupt.
+ */
+static int dwc_otg_pcd_handle_in_nak_effective(struct dwc_pcd *pcd)
+{
+ struct device_if *dev_if = GET_CORE_IF(pcd)->dev_if;
+ u32 diepctl = 0;
+ u32 diepctl_rd = 0;
+ u32 intr_mask = 0;
+ u32 gintsts = 0;
+ u32 i;
+
+ /* Disable all active IN EPs */
+ diepctl = DWC_DEPCTL_DPID_RW(diepctl, 1);
+ diepctl = DWC_DEPCTL_SET_NAK_RW(diepctl, 1);
+ for (i = 0; i <= dev_if->num_in_eps; i++) {
+ diepctl_rd = dwc_reg_read(in_ep_ctl_reg(pcd, i), 0);
+ if (DWC_DEPCTL_EPENA_RD(diepctl_rd))
+ dwc_reg_write(in_ep_ctl_reg(pcd, i), 0, diepctl);
+ }
+
+ /* Disable the Global IN NAK Effective Interrupt */
+ intr_mask |= DWC_INTMSK_GLBL_IN_NAK;
+ dwc_reg_modify((GET_CORE_IF(pcd)->core_global_regs), DWC_GINTMSK,
+ intr_mask, 0);
+
+ /* Clear interrupt */
+ gintsts |= DWC_INTSTS_GLBL_IN_NAK;
+ dwc_reg_write((GET_CORE_IF(pcd)->core_global_regs), DWC_GINTSTS,
+ gintsts);
+ return 1;
+}
+
+/**
+ * This function handles the Global OUT NAK Effective interrupt.
+ */
+static int dwc_otg_pcd_handle_out_nak_effective(struct dwc_pcd *pcd)
+{
+ u32 intr_mask = 0;
+ u32 gintsts = 0;
+
+ pr_info("Interrupt handler not implemented for Global IN "
+ "NAK Effective\n");
+
+ /* Turn off and clear the interrupt */
+ intr_mask |= DWC_INTMSK_GLBL_OUT_NAK;
+ dwc_reg_modify((GET_CORE_IF(pcd)->core_global_regs), DWC_GINTMSK,
+ intr_mask, 0);
+
+ /* Clear goutnakeff */
+ gintsts |= DWC_INTSTS_GLBL_OUT_NAK;
+ dwc_reg_write((GET_CORE_IF(pcd)->core_global_regs), DWC_GINTSTS,
+ gintsts);
+ return 1;
+}
+
+/**
+ * PCD interrupt handler.
+ *
+ * The PCD handles the device interrupts. Many conditions can cause a
+ * device interrupt. When an interrupt occurs, the device interrupt
+ * service routine determines the cause of the interrupt and
+ * dispatches handling to the appropriate function. These interrupt
+ * handling functions are described below.
+ *
+ * All interrupt registers are processed from LSB to MSB.
+ *
+ */
+int dwc_otg_pcd_handle_intr(struct dwc_pcd *pcd)
+{
+ struct core_if *core_if = GET_CORE_IF(pcd);
+ u32 gintr_status;
+ int ret = 0;
+
+ if (dwc_otg_is_device_mode(core_if)) {
+ spin_lock(&pcd->lock);
+
+ gintr_status = dwc_otg_read_core_intr(core_if);
+ if (!gintr_status) {
+ spin_unlock(&pcd->lock);
+ return 0;
+ }
+
+ if (gintr_status & DWC_INTSTS_STRT_OF_FRM)
+ ret |= dwc_otg_pcd_handle_sof_intr(pcd);
+ if (gintr_status & DWC_INTSTS_RXFIFO_NOT_EMPT)
+ ret |= dwc_otg_pcd_handle_rx_status_q_level_intr(pcd);
+ if (gintr_status & DWC_INTSTS_NP_TXFIFO_EMPT)
+ ret |= dwc_otg_pcd_handle_np_tx_fifo_empty_intr(pcd);
+ if (gintr_status & DWC_INTSTS_GLBL_IN_NAK)
+ ret |= dwc_otg_pcd_handle_in_nak_effective(pcd);
+ if (gintr_status & DWC_INTSTS_GLBL_OUT_NAK)
+ ret |= dwc_otg_pcd_handle_out_nak_effective(pcd);
+ if (gintr_status & DWC_INTSTS_I2C_INTR)
+ ret |= dwc_otg_pcd_handle_i2c_intr(pcd);
+ if (gintr_status & DWC_INTSTS_EARLY_SUSP)
+ ret |= dwc_otg_pcd_handle_early_suspend_intr(pcd);
+ if (gintr_status & DWC_INTSTS_USB_RST)
+ ret |= dwc_otg_pcd_handle_usb_reset_intr(pcd);
+ if (gintr_status & DWC_INTSTS_ENUM_DONE)
+ ret |= dwc_otg_pcd_handle_enum_done_intr(pcd);
+ if (gintr_status & DWC_INTSTS_ISYNC_OUTPKT_DRP)
+ ret |=
+ dwc_otg_pcd_handle_isoc_out_packet_dropped_intr
+ (pcd);
+ if (gintr_status & DWC_INTSTS_END_OF_PFRM)
+ ret |= dwc_otg_pcd_handle_end_periodic_frame_intr(pcd);
+ if (gintr_status & DWC_INTSTS_ENDP_MIS_MTCH)
+ ret |= dwc_otg_pcd_handle_ep_mismatch_intr(core_if);
+ if (gintr_status & DWC_INTSTS_IN_ENDP)
+ ret |= dwc_otg_pcd_handle_in_ep_intr(pcd);
+ if (gintr_status & DWC_INTSTS_OUT_ENDP)
+ ret |= dwc_otg_pcd_handle_out_ep_intr(pcd);
+ if (gintr_status & DWC_INTSTS_INCMP_IN_ATX)
+ ret |= dwc_otg_pcd_handle_incomplete_isoc_in_intr(pcd);
+ if (gintr_status & DWC_INTSTS_INCMP_OUT_PTX)
+ ret |= dwc_otg_pcd_handle_incomplete_isoc_out_intr(pcd);
+
+ spin_unlock(&pcd->lock);
+ }
+ return ret;
+}
diff --git a/drivers/usb/dwc/regs.h b/drivers/usb/dwc/regs.h
new file mode 100644
index 0000000..d1748f1
--- /dev/null
+++ b/drivers/usb/dwc/regs.h
@@ -0,0 +1,1326 @@
+/*
+ * DesignWare HS OTG controller driver
+ * Copyright (C) 2006 Synopsys, Inc.
+ * Portions Copyright (C) 2010 Applied Micro Circuits Corporation.
+ *
+ * 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 version 2 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
+ * or write to the Free Software Foundation, Inc., 51 Franklin Street,
+ * Suite 500, Boston, MA 02110-1335 USA.
+ *
+ * Based on Synopsys driver version 2.60a
+ * Modified by Mark Miesfeld <mmiesfeld@apm.com>
+ *
+ * Revamped register difinitions by Tirumala R Marri(tmarri@apm.com)
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL SYNOPSYS, INC. 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.
+ *
+ */
+
+#ifndef __DWC_OTG_REGS_H__
+#define __DWC_OTG_REGS_H__
+
+#include <linux/types.h>
+/*Bit fields in the Device EP Transfer Size Register is 11 bits */
+#undef DWC_LIMITED_XFER_SIZE
+/*
+ * This file contains the Macro defintions for accessing the DWC_otg core
+ * registers.
+ *
+ * The application interfaces with the HS OTG core by reading from and
+ * writing to the Control and Status Register (CSR) space through the
+ * AHB Slave interface. These registers are 32 bits wide, and the
+ * addresses are 32-bit-block aligned.
+ * CSRs are classified as follows:
+ * - Core Global Registers
+ * - Device Mode Registers
+ * - Device Global Registers
+ * - Device Endpoint Specific Registers
+ * - Host Mode Registers
+ * - Host Global Registers
+ * - Host Port CSRs
+ * - Host Channel Specific Registers
+ *
+ * Only the Core Global registers can be accessed in both Device and
+ * Host modes. When the HS OTG core is operating in one mode, either
+ * Device or Host, the application must not access registers from the
+ * other mode. When the core switches from one mode to another, the
+ * registers in the new mode of operation must be reprogrammed as they
+ * would be after a power-on reset.
+ */
+
+/*
+ * DWC_otg Core registers. The core_global_regs structure defines the
+ * size and relative field offsets for the Core Global registers.
+ */
+#define DWC_GOTGCTL 0x000
+#define DWC_GOTGINT 0x004
+#define DWC_GAHBCFG 0x008
+#define DWC_GUSBCFG 0x00C
+#define DWC_GRSTCTL 0x010
+#define DWC_GINTSTS 0x014
+#define DWC_GINTMSK 0x018
+#define DWC_GRXSTSR 0x01C
+#define DWC_GRXSTSP 0x020
+#define DWC_GRXFSIZ 0x024
+#define DWC_GNPTXFSIZ 0x028
+#define DWC_GNPTXSTS 0x02C
+#define DWC_GI2CCTL 0x030
+#define DWC_VDCTL 0x034
+#define DWC_GGPIO 0x038
+#define DWC_GUID 0x03C
+#define DWC_GSNPSID 0x040
+#define DWC_GHWCFG1 0x044
+#define DWC_GHWCFG2 0x048
+#define DWC_GHWCFG3 0x04c
+#define DWC_GHWCFG4 0x050
+#define DWC_HPTXFSIZ 0x100
+#define DWC_DPTX_FSIZ_DIPTXF(x) (0x104 + x * 4) /* 15 <= x > 1 */
+
+#define DWC_GLBINTRMASK 0x0001
+#define DWC_DMAENABLE 0x0020
+#define DWC_NPTXEMPTYLVL_EMPTY 0x0080
+#define DWC_NPTXEMPTYLVL_HALFEMPTY 0x0000
+#define DWC_PTXEMPTYLVL_EMPTY 0x0100
+#define DWC_PTXEMPTYLVL_HALFEMPTY 0x0000
+
+#define DWC_SLAVE_ONLY_ARCH 0
+#define DWC_EXT_DMA_ARCH 1
+#define DWC_INT_DMA_ARCH 2
+
+#define DWC_MODE_HNP_SRP_CAPABLE 0
+#define DWC_MODE_SRP_ONLY_CAPABLE 1
+#define DWC_MODE_NO_HNP_SRP_CAPABLE 2
+#define DWC_MODE_SRP_CAPABLE_DEVICE 3
+#define DWC_MODE_NO_SRP_CAPABLE_DEVICE 4
+#define DWC_MODE_SRP_CAPABLE_HOST 5
+#define DWC_MODE_NO_SRP_CAPABLE_HOST 6
+
+/*
+ * These Macros represents the bit fields of the Core OTG Controland Status
+ * Register (GOTGCTL). Set the bits using the bit fields then write the u32
+ * value to the register.
+ */
+#define DWC_GCTL_BSESSION_VALID (1 << 19)
+#define DWC_GCTL_CSESSION_VALID (1 << 18)
+#define DWC_GCTL_DEBOUNCE (1 << 17)
+#define DWC_GCTL_CONN_ID_STATUS (1 << 16)
+#define DWC_GCTL_DEV_HNP_ENA (1 << 11)
+#define DWC_GCTL_HOST_HNP_ENA (1 << 10)
+#define DWC_GCTL_HNP_REQ (1 << 9)
+#define DWC_GCTL_HOST_NEG_SUCCES (1 << 8)
+#define DWC_GCTL_SES_REQ (1 << 1)
+#define DWC_GCTL_SES_REQ_SUCCESS (1 << 0)
+
+#define DWC_GCTL_BSESSION_VALID_RD(reg) (((reg) & (0x001 << 19)) >> 19)
+#define DWC_GCTL_CSESSION_VALID_RD(reg) (((reg) & (0x001 << 18)) >> 18)
+#define DWC_GCTL_DEBOUNCE_RD(reg) (((reg) & (0x001 << 17)) >> 17)
+#define DWC_GCTL_CONN_ID_STATUS_RD(reg) (((reg) & (0x001 << 16)) >> 16)
+#define DWC_GCTL_DEV_HNP_ENA_RD(reg) (((reg) & (0x001 << 11)) >> 11)
+#define DWC_GCTL_HOST_HNP_ENA_RD(reg) (((reg) & (0x001 << 10)) >> 10)
+#define DWC_GCTL_HNP_REQ_RD(reg) (((reg) & (0x001 << 9)) >> 9)
+#define DWC_GCTL_HOST_NEG_SUCCES_RD(reg) (((reg) & (0x001 << 8)) >> 8)
+#define DWC_GCTL_SES_REQ_RD(reg) (((reg) & (0x001 << 1)) >> 1)
+#define DWC_GCTL_SES_REQ_SUCCESS_RD(reg) (((reg) & (0x001 << 0)) >> 0)
+
+#define DWC_GCTL_BSESSION_VALID_RW(reg, x) \
+ (((reg) & (~((u32)0x01 << 19))) | ((x) << 19))
+#define DWC_GCTL_CSESSION_VALID_RW(reg, x) \
+ (((reg) & (~((u32)0x01 << 18))) | ((x) << 18))
+#define DWC_GCTL_DEBOUNCE_RW(reg, x) \
+ (((reg) & (~((u32)0x01 << 17))) | ((x) << 17))
+#define DWC_GCTL_CONN_ID_STATUS_RW(reg, x) \
+ (((reg) & (~((u32)0x01 << 16))) | ((x) << 16))
+#define DWC_GCTL_DEV_HNP_ENA_RW (reg, x) \
+ (((reg) & (~((u32)0x01 << 11))) | ((x) << 11))
+#define DWC_GCTL_HOST_HNP_ENA_RW(reg, x) \
+ (((reg) & (~((u32)0x01 << 10))) | ((x) << 10))
+#define DWC_GCTL_HNP_REQ_RW(reg, x) \
+ (((reg) & (~((u32)0x01 << 9))) | ((x) << 9))
+#define DWC_GCTL_HOST_NEG_SUCCES_RW(reg, x) \
+ (((reg) & (~((u32)0x01 << 8))) | ((x) << 8))
+#define DWC_GCTL_SES_REQ_RW(reg, x) \
+ (((reg) & (~((u32)0x01 << 1))) | ((x) << 1))
+#define DWC_GCTL_SES_REQ_SUCCESS_RW(reg, x) \
+ (((reg) & (~((u32)0x01 << 0))) | ((x) << 0))
+/*
+ * These Macros represents the bit fields of the Core OTG Interrupt Register
+ * (GOTGINT). Set/clear the bits using the bit fields then write the u32
+ * value to the register.
+ */
+#define DWC_GINT_DEBDONE (1 << 19)
+#define DWC_GINT_DEVTOUT (1 << 18)
+#define DWC_GINT_HST_NEGDET (1 << 17)
+#define DWC_GINT_HST_NEGSUC (1 << 9)
+#define DWC_GINT_SES_REQSUC (1 << 8)
+#define DWC_GINT_SES_ENDDET (1 << 2)
+
+/*
+ * These Macros represents the bit fields of the Core AHB Configuration Register
+ * (GAHBCFG). Set/clear the bits using the bit fields then write the u32 value
+ * to the register.
+ */
+#define DWC_AHBCFG_FIFO_EMPTY (1 << 8)
+#define DWC_AHBCFG_NPFIFO_EMPTY (1 << 7)
+#define DWC_AHBCFG_DMA_ENA (1 << 5)
+#define DWC_AHBCFG_BURST_LEN(x) (x << 1)
+#define DWC_AHBCFG_GLBL_INT_MASK (1 << 0)
+
+#define DWC_GAHBCFG_TXFEMPTYLVL_EMPTY 1
+#define DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY 0
+#define DWC_GAHBCFG_DMAENABLE 1
+#define DWC_GAHBCFG_INT_DMA_BURST_SINGLE 0
+#define DWC_GAHBCFG_INT_DMA_BURST_INCR 1
+#define DWC_GAHBCFG_INT_DMA_BURST_INCR4 3
+#define DWC_GAHBCFG_INT_DMA_BURST_INCR8 5
+#define DWC_GAHBCFG_INT_DMA_BURST_INCR16 7
+
+/*
+
+ * (GUSBCFG). Set the bits using the bit fields then write the u32 value to the
+ * register.
+ */
+#define DWC_USBCFG_CORR_PKT (1 << 31)
+#define DWC_USBCFG_FRC_DEV_MODE (1 << 30)
+#define DWC_USBCFG_FRC_HST_MODE (1 << 29)
+#define DWC_USBCFG_TERM_SEL_DL_PULSE (1 << 22)
+#define DWC_USBCFG_ULPI_INTVBUS_INDICATOR (1 << 21)
+#define DWC_USBCFG_ULPI_EXT_VBUS_DRV (1 << 20)
+#define DWC_USBCFG_ULPI_CLK_SUS_M (1 << 19)
+#define DWC_USBCFG_ULPI_AUTO_RES (1 << 18)
+#define DWC_USBCFG_ULPI_FSLS (1 << 17)
+#define DWC_USBCFG_OTGUTMIFSSEL (1 << 16)
+#define DWC_USBCFG_PHYLPWRCLKSEL (1 << 15)
+#define DWC_USBCFG_NPTXFRWNDEN (1 << 14)
+#define DWC_USBCFG_TRN_TIME(x) (x << 10)
+#define DWC_USBCFG_HNP_CAP (1 << 9)
+#define DWC_USBCFG_SRP_CAP (1 << 8)
+#define DWC_USBCFG_DDRSEL (1 << 7)
+#define DWC_USBCFG_USB_2_11 (1 << 6)
+#define DWC_USBCFG_FSINTF (1 << 5)
+#define DWC_USBCFG_ULPI_UTMI_SEL (1 << 4)
+#define DWC_USBCFG_PHYIF (1 << 3)
+#define DWC_USBCFG_TOUT_CAL(x) (x << 0)
+
+/*
+ * These Macros represents the bit fields of the Core Reset Register (GRSTCTL).
+ * Set/clear the bits using the bit fields then write the u32 value to the
+ * register.
+ */
+#define DWC_RSTCTL_AHB_IDLE (1 << 31)
+#define DWC_RSTCTL_DMA_REQ (1 << 30)
+#define DWC_RSTCTL_TX_FIFO_NUM(reg, x) \
+ (((reg) & (~((u32)0x1f << 6))) | ((x) << 6))
+#define DWC_RSTCTL_TX_FIFO_FLUSH (1 << 5)
+#define DWC_RSTCTL_RX_FIFO_FLUSH (1 << 4)
+#define DWC_RSTCTL_TKN_QUE_FLUSH (1 << 3)
+#define DWC_RSTCTL_HSTFRM_CNTR_RST (1 << 2)
+#define DWC_RSTCTL_HCLK_SFT_RST (1 << 1)
+#define DWC_RSTCTL_SFT_RST (1 << 1)
+#define DWC_GRSTCTL_TXFNUM_ALL 0x10
+
+/*
+ * These Macros represents the bit fields of the Core Interrupt Mask Register
+ * (GINTMSK). Set/clear the bits using the bit fields then write the u32 value
+ * to the register.
+ */
+#define DWC_INTMSK_WKP (1 << 31)
+#define DWC_INTMSK_NEW_SES_DET (1 << 30)
+#define DWC_INTMSK_SES_DISCON_DET (1 << 29)
+#define DWC_INTMSK_CON_ID_STS_CHG (1 << 28)
+#define DWC_INTMSK_P_TXFIFO_EMPTY (1 << 26)
+#define DWC_INTMSK_HST_CHAN (1 << 25)
+#define DWC_INTMSK_HST_PORT (1 << 24)
+#define DWC_INTMSK_DATA_FETCH_SUS (1 << 23)
+#define DWC_INTMSK_INCMP_PTX (1 << 22)
+#define DWC_INTMSK_INCMP_OUT_PTX (1 << 21)
+#define DWC_INTMSK_INCMP_IN_ATX (1 << 20)
+#define DWC_INTMSK_OUT_ENDP (1 << 19)
+#define DWC_INTMSK_IN_ENDP (1 << 18)
+#define DWC_INTMSK_ENDP_MIS_MTCH (1 << 17)
+#define DWC_INTMSK_END_OF_PFRM (1 << 15)
+#define DWC_INTMSK_ISYNC_OUTPKT_DRP (1 << 14)
+#define DWC_INTMSK_ENUM_DONE (1 << 13)
+#define DWC_INTMSK_USB_RST (1 << 12)
+#define DWC_INTMSK_USB_SUSP (1 << 11)
+#define DWC_INTMSK_EARLY_SUSP (1 << 10)
+#define DWC_INTMSK_I2C_INTR (1 << 9)
+#define DWC_INTMSK_GLBL_OUT_NAK (1 << 7)
+#define DWC_INTMSK_GLBL_IN_NAK (1 << 6)
+#define DWC_INTMSK_NP_TXFIFO_EMPT (1 << 5)
+#define DWC_INTMSK_RXFIFO_NOT_EMPT (1 << 4)
+#define DWC_INTMSK_STRT_OF_FRM (1 << 3)
+#define DWC_INTMSK_OTG (1 << 2)
+#define DWC_INTMSK_MODE_MISMTC (1 << 1)
+/*
+ * These Macros represents the bit fields of the Core Interrupt Register
+ * (GINTSTS). Set/clear the bits using the bit fields then write the u32 value
+ * to the register.
+ */
+#define DWC_INTSTS_WKP (1 << 31)
+#define DWC_INTSTS_NEW_SES_DET (1 << 30)
+#define DWC_INTSTS_SES_DISCON_DET (1 << 29)
+#define DWC_INTSTS_CON_ID_STS_CHG (1 << 28)
+#define DWC_INTSTS_P_TXFIFO_EMPTY (1 << 26)
+#define DWC_INTSTS_HST_CHAN (1 << 25)
+#define DWC_INTSTS_HST_PORT (1 << 24)
+#define DWC_INTSTS_DATA_FETCH_SUS (1 << 23)
+#define DWC_INTSTS_INCMP_PTX (1 << 22)
+#define DWC_INTSTS_INCMP_OUT_PTX (1 << 21)
+#define DWC_INTSTS_INCMP_IN_ATX (1 << 20)
+#define DWC_INTSTS_OUT_ENDP (1 << 19)
+#define DWC_INTSTS_IN_ENDP (1 << 18)
+#define DWC_INTSTS_ENDP_MIS_MTCH (1 << 17)
+#define DWC_INTSTS_END_OF_PFRM (1 << 15)
+#define DWC_INTSTS_ISYNC_OUTPKT_DRP (1 << 14)
+#define DWC_INTSTS_ENUM_DONE (1 << 13)
+#define DWC_INTSTS_USB_RST (1 << 12)
+#define DWC_INTSTS_USB_SUSP (1 << 11)
+#define DWC_INTSTS_EARLY_SUSP (1 << 10)
+#define DWC_INTSTS_I2C_INTR (1 << 9)
+#define DWC_INTSTS_GLBL_OUT_NAK (1 << 7)
+#define DWC_INTSTS_GLBL_IN_NAK (1 << 6)
+#define DWC_INTSTS_NP_TXFIFO_EMPT (1 << 5)
+#define DWC_INTSTS_RXFIFO_NOT_EMPT (1 << 4)
+#define DWC_INTSTS_STRT_OF_FRM (1 << 3)
+#define DWC_INTSTS_OTG (1 << 2)
+#define DWC_INTSTS_MODE_MISMTC (1 << 1)
+#define DWC_INTSTS_CURR_MODE (1 << 0)
+#define DWC_SOF_INTR_MASK 0x0008
+#define DWC_HOST_MODE 1
+
+/*
+ * These Macros represents the bit fields in the Device Receive Status Read and
+ * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the u32
+ * element then read out the bits using the bit elements.
+ */
+#define DWC_DM_RXSTS_PKT_STS (0x01f << 17)
+#define DWC_DM_RXSTS_PKT_DPID (0x003 << 15)
+#define DWC_DM_RXSTS_BYTE_CNT (0x7ff << 4)
+#define DWC_DM_RXSTS_CHAN_NUM (0x00f << 0)
+
+#define DWC_DM_RXSTS_PKT_STS_RD(reg) (((reg) & (0x00f << 17)) >> 17)
+#define DWC_DM_RXSTS_PKT_DPID_RD(reg) (((reg) & (0x003 << 15)) >> 15)
+#define DWC_DM_RXSTS_BYTE_CNT_RD(reg) (((reg) & (0x7ff << 04)) >> 04)
+#define DWC_DM_RXSTS_CHAN_NUM_RD(reg) ((reg) & 0x00f)
+
+#define DWC_STS_DATA_UPDT 0x2 /* OUT Data Packet */
+#define DWC_STS_XFER_COMP 0x3 /* OUT Data Transfer Complete */
+#define DWC_DSTS_GOUT_NAK 0x1 /* Global OUT NAK */
+#define DWC_DSTS_SETUP_COMP 0x4 /* Setup Phase Complete */
+#define DWC_DSTS_SETUP_UPDT 0x6 /* SETUP Packet */
+
+/*
+ * These Macros represents the bit fields in the Host Receive Status Read and
+ * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the u32
+ * element then read out the bits using the bit elements.
+ */
+#define DWC_HM_RXSTS_FRM_NUM (0x00f << 21)
+#define DWC_HM_RXSTS_PKT_STS (0x01f << 17)
+#define DWC_HM_RXSTS_PKT_DPID (0x003 << 15)
+#define DWC_HM_RXSTS_BYTE_CNT (0x7ff << 4)
+#define DWC_HM_RXSTS_CHAN_NUM (0x00f << 0)
+
+#define DWC_HM_RXSTS_PKT_STS_RD(reg) (((reg) & (0x00f << 17)) >> 17)
+#define DWC_HM_RXSTS_PKT_DPID_RD(reg) (((reg) & (0x003 << 15)) >> 15)
+#define DWC_HM_RXSTS_BYTE_CNT_RD(reg) (((reg) & (0x7ff << 04)) >> 04)
+#define DWC_HM_RXSTS_CHAN_NUM_RD(reg) ((reg) & 0x00f)
+
+#define DWC_GRXSTS_PKTSTS_IN 0x2
+#define DWC_GRXSTS_PKTSTS_IN_XFER_COMP 0x3
+#define DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR 0x5
+#define DWC_GRXSTS_PKTSTS_CH_HALTED 0x7
+
+/*
+ * These Macros represents the bit fields in the FIFO Size Registers (HPTXFSIZ,
+ * GNPTXFSIZ, DPTXFSIZn). Read the register into the u32 element then
+ * read out the bits using the bit elements.
+ */
+#define DWC_RX_FIFO_DEPTH_RD(reg) (((reg) & ((u32)0xffff << 16)) >> 16)
+#define DWC_RX_FIFO_DEPTH_WR(reg, x) \
+ (((reg) & (~((u32)0xffff << 16))) | ((x) << 16))
+#define DWC_RX_FIFO_START_ADDR_RD(reg) ((reg) & 0xffff)
+#define DWC_RX_FIFO_START_ADDR_WR(reg, x) \
+ (((reg) & (~((u32)0xffff))) | (x))
+
+/*
+ * These Macros represents the bit fields in the Non-Periodic Tx FIFO/Queue
+ * Status Register (GNPTXSTS). Read the register into the u32 element then read
+ * out the bits using the bit elements.
+ */
+#define DWC_GNPTXSTS_NPTXQTOP_CHNEP_RD(x) (((x) & (0x3f << 26)) >> 26)
+#define DWC_GNPTXSTS_NPTXQTOP_TKN_RD(x) (((x) & (0x03 << 24)) >> 24)
+#define DWC_GNPTXSTS_NPTXQSPCAVAIL_RD(x) (((x) & (0xff << 16)) >> 16)
+#define DWC_GNPTXSTS_NPTXFSPCAVAIL_RD(x) (0xffff & (x))
+
+/*
+ * These Macros represents the bit fields in the Transmit FIFO Status Register
+ * (DTXFSTS). Read the register into the u32 element then read out the bits
+ * using the bit elements.
+ */
+#define DWC_DTXFSTS_TXFSSPC_AVAI_RD(x) ((x) & 0xffff)
+
+/*
+ * These Macros represents the bit fields in the I2C Control Register (I2CCTL).
+ * Read the register into the u32 element then read out the bits using the bit
+ * elements.
+ */
+#define DWC_I2CCTL_BSYDNE (1 << 31)
+#define DWC_I2CCTL_RW (1 << 30)
+#define DWC_I2CCTL_I2CDEVADDR(x) ((x) << 27)
+#define DWC_I2CCTL_I2CSUSCTL (1 << 25)
+#define DWC_I2CCTL_ACK (1 << 24)
+#define DWC_I2CCTL_I2CEN (1 << 23)
+#define DWC_I2CCTL_ADDR (1 << 22)
+#define DWC_I2CCTL_REGADDR(x) ((x) << 14)
+#define DWC_I2CCTL_RWDATA(x) ((x) << 6)
+
+/*
+ * These Macros represents the bit fields in the User HW Config1 Register. Read
+ * the register into the u32 element then read out the bits using the bit
+ * elements.
+ */
+#define DWC_HWCFG1_EPDIR15(x) ((x) << 30)
+#define DWC_HWCFG1_EPDIR14(x) ((x) << 28)
+#define DWC_HWCFG1_EPDIR13(x) ((x) << 26)
+#define DWC_HWCFG1_EPDIR12(x) ((x) << 24)
+#define DWC_HWCFG1_EPDIR11(x) ((x) << 22)
+#define DWC_HWCFG1_EPDIR10(x) ((x) << 20)
+#define DWC_HWCFG1_EPDIR9(x) ((x) << 18)
+#define DWC_HWCFG1_EPDIR8(x) ((x) << 16)
+#define DWC_HWCFG1_EPDIR7(x) ((x) << 14)
+#define DWC_HWCFG1_EPDIR6(x) ((x) << 13)
+#define DWC_HWCFG1_EPDIR5(x) ((x) << 10)
+#define DWC_HWCFG1_EPDIR4(x) ((x) << 8)
+#define DWC_HWCFG1_EPDIR3(x) ((x) << 6)
+#define DWC_HWCFG1_EPDIR2(x) ((x) << 4)
+#define DWC_HWCFG1_EPDIR1(x) ((x) << 2)
+#define DWC_HWCFG1_EPDIR0(x) ((x) << 0)
+
+/*
+ * These Macros represents the bit fields in the User HW Config2 Register. Read
+ * the register into the u32 element then read out the bits using the bit
+ * elements.
+ */
+#define DWC_HWCFG2_DEV_TKN_Q_DEPTH_RD(x) (((x) & (0x1F << 26)) >> 26)
+#define DWC_HWCFG2_HOST_PERIO_Q_DEPTH_RD(x) (((x) & (0x3 << 24)) >> 24)
+#define DWC_HWCFG2_NP_TX_Q_DEPTH_RD(x) (((x) & (0x3 << 22)) >> 22)
+#define DWC_HWCFG2_RX_STS_Q_DEPTH_RD(x) (((x) & (0x3 << 20)) >> 20)
+#define DWC_HWCFG2_DYN_FIFO_RD(x) (((x) & (0x1 << 19)) >> 19)
+#define DWC_HWCFG2_PERIO_EP_SUPP_RD(x) (((x) & (0x1 << 18)) >> 18)
+#define DWC_HWCFG2_NO_HST_CHAN_RD(x) (((x) & (0xf << 14)) >> 14)
+#define DWC_HWCFG2_NO_DEV_EP_RD(x) (((x) & (0xf << 10)) >> 10)
+#define DWC_HWCFG2_FS_PHY_TYPE_RD(x) (((x) & (0x3 << 8)) >> 8)
+#define DWC_HWCFG2_HS_PHY_TYPE_RD(x) (((x) & (0x3 << 6)) >> 6)
+#define DWC_HWCFG2_P_2_P_RD(x) (((x) & (0x1 << 5)) >> 5)
+#define DWC_HWCFG2_ARCH_RD(x) (((x) & (0x3 << 3)) >> 3)
+#define DWC_HWCFG2_OP_MODE_RD(x) ((x) & 0x7)
+
+#define DWC_HWCFG2_HS_PHY_TYPE_NOT_SUPPORTED 0
+#define DWC_HWCFG2_HS_PHY_TYPE_UTMI 1
+#define DWC_HWCFG2_HS_PHY_TYPE_ULPI 2
+#define DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI 3
+#define DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG 0
+#define DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG 1
+#define DWC_HWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE_OTG 2
+#define DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE 3
+#define DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE 4
+#define DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST 5
+#define DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST 6
+
+/*
+ * These Macros represents the bit fields in the User HW Config3 Register. ead
+ * the register into the u32 element then read out the bits using the bit
+ * elements.
+ */
+#define DWC_HWCFG3_DFIFO_DEPTH_RD(x) (((x) & (0xffff << 16)) >> 16)
+#define DWC_HWCFG3_AHB_PHY_CLK_SYNC_RD(x) (((x) & (0x1 << 12)) >> 12)
+#define DWC_HWCFG3_SYNC_RST_TYPE_RD(x) (((x) & (0x1 << 11)) >> 11)
+#define DWC_HWCFG3_OPT_FEATURES_RD(x) (((x) & (0x1 << 10)) >> 10)
+#define DWC_HWCFG3_VEND_CTRL_IF_RD(x) (((x) & (0x1 << 9)) >> 9)
+#define DWC_HWCFG3_I2C_RD(x) (((x) & (0x1 << 8)) >> 8)
+#define DWC_HWCFG3_OTG_FUNC_RD(x) (((x) & (0x1 << 07)) >> 07)
+#define DWC_HWCFG3_PKTSIZE_CTR_WIDTH_RD(x) (((x) & (0x7 << 04)) >> 04)
+#define DWC_HWCFG3_XFERSIZE_CTR_WIDTH_RD(x) ((x) & 0xf)
+
+/*
+ * These Macros represents the bit fields in the User HW Config4 Register. Read
+ * the register into the u32 element then read out the bits using the bit
+ * elements.
+ */
+#define DWC_HWCFG4_NUM_IN_EPS_RD(x) (((x) & (0xF << 26)) >> 26)
+#define DWC_HWCFG4_DED_FIFO_ENA_RD(x) (((x) & (0x1 << 25)) >> 25)
+#define DWC_HWCFG4_SES_END_FILT_EN_RD(x) (((x) & (0x1 << 24)) >> 24)
+#define DWC_HWCFG4_BVALID_FILT_EN_RD(x) (((x) & (0x1 << 23)) >> 23)
+#define DWC_HWCFG4_AVALID_FILT_EN_RD(x) (((x) & (0x1 << 22)) >> 22)
+#define DWC_HWCFG4_VBUS_VALID_FILT_EN_RD(x) (((x) & (0x1 << 21)) >> 21)
+#define DWC_HWCFG4_IDDIG_FILT_EN_RD(x) (((x) & (0x1 << 20)) >> 20)
+#define DWC_HWCFG4_NUM_DEV_MODE_CTRL_EP_RD(x) (((x) & (0xF << 16)) >> 16)
+#define DWC_HWCFG4_UTMI_PHY_DATA_WIDTH_RD(x) (((x) & (0x3 << 14)) >> 14)
+#define DWC_HWCFG4_MIN_AHB_FREQ_RD(x) (((x) & (0x1 << 05)) >> 05)
+#define DWC_HWCFG4_POWER_OPT_RD(x) (((x) & (0x1 << 04)) >> 04)
+#define DWC_HWCFG4_NUM_DEV_PERIO_IN_EP_RD(x) ((x) & 0xf)
+
+/*
+ * Device Global Registers. Offsets 800h-BFFh
+ *
+ * The following structures define the size and relative field offsets for the
+ * Device Mode Registers.
+ *
+ * These registers are visible only in Device mode and must not be accessed in
+ * Host mode, as the results are unknown.
+ */
+#define DWC_DCFG 0x000
+#define DWC_DCTL 0x004
+#define DWC_DSTS 0x008
+#define DWC_DIEPMSK 0x010
+#define DWC_DOEPMSK 0x014
+#define DWC_DAINT 0x018
+#define DWC_DAINTMSK 0x01C
+#define DWC_DTKNQR1 0x020
+#define DWC_DTKNQR2 0x024
+#define DWC_DVBUSDIS 0x028
+#define DWC_DVBUSPULSE 0x02C
+#define DWC_DTKNQR3_DTHRCTL 0x030
+#define DWC_DTKNQR4FIFOEMPTYMSK 0x034
+
+/*
+ * These Macros represents the bit fields in the Device Configuration
+ * Register. Read the register into the u32 member then
+ * set/clear the bits using the bit elements. Write the
+ * u32 member to the dcfg register.
+*/
+#define DWC_DCFG_IN_EP_MISMATCH_CNT_RD(x) (((x) & (0x1f << 18)) >> 18)
+#define DWC_DCFG_P_FRM_INTRVL_RD(x) (((x) & (0x03 << 11)) >> 11)
+#define DWC_DCFG_DEV_ADDR_RD(x) (((x) & (0x3f << 04)) >> 04)
+#define DWC_DCFG_NGL_STS_OUT_RD(x) (((x) & (0x1 << 2)) >> 2)
+#define DWC_DCFG_DEV_SPEED_RD(x) ((x) & 0x3)
+
+#define DWC_DCFG_IN_EP_MISMATCH_CNT_WR(reg, x) \
+ (((reg) & (~((u32)0x1f << 18))) | ((x) << 18))
+#define DWC_DCFG_P_FRM_INTRVL_WR(reg, x) \
+ (((reg) & (~((u32)0x03 << 11))) | ((x) << 11))
+#define DWC_DCFG_DEV_ADDR_WR(reg, x) \
+ (((reg) & (~((u32)0x3f << 04))) | ((x) << 04))
+#define DWC_DCFG_NGL_STS_OUT_WR(reg, x) \
+ (((reg) & (~((u32)0x1 << 2))) | ((x) << 2))
+#define DWC_DCFG_DEV_SPEED_WR(reg, x) \
+ (((reg) & (~(u32)0x3)) | (x))
+
+#define DWC_DCFG_FRAME_INTERVAL_80 0
+#define DWC_DCFG_FRAME_INTERVAL_85 1
+#define DWC_DCFG_FRAME_INTERVAL_90 2
+#define DWC_DCFG_FRAME_INTERVAL_95 3
+
+/*
+ * These Macros represents the bit fields in the Device Control Register. Read
+ * the register into the u32 member then set/clear the bits using the bit
+ * elements.
+ */
+#define DWC_DCTL_PWR_ON_PROG_DONE_RD(x) (((x) & (1 << 11)) >> 11)
+
+#define DWC_DCTL_PWR_ON_PROG_DONE_WR(reg, x) \
+ (((reg) & (~((u32)0x01 << 11))) | ((x) << 11))
+#define DWC_DCTL_CLR_GLBL_OUT_NAK_WR(reg, x) \
+ (((reg) & (~((u32)0x01 << 10))) | ((x) << 10))
+#define DWC_DCTL_SET_GLBL_OUT_NAL(reg, x) \
+ (((reg) & (~((u32)0x01 << 9))) | ((x) << 9))
+#define DWC_DCTL_CLR_CLBL_NP_IN_NAK(reg, x) \
+ (((reg) & (~((u32)0x01 << 8))) | ((x) << 8))
+#define DWC_DCTL_SET_GLBL_NP_IN_NAK(reg, x) \
+ (((reg) & (~((u32)0x01 << 07))) | ((x) << 07))
+#define DWC_DCTL_TST_CTL(reg, x) \
+ (((reg) & (~((u32)0x07 << 04))) | ((x) << 04))
+#define DWC_DCTL_GLBL_OUT_NAK_STS(reg, x) \
+ (((reg) & (~((u32)0x01 << 03))) | ((x) << 03))
+#define DWC_DCTL_GLBL_NP_IN_NAK(reg, x) \
+ (((reg) & (~((u32)0x01 << 02))) | ((x) << 02))
+#define DWC_DCTL_SFT_DISCONNECT(reg, x) \
+ (((reg) & (~((u32)0x01 << 01))) | ((x) << 01))
+#define DEC_DCTL_REMOTE_WAKEUP_SIG(reg, x) \
+ (((reg) & (~((u32)0x01 << 00))) | ((x) << 00))
+
+/*
+ * These Macros represents the bit fields in the Dev Status Register. Read the
+ * register into the u32 member then set/clear the bits using the bit elements.
+ */
+#define DWC_DSTS_SOFFN_RD(x) (((x) & (0x3fff << 8)) >> 8)
+#define DWC_DSTS_ERRTICERR_RD(x) (((x) & (0x0001 << 3)) >> 3)
+#define DWC_DSTS_ENUM_SPEED_RD(x) (((x) & (0x0003 << 1)) >> 1)
+#define DWC_DSTS_SUSP_STS_RD(x) ((x) & 1)
+
+#define DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ 0
+#define DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ 1
+#define DWC_DSTS_ENUMSPD_LS_PHY_6MHZ 2
+#define DWC_DSTS_ENUMSPD_FS_PHY_48MHZ 3
+
+/*
+ * These Macros represents the bit fields in the Device IN EP Interrupt Register
+ * and the Device IN EP Common Mask Register.
+ *
+ * Read the register into the u32 member then set/clear the bits using the bit
+ * elements.
+ */
+#define DWC_DIEPINT_TXFIFO_UNDERN_RD(x) (((x) & (0x1 << 8)) >> 8)
+#define DWC_DIEPINT_TXFIFO_EMPTY_RD(x) (((x) & (0x1 << 7)) >> 7)
+#define DWC_DIEPINT_IN_EP_NAK_RD(x) (((x) & (0x1 << 6)) >> 6)
+#define DWC_DIEPINT_IN_TKN_EP_MISS_RD(x) (((x) & (0x1 << 5)) >> 5)
+#define DWC_DIEPINT_IN_TKN_TX_EMPTY_RD(x) (((x) & (0x1 << 4)) >> 4)
+#define DWC_DIEPINT_TOUT_COND_RD(x) (((x) & (0x1 << 3)) >> 3)
+#define DWC_DIEPINT_AHB_ERROR_RD(x) (((x) & (0x1 << 2)) >> 2)
+#define DWC_DIEPINT_EP_DISA_RD(x) (((x) & (0x1 << 1)) >> 1)
+#define DWC_DIEPINT_TX_CMPL_RD(x) ((x) & 0x1)
+
+#define DWC_DIEPINT_TXFIFO_UNDERN_RW(reg, x) \
+ (((reg) & (~((u32)0x01 << 8))) | ((x) << 8))
+#define DWC_DIEPINT_TXFIFO_EMPTY_RW(reg, x) \
+ (((reg) & (~((u32)0x01 << 7))) | ((x) << 7))
+#define DWC_DIEPINT_IN_EP_NAK_RW(reg, x) \
+ (((reg) & (~((u32)0x01 << 6))) | ((x) << 6))
+#define DWC_DIEPINT_IN_TKN_EP_MISS_RW(reg, x) \
+ (((reg) & (~((u32)0x01 << 5))) | ((x) << 5))
+#define DWC_DIEPINT_IN_TKN_TX_EMPTY_RW(reg, x) \
+ (((reg) & (~((u32)0x01 << 4))) | ((x) << 4))
+#define DWC_DIEPINT_TOUT_COND_RW(reg, x) \
+ (((reg) & (~((u32)0x01 << 3))) | ((x) << 3))
+#define DWC_DIEPINT_AHB_ERROR_RW(reg, x) \
+ (((reg) & (~((u32)0x01 << 2))) | ((x) << 2))
+#define DWC_DIEPINT_EP_DISA_RW(reg, x) \
+ (((reg) & (~((u32)0x01 << 1))) | ((x) << 1))
+#define DWC_DIEPINT_TX_CMPL_RW(reg, x) \
+ (((reg) & (~((u32)0x01 << 0))) | ((x) << 0))
+
+#define DWC_DIEPMSK_TXFIFO_UNDERN_RW(reg, x) \
+ (((reg) & (~((u32)0x01 << 8))) | ((x) << 8))
+#define DWC_DIEPMSK_TXFIFO_EMPTY_RW(reg, x) \
+ (((reg) & (~((u32)0x01 << 7))) | ((x) << 7))
+#define DWC_DIEPMSK_IN_EP_NAK_RW(reg, x) \
+ (((reg) & (~((u32)0x01 << 6))) | ((x) << 6))
+#define DWC_DIEPMSK_IN_TKN_EP_MISS_RW(reg, x) \
+ (((reg) & (~((u32)0x01 << 5))) | ((x) << 5))
+#define DWC_DIEPMSK_IN_TKN_TX_EMPTY_RW(reg, x) \
+ (((reg) & (~((u32)0x01 << 4))) | ((x) << 4))
+#define DWC_DIEPMSK_TOUT_COND_RW(reg, x) \
+ (((reg) & (~((u32)0x01 << 3))) | ((x) << 3))
+#define DWC_DIEPMSK_AHB_ERROR_RW(reg, x) \
+ (((reg) & (~((u32)0x01 << 2))) | ((x) << 2))
+#define DWC_DIEPMSK_EP_DISA_RW(reg, x) \
+ (((reg) & (~((u32)0x01 << 1))) | ((x) << 1))
+#define DWC_DIEPMSK_TX_CMPL_RW(reg, x) \
+ (((reg) & (~((u32)0x01 << 0))) | ((x) << 0))
+
+/*
+ * These Macros represents the bit fields in the Device OUT EP Itr Register
+ * and Device OUT EP Common Interrupt Mask Register.
+ *
+ * Read the register into the u32 member then set/clear the bits using the bit
+ * elements.
+ */
+#define DWC_DOEPINT_OUTPKT_ERR_RD(x) (((x) & (0x1 << 8)) >> 8)
+#define DWC_DOEPINT_B2B_PKTS_RD(x) (((x) & (0x1 << 6)) >> 6)
+#define DWC_DOEPINT_OUT_TKN_RD(x) (((x) & (0x1 << 4)) >> 4)
+#define DWC_DOEPINT_SETUP_DONE_RD(x) (((x) & (0x1 << 3)) >> 3)
+#define DWC_DOEPINT_AHB_ERROR_RD(x) (((x) & (0x1 << 2)) >> 2)
+#define DWC_DOEPINT_EP_DISA_RD(x) (((x) & (0x1 << 1)) >> 1)
+#define DWC_DOEPINT_TX_COMPL_RD(x) (((x) & (0x1 << 0)) >> 0)
+
+#define DWC_DOEPMSK_OUTPKT_ERR_RW(reg, x) \
+ (((reg) & (~((u32)0x01 << 8))) | ((x) << 8))
+#define DWC_DOEPMSK_B2B_PKTS_RW(reg, x) \
+ (((reg) & (~((u32)0x01 << 6))) | ((x) << 6))
+#define DWC_DOEPMSK_OUT_TKN_RW(reg, x) \
+ (((reg) & (~((u32)0x01 << 4))) | ((x) << 4))
+#define DWC_DOEPMSK_SETUP_DONE_RW(reg, x) \
+ (((reg) & (~((u32)0x01 << 3))) | ((x) << 3))
+#define DWC_DOEPMSK_AHB_ERROR_RW(reg, x) \
+ (((reg) & (~((u32)0x01 << 2))) | ((x) << 2))
+#define DWC_DOEPMSK_EP_DISA_RW(reg, x) \
+ (((reg) & (~((u32)0x01 << 1))) | ((x) << 1))
+#define DWC_DOEPMSK_TX_COMPL_RW(reg, x) \
+ (((reg) & (~((u32)0x01 << 0))) | ((x) << 0))
+
+/*
+ * These Macros represents the bit fields in the Device All EP Intr and Mask
+ * Registers. Read the register into the u32 member then set/clear the bits
+ * using the bit elements.
+ */
+#define DWC_DAINT_OUT_EP_RD(reg, ep) \
+ (((reg) & (1 << (ep + 16))) >> (ep + 16))
+#define DWC_DAINTMSK_OUT_EP_RW(reg, ep) \
+ (((reg) & (~(u32)(1 << (ep + 16)))) | (1 << (ep + 16)))
+#define DWC_DAINT_IN_EP_RD(reg, ep) (((reg) & (1 << ep)) >> ep)
+#define DWC_DAINTMSK_IN_EP_RW(reg, ep) \
+ (((reg) & (~(u32)(1 << ep))) | (1 << ep))
+#define DWC_DAINT_OUTEP15 (1 << 31)
+#define DWC_DAINT_OUTEP14 (1 << 30)
+#define DWC_DAINT_OUTEP13 (1 << 29)
+#define DWC_DAINT_OUTEP12 (1 << 28)
+#define DWC_DAINT_OUTEP11 (1 << 27)
+#define DWC_DAINT_OUTEP10 (1 << 26)
+#define DWC_DAINT_OUTEP09 (1 << 25)
+#define DWC_DAINT_OUTEP08 (1 << 24)
+#define DWC_DAINT_OUTEP07 (1 << 23)
+#define DWC_DAINT_OUTEP06 (1 << 22)
+#define DWC_DAINT_OUTEP05 (1 << 21)
+#define DWC_DAINT_OUTEP04 (1 << 20)
+#define DWC_DAINT_OUTEP03 (1 << 19)
+#define DWC_DAINT_OUTEP02 (1 << 18)
+#define DWC_DAINT_OUTEP01 (1 << 17)
+#define DWC_DAINT_OUTEP00 (1 << 16)
+#define DWC_DAINT_INEP15 (1 << 15)
+#define DWC_DAINT_INEP14 (1 << 14)
+#define DWC_DAINT_INEP13 (1 << 13)
+#define DWC_DAINT_INEP12 (1 << 12)
+#define DWC_DAINT_INEP11 (1 << 11)
+#define DWC_DAINT_INEP10 (1 << 10)
+#define DWC_DAINT_INEP09 (1 << 9)
+#define DWC_DAINT_INEP08 (1 << 8)
+#define DWC_DAINT_INEP07 (1 << 07)
+#define DWC_DAINT_INEP06 (1 << 06)
+#define DWC_DAINT_INEP05 (1 << 05)
+#define DWC_DAINT_INEP04 (1 << 04)
+#define DWC_DAINT_INEP03 (1 << 03)
+#define DWC_DAINT_INEP02 (1 << 02)
+#define DWC_DAINT_INEP01 (1 << 01)
+#define DWC_DAINT_INEP00 (1 << 00)
+
+/*
+ * These Macros represents the bit fields in the Device IN Token Queue Read
+ * Registers. Read the register into the u32 member. READ-ONLY Register
+ */
+#define DWC_DTKNQR1_EP_TKN_NO_RD(x) (((x) & (0xffffff << 8)) >> 8)
+#define DWC_DTKNQR1_WRAP_BIT_RD(x) (((x) & (1 << 7)) >> 7)
+#define DWC_DTKNQR1_INT_TKN_Q_WR_PTR_RD(x) ((x) & 0x1f)
+
+/*
+ * These Macros represents Threshold control Register. Read and wr the register
+ * into the u32 member. READ-WRITABLE Register
+ */
+#define DWC_DTHCTRL_RX_ARB_PARK_EN_RD(x) (((x) & (0x001 << 27)) >> 27)
+#define DWC_DTHCTRL_RX_THR_LEN_RD(x) (((x) & (0x1ff << 17)) >> 17)
+#define DWC_DTHCTRL_RX_THR_EN_RD(x) (((x) & (0x001 << 16)) >> 16)
+#define DWC_DTHCTRL_TX_THR_LEN_RD(x) (((x) & (0x1ff << 02)) >> 02)
+#define DWC_DTHCTRL_ISO_THR_EN(x) (((x) & (0x001 << 01)) >> 01)
+#define DWC_DTHCTRL_NON_ISO_THR_ENA_RD(x) (((x) & (0x001 << 00)) >> 00)
+
+#define DWC_DTHCTRL_RX_ARB_PARK_EN_RW(reg, x) \
+ (((reg) & (~((u32)0x001 << 27))) | ((x) << 27))
+#define DWC_DTHCTRL_RX_THR_LEN_RW(reg, x) \
+ (((reg) & (~((u32)0x1ff << 17))) | ((x) << 17))
+#define DWC_DTHCTRL_RX_THR_EN_RW(reg, x) \
+ (((reg) & (~((u32)0x001 << 16))) | ((x) << 16))
+#define DWC_DTHCTRL_TX_THR_LEN_RW(reg, x) \
+ (((reg) & (~((u32)0x1ff << 02))) | ((x) << 02))
+#define DWC_DTHCTRL_ISO_THR_EN_RW(reg, x) \
+ (((reg) & (~((u32)0x001 << 01))) | ((x) << 01))
+#define DWC_DTHCTRL_NON_ISO_THR_ENA_RW(reg, x) \
+ (((reg) & (~((u32)0x001 << 00))) | ((x) << 00))
+
+/*
+ * Device Logical IN Endpoint-Specific Registers. Offsets 900h-AFCh
+ *
+ * There will be one set of endpoint registers per logical endpoint implemented.
+ *
+ * These registers are visible only in Device mode and must not be accessed in
+ * Host mode, as the results are unknown.
+ */
+#define DWC_DIEPCTL 0x00
+#define DWC_DIEPINT 0x08
+#define DWC_DIEPTSIZ 0x10
+#define DWC_DIEPDMA 0x14
+#define DWC_DTXFSTS 0x18
+
+/*
+ * Device Logical OUT Endpoint-Specific Registers. Offsets: B00h-CFCh
+ *
+ * There will be one set of endpoint registers per logical endpoint implemented.
+ *
+ * These registers are visible only in Device mode and must not be accessed in
+ * Host mode, as the results are unknown.
+ */
+#define DWC_DOEPCTL 0x00
+#define DWC_DOEPFN 0x04
+#define DWC_DOEPINT 0x08
+#define DWC_DOEPTSIZ 0x10
+#define DWC_DOEPDMA 0x14
+
+/*
+ * These Macros represents the bit fields in the Device EP Ctrl Register. Read
+ * the register into the u32 member then set/clear the bits using the bit
+ * elements.
+ */
+#define DWC_DEP0CTL_MPS_64 0
+#define DWC_DEP0CTL_MPS_32 1
+#define DWC_DEP0CTL_MPS_16 2
+#define DWC_DEP0CTL_MPS_8 3
+
+#define DWC_DEPCTL_EPENA_RD(x) (((x) & (0x1 << 31)) >> 31)
+#define DWC_DEPCTL_EPDIS_RD(x) (((x) & (0x1 << 30)) >> 30)
+#define DWC_DEPCTL_SET_DATA1_PID_RD(x) (((x) & (0x1 << 29)) >> 29)
+#define DWC_DEPCTL_SET_DATA0_PID_RD(x) (((x) & (0x1 << 28)) >> 28)
+#define DWC_DEPCTL_SET_NAK_RD(x) (((x) & (0x1 << 27)) >> 27)
+#define DWC_DEPCTL_CLR_NAK_RD(x) (((x) & (0x1 << 26)) >> 26)
+#define DWC_DEPCTL_TX_FIFO_NUM_RD(x) (((x) & (0xf << 22)) >> 22)
+#define DWC_DEPCTL_STALL_HNDSHK _RD(x) (((x) & (0x1 << 21)) >> 21)
+#define DWC_DEPCTL_SNP_MODE_RD(x) (((x) & (0x1 << 20)) >> 20)
+#define DWC_DEPCTL_EP_TYPE_RD(x) (((x) & (0x3 << 18)) >> 18)
+#define DWC_DEPCTL_NKASTS_RD(x) (((x) & (0x1 << 17)) >> 17)
+#define DWC_DEPCTL_DPID _RD(x) (((x) & (0x1 << 16)) >> 16)
+#define DWC_DEPCTL_ACT_EP_RD(x) (((x) & (0x1 << 15)) >> 15)
+#define DWC_DEPCTL_NXT_EP_RD(x) (((x) & (0xf << 11)) >> 11)
+#define DWC_DEPCTL_MPS_RD(x) (((x) & (0x7ff << 00)) >> 00)
+
+#define DWC_DEPCTL_EPENA_RW(reg, x) \
+ (((reg) & (~((u32)0x001 << 31))) | ((x) << 31))
+#define DWC_DEPCTL_EPDIS_RW(reg, x) \
+ (((reg) & (~((u32)0x001 << 30))) | ((x) << 30))
+#define DWC_DEPCTL_SET_DATA1_PID_RW(reg, x) \
+ (((reg) & (~((u32)0x001 << 29))) | ((x) << 29))
+#define DWC_DEPCTL_SET_DATA0_PID_RW(reg, x) \
+ (((reg) & (~((u32)0x001 << 28))) | ((x) << 28))
+#define DWC_DEPCTL_SET_NAK_RW(reg, x) \
+ (((reg) & (~((u32)0x001 << 27))) | ((x) << 27))
+#define DWC_DEPCTL_CLR_NAK_RW(reg, x) \
+ (((reg) & (~((u32)0x001 << 26))) | ((x) << 26))
+#define DWC_DEPCTL_TX_FIFO_NUM_RW(reg, x) \
+ (((reg) & (~((u32)0x00f << 22))) | ((x) << 22))
+#define DWC_DEPCTL_STALL_HNDSHK_RW(reg, x) \
+ (((reg) & (~((u32)0x001 << 21))) | ((x) << 21))
+#define DWC_DEPCTL_SNP_MODE_RW(reg, x) \
+ (((reg) & (~((u32)0x001 << 20))) | ((x) << 20))
+#define DWC_DEPCTL_EP_TYPE_RW(reg, x) \
+ (((reg) & (~((u32)0x003 << 18))) | ((x) << 18))
+#define DWC_DEPCTL_NKASTS_RW(reg, x) \
+ (((reg) & (~((u32)0x001 << 17))) | ((x) << 17))
+#define DWC_DEPCTL_DPID_RW(reg, x) \
+ (((reg) & (~((u32)0x001 << 16))) | ((x) << 16))
+#define DWC_DEPCTL_ACT_EP_RW(reg, x) \
+ (((reg) & (~((u32)0x001 << 15))) | ((x) << 15))
+#define DWC_DEPCTL_NXT_EP_RW(reg, x) \
+ (((reg) & (~((u32)0x00f << 11))) | ((x) << 11))
+#define DWC_DEPCTL_MPS_RW(reg, x) \
+ (((reg) & (~((u32)0x7ff << 00))) | ((x) << 00))
+
+/*
+ * These Macros represents the bit fields in the Device EP Txfer Size Register.
+ * Read the register into the u32 member then set/clear the bits using the bit
+ * elements.
+ */
+#if defined(DWC_LIMITED_XFER_SIZE)
+#define DWC_DEPTSIZ_MCOUNT_RD(x) (((x) & (0x003 << 29)) >> 29)
+#define DWC_DEPTSIZ_PKT_CNT_RD(x) (((x) & (0x01f << 19)) >> 19)
+#define DWC_DEPTSIZ_XFER_SIZ_RD(x) (((x) & (0x7ff << 00)) >> 00)
+#define DWC_DEPTSIZ_MCOUNT_RW(reg, x) \
+ (((reg) & (~((u32)0x003 << 29))) | ((x) << 29))
+#define DWC_DEPTSIZ_PKT_CNT_RW(reg, x) \
+ (((reg) & (~((u32)0x01f << 19))) | ((x) << 19))
+#define DWC_DEPTSIZ_XFER_SIZ_RW(reg, x) \
+ (((reg) & (~((u32)0x7ff << 00))) | ((x) << 00))
+#else
+#define DWC_DEPTSIZ_MCOUNT_RD(x) \
+ (((x) & (0x003 << 29)) >> 29)
+#define DWC_DEPTSIZ_PKT_CNT_RD(x) \
+ (((x) & (0x3ff << 19)) >> 19)
+#define DWC_DEPTSIZ_XFER_SIZ_RD(x) \
+ (((x) & (0x7ffff << 00)) >> 00)
+#define DWC_DEPTSIZ_MCOUNT_RW(reg, x) \
+ (((reg) & (~((u32)0x003 << 29))) | ((x) << 29))
+#define DWC_DEPTSIZ_PKT_CNT_RW(reg, x) \
+ (((reg) & (~((u32)0x7ff << 19))) | ((x) << 19))
+#define DWC_DEPTSIZ_XFER_SIZ_RW(reg, x) \
+ (((reg) & (~((u32)0x7ffff << 00))) | ((x) << 00))
+#endif
+
+/*
+ * These Macros represents the bit fields in the Device EP 0 Transfer Size
+ * Register. Read the register into the u32 member then set/clear the bits
+ * using the bit elements.
+ */
+#define DWC_DEPTSIZ0_SUPCNT_RD(x) (((x) & (0x003 << 29)) >> 29)
+#define DWC_DEPTSIZ0_PKT_CNT_RD(x) (((x) & (0x001 << 19)) >> 19)
+#define DWC_DEPTSIZ0_XFER_SIZ_RD(x) (((x) & (0x07f << 00)) >> 00)
+#define DWC_DEPTSIZ0_SUPCNT_RW(reg, x) \
+ (((reg) & (~((u32)0x003 << 29))) | ((x) << 29))
+#define DWC_DEPTSIZ0_PKT_CNT_RW(reg, x) \
+ (((reg) & (~((u32)0x001 << 19))) | ((x) << 19))
+#define DWC_DEPTSIZ0_XFER_SIZ_RW(reg, x) \
+ (((reg) & (~((u32)0x07f << 00))) | ((x) << 00))
+
+#define MAX_PERIO_FIFOS 15 /* Max periodic FIFOs */
+#define MAX_TX_FIFOS 15 /* Max non-periodic FIFOs */
+
+/* Maximum number of Endpoints/HostChannels */
+#define MAX_EPS_CHANNELS 12 /* This come from device tree or defconfig */
+
+/*
+ * The device_if structure contains information needed to manage the DWC_otg
+ * controller acting in device mode. It represents the programming view of the
+ * device-specific aspects of the controller.
+ */
+struct device_if {
+ /* Device Global Registers starting at offset 800h */
+ ulong dev_global_regs;
+#define DWC_DEV_GLOBAL_REG_OFFSET 0x800
+
+ /* Device Logical IN Endpoint-Specific Registers 900h-AFCh */
+ ulong in_ep_regs[MAX_EPS_CHANNELS];
+#define DWC_DEV_IN_EP_REG_OFFSET 0x900
+#define DWC_EP_REG_OFFSET 0x20
+
+ /* Device Logical OUT Endpoint-Specific Registers B00h-CFCh */
+ ulong out_ep_regs[MAX_EPS_CHANNELS];
+#define DWC_DEV_OUT_EP_REG_OFFSET 0xB00
+
+ /* Device configuration information */
+ /* Device Speed 0: Unknown, 1: LS, 2:FS, 3: HS */
+ u8 speed;
+ /* Number # of Tx EP range: 0-15 exept ep0 */
+ u8 num_in_eps;
+ /* Number # of Rx EP range: 0-15 exept ep 0 */
+ u8 num_out_eps;
+
+ /* Size of periodic FIFOs (Bytes) */
+ u16 perio_tx_fifo_size[MAX_PERIO_FIFOS];
+
+ /* Size of Tx FIFOs (Bytes) */
+ u16 tx_fifo_size[MAX_TX_FIFOS];
+
+ /* Thresholding enable flags and length varaiables */
+ u16 rx_thr_en;
+ u16 iso_tx_thr_en;
+ u16 non_iso_tx_thr_en;
+ u16 rx_thr_length;
+ u16 tx_thr_length;
+};
+
+/*
+ * These Macros represents the bit fields in the Power and Clock Gating Control
+ * Register. Read the register into the u32 member then set/clear the
+ * bits using the bit elements.
+ */
+#define DWC_PCGCCTL_PHY_SUS_RD(x) (((x) & (0x001 << 4)) >> 4)
+#define DWC_PCGCCTL_RSTP_DWN_RD(x) (((x) & (0x001 << 3)) >> 3)
+#define DWC_PCGCCTL_PWR_CLAMP_RD(x) (((x) & (0x001 << 2)) >> 2)
+#define DWC_PCGCCTL_GATE_HCLK_RD(x) (((x) & (0x001 << 1)) >> 1)
+#define DWC_PCGCCTL_STOP_CLK_RD(x) (((x) & (0x001 << 0)) >> 0)
+
+#define DWC_PCGCCTL_RSTP_DWN_RW(reg, x) \
+ (((reg) & (~((u32)0x001 << 3))) | ((x) << 3))
+#define DWC_PCGCCTL_PWR_CLAMP_RW(reg, x) \
+ (((reg) & (~((u32)0x001 << 2))) | ((x) << 2))
+#define DWC_PCGCCTL_GATE_HCLK_RW(reg, x) \
+ (((reg) & (~((u32)0x001 << 1))) | ((x) << 1))
+#define DWC_PCGCCTL_STOP_CLK_SET(reg) \
+ (((reg) | 1))
+#define DWC_PCGCCTL_STOP_CLK_CLR(reg) \
+ (((reg) & (~((u32)0x001 << 0))))
+
+/*
+ * Host Mode Register Structures
+ */
+
+/*
+ * The Host Global Registers structure defines the size and relative field
+ * offsets for the Host Mode Global Registers. Host Global Registers offsets
+ * 400h-7FFh.
+*/
+#define DWC_HCFG 0x00
+#define DWC_HFIR 0x04
+#define DWC_HFNUM 0x08
+#define DWC_HPTXSTS 0x10
+#define DWC_HAINT 0x14
+#define DWC_HAINTMSK 0x18
+
+/*
+ * These Macros represents the bit fields in the Host Configuration Register.
+ * Read the register into the u32 member then set/clear the bits using the bit
+ * elements. Write the u32 member to the hcfg register.
+ */
+#define DWC_HCFG_FSLSUPP_RD(x) (((x) & (0x001 << 2)) >> 2)
+#define DWC_HCFG_FSLSP_CLK_RD(x) (((x) & (0x003 << 0)) >> 0)
+#define DWC_HCFG_FSLSUPP_RW(reg, x) \
+ (((reg) & (~((u32)0x001 << 2))) | ((x) << 2))
+#define DWC_HCFG_FSLSP_CLK_RW(reg, x) \
+ (((reg) & (~((u32)0x003 << 0))) | ((x) << 0))
+
+#define DWC_HCFG_30_60_MHZ 0
+#define DWC_HCFG_48_MHZ 1
+#define DWC_HCFG_6_MHZ 2
+
+/*
+ * These Macros represents the bit fields in the Host Frame Remaing/Number
+ * Register.
+ */
+#define DWC_HFIR_FRINT_RD(x) (((x) & (0xffff << 0)) >> 0)
+#define DWC_HFIR_FRINT_RW(reg, x) \
+ (((reg) & (~((u32)0xffff << 0))) | ((x) << 0))
+
+/*
+ * These Macros represents the bit fields in the Host Frame Remaing/Number
+ * Register.
+ */
+#define DWC_HFNUM_FRREM_RD(x) (((x) & (0xffff << 16)) >> 16)
+#define DWC_HFNUM_FRNUM_RD(x) (((x) & (0xffff << 0)) >> 0)
+#define DWC_HFNUM_FRREM_RW(reg, x) \
+ (((reg) & (~((u32)0xffff << 16))) | ((x) << 16))
+#define DWC_HFNUM_FRNUM_RW(reg, x) \
+ (((reg) & (~((u32)0xffff << 0))) | ((x) << 0))
+#define DWC_HFNUM_MAX_FRNUM 0x3FFF
+#define DWC_HFNUM_MAX_FRNUM 0x3FFF
+
+#define DWC_HPTXSTS_PTXQTOP_ODD_RD(x) (((x) & (0x01 << 31)) >> 31)
+#define DWC_HPTXSTS_PTXQTOP_CHNUM_RD(x) (((x) & (0x0f << 27)) >> 27)
+#define DWC_HPTXSTS_PTXQTOP_TKN_RD(x) (((x) & (0x03 << 25)) >> 25)
+#define DWC_HPTXSTS_PTXQTOP_TERM_RD(x) (((x) & (0x01 << 24)) >> 24)
+#define DWC_HPTXSTS_PTXSPC_AVAIL_RD(x) (((x) & (0xff << 16)) >> 16)
+#define DWC_HPTXSTS_PTXFSPC_AVAIL_RD(x) (((x) & (0xffff << 00)) >> 00)
+
+/*
+ * These Macros represents the bit fields in the Host Port Control and Status
+ * Register. Read the register into the u32 member then set/clear the bits using
+ * the bit elements. Write the u32 member to the hprt0 register.
+ */
+#define DWC_HPRT0_PRT_SPD_RD(x) (((x) & (0x3 << 17)) >> 17)
+#define DWC_HPRT0_PRT_TST_CTL_RD(x) (((x) & (0xf << 13)) >> 13)
+#define DWC_HPRT0_PRT_PWR_RD(x) (((x) & (0x1 << 12)) >> 12)
+#define DWC_HPRT0_PRT_LSTS_RD(x) (((x) & (0x3 << 10)) >> 10)
+#define DWC_HPRT0_PRT_RST_RD(x) (((x) & (0x1 << 8)) >> 8)
+#define DWC_HPRT0_PRT_SUS_RD(x) (((x) & (0x1 << 7)) >> 7)
+#define DWC_HPRT0_PRT_RES_RD(x) (((x) & (0x1 << 6)) >> 6)
+#define DWC_HPRT0_PRT_OVRCURR_CHG_RD(x) (((x) & (0x1 << 5)) >> 5)
+#define DWC_HPRT0_PRT_OVRCURR_ACT_RD(x) (((x) & (0x1 << 4)) >> 4)
+#define DWC_HPRT0_PRT_ENA_DIS_CHG_RD(x) (((x) & (0x1 << 3)) >> 3)
+#define DWC_HPRT0_PRT_ENA_RD(x) (((x) & (0x1 << 2)) >> 2)
+#define DWC_HPRT0_PRT_CONN_DET_RD(x) (((x) & (0x1 << 1)) >> 1)
+#define DWC_HPRT0_PRT_STS_RD(x) (((x) & (0x1 << 0)) >> 0)
+
+#define DWC_HPRT0_PRT_SPD_RW(reg, x) \
+ (((reg) & (~((u32)0x3 << 17))) | ((x) << 17))
+#define DWC_HPRT0_PRT_TST_CTL_RW(reg, x) \
+ (((reg) & (~((u32)0xf << 13))) | ((x) << 13))
+#define DWC_HPRT0_PRT_PWR_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 12))) | ((x) << 12))
+#define DWC_HPRT0_PRT_LSTS_RW(reg, x) \
+ (((reg) & (~((u32)0x3 << 10))) | ((x) << 10))
+#define DWC_HPRT0_PRT_RST_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 8))) | ((x) << 8))
+#define DWC_HPRT0_PRT_SUS_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 7))) | ((x) << 7))
+#define DWC_HPRT0_PRT_RES_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 6))) | ((x) << 6))
+#define DWC_HPRT0_PRT_OVRCURR_CHG_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 5))) | ((x) << 5))
+#define DWC_HPRT0_PRT_OVRCURR_ACT_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 4))) | ((x) << 4))
+#define DWC_HPRT0_PRT_ENA_DIS_CHG_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 3))) | ((x) << 3))
+#define DWC_HPRT0_PRT_ENA_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 2))) | ((x) << 2))
+#define DWC_HPRT0_PRT_CONN_DET_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 1))) | ((x) << 1))
+#define DWC_HPRT0_PRT_STS_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 0))) | ((x) << 0))
+
+#define DWC_HPRT0_PRTSPD_HIGH_SPEED 0
+#define DWC_HPRT0_PRTSPD_FULL_SPEED 1
+#define DWC_HPRT0_PRTSPD_LOW_SPEED 2
+
+/*
+ * These Macros represents the bit fields in the Host All Interrupt Register.
+ */
+#define DWC_HAINT_CH15_RD(x) (((x) & (0x1 << 15)) >> 15)
+#define DWC_HAINT_CH14_RD(x) (((x) & (0x1 << 14)) >> 14)
+#define DWC_HAINT_CH13_RD(x) (((x) & (0x1 << 13)) >> 13)
+#define DWC_HAINT_CH12_RD(x) (((x) & (0x1 << 12)) >> 12)
+#define DWC_HAINT_CH11_RD(x) (((x) & (0x1 << 11)) >> 11)
+#define DWC_HAINT_CH10_RD(x) (((x) & (0x1 << 10)) >> 10)
+#define DWC_HAINT_CH09_RD(x) (((x) & (0x1 << 9)) >> 9)
+#define DWC_HAINT_CH08_RD(x) (((x) & (0x1 << 8)) >> 8)
+#define DWC_HAINT_CH07_RD(x) (((x) & (0x1 << 7)) >> 7)
+#define DWC_HAINT_CH06_RD(x) (((x) & (0x1 << 6)) >> 6)
+#define DWC_HAINT_CH05_RD(x) (((x) & (0x1 << 5)) >> 5)
+#define DWC_HAINT_CH04_RD(x) (((x) & (0x1 << 4)) >> 4)
+#define DWC_HAINT_CH03_RD(x) (((x) & (0x1 << 3)) >> 3)
+#define DWC_HAINT_CH02_RD(x) (((x) & (0x1 << 2)) >> 2)
+#define DWC_HAINT_CH01_RD(x) (((x) & (0x1 << 1)) >> 1)
+#define DWC_HAINT_CH00_RD(x) (((x) & (0x1 << 0)) >> 0)
+
+#define DWC_HAINT_RD(x) (((x) & (0xffff << 0)) >> 0)
+
+/*
+ * These Macros represents the bit fields in the Host All Interrupt Register.
+ */
+#define DWC_HAINTMSK_CH15_RD(x) (((x) & (0x1 << 15)) >> 15)
+#define DWC_HAINTMSK_CH14_RD(x) (((x) & (0x1 << 14)) >> 14)
+#define DWC_HAINTMSK_CH13_RD(x) (((x) & (0x1 << 13)) >> 13)
+#define DWC_HAINTMSK_CH12_RD(x) (((x) & (0x1 << 12)) >> 12)
+#define DWC_HAINTMSK_CH11_RD(x) (((x) & (0x1 << 11)) >> 11)
+#define DWC_HAINTMSK_CH10_RD(x) (((x) & (0x1 << 10)) >> 10)
+#define DWC_HAINTMSK_CH09_RD(x) (((x) & (0x1 << 9)) >> 9)
+#define DWC_HAINTMSK_CH08_RD(x) (((x) & (0x1 << 8)) >> 8)
+#define DWC_HAINTMSK_CH07_RD(x) (((x) & (0x1 << 7)) >> 7)
+#define DWC_HAINTMSK_CH06_RD(x) (((x) & (0x1 << 6)) >> 6)
+#define DWC_HAINTMSK_CH05_RD(x) (((x) & (0x1 << 5)) >> 5)
+#define DWC_HAINTMSK_CH04_RD(x) (((x) & (0x1 << 4)) >> 4)
+#define DWC_HAINTMSK_CH03_RD(x) (((x) & (0x1 << 3)) >> 3)
+#define DWC_HAINTMSK_CH02_RD(x) (((x) & (0x1 << 2)) >> 2)
+#define DWC_HAINTMSK_CH01_RD(x) (((x) & (0x1 << 1)) >> 1)
+#define DWC_HAINTMSK_CH00_RD(x) (((x) & (0x1 << 0)) >> 0)
+#define DWC_HAINTMSK_RD(x) ((x) & 0xffff)
+
+#define DWC_HAINTMSK_CH15_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 15))) | ((x) << 15))
+#define DWC_HAINTMSK_CH14_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 14))) | ((x) << 14))
+#define DWC_HAINTMSK_CH13_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 13))) | ((x) << 13))
+#define DWC_HAINTMSK_CH12_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 12))) | ((x) << 12))
+#define DWC_HAINTMSK_CH11_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 11))) | ((x) << 11))
+#define DWC_HAINTMSK_CH10_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 10))) | ((x) << 10))
+#define DWC_HAINTMSK_CH09_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 9))) | ((x) << 9))
+#define DWC_HAINTMSK_CH08_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 8))) | ((x) << 8))
+#define DWC_HAINTMSK_CH07_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 7))) | ((x) << 7))
+#define DWC_HAINTMSK_CH06_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 6))) | ((x) << 6))
+#define DWC_HAINTMSK_CH05_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 5))) | ((x) << 5))
+#define DWC_HAINTMSK_CH04_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 4))) | ((x) << 4))
+#define DWC_HAINTMSK_CH03_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 3))) | ((x) << 3))
+#define DWC_HAINTMSK_CH02_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 2))) | ((x) << 2))
+#define DWC_HAINTMSK_CH01_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 1))) | ((x) << 1))
+#define DWC_HAINTMSK_CH00_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 0))) | ((x) << 0))
+#define DWC_HAINTMSK_RW(reg, x) \
+ (((reg) & (~((u32)0xffff))) | x)
+
+/*
+ * Host Channel Specific Registers. 500h-5FCh
+ */
+#define DWC_HCCHAR 0x00
+#define DWC_HCSPLT 0x04
+#define DWC_HCINT 0x08
+#define DWC_HCINTMSK 0x0C
+#define DWC_HCTSIZ 0x10
+#define DWC_HCDMA 0x14
+
+/*
+ * These Macros represents the bit fields in the Host Channel Characteristics
+ * Register. Read the register into the u32 member then set/clear the bits using
+ * the bit elements. Write the u32 member to the hcchar register.
+ */
+#define DWC_HCCHAR_ENA_RD(x) (((x) & (0x001 << 31)) >> 31)
+#define DWC_HCCHAR_DIS_RD(x) (((x) & (0x001 << 30)) >> 30)
+#define DWC_HCCHAR_ODD_FRAME_RD(x) (((x) & (0x001 << 29)) >> 29)
+#define DWC_HCCHAR_DEV_ADDR_RD(x) (((x) & (0x07f << 22)) >> 22)
+#define DWC_HCCHAR_MULTI_CNT_RD(x) (((x) & (0x003 << 20)) >> 20)
+#define DWC_HCCHAR_EPTYPE_RD(x) (((x) & (0x003 << 18)) >> 18)
+#define DWC_HCCHAR_LSP_DEV_RD(x) (((x) & (0x001 << 17)) >> 17)
+#define DWC_HCCHAR_EPDIR_RD(x) (((x) & (0x001 << 15)) >> 15)
+#define DWC_HCCHAR_EP_NUM_RD(x) (((x) & (0x00f << 11)) >> 11)
+#define DWC_HCCHAR_MPS_RD(x) (((x) & (0x7ff << 0)) >> 0)
+
+#define DWC_HCCHAR_ENA_RW(reg, x) \
+ (((reg) & (~((u32)0x001 << 31))) | ((x) << 31))
+#define DWC_HCCHAR_DIS_RW(reg, x) \
+ (((reg) & (~((u32)0x001 << 30))) | ((x) << 30))
+#define DWC_HCCHAR_ODD_FRAME_RW(reg, x) \
+ (((reg) & (~((u32)0x001 << 29))) | ((x) << 29))
+#define DWC_HCCHAR_DEV_ADDR_RW(reg, x) \
+ (((reg) & (~((u32)0x07f << 22))) | ((x) << 22))
+#define DWC_HCCHAR_MULTI_CNT_RW(reg, x) \
+ (((reg) & (~((u32)0x003 << 20))) | ((x) << 20))
+#define DWC_HCCHAR_EPTYPE_RW(reg, x) \
+ (((reg) & (~((u32)0x003 << 18))) | ((x) << 18))
+#define DWC_HCCHAR_LSP_DEV_RW(reg, x) \
+ (((reg) & (~((u32)0x001 << 17))) | ((x) << 17))
+#define DWC_HCCHAR_EPDIR_RW(reg, x) \
+ (((reg) & (~((u32)0x001 << 15))) | ((x) << 15))
+#define DWC_HCCHAR_EP_NUM_RW(reg, x) \
+ (((reg) & (~((u32)0x00f << 11))) | ((x) << 11))
+#define DWC_HCCHAR_MPS_RW(reg, x) \
+ (((reg) & (~((u32)0x7ff << 0))) | ((x) << 0))
+
+#define DWC_HCSPLT_ENA_RD(x) (((x) & (0x01 << 31)) >> 31)
+#define DWC_HCSPLT_COMP_SPLT_RD(x) (((x) & (0x01 << 16)) >> 16)
+#define DWC_HCSPLT_TRANS_POS_RD(x) (((x) & (0x03 << 14)) >> 14)
+#define DWC_HCSPLT_HUB_ADDR_RD(x) (((x) & (0x7f << 7)) >> 7)
+#define DWC_HCSPLT_PRT_ADDR_RD(x) (((x) & (0x7f << 0)) >> 0)
+
+#define DWC_HCSPLT_ENA_RW(reg, x) \
+ (((reg) & (~((u32)0x01 << 31))) | ((x) << 31))
+#define DWC_HCSPLT_COMP_SPLT_RW(reg, x) \
+ (((reg) & (~((u32)0x01 << 16))) | ((x) << 16))
+#define DWC_HCSPLT_TRANS_POS_RW(reg, x) \
+ (((reg) & (~((u32)0x03 << 14))) | ((x) << 14))
+#define DWC_HCSPLT_HUB_ADDR_RW(reg, x) \
+ (((reg) & (~((u32)0x7f << 7))) | ((x) << 7))
+#define DWC_HCSPLT_PRT_ADDR_RW(reg, x) \
+ (((reg) & (~((u32)0x7f << 0))) | ((x) << 0))
+
+#define DWC_HCSPLIT_XACTPOS_MID 0
+#define DWC_HCSPLIT_XACTPOS_END 1
+#define DWC_HCSPLIT_XACTPOS_BEGIN 2
+#define DWC_HCSPLIT_XACTPOS_ALL 3
+
+/*
+ * These Macros represents the bit fields in the Host All Interrupt
+ * Register.
+ */
+#define DWC_HCINT_DATA_TOG_ERR_RD(x) (((x) & (0x1 << 10)) >> 10)
+#define DWC_HCINT_FRAME_OVERN_ERR_RD(x) (((x) & (0x1 << 9)) >> 9)
+#define DWC_HCINT_BBL_ERR_RD(x) (((x) & (0x1 << 8)) >> 8)
+#define DWC_HCINT_TRANS_ERR_RD(x) (((x) & (0x1 << 7)) >> 7)
+#define DWC_HCINT_NYET_RESP_REC_RD(x) (((x) & (0x1 << 6)) >> 6)
+#define DWC_HCINT_ACK_RESP_REC_RD(x) (((x) & (0x1 << 5)) >> 5)
+#define DWC_HCINT_NAK_RESP_REC_RD(x) (((x) & (0x1 << 4)) >> 4)
+#define DWC_HCINT_STALL_RESP_REC_RD(x) (((x) & (0x1 << 3)) >> 3)
+#define DWC_HCINT_AHB_ERR_RD(x) (((x) & (0x1 << 2)) >> 2)
+#define DWC_HCINT_CHAN_HALTED_RD(x) (((x) & (0x1 << 1)) >> 1)
+#define DWC_HCINT_TXFER_CMPL_RD(x) (((x) & (0x1 << 0)) >> 0)
+
+#define DWC_HCINT_DATA_TOG_ERR_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 10))) | ((x) << 10))
+#define DWC_HCINT_FRAME_OVERN_ERR_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 9))) | ((x) << 9))
+#define DWC_HCINT_BBL_ERR_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 8))) | ((x) << 8))
+#define DWC_HCINT_TRANS_ERR_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 7))) | ((x) << 7))
+#define DWC_HCINT_NYET_RESP_REC_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 6))) | ((x) << 6))
+#define DWC_HCINT_ACK_RESP_REC_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 5))) | ((x) << 5))
+#define DWC_HCINT_NAK_RESP_REC_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 4))) | ((x) << 4))
+#define DWC_HCINT_STALL_RESP_REC_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 3))) | ((x) << 3))
+#define DWC_HCINT_AHB_ERR_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 2))) | ((x) << 2))
+#define DWC_HCINT_CHAN_HALTED_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 1))) | ((x) << 1))
+#define DWC_HCINT_TXFER_CMPL_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 0))) | ((x) << 0))
+
+/*
+ * These Macros represents the bit fields in the Host Channel Transfer Size
+ * Register. Read the register into the u32 member then set/clear the bits
+ * using the bit elements. Write the u32 member to the hcchar register.
+ */
+#define DWC_HCTSIZ_DO_PING_PROTO_RD(x) (((x) & (0x00001 << 31)) >> 31)
+#define DWC_HCTSIZ_PKT_PID_RD(x) (((x) & (0x00003 << 29)) >> 29)
+#define DWC_HCTSIZ_PKT_CNT_RD(x) (((x) & (0x003ff << 19)) >> 19)
+#define DWC_HCTSIZ_XFER_SIZE_RD(x) (((x) & (0x7ffff << 00)) >> 00)
+
+#define DWC_HCTSIZ_DO_PING_PROTO_RW(reg, x) \
+ (((reg) & (~((u32)0x00001 << 31))) | ((x) << 31))
+#define DWC_HCTSIZ_PKT_PID_RW(reg, x) \
+ (((reg) & (~((u32)0x00003 << 29))) | ((x) << 29))
+#define DWC_HCTSIZ_PKT_CNT_RW(reg, x) \
+ (((reg) & (~((u32)0x003ff << 19))) | ((x) << 19))
+#define DWC_HCTSIZ_XFER_SIZE_RW(reg, x) \
+ (((reg) & (~((u32)0x7ffff << 00))) | ((x) << 00))
+
+#define DWC_HCTSIZ_DATA0 0
+#define DWC_HCTSIZ_DATA1 2
+#define DWC_HCTSIZ_DATA2 1
+#define DWC_HCTSIZ_MDATA 3
+#define DWC_HCTSIZ_SETUP 3
+
+/*
+ * These Macros represents the bit fields in the Host Channel Interrupt Mask
+ * Register. Read the register into the u32 member then set/clear the bits using
+ * the bit elements. Write the u32 member to the hcintmsk register.
+ */
+#define DWC_HCINTMSK_DATA_TOG_ERR_RD(x) (((x) & (0x1 << 10)) >> 10)
+#define DWC_HCINTMSK_FRAME_OVERN_ERR_RD(x) (((x) & (0x1 << 9)) >> 9)
+#define DWC_HCINTMSK_BBL_ERR_RD(x) (((x) & (0x1 << 8)) >> 8)
+#define DWC_HCINTMSK_TRANS_ERR_RD(x) (((x) & (0x1 << 7)) >> 7)
+#define DWC_HCINTMSK_NYET_RESP_REC_RD(x) (((x) & (0x1 << 6)) >> 6)
+#define DWC_HCINTMSK_ACK_RESP_REC_RD(x) (((x) & (0x1 << 5)) >> 5)
+#define DWC_HCINTMSK_NAK_RESP_REC_RD(x) (((x) & (0x1 << 4)) >> 4)
+#define DWC_HCINTMSK_STALL_RESP_REC_RD(x) (((x) & (0x1 << 3)) >> 3)
+#define DWC_HCINTMSK_AHB_ERR_RD(x) (((x) & (0x1 << 2)) >> 2)
+#define DWC_HCINTMSK_CHAN_HALTED_RD(x) (((x) & (0x1 << 1)) >> 1)
+#define DWC_HCINTMSK_TXFER_CMPL_RD(x) (((x) & (0x1 << 0)) >> 0)
+
+#define DWC_HCINTMSK_DATA_TOG_ERR_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 10))) | ((x) << 10))
+#define DWC_HCINTMSK_FRAME_OVERN_ERR_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 9))) | ((x) << 9))
+#define DWC_HCINTMSK_BBL_ERR_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 8))) | ((x) << 8))
+#define DWC_HCINTMSK_TRANS_ERR_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 7))) | ((x) << 7))
+#define DWC_HCINTMSK_NYET_RESP_REC_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 6))) | ((x) << 6))
+#define DWC_HCINTMSK_ACK_RESP_REC_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 5))) | ((x) << 5))
+#define DWC_HCINTMSK_NAK_RESP_REC_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 4))) | ((x) << 4))
+#define DWC_HCINTMSK_STALL_RESP_REC_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 3))) | ((x) << 3))
+#define DWC_HCINTMSK_AHB_ERR_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 2))) | ((x) << 2))
+#define DWC_HCINTMSK_CHAN_HALTED_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 1))) | ((x) << 1))
+#define DWC_HCINTMSK_TXFER_CMPL_RW(reg, x) \
+ (((reg) & (~((u32)0x1 << 0))) | ((x) << 0))
+
+/*
+ * OTG Host Interface Structure.
+ *
+ * The OTG Host Interface Structure structure contains information needed to
+ * manage the DWC_otg controller acting in host mode. It represents the
+ * programming view of the host-specific aspects of the controller.
+ */
+struct dwc_host_if { /* CONFIG_DWC_OTG_REG_LE */
+ /* Host Global Registers starting at offset 400h. */
+ ulong host_global_regs;
+#define DWC_OTG_HOST_GLOBAL_REG_OFFSET 0x400
+
+ /* Host Port 0 Control and Status Register */
+ ulong hprt0;
+#define DWC_OTG_HOST_PORT_REGS_OFFSET 0x440
+
+ /* Host Channel Specific Registers at offsets 500h-5FCh. */
+ ulong hc_regs[MAX_EPS_CHANNELS];
+#define DWC_OTG_HOST_CHAN_REGS_OFFSET 0x500
+#define DWC_OTG_CHAN_REGS_OFFSET 0x20
+
+ /* Host configuration information */
+ /* Number of Host Channels (range: 1-16) */
+ u8 num_host_channels;
+ /* Periodic EPs supported (0: no, 1: yes) */
+ u8 perio_eps_supported;
+ /* Periodic Tx FIFO Size (Only 1 host periodic Tx FIFO) */
+ u16 perio_tx_fifo_size;
+};
+#endif
diff --git a/drivers/usb/early/ehci-dbgp.c b/drivers/usb/early/ehci-dbgp.c
index 1fc8f12..347bb05 100644
--- a/drivers/usb/early/ehci-dbgp.c
+++ b/drivers/usb/early/ehci-dbgp.c
@@ -450,7 +450,7 @@ static int dbgp_ehci_startup(void)
writel(FLAG_CF, &ehci_regs->configured_flag);
/* Wait until the controller is no longer halted */
- loop = 10;
+ loop = 1000;
do {
status = readl(&ehci_regs->status);
if (!(status & STS_HALT))
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index aca160e..9f30cf5 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -112,6 +112,7 @@ config USB_GADGET_SELECTED
choice
prompt "USB Peripheral Controller"
depends on USB_GADGET
+ default USB_GADGET_S3C_OTGD if (ARCH_S5PV210)
help
A USB device uses a controller to talk to its host.
Systems should have only one such upstream link.
@@ -373,6 +374,20 @@ config USB_S3C_HSUDC
default USB_GADGET
select USB_GADGET_SELECTED
+config USB_GADGET_S3C_OTGD
+ boolean "S3C HS USB OTG Device"
+ depends on (ARCH_S5PV210)
+ help
+ Samsung's S3C64XX processors include high speed USB OTG2.0
+ controller. It has 15 configurable endpoints, as well as
+ endpoint zero (for control transfers).
+
+ This driver has been tested on the S3C6410, S5P6440, S5PC100 processor.
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "s3c-udc-otg" and force all
+ gadget drivers to also be dynamically linked.
+
config USB_GADGET_PXA_U2O
boolean "PXA9xx Processor USB2.0 controller"
select USB_GADGET_DUALSPEED
@@ -633,6 +648,43 @@ config USB_DUMMY_HCD
endchoice
+comment "NOTE: S3C OTG device role enables the controller driver below"
+ depends on USB_GADGET_S3C_OTGD
+
+config USB_S3C_OTGD
+ tristate "S3C high speed(2.0, dual-speed) USB OTG device"
+ depends on USB_GADGET && USB_GADGET_S3C_OTGD
+ default y
+ default USB_GADGET
+ select USB_GADGET_SELECTED
+ select USB_GADGET_DUALSPEED
+ help
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "s3c-udc-otg-hs" and force all
+ gadget drivers to also be dynamically linked.
+
+choice
+ prompt "S3C OTGD transfer mode"
+ depends on USB_S3C_OTGD
+ default y
+ help
+ S3C USB OTG conteroller supports DMA mode and Slave mode
+ for the dat transfer. You must slect one for the core
+ operation mode.
+
+config USB_GADGET_S3C_OTGD_DMA_MODE
+ bool "enabled DMA MODE"
+ depends on USB_GADGET_S3C_OTGD
+ help
+ S3C USB OTG core operates in DMA mode.
+
+config USB_GADGET_S3C_OTGD_SLAVE_MODE
+ bool "enabled Slave MODE"
+ depends on USB_GADGET_S3C_OTGD
+ help
+ S3C USB OTG core operates in Slave mode.
+endchoice
+
# Selected by UDC drivers that support high-speed operation.
config USB_GADGET_DUALSPEED
bool
@@ -944,6 +996,12 @@ config USB_G_ANDROID
The functions can be configured via a board file and may be
enabled and disabled dynamically.
+config USB_ANDROID_RNDIS_DWORD_ALIGNED
+ boolean "Use double word aligned"
+ depends on USB_G_ANDROID
+ help
+ Provides dword aligned for DMA controller.
+
config USB_CDC_COMPOSITE
tristate "CDC Composite Device (Ethernet and ACM)"
depends on NET
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index ab17a4c..0cb5b62 100644..100755
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_USB_IMX) += imx_udc.o
obj-$(CONFIG_USB_GOKU) += goku_udc.o
obj-$(CONFIG_USB_OMAP) += omap_udc.o
obj-$(CONFIG_USB_S3C2410) += s3c2410_udc.o
+obj-$(CONFIG_USB_S3C_OTGD) += s3c_udc_otg.o
obj-$(CONFIG_USB_AT91) += at91_udc.o
obj-$(CONFIG_USB_ATMEL_USBA) += atmel_usba_udc.o
obj-$(CONFIG_USB_FSL_USB2) += fsl_usb2_udc.o
diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c
index 9b7360f..431cc35 100644
--- a/drivers/usb/gadget/epautoconf.c
+++ b/drivers/usb/gadget/epautoconf.c
@@ -290,6 +290,60 @@ struct usb_ep *usb_ep_autoconfig (
if (ep && ep_matches (gadget, ep, desc))
return ep;
#endif
+ } else if (gadget_is_s3c(gadget)) {
+ if (USB_ENDPOINT_XFER_INT == type) {
+ /* single buffering is enough */
+ ep = find_ep (gadget, "ep3-int");
+ if (ep && ep_matches (gadget, ep, desc))
+ return ep;
+ ep = find_ep (gadget, "ep6-int");
+ if (ep && ep_matches (gadget, ep, desc))
+ return ep;
+ ep = find_ep (gadget, "ep9-int");
+ if (ep && ep_matches (gadget, ep, desc))
+ return ep;
+ ep = find_ep (gadget, "ep12-int");
+ if (ep && ep_matches (gadget, ep, desc))
+ return ep;
+ } else if (USB_ENDPOINT_XFER_BULK == type
+ && (USB_DIR_IN & desc->bEndpointAddress)) {
+ ep = find_ep (gadget, "ep2-bulk");
+ if (ep && ep_matches (gadget, ep, desc))
+ return ep;
+ ep = find_ep (gadget, "ep5-bulk");
+ if (ep && ep_matches (gadget, ep, desc))
+ return ep;
+ ep = find_ep (gadget, "ep8-bulk");
+ if (ep && ep_matches (gadget, ep, desc))
+ return ep;
+ ep = find_ep (gadget, "ep11-bulk");
+ if (ep && ep_matches (gadget, ep, desc))
+ return ep;
+ ep = find_ep (gadget, "ep14-bulk");
+ if (ep && ep_matches (gadget, ep, desc))
+ return ep;
+ } else if (USB_ENDPOINT_XFER_BULK == type
+ && !(USB_DIR_IN & desc->bEndpointAddress)) {
+ ep = find_ep (gadget, "ep1-bulk");
+ if (ep && ep_matches (gadget, ep, desc))
+ return ep;
+ ep = find_ep (gadget, "ep4-bulk");
+ if (ep && ep_matches (gadget, ep, desc))
+ return ep;
+ ep = find_ep (gadget, "ep7-bulk");
+ if (ep && ep_matches (gadget, ep, desc))
+ return ep;
+ ep = find_ep (gadget, "ep10-bulk");
+ if (ep && ep_matches (gadget, ep, desc))
+ return ep;
+ ep = find_ep (gadget, "ep13-bulk");
+ if (ep && ep_matches (gadget, ep, desc))
+ return ep;
+ } else if (USB_ENDPOINT_XFER_ISOC == type) {
+ ep = find_ep(gadget, "ep15-iso");
+ if (ep && ep_matches(gadget, ep, desc))
+ return ep;
+ }
}
/* Second, look at endpoints until an unclaimed one looks usable */
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index bc2f624..7405647 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -908,11 +908,13 @@ static int do_write(struct fsg_common *common)
curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
return -EINVAL;
}
+#ifndef CONFIG_USB_ANDROID_MASS_STORAGE
if (!curlun->nofua && (common->cmnd[1] & 0x08)) { /* FUA */
spin_lock(&curlun->filp->f_lock);
curlun->filp->f_flags |= O_SYNC;
spin_unlock(&curlun->filp->f_lock);
}
+#endif
}
if (lba >= curlun->num_sectors) {
curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index 5308381..44d789d 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -717,6 +717,8 @@ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req)
lastreq = list_entry(ep->queue.prev, struct fsl_req, queue);
lastreq->tail->next_td_ptr =
cpu_to_hc32(req->head->td_dma & DTD_ADDR_MASK);
+ /* Ensure dTD's next dtd pointer to be updated */
+ wmb();
/* Read prime bit, if 1 goto done */
if (fsl_readl(&dr_regs->endpointprime) & bitmask)
goto out;
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
index bcdac7c..839c9a3 100644
--- a/drivers/usb/gadget/gadget_chips.h
+++ b/drivers/usb/gadget/gadget_chips.h
@@ -70,6 +70,12 @@
#define gadget_is_s3c2410(g) 0
#endif
+#if CONFIG_USB_GADGET_S3C_OTGD
+#define gadget_is_s3c(g) !strcmp("s3c-udc", (g)->name)
+#else
+#define gadget_is_s3c(g) 0
+#endif
+
#ifdef CONFIG_USB_GADGET_AT91
#define gadget_is_at91(g) !strcmp("at91_udc", (g)->name)
#else
@@ -223,6 +229,8 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget)
return 0x29;
else if (gadget_is_s3c_hsudc(gadget))
return 0x30;
+ else if (gadget_is_s3c(gadget))
+ return 0x31;
return -ENOENT;
}
diff --git a/drivers/usb/gadget/s3c_udc.h b/drivers/usb/gadget/s3c_udc.h
new file mode 100644
index 0000000..a776167
--- /dev/null
+++ b/drivers/usb/gadget/s3c_udc.h
@@ -0,0 +1,164 @@
+/*
+ * drivers/usb/gadget/s3c_udc.h
+ * Samsung S3C on-chip full/high speed USB device controllers
+ * Copyright (C) 2005 for Samsung Electronics
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef __S3C_USB_GADGET
+#define __S3C_USB_GADGET
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/proc_fs.h>
+#include <linux/mm.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/byteorder.h>
+#include <asm/dma.h>
+#include <linux/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/unaligned.h>
+/* #include <asm/hardware.h> */
+
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+
+/* Max packet size */
+#if defined(CONFIG_USB_GADGET_S3C_FS)
+#define EP0_FIFO_SIZE 8
+#define EP_FIFO_SIZE 64
+#define S3C_MAX_ENDPOINTS 5
+#elif defined(CONFIG_USB_GADGET_S3C_HS) || defined(CONFIG_ARCH_S5PV210)
+#define EP0_FIFO_SIZE 64
+#define EP_FIFO_SIZE 512
+#define EP_FIFO_SIZE2 1024
+#define S3C_MAX_ENDPOINTS 16
+#define DED_TX_FIFO 1 /* Dedicated NPTx fifo for s5p6440 */
+#else
+#define EP0_FIFO_SIZE 64
+#define EP_FIFO_SIZE 512
+#define EP_FIFO_SIZE2 1024
+#define S3C_MAX_ENDPOINTS 16
+#endif
+
+#define WAIT_FOR_SETUP 0
+#define DATA_STATE_XMIT 1
+#define DATA_STATE_NEED_ZLP 2
+#define WAIT_FOR_OUT_STATUS 3
+#define DATA_STATE_RECV 4
+#define RegReadErr 5
+#define FAIL_TO_SETUP 6
+
+#define TEST_J_SEL 0x1
+#define TEST_K_SEL 0x2
+#define TEST_SE0_NAK_SEL 0x3
+#define TEST_PACKET_SEL 0x4
+#define TEST_FORCE_ENABLE_SEL 0x5
+
+
+typedef enum ep_type {
+ ep_control, ep_bulk_in, ep_bulk_out, ep_interrupt, ep_isochronous
+} ep_type_t;
+
+struct s3c_ep {
+ struct usb_ep ep;
+ struct s3c_udc *dev;
+
+ const struct usb_endpoint_descriptor *desc;
+ struct list_head queue;
+ unsigned long pio_irqs;
+
+ u8 stopped;
+ u8 bEndpointAddress;
+ u8 bmAttributes;
+
+ ep_type_t ep_type;
+ u32 fifo;
+#ifdef CONFIG_USB_GADGET_S3C_FS
+ u32 csr1;
+ u32 csr2;
+#endif
+};
+
+struct s3c_request {
+ struct usb_request req;
+ struct list_head queue;
+ unsigned char mapped;
+};
+
+struct s3c_udc {
+ struct usb_gadget gadget;
+ struct usb_gadget_driver *driver;
+ /* struct device *dev; */
+ struct platform_device *dev;
+ spinlock_t lock;
+ u16 status;
+ int ep0state;
+ struct s3c_ep ep[S3C_MAX_ENDPOINTS];
+
+ unsigned char usb_address;
+
+ unsigned req_pending:1, req_std:1, req_config:1;
+
+ struct regulator *udc_vcc_d, *udc_vcc_a;
+ int udc_enabled;
+ int soft_disconnected;
+};
+
+extern struct s3c_udc *the_controller;
+extern void otg_phy_init(void);
+extern void otg_phy_off(void);
+extern struct usb_ctrlrequest usb_ctrl;
+extern struct i2c_driver fsa9480_i2c_driver;
+
+#define ep_is_in(EP) (((EP)->bEndpointAddress&USB_DIR_IN) == USB_DIR_IN)
+#define ep_index(EP) ((EP)->bEndpointAddress&0xF)
+#define ep_maxpacket(EP) ((EP)->ep.maxpacket)
+
+#if defined CONFIG_USB_S3C_OTG_HOST || defined CONFIG_USB_DWC_OTG
+#define USB_OTG_DRIVER_S3CHS 1
+#define USB_OTG_DRIVER_S3CFSLS 2
+#define USB_OTG_DRIVER_S3C USB_OTG_DRIVER_S3CHS | USB_OTG_DRIVER_S3CFSLS
+#define USB_OTG_DRIVER_DWC 4
+#endif
+extern atomic_t g_OtgHostMode; // actual mode: client (0) or host (1)
+extern atomic_t g_OtgOperationMode; // operation mode: 'c'lient, 'h'ost, 'o'tg or 'a'uto-host
+extern atomic_t g_OtgLastCableState; // last cable state: detached (0), client attached (1), otg attached (2)
+extern atomic_t g_OtgDriver; // driver to use: 0: S3C High-speed, 1: S3C Low-speed/Full-speed, 2: DWC
+#ifdef CONFIG_USB_S3C_OTG_HOST
+extern struct platform_driver s5pc110_otg_driver;
+#endif
+#ifdef CONFIG_USB_DWC_OTG
+extern struct platform_driver dwc_otg_driver;
+#endif
+extern int s3c_is_otgmode(void);
+extern int s3c_get_drivermode(void);
+#endif
diff --git a/drivers/usb/gadget/s3c_udc_otg.c b/drivers/usb/gadget/s3c_udc_otg.c
new file mode 100644
index 0000000..7bbcedc
--- /dev/null
+++ b/drivers/usb/gadget/s3c_udc_otg.c
@@ -0,0 +1,1547 @@
+/*
+ * drivers/usb/gadget/s3c_udc_otg.c
+ * Samsung S3C on-chip full/high speed USB OTG 2.0 device controllers
+ *
+ * Copyright (C) 2008 for Samsung Electronics
+ *
+ *
+ * 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 "s3c_udc.h"
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <mach/map.h>
+#include <plat/regs-otg.h>
+#include <linux/i2c.h>
+#include <linux/regulator/consumer.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/vmalloc.h>
+#include <linux/proc_fs.h>
+#include <asm/uaccess.h>
+#if defined(CONFIG_USB_GADGET_S3C_OTGD_DMA_MODE) /* DMA mode */
+#define OTG_DMA_MODE 1
+
+#elif defined(CONFIG_USB_GADGET_S3C_OTGD_SLAVE_MODE) /* Slave mode */
+#define OTG_DMA_MODE 0
+#error " Slave Mode is not implemented to do later"
+#else
+#error " Unknown S3C OTG operation mode, Select a correct operation mode"
+#endif
+
+#define DEBUG_S3C_UDC_SETUP
+#undef DEBUG_S3C_UDC_EP0
+#define DEBUG_S3C_UDC_ISR
+#undef DEBUG_S3C_UDC_OUT_EP
+#undef DEBUG_S3C_UDC_IN_EP
+#undef DEBUG_S3C_UDC
+
+#define EP0_CON 0
+#define EP1_OUT 1
+#define EP2_IN 2
+#define EP3_IN 3
+#define EP_MASK 0xF
+
+#if defined(DEBUG_S3C_UDC_SETUP) || defined(DEBUG_S3C_UDC_ISR)\
+ || defined(DEBUG_S3C_UDC_OUT_EP)
+
+static char *state_names[] = {
+ "WAIT_FOR_SETUP",
+ "DATA_STATE_XMIT",
+ "DATA_STATE_NEED_ZLP",
+ "WAIT_FOR_OUT_STATUS",
+ "DATA_STATE_RECV",
+ };
+#endif
+
+#ifdef DEBUG_S3C_UDC_SETUP
+#define DEBUG_SETUP(fmt, args...) pr_debug(fmt, ##args)
+#else
+#define DEBUG_SETUP(fmt, args...) do {} while (0)
+#endif
+
+#ifdef DEBUG_S3C_UDC_EP0
+#define DEBUG_EP0(fmt, args...) printk(fmt, ##args)
+#else
+#define DEBUG_EP0(fmt, args...) do {} while (0)
+#endif
+
+#ifdef DEBUG_S3C_UDC
+#define DEBUG(fmt, args...) printk(fmt, ##args)
+#else
+#define DEBUG(fmt, args...) do {} while (0)
+#endif
+
+#ifdef DEBUG_S3C_UDC_ISR
+#define DEBUG_ISR(fmt, args...) pr_debug(fmt, ##args)
+#else
+#define DEBUG_ISR(fmt, args...) do {} while (0)
+#endif
+
+#ifdef DEBUG_S3C_UDC_OUT_EP
+#define DEBUG_OUT_EP(fmt, args...) printk(fmt, ##args)
+#else
+#define DEBUG_OUT_EP(fmt, args...) do {} while (0)
+#endif
+
+#ifdef DEBUG_S3C_UDC_IN_EP
+#define DEBUG_IN_EP(fmt, args...) printk(fmt, ##args)
+#else
+#define DEBUG_IN_EP(fmt, args...) do {} while (0)
+#endif
+
+
+#define DRIVER_DESC "S3C HS USB Device Controller Driver, (c) 2008-2009 Samsung Electronics"
+#define DRIVER_VERSION "15 March 2009"
+
+struct s3c_udc *the_controller;
+
+static struct clk *otg_clock;
+static const char driver_name[] = "s3c-udc";
+static const char driver_desc[] = DRIVER_DESC;
+static const char ep0name[] = "ep0-control";
+
+/* Max packet size*/
+static unsigned int ep0_fifo_size = 64;
+static unsigned int ep_fifo_size = 512;
+static unsigned int ep_fifo_size2 = 1024;
+static int reset_available = 1;
+
+/*
+ Local declarations.
+*/
+static int s3c_ep_enable(struct usb_ep *ep,
+ const struct usb_endpoint_descriptor *);
+static int s3c_ep_disable(struct usb_ep *ep);
+static struct usb_request *s3c_alloc_request(struct usb_ep *ep,
+ gfp_t gfp_flags);
+static void s3c_free_request(struct usb_ep *ep, struct usb_request *);
+
+static int s3c_queue(struct usb_ep *ep,
+ struct usb_request *, gfp_t gfp_flags);
+static int s3c_dequeue(struct usb_ep *ep, struct usb_request *);
+static int s3c_fifo_status(struct usb_ep *ep);
+static void s3c_fifo_flush(struct usb_ep *ep);
+static void s3c_ep0_read(struct s3c_udc *dev);
+static void s3c_ep0_kick(struct s3c_udc *dev, struct s3c_ep *ep);
+static void s3c_handle_ep0(struct s3c_udc *dev);
+static int s3c_ep0_write(struct s3c_udc *dev);
+static int write_fifo_ep0(struct s3c_ep *ep, struct s3c_request *req);
+static void done(struct s3c_ep *ep, struct s3c_request *req, int status);
+static void stop_activity(struct s3c_udc *dev,
+ struct usb_gadget_driver *driver);
+static int udc_enable(struct s3c_udc *dev);
+static void udc_set_address(struct s3c_udc *dev, unsigned char address);
+static void reconfig_usbd(void);
+static void set_max_pktsize(struct s3c_udc *dev, enum usb_device_speed speed);
+static void nuke(struct s3c_ep *ep, int status);
+static int s3c_udc_set_halt(struct usb_ep *_ep, int value);
+
+static struct usb_ep_ops s3c_ep_ops = {
+ .enable = s3c_ep_enable,
+ .disable = s3c_ep_disable,
+
+ .alloc_request = s3c_alloc_request,
+ .free_request = s3c_free_request,
+
+ .queue = s3c_queue,
+ .dequeue = s3c_dequeue,
+
+ .set_halt = s3c_udc_set_halt,
+ .fifo_status = s3c_fifo_status,
+ .fifo_flush = s3c_fifo_flush,
+};
+
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+
+static const char proc_node_name[] = "driver/udc";
+
+static int
+udc_proc_read(char *page, char **start, off_t off, int count,
+ int *eof, void *_dev)
+{
+ char *buf = page;
+ struct s3c_udc *dev = _dev;
+ char *next = buf;
+ unsigned size = count;
+ unsigned long flags;
+ int t;
+
+ if (off != 0)
+ return 0;
+
+ local_irq_save(flags);
+
+ /* basic device status */
+ t = scnprintf(next, size,
+ DRIVER_DESC "\n"
+ "%s version: %s\n"
+ "Gadget driver: %s\n"
+ "\n",
+ driver_name, DRIVER_VERSION,
+ dev->driver ? dev->driver->driver.name : "(none)");
+ size -= t;
+ next += t;
+
+ local_irq_restore(flags);
+ *eof = 1;
+ return count - size;
+}
+
+#define create_proc_files() \
+ create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev)
+#define remove_proc_files() \
+ remove_proc_entry(proc_node_name, NULL)
+
+#else /* !CONFIG_USB_GADGET_DEBUG_FILES */
+
+#define create_proc_files() do {} while (0)
+#define remove_proc_files() do {} while (0)
+
+#endif /* CONFIG_USB_GADGET_DEBUG_FILES */
+
+#if OTG_DMA_MODE /* DMA Mode */
+#include "s3c_udc_otg_xfer_dma.c"
+
+#else /* Slave Mode */
+#include "s3c_udc_otg_xfer_slave.c"
+#endif
+
+/*
+ * udc_disable - disable USB device controller
+ */
+static void udc_disable(struct s3c_udc *dev)
+{
+ DEBUG_SETUP("%s: %p\n", __func__, dev);
+
+ udc_set_address(dev, 0);
+
+ dev->ep0state = WAIT_FOR_SETUP;
+ dev->gadget.speed = USB_SPEED_UNKNOWN;
+ dev->usb_address = 0;
+
+ otg_phy_off();
+}
+
+/*
+ * udc_reinit - initialize software state
+ */
+static void udc_reinit(struct s3c_udc *dev)
+{
+ unsigned int i;
+
+ DEBUG_SETUP("%s: %p\n", __func__, dev);
+
+ /* device/ep0 records init */
+ INIT_LIST_HEAD(&dev->gadget.ep_list);
+ INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
+ dev->ep0state = WAIT_FOR_SETUP;
+
+ /* basic endpoint records init */
+ for (i = 0; i < S3C_MAX_ENDPOINTS; i++) {
+ struct s3c_ep *ep = &dev->ep[i];
+
+ if (i != 0)
+ list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);
+
+ ep->desc = 0;
+ ep->stopped = 0;
+ INIT_LIST_HEAD(&ep->queue);
+ ep->pio_irqs = 0;
+ }
+
+ /* the rest was statically initialized, and is read-only */
+}
+
+#define BYTES2MAXP(x) (x / 8)
+#define MAXP2BYTES(x) (x * 8)
+
+/* until it's enabled, this UDC should be completely invisible
+ * to any USB host.
+ */
+static int udc_enable(struct s3c_udc *dev)
+{
+ unsigned long flags;
+
+ DEBUG_SETUP("%s: %p\n", __func__, dev);
+
+ otg_phy_init();
+
+ spin_lock_irqsave(&dev->lock, flags);
+ reconfig_usbd();
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+ DEBUG_SETUP("S3C USB 2.0 OTG Controller Core Initialized : 0x%x\n",
+ readl(S3C_UDC_OTG_GINTMSK));
+
+ dev->gadget.speed = USB_SPEED_UNKNOWN;
+
+ return 0;
+}
+
+/*
+ Register entry point for the peripheral controller driver.
+*/
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+ int (*bind)(struct usb_gadget *))
+{
+ struct s3c_udc *dev = the_controller;
+ int retval;
+
+ DEBUG_SETUP("%s: %s\n", __func__, driver->driver.name);
+
+/*
+ * adb composite fail to !driver->unbind in composite.c as below
+ * static struct usb_gadget_driver composite_driver = {
+ * .speed = USB_SPEED_HIGH,
+ * .bind = composite_bind,
+ * .unbind = __exit_p(composite_unbind),
+ */
+ if (!driver
+ || (driver->speed != USB_SPEED_FULL && driver->speed != USB_SPEED_HIGH)
+ || !bind
+ || !driver->disconnect || !driver->setup)
+ return -EINVAL;
+ if (!dev)
+ return -ENODEV;
+ if (dev->driver)
+ return -EBUSY;
+
+ /* first hook up the driver ... */
+ dev->driver = driver;
+ /* initialize device status as self-powered.*/
+ dev->status = 1 << USB_DEVICE_SELF_POWERED;
+ dev->gadget.dev.driver = &driver->driver;
+ retval = device_add(&dev->gadget.dev);
+
+ if (retval) {
+ printk(KERN_ERR "target device_add failed, error %d\n", retval);
+ return retval;
+ }
+
+ retval = bind(&dev->gadget);
+ if (retval) {
+ printk(KERN_ERR "%s: bind to driver %s --> error %d\n",
+ dev->gadget.name, driver->driver.name, retval);
+ device_del(&dev->gadget.dev);
+
+ dev->driver = 0;
+ dev->gadget.dev.driver = 0;
+ return retval;
+ }
+
+ enable_irq(IRQ_OTG);
+
+ retval = usb_gadget_vbus_connect(&dev->gadget);
+ if (retval < 0)
+ dev_dbg(&dev->gadget.dev, "%s vbus connect %d\n",
+ __func__, retval);
+
+ if (!(readl(S3C_UDC_OTG_GOTGCTL) & B_SESSION_VALID)) {
+ retval = usb_gadget_vbus_disconnect(&dev->gadget);
+ if (retval < 0) {
+ dev_dbg(&dev->gadget.dev, "%s vbus disconnect %d\n",
+ __func__, retval);
+ }
+ }
+
+ printk(KERN_DEBUG "Registered gadget driver '%s'\n",
+ driver->driver.name);
+
+ return 0;
+}
+EXPORT_SYMBOL(usb_gadget_probe_driver);
+
+/*
+ Unregister entry point for the peripheral controller driver.
+*/
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+{
+ struct s3c_udc *dev = the_controller;
+ unsigned long flags;
+
+ if (!dev)
+ return -ENODEV;
+ if (!driver || driver != dev->driver)
+ return -EINVAL;
+
+ spin_lock_irqsave(&dev->lock, flags);
+ dev->driver = 0;
+ stop_activity(dev, driver);
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+ driver->unbind(&dev->gadget);
+ device_del(&dev->gadget.dev);
+
+ disable_irq(IRQ_OTG);
+
+ printk(KERN_DEBUG "Unregistered gadget driver '%s'\n",
+ driver->driver.name);
+
+ udc_disable(dev);
+
+ return 0;
+}
+EXPORT_SYMBOL(usb_gadget_unregister_driver);
+
+static int s3c_udc_power(struct s3c_udc *dev, char en)
+{
+ pr_debug("%s : %s\n", __func__, en ? "ON" : "OFF");
+
+ if (en) {
+ regulator_enable(dev->udc_vcc_d);
+ regulator_enable(dev->udc_vcc_a);
+ } else {
+ regulator_disable(dev->udc_vcc_d);
+ regulator_disable(dev->udc_vcc_a);
+ }
+
+ return 0;
+}
+
+int s3c_vbus_enable(struct usb_gadget *gadget, int enable)
+{
+ unsigned long flags;
+ struct s3c_udc *dev = the_controller;
+
+ if (dev->udc_enabled != enable) {
+ dev->udc_enabled = enable;
+ if (!enable) {
+ spin_lock_irqsave(&dev->lock, flags);
+ stop_activity(dev, dev->driver);
+ spin_unlock_irqrestore(&dev->lock, flags);
+ udc_disable(dev);
+ clk_disable(otg_clock);
+ s3c_udc_power(dev, 0);
+ } else {
+ s3c_udc_power(dev, 1);
+ clk_enable(otg_clock);
+ udc_reinit(dev);
+ udc_enable(dev);
+ }
+ } else
+ dev_dbg(&dev->gadget.dev, "%s, udc : %d, en : %d\n",
+ __func__, dev->udc_enabled, enable);
+
+ return 0;
+}
+
+/*
+ * done - retire a request; caller blocked irqs
+ */
+static void done(struct s3c_ep *ep, struct s3c_request *req, int status)
+{
+ unsigned int stopped = ep->stopped;
+ struct device *dev = &the_controller->dev->dev;
+ DEBUG("%s: %s %p, req = %p, stopped = %d\n",
+ __func__, ep->ep.name, ep, &req->req, stopped);
+
+ list_del_init(&req->queue);
+
+ if (likely(req->req.status == -EINPROGRESS))
+ req->req.status = status;
+ else
+ status = req->req.status;
+
+ if (req->mapped) {
+ dma_unmap_single(dev, req->req.dma, req->req.length,
+ (ep->bEndpointAddress & USB_DIR_IN) ?
+ DMA_TO_DEVICE : DMA_FROM_DEVICE);
+ req->req.dma = DMA_ADDR_INVALID;
+ req->mapped = 0;
+ }
+ if (status && status != -ESHUTDOWN) {
+ DEBUG("complete %s req %p stat %d len %u/%u\n",
+ ep->ep.name, &req->req, status,
+ req->req.actual, req->req.length);
+ }
+
+ /* don't modify queue heads during completion callback */
+ ep->stopped = 1;
+
+ spin_unlock(&ep->dev->lock);
+ req->req.complete(&ep->ep, &req->req);
+ spin_lock(&ep->dev->lock);
+
+ ep->stopped = stopped;
+}
+
+/*
+ * nuke - dequeue ALL requests
+ */
+static void nuke(struct s3c_ep *ep, int status)
+{
+ struct s3c_request *req;
+
+ DEBUG("%s: %s %p\n", __func__, ep->ep.name, ep);
+
+ /* called with irqs blocked */
+ while (!list_empty(&ep->queue)) {
+ req = list_entry(ep->queue.next, struct s3c_request, queue);
+ done(ep, req, status);
+ }
+}
+
+static void stop_activity(struct s3c_udc *dev,
+ struct usb_gadget_driver *driver)
+{
+ int i;
+
+ /* don't disconnect drivers more than once */
+ if (dev->gadget.speed == USB_SPEED_UNKNOWN)
+ driver = 0;
+ dev->gadget.speed = USB_SPEED_UNKNOWN;
+
+ /* prevent new request submissions, kill any outstanding requests */
+ for (i = 0; i < S3C_MAX_ENDPOINTS; i++) {
+ struct s3c_ep *ep = &dev->ep[i];
+ ep->stopped = 1;
+ nuke(ep, -ESHUTDOWN);
+ }
+
+ /* report disconnect; the driver is already quiesced */
+ if (driver) {
+ spin_unlock(&dev->lock);
+ driver->disconnect(&dev->gadget);
+ spin_lock(&dev->lock);
+ }
+
+ /* re-init driver-visible data structures */
+ udc_reinit(dev);
+}
+
+static void reconfig_usbd(void)
+{
+ struct s3c_udc *dev = the_controller;
+ /* 2. Soft-reset OTG Core and then unreset again. */
+#ifdef DED_TX_FIFO
+ int i;
+#endif
+ unsigned int uTemp;
+ writel(CORE_SOFT_RESET, S3C_UDC_OTG_GRSTCTL);
+
+ writel(0<<15 /* PHY Low Power Clock sel*/
+ |1<<14 /* Non-Periodic TxFIFO Rewind Enable*/
+ |0x5<<10 /* Turnaround time*/
+ |0<<9|0<<8 /* [0:HNP disable, 1:HNP enable][ 0:SRP disable, 1:SRP enable] H1= 1,1*/
+ |0<<7 /* Ulpi DDR sel*/
+ |0<<6 /* 0: high speed utmi+, 1: full speed serial*/
+ |0<<4 /* 0: utmi+, 1:ulpi*/
+ |1<<3 /* phy i/f 0:8bit, 1:16bit*/
+ |0x7<<0, /* HS/FS Timeout**/
+ S3C_UDC_OTG_GUSBCFG);
+
+ /* 3. Put the OTG device core in the disconnected state.*/
+ uTemp = readl(S3C_UDC_OTG_DCTL);
+ uTemp |= SOFT_DISCONNECT;
+ writel(uTemp, S3C_UDC_OTG_DCTL);
+
+ udelay(20);
+
+ /* 4. Make the OTG device core exit from the disconnected state.*/
+ if (!dev->soft_disconnected) {
+ uTemp = readl(S3C_UDC_OTG_DCTL);
+ uTemp = uTemp & ~SOFT_DISCONNECT;
+ writel(uTemp, S3C_UDC_OTG_DCTL);
+ }
+
+ /* 5. Configure OTG Core to initial settings of device mode.*/
+ /* [][1: full speed(30Mhz) 0:high speed]*/
+ writel(1<<18|0x0<<0, S3C_UDC_OTG_DCFG);
+
+ mdelay(1);
+
+ /* 6. Unmask the core interrupts*/
+ writel(GINTMSK_INIT, S3C_UDC_OTG_GINTMSK);
+
+ /* 7. Set NAK bit of EP0, EP1, EP2*/
+ writel(DEPCTL_EPDIS|DEPCTL_SNAK|(0<<0), S3C_UDC_OTG_DOEPCTL(EP0_CON));
+ writel(DEPCTL_EPDIS|DEPCTL_SNAK|(0<<0), S3C_UDC_OTG_DIEPCTL(EP0_CON));
+
+ /* 8. Unmask EPO interrupts*/
+ writel(((1<<EP0_CON)<<DAINT_OUT_BIT)|(1<<EP0_CON),
+ S3C_UDC_OTG_DAINTMSK);
+
+ /* 9. Unmask device OUT EP common interrupts*/
+ writel(DOEPMSK_INIT, S3C_UDC_OTG_DOEPMSK);
+
+ /* 10. Unmask device IN EP common interrupts*/
+ writel(DIEPMSK_INIT, S3C_UDC_OTG_DIEPMSK);
+
+ /* 11. Set Rx FIFO Size (in 32-bit words) */
+ writel(RX_FIFO_SIZE, S3C_UDC_OTG_GRXFSIZ);
+
+ /* 12. Set Non Periodic Tx FIFO Size*/
+ writel((NPTX_FIFO_SIZE) << 16 | (NPTX_FIFO_START_ADDR) << 0,
+ S3C_UDC_OTG_GNPTXFSIZ);
+
+#ifdef DED_TX_FIFO
+ for (i = 1; i < S3C_MAX_ENDPOINTS; i++)
+ writel((PTX_FIFO_SIZE) << 16 |
+ (NPTX_FIFO_START_ADDR + NPTX_FIFO_SIZE + PTX_FIFO_SIZE*(i-1)) << 0,
+ S3C_UDC_OTG_DIEPTXF(i));
+#endif
+
+ /* Flush the RX FIFO */
+ writel(0x10, S3C_UDC_OTG_GRSTCTL);
+ while (readl(S3C_UDC_OTG_GRSTCTL) & 0x10)
+ ;
+
+ /* Flush all the Tx FIFO's */
+ writel(0x10<<6, S3C_UDC_OTG_GRSTCTL);
+ writel((0x10<<6)|0x20, S3C_UDC_OTG_GRSTCTL);
+ while (readl(S3C_UDC_OTG_GRSTCTL) & 0x20)
+ ;
+
+ /* 13. Initialize OTG Link Core.*/
+ writel(GAHBCFG_INIT, S3C_UDC_OTG_GAHBCFG);
+}
+
+static void set_max_pktsize(struct s3c_udc *dev, enum usb_device_speed speed)
+{
+ unsigned int ep_ctrl;
+ int i;
+ if (speed == USB_SPEED_HIGH) {
+ ep0_fifo_size = 64;
+ ep_fifo_size = 512;
+ ep_fifo_size2 = 1024;
+ dev->gadget.speed = USB_SPEED_HIGH;
+ } else {
+ ep0_fifo_size = 64;
+ ep_fifo_size = 64;
+ ep_fifo_size2 = 64;
+ dev->gadget.speed = USB_SPEED_FULL;
+ }
+
+ dev->ep[0].ep.maxpacket = ep0_fifo_size;
+ for (i = 1; i < S3C_MAX_ENDPOINTS; i++) {
+ /* fullspeed limitations don't apply to isochronous endpoints */
+ if (dev->ep[i].bmAttributes != USB_ENDPOINT_XFER_ISOC)
+ dev->ep[i].ep.maxpacket = ep_fifo_size;
+ }
+
+ /* EP0 - Control IN (64 bytes)*/
+ ep_ctrl = readl(S3C_UDC_OTG_DIEPCTL(EP0_CON));
+ writel(ep_ctrl|(0<<0), S3C_UDC_OTG_DIEPCTL(EP0_CON));
+
+ /* EP0 - Control OUT (64 bytes)*/
+ ep_ctrl = readl(S3C_UDC_OTG_DOEPCTL(EP0_CON));
+ writel(ep_ctrl|(0<<0), S3C_UDC_OTG_DOEPCTL(EP0_CON));
+}
+
+static int s3c_ep_enable(struct usb_ep *_ep,
+ const struct usb_endpoint_descriptor *desc)
+{
+ struct s3c_ep *ep;
+ struct s3c_udc *dev;
+ unsigned long flags;
+
+ DEBUG("%s: %p\n", __func__, _ep);
+
+ ep = container_of(_ep, struct s3c_ep, ep);
+ if (!_ep || !desc || ep->desc || _ep->name == ep0name
+ || desc->bDescriptorType != USB_DT_ENDPOINT
+ || ep->bEndpointAddress != desc->bEndpointAddress
+ || ep_maxpacket(ep) < le16_to_cpu(desc->wMaxPacketSize)) {
+
+ DEBUG("%s: bad ep or descriptor\n", __func__);
+ return -EINVAL;
+ }
+
+ /* xfer types must match, except that interrupt ~= bulk */
+ if (ep->bmAttributes !=
+ (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+ && ep->bmAttributes != USB_ENDPOINT_XFER_BULK
+ && desc->bmAttributes != USB_ENDPOINT_XFER_INT) {
+
+ DEBUG("%s: %s type mismatch\n", __func__, _ep->name);
+ return -EINVAL;
+ }
+
+ /* hardware _could_ do smaller, but driver doesn't */
+ if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK
+ && le16_to_cpu(desc->wMaxPacketSize) != ep_maxpacket(ep))
+ || !desc->wMaxPacketSize) {
+
+ DEBUG("%s: bad %s maxpacket\n", __func__, _ep->name);
+ return -ERANGE;
+ }
+
+ dev = ep->dev;
+ if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) {
+
+ DEBUG("%s: bogus device state\n", __func__);
+ return -ESHUTDOWN;
+ }
+
+ ep->stopped = 0;
+ ep->desc = desc;
+ ep->pio_irqs = 0;
+ ep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize);
+
+ /* Reset halt state */
+ s3c_udc_set_halt(_ep, 0);
+
+ spin_lock_irqsave(&ep->dev->lock, flags);
+ s3c_udc_ep_activate(ep);
+ spin_unlock_irqrestore(&ep->dev->lock, flags);
+
+ DEBUG("%s: enabled %s, stopped = %d, maxpacket = %d\n",
+ __func__, _ep->name, ep->stopped, ep->ep.maxpacket);
+ return 0;
+}
+
+/** Disable EP
+ */
+static int s3c_ep_disable(struct usb_ep *_ep)
+{
+ struct s3c_ep *ep;
+ unsigned long flags;
+
+ DEBUG("%s: %p\n", __func__, _ep);
+
+ ep = container_of(_ep, struct s3c_ep, ep);
+ if (!_ep || !ep->desc) {
+ DEBUG("%s: %s not enabled\n", __func__,
+ _ep ? ep->ep.name : NULL);
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&ep->dev->lock, flags);
+
+ /* Nuke all pending requests */
+ nuke(ep, -ESHUTDOWN);
+
+ ep->desc = 0;
+ ep->stopped = 1;
+
+ spin_unlock_irqrestore(&ep->dev->lock, flags);
+
+ DEBUG("%s: disabled %s\n", __func__, _ep->name);
+ return 0;
+}
+
+static struct usb_request *s3c_alloc_request(struct usb_ep *ep,
+ gfp_t gfp_flags)
+{
+ struct s3c_request *req;
+
+ DEBUG("%s: %s %p\n", __func__, ep->name, ep);
+
+ req = kzalloc(sizeof(*req), gfp_flags);
+ if (req)
+ INIT_LIST_HEAD(&req->queue);
+
+ return &req->req;
+}
+
+static void s3c_free_request(struct usb_ep *ep, struct usb_request *_req)
+{
+ struct s3c_request *req = container_of(_req, struct s3c_request, req);
+ DEBUG("%s: %p\n", __func__, ep);
+ kfree(req);
+}
+
+/* dequeue JUST ONE request */
+static int s3c_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+ struct s3c_ep *ep;
+ struct s3c_request *req;
+ unsigned long flags;
+
+ DEBUG("%s: %p\n", __func__, _ep);
+
+ ep = container_of(_ep, struct s3c_ep, ep);
+ if (!_ep || ep->ep.name == ep0name)
+ return -EINVAL;
+
+ spin_lock_irqsave(&ep->dev->lock, flags);
+
+ /* make sure it's actually queued on this endpoint */
+ list_for_each_entry(req, &ep->queue, queue) {
+ if (&req->req == _req)
+ break;
+ }
+ if (&req->req != _req) {
+ spin_unlock_irqrestore(&ep->dev->lock, flags);
+ return -EINVAL;
+ }
+
+ done(ep, req, -ECONNRESET);
+
+ spin_unlock_irqrestore(&ep->dev->lock, flags);
+ return 0;
+}
+
+/** Return bytes in EP FIFO
+ */
+static int s3c_fifo_status(struct usb_ep *_ep)
+{
+ int count = 0;
+ struct s3c_ep *ep;
+
+ ep = container_of(_ep, struct s3c_ep, ep);
+ if (!_ep) {
+ DEBUG("%s: bad ep\n", __func__);
+ return -ENODEV;
+ }
+
+ DEBUG("%s: %d\n", __func__, ep_index(ep));
+
+ /* LPD can't report unclaimed bytes from IN fifos */
+ if (ep_is_in(ep))
+ return -EOPNOTSUPP;
+
+ return count;
+}
+
+/** Flush EP FIFO
+ */
+static void s3c_fifo_flush(struct usb_ep *_ep)
+{
+ struct s3c_ep *ep;
+
+ ep = container_of(_ep, struct s3c_ep, ep);
+ if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) {
+ DEBUG("%s: bad ep\n", __func__);
+ return;
+ }
+
+ DEBUG("%s: %d\n", __func__, ep_index(ep));
+}
+
+/* ---------------------------------------------------------------------------
+ * device-scoped parts of the api to the usb controller hardware
+ * ---------------------------------------------------------------------------
+ */
+
+static int s3c_udc_get_frame(struct usb_gadget *_gadget)
+{
+ unsigned int frame;
+ DEBUG("%s: %p\n", __func__, _gadget);
+ /*fram count number [21:8]*/
+ frame = readl(S3C_UDC_OTG_DSTS);
+ frame &= SOFFN_MASK;
+ frame >>= SOFFN_SHIFT;
+ return frame;
+}
+
+static int s3c_udc_wakeup(struct usb_gadget *_gadget)
+{
+ unsigned int dev_gctl, dev_dctl, dev_status;
+ unsigned long flags;
+ int retVal = -EINVAL;
+ struct s3c_udc *dev = the_controller;
+
+ DEBUG("%s: %p\n", __func__, _gadget);
+
+ if (!_gadget)
+ return -ENODEV;
+
+ spin_lock_irqsave(&dev->lock, flags);
+
+ if (!(dev->status & (1 << USB_DEVICE_REMOTE_WAKEUP))) {
+ DEBUG_SETUP("%s::Remote Wakeup is not set\n", __func__);
+ goto wakeup_exit;
+ }
+ /* check for session */
+ dev_gctl = readl(S3C_UDC_OTG_GOTGCTL);
+ if (dev_gctl & B_SESSION_VALID) {
+ /* check for suspend state */
+ dev_status = readl(S3C_UDC_OTG_DSTS);
+ if (dev_status & USB_SUSPEND) {
+ DEBUG_SETUP("%s:: Set Remote wakeup\n", __func__);
+ dev_dctl = readl(S3C_UDC_OTG_DCTL);
+ dev_dctl |= REMOTE_WAKEUP;
+ writel(dev_dctl, S3C_UDC_OTG_DCTL);
+ mdelay(1);
+ DEBUG_SETUP("%s:: Clear Remote Wakeup\n", __func__);
+ dev_dctl = readl(S3C_UDC_OTG_DCTL);
+ dev_dctl &= (~REMOTE_WAKEUP);
+ writel(dev_dctl, S3C_UDC_OTG_DCTL);
+ } else {
+ DEBUG_SETUP("%s:: already woke up\n", __func__);
+ }
+
+ } else if (dev_gctl & SESSION_REQ) {
+ DEBUG_SETUP("%s:: Session request already active\n", __func__);
+ goto wakeup_exit;
+ }
+
+ retVal = 0;
+wakeup_exit:
+ spin_unlock_irqrestore(&dev->lock, flags);
+ return retVal;
+}
+
+void s3c_udc_soft_connect(void)
+{
+ struct s3c_udc *dev = the_controller;
+ unsigned long flags;
+ u32 uTemp;
+
+ DEBUG("[%s]\n", __func__);
+
+ spin_lock_irqsave(&dev->lock, flags);
+
+ uTemp = readl(S3C_UDC_OTG_DCTL);
+ uTemp = uTemp & ~SOFT_DISCONNECT;
+ writel(uTemp, S3C_UDC_OTG_DCTL);
+ udelay(20);
+
+ reset_available = 1;
+
+ /* Unmask the core interrupt */
+ writel(readl(S3C_UDC_OTG_GINTSTS), S3C_UDC_OTG_GINTSTS);
+ writel(GINTMSK_INIT, S3C_UDC_OTG_GINTMSK);
+
+ dev->soft_disconnected = 0;
+ spin_unlock_irqrestore(&dev->lock, flags);
+}
+
+void s3c_udc_soft_disconnect(void)
+{
+ u32 uTemp;
+ struct s3c_udc *dev = the_controller;
+ unsigned long flags;
+
+ DEBUG("[%s]\n", __func__);
+
+ spin_lock_irqsave(&dev->lock, flags);
+
+ /* Mask the core interrupt */
+ writel(0, S3C_UDC_OTG_GINTMSK);
+
+ uTemp = readl(S3C_UDC_OTG_DCTL);
+ uTemp |= SOFT_DISCONNECT;
+ writel(uTemp, S3C_UDC_OTG_DCTL);
+
+ stop_activity(dev, dev->driver);
+
+ dev->soft_disconnected = 1;
+ spin_unlock_irqrestore(&dev->lock, flags);
+}
+
+static int s3c_udc_pullup(struct usb_gadget *gadget, int is_on)
+{
+ if (is_on)
+ s3c_udc_soft_connect();
+ else
+ s3c_udc_soft_disconnect();
+ return 0;
+}
+
+
+static const struct usb_gadget_ops s3c_udc_ops = {
+ .get_frame = s3c_udc_get_frame,
+ .wakeup = s3c_udc_wakeup,
+ /* current versions must always be self-powered */
+ .pullup = s3c_udc_pullup,
+ .vbus_session = s3c_vbus_enable,
+};
+
+static void nop_release(struct device *dev)
+{
+ DEBUG("%s\n", __func__);
+}
+
+static struct s3c_udc memory = {
+ .usb_address = 0,
+
+ .gadget = {
+ .ops = &s3c_udc_ops,
+ .ep0 = &memory.ep[0].ep,
+ .name = driver_name,
+ .dev = {
+ .release = nop_release,
+ },
+ },
+
+ /* control endpoint */
+ .ep[0] = {
+ .ep = {
+ .name = ep0name,
+ .ops = &s3c_ep_ops,
+ .maxpacket = EP0_FIFO_SIZE,
+ },
+ .dev = &memory,
+
+ .bEndpointAddress = 0,
+ .bmAttributes = 0,
+
+ .ep_type = ep_control,
+ .fifo = (unsigned int) S3C_UDC_OTG_EP0_FIFO,
+ },
+
+ /* first group of endpoints */
+ .ep[1] = {
+ .ep = {
+ .name = "ep1-bulk",
+ .ops = &s3c_ep_ops,
+ .maxpacket = EP_FIFO_SIZE,
+ },
+ .dev = &memory,
+
+ .bEndpointAddress = USB_DIR_OUT | 1,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+
+ .ep_type = ep_bulk_out,
+ .fifo = (unsigned int) S3C_UDC_OTG_EP1_FIFO,
+ },
+
+ .ep[2] = {
+ .ep = {
+ .name = "ep2-bulk",
+ .ops = &s3c_ep_ops,
+ .maxpacket = EP_FIFO_SIZE,
+ },
+ .dev = &memory,
+
+ .bEndpointAddress = USB_DIR_IN | 2,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+
+ .ep_type = ep_bulk_in,
+ .fifo = (unsigned int) S3C_UDC_OTG_EP2_FIFO,
+ },
+
+ .ep[3] = {
+ .ep = {
+ .name = "ep3-int",
+ .ops = &s3c_ep_ops,
+ .maxpacket = EP_FIFO_SIZE,
+ },
+ .dev = &memory,
+
+ .bEndpointAddress = USB_DIR_IN | 3,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+
+ .ep_type = ep_interrupt,
+ .fifo = (unsigned int) S3C_UDC_OTG_EP3_FIFO,
+ },
+ .ep[4] = {
+ .ep = {
+ .name = "ep4-bulk",
+ .ops = &s3c_ep_ops,
+ .maxpacket = EP_FIFO_SIZE,
+ },
+ .dev = &memory,
+
+ .bEndpointAddress = USB_DIR_OUT | 4,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+
+ .ep_type = ep_bulk_out,
+ .fifo = (unsigned int) S3C_UDC_OTG_EP4_FIFO,
+ },
+ .ep[5] = {
+ .ep = {
+ .name = "ep5-bulk",
+ .ops = &s3c_ep_ops,
+ .maxpacket = EP_FIFO_SIZE,
+ },
+ .dev = &memory,
+
+ .bEndpointAddress = USB_DIR_IN | 5,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+
+ .ep_type = ep_bulk_in,
+ .fifo = (unsigned int) S3C_UDC_OTG_EP5_FIFO,
+ },
+ .ep[6] = {
+ .ep = {
+ .name = "ep6-int",
+ .ops = &s3c_ep_ops,
+ .maxpacket = EP_FIFO_SIZE,
+ },
+ .dev = &memory,
+
+ .bEndpointAddress = USB_DIR_IN | 6,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+
+ .ep_type = ep_interrupt,
+ .fifo = (unsigned int) S3C_UDC_OTG_EP6_FIFO,
+ },
+ .ep[7] = {
+ .ep = {
+ .name = "ep7-bulk",
+ .ops = &s3c_ep_ops,
+ .maxpacket = EP_FIFO_SIZE,
+ },
+ .dev = &memory,
+
+ .bEndpointAddress = USB_DIR_OUT | 7,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+
+ .ep_type = ep_bulk_out,
+ .fifo = (unsigned int) S3C_UDC_OTG_EP7_FIFO,
+ },
+ .ep[8] = {
+ .ep = {
+ .name = "ep8-bulk",
+ .ops = &s3c_ep_ops,
+ .maxpacket = EP_FIFO_SIZE,
+ },
+ .dev = &memory,
+
+ .bEndpointAddress = USB_DIR_IN | 8,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+
+ .ep_type = ep_bulk_in,
+ .fifo = (unsigned int) S3C_UDC_OTG_EP8_FIFO,
+ },
+ .ep[9] = {
+ .ep = {
+ .name = "ep9-int",
+ .ops = &s3c_ep_ops,
+ .maxpacket = EP_FIFO_SIZE,
+ },
+ .dev = &memory,
+
+ .bEndpointAddress = USB_DIR_IN | 9,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+
+ .ep_type = ep_interrupt,
+ .fifo = (unsigned int) S3C_UDC_OTG_EP9_FIFO,
+ },
+ .ep[10] = {
+ .ep = {
+ .name = "ep10-bulk",
+ .ops = &s3c_ep_ops,
+ .maxpacket = EP_FIFO_SIZE,
+ },
+ .dev = &memory,
+
+ .bEndpointAddress = USB_DIR_OUT | 0xa,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+
+ .ep_type = ep_bulk_out,
+ .fifo = (unsigned int) S3C_UDC_OTG_EP10_FIFO,
+ },
+ .ep[11] = {
+ .ep = {
+ .name = "ep11-bulk",
+ .ops = &s3c_ep_ops,
+ .maxpacket = EP_FIFO_SIZE,
+ },
+ .dev = &memory,
+
+ .bEndpointAddress = USB_DIR_IN | 0xb,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+
+ .ep_type = ep_bulk_in,
+ .fifo = (unsigned int) S3C_UDC_OTG_EP11_FIFO,
+ },
+ .ep[12] = {
+ .ep = {
+ .name = "ep12-int",
+ .ops = &s3c_ep_ops,
+ .maxpacket = EP_FIFO_SIZE,
+ },
+ .dev = &memory,
+
+ .bEndpointAddress = USB_DIR_IN | 0xc,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+
+ .ep_type = ep_interrupt,
+ .fifo = (unsigned int) S3C_UDC_OTG_EP12_FIFO,
+ },
+ .ep[13] = {
+ .ep = {
+ .name = "ep13-bulk",
+ .ops = &s3c_ep_ops,
+ .maxpacket = EP_FIFO_SIZE,
+ },
+ .dev = &memory,
+
+ .bEndpointAddress = USB_DIR_OUT | 0xd,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+
+ .ep_type = ep_bulk_out,
+ .fifo = (unsigned int) S3C_UDC_OTG_EP13_FIFO,
+ },
+ .ep[14] = {
+ .ep = {
+ .name = "ep14-bulk",
+ .ops = &s3c_ep_ops,
+ .maxpacket = EP_FIFO_SIZE,
+ },
+ .dev = &memory,
+
+ .bEndpointAddress = USB_DIR_IN | 0xe,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+
+ .ep_type = ep_bulk_in,
+ .fifo = (unsigned int) S3C_UDC_OTG_EP14_FIFO,
+ },
+ .ep[15] = {
+ .ep = {
+ .name = "ep15-iso",
+ .ops = &s3c_ep_ops,
+ .maxpacket = EP_FIFO_SIZE,
+ },
+ .dev = &memory,
+
+ .bEndpointAddress = USB_DIR_IN | 0xf,
+ .bmAttributes = USB_ENDPOINT_XFER_ISOC,
+
+ .ep_type = ep_isochronous,
+ .fifo = (unsigned int) S3C_UDC_OTG_EP15_FIFO,
+ },
+};
+
+#if defined CONFIG_USB_S3C_OTG_HOST || defined CONFIG_USB_DWC_OTG
+atomic_t g_OtgHostMode; // actual mode: client (0) or host (1)
+atomic_t g_OtgOperationMode; // operation mode: 'c'lient, 'h'ost, 'o'tg or 'a'uto-host
+atomic_t g_OtgLastCableState; // last cable state: detached (0), client attached (1), otg attached (2)
+atomic_t g_OtgDriver; // driver to use: 0: S3C High-speed, 1: S3C Low-speed/Full-speed, 2: DWC
+
+int s3c_is_otgmode(void)
+{
+ printk("otgmode = %d\n", atomic_read(&g_OtgHostMode));
+ return atomic_read(&g_OtgHostMode);
+}
+EXPORT_SYMBOL(s3c_is_otgmode);
+
+int s3c_get_drivermode(void)
+{
+ printk("drivermode = %d\n", atomic_read(&g_OtgDriver));
+ return atomic_read(&g_OtgDriver);
+}
+EXPORT_SYMBOL(s3c_get_drivermode);
+
+void set_otghost_mode(int mode) {
+//sztupy:
+// this function will determine what to do with the new information according to the current mode of operation
+// mode: 0: cable detached, 1: client cable attached, 2: otg cable attached, -1: operation config changed
+// modes of operation: c: always client, h: always host, g: otg mode (host if otg cable), a: automatic mode (host if cable plugged in)
+
+ struct s3c_udc *dev = the_controller;
+ int enable = 0;
+ int rval;
+ char opmode = atomic_read(&g_OtgOperationMode);
+ if (mode==-1) mode = atomic_read(&g_OtgLastCableState);
+ atomic_set(&g_OtgLastCableState, mode);
+ switch (opmode) {
+ case 'h': enable = 1; break;
+ case 'o': enable = (mode==2); break;
+ case 'a': enable = (mode>0); break;
+ default: atomic_set(&g_OtgOperationMode,'c'); enable = 0; break;
+ }
+
+ if (enable && !atomic_read(&g_OtgHostMode)) {
+ printk("Setting OTG host mode\n");
+ free_irq(IRQ_OTG, dev);
+ s3c_vbus_enable(&dev->gadget, 1);
+
+#if defined CONFIG_USB_S3C_OTG_HOST && defined CONFIG_USB_DWC_OTG
+ if (atomic_read(&g_OtgDriver) & USB_OTG_DRIVER_DWC) {
+ rval = platform_driver_register(&dwc_otg_driver);
+ } else {
+ rval = platform_driver_register(&s5pc110_otg_driver);
+ }
+ if (rval < 0)
+#elif defined CONFIG_USB_DWC_OTG
+ if (platform_driver_register(&dwc_otg_driver) < 0)
+#elif defined CONFIG_USB_S3C_OTG_HOST
+ if (platform_driver_register(&s5pc110_otg_driver) < 0)
+#endif
+ {
+ printk("platform_driver_register failed...\n");
+ atomic_set(&g_OtgHostMode , 0);
+ } else {
+ printk("platform_driver_registered\n");
+ atomic_set(&g_OtgHostMode , atomic_read(&g_OtgDriver)+1);
+ }
+ } else if (!enable && atomic_read(&g_OtgHostMode)) {
+// sztupy: also handle the disabling here
+ printk("Disabling OTG host mode\n");
+ s3c_vbus_enable(&dev->gadget, 0);
+#if defined CONFIG_USB_S3C_OTG_HOST && defined CONFIG_USB_DWC_OTG
+ if ((atomic_read(&g_OtgHostMode)-1) & USB_OTG_DRIVER_DWC) {
+ platform_driver_unregister(&dwc_otg_driver);
+ } else {
+ platform_driver_unregister(&s5pc110_otg_driver);
+ }
+#elif defined CONFIG_USB_S3C_OTG_HOST
+ platform_driver_unregister(&s5pc110_otg_driver);
+#elif defined CONFIG_USB_DWC_OTG
+ platform_driver_unregister(&dwc_otg_driver);
+#endif
+ printk("platform_driver_unregistered\n");
+ /* irq setup after old hardware state is cleaned up */
+ if (request_irq(IRQ_OTG, s3c_udc_irq, 0, driver_name, dev)) {
+ printk("Warning: Could not request IRQ for USB gadget!\n");
+ }
+ atomic_set(&g_OtgHostMode , 0);
+ } else {
+ printk("OTG: no changes needed\n");
+ }
+}
+
+EXPORT_SYMBOL(set_otghost_mode);
+
+static ssize_t usbmode_read(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ const char *msg = "client";
+ const char *msg2 = "disconnected";
+ const char *msg3 = "gadget";
+ switch(atomic_read(&g_OtgOperationMode)) {
+ case 'o': msg = "otg"; break;
+ case 'h': msg = "host"; break;
+ case 'a': msg = "auto-host"; break;
+ }
+ switch(atomic_read(&g_OtgLastCableState)) {
+ case 1: msg2 = "usb connected"; break;
+ case 2: msg2 = "otg connected"; break;
+ }
+ switch(atomic_read(&g_OtgHostMode)) {
+ case USB_OTG_DRIVER_S3CHS: msg3 = "host (S3C/HS)"; break;
+ case USB_OTG_DRIVER_S3CFSLS: msg3 = "host (S3C/FSLS)"; break;
+ case USB_OTG_DRIVER_DWC: msg3 = "host (DWC)"; break;
+ }
+
+ return sprintf(buf,"%s (cable: %s; state: %s)\n", msg, msg2, msg3);
+}
+
+static ssize_t usbmode_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ char c;
+ printk("input data --> %s", buf);
+ c = buf[0];
+ switch(c) {
+ case 'a': atomic_set(&g_OtgOperationMode, 'a'); set_otghost_mode(-1);break;
+ case 'h': atomic_set(&g_OtgOperationMode, 'h'); set_otghost_mode(-1);break;
+ case 'c': atomic_set(&g_OtgOperationMode, 'c'); set_otghost_mode(-1);break;
+ case 'o': atomic_set(&g_OtgOperationMode, 'o'); set_otghost_mode(-1);break;
+ default: printk("Invalid input data\n");
+ }
+ return size;
+}
+
+static ssize_t usbdriver_read(struct device *dev, struct device_attribute *attr, char *buf) {
+ const char *msg = "h:S3C driver (high-speed)";
+ switch(atomic_read(&g_OtgDriver)) {
+ case USB_OTG_DRIVER_S3CFSLS: msg = "l:S3C driver (low-speed / full-speed)";break;
+ case USB_OTG_DRIVER_DWC: msg = "d:DWC driver";break;
+ }
+ return sprintf(buf,"%s\n",msg);
+}
+
+static ssize_t usbdriver_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) {
+ char c;
+ printk("input data --> %s", buf);
+ c = buf[0];
+ switch(c) {
+#if defined CONFIG_USB_S3C_OTG_HOST
+ case 'h': atomic_set(&g_OtgDriver, USB_OTG_DRIVER_S3CHS); break;
+ case 'l': atomic_set(&g_OtgDriver, USB_OTG_DRIVER_S3CFSLS); break;
+#endif
+#if defined CONFIG_USB_DWC_OTG
+ case 'd': atomic_set(&g_OtgDriver, USB_OTG_DRIVER_DWC); break;
+#endif
+ default: printk("Invalid input data\n");
+ }
+ return size;
+
+}
+
+static ssize_t usbversion_read(struct device *dev, struct device_attribute *attr, char *buf) {
+ return sprintf(buf,"version: build 5\ndrivers:%s%s\n",
+#if defined CONFIG_USB_S3C_OTG_HOST
+ " S3CHS S3CFSLS"
+#else
+ ""
+#endif
+ ,
+#if defined CONFIG_USB_DWC_OTG
+ " DWC"
+#else
+ ""
+#endif
+ );
+}
+
+// kevinh - Allow changing USB host/target modes on S3C android devices without a special cable
+static DEVICE_ATTR(opmode, S_IRUGO | S_IWUSR, usbmode_read, usbmode_write);
+// sztupy - add some more attributes
+static DEVICE_ATTR(hostdriver, S_IRUGO | S_IWUSR, usbdriver_read, usbdriver_write);
+static DEVICE_ATTR(version, S_IRUGO, usbversion_read, NULL);
+#endif
+
+/*
+ * probe - binds to the platform device
+ */
+static int s3c_udc_probe(struct platform_device *pdev)
+{
+ struct s3c_udc *dev = &memory;
+ int retval;
+ DEBUG("%s: %p\n", __func__, pdev);
+
+ spin_lock_init(&dev->lock);
+ dev->dev = pdev;
+
+ device_initialize(&dev->gadget.dev);
+ dev->gadget.dev.parent = &pdev->dev;
+
+ dev->gadget.is_dualspeed = 1; /* Hack only*/
+ dev->gadget.is_otg = 0;
+ dev->gadget.is_a_peripheral = 0;
+ dev->gadget.b_hnp_enable = 0;
+ dev->gadget.a_hnp_support = 0;
+ dev->gadget.a_alt_hnp_support = 0;
+
+ dev->udc_vcc_d = regulator_get(&pdev->dev, "pd_io");
+ dev->udc_vcc_a = regulator_get(&pdev->dev, "pd_core");
+ if (IS_ERR(dev->udc_vcc_d) || IS_ERR(dev->udc_vcc_a)) {
+ printk(KERN_ERR "failed to find udc vcc source\n");
+ return -ENOENT;
+ }
+
+ the_controller = dev;
+ platform_set_drvdata(pdev, dev);
+
+ dev_set_name(&dev->gadget.dev, "gadget");
+ otg_clock = clk_get(&pdev->dev, "otg");
+ if (otg_clock == NULL) {
+ printk(KERN_ERR "failed to find otg clock source\n");
+ return -ENOENT;
+ }
+
+ udc_reinit(dev);
+
+ /* irq setup after old hardware state is cleaned up */
+ retval =
+ request_irq(IRQ_OTG, s3c_udc_irq, 0, driver_name, dev);
+
+ if (retval != 0) {
+ DEBUG(KERN_ERR "%s: can't get irq %i, err %d\n", driver_name,
+ IRQ_OTG, retval);
+ return -EBUSY;
+ }
+
+ disable_irq(IRQ_OTG);
+ create_proc_files();
+#if defined CONFIG_USB_S3C_OTG_HOST || defined CONFIG_USB_DWC_OTG
+ if (device_create_file(&pdev->dev, &dev_attr_opmode) < 0)
+ printk("Failed to create device file(%s)!\n", dev_attr_opmode.attr.name);
+ if (device_create_file(&pdev->dev, &dev_attr_hostdriver) < 0)
+ printk("Failed to create device file(%s)!\n", dev_attr_hostdriver.attr.name);
+ if (device_create_file(&pdev->dev, &dev_attr_version) < 0)
+ printk("Failed to create device file(%s)!\n", dev_attr_version.attr.name);
+#if !defined CONFIG_USB_S3C_OTG_HOST
+ atomic_set(&g_OtgDriver, USB_OTG_DRIVER_DWC);
+#endif
+#endif
+ return retval;
+}
+
+static int s3c_udc_remove(struct platform_device *pdev)
+{
+ struct s3c_udc *dev = platform_get_drvdata(pdev);
+
+ DEBUG("%s: %p\n", __func__, pdev);
+
+ if (otg_clock != NULL) {
+ clk_disable(otg_clock);
+ clk_put(otg_clock);
+ otg_clock = NULL;
+ }
+
+ remove_proc_files();
+ usb_gadget_unregister_driver(dev->driver);
+
+ free_irq(IRQ_OTG, dev);
+
+ platform_set_drvdata(pdev, 0);
+
+ the_controller = 0;
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int s3c_udc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct s3c_udc *dev = the_controller;
+
+ disable_irq(IRQ_OTG);
+
+ if (dev->driver && dev->driver->suspend)
+ dev->driver->suspend(&dev->gadget);
+
+ if (dev->udc_enabled)
+ usb_gadget_vbus_disconnect(&dev->gadget);
+
+ return 0;
+}
+
+static int s3c_udc_resume(struct platform_device *pdev)
+{
+ struct s3c_udc *dev = the_controller;
+
+ if (dev->driver && dev->driver->resume)
+ dev->driver->resume(&dev->gadget);
+
+ enable_irq(IRQ_OTG);
+
+ return 0;
+}
+#else
+#define s3c_udc_suspend NULL
+#define s3c_udc_resume NULL
+#endif /* CONFIG_PM */
+
+/*-------------------------------------------------------------------------*/
+static struct platform_driver s3c_udc_driver = {
+ .probe = s3c_udc_probe,
+ .remove = s3c_udc_remove,
+ .suspend = s3c_udc_suspend,
+ .resume = s3c_udc_resume,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "s3c-usbgadget",
+ },
+};
+
+static int __init udc_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&s3c_udc_driver);
+ if (!ret)
+ printk(KERN_INFO "%s : %s\n"
+ "%s : version %s %s\n",
+ driver_name, DRIVER_DESC,
+ driver_name, DRIVER_VERSION, OTG_DMA_MODE ?
+ "(DMA Mode)" : "(Slave Mode)");
+
+ return ret;
+}
+
+static void __exit udc_exit(void)
+{
+ platform_driver_unregister(&s3c_udc_driver);
+ printk(KERN_INFO "Unloaded %s version %s\n",
+ driver_name, DRIVER_VERSION);
+}
+
+module_init(udc_init);
+module_exit(udc_exit);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Samsung");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/s3c_udc_otg_xfer_dma.c b/drivers/usb/gadget/s3c_udc_otg_xfer_dma.c
new file mode 100644
index 0000000..70cf602
--- /dev/null
+++ b/drivers/usb/gadget/s3c_udc_otg_xfer_dma.c
@@ -0,0 +1,1387 @@
+/*
+ * drivers/usb/gadget/s3c_udc_otg_xfer_dma.c
+ * Samsung S3C on-chip full/high speed USB OTG 2.0 device controllers
+ *
+ * Copyright (C) 2009 for Samsung Electronics
+ *
+ *
+ * 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
+ *
+ */
+
+#define GINTMSK_INIT (INT_OUT_EP|INT_IN_EP|INT_RESUME|INT_ENUMDONE|INT_RESET|INT_SUSPEND)
+#define DOEPMSK_INIT (CTRL_OUT_EP_SETUP_PHASE_DONE|AHB_ERROR|TRANSFER_DONE)
+#define DIEPMSK_INIT (NON_ISO_IN_EP_TIMEOUT|AHB_ERROR|TRANSFER_DONE)
+#define GAHBCFG_INIT (PTXFE_HALF|NPTXFE_HALF|MODE_DMA|BURST_INCR4|GBL_INT_UNMASK)
+
+#define DMA_ADDR_INVALID (~(dma_addr_t)0)
+
+static u8 clear_feature_num;
+static int clear_feature_flag;
+static int set_conf_done;
+
+/* Bulk-Only Mass Storage Reset (class-specific request) */
+#define GET_MAX_LUN_REQUEST 0xFE
+#define BOT_RESET_REQUEST 0xFF
+
+/* TEST MODE in set_feature request */
+#define TEST_SELECTOR_MASK 0xFF
+#define TEST_PKT_SIZE 53
+
+static u8 test_pkt[TEST_PKT_SIZE] __attribute__((aligned(8))) = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* JKJKJKJK x 9 */
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, /* JJKKJJKK x 8 */
+ 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, /* JJJJKKKK x 8 */
+ 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* JJJJJJJKKKKKKK x 8 - '1' */
+ 0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, /* '1' + JJJJJJJK x 8 */
+ 0xFC, 0x7E, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0x7E /* {JKKKKKKK x 10}, JK */
+};
+
+void s3c_udc_ep_set_stall(struct s3c_ep *ep);
+
+#if defined(CONFIG_MACH_SMDKC110) || defined(CONFIG_MACH_SMDKV210)
+extern void s3c_cable_check_status(int flag);
+
+void s3c_udc_cable_connect(struct s3c_udc *dev)
+{
+ s3c_cable_check_status(1);
+}
+
+void s3c_udc_cable_disconnect(struct s3c_udc *dev)
+{
+ s3c_cable_check_status(0);
+}
+#endif
+
+static inline void s3c_udc_ep0_zlp(void)
+{
+ u32 ep_ctrl;
+
+ writel(virt_to_phys(&usb_ctrl), S3C_UDC_OTG_DIEPDMA(EP0_CON));
+ writel((1<<19 | 0<<0), S3C_UDC_OTG_DIEPTSIZ(EP0_CON));
+
+ ep_ctrl = readl(S3C_UDC_OTG_DIEPCTL(EP0_CON));
+ writel(ep_ctrl|DEPCTL_EPENA|DEPCTL_CNAK, S3C_UDC_OTG_DIEPCTL(EP0_CON));
+
+ DEBUG_EP0("%s:EP0 ZLP DIEPCTL0 = 0x%x\n",
+ __func__, readl(S3C_UDC_OTG_DIEPCTL(EP0_CON)));
+}
+
+static inline void s3c_udc_pre_setup(void)
+{
+ u32 ep_ctrl;
+
+ DEBUG_IN_EP("%s : Prepare Setup packets.\n", __func__);
+
+ writel((1 << 19)|sizeof(struct usb_ctrlrequest), S3C_UDC_OTG_DOEPTSIZ(EP0_CON));
+ writel(virt_to_phys(&usb_ctrl), S3C_UDC_OTG_DOEPDMA(EP0_CON));
+
+ ep_ctrl = readl(S3C_UDC_OTG_DOEPCTL(EP0_CON));
+ writel(ep_ctrl|DEPCTL_EPENA|DEPCTL_CNAK, S3C_UDC_OTG_DOEPCTL(EP0_CON));
+}
+
+static int setdma_rx(struct s3c_ep *ep, struct s3c_request *req)
+{
+ u32 *buf, ctrl;
+ u32 length, pktcnt;
+ u32 ep_num = ep_index(ep);
+
+ struct device *dev = &the_controller->dev->dev;
+ buf = req->req.buf + req->req.actual;
+ prefetchw(buf);
+
+ length = req->req.length - req->req.actual;
+ req->req.dma = dma_map_single(dev, buf,
+ length, DMA_FROM_DEVICE);
+ req->mapped = 1;
+
+ if (length == 0)
+ pktcnt = 1;
+ else
+ pktcnt = (length - 1)/(ep->ep.maxpacket) + 1;
+
+ ctrl = readl(S3C_UDC_OTG_DOEPCTL(ep_num));
+
+ writel(virt_to_phys(buf), S3C_UDC_OTG_DOEPDMA(ep_num));
+ writel((pktcnt<<19)|(length<<0), S3C_UDC_OTG_DOEPTSIZ(ep_num));
+ writel(DEPCTL_EPENA|DEPCTL_CNAK|ctrl, S3C_UDC_OTG_DOEPCTL(ep_num));
+
+ DEBUG_OUT_EP("%s: EP%d RX DMA start : DOEPDMA = 0x%x, DOEPTSIZ = 0x%x, DOEPCTL = 0x%x\n"
+ "\tbuf = 0x%p, pktcnt = %d, xfersize = %d\n",
+ __func__, ep_num,
+ readl(S3C_UDC_OTG_DOEPDMA(ep_num)),
+ readl(S3C_UDC_OTG_DOEPTSIZ(ep_num)),
+ readl(S3C_UDC_OTG_DOEPCTL(ep_num)),
+ buf, pktcnt, length);
+ return 0;
+
+}
+
+static int setdma_tx(struct s3c_ep *ep, struct s3c_request *req)
+{
+ u32 *buf, ctrl = 0;
+ u32 length, pktcnt;
+ u32 ep_num = ep_index(ep);
+ struct device *dev = &the_controller->dev->dev;
+
+ buf = req->req.buf + req->req.actual;
+ prefetch(buf);
+ length = req->req.length - req->req.actual;
+
+ if (ep_num == EP0_CON)
+ length = min(length, (u32)ep_maxpacket(ep));
+
+ req->req.actual += length;
+ req->req.dma = dma_map_single(dev, buf,
+ length, DMA_TO_DEVICE);
+ req->mapped = 1;
+
+ if (length == 0)
+ pktcnt = 1;
+ else
+ pktcnt = (length - 1)/(ep->ep.maxpacket) + 1;
+
+#ifdef DED_TX_FIFO
+ /* Write the FIFO number to be used for this endpoint */
+ ctrl = readl(S3C_UDC_OTG_DIEPCTL(ep_num));
+ ctrl &= ~DEPCTL_TXFNUM_MASK;;
+ ctrl |= (ep_num << DEPCTL_TXFNUM_BIT);
+ writel(ctrl , S3C_UDC_OTG_DIEPCTL(ep_num));
+#endif
+
+ writel(virt_to_phys(buf), S3C_UDC_OTG_DIEPDMA(ep_num));
+ writel((pktcnt<<19)|(length<<0), S3C_UDC_OTG_DIEPTSIZ(ep_num));
+ ctrl = readl(S3C_UDC_OTG_DIEPCTL(ep_num));
+ if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC)
+ ctrl |= DEPCTL_SET_ODD_FRM;
+ writel(DEPCTL_EPENA|DEPCTL_CNAK|ctrl, S3C_UDC_OTG_DIEPCTL(ep_num));
+
+ DEBUG_IN_EP("%s:EP%d TX DMA start : DIEPDMA0 = 0x%x, DIEPTSIZ0 = 0x%x, DIEPCTL0 = 0x%x\n"
+ "\tbuf = 0x%p, pktcnt = %d, xfersize = %d\n",
+ __func__, ep_num,
+ readl(S3C_UDC_OTG_DIEPDMA(ep_num)),
+ readl(S3C_UDC_OTG_DIEPTSIZ(ep_num)),
+ readl(S3C_UDC_OTG_DIEPCTL(ep_num)),
+ buf, pktcnt, length);
+
+ return length;
+}
+
+static void complete_rx(struct s3c_udc *dev, u8 ep_num)
+{
+ struct s3c_ep *ep = &dev->ep[ep_num];
+ struct s3c_request *req = NULL;
+ u32 ep_tsr = 0, xfer_size = 0, xfer_length, is_short = 0;
+
+ if (list_empty(&ep->queue)) {
+ DEBUG_OUT_EP("%s: RX DMA done : NULL REQ on OUT EP-%d\n",
+ __func__, ep_num);
+ return;
+
+ }
+
+ req = list_entry(ep->queue.next, struct s3c_request, queue);
+
+ ep_tsr = readl(S3C_UDC_OTG_DOEPTSIZ(ep_num));
+
+ if (ep_num == EP0_CON)
+ xfer_size = (ep_tsr & 0x7f);
+
+ else
+ xfer_size = (ep_tsr & 0x7fff);
+
+ __dma_single_cpu_to_dev(req->req.buf, req->req.length, DMA_FROM_DEVICE);
+ xfer_length = req->req.length - xfer_size;
+ req->req.actual += min(xfer_length, req->req.length - req->req.actual);
+ is_short = (xfer_length < ep->ep.maxpacket);
+
+ DEBUG_OUT_EP("%s: RX DMA done : ep = %d, rx bytes = %d/%d, "
+ "is_short = %d, DOEPTSIZ = 0x%x, remained bytes = %d\n",
+ __func__, ep_num, req->req.actual, req->req.length,
+ is_short, ep_tsr, xfer_size);
+
+ if (is_short || req->req.actual == xfer_length) {
+ if (ep_num == EP0_CON && dev->ep0state == DATA_STATE_RECV) {
+ DEBUG_OUT_EP(" => Send ZLP\n");
+ dev->ep0state = WAIT_FOR_SETUP;
+ s3c_udc_ep0_zlp();
+
+ } else {
+ done(ep, req, 0);
+
+ if (!list_empty(&ep->queue)) {
+ req = list_entry(ep->queue.next, struct s3c_request, queue);
+ DEBUG_OUT_EP("%s: Next Rx request start...\n", __func__);
+ setdma_rx(ep, req);
+ }
+ }
+ }
+}
+
+static void complete_tx(struct s3c_udc *dev, u8 ep_num)
+{
+ struct s3c_ep *ep = &dev->ep[ep_num];
+ struct s3c_request *req;
+ u32 ep_tsr = 0, xfer_size = 0, xfer_length, is_short = 0;
+ u32 last;
+
+ if (list_empty(&ep->queue)) {
+ DEBUG_IN_EP("%s: TX DMA done : NULL REQ on IN EP-%d\n",
+ __func__, ep_num);
+ return;
+
+ }
+
+ req = list_entry(ep->queue.next, struct s3c_request, queue);
+
+ if (dev->ep0state == DATA_STATE_XMIT) {
+ DEBUG_IN_EP("%s: ep_num = %d, ep0stat == DATA_STATE_XMIT\n",
+ __func__, ep_num);
+
+ last = write_fifo_ep0(ep, req);
+
+ if (last)
+ dev->ep0state = WAIT_FOR_SETUP;
+
+ return;
+ }
+
+ ep_tsr = readl(S3C_UDC_OTG_DIEPTSIZ(ep_num));
+
+ if (ep_num == EP0_CON)
+ xfer_size = (ep_tsr & 0x7f);
+ else
+ xfer_size = (ep_tsr & 0x7fff);
+
+ req->req.actual = req->req.length - xfer_size;
+ xfer_length = req->req.length - xfer_size;
+ req->req.actual += min(xfer_length, req->req.length - req->req.actual);
+ is_short = (xfer_length < ep->ep.maxpacket);
+
+ DEBUG_IN_EP("%s: TX DMA done : ep = %d, tx bytes = %d/%d, "
+ "is_short = %d, DIEPTSIZ = 0x%x, remained bytes = %d\n",
+ __func__, ep_num, req->req.actual, req->req.length,
+ is_short, ep_tsr, xfer_size);
+
+ if (req->req.actual == req->req.length) {
+ done(ep, req, 0);
+
+ if (!list_empty(&ep->queue)) {
+ req = list_entry(ep->queue.next, struct s3c_request, queue);
+ DEBUG_IN_EP("%s: Next Tx request start...\n", __func__);
+ setdma_tx(ep, req);
+ }
+ }
+}
+static inline void s3c_udc_check_tx_queue(struct s3c_udc *dev, u8 ep_num)
+{
+ struct s3c_ep *ep = &dev->ep[ep_num];
+ struct s3c_request *req;
+
+ DEBUG_IN_EP("%s: Check queue, ep_num = %d\n", __func__, ep_num);
+
+ if (!list_empty(&ep->queue)) {
+ req = list_entry(ep->queue.next, struct s3c_request, queue);
+ DEBUG_IN_EP("%s: Next Tx request(0x%p) start...\n", __func__, req);
+
+ if (ep_is_in(ep))
+ setdma_tx(ep, req);
+ else
+ setdma_rx(ep, req);
+ } else {
+ DEBUG_IN_EP("%s: NULL REQ on IN EP-%d\n", __func__, ep_num);
+
+ return;
+ }
+
+}
+
+static void process_ep_in_intr(struct s3c_udc *dev)
+{
+ u32 ep_intr, ep_intr_status;
+ u8 ep_num = 0;
+
+ ep_intr = readl(S3C_UDC_OTG_DAINT);
+ DEBUG_IN_EP("*** %s: EP In interrupt : DAINT = 0x%x\n",
+ __func__, ep_intr);
+
+ ep_intr &= DAINT_MASK;
+
+ while (ep_intr) {
+ if (ep_intr & 0x1) {
+ ep_intr_status = readl(S3C_UDC_OTG_DIEPINT(ep_num));
+ DEBUG_IN_EP("\tEP%d-IN : DIEPINT = 0x%x\n",
+ ep_num, ep_intr_status);
+
+ /* Interrupt Clear */
+ writel(ep_intr_status, S3C_UDC_OTG_DIEPINT(ep_num));
+
+ if (ep_intr_status & TRANSFER_DONE) {
+ complete_tx(dev, ep_num);
+
+ if (ep_num == 0) {
+ if (dev->ep0state == WAIT_FOR_SETUP)
+ s3c_udc_pre_setup();
+
+ /* continue transfer after set_clear_halt for DMA mode */
+ if (clear_feature_flag == 1) {
+ s3c_udc_check_tx_queue(dev, clear_feature_num);
+ clear_feature_flag = 0;
+ }
+ }
+ }
+ }
+ ep_num++;
+ ep_intr >>= 1;
+ }
+
+}
+
+static void process_ep_out_intr(struct s3c_udc *dev)
+{
+ u32 ep_intr, ep_intr_status, ep_ctrl;
+ u8 ep_num = 0;
+
+ ep_intr = readl(S3C_UDC_OTG_DAINT);
+ DEBUG_OUT_EP("*** %s: EP OUT interrupt : DAINT = 0x%x\n",
+ __func__, ep_intr);
+
+ ep_intr = (ep_intr >> DAINT_OUT_BIT) & DAINT_MASK;
+
+ while (ep_intr) {
+ if (ep_intr & 0x1) {
+ ep_intr_status = readl(S3C_UDC_OTG_DOEPINT(ep_num));
+ DEBUG_OUT_EP("\tEP%d-OUT : DOEPINT = 0x%x\n",
+ ep_num, ep_intr_status);
+
+ /* Interrupt Clear */
+ writel(ep_intr_status, S3C_UDC_OTG_DOEPINT(ep_num));
+
+ if (ep_num == 0) {
+ if (ep_intr_status & CTRL_OUT_EP_SETUP_PHASE_DONE) {
+ DEBUG_OUT_EP("\tSETUP packet(transaction) arrived\n");
+ s3c_handle_ep0(dev);
+ }
+
+ if (ep_intr_status & TRANSFER_DONE) {
+ complete_rx(dev, ep_num);
+
+ writel((3<<29)|(1<<19)|sizeof(struct usb_ctrlrequest),
+ S3C_UDC_OTG_DOEPTSIZ(EP0_CON));
+ writel(virt_to_phys(&usb_ctrl),
+ S3C_UDC_OTG_DOEPDMA(EP0_CON));
+
+ ep_ctrl = readl(S3C_UDC_OTG_DOEPCTL(EP0_CON));
+ writel(ep_ctrl|DEPCTL_EPENA|DEPCTL_SNAK,
+ S3C_UDC_OTG_DOEPCTL(EP0_CON));
+ }
+
+ } else {
+ if (ep_intr_status & TRANSFER_DONE)
+ complete_rx(dev, ep_num);
+ }
+ }
+ ep_num++;
+ ep_intr >>= 1;
+ }
+}
+
+/*
+ * usb client interrupt handler.
+ */
+static irqreturn_t s3c_udc_irq(int irq, void *_dev)
+{
+ struct s3c_udc *dev = _dev;
+ u32 intr_status;
+ u32 usb_status, gintmsk;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dev->lock, flags);
+
+ intr_status = readl(S3C_UDC_OTG_GINTSTS);
+ gintmsk = readl(S3C_UDC_OTG_GINTMSK);
+
+ DEBUG_ISR("\n*** %s : GINTSTS=0x%x(on state %s), GINTMSK : 0x%x, DAINT : 0x%x, DAINTMSK : 0x%x\n",
+ __func__, intr_status, state_names[dev->ep0state], gintmsk,
+ readl(S3C_UDC_OTG_DAINT), readl(S3C_UDC_OTG_DAINTMSK));
+
+ if (!intr_status) {
+ spin_unlock_irqrestore(&dev->lock, flags);
+ return IRQ_HANDLED;
+ }
+
+ if (intr_status & INT_ENUMDONE) {
+ DEBUG_ISR("\tSpeed Detection interrupt\n");
+
+ writel(INT_ENUMDONE, S3C_UDC_OTG_GINTSTS);
+ usb_status = (readl(S3C_UDC_OTG_DSTS) & 0x6);
+
+ if (usb_status & (USB_FULL_30_60MHZ | USB_FULL_48MHZ)) {
+ DEBUG_ISR("\t\tFull Speed Detection\n");
+ set_max_pktsize(dev, USB_SPEED_FULL);
+
+ } else {
+ DEBUG_ISR("\t\tHigh Speed Detection : 0x%x\n", usb_status);
+ set_max_pktsize(dev, USB_SPEED_HIGH);
+ }
+ }
+
+ if (intr_status & INT_EARLY_SUSPEND) {
+ DEBUG_ISR("\tEarly suspend interrupt\n");
+ writel(INT_EARLY_SUSPEND, S3C_UDC_OTG_GINTSTS);
+ }
+
+ if (intr_status & INT_SUSPEND) {
+ usb_status = readl(S3C_UDC_OTG_DSTS);
+ DEBUG_ISR("\tSuspend interrupt :(DSTS):0x%x\n", usb_status);
+ writel(INT_SUSPEND, S3C_UDC_OTG_GINTSTS);
+
+ if (dev->gadget.speed != USB_SPEED_UNKNOWN
+ && dev->driver
+ && dev->driver->suspend) {
+ spin_unlock(&dev->lock);
+ dev->driver->suspend(&dev->gadget);
+ spin_lock(&dev->lock);
+ }
+ if (dev->status & (1 << USB_DEVICE_REMOTE_WAKEUP)) {
+ DEBUG_ISR("device is under remote wakeup\n");
+ spin_unlock_irqrestore(&dev->lock, flags);
+ return IRQ_HANDLED;
+ }
+ if (dev->driver) {
+ spin_unlock(&dev->lock);
+ dev->driver->disconnect(&dev->gadget);
+ spin_lock(&dev->lock);
+ }
+#if defined(CONFIG_MACH_SMDKC110) || defined(CONFIG_MACH_SMDKV210)
+ s3c_udc_cable_disconnect(dev);
+#endif
+ }
+
+ if (intr_status & INT_RESUME) {
+ DEBUG_ISR("\tResume interrupt\n");
+ writel(INT_RESUME, S3C_UDC_OTG_GINTSTS);
+
+ if (dev->gadget.speed != USB_SPEED_UNKNOWN
+ && dev->driver
+ && dev->driver->resume) {
+
+ dev->driver->resume(&dev->gadget);
+ }
+ }
+
+ if (intr_status & INT_RESET) {
+ usb_status = readl(S3C_UDC_OTG_GOTGCTL);
+ DEBUG_ISR("\tReset interrupt - (GOTGCTL):0x%x\n", usb_status);
+ writel(INT_RESET, S3C_UDC_OTG_GINTSTS);
+
+ set_conf_done = 0;
+
+ if ((usb_status & 0xc0000) == (0x3 << 18)) {
+ if (reset_available) {
+ DEBUG_ISR("\t\tOTG core got reset (%d)!!\n", reset_available);
+ stop_activity(dev, dev->driver);
+ reconfig_usbd();
+ dev->ep0state = WAIT_FOR_SETUP;
+ reset_available = 0;
+ s3c_udc_pre_setup();
+ }
+ } else if (!(usb_status & B_SESSION_VALID)) {
+ reset_available = 1;
+ if (dev->udc_enabled) {
+ DEBUG_ISR("Reset without B_SESSION\n");
+ if (dev->driver) {
+ spin_unlock(&dev->lock);
+ dev->driver->disconnect(&dev->gadget);
+ spin_lock(&dev->lock);
+ }
+ }
+ } else {
+ reset_available = 1;
+ DEBUG_ISR("\t\tRESET handling skipped\n");
+ }
+ }
+
+ if (intr_status & INT_IN_EP)
+ process_ep_in_intr(dev);
+
+ if (intr_status & INT_OUT_EP)
+ process_ep_out_intr(dev);
+
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+ return IRQ_HANDLED;
+}
+
+/** Queue one request
+ * Kickstart transfer if needed
+ */
+static int s3c_queue(struct usb_ep *_ep, struct usb_request *_req,
+ gfp_t gfp_flags)
+{
+ struct s3c_request *req;
+ struct s3c_ep *ep;
+ struct s3c_udc *dev;
+ unsigned long flags;
+ u32 ep_num, gintsts;
+
+ req = container_of(_req, struct s3c_request, req);
+ if (unlikely(!_req || !_req->complete || !_req->buf || !list_empty(&req->queue))) {
+
+ DEBUG("%s: bad params\n", __func__);
+ return -EINVAL;
+ }
+
+ ep = container_of(_ep, struct s3c_ep, ep);
+
+ if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) {
+
+ DEBUG("%s: bad ep\n", __func__);
+ return -EINVAL;
+ }
+
+ ep_num = ep_index(ep);
+ dev = ep->dev;
+ if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)) {
+
+ DEBUG("%s: bogus device state %p\n", __func__, dev->driver);
+ return -ESHUTDOWN;
+ }
+
+ spin_lock_irqsave(&dev->lock, flags);
+
+ _req->status = -EINPROGRESS;
+ _req->actual = 0;
+
+ /* kickstart this i/o queue? */
+ DEBUG("\n*** %s: %s-%s req = %p, len = %d, buf = %p"
+ "Q empty = %d, stopped = %d\n",
+ __func__, _ep->name, ep_is_in(ep) ? "in" : "out",
+ _req, _req->length, _req->buf,
+ list_empty(&ep->queue), ep->stopped);
+
+ if (list_empty(&ep->queue) && !ep->stopped) {
+
+ if (ep_num == 0) {
+ /* EP0 */
+ list_add_tail(&req->queue, &ep->queue);
+ s3c_ep0_kick(dev, ep);
+ req = 0;
+
+ } else if (ep_is_in(ep)) {
+ gintsts = readl(S3C_UDC_OTG_GINTSTS);
+ DEBUG_IN_EP("%s: ep_is_in, S3C_UDC_OTG_GINTSTS=0x%x\n",
+ __func__, gintsts);
+
+ if (set_conf_done == 1) {
+ setdma_tx(ep, req);
+ } else {
+ done(ep, req, 0);
+ DEBUG("%s: Not yet Set_configureation, ep_num = %d, req = %p\n",
+ __func__, ep_num, req);
+ req = 0;
+ }
+
+ } else {
+ gintsts = readl(S3C_UDC_OTG_GINTSTS);
+ DEBUG_OUT_EP("%s: ep_is_out, S3C_UDC_OTG_GINTSTS=0x%x\n",
+ __func__, gintsts);
+
+ setdma_rx(ep, req);
+ }
+ }
+
+ /* pio or dma irq handler advances the queue. */
+ if (likely(req != 0))
+ list_add_tail(&req->queue, &ep->queue);
+
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+ return 0;
+}
+
+/****************************************************************/
+/* End Point 0 related functions */
+/****************************************************************/
+
+/* return: 0 = still running, 1 = completed, negative = errno */
+static int write_fifo_ep0(struct s3c_ep *ep, struct s3c_request *req)
+{
+ u32 max;
+ unsigned count;
+ int is_last;
+
+ max = ep_maxpacket(ep);
+
+ DEBUG_EP0("%s: max = %d\n", __func__, max);
+
+ count = setdma_tx(ep, req);
+
+ /* last packet is usually short (or a zlp) */
+ if (likely(count != max))
+ is_last = 1;
+ else {
+ if (likely(req->req.length != req->req.actual) || req->req.zero)
+ is_last = 0;
+ else
+ is_last = 1;
+ }
+
+ DEBUG_EP0("%s: wrote %s %d bytes%s %d left %p\n", __func__,
+ ep->ep.name, count,
+ is_last ? "/L" : "", req->req.length - req->req.actual, req);
+
+ /* requests complete when all IN data is in the FIFO */
+ if (is_last) {
+ ep->dev->ep0state = WAIT_FOR_SETUP;
+ return 1;
+ }
+
+ return 0;
+}
+
+static inline int s3c_fifo_read(struct s3c_ep *ep, u32 *cp, int max)
+{
+ u32 bytes;
+
+ bytes = sizeof(struct usb_ctrlrequest);
+ __dma_single_cpu_to_dev(&usb_ctrl, bytes, DMA_FROM_DEVICE);
+ DEBUG_EP0("%s: bytes=%d, ep_index=%d\n", __func__, bytes, ep_index(ep));
+
+ return bytes;
+}
+
+/**
+ * udc_set_address - set the USB address for this device
+ * @address:
+ *
+ * Called from control endpoint function
+ * after it decodes a set address setup packet.
+ */
+static void udc_set_address(struct s3c_udc *dev, unsigned char address)
+{
+ u32 ctrl = readl(S3C_UDC_OTG_DCFG);
+ writel(address << 4 | ctrl, S3C_UDC_OTG_DCFG);
+
+ s3c_udc_ep0_zlp();
+
+ DEBUG_EP0("%s: USB OTG 2.0 Device address=%d, DCFG=0x%x\n",
+ __func__, address, readl(S3C_UDC_OTG_DCFG));
+
+ dev->usb_address = address;
+}
+
+static inline void s3c_udc_ep0_set_stall(struct s3c_ep *ep)
+{
+ struct s3c_udc *dev;
+ u32 ep_ctrl = 0;
+
+ dev = ep->dev;
+ ep_ctrl = readl(S3C_UDC_OTG_DIEPCTL(EP0_CON));
+
+ /* set the disable and stall bits */
+ if (ep_ctrl & DEPCTL_EPENA)
+ ep_ctrl |= DEPCTL_EPDIS;
+
+ ep_ctrl |= DEPCTL_STALL;
+
+ writel(ep_ctrl, S3C_UDC_OTG_DIEPCTL(EP0_CON));
+
+ DEBUG_EP0("%s: set ep%d stall, DIEPCTL0 = 0x%x\n",
+ __func__, ep_index(ep), readl(S3C_UDC_OTG_DIEPCTL(EP0_CON)));
+ /*
+ * The application can only set this bit, and the core clears it,
+ * when a SETUP token is received for this endpoint
+ */
+ dev->ep0state = WAIT_FOR_SETUP;
+
+ s3c_udc_pre_setup();
+}
+
+static void s3c_ep0_read(struct s3c_udc *dev)
+{
+ struct s3c_request *req;
+ struct s3c_ep *ep = &dev->ep[0];
+ int ret;
+
+ if (!list_empty(&ep->queue)) {
+ req = list_entry(ep->queue.next, struct s3c_request, queue);
+
+ } else {
+ DEBUG("%s: ---> BUG\n", __func__);
+ BUG();
+ return;
+ }
+
+ DEBUG_EP0("%s: req = %p, req.length = 0x%x, req.actual = 0x%x\n",
+ __func__, req, req->req.length, req->req.actual);
+
+ if (req->req.length == 0) {
+ /* zlp for Set_configuration, Set_interface,
+ * or Bulk-Only mass storge reset */
+
+ dev->ep0state = WAIT_FOR_SETUP;
+ set_conf_done = 1;
+ s3c_udc_ep0_zlp();
+ done(ep, req, 0);
+ DEBUG_EP0("%s: req.length = 0, bRequest = %d\n", __func__, usb_ctrl.bRequest);
+ return;
+ }
+
+ ret = setdma_rx(ep, req);
+}
+
+/*
+ * DATA_STATE_XMIT
+ */
+static int s3c_ep0_write(struct s3c_udc *dev)
+{
+ struct s3c_request *req;
+ struct s3c_ep *ep = &dev->ep[0];
+ int ret, need_zlp = 0;
+
+ if (list_empty(&ep->queue))
+ req = 0;
+ else
+ req = list_entry(ep->queue.next, struct s3c_request, queue);
+
+ if (!req) {
+ DEBUG_EP0("%s: NULL REQ\n", __func__);
+ return 0;
+ }
+
+ DEBUG_EP0("%s: req = %p, req.length = 0x%x, req.actual = 0x%x\n",
+ __func__, req, req->req.length, req->req.actual);
+
+ if (req->req.length - req->req.actual == ep0_fifo_size) {
+ /* Next write will end with the packet size, */
+ /* so we need Zero-length-packet */
+ need_zlp = 1;
+ }
+
+ ret = write_fifo_ep0(ep, req);
+
+ if ((ret == 1) && !need_zlp) {
+ /* Last packet */
+ dev->ep0state = WAIT_FOR_SETUP;
+ DEBUG_EP0("%s: finished, waiting for status\n", __func__);
+
+ } else {
+ dev->ep0state = DATA_STATE_XMIT;
+ DEBUG_EP0("%s: not finished\n", __func__);
+ }
+
+ if (need_zlp) {
+ dev->ep0state = DATA_STATE_NEED_ZLP;
+ DEBUG_EP0("%s: Need ZLP!\n", __func__);
+ }
+
+ return 1;
+}
+
+u16 g_status __attribute__((aligned(8)));
+
+static int s3c_udc_get_status(struct s3c_udc *dev,
+ struct usb_ctrlrequest *crq)
+{
+ u8 ep_num = crq->wIndex & 0x7F;
+ u32 ep_ctrl;
+
+ DEBUG_SETUP("%s: *** USB_REQ_GET_STATUS\n", __func__);
+
+ switch (crq->bRequestType & USB_RECIP_MASK) {
+ case USB_RECIP_INTERFACE:
+ g_status = 0;
+ DEBUG_SETUP("\tGET_STATUS: USB_RECIP_INTERFACE, g_stauts = %d\n", g_status);
+ break;
+
+ case USB_RECIP_DEVICE:
+ /* update device status */
+ g_status = dev->status;
+ DEBUG_SETUP("\tGET_STATUS: USB_RECIP_DEVICE, g_stauts = %d\n", g_status);
+ break;
+
+ case USB_RECIP_ENDPOINT:
+ if (crq->wLength > 2) {
+ DEBUG_SETUP("\tGET_STATUS: Not support EP or wLength\n");
+ return 1;
+ }
+
+ g_status = dev->ep[ep_num].stopped;
+ DEBUG_SETUP("\tGET_STATUS: USB_RECIP_ENDPOINT, g_stauts = %d\n", g_status);
+
+ break;
+
+ default:
+ return 1;
+ }
+ __dma_single_cpu_to_dev(&g_status, 2, DMA_TO_DEVICE);
+
+ writel(virt_to_phys(&g_status), S3C_UDC_OTG_DIEPDMA(EP0_CON));
+ writel((1<<19)|(2<<0), S3C_UDC_OTG_DIEPTSIZ(EP0_CON));
+
+ ep_ctrl = readl(S3C_UDC_OTG_DIEPCTL(EP0_CON));
+ writel(ep_ctrl|DEPCTL_EPENA|DEPCTL_CNAK, S3C_UDC_OTG_DIEPCTL(EP0_CON));
+ dev->ep0state = WAIT_FOR_SETUP;
+
+ return 0;
+}
+
+void s3c_udc_ep_set_stall(struct s3c_ep *ep)
+{
+ u8 ep_num;
+ u32 ep_ctrl = 0;
+
+ ep_num = ep_index(ep);
+ DEBUG("%s: ep_num = %d, ep_type = %d\n", __func__, ep_num, ep->ep_type);
+
+ if (ep_is_in(ep)) {
+ ep_ctrl = readl(S3C_UDC_OTG_DIEPCTL(ep_num));
+
+ /* set the disable and stall bits */
+ if (ep_ctrl & DEPCTL_EPENA)
+ ep_ctrl |= DEPCTL_EPDIS;
+
+ ep_ctrl |= DEPCTL_STALL;
+
+ writel(ep_ctrl, S3C_UDC_OTG_DIEPCTL(ep_num));
+ DEBUG("%s: set stall, DIEPCTL%d = 0x%x\n",
+ __func__, ep_num, readl(S3C_UDC_OTG_DIEPCTL(ep_num)));
+
+ } else {
+ ep_ctrl = readl(S3C_UDC_OTG_DOEPCTL(ep_num));
+
+ /* set the stall bit */
+ ep_ctrl |= DEPCTL_STALL;
+
+ writel(ep_ctrl, S3C_UDC_OTG_DOEPCTL(ep_num));
+ DEBUG("%s: set stall, DOEPCTL%d = 0x%x\n",
+ __func__, ep_num, readl(S3C_UDC_OTG_DOEPCTL(ep_num)));
+ }
+
+ return;
+}
+
+void s3c_udc_ep_clear_stall(struct s3c_ep *ep)
+{
+ u8 ep_num;
+ u32 ep_ctrl = 0;
+
+ ep_num = ep_index(ep);
+ DEBUG("%s: ep_num = %d, ep_type = %d\n", __func__, ep_num, ep->ep_type);
+
+ if (ep_is_in(ep)) {
+ ep_ctrl = readl(S3C_UDC_OTG_DIEPCTL(ep_num));
+
+ /* clear stall bit */
+ ep_ctrl &= ~DEPCTL_STALL;
+
+ /*
+ * USB Spec 9.4.5: For endpoints using data toggle, regardless
+ * of whether an endpoint has the Halt feature set, a
+ * ClearFeature(ENDPOINT_HALT) request always results in the
+ * data toggle being reinitialized to DATA0.
+ */
+ if (ep->bmAttributes == USB_ENDPOINT_XFER_INT
+ || ep->bmAttributes == USB_ENDPOINT_XFER_BULK) {
+ ep_ctrl |= DEPCTL_SETD0PID; /* DATA0 */
+ }
+
+ writel(ep_ctrl, S3C_UDC_OTG_DIEPCTL(ep_num));
+ DEBUG("%s: cleared stall, DIEPCTL%d = 0x%x\n",
+ __func__, ep_num, readl(S3C_UDC_OTG_DIEPCTL(ep_num)));
+
+ } else {
+ ep_ctrl = readl(S3C_UDC_OTG_DOEPCTL(ep_num));
+
+ /* clear stall bit */
+ ep_ctrl &= ~DEPCTL_STALL;
+
+ if (ep->bmAttributes == USB_ENDPOINT_XFER_INT
+ || ep->bmAttributes == USB_ENDPOINT_XFER_BULK) {
+ ep_ctrl |= DEPCTL_SETD0PID; /* DATA0 */
+ }
+
+ writel(ep_ctrl, S3C_UDC_OTG_DOEPCTL(ep_num));
+ DEBUG("%s: cleared stall, DOEPCTL%d = 0x%x\n",
+ __func__, ep_num, readl(S3C_UDC_OTG_DOEPCTL(ep_num)));
+ }
+
+ return;
+}
+
+static int s3c_udc_set_halt(struct usb_ep *_ep, int value)
+{
+ struct s3c_ep *ep;
+ struct s3c_udc *dev;
+ unsigned long flags;
+ u8 ep_num;
+
+ ep = container_of(_ep, struct s3c_ep, ep);
+ ep_num = ep_index(ep);
+
+ if (unlikely(!_ep || !ep->desc || ep_num == EP0_CON ||
+ ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC)) {
+ DEBUG("%s: %s bad ep or descriptor\n", __func__, ep->ep.name);
+ return -EINVAL;
+ }
+
+ /* Attempt to halt IN ep will fail if any transfer requests
+ * are still queue */
+ if (value && ep_is_in(ep) && !list_empty(&ep->queue)) {
+ DEBUG("%s: %s queue not empty, req = %p\n",
+ __func__, ep->ep.name,
+ list_entry(ep->queue.next, struct s3c_request, queue));
+
+ return -EAGAIN;
+ }
+
+ dev = ep->dev;
+ DEBUG("%s: ep_num = %d, value = %d\n", __func__, ep_num, value);
+
+ spin_lock_irqsave(&dev->lock, flags);
+
+ if (value == 0) {
+ ep->stopped = 0;
+ s3c_udc_ep_clear_stall(ep);
+ } else {
+ ep->stopped = 1;
+ s3c_udc_ep_set_stall(ep);
+ }
+
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+ return 0;
+}
+
+void s3c_udc_ep_activate(struct s3c_ep *ep)
+{
+ u8 ep_num;
+ u32 ep_ctrl = 0, daintmsk = 0;
+
+ ep_num = ep_index(ep);
+
+ /* Read DEPCTLn register */
+ if (ep_is_in(ep)) {
+ ep_ctrl = readl(S3C_UDC_OTG_DIEPCTL(ep_num));
+ daintmsk = 1 << ep_num;
+ } else {
+ ep_ctrl = readl(S3C_UDC_OTG_DOEPCTL(ep_num));
+ daintmsk = (1 << ep_num) << DAINT_OUT_BIT;
+ }
+
+ DEBUG("%s: EPCTRL%d = 0x%x, ep_is_in = %d\n",
+ __func__, ep_num, ep_ctrl, ep_is_in(ep));
+
+ /* If the EP is already active don't change the EP Control
+ * register. */
+ if (!(ep_ctrl & DEPCTL_USBACTEP)) {
+ ep_ctrl = (ep_ctrl & ~DEPCTL_TYPE_MASK) | (ep->bmAttributes << DEPCTL_TYPE_BIT);
+ ep_ctrl = (ep_ctrl & ~DEPCTL_MPS_MASK) | (ep->ep.maxpacket << DEPCTL_MPS_BIT);
+ ep_ctrl |= (DEPCTL_SETD0PID | DEPCTL_USBACTEP);
+
+ if (ep_is_in(ep)) {
+ writel(ep_ctrl, S3C_UDC_OTG_DIEPCTL(ep_num));
+ DEBUG("%s: USB Ative EP%d, DIEPCTRL%d = 0x%x\n",
+ __func__, ep_num, ep_num, readl(S3C_UDC_OTG_DIEPCTL(ep_num)));
+ } else {
+ writel(ep_ctrl, S3C_UDC_OTG_DOEPCTL(ep_num));
+ DEBUG("%s: USB Ative EP%d, DOEPCTRL%d = 0x%x\n",
+ __func__, ep_num, ep_num, readl(S3C_UDC_OTG_DOEPCTL(ep_num)));
+ }
+ }
+
+ /* Unmask EP Interrtupt */
+ writel(readl(S3C_UDC_OTG_DAINTMSK)|daintmsk, S3C_UDC_OTG_DAINTMSK);
+ DEBUG("%s: DAINTMSK = 0x%x\n", __func__, readl(S3C_UDC_OTG_DAINTMSK));
+
+}
+
+static int s3c_udc_clear_feature(struct usb_ep *_ep)
+{
+ struct s3c_ep *ep;
+ u8 ep_num;
+ struct s3c_udc *dev = the_controller;
+ ep = container_of(_ep, struct s3c_ep, ep);
+ ep_num = ep_index(ep);
+
+ DEBUG_SETUP("%s: ep_num = %d, is_in = %d, clear_feature_flag = %d\n",
+ __func__, ep_num, ep_is_in(ep), clear_feature_flag);
+
+ if (usb_ctrl.wLength != 0) {
+ DEBUG_SETUP("\tCLEAR_FEATURE: wLength is not zero.....\n");
+ return 1;
+ }
+
+ switch (usb_ctrl.bRequestType & USB_RECIP_MASK) {
+ case USB_RECIP_DEVICE:
+ switch (usb_ctrl.wValue) {
+ case USB_DEVICE_REMOTE_WAKEUP:
+ DEBUG_SETUP("\tCLEAR_FEATURE: USB_DEVICE_REMOTE_WAKEUP\n");
+ printk(KERN_INFO "%s:: USB_DEVICE_REMOTE_WAKEUP\n", __func__);
+ dev->status &= ~(1 << USB_DEVICE_REMOTE_WAKEUP);
+ break;
+
+ case USB_DEVICE_TEST_MODE:
+ DEBUG_SETUP("\tCLEAR_FEATURE: USB_DEVICE_TEST_MODE\n");
+ /** @todo Add CLEAR_FEATURE for TEST modes. */
+ break;
+ }
+
+ s3c_udc_ep0_zlp();
+ break;
+
+ case USB_RECIP_ENDPOINT:
+ DEBUG_SETUP("\tCLEAR_FEATURE: USB_RECIP_ENDPOINT, wValue = %d\n",
+ usb_ctrl.wValue);
+
+ if (usb_ctrl.wValue == USB_ENDPOINT_HALT) {
+ if (ep_num == 0) {
+ s3c_udc_ep0_set_stall(ep);
+ return 0;
+ }
+
+ s3c_udc_ep0_zlp();
+
+ s3c_udc_ep_clear_stall(ep);
+ s3c_udc_ep_activate(ep);
+ ep->stopped = 0;
+
+ clear_feature_num = ep_num;
+ clear_feature_flag = 1;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+/* Set into the test mode for Test Mode set_feature request */
+static inline void set_test_mode(void)
+{
+ u32 ep_ctrl, dctl;
+ u8 test_selector = (usb_ctrl.wIndex>>8) & TEST_SELECTOR_MASK;
+
+ if (test_selector > 0 && test_selector < 6) {
+ ep_ctrl = readl(S3C_UDC_OTG_DIEPCTL(EP0_CON));
+
+ writel(1<<19 | 0<<0, S3C_UDC_OTG_DIEPTSIZ(EP0_CON));
+ writel(ep_ctrl|DEPCTL_EPENA|DEPCTL_CNAK|EP0_CON<<DEPCTL_NEXT_EP_BIT , S3C_UDC_OTG_DIEPCTL(EP0_CON));
+ }
+
+ switch (test_selector) {
+ case TEST_J_SEL:
+ /* some delay is necessary like printk() or udelay() */
+ printk(KERN_INFO "Test mode selector in set_feature request is TEST J\n");
+
+ dctl = readl(S3C_UDC_OTG_DCTL);
+ writel((dctl&~(TEST_CONTROL_MASK))|TEST_J_MODE, S3C_UDC_OTG_DCTL);
+ break;
+ case TEST_K_SEL:
+ /* some delay is necessary like printk() or udelay() */
+ printk(KERN_INFO "Test mode selector in set_feature request is TEST K\n");
+
+ dctl = readl(S3C_UDC_OTG_DCTL);
+ writel((dctl&~(TEST_CONTROL_MASK))|TEST_K_MODE, S3C_UDC_OTG_DCTL);
+ break;
+ case TEST_SE0_NAK_SEL:
+ /* some delay is necessary like printk() or udelay() */
+ printk(KERN_INFO "Test mode selector in set_feature request is TEST SE0 NAK\n");
+
+ dctl = readl(S3C_UDC_OTG_DCTL);
+ writel((dctl&~(TEST_CONTROL_MASK))|TEST_SE0_NAK_MODE, S3C_UDC_OTG_DCTL);
+ break;
+ case TEST_PACKET_SEL:
+ /* some delay is necessary like printk() or udelay() */
+ printk(KERN_INFO "Test mode selector in set_feature request is TEST PACKET\n");
+ __dma_single_cpu_to_dev(test_pkt, TEST_PKT_SIZE, DMA_TO_DEVICE);
+ writel(virt_to_phys(test_pkt), S3C_UDC_OTG_DIEPDMA(EP0_CON));
+
+ ep_ctrl = readl(S3C_UDC_OTG_DIEPCTL(EP0_CON));
+
+ writel(1<<19 | TEST_PKT_SIZE<<0, S3C_UDC_OTG_DIEPTSIZ(EP0_CON));
+ writel(ep_ctrl|DEPCTL_EPENA|DEPCTL_CNAK|EP0_CON<<DEPCTL_NEXT_EP_BIT, S3C_UDC_OTG_DIEPCTL(EP0_CON));
+
+ dctl = readl(S3C_UDC_OTG_DCTL);
+ writel((dctl&~(TEST_CONTROL_MASK))|TEST_PACKET_MODE, S3C_UDC_OTG_DCTL);
+ break;
+ case TEST_FORCE_ENABLE_SEL:
+ /* some delay is necessary like printk() or udelay() */
+ printk(KERN_INFO "Test mode selector in set_feature request is TEST FORCE ENABLE\n");
+
+ dctl = readl(S3C_UDC_OTG_DCTL);
+ writel((dctl&~(TEST_CONTROL_MASK))|TEST_FORCE_ENABLE_MODE, S3C_UDC_OTG_DCTL);
+ break;
+ }
+}
+
+static int s3c_udc_set_feature(struct usb_ep *_ep)
+{
+ struct s3c_ep *ep;
+ u8 ep_num;
+ struct s3c_udc *dev = the_controller;
+ ep = container_of(_ep, struct s3c_ep, ep);
+ ep_num = ep_index(ep);
+
+ DEBUG_SETUP("%s: *** USB_REQ_SET_FEATURE , ep_num = %d\n", __func__, ep_num);
+
+ if (usb_ctrl.wLength != 0) {
+ DEBUG_SETUP("\tSET_FEATURE: wLength is not zero.....\n");
+ return 1;
+ }
+
+ switch (usb_ctrl.bRequestType & USB_RECIP_MASK) {
+ case USB_RECIP_DEVICE:
+ switch (usb_ctrl.wValue) {
+ case USB_DEVICE_REMOTE_WAKEUP:
+ DEBUG_SETUP("\tSET_FEATURE: USB_DEVICE_REMOTE_WAKEUP\n");
+ printk(KERN_INFO "%s:: USB_DEVICE_REMOTE_WAKEUP\n", __func__);
+ dev->status |= (1 << USB_DEVICE_REMOTE_WAKEUP);
+ break;
+
+ case USB_DEVICE_TEST_MODE:
+ DEBUG_SETUP("\tSET_FEATURE: USB_DEVICE_TEST_MODE\n");
+ set_test_mode();
+ break;
+
+ case USB_DEVICE_B_HNP_ENABLE:
+ DEBUG_SETUP("\tSET_FEATURE: USB_DEVICE_B_HNP_ENABLE\n");
+ break;
+
+ case USB_DEVICE_A_HNP_SUPPORT:
+ /* RH port supports HNP */
+ DEBUG_SETUP("\tSET_FEATURE: USB_DEVICE_A_HNP_SUPPORT\n");
+ break;
+
+ case USB_DEVICE_A_ALT_HNP_SUPPORT:
+ /* other RH port does */
+ DEBUG_SETUP("\tSET_FEATURE: USB_DEVICE_A_ALT_HNP_SUPPORT\n");
+ break;
+ }
+
+ s3c_udc_ep0_zlp();
+ return 0;
+
+ case USB_RECIP_INTERFACE:
+ DEBUG_SETUP("\tSET_FEATURE: USB_RECIP_INTERFACE\n");
+ break;
+
+ case USB_RECIP_ENDPOINT:
+ DEBUG_SETUP("\tSET_FEATURE: USB_RECIP_ENDPOINT\n");
+ if (usb_ctrl.wValue == USB_ENDPOINT_HALT) {
+ if (ep_num == 0) {
+ s3c_udc_ep0_set_stall(ep);
+ return 0;
+ }
+ ep->stopped = 1;
+ s3c_udc_ep_set_stall(ep);
+ }
+
+ s3c_udc_ep0_zlp();
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * WAIT_FOR_SETUP (OUT_PKT_RDY)
+ */
+static void s3c_ep0_setup(struct s3c_udc *dev)
+{
+ struct s3c_ep *ep = &dev->ep[0];
+ int i, bytes, is_in;
+ u8 ep_num;
+
+ /* Nuke all previous transfers */
+ nuke(ep, -EPROTO);
+
+ /* read control req from fifo (8 bytes) */
+ bytes = s3c_fifo_read(ep, (u32 *)&usb_ctrl, 8);
+
+ DEBUG_SETUP("%s: bRequestType = 0x%x(%s), bRequest = 0x%x"
+ "\twLength = 0x%x, wValue = 0x%x, wIndex= 0x%x\n",
+ __func__, usb_ctrl.bRequestType,
+ (usb_ctrl.bRequestType & USB_DIR_IN) ? "IN" : "OUT", usb_ctrl.bRequest,
+ usb_ctrl.wLength, usb_ctrl.wValue, usb_ctrl.wIndex);
+
+ if (usb_ctrl.bRequest == GET_MAX_LUN_REQUEST && usb_ctrl.wLength != 1) {
+ DEBUG_SETUP("\t%s:GET_MAX_LUN_REQUEST:invalid wLength = %d, setup returned\n",
+ __func__, usb_ctrl.wLength);
+
+ s3c_udc_ep0_set_stall(ep);
+ dev->ep0state = WAIT_FOR_SETUP;
+
+ return;
+ } else if (usb_ctrl.bRequest == BOT_RESET_REQUEST && usb_ctrl.wLength != 0) {
+ /* Bulk-Only *mass storge reset of class-specific request */
+ DEBUG_SETUP("\t%s:BOT Rest:invalid wLength = %d, setup returned\n",
+ __func__, usb_ctrl.wLength);
+
+ s3c_udc_ep0_set_stall(ep);
+ dev->ep0state = WAIT_FOR_SETUP;
+
+ return;
+ }
+
+ /* Set direction of EP0 */
+ if (likely(usb_ctrl.bRequestType & USB_DIR_IN)) {
+ ep->bEndpointAddress |= USB_DIR_IN;
+ is_in = 1;
+
+ } else {
+ ep->bEndpointAddress &= ~USB_DIR_IN;
+ is_in = 0;
+ }
+ /* cope with automagic for some standard requests. */
+ dev->req_std = (usb_ctrl.bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD;
+ dev->req_config = 0;
+ dev->req_pending = 1;
+
+ /* Handle some SETUP packets ourselves */
+ switch (usb_ctrl.bRequest) {
+ case USB_REQ_SET_ADDRESS:
+ DEBUG_SETUP("%s: *** USB_REQ_SET_ADDRESS (%d)\n",
+ __func__, usb_ctrl.wValue);
+
+ if (usb_ctrl.bRequestType
+ != (USB_TYPE_STANDARD | USB_RECIP_DEVICE))
+ break;
+
+ udc_set_address(dev, usb_ctrl.wValue);
+ return;
+
+ case USB_REQ_SET_CONFIGURATION:
+ DEBUG_SETUP("============================================\n");
+ DEBUG_SETUP("%s: USB_REQ_SET_CONFIGURATION (%d)\n",
+ __func__, usb_ctrl.wValue);
+
+ if (usb_ctrl.bRequestType == USB_RECIP_DEVICE) {
+ reset_available = 1;
+ dev->req_config = 1;
+ }
+
+#if defined(CONFIG_MACH_SMDKC110) || defined(CONFIG_MACH_SMDKV210)
+ s3c_udc_cable_connect(dev);
+#endif
+ break;
+
+ case USB_REQ_GET_DESCRIPTOR:
+ DEBUG_SETUP("%s: *** USB_REQ_GET_DESCRIPTOR\n", __func__);
+ break;
+
+ case USB_REQ_SET_INTERFACE:
+ DEBUG_SETUP("%s: *** USB_REQ_SET_INTERFACE (%d)\n",
+ __func__, usb_ctrl.wValue);
+
+ if (usb_ctrl.bRequestType == USB_RECIP_INTERFACE) {
+ reset_available = 1;
+ dev->req_config = 1;
+ }
+ break;
+
+ case USB_REQ_GET_CONFIGURATION:
+ DEBUG_SETUP("%s: *** USB_REQ_GET_CONFIGURATION\n", __func__);
+ break;
+
+ case USB_REQ_GET_STATUS:
+ if (dev->req_std) {
+ if (!s3c_udc_get_status(dev, &usb_ctrl))
+ return;
+ }
+ break;
+
+ case USB_REQ_CLEAR_FEATURE:
+ ep_num = usb_ctrl.wIndex & 0x7f;
+
+ if (!s3c_udc_clear_feature(&dev->ep[ep_num].ep))
+ return;
+ break;
+
+ case USB_REQ_SET_FEATURE:
+ ep_num = usb_ctrl.wIndex & 0x7f;
+
+ if (!s3c_udc_set_feature(&dev->ep[ep_num].ep))
+ return;
+ break;
+
+ default:
+ DEBUG_SETUP("%s: *** Default of usb_ctrl.bRequest=0x%x happened.\n",
+ __func__, usb_ctrl.bRequest);
+ break;
+ }
+
+ if (likely(dev->driver)) {
+ /* device-2-host (IN) or no data setup command,
+ * process immediately */
+ DEBUG_SETUP("%s: usb_ctrlrequest will be passed to fsg_setup()\n", __func__);
+
+ spin_unlock(&dev->lock);
+ i = dev->driver->setup(&dev->gadget, &usb_ctrl);
+ spin_lock(&dev->lock);
+
+ if (i < 0) {
+ if (dev->req_config) {
+ DEBUG_SETUP("\tconfig change 0x%02x fail %d?\n",
+ (u32)&usb_ctrl.bRequest, i);
+ return;
+ }
+
+ /* setup processing failed, force stall */
+ s3c_udc_ep0_set_stall(ep);
+ dev->ep0state = WAIT_FOR_SETUP;
+
+ DEBUG_SETUP("\tdev->driver->setup failed (%d), bRequest = %d\n",
+ i, usb_ctrl.bRequest);
+
+
+ } else if (dev->req_pending) {
+ dev->req_pending = 0;
+ DEBUG_SETUP("\tdev->req_pending...\n");
+ }
+
+ DEBUG_SETUP("\tep0state = %s\n", state_names[dev->ep0state]);
+
+ }
+}
+
+/*
+ * handle ep0 interrupt
+ */
+static void s3c_handle_ep0(struct s3c_udc *dev)
+{
+ if (dev->ep0state == WAIT_FOR_SETUP) {
+ DEBUG_OUT_EP("%s: WAIT_FOR_SETUP\n", __func__);
+ s3c_ep0_setup(dev);
+
+ } else {
+ DEBUG_OUT_EP("%s: strange state!!(state = %s)\n",
+ __func__, state_names[dev->ep0state]);
+ }
+}
+
+static void s3c_ep0_kick(struct s3c_udc *dev, struct s3c_ep *ep)
+{
+ DEBUG_EP0("%s: ep_is_in = %d\n", __func__, ep_is_in(ep));
+ if (ep_is_in(ep)) {
+ dev->ep0state = DATA_STATE_XMIT;
+ s3c_ep0_write(dev);
+
+ } else {
+ dev->ep0state = DATA_STATE_RECV;
+ s3c_ep0_read(dev);
+ }
+}
+
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
index b5a30fe..f30c307 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/u_ether.c
@@ -249,11 +249,13 @@ rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags)
goto enomem;
}
+#ifndef CONFIG_USB_ANDROID_RNDIS_DWORD_ALIGNED
/* Some platforms perform better when IP packets are aligned,
* but on at least one, checksumming fails otherwise. Note:
* RNDIS headers involve variable numbers of LE32 values.
*/
skb_reserve(skb, NET_IP_ALIGN);
+#endif
req->buf = skb->data;
req->length = size;
@@ -483,7 +485,10 @@ static void tx_complete(struct usb_ep *ep, struct usb_request *req)
list_add(&req->list, &dev->tx_reqs);
spin_unlock(&dev->req_lock);
dev_kfree_skb_any(skb);
-
+#ifdef CONFIG_USB_ANDROID_RNDIS_DWORD_ALIGNED
+ if (req->buf != skb->data)
+ kfree(req->buf);
+#endif
atomic_dec(&dev->tx_qlen);
if (netif_carrier_ok(dev->net))
netif_wake_queue(dev->net);
@@ -577,7 +582,21 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
length = skb->len;
}
+
+#ifdef CONFIG_USB_ANDROID_RNDIS_DWORD_ALIGNED
+ if ((int)skb->data & 3) {
+ req->buf = kmalloc(skb->len, GFP_ATOMIC);
+ if (!req->buf)
+ goto drop;
+ memcpy((void *)req->buf, (void *)skb->data, skb->len);
+ }
+ else {
+ req->buf = skb->data;
+ }
+#else
req->buf = skb->data;
+#endif
+
req->context = skb;
req->complete = tx_complete;
@@ -618,6 +637,10 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
dev_kfree_skb_any(skb);
drop:
dev->net->stats.tx_dropped++;
+#ifdef CONFIG_USB_ANDROID_RNDIS_DWORD_ALIGNED
+ if (req->buf != skb->data)
+ kfree(req->buf);
+#endif
spin_lock_irqsave(&dev->req_lock, flags);
if (list_empty(&dev->tx_reqs))
netif_start_queue(net);
@@ -823,12 +846,6 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
SET_ETHTOOL_OPS(net, &ops);
- /* two kinds of host-initiated state changes:
- * - iff DATA transfer is active, carrier is "on"
- * - tx queueing enabled if open *and* carrier is "on"
- */
- netif_carrier_off(net);
-
dev->gadget = g;
SET_NETDEV_DEV(net, &g->dev);
SET_NETDEV_DEVTYPE(net, &gadget_type);
@@ -842,6 +859,12 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
INFO(dev, "HOST MAC %pM\n", dev->host_mac);
the_dev = dev;
+
+ /* two kinds of host-initiated state changes:
+ * - iff DATA transfer is active, carrier is "on"
+ * - tx queueing enabled if open *and* carrier is "on"
+ */
+ netif_carrier_off(net);
}
return status;
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index ab085f1..67c452d 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -578,3 +578,19 @@ config USB_OCTEON_OHCI
config USB_OCTEON2_COMMON
bool
default y if USB_OCTEON_EHCI || USB_OCTEON_OHCI
+
+config USB_S3C_OTG_HOST
+ tristate "S3C USB OTG Host support"
+ depends on USB && (PLAT_S3C64XX || PLAT_S5P)
+ help
+ Samsung's S3C64XX processors include high speed USB OTG2.0
+ controller. It has 15 configurable endpoints, as well as
+ endpoint zero (for control transfers).
+
+ This driver support only OTG Host role. If you want to use
+ OTG Device role, select USB Gadget support and S3C OTG Device.
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "s3c_otg_hcd" and force all
+ drivers to also be dynamically linked.
+
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 624a362..de59025 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -15,6 +15,7 @@ xhci-hcd-y := xhci.o xhci-mem.o xhci-pci.o
xhci-hcd-y += xhci-ring.o xhci-hub.o xhci-dbg.o
obj-$(CONFIG_USB_WHCI_HCD) += whci/
+obj-$(CONFIG_USB_S3C_OTG_HOST) += s3c-otg/
obj-$(CONFIG_PCI) += pci-quirks.o
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 3940d28..f768314 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -144,14 +144,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
hcd->has_tt = 1;
tdi_reset(ehci);
}
- if (pdev->subsystem_vendor == PCI_VENDOR_ID_ASUSTEK) {
- /* EHCI #1 or #2 on 6 Series/C200 Series chipset */
- if (pdev->device == 0x1c26 || pdev->device == 0x1c2d) {
- ehci_info(ehci, "broken D3 during system sleep on ASUS\n");
- hcd->broken_pci_sleep = 1;
- device_set_wakeup_capable(&pdev->dev, false);
- }
- }
break;
case PCI_VENDOR_ID_TDI:
if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
@@ -365,7 +357,9 @@ static bool usb_is_intel_switchable_ehci(struct pci_dev *pdev)
{
return pdev->class == PCI_CLASS_SERIAL_USB_EHCI &&
pdev->vendor == PCI_VENDOR_ID_INTEL &&
- pdev->device == 0x1E26;
+ (pdev->device == 0x1E26 ||
+ pdev->device == 0x8C2D ||
+ pdev->device == 0x8C26);
}
static void ehci_enable_xhci_companion(void)
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index e4dd26a..08fdcfa 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -130,9 +130,17 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh)
else {
qtd = list_entry (qh->qtd_list.next,
struct ehci_qtd, qtd_list);
- /* first qtd may already be partially processed */
- if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw->hw_current)
+ /*
+ * first qtd may already be partially processed.
+ * If we come here during unlink, the QH overlay region
+ * might have reference to the just unlinked qtd. The
+ * qtd is updated in qh_completions(). Update the QH
+ * overlay here.
+ */
+ if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw->hw_current) {
+ qh->hw->hw_qtd_next = qtd->hw_next;
qtd = NULL;
+ }
}
if (qtd)
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index 7fec8bd..3f623fb 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -73,7 +73,9 @@
#define NB_PIF0_PWRDOWN_1 0x01100013
#define USB_INTEL_XUSB2PR 0xD0
+#define USB_INTEL_USB2PRM 0xD4
#define USB_INTEL_USB3_PSSEN 0xD8
+#define USB_INTEL_USB3PRM 0xDC
static struct amd_chipset_info {
struct pci_dev *nb_dev;
@@ -541,7 +543,14 @@ static const struct dmi_system_id __devinitconst ehci_dmi_nohandoff_table[] = {
/* Pegatron Lucid (Ordissimo AIRIS) */
.matches = {
DMI_MATCH(DMI_BOARD_NAME, "M11JB"),
- DMI_MATCH(DMI_BIOS_VERSION, "Lucid-GE-133"),
+ DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"),
+ },
+ },
+ {
+ /* Pegatron Lucid (Ordissimo) */
+ .matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "Ordissimo"),
+ DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"),
},
},
{ }
@@ -711,12 +720,28 @@ static int handshake(void __iomem *ptr, u32 mask, u32 done,
return -ETIMEDOUT;
}
-bool usb_is_intel_switchable_xhci(struct pci_dev *pdev)
+#define PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI 0x8C31
+
+bool usb_is_intel_ppt_switchable_xhci(struct pci_dev *pdev)
{
return pdev->class == PCI_CLASS_SERIAL_USB_XHCI &&
pdev->vendor == PCI_VENDOR_ID_INTEL &&
pdev->device == PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI;
}
+
+/* The Intel Lynx Point chipset also has switchable ports. */
+bool usb_is_intel_lpt_switchable_xhci(struct pci_dev *pdev)
+{
+ return pdev->class == PCI_CLASS_SERIAL_USB_XHCI &&
+ pdev->vendor == PCI_VENDOR_ID_INTEL &&
+ pdev->device == PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI;
+}
+
+bool usb_is_intel_switchable_xhci(struct pci_dev *pdev)
+{
+ return usb_is_intel_ppt_switchable_xhci(pdev) ||
+ usb_is_intel_lpt_switchable_xhci(pdev);
+}
EXPORT_SYMBOL_GPL(usb_is_intel_switchable_xhci);
/*
@@ -739,12 +764,21 @@ EXPORT_SYMBOL_GPL(usb_is_intel_switchable_xhci);
*/
void usb_enable_xhci_ports(struct pci_dev *xhci_pdev)
{
+#if defined(CONFIG_USB_XHCI_HCD) || defined(CONFIG_USB_XHCI_HCD_MODULE)
u32 ports_available;
- ports_available = 0xffffffff;
+ /* Read USB3PRM, the USB 3.0 Port Routing Mask Register
+ * Indicate the ports that can be changed from OS.
+ */
+ pci_read_config_dword(xhci_pdev, USB_INTEL_USB3PRM,
+ &ports_available);
+
+ dev_dbg(&xhci_pdev->dev, "Configurable ports to enable SuperSpeed: 0x%x\n",
+ ports_available);
+
/* Write USB3_PSSEN, the USB 3.0 Port SuperSpeed Enable
- * Register, to turn on SuperSpeed terminations for all
- * available ports.
+ * Register, to turn on SuperSpeed terminations for the
+ * switchable ports.
*/
pci_write_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN,
cpu_to_le32(ports_available));
@@ -754,7 +788,16 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev)
dev_dbg(&xhci_pdev->dev, "USB 3.0 ports that are now enabled "
"under xHCI: 0x%x\n", ports_available);
- ports_available = 0xffffffff;
+ /* Read XUSB2PRM, xHCI USB 2.0 Port Routing Mask Register
+ * Indicate the USB 2.0 ports to be controlled by the xHCI host.
+ */
+
+ pci_read_config_dword(xhci_pdev, USB_INTEL_USB2PRM,
+ &ports_available);
+
+ dev_dbg(&xhci_pdev->dev, "Configurable USB 2.0 ports to hand over to xCHI: 0x%x\n",
+ ports_available);
+
/* Write XUSB2PR, the xHC USB 2.0 Port Routing Register, to
* switch the USB 2.0 power and data lines over to the xHCI
* host.
@@ -766,9 +809,28 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev)
&ports_available);
dev_dbg(&xhci_pdev->dev, "USB 2.0 ports that are now switched over "
"to xHCI: 0x%x\n", ports_available);
+#else
+ /* Don't switchover the ports if the user hasn't compiled the xHCI
+ * driver. Otherwise they will see "dead" USB ports that don't power
+ * the devices.
+ */
+ dev_warn(&xhci_pdev->dev,
+ "CONFIG_USB_XHCI_HCD is turned off, "
+ "defaulting to EHCI.\n");
+ dev_warn(&xhci_pdev->dev,
+ "USB 3.0 devices will work at USB 2.0 speeds.\n");
+#endif /* CONFIG_USB_XHCI_HCD || CONFIG_USB_XHCI_HCD_MODULE */
+
}
EXPORT_SYMBOL_GPL(usb_enable_xhci_ports);
+void usb_disable_xhci_ports(struct pci_dev *xhci_pdev)
+{
+ pci_write_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN, 0x0);
+ pci_write_config_dword(xhci_pdev, USB_INTEL_XUSB2PR, 0x0);
+}
+EXPORT_SYMBOL_GPL(usb_disable_xhci_ports);
+
/**
* PCI Quirks for xHCI.
*
@@ -784,12 +846,12 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)
void __iomem *op_reg_base;
u32 val;
int timeout;
+ int len = pci_resource_len(pdev, 0);
if (!mmio_resource_enabled(pdev, 0))
return;
- base = ioremap_nocache(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0));
+ base = ioremap_nocache(pci_resource_start(pdev, 0), len);
if (base == NULL)
return;
@@ -799,9 +861,17 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)
*/
ext_cap_offset = xhci_find_next_cap_offset(base, XHCI_HCC_PARAMS_OFFSET);
do {
+ if ((ext_cap_offset + sizeof(val)) > len) {
+ /* We're reading garbage from the controller */
+ dev_warn(&pdev->dev,
+ "xHCI controller failing to respond");
+ return;
+ }
+
if (!ext_cap_offset)
/* We've reached the end of the extended capabilities */
goto hc_init;
+
val = readl(base + ext_cap_offset);
if (XHCI_EXT_CAPS_ID(val) == XHCI_EXT_CAPS_LEGACY)
break;
@@ -832,9 +902,10 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)
/* Disable any BIOS SMIs and clear all SMI events*/
writel(val, base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET);
+hc_init:
if (usb_is_intel_switchable_xhci(pdev))
usb_enable_xhci_ports(pdev);
-hc_init:
+
op_reg_base = base + XHCI_HC_LENGTH(readl(base));
/* Wait for the host controller to be ready before writing any
diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h
index b1002a8..7f69a39 100644
--- a/drivers/usb/host/pci-quirks.h
+++ b/drivers/usb/host/pci-quirks.h
@@ -10,10 +10,12 @@ void usb_amd_quirk_pll_disable(void);
void usb_amd_quirk_pll_enable(void);
bool usb_is_intel_switchable_xhci(struct pci_dev *pdev);
void usb_enable_xhci_ports(struct pci_dev *xhci_pdev);
+void usb_disable_xhci_ports(struct pci_dev *xhci_pdev);
#else
static inline void usb_amd_quirk_pll_disable(void) {}
static inline void usb_amd_quirk_pll_enable(void) {}
static inline void usb_amd_dev_put(void) {}
+static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {}
#endif /* CONFIG_PCI */
#endif /* __LINUX_USB_PCI_QUIRKS_H */
diff --git a/drivers/usb/host/s3c-otg/Makefile b/drivers/usb/host/s3c-otg/Makefile
new file mode 100644
index 0000000..37674c8
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/Makefile
@@ -0,0 +1,18 @@
+#
+# Makefile for USB OTG Host Controller Drivers
+#
+
+obj-$(CONFIG_USB_S3C_OTG_HOST) += s3c_otg_hcd.o
+
+s3c_otg_hcd-objs += s3c-otg-hcdi-driver.o s3c-otg-hcdi-hcd.o
+s3c_otg_hcd-objs += s3c-otg-transfer-common.o s3c-otg-transfer-nonperiodic.o \
+ s3c-otg-transfer-periodic.o
+s3c_otg_hcd-objs += s3c-otg-scheduler-ischeduler.o s3c-otg-scheduler-scheduler.o \
+ s3c-otg-scheduler-readyq.o
+s3c_otg_hcd-objs += s3c-otg-oci.o
+s3c_otg_hcd-objs += s3c-otg-transferchecker-common.o \
+ s3c-otg-transferchecker-control.o \
+ s3c-otg-transferchecker-bulk.o \
+ s3c-otg-transferchecker-interrupt.o
+s3c_otg_hcd-objs += s3c-otg-isr.o
+s3c_otg_hcd-objs += s3c-otg-roothub.o
diff --git a/drivers/usb/host/s3c-otg/debug-mem.c b/drivers/usb/host/s3c-otg/debug-mem.c
new file mode 100644
index 0000000..de85853
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/debug-mem.c
@@ -0,0 +1,55 @@
+#include "s3c-otg-hcdi-hcd.h"
+#include "debug-mem.h"
+
+#define MAX_ALLOCS 1024
+
+typedef void *ElemType;
+
+static ElemType alloced[MAX_ALLOCS];
+static int numalloced = 0;
+
+#define fail(args...) ( printk(args), dump_stack() )
+
+void debug_alloc(void *addr) {
+ ElemType *freeloc = NULL;
+ ElemType *c = alloced;
+ int i;
+
+ if(!addr)
+ fail("MEMD alloc of NULL");
+
+ for(i = 0; i < numalloced; i++, c++) {
+ if(*c == NULL && freeloc == NULL)
+ freeloc = c;
+ else if(*c == addr)
+ fail("MEMD multiple allocs of %p", addr);
+ }
+
+ if(freeloc)
+ *freeloc = addr;
+ else {
+ if(numalloced >= MAX_ALLOCS)
+ fail("MEMD too many allocs");
+ else {
+ alloced[numalloced++] = addr;
+ }
+ }
+}
+
+void debug_free(void *addr) {
+ ElemType *c = alloced;
+ int i;
+
+ if(!addr)
+ fail("free of NULL");
+
+ for(i = 0; i < numalloced; i++, c++) {
+ if(*c == addr) {
+ *c = NULL;
+ return;
+ }
+ }
+
+ fail("MEMD freed addr %p was never alloced\n", addr);
+}
+
diff --git a/drivers/usb/host/s3c-otg/debug-mem.h b/drivers/usb/host/s3c-otg/debug-mem.h
new file mode 100644
index 0000000..4164793
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/debug-mem.h
@@ -0,0 +1,9 @@
+#ifndef __DEBUGMEM_H
+#define __DEBUGMEM_H
+
+// kevinh quick hack to see if the s3c stuff is doing memory properly
+
+void debug_alloc(void *addr);
+void debug_free(void *addr);
+
+#endif
diff --git a/drivers/usb/host/s3c-otg/s3c-otg-common-common.h b/drivers/usb/host/s3c-otg/s3c-otg-common-common.h
new file mode 100644
index 0000000..720154e
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/s3c-otg-common-common.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+ * (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+ *
+ * @file s3c-otg-common-common.h
+ * @brief it includes common header files for all modules \n
+ * @version
+ * ex)-# Jun 11,2008 v1.0 by SeungSoo Yang (ss1.yang@samsung.com) \n
+ * : Creating the initial version of this code \n
+ * @see None
+ ****************************************************************************/
+/****************************************************************************
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ ****************************************************************************/
+
+#ifndef _S3C_OTG_COMMON_COMMON_H_
+#define _S3C_OTG_COMMON_COMMON_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+//#include "s3c-otg-common-typedef.h"
+#include "s3c-otg-common-errorcode.h"
+#include <linux/errno.h>
+#include <linux/usb.h>
+
+//Define OS
+#define LINUX 1
+
+//Kernel Version
+#define KERNEL_2_6_21
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _S3C_OTG_COMMON_COMMON_H_ */
diff --git a/drivers/usb/host/s3c-otg/s3c-otg-common-const.h b/drivers/usb/host/s3c-otg/s3c-otg-common-const.h
new file mode 100644
index 0000000..f0f5cb9
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/s3c-otg-common-const.h
@@ -0,0 +1,167 @@
+/****************************************************************************
+ * (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+ *
+ * [File Name] : s3c-otg-common-const.h
+ * [Description] : The Header file defines constants to be used at sub-modules of S3C6400HCD.
+ * [Author] : Yang Soon Yeal { syatom.yang@samsung.com }
+ * [Department] : System LSI Division/System SW Lab
+ * [Created Date]: 2008/06/03
+ * [Revision History]
+ * (1) 2008/06/03 by Yang Soon Yeal { syatom.yang@samsung.com }
+ * - Created s3c-otg-common-const.h file and defines some constants.
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ ****************************************************************************/
+
+#ifndef _CONST_TYPE_DEF_H_
+#define _CONST_TYPE_DEF_H_
+
+/*
+// ----------------------------------------------------------------------------
+// Include files : None.
+// ----------------------------------------------------------------------------
+*/
+
+#include "s3c-otg-common-common.h"
+
+//#include "s3c-otg-common-regdef.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * @def OTG_PORT_NUMBER
+ *
+ * @brief write~ description
+ *
+ * describe in detail
+ */
+#define OTG_PORT_NUMBER 0
+
+
+
+//Defines Stages of Control Transfer
+#define SETUP_STAGE 1
+#define DATA_STAGE 2
+#define STATUS_STAGE 3
+#define COMPLETE_STAGE 4
+
+
+//Defines Direction of Endpoint
+#define EP_IN 1
+#define EP_OUT 0
+
+//Define speed of USB Device
+#define LOW_SPEED_OTG 2
+#define FULL_SPEED_OTG 1
+#define HIGH_SPEED_OTG 0
+#define SUPER_SPEED_OTG 3
+
+//Define multiple count of packet in periodic transfer.
+#define MULTI_COUNT_ZERO 0
+#define MULTI_COUNT_ONE 1
+#define MULTI_COUNT_TWO 2
+
+//Define USB Transfer Types.
+#define CONTROL_TRANSFER 0
+#define ISOCH_TRANSFER 1
+#define BULK_TRANSFER 2
+#define INT_TRANSFER 3
+
+#define BULK_TIMEOUT 300
+
+//Defines PID
+#define DATA0 0
+#define DATA1 2
+#define DATA2 1
+#define MDATA 3
+#define SETUP 3
+
+//Defines USB Transfer Request Size on USB2.0
+#define USB_20_STAND_DEV_REQUEST_SIZE 8
+//Define Max Channel Number
+#define MAX_CH_NUMBER 16
+//Define Channel Number
+#define CH_0 0
+#define CH_1 1
+#define CH_2 2
+#define CH_3 3
+#define CH_4 4
+#define CH_5 5
+#define CH_6 6
+#define CH_7 7
+#define CH_8 8
+#define CH_9 9
+#define CH_10 10
+#define CH_11 11
+#define CH_12 12
+#define CH_13 13
+#define CH_14 14
+#define CH_15 15
+#define CH_NONE 20
+
+
+// define the Constant for result of processing the USB Transfer.
+#define RE_TRANSMIT 1
+#define RE_SCHEDULE 2
+#define DE_ALLOCATE 3
+#define NO_ACTION 4
+
+//define the threshold value to retransmit USB Transfer
+#define RETRANSMIT_THRESHOLD 2
+
+//define the maximum size of data to be tranferred through channel.
+#define MAX_CH_TRANSFER_SIZE 65536//65535
+
+//define Max Frame Number which Synopsys OTG suppports.
+#define MAX_FRAME_NUMBER 0x3FFF
+// Channel Interrupt Status
+#define CH_STATUS_DataTglErr (0x1<<10)
+#define CH_STATUS_FrmOvrun (0x1<<9)
+#define CH_STATUS_BblErr (0x1<<8)
+#define CH_STATUS_XactErr (0x1<<7)
+#define CH_STATUS_NYET (0x1<<6)
+#define CH_STATUS_ACK (0x1<<5)
+#define CH_STATUS_NAK (0x1<<4)
+#define CH_STATUS_STALL (0x1<<3)
+#define CH_STATUS_AHBErr (0x1<<2)
+#define CH_STATUS_ChHltd (0x1<<1)
+#define CH_STATUS_XferCompl (0x1<<0)
+#define CH_STATUS_ALL 0x7FF
+
+
+//Define USB Transfer Flag..
+//typedef URB_SHORT_NOT_OK USB_TRANS_FLAG_NOT_SHORT;
+//typedef URB_ISO_ASAP USB_TRANS_FLAG_ISO_ASYNCH;
+
+#define USB_TRANS_FLAG_NOT_SHORT URB_SHORT_NOT_OK
+#define USB_TRANS_FLAG_ISO_ASYNCH URB_ISO_ASAP
+
+
+#define HFNUM_MAX_FRNUM 0x3FFF
+#define SCHEDULE_SLOT 10
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
+
+
diff --git a/drivers/usb/host/s3c-otg/s3c-otg-common-datastruct.h b/drivers/usb/host/s3c-otg/s3c-otg-common-datastruct.h
new file mode 100644
index 0000000..c31e8ab
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/s3c-otg-common-datastruct.h
@@ -0,0 +1,811 @@
+/****************************************************************************
+ * (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+ *
+ * [File Name] : s3c-otg-common-datastruct.h
+ * [Description] : The Header file defines Data Structures to be used at sub-modules of S3C6400HCD.
+ * [Author] : Yang Soon Yeal { syatom.yang@samsung.com }
+ * [Department] : System LSI Division/System SW Lab
+ * [Created Date]: 2008/06/03
+ * [Revision History]
+ * (1) 2008/06/03 by Yang Soon Yeal { syatom.yang@samsung.com }
+ * - Created this file and defines Data Structure to be managed by Transfer.
+ * (2) 2008/08/18 by SeungSoo Yang ( ss1.yang@samsung.com )
+ * - modifying ED structure
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ ****************************************************************************/
+
+#ifndef _DATA_STRUCT_DEF_H
+#define _DATA_STRUCT_DEF_H
+
+/*
+// ----------------------------------------------------------------------------
+// Include files : None.
+// ----------------------------------------------------------------------------
+*/
+
+#include <linux/wakelock.h>
+#include <plat/s5p-otghost.h>
+//#include "s3c-otg-common-typedef.h"
+#include "s3c-otg-hcdi-list.h"
+
+//#include "s3c-otg-common-regdef.h"
+//#include "s3c-otg-common-errorcode.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef union _hcintmsk_t
+{
+ // raw register data
+ u32 d32;
+
+ // register bits
+ struct
+ {
+ unsigned xfercompl : 1;
+ unsigned chhltd : 1;
+ unsigned ahberr : 1;
+ unsigned stall : 1;
+ unsigned nak : 1;
+ unsigned ack : 1;
+ unsigned nyet : 1;
+ unsigned xacterr : 1;
+ unsigned bblerr : 1;
+ unsigned frmovrun : 1;
+ unsigned datatglerr : 1;
+ unsigned reserved : 21;
+ } b;
+} hcintmsk_t;
+
+typedef union _hcintn_t
+{
+ u32 d32;
+ struct
+ {
+ u32 xfercompl :1;
+ u32 chhltd :1;
+ u32 abherr :1;
+ u32 stall :1;
+ u32 nak :1;
+ u32 ack :1;
+ u32 nyet :1;
+ u32 xacterr :1;
+ u32 bblerr :1;
+ u32 frmovrun :1;
+ u32 datatglerr :1;
+ u32 reserved :21;
+ }b;
+}hcintn_t;
+
+
+typedef union _pcgcctl_t
+{
+ /** raw register data */
+ u32 d32;
+ /** register bits */
+ struct
+ {
+ unsigned stoppclk :1;
+ unsigned gatehclk :1;
+ unsigned pwrclmp :1;
+ unsigned rstpdwnmodule :1;
+ unsigned physuspended :1;
+ unsigned Reserved5_31 :27;
+ }b;
+}pcgcctl_t;
+
+
+typedef struct isoch_packet_desc
+{
+ u32 isoch_packiet_start_addr;// start address of buffer is buffer address + uiOffsert.
+ u32 buf_size;
+ u32 transferred_szie;
+ u32 isoch_status;
+}isoch_packet_desc_t;//, *isoch_packet_desc_t *,**isoch_packet_desc_t **;
+
+
+typedef struct standard_dev_req_info
+{
+ bool is_data_stage;
+ u8 conrol_transfer_stage;
+ u32 vir_standard_dev_req_addr;
+ u32 phy_standard_dev_req_addr;
+}standard_dev_req_info_t;
+
+
+typedef struct control_data_tgl_t
+{
+ u8 setup_tgl;
+ u8 data_tgl;
+ u8 status_tgl;
+}control_data_tgl_t;
+
+
+
+typedef struct ed_status
+{
+ u8 data_tgl;
+ control_data_tgl_t control_data_tgl;
+ bool is_ping_enable;
+ bool is_in_transfer_ready_q;
+ bool is_in_transferring;
+ u32 in_transferring_td;
+ bool is_alloc_resource_for_ed;
+ bool is_complete_split;
+// sztupy: split transaction support
+#define ED_STATUS_SPLIT_POS_ALL 3
+#define ED_STATUS_SPLIT_POS_BEGIN 2
+#define ED_STATUS_SPLIT_POS_MID 1
+#define ED_STATUS_SPLIT_POS_END 0
+ u8 split_pos;
+ u32 split_offset;
+}ed_status_t;//, *ed_status_t *,**ed_status_t **;
+
+
+typedef struct ed_desc
+{
+ u8 device_addr;
+ u8 endpoint_num;
+ bool is_ep_in;
+ u8 dev_speed;
+ u8 endpoint_type;
+ u16 max_packet_size;
+ u8 mc;
+ u8 interval;
+ u32 sched_frame;
+ u32 used_bus_time;
+ u8 hub_addr;
+ u8 hub_port;
+ bool is_do_split;
+}ed_dest_t;//, *ed_dest_t *,**ed_dest_t **;
+
+
+//Defines the Data Structures of Transfer.
+typedef struct hc_reg
+{
+
+ hcintmsk_t hc_int_msk;
+ hcintn_t hc_int;
+ u32 dma_addr;
+
+}hc_reg_t;//, *hc_reg_t *, **hc_reg_t **;
+
+
+typedef struct stransfer
+{
+ u32 stransfer_id;
+ u32 parent_td;
+ ed_dest_t *ed_desc_p;
+ ed_status_t *ed_status_p;
+ u32 start_vir_buf_addr;
+ u32 start_phy_buf_addr;
+ u32 buf_size;
+ u32 packet_cnt;
+ u8 alloc_chnum;
+ hc_reg_t hc_reg;
+}stransfer_t;//, *stransfer_t *,**stransfer_t **;
+
+
+typedef struct ed
+{
+ u32 ed_id;
+ bool is_halted;
+ bool is_need_to_insert_scheduler;
+ ed_dest_t ed_desc;
+ ed_status_t ed_status;
+ otg_list_head ed_list_entry;
+ otg_list_head td_list_entry;
+ otg_list_head trans_ready_q_list_entry;
+ u32 num_td;
+ void *ed_private;
+}ed_t;//, *ed_t *, **ed_t **;
+
+
+
+typedef struct td
+{
+ u32 td_id;
+ ed_t *parent_ed_p;
+ void *call_back_func_p;
+ void *call_back_func_param_p;
+ bool is_transferring;
+ bool is_transfer_done;
+ u32 transferred_szie;
+ bool is_standard_dev_req;
+ standard_dev_req_info_t standard_dev_req_info;
+ u32 vir_buf_addr;
+ u32 phy_buf_addr;
+ u32 buf_size;
+ u32 transfer_flag;
+ stransfer_t cur_stransfer;
+ USB_ERROR_CODE error_code;
+ u32 err_cnt;
+ otg_list_head td_list_entry;
+
+ //Isochronous Transfer Specific
+ u32 isoch_packet_num;
+ isoch_packet_desc_t *isoch_packet_desc_p;
+ u32 isoch_packet_index;
+ u32 isoch_packet_position;
+ u32 sched_frame;
+ u32 interval;
+ u32 used_total_bus_time;
+
+ // the private data can be used by S3C6400Interface.
+ void *td_private;
+}td_t;//, *td_t *,**td_t **;
+
+
+//Define Data Structures of Scheduler.
+typedef struct trans_ready_q
+{
+ bool is_periodic_transfer;
+ otg_list_head trans_ready_q_list_head;
+ u32 trans_ready_entry_num;
+
+ //In case of Periodic Transfer
+ u32 total_perio_bus_bandwidth;
+ u8 total_alloc_chnum;
+}trans_ready_q_t;//, *trans_ready_q_t *,**trans_ready_q_t **;
+
+
+//Define USB OTG Reg Data Structure by Kyuhyeok.
+
+#define MAX_COUNT 10000
+#define INT_ALL 0xffffffff
+
+typedef union _haint_t
+{
+ u32 d32;
+ struct
+ {
+ u32 channel_intr_0 :1;
+ u32 channel_intr_1 :1;
+ u32 channel_intr_2 :1;
+ u32 channel_intr_3 :1;
+ u32 channel_intr_4 :1;
+ u32 channel_intr_5 :1;
+ u32 channel_intr_6 :1;
+ u32 channel_intr_7 :1;
+ u32 channel_intr_8 :1;
+ u32 channel_intr_9 :1;
+ u32 channel_intr_10 :1;
+ u32 channel_intr_11 :1;
+ u32 channel_intr_12 :1;
+ u32 channel_intr_13 :1;
+ u32 channel_intr_14 :1;
+ u32 channel_intr_15 :1;
+ u32 reserved1 :16;
+ }b;
+}haint_t;
+
+typedef union _gresetctl_t
+{
+ /** raw register data */
+ u32 d32;
+ /** register bits */
+ struct
+ {
+ unsigned csftrst : 1;
+ unsigned hsftrst : 1;
+ unsigned hstfrm : 1;
+ unsigned intknqflsh : 1;
+ unsigned rxfflsh : 1;
+ unsigned txfflsh : 1;
+ unsigned txfnum : 5;
+ unsigned reserved11_29 : 19;
+ unsigned dmareq : 1;
+ unsigned ahbidle : 1;
+ } b;
+} gresetctl_t;
+
+
+typedef union _gahbcfg_t
+{
+ /** raw register data */
+ u32 d32;
+ /** register bits */
+ struct
+ {
+ unsigned glblintrmsk : 1;
+#define GAHBCFG_GLBINT_ENABLE 1
+ unsigned hburstlen : 4;
+#define INT_DMA_MODE_SINGLE 00
+#define INT_DMA_MODE_INCR 01
+#define INT_DMA_MODE_INCR4 03
+#define INT_DMA_MODE_INCR8 05
+#define INT_DMA_MODE_INCR16 07
+ unsigned dmaenable : 1;
+#define GAHBCFG_DMAENABLE 1
+ unsigned reserved : 1;
+ unsigned nptxfemplvl : 1;
+ unsigned ptxfemplvl : 1;
+#define GAHBCFG_TXFEMPTYLVL_EMPTY 1
+#define GAHBCFG_TXFEMPTYLVL_HALFEMPTY 0
+ unsigned reserved9_31 : 22;
+ } b;
+} gahbcfg_t;
+
+typedef union _gusbcfg_t
+{
+ /** raw register data */
+ u32 d32;
+ /** register bits */
+ struct
+ {
+ unsigned toutcal : 3;
+ unsigned phyif : 1;
+ unsigned ulpi_utmi_sel : 1;
+ unsigned fsintf : 1;
+ unsigned physel : 1;
+ unsigned ddrsel : 1;
+ unsigned srpcap : 1;
+ unsigned hnpcap : 1;
+ unsigned usbtrdtim : 4;
+ unsigned nptxfrwnden : 1;
+ unsigned phylpwrclksel : 1;
+ unsigned reserved : 13;
+ unsigned forcehstmode : 1;
+ unsigned reserved2 : 2;
+ } b;
+} gusbcfg_t;
+
+
+typedef union _ghwcfg2_t
+{
+ /** raw register data */
+ u32 d32;
+ /** register bits */
+ struct {
+ /* GHWCFG2 */
+ unsigned op_mode : 3;
+#define MODE_HNP_SRP_CAPABLE 0
+#define MODE_SRP_ONLY_CAPABLE 1
+#define MODE_NO_HNP_SRP_CAPABLE 2
+#define MODE_SRP_CAPABLE_DEVICE 3
+#define MODE_NO_SRP_CAPABLE_DEVICE 4
+#define MODE_SRP_CAPABLE_HOST 5
+#define MODE_NO_SRP_CAPABLE_HOST 6
+
+ unsigned architecture : 2;
+#define HWCFG2_ARCH_SLAVE_ONLY 0x00
+#define HWCFG2_ARCH_EXT_DMA 0x01
+#define HWCFG2_ARCH_INT_DMA 0x02
+
+ unsigned point2point : 1;
+ unsigned hs_phy_type : 2;
+ unsigned fs_phy_type : 2;
+ unsigned num_dev_ep : 4;
+ unsigned num_host_chan : 4;
+ unsigned perio_ep_supported : 1;
+ unsigned dynamic_fifo : 1;
+ unsigned rx_status_q_depth : 2;
+ unsigned nonperio_tx_q_depth : 2;
+ unsigned host_perio_tx_q_depth : 2;
+ unsigned dev_token_q_depth : 5;
+ unsigned reserved31 : 1;
+ } b;
+} ghwcfg2_t;
+
+typedef union _gintsts_t
+{
+ /** raw register data */
+ u32 d32;
+#define SOF_INTR_MASK 0x0008
+ /** register bits */
+ struct
+ {
+#define HOST_MODE 1
+#define DEVICE_MODE 0
+ unsigned curmode : 1;
+#define OTG_HOST_MODE 1
+#define OTG_DEVICE_MODE 0
+
+ unsigned modemismatch : 1;
+ unsigned otgintr : 1;
+ unsigned sofintr : 1;
+ unsigned rxstsqlvl : 1;
+ unsigned nptxfempty : 1;
+ unsigned ginnakeff : 1;
+ unsigned goutnakeff : 1;
+ unsigned reserved8 : 1;
+ unsigned i2cintr : 1;
+ unsigned erlysuspend : 1;
+ unsigned usbsuspend : 1;
+ unsigned usbreset : 1;
+ unsigned enumdone : 1;
+ unsigned isooutdrop : 1;
+ unsigned eopframe : 1;
+ unsigned intokenrx : 1;
+ unsigned epmismatch : 1;
+ unsigned inepint : 1;
+ unsigned outepintr : 1;
+ unsigned incompisoin : 1;
+ unsigned incompisoout : 1;
+ unsigned reserved22_23 : 2;
+ unsigned portintr : 1;
+ unsigned hcintr : 1;
+ unsigned ptxfempty : 1;
+ unsigned reserved27 : 1;
+ unsigned conidstschng : 1;
+ unsigned disconnect : 1;
+ unsigned sessreqintr : 1;
+ unsigned wkupintr : 1;
+ } b;
+} gintsts_t;
+
+
+typedef union _hcfg_t
+{
+ /** raw register data */
+ u32 d32;
+
+ /** register bits */
+ struct
+ {
+ /** FS/LS Phy Clock Select */
+ unsigned fslspclksel : 2;
+#define HCFG_30_60_MHZ 0
+#define HCFG_48_MHZ 1
+#define HCFG_6_MHZ 2
+
+ /** FS/LS Only Support */
+ unsigned fslssupp : 1;
+ unsigned reserved3_31 : 29;
+ } b;
+} hcfg_t;
+
+typedef union _hprt_t
+{
+ /** raw register data */
+ u32 d32;
+ /** register bits */
+ struct
+ {
+ unsigned prtconnsts : 1;
+ unsigned prtconndet : 1;
+ unsigned prtena : 1;
+ unsigned prtenchng : 1;
+ unsigned prtovrcurract : 1;
+ unsigned prtovrcurrchng : 1;
+ unsigned prtres : 1;
+ unsigned prtsusp : 1;
+ unsigned prtrst : 1;
+ unsigned reserved9 : 1;
+ unsigned prtlnsts : 2;
+ unsigned prtpwr : 1;
+ unsigned prttstctl : 4;
+ unsigned prtspd : 2;
+#define HPRT0_PRTSPD_HIGH_SPEED 0
+#define HPRT0_PRTSPD_FULL_SPEED 1
+#define HPRT0_PRTSPD_LOW_SPEED 2
+ unsigned reserved19_31 : 13;
+ } b;
+} hprt_t;
+
+
+typedef union _gintmsk_t
+{
+ /** raw register data */
+ u32 d32;
+ /** register bits */
+ struct
+ {
+ unsigned reserved0 : 1;
+ unsigned modemismatch : 1;
+ unsigned otgintr : 1;
+ unsigned sofintr : 1;
+ unsigned rxstsqlvl : 1;
+ unsigned nptxfempty : 1;
+ unsigned ginnakeff : 1;
+ unsigned goutnakeff : 1;
+ unsigned reserved8 : 1;
+ unsigned i2cintr : 1;
+ unsigned erlysuspend : 1;
+ unsigned usbsuspend : 1;
+ unsigned usbreset : 1;
+ unsigned enumdone : 1;
+ unsigned isooutdrop : 1;
+ unsigned eopframe : 1;
+ unsigned reserved16 : 1;
+ unsigned epmismatch : 1;
+ unsigned inepintr : 1;
+ unsigned outepintr : 1;
+ unsigned incompisoin : 1;
+ unsigned incompisoout : 1;
+ unsigned reserved22_23 : 2;
+ unsigned portintr : 1;
+ unsigned hcintr : 1;
+ unsigned ptxfempty : 1;
+ unsigned reserved27 : 1;
+ unsigned conidstschng : 1;
+ unsigned disconnect : 1;
+ unsigned sessreqintr : 1;
+ unsigned wkupintr : 1;
+ } b;
+} gintmsk_t;
+
+
+typedef struct _hc_t
+{
+
+ u8 hc_num; // Host channel number used for register address lookup
+
+ unsigned dev_addr : 7; // Device to access
+ unsigned ep_is_in : 1; // EP direction; 0: OUT, 1: IN
+
+ unsigned ep_num : 4; // EP to access
+ unsigned low_speed : 1; // 1: Low speed, 0: Not low speed
+ unsigned ep_type : 2; // Endpoint type.
+ // One of the following values:
+ // - OTG_EP_TYPE_CONTROL: 0
+ // - OTG_EP_TYPE_ISOC: 1
+ // - OTG_EP_TYPE_BULK: 2
+ // - OTG_EP_TYPE_INTR: 3
+
+ unsigned rsvdb1 : 1; // 8 bit padding
+
+ u8 rsvd2; // 4 byte boundary
+
+ unsigned max_packet : 12; // Max packet size in bytes
+
+ unsigned data_pid_start : 2;
+#define OTG_HC_PID_DATA0 0
+#define OTG_HC_PID_DATA2 1
+#define OTG_HC_PID_DATA1 2
+#define OTG_HC_PID_MDATA 3
+#define OTG_HC_PID_SETUP 3
+
+ unsigned multi_count : 2; // Number of periodic transactions per (micro)frame
+
+
+ // Flag to indicate whether the transfer has been started. Set to 1 if
+ // it has been started, 0 otherwise.
+ u8 xfer_started;
+
+
+ // Set to 1 to indicate that a PING request should be issued on this
+ // channel. If 0, process normally.
+ u8 do_ping;
+
+ // Set to 1 to indicate that the error count for this transaction is
+ // non-zero. Set to 0 if the error count is 0.
+ u8 error_state;
+ u32 *xfer_buff; // Pointer to the current transfer buffer position.
+ u16 start_pkt_count; // Packet count at start of transfer.
+
+ u32 xfer_len; // Total number of bytes to transfer.
+ u32 xfer_count; // Number of bytes transferred so far.
+
+
+ // Set to 1 if the host channel has been halted, but the core is not
+ // finished flushing queued requests. Otherwise 0.
+ u8 halt_pending;
+ u8 halt_status; // Reason for halting the host channel
+ u8 short_read; // Set when the host channel does a short read.
+ u8 rsvd3; // 4 byte boundary
+
+} hc_t;
+
+
+// Port status for the HC
+#define HCD_DRIVE_RESET 0x0001
+#define HCD_SEND_SETUP 0x0002
+
+#define HC_MAX_PKT_COUNT 511
+#define HC_MAX_TRANSFER_SIZE 65535
+#define MAXP_SIZE_64BYTE 64
+#define MAXP_SIZE_512BYTE 512
+#define MAXP_SIZE_1024BYTE 1024
+
+typedef union _hcchar_t
+{
+ // raw register data
+ u32 d32;
+
+ // register bits
+ struct
+ {
+ // Maximum packet size in bytes
+ unsigned mps : 11;
+
+ // Endpoint number
+ unsigned epnum : 4;
+
+ // 0: OUT, 1: IN
+ unsigned epdir : 1;
+#define HCDIR_OUT 0
+#define HCDIR_IN 1
+
+ unsigned reserved : 1;
+
+ // 0: Full/high speed device, 1: Low speed device
+ unsigned lspddev : 1;
+
+ // 0: Control, 1: Isoc, 2: Bulk, 3: Intr
+ unsigned eptype : 2;
+#define OTG_EP_TYPE_CONTROL 0
+#define OTG_EP_TYPE_ISOC 1
+#define OTG_EP_TYPE_BULK 2
+#define OTG_EP_TYPE_INTR 3
+
+ // Packets per frame for periodic transfers. 0 is reserved.
+ unsigned multicnt : 2;
+
+ // Device address
+ unsigned devaddr : 7;
+
+ // Frame to transmit periodic transaction.
+ // 0: even, 1: odd
+ unsigned oddfrm : 1;
+
+ // Channel disable
+ unsigned chdis : 1;
+
+ // Channel enable
+ unsigned chen : 1;
+ } b;
+} hcchar_t;
+
+// sztupy: adding struct to handle HCSPLT register
+typedef union _hcsplt_t {
+ // raw register data
+ u32 d32;
+
+ // register bits
+ struct
+ {
+ unsigned prtaddr : 7;
+ unsigned hubaddr : 7;
+ unsigned xactpos : 2;
+ unsigned compsplt : 1;
+ unsigned reserved : 14;
+ unsigned spltena : 1;
+ } b;
+
+} hcsplt_t;
+
+typedef union _hctsiz_t
+{
+ // raw register data
+ u32 d32;
+
+ // register bits
+ struct
+ {
+ // Total transfer size in bytes
+ unsigned xfersize : 19;
+
+ // Data packets to transfer
+ unsigned pktcnt : 10;
+
+ // Packet ID for next data packet
+ // 0: DATA0
+ // 1: DATA2
+ // 2: DATA1
+ // 3: MDATA (non-Control), SETUP (Control)
+ unsigned pid : 2;
+#define HCTSIZ_DATA0 0
+#define HCTSIZ_DATA1 2
+#define HCTSIZ_DATA2 1
+#define HCTSIZ_MDATA 3
+#define HCTSIZ_SETUP 3
+
+ // Do PING protocol when 1
+ unsigned dopng : 1;
+ } b;
+} hctsiz_t;
+
+
+
+typedef union _grxstsr_t
+{
+ // raw register data
+ u32 d32;
+
+ // register bits
+ struct
+ {
+ unsigned chnum : 4;
+ unsigned bcnt : 11;
+ unsigned dpid : 2;
+ unsigned pktsts : 4;
+ unsigned Reserved : 11;
+ } b;
+} grxstsr_t;
+
+typedef union _hfir_t
+{
+ // raw register data
+ u32 d32;
+
+ // register bits
+ struct
+ {
+ unsigned frint : 16;
+ unsigned Reserved : 16;
+ } b;
+} hfir_t;
+
+typedef union _hfnum_t
+{
+ // raw register data
+ u32 d32;
+
+ // register bits
+ struct
+ {
+ unsigned frnum : 16;
+#define HFNUM_MAX_FRNUM 0x3FFF
+ unsigned frrem : 16;
+ } b;
+} hfnum_t;
+
+typedef union grstctl_t
+{
+ /** raw register data */
+ u32 d32;
+ /** register bits */
+ struct
+ {
+ unsigned csftrst : 1;
+ unsigned hsftrst : 1;
+ unsigned hstfrm : 1;
+ unsigned intknqflsh : 1;
+ unsigned rxfflsh : 1;
+ unsigned txfflsh : 1;
+ unsigned txfnum : 5;
+ unsigned reserved11_29 : 19;
+ unsigned dmareq : 1;
+ unsigned ahbidle : 1;
+ } b;
+} grstctl_t;
+
+typedef struct hc_info
+{
+ hcintmsk_t hc_int_msk;
+ hcintn_t hc_int;
+ u32 dma_addr;
+ hcchar_t hc_char;
+ hctsiz_t hc_size;
+}hc_info_t;//, *hc_info_t *, **hc_info_t **;
+
+#ifndef USB_MAXCHILDREN
+ #define USB_MAXCHILDREN (31)
+#endif
+
+typedef struct _usb_hub_descriptor_t
+{
+ u8 desc_length;
+ u8 desc_type;
+ u8 port_number;
+ u16 hub_characteristics;
+ u8 power_on_to_power_good;
+ u8 hub_control_current;
+ /* add 1 bit for hub status change; round to bytes */
+ u8 DeviceRemovable[(USB_MAXCHILDREN + 1 + 7) / 8];
+ u8 port_pwr_ctrl_mask[(USB_MAXCHILDREN + 1 + 7) / 8];
+}usb_hub_descriptor_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/drivers/usb/host/s3c-otg/s3c-otg-common-errorcode.h b/drivers/usb/host/s3c-otg/s3c-otg-common-errorcode.h
new file mode 100644
index 0000000..b2b3bee
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/s3c-otg-common-errorcode.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+ * (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+ *
+ * [File Name] : s3c-otg-common-errorcode.h
+ * [Description] : The Header file defines Error Codes to be used at sub-modules of S3C6400HCD.
+ * [Author] : Yang Soon Yeal { syatom.yang@samsung.com }
+ * [Department] : System LSI Division/System SW Lab
+ * [Created Date]: 2008/06/03
+ * [Revision History]
+ * (1) 2008/06/03 by Yang Soon Yeal { syatom.yang@samsung.com }
+ * - Created this file.
+ * (2) 2008/08/18 by SeungSoo Yang ( ss1.yang@samsung.com )
+ * - add HCD error code
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ ****************************************************************************/
+
+#ifndef _ERROR_CODE_DEF_H
+#define _ERROR_CODE_DEF_H
+
+/*
+// ----------------------------------------------------------------------------
+// Include files : None.
+// ----------------------------------------------------------------------------
+*/
+
+//#include "s3c-otg-common-typedef.h"
+#include "s3c-otg-common-common.h"
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+typedef int USB_ERROR_CODE;
+
+//General USB Error Code.
+#define USB_ERR_SUCCESS 0
+#define USB_ERR_FAIL -1
+
+#define USB_ERR_NO 1
+
+#define USB_ERR_NO_ENTITY -2
+
+//S3CTransfer Error Code
+#define USB_ERR_NODEV -ENODEV
+#define USB_ERR_NOMEM -ENOMEM
+#define USB_ERR_NOSPACE -ENOSPC
+#define USB_ERR_NOIO -EIO
+
+//OTG-HCD error code
+#define USB_ERR_NOELEMENT -ENOENT
+#define USB_ERR_ESHUTDOWN -ESHUTDOWN /* unplug */
+#define USB_ERR_DEQUEUED -ECONNRESET /* unlink */
+
+
+//S3CScheduler Error Code
+#define USB_ERR_ALREADY_EXIST -1
+#define USB_ERR_NO_RESOURCE -2
+#define USB_ERR_NO_CHANNEL -3
+#define USB_ERR_NO_BANDWIDTH -4
+#define USB_ERR_ALL_RESROUCE -5
+
+
+
+
+/************************************************
+ *Defines the USB Error Status Code of USB Transfer.
+ ************************************************/
+
+//#ifdef LINUX
+
+#define USB_ERR_STATUS_COMPLETE 0
+#define USB_ERR_STATUS_INPROGRESS -EINPROGRESS
+#define USB_ERR_STATUS_CRC -EILSEQ
+#define USB_ERR_STATUS_XACTERR -EPROTO
+#define USB_ERR_STATUS_STALL -EPIPE
+#define USB_ERR_STATUS_BBLERR -EOVERFLOW
+#define USB_ERR_STATUS_AHBERR -EIO
+#define USB_ERR_STATUS_FRMOVRUN_OUT -ENOSR
+#define USB_ERR_STATUS_FRMOVRUN_IN -ECOMM
+#define USB_ERR_STATUS_SHORTREAD -EREMOTEIO
+
+//#else
+
+//#endif
+
+
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
+
diff --git a/drivers/usb/host/s3c-otg/s3c-otg-common-regdef.h b/drivers/usb/host/s3c-otg/s3c-otg-common-regdef.h
new file mode 100644
index 0000000..ed119d7
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/s3c-otg-common-regdef.h
@@ -0,0 +1,302 @@
+/****************************************************************************
+* (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+*
+* [File Name] : s3c-otg-common-regdef.h
+* [Description] :
+*
+* [Author] : Kyu Hyeok Jang { kyuhyeok.jang@samsung.com }
+* [Department] : System LSI Division/Embedded Software Center
+* [Created Date]: 2007/12/15
+* [Revision History]
+* (1) 2007/12/15 by Kyu Hyeok Jang { kyuhyeok.jang@samsung.com }
+* - Created
+*
+****************************************************************************/
+/****************************************************************************
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ ****************************************************************************/
+
+#ifndef _OTG_REG_DEF_H
+#define _OTG_REG_DEF_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef struct {
+ u32 OPHYPWR;
+ u32 OPHYCLK;
+ u32 ORSTCON;
+}OTG_PHY_REG, *PS_OTG_PHY_REG;
+
+#define GOTGCTL 0x000 // OTG Control & Status
+#define GOTGINT 0x004 // OTG Interrupt
+#define GAHBCFG 0x008 // Core AHB Configuration
+#define GUSBCFG 0x00C // Core USB Configuration
+#define GRSTCTL 0x010 // Core Reset
+#define GINTSTS 0x014 // Core Interrupt
+#define GINTMSK 0x018 // Core Interrupt Mask
+#define GRXSTSR 0x01C // Receive Status Debug Read/Status Read
+#define GRXSTSP 0x020 // Receive Status Debug Pop/Status Pop
+#define GRXFSIZ 0x024 // Receive FIFO Size
+#define GNPTXFSIZ 0x028 // Non-Periodic Transmit FIFO Size
+#define GNPTXSTS 0x02C // Non-Periodic Transmit FIFO/Queue Status
+#define GPVNDCTL 0x034 // PHY Vendor Control
+#define GGPIO 0x038 // General Purpose I/O
+#define GUID 0x03C // User ID
+#define GSNPSID 0x040 // Synopsys ID
+#define GHWCFG1 0x044 // User HW Config1
+#define GHWCFG2 0x048 // User HW Config2
+#define GHWCFG3 0x04C // User HW Config3
+#define GHWCFG4 0x050 // User HW Config4
+
+#define HPTXFSIZ 0x100 // Host Periodic Transmit FIFO Size
+#define DPTXFSIZ1 0x104 // Device Periodic Transmit FIFO-1 Size
+#define DPTXFSIZ2 0x108 // Device Periodic Transmit FIFO-2 Size
+#define DPTXFSIZ3 0x10C // Device Periodic Transmit FIFO-3 Size
+#define DPTXFSIZ4 0x110 // Device Periodic Transmit FIFO-4 Size
+#define DPTXFSIZ5 0x114 // Device Periodic Transmit FIFO-5 Size
+#define DPTXFSIZ6 0x118 // Device Periodic Transmit FIFO-6 Size
+#define DPTXFSIZ7 0x11C // Device Periodic Transmit FIFO-7 Size
+#define DPTXFSIZ8 0x120 // Device Periodic Transmit FIFO-8 Size
+#define DPTXFSIZ9 0x124 // Device Periodic Transmit FIFO-9 Size
+#define DPTXFSIZ10 0x128 // Device Periodic Transmit FIFO-10 Size
+#define DPTXFSIZ11 0x12C // Device Periodic Transmit FIFO-11 Size
+#define DPTXFSIZ12 0x130 // Device Periodic Transmit FIFO-12 Size
+#define DPTXFSIZ13 0x134 // Device Periodic Transmit FIFO-13 Size
+#define DPTXFSIZ14 0x138 // Device Periodic Transmit FIFO-14 Size
+#define DPTXFSIZ15 0x13C // Device Periodic Transmit FIFO-15 Size
+
+//*********************************************************************
+// Host Mode Registers
+//*********************************************************************
+// Host Global Registers
+
+// Channel specific registers
+#define HCCHAR_ADDR 0x500
+#define HCCHAR(n) 0x500 + ((n)*0x20)
+#define HCSPLT(n) 0x504 + ((n)*0x20)
+#define HCINT(n) 0x508 + ((n)*0x20)
+#define HCINTMSK(n) 0x50C + ((n)*0x20)
+#define HCTSIZ(n) 0x510 + ((n)*0x20)
+#define HCDMA(n) 0x514 + ((n)*0x20)
+
+#define HCFG 0x400 // Host Configuration
+#define HFIR 0x404 // Host Frame Interval
+#define HFNUM 0x408 // Host Frame Number/Frame Time Remaining
+#define HPTXSTS 0x410 // Host Periodic Transmit FIFO/Queue Status
+#define HAINT 0x414 // Host All Channels Interrupt
+#define HAINTMSK 0x418 // Host All Channels Interrupt Mask
+
+// Host Port Control & Status Registers
+
+#define HPRT 0x440 // Host Port Control & Status
+
+// Device Logical Endpoints-Specific Registers
+
+#define DIEPCTL 0x900 // Device IN Endpoint 0 Control
+#define DOEPCTL(n) 0xB00 + ((n)*0x20)) // Device OUT Endpoint 0 Control
+#define DIEPINT(n) 0x908 + ((n)*0x20)) // Device IN Endpoint 0 Interrupt
+#define DOEPINT(n) 0xB08 + ((n)*0x20)) // Device OUT Endpoint 0 Interrupt
+#define DIEPTSIZ(n) 0x910 + ((n)*0x20)) // Device IN Endpoint 0 Transfer Size
+#define DOEPTSIZ(n) 0xB10 + ((n)*0x20)) // Device OUT Endpoint 0 Transfer Size
+#define DIEPDMA(n) 0x914 + ((n)*0x20)) // Device IN Endpoint 0 DMA Address
+#define DOEPDMA(n) 0xB14 + ((n)*0x20)) // Device OUT Endpoint 0 DMA Address
+
+#define EP_FIFO(n) 0x1000 + ((n)*0x1000))
+
+#define PCGCCTL 0x0E00
+
+//
+#define BASE_REGISTER_OFFSET 0x0
+#define REGISTER_SET_SIZE 0x200
+
+// Power Reg Bits
+#define USB_RESET 0x8
+#define MCU_RESUME 0x4
+#define SUSPEND_MODE 0x2
+#define SUSPEND_MODE_ENABLE_CTRL 0x1
+
+// EP0 CSR
+#define EP0_OUT_PACKET_RDY 0x1
+#define EP0_IN_PACKET_RDY 0x2
+#define EP0_SENT_STALL 0x4
+#define DATA_END 0x8
+#define SETUP_END 0x10
+#define EP0_SEND_STALL 0x20
+#define SERVICED_OUT_PKY_RDY 0x40
+#define SERVICED_SETUP_END 0x80
+
+// IN_CSR1_REG Bit definitions
+#define IN_PACKET_READY 0x1
+#define UNDER_RUN 0x4 // Iso Mode Only
+#define FLUSH_IN_FIFO 0x8
+#define IN_SEND_STALL 0x10
+#define IN_SENT_STALL 0x20
+#define IN_CLR_DATA_TOGGLE 0x40
+
+// OUT_CSR1_REG Bit definitions
+#define OUT_PACKET_READY 0x1
+#define FLUSH_OUT_FIFO 0x10
+#define OUT_SEND_STALL 0x20
+#define OUT_SENT_STALL 0x40
+#define OUT_CLR_DATA_TOGGLE 0x80
+
+// IN_CSR2_REG Bit definitions
+#define IN_DMA_INT_DISABLE 0x10
+#define SET_MODE_IN 0x20
+
+#define EPTYPE (0x3<<18)
+#define SET_TYPE_CONTROL (0x0<<18)
+#define SET_TYPE_ISO (0x1<<18)
+#define SET_TYPE_BULK (0x2<<18)
+#define SET_TYPE_INTERRUPT (0x3<<18)
+
+#define AUTO_MODE 0x80
+
+// OUT_CSR2_REG Bit definitions
+#define AUTO_CLR 0x40
+#define OUT_DMA_INT_DISABLE 0x20
+
+// Can be used for Interrupt and Interrupt Enable Reg - common bit def
+#define EP0_IN_INT (0x1<<0)
+#define EP1_IN_INT (0x1<<1)
+#define EP2_IN_INT (0x1<<2)
+#define EP3_IN_INT (0x1<<3)
+#define EP4_IN_INT (0x1<<4)
+#define EP5_IN_INT (0x1<<5)
+#define EP6_IN_INT (0x1<<6)
+#define EP7_IN_INT (0x1<<7)
+#define EP8_IN_INT (0x1<<8)
+#define EP9_IN_INT (0x1<<9)
+#define EP10_IN_INT (0x1<<10)
+#define EP11_IN_INT (0x1<<11)
+#define EP12_IN_INT (0x1<<12)
+#define EP13_IN_INT (0x1<<13)
+#define EP14_IN_INT (0x1<<14)
+#define EP15_IN_INT (0x1<<15)
+#define EP0_OUT_INT (0x1<<16)
+#define EP1_OUT_INT (0x1<<17)
+#define EP2_OUT_INT (0x1<<18)
+#define EP3_OUT_INT (0x1<<19)
+#define EP4_OUT_INT (0x1<<20)
+#define EP5_OUT_INT (0x1<<21)
+#define EP6_OUT_INT (0x1<<22)
+#define EP7_OUT_INT (0x1<<23)
+#define EP8_OUT_INT (0x1<<24)
+#define EP9_OUT_INT (0x1<<25)
+#define EP10_OUT_INT (0x1<<26)
+#define EP11_OUT_INT (0x1<<27)
+#define EP12_OUT_INT (0x1<<28)
+#define EP13_OUT_INT (0x1<<29)
+#define EP14_OUT_INT (0x1<<30)
+#define EP15_OUT_INT (0x1<<31)
+
+// GOTGINT
+#define SesEndDet (0x1<<2)
+
+// GRSTCTL
+#define TxFFlsh (0x1<<5)
+#define RxFFlsh (0x1<<4)
+#define INTknQFlsh (0x1<<3)
+#define FrmCntrRst (0x1<<2)
+#define HSftRst (0x1<<1)
+#define CSftRst (0x1<<0)
+
+#define CLEAR_ALL_EP_INTRS 0xffffffff
+
+#define EP_INTERRUPT_DISABLE_ALL 0x0 // Bits to write to EP_INT_EN_REG - Use CLEAR
+
+// DMA control register bit definitions
+#define RUN_OB 0x80
+#define STATE 0x70
+#define DEMAND_MODE 0x8
+#define OUT_DMA_RUN 0x4
+#define IN_DMA_RUN 0x2
+#define DMA_MODE_EN 0x1
+
+
+#define REAL_PHYSICAL_ADDR_EP0_FIFO (0x520001c0) //Endpoint 0 FIFO
+#define REAL_PHYSICAL_ADDR_EP1_FIFO (0x520001c4) //Endpoint 1 FIFO
+#define REAL_PHYSICAL_ADDR_EP2_FIFO (0x520001c8) //Endpoint 2 FIFO
+#define REAL_PHYSICAL_ADDR_EP3_FIFO (0x520001cc) //Endpoint 3 FIFO
+#define REAL_PHYSICAL_ADDR_EP4_FIFO (0x520001d0) //Endpoint 4 FIFO
+
+// GAHBCFG
+#define MODE_DMA (1<<5)
+#define MODE_SLAVE (0<<5)
+#define BURST_SINGLE (0<<1)
+#define BURST_INCR (1<<1)
+#define BURST_INCR4 (3<<1)
+#define BURST_INCR8 (5<<1)
+#define BURST_INCR16 (7<<1)
+#define GBL_INT_MASK (0<<0)
+#define GBL_INT_UNMASK (1<<0)
+
+// For USB DMA
+//BOOL InitUsbdDriverGlobals(void); //:-)
+//void UsbdDeallocateVm(void); //:-)
+//BOOL UsbdAllocateVm(void); //:-)
+//void UsbdInitDma(int epnum, int bufIndex,int bufOffset); //:-)
+
+
+//by Kevin
+
+//////////////////////////////////////////////////////////////////////////
+
+/*
+inline u32 ReadReg(
+ u32 uiOffset
+ )
+{
+ volatile u32 *pbReg = ctrlr_base_reg_addr(uiOffset);
+ u32 uiValue = (u32) *pbReg;
+ return uiValue;
+}
+
+inline void WriteReg(
+ u32 uiOffset,
+ u32 bValue
+ )
+{
+ volatile ULONG *pbReg = ctrlr_base_reg_addr(uiOffset);
+ *pbReg = (ULONG) bValue;
+}
+
+inline void UpdateReg(
+ u32 uiOffset,
+ u32 bValue
+ )
+{
+ WriteReg(uiOffset, (ReadReg(uiOffset) | bValue));
+};
+
+inline void ClearReg(
+ u32 uiOffeset,
+ u32 bValue
+ )
+{
+ WriteReg(uiOffeset, (ReadReg(uiOffeset) & ~bValue));
+};
+*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/drivers/usb/host/s3c-otg/s3c-otg-hcdi-debug.h b/drivers/usb/host/s3c-otg/s3c-otg-hcdi-debug.h
new file mode 100644
index 0000000..20416b1
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/s3c-otg-hcdi-debug.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+ * (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+ *
+ * @file s3c-otg-hcdi-debug.c
+ * @brief It provides debug functions for display message \n
+ * @version
+ * -# Jun 9,2008 v1.0 by SeungSoo Yang (ss1.yang@samsung.com) \n
+ * : Creating the initial version of this code \n
+ * -# Jul 15,2008 v1.2 by SeungSoo Yang (ss1.yang@samsung.com) \n
+ * : Optimizing for performance \n
+ * @see None
+ ****************************************************************************/
+/****************************************************************************
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ ****************************************************************************/
+
+#ifndef _S3C_OTG_HCDI_DEBUG_H_
+#define _S3C_OTG_HCDI_DEBUG_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define OTG_DEBUG
+
+#ifdef OTG_DEBUG
+#if 0
+#include <linux/stddef.h>
+#endif
+
+#define OTG_DBG_OTGHCDI_DRIVER true
+#define OTG_DBG_OTGHCDI_HCD false
+#define OTG_DBG_OTGHCDI_KAL false
+#define OTG_DBG_OTGHCDI_LIST false
+#define OTG_DBG_OTGHCDI_MEM false
+
+#define OTG_DBG_TRANSFER false
+#define OTG_DBG_SCHEDULE false
+#define OTG_DBG_OCI false
+#define OTG_DBG_DONETRASF false
+#define OTG_DBG_ISR false
+#define OTG_DBG_ROOTHUB false
+
+
+#include <linux/kernel.h> //for printk
+
+#define otg_err(is_active, msg...) \
+ do{ if (/*(is_active) == */true)\
+ {\
+ pr_err("otg_err: in %s()::%05d ", __func__ , __LINE__); \
+ pr_err("=> " msg); \
+ }\
+ }while(0)
+
+#define otg_dbg(is_active, msg...) \
+ do{ if ((is_active) == true)\
+ {\
+ pr_info("otg_dbg: in %s()::%05d ", __func__, __LINE__); \
+ pr_info("=> " msg); \
+ }\
+ }while(0)
+
+#else //OTG_DEBUG
+
+# define otg_err(is_active, msg...) do{}while(0)
+# define otg_dbg(is_active, msg...) do{}while(0)
+
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _S3C_OTG_HCDI_DEBUG_H_ */
diff --git a/drivers/usb/host/s3c-otg/s3c-otg-hcdi-driver.c b/drivers/usb/host/s3c-otg/s3c-otg-hcdi-driver.c
new file mode 100644
index 0000000..f99261f
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/s3c-otg-hcdi-driver.c
@@ -0,0 +1,386 @@
+/****************************************************************************
+ * (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+ *
+ * @file s3c-otg-hcdi-driver.c
+ * @brief It provides functions related with module for OTGHCD driver. \n
+ * @version
+ * -# Jun 9,2008 v1.0 by SeungSoo Yang (ss1.yang@samsung.com) \n
+ * : Creating the initial version of this code \n
+ * -# Jul 15,2008 v1.2 by SeungSoo Yang (ss1.yang@samsung.com) \n
+ * : Optimizing for performance \n
+ * -# Aug 18,2008 v1.3 by SeungSoo Yang (ss1.yang@samsung.com) \n
+ * : Modifying for successful rmmod & disconnecting \n
+ * @see None
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * 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 "s3c-otg-hcdi-driver.h"
+#include "../../gadget/s3c_udc.h"
+extern void otg_phy_off(void);
+
+/**
+ * static int s5pc110_otg_drv_probe (struct platform_device *pdev)
+ *
+ * @brief probe function of OTG hcd platform_driver
+ *
+ * @param [in] pdev : pointer of platform_device of otg hcd platform_driver
+ *
+ * @return USB_ERR_SUCCESS : If success \n
+ * USB_ERR_FAIL : If fail \n
+ * @remark
+ * it allocates resources of it and call other modules' init function.
+ * then call usb_create_hcd, usb_add_hcd, s5pc110_otghcd_start functions
+ */
+
+struct usb_hcd* g_pUsbHcd = NULL;
+
+static void otg_power_work(struct work_struct *work)
+{
+ struct sec_otghost *otghost = container_of(work,
+ struct sec_otghost, work);
+ struct sec_otghost_data *hdata = otghost->otg_data;
+
+ if (hdata && hdata->set_pwr_cb) {
+ hdata->set_pwr_cb(0);
+#ifdef CONFIG_USB_HOST_NOTIFY
+ if (g_pUsbHcd)
+ host_state_notify(&g_pUsbHcd->ndev, NOTIFY_HOST_OVERCURRENT);
+#endif
+ } else {
+ otg_err(true, "invalid otghost data\n");
+ }
+}
+
+static int s5pc110_otg_drv_probe (struct platform_device *pdev)
+{
+ int ret_val = 0;
+ u32 reg_val = 0;
+ struct sec_otghost *otghost = NULL;
+ struct sec_otghost_data *otg_data = dev_get_platdata(&pdev->dev);
+
+ otg_dbg(OTG_DBG_OTGHCDI_DRIVER, "s3c_otg_drv_probe\n");
+
+ reset_scheduler_numbers();
+ /*init for host mode*/
+ /**
+ Allocate memory for the base HCD & Initialize the base HCD.
+ */
+ g_pUsbHcd = usb_create_hcd(&s5pc110_otg_hc_driver, &pdev->dev,
+ "s3cotg");/*pdev->dev.bus_id*/
+ if (g_pUsbHcd == NULL) {
+ ret_val = -ENOMEM;
+ otg_err(OTG_DBG_OTGHCDI_DRIVER,
+ "failed to usb_create_hcd\n");
+ goto err_out_clk;
+ }
+
+ /* mapping hcd resource & device resource*/
+
+ g_pUsbHcd->rsrc_start = pdev->resource[0].start;
+ g_pUsbHcd->rsrc_len = pdev->resource[0].end -
+ pdev->resource[0].start + 1;
+
+ if (!request_mem_region(g_pUsbHcd->rsrc_start, g_pUsbHcd->rsrc_len,
+ gHcdName)) {
+ otg_err(OTG_DBG_OTGHCDI_DRIVER,
+ "failed to request_mem_region\n");
+ ret_val = -EBUSY;
+ goto err_out_create_hcd;
+ }
+
+
+ /* Physical address => Virtual address */
+ g_pUsbHcd->regs = S3C_VA_OTG;
+ g_pUsbHcd->self.otg_port = 1;
+
+ g_pUDCBase = (u8 *)g_pUsbHcd->regs;
+
+ otghost = hcd_to_sec_otghost(g_pUsbHcd);
+
+ if (otghost == NULL) {
+ otg_err(true, "failed to get otghost hcd\n");
+ ret_val = USB_ERR_FAIL;
+ goto err_out_create_hcd;
+ }
+ otghost->otg_data = otg_data;
+
+ if ((s3c_get_drivermode()) & USB_OTG_DRIVER_S3CFSLS) {
+ otghost->is_hs = 0; // force USB 1.x mode
+ } else {
+ otghost->is_hs = 1;
+ }
+
+ INIT_WORK(&otghost->work, otg_power_work);
+ otghost->wq = create_singlethread_workqueue("sec_otghostd");
+
+ /* call others' init() */
+ ret_val = otg_hcd_init_modules(otghost);
+ if (ret_val != USB_ERR_SUCCESS) {
+ otg_err(OTG_DBG_OTGHCDI_DRIVER,
+ "failed to otg_hcd_init_modules\n");
+ ret_val = USB_ERR_FAIL;
+ goto err_out_create_hcd;
+ }
+
+ /**
+ * Attempt to ensure this device is really a s5pc110 USB-OTG Controller.
+ * Read and verify the SNPSID register contents. The value should be
+ * 0x45F42XXX, which corresponds to "OT2", as in "OTG version 2.XX".
+ */
+ reg_val = read_reg_32(0x40);
+ if ((reg_val & 0xFFFFF000) != 0x4F542000) {
+ otg_err(OTG_DBG_OTGHCDI_DRIVER,
+ "Bad value for SNPSID: 0x%x\n", reg_val);
+ ret_val = -EINVAL;
+ goto err_out_create_hcd_init;
+ }
+#ifdef CONFIG_USB_HOST_NOTIFY
+ if (otg_data->host_notify) {
+ g_pUsbHcd->host_notify = otg_data->host_notify;
+ g_pUsbHcd->ndev.name = dev_name(&pdev->dev);
+ ret_val = host_notify_dev_register(&g_pUsbHcd->ndev);
+ if (ret_val) {
+ otg_err(OTG_DBG_OTGHCDI_DRIVER,
+ "Failed to host_notify_dev_register\n");
+ goto err_out_create_hcd_init;
+ }
+ }
+#endif
+#ifdef CONFIG_USB_SEC_WHITELIST
+ if (otg_data->sec_whlist_table_num)
+ g_pUsbHcd->sec_whlist_table_num = otg_data->sec_whlist_table_num;
+#endif
+
+ /*
+ * Finish generic HCD initialization and start the HCD. This function
+ * allocates the DMA buffer pool, registers the USB bus, requests the
+ * IRQ line, and calls s5pc110_otghcd_start method.
+ */
+ ret_val = usb_add_hcd(g_pUsbHcd,
+ pdev->resource[1].start, IRQF_DISABLED);
+ if (ret_val < 0) {
+ goto err_out_host_notify_register;
+ }
+
+ otg_dbg(OTG_DBG_OTGHCDI_DRIVER,
+ "OTG HCD Initialized HCD, bus=%s, usbbus=%d\n",
+ "C110 OTG Controller", g_pUsbHcd->self.busnum);
+
+ /* otg_print_registers(); */
+
+ wake_lock_init(&otghost->wake_lock, WAKE_LOCK_SUSPEND, "usb_otg");
+ wake_lock(&otghost->wake_lock);
+
+ return USB_ERR_SUCCESS;
+err_out_host_notify_register:
+#ifdef CONFIG_USB_HOST_NOTIFY
+ host_notify_dev_unregister(&g_pUsbHcd->ndev);
+#endif
+
+err_out_create_hcd_init:
+ otg_hcd_deinit_modules(otghost);
+ release_mem_region(g_pUsbHcd->rsrc_start, g_pUsbHcd->rsrc_len);
+
+err_out_create_hcd:
+ usb_put_hcd(g_pUsbHcd);
+
+err_out_clk:
+
+ return ret_val;
+}
+
+/**
+ * static int s5pc110_otg_drv_remove (struct platform_device *dev)
+ *
+ * @brief remove function of OTG hcd platform_driver
+ *
+ * @param [in] pdev : pointer of platform_device of otg hcd platform_driver
+ *
+ * @return USB_ERR_SUCCESS : If success \n
+ * USB_ERR_FAIL : If fail \n
+ * @remark
+ * This function is called when the otg device unregistered with the
+ * s5pc110_otg_driver. This happens, for example, when the rmmod command is
+ * executed. The device may or may not be electrically present. If it is
+ * present, the driver stops device processing. Any resources used on behalf
+ * of this device are freed.
+ */
+static int s5pc110_otg_drv_remove (struct platform_device *dev)
+{
+ struct sec_otghost *otghost = NULL;
+
+ otg_dbg(OTG_DBG_OTGHCDI_DRIVER, "s5pc110_otg_drv_remove\n");
+
+ otghost = hcd_to_sec_otghost(g_pUsbHcd);
+
+#ifdef CONFIG_USB_HOST_NOTIFY
+ host_notify_dev_unregister(&g_pUsbHcd->ndev);
+#endif
+
+ otg_hcd_deinit_modules(otghost);
+
+ destroy_workqueue(otghost->wq);
+
+ wake_unlock(&otghost->wake_lock);
+ wake_lock_destroy(&otghost->wake_lock);
+
+ usb_remove_hcd(g_pUsbHcd);
+
+ release_mem_region(g_pUsbHcd->rsrc_start, g_pUsbHcd->rsrc_len);
+
+ usb_put_hcd(g_pUsbHcd);
+
+ otg_phy_off();
+
+ return USB_ERR_SUCCESS;
+}
+
+/**
+ * @struct s5pc110_otg_driver
+ *
+ * @brief
+ * This structure defines the methods to be called by a bus driver
+ * during the lifecycle of a device on that bus. Both drivers and
+ * devices are registered with a bus driver. The bus driver matches
+ * devices to drivers based on information in the device and driver
+ * structures.
+ *
+ * The probe function is called when the bus driver matches a device
+ * to this driver. The remove function is called when a device is
+ * unregistered with the bus driver.
+ */
+struct platform_driver s5pc110_otg_driver = {
+ .probe = s5pc110_otg_drv_probe,
+ .remove = s5pc110_otg_drv_remove,
+ .shutdown = usb_hcd_platform_shutdown,
+ .driver = {
+ .name = "s3c_otghcd",
+ .owner = THIS_MODULE,
+ },
+};
+
+/**
+ * static int __init s5pc110_otg_module_init(void)
+ *
+ * @brief module_init function
+ *
+ * @return it returns result of platform_driver_register
+ * @remark
+ * This function is called when the s5pc110_otg_driver is installed with the
+ * insmod command. It registers the s5pc110_otg_driver structure with the
+ * appropriate bus driver. This will cause the s5pc110_otg_driver_probe function
+ * to be called. In addition, the bus driver will automatically expose
+ * attributes defined for the device and driver in the special sysfs file
+ * system.
+ */
+ /*
+static int __init s5pc110_otg_module_init(void)
+{
+ int ret_val = 0;
+
+ otg_dbg(OTG_DBG_OTGHCDI_DRIVER,
+ "s3c_otg_module_init \n");
+
+ ret_val = platform_driver_register(&s5pc110_otg_driver);
+ if (ret_val < 0)
+ {
+ otg_err(OTG_DBG_OTGHCDI_DRIVER,
+ "platform_driver_register \n");
+ }
+ return ret_val;
+} */
+
+/**
+ * static void __exit s5pc110_otg_module_exit(void)
+ *
+ * @brief module_exit function
+ *
+ * @remark
+ * This function is called when the driver is removed from the kernel
+ * with the rmmod command. The driver unregisters itself with its bus
+ * driver.
+ */
+static void __exit s5pc110_otg_module_exit(void)
+{
+ otg_dbg(OTG_DBG_OTGHCDI_DRIVER,
+ "s3c_otg_module_exit \n");
+ platform_driver_unregister(&s5pc110_otg_driver);
+}
+
+/* for debug */
+void otg_print_registers(void)
+{
+ /* USB PHY Control Registers */
+ otg_dbg(OTG_DBG_OTGHCDI_DRIVER,
+ "USB_CONTROL = 0x%x.\n", readl(0xfb10e80c));
+ otg_dbg(OTG_DBG_OTGHCDI_DRIVER,
+ "UPHYPWR = 0x%x.\n", readl(S3C_USBOTG_PHYPWR));
+ otg_dbg(OTG_DBG_OTGHCDI_DRIVER,
+ "UPHYCLK = 0x%x.\n", readl(S3C_USBOTG_PHYCLK));
+ otg_dbg(OTG_DBG_OTGHCDI_DRIVER,
+ "URSTCON = 0x%x.\n", readl(S3C_USBOTG_RSTCON));
+
+ /* OTG LINK Core registers (Core Global Registers) */
+ otg_dbg(OTG_DBG_OTGHCDI_DRIVER,
+ "GOTGCTL = 0x%x.\n", read_reg_32(GOTGCTL));
+ otg_dbg(OTG_DBG_OTGHCDI_DRIVER,
+ "GOTGINT = 0x%x.\n", read_reg_32(GOTGINT));
+ otg_dbg(OTG_DBG_OTGHCDI_DRIVER,
+ "GAHBCFG = 0x%x.\n", read_reg_32(GAHBCFG));
+ otg_dbg(OTG_DBG_OTGHCDI_DRIVER,
+ "GUSBCFG = 0x%x.\n", read_reg_32(GUSBCFG));
+ otg_dbg(OTG_DBG_OTGHCDI_DRIVER,
+ "GINTSTS = 0x%x.\n", read_reg_32(GINTSTS));
+ otg_dbg(OTG_DBG_OTGHCDI_DRIVER,
+ "GINTMSK = 0x%x.\n", read_reg_32(GINTMSK));
+
+ /* Host Mode Registers */
+ otg_dbg(OTG_DBG_OTGHCDI_DRIVER,
+ "HCFG = 0x%x.\n", read_reg_32(HCFG));
+ otg_dbg(OTG_DBG_OTGHCDI_DRIVER,
+ "HPRT = 0x%x.\n", read_reg_32(HPRT));
+ otg_dbg(OTG_DBG_OTGHCDI_DRIVER,
+ "HFIR = 0x%x.\n", read_reg_32(HFIR));
+
+ /* Synopsys ID */
+ otg_dbg(OTG_DBG_OTGHCDI_DRIVER,
+ "GSNPSID = 0x%x.\n", read_reg_32(GSNPSID));
+
+ /* HWCFG */
+ otg_dbg(OTG_DBG_OTGHCDI_DRIVER,
+ "GHWCFG1 = 0x%x.\n", read_reg_32(GHWCFG1));
+ otg_dbg(OTG_DBG_OTGHCDI_DRIVER,
+ "GHWCFG2 = 0x%x.\n", read_reg_32(GHWCFG2));
+ otg_dbg(OTG_DBG_OTGHCDI_DRIVER,
+ "GHWCFG3 = 0x%x.\n", read_reg_32(GHWCFG3));
+ otg_dbg(OTG_DBG_OTGHCDI_DRIVER,
+ "GHWCFG4 = 0x%x.\n", read_reg_32(GHWCFG4));
+
+ /* PCGCCTL */
+ otg_dbg(OTG_DBG_OTGHCDI_DRIVER,
+ "PCGCCTL = 0x%x.\n", read_reg_32(PCGCCTL));
+}
+
+/*
+module_init(s5pc110_otg_module_init);
+module_exit(s5pc110_otg_module_exit);
+*/
+
+MODULE_DESCRIPTION("OTG USB HOST controller driver");
+MODULE_AUTHOR("SAMSUNG / System LSI / EMSP");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/host/s3c-otg/s3c-otg-hcdi-driver.h b/drivers/usb/host/s3c-otg/s3c-otg-hcdi-driver.h
new file mode 100644
index 0000000..4488df2
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/s3c-otg-hcdi-driver.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+ * (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+ *
+ * @file s3c-otg-hcdi-driver.h
+ * @brief header of s3c-otg-hcdi-driver \n
+ * @version
+ * -# Jun 9,2008 v1.0 by SeungSoo Yang (ss1.yang@samsung.com) \n
+ * : Creating the initial version of this code \n
+ * -# Jul 15,2008 v1.2 by SeungSoo Yang (ss1.yang@samsung.com) \n
+ * : Optimizing for performance \n
+ * -# Aug 18,2008 v1.3 by SeungSoo Yang (ss1.yang@samsung.com) \n
+ * : Modifying for successful rmmod & disconnecting \n
+ * @see None
+ ****************************************************************************/
+/****************************************************************************
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ ****************************************************************************/
+
+#ifndef _S3C_OTG_HCDI_DRIVER_H_
+#define _S3C_OTG_HCDI_DRIVER_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <linux/module.h>
+#include <linux/init.h>
+//#include <linux/clk.h> //for clk_get, clk_enable etc.
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h> //for SA_SHIRQ
+#include <mach/map.h> //address for smdk
+#include <linux/dma-mapping.h> //dma_alloc_coherent
+#include <linux/ioport.h> //request_mem_request ...
+#include <asm/irq.h> //for IRQ_OTG
+#include <linux/clk.h>
+
+
+#include "s3c-otg-common-common.h"
+#include "s3c-otg-common-regdef.h"
+
+#include "s3c-otg-hcdi-debug.h"
+#include "s3c-otg-hcdi-hcd.h"
+#include "s3c-otg-hcdi-kal.h"
+
+
+volatile u8 * g_pUDCBase;
+
+static const char gHcdName[] = "EMSP_OTG_HCD";
+
+//extern int otg_hcd_init_modules(struct sec_otghost *otghost);
+//extern void otg_hcd_deinit_modules(struct sec_otghost *otghost);
+
+//void otg_print_registers();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _S3C_OTG_HCDI_DRIVER_H_ */
diff --git a/drivers/usb/host/s3c-otg/s3c-otg-hcdi-hcd.c b/drivers/usb/host/s3c-otg/s3c-otg-hcdi-hcd.c
new file mode 100644
index 0000000..2b440a3
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/s3c-otg-hcdi-hcd.c
@@ -0,0 +1,708 @@
+/****************************************************************************
+ * (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+ *
+ * @file s3c-otg-hcdi-hcd.c
+ * @brief implementation of structure hc_drive \n
+ * @version
+ * -# Jun 11,2008 v1.0 by SeungSoo Yang (ss1.yang@samsung.com) \n
+ * : Creating the initial version of this code \n
+ * -# Jul 15,2008 v1.2 by SeungSoo Yang (ss1.yang@samsung.com) \n
+ * : Optimizing for performance \n
+ * -# Aug 18,2008 v1.3 by SeungSoo Yang (ss1.yang@samsung.com) \n
+ * : Modifying for successful rmmod & disconnecting \n
+ * @see None
+ ****************************************************************************/
+/****************************************************************************
+ * 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 "s3c-otg-hcdi-hcd.h"
+
+/**
+ * otg_hcd_init_modules(struct sec_otghost *otghost)
+ *
+ * @brief call other modules' init functions
+ *
+ * @return PASS : If success \n
+ * FAIL : If fail \n
+ */
+int otg_hcd_init_modules(struct sec_otghost *otghost)
+{
+ unsigned long spin_lock_flag = 0;
+
+ otg_dbg(OTG_DBG_OTGHCDI_HCD, "otg_hcd_init_modules\n");
+
+ spin_lock_init(&otghost->lock);
+
+ spin_lock_irq_save_otg(&otghost->lock, spin_lock_flag);
+
+ init_transfer();
+ init_scheduler();
+ oci_init(otghost);
+
+ spin_unlock_irq_save_otg(&otghost->lock, spin_lock_flag);
+
+ return USB_ERR_SUCCESS;
+};
+
+/**
+ * void otg_hcd_deinit_modules(struct sec_otghost *otghost)
+ *
+ * @brief call other modules' de-init functions
+ *
+ * @return PASS : If success \n
+ * FAIL : If fail \n
+ */
+void otg_hcd_deinit_modules(struct sec_otghost *otghost)
+{
+ unsigned long spin_lock_flag = 0;
+
+ otg_dbg(OTG_DBG_OTGHCDI_HCD, "otg_hcd_deinit_modules \n");
+
+ spin_lock_irq_save_otg(&otghost->lock, spin_lock_flag);
+
+ deinit_transfer(otghost);
+
+ spin_unlock_irq_save_otg(&otghost->lock, spin_lock_flag);
+}
+
+/**
+ * irqreturn_t (*s5pc110_otghcd_irq) (struct usb_hcd *hcd)
+ *
+ * @brief interrupt handler of otg irq
+ *
+ * @param [in] hcd : pointer of usb_hcd
+ *
+ * @return IRQ_HANDLED \n
+ */
+irqreturn_t s5pc110_otghcd_irq(struct usb_hcd *hcd)
+{
+ struct sec_otghost *otghost = hcd_to_sec_otghost(hcd);
+
+ otg_dbg(OTG_DBG_OTGHCDI_HCD, "s5pc110_otghcd_irq \n");
+
+ spin_lock_otg(&otghost->lock);
+ otg_handle_interrupt(hcd);
+ spin_unlock_otg(&otghost->lock);
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * int s5pc110_otghcd_start(struct usb_hcd *hcd)
+ *
+ * @brief initialize and start otg hcd
+ *
+ * @param [in] usb_hcd_p : pointer of usb_hcd
+ *
+ * @return USB_ERR_SUCCESS : If success \n
+ * USB_ERR_FAIL : If call fail \n
+ */
+int s5pc110_otghcd_start(struct usb_hcd *usb_hcd_p)
+{
+ struct usb_bus *usb_bus_p;
+ struct sec_otghost *otghost = hcd_to_sec_otghost(usb_hcd_p);
+
+ otg_dbg(OTG_DBG_OTGHCDI_HCD, "s5pc110_otghcd_start \n");
+
+ usb_bus_p = hcd_to_bus(usb_hcd_p);
+
+ /* Initialize and connect root hub if one is not already attached */
+ if (usb_bus_p->root_hub) {
+ otg_dbg(OTG_DBG_OTGHCDI_HCD, "OTG HCD Has Root Hub\n");
+
+ /* Inform the HUB driver to resume. */
+ otg_usbcore_resume_roothub();
+ } else {
+ otg_err(OTG_DBG_OTGHCDI_HCD,
+ "OTG HCD Does Not Have Root Hub\n");
+ return USB_ERR_FAIL;
+ }
+
+ set_bit(HCD_FLAG_POLL_RH,&usb_hcd_p->flags);
+ usb_hcd_p->uses_new_polling = 1;
+
+ /* init bus state before enable irq */
+ usb_hcd_p->state = HC_STATE_RUNNING;
+
+ oci_start(otghost); /* enable irq */
+
+ return USB_ERR_SUCCESS;
+}
+
+/**
+ * void s5pc110_otghcd_stop(struct usb_hcd *hcd)
+ *
+ * @brief deinitialize and stop otg hcd
+ *
+ * @param [in] hcd : pointer of usb_hcd
+ *
+ */
+void s5pc110_otghcd_stop(struct usb_hcd *hcd)
+{
+ unsigned long spin_lock_flag = 0;
+ struct sec_otghost *otghost = hcd_to_sec_otghost(hcd);
+
+ otg_dbg(OTG_DBG_OTGHCDI_HCD, "s5pc110_otghcd_stop \n");
+
+ otg_hcd_deinit_modules(otghost);
+
+ spin_lock_irq_save_otg(&otghost->lock, spin_lock_flag);
+
+ oci_stop(otghost);
+ root_hub_feature(hcd, 0, ClearPortFeature, USB_PORT_FEAT_POWER, NULL);
+
+ spin_unlock_irq_save_otg(&otghost->lock, spin_lock_flag);
+}
+
+/**
+ * void s5pc110_otghcd_shutdown(struct usb_hcd *hcd)
+ *
+ * @brief shutdown otg hcd
+ *
+ * @param [in] usb_hcd_p : pointer of usb_hcd
+ *
+ */
+void s5pc110_otghcd_shutdown(struct usb_hcd *usb_hcd_p)
+{
+ unsigned long spin_lock_flag = 0;
+ struct sec_otghost *otghost = hcd_to_sec_otghost(usb_hcd_p);
+
+ otg_dbg(OTG_DBG_OTGHCDI_HCD, "s5pc110_otghcd_shutdown \n");
+ otg_hcd_deinit_modules(otghost);
+
+ spin_lock_irq_save_otg(&otghost->lock, spin_lock_flag);
+
+ oci_stop(otghost);
+ root_hub_feature(usb_hcd_p, 0, ClearPortFeature, USB_PORT_FEAT_POWER, NULL);
+
+ spin_unlock_irq_save_otg(&otghost->lock, spin_lock_flag);
+
+ free_irq(IRQ_OTG, usb_hcd_p);
+ usb_hcd_p->state = HC_STATE_HALT;
+ otg_usbcore_hc_died();
+}
+
+
+/**
+ * int s5pc110_otghcd_get_frame_number(struct usb_hcd *hcd)
+ *
+ * @brief get currnet frame number
+ *
+ * @param [in] hcd : pointer of usb_hcd
+ *
+ * @return ret : frame number \n
+ */
+int s5pc110_otghcd_get_frame_number(struct usb_hcd *hcd)
+{
+ int ret = 0;
+ unsigned long spin_lock_flag = 0;
+ struct sec_otghost *otghost = hcd_to_sec_otghost(hcd);
+
+ otg_dbg(OTG_DBG_OTGHCDI_HCD, "s5pc110_otghcd_get_frame_number \n");
+
+ spin_lock_irq_save_otg(&otghost->lock, spin_lock_flag);
+ ret = oci_get_frame_num();
+ spin_unlock_irq_save_otg(&otghost->lock, spin_lock_flag);
+
+ return ret;
+}
+
+
+/**
+ * int s5pc110_otghcd_urb_enqueue()
+ *
+ * @brief enqueue a urb to otg hcd
+ *
+ * @param [in] hcd : pointer of usb_hcd
+ * [in] ep : pointer of usb_host_endpoint
+ * [in] urb : pointer of urb
+ * [in] mem_flags : type of gfp_t
+ *
+ * @return USB_ERR_SUCCESS : If success \n
+ * USB_ERR_FAIL : If call fail \n
+ */
+int s5pc110_otghcd_urb_enqueue (struct usb_hcd *hcd,
+ struct urb *urb,
+ gfp_t mem_flags)
+{
+ int ret_val = 0;
+ u32 trans_flag = 0;
+ u32 return_td_addr = 0;
+ u8 dev_speed, ed_type = 0, additional_multi_count;
+ u16 max_packet_size;
+
+ u8 dev_addr = 0;
+ u8 ep_num = 0;
+ bool f_is_ep_in = true;
+ u8 interval = 0;
+ u32 sched_frame = 0;
+ u8 hub_addr = 0;
+ u8 hub_port = 0;
+ bool f_is_do_split = false;
+ ed_t *target_ed = NULL;
+ isoch_packet_desc_t *new_isoch_packet_desc = NULL;
+ unsigned long spin_lock_flag = 0;
+ struct sec_otghost *otghost = hcd_to_sec_otghost(hcd);
+
+ if (!otghost->port_flag.b.port_connect_status) {
+ printk(KERN_ERR"%s %d\n", __func__, __LINE__);
+ return USB_ERR_NOIO;
+ }
+
+ spin_lock_irq_save_otg(&otghost->lock, spin_lock_flag);
+
+ otg_dbg(OTG_DBG_OTGHCDI_HCD, "s5pc110_otghcd_urb_enqueue \n");
+
+ /* check ep has ed_t or not */
+ if(!(urb->ep->hcpriv)) {
+ /* for getting dev_speed */
+ switch (urb->dev->speed) {
+ case USB_SPEED_HIGH :
+ otg_dbg(OTG_DBG_OTGHCDI_HCD, "HS_OTG \n");
+ dev_speed = HIGH_SPEED_OTG;
+ break;
+
+ case USB_SPEED_FULL :
+ otg_dbg(OTG_DBG_OTGHCDI_HCD, "FS_OTG \n");
+ dev_speed = FULL_SPEED_OTG;
+ break;
+
+ case USB_SPEED_LOW :
+ otg_dbg(OTG_DBG_OTGHCDI_HCD, "LS_OTG \n");
+ dev_speed = LOW_SPEED_OTG;
+ break;
+
+ default:
+ otg_err(OTG_DBG_OTGHCDI_HCD,
+ "unKnown Device Speed \n");
+ spin_unlock_irq_save_otg(&otghost->lock,
+ spin_lock_flag);
+ return USB_ERR_FAIL;
+ }
+
+ /* for getting ed_type */
+ switch (usb_pipetype(urb->pipe)) {
+ case PIPE_BULK :
+ otg_dbg(OTG_DBG_OTGHCDI_HCD, "bulk transfer \n");
+ ed_type = BULK_TRANSFER;
+ break;
+
+ case PIPE_INTERRUPT :
+ otg_dbg(OTG_DBG_OTGHCDI_HCD, "interrupt transfer \n");
+ ed_type = INT_TRANSFER;
+ break;
+
+ case PIPE_CONTROL :
+ otg_dbg(OTG_DBG_OTGHCDI_HCD, "control transfer \n");
+ ed_type = CONTROL_TRANSFER;
+ break;
+
+ case PIPE_ISOCHRONOUS :
+ otg_dbg(OTG_DBG_OTGHCDI_HCD, "isochronous transfer \n");
+ ed_type = ISOCH_TRANSFER;
+ break;
+ default:
+ otg_err(OTG_DBG_OTGHCDI_HCD, "unKnown ep type \n");
+ spin_unlock_irq_save_otg(&otghost->lock,
+ spin_lock_flag);
+ return USB_ERR_FAIL;
+ }
+
+ max_packet_size = usb_maxpacket(urb->dev, urb->pipe,
+ !(usb_pipein(urb->pipe)));
+ additional_multi_count = ((max_packet_size) >> 11) & 0x03;
+ dev_addr = usb_pipedevice(urb->pipe);
+ ep_num = usb_pipeendpoint(urb->pipe);
+ f_is_ep_in = usb_pipein(urb->pipe) ? true : false;
+ interval = (u8)(urb->interval);
+ sched_frame = (u8)(urb->start_frame);
+
+ /* check */
+ if(urb->dev->tt == NULL) {
+ otg_dbg(OTG_DBG_OTGHCDI_HCD, "urb->dev->tt == NULL\n");
+ hub_port = 0; /* u8 hub_port */
+ hub_addr = 0; /* u8 hub_addr */
+ }
+ else {
+ hub_port = (u8)(urb->dev->ttport);
+ if (urb->dev->tt->hub) {
+ if (((dev_speed == FULL_SPEED_OTG) ||
+ (dev_speed == LOW_SPEED_OTG)) &&
+ (urb->dev->tt) && (urb->dev->tt->hub->devnum != 1)) {
+ if (otghost->is_hs) // only allow split transactions in HS mode
+ f_is_do_split = true;
+ }
+ hub_addr = (u8)(urb->dev->tt->hub->devnum);
+ }
+ if (urb->dev->tt->multi) {
+ hub_addr = 0x80;
+ }
+ }
+ otg_dbg(OTG_DBG_OTGHCDI_HCD,
+ "dev_spped =%d, hub_port=%d, hub_addr=%d\n",
+ dev_speed, hub_port, hub_addr);
+
+ ret_val = create_ed(&target_ed);
+ if(ret_val != USB_ERR_SUCCESS) {
+ otg_err(OTG_DBG_OTGHCDI_HCD,
+ "fail to create_ed() \n");
+ spin_unlock_irq_save_otg(&otghost->lock,
+ spin_lock_flag);
+ return ret_val;
+ }
+
+ ret_val = init_ed( target_ed,
+ dev_addr,
+ ep_num,
+ f_is_ep_in,
+ dev_speed,
+ ed_type,
+ max_packet_size,
+ additional_multi_count,
+ interval,
+ sched_frame,
+ hub_addr,
+ hub_port,
+ f_is_do_split,
+ (void *)urb->ep);
+
+ if(ret_val != USB_ERR_SUCCESS) {
+ otg_err(OTG_DBG_OTGHCDI_HCD,
+ "fail to init_ed() :err = %d \n",(int)ret_val);
+ otg_mem_free(target_ed);
+ spin_unlock_irq_save_otg(&otghost->lock,
+ spin_lock_flag);
+ return USB_ERR_FAIL;
+ }
+
+ urb->ep->hcpriv = (void *)(target_ed);
+ } /* if(!(ep->hcpriv)) */
+ else {
+ dev_addr = usb_pipedevice(urb->pipe);
+ if(((ed_t *)(urb->ep->hcpriv))->ed_desc.device_addr != dev_addr) {
+ ((ed_t *)urb->ep->hcpriv)->ed_desc.device_addr = dev_addr;
+ }
+ }
+
+ target_ed = (ed_t *)urb->ep->hcpriv;
+
+ if(urb->transfer_flags & URB_SHORT_NOT_OK)
+ trans_flag += USB_TRANS_FLAG_NOT_SHORT;
+ if (urb->transfer_flags & URB_ISO_ASAP)
+ trans_flag += USB_TRANS_FLAG_ISO_ASYNCH;
+
+ if(ed_type == ISOCH_TRANSFER) {
+ otg_err(OTG_DBG_OTGHCDI_HCD, "ISO not yet supported \n");
+ spin_unlock_irq_save_otg(&otghost->lock, spin_lock_flag);
+ return USB_ERR_FAIL;
+ }
+
+ if (!HC_IS_RUNNING(hcd->state)) {
+ otg_err(OTG_DBG_OTGHCDI_HCD, "!HC_IS_RUNNING(hcd->state) \n");
+ spin_unlock_irq_save_otg(&otghost->lock, spin_lock_flag);
+ return -USB_ERR_NODEV;
+ }
+
+ /* in case of unlink-during-submit */
+ if (urb->status != -EINPROGRESS) {
+ otg_err(OTG_DBG_OTGHCDI_HCD, "urb->status is -EINPROGRESS\n");
+ urb->hcpriv = NULL;
+ spin_unlock_irq_save_otg(&otghost->lock, spin_lock_flag);
+ usb_hcd_giveback_urb(hcd, urb, urb->status);
+ return USB_ERR_SUCCESS;
+ }
+
+ ret_val = issue_transfer(otghost, target_ed, (void *)NULL, (void *)NULL,
+ trans_flag,
+ (usb_pipetype(urb->pipe) == PIPE_CONTROL)?true:false,
+ (u32)urb->setup_packet, (u32)urb->setup_dma,
+ (u32)urb->transfer_buffer, (u32)urb->transfer_dma,
+ (u32)urb->transfer_buffer_length,
+ (u32)urb->start_frame,(u32)urb->number_of_packets,
+ new_isoch_packet_desc, (void *)urb, &return_td_addr);
+
+ if(ret_val != USB_ERR_SUCCESS) {
+ otg_err(OTG_DBG_OTGHCDI_HCD, "fail to issue_transfer() \n");
+ spin_unlock_irq_save_otg(&otghost->lock, spin_lock_flag);
+ return USB_ERR_FAIL;
+ }
+ urb->hcpriv = (void *)return_td_addr;
+
+ spin_unlock_irq_save_otg(&otghost->lock, spin_lock_flag);
+ return USB_ERR_SUCCESS;
+}
+
+/**
+ * int s5pc110_otghcd_urb_dequeue(struct usb_hcd *_hcd, struct urb *_urb )
+ *
+ * @brief dequeue a urb to otg
+ *
+ * @param [in] _hcd : pointer of usb_hcd
+ * [in] _urb : pointer of urb
+ *
+ * @return USB_ERR_SUCCESS : If success \n
+ * USB_ERR_FAIL : If call fail \n
+ */
+int s5pc110_otghcd_urb_dequeue(
+ struct usb_hcd *_hcd, struct urb *_urb, int status)
+{
+ int ret_val = 0;
+ struct sec_otghost *otghost = hcd_to_sec_otghost(_hcd);
+
+ unsigned long spin_lock_flag = 0;
+ td_t *cancel_td;
+
+ spin_lock_irq_save_otg(&otghost->lock, spin_lock_flag);
+
+ otg_dbg(OTG_DBG_OTGHCDI_HCD, "s5pc110_otghcd_urb_dequeue \n");
+
+ /* Dequeue should be performed only if endpoint is enabled */
+ if (_urb->ep->enabled == 0) {
+ spin_unlock_irq_save_otg(&otghost->lock, spin_lock_flag);
+ usb_hcd_giveback_urb(_hcd, _urb, status);
+ return USB_ERR_SUCCESS;
+ }
+
+ //kevinh read this from inside the spinlock
+ cancel_td = (td_t *)_urb->hcpriv;
+
+ if (cancel_td == NULL) {
+ otg_err(OTG_DBG_OTGHCDI_HCD, "cancel_td is NULL\n");
+ spin_unlock_irq_save_otg(&otghost->lock, spin_lock_flag);
+ return USB_ERR_FAIL;
+ }
+ otg_dbg(OTG_DBG_OTGHCDI_HCD,
+ "s5pc110_otghcd_urb_dequeue, status = %d\n", status);
+
+
+ ret_val = usb_hcd_check_unlink_urb(_hcd, _urb, status);
+ if( (ret_val) && (ret_val != -EIDRM) ) {
+ otg_dbg(OTG_DBG_OTGHCDI_HCD, "ret_val = %d\n", ret_val);
+ spin_unlock_irq_save_otg(&otghost->lock, spin_lock_flag);
+ usb_hcd_giveback_urb(_hcd, _urb, status);
+ return ret_val;
+ }
+
+ if (!HC_IS_RUNNING(_hcd->state)) {
+ otg_err(OTG_DBG_OTGHCDI_HCD, "!HC_IS_RUNNING(hcd->state) \n");
+ spin_unlock_irq_save_otg(&otghost->lock, spin_lock_flag);
+ otg_usbcore_giveback(cancel_td);
+ return USB_ERR_SUCCESS;
+ }
+
+ ret_val = cancel_transfer(otghost, cancel_td->parent_ed_p, cancel_td);
+ if(ret_val != USB_ERR_DEQUEUED && ret_val != USB_ERR_NOELEMENT) {
+ otg_err(OTG_DBG_OTGHCDI_HCD, "fail to cancel_transfer() \n");
+ otg_usbcore_giveback(cancel_td);
+ spin_unlock_irq_save_otg(&otghost->lock, spin_lock_flag);
+ return USB_ERR_FAIL;
+ }
+ otg_usbcore_giveback(cancel_td);
+ delete_td(otghost, cancel_td);
+ spin_unlock_irq_save_otg(&otghost->lock, spin_lock_flag);
+ return USB_ERR_SUCCESS;
+}
+
+/**
+ * void s5pc110_otghcd_endpoint_disable(
+ * struct usb_hcd *hcd,
+ * struct usb_host_endpoint *ep)
+ *
+ * @brief disable a endpoint
+ *
+ * @param [in] hcd : pointer of usb_hcd
+ * [in] ep : pointer of usb_host_endpoint
+ */
+void s5pc110_otghcd_endpoint_disable(
+ struct usb_hcd *hcd,
+ struct usb_host_endpoint *ep)
+{
+ int ret_val = 0;
+ unsigned long spin_lock_flag = 0;
+ struct sec_otghost *otghost = hcd_to_sec_otghost(hcd);
+
+ otg_dbg(OTG_DBG_OTGHCDI_HCD, "s5pc110_otghcd_endpoint_disable \n");
+
+ if(!((ed_t *)ep->hcpriv))
+ return;
+
+ spin_lock_irq_save_otg(&otghost->lock, spin_lock_flag);
+ ret_val = delete_ed(otghost, (ed_t *)ep->hcpriv);
+ spin_unlock_irq_save_otg(&otghost->lock, spin_lock_flag);
+
+ if(ret_val != USB_ERR_SUCCESS) {
+ otg_err(OTG_DBG_OTGHCDI_HCD, "fail to delete_ed() \n");
+ return ;
+ }
+
+ /* ep->hcpriv = NULL; delete_ed coveres it */
+}
+
+/**
+ * int s5pc110_otghcd_hub_status_data(struct usb_hcd *_hcd, char *_buf)
+ *
+ * @brief get status of root hub
+ *
+ * @param [in] _hcd : pointer of usb_hcd
+ * [inout] _buf : pointer of buffer for write a status data
+ *
+ * @return ret_val : return port status \n
+ */
+int s5pc110_otghcd_hub_status_data(struct usb_hcd *_hcd, char *_buf)
+{
+ int ret_val = 0;
+ unsigned long spin_lock_flag = 0;
+ struct sec_otghost *otghost = hcd_to_sec_otghost(_hcd);
+
+ /* otg_dbg(OTG_DBG_OTGHCDI_HCD, "s5pc110_otghcd_hub_status_data \n"); */
+
+ /* if !USB_SUSPEND, root hub timers won't get shut down ... */
+ if (!HC_IS_RUNNING(_hcd->state)) {
+ otg_dbg(OTG_DBG_OTGHCDI_HCD,
+ "_hcd->state is NOT HC_IS_RUNNING \n");
+ return 0;
+ }
+
+ spin_lock_irq_save_otg(&otghost->lock, spin_lock_flag);
+ ret_val = get_otg_port_status(_hcd, OTG_PORT_NUMBER, _buf);
+ spin_unlock_irq_save_otg(&otghost->lock, spin_lock_flag);
+
+ return (int)ret_val;
+}
+
+/**
+ * int s5pc110_otghcd_hub_control()
+ *
+ * @brief control root hub
+ *
+ * @param [in] hcd : pointer of usb_hcd
+ * [in] typeReq : type of control request
+ * [in] value : value
+ * [in] index : index
+ * [in] buf_p : pointer of urb
+ * [in] length : type of gfp_t
+ *
+ * @return ret_val : return root_hub_feature \n
+ */
+int
+s5pc110_otghcd_hub_control (
+ struct usb_hcd *hcd,
+ u16 typeReq,
+ u16 value,
+ u16 index,
+ char* buf_p,
+ u16 length
+)
+{
+ int ret_val = 0;
+ unsigned long spin_lock_flag = 0;
+ struct sec_otghost *otghost = hcd_to_sec_otghost(hcd);
+
+ otg_dbg(OTG_DBG_OTGHCDI_HCD, "s5pc110_otghcd_hub_control \n");
+
+ spin_lock_irq_save_otg(&otghost->lock, spin_lock_flag);
+
+ ret_val = root_hub_feature(hcd, OTG_PORT_NUMBER,
+ typeReq, value, (void *)buf_p);
+
+ spin_unlock_irq_save_otg(&otghost->lock, spin_lock_flag);
+ if(ret_val != USB_ERR_SUCCESS) {
+ otg_err(OTG_DBG_OTGHCDI_HCD, "fail to root_hub_feature() \n");
+ return ret_val;
+ }
+ return (int)ret_val;
+}
+
+/**
+ * int s5pc110_otghcd_bus_suspend(struct usb_hcd *hcd)
+ *
+ * @brief suspend otg hcd
+ *
+ * @param [in] hcd : pointer of usb_hcd
+ *
+ * @return USB_ERR_SUCCESS \n
+ */
+int s5pc110_otghcd_bus_suspend(struct usb_hcd *hcd)
+{
+ unsigned long spin_lock_flag = 0;
+ struct sec_otghost *otghost = hcd_to_sec_otghost(hcd);
+
+ otg_dbg(OTG_DBG_OTGHCDI_HCD, "s5pc110_otghcd_bus_suspend \n");
+
+ spin_lock_irq_save_otg(&otghost->lock, spin_lock_flag);
+ bus_suspend();
+ spin_unlock_irq_save_otg(&otghost->lock, spin_lock_flag);
+
+ return USB_ERR_SUCCESS;
+}
+
+/**
+ * int s5pc110_otghcd_bus_resume(struct usb_hcd *hcd)
+ *
+ * @brief resume otg hcd
+ *
+ * @param [in] hcd : pointer of usb_hcd
+ *
+ * @return USB_ERR_SUCCESS \n
+ */
+int s5pc110_otghcd_bus_resume(struct usb_hcd *hcd)
+{
+ unsigned long spin_lock_flag = 0;
+ struct sec_otghost *otghost = hcd_to_sec_otghost(hcd);
+
+ otg_dbg(OTG_DBG_OTGHCDI_HCD, "s5pc110_otghcd_bus_resume \n");
+
+ spin_lock_irq_save_otg(&otghost->lock, spin_lock_flag);
+
+ if(bus_resume(otghost) != USB_ERR_SUCCESS) {
+ return USB_ERR_FAIL;
+ }
+
+ spin_unlock_irq_save_otg(&otghost->lock, spin_lock_flag);
+ return USB_ERR_SUCCESS;
+}
+
+/**
+ * int s5pc110_otghcd_start_port_reset(struct usb_hcd *hcd, unsigned port)
+ *
+ * @brief reset otg port
+ *
+ * @param [in] hcd : pointer of usb_hcd
+ * [in] port : number of port
+ *
+ * @return USB_ERR_SUCCESS : If success \n
+ * ret_val : If call fail \n
+ */
+int s5pc110_otghcd_start_port_reset(struct usb_hcd *hcd, unsigned port)
+{
+ int ret_val = 0;
+
+ unsigned long spin_lock_flag = 0;
+ struct sec_otghost *otghost = hcd_to_sec_otghost(hcd);
+
+ otg_dbg(OTG_DBG_OTGHCDI_HCD, "s5pc110_otghcd_start_port_reset \n");
+
+ spin_lock_irq_save_otg(&otghost->lock, spin_lock_flag);
+ ret_val = reset_and_enable_port(hcd, OTG_PORT_NUMBER);
+ spin_unlock_irq_save_otg(&otghost->lock, spin_lock_flag);
+
+ if(ret_val != USB_ERR_SUCCESS) {
+ otg_err(OTG_DBG_OTGHCDI_HCD,
+ "fail to reset_and_enable_port() \n");
+ return ret_val;
+ }
+ return USB_ERR_SUCCESS;
+}
diff --git a/drivers/usb/host/s3c-otg/s3c-otg-hcdi-hcd.h b/drivers/usb/host/s3c-otg/s3c-otg-hcdi-hcd.h
new file mode 100644
index 0000000..95764d8
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/s3c-otg-hcdi-hcd.h
@@ -0,0 +1,152 @@
+/****************************************************************************
+ * (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+ *
+ * @file s3c-otg-hcdi-hcd.h
+ * @brief header of s3c-otg-hcdi-hcd \n
+ * @version
+ * -# Jun 9,2008 v1.0 by SeungSoo Yang (ss1.yang@samsung.com) \n
+ * : Creating the initial version of this code \n
+ * -# Jul 15,2008 v1.2 by SeungSoo Yang (ss1.yang@samsung.com) \n
+ * : Optimizing for performance \n
+ * -# Aug 18,2008 v1.3 by SeungSoo Yang (ss1.yang@samsung.com) \n
+ * : Modifying for successful rmmod & disconnecting \n
+ * @see None
+ ****************************************************************************/
+/****************************************************************************
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ ****************************************************************************/
+
+#ifndef _S3C_OTG_HCDI_HCD_H_
+#define _S3C_OTG_HCDI_HCD_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+//for IRQ_NONE (0) IRQ_HANDLED (1) IRQ_RETVAL(x) ((x) != 0)
+#include <linux/interrupt.h>
+
+#include <linux/usb.h>
+
+#include "s3c-otg-hcdi-debug.h"
+#include "s3c-otg-hcdi-kal.h"
+
+#include "s3c-otg-common-common.h"
+#include "s3c-otg-common-datastruct.h"
+#include "s3c-otg-common-const.h"
+
+#include "s3c-otg-transfer-transfer.h"
+#include "s3c-otg-oci.h"
+#include "s3c-otg-roothub.h"
+
+//placed in ISR
+//void otg_handle_interrupt(struct usb_hcd *hcd);
+
+irqreturn_t s5pc110_otghcd_irq(struct usb_hcd *hcd);
+
+int s5pc110_otghcd_start(struct usb_hcd *hcd);
+void s5pc110_otghcd_stop(struct usb_hcd *hcd);
+void s5pc110_otghcd_shutdown(struct usb_hcd *hcd);
+
+int s5pc110_otghcd_get_frame_number(struct usb_hcd *hcd);
+
+int s5pc110_otghcd_urb_enqueue(
+ struct usb_hcd *hcd,
+ struct urb *urb,
+ gfp_t mem_flags);
+
+int s5pc110_otghcd_urb_dequeue(
+ struct usb_hcd *_hcd,
+ struct urb *_urb,
+ int status);
+
+void s5pc110_otghcd_endpoint_disable(
+ struct usb_hcd *hcd,
+ struct usb_host_endpoint *ep);
+
+int s5pc110_otghcd_hub_status_data(
+ struct usb_hcd *_hcd,
+ char *_buf);
+
+int s5pc110_otghcd_hub_control(
+ struct usb_hcd *hcd,
+ u16 type_req,
+ u16 value,
+ u16 index,
+ char * buf,
+ u16 length);
+
+int s5pc110_otghcd_bus_suspend(struct usb_hcd *hcd);
+int s5pc110_otghcd_bus_resume(struct usb_hcd *hcd);
+int s5pc110_otghcd_start_port_reset(struct usb_hcd *hcd, unsigned port);
+
+/**
+ * @struct hc_driver s5pc110_otg_hc_driver
+ *
+ * @brief implementation of hc_driver for OTG HCD
+ *
+ * describe in detail
+ */
+static const struct hc_driver s5pc110_otg_hc_driver = {
+ .description = "EMSP_OTGHCD",
+ .product_desc = "S3C OTGHCD",
+ .hcd_priv_size = sizeof(struct sec_otghost),
+
+ .irq = s5pc110_otghcd_irq,
+ .flags = HCD_MEMORY | HCD_USB2,
+
+ /** basic lifecycle operations */
+ //.reset =
+ .start = s5pc110_otghcd_start,
+ //.suspend = ,
+ //.resume = ,
+ .stop = s5pc110_otghcd_stop,
+ .shutdown = s5pc110_otghcd_shutdown,
+
+ /** managing i/o requests and associated device resources */
+ .urb_enqueue = s5pc110_otghcd_urb_enqueue,
+ .urb_dequeue = s5pc110_otghcd_urb_dequeue,
+ .endpoint_disable = s5pc110_otghcd_endpoint_disable,
+
+ /** scheduling support */
+ .get_frame_number = s5pc110_otghcd_get_frame_number,
+
+ /** root hub support */
+ .hub_status_data = s5pc110_otghcd_hub_status_data,
+ .hub_control = s5pc110_otghcd_hub_control,
+ //.hub_irq_enable =
+ .bus_suspend = s5pc110_otghcd_bus_suspend,
+ .bus_resume = s5pc110_otghcd_bus_resume,
+ .start_port_reset = s5pc110_otghcd_start_port_reset,
+};
+
+static inline struct sec_otghost *hcd_to_sec_otghost (struct usb_hcd *hcd)
+{
+ return (struct sec_otghost *) (hcd->hcd_priv);
+}
+static inline struct usb_hcd *sec_otghost_to_hcd (struct sec_otghost *otghost)
+{
+ return container_of ((void *) otghost, struct usb_hcd, hcd_priv);
+}
+
+int otg_hcd_init_modules(struct sec_otghost *otghost);
+void otg_hcd_deinit_modules(struct sec_otghost *otghost);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _S3C_OTG_HCDI_HCD_H_ */
+
diff --git a/drivers/usb/host/s3c-otg/s3c-otg-hcdi-kal.h b/drivers/usb/host/s3c-otg/s3c-otg-hcdi-kal.h
new file mode 100644
index 0000000..23bded6
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/s3c-otg-hcdi-kal.h
@@ -0,0 +1,420 @@
+/****************************************************************************
+ * (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+ *
+ * @file s3c-otg-hcdi-kal.h
+ * @brief header of s3c-otg-hcdi-kal \n
+ * @version
+ * -# Jun 9,2008 v1.0 by SeungSoo Yang (ss1.yang@samsung.com) \n
+ * : Creating the initial version of this code \n
+ * -# Jul 15,2008 v1.2 by SeungSoo Yang (ss1.yang@samsung.com) \n
+ * : Optimizing for performance \n
+ * -# Aug 18,2008 v1.3 by SeungSoo Yang (ss1.yang@samsung.com) \n
+ * : Modifying for successful rmmod & disconnecting \n
+ * @see None
+ ****************************************************************************/
+/****************************************************************************
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ ****************************************************************************/
+
+#ifndef _S3C_OTG_HCDI_KAL_H_
+#define _S3C_OTG_HCDI_KAL_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "s3c-otg-hcdi-debug.h"
+#include "s3c-otg-common-common.h"
+#include "s3c-otg-common-datastruct.h"
+#include "s3c-otg-common-const.h"
+
+#include <asm/io.h> //for readl, writel
+#include <linux/usb/ch9.h> //for usb_device_driver, enum usb_device_speed
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <mach/map.h>
+#include <plat/regs-otg.h>
+
+extern volatile u8 * g_pUDCBase;
+extern struct usb_hcd* g_pUsbHcd;
+
+#include <linux/spinlock.h>
+#define SPINLOCK_t spinlock_t
+#define SPIN_LOCK_INIT SPIN_LOCK_UNLOCKED
+
+#define spin_lock_otg(lock) spin_lock(lock)
+#define spin_lock_irg_otg(lock) spin_lock_irq(lock)
+#define spin_lock_irq_save_otg(lock, flags) spin_lock_irqsave(lock, flags)
+
+#define spin_unlock_otg(lock) spin_unlock(lock)
+#define spin_unlock_irq_otg(lock) spin_unlock_irq(lock)
+#define spin_unlock_irq_save_otg(lock, flags) spin_unlock_irqrestore(lock, flags)
+
+#define ctrlr_base_reg_addr(offset) \
+ ((volatile unsigned int *)((g_pUDCBase) + (offset)))
+/**
+ * otg_kal_make_ep_null
+ *
+ * @brief make ep->hcpriv NULL
+ *
+ * @param [in] pdelete_ed : pointer of ed
+ *
+ * @return void \n
+ */
+static inline void
+otg_kal_make_ep_null
+(
+ ed_t *pdelete_ed
+)
+{
+ ((struct usb_host_endpoint *)(pdelete_ed->ed_private))->hcpriv = NULL;
+}
+//---------------------------------------------------------------------------------------
+
+/**
+ * otg_kal_is_ep_null
+ *
+ * @brief check ep->hcpriv is NULL or not
+ *
+ * @param [in] pdelete_ed : pointer of ed
+ *
+ * @return bool \n
+ */
+static inline bool
+otg_kal_is_ep_null
+(
+ ed_t *pdelete_ed
+)
+{
+ if (((struct usb_host_endpoint *)(pdelete_ed->ed_private))->hcpriv == NULL)
+ return true;
+ else
+ return false;
+}
+//---------------------------------------------------------------------------------------
+
+
+/**
+ * int otg_usbcore_get_calc_bustime()
+ *
+ * @brief get bus time of usbcore
+ *
+ * @param [in] speed : usb speed
+ * [in] is_input : input or not
+ * [in] is_isoch : isochronous or not
+ * [in] byte_count : bytes
+ *
+ * @return bus time of usbcore \n
+ */
+static inline int
+otg_usbcore_get_calc_bustime
+(
+ u8 speed,
+ bool is_input,
+ bool is_isoch,
+ unsigned int byte_count
+)
+{
+ unsigned int convert_speed = 0;
+
+ otg_dbg(OTG_DBG_OTGHCDI_KAL, "otg_usbcore_get_calc_bustime \n");
+/* enum usb_device_speed {
+ USB_SPEED_UNKNOWN = 0,
+ USB_SPEED_LOW, USB_SPEED_FULL,
+ USB_SPEED_HIGH,
+ USB_SPEED_VARIABLE, };*/
+ switch(speed) {
+ case HIGH_SPEED_OTG :
+ convert_speed = USB_SPEED_HIGH;
+ break;
+
+ case FULL_SPEED_OTG :
+ convert_speed = USB_SPEED_FULL;
+ break;
+
+ case LOW_SPEED_OTG :
+ convert_speed = USB_SPEED_LOW;
+ break;
+
+ default:
+ convert_speed = USB_SPEED_UNKNOWN;
+ break;
+ }
+ return usb_calc_bus_time(convert_speed, is_input, (unsigned int)is_isoch, byte_count);
+}
+
+//-------------------------------------------------------------------------------
+
+/**
+ * void otg_usbcore_giveback(td_t td_p)
+ *
+ * @brief give-back a td as urb
+ *
+ * @param [in] td_p : pointer of td_t to give back
+ *
+ * @return void \n
+ */
+static inline void
+otg_usbcore_giveback(td_t * td_p)
+{
+ struct urb *urb_p = NULL;
+
+ otg_dbg(OTG_DBG_OTGHCDI_KAL, "otg_usbcore_giveback \n");
+
+ if (td_p->td_private == NULL)
+ {
+ otg_err(OTG_DBG_OTGHCDI_KAL,
+ "td_p->td_private == NULL \n");
+ return;
+ }
+
+ urb_p = (struct urb *)td_p->td_private;
+
+ urb_p->actual_length = (int)(td_p->transferred_szie);
+ urb_p->status = (int)(td_p->error_code);
+ urb_p->error_count = (int)(td_p->err_cnt);
+ urb_p->hcpriv = NULL;
+
+ usb_hcd_giveback_urb(g_pUsbHcd, urb_p, urb_p->status);
+}
+//-------------------------------------------------------------------------------
+
+/**
+ * void otg_usbcore_hc_died(void)
+ *
+ * @brief inform usbcore of hc die
+ *
+ * @return void \n
+ */
+static inline void
+otg_usbcore_hc_died(void)
+{
+ otg_dbg(OTG_DBG_OTGHCDI_KAL, "otg_usbcore_hc_died \n");
+ usb_hc_died(g_pUsbHcd);
+}
+//-------------------------------------------------------------------------------
+
+/**
+ * void otg_usbcore_poll_rh_status(void)
+ *
+ * @brief invoke usbcore's usb_hcd_poll_rh_status
+ *
+ * @param void
+ *
+ * @return void \n
+ */
+static inline void
+otg_usbcore_poll_rh_status(void)
+{
+ usb_hcd_poll_rh_status(g_pUsbHcd);
+}
+//-------------------------------------------------------------------------------
+
+/**
+ * void otg_usbcore_resume_roothub(void)
+ *
+ * @brief invoke usbcore's usb_hcd_resume_root_hub
+ *
+ * @param void
+ *
+ * @return void \n
+ */
+static inline void
+otg_usbcore_resume_roothub(void)
+{
+ otg_dbg(OTG_DBG_OTGHCDI_KAL,
+ "otg_usbcore_resume_roothub \n");
+ usb_hcd_resume_root_hub(g_pUsbHcd);
+};
+//-------------------------------------------------------------------------------
+
+/**
+ * int otg_usbcore_inc_usb_bandwidth(u32 band_width)
+ *
+ * @brief increase bandwidth of usb bus
+ *
+ * @param [in] band_width : bandwidth to be increased
+ *
+ * @return USB_ERR_SUCCESS \n
+ */
+static inline int
+otg_usbcore_inc_usb_bandwidth(u32 band_width)
+{
+ otg_dbg(OTG_DBG_OTGHCDI_KAL,
+ "otg_usbcore_inc_usb_bandwidth \n");
+ hcd_to_bus(g_pUsbHcd)->bandwidth_allocated += band_width;
+ return USB_ERR_SUCCESS;
+}
+//-------------------------------------------------------------------------------
+
+/**
+ * int otg_usbcore_des_usb_bandwidth(u32 uiBandwidth)
+ *
+ * @brief decrease bandwidth of usb bus
+ *
+ * @param [in] band_width : bandwidth to be decreased
+ *
+ * @return USB_ERR_SUCCESS \n
+ */
+static inline int
+otg_usbcore_des_usb_bandwidth(u32 band_width)
+{
+ otg_dbg(OTG_DBG_OTGHCDI_KAL,
+ "otg_usbcore_des_usb_bandwidth \n");
+ hcd_to_bus(g_pUsbHcd)->bandwidth_allocated -= band_width;
+ return USB_ERR_SUCCESS;
+}
+//-------------------------------------------------------------------------------
+
+/**
+ * int otg_usbcore_inc_periodic_transfer_cnt(u8 transfer_type)
+ *
+ * @brief increase count of periodic transfer
+ *
+ * @param [in] transfer_type : type of transfer
+ *
+ * @return USB_ERR_SUCCESS : If success \n
+ * USB_ERR_FAIL : If call fail \n
+ */
+static inline int
+otg_usbcore_inc_periodic_transfer_cnt(u8 transfer_type)
+{
+ otg_dbg(OTG_DBG_OTGHCDI_KAL,
+ "otg_usbcore_inc_periodic_transfer_cnt \n");
+
+ switch(transfer_type) {
+ case INT_TRANSFER :
+ hcd_to_bus(g_pUsbHcd)->bandwidth_int_reqs++;
+ break;
+ case ISOCH_TRANSFER :
+ hcd_to_bus(g_pUsbHcd)->bandwidth_isoc_reqs++;
+ break;
+ default:
+ otg_err(OTG_DBG_OTGHCDI_KAL,
+ "not proper TransferType for otg_usbcore_inc_periodic_transfer_cnt()\n");
+ return USB_ERR_FAIL;
+ }
+ return USB_ERR_SUCCESS;
+}
+//-------------------------------------------------------------------------------
+
+/**
+ * int otg_usbcore_des_periodic_transfer_cnt(u8 transfer_type)
+ *
+ * @brief decrease count of periodic transfer
+ *
+ * @param [in] transfer_type : type of transfer
+ *
+ * @return USB_ERR_SUCCESS : If success \n
+ * USB_ERR_FAIL : If call fail \n
+ */
+static inline int
+otg_usbcore_des_periodic_transfer_cnt(u8 transfer_type)
+{
+ otg_dbg(OTG_DBG_OTGHCDI_KAL,
+ "otg_usbcore_des_periodic_transfer_cnt \n");
+
+ switch(transfer_type) {
+ case INT_TRANSFER :
+ hcd_to_bus(g_pUsbHcd)->bandwidth_int_reqs--;
+ break;
+ case ISOCH_TRANSFER :
+ hcd_to_bus(g_pUsbHcd)->bandwidth_isoc_reqs--;
+ break;
+ default:
+ otg_err(OTG_DBG_OTGHCDI_KAL,
+ "not proper TransferType for otg_usbcore_des_periodic_transfer_cnt()\n");
+ return USB_ERR_FAIL;
+ }
+ return USB_ERR_SUCCESS;
+}
+//-------------------------------------------------------------------------------
+
+/**
+ * u32 read_reg_32(u32 offset)
+ *
+ * @brief Reads the content of a register.
+ *
+ * @param [in] offset : offset of address of register to read.
+ *
+ * @return contents of the register. \n
+ * @remark call readl()
+ */
+static inline u32 read_reg_32(u32 offset)
+{
+ volatile unsigned int * reg_addr_p = ctrlr_base_reg_addr(offset);
+
+ return *reg_addr_p;
+ //return readl(reg_addr_p);
+};
+//-------------------------------------------------------------------------------
+
+/**
+ * void write_reg_32( u32 offset, const u32 value)
+ *
+ * @brief Writes a register with a 32 bit value.
+ *
+ * @param [in] offset : offset of address of register to write.
+ * @param [in] value : value to write
+ *
+ * @remark call writel()
+ */
+static inline void write_reg_32( u32 offset, const u32 value)
+{
+ volatile unsigned int * reg_addr_p = ctrlr_base_reg_addr(offset);
+
+ *reg_addr_p = value;
+ //writel( value, reg_addr_p );
+};
+//-------------------------------------------------------------------------------
+
+/**
+ * void update_reg_32(u32 offset, u32 value)
+ *
+ * @brief logic or operation
+ *
+ * @param [in] offset : offset of address of register to write.
+ * @param [in] value : value to or
+ *
+ */
+static inline void update_reg_32(u32 offset, u32 value)
+{
+ write_reg_32(offset, (read_reg_32(offset) | value));
+}
+//---------------------------------------------------------------------------------------
+
+/**
+ * void clear_reg_32(u32 offset, u32 value)
+ *
+ * @brief logic not operation
+ *
+ * @param [in] offset : offset of address of register to write.
+ * @param [in] value : value to not
+ *
+ */
+static inline void clear_reg_32(u32 offset, u32 value)
+{
+ write_reg_32(offset, (read_reg_32(offset) & ~value));
+}
+//---------------------------------------------------------------------------------------
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _S3C_OTG_HCDI_KAL_H_ */
+
diff --git a/drivers/usb/host/s3c-otg/s3c-otg-hcdi-list.h b/drivers/usb/host/s3c-otg/s3c-otg-hcdi-list.h
new file mode 100644
index 0000000..03ae3d8
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/s3c-otg-hcdi-list.h
@@ -0,0 +1,217 @@
+/****************************************************************************
+ * (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+ *
+ * @file s3c-otg-hcdi-list.h
+ * @brief list functions for otg \n
+ * @version
+ * -# Jun 9,2008 v1.0 by SeungSoo Yang (ss1.yang@samsung.com) \n
+ * : Creating the initial version of this code \n
+ * -# Jul 15,2008 v1.2 by SeungSoo Yang (ss1.yang@samsung.com) \n
+ * : Optimizing for performance \n
+ * @see None
+ ****************************************************************************/
+/****************************************************************************
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ ****************************************************************************/
+
+#ifndef _S3C_OTG_HCDI_LIST_H_
+#define _S3C_OTG_HCDI_LIST_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "s3c-otg-common-common.h"
+#include "s3c-otg-hcdi-debug.h"
+
+#include <linux/list.h>
+
+typedef struct list_head otg_list_head;
+
+#define otg_list_get_node(ptr, type, member) container_of(ptr, type, member)
+
+
+#define otg_list_for_each_safe(pos, n, head) \
+ for (pos = (head)->next, n = pos->next; pos != (head); \
+ pos = n, n = pos->next)
+
+
+/**
+ * void otg_list_push_next(otg_list_head *new_node_p, otg_list_head *list_head_p)
+ *
+ * @brief push a list node into the next of head
+ *
+ * @param [in] new_node_p : node to be pushed
+ * @param [in] otg_list_head : target list head
+ *
+ * @return void \n
+ */
+
+static inline
+void otg_list_push_next(otg_list_head *new_node_p, otg_list_head *list_head_p)
+{
+ otg_dbg(OTG_DBG_OTGHCDI_LIST, "otg_list_push_next \n");
+ list_add(new_node_p, list_head_p);
+}
+//-------------------------------------------------------------------------------
+
+/**
+ * void otg_list_push_prev(otg_list_head *new_node_p, otg_list_head *list_head_p)
+ *
+ * @brief push a list node into the previous of head
+ *
+ * @param [in] new_node_p : node to be pushed
+ * @param [in] otg_list_head : target list head
+ *
+ * @return void \n
+ */
+static inline
+void otg_list_push_prev(otg_list_head *new_node_p, otg_list_head *list_head_p)
+{
+ otg_dbg(OTG_DBG_OTGHCDI_LIST, "otg_list_push_prev \n");
+ list_add_tail(new_node_p, list_head_p);
+}
+//-------------------------------------------------------------------------------
+
+/**
+ * void otg_list_pop(otg_list_head *list_entity_p)
+ *
+ * @brief pop a list node
+ *
+ * @param [in] new_node_p : node to be poped
+ * @param [in] otg_list_head : target list head
+ *
+ * @return void \n
+ */
+static inline
+void otg_list_pop(otg_list_head *list_entity_p)
+{
+ otg_dbg(OTG_DBG_OTGHCDI_LIST, "otg_list_pop \n");
+ list_del(list_entity_p);
+}
+//-------------------------------------------------------------------------------
+
+/**
+ * void otg_list_move_next(otg_list_head *node_p, otg_list_head *list_head_p)
+ *
+ * @brief move a list to next of head
+ *
+ * @param [in] new_node_p : node to be moved
+ * @param [in] otg_list_head : target list head
+ *
+ * @return void \n
+ */
+static inline
+void otg_list_move_next(otg_list_head *node_p, otg_list_head *list_head_p)
+{
+ otg_dbg(OTG_DBG_OTGHCDI_LIST, "otg_list_move_next \n");
+ list_move(node_p, list_head_p);
+}
+//-------------------------------------------------------------------------------
+
+/**
+ * void otg_list_move_prev(otg_list_head *node_p, otg_list_head *list_head_p)
+ *
+ * @brief move a list to previous of head
+ *
+ * @param [in] new_node_p : node to be moved
+ * @param [in] otg_list_head : target list head
+ *
+ * @return void \n
+ */
+static inline
+void otg_list_move_prev(otg_list_head *node_p, otg_list_head *list_head_p)
+{
+ otg_dbg(OTG_DBG_OTGHCDI_LIST, "otg_list_move_prev \n");
+ list_move_tail(node_p, list_head_p);
+}
+//-------------------------------------------------------------------------------
+
+/**
+ * bool otg_list_empty(otg_list_head *list_head_p)
+ *
+ * @brief check a list empty or not
+ *
+ * @param [in] list_head_p : node to check
+ *
+ * @return true : empty list \n
+ * false : not empty list
+ */
+static inline
+bool otg_list_empty(otg_list_head *list_head_p)
+{
+
+ otg_dbg(OTG_DBG_OTGHCDI_LIST, "otg_list_empty \n");
+ if(list_empty(list_head_p))
+ return true;
+ return false;
+}
+//-------------------------------------------------------------------------------
+
+/**
+ * void otg_list_merge(otg_list_head *list_p, otg_list_head *head_p)
+ *
+ * @brief merge two list
+ *
+ * @param [in] list_p : a head
+ * @param [in] head_p : target list head
+ *
+ * @return void \n
+ */
+static inline
+void otg_list_merge(otg_list_head *list_p, otg_list_head *head_p)
+{
+ otg_dbg(OTG_DBG_OTGHCDI_LIST, "otg_list_merge \n");
+ list_splice(list_p, head_p);
+}
+//-------------------------------------------------------------------------------
+
+/**
+ * void otg_list_init(otg_list_head *list_p)
+ *
+ * @brief initialize a list
+ *
+ * @param [in] list_p : node to be initialized
+ *
+ * @return void \n
+ */
+static inline
+void otg_list_init(otg_list_head *list_p)
+{
+ otg_dbg(OTG_DBG_OTGHCDI_LIST, "otg_list_init \n");
+ list_p->next = list_p;
+ list_p->prev = list_p;
+}
+//-------------------------------------------------------------------------------
+
+/*
+void otg_list_push_next(otg_list_head *new_node_p, otg_list_head *list_head_p );
+void otg_list_push_prev(otg_list_head *new_node_p, otg_list_head *list_head_p);
+void otg_list_pop(otg_list_head *list_entity_p);
+
+void otg_list_move_next(otg_list_head *node_p, otg_list_head *list_head_p);
+void otg_list_move_prev(otg_list_head *node_p, otg_list_head *list_head_p);
+
+bool otg_list_empty(otg_list_head *list_head_p);
+void otg_list_merge(otg_list_head *list_p, otg_list_head *head_p);
+void otg_list_init(otg_list_head *list_p);
+*/
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _S3C_OTG_HCDI_LIST_H_ */
+
diff --git a/drivers/usb/host/s3c-otg/s3c-otg-hcdi-memory.h b/drivers/usb/host/s3c-otg/s3c-otg-hcdi-memory.h
new file mode 100644
index 0000000..c87f15e
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/s3c-otg-hcdi-memory.h
@@ -0,0 +1,191 @@
+/****************************************************************************
+ * (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+ *
+ * @file s3c-otg-hcdi-memory.h
+ * @brief header of s3c-otg-hcdi-memory \n
+ * @version
+ * -# Jun 9,2008 v1.0 by SeungSoo Yang (ss1.yang@samsung.com) \n
+ * : Creating the initial version of this code \n
+ * -# Jul 15,2008 v1.2 by SeungSoo Yang (ss1.yang@samsung.com) \n
+ * : Optimizing for performance \n
+ * @see None
+ ****************************************************************************/
+/****************************************************************************
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ ****************************************************************************/
+
+#ifndef _S3C_OTG_HCDI_MEMORY_H_
+#define _S3C_OTG_HCDI_MEMORY_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "s3c-otg-common-common.h"
+#include "s3c-otg-hcdi-debug.h"
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+/**
+ * @enum otg_mem_alloc_flag
+ *
+ * @brief enumeration for flag of memory allocation
+ */
+typedef
+enum otg_mem_alloc_flag
+{
+ USB_MEM_SYNC, USB_MEM_ASYNC, USB_MEM_DMA
+}otg_mem_alloc_flag_t;
+//---------------------------------------------------------------------------------------
+
+/*
+inline int otg_mem_alloc(void ** addr_pp, u16 byte_size, otg_mem_alloc_flag_t type);
+inline int otg_mem_copy(void * to_addr_p, void * from_addr_p, u16 byte_size);
+//inline int otg_mem_free(void * addr_p);
+inline int otg_mem_set(void * addr_p, char value, u16 byte_size);
+*/
+
+/**
+ * int otg_mem_alloc(void ** addr_pp, u16 byte_size, u8 ubType);
+ *
+ * @brief allocating momory specified
+ *
+ * @param [inout] addr_pp : address to be assigned
+ * [in] byte_size : size of memory
+ * [in] type : otg_mem_alloc_flag_t type
+ *
+ * @return USB_ERR_SUCCESS : If success \n
+ * USB_ERR_FAIL : If call fail \n
+ */
+static inline int
+otg_mem_alloc (
+ void ** addr_pp,
+ u16 byte_size,
+ otg_mem_alloc_flag_t type
+)
+{
+ gfp_t flags;
+ otg_dbg(OTG_DBG_OTGHCDI_MEM, "otg_mem_alloc \n");
+
+ switch(type) {
+ case USB_MEM_SYNC:
+ flags = GFP_KERNEL;
+ break;
+ case USB_MEM_ASYNC:
+ flags = GFP_ATOMIC;
+ break;
+ case USB_MEM_DMA:
+ flags = GFP_DMA;
+ break;
+ default:
+ otg_err(OTG_DBG_OTGHCDI_MEM,
+ "not proper otg_mem_alloc_flag_t in otg_mem_alloc \n");
+ return USB_ERR_FAIL;
+ }
+
+ *addr_pp = kmalloc((size_t)byte_size, flags);
+ if(*addr_pp == 0) {
+ otg_err(OTG_DBG_OTGHCDI_MEM,
+ "kmalloc failed\n");
+ return USB_ERR_FAIL;
+ }
+ return USB_ERR_SUCCESS;
+}
+//-------------------------------------------------------------------------------
+
+/**
+ * int otg_mem_copy(void * to_addr_p, void * from_addr_p, u16 byte_size);
+ *
+ * @brief memory copy
+ *
+ * @param [in] to_addr_p : target address
+ * [in] from_addr_p : source address
+ * [in] byte_size : size
+ *
+ * @return USB_ERR_SUCCESS : If success \n
+ * USB_ERR_FAIL : If call fail \n
+ */
+static inline int
+otg_mem_copy
+(
+ void * to_addr_p,
+ void * from_addr_p,
+ u16 byte_size
+)
+{
+ otg_dbg(OTG_DBG_OTGHCDI_MEM,
+ "otg_mem_copy \n");
+
+ memcpy(to_addr_p, from_addr_p, (size_t)byte_size);
+
+ return USB_ERR_SUCCESS;
+}
+//-------------------------------------------------------------------------------
+
+/**
+ * int otg_mem_free(void * addr_p);
+ *
+ * @brief de-allocating memory
+ *
+ * @param [in] addr_p : target address to be de-allocated
+ *
+ * @return USB_ERR_SUCCESS : If success \n
+ * USB_ERR_FAIL : If call fail \n
+ */
+static inline int
+otg_mem_free(void * addr_p)
+{
+ otg_dbg(OTG_DBG_OTGHCDI_MEM,
+ "otg_mem_free \n");
+ kfree(addr_p);
+ return USB_ERR_SUCCESS;
+}
+
+//-------------------------------------------------------------------------------
+
+/**
+ * int otg_mem_set(void * addr_p, char value, u16 byte_size)
+ *
+ * @brief writing a value to memory
+ *
+ * @param [in] addr_p : target address
+ * [in] value : value to be written
+ * [in] byte_size : size
+ *
+ * @return USB_ERR_SUCCESS : If success \n
+ * USB_ERR_FAIL : If call fail \n
+ */
+static inline int
+otg_mem_set
+(
+ void * addr_p,
+ char value,
+ u16 byte_size
+)
+{
+ otg_dbg(OTG_DBG_OTGHCDI_MEM,
+ "otg_mem_set \n");
+ memset(addr_p, value, (size_t)byte_size);
+ return USB_ERR_SUCCESS;
+}
+//-------------------------------------------------------------------------------
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _S3C_OTG_HCDI_MEMORY_H_ */
diff --git a/drivers/usb/host/s3c-otg/s3c-otg-isr.c b/drivers/usb/host/s3c-otg/s3c-otg-isr.c
new file mode 100644
index 0000000..6bb790d
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/s3c-otg-isr.c
@@ -0,0 +1,294 @@
+/****************************************************************************
+ * (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+ *
+ * [File Name] : Isr.c
+ * [Description] : The file implement the external and internal functions of ISR
+ * [Author] : Jang Kyu Hyeok { kyuhyeok.jang@samsung.com }
+ * [Department] : System LSI Division/Embedded S/W Platform
+ * [Created Date]: 2009/02/10
+ * [Revision History]
+ * (1) 2008/06/13 by Jang Kyu Hyeok { kyuhyeok.jang@samsung.com }
+ * - Created this file and implements functions of ISR
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * 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 "s3c-otg-isr.h"
+
+/**
+ * void otg_handle_interrupt(void)
+ *
+ * @brief Main interrupt processing routine
+ *
+ * @param None
+ *
+ * @return None
+ *
+ * @remark
+ *
+ */
+
+__inline__ void otg_handle_interrupt(struct usb_hcd *hcd)
+{
+ gintsts_t clearIntr = {.d32 = 0};
+ gintsts_t gintsts = {.d32 = 0};
+ struct sec_otghost *otghost = hcd_to_sec_otghost(hcd);
+
+ gintsts.d32 = read_reg_32(GINTSTS) & read_reg_32(GINTMSK);
+
+ otg_dbg(OTG_DBG_ISR, "otg_handle_interrupt - GINTSTS=0x%8x\n",
+ gintsts.d32);
+
+ if (gintsts.b.wkupintr) {
+ otg_dbg(true, "Wakeup Interrupt\n");
+ clearIntr.b.wkupintr = 1;
+ }
+
+ if (gintsts.b.disconnect) {
+ otg_dbg(true, "Disconnect Interrupt\n");
+ otghost->port_flag.b.port_connect_status_change = 1;
+ otghost->port_flag.b.port_connect_status = 0;
+ clearIntr.b.disconnect = 1;
+ /*
+ wake_unlock(&otghost->wake_lock);
+ */
+ }
+
+ if (gintsts.b.conidstschng) {
+ otg_dbg(OTG_DBG_ISR, "Connect ID Status Change Interrupt\n");
+ clearIntr.b.conidstschng = 1;
+ oci_init_mode(otghost);
+ }
+
+ if (gintsts.b.hcintr) {
+ /* Mask Channel Interrupt to prevent generating interrupt */
+ otg_dbg(OTG_DBG_ISR, "Channel Interrupt\n");
+ if(!otghost->ch_halt) {
+ do_transfer_checker(otghost);
+ }
+ }
+
+ if (gintsts.b.portintr) {
+ /* Read Only */
+ otg_dbg(true, "Port Interrupt\n");
+ process_port_intr(hcd);
+ }
+
+
+ if (gintsts.b.otgintr) {
+ /* Read Only */
+ otg_dbg(OTG_DBG_ISR, "OTG Interrupt\n");
+ }
+
+ if (gintsts.b.sofintr) {
+ /* otg_dbg(OTG_DBG_ISR, "SOF Interrupt\n"); */
+ do_schedule(otghost);
+ clearIntr.b.sofintr = 1;
+ }
+
+ if (gintsts.b.modemismatch) {
+ otg_dbg(OTG_DBG_ISR, "Mode Mismatch Interrupt\n");
+ clearIntr.b.modemismatch = 1;
+ }
+ update_reg_32(GINTSTS, clearIntr.d32);
+}
+
+/**
+ * void mask_channel_interrupt(u32 ch_num, u32 mask_info)
+ *
+ * @brief Mask specific channel interrupt
+ *
+ * @param [IN] chnum : channel number for masking
+ * [IN] mask_info : mask information to write register
+ *
+ * @return None
+ *
+ * @remark
+ *
+ */
+void mask_channel_interrupt(u32 ch_num, u32 mask_info)
+{
+ clear_reg_32(HCINTMSK(ch_num),mask_info);
+}
+
+/**
+ * void unmask_channel_interrupt(u32 ch_num, u32 mask_info)
+ *
+ * @brief Unmask specific channel interrupt
+ *
+ * @param [IN] chnum : channel number for unmasking
+ * [IN] mask_info : mask information to write register
+ *
+ * @return None
+ *
+ * @remark
+ *
+ */
+void unmask_channel_interrupt(u32 ch_num, u32 mask_info)
+{
+ update_reg_32(HCINTMSK(ch_num),mask_info);
+}
+
+/**
+ * int get_ch_info(hc_info_t * hc_reg, u8 ch_num)
+ *
+ * @brief Get current channel information about specific channel
+ *
+ * @param [OUT] hc_reg : structure to write channel inforamtion value
+ * [IN] ch_num : channel number for unmasking
+ *
+ * @return None
+ *
+ * @remark
+ *
+ */
+int get_ch_info(hc_info_t *hc_reg, u8 ch_num)
+{
+ if(hc_reg !=NULL) {
+ hc_reg->hc_int_msk.d32 = read_reg_32(HCINTMSK(ch_num));
+ hc_reg->hc_int.d32 = read_reg_32(HCINT(ch_num));
+ hc_reg->dma_addr = read_reg_32(HCDMA(ch_num));
+ hc_reg->hc_char.d32 = read_reg_32(HCCHAR(ch_num));
+ hc_reg->hc_size.d32 = read_reg_32(HCTSIZ(ch_num));
+
+ return USB_ERR_SUCCESS;
+ }
+ return USB_ERR_FAIL;
+}
+
+/**
+ * void get_intr_ch(u32* haint, u32* haintmsk)
+ *
+ * @brief Get Channel Interrupt Information in HAINT, HAINTMSK register
+ *
+ * @param [OUT] haint : HAINT register value
+ * [OUT] haintmsk : HAINTMSK register value
+ *
+ * @return None
+ *
+ * @remark
+ *
+ */
+void get_intr_ch(u32 *haint, u32 *haintmsk)
+{
+ *haint = read_reg_32(HAINT);
+ *haintmsk = read_reg_32(HAINTMSK);
+}
+
+/**
+ * void clear_ch_intr(u8 ch_num, u32 clear_bit)
+ *
+ * @brief Get Channel Interrupt Information in HAINT, HAINTMSK register
+ *
+ * @param [IN] haint : HAINT register value
+ * [IN] haintmsk : HAINTMSK register value
+ *
+ * @return None
+ *
+ * @remark
+ *
+ */
+void clear_ch_intr(u8 ch_num, u32 clear_bit)
+{
+ update_reg_32(HCINT(ch_num),clear_bit);
+}
+
+/**
+ * void enable_sof(void)
+ *
+ * @brief Generate SOF Interrupt.
+ *
+ * @param None
+ *
+ * @return None
+ *
+ * @remark
+ *
+ */
+void enable_sof(void)
+{
+ gintmsk_t gintmsk = {.d32 = 0};
+ gintmsk.b.sofintr = 1;
+ update_reg_32(GINTMSK, gintmsk.d32);
+}
+
+/**
+ * void disable_sof(void)
+ *
+ * @brief Stop to generage SOF interrupt
+ *
+ * @param None
+ *
+ * @return None
+ *
+ * @remark
+ *
+ */
+void disable_sof(void)
+{
+ gintmsk_t gintmsk = {.d32 = 0};
+ gintmsk.b.sofintr = 1;
+ clear_reg_32(GINTMSK, gintmsk.d32);
+}
+
+/*Internal function of isr */
+void process_port_intr(struct usb_hcd *hcd)
+{
+ hprt_t hprt; /* by ss1, clear_hprt; */
+ struct sec_otghost *otghost = hcd_to_sec_otghost(hcd);
+
+ hprt.d32 = read_reg_32(HPRT);
+
+ otg_dbg(OTG_DBG_ISR, "Port Interrupt() : HPRT = 0x%x\n",hprt.d32);
+
+ if(hprt.b.prtconndet) {
+ otg_dbg(true, "detect connection");
+
+ otghost->port_flag.b.port_connect_status_change = 1;
+
+ if(hprt.b.prtconnsts)
+ otghost->port_flag.b.port_connect_status = 1;
+
+ /* wake_lock(&otghost->wake_lock); */
+ }
+
+
+ if(hprt.b.prtenchng) {
+ otg_dbg(true, "port enable/disable changed\n");
+ otghost->port_flag.b.port_enable_change = 1;
+ }
+
+ if(hprt.b.prtovrcurrchng) {
+ otg_dbg(true, "over current condition is changed\n");
+ if(hprt.b.prtovrcurract) {
+ otg_dbg(true, "port_over_current_change = 1\n");
+ otghost->port_flag.b.port_over_current_change = 1;
+ }
+ else {
+ otghost->port_flag.b.port_over_current_change = 0;
+ }
+ /* defer otg power control into a kernel thread */
+ queue_work(otghost->wq, &otghost->work);
+ }
+
+ hprt.b.prtena = 0; /* prtena¸¦ writeclear½ÃŰ¸é ¾ÈµÊ. */
+ /* hprt.b.prtpwr = 0; */
+ hprt.b.prtrst = 0;
+ hprt.b.prtconnsts = 0;
+
+ write_reg_32(HPRT, hprt.d32);
+}
diff --git a/drivers/usb/host/s3c-otg/s3c-otg-isr.h b/drivers/usb/host/s3c-otg/s3c-otg-isr.h
new file mode 100644
index 0000000..cad4cf5
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/s3c-otg-isr.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+ * (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+ *
+ * [File Name] :s3c-otg-isr.h
+ * [Description] : The Header file defines the external and internal functions of ISR.
+ * [Author] : Jang Kyu Hyeok { kyuhyeok.jang@samsung.com }
+ * [Department] : System LSI Division/Embedded S/W Platform
+ * [Created Date]: 2008/06/18
+ * [Revision History]
+ * (1) 2008/06/18 by Jang Kyu Hyeok { kyuhyeok.jang@samsung.com }
+ * - Created this file and defines functions of Scheduler
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ ****************************************************************************/
+
+#ifndef _ISR_H_
+#define _ISR_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "s3c-otg-common-errorcode.h"
+#include "s3c-otg-common-const.h"
+#include "s3c-otg-common-datastruct.h"
+#include "s3c-otg-common-regdef.h"
+#include "s3c-otg-hcdi-kal.h"
+#include "s3c-otg-scheduler-scheduler.h"
+#include "s3c-otg-transferchecker-common.h"
+#include "s3c-otg-roothub.h"
+#include "s3c-otg-oci.h"
+
+__inline__ void otg_handle_interrupt(struct usb_hcd *hcd);
+
+void process_port_intr(struct usb_hcd *hcd);
+
+void mask_channel_interrupt(u32 ch_num, u32 mask_info);
+
+void unmask_channel_interrupt(u32 ch_num, u32 mask_info);
+
+extern int get_ch_info(hc_info_t *hc_reg, u8 ch_num);
+
+extern void get_intr_ch(u32 *haint, u32 *haintmsk);
+
+extern void clear_ch_intr(u8 ch_num, u32 clear_bit);
+
+extern void enable_sof(void);
+
+extern void disable_sof(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _ISR_H_ */
+
+
+
diff --git a/drivers/usb/host/s3c-otg/s3c-otg-oci.c b/drivers/usb/host/s3c-otg/s3c-otg-oci.c
new file mode 100644
index 0000000..0744b9e
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/s3c-otg-oci.c
@@ -0,0 +1,815 @@
+/****************************************************************************
+ * (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+ *
+ * [File Name] : OCI.c
+ * [Description] : The file implement the external and internal functions of OCI
+ * [Author] : Jang Kyu Hyeok { kyuhyeok.jang@samsung.com }
+ * [Department] : System LSI Division/Embedded S/W Platform
+ * [Created Date]: 2009/02/10
+ * [Revision History]
+ * (1) 2008/06/12 by Jang Kyu Hyeok { kyuhyeok.jang@samsung.com }
+ * - Created this file and Implement functions of OCI
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * 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 "s3c-otg-oci.h"
+
+static bool ch_enable[16];
+
+/**
+ * int oci_init(struct sec_otghost *otghost)
+ *
+ * @brief Initialize oci module.
+ *
+ * @param None
+ *
+ * @return USB_ERR_SUCCESS : If success \n
+ * USB_ERR_FAIL : If call fail \n
+ * @remark
+ *
+ */
+int oci_init(struct sec_otghost *otghost)
+{
+ otg_mem_set((void*)ch_enable, true, sizeof(bool)*16);
+ otghost->ch_halt = false;
+
+ if(oci_sys_init(otghost) == USB_ERR_SUCCESS) {
+ if(oci_core_reset() == USB_ERR_SUCCESS) {
+ oci_set_global_interrupt(false);
+ return USB_ERR_SUCCESS;
+ }
+ else {
+ otg_dbg(OTG_DBG_OCI, "oci_core_reset() Fail\n");
+ return USB_ERR_FAIL;
+ }
+ }
+
+ return USB_ERR_FAIL;
+}
+
+/**
+ * int oci_core_init(struct sec_otghost *otghost)
+ *
+ * @brief process core initialize as s5pc110 otg spec
+ *
+ * @param None
+ *
+ * @return USB_ERR_SUCCESS : If success \n
+ * USB_ERR_FAIL : If call fail \n
+ * @remark
+ *
+ */
+int oci_core_init(struct sec_otghost *otghost)
+{
+ gahbcfg_t ahbcfg = {.d32 = 0};
+ gusbcfg_t usbcfg = {.d32 = 0};
+ ghwcfg2_t hwcfg2 = {.d32 = 0};
+ gintmsk_t gintmsk = {.d32 = 0};
+
+ otg_dbg(OTG_DBG_OCI, "oci_core_init \n");
+
+ usbcfg.d32 = read_reg_32(GUSBCFG);
+ otg_dbg(OTG_DBG_OCI, "before - GUSBCFG=0x%x, GOTGCTL=0x%x\n",
+ usbcfg.d32, read_reg_32(GOTGCTL));
+
+ /* PHY parameters */
+ usbcfg.b.physel = 0;
+ usbcfg.b.phyif = 1; /* 16 bit */
+ usbcfg.b.ulpi_utmi_sel = 0; /* UTMI */
+ /* usbcfg.b.ddrsel = 1; */ /* DDR */
+ usbcfg.b.usbtrdtim = 5; /* 16 bit UTMI */
+ usbcfg.b.toutcal = 7;
+ usbcfg.b.forcehstmode = 1;
+ write_reg_32 (GUSBCFG, usbcfg.d32);
+
+ // per
+ // http://forum.xda-developers.com/showthread.php?t=709135&page=21
+ // we need a 25msec delay after setting this -kevinh
+
+ mdelay(100);
+
+ otg_dbg(OTG_DBG_OCI,
+ "after - GUSBCFG=0x%x, GOTGCTL=0x%x\n",
+ read_reg_32(GUSBCFG),
+ read_reg_32(GOTGCTL));
+
+ /* Reset after setting the PHY parameters */
+ if(oci_core_reset() == USB_ERR_SUCCESS) {
+ /* Program the GAHBCFG Register.*/
+ hwcfg2.d32 = read_reg_32 (GHWCFG2);
+
+ switch (hwcfg2.b.architecture) {
+ case HWCFG2_ARCH_SLAVE_ONLY:
+ otg_dbg(OTG_DBG_OCI, "Slave Only Mode\n");
+ ahbcfg.b.nptxfemplvl = 0;
+ ahbcfg.b.ptxfemplvl = 0;
+ break;
+
+ case HWCFG2_ARCH_EXT_DMA:
+ otg_dbg(OTG_DBG_OCI, "External DMA Mode - TBD!\n");
+ break;
+
+ case HWCFG2_ARCH_INT_DMA:
+ otg_dbg(OTG_DBG_OCI, "Internal DMA Setting \n");
+ ahbcfg.b.dmaenable = true;
+ ahbcfg.b.hburstlen = INT_DMA_MODE_INCR4;
+ break;
+
+ default:
+ otg_dbg(OTG_DBG_OCI, "ERR> hwcfg2\n ");
+ break;
+ }
+ write_reg_32 (GAHBCFG, ahbcfg.d32);
+
+ /* Program the GUSBCFG register.*/
+ switch (hwcfg2.b.op_mode) {
+ case MODE_HNP_SRP_CAPABLE:
+ otg_dbg(OTG_DBG_OCI,
+ "GHWCFG2 OP Mode : MODE_HNP_SRP_CAPABLE \n");
+ usbcfg.b.hnpcap = 1;
+ usbcfg.b.srpcap = 1;
+
+ otg_dbg(OTG_DBG_OCI,
+ "OTG_DBG_OCI : use HNP and SRP \n");
+ break;
+
+ case MODE_SRP_ONLY_CAPABLE:
+ otg_dbg(OTG_DBG_OCI,
+ "GHWCFG2 OP Mode : MODE_SRP_ONLY_CAPABLE \n");
+ usbcfg.b.srpcap = 1;
+ break;
+
+ case MODE_NO_HNP_SRP_CAPABLE:
+ otg_dbg(OTG_DBG_OCI,
+ "GHWCFG2 OP Mode : MODE_NO_HNP_SRP_CAPABLE \n");
+ usbcfg.b.hnpcap = 0;
+ break;
+
+ case MODE_SRP_CAPABLE_DEVICE:
+ otg_dbg(OTG_DBG_OCI,
+ "GHWCFG2 OP Mode : MODE_SRP_CAPABLE_DEVICE \n");
+ usbcfg.b.srpcap = 1;
+ break;
+
+ case MODE_NO_SRP_CAPABLE_DEVICE:
+ otg_dbg(OTG_DBG_OCI,
+ "GHWCFG2 OP Mode : MODE_NO_SRP_CAPABLE_DEVICE \n");
+ usbcfg.b.srpcap = 0;
+ break;
+
+ case MODE_SRP_CAPABLE_HOST:
+ otg_dbg(OTG_DBG_OCI,
+ "GHWCFG2 OP Mode : MODE_SRP_CAPABLE_HOST \n");
+ usbcfg.b.srpcap = 1;
+ break;
+
+ case MODE_NO_SRP_CAPABLE_HOST:
+ otg_dbg(OTG_DBG_OCI,
+ "GHWCFG2 OP Mode : MODE_NO_SRP_CAPABLE_HOST \n");
+ usbcfg.b.srpcap = 0;
+ break;
+ default :
+ otg_err(OTG_DBG_OCI, "ERR> hwcfg2\n ");
+ break;
+ }
+ write_reg_32 (GUSBCFG, usbcfg.d32);
+
+ /* Program the GINTMSK register.*/
+ gintmsk.b.modemismatch = 1;
+ gintmsk.b.sofintr = 1;
+ /*gintmsk.b.otgintr = 1; */
+ gintmsk.b.conidstschng = 1;
+ /*gintmsk.b.wkupintr = 1;*/
+ gintmsk.b.disconnect = 1;
+ /*gintmsk.b.usbsuspend = 1;*/
+ /*gintmsk.b.sessreqintr = 1;*/
+ /*gintmsk.b.portintr = 1;*/
+ /*gintmsk.b.hcintr = 1; */
+ write_reg_32(GINTMSK, gintmsk.d32);
+
+ return USB_ERR_SUCCESS;
+ }
+ else {
+ otg_err(OTG_DBG_OCI, "Core Reset FAIL\n");
+ return USB_ERR_FAIL;
+ }
+}
+
+/**
+ * int oci_host_init(struct sec_otghost *otghost)
+ *
+ * @brief Process host initialize as s5pc110 spec
+ *
+ * @param None
+ *
+ * @return USB_ERR_SUCCESS : If success \n
+ * USB_ERR_FAIL : If call fail \n
+ * @remark
+ *
+ */
+int oci_host_init(struct sec_otghost *otghost)
+{
+ gintmsk_t gintmsk = {.d32 = 0};
+ hcfg_t hcfg = {.d32 = 0};
+#if 0
+/*#ifdef CONFIG_USB_S3C_OTG_HOST_DTGDRVVBUS*/
+ hprt_t hprt;
+ hprt.d32 = read_reg_32(HPRT);
+#endif
+
+ otg_dbg(OTG_DBG_OCI, "oci_host_init\n");
+
+ gintmsk.b.portintr = 1;
+ update_reg_32(GINTMSK,gintmsk.d32);
+
+ if (!otghost->is_hs) {
+ hcfg.b.fslssupp = 1; // force USB 1.x mode
+ } else {
+ hcfg.b.fslssupp = 0;
+ }
+ hcfg.b.fslspclksel = HCFG_30_60_MHZ;
+ update_reg_32(HCFG, hcfg.d32);
+
+#if 0
+/*#ifdef CONFIG_USB_S3C_OTG_HOST_DTGDRVVBUS*/
+ /* turn on vbus */
+ if(!hprt.b.prtpwr) {
+ hprt.b.prtpwr = 1;
+ write_reg_32(HPRT, hprt.d32);
+
+ otg_dbg(true, "turn on Vbus\n");
+ }
+#endif
+
+ oci_config_flush_fifo(OTG_HOST_MODE);
+
+ return USB_ERR_SUCCESS;
+}
+
+/**
+ * int oci_start(struct sec_otghost *otghost)
+ *
+ * @brief start to operate oci module by calling oci_core_init function
+ *
+ * @param None
+ *
+ * @return USB_ERR_SUCCESS : If success \n
+ * USB_ERR_FAIL : If call fail \n
+ * @remark
+ *
+ */
+int oci_start(struct sec_otghost *otghost)
+{
+ otg_dbg(OTG_DBG_OCI, "oci_start \n");
+
+ if(oci_core_init(otghost) == USB_ERR_SUCCESS) {
+ mdelay(50);
+ if(oci_init_mode(otghost) == USB_ERR_SUCCESS) {
+ oci_set_global_interrupt(true);
+ return USB_ERR_SUCCESS;
+ }
+ else {
+ otg_dbg(OTG_DBG_OCI, "oci_init_mode() Fail\n");
+ return USB_ERR_FAIL;
+ }
+ }
+ else {
+ otg_dbg(OTG_DBG_OCI, "oci_core_init() Fail\n");
+ return USB_ERR_FAIL;
+ }
+}
+
+/**
+ * int oci_stop(struct sec_otghost *otghost)
+ *
+ * @brief stop to opearte otg core
+ *
+ * @param None
+ *
+ * @return USB_ERR_SUCCESS : If success \n
+ * USB_ERR_FAIL : If call fail \n
+ * @remark
+ *
+ */
+int oci_stop(struct sec_otghost *otghost)
+{
+ gintmsk_t gintmsk = {.d32 = 0};
+
+ otg_dbg(OTG_DBG_OCI, "oci_stop\n");
+
+ /* sometimes, port interrupt occured after removed
+ * otg host driver. so, we have to mask port interrupt. */
+ write_reg_32(GINTMSK, gintmsk.d32);
+
+ oci_set_global_interrupt(false);
+
+ return USB_ERR_SUCCESS;
+}
+
+/**
+ * oci_start_transfer(struct sec_otghost *otghost, stransfer_t *st_t)
+ *
+ * @brief start transfer by using transfer information to receive from scheduler
+ *
+ * @param [IN] *st_t - information about transfer to write register by calling oci_channel_init function
+ *
+ * @return USB_ERR_SUCCESS : If success \n
+ * USB_ERR_FAIL : If call fail \n
+ * @remark
+ *
+ */
+
+u8 oci_start_transfer(struct sec_otghost *otghost, stransfer_t *st_t)
+{
+ hcchar_t hcchar = {.d32 = 0};
+
+ otg_dbg(OTG_DBG_OCI, "oci_start_transfer \n");
+
+ if(st_t->alloc_chnum ==CH_NONE) {
+
+ if( oci_channel_alloc(&(st_t->alloc_chnum)) == USB_ERR_SUCCESS) {
+ oci_channel_init(st_t->alloc_chnum, st_t);
+
+ hcchar.b.chen = 1;
+ update_reg_32(HCCHAR(st_t->alloc_chnum), hcchar.d32);
+ return st_t->alloc_chnum;
+ }
+ else {
+ otg_dbg(OTG_DBG_OCI,
+ "oci_start_transfer Fail - Channel Allocation Error\n");
+ return CH_NONE;
+ }
+ }
+ else {
+ oci_channel_init(st_t->alloc_chnum, st_t);
+
+ hcchar.b.chen = 1;
+ update_reg_32(HCCHAR(st_t->alloc_chnum), hcchar.d32);
+
+ return st_t->alloc_chnum;
+ }
+}
+
+/**
+ * int oci_stop_transfer(struct sec_otghost *otghost, u8 ch_num)
+ *
+ * @brief stop to transfer even if transfering
+ *
+ * @param None
+ *
+ * @return USB_ERR_SUCCESS : If success \n
+ * USB_ERR_FAIL : If call fail \n
+ * @remark
+ *
+ */
+int oci_stop_transfer(struct sec_otghost *otghost, u8 ch_num)
+{
+ hcchar_t hcchar = {.d32 = 0};
+ hcintmsk_t hcintmsk = {.d32 = 0};
+ int count = 0, max_error_count = 10000;
+
+ otg_dbg(OTG_DBG_OCI,
+ "step1: oci_stop_transfer ch=%d, hcchar=0x%x\n",
+ ch_num, read_reg_32(HCCHAR(ch_num)));
+
+ if(ch_num>16)
+ return USB_ERR_FAIL;
+
+ otghost->ch_halt = true;
+
+ hcintmsk.b.chhltd = 1;
+ update_reg_32(HCINTMSK(ch_num),hcintmsk.d32);
+
+ hcchar.b.chdis = 1;
+ hcchar.b.chen = 1;
+ update_reg_32(HCCHAR(ch_num),hcchar.d32);
+
+ /* wait for Channel Disabled Interrupt */
+ do {
+ hcchar.d32 = read_reg_32(HCCHAR(ch_num));
+
+ if(count > max_error_count) {
+ otg_dbg(OTG_DBG_OCI,
+ "Warning!! oci_stop_transfer()"
+ "ChDis is not cleared! ch=%d, hcchar=0x%x\n",
+ ch_num, hcchar.d32);
+ break;
+ }
+ count++;
+
+ } while(hcchar.b.chdis);
+
+ //kevinh: wait for Channel Disabled Interrupt
+ count = 0;
+ do {
+ hcintmsk.d32 = read_reg_32(HCINT(ch_num));
+ if(count > max_error_count) {
+ printk("chhltd int never occurred! ch=%d, intreg=0x%x\n",
+ ch_num, hcintmsk.d32);
+ break;
+ }
+ count++;
+ } while(!hcintmsk.b.chhltd);
+
+ oci_channel_dealloc(ch_num);
+
+ clear_reg_32(HAINTMSK,ch_num);
+ write_reg_32(HCINT(ch_num),INT_ALL);
+ clear_reg_32(HCINTMSK(ch_num), INT_ALL);
+
+ otghost->ch_halt = false;
+ otg_dbg(OTG_DBG_OCI,
+ "step2 : oci_stop_transfer ch=%d, hcchar=0x%x\n",
+ ch_num, read_reg_32(HCCHAR(ch_num)));
+
+ return USB_ERR_SUCCESS;
+}
+
+/**
+ * int oci_channel_init( u8 ch_num, stransfer_t *st_t)
+ *
+ * @brief Process channel initialize to prepare starting transfer
+ *
+ * @param None
+ *
+ * @return USB_ERR_SUCCESS : If success \n
+ * USB_ERR_FAIL : If call fail \n
+ * @remark
+ *
+ */
+int oci_channel_init( u8 ch_num, stransfer_t *st_t)
+{
+ u32 intr_enable = 0;
+ gintmsk_t gintmsk = {.d32 = 0};
+ hcchar_t hcchar = {.d32 = 0};
+ hctsiz_t hctsiz = {.d32 = 0};
+ hcsplt_t hcsplt = {.d32 = 0};
+
+ otg_dbg(OTG_DBG_OCI, "oci_channel_init \n");
+
+ /* Clear channel information */
+ write_reg_32(HCTSIZ(ch_num), 0);
+ write_reg_32(HCCHAR(ch_num), 0);
+ write_reg_32(HCINTMSK(ch_num), 0);
+ write_reg_32(HCINT(ch_num), INT_ALL);/*write clear*/
+ write_reg_32(HCDMA(ch_num), 0);
+
+ /* enable host channel interrupt in GINTSTS */
+ gintmsk.b.hcintr =1;
+ update_reg_32(GINTMSK, gintmsk.d32);
+ /* Enable the top level host channel interrupt in HAINT */
+ intr_enable = (1 << ch_num);
+ update_reg_32(HAINTMSK, intr_enable);
+ /* unmask the down level host channel interrupt in HCINT */
+ write_reg_32(HCINTMSK(ch_num),st_t->hc_reg.hc_int_msk.d32);
+
+ /* Program the HCSIZn register with the endpoint characteristics for */
+ hctsiz.b.xfersize = st_t->buf_size;
+ hctsiz.b.pktcnt = st_t->packet_cnt;
+
+ /* Program the HCCHARn register with the endpoint characteristics for */
+ hcchar.b.mps = st_t->ed_desc_p->max_packet_size;
+ hcchar.b.epnum = st_t->ed_desc_p->endpoint_num;
+ hcchar.b.epdir = st_t->ed_desc_p->is_ep_in;
+ hcchar.b.lspddev = (st_t->ed_desc_p->dev_speed == LOW_SPEED_OTG);
+ hcchar.b.eptype = st_t->ed_desc_p->endpoint_type;
+ hcchar.b.multicnt = st_t->ed_desc_p->mc;
+ hcchar.b.devaddr = st_t->ed_desc_p->device_addr;
+
+ if(st_t->ed_desc_p->endpoint_type == INT_TRANSFER ||
+ st_t->ed_desc_p->endpoint_type == ISOCH_TRANSFER) {
+ u32 uiFrameNum = 0;
+ uiFrameNum = oci_get_frame_num();
+
+ hcchar.b.oddfrm = uiFrameNum%2?1:0;
+
+ /*
+ * if transfer type is periodic transfer,
+ * must support sof interrupt
+ */
+
+ /*
+ gintmsk.b.sofintr = 1;
+ update_reg_32(GINTMSK, gintmsk.d32);
+ */
+ }
+
+ if(st_t->ed_desc_p->endpoint_type == CONTROL_TRANSFER) {
+ td_t *td_p;
+ td_p = (td_t *)st_t->parent_td;
+
+ switch(td_p->standard_dev_req_info.conrol_transfer_stage) {
+ case SETUP_STAGE:
+ hctsiz.b.pid = st_t->ed_status_p->control_data_tgl.setup_tgl;
+ hcchar.b.epdir = EP_OUT;
+ break;
+ case DATA_STAGE:
+ hctsiz.b.pid = st_t->ed_status_p->control_data_tgl.data_tgl;
+ hcchar.b.epdir = st_t->ed_desc_p->is_ep_in;
+ break;
+ case STATUS_STAGE:
+ hctsiz.b.pid = st_t->ed_status_p->control_data_tgl.status_tgl;
+
+ if(td_p->standard_dev_req_info.is_data_stage) {
+ hcchar.b.epdir = ~(st_t->ed_desc_p->is_ep_in);
+ }
+ else {
+ hcchar.b.epdir = EP_IN;
+ }
+ break;
+ default:break;
+ }
+ }
+ else {
+ hctsiz.b.pid = st_t->ed_status_p->data_tgl;
+ }
+
+ hctsiz.b.dopng = st_t->ed_status_p->is_ping_enable;
+ write_reg_32(HCTSIZ(ch_num),hctsiz.d32);
+ st_t->ed_status_p->is_ping_enable = false;
+
+ /* Write DMA Address */
+ write_reg_32(HCDMA(ch_num),st_t->start_phy_buf_addr);
+
+ /* Wrote HCCHAR Register */
+ write_reg_32(HCCHAR(ch_num),hcchar.d32);
+
+ /* sztupy: Enable split transaction support if driver is in HS mode */
+ if (st_t->ed_desc_p->is_do_split) {
+ printk("splittrans");
+ hcsplt.b.spltena = 1;
+ hcsplt.b.hubaddr = st_t->ed_desc_p->hub_addr;
+ hcsplt.b.prtaddr = st_t->ed_desc_p->hub_port;
+ hcsplt.b.xactpos = st_t->ed_status_p->split_pos;
+ hcsplt.b.compsplt = st_t->ed_status_p->is_complete_split;
+ }
+ write_reg_32(HCSPLT(ch_num),hcsplt.d32);
+
+ return USB_ERR_SUCCESS;
+}
+
+/**
+ * u32 oci_get_frame_num(void)
+ *
+ * @brief Get current frame number by reading register.
+ *
+ * @param None
+ *
+ * @return USB_ERR_SUCCESS : If success \n
+ * USB_ERR_FAIL : If call fail \n
+ * @remark
+ *
+ */
+u32 oci_get_frame_num(void)
+{
+ hfnum_t hfnum;
+ hfnum.d32 = read_reg_32(HFNUM);
+
+ otg_dbg(OTG_DBG_OCI, " oci_get_frame_num=%d\n", hfnum.b.frnum);
+
+ return hfnum.b.frnum;
+}
+
+/**
+ * u16 oci_get_frame_interval(void)
+ *
+ * @brief Get current frame interval by reading register.
+ *
+ * @param None
+ *
+ * @return USB_ERR_SUCCESS : If success \n
+ * USB_ERR_FAIL : If call fail \n
+ * @remark
+ *
+ */
+u16 oci_get_frame_interval(void)
+{
+ hfir_t hfir;
+ hfir.d32 = read_reg_32(HFIR);
+ return hfir.b.frint;
+}
+
+void oci_set_frame_interval(u16 interval)
+{
+ hfir_t hfir = {.d32 = 0};
+ hfir.b.frint = interval;
+ write_reg_32(HFIR, hfir.d32);
+}
+
+/* OCI Internal Functions */
+
+int oci_channel_alloc(u8 *ch_num)
+{
+ u8 ch;
+
+ hcchar_t hcchar = {.d32 = 0};
+
+ for(ch = 0 ; ch<16 ; ch++) {
+ if(ch_enable[ch] == true) {
+ hcchar.d32 = read_reg_32(HCCHAR(ch));
+
+ if(hcchar.b.chdis == 0) {
+ *ch_num = ch;
+ ch_enable[ch] = false;
+ return USB_ERR_SUCCESS;
+ }
+ }
+ }
+
+ return USB_ERR_FAIL;
+}
+
+int oci_channel_dealloc(u8 ch_num)
+{
+ if(ch_num < 16 && ch_enable[ch_num] == false) {
+ ch_enable[ch_num] = true;
+
+ write_reg_32(HCTSIZ(ch_num), 0);
+ write_reg_32(HCCHAR(ch_num), 0);
+ write_reg_32(HCINTMSK(ch_num), 0);
+ write_reg_32(HCINT(ch_num), INT_ALL);
+ write_reg_32(HCDMA(ch_num), 0);
+ return USB_ERR_SUCCESS;
+ }
+
+ return USB_ERR_FAIL;
+}
+
+int oci_sys_init(struct sec_otghost *otghost)
+{
+ otg_host_phy_init();
+
+ return USB_ERR_SUCCESS;
+}
+
+void oci_set_global_interrupt(bool set)
+{
+ gahbcfg_t ahbcfg;
+
+ otg_dbg(OTG_DBG_OCI, " oci_set_global_interrupt\n");
+
+ ahbcfg.d32 = 0;
+ ahbcfg.b.glblintrmsk = 1;
+
+ if(set) {
+ update_reg_32(GAHBCFG,ahbcfg.d32);
+ }
+ else {
+ clear_reg_32(GAHBCFG,ahbcfg.d32);
+ }
+}
+
+int oci_init_mode(struct sec_otghost *otghost)
+{
+ gintsts_t gintsts;
+
+ gintsts.d32 = read_reg_32(GINTSTS);
+
+ otg_dbg(OTG_DBG_OCI,
+ "GINSTS = 0x%x,GINMSK = 0x%x.\n",
+ (unsigned int)gintsts.d32,
+ (unsigned int)read_reg_32(GINTMSK));
+
+ if(gintsts.b.curmode == OTG_HOST_MODE) {
+ otg_dbg(OTG_DBG_OCI, "HOST Mode\n");
+
+ if(oci_host_init(otghost) == USB_ERR_SUCCESS) {
+ return USB_ERR_SUCCESS;
+ }
+ else {
+ otg_dbg(OTG_DBG_OCI, "oci_host_init() Fail\n");
+ return USB_ERR_FAIL;
+ }
+ }
+ else { /* Device Mode */
+ otg_dbg(OTG_DBG_OCI, "DEVICE Mode\n");
+ if(oci_dev_init(otghost) == USB_ERR_SUCCESS) {
+ return USB_ERR_SUCCESS;
+ }
+ else {
+ otg_err(OTG_DBG_OCI, "oci_dev_init() Fail\n");
+ return USB_ERR_FAIL;
+ }
+ }
+
+ return USB_ERR_SUCCESS;
+}
+
+void oci_config_flush_fifo(u32 mode)
+{
+ ghwcfg2_t hwcfg2 = {.d32 = 0};
+
+ otg_dbg(OTG_DBG_OCI, "oci_config_flush_fifo\n");
+
+ hwcfg2.d32 = read_reg_32(GHWCFG2);
+
+ /* Configure data FIFO sizes */
+ if (hwcfg2.b.dynamic_fifo) {
+ /* Rx FIFO */
+ write_reg_32(GRXFSIZ, 0x0000010D);
+
+ /* Non-periodic Tx FIFO */
+ write_reg_32(GNPTXFSIZ, 0x0080010D);
+
+ if (mode == OTG_HOST_MODE) {
+ /* For Periodic transactions, */
+ /* program HPTXFSIZ */
+ }
+ }
+
+ /* Flush the FIFOs */
+ oci_flush_tx_fifo(0);
+
+ oci_flush_rx_fifo();
+}
+
+void oci_flush_tx_fifo(u32 num)
+{
+ grstctl_t greset = {.d32 = 0};
+ u32 count = 0;
+
+ otg_dbg(OTG_DBG_OCI, "oci_flush_tx_fifo\n");
+
+ greset.b.txfflsh = 1;
+ greset.b.txfnum = num;
+ write_reg_32(GRSTCTL, greset.d32);
+
+ /* wait for flush to end */
+ while (greset.b.txfflsh == 1) {
+ greset.d32 = read_reg_32(GRSTCTL);
+ if (++count > MAX_COUNT)
+ break;
+ };
+
+ /* Wait for 3 PHY Clocks*/
+ udelay(30);
+}
+
+void oci_flush_rx_fifo(void)
+{
+ grstctl_t greset = {.d32 = 0};
+ u32 count = 0;
+
+ otg_dbg(OTG_DBG_OCI, "oci_flush_rx_fifo\n");
+
+ greset.b.rxfflsh = 1;
+ write_reg_32(GRSTCTL, greset.d32 );
+
+ do {
+ greset.d32 = read_reg_32(GRSTCTL);
+ if (++count > MAX_COUNT)
+ break;
+ } while (greset.b.rxfflsh == 1);
+
+ /* Wait for 3 PHY Clocks*/
+ udelay(30);
+}
+
+int oci_core_reset(void)
+{
+ u32 count = 0;
+ grstctl_t greset = {.d32 = 0};
+
+ otg_dbg(OTG_DBG_OCI, "oci_core_reset\n");
+
+ /* Wait for AHB master IDLE state. */
+ do {
+ greset.d32 = read_reg_32 (GRSTCTL);
+ mdelay (50);
+
+ if(++count>100) {
+ otg_dbg(OTG_DBG_OCI, "AHB status is not IDLE\n");
+ return USB_ERR_FAIL;
+ }
+ } while (greset.b.ahbidle != 1);
+
+ /* Core Soft Reset */
+ greset.b.csftrst = 1;
+ write_reg_32 (GRSTCTL, greset.d32);
+
+ /* Wait for 3 PHY Clocks*/
+ mdelay (50);
+ return USB_ERR_SUCCESS;
+}
+
+int oci_dev_init(struct sec_otghost *otghost)
+{
+ otg_dbg(OTG_DBG_OCI, "oci_dev_init - do nothing.\n");
+ /* return USB_ERR_FAIL; */
+ return USB_ERR_SUCCESS;
+}
diff --git a/drivers/usb/host/s3c-otg/s3c-otg-oci.h b/drivers/usb/host/s3c-otg/s3c-otg-oci.h
new file mode 100644
index 0000000..03c97e9
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/s3c-otg-oci.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+ * (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+ *
+ * [File Name] :s3c-otg-oci.h
+ * [Description] : The Header file defines the external and internal functions of OCI.
+ * [Author] : Jang Kyu Hyeok { kyuhyeok.jang@samsung.com }
+ * [Department] : System LSI Division/Embedded S/W Platform
+ * [Created Date]: 2008/06/18
+ * [Revision History]
+ * (1) 2008/06/25 by Jang Kyu Hyeok { kyuhyeok.jang@samsung.com }
+ * - Added some functions and data structure of OCI
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ ****************************************************************************/
+
+#ifndef _OCI_H_
+#define _OCI_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+//#include "s3c-otg-common-const.h"
+#include "s3c-otg-common-errorcode.h"
+#include "s3c-otg-common-regdef.h"
+#include "s3c-otg-hcdi-kal.h"
+#include "s3c-otg-hcdi-memory.h"
+#include "s3c-otg-hcdi-debug.h"
+#include "s3c-otg-roothub.h"
+#include "s3c-otg-hcdi-hcd.h"
+
+#include <mach/map.h> //virtual address for smdk
+
+extern void otg_host_phy_init(void);
+#include <mach/regs-clock.h>
+
+//OCI interace
+int oci_init(struct sec_otghost *otghost);
+
+int oci_start(struct sec_otghost *otghost);
+int oci_stop(struct sec_otghost *otghost);
+
+u8 oci_start_transfer(struct sec_otghost *otghost, stransfer_t *st_t);
+int oci_stop_transfer(struct sec_otghost *otghost, u8 ch_num);
+
+int oci_channel_init(u8 ch_num, stransfer_t *st_t);
+u32 oci_get_frame_num(void);
+u16 oci_get_frame_interval(void);
+void oci_set_frame_interval(u16 intervl);
+
+///OCI Internal Functions
+int oci_sys_init(struct sec_otghost *otghost);
+int oci_core_init(struct sec_otghost *otghost);
+int oci_init_mode(struct sec_otghost *otghost);
+int oci_host_init(struct sec_otghost *otghost);
+int oci_dev_init(struct sec_otghost *otghost);
+
+int oci_channel_alloc(u8 *ch_num);
+int oci_channel_dealloc(u8 ch_num);
+
+void oci_config_flush_fifo(u32 mode);
+void oci_flush_tx_fifo(u32 num);
+void oci_flush_rx_fifo(void);
+
+int oci_core_reset(void);
+void oci_set_global_interrupt(bool set);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _OCI_H_ */
diff --git a/drivers/usb/host/s3c-otg/s3c-otg-roothub.c b/drivers/usb/host/s3c-otg/s3c-otg-roothub.c
new file mode 100644
index 0000000..7d9d289
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/s3c-otg-roothub.c
@@ -0,0 +1,605 @@
+/* for* ==========================================================================
+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
+ * otherwise expressly agreed to in writing between Synopsys and you.
+ *
+ * The Software IS NOT an item of Licensed Software or Licensed Product under
+ * any End User Software License Agreement or Agreement for Licensed Product
+ * with Synopsys or any supplement thereto. You are permitted to use and
+ * redistribute this Software in source and binary forms, with or without
+ * modification, provided that redistributions of source code must retain this
+ * notice. You may not view, use, disclose, copy or distribute this file or
+ * any information contained herein except pursuant to this license grant from
+ * Synopsys. If you do not agree with this notice, including the disclaimer
+ * below, then you are not authorized to use the Software.
+ *
+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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.
+ * ========================================================================== */
+/****************************************************************************
+ * (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+ *
+ * [File Name] : RootHub.c
+ * [Description] : The file implement the external and internal functions of RootHub
+ * [Author] : Jang Kyu Hyeok { kyuhyeok.jang@samsung.com }
+ * [Department] : System LSI Division/Embedded S/W Platform
+ * [Created Date]: 2009/02/10
+ * [Revision History]
+ * (1) 2008/06/13 by Jang Kyu Hyeok { kyuhyeok.jang@samsung.com }
+ * - Created this file and implements functions of RootHub
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * 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 "s3c-otg-roothub.h"
+
+static void setPortPower(bool on)
+{
+#ifdef CONFIG_USB_S3C_OTG_HOST_DTGDRVVBUS
+ hprt_t hprt = {.d32 = 0};
+
+ if(on) {
+ hprt.d32 = read_reg_32(HPRT);
+ if(!hprt.b.prtpwr) {
+ /*hprt.d32 = 0;*/
+ hprt.b.prtpwr = 1;
+ write_reg_32(HPRT, hprt.d32);
+ }
+ }
+ else {
+ hprt.b.prtpwr = 1;
+ clear_reg_32(HPRT, hprt.d32);
+ }
+#else
+ otg_dbg(true, "turn %s Vbus\n", on ? "on" : "off");
+#endif
+}
+
+/**
+ * int get_otg_port_status(const u8 port, char* status)
+ *
+ * @brief Get port change bitmap information
+ *
+ * @param [IN] port : port number
+ * [OUT] status : buffer to store bitmap information
+ *
+ * @returnUSB_ERR_SUCCESS : If success \n
+ * USB_ERR_FAIL : If call fail \n
+ *
+ * @remark
+ *
+ */
+__inline__ int get_otg_port_status(
+ struct usb_hcd *hcd, const u8 port, char *status)
+{
+
+ struct sec_otghost *otghost = hcd_to_sec_otghost(hcd);
+ /* return root_hub_feature(port, GetPortStatus, NULL, status); */
+#if 0
+ /* for debug */
+ hprt_t hprt;
+
+ hprt.d32 = read_reg_32(HPRT);
+
+ otg_dbg(OTG_DBG_ROOTHUB,
+ "HPRT:spd=%d,pwr=%d,lnsts=%d,rst=%d,susp=%d,res=%d,ovrcurract=%d,ena=%d,connsts=%d\n",
+ hprt.b.prtspd,
+ hprt.b.prtpwr,
+ hprt.b.prtlnsts,
+ hprt.b.prtrst,
+ hprt.b.prtsusp,
+ hprt.b.prtres,
+ hprt.b.prtovrcurract,
+ hprt.b.prtena,
+ hprt.b.prtconnsts);
+
+#endif
+ status[port] = 0;
+ status[port] |= (otghost->port_flag.b.port_connect_status_change ||
+ otghost->port_flag.b.port_reset_change ||
+ otghost->port_flag.b.port_enable_change ||
+ otghost->port_flag.b.port_suspend_change ||
+ otghost->port_flag.b.port_over_current_change) << 1;
+
+#if 0
+ //* for debug */
+ otg_dbg(OTG_DBG_ROOTHUB,
+ "connect:%d,reset:%d,enable:%d,suspend:%d,over_current:%d\n",
+ otghost->port_flag.b.port_connect_status_change,
+ otghost->port_flag.b.port_reset_change,
+ otghost->port_flag.b.port_enable_change,
+ otghost->port_flag.b.port_suspend_change,
+ otghost->port_flag.b.port_over_current_change);
+#endif
+
+ if (status[port]) {
+ otg_dbg(OTG_DBG_ROOTHUB,
+ " Root port status changed\n");
+ otg_dbg(OTG_DBG_ROOTHUB,
+ " port_connect_status_change: %d\n",
+ otghost->port_flag.b.port_connect_status_change);
+ otg_dbg(OTG_DBG_ROOTHUB,
+ " port_reset_change: %d\n",
+ otghost->port_flag.b.port_reset_change);
+ otg_dbg(OTG_DBG_ROOTHUB,
+ " port_enable_change: %d\n",
+ otghost->port_flag.b.port_enable_change);
+ otg_dbg(OTG_DBG_ROOTHUB,
+ " port_suspend_change: %d\n",
+ otghost->port_flag.b.port_suspend_change);
+ otg_dbg(OTG_DBG_ROOTHUB,
+ " port_over_current_change: %d\n",
+ otghost->port_flag.b.port_over_current_change);
+ }
+
+ return (status[port] !=0);
+}
+
+/**
+ * int reset_and_enable_port(struct usb_hcd *hcd, const u8 port)
+ *
+ * @brief Reset port and make enable status the specific port
+ *
+ * @param [IN] port : port number
+ *
+ * @return USB_ERR_SUCCESS : If success \n
+ * USB_ERR_FAIL : If call fail \n
+ *
+ * @remark
+ *
+ */
+int reset_and_enable_port(struct usb_hcd *hcd, const u8 port)
+{
+ hprt_t hprt;
+ u32 count = 0;
+ u32 max_error_count = 10000;
+ struct sec_otghost *otghost = hcd_to_sec_otghost(hcd);
+
+ hprt.d32 = read_reg_32(HPRT);
+
+ otg_dbg(OTG_DBG_ROOTHUB,
+ " reset_and_enable_port\n");
+
+ if(hprt.b.prtconnsts==0) {
+ otg_dbg(OTG_DBG_ROOTHUB,
+ "No Attached Device, HPRT = 0x%x\n", hprt.d32);
+
+ otghost->port_flag.b.port_connect_status_change = 1;
+ otghost->port_flag.b.port_connect_status = 0;
+
+ return USB_ERR_FAIL;
+ }
+
+ if(!hprt.b.prtena) {
+ hprt.b.prtrst = 1; /* drive reset */
+ write_reg_32(HPRT, hprt.d32);
+
+ mdelay(60);
+ hprt.b.prtrst = 0;
+ write_reg_32(HPRT, hprt.d32);
+
+ do {
+ hprt.d32 = read_reg_32(HPRT);
+
+ if(count > max_error_count) {
+ otg_dbg(OTG_DBG_ROOTHUB,
+ "Port Reset Fail : HPRT : 0x%x\n", hprt.d32);
+ return USB_ERR_FAIL;
+ }
+ count++;
+
+ } while(!hprt.b.prtena);
+
+ }
+ return USB_ERR_SUCCESS;
+}
+
+/**
+ * int root_hub_feature(
+ * struct usb_hcd *hcd,
+ * const u8 port,
+ * const u16 type_req,
+ * const u16 feature,
+ * void* buf)
+ *
+ * @brief Get port change bitmap information
+ *
+ * @param [IN] port : port number
+ * [IN] type_req : request type of hub feature as usb 2.0 spec
+ * [IN] feature : hub feature as usb 2.0 spec
+ * [OUT] status : buffer to store results
+ *
+ * @return USB_ERR_SUCCESS : If success \n
+ * USB_ERR_FAIL : If call fail \n
+ *
+ * @remark
+ *
+ */
+__inline__ int root_hub_feature(
+ struct usb_hcd *hcd,
+ const u8 port,
+ const u16 type_req,
+ const u16 feature,
+ void *buf)
+{
+ int retval = USB_ERR_SUCCESS;
+ usb_hub_descriptor_t *desc = NULL;
+ u32 port_status = 0;
+ hprt_t hprt = {.d32 = 0};
+ struct sec_otghost *otghost = hcd_to_sec_otghost(hcd);
+
+ otg_dbg(OTG_DBG_ROOTHUB, " root_hub_feature\n");
+
+ switch (type_req) {
+ case ClearHubFeature:
+ otg_dbg(OTG_DBG_ROOTHUB, "case ClearHubFeature\n");
+ switch (feature) {
+ case C_HUB_LOCAL_POWER:
+ otg_dbg(OTG_DBG_ROOTHUB,
+ "case ClearHubFeature -C_HUB_LOCAL_POWER\n");
+ break;
+ case C_HUB_OVER_CURRENT:
+ otg_dbg(OTG_DBG_ROOTHUB,
+ "case ClearHubFeature -C_HUB_OVER_CURRENT\n");
+ /* Nothing required here */
+ break;
+ default:
+ retval = USB_ERR_FAIL;
+ }
+ break;
+
+ case ClearPortFeature:
+ otg_dbg(OTG_DBG_ROOTHUB, "case ClearPortFeature\n");
+ switch (feature) {
+ case USB_PORT_FEAT_ENABLE:
+ otg_dbg(OTG_DBG_ROOTHUB,
+ "case ClearPortFeature -USB_PORT_FEAT_ENABLE\n");
+ hprt.b.prtena = 1;
+ update_reg_32(HPRT, hprt.d32);
+ break;
+
+ case USB_PORT_FEAT_SUSPEND:
+ otg_dbg(OTG_DBG_ROOTHUB,
+ "case ClearPortFeature -USB_PORT_FEAT_SUSPEND\n");
+ bus_resume(otghost);
+ break;
+
+ case USB_PORT_FEAT_POWER:
+ otg_dbg(OTG_DBG_ROOTHUB,
+ "case ClearPortFeature -USB_PORT_FEAT_POWER\n");
+ setPortPower(false);
+ break;
+
+ case USB_PORT_FEAT_INDICATOR:
+ otg_dbg(OTG_DBG_ROOTHUB,
+ "case ClearPortFeature -USB_PORT_FEAT_INDICATOR\n");
+ /* Port inidicator not supported */
+ break;
+
+ case USB_PORT_FEAT_C_CONNECTION:
+ otg_dbg(OTG_DBG_ROOTHUB,
+ "case ClearPortFeature -USB_PORT_FEAT_C_CONNECTION\n");
+ /* Clears drivers internal connect status change flag */
+ otghost->port_flag.b.port_connect_status_change = 0;
+ break;
+
+ case USB_PORT_FEAT_C_RESET:
+ otg_dbg(OTG_DBG_ROOTHUB,
+ "case ClearPortFeature -USB_PORT_FEAT_C_RESET\n");
+ /* Clears the driver's internal Port Reset Change flag*/
+ otghost->port_flag.b.port_reset_change = 0;
+ break;
+
+ case USB_PORT_FEAT_C_ENABLE:
+ otg_dbg(OTG_DBG_ROOTHUB,
+ "case ClearPortFeature -USB_PORT_FEAT_C_ENABLE\n");
+ /* Clears the driver's internal Port Enable/Disable Change flag */
+ otghost->port_flag.b.port_enable_change = 0;
+ break;
+
+ case USB_PORT_FEAT_C_SUSPEND:
+ otg_dbg(OTG_DBG_ROOTHUB,
+ "case ClearPortFeature -USB_PORT_FEAT_C_SUSPEND\n");
+ /* Clears the driver's internal Port Suspend
+ * Change flag, which is set when resume signaling on
+ * the host port is complete */
+ otghost->port_flag.b.port_suspend_change = 0;
+ break;
+
+ case USB_PORT_FEAT_C_OVER_CURRENT:
+ otg_dbg(OTG_DBG_ROOTHUB, "case ClearPortFeature - \
+ USB_PORT_FEAT_C_OVER_CURRENT\n");
+ otghost->port_flag.b.port_over_current_change = 0;
+ break;
+
+ default:
+ retval = USB_ERR_FAIL;
+ otg_dbg(OTG_DBG_ROOTHUB,
+ "case ClearPortFeature - FAIL\n");
+ }
+ break;
+
+ case GetHubDescriptor:
+ otg_dbg(OTG_DBG_ROOTHUB, "case GetHubDescriptor\n");
+ desc = (usb_hub_descriptor_t *)buf;
+ desc->desc_length = 9;
+ desc->desc_type = 0x29;
+ desc->port_number = 1;
+ desc->hub_characteristics = 0x08;
+ desc->power_on_to_power_good = 1;
+ desc->hub_control_current = 0;
+ desc->DeviceRemovable[0] = 0;
+ desc->DeviceRemovable[1] = 0xff;
+ break;
+
+ case GetHubStatus:
+ otg_dbg(OTG_DBG_ROOTHUB, "case GetHubStatus\n");
+ otg_mem_set(buf, 0, 4);
+ break;
+
+ case GetPortStatus:
+ otg_dbg(OTG_DBG_ROOTHUB, "case GetPortStatus\n");
+
+ if (otghost->port_flag.b.port_connect_status_change) {
+ port_status |= (1 << USB_PORT_FEAT_C_CONNECTION);
+ otg_dbg(OTG_DBG_ROOTHUB,
+ "case GetPortStatus - USB_PORT_FEAT_C_CONNECTION\n");
+ }
+
+ if (otghost->port_flag.b.port_enable_change) {
+ port_status |= (1 << USB_PORT_FEAT_C_ENABLE);
+ otg_dbg(OTG_DBG_ROOTHUB,
+ "case GetPortStatus - USB_PORT_FEAT_C_ENABLE\n");
+ }
+
+ if (otghost->port_flag.b.port_suspend_change) {
+ port_status |= (1 << USB_PORT_FEAT_C_SUSPEND);
+ otg_dbg(OTG_DBG_ROOTHUB,
+ "case GetPortStatus - USB_PORT_FEAT_C_SUSPEND\n");
+ }
+
+ if (otghost->port_flag.b.port_reset_change) {
+ port_status|= (1 << USB_PORT_FEAT_C_RESET);
+ otg_dbg(OTG_DBG_ROOTHUB,
+ "case GetPortStatus - USB_PORT_FEAT_C_RESET\n");
+ }
+
+ if (otghost->port_flag.b.port_over_current_change) {
+ port_status |= (1 << USB_PORT_FEAT_C_OVER_CURRENT);
+ otg_dbg(OTG_DBG_ROOTHUB,
+ "case GetPortStatus - USB_PORT_FEAT_C_OVER_CURRENT\n");
+ }
+
+ if (!otghost->port_flag.b.port_connect_status) {
+ /*
+ * The port is disconnected, which means the core is
+ * either in device mode or it soon will be. Just
+ * return 0's for the remainder of the port status
+ * since the port register can't be read if the core
+ * is in device mode.
+ */
+ otg_dbg(OTG_DBG_ROOTHUB,
+ "case GetPortStatus - disconnected\n");
+
+ *((__le32*)buf) = cpu_to_le32(port_status);
+ /*break;*/
+ }
+
+ hprt.d32 = read_reg_32(HPRT);
+
+ if (hprt.b.prtconnsts)
+ port_status|= (1 << USB_PORT_FEAT_CONNECTION);
+
+ if (hprt.b.prtena)
+ port_status |= (1 << USB_PORT_FEAT_ENABLE);
+
+ if (hprt.b.prtsusp)
+ port_status |= (1 << USB_PORT_FEAT_SUSPEND);
+
+ if (hprt.b.prtovrcurract)
+ port_status |= (1 << USB_PORT_FEAT_OVER_CURRENT);
+
+ if (hprt.b.prtrst)
+ port_status |= (1 << USB_PORT_FEAT_RESET);
+
+ if (hprt.b.prtpwr)
+ port_status |= (1 << USB_PORT_FEAT_POWER);
+
+ if (hprt.b.prtspd == 0) {
+ port_status |= USB_PORT_STAT_HIGH_SPEED;
+ }
+ else {
+ if (hprt.b.prtspd == 2)
+ port_status |= USB_PORT_STAT_LOW_SPEED;
+ }
+
+ if (hprt.b.prttstctl)
+ port_status |= (1 << USB_PORT_FEAT_TEST);
+
+ *((__le32*)buf) = cpu_to_le32(port_status);
+
+ otg_dbg(OTG_DBG_ROOTHUB, "port_status=0x%x.\n", port_status);
+ break;
+
+ case SetHubFeature:
+ otg_dbg(OTG_DBG_ROOTHUB, "case SetHubFeature\n");
+ /* No HUB features supported */
+ break;
+
+ case SetPortFeature:
+ otg_dbg(OTG_DBG_ROOTHUB, "case SetPortFeature\n");
+ if (!otghost->port_flag.b.port_connect_status) {
+ /*
+ * The port is disconnected, which means the core is
+ * either in device mode or it soon will be. Just
+ * return without doing anything since the port
+ * register can't be written if the core is in device
+ * mode.
+ */
+ otg_dbg(OTG_DBG_ROOTHUB,
+ "case SetPortFeature - disconnected\n");
+
+ /*break;*/
+ }
+
+ switch (feature) {
+ case USB_PORT_FEAT_SUSPEND:
+ otg_dbg(true,
+ "case SetPortFeature -USB_PORT_FEAT_SUSPEND\n");
+ bus_suspend();
+ break;
+
+ case USB_PORT_FEAT_POWER:
+ otg_dbg(true,
+ "case SetPortFeature -USB_PORT_FEAT_POWER\n");
+ setPortPower(true);
+ break;
+
+ case USB_PORT_FEAT_RESET:
+ otg_dbg(true,
+ "case SetPortFeature -USB_PORT_FEAT_RESET\n");
+ retval = reset_and_enable_port(hcd, port);
+ /*
+ if(retval == USB_ERR_SUCCESS)
+ wake_lock(&otghost->wake_lock);
+ */
+ break;
+
+ case USB_PORT_FEAT_INDICATOR:
+ otg_dbg(true,
+ "case SetPortFeature -USB_PORT_FEAT_INDICATOR\n");
+ break;
+
+ default :
+ otg_dbg(true, "case SetPortFeature -USB_ERR_FAIL\n");
+ retval = USB_ERR_FAIL;
+ break;
+ }
+ break;
+
+ default:
+ retval = USB_ERR_FAIL;
+ otg_err(true, "root_hub_feature() Function Error\n");
+ break;
+ }
+
+ if(retval != USB_ERR_SUCCESS)
+ retval = USB_ERR_FAIL;
+
+ return retval;
+}
+
+/**
+ * void bus_suspend(void)
+ *
+ * @brief Make suspend status when this platform support PM Mode
+ *
+ * @param None
+ *
+ * @return None
+ *
+ * @remark
+ *
+ */
+void bus_suspend(void)
+{
+ hprt_t hprt;
+ pcgcctl_t pcgcctl;
+
+ otg_dbg(OTG_DBG_ROOTHUB, " bus_suspend\n");
+
+ hprt.d32 = 0;
+ pcgcctl.d32 = 0;
+
+ hprt.b.prtsusp = 1;
+ update_reg_32(HPRT, hprt.d32);
+
+ pcgcctl.b.pwrclmp = 1;
+ update_reg_32(PCGCCTL,pcgcctl.d32);
+ udelay(1);
+
+ pcgcctl.b.rstpdwnmodule = 1;
+ update_reg_32(PCGCCTL,pcgcctl.d32);
+ udelay(1);
+
+ pcgcctl.b.stoppclk = 1;
+ update_reg_32(PCGCCTL,pcgcctl.d32);
+ udelay(1);
+}
+
+/**
+ * int bus_resume(struct sec_otghost *otghost)
+ *
+ * @brief Make resume status when this platform support PM Mode
+ *
+ * @param None
+ *
+ * @return USB_ERR_SUCCESS : If success \n
+ * USB_ERR_FAIL : If call fail \n
+ *
+ * @remark
+ *
+ */
+int bus_resume(struct sec_otghost *otghost)
+{
+ /*
+ hprt_t hprt;
+ pcgcctl_t pcgcctl;
+ hprt.d32 = 0;
+ pcgcctl.d32 = 0;
+
+ pcgcctl.b.stoppclk = 1;
+ clear_reg_32(PCGCCTL,pcgcctl.d32);
+ udelay(1);
+
+ pcgcctl.b.pwrclmp = 1;
+ clear_reg_32(PCGCCTL,pcgcctl.d32);
+ udelay(1);
+
+ pcgcctl.b.rstpdwnmodule = 1;
+ clear_reg_32(PCGCCTL,pcgcctl.d32);
+ udelay(1);
+
+ hprt.b.prtres = 1;
+ update_reg_32(HPRT, hprt.d32);
+ mdelay(20);
+
+ clear_reg_32(HPRT, hprt.d32);
+ */
+ otg_dbg(OTG_DBG_ROOTHUB, "bus_resume()......\n");
+
+ otg_dbg(OTG_DBG_ROOTHUB, "wait for 50 ms...\n");
+
+ mdelay(50);
+ if(oci_init(otghost) == USB_ERR_SUCCESS) {
+ if(oci_start(otghost) == USB_ERR_SUCCESS) {
+ otg_dbg(OTG_DBG_ROOTHUB, "OTG Init Success\n");
+ return USB_ERR_SUCCESS;
+ }
+ }
+
+ return USB_ERR_FAIL;
+}
diff --git a/drivers/usb/host/s3c-otg/s3c-otg-roothub.h b/drivers/usb/host/s3c-otg/s3c-otg-roothub.h
new file mode 100644
index 0000000..03883d1
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/s3c-otg-roothub.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+ * (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+ *
+ * [File Name] :s3c-otg-roothub.h
+ * [Description] : The Header file defines the external and internal functions of RootHub.
+ * [Author] : Jang Kyu Hyeok { kyuhyeok.jang@samsung.com }
+ * [Department] : System LSI Division/Embedded S/W Platform
+ * [Created Date]: 2008/06/13
+ * [Revision History]
+ * (1) 2008/06/13 by Jang Kyu Hyeok { kyuhyeok.jang@samsung.com }
+ * - Created this file and defines functions of RootHub
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ ****************************************************************************/
+
+#ifndef _ROOTHUB_H_
+#define _ROOTHUB_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "s3c-otg-common-errorcode.h"
+#include "s3c-otg-common-regdef.h"
+#include "s3c-otg-common-datastruct.h"
+#include "s3c-otg-hcdi-kal.h"
+#include "s3c-otg-hcdi-memory.h"
+#include "s3c-otg-oci.h"
+
+__inline__ int root_hub_feature(
+ struct usb_hcd *hcd,
+ const u8 port,
+ const u16 type_req,
+ const u16 feature,
+ void *buf);
+
+__inline__ int get_otg_port_status(
+ struct usb_hcd *hcd, const u8 port, char *status);
+
+int reset_and_enable_port(struct usb_hcd *hcd, const u8 port);
+void bus_suspend(void);
+
+int bus_resume(struct sec_otghost *otghost);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _ROOTHUB_H_ */
+
+
diff --git a/drivers/usb/host/s3c-otg/s3c-otg-scheduler-ischeduler.c b/drivers/usb/host/s3c-otg/s3c-otg-scheduler-ischeduler.c
new file mode 100644
index 0000000..d94fb1a
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/s3c-otg-scheduler-ischeduler.c
@@ -0,0 +1,369 @@
+/****************************************************************************
+ * (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+ *
+ * [File Name] : Scheduler.c
+ * [Description] : The source file implements the internal functions of Scheduler.
+ * [Author] : Yang Soon Yeal { syatom.yang@samsung.com }
+ * [Department] : System LSI Division/System SW Lab
+ * [Created Date]: 2009/2/10
+ * [Revision History]
+ * (1) 2008/06/03 by Yang Soon Yeal { syatom.yang@samsung.com }
+ * - Created this file and implements functions of Scheduler
+ * -# Jul 15,2008 v1.2 by SeungSoo Yang (ss1.yang@samsung.com) \n
+ * : Optimizing for performance \n
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * 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 "s3c-otg-scheduler-scheduler.h"
+
+void init_scheduler(void)
+{
+ /*init_scheduling();*/
+ init_transfer_ready_q();
+}
+
+/******************************************************************************/
+/*!
+ * @name int reserve_used_resource_for_periodic(u32 usb_time)
+ *
+ * @brief this function reserves the necessary resource of USB Transfer for Periodic Transfer.
+ * So, this function firstly checks there ares some available USB Time
+ * and Channel resource for USB Transfer.
+ * if there exists necessary resources for Periodic Transfer, then reserves the resource.
+ *
+ * @param [IN] usb_time = indicates the USB Time for the USB Transfer.
+ *
+ * @return USB_ERR_SUCCESS - if success to insert pInsertED to S3CScheduler.
+ * USB_ERR_NO_BANDWIDTH - if fail to reserve the USB Bandwidth.
+ * USB_ERR_NO_CHANNEL - if fail to reserve the Channel.
+ */
+/******************************************************************************/
+
+int reserve_used_resource_for_periodic(u32 usb_time, u8 dev_speed, u8 trans_type)
+{
+ if(inc_perio_bus_time(usb_time,dev_speed)==USB_ERR_SUCCESS) {
+ if(inc_perio_chnum()==USB_ERR_SUCCESS) {
+ otg_usbcore_inc_usb_bandwidth(usb_time);
+ otg_usbcore_inc_periodic_transfer_cnt(trans_type);
+ return USB_ERR_SUCCESS;
+ }
+ else {
+ dec_perio_bus_time(usb_time);
+ return USB_ERR_NO_CHANNEL;
+ }
+ }
+ else {
+ return USB_ERR_NO_BANDWIDTH;
+ }
+}
+
+/******************************************************************************/
+/*!
+ * @name int free_usb_resource_for_periodic(ed_t * pFreeED)
+ *
+ * @brief this function frees the resources to be allocated to pFreeED at S3CScheduler.
+ * that is, this functions only releases the resources to be allocated by S3C6400Scheduler.
+ *
+ * @param [IN] pFreeED = indicates ed_t to have the information of the resource to be released.
+ *
+ * @return USB_ERR_SUCCESS - if success to free the USB Resource.
+ * USB_ERR_FAIL - if fail to free the USB Resrouce.
+ */
+/******************************************************************************/
+int free_usb_resource_for_periodic(
+ u32 free_usb_time, u8 free_chnum, u8 trans_type)
+{
+ if(dec_perio_bus_time(free_usb_time)==USB_ERR_SUCCESS) {
+ if(dec_perio_chnum()==USB_ERR_SUCCESS) {
+ if(free_chnum!=CH_NONE) {
+ oci_channel_dealloc(free_chnum);
+ set_transferring_td_array(free_chnum, 0);
+ }
+ otg_usbcore_des_usb_bandwidth(free_usb_time);
+ otg_usbcore_des_periodic_transfer_cnt(trans_type);
+ return USB_ERR_SUCCESS;
+ }
+ }
+ return USB_ERR_FAIL;
+}
+
+/******************************************************************************/
+/*!
+ * @name int remove_ed_from_scheduler(ed_t * remove_ed)
+ *
+ * @brief this function just remove the remove_ed from TransferReadyQ. So if you want to
+ * stop the USB Tranfer of remove_ed or release the releated resources.
+ * you should call another functions of S3CScheduler.
+ *
+ * @param [IN] remove_ed = indicates ed_t to be removed from TransferReadyQ.
+ *
+ * @return USB_ERR_SUCCESS - if success to remove the remove_ed from TransferReadyQ.
+ * USB_ERR_FAIL - if fail to remove the remove_ed from TransferReadyQ.
+ */
+ /******************************************************************************/
+int remove_ed_from_scheduler(ed_t *remove_ed)
+{
+ if(remove_ed->ed_status.is_in_transfer_ready_q) {
+ remove_ed_from_ready_q(remove_ed);
+ remove_ed->ed_status.is_in_transfer_ready_q = false;
+
+ return USB_ERR_SUCCESS;
+ }
+ else {
+ return USB_ERR_FAIL;
+ }
+}
+
+/******************************************************************************/
+/*!
+ * @name int cancel_to_transfer_td(struct sec_otghost *otghost, td_t *cancel_td)
+ *
+ * @brief this function stop to execute the USB Transfer of cancel_td and
+ * release the Channel Resources to be allocated the cancel_td ,if the Transfer Type of
+ * cancel_td is NonPeriodic Transfer.
+ * this function don't release any usb resources(Channel, USB Bandwidth) for Periodic Transfer.
+ * if you want to release some usb resources for a periodic Transfer, you should call
+ * the free_usb_resource_for_periodic()
+ *
+ * @param [IN] cancel_td = indicates the td_t to be canceled.
+ *
+ * @return USB_ERR_SUCCESS - if success to cancel the USB Transfer of cancel_td.
+ * USB_ERR_FAIL - if fail to cancel the USB Transfer of cancel_td.
+ */
+ /******************************************************************************/
+int cancel_to_transfer_td(struct sec_otghost *otghost, td_t *cancel_td)
+{
+ if(cancel_td->is_transfer_done) {
+ return USB_ERR_FAIL;
+ }
+
+ if(cancel_td->is_transferring) {
+ int err;
+
+ err = oci_stop_transfer(otghost, cancel_td->cur_stransfer.alloc_chnum);
+
+ if(err == USB_ERR_SUCCESS) {
+ set_transferring_td_array(cancel_td->cur_stransfer.alloc_chnum,0);
+
+ cancel_td->cur_stransfer.alloc_chnum = CH_NONE;
+ cancel_td->is_transferring = false;
+ cancel_td->parent_ed_p->ed_status.is_in_transferring = false;
+ cancel_td->parent_ed_p->ed_status.in_transferring_td = 0;
+ cancel_td->parent_ed_p->is_need_to_insert_scheduler = true;
+
+ if(cancel_td->cur_stransfer.ed_desc_p->endpoint_type == BULK_TRANSFER ||
+ cancel_td->cur_stransfer.ed_desc_p->endpoint_type == CONTROL_TRANSFER ) {
+ dec_nonperio_chnum();
+ }
+ return err;
+ }
+ else {
+ return err;
+ }
+ }
+ else {
+ return USB_ERR_FAIL;
+ }
+ return USB_ERR_SUCCESS;
+}
+
+
+/******************************************************************************/
+/*!
+ * @name int retransmit(struct sec_otghost *otghost, td_t *retrasmit_td)
+ *
+ * @brief this function retransmits the retrasmit_td immediately.
+ * So, the Channel of pRetransmitted is reused for retransmittion.
+ *
+ * @param [IN] retrasmit_td = indicates the pointer ot the td_t to be retransmitted.
+ *
+ * @return USB_ERR_SUCCESS - if success to retransmit the retrasmit_td.
+ * USB_ERR_FAIL - if fail to retransmit the retrasmit_td.
+ */
+ /******************************************************************************/
+int retransmit(struct sec_otghost *otghost, td_t *retrasmit_td)
+{
+ u32 td_addr=0;
+
+ if(get_transferring_td_array(retrasmit_td->cur_stransfer.alloc_chnum,&td_addr)==USB_ERR_SUCCESS) {
+ if(td_addr == (u32)retrasmit_td) {
+ if(oci_start_transfer(otghost, &retrasmit_td->cur_stransfer)
+ == retrasmit_td->cur_stransfer.alloc_chnum) {
+ retrasmit_td->is_transferring = true;
+ retrasmit_td->parent_ed_p->ed_status.in_transferring_td = (u32)retrasmit_td;
+ retrasmit_td->parent_ed_p->ed_status.is_in_transfer_ready_q = false;
+ retrasmit_td->parent_ed_p->ed_status.is_in_transferring = true;
+ }
+ }
+ else {
+ return USB_ERR_FAIL;
+ }
+ }
+ else {
+ return USB_ERR_FAIL;
+ }
+
+ return USB_ERR_SUCCESS;
+
+}
+
+/******************************************************************************/
+/*!
+ * @name int reschedule(td_t *reschedule_td)
+ *
+ * @brief this function re-schedules the reschedule_td.
+ * So, the Channel of pRescheuleTD is released and reschedule_td is inserted to TransferReadyQ.
+ *
+ * @param [IN] reschedule_td = indicates the pointer ot the td_t to be rescheduled.
+ *
+ * @return USB_ERR_SUCCESS - if success to re-schedule the reschedule_td.
+ * USB_ERR_FAIL - if fail to re-schedule the reschedule_td.
+ */
+ /******************************************************************************/
+int reschedule(td_t *reschedule_td)
+{
+ u32 td_addr;
+
+ if(get_transferring_td_array(reschedule_td->cur_stransfer.alloc_chnum, &td_addr)==USB_ERR_SUCCESS)
+ {
+ if((u32)reschedule_td == td_addr)
+ {
+ set_transferring_td_array(reschedule_td->cur_stransfer.alloc_chnum, 0);
+ oci_channel_dealloc(reschedule_td->cur_stransfer.alloc_chnum);
+
+ reschedule_td->cur_stransfer.alloc_chnum = CH_NONE;
+ reschedule_td->parent_ed_p->is_need_to_insert_scheduler = true;
+ reschedule_td->parent_ed_p->ed_status.in_transferring_td = 0;
+
+ if(reschedule_td->parent_ed_p->ed_desc.endpoint_type == BULK_TRANSFER||
+ reschedule_td->parent_ed_p->ed_desc.endpoint_type == CONTROL_TRANSFER )
+ {
+ /* Increase the available Channel */
+ dec_nonperio_chnum();
+
+ }
+
+ insert_ed_to_ready_q(reschedule_td->parent_ed_p, false);
+ reschedule_td->parent_ed_p->ed_status.is_in_transfer_ready_q =true;
+
+ }
+ else
+ {
+ /* this case is not support.... */
+ }
+ }
+
+ return USB_ERR_SUCCESS;
+}
+
+/******************************************************************************/
+/*!
+ * @name int deallocate(td_t *deallocate_td)
+ *
+ * @brief this function frees resources to be allocated deallocate_td by S3CScheduler.
+ * this function just free the resource by S3CScheduler. that is, Channel Resource.
+ * if there are another td_t at ed_t, deallocate() insert the ed_t to TransferReadyQ.
+ *
+ * @param [IN] deallocate_td = indicates the pointer ot the td_t to be deallocated.
+ *
+ * @return USB_ERR_SUCCESS - if success to dealloate the resources for the deallocate_td.
+ * USB_ERR_FAIL - if fail to dealloate the resources for the deallocate_td.
+ */
+ /******************************************************************************/
+int deallocate(td_t *deallocate_td)
+{
+ u32 td_addr;
+
+ if(get_transferring_td_array(deallocate_td->cur_stransfer.alloc_chnum , &td_addr)==USB_ERR_SUCCESS)
+ {
+ if((u32)deallocate_td == td_addr)
+ {
+ set_transferring_td_array(deallocate_td->cur_stransfer.alloc_chnum, 0);
+ oci_channel_dealloc(deallocate_td->cur_stransfer.alloc_chnum);
+
+ deallocate_td->cur_stransfer.alloc_chnum = CH_NONE;
+
+ if(deallocate_td->parent_ed_p->ed_desc.endpoint_type == BULK_TRANSFER||
+ deallocate_td->parent_ed_p->ed_desc.endpoint_type == CONTROL_TRANSFER )
+ {
+ /* Increase the available Channel */
+ dec_nonperio_chnum();
+ }
+
+ deallocate_td->parent_ed_p->is_need_to_insert_scheduler = true;
+
+ if(deallocate_td->parent_ed_p->num_td)
+ {
+ /* insert ed_t to TransferReadyQ. */
+ insert_ed_to_ready_q(deallocate_td->parent_ed_p , false);
+ deallocate_td->parent_ed_p->ed_status.is_in_transfer_ready_q = true;
+ deallocate_td->parent_ed_p->is_need_to_insert_scheduler = false;
+ }
+ return USB_ERR_SUCCESS;
+ }
+ else
+ {
+ return USB_ERR_FAIL;
+ }
+ }
+ else
+ {
+ return USB_ERR_FAIL;
+ }
+
+}
+
+/* TBD.... */
+void do_schedule(struct sec_otghost *otghost)
+{
+ if(get_avail_chnum()) {
+ do_periodic_schedule(otghost);
+ do_nonperiodic_schedule(otghost);
+ }
+}
+
+/******************************************************************************/
+/*!
+ * @name int get_td_info(u8 chnum,
+ * unsigned int *td_addr_p)
+ *
+ * @brief this function returns the pointer of td_t at TransferringTDArray[chnum]
+ *
+ * @param [IN] chnum = indicates the index of TransferringTDArray
+ * to include the address of td_t which we gets
+ * [OUT] td_addr_p= indicate pointer to store the address of td_t.
+ *
+ * @return USB_ERR_SUCCESS -if success to get the address of td_t.
+ * USB_ERR_FAIL -if fail to get the address of td_t.
+ */
+ /******************************************************************************/
+int get_td_info( u8 chnum,
+ unsigned int *td_addr_p)
+{
+ u32 td_addr;
+
+ if(get_transferring_td_array(chnum, &td_addr)==USB_ERR_SUCCESS)
+ {
+ *td_addr_p = td_addr;
+ return USB_ERR_SUCCESS;
+ }
+
+ return USB_ERR_FAIL;
+}
+
+
diff --git a/drivers/usb/host/s3c-otg/s3c-otg-scheduler-readyq.c b/drivers/usb/host/s3c-otg/s3c-otg-scheduler-readyq.c
new file mode 100644
index 0000000..7b41f0c
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/s3c-otg-scheduler-readyq.c
@@ -0,0 +1,264 @@
+/****************************************************************************
+ * (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+ *
+ * [File Name] : TransferReadyQ.c
+ * [Description] : The source file implements the internal functions of TransferReadyQ.
+ * [Author] : Yang Soon Yeal { syatom.yang@samsung.com }
+ * [Department] : System LSI Division/System SW Lab
+ * [Created Date]: 2008/06/04
+ * [Revision History]
+ * (1) 2008/06/04 by Yang Soon Yeal { syatom.yang@samsung.com }
+ * - Created this file and implements functions of TransferReadyQ.
+ * -# Jul 15,2008 v1.2 by SeungSoo Yang (ss1.yang@samsung.com) \n
+ * : Optimizing for performance \n
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * 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 "s3c-otg-scheduler-scheduler.h"
+
+static trans_ready_q_t periodic_trans_ready_q;
+static trans_ready_q_t nonperiodic_trans_ready_q;
+
+/******************************************************************************/
+/*!
+ * @name void init_transfer_ready_q(void)
+ *
+ * @brief this function initiates PeriodicTransferReadyQ and NonPeriodicTransferReadyQ.
+ *
+ *
+ * @param void
+ *
+ * @return void.
+ */
+/******************************************************************************/
+void init_transfer_ready_q(void)
+{
+ otg_dbg(OTG_DBG_SCHEDULE,"start init_transfer_ready_q\n");
+
+ otg_list_init(&periodic_trans_ready_q.trans_ready_q_list_head);
+ periodic_trans_ready_q.is_periodic_transfer = true;
+ periodic_trans_ready_q.trans_ready_entry_num = 0;
+ periodic_trans_ready_q.total_alloc_chnum = 0;
+ periodic_trans_ready_q.total_perio_bus_bandwidth = 0;
+
+ otg_list_init(&nonperiodic_trans_ready_q.trans_ready_q_list_head);
+ nonperiodic_trans_ready_q.is_periodic_transfer = false;
+ nonperiodic_trans_ready_q.trans_ready_entry_num = 0;
+ nonperiodic_trans_ready_q.total_alloc_chnum = 0;
+ nonperiodic_trans_ready_q.total_perio_bus_bandwidth = 0;
+
+
+}
+
+
+/******************************************************************************/
+/*!
+ * @name int insert_ed_to_ready_q(ed_t *insert_ed,
+ * bool f_isfirst)
+ *
+ * @brief this function inserts ed_t * to TransferReadyQ.
+ *
+ *
+ * @param [IN] insert_ed = indicates the ed_t to be inserted to TransferReadyQ.
+ * [IN] f_isfirst = indicates whether the insert_ed is inserted as first entry of TransferReadyQ.
+ *
+ * @return USB_ERR_SUCCESS -if successes to insert the insert_ed to TransferReadyQ.
+ * USB_ERR_FAILl -if fails to insert the insert_ed to TransferReadyQ.
+ */
+/******************************************************************************/
+int insert_ed_to_ready_q(ed_t *insert_ed,
+ bool f_isfirst)
+{
+
+ if(insert_ed->ed_desc.endpoint_type == BULK_TRANSFER||
+ insert_ed->ed_desc.endpoint_type == CONTROL_TRANSFER)
+ {
+ if(f_isfirst)
+ {
+ otg_list_push_next(&insert_ed->trans_ready_q_list_entry,&nonperiodic_trans_ready_q.trans_ready_q_list_head);
+ }
+ else
+ {
+ otg_list_push_prev(&insert_ed->trans_ready_q_list_entry,&nonperiodic_trans_ready_q.trans_ready_q_list_head);
+ }
+ nonperiodic_trans_ready_q.trans_ready_entry_num++;
+ }
+ else
+ {
+ if(f_isfirst)
+ {
+ otg_list_push_next(&insert_ed->trans_ready_q_list_entry,&periodic_trans_ready_q.trans_ready_q_list_head);
+ }
+ else
+ {
+ otg_list_push_prev(&insert_ed->trans_ready_q_list_entry,&periodic_trans_ready_q.trans_ready_q_list_head);
+ }
+ periodic_trans_ready_q.trans_ready_entry_num++;
+ }
+
+ return USB_ERR_SUCCESS;
+
+}
+
+
+u32 get_periodic_ready_q_entity_num(void)
+{
+ return periodic_trans_ready_q.trans_ready_entry_num;
+}
+/******************************************************************************/
+/*!
+ * @name int remove_ed_from_ready_q(ed_t *remove_ed)
+ *
+ * @brief this function removes ed_t * from TransferReadyQ.
+ *
+ *
+ * @param [IN] remove_ed = indicate the ed_t to be removed from TransferReadyQ.
+ *
+ * @return USB_ERR_SUCCESS -if successes to remove the remove_ed from TransferReadyQ.
+ * USB_ERR_FAILl -if fails to remove the remove_ed from TransferReadyQ.
+ */
+/******************************************************************************/
+int remove_ed_from_ready_q(ed_t *remove_ed)
+{
+// SPINLOCK_t SLForRemoveED_t = SPIN_LOCK_INIT;
+// u32 uiSLFlag=0;
+
+ otg_list_pop(&remove_ed->trans_ready_q_list_entry);
+
+ if(remove_ed->ed_desc.endpoint_type == BULK_TRANSFER||
+ remove_ed->ed_desc.endpoint_type == CONTROL_TRANSFER)
+ {
+// spin_lock_irq_save_otg(&SLForRemoveED_t, uiSLFlag);
+// otg_list_pop(&remove_ed->trans_ready_q_list_entry);
+ nonperiodic_trans_ready_q.trans_ready_entry_num--;
+// spin_unlock_irq_save_otg(&SLForRemoveED_t, uiSLFlag);
+ }
+ else
+ {
+// spin_lock_irq_save_otg(&SLForRemoveED_t, uiSLFlag);
+// otg_list_pop(&remove_ed->trans_ready_q_list_entry);
+ periodic_trans_ready_q.trans_ready_entry_num--;
+// spin_unlock_irq_save_otg(&SLForRemoveED_t, uiSLFlag);
+ }
+
+ return USB_ERR_SUCCESS;
+
+}
+
+//by ss1 unused func
+/*
+bool check_ed_on_ready_q(ed_t *check_ed_p)
+{
+
+ if(check_ed_p->ed_status.is_in_transfer_ready_q)
+ return true;
+ else
+ return false;
+}*/
+
+/******************************************************************************/
+/*!
+ * @name int get_ed_from_ready_q(bool f_isperiodic,
+ * td_t **get_ed)
+ *
+ * @brief this function returns the first entity of TransferReadyQ.
+ * if there are some ed_t on TransferReadyQ, this function pops first ed_t from TransferReadyQ.
+ * So, the TransferReadyQ don's has the poped ed_t.
+ *
+ *
+ * @param [IN] f_isperiodic = indicate whether Periodic or not
+ * [OUT] get_ed = indicate the double pointer to store the address of first entity
+ * on TransferReadyQ.
+ *
+ * @return USB_ERR_SUCCESS -if successes to get frist ed_t from TransferReadyQ.
+ * USB_ERR_NO_ENTITY -if fails to get frist ed_t from TransferReadyQ
+ * because there is no entity on TransferReadyQ.
+ */
+/******************************************************************************/
+
+int get_ed_from_ready_q(bool f_isperiodic,
+ ed_t **get_ed)
+{
+ if(f_isperiodic)
+ {
+ otg_list_head *transreadyq_list_entity=NULL;
+
+ if(periodic_trans_ready_q.trans_ready_entry_num==0)
+ {
+ return USB_ERR_NO_ENTITY;
+ }
+
+ transreadyq_list_entity = periodic_trans_ready_q.trans_ready_q_list_head.next;
+
+ //if(transreadyq_list_entity!= &periodic_trans_ready_q.trans_ready_q_list_head)
+ if(!otg_list_empty(&periodic_trans_ready_q.trans_ready_q_list_head))
+ {
+ *get_ed = otg_list_get_node(transreadyq_list_entity,ed_t,trans_ready_q_list_entry);
+ if (transreadyq_list_entity->prev == LIST_POISON2 ||
+ transreadyq_list_entity->next == LIST_POISON1) {
+ printk(KERN_ERR "s3c-otg-scheduler get_ed_from_ready_q error\n");
+ periodic_trans_ready_q.trans_ready_entry_num =0;
+ }
+ else {
+ otg_list_pop(transreadyq_list_entity);
+ periodic_trans_ready_q.trans_ready_entry_num--;
+ }
+
+ return USB_ERR_SUCCESS;
+ }
+ else
+ {
+ return USB_ERR_NO_ENTITY;
+ }
+ }
+ else
+ {
+ otg_list_head *transreadyq_list_entity=NULL;
+
+ if(nonperiodic_trans_ready_q.trans_ready_entry_num==0)
+ {
+ return USB_ERR_NO_ENTITY;
+ }
+
+ transreadyq_list_entity = nonperiodic_trans_ready_q.trans_ready_q_list_head.next;
+
+ //if(transreadyq_list_entity!= &nonperiodic_trans_ready_q.trans_ready_q_list_head)
+ if(!otg_list_empty(&nonperiodic_trans_ready_q.trans_ready_q_list_head))
+ {
+ *get_ed = otg_list_get_node(transreadyq_list_entity,ed_t, trans_ready_q_list_entry);
+ if (transreadyq_list_entity->prev == LIST_POISON2 ||
+ transreadyq_list_entity->next == LIST_POISON1) {
+ printk(KERN_ERR "s3c-otg-scheduler get_ed_from_ready_q error\n");
+ nonperiodic_trans_ready_q.trans_ready_entry_num =0;
+ }
+ else {
+ otg_list_pop(transreadyq_list_entity);
+ nonperiodic_trans_ready_q.trans_ready_entry_num--;
+ }
+
+ return USB_ERR_SUCCESS;
+ }
+ else
+ {
+ return USB_ERR_NO_ENTITY;
+ }
+ }
+}
+
+
diff --git a/drivers/usb/host/s3c-otg/s3c-otg-scheduler-scheduler.c b/drivers/usb/host/s3c-otg/s3c-otg-scheduler-scheduler.c
new file mode 100644
index 0000000..034cec4
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/s3c-otg-scheduler-scheduler.c
@@ -0,0 +1,424 @@
+/****************************************************************************
+ * (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+ *
+ * [File Name] : Scheduler.c
+ * [Description] : The source file implements the internal functions of Scheduler.
+ * [Author] : Yang Soon Yeal { syatom.yang@samsung.com }
+ * [Department] : System LSI Division/System SW Lab
+ * [Created Date]: 2008/06/04
+ * [Revision History]
+ * (1) 2008/06/03 by Yang Soon Yeal { syatom.yang@samsung.com }
+ * - Created this file and implements functions of Scheduler
+ * -# Jul 15,2008 v1.2 by SeungSoo Yang (ss1.yang@samsung.com) \n
+ * : Optimizing for performance \n
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * 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 "s3c-otg-scheduler-scheduler.h"
+
+//Define constant variables
+
+//the max periodic bus time is 80%*125us on High Speed Mode
+static const u32 perio_highbustime_threshold = 100;
+
+//the max periodic bus time is 90%*1000us(1ms) on Full/Low Speed Mode .
+static const u32 perio_fullbustime_threshold = 900;
+
+static const u8 perio_chnum_threshold = 14;
+//static const u8 total_chnum_threshold = 16;
+static u8 total_chnum_threshold = 16;
+
+ //Define global variables
+// kevinh: add volatile
+static volatile u32 perio_used_bustime = 0;
+static volatile u8 perio_used_chnum = 0;
+static volatile u8 nonperio_used_chnum = 0;
+static volatile u8 total_used_chnum = 0;
+static volatile u32 transferring_td_array[16]={0};
+
+void reset_scheduler_numbers(void) {
+ total_chnum_threshold = 16;
+ perio_used_bustime = 0;
+ perio_used_chnum = 0;
+ nonperio_used_chnum = 0;
+ total_used_chnum = 0;
+ memset(transferring_td_array,0,sizeof(transferring_td_array));
+}
+
+int inc_perio_bus_time(u32 bus_time, u8 dev_speed)
+{
+ switch(dev_speed) {
+ case HIGH_SPEED_OTG:
+ if((bus_time+perio_used_bustime)<=perio_highbustime_threshold) {
+ perio_used_bustime=+bus_time;
+ return USB_ERR_SUCCESS;
+ }
+ else {
+ return USB_ERR_FAIL;
+ }
+
+ case LOW_SPEED_OTG:
+ case FULL_SPEED_OTG:
+ if((bus_time+perio_used_bustime)<=perio_fullbustime_threshold) {
+ perio_used_bustime=+bus_time;
+ return USB_ERR_SUCCESS;
+ }
+ else {
+ return USB_ERR_FAIL;
+ }
+ case SUPER_SPEED_OTG:
+ break;
+ default:
+ break;
+ }
+ return USB_ERR_FAIL;
+}
+
+int dec_perio_bus_time(u32 bus_time)
+{
+ if(perio_used_bustime >= bus_time ) {
+ perio_used_bustime =- bus_time;
+ return USB_ERR_SUCCESS;
+ }
+ else {
+ return USB_ERR_FAIL;
+ }
+}
+
+int inc_perio_chnum(void)
+{
+ if(perio_used_chnum<perio_chnum_threshold)
+ {
+ if(total_used_chnum<total_chnum_threshold)
+ {
+ perio_used_chnum++;
+ total_used_chnum++;
+ return USB_ERR_SUCCESS;
+ }
+ }
+ return USB_ERR_FAIL;
+}
+
+u8 get_avail_chnum(void)
+{
+ return total_chnum_threshold - total_used_chnum;
+}
+
+int dec_perio_chnum(void)
+{
+ if(perio_used_chnum>0)
+ {
+ if(total_used_chnum>0)
+ {
+ perio_used_chnum--;
+ total_used_chnum--;
+ return USB_ERR_SUCCESS;
+ }
+ }
+ return USB_ERR_FAIL;
+}
+
+int inc_non_perio_chnum(void)
+{
+ if(nonperio_used_chnum<total_chnum_threshold)
+ {
+ if(total_used_chnum<total_chnum_threshold)
+ {
+ nonperio_used_chnum++;
+ total_used_chnum++;
+ return USB_ERR_SUCCESS;
+ }
+ }
+ return USB_ERR_FAIL;
+}
+
+int dec_nonperio_chnum(void)
+{
+ if(nonperio_used_chnum>0)
+ {
+ if(total_used_chnum>0)
+ {
+ nonperio_used_chnum--;
+ total_used_chnum--;
+ return USB_ERR_SUCCESS;
+ }
+ }
+ return USB_ERR_FAIL;
+}
+
+int get_transferring_td_array(u8 chnum, unsigned int *td_addr)
+{
+ if(transferring_td_array[chnum]!=0)
+ {
+ *td_addr = transferring_td_array[chnum];
+ return USB_ERR_SUCCESS;
+ }
+
+ return USB_ERR_FAIL;
+}
+
+int set_transferring_td_array(u8 chnum, u32 td_addr)
+{
+ if(td_addr ==0)
+ {
+ transferring_td_array[chnum] = td_addr;
+ return USB_ERR_SUCCESS;
+ }
+
+ if(transferring_td_array[chnum] == 0)
+ {
+ transferring_td_array[chnum] = td_addr;
+ return USB_ERR_SUCCESS;
+ }
+ else
+ {
+ return USB_ERR_FAIL;
+ }
+}
+
+/******************************************************************************/
+/*!
+ * @name int insert_ed_to_scheduler(struct sec_otghost *otghost, ed_t *insert_ed)
+ *
+ * @brief this function transfers the insert_ed to S3C6400Scheduler, and
+ * after that, the insert_ed is inserted to TransferReadyQ and scheduled by Scheduler.
+ *
+ *
+ * @param [IN] insert_ed = indicates pointer of ed_t to be inserted to TransferReadyQ.
+ *
+ * @return USB_ERR_ALREADY_EXIST - if the insert_ed is already existed.
+ * USB_ERR_SUCCESS - if success to insert insert_ed to S3CScheduler.
+ */
+/******************************************************************************/
+int insert_ed_to_scheduler(struct sec_otghost *otghost, ed_t *insert_ed)
+{
+ if(!insert_ed->is_need_to_insert_scheduler)
+ return USB_ERR_ALREADY_EXIST;
+
+ insert_ed_to_ready_q(insert_ed, false);
+ insert_ed->is_need_to_insert_scheduler = false;
+ insert_ed->ed_status.is_in_transfer_ready_q = true;
+
+ do_periodic_schedule(otghost);
+ do_nonperiodic_schedule(otghost);
+
+ return USB_ERR_SUCCESS;
+}
+
+/******************************************************************************/
+/*!
+ * @name int do_periodic_schedule(struct sec_otghost *otghost)
+ *
+ * @brief this function schedules PeriodicTransferReadyQ.
+ * this function checks whether PeriodicTransferReadyQ has some ed_t.
+ * if there are some ed_t on PeriodicTransferReadyQ
+ * , this function request to start USB Trasnfer to S3C6400OCI.
+ *
+ *
+ * @param void
+ *
+ * @return void
+ */
+/******************************************************************************/
+void do_periodic_schedule(struct sec_otghost *otghost)
+{
+ ed_t *scheduling_ed= NULL;
+ int err_sched = USB_ERR_SUCCESS;
+ u32 sched_cnt = 0;
+
+ otg_dbg(OTG_DBG_SCHEDULE,"*******Start to DoPeriodicSchedul*********\n");
+
+ sched_cnt = get_periodic_ready_q_entity_num();
+
+ while(sched_cnt) {
+ //in periodic transfser, the channel resource was already reserved.
+ //So, we don't need this routine...
+
+start_sched_perio_transfer:
+ if(!sched_cnt)
+ goto end_sched_perio_transfer;
+
+ err_sched = get_ed_from_ready_q(true, &scheduling_ed);
+
+ if(err_sched==USB_ERR_SUCCESS) {
+ otg_list_head *td_list_entry;
+ td_t *td;
+ u32 cur_frame_num = 0;
+
+ otg_dbg(OTG_DBG_SCHEDULE,"the ed_t to be scheduled :%d",(int)scheduling_ed);
+ sched_cnt--;
+ td_list_entry = scheduling_ed->td_list_entry.next;
+
+ if(td_list_entry == &scheduling_ed->td_list_entry) {
+ //scheduling_ed has no td_t. so we schedules another ed_t on PeriodicTransferReadyQ.
+ goto start_sched_perio_transfer;
+ }
+
+ if(scheduling_ed->ed_status.is_in_transferring) {
+ //scheduling_ed is already Scheduled. so we schedules another ed_t on PeriodicTransferReadyQ.
+ goto start_sched_perio_transfer;
+ }
+
+ cur_frame_num = oci_get_frame_num();
+
+ if(((cur_frame_num-scheduling_ed->ed_desc.sched_frame)&HFNUM_MAX_FRNUM)>(HFNUM_MAX_FRNUM>>1)) {
+ insert_ed_to_ready_q(scheduling_ed, false);
+ goto start_sched_perio_transfer;
+ }
+
+ td = otg_list_get_node(td_list_entry, td_t, td_list_entry);
+
+ if((!td->is_transferring) && (!td->is_transfer_done)) {
+ u8 alloc_ch;
+ otg_dbg(OTG_DBG_SCHEDULE,"the td_t to be scheduled :%d",(int)td);
+ alloc_ch = oci_start_transfer(otghost, &td->cur_stransfer);
+ if(alloc_ch<total_chnum_threshold) {
+ td->cur_stransfer.alloc_chnum = alloc_ch;
+ set_transferring_td_array(alloc_ch, (u32)td);
+
+ scheduling_ed->ed_status.is_in_transferring = true;
+ scheduling_ed->ed_status.is_in_transfer_ready_q = false;
+ scheduling_ed->ed_status.in_transferring_td = (u32)td;
+
+ td->is_transferring = true;
+ }
+ else {
+ //we should insert the ed_t to TransferReadyQ, because the USB Transfer of the ed_t is failed.
+ scheduling_ed->ed_status.is_in_transferring = false;
+ scheduling_ed->ed_status.is_in_transfer_ready_q = true;
+ scheduling_ed->ed_status.in_transferring_td = 0;
+
+ insert_ed_to_ready_q(scheduling_ed,true);
+
+ scheduling_ed->is_need_to_insert_scheduler = false;
+ goto end_sched_perio_transfer;
+ }
+
+ }
+ else { // the selected td_t was already transferring or completed to transfer.
+ //we should decide how to control this case.
+ goto end_sched_perio_transfer;
+ }
+ }
+ else {
+ // there is no ED on PeriodicTransferQ. So we finish scheduling.
+ goto end_sched_perio_transfer;
+ }
+ }
+
+end_sched_perio_transfer:
+
+ return;
+}
+
+
+/******************************************************************************/
+/*!
+ * @name int do_nonperiodic_schedule(struct sec_otghost *otghost)
+ *
+ * @brief this function start to schedule thie NonPeriodicTransferReadyQ.
+ * this function checks whether NonPeriodicTransferReadyQ has some ed_t.
+ * if there are some ed_t on NonPeriodicTransferReadyQ
+ * , this function request to start USB Trasnfer to S3C6400OCI.
+ *
+ *
+ * @param void
+ *
+ * @return void
+ */
+/******************************************************************************/
+void do_nonperiodic_schedule(struct sec_otghost *otghost)
+{
+ if(total_used_chnum<total_chnum_threshold) {
+ ed_t *scheduling_ed;
+ int err_sched;
+
+ while(1) {
+
+start_sched_nonperio_transfer:
+
+ //check there is available channel resource for Non-Periodic Transfer.
+ if(total_used_chnum==total_chnum_threshold) {
+ goto end_sched_nonperio_transfer;
+ }
+
+ err_sched = get_ed_from_ready_q(false, &scheduling_ed);
+
+ if(err_sched ==USB_ERR_SUCCESS ) {
+ otg_list_head *td_list_entry;
+ td_t *td;
+
+ td_list_entry = scheduling_ed->td_list_entry.next;
+
+ //if(td_list_entry == &scheduling_ed->td_list_entry)
+ if(otg_list_empty(&scheduling_ed->td_list_entry)) {
+ //scheduling_ed has no td_t. so we schedules another ed_t on PeriodicTransferReadyQ.
+ goto start_sched_nonperio_transfer;
+ }
+
+ if(scheduling_ed->ed_status.is_in_transferring) {
+ //scheduling_ed is already Scheduled. so we schedules another ed_t on PeriodicTransferReadyQ.
+ goto start_sched_nonperio_transfer;
+ }
+
+ td = otg_list_get_node(td_list_entry, td_t, td_list_entry);
+
+ if((!td->is_transferring) && (!td->is_transfer_done)) {
+ u8 alloc_ch;
+
+ alloc_ch = oci_start_transfer(otghost, &td->cur_stransfer);
+
+ if(alloc_ch<total_chnum_threshold) {
+ td->cur_stransfer.alloc_chnum = alloc_ch;
+ set_transferring_td_array(alloc_ch, (u32)td);
+
+ inc_non_perio_chnum();
+
+ scheduling_ed->ed_status.is_in_transferring = true;
+ scheduling_ed->ed_status.is_in_transfer_ready_q = false;
+ scheduling_ed->ed_status.in_transferring_td =(u32)td;
+ td->is_transferring = true;
+ }
+ else {
+ //we should insert the ed_t to TransferReadyQ, because the USB Transfer of the ed_t is failed.
+ scheduling_ed->ed_status.is_in_transferring = false;
+ scheduling_ed->ed_status.in_transferring_td =0;
+ insert_ed_to_ready_q(scheduling_ed,true);
+ scheduling_ed->ed_status.is_in_transfer_ready_q = true;
+
+ goto end_sched_nonperio_transfer;
+ }
+ }
+ else {
+ goto end_sched_nonperio_transfer;
+ }
+ }
+ else { //there is no ed_t on NonPeriodicTransferReadyQ.
+ //So, we finish do_nonperiodic_schedule().
+ goto end_sched_nonperio_transfer;
+ }
+ }
+ }
+
+end_sched_nonperio_transfer:
+
+ return;
+}
+
+
+
diff --git a/drivers/usb/host/s3c-otg/s3c-otg-scheduler-scheduler.h b/drivers/usb/host/s3c-otg/s3c-otg-scheduler-scheduler.h
new file mode 100644
index 0000000..f9905fa
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/s3c-otg-scheduler-scheduler.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+ * (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+ *
+ * [File Name] : Scheduler.h
+ * [Description] : The Header file defines the external and internal functions of Scheduler.
+ * [Author] : Yang Soon Yeal { syatom.yang@samsung.com }
+ * [Department] : System LSI Division/System SW Lab
+ * [Created Date]: 2008/06/03
+ * [Revision History]
+ * (1) 2008/06/03 by Yang Soon Yeal { syatom.yang@samsung.com }
+ * - Created this file and defines functions of Scheduler
+ * -# Jul 15,2008 v1.2 by SeungSoo Yang (ss1.yang@samsung.com) \n
+ * : Optimizing for performance \n
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ ****************************************************************************/
+
+#ifndef _SCHEDULER_H
+#define _SCHEDULER_H
+
+/*
+// ----------------------------------------------------------------------------
+// Include files : None.
+// ----------------------------------------------------------------------------
+*/
+//#include "s3c-otg-common-typedef.h"
+#include "s3c-otg-common-const.h"
+#include "s3c-otg-common-errorcode.h"
+#include "s3c-otg-common-datastruct.h"
+#include "s3c-otg-hcdi-memory.h"
+#include "s3c-otg-hcdi-kal.h"
+#include "s3c-otg-hcdi-debug.h"
+#include "s3c-otg-oci.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+//Defines external functions of IScheduler.c
+extern void init_scheduler(void);
+extern int reserve_used_resource_for_periodic(u32 usb_time,u8 dev_speed, u8 trans_type);
+extern int free_usb_resource_for_periodic(u32 free_usb_time, u8 free_chnum, u8 trans_type);
+extern int remove_ed_from_scheduler(ed_t *remove_ed);
+extern int cancel_to_transfer_td(struct sec_otghost *otghost, td_t *cancel_td);
+extern int retransmit(struct sec_otghost *otghost, td_t *retransmit_td);
+extern int reschedule(td_t *resched_td);
+extern int deallocate(td_t *dealloc_td);
+extern void do_schedule(struct sec_otghost *otghost);
+extern int get_td_info(u8 chnum,unsigned int *td_addr);
+
+// Defines functiions of TranferReadyQ.
+void init_transfer_ready_q(void);
+int insert_ed_to_ready_q(ed_t *insert_ed, bool f_isfirst);
+int remove_ed_from_ready_q(ed_t *remove_ed);
+int get_ed_from_ready_q(bool f_isperiodic, ed_t **get_ed);
+
+//Define functions of Scheduler
+void do_periodic_schedule(struct sec_otghost *otghost);
+void do_nonperiodic_schedule(struct sec_otghost *otghost);
+int set_transferring_td_array(u8 chnum, u32 td_addr);
+int get_transferring_td_array(u8 chnum, unsigned int *td_addr);
+
+
+//Define fuctions to manage some static global variable.
+int inc_perio_bus_time(u32 uiBusTime, u8 dev_speed);
+int dec_perio_bus_time(u32 uiBusTime);
+
+u8 get_avail_chnum(void);
+int inc_perio_chnum(void);
+int dec_perio_chnum(void);
+int inc_non_perio_chnum(void);
+int dec_nonperio_chnum(void);
+u32 get_periodic_ready_q_entity_num(void);
+
+int insert_ed_to_scheduler(struct sec_otghost *otghost, ed_t *insert_ed);
+
+void reset_scheduler_numbers(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
+
diff --git a/drivers/usb/host/s3c-otg/s3c-otg-transfer-common.c b/drivers/usb/host/s3c-otg/s3c-otg-transfer-common.c
new file mode 100644
index 0000000..93b6349
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/s3c-otg-transfer-common.c
@@ -0,0 +1,810 @@
+/****************************************************************************
+ * (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+ *
+ * [File Name] : Commons3c-otg-transfer-transfer.h
+ * [Description] : This source file implements the functions to be defined at CommonTransfer Module.
+ * [Author] : Yang Soon Yeal { syatom.yang@samsung.com }
+ * [Department] : System LSI Division/System SW Lab
+ * [Created Date]: 2008/06/03
+ * [Revision History]
+ * (1) 2008/06/03 by Yang Soon Yeal { syatom.yang@samsung.com }
+ * - Created this file and implements some functions of CommonTransfer.
+ * (2) 2008/07/15 by SeungSoo Yang ( ss1.yang@samsung.com )n
+ * - Optimizing for performance \n
+ * (3) 2008/08/18 by SeungSoo Yang ( ss1.yang@samsung.com )
+ * - Modifying for successful rmmod & disconnecting \n
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * 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 "s3c-otg-transfer-transfer.h"
+
+// the header pointer to indicate the ED_list to manage the ed_t to be created and initiated.
+static otg_list_head ed_list_head;
+static u32 ref_periodic_transfer;
+
+/******************************************************************************/
+/*!
+ * @name void init_transfer(void)
+ *
+ * @brief this function initiates the S3CTranfer module. that is, this functions initiates
+ * the ED_list_head OTG List which manages the all ed_t to be existed.
+ *
+ * @param void
+ *
+ * @return void
+ */
+/******************************************************************************/
+
+void init_transfer(void)
+{
+ otg_dbg(OTG_DBG_TRANSFER,"start to init_transfer\n");
+ otg_list_init(&ed_list_head);
+ ref_periodic_transfer = 0;
+}
+
+
+/******************************************************************************/
+/*!
+ * @name void DeInitTransfer(void)
+ *
+ * @brief this function Deinitiates the S3CTranfer module. this functions check which there are
+ * some ed_t on ED_list_head. if some ed_t exists, deinit_transfer() deletes the ed_t.
+ *
+ *
+ * @param void
+ *
+ * @return void
+ */
+/******************************************************************************/
+void deinit_transfer(struct sec_otghost *otghost)
+{
+ otg_list_head *ed_list_member;
+ ed_t *delete_ed_p;
+
+ while(otg_list_empty(&ed_list_head) != true) {
+ ed_list_member = ed_list_head.next;
+
+ /* otg_list_pop(ed_list_member); */
+
+ delete_ed_p= otg_list_get_node(ed_list_member,ed_t,ed_list_entry);
+
+ delete_ed(otghost, delete_ed_p);
+ }
+}
+
+/******************************************************************************/
+/*!
+ * @name int delete_ed(ed_t *delete_ed)
+ *
+ * @brief this function delete the delete_ed.
+ * if there is some available TD_ts on delete_ed, then this function also deletes these td_t
+ *
+ *
+ * @param [IN] delete_ed = indicates the address of ed_t to be deleted.
+ *
+ * @return USB_ERR_SUCCESS -if successes to delete the ed_t.
+ * USB_ERR_FAILl -if fails to delete the ed_t.
+ */
+/******************************************************************************/
+int delete_ed(struct sec_otghost *otghost, ed_t *delete_ed)
+{
+ otg_kal_make_ep_null(delete_ed);
+
+ if(delete_ed->num_td) {
+ cancel_all_td(otghost, delete_ed);
+ /**
+ need to giveback of td's urb with considering life-cycle of
+ TD, ED, urb->hcpriv, td->private, ep->hcpriv, td->parentED
+ (commented by ss1.yang)
+ */
+ }
+
+ otg_list_pop(&delete_ed->ed_list_entry);
+
+ if(delete_ed->ed_desc.endpoint_type == INT_TRANSFER ||
+ delete_ed->ed_desc.endpoint_type == ISOCH_TRANSFER) {
+ ref_periodic_transfer--;
+ }
+
+ if(ref_periodic_transfer==0) {
+ disable_sof();
+ }
+ otg_mem_free(delete_ed);
+
+ return USB_ERR_SUCCESS;
+}
+
+/******************************************************************************/
+/*!
+ * @name int delete_td(struct sec_otghost *otghost, td_t *delete_td)
+ *
+ * @brief this function frees memory resource for the delete_td.
+ * and if delete_td is transferring USB Transfer, then this function request to cancel
+ * the USB Transfer to S3CScheduler.
+ *
+ *
+ * @param [OUT] new_td_p = returns the address of the new td_t .
+ *
+ * @return USB_ERR_SUCCESS -if successes to create the new td_t.
+ * USB_ERR_FAILl -if fails to create to new td_t.
+ */
+/******************************************************************************/
+int delete_td(struct sec_otghost *otghost, td_t *delete_td)
+{
+ if(delete_td->is_transferring) {
+ //at this case, we should cancel the USB Transfer.
+ cancel_to_transfer_td(otghost, delete_td);
+ }
+
+ otg_mem_free(delete_td);
+ return USB_ERR_SUCCESS;
+}
+
+int create_isoch_packet_desc(isoch_packet_desc_t **new_isoch_packet_desc,
+ u32 isoch_packet_num)
+{
+ return otg_mem_alloc((void **)new_isoch_packet_desc,
+ (u16)sizeof(isoch_packet_desc_t)*isoch_packet_num,USB_MEM_SYNC);
+}
+
+int delete_isoch_packet_desc(isoch_packet_desc_t *del_isoch_packet_desc,
+ u32 isoch_packet_num)
+{
+ return otg_mem_free(del_isoch_packet_desc);
+}
+
+/******************************************************************************/
+/*!
+ * @name void init_isoch_packet_desc( isoch_packet_desc_t *init_isoch_packet_desc,
+ * u32 isoch_packet_start_addr,
+ * u32 isoch_packet_size,
+ * u32 index)
+ *
+ * @brief this function initiates the isoch_packet_desc_t[index].
+ *
+ *
+ * @param [OUT] init_isoch_packet_desc = indicates the pointer of IsochPackDesc_t to be initiated.
+ * [IN] isoch_packet_start_addr = indicates the start address of the buffer to be used
+ * at USB Isochronous Transfer.
+ * [IN] isoch_packet_size = indicates the size of Isochronous packet.
+ * [IN] index = indicates the index to be mapped with this init_isoch_packet_desc.
+ *
+ * @return void
+ */
+/******************************************************************************/
+void init_isoch_packet_desc(isoch_packet_desc_t *init_isoch_packet_desc,
+ u32 isoch_packet_start_addr,
+ u32 isoch_packet_size,
+ u32 index)
+{
+ init_isoch_packet_desc[index].buf_size = isoch_packet_size;
+ init_isoch_packet_desc[index].isoch_packiet_start_addr = isoch_packet_start_addr;
+ init_isoch_packet_desc[index].isoch_status = 0;
+ init_isoch_packet_desc[index].transferred_szie = 0;
+}
+
+/******************************************************************************/
+/*!
+ * @name int create_ed(ed_t **new_ed)
+ *
+ * @brief this function creates a new ed_t and returns the ed_t to Caller
+ *
+ *
+ * @param [OUT] new_ed = returns the address of the new ed_t .
+ *
+ * @return USB_ERR_SUCCESS -if successes to create the new ed_t.
+ * USB_ERR_FAILl -if fails to create to new ed_t.
+ */
+/******************************************************************************/
+int create_ed(ed_t **new_ed)
+{
+ int err_code = USB_ERR_SUCCESS;
+
+ err_code = otg_mem_alloc((void **)new_ed,(u16)sizeof(ed_t), USB_MEM_ASYNC);
+ otg_mem_set(*new_ed, 0, sizeof(ed_t));
+ return err_code;
+}
+
+
+/******************************************************************************/
+/*!
+ * @name int init_ed( ed_t *init_ed,
+ * u8 dev_addr,
+ * u8 ep_num,
+ * bool f_is_ep_in,
+ * u8 dev_speed,
+ * u8 ep_type,
+ * u32 max_packet_size,
+ * u8 multi_count,
+ * u8 interval,
+ * u32 sched_frame,
+ * u8 hub_addr,
+ * u8 hub_port,
+ * bool f_is_do_split)
+ *
+ * @brief this function initiates the init_ed by using the another parameters.
+ *
+ *
+ * @param [OUT] init_ed = returns the ed_t to be initiated.
+ * [IN] dev_addr = inidcates the address of USB Device.
+ * [IN] ep_num = inidcates the number of the specific endpoint on USB Device.
+ * [IN] f_is_ep_in = inidcates whether the endpoint is IN or not
+ * [IN] dev_speed = inidcates the speed of USB Device.
+ * [IN] max_packet_size = inidcates the maximum packet size of a specific endpoint on USB Device.
+ * [IN] multi_count = if the endpoint supports periodic transfer
+ * , this indicates the multiple packet to be transferred on a uframe
+ * [IN] interval= if the endpoint support periodic transfer, this indicates the polling rate.
+ * [IN] sched_frame= if the endpoint supports periodic transfer, this indicates the start frame number.
+ * [IN] hub_addr= indicate the address of hub which the USB device attachs to.
+ * [IN] hub_port= inidcates the port number of the hub which the USB device attachs to.
+ * [IN] f_is_do_split= inidcates whether this tranfer is split transaction or not.
+ *
+ * @return USB_ERR_SUCCESS -if successes to initiate the ed_t.
+ * USB_ERR_FAILl -if fails to initiate the ed_t.
+ * USB_ERR_NOSPACE -if fails to initiate the ed_t
+ * because there is no USB Resource for this init_ed.
+ */
+/******************************************************************************/
+int init_ed(ed_t *init_ed,
+ u8 dev_addr,
+ u8 ep_num,
+ bool f_is_ep_in,
+ u8 dev_speed,
+ u8 ep_type,
+ u16 max_packet_size,
+ u8 multi_count,
+ u8 interval,
+ u32 sched_frame,
+ u8 hub_addr,
+ u8 hub_port,
+ bool f_is_do_split,
+ void *ep)
+{
+ init_ed->is_halted = false;
+ init_ed->is_need_to_insert_scheduler= true;
+ init_ed->ed_id = (u32)init_ed;
+ init_ed->num_td = 0;
+ init_ed->ed_private = ep;
+
+ otg_list_init(&init_ed->td_list_entry);
+
+ //start to initiate struct ed_desc....
+ init_ed->ed_desc.is_do_split = f_is_do_split;
+ init_ed->ed_desc.is_ep_in = f_is_ep_in;
+ init_ed->ed_desc.dev_speed = dev_speed;
+ init_ed->ed_desc.hub_addr = hub_addr;
+ init_ed->ed_desc.hub_port = hub_port;
+ init_ed->ed_desc.mc = multi_count;
+ init_ed->ed_desc.device_addr = dev_addr;
+ init_ed->ed_desc.endpoint_num = ep_num;
+ init_ed->ed_desc.endpoint_type = ep_type;
+ init_ed->ed_desc.max_packet_size = max_packet_size;
+ init_ed->ed_desc.sched_frame = sched_frame;
+
+ if(init_ed->ed_desc.endpoint_type == INT_TRANSFER) {
+ if(init_ed->ed_desc.dev_speed == LOW_SPEED_OTG ||init_ed->ed_desc.dev_speed == FULL_SPEED_OTG) {
+ init_ed->ed_desc.interval =interval;
+ }
+ else if(init_ed->ed_desc.dev_speed == HIGH_SPEED_OTG) {
+ u8 count = 0;
+ u8 cal_interval = 1;
+
+ for(count = 0;count<(init_ed->ed_desc.interval-1);count++) {
+ cal_interval *=2;
+ }
+
+ init_ed->ed_desc.interval =cal_interval;
+ }
+ else {
+ otg_dbg(OTG_DBG_TRANSFER,"Super-Speed is not supported\n");
+ }
+ init_ed->ed_desc.sched_frame = (SCHEDULE_SLOT+oci_get_frame_num())&HFNUM_MAX_FRNUM;
+ ref_periodic_transfer++;
+ }
+ if(init_ed->ed_desc.endpoint_type==ISOCH_TRANSFER) {
+ u8 count = 0;
+ u8 cal_interval = 1;
+
+ for(count = 0;count<(init_ed->ed_desc.interval-1);count++)
+ {
+ cal_interval *=2;
+ }
+
+ init_ed->ed_desc.interval = cal_interval;
+ init_ed->ed_desc.sched_frame = (SCHEDULE_SLOT+oci_get_frame_num())&HFNUM_MAX_FRNUM;
+ ref_periodic_transfer++;
+ }
+
+ //start to initiate struct ed_status....
+
+ //initiates PID
+ switch(ep_type) {
+ case BULK_TRANSFER:
+ case INT_TRANSFER:
+ init_ed->ed_status.data_tgl = DATA0;
+ break;
+
+ case CONTROL_TRANSFER:
+ init_ed->ed_status.control_data_tgl.setup_tgl = SETUP;
+ init_ed->ed_status.control_data_tgl.data_tgl = DATA1;
+ init_ed->ed_status.control_data_tgl.status_tgl = DATA1;
+ break;
+
+ case ISOCH_TRANSFER:
+ if(f_is_ep_in) {
+ switch(multi_count) {
+ case MULTI_COUNT_ZERO :
+ init_ed->ed_status.data_tgl = DATA0;
+ break;
+ case MULTI_COUNT_ONE :
+ init_ed->ed_status.data_tgl = DATA1;
+ break;
+ case MULTI_COUNT_TWO :
+ init_ed->ed_status.data_tgl = DATA2;
+ break;
+ default:
+ break;
+ }
+ }
+ else {
+ switch(multi_count) {
+ case MULTI_COUNT_ZERO :
+ init_ed->ed_status.data_tgl = DATA0;
+ break;
+ case MULTI_COUNT_ONE :
+ init_ed->ed_status.data_tgl = MDATA;
+ break;
+ case MULTI_COUNT_TWO :
+ init_ed->ed_status.data_tgl = MDATA;
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ if(init_ed->ed_desc.endpoint_type == INT_TRANSFER ||
+ init_ed->ed_desc.endpoint_type == ISOCH_TRANSFER) {
+ u32 usb_time = 0, byte_count = 0;
+
+ //calculates the bytes to be transferred at one (uframe)frame.
+ byte_count = (init_ed->ed_desc.mc+1)*init_ed->ed_desc.max_packet_size;
+
+ usb_time = (u32)otg_usbcore_get_calc_bustime(init_ed->ed_desc.dev_speed,
+ init_ed->ed_desc.is_ep_in,
+ (init_ed->ed_desc.endpoint_type==ISOCH_TRANSFER?true:false),
+ byte_count);
+ usb_time /= 1000; //convert nanosec unit to usec unit
+
+ if(reserve_used_resource_for_periodic(usb_time, init_ed->ed_desc.dev_speed, init_ed->ed_desc.endpoint_type) != USB_ERR_SUCCESS) {
+ return USB_ERR_NOSPACE;
+ }
+
+ init_ed->ed_status.is_alloc_resource_for_ed =true;
+ init_ed->ed_desc.used_bus_time =usb_time;
+ init_ed->ed_desc.mc =multi_count+1;
+ }
+
+ init_ed->ed_status.is_in_transfer_ready_q =false;
+ init_ed->ed_status.is_in_transferring =false;
+ init_ed->ed_status.is_ping_enable =false;
+ init_ed->ed_status.in_transferring_td =0;
+
+// sztupy: split transaction support
+ init_ed->ed_status.is_complete_split = false;
+ init_ed->ed_status.split_pos = ED_STATUS_SPLIT_POS_ALL;
+ init_ed->ed_status.split_offset = 0;
+
+ //push the ed_t to ED_list.
+ otg_list_push_prev(&init_ed->ed_list_entry,&ed_list_head);
+
+ if(ref_periodic_transfer) {
+ enable_sof();
+ }
+ return USB_ERR_SUCCESS;
+}
+
+
+/******************************************************************************/
+/*!
+ * @name int create_td(td_t **new_td)
+ *
+ * @brief this function creates a new td_t and returns the td_t to Caller
+ *
+ *
+ * @param [OUT] new_td = returns the address of the new td_t .
+ *
+ * @return USB_ERR_SUCCESS -if successes to create the new td_t.
+ * USB_ERR_FAILl -if fails to create to new td_t.
+ */
+/******************************************************************************/
+int create_td(td_t **new_td)
+{
+ int err_code = USB_ERR_SUCCESS;
+
+ err_code = otg_mem_alloc((void **)new_td,(u16)sizeof(td_t), USB_MEM_ASYNC);
+ otg_mem_set(*new_td, 0, sizeof(td_t));
+ return err_code;
+}
+
+
+/******************************************************************************/
+/*!
+ * @name int init_td( td_t *init_td,
+ * ed_t *parent_ed,
+ * void *call_back_fun,
+ * void *call_back_param,
+ * u32 transfer_flag,
+ * bool f_is_standard_dev_req,
+ * u32 phy_setup,
+ * u32 vir_setup,
+ * u32 vir_buf_addr,
+ * u32 phy_buf_addr,
+ * u32 buf_size,
+ * u32 isoch_start_frame,
+ * isoch_packet_desc_t *isoch_packet_desc,
+ * u32 isoch_packet_num,
+ * void *td_priv)
+ *
+ * @brief this function initiates the init_td by using another parameter.
+ *
+ *
+ * @param [IN] init_td - indicate the td_t to be initiated.
+ * [IN] parent_ed - indicate the ed_t to manage this init_td
+ * [IN] call_back_func - indicate the call-back function of application.
+ * [IN] call_back_param - indicate the parameter of the call-back function.
+ * [IN] transfer_flag - indicate the transfer flag.
+ * [IN] f_is_standard_dev_req - indicates the issue transfer request is USB Standard Request
+ * [IN] phy_setup - the physical address of buffer to store the USB Standard Request.
+ * [IN] vir_setup - the virtual address of buffer to store the USB Standard Request.
+ * [IN] vir_buf_addr - the virtual address of buffer to store the data to be transferred or received.
+ * [IN] phy_buf_addr - the physical address of buffer to store the data to be transferred or received.
+ * [IN] buf_size - indicates the buffer size.
+ * [IN] isoch_start_frame - if this usb transfer is isochronous transfer
+ * , this indicates the start frame to start the usb transfer.
+ * [IN] isoch_packet_desc - if the usb transfer is isochronous transfer
+ * , this indicates the structure to describe the isochronous transfer.
+ * [IN] isoch_packet_num - if the usb transfer is isochronous transfer
+ * , this indicates the number of packet to consist of the usb transfer.
+ * [IN] td_priv - indicate the private data to be delivered from usb core of linux.
+ * td_priv stores the urb of linux.
+ *
+ * @return USB_ERR_SUCCESS -if successes to initiate the new td_t.
+ * USB_ERR_FAILl -if fails to create to new td_t.
+ */
+/******************************************************************************/
+int init_td( td_t *init_td,
+ ed_t *parent_ed,
+ void *call_back_fun,
+ void *call_back_param,
+ u32 transfer_flag,
+ bool f_is_standard_dev_req,
+ u32 phy_setup,
+ u32 vir_setup,
+ u32 vir_buf_addr,
+ u32 phy_buf_addr,
+ u32 buf_size,
+ u32 isoch_start_frame,
+ isoch_packet_desc_t *isoch_packet_desc,
+ u32 isoch_packet_num,
+ void *td_priv)
+{
+ if(f_is_standard_dev_req) {
+ if((phy_buf_addr>0) && (buf_size>0)) {
+ init_td->standard_dev_req_info.is_data_stage = true;
+ }
+ else {
+ init_td->standard_dev_req_info.is_data_stage = false;
+ }
+ init_td->standard_dev_req_info.conrol_transfer_stage = SETUP_STAGE;
+ init_td->standard_dev_req_info.phy_standard_dev_req_addr = phy_setup;
+ init_td->standard_dev_req_info.vir_standard_dev_req_addr = vir_setup;
+ }
+
+ init_td->call_back_func_p = call_back_fun;
+ init_td->call_back_func_param_p = call_back_param;
+ init_td->error_code = USB_ERR_SUCCESS;
+ init_td->is_standard_dev_req = f_is_standard_dev_req;
+ init_td->is_transfer_done = false;
+ init_td->is_transferring = false;
+ init_td->td_private = td_priv;
+ init_td->err_cnt = 0;
+ init_td->parent_ed_p = parent_ed;
+ init_td->phy_buf_addr = phy_buf_addr;
+ init_td->vir_buf_addr = vir_buf_addr;
+ init_td->buf_size = buf_size;
+ init_td->isoch_packet_desc_p = isoch_packet_desc;
+ init_td->isoch_packet_num = isoch_packet_num;
+ init_td->isoch_packet_index = 0;
+ init_td->isoch_packet_position = 0;
+ init_td->sched_frame = isoch_start_frame;
+ init_td->used_total_bus_time = parent_ed->ed_desc.used_bus_time;
+ init_td->td_id = (u32)init_td;
+ init_td->transfer_flag = transfer_flag;
+ init_td->transferred_szie = 0;
+
+ switch(parent_ed->ed_desc.endpoint_type) {
+ case CONTROL_TRANSFER:
+ init_nonperio_stransfer(true, init_td);
+ break;
+
+ case BULK_TRANSFER:
+ init_nonperio_stransfer(false, init_td);
+ break;
+
+ case INT_TRANSFER:
+ init_perio_stransfer(false, init_td);
+ break;
+
+ case ISOCH_TRANSFER:
+ init_perio_stransfer(true, init_td);
+ break;
+
+ default:
+ return USB_ERR_FAIL;
+ }
+
+ //insert the td_t to parent_ed->td_list_entry.
+ otg_list_push_prev(&init_td->td_list_entry,&parent_ed->td_list_entry);
+ parent_ed->num_td++;
+
+ return USB_ERR_SUCCESS;
+}
+
+/******************************************************************************/
+/*!
+ * @name int issue_transfer(struct sec_otghost *otghost,
+ * ed_t *parent_ed,
+ * void *call_back_func,
+ * void *call_back_param,
+ * u32 transfer_flag,
+ * bool f_is_standard_dev_req,
+ * u32 setup_vir_addr,
+ * u32 setup_phy_addr,
+ * u32 vir_buf_addr,
+ * u32 phy_buf_addr,
+ * u32 buf_size,
+ * u32 start_frame,
+ * u32 isoch_packet_num,
+ * isoch_packet_desc_t *isoch_packet_desc,
+ * void *td_priv,
+ * unsigned int *return_td_addr)
+ *
+ * @brief this function start USB Transfer
+ *
+ *
+ * @param [IN] parent_ed - indicate the ed_t to manage this issue transfer.
+ * [IN] call_back_func - indicate the call-back function of application.
+ * [IN] call_back_param - indicate the parameter of the call-back function.
+ * [IN] transfer_flag - indicate the transfer flag.
+ * [IN] f_is_standard_dev_req - indicates the issue transfer request is USB Standard Request
+ * [IN] setup_vir_addr - the virtual address of buffer to store the USB Standard Request.
+ * [IN] setup_phy_addr - the physical address of buffer to store the USB Standard Request.
+ * [IN] vir_buf_addr - the virtual address of buffer to store the data to be transferred or received.
+ * [IN] phy_buf_addr - the physical address of buffer to store the data to be transferred or received.
+ * [IN] buf_size - indicates the buffer size.
+ * [IN] start_frame - if this usb transfer is isochronous transfer
+ * , this indicates the start frame to start the usb transfer.
+ * [IN] isoch_packet_num - if the usb transfer is isochronous transfer
+ * , this indicates the number of packet to consist of the usb transfer.
+ * [IN] isoch_packet_desc - if the usb transfer is isochronous transfer
+ * , this indicates the structure to describe the isochronous transfer.
+ * [IN] td_priv - indicate the private data to be delivered from usb core of linux.
+ * td_priv stores the urb of linux.
+ * [OUT] return_td_addr - indicates the variable address to store the new td_t for this transfer
+ *
+ * @return USB_ERR_SUCCESS -if successes to initiate the new td_t.
+ * USB_ERR_FAILl -if fails to create to new td_t.
+ */
+/******************************************************************************/
+int issue_transfer(struct sec_otghost *otghost,
+ ed_t *parent_ed,
+ void *call_back_func,
+ void *call_back_param,
+ u32 transfer_flag,
+ bool f_is_standard_dev_req,
+ u32 setup_vir_addr,
+ u32 setup_phy_addr,
+ u32 vir_buf_addr,
+ u32 phy_buf_addr,
+ u32 buf_size,
+ u32 start_frame,
+ u32 isoch_packet_num,
+ isoch_packet_desc_t *isoch_packet_desc,
+ void *td_priv,
+ unsigned int *return_td_addr)
+{
+ td_t *new_td_p = NULL;
+
+ int err = USB_ERR_SUCCESS;
+ if(create_td(&new_td_p)==USB_ERR_SUCCESS) {
+ err = init_td( new_td_p,
+ parent_ed,
+ call_back_func,
+ call_back_param,
+ transfer_flag,
+ f_is_standard_dev_req,
+ setup_phy_addr,
+ setup_vir_addr,
+ vir_buf_addr,
+ phy_buf_addr,
+ buf_size,
+ start_frame,
+ isoch_packet_desc,
+ isoch_packet_num,
+ td_priv);
+
+ if(err !=USB_ERR_SUCCESS) {
+ return USB_ERR_NOMEM;
+ }
+
+ if(parent_ed->is_need_to_insert_scheduler) {
+ insert_ed_to_scheduler(otghost, parent_ed);
+ }
+
+ *return_td_addr = (u32)new_td_p;
+
+ return USB_ERR_SUCCESS;
+ }
+ else {
+ return USB_ERR_NOMEM;
+ }
+}
+
+/******************************************************************************/
+/*!
+ * @name int cancel_transfer(struct sec_otghost *otghost,
+ * ed_t *parent_ed,
+ * td_t *cancel_td)
+ *
+ * @brief this function cancels to transfer USB Transfer of cancel_td.
+ * this function firstly check whether this cancel_td is transferring or not
+ * if the cancel_td is transferring, the this function requests to cancel the USB Transfer
+ * to S3CScheduler. if the parent_ed is for Periodic Transfer, and
+ * there is not any td_t at parent_ed, then this function requests to release
+ * some usb resources for the ed_t to S3CScheduler. finally this function deletes the cancel_td.
+ *
+ * @param [IN] pUpdateTD = indicates the pointer ot the td_t to have STransfer to be updated.
+ *
+ * @return USB_ERR_SUCCESS - if success to update the STranfer of pUpdateTD.
+ * USB_ERR_FAIL - if fail to update the STranfer of pUpdateTD.
+ */
+ /******************************************************************************/
+int cancel_transfer(struct sec_otghost *otghost,
+ ed_t *parent_ed,
+ td_t *cancel_td)
+{
+ int err = USB_ERR_DEQUEUED;
+ otg_list_head *tmp_list_p, *tmp_list2_p;
+ bool cond_found = false;
+
+ if(parent_ed == NULL || cancel_td == NULL) {
+ otg_dbg(OTG_DBG_TRANSFER, "parent_ed == NULL || cancel_td == NULL\n");
+ cancel_td->error_code = USB_ERR_NOELEMENT;
+ otg_usbcore_giveback(cancel_td);
+ return cancel_td->error_code;
+ }
+
+ otg_list_for_each_safe(tmp_list_p, tmp_list2_p, &parent_ed->td_list_entry) {
+ if(&cancel_td->td_list_entry == tmp_list_p) {
+ cond_found = true;
+ break;
+ }
+ }
+
+ if (cond_found != true) {
+ otg_dbg(OTG_DBG_TRANSFER, "cond_found != true \n");
+ cancel_td->error_code = USB_ERR_NOELEMENT;
+ otg_usbcore_giveback(cancel_td);
+ return cancel_td->error_code;
+ }
+
+
+ if(cancel_td->is_transferring) {
+ if(!parent_ed->ed_status.is_in_transfer_ready_q) {
+ err = cancel_to_transfer_td(otghost, cancel_td);
+
+ parent_ed->ed_status.in_transferring_td = 0;
+
+ if(err != USB_ERR_SUCCESS) {
+ otg_dbg(OTG_DBG_TRANSFER, "cancel_to_transfer_td \n");
+ cancel_td->error_code = err;
+ otg_usbcore_giveback(cancel_td);
+ goto ErrorStatus;
+ }
+
+ }
+ // kevinh - even if the record was in the ready queue it is important to delete it as well. We can also always remove the ed from the scheduler
+ // once all tds have been removed
+ otg_list_pop(&cancel_td->td_list_entry);
+ parent_ed->num_td--;
+ }
+ else {
+ otg_list_pop(&cancel_td->td_list_entry);
+ parent_ed->num_td--;
+
+ if(parent_ed->num_td==0) {
+ remove_ed_from_scheduler(parent_ed);
+ }
+ }
+
+ if(parent_ed->num_td) {
+ // kevinh - we do not want to force insert_scheduler, because if this endpoint _was_ already scheduled
+ // because the deleted td was not the active td then we will now put ed into the scheduler list twice, thus
+ // corrupting it.
+ // parent_ed->is_need_to_insert_scheduler = true;
+ insert_ed_to_scheduler(otghost, parent_ed);
+ }
+ else {
+ if(parent_ed->ed_desc.endpoint_type == INT_TRANSFER ||
+ parent_ed->ed_desc.endpoint_type == ISOCH_TRANSFER) {
+ //Release channel and usb bus resource for this ed_t.
+ //but, not release memory for this ed_t.
+ free_usb_resource_for_periodic(parent_ed->ed_desc.used_bus_time,
+ cancel_td->cur_stransfer.alloc_chnum,
+ cancel_td->parent_ed_p->ed_desc.endpoint_type);
+
+ parent_ed->ed_status.is_alloc_resource_for_ed =false;
+ }
+ }
+ // the caller of this functions should call otg_usbcore_giveback(cancel_td);
+ cancel_td->error_code = USB_ERR_DEQUEUED;
+ // kevinh - fixed bug, the caller should take care of calling delete_td because they might still want to do some
+ // operations on that memory
+ // delete_td(cancel_td);
+ // otg_usbcore_giveback(cancel_td);
+
+ErrorStatus:
+
+ return err;
+}
+
+
+/******************************************************************************/
+/*!
+ * @name int cancel_all_td(struct sec_otghost *otghost, ed_t *parent_ed)
+ *
+ * @brief this function cancels all Transfer which parent_ed manages.
+ *
+ * @param [IN] parent_ed = indicates the pointer ot the ed_t to manage TD_ts to be canceled.
+ *
+ * @return USB_ERR_SUCCESS - if success to cancel all TD_ts of pParentsED.
+ * USB_ERR_FAIL - if fail to cancel all TD_ts of pParentsED.
+ */
+ /******************************************************************************/
+int cancel_all_td(struct sec_otghost *otghost, ed_t *parent_ed)
+{
+ otg_list_head *cancel_td_list_entry;
+ td_t *cancel_td;
+
+ otg_dbg(OTG_DBG_OTGHCDI_HCD, "cancel_all_td \n");
+ do {
+ cancel_td_list_entry = parent_ed->td_list_entry.next;
+
+ cancel_td = otg_list_get_node(cancel_td_list_entry,td_t, td_list_entry);
+
+ if(cancel_transfer(otghost, parent_ed, cancel_td) == USB_ERR_DEQUEUED)
+ // kevinh FIXME - do we also need to giveback?
+ delete_td(otghost,cancel_td);
+ } while(parent_ed->num_td);
+
+ return USB_ERR_SUCCESS;
+}
diff --git a/drivers/usb/host/s3c-otg/s3c-otg-transfer-nonperiodic.c b/drivers/usb/host/s3c-otg/s3c-otg-transfer-nonperiodic.c
new file mode 100644
index 0000000..013a2a2
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/s3c-otg-transfer-nonperiodic.c
@@ -0,0 +1,140 @@
+/****************************************************************************
+ * (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+ *
+ * [File Name] : NonPeriodicTransfer.c
+ * [Description] : This source file implements the functions to be defined at NonPeriodicTransfer Module.
+ * [Author] : Yang Soon Yeal { syatom.yang@samsung.com }
+ * [Department] : System LSI Division/System SW Lab
+ * [Created Date]: 2008/06/07
+ * [Revision History]
+ * (1) 2008/06/07 by Yang Soon Yeal { syatom.yang@samsung.com }
+ * - Created this file and implements some functions of NonPeriodicTransfer.
+ * -# Jul 15,2008 v1.2 by SeungSoo Yang (ss1.yang@samsung.com) \n
+ * : Optimizing for performance \n
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * 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 "s3c-otg-transfer-transfer.h"
+
+/******************************************************************************/
+/*!
+ * @name int init_nonperio_stransfer( bool f_is_standard_dev_req,
+ * td_t *parent_td)
+ *
+ * @brief this function initiates the parent_td->cur_stransfer for NonPeriodic Transfer and
+ * inserts this init_td_p to init_td_p->parent_ed_p.
+ *
+ * @param [IN] f_is_standard_dev_req = indicates whether this transfer is Control or not.
+ * [IN] parent_td = indicates the address of td_t to be initiated.
+ *
+ * @return USB_ERR_SUCCESS - if success to update the STranfer of pUpdateTD.
+ * USB_ERR_FAIL - if fail to update the STranfer of pUpdateTD.
+ */
+ /******************************************************************************/
+int init_nonperio_stransfer(bool f_is_standard_dev_req,
+ td_t *parent_td)
+{
+
+
+ parent_td->cur_stransfer.ed_desc_p = &parent_td->parent_ed_p->ed_desc;
+ parent_td->cur_stransfer.ed_status_p = &parent_td->parent_ed_p->ed_status;
+ parent_td->cur_stransfer.alloc_chnum = CH_NONE;
+ parent_td->cur_stransfer.parent_td = (u32)parent_td;
+ parent_td->cur_stransfer.stransfer_id = (u32)&parent_td->cur_stransfer;
+
+ otg_mem_set(&(parent_td->cur_stransfer.hc_reg), 0, sizeof(hc_reg_t));
+
+ parent_td->cur_stransfer.hc_reg.hc_int_msk.b.chhltd = 1;
+
+ if(f_is_standard_dev_req)
+ {
+ parent_td->cur_stransfer.buf_size = USB_20_STAND_DEV_REQUEST_SIZE;
+ parent_td->cur_stransfer.start_phy_buf_addr = parent_td->standard_dev_req_info.phy_standard_dev_req_addr;
+ parent_td->cur_stransfer.start_vir_buf_addr = parent_td->standard_dev_req_info.vir_standard_dev_req_addr;
+ }
+ else
+ {
+ parent_td->cur_stransfer.buf_size = (parent_td->buf_size>MAX_CH_TRANSFER_SIZE)
+ ?MAX_CH_TRANSFER_SIZE
+ :parent_td->buf_size;
+
+ parent_td->cur_stransfer.start_phy_buf_addr = parent_td->phy_buf_addr;
+ parent_td->cur_stransfer.start_vir_buf_addr = parent_td->vir_buf_addr;
+ }
+
+ parent_td->cur_stransfer.packet_cnt = calc_packet_cnt(parent_td->cur_stransfer.buf_size
+ , parent_td->parent_ed_p->ed_desc.max_packet_size);
+
+ return USB_ERR_SUCCESS;
+}
+
+
+/******************************************************************************/
+/*!
+ * @name void update_nonperio_stransfer(td_t *parent_td)
+ *
+ * @brief this function updates the parent_td->cur_stransfer to be used by S3COCI.
+ *
+ * @param [IN/OUT]parent_td = indicates the pointer of td_t to store the STranser to be updated.
+ *
+ * @return USB_ERR_SUCCESS -if success to update the parent_td->cur_stransfer.
+ * USB_ERR_FAIL -if fail to update the parent_td->cur_stransfer.
+ */
+ /******************************************************************************/
+void update_nonperio_stransfer(td_t *parent_td)
+{
+ switch(parent_td->parent_ed_p->ed_desc.endpoint_type) {
+ case BULK_TRANSFER:
+ parent_td->cur_stransfer.start_phy_buf_addr = parent_td->phy_buf_addr+parent_td->transferred_szie;
+ parent_td->cur_stransfer.start_vir_buf_addr = parent_td->vir_buf_addr+parent_td->transferred_szie;
+ parent_td->cur_stransfer.buf_size = ((parent_td->buf_size - parent_td->transferred_szie)>MAX_CH_TRANSFER_SIZE)
+ ?MAX_CH_TRANSFER_SIZE
+ :parent_td->buf_size - parent_td->transferred_szie;
+ break;
+
+ case CONTROL_TRANSFER:
+ if(parent_td->standard_dev_req_info.conrol_transfer_stage == SETUP_STAGE)
+ {
+ // but, this case will not be occured......
+ parent_td->cur_stransfer.start_phy_buf_addr = parent_td->standard_dev_req_info.phy_standard_dev_req_addr;
+ parent_td->cur_stransfer.start_vir_buf_addr = parent_td->standard_dev_req_info.vir_standard_dev_req_addr;
+ parent_td->cur_stransfer.buf_size = 8;
+ }
+ else if(parent_td->standard_dev_req_info.conrol_transfer_stage == DATA_STAGE)
+ {
+ parent_td->cur_stransfer.start_phy_buf_addr = parent_td->phy_buf_addr+parent_td->transferred_szie;
+ parent_td->cur_stransfer.start_vir_buf_addr = parent_td->vir_buf_addr+parent_td->transferred_szie;
+ parent_td->cur_stransfer.buf_size = ((parent_td->buf_size - parent_td->transferred_szie)>MAX_CH_TRANSFER_SIZE)
+ ?MAX_CH_TRANSFER_SIZE
+ :parent_td->buf_size - parent_td->transferred_szie;
+ }
+ else
+ {
+ parent_td->cur_stransfer.start_phy_buf_addr = 0;
+ parent_td->cur_stransfer.start_vir_buf_addr = 0;
+ parent_td->cur_stransfer.buf_size = 0;
+ }
+ break;
+ default:
+ break;
+ }
+
+ parent_td->cur_stransfer.packet_cnt = calc_packet_cnt(parent_td->cur_stransfer.buf_size, parent_td->parent_ed_p->ed_desc.max_packet_size);
+
+}
diff --git a/drivers/usb/host/s3c-otg/s3c-otg-transfer-periodic.c b/drivers/usb/host/s3c-otg/s3c-otg-transfer-periodic.c
new file mode 100644
index 0000000..f254b78
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/s3c-otg-transfer-periodic.c
@@ -0,0 +1,128 @@
+/****************************************************************************
+ * (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+ *
+ * [File Name] : NonPeriodicTransfer.c
+ * [Description] : This source file implements the functions to be defined at NonPeriodicTransfer Module.
+ * [Author] : Yang Soon Yeal { syatom.yang@samsung.com }
+ * [Department] : System LSI Division/System SW Lab
+ * [Created Date]: 2008/06/09
+ * [Revision History]
+ * (1) 2008/06/09 by Yang Soon Yeal { syatom.yang@samsung.com }
+ * - Created this file and implements some functions of PeriodicTransfer.
+ * -# Jul 15,2008 v1.2 by SeungSoo Yang (ss1.yang@samsung.com) \n
+ * : Optimizing for performance \n
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * 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 "s3c-otg-transfer-transfer.h"
+
+
+/******************************************************************************/
+/*!
+ * @name int init_perio_stransfer( bool f_is_isoch_transfer,
+ * td_t *parent_td)
+ *
+ * @brief this function initiates the parent_td->cur_stransfer for Periodic Transfer and
+ * inserts this init_td_p to init_td_p->parent_ed_p.
+ *
+ * @param [IN] f_is_isoch_transfer = indicates whether this transfer is Isochronous or not.
+ * [IN] parent_td = indicates the address of td_t to be initiated.
+ *
+ * @return USB_ERR_SUCCESS -if success to update the STranfer of pUpdateTD.
+ * USB_ERR_FAIL -if fail to update the STranfer of pUpdateTD.
+ */
+ /******************************************************************************/
+int init_perio_stransfer( bool f_is_isoch_transfer,
+ td_t *parent_td)
+{
+ parent_td->cur_stransfer.ed_desc_p = &parent_td->parent_ed_p->ed_desc;
+ parent_td->cur_stransfer.ed_status_p = &parent_td->parent_ed_p->ed_status;
+ parent_td->cur_stransfer.alloc_chnum = CH_NONE;
+ parent_td->cur_stransfer.parent_td = (u32)parent_td;
+ parent_td->cur_stransfer.stransfer_id = (u32)&parent_td->cur_stransfer;
+
+ otg_mem_set(&parent_td->cur_stransfer.hc_reg, 0, sizeof(hc_reg_t));
+
+ parent_td->cur_stransfer.hc_reg.hc_int_msk.b.chhltd = 1;
+
+ if(f_is_isoch_transfer)
+ {
+ // initiates the STransfer usinb the IsochPacketDesc[0].
+ parent_td->cur_stransfer.buf_size =parent_td->isoch_packet_desc_p[0].buf_size;
+ parent_td->cur_stransfer.start_phy_buf_addr =parent_td->phy_buf_addr + parent_td->isoch_packet_desc_p[0].isoch_packiet_start_addr;
+ parent_td->cur_stransfer.start_vir_buf_addr =parent_td->vir_buf_addr + parent_td->isoch_packet_desc_p[0].isoch_packiet_start_addr;
+ }
+ else
+ {
+ parent_td->cur_stransfer.buf_size =(parent_td->buf_size>MAX_CH_TRANSFER_SIZE)
+ ?MAX_CH_TRANSFER_SIZE
+ :parent_td->buf_size;
+
+ parent_td->cur_stransfer.start_phy_buf_addr =parent_td->phy_buf_addr;
+ parent_td->cur_stransfer.start_vir_buf_addr =parent_td->vir_buf_addr;
+ }
+
+ parent_td->cur_stransfer.packet_cnt = calc_packet_cnt(parent_td->cur_stransfer.buf_size, parent_td->parent_ed_p->ed_desc.max_packet_size);
+
+ return USB_ERR_SUCCESS;
+}
+
+
+/******************************************************************************/
+/*!
+ * @name void update_perio_stransfer(td_t *parent_td)
+ *
+ * @brief this function updates the parent_td->cur_stransfer to be used by S3COCI.
+ * the STransfer of parent_td is for Periodic Transfer.
+ *
+ * @param [IN/OUT]parent_td = indicates the pointer of td_t to store the STranser to be updated.
+ *
+ * @return USB_ERR_SUCCESS -if success to update the parent_td->cur_stransfer.
+ * USB_ERR_FAIL -if fail to update the parent_td->cur_stransfer.
+ */
+ /******************************************************************************/
+void update_perio_stransfer(td_t *parent_td)
+{
+ switch(parent_td->parent_ed_p->ed_desc.endpoint_type) {
+ case INT_TRANSFER:
+ parent_td->cur_stransfer.start_phy_buf_addr = parent_td->phy_buf_addr+parent_td->transferred_szie;
+ parent_td->cur_stransfer.start_vir_buf_addr = parent_td->vir_buf_addr+parent_td->transferred_szie;
+ parent_td->cur_stransfer.buf_size = (parent_td->buf_size>MAX_CH_TRANSFER_SIZE)
+ ?MAX_CH_TRANSFER_SIZE :parent_td->buf_size;
+ break;
+
+ case ISOCH_TRANSFER:
+ parent_td->cur_stransfer.start_phy_buf_addr = parent_td->phy_buf_addr
+ +parent_td->isoch_packet_desc_p[parent_td->isoch_packet_index].isoch_packiet_start_addr
+ +parent_td->isoch_packet_position;
+
+ parent_td->cur_stransfer.start_vir_buf_addr = parent_td->vir_buf_addr
+ +parent_td->isoch_packet_desc_p[parent_td->isoch_packet_index].isoch_packiet_start_addr
+ +parent_td->isoch_packet_position;
+
+ parent_td->cur_stransfer.buf_size = (parent_td->isoch_packet_desc_p[parent_td->isoch_packet_index].buf_size - parent_td->isoch_packet_position)>MAX_CH_TRANSFER_SIZE
+ ?MAX_CH_TRANSFER_SIZE
+ :parent_td->isoch_packet_desc_p[parent_td->isoch_packet_index].buf_size - parent_td->isoch_packet_position;
+
+ break;
+
+ default:
+ break;
+ }
+}
+
diff --git a/drivers/usb/host/s3c-otg/s3c-otg-transfer-transfer.h b/drivers/usb/host/s3c-otg/s3c-otg-transfer-transfer.h
new file mode 100644
index 0000000..6e1532c
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/s3c-otg-transfer-transfer.h
@@ -0,0 +1,144 @@
+/****************************************************************************
+ * (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+ *
+ * [File Name] : s3c-otg-transfer-transfer.h
+ * [Description] : The Header file defines the external and internal functions of Transfer.
+ * [Author] : Yang Soon Yeal { syatom.yang@samsung.com }
+ * [Department] : System LSI Division/System SW Lab
+ * [Created Date]: 2008/06/03
+ * [Revision History]
+ * (1) 2008/06/03 by Yang Soon Yeal { syatom.yang@samsung.com }
+ * - Created this file and defines functions of Transfer
+ * -# Jul 15,2008 v1.2 by SeungSoo Yang (ss1.yang@samsung.com) \n
+ * : Optimizing for performance \n
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ ****************************************************************************/
+
+#ifndef _TRANSFER_H
+#define _TRANSFER_H
+
+/*
+// ----------------------------------------------------------------------------
+// Include files : None.
+// ----------------------------------------------------------------------------
+*/
+//#include "s3c-otg-common-const.h"
+#include "s3c-otg-common-errorcode.h"
+#include "s3c-otg-common-datastruct.h"
+#include "s3c-otg-hcdi-memory.h"
+#include "s3c-otg-hcdi-kal.h"
+#include "s3c-otg-hcdi-debug.h"
+
+#include "s3c-otg-scheduler-scheduler.h"
+#include "s3c-otg-isr.h"
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+void init_transfer(void);
+void deinit_transfer(struct sec_otghost *otghost);
+
+int issue_transfer(struct sec_otghost *otghost,
+ ed_t *parent_ed,
+ void *call_back_func,
+ void *call_back_param,
+ u32 transfer_flag,
+ bool f_is_standard_dev_req,
+ u32 setup_vir_addr,
+ u32 setup_phy_addr,
+ u32 vir_buf_addr,
+ u32 phy_buf_addr,
+ u32 buf_size,
+ u32 start_frame,
+ u32 isoch_packet_num,
+ isoch_packet_desc_t *isoch_packet_desc,
+ void *td_priv,
+ unsigned int *return_td_addr);
+
+int cancel_transfer(struct sec_otghost *otghost,
+ ed_t *parent_ed,
+ td_t *cancel_td);
+
+int cancel_all_td(struct sec_otghost *otghost, ed_t *parent_ed);
+
+int create_ed(ed_t ** new_ed);
+
+int init_ed(ed_t * init_ed,
+ u8 dev_addr,
+ u8 ep_num,
+ bool f_is_ep_in,
+ u8 dev_speed,
+ u8 ep_type,
+ u16 max_packet_size,
+ u8 multi_count,
+ u8 interval,
+ u32 sched_frame,
+ u8 hub_addr,
+ u8 hub_port,
+ bool f_is_do_split,
+ void *ep);
+
+int delete_ed(struct sec_otghost *otghost, ed_t *delete_ed);
+
+int delete_td(struct sec_otghost *otghost, td_t * delete_td);
+
+int create_isoch_packet_desc( isoch_packet_desc_t **new_isoch_packet_desc,
+ u32 isoch_packet_num);
+
+int delete_isoch_packet_desc( isoch_packet_desc_t *del_isoch_packet_desc,
+ u32 isoch_packet_num);
+
+
+void init_isoch_packet_desc( isoch_packet_desc_t *init_isoch_packet_desc,
+ u32 offset,
+ u32 isoch_packet_size,
+ u32 index);
+
+// NonPeriodicTransfer.c implements.
+
+int init_nonperio_stransfer(bool f_is_standard_dev_req,
+ td_t *parent_td);
+
+void update_nonperio_stransfer(td_t *parent_td);
+
+//PeriodicTransfer.c implements
+
+int init_perio_stransfer( bool f_is_isoch_transfer,
+ td_t *parent_td);
+
+void update_perio_stransfer(td_t *parent_td);
+
+static inline u32 calc_packet_cnt(u32 data_size, u16 max_packet_size)
+{
+ if(data_size != 0)
+ {
+ return (data_size%max_packet_size==0)?data_size/max_packet_size:data_size/max_packet_size+1;
+ }
+ return 1;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
+
diff --git a/drivers/usb/host/s3c-otg/s3c-otg-transferchecker-bulk.c b/drivers/usb/host/s3c-otg/s3c-otg-transferchecker-bulk.c
new file mode 100644
index 0000000..e544f5c
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/s3c-otg-transferchecker-bulk.c
@@ -0,0 +1,720 @@
+/****************************************************************************
+ * (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+ *
+ * [File Name] : BulkTransferChecker.c
+ * [Description] : The Source file implements the external and internal functions of BulkTransferChecker.
+ * [Author] : Yang Soon Yeal { syatom.yang@samsung.com }
+ * [Department] : System LSI Division/System SW Lab
+ * [Created Date]: 2008/06/13
+ * [Revision History]
+ * (1) 2008/06/18 by Yang Soon Yeal { syatom.yang@samsung.com }
+ * - Created this file and implements functions of BulkTransferChecker
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * 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 "s3c-otg-transferchecker-bulk.h"
+#include "s3c-otg-isr.h"
+
+/******************************************************************************/
+/*!
+ * @name u8 process_bulk_transfer(td_t *result_td,
+ hc_info_t *hc_reg_data)
+
+ *
+ * @brief this function processes the result of the Bulk Transfer.
+ * firstly, this function checks the result of the Bulk Transfer.
+ * and according to the result, calls the sub-functions to process the result.
+ *
+ *
+ * @param [IN] result_td -indicates the pointer of the td_t whose channel is interruped.
+ * [IN] hc_reg_data -indicates the interrupt information of the Channel to be interrupted
+ *
+ * @return RE_TRANSMIT -if need to retransmit the result_td.
+ * RE_SCHEDULE -if need to reschedule the result_td.
+ * DE_ALLOCATE -if USB Transfer is completed.
+ * NO_ACTION -if we don't need any action,
+ */
+/******************************************************************************/
+u8 process_bulk_transfer(td_t *result_td,
+ hc_info_t *hc_reg_data)
+{
+ hcintn_t hc_intr_info;
+ u8 return_val=0;
+
+ //we just deal with the interrupts to be unmasked.
+ hc_intr_info.d32 = hc_reg_data->hc_int.d32 & result_td->cur_stransfer.hc_reg.hc_int_msk.d32;
+
+ if(result_td->parent_ed_p->ed_desc.is_ep_in)
+ {
+ if(hc_intr_info.b.chhltd)
+ {
+ return_val = process_chhltd_on_bulk(result_td, hc_reg_data);
+ }
+
+ else if (hc_intr_info.b.ack)
+ {
+ return_val =process_ack_on_bulk(result_td, hc_reg_data);
+ }
+
+ else if (hc_intr_info.b.nak)
+ {
+ return_val =process_nak_on_bulk(result_td, hc_reg_data);
+ }
+
+ else if (hc_intr_info.b.datatglerr)
+ {
+ return_val = process_datatgl_on_bulk(result_td,hc_reg_data);
+ }
+ }
+ else
+ {
+ if(hc_intr_info.b.chhltd)
+ {
+ return_val = process_chhltd_on_bulk(result_td, hc_reg_data);
+
+ }
+
+ else if(hc_intr_info.b.ack)
+ {
+ return_val =process_ack_on_bulk( result_td, hc_reg_data);
+ }
+ }
+
+ return return_val;
+}
+
+/******************************************************************************/
+/*!
+ * @name u8 process_chhltd_on_bulk(td_t *result_td,
+ * hc_info_t *hc_reg_data)
+ *
+ *
+ * @brief this function processes Channel Halt event according to Synopsys OTG Spec.
+ * firstly, this function checks the reason of the Channel Halt, and according to the reason,
+ * calls the sub-functions to process the result.
+ *
+ *
+ * @param [IN] result_td -indicates the pointer of the td_t to be mapped with the uChNum.
+ * [IN] hc_reg_data -indicates the interrupt information of the Channel to be interrupted
+ *
+ * @return RE_TRANSMIT -if need to retransmit the result_td.
+ * RE_SCHEDULE -if need to reschedule the result_td.
+ * DE_ALLOCATE -if USB Transfer is completed.
+ */
+/******************************************************************************/
+u8 process_chhltd_on_bulk(td_t *result_td,
+ hc_info_t *hc_reg_data)
+{
+#if 0
+ if(result_td->parent_ed_p->ed_desc.is_ep_in)
+ {
+ if(hc_reg_data->hc_int.b.xfercompl)
+ {
+ return process_xfercompl_on_bulk( result_td, hc_reg_data);
+ }
+ else if(hc_reg_data->hc_int.b.stall)
+ {
+ return process_stall_on_bulk(result_td, hc_reg_data);
+ }
+ else if(hc_reg_data->hc_int.b.bblerr)
+ {
+ return process_bblerr_on_bulk(result_td, hc_reg_data);
+ }
+ else if(hc_reg_data->hc_int.b.xacterr)
+ {
+ return process_xacterr_on_bulk(result_td, hc_reg_data);
+ }
+ else
+ {
+ //Occure Error State.....
+ clear_ch_intr(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ALL);
+
+ //Mask ack Interrupt..
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ACK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+
+ result_td->err_cnt++;
+ if(result_td->err_cnt == 3)
+ {
+ result_td->error_code = USB_ERR_STATUS_XACTERR;
+ result_td->err_cnt = 0;
+ return DE_ALLOCATE;
+ }
+
+ return RE_TRANSMIT;
+ }
+ }
+ else
+ {
+ if(hc_reg_data->hc_int.b.xfercompl)
+ {
+ return process_xfercompl_on_bulk(result_td, hc_reg_data);
+ }
+ else if(hc_reg_data->hc_int.b.stall)
+ {
+ return process_stall_on_bulk(result_td, hc_reg_data);
+ }
+ else if(hc_reg_data->hc_int.b.xacterr)
+ {
+ return process_xacterr_on_bulk(result_td, hc_reg_data);
+ }
+
+ else if(hc_reg_data->hc_int.b.nak)
+ {
+ return process_nak_on_bulk(result_td, hc_reg_data);
+ }
+ else if(hc_reg_data->hc_int.b.nyet)
+ {
+ return process_nyet_on_bulk(result_td, hc_reg_data);
+ }
+ else
+ {
+ //occur error state...
+ clear_ch_intr(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ALL);
+
+ //Mask ack Interrupt..
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ACK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+
+ result_td->err_cnt++;
+ if(result_td->err_cnt == 3)
+ {
+ result_td->error_code = USB_ERR_STATUS_XACTERR;
+ result_td->err_cnt = 0;
+ return DE_ALLOCATE;
+ }
+
+ return RE_TRANSMIT;
+ }
+
+
+
+ }
+#else
+ if(hc_reg_data->hc_int.b.xfercompl)
+ {
+ return process_xfercompl_on_bulk( result_td, hc_reg_data);
+ }
+ else if(hc_reg_data->hc_int.b.stall)
+ {
+ return process_stall_on_bulk(result_td, hc_reg_data);
+ }
+ else if(hc_reg_data->hc_int.b.bblerr)
+ {
+ return process_bblerr_on_bulk(result_td, hc_reg_data);
+ }
+ else if(hc_reg_data->hc_int.b.xacterr)
+ {
+ return process_xacterr_on_bulk(result_td, hc_reg_data);
+ }
+ else if(hc_reg_data->hc_int.b.nak)
+ {
+ return process_nak_on_bulk(result_td, hc_reg_data);
+ }
+ else if(hc_reg_data->hc_int.b.nyet)
+ {
+ return process_nyet_on_bulk(result_td, hc_reg_data);
+ }
+ else
+ {
+ //occur error state...
+ clear_ch_intr(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ALL);
+
+ //Mask ack Interrupt..
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ACK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+
+ result_td->err_cnt++;
+ if(result_td->err_cnt == 3)
+ {
+ result_td->error_code = USB_ERR_STATUS_XACTERR;
+ result_td->err_cnt = 0;
+ return DE_ALLOCATE;
+ }
+
+ return RE_TRANSMIT;
+ }
+#endif
+ return USB_ERR_SUCCESS;
+
+}
+
+/******************************************************************************/
+/*!
+ * @name u8 process_xfercompl_on_bulk( td_t *result_td,
+ * hc_info_t *hc_reg_data)
+ *
+ *
+ * @brief this function deals with the xfercompl event according to Synopsys OTG Spec.
+ * the procedure of this function is as following
+ * 1. clears all bits of the channel' HCINT by using clear_ch_intr() of S3CIsr.
+ * 2. masks some bit of HCINTMSK
+ * 3. updates the result_td fields
+ * err_cnt/u8/standard_dev_req_info.
+ * 4. updates the result_td->parent_ed_p->ed_status.
+ * BulkDataTgl.
+ * 5. calculates the tranferred size by calling calc_transferred_size() on DATA_STAGE.
+ *
+ * @param [IN] result_td -indicates the pointer of the td_t to be mapped with the uChNum.
+ * [IN] hc_reg_data -indicates the interrupt information of the Channel to be interrupted
+ *
+ * @return USB_ERR_SUCCESS
+ */
+/******************************************************************************/
+u8 process_xfercompl_on_bulk(td_t *result_td,
+ hc_info_t *hc_reg_data)
+{
+ u8 ret_val=0;
+
+ result_td->err_cnt = 0;
+
+ clear_ch_intr(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ALL);
+
+ //Mask ack Interrupt..
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ACK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+
+ result_td->parent_ed_p->ed_status.is_ping_enable =false;
+
+ result_td->transferred_szie += calc_transferred_size(true,result_td, hc_reg_data);
+
+ if(result_td->transferred_szie==result_td->buf_size)
+ {//at IN Transfer, short transfer is accepted.
+ result_td->error_code = USB_ERR_STATUS_COMPLETE;
+ ret_val = DE_ALLOCATE;
+ }
+ else
+ {
+ if(result_td->parent_ed_p->ed_desc.is_ep_in&& hc_reg_data->hc_size.b.xfersize)
+ {
+ if(result_td->transfer_flag&USB_TRANS_FLAG_NOT_SHORT)
+ {
+ result_td->error_code =USB_ERR_STATUS_SHORTREAD;
+ }
+ else
+ {
+ result_td->error_code =USB_ERR_STATUS_COMPLETE;
+ }
+ ret_val = DE_ALLOCATE;
+ }
+ else
+ {
+ ret_val = RE_SCHEDULE;
+ }
+ }
+ update_datatgl(hc_reg_data->hc_size.b.pid, result_td);
+
+ if(hc_reg_data->hc_int.b.nyet)
+ {
+ //at OUT Transfer, we must re-transmit.
+ if(result_td->parent_ed_p->ed_desc.is_ep_in==false)
+ {
+
+ if(result_td->parent_ed_p->ed_desc.dev_speed == HIGH_SPEED_OTG)
+ {
+ result_td->parent_ed_p->ed_status.is_ping_enable = true;
+ }
+ else
+ {
+ result_td->parent_ed_p->ed_status.is_ping_enable = false;
+ }
+ }
+ }
+
+ return ret_val;
+
+}
+
+/******************************************************************************/
+/*!
+ * @name u8 process_ahb_on_bulk(td_t *result_td,
+ * hc_info_t *hc_reg_data)
+ *
+ *
+ * @brief this function deals with theAHB Errorl event according to Synopsys OTG Spec.
+ * this function stop the channel to be executed
+ * TBD....
+ *
+ * @param [IN] result_td -indicates the pointer of the td_t to be mapped with the uChNum.
+ * [IN] hc_reg_data -indicates the interrupt information of the Channel to be interrupted
+ *
+ * @return USB_ERR_SUCCESS
+ */
+/******************************************************************************/
+u8 process_ahb_on_bulk(td_t *result_td,
+ hc_info_t *hc_reg_data)
+{
+ result_td->err_cnt =0;
+ result_td->error_code =USB_ERR_STATUS_AHBERR;
+
+ clear_ch_intr(result_td->cur_stransfer.alloc_chnum, CH_STATUS_AHBErr);
+
+ //Mask ack Interrupt..
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ACK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+
+ // we just calculate the size of the transferred data on Data Stage of Bulk Transfer.
+ result_td->transferred_szie += calc_transferred_size(false,result_td, hc_reg_data);
+ result_td->parent_ed_p->ed_status.is_ping_enable = false;
+
+ return DE_ALLOCATE;
+
+}
+
+/******************************************************************************/
+/*!
+ * @name u8 process_stall_on_bulk(td_t *result_td,
+ * hc_info_t *hc_reg_data)
+ *
+ *
+ * @brief this function deals with theStall event according to Synopsys OTG Spec.
+ * when Stall is occured at Bulk Transfer, we should reset the PID as DATA0
+ *
+ * @param [IN] result_td -indicates the pointer of the td_t to be mapped with the uChNum.
+ * [IN] hc_reg_data -indicates the interrupt information of the Channel to be interrupted
+ *
+ * @return DE_ALLOCATE
+ */
+/******************************************************************************/
+u8 process_stall_on_bulk( td_t * result_td,
+ hc_info_t * hc_reg_data)
+{
+ result_td->err_cnt =0;
+ result_td->error_code =USB_ERR_STATUS_STALL;
+
+ //this channel is stalled, So we don't process another interrupts.
+ clear_ch_intr(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ALL);
+
+ //Mask ack Interrupt..
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ACK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+
+ result_td->parent_ed_p->ed_status.is_ping_enable = false;
+ result_td->transferred_szie += calc_transferred_size(false,result_td, hc_reg_data);
+
+ update_datatgl(DATA0, result_td);
+
+
+ return DE_ALLOCATE;
+}
+
+/******************************************************************************/
+/*!
+ * @name u8 process_nak_on_bulk(td_t *result_td,
+ * hc_info_t *hc_reg_data)
+ *
+ *
+ * @brief this function deals with the nak event according to Synopsys OTG Spec.
+ * nak is occured at OUT/IN Transaction of Data/Status Stage, and is not occured at Setup Stage.
+ * If nak is occured at IN Transaction, this function processes this interrupt as following.
+ * 1. resets the result_td->err_cnt.
+ * 2. masks ack/nak/DaaTglErr bit of HCINTMSK.
+ * 3. clears the nak bit of HCINT
+ * 4. be careful, nak of IN Transaction don't require re-transmit.
+ * If nak is occured at OUT Transaction, this function processes this interrupt as following.
+ * 1. all procedures of IN Transaction are executed.
+ * 2. calculates the size of the transferred data.
+ * 3. if the speed of USB Device is High-Speed, sets the ping protocol.
+ * 4. update the Toggle
+ * at OUT Transaction, this function check whether the speed of USB Device is High-Speed or not.
+ * if USB Device is High-Speed, then
+ * this function sets the ping protocol.
+ *
+ * @param [IN] result_td -indicates the pointer of the td_t to be mapped with the uChNum.
+ * [IN] hc_reg_data -indicates the interrupt information of the Channel to be interrupted
+ *
+ * @return RE_SCHEDULE -if the direction of the Transfer is OUT
+ * NO_ACTION -if the direction of the Transfer is IN
+ */
+/******************************************************************************/
+u8 process_nak_on_bulk(td_t *result_td,
+ hc_info_t *hc_reg_data)
+{
+ result_td->err_cnt = 0;
+
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ACK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+
+ clear_ch_intr(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+
+ //at OUT Transfer, we must re-transmit.
+ if(result_td->parent_ed_p->ed_desc.is_ep_in==false)
+ {
+ result_td->transferred_szie += calc_transferred_size(false,result_td, hc_reg_data);
+
+ if(result_td->parent_ed_p->ed_desc.dev_speed == HIGH_SPEED_OTG)
+ {
+ result_td->parent_ed_p->ed_status.is_ping_enable = true;
+ }
+ else
+ {
+ result_td->parent_ed_p->ed_status.is_ping_enable = false;
+ }
+
+ update_datatgl(hc_reg_data->hc_size.b.pid, result_td);
+
+ return RE_TRANSMIT;
+ }
+ return NO_ACTION;
+
+}
+
+/******************************************************************************/
+/*!
+ * @name u8 process_ack_on_bulk(td_t *result_td,
+ * hc_info_t *hc_reg_data)
+ *
+ *
+ * @brief this function deals with the ack event according to Synopsys OTG Spec.
+ * ack of IN/OUT Transaction don't need any retransmit.
+ * this function just resets result_td->err_cnt and masks ack/nak/DataTgl of HCINTMSK.
+ * finally, this function clears ack bit of HCINT and ed_status.is_ping_enable.
+ *
+ * @param [IN] result_td -indicates the pointer of the td_t to be mapped with the uChNum.
+ * [IN] hc_reg_data -indicates the interrupt information of the Channel to be interrupted
+ *
+ * @return USB_ERR_SUCCESS
+ */
+/******************************************************************************/
+u8 process_ack_on_bulk(td_t *result_td,
+ hc_info_t *hc_reg_data)
+{
+ result_td->err_cnt = 0;
+
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ACK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+
+ clear_ch_intr(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ACK);
+
+ result_td->parent_ed_p->ed_status.is_ping_enable = false;
+
+ return NO_ACTION;
+
+}
+
+/******************************************************************************/
+/*!
+ * @name u8 process_nyet_on_bulk(td_t *result_td,
+ * hc_info_t *hc_reg_data)
+ *
+ *
+ * @brief this function deals with the nyet event according to Synopsys OTG Spec.
+ * nyet is only occured at OUT Transaction.
+ * If nyet is occured at OUT Transaction, this function processes this interrupt as following.
+ * 1. resets the result_td->err_cnt.
+ * 2. masks ack/nak/datatglerr bit of HCINTMSK.
+ * 3. clears the nyet bit of HCINT
+ * 4. calculates the size of the transferred data.
+ * 5. if the speed of USB Device is High-Speed, sets the ping protocol.
+ * 6. update the Data Toggle.
+ * 7. return RE_SCHEDULE to retransmit.
+ *
+ * @param [IN] result_td -indicates the pointer of the td_t to be mapped with the uChNum.
+ * [IN] hc_reg_data -indicates the interrupt information of the Channel to be interrupted
+ *
+ * @return RE_SCHEDULE
+ */
+/******************************************************************************/
+u8 process_nyet_on_bulk(td_t *result_td,
+ hc_info_t *hc_reg_data)
+{
+ if(result_td->parent_ed_p->ed_desc.is_ep_in)
+ {
+ // Error State....
+ return NO_ACTION;
+ }
+
+ result_td->err_cnt = 0;
+
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ACK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+
+ clear_ch_intr(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NYET);
+
+ result_td->transferred_szie += calc_transferred_size(false,result_td, hc_reg_data);
+
+ if(result_td->parent_ed_p->ed_desc.dev_speed == HIGH_SPEED_OTG)
+ {
+ result_td->parent_ed_p->ed_status.is_ping_enable = true;
+ }
+ else
+ {
+ result_td->parent_ed_p->ed_status.is_ping_enable = false;
+ }
+
+ update_datatgl(hc_reg_data->hc_size.b.pid, result_td);
+
+ return RE_TRANSMIT;
+
+}
+
+/******************************************************************************/
+/*!
+ * @name u8 process_xacterr_on_bulk( td_t *result_td,
+ * hc_info_t *hc_reg_data)
+ *
+ *
+ * @brief this function deals with the xacterr event according to Synopsys OTG Spec.
+ * xacterr is occured at OUT/IN Transaction and we should retransmit the USB Transfer
+ * if the Error Counter is less than the RETRANSMIT_THRESHOLD.
+ * the reasons of xacterr is Timeout/CRC error/false EOP.
+ * the procedure to process xacterr is as following.
+ * 1. increses the result_td->err_cnt
+ * 2. check whether the result_td->err_cnt is equal to 3.
+ * 2. unmasks ack/nak/datatglerr bit of HCINTMSK.
+ * 3. clears the xacterr bit of HCINT
+ * 4. calculates the size of the transferred data.
+ * 5. if the speed of USB Device is High-Speed, sets the ping protocol.
+ * 6. update the Data Toggle.
+ *
+ * @param [IN] result_td -indicates the pointer of the td_t to be mapped with the uChNum.
+ * [IN] hc_reg_data -indicates the interrupt information of the Channel to be interrupted
+ *
+ * @return RE_TRANSMIT -if the error count is less than 3
+ * DE_ALLOCATE -if the error count is equal to 3
+ */
+/******************************************************************************/
+u8 process_xacterr_on_bulk( td_t *result_td,
+ hc_info_t *hc_reg_data)
+{
+ u8 ret_val = 0;
+
+ if(result_td->err_cnt<RETRANSMIT_THRESHOLD)
+ {
+ result_td->cur_stransfer.hc_reg.hc_int_msk.d32 |= (CH_STATUS_ACK+CH_STATUS_NAK+CH_STATUS_DataTglErr);
+ ret_val = RE_TRANSMIT;
+ result_td->err_cnt++ ;
+ }
+ else
+ {
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ACK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+ ret_val = DE_ALLOCATE;
+ result_td->err_cnt = 0 ;
+ result_td->error_code = USB_ERR_STATUS_XACTERR;
+ }
+
+ clear_ch_intr(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+
+ result_td->transferred_szie += calc_transferred_size(false,result_td, hc_reg_data);
+
+ if(result_td->parent_ed_p->ed_desc.is_ep_in==false)
+ {
+ if(result_td->parent_ed_p->ed_desc.dev_speed == HIGH_SPEED_OTG)
+ {
+ result_td->parent_ed_p->ed_status.is_ping_enable = true;
+ }
+ else
+ {
+ result_td->parent_ed_p->ed_status.is_ping_enable = false;
+ }
+ }
+
+
+ update_datatgl(hc_reg_data->hc_size.b.pid, result_td);
+
+ return ret_val;
+
+}
+
+/******************************************************************************/
+/*!
+ * @name void process_bblerr_on_bulk(td_t *result_td,
+ * hc_info_t *hc_reg_data)
+ *
+ *
+ * @brief this function deals with the Babble event according to Synopsys OTG Spec.
+ * babble error is occured when the buffer to receive data to be transmit is overflow.
+ * So, babble error can be just occured at IN Transaction.
+ * when Babble Error is occured, we should stop the USB Transfer, and return the fact
+ * to Application.
+ *
+ * @param [IN] result_td -indicates the pointer of the td_t to be mapped with the uChNum.
+ * [IN] hc_reg_data -indicates the interrupt information of the Channel to be interrupted
+ *
+ * @return DE_ALLOCATE
+ */
+/******************************************************************************/
+u8 process_bblerr_on_bulk(td_t *result_td,
+ hc_info_t *hc_reg_data)
+{
+
+ if(!result_td->parent_ed_p->ed_desc.is_ep_in)
+ {
+ return NO_ACTION;
+ }
+
+ result_td->err_cnt =0;
+ result_td->error_code =USB_ERR_STATUS_BBLERR;
+
+ clear_ch_intr(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ALL);
+
+ //Mask ack Interrupt..
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ACK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+
+ result_td->parent_ed_p->ed_status.is_ping_enable =false;
+ result_td->transferred_szie += calc_transferred_size(false, result_td, hc_reg_data);
+
+ return DE_ALLOCATE;
+
+
+}
+
+/******************************************************************************/
+/*!
+ * @name u8 process_datatgl_on_bulk( td_t *result_td,
+ * hc_info_t *hc_reg_data)
+ *
+ *
+ * @brief this function deals with the datatglerr event according to Synopsys OTG Spec.
+ * the datatglerr event is occured at IN Transfer, and the channel is not halted.
+ * this function just resets result_td->err_cnt and masks ack/nak/DataTgl of HCINTMSK.
+ * finally, this function clears datatglerr bit of HCINT.
+ *
+ * @param [IN] result_td -indicates the pointer of the td_t to be mapped with the uChNum.
+ * [IN] hc_reg_data -indicates the interrupt information of the Channel to be interrupted
+ *
+ * @return NO_ACTION
+ */
+/******************************************************************************/
+u8 process_datatgl_on_bulk(td_t *result_td,
+ hc_info_t *hc_reg_data)
+{
+ result_td->err_cnt = 0;
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ACK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+ clear_ch_intr(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+
+ return NO_ACTION;
+
+}
+
+
diff --git a/drivers/usb/host/s3c-otg/s3c-otg-transferchecker-bulk.h b/drivers/usb/host/s3c-otg/s3c-otg-transferchecker-bulk.h
new file mode 100644
index 0000000..e1f84ca
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/s3c-otg-transferchecker-bulk.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+ * (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+ *
+ * [File Name] : BulkTransferChecker.h
+ * [Description] : The Header file defines the external and internal functions of BulkTransferChecker
+ * [Author] : Yang Soon Yeal { syatom.yang@samsung.com }
+ * [Department] : System LSI Division/System SW Lab
+ * [Created Date]: 2008/06/18
+ * [Revision History]
+ * (1) 2008/06/18 by Yang Soon Yeal { syatom.yang@samsung.com }
+ * - Created this file and defines functions of BulkTransferChecker
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ ****************************************************************************/
+
+#ifndef _BULK_TRANSFER_CHECKER_H
+#define _BULK_TRANSFER_CHECKER_H
+
+/*
+// ----------------------------------------------------------------------------
+// Include files : None.
+// ----------------------------------------------------------------------------
+*/
+//#include "s3c-otg-common-typedef.h"
+#include "s3c-otg-common-const.h"
+#include "s3c-otg-common-errorcode.h"
+#include "s3c-otg-common-datastruct.h"
+
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+u8 process_bulk_transfer(td_t *raw_td,
+ hc_info_t *hc_reg_data);
+
+u8 process_xfercompl_on_bulk(td_t *raw_td,
+ hc_info_t *hc_reg_data);
+
+u8 process_chhltd_on_bulk(td_t *raw_td,
+ hc_info_t *hc_reg_data);
+
+u8 process_ahb_on_bulk(td_t *raw_td,
+ hc_info_t *hc_reg_data);
+
+u8 process_stall_on_bulk(td_t *raw_td,
+ hc_info_t *hc_reg_data);
+
+u8 process_nak_on_bulk(td_t *raw_td,
+ hc_info_t *hc_reg_data);
+
+u8 process_ack_on_bulk(td_t *raw_td,
+ hc_info_t *hc_reg_data);
+
+u8 process_nyet_on_bulk(td_t *raw_td,
+ hc_info_t *hc_reg_data);
+
+u8 process_xacterr_on_bulk(td_t *raw_td,
+ hc_info_t *hc_reg_data);
+
+u8 process_bblerr_on_bulk(td_t *raw_td,
+ hc_info_t *hc_reg_data);
+
+u8 process_datatgl_on_bulk(td_t *raw_td,
+ hc_info_t *hc_reg_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
+
diff --git a/drivers/usb/host/s3c-otg/s3c-otg-transferchecker-checker.h b/drivers/usb/host/s3c-otg/s3c-otg-transferchecker-checker.h
new file mode 100644
index 0000000..cefbcaf
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/s3c-otg-transferchecker-checker.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+ * (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+ *
+ * [File Name] : DoneTransferChecker.h
+ * [Description] : The Header file defines the external and internal functions of S3CDoneTransferChecker.
+ * [Author] : Yang Soon Yeal { syatom.yang@samsung.com }
+ * [Department] : System LSI Division/System SW Lab
+ * [Created Date]: 2008/06/12
+ * [Revision History]
+ * (1) 2008/06/12 by Yang Soon Yeal { syatom.yang@samsung.com }
+ * - Created this file and defines functions of S3CDoneTransferChecker
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ ****************************************************************************/
+
+#ifndef _DONE_TRANSFER_CHECKER_H
+#define _DONE_TRANSFER_CHECKER_H
+
+/*
+// ----------------------------------------------------------------------------
+// Include files : None.
+// ----------------------------------------------------------------------------
+*/
+
+//#include "s3c-otg-common-typedef.h"
+#include "s3c-otg-common-const.h"
+#include "s3c-otg-common-errorcode.h"
+#include "s3c-otg-common-datastruct.h"
+
+#include "s3c-otg-hcdi-debug.h"
+
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
+
+
+
+
+
+
diff --git a/drivers/usb/host/s3c-otg/s3c-otg-transferchecker-common.c b/drivers/usb/host/s3c-otg/s3c-otg-transferchecker-common.c
new file mode 100644
index 0000000..689d379
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/s3c-otg-transferchecker-common.c
@@ -0,0 +1,238 @@
+/****************************************************************************
+ * (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+ *
+ * [File Name] : CommonTransferChecker.c
+ * [Description] : The Source file implements the external and internal functions of CommonTransferChecker.
+ * [Author] : Yang Soon Yeal { syatom.yang@samsung.com }
+ * [Department] : System LSI Division/System SW Lab
+ * [Created Date]: 2009/01/12
+ * [Revision History]
+ * (1) 2008/06/12 by Yang Soon Yeal { syatom.yang@samsung.com }
+ * - Created this file and implements functions of CommonTransferChecker
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * 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 "s3c-otg-transferchecker-common.h"
+
+/******************************************************************************/
+/*!
+ * @name int init_done_transfer_checker(void)
+ *
+ * @brief this function initiates S3CDoneTransferChecker Module.
+ *
+ *
+ * @param void
+ *
+ * @return void
+ */
+/******************************************************************************/
+//ss1
+/*void init_done_transfer_checker(void)
+{
+ return USB_ERR_SUCCESS;
+}*/
+
+/******************************************************************************/
+/*!
+ * @name void do_transfer_checker(struct sec_otghost *otghost)
+ *
+ * @brief this function processes the result of USB Transfer. So, do_transfer_checker fistly
+ * check which channel occurs OTG Interrupt and gets the status information of the channel.
+ * do_transfer_checker requests the information of td_t to S3CScheduler.
+ * To process the interrupt of the channel, do_transfer_checker calls the sub-modules of
+ * S3CDoneTransferChecker, for example, ControlTransferChecker, BulkTransferChecker.
+ * according to the process result of the channel interrupt, do_transfer_checker decides
+ * the USB Transfer will be done or retransmitted.
+ *
+ *
+ * @param void
+ *
+ * @return void
+ */
+/*******************************************************************************/
+void do_transfer_checker (struct sec_otghost *otghost)
+__releases(&otghost->lock)
+__acquires(&otghost->lock)
+{
+ u32 hc_intr = 0;
+ u32 hc_intr_msk = 0;
+ u8 do_try_cnt = 0;
+
+ hc_info_t ch_info;
+ u32 td_addr = 0;
+ td_t *done_td = {0};
+ u8 proc_result = 0;
+
+ //by ss1
+ otg_mem_set((void *)&ch_info, 0, sizeof(hc_info_t));
+
+ // Get value of HAINT...
+ get_intr_ch(&hc_intr,&hc_intr_msk);
+
+start_do_transfer_checker:
+
+ while(do_try_cnt<MAX_CH_NUMBER) {
+ //checks the channel number to be masked or not.
+ if(!(hc_intr & hc_intr_msk & (1<<do_try_cnt))) {
+ do_try_cnt++;
+ goto start_do_transfer_checker;
+ }
+
+ //Gets the address of the td_t to have the channel to be interrupted.
+ if(get_td_info(do_try_cnt, &td_addr) == USB_ERR_SUCCESS) {
+
+ done_td = (td_t *)td_addr;
+
+ if(do_try_cnt != done_td->cur_stransfer.alloc_chnum) {
+ do_try_cnt++;
+ goto start_do_transfer_checker;
+ }
+ }
+ else {
+ do_try_cnt++;
+ goto start_do_transfer_checker;
+ }
+
+ //Gets the informationof channel to be interrupted.
+ get_ch_info(&ch_info,do_try_cnt);
+
+ switch(done_td->parent_ed_p->ed_desc.endpoint_type) {
+ case CONTROL_TRANSFER:
+ proc_result = process_control_transfer(done_td, &ch_info);
+ break;
+ case BULK_TRANSFER:
+ proc_result = process_bulk_transfer(done_td, &ch_info);
+ break;
+ case INT_TRANSFER:
+ proc_result = process_intr_transfer(done_td, &ch_info);
+ break;
+ case ISOCH_TRANSFER:
+ /* proc_result = ProcessIsochTransfer(done_td, &ch_info); */
+ break;
+ default:break;
+ }
+
+ if((proc_result == RE_TRANSMIT) || (proc_result == RE_SCHEDULE)) {
+ done_td->parent_ed_p->ed_status.is_in_transferring = false;
+ done_td->is_transfer_done = false;
+ done_td->is_transferring = false;
+
+ if(done_td->parent_ed_p->ed_desc.endpoint_type == CONTROL_TRANSFER ||
+ done_td->parent_ed_p->ed_desc.endpoint_type==BULK_TRANSFER) {
+ update_nonperio_stransfer(done_td);
+ }
+ else {
+ update_perio_stransfer(done_td);
+ }
+
+ if(proc_result == RE_TRANSMIT) {
+ retransmit(otghost, done_td);
+ }
+ else {
+ reschedule(done_td);
+ }
+ }
+
+ else if(proc_result==DE_ALLOCATE) {
+ done_td->parent_ed_p->ed_status.is_in_transferring = false;
+ done_td->parent_ed_p->ed_status.in_transferring_td = 0;
+ done_td->is_transfer_done = true;
+ done_td->is_transferring = false;
+
+ spin_unlock_otg(&otghost->lock);
+ otg_usbcore_giveback( done_td);
+ spin_lock_otg(&otghost->lock);
+ release_trans_resource(otghost, done_td);
+ }
+ else { //NO_ACTION....
+ done_td->parent_ed_p->ed_status.is_in_transferring = true;
+ done_td->parent_ed_p->ed_status.in_transferring_td = (u32)done_td;
+ done_td->is_transfer_done = false;
+ done_td->is_transferring = true;
+ }
+ do_try_cnt++;
+ }
+ // Complete to process the Channel Interrupt.
+ // So. we now start to scheduler of S3CScheduler.
+ do_schedule(otghost);
+}
+
+
+int release_trans_resource(struct sec_otghost *otghost, td_t *done_td)
+{
+ //remove the pDeallocateTD from parent_ed_p.
+ otg_list_pop(&done_td->td_list_entry);
+ done_td->parent_ed_p->num_td--;
+
+ //Call deallocate to release the channel and bandwidth resource of S3CScheduler.
+ deallocate(done_td);
+ delete_td(otghost, done_td);
+ return USB_ERR_SUCCESS;
+}
+
+u32 calc_transferred_size(bool f_is_complete, td_t *td, hc_info_t *hc_info)
+{
+ if(f_is_complete) {
+ if(td->parent_ed_p->ed_desc.is_ep_in) {
+ return td->cur_stransfer.buf_size - hc_info->hc_size.b.xfersize;
+ }
+ else {
+ return td->cur_stransfer.buf_size;
+ }
+ }
+ else {
+ return (td->cur_stransfer.packet_cnt - hc_info->hc_size.b.pktcnt)*td->parent_ed_p->ed_desc.max_packet_size;
+ }
+}
+
+void update_frame_number(td_t *pResultTD)
+{
+ u32 cur_frame_num=0;
+
+ if(pResultTD->parent_ed_p->ed_desc.endpoint_type == CONTROL_TRANSFER ||
+ pResultTD->parent_ed_p->ed_desc.endpoint_type == BULK_TRANSFER) {
+ return;
+ }
+
+ pResultTD->parent_ed_p->ed_desc.sched_frame+= pResultTD->parent_ed_p->ed_desc.interval;
+ pResultTD->parent_ed_p->ed_desc.sched_frame &= HFNUM_MAX_FRNUM;
+
+ cur_frame_num = oci_get_frame_num();
+ if(((cur_frame_num - pResultTD->parent_ed_p->ed_desc.sched_frame)&HFNUM_MAX_FRNUM) <= (HFNUM_MAX_FRNUM>>1)) {
+ pResultTD->parent_ed_p->ed_desc.sched_frame = cur_frame_num;
+ }
+}
+
+void update_datatgl(u8 ubCurDataTgl, td_t *td)
+{
+ switch(td->parent_ed_p->ed_desc.endpoint_type) {
+ case CONTROL_TRANSFER:
+ if(td->standard_dev_req_info.conrol_transfer_stage == DATA_STAGE) {
+ td->parent_ed_p->ed_status.control_data_tgl.data_tgl = ubCurDataTgl;
+ }
+ break;
+ case BULK_TRANSFER:
+ case INT_TRANSFER:
+ td->parent_ed_p->ed_status.data_tgl = ubCurDataTgl;
+ break;
+
+ case ISOCH_TRANSFER:
+ break;
+ default:break;
+ }
+}
diff --git a/drivers/usb/host/s3c-otg/s3c-otg-transferchecker-common.h b/drivers/usb/host/s3c-otg/s3c-otg-transferchecker-common.h
new file mode 100644
index 0000000..2ea05b8
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/s3c-otg-transferchecker-common.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+ * (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+ *
+ * [File Name] : CommonTransferChecker.h
+ * [Description] : The Header file defines the external and internal functions of CommonTransferChecker.
+ * [Author] : Yang Soon Yeal { syatom.yang@samsung.com }
+ * [Department] : System LSI Division/System SW Lab
+ * [Created Date]: 2008/06/12
+ * [Revision History]
+ * (1) 2008/06/12 by Yang Soon Yeal { syatom.yang@samsung.com }
+ * - Created this file and defines functions of CommonTransferChecker
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ ****************************************************************************/
+
+#ifndef _COMMON_TRANSFER_CHECKER_H
+#define _COMMON_TRANSFER_CHECKER_H
+
+/*
+// ----------------------------------------------------------------------------
+// Include files : None.
+// ----------------------------------------------------------------------------
+*/
+
+#include "s3c-otg-common-common.h"
+//#include "s3c-otg-common-const.h"
+#include "s3c-otg-common-errorcode.h"
+#include "s3c-otg-common-datastruct.h"
+#include "s3c-otg-common-regdef.h"
+#include "s3c-otg-transfer-transfer.h"
+
+#include "s3c-otg-hcdi-debug.h"
+#include "s3c-otg-hcdi-memory.h"
+#include "s3c-otg-scheduler-scheduler.h"
+#include "s3c-otg-isr.h"
+#include "s3c-otg-transferchecker-control.h"
+#include "s3c-otg-transferchecker-bulk.h"
+#include "s3c-otg-transferchecker-interrupt.h"
+//#include "s3c-otg-transferchecker-iso.h"
+
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+//void init_done_transfer_checker (void);
+void do_transfer_checker (struct sec_otghost *otghost);
+int release_trans_resource(struct sec_otghost *otghost, td_t *done_td);
+u32 calc_transferred_size(bool f_is_complete,
+ td_t *td,
+ hc_info_t *hc_info);
+void update_frame_number(td_t *result_td);
+void update_datatgl(u8 cur_data_tgl,
+ td_t *td);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
+
+
diff --git a/drivers/usb/host/s3c-otg/s3c-otg-transferchecker-control.c b/drivers/usb/host/s3c-otg/s3c-otg-transferchecker-control.c
new file mode 100644
index 0000000..863f951
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/s3c-otg-transferchecker-control.c
@@ -0,0 +1,698 @@
+/****************************************************************************
+ * (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+ *
+ * [File Name] : ControlTransferChecker.c
+ * [Description] : The Source file implements the external and internal functions of ControlTransferChecker.
+ * [Author] : Yang Soon Yeal { syatom.yang@samsung.com }
+ * [Department] : System LSI Division/System SW Lab
+ * [Created Date]: 2009/02/10
+ * [Revision History]
+ * (1) 2008/06/13 by Yang Soon Yeal { syatom.yang@samsung.com }
+ * - Created this file and implements functions of ControlTransferChecker
+ * (2) 2008/06/18 by Yang Soon Yeal { syatom.yang@samsung.com }
+ * - Completed to implement ControlTransferChecker.c v1.0
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * 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 "s3c-otg-transferchecker-control.h"
+#include "s3c-otg-isr.h"
+
+
+
+/******************************************************************************/
+/*!
+ * @name u8 process_control_transfer(td_t *result_td,
+ hc_info_t *hc_reg_data)
+
+ *
+ * @brief this function processes the result of the Control Transfer.
+ * firstly, this function checks the result the Control Transfer.
+ * and according to the result, calls the sub-functions to process the result.
+ *
+ *
+ * @param [IN] result_td -indicates the pointer of the td_t to be mapped with the uChNum.
+ * [IN] ubChNum -indicates the number of the channel to be interrupted.
+ * [IN] hc_reg_data -indicates the interrupt information of the Channel to be interrupted
+ *
+ * @return RE_TRANSMIT -if need to retransmit the result_td.
+ * RE_SCHEDULE -if need to reschedule the result_td.
+ * DE_ALLOCATE -if USB Transfer is completed.
+ */
+/******************************************************************************/
+u8 process_control_transfer(td_t *result_td,
+ hc_info_t *hc_reg_data)
+{
+ hcintn_t hcintr_info;
+ u8 ret_val=0;
+
+ //we just deal with the interrupts to be unmasked.
+ hcintr_info.d32 = hc_reg_data->hc_int.d32&result_td->cur_stransfer.hc_reg.hc_int_msk.d32;
+
+ if(result_td->parent_ed_p->ed_desc.is_ep_in)
+ {
+ if(hcintr_info.b.chhltd)
+ {
+ ret_val = process_chhltd_on_control(result_td, hc_reg_data);
+ }
+
+ else if (hcintr_info.b.ack)
+ {
+ ret_val =process_ack_on_control(result_td, hc_reg_data);
+ }
+
+ else if (hcintr_info.b.nak)
+ {
+ ret_val =process_nak_on_control(result_td, hc_reg_data);
+ }
+
+ else if (hcintr_info.b.datatglerr)
+ {
+ ret_val = process_datatgl_on_control(result_td,hc_reg_data);
+ }
+ }
+ else
+ {
+ if(hcintr_info.b.chhltd)
+ {
+ ret_val = process_chhltd_on_control(result_td, hc_reg_data);
+ }
+
+ else if(hcintr_info.b.ack)
+ {
+ ret_val =process_ack_on_control( result_td, hc_reg_data);
+
+ }
+ }
+
+ return ret_val;
+}
+
+/******************************************************************************/
+/*!
+ * @name u8 process_chhltd_on_control( td_t *result_td,
+ * hc_info_t *hc_reg_data)
+ *
+ *
+ * @brief this function processes Channel Halt event according to Synopsys OTG Spec.
+ * firstly, this function checks the reason of the Channel Halt, and according to the reason,
+ * calls the sub-functions to process the result.
+ *
+ *
+ * @param [IN] result_td -indicates the pointer of the td_t to be mapped with the uChNum.
+ * [IN] hc_reg_data -indicates the interrupt information of the Channel to be interrupted
+ *
+ * @return RE_TRANSMIT -if need to retransmit the result_td.
+ * RE_SCHEDULE -if need to reschedule the result_td.
+ * DE_ALLOCATE -if USB Transfer is completed.
+ */
+/******************************************************************************/
+u8 process_chhltd_on_control( td_t *result_td,
+ hc_info_t *hc_reg_data)
+{
+ if(hc_reg_data->hc_int.b.xfercompl)
+ {
+ return process_xfercompl_on_control( result_td, hc_reg_data);
+ }
+ else if(hc_reg_data->hc_int.b.stall)
+ {
+ return process_stall_on_control(result_td, hc_reg_data);
+ }
+ else if(hc_reg_data->hc_int.b.bblerr)
+ {
+ return process_bblerr_on_control(result_td, hc_reg_data);
+ }
+ else if(hc_reg_data->hc_int.b.xacterr)
+ {
+ return process_xacterr_on_control(result_td, hc_reg_data);
+ }
+ else if(hc_reg_data->hc_int.b.nak)
+ {
+ return process_nak_on_control(result_td, hc_reg_data);
+ }
+ else if(hc_reg_data->hc_int.b.nyet)
+ {
+ return process_nyet_on_control(result_td, hc_reg_data);
+ }
+ else
+ {
+
+ //Occure Error State.....
+ clear_ch_intr(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ALL);
+
+ //Mask ack Interrupt..
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ACK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+ result_td->err_cnt++;
+ if(result_td->err_cnt == 3)
+ {
+ result_td->error_code = USB_ERR_STATUS_XACTERR;
+ result_td->err_cnt = 0;
+ return DE_ALLOCATE;
+ }
+ return RE_TRANSMIT;
+ }
+ return USB_ERR_SUCCESS;
+}
+
+/******************************************************************************/
+/*!
+ * @name u8 process_xfercompl_on_control(td_t *result_td,
+ * hc_info_t *hc_reg_data)
+ *
+ *
+ * @brief this function deals with the xfercompl event according to Synopsys OTG Spec.
+ * the procedure of this function is as following
+ * 1. clears all bits of the channel' HCINT by using clear_ch_intr() of S3CIsr.
+ * 2. masks some bit of HCINTMSK
+ * 3. updates the result_td fields
+ * err_cnt/u8/standard_dev_req_info.
+ * 4. updates the result_td->parent_ed_p->ed_status.
+ * control_data_tgl.
+ * 5. calculates the tranferred size by calling calc_transferred_size() on DATA_STAGE.
+ *
+ * @param [IN] result_td -indicates the pointer of the td_t to be mapped with the uChNum.
+ * [IN] hc_reg_data -indicates the interrupt information of the Channel to be interrupted
+ *
+ * @return USB_ERR_SUCCESS
+ */
+/******************************************************************************/
+u8 process_xfercompl_on_control(td_t *result_td, hc_info_t *hc_reg_data)
+{
+ u8 ret_val = 0;
+
+ result_td->err_cnt = 0;
+
+ clear_ch_intr(result_td->cur_stransfer.alloc_chnum,CH_STATUS_ALL);
+ //Mask ack Interrupt..
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ACK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+
+ result_td->parent_ed_p->ed_status.is_ping_enable = false;
+
+ switch(result_td->standard_dev_req_info.conrol_transfer_stage) {
+ case SETUP_STAGE:
+ if(result_td->standard_dev_req_info.is_data_stage) {
+ result_td->standard_dev_req_info.conrol_transfer_stage = DATA_STAGE;
+ }
+ else {
+ result_td->standard_dev_req_info.conrol_transfer_stage = STATUS_STAGE;
+ }
+ ret_val = RE_TRANSMIT;
+
+ break;
+
+ case DATA_STAGE:
+
+ result_td->transferred_szie += calc_transferred_size(true,result_td, hc_reg_data);
+
+ /* at IN Transfer, short transfer is accepted. */
+ if(result_td->transferred_szie==result_td->buf_size) {
+ result_td->standard_dev_req_info.conrol_transfer_stage =STATUS_STAGE;
+ result_td->error_code = USB_ERR_STATUS_COMPLETE;
+ }
+ else {
+ if(result_td->parent_ed_p->ed_desc.is_ep_in&& hc_reg_data->hc_size.b.xfersize) {
+ if(result_td->transfer_flag&USB_TRANS_FLAG_NOT_SHORT) {
+ result_td->error_code = USB_ERR_STATUS_SHORTREAD;
+ result_td->standard_dev_req_info.conrol_transfer_stage=STATUS_STAGE;
+ }
+ else {
+ result_td->error_code = USB_ERR_STATUS_COMPLETE;
+ result_td->standard_dev_req_info.conrol_transfer_stage =STATUS_STAGE;
+ }
+ }
+ else { // the Data Stage is not completed. So we need to continue Data Stage.
+ result_td->standard_dev_req_info.conrol_transfer_stage = DATA_STAGE;
+ update_datatgl(hc_reg_data->hc_size.b.pid, result_td);
+ }
+ }
+
+ if(hc_reg_data->hc_int.b.nyet) {
+ /* at OUT Transfer, we must re-transmit. */
+ if(result_td->parent_ed_p->ed_desc.is_ep_in==false) {
+ if(result_td->parent_ed_p->ed_desc.dev_speed == HIGH_SPEED_OTG) {
+ result_td->parent_ed_p->ed_status.is_ping_enable = true;
+ }
+ else {
+ result_td->parent_ed_p->ed_status.is_ping_enable = false;
+ }
+ }
+ }
+ ret_val = RE_TRANSMIT;
+ break;
+
+ case STATUS_STAGE:
+ result_td->standard_dev_req_info.conrol_transfer_stage = COMPLETE_STAGE;
+
+ if(hc_reg_data->hc_int.b.nyet) {
+ //at OUT Transfer, we must re-transmit.
+ if(result_td->parent_ed_p->ed_desc.is_ep_in==false) {
+ if(result_td->parent_ed_p->ed_desc.dev_speed == HIGH_SPEED_OTG) {
+ result_td->parent_ed_p->ed_status.is_ping_enable = true;
+ }
+ else {
+ result_td->parent_ed_p->ed_status.is_ping_enable = false;
+ }
+ }
+ }
+
+ ret_val = DE_ALLOCATE;
+ break;
+
+ default:
+ break;
+ }
+
+ return ret_val;
+}
+
+/******************************************************************************/
+/*!
+ * @name u8 process_ahb_on_control( td_t *result_td,
+ * hc_info_t *hc_reg_data)
+ *
+ *
+ * @brief this function deals with theAHB Errorl event according to Synopsys OTG Spec.
+ * this function stop the channel to be executed
+ *
+ * @param [IN] result_td -indicates the pointer of the td_t to be mapped with the uChNum.
+ * [IN] hc_reg_data -indicates the interrupt information of the Channel to be interrupted
+ *
+ * @return DE_ALLOCATE
+ */
+/******************************************************************************/
+u8 process_ahb_on_control( td_t *result_td,
+ hc_info_t *hc_reg_data)
+{
+ result_td->err_cnt =0;
+ result_td->error_code =USB_ERR_STATUS_AHBERR;
+
+ clear_ch_intr(result_td->cur_stransfer.alloc_chnum, CH_STATUS_AHBErr);
+
+ //Mask ack Interrupt..
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ACK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+
+ // we just calculate the size of the transferred data on Data Stage of Control Transfer.
+ if(result_td->standard_dev_req_info.conrol_transfer_stage == DATA_STAGE)
+ {
+ result_td->transferred_szie += calc_transferred_size(false,result_td, hc_reg_data);
+ }
+
+ return DE_ALLOCATE;
+
+}
+
+/******************************************************************************/
+/*!
+ * @name u8 process_stall_on_control( td_t *result_td,
+ * hc_info_t *hc_reg_data)
+ *
+ *
+ * @brief this function deals with theStall event according to Synopsys OTG Spec.
+ * but USB2.0 Spec don't permit the Stall on Setup Stage of Control Transfer.
+ *
+ * @param [IN] result_td -indicates the pointer of the td_t to be mapped with the uChNum.
+ * [IN] hc_reg_data -indicates the interrupt information of the Channel to be interrupted
+ *
+ * @return DE_ALLOCATE
+ */
+/******************************************************************************/
+u8 process_stall_on_control( td_t *result_td,
+ hc_info_t *hc_reg_data)
+{
+ result_td->err_cnt =0;
+ result_td->error_code =USB_ERR_STATUS_STALL;
+
+ clear_ch_intr(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ALL);
+
+ //Mask ack Interrupt..
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ACK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+
+ result_td->parent_ed_p->ed_status.is_ping_enable = false;
+
+ // we just calculate the size of the transferred data on Data Stage of Control Transfer.
+ if(result_td->standard_dev_req_info.conrol_transfer_stage == DATA_STAGE)
+ {
+ result_td->transferred_szie += calc_transferred_size(false,result_td, hc_reg_data);
+ }
+
+ return DE_ALLOCATE;
+}
+
+/******************************************************************************/
+/*!
+ * @name u8 process_nak_on_control( td_t *result_td,
+ * hc_info_t *hc_reg_data)
+ *
+ *
+ * @brief this function deals with the nak event according to Synopsys OTG Spec.
+ * nak is occured at OUT/IN Transaction of Data/Status Stage, and is not occured at Setup Stage.
+ * If nak is occured at IN Transaction, this function processes this interrupt as following.
+ * 1. resets the result_td->err_cnt.
+ * 2. masks ack/nak/DaaTglErr bit of HCINTMSK.
+ * 3. clears the nak bit of HCINT
+ * 4. be careful, nak of IN Transaction don't require re-transmit.
+ * If nak is occured at OUT Transaction, this function processes this interrupt as following.
+ * 1. all procedures of IN Transaction are executed.
+ * 2. calculates the size of the transferred data.
+ * 3. if the speed of USB Device is High-Speed, sets the ping protocol.
+ * 4. update the Toggle
+ * at OUT Transaction, this function check whether the speed of USB Device is High-Speed or not.
+ * if USB Device is High-Speed, then
+ * this function sets the ping protocol.
+ *
+ * @param [IN] result_td -indicates the pointer of the td_t to be mapped with the uChNum.
+ * [IN] hc_reg_data -indicates the interrupt information of the Channel to be interrupted
+ *
+ * @return RE_SCHEDULE
+ */
+/******************************************************************************/
+u8 process_nak_on_control( td_t *result_td,
+ hc_info_t *hc_reg_data)
+{
+ result_td->err_cnt = 0;
+
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ACK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+ clear_ch_intr(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+
+ //at OUT Transfer, we must re-transmit.
+ if(result_td->parent_ed_p->ed_desc.is_ep_in==false)
+ {
+ result_td->transferred_szie += calc_transferred_size(false,result_td, hc_reg_data);
+
+ update_datatgl(hc_reg_data->hc_size.b.pid, result_td);
+ }
+
+ if(result_td->parent_ed_p->ed_desc.dev_speed == HIGH_SPEED_OTG)
+ {
+ if(result_td->standard_dev_req_info.conrol_transfer_stage == DATA_STAGE)
+ {
+ if(result_td->parent_ed_p->ed_desc.is_ep_in==false)
+ {
+ result_td->parent_ed_p->ed_status.is_ping_enable = true;
+ }
+ }
+ else if(result_td->standard_dev_req_info.conrol_transfer_stage == STATUS_STAGE)
+ {
+ if(result_td->parent_ed_p->ed_desc.is_ep_in==true)
+ {
+ result_td->parent_ed_p->ed_status.is_ping_enable = true;
+ }
+ }
+ else
+ {
+ result_td->parent_ed_p->ed_status.is_ping_enable = false;
+ }
+
+ }
+
+ return RE_SCHEDULE;
+
+
+}
+
+/******************************************************************************/
+/*!
+ * @name u8 process_ack_on_control( td_t *result_td,
+ * hc_info_t *hc_reg_data)
+ *
+ *
+ * @brief this function deals with the ack event according to Synopsys OTG Spec.
+ * ack of IN/OUT Transaction don't need any retransmit.
+ * this function just resets result_td->err_cnt and masks ack/nak/DataTgl of HCINTMSK.
+ * finally, this function clears ack bit of HCINT.
+ *
+ * @param [IN] result_td -indicates the pointer of the td_t to be mapped with the uChNum.
+ * [IN] hc_reg_data -indicates the interrupt information of the Channel to be interrupted
+ *
+ * @return NO_ACTION
+ */
+/******************************************************************************/
+u8 process_ack_on_control(td_t *result_td,
+ hc_info_t *hc_reg_data)
+{
+ result_td->err_cnt = 0;
+
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ACK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+ clear_ch_intr(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ACK);
+
+ result_td->parent_ed_p->ed_status.is_ping_enable =false;
+
+ return NO_ACTION;
+
+}
+
+/******************************************************************************/
+/*!
+ * @name u8 process_nyet_on_control(td_t *result_td,
+ * hc_info_t *hc_reg_data)
+ *
+ *
+ * @brief this function deals with the nyet event according to Synopsys OTG Spec.
+ * nyet is occured at OUT Transaction of Data/Status Stage, and is not occured at Setup Stage.
+ * If nyet is occured at OUT Transaction, this function processes this interrupt as following.
+ * 1. resets the result_td->err_cnt.
+ * 2. masks ack/nak/datatglerr bit of HCINTMSK.
+ * 3. clears the nyet bit of HCINT
+ * 4. calculates the size of the transferred data.
+ * 5. if the speed of USB Device is High-Speed, sets the ping protocol.
+ * 6. update the Data Toggle.
+ *
+ * @param [IN] result_td -indicates the pointer of the td_t to be mapped with the uChNum.
+ * [IN] hc_reg_data -indicates the interrupt information of the Channel to be interrupted
+ *
+ * @return RE_SCHEDULE
+ */
+/******************************************************************************/
+u8 process_nyet_on_control(td_t *result_td,
+ hc_info_t *hc_reg_data)
+{
+ result_td->err_cnt = 0;
+
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ACK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+ clear_ch_intr(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NYET);
+
+ result_td->transferred_szie += calc_transferred_size(false,result_td, hc_reg_data);
+
+ if(result_td->parent_ed_p->ed_desc.dev_speed == HIGH_SPEED_OTG)
+ {
+ if(result_td->standard_dev_req_info.conrol_transfer_stage == DATA_STAGE)
+ {
+ if(result_td->parent_ed_p->ed_desc.is_ep_in==false)
+ {
+ result_td->parent_ed_p->ed_status.is_ping_enable = true;
+ }
+ }
+ else if(result_td->standard_dev_req_info.conrol_transfer_stage == STATUS_STAGE)
+ {
+ if(result_td->parent_ed_p->ed_desc.is_ep_in==true)
+ {
+ result_td->parent_ed_p->ed_status.is_ping_enable = true;
+ }
+ }
+ else
+ {
+ result_td->parent_ed_p->ed_status.is_ping_enable = false;
+ }
+
+ }
+
+ update_datatgl(hc_reg_data->hc_size.b.pid, result_td);
+
+ return RE_SCHEDULE;
+}
+
+/******************************************************************************/
+/*!
+ * @name u8 process_xacterr_on_control( td_t *result_td,
+ * hc_info_t *hc_reg_data)
+ *
+ *
+ * @brief this function deals with the xacterr event according to Synopsys OTG Spec.
+ * xacterr is occured at OUT/IN Transaction of Data/Status Stage, and is not occured at Setup Stage.
+ * if Timeout/CRC error/false EOP is occured, then xacterr is occured.
+ * the procedure to process xacterr is as following.
+ * 1. increses the result_td->err_cnt
+ * 2. check whether the result_td->err_cnt is equal to 3.
+ * 2. unmasks ack/nak/datatglerr bit of HCINTMSK.
+ * 3. clears the xacterr bit of HCINT
+ * 4. calculates the size of the transferred data.
+ * 5. if the speed of USB Device is High-Speed, sets the ping protocol.
+ * 6. update the Data Toggle.
+ *
+ * @param [IN] result_td -indicates the pointer of the td_t to be mapped with the uChNum.
+ * [IN] hc_reg_data -indicates the interrupt information of the Channel to be interrupted
+ *
+ * @return RE_TRANSMIT -if the Error Counter is less than RETRANSMIT_THRESHOLD
+ * DE_ALLOCATE -if the Error Counter is equal to RETRANSMIT_THRESHOLD
+ */
+/******************************************************************************/
+u8 process_xacterr_on_control(td_t *result_td,
+ hc_info_t *hc_reg_data)
+{
+ u8 ret_val=0;
+
+ if(result_td->err_cnt<RETRANSMIT_THRESHOLD)
+ {
+ result_td->cur_stransfer.hc_reg.hc_int_msk.d32 |= (CH_STATUS_ACK+CH_STATUS_NAK+CH_STATUS_DataTglErr);
+ ret_val = RE_TRANSMIT;
+ unmask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ACK);
+ unmask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+ unmask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+ result_td->err_cnt++ ;
+ }
+ else
+ {
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ACK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+ ret_val = DE_ALLOCATE;
+ result_td->err_cnt = 0 ;
+ result_td->error_code = USB_ERR_STATUS_XACTERR;
+ }
+
+ clear_ch_intr(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+
+ if(result_td->standard_dev_req_info.conrol_transfer_stage == DATA_STAGE)
+ {
+ result_td->transferred_szie += calc_transferred_size(false,result_td, hc_reg_data);
+
+ }
+
+ if(result_td->parent_ed_p->ed_desc.dev_speed == HIGH_SPEED_OTG)
+ {
+ if(result_td->standard_dev_req_info.conrol_transfer_stage == DATA_STAGE)
+ {
+ if(result_td->parent_ed_p->ed_desc.is_ep_in==false)
+ {
+ result_td->parent_ed_p->ed_status.is_ping_enable = true;
+ }
+ }
+ else if(result_td->standard_dev_req_info.conrol_transfer_stage == STATUS_STAGE)
+ {
+ if(result_td->parent_ed_p->ed_desc.is_ep_in==true)
+ {
+ result_td->parent_ed_p->ed_status.is_ping_enable = true;
+ }
+ }
+ else
+ {
+ result_td->parent_ed_p->ed_status.is_ping_enable = false;
+ }
+
+
+ }
+
+
+
+ update_datatgl(hc_reg_data->hc_size.b.pid, result_td);
+
+ return ret_val;
+
+}
+
+/******************************************************************************/
+/*!
+ * @name void process_bblerr_on_control( td_t *result_td,
+ * hc_info_t *hc_reg_data)
+ *
+ *
+ * @brief this function deals with the Babble event according to Synopsys OTG Spec.
+ * babble error can be just occured at IN Transaction. So if the direction of transfer is
+ * OUT, this function return Error Code.
+ *
+ * @param [IN] result_td -indicates the pointer of the td_t to be mapped with the uChNum.
+ * [IN] hc_reg_data -indicates the interrupt information of the Channel to be interrupted
+ *
+ * @return DE_ALLOCATE
+ * NO_ACTION -if the direction is OUT
+ */
+/******************************************************************************/
+u8 process_bblerr_on_control( td_t *result_td,
+ hc_info_t *hc_reg_data)
+{
+
+ if(!result_td->parent_ed_p->ed_desc.is_ep_in)
+ {
+ return NO_ACTION;
+ }
+
+ result_td->err_cnt = 0;
+ result_td->error_code =USB_ERR_STATUS_BBLERR;
+
+ clear_ch_intr(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ALL);
+
+ //Mask ack Interrupt..
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ACK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+
+ result_td->parent_ed_p->ed_status.is_ping_enable =false;
+
+ // we just calculate the size of the transferred data on Data Stage of Control Transfer.
+ if(result_td->standard_dev_req_info.conrol_transfer_stage == DATA_STAGE)
+ {
+ result_td->transferred_szie += calc_transferred_size(false, result_td, hc_reg_data);
+ }
+
+ return DE_ALLOCATE;
+}
+
+/******************************************************************************/
+/*!
+ * @name u8 process_datatgl_on_control(td_t *result_td,
+ * hc_info_t *hc_reg_data)
+ *
+ *
+ * @brief this function deals with the datatglerr event according to Synopsys OTG Spec.
+ * the datatglerr event is occured at IN Transfer.
+ * this function just resets result_td->err_cnt and masks ack/nak/DataTgl of HCINTMSK.
+ * finally, this function clears datatglerr bit of HCINT.
+ *
+ * @param [IN] result_td -indicates the pointer of the td_t to be mapped with the uChNum.
+ * [IN] hc_reg_data -indicates the interrupt information of the Channel to be interrupted
+ *
+ * @return NO_ACTION
+ */
+/******************************************************************************/
+u8 process_datatgl_on_control( td_t * result_td,
+ hc_info_t * hc_reg_data)
+{
+ result_td->err_cnt = 0;
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ACK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+ clear_ch_intr(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+
+ return NO_ACTION;
+
+}
+
+
diff --git a/drivers/usb/host/s3c-otg/s3c-otg-transferchecker-control.h b/drivers/usb/host/s3c-otg/s3c-otg-transferchecker-control.h
new file mode 100644
index 0000000..4d85367
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/s3c-otg-transferchecker-control.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+ * (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+ *
+ * [File Name] : ControlTransferChecker.h
+ * [Description] : The Header file defines the external and internal functions of ControlTransferChecker
+ * [Author] : Yang Soon Yeal { syatom.yang@samsung.com }
+ * [Department] : System LSI Division/System SW Lab
+ * [Created Date]: 2009/01/12
+ * [Revision History]
+ * (1) 2008/06/13 by Yang Soon Yeal { syatom.yang@samsung.com }
+ * - Created this file and defines functions of ControlTransferChecker
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ ****************************************************************************/
+
+#ifndef _CONTROL_TRANSFER_CHECKER_H
+#define _CONTROL_TRANSFER_CHECKER_H
+
+/*
+// ----------------------------------------------------------------------------
+// Include files : None.
+// ----------------------------------------------------------------------------
+*/
+
+#include "s3c-otg-common-common.h"
+//#include "s3c-otg-common-typedef.h"
+#include "s3c-otg-common-const.h"
+#include "s3c-otg-common-errorcode.h"
+#include "s3c-otg-common-datastruct.h"
+#include "s3c-otg-common-regdef.h"
+
+#include "s3c-otg-hcdi-debug.h"
+#include "s3c-otg-scheduler-scheduler.h"
+
+#include "s3c-otg-transferchecker-checker.h"
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+u8 process_control_transfer( td_t *raw_td,
+ hc_info_t *hc_reg_data);
+
+u8 process_xfercompl_on_control(td_t *raw_td,
+ hc_info_t *hc_reg_data);
+
+u8 process_chhltd_on_control( td_t *raw_td,
+ hc_info_t *hc_reg_data);
+
+u8 process_ahb_on_control( td_t *raw_td,
+ hc_info_t *hc_reg_data);
+
+u8 process_stall_on_control( td_t *raw_td,
+ hc_info_t *hc_reg_data);
+
+u8 process_nak_on_control (td_t *raw_td,
+ hc_info_t *hc_reg_data);
+
+u8 process_ack_on_control (td_t *raw_td,
+ hc_info_t *hc_reg_data);
+
+u8 process_nyet_on_control( td_t *raw_td,
+ hc_info_t *hc_reg_data);
+
+u8 process_xacterr_on_control(td_t *raw_td,
+ hc_info_t *hc_reg_data);
+
+u8 process_bblerr_on_control( td_t *raw_td,
+ hc_info_t *hc_reg_data);
+
+u8 process_datatgl_on_control(td_t *raw_td,
+ hc_info_t *hc_reg_data);
+u8 process_indirection_on_control( td_t *result_td,
+ hc_info_t *hc_reg_data);
+
+u8 process_outdirection_on_control(td_t *result_td,
+ hc_info_t *hc_reg_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/drivers/usb/host/s3c-otg/s3c-otg-transferchecker-interrupt.c b/drivers/usb/host/s3c-otg/s3c-otg-transferchecker-interrupt.c
new file mode 100644
index 0000000..653628e
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/s3c-otg-transferchecker-interrupt.c
@@ -0,0 +1,574 @@
+/****************************************************************************
+ * (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+ *
+ * [File Name] : IntTransferChecker.c
+ * [Description] : The Source file implements the external and internal functions of IntTransferChecker
+ * [Author] : Yang Soon Yeal { syatom.yang@samsung.com }
+ * [Department] : System LSI Division/System SW Lab
+ * [Created Date]: 2008/06/19
+ * [Revision History]
+ * (1) 2008/06/18 by Yang Soon Yeal { syatom.yang@samsung.com }
+ * - Created this file and implements functions of IntTransferChecker
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * 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 "s3c-otg-transferchecker-interrupt.h"
+
+/******************************************************************************/
+/*!
+ * @name u8 process_intr_transfer(td_t *result_td,
+ * hc_info_t *HCRegData)
+ *
+ *
+ * @brief this function processes the result of the Interrupt Transfer.
+ * firstly, this function checks the result of the Interrupt Transfer.
+ * and according to the result, calls the sub-functions to process the result.
+ *
+ *
+ * @param [IN] result_td -indicates the pointer of the td_t whose channel is interruped.
+ * [IN] HCRegData -indicates the interrupt information of the Channel to be interrupted
+ *
+ * @return RE_TRANSMIT -if need to retransmit the result_td.
+ * RE_SCHEDULE -if need to reschedule the result_td.
+ * DE_ALLOCATE -if USB Transfer is completed.
+ * NO_ACTION -if we don't need any action,
+ */
+/******************************************************************************/
+u8 process_intr_transfer(td_t *result_td, hc_info_t *hc_reg_data)
+{
+ hcintn_t hc_intr_info;
+ u8 ret_val=0;
+
+ //we just deal with the interrupts to be unmasked.
+ hc_intr_info.d32 = hc_reg_data->hc_int.d32&result_td->cur_stransfer.hc_reg.hc_int_msk.d32;
+
+ if(result_td->parent_ed_p->ed_desc.is_ep_in) {
+ if(hc_intr_info.b.chhltd) {
+ ret_val = process_chhltd_on_intr(result_td, hc_reg_data);
+ }
+
+ else if (hc_intr_info.b.ack) {
+ ret_val = process_ack_on_intr(result_td, hc_reg_data);
+ }
+ }
+ else {
+ if(hc_intr_info.b.chhltd) {
+ ret_val = process_chhltd_on_intr(result_td, hc_reg_data);
+ }
+
+ else if(hc_intr_info.b.ack) {
+ ret_val = process_ack_on_intr( result_td, hc_reg_data);
+ }
+ }
+
+ return ret_val;
+}
+
+/******************************************************************************/
+/*!
+ * @name u8 process_chhltd_on_intr(td_t *result_td,
+ * hc_info_t *HCRegData)
+ *
+ *
+ * @brief this function processes Channel Halt event according to Synopsys OTG Spec.
+ * firstly, this function checks the reason of the Channel Halt, and according to the reason,
+ * calls the sub-functions to process the result.
+ *
+ *
+ * @param [IN] result_td -indicates the pointer of the td_t to be mapped with the uChNum.
+ * [IN] HCRegData -indicates the interrupt information of the Channel to be interrupted
+ *
+ * @return RE_TRANSMIT -if need to retransmit the result_td.
+ * RE_SCHEDULE -if need to reschedule the result_td.
+ * DE_ALLOCATE -if USB Transfer is completed.
+ */
+/******************************************************************************/
+u8 process_chhltd_on_intr(td_t *result_td,
+ hc_info_t *hc_reg_data)
+{
+ if(result_td->parent_ed_p->ed_desc.is_ep_in)
+ {
+ if(hc_reg_data->hc_int.b.xfercompl)
+ {
+ return process_xfercompl_on_intr( result_td, hc_reg_data);
+ }
+ else if(hc_reg_data->hc_int.b.stall)
+ {
+ return process_stall_on_intr(result_td, hc_reg_data);
+ }
+ else if(hc_reg_data->hc_int.b.bblerr)
+ {
+ return process_bblerr_on_intr(result_td, hc_reg_data);
+ }
+ else if (hc_reg_data->hc_int.b.nak)
+ {
+ return process_nak_on_intr(result_td, hc_reg_data);
+ }
+ else if(hc_reg_data->hc_int.b.datatglerr)
+ {
+ return process_datatgl_on_intr(result_td, hc_reg_data);
+ }
+ else if(hc_reg_data->hc_int.b.frmovrun)
+ {
+ return process_frmovrrun_on_intr(result_td,hc_reg_data);
+ }
+ else if(hc_reg_data->hc_int.b.xacterr)
+ {
+ return process_xacterr_on_intr(result_td, hc_reg_data);
+ }
+ else
+ {
+ clear_ch_intr(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ALL);
+
+ //Mask ack Interrupt..
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ACK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+ return RE_TRANSMIT;
+ }
+ }
+ else
+ {
+ if(hc_reg_data->hc_int.b.xfercompl)
+ {
+ return process_xfercompl_on_intr( result_td, hc_reg_data);
+ }
+ else if(hc_reg_data->hc_int.b.stall)
+ {
+ return process_stall_on_intr(result_td, hc_reg_data);
+ }
+ else if (hc_reg_data->hc_int.b.nak)
+ {
+ return process_nak_on_intr(result_td, hc_reg_data);
+ }
+ else if(hc_reg_data->hc_int.b.frmovrun)
+ {
+ return process_frmovrrun_on_intr(result_td,hc_reg_data);
+ }
+ else if(hc_reg_data->hc_int.b.xacterr)
+ {
+ return process_xacterr_on_intr(result_td, hc_reg_data);
+ }
+ else
+ {
+ clear_ch_intr(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ALL);
+
+ //Mask ack Interrupt..
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ACK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+
+ result_td->err_cnt++;
+ if(result_td->err_cnt == 3)
+ {
+ result_td->error_code = USB_ERR_STATUS_XACTERR;
+ result_td->err_cnt = 0;
+ return DE_ALLOCATE;
+ }
+
+ return RE_TRANSMIT;
+ }
+
+ }
+
+
+}
+
+/******************************************************************************/
+/*!
+ * @name u8 process_xfercompl_on_intr( td_t *result_td,
+ * hc_info_t *hc_reg_data)
+ *
+ *
+ * @brief this function deals with the xfercompl event according to Synopsys OTG Spec.
+ * the procedure of this function is as following
+ * 1. clears all bits of the channel' HCINT by using clear_ch_intr() of S3CIsr.
+ * 2. masks ack/nak(?)/datatglerr(?) bit of HCINTMSK
+ * 3. Resets the err_cnt of result_td.
+ * 4. updates the result_td->parent_ed_p->ed_status.
+ * IntDataTgl.
+ * 5. calculates the tranferred size by calling calc_transferred_size() on DATA_STAGE.
+ *
+ * @param [IN] result_td -indicates the pointer of the td_t to be mapped with the uChNum.
+ * [IN] HCRegData -indicates the interrupt information of the Channel to be interrupted
+ *
+ * @return DE_ALLOCATE -if USB Transfer is completed.
+ * RE_TRANSMIT -if need to retransmit the result_td.
+ */
+/******************************************************************************/
+u8 process_xfercompl_on_intr( td_t *result_td,
+ hc_info_t *hc_reg_data)
+{
+ u8 ret_val=0;
+
+ result_td->err_cnt =0;
+
+ clear_ch_intr(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ALL);
+
+ //Mask ack Interrupt..
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ACK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+
+ result_td->transferred_szie += calc_transferred_size(true,result_td, hc_reg_data);
+
+ if(result_td->transferred_szie==result_td->buf_size)
+ {//at IN Transfer, short transfer is accepted.
+ result_td->error_code = USB_ERR_STATUS_COMPLETE;
+ ret_val = DE_ALLOCATE;
+ }
+ else
+ {
+ // this routine will not be executed on Interrupt Transfer.
+ // So, we should decide to remove this routine or not.
+ if(result_td->parent_ed_p->ed_desc.is_ep_in&& hc_reg_data->hc_size.b.xfersize)
+ {
+ if(result_td->transfer_flag&USB_TRANS_FLAG_NOT_SHORT)
+ {
+ result_td->error_code = USB_ERR_STATUS_SHORTREAD;
+ }
+ else
+ {
+ result_td->error_code = USB_ERR_STATUS_COMPLETE;
+ }
+ ret_val = DE_ALLOCATE;
+ }
+ else
+ { // the Data Stage is not completed. So we need to continue Data Stage.
+ update_datatgl(hc_reg_data->hc_size.b.pid, result_td);
+ ret_val = RE_TRANSMIT;
+ }
+ }
+
+ update_datatgl(hc_reg_data->hc_size.b.pid, result_td);
+
+ return ret_val;
+
+}
+
+/******************************************************************************/
+/*!
+ * @name u8 process_ahb_on_intr(td_t *result_td,
+ * hc_info_t *hc_reg_data)
+ *
+ *
+ * @brief this function deals with theAHB Errorl event according to Synopsys OTG Spec.
+ * this function stop the channel to be executed
+ *
+ *
+ * @param [IN] result_td -indicates the pointer of the td_t to be mapped with the uChNum.
+ * [IN] HCRegData -indicates the interrupt information of the Channel to be interrupted
+ *
+ * @return DE_ALLOCATE
+ */
+/******************************************************************************/
+u8 process_ahb_on_intr(td_t *result_td,
+ hc_info_t *hc_reg_data)
+{
+ result_td->err_cnt = 0;
+ result_td->error_code = USB_ERR_STATUS_AHBERR;
+
+ clear_ch_intr(result_td->cur_stransfer.alloc_chnum, CH_STATUS_AHBErr);
+
+ //Mask ack Interrupt..
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ACK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+
+ // we just calculate the size of the transferred data on Data Stage of Int Transfer.
+ result_td->transferred_szie += calc_transferred_size(false,result_td, hc_reg_data);
+ result_td->parent_ed_p->ed_status.is_ping_enable =false;
+
+ return DE_ALLOCATE;
+
+}
+
+/******************************************************************************/
+/*!
+ * @name u8 process_stall_on_intr(td_t *result_td,
+ * hc_info_t *hc_reg_data)
+ *
+ *
+ * @brief this function deals with the Stall event according to Synopsys OTG Spec.
+ * when Stall is occured at Int Transfer, we should reset the PID as DATA0
+ *
+ * @param [IN] result_td -indicates the pointer of the td_t to be mapped with the uChNum.
+ * [IN] HCRegData -indicates the interrupt information of the Channel to be interrupted
+ *
+ * @return DE_ALLOCATE
+ */
+/******************************************************************************/
+u8 process_stall_on_intr(td_t *result_td,
+ hc_info_t *hc_reg_data)
+{
+ result_td->err_cnt = 0;
+ result_td->error_code = USB_ERR_STATUS_STALL;
+
+ //this channel is stalled, So we don't process another interrupts.
+ clear_ch_intr(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ALL);
+
+ //Mask ack Interrupt..
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ACK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+
+ result_td->transferred_szie += calc_transferred_size(false,result_td, hc_reg_data);
+
+ update_datatgl(DATA0, result_td);
+
+ return DE_ALLOCATE;
+}
+
+/******************************************************************************/
+/*!
+ * @name u8 process_nak_on_intr(td_t *result_td,
+ * hc_info_t *hc_reg_data)
+ *
+ *
+ * @brief this function deals with the nak event according to Synopsys OTG Spec.
+ * nak is occured at OUT/IN Transaction of Interrupt Transfer.
+ * we can't use ping protocol on Interrupt Transfer. and Syonopsys OTG IP occures
+ * chhltd interrupt on nak of IN/OUT Transaction. So we should retransmit the transfer
+ * on IN Transfer.
+ * If nak is occured at IN Transaction, this function processes this interrupt as following.
+ * 1. resets the result_td->err_cnt.
+ * 2. masks ack/nak/DaaTglErr bit of HCINTMSK.
+ * 3. clears the nak bit of HCINT
+ * 4. calculates frame number to retransmit this Interrupt Transfer.
+ *
+ * If nak is occured at OUT Transaction, this function processes this interrupt as following.
+ * 1. all procedures of IN Transaction are executed.
+ * 2. calculates the size of the transferred data.
+ * 3. if the speed of USB Device is High-Speed, sets the ping protocol.
+ * 4. update the Toggle
+ * at OUT Transaction, this function check whether the speed of USB Device is High-Speed or not.
+ * if USB Device is High-Speed, then
+ * this function sets the ping protocol.
+ *
+ * @param [IN] result_td -indicates the pointer of the td_t to be mapped with the uChNum.
+ * [IN] HCRegData -indicates the interrupt information of the Channel to be interrupted
+ *
+ * @return RE_SCHEDULE -if the direction of the Transfer is OUT
+ * NO_ACTION -if the direction of the Transfer is IN
+ */
+/******************************************************************************/
+u8 process_nak_on_intr(td_t *result_td,
+ hc_info_t *hc_reg_data)
+{
+ result_td->err_cnt = 0;
+
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ACK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+
+ clear_ch_intr(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+
+
+ result_td->transferred_szie += calc_transferred_size(false,result_td, hc_reg_data);
+
+ update_datatgl(hc_reg_data->hc_size.b.pid, result_td);
+
+ update_frame_number(result_td);
+
+ return RE_SCHEDULE;
+// return RE_TRANSMIT;
+
+
+}
+
+/******************************************************************************/
+/*!
+ * @name u8 process_ack_on_intr(td_t *result_td,
+ * hc_info_t *hc_reg_data)
+ *
+ *
+ * @brief this function deals with the ack event according to Synopsys OTG Spec.
+ * ack of IN/OUT Transaction don't need any retransmit.
+ * this function just resets result_td->err_cnt and masks ack/nak/DataTgl of HCINTMSK.
+ * finally, this function clears ack bit of HCINT and ed_status.is_ping_enable.
+ *
+ * @param [IN] result_td -indicates the pointer of the td_t to be mapped with the uChNum.
+ * [IN] HCRegData -indicates the interrupt information of the Channel to be interrupted
+ *
+ * @return NO_ACTION
+ */
+/******************************************************************************/
+u8 process_ack_on_intr(td_t *result_td,
+ hc_info_t *hc_reg_data)
+{
+ result_td->err_cnt = 0;
+
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ACK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+
+ clear_ch_intr(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ACK);
+
+ return NO_ACTION;
+}
+
+/******************************************************************************/
+/*!
+ * @name u8 process_xacterr_on_intr(td_t *result_td,
+ * hc_info_t *hc_reg_data)
+ *
+ * @brief this function deals with the xacterr event according to Synopsys OTG Spec.
+ * xacterr is occured at OUT/IN Transaction and we should retransmit the USB Transfer
+ * if the Error Counter is less than the RETRANSMIT_THRESHOLD.
+ * the reasons of xacterr is Timeout/CRC error/false EOP.
+ * the procedure to process xacterr is as following.
+ * 1. increses the result_td->err_cnt
+ * 2. check whether the result_td->err_cnt is equal to 3.
+ * 2. unmasks ack/nak/datatglerr bit of HCINTMSK.
+ * 3. clears the xacterr bit of HCINT
+ * 4. calculates the size of the transferred data.
+ * 5. update the Data Toggle.
+ * 6. update the frame number to start retransmitting the Interrupt Transfer.
+ *
+ * @param [IN] result_td -indicates the pointer of the td_t to be mapped with the uChNum.
+ * [IN] HCRegData -indicates the interrupt information of the Channel to be interrupted
+ *
+ * @return RE_SCHEDULE -if the error count is less than 3
+ * DE_ALLOCATE -if the error count is equal to 3
+ */
+/******************************************************************************/
+u8 process_xacterr_on_intr(td_t *result_td,
+ hc_info_t *hc_reg_data)
+{
+ u8 ret_val = 0;
+
+ if(result_td->err_cnt<RETRANSMIT_THRESHOLD)
+ {
+ result_td->cur_stransfer.hc_reg.hc_int_msk.d32 |=(CH_STATUS_ACK+CH_STATUS_NAK+CH_STATUS_DataTglErr);
+ ret_val = RE_SCHEDULE;
+ result_td->err_cnt++ ;
+ }
+ else
+ {
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ACK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+ ret_val = DE_ALLOCATE;
+ result_td->err_cnt = 0 ;
+ }
+
+ clear_ch_intr(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+
+ result_td->transferred_szie += calc_transferred_size(false,result_td, hc_reg_data);
+
+ update_datatgl(hc_reg_data->hc_size.b.pid, result_td);
+
+ if(ret_val == RE_SCHEDULE)
+ { //Calculates the frame number
+ update_frame_number(result_td);
+ }
+
+ return ret_val;
+}
+
+/******************************************************************************/
+/*!
+ * @name void process_bblerr_on_intr(td_t *result_td,
+ * hc_info_t *hc_reg_data)
+ *
+ *
+ * @brief this function deals with the Babble event according to Synopsys OTG Spec.
+ * babble error is occured when the USB device continues to send packets
+ * althrough EOP is occured. So Babble error is only occured at IN Transfer.
+ * when Babble Error is occured, we should stop the USB Transfer, and return the fact
+ * to Application.
+ *
+ * @param [IN] result_td -indicates the pointer of the td_t to be mapped with the uChNum.
+ * [IN] HCRegData -indicates the interrupt information of the Channel to be interrupted
+ *
+ * @return DE_ALLOCATE
+ */
+/******************************************************************************/
+u8 process_bblerr_on_intr(td_t *result_td,
+ hc_info_t *hc_reg_data)
+{
+
+ if(!result_td->parent_ed_p->ed_desc.is_ep_in)
+ {
+ return NO_ACTION;
+ }
+
+ result_td->err_cnt = 0;
+ result_td->error_code =USB_ERR_STATUS_BBLERR;
+
+ clear_ch_intr(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ALL);
+
+ //Mask ack Interrupt..
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ACK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+
+ result_td->transferred_szie += calc_transferred_size(false, result_td, hc_reg_data);
+ return DE_ALLOCATE;
+}
+
+/******************************************************************************/
+/*!
+ * @name u8 process_datatgl_on_intr( td_t *result_td,
+ * hc_info_t *hc_reg_data)
+ *
+ * @brief this function deals with the datatglerr event according to Synopsys OTG Spec.
+ * the datatglerr event is occured at IN Transfer, and the channel is not halted.
+ * this function just resets result_td->err_cnt and masks ack/nak/DataTgl of HCINTMSK.
+ * finally, this function clears datatglerr bit of HCINT.
+ *
+ * @param [IN] result_td -indicates the pointer of the td_t to be mapped with the uChNum.
+ * [IN] HCRegData -indicates the interrupt information of the Channel to be interrupted
+ *
+ * @return RE_SCHEDULE
+ */
+/******************************************************************************/
+u8 process_datatgl_on_intr(td_t *result_td,
+ hc_info_t *hc_reg_data)
+{
+ result_td->err_cnt = 0;
+
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_ACK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+ mask_channel_interrupt(result_td->cur_stransfer.alloc_chnum, CH_STATUS_DataTglErr);
+
+ clear_ch_intr(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+
+ result_td->transferred_szie += calc_transferred_size(false,result_td, hc_reg_data);
+
+ update_datatgl(hc_reg_data->hc_size.b.pid, result_td);
+
+ update_frame_number(result_td);
+
+ return RE_SCHEDULE;
+}
+
+u8 process_frmovrrun_on_intr(td_t *result_td,
+ hc_info_t *hc_reg_data)
+{
+
+ clear_ch_intr(result_td->cur_stransfer.alloc_chnum, CH_STATUS_NAK);
+
+ update_datatgl(hc_reg_data->hc_size.b.pid, result_td);
+
+ update_frame_number(result_td);
+
+ return RE_TRANSMIT;
+}
+
diff --git a/drivers/usb/host/s3c-otg/s3c-otg-transferchecker-interrupt.h b/drivers/usb/host/s3c-otg/s3c-otg-transferchecker-interrupt.h
new file mode 100644
index 0000000..0a735a2
--- /dev/null
+++ b/drivers/usb/host/s3c-otg/s3c-otg-transferchecker-interrupt.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+ * (C) Copyright 2008 Samsung Electronics Co., Ltd., All rights reserved
+ *
+ * [File Name] : IntTransferChecker.h
+ * [Description] : The Header file defines the external and internal functions of IntTransferChecker
+ * [Author] : Yang Soon Yeal { syatom.yang@samsung.com }
+ * [Department] : System LSI Division/System SW Lab
+ * [Created Date]: 2008/06/19
+ * [Revision History]
+ * (1) 2008/06/18 by Yang Soon Yeal { syatom.yang@samsung.com }
+ * - Created this file and defines functions of IntTransferChecker
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ ****************************************************************************/
+
+#ifndef _INT_TRANSFER_CHECKER_H
+#define _INT_TRANSFER_CHECKER_H
+
+/*
+// ----------------------------------------------------------------------------
+// Include files : None.
+// ----------------------------------------------------------------------------
+*/
+
+#include "s3c-otg-common-common.h"
+//#include "s3c-otg-common-typedef.h"
+#include "s3c-otg-common-const.h"
+#include "s3c-otg-common-errorcode.h"
+#include "s3c-otg-common-datastruct.h"
+#include "s3c-otg-common-regdef.h"
+
+#include "s3c-otg-hcdi-debug.h"
+#include "s3c-otg-scheduler-scheduler.h"
+#include "s3c-otg-isr.h"
+#include "s3c-otg-transferchecker-checker.h"
+
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+u8 process_intr_transfer(td_t *pRawTD,
+ hc_info_t *pHCRegData);
+
+u8 process_xfercompl_on_intr(td_t *pRawTD,
+ hc_info_t *pHCRegData);
+
+u8 process_chhltd_on_intr(td_t *pRawTD,
+ hc_info_t *pHCRegData);
+
+u8 process_ahb_on_intr(td_t *pRawTD,
+ hc_info_t *pHCRegData);
+
+u8 process_stall_on_intr(td_t *pRawTD,
+ hc_info_t *pHCRegData);
+
+u8 process_nak_on_intr(td_t *pRawTD,
+ hc_info_t *pHCRegData);
+
+u8 process_frmovrrun_on_intr(td_t *pRawTD,
+ hc_info_t *pHCRegData);
+
+u8 process_ack_on_intr(td_t *pRawTD,
+ hc_info_t *pHCRegData);
+
+u8 process_xacterr_on_intr(td_t *pRawTD,
+ hc_info_t *pHCRegData);
+
+u8 process_bblerr_on_intr(td_t *pRawTD,
+ hc_info_t *pHCRegData);
+
+u8 process_datatgl_on_intr(td_t *pRawTD,
+ hc_info_t *pHCRegData);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
+
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index a4468d9..a44f2d4 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1505,6 +1505,7 @@ void xhci_free_command(struct xhci_hcd *xhci,
void xhci_mem_cleanup(struct xhci_hcd *xhci)
{
struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
+ struct xhci_cd *cur_cd, *next_cd;
int size;
int i;
@@ -1520,10 +1521,16 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
xhci->event_ring = NULL;
xhci_dbg(xhci, "Freed event ring\n");
+ xhci->cmd_ring_reserved_trbs = 0;
if (xhci->cmd_ring)
xhci_ring_free(xhci, xhci->cmd_ring);
xhci->cmd_ring = NULL;
xhci_dbg(xhci, "Freed command ring\n");
+ list_for_each_entry_safe(cur_cd, next_cd,
+ &xhci->cancel_cmd_list, cancel_cmd_list) {
+ list_del(&cur_cd->cancel_cmd_list);
+ kfree(cur_cd);
+ }
for (i = 1; i < MAX_HC_SLOTS; ++i)
xhci_free_virt_device(xhci, i);
@@ -2013,6 +2020,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
xhci->cmd_ring = xhci_ring_alloc(xhci, 1, true, false, flags);
if (!xhci->cmd_ring)
goto fail;
+ INIT_LIST_HEAD(&xhci->cancel_cmd_list);
xhci_dbg(xhci, "Allocated command ring at %p\n", xhci->cmd_ring);
xhci_dbg(xhci, "First segment DMA is 0x%llx\n",
(unsigned long long)xhci->cmd_ring->first_seg->dma);
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 4509f69..73fea4b 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -123,6 +123,7 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
xhci_dbg(xhci, "QUIRK: Fresco Logic revision %u "
"has broken MSI implementation\n",
pdev->revision);
+ xhci->quirks |= XHCI_TRUST_TX_LENGTH;
}
if (pdev->vendor == PCI_VENDOR_ID_NEC)
@@ -139,11 +140,22 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
xhci->quirks |= XHCI_SPURIOUS_SUCCESS;
xhci->quirks |= XHCI_EP_LIMIT_QUIRK;
xhci->limit_active_eps = 64;
+ /*
+ * PPT desktop boards DH77EB and DH77DF will power back on after
+ * a few seconds of being shutdown. The fix for this is to
+ * switch the ports from xHCI to EHCI on shutdown. We can't use
+ * DMI information to find those particular boards (since each
+ * vendor will change the board name), so we have to key off all
+ * PPT chipsets.
+ */
+ xhci->quirks |= XHCI_SPURIOUS_REBOOT;
+ xhci->quirks |= XHCI_AVOID_BEI;
}
if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
pdev->device == PCI_DEVICE_ID_ASROCK_P67) {
xhci->quirks |= XHCI_RESET_ON_RESUME;
xhci_dbg(xhci, "QUIRK: Resetting on resume\n");
+ xhci->quirks |= XHCI_TRUST_TX_LENGTH;
}
if (pdev->vendor == PCI_VENDOR_ID_VIA)
xhci->quirks |= XHCI_RESET_ON_RESUME;
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index c42fdff..1a38281 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -147,25 +147,34 @@ static void next_trb(struct xhci_hcd *xhci,
*/
static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer)
{
- union xhci_trb *next = ++(ring->dequeue);
unsigned long long addr;
ring->deq_updates++;
- /* Update the dequeue pointer further if that was a link TRB or we're at
- * the end of an event ring segment (which doesn't have link TRBS)
- */
- while (last_trb(xhci, ring, ring->deq_seg, next)) {
- if (consumer && last_trb_on_last_seg(xhci, ring, ring->deq_seg, next)) {
- ring->cycle_state = (ring->cycle_state ? 0 : 1);
- if (!in_interrupt())
- xhci_dbg(xhci, "Toggle cycle state for ring %p = %i\n",
- ring,
- (unsigned int) ring->cycle_state);
+
+ do {
+ /*
+ * Update the dequeue pointer further if that was a link TRB or
+ * we're at the end of an event ring segment (which doesn't have
+ * link TRBS)
+ */
+ if (last_trb(xhci, ring, ring->deq_seg, ring->dequeue)) {
+ if (consumer && last_trb_on_last_seg(xhci, ring,
+ ring->deq_seg, ring->dequeue)) {
+ if (!in_interrupt())
+ xhci_dbg(xhci, "Toggle cycle state "
+ "for ring %p = %i\n",
+ ring,
+ (unsigned int)
+ ring->cycle_state);
+ ring->cycle_state = (ring->cycle_state ? 0 : 1);
+ }
+ ring->deq_seg = ring->deq_seg->next;
+ ring->dequeue = ring->deq_seg->trbs;
+ } else {
+ ring->dequeue++;
}
- ring->deq_seg = ring->deq_seg->next;
- ring->dequeue = ring->deq_seg->trbs;
- next = ring->dequeue;
- }
+ } while (last_trb(xhci, ring, ring->deq_seg, ring->dequeue));
+
addr = (unsigned long long) xhci_trb_virt_to_dma(ring->deq_seg, ring->dequeue);
}
@@ -302,12 +311,123 @@ static int room_on_ring(struct xhci_hcd *xhci, struct xhci_ring *ring,
/* Ring the host controller doorbell after placing a command on the ring */
void xhci_ring_cmd_db(struct xhci_hcd *xhci)
{
+ if (!(xhci->cmd_ring_state & CMD_RING_STATE_RUNNING))
+ return;
+
xhci_dbg(xhci, "// Ding dong!\n");
xhci_writel(xhci, DB_VALUE_HOST, &xhci->dba->doorbell[0]);
/* Flush PCI posted writes */
xhci_readl(xhci, &xhci->dba->doorbell[0]);
}
+static int xhci_abort_cmd_ring(struct xhci_hcd *xhci)
+{
+ u64 temp_64;
+ int ret;
+
+ xhci_dbg(xhci, "Abort command ring\n");
+
+ if (!(xhci->cmd_ring_state & CMD_RING_STATE_RUNNING)) {
+ xhci_dbg(xhci, "The command ring isn't running, "
+ "Have the command ring been stopped?\n");
+ return 0;
+ }
+
+ temp_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
+ if (!(temp_64 & CMD_RING_RUNNING)) {
+ xhci_dbg(xhci, "Command ring had been stopped\n");
+ return 0;
+ }
+ xhci->cmd_ring_state = CMD_RING_STATE_ABORTED;
+ xhci_write_64(xhci, temp_64 | CMD_RING_ABORT,
+ &xhci->op_regs->cmd_ring);
+
+ /* Section 4.6.1.2 of xHCI 1.0 spec says software should
+ * time the completion od all xHCI commands, including
+ * the Command Abort operation. If software doesn't see
+ * CRR negated in a timely manner (e.g. longer than 5
+ * seconds), then it should assume that the there are
+ * larger problems with the xHC and assert HCRST.
+ */
+ ret = handshake(xhci, &xhci->op_regs->cmd_ring,
+ CMD_RING_RUNNING, 0, 5 * 1000 * 1000);
+ if (ret < 0) {
+ xhci_err(xhci, "Stopped the command ring failed, "
+ "maybe the host is dead\n");
+ xhci->xhc_state |= XHCI_STATE_DYING;
+ xhci_quiesce(xhci);
+ xhci_halt(xhci);
+ return -ESHUTDOWN;
+ }
+
+ return 0;
+}
+
+static int xhci_queue_cd(struct xhci_hcd *xhci,
+ struct xhci_command *command,
+ union xhci_trb *cmd_trb)
+{
+ struct xhci_cd *cd;
+ cd = kzalloc(sizeof(struct xhci_cd), GFP_ATOMIC);
+ if (!cd)
+ return -ENOMEM;
+ INIT_LIST_HEAD(&cd->cancel_cmd_list);
+
+ cd->command = command;
+ cd->cmd_trb = cmd_trb;
+ list_add_tail(&cd->cancel_cmd_list, &xhci->cancel_cmd_list);
+
+ return 0;
+}
+
+/*
+ * Cancel the command which has issue.
+ *
+ * Some commands may hang due to waiting for acknowledgement from
+ * usb device. It is outside of the xHC's ability to control and
+ * will cause the command ring is blocked. When it occurs software
+ * should intervene to recover the command ring.
+ * See Section 4.6.1.1 and 4.6.1.2
+ */
+int xhci_cancel_cmd(struct xhci_hcd *xhci, struct xhci_command *command,
+ union xhci_trb *cmd_trb)
+{
+ int retval = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&xhci->lock, flags);
+
+ if (xhci->xhc_state & XHCI_STATE_DYING) {
+ xhci_warn(xhci, "Abort the command ring,"
+ " but the xHCI is dead.\n");
+ retval = -ESHUTDOWN;
+ goto fail;
+ }
+
+ /* queue the cmd desriptor to cancel_cmd_list */
+ retval = xhci_queue_cd(xhci, command, cmd_trb);
+ if (retval) {
+ xhci_warn(xhci, "Queuing command descriptor failed.\n");
+ goto fail;
+ }
+
+ /* abort command ring */
+ retval = xhci_abort_cmd_ring(xhci);
+ if (retval) {
+ xhci_err(xhci, "Abort command ring failed\n");
+ if (unlikely(retval == -ESHUTDOWN)) {
+ spin_unlock_irqrestore(&xhci->lock, flags);
+ usb_hc_died(xhci_to_hcd(xhci)->primary_hcd);
+ xhci_dbg(xhci, "xHCI host controller is dead.\n");
+ return retval;
+ }
+ }
+
+fail:
+ spin_unlock_irqrestore(&xhci->lock, flags);
+ return retval;
+}
+
void xhci_ring_ep_doorbell(struct xhci_hcd *xhci,
unsigned int slot_id,
unsigned int ep_index,
@@ -1037,6 +1157,20 @@ static void handle_reset_ep_completion(struct xhci_hcd *xhci,
}
}
+/* Complete the command and detele it from the devcie's command queue.
+ */
+static void xhci_complete_cmd_in_cmd_wait_list(struct xhci_hcd *xhci,
+ struct xhci_command *command, u32 status)
+{
+ command->status = status;
+ list_del(&command->cmd_list);
+ if (command->completion)
+ complete(command->completion);
+ else
+ xhci_free_command(xhci, command);
+}
+
+
/* Check to see if a command in the device's command queue matches this one.
* Signal the completion or free the command, and return 1. Return 0 if the
* completed command isn't at the head of the command list.
@@ -1055,15 +1189,155 @@ static int handle_cmd_in_cmd_wait_list(struct xhci_hcd *xhci,
if (xhci->cmd_ring->dequeue != command->command_trb)
return 0;
- command->status = GET_COMP_CODE(le32_to_cpu(event->status));
- list_del(&command->cmd_list);
- if (command->completion)
- complete(command->completion);
- else
- xhci_free_command(xhci, command);
+ xhci_complete_cmd_in_cmd_wait_list(xhci, command,
+ GET_COMP_CODE(le32_to_cpu(event->status)));
return 1;
}
+/*
+ * Finding the command trb need to be cancelled and modifying it to
+ * NO OP command. And if the command is in device's command wait
+ * list, finishing and freeing it.
+ *
+ * If we can't find the command trb, we think it had already been
+ * executed.
+ */
+static void xhci_cmd_to_noop(struct xhci_hcd *xhci, struct xhci_cd *cur_cd)
+{
+ struct xhci_segment *cur_seg;
+ union xhci_trb *cmd_trb;
+ u32 cycle_state;
+
+ if (xhci->cmd_ring->dequeue == xhci->cmd_ring->enqueue)
+ return;
+
+ /* find the current segment of command ring */
+ cur_seg = find_trb_seg(xhci->cmd_ring->first_seg,
+ xhci->cmd_ring->dequeue, &cycle_state);
+
+ if (!cur_seg) {
+ xhci_warn(xhci, "Command ring mismatch, dequeue = %p %llx (dma)\n",
+ xhci->cmd_ring->dequeue,
+ (unsigned long long)
+ xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
+ xhci->cmd_ring->dequeue));
+ xhci_debug_ring(xhci, xhci->cmd_ring);
+ xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring);
+ return;
+ }
+
+ /* find the command trb matched by cd from command ring */
+ for (cmd_trb = xhci->cmd_ring->dequeue;
+ cmd_trb != xhci->cmd_ring->enqueue;
+ next_trb(xhci, xhci->cmd_ring, &cur_seg, &cmd_trb)) {
+ /* If the trb is link trb, continue */
+ if (TRB_TYPE_LINK_LE32(cmd_trb->generic.field[3]))
+ continue;
+
+ if (cur_cd->cmd_trb == cmd_trb) {
+
+ /* If the command in device's command list, we should
+ * finish it and free the command structure.
+ */
+ if (cur_cd->command)
+ xhci_complete_cmd_in_cmd_wait_list(xhci,
+ cur_cd->command, COMP_CMD_STOP);
+
+ /* get cycle state from the origin command trb */
+ cycle_state = le32_to_cpu(cmd_trb->generic.field[3])
+ & TRB_CYCLE;
+
+ /* modify the command trb to NO OP command */
+ cmd_trb->generic.field[0] = 0;
+ cmd_trb->generic.field[1] = 0;
+ cmd_trb->generic.field[2] = 0;
+ cmd_trb->generic.field[3] = cpu_to_le32(
+ TRB_TYPE(TRB_CMD_NOOP) | cycle_state);
+ break;
+ }
+ }
+}
+
+static void xhci_cancel_cmd_in_cd_list(struct xhci_hcd *xhci)
+{
+ struct xhci_cd *cur_cd, *next_cd;
+
+ if (list_empty(&xhci->cancel_cmd_list))
+ return;
+
+ list_for_each_entry_safe(cur_cd, next_cd,
+ &xhci->cancel_cmd_list, cancel_cmd_list) {
+ xhci_cmd_to_noop(xhci, cur_cd);
+ list_del(&cur_cd->cancel_cmd_list);
+ kfree(cur_cd);
+ }
+}
+
+/*
+ * traversing the cancel_cmd_list. If the command descriptor according
+ * to cmd_trb is found, the function free it and return 1, otherwise
+ * return 0.
+ */
+static int xhci_search_cmd_trb_in_cd_list(struct xhci_hcd *xhci,
+ union xhci_trb *cmd_trb)
+{
+ struct xhci_cd *cur_cd, *next_cd;
+
+ if (list_empty(&xhci->cancel_cmd_list))
+ return 0;
+
+ list_for_each_entry_safe(cur_cd, next_cd,
+ &xhci->cancel_cmd_list, cancel_cmd_list) {
+ if (cur_cd->cmd_trb == cmd_trb) {
+ if (cur_cd->command)
+ xhci_complete_cmd_in_cmd_wait_list(xhci,
+ cur_cd->command, COMP_CMD_STOP);
+ list_del(&cur_cd->cancel_cmd_list);
+ kfree(cur_cd);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * If the cmd_trb_comp_code is COMP_CMD_ABORT, we just check whether the
+ * trb pointed by the command ring dequeue pointer is the trb we want to
+ * cancel or not. And if the cmd_trb_comp_code is COMP_CMD_STOP, we will
+ * traverse the cancel_cmd_list to trun the all of the commands according
+ * to command descriptor to NO-OP trb.
+ */
+static int handle_stopped_cmd_ring(struct xhci_hcd *xhci,
+ int cmd_trb_comp_code)
+{
+ int cur_trb_is_good = 0;
+
+ /* Searching the cmd trb pointed by the command ring dequeue
+ * pointer in command descriptor list. If it is found, free it.
+ */
+ cur_trb_is_good = xhci_search_cmd_trb_in_cd_list(xhci,
+ xhci->cmd_ring->dequeue);
+
+ if (cmd_trb_comp_code == COMP_CMD_ABORT)
+ xhci->cmd_ring_state = CMD_RING_STATE_STOPPED;
+ else if (cmd_trb_comp_code == COMP_CMD_STOP) {
+ /* traversing the cancel_cmd_list and canceling
+ * the command according to command descriptor
+ */
+ xhci_cancel_cmd_in_cd_list(xhci);
+
+ xhci->cmd_ring_state = CMD_RING_STATE_RUNNING;
+ /*
+ * ring command ring doorbell again to restart the
+ * command ring
+ */
+ if (xhci->cmd_ring->dequeue != xhci->cmd_ring->enqueue)
+ xhci_ring_cmd_db(xhci);
+ }
+ return cur_trb_is_good;
+}
+
static void handle_cmd_completion(struct xhci_hcd *xhci,
struct xhci_event_cmd *event)
{
@@ -1089,6 +1363,22 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
xhci->error_bitmask |= 1 << 5;
return;
}
+
+ if ((GET_COMP_CODE(le32_to_cpu(event->status)) == COMP_CMD_ABORT) ||
+ (GET_COMP_CODE(le32_to_cpu(event->status)) == COMP_CMD_STOP)) {
+ /* If the return value is 0, we think the trb pointed by
+ * command ring dequeue pointer is a good trb. The good
+ * trb means we don't want to cancel the trb, but it have
+ * been stopped by host. So we should handle it normally.
+ * Otherwise, driver should invoke inc_deq() and return.
+ */
+ if (handle_stopped_cmd_ring(xhci,
+ GET_COMP_CODE(le32_to_cpu(event->status)))) {
+ inc_deq(xhci, xhci->cmd_ring, false);
+ return;
+ }
+ }
+
switch (le32_to_cpu(xhci->cmd_ring->dequeue->generic.field[3])
& TRB_TYPE_BITMASK) {
case TRB_TYPE(TRB_ENABLE_SLOT):
@@ -1739,8 +2029,12 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
/* handle completion code */
switch (trb_comp_code) {
case COMP_SUCCESS:
- frame->status = 0;
- break;
+ if (TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) {
+ frame->status = 0;
+ break;
+ }
+ if ((xhci->quirks & XHCI_TRUST_TX_LENGTH))
+ trb_comp_code = COMP_SHORT_TX;
case COMP_SHORT_TX:
frame->status = td->urb->transfer_flags & URB_SHORT_NOT_OK ?
-EREMOTEIO : 0;
@@ -1756,6 +2050,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
break;
case COMP_DEV_ERR:
case COMP_STALL:
+ case COMP_TX_ERR:
frame->status = -EPROTO;
skip_td = true;
break;
@@ -1838,13 +2133,16 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
switch (trb_comp_code) {
case COMP_SUCCESS:
/* Double check that the HW transferred everything. */
- if (event_trb != td->last_trb) {
+ if (event_trb != td->last_trb ||
+ TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
xhci_warn(xhci, "WARN Successful completion "
"on short TX\n");
if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
*status = -EREMOTEIO;
else
*status = 0;
+ if ((xhci->quirks & XHCI_TRUST_TX_LENGTH))
+ trb_comp_code = COMP_SHORT_TX;
} else {
*status = 0;
}
@@ -1985,6 +2283,13 @@ static int handle_tx_event(struct xhci_hcd *xhci,
* transfer type
*/
case COMP_SUCCESS:
+ if (TRB_LEN(le32_to_cpu(event->transfer_len)) == 0)
+ break;
+ if (xhci->quirks & XHCI_TRUST_TX_LENGTH)
+ trb_comp_code = COMP_SHORT_TX;
+ else
+ xhci_warn(xhci, "WARN Successful completion on short TX: "
+ "needs XHCI_TRUST_TX_LENGTH quirk?\n");
case COMP_SHORT_TX:
break;
case COMP_STOP:
@@ -3341,7 +3646,9 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
} else {
td->last_trb = ep_ring->enqueue;
field |= TRB_IOC;
- if (xhci->hci_version == 0x100) {
+ if (xhci->hci_version == 0x100 &&
+ !(xhci->quirks &
+ XHCI_AVOID_BEI)) {
/* Set BEI bit except for the last td */
if (i < num_tds - 1)
field |= TRB_BEI;
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index dbba936..4864b25 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -51,7 +51,7 @@ MODULE_PARM_DESC(link_quirk, "Don't clear the chain bit on a link TRB");
* handshake done). There are two failure modes: "usec" have passed (major
* hardware flakeout), or the register reads as all-ones (hardware removed).
*/
-static int handshake(struct xhci_hcd *xhci, void __iomem *ptr,
+int handshake(struct xhci_hcd *xhci, void __iomem *ptr,
u32 mask, u32 done, int usec)
{
u32 result;
@@ -104,8 +104,10 @@ int xhci_halt(struct xhci_hcd *xhci)
ret = handshake(xhci, &xhci->op_regs->status,
STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC);
- if (!ret)
+ if (!ret) {
xhci->xhc_state |= XHCI_STATE_HALTED;
+ xhci->cmd_ring_state = CMD_RING_STATE_STOPPED;
+ }
return ret;
}
@@ -163,7 +165,7 @@ int xhci_reset(struct xhci_hcd *xhci)
xhci_writel(xhci, command, &xhci->op_regs->command);
ret = handshake(xhci, &xhci->op_regs->command,
- CMD_RESET, 0, 250 * 1000);
+ CMD_RESET, 0, 10 * 1000 * 1000);
if (ret)
return ret;
@@ -172,7 +174,8 @@ int xhci_reset(struct xhci_hcd *xhci)
* xHCI cannot write to any doorbells or operational registers other
* than status until the "Controller Not Ready" flag is cleared.
*/
- return handshake(xhci, &xhci->op_regs->status, STS_CNR, 0, 250 * 1000);
+ return handshake(xhci, &xhci->op_regs->status,
+ STS_CNR, 0, 10 * 1000 * 1000);
}
/*
@@ -389,6 +392,7 @@ static int xhci_run_finished(struct xhci_hcd *xhci)
return -ENODEV;
}
xhci->shared_hcd->state = HC_STATE_RUNNING;
+ xhci->cmd_ring_state = CMD_RING_STATE_RUNNING;
if (xhci->quirks & XHCI_NEC_HOST)
xhci_ring_cmd_db(xhci);
@@ -593,6 +597,9 @@ void xhci_shutdown(struct usb_hcd *hcd)
{
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+ if (xhci->quirks & XHCI_SPURIOUS_REBOOT)
+ usb_disable_xhci_ports(to_pci_dev(hcd->self.controller));
+
spin_lock_irq(&xhci->lock);
xhci_halt(xhci);
spin_unlock_irq(&xhci->lock);
@@ -716,7 +723,7 @@ int xhci_suspend(struct xhci_hcd *xhci)
command &= ~CMD_RUN;
xhci_writel(xhci, command, &xhci->op_regs->command);
if (handshake(xhci, &xhci->op_regs->status,
- STS_HALT, STS_HALT, 100*100)) {
+ STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC)) {
xhci_warn(xhci, "WARN: xHC CMD_RUN timeout\n");
spin_unlock_irq(&xhci->lock);
return -ETIMEDOUT;
@@ -730,8 +737,8 @@ int xhci_suspend(struct xhci_hcd *xhci)
command = xhci_readl(xhci, &xhci->op_regs->command);
command |= CMD_CSS;
xhci_writel(xhci, command, &xhci->op_regs->command);
- if (handshake(xhci, &xhci->op_regs->status, STS_SAVE, 0, 10*100)) {
- xhci_warn(xhci, "WARN: xHC CMD_CSS timeout\n");
+ if (handshake(xhci, &xhci->op_regs->status, STS_SAVE, 0, 10 * 1000)) {
+ xhci_warn(xhci, "WARN: xHC save state timeout\n");
spin_unlock_irq(&xhci->lock);
return -ETIMEDOUT;
}
@@ -786,8 +793,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
command |= CMD_CRS;
xhci_writel(xhci, command, &xhci->op_regs->command);
if (handshake(xhci, &xhci->op_regs->status,
- STS_RESTORE, 0, 10*100)) {
- xhci_dbg(xhci, "WARN: xHC CMD_CSS timeout\n");
+ STS_RESTORE, 0, 10 * 1000)) {
+ xhci_warn(xhci, "WARN: xHC restore state timeout\n");
spin_unlock_irq(&xhci->lock);
return -ETIMEDOUT;
}
@@ -1771,6 +1778,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
struct completion *cmd_completion;
u32 *cmd_status;
struct xhci_virt_device *virt_dev;
+ union xhci_trb *cmd_trb;
spin_lock_irqsave(&xhci->lock, flags);
virt_dev = xhci->devs[udev->slot_id];
@@ -1813,6 +1821,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
}
init_completion(cmd_completion);
+ cmd_trb = xhci->cmd_ring->dequeue;
if (!ctx_change)
ret = xhci_queue_configure_endpoint(xhci, in_ctx->dma,
udev->slot_id, must_succeed);
@@ -1834,14 +1843,17 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
/* Wait for the configure endpoint command to complete */
timeleft = wait_for_completion_interruptible_timeout(
cmd_completion,
- USB_CTRL_SET_TIMEOUT);
+ XHCI_CMD_DEFAULT_TIMEOUT);
if (timeleft <= 0) {
xhci_warn(xhci, "%s while waiting for %s command\n",
timeleft == 0 ? "Timeout" : "Signal",
ctx_change == 0 ?
"configure endpoint" :
"evaluate context");
- /* FIXME cancel the configure endpoint command */
+ /* cancel the configure endpoint command */
+ ret = xhci_cancel_cmd(xhci, command, cmd_trb);
+ if (ret < 0)
+ return ret;
return -ETIME;
}
@@ -2774,8 +2786,10 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
unsigned long flags;
int timeleft;
int ret;
+ union xhci_trb *cmd_trb;
spin_lock_irqsave(&xhci->lock, flags);
+ cmd_trb = xhci->cmd_ring->dequeue;
ret = xhci_queue_slot_control(xhci, TRB_ENABLE_SLOT, 0);
if (ret) {
spin_unlock_irqrestore(&xhci->lock, flags);
@@ -2787,12 +2801,12 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
/* XXX: how much time for xHC slot assignment? */
timeleft = wait_for_completion_interruptible_timeout(&xhci->addr_dev,
- USB_CTRL_SET_TIMEOUT);
+ XHCI_CMD_DEFAULT_TIMEOUT);
if (timeleft <= 0) {
xhci_warn(xhci, "%s while waiting for a slot\n",
timeleft == 0 ? "Timeout" : "Signal");
- /* FIXME cancel the enable slot request */
- return 0;
+ /* cancel the enable slot request */
+ return xhci_cancel_cmd(xhci, NULL, cmd_trb);
}
if (!xhci->slot_id) {
@@ -2853,6 +2867,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
struct xhci_slot_ctx *slot_ctx;
struct xhci_input_control_ctx *ctrl_ctx;
u64 temp_64;
+ union xhci_trb *cmd_trb;
if (!udev->slot_id) {
xhci_dbg(xhci, "Bad Slot ID %d\n", udev->slot_id);
@@ -2891,6 +2906,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2);
spin_lock_irqsave(&xhci->lock, flags);
+ cmd_trb = xhci->cmd_ring->dequeue;
ret = xhci_queue_address_device(xhci, virt_dev->in_ctx->dma,
udev->slot_id);
if (ret) {
@@ -2903,7 +2919,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
/* ctrl tx can take up to 5 sec; XXX: need more time for xHC? */
timeleft = wait_for_completion_interruptible_timeout(&xhci->addr_dev,
- USB_CTRL_SET_TIMEOUT);
+ XHCI_CMD_DEFAULT_TIMEOUT);
/* FIXME: From section 4.3.4: "Software shall be responsible for timing
* the SetAddress() "recovery interval" required by USB and aborting the
* command on a timeout.
@@ -2911,7 +2927,10 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
if (timeleft <= 0) {
xhci_warn(xhci, "%s while waiting for a slot\n",
timeleft == 0 ? "Timeout" : "Signal");
- /* FIXME cancel the address device command */
+ /* cancel the address device command */
+ ret = xhci_cancel_cmd(xhci, NULL, cmd_trb);
+ if (ret < 0)
+ return ret;
return -ETIME;
}
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index dfd260a..1d72895 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1070,6 +1070,9 @@ union xhci_trb {
#define TRB_MFINDEX_WRAP 39
/* TRB IDs 40-47 reserved, 48-63 is vendor-defined */
+#define TRB_TYPE_LINK_LE32(x) (((x) & cpu_to_le32(TRB_TYPE_BITMASK)) == \
+ cpu_to_le32(TRB_TYPE(TRB_LINK)))
+
/* Nec vendor-specific command completion event. */
#define TRB_NEC_CMD_COMP 48
/* Get NEC firmware revision. */
@@ -1111,6 +1114,16 @@ struct xhci_td {
union xhci_trb *last_trb;
};
+/* xHCI command default timeout value */
+#define XHCI_CMD_DEFAULT_TIMEOUT (5 * HZ)
+
+/* command descriptor */
+struct xhci_cd {
+ struct list_head cancel_cmd_list;
+ struct xhci_command *command;
+ union xhci_trb *cmd_trb;
+};
+
struct xhci_dequeue_state {
struct xhci_segment *new_deq_seg;
union xhci_trb *new_deq_ptr;
@@ -1252,6 +1265,11 @@ struct xhci_hcd {
/* data structures */
struct xhci_device_context_array *dcbaa;
struct xhci_ring *cmd_ring;
+ unsigned int cmd_ring_state;
+#define CMD_RING_STATE_RUNNING (1 << 0)
+#define CMD_RING_STATE_ABORTED (1 << 1)
+#define CMD_RING_STATE_STOPPED (1 << 2)
+ struct list_head cancel_cmd_list;
unsigned int cmd_ring_reserved_trbs;
struct xhci_ring *event_ring;
struct xhci_erst erst;
@@ -1315,6 +1333,9 @@ struct xhci_hcd {
#define XHCI_BROKEN_MSI (1 << 6)
#define XHCI_RESET_ON_RESUME (1 << 7)
#define XHCI_AMD_0x96_HOST (1 << 9)
+#define XHCI_TRUST_TX_LENGTH (1 << 10)
+#define XHCI_SPURIOUS_REBOOT (1 << 13)
+#define XHCI_AVOID_BEI (1 << 15)
unsigned int num_active_eps;
unsigned int limit_active_eps;
/* There are two roothubs to keep track of bus suspend info for */
@@ -1483,6 +1504,8 @@ void xhci_unregister_pci(void);
#endif
/* xHCI host controller glue */
+int handshake(struct xhci_hcd *xhci, void __iomem *ptr,
+ u32 mask, u32 done, int usec);
void xhci_quiesce(struct xhci_hcd *xhci);
int xhci_halt(struct xhci_hcd *xhci);
int xhci_reset(struct xhci_hcd *xhci);
@@ -1565,6 +1588,8 @@ void xhci_queue_config_ep_quirk(struct xhci_hcd *xhci,
unsigned int slot_id, unsigned int ep_index,
struct xhci_dequeue_state *deq_state);
void xhci_stop_endpoint_command_watchdog(unsigned long arg);
+int xhci_cancel_cmd(struct xhci_hcd *xhci, struct xhci_command *command,
+ union xhci_trb *cmd_trb);
void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id,
unsigned int ep_index, unsigned int stream_id);
diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c
index fc15ad4..723e833 100644
--- a/drivers/usb/misc/emi62.c
+++ b/drivers/usb/misc/emi62.c
@@ -259,7 +259,7 @@ wraperr:
return err;
}
-static const struct usb_device_id id_table[] __devinitconst = {
+static const struct usb_device_id id_table[] = {
{ USB_DEVICE(EMI62_VENDOR_ID, EMI62_PRODUCT_ID) },
{ } /* Terminating entry */
};
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index bb10846..5707f56 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -1023,7 +1023,10 @@ test_ctrl_queue(struct usbtest_dev *dev, struct usbtest_param *param)
case 13: /* short read, resembling case 10 */
req.wValue = cpu_to_le16((USB_DT_CONFIG << 8) | 0);
/* last data packet "should" be DATA1, not DATA0 */
- len = 1024 - udev->descriptor.bMaxPacketSize0;
+ if (udev->speed == USB_SPEED_SUPER)
+ len = 1024 - 512;
+ else
+ len = 1024 - udev->descriptor.bMaxPacketSize0;
expected = -EREMOTEIO;
break;
case 14: /* short read; try to fill the last packet */
@@ -1382,11 +1385,15 @@ static int test_halt(struct usbtest_dev *tdev, int ep, struct urb *urb)
static int halt_simple(struct usbtest_dev *dev)
{
- int ep;
- int retval = 0;
- struct urb *urb;
+ int ep;
+ int retval = 0;
+ struct urb *urb;
+ struct usb_device *udev = testdev_to_usbdev(dev);
- urb = simple_alloc_urb(testdev_to_usbdev(dev), 0, 512);
+ if (udev->speed == USB_SPEED_SUPER)
+ urb = simple_alloc_urb(udev, 0, 1024);
+ else
+ urb = simple_alloc_urb(udev, 0, 512);
if (urb == NULL)
return -ENOMEM;
diff --git a/drivers/usb/notify/Kconfig b/drivers/usb/notify/Kconfig
new file mode 100755
index 0000000..159affa
--- /dev/null
+++ b/drivers/usb/notify/Kconfig
@@ -0,0 +1,11 @@
+#
+# USB Host notify configuration
+#
+
+config USB_HOST_NOTIFY
+ boolean "USB Host notify Driver"
+ depends on USB
+ help
+ Android framework needs uevents for usb host operation.
+ Host notify Driver serves uevent format
+ that is used by usb host or otg. \ No newline at end of file
diff --git a/drivers/usb/notify/Makefile b/drivers/usb/notify/Makefile
new file mode 100755
index 0000000..996eaa3
--- /dev/null
+++ b/drivers/usb/notify/Makefile
@@ -0,0 +1,4 @@
+
+# host notify driver
+obj-y += host_notify_class.o
+
diff --git a/drivers/usb/notify/host_notify_class.c b/drivers/usb/notify/host_notify_class.c
new file mode 100755
index 0000000..09ad529
--- /dev/null
+++ b/drivers/usb/notify/host_notify_class.c
@@ -0,0 +1,262 @@
+/*
+ * drivers/usb/notify/host_notify_class.c
+ *
+ * Copyright (C) 2011 Samsung, Inc.
+ * Author: Dongrak Shin <dongrak.shin@samsung.com>
+ *
+*/
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/err.h>
+#include <linux/host_notify.h>
+
+struct notify_data {
+ struct class *host_notify_class;
+ atomic_t device_count;
+};
+
+static struct notify_data host_notify;
+
+static ssize_t mode_show(
+ struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct host_notify_dev *ndev = (struct host_notify_dev *)
+ dev_get_drvdata(dev);
+ char *mode;
+
+ switch (ndev->mode) {
+ case NOTIFY_HOST_MODE:
+ mode = "HOST";
+ break;
+ case NOTIFY_PERIPHERAL_MODE:
+ mode = "PERIPHERAL";
+ break;
+ case NOTIFY_TEST_MODE:
+ mode = "TEST";
+ break;
+ case NOTIFY_NONE_MODE:
+ default:
+ mode = "NONE";
+ break;
+ }
+
+ return sprintf(buf, "%s\n", mode);
+}
+
+static ssize_t mode_store(
+ struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct host_notify_dev *ndev = (struct host_notify_dev *)
+ dev_get_drvdata(dev);
+
+ char *mode;
+ size_t ret = -ENOMEM;
+
+ mode = kzalloc(size+1, GFP_KERNEL);
+ if (!mode)
+ goto error;
+
+ sscanf(buf, "%s", mode);
+
+ if (ndev->set_mode) {
+ if (!strcmp(mode, "HOST"))
+ ndev->set_mode(NOTIFY_SET_ON);
+ else if (!strcmp(mode, "NONE"))
+ ndev->set_mode(NOTIFY_SET_OFF);
+ printk(KERN_INFO "host_notify: set mode %s\n", mode);
+ }
+ ret = size;
+ kfree(mode);
+error:
+ return ret;
+}
+
+static ssize_t booster_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct host_notify_dev *ndev = (struct host_notify_dev *)
+ dev_get_drvdata(dev);
+ char *booster;
+
+ switch (ndev->booster) {
+ case NOTIFY_POWER_ON:
+ booster = "ON";
+ break;
+ case NOTIFY_POWER_OFF:
+ default:
+ booster = "OFF";
+ break;
+ }
+
+ return sprintf(buf, "%s\n", booster);
+}
+
+static ssize_t booster_store(
+ struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct host_notify_dev *ndev = (struct host_notify_dev *)
+ dev_get_drvdata(dev);
+
+ char *booster;
+ size_t ret = -ENOMEM;
+
+ booster = kzalloc(size+1, GFP_KERNEL);
+ if (!booster)
+ goto error;
+
+ sscanf(buf, "%s", booster);
+
+ if (ndev->set_booster) {
+ if (!strcmp(booster, "ON")) {
+ ndev->set_booster(NOTIFY_SET_ON);
+ ndev->mode = NOTIFY_TEST_MODE;
+ } else if (!strcmp(booster, "OFF")) {
+ ndev->set_booster(NOTIFY_SET_OFF);
+ ndev->mode = NOTIFY_NONE_MODE;
+ }
+ printk(KERN_INFO "host_notify: set booster %s\n", booster);
+ }
+ ret = size;
+ kfree(booster);
+error:
+ return ret;
+}
+
+static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR | S_IWGRP, mode_show, mode_store);
+static DEVICE_ATTR(booster, S_IRUGO | S_IWUSR | S_IWGRP,
+ booster_show, booster_store);
+
+static struct attribute *host_notify_attrs[] = {
+ &dev_attr_mode.attr,
+ &dev_attr_booster.attr,
+ NULL,
+};
+
+static struct attribute_group host_notify_attr_grp = {
+ .attrs = host_notify_attrs,
+};
+
+void host_state_notify(struct host_notify_dev *ndev, int state)
+{
+ printk(KERN_INFO "host_notify: ndev name=%s: from state=%d -> to state=%d\n",
+ ndev->name, ndev->state, state);
+ if (ndev->state != state) {
+ ndev->state = state;
+ kobject_uevent(&ndev->dev->kobj, KOBJ_CHANGE);
+ }
+}
+EXPORT_SYMBOL_GPL(host_state_notify);
+
+static int
+host_notify_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+ struct host_notify_dev *ndev = (struct host_notify_dev *)
+ dev_get_drvdata(dev);
+ char *state;
+
+ if (!ndev) {
+ /* this happens when the device is first created */
+ return 0;
+ }
+ switch (ndev->state) {
+ case NOTIFY_HOST_ADD:
+ state = "ADD";
+ break;
+ case NOTIFY_HOST_REMOVE:
+ state = "REMOVE";
+ break;
+ case NOTIFY_HOST_OVERCURRENT:
+ state = "OVERCURRENT";
+ break;
+ case NOTIFY_HOST_LOWBATT:
+ state = "LOWBATT";
+ break;
+ case NOTIFY_HOST_UNKNOWN:
+ state = "UNKNOWN";
+ break;
+ case NOTIFY_HOST_NONE:
+ default:
+ return 0;
+ }
+ if (add_uevent_var(env, "DEVNAME=%s", ndev->dev->kobj.name))
+ return -ENOMEM;
+ if (add_uevent_var(env, "STATE=%s", state))
+ return -ENOMEM;
+ return 0;
+}
+
+static int create_notify_class(void)
+{
+ if (!host_notify.host_notify_class) {
+ host_notify.host_notify_class
+ = class_create(THIS_MODULE, "host_notify");
+ if (IS_ERR(host_notify.host_notify_class))
+ return PTR_ERR(host_notify.host_notify_class);
+ atomic_set(&host_notify.device_count, 0);
+ host_notify.host_notify_class->dev_uevent = host_notify_uevent;
+ }
+
+ return 0;
+}
+
+int host_notify_dev_register(struct host_notify_dev *ndev)
+{
+ int ret;
+
+ if (!host_notify.host_notify_class) {
+ ret = create_notify_class();
+ if (ret < 0)
+ return ret;
+ }
+
+ ndev->index = atomic_inc_return(&host_notify.device_count);
+ ndev->dev = device_create(host_notify.host_notify_class, NULL,
+ MKDEV(0, ndev->index), NULL, ndev->name);
+ if (IS_ERR(ndev->dev))
+ return PTR_ERR(ndev->dev);
+
+ ret = sysfs_create_group(&ndev->dev->kobj, &host_notify_attr_grp);
+ if (ret < 0) {
+ device_destroy(host_notify.host_notify_class,
+ MKDEV(0, ndev->index));
+ return ret;
+ }
+
+ dev_set_drvdata(ndev->dev, ndev);
+ ndev->state = 0;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(host_notify_dev_register);
+
+void host_notify_dev_unregister(struct host_notify_dev *ndev)
+{
+ ndev->state = NOTIFY_HOST_NONE;
+ sysfs_remove_group(&ndev->dev->kobj, &host_notify_attr_grp);
+ device_destroy(host_notify.host_notify_class, MKDEV(0, ndev->index));
+ dev_set_drvdata(ndev->dev, NULL);
+}
+EXPORT_SYMBOL_GPL(host_notify_dev_unregister);
+
+static int __init notify_class_init(void)
+{
+ return create_notify_class();
+}
+
+static void __exit notify_class_exit(void)
+{
+ class_destroy(host_notify.host_notify_class);
+}
+
+module_init(notify_class_init);
+module_exit(notify_class_exit);
+
+MODULE_AUTHOR("Dongrak Shin <dongrak.shin@samsung.com>");
+MODULE_DESCRIPTION("Usb host notify driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index f2c57e0..35e6b5f 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -82,6 +82,7 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x10C4, 0x8066) }, /* Argussoft In-System Programmer */
{ USB_DEVICE(0x10C4, 0x806F) }, /* IMS USB to RS422 Converter Cable */
{ USB_DEVICE(0x10C4, 0x807A) }, /* Crumb128 board */
+ { USB_DEVICE(0x10C4, 0x80C4) }, /* Cygnal Integrated Products, Inc., Optris infrared thermometer */
{ USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */
{ USB_DEVICE(0x10C4, 0x80DD) }, /* Tracient RFID */
{ USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */
@@ -92,6 +93,7 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */
{ USB_DEVICE(0x10C4, 0x8156) }, /* B&G H3000 link cable */
{ USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */
+ { USB_DEVICE(0x10C4, 0x815F) }, /* Timewave HamLinkUSB */
{ USB_DEVICE(0x10C4, 0x818B) }, /* AVIT Research USB to TTL */
{ USB_DEVICE(0x10C4, 0x819F) }, /* MJS USB Toslink Switcher */
{ USB_DEVICE(0x10C4, 0x81A6) }, /* ThinkOptics WavIt */
@@ -133,7 +135,13 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x10CE, 0xEA6A) }, /* Silicon Labs MobiData GPRS USB Modem 100EU */
{ USB_DEVICE(0x13AD, 0x9999) }, /* Baltech card reader */
{ USB_DEVICE(0x1555, 0x0004) }, /* Owen AC4 USB-RS485 Converter */
+ { USB_DEVICE(0x166A, 0x0201) }, /* Clipsal 5500PACA C-Bus Pascal Automation Controller */
+ { USB_DEVICE(0x166A, 0x0301) }, /* Clipsal 5800PC C-Bus Wireless PC Interface */
{ USB_DEVICE(0x166A, 0x0303) }, /* Clipsal 5500PCU C-Bus USB interface */
+ { USB_DEVICE(0x166A, 0x0304) }, /* Clipsal 5000CT2 C-Bus Black and White Touchscreen */
+ { USB_DEVICE(0x166A, 0x0305) }, /* Clipsal C-5000CT2 C-Bus Spectrum Colour Touchscreen */
+ { USB_DEVICE(0x166A, 0x0401) }, /* Clipsal L51xx C-Bus Architectural Dimmer */
+ { USB_DEVICE(0x166A, 0x0101) }, /* Clipsal 5560884 C-Bus Multi-room Audio Matrix Switcher */
{ USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */
{ USB_DEVICE(0x16DC, 0x0010) }, /* W-IE-NE-R Plein & Baus GmbH PL512 Power Supply */
{ USB_DEVICE(0x16DC, 0x0011) }, /* W-IE-NE-R Plein & Baus GmbH RCM Remote Control for MARATON Power Supply */
@@ -145,7 +153,11 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */
{ USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
{ USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */
+ { USB_DEVICE(0x1E29, 0x0102) }, /* Festo CPX-USB */
+ { USB_DEVICE(0x1E29, 0x0501) }, /* Festo CMSP */
{ USB_DEVICE(0x3195, 0xF190) }, /* Link Instruments MSO-19 */
+ { USB_DEVICE(0x3195, 0xF280) }, /* Link Instruments MSO-28 */
+ { USB_DEVICE(0x3195, 0xF281) }, /* Link Instruments MSO-28 */
{ USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */
{ } /* Terminating Entry */
};
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 60d7b1e..00f1bf5 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -582,6 +582,8 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_IBS_PEDO_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_IBS_PROD_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_TAVIR_STK500_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_TIAO_UMPA_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
/*
* ELV devices:
*/
@@ -702,6 +704,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_PCDJ_DAC2_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_RRCIRKITS_LOCOBUFFER_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ASK_RDR400_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_NZR_SEM_USB_PID) },
{ USB_DEVICE(ICOM_VID, ICOM_ID_1_PID) },
{ USB_DEVICE(ICOM_VID, ICOM_OPC_U_UC_PID) },
{ USB_DEVICE(ICOM_VID, ICOM_ID_RP2C1_PID) },
@@ -735,6 +738,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) },
{ USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_SERIAL_VX7_PID) },
{ USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_CT29B_PID) },
+ { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_RTS01_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_PHI_FISCO_PID) },
{ USB_DEVICE(TML_VID, TML_USB_SERIAL_PID) },
@@ -801,12 +805,33 @@ static struct usb_device_id id_table_combined [] = {
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(ADI_VID, ADI_GNICEPLUS_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
- { USB_DEVICE(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID,
+ USB_CLASS_VENDOR_SPEC,
+ USB_SUBCLASS_VENDOR_SPEC, 0x00) },
{ USB_DEVICE(JETI_VID, JETI_SPC1201_PID) },
{ USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(LARSENBRUSGAARD_VID, LB_ALTITRACK_PID) },
{ USB_DEVICE(GN_OTOMETRICS_VID, AURICAL_USB_PID) },
+ { USB_DEVICE(FTDI_VID, PI_C865_PID) },
+ { USB_DEVICE(FTDI_VID, PI_C857_PID) },
+ { USB_DEVICE(PI_VID, PI_C866_PID) },
+ { USB_DEVICE(PI_VID, PI_C663_PID) },
+ { USB_DEVICE(PI_VID, PI_C725_PID) },
+ { USB_DEVICE(PI_VID, PI_E517_PID) },
+ { USB_DEVICE(PI_VID, PI_C863_PID) },
+ { USB_DEVICE(PI_VID, PI_E861_PID) },
+ { USB_DEVICE(PI_VID, PI_C867_PID) },
+ { USB_DEVICE(PI_VID, PI_E609_PID) },
+ { USB_DEVICE(PI_VID, PI_E709_PID) },
+ { USB_DEVICE(PI_VID, PI_100F_PID) },
+ { USB_DEVICE(PI_VID, PI_1011_PID) },
+ { USB_DEVICE(PI_VID, PI_1012_PID) },
+ { USB_DEVICE(PI_VID, PI_1013_PID) },
+ { USB_DEVICE(PI_VID, PI_1014_PID) },
+ { USB_DEVICE(PI_VID, PI_1015_PID) },
+ { USB_DEVICE(PI_VID, PI_1016_PID) },
+ { USB_DEVICE(KONDO_VID, KONDO_USB_SERIAL_PID) },
{ USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) },
{ USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index c6dd18e..7b5eb74 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -75,6 +75,9 @@
#define FTDI_OPENDCC_GATEWAY_PID 0xBFDB
#define FTDI_OPENDCC_GBM_PID 0xBFDC
+/* NZR SEM 16+ USB (http://www.nzr.de) */
+#define FTDI_NZR_SEM_USB_PID 0xC1E0 /* NZR SEM-LOG16+ */
+
/*
* RR-CirKits LocoBuffer USB (http://www.rr-cirkits.com)
*/
@@ -514,6 +517,11 @@
*/
#define FTDI_TAVIR_STK500_PID 0xFA33 /* STK500 AVR programmer */
+/*
+ * TIAO product ids (FTDI_VID)
+ * http://www.tiaowiki.com/w/Main_Page
+ */
+#define FTDI_TIAO_UMPA_PID 0x8a98 /* TIAO/DIYGADGET USB Multi-Protocol Adapter */
/********************************/
@@ -539,7 +547,10 @@
/*
* Microchip Technology, Inc.
*
- * MICROCHIP_VID (0x04D8) and MICROCHIP_USB_BOARD_PID (0x000A) are also used by:
+ * MICROCHIP_VID (0x04D8) and MICROCHIP_USB_BOARD_PID (0x000A) are
+ * used by single function CDC ACM class based firmware demo
+ * applications. The VID/PID has also been used in firmware
+ * emulating FTDI serial chips by:
* Hornby Elite - Digital Command Control Console
* http://www.hornby.com/hornby-dcc/controllers/
*/
@@ -784,6 +795,41 @@
#define RTSYSTEMS_VID 0x2100 /* Vendor ID */
#define RTSYSTEMS_SERIAL_VX7_PID 0x9e52 /* Serial converter for VX-7 Radios using FT232RL */
#define RTSYSTEMS_CT29B_PID 0x9e54 /* CT29B Radio Cable */
+#define RTSYSTEMS_RTS01_PID 0x9e57 /* USB-RTS01 Radio Cable */
+
+
+/*
+ * Physik Instrumente
+ * http://www.physikinstrumente.com/en/products/
+ */
+/* These two devices use the VID of FTDI */
+#define PI_C865_PID 0xe0a0 /* PI C-865 Piezomotor Controller */
+#define PI_C857_PID 0xe0a1 /* PI Encoder Trigger Box */
+
+#define PI_VID 0x1a72 /* Vendor ID */
+#define PI_C866_PID 0x1000 /* PI C-866 Piezomotor Controller */
+#define PI_C663_PID 0x1001 /* PI C-663 Mercury-Step */
+#define PI_C725_PID 0x1002 /* PI C-725 Piezomotor Controller */
+#define PI_E517_PID 0x1005 /* PI E-517 Digital Piezo Controller Operation Module */
+#define PI_C863_PID 0x1007 /* PI C-863 */
+#define PI_E861_PID 0x1008 /* PI E-861 Piezomotor Controller */
+#define PI_C867_PID 0x1009 /* PI C-867 Piezomotor Controller */
+#define PI_E609_PID 0x100D /* PI E-609 Digital Piezo Controller */
+#define PI_E709_PID 0x100E /* PI E-709 Digital Piezo Controller */
+#define PI_100F_PID 0x100F /* PI Digital Piezo Controller */
+#define PI_1011_PID 0x1011 /* PI Digital Piezo Controller */
+#define PI_1012_PID 0x1012 /* PI Motion Controller */
+#define PI_1013_PID 0x1013 /* PI Motion Controller */
+#define PI_1014_PID 0x1014 /* PI Device */
+#define PI_1015_PID 0x1015 /* PI Device */
+#define PI_1016_PID 0x1016 /* PI Digital Servo Module */
+
+/*
+ * Kondo Kagaku Co.Ltd.
+ * http://www.kondo-robot.com/EN
+ */
+#define KONDO_VID 0x165c
+#define KONDO_USB_SERIAL_PID 0x0002
/*
* Bayer Ascensia Contour blood glucose meter USB-converter cable.
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index ba0d287..42de17b 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -359,13 +359,16 @@ static int mct_u232_set_modem_ctrl(struct usb_serial *serial,
MCT_U232_SET_REQUEST_TYPE,
0, 0, buf, MCT_U232_SET_MODEM_CTRL_SIZE,
WDR_TIMEOUT);
- if (rc < 0)
- dev_err(&serial->dev->dev,
- "Set MODEM CTRL 0x%x failed (error = %d)\n", mcr, rc);
+ kfree(buf);
+
dbg("set_modem_ctrl: state=0x%x ==> mcr=0x%x", control_state, mcr);
- kfree(buf);
- return rc;
+ if (rc < 0) {
+ dev_err(&serial->dev->dev,
+ "Set MODEM CTRL 0x%x failed (error = %d)\n", mcr, rc);
+ return rc;
+ }
+ return 0;
} /* mct_u232_set_modem_ctrl */
static int mct_u232_get_modem_stat(struct usb_serial *serial,
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 3257519..2d34dfd 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -206,7 +206,7 @@ static const struct usb_device_id moschip_port_id_table[] = {
{} /* terminating entry */
};
-static const struct usb_device_id moschip_id_table_combined[] __devinitconst = {
+static const struct usb_device_id moschip_id_table_combined[] = {
{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)},
{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},
{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2)},
@@ -235,12 +235,10 @@ struct moschip_port {
int port_num; /*Actual port number in the device(1,2,etc) */
struct urb *write_urb; /* write URB for this port */
struct urb *read_urb; /* read URB for this port */
- struct urb *int_urb;
__u8 shadowLCR; /* last LCR value received */
__u8 shadowMCR; /* last MCR value received */
char open;
char open_ports;
- char zombie;
wait_queue_head_t wait_chase; /* for handling sleeping while waiting for chase to finish */
wait_queue_head_t delta_msr_wait; /* for handling sleeping while waiting for msr change to happen */
int delta_msr_cond;
@@ -505,7 +503,6 @@ static void mos7840_control_callback(struct urb *urb)
unsigned char *data;
struct moschip_port *mos7840_port;
__u8 regval = 0x0;
- int result = 0;
int status = urb->status;
mos7840_port = urb->context;
@@ -524,7 +521,7 @@ static void mos7840_control_callback(struct urb *urb)
default:
dbg("%s - nonzero urb status received: %d", __func__,
status);
- goto exit;
+ return;
}
dbg("%s urb buffer size is %d", __func__, urb->actual_length);
@@ -537,17 +534,6 @@ static void mos7840_control_callback(struct urb *urb)
mos7840_handle_new_msr(mos7840_port, regval);
else if (mos7840_port->MsrLsr == 1)
mos7840_handle_new_lsr(mos7840_port, regval);
-
-exit:
- spin_lock(&mos7840_port->pool_lock);
- if (!mos7840_port->zombie)
- result = usb_submit_urb(mos7840_port->int_urb, GFP_ATOMIC);
- spin_unlock(&mos7840_port->pool_lock);
- if (result) {
- dev_err(&urb->dev->dev,
- "%s - Error %d submitting interrupt urb\n",
- __func__, result);
- }
}
static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg,
@@ -655,14 +641,7 @@ static void mos7840_interrupt_callback(struct urb *urb)
wreg = MODEM_STATUS_REGISTER;
break;
}
- spin_lock(&mos7840_port->pool_lock);
- if (!mos7840_port->zombie) {
- rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data);
- } else {
- spin_unlock(&mos7840_port->pool_lock);
- return;
- }
- spin_unlock(&mos7840_port->pool_lock);
+ rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data);
}
}
}
@@ -1191,9 +1170,12 @@ static int mos7840_chars_in_buffer(struct tty_struct *tty)
}
spin_lock_irqsave(&mos7840_port->pool_lock, flags);
- for (i = 0; i < NUM_URBS; ++i)
- if (mos7840_port->busy[i])
- chars += URB_TRANSFER_BUFFER_SIZE;
+ for (i = 0; i < NUM_URBS; ++i) {
+ if (mos7840_port->busy[i]) {
+ struct urb *urb = mos7840_port->write_urb_pool[i];
+ chars += urb->transfer_buffer_length;
+ }
+ }
spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
dbg("%s - returns %d", __func__, chars);
return chars;
@@ -2592,7 +2574,6 @@ error:
kfree(mos7840_port->ctrl_buf);
usb_free_urb(mos7840_port->control_urb);
kfree(mos7840_port);
- serial->port[i] = NULL;
}
return status;
}
@@ -2623,9 +2604,6 @@ static void mos7840_disconnect(struct usb_serial *serial)
mos7840_port = mos7840_get_port_private(serial->port[i]);
dbg ("mos7840_port %d = %p", i, mos7840_port);
if (mos7840_port) {
- spin_lock_irqsave(&mos7840_port->pool_lock, flags);
- mos7840_port->zombie = 1;
- spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
usb_kill_urb(mos7840_port->control_urb);
}
}
@@ -2659,6 +2637,7 @@ static void mos7840_release(struct usb_serial *serial)
mos7840_port = mos7840_get_port_private(serial->port[i]);
dbg("mos7840_port %d = %p", i, mos7840_port);
if (mos7840_port) {
+ usb_free_urb(mos7840_port->control_urb);
kfree(mos7840_port->ctrl_buf);
kfree(mos7840_port->dr);
kfree(mos7840_port);
diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c
index 96423f3..5d274b3 100644
--- a/drivers/usb/serial/opticon.c
+++ b/drivers/usb/serial/opticon.c
@@ -160,7 +160,11 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype,
{
struct usb_serial *serial = port->serial;
int retval;
- u8 buffer[2];
+ u8 *buffer;
+
+ buffer = kzalloc(1, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
buffer[0] = val;
/* Send the message to the vendor control endpoint
@@ -169,6 +173,7 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype,
requesttype,
USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE,
0, 0, buffer, 1, 0);
+ kfree(buffer);
return retval;
}
@@ -292,7 +297,7 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,
if (!dr) {
dev_err(&port->dev, "out of memory\n");
count = -ENOMEM;
- goto error;
+ goto error_no_dr;
}
dr->bRequestType = USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT;
@@ -322,6 +327,8 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,
return count;
error:
+ kfree(dr);
+error_no_dr:
usb_free_urb(urb);
error_no_urb:
kfree(buffer);
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index cbe3451..c334670 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -47,6 +47,7 @@
/* Function prototypes */
static int option_probe(struct usb_serial *serial,
const struct usb_device_id *id);
+static void option_release(struct usb_serial *serial);
static int option_send_setup(struct usb_serial_port *port);
static void option_instat_callback(struct urb *urb);
@@ -79,84 +80,9 @@ static void option_instat_callback(struct urb *urb);
#define OPTION_PRODUCT_GTM380_MODEM 0x7201
#define HUAWEI_VENDOR_ID 0x12D1
-#define HUAWEI_PRODUCT_E600 0x1001
-#define HUAWEI_PRODUCT_E220 0x1003
-#define HUAWEI_PRODUCT_E220BIS 0x1004
-#define HUAWEI_PRODUCT_E1401 0x1401
-#define HUAWEI_PRODUCT_E1402 0x1402
-#define HUAWEI_PRODUCT_E1403 0x1403
-#define HUAWEI_PRODUCT_E1404 0x1404
-#define HUAWEI_PRODUCT_E1405 0x1405
-#define HUAWEI_PRODUCT_E1406 0x1406
-#define HUAWEI_PRODUCT_E1407 0x1407
-#define HUAWEI_PRODUCT_E1408 0x1408
-#define HUAWEI_PRODUCT_E1409 0x1409
-#define HUAWEI_PRODUCT_E140A 0x140A
-#define HUAWEI_PRODUCT_E140B 0x140B
-#define HUAWEI_PRODUCT_E140C 0x140C
-#define HUAWEI_PRODUCT_E140D 0x140D
-#define HUAWEI_PRODUCT_E140E 0x140E
-#define HUAWEI_PRODUCT_E140F 0x140F
-#define HUAWEI_PRODUCT_E1410 0x1410
-#define HUAWEI_PRODUCT_E1411 0x1411
-#define HUAWEI_PRODUCT_E1412 0x1412
-#define HUAWEI_PRODUCT_E1413 0x1413
-#define HUAWEI_PRODUCT_E1414 0x1414
-#define HUAWEI_PRODUCT_E1415 0x1415
-#define HUAWEI_PRODUCT_E1416 0x1416
-#define HUAWEI_PRODUCT_E1417 0x1417
-#define HUAWEI_PRODUCT_E1418 0x1418
-#define HUAWEI_PRODUCT_E1419 0x1419
-#define HUAWEI_PRODUCT_E141A 0x141A
-#define HUAWEI_PRODUCT_E141B 0x141B
-#define HUAWEI_PRODUCT_E141C 0x141C
-#define HUAWEI_PRODUCT_E141D 0x141D
-#define HUAWEI_PRODUCT_E141E 0x141E
-#define HUAWEI_PRODUCT_E141F 0x141F
-#define HUAWEI_PRODUCT_E1420 0x1420
-#define HUAWEI_PRODUCT_E1421 0x1421
-#define HUAWEI_PRODUCT_E1422 0x1422
-#define HUAWEI_PRODUCT_E1423 0x1423
-#define HUAWEI_PRODUCT_E1424 0x1424
-#define HUAWEI_PRODUCT_E1425 0x1425
-#define HUAWEI_PRODUCT_E1426 0x1426
-#define HUAWEI_PRODUCT_E1427 0x1427
-#define HUAWEI_PRODUCT_E1428 0x1428
-#define HUAWEI_PRODUCT_E1429 0x1429
-#define HUAWEI_PRODUCT_E142A 0x142A
-#define HUAWEI_PRODUCT_E142B 0x142B
-#define HUAWEI_PRODUCT_E142C 0x142C
-#define HUAWEI_PRODUCT_E142D 0x142D
-#define HUAWEI_PRODUCT_E142E 0x142E
-#define HUAWEI_PRODUCT_E142F 0x142F
-#define HUAWEI_PRODUCT_E1430 0x1430
-#define HUAWEI_PRODUCT_E1431 0x1431
-#define HUAWEI_PRODUCT_E1432 0x1432
-#define HUAWEI_PRODUCT_E1433 0x1433
-#define HUAWEI_PRODUCT_E1434 0x1434
-#define HUAWEI_PRODUCT_E1435 0x1435
-#define HUAWEI_PRODUCT_E1436 0x1436
-#define HUAWEI_PRODUCT_E1437 0x1437
-#define HUAWEI_PRODUCT_E1438 0x1438
-#define HUAWEI_PRODUCT_E1439 0x1439
-#define HUAWEI_PRODUCT_E143A 0x143A
-#define HUAWEI_PRODUCT_E143B 0x143B
-#define HUAWEI_PRODUCT_E143C 0x143C
-#define HUAWEI_PRODUCT_E143D 0x143D
-#define HUAWEI_PRODUCT_E143E 0x143E
-#define HUAWEI_PRODUCT_E143F 0x143F
#define HUAWEI_PRODUCT_K4505 0x1464
#define HUAWEI_PRODUCT_K3765 0x1465
-#define HUAWEI_PRODUCT_E14AC 0x14AC
-#define HUAWEI_PRODUCT_K3806 0x14AE
#define HUAWEI_PRODUCT_K4605 0x14C6
-#define HUAWEI_PRODUCT_K3770 0x14C9
-#define HUAWEI_PRODUCT_K3771 0x14CA
-#define HUAWEI_PRODUCT_K4510 0x14CB
-#define HUAWEI_PRODUCT_K4511 0x14CC
-#define HUAWEI_PRODUCT_ETS1220 0x1803
-#define HUAWEI_PRODUCT_E353 0x1506
-#define HUAWEI_PRODUCT_E173S 0x1C05
#define QUANTA_VENDOR_ID 0x0408
#define QUANTA_PRODUCT_Q101 0xEA02
@@ -234,6 +160,7 @@ static void option_instat_callback(struct urb *urb);
#define NOVATELWIRELESS_PRODUCT_G1 0xA001
#define NOVATELWIRELESS_PRODUCT_G1_M 0xA002
#define NOVATELWIRELESS_PRODUCT_G2 0xA010
+#define NOVATELWIRELESS_PRODUCT_MC551 0xB001
/* AMOI PRODUCTS */
#define AMOI_VENDOR_ID 0x1614
@@ -425,7 +352,7 @@ static void option_instat_callback(struct urb *urb);
#define SAMSUNG_VENDOR_ID 0x04e8
#define SAMSUNG_PRODUCT_GT_B3730 0x6889
-/* YUGA products www.yuga-info.com*/
+/* YUGA products www.yuga-info.com gavin.kx@qq.com */
#define YUGA_VENDOR_ID 0x257A
#define YUGA_PRODUCT_CEM600 0x1601
#define YUGA_PRODUCT_CEM610 0x1602
@@ -442,6 +369,8 @@ static void option_instat_callback(struct urb *urb);
#define YUGA_PRODUCT_CEU516 0x160C
#define YUGA_PRODUCT_CEU528 0x160D
#define YUGA_PRODUCT_CEU526 0x160F
+#define YUGA_PRODUCT_CEU881 0x161F
+#define YUGA_PRODUCT_CEU882 0x162F
#define YUGA_PRODUCT_CWM600 0x2601
#define YUGA_PRODUCT_CWM610 0x2602
@@ -457,23 +386,26 @@ static void option_instat_callback(struct urb *urb);
#define YUGA_PRODUCT_CWU518 0x260B
#define YUGA_PRODUCT_CWU516 0x260C
#define YUGA_PRODUCT_CWU528 0x260D
+#define YUGA_PRODUCT_CWU581 0x260E
#define YUGA_PRODUCT_CWU526 0x260F
-
-#define YUGA_PRODUCT_CLM600 0x2601
-#define YUGA_PRODUCT_CLM610 0x2602
-#define YUGA_PRODUCT_CLM500 0x2603
-#define YUGA_PRODUCT_CLM510 0x2604
-#define YUGA_PRODUCT_CLM800 0x2605
-#define YUGA_PRODUCT_CLM900 0x2606
-
-#define YUGA_PRODUCT_CLU718 0x2607
-#define YUGA_PRODUCT_CLU716 0x2608
-#define YUGA_PRODUCT_CLU728 0x2609
-#define YUGA_PRODUCT_CLU726 0x260A
-#define YUGA_PRODUCT_CLU518 0x260B
-#define YUGA_PRODUCT_CLU516 0x260C
-#define YUGA_PRODUCT_CLU528 0x260D
-#define YUGA_PRODUCT_CLU526 0x260F
+#define YUGA_PRODUCT_CWU582 0x261F
+#define YUGA_PRODUCT_CWU583 0x262F
+
+#define YUGA_PRODUCT_CLM600 0x3601
+#define YUGA_PRODUCT_CLM610 0x3602
+#define YUGA_PRODUCT_CLM500 0x3603
+#define YUGA_PRODUCT_CLM510 0x3604
+#define YUGA_PRODUCT_CLM800 0x3605
+#define YUGA_PRODUCT_CLM900 0x3606
+
+#define YUGA_PRODUCT_CLU718 0x3607
+#define YUGA_PRODUCT_CLU716 0x3608
+#define YUGA_PRODUCT_CLU728 0x3609
+#define YUGA_PRODUCT_CLU726 0x360A
+#define YUGA_PRODUCT_CLU518 0x360B
+#define YUGA_PRODUCT_CLU516 0x360C
+#define YUGA_PRODUCT_CLU528 0x360D
+#define YUGA_PRODUCT_CLU526 0x360F
/* Viettel products */
#define VIETTEL_VENDOR_ID 0x2262
@@ -489,6 +421,19 @@ static void option_instat_callback(struct urb *urb);
/* MediaTek products */
#define MEDIATEK_VENDOR_ID 0x0e8d
+#define MEDIATEK_PRODUCT_DC_1COM 0x00a0
+#define MEDIATEK_PRODUCT_DC_4COM 0x00a5
+#define MEDIATEK_PRODUCT_DC_5COM 0x00a4
+#define MEDIATEK_PRODUCT_7208_1COM 0x7101
+#define MEDIATEK_PRODUCT_7208_2COM 0x7102
+#define MEDIATEK_PRODUCT_FP_1COM 0x0003
+#define MEDIATEK_PRODUCT_FP_2COM 0x0023
+#define MEDIATEK_PRODUCT_FPDC_1COM 0x0043
+#define MEDIATEK_PRODUCT_FPDC_2COM 0x0033
+
+/* Cellient products */
+#define CELLIENT_VENDOR_ID 0x2692
+#define CELLIENT_PRODUCT_MEN200 0x9005
/* some devices interfaces need special handling due to a number of reasons */
enum option_blacklist_reason {
@@ -542,6 +487,10 @@ static const struct option_blacklist_info net_intf1_blacklist = {
.reserved = BIT(1),
};
+static const struct option_blacklist_info net_intf2_blacklist = {
+ .reserved = BIT(2),
+};
+
static const struct option_blacklist_info net_intf3_blacklist = {
.reserved = BIT(3),
};
@@ -554,11 +503,19 @@ static const struct option_blacklist_info net_intf5_blacklist = {
.reserved = BIT(5),
};
+static const struct option_blacklist_info net_intf6_blacklist = {
+ .reserved = BIT(6),
+};
+
static const struct option_blacklist_info zte_mf626_blacklist = {
.sendsetup = BIT(0) | BIT(1),
.reserved = BIT(4),
};
+static const struct option_blacklist_info zte_1255_blacklist = {
+ .reserved = BIT(3) | BIT(4),
+};
+
static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
@@ -590,99 +547,123 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLX) },
{ USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GKE) },
{ USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLE) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220BIS, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1401, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1402, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1403, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1404, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1405, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1406, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1407, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1408, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1409, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140A, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140B, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140C, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140D, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140E, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140F, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1410, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1411, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1412, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1413, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1414, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1415, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1416, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1417, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1418, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1419, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141A, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141B, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141C, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141D, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141E, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141F, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1420, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1421, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1422, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1423, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1424, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1425, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1426, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1427, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1428, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1429, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142A, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142B, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142C, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142D, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142E, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142F, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1430, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1431, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1432, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1433, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1434, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1435, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1436, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1437, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1438, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1439, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143A, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143B, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143C, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143D, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143E, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143F, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173S, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ETS1220, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3806, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x31) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x32) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3771, 0xff, 0x02, 0x31) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3771, 0xff, 0x02, 0x32) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4510, 0xff, 0x01, 0x31) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4510, 0xff, 0x01, 0x32) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4511, 0xff, 0x01, 0x31) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4511, 0xff, 0x01, 0x32) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x01) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x02) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x03) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x10) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x12) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x13) },
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x01) }, /* E398 3G Modem */
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x02) }, /* E398 3G PC UI Interface */
- { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x03) }, /* E398 3G Application Interface */
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0xff, 0xff) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x01) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x02) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x03) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x04) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x05) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x06) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0D) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0E) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0F) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x10) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x12) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x13) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x14) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x15) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x17) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x18) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x19) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x1A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x1B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x1C) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x31) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x32) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x33) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x34) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x35) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x36) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3D) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3E) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3F) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x48) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x49) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x4A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x4B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x4C) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x61) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x62) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x63) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x64) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x65) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x66) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6D) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6E) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6F) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x78) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x79) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x7A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x7B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x7C) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x01) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x02) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x03) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x04) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x05) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x06) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0D) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0E) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0F) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x10) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x12) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x13) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x14) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x15) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x17) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x18) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x19) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x1A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x1B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x1C) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x31) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x32) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x33) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x34) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x35) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x36) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3D) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3E) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3F) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x48) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x49) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x4A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x4B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x4C) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x61) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x62) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x63) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x64) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x65) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x66) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6D) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6E) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6F) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x78) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x79) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7A) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7B) },
+ { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7C) },
+
+
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) },
@@ -722,6 +703,8 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G1) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G1_M) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G2) },
+ /* Novatel Ovation MC551 a.k.a. Verizon USB551L */
+ { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC551, 0xff, 0xff, 0xff) },
{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01) },
{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01A) },
@@ -878,13 +861,19 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0113, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf5_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0117, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0118, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0121, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0118, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0121, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0122, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0123, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0124, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0125, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0126, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0123, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0124, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0125, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf6_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0126, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0128, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0142, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0143, 0xff, 0xff, 0xff) },
@@ -895,8 +884,10 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0153, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0155, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0156, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0157, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0157, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0159, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0161, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0162, 0xff, 0xff, 0xff) },
@@ -904,9 +895,22 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0165, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0167, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0191, 0xff, 0xff, 0xff), /* ZTE EuFi890 */
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0199, 0xff, 0xff, 0xff), /* ZTE MF820S */
+ .driver_info = (kernel_ulong_t)&net_intf1_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0257, 0xff, 0xff, 0xff), /* ZTE MF821 */
+ .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0326, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1021, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1057, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1058, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1059, 0xff, 0xff, 0xff) },
@@ -1022,18 +1026,24 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1169, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1170, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1244, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1245, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1245, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1246, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1247, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1247, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1248, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1249, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1250, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1251, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1252, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1252, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1253, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1254, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1255, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1256, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1254, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1255, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&zte_1255_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1256, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1257, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1258, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1259, 0xff, 0xff, 0xff) },
@@ -1078,6 +1088,16 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1298, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1299, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1300, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1401, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1402, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1424, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1425, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1426, 0xff, 0xff, 0xff), /* ZTE MF91 */
+ .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff,
0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_k3765_z_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) },
@@ -1089,15 +1109,21 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0094, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0133, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf1_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0133, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0147, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0152, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0168, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0168, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0170, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0176, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0178, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0176, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0178, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) },
@@ -1109,6 +1135,10 @@ static const struct usb_device_id option_ids[] = {
.driver_info = (kernel_ulong_t)&zte_ad3812_z_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2716, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&zte_mc2716_z_blacklist },
+ { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x01) },
+ { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x05) },
+ { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x86, 0x10) },
+
{ USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
{ USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) },
{ USB_DEVICE(ALINK_VENDOR_ID, DLINK_PRODUCT_DWM_652_U5) }, /* Yes, ALINK_VENDOR_ID */
@@ -1207,6 +1237,11 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU516) },
{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU528) },
{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU526) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU881) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU882) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU581) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU582) },
+ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU583) },
{ USB_DEVICE_AND_INTERFACE_INFO(VIETTEL_VENDOR_ID, VIETTEL_PRODUCT_VT1000, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZD_VENDOR_ID, ZD_PRODUCT_7000, 0xff, 0xff, 0xff) },
{ USB_DEVICE(LG_VENDOR_ID, LG_PRODUCT_L02C) }, /* docomo L-02C modem */
@@ -1214,6 +1249,18 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a1, 0xff, 0x02, 0x01) },
{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a2, 0xff, 0x00, 0x00) },
{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a2, 0xff, 0x02, 0x01) }, /* MediaTek MT6276M modem & app port */
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_1COM, 0x0a, 0x00, 0x00) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_5COM, 0xff, 0x02, 0x01) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_5COM, 0xff, 0x00, 0x00) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM, 0xff, 0x02, 0x01) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM, 0xff, 0x00, 0x00) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_7208_1COM, 0x02, 0x00, 0x00) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_7208_2COM, 0x02, 0x02, 0x01) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FP_1COM, 0x0a, 0x00, 0x00) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FP_2COM, 0x0a, 0x00, 0x00) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_1COM, 0x0a, 0x00, 0x00) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_2COM, 0x0a, 0x00, 0x00) },
+ { USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, option_ids);
@@ -1257,7 +1304,7 @@ static struct usb_serial_driver option_1port_device = {
.ioctl = usb_wwan_ioctl,
.attach = usb_wwan_startup,
.disconnect = usb_wwan_disconnect,
- .release = usb_wwan_release,
+ .release = option_release,
.read_int_callback = option_instat_callback,
#ifdef CONFIG_PM
.suspend = usb_wwan_suspend,
@@ -1267,35 +1314,6 @@ static struct usb_serial_driver option_1port_device = {
static int debug;
-/* per port private data */
-
-#define N_IN_URB 4
-#define N_OUT_URB 4
-#define IN_BUFLEN 4096
-#define OUT_BUFLEN 4096
-
-struct option_port_private {
- /* Input endpoints and buffer for this port */
- struct urb *in_urbs[N_IN_URB];
- u8 *in_buffer[N_IN_URB];
- /* Output endpoints and buffer for this port */
- struct urb *out_urbs[N_OUT_URB];
- u8 *out_buffer[N_OUT_URB];
- unsigned long out_busy; /* Bit vector of URBs in use */
- int opened;
- struct usb_anchor delayed;
-
- /* Settings for the port */
- int rts_state; /* Handshaking pins (outputs) */
- int dtr_state;
- int cts_state; /* Handshaking pins (inputs) */
- int dsr_state;
- int dcd_state;
- int ri_state;
-
- unsigned long tx_start_time[N_OUT_URB];
-};
-
/* Functions used by new usb-serial code. */
static int __init option_init(void)
{
@@ -1393,12 +1411,22 @@ static int option_probe(struct usb_serial *serial,
return 0;
}
+static void option_release(struct usb_serial *serial)
+{
+ struct usb_wwan_intf_private *priv = usb_get_serial_data(serial);
+
+ usb_wwan_release(serial);
+
+ kfree(priv);
+}
+
static void option_instat_callback(struct urb *urb)
{
int err;
int status = urb->status;
struct usb_serial_port *port = urb->context;
- struct option_port_private *portdata = usb_get_serial_port_data(port);
+ struct usb_wwan_port_private *portdata =
+ usb_get_serial_port_data(port);
dbg("%s", __func__);
dbg("%s: urb %p port %p has data %p", __func__, urb, port, portdata);
@@ -1459,7 +1487,7 @@ static int option_send_setup(struct usb_serial_port *port)
struct usb_serial *serial = port->serial;
struct usb_wwan_intf_private *intfdata =
(struct usb_wwan_intf_private *) serial->private;
- struct option_port_private *portdata;
+ struct usb_wwan_port_private *portdata;
int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
int val = 0;
dbg("%s", __func__);
diff --git a/drivers/usb/serial/qcaux.c b/drivers/usb/serial/qcaux.c
index a348198..87271e3 100644
--- a/drivers/usb/serial/qcaux.c
+++ b/drivers/usb/serial/qcaux.c
@@ -36,8 +36,6 @@
#define UTSTARCOM_PRODUCT_UM175_V1 0x3712
#define UTSTARCOM_PRODUCT_UM175_V2 0x3714
#define UTSTARCOM_PRODUCT_UM175_ALLTEL 0x3715
-#define PANTECH_PRODUCT_UML190_VZW 0x3716
-#define PANTECH_PRODUCT_UML290_VZW 0x3718
/* CMOTECH devices */
#define CMOTECH_VENDOR_ID 0x16d8
@@ -68,11 +66,9 @@ static struct usb_device_id id_table[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(LG_VENDOR_ID, LG_PRODUCT_VX4400_6000, 0xff, 0xff, 0x00) },
{ USB_DEVICE_AND_INTERFACE_INFO(SANYO_VENDOR_ID, SANYO_PRODUCT_KATANA_LX, 0xff, 0xff, 0x00) },
{ USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_U520, 0xff, 0x00, 0x00) },
- { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML190_VZW, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML190_VZW, 0xff, 0xfe, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xfd, 0xff) }, /* NMEA */
- { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xfe, 0xff) }, /* WMC */
- { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xff, 0xff) }, /* DIAG */
+ { USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xfd, 0xff) }, /* NMEA */
+ { USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xfe, 0xff) }, /* WMC */
+ { USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xff, 0xff) }, /* DIAG */
{ },
};
MODULE_DEVICE_TABLE(usb, id_table);
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
index 247c014..7cd2c26 100644
--- a/drivers/usb/serial/qcserial.c
+++ b/drivers/usb/serial/qcserial.c
@@ -104,7 +104,13 @@ static const struct usb_device_id id_table[] = {
{USB_DEVICE(0x1410, 0xa021)}, /* Novatel Gobi 3000 Composite */
{USB_DEVICE(0x413c, 0x8193)}, /* Dell Gobi 3000 QDL */
{USB_DEVICE(0x413c, 0x8194)}, /* Dell Gobi 3000 Composite */
+ {USB_DEVICE(0x1199, 0x9010)}, /* Sierra Wireless Gobi 3000 QDL */
+ {USB_DEVICE(0x1199, 0x9012)}, /* Sierra Wireless Gobi 3000 QDL */
{USB_DEVICE(0x1199, 0x9013)}, /* Sierra Wireless Gobi 3000 Modem device (MC8355) */
+ {USB_DEVICE(0x1199, 0x9014)}, /* Sierra Wireless Gobi 3000 QDL */
+ {USB_DEVICE(0x1199, 0x9015)}, /* Sierra Wireless Gobi 3000 Modem device */
+ {USB_DEVICE(0x1199, 0x9018)}, /* Sierra Wireless Gobi 3000 QDL */
+ {USB_DEVICE(0x1199, 0x9019)}, /* Sierra Wireless Gobi 3000 Modem device */
{USB_DEVICE(0x12D1, 0x14F0)}, /* Sony Gobi 3000 QDL */
{USB_DEVICE(0x12D1, 0x14F1)}, /* Sony Gobi 3000 Composite */
{ } /* Terminating entry */
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index ef71ba3..a159ad0 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -171,7 +171,6 @@ static int sierra_probe(struct usb_serial *serial,
{
int result = 0;
struct usb_device *udev;
- struct sierra_intf_private *data;
u8 ifnum;
udev = serial->dev;
@@ -199,11 +198,6 @@ static int sierra_probe(struct usb_serial *serial,
return -ENODEV;
}
- data = serial->private = kzalloc(sizeof(struct sierra_intf_private), GFP_KERNEL);
- if (!data)
- return -ENOMEM;
- spin_lock_init(&data->susp_lock);
-
return result;
}
@@ -304,6 +298,10 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless Direct IP modems */
.driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
},
+ /* AT&T Direct IP LTE modems */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x0F3D, 0x68AA, 0xFF, 0xFF, 0xFF),
+ .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
+ },
{ USB_DEVICE(0x0f3d, 0x68A3), /* Airprime/Sierra Wireless Direct IP modems */
.driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
},
@@ -911,6 +909,7 @@ static void sierra_dtr_rts(struct usb_serial_port *port, int on)
static int sierra_startup(struct usb_serial *serial)
{
struct usb_serial_port *port;
+ struct sierra_intf_private *intfdata;
struct sierra_port_private *portdata;
struct sierra_iface_info *himemoryp = NULL;
int i;
@@ -918,6 +917,14 @@ static int sierra_startup(struct usb_serial *serial)
dev_dbg(&serial->dev->dev, "%s\n", __func__);
+ intfdata = kzalloc(sizeof(*intfdata), GFP_KERNEL);
+ if (!intfdata)
+ return -ENOMEM;
+
+ spin_lock_init(&intfdata->susp_lock);
+
+ usb_set_serial_data(serial, intfdata);
+
/* Set Device mode to D0 */
sierra_set_power_state(serial->dev, 0x0000);
@@ -933,7 +940,7 @@ static int sierra_startup(struct usb_serial *serial)
dev_dbg(&port->dev, "%s: kmalloc for "
"sierra_port_private (%d) failed!\n",
__func__, i);
- return -ENOMEM;
+ goto err;
}
spin_lock_init(&portdata->lock);
init_usb_anchor(&portdata->active);
@@ -970,6 +977,14 @@ static int sierra_startup(struct usb_serial *serial)
}
return 0;
+err:
+ for (--i; i >= 0; --i) {
+ portdata = usb_get_serial_port_data(serial->port[i]);
+ kfree(portdata);
+ }
+ kfree(intfdata);
+
+ return -ENOMEM;
}
static void sierra_release(struct usb_serial *serial)
@@ -989,6 +1004,7 @@ static void sierra_release(struct usb_serial *serial)
continue;
kfree(portdata);
}
+ kfree(serial->private);
}
#ifdef CONFIG_PM
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index 21c82b0..2856474 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -165,7 +165,7 @@ static unsigned int product_5052_count;
/* the array dimension is the number of default entries plus */
/* TI_EXTRA_VID_PID_COUNT user defined entries plus 1 terminating */
/* null entry */
-static struct usb_device_id ti_id_table_3410[14+TI_EXTRA_VID_PID_COUNT+1] = {
+static struct usb_device_id ti_id_table_3410[15+TI_EXTRA_VID_PID_COUNT+1] = {
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) },
{ USB_DEVICE(MTS_VENDOR_ID, MTS_GSM_NO_FW_PRODUCT_ID) },
@@ -180,6 +180,7 @@ static struct usb_device_id ti_id_table_3410[14+TI_EXTRA_VID_PID_COUNT+1] = {
{ USB_DEVICE(IBM_VENDOR_ID, IBM_454B_PRODUCT_ID) },
{ USB_DEVICE(IBM_VENDOR_ID, IBM_454C_PRODUCT_ID) },
{ USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_PRODUCT_ID) },
+ { USB_DEVICE(TI_VENDOR_ID, FRI2_PRODUCT_ID) },
};
static struct usb_device_id ti_id_table_5052[5+TI_EXTRA_VID_PID_COUNT+1] = {
@@ -189,7 +190,7 @@ static struct usb_device_id ti_id_table_5052[5+TI_EXTRA_VID_PID_COUNT+1] = {
{ USB_DEVICE(TI_VENDOR_ID, TI_5052_FIRMWARE_PRODUCT_ID) },
};
-static struct usb_device_id ti_id_table_combined[18+2*TI_EXTRA_VID_PID_COUNT+1] = {
+static struct usb_device_id ti_id_table_combined[19+2*TI_EXTRA_VID_PID_COUNT+1] = {
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) },
{ USB_DEVICE(MTS_VENDOR_ID, MTS_GSM_NO_FW_PRODUCT_ID) },
@@ -208,6 +209,7 @@ static struct usb_device_id ti_id_table_combined[18+2*TI_EXTRA_VID_PID_COUNT+1]
{ USB_DEVICE(IBM_VENDOR_ID, IBM_454B_PRODUCT_ID) },
{ USB_DEVICE(IBM_VENDOR_ID, IBM_454C_PRODUCT_ID) },
{ USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_PRODUCT_ID) },
+ { USB_DEVICE(TI_VENDOR_ID, FRI2_PRODUCT_ID) },
{ }
};
diff --git a/drivers/usb/serial/ti_usb_3410_5052.h b/drivers/usb/serial/ti_usb_3410_5052.h
index f140f1b..b353e7e 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.h
+++ b/drivers/usb/serial/ti_usb_3410_5052.h
@@ -37,6 +37,7 @@
#define TI_5152_BOOT_PRODUCT_ID 0x5152 /* no EEPROM, no firmware */
#define TI_5052_EEPROM_PRODUCT_ID 0x505A /* EEPROM, no firmware */
#define TI_5052_FIRMWARE_PRODUCT_ID 0x505F /* firmware is running */
+#define FRI2_PRODUCT_ID 0x5053 /* Fish River Island II */
/* Multi-Tech vendor and product ids */
#define MTS_VENDOR_ID 0x06E0
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 5d7b71b..6f81aa5 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -669,12 +669,14 @@ exit:
static struct usb_serial_driver *search_serial_device(
struct usb_interface *iface)
{
- const struct usb_device_id *id;
+ const struct usb_device_id *id = NULL;
struct usb_serial_driver *drv;
+ struct usb_driver *driver = to_usb_driver(iface->dev.driver);
/* Check if the usb id matches a known device */
list_for_each_entry(drv, &usb_serial_driver_list, driver_list) {
- id = get_iface_id(drv, iface);
+ if (drv->usb_driver == driver)
+ id = get_iface_id(drv, iface);
if (id)
return drv;
}
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 5b073bc..59d646d 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -576,6 +576,7 @@ no_firmware:
"%s: please contact support@connecttech.com\n",
serial->type->description);
kfree(result);
+ kfree(command);
return -ENODEV;
no_command_private:
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index 24caba7..fa8a1b2 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -1004,6 +1004,12 @@ UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9999,
USB_SC_8070, USB_PR_CB, NULL,
US_FL_NEED_OVERRIDE | US_FL_FIX_INQUIRY ),
+/* Submitted by Oleksandr Chumachenko <ledest@gmail.com> */
+UNUSUAL_DEV( 0x07cf, 0x1167, 0x0100, 0x0100,
+ "Casio",
+ "EX-N1 DigitalCamera",
+ USB_SC_8070, USB_PR_DEVICE, NULL, 0),
+
/* Submitted by Hartmut Wahl <hwahl@hwahl.de>*/
UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001,
"Samsung",
@@ -1885,6 +1891,13 @@ UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201,
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ),
+/* Reported by Jesse Feddema <jdfeddema@gmail.com> */
+UNUSUAL_DEV( 0x177f, 0x0400, 0x0000, 0x0000,
+ "Yarvik",
+ "PMP400",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ US_FL_BULK_IGNORE_TAG | US_FL_MAX_SECTORS_64 ),
+
/* Reported by Hans de Goede <hdegoede@redhat.com>
* These Appotech controllers are found in Picture Frames, they provide a
* (buggy) emulation of a cdrom drive which contains the windows software
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index e224a92..f274826 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -305,7 +305,8 @@ static void handle_rx(struct vhost_net *net)
.hdr.gso_type = VIRTIO_NET_HDR_GSO_NONE
};
size_t total_len = 0;
- int err, headcount, mergeable;
+ int err, mergeable;
+ s16 headcount;
size_t vhost_hlen, sock_hlen;
size_t vhost_len, sock_len;
/* TODO: check that we are running from vhost_worker? */
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index ea966b3..61047fe 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -217,6 +217,8 @@ static int vhost_worker(void *data)
if (work) {
__set_current_state(TASK_RUNNING);
work->fn(work);
+ if (need_resched())
+ schedule();
} else
schedule();
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 4c85a4b..deb18c3 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -25,6 +25,8 @@ source "drivers/gpu/stub/Kconfig"
source "drivers/gpu/ion/Kconfig"
+source "drivers/gpu/pvr/Kconfig"
+
config VGASTATE
tristate
default n
@@ -261,6 +263,8 @@ config FB_TILEBLITTING
comment "Frame buffer hardware drivers"
depends on FB
+source "drivers/video/samsung/Kconfig"
+
config FB_CIRRUS
tristate "Cirrus Logic support"
depends on FB && (ZORRO || PCI)
@@ -2027,53 +2031,6 @@ config FB_TMIO_ACCELL
depends on FB_TMIO
default y
-config FB_S3C
- tristate "Samsung S3C framebuffer support"
- depends on FB && S3C_DEV_FB
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- ---help---
- Frame buffer driver for the built-in FB controller in the Samsung
- SoC line from the S3C2443 onwards, including the S3C2416, S3C2450,
- and the S3C64XX series such as the S3C6400 and S3C6410.
-
- These chips all have the same basic framebuffer design with the
- actual capabilities depending on the chip. For instance the S3C6400
- and S3C6410 support 4 hardware windows whereas the S3C24XX series
- currently only have two.
-
- Currently the support is only for the S3C6400 and S3C6410 SoCs.
-
-config FB_S3C_DEBUG_REGWRITE
- bool "Debug register writes"
- depends on FB_S3C
- ---help---
- Show all register writes via printk(KERN_DEBUG)
-
-config FB_S3C2410
- tristate "S3C2410 LCD framebuffer support"
- depends on FB && ARCH_S3C2410
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- ---help---
- Frame buffer driver for the built-in LCD controller in the Samsung
- S3C2410 processor.
-
- This driver is also available as a module ( = code which can be
- inserted and removed from the running kernel whenever you want). The
- module will be called s3c2410fb. If you want to compile it as a module,
- say M here and read <file:Documentation/kbuild/modules.txt>.
-
- If unsure, say N.
-config FB_S3C2410_DEBUG
- bool "S3C2410 lcd debug messages"
- depends on FB_S3C2410
- help
- Turn on debugging messages. Note that you can set/unset at run time
- through sysfs
-
config FB_NUC900
bool "NUC900 LCD framebuffer support"
depends on FB && ARCH_W90X900
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 8b83129..98f64e7 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -117,7 +117,7 @@ obj-$(CONFIG_FB_BROADSHEET) += broadsheetfb.o
obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o
obj-$(CONFIG_FB_SH7760) += sh7760fb.o
obj-$(CONFIG_FB_IMX) += imxfb.o
-obj-$(CONFIG_FB_S3C) += s3c-fb.o
+obj-$(CONFIG_FB_S3C) += samsung/
obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o
obj-$(CONFIG_FB_FSL_DIU) += fsl-diu-fb.o
obj-$(CONFIG_FB_COBALT) += cobalt_lcdfb.o
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 8745637..bf9a9b7 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -373,8 +373,15 @@ static void fb_flashcursor(struct work_struct *work)
struct vc_data *vc = NULL;
int c;
int mode;
+ int ret;
+
+ /* FIXME: we should sort out the unbind locking instead */
+ /* instead we just fail to flash the cursor if we can't get
+ * the lock instead of blocking fbcon deinit */
+ ret = console_trylock();
+ if (ret == 0)
+ return;
- console_lock();
if (ops && ops->currcon != -1)
vc = vc_cons[ops->currcon].d;
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 7a41220..7464a0a 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -35,6 +35,9 @@
#include <asm/fb.h>
+#ifdef CONFIG_FB_S3C
+#include <samsung/s3cfb.h>
+#endif
/*
* Frame buffer device initialization and setup routines
@@ -1169,6 +1172,10 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
unlock_fb_info(info);
break;
default:
+// Skip mutex for vsync poll because it's in its own thread
+#ifdef CONFIG_FB_S3C
+ if (cmd != S3CFB_WAIT_FOR_VSYNC)
+#endif
if (!lock_fb_info(info))
return -ENODEV;
fb = info->fbops;
@@ -1176,6 +1183,9 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
ret = fb->fb_ioctl(info, cmd, arg);
else
ret = -ENOTTY;
+#ifdef CONFIG_FB_S3C
+ if (cmd != S3CFB_WAIT_FOR_VSYNC)
+#endif
unlock_fb_info(info);
}
return ret;
diff --git a/drivers/video/samsung/Kconfig b/drivers/video/samsung/Kconfig
new file mode 100755
index 0000000..5a1122b
--- /dev/null
+++ b/drivers/video/samsung/Kconfig
@@ -0,0 +1,174 @@
+#
+# S3C Video configuration
+#
+
+config FB_S3C
+ tristate "S3C Framebuffer support"
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FRAMEBUFFER_CONSOLE_DETECT_PRIMARY if VT
+ depends on FB && ARCH_S5PV210
+ default n
+ ---help---
+ This enables support for Samsung Display Controller (FIMD)
+
+config FB_S3C_SPLASH_SCREEN
+ bool "SPLASH_SCREEN on LCD"
+ depends on FB_S3C
+ default n
+
+config FB_S3C_LCD_INIT
+ bool "LCD init in kernel"
+ depends on FB_S3C
+ default y
+
+config FB_S3C_DEBUG
+ bool "S3C Framebuffer debug messages"
+ depends on FB_S3C
+
+config FB_S3C_TRACE_UNDERRUN
+ bool "S3C Framebuffer FIFO underrun trace"
+ depends on FB_S3C
+
+config FB_S3C_DEFAULT_WINDOW
+ int "Default Window (0-4)"
+ range 0 4
+ depends on FB_S3C
+ default "2"
+ ---help---
+ This indicates the default window number, and which is used as console framebuffer
+
+config FB_S3C_NR_BUFFERS
+ int "Number of frame buffers (1-3)"
+ depends on FB_S3C
+ default "2"
+ ---help---
+ This indicates the number of buffers for pan display,
+ 1 means no pan display and
+ 2 means the double size of video buffer will be allocated for default window
+
+config FB_S3C_NUM_OVLY_WIN
+ int "Number of overlay window (0-3)"
+ range 0 3
+ depends on FB_S3C
+ default "1"
+ ---help---
+ This indicates the number of overlay windows for video rendering
+
+config FB_S3C_NUM_BUF_OVLY_WIN
+ int "Number of buffers for overlay window (2-3)"
+ range 2 3
+ depends on FB_S3C
+ default "3"
+ ---help---
+ This indicates the number of buffers for overlay windows
+
+config FB_S3C_VIRTUAL
+ bool "Virtual Screen"
+ depends on FB_S3C
+ default n
+ ---help---
+ This uses 1920 x 1080 virtual screen.
+
+config FB_S3C_X_VRES
+ int "xres_virtual"
+ depends on FB_S3C && FB_S3C_VIRTUAL
+ default "1920"
+ help
+ This indicates var.xres_virtual which has to be bigger than var.xres.
+
+config FB_S3C_Y_VRES
+ int "yres_virtual"
+ depends on FB_S3C && FB_S3C_VIRTUAL
+ default "1080"
+ help
+ This indicates var.yres_virtual which has to be bigger than var.yres.
+
+choice
+depends on FB_S3C
+prompt "Select LCD Type"
+default FB_S3C_LTE480WV
+config FB_S3C_LTE480WV
+ bool "LTE480WV"
+ depends on (MACH_SMDKV210 || MACH_SMDKC110)
+ ---help---
+ This enables support for Samsung LTE480WV 4.8\" WVGA LCD panel
+
+config FB_S3C_HT101HD1
+ bool "HT101HD1"
+ depends on MACH_SMDKV210
+ ---help---
+ This enables support for HT101HD1 WXVGA(1366*768) LCD panel
+endchoice
+
+config FB_S3C_TL2796
+ bool "TL2796"
+ depends on FB_S3C
+ select SPI
+ select SPI_GPIO
+ select SPI_BITBANG
+ ---help---
+ This enables support for Samsung TL2796 WVGA LCD panel
+
+config FB_VOODOO
+ bool "Voodoo Color"
+ depends on FB_S3C_TL2796
+ default y
+ ---help---
+ This enables support Voodoo color mods
+
+config FB_VOODOO_DEBUG_LOG
+ bool "Verbose Super AMOLED driver logs"
+ depends on FB_VOODOO
+ default n
+ ---help---
+ Logging for developers
+ Super AMOLED hardware command decoding and driver calculations
+
+config FB_S3C_NT35580
+ bool "NT35580"
+ depends on FB_S3C
+ select SPI
+ select SPI_GPIO
+ select SPI_BITBANG
+ ---help---
+ This enables support for SONY NT35580 WVGA LCD panel
+
+config FB_S3C_LVDS
+ bool "LVDS"
+ depends on FB_S3C && (ARCH_S5PV210)
+ default y
+ ---help---
+ This enables support for Samsung LVDS LCD panel
+
+config FB_S3C_AMS701KA
+ bool "AMS701KA"
+ depends on FB_S3C && (ARCH_S5PV210)
+ select SPI
+ select SPI_GPIO
+ default n
+ ---help---
+ This enables support for Samsung AMS701KA LCD panel
+
+config FB_S3C_MDNIE
+ bool "Samsung MDNIE"
+ depends on FB_S3C
+ depends on FB_S3C && (ARCH_S5PV210)
+ default "0"
+ ---help---
+ This enables support for Samsung MDNIE feature
+
+config TL2796_CONVERT_COLORS_RES
+ bool "TL2796 6500K Colors"
+ depends on FB_S3C_TL2796
+ default y
+ ---help---
+ This scales from 8500K colors to 6500K colors
+
+config FB_S3C_CMC623
+ bool "Samsung CMC623"
+ depends on FB_S3C && (ARCH_S5PV210)
+ default "0"
+ ---help---
+ This enables support for Samsung CMC623 feature
diff --git a/drivers/video/samsung/Makefile b/drivers/video/samsung/Makefile
new file mode 100644
index 0000000..d4f5271
--- /dev/null
+++ b/drivers/video/samsung/Makefile
@@ -0,0 +1,22 @@
+#
+# Makefile for the s3c framebuffer driver
+#
+
+ifeq ($(CONFIG_FB_S3C),y)
+obj-y += s3cfb.o
+obj-$(CONFIG_ARCH_S5PV210) += s3cfb_fimd6x.o
+
+obj-$(CONFIG_FB_S3C_LTE480WV) += s3cfb_lte480wv.o
+obj-$(CONFIG_FB_S3C_LVDS) += s3cfb_lvds.o
+obj-$(CONFIG_FB_S3C_HT101HD1) += s3cfb_ht101hd1.o
+obj-$(CONFIG_FB_S3C_TL2796) += s3cfb_tl2796.o
+obj-$(CONFIG_FB_S3C_NT35580) += s3cfb_nt35580.o
+obj-$(CONFIG_FB_S3C_AMS701KA) += s3cfb_ams701ka.o
+obj-$(CONFIG_FB_S3C_MDNIE) += s3cfb_mdnie.o s3cfb_ielcd.o
+obj-$(CONFIG_FB_S3C_CMC623) += tune_cmc623.o
+endif
+
+ifeq ($(CONFIG_FB_S3C_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
+
diff --git a/drivers/video/samsung/s3cfb.c b/drivers/video/samsung/s3cfb.c
new file mode 100755
index 0000000..6db4899
--- /dev/null
+++ b/drivers/video/samsung/s3cfb.c
@@ -0,0 +1,1269 @@
+/* linux/drivers/video/samsung/s3cfb.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Core file for Samsung Display Controller (FIMD) driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/poll.h>
+#include <linux/wait.h>
+#include <linux/fs.h>
+#include <linux/irq.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/ctype.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/io.h>
+#include <linux/memory.h>
+#include <linux/cpufreq.h>
+#include <linux/kthread.h>
+#include <plat/clock.h>
+#include <plat/cpu-freq.h>
+#include <plat/media.h>
+#ifdef CONFIG_HAS_WAKELOCK
+#include <linux/wakelock.h>
+#include <linux/earlysuspend.h>
+#include <linux/suspend.h>
+#endif
+#include "s3cfb.h"
+
+#if (CONFIG_FB_S3C_NUM_OVLY_WIN >= CONFIG_FB_S3C_DEFAULT_WINDOW)
+#error "FB_S3C_NUM_OVLY_WIN should be less than FB_S3C_DEFAULT_WINDOW"
+#endif
+
+struct s3c_platform_fb *to_fb_plat(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+
+ return (struct s3c_platform_fb *)pdev->dev.platform_data;
+}
+
+static unsigned int bootloaderfb;
+module_param_named(bootloaderfb, bootloaderfb, uint, 0444);
+MODULE_PARM_DESC(bootloaderfb, "Address of booting logo image in Bootloader");
+
+#ifndef CONFIG_FRAMEBUFFER_CONSOLE
+static int s3cfb_draw_logo(struct fb_info *fb)
+{
+#ifdef CONFIG_FB_S3C_SPLASH_SCREEN
+ struct fb_fix_screeninfo *fix = &fb->fix;
+ struct fb_var_screeninfo *var = &fb->var;
+
+ u32 height = var->yres / 3;
+ u32 line = fix->line_length;
+ u32 i, j;
+
+ for (i = 0; i < height; i++) {
+ int offset = i * line;
+ for (j = 0; j < var->xres; j++) {
+ fb->screen_base[offset++] = 0;
+ fb->screen_base[offset++] = 0;
+ fb->screen_base[offset++] = 0xff;
+ fb->screen_base[offset++] = 0;
+ }
+ }
+
+ for (i = height; i < height * 2; i++) {
+ int offset = i * line;
+ for (j = 0; j < var->xres; j++) {
+ fb->screen_base[offset++] = 0;
+ fb->screen_base[offset++] = 0xff;
+ fb->screen_base[offset++] = 0;
+ fb->screen_base[offset++] = 0;
+ }
+ }
+
+ for (i = height * 2; i < height * 3; i++) {
+ int offset = i * line;
+ for (j = 0; j < var->xres; j++) {
+ fb->screen_base[offset++] = 0xff;
+ fb->screen_base[offset++] = 0;
+ fb->screen_base[offset++] = 0;
+ fb->screen_base[offset++] = 0;
+ }
+ }
+#endif
+ if (bootloaderfb) {
+ u8 *logo_virt_buf;
+ logo_virt_buf = ioremap_nocache(bootloaderfb,
+ fb->var.yres * fb->fix.line_length);
+
+ memcpy(fb->screen_base, logo_virt_buf,
+ fb->var.yres * fb->fix.line_length);
+ iounmap(logo_virt_buf);
+ }
+ return 0;
+}
+#endif
+static irqreturn_t s3cfb_irq_frame(int irq, void *data)
+{
+ struct s3cfb_global *fbdev = (struct s3cfb_global *)data;
+
+ s3cfb_clear_interrupt(fbdev);
+
+ fbdev->vsync_timestamp = ktime_get();
+ wmb();
+ wake_up_interruptible(&fbdev->vsync_wait);
+
+ return IRQ_HANDLED;
+}
+static int s3cfb_vsync_timestamp_changed(struct s3cfb_global *fbdev,
+ ktime_t prev_timestamp)
+{
+ rmb();
+ return !ktime_equal(prev_timestamp, fbdev->vsync_timestamp);
+}
+static void s3cfb_set_window(struct s3cfb_global *ctrl, int id, int enable)
+{
+ struct s3cfb_window *win = ctrl->fb[id]->par;
+
+ if (enable) {
+ s3cfb_window_on(ctrl, id);
+ win->enabled = 1;
+ } else {
+ s3cfb_window_off(ctrl, id);
+ win->enabled = 0;
+ }
+}
+static int s3cfb_init_global(struct s3cfb_global *ctrl)
+{
+ ctrl->output = OUTPUT_RGB;
+ ctrl->rgb_mode = MODE_RGB_P;
+
+ init_waitqueue_head(&ctrl->vsync_wait);
+ mutex_init(&ctrl->lock);
+
+ s3cfb_set_output(ctrl);
+ s3cfb_set_display_mode(ctrl);
+ s3cfb_set_polarity(ctrl);
+ s3cfb_set_timing(ctrl);
+ s3cfb_set_lcd_size(ctrl);
+
+ return 0;
+}
+static int s3cfb_map_video_memory(struct fb_info *fb)
+{
+ struct fb_fix_screeninfo *fix = &fb->fix;
+ struct s3cfb_window *win = fb->par;
+ struct s3cfb_global *fbdev =
+ platform_get_drvdata(to_platform_device(fb->device));
+ struct s3c_platform_fb *pdata = to_fb_plat(fbdev->dev);
+
+ if (win->owner == DMA_MEM_OTHER) {
+ fix->smem_start = win->other_mem_addr;
+ fix->smem_len = win->other_mem_size;
+ return 0;
+ }
+
+ if (fb->screen_base)
+ return 0;
+
+ if (pdata && pdata->pmem_start[win->id] &&
+ (pdata->pmem_size[win->id] >= fix->smem_len)) {
+ fix->smem_start = pdata->pmem_start[win->id];
+ fb->screen_base = ioremap_wc(fix->smem_start, pdata->pmem_size[win->id]);
+ } else
+ fb->screen_base = dma_alloc_writecombine(fbdev->dev,
+ PAGE_ALIGN(fix->smem_len),
+ (unsigned int *)
+ &fix->smem_start, GFP_KERNEL);
+
+ if (!fb->screen_base)
+ return -ENOMEM;
+
+ dev_info(fbdev->dev, "[fb%d] dma: 0x%08x, cpu: 0x%08x, "
+ "size: 0x%08x\n", win->id,
+ (unsigned int)fix->smem_start,
+ (unsigned int)fb->screen_base, fix->smem_len);
+
+ memset(fb->screen_base, 0, fix->smem_len);
+ win->owner = DMA_MEM_FIMD;
+
+ return 0;
+}
+
+static int s3cfb_map_default_video_memory(struct fb_info *fb)
+{
+#if defined(CONFIG_FB_S3C_VIRTUAL)
+ struct fb_fix_screeninfo *fix = &fb->fix;
+ struct s3cfb_window *win = fb->par;
+ struct s3c_platform_fb *pdata = to_fb_plat(fbdev->dev);
+
+ if (win->owner == DMA_MEM_OTHER)
+ return 0;
+
+ fix->smem_start = pdata->pmem_start[win->id];
+ fb->screen_base = ioremap_wc(fix->smem_start, pdata->pmem_size[win->id]);
+
+ if (!fb->screen_base)
+ return -ENOMEM;
+ else
+ dev_info(fbdev->dev, "[fb%d] dma: 0x%08x, cpu: 0x%08x, "
+ "size: 0x%08x\n", win->id,
+ (unsigned int)fix->smem_start,
+ (unsigned int)fb->screen_base, fix->smem_len);
+
+ memset(fb->screen_base, 0, fix->smem_len);
+ win->owner = DMA_MEM_FIMD;
+#else
+ s3cfb_map_video_memory(fb);
+#endif
+ return 0;
+}
+
+static int s3cfb_unmap_video_memory(struct fb_info *fb)
+{
+ struct s3cfb_global *fbdev =
+ platform_get_drvdata(to_platform_device(fb->device));
+ struct s3c_platform_fb *pdata = to_fb_plat(fbdev->dev);
+ struct fb_fix_screeninfo *fix = &fb->fix;
+ struct s3cfb_window *win = fb->par;
+
+ if (fix->smem_start) {
+ if (win->owner == DMA_MEM_FIMD) {
+ if (pdata && pdata->pmem_start[win->id] &&
+ (pdata->pmem_size[win->id] >= fix->smem_len))
+ iounmap(fb->screen_base);
+ else
+ dma_free_writecombine(fbdev->dev, fix->smem_len,
+ fb->screen_base, fix->smem_start);
+ }
+ fix->smem_start = 0;
+ fix->smem_len = 0;
+ fb->screen_base = 0;
+ dev_info(fbdev->dev,
+ "[fb%d] video memory released\n", win->id);
+ }
+
+ return 0;
+}
+static int s3cfb_unmap_default_video_memory(struct fb_info *fb)
+{
+ struct s3cfb_global *fbdev =
+ platform_get_drvdata(to_platform_device(fb->device));
+ struct fb_fix_screeninfo *fix = &fb->fix;
+ struct s3cfb_window *win = fb->par;
+
+ if (fix->smem_start) {
+#if defined(CONFIG_FB_S3C_VIRTUAL)
+ iounmap(fb->screen_base);
+#else
+ dma_free_writecombine(fbdev->dev, fix->smem_len,
+ fb->screen_base, fix->smem_start);
+#endif
+ fix->smem_start = 0;
+ fix->smem_len = 0;
+ fb->screen_base = 0;
+ dev_info(fbdev->dev,
+ "[fb%d] video memory released\n", win->id);
+ }
+
+ return 0;
+}
+
+static void s3cfb_set_bitfield(struct fb_var_screeninfo *var)
+{
+ switch (var->bits_per_pixel) {
+ case 16:
+ if (var->transp.length == 1) {
+ var->red.offset = 10;
+ var->red.length = 5;
+ var->green.offset = 5;
+ var->green.length = 5;
+ var->blue.offset = 0;
+ var->blue.length = 5;
+ var->transp.offset = 15;
+ } else if (var->transp.length == 4) {
+ var->red.offset = 8;
+ var->red.length = 4;
+ var->green.offset = 4;
+ var->green.length = 4;
+ var->blue.offset = 0;
+ var->blue.length = 4;
+ var->transp.offset = 12;
+ } else {
+ 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;
+ }
+ break;
+
+ case 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;
+ break;
+
+ case 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;
+
+ break;
+ }
+}
+
+static void s3cfb_set_alpha_info(struct fb_var_screeninfo *var,
+ struct s3cfb_window *win)
+{
+ if (var->transp.length > 0)
+ win->alpha.mode = PIXEL_BLENDING;
+ else {
+ win->alpha.mode = PLANE_BLENDING;
+ win->alpha.channel = 0;
+ win->alpha.value = S3CFB_AVALUE(0xf, 0xf, 0xf);
+ }
+}
+static int s3cfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fb)
+{
+ struct s3cfb_window *win = fb->par;
+ struct s3cfb_global *fbdev =
+ platform_get_drvdata(to_platform_device(fb->device));
+ struct s3cfb_lcd *lcd = fbdev->lcd;
+
+ dev_dbg(fbdev->dev, "[fb%d] check_var\n", win->id);
+
+ if (var->bits_per_pixel != 16 && var->bits_per_pixel != 24 &&
+ var->bits_per_pixel != 32) {
+ dev_err(fbdev->dev, "invalid bits per pixel\n");
+ return -EINVAL;
+ }
+
+ if (var->xres > lcd->width)
+ var->xres = lcd->width;
+
+ if (var->yres > lcd->height)
+ var->yres = lcd->height;
+
+ if (var->xres_virtual < var->xres)
+ var->xres_virtual = var->xres;
+
+ var->xoffset = 0;
+
+ if (var->yoffset + var->yres > var->yres_virtual)
+ var->yoffset = var->yres_virtual - var->yres;
+
+ if (win->x + var->xres > lcd->width)
+ win->x = lcd->width - var->xres;
+
+ if (win->y + var->yres > lcd->height)
+ win->y = lcd->height - var->yres;
+
+ s3cfb_set_bitfield(var);
+ s3cfb_set_alpha_info(var, win);
+
+ return 0;
+}
+
+static void s3cfb_set_win_params(struct s3cfb_global *ctrl, int id)
+{
+ s3cfb_set_window_control(ctrl, id);
+ s3cfb_set_window_position(ctrl, id);
+ s3cfb_set_window_size(ctrl, id);
+ s3cfb_set_buffer_address(ctrl, id);
+ s3cfb_set_buffer_size(ctrl, id);
+
+ if (id > 0) {
+ s3cfb_set_alpha_blending(ctrl, id);
+ s3cfb_set_chroma_key(ctrl, id);
+ }
+}
+static int s3cfb_set_par(struct fb_info *fb)
+{
+ struct s3cfb_global *fbdev =
+ platform_get_drvdata(to_platform_device(fb->device));
+ struct s3c_platform_fb *pdata = to_fb_plat(fbdev->dev);
+ struct s3cfb_window *win = fb->par;
+
+ dev_dbg(fbdev->dev, "[fb%d] set_par\n", win->id);
+
+ /* modify the fix info */
+ if (win->id != pdata->default_win) {
+ fb->fix.line_length = fb->var.xres_virtual *
+ fb->var.bits_per_pixel / 8;
+ fb->fix.smem_len = fb->fix.line_length * fb->var.yres_virtual;
+
+ s3cfb_map_video_memory(fb);
+ }
+
+ s3cfb_set_win_params(fbdev, win->id);
+
+ return 0;
+}
+
+static int s3cfb_blank(int blank_mode, struct fb_info *fb)
+{
+ struct s3cfb_window *win = fb->par;
+ struct s3cfb_global *fbdev =
+ platform_get_drvdata(to_platform_device(fb->device));
+
+ dev_dbg(fbdev->dev, "change blank mode\n");
+
+ switch (blank_mode) {
+ case FB_BLANK_UNBLANK:
+ if (fb->fix.smem_start) {
+ s3cfb_win_map_off(fbdev, win->id);
+ s3cfb_set_window(fbdev, win->id, 1);
+ } else
+ dev_info(fbdev->dev,
+ "[fb%d] no allocated memory for unblank\n",
+ win->id);
+ break;
+
+ case FB_BLANK_NORMAL:
+ s3cfb_win_map_on(fbdev, win->id, 0);
+ s3cfb_set_window(fbdev, win->id, 1);
+
+ break;
+
+ case FB_BLANK_POWERDOWN:
+ s3cfb_set_window(fbdev, win->id, 0);
+ s3cfb_win_map_off(fbdev, win->id);
+
+ break;
+
+ case FB_BLANK_VSYNC_SUSPEND:
+ case FB_BLANK_HSYNC_SUSPEND:
+ default:
+ dev_dbg(fbdev->dev, "unsupported blank mode\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int s3cfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fb)
+{
+ struct fb_fix_screeninfo *fix = &fb->fix;
+ struct s3cfb_window *win = fb->par;
+ struct s3cfb_global *fbdev =
+ platform_get_drvdata(to_platform_device(fb->device));
+
+ if (var->yoffset + var->yres > var->yres_virtual) {
+ dev_err(fbdev->dev, "invalid yoffset value\n");
+ return -EINVAL;
+ }
+
+ if (win->owner == DMA_MEM_OTHER)
+ fix->smem_start = win->other_mem_addr;
+
+ fb->var.yoffset = var->yoffset;
+
+ dev_dbg(fbdev->dev,
+ "[fb%d] yoffset for pan display: %d\n",
+ win->id, var->yoffset);
+
+ s3cfb_set_buffer_address(fbdev, win->id);
+
+ return 0;
+}
+
+static unsigned int __chan_to_field(unsigned int chan,
+ struct fb_bitfield bf)
+{
+ chan &= 0xffff;
+ chan >>= 16 - bf.length;
+
+ return chan << bf.offset;
+}
+
+static int s3cfb_setcolreg(unsigned int regno, unsigned int red,
+ unsigned int green, unsigned int blue,
+ unsigned int transp, struct fb_info *fb)
+{
+ unsigned int *pal = (unsigned int *)fb->pseudo_palette;
+ unsigned int val = 0;
+
+ if (regno < 16) {
+ val |= __chan_to_field(red, fb->var.red);
+ val |= __chan_to_field(green, fb->var.green);
+ val |= __chan_to_field(blue, fb->var.blue);
+ val |= __chan_to_field(transp, fb->var.transp);
+
+ pal[regno] = val;
+ }
+
+ return 0;
+}
+
+static int s3cfb_open(struct fb_info *fb, int user)
+{
+ struct s3cfb_global *fbdev =
+ platform_get_drvdata(to_platform_device(fb->device));
+ struct s3c_platform_fb *pdata = to_fb_plat(fbdev->dev);
+ struct s3cfb_window *win = fb->par;
+ int ret = 0;
+
+ mutex_lock(&fbdev->lock);
+
+ if (win->in_use && win->id != pdata->default_win)
+ ret = -EBUSY;
+ else
+ win->in_use++;
+
+ mutex_unlock(&fbdev->lock);
+
+ return ret;
+}
+static int s3cfb_release_window(struct fb_info *fb)
+{
+ struct s3cfb_global *fbdev =
+ platform_get_drvdata(to_platform_device(fb->device));
+ struct s3c_platform_fb *pdata = to_fb_plat(fbdev->dev);
+ struct s3cfb_window *win = fb->par;
+
+ if (win->id != pdata->default_win) {
+ s3cfb_set_window(fbdev, win->id, 0);
+ s3cfb_unmap_video_memory(fb);
+ s3cfb_set_buffer_address(fbdev, win->id);
+ }
+
+ win->x = 0;
+ win->y = 0;
+
+ return 0;
+}
+static int s3cfb_release(struct fb_info *fb, int user)
+{
+ struct s3cfb_global *fbdev =
+ platform_get_drvdata(to_platform_device(fb->device));
+ struct s3cfb_window *win = fb->par;
+
+ s3cfb_release_window(fb);
+
+ mutex_lock(&fbdev->lock);
+
+ if (!WARN_ON(!win->in_use))
+ win->in_use--;
+
+ mutex_unlock(&fbdev->lock);
+
+ return 0;
+}
+
+static int s3cfb_wait_for_vsync(struct s3cfb_global *ctrl)
+{
+ ktime_t prev_timestamp;
+ int ret;
+
+ prev_timestamp = ctrl->vsync_timestamp;
+ ret = wait_event_interruptible_timeout(ctrl->vsync_wait,
+ s3cfb_vsync_timestamp_changed(ctrl, prev_timestamp),
+ msecs_to_jiffies(100));
+ if (ret == 0)
+ return -ETIMEDOUT;
+ if (ret < 0)
+ return ret;
+
+ return ret;
+}
+static int s3cfb_ioctl(struct fb_info *fb, unsigned int cmd, unsigned long arg)
+{
+ struct s3cfb_global *fbdev =
+ platform_get_drvdata(to_platform_device(fb->device));
+ struct fb_var_screeninfo *var = &fb->var;
+ struct s3cfb_window *win = fb->par;
+ struct s3cfb_lcd *lcd = fbdev->lcd;
+ struct fb_fix_screeninfo *fix = &fb->fix;
+ struct s3cfb_next_info next_fb_info;
+
+ int ret = 0;
+
+ union {
+ struct s3cfb_user_window user_window;
+ struct s3cfb_user_plane_alpha user_alpha;
+ struct s3cfb_user_chroma user_chroma;
+ int vsync;
+ } p;
+
+ switch (cmd) {
+ case FBIO_WAITFORVSYNC:
+ s3cfb_wait_for_vsync(fbdev);
+ break;
+
+ // Custom IOCTL added to return the VSYNC timestamp
+ case S3CFB_WAIT_FOR_VSYNC:
+ ret = s3cfb_wait_for_vsync(fbdev);
+ if(ret > 0) {
+ u64 nsecs = ktime_to_ns(fbdev->vsync_timestamp);
+ copy_to_user((void*)arg, &nsecs, sizeof(u64));
+ }
+ break;
+
+ case S3CFB_WIN_POSITION:
+ if (copy_from_user(&p.user_window,
+ (struct s3cfb_user_window __user *)arg,
+ sizeof(p.user_window)))
+ ret = -EFAULT;
+ else {
+ if (p.user_window.x < 0)
+ p.user_window.x = 0;
+
+ if (p.user_window.y < 0)
+ p.user_window.y = 0;
+
+ if (p.user_window.x + var->xres > lcd->width)
+ win->x = lcd->width - var->xres;
+ else
+ win->x = p.user_window.x;
+
+ if (p.user_window.y + var->yres > lcd->height)
+ win->y = lcd->height - var->yres;
+ else
+ win->y = p.user_window.y;
+
+ s3cfb_set_window_position(fbdev, win->id);
+ }
+ break;
+
+ case S3CFB_WIN_SET_PLANE_ALPHA:
+ if (copy_from_user(&p.user_alpha,
+ (struct s3cfb_user_plane_alpha __user *)arg,
+ sizeof(p.user_alpha)))
+ ret = -EFAULT;
+ else {
+ win->alpha.mode = PLANE_BLENDING;
+ win->alpha.channel = p.user_alpha.channel;
+ win->alpha.value =
+ S3CFB_AVALUE(p.user_alpha.red,
+ p.user_alpha.green, p.user_alpha.blue);
+
+ s3cfb_set_alpha_blending(fbdev, win->id);
+ }
+ break;
+
+ case S3CFB_WIN_SET_CHROMA:
+ if (copy_from_user(&p.user_chroma,
+ (struct s3cfb_user_chroma __user *)arg,
+ sizeof(p.user_chroma)))
+ ret = -EFAULT;
+ else {
+ win->chroma.enabled = p.user_chroma.enabled;
+ win->chroma.key = S3CFB_CHROMA(p.user_chroma.red,
+ p.user_chroma.green,
+ p.user_chroma.blue);
+
+ s3cfb_set_chroma_key(fbdev, win->id);
+ }
+ break;
+
+ case S3CFB_SET_VSYNC_INT:
+ if (get_user(p.vsync, (int __user *)arg))
+ ret = -EFAULT;
+ else {
+ if (p.vsync)
+ s3cfb_set_global_interrupt(fbdev, 1);
+
+ s3cfb_set_vsync_interrupt(fbdev, p.vsync);
+ }
+ break;
+
+ case S3CFB_GET_CURR_FB_INFO:
+ next_fb_info.phy_start_addr = fix->smem_start;
+ next_fb_info.xres = var->xres;
+ next_fb_info.yres = var->yres;
+ next_fb_info.xres_virtual = var->xres_virtual;
+ next_fb_info.yres_virtual = var->yres_virtual;
+ next_fb_info.xoffset = var->xoffset;
+ next_fb_info.yoffset = var->yoffset;
+ next_fb_info.lcd_offset_x = 0;
+ next_fb_info.lcd_offset_y = 0;
+
+ if (copy_to_user((void *)arg,
+ (struct s3cfb_next_info *) &next_fb_info,
+ sizeof(struct s3cfb_next_info)))
+ return -EFAULT;
+ break;
+ }
+
+ return ret;
+}
+
+struct fb_ops s3cfb_ops = {
+ .owner = THIS_MODULE,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+ .fb_check_var = s3cfb_check_var,
+ .fb_set_par = s3cfb_set_par,
+ .fb_blank = s3cfb_blank,
+ .fb_pan_display = s3cfb_pan_display,
+ .fb_setcolreg = s3cfb_setcolreg,
+ .fb_ioctl = s3cfb_ioctl,
+ .fb_open = s3cfb_open,
+ .fb_release = s3cfb_release,
+};
+
+static void s3cfb_init_fbinfo(struct s3cfb_global *ctrl, int id)
+{
+ struct fb_info *fb = ctrl->fb[id];
+ struct fb_fix_screeninfo *fix = &fb->fix;
+ struct fb_var_screeninfo *var = &fb->var;
+ struct s3cfb_window *win = fb->par;
+ struct s3cfb_alpha *alpha = &win->alpha;
+ struct s3cfb_lcd *lcd = ctrl->lcd;
+ struct s3cfb_lcd_timing *timing = &lcd->timing;
+
+ memset(win, 0, sizeof(*win));
+ platform_set_drvdata(to_platform_device(ctrl->dev), ctrl);
+ strcpy(fix->id, S3CFB_NAME);
+
+ win->id = id;
+ win->path = DATA_PATH_DMA;
+ win->dma_burst = 16;
+ alpha->mode = PLANE_BLENDING;
+
+ fb->fbops = &s3cfb_ops;
+ fb->flags = FBINFO_FLAG_DEFAULT;
+ fb->pseudo_palette = &win->pseudo_pal;
+#if (CONFIG_FB_S3C_NR_BUFFERS != 1)
+ fix->xpanstep = 2;
+ fix->ypanstep = 1;
+#else
+ fix->xpanstep = 0;
+ fix->ypanstep = 0;
+#endif
+ fix->type = FB_TYPE_PACKED_PIXELS;
+ fix->accel = FB_ACCEL_NONE;
+ fix->visual = FB_VISUAL_TRUECOLOR;
+ var->xres = lcd->width;
+ var->yres = lcd->height;
+#if defined(CONFIG_FB_S3C_VIRTUAL)
+ var->xres_virtual = CONFIG_FB_S3C_X_VRES;
+ var->yres_virtual = CONFIG_FB_S3C_Y_VRES * CONFIG_FB_S3C_NR_BUFFERS;
+#else
+ var->xres_virtual = var->xres;
+ var->yres_virtual = var->yres * CONFIG_FB_S3C_NR_BUFFERS;
+#endif
+ var->bits_per_pixel = 32;
+ var->xoffset = 0;
+ var->yoffset = 0;
+ var->width = lcd->p_width;
+ var->height = lcd->p_height;
+ var->transp.length = 0;
+
+ fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
+ fix->smem_len = fix->line_length * var->yres_virtual;
+
+ var->nonstd = 0;
+ var->activate = FB_ACTIVATE_NOW;
+ var->vmode = FB_VMODE_NONINTERLACED;
+ var->hsync_len = timing->h_sw;
+ var->vsync_len = timing->v_sw;
+ var->left_margin = timing->h_fp;
+ var->right_margin = timing->h_bp;
+ var->upper_margin = timing->v_fp;
+ var->lower_margin = timing->v_bp;
+
+ ctrl->pixclock_hz = lcd->freq * (var->left_margin + var->right_margin +
+ var->hsync_len + var->xres) *
+ (var->upper_margin + var->lower_margin +
+ var->vsync_len + var->yres);
+ var->pixclock = KHZ2PICOS(ctrl->pixclock_hz / 1000);
+
+ dev_dbg(ctrl->dev, "pixclock: %d\n", var->pixclock);
+
+ s3cfb_set_bitfield(var);
+ s3cfb_set_alpha_info(var, win);
+
+}
+
+static int s3cfb_alloc_framebuffer(struct s3cfb_global *ctrl)
+{
+ struct s3c_platform_fb *pdata = to_fb_plat(ctrl->dev);
+ int ret, i;
+
+ ctrl->fb = kmalloc(pdata->nr_wins *
+ sizeof(*(ctrl->fb)), GFP_KERNEL);
+ if (!ctrl->fb) {
+ dev_err(ctrl->dev, "not enough memory\n");
+ ret = -ENOMEM;
+ goto err_alloc;
+ }
+
+ for (i = 0; i < pdata->nr_wins; i++) {
+ ctrl->fb[i] = framebuffer_alloc(sizeof(*ctrl->fb),
+ ctrl->dev);
+ if (!ctrl->fb[i]) {
+ dev_err(ctrl->dev, "not enough memory\n");
+ ret = -ENOMEM;
+ goto err_alloc_fb;
+ }
+
+ s3cfb_init_fbinfo(ctrl, i);
+
+ if (i == pdata->default_win) {
+ if (s3cfb_map_video_memory(ctrl->fb[i])) {
+ dev_err(ctrl->dev,
+ "failed to map video memory "
+ "for default window (%d)\n", i);
+ ret = -ENOMEM;
+ goto err_map_video_mem;
+ }
+ }
+ }
+
+ return 0;
+
+err_alloc_fb:
+ while (--i >= 0) {
+ if (i == pdata->default_win)
+ s3cfb_unmap_default_video_memory(ctrl->fb[i]);
+
+err_map_video_mem:
+ framebuffer_release(ctrl->fb[i]);
+ }
+ kfree(ctrl->fb);
+
+err_alloc:
+ return ret;
+}
+
+static int s3cfb_register_framebuffer(struct s3cfb_global *ctrl)
+{
+ struct s3c_platform_fb *pdata = to_fb_plat(ctrl->dev);
+ int ret, i, j;
+
+ for (i = pdata->default_win;
+ i < pdata->nr_wins + pdata->default_win; i++) {
+ j = i % pdata->nr_wins;
+ ret = register_framebuffer(ctrl->fb[j]);
+ if (ret) {
+ dev_err(ctrl->dev, "failed to register "
+ "framebuffer device\n");
+ return -EINVAL;
+ goto err_register_fb;
+ }
+#ifndef CONFIG_FRAMEBUFFER_CONSOLE
+ if (j == pdata->default_win) {
+ s3cfb_check_var(&ctrl->fb[j]->var, ctrl->fb[j]);
+ s3cfb_set_par(ctrl->fb[j]);
+ s3cfb_draw_logo(ctrl->fb[j]);
+ }
+#endif
+ }
+
+ return 0;
+err_register_fb:
+ while (--i >= pdata->default_win) {
+ j = i % pdata->nr_wins;
+ unregister_framebuffer(ctrl->fb[j]);
+ }
+ return ret;
+}
+static int s3cfb_sysfs_show_win_power(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct s3c_platform_fb *pdata = to_fb_plat(dev);
+ struct platform_device *pdev = to_platform_device(dev);
+ struct s3cfb_global *fbdev = platform_get_drvdata(pdev);
+ struct s3cfb_window *win;
+ char temp[16];
+ int i;
+
+ for (i = 0; i < pdata->nr_wins; i++) {
+ win = fbdev->fb[i]->par;
+ sprintf(temp, "[fb%d] %s\n", i, win->enabled ? "on" : "off");
+ strcat(buf, temp);
+ }
+
+ return strlen(buf);
+}
+
+static int s3cfb_sysfs_store_win_power(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct s3c_platform_fb *pdata = to_fb_plat(dev);
+ struct platform_device *pdev = to_platform_device(dev);
+ struct s3cfb_global *fbdev = platform_get_drvdata(pdev);
+ int id, to;
+ int ret = 0;
+
+ ret = strict_strtoul(buf, 10, (unsigned long *)&id);
+ if (ret < 0)
+ return -EINVAL;
+
+ to = (id % 10);
+ if (to != 0 && to != 1)
+ return -EINVAL;
+
+ id = (id / 10);
+ if (id < 0 || id >= pdata->nr_wins)
+ return -EINVAL;
+
+ s3cfb_set_window(fbdev, id, to);
+
+ return len;
+}
+
+static DEVICE_ATTR(win_power, S_IRUGO | S_IWUSR,
+ s3cfb_sysfs_show_win_power, s3cfb_sysfs_store_win_power);
+
+static int __devinit s3cfb_probe(struct platform_device *pdev)
+{
+ struct s3c_platform_fb *pdata;
+ struct s3cfb_global *fbdev;
+ struct resource *res;
+ int i, j, ret = 0;
+
+ fbdev = kzalloc(sizeof(struct s3cfb_global), GFP_KERNEL);
+ if (!fbdev) {
+ dev_err(fbdev->dev, "failed to allocate for "
+ "global fb structure\n");
+ ret = -ENOMEM;
+ goto err_global;
+ }
+ fbdev->dev = &pdev->dev;
+
+ fbdev->regulator = regulator_get(&pdev->dev, "pd");
+ if (!fbdev->regulator) {
+ dev_err(fbdev->dev, "failed to get regulator\n");
+ ret = -EINVAL;
+ goto err_regulator;
+ }
+ ret = regulator_enable(fbdev->regulator);
+ if (ret < 0) {
+ dev_err(fbdev->dev, "failed to enable regulator\n");
+ ret = -EINVAL;
+ goto err_regulator;
+ }
+
+ fbdev->vcc_lcd = regulator_get(&pdev->dev, "vcc_lcd");
+ if (!fbdev->vcc_lcd) {
+ dev_err(fbdev->dev, "failed to get vcc_lcd\n");
+ ret = -EINVAL;
+ goto err_vcc_lcd;
+ }
+ ret = regulator_enable(fbdev->vcc_lcd);
+ if (ret < 0) {
+ dev_err(fbdev->dev, "failed to enable vcc_lcd\n");
+ ret = -EINVAL;
+ goto err_vcc_lcd;
+ }
+
+ fbdev->vlcd = regulator_get(&pdev->dev, "vlcd");
+ if (!fbdev->vlcd) {
+ dev_err(fbdev->dev, "failed to get vlcd\n");
+ ret = -EINVAL;
+ goto err_vlcd;
+ }
+ ret = regulator_enable(fbdev->vlcd);
+ if (ret < 0) {
+ dev_err(fbdev->dev, "failed to enable vlcd\n");
+ ret = -EINVAL;
+ goto err_vlcd;
+ }
+
+ pdata = to_fb_plat(&pdev->dev);
+ if (!pdata) {
+ dev_err(fbdev->dev, "failed to get platform data\n");
+ ret = -EINVAL;
+ goto err_pdata;
+ }
+
+ fbdev->lcd = (struct s3cfb_lcd *)pdata->lcd;
+
+ if (pdata->cfg_gpio)
+ pdata->cfg_gpio(pdev);
+
+ if (pdata->clk_on)
+ pdata->clk_on(pdev, &fbdev->clock);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(fbdev->dev, "failed to get io memory region\n");
+ ret = -EINVAL;
+ goto err_io;
+ }
+
+ res = request_mem_region(res->start,
+ res->end - res->start + 1, pdev->name);
+ if (!res) {
+ dev_err(fbdev->dev, "failed to request io memory region\n");
+ ret = -EINVAL;
+ goto err_io;
+ }
+
+ fbdev->regs = ioremap(res->start, res->end - res->start + 1);
+ if (!fbdev->regs) {
+ dev_err(fbdev->dev, "failed to remap io region\n");
+ ret = -EINVAL;
+ goto err_mem;
+ }
+
+ s3cfb_set_vsync_interrupt(fbdev, 1);
+ s3cfb_set_global_interrupt(fbdev, 1);
+ s3cfb_init_global(fbdev);
+
+ if (s3cfb_alloc_framebuffer(fbdev)) {
+ ret = -ENOMEM;
+ goto err_alloc;
+ }
+
+ if (s3cfb_register_framebuffer(fbdev)) {
+ ret = -EINVAL;
+ goto err_register;
+ }
+
+ s3cfb_set_clock(fbdev);
+ s3cfb_set_window(fbdev, pdata->default_win, 1);
+
+ s3cfb_display_on(fbdev);
+
+ fbdev->irq = platform_get_irq(pdev, 0);
+ if (request_irq(fbdev->irq, s3cfb_irq_frame, IRQF_SHARED,
+ pdev->name, fbdev)) {
+ dev_err(fbdev->dev, "request_irq failed\n");
+ ret = -EINVAL;
+ goto err_irq;
+ }
+
+#ifdef CONFIG_FB_S3C_LCD_INIT
+#if defined(CONFIG_FB_S3C_TL2796)
+ if (pdata->backlight_on)
+ pdata->backlight_on(pdev);
+#endif
+ if (!bootloaderfb && pdata->reset_lcd)
+ pdata->reset_lcd(pdev);
+#endif
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ fbdev->early_suspend.suspend = s3cfb_early_suspend;
+ fbdev->early_suspend.resume = s3cfb_late_resume;
+ fbdev->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
+ register_early_suspend(&fbdev->early_suspend);
+#endif
+
+ ret = device_create_file(&(pdev->dev), &dev_attr_win_power);
+ if (ret < 0)
+ dev_err(fbdev->dev, "failed to add sysfs entries\n");
+
+ dev_info(fbdev->dev, "registered successfully\n");
+
+ return 0;
+
+err_irq:
+ s3cfb_display_off(fbdev);
+ s3cfb_set_window(fbdev, pdata->default_win, 0);
+ for (i = pdata->default_win;
+ i < pdata->nr_wins + pdata->default_win; i++) {
+ j = i % pdata->nr_wins;
+ unregister_framebuffer(fbdev->fb[j]);
+ }
+err_register:
+ for (i = 0; i < pdata->nr_wins; i++) {
+ if (i == pdata->default_win)
+ s3cfb_unmap_default_video_memory(fbdev->fb[i]);
+ framebuffer_release(fbdev->fb[i]);
+ }
+ kfree(fbdev->fb);
+
+err_alloc:
+ iounmap(fbdev->regs);
+
+err_mem:
+ release_mem_region(res->start,
+ res->end - res->start + 1);
+
+err_io:
+ pdata->clk_off(pdev, &fbdev->clock);
+
+err_pdata:
+ regulator_disable(fbdev->vlcd);
+
+err_vlcd:
+ regulator_disable(fbdev->vcc_lcd);
+
+err_vcc_lcd:
+ regulator_disable(fbdev->regulator);
+
+err_regulator:
+ kfree(fbdev);
+
+err_global:
+ return ret;
+}
+
+static int __devexit s3cfb_remove(struct platform_device *pdev)
+{
+ struct s3c_platform_fb *pdata = to_fb_plat(&pdev->dev);
+ struct s3cfb_global *fbdev = platform_get_drvdata(pdev);
+ struct s3cfb_window *win;
+ struct resource *res;
+ struct fb_info *fb;
+ int i;
+
+ device_remove_file(&(pdev->dev), &dev_attr_win_power);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&fbdev->early_suspend);
+#endif
+
+ free_irq(fbdev->irq, fbdev);
+ iounmap(fbdev->regs);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res)
+ release_mem_region(res->start,
+ res->end - res->start + 1);
+
+ pdata->clk_off(pdev, &fbdev->clock);
+
+ for (i = 0; i < pdata->nr_wins; i++) {
+ fb = fbdev->fb[i];
+
+ if (fb) {
+ win = fb->par;
+ if (win->id == pdata->default_win)
+ s3cfb_unmap_default_video_memory(fb);
+ else
+ s3cfb_unmap_video_memory(fb);
+
+ s3cfb_set_buffer_address(fbdev, i);
+ framebuffer_release(fb);
+ }
+ }
+
+ regulator_disable(fbdev->regulator);
+
+ kfree(fbdev->fb);
+ kfree(fbdev);
+
+ return 0;
+}
+
+void s3cfb_early_suspend(struct early_suspend *h)
+{
+ struct s3cfb_global *fbdev =
+ container_of(h, struct s3cfb_global, early_suspend);
+
+ pr_debug("s3cfb_early_suspend is called\n");
+
+ s3cfb_display_off(fbdev);
+ clk_disable(fbdev->clock);
+#if defined(CONFIG_FB_S3C_TL2796)
+ lcd_cfg_gpio_early_suspend();
+#endif
+ regulator_disable(fbdev->vlcd);
+ regulator_disable(fbdev->vcc_lcd);
+ regulator_disable(fbdev->regulator);
+
+ return ;
+}
+
+void s3cfb_late_resume(struct early_suspend *h)
+{
+ struct s3cfb_global *fbdev =
+ container_of(h, struct s3cfb_global, early_suspend);
+ struct s3c_platform_fb *pdata = to_fb_plat(fbdev->dev);
+ struct platform_device *pdev = to_platform_device(fbdev->dev);
+ struct fb_info *fb;
+ struct s3cfb_window *win;
+ int i, j, ret;
+
+ pr_info("s3cfb_late_resume is called\n");
+
+ ret = regulator_enable(fbdev->regulator);
+ if (ret < 0)
+ dev_err(fbdev->dev, "failed to enable regulator\n");
+
+ ret = regulator_enable(fbdev->vcc_lcd);
+ if (ret < 0)
+ dev_err(fbdev->dev, "failed to enable vcc_lcd\n");
+
+ ret = regulator_enable(fbdev->vlcd);
+ if (ret < 0)
+ dev_err(fbdev->dev, "failed to enable vlcd\n");
+
+#if defined(CONFIG_FB_S3C_TL2796)
+ lcd_cfg_gpio_late_resume();
+#endif
+ dev_dbg(fbdev->dev, "wake up from suspend\n");
+ if (pdata->cfg_gpio)
+ pdata->cfg_gpio(pdev);
+
+ clk_enable(fbdev->clock);
+ s3cfb_init_global(fbdev);
+ s3cfb_set_clock(fbdev);
+
+ s3cfb_display_on(fbdev);
+
+ for (i = pdata->default_win;
+ i < pdata->nr_wins + pdata->default_win; i++) {
+ j = i % pdata->nr_wins;
+ fb = fbdev->fb[j];
+ win = fb->par;
+ if ((win->path == DATA_PATH_DMA) && (win->enabled)) {
+ s3cfb_set_par(fb);
+ s3cfb_set_window(fbdev, win->id, 1);
+ }
+ }
+
+ s3cfb_set_vsync_interrupt(fbdev, 1);
+ s3cfb_set_global_interrupt(fbdev, 1);
+
+ if (pdata->backlight_on)
+ pdata->backlight_on(pdev);
+
+ if (pdata->reset_lcd)
+ pdata->reset_lcd(pdev);
+
+ pr_info("s3cfb_late_resume is complete\n");
+ return ;
+}
+
+static struct platform_driver s3cfb_driver = {
+ .probe = s3cfb_probe,
+ .remove = __devexit_p(s3cfb_remove),
+ .driver = {
+ .name = S3CFB_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init s3cfb_register(void)
+{
+ platform_driver_register(&s3cfb_driver);
+
+ return 0;
+}
+static void __exit s3cfb_unregister(void)
+{
+ platform_driver_unregister(&s3cfb_driver);
+}
+
+module_init(s3cfb_register);
+module_exit(s3cfb_unregister);
+
+MODULE_AUTHOR("Jonghun, Han <jonghun.han@samsung.com>");
+MODULE_AUTHOR("Jinsung, Yang <jsgood.yang@samsung.com>");
+MODULE_DESCRIPTION("Samsung Display Controller (FIMD) driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/samsung/s3cfb.h b/drivers/video/samsung/s3cfb.h
new file mode 100755
index 0000000..147b4d8
--- /dev/null
+++ b/drivers/video/samsung/s3cfb.h
@@ -0,0 +1,375 @@
+/* linux/drivers/video/samsung/s3cfb.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Header file for Samsung Display Driver (FIMD) driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef _S3CFB_H
+#define _S3CFB_H
+
+#ifdef __KERNEL__
+#include <linux/wait.h>
+#include <linux/mutex.h>
+#include <linux/fb.h>
+#ifdef CONFIG_HAS_WAKELOCK
+#include <linux/wakelock.h>
+#include <linux/earlysuspend.h>
+#endif
+#include <plat/fb.h>
+#endif
+
+/*
+ * C O M M O N D E F I N I T I O N S
+ *
+*/
+#define S3CFB_NAME "s3cfb"
+
+#define S3CFB_AVALUE(r, g, b) (((r & 0xf) << 8) | \
+ ((g & 0xf) << 4) | \
+ ((b & 0xf) << 0))
+#define S3CFB_CHROMA(r, g, b) (((r & 0xff) << 16) | \
+ ((g & 0xff) << 8) | \
+ ((b & 0xff) << 0))
+
+/*
+ * E N U M E R A T I O N S
+ *
+*/
+enum s3cfb_data_path_t {
+ DATA_PATH_FIFO = 0,
+ DATA_PATH_DMA = 1,
+ DATA_PATH_IPC = 2,
+};
+
+enum s3cfb_alpha_t {
+ PLANE_BLENDING,
+ PIXEL_BLENDING,
+};
+
+enum s3cfb_chroma_dir_t {
+ CHROMA_FG,
+ CHROMA_BG,
+};
+
+enum s3cfb_output_t {
+ OUTPUT_RGB,
+ OUTPUT_ITU,
+ OUTPUT_I80LDI0,
+ OUTPUT_I80LDI1,
+ OUTPUT_WB_RGB,
+ OUTPUT_WB_I80LDI0,
+ OUTPUT_WB_I80LDI1,
+};
+
+enum s3cfb_rgb_mode_t {
+ MODE_RGB_P = 0,
+ MODE_BGR_P = 1,
+ MODE_RGB_S = 2,
+ MODE_BGR_S = 3,
+};
+
+enum s3cfb_mem_owner_t {
+ DMA_MEM_NONE = 0,
+ DMA_MEM_FIMD = 1,
+ DMA_MEM_OTHER = 2,
+};
+
+/*
+ * F I M D S T R U C T U R E S
+ *
+*/
+
+/*
+ * struct s3cfb_alpha
+ * @mode: blending method (plane/pixel)
+ * @channel: alpha channel (0/1)
+ * @value: alpha value (for plane blending)
+*/
+struct s3cfb_alpha {
+ enum s3cfb_alpha_t mode;
+ int channel;
+ unsigned int value;
+};
+
+/*
+ * struct s3cfb_chroma
+ * @enabled: if chroma key function enabled
+ * @blended: if chroma key alpha blending enabled (unused)
+ * @key: chroma value to be applied
+ * @comp_key: compare key (unused)
+ * @alpha: alpha value for chroma (unused)
+ * @dir: chroma key direction (fg/bg, fixed to fg)
+ *
+*/
+struct s3cfb_chroma {
+ int enabled;
+ int blended;
+ unsigned int key;
+ unsigned int comp_key;
+ unsigned int alpha;
+ enum s3cfb_chroma_dir_t dir;
+};
+
+/*
+ * struct s3cfb_lcd_polarity
+ * @rise_vclk: if 1, video data is fetched at rising edge
+ * @inv_hsync: if HSYNC polarity is inversed
+ * @inv_vsync: if VSYNC polarity is inversed
+ * @inv_vden: if VDEN polarity is inversed
+*/
+struct s3cfb_lcd_polarity {
+ int rise_vclk;
+ int inv_hsync;
+ int inv_vsync;
+ int inv_vden;
+};
+
+/*
+ * struct s3cfb_lcd_timing
+ * @h_fp: horizontal front porch
+ * @h_bp: horizontal back porch
+ * @h_sw: horizontal sync width
+ * @v_fp: vertical front porch
+ * @v_fpe: vertical front porch for even field
+ * @v_bp: vertical back porch
+ * @v_bpe: vertical back porch for even field
+*/
+struct s3cfb_lcd_timing {
+ int h_fp;
+ int h_bp;
+ int h_sw;
+ int v_fp;
+ int v_fpe;
+ int v_bp;
+ int v_bpe;
+ int v_sw;
+};
+
+/*
+ * struct s3cfb_lcd
+ * @width: horizontal resolution
+ * @height: vertical resolution
+ * @p_width: width of lcd in mm
+ * @p_height: height of lcd in mm
+ * @bpp: bits per pixel
+ * @freq: vframe frequency
+ * @timing: timing values
+ * @polarity: polarity settings
+ * @init_ldi: pointer to LDI init function
+ *
+*/
+struct s3cfb_lcd {
+ int width;
+ int height;
+ int p_width;
+ int p_height;
+ int bpp;
+ int freq;
+ struct s3cfb_lcd_timing timing;
+ struct s3cfb_lcd_polarity polarity;
+
+ void (*init_ldi)(void);
+ void (*deinit_ldi)(void);
+};
+
+/*
+ * struct s3cfb_window
+ * @id: window id
+ * @enabled: if enabled
+ * @x: left x of start offset
+ * @y: top y of start offset
+ * @path: data path (dma/fifo)
+ * @local_channel: local channel for fifo path (0/1)
+ * @dma_burst: dma burst length (4/8/16)
+ * @unpacked: if unpacked format is
+ * @pseudo_pal: pseudo palette for fb layer
+ * @alpha: alpha blending structure
+ * @chroma: chroma key structure
+*/
+struct s3cfb_window {
+ int id;
+ int enabled;
+ int in_use;
+ int x;
+ int y;
+ enum s3cfb_data_path_t path;
+ enum s3cfb_mem_owner_t owner;
+ unsigned int other_mem_addr;
+ unsigned int other_mem_size;
+ int local_channel;
+ int dma_burst;
+ unsigned int pseudo_pal[16];
+ struct s3cfb_alpha alpha;
+ struct s3cfb_chroma chroma;
+};
+
+/*
+ * struct s3cfb_global
+ *
+ * @fb: pointer to fb_info
+ * @enabled: if signal output enabled
+ * @dsi: if mipi-dsim enabled
+ * @interlace: if interlace format is used
+ * @output: output path (RGB/I80/Etc)
+ * @rgb_mode: RGB mode
+ * @lcd: pointer to lcd structure
+*/
+struct s3cfb_global {
+ /* general */
+ void __iomem *regs;
+ struct mutex lock;
+ struct device *dev;
+ struct clk *clock;
+ struct regulator *regulator;
+ struct regulator *vcc_lcd;
+ struct regulator *vlcd;
+ int irq;
+ struct fb_info **fb;
+
+ wait_queue_head_t vsync_wait;
+ ktime_t vsync_timestamp;
+
+ int vsync_state;
+ struct task_struct *vsync_thread;
+
+ /* fimd */
+ int enabled;
+ int dsi;
+ int interlace;
+ enum s3cfb_output_t output;
+ enum s3cfb_rgb_mode_t rgb_mode;
+ struct s3cfb_lcd *lcd;
+ u32 pixclock_hz;
+
+#ifdef CONFIG_HAS_WAKELOCK
+ struct early_suspend early_suspend;
+ struct wake_lock idle_lock;
+#endif
+
+#ifdef CONFIG_CPU_FREQ
+ struct notifier_block freq_transition;
+ struct notifier_block freq_policy;
+#endif
+
+};
+
+
+/*
+ * S T R U C T U R E S F O R C U S T O M I O C T L S
+ *
+*/
+struct s3cfb_user_window {
+ int x;
+ int y;
+};
+
+struct s3cfb_user_plane_alpha {
+ int channel;
+ unsigned char red;
+ unsigned char green;
+ unsigned char blue;
+};
+
+struct s3cfb_user_chroma {
+ int enabled;
+ unsigned char red;
+ unsigned char green;
+ unsigned char blue;
+};
+
+struct s3cfb_next_info {
+ unsigned int phy_start_addr;
+ unsigned int xres; /* visible resolution*/
+ unsigned int yres;
+ unsigned int xres_virtual; /* virtual resolution*/
+ unsigned int yres_virtual;
+ unsigned int xoffset; /* offset from virtual to visible */
+ unsigned int yoffset; /* resolution */
+ unsigned int lcd_offset_x;
+ unsigned int lcd_offset_y;
+};
+
+/*
+ * C U S T O M I O C T L S
+ *
+*/
+#define S3CFB_WIN_POSITION _IOW('F', 203, \
+ struct s3cfb_user_window)
+#define S3CFB_WIN_SET_PLANE_ALPHA _IOW('F', 204, \
+ struct s3cfb_user_plane_alpha)
+#define S3CFB_WIN_SET_CHROMA _IOW('F', 205, \
+ struct s3cfb_user_chroma)
+#define S3CFB_SET_VSYNC_INT _IOW('F', 206, u32)
+#define S3CFB_GET_VSYNC_INT_STATUS _IOR('F', 207, u32)
+#define S3CFB_GET_LCD_WIDTH _IOR('F', 302, int)
+#define S3CFB_GET_LCD_HEIGHT _IOR('F', 303, int)
+#define S3CFB_SET_WRITEBACK _IOW('F', 304, u32)
+#define S3CFB_GET_CURR_FB_INFO _IOR('F', 305, struct s3cfb_next_info)
+#define S3CFB_SET_WIN_ON _IOW('F', 306, u32)
+#define S3CFB_SET_WIN_OFF _IOW('F', 307, u32)
+#define S3CFB_SET_WIN_PATH _IOW('F', 308, \
+ enum s3cfb_data_path_t)
+#define S3CFB_SET_WIN_ADDR _IOW('F', 309, unsigned long)
+#define S3CFB_SET_WIN_MEM _IOW('F', 310, \
+ enum s3cfb_mem_owner_t)
+// New IOCTL that waits for vsync and returns a timestamp
+#define S3CFB_WAIT_FOR_VSYNC _IOR('F', 311, u64)
+
+/*
+ * E X T E R N S
+ *
+*/
+extern int soft_cursor(struct fb_info *info, struct fb_cursor *cursor);
+extern void s3cfb_set_lcd_info(struct s3cfb_global *ctrl);
+extern struct s3c_platform_fb *to_fb_plat(struct device *dev);
+extern void s3cfb_check_line_count(struct s3cfb_global *ctrl);
+extern int s3cfb_set_output(struct s3cfb_global *ctrl);
+extern int s3cfb_set_display_mode(struct s3cfb_global *ctrl);
+extern int s3cfb_display_on(struct s3cfb_global *ctrl);
+extern int s3cfb_display_off(struct s3cfb_global *ctrl);
+extern int s3cfb_frame_off(struct s3cfb_global *ctrl);
+extern int s3cfb_set_clock(struct s3cfb_global *ctrl);
+extern int s3cfb_set_polarity(struct s3cfb_global *ctrl);
+extern int s3cfb_set_timing(struct s3cfb_global *ctrl);
+extern int s3cfb_set_lcd_size(struct s3cfb_global *ctrl);
+extern int s3cfb_set_global_interrupt(struct s3cfb_global *ctrl, int enable);
+extern int s3cfb_set_vsync_interrupt(struct s3cfb_global *ctrl, int enable);
+extern int s3cfb_get_vsync_interrupt(struct s3cfb_global *ctrl);
+extern int s3cfb_set_fifo_interrupt(struct s3cfb_global *ctrl, int enable);
+extern int s3cfb_clear_interrupt(struct s3cfb_global *ctrl);
+extern int s3cfb_channel_localpath_on(struct s3cfb_global *ctrl, int id);
+extern int s3cfb_channel_localpath_off(struct s3cfb_global *ctrl, int id);
+extern int s3cfb_window_on(struct s3cfb_global *ctrl, int id);
+extern int s3cfb_window_off(struct s3cfb_global *ctrl, int id);
+extern int s3cfb_win_map_on(struct s3cfb_global *ctrl, int id, int color);
+extern int s3cfb_win_map_off(struct s3cfb_global *ctrl, int id);
+extern int s3cfb_set_window_control(struct s3cfb_global *ctrl, int id);
+extern int s3cfb_set_alpha_blending(struct s3cfb_global *ctrl, int id);
+extern int s3cfb_set_window_position(struct s3cfb_global *ctrl, int id);
+extern int s3cfb_set_window_size(struct s3cfb_global *ctrl, int id);
+extern int s3cfb_set_buffer_address(struct s3cfb_global *ctrl, int id);
+extern int s3cfb_set_buffer_size(struct s3cfb_global *ctrl, int id);
+extern int s3cfb_set_chroma_key(struct s3cfb_global *ctrl, int id);
+
+#ifdef CONFIG_HAS_WAKELOCK
+#ifdef CONFIG_HAS_EARLYSUSPEND
+extern void s3cfb_early_suspend(struct early_suspend *h);
+extern void s3cfb_late_resume(struct early_suspend *h);
+#endif
+#endif
+
+#if defined(CONFIG_FB_S3C_TL2796)
+extern void tl2796_ldi_init(void);
+extern void tl2796_ldi_enable(void);
+extern void tl2796_ldi_disable(void);
+extern void lcd_cfg_gpio_early_suspend(void);
+extern void lcd_cfg_gpio_late_resume(void);
+#endif
+
+#endif /* _S3CFB_H */
diff --git a/drivers/video/samsung/s3cfb_ams701ka.c b/drivers/video/samsung/s3cfb_ams701ka.c
new file mode 100644
index 0000000..018d25d
--- /dev/null
+++ b/drivers/video/samsung/s3cfb_ams701ka.c
@@ -0,0 +1,723 @@
+/*
+ * ams701ka AMOLED Panel Driver for the Samsung Universal board
+ *
+ * Derived from drivers/video/samsung/s3cfb_tl2796.c
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/wait.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/lcd.h>
+#include <linux/backlight.h>
+
+#ifdef CONFIG_HAS_WAKELOCK
+#include <linux/wakelock.h>
+#include <linux/earlysuspend.h>
+#include <linux/suspend.h>
+#endif
+
+#include <plat/gpio-cfg.h>
+#include <plat/regs-fb.h>
+
+#include "s3cfb.h"
+
+#define SLEEPMSEC 0x1000
+#define ENDDEF 0x2000
+#define DEFMASK 0xFF00
+#define COMMAND_ONLY 0xFE
+#define DATA_ONLY 0xFF
+
+const unsigned short SEQ_DISPLAY_ON[] = {
+ 0x2e, 0x0607,
+ SLEEPMSEC, 1,
+ 0x30, 0x230D,
+ 0x31, 0x161E,
+ ENDDEF, 0x0000
+};
+
+const unsigned short SEQ_MANUAL_DISPLAY_ON[] = {
+ 0x12, 0x0001,
+ SLEEPMSEC, 1,
+ 0x12, 0x0003,
+ SLEEPMSEC, 1,
+ 0x12, 0x0007,
+ SLEEPMSEC, 1,
+ 0x2e, 0x0605,
+ SLEEPMSEC, 1,
+ 0x30, 0x2307,
+ 0x31, 0x161E,
+ SLEEPMSEC, 5,
+ 0x12, 0x000f,
+ SLEEPMSEC, 10,
+ 0x12, 0x001f,
+ SLEEPMSEC, 10,
+
+ 0xf4, 0x0003,
+
+ ENDDEF, 0x0000
+};
+
+const unsigned short SEQ_DISPLAY_OFF[] = {
+ 0x12, 0x000f,
+ 0x12, 0x0007,
+ SLEEPMSEC, 1, /* FIXME */
+ 0x12, 0x0001,
+ 0x12, 0x0000,
+ SLEEPMSEC, 1, /* FIXME */
+ ENDDEF, 0x0000
+};
+
+const unsigned short SEQ_STANDBY_ON[] = {
+ 0x02, 0x2301,
+
+ ENDDEF, 0x0000
+};
+
+const unsigned short SEQ_STANDBY_OFF[] = {
+ 0x02, 0x2300,
+
+ ENDDEF, 0x0000
+};
+
+const unsigned short GAMMA_SETTING[] = {
+
+#if 0
+ /* Low Red Gamma */
+ 0x4c, 0xc209,
+ 0x4d, 0xdac8,
+ 0x4e, 0xc4bf,
+ 0x4f, 0x0093,
+
+ /* Low Green Gamma */
+ 0x50, 0xad04,
+ 0x51, 0xd1c5,
+ 0x52, 0xbfc8,
+ 0x53, 0x009d,
+
+ /* Low Blue Gamma */
+ 0x54, 0xbb09,
+ 0x55, 0xd2c9,
+ 0x56, 0xbcc4,
+ 0x57, 0x00b7,
+#endif
+#if 0 //SLP1
+ /* High Red Gamma */
+ 0x40, 0xCA09, 0x41, 0xD9C9, 0x42, 0xC3B5, 0x43, 0x00A7,
+
+ /* High Green Gamma */
+ 0x44, 0xBC04, 0x45, 0xD4C5, 0x46, 0xC0B1, 0x47, 0x00C8,
+
+ /* High Blue Gamma */
+ 0x48, 0xC209, 0x49, 0xD3C1, 0x4a, 0xBCAC, 0x4b, 0x00D8,
+#else //SLP2
+ /* High Red Gamma */
+ 0x40, 0xC809, 0x41, 0xD9C9, 0x42, 0xC3B5, 0x43, 0x00A6,
+
+ /* High Green Gamma */
+ 0x44, 0xBD04, 0x45, 0xD4C5, 0x46, 0xBEB0, 0x47, 0x00C7,
+
+ /* High Blue Gamma */
+ 0x48, 0xBD09, 0x49, 0xD2C1, 0x4a, 0xBCAC, 0x4b, 0x00D7,
+#endif
+
+ 0x3f, 0x0004, /* gamma setting : ams701ka */
+ 0x32, 0x0002,
+ ENDDEF, 0x0000
+};
+
+const unsigned short MANUAL_POWER_ON_SETTING[] = {
+ 0x06, 0x0000,
+
+ SLEEPMSEC, 30, /* FIXME */
+ 0x06, 0x0001,
+ SLEEPMSEC, 30, /* FIXME */
+ 0x06, 0x0005,
+ SLEEPMSEC, 30, /* FIXME */
+ 0x06, 0x0007,
+ SLEEPMSEC, 30, /* FIXME */
+ 0x06, 0x000f,
+ SLEEPMSEC, 30, /* FIXME */
+ 0x06, 0x001f,
+ SLEEPMSEC, 30, /* FIXME */
+ 0x06, 0x003f,
+ SLEEPMSEC, 30, /* FIXME */
+ 0x06, 0x007f,
+ SLEEPMSEC, 30, /* FIXME */
+ 0x06, 0x00ff,
+ SLEEPMSEC, 30, /* FIXME */
+ 0x06, 0x08ff,
+ SLEEPMSEC, 30, /* FIXME */
+
+ 0x03, 0x134A, /* ETC Register setting */
+ 0x04, 0x86a4, /* LTPS Power on setting VCIR=2.7V Display is not clean */
+
+ 0x14, 0x0808, /* VFP, VBP Register setting */
+ 0x15, 0x3090, /* HSW,HFP,HBP Register setting */
+ ENDDEF, 0x0000
+
+};
+
+const unsigned short MANUAL_POWER_OFF_SETTING[] = {
+ 0x06, 0x8FF,
+ SLEEPMSEC, 1,
+ 0x06, 0x3FF,
+ SLEEPMSEC, 5,
+ 0x06, 0x07F,
+ SLEEPMSEC, 5,
+ 0x06, 0x03F,
+ SLEEPMSEC, 5,
+ 0x06, 0x01F,
+ SLEEPMSEC, 5,
+ 0x06, 0x00F,
+ SLEEPMSEC, 5,
+ 0x06, 0x007,
+ SLEEPMSEC, 5,
+ 0x06, 0x003,
+ SLEEPMSEC, 5,
+ 0x06, 0x001,
+ SLEEPMSEC, 5,
+ 0x06, 0x000,
+ SLEEPMSEC, 5,
+
+ ENDDEF, 0x0000
+};
+
+const unsigned short SEQ_SLEEP_OUT[] = {
+ 0x02, 0x2300, /* Sleep Out */
+ SLEEPMSEC, 1, /* FIXME */
+ ENDDEF, 0x0000
+};
+
+const unsigned short ACL_ON_DISPLAY_SETTING[] = {
+ 0x5b, 0x0013,
+ 0x5c, 0x0000,
+ 0x5d, 0x03ff,
+ 0x5e, 0x0000,
+ 0x5f, 0x0257,
+ ENDDEF, 0x0000
+};
+
+const unsigned short ACL_ON_WINDOW_SETTING[] = {
+ 0x5b, 0x0013,
+ 0x5c, 0x0200,
+ 0x5d, 0x03ff,
+ 0x5e, 0x0000,
+ 0x5f, 0x0257,
+ ENDDEF, 0x0000
+};
+
+const unsigned short GAMMA22_SETTINGS[][30] = {
+ // Luminance : 70nit
+ { 0x40, 0xD309, 0x41, 0xDDDD, 0x42, 0xD3C1, 0x43, 0x0061, /* High Red Gamma */
+ 0x44, 0x9804, 0x45, 0xDAD1, 0x46, 0xCEBD, 0x47, 0x0075, /* High Green Gamma */
+ 0x48, 0xC509, 0x49, 0xDBD3, 0x4a, 0xCCBC, 0x4b, 0x007F, /* High Blue Gamma */
+ 0x3f, 0x0004, 0x32, 0x0002, ENDDEF, 0x0000 /* gamma setting : ams701ka */
+ },
+ // Luminance : 82nit
+ { 0x40, 0xCF09, 0x41, 0xDDDC, 0x42, 0xD1C1, 0x43, 0x0067, /* High Red Gamma */
+ 0x44, 0x9A04, 0x45, 0xDCD0, 0x46, 0xCDBC, 0x47, 0x007C, /* High Green Gamma */
+ 0x48, 0xC109, 0x49, 0xDCD2, 0x4a, 0xCBBA, 0x4b, 0x0087, /* High Blue Gamma */
+ 0x3f, 0x0004, 0x32, 0x0002, ENDDEF, 0x0000 /* gamma setting : ams701ka */
+ },
+ // Luminance : 94nit
+ { 0x40, 0xCF09, 0x41, 0xDCDC, 0x42, 0xD2BF, 0x43, 0x006C, /* High Red Gamma */
+ 0x44, 0xA804, 0x45, 0xDAD2, 0x46, 0xCCBB, 0x47, 0x0083, /* High Green Gamma */
+ 0x48, 0xC309, 0x49, 0xDAD4, 0x4a, 0xCAB9, 0x4b, 0x008E, /* High Blue Gamma */
+ 0x3f, 0x0004, 0x32, 0x0002, ENDDEF, 0x0000 /* gamma setting : ams701ka */
+ },
+ // Luminance : 106nit
+ { 0x40, 0xCD09, 0x41, 0xDCDA, 0x42, 0xD0BE, 0x43, 0x0072, /* High Red Gamma */
+ 0x44, 0xA904, 0x45, 0xDAD0, 0x46, 0xCABA, 0x47, 0x008B, /* High Green Gamma */
+ 0x48, 0xC209, 0x49, 0xDAD1, 0x4a, 0xC8B8, 0x4b, 0x0096, /* High Blue Gamma */
+ 0x3f, 0x0004, 0x32, 0x0002, ENDDEF, 0x0000 /* gamma setting : ams701ka */
+ },
+ // Luminance : 118nit
+ { 0x40, 0xCF09, 0x41, 0xDBDA, 0x42, 0xCFBE, 0x43, 0x0077, /* High Red Gamma */
+ 0x44, 0xAD04, 0x45, 0xDAD1, 0x46, 0xCAB9, 0x47, 0x0090, /* High Green Gamma */
+ 0x48, 0xC309, 0x49, 0xD9D2, 0x4a, 0xC9B7, 0x4b, 0x009B, /* High Blue Gamma */
+ 0x3f, 0x0004, 0x32, 0x0002, ENDDEF, 0x0000 /* gamma setting : ams701ka */
+ },
+ // Luminance : 130nit
+ { 0x40, 0xCD09, 0x41, 0xDCD9, 0x42, 0xCDBD, 0x43, 0x007C, /* High Red Gamma */
+ 0x44, 0xAE04, 0x45, 0xDBD1, 0x46, 0xC7B8, 0x47, 0x0097, /* High Green Gamma */
+ 0x48, 0xC209, 0x49, 0xDAD1, 0x4a, 0xC6B6, 0x4b, 0x00A2, /* High Blue Gamma */
+ 0x3f, 0x0004, 0x32, 0x0002, ENDDEF, 0x0000 /* gamma setting : ams701ka */
+ },
+ // Luminance : 142nit
+ { 0x40, 0xCD09, 0x41, 0xDAD9, 0x42, 0xCEBB, 0x43, 0x0080, /* High Red Gamma */
+ 0x44, 0xB104, 0x45, 0xDAD1, 0x46, 0xC7B7, 0x47, 0x009C, /* High Green Gamma */
+ 0x48, 0xC209, 0x49, 0xDAD1, 0x4a, 0xC6B4, 0x4b, 0x00A8, /* High Blue Gamma */
+ 0x3f, 0x0004, 0x32, 0x0002, ENDDEF, 0x0000 /* gamma setting : ams701ka */
+ },
+ // Luminance : 154nit
+ { 0x40, 0xCB09, 0x41, 0xDAD9, 0x42, 0xCCBB, 0x43, 0x0085, /* High Red Gamma */
+ 0x44, 0xB104, 0x45, 0xD9D1, 0x46, 0xC7B6, 0x47, 0x00A1, /* High Green Gamma */
+ 0x48, 0xC109, 0x49, 0xD9D1, 0x4a, 0xC5B3, 0x4b, 0x00AE, /* High Blue Gamma */
+ 0x3f, 0x0004, 0x32, 0x0002, ENDDEF, 0x0000 /* gamma setting : ams701ka */
+ },
+ // Luminance : 166nit
+ { 0x40, 0xCD09, 0x41, 0xD9D9, 0x42, 0xCBBB, 0x43, 0x0089, /* High Red Gamma */
+ 0x44, 0xB704, 0x45, 0xD9D1, 0x46, 0xC6B6, 0x47, 0x00A6, /* High Green Gamma */
+ 0x48, 0xC309, 0x49, 0xD9D0, 0x4a, 0xC4B3, 0x4b, 0x00B3, /* High Blue Gamma */
+ 0x3f, 0x0004, 0x32, 0x0002, ENDDEF, 0x0000 /* gamma setting : ams701ka */
+ },
+ // Luminance : 178nit
+ { 0x40, 0xCB09, 0x41, 0xDAD8, 0x42, 0xCABA, 0x43, 0x008D, /* High Red Gamma */
+ 0x44, 0xB304, 0x45, 0xDAD0, 0x46, 0xC5B4, 0x47, 0x00AC, /* High Green Gamma */
+ 0x48, 0xC109, 0x49, 0xD9D0, 0x4a, 0xC3B2, 0x4b, 0x00B8, /* High Blue Gamma */
+ 0x3f, 0x0004, 0x32, 0x0002, ENDDEF, 0x0000 /* gamma setting : ams701ka */
+ },
+ // Luminance : 190nit
+ { 0x40, 0xCA09, 0x41, 0xDAD8, 0x42, 0xC9B9, 0x43, 0x0091, /* High Red Gamma */
+ 0x44, 0xB404, 0x45, 0xD8D0, 0x46, 0xC4B4, 0x47, 0x00B1, /* High Green Gamma */
+ 0x48, 0xC009, 0x49, 0xD8D0, 0x4a, 0xC3B1, 0x4b, 0x00BD, /* High Blue Gamma */
+ 0x3f, 0x0004, 0x32, 0x0002, ENDDEF, 0x0000 /* gamma setting : ams701ka */
+ },
+ // Luminance : 202nit
+ { 0x40, 0xCA09, 0x41, 0xD9D8, 0x42, 0xC8B9, 0x43, 0x0095, /* High Red Gamma */
+ 0x44, 0xB504, 0x45, 0xD9D1, 0x46, 0xC3B4, 0x47, 0x00B5, /* High Green Gamma */
+ 0x48, 0xC009, 0x49, 0xD8D0, 0x4a, 0xC2B1, 0x4b, 0x00C1, /* High Blue Gamma */
+ 0x3f, 0x0004, 0x32, 0x0002, ENDDEF, 0x0000 /* gamma setting : ams701ka */
+ },
+ // Luminance : 214nit
+ { 0x40, 0xCB09, 0x41, 0xDB07, 0x42, 0xC8B6, 0x43, 0x0099, /* High Red Gamma */
+ 0x44, 0xB704, 0x45, 0xD9D0, 0x46, 0xC2B2, 0x47, 0x00BA, /* High Green Gamma */
+ 0x48, 0xC209, 0x49, 0xD9CF, 0x4a, 0xC0AF, 0x4b, 0x00C8, /* High Blue Gamma */
+ 0x3f, 0x0004, 0x32, 0x0002, ENDDEF, 0x0000 /* gamma setting : ams701ka */
+ },
+ // Luminance : 226nit
+ { 0x40, 0xC909, 0x41, 0xD9D7, 0x42, 0xC7B7, 0x43, 0x009D, /* High Red Gamma */
+ 0x44, 0xB504, 0x45, 0xD7D0, 0x46, 0xC2B3, 0x47, 0x00BE, /* High Green Gamma */
+ 0x48, 0xBF09, 0x49, 0xD7CF, 0x4a, 0xC1B0, 0x4b, 0x00CB, /* High Blue Gamma */
+ 0x3f, 0x0004, 0x32, 0x0002, ENDDEF, 0x0000 /* gamma setting : ams701ka */
+ },
+ // Luminance : 238nit
+ { 0x40, 0xC209, 0x41, 0xD8D7, 0x42, 0xC3B5, 0x43, 0x00A0, /* High Red Gamma */
+ 0x44, 0xB604, 0x45, 0xD7D0, 0x46, 0xBFB1, 0x47, 0x00C5, /* High Green Gamma */
+ 0x48, 0xBF09, 0x49, 0xD7D0, 0x4a, 0xBBAE, 0x4b, 0x00D9, /* High Blue Gamma */
+ 0x3f, 0x0004, 0x32, 0x0002, ENDDEF, 0x0000 /* gamma setting : ams701ka */
+ },
+ // Luminance : 250nit
+ { 0x40, 0xC909, 0x41, 0xD7D8, 0x42, 0xC5B6, 0x43, 0x00A4, /* High Red Gamma */
+ 0x44, 0xB304, 0x45, 0xD7D1, 0x46, 0xBFB2, 0x47, 0x00C4, /* High Green Gamma */
+ 0x48, 0xBF09, 0x49, 0xD6D0, 0x4a, 0xBDAE, 0x4b, 0x00D7, /* High Blue Gamma */
+ 0x3f, 0x0004, 0x32, 0x0002, ENDDEF, 0x0000 /* gamma setting : ams701ka */
+ },
+};
+
+const unsigned short GAMMA19_SETTINGS[][30] = {
+ // Luminance : 250nit
+ { 0x40, 0xCA09, 0x41, 0xDBDA, 0x42, 0xCBBD, 0x43, 0x00A4, /* High Red Gamma */
+ 0x44, 0xC104, 0x45, 0xDAD4, 0x46, 0xC8B9, 0x47, 0x00C4, /* High Green Gamma */
+ 0x48, 0xC409, 0x49, 0xD9D3, 0x4a, 0xC3B6, 0x4b, 0x00D7, /* High Blue Gamma */
+ 0x3f, 0x0004, 0x32, 0x0002, ENDDEF, 0x0000 /* gamma setting : ams701ka */
+ },
+};
+
+#define MAX_BL_LEVEL 16
+
+static int locked = 0;
+
+typedef enum {
+ LDI_ENABLE = 1,
+ LDI_DISABLE = 0,
+} ldi_enable_t;
+
+static ldi_enable_t ldi_enable = LDI_DISABLE;
+
+struct s5p_lcd{
+ struct spi_device *g_spi;
+ struct lcd_device *lcd_dev;
+ struct backlight_device *bl_dev;
+};
+
+static struct s5p_lcd lcd;
+
+static int ams701ka_spi_write_driver(unsigned char addr, unsigned short data)
+{
+ u32 buf[1];
+ struct spi_message msg;
+
+ struct spi_transfer xfer = {
+ .len = 4,
+ .tx_buf = buf,
+ };
+
+ buf[0] = (addr << 16) | data;
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfer, &msg);
+
+ if(!(lcd.g_spi))
+ return -EINVAL;
+
+ return spi_sync(lcd.g_spi, &msg);
+}
+
+static void ams701ka_spi_write(unsigned char address, unsigned short command)
+{
+ if (address != DATA_ONLY)
+ ams701ka_spi_write_driver(0x70, address);
+
+ ams701ka_spi_write_driver(0x72, command);
+}
+
+static void ams701ka_panel_send_sequence(const unsigned short *wbuf)
+{
+ int i = 0;
+
+ while ((wbuf[i] & DEFMASK) != ENDDEF) {
+ if ((wbuf[i] & DEFMASK) != SLEEPMSEC)
+ ams701ka_spi_write(wbuf[i], wbuf[i+1]);
+ else
+ mdelay(wbuf[i+1]);
+ i += 2;
+ }
+}
+
+static void ams701ka_ldi_init(void)
+{
+ printk("AMS701KA_LDI_INIT!!!!!!!!!!!!!!!\n");
+
+ ams701ka_panel_send_sequence(GAMMA_SETTING);
+ ams701ka_panel_send_sequence(SEQ_SLEEP_OUT);
+ //ams701ka_panel_send_sequence(MANUAL_POWER_ON_SETTING);
+ ams701ka_panel_send_sequence(SEQ_DISPLAY_ON);
+ //ams701ka_panel_send_sequence(ACL_ON_DISPLAY_SETTING);
+
+ ldi_enable = LDI_ENABLE;
+}
+
+static int s5p_lcd_set_power(struct lcd_device *ld)
+{
+ printk("\n+++lcd set power\n");
+
+ return 0;
+}
+
+static struct lcd_ops s5p_lcd_ops = {
+ .set_power = s5p_lcd_set_power,
+};
+
+static int gamma_level = 16;
+
+static int s5p_bl_update_status(struct backlight_device* bd)
+{
+
+ int b = bd->props.brightness;
+ int bl = 255 - b;
+ int level = 0;
+ int i = 0;
+
+ if ((!locked) && (ldi_enable == LDI_ENABLE))
+ {
+ locked = 1;
+
+ if((bl <= 255) && (bl > 230))
+ level = 1;
+ else if((bl <= 230) && (bl > 200))
+ level = 6;
+ else if((bl <= 200) && (bl > 150))
+ level = 7;
+ else if((bl <= 150) && (bl > 100))
+ level = 8;
+ else if((bl <= 100) && (bl > 50))
+ level = 9;
+ else if((bl <= 50) && (bl >= 0))
+ level = 10;
+ else {
+ printk("bl(%d) is wrong \n", bl);
+ level = -1;
+ }
+
+ level = (b+1) / MAX_BL_LEVEL;
+
+ if (level < 1)
+ level = 1;
+ if (level > MAX_BL_LEVEL)
+ level = MAX_BL_LEVEL;
+
+ printk("Brightness is updated to level %d(%d)\n", level, b);
+
+ gamma_level = level;
+
+ ams701ka_panel_send_sequence(GAMMA22_SETTINGS[level-1]);
+
+ /*
+ switch(level)
+ {
+ case 5:
+ case 4:
+ case 3:
+ case 2:
+ case 1: //dimming
+ //s6e63m0_panel_send_sequence(s6e63m0_22gamma_50cd);
+ break;
+ case 6:
+ //s6e63m0_panel_send_sequence(s6e63m0_22gamma_100cd);
+ break;
+ case 7:
+ //s6e63m0_panel_send_sequence(s6e63m0_22gamma_140cd);
+ break;
+ case 8:
+ //s6e63m0_panel_send_sequence(s6e63m0_22gamma_180cd);
+ break;
+ case 9:
+ //s6e63m0_panel_send_sequence(s6e63m0_22gamma_260cd);
+ break;
+ case 10:
+ //s6e63m0_panel_send_sequence(s6e63m0_22gamma_300cd);
+ break;
+ default:
+ break;
+ }
+ */
+
+ locked = 0;
+ } else {
+ printk("Brightness updating is skip. locked: %d ~ ldi_enable: %d\n", locked, ldi_enable);
+ }
+
+ return 0;
+}
+
+void lightsensor_backlight_level_ctrl(int value)
+{
+ printk("Lightsensor_backlight_level_ctrl is called : level(%d)\n",value);
+
+ if(value > 21 || value < 1)
+ return;
+
+ switch(value){
+ case 21:
+ //s6e63m0_panel_send_sequence(s6e63m0_22gamma_180cd);
+ break;
+ case 20:
+ //s6e63m0_panel_send_sequence(s6e63m0_22gamma_180cd);
+ break;
+ case 19:
+ //s6e63m0_panel_send_sequence(s6e63m0_22gamma_180cd);
+ break;
+ case 18:
+ //s6e63m0_panel_send_sequence(s6e63m0_22gamma_180cd);
+ break;
+ case 17:
+ //s6e63m0_panel_send_sequence(s6e63m0_22gamma_180cd);
+ break;
+ case 16:
+ //s6e63m0_panel_send_sequence(s6e63m0_22gamma_180cd);
+ break;
+ case 15:
+ //s6e63m0_panel_send_sequence(s6e63m0_22gamma_180cd);
+ break;
+ case 14:
+ //s6e63m0_panel_send_sequence(s6e63m0_22gamma_180cd);
+ break;
+ case 13:
+ //s6e63m0_panel_send_sequence(s6e63m0_22gamma_180cd);
+ break;
+ case 12:
+ //s6e63m0_panel_send_sequence(s6e63m0_22gamma_180cd);
+ break;
+ case 11:
+ //s6e63m0_panel_send_sequence(s6e63m0_22gamma_180cd);
+ break;
+ case 10:
+ //s6e63m0_panel_send_sequence(s6e63m0_22gamma_180cd);
+ break;
+ case 9:
+ //s6e63m0_panel_send_sequence(s6e63m0_22gamma_180cd);
+ break;
+ case 8:
+ //s6e63m0_panel_send_sequence(s6e63m0_22gamma_180cd);
+ break;
+ case 7:
+ //s6e63m0_panel_send_sequence(s6e63m0_22gamma_180cd);
+ break;
+ case 6:
+ //s6e63m0_panel_send_sequence(s6e63m0_22gamma_180cd);
+ break;
+ case 5:
+ //s6e63m0_panel_send_sequence(s6e63m0_22gamma_180cd);
+ break;
+ case 4:
+ //s6e63m0_panel_send_sequence(s6e63m0_22gamma_180cd);
+ break;
+ case 3:
+ //s6e63m0_panel_send_sequence(s6e63m0_22gamma_180cd);
+ break;
+ case 2:
+ //s6e63m0_panel_send_sequence(s6e63m0_22gamma_180cd);
+ break;
+ case 1:
+ //s6e63m0_panel_send_sequence(s6e63m0_22gamma_180cd);
+ break;
+ default:
+ break;
+ }
+}
+EXPORT_SYMBOL(lightsensor_backlight_level_ctrl);
+
+
+static int s5p_bl_get_brightness(struct backlilght_device* bd)
+{
+ /* TODO: Should implemented. */
+ printk("Reading brightness\n");
+
+ return 0;
+}
+
+static struct backlight_ops s5p_bl_ops = {
+ .update_status = s5p_bl_update_status,
+ .get_brightness = s5p_bl_get_brightness,
+};
+
+static int __init ams701ka_probe(struct spi_device *spi)
+{
+ int ret = 0;
+
+ spi->bits_per_word = 24;
+ ret = spi_setup(spi);
+
+ if (ret < 0)
+ return ret;
+
+ if (!spi)
+ return -EINVAL;
+
+ lcd.g_spi = spi;
+
+ lcd.lcd_dev = lcd_device_register("s5p_lcd",&spi->dev,&lcd,&s5p_lcd_ops);
+
+ lcd.bl_dev = backlight_device_register("s5p_bl",&spi->dev,&lcd,&s5p_bl_ops);
+
+ lcd.bl_dev->props.max_brightness = 255;
+
+ dev_set_drvdata(&spi->dev,&lcd);
+
+ ams701ka_ldi_init();
+
+ printk("AMS701KA_PROBE success\n");
+
+ return ret;
+}
+
+#if 0 //def CONFIG_HAS_EARLYSUSPEND
+static void ams701ka_suspend(struct early_suspend *h)
+{
+ printk("AMS701KA SUSPEND!!!!!!!!\n");
+
+ ams701ka_panel_send_sequence(SEQ_STANDBY_ON);
+
+ ldi_enable = LDI_DISABLE;
+}
+
+static void ams701ka_resume(struct early_suspend *h)
+{
+ mdelay(200);
+ printk("AMS701KA RESUME START!!!!!!!!!!!\n");
+#if 0
+ ams701ka_panel_send_sequence(SEQ_STANDBY_OFF);
+ mdelay(100);
+#endif
+ //ams701ka_panel_send_sequence(GAMMA_SETTING);
+ ams701ka_panel_send_sequence(GAMMA22_SETTINGS[0]);
+
+ ams701ka_panel_send_sequence(SEQ_DISPLAY_ON);
+ ams701ka_panel_send_sequence(SEQ_SLEEP_OUT);
+ ams701ka_panel_send_sequence(SEQ_DISPLAY_ON);
+
+ printk("AMS701KA RESUME END!!!!!!!!!!!\n");
+
+ ldi_enable = LDI_ENABLE;
+}
+#else
+#ifdef CONFIG_PM
+static int ams701ka_suspend(struct spi_device *spi, pm_message_t mesg)
+{
+ printk("AMS701KA SUSPEND!!!!!!!!\n");
+ ams701ka_panel_send_sequence(SEQ_STANDBY_ON);
+
+ ldi_enable = LDI_DISABLE;
+
+ return 0;
+}
+
+static int ams701ka_resume(struct spi_device *spi)
+{
+ ams701ka_panel_send_sequence(SEQ_STANDBY_OFF);
+
+ mdelay(100);
+
+ ams701ka_panel_send_sequence(GAMMA_SETTING);
+ ams701ka_panel_send_sequence(SEQ_SLEEP_OUT);
+ ams701ka_panel_send_sequence(SEQ_DISPLAY_ON);
+
+ ldi_enable = LDI_ENABLE;
+
+ return 0;
+}
+#endif
+
+#endif
+
+static struct spi_driver ams701ka_driver = {
+ .driver = {
+ .name = "ams701ka",
+ .owner = THIS_MODULE,
+ },
+ .probe = ams701ka_probe,
+ .remove = __exit_p(ams701ka_remove),
+#ifdef CONFIG_HAS_WAKELOCK
+#if 0 //def CONFIG_HAS_EARLYSUSPEND
+ .early_suspend = {
+ .suspend = ams701ka_suspend,
+ .resume = ams701ka_resume,
+ .level = EARLY_SUSPEND_LEVEL_STOP_DRAWING,
+ },
+#endif
+#else
+#ifdef CONFIG_PM
+ .suspend = ams701ka_suspend,
+ .resume = ams701ka_resume,
+#endif
+#endif
+};
+
+static int __init ams701ka_init(void)
+{
+ int ret;
+
+ ret = spi_register_driver(&ams701ka_driver);
+
+#if 0 //def CONFIG_HAS_EARLYSUSPEND
+ register_early_suspend(&ams701ka_driver.early_suspend);
+#endif
+ return ret;
+}
+
+static void __exit ams701ka_exit(void)
+{
+ spi_unregister_driver(&ams701ka_driver);
+}
+
+
+module_init(ams701ka_init);
+module_exit(ams701ka_exit);
+
diff --git a/drivers/video/samsung/s3cfb_fimd6x.c b/drivers/video/samsung/s3cfb_fimd6x.c
new file mode 100644
index 0000000..bfe85af
--- /dev/null
+++ b/drivers/video/samsung/s3cfb_fimd6x.c
@@ -0,0 +1,746 @@
+/* linux/drivers/video/samsung/s3cfb_fimd6x.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Register interface file for Samsung Display Controller (FIMD) driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/fb.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <mach/map.h>
+#include <plat/clock.h>
+#include <plat/fb.h>
+#include <plat/regs-fb.h>
+
+#include "s3cfb.h"
+
+void s3cfb_check_line_count(struct s3cfb_global *ctrl)
+{
+ int timeout = 30 * 5300;
+ int i = 0;
+
+ do {
+ if (!(readl(ctrl->regs + S3C_VIDCON1) & 0x7ff0000))
+ break;
+ i++;
+ } while (i < timeout);
+
+ if (i == timeout) {
+ dev_err(ctrl->dev, "line count mismatch\n");
+ s3cfb_display_on(ctrl);
+ }
+}
+
+int s3cfb_set_output(struct s3cfb_global *ctrl)
+{
+ u32 cfg;
+
+ cfg = readl(ctrl->regs + S3C_VIDCON0);
+ cfg &= ~S3C_VIDCON0_VIDOUT_MASK;
+
+ if (ctrl->output == OUTPUT_RGB)
+ cfg |= S3C_VIDCON0_VIDOUT_RGB;
+ else if (ctrl->output == OUTPUT_ITU)
+ cfg |= S3C_VIDCON0_VIDOUT_ITU;
+ else if (ctrl->output == OUTPUT_I80LDI0)
+ cfg |= S3C_VIDCON0_VIDOUT_I80LDI0;
+ else if (ctrl->output == OUTPUT_I80LDI1)
+ cfg |= S3C_VIDCON0_VIDOUT_I80LDI1;
+ else if (ctrl->output == OUTPUT_WB_RGB)
+ cfg |= S3C_VIDCON0_VIDOUT_WB_RGB;
+ else if (ctrl->output == OUTPUT_WB_I80LDI0)
+ cfg |= S3C_VIDCON0_VIDOUT_WB_I80LDI0;
+ else if (ctrl->output == OUTPUT_WB_I80LDI1)
+ cfg |= S3C_VIDCON0_VIDOUT_WB_I80LDI1;
+ else {
+ dev_err(ctrl->dev, "invalid output type: %d\n", ctrl->output);
+ return -EINVAL;
+ }
+
+ writel(cfg, ctrl->regs + S3C_VIDCON0);
+
+ cfg = readl(ctrl->regs + S3C_VIDCON2);
+ cfg &= ~(S3C_VIDCON2_WB_MASK | S3C_VIDCON2_TVFORMATSEL_MASK | \
+ S3C_VIDCON2_TVFORMATSEL_YUV_MASK);
+
+ if (ctrl->output == OUTPUT_RGB)
+ cfg |= S3C_VIDCON2_WB_DISABLE;
+ else if (ctrl->output == OUTPUT_ITU)
+ cfg |= S3C_VIDCON2_WB_DISABLE;
+ else if (ctrl->output == OUTPUT_I80LDI0)
+ cfg |= S3C_VIDCON2_WB_DISABLE;
+ else if (ctrl->output == OUTPUT_I80LDI1)
+ cfg |= S3C_VIDCON2_WB_DISABLE;
+ else if (ctrl->output == OUTPUT_WB_RGB)
+ cfg |= (S3C_VIDCON2_WB_ENABLE | S3C_VIDCON2_TVFORMATSEL_SW | \
+ S3C_VIDCON2_TVFORMATSEL_YUV444);
+ else if (ctrl->output == OUTPUT_WB_I80LDI0)
+ cfg |= (S3C_VIDCON2_WB_ENABLE | S3C_VIDCON2_TVFORMATSEL_SW | \
+ S3C_VIDCON2_TVFORMATSEL_YUV444);
+ else if (ctrl->output == OUTPUT_WB_I80LDI1)
+ cfg |= (S3C_VIDCON2_WB_ENABLE | S3C_VIDCON2_TVFORMATSEL_SW | \
+ S3C_VIDCON2_TVFORMATSEL_YUV444);
+ else {
+ dev_err(ctrl->dev, "invalid output type: %d\n", ctrl->output);
+ return -EINVAL;
+ }
+
+ writel(cfg, ctrl->regs + S3C_VIDCON2);
+
+ return 0;
+}
+
+int s3cfb_set_display_mode(struct s3cfb_global *ctrl)
+{
+ u32 cfg;
+
+ cfg = readl(ctrl->regs + S3C_VIDCON0);
+ cfg &= ~S3C_VIDCON0_PNRMODE_MASK;
+ cfg |= (ctrl->rgb_mode << S3C_VIDCON0_PNRMODE_SHIFT);
+ writel(cfg, ctrl->regs + S3C_VIDCON0);
+
+ return 0;
+}
+
+int s3cfb_display_on(struct s3cfb_global *ctrl)
+{
+ u32 cfg;
+
+ cfg = readl(ctrl->regs + S3C_VIDCON0);
+ cfg |= (S3C_VIDCON0_ENVID_ENABLE | S3C_VIDCON0_ENVID_F_ENABLE);
+ writel(cfg, ctrl->regs + S3C_VIDCON0);
+
+ dev_dbg(ctrl->dev, "global display is on\n");
+
+ return 0;
+}
+
+int s3cfb_display_off(struct s3cfb_global *ctrl)
+{
+ u32 cfg;
+
+ cfg = readl(ctrl->regs + S3C_VIDCON0);
+ cfg &= ~S3C_VIDCON0_ENVID_ENABLE;
+ writel(cfg, ctrl->regs + S3C_VIDCON0);
+
+ cfg &= ~S3C_VIDCON0_ENVID_F_ENABLE;
+ writel(cfg, ctrl->regs + S3C_VIDCON0);
+
+ dev_dbg(ctrl->dev, "global display is off\n");
+
+ return 0;
+}
+
+int s3cfb_frame_off(struct s3cfb_global *ctrl)
+{
+ u32 cfg;
+
+ cfg = readl(ctrl->regs + S3C_VIDCON0);
+ cfg &= ~S3C_VIDCON0_ENVID_F_ENABLE;
+ writel(cfg, ctrl->regs + S3C_VIDCON0);
+
+ dev_dbg(ctrl->dev, "current frame display is off\n");
+
+ return 0;
+}
+
+void s3cfb_readjust_pixclock(struct s3cfb_global *ctrl, u32 src_clk, u32 div)
+{
+ struct s3c_platform_fb *pdata = to_fb_plat(ctrl->dev);
+ int i;
+ u32 pixclock;
+
+ pixclock = KHZ2PICOS(src_clk / 1000) * div;
+ dev_info(ctrl->dev, "pixclock adjusted from %d to %d\n",
+ ctrl->fb[0]->var.pixclock, pixclock);
+ for (i = 0; i < pdata->nr_wins; i++)
+ ctrl->fb[i]->var.pixclock = pixclock;
+}
+
+int s3cfb_set_clock(struct s3cfb_global *ctrl)
+{
+ struct s3c_platform_fb *pdata = to_fb_plat(ctrl->dev);
+ u32 cfg, maxclk, src_clk, vclk, div;
+
+ maxclk = 86 * 1000000;
+
+ /* fixed clock source: hclk */
+ cfg = readl(ctrl->regs + S3C_VIDCON0);
+ cfg &= ~(S3C_VIDCON0_CLKSEL_MASK | S3C_VIDCON0_CLKVALUP_MASK |
+ S3C_VIDCON0_VCLKEN_MASK | S3C_VIDCON0_CLKDIR_MASK |
+ S3C_VIDCON0_CLKVAL_F(-1));
+ cfg |= (S3C_VIDCON0_CLKVALUP_ALWAYS | S3C_VIDCON0_VCLKEN_NORMAL |
+ S3C_VIDCON0_CLKDIR_DIVIDED);
+
+
+ if (strcmp(pdata->clk_name, "sclk_fimd") == 0) {
+ cfg |= S3C_VIDCON0_CLKSEL_SCLK;
+ src_clk = clk_get_rate(ctrl->clock);
+ printk(KERN_INFO "FIMD src sclk = %d\n", src_clk);
+ } else {
+ cfg |= S3C_VIDCON0_CLKSEL_HCLK;
+ src_clk = ctrl->clock->parent->rate;
+ printk(KERN_INFO "FIMD src hclk = %d\n", src_clk);
+ }
+
+ vclk = ctrl->pixclock_hz;
+
+ if (vclk > maxclk) {
+ dev_info(ctrl->dev, "vclk(%d) should be smaller than %d\n",
+ vclk, maxclk);
+ /* vclk = maxclk; */
+ }
+
+ div = src_clk / vclk;
+ if (src_clk % vclk)
+ div++;
+
+ if ((src_clk/div) > maxclk)
+ dev_info(ctrl->dev, "vclk(%d) should be smaller than %d Hz\n",
+ src_clk/div, maxclk);
+
+ cfg |= S3C_VIDCON0_CLKVAL_F(div - 1);
+ writel(cfg, ctrl->regs + S3C_VIDCON0);
+
+ dev_dbg(ctrl->dev, "parent clock: %d, vclk: %d, vclk div: %d\n",
+ src_clk, vclk, div);
+
+ s3cfb_readjust_pixclock(ctrl, src_clk, div);
+ return 0;
+}
+
+int s3cfb_set_polarity(struct s3cfb_global *ctrl)
+{
+ struct s3cfb_lcd_polarity *pol;
+ u32 cfg;
+
+ pol = &ctrl->lcd->polarity;
+ cfg = 0;
+
+ if (pol->rise_vclk)
+ cfg |= S3C_VIDCON1_IVCLK_RISING_EDGE;
+
+ if (pol->inv_hsync)
+ cfg |= S3C_VIDCON1_IHSYNC_INVERT;
+
+ if (pol->inv_vsync)
+ cfg |= S3C_VIDCON1_IVSYNC_INVERT;
+
+ if (pol->inv_vden)
+ cfg |= S3C_VIDCON1_IVDEN_INVERT;
+
+ writel(cfg, ctrl->regs + S3C_VIDCON1);
+
+ return 0;
+}
+
+int s3cfb_set_timing(struct s3cfb_global *ctrl)
+{
+ struct s3cfb_lcd_timing *time;
+ u32 cfg;
+
+ time = &ctrl->lcd->timing;
+ cfg = 0;
+
+ cfg |= S3C_VIDTCON0_VBPDE(time->v_bpe - 1);
+ cfg |= S3C_VIDTCON0_VBPD(time->v_bp - 1);
+ cfg |= S3C_VIDTCON0_VFPD(time->v_fp - 1);
+ cfg |= S3C_VIDTCON0_VSPW(time->v_sw - 1);
+
+ writel(cfg, ctrl->regs + S3C_VIDTCON0);
+
+ cfg = 0;
+
+ cfg |= S3C_VIDTCON1_VFPDE(time->v_fpe - 1);
+ cfg |= S3C_VIDTCON1_HBPD(time->h_bp - 1);
+ cfg |= S3C_VIDTCON1_HFPD(time->h_fp - 1);
+ cfg |= S3C_VIDTCON1_HSPW(time->h_sw - 1);
+
+ writel(cfg, ctrl->regs + S3C_VIDTCON1);
+
+ return 0;
+}
+
+int s3cfb_set_lcd_size(struct s3cfb_global *ctrl)
+{
+ u32 cfg = 0;
+
+ cfg |= S3C_VIDTCON2_HOZVAL(ctrl->lcd->width - 1);
+ cfg |= S3C_VIDTCON2_LINEVAL(ctrl->lcd->height - 1);
+
+ writel(cfg, ctrl->regs + S3C_VIDTCON2);
+
+ return 0;
+}
+
+int s3cfb_set_global_interrupt(struct s3cfb_global *ctrl, int enable)
+{
+ u32 cfg = 0;
+
+ cfg = readl(ctrl->regs + S3C_VIDINTCON0);
+ cfg &= ~(S3C_VIDINTCON0_INTFRMEN_ENABLE | S3C_VIDINTCON0_INT_ENABLE);
+
+ if (enable) {
+ dev_dbg(ctrl->dev, "video interrupt is on\n");
+ cfg |= (S3C_VIDINTCON0_INTFRMEN_ENABLE |
+ S3C_VIDINTCON0_INT_ENABLE);
+ } else {
+ dev_dbg(ctrl->dev, "video interrupt is off\n");
+ cfg |= (S3C_VIDINTCON0_INTFRMEN_DISABLE |
+ S3C_VIDINTCON0_INT_DISABLE);
+ }
+
+ writel(cfg, ctrl->regs + S3C_VIDINTCON0);
+
+ return 0;
+}
+
+int s3cfb_set_vsync_interrupt(struct s3cfb_global *ctrl, int enable)
+{
+ u32 cfg = 0;
+
+ cfg = readl(ctrl->regs + S3C_VIDINTCON0);
+
+ if (enable) {
+ dev_dbg(ctrl->dev, "vsync interrupt is on\n");
+ cfg &= ~S3C_VIDINTCON0_FRAMESEL0_MASK;
+ cfg |= S3C_VIDINTCON0_INTFRMEN_ENABLE |
+ S3C_VIDINTCON0_FRAMESEL0_VSYNC;
+ } else {
+ dev_dbg(ctrl->dev, "vsync interrupt is off\n");
+ cfg &= ~S3C_VIDINTCON0_INTFRMEN_ENABLE;
+ }
+
+ writel(cfg, ctrl->regs + S3C_VIDINTCON0);
+
+ return 0;
+}
+
+int s3cfb_get_vsync_interrupt(struct s3cfb_global *ctrl)
+{
+ u32 cfg = 0;
+
+ cfg = readl(ctrl->regs + S3C_VIDINTCON0);
+ cfg &= S3C_VIDINTCON0_INTFRMEN_ENABLE;
+
+ if (cfg & S3C_VIDINTCON0_INTFRMEN_ENABLE) {
+ dev_dbg(ctrl->dev, "vsync interrupt is on\n");
+ return 1;
+ } else {
+ dev_dbg(ctrl->dev, "vsync interrupt is off\n");
+ return 0;
+ }
+}
+
+
+#ifdef CONFIG_FB_S3C_TRACE_UNDERRUN
+int s3cfb_set_fifo_interrupt(struct s3cfb_global *ctrl, int enable)
+{
+ u32 cfg = 0;
+
+ cfg = readl(ctrl->regs + S3C_VIDINTCON0);
+
+ cfg &= ~(S3C_VIDINTCON0_FIFOSEL_MASK | S3C_VIDINTCON0_FIFOLEVEL_MASK);
+ cfg |= (S3C_VIDINTCON0_FIFOSEL_ALL | S3C_VIDINTCON0_FIFOLEVEL_EMPTY);
+
+ if (enable) {
+ dev_dbg(ctrl->dev, "fifo interrupt is on\n");
+ cfg |= (S3C_VIDINTCON0_INTFIFO_ENABLE |
+ S3C_VIDINTCON0_INT_ENABLE);
+ } else {
+ dev_dbg(ctrl->dev, "fifo interrupt is off\n");
+ cfg &= ~(S3C_VIDINTCON0_INTFIFO_ENABLE |
+ S3C_VIDINTCON0_INT_ENABLE);
+ }
+
+ writel(cfg, ctrl->regs + S3C_VIDINTCON0);
+
+ return 0;
+}
+#endif
+
+int s3cfb_clear_interrupt(struct s3cfb_global *ctrl)
+{
+ u32 cfg = 0;
+
+ cfg = readl(ctrl->regs + S3C_VIDINTCON1);
+
+ if (cfg & S3C_VIDINTCON1_INTFIFOPEND)
+ dev_info(ctrl->dev, "fifo underrun occur\n");
+
+ cfg |= (S3C_VIDINTCON1_INTVPPEND | S3C_VIDINTCON1_INTI80PEND |
+ S3C_VIDINTCON1_INTFRMPEND | S3C_VIDINTCON1_INTFIFOPEND);
+
+ writel(cfg, ctrl->regs + S3C_VIDINTCON1);
+
+ return 0;
+}
+
+int s3cfb_channel_localpath_on(struct s3cfb_global *ctrl, int id)
+{
+ struct s3c_platform_fb *pdata = to_fb_plat(ctrl->dev);
+ u32 cfg;
+
+ if (pdata->hw_ver == 0x62) {
+ cfg = readl(ctrl->regs + S3C_WINSHMAP);
+ cfg |= S3C_WINSHMAP_LOCAL_ENABLE(id);
+ writel(cfg, ctrl->regs + S3C_WINSHMAP);
+ }
+
+ dev_dbg(ctrl->dev, "[fb%d] local path enabled\n", id);
+
+ return 0;
+}
+
+int s3cfb_channel_localpath_off(struct s3cfb_global *ctrl, int id)
+{
+ struct s3c_platform_fb *pdata = to_fb_plat(ctrl->dev);
+ u32 cfg;
+
+ if (pdata->hw_ver == 0x62) {
+ cfg = readl(ctrl->regs + S3C_WINSHMAP);
+ cfg &= ~S3C_WINSHMAP_LOCAL_DISABLE(id);
+ writel(cfg, ctrl->regs + S3C_WINSHMAP);
+ }
+
+ dev_dbg(ctrl->dev, "[fb%d] local path disabled\n", id);
+
+ return 0;
+}
+
+int s3cfb_window_on(struct s3cfb_global *ctrl, int id)
+{
+ struct s3c_platform_fb *pdata = to_fb_plat(ctrl->dev);
+ u32 cfg;
+
+ cfg = readl(ctrl->regs + S3C_WINCON(id));
+ cfg |= S3C_WINCON_ENWIN_ENABLE;
+ writel(cfg, ctrl->regs + S3C_WINCON(id));
+
+ if (pdata->hw_ver == 0x62) {
+ cfg = readl(ctrl->regs + S3C_WINSHMAP);
+ cfg |= S3C_WINSHMAP_CH_ENABLE(id);
+ writel(cfg, ctrl->regs + S3C_WINSHMAP);
+ }
+
+ dev_dbg(ctrl->dev, "[fb%d] turn on\n", id);
+
+ return 0;
+}
+
+int s3cfb_window_off(struct s3cfb_global *ctrl, int id)
+{
+ struct s3c_platform_fb *pdata = to_fb_plat(ctrl->dev);
+ u32 cfg;
+
+ cfg = readl(ctrl->regs + S3C_WINCON(id));
+ cfg &= ~(S3C_WINCON_ENWIN_ENABLE | S3C_WINCON_DATAPATH_MASK);
+ cfg |= S3C_WINCON_DATAPATH_DMA;
+ writel(cfg, ctrl->regs + S3C_WINCON(id));
+
+ if (pdata->hw_ver == 0x62) {
+ cfg = readl(ctrl->regs + S3C_WINSHMAP);
+ cfg &= ~S3C_WINSHMAP_CH_DISABLE(id);
+ writel(cfg, ctrl->regs + S3C_WINSHMAP);
+ }
+
+ dev_dbg(ctrl->dev, "[fb%d] turn off\n", id);
+
+ return 0;
+}
+
+int s3cfb_win_map_on(struct s3cfb_global *ctrl, int id, int color)
+{
+ u32 cfg = 0;
+
+ cfg |= S3C_WINMAP_ENABLE;
+ cfg |= S3C_WINMAP_COLOR(color);
+ writel(cfg, ctrl->regs + S3C_WINMAP(id));
+
+ dev_dbg(ctrl->dev, "[fb%d] win map on : 0x%08x\n", id, color);
+
+ return 0;
+}
+
+int s3cfb_win_map_off(struct s3cfb_global *ctrl, int id)
+{
+ writel(0, ctrl->regs + S3C_WINMAP(id));
+
+ dev_dbg(ctrl->dev, "[fb%d] win map off\n", id);
+
+ return 0;
+}
+
+int s3cfb_set_window_control(struct s3cfb_global *ctrl, int id)
+{
+ struct s3c_platform_fb *pdata = to_fb_plat(ctrl->dev);
+ struct fb_info *fb = ctrl->fb[id];
+ struct fb_var_screeninfo *var = &fb->var;
+ struct s3cfb_window *win = fb->par;
+ u32 cfg;
+
+ cfg = readl(ctrl->regs + S3C_WINCON(id));
+
+ cfg &= ~(S3C_WINCON_BITSWP_ENABLE | S3C_WINCON_BYTESWP_ENABLE |
+ S3C_WINCON_HAWSWP_ENABLE | S3C_WINCON_WSWP_ENABLE |
+ S3C_WINCON_BURSTLEN_MASK | S3C_WINCON_BPPMODE_MASK |
+ S3C_WINCON_INRGB_MASK | S3C_WINCON_DATAPATH_MASK);
+
+ if (win->path != DATA_PATH_DMA) {
+ dev_dbg(ctrl->dev, "[fb%d] data path: fifo\n", id);
+
+ cfg |= S3C_WINCON_DATAPATH_LOCAL;
+
+ if (win->path == DATA_PATH_FIFO) {
+ cfg |= S3C_WINCON_INRGB_RGB;
+ cfg |= S3C_WINCON_BPPMODE_24BPP_888;
+ } else if (win->path == DATA_PATH_IPC) {
+ cfg |= S3C_WINCON_INRGB_YUV;
+ cfg |= S3C_WINCON_BPPMODE_24BPP_888;
+ }
+
+ if (id == 1) {
+ cfg &= ~(S3C_WINCON1_LOCALSEL_MASK |
+ S3C_WINCON1_VP_ENABLE);
+
+ if (win->local_channel == 0) {
+ cfg |= S3C_WINCON1_LOCALSEL_FIMC1;
+ } else {
+ cfg |= (S3C_WINCON1_LOCALSEL_VP |
+ S3C_WINCON1_VP_ENABLE);
+ }
+ }
+ } else {
+ dev_dbg(ctrl->dev, "[fb%d] data path: dma\n", id);
+
+ cfg |= S3C_WINCON_DATAPATH_DMA;
+
+ if (fb->var.bits_per_pixel == 16 && pdata->swap & FB_SWAP_HWORD)
+ cfg |= S3C_WINCON_HAWSWP_ENABLE;
+
+ if (fb->var.bits_per_pixel == 32 && pdata->swap & FB_SWAP_WORD)
+ cfg |= S3C_WINCON_WSWP_ENABLE;
+
+ /* dma burst */
+ if (win->dma_burst == 4)
+ cfg |= S3C_WINCON_BURSTLEN_4WORD;
+ else if (win->dma_burst == 8)
+ cfg |= S3C_WINCON_BURSTLEN_8WORD;
+ else
+ cfg |= S3C_WINCON_BURSTLEN_16WORD;
+
+ /* bpp mode set */
+ switch (fb->var.bits_per_pixel) {
+ case 16:
+ if (var->transp.length == 1) {
+ dev_dbg(ctrl->dev,
+ "[fb%d] bpp mode: A1-R5-G5-B5\n", id);
+ cfg |= S3C_WINCON_BPPMODE_16BPP_A555;
+ } else if (var->transp.length == 4) {
+ dev_dbg(ctrl->dev,
+ "[fb%d] bpp mode: A4-R4-G4-B4\n", id);
+ cfg |= S3C_WINCON_BPPMODE_16BPP_A444;
+ } else {
+ dev_dbg(ctrl->dev,
+ "[fb%d] bpp mode: R5-G6-B5\n", id);
+ cfg |= S3C_WINCON_BPPMODE_16BPP_565;
+ }
+ break;
+
+ case 24: /* packed 24 bpp: nothing to do for 6.x fimd */
+ break;
+
+ case 32:
+ if (var->transp.length == 0) {
+ dev_dbg(ctrl->dev,
+ "[fb%d] bpp mode: R8-G8-B8\n", id);
+ cfg |= S3C_WINCON_BPPMODE_24BPP_888;
+ } else {
+ dev_dbg(ctrl->dev,
+ "[fb%d] bpp mode: A8-R8-G8-B8\n", id);
+ cfg |= S3C_WINCON_BPPMODE_32BPP;
+ }
+ break;
+ }
+ }
+
+ writel(cfg, ctrl->regs + S3C_WINCON(id));
+
+ return 0;
+}
+
+int s3cfb_set_buffer_address(struct s3cfb_global *ctrl, int id)
+{
+ struct fb_fix_screeninfo *fix = &ctrl->fb[id]->fix;
+ struct fb_var_screeninfo *var = &ctrl->fb[id]->var;
+ struct s3c_platform_fb *pdata = to_fb_plat(ctrl->dev);
+ dma_addr_t start_addr = 0, end_addr = 0;
+ u32 shw;
+
+ if (fix->smem_start) {
+ start_addr = fix->smem_start + (var->xres_virtual *
+ (var->bits_per_pixel / 8) * var->yoffset);
+
+ end_addr = start_addr + fix->line_length * var->yres;
+ }
+
+ if (pdata->hw_ver == 0x62) {
+ shw = readl(ctrl->regs + S3C_WINSHMAP);
+ shw |= S3C_WINSHMAP_PROTECT(id);
+ writel(shw, ctrl->regs + S3C_WINSHMAP);
+ }
+
+ writel(start_addr, ctrl->regs + S3C_VIDADDR_START0(id));
+ writel(end_addr, ctrl->regs + S3C_VIDADDR_END0(id));
+
+ if (pdata->hw_ver == 0x62) {
+ shw = readl(ctrl->regs + S3C_WINSHMAP);
+ shw &= ~(S3C_WINSHMAP_PROTECT(id));
+ writel(shw, ctrl->regs + S3C_WINSHMAP);
+ }
+
+ dev_dbg(ctrl->dev, "[fb%d] start_addr: 0x%08x, end_addr: 0x%08x\n",
+ id, start_addr, end_addr);
+
+ return 0;
+}
+
+int s3cfb_set_alpha_blending(struct s3cfb_global *ctrl, int id)
+{
+ struct s3cfb_window *win = ctrl->fb[id]->par;
+ struct s3cfb_alpha *alpha = &win->alpha;
+ u32 avalue = 0, cfg;
+
+ if (id == 0) {
+ dev_err(ctrl->dev, "[fb%d] does not support alpha blending\n",
+ id);
+ return -EINVAL;
+ }
+
+ cfg = readl(ctrl->regs + S3C_WINCON(id));
+ cfg &= ~(S3C_WINCON_BLD_MASK | S3C_WINCON_ALPHA_SEL_MASK);
+
+ if (alpha->mode == PIXEL_BLENDING) {
+ dev_dbg(ctrl->dev, "[fb%d] alpha mode: pixel blending\n", id);
+
+ /* fixing to DATA[31:24] for alpha value */
+ cfg |= (S3C_WINCON_BLD_PIXEL | S3C_WINCON_ALPHA1_SEL);
+ } else {
+ dev_dbg(ctrl->dev, "[fb%d] alpha mode: plane %d blending\n",
+ id, alpha->channel);
+
+ cfg |= S3C_WINCON_BLD_PLANE;
+
+ if (alpha->channel == 0) {
+ cfg |= S3C_WINCON_ALPHA0_SEL;
+ avalue = (alpha->value << S3C_VIDOSD_ALPHA0_SHIFT);
+ } else {
+ cfg |= S3C_WINCON_ALPHA1_SEL;
+ avalue = (alpha->value << S3C_VIDOSD_ALPHA1_SHIFT);
+ }
+ }
+
+ writel(cfg, ctrl->regs + S3C_WINCON(id));
+ writel(avalue, ctrl->regs + S3C_VIDOSD_C(id));
+
+ return 0;
+}
+
+int s3cfb_set_window_position(struct s3cfb_global *ctrl, int id)
+{
+ struct fb_var_screeninfo *var = &ctrl->fb[id]->var;
+ struct s3cfb_window *win = ctrl->fb[id]->par;
+ u32 cfg, shw;
+
+ shw = readl(ctrl->regs + S3C_WINSHMAP);
+ shw |= S3C_WINSHMAP_PROTECT(id);
+ writel(shw, ctrl->regs + S3C_WINSHMAP);
+
+ cfg = S3C_VIDOSD_LEFT_X(win->x) | S3C_VIDOSD_TOP_Y(win->y);
+ writel(cfg, ctrl->regs + S3C_VIDOSD_A(id));
+
+ cfg = S3C_VIDOSD_RIGHT_X(win->x + var->xres - 1) |
+ S3C_VIDOSD_BOTTOM_Y(win->y + var->yres - 1);
+
+ writel(cfg, ctrl->regs + S3C_VIDOSD_B(id));
+
+ shw = readl(ctrl->regs + S3C_WINSHMAP);
+ shw &= ~(S3C_WINSHMAP_PROTECT(id));
+ writel(shw, ctrl->regs + S3C_WINSHMAP);
+
+ dev_dbg(ctrl->dev, "[fb%d] offset: (%d, %d, %d, %d)\n", id,
+ win->x, win->y, win->x + var->xres - 1, win->y + var->yres - 1);
+
+ return 0;
+}
+
+int s3cfb_set_window_size(struct s3cfb_global *ctrl, int id)
+{
+ struct fb_var_screeninfo *var = &ctrl->fb[id]->var;
+ u32 cfg;
+
+ if (id > 2)
+ return 0;
+
+ cfg = S3C_VIDOSD_SIZE(var->xres * var->yres);
+
+ if (id == 0)
+ writel(cfg, ctrl->regs + S3C_VIDOSD_C(id));
+ else
+ writel(cfg, ctrl->regs + S3C_VIDOSD_D(id));
+
+ dev_dbg(ctrl->dev, "[fb%d] resolution: %d x %d\n", id,
+ var->xres, var->yres);
+
+ return 0;
+}
+
+int s3cfb_set_buffer_size(struct s3cfb_global *ctrl, int id)
+{
+ struct fb_var_screeninfo *var = &ctrl->fb[id]->var;
+ u32 offset = (var->xres_virtual - var->xres) * var->bits_per_pixel / 8;
+ u32 cfg = 0;
+
+ cfg = S3C_VIDADDR_PAGEWIDTH(var->xres * var->bits_per_pixel / 8);
+ cfg |= S3C_VIDADDR_OFFSIZE(offset);
+
+ writel(cfg, ctrl->regs + S3C_VIDADDR_SIZE(id));
+
+ return 0;
+}
+
+int s3cfb_set_chroma_key(struct s3cfb_global *ctrl, int id)
+{
+ struct s3cfb_window *win = ctrl->fb[id]->par;
+ struct s3cfb_chroma *chroma = &win->chroma;
+ u32 cfg = 0;
+
+ if (id == 0) {
+ dev_err(ctrl->dev, "[fb%d] does not support chroma key\n", id);
+ return -EINVAL;
+ }
+
+ cfg = (S3C_KEYCON0_KEYBLEN_DISABLE | S3C_KEYCON0_DIRCON_MATCH_FG);
+
+ if (chroma->enabled)
+ cfg |= S3C_KEYCON0_KEY_ENABLE;
+
+ writel(cfg, ctrl->regs + S3C_KEYCON(id));
+
+ cfg = S3C_KEYCON1_COLVAL(chroma->key);
+ writel(cfg, ctrl->regs + S3C_KEYVAL(id));
+
+ dev_dbg(ctrl->dev, "[fb%d] chroma key: 0x%08x, %s\n", id, cfg,
+ chroma->enabled ? "enabled" : "disabled");
+
+ return 0;
+}
+
diff --git a/drivers/video/samsung/s3cfb_ht101hd1.c b/drivers/video/samsung/s3cfb_ht101hd1.c
new file mode 100644
index 0000000..0a4e760
--- /dev/null
+++ b/drivers/video/samsung/s3cfb_ht101hd1.c
@@ -0,0 +1,46 @@
+/* linux/drivers/video/samsung/s3cfb_ht101hd1.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * HT101HD1-100 XWVGA Landscape LCD module driver for the SMDK
+ *
+ * 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 "s3cfb.h"
+
+static struct s3cfb_lcd ht101hd1 = {
+ .width = 1376,
+ .height = 768,
+ .bpp = 24,
+ .freq = 60,
+
+ .timing = {
+ .h_fp = 49,
+ .h_bp = 17,
+ .h_sw = 33,
+ .v_fp = 4,
+ .v_fpe = 1,
+ .v_bp = 15,
+ .v_bpe = 1,
+ .v_sw = 6,
+ },
+
+ .polarity = {
+ .rise_vclk = 0,
+ .inv_hsync = 1,
+ .inv_vsync = 1,
+ .inv_vden = 0,
+ },
+};
+
+/* name should be fixed as 's3cfb_set_lcd_info' */
+void s3cfb_set_lcd_info(struct s3cfb_global *ctrl)
+{
+ ht101hd1.init_ldi = NULL;
+ ctrl->lcd = &ht101hd1;
+}
+
diff --git a/drivers/video/samsung/s3cfb_ielcd.c b/drivers/video/samsung/s3cfb_ielcd.c
new file mode 100644
index 0000000..9c17459
--- /dev/null
+++ b/drivers/video/samsung/s3cfb_ielcd.c
@@ -0,0 +1,186 @@
+/* linux/drivers/video/samsung/s3cfb_mdnie.c
+ *
+ * Register interface file for Samsung IELCD driver
+ *
+ * Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.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/kernel.h>
+#include <linux/errno.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/poll.h>
+#include <linux/wait.h>
+#include <linux/fs.h>
+#include <linux/irq.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/ctype.h>
+#include <linux/miscdevice.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+
+
+#include <asm/io.h>
+#include <mach/map.h>
+#include <plat/clock.h>
+#include <plat/fb.h>
+#include <plat/regs-fb.h>
+#include <plat/pm.h>
+
+#include "s3cfb.h"
+#include "s3cfb_mdnie.h"
+#include "s3cfb_ielcd.h"
+
+
+
+static struct resource *s3c_ielcd_mem;
+static void __iomem *s3c_ielcd_base;
+
+
+#define s3c_ielcd_readl(addr) __raw_readl((s3c_ielcd_base + addr))
+#define s3c_ielcd_writel(val,addr) __raw_writel(val,(s3c_ielcd_base + addr))
+
+
+static struct s3cfb_global ielcd_fb;
+static struct s3cfb_global *ielcd_fbdev;
+
+
+
+static char banner[] __initdata = KERN_INFO "S3C IELCD Driver, (c) 2010 Samsung Electronics\n";
+
+int s3c_ielcd_hw_init(void)
+{
+ printk("IELCD INIT ..........\n");
+
+ printk(banner);
+
+ s3c_ielcd_mem = request_mem_region(S3C_IELCD_PHY_BASE,S3C_IELCD_MAP_SIZE,"ielcd");
+ if(s3c_ielcd_mem == NULL) {
+ printk(KERN_ERR "IELCD: failed to reserved memory region\n");
+ return -ENOENT;
+ }
+
+ s3c_ielcd_base = ioremap(S3C_IELCD_PHY_BASE,S3C_IELCD_MAP_SIZE);
+ if(s3c_ielcd_base == NULL) {
+ printk(KERN_ERR "IELCD failed ioremap\n");
+ return -ENOENT;
+ }
+
+ printk("IELCD INIT SUCCESS Addr : 0x%p\n",s3c_ielcd_base);
+
+ ielcd_fbdev = &ielcd_fb;
+
+ //s3c_ielcd_writel(3,S3C_IELCD_DULACON);
+
+ return 0;
+
+}
+
+
+int s3c_ielcd_logic_start(void)
+{
+ s3c_ielcd_writel(S3C_IELCD_MAGIC_KEY,S3C_IELCD_MODE);
+ return 0;
+}
+
+int s3c_ielcd_logic_stop(void)
+{
+ s3c_ielcd_writel(0,S3C_IELCD_MODE);
+ return 0;
+}
+
+
+int s3c_ielcd_start(void)
+{
+ unsigned int con;
+
+ con = s3c_ielcd_readl(S3C_IELCD_VIDCON0);
+ con |= (S3C_VIDCON0_ENVID_ENABLE| S3C_VIDCON0_ENVID_F_ENABLE);
+ s3c_ielcd_writel(con,S3C_IELCD_VIDCON0);
+
+ return 0;
+}
+
+int s3c_ielcd_stop(void)
+{
+ unsigned int con;
+
+ con = s3c_ielcd_readl(S3C_IELCD_VIDCON0);
+ //con &= ~(S3C_VIDCON0_ENVID_ENABLE| S3C_VIDCON0_ENVID_F_ENABLE);
+ con &= ~(S3C_VIDCON0_ENVID_F_ENABLE);
+ s3c_ielcd_writel(con,S3C_IELCD_VIDCON0);
+
+ return 0;
+}
+
+
+int s3c_ielcd_init_global(struct s3cfb_global *ctrl)
+{
+ unsigned int cfg;
+
+ *ielcd_fbdev = *ctrl;
+ ielcd_fbdev->regs = s3c_ielcd_base;
+
+
+
+ s3cfb_set_polarity(ielcd_fbdev);
+ s3cfb_set_timing(ielcd_fbdev);
+ s3cfb_set_lcd_size(ielcd_fbdev);
+
+ // dithmode
+
+ s3c_ielcd_writel(0x0,S3C_IELCD_DITHMODE);
+
+ // clk mode and mode
+ // read from lcd vid con
+ cfg = readl(ctrl->regs + S3C_VIDCON0);
+ cfg &= ~((7 << 26) | (1 << 5) | (1 << 0));
+ cfg |= (0 << 26| 0 << 5);
+
+ s3c_ielcd_writel(cfg,S3C_IELCD_VIDCON0);
+
+
+ s3c_ielcd_writel(1<<5,S3C_IELCD_VIDINTCON0);
+
+ s3cfb_set_vsync_interrupt(ielcd_fbdev, 0);
+ s3cfb_set_global_interrupt(ielcd_fbdev, 0);
+
+ //s3cfb_display_on(ielcd_fbdev);
+
+
+ s3c_ielcd_writel(0,S3C_IELCD_VIDOSD0A);
+ s3c_ielcd_writel((ctrl->lcd->width - 1) << 11 | (ctrl->lcd->height - 1), S3C_IELCD_VIDOSD0B);
+ s3c_ielcd_writel((ctrl->lcd->width * ctrl->lcd->height ), S3C_IELCD_VIDOSD0C);
+
+ cfg = S3C_WINCON_DATAPATH_LOCAL|S3C_WINCON_BPPMODE_32BPP;
+ cfg |= S3C_WINCON_INRGB_RGB;
+
+
+ s3c_ielcd_writel(cfg,S3C_IELCD_WINCON0);
+
+ s3cfb_window_on(ielcd_fbdev,0);
+ return 0;
+}
+
+
+int s3c_ielcd_set_clock(struct s3cfb_global *ctrl)
+{
+ *ielcd_fbdev = *ctrl;
+ ielcd_fbdev->regs = s3c_ielcd_base;
+ s3cfb_set_clock(ctrl);
+ //clk_enable(ielcd_clock);
+ return 0;
+}
+
+
+//module_init(s3c_ielcd_hw_init);
+
+
diff --git a/drivers/video/samsung/s3cfb_ielcd.h b/drivers/video/samsung/s3cfb_ielcd.h
new file mode 100644
index 0000000..a380da4
--- /dev/null
+++ b/drivers/video/samsung/s3cfb_ielcd.h
@@ -0,0 +1,100 @@
+
+/* linux/drivers/video/samsung/s3cfb_ielcd.h
+ *
+ * Header file for Samsung (IELCD) driver
+ *
+ * Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.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 _S3CFB_IELCD_H
+#define _S3CFB_IELCD_H
+
+
+#define S3C_IELCD_MAGIC_KEY 0x2ff47
+
+#define S3C_IELCD_PHY_BASE 0xF8200000
+#define S3C_IELCD_MAP_SIZE 0x00008000
+
+/*
+ * Register Map
+*/
+#define S3C_IELCD_VIDCON0 (0x0000)
+#define S3C_IELCD_VIDCON1 (0x0004)
+#define S3C_IELCD_VIDCON2 (0x0008)
+#define S3C_IELCD_VIDCON3 (0x000C)
+
+#define S3C_IELCD_VIDTCON0 (0x0010)
+#define S3C_IELCD_VIDTCON1 (0x0014)
+#define S3C_IELCD_VIDTCON2 (0x0018)
+#define S3C_IELCD_VIDTCON3 (0x001C)
+
+#define S3C_IELCD_WINCON0 (0x0020)
+
+#define S3C_IELCD_SHADOWCON (0x0034)
+
+#define S3C_IELCD_VIDOSD0A (0x0040)
+#define S3C_IELCD_VIDOSD0B (0x0044)
+#define S3C_IELCD_VIDOSD0C (0x0048)
+
+#define S3C_IELCD_VIDINTCON0 (0x0130)
+#define S3C_IELCD_VIDINTCON1 (0x0134)
+
+
+#define S3C_IELCD_DITHMODE (0x0170)
+
+#define S3C_IELCD_WIN0MAP (0x0180)
+
+#define S3C_IELCD_WPALCON_H (0x019C)
+#define S3C_IELCD_WPALCON_L (0x01A0)
+
+#define S3C_IELCD_TRIGCON (0x01A4)
+
+#define S3C_IELCD_ITUIFCON (0x01A8)
+
+#define S3C_IELCD_I80IFCONA0 (0x01B0)
+#define S3C_IELCD_I80IFCONA1 (0x01B4)
+#define S3C_IELCD_I80IFCONB0 (0x01B8)
+#define S3C_IELCD_I80IFCONB1 (0x01BC)
+
+#define S3C_IELCD_CMDCON0 (0x01D0)
+#define S3C_IELCD_CMDCON1 (0x01D4)
+
+
+#define S3C_IELCD_SIFCCON0 (0x01E8)
+#define S3C_IELCD_SIFCCON1 (0x01E4)
+#define S3C_IELCD_SIFCCON2 (0x01E8)
+
+
+#define S3C_IELCD_MODE (0x0278)
+#define S3C_IELCD_DULACON (0x027c)
+
+#define S3C_IELCD_LDICMD0 (0x0280)
+#define S3C_IELCD_LDICMD1 (0x0284)
+#define S3C_IELCD_LDICMD2 (0x0288)
+#define S3C_IELCD_LDICMD3 (0x028C)
+#define S3C_IELCD_LDICMD4 (0x0290)
+#define S3C_IELCD_LDICMD5 (0x0294)
+#define S3C_IELCD_LDICMD6 (0x0298)
+#define S3C_IELCD_LDICMD7 (0x029C)
+#define S3C_IELCD_LDICMD8 (0x02A0)
+#define S3C_IELCD_LDICMD9 (0x02A4)
+#define S3C_IELCD_LDICMD10 (0x02A8)
+#define S3C_IELCD_LDICMD11 (0x02AC)
+
+int s3c_ielcd_hw_init(void);
+int s3c_ielcd_logic_start(void);
+int s3c_ielcd_logic_stop(void);
+int s3c_ielcd_start(void);
+int s3c_ielcd_stop(void);
+
+
+int s3c_ielcd_init_global(struct s3cfb_global *ctrl);
+int s3c_ielcd_set_clock(struct s3cfb_global *ctrl);
+//int s3c_ielcd_clk_enable(struct s3cfb_global *ctrl);
+
+#endif
diff --git a/drivers/video/samsung/s3cfb_lte480wv.c b/drivers/video/samsung/s3cfb_lte480wv.c
new file mode 100644
index 0000000..9967feb
--- /dev/null
+++ b/drivers/video/samsung/s3cfb_lte480wv.c
@@ -0,0 +1,46 @@
+/* linux/drivers/video/samsung/s3cfb_lte480wv.c
+ *
+ * Samsung LTE480 4.8" WVGA Display Panel Support
+ *
+ * Jinsung Yang, Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.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 "s3cfb.h"
+
+static struct s3cfb_lcd lte480wv = {
+ .width = 800,
+ .height = 480,
+ .bpp = 32,
+ .freq = 60,
+
+ .timing = {
+ .h_fp = 8,
+ .h_bp = 13,
+ .h_sw = 3,
+ .v_fp = 5,
+ .v_fpe = 1,
+ .v_bp = 7,
+ .v_bpe = 1,
+ .v_sw = 1,
+ },
+
+ .polarity = {
+ .rise_vclk = 0,
+ .inv_hsync = 1,
+ .inv_vsync = 1,
+ .inv_vden = 0,
+ },
+};
+
+/* name should be fixed as 's3cfb_set_lcd_info' */
+void s3cfb_set_lcd_info(struct s3cfb_global *ctrl)
+{
+ lte480wv.init_ldi = NULL;
+ ctrl->lcd = &lte480wv;
+}
+
diff --git a/drivers/video/samsung/s3cfb_lvds.c b/drivers/video/samsung/s3cfb_lvds.c
new file mode 100644
index 0000000..e3a96db
--- /dev/null
+++ b/drivers/video/samsung/s3cfb_lvds.c
@@ -0,0 +1,199 @@
+/* linux/drivers/video/samsung/s3cfb_lvds.c
+ *
+ * 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 "s3cfb.h"
+
+#if 0
+static struct s3cfb_lcd lvds = {
+ .width = 1024,
+ .height = 600,
+ .bpp = 32,
+ .freq = 60,
+
+ .timing = {
+ .h_fp = 79,
+ .h_bp = 200,
+ .h_sw = 40,
+ .v_fp = 10,
+ .v_fpe = 1,
+ .v_bp = 11,
+ .v_bpe = 1,
+ .v_sw = 10,
+
+ },
+
+ .polarity = {
+ .rise_vclk = 0,
+ .inv_hsync = 1,
+ .inv_vsync = 1,
+ .inv_vden = 0,
+ },
+}
+/* name should be fixed as 's3cfb_set_lcd_info' */
+void s3cfb_set_lcd_info_lvds(struct s3cfb_global *ctrl)
+{
+ lvds.init_ldi = NULL;
+ ctrl->lcd = &lvds;
+}
+#endif
+
+//#define MDNIE_TUNING
+
+#ifdef MDNIE_TUNING
+
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <asm/uaccess.h>
+
+#define MDNIE_TUNING_TUNEFILE_PATH "/sdcard/sd/p1/mdnie_tune"
+#define TUNE_TEXT_MAX_LINES 100
+#define TUNE_MAX_VALUES 200
+
+unsigned short *test[1];
+EXPORT_SYMBOL(test);
+
+extern void mDNIe_txtbuf_to_parsing(void);
+
+static int parse_from_text(char * src, int len, unsigned short * output)
+{
+ int i,count, ret;
+ int out_index=0;
+ char * str_line[TUNE_TEXT_MAX_LINES];
+ char * sstart;
+ char * c;
+ unsigned int data1, data2;
+
+ c = src;
+ count = 0;
+ sstart = c;
+ for(i=0; i<len; i++,c++)
+ {
+ char a = *c;
+ if(a=='\r' || a=='\n')
+ {
+ if(c > sstart)
+ {
+ str_line[count] = sstart;
+ count++;
+ }
+ *c='\0';
+ sstart = c+1;
+ }
+ }
+ if(c > sstart)
+ {
+ str_line[count] = sstart;
+ count++;
+ }
+
+ printk("<MDNIE> %s lines:%d\n", __func__, count);
+
+ for(i=0; i<count; i++)
+ {
+ printk("line:%d, string:%s[end]\n", i, str_line[i]);
+ ret = sscanf(str_line[i], "0x%x,0x%x\n", &data1, &data2);
+ printk("line:%d, num:%d, d1:0x%04x, d2:0x%04x\n", i, ret, data1, data2);
+ if(ret == 2)
+ {
+ output[out_index++] = data1;
+ output[out_index++] = data2;
+ }
+ }
+
+ output[out_index] = 0xffff; // END_SEQ
+
+ return out_index;
+
+}
+
+int mDNIe_tuning_load_from_file(void)
+{
+ struct file *filp;
+ char *dp;
+ long l;
+ loff_t pos;
+ int i;
+ int ret;
+
+ printk("<MDNIE> %s start.\n", __func__);
+
+ mm_segment_t fs = get_fs();
+
+ set_fs(get_ds());
+
+ filp = filp_open(MDNIE_TUNING_TUNEFILE_PATH, O_RDONLY, 0);
+
+ if(IS_ERR(filp))
+ {
+ printk("<MDNIE> file open error:%d\n", filp);
+ return -1;
+ }
+
+ l = filp->f_path.dentry->d_inode->i_size;
+ printk("<MDNIE> l = %ld\n", l);
+
+ //dp = kmalloc(l, GFP_KERNEL);
+ dp = kmalloc(l+10, GFP_KERNEL); // add cushion
+ if(dp == NULL)
+ {
+ printk("<MDNIE> Out of Memory\n");
+ filp_close(filp, current->files);
+ return -1;
+ }
+ pos = 0;
+ memset(dp, 0, l);
+ ret = vfs_read(filp, (char __user *)dp, l, &pos);
+
+ if(ret != l)
+ {
+ printk("<MDNIE> Failed to read file ret = %d\n", ret);
+ kfree(dp);
+ filp_close(filp, current->files);
+ return -1;
+ }
+
+ filp_close(filp, current->files);
+
+ set_fs(fs);
+
+ for(i=0; i<l; i++)
+ {
+ printk("%x ", dp[i]);
+ }
+ printk("\n");
+
+ test[0] = kmalloc(TUNE_MAX_VALUES*sizeof(short), GFP_KERNEL);
+ if(test[0] == NULL)
+ {
+ printk("<MDNIE> Out of Memory\n");
+ kfree(dp);
+ return -1;
+ }
+
+ ret = parse_from_text(dp, l, test[0]);
+ printk("<MDNIE> parsing data:%d\n", ret);
+
+ if(ret > 0)
+ {
+ printk("<MDNIE> Call mDNIe_txtbuf_to_parsing\n");
+ mDNIe_txtbuf_to_parsing();
+ }
+
+ kfree(test[0]);
+ kfree(dp);
+
+ return ret;
+// printk("<=PCAM=> sr200pc10_regs_table 0x%x, %ld\n", (unsigned int)dp, l);
+}
+EXPORT_SYMBOL(mDNIe_tuning_load_from_file);
+
+
+#endif
+
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/video/samsung/s3cfb_mdnie.c b/drivers/video/samsung/s3cfb_mdnie.c
new file mode 100644
index 0000000..eaca0d3
--- /dev/null
+++ b/drivers/video/samsung/s3cfb_mdnie.c
@@ -0,0 +1,1264 @@
+/* linux/drivers/video/samsung/s3cfb_mdnie.c
+ *
+ * Register interface file for Samsung MDNIE driver
+ *
+ * Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.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/kernel.h>
+#include <linux/errno.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/poll.h>
+#include <linux/wait.h>
+#include <linux/fs.h>
+#include <linux/irq.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/ctype.h>
+#include <linux/miscdevice.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/fb.h>
+
+
+#include <asm/io.h>
+#include <mach/map.h>
+#include <plat/clock.h>
+#include <plat/fb.h>
+#include <plat/regs-fb.h>
+#include <plat/pm.h>
+#include "s3cfb.h"
+#include "s3cfb_mdnie.h"
+#include "s3cfb_ielcd.h"
+
+
+
+static struct resource *s3c_mdnie_mem;
+static void __iomem *s3c_mdnie_base;
+
+#define C110_MDNIE_ADDR 0xfae00000
+
+#define s3c_mdnie_readw(addr) __raw_readw((s3c_mdnie_base + addr))
+#define s3c_mdnie_readl(addr) __raw_readl((s3c_mdnie_base + addr))
+#define s3c_mdnie_writel(val,addr) __raw_writel(val,(s3c_mdnie_base + addr))
+
+
+static char banner[] __initdata = KERN_INFO "S3C MDNIE Driver, (c) 2010 Samsung Electronics\n";
+
+struct clk *mdnie_clock;
+
+#define DEBUG_MDNIE
+
+//#define MDNIE_TUNING
+//#define MDNIE_TUNINGMODE_FOR_BACKLIGHT
+
+/*********** for debug **********************************************************/
+#if 0
+#define gprintk(fmt, x... ) printk( "%s(%d): " fmt, __FUNCTION__ ,__LINE__, ## x)
+#else
+#define gprintk(x...) do { } while (0)
+#endif
+/*******************************************************************************/
+
+
+#define END_SEQ 0xffff
+
+#define TRUE 1
+#define FALSE 0
+
+
+typedef struct {
+ u16 addr;
+ u16 data;
+} mDNIe_data_type;
+
+typedef enum
+{
+ mDNIe_UI_MODE,
+ mDNIe_VIDEO_MODE,
+ mDNIe_VIDEO_WARM_MODE,
+ mDNIe_VIDEO_COLD_MODE,
+ mDNIe_CAMERA_MODE,
+ mDNIe_NAVI
+}Lcd_mDNIe_UI;
+
+struct class *mdnieset_ui_class;
+struct device *switch_mdnieset_ui_dev;
+struct class *mdnieset_outdoor_class;
+struct device *switch_mdnieset_outdoor_dev;
+
+
+mDNIe_data_type mDNIe_Video[]=
+{
+ 0x0084, 0x0040,
+ 0x0090, 0x0000,
+ 0x0094, 0x0fff,
+ 0x0098, 0x005c,
+ 0x009C, 0x0ff0,
+ 0x00AC, 0x00E0,
+ 0x00B4, 0x0001,
+ 0x00C0, 0x0400,
+ 0x00C4, 0x7200,
+ 0x00C8, 0x008d,
+ 0x00D0, 0x0100,
+ END_SEQ, 0x0000,
+};
+
+mDNIe_data_type mDNIe_Camera[]=
+{
+ 0x0084, 0x0040,
+ 0x0090, 0x0000,
+ 0x0094, 0x0FFF,
+ 0x0098, 0x005C,
+ 0x009C, 0x0010,
+ 0x00AC, 0x0000,
+ 0x00B4, 0x03FF,
+ 0x00C0, 0x0400,
+ 0x00C4, 0x7200,
+ 0x00C8, 0x008D,
+ 0x00D0, 0x00C0,
+ END_SEQ, 0x0000,
+};
+
+mDNIe_data_type mDNIe_Camera_Outdoor_Mode[]=
+{
+ 0x0084, 0x0090,
+ 0x0090, 0x0000,
+ 0x0094, 0x0FFF,
+ 0x0098, 0x005C,
+ 0x009C, 0x0010,
+ 0x00AC, 0x0000,
+ 0x00B4, 0x03FF,
+ 0x0100, 0x6050,
+ 0x0198, 0x0001,
+ 0x0194, 0x0011,
+ END_SEQ, 0x0000,
+};
+
+mDNIe_data_type mDNIe_UI[]=
+{
+//bypass
+ 0x0084, 0x0000,
+ 0x0090, 0x0000,
+ 0x0094, 0x0fff,
+ 0x0098, 0x005c,
+ 0x009C, 0x0010,
+ 0x00AC, 0x0000,
+ 0x00B4, 0x03ff,
+/*
+ //start
+ 0x0084,0x0040, // HDTR
+ 0x0090,0x0000, // DeConTh off
+ 0x0094,0x0FFF, // DirTh off
+ 0x0098,0x005C, // SimplTh off
+ 0x009C,0x0FFA, // 0x0012, DE CEonoff CEdark AMOLED ---- 0000 000|0| 000|0
+ 0x00AC,0x0500, // 0x0000, skinoff CSoff
+ 0x00B4,0x0001, // 0x03FF, DETh ---- --00 0000 0000
+ 0x00C0,0x0400, // PCC skin
+ 0x00C4,0x6A74,
+ 0x00C8,0x0099,
+ 0x00D0,0x01B6,
+ 0x0084,0x0040,
+ //0x0084,0x0000, // HDTR
+ //0x0100,0x8080,
+ //end
+*/
+ END_SEQ, 0x0000,
+};
+
+mDNIe_data_type mDNIe_Video_Warm[]=
+{
+ 0x0084, 0x0020,
+ 0x0090, 0x0000,
+ 0x0094, 0x0fff,
+ 0x0098, 0x005C,
+ 0x009C, 0x0FF0,
+ 0x00AC, 0x0000,
+ 0x00B4, 0x0001,
+ 0x0120, 0x0028,
+ 0x0138, 0x7600,
+ 0x0140, 0x0090,
+ END_SEQ, 0x0000,
+};
+
+mDNIe_data_type mDNIe_Video_WO_Mode[]=
+{
+ 0x0084, 0x0090,
+ 0x0090, 0x0000,
+ 0x0094, 0x0fff,
+ 0x0098, 0x005C,
+ 0x009C, 0x0ff0,
+ 0x00AC, 0x0000,
+ 0x00B4, 0x0001,
+ 0x0100, 0x6050,
+ 0x0198, 0x0001,
+ 0x0194, 0x0011,
+ END_SEQ, 0x0000,
+};
+
+mDNIe_data_type mDNIe_Video_Cold[]=
+{
+ 0x0084, 0x0020,
+ 0x0090, 0x0000,
+ 0x0094, 0x0fff,
+ 0x0098, 0x005c,
+ 0x009C, 0x0ff0,
+ 0x00AC, 0x0000,
+ 0x00B4, 0x0001,
+ 0x0120, 0x0064,
+ 0x0140, 0x9400,
+ 0x0148, 0x006D,
+ END_SEQ, 0x0000,
+};
+
+mDNIe_data_type mDNIe_Video_CO_Mode[]=
+{
+ 0x0084, 0x0090,
+ 0x0090, 0x0000,
+ 0x0094, 0x0fff,
+ 0x0098, 0x005C,
+ 0x009C, 0x0ff0,
+ 0x00AC, 0x0000,
+ 0x00B4, 0x0001,
+ 0x0100, 0x6050,
+ 0x0198, 0x0001,
+ 0x0194, 0x0011,
+ END_SEQ, 0x0000,
+
+};
+
+mDNIe_data_type mDNIe_Outdoor_Mode[]=
+{
+ 0x0084, 0x0090,
+ 0x0090, 0x0000,
+ 0x0094, 0x0fff,
+ 0x0098, 0x005C,
+ 0x009C, 0x0ff0,
+ 0x00AC, 0x0000,
+ 0x00B4, 0x0001,
+ 0x0100, 0x6050,
+ 0x0198, 0x0001,
+ 0x0194, 0x0011,
+ END_SEQ, 0x0000,
+
+};
+
+
+Lcd_mDNIe_UI current_mDNIe_UI = mDNIe_UI_MODE; // mDNIe Set Status Checking Value.
+u8 current_mDNIe_OutDoor_OnOff = FALSE;
+
+int mDNIe_Tuning_Mode = FALSE;
+
+#ifdef MDNIE_TUNINGMODE_FOR_BACKLIGHT
+u16 mDNIe_data_ui[50] = {0};
+u16 mDNIe_data_300cd_level1[50] = {0};
+u16 mDNIe_data_300cd_level2[50] = {0};
+
+u16 mDNIe_data_ui_down[50] = {0};
+
+
+
+u16 *pmDNIe_Gamma_set[] = {
+ mDNIe_data_ui,//0
+ mDNIe_data_300cd_level1,//01
+ mDNIe_data_300cd_level2,//02
+ mDNIe_data_ui_down,
+ };
+
+int level_outdoor = 0;
+
+#endif
+
+
+#ifdef MDNIE_TUNING
+u16 light_step = 0;
+u16 saturation_step = 0;
+u16 cs_step = 0;
+
+u16 adc_level_formDNIe[6] = {0};
+u16 mDNIe_data_level0[100] = {0};
+u16 mDNIe_data_level1[100] = {0};
+u16 mDNIe_data_level2[100] = {0};
+u16 mDNIe_data_level3[100] = {0};
+u16 mDNIe_data_level4[100] = {0};
+u16 mDNIe_data_level5[100] = {0};
+
+int mDNIe_data_level0_cnt = 0;
+int mDNIe_data_level1_cnt = 0;
+int mDNIe_data_level2_cnt = 0;
+int mDNIe_data_level3_cnt = 0;
+int mDNIe_data_level4_cnt = 0;
+int mDNIe_data_level5_cnt = 0;
+
+
+u16 mDNIe_data[200] = {0};
+
+
+extern unsigned short *test[1];
+int mdnie_tuning_load = 0;
+EXPORT_SYMBOL(mdnie_tuning_load);
+
+
+void mDNIe_txtbuf_to_parsing_for_lightsensor(void)
+{
+ int i = 0;
+ int cnt;
+
+ light_step = test[0][0];
+ saturation_step = test[0][1];
+ cs_step = test[0][2];
+
+/*1 level */
+ adc_level_formDNIe[0] = test[0][3];
+
+ for(i=0; (test[0][i+4] != END_SEQ); i++)
+ {
+ if(test[0][i+4] != END_SEQ)
+ mDNIe_data_level0[i] = test[0][i+4];
+ }
+ mDNIe_data_level0[i] = END_SEQ;
+ mDNIe_data_level0_cnt = i;
+ cnt = i+5;
+
+/*2 level */
+ adc_level_formDNIe[1] = test[0][cnt];
+ cnt++;
+ for(i=0; (test[0][cnt+i] != END_SEQ); i++)
+ {
+ if(test[0][cnt+i] != END_SEQ)
+ mDNIe_data_level1[i] = test[0][cnt+i];
+ }
+ mDNIe_data_level1[i] = END_SEQ;
+ mDNIe_data_level1_cnt = i;
+ cnt += i+1;
+
+/*3 level */
+ adc_level_formDNIe[2] = test[0][cnt];
+ cnt++;
+ for(i=0; (test[0][cnt+i] != END_SEQ); i++)
+ {
+ if(test[0][cnt+i] != END_SEQ)
+ mDNIe_data_level2[i] = test[0][cnt+i];
+ }
+ mDNIe_data_level2[i] = END_SEQ;
+ mDNIe_data_level2_cnt = i;
+ cnt += i+1;
+
+/*4 level */
+ adc_level_formDNIe[3] = test[0][cnt];
+ cnt++;
+ for(i=0; (test[0][cnt+i] != END_SEQ); i++)
+ {
+ if(test[0][cnt+i] != END_SEQ)
+ mDNIe_data_level3[i] = test[0][cnt+i];
+ }
+ mDNIe_data_level3[i] = END_SEQ;
+ mDNIe_data_level3_cnt = i;
+ cnt += i+1;
+
+/*5level */
+ adc_level_formDNIe[4] = test[0][cnt];
+ cnt++;
+ for(i=0; (test[0][cnt+i] != END_SEQ); i++)
+ {
+ if(test[0][cnt+i] != END_SEQ)
+ mDNIe_data_level4[i] = test[0][cnt+i];
+ }
+ mDNIe_data_level4[i] = END_SEQ;
+ mDNIe_data_level4_cnt = i;
+ cnt += i+1;
+
+/*6 level */
+ adc_level_formDNIe[5] = test[0][cnt];
+ cnt++;
+ for(i=0; (test[0][cnt+i] != END_SEQ); i++)
+ {
+ if(test[0][cnt+i] != END_SEQ)
+ mDNIe_data_level5[i] = test[0][cnt+i];
+ }
+ mDNIe_data_level5[i] = END_SEQ;
+ mDNIe_data_level5_cnt = i;
+ cnt += i+1;
+
+
+ mdnie_tuning_load = 1;
+}
+EXPORT_SYMBOL(mDNIe_txtbuf_to_parsing_for_lightsensor);
+
+#endif
+
+
+
+int s3c_mdnie_hw_init(void)
+{
+ printk("MDNIE INIT ..........\n");
+
+ printk(banner);
+
+ s3c_mdnie_mem = request_mem_region(S3C_MDNIE_PHY_BASE,S3C_MDNIE_MAP_SIZE,"mdnie");
+ if(s3c_mdnie_mem == NULL) {
+ printk(KERN_ERR "MDNIE: failed to reserved memory region\n");
+ return -ENOENT;
+ }
+
+ s3c_mdnie_base = ioremap(S3C_MDNIE_PHY_BASE,S3C_MDNIE_MAP_SIZE);
+ if(s3c_mdnie_base == NULL) {
+ printk(KERN_ERR "MDNIE failed ioremap\n");
+ return -ENOENT;
+ }
+
+ /* clock */
+
+// mdnie_clock = clk_get(NULL,"mdnie");
+// mdnie_clock = clk_get(NULL,"mdnie_sel");
+// mdnie_clock = clk_get(NULL,"mout_mdnie_pwm");
+ mdnie_clock = clk_get(NULL,"sclk_mdnie");
+
+ if (IS_ERR(mdnie_clock)) {
+ printk("failed to get mdnie clock source\n");
+ return -EINVAL;
+ }
+
+ printk("MDNIE INIT SUCCESS Addr : 0x%p\n",s3c_mdnie_base);
+
+ return 0;
+
+}
+
+
+int s3c_mdnie_mask(void)
+{
+ unsigned int mask;
+
+ mask = s3c_mdnie_readl(S3C_MDNIE_rR1);
+ mask |= S3C_MDNIE_REG_MASK;
+ s3c_mdnie_writel(mask,S3C_MDNIE_rR1);
+
+ return 0;
+}
+
+int s3c_mdnie_unmask(void)
+{
+ unsigned int mask;
+
+ mask = s3c_mdnie_readl(S3C_MDNIE_rR1);
+ mask &= ~S3C_MDNIE_REG_MASK;
+ s3c_mdnie_writel(mask,S3C_MDNIE_rR1);
+
+ return 0;
+}
+
+int s3c_mdnie_select_mode(int algo, int mcm, int lpa)
+{
+ s3c_mdnie_writel(0x0000,S3C_MDNIE_rR1);
+ s3c_mdnie_writel(0x0000,S3C_MDNIE_rR36);
+ s3c_mdnie_writel(0x0FFF,S3C_MDNIE_rR37);
+ s3c_mdnie_writel(0x005c,S3C_MDNIE_rR38);
+
+ s3c_mdnie_writel(0x0ff0,S3C_MDNIE_rR39);
+ s3c_mdnie_writel(0x0064,S3C_MDNIE_rR43);
+ s3c_mdnie_writel(0x0364,S3C_MDNIE_rR45);
+
+ return 0;
+}
+
+
+int s3c_mdnie_set_size(unsigned int hsize, unsigned int vsize)
+{
+
+ unsigned int size;
+
+ size = s3c_mdnie_readl(S3C_MDNIE_rR2);
+ size &= ~S3C_MDNIE_SIZE_MASK;
+ size |= hsize;
+ s3c_mdnie_writel(size,S3C_MDNIE_rR2);
+
+ size = s3c_mdnie_readl(S3C_MDNIE_rR3);
+ size &= ~S3C_MDNIE_SIZE_MASK;
+ size |= vsize;
+ s3c_mdnie_writel(size,S3C_MDNIE_rR3);
+
+ return 0;
+}
+
+int s3c_mdnie_setup(void)
+{
+
+ s3c_mdnie_hw_init();
+ s3c_ielcd_hw_init();
+
+ clk_enable(mdnie_clock);
+ return 0;
+
+}
+
+void mDNIe_Mode_Change(mDNIe_data_type *mode)
+{
+
+ if(mDNIe_Tuning_Mode == TRUE)
+ {
+ printk("mDNIe_Mode_Change [mDNIe_Tuning_Mode = TRUE, API is Return] \n");
+ return;
+ }
+ else
+ {
+ s3c_mdnie_mask();
+ while ( mode->addr != END_SEQ)
+ {
+ s3c_mdnie_writel(mode->data, mode->addr);
+ printk(KERN_INFO "[mDNIe] mDNIe_tuning_initialize: addr(0x%x), data(0x%x) \n",mode->addr, mode->data);
+ mode++;
+ }
+ s3c_mdnie_unmask();
+ }
+}
+
+void mDNIe_Set_Mode(Lcd_mDNIe_UI mode, u8 mDNIe_Outdoor_OnOff)
+{
+ if(mDNIe_Outdoor_OnOff)
+ {
+ switch(mode)
+ {
+ case mDNIe_UI_MODE:
+ mDNIe_Mode_Change(mDNIe_UI);
+ break;
+
+ case mDNIe_VIDEO_MODE:
+ mDNIe_Mode_Change(mDNIe_Outdoor_Mode);
+ break;
+
+ case mDNIe_VIDEO_WARM_MODE:
+ mDNIe_Mode_Change(mDNIe_Video_WO_Mode);
+ break;
+
+ case mDNIe_VIDEO_COLD_MODE:
+ mDNIe_Mode_Change(mDNIe_Video_CO_Mode);
+ break;
+
+ case mDNIe_CAMERA_MODE:
+ mDNIe_Mode_Change(mDNIe_Camera_Outdoor_Mode);
+ break;
+
+ case mDNIe_NAVI:
+ mDNIe_Mode_Change(mDNIe_Outdoor_Mode);
+ break;
+ }
+
+ current_mDNIe_UI = mode;
+ #if 0
+ if(current_mDNIe_UI == mDNIe_UI_MODE)
+ current_mDNIe_OutDoor_OnOff = FALSE;
+ else
+ #endif
+ current_mDNIe_OutDoor_OnOff = TRUE;
+ }
+ else
+ {
+ switch(mode)
+ {
+ case mDNIe_UI_MODE:
+ mDNIe_Mode_Change(mDNIe_UI);
+ break;
+
+ case mDNIe_VIDEO_MODE:
+ mDNIe_Mode_Change(mDNIe_Video);
+ break;
+
+ case mDNIe_VIDEO_WARM_MODE:
+ mDNIe_Mode_Change(mDNIe_Video_Warm);
+ break;
+
+ case mDNIe_VIDEO_COLD_MODE:
+ mDNIe_Mode_Change(mDNIe_Video_Cold);
+ break;
+
+ case mDNIe_CAMERA_MODE:
+ mDNIe_Mode_Change(mDNIe_Camera);
+ break;
+
+ case mDNIe_NAVI:
+ mDNIe_Mode_Change(mDNIe_UI);
+ break;
+ }
+
+ current_mDNIe_UI = mode;
+ current_mDNIe_OutDoor_OnOff = FALSE;
+ }
+ printk("[mDNIe] mDNIe_Set_Mode: current_mDNIe_UI(%d), current_mDNIe_OutDoor_OnOff(%d) \n",current_mDNIe_UI, current_mDNIe_OutDoor_OnOff);
+}
+EXPORT_SYMBOL(mDNIe_Set_Mode);
+
+void mDNIe_Mode_Set(void)
+{
+ mDNIe_Set_Mode(current_mDNIe_UI, current_mDNIe_OutDoor_OnOff);
+}
+EXPORT_SYMBOL(mDNIe_Mode_Set);
+
+static ssize_t mdnieset_ui_file_cmd_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ printk("called %s \n",__func__);
+
+ int mdnie_ui = 0;
+
+ switch(current_mDNIe_UI)
+ {
+ case mDNIe_UI_MODE:
+ default:
+ mdnie_ui = 0;
+ break;
+
+ case mDNIe_VIDEO_MODE:
+ mdnie_ui = 1;
+ break;
+
+ case mDNIe_VIDEO_WARM_MODE:
+ mdnie_ui = 2;
+ break;
+
+ case mDNIe_VIDEO_COLD_MODE:
+ mdnie_ui = 3;
+ break;
+
+ case mDNIe_CAMERA_MODE:
+ mdnie_ui = 4;
+ break;
+
+ case mDNIe_NAVI:
+ mdnie_ui = 5;
+ break;
+ }
+ return sprintf(buf,"%u\n",mdnie_ui);
+}
+
+static ssize_t mdnieset_ui_file_cmd_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ int value;
+
+ sscanf(buf, "%d", &value);
+
+ printk(KERN_INFO "[mdnie set] in mdnieset_ui_file_cmd_store, input value = %d \n",value);
+
+ switch(value)
+ {
+ case SIG_MDNIE_UI_MODE:
+ current_mDNIe_UI = mDNIe_UI_MODE;
+ break;
+
+ case SIG_MDNIE_VIDEO_MODE:
+ current_mDNIe_UI = mDNIe_VIDEO_MODE;
+ break;
+
+ case SIG_MDNIE_VIDEO_WARM_MODE:
+ current_mDNIe_UI = mDNIe_VIDEO_WARM_MODE;
+ break;
+
+ case SIG_MDNIE_VIDEO_COLD_MODE:
+ current_mDNIe_UI = mDNIe_VIDEO_COLD_MODE;
+ break;
+
+ case SIG_MDNIE_CAMERA_MODE:
+ current_mDNIe_UI = mDNIe_CAMERA_MODE;
+ break;
+
+ case SIG_MDNIE_NAVI:
+ current_mDNIe_UI = mDNIe_NAVI;
+ break;
+
+ default:
+ printk("\nmdnieset_ui_file_cmd_store value is wrong : value(%d)\n",value);
+ break;
+ }
+
+ mDNIe_Set_Mode(current_mDNIe_UI, current_mDNIe_OutDoor_OnOff);
+
+ return size;
+}
+
+static DEVICE_ATTR(mdnieset_ui_file_cmd,0666, mdnieset_ui_file_cmd_show, mdnieset_ui_file_cmd_store);
+
+static ssize_t mdnieset_outdoor_file_cmd_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ printk("called %s \n",__func__);
+
+ return sprintf(buf,"%u\n",current_mDNIe_OutDoor_OnOff);
+}
+
+static ssize_t mdnieset_outdoor_file_cmd_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ int value;
+
+ sscanf(buf, "%d", &value);
+
+ printk(KERN_INFO "[mdnie set] in mdnieset_outdoor_file_cmd_store, input value = %d \n",value);
+
+ if(value)
+ {
+ current_mDNIe_OutDoor_OnOff = TRUE;
+ }
+ else
+ {
+ current_mDNIe_OutDoor_OnOff = FALSE;
+ }
+
+ mDNIe_Set_Mode(current_mDNIe_UI, current_mDNIe_OutDoor_OnOff);
+
+ return size;
+}
+
+static DEVICE_ATTR(mdnieset_outdoor_file_cmd,0666, mdnieset_outdoor_file_cmd_show, mdnieset_outdoor_file_cmd_store);
+
+void init_mdnie_class(void)
+{
+ mdnieset_ui_class = class_create(THIS_MODULE, "mdnieset_ui");
+ if (IS_ERR(mdnieset_ui_class))
+ pr_err("Failed to create class(mdnieset_ui_class)!\n");
+
+ switch_mdnieset_ui_dev = device_create(mdnieset_ui_class, NULL, 0, NULL, "switch_mdnieset_ui");
+ if (IS_ERR(switch_mdnieset_ui_dev))
+ pr_err("Failed to create device(switch_mdnieset_ui_dev)!\n");
+
+ if (device_create_file(switch_mdnieset_ui_dev, &dev_attr_mdnieset_ui_file_cmd) < 0)
+ pr_err("Failed to create device file(%s)!\n", dev_attr_mdnieset_ui_file_cmd.attr.name);
+
+ mdnieset_outdoor_class = class_create(THIS_MODULE, "mdnieset_outdoor");
+ if (IS_ERR(mdnieset_outdoor_class))
+ pr_err("Failed to create class(mdnieset_outdoor_class)!\n");
+
+ switch_mdnieset_outdoor_dev = device_create(mdnieset_outdoor_class, NULL, 0, NULL, "switch_mdnieset_outdoor");
+ if (IS_ERR(switch_mdnieset_outdoor_dev))
+ pr_err("Failed to create device(switch_mdnieset_outdoor_dev)!\n");
+
+ if (device_create_file(switch_mdnieset_outdoor_dev, &dev_attr_mdnieset_outdoor_file_cmd) < 0)
+ pr_err("Failed to create device file(%s)!\n", dev_attr_mdnieset_outdoor_file_cmd.attr.name);
+}
+EXPORT_SYMBOL(init_mdnie_class);
+
+
+#ifdef MDNIE_TUNING
+static u16 pre_0x0100 = 0;
+static u16 pre_0x00AC = 0;
+
+static int pre_adc_level = 0;
+static int cur_adc_level = 0;
+
+
+static int mdnie_level;
+static int init_mdnie = 0;
+
+void mDNIe_Mode_set_for_lightsensor(u16 *buf)
+{
+ u32 i = 0;
+ int cnt = 0;
+
+ s3c_mdnie_mask();
+if(cur_adc_level >= pre_adc_level) //0 => END_SEQ
+{
+ while ( (*(buf+i)) != END_SEQ)
+ {
+ if((*(buf+i)) == 0x0100)
+ {
+ if(init_mdnie == 0)
+ {
+ pre_0x0100 = (*(buf+(i+1)));
+ }
+ if(pre_0x0100 < (*(buf+(i+1)))){
+ while ((pre_0x0100 < (*(buf+(i+1))))&&(pre_0x0100 <= 0x8080)&&(pre_0x0100 >= 0x0000))
+ {
+ s3c_mdnie_writel(pre_0x0100, (*(buf+i)));
+ printk("[mDNIe] mDNIe_tuning_initialize: addr(0x%x), data(0x%x) \n",(*(buf+i)),pre_0x0100);
+ pre_0x0100 = ((pre_0x0100 & 0xff00) + (light_step<<8)) | ((pre_0x0100 & 0x00ff) + (saturation_step));
+ }
+ }
+ else if(pre_0x0100 > (*(buf+(i+1)))){
+ while (pre_0x0100 > (*(buf+(i+1)))&&(pre_0x0100 >= 0x0000)&&(pre_0x0100 <= 0x8080))
+ {
+ s3c_mdnie_writel(pre_0x0100, (*(buf+i)));
+ printk("[mDNIe] mDNIe_tuning_initialize: addr(0x%x), data(0x%x) \n",(*(buf+i)),pre_0x0100);
+ pre_0x0100 = ((pre_0x0100 & 0xff00) - (light_step<<8)) | ((pre_0x0100 & 0x00ff) - (saturation_step));
+ }
+ }
+ s3c_mdnie_writel((*(buf+i+1)), (*(buf+i)));
+ pre_0x0100 = (*(buf+i+1));
+ }
+ else if((*(buf+i)) == 0x00AC)
+ {
+ if(init_mdnie == 0)
+ {
+ pre_0x00AC = (*(buf+(i+1)));
+ }
+ if(pre_0x00AC < (*(buf+(i+1)))){
+ while (pre_0x00AC < (*(buf+(i+1)))&&(pre_0x00AC <= 0x03ff)&&(pre_0x00AC >= 0x0000))
+ {
+ s3c_mdnie_writel(pre_0x00AC, (*(buf+i)));
+ printk("[mDNIe] mDNIe_tuning_initialize: addr(0x%x), data(0x%x) \n",(*(buf+i)),pre_0x00AC);
+ pre_0x00AC +=(cs_step);
+ }
+ }
+ else if(pre_0x00AC > (*(buf+(i+1)))){
+ while (pre_0x00AC > (*(buf+(i+1)))&&(pre_0x00AC >= 0x0000)&&(pre_0x00AC <= 0x03ff))
+ {
+ s3c_mdnie_writel(pre_0x00AC, (*(buf+i)));
+ printk("[mDNIe] mDNIe_tuning_initialize: addr(0x%x), data(0x%x) \n",(*(buf+i)),pre_0x00AC);
+ pre_0x00AC -=(cs_step);
+ }
+ }
+ s3c_mdnie_writel((*(buf+i+1)), (*(buf+i)));
+ pre_0x00AC = (*(buf+i+1));
+ }
+ else
+ {
+ s3c_mdnie_writel((*(buf+i+1)), (*(buf+i)));
+ }
+ printk("[mDNIe] mDNIe_tuning_initialize: addr(0x%x), data(0x%x) \n",(*(buf+i)),(*(buf+(i+1))));
+ i+=2;
+ }
+}
+else // if(cur_adc_level < pre_adc_level) //END_SEQ => 0
+{
+ switch (cur_adc_level) {
+ case 0:
+ cnt = mDNIe_data_level0_cnt;
+ break;
+ case 1:
+ cnt = mDNIe_data_level1_cnt;
+ break;
+ case 2:
+ cnt = mDNIe_data_level2_cnt;
+ break;
+ case 3:
+ default:
+ cnt = mDNIe_data_level3_cnt;
+ break;
+ case 4:
+ cnt = mDNIe_data_level4_cnt;
+ break;
+ case 5:
+ cnt = mDNIe_data_level5_cnt;
+ break;
+ }
+
+ cnt--; //remove END_SEQ
+
+ while ( cnt > 0)
+ {
+ if((*(buf+cnt-1)) == 0x0100)
+ {
+ if(init_mdnie == 0)
+ {
+ pre_0x0100 = (*(buf+cnt));
+ }
+ if(pre_0x0100 < (*(buf+cnt))){
+ while ((pre_0x0100 < (*(buf+cnt)))&&(pre_0x0100 <= 0x8080)&&(pre_0x0100 >= 0x0000))
+ {
+ s3c_mdnie_writel(pre_0x0100, (*(buf+cnt-1)));
+ printk("[mDNIe] mDNIe_tuning_initialize: addr(0x%x), data(0x%x) \n",(*(buf+cnt-1)),pre_0x0100);
+ pre_0x0100 = ((pre_0x0100 & 0xff00) + (light_step<<8)) | ((pre_0x0100 & 0x00ff) + (saturation_step));
+ }
+ }
+ else if(pre_0x0100 > (*(buf+cnt))){
+ while (pre_0x0100 > (*(buf+cnt))&&(pre_0x0100 >= 0x0000)&&(pre_0x0100 <= 0x8080))
+ {
+ s3c_mdnie_writel(pre_0x0100, (*(buf+cnt-1)));
+ printk("[mDNIe] mDNIe_tuning_initialize: addr(0x%x), data(0x%x) \n",(*(buf+cnt-1)),pre_0x0100);
+ pre_0x0100 = ((pre_0x0100 & 0xff00) - (light_step<<8)) | ((pre_0x0100 & 0x00ff) - (saturation_step));
+ }
+ }
+ s3c_mdnie_writel((*(buf+cnt)), (*(buf+cnt-1)));
+ pre_0x0100 = (*(buf+cnt));
+ }
+ else if((*(buf+cnt-1)) == 0x00AC)
+ {
+ if(init_mdnie == 0)
+ {
+ pre_0x00AC = (*(buf+cnt));
+ }
+ if(pre_0x00AC < (*(buf+cnt))){
+ while (pre_0x00AC < (*(buf+cnt))&&(pre_0x00AC <= 0x03ff)&&(pre_0x00AC >= 0x0000))
+ {
+ s3c_mdnie_writel(pre_0x00AC, (*(buf+cnt-1)));
+ printk("[mDNIe] mDNIe_tuning_initialize: addr(0x%x), data(0x%x) \n",(*(buf+cnt-1)),pre_0x00AC);
+ pre_0x00AC +=(cs_step);
+ }
+ }
+ else if(pre_0x00AC > (*(buf+cnt))){
+ while (pre_0x00AC > (*(buf+cnt))&&(pre_0x00AC >= 0x0000)&&(pre_0x00AC <= 0x03ff))
+ {
+ s3c_mdnie_writel(pre_0x00AC, (*(buf+cnt-1)));
+ printk("[mDNIe] mDNIe_tuning_initialize: addr(0x%x), data(0x%x) \n",(*(buf+cnt-1)),pre_0x00AC);
+ pre_0x00AC -=(cs_step);
+ }
+ }
+ s3c_mdnie_writel((*(buf+cnt)), (*(buf+cnt-1)));
+ pre_0x00AC = (*(buf+cnt));
+ }
+ else
+ {
+ //s3c_mdnie_writel((*(buf+i+1)), (*(buf+i)));
+ s3c_mdnie_writel((*(buf+cnt)), (*(buf+cnt-1)));
+ }
+
+ printk("[mDNIe] mDNIe_tuning_initialize: addr(0x%x), data(0x%x) \n",(*(buf+cnt-1)),(*(buf+cnt)));
+
+ cnt -=2;
+ }
+}
+ s3c_mdnie_unmask();
+}
+
+int mdnie_lock = 0;
+
+void mDNIe_Set_Register_for_lightsensor(int adc)
+{
+
+ if(init_mdnie == 0)
+ pre_adc_level = cur_adc_level;
+
+ if(!mdnie_lock){
+ mdnie_lock = 1;
+
+ if((adc >= adc_level_formDNIe[0])&&(adc < adc_level_formDNIe[1]))
+ {
+ cur_adc_level = 0;
+
+ if(mdnie_level != 0)
+ mDNIe_Mode_set_for_lightsensor(mDNIe_data_level0);
+
+ mdnie_level = 0;
+ }
+ else if((adc >= adc_level_formDNIe[1])&&(adc < adc_level_formDNIe[2]))
+ {
+ cur_adc_level = 1;
+
+ if(mdnie_level != 1)
+ mDNIe_Mode_set_for_lightsensor(mDNIe_data_level1);
+
+ mdnie_level = 1;
+ }
+ else if((adc >= adc_level_formDNIe[2])&&(adc < adc_level_formDNIe[3]))
+ {
+ cur_adc_level = 2;
+
+ if(mdnie_level != 2)
+ mDNIe_Mode_set_for_lightsensor(mDNIe_data_level2);
+
+ mdnie_level = 2;
+ }
+ else if((adc >= adc_level_formDNIe[3])&&(adc < adc_level_formDNIe[4]))
+ {
+ cur_adc_level = 3;
+
+ if(mdnie_level != 3)
+ mDNIe_Mode_set_for_lightsensor(mDNIe_data_level3);
+
+ mdnie_level = 3;
+ }
+ else if((adc >= adc_level_formDNIe[4])&&(adc < adc_level_formDNIe[5]))
+ {
+ cur_adc_level = 4;
+
+ if(mdnie_level != 4)
+ mDNIe_Mode_set_for_lightsensor(mDNIe_data_level4);
+
+ mdnie_level = 4;
+ }
+ else if(adc >= adc_level_formDNIe[5])
+ {
+ cur_adc_level = 5;
+
+ if(mdnie_level != 5)
+ mDNIe_Mode_set_for_lightsensor(mDNIe_data_level5);
+
+ mdnie_level = 5;
+ }
+
+ pre_adc_level = cur_adc_level;
+
+ init_mdnie = 1;
+
+ mdnie_lock = 0;
+ }
+ else
+ printk("[mDNIe] mDNIe_tuning - mdnie_lock(%d) \n",mdnie_lock);
+}
+EXPORT_SYMBOL(mDNIe_Set_Register_for_lightsensor);
+
+
+void mDNIe_tuning_set(void)
+{
+ u32 i = 0;
+
+ s3c_mdnie_mask();
+ while ( mDNIe_data[i] != END_SEQ)
+ {
+ s3c_mdnie_writel(mDNIe_data[i+1], mDNIe_data[i]);
+ printk("[mDNIe] mDNIe_tuning_initialize: addr(0x%x), data(0x%x) \n",mDNIe_data[i], mDNIe_data[i+1]);
+ i+=2;
+ }
+ s3c_mdnie_unmask();
+}
+
+
+void mDNIe_txtbuf_to_parsing(void)
+{
+ int i = 0;
+
+ for(i=0; (test[0][i] != END_SEQ); i++)
+ {
+ if(test[0][i] != END_SEQ)
+ mDNIe_data[i] = test[0][i];
+ }
+ mDNIe_data[i] = END_SEQ;
+
+ mDNIe_tuning_set();
+
+ mDNIe_Tuning_Mode = TRUE;
+}
+EXPORT_SYMBOL(mDNIe_txtbuf_to_parsing);
+#endif
+
+#ifdef MDNIE_TUNINGMODE_FOR_BACKLIGHT
+int mdnie_tuning_backlight = 0;
+
+void mDNIe_Mode_set_for_backlight(u16 *buf)
+{
+ u32 i = 0;
+ int cnt = 0;
+
+ if(mdnie_tuning_backlight){
+ s3c_mdnie_mask();
+
+ while ((*(buf+i)) != END_SEQ)
+ {
+ if((*(buf+i)) == 0x0100)
+ {
+ if(pre_0x0100 < (*(buf+(i+1)))){
+ while ((pre_0x0100 < (*(buf+(i+1))))&&(pre_0x0100 <= 0x6060)&&(pre_0x0100 >= 0x0000))
+ {
+ s3c_mdnie_writel(pre_0x0100, (*(buf+i)));
+ printk("[mDNIe] mDNIe_tuning_initialize: addr(0x%x), data(0x%x) \n",(*(buf+i)),pre_0x0100);
+ pre_0x0100 = ((pre_0x0100 & 0xff00) + (0x1<<8)) | ((pre_0x0100 & 0x00ff) + (0x1));
+ }
+ }
+ else if(pre_0x0100 > (*(buf+(i+1)))){
+ while (pre_0x0100 > (*(buf+(i+1)))&&(pre_0x0100 >= 0x0000)&&(pre_0x0100 <= 0x6060))
+ {
+ s3c_mdnie_writel(pre_0x0100, (*(buf+i)));
+ printk("[mDNIe] mDNIe_tuning_initialize: addr(0x%x), data(0x%x) \n",(*(buf+i)),pre_0x0100);
+ pre_0x0100 = ((pre_0x0100 & 0xff00) - (0x1<<8)) | ((pre_0x0100 & 0x00ff) - (0x1));
+ }
+ }
+ s3c_mdnie_writel((*(buf+i+1)), (*(buf+i)));
+ pre_0x0100 = (*(buf+i+1));
+ }
+ else
+ {
+ s3c_mdnie_writel((*(buf+i+1)), (*(buf+i)));
+ }
+ printk("[mDNIe] mDNIe_Mode_set_for_backlight : addr(0x%x), data(0x%x) \n",(*(buf+i)),(*(buf+(i+1))));
+ i+=2;
+ }
+
+ s3c_mdnie_unmask();
+ }
+}
+EXPORT_SYMBOL(mDNIe_Mode_set_for_backlight);
+
+void mDNIe_txtbuf_to_parsing_for_backlight(void)
+{
+ int i = 0;
+ int cnt = 0;
+
+
+ for(i=0; (test[0][i] != END_SEQ); i++)
+ {
+ if(test[0][i] != END_SEQ)
+ mDNIe_data_ui[i] = test[0][i];
+ }
+ mDNIe_data_ui[i] = END_SEQ;
+ cnt = i+1;
+
+ for(i=0; (test[0][cnt+i] != END_SEQ); i++)
+ {
+ if(test[0][cnt+i] != END_SEQ)
+ mDNIe_data_300cd_level1[i] = test[0][cnt+i];
+ }
+ mDNIe_data_300cd_level1[i] = END_SEQ;
+ cnt += i+1;
+
+ for(i=0; (test[0][cnt+i] != END_SEQ); i++)
+ {
+ if(test[0][cnt+i] != END_SEQ)
+ mDNIe_data_300cd_level2[i] = test[0][cnt+i];
+ }
+ mDNIe_data_300cd_level2[i] = END_SEQ;
+ cnt += i+1;
+
+ for(i=0; (test[0][cnt+i] != END_SEQ); i++)
+ {
+ if(test[0][cnt+i] != END_SEQ)
+ mDNIe_data_ui_down[i] = test[0][cnt+i];
+ }
+ mDNIe_data_ui_down[i] = END_SEQ;
+ cnt += i+1;
+
+ mdnie_tuning_backlight = 1;
+
+ mDNIe_Mode_set_for_backlight(pmDNIe_Gamma_set[0]);
+}
+EXPORT_SYMBOL(mDNIe_txtbuf_to_parsing_for_backlight);
+
+#endif
+
+
+// value: 0 ~ 100
+void s5p_mdine_pwm_brightness(int value)
+{
+ u32 reg, data;
+
+#ifdef DEBUG_MDNIE
+ if((s3c_mdnie_readw(0x0084) & 0x0010) != 0x0010)
+ {
+ printk("%s: reg(0x0084) is not 0x0010\n", __func__);
+ }
+ if(s3c_mdnie_readw(0x0198) != 0x0000)
+ {
+ printk("%s: reg(0x0198) is not 0x0000\n", __func__);
+ }
+ if((s3c_mdnie_readw(0x019C) & 0xff00) != 0xC000)
+ {
+ printk("%s: reg(0x019C) is not 0xC000\n", __func__);
+ }
+#endif
+
+ if(value<0)
+ data = 0;
+ else if(value>100)
+ data = 100;
+ else
+ data = value;
+
+ reg = s3c_mdnie_readw(0x019C);
+ reg &= ~0x00ff;
+ reg |= 0x00ff & data;
+ s3c_mdnie_writel(reg,0x019C);
+}
+EXPORT_SYMBOL(s5p_mdine_pwm_brightness);
+
+void s5p_mdine_pwm_enable(int on)
+{
+ u16 data;
+
+ printk("%s:%d\n", __func__, on);
+
+ if(on)
+ {
+ data = s3c_mdnie_readw(0x0084);
+ data = data | 0x0010;
+ s3c_mdnie_writel(data,0x0084); // on
+
+ s3c_mdnie_writel(0x0000,0x0198); // CABC disable
+
+ data = s3c_mdnie_readw(0x019C);
+ data = (data & ~0xFF00) | 0xC000; // PWM on
+ s3c_mdnie_writel(data,0x019C); //
+ }
+ else
+ {
+ data = s3c_mdnie_readw(0x0084);
+ data = data & ~0x0010;
+ s3c_mdnie_writel(data,0x0084); // off
+ }
+}
+EXPORT_SYMBOL(s5p_mdine_pwm_enable);
+
+void s5p_mdine_cabc_enable(int on)
+{
+ u16 data;
+
+ printk("%s:%d\n", __func__, on);
+
+ if(on)
+ {
+ data = s3c_mdnie_readw(0x0084);
+ data = data | 0x0010;
+ s3c_mdnie_writel(data,0x0084); // on
+
+ s3c_mdnie_writel(0x0002,0x0198); // CABC enable
+
+ data = s3c_mdnie_readw(0x019C);
+ data = (data & ~0xFF00) | 0x8000; //PWM off
+ s3c_mdnie_writel(data,0x019C); //
+ }
+ else
+ {
+ data = s3c_mdnie_readw(0x0084);
+ data = data & ~0x0010;
+ s3c_mdnie_writel(data,0x0084); // off
+ }
+}
+EXPORT_SYMBOL(s5p_mdine_cabc_enable);
+
+int s3c_mdnie_init_global(struct s3cfb_global *s3cfb_ctrl)
+{
+
+ // clk enable
+ clk_enable(mdnie_clock);
+
+ s3c_mdnie_set_size(s3cfb_ctrl->lcd->width,s3cfb_ctrl->lcd->height);
+
+ mDNIe_Set_Mode(current_mDNIe_UI, current_mDNIe_OutDoor_OnOff); //Add
+
+ s3c_ielcd_logic_start();
+ s3c_ielcd_init_global(s3cfb_ctrl);
+
+ s5p_mdine_pwm_enable(1);
+
+ return 0;
+
+}
+
+int s3c_mdnie_start(struct s3cfb_global *ctrl)
+{
+
+ //s3c_ielcd_set_clock(ctrl);
+ s3c_ielcd_start();
+
+ return 0;
+
+}
+
+int s3c_mdnie_off(void)
+{
+
+ s3c_ielcd_logic_stop();
+ clk_disable(mdnie_clock);
+
+ return 0;
+}
+
+
+int s3c_mdnie_stop(void)
+{
+
+ s3c_ielcd_stop();
+
+ return 0;
+
+}
+
+
+MODULE_AUTHOR("lsi");
+MODULE_DESCRIPTION("S3C MDNIE Device Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/samsung/s3cfb_mdnie.h b/drivers/video/samsung/s3cfb_mdnie.h
new file mode 100644
index 0000000..d919d5a
--- /dev/null
+++ b/drivers/video/samsung/s3cfb_mdnie.h
@@ -0,0 +1,349 @@
+
+/* linux/drivers/video/samsung/s3cfb_mdnie.h
+ *
+ * Header file for Samsung (MDNIE) driver
+ *
+ * Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.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 _S3CFB_MDNIE_H
+#define _S3CFB_MDNIE_H
+
+
+
+#define S3C_MDNIE_PHY_BASE 0xFAE00000
+#define S3C_MDNIE_MAP_SIZE 0x00001000
+
+
+#define S3C_MDNIE_rR1 0x0084
+#define S3C_MDNIE_rR2 0x0088
+#define S3C_MDNIE_rR3 0x008C
+
+
+#define S3C_MDNIE_rR36 0x0090
+#define S3C_MDNIE_rR37 0x0094
+#define S3C_MDNIE_rR38 0x0098
+#define S3C_MDNIE_rR39 0x009C
+#define S3C_MDNIE_rR40 0x00A0
+#define S3C_MDNIE_rR41 0x00A4
+#define S3C_MDNIE_rR42 0x00A8
+#define S3C_MDNIE_rR43 0x00AC
+#define S3C_MDNIE_rR44 0x00B0
+#define S3C_MDNIE_rR45 0x00B4
+#define S3C_MDNIE_rR46 0x00B8
+
+#define S3C_MDNIE_rR48 0x00C0
+
+
+#define S3C_MDNIE_rR49 0x00C4
+#define S3C_MDNIE_rR50 0x00C8
+#define S3C_MDNIE_rR51 0x00CC
+#define S3C_MDNIE_rR52 0x00D0
+#define S3C_MDNIE_rR53 0x00D4
+#define S3C_MDNIE_rR54 0x00D8
+#define S3C_MDNIE_rR55 0x00DC
+#define S3C_MDNIE_rR56 0x00E0
+
+
+#define S3C_MDNIE_rR64 0x0100
+#define S3C_MDNIE_rR65 0x0104
+#define S3C_MDNIE_rR66 0x0108
+#define S3C_MDNIE_rR67 0x010C
+#define S3C_MDNIE_rR68 0x0110
+#define S3C_MDNIE_rR69 0x0114
+
+
+#define S3C_MDNIE_rR72 0x0120
+#define S3C_MDNIE_rR73 0x0124
+#define S3C_MDNIE_rR74 0x0128
+#define S3C_MDNIE_rR75 0x012C
+#define S3C_MDNIE_rR76 0x0130
+#define S3C_MDNIE_rR77 0x0134
+#define S3C_MDNIE_rR78 0x0138
+#define S3C_MDNIE_rR79 0x013C
+#define S3C_MDNIE_rR80 0x0140
+#define S3C_MDNIE_rR81 0x0144
+#define S3C_MDNIE_rR82 0x0148
+#define S3C_MDNIE_rR83 0x014C
+#define S3C_MDNIE_rR84 0x0150
+#define S3C_MDNIE_rR85 0x0154
+#define S3C_MDNIE_rR86 0x0158
+#define S3C_MDNIE_rR87 0x015C
+
+
+#define S3C_MDNIE_rR88 0x0160
+#define S3C_MDNIE_rR89 0x0164
+#define S3C_MDNIE_rR90 0x0168
+#define S3C_MDNIE_rR91 0x016C
+#define S3C_MDNIE_rR92 0x0170
+#define S3C_MDNIE_rR93 0x0174
+#define S3C_MDNIE_rR94 0x0178
+#define S3C_MDNIE_rR95 0x017C
+#define S3C_MDNIE_rR96 0x0180
+#define S3C_MDNIE_rR97 0x0184
+#define S3C_MDNIE_rR98 0x0188
+#define S3C_MDNIE_rR99 0x018C
+#define S3C_MDNIE_rR100 0x0190
+#define S3C_MDNIE_rR101 0x0194
+
+#define S3C_MDNIE_rR102 0x0198
+
+#define S3C_MDNIE_rR103 0x019C
+
+
+
+
+//R1
+#define S3C_MDNIE_HDTR (0<<6)
+#define S3C_MDNIE_HDTR_CP (1<<6) // Color Preference
+#define S3C_MDNIE_HDTR_VE (2<<6) // Visibility Enhancement
+#define S3C_MDNIE_MCM_OFF (0<<5)
+#define S3C_MDNIE_MCM_ON (1<<5)
+#define S3C_MDNIE_LPA_OFF (0<<4)
+#define S3C_MDNIE_LPA_ON (1<<4)
+#define S3C_MDNIE_ALGORITHM_MASK (0xF<<4)
+#define S3C_MDNIE_REG_UNMASK (0<<0)
+#define S3C_MDNIE_REG_MASK (1<<0)
+//R2
+#define S3C_MDNIE_HSIZE(n) (((n)&0x7FF)<<0)
+//R3
+#define S3C_MDNIE_VSIZE(n) (((n)&0x7FF)<<0)
+#define S3C_MDNIE_SIZE_MASK (0x7FF<<0)
+
+//R36
+#define S3C_MDNIE_DECONT_TH(n) (((n)&0xFFF)<<0 )
+//R37
+#define S3C_MDNIE_DIRECT_TH(n) (((n)&0xFFF)<<0)
+//R38
+#define S3C_MDNIE_SIMPLE_TH(n) (((n)&0x7F)<<0)
+//R39
+#define S3C_MDNIE_DE_CONT(n) (((n)&0x7F)<<5)
+#define S3C_MDNIE_CE_ON (0<<4)
+#define S3C_MDNIE_CE_OFF (1<<4)
+#define S3C_MDNIE_CE_CURVE(n) (((n)&0x7)<<1)
+#define S3C_MDNIE_AMOLED_NOTSELECT (0<<0)
+#define S3C_MDNIE_AMOLED_SELECT (1<<0)
+//R40
+#define S3C_MDNIE_IPF_ALPHA(n) (((n)&0xFF)<<7)
+#define S3C_MDNIE_IPF_BETA(n) (((n)&0xFF)<<0)
+//R41
+#define S3C_MDNIE_IPF_THETA(n) (((n)&0xFF)<<0)
+//R42
+#define S3C_MDNIE_IPF_CNTRST(n) (((n)&0x3)<<12)
+#define S3C_MDNIE_IPF_G(n) (((n)&0xF)<<8)
+#define S3C_MDNIE_IPF_T(n) (((n)&0xFF)<<0)
+
+//R43
+#define S3C_MDNIE_CS_SKIN_OFF (0<<10)
+#define S3C_MDNIE_CS_SKIN_ON (1<<10)
+#define S3C_MDNIE_CS_CONT(n) (((n)&0x3FF)<<0)
+
+//R45
+#define S3C_MDNIE_DE_TH(n) (((n)&0x3FF)<<0)
+
+//R48
+#define S3C_MDNIE_SN_LVL_0 (0<<10)
+#define S3C_MDNIE_SN_LVL_1 (1<<10)
+#define S3C_MDNIE_SN_LVL_2 (2<<10)
+#define S3C_MDNIE_SN_LVL_3 (3<<10)
+#define S3C_MDNIE_SY_LVL_0 (0<<8)
+#define S3C_MDNIE_SY_LVL_1 (1<<8)
+#define S3C_MDNIE_SY_LVL_2 (2<<8)
+#define S3C_MDNIE_SY_LVL_3 (3<<8)
+#define S3C_MDNIE_GR_LVL_0 (0<<6)
+#define S3C_MDNIE_GR_LVL_1 (1<<6)
+#define S3C_MDNIE_GR_LVL_2 (2<<6)
+#define S3C_MDNIE_GR_LVL_3 (3<<6)
+#define S3C_MDNIE_RD_LVL_0 (0<<4)
+#define S3C_MDNIE_RD_LVL_1 (1<<4)
+#define S3C_MDNIE_RD_LVL_2 (2<<4)
+#define S3C_MDNIE_RD_LVL_3 (3<<4)
+#define S3C_MDNIE_YE_LVL_0 (0<<2)
+#define S3C_MDNIE_YE_LVL_1 (1<<2)
+#define S3C_MDNIE_YE_LVL_2 (2<<2)
+#define S3C_MDNIE_YE_LVL_3 (3<<2)
+#define S3C_MDNIE_PU_LVL_0 (0<<0)
+#define S3C_MDNIE_PU_LVL_1 (1<<0)
+#define S3C_MDNIE_PU_LVL_2 (2<<0)
+#define S3C_MDNIE_PU_LVL_3 (3<<0)
+
+//R49
+#define S3C_MDNIE_SN_L1_TCB(n) (((n)&0xFF)<<8)
+#define S3C_MDNIE_SN_L2_TCB(n) (((n)&0xFF)<<0)
+//R50
+#define S3C_MDNIE_SN_L3_TCB(n) (((n)&0xFF)<<8)
+#define S3C_MDNIE_SN_L1_TCR(n) (((n)&0xFF)<<0)
+//R51
+#define S3C_MDNIE_SN_L2_TCR(n) (((n)&0xFF)<<8)
+#define S3C_MDNIE_SN_L3_TCR(n) (((n)&0xFF)<<0)
+//R52
+#define S3C_MDNIE_SN_L1_S(n) (((n)&0x7)<<6)
+#define S3C_MDNIE_SN_L2_S(n) (((n)&0x7)<<3)
+#define S3C_MDNIE_SN_L3_S(n) (((n)&0x7)<<0)
+//R53
+#define S3C_MDNIE_RD_L1_TCB(n) (((n)&0xFF)<<8)
+#define S3C_MDNIE_RD_L2_TCB(n) (((n)&0xFF)<<0)
+//R54
+#define S3C_MDNIE_RD_L3_TCB(n) (((n)&0xFF)<<8)
+#define S3C_MDNIE_RD_L1_TCR(n) (((n)&0xFF)<<0)
+//R55
+#define S3C_MDNIE_RD_L2_TCR(n) (((n)&0xFF)<<8)
+#define S3C_MDNIE_RD_L3_TCR(n) (((n)&0xFF)<<0)
+//R56
+#define S3C_MDNIE_RD_L1_S(n) (((n)&0x7)<<6)
+#define S3C_MDNIE_RD_L2_S(n) (((n)&0x7)<<3)
+#define S3C_MDNIE_RD_L3_S(n) (((n)&0x7)<<0)
+
+//R64
+#define S3C_MDNIE_LIGHT_P(n) (((n)&0xFF)<<8)
+#define S3C_MDNIE_CHROMA_P(n) (((n)&0xFF)<<0)
+//R65
+#define S3C_MDNIE_TRANSFUNL_1(n) (((n)&0x7F)<<8)
+#define S3C_MDNIE_TRANSFUNL_2(n) (((n)&0x7F)<<0)
+//R66
+#define S3C_MDNIE_TRANSFUNL_3(n) (((n)&0x7F)<<8)
+#define S3C_MDNIE_TRANSFUNL_4(n) (((n)&0x7F)<<0)
+//R67
+#define S3C_MDNIE_TRANSFUNL_5(n) (((n)&0x7F)<<8)
+#define S3C_MDNIE_TRANSFUNL_6(n) (((n)&0x7F)<<0)
+//R68
+#define S3C_MDNIE_TRANSFUNL_7(n) (((n)&0x7F)<<8)
+#define S3C_MDNIE_TRANSFUNL_8(n) (((n)&0x7F)<<0)
+//R69
+#define S3C_MDNIE_TRANSFUNL_9(n) (((n)&0x7F)<<8)
+
+//R72
+#define S3C_MDNIE_QUADRANT_OFF (0<<8)
+#define S3C_MDNIE_QUADRAND_ON (1<<8)
+#define S3C_MDNIE_COLOR_TEMP_DEST(n) ((((n)&0xFF)<<0)
+//R73
+#define S3C_MDNIE_COLOR_TEMP1(n) (((n)&0xFF)<<8)
+#define S3C_MDNIE_COLOR_TEMP2(n) (((n)&0xFF)<<0)
+//R74
+#define S3C_MDNIE_COLOR_TEMP3(n) (((n)&0xFF)<<8)
+#define S3C_MDNIE_COLOR_TEMP4(n) (((n)&0xFF)<<0)
+//R75
+#define S3C_MDNIE_COLOR_TEMP5(n) (((n)&0xFF)<<8)
+#define S3C_MDNIE_LSF1(n) (((n)&0xFF)<<0)
+//R76
+#define S3C_MDNIE_LSF2(n) (((n)&0xFF)<<8)
+#define S3C_MDNIE_LSF3(n) (((n)&0xFF)<<0)
+//R76
+#define S3C_MDNIE_LSF4(n) (((n)&0xFF)<<8)
+#define S3C_MDNIE_LSF5(n) (((n)&0xFF)<<0)
+//R78
+#define S3C_MDNIE_CT1_HIGH_CB(n) (((n)&0xFF)<<8)
+#define S3C_MDNIE_CT2_HIGH_CB(n) (((n)&0xFF)<<0)
+//R79
+#define S3C_MDNIE_CT3_HIGH_CB(n) (((n)&0xFF)<<8)
+#define S3C_MDNIE_CT4_HIGH_CB(n) (((n)&0xFF)<<0)
+//R80
+#define S3C_MDNIE_CT5_HIGH_CB(n) (((n)&0xFF)<<8)
+#define S3C_MDNIE_CT1_HIGH_CR(n) (((n)&0xFF)<<0)
+//R81
+#define S3C_MDNIE_CT2_HIGH_CR(n) (((n)&0xFF)<<8)
+#define S3C_MDNIE_CT3_HIGH_CR(n) (((n)&0xFF)<<0)
+//R82
+#define S3C_MDNIE_CT4_HIGH_CR(n) (((n)&0xFF)<<8)
+#define S3C_MDNIE_CT5_HIGH_CR(n) (((n)&0xFF)<<0)
+//R83
+#define S3C_MDNIE_GRAY_AXIS_LONG(n) (((n)&0xFF)<<8)
+#define S3C_MDNIE_GRAY_AXIS_SHORT(n) (((n)&0xFF)<<0)
+//R84
+#define S3C_MDNIE_GRAY_ANGLE_COS(n) (((n)&0x3ff)<<0)
+//R85
+#define S3C_MDNIE_GRAY_ANGLE_SIN(n) (((n)&0x3ff)<<0)
+//R86
+#define S3C_MDNIE_QUADRANT_TMP1(n) (((n)&0xFF)<<8)
+#define S3C_MDNIE_QUADRANT_TMP2(n) (((n)&0xFF)<<0)
+//R87
+#define S3C_MDNIE_QUADRANT_TMP3(n) (((n)&0xFF)<<8)
+#define S3C_MDNIE_QUADRANT_TMP4(n) (((n)&0xFF)<<0)
+
+//R88
+#define S3C_MDNIE_FGain_LUT0(n) (((n)&0x7F)<<8)
+#define S3C_MDNIE_FGain_LUT1(n) (((n)&0x7F)<<0)
+//R89
+#define S3C_MDNIE_FGain_LUT2(n) (((n)&0x7F)<<8)
+#define S3C_MDNIE_FGain_LUT3(n) (((n)&0x7F)<<0)
+//R90
+#define S3C_MDNIE_FGain_LUT4(n) (((n)&0x7F)<<8)
+#define S3C_MDNIE_FGain_LUT5(n) (((n)&0x7F)<<0)
+//R91
+#define S3C_MDNIE_FGain_LUT6(n) (((n)&0x7F)<<8)
+#define S3C_MDNIE_FGain_LUT7(n) (((n)&0x7F)<<0)
+//R92
+#define S3C_MDNIE_DGain_LUT0(n) (((n)&0x7F)<<8)
+#define S3C_MDNIE_DGain_LUT1(n) (((n)&0x7F)<<0)
+//R93
+#define S3C_MDNIE_DGain_LUT2(n) (((n)&0x7F)<<8)
+#define S3C_MDNIE_DGain_LUT3(n) (((n)&0x7F)<<0)
+//R94
+#define S3C_MDNIE_DGain_LUT4(n) (((n)&0x7F)<<8)
+#define S3C_MDNIE_DGain_LUT5(n) (((n)&0x7F)<<0)
+//R95
+#define S3C_MDNIE_DGain_LUT6(n) (((n)&0x7F)<<8)
+#define S3C_MDNIE_DGain_LUT7(n) (((n)&0x7F)<<0)
+//R96
+#define S3C_MDNIE_Power_LUT0(n) (((n)&0x7F)<<8)
+#define S3C_MDNIE_Power_LUT1(n) (((n)&0x7F)<<0)
+//R97
+#define S3C_MDNIE_Power_LUT2(n) (((n)&0x7F)<<8)
+#define S3C_MDNIE_Power_LUT3(n) (((n)&0x7F)<<0)
+//R98
+#define S3C_MDNIE_Power_LUT4(n) (((n)&0x7F)<<8)
+#define S3C_MDNIE_Power_LUT5(n) (((n)&0x7F)<<0)
+//R99
+#define S3C_MDNIE_Power_LUT6(n) (((n)&0x7F)<<8)
+#define S3C_MDNIE_Power_LUT7(n) (((n)&0x7F)<<0)
+//R100
+#define S3C_MDNIE_Power_LUT8(n) (((n)&0x7F)<<8)
+
+//R101
+#define S3C_MDNIE_ZONAL_PARA0(n) (((n)&0x3)<<4)
+#define S3C_MDNIE_ZONAL_PARA1(n) (((n)&0x3)<<0)
+//R102
+#define S3C_MDNIE_BLU_DISABLE (0<<1)
+#define S3C_MDNIE_BLU_ENABLE (1<<1)
+#define S3C_MDNIE_DISPLAY_LCD (0<<0)
+#define S3C_MDNIE_DISPLAY_OLED (1<<0)
+
+//R103
+#define S3C_MDNIE_PWM_PHIGH (1<<15)
+#define S3C_MDNIE_PWM_PLOW (0<<15)
+#define S3C_MDNIE_PWM_CT_LPA (0<<14) // using LPA counter
+#define S3C_MDNIE_PWM_CT_PWM (1<<14) // using PWM counter
+#define S3C_MDNIE_PWM_CT(n) (((n)&0x3F)<<0)
+
+
+
+
+#define SIG_MDNIE_UI_MODE 0
+#define SIG_MDNIE_VIDEO_MODE 1
+#define SIG_MDNIE_VIDEO_WARM_MODE 2
+#define SIG_MDNIE_VIDEO_COLD_MODE 3
+#define SIG_MDNIE_CAMERA_MODE 4
+#define SIG_MDNIE_NAVI 5
+
+
+int s3c_mdnie_init(void);
+int s3c_mdnie_enable(void);
+int s3c_mdnie_disable(void);
+int s3c_mdnie_control(int cmd, void * arg);
+
+
+int s3c_mdnie_setup(void);
+
+int s3c_mdnie_init_global(struct s3cfb_global *s3cfb_ctrl);
+
+int s3c_mdnie_start(struct s3cfb_global *ctrl);
+int s3c_mdnie_off(void);
+int s3c_mdnie_stop(void);
+extern void mDNIe_Mode_Set(void);
+
+#endif
diff --git a/drivers/video/samsung/s3cfb_nt35580.c b/drivers/video/samsung/s3cfb_nt35580.c
new file mode 100755
index 0000000..3a76083
--- /dev/null
+++ b/drivers/video/samsung/s3cfb_nt35580.c
@@ -0,0 +1,273 @@
+/*
+ * nt35580 TFT Panel Driver for the Samsung Universal board
+ *
+ * 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/wait.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/lcd.h>
+#include <linux/backlight.h>
+#include <linux/nt35580.h>
+#include <plat/gpio-cfg.h>
+#include <plat/regs-fb.h>
+#include <linux/earlysuspend.h>
+
+#define NT35580_POWERON_DELAY 150
+
+struct s5p_lcd {
+ int ldi_enable;
+ int bl;
+ struct mutex lock;
+ struct device *dev;
+ struct spi_device *g_spi;
+ struct s5p_tft_panel_data *data;
+ struct backlight_device *bl_dev;
+ struct early_suspend early_suspend;
+};
+
+static int nt35580_spi_write_driver(struct s5p_lcd *lcd, u16 reg)
+{
+ u16 buf;
+ int ret;
+ struct spi_message msg;
+
+ struct spi_transfer xfer = {
+ .len = 2,
+ .tx_buf = &buf,
+ };
+
+ buf = reg;
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfer, &msg);
+
+ ret = spi_sync(lcd->g_spi, &msg);
+
+ if (ret < 0)
+ pr_err("%s: error: spi_sync (%d)", __func__, ret);
+
+ return ret;
+}
+
+static void nt35580_panel_send_sequence(struct s5p_lcd *lcd,
+ const u16 *wbuf)
+{
+ int i = 0;
+
+ while ((wbuf[i] & DEFMASK) != ENDDEF)
+ if ((wbuf[i] & DEFMASK) != SLEEPMSEC) {
+ nt35580_spi_write_driver(lcd, wbuf[i]);
+ i += 1;
+ } else {
+ msleep(wbuf[i+1]);
+ i += 2;
+ }
+}
+
+static void update_brightness(struct s5p_lcd *lcd, int level)
+{
+ struct s5p_tft_panel_data *pdata = lcd->data;
+
+ pdata->brightness_set[pdata->pwm_reg_offset] = 0x100 | (level & 0xff);
+
+ nt35580_panel_send_sequence(lcd, pdata->brightness_set);
+}
+
+static void nt35580_ldi_enable(struct s5p_lcd *lcd)
+{
+ struct s5p_tft_panel_data *pdata = lcd->data;
+
+ mutex_lock(&lcd->lock);
+
+ msleep(NT35580_POWERON_DELAY);
+
+ nt35580_panel_send_sequence(lcd, pdata->seq_set);
+ update_brightness(lcd, lcd->bl);
+ nt35580_panel_send_sequence(lcd, pdata->display_on);
+
+ lcd->ldi_enable = 1;
+
+ mutex_unlock(&lcd->lock);
+}
+
+static void nt35580_ldi_disable(struct s5p_lcd *lcd)
+{
+ struct s5p_tft_panel_data *pdata = lcd->data;
+
+ mutex_lock(&lcd->lock);
+
+ lcd->ldi_enable = 0;
+ nt35580_panel_send_sequence(lcd, pdata->display_off);
+ nt35580_panel_send_sequence(lcd, pdata->sleep_in);
+
+ mutex_unlock(&lcd->lock);
+}
+
+static int s5p_bl_update_status(struct backlight_device *bd)
+{
+ struct s5p_lcd *lcd = bl_get_data(bd);
+ int bl = bd->props.brightness;
+
+ pr_debug("\nupdate status brightness %d\n",
+ bd->props.brightness);
+
+ if (bl < 0 || bl > 255)
+ return -EINVAL;
+
+ mutex_lock(&lcd->lock);
+
+ lcd->bl = bl;
+
+ if (lcd->ldi_enable) {
+ pr_debug("\n bl :%d\n", bl);
+ update_brightness(lcd, bl);
+ }
+
+ mutex_unlock(&lcd->lock);
+
+ return 0;
+}
+
+const struct backlight_ops s5p_bl_tft_ops = {
+ .update_status = s5p_bl_update_status,
+};
+
+void nt35580_early_suspend(struct early_suspend *h)
+{
+ struct s5p_lcd *lcd = container_of(h, struct s5p_lcd,
+ early_suspend);
+
+ nt35580_ldi_disable(lcd);
+
+ return;
+}
+void nt35580_late_resume(struct early_suspend *h)
+{
+ struct s5p_lcd *lcd = container_of(h, struct s5p_lcd,
+ early_suspend);
+
+ nt35580_ldi_enable(lcd);
+
+ return;
+}
+static int __devinit nt35580_probe(struct spi_device *spi)
+{
+ struct s5p_lcd *lcd;
+ int ret;
+
+ lcd = kzalloc(sizeof(*lcd), GFP_KERNEL);
+ if (!lcd) {
+ pr_err("failed to allocate for lcd\n");
+ ret = -ENOMEM;
+ goto err_alloc;
+ }
+ mutex_init(&lcd->lock);
+
+ spi->bits_per_word = 9;
+ if (spi_setup(spi)) {
+ pr_err("failed to setup spi\n");
+ ret = -EINVAL;
+ goto err_setup;
+ }
+
+ lcd->g_spi = spi;
+ lcd->dev = &spi->dev;
+ lcd->bl = 255;
+
+ if (!spi->dev.platform_data) {
+ dev_err(lcd->dev, "failed to get platform data\n");
+ ret = -EINVAL;
+ goto err_setup;
+ }
+ lcd->data = (struct s5p_tft_panel_data *)spi->dev.platform_data;
+
+ if (!lcd->data->seq_set || !lcd->data->display_on ||
+ !lcd->data->display_off || !lcd->data->sleep_in ||
+ !lcd->data->brightness_set || !lcd->data->pwm_reg_offset) {
+ dev_err(lcd->dev, "Invalid platform data\n");
+ ret = -EINVAL;
+ goto err_setup;
+ }
+
+ lcd->bl_dev = backlight_device_register("s5p_bl",
+ &spi->dev, lcd, &s5p_bl_tft_ops, NULL);
+ if (!lcd->bl_dev) {
+ dev_err(lcd->dev, "failed to register backlight\n");
+ ret = -EINVAL;
+ goto err_setup;
+ }
+
+ lcd->bl_dev->props.max_brightness = 255;
+ lcd->bl_dev->props.brightness = lcd->bl;
+ spi_set_drvdata(spi, lcd);
+
+ lcd->ldi_enable = 1;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ lcd->early_suspend.suspend = nt35580_early_suspend;
+ lcd->early_suspend.resume = nt35580_late_resume;
+ lcd->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 1;
+ register_early_suspend(&lcd->early_suspend);
+#endif
+ pr_info("%s successfully probed\n", __func__);
+
+ return 0;
+
+err_setup:
+ mutex_destroy(&lcd->lock);
+ kfree(lcd);
+
+err_alloc:
+ return ret;
+}
+
+static int __devexit nt35580_remove(struct spi_device *spi)
+{
+ struct s5p_lcd *lcd = spi_get_drvdata(spi);
+
+ unregister_early_suspend(&lcd->early_suspend);
+
+ backlight_device_unregister(lcd->bl_dev);
+
+ nt35580_ldi_disable(lcd);
+
+ kfree(lcd);
+
+ return 0;
+}
+
+static struct spi_driver nt35580_driver = {
+ .driver = {
+ .name = "nt35580",
+ .owner = THIS_MODULE,
+ },
+ .probe = nt35580_probe,
+ .remove = __devexit_p(nt35580_remove),
+};
+
+static int __init nt35580_init(void)
+{
+ return spi_register_driver(&nt35580_driver);
+}
+static void __exit nt35580_exit(void)
+{
+ spi_unregister_driver(&nt35580_driver);
+}
+
+module_init(nt35580_init);
+module_exit(nt35580_exit);
diff --git a/drivers/video/samsung/s3cfb_tl2796.c b/drivers/video/samsung/s3cfb_tl2796.c
new file mode 100755
index 0000000..597cc6b
--- /dev/null
+++ b/drivers/video/samsung/s3cfb_tl2796.c
@@ -0,0 +1,1221 @@
+/*
+ * s6e63m0 AMOLED Panel Driver for the Samsung Universal board
+ *
+ * Derived from drivers/video/omap/lcd-apollon.c
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/wait.h>
+#include <linux/fb.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/seq_file.h>
+#include <linux/spi/spi.h>
+#include <linux/lcd.h>
+#include <linux/backlight.h>
+#include <linux/tl2796.h>
+#include <plat/gpio-cfg.h>
+#include <plat/regs-fb.h>
+#include <linux/earlysuspend.h>
+#ifdef CONFIG_FB_VOODOO
+#include <linux/miscdevice.h>
+#define VOODOO_COLOR_VERSION 3
+#endif
+
+#define SLEEPMSEC 0x1000
+#define ENDDEF 0x2000
+#define DEFMASK 0xFF00
+
+#define NUM_GAMMA_REGS 21
+
+static const struct tl2796_gamma_adj_points default_gamma_adj_points = {
+ .v0 = BV_0,
+ .v1 = BV_1,
+ .v19 = BV_19,
+ .v43 = BV_43,
+ .v87 = BV_87,
+ .v171 = BV_171,
+ .v255 = BV_255,
+};
+
+struct tl2796_gamma_reg_offsets {
+ s16 v[3][6];
+};
+
+struct s5p_lcd{
+ int ldi_enable;
+ int bl;
+ const struct tl2796_gamma_adj_points *gamma_adj_points;
+ struct tl2796_gamma_reg_offsets gamma_reg_offsets;
+ u32 color_mult[3];
+ struct mutex lock;
+ struct device *dev;
+ struct spi_device *g_spi;
+ struct s5p_panel_data *data;
+ struct backlight_device *bl_dev;
+ struct early_suspend early_suspend;
+ struct dentry *debug_dir;
+};
+
+#ifdef CONFIG_FB_VOODOO
+struct s5p_lcd *lcd_;
+
+u32 original_color_adj_mults[3];
+unsigned int panel_config_sequence = 0;
+
+int hacky_v1_offset[3] = {0, 0, 0};
+
+static const u16 s6e63m0_SEQ_ETC_SETTING_SAMSUNG[] = {
+ /* ETC Condition Set Command */
+ 0x0F6,
+ 0x100, 0x18E,
+ 0x107,
+ 0x0B3,
+ 0x16C,
+ 0x0B5,
+ 0x12C, 0x112,
+ 0x10C, 0x10A,
+ 0x110, 0x10E,
+ 0x117, 0x113,
+ 0x11F, 0x11A,
+ 0x12A, 0x124,
+ 0x11F, 0x11B,
+ 0x11A, 0x117,
+ 0x12B, 0x126,
+ 0x122, 0x120,
+ 0x13A, 0x134,
+ 0x130, 0x12C,
+ 0x129, 0x126,
+ 0x125, 0x123,
+ 0x121, 0x120,
+ 0x11E, 0x11E,
+ 0x0B6,
+ 0x100, 0x100,
+ 0x111, 0x122,
+ 0x133, 0x144,
+ 0x144, 0x144,
+ 0x155, 0x155,
+ 0x166, 0x166,
+ 0x166, 0x166,
+ 0x166, 0x166,
+ 0x0B7,
+ 0x12C, 0x112,
+ 0x10C, 0x10A,
+ 0x110, 0x10E,
+ 0x117, 0x113,
+ 0x11F, 0x11A,
+ 0x12A, 0x124,
+ 0x11F, 0x11B,
+ 0x11A, 0x117,
+ 0x12B, 0x126,
+ 0x122, 0x120,
+ 0x13A, 0x134,
+ 0x130, 0x12C,
+ 0x129, 0x126,
+ 0x125, 0x123,
+ 0x121, 0x120,
+ 0x11E, 0x11E,
+ 0x0B8,
+ 0x100, 0x100,
+ 0x111, 0x122,
+ 0x133, 0x144,
+ 0x144, 0x144,
+ 0x155, 0x155,
+ 0x166, 0x166,
+ 0x166, 0x166,
+ 0x166, 0x166,
+ 0x0B9,
+ 0x12C, 0x112,
+ 0x10C, 0x10A,
+ 0x110, 0x10E,
+ 0x117, 0x113,
+ 0x11F, 0x11A,
+ 0x12A, 0x124,
+ 0x11F, 0x11B,
+ 0x11A, 0x117,
+ 0x12B, 0x126,
+ 0x122, 0x120,
+ 0x13A, 0x134,
+ 0x130, 0x12C,
+ 0x129, 0x126,
+ 0x125, 0x123,
+ 0x121, 0x120,
+ 0x11E, 0x11E,
+ 0x0BA,
+ 0x100, 0x100,
+ 0x111, 0x122,
+ 0x133, 0x144,
+ 0x144, 0x144,
+ 0x155, 0x155,
+ 0x166, 0x166,
+ 0x166, 0x166,
+ 0x166, 0x166,
+ 0x011,
+ SLEEPMSEC, 120,
+ 0x029,
+ ENDDEF, 0x0000
+};
+#endif
+
+static u32 gamma_lookup(struct s5p_lcd *lcd, u8 brightness, u32 val, int c)
+{
+ // c color (red, green, blue)
+ // val brightness value (BV_0, BV_1, BV_19, BV_43, BV_87, BV_171, BV_255)
+ // b brightness value divided by brightness level
+
+ // bl brightness range - low
+ // bh brightness range - high
+
+ // vl gamma table range - low
+ // vh gamma table range - high
+
+ // ret return value from the gamma table
+
+ int i;
+ u32 bl = 0;
+ u32 bh = 0;
+ u32 vl = 0;
+ u32 vh;
+ u32 b;
+ u32 ret;
+ u64 tmp;
+ struct s5p_panel_data *pdata = lcd->data;
+ const struct tl2796_gamma_adj_points *bv = lcd->gamma_adj_points;
+
+ if (!val) {
+ b = 0;
+ } else {
+ tmp = bv->v255 - bv->v0;
+ tmp *= brightness;
+ do_div(tmp, 255);
+
+ tmp *= lcd->color_mult[c];
+ do_div(tmp, 0xffffffff);
+
+ tmp *= (val - bv->v0);
+ do_div(tmp, bv->v255 - bv->v0);
+ b = tmp + bv->v0;
+ }
+
+ // find which entry of the gamma table fits for val
+ // as a result, i becomes the index in the gamma table for val and color c
+ for (i = 0; i < pdata->gamma_table_size; i++) {
+ bl = bh;
+ bh = pdata->gamma_table[i].brightness;
+ if (bh >= b)
+ break;
+ }
+
+ // save corresponding value from the gamma table as vh
+ // high value of the range
+ vh = pdata->gamma_table[i].v[c];
+
+ // for special black point and gamma 0 (i==0 or i==1), return value
+ // is static. vl = vh = same as the value in gamma table for i
+ if (i == 0 || (b - bl) == 0) {
+ ret = vl = vh;
+ } else {
+ // simple proportional calculation of ret
+ // based on vl and vh from gamma table ranges
+ vl = pdata->gamma_table[i - 1].v[c];
+ tmp = (u64)vh * (b - bl) + (u64)vl * (bh - b);
+ do_div(tmp, bh - bl);
+ ret = tmp;
+ }
+
+ pr_debug("%s: looking for %3d %08x c %d, %08x, "
+ "found %08x:%08x, v %7d:%7d, ret %7d\n",
+ __func__, brightness, val, c, b, bl, bh, vl, vh, ret);
+
+ return ret;
+}
+
+static void setup_gamma_regs(struct s5p_lcd *lcd, u16 gamma_regs[])
+{
+ int c, i;
+ u8 brightness = lcd->bl;
+ const struct tl2796_gamma_adj_points *bv = lcd->gamma_adj_points;
+
+ // red, green then blue
+ for (c = 0; c < 3; c++) {
+ // initialize v0 (black point) from the gamma table
+ // vx are gamma points 1 to 4.
+ // adj becomes one of the value sent to the panel
+ u32 adj;
+ u32 v0 = gamma_lookup(lcd, brightness, BV_0, c);
+ u32 vx[6];
+ u32 v1;
+ u32 v255;
+
+ // calculate gamma 0 value, based on v0 and v1
+ v1 = vx[0] = gamma_lookup(lcd, brightness, bv->v1, c);
+ adj = 600 - 5 - DIV_ROUND_CLOSEST(600 * v1, v0);
+ adj -= lcd->gamma_reg_offsets.v[c][0];
+ if (adj > 140) {
+ pr_debug("%s: bad adj value %d, v0 %d, v1 %d, c %d\n",
+ __func__, adj, v0, v1, c);
+ if ((int)adj < 0)
+ adj = 0;
+ else
+ adj = 140;
+ }
+ // record gamma 0
+#ifdef CONFIG_FB_VOODOO
+ // terrible shameful hack allowing to get back standard
+ // colors without fixing the real thing properly (gamma table)
+ // it consist on a simple (negative) offset applied on v0
+ int adj_hack = adj + ((hacky_v1_offset[c] * (int)adj) / 100);
+ if (adj_hack > 140)
+ adj_hack = 140;
+ gamma_regs[c] = adj_hack | 0x100;
+#else
+ gamma_regs[c] = adj | 0x100;
+#endif
+
+ // calculate brightness value for color c
+ v255 = vx[5] = gamma_lookup(lcd, brightness, bv->v255, c);
+ adj = 600 - 120 - DIV_ROUND_CLOSEST(600 * v255, v0);
+ adj -= lcd->gamma_reg_offsets.v[c][5];
+ if (adj > 380) {
+ pr_debug("%s: bad adj value %d, v0 %d, v255 %d, c %d\n",
+ __func__, adj, v0, v255, c);
+ if ((int)adj < 0)
+ adj = 0;
+ else
+ adj = 380;
+ }
+ // command to set brightness value for color c: always 0x100
+ gamma_regs[3 * 5 + 2 * c] = adj >> 8 | 0x100;
+ // record brightness value for color c = adj
+ gamma_regs[3 * 5 + 2 * c + 1] = (adj & 0xff) | 0x100;
+
+ vx[1] = gamma_lookup(lcd, brightness, bv->v19, c);
+ vx[2] = gamma_lookup(lcd, brightness, bv->v43, c);
+ vx[3] = gamma_lookup(lcd, brightness, bv->v87, c);
+ vx[4] = gamma_lookup(lcd, brightness, bv->v171, c);
+
+ // calculate gamma points 4 to 1 successively
+ // those are calculated from vx[4] to vx[1], based on
+ // gamma table values chosen to follow current brightness
+ for (i = 4; i >= 1; i--) {
+ if (v1 <= vx[i + 1]) {
+ adj = -1;
+ } else {
+ // actual calculation
+ adj = DIV_ROUND_CLOSEST(320 * (v1 - vx[i]),
+ v1 - vx[i + 1]) - 65;
+ // new in 2.3.3: offset value based on mtp
+ // offsets are calculated from screen hardware
+ // readings in tl2796_read_mtp_info()
+ adj -= lcd->gamma_reg_offsets.v[c][i];
+ }
+ if (adj > 255) {
+ pr_debug("%s: bad adj value %d, "
+ "vh %d, v %d, c %d\n",
+ __func__, adj, vx[i + 1], vx[i], c);
+ if ((int)adj < 0)
+ adj = 0;
+ else
+ adj = 255;
+ }
+ gamma_regs[3 * i + c] = adj | 0x100;
+ }
+ }
+}
+
+static int s6e63m0_spi_write_driver(struct s5p_lcd *lcd, u16 reg)
+{
+ u16 buf[1];
+ int ret;
+ struct spi_message msg;
+
+ struct spi_transfer xfer = {
+ .len = 2,
+ .tx_buf = buf,
+ };
+
+ buf[0] = reg;
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfer, &msg);
+
+ ret = spi_sync(lcd->g_spi, &msg);
+
+ if (ret < 0)
+ pr_err("%s error\n", __func__);
+
+ return ret ;
+}
+
+#ifdef CONFIG_FB_VOODOO_DEBUG_LOG
+static void voodoo_print_decoded_commands(short unsigned int commands_record[], int i)
+{
+ if (i == 25)
+ {
+ printk("Super AMOLED commands decoding:\n");
+ printk("Brightness gains: Red = %3d, Green = %3d, Blue = %3d\n",
+ commands_record[18]-256, commands_record[20]-256, commands_record[22]-256);
+ printk("Gamma 0: Red = %3d, Green = %3d, Blue = %3d\n",
+ commands_record[2]-256, commands_record[3]-256, commands_record[4]-256);
+ printk("Gamma 1: Red = %3d, Green = %3d, Blue = %3d\n",
+ commands_record[5]-256, commands_record[6]-256, commands_record[7]-256);
+ printk("Gamma 2: Red = %3d, Green = %3d, Blue = %3d\n",
+ commands_record[8]-256, commands_record[9]-256, commands_record[10]-256);
+ printk("Gamma 3: Red = %3d, Green = %3d, Blue = %3d\n",
+ commands_record[11]-256, commands_record[12]-256, commands_record[13]-256);
+ printk("Gamma 4: Red = %3d, Green = %3d, Blue = %3d\n",
+ commands_record[14]-256, commands_record[15]-256, commands_record[16]-256);
+ }
+
+}
+#endif
+
+static void s6e63m0_panel_send_sequence(struct s5p_lcd *lcd,
+ const u16 *wbuf)
+{
+ int i = 0;
+
+#ifdef CONFIG_FB_VOODOO_DEBUG_LOG
+ short unsigned int commands_record[256];
+ printk("Beginning sending commands to the Super AMOLED panel:\n");
+#endif
+
+ while ((wbuf[i] & DEFMASK) != ENDDEF) {
+ if ((wbuf[i] & DEFMASK) != SLEEPMSEC) {
+ s6e63m0_spi_write_driver(lcd, wbuf[i]);
+#ifdef CONFIG_FB_VOODOO_DEBUG_LOG
+ printk("%3d = %5d - 0x%X\n", i, wbuf[i], wbuf[i]);
+ commands_record[i] = wbuf[i];
+#endif
+ i += 1;
+ } else {
+ msleep(wbuf[i+1]);
+ i += 2;
+ }
+ }
+#ifdef CONFIG_FB_VOODOO_DEBUG_LOG
+ voodoo_print_decoded_commands(commands_record, i);
+#endif
+}
+
+static void update_brightness(struct s5p_lcd *lcd)
+{
+ u16 gamma_regs[27];
+
+ gamma_regs[0] = 0x0FA;
+ gamma_regs[1] = 0x102;
+ gamma_regs[23] = 0x0FA;
+ gamma_regs[24] = 0x103;
+ gamma_regs[25] = ENDDEF;
+ gamma_regs[26] = 0x0000;
+
+ setup_gamma_regs(lcd, gamma_regs + 2);
+
+ s6e63m0_panel_send_sequence(lcd, gamma_regs);
+}
+
+static void tl2796_ldi_enable(struct s5p_lcd *lcd)
+{
+ struct s5p_panel_data *pdata = lcd->data;
+
+ mutex_lock(&lcd->lock);
+
+ s6e63m0_panel_send_sequence(lcd, pdata->seq_display_set);
+ update_brightness(lcd);
+#ifdef CONFIG_FB_VOODOO
+ if (panel_config_sequence == 1)
+ s6e63m0_panel_send_sequence(lcd, pdata->seq_etc_set);
+ else
+ s6e63m0_panel_send_sequence(lcd, s6e63m0_SEQ_ETC_SETTING_SAMSUNG);
+#else
+ s6e63m0_panel_send_sequence(lcd, pdata->seq_etc_set);
+#endif
+ lcd->ldi_enable = 1;
+
+ mutex_unlock(&lcd->lock);
+}
+
+static void tl2796_ldi_disable(struct s5p_lcd *lcd)
+{
+ struct s5p_panel_data *pdata = lcd->data;
+
+ mutex_lock(&lcd->lock);
+
+ lcd->ldi_enable = 0;
+ s6e63m0_panel_send_sequence(lcd, pdata->standby_on);
+
+ mutex_unlock(&lcd->lock);
+}
+
+static int s5p_bl_update_status(struct backlight_device *bd)
+{
+ struct s5p_lcd *lcd = bl_get_data(bd);
+ int bl = bd->props.brightness;
+
+ pr_debug("\nupdate status brightness %d\n",
+ bd->props.brightness);
+
+ if (bl < 0 || bl > 255)
+ return -EINVAL;
+
+ mutex_lock(&lcd->lock);
+
+ lcd->bl = bl;
+
+ if (lcd->ldi_enable) {
+ pr_debug("\n bl :%d\n", bl);
+ update_brightness(lcd);
+ }
+
+ mutex_unlock(&lcd->lock);
+
+ return 0;
+}
+
+const struct backlight_ops s5p_bl_ops = {
+ .update_status = s5p_bl_update_status,
+};
+
+void tl2796_early_suspend(struct early_suspend *h)
+{
+ struct s5p_lcd *lcd = container_of(h, struct s5p_lcd,
+ early_suspend);
+
+ tl2796_ldi_disable(lcd);
+
+ return ;
+}
+void tl2796_late_resume(struct early_suspend *h)
+{
+ struct s5p_lcd *lcd = container_of(h, struct s5p_lcd,
+ early_suspend);
+
+ tl2796_ldi_enable(lcd);
+
+ return ;
+}
+
+static void seq_print_gamma_regs(struct seq_file *m, const u16 gamma_regs[])
+{
+ struct s5p_lcd *lcd = m->private;
+ int c, i;
+ const int adj_points[] = { 1, 19, 43, 87, 171, 255 };
+ const char color[] = { 'R', 'G', 'B' };
+ u8 brightness = lcd->bl;
+ const struct tl2796_gamma_adj_points *bv = lcd->gamma_adj_points;
+ const struct tl2796_gamma_reg_offsets *offset = &lcd->gamma_reg_offsets;
+
+ for (c = 0; c < 3; c++) {
+ // vt values are the direct result of gamma table lookups
+ // for a given brightness level and an adjustement point
+
+ // adj values correspond to what is sent to the the screen
+ // for each adjustement points
+
+ // v is ?
+
+ u32 adj[6];
+ u32 vt[6];
+ u32 v[6];
+ int scale = gamma_lookup(lcd, brightness, BV_0, c);
+
+ vt[0] = gamma_lookup(lcd, brightness, bv->v1, c);
+ vt[1] = gamma_lookup(lcd, brightness, bv->v19, c);
+ vt[2] = gamma_lookup(lcd, brightness, bv->v43, c);
+ vt[3] = gamma_lookup(lcd, brightness, bv->v87, c);
+ vt[4] = gamma_lookup(lcd, brightness, bv->v171, c);
+ vt[5] = gamma_lookup(lcd, brightness, bv->v255, c);
+
+ adj[0] = gamma_regs[c] & 0xff;
+ v[0] = DIV_ROUND_CLOSEST(
+ (600 - 5 - adj[0] - offset->v[c][0]) * scale, 600);
+
+ adj[5] = gamma_regs[3 * 5 + 2 * c] & 0xff;
+ adj[5] = adj[5] << 8 | (gamma_regs[3 * 5 + 2 * c + 1] & 0xff);
+ v[5] = DIV_ROUND_CLOSEST(
+ (600 - 120 - adj[5] - offset->v[c][5]) * scale, 600);
+
+ for (i = 4; i >= 1; i--) {
+ adj[i] = gamma_regs[3 * i + c] & 0xff;
+ v[i] = v[0] - DIV_ROUND_CLOSEST((v[0] - v[i + 1]) *
+ (65 + adj[i] + offset->v[c][i]), 320);
+ }
+ seq_printf(m, "%c v0 %7d\n",
+ color[c], scale);
+ for (i = 0; i < 6; i++) {
+ seq_printf(m, "%c adj %3d (%02x) %+4d "
+ "v%-3d %7d - %7d %+8d\n",
+ color[c], adj[i], adj[i], offset->v[c][i],
+ adj_points[i], v[i], vt[i], v[i] - vt[i]);
+ }
+ }
+}
+
+static int tl2796_current_gamma_show(struct seq_file *m, void *unused)
+{
+ struct s5p_lcd *lcd = m->private;
+ u16 gamma_regs[NUM_GAMMA_REGS];
+
+ mutex_lock(&lcd->lock);
+ setup_gamma_regs(lcd, gamma_regs);
+ seq_printf(m, "brightness %3d:\n", lcd->bl);
+ seq_print_gamma_regs(m, gamma_regs);
+ mutex_unlock(&lcd->lock);
+ return 0;
+}
+
+static int tl2796_current_gamma_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, tl2796_current_gamma_show, inode->i_private);
+}
+
+static const struct file_operations tl2796_current_gamma_fops = {
+ .open = tl2796_current_gamma_open,
+ .read = seq_read,
+ .release = single_release,
+};
+
+static void tl2796_parallel_read(struct s5p_lcd *lcd, u8 cmd,
+ u8 *data, size_t len)
+{
+ int i;
+ struct s5p_panel_data *pdata = lcd->data;
+ int delay = 10;
+
+ gpio_set_value(pdata->gpio_dcx, 0);
+ udelay(delay);
+ gpio_set_value(pdata->gpio_wrx, 0);
+ for (i = 0; i < 8; i++)
+ gpio_direction_output(pdata->gpio_db[i], (cmd >> i) & 1);
+ udelay(delay);
+ gpio_set_value(pdata->gpio_wrx, 1);
+ udelay(delay);
+ gpio_set_value(pdata->gpio_dcx, 1);
+ for (i = 0; i < 8; i++)
+ gpio_direction_input(pdata->gpio_db[i]);
+
+ udelay(delay);
+ gpio_set_value(pdata->gpio_rdx, 0);
+ udelay(delay);
+ gpio_set_value(pdata->gpio_rdx, 1);
+ udelay(delay);
+
+ while (len--) {
+ u8 d = 0;
+ gpio_set_value(pdata->gpio_rdx, 0);
+ udelay(delay);
+ for (i = 0; i < 8; i++)
+ d |= gpio_get_value(pdata->gpio_db[i]) << i;
+ *data++ = d;
+ gpio_set_value(pdata->gpio_rdx, 1);
+ udelay(delay);
+ }
+ gpio_set_value(pdata->gpio_rdx, 1);
+}
+
+static int tl2796_parallel_setup_gpios(struct s5p_lcd *lcd, bool init)
+{
+ int ret;
+ struct s5p_panel_data *pdata = lcd->data;
+
+ if (!pdata->configure_mtp_gpios)
+ return -EINVAL;
+
+ if (init) {
+ ret = pdata->configure_mtp_gpios(pdata, true);
+ if (ret)
+ return ret;
+
+ gpio_direction_output(pdata->gpio_wrx, 1);
+ gpio_direction_output(pdata->gpio_rdx, 1);
+ gpio_direction_output(pdata->gpio_dcx, 0);
+ gpio_direction_output(pdata->gpio_csx, 0);
+ } else {
+ gpio_set_value(pdata->gpio_csx, 1);
+ pdata->configure_mtp_gpios(pdata, false);
+ }
+ return 0;
+}
+
+static u64 tl2796_voltage_lookup(struct s5p_lcd *lcd, int c, u32 v)
+{
+ int i;
+ u32 vh = ~0, vl = ~0;
+ u32 bl, bh = 0;
+ u64 ret;
+ struct s5p_panel_data *pdata = lcd->data;
+
+ for (i = 0; i < pdata->gamma_table_size; i++) {
+ vh = vl;
+ vl = pdata->gamma_table[i].v[c];
+ bh = bl;
+ bl = pdata->gamma_table[i].brightness;
+ if (vl <= v)
+ break;
+ }
+ if (i == 0 || (v - vl) == 0) {
+ ret = bl;
+ } else {
+ ret = (u64)bh * (s32)(v - vl) + (u64)bl * (vh - v);
+ do_div(ret, vh - vl);
+ }
+ pr_debug("%s: looking for %7d c %d, "
+ "found %7d:%7d, b %08x:%08x, ret %08llx\n",
+ __func__, v, c, vl, vh, bl, bh, ret);
+ return ret;
+}
+
+static void tl2796_adjust_brightness_from_mtp(struct s5p_lcd *lcd)
+{
+ int c;
+ u32 v255[3];
+ u64 bc[3];
+ u64 bcmax;
+ int shift;
+ const struct tl2796_gamma_reg_offsets *offset = &lcd->gamma_reg_offsets;
+ const u16 *factory_v255_regs = lcd->data->factory_v255_regs;
+
+ for (c = 0; c < 3; c++) {
+ int scale = gamma_lookup(lcd, 255, BV_0, c);
+ v255[c] = DIV_ROUND_CLOSEST((600 - 120 - factory_v255_regs[c] -
+ offset->v[c][5]) * scale, 600);
+ // new in 2.3.3, read voltages from the screen hardware
+ bc[c] = tl2796_voltage_lookup(lcd, c, v255[c]);
+ }
+
+ shift = lcd->data->color_adj.rshift;
+ if (shift)
+ for (c = 0; c < 3; c++)
+ bc[c] = bc[c] * lcd->data->color_adj.mult[c] >> shift;
+
+ bcmax = 0xffffffff;
+ for (c = 0; c < 3; c++)
+ if (bc[c] > bcmax)
+ bcmax = bc[c];
+
+ if (bcmax != 0xffffffff) {
+ pr_warn("tl2796: factory calibration info is out of range: "
+ "scale to 0x%llx\n", bcmax);
+ bcmax += 1;
+ shift = fls(bcmax >> 32);
+ for (c = 0; c < 3; c++) {
+ bc[c] <<= 32 - shift;
+ do_div(bc[c], bcmax >> shift);
+ }
+ }
+
+ for (c = 0; c < 3; c++) {
+ lcd->color_mult[c] = bc[c];
+#ifdef CONFIG_FB_VOODOO
+ original_color_adj_mults[c] = bc[c];
+#endif
+ pr_info("tl2796: c%d, b-%08llx, got v %d, factory wants %d\n",
+ c, bc[c], gamma_lookup(lcd, 255, BV_255, c), v255[c]);
+ }
+}
+
+static s16 s9_to_s16(s16 v)
+{
+ return (s16)(v << 7) >> 7;
+}
+
+static void tl2796_read_mtp_info(struct s5p_lcd *lcd)
+{
+ int c, i;
+ u8 data[21];
+ u16 prepare_mtp_read[] = {
+ /* LV2, LV3, MTP lock release code */
+ 0xf0, 0x15a, 0x15a,
+ 0xf1, 0x15a, 0x15a,
+ 0xfc, 0x15a, 0x15a,
+ /* MTP cell enable */
+ 0xd1, 0x180,
+ /* Sleep out */
+ 0x11,
+ /* Sleep in (start to read seq) */
+ 0x10,
+ SLEEPMSEC, 40,
+
+ ENDDEF, 0x0000
+ };
+ u16 start_mtp_read[] = {
+ /* MPU 8bit read mode start */
+ 0xfc, 0x10c,
+
+ ENDDEF, 0x0000
+ };
+
+ s6e63m0_panel_send_sequence(lcd, prepare_mtp_read);
+
+ if (tl2796_parallel_setup_gpios(lcd, true)) {
+ pr_err("%s: could not configure gpios\n", __func__);
+ return;
+ }
+
+ s6e63m0_panel_send_sequence(lcd, start_mtp_read);
+
+ tl2796_parallel_read(lcd, 0xd3, data, sizeof(data));
+
+ for (c = 0; c < 3; c++) {
+ for (i = 0; i < 5; i++)
+ lcd->gamma_reg_offsets.v[c][i] = (s8)data[c * 7 + i];
+
+ lcd->gamma_reg_offsets.v[c][5] =
+ s9_to_s16(data[c * 7 + 5] << 8 | data[c * 7 + 6]);
+ }
+
+ tl2796_parallel_setup_gpios(lcd, false);
+
+ tl2796_adjust_brightness_from_mtp(lcd);
+}
+
+#ifdef CONFIG_FB_VOODOO
+/*
+ *
+ * Voodoo Color
+ *
+ */
+
+static ssize_t gamma_table_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int point;
+ int color;
+ for(point = 0; point < lcd_->data->gamma_table_size; point++)
+ {
+ for(color = 0; color < 3; color++)
+ {
+ sprintf(buf,"%s%u", buf, lcd_->data->gamma_table[point].v[color] );
+ if (color != 2)
+ sprintf(buf,"%s,", buf);
+ }
+
+ sprintf(buf,"%s\n", buf);
+ }
+
+ return sprintf(buf, "%s", buf);
+}
+
+static ssize_t gamma_table_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ int point = 0;
+ u32 values[3];
+ struct gamma_entry new_gamma_table[lcd_->data->gamma_table_size];
+ int unsigned bytes_read = 0;
+ int color;
+
+ // skip comments or whatever on top of the file, max 1kB
+ int i;
+ for ( i = 0; ! sscanf(buf, "%u,%u,%u%n", &values[0], &values[1], &values[2], &bytes_read) && i <= 1024; i++)
+ buf += 1;
+
+ // read the standard gamma table format
+ while (sscanf(buf, "%u,%u,%u%n", &values[0], &values[1], &values[2], &bytes_read) && point < lcd_->data->gamma_table_size)
+ {
+ buf += bytes_read;
+ color = 0;
+ printk("Voodoo color: gamma table point %2d: ", point);
+ while (color < 3)
+ {
+ switch (color)
+ {
+ case 0: printk("red = %7d ", values[color]); break;
+ case 1: printk("green = %7d ", values[color]); break;
+ case 2: printk("blue = %7d\n", values[color]); break;
+ }
+
+ new_gamma_table[point].v[color] = values[color];
+ color++;
+ }
+ point++;
+ }
+
+ if (point == lcd_->data->gamma_table_size)
+ {
+ printk("Voodoo color: updating gamma table (%d points)\n", point);
+
+ // set the new gamma table in kernel
+ for (point = 0; point < lcd_->data->gamma_table_size; point++)
+ for (color=0; color < 3; color++)
+ lcd_->data->gamma_table[point].v[color] = new_gamma_table[point].v[color];
+
+ update_brightness(lcd_);
+ }
+ else
+ printk("Voodoo color: gamma table malformed: ignored\n");
+
+ return size;
+}
+
+static ssize_t apply_custom_brightness_gammas_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ int bytes_read = 0;
+ int user_values[3];
+ u16 gamma_regs[27];
+ int i = 0;
+ int j = 0;
+ int k = 0;
+
+ // copied from update_brightness() to generate easily a valid panel command sequence
+ gamma_regs[0] = 0x0FA;
+ gamma_regs[1] = 0x102;
+ gamma_regs[23] = 0x0FA;
+ gamma_regs[24] = 0x103;
+ gamma_regs[25] = ENDDEF;
+ gamma_regs[26] = 0x0000;
+
+ setup_gamma_regs(lcd_, gamma_regs + 2);
+
+ // replace calculated values by user values
+ printk("Voodoo color: send user brightness and gamma values to the Super AMOLED panel:\n");
+ // scan for gamma points 1, 2, 3 and 4 and then brightness and black
+ while (sscanf(buf, "%d,%d,%d%n", &user_values[0], &user_values[1], &user_values[2], &bytes_read) && i <= 5)
+ {
+ printk("Voodoo color: [%d] = %d,%d,%d\n", i, user_values[0], user_values[1], user_values[2]);
+ buf += bytes_read;
+
+ // brightness
+ if (i == 0)
+ for (j = 0; j < 3; j++)
+ {
+ gamma_regs[18+k] = user_values[j]+256;
+ // skip 2 registers
+ k = k+2;
+ }
+
+ // gamma 0 to gamma 4
+ if (i > 0 && i <= 5)
+ for (j = 0; j < 3; j++)
+ gamma_regs[2+((i-1)*3)+j] = user_values[j]+256;
+
+ i++;
+ }
+
+ s6e63m0_panel_send_sequence(lcd_, gamma_regs);
+
+ return size;
+}
+
+static ssize_t red_multiplier_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%u\n", lcd_->color_mult[0]);
+}
+
+static ssize_t red_multiplier_original_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%u\n", original_color_adj_mults[0]);
+}
+
+static ssize_t red_multiplier_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ u32 value;
+ if (sscanf(buf, "%u", &value) == 1)
+ {
+ lcd_->color_mult[0] = value;
+ update_brightness(lcd_);
+ }
+ return size;
+}
+
+static ssize_t green_multiplier_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%u\n", lcd_->color_mult[1]);
+}
+
+static ssize_t green_multiplier_original_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%u\n", original_color_adj_mults[1]);
+}
+
+static ssize_t green_multiplier_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ u32 value;
+ if (sscanf(buf, "%u", &value) == 1)
+ {
+ lcd_->color_mult[1] = value;
+ update_brightness(lcd_);
+ }
+ return size;
+}
+
+static ssize_t blue_multiplier_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%u\n", lcd_->color_mult[2]);
+}
+
+static ssize_t blue_multiplier_original_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%u\n", original_color_adj_mults[2]);
+}
+
+static ssize_t blue_multiplier_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ u32 value;
+ if (sscanf(buf, "%u", &value) == 1)
+ {
+ lcd_->color_mult[2] = value;
+ update_brightness(lcd_);
+ }
+ return size;
+}
+
+static ssize_t panel_config_sequence_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%u\n", panel_config_sequence);
+}
+
+static ssize_t panel_config_sequence_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct s5p_panel_data *pdata = lcd_->data;
+ unsigned int value;
+ if (sscanf(buf, "%u", &value) == 1)
+ {
+ panel_config_sequence = value == 1 ? 1 : 0;
+ if (panel_config_sequence == 1)
+ s6e63m0_panel_send_sequence(lcd_, s6e63m0_SEQ_ETC_SETTING_SAMSUNG);
+ else
+ s6e63m0_panel_send_sequence(lcd_, pdata->seq_etc_set);
+ }
+ return size;
+}
+
+static ssize_t red_v1_offset_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", hacky_v1_offset[0]);
+}
+
+static ssize_t red_v1_offset_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ u32 value;
+ if (sscanf(buf, "%d", &value) == 1)
+ {
+ hacky_v1_offset[0] = value;
+ update_brightness(lcd_);
+ }
+ return size;
+}
+
+static ssize_t green_v1_offset_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", hacky_v1_offset[1]);
+}
+
+static ssize_t green_v1_offset_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ u32 value;
+ if (sscanf(buf, "%d", &value) == 1)
+ {
+ hacky_v1_offset[1] = value;
+ update_brightness(lcd_);
+ }
+ return size;
+}
+
+static ssize_t blue_v1_offset_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", hacky_v1_offset[2]);
+}
+
+static ssize_t blue_v1_offset_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ int value;
+ if (sscanf(buf, "%d", &value) == 1)
+ {
+ hacky_v1_offset[2] = value;
+ update_brightness(lcd_);
+ }
+ return size;
+}
+
+static ssize_t voodoo_color_version(struct device *dev, struct device_attribute *attr, char *buf) {
+ return sprintf(buf, "%u\n", VOODOO_COLOR_VERSION);
+}
+
+static DEVICE_ATTR(gamma_table, S_IRUGO | S_IWUGO, gamma_table_show, gamma_table_store);
+static DEVICE_ATTR(apply_custom_brightness_gammas, S_IWUGO, NULL, apply_custom_brightness_gammas_store);
+static DEVICE_ATTR(panel_config_sequence, S_IRUGO | S_IWUGO, panel_config_sequence_show, panel_config_sequence_store);
+static DEVICE_ATTR(red_multiplier, S_IRUGO | S_IWUGO, red_multiplier_show, red_multiplier_store);
+static DEVICE_ATTR(red_multiplier_original, S_IRUGO, red_multiplier_original_show, NULL);
+static DEVICE_ATTR(green_multiplier, S_IRUGO | S_IWUGO, green_multiplier_show, green_multiplier_store);
+static DEVICE_ATTR(green_multiplier_original, S_IRUGO, green_multiplier_original_show, NULL);
+static DEVICE_ATTR(blue_multiplier, S_IRUGO | S_IWUGO, blue_multiplier_show, blue_multiplier_store);
+static DEVICE_ATTR(blue_multiplier_original, S_IRUGO, blue_multiplier_original_show, NULL);
+static DEVICE_ATTR(red_v1_offset, S_IRUGO | S_IWUGO, red_v1_offset_show, red_v1_offset_store);
+static DEVICE_ATTR(green_v1_offset, S_IRUGO | S_IWUGO, green_v1_offset_show, green_v1_offset_store);
+static DEVICE_ATTR(blue_v1_offset, S_IRUGO | S_IWUGO, blue_v1_offset_show, blue_v1_offset_store);
+static DEVICE_ATTR(version, S_IRUGO, voodoo_color_version, NULL);
+
+
+static struct attribute *voodoo_color_attributes[] = {
+ &dev_attr_gamma_table.attr,
+ &dev_attr_apply_custom_brightness_gammas.attr,
+ &dev_attr_panel_config_sequence.attr,
+ &dev_attr_red_multiplier.attr,
+ &dev_attr_red_multiplier_original.attr,
+ &dev_attr_green_multiplier.attr,
+ &dev_attr_green_multiplier_original.attr,
+ &dev_attr_blue_multiplier.attr,
+ &dev_attr_blue_multiplier_original.attr,
+ &dev_attr_red_v1_offset.attr,
+ &dev_attr_green_v1_offset.attr,
+ &dev_attr_blue_v1_offset.attr,
+ &dev_attr_version.attr,
+ NULL
+};
+
+static struct attribute_group voodoo_color_group = {
+ .attrs = voodoo_color_attributes,
+};
+
+static struct miscdevice voodoo_color_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "samoled_color",
+};
+#endif
+
+static int __devinit tl2796_probe(struct spi_device *spi)
+{
+ struct s5p_lcd *lcd;
+ int ret;
+ int c;
+
+ lcd = kzalloc(sizeof(struct s5p_lcd), GFP_KERNEL);
+ if (!lcd) {
+ pr_err("failed to allocate for lcd\n");
+ ret = -ENOMEM;
+ goto err_alloc;
+ }
+ mutex_init(&lcd->lock);
+
+ spi->bits_per_word = 9;
+ if (spi_setup(spi)) {
+ pr_err("failed to setup spi\n");
+ ret = -EINVAL;
+ goto err_setup;
+ }
+
+ lcd->g_spi = spi;
+ lcd->dev = &spi->dev;
+ lcd->bl = 255;
+ for (c = 0; c < 3; c++)
+ lcd->color_mult[c] = 0xffffffff;
+
+ if (!spi->dev.platform_data) {
+ dev_err(lcd->dev, "failed to get platform data\n");
+ ret = -EINVAL;
+ goto err_setup;
+ }
+ lcd->data = (struct s5p_panel_data *)spi->dev.platform_data;
+
+ if (!lcd->data->gamma_table || !lcd->data->seq_display_set ||
+ !lcd->data->seq_etc_set || !lcd->data->standby_on ||
+ !lcd->data->standby_off) {
+ dev_err(lcd->dev, "Invalid platform data\n");
+ ret = -EINVAL;
+ goto err_setup;
+ }
+ lcd->gamma_adj_points =
+ lcd->data->gamma_adj_points ?: &default_gamma_adj_points;
+
+ spi_set_drvdata(spi, lcd);
+ tl2796_read_mtp_info(lcd);
+
+ lcd->bl_dev = backlight_device_register("s5p_bl",
+ &spi->dev, lcd, &s5p_bl_ops, NULL);
+ if (!lcd->bl_dev) {
+ dev_err(lcd->dev, "failed to register backlight\n");
+ ret = -EINVAL;
+ goto err_setup;
+ }
+
+ lcd->bl_dev->props.max_brightness = 255;
+ lcd->bl_dev->props.brightness = lcd->bl;
+
+ tl2796_ldi_enable(lcd);
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ lcd->early_suspend.suspend = tl2796_early_suspend;
+ lcd->early_suspend.resume = tl2796_late_resume;
+ lcd->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 1;
+ register_early_suspend(&lcd->early_suspend);
+#endif
+
+ lcd->debug_dir = debugfs_create_dir("s5p_bl", NULL);
+ if (!lcd->debug_dir)
+ dev_err(lcd->dev, "failed to create debug dir\n");
+ else
+ debugfs_create_file("current_gamma", S_IRUGO,
+ lcd->debug_dir, lcd, &tl2796_current_gamma_fops);
+
+#ifdef CONFIG_FB_VOODOO
+ misc_register(&voodoo_color_device);
+ if (sysfs_create_group(&voodoo_color_device.this_device->kobj, &voodoo_color_group) < 0)
+ {
+ printk("%s sysfs_create_group fail\n", __FUNCTION__);
+ pr_err("Failed to create sysfs group for device (%s)!\n", voodoo_color_device.name);
+ }
+
+ // make a copy of the codec pointer
+ lcd_ = lcd;
+#endif
+ pr_info("tl2796_probe successfully proved\n");
+
+ return 0;
+
+err_setup:
+ mutex_destroy(&lcd->lock);
+ kfree(lcd);
+
+err_alloc:
+ return ret;
+}
+
+static int __devexit tl2796_remove(struct spi_device *spi)
+{
+ struct s5p_lcd *lcd = spi_get_drvdata(spi);
+
+ debugfs_remove_recursive(lcd->debug_dir);
+
+ unregister_early_suspend(&lcd->early_suspend);
+
+ backlight_device_unregister(lcd->bl_dev);
+
+ tl2796_ldi_disable(lcd);
+
+ kfree(lcd);
+
+ return 0;
+}
+
+static struct spi_driver tl2796_driver = {
+ .driver = {
+ .name = "tl2796",
+ .owner = THIS_MODULE,
+ },
+ .probe = tl2796_probe,
+ .remove = __devexit_p(tl2796_remove),
+};
+
+static int __init tl2796_init(void)
+{
+ return spi_register_driver(&tl2796_driver);
+}
+static void __exit tl2796_exit(void)
+{
+ spi_unregister_driver(&tl2796_driver);
+}
+
+module_init(tl2796_init);
+module_exit(tl2796_exit);
diff --git a/drivers/video/samsung/tune_cmc623.c b/drivers/video/samsung/tune_cmc623.c
new file mode 100644
index 0000000..12b6b33
--- /dev/null
+++ b/drivers/video/samsung/tune_cmc623.c
@@ -0,0 +1,1579 @@
+/*
+ * cmc623_tune.c
+ *
+ * Parameter read & save driver on param partition.
+ *
+ * COPYRIGHT(C) Samsung Electronics Co.Ltd. 2006-2010 All Right Reserved.
+ *
+ */
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <asm/uaccess.h>
+// #include <linux/tegra_devices.h>
+// #include <nvodm_services.h>
+#include <linux/i2c.h>
+#include "tune_cmc623.h"
+#include <mach/gpio.h>
+#include <mach/gpio-p1.h>
+#include <plat/gpio-cfg.h>
+#include <linux/delay.h>
+
+#if 0 // dgahn.test: turn off AP LED
+#define GPIO_PORT_LEDAP 'v'-'a' // LED_AP: GPIO_PV4
+#define GPIO_PIN_LEDAP 4
+#endif
+
+//#define CMC623_TUNING
+
+//#define MDNIE_TUNING_TUNEFILE_PATH "/sdcard/sd/p1/mdnie_tune"
+//#define CMC623_PATH_TUNING_DATA "/sdcard/cmc623_tune"
+#define CMC623_PATH_TUNING_DATA3 "/sdcard/sd/p1/mdnie_tune"
+#define CMC623_PATH_TUNING_DATA2 "/sdcard/sd/p1/1"
+#define CMC623_PATH_TUNING_DATA "/sdcard/sd/p1/cmc623_tune"
+
+#define CMC623_ADDR 0x70 /* slave addr for i2c */
+#define CMC623_DEVICE_ADDR (0x38 << 1)
+#define CMC623_MAX_SETTINGS 100
+#define CMC623_I2C_SPEED_KHZ 400
+
+#define klogi(fmt, arg...) printk(KERN_INFO "%s: " fmt "\n" , __func__, ## arg)
+#define kloge(fmt, arg...) printk(KERN_ERR "%s(%d): " fmt "\n" , __func__, __LINE__, ## arg)
+
+//static NvOdmServicesI2cHandle s_hOdmI2c;
+
+#ifdef CMC623_TUNING
+static Cmc623RegisterSet Cmc623_TuneSeq[CMC623_MAX_SETTINGS];
+#endif
+
+#if 1
+/*
+static unsigned short cmc6230_normal_i2c[] = { I2C_CLIENT_END };
+static unsigned short cmc6230_ignore[] = { I2C_CLIENT_END };
+static unsigned short cmc6230_probe[] = { 8, (0x38), I2C_CLIENT_END }; // ºÎÆÃ ¾ÈµÊ P1_LSJ : DE07
+*/
+//static unsigned short cmc6230_probe[] = { 8, (0x70), I2C_CLIENT_END }; // ºÎÆÃ OK
+//static unsigned short cmc6230_probe[] = { 8, (0x70 >> 1), I2C_CLIENT_END }; // Error ¹ß»ý
+#else
+static unsigned short cmc6230_normal_i2c[] = {(CMC623_ADDR>>1),I2C_CLIENT_END};
+static unsigned short cmc6230_ignore[] = {1,(CMC623_ADDR>>1),I2C_CLIENT_END};
+static unsigned short cmc6230_probe[] = {I2C_CLIENT_END};
+
+unsigned short qt602240_i2c_normal[] = {I2C_CLIENT_END};
+unsigned short qt602240_i2c_ignore[] = {I2C_CLIENT_END};
+unsigned short qt602240_i2c_probe[] = {2, QT602240_I2C_ADDR, I2C_CLIENT_END};
+#endif
+
+#if 1 // P1_LSJ : DE04 : Add
+static struct i2c_client *g_client;
+#define I2C_M_WR 0 /* for i2c */
+#define I2c_M_RD 1 /* for i2c */
+
+/* Each client has this additional data */
+struct cmc623_data {
+ struct i2c_client *client;
+};
+
+static struct cmc623_data * p_cmc623_data = NULL;
+
+//static struct i2c_driver cmc623_i2c_driver;
+//static struct i2c_client *cmc623_i2c_client = NULL;
+
+/*
+static struct i2c_client_address_data cmc623_addr_data = {
+ .normal_i2c = cmc6230_normal_i2c,
+ .ignore = cmc6230_ignore,
+ .probe = cmc6230_probe,
+};
+*/
+
+//unsigned short *test[1];
+//EXPORT_SYMBOL(test);
+#endif
+
+#if 1
+static int cmc623_I2cWrite(struct i2c_client *client, u8 reg, u8 *data, u8 length)
+{
+ int ret, i;
+ u8 buf[length+1];
+ struct i2c_msg msg[1];
+
+ buf[0] = reg;
+ for(i=0; i<length; i++)
+ {
+ buf[i+1] = *(data++);
+ }
+
+ msg[0].addr = client->addr;
+ msg[0].flags = 0;
+ msg[0].len = length+1;
+ msg[0].buf = buf;
+
+ ret = i2c_transfer(client->adapter, msg, 1);
+ if (ret != 1)
+ {
+ return -EIO;
+ }
+
+ return 0;
+}
+
+bool cmc623_I2cWrite16( unsigned char Addr, unsigned long Data)
+{
+ int err;
+ struct i2c_msg msg[1];
+ unsigned char data[3];
+
+ if(!p_cmc623_data)
+ {
+ printk(KERN_ERR "p_cmc623_data is NULL\n");
+ return -ENODEV;
+ }
+ g_client = p_cmc623_data->client;
+
+ if( (g_client == NULL))
+ {
+ printk("cmc623_I2cWrite16 g_client is NULL\n");
+ return -ENODEV;
+ }
+
+ if (!g_client->adapter)
+ {
+ printk("cmc623_I2cWrite16 g_client->adapter is NULL\n");
+ return -ENODEV;
+ }
+
+ data[0] = Addr;
+ data[1] = ((Data >>8)&0xFF);
+ data[2] = (Data)&0xFF;
+ msg->addr = g_client->addr;
+ msg->flags = I2C_M_WR;
+ msg->len = 3;
+ msg->buf = data;
+
+ err = i2c_transfer(g_client->adapter, msg, 1);
+
+ if (err >= 0)
+ {
+ //printk("%s %d i2c transfer OK\n", __func__, __LINE__);/* add by inter.park */
+ return 0;
+ }
+
+ printk("%s %d i2c transfer error:%d\n", __func__, __LINE__, err);/* add by inter.park */
+ return err;
+}
+
+#else
+NvBool cmc623_I2cWrite16( NvU8 Addr, NvU32 Data)
+{
+ NvBool RetVal = NV_TRUE;
+
+ NvU8 WriteBuffer[3];
+ NvOdmI2cStatus status = NvOdmI2cStatus_Success;
+ NvOdmI2cTransactionInfo TransactionInfo;
+ NvU32 DeviceAddr = (NvU32)CMC623_DEVICE_ADDR;
+
+ s_hOdmI2c = NvOdmI2cPinMuxOpen(NvOdmIoModule_I2c, 1, NvOdmI2cPinMap_Config2);
+ if (!s_hOdmI2c) {
+ RetVal = NV_FALSE;
+ kloge("NvOdmI2cPinMuxOpen Failed!\n");
+ goto CMC623_I2cWrite16_exit;
+ }
+
+ WriteBuffer[0] = Addr & 0xFF; // PMU offset
+ WriteBuffer[1] = (NvU8)((Data >> 8) & 0xFF);
+ WriteBuffer[2] = (NvU8)(Data & 0xFF);
+
+ TransactionInfo.Address = DeviceAddr;
+ TransactionInfo.Buf = WriteBuffer;
+ TransactionInfo.Flags = NVODM_I2C_IS_WRITE;
+ TransactionInfo.NumBytes = 3;
+
+ status = NvOdmI2cTransaction(s_hOdmI2c, &TransactionInfo, 1,
+ CMC623_I2C_SPEED_KHZ, NV_WAIT_INFINITE);
+ if (status == NvOdmI2cStatus_Success)
+ RetVal = NV_TRUE;
+ else {
+ switch (status) {
+ case NvOdmI2cStatus_Timeout:
+ kloge("cmc623_I2cWrite16 Failed: Timeout");
+ break;
+ case NvOdmI2cStatus_SlaveNotFound:
+ kloge("cmc623_I2cWrite16 Failed: SlaveNotFound");
+ default:
+ break;
+ }
+ RetVal = NV_FALSE;
+ }
+
+CMC623_I2cWrite16_exit:
+ NvOdmI2cClose(s_hOdmI2c);
+ s_hOdmI2c = NULL;
+ return RetVal;
+}
+#endif
+
+#if 1 // P1_LSJ : DE04
+char cmc623_I2cRead(u8 reg, u8 *val, unsigned int len )
+{
+ int err;
+ struct i2c_msg msg[1];
+
+ unsigned char data[1];
+ if( (g_client == NULL) || (!g_client->adapter) )
+ {
+ return -ENODEV;
+ }
+
+ msg->addr = g_client->addr;
+ msg->flags = I2C_M_WR;
+ msg->len = 1;
+ msg->buf = data;
+ *data = reg;
+
+ err = i2c_transfer(g_client->adapter, msg, 1);
+
+ if (err >= 0)
+ {
+ msg->flags = I2C_M_RD;
+ msg->len = len;
+ msg->buf = val;
+ err = i2c_transfer(g_client->adapter, msg, 1);
+ }
+
+ if (err >= 0)
+ {
+ return 0;
+ }
+ printk("%s %d i2c transfer error\n", __func__, __LINE__);/* add by inter.park */
+
+ return err;
+
+}
+
+#else
+NvBool cmc623_I2cRead16(
+ NvU8 Addr,
+ NvU32 *Data)
+{
+ NvBool RetVal = NV_TRUE;
+
+ NvU8 ReadBuffer[2]; // 2 bytes
+ NvOdmI2cStatus status = NvOdmI2cStatus_Success;
+ NvOdmI2cTransactionInfo TransactionInfo[2];
+ NvU32 DeviceAddr = (NvU32)CMC623_DEVICE_ADDR;
+
+ s_hOdmI2c = NvOdmI2cPinMuxOpen(NvOdmIoModule_I2c, 1, NvOdmI2cPinMap_Config2);
+ if (!s_hOdmI2c) {
+ RetVal = NV_FALSE;
+ goto CMC623_I2cRead16_exit;
+ }
+
+ // Write the PMU offset
+ ReadBuffer[0] = Addr & 0xFF;
+
+ TransactionInfo[0].Address = DeviceAddr;
+ TransactionInfo[0].Buf = &ReadBuffer[0];
+ TransactionInfo[0].Flags = NVODM_I2C_IS_WRITE/* | NVODM_I2C_USE_REPEATED_START*/;
+ TransactionInfo[0].NumBytes = 1;
+
+ TransactionInfo[1].Address = (DeviceAddr | 0x1);
+ TransactionInfo[1].Buf = &ReadBuffer[0];
+ TransactionInfo[1].Flags = 0;
+ TransactionInfo[1].NumBytes = 2; // 2 bytes
+
+ status = NvOdmI2cTransaction(s_hOdmI2c, &TransactionInfo[0], 2,
+ CMC623_I2C_SPEED_KHZ, NV_WAIT_INFINITE);
+ if (status == NvOdmI2cStatus_Success) {
+ *Data = (ReadBuffer[0] << 8) | ReadBuffer[1];
+ RetVal = NV_TRUE;
+ }
+ else
+ RetVal = NV_FALSE;
+
+CMC623_I2cRead16_exit:
+ NvOdmI2cClose(s_hOdmI2c);
+ s_hOdmI2c = NULL;
+ return RetVal;
+}
+#endif
+
+#ifdef CMC623_TUNING
+
+//static bool cmc623_tune(unsigned long num)
+bool cmc623_tune(unsigned long num) // P1_LSJ : DE08
+{
+ unsigned long i;
+ int k=0;
+
+ // num = NV_ARRAY_SIZE(Cmc623_TuneSeq);
+ printk("========== Start of tuning CMC623 Jun ==========\n");
+
+ for (i=0; i<num; i++)
+ {
+ printk("[%2d] Writing => reg: 0x%2x, data: 0x%4x\n", i+1, Cmc623_TuneSeq[i].RegAddr, Cmc623_TuneSeq[i].Data);
+
+ if (0 > cmc623_I2cWrite16(Cmc623_TuneSeq[i].RegAddr, Cmc623_TuneSeq[i].Data))
+
+ // cmc623_I2cWrite(struct i2c_client *client, u8 reg, u8 *data, u8 length)
+ //if (!cmc623_I2cWrite16(Cmc623_TuneSeq[i].RegAddr, Cmc623_TuneSeq[i].Data))
+ {
+ printk("I2cWrite16 failed\n");
+ return 0;
+ }
+ else
+ {
+ printk("I2cWrite16 succeed\n");
+ }
+
+ if ( Cmc623_TuneSeq[i].RegAddr == CMC623_REG_SWRESET && Cmc623_TuneSeq[i].Data == 0xffff )
+ {
+ // NvOdmOsWaitUS(3000); // 3ms
+ // msleep(3);
+ mdelay(3);
+ }
+ }
+ printk("========== End of tuning CMC623 Jun ==========\n");
+ return 1;
+}
+
+//static int parse_text(char * src, int len, unsigned short * output)
+static int parse_text(char * src, int len)
+{
+ int i,count, ret;
+ int index=0;
+ char * str_line[CMC623_MAX_SETTINGS];
+ char * sstart;
+ char * c;
+ unsigned int data1, data2;
+
+ c = src;
+ count = 0;
+ sstart = c;
+
+ for(i=0; i<len; i++,c++)
+ {
+ char a = *c;
+ if(a=='\r' || a=='\n')
+ {
+ if(c > sstart)
+ {
+ str_line[count] = sstart;
+ count++;
+ }
+ *c='\0';
+ sstart = c+1;
+ }
+ }
+
+ if(c > sstart)
+ {
+ str_line[count] = sstart;
+ count++;
+ }
+
+ printk("----------------------------- Total number of lines:%d\n", count);
+
+ for(i=0; i<count; i++)
+ {
+ printk("line:%d, [start]%s[end]\n", i, str_line[i]);
+ ret = sscanf(str_line[i], "0x%x,0x%x\n", &data1, &data2);
+ printk("Result => [0x%2x 0x%4x] %s\n", data1, data2, (ret==2)?"Ok":"Not available");
+ if(ret == 2)
+ {
+ #if 1 // P1_LSJ : DE08
+ Cmc623_TuneSeq[index].RegAddr = (unsigned char)data1;
+ Cmc623_TuneSeq[index++].Data = (unsigned long)data2;
+ #else
+ Cmc623_TuneSeq[index].RegAddr = (NvU8)data1;
+ Cmc623_TuneSeq[index++].Data = (NvU32)data2;
+ #endif
+ }
+ }
+ return index;
+}
+
+static int cmc623_load_data(void)
+{
+ struct file *filp;
+ char *dp;
+ long l, i ;
+ loff_t pos;
+ int ret, num;
+ mm_segment_t fs;
+
+ klogi("cmc623_load_data start!");
+
+ fs = get_fs();
+ set_fs(get_ds());
+
+ filp = filp_open(CMC623_PATH_TUNING_DATA, O_RDONLY, 0);
+ if(IS_ERR(filp))
+ {
+ kloge("file open error:%d", filp);
+
+ return -1;
+
+ /*
+ filp = filp_open(CMC623_PATH_TUNING_DATA2, O_RDONLY, 0);
+ if(IS_ERR(filp))
+ {
+ kloge("file open error2");
+
+ filp = filp_open(CMC623_PATH_TUNING_DATA3, O_RDONLY, 0);
+ if(IS_ERR(filp))
+ {
+ kloge("file open error3");
+ return -1;
+ }
+ }
+ */
+ }
+
+ l = filp->f_path.dentry->d_inode->i_size;
+ klogi("Size of the file : %ld(bytes)", l);
+
+ //dp = kmalloc(l, GFP_KERNEL);
+ dp = kmalloc(l+10, GFP_KERNEL); // add cushion
+ if(dp == NULL)
+ {
+ kloge("Out of Memory!");
+ filp_close(filp, current->files);
+ return -1;
+ }
+ pos = 0;
+ memset(dp, 0, l);
+ kloge("== Before vfs_read ======");
+ ret = vfs_read(filp, (char __user *)dp, l, &pos); // P1_LSJ : DE08 : ¿©±â¼­ Á×À½
+ kloge("== After vfs_read ======");
+
+ if(ret != l)
+ {
+ kloge("<CMC623> Failed to read file (ret = %d)", ret);
+ kfree(dp);
+ filp_close(filp, current->files);
+ return -1;
+ }
+
+ filp_close(filp, current->files);
+
+ set_fs(fs);
+
+ for(i=0; i<l; i++)
+ {
+ printk("%x ", dp[i]);
+ }
+ printk("\n");
+
+ num = parse_text(dp, l);
+
+ if(!num)
+ {
+ kloge("Nothing to parse!");
+ kfree(dp);
+ return -1;
+ }
+
+ printk("------ Jun Total number of parsed lines: %d\n", num);
+ cmc623_tune(num);
+
+ kfree(dp);
+ return num;
+}
+
+int CMC623_tuning_load_from_file(void)
+{
+ return cmc623_load_data();
+}
+EXPORT_SYMBOL(CMC623_tuning_load_from_file);
+
+#endif //CMC623_TUNING
+
+
+int cmc623_test(void)
+{
+ int ret = 0;
+ int k =0;
+
+ klogi("===== cmc623_test =====");
+
+ if (gpio_is_valid(GPIO_CMC_BYPASS))
+ {
+ if (gpio_request(GPIO_CMC_BYPASS, "CMC_BYPASS"))
+ printk(KERN_ERR "Filed to request GPIO_CMC_BYPASS!\n");
+ gpio_direction_output(GPIO_CMC_BYPASS, GPIO_LEVEL_LOW);
+ }
+ s3c_gpio_setpull(GPIO_CMC_BYPASS, S3C_GPIO_PULL_NONE);
+ gpio_set_value(GPIO_CMC_BYPASS, GPIO_LEVEL_HIGH);
+ mdelay(2);
+
+ if (gpio_is_valid(GPIO_CMC_RST)) {
+ if (gpio_request(GPIO_CMC_RST, "CMC_RST"))
+ printk(KERN_ERR "Filed to request GPIO_CMC_RST!\n");
+ gpio_direction_output(GPIO_CMC_RST, GPIO_LEVEL_HIGH);
+ }
+ s3c_gpio_setpull(GPIO_CMC_RST, S3C_GPIO_PULL_NONE);
+ gpio_set_value(GPIO_CMC_RST, GPIO_LEVEL_LOW);
+ mdelay(4);
+ gpio_set_value(GPIO_CMC_RST, GPIO_LEVEL_HIGH);
+ mdelay(5);
+
+ // a27 // P1_LSJ DE13
+ // add, value // DNR:bypass, HDTR: bypass Gamma:ÀúÁ¶µµ down 2 ´õ ³·°Ô
+ cmc623_I2cWrite16(0x00, 0x0000); //BANK 0
+ cmc623_I2cWrite16(0x01, 0x0040); //algorithm selection
+ cmc623_I2cWrite16(0x24, 0x0001);
+ cmc623_I2cWrite16(0x0b, 0x0184);
+ cmc623_I2cWrite16(0x12, 0x0000);
+ cmc623_I2cWrite16(0x13, 0x0000);
+ cmc623_I2cWrite16(0x14, 0x0000);
+ cmc623_I2cWrite16(0x15, 0x0000);
+ cmc623_I2cWrite16(0x16, 0x0000);
+ cmc623_I2cWrite16(0x17, 0x0000);
+ cmc623_I2cWrite16(0x18, 0x0000);
+ cmc623_I2cWrite16(0x19, 0x0000);
+ cmc623_I2cWrite16(0x0d, 0x1a08);
+ cmc623_I2cWrite16(0x0e, 0x0809);
+ cmc623_I2cWrite16(0x22, 0x0400);
+ cmc623_I2cWrite16(0x23, 0x0258);
+
+ cmc623_I2cWrite16(0x2c, 0x003c); //DNR
+ cmc623_I2cWrite16(0x2d, 0x0a08); //DNR
+ cmc623_I2cWrite16(0x2e, 0x1010); //DNR
+ cmc623_I2cWrite16(0x2f, 0x0400); //DNR
+ cmc623_I2cWrite16(0x3a, 0x000C); //HDTR DE,
+ cmc623_I2cWrite16(0x3b, 0x03ff); //DE strength
+ cmc623_I2cWrite16(0x42, 0x0001); //max_Diff
+ cmc623_I2cWrite16(0x49, 0x0400); //PCC
+ cmc623_I2cWrite16(0x4a, 0x7272);
+ cmc623_I2cWrite16(0x4b, 0x8d8d);
+ cmc623_I2cWrite16(0x4d, 0x01c0);
+ cmc623_I2cWrite16(0xC8, 0x0000); //scr
+ cmc623_I2cWrite16(0xC9, 0x1000);
+ cmc623_I2cWrite16(0xCA, 0xFFFF);
+ cmc623_I2cWrite16(0xCB, 0xFFFF);
+ cmc623_I2cWrite16(0xCC, 0x0000);
+ cmc623_I2cWrite16(0xCD, 0xFFFF);
+ cmc623_I2cWrite16(0xCE, 0x1000);
+ cmc623_I2cWrite16(0xCF, 0xF0F0);
+ cmc623_I2cWrite16(0xD0, 0x00FF);
+ cmc623_I2cWrite16(0xD1, 0x00FF);
+ cmc623_I2cWrite16(0xD2, 0x00FF);
+ cmc623_I2cWrite16(0xD3, 0x00FF);
+
+ cmc623_I2cWrite16(0x00, 0x0001); //BANK 1
+ cmc623_I2cWrite16(0x09, 0x0400);
+ cmc623_I2cWrite16(0x0a, 0x0258);
+ cmc623_I2cWrite16(0x0b, 0x0400);
+ cmc623_I2cWrite16(0x0c, 0x0258);
+ cmc623_I2cWrite16(0x01, 0x0500);
+ cmc623_I2cWrite16(0x06, 0x0074);
+ cmc623_I2cWrite16(0x07, 0x2225);
+ cmc623_I2cWrite16(0x65, 0x0008);
+ cmc623_I2cWrite16(0x68, 0x0080);
+ cmc623_I2cWrite16(0x6c, 0x0a28);
+ cmc623_I2cWrite16(0x6d, 0x0b0a);
+ cmc623_I2cWrite16(0x6e, 0xe1b3);
+
+ cmc623_I2cWrite16(0x20, 0x0000); //GAMMA
+ cmc623_I2cWrite16(0x21, 0x1800);
+ cmc623_I2cWrite16(0x22, 0x1800);
+ cmc623_I2cWrite16(0x23, 0x1800);
+ cmc623_I2cWrite16(0x24, 0x1800);
+ cmc623_I2cWrite16(0x25, 0x1800);
+ cmc623_I2cWrite16(0x26, 0x1800);
+ cmc623_I2cWrite16(0x27, 0x1800);
+ cmc623_I2cWrite16(0x28, 0x1800);
+ cmc623_I2cWrite16(0x29, 0x1800);
+ cmc623_I2cWrite16(0x2A, 0x1800);
+ cmc623_I2cWrite16(0x2B, 0x1800);
+ cmc623_I2cWrite16(0x2C, 0x1800);
+ cmc623_I2cWrite16(0x2D, 0x1800);
+ cmc623_I2cWrite16(0x2E, 0x1800);
+ cmc623_I2cWrite16(0x2F, 0x1800);
+ cmc623_I2cWrite16(0x30, 0x1800);
+ cmc623_I2cWrite16(0x31, 0x9903);
+ cmc623_I2cWrite16(0x32, 0x9c0a);
+ cmc623_I2cWrite16(0x33, 0xa31c);
+ cmc623_I2cWrite16(0x34, 0xa420);
+ cmc623_I2cWrite16(0x35, 0xa420);
+ cmc623_I2cWrite16(0x36, 0xa420);
+ cmc623_I2cWrite16(0x37, 0xa420);
+ cmc623_I2cWrite16(0x38, 0xFF00);
+ cmc623_I2cWrite16(0x20, 0x0001);
+
+ cmc623_I2cWrite16(0x00, 0x0000);
+ cmc623_I2cWrite16(0x28, 0x0000);
+ cmc623_I2cWrite16(0x09, 0x0000);
+ cmc623_I2cWrite16(0x09, 0xffff);
+
+ //delay 5ms
+ mdelay(5);
+ cmc623_I2cWrite16(0x26, 0x0001);
+
+ klogi("===== cmc623_load_data START =====");
+ // ret = cmc623_load_data();
+ klogi("===== cmc623_load_data END =====");
+ klogi("===== cmc623_test ret (%d)=====", ret);
+
+ return ret;
+}
+EXPORT_SYMBOL(cmc623_test);
+
+int cmc623_gamma_set(void) // P1_LSJ DE19
+{
+ int ret = 0;
+ int k =0;
+
+ printk("**************************************\n");
+ printk("**** < cmc623_gamma_set > *****\n");
+ printk("**************************************\n");
+
+ if (gpio_is_valid(GPIO_CMC_BYPASS))
+ {
+ gpio_direction_output(GPIO_CMC_BYPASS, GPIO_LEVEL_LOW);
+ }
+ s3c_gpio_setpull(GPIO_CMC_BYPASS, S3C_GPIO_PULL_NONE);
+ gpio_set_value(GPIO_CMC_BYPASS, GPIO_LEVEL_HIGH);
+ mdelay(2);
+
+ if (gpio_is_valid(GPIO_CMC_RST))
+ {
+ gpio_direction_output(GPIO_CMC_RST, GPIO_LEVEL_HIGH);
+ }
+ s3c_gpio_setpull(GPIO_CMC_RST, S3C_GPIO_PULL_NONE);
+ gpio_set_value(GPIO_CMC_RST, GPIO_LEVEL_LOW);
+ mdelay(4);
+ gpio_set_value(GPIO_CMC_RST, GPIO_LEVEL_HIGH);
+ mdelay(5);
+
+#if 0
+ cmc623_I2cWrite16(0x00, 0x0000); //BANK 0
+ cmc623_I2cWrite16(0x01, 0x0040); //algorithm selection
+ cmc623_I2cWrite16(0x10, 0x001A); // PCLK Polarity Sel
+ cmc623_I2cWrite16(0x24, 0x0001); // Polarity Sel
+ cmc623_I2cWrite16(0x0b, 0x0184); // Clock Gating
+ cmc623_I2cWrite16(0x12, 0x0000); // Pad strength start
+ cmc623_I2cWrite16(0x13, 0x0000);
+ cmc623_I2cWrite16(0x14, 0x0000);
+ cmc623_I2cWrite16(0x15, 0x0000);
+ cmc623_I2cWrite16(0x16, 0x0000);
+ cmc623_I2cWrite16(0x17, 0x0000);
+ cmc623_I2cWrite16(0x18, 0x0000);
+ cmc623_I2cWrite16(0x19, 0x0000); // Pad strength end
+ cmc623_I2cWrite16(0x0d, 0x1a0a); // A-Stage clk
+ cmc623_I2cWrite16(0x0e, 0x0a0b); // B-stage clk
+ cmc623_I2cWrite16(0x22, 0x0400); // H_Size
+ cmc623_I2cWrite16(0x23, 0x0258); // V_Size
+ cmc623_I2cWrite16(0x2c, 0x0fff); //DNR bypass
+ cmc623_I2cWrite16(0x2e, 0x0000); //DNR bypass
+ cmc623_I2cWrite16(0x3a, 0x000c); //HDTR on DE,
+ cmc623_I2cWrite16(0x3b, 0x03ff); //DE strength
+ cmc623_I2cWrite16(0x42, 0x0001); //max_Diff
+ cmc623_I2cWrite16(0x49, 0x0400); //PCC
+ cmc623_I2cWrite16(0x4a, 0x7272);
+ cmc623_I2cWrite16(0x4b, 0x8d8d);
+ cmc623_I2cWrite16(0x4d, 0x01c0);
+ cmc623_I2cWrite16(0xC8, 0x0000); //scr
+ cmc623_I2cWrite16(0xC9, 0x1000);
+ cmc623_I2cWrite16(0xCA, 0xFFFF);
+ cmc623_I2cWrite16(0xCB, 0xFFFF);
+ cmc623_I2cWrite16(0xCC, 0x0000);
+ cmc623_I2cWrite16(0xCD, 0xFFFF);
+ cmc623_I2cWrite16(0xCE, 0x1000);
+ cmc623_I2cWrite16(0xCF, 0xF0F0);
+ cmc623_I2cWrite16(0xD0, 0x00FF);
+ cmc623_I2cWrite16(0xD1, 0x00FF);
+ cmc623_I2cWrite16(0xD2, 0x00FF);
+ cmc623_I2cWrite16(0xD3, 0x00FF);
+ cmc623_I2cWrite16(0x00, 0x0001); //BANK 1
+ cmc623_I2cWrite16(0x09, 0x0400); // H_Size
+ cmc623_I2cWrite16(0x0a, 0x0258); // V_Size
+ cmc623_I2cWrite16(0x0b, 0x0400); // H_Size
+ cmc623_I2cWrite16(0x0c, 0x0258); // V_Size
+ cmc623_I2cWrite16(0x01, 0x0500); // BF_Line
+ cmc623_I2cWrite16(0x06, 0x0062); // Refresh time
+ cmc623_I2cWrite16(0x07, 0x2225); // eDRAM
+ cmc623_I2cWrite16(0x65, 0x0008); // V_Sync cal.
+ cmc623_I2cWrite16(0x68, 0x0080); // TCON Polarity
+ cmc623_I2cWrite16(0x6c, 0x0414); // VLW,HLW
+ cmc623_I2cWrite16(0x6d, 0x0506); // VBP,VFP
+ cmc623_I2cWrite16(0x6e, 0x1e32); // HBP,HFP
+ cmc623_I2cWrite16(0x20, 0x0000); //GAMMA 11
+ cmc623_I2cWrite16(0x21, 0x2000);
+ cmc623_I2cWrite16(0x22, 0x2000);
+ cmc623_I2cWrite16(0x23, 0x2000);
+ cmc623_I2cWrite16(0x24, 0x2000);
+ cmc623_I2cWrite16(0x25, 0x2000);
+ cmc623_I2cWrite16(0x26, 0x2000);
+ cmc623_I2cWrite16(0x27, 0x2000);
+ cmc623_I2cWrite16(0x28, 0x2000);
+ cmc623_I2cWrite16(0x29, 0x1f01);
+ cmc623_I2cWrite16(0x2A, 0x1f01);
+ cmc623_I2cWrite16(0x2B, 0x1f01);
+ cmc623_I2cWrite16(0x2C, 0x1f01);
+ cmc623_I2cWrite16(0x2D, 0x1f01);
+ cmc623_I2cWrite16(0x2E, 0x1f01);
+ cmc623_I2cWrite16(0x2F, 0x1f01);
+ cmc623_I2cWrite16(0x30, 0x1f01);
+ cmc623_I2cWrite16(0x31, 0x1f01);
+ cmc623_I2cWrite16(0x32, 0x1f01);
+ cmc623_I2cWrite16(0x33, 0x1f01);
+ cmc623_I2cWrite16(0x34, 0xa20b);
+ cmc623_I2cWrite16(0x35, 0xa20b);
+ cmc623_I2cWrite16(0x36, 0x2000);
+ cmc623_I2cWrite16(0x37, 0x1f08);
+ cmc623_I2cWrite16(0x38, 0xFF00);
+ cmc623_I2cWrite16(0x20, 0x0001); // GAMMA 11
+ cmc623_I2cWrite16(0x00, 0x0000);
+ cmc623_I2cWrite16(0x28, 0x0000);
+ cmc623_I2cWrite16(0x09, 0x0000);
+ cmc623_I2cWrite16(0x09, 0xffff);
+
+ //delay 5ms
+ mdelay(5);
+
+ cmc623_I2cWrite16(0x26, 0x0001);
+#else
+ // add, value
+ cmc623_I2cWrite16(0x00, 0x0000); //BANK 0
+ cmc623_I2cWrite16(0x01, 0x0040); //algorithm selection
+ cmc623_I2cWrite16(0x24, 0x0001);
+ cmc623_I2cWrite16(0x0b, 0x0184);
+ cmc623_I2cWrite16(0x12, 0x0000);
+ cmc623_I2cWrite16(0x13, 0x0000);
+ cmc623_I2cWrite16(0x14, 0x0000);
+ cmc623_I2cWrite16(0x15, 0x0000);
+ cmc623_I2cWrite16(0x16, 0x0000);
+ cmc623_I2cWrite16(0x17, 0x0000);
+ cmc623_I2cWrite16(0x18, 0x0000);
+ cmc623_I2cWrite16(0x19, 0x0000);
+ cmc623_I2cWrite16(0x0d, 0x1a08);
+ cmc623_I2cWrite16(0x0e, 0x0809);
+ cmc623_I2cWrite16(0x22, 0x0400);
+ cmc623_I2cWrite16(0x23, 0x0258);
+
+ cmc623_I2cWrite16(0x2c, 0x0fff); //DNR bypass
+ cmc623_I2cWrite16(0x2e, 0x0000); //DNR bypass
+ cmc623_I2cWrite16(0x3a, 0x0000); //HDTR DE,
+ cmc623_I2cWrite16(0xC8, 0x0000); //scr
+ cmc623_I2cWrite16(0xC9, 0x2000);
+ cmc623_I2cWrite16(0xCA, 0xFFFF);
+ cmc623_I2cWrite16(0xCB, 0xFFFF);
+ cmc623_I2cWrite16(0xCC, 0x0000);
+ cmc623_I2cWrite16(0xCD, 0xFFFF);
+ cmc623_I2cWrite16(0xCE, 0x1000);
+ cmc623_I2cWrite16(0xCF, 0xECF0);
+ cmc623_I2cWrite16(0xD0, 0x00FF);
+ cmc623_I2cWrite16(0xD1, 0x00FF);
+ cmc623_I2cWrite16(0xD2, 0x00FF);
+ cmc623_I2cWrite16(0xD3, 0x00FF);
+
+ cmc623_I2cWrite16(0x00, 0x0001); //BANK 1
+ cmc623_I2cWrite16(0x09, 0x0400);
+ cmc623_I2cWrite16(0x0a, 0x0258);
+ cmc623_I2cWrite16(0x0b, 0x0400);
+ cmc623_I2cWrite16(0x0c, 0x0258);
+ cmc623_I2cWrite16(0x01, 0x0500);
+ cmc623_I2cWrite16(0x06, 0x0074);
+ cmc623_I2cWrite16(0x07, 0x2225);
+ cmc623_I2cWrite16(0x65, 0x0008);
+ cmc623_I2cWrite16(0x68, 0x0080);
+ //
+ cmc623_I2cWrite16(0x6c, 0x0414);
+ cmc623_I2cWrite16(0x6d, 0x0506);
+ cmc623_I2cWrite16(0x6e, 0x1e32);
+// cmc623_I2cWrite16(0x6c, 0x0a28);
+// cmc623_I2cWrite16(0x6d, 0x0b0a);
+// cmc623_I2cWrite16(0x6e, 0xe1b3);
+
+ cmc623_I2cWrite16(0x20, 0x0000); //GAMMA
+ cmc623_I2cWrite16(0x21, 0x1800);
+ cmc623_I2cWrite16(0x22, 0x1800);
+ cmc623_I2cWrite16(0x23, 0x1800);
+ cmc623_I2cWrite16(0x24, 0x1800);
+ cmc623_I2cWrite16(0x25, 0x1800);
+ cmc623_I2cWrite16(0x26, 0x1800);
+ cmc623_I2cWrite16(0x27, 0x1800);
+ cmc623_I2cWrite16(0x28, 0x1800);
+ cmc623_I2cWrite16(0x29, 0x1800);
+ cmc623_I2cWrite16(0x2A, 0x1800);
+ cmc623_I2cWrite16(0x2B, 0x1800);
+ cmc623_I2cWrite16(0x2C, 0x1800);
+ cmc623_I2cWrite16(0x2D, 0x1800);
+ cmc623_I2cWrite16(0x2E, 0x1800);
+ cmc623_I2cWrite16(0x2F, 0x1800);
+ cmc623_I2cWrite16(0x30, 0x1800);
+ cmc623_I2cWrite16(0x31, 0x9903);
+ cmc623_I2cWrite16(0x32, 0x9c0a);
+ cmc623_I2cWrite16(0x33, 0xa31c);
+ cmc623_I2cWrite16(0x34, 0xa420);
+ cmc623_I2cWrite16(0x35, 0xa420);
+ cmc623_I2cWrite16(0x36, 0xa420);
+ cmc623_I2cWrite16(0x37, 0xa420);
+ cmc623_I2cWrite16(0x38, 0xFF00);
+ cmc623_I2cWrite16(0x20, 0x0001);
+
+ cmc623_I2cWrite16(0x00, 0x0000);
+ cmc623_I2cWrite16(0x28, 0x0000);
+ cmc623_I2cWrite16(0x09, 0x0000);
+ cmc623_I2cWrite16(0x09, 0xffff);
+
+ //delay 5ms
+ mdelay(5);
+ cmc623_I2cWrite16(0x26, 0x0001);
+#endif
+
+ return ret;
+}
+EXPORT_SYMBOL(cmc623_gamma_set);
+
+int cmc623_gamma_set_DMB(void) // P1_LSJ DE19
+{
+ int ret = 0;
+ int k =0;
+
+ printk("**************************************\n");
+ printk("**** < cmc623_gamma_set_DMB > *****\n");
+ printk("**************************************\n");
+
+ if (gpio_is_valid(GPIO_CMC_BYPASS))
+ {
+ if (gpio_request(GPIO_CMC_BYPASS, "CMC_BYPASS"))
+ printk(KERN_ERR "Filed to request GPIO_CMC_BYPASS!\n");
+ gpio_direction_output(GPIO_CMC_BYPASS, GPIO_LEVEL_LOW);
+ }
+ s3c_gpio_setpull(GPIO_CMC_BYPASS, S3C_GPIO_PULL_NONE);
+ gpio_set_value(GPIO_CMC_BYPASS, GPIO_LEVEL_HIGH);
+ mdelay(2);
+
+ if (gpio_is_valid(GPIO_CMC_RST)) {
+ if (gpio_request(GPIO_CMC_RST, "CMC_RST"))
+ printk(KERN_ERR "Filed to request GPIO_CMC_RST!\n");
+ gpio_direction_output(GPIO_CMC_RST, GPIO_LEVEL_HIGH);
+ }
+ s3c_gpio_setpull(GPIO_CMC_RST, S3C_GPIO_PULL_NONE);
+ gpio_set_value(GPIO_CMC_RST, GPIO_LEVEL_LOW);
+ mdelay(4);
+ gpio_set_value(GPIO_CMC_RST, GPIO_LEVEL_HIGH);
+ mdelay(5);
+
+ // add, value
+ cmc623_I2cWrite16(0x00, 0x0000); //BANK 0
+ cmc623_I2cWrite16(0x01, 0x0040); //algorithm selection
+ cmc623_I2cWrite16(0x24, 0x0001);
+ cmc623_I2cWrite16(0x0b, 0x0184);
+ cmc623_I2cWrite16(0x12, 0x0000);
+ cmc623_I2cWrite16(0x13, 0x0000);
+ cmc623_I2cWrite16(0x14, 0x0000);
+ cmc623_I2cWrite16(0x15, 0x0000);
+ cmc623_I2cWrite16(0x16, 0x0000);
+ cmc623_I2cWrite16(0x17, 0x0000);
+ cmc623_I2cWrite16(0x18, 0x0000);
+ cmc623_I2cWrite16(0x19, 0x0000);
+ cmc623_I2cWrite16(0x0d, 0x1a08);
+ cmc623_I2cWrite16(0x0e, 0x0809);
+ cmc623_I2cWrite16(0x22, 0x0400);
+ cmc623_I2cWrite16(0x23, 0x0258);
+
+ cmc623_I2cWrite16(0x2c, 0x003c); //DNR
+ cmc623_I2cWrite16(0x2d, 0x0a08); //DNR
+ cmc623_I2cWrite16(0x2e, 0x1010); //DNR
+ cmc623_I2cWrite16(0x2f, 0x0400); //DNR
+ cmc623_I2cWrite16(0x3a, 0x000c); //HDTR on DE,
+ cmc623_I2cWrite16(0x3b, 0x03ff); //DE strength
+ cmc623_I2cWrite16(0x42, 0x0001); //max_Diff
+ cmc623_I2cWrite16(0x49, 0x0400); //PCC
+ cmc623_I2cWrite16(0x4a, 0x7272);
+ cmc623_I2cWrite16(0x4b, 0x8d8d);
+ cmc623_I2cWrite16(0x4d, 0x01c0);
+ cmc623_I2cWrite16(0xC8, 0x0000); //scr
+ cmc623_I2cWrite16(0xC9, 0x1000);
+ cmc623_I2cWrite16(0xCA, 0xFFFF);
+ cmc623_I2cWrite16(0xCB, 0xFFFF);
+ cmc623_I2cWrite16(0xCC, 0x0000);
+ cmc623_I2cWrite16(0xCD, 0xFFFF);
+ cmc623_I2cWrite16(0xCE, 0x1000);
+ cmc623_I2cWrite16(0xCF, 0xF0F0);
+ cmc623_I2cWrite16(0xD0, 0x00FF);
+ cmc623_I2cWrite16(0xD1, 0x00FF);
+ cmc623_I2cWrite16(0xD2, 0x00FF);
+ cmc623_I2cWrite16(0xD3, 0x00FF);
+
+ cmc623_I2cWrite16(0x00, 0x0001); //BANK 1
+ cmc623_I2cWrite16(0x09, 0x0400);
+ cmc623_I2cWrite16(0x0a, 0x0258);
+ cmc623_I2cWrite16(0x0b, 0x0400);
+ cmc623_I2cWrite16(0x0c, 0x0258);
+ cmc623_I2cWrite16(0x01, 0x0500);
+ cmc623_I2cWrite16(0x06, 0x0074);
+ cmc623_I2cWrite16(0x07, 0x2225);
+ cmc623_I2cWrite16(0x65, 0x0008);
+ cmc623_I2cWrite16(0x68, 0x0080);
+ cmc623_I2cWrite16(0x6c, 0x0a28);
+ cmc623_I2cWrite16(0x6d, 0x0b0a);
+ cmc623_I2cWrite16(0x6e, 0xe1b3);
+
+ cmc623_I2cWrite16(0x20, 0x0000); //GAMMA
+ cmc623_I2cWrite16(0x21, 0x1800);
+ cmc623_I2cWrite16(0x22, 0x1800);
+ cmc623_I2cWrite16(0x23, 0x1800);
+ cmc623_I2cWrite16(0x24, 0x1800);
+ cmc623_I2cWrite16(0x25, 0x1800);
+ cmc623_I2cWrite16(0x26, 0x1800);
+ cmc623_I2cWrite16(0x27, 0x1800);
+ cmc623_I2cWrite16(0x28, 0x1800);
+ cmc623_I2cWrite16(0x29, 0x1800);
+ cmc623_I2cWrite16(0x2A, 0x1800);
+ cmc623_I2cWrite16(0x2B, 0x1800);
+ cmc623_I2cWrite16(0x2C, 0x1800);
+ cmc623_I2cWrite16(0x2D, 0x1800);
+ cmc623_I2cWrite16(0x2E, 0x1800);
+ cmc623_I2cWrite16(0x2F, 0x1800);
+ cmc623_I2cWrite16(0x30, 0x1800);
+ cmc623_I2cWrite16(0x31, 0x9903);
+ cmc623_I2cWrite16(0x32, 0x9c0a);
+ cmc623_I2cWrite16(0x33, 0xa31c);
+ cmc623_I2cWrite16(0x34, 0xa420);
+ cmc623_I2cWrite16(0x35, 0xa420);
+ cmc623_I2cWrite16(0x36, 0xa420);
+ cmc623_I2cWrite16(0x37, 0xa420);
+ cmc623_I2cWrite16(0x38, 0xFF00);
+ cmc623_I2cWrite16(0x20, 0x0001);
+
+ cmc623_I2cWrite16(0x00, 0x0000);
+ cmc623_I2cWrite16(0x28, 0x0000);
+ cmc623_I2cWrite16(0x09, 0x0000);
+ cmc623_I2cWrite16(0x09, 0xffff);
+
+ //delay 5ms
+ mdelay(5);
+ cmc623_I2cWrite16(0x26, 0x0001);
+
+ return ret;
+}
+EXPORT_SYMBOL(cmc623_gamma_set_DMB);
+
+int cmc623_DMB_test(void) // P1_LSJ : DE11
+{
+ int ret = 0;
+
+ klogi("===== cmc623_DMBtest =====");
+
+ if (gpio_is_valid(GPIO_CMC_BYPASS)) {
+ if (gpio_request(GPIO_CMC_BYPASS, "CMC_BYPASS"))
+ printk(KERN_ERR "Filed to request GPIO_CMC_BYPASS!\n");
+ gpio_direction_output(GPIO_CMC_BYPASS, GPIO_LEVEL_LOW);
+ }
+ s3c_gpio_setpull(GPIO_CMC_BYPASS, S3C_GPIO_PULL_NONE);
+ gpio_set_value(GPIO_CMC_BYPASS, GPIO_LEVEL_HIGH);
+ mdelay(2);
+
+ if (gpio_is_valid(GPIO_CMC_RST)) {
+ if (gpio_request(GPIO_CMC_RST, "CMC_RST"))
+ printk(KERN_ERR "Filed to request GPIO_CMC_RST!\n");
+ gpio_direction_output(GPIO_CMC_RST, GPIO_LEVEL_HIGH);
+ }
+ s3c_gpio_setpull(GPIO_CMC_RST, S3C_GPIO_PULL_NONE);
+ gpio_set_value(GPIO_CMC_RST, GPIO_LEVEL_LOW);
+ mdelay(4);
+ gpio_set_value(GPIO_CMC_RST, GPIO_LEVEL_HIGH);
+ mdelay(5);
+
+ // a17 mdelay(5);
+ // add, value
+ cmc623_I2cWrite16(0x00, 0x0000); //BANK 0
+ cmc623_I2cWrite16(0x01, 0x0040); //algorithm selection
+ cmc623_I2cWrite16(0x24, 0x0001);
+ cmc623_I2cWrite16(0x0b, 0x0184);
+ cmc623_I2cWrite16(0x12, 0x0000);
+ cmc623_I2cWrite16(0x13, 0x0000);
+ cmc623_I2cWrite16(0x14, 0x0000);
+ cmc623_I2cWrite16(0x15, 0x0000);
+ cmc623_I2cWrite16(0x16, 0x0000);
+ cmc623_I2cWrite16(0x17, 0x0000);
+ cmc623_I2cWrite16(0x18, 0x0000);
+ cmc623_I2cWrite16(0x19, 0x0000);
+ cmc623_I2cWrite16(0x0d, 0x1a08);
+ cmc623_I2cWrite16(0x0e, 0x0809);
+ cmc623_I2cWrite16(0x22, 0x0400);
+ cmc623_I2cWrite16(0x23, 0x0258);
+
+ cmc623_I2cWrite16(0x2c, 0x0fff); //DNR bypass
+ cmc623_I2cWrite16(0x2e, 0x0000); //DNR bypass
+ cmc623_I2cWrite16(0x3a, 0x0000); //HDTR DE,
+ cmc623_I2cWrite16(0xC8, 0x0000); //scr
+ cmc623_I2cWrite16(0xC9, 0x1800);
+ cmc623_I2cWrite16(0xCA, 0xFFFF);
+ cmc623_I2cWrite16(0xCB, 0xFFFF);
+ cmc623_I2cWrite16(0xCC, 0x0000);
+ cmc623_I2cWrite16(0xCD, 0xFFFF);
+ cmc623_I2cWrite16(0xCE, 0x1000);
+ cmc623_I2cWrite16(0xCF, 0xF0F0);
+ cmc623_I2cWrite16(0xD0, 0x00FF);
+ cmc623_I2cWrite16(0xD1, 0x00FF);
+ cmc623_I2cWrite16(0xD2, 0x00FF);
+ cmc623_I2cWrite16(0xD3, 0x00FF);
+
+ cmc623_I2cWrite16(0x00, 0x0001); //BANK 1
+ cmc623_I2cWrite16(0x09, 0x0400);
+ cmc623_I2cWrite16(0x0a, 0x0258);
+ cmc623_I2cWrite16(0x0b, 0x0400);
+ cmc623_I2cWrite16(0x0c, 0x0258);
+ cmc623_I2cWrite16(0x01, 0x0500);
+ cmc623_I2cWrite16(0x06, 0x0074);
+ cmc623_I2cWrite16(0x07, 0x2225);
+ cmc623_I2cWrite16(0x65, 0x0008);
+ cmc623_I2cWrite16(0x68, 0x0080);
+ cmc623_I2cWrite16(0x6c, 0x0a28);
+ cmc623_I2cWrite16(0x6d, 0x0b0a);
+ cmc623_I2cWrite16(0x6e, 0xe1b3);
+
+ cmc623_I2cWrite16(0x20, 0x0000); //GAMMA
+ cmc623_I2cWrite16(0x21, 0x0100);
+ cmc623_I2cWrite16(0x22, 0x0100);
+ cmc623_I2cWrite16(0x23, 0x0100);
+ cmc623_I2cWrite16(0x24, 0x0100);
+ cmc623_I2cWrite16(0x25, 0x0100);
+ cmc623_I2cWrite16(0x26, 0x0100);
+ cmc623_I2cWrite16(0x27, 0x0100);
+ cmc623_I2cWrite16(0x28, 0x0100);
+ cmc623_I2cWrite16(0x29, 0xa318);
+ cmc623_I2cWrite16(0x2A, 0xa318);
+ cmc623_I2cWrite16(0x2B, 0xa318);
+ cmc623_I2cWrite16(0x2C, 0xa318);
+ cmc623_I2cWrite16(0x2D, 0xa318);
+ cmc623_I2cWrite16(0x2E, 0xa318);
+ cmc623_I2cWrite16(0x2F, 0xa318);
+ cmc623_I2cWrite16(0x30, 0xa318);
+ cmc623_I2cWrite16(0x31, 0xa318);
+ cmc623_I2cWrite16(0x32, 0xa318);
+ cmc623_I2cWrite16(0x33, 0xa318);
+ cmc623_I2cWrite16(0x34, 0xa318);
+ cmc623_I2cWrite16(0x35, 0xa318);
+ cmc623_I2cWrite16(0x36, 0xa318);
+ cmc623_I2cWrite16(0x37, 0xa318);
+ cmc623_I2cWrite16(0x38, 0xFF00);
+ cmc623_I2cWrite16(0x20, 0x0001);
+
+ cmc623_I2cWrite16(0x00, 0x0000);
+ cmc623_I2cWrite16(0x28, 0x0000);
+ cmc623_I2cWrite16(0x09, 0x0000);
+ cmc623_I2cWrite16(0x09, 0xffff);
+
+ //delay 5ms
+ mdelay(5);
+ cmc623_I2cWrite16(0x26, 0x0001);
+
+ // ret = cmc623_load_data();
+ klogi("===== cmc623_DMB_test ret (%d)=====", ret);
+ return ret;
+}
+EXPORT_SYMBOL(cmc623_DMB_test);
+
+static int cmc623_tuning_set (void) // P1_LSJ DE19
+{
+ int ret = 0;
+ int k =0;
+
+ printk("**************************************\n");
+ printk("**** < cmc623_tuning_set > *****\n");
+ printk("**************************************\n");
+
+ cmc623_I2cWrite16(0x00, 0x0000); //BANK 0
+ cmc623_I2cWrite16(0x01, 0x0070); //algorithm selection
+ cmc623_I2cWrite16(0xb4, 0x4400); //PWM ratio
+ cmc623_I2cWrite16(0xb3, 0xffff); //up/down step
+ cmc623_I2cWrite16(0x10, 0x001A); // PCLK Polarity Sel
+ cmc623_I2cWrite16(0x24, 0x0001); // Polarity Sel
+ cmc623_I2cWrite16(0x0b, 0x0184); // Clock Gating
+ cmc623_I2cWrite16(0x12, 0x0000); // Pad strength start
+ cmc623_I2cWrite16(0x13, 0x0000);
+ cmc623_I2cWrite16(0x14, 0x0000);
+ cmc623_I2cWrite16(0x15, 0x0000);
+ cmc623_I2cWrite16(0x16, 0x0000);
+ cmc623_I2cWrite16(0x17, 0x0000);
+ cmc623_I2cWrite16(0x18, 0x0000);
+ cmc623_I2cWrite16(0x19, 0x0000); // Pad strength end
+ cmc623_I2cWrite16(0x0f, 0x0010); // PWM clock ratio
+ cmc623_I2cWrite16(0x0d, 0x1a0a); // A-Stage clk
+ cmc623_I2cWrite16(0x0e, 0x0a0b); // B-stage clk
+ cmc623_I2cWrite16(0x22, 0x0400); // H_Size
+ cmc623_I2cWrite16(0x23, 0x0258); // V_Size
+ cmc623_I2cWrite16(0x2c, 0x0fff); //DNR bypass
+ cmc623_I2cWrite16(0x2e, 0x0000); //DNR bypass
+ cmc623_I2cWrite16(0x3a, 0x000c); //HDTR on DE,
+ cmc623_I2cWrite16(0x3b, 0x03ff); //DE strength
+ cmc623_I2cWrite16(0x42, 0x0001); //max_Diff
+ cmc623_I2cWrite16(0x49, 0x0400); //PCC
+ cmc623_I2cWrite16(0x4a, 0x7272);
+ cmc623_I2cWrite16(0x4b, 0x8d8d);
+ cmc623_I2cWrite16(0x4d, 0x01c0);
+ cmc623_I2cWrite16(0xC8, 0x0000); //scr
+ cmc623_I2cWrite16(0xC9, 0x1000);
+ cmc623_I2cWrite16(0xCA, 0xFFFF);
+ cmc623_I2cWrite16(0xCB, 0xFFFF);
+ cmc623_I2cWrite16(0xCC, 0x0000);
+ cmc623_I2cWrite16(0xCD, 0xFFFF);
+ cmc623_I2cWrite16(0xCE, 0x1000);
+ cmc623_I2cWrite16(0xCF, 0xF0F0);
+ cmc623_I2cWrite16(0xD0, 0x00FF);
+ cmc623_I2cWrite16(0xD1, 0x00FF);
+ cmc623_I2cWrite16(0xD2, 0x00FF);
+ cmc623_I2cWrite16(0xD3, 0x00FF);
+ cmc623_I2cWrite16(0x00, 0x0001); //BANK 1
+ cmc623_I2cWrite16(0x09, 0x0400); // H_Size
+ cmc623_I2cWrite16(0x0a, 0x0258); // V_Size
+ cmc623_I2cWrite16(0x0b, 0x0400); // H_Size
+ cmc623_I2cWrite16(0x0c, 0x0258); // V_Size
+ cmc623_I2cWrite16(0x01, 0x0500); // BF_Line
+ cmc623_I2cWrite16(0x06, 0x0062); // Refresh time
+ cmc623_I2cWrite16(0x07, 0x2225); // eDRAM
+ cmc623_I2cWrite16(0x65, 0x0008); // V_Sync cal.
+ cmc623_I2cWrite16(0x68, 0x0080); // TCON Polarity
+ cmc623_I2cWrite16(0x6c, 0x0414); // VLW,HLW
+ cmc623_I2cWrite16(0x6d, 0x0506); // VBP,VFP
+ cmc623_I2cWrite16(0x6e, 0x1e32); // HBP,HFP
+ cmc623_I2cWrite16(0x20, 0x0000); //GAMMA 11
+ cmc623_I2cWrite16(0x21, 0x2000);
+ cmc623_I2cWrite16(0x22, 0x2000);
+ cmc623_I2cWrite16(0x23, 0x2000);
+ cmc623_I2cWrite16(0x24, 0x2000);
+ cmc623_I2cWrite16(0x25, 0x2000);
+ cmc623_I2cWrite16(0x26, 0x2000);
+ cmc623_I2cWrite16(0x27, 0x2000);
+ cmc623_I2cWrite16(0x28, 0x2000);
+ cmc623_I2cWrite16(0x29, 0x1f01);
+ cmc623_I2cWrite16(0x2A, 0x1f01);
+ cmc623_I2cWrite16(0x2B, 0x1f01);
+ cmc623_I2cWrite16(0x2C, 0x1f01);
+ cmc623_I2cWrite16(0x2D, 0x1f01);
+ cmc623_I2cWrite16(0x2E, 0x1f01);
+ cmc623_I2cWrite16(0x2F, 0x1f01);
+ cmc623_I2cWrite16(0x30, 0x1f01);
+ cmc623_I2cWrite16(0x31, 0x1f01);
+ cmc623_I2cWrite16(0x32, 0x1f01);
+ cmc623_I2cWrite16(0x33, 0x1f01);
+ cmc623_I2cWrite16(0x34, 0xa20b);
+ cmc623_I2cWrite16(0x35, 0xa20b);
+ cmc623_I2cWrite16(0x36, 0x2000);
+ cmc623_I2cWrite16(0x37, 0x1f08);
+ cmc623_I2cWrite16(0x38, 0xFF00);
+ cmc623_I2cWrite16(0x20, 0x0001); // GAMMA 11
+ cmc623_I2cWrite16(0x00, 0x0000);
+ cmc623_I2cWrite16(0x28, 0x0000);
+ cmc623_I2cWrite16(0x09, 0x0000);
+ cmc623_I2cWrite16(0x09, 0xffff);
+
+ //delay 5ms
+ msleep(5);
+
+ cmc623_I2cWrite16(0x26, 0x0001);
+
+ printk("**** < end cmc623_tuning_set > *****\n");
+
+ return ret;
+}
+
+// value: 0 ~ 1600
+void tune_cmc623_pwm_brightness(int value)
+{
+ u32 reg, data;
+
+ if(!p_cmc623_data)
+ {
+ printk(KERN_ERR "%s cmc623 is not initialized\n", __func__);
+ }
+
+ if(value<0)
+ data = 0;
+ else if(value>1600)
+ data = 1600;
+ else
+ data = value;
+
+ reg = 0x4000 | data;
+
+ cmc623_I2cWrite16(0x00, 0x0000); //bank0
+ cmc623_I2cWrite16(0xB4, reg); //pwn duty
+ cmc623_I2cWrite16(0x28, 0x0000);
+}
+EXPORT_SYMBOL(tune_cmc623_pwm_brightness);
+
+static int tune_cmc623_hw_rst()
+{
+ if (gpio_is_valid(GPIO_CMC_BYPASS))
+ {
+ gpio_direction_output(GPIO_CMC_BYPASS, GPIO_LEVEL_LOW);
+ }
+ s3c_gpio_setpull(GPIO_CMC_BYPASS, S3C_GPIO_PULL_NONE);
+ gpio_set_value(GPIO_CMC_BYPASS, GPIO_LEVEL_HIGH);
+ msleep(2);
+
+ if (gpio_is_valid(GPIO_CMC_RST))
+ {
+ gpio_direction_output(GPIO_CMC_RST, GPIO_LEVEL_HIGH);
+ }
+ s3c_gpio_setpull(GPIO_CMC_RST, S3C_GPIO_PULL_NONE);
+ gpio_set_value(GPIO_CMC_RST, GPIO_LEVEL_LOW);
+ msleep(4);
+ gpio_set_value(GPIO_CMC_RST, GPIO_LEVEL_HIGH);
+ msleep(5);
+
+ return 0;
+}
+
+int tune_cmc623_suspend()
+{
+ printk(KERN_INFO "%s called\n", __func__);
+
+ if(!p_cmc623_data)
+ {
+ printk(KERN_ERR "%s cmc623 is not initialized\n", __func__);
+ return 0;
+ }
+
+ // 1.2V/1.8V/3.3V may be on
+
+ // CMC623[0x07] := 0x0004
+ cmc623_I2cWrite16(0x07, 0x0004);
+
+ // SLEEPB(L6) <= LOW
+ gpio_set_value(GPIO_CMC_SLEEP, GPIO_LEVEL_LOW);
+
+ // BYPASSB(A2) <= LOW
+ gpio_set_value(GPIO_CMC_BYPASS, GPIO_LEVEL_LOW);
+
+ // wait 1ms
+ msleep(1);
+
+ // FAILSAFEB(E6) <= LOW
+ gpio_set_value(GPIO_CMC_SHDN, GPIO_LEVEL_LOW);
+
+ // 1.2V/3.3V off
+ gpio_set_value(GPIO_CMC_EN, GPIO_LEVEL_LOW);
+
+ // FAILSAFEB(E6) <= HIGH
+ gpio_set_value(GPIO_CMC_SHDN, GPIO_LEVEL_HIGH);
+
+ // 1.8V off (optional, but all io lines shoud be all low or all high or all high-z while sleep for preventing leakage current)
+
+ // Reset chip
+ //gpio_set_value(GPIO_CMC_RST, GPIO_LEVEL_LOW);
+ //mdelay(4);
+
+ return 0;
+}
+EXPORT_SYMBOL(tune_cmc623_suspend);
+
+int tune_cmc623_resume()
+{
+ printk(KERN_INFO "%s called\n", __func__);
+
+ if(!p_cmc623_data)
+ {
+ printk(KERN_ERR "%s cmc623 is not initialized\n", __func__);
+ return 0;
+ }
+
+ // 1.2V/1.8V/3.3V may be off
+
+ // 1.2V/1.8V/3.3V on
+ gpio_set_value(GPIO_CMC_EN, GPIO_LEVEL_HIGH);
+
+ // FAILSAFEB(E6) <= HIGH
+ gpio_set_value(GPIO_CMC_SHDN, GPIO_LEVEL_HIGH);
+
+ // SLEEPB(L6) <= HIGH
+ gpio_set_value(GPIO_CMC_SLEEP, GPIO_LEVEL_HIGH);
+
+ // BYPASSB(A2) <= HIGH
+ gpio_set_value(GPIO_CMC_BYPASS, GPIO_LEVEL_HIGH);
+
+ // RESETB(K6) <= HIGH
+ gpio_set_value(GPIO_CMC_RST, GPIO_LEVEL_HIGH);
+
+ // wait 0.1ms or above
+ udelay(100);
+
+ // RESETB(K6) <= LOW
+ gpio_set_value(GPIO_CMC_RST, GPIO_LEVEL_LOW);
+
+ // wait 4ms or above
+ msleep(4);
+
+ // RESETB(K6) <= HIGH
+ gpio_set_value(GPIO_CMC_RST, GPIO_LEVEL_HIGH);
+
+ // wait 0.3ms or above
+ udelay(300);
+
+ // set registers using I2C
+ cmc623_tuning_set();
+
+ return 0;
+}
+EXPORT_SYMBOL(tune_cmc623_resume);
+
+static ssize_t tune_cmc623_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int ret=0;
+
+#ifdef CMC623_TUNING
+ klogi("");
+ ret = cmc623_load_data();
+#endif
+
+ if(ret<0)
+ {
+ return sprintf(buf, "FAIL\n");
+ }
+ else
+ {
+ return sprintf(buf, "OK\n");
+ }
+}
+
+static ssize_t tune_cmc623_store(struct device *dev, struct device_attribute *attr,const char *buf, size_t size)
+{
+ return size;
+}
+
+static DEVICE_ATTR(tune, S_IRUGO | S_IWUSR, tune_cmc623_show, tune_cmc623_store);
+
+static ssize_t register_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int ret=0;
+
+ return sprintf(buf, "OK\n");
+}
+
+static ssize_t register_store(struct device *dev, struct device_attribute *attr,const char *buf, size_t size)
+{
+ int ret;
+ u32 data1, data2;
+
+ printk("[cmc623] %s : %s\n", __func__, buf);
+ ret = sscanf(buf, "0x%x 0x%x\n", &data1, &data2);
+ if(ret == 2)
+ {
+ printk("addr:0x%04x, data:0x%04x\n", data1, data2);
+ cmc623_I2cWrite16(data1, data2);
+ }
+ else
+ {
+ printk("parse error num:%d, data:0x%04x, data:0x%04x\n", ret, data1, data2);
+ }
+
+ return size;
+}
+
+static DEVICE_ATTR(register, S_IRUGO | S_IWUSR, register_show, register_store);
+
+/*
+static int cmc623_attach(struct i2c_adapter *adap, int addr, int kind)
+{
+ struct i2c_client *c;
+ int ret;
+
+ printk("==============================\n");
+ printk("cmc623 attach START!!! \n");
+ printk("==============================\n");
+
+ c = kmalloc(sizeof(*c), GFP_KERNEL);
+ if (!c)
+ {
+ return -ENOMEM;
+ }
+
+ memset(c, 0, sizeof(struct i2c_client));
+ // strncpy(c->name, cmc623_i2c_driver.driver.name, I2C_NAME_SIZE);
+ strncpy(c->name, "sec_tune_cmc623_i2c" , I2C_NAME_SIZE);
+
+ c->addr = addr;
+ c->adapter = adap;
+ // c->driver = &cmc623_i2c_driver;
+ c->driver = &sec_tune_cmc623_i2c_driver; // P1_LSJ : DE07
+
+ ret = i2c_attach_client(c);
+ if (ret < 0)
+ {
+ printk("cmc623 attach failed!!! (%d)\n", ret);
+ return ret;
+ }
+
+ printk("cmc623 attach success!!!\n");
+
+ cmc623_i2c_client = c;
+ return 0;
+}
+*/
+
+static int cmc623_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+ struct cmc623_data *data;
+// struct i2c_client *c;
+ int ret = 0;
+
+ printk("==============================\n");
+ printk("cmc623 attach START!!! \n");
+ printk("==============================\n");
+
+ data = kzalloc(sizeof(struct cmc623_data), GFP_KERNEL);
+ if (!data)
+ {
+ dev_err(&client->dev, "Failed to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ data->client = client;
+ i2c_set_clientdata(client, data);
+
+ dev_info(&client->dev, "cmc623 i2c probe success!!!\n");
+
+ p_cmc623_data = data;
+
+ tune_cmc623_hw_rst();
+ cmc623_tuning_set();
+
+// ret = cmc623_gamma_set(); // P1_LSJ : DE19
+ printk("cmc623_gamma_set Return value (%d)\n", ret);
+
+// cmc623_i2c_client = c;
+ return 0;
+}
+
+static int __devexit cmc623_i2c_remove(struct i2c_client *client)
+{
+ struct cmc623_data *data = i2c_get_clientdata(client);
+
+ p_cmc623_data = NULL;
+
+ i2c_set_clientdata(client, NULL);
+
+ kfree(data);
+
+ dev_info(&client->dev, "cmc623 i2c remove success!!!\n");
+
+ return 0;
+}
+
+static const struct i2c_device_id sec_tune_cmc623_ids[] = {
+ { "sec_tune_cmc623_i2c", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, sec_tune_cmc623_ids);
+
+struct i2c_driver sec_tune_cmc623_i2c_driver =
+{
+ .driver = {
+ .name = "sec_tune_cmc623_i2c",
+ .owner = THIS_MODULE,
+ },
+ .probe = cmc623_i2c_probe,
+ .remove = __devexit_p(cmc623_i2c_remove),
+ .id_table = sec_tune_cmc623_ids,
+};
+
+extern struct class *sec_class;
+struct device *tune_cmc623_dev;
+
+static int __devinit cmc623_probe(struct platform_device *pdev)
+{
+ int ret=0;
+
+ printk("**** < cmc623_probe > ***********\n");
+
+ tune_cmc623_dev = device_create(sec_class, NULL, 0, NULL, "sec_tune_cmc623");
+
+ if (IS_ERR(tune_cmc623_dev))
+ {
+ printk("Failed to create device!");
+ ret = -1;
+ }
+ if (device_create_file(tune_cmc623_dev, &dev_attr_tune) < 0) {
+ printk("Failed to create device file!(%s)!\n", dev_attr_tune.attr.name);
+ ret = -1;
+ }
+ if (device_create_file(tune_cmc623_dev, &dev_attr_register) < 0) {
+ printk("Failed to create device file!(%s)!\n", dev_attr_register.attr.name);
+ ret = -1;
+ }
+
+ printk("<sec_tune_cmc623_i2c_driver Add START> \n");
+ ret = i2c_add_driver(&sec_tune_cmc623_i2c_driver); // P1_LSJ : DE07
+ printk("cmc623_init Return value (%d)\n", ret);
+
+// ret = cmc623_gamma_set(); // P1_LSJ : DE19
+// printk("cmc623_gamma_set Return value (%d)\n", ret);
+ printk("<sec_tune_cmc623_i2c_driver Add END> \n");
+
+ return ret;
+}
+
+static int __devexit cmc623_remove(struct platform_device *pdev)
+{
+ i2c_del_driver(&sec_tune_cmc623_i2c_driver);
+
+ return 0;
+}
+
+struct platform_driver sec_tune_cmc623 = {
+ .driver = {
+ .name = "sec_tune_cmc623",
+ .owner = THIS_MODULE,
+ },
+ .probe = cmc623_probe,
+ .remove = cmc623_remove,
+};
+
+/*
+static int cmc623_attach_adapter(struct i2c_adapter *adap)
+{
+ printk("%s\n", __func__);
+ return i2c_probe(adap, &cmc623_addr_data, cmc623_attach); // P1_LSJ : DE07
+}
+*/
+
+static int __init cmc623_init(void)
+{
+ int ret=0;
+
+ #if 0 // P1_LSJ : DE04 // dgahn.test: turn off AP LED
+ klogi("***** System LED turned off");
+ NvOdmServicesGpioHandle hGpio;
+ NvOdmGpioPinHandle hLEDApGpioPin;
+
+ hGpio = NvOdmGpioOpen();
+ hLEDApGpioPin = NvOdmGpioAcquirePinHandle(hGpio, GPIO_PORT_LEDAP, GPIO_PIN_LEDAP);
+
+ NvOdmGpioSetState(hGpio, hLEDApGpioPin, 0x0); // set low
+ NvOdmGpioConfig(hGpio, hLEDApGpioPin, NvOdmGpioPinMode_Output);
+
+ NvOdmGpioClose(hGpio);
+ #endif
+
+ printk("**************************************\n");
+ printk("**** < cmc623_init > **\n");
+ printk("**************************************\n");
+
+ return platform_driver_register(&sec_tune_cmc623);
+}
+
+static void __exit cmc623_exit(void)
+{
+ platform_driver_unregister(&sec_tune_cmc623);
+}
+
+// module_init(cmc623_init);
+module_init(cmc623_init);
+module_exit(cmc623_exit);
+
+/* Module information */
+MODULE_AUTHOR("Samsung");
+MODULE_DESCRIPTION("Tuning CMC623 image converter");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/samsung/tune_cmc623.h b/drivers/video/samsung/tune_cmc623.h
new file mode 100644
index 0000000..86cd11b
--- /dev/null
+++ b/drivers/video/samsung/tune_cmc623.h
@@ -0,0 +1,138 @@
+#ifndef TUNE2CMC623_HEADER
+#define TUNE2CMC623_HEADER
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+/** CMC623 registers **/
+
+
+/* SFR Bank selection */
+#define CMC623_REG_SELBANK 0x00 // Bank0
+
+/* A stage configuration */
+#define CMC623_REG_DNRHDTROVE 0x01
+#define CMC623_REG_DITHEROFF 0x06
+#define CMC623_REG_CLKCONT 0x10
+#define CMC623_REG_CLKGATINGOFF 0x0a
+#define CMC623_REG_INPUTIFCON 0x24
+#define CMC623_REG_CLKMONCONT 0x11 // Clock Monitor Ctrl Register
+#define CMC623_REG_HDRTCEOFF 0x3a
+#define CMC623_REG_I2C 0x0d
+#define CMC623_REG_BSTAGE 0x0e
+#define CMC623_REG_CABCCTRL 0x7c
+#define CMC623_REG_PWMCTRL 0xb4
+#define CMC623_REG_OVEMAX 0x54
+
+/* A stage image size */
+#define CMC623_REG_1280 0x22
+#define CMC623_REG_800 0x23
+
+/* B stage image size */
+#define CMC623_REG_SCALERINPH 0x09
+#define CMC623_REG_SCALERINPV 0x0a
+#define CMC623_REG_SCALEROUTH 0x0b
+#define CMC623_REG_SCALEROUTV 0x0c
+
+/* EDRAM configuration */
+#define CMC623_REG_EDRBFOUT40 0x01
+#define CMC623_REG_EDRAUTOREF 0x06
+#define CMC623_REG_EDRACPARAMTIM 0x07
+
+/* Vsync Calibartion */
+#define CMC623_REG_CALVAL10 0x65
+
+/* tcon output polarity */
+#define CMC623_REG_TCONOUTPOL 0x68
+
+/* tcon RGB configuration */
+#define CMC623_REG_TCONRGB1 0x6c
+#define CMC623_REG_TCONRGB2 0x6d
+#define CMC623_REG_TCONRGB3 0x6e
+
+/* Reg update */
+#define CMC623_REG_REGMASK 0x28
+#define CMC623_REG_SWRESET 0x09
+#define CMC623_REG_RGBIFEN 0x26
+
+#if 1 // P1_LSJ : DE04
+typedef struct
+{
+ unsigned char RegAddr;
+ unsigned long Data; // data to write
+}Cmc623RegisterSet;
+#else
+typedef struct
+{
+ NvU8 RegAddr;
+ NvU32 Data; // data to write
+}Cmc623RegisterSet;
+#endif
+
+static Cmc623RegisterSet Cmc623_InitSeq[] =
+{
+ /* select SFR Bank0 */
+ {CMC623_REG_SELBANK, 0x0000},
+
+ /* A stage configuration */
+ {CMC623_REG_DNRHDTROVE, 0x0030},
+ {CMC623_REG_DITHEROFF, 0x0000},
+ {CMC623_REG_CLKCONT, 0x0012},
+ {CMC623_REG_CLKGATINGOFF, 0x0000},
+ {CMC623_REG_INPUTIFCON, 0x0001},
+ // {CMC623_REG_CLKMONCONT, 0x0081},
+ {CMC623_REG_HDRTCEOFF, 0x001d},
+ {CMC623_REG_I2C, 0x180a},
+ {CMC623_REG_BSTAGE, 0x0a0b},
+ {CMC623_REG_CABCCTRL, 0x0002},
+ {CMC623_REG_PWMCTRL, 0x5000},
+
+ // {CMC623_REG_OVEMAX, 0x8080},
+ {CMC623_REG_1280, 0x0500},
+ {CMC623_REG_800, 0x0320},
+
+ /* select SFR Bank1 */
+ {CMC623_REG_SELBANK, 0x0001},
+
+ /* B stage image size */
+ {CMC623_REG_SCALERINPH, 0x0500},
+ {CMC623_REG_SCALERINPV, 0x0320},
+ {CMC623_REG_SCALEROUTH, 0x0500},
+ {CMC623_REG_SCALEROUTV, 0x0320},
+
+ /* EDRAM configuration */
+ {CMC623_REG_EDRBFOUT40, 0x0280},
+ {CMC623_REG_EDRAUTOREF, 0x0059},
+ {CMC623_REG_EDRACPARAMTIM, 0x2225},
+
+ /* Vsync Calibartion */
+ {CMC623_REG_CALVAL10, 0x000a},
+
+ /* tcon output polarity */
+ {CMC623_REG_TCONOUTPOL, 0x0008},
+
+ /* tcon RGB configuration */
+ {CMC623_REG_TCONRGB1, 0x0488},
+ {CMC623_REG_TCONRGB2, 0x1504},
+ {CMC623_REG_TCONRGB3, 0x8a22},
+
+ /* Reg update */
+ {CMC623_REG_SELBANK, 0x0000}, // select BANK0
+ {CMC623_REG_REGMASK, 0x0000},
+ {CMC623_REG_SWRESET, 0x0000}, // SW reset
+ {CMC623_REG_SWRESET, 0xffff}, // !SW reset, (!note: sleep required after this)
+ {CMC623_REG_RGBIFEN, 0x0001}, // enable RGB IF
+};
+
+static int cmc623_attach_adapter(struct i2c_adapter *adap);
+
+extern int tune_cmc623_suspend();
+extern int tune_cmc623_resume();
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif //TUNE2CMC623_HEADER
diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c
index 415e9b2..6a7725a 100644
--- a/drivers/video/udlfb.c
+++ b/drivers/video/udlfb.c
@@ -613,7 +613,7 @@ static ssize_t dlfb_ops_write(struct fb_info *info, const char __user *buf,
result = fb_sys_write(info, buf, count, ppos);
if (result > 0) {
- int start = max((int)(offset / info->fix.line_length) - 1, 0);
+ int start = max((int)(offset / info->fix.line_length), 0);
int lines = min((u32)((result / info->fix.line_length) + 1),
(u32)info->var.yres);
diff --git a/drivers/video/via/via_clock.c b/drivers/video/via/via_clock.c
index af8f26b..db1e392 100644
--- a/drivers/video/via/via_clock.c
+++ b/drivers/video/via/via_clock.c
@@ -25,6 +25,7 @@
#include <linux/kernel.h>
#include <linux/via-core.h>
+#include <asm/olpc.h>
#include "via_clock.h"
#include "global.h"
#include "debug.h"
@@ -289,6 +290,10 @@ static void dummy_set_pll(struct via_pll_config config)
printk(KERN_INFO "Using undocumented set PLL.\n%s", via_slap);
}
+static void noop_set_clock_state(u8 state)
+{
+}
+
void via_clock_init(struct via_clock *clock, int gfx_chip)
{
switch (gfx_chip) {
@@ -346,4 +351,18 @@ void via_clock_init(struct via_clock *clock, int gfx_chip)
break;
}
+
+ if (machine_is_olpc()) {
+ /* The OLPC XO-1.5 cannot suspend/resume reliably if the
+ * IGA1/IGA2 clocks are set as on or off (memory rot
+ * occasionally happens during suspend under such
+ * configurations).
+ *
+ * The only known stable scenario is to leave this bits as-is,
+ * which in their default states are documented to enable the
+ * clock only when it is needed.
+ */
+ clock->set_primary_clock_state = noop_set_clock_state;
+ clock->set_secondary_clock_state = noop_set_clock_state;
+ }
}
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c
index d4ab797..479484f 100644
--- a/drivers/watchdog/hpwdt.c
+++ b/drivers/watchdog/hpwdt.c
@@ -773,6 +773,9 @@ static int __devinit hpwdt_init_one(struct pci_dev *dev,
hpwdt_timer_reg = pci_mem_addr + 0x70;
hpwdt_timer_con = pci_mem_addr + 0x72;
+ /* Make sure that timer is disabled until /dev/watchdog is opened */
+ hpwdt_stop();
+
/* Make sure that we have a valid soft_margin */
if (hpwdt_change_timer(soft_margin))
hpwdt_change_timer(DEFAULT_MARGIN);
diff --git a/firmware/Makefile b/firmware/Makefile
index 5f43bfb..1eebc0b 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -26,6 +26,7 @@ fw-shipped- += acenic/tg1.bin
else
acenic-objs := acenic/tg1.bin acenic/tg2.bin
endif
+fw-shipped-$(CONFIG_VIDEO_MFC50) += samsung_mfc_fw.bin
fw-shipped-$(CONFIG_3C359) += 3com/3C359.bin
fw-shipped-$(CONFIG_ACENIC) += $(acenic-objs)
fw-shipped-$(CONFIG_ADAPTEC_STARFIRE) += adaptec/starfire_rx.bin \
diff --git a/firmware/samsung_mfc_fw.bin.ihex b/firmware/samsung_mfc_fw.bin.ihex
new file mode 100644
index 0000000..6daac7e
--- /dev/null
+++ b/firmware/samsung_mfc_fw.bin.ihex
@@ -0,0 +1,18777 @@
+:1000000000000000000000000000000000000000F0
+:1000100000000000000000000000000000000000E0
+:1000200000000000000000000000000000000000D0
+:1000300000000000000000000000000000000000C0
+:1000400000000000000000000000000000000000B0
+:1000500000000000000000000000000000000000A0
+:100060000000000000000000000000000000000090
+:100070000000000000000000000000000000000080
+:100080000000000000000000000000000000000070
+:100090000000000000000000000000000000000060
+:1000A0000000000000000000000000000000000050
+:1000B0000000000000000000000000000000000040
+:1000C0000000000000000000000000000000000030
+:1000D0000000000000000000000000000000000020
+:1000E0000000000000000000000000000000000010
+:1000F0000000000000000000000000000000000000
+:1001000000000015000000150000009C0000409C4D
+:100110000000609C0000809C0000A09C0000C09C2F
+:100120000000E09C0000009D0000209D0000409D1C
+:100130000000609D0000809D0000A09D0000C09D0B
+:100140000000E09D0000009E0000209E0000409EF8
+:100150000000609E0000809E0000A09E0000C09EE7
+:100160000000E09E0000009F0000209F0000409FD4
+:100170000000609F0000809F0000A09F0000C09FC3
+:100180000000E09F00006018002063A800180044F1
+:10019000000000150000000000000000000000004A
+:1001A000000000000000000000000000000000004F
+:1001B000000000000000000000000000000000003F
+:1001C000000000000000000000000000000000002F
+:1001D000000000000000000000000000000000001F
+:1001E000000000000000000000000000000000000F
+:1001F00000000000000000000000000000000000FF
+:100200008CFF219C184801D449030004000000150C
+:1002100000002019A40F29A90400401954804AA9FC
+:1002200000004A8500500044000000150000000056
+:1002300000000000000000000000000000000000BE
+:1002400000000000000000000000000000000000AE
+:10025000000000000000000000000000000000009E
+:10026000000000000000000000000000000000008E
+:10027000000000000000000000000000000000007E
+:10028000000000000000000000000000000000006E
+:10029000000000000000000000000000000000005E
+:1002A000000000000000000000000000000000004E
+:1002B000000000000000000000000000000000003E
+:1002C000000000000000000000000000000000002E
+:1002D000000000000000000000000000000000001E
+:1002E000000000000000000000000000000000000E
+:1002F00000000000000000000000000000000000FE
+:100300008CFF219C184801D409030004000000154B
+:1003100000002019A40F29A90400401968804AA9E7
+:1003200000004A8500500044000000150000000055
+:1003300000000000000000000000000000000000BD
+:1003400000000000000000000000000000000000AD
+:10035000000000000000000000000000000000009D
+:10036000000000000000000000000000000000008D
+:10037000000000000000000000000000000000007D
+:10038000000000000000000000000000000000006D
+:10039000000000000000000000000000000000005D
+:1003A000000000000000000000000000000000004D
+:1003B000000000000000000000000000000000003D
+:1003C000000000000000000000000000000000002D
+:1003D000000000000000000000000000000000001D
+:1003E000000000000000000000000000000000000D
+:1003F00000000000000000000000000000000000FD
+:100400008CFF219C184801D4C9020004000000158B
+:1004100000002019A40F29A90400401974804AA9DA
+:1004200000004A8500500044000000150000000054
+:1004300000000000000000000000000000000000BC
+:1004400000000000000000000000000000000000AC
+:10045000000000000000000000000000000000009C
+:10046000000000000000000000000000000000008C
+:10047000000000000000000000000000000000007C
+:10048000000000000000000000000000000000006C
+:10049000000000000000000000000000000000005C
+:1004A000000000000000000000000000000000004C
+:1004B000000000000000000000000000000000003C
+:1004C000000000000000000000000000000000002C
+:1004D000000000000000000000000000000000001C
+:1004E000000000000000000000000000000000000C
+:1004F00000000000000000000000000000000000FC
+:100500008CFF219C184801D48902000400000015CA
+:1005100000002019A40F29A90400401964804AA9E9
+:1005200000004A8500500044000000150000000053
+:1005300000000000000000000000000000000000BB
+:1005400000000000000000000000000000000000AB
+:10055000000000000000000000000000000000009B
+:10056000000000000000000000000000000000008B
+:10057000000000000000000000000000000000007B
+:10058000000000000000000000000000000000006B
+:10059000000000000000000000000000000000005B
+:1005A000000000000000000000000000000000004B
+:1005B000000000000000000000000000000000003B
+:1005C000000000000000000000000000000000002B
+:1005D000000000000000000000000000000000001B
+:1005E000000000000000000000000000000000000B
+:1005F00000000000000000000000000000000000FB
+:100600008CFF219C184801D4490200040000001509
+:1006100000002019A40F29A90400401970804AA9DC
+:1006200000004A8500500044000000150000000052
+:1006300000000000000000000000000000000000BA
+:1006400000000000000000000000000000000000AA
+:10065000000000000000000000000000000000009A
+:10066000000000000000000000000000000000008A
+:10067000000000000000000000000000000000007A
+:10068000000000000000000000000000000000006A
+:10069000000000000000000000000000000000005A
+:1006A000000000000000000000000000000000004A
+:1006B000000000000000000000000000000000003A
+:1006C000000000000000000000000000000000002A
+:1006D000000000000000000000000000000000001A
+:1006E000000000000000000000000000000000000A
+:1006F00000000000000000000000000000000000FA
+:100700008CFF219C184801D4090200040000001548
+:1007100000002019A40F29A90400401984804AA9C7
+:1007200000004A8500500044000000150000000051
+:1007300000000000000000000000000000000000B9
+:1007400000000000000000000000000000000000A9
+:100750000000000000000000000000000000000099
+:100760000000000000000000000000000000000089
+:100770000000000000000000000000000000000079
+:100780000000000000000000000000000000000069
+:100790000000000000000000000000000000000059
+:1007A0000000000000000000000000000000000049
+:1007B0000000000000000000000000000000000039
+:1007C0000000000000000000000000000000000029
+:1007D0000000000000000000000000000000000019
+:1007E0000000000000000000000000000000000009
+:1007F00000000000000000000000000000000000F9
+:100800008CFF219C184801D4C90100040000001588
+:1008100000002019A40F29A90400401978804AA9D2
+:1008200000004A8500500044000000150000000050
+:1008300000000000000000000000000000000000B8
+:1008400000000000000000000000000000000000A8
+:100850000000000000000000000000000000000098
+:100860000000000000000000000000000000000088
+:100870000000000000000000000000000000000078
+:100880000000000000000000000000000000000068
+:100890000000000000000000000000000000000058
+:1008A0000000000000000000000000000000000048
+:1008B0000000000000000000000000000000000038
+:1008C0000000000000000000000000000000000028
+:1008D0000000000000000000000000000000000018
+:1008E0000000000000000000000000000000000008
+:1008F00000000000000000000000000000000000F8
+:100900008CFF219C184801D48901000400000015C7
+:1009100000002019A40F29A9040040197C804AA9CD
+:1009200000004A850050004400000015000000004F
+:1009300000000000000000000000000000000000B7
+:1009400000000000000000000000000000000000A7
+:100950000000000000000000000000000000000097
+:100960000000000000000000000000000000000087
+:100970000000000000000000000000000000000077
+:100980000000000000000000000000000000000067
+:100990000000000000000000000000000000000057
+:1009A0000000000000000000000000000000000047
+:1009B0000000000000000000000000000000000037
+:1009C0000000000000000000000000000000000027
+:1009D0000000000000000000000000000000000017
+:1009E0000000000000000000000000000000000007
+:1009F00000000000000000000000000000000000F7
+:100A00008CFF219C184801D4490100040000001506
+:100A100000002019A40F29A9040040195C804AA9EC
+:100A200000004A850050004400000015000000004E
+:100A300000000000000000000000000000000000B6
+:100A400000000000000000000000000000000000A6
+:100A50000000000000000000000000000000000096
+:100A60000000000000000000000000000000000086
+:100A70000000000000000000000000000000000076
+:100A80000000000000000000000000000000000066
+:100A90000000000000000000000000000000000056
+:100AA0000000000000000000000000000000000046
+:100AB0000000000000000000000000000000000036
+:100AC0000000000000000000000000000000000026
+:100AD0000000000000000000000000000000000016
+:100AE0000000000000000000000000000000000006
+:100AF00000000000000000000000000000000000F6
+:100B00008CFF219C184801D4090100040000001545
+:100B100000002019A40F29A90400401960804AA9E7
+:100B200000004A850050004400000015000000004D
+:100B300000000000000000000000000000000000B5
+:100B400000000000000000000000000000000000A5
+:100B50000000000000000000000000000000000095
+:100B60000000000000000000000000000000000085
+:100B70000000000000000000000000000000000075
+:100B80000000000000000000000000000000000065
+:100B90000000000000000000000000000000000055
+:100BA0000000000000000000000000000000000045
+:100BB0000000000000000000000000000000000035
+:100BC0000000000000000000000000000000000025
+:100BD0000000000000000000000000000000000015
+:100BE0000000000000000000000000000000000005
+:100BF00000000000000000000000000000000000F5
+:100C00000400639C110080B4070084A40020C0E0AD
+:100C1000200080B40000A0182410A5A80228A4E099
+:100C2000400080B4010084A8402000C0000080186B
+:100C3000441084A8202000C0000000240800639C09
+:100C400000000000000000000000000000000000A4
+:100C50000000000000000000000000000000000094
+:100C60000000000000000000000000000000000084
+:100C70000000000000000000000000000000000074
+:100C80000000000000000000000000000000000064
+:100C90000000000000000000000000000000000054
+:100CA0000000000000000000000000000000000044
+:100CB0000000000000000000000000000000000034
+:100CC0000000000000000000000000000000000024
+:100CD0000000000000000000000000000000000014
+:100CE0000000000000000000000000000000000004
+:100CF00000000000000000000000000000000000F4
+:100D00008CFF219C184801D48900000400000015C4
+:100D100000002019A40F29A90400401958804AA9ED
+:100D200000004A850050004400000015000000004B
+:100D300000000000000000000000000000000000B3
+:100D400000000000000000000000000000000000A3
+:100D50000000000000000000000000000000000093
+:100D60000000000000000000000000000000000083
+:100D70000000000000000000000000000000000073
+:100D80000000000000000000000000000000000063
+:100D90000000000000000000000000000000000053
+:100DA0000000000000000000000000000000000043
+:100DB0000000000000000000000000000000000033
+:100DC0000000000000000000000000000000000023
+:100DD0000000000000000000000000000000000013
+:100DE0000000000000000000000000000000000003
+:100DF00000000000000000000000000000000000F3
+:100E00008CFF219C184801D4490000040000001503
+:100E100000002019A40F29A90400401988804AA9BC
+:100E200000004A850050004400000015000000004A
+:100E300000000000000000000000000000000000B2
+:100E400000000000000000000000000000000000A2
+:100E50000000000000000000000000000000000092
+:100E60000000000000000000000000000000000082
+:100E70000000000000000000000000000000000072
+:100E80000000000000000000000000000000000062
+:100E90000000000000000000000000000000000052
+:100EA0000000000000000000000000000000000042
+:100EB0000000000000000000000000000000000032
+:100EC0000000000000000000000000000000000022
+:100ED0000000000000000000000000000000000012
+:100EE000F0FF219C001001D41000419CFC1FE2D7B0
+:100EF000F827E2D7FCFF628400408018000084A835
+:100F0000002063E0F41FE2D7F4FF628400008384D2
+:100F1000F8FF6284001804E4FCFFFF1300000015D2
+:100F200000004184004800441000219C001801D4B6
+:100F3000042001D4082801D40C3001D4103801D485
+:100F4000144001D41C5001D4205801D4246001D491
+:100F5000286801D42C7001D4307801D4348001D4B5
+:100F6000388801D43C9001D4409801D444A001D4E5
+:100F700048A801D44CB001D450B801D454C001D415
+:100F800058C801D45CD001D460D801D464E001D445
+:100F900068E801D46CF001D470F801D40048004432
+:100FA0000000001500006184040081840800A18411
+:100FB0000C00C1841000E184140001851800218513
+:100FC0001C00418520006185240081852800A185C1
+:100FD0002C00C1853000E18534000186380021866F
+:100FE0003C00418640006186440081864800A1861D
+:100FF0004C00C1865000E1865400018758002187CB
+:101000005C00418760006187640081876800A18778
+:101010006C00C1877000E1877400219C00000024EF
+:1010200000000015FEFF609C110080B4031884E0EE
+:10103000060084A8112000C00000609C0100002070
+:101040000200639C0000609D110080B4070084A42E
+:10105000070004BC030000100000001501006B9D98
+:10106000040003BC030000100000001502006B9D8B
+:101070001C0005BC030000100000001504006B9D5F
+:10108000010006BC030000100000001508006B9D65
+:101090000048004400000015110060B4200063A85F
+:1010A000401800C0204800C00000002400000015C7
+:1010B000110060B4400063A8401800C0204800C080
+:1010C00000000024000000150000609D001800448E
+:1010D00000000015110000B5020008A9404000C042
+:1010E000201800C0000000243412601978566BA943
+:1010F00000006485004800440000001534126019A7
+:1011000078566BA900006495004800440000001563
+:1011100034126018785663A8001804D400480044BC
+:101120000000001534126018785663A8001804DC1B
+:1011300000480044000000153412601978566BA96D
+:10114000004800440000648500480044010000217C
+:10115000004800440000001500480044FFFF609C68
+:1011600000480044000000150000609D110060B4BC
+:10117000020063A8111800C001006B9D0000000070
+:101180000000A4840000609D0048004401006B9DA5
+:10119000000000000000000000000000000000004F
+:1011A000000000000000000000000000000000003F
+:1011B000000000000000000000000000000000002F
+:1011C000000000000000000000000000000000001F
+:1011D000000000000000000000000000000000000F
+:1011E00000000000000000000000000000000000FF
+:1011F00000000000000000000000000000000000EF
+:1012000000000000000000000000000000000000DE
+:1012100000000000000000000000000000000000CE
+:1012200000000000000000000000000000000000BE
+:1012300000000000000000000000000000000000AE
+:10124000000000000000000000000000000000009E
+:10125000000000000000000000000000000000008E
+:10126000000000000000000000000000000000007E
+:10127000000000000000000000000000000000006E
+:10128000000000000000000000000000000000005E
+:10129000000000000000000000000000000000004E
+:1012A000000000000000000000000000000000003E
+:1012B000000000000000000000000000000000002E
+:1012C000000000000000000000000000000000001E
+:1012D000000000000000000000000000000000000E
+:1012E00000000000000000000000000000000000FE
+:1012F00000000000000000000000000000000000EE
+:1013000000000000000000000000000000000000DD
+:1013100000000000000000000000000000000000CD
+:1013200000000000000000000000000000000000BD
+:1013300000000000000000000000000000000000AD
+:10134000000000000000000000000000000000009D
+:10135000000000000000000000000000000000008D
+:10136000000000000000000000000000000000007D
+:10137000000000000000000000000000000000006D
+:10138000000000000000000000000000000000005D
+:10139000000000000000000000000000000000004D
+:1013A000000000000000000000000000000000003D
+:1013B000000000000000000000000000000000002D
+:1013C000000000000000000000000000000000001D
+:1013D000000000000000000000000000000000000D
+:1013E00000000000000000000000000000000000FD
+:1013F00000000000000000000000000000000000ED
+:1014000000000000000000000000000000000000DC
+:1014100000000000000000000000000000000000CC
+:1014200000000000000000000000000000000000BC
+:1014300000000000000000000000000000000000AC
+:10144000000000000000000000000000000000009C
+:10145000000000000000000000000000000000008C
+:10146000000000000000000000000000000000007C
+:10147000000000000000000000000000000000006C
+:10148000000000000000000000000000000000005C
+:10149000000000000000000000000000000000004C
+:1014A000000000000000000000000000000000003C
+:1014B000000000000000000000000000000000002C
+:1014C000000000000000000000000000000000001C
+:1014D000000000000000000000000000000000000C
+:1014E00000000000000000000000000000000000FC
+:1014F00000000000000000000000000000000000EC
+:1015000000000000000000000000000000000000DB
+:1015100000000000000000000000000000000000CB
+:1015200000000000000000000000000000000000BB
+:1015300000000000000000000000000000000000AB
+:10154000000000000000000000000000000000009B
+:10155000000000000000000000000000000000008B
+:10156000000000000000000000000000000000007B
+:10157000000000000000000000000000000000006B
+:10158000000000000000000000000000000000005B
+:10159000000000000000000000000000000000004B
+:1015A000000000000000000000000000000000003B
+:1015B000000000000000000000000000000000002B
+:1015C000000000000000000000000000000000001B
+:1015D000000000000000000000000000000000000B
+:1015E00000000000000000000000000000000000FB
+:1015F00000000000000000000000000000000000EB
+:1016000000000000000000000000000000000000DA
+:1016100000000000000000000000000000000000CA
+:1016200000000000000000000000000000000000BA
+:1016300000000000000000000000000000000000AA
+:10164000000000000000000000000000000000009A
+:10165000000000000000000000000000000000008A
+:10166000000000000000000000000000000000007A
+:10167000000000000000000000000000000000006A
+:10168000000000000000000000000000000000005A
+:10169000000000000000000000000000000000004A
+:1016A000000000000000000000000000000000003A
+:1016B000000000000000000000000000000000002A
+:1016C000000000000000000000000000000000001A
+:1016D000000000000000000000000000000000000A
+:1016E00000000000000000000000000000000000FA
+:1016F00000000000000000000000000000000000EA
+:1017000000000000000000000000000000000000D9
+:1017100000000000000000000000000000000000C9
+:1017200000000000000000000000000000000000B9
+:1017300000000000000000000000000000000000A9
+:101740000000000000000000000000000000000099
+:101750000000000000000000000000000000000089
+:101760000000000000000000000000000000000079
+:101770000000000000000000000000000000000069
+:101780000000000000000000000000000000000059
+:101790000000000000000000000000000000000049
+:1017A0000000000000000000000000000000000039
+:1017B0000000000000000000000000000000000029
+:1017C0000000000000000000000000000000000019
+:1017D0000000000000000000000000000000000009
+:1017E00000000000000000000000000000000000F9
+:1017F00000000000000000000000000000000000E9
+:1018000000000000000000000000000000000000D8
+:1018100000000000000000000000000000000000C8
+:1018200000000000000000000000000000000000B8
+:1018300000000000000000000000000000000000A8
+:101840000000000000000000000000000000000098
+:101850000000000000000000000000000000000088
+:101860000000000000000000000000000000000078
+:101870000000000000000000000000000000000068
+:101880000000000000000000000000000000000058
+:101890000000000000000000000000000000000048
+:1018A0000000000000000000000000000000000038
+:1018B0000000000000000000000000000000000028
+:1018C0000000000000000000000000000000000018
+:1018D0000000000000000000000000000000000008
+:1018E00000000000000000000000000000000000F8
+:1018F00000000000000000000000000000000000E8
+:1019000000000000000000000000000000000000D7
+:1019100000000000000000000000000000000000C7
+:1019200000000000000000000000000000000000B7
+:1019300000000000000000000000000000000000A7
+:101940000000000000000000000000000000000097
+:101950000000000000000000000000000000000087
+:101960000000000000000000000000000000000077
+:101970000000000000000000000000000000000067
+:101980000000000000000000000000000000000057
+:101990000000000000000000000000000000000047
+:1019A0000000000000000000000000000000000037
+:1019B0000000000000000000000000000000000027
+:1019C0000000000000000000000000000000000017
+:1019D0000000000000000000000000000000000007
+:1019E00000000000000000000000000000000000F7
+:1019F00000000000000000000000000000000000E7
+:101A000000000000000000000000000000000000D6
+:101A100000000000000000000000000000000000C6
+:101A200000000000000000000000000000000000B6
+:101A300000000000000000000000000000000000A6
+:101A40000000000000000000000000000000000096
+:101A50000000000000000000000000000000000086
+:101A60000000000000000000000000000000000076
+:101A70000000000000000000000000000000000066
+:101A80000000000000000000000000000000000056
+:101A90000000000000000000000000000000000046
+:101AA0000000000000000000000000000000000036
+:101AB0000000000000000000000000000000000026
+:101AC0000000000000000000000000000000000016
+:101AD0000000000000000000000000000000000006
+:101AE00000000000000000000000000000000000F6
+:101AF00000000000000000000000000000000000E6
+:101B000000000000000000000000000000000000D5
+:101B100000000000000000000000000000000000C5
+:101B200000000000000000000000000000000000B5
+:101B300000000000000000000000000000000000A5
+:101B40000000000000000000000000000000000095
+:101B50000000000000000000000000000000000085
+:101B60000000000000000000000000000000000075
+:101B70000000000000000000000000000000000065
+:101B80000000000000000000000000000000000055
+:101B90000000000000000000000000000000000045
+:101BA0000000000000000000000000000000000035
+:101BB0000000000000000000000000000000000025
+:101BC0000000000000000000000000000000000015
+:101BD0000000000000000000000000000000000005
+:101BE00000000000000000000000000000000000F5
+:101BF00000000000000000000000000000000000E5
+:101C000000000000000000000000000000000000D4
+:101C100000000000000000000000000000000000C4
+:101C200000000000000000000000000000000000B4
+:101C300000000000000000000000000000000000A4
+:101C40000000000000000000000000000000000094
+:101C50000000000000000000000000000000000084
+:101C60000000000000000000000000000000000074
+:101C70000000000000000000000000000000000064
+:101C80000000000000000000000000000000000054
+:101C90000000000000000000000000000000000044
+:101CA0000000000000000000000000000000000034
+:101CB0000000000000000000000000000000000024
+:101CC0000000000000000000000000000000000014
+:101CD0000000000000000000000000000000000004
+:101CE00000000000000000000000000000000000F4
+:101CF00000000000000000000000000000000000E4
+:101D000000000000000000000000000000000000D3
+:101D100000000000000000000000000000000000C3
+:101D200000000000000000000000000000000000B3
+:101D300000000000000000000000000000000000A3
+:101D40000000000000000000000000000000000093
+:101D50000000000000000000000000000000000083
+:101D60000000000000000000000000000000000073
+:101D70000000000000000000000000000000000063
+:101D80000000000000000000000000000000000053
+:101D90000000000000000000000000000000000043
+:101DA0000000000000000000000000000000000033
+:101DB0000000000000000000000000000000000023
+:101DC0000000000000000000000000000000000013
+:101DD0000000000000000000000000000000000003
+:101DE00000000000000000000000000000000000F3
+:101DF00000000000000000000000000000000000E3
+:101E000000000000000000000000000000000000D2
+:101E100000000000000000000000000000000000C2
+:101E200000000000000000000000000000000000B2
+:101E300000000000000000000000000000000000A2
+:101E40000000000000000000000000000000000092
+:101E50000000000000000000000000000000000082
+:101E60000000000000000000000000000000000072
+:101E70000000000000000000000000000000000062
+:101E80000000000000000000000000000000000052
+:101E90000000000000000000000000000000000042
+:101EA0000000000000000000000000000000000032
+:101EB0000000000000000000000000000000000022
+:101EC0000000000000000000000000000000000012
+:101ED0000000000000000000000000000000000002
+:101EE00000000000000000000000000000000000F2
+:101EF00000000000000000000000000000000000E2
+:101F000000000000000000000000000000000000D1
+:101F100000000000000000000000000000000000C1
+:101F200000000000000000000000000000000000B1
+:101F300000000000000000000000000000000000A1
+:101F40000000000000000000000000000000000091
+:101F50000000000000000000000000000000000081
+:101F60000000000000000000000000000000000071
+:101F70000000000000000000000000000000000061
+:101F80000000000000000000000000000000000051
+:101F90000000000000000000000000000000000041
+:101FA0000000000000000000000000000000000031
+:101FB0000000000000000000000000000000000021
+:101FC0000000000000000000000000000000000011
+:101FD0000000000000000000000000000000000001
+:101FE00000000000000000000000000000000000F1
+:101FF00000000000000000000000000000000000E1
+:102000000100409D10004AA908004AA9115000C0D3
+:10201000000000150000001500000015000000156C
+:10202000000000150100609C000003BCFFFFFF0FD3
+:10203000FFFF639C0000609C0000809C040020184F
+:1020400040A521A800004018542042A800100044D8
+:1020500000000015FCFF219C004801D44D0700043E
+:10206000000000150500000400006BA80000218599
+:10207000004800440400219C001860E001000015A5
+:10208000000000000000001500480044000000159A
+:10209000000061840400819C0000639C0000849C1B
+:1020A0000300001500480044000000150000639C78
+:1020B00002000015004800440000001500480044DC
+:1020C0000000001500480044000000150000609D5D
+:1020D0000048004400000015002003C000480044F0
+:1020E00000000015000063B4000063A9004800442C
+:1020F00000000015002003D4004800440000001533
+:1021000000006384000063A900480044000000153B
+:10211000FFFFA59CFFFFC09C003025E40A00000CD7
+:10212000000063A90000E48CFFFFA59C003803D8E1
+:102130000100849C003025E4FBFFFF130100639C39
+:10214000000063A90048004400000015FFFF639CE5
+:10215000481884E0010084A4000064A900480044F9
+:1021600000000015482065E12100E09CFFFFC09CB5
+:1021700001006BB90220E7E004186BE1FFFF849CCB
+:102180004838C6E008206BE10330A5E004286BE185
+:102190000048004400000015000083A80000609D76
+:1021A00000006390005823E40700000C0000A09C8E
+:1021B0000100849C00006490002823E4FDFFFF13CD
+:1021C00001006B9D0048004400000015DCFF219CCD
+:1021D000004801D4045001D4086001D40C7001D42B
+:1021E000108001D41400019E000083A9000044A9BE
+:1021F0000000E09C003804E42E0000100000B0A8AD
+:10220000003864E5040000100000609C022040E1FA
+:102210000100E09C00182AE40E00000C0A00009D5A
+:102220000000C09C09438AE0030064B8002063E01A
+:10223000002063E002186AE03000639C000044A9BB
+:10224000001805D8003024E4F7FFFF130100A59C17
+:102250000000609C001807E4050000100000001555
+:102260002D00609C001805D80100A59C0000609C12
+:102270000000409D001805D8000070A8C7FFFF07A8
+:102280000000CCA900588AE50D00000C000070A8E1
+:10229000C2FFFF0701008C9D02506BE100806BE1E3
+:1022A00001004A9DFFFF6B8DF4FFFF0300580ED81D
+:1022B0003000609C00180CD801008C9D00006CA9B7
+:1022C0000000218504004185080081850C00C1853E
+:1022D00010000186004800442400219CDCFF219C62
+:1022E000004801D4045001D4086001D40C7001D41A
+:1022F000108001D41400019E000083A90000609C9E
+:10230000001804E423000010000030A9001824E4A1
+:102310000F00000C0900609D0000409D0F0064A4A8
+:10232000000009A93000E39C0100299D005843E406
+:102330000300000C0028C3E0F6FFE69C440084B8CC
+:10234000005024E4F6FFFF13003808D80000609C1A
+:102350000000409D001809D8000070A88FFFFF07FB
+:102360000000CCA900588AE50D00000C000070A800
+:102370008AFFFF0701008C9D02506BE100806BE13A
+:1023800001004A9DFFFF6B8DF4FFFF0300580ED83C
+:102390003000609C00180CD801008C9D00006CA9D6
+:1023A0000000218504004185080081850C00C1855D
+:1023B00010000186004800442400219CFC00609C21
+:1023C0000000809C002003D4F800809C0000609CEA
+:1023D000001804D40048004400000015FCFF219CB4
+:1023E000004801D40000C09C002086E52200000CBB
+:1023F0000300E09C0200009D0230A4E00038A5E547
+:1024000010000010004025E40000A3900300238D7D
+:10241000032803D8004803D80100A3900200238DAD
+:10242000014803D8022803D80400C69C002086E592
+:10243000F2FFFF130400639C0F0000000000001572
+:1024400007000010003825E40000A3900100238D50
+:10245000012803D8F5FFFF03004803D8F3FFFF135B
+:10246000000000150000A3900200238DEEFFFF0383
+:10247000004803D800002185004800440400219C46
+:10248000ECFF219C004801D4045001D4086001D421
+:102490000C7001D4108001D4000083A93FFFFF0716
+:1024A000FC00C09D03008B9CFCFFA09C00006CA85E
+:1024B000032844E1F400009EC9FFFF0700008AA83A
+:1024C0000000CE8400008CA80000AAA80230F0E032
+:1024D000005087E412000010000066A80DFFFF07FF
+:1024E000000000150000CE840000609C0000809C6D
+:1024F0000050C6E0008026E40400000CE000A09C30
+:102500001700000000300ED423080004000000155E
+:102510000000609C1200000000180ED4FDFEFF07B2
+:102520000000A7A80000609C0000809C1A0800041E
+:10253000E000A09C00008E840000609C0020AAE0C7
+:1025400002208CE00CFF459DF400849D0000AAA8A9
+:10255000F0FEFF0700008CA800500ED4000021857B
+:1025600004004185080081850C00C18510000186AA
+:10257000004800441400219C0000609D0048004475
+:1025800000000015F4FF219C004801D4045001D440
+:10259000086001D4004040195C004AA9000083A8EB
+:1025A00000008A8504006018206D63A8F3FFFF0710
+:1025B0000000001500006A8400180CE4FEFFFF1301
+:1025C0000000001500002185040041850800818578
+:1025D000004800440C00219CFCFF219C0040601836
+:1025E0005C0063A800006384001801D400008184AB
+:1025F000004800440400219CF4FF219C004801D4C1
+:10260000045001D4086001D40400A0185083A5A888
+:102610000000609C00008584001804E40900000CA0
+:10262000000085A90000409DECFFFF070000001599
+:1026300000006C84005003E4FCFFFF130000001551
+:102640000000218504004185080081850048004480
+:102650000C00219CF8FF219C004801D4045001D4B7
+:102660002B010004000044A917010004000000151C
+:102670008FFEFF0700006AA8EEEE6018EEEE63A87A
+:102680008BFEFF07000000157CFEFF070100609C29
+:102690000000218504004185004800440800219C79
+:1026A000FCFF219C004801D40100609C0040801880
+:1026B000680084A80040A018E400A5A8001804D46D
+:1026C0000000C09C00006584420063B8010063A460
+:1026D000003003E4160000102000609C00408018C9
+:1026E000E80084A80000A4844800A5B80300809CEA
+:1026F000FF3FA5A4002025E41300001000000015F2
+:1027000000408018080484A8003004D476FEFF0737
+:102710000000001504008B9C2000609C6FFEFF07EA
+:102720000000001508000000000000150000A5844E
+:102730002000609C0100A5A4003005E4F8FFFF0F15
+:102740000001809C00406018E40063A80000809CA9
+:10275000002003D400002185004800440400219C8F
+:1027600000406018680063A80200809C002003D429
+:102770000048004400000015FCFF219C004801D4E3
+:1027800000408018680084A80400A09C4000609C61
+:10279000002804D454FEFF0700000015FDFF609CD4
+:1027A00003188BE04DFEFF074000609C0000218570
+:1027B000004800440400219C04006018508363A872
+:1027C0000100809C002003D400408018041684A8D7
+:1027D0000000609C001804D400480044000000156C
+:1027E000F8FF219C004801D4045001D40248609CA9
+:1027F0003DFEFF070000409D00206BA500500BE44C
+:102800005E00000C0000001537FEFF070248609CC8
+:1028100000106BA500500BE44B00000C00000015ED
+:1028200031FEFF070248609C00086BA500500BE4D6
+:102830003800000C000000152BFEFF070248609CCA
+:1028400000046BA500500BE42500000C00000015EF
+:1028500025FEFF070248609C00026BA500500BE4B8
+:102860001200000C000000151FFEFF070248609CCC
+:1028700080006BA500500BE44D0000100000001517
+:10288000CEFFFF070000001517FEFF070248609CFF
+:102890007FFF609C03188BE010FEFF070248609CDE
+:1028A000430000000000001504006018648363A862
+:1028B0000000838400200048000000150AFEFF0786
+:1028C0000248609CFFFD609C03188BE003FEFF073D
+:1028D0000248609CE5FFFF0300000015040060183B
+:1028E000608363A800008384002000480000001576
+:1028F000FDFDFF070248609CFFFB609C03188BE016
+:10290000F6FDFF070248609CD2FFFF0300000015A0
+:1029100004006018548363A80000838400200048EA
+:1029200000000015F0FDFF070248609CFFF7609C67
+:1029300003188BE0E9FDFF070248609CBFFFFF031F
+:1029400000000015040060185C8363A80000838405
+:102950000020004800000015E3FDFF070248609CCE
+:10296000FFEF609C03188BE0DCFDFF070248609CD2
+:10297000ACFFFF030000001504006018588363A833
+:10298000000083840020004800000015D6FDFF07EA
+:102990000248609CFFDF609C03188BE0CFFDFF07BF
+:1029A0000248609C99FFFF0300000015000021858C
+:1029B00004004185004800440800219C0040601844
+:1029C000680063A81000809C002003D400480044E5
+:1029D00000000015FCFF219C004801D42000609CF1
+:1029E00000408018680084A8001804D4BEFDFF07CA
+:1029F0000000001504008B9CB8FDFF072000609CC0
+:102A000000002185004800440400219CFCFF219C1B
+:102A1000004801D44000609C00408018680084A8F1
+:102A2000001804D4B0FDFF0700000015FFEF609C04
+:102A300003188BE0A9FDFF074000609C0000218582
+:102A4000004800440400219C00406018680063A80E
+:102A50008000809C002003D4004800440000001542
+:102A600000406018680063A80001809C002003D427
+:102A7000004800440000001500406018680063A88A
+:102A80000002809C002003D4004800440000001590
+:102A900000406018680063A80004809C002003D4F4
+:102AA0000048004400000015FCFF219C004801D4B0
+:102AB0007AF9FF0700000015000021850048004456
+:102AC0000400219CFCFF219C004801D486FDFF07E7
+:102AD0001100609CDFFF609C03188BE07FFDFF0707
+:102AE0001100609C00002185004800440400219CE6
+:102AF000FCFF219C004801D46EF9FF07000000157F
+:102B000000002185004800440400219CFCFF219C1A
+:102B1000004801D474FDFF071100609CBFFF609C5A
+:102B200003188BE06DFDFF071100609C00002185FC
+:102B3000004800440400219CF8FF219C004801D477
+:102B4000045001D4000043A967FDFF071100609CF9
+:102B5000FDFF609C03188BE060FDFF071100609C87
+:102B6000FF0F8018FFFF84A80050609C03204AE1FB
+:102B700000608018000084A804204AE157FDFF0788
+:102B800000008AA80150609C54FDFF070000809C53
+:102B90000000218504004185004800440800219C74
+:102BA000F8FF219C004801D4045001D4000043A93F
+:102BB000FFFF609D0600809C0020AAE40D00000C31
+:102BC0000048609C48FDFF07000000150D00C09CF8
+:102BD0000100A09C0250C6E00048609C0830A5E0BF
+:102BE000FFFFA5AC3DFDFF0703288BE00000609DC3
+:102BF0000000218504004185004800440800219C14
+:102C0000F8FF219C004801D4045001D4000043A9DE
+:102C1000FFFF609D0600809C0020AAE40C00000CD1
+:102C20000048609C30FDFF07000000150D00C09CAF
+:102C30000100A09C0250C6E00048609C0830A5E05E
+:102C400026FDFF0704288BE00000609D0000218521
+:102C500004004185004800440800219C04006018DD
+:102C6000548063A800008018A02684A8002003D404
+:102C700004008018848084A800006018602763A87E
+:102C8000001804D404006018648063A80000801851
+:102C9000782784A8002003D404008018788084A8B2
+:102CA00000006018E02763A8001804D4040060182E
+:102CB0005C8063A800008018602A84A8002003D4E8
+:102CC00004008018748084A800006018902A63A80B
+:102CD000001804D4040060187C8063A800008018E9
+:102CE000482A84A8002003D404008018688084A89F
+:102CF00000006018782A63A8001804D40400601843
+:102D0000888063A800008018BC2984A8002003D410
+:102D100004008018708084A800006018D42963A87B
+:102D2000001804D404006018608063A800008018B4
+:102D30000C2A84A8002003D4004800440000001599
+:102D4000FCFF219C004801D4E7FCFF071100609CB8
+:102D500004008BA8E1FCFF071100609C00002185A6
+:102D6000004800440400219CFCFF219C004801D441
+:102D70008CFFFF070000609C8AFFFF070100609C3A
+:102D800088FFFF070200609C86FFFF070300609C2E
+:102D900084FFFF070400609C9AFFFF070600609C09
+:102DA00000002185004800440400219C0040601878
+:102DB000300063A80000809C002003D40048004439
+:102DC0000000001500406018080063A80100809C06
+:102DD000002003D4004800440000001500406018A3
+:102DE000200263A80000809C002003D400408018CB
+:102DF000240284A80000609C001804D400406018DD
+:102E0000280263A80000809C002003D400408018A2
+:102E10002C0284A80000609C001804D400480044E0
+:102E20000000001500400019480008A9002008D43F
+:102E3000004080184C0084A8002804D40400849C1E
+:102E40000040A0184400A5A8003004D40400849CCD
+:102E5000003804D4001805D40048004400000015D0
+:102E60000040A0180020A5A8FFFF80A800006584EE
+:102E7000002023E4FEFFFF1300000015004800447B
+:102E8000000000150040A0184400A5A80000809C88
+:102E900000006584002023E4FEFFFF1300000015FE
+:102EA0000048004400000015FCFF219C004801D4AC
+:102EB000720700040000001500406018000063A8BD
+:102EC0001B00809C002003D4FF03809C002003D4BF
+:102ED00000002185004800440400219C0000A09CC3
+:102EE000FF00C3A40100609D00408018402084A81A
+:102EF000000064840100A59CFFFF63A4001826E481
+:102F00000700000C4000849C0100609D0058A5E56E
+:102F1000F8FFFF13000000150000609D004800440A
+:102F200000000015040063B804008018E88184A83C
+:102F3000002063E0000083840400609C001844E4E7
+:102F4000030000100000609D0100609D00480044E7
+:102F500000000015060063B800408018402084A8D7
+:102F60000000609D002063E000008384FFFF60A8F4
+:102F7000FFFF84A4001824E40300000C00000015E7
+:102F80000100609D0048004400000015FCFF219CEA
+:102F9000004801D40600A3B80040C0186420C6A8A9
+:102FA0000080E0188000E7A8003065E00000009D88
+:102FB00000006384004003E4280000100038C3E0F0
+:102FC0000080601B84007BAB0040E0184420E7A831
+:102FD00000D823E30038E5E20040601B50207BABC3
+:102FE0000800E79C00D865E2003825E20080601BFD
+:102FF00088007BAB0800E79C00D8E3E1003865E17E
+:1030000004007B9F002006D4004004E40B00001065
+:1030100000D823E10100609C001806D40000F78668
+:1030200000B819D40000318600880FD4004009D4BC
+:103030000A000000000000150000809C002006D45B
+:1030400000007386009819D400006B8500580FD4D7
+:1030500000007784001809D400002185004800444E
+:103060000400219CE8FF219C004801D4045001D4B5
+:10307000086001D40C7001D4108001D40000C3A9F1
+:103080000000809D00406018300063A80000838429
+:10309000006024E4B700000C0500609C001844E4C4
+:1030A0004500001000000015020064B804008018FC
+:1030B0002C6D84A8002063E000008384002000447D
+:1030C0000000001500406018340063A8004040195B
+:1030D00038004AA9000083840040E0183C00E7A8BB
+:1030E00000400019400008A90000AA841400619C57
+:1030F0000000C7840F00A5A40B00C6B80000E88438
+:10310000A30000040000001500006A840400801879
+:10311000BC8084A800008BA95F0063B85AFFFF073A
+:10312000001804D40000609C00182CE41800000C67
+:103130000200609C00182CE41300000C2000609C2E
+:103140001000609C00182CE40800000C2000609C1B
+:1031500017FFFF07000000151BFFFF070000001509
+:1031600084000000000000151900A09C1400818458
+:103170000000C09C2CFFFF070000E09CF5FFFF0350
+:1031800000000015FAFFFF030100A09C14008184D9
+:103190000100609C0000A09C0000C09C22FFFF0773
+:1031A0000000E09C00006E840100639CE9FFFF03C7
+:1031B00000180ED434FFFF07000000152000609CAB
+:1031C0000000809CEBFFFF030200A09C0040401920
+:1031D00034004AA90000009E00006A8440FFFF07F7
+:1031E000FF0063A400800BE46200000C00000015E7
+:1031F00000006A840000809CD9000004FF0063A4E2
+:1032000021FFFF0700008BA900800CE406000010DE
+:103210000000C09C00008CA82000609CD6FFFF032B
+:103220000400A09C0200609C0000809C0000A09C08
+:10323000FDFEFF070000E09C00006E84DCFFFF0342
+:10324000FFFF639C0000609CF0FF809C00180ED480
+:1032500004004019B0804AA9040060184FA563A873
+:10326000032063E000408018340084A800180AD4CA
+:103270000000848404006018388363A802FFFF07FD
+:10328000002003D400008A840800609C0000A09CF9
+:10329000B8FFFF030010849C0000609C0000809D2C
+:1032A0002DFFFF07FFFF409D00600BE41D00000C99
+:1032B0000000001528FFFF070100609C00600BE480
+:1032C0000800000C00000015EFFEFF0700000015CD
+:1032D00000008AA80C00609CA6FFFF030000A09CD1
+:1032E0000040A0188020A5A8FFFF4AA50000658423
+:1032F000FFFFC3A4FFFF60A8100086B8001805D424
+:1033000000204AE108FFFF07000066A800008BA824
+:103310001FFFFF070100609CECFFFF03000000158A
+:1033200000406018402063A800008384FFFFC4A40D
+:10333000FFFF80A8002003D4FFFF8018000084A8AE
+:10334000000066A8F8FEFF07002046E100008BA8F9
+:103350000FFFFF070000609CD7FFFF030000001570
+:1033600004006018608963A80000809C002003D4DA
+:103370000000218504004185080081850C00C1857D
+:1033800010000186004800441800219CF4FF219C95
+:10339000004801D4045001D4086001D40000A5A95C
+:1033A0000000E6A9000007A9000083A9000024A9E5
+:1033B0000000A09C0000409D0400E018EC81E7A8FC
+:1033C0000400C018E881C6A8F8FF86840000609C4D
+:1033D000001824E41400000C0F00609C1000E79C0F
+:1033E00001004A9D0018AAE4F8FFFF131000C69CD4
+:1033F0001000609D00582AE406000010005825E4E3
+:10340000FF00209D0200609D5000000000480CD489
+:103410004E00000C0000001500500CD44B000000C2
+:103420000000609D0500809C002029E4150000102C
+:103430000000A09C0100A09C000025A9020089B802
+:10344000004806D4FF006AA404002019288929A98D
+:10345000004884E0000064850100209D0000809CFD
+:10346000F84FE6D7FC27E6D7000087A80000CDA8D4
+:10347000005800480000EFA8DEFFFF030000ABA8E3
+:103480000600609D005829E4040000100700609CBD
+:10349000EAFFFF030200A09C001829E405000010C9
+:1034A0000800609C0200209DE5FFFF030100A09C36
+:1034B000001829E4050000100900609C0200209D0E
+:1034C000DFFFFF030300A09C001829E405000010A3
+:1034D0001000609C0200209DD9FFFF030400A09C07
+:1034E000001829E4040000101100609CD4FFFF03C1
+:1034F000000024A9001829E4040000101200609CB8
+:10350000CFFFFF0300002BA9001829E404000010DE
+:103510001300609CE5FFFF0300002BA9001829E4BD
+:10352000050000101400609C0100209DC4FFFF03F3
+:103530000200A09C001829E4C2FFFF13020089B812
+:10354000E0FFFF030100209D00002185040041856C
+:1035500008008185004800440C00219C0400A3B8A9
+:1035600004008018E08184A80020C5E00F00809C42
+:10357000002043E40E0000100200609D040060186B
+:10358000E88163A8000086840018A5E00100609C23
+:10359000001824E4060000100000809CFF00609CDE
+:1035A000002006D4001805D40000609D00480044A7
+:1035B000000000150080C0180400C6A80080E018B4
+:1035C0001800E7A80030A3E00000A5840038C3E09D
+:1035D000042804D40000C6840080A0182800A5A8F0
+:1035E0000028E3E0183004D40000E7840080C0180D
+:1035F0002C00C6A8283804D40030A3E00080E018CE
+:103600003000E7A80000A5840038C3E02C2804D4CB
+:103610000000C6840080A0183400A5A8303004D46F
+:103620000028E3E00080C0183800C6A80000E78446
+:103630000030A3E0343804D40000A5840080E018F2
+:103640004400E7A8382804D40038C3E00080A0185C
+:103650004800A5A80000C6840028E3E0443004D454
+:103660000000E7840080C0184C00C6A8483804D485
+:103670000030A3E00080E0186400E7A80000A58403
+:103680000038C3E04C2804D40000C6840080A01891
+:103690006800A5A8503004D40028E3E00080C018DA
+:1036A0006C00C6A80000E784003063E0000063847B
+:1036B000543804D4581804D40048004400000015BD
+:1036C000F8FF219C004801D4045001D40000A4A8B4
+:1036D00000808018000084A80020C3E00800849CBB
+:1036E0000020E3E00400849C002003E10400849CAB
+:1036F000002023E10400849C002063E10800849CF6
+:103700000020A3E10400849C0020E3E10400849CE9
+:10371000002023E21800849C002063E20400849CC3
+:103720000020A3E23C00849C0020E3E23400849C5F
+:10373000002023E30800849C002063E30400849CB1
+:103740000020A3E30C00849C0020E3E30400849C9D
+:10375000002043E10000809C002003E422000010D0
+:10376000000000150000658408008584001806D458
+:103770000C006584002007D4001808D4100085844C
+:1037800014006584002009D400180BD41C00858423
+:103790002000658400200DD400180FD424008584F7
+:1037A0003C006584002011D4001813D440008584A7
+:1037B0007C016584002015D4001817D4800185840D
+:1037C00088016584002019D400181BD484018584E5
+:1037D0008C01658400201DD49001A58400181FD49D
+:1037E00000280AD4000021850400418500480044D7
+:1037F0000800219C060063B800408018402084A87F
+:103800000000609D002063E00000A384000083842A
+:103810005000A5B8FFFF84A40600609C0018A5E432
+:1038200004000010040084B8110000000200609D34
+:103830000400C018E081C6A8003064E00000838462
+:10384000005824E40A0000100100609C001825E4E0
+:103850000700000C0500609D0400609C001825E432
+:103860000300000C0700609D0A00609D00480044B2
+:1038700000000015F0FF219C004801D4045001D441
+:10388000086001D40C7001D4000084A90000C5A90F
+:1038900074FDFF07FF0043A500408018002084A8A6
+:1038A00006006AB8006004D400408018402084A854
+:1038B000002063E0FFFF80A8002003D472FDFF0713
+:1038C0000000001500008AA80000AEA82000609C3F
+:1038D0000000C09C54FDFF070000E09C0000218513
+:1038E00004004185080081850C00C1850048004422
+:1038F0001000219CF4FF219C004801D4045001D405
+:10390000086001D40600C3B8000083A80000A09C92
+:1039100004006018446D63A8002824E4030000102C
+:10392000000000150100A09C004080186C2084A8B5
+:103930000040E0184020E7A8002086E10600A5B876
+:10394000003886E00040C0186C20C6A8003045E171
+:103950000000C4840038A5E000008584FFFFC6A4F1
+:10396000FFFF84A4002026E40400000C00000015E2
+:103970000D0000000100609D00008C8500004A855C
+:10398000FEFAFF0700008CA804006018546D63A8BD
+:10399000FAFAFF0700008AA80050ACE4F5FFFF1315
+:1039A0000000609D0000218504004185080081859C
+:1039B000004800440C00219C0040601804C563A826
+:1039C0000000809C002003D40040801808C584A813
+:1039D0000000609C001804D4004060180CC563A867
+:1039E0000000809C002003D40040801810C584A8EB
+:1039F0000000609C001804D40040601814C563A83F
+:103A00000000809C002003D40040801818C584A8C2
+:103A10000000609C001804D4004060181CC563A816
+:103A20000000809C002003D40040801820C584A89A
+:103A30000000609C001804D400406018A0C563A872
+:103A40000000809C002003D400408018A4C584A8F6
+:103A50000000609C001804D400406018A8C563A84A
+:103A60000000809C002003D400408018ACC584A8CE
+:103A70000000609C001804D400406018B0C563A822
+:103A80000000809C002003D400408018B4C584A8A6
+:103A90000000609C001804D40040601888C563A82A
+:103AA0000000809C002003D4004080188CC584A8AE
+:103AB0000000609C001804D40040601804D063A883
+:103AC0000000809C002003D40040801810D084A8FF
+:103AD0000000609C001804D4004060181CD063A84B
+:103AE0002C01809C002003D40040801820D084A8A2
+:103AF000AA00609C001804D40040601834D063A869
+:103B00000000809C002003D40040801808E084A8B6
+:103B10000000609C001804D4004800440000001518
+:103B2000F8FF219C004801D4045001D40080801883
+:103B3000B40084A80100409D002063E00000609D67
+:103B40000000C3844C0086B84800A6B80C00609CF6
+:103B50000F0084A4001824E4110000100F00A5A495
+:103B6000005025E40E000010440066B80F0063A466
+:103B7000005023E40A0000100F00A6A404006018FF
+:103B8000646D63A8005025E4050000100000809CCF
+:103B90007AFAFF070000001500006AA900002185DD
+:103BA00004004185004800440800219CF8FF219C46
+:103BB000004801D4045001D400408018002084A89B
+:103BC000FFFFA0A8000043A9002804D4004060180B
+:103BD000580063A80040A0184020A5A8FFFF80A8B7
+:103BE000002005D4FFFFA0A800408018802084A8F2
+:103BF000002804D410008018280984A8002003D4C9
+:103C0000EFF9FF070000001515FCFF070000001585
+:103C10004CFCFF070000001500408018800084A8BD
+:103C20000100A09C00006AA8002804D40000C09CE9
+:103C30000000809C0000A09C7BFCFF070000E09C33
+:103C400061FCFF070000001500002185040041858C
+:103C5000004800440800219CF0FF219C004801D44A
+:103C6000045001D4086001D40C7001D400408018C5
+:103C7000300084A80000C3A90000A48404006018D8
+:103C8000608963A80000E09C000083840000C09C61
+:103C9000003024E403000010FF00A5A40100E09C14
+:103CA0000600609C001825E4030000100000809CC2
+:103CB0000100809C032067E0003003E42100000C39
+:103CC0000000809C0F00C09C0400A018E081A5A803
+:103CD000040064B80000E09C0100849C002863E0BC
+:103CE000FF0084A40030A4E4FAFFFF13003803D4DB
+:103CF00004008018388384A800380ED40900609C22
+:103D0000003804D4000084A9A9FFFF070000409DEB
+:103D1000D5FCFF0700006EA800006C84005003E48F
+:103D2000FCFFFF130000809C04006018A08063A8C3
+:103D30000100A09C042003D40C000000002803D440
+:103D40001BFCFF070000001599FFFF070B00609C9C
+:103D5000040060186C6D63A808FAFF070000809CDF
+:103D600002FCFF070000001504006018608963A8CA
+:103D70000100E09C003803D4000021850400418547
+:103D8000080081850C00C185004800441000219C7A
+:103D9000CCFF219C004801D4045001D4086001D418
+:103DA0000C7001D4108001D4149001D418A001D457
+:103DB0001CB001D420C001D424D001D428E001D407
+:103DC0002CF001D40000609C301801D4A3FFFF0741
+:103DD0003000619C04006018708363A84A0B0104E2
+:103DE000000000150000609C00180BE49B00001010
+:103DF0009900809C00408018680084A89A00A09CCC
+:103E000000006BA8002804D4AE0C0004FFFF80AAB9
+:103E10000400C01AA080D6AA0400001BE08118ABE1
+:103E20000000C09D06006EB80040A0184020A5A864
+:103E3000002883E100008C84FFFF44A500A00AE471
+:103E4000340000100000409EABFEFF0700006EA88B
+:103E500000900BE42F0000100000001566FEFF0725
+:103E600000006EA800000BAA00006EA82F0C000432
+:103E700000008AA8009010E46800000C0400AAB8B2
+:103E800000406018140B63A80C9016D400C085E0A5
+:103E90000800C4840000A4A8000096840200C6B8EC
+:103EA000002003D40C00858400406018540863A8E7
+:103EB0000400B684002803D404006018448963A871
+:103EC0003000A1840018C6E00000E68400380048F5
+:103ED00000006EA8B9FEFF07000000150C007684F4
+:103EE000009023E4070000101B00809C0040601835
+:103EF000000063A8FF03A09C002003D4002803D483
+:103F0000B1FBFF0700000015310C000400006EA893
+:103F100000400019300008A90000E09C0040C018D3
+:103F20004020C6A80040A0188020A5A800006884F2
+:103F3000003823E40C000010FFFF80A80000668416
+:103F4000032063E0002023E40700001000000015B8
+:103F500000006584032063E0002023E4F4FFFF0FEA
+:103F60000000001540FCFF073000619C0400601851
+:103F7000608963A80000809C0000A384002025E4E1
+:103F80001100001001006E9C00408018402084A8A1
+:103F9000FFFFA0A800006484032863E0002823E456
+:103FA0000900001001006E9C00408018802084A849
+:103FB00000006484032863E0002823E40900000C67
+:103FC00001006E9C0100809CFF00C3A50020AEE4B0
+:103FD00096FFFF1306006EB893FFFF030000C09D1D
+:103FE0000A00609C0000809C0000A09C0000C09C17
+:103FF0008DFBFF070000E09C00406018300063A8C4
+:104000000000809C002003D46FFBFF070000001518
+:10401000000000000000001592FBFF0700000015E3
+:1040200000406018002063A8005003D400A00CD406
+:1040300095FBFF070000001500008EA80000B0A847
+:104040002000609C0000C09C77FBFF070000E09C04
+:1040500075FFFF030000C09D00406018640063A866
+:10406000002003D46BFFFF03FFFF80AA000021851F
+:1040700004004185080081850C00C185100001867F
+:1040800014004186180081861C00C186200001872B
+:1040900024004187280081872C00C1870048004404
+:1040A0003400219CFCFF219C004801D404006018CE
+:1040B000388363A80028C09C0000A384F0FF809C84
+:1040C00004002019B47F29A90A33A5E00400601870
+:1040D0004FA563A80000E09C032003E104006018E2
+:1040E000B07F63A8004003D4020085B8002809D43B
+:1040F000002088E00A3384E0020064B8002063E016
+:104100000B0063B804008018B08084A8003063E01E
+:10411000002887E40A00000C001804D4000088A8D6
+:104120000000609C0100E79C001804D40000698432
+:10413000001887E4FBFFFF130400849C0400601850
+:10414000388363A80000638500002185004800448F
+:104150000400219CFCFF219C004801D40000A3A87E
+:104160000000609C001825E44700000C0000609DE2
+:104170000028609CFFFFA59C04008018B47F84A8E1
+:104180000A1BA5E0000064850000A09D0000E09CE3
+:10419000020065B8002863E00B0063B80028039DA7
+:1041A0000000C8A80200A7B8005887E41300000C5C
+:1041B0000000209D04006018B07F63A80000838485
+:1041C000002085E000006484004823E42B000010F8
+:1041D000003028E403000010000000150000A7A92B
+:1041E00000D8C69C004826E40400000C0000209D76
+:1041F000EDFFFF030100E79C004806E40400001007
+:104200000200EDB8200000000000609D040080184E
+:10421000B08084A8006867E00000A4840B0063B845
+:10422000004828E40E00000C001865E10400601846
+:10423000B07F63A80100CD9C0000838400D8089D56
+:104240000000A6A9002087E00000609C0200E6B8FC
+:10425000001828E4F6FFFF13003004D4040080188F
+:10426000B07F84A800006484FFFF80A8001867E086
+:1042700005000000002003D40000C8A8DDFFFF03F4
+:104280000000A09D00002185004800440400219CFE
+:1042900004008018B08084A8FFFF00A90000A48457
+:1042A0000000E09C022863E004008018B07F84A82E
+:1042B0000028A09C0000C4840A2B63E102006BB8B4
+:1042C0000400A018B47FA5A8003083E00000648437
+:1042D000004003E40C000010003823E40300000C4D
+:1042E0000000609C001804D40000658401006B9DF0
+:1042F00000188BE4F6FFFF130400849C0500000007
+:1043000001006B9D0000609C001804D401006B9DAF
+:104310000048004400000015CCFF219C004801D457
+:10432000045001D4086001D40C7001D4108001D471
+:10433000149001D418A001D41CB001D420C001D421
+:1043400024D001D428E001D42CF001D40400201999
+:10435000B08029A90400E018B47FE7A800006984B0
+:10436000000045AA021884E0000007850028609C30
+:104370000A1B44E1004065E479000010303001D4AC
+:1043800004006018B07F63A80200E5B800008384D1
+:10439000002087E00000609C00008484001824E472
+:1043A0006F00000C0000A7A9001824E46C00000CAA
+:1043B00002006AB8002887E0000007AA005063E006
+:1043C0000B0044BB0B00C3BA00009AAA000016AB56
+:1043D00004008018B08084A80200EAB80000648459
+:1043E0000000C09C0400A018EC81A5A800B023E147
+:1043F00000D003E100008584004024E4090000109F
+:104400000100C69C3000618500006B84001824E424
+:10441000030000100000001500480BD4004805D42C
+:104420000F00609C0018A6E5F3FFFF131000A59C89
+:104430000400C01BB07FDEAB0000DE84FFFF80A85D
+:1044400000306DE00000A384002025E42400000C6F
+:1044500000006DA90400801BB0809CAB0000D8A9AF
+:10446000000094A9003067E001004A9D00308BE015
+:10447000005003D40000A09C000069A8002804D4C8
+:104480000400109E000088A80028A09C21F7FF07C8
+:1044900000288C9D0000DE840028CE9D0200EAB832
+:1044A000003070E000009C840000B0A900285A9FF2
+:1044B0000000A384007024E10028949E0100529E15
+:1044C0000028D69E0028189F006004E1FFFF60A826
+:1044D000001825E4E4FFFF13000070A90400801910
+:1044E000B07F8CA9000088A80000CC84FFFF00A941
+:1044F0000028A09C0030E7E00000609D0030CDE087
+:10450000004007D4000069A800285AE3005806D4E8
+:1045100000F7FF070400109E04006018B47F63A832
+:104520000028949E000083840100529E0028D69E9D
+:104530000028189F002072E40900001001004A9D25
+:1045400000006C840000809C001870E00000A384D0
+:10455000002025E49FFFFF130000B0A90000218583
+:1045600004004185080081850C00C185100001868A
+:1045700014004186180081861C00C1862000018736
+:1045800024004187280081872C00C187004800440F
+:104590003400219C180084B8980084B80000C09CA6
+:1045A000002886E50700000C0000E3A8003067E063
+:1045B0000100C69C002886E5FDFFFF13002003D8FC
+:1045C0000048004400000015ECFF219C004801D485
+:1045D000045001D4086001D40C7001D4108001D4BF
+:1045E000000083A9000045A9000004AABEF6FF0749
+:1045F0000048609C0000CBA90048609CB7F6FF070C
+:104600000000809C0000AC8C00008EA80048609CDC
+:1046100000282AE41500000CFFFFCA9C00006C8CE7
+:104620000000A09C0100639C00180CD802008C8C38
+:10463000FF0064A4003003E4030000100000001534
+:104640000100A39C02280CD800008EA80018ACE042
+:104650000048609C038005D8A0F6FF070000001505
+:10466000050000000000609D9CF6FF07000000159B
+:10467000FFFF609D000021850400418508008185C1
+:104680000C00C18510000186004800441400219CE4
+:10469000E8FF219C004801D4045001D4086001D4F3
+:1046A0000C7001D4108001D4149001D4FF00E3A455
+:1046B000000084A90600E7B800408018602084A8A4
+:1046C000000046A90020E7E0000005AA0000C78519
+:1046D00085F6FF070048609C00004BAA0048609CDC
+:1046E0007EF6FF070000809C0000009D005088E4DB
+:1046F0001800000C0100CC8CFFFF6A9DFFFFA09DFD
+:1047000000302CE10100609C0300A9900100E69CB0
+:10471000006805E407000010082863E003188EE035
+:104720000000609C001804E41100000C000000155B
+:10473000005806E40300000C000000150000E09C97
+:104740000100089D005088E4EEFFFF130000C7A899
+:10475000FFFF609C000092A8001810D45FF6FF07CE
+:104760000048609C17000000FFFF609D002810D4E7
+:104770000100CC8CFF0066A400008C8C0018ACE01B
+:104780000300E58CFF00849C033809D800200CD876
+:10479000005803E409000010036805D80100669C76
+:1047A00001180CD8000092A84CF6FF070048609C46
+:1047B000040000000000609DFAFFFF030000609C01
+:1047C0000000218504004185080081850C00C18519
+:1047D0001000018614004186004800441800219C06
+:1047E000ECFF219C004801D4045001D4086001D49E
+:1047F0000C7001D4108001D4000083A9000045A9E9
+:104800000000C4A90048609C37F6FF07FFFF4A9DDF
+:1048100000000BAA0048609C30F6FF070000809C57
+:104820000000CC8C000090A80000A09C003005E4A3
+:10483000170000100048609C0100AC8C0000E09C58
+:104840000028CCE00300869000200ED400006C8C81
+:10485000FF00639C00180CD8005005E40300001012
+:10486000000000150100E59C01380CD8FFFFA09C5A
+:10487000000090A80048609C032806D817F6FF07A0
+:1048800000000015070000000000609DFFFFA09CD5
+:1048900000280ED411F6FF0700000015FFFF609DF1
+:1048A0000000218504004185080081850C00C18538
+:1048B00010000186004800441400219C000003A958
+:1048C0000000C09C002886E40C00000C0000E4A856
+:1048D000003088E00300648C180063B8980063B867
+:1048E000003823E40700000C0100C69C002886E481
+:1048F000F9FFFF13003088E0030000000000609D16
+:104900000100609D00480044000000150040601850
+:10491000040A63A80100809C002003D40000809C4E
+:10492000002003D40048004400000015160008B918
+:10493000100084B81000C6B80E00E7B8042088E064
+:10494000080063B8043008E1043884E00000C18442
+:10495000041884E00800A5B8043084E0043808E1B5
+:1049600000406018080A63A8042808E1002003D466
+:10497000043008E1004080180C0A84A8004004D4E8
+:1049800000480044000000150000A3A80040C01823
+:104990000002C6A800016018021063A8FF0084A4EA
+:1049A000001806D40300609C001825E407000010DE
+:1049B0000400609C00006684030863A8001806D405
+:1049C0001100000000000015001825E40700001089
+:1049D0000000001500006684C4008018013884A817
+:1049E000F7FFFF03042063E00000609C001804E46C
+:1049F000050000100000001500006684F0FFFF03B2
+:104A0000010863A800406018100263A80000809CA1
+:104A1000002003D40048004400000015F0FF219C52
+:104A2000004801D40040C0182402C6A8020004B9FE
+:104A3000000066844200A5B80000E09C081801D47C
+:104A400014002019804329A9004060182C0263A893
+:104A500000008384000063A9042001D40000668460
+:104A6000081801D400008B84042001D4080081843C
+:104A700004006184001864E41300001000000015B5
+:104A80000400618408008184022063E0021865E06C
+:104A90000C1801D40100E79C004827E40800000C32
+:104AA000000000150C006184004083E5ECFFFF135B
+:104AB00000000015080000000100609D06000000D5
+:104AC0000000609D0800618404008184F1FFFF0301
+:104AD000022063E000002185004800441000219C72
+:104AE000F4FF219C004801D4045001D4086001D493
+:104AF0000040201A2C0231AA04006018C88063A864
+:104B00000000B1850040E0190404EFA900406019DD
+:104B100008046BA90200ADB80000E384040080190A
+:104B200040838CA9420084B80028E7E00400AD9DD2
+:104B30000080A0180000A5A8002867E000000385F9
+:104B40000400A59C00806018080063A8002827E1E5
+:104B5000001847E10800A59C030068B80028E7E0BA
+:104B60001F00A018FFFFA5A80328C8E00007A01891
+:104B70000000A5A8580008B9032863E00418C6E09F
+:104B80000400A018D081A5A800406018000463A804
+:104B9000004005D4003003D47F00A018FFFFA5A873
+:104BA000000069840200639C032863E000180FD4AE
+:104BB0000000A09C00004A850000678400280BD4F8
+:104BC00000500CD40080A0180000A5A8032863E0C2
+:104BD0000100A09C04180CD400280BD400208DE404
+:104BE00003000010000000150000A09D006811D413
+:104BF00000006F8500002185040041850800818543
+:104C0000004800440C00219CF8FFC09CFF0063A4F6
+:104C10000330A4E0060063B8070084A44200A5B8EE
+:104C2000180084B80040C0180404C6A80420A5E0F9
+:104C300000408018482084A8002063E000408018CD
+:104C4000000484A8002804D4000083840400849C09
+:104C500000406018080463A8002006D40000809C6F
+:104C6000002003D40100809C002003D4000066854E
+:104C7000004800440000001500406018080463A8C4
+:104C80000000809C002003D4004800440000001570
+:104C9000000083A80000609C001824E408000010B5
+:104CA0000000809C040060185C8363A802008018E8
+:104CB000448284A805000000002003D4040060188A
+:104CC0005C8363A8002003D4004800440000001562
+:104CD0000400A0186489A5A80000609C00008584D9
+:104CE000001824E4630000102100809C0400601878
+:104CF000B87F63A8002003D404008018BC7F84A878
+:104D00002200609C001804D404006018C07F63A8CF
+:104D10002300809C002003D404008018C47F84A852
+:104D20002400609C001804D404006018C87F63A8A5
+:104D30002500809C002003D404008018CC7F84A828
+:104D40002600609C001804D404006018D07F63A87B
+:104D50002700809C002003D404008018D47F84A8FE
+:104D60002800609C001804D404006018D87F63A851
+:104D70002900809C002003D404008018DC7F84A8D4
+:104D80002A00609C001804D404006018E07F63A827
+:104D90004000809C002003D404008018E47F84A895
+:104DA0000000609C001804D404006018748463A898
+:104DB0008406809C002003D404008018788484A892
+:104DC0008806609C001804D404006018E87F63A87B
+:104DD0008C06809C002003D404008018EC7F84A8FB
+:104DE0009006609C001804D404006018F07F63A84B
+:104DF0009406809C002003D404008018F47F84A8CB
+:104E00009806609C001804D404006018F87F63A81A
+:104E10009C06809C002003D404008018FC7F84A89A
+:104E2000A006609C001804D404006018008063A8E9
+:104E3000A406809C002003D404008018048084A869
+:104E4000A806609C001804D404006018088063A8B9
+:104E50000007809C002003D4040080180C8084A8E4
+:104E60000006609C001804D40100809C002005D43A
+:104E70000048004400000015FCFF219C004801D4BC
+:104E8000000063AA000024AA0000E5A90000A6A96A
+:104E90000000209D003889E42600000C000067A96E
+:104EA0000400601BE07F7BAB0400201B088039AB53
+:104EB0000400E01AE47FF7AA0400A01A0C80B5AA47
+:104EC0000200A9B800007B84007885E0004863E018
+:104ED0000098C5E0001804D40068E5E0000099845B
+:104EE00000406018000063A8008805E1002085E00C
+:104EF000001884E000008484002006D40000778439
+:104F0000004863E0001807D40100299D0000758463
+:104F10000018A5E000406018000063A80018A5E094
+:104F20000000A584005889E4E6FFFF13002808D498
+:104F300000002185004800440400219C0000838477
+:104F40000080E0180000E7A80000A09C0400639C1B
+:104F50000800C09C003884E00000E4840100A59CA7
+:104F6000003803D40400849C0030A5E5FBFFFF1348
+:104F70000400639C00480044000000150000838486
+:104F80000080E0180000E7A80000A09C0400639CDB
+:104F90000800C09C003884E00000E3840100A59C68
+:104FA000003804D40400639C0030A5E5FBFFFF1328
+:104FB0000400849C0048004400000015CCFF219CA4
+:104FC000004801D4045001D4086001D40C7001D40D
+:104FD000002884E0FF0003A5420044B9000085A931
+:104FE0001000C19D02006AB80080A0180000A5A8AA
+:104FF0000000A6A9002863E00100C09C00006384B3
+:105000000800E09C0400AE9C101801D40000609CD5
+:105010000100C69C001805D40038A6E5FDFFFF136B
+:105020000400A59C0400609C001828E454000010B3
+:105030000000609C030084A4001804E445000010F4
+:10504000000000150100609C001824E422000010FC
+:105050001000E1840400A0186C89A5A8FF00E7A453
+:105060000200658C0100C58C180063B80000858CB7
+:105070001000C6B8080084B8043063E0042063E080
+:105080000018E7E0103801D402004AB900006DA80A
+:10509000ABFFFF0700500DD40080E0180000E7A828
+:1050A00000008EA800386AE00000C09C0800A09CA8
+:1050B0000000E4840100C69C003803D40400849CF2
+:1050C0000028A6E5FBFFFF130400639CEF0000002F
+:1050D00024006C9D0200609C001824E40E00001067
+:1050E000000000150400A0186C89A5A8FFFFE7A424
+:1050F0000100858C0000658C180084B8100063B82E
+:105100000200C58C041884E0143001D4DEFFFF03D4
+:105110000020E7E00400A0186C89A5A8FF00C018D3
+:10512000FFFFC6A80000858C0330E7E00200658C15
+:10513000180084B8080063B80100C58C0020E7E0BF
+:10514000043063E0103801D4D0FFFF03141801D4F9
+:105150000400A0186C89A5A80200658C0100858C4C
+:10516000100063B8080084B80000C58C042063E018
+:10517000043063E0C5FFFF03101801D40100A09CB8
+:10518000002828E472000010001828E4030084A41A
+:105190000400601978896BA90000609C001804E481
+:1051A00054000010002824E41B000010100021858A
+:1051B0000200AB8CFF0009A501008B8C1800A5B87C
+:1051C000100084B806006B8C0420A5E00500CB8C91
+:1051D000180063B80000EB8C1000C6B804008B8C7C
+:1051E0000800E7B8043063E0080084B80300CB8C03
+:1051F0000438A5E0042063E00700EB8C002828E1D8
+:10520000043063E0104801D4141801D49FFFFF0359
+:10521000183801D40200609C001824E41B00001020
+:105220000000001505006B8CFFFF29A504008B8C86
+:10523000180063B80100EB8C100084B80000AB8C40
+:105240001800E7B8042063E00300CB8C1000A5B879
+:105250000800C6B80428E7E007008B8C043063E040
+:10526000003829E10200AB8C080084B806000B8DE1
+:10527000042863E0044084E0104801D4141801D4E9
+:1052800082FFFF03182001D40400AB8CFF00E0185C
+:10529000FFFFE7A803006B8C1800A5B8033829E1CD
+:1052A0000200CB8C100063B80800C6B80418A5E053
+:1052B00007008B8C0430A5E00600EB8C100084B84E
+:1052C00000006B8C0800E7B80100CB8C180063B8B5
+:1052D000043884E005000B8D001829E10430A5E0B6
+:1052E000044084E0104801D4E6FFFF03142801D4F1
+:1052F00003008B8C0200AB8C180084B81000A5B89A
+:1053000007006B8C042884E00600CB8C180063B87F
+:105310000100EB8C1000C6B80500AB8C043063E0D4
+:105320000800E7B80800A5B804000B8D043884E035
+:10533000042863E00000CB8C044063E0043084E088
+:10534000141801D451FFFF03102001D444000010B1
+:105350000300609C0400E0186889E7A8030084A4A7
+:105360000000609C001804E43300001000000015E9
+:105370000100609C001824E40F0000101000A184BC
+:10538000FF00C5A40200678C0100A78C180063B859
+:105390000000878C1000A5B8080084B8042863E0DA
+:1053A000042063E00018A6E0102801D467FFFF0383
+:1053B0000300678C0200609C001824E40F000010BA
+:1053C000000000150100878CFFFFA5A40000678C7A
+:1053D000180084B8100063B8041884E00020A5E029
+:1053E000102801D40300678C0200878C080063B882
+:1053F00056FFFF03042063E00000678CFF00C01825
+:10540000FFFFC6A8180063B8033085E00018A4E0C9
+:10541000102801D40300678C0200878C100063B849
+:10542000080084B80100A78C042063E047FFFF0355
+:10543000042863E00300678C0200878C180063B8BF
+:105440000100A78C100084B80800A5B8042063E010
+:105450000000C78C47FFFF03042863E0001828E41E
+:1054600006000010000000150400E0187489E7A889
+:10547000BCFFFF03030084A40400E0187089E7A8C0
+:10548000B8FFFF03030084A40000218504004185C8
+:10549000080081850C00C185004800443400219C2F
+:1054A000060063B800408018682084A8FFBFA09C55
+:1054B000002063E000006385000083844E006BB928
+:1054C000032884E001006BA5002003D400480044B9
+:1054D00000000015F4FF219C004801D4045001D4C1
+:1054E000086001D4000043A9000084A904006018EA
+:1054F0007A6D63A821F4FF0700008AA80080801855
+:10550000000084A80080E0180400E7A800206AE0FA
+:105510000000A09C000063841F00C09C00388AE04B
+:1055200000180CD404006C9C0000E4840100A59CCD
+:10553000003803D40400849C0030A5E5FBFFFF1372
+:105540000400639C00808018840084A80080A01858
+:105550008800A5A800206AE00080E0188C00E7A879
+:105560000000638400288AE0000084840038AAE0F8
+:1055700088200CD40000A58400808018900084A8A6
+:105580000C00E79C84180CD48C280CD400206AE012
+:105590000080A0189400A5A80000638400288AE079
+:1055A000000084840038AAE094200CD40000A58474
+:1055B000008080189C0084A80C00E79C90180CD4F4
+:1055C00098280CD400206AE00080A018A000A5A8AC
+:1055D0000000638400288AE0000084840038AAE088
+:1055E000A0200CD40000A58400808018A80084A806
+:1055F0000C00E79C9C180CD4A4280CD400206AE072
+:105600000080A018AC00A5A80000638400288AE0F0
+:10561000000084840038AAE0AC200CD40000A584EB
+:1056200000808018B40084A80C00E79CA8180CD453
+:10563000B0280CD400206AE00080A018B800A5A80B
+:105640000000638400288AE0000084840038AAE017
+:10565000B4180CD40000A58400806018C00063A8B2
+:105660000C00E79CBC280CD40018CAE0B8200CD46D
+:105670000080A018C400A5A80000C68400288AE005
+:1056800000386AE000008484C0300CD4C4200CD4FC
+:1056900000006384C8180CD40000218504004185F3
+:1056A00008008185004800440C00219CD8FF219C03
+:1056B000004801D4045001D4086001D40C7001D416
+:1056C000108001D4149001D418A001D41CB001D4CE
+:1056D00020C001D424D001D4060044B900402019D0
+:1056E000442029A90040601948206BA900488AE09D
+:1056F000000046AB0000048600582AE1000005AB1C
+:105700002C00C186FF0083A60000C7A92800C18421
+:10571000000096A8000048AA000089850000A09C0F
+:10572000002806E406000010000066A8A2F7FF07A4
+:10573000000000151800768400188CE1006012D477
+:1057400004006018748463A80040A0180000A5A895
+:105750000000E3840B0090B8FF0F601900F86BA9FC
+:10576000004060184C2063A80028E7E000182AE1F8
+:10577000008007D404006018788463A8000029859D
+:105780000040E0180001E7A8035884E0000003850A
+:10579000002808E13000C184000074A80000ACA813
+:1057A000004808D404480ED40100009D00800ED4A7
+:1057B000004007D402FEFF070000001500406018FB
+:1057C000200163A800402019582029A9005803D4BB
+:1057D00000488AE0004060195C206BA900008484C6
+:1057E00000586AE000006384002018D400181AD41E
+:1057F0000000218504004185080081850C00C185D9
+:105800001000018614004186180081861C00C186A4
+:105810002000018724004187004800442800219C83
+:105820000040A018300CA5A80000C09C0000A58472
+:10583000002803D400406018340C63A80000A4A81A
+:10584000000083840100609C001824E40300001021
+:10585000000000150000C3A8003005D40048004433
+:105860000000001504008018E87F84A80000A484CC
+:1058700004008018EC7F84A80000C48400408018D5
+:10588000000084A80020A5E004008018F07F84A810
+:105890000000A5840000E48400408018000084A873
+:1058A000082803D40020C6E004008018F47F84A8F0
+:1058B0000000C6840000A48400408018000084A872
+:1058C0000C3003D40020E7E004008018F87F84A89F
+:1058D0000000E7840000048500408018000084A8D0
+:1058E000103803D40020A5E004008018FC7F84A8B1
+:1058F0000000A5840000E48400408018000084A813
+:10590000142803D4002008E104008018008084A833
+:10591000000008850000C48400408018000084A8AE
+:10592000184003D40020E7E004008018048084A815
+:105930000000E7840000A48400408018000084A8D0
+:105940001C3803D40020C6E00020A5E00000C68477
+:105950000000A584203003D4242803D40048004448
+:1059600000000015F8FF219C004801D4045001D428
+:105970000400E0187484E7A8FF00C6A400000785AF
+:105980000400E0187884E7A8000027850040E018AC
+:105990000000E7A8003808E10400E018E87FE7A865
+:1059A000000047850000E384003808D40040E01878
+:1059B0000000E7A8003829E10400E018EC7FE7A820
+:1059C000000007850400E384003809D40040E01893
+:1059D0000000E7A800384AE10400E018F07FE7A8DB
+:1059E000000027850800E38400380AD40040E0184E
+:1059F0000000E7A8003808E10400E018F47FE7A8F9
+:105A0000000047850C00E384003808D40040E0180B
+:105A10000000E7A8003829E10400E018F87FE7A8B3
+:105A2000000007851000E384003809D40040E01826
+:105A30000000E7A800384AE10400E018FC7FE7A86E
+:105A4000000067851400E38400380AD40040E018A1
+:105A50000000E7A8000044A9003808E10400E018AD
+:105A60000080E7A8000027851800E384003808D4E8
+:105A70000040E0180000E7A800386BE10400E018DF
+:105A80000480E7A8000007851C00E38400380BD4DD
+:105A90000040E0180000E7A8003829E12000E38476
+:105AA000003809D4240063840040E0180000E7A80F
+:105AB000000025A9003808E1001808D40000009D66
+:105AC000003088E51600000C000000150400601886
+:105AD000088063A8040080180C8084A80000A384B8
+:105AE000000064840038A5E00038E3E0020068B8F4
+:105AF000005083E00100089D004863E000008484BA
+:105B000000006384002005D4001807D40400A59C7D
+:105B1000003088E5F6FFFF130400E79C00002185B4
+:105B200004004185004800440800219CECFF219CB2
+:105B3000004801D4045001D4086001D40C7001D491
+:105B4000108001D4000083A9000044A90000C09C7B
+:105B50000000209D0300609C00182CE45900000CFC
+:105B60000000009E0400609C00182CE44E00000C15
+:105B70006C0D649C0100C09D00702CE43E00000C84
+:105B80000200609C00182CE43400000CC811649CD6
+:105B900004006018B87F63A804008018C07F84A840
+:105BA0000000E3844A00C6B8000084840040601806
+:105BB000100B63A8180007B9002003D40800A6B88A
+:105BC00000406018180163A800408018300284A8C3
+:105BD000004003D40A00C6B80400639C0038A5E066
+:105BE000003003D40000E09C002804D40040C0181A
+:105BF0000C04C6A8000064840080A0180000A5A8BA
+:105C0000042863E00100809C001806D400202CE4E6
+:105C1000030000100000A09C0000E4A8002810E48D
+:105C2000030000100000609C000064A8031867E0F7
+:105C3000002803E42B00001000000015000066841B
+:105C400000408018000084A8042063E0001806D4F7
+:105C500024000000000000158805C48C7012AA9C66
+:105C600041FFFF07F011849CC0112A85C9FFFF0383
+:105C7000BC11CA841C03C48C980D649C400EAA9C61
+:105C800039FFFF07C00D849C880D6A8C8C0DCA8477
+:105C9000008023E4BFFFFF13900D2A85BDFFFF03A3
+:105CA00000000EAA570DC48C140EAA9C2EFFFF07ED
+:105CB000940D849C680D2A85B6FFFF03640DCA8489
+:105CC000900BC48C5012649C1C0CAA9C26FFFF07EE
+:105CD0009C0B849C48122A85AEFFFF034C12CA8499
+:105CE00004006018C47F63A84A00C9B80000E384B8
+:105CF0000800C6B804006018BC7F63A81000E7B8AD
+:105D00000000838404006018D07F63A80020C6E0F0
+:105D10000000A38404006018D47F63A81000A5B815
+:105D20000000838404006018C87F63A8080084B85A
+:105D3000000003850020A5E000406018340263A83D
+:105D40000040E7E0003003D404008018CC7F84A832
+:105D500004006018D87F63A8000084840000C38416
+:105D6000004060180C0B63A80030A5E0003803D495
+:105D70000400C018DC7FC6A800406018240C63A88B
+:105D80000000C684002003D404006018788463A84F
+:105D900000408018088084A80000E384002804D410
+:105DA000004060187C9063A804008018748484A864
+:105DB000003003D40040A0180000A5A800006484AF
+:105DC0000028E7E000408018000084A80000A784B5
+:105DD000002063E00000C3840B00A5B80400801815
+:105DE000908084A80B00C6B804006018C88063A81F
+:105DF000003004D4002803D400002185040041852C
+:105E0000080081850C00C18510000186004800440F
+:105E10001400219C00408018000184A8FEFFE09C33
+:105E2000000064840040C0180401C6A80000A09CC3
+:105E3000033863E0001804D400006684070063A4FC
+:105E4000002823E4FDFFFF130200809C0040A018FF
+:105E50000402A5A800006584480063B8070063A495
+:105E6000FDFF639C0020A3E4FBFFFF13000000156F
+:105E700000406018000263A8FEFFC09C00008384FD
+:105E80000040A0180000A5A8E703E09C033084E0D0
+:105E9000002003D4003805D4FF03609C001805D40B
+:105EA0000048004400000015F4FF219C004801D484
+:105EB000045001D4086001D40000A3A8000084A904
+:105EC0000300609C001825E46600000C0000409D63
+:105ED0000400609C001825E44400000C0100609C54
+:105EE000001825E42300000C0200609C001825E443
+:105EF00078000010000000155BFEFF07C811649CCD
+:105F000088050C8D00408AE47200000CF011EC9CB6
+:105F100004006018088063A80000A3847012CC9C61
+:105F2000040060180C8063A800008384004060189F
+:105F3000000063A80018A5E0001884E00000658454
+:105F400001004A9D001807D40400A59C0000648449
+:105F50000400E79C001806D40400849C00408AE4F6
+:105F6000F7FFFF130400C69C5A0000000000001554
+:105F70003DFEFF07980D649C1C030C8D00408AE4D5
+:105F80005400000CC00DEC9C04006018088063A84D
+:105F90000000A384400ECC9C040060180C8063A811
+:105FA0000000838400406018000063A80018A5E08A
+:105FB000001884E00000658401004A9D001807D4A1
+:105FC0000400A59C000064840400E79C001806D42B
+:105FD0000400849C00408AE4F7FFFF130400C69C81
+:105FE0003C000000000000151FFEFF076C0D649CC4
+:105FF000540D0C8500408AE43600000C940DEC9C96
+:1060000004006018088063A80000A384140ECC9CD0
+:10601000040060180C8063A80000838400406018AE
+:10602000000063A80018A5E0001884E00000658463
+:1060300001004A9D001807D40400A59C0000648458
+:106040000400E79C001806D40400849C00408AE405
+:10605000F7FFFF130400C69C1E000000000000159F
+:1060600001FEFF075012649C900B0C8D00408AE4E7
+:106070001800000C9C0BEC9C04006018088063A8BE
+:106080000000A3841C0CCC9C040060180C8063A846
+:106090000000838400406018000063A80018A5E099
+:1060A000001884E00000658401004A9D001807D4B0
+:1060B0000400A59C000064840400E79C001806D43A
+:1060C0000400849C00408AE4F7FFFF130400C69C90
+:1060D00000002185040041850800818500480044B6
+:1060E0000C00219C80FFA09C7F00639C1F00849C6F
+:1060F000032863E0E0FFA09C032884E0062363E01C
+:1061000000E0809CFF1F639C032063E0000063A904
+:10611000004800440000001500406018180463A8FF
+:106120000000638507006B9D43006BB90048004485
+:106130000000001500406018140463A80000638587
+:10614000004800440000001500406018080463A8DF
+:106150000000609D00008384480084B80000609CBB
+:10616000070084A4001804E4070000100200A4B88B
+:106170000040C0180003C6A8000064A9003065E014
+:10618000000083840048004400000015E8FF219CC3
+:10619000004801D4045001D4086001D40C7001D42B
+:1061A000108001D4149001D4000044AA000003AA76
+:1061B000000046A9000085A9000065A8CAFFFF07E6
+:1061C000000086A85F008AB800006CA80000CBA978
+:1061D00000204AE181004AB9C3FFFF0700008AA8F6
+:1061E0000000609C0000809C0080AEE40300001072
+:1061F0000100A09C000065A80090ABE40400001022
+:10620000042083E00100809C042083E00000609C67
+:10621000001804E40400000C000065A90000A09C24
+:10622000000065A9000021850400418508008185E2
+:106230000C00C1851000018614004186004800440E
+:106240001800219C0080C0180000C6A80080E0183B
+:106250000400E7A80030A3E00038C3E00000E484B5
+:10626000003805D40080A0180800A5A80028E3E0A5
+:106270000400A484002806D40080C0180C00C6A81E
+:106280000030A3E00800C484003007D40C00C484AC
+:106290000080E0181000E7A810008484003863E054
+:1062A000003005D4002003D400480044000000154D
+:1062B0000080C0180000C6A80080E0180400E7A80D
+:1062C0000030A3E00000A5840038C3E0002804D417
+:1062D0000000C6840080A0180800A5A80028E3E0FC
+:1062E000043004D40000E7840080C0180C00C6A865
+:1062F000083804D40030A3E00080E0181000E7A8BC
+:106300000000A584003863E0000063840C2804D4F6
+:10631000101804D40048004400000015E0FF219C40
+:10632000004801D4045001D4086001D40C7001D499
+:10633000108001D4149001D418A001D41CB001D451
+:106340000000C3A9000004AA00006384000045A95E
+:10635000000086A9000087AA002823E40600001098
+:106360000000C8AA00006484003023E42800000C68
+:106370000000609D00006AA85BFFFF0700008CA87A
+:1063800041008CB800004BAA57FFFF0700006AA825
+:1063900000A0B2E4030000100000809C0100809C7B
+:1063A00000B0ABE4030000100000609C0100609CA2
+:1063B000041864E00000809C002003E40600001044
+:1063C00000A072E400500ED40200609D1000000096
+:1063D000006010D4030000100000A09C0100A09CED
+:1063E00000B06BE4030000100000609C0100609CA2
+:1063F000041865E0002003E4040000100300609D21
+:10640000F3FFFF0300500ED40000609D00002185C3
+:1064100004004185080081850C00C18510000186BB
+:1064200014004186180081861C00C1860048004483
+:106430002000219CE4FF219C004801D4045001D499
+:10644000000044A91400809C082001D468210AD4CB
+:10645000E0008A846C210AD4E4008A8470210AD482
+:10646000E8008A8474210AD40000809C78210AD430
+:10647000E0008A840C2001D4E4008A84102001D436
+:10648000E8008A84142001D40000809C182001D4E4
+:106490006DFFFF070800819C68016A850000218567
+:1064A00004004185004800441C00219CD8FF219C29
+:1064B000004801D4045001D4086001D40C7001D408
+:1064C000108001D4000044A90000C6A91400E09C7B
+:1064D000E000CA84000003AA000085A86C310AD439
+:1064E00004006018836D63A8E400CA840000809DE6
+:1064F00070310AD468390AD4E800CA8474310AD4E5
+:106500000000C09C0028A7E40800001078310AD4DD
+:106510001AF0FF070000001500506EE09DFF809C00
+:1065200014000000282103D804006018996D63A8A6
+:1065300012F0FF07000090A86801CA84143001D44B
+:106540006C016A84181801D470018A841C2001D45B
+:106550007401CA841400819C203001D478016A84BB
+:10656000241801D438FFFF07000070A868018A854D
+:1065700000006CA900002185040041850800818588
+:106580000C00C18510000186004800442800219CB1
+:10659000D4FF219C004801D4045001D4086001D4E8
+:1065A0000C7001D4108001D4149001D4000084A98F
+:1065B000000045AA010088B83F00679D000003AABB
+:1065C0001F00849C1F00089D9F00A4B89F004BB92A
+:1065D0009F0028B95B00A5B85A004AB95B0029B9E9
+:1065E000002884E000506BE1E0FFA09C004808E137
+:1065F000032884E086006BB92000849C032808E10E
+:10660000300061840623ABE00000C6A900008BA81F
+:106610000000609D005803E4380000102000E89C52
+:106620000600E5B85C00AC841400479D04006018C7
+:10663000A96D63A8000090A82C00C79C0028A6E4C0
+:106640000E00001000602EE10000609C97FFA09CEF
+:10665000481909D804006018B56D63A8282909D81D
+:10666000C6EFFF07000086A80000609C0000609D48
+:1066700025000000001812D4EC00AC846C290CD466
+:1066800078390CD4F000AC8470290CD468510CD447
+:10669000F400AC84B9EFFF0774290CD468016C8452
+:1066A0001800819C181801D46C01AC841C2801D4FA
+:1066B00070016C84201801D47401AC84242801D4A6
+:1066C00078016C84281801D4DFFEFF07000070A851
+:1066D00000606EE00000A09C000083A8282903D879
+:1066E0000100609C0100A09C481904D8002812D425
+:1066F0000500000068016C85063B64E0CAFFFF03EB
+:106700000600E3B80000218504004185080081856A
+:106710000C00C18510000186140041860048004429
+:106720002C00219CDCFF219C004801D4045001D4A2
+:10673000086001D40C7001D40000C4A93F00A79DDB
+:10674000010088B89F008DB90000EDA81F00849C4F
+:106750005A008CB99F0024B91F00089D0060ADE16C
+:106760005B0029B98600ADB99F0068B9004884E094
+:106770000060E7E0E0FF209D5B006BB9034884E028
+:10678000000043A92000849C005808E10623ADE1E5
+:10679000034808E1240061840000609D860087B8FA
+:1067A000005803E42B0000102000E89C0600EDB820
+:1067B0001400279D0070C6E004006018A96D63A84E
+:1067C0001800079D0028A8E40A00001000008AA80D
+:1067D00097FF609C281906D804006018B56D63A85F
+:1067E00066EFFF07000088A81D0000000000609D04
+:1067F000EC00AE8468490ED46C290ED4F0002E85CE
+:10680000F400AE8478390ED470490ED45BEFFF07E4
+:1068100074290ED468012E851000819C104801D483
+:106820006C016E84141801D47001AE84182801D450
+:1068300074012E851C4801D478016E84201801D47F
+:1068400081FEFF0700006AA80500000068016E8550
+:10685000063B64E0D7FFFF030600E3B80000218594
+:1068600004004185080081850C00C1850048004472
+:106870002400219CBCFF219C004801D4045001D479
+:10688000086001D40C7001D4108001D4149001D49C
+:1068900018A001D4000084A9000003AA4C0084843D
+:1068A000000045A9000046AA0038C4E104006018B1
+:1068B000C56D63A800008EA830EFFF070000809E22
+:1068C0003000819C7BFEFF0700006EA830008184B1
+:1068D0000050A4E43100000C3C006184E8008C848A
+:1068E000002023E4080000100000001504006018D8
+:1068F000D46D63A821EFFF07000090A82F000000CF
+:10690000000074A904006018E16D63A81BEFFF0785
+:10691000000090A8300061841C1801D434008184E8
+:1069200038006184202001D4241801D43C008184E3
+:1069300040006184282001D42C1801D41C00819CC3
+:1069400041FEFF07000070A84000E1841400109E83
+:10695000003894E40F00000C0000C09C00808018F8
+:10696000000084A800806018140063A80020B0E034
+:1069700000188EE0000064840400C69C001805D452
+:106980000400849C003886E4FBFFFF130400A59CF0
+:10699000090000003000818604006018EE6D63A8D5
+:1069A000F6EEFF0700000015006072E09CFF809C7F
+:1069B000282103D8000074A9000021850400418526
+:1069C000080081850C00C1851000018614004186F5
+:1069D00018008186004800444400219CE4FF219C6B
+:1069E000004801D4045001D4086001D40C7001D4D3
+:1069F000108001D4149001D418A001D40000C6A9BD
+:106A0000000045A90000C4A80623A8E0000083AA4E
+:106A1000000008AA000087A904006018016E63A89E
+:106A20000633CEE000008AA8002847E2D3EEFF0735
+:106A300000304AE1040060180A6E63A8CFEEFF0739
+:106A400000008EA804006018136E63A8CBEEFF0749
+:106A500000008CA8040060181C6E63A8C7EEFF0736
+:106A6000000090A800908AE41900000C0100E09C4E
+:106A70009F00AAB8F8FF609C5B0085B85D00A5B8D0
+:106A800000208AE0850084B80028AAE0020084B8CB
+:106A90000318A5E00228CAE000806018000063A87F
+:106AA00000A084E00830C7E0001884E001004A9D9F
+:106AB000000064840828C6E0043063E0001804D4B1
+:106AC00000908AE4ECFFFF139F00AAB80000218524
+:106AD00004004185080081850C00C18510000186F5
+:106AE0001400418618008186004800441C00219C47
+:106AF000CCFF219C004801D4045001D4086001D48B
+:106B00000C7001D4108001D4149001D418A001D4C9
+:106B10001CB001D40643E7E0000043AA0000C4A96A
+:106B200004006018256E63A8000092A8000045A923
+:106B3000000086AA0000C09E0700E79C8FEEFF07BA
+:106B4000430007BA1700709CFF3F8018FCFF84A821
+:106B5000032083E10050ACE40A000010000000159F
+:106B600004006018386E63A884EEFF0700008CA84C
+:106B7000007074E098FFC09C27000000283103D803
+:106B800004006018506E63A87CEEFF07000092A816
+:106B9000206001D4308001D4F8006E84FC008E8423
+:106BA0000001CE846C190ED470210ED474310ED431
+:106BB00068610ED478810ED4241801D4FC008E8430
+:106BC000000072A8282001D41400529E0001CE8437
+:106BD0002000819C9CFDFF072C3001D47801AE84FD
+:106BE000002896E40B00000C0000809C0080C01878
+:106BF0000000C6A8003072E00000C09C0400849C25
+:106C0000003003D4002884E4FCFFFF130400639CDD
+:106C10006801CE86000076A9000021850400418528
+:106C2000080081850C00C185100001861400418692
+:106C3000180081861C00C186004800443400219C55
+:106C4000F0FF219C004801D4045001D4086001D415
+:106C50000C7001D4000004A9FF0063A4000086A901
+:106C6000000083A80000C7A8000045A91000609C90
+:106C70000000A8A86CF0FF070000E09C52F0FF079E
+:106C80000000001580F0FF07000000150040A0186C
+:106C90000800A5A80000809C00006584002023E473
+:106CA000FEFFFF130000001500406018300063A8CD
+:106CB0000700809C0000C38500202EE41B0000100C
+:106CC0000400639C5F00CCB8000063848B008CB828
+:106CD0000000A3A800180AD4003084E00040601827
+:106CE000140663A8810084B8002803D40040C018AB
+:106CF0002CC5C6A80020A5E00040601808C063A805
+:106D00000100809C002003D400408018180684A84D
+:106D10000800639C002804D40100809C002003D458
+:106D20001C0000000F00609C00408018000084A838
+:106D3000FB03C09CFF03609C003004D40040A018FB
+:106D400018C0A5A8001804D40100C09C0100809CB4
+:106D50000040601808C063A8002003D40800639CAA
+:106D6000002003D40040601858C063A80000809C35
+:106D7000003003D40040C0182CC5C6A800006584AC
+:106D8000100063A4002003E4FDFFFF131F00609CBC
+:106D9000001806D40000809C002006D404F0FF07F1
+:106DA0000000001500006EA9000021850400418547
+:106DB000080081850C00C185004800441000219C1A
+:106DC0000000C3A80700609C001825E41D00001007
+:106DD000000065A95F00A4B88B0064B8004080186B
+:106DE000140684A8002863E0003004D40100A09CAD
+:106DF0000040801808C084A8810063B8002804D42B
+:106E0000001866E000408018180684A80100C09CA5
+:106E1000001804D40040A0182CC5A5A80040601894
+:106E200010C063A80000809C003003D40F00609C59
+:106E3000001805D4002005D41F0000000000001534
+:106E400000408018000084A8FB03A09CFF03C09CA6
+:106E5000002804D40040601808C063A8003004D49F
+:106E60000040A01818C0A5A80100809C0100C09C8B
+:106E7000002003D40800639C002003D40040601865
+:106E800058C063A80000809C003003D40040C018A4
+:106E90002CC5C6A800006584100063A4002003E48C
+:106EA000FDFFFF131F00609C0000809C001806D4AB
+:106EB000002006D400480044000000150000609D3A
+:106EC00000480044000000150000609D0048004498
+:106ED000000000150000609D0048004400000015FF
+:106EE0000000609D00480044000000150000609D07
+:106EF00000480044000000150000609D0048004468
+:106F0000000000150000609D0048004400000015CE
+:106F10000000609D00480044000000150000609DD6
+:106F200000480044000000150300A3B80400C01886
+:106F30004C80C6A80218A5E0001806D40200A5B827
+:106F400004006018508063A8002003D40400601877
+:106F5000108063A80018A5E004006018488063A8AA
+:106F6000002803D400480044000000150400601805
+:106F7000488063A80000A09C00008384002804D4FB
+:106F8000042804D40400609C0800849C0000C09C79
+:106F90000100A59C003004D40018A5E5FDFFFF13F7
+:106FA0000400849CFFFF809C040060184C8063A850
+:106FB000FFFFC09C002003D404008018508084A8E8
+:106FC000003004D40048004400000015FCFF219C60
+:106FD000004801D4E6FFFF070000001500002185EE
+:106FE000004800440400219CA600809C002023E46B
+:106FF000080000100000001504006018488063A815
+:107000000000A38408008584010084A8082005D41A
+:107010000048004400000015F8FF219C004801D4FE
+:10702000045001D40000A3A8A600809C0000409D4D
+:10703000002025E406000010000064A8EBFFFF0715
+:10704000000000151700000000006AA90400601885
+:10705000508063A80000838404006018488063A8FF
+:10706000040084B80000C38404006018E08163A8B1
+:10707000001884E00800A4840C0064840200A5B811
+:1070800004008018808984A80020A5E000006585A0
+:10709000005800480400868400004BA900006AA93B
+:1070A0000000218504004185004800440800219C1F
+:1070B000004800440000001500480044000000158E
+:1070C000F8FF219C004801D4045001D4F9FFFF07C8
+:1070D000000043A9F9FFFF07000000150400601835
+:1070E000488063A8000083840200609C045004D49C
+:1070F000001804D4000021850400418500480044A4
+:107100000800219C0100609D00480044000000151B
+:107110000100609D0048004400000015F8FF219C1C
+:10712000004801D4045001D4F7FFFF070000409D40
+:1071300000500BE4040000100000001508000000DF
+:107140000A00409DF3FFFF070000001500500BE40C
+:1071500003000010000000150B00409D04006018A3
+:10716000708363A86BFE000400008AA800002185DC
+:1071700004004185004800440800219CFCFF219C3C
+:10718000004801D4FFFF639C0000A5A9470063B835
+:107190000000A6A842002DB90100639DFFFFE49CFA
+:1071A0002000659C001844E4030000100000C09C0F
+:1071B0000100C09C002065E4030000100000609CFA
+:1071C0000100609C031866E00000809C002003E43E
+:1071D0001E000010450005B9450067B8010063A412
+:1071E000002023E4190000100100E8A500202FE48E
+:1071F000160000104800EDB8460085B847006DB88D
+:10720000FF0084A41F00A5A4065B84E00400A5B8C9
+:107210000F00C9A43F00E7A40430A5E0010063A467
+:10722000007823E405000010003884E046006DB8C3
+:1072300018000000010063A446006DB8010063A4BB
+:1072400014000000020063A8460085B81F0065A472
+:107250004500C9B8FF0084A4040063B8065B84E05D
+:107260000F00A9A47F00E6A40428A3E00100C6A49F
+:10727000010068A4001826E404000010003884E02F
+:10728000ECFFFF03440069B8EDFFFF03440069B859
+:107290000D0064B90B0063B80200A5B804186BE1D7
+:1072A00004286BE100002185004800440400219C73
+:1072B000FCFF219C004801D4004000190C1608A9CD
+:1072C000001808D400406018101663A8002003D4EA
+:1072D0000400639C004080181C1684A8002803D476
+:1072E0000400639C003003D4003804D40400601808
+:1072F000508363A80000809C002003D400408018C5
+:10730000001684A80100609C001804D4BBECFF07A1
+:10731000000000150000609D000021850048004429
+:107320000400219CF0FF219C004801D4045001D4AA
+:10733000086001D40C7001D40000C384000083A94C
+:107340000000609C001806E44800000C000146A9FB
+:1073500008004C850100C09D0070AAE52000000CCB
+:107360000000001500702AE4600000100000001505
+:107370001C00AC8414006C840F00A5B8080063B82E
+:1073800018008C840418A5E02400EC84070084B85D
+:107390002C006C840800E7B80420A5E00400CC842D
+:1073A000080063B8000085A820002C85000146A9CC
+:1073B00028000C85044867E10000C5A8044023E1CB
+:1073C00030280CD40000EAA80000A9A8B9FFFF07E4
+:1073D00000006BA8460000000000609D1C00AC840B
+:1073E000FFFF4A9D14008C840F00A5B808004AB91D
+:1073F00018006C84080084B8070063B80420A5E076
+:107400002400CC840418A5E02C00EC840800C6B845
+:10741000000085A820006C840800E7B828002C85AF
+:10742000041866E10C000C85044827E10000C5A89B
+:1074300004404AE130280CD400006BA80000EAA800
+:107440000000A9A89BFFFF0700004EA914006C8450
+:1074500008008C84002063E008700CD4FFFF639C5C
+:10746000C1FFFF0314180CD41C00AC8414008C84DE
+:107470000F00A5B80000EAA818006C84080084B8C2
+:10748000070063B80420A5E010000C850418A5E0EF
+:107490002400CC840440A5E02C006C840800C6B80D
+:1074A000000085A820000C85080063B828002C8502
+:1074B000044066E1044823E10000C5A830280CD44C
+:1074C0000000A9A87BFFFF0700006BA808006C84E0
+:1074D00014008C84FFFF639C0100849C08180CD46A
+:1074E0009CFFFF0314200CD40000609D0000218548
+:1074F00004004185080081850C00C18500480044D6
+:107500001000219CFCFF219C004801D40400C018FD
+:107510005080C6A80000A6840400A5B80400C018C6
+:10752000E081C6A80030A5E00800C5840200C6B806
+:107530000400A0189C89A5A80028C6E00000668564
+:107540000058004800000015000021850048004454
+:107550000400219CF8FF219C004801D4045001D470
+:10756000E9FFFF07000044A90000809C00200BE415
+:107570000400001000006AA8E9FEFF0700000015E3
+:1075800004006018488063A80000609D00008384A8
+:107590000100609C041804D40300609C001804D40B
+:1075A0000000218504004185004800440800219C1A
+:1075B000B801A3840200A5B80018A5E0B02725D41F
+:1075C0000048004400000015FCFF219C004801D445
+:1075D000F8FFFF070000809C000021850048004460
+:1075E0000400219CB8018384020084B8B00F849CFD
+:1075F000002063E0000063850000809C002003D42D
+:107600000048004400000015B8018384020084B8DB
+:10761000001884E0B00F64850048004400000015A5
+:10762000FCFF219C004801D4C8FAFF0700000015A8
+:1076300000406018800363A8B701809C0000A38409
+:10764000002025E40500001000000015004060182F
+:10765000000363A8000083840000218500480044E3
+:107660000400219C0040A018280BA5A80000609CE5
+:1076700000008584001804E40300001000000015D9
+:10768000001805D400480044000000150000C3A8FD
+:107690000000809C00406018280B63A80000A384B1
+:1076A000002025E43C00001000000015B8016684AD
+:1076B000020063B80030A3E0900A85843F00609C1C
+:1076C000100BE5840200C4B80018A4E42A000010DE
+:1076D0000000A6A800406018000663A8001886E015
+:1076E0000000A484004060180C0563A80000838497
+:1076F0000B00A5B80040C0180006C6A800406018DE
+:107700002C0B63A8002884E0002003D4020067B893
+:107710000030A3E03F00609C0018A7E411000010B7
+:10772000000000150000A584004080180C0584A806
+:107730000B00A5B80000648400408018300B84A8BA
+:10774000002863E0001804D400406018280B63A8E8
+:107750000100809C002003D40F00000000000015F1
+:107760000000A58400408018080584A8F2FFFF03EC
+:107770000B00A5B80040C0180006C6A8004060185D
+:10778000080563A8003085E00000A484D8FFFF034B
+:107790000000001500480044000000150000809C17
+:1077A000902043D4FFFF809C5C2043D4602043D4CE
+:1077B000642043D4682043D4942043D40048004438
+:1077C00000000015F8FF219C004801D4045001D4AA
+:1077D0008EFFFF07000043A97A00609C00182BE48D
+:1077E000030000100000A09C0100A09C1C00609CF5
+:1077F00000182BE4030000100000809C0100809C16
+:10780000042065E00000809C002003E410000010CC
+:107810000000001583016A8C002023E4030000109F
+:107820000300809C0B00809C004060181C2063A813
+:10783000002003D4B8018A84E8016A9C63F3FF073F
+:10784000900BAA8C0A0000000000001583016A8CCE
+:10785000002023E4030000100000809C0800809CAE
+:10786000004060181C2063A8002003D4CCFFFF0751
+:1078700000006AA8000021850400418500480044FA
+:107880000800219CFCFF219C004801D40040A01866
+:107890002020A5A8AB00809C0000C5840100A09C0E
+:1078A000002826E4040000100000E3A80000A09CCB
+:1078B000302843D43010C7840000A09C002806E480
+:1078C00004000010000000153AFFFF07000000153B
+:1078D00000002185004800440400219C00408018DD
+:1078E000180484A80100609D0000A484AC0D83846A
+:1078F0004300A5B8002085E40300000C000000153B
+:107900000000609D0048004400000015ECFF219C31
+:10791000004801D4045001D4086001D40C7001D493
+:10792000108001D4000083A90000C09D0000609C6D
+:10793000900BAC8CE8190CD8E9190CD8EA190CD8C2
+:10794000C4190CD8C5190CD800288EE50E00000CFF
+:10795000C6190CD8E8010C9EC7014C9D00008EA8EA
+:10796000000070A819F3FF070100CE9DFFFF609C87
+:10797000900BAC8C00180AD800288EE5F8FFFF1396
+:1079800001004A9D00002185040041850800818591
+:107990000C00C18510000186004800441400219CA1
+:1079A000FCFF219C004801D47A01038D0000C3A88C
+:1079B0000300609C004023E41E000010000000153E
+:1079C0000200E694000066940F00879C0000209D52
+:1079D0000F00639C840084B8840063B89C01A68473
+:1079E000FFFF849CFFFF639C004825E40F0000100C
+:1079F000401A46D414006684004823E40B000010AB
+:107A0000FF00A8A40300609C001825E407000010F4
+:107A10001F00E79C850067B8010063B8FFFF639C07
+:107A200007000000441A46D405000000442246D452
+:107A300002006694E4FFFF034100E3B800002185E3
+:107A4000004800440400219CF8FF219C004801D418
+:107A5000045001D40C02A384000043A90100C09C7F
+:107A60008301638C001805D87A016A8C031805D845
+:107A700000008A94003084E07B016A8C083084E046
+:107A8000241805D40A2005DC02006A94003063E063
+:107A9000083063E00C1805DC6C018A8CFF00849CC4
+:107AA000FF0084A4003044E4180000100000609C33
+:107AB000063005D87A018A8C0200609C001824E404
+:107AC0000A00001000000015B801CA84020086B840
+:107AD0006A016A940050A4E0301F25D458106A84CB
+:107AE0000C000000301E25D4B801CA84020086B8FC
+:107AF0006A016A940050A4E0B01E25D458106A842C
+:107B000004000000B01D25D4EBFFFF03061805D8C4
+:107B10000000EA9400006AA80050A4E00200CA94A1
+:107B20009C3C25D49FFFFF071C3525D4D8FEFF07BA
+:107B300000006AA800002185040041850048004437
+:107B40000800219CF4FF219C004801D4045001D47A
+:107B5000086001D4FF0044A5FFFFAA9CAE00809CF2
+:107B6000002045E407000010000083A96601A38CF3
+:107B70000000809C002005E44D00000C0000001572
+:107B8000B400609C00180AE44F00001000184AE599
+:107B90002B000010B700609CB200609C00180AE443
+:107BA0001E00001000184AE5140000100000809C20
+:107BB00000200AE44400000C0000001566016C8CF3
+:107BC000002003E4070000100100609CB0016C84F9
+:107BD000002003E40500000C000000150100609C7B
+:107BE0003900000067190CD8AB0B000400006CA82A
+:107BF000FCFFFF030100609C190B000400006CA84F
+:107C00000000609C74190CD80100609C66190CD8A7
+:107C1000F4FFFF030000609C66018C8C0000609CF8
+:107C2000001804E42800001000000015F30B000405
+:107C3000AC0D6C84240000000000001500180AE45C
+:107C40002100001000184AE50E000010B800609CEA
+:107C5000B500609C00180AE41B00000C0000609C4A
+:107C600066018C8C001804E4170000100000001559
+:107C7000630D000400006CA8130000000000001554
+:107C800000180AE41000000C0000609C66018C8C57
+:107C9000001804E40C000010000000155D0B000447
+:107CA00000006CA808000000000000159F0B0004F5
+:107CB0000000001507006BB900506BE1FFFF6B9DE2
+:107CC000A0590CD40000218504004185080081855D
+:107CD000004800440C00219CE8FF219C004801D48E
+:107CE000045001D4086001D40C7001D4108001D478
+:107CF000149001D4000083A90040001AE00310AAE8
+:107D000000406018180463A80100409D00004386ED
+:107D10000040C0192003CEA90CF9FF070000001590
+:107D200000009084005024E40A00000C00006CA8BD
+:107D3000EBFEFF070000001500502BE40500000CCF
+:107D40000000001500006E84F6FFFF030000001520
+:107D500000406018180463A80000638502906BE17E
+:107D600007006B9D9F006BB85D0063B800186BE166
+:107D700083006BB9000021850400418508008185DE
+:107D80000C00C185100001861400418600480044A3
+:107D90001800219CE8FF219C004801D4045001D424
+:107DA000086001D40C7001D4108001D4149001D467
+:107DB000000043A90040401A800352AAAE00009E72
+:107DC0000040C0191804CEA90040801900038CA9F6
+:107DD000C2FFFF0700006AA800007284FF0063A5CD
+:107DE000FFFF8B9C008044E40C00000C0000001599
+:107DF00000006E840700639CAC0D8A84430063B866
+:107E0000002083E40500000CFFFF609D00006C84EF
+:107E1000F0FFFF03000000150000218504004185EC
+:107E2000080081850C00C185100001861400418680
+:107E3000004800441800219CF8FF219C004801D410
+:107E4000045001D4A5FFFF07000043A9B3F8FF07C2
+:107E5000000000154C584AD40000218504004185DB
+:107E6000004800440800219CF8FF219C004801D4F0
+:107E7000045001D499FFFF07000043A9AC0D8A8488
+:107E800000006AA800208BE4050000100000A09C00
+:107E90000100609C0E000000B0190AD40040A01838
+:107EA0000003A5A80000858427FFFF07FF0084A426
+:107EB00067016A8C0100809C002023E4040000100C
+:107EC0000000A09CB0210AD40000A4A8000065A96D
+:107ED0000000218504004185004800440800219CE1
+:107EE000F4FF219C004801D4045001D4086001D45F
+:107EF000B401C384000043A9E801839D000086A863
+:107F0000FFFFA09C002806E40B00001000006CA8F6
+:107F10006BF2FF07900BAA8C0000809C00202BE4E2
+:107F20000500001000006CA8B4018A84A7F1FF07C7
+:107F3000900BAA8C900BAA8CC4016A9C29F2FF07B3
+:107F4000B4018A9C000021850400418508008185D8
+:107F5000004800440C00219CE8FF219C004801D40B
+:107F6000045001D4086001D40C7001D4108001D4F5
+:107F7000000083A90000609C00182CE4040000109D
+:107F8000000044A924000000FFFF609D9B01648C59
+:107F9000E801049EFFFFC09D900BC48C1400A19CBF
+:107FA000BCF1FF07000090A800702BE41300000C48
+:107FB0000000001514008184BC016A84001804E4E8
+:107FC000070000100000001514008184C0016A84BD
+:107FD000001804E40F00000C000000151400818458
+:107FE000000070A879F1FF07900BAA8C00702BE4B9
+:107FF0000400001000006CA80700000000006EA93B
+:10800000D6FFFF0700008AA803000000000000154B
+:1080100014006185000021850400418508008185E8
+:108020000C00C18510000186004800441800219C06
+:10803000F4FF219C004801D4045001D4000043A95E
+:108040000200609CC5FFFF0700008AA8085801D401
+:10805000FFFF809C08006184002023E40C00000CDA
+:10806000000064A9080061840000609D000083A8EE
+:10807000B8190AD4040063B8022063E0020063B8B0
+:1080800000186AE01002639C0C1A0AD400002185D3
+:1080900004004185004800440C00219CFCFF219C09
+:1080A000004801D40040601818A063A800400019DF
+:1080B000200808A90000A3840040E018280CE7A8C5
+:1080C0000000E09D0000C384FFFFA5A40000A09D68
+:1080D00000006884500026B90100609D000087847C
+:1080E00000006784500084B80000C884FFFF63A4C8
+:1080F000001825E403000010000000150000EBA9A3
+:10810000002029E40400001003688FE00100A09D16
+:1081100003688FE00000609C001804E40300000C7A
+:10812000000000150000609D00002185004800440B
+:108130000400219CECFF219C004801D4045001D490
+:10814000086001D40C7001D4108001D4980B838492
+:10815000000003AA0000609C001824E40C0000103A
+:108160000000409D0F27C09D0000809D0070AAE583
+:108170000700000C00000015C9FFFF0701004A9D21
+:1081800000600BE4FAFFFF13000000150040C01868
+:108190001005C6A80000409D00006684005023E43E
+:1081A0000B00000C0F27A09C0000809C01004A9D42
+:1081B0000028AAE50600000C0000001500006684F7
+:1081C000002023E4FBFFFF1301004A9DE8117084A7
+:1081D0000000809C010063A4002003E41000001054
+:1081E0000000409D0040C018380CC6A800006684FE
+:1081F000005023E40A00000C0F27A09C01004A9DB8
+:108200000028AAE50600000C0000001500006684A6
+:10821000002023E4FBFFFF1301004A9D000021859D
+:1082200004004185080081850C00C185100001868D
+:10823000004800441400219CF8FF219C004801D410
+:10824000045001D40C028384000043A90600A48CCE
+:108250000000809C002005E410000010C401639C15
+:10826000BC01CA84FFFFA09C002806E40700000CA4
+:10827000000086A8BC016A84C0190AD4B8016A84C7
+:1082800009000000BC190AD4D0F0FF07900BAA8C9B
+:10829000FAFFFF03BC016A84900BAA8CCBF0FF07A6
+:1082A000B8018A840000218504004185004800440B
+:1082B0000800219CD0FF219C044801D4085001D41F
+:1082C0000C6001D4107001D4148001D4189001D432
+:1082D0001CA001D420B001D424C001D428D001D4E2
+:1082E0002CE001D4B8010385000043A90000409EA2
+:1082F0000200A8B8000063940000009E0050C5E092
+:108300000F00639C02008A94840003BB9C0BE684EC
+:108310000F00849CB0108A850B0047BB8400C4BA50
+:10832000B410C685A40D6A84009023E404000010F4
+:1083300000008CAB820000000000609D005068E0EF
+:108340000000809C0000A3A89C2143D80000609CF2
+:10835000E811EA84400087A4009004E41E000010A5
+:108360007C1945D89C106A84009003E41B0000101F
+:10837000010067A41400809EECFFAC9C0000C8A81C
+:1083800000006EA80000F0A800A04CE56700000CFB
+:1083900054108A9C38F9FF07000000150000609C0B
+:1083A00000180BE406000010000000150058CEE194
+:1083B00002588CE1005810E20100409E00182BE4A6
+:1083C0000400000C00000015ECFFFF03B8010A8553
+:1083D000E811EA84010067A40000009E008003E425
+:1083E000500000100000809C1400609C00184CE5B8
+:1083F0003200001054108A9CB8016A8497FF809C58
+:10840000005063E07C2143D80000609C0000809C09
+:10841000341A4AD4020067A4002003E405000010C7
+:1084200002607CE028724AD42C1A4AD424224AD40E
+:10843000A00D6A84002003E4030000100000A09C4B
+:108440000100A09C002012E4030000100000609CCA
+:108450000100609C041865E0002003E40A0000109D
+:108460000000609C1300609C0018ACE50900000C43
+:108470009DFF809CB8016A84005063E07C2143D852
+:108480000000609C0100609D2D000000A41D2AD406
+:10849000B801CA8454108A9C00006EA804F8FF0733
+:1084A0000000ACA8B8016A840100809C005063E021
+:1084B000F4FFFF039C2143D8B801CA84ECFFAC9CB5
+:1084C00014006A84008023E4030000100000E09C94
+:1084D0000100E09C003801D400006EA80000F8A85C
+:1084E00091F8FF07000016A902D06EE01400639C0B
+:1084F000430063B800800BE4080000109C1D2AD4E0
+:108500000100609CE811EA8402588CE10058CEE139
+:10851000BEFFFF03A01D2AD4BCFFFF03E811EA84BD
+:10852000BAFFFF03A0252AD4005068E09CFF809C7E
+:10853000E811EA84A8FFFF037C2143D804002185C9
+:10854000080041850C0081851000C185140001865A
+:10855000180041861C0081862000C1862400018706
+:10856000280041872C008187004800443000219C6E
+:10857000F4FF219C004801D4045001D4086001D4C8
+:10858000004000192C0808A9000047A90000088530
+:10859000000086A9004004D400408018280884A860
+:1085A00000008484FCFDFF07002005D4FFFF609CD1
+:1085B00000180BE404000010000000150700000084
+:1085C00000580AD400408018240884A8000064845D
+:1085D000FFFF639C00180AD400408018200884A87C
+:1085E00000006484FFFF639C00180CD40000218508
+:1085F0000400418508008185004800440C00219C4E
+:10860000D4FF219C004801D4045001D4086001D457
+:108610000C7001D4108001D4149001D418A001D49E
+:10862000000043A90000C09DE8116384020063A418
+:10863000007023E44600000C54104A9E00006A9427
+:108640000F00639C02000A95840083BA000092A880
+:108650000F00089D24126A84840008B9007023E486
+:108660001600000C0000F4A834122A8500006AA845
+:108670002800819C2400A19C2000C19C0000009D3A
+:10868000004009E4320000101C00E19CB9FFFF0724
+:108690000000001530126A84000094A82800A1840C
+:1086A0002400C1842000E184CDF8FF071C0001856F
+:1086B000280000000000609DB010AA842C126A847B
+:1086C00028128A85021805E2B801CA8400006CA845
+:1086D00008F9FF070000B0A81400CC9C025810E273
+:1086E00000700BE41500001000588CE130324AD4C1
+:1086F00000006CA80100C09C000092A834324AD44B
+:108700001300C09C0030B0E50500000C0000B0A8CC
+:108710000100609CD5FFFF03241A4AD464F7FF07C9
+:10872000B801CA84B8016A840100809C005063E0EB
+:10873000F8FFFF039C2143D8B8016A8498FFC09CCE
+:10874000005063E0F3FFFF037C3143D80000609DDD
+:108750000000218504004185080081850C00C18549
+:1087600010000186140041861800818600480044EC
+:108770002C00219CE8FF219C004801D4045001D426
+:10878000E81103851400819C1000A19C0C00C19C81
+:108790000800E19C000043A9800008A50000209D7E
+:1087A000004828E41100000C0000609D71FFFF07E5
+:1087B00000000015140081840C006184022063E035
+:1087C0001000A1840100639C08008184022884E0D9
+:1087D0003812CA840100849C062363E00018C6E0B6
+:1087E00038324AD4000066A9000021850400418582
+:1087F000004800441800219CF8FF219C004801D447
+:10880000045001D40000C4A8000043A9441283848A
+:10881000002025E4230000100000609D40128384A6
+:10882000002026E41F0000100300809C7A01A38C26
+:10883000002804E406000010000000157401838C79
+:10884000005824E41400000C000000157BFEFF0714
+:10885000000000150100609C7A01AA8C000063A949
+:10886000A8190AD4FF0085A40300609C001804E442
+:108870000C0000100000609C74018A8C001824E435
+:10888000030000100000A09C0100A09C0500000057
+:1088900074290AD80100609CF3FFFF03AC190AD4C5
+:1088A0000000218504004185004800440800219C07
+:1088B000140083840000A3A80000609C001804E456
+:1088C0000C0000101F00C09C000065940030A3E461
+:1088D00012000010FFFF609D020065940030A3E4C9
+:1088E0000E000010000000150C0000000000609D4C
+:1088F000000085940F00609C0018A4E4070000109D
+:10890000FFFF609D020085941F00609C0018A4E496
+:10891000F6FFFF0F0000001500480044000000159E
+:10892000ECFF219C004801D4045001D4086001D41C
+:108930000C7001D4108001D4004080180C0884A869
+:108940000000A09C0040E01818A0E7A8002804D46C
+:10895000004000191CA008A90000C784000043A91A
+:108960000000809D0000A784FFFFC6A5000088844A
+:10897000FA0084A4006004E404000010500005BA6A
+:108980000100809C982323D400008884620084A482
+:10899000006004E40500000C000000150000609C6D
+:1089A00047000000981B2AD4BC01AA84B8018A841D
+:1089B000F0714AD8F4294AD4F8214AD4BDFFFF0700
+:1089C000F1814AD800606BE5320000100000A09CE5
+:1089D0000100A09C00006AA8982B2AD4F5FAFF0792
+:1089E0001C00809C0100609CA8190AD4AC190AD410
+:1089F00000406018000063A8FB03809C0040E01862
+:108A00001005E7A8002003D40F27C09C000067844E
+:108A10000000809C002023E40A00000C0000A09CC1
+:108A20000100849C0030A4E50600000C0000001545
+:108A300000006784002823E4FBFFFF130100849CEF
+:108A400000408018000084A8FF03A09C00006AA8D2
+:108A5000002804D4A2FBFF07000000150100609C61
+:108A600000182BE4160000100000001500406018EC
+:108A7000240863A800408018200884A80000A3846C
+:108A800000006484FFFF059E0D000000FFFFC39DF2
+:108A9000B8018A8400006AA8982B2AD4005084E088
+:108AA000A5FFA09CD7FEFF077C2944D832FFFF0713
+:108AB00000006AA8CFFFFF030000001500408018E7
+:108AC0001CA084A80000A09C00006AA8002804D470
+:108AD00000008EA849FFFF070000B0A80000218514
+:108AE00004004185080081850C00C18510000186C5
+:108AF000004800441400219CF8FF219C004801D448
+:108B0000045001D4000043850100809CF5E0FF077C
+:108B10000808609C0000609C981B2AD481FFFF0716
+:108B200000006AA884FDFF0700006AA800002185F4
+:108B300004004185004800440800219CECFF219C72
+:108B4000004801D4045001D4086001D40C7001D451
+:108B5000108001D400004385000003AA0000809D1E
+:108B60005EFCFF0700006AA800408018000384A88C
+:108B700000006AA80000A484FF00C5A5F2FBFF075F
+:108B800000008EA867016A8C006003E45A00000CA4
+:108B900040106A9C66016A8C0000809D006023E49E
+:108BA0004F00000CFFFF8E9CAE00609C0018A4E4F8
+:108BB0005B00000C0000609D67016A8C006003E4AC
+:108BC00027000010000000159C016A84006003E487
+:108BD000050000100300609C0100A09C7A190AD8CF
+:108BE0007C290AD87A018A8C0300609C001824E44E
+:108BF000030000100000609C74190AD874016A8C8C
+:108C0000006023E42600000C00000015A0018A8407
+:108C100044126A840018A4E40B0000107900809CC0
+:108C20000100609C981B2AD400006AA861FAFF0723
+:108C3000000000150100A09CA8290AD438000000FB
+:108C40000000609D81FBFF0700006AA80000609C97
+:108C50000100A09C67190AD8A4290AD49D09000420
+:108C600000006AA800408018080884A80100A09CA1
+:108C7000000070A8002804D4A0FFFF070000001522
+:108C8000980B8A840000609C001804E4ECFFFF0F3E
+:108C900000000015220000000100609DE5FCFF07B8
+:108CA00000006AA8FFFF609C00182BE40A00000C7B
+:108CB00000006AA8E8116A84006003E4D4FFFF138F
+:108CC000000000157CFDFF0700006AA8D1FFFF032C
+:108CD000A0018A84D6FFFF037D00809C04006018F9
+:108CE000646E63A825E6FF070000809C0C0000006E
+:108CF0000000609D0000AA9444108A9C0200CA945F
+:108D00003810EA8486F5FF073C100A850000609C55
+:108D100000180BE4A0FFFF130000001500002185E0
+:108D200004004185080081850C00C1851000018682
+:108D3000004800441400219CF0FF219C004801D40D
+:108D4000045001D4086001D40C7001D4FF0083A545
+:108D50000000C6A910006018000063A80018A7E46E
+:108D600005000010000047A900806018000063A8FB
+:108D7000041847E10000C09C00302AE40300001002
+:108D80000000E09C0100E09C7712609C001848E421
+:108D9000030000100000A09C0100A09C042867E0D4
+:108DA000003003E45900000C1000609D005004D412
+:108DB0007812A09C00006AA8F7EDFF070000809CD5
+:108DC0000000809C0000E09C67210AD80400601825
+:108DD000588363A866210AD80000809C96610AD84F
+:108DE000003803D4B0390AD40000609C943B2AD4E4
+:108DF00000180ADC040060185C8363A8983B2AD43E
+:108E0000002003D438384AD404008018548384A83E
+:108E10000000609C003804D402180ADC0000809C2A
+:108E200004006018608363A83C384AD4002003D44F
+:108E300040384AD404008018648384A80100609CF0
+:108E4000003804D49C190AD4FFFF809C44384AD4CB
+:108E5000B8210AD4B4210AD4BC210AD4C0210AD42E
+:108E600048384AD4E8394AD4EC394AD49C3D2AD40B
+:108E7000A03D2AD4BDE7FF073C3A4AD495EFFF074F
+:108E80000000001504006018508363A80100E09CF6
+:108E9000A8752AD4003803D434384AD40000609C22
+:108EA0000000A09C50184AD41F00C09CB00F6A9CC0
+:108EB0009C118A9C0000E09C0100A59CE03FE4DB43
+:108EC000FFFFE09C003EE3D7803EE3D70000E09C3C
+:108ED000003804D80000E09C0100849C803FE3D768
+:108EE000EC3CE3D76C3DE3D7003803D40030A5E574
+:108EF000F1FFFF130400639C0100609C343A4AD4E4
+:108F000030184AD40000609D00002185040041858E
+:108F1000080081850C00C185004800441000219C98
+:108F2000F8FF219C004801D4045001D4B801838487
+:108F30000000C3A80040401924164AA9FFFF609C06
+:108F4000001824E42700000C020004B90200E69493
+:108F50000030A8E000406018200863A87B01868CE0
+:108F60000F00E79C8400E7B80000C3840F0084B8BA
+:108F70000800E7B8100B65840430E7E0900AA58488
+:108F8000080063B80100C09C042863E000300AD4E4
+:108F90000000A3A8C7F8FF070000C4A80000609C59
+:108FA00000408018281684A800180AD40040A01891
+:108FB0002C16A5A80000848400406018302063A807
+:108FC0000000C09C002003D40000A5840400639C22
+:108FD00000408018041684A8002803D4003004D46C
+:108FE0000000218504004185004800440800219CC0
+:108FF000F8FF219C004801D4045001D4B40103853A
+:10900000000043A9FFFF809C002028E41400000C0E
+:109010000200A8B80018E5E0001828E1300E8784A7
+:10902000B00D6784B00EA784300FE7845C184AD473
+:10903000E811CA840000609C60204AD464284AD4A5
+:10904000001806E40800001068384AD49C11698CA6
+:1090500094404AD40400000090184AD4D0F9FF0785
+:109060000000001565016A8C64018A8C080063B8F1
+:10907000042063E0D0194AD4000021850400418512
+:10908000004800440800219CF8FF219C004801D4BE
+:10909000045001D41EFAFF07000043A90100609CA0
+:1090A00030184AD4FFFF609CBC190AD4C0190AD4F6
+:1090B000B4190AD400002185040041850048004409
+:1090C0000800219CF8FF219C004801D4045001D4E1
+:1090D000000043A9F3F0FF07980163840000809C1F
+:1090E00000200BE40400001000006AA8E7FFFF075F
+:1090F000000000150000218504004185004800445F
+:109100000800219CFCFF219C004801D40C02C38470
+:109110000000E3A80000809C0600A68C002005E467
+:1091200005000010C401639C900BA78C0400000094
+:10913000B8018784900BA78CBC01878423EDFF07BF
+:109140000000001500002185004800440400219C17
+:10915000E8FF219C004801D4045001D4086001D4E8
+:109160000C7001D4108001D4149001D4020084B892
+:10917000000083A9000006AA001864E00400C5B935
+:109180001C0CE3840400C6B80000AEA89C0B438509
+:109190000B0047BA00006C940B004AB9F8F7FF07C0
+:1091A00002008C947A016C8C0300809C002023E4E4
+:1091B0002F00001000584AE10000C4A80000A09C45
+:1091C0000F00E09C00800019000008A90000809CAE
+:1091D00000406AE080802019808029A90100849CD9
+:1091E000004803D40030A4E5FBFFFF130400639C98
+:1091F0000100A59C0038A5E5F3FFFF1340004A9D40
+:1092000002008C940300D0B80000AEA8410084B8DE
+:10921000DBF7FF0700006C940058F2E00000A09C10
+:109220000300C09C0700009D00802019000029A9B0
+:109230000000809C004867E080802019808029A978
+:109240000100849C004803D40030A4E5FBFFFF1319
+:109250000400639C0100A59C0040A5E5F3FFFF13FB
+:109260004000E79C2D000000000000150000C4A88D
+:109270000000A09C1F00E09C00800019000008A9CD
+:109280000000809C00406AE080802019808029A92D
+:109290000100849C004803D40030A4E5FBFFFF13C9
+:1092A0000400639C0200A59C0038A5E5F3FFFF13B2
+:1092B00080004A9D02008C940300D0B80000AEA844
+:1092C000410084B8AEF7FF0700006C940058F2E04C
+:1092D0000000A09C0300C09C0F00009D008020198E
+:1092E000000029A90000809C004867E080802019C8
+:1092F000808029A90100849C004803D40030A4E5A3
+:10930000FBFFFF130400639C0200A59C0040A5E541
+:10931000F3FFFF138000E79C0000218504004185D6
+:10932000080081850C00C18510000186140041866B
+:10933000004800441800219CC8FF219C004801D42B
+:10934000045001D4086001D40C7001D4108001D401
+:10935000149001D418A001D41CB001D420C001D4B1
+:1093600024D001D4000043A93400819C3000A19C8A
+:109370002C00C19C7FFCFF072800E19C3000C184C9
+:109380000000609D28006184023063E00100439F7B
+:109390007A018A8C0300609C001804E4030000102A
+:1093A0003400A1840100609D0200609C001824E448
+:1093B000030000100000209D0100209DF8118A8408
+:1093C00000006AA80F0009BB0200E4B80700CBBA8E
+:1093D000005007E1100B4885900A88855DFFFF0764
+:1093E00008004AB93000C1840460CAE10000809CD2
+:1093F000080066B83400A184041878E004B063E083
+:109400000020BAE51A000010042843E22C008184F1
+:109410000100859D0100649C00188CE51100000C82
+:109420000101809E0800C6B800006EA8000092A846
+:109430000430D8E00000AEA804B0C6E00000F4A8F4
+:109440009CF7FF070460C6E02C00818401008C9D1E
+:109450000100649C00188CE5F3FFFF133000C18409
+:109460000100C69CFFFF5A9F303001D400307AE0E3
+:10947000001886E51D00000C000006AA2C0081845F
+:109480000000809D0100649C00188CE51200000C17
+:10949000080070B80101809E041878E004B043E130
+:1094A0000460CAE000006EA8000092A80000AEA808
+:1094B0000000F4A87FF7FF0701008C9D2C00818439
+:1094C0000100649C00188CE5F7FFFF130460CAE0FC
+:1094D0003000C1840100109E00307AE0001890E551
+:1094E000E8FFFF13000000150000609D00002185CB
+:1094F00004004185080081850C00C18510000186AB
+:1095000014004186180081861C00C1862000018756
+:1095100024004187004800443800219CB8FF219C6A
+:10952000004801D4045001D4086001D41400419DC6
+:10953000000083A910008A9C1400AA9C1000C19C02
+:109540000CFCFF070C00E19C2800A18400006AA825
+:1095500000402019200829A90C0081840000C09C2B
+:109560000000009D022884E00100E49C7A01AC8C9C
+:109570000300809C002005E40300001024004185C6
+:109580000100C09C0200809C002025E40300001024
+:109590002C3001D40100009DF411AC8400008984BA
+:1095A0000200A5B8202001D40000809C442001D4F2
+:1095B000F811CC841C3801D4304001D40060E5E0BF
+:1095C0000200C6B8900AA784006006E1342801D4DE
+:1095D00000008984100BE784025084E0383801D4FD
+:1095E00000002985900AC8843C3001D4100B0885FE
+:1095F000142001D4404001D4184801D44AF7FF0791
+:1096000000000015000021850400418508008185C7
+:10961000004800444800219CFCFF219C004801D4E4
+:109620006C01C38C0100A09C002826E406000010F9
+:109630000000001541FFFF070000001504000000B6
+:1096400000000015B6FFFF0700000015000021858F
+:10965000004800440400219CE4FF219C0C4801D4F4
+:10966000105001D4146001D4187001D40600A4B8BD
+:109670000000C4A90300C09C00408018040884A80E
+:10968000000043A9003004D498710AD40040801827
+:10969000402084A80040C0186420C6A8002065E0CF
+:1096A000000083850030A5E00000609C0000A584D8
+:1096B00050008CB94C184AD450284AD40300609CFE
+:1096C00074EDFF0707008CA5FC118A9C54106A9C5E
+:1096D000082001D4041801D44C12AA9C4812CA9C38
+:1096E0005012EA9CAC0D0A9D00008EA850104A85CD
+:1096F0000300609CEEEFFF07005001D400006CA94E
+:109700000C00218510004185140081851800C18559
+:10971000004800441C00219CF0FF219C004801D41B
+:10972000045001D4086001D40C7001D4000044A995
+:10973000000083A9CBE5FF070000C5A90000809CBD
+:1097400000200AE4E900001000000015A8016C8464
+:10975000002023E40A00001000000015940B0C8583
+:10976000002028E40600001000000015980B6C840F
+:10977000002023E40500000C0000209DD9F9FF071C
+:1097800000006CA80000209D00480EE4D7000010E7
+:10979000FEFF6E9C0100409D005043E468000010F5
+:1097A000FFFF609C00406018102063A800408018F4
+:1097B000142084A8004803D4004804D483016C8C8E
+:1097C000004823E4030000100000809C0800809CF7
+:1097D000004060181C2063A8002003D40200809C75
+:1097E00000202EE44A000010000083A8940B0C8592
+:1097F00000006384100063A8001804D4B8016C84CE
+:109800000040C0182420C6A80040E0182820E7A87F
+:10981000020063B80040A0180C05A5A89C0B839C0F
+:109820001C0C639C00208CE000186CE00000848419
+:1098300000006384002006D4001807D4000085844B
+:10984000000066844B0084B80040A0180805A5A855
+:10985000002063E0001806D40000858400006784BF
+:109860004B0084B8002063E00000809C001807D4FF
+:10987000002008E4030000100100809C0300809C8D
+:1098800083016C8C0000A09C002823E403000010DE
+:1098900000000015080084A8004060182C2063A870
+:1098A000002003D404008018BC8084A800006484D5
+:1098B000002803E48D000010002828E48B0000102D
+:1098C00000000015A8016C84002803E48700001044
+:1098D0000000001500406018640063A80B00809C25
+:1098E0000040A0182C20A5A8002003D400008584E7
+:1098F00000006CA8200084A8002005D489FDFF0783
+:10990000000000157A0000004C108C840300609C5D
+:1099100000182EE408000010000000150040801818
+:109920001C2084A8940B0C8500006484B3FFFF0303
+:10993000200063A8B2FFFF03940B0C85B401AC8434
+:10994000001825E4190000100200A5B800406018B6
+:10995000102063A80000809C940B0C85002003D489
+:109960000400639C002003D4004808E403000010B6
+:109970000000609C0300609C0000A3A883018C8C05
+:109980000000609C001824E4030000100000001593
+:109990000800A5A8004060181C2063A8002803D474
+:1099A00098FFFF03B8016C8400406018082063A88A
+:1099B00000400019142008A99C0C859C1C0DC59C16
+:1099C00000208CE00030CCE0000084849C0BE59CFF
+:1099D000002003D40000C68400406018042063A85F
+:1099E0000038ECE01C0CA59C003003D40028ACE04F
+:1099F0000000E7840040C0181020C6A8004080186E
+:109A00000C0584A80000A584003806D4002808D4DA
+:109A100000006484000086844B0063B8AC01AC8411
+:109A2000001884E000406018080563A8002006D4F0
+:109A300000008384000068844B0084B8002063E049
+:109A4000001808D4004805E40E00001000000015BE
+:109A500083016C8C004823E4030000100000A09CEC
+:109A60000800A09C6A018C94004060181C2063A828
+:109A7000940B0C85002803D461FFFF033C224CD4D7
+:109A8000940B0C85004828E4060000100000001527
+:109A900048106C84004823E40C00000C0000001502
+:109AA00083016C8C004823E4030000100200809CBA
+:109AB0000A00809C004060181C2063A8002003D48A
+:109AC00050FFFF03B8016C8483016C8C004823E4D1
+:109AD0000400001000000015F7FFFF030900809C40
+:109AE000F5FFFF0300008AA84C108C84004060182A
+:109AF000182063A8002003D49801AC84004080188B
+:109B0000002084A800006CA89601CC8C0600A5B8A3
+:109B1000003004D400408018402084A86C01CC8C14
+:109B20000020A5E000408018202084A8003004D444
+:109B3000FFFF80A8002005D42EFDFF0700000015C0
+:109B400050106C84DFE6FF0754108C9CCEE4FF07B6
+:109B50000000001500002185040041850800818572
+:109B60000C00C185004800441000219CFCFF219C92
+:109B7000004801D4341083840000C3A80600A09CD0
+:109B80000100609C001804E4060000100000609DC5
+:109B90009601868C38E7FF079B01668CFFFF609D6E
+:109BA00000002185004800440400219CFCFF219C0A
+:109BB000004801D4341083840000C3A80100609CD5
+:109BC000001824E40800000C0800A09C0200609C1F
+:109BD0000018A4E40400000C0900A09C060000008A
+:109BE0000000609D9601868C23E7FF079B01668C31
+:109BF000FFFF609D00002185004800440400219C77
+:109C0000F8FF219C004801D4045001D4900BA38C90
+:109C10000000E3A85410239D0300609C002883E407
+:109C2000030000100000409D4A00409DE811678439
+:109C30000000809C002003E40700001000000015D5
+:109C4000EC116784002023E404000010FF0085A4C9
+:109C50004D00409DFF0085A40000A09C002085E5EC
+:109C60001100000C000000151C0C6784002823E480
+:109C70000C00000C0000C4A80000009D1C0C879C78
+:109C80000100A59C003085E50700000C0400849CC1
+:109C900000006484004023E4FBFFFF130100A59C47
+:109CA0004E00409D50006984540089840200C7948E
+:109CB00037F1FF070000A7940100609C00182BE417
+:109CC0000400001000006AA94700409D00006AA936
+:109CD0000000218504004185004800440800219CC3
+:109CE000FCFF219C004801D43410A3840100E09CB7
+:109CF000003825E42400000C0000C3A80200609C8A
+:109D0000001825E41D00000CFEFF649C0038A3E44D
+:109D10001700000C0000009DAC0D6684004023E499
+:109D2000030000100000209D000027A90300609C94
+:109D3000001804E4030000100000A09C0000A7A885
+:109D4000032869E0004003E40400000C7B00A09CB1
+:109D5000100000000000609D9601868CC6E6FF079B
+:109D60009B01668C0B000000FFFF609D9601868CB6
+:109D7000FBFFFF030F00A09C9601868CF8FFFF03FA
+:109D80000C00A09C9601838CF5FFFF030B00A09CA8
+:109D900000002185004800440400219CFCFF219C18
+:109DA000004801D4000003A90D00A09C0000E09C25
+:109DB0000500609C001804E4030000100000C09C33
+:109DC0000100E09C0200609C001804E40400001004
+:109DD000033087E00100C09C033087E00000609CF6
+:109DE000001804E4060000100000609D9601888CB5
+:109DF000A1E6FF079B01688CFFFF609D00002185A5
+:109E0000004800440400219CFCFF219C004801D430
+:109E10000000C3A80E00A09CFEFF849C0100609C73
+:109E20000018A4E4060000100000609D9601868CD6
+:109E300091E6FF079B01668CFFFF609D0000218576
+:109E4000004800440400219CFCFF219C004801D4F0
+:109E50000000C4A80000E3A8FFFF849C0200609CEF
+:109E60000018A4E40B00000C0F00A09C0100609CF3
+:109E7000001826E40B0000100000609D4810878445
+:109E80000000609C001824E406000010000000158B
+:109E90009601878C78E6FF079B01678CFFFF609D2A
+:109EA00000002185004800440400219CE8FF219C1B
+:109EB000004801D4045001D4086001D40C7001D4CE
+:109EC000108001D4149001D45410C39C000043A905
+:109ED000380086840000A09C0300609CE8214AD4DE
+:109EE0000000009E4400C68400008AA80400409E32
+:109EF000EC314AD40EEFFF070000809D9B016A8C75
+:109F00000000809C41EBFF070000A09CB0810AD4B8
+:109F1000D6F7FF0700006AA8B0016A84006003E476
+:109F2000FCFFFF130000CBA9C4F7FF0700006AA8DD
+:109F3000FCFF6B9DB8EFFF074C584AD44FEBFF076F
+:109F4000000000150100609C00182EE41C00000CAD
+:109F50000400A09C2000409E3400009EFFFFC09D96
+:109F600000006AA80000809CECFDFF070000A09C98
+:109F700000008A940005609C001844E4060000106C
+:109F8000D002609C02008A94001844E42D00000C6A
+:109F900000000015E3E6FF0750106A840000609C93
+:109FA00000180BE427000010000000152000409E60
+:109FB0001C00009E23000000FFFFC09D0000CA940B
+:109FC00000406018082063A800408018042084A87E
+:109FD0000200EA940400009D003003D440304AD4CB
+:109FE000003804D4000066A8902B2AD8000087A867
+:109FF0000040A0180C20A5A844384AD4004005D43D
+:10A0000039F0FF070000001502008A9400006A94EE
+:10A01000410084B834F0FF07D4594AD490096A9CAF
+:10A02000100A8A9C900AAA9C100BCA9CD8594AD440
+:10A0300092EBFF072000E09CCBFFFF0300006AA823
+:10A0400098018A84000072A80000B0A80000C09C9B
+:10A0500075E3FF070000E09C00006EA90000218569
+:10A0600004004185080081850C00C185100001862F
+:10A0700014004186004800441800219CF4FF219CF4
+:10A08000004801D4045001D4086001D49801C3846D
+:10A090000040E0186820E7A8000043A90600C6B801
+:10A0A000000083A80000A09C0038C6E00300609C6C
+:10A0B0000000E68454108A9D7CEFFF07903B2AD86D
+:10A0C000D0FEFF0700006AA80000ABA82000609C3B
+:10A0D0000000C09C0000009D00400BE41D00000C2F
+:10A0E0000000E09CE8116A845F0063A4004003E480
+:10A0F0001400000CB0108A9C50006C8438184AD4AC
+:10A1000054008C8500006AA801F6FF073C604AD421
+:10A1100000006AA80000809C80FDFF070000A09C52
+:10A1200098018A840F00609C0000A09C0000C09CE5
+:10A130003DE3FF070000E09C090000000000609D77
+:10A14000E5ECFF07EC116A84EDFFFF0350006C841F
+:10A1500035E3FF0798018A84FFFF609D0000218599
+:10A160000400418508008185004800440C00219CC2
+:10A17000F8FF219C004801D4045001D4B401A38409
+:10A18000000043A9FFFF809C002005E4140000109C
+:10A190000018C5E07C11A68C0000809C002005E41E
+:10A1A0000F000010000000150FF5FF07000000155C
+:10A1B000B401CA84FFFF8BA40000E09C7C11C69C04
+:10A1C00000006AA80030CAE00000A68C1000A5B804
+:10A1D000003806D8F7F4FF07042884E00000218542
+:10A1E00004004185004800440800219CECFF219CAC
+:10A1F000004801D4045001D4086001D40C7001D48B
+:10A200000000809C0100809D101801D4982323D465
+:10A21000A82103D4AC2103D4A46523D4AAFBFF074F
+:10A220000000409D100081840300609C40EEFF0709
+:10A230000000A09C1000C1840000A09C6C108684CB
+:10A2400072EAFF079B01668C10008184940B648482
+:10A25000005023E42C000010000000154810648416
+:10A26000005023E42800001000000015A8016484B9
+:10A27000005023E42400001000000015AC016484A9
+:10A28000005023E4210000100900809C0000C09DC4
+:10A290000800A09C00408018640084A81000619C05
+:10A2A000002804D426FAFF07000000151000A1843E
+:10A2B000A8016584005023E40600001000008BA96B
+:10A2C000AC018584005024E43600000C000065A831
+:10A2D000FEFF8C9C0100609C001844E42F00000CE1
+:10A2E00000000015A8016584007023E40700001039
+:10A2F0000900809CAC016584007023E4E6FFFF0F39
+:10A300000800A09C0900809C00406018640063A8BD
+:10A31000002003D4D4F4FF0700000015C1F4FF07A8
+:10A3200000000015C5F6FF0710006184BAEEFF07B4
+:10A330000000001551EAFF070000001510006184BD
+:10A340000100809CF5FCFF070000ACA84EF5FF075C
+:10A350001000618487FFFF07100061840000809C6B
+:10A3600000200CE409000010100061841000A1849A
+:10A37000980B6584002023E404000010000065A809
+:10A38000200000000500409D0FF5FF072000409DC4
+:10A390001C0000001000A184DBFFFF03486045D4CF
+:10A3A0004FF5FF07000000150100E09C00382BE48A
+:10A3B000C8FFFF131000A1841000C1847C00809CA2
+:10A3C0006701A68C000066A8983B26D4005025E4BF
+:10A3D00006000010A83906D476F4FF077B00809CA5
+:10A3E000BCFFFF031000A18472F4FF0700000015FA
+:10A3F00092F7FF0710006184B6FFFF031000A184ED
+:10A4000079F4FF07000065A81000C1840000ABA824
+:10A4100000006AA8980186840000E09C82E2FF07A1
+:10A420000000C09C00006CA900002185040041854B
+:10A43000080081850C00C185004800441400219C5F
+:10A44000F4FF219C004801D4045001D4086001D4D9
+:10A45000000043A9000084A90500A09C002824E472
+:10A460000A00000C0000609D0200C09C003024E443
+:10A4700023000010000000154810A384003025E4DC
+:10A48000150000100300C09C940B6A84005823E45C
+:10A490000A00000C0100A09C0700609C00008CA832
+:10A4A00034184AD400006AA84600000400000015D1
+:10A4B0001300000000000015BC018A84C4016A9CDE
+:10A4C000942B2AD441E8FF07900BAA8CF4FFFF03DA
+:10A4D0000700609C003025E4090000100000001512
+:10A4E000940BA384005825E4030000100000A09CF6
+:10A4F000482843D4EDFFFF0334304AD400002185BF
+:10A500000400418508008185004800440C00219C1E
+:10A51000F0FF219C004801D4045001D4086001D40C
+:10A520000C7001D4000044A9000083A9D7FAFF07EA
+:10A530000000C09D00006CA80300C09C00302AE40D
+:10A540001600000C00008AA800006CA800008AA871
+:10A550000200A09C00282AE40D00000C0100E09CF1
+:10A5600000382AE410000010000000150000A09C34
+:10A5700034384CD448284CD4942B2CD411000004EB
+:10A5800000000015080000000000CBA934304CD4B6
+:10A59000FAFFFF030000A09C0700A09CF8FFFF0348
+:10A5A00034284CD400006EA90000218504004185A8
+:10A5B000080081850C00C185004800441000219CE2
+:10A5C000F4FF219C004801D4045001D4086001D458
+:10A5D0003410A384000043A9000084A9004060183F
+:10A5E000640063A80000609D002803D40A00609CFA
+:10A5F000001845E47B000010020065B804008018D4
+:10A600007C6E84A8002063E0000083840020004466
+:10A6100000000015FFFF809D55FDFF0700006AA8A0
+:10A6200000602BE46F00000C00006CA920FEFF0707
+:10A6300000006AA800600BE46A0000100200C09CE1
+:10A640006800000034304AD4FFFF809D58FDFF07AA
+:10A6500000006AA800602BE46200000C00006CA9F6
+:10A6600087FEFF0700006AA800600BE45D00001091
+:10A670000300609C5B00000034184AD400006AA804
+:10A6800098FDFF0700008CA8FFFF609C00182BE4DA
+:10A690001F00000C000000150300609C00182CE453
+:10A6A000060000100000609CAC0D8A84001824E4B1
+:10A6B0001100000C0700809CCDFEFF0700006AA877
+:10A6C0000300C09C00302CE40400001034304AD455
+:10A6D0000700609C34184AD4FEFF8B9C0100609CEC
+:10A6E000001844E43F0000100600809C3D0000007C
+:10A6F00034204AD400006AA834204AD4B1FFFF07AE
+:10A7000000008CA837000000000000153500000094
+:10A71000000063A900006AA8A1FDFF0700008CA843
+:10A72000FFFF609C00182BE4F9FFFF0F00000015ED
+:10A7300000006AA843FFFF0700008CA82900000062
+:10A740000000001500006AA8B0FDFF0700008CA8FB
+:10A75000FFFF609C00182BE42200000C000063A99E
+:10A76000940B8A840000609C001824E40E00000C06
+:10A770000100C09C9EFEFF0700006AA80040601810
+:10A780001C2063A8000083840300609C030084A451
+:10A79000001824E4130000100A00609C110000005F
+:10A7A00034184AD400006AA857FAFF0794332AD411
+:10A7B000F1FFFF030000001500006AA8A3FDFF07DA
+:10A7C00000008CA8FFFF609C00182BE40500000C23
+:10A7D000000063A900006AA84EFFFF0700008CA8D4
+:10A7E000000021850400418508008185004800445F
+:10A7F0000C00219CF4FF219C004801D4045001D49A
+:10A80000086001D4000044A9FF0063A4004080193F
+:10A8100064008CA9000083A80100609C00180CD47F
+:10A820008EFBFF0700006AA80200609C00008BA856
+:10A8300000180CD400006AA862FFFF07FC114A9DB3
+:10A84000CFE9FF0700006AA80000218504004185C8
+:10A8500008008185004800440C00219CFCFF219CDD
+:10A86000004801D400408018300384A8000023A9C8
+:10A870000000E4840040A0181003A5A80040C01800
+:10A880000403C6A80000048500006584041809D8E4
+:10A8900000406018480363A800008584052009D89B
+:10A8A00000006384081809D4000086840040601802
+:10A8B000280363A8003809DC0000E38400008684D4
+:10A8C0000000609C0E2009D80000A684024009DC2C
+:10A8D000FF0085A40C3809DC001804E434000010E3
+:10A8E000542909D80000C09C3F00609D0400001955
+:10A8F000B88908A90040E0182003E7A8004066E0F6
+:10A900000000A7840100C69C0000838C004884E0FE
+:10A910000058A6E5FAFFFF13542804D80040601839
+:10A92000040363A800008384552109D80000609CBB
+:10A93000FF0084A4001804E4130000100000C09C71
+:10A940003F00609D04000019B88908A90040E01884
+:10A950002003E7A8004066E00000A7840100C69C31
+:10A960000000838C004884E00058A6E5FAFFFF133E
+:10A97000942804D81401699C0000C09C1A000000AF
+:10A980003F00809C3F00809C9400699C1000A09C2C
+:10A990000100C69C002803D80020A6E5FDFFFF1398
+:10A9A0000100639CF5FFFF031401699C0000C09C3B
+:10A9B0003F00E09C0400A018388AA5A85400899C98
+:10A9C000002866E00000638C0100C69C001804D8D3
+:10A9D0000038A6E5FBFFFF130100849CD0FFFF03B6
+:10A9E0000000001540FFA38C0100C69CC02FE3DBD4
+:10A9F00080FFA38C002803D80020A6E5FAFFFF13F0
+:10AA00000100639C00002185004800440400219C53
+:10AA10000040A0180403A5A800408018180384A8CB
+:10AA20000000658400406018140363A80000C3841C
+:10AA30000000E484000065840000C4840000648495
+:10AA40000000C58400006584004800440000001533
+:10AA50000040C0180403C6A80000609D0000668482
+:10AA6000005823E40A00000C0000809C0040A0185D
+:10AA70002003A5A80000658401006B9D000066848A
+:10AA8000002023E4FCFFFF130000001500480044F1
+:10AA90000000001500408018280384A80040001919
+:10AAA0000C0308A90000C4840000E3A80000A884E7
+:10AAB0006C2903D800406018400363A8FE00A59CE1
+:10AAC00000008384FF00A5A46A3107DC0100609CBC
+:10AAD000001845E4080000106E2107DC00406018F3
+:10AAE000040363A800008384702107D800006884F1
+:10AAF000711907D86C01878C0300609C001824E44E
+:10AB0000080000100000001500406018040363A84E
+:10AB100000008384722107D800006884731907D865
+:10AB20000048004400000015F8FF219C004801D4B3
+:10AB3000045001D49C0183840000C3A80000609CE1
+:10AB4000001824E40A0000100000409D02008694D2
+:10AB5000F00A609C0018A4E4050000100000001535
+:10AB6000004060180C0363A8000043855801868CE0
+:10AB70000040E0180403E7A80100609C001824E4EA
+:10AB80000600001000000015004060181C0363A8B8
+:10AB900000008384592106D800406018140363A87C
+:10ABA000000083845B2106D80000609C0000A7841D
+:10ABB000001805E40400000C0000609C0A0000007E
+:10ABC0005A1906D8000067845A1906D80040601840
+:10ABD000180363A800008784000083849DFFFF079B
+:10ABE0000000001500006AA90000218504004185CD
+:10ABF000004800440800219CFCFF219C004801D42F
+:10AC000000402019E00329A90000A3A80100009D2D
+:10AC100000006984004023E41000000C00000015CF
+:10AC20000040E0182003E7A80040C0181804C6A898
+:10AC30000000878400006684430063B8002883E432
+:10AC40000600000C0000001500006984004023E4A9
+:10AC5000F8FFFF13000000150000218500480044A4
+:10AC60000400219CFCFF219C004801D4000023A982
+:10AC700000400019200308A90000609C0040E01873
+:10AC80000403E7A8581909D80040A0180803A5A88C
+:10AC900000006884101809D400006784141809D4CF
+:10ACA00010008984000065848700C4B88400A4B9BA
+:10ACB000181809D40F0064A5000065840100C6A41B
+:10ACC0000000809C281809D4000065842C1809D441
+:10ACD00000406018300363A800006384301809D472
+:10ACE0000000609C9C1909D400006784000008855E
+:10ACF00000406018140363A80000E7840000A584E6
+:10AD000000006384344009D41C3809D4202809D4B5
+:10AD1000002006E40A000010241809D40500609CF5
+:10AD200000182BE40A00001085FF609C641909D804
+:10AD30000800609C06000000651909D81300698CA2
+:10AD4000646909D8FCFFFF030F0063A42A0069941B
+:10AD5000000089940C0063B8FF0F84A42E00C994EE
+:10AD6000042063E03000E9840C00C6B83600899402
+:10AD70001200E7B80200A9940A0084B8001809DCA0
+:10AD8000FF0FA5A4080009850428C6E00C006994FB
+:10AD9000003808E1002063E0023009DC084009D4F3
+:10ADA0000C1809DC00002185004800440400219CA7
+:10ADB0000000A3A80040E0180403E7A800406018C2
+:10ADC0000C0363A800400019380308A9000063843D
+:10ADD0000040C0182003C6A8381805D400006784B6
+:10ADE0003C1805D4000083A80000609C001804E40F
+:10ADF000080000100000001500006684401805D40B
+:10AE0000000066840000C684441805D4483005D488
+:10AE1000000068844C1805D4000067840000088591
+:10AE2000504005D40048004400000015FCFF219C60
+:10AE3000004801D4000003A900406018040363A87F
+:10AE400000008384542108D80000609CFF0084A483
+:10AE5000001804E411000010000000150000E09C40
+:10AE60003F00A09D04006019B8896BA9004020191B
+:10AE7000200329A90058A7E00000C9840100E79C2D
+:10AE80000000658C004083E0543004D80068A7E5DA
+:10AE9000F9FFFF13D43004D800406018040363A8FE
+:10AEA00000008384552108D80000609CFF0084A422
+:10AEB000001804E411000010000000150000E09CE0
+:10AEC0003F00A09D04006019B8896BA900402019BB
+:10AED000200329A90058A7E00000C9840100E79CCD
+:10AEE0000000658C004083E0943004D80068A7E53A
+:10AEF000F9FFFF13143104D800406018040363A85D
+:10AF000000008384562108D80000609CFF0084A4C0
+:10AF1000001804E40F0000100000E09C3F00609D5A
+:10AF200004002019B88929A90040C0182003C6A828
+:10AF3000004867E00000A6840100E79C0000838CC5
+:10AF4000004084E00058A7E5FAFFFF13D42804D896
+:10AF500000406018040363A800008384572108D8C8
+:10AF60000000609CFF0084A4001804E40F0000109F
+:10AF70000000E09C3F00609D04002019B88929A9C9
+:10AF80000040C0182003C6A8004867E00000A6845F
+:10AF90000100E79C0000838C004084E00058A7E596
+:10AFA000FAFFFF13142904D800002185004800444B
+:10AFB0000400219C0040A0180803A5A80000858477
+:10AFC0000100849C582103D800480044000000156B
+:10AFD000FCFF219C004801D4000083A80000A09C35
+:10AFE00014006384002803E4220000100300C09CC6
+:10AFF0008101648C002803E4070000100100209DFB
+:10B000007B01648C002803E4030000100200209DF3
+:10B010000300209D0000C09C004886E51F00000C36
+:10B020009001A49C00400019400308A90040E018CA
+:10B030000403E7A8000088840100C69C0000678420
+:10B0400000006884001805DCFA27E5DF0200A59CF3
+:10B0500000006784004886E5F7FFFF130000001535
+:10B060000E00000000000015EBFFFF030200209D12
+:10B070007A01648C003003E4E7FFFF0F0100209D9C
+:10B080008101648C002803E4F8FFFF130000001521
+:10B09000E1FFFF03000026A90000218500480044CD
+:10B0A0000400219C0040A0181003A5A80000E3A8FC
+:10B0B000000085840040C0180803C6A8004000199D
+:10B0C000040308A9752103D800006584761907D800
+:10B0D00000008584772107D800006584781907D897
+:10B0E00000008684792107D8000066847A1907D881
+:10B0F000000088847B2107D8000068847C1907D869
+:10B10000000088847D2107D8000068847E1907D854
+:10B11000000088847F2107D800006884801907D840
+:10B1200000008884812107D800006884821907D82C
+:10B1300000008884832107D80000809C0000688478
+:10B14000841907D8FF0063A4002003E41000001056
+:10B150000000001500008884004060180C0363A8FC
+:10B16000852107D800008384862107D81000639CBE
+:10B170000000A884872907D8000083840400639C0A
+:10B18000882107D800008384892107D8004800441B
+:10B19000000000150048004400000015004800446D
+:10B1A0000000001500408018040384A800406018C7
+:10B1B000200363A80000A4840000C3840040A018FA
+:10B1C0005803A5A80000C484004060181C0363A8AD
+:10B1D0000000C3840000648400406018500363A82A
+:10B1E0000000C3840000648400006584000064845F
+:10B1F000000065840048004400000015FCFF219C0D
+:10B20000004801D40000A3A80A00809C00406018F8
+:10B21000100363A800006384002043E42A000010A8
+:10B22000020063B804008018A86E84A8002063E0C0
+:10B230000000838400200044000000158AFEFF0700
+:10B24000000065A82000000000000015D9FEFF07DF
+:10B25000000065A81C00000000000015F4FEFF07B8
+:10B26000000065A81800000000000015CEFFFF07D1
+:10B270000000001514000000000000154EFFFF073D
+:10B28000000065A8100000000000001551FFFF0736
+:10B29000000065A80C0000000000001582FFFF07F9
+:10B2A000000065A80800000000000015BAFFFF07B5
+:10B2B000000000150400000000000015B8FFFF07A3
+:10B2C0000000001500002185004800440400219C76
+:10B2D000F0FF219C004801D4045001D4086001D43F
+:10B2E0000C7001D4000043A9000083949C01AA843F
+:10B2F00000406018300863A80F00849C002803D425
+:10B30000840084B86C01AA8C0400639C002803D4D8
+:10B310009C01CA8400406018200863A80000A09C1B
+:10B32000002003D4002826E49E0100100000001530
+:10B3300014006A84002823E49A010010000000151C
+:10B3400002006A941F00639C850063B8010063B823
+:10B3500000408018240884A8A001AA840100C09D90
+:10B36000001804D400408018280884A8A4016A8426
+:10B37000002804D4007023E4040000100000609C46
+:10B38000001804D4A4190AD45B016A8C0040801808
+:10B3900014A084A80000A09C1F0063A40000809D4E
+:10B3A000001804D47E016A8C006023E403000010BE
+:10B3B000000000150000AEA800406018040C63A84F
+:10B3C00000408018200884A8002803D4000064846A
+:10B3D0000040A0182408A5A8040063B80040801805
+:10B3E000180884A8001804D4000065840400849C14
+:10B3F000040063B82000A59C001804D40000809CC1
+:10B4000000406018000C63A8002005D4002003D47D
+:10B410003FE5FF0700000015A80D8A84006024E4C2
+:10B42000030000100000C09C0000CEA80200A09CF9
+:10B43000002824E4030000100000609C00006EA8B7
+:10B44000041866E0006003E43B010010FFFF649C09
+:10B450006C016A8C002823E437010010FFFF649C14
+:10B4600000408018000A84A80040A0185408A5A82D
+:10B47000007004D400006584010063A8001805D49E
+:10B480009C018A840000609C001824E4F4000010F1
+:10B490000000001572016A8C0100C09C70018A8C4A
+:10B4A000010063B8010084A4020063A4041884E0CE
+:10B4B0000040601810A063A8002003D48001AA8C6B
+:10B4C00000408018080C84A8002804D483016A8CEA
+:10B4D00000408018380884A8FFFF63AC001804D42B
+:10B4E0007901AA8C00406018200C63A8002803D4BE
+:10B4F0007A018A8C003024E4C40000100200609CB1
+:10B5000000406018400863A8003003D40040801851
+:10B510003C0884A8003004D4004060183C0863A8AC
+:10B520000100809C0000A384002025E40C00001092
+:10B53000000000150040A0181C08A5A80040C01875
+:10B540002408C6A800006584482063E0001805D4DC
+:10B5500000008684410084B8002006D47B018A8CD8
+:10B56000004060181C0C63A8002003D47C01AA8C46
+:10B570000040601800A063A8002803D47D01CA8C95
+:10B580000400639C003003D476018A8C7701CA8C56
+:10B59000040084B875016A8C0800C6B8F00084A461
+:10B5A0007801AA8C0F0063A4000FC6A40C00A5B8F4
+:10B5B000042063E000F0A5A4043063E0004080189C
+:10B5C00008A084A8042863E0001804D47F01AA8C92
+:10B5D000004060180CA063A8002803D43F00E09C42
+:10B5E0000000A09C54008A9C0040C0180010C6A80F
+:10B5F0000000648C0100A59C001806D40100849C06
+:10B600000038A5E5FBFFFF130400C69C0000A09CCA
+:10B610003F00E09C94008A9C0040C0180011C6A81E
+:10B620000000648C0100A59C001806D40100849CD5
+:10B630000038A5E5FBFFFF130400C69CB801EA84AF
+:10B640000300009D020067B80050A3E0100B858442
+:10B6500000406018080B63A8900AC584080084B8ED
+:10B66000003084E0002003D46C018A8C004024E484
+:10B67000390000100200609CBC01EA84FFFF209D9D
+:10B68000004827E404000010020067B80000E09CB6
+:10B69000020067B80050A3E0100B858400406018DA
+:10B6A000040B63A8900AC584080084B8003084E0C5
+:10B6B000002003D47A01AA8C004025E41200001077
+:10B6C00000000015C0018A84004824E40400001032
+:10B6D000020064B8000087A8020064B80050A3E02C
+:10B6E000100B858400406018000B63A8900AC58485
+:10B6F000080084B8003084E0002003D4AE000000CD
+:10B700009C0D8A84C0018A84004824E4040000104F
+:10B71000020064B8000087A8020064B80050A3E0EB
+:10B72000100B8584900AC584180064B81000A6B870
+:10B73000080084B8002863E0002063E0004080181F
+:10B74000000B84A8003063E0001804D49A000000C5
+:10B750009C0D8A84001824E4960000100000001557
+:10B760007A018A8C004024E4090000100000609CEB
+:10B77000BC018A84FFFF609C001824E4D8FFFF13FB
+:10B78000020064B8D5FFFF030000809C74018A8C1E
+:10B79000001824E408000010FFFF609CBC018A84AC
+:10B7A000001824E4DEFFFF13020064B8DBFFFF0390
+:10B7B0000000809C001827E4030000100000001522
+:10B7C0000000E09CBC018A84001824E403000010FF
+:10B7D00000000015000087A8020084B80200E7B846
+:10B7E000005064E00050C7E0900AA384100B63840B
+:10B7F0001000A5B8100B8684180063B8080084B840
+:10B80000CDFFFF03900AC684001824E4080000104E
+:10B810000300609C00406018400863A80000A09CE2
+:10B82000002803D43AFFFF0300000015001824E4A9
+:10B830003AFFFF130000001500406018400863A89D
+:10B84000004080183C0884A8003003D40000609CAD
+:10B85000001804D431FFFF030000001572016A8C48
+:10B860000040A01810A0A5A870018A8C010063B840
+:10B87000010084A4020063A4041884E0002005D41D
+:10B8800000406018400863A80100809C0000A09C54
+:10B89000002003D4004080183C0884A80100609C6C
+:10B8A000002804D40040A01800A0A5A8001805D4C2
+:10B8B00071016A8C7301AA8C040083B80800C5B8B2
+:10B8C000F00084A40F0063A40C00A5B8042063E07A
+:10B8D000000FC6A400F0A5A4043063E00040801867
+:10B8E00008A084A8042863E0001804D47F01AA8C6F
+:10B8F000004060180CA063A8002803D47D018A8C46
+:10B900000040601804A063A8002003D48001AA8C22
+:10B9100000406018080C63A8002803D47B018A8CBF
+:10B920001400639C002003D47901AA8C2BFFFF0331
+:10B930000400639C0100C09C003043E40F00001031
+:10B94000000000156C018A8C0300609C001824E440
+:10B950000A0000100000001500408018000A84A8AA
+:10B960000040A0185408A5A8003004D40000658445
+:10B97000C3FEFF03043063E000408018000A84A87F
+:10B980000000609C0040A0185408A5A8001804D42A
+:10B9900000006584FEFF809CB9FEFF03032063E086
+:10B9A00002006A940F00639C6AFEFF03840063B880
+:10B9B0009C0D8A8400406018300C63A80100A09C94
+:10B9C000002003D4A00D4A8500408018340C84A8C0
+:10B9D0000040601824A063A8005004D4002803D4B9
+:10B9E0000000218504004185080081850C00C18587
+:10B9F000004800441000219CFCFF219C004801D419
+:10BA00000100A09C0040801878C084A8000003A911
+:10BA1000002804D40040601880C163A86700C09C5F
+:10BA2000002803D45C0088840040A01820C1A5A889
+:10BA30000200609C003005D4001824E45600001079
+:10BA40000000609C4200609C001805D40040601813
+:10BA500020C163A80000A09C6000C8840040201999
+:10BA600004C129A90100609D002803D4003003D43B
+:10BA7000005809D4005824E4050000102C00809CD4
+:10BA8000004060181CC163A8002003D40040601867
+:10BA900014C163A81A00A09C0040C01800C2C6A828
+:10BAA000002803D41C008884D8016884FFFF849C8C
+:10BAB000001806D42000A8840000609C001809D457
+:10BAC000FFFFA59C002006D46400E884002806D46B
+:10BAD000001827E42B0000100000809C005809D4B7
+:10BAE000E801C8840040A01804C1A5A80100809CFA
+:10BAF00068026884003005D4001805D4002023E4CF
+:10BB00000A000010000000156C02C8840040601894
+:10BB100000C263A8002005D4003003D4002005D45F
+:10BB200070028884002003D4F80288840000609C9E
+:10BB3000001824E41F00000C0300C09C00406018A3
+:10BB400008C163A8FC0288840040A01820C1A5A8F1
+:10BB5000003003D4002005D4FF00609C001824E4CA
+:10BB60000600001000000015000308850040601862
+:10BB700080C163A8004003D40E0000000000609C58
+:10BB80000040601808C163A8002003D4D6FFFF035B
+:10BB9000E801C884001824E4ACFFFF136400609C33
+:10BBA0004D00C09C003005D4A9FFFF030000001524
+:10BBB000001805D4171000040000001500002185AE
+:10BBC000004800440400219CFCFF219C004801D453
+:10BBD0000040801878C084A80100A09C0100209D2E
+:10BBE000002804D40000C3A80040A01880C1A5A864
+:10BBF0000040801820C184A8004805D400400019E6
+:10BC000008C108A96800A09C0300209D002804D456
+:10BC10000040E01804C1E7A8CC0186840040601809
+:10BC200000C263A8004808D46400A6840100209DD7
+:10BC3000002007D4002807D480028684004807D457
+:10BC40007802A684E6FF849C7C022685002803D423
+:10BC5000004803D45C00A684004060180CC163A8AF
+:10BC60000000209D004803D40040601804C263A86F
+:10BC70000100209D002003D40300609C7402868490
+:10BC8000001808D4002007D40000609C001808D4D5
+:10BC9000004825E40500001000000015EC01C684F2
+:10BCA000003007D4004808D4DA0F00040000001563
+:10BCB00000002185004800440400219CF0FF219CE5
+:10BCC000004801D4045001D4086001D40C7001D4A0
+:10BCD0000100609D0040201978C029A9000043A9F7
+:10BCE000005809D40040601880C163A80000C4A9AE
+:10BCF000005803D40200609C001824E4A80000103F
+:10BD0000000085A90040601820C163A86500809CE0
+:10BD1000002003D40040801800C284A80000609C6A
+:10BD2000004004D400182CE40600000C00000015AC
+:10BD30000100609C00182CE4960000100200209D79
+:10BD4000001804D428006A840040201900C229A9E0
+:10BD50000000609D0C008A84FFFF639C0100009D31
+:10BD6000031884E0005809D40040601810C163A88B
+:10BD70006400AA84002003D4004025E408000010D9
+:10BD80000200609C0040601804C163A848008A84D7
+:10BD9000004003D4002003D40200609C00182EE46D
+:10BDA00008000010FEFFA09C3C008A845F0064B87D
+:10BDB000001864E0032863E0021884E0002009D43E
+:10BDC00038002A850040601814C163A8004803D4D5
+:10BDD00000402CE405000010000000150040601831
+:10BDE00004C163A8004003D400404CE41A000010D2
+:10BDF00000006AA80000609C00182CE45B000010A2
+:10BE00000000001578026A84001806E403000010A0
+:10BE10000000809C000088A80040601804C163A84E
+:10BE20000100A09C002003D4002824E40A00001094
+:10BE300000006AA80040601800C263A8003003D464
+:10BE400000282CE40300001000000015003803D483
+:10BE500000006AA80000A6A8C102000400008CA887
+:10BE60000100609C00180EE4080000100200609CB5
+:10BE700000182EE4370000100000609D004060189C
+:10BE800008C163A8005803D4CC016A840100A09CB7
+:10BE9000002823E4030000100000C09C0000C5A897
+:10BEA0000200609C00180CE4030000100000809C5D
+:10BEB000000085A8032086E00000609C001804E4D0
+:10BEC000080000100700609C00180CE4050000103A
+:10BED0000000A09C0040601800C263A8002803D4A2
+:10BEE0008402CA840040E01804C2E7A80100A09CB4
+:10BEF00074026A84003007D4002823E4360000105E
+:10BF00000000001568008A840040601800C263A821
+:10BF1000002003D4002804E42F00001000000015C6
+:10BF2000D0016A84D4018A845F00A3B85F00C4B8DA
+:10BF3000002863E0003084E0810063B8810084B8A9
+:10BF4000001807D4002007D42300000000000015CB
+:10BF50000040601804C163A80000809C002003D446
+:10BF6000CBFFFF03CC016A8478026A84001826E4C0
+:10BF7000A9FFFF130000809C7C026A84001827E45C
+:10BF8000A6FFFF0F00000015A4FFFF03000088A814
+:10BF9000004804D46DFFFF0328006A840100809CE0
+:10BFA00000202EE40600001000000015004060187C
+:10BFB00020C163A857FFFF03000000150040601870
+:10BFC00020C163A84100A09C002803D452FFFF03B6
+:10BFD00000000015000021850400418508008185CE
+:10BFE0000C00C185004800441000219CD8FF219C12
+:10BFF000004801D4045001D4086001D40C7001D46D
+:10C00000108001D4149001D418A001D41CB001D424
+:10C0100020C001D424D001D40100609D004020192B
+:10C0200078C029A90040401980C14AA9005809D404
+:10C03000000083A900580AD40040601824C563A8F2
+:10C04000000044AA2B00C18E000005AA000006AB28
+:10C0500000008384000047AB000088AA080044A5C4
+:10C060000000609C00180AE4180000100700C09D42
+:10C07000B4036C840058A3E084038C840600609CA5
+:10C08000001824E41B020010B42B0CD4B0036C8401
+:10C09000A0038C840028A3E0002085E50B0200109B
+:10C0A000020085B80800C09D000065A898008C8437
+:10C0B00044EBFF070000AEA80700609C00180EE4E8
+:10C0C0001B02000C00006EA90200609C001832E404
+:10C0D000F10100100100809C0040601820C163A89D
+:10C0E0006500809C002003D40040601824C563A82C
+:10C0F000000083840000609C080044A500180AE446
+:10C100001800001000000015B4036C840100A39C0B
+:10C1100084038C840600609C001824E4D001001085
+:10C12000B42B0CD4B0036C84A0038C840028A3E04F
+:10C13000002085E5C0010010020085B80800C09D00
+:10C14000000065A898008C841EEBFF070000AEA8D5
+:10C150000700609C00180EE4F501000C00006EA9B9
+:10C160000040601800C263A80040801824C584A85D
+:10C1700000A003D4000064840000809C080043A554
+:10C1800000200AE4180000100000609CB4036C84D6
+:10C190000100A39C84038C840600609C001824E4A6
+:10C1A00097010010B42B0CD4B0036C84A0038C84D2
+:10C1B0000028A3E0002085E587010010020085B873
+:10C1C0000800C09D000065A898008C84FDEAFF0768
+:10C1D0000000AEA80700609C00180EE4D301000C1C
+:10C1E0000000609C001830E46F0100100100809C8A
+:10C1F0000040601800C263A80000609D005803D48E
+:10C2000028008C840040601800C263A80000C09C15
+:10C210000C00AC84FFFF849C003003D40320A5E015
+:10C220000040601810C163A86400CC840100809CA9
+:10C23000002803D4002026E40700001000000015A9
+:10C240000040601804C163A848002C85002003D476
+:10C25000004803D40040601824C563A8000083840C
+:10C260000000609C080044A500180AE418000010B3
+:10C270000200609CB4036C840100A39C84038C8442
+:10C280000600609C001824E439010010B42B0CD483
+:10C29000B0036C84A0038C840028A3E0002085E513
+:10C2A00029010010020085B80800C09D000065A8A3
+:10C2B00098008C84C3EAFF070000AEA80700609CCA
+:10C2C00000180EE49901000C0200609C001832E492
+:10C2D0000A000010FEFFA09C3C006C845F0083B845
+:10C2E000002083E0032884E00040A01800C2A5A835
+:10C2F000022063E0001805D43800CC8400406018A8
+:10C3000014C163A80100809C003003D4002030E4F5
+:10C3100005000010000000150040601804C163A86B
+:10C32000002003D40040601824C563A80000838463
+:10C330000000609C080044A500180AE418000010E2
+:10C340000100809CB4036C840100A39C84038C8452
+:10C350000600609C001824E4ED000010B42B0CD4FF
+:10C36000B0036C84A0038C840028A3E0002085E542
+:10C37000DD000010020085B80800C09D000065A81F
+:10C3800098008C848FEAFF070000AEA80700609C2D
+:10C3900000180EE46501000C0100809C002050E4B0
+:10C3A0001A00001000006CA80000609C001830E427
+:10C3B000C30000100000001578026C84001818E417
+:10C3C000030000100000A09C0000A4A8004060181A
+:10C3D00004C163A80100809C002803D4002025E448
+:10C3E0000A00001000006CA80040601800C263A89A
+:10C3F00000C003D4002030E403000010000000154A
+:10C4000000D003D400006CA80000B8A854010004B8
+:10C41000000090A80100609C001812E409000010C0
+:10C420000200609C001832E4A00000100000809C14
+:10C430000040601808C163A80000609D005803D444
+:10C440000040601824C563A8000083840000609C3D
+:10C45000080044A500180AE41800001000000015A8
+:10C46000B4036C840100A39C84038C840600609C4C
+:10C47000001824E47F000010B42B0CD4B0036C84AB
+:10C48000A0038C840028A3E0002085E56F00001045
+:10C49000020085B80800C09D000065A898008C8443
+:10C4A00048EAFF070000AEA80700609C00180EE4F1
+:10C4B0001F01000C00006EA9CC016C840100A09C3F
+:10C4C000002823E4030000100000C09C0000C5A861
+:10C4D0000200609C001810E4030000100000809C23
+:10C4E000000085A8032086E00000609C001804E49A
+:10C4F000080000100700609C001810E40500001000
+:10C500000000C09C0040601800C263A8003003D443
+:10C5100084022C850040E01804C2E7A80100A09C1A
+:10C5200074026C84004807D4002823E41300001030
+:10C530000000001568008C840040601800C263A8E9
+:10C54000002003D4002804E40C00001000000015B3
+:10C55000D0016C84D4018C845F00A3B85F00C4B8A0
+:10C56000002863E0003084E0810063B8810084B873
+:10C57000001807D4002007D40040601824C563A821
+:10C58000000083840000609C080044A500180AE4B1
+:10C59000E600001000000015B4036C840100A39CA9
+:10C5A00084038C840600609C001824E419000010A9
+:10C5B000B42B0CD4B0036C84A0038C840028A3E0BB
+:10C5C000002085E509000010020085B80800C09D24
+:10C5D000000065A898008C84FAE9FF070000AEA867
+:10C5E000D300000000006EA988036C8400806019ED
+:10C5F00000006BA99803AC84002863E0001884E075
+:10C60000005884E00000A484F3FFFF03000065A845
+:10C6100014DAFF07000000155000EC8C0040801871
+:10C62000002084A81402AC9C9800CC84000076A85A
+:10C63000003804D400008AA882E9FF070000E6A8B9
+:10C64000BA0000000000CBA988036C849803AC8476
+:10C65000002863E00080A0180000A5A8001884E06E
+:10C66000002884E00000A4848DFFFF03000065A87B
+:10C67000FCD9FF07000000155000EC8C004060184A
+:10C68000002063A81402AC9C9800CC8400008AA807
+:10C69000003803D4000076A86AE9FF070000E6A886
+:10C6A00082FFFF030000CBA90040601804C163A80B
+:10C6B000002003D463FFFF030000001578026C84A0
+:10C6C000001838E441FFFF130000A09C7C026C843A
+:10C6D00000183AE43EFFFF0F000000153CFFFF0387
+:10C6E0000000A4A888036C8400802019000029A9F8
+:10C6F0009803AC84002863E0001884E0004884E0DC
+:10C700000000A4841FFFFF03000065A8D5D9FF0720
+:10C71000000000155000EC8C00406018002063A859
+:10C720001402AC9C9800CC8400008AA8003803D482
+:10C73000000076A843E9FF070000E6A814FFFF0306
+:10C740000000CBA988036C840080601900006BA9ED
+:10C750009803AC84002863E0001884E0005884E06B
+:10C760000000A484D3FEFF03000065A8BDD9FF0725
+:10C77000000000155000EC8C00406018002063A8F9
+:10C780001402AC9C9800CC8400008AA8003803D422
+:10C79000000076A82BE9FF070000E6A8C8FEFF030B
+:10C7A0000000CBA9002030E40700001000000015B5
+:10C7B0000040601800C263A8002003D492FEFF036B
+:10C7C00028008C840040601800C263A8FBFFFF03B0
+:10C7D0000200809C88036C8400802019000029A935
+:10C7E0009803AC84002863E0001884E0004884E0EB
+:10C7F0000000A48475FEFF03000065A899D9FF0717
+:10C80000000000155000EC8C00406018002063A868
+:10C810001402AC9C9800CC8400008AA8003803D491
+:10C82000000076A807E9FF070000E6A86AFEFF03FC
+:10C830000000CBA988036C840080C0180000C6A843
+:10C840009803AC84002863E0001884E0003084E0A2
+:10C850000000A4843CFEFF03000065A881D9FF0707
+:10C86000000000155000EC8C00406018002063A808
+:10C870001402AC9C9800CC8400008AA8003803D431
+:10C88000000076A8EFE8FF070000E6A831FEFF03EE
+:10C890000000CBA9002032E40600001000000015C3
+:10C8A0000040601820C163A80FFEFF0300000015C0
+:10C8B0000040601820C163A84100A09C002803D458
+:10C8C0000AFEFF030000001588036C849803AC8403
+:10C8D000002863E0001884E000806018000063A86E
+:10C8E000001884E00000A484F1FDFF03000065A8A7
+:10C8F0005CD9FF07000000155000EC8C0040601868
+:10C90000002063A81402AC9C9800CC8400008AA884
+:10C91000003803D4000076A8CAE8FF070000E6A8A4
+:10C92000E6FDFF030000CBA900006EA900002185F1
+:10C9300004004185080081850C00C1851000018636
+:10C9400014004186180081861C00C18620000187E2
+:10C9500024004187004800442800219CFCFF219CC2
+:10C96000004801D40000C4A8640063850000A3A8A7
+:10C970000000009D240083840700609C001824E4CC
+:10C98000030000100000E09C0100E09C004026E451
+:10C99000030000100000609C0100609C031867E029
+:10C9A000004003E4080000100700609CD801658483
+:10C9B0000100809C002003E4030000100700609C3D
+:10C9C000000004A9001806E4030000100000E09C29
+:10C9D0000100E09C0200609C001806E403000010C7
+:10C9E0000000809C0100809C032067E00000E09C28
+:10C9F000003803E4200000100100809C00202BE49C
+:10CA0000030000100000209D000024A9002028E45D
+:10CA1000030000100000609C000064A8031869E097
+:10CA2000003803E41D000010000000154800658474
+:10CA3000002023E4030000100000A09C0000A4A834
+:10CA40000040601804C163A80000809C002803D443
+:10CA5000002005E4090000100100609C00406018FF
+:10CA600000C263A8002003D4002003D40300809CEC
+:10CA7000002003D40100609C001826E40900001087
+:10CA80000000809C0040601804C163A8002003D40B
+:10CA90000400000000000015EAFFFF030000A09C56
+:10CAA00000002185004800440400219CFCFE219CDC
+:10CAB000004801D40000A4A9640083840000609DA4
+:10CAC000005804E44D0000100000E3A80C0063844B
+:10CAD000010063B80100039D0000609C001804E49D
+:10CAE000440000100000001528006784010063B8AE
+:10CAF0000100839C0000609C001825E433000010B6
+:10CB00000100609C0230C8E00000609DFFFF669C51
+:10CB1000005863E504000010000023A9002066E02F
+:10CB2000FFFF239D0040A9E5030000100000C9A8F5
+:10CB30000220C9E00000609D00586DE51F00000C58
+:10CB40000000ADA88400E19C0400219D020065B8AE
+:10CB5000001889E0FFFFA59C00008484001867E0AE
+:10CB6000005865E5FAFFFF13002003D401000D9D76
+:10CB70000000A09C004085E52200000C003009D494
+:10CB8000000089A88400E19C000067840100A59C46
+:10CB9000003003E4040000100400E79C001804D4F3
+:10CBA0000400849C004085E5F8FFFF130000001599
+:10CBB0001400000000000015EDFFFF030400219D9C
+:10CBC000D9FFFF03000023A9001825E4D6FFFF13B7
+:10CBD0000030C8E0001866E0002083E5F9FFFF138D
+:10CBE00000000015022066E0CFFFFF030100239D37
+:10CBF000C1FFFF0328008784B8FFFF030C000385F3
+:10CC000000002185004800440401219CE0FF219C94
+:10CC1000004801D4045001D4086001D40C7001D440
+:10CC2000108001D4149001D418A001D41CB001D4F8
+:10CC3000FF0003A6000084A90000609C0600D0B994
+:10CC4000B81B04D4881B04D48C1B04D40040C01827
+:10CC50006420C6A800408018402084A80030AEE0C0
+:10CC600000206EE00000E09C000083840000C09E75
+:10CC70000600609D500084B80000A5840C00609CF4
+:10CC8000070084A4903B0CD4941B0CD4882A0CD4A9
+:10CC9000983B0CD49C3B0CD4A03B0CD4A41B0CD4D0
+:10CCA000A83B0CD4AC3B0CD4B03B0CD4005824E4CF
+:10CCB0003500001084230CD40000C5A80080E018C3
+:10CCC000A400E7A8004080184C2084A8003866E043
+:10CCD00000202EE1000063840040A0185820A5A881
+:10CCE00000808018A80084A800284EE1881B0CD47E
+:10CCF0000020A6E000806018AC0063A80000A584B6
+:10CD00000018E6E00000E784008060182C0063A8AB
+:10CD10008C2B0CD4903B0CD40040A0186820A5A804
+:10CD200088038C8400280EE10080E0180800E7A842
+:10CD30000018C6E00038A4E00000A584FF7FE018DA
+:10CD4000F8FFE7A8040065B89C2B0CD41400639C82
+:10CD5000001884E0981B0CD40038A4E0FF7F601812
+:10CD6000FCFF63A80000A584001884E00000848410
+:10CD7000002009D4A02B0CD400B00AD400B008D4F1
+:10CD800000B006D400408018442084A80040A018B9
+:10CD90005020A5A884030C8500004BA900208EE23A
+:10CDA00000284EE2005028E426000010000070A881
+:10CDB00088038C840080E0180000E7A80040C018B9
+:10CDC0005420C6A898036C8400300EE1001864E07B
+:10CDD0009403AC84003863E000006384002884E09E
+:10CDE000001814D40038C4E08802AC840000C68463
+:10CDF000003012D40080C0180400C6A8003064E0DF
+:10CE00000030E5E000006384001808D4008060185A
+:10CE1000080063A80018C4E00000C6842800639CD2
+:10CE2000003007D40018A5E00080C0180C00C6A888
+:10CE3000003084E000008484002005D4000070A845
+:10CE4000BE00000400008CA88403EC840000A09CB9
+:10CE5000005027E403000010000007A90100A09C77
+:10CE60000700609C00182BE4030000100000809C69
+:10CE70000100809C032085E00000609C001804E411
+:10CE8000200000100600609C94036C840100209D2B
+:10CE9000A8038C841000639C004884E0DC02AC840E
+:10CEA000941B0CD4004825E40F000010A8230CD4D8
+:10CEB000B4036C8498038C84020063B8A403AC842C
+:10CEC000001884E0AC03CC840018A5E00400849C26
+:10CED0002800A59C0048C6E098230CD4A42B0CD4B1
+:10CEE000AC330CD4A8038C849C036C84001884E5B8
+:10CEF00074000010000000150000C9AA0600609C24
+:10CF0000001807E4030000100000A09C0100A09C92
+:10CF10000100609C001836E4030000100000809CB3
+:10CF2000000083A8042085E00000609C001824E431
+:10CF3000050000100800609C00180BE49AFFFF0F2A
+:10CF4000000000150600609C001827E46C0000102B
+:10CF50000800609C00182BE4170000100000209DC2
+:10CF6000EC036C84C402CC84003023E45300000C36
+:10CF70000400E09CEC038C9C0100299D3000849C03
+:10CF80000038A9E54B00000C0100A9B8000064843A
+:10CF9000003023E4F9FFFF1300000015004865E0AE
+:10CFA000FF7FE018FFFFE7A8040063B8006063E0BC
+:10CFB000EC3B03D48C034C8500806018000063A810
+:10CFC00000808018080084A888036C850018CAE0D7
+:10CFD0000020EAE000186BE0A403AC840000209D70
+:10CFE0000000638400288AE0001806D4A0030C85A2
+:10CFF000005065E0AC03CC84003007D40080E0181A
+:10D000000000E7A8B003CC84003884E0A803EC84D7
+:10D01000023008E1003804D400808018040084A89D
+:10D02000002063E00800859C004003D4004089E5AF
+:10D030001300000CA4230CD498036C840080C01847
+:10D040000000C6A80000A4A800186BE0005084E00F
+:10D05000003063E00030C4E0000083840400A59C3D
+:10D060000100299D002006D40400639C004089E54E
+:10D07000FAFFFF130400C69CA42B0CD4B803AC84A5
+:10D080000080E0180400E7A8000090A8A4038C85A5
+:10D0900000386AE00000C09C006003D40000E09CFF
+:10D0A00061D7FF070E00609C15000000000000150E
+:10D0B000BCFFFF03004865E0B9FFFF030000A09C30
+:10D0C000A003CC84B003AC84022866E0A4038C8463
+:10D0D000020063B8001884E0003065E59AFFFF1392
+:10D0E0002800849C90036C84002083E584FFFF0F5C
+:10D0F0000600609C95FFFF030000001500408018AB
+:10D10000402084A8FFFFA0A800206EE0002803D4E0
+:10D110000000218504004185080081850C00C1853F
+:10D120001000018614004186180081861C00C1860B
+:10D13000004800442000219CD8FF219C004801D4D5
+:10D14000045001D4086001D40C7001D4108001D4C3
+:10D15000149001D418A001D41CB001D420C001D473
+:10D1600024D001D4C402A484000004AA0000609D5D
+:10D170000040801844C584A80400C09CFF0083A61A
+:10D18000003004D44C5810D4EC5A10D44C5B10D45A
+:10D19000B45B10D4505B10D4545B10D4585B10D4E3
+:10D1A0005C5B10D4605B10D4645B10D4685B10D4FB
+:10D1B0006C5B10D4FFFF409E0000209E008805E4B9
+:10D1C000070000100700009FDC0290840100609CB3
+:10D1D000001804E40D00000C0600D4B80600D4B812
+:10D1E00000408018442084A80040A0184C20A5A826
+:10D1F000002066E000006384002886E0000084844C
+:10D20000141A10D4982010D40040601950206BA933
+:10D210000040A0185420A5A8005866E0002886E029
+:10D220000000638408006B9D0100409D0000848421
+:10D230000058A6E0302210D42C1A10D400408018D8
+:10D24000682084A88403B086002066E000008584FE
+:10D2500000002386035044E35F00B1B84E0071B86C
+:10D26000F02A10D4005035E40E06000C0350C3E23F
+:10D270008802F0850000609E00980FE448000010CE
+:10D280000000EFAA005035E4B205001000000015C0
+:10D290000080A0182800A5A80080C0183400C6A8E7
+:10D2A00000286FE000308FE00000238600806019C6
+:10D2B00070006BA90080C018A000C6A8000084847C
+:10D2C0005000D1B94F0011B9430031B9410051B9F3
+:10D2D0000058AFE00100B1A500806018740063A899
+:10D2E000B42210D4000025860018EFE000808018DA
+:10D2F000780084A800306FE100206FE00080A01863
+:10D300009C00A5A80000C78400288FE03F0091A5DD
+:10D31000000063844600B1B8010008A5001B10D4CA
+:10D3200000002486010029A503004AA500008B8483
+:10D33000500071B83F00A5A47C00F084FF00C6A493
+:10D34000010063A4010084A4FFFF71A58C7210D4B6
+:10D35000F84210D4904A10D4945210D4986A10D441
+:10D36000E46210D4E82A10D4FC3210D4485B10D404
+:10D37000441B10D40100E7A4009827E46D050010B9
+:10D38000A02110D4709B10D400808018300084A895
+:10D39000002077E000006384A41A10D414021085E2
+:10D3A000004060187CC063A80900609D98009084CC
+:10D3B0000B00E8B80100409D5F00C4B8003803D4FA
+:10D3C0008B00A4B800406018140663A8003084E005
+:10D3D000004003D4810084B80040601800C063A8F6
+:10D3E0000030A5E0002003D48100A5B80020E7E0CC
+:10D3F0000040601880C063A8002808E1003803D40A
+:10D4000000408018180684A80100A09C004004D4A5
+:10D4100000406018140B63A800408018000884A81E
+:10D42000002803D40000C09C002804D400406018E9
+:10D43000040863A8004080183CC584A8003003D4C9
+:10D44000005804D40040601808C063A80040801849
+:10D4500010C084A8002803D40100C09C002804D474
+:10D460000040601860C063A80800809C0D00A09C6C
+:10D47000002003D4940070850040801888C084A8E0
+:10D480000040601854C063A8002804D4003003D4BE
+:10D490000040801828C584A80800639C005804D464
+:10D4A0000500A09CA00090840600C09C0000609D28
+:10D4B000002003D40040801850C584A800406018A4
+:10D4C00054C563A8002804D4003003D41000849C01
+:10D4D0001000639C005804D40100A09C0400809CB0
+:10D4E0000200C09C002003D40050601900006BA90A
+:10D4F0000040801880C584A81400639C002804D4D0
+:10D50000003003D4004080180C0B84A80040601841
+:10D5100044D163A8005804D46C00D0844800809C97
+:10D520000040A018040AA5A8002003D40000609DB4
+:10D5300000406018000A63A8003003D4005805D4E6
+:10D54000005026E40400001000000015005005D42F
+:10D55000005805D400406018000063A8FB03A09C9D
+:10D56000FF03C09C002803D40040801884C084A816
+:10D57000003003D40000609D005004D4005804D44F
+:10D58000005035E4B904000C0800609CBC03908492
+:10D59000001824E45A0100100B00A09CB82B10D4F2
+:10D5A0000040A018280BA5A80100609C00008584FD
+:10D5B000001824E4050000100000809C0000609D1D
+:10D5C000005805D40000809C0040601804D063A877
+:10D5D000002003D40600809C002015E44401000CC8
+:10D5E000000000150040E01850C0E7A85000B08CC3
+:10D5F00000406018002063A800008784002803D43E
+:10D600000700809C002038E4340100100000A09C3A
+:10D610000040801848C084A84C03D0840000648473
+:10D620000000A78400408018042084A8002863E03C
+:10D63000430063B8023063E0001804D4CC02D08405
+:10D6400000406018082063A80040801814C084A817
+:10D65000003003D4DC02B0840400639C00008484A6
+:10D66000002003D40100809C002025E41901001053
+:10D670000000609C001832E40B010010002032E42E
+:10D680000200409E00406018102063A80100809CAA
+:10D69000009003D4002025E4FA0000100000809CD4
+:10D6A0002C0270850400639C00408018182084A818
+:10D6B000005803D430027084001804D40600409D42
+:10D6C000005015E4EB00000C000000158802D08427
+:10D6D0000000609C001806E4150000100700609C24
+:10D6E00084037084005003E4110000100700609C64
+:10D6F0000080601908006BA9008080180C0084A8C5
+:10D70000005866E00020A6E00000609D005803D4A9
+:10D71000005805D4008060183C0063A88003B084E2
+:10D72000001886E0002804D40700609C001838E444
+:10D730000B0000100000209EEC0290849F0064B853
+:10D740009800B0845D0063B8001884E0830084B85A
+:10D75000092B64E0062B63E0021824E2B803F0848E
+:10D760009400609CFFFF879C001844E4BE00000CFE
+:10D77000000094A8840310850100609C001828E430
+:10D78000B400000C0000A7A8D80270840000809CA0
+:10D79000002023E4AD00001000000015DC02B0847E
+:10D7A000002025E4A400000C000000150100609C8E
+:10D7B000001825E41A0000100700609C0000809CFF
+:10D7C000002006E416000010000000150600609C12
+:10D7D000001808E4120000100700609C48007084E4
+:10D7E000002023E48B00001000000015D402708498
+:10D7F0000080601908006BA9010083B80058A6E0FA
+:10D80000001884E0040084B8D003849C002090E0D9
+:10D8100000008484002005D40700609C001838E4D0
+:10D8200078000010000094A80000A7A80000D1A86C
+:10D830000500609C7CD5FF070000E09CDC02708442
+:10D840000100A09C002823E49A0400100600609CBC
+:10D8500084039084001824E4030000100000C09C9E
+:10D860000000C5A80700609C001838E40300001001
+:10D870000000809C000085A8032066E00000009D59
+:10D88000004003E48C040010000078A98C0350854C
+:10D890000080C0180000C6A80080601904006BA9B1
+:10D8A000A403F08400386AE0B4033085003083E0DC
+:10D8B0000058C3E00200A9B8AC0370852800259E7B
+:10D8C000005804D40080A0180800A5A82C02708578
+:10D8D000002883E0008806D4005804D40080C018D3
+:10D8E0000C00C6A8300270850030A3E000808018CC
+:10D8F000100084A8005805D40020C3E0CC02B084F6
+:10D900000400849C002063E0002806D44800908432
+:10D91000009003D4004024E4330000100000001500
+:10D92000D4029084010064B8002063E0040063B86E
+:10D93000008063E0D0032386EC02908400384AE143
+:10D940000080C0181800C6A89F0064B80030AAE084
+:10D95000008060191C006BA95D0063B8008805D4C5
+:10D960000058EAE0001884E00080A0182000A5A874
+:10D97000830084B80100299D0028CAE0002007D454
+:10D980000000009D004806D4004888E54A04000CC9
+:10D99000000078A9980370840080C0182400C6A8ED
+:10D9A0000080601900006BA9880390840030AAE011
+:10D9B000001884E0B0037084005884E000002486DE
+:10D9C0000100639C0100089D008805D40400849C2C
+:10D9D000004888E5FAFFFF130400A59C3504000009
+:10D9E000B01B10D4D4029084010064B8002063E01E
+:10D9F000040063B8008063E0D0FFFF03D4032386F4
+:10DA00000000A7A80D00609C8BFFFF030000C09CD6
+:10DA1000008080180C0084A8D40270840020A6E046
+:10DA2000010083B8001884E0040084B878FFFF0385
+:10DA3000D403849C000094A80000A7A80000D1A8EB
+:10DA40007DFFFF030700609C59FFFF03DC02B084E9
+:10DA50000900C09CBC3310D40000D1A876FFFF039E
+:10DA60000400609C0000A7A8E8FFFF032000609C62
+:10DA700005D5FF070000001516FFFF038802D084BC
+:10DA800000406018142063A80000A09C002003D46C
+:10DA900000408018182084A8002804D409FFFF0340
+:10DAA0000600409D040000100400609CF6FEFF0389
+:10DAB0000300409E001832E404000010000000152E
+:10DAC000F1FEFF03000043AAEFFEFF03000044AA9B
+:10DAD000EDFEFF03FFFF409E00406018042063A896
+:10DAE000002803D4D7FEFF03CC02D084DDD4FF0787
+:10DAF00000000015BCFEFF038403B086A000708404
+:10DB0000005023E4050000100200C09C0040601893
+:10DB100058C063A8003003D4005036E44F03000C13
+:10DB2000000000150300609C001835E40800001098
+:10DB30000100209E2C0290840000609C001824E4C8
+:10DB400003000010000000150000209E6400F08516
+:10DB50000100A09C00282FE43D03001000002FA925
+:10DB6000C40270840000809C032863E0002003E46A
+:10DB7000380300100000609D482810D40000609C0D
+:10DB8000001829E430030010000000150700009F72
+:10DB9000D802B0840100809C002025E40F0300100F
+:10DBA0000100609C480070840000C09C003023E4A9
+:10DBB000030000100000E09C0000E4A8002031E415
+:10DBC000030000100000609C000064A8031867E0D8
+:10DBD000003003E4010300100100609C0000009D80
+:10DBE0000400C09CFF7FA018FFFFA5A8EC03909C39
+:10DBF0000030A8E50C00000C000000150000648453
+:10DC0000002823E40500000C000000153000849C6F
+:10DC1000F8FFFF030100089DC4027084C84210D4BD
+:10DC2000001804D4C802708500808018000084A801
+:10DC300001006BB8A4021085005863E00320E8E0FF
+:10DC4000040063B82C02D084008083E0C03304D485
+:10DC50000000A4A80000C4A830029084C82305D402
+:10DC6000000085A89C02B084D02B06D40000A6A892
+:10DC70000000C09CD43304D40000C4A8A002908447
+:10DC8000D82305D4DC4306D40000809C002007E4A0
+:10DC9000C3020010E4D306D4900068B8FFFF88A444
+:10DCA000FF7F63A4B02210D4AC1A10D40403708494
+:10DCB000AC025085005003E4170000100100809C66
+:10DCC000B4007084002023E413000010000000154D
+:10DCD00028037084002023E4070000100000609CEB
+:10DCE00034039084001804E40300001000000015C1
+:10DCF000B82010D4B80070840000809C0A1B6AE031
+:10DD0000082310D40C2310D4142310D4182310D4B7
+:10DD10001C1B10D4080370840080C0180000C6A823
+:10DD20000000A09CB00290840330E8E00100809DD8
+:10DD3000002063E0202B10D4102B10D40000009D95
+:10DD4000081B10D40000C09C004007E42100001014
+:10DD500000000015B4007084006023E41D00001072
+:10DD600000000015080370840C0390840020A3E5D4
+:10DD7000030000100000209E022023E21C03B08458
+:10DD80000028B1E4030000100000609C0100609CCA
+:10DD9000101B10D4002884E0140370840100639CDD
+:10DDA000B80030860C2310D4008823E4090000104A
+:10DDB000141B10D4180370840000809C0100639C25
+:10DDC000142310D4181B10D4061B8AE00C2310D483
+:10DDD00010037084003023E40600000C01006BB8CF
+:10DDE000200370840100639CD8FFFF03201B10D424
+:10DDF000AC02B084005863E02003D084040063B810
+:10DE0000042B10D4008063E0E83303D40100A09C0D
+:10DE1000002829E4580200100000609C74007084FF
+:10DE2000C4029084082863E0002023E4520200101A
+:10DE30000000609CDC2A10D4DC02B0840100809CCD
+:10DE4000002025E4460200100000C09C4800908499
+:10DE50000000609C001824E4F101000C0000001593
+:10DE6000C8017084003023E4120000100400409EBA
+:10DE7000240050860200609C001832E40300001069
+:10DE80000000E09C0100E09C0700609C001832E468
+:10DE9000030000100000809C0100809C042067E0CB
+:10DEA000003003E403000010000000150000409E55
+:10DEB000B00070840000809C002023E40C0000105F
+:10DEC0000100609CB4007084002023E4080000106E
+:10DED0000100609C002032E4C9010010001832E407
+:10DEE000E4027085AC5810D40100609C001825E451
+:10DEF000BA0100100100809C480070840000809CE2
+:10DF0000002023E4AC0100100000E3A8D402B08498
+:10DF1000010065B8002863E0040063B8008083E076
+:10DF2000000064A8C8038484C0036384302210D432
+:10DF30002C1A10D4F4029084010065B8002863E024
+:10DF4000040063B80080A3E0E8036584E403C584AB
+:10DF5000201B10D4043084E00100609C001827E4EA
+:10DF600004000010F42210D40000A09C202B10D438
+:10DF7000200390840000609C001824E48C010010B1
+:10DF80000100C09C101B10D4C801F0840000409D0B
+:10DF9000005027E484010010000000151003D08415
+:10DFA000005026E45A00000C0200609C0000609CB7
+:10DFB000001826E4130000100100609C0100009D81
+:10DFC000004027E40F0000100000609DD402708420
+:10DFD0000040A01800C5A5A8084083E0004005D473
+:10DFE000001884E0005805D4040084B8FF7F60184E
+:10DFF000FFFF63A8008084E0EC1B04D40100609C58
+:10E00000001806E404000010001807E41300000CD8
+:10E0100000000015540190840000009DA801708448
+:10E020000218A4E0004065E50300001000000015A0
+:10E030000000A09CB00170848C019084022063E0F9
+:10E04000542910D4004063E503000010B01910D427
+:10E050000000609CB01910D40100409D005026E4DF
+:10E06000060000100000809D94017084A801908437
+:10E07000002063E0941910D4006026E4060000102C
+:10E080000100609C005027E41200000C0000001505
+:10E090000100609C001826E4060000100000001536
+:10E0A00020037084FFFF639CB2FFFF03201B10D48A
+:10E0B0008403B086D002D0840100669CD01A10D4AC
+:10E0C000C40270840100639C36FDFF03C41A10D49F
+:10E0D000260F0004000070A864007084005023E440
+:10E0E000090000100000E3A948007084006023E4E8
+:10E0F00005000010000000151003D084E5FFFF03A9
+:10E10000C85110D4E3FFFF031003D084001812E4B9
+:10E11000030000100700609C3C5010D4001838E445
+:10E120001B01000C000074A80100609C00182FE483
+:10E13000080000100700609C48007084005023E431
+:10E14000040000100700609C0000609DC85910D4B6
+:10E15000001838E40C0100100100609CA0009084BD
+:10E16000001804E4060100100300609C8403B086DC
+:10E17000001815E44200000C0600609C0040601886
+:10E180004CC063A84000A09C00008384430024BAD4
+:10E190000028B1E40C00000C000000154C03708452
+:10E1A0000040801880C184A8FFFFC09C0400319EFD
+:10E1B000003004D40028B1E4FCFFFF130400639C8A
+:10E1C0004C1B10D40040601858C063A80100609D2B
+:10E1D0000040801900208CA9005803D40040C019C9
+:10E1E0002CC5CEA90040601824C563A80000838414
+:10E1F0000000609C080044A500180AE41400001008
+:10E2000000000015B40370840100A39C0600609C0C
+:10E21000001835E4CE000010B42B10D4B003708485
+:10E22000002823E2A0039084002091E4BE000010A7
+:10E230000200B1B80800009F98009084000071A807
+:10E24000E0E2FF070000B8A88403B0860040601831
+:10E2500018C063A8000083840000609C100084A4A0
+:10E26000001804E4E0FFFF13000000151F00A09C4D
+:10E2700000280ED400180ED40600609C001835E467
+:10E28000030000100000A09C0100A09C0700809CDF
+:10E29000002018E4030000100000609C0100609C56
+:10E2A000031865E00000A09C002803E40202000CB3
+:10E2B000000078A948003085002829E49700001064
+:10E2C000002018E4030000100000C09C0100C09C66
+:10E2D0000100809C002012E4030000100000609CFC
+:10E2E000000064A8031866E0002803E4880000101A
+:10E2F00000000015D002D0840000609D0000009D49
+:10E30000EC0370840400E09CCC3210D4003023E491
+:10E310000C00000CD45A10D4EC03B09C0100089DF2
+:10E320000038A8E50700000C3000A59C000085849B
+:10E33000CC027084001824E4F9FFFF13D44210D4F7
+:10E340000800609CD402B084401B10D4010065B862
+:10E35000002863E0040063B8008083E0000064A844
+:10E36000C8038484C0036384302210D42C1A10D4D0
+:10E37000010065B8FF7F8018FFFF84A8002863E0D4
+:10E38000040063B8008063E0EC2303D40700609CC2
+:10E39000001838E4030000100000809C0100809CFD
+:10E3A0000100A09C002832E4030000100000609CE3
+:10E3B000000065A8041864E00000E09C003803E455
+:10E3C0004B0000100300609C002852E4060000107F
+:10E3D000000000159C00708488009084002063E099
+:10E3E0009C1810D4400070849C009084FFFF639CB4
+:10E3F000002063E5040000100200609C0000609DA6
+:10E400009C5810D4001832E40500001000000015DC
+:10E410003C0070840100639C3C1810D4003829E44F
+:10E420001C000010002832E437000010249010D4A3
+:10E43000100070840100639C101810D40200609CCE
+:10E44000001812E40700001000000015100090846E
+:10E4500074007084001804E40500000C000000152E
+:10E46000140070840100639C141810D40800708498
+:10E470000100809C0100639C002012E40500001054
+:10E48000081810D418007084002063E0181810D405
+:10E49000640090840100609C001824E404000010D3
+:10E4A000001809E406000010000000150000609C40
+:10E4B000001824E4080000100100609C001812E419
+:10E4C00005000010000000150C0070840100639C22
+:10E4D0000C1810D4040070840000809C0100639C20
+:10E4E000002010D4041810D40300609C001835E4F8
+:10E4F000F3FEFF130100669C0000A09CF0FEFF03EA
+:10E50000D82A10D4CDFFFF030000609CD002D08435
+:10E5100098FFFF03D402B084D002D0849CFFFF0395
+:10E52000402310D49803908488037084002063E013
+:10E5300000808018000084A8001865E0002063E0D7
+:10E54000000023863EFFFF039800908445D2FF071A
+:10E55000000000155000908C000074A81402B09CBC
+:10E560009800D08400200CD40000E6A8B5E1FF0795
+:10E5700000008AA835FFFF0300000BAB00FFFF037C
+:10E580008403B0863DFFFF038403B086000090A89B
+:10E59000550100040000B2A86400F085E3FEFF030B
+:10E5A00000000BAB82FEFF031003D08477FEFF0355
+:10E5B000103310D4D402B084010065B8002863E0A1
+:10E5C000040063B8008083E0000064A8CC03848466
+:10E5D00057FEFF03C40363840040601800C563A8AE
+:10E5E0000000A09C002003D48403B086D002D08415
+:10E5F000002803D4B2FEFF030100669C0500001052
+:10E6000000000015E802708438FEFF03AC1810D437
+:10E61000E002908435FEFF03AC2010D4D504000442
+:10E62000000070A80200C09C00302BE4070000101E
+:10E6300000004BAA0000609D145810D4085810D454
+:10E640000C5810D4185810D46400F0850100609C58
+:10E6500000182FE403000010000023AA000026AADF
+:10E660000200609C001832E4030000100000A09C2F
+:10E670000100A09C0400609C001832E4030000101C
+:10E680000000809C0100809C042085E00000609CCC
+:10E69000001804E4270000100100609CD002708480
+:10E6A000CC1A10D40000809CEC0370840000009D04
+:10E6B0000400C09CCC02B084002823E40B00000CB2
+:10E6C000D42210D4EC03909C0100089D0030A8E5F2
+:10E6D0000600000C3000849C00006484002823E4C1
+:10E6E000FAFFFF13D44210D40500609C001828E400
+:10E6F0000E0000100100809C3C037084002023E485
+:10E700000600000C0000C09C0000A09C3C2310D41C
+:10E71000C3FFFF03742810D40000A09CDC3210D487
+:10E72000E4FDFF03D83210D4E2FDFF03DC02B08425
+:10E73000001832E40500001000000015D002D0845B
+:10E74000D8FFFF03028866E074007084068B63E0E4
+:10E75000D002D084D3FFFF03001866E000406018A9
+:10E7600000C563A8002003D4003003D456FEFF0385
+:10E77000C4027084001829E4B0FDFF1300000015E6
+:10E7800074009084C4027084001824E4ABFDFF136D
+:10E790000100C09CA9FDFF03DC3210D41E00C09C08
+:10E7A000C40270840000809C002003E40300001079
+:10E7B000AC3210D40100809C0100A09C002816E41B
+:10E7C000030000100000609C000065A8031864E0CE
+:10E7D00037FDFF03B01A10D4001825E40300001021
+:10E7E0000000C09C0000C3A8001831E40300001022
+:10E7F0000000809C000083A8032086E00000609C4D
+:10E80000001804E483FDFF130100A09CC80290845B
+:10E81000010064B82C027085002063E0040063B836
+:10E82000008083E00000A4A8C45B04D4000064A8B6
+:10E8300030029084CC2305D49C02B08474FDFF0385
+:10E84000D42B03D4D3FCFF03400310870000609D4A
+:10E85000CBFCFF03485810D44A060004000070A8FF
+:10E86000B1FCFF038403B086AC009084BC1B10D4C1
+:10E87000D85210D4000070A8802210D4F9080004E7
+:10E88000D02010D4A0007084005023E405000010B4
+:10E890000200C09C0040601858C063A8003003D438
+:10E8A0000040801800C584A80000609D005004D47A
+:10E8B000000070A8005804D450F4FF0700000015B1
+:10E8C000C2F4FF07000070A8A0007084005023E489
+:10E8D00012000010000000150040601858C063A826
+:10E8E0000040A01818C0A5A8005003D40000809CC8
+:10E8F0000040C0182CC5C6A800006584100063A4A1
+:10E90000002003E4FDFFFF131F00609C0000809CBB
+:10E91000001806D4002006D40040601848C063A840
+:10E920008403B086000063841EFBFF03EC1A10D43E
+:10E930000080601938006BA900588FE000006484E3
+:10E94000450063B8010063A490FAFF03701B10D464
+:10E9500000808018040084A80080A0182C00A5A8BE
+:10E9600000206FE00000638400288FE000008484B2
+:10E970009C1A10D4010064A4009803E4080000105D
+:10E98000A02210D40080C0189800C6A82C5310D420
+:10E9900000306FE000006384381B10D4020064A4D0
+:10E9A000009803E409000010040064A400806019CA
+:10E9B00094006BA9285310D400586FE000006384C2
+:10E9C000341B10D4040064A4009803E40800001071
+:10E9D0000000001500808018900084A8245310D4F3
+:10E9E00000206FE000006384301B10D4700370843B
+:10E9F000005023E465FAFF13000000150080A01802
+:10EA00004400A5A80080C0180000C6A800286FE038
+:10EA10000080601904006BA900002386003091E09B
+:10EA2000005871E0000084840C00C69C0C006B9DB3
+:10EA3000502310D40000638400808018080084A84C
+:10EA40000020B1E0541B10D40000A584003091E0F8
+:10EA5000005871E0000084840C00C69C0C006B9D83
+:10EA60005C2310D4582B10D400808018140084A884
+:10EA7000000063840020B1E00000A584003091E034
+:10EA8000601B10D400008484005871E0000063848F
+:10EA9000642B10D4682310D43CFAFF036C1B10D4F1
+:10EAA00024010004000070A8F2F9FF038403B0867B
+:10EAB000000078A9000021850400418508008185B7
+:10EAC0000C00C18510000186140041861800818663
+:10EAD0001C00C186200001872400418700480044B3
+:10EAE0002800219CC8FF219C104801D4145001D457
+:10EAF000186001D41C7001D4208001D4249001D46A
+:10EB000028A001D42CB001D430C001D434D001D419
+:10EB1000FF0043A7000044A9000064A8FA02000413
+:10EB20000000C5A91C008A840600609C001844E50A
+:10EB3000090000100100A09C004060180CC563A8EB
+:10EB400080200AD4002803D47C280AD40400639CC3
+:10EB5000002003D4FF7F8018F7F884A800406018D5
+:10EB6000E0D063A88400AA84002003D40707809C17
+:10EB7000002045E503000010F8F8C59C0000C09C8B
+:10EB800060006A840040A01838C5A5A85C008A848B
+:10EB9000080063B8003005D4042063E06C00AA8448
+:10EBA000040063A800408018300884A8001804D42A
+:10EBB0001C008A8400406018200863A8002003D449
+:10EBC00020006A8400408018240884A8001804D417
+:10EBD00040008A84004060183CD063A8002003D421
+:10EBE0000100809C002025E4C00000100200809CF1
+:10EBF00000406018540863A80300A09C002803D4B8
+:10EC00004800CA840000409E0100809C002026E449
+:10EC1000B10000100000A6A800406018400863A8DA
+:10EC2000009003D40000609C001825E48E00000CC6
+:10EC30000000001530008A8500182EE4080000103E
+:10EC400034008A86D8016A84010063B800182CE475
+:10EC50008300001000000015FFFF8C9D0000609CE9
+:10EC600000182EE4090000100100809C00202CE414
+:10EC70000600001000000015D8016A84002003E49B
+:10EC8000070000100000001524008A840700609C23
+:10EC9000001804E40300000C000000150100409E71
+:10ECA00038006A840000009E003063E000800CE4BD
+:10ECB0000300001038180AD4FFFF8C9D05008CB8A3
+:10ECC000FFFF949E0040601814D063A804A084E065
+:10ECD0000000B2A8002003D400006AA8E1030004E9
+:10ECE00000008EA800802CE45A00001000000015DF
+:10ECF0000000409E0100609C00182EE450000010AF
+:10ED00000000A09C000043AA0040601818D063A82F
+:10ED1000009003D40200609C00182EE40300001051
+:10ED20000000809C0100809C0700009F00C02EE432
+:10ED3000030000100000609C0100609C041864E067
+:10ED40000000C09E00B003E43900000C00006AA877
+:10ED500000008EA8900900040100009E0040601889
+:10ED600000C563A80000A09C008003D490028A84A0
+:10ED7000002803D4008024E42200000C00000015C9
+:10ED80000000809CFF7FA018FFFFA5A8002001D4F1
+:10ED9000042801D4082001D400007AA80000CCA8DF
+:10EDA00000008AA80C9001D40000F4A80000AEA8CE
+:10EDB000AE0500040000009DB4006A8400008BA929
+:10EDC000008023E4030000100000809C000090A855
+:10EDD00000C02CE4030000100000609C000070A83C
+:10EDE000041864E000B003E44500001000006AA8C5
+:10EDF000CB0A000400008EA84200000000006CA9AD
+:10EE0000FEF2FF0700006AA870F3FF0700006AA87F
+:10EE10000000609C901A0AD40040601848C063A8A3
+:10EE200000006384D7FFFF03EC1A0AD4040900042E
+:10EE300000008EA8C7FFFF0300006AA8004060180A
+:10EE400018D063A8002803D4B4FFFF030200609C1D
+:10EE5000DC016A84A8FFFF03FFFF439E80FFFF03DE
+:10EE600001008C9D00006AA85703000400008EA8D2
+:10EE70002C006A84FFFF639CD8018A8403186BE12D
+:10EE800018006A840018A4E50300001038580AD45A
+:10EE9000000083A864006A84000084A90100E09C4B
+:10EEA000003823E40300001018200AD4083884E155
+:10EEB00000382EE40300001000000015000087A9B0
+:10EEC0004800CA84000087AA30600AD475FFFF0397
+:10EED00034380AD400406018400863A8002003D4E6
+:10EEE00052FFFF030000609C00406018540863A8B4
+:10EEF000002003D444FFFF034800CA8400006CA92B
+:10EF00001000218514004185180081851C00C185F1
+:10EF10002000018624004186280081862C00C186BD
+:10EF20003000018734004187004800443800219CAC
+:10EF3000F4FF219C004801D4045001D4086001D49E
+:10EF4000000083A9004080181C0884A800406018B5
+:10EF5000180863A80040A01934D0ADA9000063844C
+:10EF6000AA00209E0000848454180CD458200CD48D
+:10EF700000406018300863A8004080183C0884A84E
+:10EF800000006385000084841800639C8800EBB84F
+:10EF9000000063840300EBA5FF00E7A468180CD40D
+:10EFA00064200CD4004060184C0863A8004080180E
+:10EFB00004C584A800006384D0190CD460380CD434
+:10EFC00000406018500863A800006384D4190CD472
+:10EFD00000006485004060180CC563A800006384CD
+:10EFE0000C00849C9000ABB87C180CD40000848486
+:10EFF0000040601814C563A8FFFF0BA500006384E0
+:10F000000300A5A480200CD484180CD400408018E0
+:10F0100018C584A8004060181CC563A80000C484FB
+:10F0200000006384004080188CC584A8FFFFC6A43C
+:10F030008C180CD470400CD40040601820C563A814
+:10F0400074280CD40000638490180CD4004060181D
+:10F0500088C563A800006384A4180CD400008484CD
+:10F0600000406018A0C563A800006385A8200CD4E8
+:10F070003F006BA488300CD400408018A4C584A83D
+:10F08000AC180CD40000248500406018A8C563A803
+:10F0900089000BB9000063848800EBB80800849CE9
+:10F0A000BC180CD40000648500406018B0C563A88B
+:10F0B0000100E7A4000063840800849C8800CBB8AA
+:10F0C000C8180CD40000848400406018C4C563A82C
+:10F0D0003F004BA500006384FFFF29A53F00C6A4A5
+:10F0E000D4180CD4CC200CD40040601804D063A8F1
+:10F0F0000040801848D084A800006384CC190CD448
+:10F100005C780CD40040601810D063A8B0380CD4E0
+:10F110000000638500006D848500ABB8EC190CD449
+:10F120000300A5A40040601844D063A8B8480CD4DC
+:10F130000000638400008484F0190CD4F4210CD402
+:10F14000004060181CD063A82C01809CC4500CD4D3
+:10F15000002003D4C0300CD40040801820D084A8F4
+:10F160000C00639C008804D40100809C2C01209E2C
+:10F17000002003D4E0890CD4032008E11F006BA415
+:10F18000AA00209EEC018C8400406019D8D06BA9A5
+:10F19000D8190CD4E4890CD4B4400CD40100609C80
+:10F1A000DC290CD40000AB84E8190CD40000609C6E
+:10F1B000001804E406000010F8290CD40100609C3B
+:10F1C00000182FE40900000C00000015F8016C8401
+:10F1D0000000C09C400063A8EC310CD400180BD494
+:10F1E000F8190CD400300DD40040801840D184A808
+:10F1F0000000209E0000848410220CD488026C84BD
+:10F20000AC008C84E0220CD4FC890CD4008A0CD491
+:10F21000048A0CD4088A0CD40000809C002023E4CB
+:10F22000050000100C8A0CD4AC00AC84E42A0CD489
+:10F23000E82A0CD400406018000663A8004080183B
+:10F24000100684A8000063841C1A0CD40000848477
+:10F2500000406018080663A820220CD400006384D4
+:10F2600000408018400784A8241A0CD4000084842D
+:10F2700000406018040663A828220CD400006384B0
+:10F28000004080181C0684A8541A0CD40000848402
+:10F2900000406018000763A834220CD40000638487
+:10F2A00000408018200684A8381A0CD400008484FA
+:10F2B00000406018040763A83C220CD4000063845B
+:10F2C00000408018100784A8401A0CD400008484E1
+:10F2D00000406018080763A844220CD4000063842F
+:10F2E00000408018140784A8481A0CD400008484B5
+:10F2F000004060180C0763A84C220CD40000638403
+:10F3000000408018200784A8501A0CD40000848480
+:10F31000004060182C0663A864220CD400006384AB
+:10F3200000408018300684A85C1A0CD40000848445
+:10F330000040601808C563A864002C850000638441
+:10F3400060220CD40100809C002029E461000010A0
+:10F3500078180CD4D8016C84082063E0FFFF639C0C
+:10F360000000809C781A0CD478022C8668006C848B
+:10F37000002023E4540000107C8A0CD4D0016C845B
+:10F38000002023E4510000100100609CD4016C8433
+:10F39000002023E44D0000100100609C74220CD476
+:10F3A0005400CC8458000C850F00669C0F00A89C6C
+:10F3B000840063B88400A5B8040083B8062BE3E09A
+:10F3C0001C180CD4023084E020280CD4810084B8AE
+:10F3D0006C220CD40100609C001829E42D00001060
+:10F3E00040380CD4081868E0E0FFC09C2000A09CC6
+:10F3F0009F0083B85B0084B8002083E0033084E082
+:10F40000022063E0021865E100282BE403000010ED
+:10F410000100699C0000609D6C028C8488186BE080
+:10F420000000A09C002824E417000010701A0CD4DF
+:10F43000002823E4150000100100609C682A0CD409
+:10F44000B4008C840100609C001824E40C000010BF
+:10F450000000809CB8008C840000609C001804E4CC
+:10F460000600001000000015AC026C840A2363E063
+:10F470001A0000001C1B0CD40000809C1700000028
+:10F480001C230CD40100609CEEFFFF03681A0CD40F
+:10F490009F0068B8F0FF209E1000809C5C0063B85D
+:10F4A000001868E0038863E0021868E0021864E16D
+:10F4B00000202BE4D9FFFF130100699CD7FFFF0355
+:10F4C0000000609D0100609CB6FFFF03741A0CD41D
+:10F4D000A3FFFF03D8016C840800000400006CA89F
+:10F4E000B85B0CD4000021850400418508008185AB
+:10F4F000004800440C00219CECFF219C004801D4F2
+:10F50000045001D4086001D40C7001D4108001D4DF
+:10F51000B800A384000043A9B40083840100609C68
+:10F52000001824E40F0000100000609C001825E47F
+:10F53000040000103300809C6C0000003E00609DC1
+:10F54000C0006A84002043E5680000103F00609D11
+:10F55000C4006A84002043E5640000100000001528
+:10F56000E0028A843300609C0018A4E504000010C7
+:10F570000100609C5D0000003F00609D64008A8483
+:10F58000001824E4560000100000001558006A849A
+:10F5900040008A84010083B9010004BA5400AA849F
+:10F5A0000005609C0018A5E5030000100000C09C49
+:10F5B0000100C09CD002609C0018ACE50300001064
+:10F5C0000000809C0100809C042066E00000C09D3B
+:10F5D000007003E43B00000C000000158007609CF5
+:10F5E0000018A5E5030000100000C09C0100C09CAD
+:10F5F0004004609C0018ACE5030000100000809CF3
+:10F600000100809C042086E00000609C001804E457
+:10F61000040000100300609C340000001C00609D8A
+:10F620005C008A840018A4E5040000101F00809C80
+:10F630002E000000A600609D60006A84F7FF639CB6
+:10F64000002043E429000010A700609D020063B879
+:10F6500004008018D46E84A8002063E00000838436
+:10F6600000200044000000156300609C0018B0E515
+:10F6700004000010000000151C000000B600609D92
+:10F680001A0000000000609DF9FFFF038C01609CE0
+:10F69000F7FFFF031803609CF5FFFF035406609C0F
+:10F6A000F3FFFF03100E609CF1FFFF030014609C4A
+:10F6B0000E000000A700609DEDFFFF03E01F609CAF
+:10F6C00018D1FF0788026A8400700BE40700000C61
+:10F6D0001C00609DC2FFFF035400AA8458008A8565
+:10F6E000AFFFFF0340000A8600002185040041852A
+:10F6F000080081850C00C185100001860048004487
+:10F700001400219C5400A38400408018180884A889
+:10F71000002804D49C00E3840040A0181C08A5A87D
+:10F72000580083841000E7B8002005D48800C38403
+:10F73000004080183C0884A86400A3840438C6E014
+:10F74000002804D46800A3840C00849C002804D4FE
+:10F75000D00183840040A0184C08A5A8002005D43F
+:10F76000D401A38400408018500884A8002804D441
+:10F770007C00A384004080180CC584A8002804D411
+:10F780000040A01818C5A5A81000849C003005D41E
+:10F790008C00A384002804D4900083840040A01827
+:10F7A00020C5A5A8002005D4A400A384004080188B
+:10F7B00088C584A8002804D4A80083840040A01829
+:10F7C0008CC5A5A8002005D4CC01A38400408018D6
+:10F7D00004D084A8002804D4E00183840040A01849
+:10F7E0001CD0A5A8002005D4E401A3840040801803
+:10F7F00020D084A8002804D4E80183840040A01805
+:10F8000028D0A5A8002005D4EC01A38400408018CE
+:10F8100034D084A8002804D4F00183840040A018C8
+:10F8200044D0A5A8002005D4F401A384004080188A
+:10F8300048D084A8002804D4F80183840040A0188C
+:10F84000D8D0A5A8002005D41002A38400408018B9
+:10F8500040D184A8002804D41C0283840040A0184E
+:10F860000006A5A8002005D42002A384004080182B
+:10F87000100684A8002804D4240283840040A01821
+:10F880000806A5A8002005D42802A38400408018FB
+:10F89000400784A8002804D4540283840040A018A0
+:10F8A0000406A5A8002005D43402A38400408018D3
+:10F8B0001C0684A8002804D4380283840040A018C1
+:10F8C0000007A5A8002005D43C02A38400408018AE
+:10F8D000200684A8002804D4400283840040A01895
+:10F8E0000407A5A8002005D44402A3840040801882
+:10F8F000100784A8002804D4480283840040A0187C
+:10F900000807A5A8002005D44C02A3840040801855
+:10F91000140784A8002804D4500283840040A0184F
+:10F920000C07A5A8002005D46402A3840040801819
+:10F93000200784A8002804D45C0283840040A01817
+:10F940002C06A5A8002005D46002A38400408018DE
+:10F95000300684A8002804D4780063840040A018EE
+:10F9600008C5A5A8001805D40048004400000015EB
+:10F97000F4FF219C004801D4045001D4086001D454
+:10F980007000A384000043A90000609C001825E4D7
+:10F990008200001000000015FFFF809C0000A09C6A
+:10F9A000002804E4080000100200809D00006A8422
+:10F9B0000100609D005803E45300000C0200609CAD
+:10F9C0000200809DF4026A840100A09C002823E4C8
+:10F9D000030000100000C09C0000C5A800280CE433
+:10F9E000030000100000809C000085A8032086E032
+:10F9F0000000609C001804E40500001000000015E1
+:10FA000014180AD4F41A0AD40200809D00280CE4C9
+:10FA10002E000010FFFF6C9C2C03EA84002807E4F2
+:10FA2000370000100000001528036A84002803E452
+:10FA300031000010000000152403CA84002806E4E9
+:10FA40002100000C000000150100809C002027E42C
+:10FA500004000010000000153803AA8470280AD49E
+:10FA6000002023E4080000100100609C34038A8415
+:10FA70000000609C001804E4030000100100609C7A
+:10FA8000B8200AD4001826E4080000100000609C8A
+:10FA900030038A84001804E4050000100200809DF1
+:10FAA000BC200AD40000609C0200809D14180AD477
+:10FAB0002C1B0AD4281B0AD4241B0AD46904000472
+:10FAC00000006AA8FFFF6C9C0100809C002043E4BA
+:10FAD000030000100000A09CC8290AD4C8016A8451
+:10FAE000002023E43300001000006CA93000000067
+:10FAF0000400809DD5FFFF032403CA84FEFFFF039B
+:10FB000028036A8424008A84001804E4AEFFFF13EB
+:10FB10000000809D3C036A84005803E4AAFFFF13A1
+:10FB20000000001510008A8474006A84001824E420
+:10FB3000180000100000001544036A84002803E444
+:10FB400006000010000000154803CA84002826E4BF
+:10FB50000B00001000000015FFFF809C0000609C5F
+:10FB6000001824E4040000100000001596FFFF03B5
+:10FB70000700809D94FFFF030000809D14008A848D
+:10FB8000093364E0063363E0F5FFFF03021884E005
+:10FB90008DFFFF0300008BA914008A84092B64E009
+:10FBA000062B63E07EFFFF03021884E000006CA9CF
+:10FBB000000021850400418508008185004800443B
+:10FBC0000C00219C0000A3A80200609C001824E403
+:10FBD0000E00000C0000609D0100609C001824E4F1
+:10FBE000060000100000001508006584010063B8DD
+:10FBF00006000000FEFF639D740085840800658494
+:10FC0000002063E0010063B90048004400000015D3
+:10FC10000040601804C163A80100809C0800A09CFB
+:10FC2000002003D4004080184CC084A800006484E5
+:10FC3000070063A4021865E0002803E40700001031
+:10FC4000020083B80040A01800C1A5A8002864E005
+:10FC50000000809C002003D40048004400000015F0
+:10FC6000A0FF219C004801D4045001D4086001D4B5
+:10FC70000C7001D47400C3850000A3AA0000E4AB9B
+:10FC80000700609C4400809C4C1801D4502001D493
+:10FC90000800609C0100849C541801D4582001D4B1
+:10FCA0000B00609C4000809C5C1801D4382001D47B
+:10FCB0003700639C0100849C3C1801D4402001D48F
+:10FCC0000100639C0C00809C441801D4482001D49E
+:10FCD0000700609C0800809C241801D42C1801D4D3
+:10FCE000282001D40B00609C302001D4341801D4AA
+:10FCF0003800849C3600639C102001D4182001D465
+:10FD0000141801D41C1801D40C00809C0000609CC5
+:10FD100000182EE411010010202001D4DC0195848C
+:10FD20000100609C001824E40D0100104C00419D6E
+:10FD30002400419D1000A19F4800F5850100C09C52
+:10FD40000C00B58500303FE4E200001000002FAA4F
+:10FD5000FEFF6D9CFFFF8D9C0300C3A4030064A401
+:10FD6000020063BA020066BB07002FBB00E8B3E0E5
+:10FD700000E87BE00050DBE0000083840050F3E00B
+:10FD8000004060182CD063A8080024B9007803D480
+:10FD9000000065850400639C070084B800000685A8
+:10FDA0000F00AFB8008803D4044084E0004060181E
+:10FDB0006CC563A80000E7840700CBB80448A5E041
+:10FDC000002003D40438C6E00400639C04C8A5E006
+:10FDD000003003D40440A5E000408018000984A846
+:10FDE0000100609C002804D400183FE4B10000101A
+:10FDF00008006BB80F00F1BA070091B8041877E05B
+:10FE0000042063E000408018800984A8043863E07F
+:10FE1000001804D40100609C00183FE403000010A7
+:10FE20000300ADA50400A09D0200ADB98802358590
+:10FE30000000809D00E86DE000508DE00000C3846C
+:10FE40000700A6B8000064850040601874C563A868
+:10FE50000800C6B80458A5E000408018080B84A824
+:10FE60000458C6E0002803D4003004D4006009E43C
+:10FE70002000001000E8B3E000E81BE100008584EA
+:10FE80001F0071B80050F3E0180084B80000C88467
+:10FE90001700AFB8042063E01000C6B8042863E080
+:10FEA00000008784043063E00430A5E0080084B8D3
+:10FEB00004B863E00050FBE0042063E00000078525
+:10FEC000008080185C0084A804C863E00020C9E0BA
+:10FED000044063E004C8A5E0001806D40440A5E08F
+:10FEE00000806018600063A8001889E0002804D42E
+:10FEF00000406018280B63A800008384006024E49D
+:10FF0000320000100000C09C0100609C00181FE43B
+:10FF10002E0000103E00639C0018ABE5610000104D
+:10FF200000000015004060180C0563A80000E38481
+:10FF300000E8ADE000506DE00000C584000083845F
+:10FF4000020084B800406018000663A8001884E02E
+:10FF5000000064840B0063B8004080182C0B84A858
+:10FF60000018A7E03F00609C002804D40018A6E514
+:10FF70004800001000000015004060180C0563A840
+:10FF80000000E38400E88DE000006484020063B8B0
+:10FF900000408018000684A8002063E000008384ED
+:10FFA0000B0084B800406018300B63A80020A7E065
+:10FFB000002803D400408018280B84A80100609C0E
+:10FFC000001804D40000C09C00300EE4250000108E
+:10FFD00000000015DC0195840200609C001804E418
+:10FFE000200000100000001500406018080563A8FC
+:10FFF000004080180C0584A80000A38400006484DD
+:020000021000EC
+:10000000001825E41700001000303FE41500001030
+:100010000000001500507BE0000083840100609C1C
+:10002000BCFF849C001844E40E0000100000001582
+:100030002C02958400406018240663A8002003D495
+:100040003002B58600408018280684A80040601859
+:1000500068C563A800A804D4430000000905809C7B
+:100060002C02958400406018180763A8002003D470
+:100070003002B586004080181C0784A80040601834
+:1000800068C563A800A804D437000000C623809C7C
+:1000900000406018080563A8BAFFFF0300000015C0
+:1000A00000406018080563A8A1FFFF0300000015C9
+:1000B0000F00F1BA070091B8041877E0042063E05C
+:1000C00000408018040984A852FFFF03043863E04D
+:1000D000640075840000809C002023E4050000106B
+:1000E00000202FE4FFFF6D9C1CFFFF03FEFF8D9C93
+:1000F0000800001000202DE4FFFF6D9C000026AAE0
+:10010000030063A40000E09D16FFFF030000C3A8E6
+:100110000F000010FFFF6D9C0000C09C0000E09DE0
+:100120000100609C001825E4070000100000001585
+:100130000300CDA40000E09D000066A809FFFF03B6
+:100140000000209EFEFFFF0303006DA40000E6A94F
+:10015000F4FFFF030300C3A44C00419DF7FEFF031F
+:100160003800A19F002003D40000218504004185B0
+:10017000080081850C00C185004800446000219C76
+:100180000000809C0100A09C0200C09C002803D4B9
+:10019000042003D4082003D40C2003D4102003D45B
+:1001A000142003D4243003D49C2003D4C42203D4C9
+:1001B000C82203D4CC2203D4D02203D4DC2203D41B
+:1001C000D42203D40400A09CEC03639CFF7FC018DE
+:1001D000FFFFC6A80100849C003003D40028A4E5DA
+:1001E000FDFFFF133000639C004800440000001531
+:1001F000F0FF219C004801D4045001D4086001D4D0
+:100200000C7001D4FF0083A50000C6A9100060187F
+:10021000000063A80018A7E405000010000047A92B
+:1002200000806018000063A8041847E10000C09C2B
+:1002300000302AE4030000100000E09C0100E09C74
+:10024000AF04609C001848E4030000100000A09C6C
+:100250000100A09C042867E0003003E47D00000C4E
+:100260001000609D005004D400006AA80000809C2B
+:10027000C9D0FF07B004A09C1000609C50600AD851
+:1002800028180AD42000609C2C180AD40000609C16
+:10029000841A0AD43C180AD47C180AD478180AD4D0
+:1002A00048180AD41F00609C94180AD40100609C6E
+:1002B000A0180AD40000609C6C190AD40100609C4C
+:1002C000F0180AD4EC180AD40200609CF4180AD47E
+:1002D0000600609CE0180AD40900609CE4180AD467
+:1002E0000D00609CE8180AD43300639CF8180AD407
+:1002F0001800609CFC180AD46400609C00190AD4A1
+:1003000004190AD41800609C08190AD43600609CAD
+:100310000C190AD43200609C10190AD42000609C89
+:1003200014190AD40100609C18190AD40800609CB2
+:100330001C190AD46400609C20190AD42000609C17
+:1003400024190AD428190AD42C190AD43A00609C1A
+:1003500030190AD40000609C101A0AD4D81A0AD4A2
+:100360008C1A0AD4901A0AD4941A0AD4981A0AD465
+:10037000B41A0AD49C1A0AD4A01A0AD4A41A0AD409
+:10038000A81A0AD41E00609CAC1A0AD40100609C12
+:10039000B01A0AD40000609CE01A0AD4E41A0AD405
+:1003A000E81A0AD4F01A0AD4F41A0AD4F81A0AD4A9
+:1003B0001E00609C041B0AD40000609C081B0AD429
+:1003C0000C1B0AD4101B0AD4141B0AD4181B0AD401
+:1003D0001C1B0AD4201B0AD4241B0AD4281B0AD4B1
+:1003E0002C1B0AD4301B0AD4341B0AD4381B0AD461
+:1003F0003C1B0AD40700609C401B0AD40000609C90
+:10040000441B0AD4481B0AD4A0190AD4701B0AD46E
+:10041000741B0AD4781B0AD47C1B0AD4801B0AD410
+:100420000300609C00182EE4080000100000001576
+:100430000000609C6C180AD452FFFF0700006AA8F5
+:10044000040000000000609DFBFFFF030100609CB2
+:100450000000218504004185080081850C00C185CC
+:10046000004800441000219CC0FF219C044801D496
+:10047000085001D40C6001D4107001D4148001D450
+:10048000189001D41CA001D420B001D424C001D400
+:1004900028D001D42CE001D430F001D4000084A98C
+:1004A000000005AAAC008484FF0083A70000C09E62
+:1004B0008002AC840000609C0700809E022884E0DB
+:1004C0003C3001D4383801D444180CD484220CD4E4
+:1004D00034B001D40000A09C00406018ECD063A8A8
+:1004E0000200809C002803D4002030E403000010A8
+:1004F0000700609C0100A09C001830E4030000107D
+:100500000000809C0100809C042065E00000809C2D
+:10051000002003E40600001000000015EC006C84CD
+:10052000002023E40300000C000000154C0081842F
+:100530000040601830C563A81C00AC840100009D19
+:10054000092BD6E0002003D4CC01EC8400406018D5
+:1005500050C063A800408018340884A80000638459
+:100560004C180CD4008004D400406018280863A8FC
+:100570000040801834C584A8062BA6E0003003D4C0
+:100580000400639C0228B6E0002803D48000AC84F9
+:10059000002804D4004027E4060000100000609CFE
+:1005A0000040601838D063A8004003D40000609C6D
+:1005B000001816E48F01001000000015F0026C8492
+:1005C000004023E48B0100104000A09C0040601814
+:1005D0004CC063A800008384430004B90028A8E548
+:1005E0000C00000C000000154C036C8400408018C7
+:1005F00080C184A8FFFFC09C0400089D003004D483
+:100600000028A8E5FCFFFF130400639C4C1B0CD4DE
+:100610000040601858C063A80100E09C14020C9FC1
+:10062000003803D40040401B00205AAB0040C01BE0
+:100630002CC5DEAB0040401A24C552AA00007284CB
+:100640000000C09D080043A500700AE45901000C99
+:10065000000000150040801818C084A800006484C1
+:10066000100063A4007003E4F5FFFF131F00609CFB
+:100670000000809C00181ED400201ED4F9C9FF077A
+:100680000800409DEC020C8500406018002063A823
+:100690009F00C8B85000EC8C00008AA85D00C6B866
+:1006A00098002C850000B8A8003008E1003803D479
+:1006B000830008B900007CA80000C9A8094BE8E045
+:1006C000064BE7E0023808E15ED9FF070000E8A822
+:1006D0000700609C00180BE45301000C00008BAA7B
+:1006E0000000A09CEC2A0CD40000809C0100609CBF
+:1006F000001824E4270100103C00C18400006CA80D
+:10070000000090A83800E1840000B0A8000016A9FD
+:1007100037EEFF0700E001D40700609C00180BE4EF
+:100720004101000C00008BAA00406018080863A873
+:100730000100C09C004080180C0884A8003003D43D
+:100740000000A484003025E42A00000C00000015FD
+:100750000040401A002052AA1402CC9D00406018AC
+:1007600024C563A8000083840000609C080044A5A1
+:1007700000180AE41800001000000015B4036C848F
+:100780000100A39C84038C840600609C001824E470
+:10079000F4000010B42B0CD4B0036C84002803E1E7
+:1007A000A0038C84002088E5E40000100200A8B8B3
+:1007B0000800809E98008C84000068A881D9FF07FB
+:1007C0000000B4A80700609C001814E41701000C96
+:1007D000000074A9004060180C0863A80100809C08
+:1007E0000000A384002025E4DDFFFF1300000015B6
+:1007F000004060180C0863A80000809C002003D40F
+:10080000002036E4C700001000000015EC022C8523
+:100810000000409D3400A184004000194CC008A98C
+:100820000040601850C063A80100A59C00008884A7
+:10083000342801D44C00CC840000A384002884E038
+:100840000000E884023084E00040601840C563A8DE
+:100850004400AC84002089E00038A5E00000C38695
+:100860004000CC84EC220CD400B046E55C00000CC7
+:1008700044280CD43400C1840100809C002026E46C
+:1008800055000010000000157003EC84002027E4E0
+:10089000290000100100C09C50036C843400009DAE
+:1008A0000040A3E449000010B500A09C1800809C03
+:1008B00054036C840080A0180000A5A80080C01814
+:1008C0000400C6A874230CD4002883E00030A3E001
+:1008D0001800C09C003004D400808018080084A850
+:1008E0000020C3E064038C84002005D40080A0189D
+:1008F0000C00A5A8002883E06803AC84002806D477
+:100900000080C0181000C6A80030A3E06C03CC849F
+:10091000003004D400808018140084A80400C09C17
+:10092000002063E0003005D40000809C002003D448
+:100930000100C09C003027E4E8FEFF130000A09CEB
+:100940007C038C840000609C001824E4E3FEFF1309
+:1009500000000015EC026C849F0083B87403EC84E3
+:100960005D0084B85003AC841C00079D002063E048
+:10097000830063B80040A5E40600000C025063E168
+:10098000B500609C7C330CD4D3FEFF03B81B0CD4A1
+:1009900054036C840800A79C003863E0742B0CD4CB
+:1009A0000080E0180000E7A880330CD4003883E012
+:1009B0000400E79C005004D4003863E0005803D4DE
+:1009C000C6FEFF030000A09C7C230CD4D9FFFF03CC
+:1009D000B82B0CD4D7FFFF037003EC8470036C8436
+:1009E0000100C09C003023E48F0000100000609CD8
+:1009F0007C038C84001824E48C000010000074A98F
+:100A000080036C84003023E488000010000000158F
+:100A1000EC026C849F0083B87403EC845D0084B89E
+:100A20005003AC841C00079D002063E0830063B882
+:100A30000040A5E437000010025063E15403AC8489
+:100A40000080C0180000C6A80800279D003865E097
+:100A5000000007A9003083E00080E0180400E7A848
+:100A6000005004D40038C3E000808018000084A83F
+:100A7000005806D40020E5E00080C0181000C6A889
+:100A8000004807D4003085E00080E0181400E7A893
+:100A9000F4FF089D0038A5E0004004D43400E18450
+:100AA00000808018080084A8003805D40020C3E026
+:100AB0001400E09C0080A0180C00A5A8003806D403
+:100AC000002883E05803EC840080C0181000C6A8FA
+:100AD000003804D40030A3E05C03EC84008080186C
+:100AE000140084A8003805D40020C3E06003AC845F
+:100AF0000400849C002806D4002063E00000C09C11
+:100B0000744B0CD4003003D448000000000074A9DA
+:100B1000B500E09C7C330CD443000000B83B0CD4FF
+:100B2000EC022C859F0069B85D0063B8001869E08D
+:100B300039FFFF03830043B988036C840080E01809
+:100B40000000E7A898038C84002063E0001865E0AB
+:100B5000003863E00000038518FFFF0398008C84D1
+:100B6000C0C8FF070000001550008C8C00007CA856
+:100B70000000AEA89800CC84002012D40000E6A8A3
+:100B800030D8FF0700008AA80FFFFF0300008BAAE0
+:100B900000006CA8000090A83800E1840000B0A814
+:100BA00047ECFF07000016A9E0FEFF030000001558
+:100BB000ACC8FF07000000155000EC8C00007CA8BA
+:100BC0000000B8A89800CC8400008AA800381AD485
+:100BD0001CD8FF070000E6A80700609C00180BE483
+:100BE0009DFEFF1300008BAA10000000000074A9F6
+:100BF00098008C84B403AC840300C4B8EC026C8409
+:100C0000062B84E08000639C030084B8022003E18B
+:100C10000030A8E5B5FEFF130100809CB5FEFF0380
+:100C20000100609C000074A9040021850800418532
+:100C30000C0081851000C1851400018618004186D2
+:100C40001C0081862000C18624000187280041877E
+:100C50002C0081873000C187004800444000219C5F
+:100C6000F4FF219C004801D4045001D4086001D451
+:100C700044038384000043A90100609C001824E41D
+:100C80005C0100100000001548036A849C190AD416
+:100C90006400AA850000609C00182DE4510100103A
+:100CA00000000015BC002A85B8006A840A1B69E0B0
+:100CB0008C190AD4980060187F9663A8001849E43C
+:100CC000450100100400C09C8C016A850F00A0182B
+:100CD0004042A5A81800809C03006BB8005863E050
+:100CE000020063B80A2B63E0021884E050210AD4A2
+:100CF00040006A840000809C0A1B6BE0420063B8DD
+:100D0000001884E40D00000C002023E40C00000C0B
+:100D10000100E09C0000A09C0100849C001884E479
+:100D20000700000C0100E09C022063E0002823E49F
+:100D3000FAFFFF13000000150100E09C003864E496
+:100D400003000010000084A9000087A99C010A8507
+:100D5000003828E40B0100100000609C00182DE40E
+:100D6000030100100200809C7C390AD480390AD427
+:100D700084190AD488190AD47300609C7C01EA841F
+:100D80000A1B69E02A00C09C065BE7E0020083B80A
+:100D90000400A3B8001884E00218A5E0050084B898
+:100DA0000200A5B870210AD474290AD40633C3E01E
+:100DB00090390AD40100609C001828E42900001032
+:100DC00078310AD40000609C00182DE42500001042
+:100DD0000300609C0000C09C0A1B67E038390AD4FD
+:100DE00040310AD43C190AD40000809C0A00C09CFF
+:100DF00094210AD498310AD47803000400006AA828
+:100E00008C01CA847800609CC800AA844100E6B8BE
+:100E10000A6303E17C018A840633A5E00000609C3C
+:100E2000063B84E04500A5B8002884E0001808E4EB
+:100E30000A000010D4200AD41F00A09C0028A8E4B7
+:100E400003000010000068A8000065A8062363E006
+:100E5000EB000000030063B8E9000000030064B881
+:100E600088010A850000609C001828E456000010E4
+:100E7000000000159001CA8441006018378963A8FA
+:100E8000001846E41C000010E803809C8001AA843E
+:100E90007701609C0623A5E08401EA84061B67E0D5
+:100EA000062386E00018A5E00A2B84E038210AD446
+:100EB0000000609C001807E40A0000100000001504
+:100EC00038018A84003024E4080000100000001576
+:100ED0000300609C0A1B64E03C190AD40000609C7B
+:100EE000C2FFFF0340190AD4022066E0FBFFFF03A4
+:100EF0000A3B63E08F026018285C63A8001846E490
+:100F000013000010E803609C8001AA84010086B8E9
+:100F1000061BA5E08401EA84003084E0050064B883
+:100F2000001884E07701609C003084E0061B67E0D5
+:100F30000018A5E00A2B84E0030064B8002063E0F9
+:100F4000002063E0DBFFFF0338190AD49919601809
+:100F5000999963A8001846E412000010E803A09CC9
+:100F60008001AA84E803609C030086B8061BA5E004
+:100F70008401EA84003084E0003084E07701609CE2
+:100F8000061B67E00018A5E00A2B84E0010064B8A6
+:100F9000002063E00500A3B8EAFFFF03002863E038
+:100FA00080016A847701809C8401EA84062B63E0D7
+:100FB000062387E0002063E00A1B66E0E2FFFF03F0
+:100FC000062B63E090012A8541006018378963A8E9
+:100FD000001849E41E000010E803C09C8001AA84A8
+:100FE0007701809C0633A5E08401EA84060068B896
+:100FF000004063E0020063B8004063E0004063E04B
+:101000000623E7E00633C9E00038A5E00018A5E0B4
+:101010000A2BC6E038310AD438018A847701A09CB3
+:10102000E803C09C062BA4E0060064B8002063E03F
+:10103000020063B8002063E0002063E00A33A5E00B
+:101040000A3363E0A7FFFF033C290AD48F0260182C
+:10105000285C63A8001849E419000010E803809C8C
+:101060008001CA84060068B80623C6E08401EA84C9
+:10107000004063E0020063B8004063E0004063E0CA
+:10108000010089B8004884E00500A4B8002884E085
+:101090007701A09C004884E0062BE7E00038C6E01A
+:1010A0000018C6E00A3384E0030064B8002063E05F
+:1010B000002063E0D9FFFF0338190AD4991960189A
+:1010C000999963A8001849E419000010E803E09C0E
+:1010D0008001CA84E803809C060068B80623C6E045
+:1010E0008401EA84004063E00300A9B8020063B809
+:1010F0000048A5E0004063E00048A5E0004063E050
+:101100007701809C0623E7E00038C6E00018C6E0BF
+:101110000A33A5E0010065B8002863E0050083B844
+:10112000002063E0E4FFFF03002863E080018A847D
+:101130007701A09C8401CA84063B84E0060068B85D
+:10114000004063E0020063B8004063E0004063E0F9
+:10115000062BC6E0003084E0001884E00A2389E012
+:10116000063B84E0ADFFFF0338210AD484390AD45A
+:1011700080390AD488190AD400FFFF037C210AD4DD
+:1011800000182DE40B000010010088B874006A8478
+:10119000FFFF889C061B64E080390AD484210AD4AE
+:1011A0000018A8E088190AD4F4FEFF037C290AD4A9
+:1011B0007400AA84FEFF649CFFFFC49C062B63E0BE
+:1011C00080390AD484310AD4001884E0EBFFFF038D
+:1011D00088190AD48C016A85C6FEFF0350310AD4EF
+:1011E000B8006A84BC002A85B1FEFF03010063B821
+:1011F00070008A84A7FEFF039C210AD4D101809C41
+:101200003C01AA840A2383E068290AD40000609C78
+:10121000410084B86C190AD4010065B854210AD47D
+:10122000002863E064190AD4000021850400418588
+:1012300008008185004800440C00219C000003A99F
+:10124000A00163840100C09C003023E45000000C26
+:101250000000E4A89C01A884003025E426000010CA
+:101260000000609C64008884001824E41C000010C6
+:10127000000000157C3108D4803108D4841908D4CA
+:10128000881908D4BC00A8847300609C0A1BA5E0E0
+:101290008C0188847C01E8849401C8840623E7E0FB
+:1012A000020065B8002863E0050063B8701908D42F
+:1012B0002A00609C040085B80038C6E0022884E05B
+:1012C000903108D4061BA5E0020084B8943108D4FC
+:1012D000742108D42E000000782908D4843108D461
+:1012E000881908D4803108D40200609CE6FFFF030F
+:1012F0007C1908D464008884001824E415000010C8
+:101300000200809CFFFFA59C803108D40200609CF5
+:10131000001827E40B000010842908D474006884A6
+:10132000061B65E0881908D48401888480016884DC
+:101330008801A884002063E0EDFFFF03002863E03C
+:1013400074008884062365E0F7FFFF03002063E054
+:101350000100A5B8803108D4FFFF659C002027E478
+:1013600006000010841908D474008884FEFF659C70
+:10137000EDFFFF03062363E074008884FEFF659C95
+:10138000062363E0F1FFFF03010084B80048004436
+:1013900000000015F4FF219C004801D4045001D442
+:1013A000086001D40000A3A9000024A9C801638437
+:1013B0000000809C002023E4540100100100609C88
+:1013C000B4004D8500182AE44E01001000000015FD
+:1013D000A0018D8500182CE4BE000010001809E45F
+:1013E000001809E4B7000010001849E5AA00001031
+:1013F0000200609C002009E4A1000010000000151C
+:101400004000CD845C016D840000809C0A3363E061
+:101410000000AD84002025E49700001058190DD479
+:10142000D0008D84C4006D84001864E58C00001029
+:1014300000000015C000AD84AC180DD40100609C04
+:1014400000182CE4840000100500609CAC00ED84C2
+:101450000018A7E57A0000100400809C50016D84FC
+:10146000FFFF879C0020A3E503000010000000158B
+:10147000000064A8C4180DD40018A5E503000010EE
+:10148000000085A8000083A8C4200DD40200609C41
+:10149000001809E4680000100000609CB000CD84D2
+:1014A000001826E4610000100100609C0000209DEF
+:1014B000EC480DD4F0480DD4080066B809008AB88D
+:1014C0000800A5B8C400CD84041884E0004060186A
+:1014D000A0C563A8043884E00430A5E0002003D44C
+:1014E000CC002D850C00639C002803D4C8008D849B
+:1014F0000400639C002003D41C01ED840400639C61
+:10150000FC00AD841C00E7B8004803D46001CD8422
+:101510001000A5B81000639CD4002D851000C6B83B
+:101520000428E7E0F0008D8458010D850C0084B894
+:10153000004803D40440C6E000406018BCC563A85E
+:101540000420E7E0003003D454018D840400639C40
+:1015500004012D85002003D4100029B910016D84E9
+:101560000801AD84041829E1EC008D850428E7E02A
+:1015700000406018C8C563A8F400CD8407004CB9CA
+:101580000800C6B8003803D42C010D850450C6E00D
+:101590000400639C1801AD84100008B920018D84FB
+:1015A0001000A5B830014D85080084B8004803D468
+:1015B000045008E10400639C28016D850420A5E027
+:1015C000004003D40C018D840800639C0458C6E0DD
+:1015D0000001ED8424012D850800E7B8003003D414
+:1015E0000448A5E00400639C0420E7E0002803D43D
+:1015F00000408018E0C584A814016D84F800AD8413
+:10160000080063B8003804D4042863E00400849C14
+:101610000040A01824D0A5A8001804D4006005D468
+:10162000BA00000000000015EC180DD4A3FFFF0362
+:10163000F0180DD49EFFFF03B000CD840020A5E577
+:1016400003000010000065A8000064A890FFFF03DD
+:10165000C4180DD48EFFFF03AC00ED84C000AD8430
+:101660000028A4E575FFFF13000064A873FFFF03C3
+:10167000000065A872FFFF03C000AD843C016D84CB
+:101680004000CD84E4008D845C190DD45EFFFF031F
+:1016900060210DD4001809E4050000100700609CCB
+:1016A000001809E457FFFF0F0000001538016D8492
+:1016B0004000CD845C190DD4F5FFFF03E0008D845C
+:1016C0004000CD8440016D84F0FFFF03E8008D846D
+:1016D0007E000010001849E51B000010002009E4FE
+:1016E00048FFFF0F0000001594010D85002048E51C
+:1016F000080000100300A8B84000CD840000A6A890
+:10170000E4006D845C290DD43FFFFF0360190DD404
+:101710008401CD848801ED84030066B80040A5E013
+:10172000020087B8003063E00040A5E0003063E0CD
+:10173000003884E04000CD84002063E0F1FFFF0327
+:101740000A1BA5E00200609C001809E405000010D7
+:101750000700609C001809E42AFFFF0F0000001535
+:1017600094016D8500204BE5060000100000001577
+:1017700040006D845C190DD4D0FFFF034000CD8480
+:1017800041006018378963A800184BE4100000106E
+:10179000E803C09C80016D847701809C063363E080
+:1017A0008401ED84BB00A09C88010D850623E7E041
+:1017B000062B08E1003863E00633CBE0004063E02D
+:1017C0000A1BC6E0EDFFFF035C310DD48F026018E9
+:1017D000285C63A800184BE416000010E803609C26
+:1017E0008001CD8401008BB8061BC6E084010D8505
+:1017F000005884E0BB00A09C8801ED84050064B81B
+:10180000062BE7E0001884E07701609C005884E034
+:10181000061B08E10040C6E00038C6E00A3384E059
+:10182000030064B8002063E0D3FFFF03002063E0FF
+:1018300099196018999963A800184BE416000010D4
+:10184000E803009D8001CD84E803609CBB00A09C60
+:10185000061BC6E084010D8503008BB88801ED846A
+:10186000005884E0005884E07701609C062BE7E094
+:10187000061B08E10040C6E00038C6E00A3384E0F9
+:10188000010064B8002063E00500A3B8E7FFFF0390
+:10189000002863E080016D847701809C8401ED84E1
+:1018A000064363E0BB00A09C8801CD840623E7E0EB
+:1018B000062BC6E0003863E0003063E00A1B6BE0F3
+:1018C000ADFFFF03064363E09401AD84002045E5CE
+:1018D00005000010000000154000CD847BFFFF03D1
+:1018E000000066A884016D8488018D84010063B8BE
+:1018F0004000CD84001884E074FFFF030A2365E0F4
+:1019000055FFFF03C000AD84000021850400418520
+:1019100008008185004800440C00219CF4FF219CB4
+:10192000004801D4045001D4086001D4000043A948
+:101930000000E4A800406018D4C563A8A0018A8410
+:101940000100C09C000003850040601850C063A8DF
+:101950000000A38444006A84003024E46B0000107B
+:10196000002823E140006A841000809C091BA8E045
+:10197000002065E5030000100000609C0000A4A8A2
+:10198000001885E5070000100000609CFF03809CA4
+:101990000020A5E503000010000065A8000064A871
+:1019A00008190AD4FC180AD41000609C001825E419
+:1019B0003D0000100008609C1900609C04190AD4C6
+:1019C00010190AD454016A840000809D5C018A8445
+:1019D000004863E00220A3E0006065E5030000101A
+:1019E000000000150000A09CB0016A848C018A846C
+:1019F000004863E0022063E054290AD4B0190AD4F5
+:101A0000006063E503000010000083A80000809CD4
+:101A100094026A84006003E41F00000CB0210AD421
+:101A200054018A846801AA84002864E40800001034
+:101A3000000000156C016A84022085E0002063E04C
+:101A400054290AD45C0000006C190AD46401AA84E9
+:101A50000028A4E458000010000000156C016A84FE
+:101A6000006003E4540000100228C4E00030A3E446
+:101A70000400001000000015F2FFFF03023063E0D5
+:101A8000021864E00000809C54190AD44A00000047
+:101A90006C210AD4B500000400006AA8E2FFFF032D
+:101AA00054018A840000809C092B63E0002083E5B8
+:101AB00014000010FF01809C0020A3E5030000102B
+:101AC00000000015000064A804190AD40000809CDE
+:101AD0000008609C092B63E0002083E507000010EC
+:101AE000FF01809C0020A3E5B6FFFF130000001556
+:101AF000B4FFFF03000064A8B2FFFF030000609C76
+:101B0000F2FFFF030000609C94016A84004080188B
+:101B1000B8C584A800008484024863E098210AD4F0
+:101B2000003007E41D00001094190AD4003047E586
+:101B30000D0000100200609C0000609C001807E48B
+:101B4000A1FFFF0F0000001598018A84064B84E076
+:101B500084016A84FFFF639C84190AD49AFFFF03FF
+:101B600074210AD4001807E4050000100700609CE7
+:101B7000001807E494FFFF0F0000001598018A8405
+:101B8000064B84E080016A84FFFF639C80190AD4BD
+:101B90008DFFFF0370210AD498018A84064B84E0EC
+:101BA00088016A84FFFF639C88190AD486FFFF03BB
+:101BB00078210AD400406018B8C563A80000638487
+:101BC000D0180AD4000021850400418508008185D1
+:101BD000004800440C00219CF8FF219C004801D4DF
+:101BE000045001D40000809C000043A9B02103D41C
+:101BF000C02103D4C42103D438018384A42103D495
+:101C00003C0183841B000004A82103D494028A842D
+:101C10000100609C001824E40B0000100200609C8E
+:101C2000B401AA840500609C0A00809C0300C5B82A
+:101C3000091BA5E00923C6E0BC290AD4090000005D
+:101C4000B8310AD4001824E4060000100500609C96
+:101C5000B4018A84B8210AD4091B84E0BC210AD4C7
+:101C60000000218504004185004800440800219CB3
+:101C70000000A3A81600809C60006384F7FF639CAB
+:101C8000002043E43100001000000015020063B89A
+:101C900004008018546F84A8002063E0000083844F
+:101CA0000020004400000015AF00609CAC1905D472
+:101CB000940285840100609C001824E40E0000104A
+:101CC0000200609C5C008584001824E4070000107A
+:101CD00000000015AC016584DC05809C062363E0F0
+:101CE00020000000B41905D4AC016584FCFFFF039B
+:101CF000B004809C001824E41A00001000000015B5
+:101D00008C026584F7FFFF030A0063B85E01809CC4
+:101D1000E8FFFF03AC2105D4E5FFFF03F401609C5D
+:101D2000FCFFFF03E803809CE1FFFF03D007609CFA
+:101D3000F8FFFF03D007809CDDFFFF03A00F609C2E
+:101D4000F4FFFF03A00F809CD9FFFF03B036609C17
+:101D5000D7FFFF031027609CEEFFFF03B036809C87
+:101D60000048004400000015B001A384000083A8CF
+:101D7000B8016384001885E5050000100000609C30
+:101D8000C41904D40B0000000100609CBC016484F1
+:101D9000001845E5050000100100609CC41904D43A
+:101DA000040000000000609C0000609CC41904D482
+:101DB000C81904D4C01904D4004800440000001518
+:101DC0000000609DFFFF639C005823E40600000CA8
+:101DD0000000809C410063B8002023E4FEFFFF1355
+:101DE00001006B9D0048004400000015F0FF219C9D
+:101DF000004801D4045001D4086001D40C7001D40F
+:101E0000020080185C6784A8000043A9002083E1D9
+:101E100000008C84C05900043800C48500006AA802
+:101E2000BD59000414580ED40400609C0018ABE5A2
+:101E30000300001000000015FBFF6B9D0018ABE5D0
+:101E4000060000100100C09C0800A01800E2A5A830
+:101E500000286AE0003003D40800E0184CE6E7A848
+:101E60000000AC8400388AE00100C09C0C580ED4FD
+:101E700000006484003003E44D000010185805D4BD
+:101E80000800601830ED63A800188AE00000648440
+:101E9000003023E415000010000000150200609CD3
+:101EA00000182BE40F000010000000150800E018D7
+:101EB0002CEDE7A800386AE00000E09C003003D475
+:101EC000003804D45C3805D4883805D48C3805D45F
+:101ED000A83805D4643805D4B43805D4603805D49E
+:101EE000000064840100C09C003023E40C0000105A
+:101EF0000000809C0800801800E284A80800A01858
+:101F00000CE9A5A800206AE0003003D400288AE08C
+:101F1000AB00C09C4E000000003004D400006C8474
+:101F20001800A384002025E40A000010000000151A
+:101F30000800E0182CEDE7A800388AE0000064846F
+:101F4000003023E4030000100000609C001804D45B
+:101F500000008C840100A09C18006484002823E405
+:101F60001300001000000015080080182CED84A854
+:101F700000206AE000008384002824E40C000010A4
+:101F8000000000150800C01800E2C6A80800E0180C
+:101F90000CE9E7A800306AE000388AE0002803D4A2
+:101FA000AB00609C2A000000001804D400006C8480
+:101FB0000100A09C18008384002804E42200001083
+:101FC000002844E51B0000100200609C0000609C9B
+:101FD000001804E4030000100200A09C0400A09C70
+:101FE0000800C01800E7C6A800308AE0000064843A
+:101FF0000018A5E50300001000000015002804D417
+:102000004559000400006AA8FF00609C0018ABE579
+:102010000F0000103C5B0ED40800E01800E2E7A8B7
+:102020000100809C00386AE009000000002003D411
+:10203000001804E4EAFFFF0F00000015E9FFFF03AA
+:1020400000000015E7FFFF030300A09C00002185AE
+:1020500004004185080081850C00C18500480044CA
+:102060001000219CDCFF219C004801D4045001D4C5
+:10207000086001D40C7001D4108001D4149001D4F4
+:1020800018A001D41CB001D420C001D4000083A941
+:10209000020060185C6763A80018CCE10000CE84E1
+:1020A000FF00609C380006863C0390840018A4E57D
+:1020B0002C00000C8404609C0300001960F308A944
+:1020C000061BA4E00000E09C00288CE0004084E0B7
+:1020D00000006484003823E42200000C1F00809C70
+:1020E0000300001968F308A9004065E000186CE0DF
+:1020F0000000A3840020A5E41A00000C010065B8CC
+:1021000002000019606708A9002863E00A0063B8AC
+:1021100000186CE0004063E000008384003824E491
+:102120001000000C0000001508000019E87B08A949
+:1021300000404CE200001285003808E4090000105D
+:102140000000001508006018E47B63A80018CCE2CA
+:1021500000007684003823E4080000100000001519
+:102160000800801800E284A80100A09C00206CE018
+:10217000AD010000002803D4F00368840200A01819
+:10218000C45BA5A80400639C002886E01F0063A42C
+:102190000000A484020063B800408018000384A8F3
+:1021A000002063E000006384003805E403000010B1
+:1021B000681806D4581806D41C086884003803E44C
+:1021C000870100100000A09C6C2806D42C2806D49F
+:1021D000000092840000C09C0000AE84200864844B
+:1021E0002C008584003003E407000010102010D478
+:1021F0006C006584003023E403000010000000152B
+:102200000100C09C00004E8502000019C45B08A9B3
+:102210000000809E00408AE03C3005D400006484C9
+:1022200000A003E46701000C000000150000928488
+:10223000F403648400A023E41900001000000015DA
+:10224000F80364840040A0180003A5A80400639C60
+:10225000000096841F0063A4020063B800004E854E
+:10226000002863E0D803A484000063840100809CFC
+:10227000002025E40600001074180AD46C006A845B
+:1022800000A023E44B01000C0000001500006E8448
+:102290000000C09C783003D4000092840100809E2E
+:1022A000F403648400A023E407000010000000157C
+:1022B000FC0364840000009F00C023E42801000C9C
+:1022C00000000015000072840100809CF403A384C8
+:1022D000002025E4050000100000809C00006E84B2
+:1022E000802003D47C2003D4000096840000409E0C
+:1022F0007C046484009003E41301000C00000015CA
+:1023000000004E850100C09C18006A84003023E460
+:10231000060000100000001500406018040363A8C8
+:102320000000638414180AD4540464840100639C7C
+:102330001800AA8444180AD4580484840100849C98
+:10234000003045E4FC00001048200AD4004060182A
+:10235000040363A80000638500900BE4B800000C40
+:10236000000000150800C01800E2C6A800304CE2CA
+:1023700000008E840100409D18006484005003E436
+:10238000030000100000009D484004D47C010004BC
+:1023900000006CA8000072840000A09C002803E4E8
+:1023A0002101000C000000150000D6845C04668446
+:1023B000002803E4070000100000001500006E84F0
+:1023C00018008384002824E40B00000C0000001592
+:1023D00060046684005023E409000010000000152A
+:1023E00000006E8418008384005004E40500000C93
+:1023F000000000153902000400006CA800006E8483
+:1024000002008018C85B84A80000409D002063E0A3
+:1024100000008384005004E48500000C0000609CF0
+:10242000000076840C008384005004E4080000104F
+:102430000000001500004E850200809E18006A848E
+:1024400000A003E46A00000C0000001500006E8488
+:1024500002008018005C84A80000A09C002063E0BB
+:10246000002803D46058000400006CA80000D68443
+:102470003300809C64046684005863E00000AE84EE
+:102480001A00639C081805D4085810D40020A3E44F
+:1024900004000010041810D40100009D004012D464
+:1024A000180065840100409DFDFF639C005043E4DB
+:1024B000070000101B00A09C080080180CE984A8ED
+:1024C000005012D42BFFFF0300206CE074048684BC
+:1024D0000000609C001804E43300000C0000009D24
+:1024E000304310D4384310D4344310D40000B684A1
+:1024F0000000609CDC038584001804E410000010D8
+:102500000200609CE00385840018A4E40C00001025
+:102510000500609C001844E4090000100100A09C24
+:10252000080080180CE984A800206CE01B00C09C07
+:10253000002812D4BC000000003003D400006E84D8
+:1025400002000019DC5B08A90200C018D45BC6A811
+:10255000004083E06C00A384003003E11400C69CBB
+:102560000100A59C003023E10000C4840A2BA6E0F2
+:1025700002008018E05B84A80020E3E0000088846B
+:1025800002000019E45B08A9004063E00633C4E0E0
+:10259000002807D4062B84E0003009D4A2000000F4
+:1025A000002003D4DC57000400006CA800500BE4AA
+:1025B0000600000C305B10D40000C09C343310D4F3
+:1025C000CBFFFF03383310D40758000400006CA879
+:1025D00001006BB900006CA803580004345B10D4F0
+:1025E00001006BB9C2FFFF03385B10D40200A018D2
+:1025F000005CA5A800006CA8C757000400284AE1A9
+:1026000000006E840200C018005CC6A800580AD4FE
+:10261000003063E00000838400A0A4E592FFFF1374
+:102620000100009D90FFFF03004012D4130300043B
+:1026300000008CA87CFFFF0300007684B6570004DE
+:1026400000006CA80000AE8401006B9D6C00C58486
+:10265000009006E40700001044580AD44400858422
+:102660002000609C001844E50900001000000015DF
+:10267000009026E42C0000101000609C440085842B
+:10268000001844E52400000C000000150800A01804
+:1026900000E2A5A80100C09C00284CE2003012D442
+:1026A00000004E850100609C18008A84001824E414
+:1026B00030FFFF13000000159757000400006CA8BE
+:1026C0000000AE8401006B9D0000E09C6C00C5849E
+:1026D000003806E40700001048580AD448008584F2
+:1026E0002000609C001844E5090000100100809C57
+:1026F000003826E41FFFFF131000609C480085840B
+:10270000001844E51BFFFF0F0100809C19FFFF0329
+:10271000002012D40800601800E263A8E1FFFF0364
+:1027200000184CE20800001900E208A9DDFFFF03D1
+:1027300000404CE20800A01800E2A5A80DFFFF032E
+:1027400000284CE200004E857357000400006CA87E
+:1027500000009684EBFEFF0354580AD400004E8517
+:10276000A157000400006CA800007684D80383847D
+:1027700000A024E4070000107C580AD400004E8515
+:102780006C006A8400C023E40600000C0000001501
+:1027900000006E840000009DD4FEFF03804003D43F
+:1027A0009157000400006CA8D0FEFF0380580AD4A3
+:1027B0008D57000400006CA8B8FEFF0378580AD4B7
+:1027C00002006018CC5B63A800184AE1525700046D
+:1027D00000006CA896FEFF0300580AD40040801841
+:1027E000040384A800000485003808E40B000010EE
+:1027F0006C4006D400008484003804E40500001016
+:10280000702006D40200609C72FEFF032C1806D4D0
+:10281000FEFFFF030100609C0000609CFBFFFF03C4
+:10282000701806D4000021850400418508008185C8
+:102830000C00C185100001861400418618008186B5
+:102840001C00C18620000187004800442400219C10
+:10285000F8FF219C004801D4045001D42CC8FF0784
+:10286000000043A90800601880E263A80018EAE0AD
+:102870000000C09C00008784003024E403000010A6
+:102880000000009D0100009D0200609C001824E4EF
+:10289000030000100000A09C0100A09C042868E038
+:1028A000003003E412000010000000150200801840
+:1028B0005C6784A800206AE0000083841800A48478
+:1028C000003025E40A0000100100609C00408018E0
+:1028D000000A84A80040A0185408A5A8001804D431
+:1028E0000000658421000000010063A800006784E7
+:1028F0000100C09CFFFF639C003043E41200001005
+:1029000000000015020080185C6784A800206AE0BF
+:10291000000083841800A484003025E40A0000101D
+:102920000000001500408018000A84A80040A0188C
+:102930005408A5A8003004D4000065840B000000F2
+:10294000043063E000408018000A84A80000609C06
+:102950000040A0185408A5A8001804D400006584FD
+:10296000FEFF809C032063E0001805D40000218551
+:1029700004004185004800440800219CE0FF219CA0
+:10298000004801D4045001D4086001D40C7001D473
+:10299000108001D4149001D418A001D41CB001D42B
+:1029A000000043AA0000C09C020060185C6763A896
+:1029B0000018D2E2000096840200609C1800A484F3
+:1029C000001805E403000010380084860100C09C54
+:1029D0000400609C001805E4030000100000809CC7
+:1029E0000100809C032066E00000809D006003E4FD
+:1029F000300000100000001500406018040363A8B8
+:102A0000000083840100609C202014D4001824E47A
+:102A10007100000C000044A900600AE425000010C9
+:102A2000000000150000009E2801D49DBA56000445
+:102A3000000072A800008BA91F00609C001850E5E0
+:102A40000A000010FC5EEED70100809C00204BE4E1
+:102A50005D00000C000072A80200809C00202BE4A6
+:102A60005500000C000000150000A09C0100109E05
+:102A70000400CE9D0300609C00180CE403000010CD
+:102A80000000809C0100A09C2000609C001850E584
+:102A900004000010032085E00100809C032085E0F5
+:102AA0000000609C001824E4E1FFFF130000001503
+:102AB000000096840100A09C18006484002823E490
+:102AC000490000100000001500406018040363A8CE
+:102AD00000008384A82114D4002824E43200000CD0
+:102AE000000044A90000609C00180AE43E000010A9
+:102AF000B002949D0000009E87560004000072A85A
+:102B000000004BA91F00609C001850E50A0000104F
+:102B1000FC5EECD70100809C00204BE41E00000C02
+:102B2000000072A80200809C00202BE41600000C1C
+:102B3000000000150000A09C0100109E04008C9D68
+:102B40000300609C00180AE4030000100000809C51
+:102B50000100A09C2000609C001850E504000010BB
+:102B6000032085E00100809C032085E00000609C3C
+:102B7000001824E4E1FFFF13000000151A00000014
+:102B8000000000156456000400000015EAFFFF0372
+:102B900000580CD46056000400000015E6FFFF0347
+:102BA000805FECD75AC7FF0700000015CFFFFF0377
+:102BB0000000609C5856000400000015ABFFFF03A6
+:102BC00000580ED45456000400000015A7FFFF0360
+:102BD000805FEED74EC7FF07000000158FFFFF0391
+:102BE0000000001500002185040041850800818552
+:102BF0000C00C185100001861400418618008186F2
+:102C00001C00C186004800442000219CFCFF219C40
+:102C1000004801D44800A3850000C3A84400638491
+:102C200000186DE5030000100000609D0000A3A9DE
+:102C30001F00209E0000E09D0400609E00686BE580
+:102C4000030000100000809C0100809C00884BE580
+:102C50001B0000100000609C190000000100609C37
+:102C60000000A09C0000209D005863E00100009D32
+:102C7000069B63E00200E09C003063E04402839C1A
+:102C8000004825E40C00001000000015BC0066841C
+:102C9000081868E00100A59C001804D4801EE4D741
+:102CA0000038A5E5F7FFFF130400849CE4FFFF0351
+:102CB00001006B9DF7FFFF03C0006684031864E00A
+:102CC000007823E4E7FFFF1301006BB800002185C3
+:102CD000004800440400219CACFF219C004801D422
+:102CE000045001D4086001D40C7001D4108001D4C8
+:102CF000149001D418A001D41CB001D420C001D478
+:102D000024D001D428E001D42CF001D40200801892
+:102D10005C6784A80800A018E87BA5A8002083E3CE
+:102D20000028A3E000005C85501801D4FA55000487
+:102D3000482801D44800C1840000609C00008684BB
+:102D4000BC580AD42000A484001805E43801000C03
+:102D5000000000150000609D00007C84500081840C
+:102D60004C5801D4385801D4345801D4A8FFFF0777
+:102D7000305801D400001C85440068844C00A185B3
+:102D800000186DE5030000100000A09C0100A09C4D
+:102D90004C00C1841F00609C001846E50300001031
+:102DA0000000809C0100809C032065E00000A09C46
+:102DB000002823E47F00000C0100C09C0040601844
+:102DC000040363A800008384002804E46300000C6B
+:102DD0000100209DBC00E88401006019C4326BA989
+:102DE0003000A185083869E00000809C0040CDE0FB
+:102DF0000058ADE0C41806D40000A09D002848E1AA
+:102E00000700609C001827E403000010C46926D462
+:102E1000000089A800200AD448008184000064844E
+:102E20002000A3840000809C002005E431000010F5
+:102E3000380081843800A18400408018040384A8ED
+:102E400001006019C8326BA9020065B83400C18462
+:102E50000100409FC800439E0200A6B80000C4873E
+:102E6000005803E2C800059FC809C39D0058C5E289
+:102E7000C809859E500061840100409D0000809C2F
+:102E800000201EE42700000C0000209D00007C8430
+:102E9000C000C3840090E3E00070A3E0008003E181
+:102EA00008308AE00000609C001805D40700609C90
+:102EB000001826E403000010002007D400002AA90F
+:102EC000004808D40400109E0400CE9D0400529EC9
+:102ED0000400D69E0400949E01005A9F0200609C4C
+:102EE0000018BAE5E4FFFF130400189F380081843E
+:102EF0003400A1840300849C3000C1840300A59C9D
+:102F00004C0061850C00C69C01006B9D382001D4EB
+:102F1000342801D4303001D497FFFF034C5801D43A
+:102F2000B155000400005C8500C04AE100009C85AA
+:102F30005000618400A08CE1AB55000400580AD415
+:102F400000007C840000A09D00B063E000580CD419
+:102F5000DDFFFF03006803D43000A185C4004D9D50
+:102F600050006184A0550004005048E130006184A5
+:102F700000009C85C409839C5000618400208CE182
+:102F80009955000400580AD43000A1840100C018EB
+:102F9000C432C6A800007C84003085E000580CD400
+:102FA000002063E00000609D9CFFFF03005803D4F5
+:102FB00018006884003023E4A200001050006185EE
+:102FC0000800A019E47BADA900686BE000008384D1
+:102FD0006004A484003025E49A0000100000609C86
+:102FE0004C1801D4441801D4401801D43C1801D421
+:102FF00000001C85480068844C00A18500186DE520
+:10300000030000100000A09C0100A09C4C00C184A3
+:103010001F00609C001846E5030000100000809C23
+:103020000100809C032065E00000A09C002823E4B0
+:103030008400000C0000001500406018040363A821
+:1030400000008384002804E46300000C0100209D3C
+:10305000BC00E8840100601944346BA93C00A184E1
+:10306000083869E00000A09D0040C5E00000809C99
+:103070000058A5E0441A06D4446B26D40700609C8F
+:10308000001827E403000010002848E1000089A888
+:1030900000200AD448008184000064842000A384B6
+:1030A0000000809C002005E4310000104400818471
+:1030B0004400A18400408018040384A80100601922
+:1030C00048346BA9020065B84000C1840100409FEC
+:1030D0004802439E0200A6B80000C487005803E2DD
+:1030E0004802059F480BC39D0058C5E2480B859ECA
+:1030F000500061840100409D0000809C00201EE47F
+:103100002700000C0000209D00007C84C000C384C8
+:103110000090E3E00070A3E0008003E108308AE063
+:103120000000609C001805D40700609C001826E48D
+:1031300003000010002007D400002AA9004808D48A
+:103140000400109E0400CE9D0400529E0400D69EF2
+:103150000400949E01005A9F0200609C0018BAE58A
+:10316000E4FFFF130400189F440081844000A18401
+:103170000300849C3C00C1840300A59C4C00618535
+:103180000C00C69C01006B9D442001D4402801D452
+:103190003C3001D497FFFF034C5801D41255000472
+:1031A00000005C8500C04AE100009C8550006184FD
+:1031B00000A08CE10C55000400580AD400007C8467
+:1031C0000000A09D00B063E000580CD4DDFFFF03B9
+:1031D000006803D43C0081844402449D5000618413
+:1031E00001550004005048E13C00A18400009C858A
+:1031F000440B859C5000618400208CE1FA5400044B
+:1032000000580AD43C00C1840100A0194434ADA97F
+:1032100000007C84006886E0002063E000580CD445
+:103220000000809C9CFFFF03002003D400005C850D
+:10323000B954000450006184C7FEFF03C0580AD48B
+:103240000000218504004185080081850C00C185AE
+:103250001000018614004186180081861C00C1867A
+:103260002000018724004187280081872C00C18726
+:10327000004800445400219CC8FF219C004801D410
+:10328000045001D4086001D40C7001D4108001D422
+:10329000149001D418A001D41CB001D420C001D4D2
+:1032A00024D001D428E001D42CF001D4341801D466
+:1032B000000044AA020060185C6763A80200C018FE
+:1032C000C45BC6A80018C4E30000BE840000809C54
+:1032D000003065E0302001D4000083840000609C51
+:1032E000001804E40F0000100100609C2800C69C38
+:1032F00000406018040363A8003085E00400C69C09
+:103300000030A5E00000C384003004D400006384D2
+:103310000200809C001805D47D000000302001D4FC
+:103320000200C018F45BC6A8301801D40030A5E034
+:1033300000406018040363A800006384001805D4EB
+:10334000000083A80000609C001804E470000010D6
+:103350000000809F000052AB000012AB0000D2AA18
+:10336000340081840000C09C003004E45C00001044
+:103370002005969D000072A8675400040100C09DBE
+:1033800000004BA900580CD400702BE4030000107F
+:103390000000809C00008EA80300809E00A02AE40C
+:1033A000030000100000609C00006EA8041864E098
+:1033B0000000009E008003E44500000C00000015A2
+:1033C0000200609C00182AE43D00000C000000157B
+:1033D00000A02AE4030000100000A09C0000AEA89A
+:1033E0000600609C00182AE4030000100000809C86
+:1033F00000008EA8042065E0008003E42C00000C8F
+:10340000000000150400609C00182AE42400000C51
+:103410000000001514005A9F1400189F1400D69E37
+:1034200001009C9F00800AE4030000100000A09CA3
+:103430000000AEA81F00609C00185CE503000010AF
+:103440000000809C00008EA8032065E0008023E43B
+:10345000C4FFFF1334006184008003E40400001003
+:10346000000000152A0000001CE512D400007E8434
+:1034700002008018605C84A8002063E00000638480
+:103480000100809C002043E421000010020063B88A
+:10349000009063E01E00000014E003D41E540004FA
+:1034A000000072A8DCFFFF0310580CD41A5400046B
+:1034B000000072A8D4FFFF030C580CD4165400046B
+:1034C000000072A8C3FFFF0308580CD41254000474
+:1034D000000072A8BBFFFF0304580CD400007E84D8
+:1034E00002008018605C84A8002063E000008384F0
+:1034F000003004E404000010000000159EFFFF03EC
+:103500009C02989D9CFFFF031C009A9D30006185E2
+:103510000000218504004185080081850C00C185DB
+:103520001000018614004186180081861C00C186A7
+:103530002000018724004187280081872C00C18753
+:10354000004800443800219CFCFF219C004801D425
+:103550000000C4A8000003A908008018E87B84A824
+:103560000100209D0020A6E100008D84F803648402
+:103570000400639CF4038484004804E4CC0000103D
+:103580000818E9E0004884E4600000100200609C34
+:10359000001804E4070000100100809C0800A01837
+:1035A00014E2A5A8002866E081010000002003D4F1
+:1035B0000200A018C45BA5A8002888E0000064846D
+:1035C0000000A09C002803E4140000100000001577
+:1035D00068006884A82808D4602808D45C2808D427
+:1035E000642808D4002803E407000010B42808D495
+:1035F0000800801814E284A8002066E06C01000036
+:10360000004803D4A8006884B81808D468008884E7
+:1036100067010000A42008D402008018F85B84A889
+:10362000002068E000008384002804E40400001007
+:103630000000A09CA42808D4B82808D46800C88436
+:10364000A4006884001866E42D0000100000001536
+:1036500002008018D05B84A8002068E0B80088844D
+:103660000000A384002884E0A82008D4A80068846F
+:103670000200A018C85BA5A8002888E00030C3E0BD
+:103680000000A4840000609C001825E41A000010CB
+:10369000943008D4010066B8FFFF639CB41808D4C6
+:1036A0000000809C6C006884002023E40700001068
+:1036B00000000015B40068845C1808D4641808D4AD
+:1036C000D1FFFF03601808D470006884002023E451
+:1036D0000600001000000015B40068845C1808D4CF
+:1036E000C9FFFF03641808D4B4006884FDFFFF031A
+:1036F000601808D4EAFFFF03010066B8B800A88488
+:10370000DBFFFF03A82808D40200A018C45BA5A80B
+:10371000002888E0000064840000A09C002803E4E6
+:103720001100000C0000001502008018F85B84A84E
+:10373000002068E000008384002804E40C000010EE
+:103740000000001502008018FC5B84A8002068E0DF
+:1037500000008384002804E4510000100000609CF5
+:103760000000A09C882808D48C2808D47400C88441
+:103770008C00A884002866E43C000010410087B853
+:10378000023065E0002083E43800001000000015DE
+:1037900088006884003863E0901808D46C0068845E
+:1037A0000000809C002023E422000010000000158F
+:1037B0009000888478006884003084E0001864E019
+:1037C0005C2008D40020A3E503000010601808D492
+:1037D000000064A8B41808D4641808D4B40068843D
+:1037E000641808D468008884A4006884001804E47D
+:1037F0000300001000000015A42008D40200801867
+:10380000C85B84A8002068E00000A3840000809CBE
+:10381000002005E4E6000010000000159000A884D8
+:1038200074006884882808D4E10000008C1808D44B
+:1038300070006884002023E40700001000000015D9
+:1038400090006884003063E0B41808D4E4FFFF03FC
+:103850005C1808D490006884003063E0B41808D481
+:10386000DFFFFF03601808D40028A6E40900001059
+:10387000410087B8022866E00020A3E4050000109C
+:103880000000001588006884C4FFFF03023863E06D
+:103890008800A884C2FFFF03902808D45C008884B5
+:1038A0008C2008D4B2FFFF03881808D40200A018A7
+:1038B000C45BA5A8002888E0000064840000A09CE8
+:1038C000002803E4A1000010000000156800E8844F
+:1038D000002807E447FFFF0FA82808D400006D84E4
+:1038E0000000809C0804A384002005E4040000106C
+:1038F0000000609CA8006884003863E00200801823
+:10390000C85B84A8941808D4002068E2000073847F
+:103910000000809C002023E48A00001000000015B5
+:103920009400C884002006E4060000100000609C9B
+:10393000FFFF669C941808D40000C3A80000609C98
+:103940000000AD84AC1808D408048584001804E491
+:103950001C0000100000609C000065A90000209D74
+:10396000FF00209E0000E09D0C04A59C08046B84D1
+:103970000000E09C001869E5030000100000809C36
+:103980000100E09C008849E504000010032067E086
+:103990000100809C032067E0007823E40800000C0D
+:1039A0000100299D00008584AC0068840400A59C6A
+:1039B000002063E0EEFFFF03AC1808D40000609C19
+:1039C000001806E45D0000100000809C0000ED84FB
+:1039D000FFFFC69C0000209D08048784FF00209EF6
+:1039E0000000E09D0A2386E0AC0068840C04609D22
+:1039F0009C2008D4061B84E00804A7840A2B66E0F8
+:103A0000982008D4062B63E00218C6E0A03008D442
+:103A10000000809C003049E5030000100000609C1D
+:103A20000100809C008849E504000010031864E050
+:103A30000100609C031864E0007823E40A00000C95
+:103A40000100299D00006D84005863E0980088847F
+:103A500004006B9D0000A384002884E0EDFFFF03B9
+:103A6000982008D4000073840000C09C003023E438
+:103A7000070000100000001500006D849800888485
+:103A80000004A384002884E0982008D46C00688493
+:103A9000003023E416000010000000159800888410
+:103AA0007C0068840018C4E00000AD845C3008D459
+:103AB0008000888404046584001866E0002063E0C8
+:103AC0000030A3E503000010601808D4000066A8C9
+:103AD000B41808D4641808D4A800A884B400688472
+:103AE000B82808D4CAFEFF03641808D4700068849C
+:103AF000003023E4080000100000001598006884DE
+:103B00007C008884002063E0B41808D4F3FFFF032E
+:103B10005C1808D400008D840404A4849800688490
+:103B20007C008884002863E0002063E0B41808D497
+:103B3000EAFFFF03601808D4CBFFFF03982008D4E6
+:103B40007FFFFF039400C88402008018F85B84A8FC
+:103B5000002068E000008384002804E404000010D2
+:103B60000000A09CB82808D4A42808D46800E884E1
+:103B7000A4006884001867E40A0000100000001523
+:103B800002008018D05B84A8002068E0B800888418
+:103B90000000A384002884E051FFFF03A82008D47C
+:103BA000B800A8844EFFFF03A82808D40000218590
+:103BB000004800440400219CFCFF219C004801D4E3
+:103BC000000004A9000025A9FF00C6A4002083E48A
+:103BD0000C00000C0000E3A84300A7B8070087A46E
+:103BE0000028A9E0082086E00000658C0100E79C21
+:103BF000042063E0004087E4F8FFFF13001805D8B5
+:103C000000002185004800440400219CFCFF219C09
+:103C1000004801D40000E4A90000A5A9000026A9DD
+:103C2000FF0067A5002083E41700000C000003A933
+:103C30000A4B88E0064B84E0002088E04300E4B8AB
+:103C40000700A4A40100089D0038EDE0004884E0CE
+:103C50000000678C0828ABE04300C4B8042863E088
+:103C60000030CDE0001807D8070084A40000668C5F
+:103C700008208BE0042063E0007888E4EDFFFF1368
+:103C8000001806D800002185004800440400219C4B
+:103C9000FCFF219C004801D4000026A9FFFFE59C01
+:103CA0000000C5A80000A09C002826E41000000C1D
+:103CB000000003A90080A0180000A5A80000C09C77
+:103CC000002884E00028A3E0000064840400089D2C
+:103CD000001805D40400849C000067A80400A59C7B
+:103CE000003023E4F9FFFF13FFFFE79C0000609C16
+:103CF000001809E4060000100000A09C0080801855
+:103D0000000084A8002068E0002803D4000021857A
+:103D1000004800440400219C00406018080063A88B
+:103D20000100809C002003D40048004400000015DE
+:103D3000E0FF219C004801D4045001D4086001D464
+:103D40000C7001D4108001D4149001D418A001D4B7
+:103D50001CB001D4000043AA000048A90800601864
+:103D600064E863A8000004AA001808E1000085A91F
+:103D700000006884000086AA0000C09D007003E473
+:103D80004D00000C0000C7AA0000AA8C004080185B
+:103D9000002084A8060070B8002804D400408018D1
+:103DA000402084A8002063E0FFFF80A8002003D407
+:103DB000B2C3FF07000000150800601800E763A801
+:103DC00000408018202084A80018AAE00000A584E4
+:103DD00000006AA8002804D45F0500040000001554
+:103DE00008008018B0E484A808006018B4E463A850
+:103DF0000020AAE000188AE032BEFF0700006584B8
+:103E000068BBFF070100609C1FBCFF070000001596
+:103E10000800601878E163A800188AE00000A48414
+:103E2000FFFF609C001805E4030000100000C09C28
+:103E30000100C09C0500609C001832E403000010E3
+:103E40000000809C0100809C032066E0007003E479
+:103E50001D000010020065B8080080188CE884A8D6
+:103E6000002063E000186AE000006384007003E44F
+:103E70000300001000000015100083B9080080182E
+:103E8000ECE684A800206AE000008384007004E46B
+:103E90000D0000100000001508008018DCE584A863
+:103EA000002065E000186AE00000838C0600000036
+:103EB000100084B932C4FF07000068A8B4FFFF03F4
+:103EC0000000AA8C00406018480063A800408018D9
+:103ED0004C0084A8008003D4006004D40800639CD4
+:103EE0000800849C00A003D400B004D400406018F3
+:103EF000440063A8009003D400002185040041859C
+:103F0000080081850C00C1851000018614004186DF
+:103F1000180081861C00C186004800442000219CB6
+:103F2000FCFF219C004801D40000E3A80100A09CF4
+:103F300000406018140B63A800008384002824E468
+:103F4000A90000100000001500406018580063A888
+:103F500000008384002804E4A30000100000001582
+:103F600000406018540863A8000083840000609C2F
+:103F7000040084A4001804E495000010000000155B
+:103F800000406018080563A8004080180C0584A84C
+:103F90000000A384000064844B0065B94B0023B982
+:103FA0000800801880DC84A80000009D002067E0E5
+:103FB0000000C09C0400849C0020A7E000008384D3
+:103FC00000406018000063A8001884E000006484CA
+:103FD00001008018FFFF84A8032063E0003023E481
+:103FE00003000010001805D40100009D003029E4F2
+:103FF000030000100000609C0100609C031868E052
+:10400000003003E41B00000C0000009D0800801835
+:104010008CDC84A8002067E00400849C0020A7E0DA
+:104020000000838400406018000063A8001884E04A
+:104030000000648401008018FFFF84A8032063E06F
+:10404000003023E403000010001805D40100009D97
+:10405000003029E4030000100000609C0100609C17
+:10406000031868E0003003E4040000100000009D25
+:10407000640000004F00609D08008018ACE284A836
+:10408000002067E000006384001888E54A00000C07
+:104090000000001508008018F4E084A80000A3A91F
+:1040A0000020A7E00000E09C80FC858400406018B0
+:1040B000000063A80000C09C001884E00000648435
+:1040C00001008018FFFF84A8032063E0003823E488
+:1040D00003000010001DE5D70100C09C0000609C9B
+:1040E00000182BE404000010031866E00100609C37
+:1040F000031866E0003803E43300000C0000C09CA5
+:1041000000FE858400406018000063A8001884E069
+:104110000000648401008018FFFF84A8032063E08E
+:10412000003023E403000010801EE5D70100C09C8E
+:104130000000609C001829E404000010031866E0E9
+:104140000100609C031866E0003803E41E00000CC8
+:104150000000C09C80FF858400406018000063A8B8
+:10416000001884E00000648401008018FFFF84A828
+:10417000032063E0003023E403000010001805D49E
+:104180000100C09C0000609C00182BE4040000109B
+:10419000031866E00100609C031866E0003803E441
+:1041A0000700000C0100089D006888E5BFFFFF13B1
+:1041B0000400A59C130000000000609D1100000099
+:1041C0005000609D0F0000004E00609D0040601890
+:1041D0000C0563A800408018080584A86DFFFF0344
+:1041E0000000001500406018080563A800008384E3
+:1041F0000000A3844B0064B96AFFFF034B0025B99C
+:1042000000002185004800440400219CDCFF219C23
+:10421000004801D4045001D4086001D40C7001D4CA
+:10422000020080185C6784A80800C018FCE6C6A8D5
+:104230000020A3E00030C3E1000085840800C0181E
+:1042400074E1C6A80800A018F8E6A5A8002883E134
+:104250000030A3E00200C018E85BC6A80000A585F6
+:10426000003084E00800A018B4E4A5A8002843E1C9
+:104270000800A01830E9A5A80028C3E00000648465
+:104280000700639CFF3F8018FCFF84A8430023B90C
+:104290000000AE840300699C032023E12800899C70
+:1042A0000028A4E4100000100000EC8428016D9C9C
+:1042B0000018AAE00000858C0000609C001824E42F
+:1042C0004300001098FFC09C000089A804006018FB
+:1042D000B06F63A8A9B8FF07003005D83C00000004
+:1042E00000000015420009B9FFFF609D005808E179
+:1042F000005828E41900000C00506DE000806018A0
+:10430000140063A80018E7E00000668CFFFF089D1A
+:104310000100C69C180063B80000868C0100C69C92
+:10432000100084B80000A68C042063E00100C69C45
+:104330000800A5B80000868C042863E00100C69C34
+:10434000042063E0001807D4005828E4EFFFFF13AF
+:104350000400E79C00506DE00100A09CF800CA84B6
+:104360001400899C482903D8FC006A840001AA84AF
+:104370006C310AD468210AD474290AD470190AD479
+:1043800078490AD400006C84143001D4FC00AA845B
+:10439000102001D4182801D4204801D41000819C99
+:1043A0000001CA84A8C7FF071C3001D46801AA8491
+:1043B00000006C84002863E000008E8400180CD498
+:1043C0006801AA84022884E000200ED40000218520
+:1043D00004004185080081850C00C1850048004427
+:1043E0002400219CDCFF219C004801D4045001D40E
+:1043F000086001D40C7001D40000A3A80800801844
+:10440000E87B84A80000E09C002063E00000A38516
+:1044100008008018F8E684A80800601874E163A812
+:10442000002085E1F80B6D85001885E00800601814
+:10443000B4E463A800006486001845E10000CC8461
+:104440001B006B9CF8FF809C1400269D00382BE419
+:104450007900000C0320E3E108006018FCE663A883
+:1044600014008F9C0018C5E100006E840018A4E4BD
+:104470000F00001042000BB92801739C00186AE07D
+:104480000000838C003824E46B0000109BFF809CAC
+:10449000002003D804006018C76F63A837B8FF076F
+:1044A00000008FA86400000000000015FFFF609C62
+:1044B000001808E1001828E41A00000CFC0BAD8479
+:1044C000000023AA00806018140063A80018E6E02A
+:1044D0000000C58C0400299DFFFF089D0100A59CDC
+:1044E0000000658C0100A59C080063B80000858C65
+:1044F0000418C6E00100A59C100084B80000658C7B
+:104500000420C6E0180063B80100A59C0418C6E0AA
+:10451000003007D4008828E4EEFFFF130400E79C76
+:1045200003008BA40000C09C003024E40E00000CAB
+:104530000000E09C0000C58CFFFF849C003824E450
+:104540000900000C0100A59C0000658CFFFF849C05
+:10455000080063B80100A59C003824E43200001074
+:104560000418C6E000808018000084A8002069E0DC
+:104570000400299D003003D4070089A40000609C3A
+:10458000001824E4070000100000001500808018C7
+:10459000000084A8002069E00000809C002003D473
+:1045A0001C016A846C190AD420018A8424016A845B
+:1045B00070210AD474190AD468790AD4005073E0BF
+:1045C000F80BAD850100809C482103D81C016A844A
+:1045D00078690AD4141801D420018A84182001D4DF
+:1045E00000006C8424018A841C2001D478018A8410
+:1045F000202001D4107801D413C7FF071000819C3C
+:104600006801AA8400006C84002863E000008E84A6
+:1046100000180CD46801AA84022884E00600000077
+:1046200000200ED40000658C100063B8CEFFFF039D
+:104630000418C6E00000218504004185080081853A
+:104640000C00C185004800442400219CC0FF219C2F
+:10465000004801D4045001D4086001D40C7001D486
+:10466000108001D4149001D418A001D41CB001D43E
+:1046700020C001D424D001D428E001D4000043A9F3
+:1046800008008018F8E684A808006018B4E463A85D
+:1046900000208AE300188AE200001C8604006018EB
+:1046A000D86F63A84C009485B4B7FF0700008CA8AE
+:1046B0002C00019F00006CA8FEC6FF07000098A810
+:1046C000E800948438006184002023E44900000C51
+:1046D000000000150800C01874E1C6A80800E01822
+:1046E000FCE6E7A800304AE300384AE22C004185A6
+:1046F00004006018097063A80000809C0000D28448
+:104700000000C09E1400AA9C003065E42D0000103B
+:104710000700CAA599B7FF07000000150000DA845A
+:104720000100E09C00008CA800A0C6E04200AAB8EE
+:10473000483906D8000070A800508CE100B00EE4A3
+:10474000050000100000CEA82C00E1840400E79CC6
+:104750002C3801D44FFDFF07000000150000B28483
+:1047600000808018000084A82C00C184002070E024
+:104770000250A5E0003003D4002812D4000098A80D
+:10478000FCFFA59C00006CA800B00EE40400001023
+:10479000005010E2002812D40400109EC5C6FF0786
+:1047A00000000015E800948438006184002023E4B0
+:1047B000CFFFFF13000000150F00000000801CD485
+:1047C0000000BA849CFFE09C040060181B7063A882
+:1047D00000A0A5E000008AA8283905D867B7FF0720
+:1047E00000508CE100006CA8EDFFFF03000098A8CA
+:1047F00000801CD4000021850400418508008185CB
+:104800000C00C185100001861400418618008186C5
+:104810001C00C18620000187240041872800818771
+:10482000004800444000219CFCFF219C004801D42A
+:1048300008008018E87B84A8000003A94D00A09C14
+:10484000002063E00000C38404008684002804E4A0
+:10485000110000100100209D002844E40A0000100F
+:104860006400609C4200609C001804E40400001096
+:1048700000000015080000000300209D0600000055
+:104880000000209D001804E40300000C0300209D9C
+:104890000200209D1A00A6940800E01874E1E7A821
+:1048A000020060185C6763A8003888E00018C8E060
+:1048B0000800E01844E8E7A8000064840800A5B8F0
+:1048C000010083B80448A5E0003863E00000E684F6
+:1048D000001868E00800C01804E8C6A86F00E78C5C
+:1048E000003084E0002088E0003803D8002804DC91
+:1048F00000002185004800440400219CDCFF219C2D
+:10490000004801D4045001D4086001D40C7001D4D3
+:10491000108001D4149001D418A001D41CB001D48B
+:1049200020C001D40000C3A9FF0044A64DB9FF0771
+:104930000000009E08008E84008024E4A400000C87
+:104940002000609C0100609C001824E41B00000C07
+:10495000060092B80000609C001830E40A000010C5
+:10496000000092A800000EA90F00609C0000A09C0F
+:104970000000C09CEFFCFF070000E09C9E000000D0
+:10498000000000152000609C0000B0A800000EA9E7
+:104990000000C09CE7FCFF070000E09C04006018DA
+:1049A0002E7063A8018080A8F4B6FF0700000015F0
+:1049B00091000000000000150800A01860E6A5A8FE
+:1049C0000800C01864E6C6A800286EE00030AEE01B
+:1049D000000083850040C0186820C6A800004585F7
+:1049E000003084E000006CA80000A48400008AA8C5
+:1049F000BDC5FF07FF1F85A641008AB800006CA84F
+:104A00000000CBAAB8C5FF0742004AB900006CA855
+:104A100000008AA8B4C5FF0700000BAB08006018AF
+:104A2000B0E463A80800801814E984A80018CEE058
+:104A30000800A01804E5A5A80020EEE000280EE17B
+:104A40000800601818E963A80800801808E584A821
+:104A50000018AEE000202EE10400639C00188EE0F8
+:104A6000080060180CE563A800184EE10000668499
+:104A70000000C884003007D40000C984003005D489
+:104A80000000AA84008003E40B000010002804D476
+:104A900000006884001856E406000010003058E456
+:104AA0000400001000284BE40300000C0000001577
+:104AB0004700009E0800C018ACE2C6A80030AEE077
+:104AC00000006584001874E5030000100000C09C1D
+:104AD0000100C09C2000609C0018B4E50300001099
+:104AE0000000809C0100809C042066E00000409D46
+:104AF000005003E403000010000000154A00009E6F
+:104B0000005030E494FFFF130000001500A005D40E
+:104B1000AB39000400006EA804006018577063A849
+:104B200096B6FF071200809CFEFCFF0700006EA8EF
+:104B300008008018ECE684A80800C018F4E6C6A8AF
+:104B400000206EE00030AEE000000BAA0000C3843D
+:104B5000080060184CE663A800188EE00300609C13
+:104B6000001805D40000609C0500A09C08180ED415
+:104B70005F0066A4005003E477FFFF13002804D40D
+:104B800004006018757063A87CB6FF07000086A853
+:104B900008008018F0E684A800206EE0000063841E
+:104BA000005023E404000010000000156AFFFF031A
+:104BB0004D00009E0800A01810E5A5A846C2FF07FA
+:104BC00000288EE065FFFF030000609C000092A8B3
+:104BD00000000EA90000A09C0000C09C55FCFF072F
+:104BE0000000E09C040060182E7063A86FFFFF03B4
+:104BF000008080A80000218504004185080081858F
+:104C00000C00C185100001861400418618008186C1
+:104C10001C00C18620000187004800442400219C1C
+:104C2000E4FF219C004801D4045001D4086001D461
+:104C30000C7001D4108001D4149001D418A001D4B8
+:104C4000000084AA000045AA08008018E87B84A818
+:104C50000000809D002063E00000409D0000C384B0
+:104C60000000C09D28086684005003E42A0000105C
+:104C70000000009E200086840100609C001824E44F
+:104C800017000010005024E42C0866843008868445
+:104C9000010063B8010084B81C08A684FFFF03A6C6
+:104CA000005005E40900000CFFFFC4A53808668425
+:104CB00034088684020063B8020084B8FFFF83A52D
+:104CC00015000000FFFF44A5380866843408868478
+:104CD000010063B8FAFFFF03010084B80A00001066
+:104CE000000000152E0806961C086684005003E498
+:104CF000F6FFFF133208C6953A08869506000000B5
+:104D000036084695040060187F7063A81BB6FF073D
+:104D10000000001510006EB810008CB8041870E088
+:104D200004208AE0001814D4002012D40000218549
+:104D300004004185080081850C00C18510000186B2
+:104D40001400418618008186004800441C00219C04
+:104D5000D4FF219C004801D4045001D4086001D440
+:104D60000C7001D4108001D4149001D4000023A948
+:104D7000080080187C7D84A80800A018787DA5A86C
+:104D8000002063E00800E01878E2E7A8002889E046
+:104D9000003829E20000A38408006019FCE66BA932
+:104DA000080000197CE208A99F0065B80000C484CF
+:104DB000005809E25C0063B89F00E6B80040E9E1F2
+:104DC0000018A5E05C00E7B88400A5B808006019E9
+:104DD00074E16BA90038C6E01F00A59C8400C6B82A
+:104DE0009F0065B80800E018F8E6E7A83F00C69CF9
+:104DF000003849E25B0063B89F00E6B8005809E15B
+:104E00000018A5E05A00E7B88500A5B8000088851D
+:104E10000038C6E00800A5B88600C6B80800E0184B
+:104E2000B4E4E7A80001A59C003849E1062BC6E0E0
+:104E30000200ECB808006019F4DD6BA928010C9D94
+:104E40000058E7E00000D28500406AE1003829E11F
+:104E50001800819C04006018A47063A80300C69C1D
+:104E60000000B0840300C6B81400069D0000E89C52
+:104E70000028A7E40E0000100000AFA90000CB8CB2
+:104E80000000A09C002826E404000010000087A871
+:104E900097FFA09C00280BD80000E09CB7B5FF0747
+:104EA00000380DD424000000000000150000A98483
+:104EB0000100609D00006EA80B00A5B800580FD43B
+:104EC0000228AEE0184001D41400A59C283001D47B
+:104ED0004300A5B8002811D468410AD4EC00AA8484
+:104EE000F000EA84F4000A856C290AD470390AD4E7
+:104EF00074410AD478310AD41C2801D4F000AA8461
+:104F0000202801D4F400EA84CFC4FF07243801D458
+:104F100000506CE00100009D68018A84484103D87C
+:104F20000020CEE100007084022063E0007012D403
+:104F3000001810D4000021850400418508008185F7
+:104F40000C00C18510000186140041860048004411
+:104F50002C00219CDCFF219C004801D4045001D48A
+:104F6000086001D40C7001D4000083A90800A018C7
+:104F7000B4E4A5A808006018F8E663A800284CE18E
+:104F80000018CCE10100E09C00006E840200209D2E
+:104F90000300A09D1400639D0600009DFCFFC09CC3
+:104FA0000300A4A4033064E00080C0180000C6A879
+:104FB000003063E00000C384003805E4B300001053
+:104FC000480066B8003885E4B2000010004805E4E7
+:104FD000AE000010500066B8006805E4A90000109B
+:104FE00000000015004026E4EDFFFF130100849C43
+:104FF0000800601858E663A801060019000008A917
+:1050000000182CE200007184001864E0FEFF239D6C
+:10501000004884E47000000C0100E09D0080A018AE
+:105020000000A5A80028ABE1FCFFC09C0080A018F0
+:105030000000A5A8033064E000400DD4002863E020
+:105040000400AD9D0000C3840300A4A4007805E41F
+:105050008A00001004006B9D007885E48500001034
+:105060000200609C001805E480000010500066B843
+:105070000300609C001805E47A0000100000001591
+:105080000100849C0048A4E45300000C000006A921
+:10509000FCFFC09C0300A4A4033064E00100E09C7A
+:1050A0000080C0180000C6A8003063E00000C38480
+:1050B000003805E467000010480066B8003885E451
+:1050C000660000100200609C001805E461000010FA
+:1050D000500066B80300609C001805E45B000010F7
+:1050E00000000015080066B80100849C0048A4E494
+:1050F0003900000C041808E1FCFFA09C0080C018D7
+:105100000000C6A8032864E00100E09C003063E0D2
+:105110000300A4A40000C384003805E44700001085
+:10512000480066B8003885E4460000100200609C24
+:10513000001805E441000010500066B80300609CB0
+:10514000001805E43B00001000000015100066B8D0
+:105150000100849C0048A4E41F00000C041808E12E
+:10516000FCFFA09C0080C0180000C6A8032864E0D3
+:105170000100E09C003063E00300A4A40000C384AD
+:10518000003805E427000010480066B8003885E4C0
+:10519000260000100200609C001805E421000010A9
+:1051A000500066B80300609C001805E41B00001066
+:1051B00000000015180066B80100849C0048A4E4B3
+:1051C0000500000C041808E1004884E498FFFF1370
+:1051D000FCFFC09C00808018000084A800206BE0C9
+:1051E00004006B9D004003D407008BA40000609C6A
+:1051F000001824E4290000100000C09C0080A018C2
+:105200000000A5A800286BE004006B9D003003D4CB
+:105210002300000000006E84E7FFFF035800C6B8BB
+:10522000E5FFFF03FF00C3A4E3FFFF03FF00C6A4E5
+:10523000C7FFFF035800C6B8C5FFFF03FF00C3A4A4
+:10524000C3FFFF03FF00C6A4A7FFFF035800C6B8B3
+:10525000A5FFFF03FF00C3A4A3FFFF03FF00C6A435
+:1052600088FFFF035800C6B886FFFF03FF00C3A4F2
+:1052700084FFFF03FF00C6A4FCFFFF03480066B8DD
+:1052800059FFFF035800C6B857FFFF03FF00C3A430
+:1052900055FFFF03FF00C6A400006E8408008018BD
+:1052A00074E184A81001CA840020ACE002186BE00D
+:1052B0006C310AD414018A841801CA8468190AD48A
+:1052C00074310AD470210AD4101801D400009184DA
+:1052D00010016A840200849C141801D41401CA8449
+:1052E000183001D418016A841C1801D478210AD41A
+:1052F000202001D4000065841000819C0100A09C46
+:10530000005063E0482903D8CFC3FF0700006E8434
+:1053100008006018FCE663A86801AA840018CCE0C5
+:1053200000006E84002863E00000868400180ED41C
+:105330006801AA84022884E0002006D400002185A8
+:1053400004004185080081850C00C18500480044A7
+:105350002400219CF0FF219C004801D4045001D47A
+:10536000086001D40C7001D4000023AA0040E01AA8
+:105370001C20F7AA0800601878E163A80000B7862F
+:10538000001891E000006486FFFF609C001813E4A1
+:10539000610000100000209F0800A018ECE6A5A8FE
+:1053A000002891E00000648400C803E410000010AD
+:1053B000020073B80800C018FCE5C6A80800E01891
+:1053C000F4E4E7A8003073E008000019F0E408A94D
+:1053D000001871E00038D1E00000838C0040B1E09B
+:1053E000009806D4002005D4020073B808002019E4
+:1053F000BCE429A90800601B30E37BAB0048F1E165
+:1054000000D8A3E00800A019B0E2ADA90800E01898
+:10541000B0E3E7A80800601984E76BA9006883E09F
+:105420000038C3E00800201930E429A90800601BF7
+:10543000C4E47BAB005803E10048E3E00800A01996
+:10544000C0E4ADA900D851E10800601904E76BA9D8
+:10545000006831E110007B9F005863E00800AD9DBB
+:1054600000D891E1002091E00028B1E00030D1E0C7
+:105470000038F1E0001871E0004011E1006871E1CE
+:1054800004007B9F8400D5B90000848400D8B1E17A
+:105490000300CEA50000A5840000C6840000E784B8
+:1054A000000063840000088500200FD4002809D480
+:1054B00000300AD400380BD400180CD400C82EE4F5
+:1054C0000C00001000400DD4010073B80800C01893
+:1054D00004E8C6A80800801830E684A8003063E01D
+:1054E0000020B1E0001871E000008394002005D492
+:1054F0000800E01844E8E7A8003873E0001871E0FD
+:105500000000838C010084A4030084B80420B5E269
+:1055100000A817D4004060181C2063A80000C09C9D
+:10552000000083840000209D070084A4004824E438
+:10553000030000100300609C0100C09C001824E4DC
+:10554000030000100000A09C0100A09C042866E05D
+:10555000004803E4210000100000001508000019B5
+:10556000ECE608A908006019BCE46BA9004071E0F2
+:105570000800A019C0E4ADA908000019C8E408A9F2
+:10558000005891E00068B1E00800601BC4E47BAB08
+:105590000040F1E0FFFF609D0000A09D00D8D1E039
+:1055A00000000385005804D4005805D4006806D4D0
+:1055B000004808E409000010006807D42C007B9F15
+:1055C0000800A018F4E4A5A800D871E0002891E034
+:1055D000006803D4005804D40000218504004185EC
+:1055E000080081850C00C185004800441000219C02
+:1055F0000800A01830E4A5A80000809C002863E003
+:105600001F00A09CFFFFC09C0100849C8036E3D754
+:105610000037E3D70000C09C8037E3D7003003D4C5
+:105620000028A4E5F8FFFF130400639C0048004431
+:1056300000000015FCFF219C004801D40000A3A934
+:10564000080000198CDC08A90800601880DC63A839
+:105650000040ADE000188DE008000019ACE208A998
+:10566000000064840040EDE00000E09D0800801828
+:1056700084DC84A80800001990DC08A90020CDE093
+:105680000000E784000085840040A0180000A5A861
+:105690000000C684002863E0003003D40040ADE081
+:1056A00000406018000063A80000A584001884E092
+:1056B000002804D400388FE52600000C00000015F7
+:1056C0000800801874E084A80800A018F4E0A5A8D9
+:1056D00000200DE10800601874DF63A8080080183E
+:1056E000F4DD84A800286DE100182DE10020CDE054
+:1056F00000FD68840040A0180000A5A80100EF9DEF
+:105700000000A685002863E0006803D480FE88843A
+:1057100000406018000063A80400C69C0000A88434
+:10572000001884E00018A5E00000A9850400089D89
+:1057300000006B840400299D006804D404006B9D64
+:10574000001805D400388FE5EAFFFF1300000015AC
+:1057500000002185004800440400219CFCFF219C9E
+:10576000004801D40400A0187C84A5A80000E3A987
+:105770000000C584FF0084A40000E09C0400638452
+:10578000060084B80040601924026BA9F01C06D4FE
+:105790000100A09D00406018482063A81400201953
+:1057A000804329A9001884E00000009D0000CB84FC
+:1057B0000100E79C00006484006843E40F00000CD3
+:1057C000004827E40B00000C004006E4F8FFFF133C
+:1057D00000000015040060187C8463A80100609D2F
+:1057E00000008384F00484840700000004200FD4A8
+:1057F000050000000000609D00006584F6FFFF03C7
+:10580000F06C03D400002185004800440400219C72
+:10581000F8FF219C004801D4045001D4000063A982
+:105820000800601A8CDC73AA08006018ACE263A858
+:105830000800801894DC84A800182BE200984BE143
+:1058400000206BE02100609E0800A01898DCA5A84D
+:10585000009803D400288BE08406609C0800C018E0
+:10586000ACDCC6A8001804D40030ABE02200809C59
+:105870000800E018B8DCE7A8002005D40038CBE029
+:105880008806A09C080000197CDC08A9002806D422
+:105890000040EBE02300C09C0800201980DC29A90F
+:1058A000003007D400480BE18C06E09C0800E019AA
+:1058B00088DCEFA9003808D400782BE12400009D93
+:1058C0000000F1850000A09D0006A09C004009D4C6
+:1058D0000000809C9006209D007884E50D00000C5F
+:1058E00000480AD40800601AF4DE73AA00986BE03E
+:1058F000806FE3D7002803D40100AD9D0400A59C70
+:105900000100849C007884E5FAFFFF130400639C87
+:105910000000F1844000C09C0000809C003884E5B9
+:105920000E00000C0007A09C0800001974DD08A9F7
+:1059300000406BE08037E3D7002803D40100C69C09
+:105940000400A59C0100849C003884E5FAFFFF1345
+:105950000400639C0000F1846000C09C0000809CF7
+:10596000003884E50D00000C8007A09C0800201979
+:1059700074E029A900486BE08037E3D7002803D4FE
+:105980000100C69C0400A59C0100849C003884E5AD
+:10599000FAFFFF130400639C000021850400418589
+:1059A000004800440800219CC4FF219C004801D409
+:1059B000045001D4086001D40C7001D4108001D4CB
+:1059C000149001D418A001D41CB001D420C001D47B
+:1059D00024D001D428E001D42CF001D4FF0043A648
+:1059E000000084A9000086AA0000C7ABB9BCFF076D
+:1059F000000048A910006018000063A80018BEE469
+:105A0000050000100000A09C00806018000063A842
+:105A10000418DEE300283EE4030000100000C09CF0
+:105A20000100C09C080060183BED63A800184AE420
+:105A3000030000100000809C0100809C042066E0B0
+:105A4000002803E40A00001000000015040060189C
+:105A5000B47063A8080080183CED84A8C7B2FF07A3
+:105A600000000015740200001000609D0800A018DE
+:105A7000E87BA5A804006018F37063A80028BEE0C6
+:105A8000080080183CED84A8BCB2FF07382801D478
+:105A900000F00CD400007EA80800A0183CEDA5A8DA
+:105AA000BDBAFF070000809C0800C0184CE6C6A8DD
+:105AB00004006018808463A800303EE2080060198A
+:105AC0001CC56BA900F003D408000019ACE208A9BA
+:105AD0000058DEE00800201BF0E639AB00407EE015
+:105AE0000800E018E47BE7A80800201918C529A9D8
+:105AF0000800E01978E2EFA90800A01B0CE9BDAB93
+:105B000000C87EE100389EE00048BEE000781EE15B
+:105B10000800A019A4E2ADA90800601A7CE273AAEB
+:105B200000E89EE10000209F0068FEE000983EE152
+:105B30000800E01AECE6F7AA0800E01B10E9FFAB4A
+:105B40000800E01920E9EFA92000A09F00C804D4B4
+:105B500000901ED800B85EE100F8BEE10078DEE1FA
+:105B60000800601A30ED73AA00E803D4380081847D
+:105B70000100609C0098FEE10800E01A2CEDF7AAF5
+:105B80001000E09F00C807D400C808D400B81EE287
+:105B900000F805D400C806D400180FD400C804D4F7
+:105BA0000800E0188CE8E7A808000019FCE508A93F
+:105BB00000C811D400C809D400C80AD400C80BD446
+:105BC00000C80CD400C80DD400C80ED400C810D42E
+:105BD00010C81ED408C81ED40000C09C1F00A09C82
+:105BE00000389EE000407EE00000209D0000609DA7
+:105BF0000000A09DE04FE3DB0100C69C005804D4E8
+:105C0000006803D80400849C0028A6E5FAFFFF136F
+:105C10000100639C0800E019F4E6EFA90200601A95
+:105C20005C6773AA00789EE00300209E00987EE2E5
+:105C3000008804D4349801D46135000400007EA8A3
+:105C40000800E01A00D0F7AA00007EA800B8FEE223
+:105C50007217000430B801D466FEFF0700007EA86A
+:105C600008008018B8E184A808006018B4E163A8AF
+:105C700000203EE208006019C0E16BA900185EE256
+:105C800000589EE00800601A94E173AA0800201BE7
+:105C90009C7D39AB00987EE10800E01BB0E1FFABD2
+:105CA00008002019BCE129A908006018A0E163A838
+:105CB00000C8DEE000F81EE10048BEE00800601AFF
+:105CC00080E273AA0800A01990E1ADA90800E019CC
+:105CD0008CE1EFA900181EE200683EE100987EE02A
+:105CE00000785EE10800201B9CE139AB0800E01B56
+:105CF000A8E1FFAB00C8BEE100F8FEE100A003D4BC
+:105D00000000209F0200E01B3087FFAB04006018FA
+:105D1000588363A800C804D400F803D40400801892
+:105D20005C8384A802006018448263A80800A01B5A
+:105D3000A07DBDAB001804D400E8FEE004006018AC
+:105D4000548363A801008018FCC684A800C805D449
+:105D5000002003D40800E01A98E1F7AA0800A01B6D
+:105D6000A4E1BDAB0100A01814C7A5A800B89EE12E
+:105D700000E8DEE104006018648363A80100A09FCE
+:105D8000FF7FE01AFFFFF7AA04008018608384A851
+:105D9000002803D400B806D400C807D400C808D42B
+:105DA00000C811D400C809D400C80DD400C80FD44D
+:105DB00000C804D400C812D400C80AD400E80BD428
+:105DC00000C80CD400E80ED400C810D40CC81ED4EF
+:105DD0008CB3FF070600609C3400E1840800C01803
+:105DE000B0CFC6A8E40A7E9C300001850030BEE03A
+:105DF000A0079E9C001807D4002808D4E0223ED4B7
+:105E000084FEFF0700007EA80800201978DC29A97D
+:105E1000080060199CDC6BA900487EE00000A09D92
+:105E200000581EE1006803D40006E09D0800201A17
+:105E3000C4DC31AA007808D4000A809C0000C09C11
+:105E40000000A09C00887EE0002003D40100C69CD6
+:105E50004000849C0028A6E5FCFFFF130400639C1F
+:105E60000800601A98DC73AA0040201B000039ABC0
+:105E700000989EE0000008850800E01AC4DCF7AA3C
+:105E80000800A01BB8DCBDAB000064840000C09C0F
+:105E90000000E09C00C863E000B8BEE000E89EE0BF
+:105EA000004003D4000064840040E01B0000FFAB0E
+:105EB0000100C69C0000058500F863E00400849C96
+:105EC000004003D40038A6E5F7FFFF130400A59CAB
+:105ED0000800201994DC29A90040A0181C01A5A8DD
+:105EE00000489EE02000601900006BA90000648457
+:105EF0000000E09D0800201A38E231AA180063B8BB
+:105F000000408018180184A800887EE3001804D49B
+:105F10000800601A3CE273AA005805D400406018DB
+:105F2000100863A80800E01A40E2F7AA007803D43A
+:105F300000985EE300406018100263A800B8FEE01D
+:105F4000007803D40800A01934E2ADA9004060181D
+:105F50004C4063A80800E01B48E2FFAB007803D484
+:105F60000800A0181CE2A5A80800E01914E2EFA997
+:105F7000080060184CE263A80078DEE10800201AEF
+:105F8000787D31AA0068BEE300F83EE100185EE1CA
+:105F900000289EE10088FEE10800201B44E239ABA6
+:105FA0000800C01818E2C6A80800601A7C7D73AA11
+:105FB0000800E01A887DF7AA00C81EE10030BEE1A3
+:105FC00000981EE200B83EE20800801850E284A863
+:105FD0000800E01B847DFFAB080060188C7D63A87F
+:105FE0000800A018947DA5A800207EE100F87EE2BC
+:105FF00000189EE200281EE30800201B807D39ABBC
+:106000000800C018987DC6A80800E01AC8E1F7AAE1
+:1060100000C85EE20030BEE008008018907D84A8D1
+:1060200000B89EE30800E01BCCE1FFAB080060185D
+:10603000D0E163A80020BEE200F83EE30018DEE0F5
+:106040000800E01AC4E1F7AA0800E01B60E6FFAB15
+:1060500000B89EE00800601864E663A800F8DEE27D
+:106060000018FEE20000E09F00406018040863A8EA
+:1060700000F804D400F803D40800801868E684A867
+:10608000FFFF609C00F81AD400181BD400181DD420
+:1060900000F807D400F808D400F809D400F80AD4AE
+:1060A00000F80BD400F80CD400F80DD400F80ED48E
+:1060B00000F80FD400F810D400F811D400F812D46E
+:1060C00000F813D400F814D400F815D400F805D45F
+:1060D00000F818D400F806D400F819D400F816D443
+:1060E00000F817D400207EE000F81CD40800A018A7
+:1060F0005CE6A5A800F803D40800001960DC08A934
+:106100003400E18400289EE00800C0185CDCC6A8CA
+:106110000000678402002019745C29A90040BEE1D8
+:106120000200601AF45B73AA00F804D4004883E10B
+:106130000030DEE102006019045C6BA90200E01986
+:10614000085CEFA90200201A0C5C31AA0200E01AD8
+:10615000EC5BF7AA0200201B645C39AB009803E1FA
+:106160000058A3E00078C3E00088E3E000B823E132
+:1061700000C843E13000E1870200A01B685CBDABB2
+:106180000100609E0000E09E00E863E1FFFFE09DEB
+:106190000080201A000031AAFF7F201BFFFF39ABCF
+:1061A000009807D400009F840800E01808E2E7A8E0
+:1061B0000800A01B64DCBDAB007805D4008806D4C1
+:1061C00000B808D400B809D400B80AD400B80BD479
+:1061D00000C80CD4347803D4307803D4A4B803D4E2
+:1061E00070B803D4BCB803D4C0B803D414B803D473
+:1061F0000038DEE000B804D4080000196C7D08A95E
+:1062000000B80DD444B804D448B804D44CB804D46D
+:106210000040FEE00800E01BA47DFFAB0800201951
+:10622000707D29A93800A18500E8BEE000F89EE055
+:1062300000481EE108006019747D6BA900980ED417
+:1062400000583EE1009805D400B804D400B80DD43D
+:1062500000B806D400B807D400B808D40800201A43
+:106260000CE231AA00B809D400889EE08403E09EC5
+:106270000800601984E16BA90800601A38ED73AA60
+:1062800000B804D40800A01B74E1BDAB00585EE167
+:106290000800A01988E1ADA9E00AFE8500E8DEE06B
+:1062A00000687EE100987EE30800201B10E239AB15
+:1062B0000800801880E184A80800201AD8E131AADB
+:1062C00000C8BEE0387803D40800E01B78E1FFABDB
+:1062D00000203EE10088BEE10800601AE0E173AAF8
+:1062E0000800A01B2CDCBDAB00F8FEE00800601825
+:1062F0007CE163A80800E019E4E1EFA90098DEE181
+:106300000800201B28DC39AB00E83EE208008018BA
+:10631000F8E184A800181EE100789EE10800E01A68
+:1063200024DCF7AA00C81EE20800E01B1CDCFFAB5F
+:106330000020BEE21C00739E0800A01B54E2BDAB0F
+:1063400000B8FEE100F85EE208006018F4E163A81E
+:1063500000989EE00800201BECE139AB00E89EE2CB
+:1063600000185EE30800E01A00E2F7AA00C87EE227
+:106370000800E01B20E2FFAB3000BD9F00B87EE0CC
+:1063800000F8DEE23800399F00E81EE300C8FEE2B4
+:106390000000A09F0800E01B88E2FFAB00E803D4E8
+:1063A00000F83EE300406018080463A8FFFFE09F88
+:1063B00000E805D400F806D400E803D40100A09C4E
+:1063C00000E80BD4040060187C8463A80020C01887
+:1063D0000000C6A800F807D400F808D400E809D4E3
+:1063E00000E80AD400E80CD400280DD400E80ED44C
+:1063F00000E80FD400E810D400E811D400F812D45B
+:1064000000E804D400E815D400E81AD400E813D456
+:1064100000E814D400E816D400F817D400E818D423
+:1064200000F819D400E81BD4003003D40CE81ED4C3
+:10643000000065A9000021850400418508008185D0
+:106440000C00C18510000186140041861800818669
+:106450001C00C18620000187240041872800818715
+:106460002C00C187004800443C00219C0000A3A8E8
+:106470002000C09C04000019409008A90000E09C86
+:10648000010065A4FFFFC69C3000639C004086E0CD
+:106490004100A5B8003826E4FAFFFF13001804D81D
+:1064A0000400601940906BA90048004400000015EA
+:1064B000E0FF219C004801D4045001D4086001D4BD
+:1064C0000C7001D4108001D4149001D418A001D410
+:1064D0001CB001D4000046AA020084B8000043A901
+:1064E0000800C01874DFC6A808000019F4DD08A968
+:1064F000003064E008002019787D29A900186AE0BE
+:10650000004084E00000E38400208AE000488AE242
+:10651000080060187C7D63A8000084850018CAE12B
+:10652000040005BA0400D2B8000074840B00C7BA96
+:106530000000B0A800008E8411C3FF070B008CB9C7
+:106540000200C0185C67C6A800304AE10000809CC9
+:1065500000006A842C00A384002025E43100001090
+:1065600000588CE10000A09C0300C09C0F00E09C40
+:1065700000800019000008A90000809C00406CE029
+:1065800080802019808029A90100849C004803D4C0
+:106590000030A4E5FBFFFF130400639C0100A59CF1
+:1065A0000038A5E5F3FFFF1340008C9D00008E84AA
+:1065B0000300D2B80000B0A85F00E4B80000748403
+:1065C000003884E0EEC2FF07810084B80058F6E08E
+:1065D0000000A09C0300C09C0700009D00802019C3
+:1065E000000029A90000809C004867E080802019F5
+:1065F000808029A90100849C004803D40030A4E5D0
+:10660000FBFFFF130400639C0100A59C0040A5E56F
+:10661000F3FFFF134000E79C2F000000000000156F
+:106620000000A09C0300C09C1F00E09C008000199B
+:10663000000008A90000809C00406CE080802019C8
+:10664000808029A90100849C004803D40030A4E57F
+:10665000FBFFFF130400639C0200A59C0038A5E526
+:10666000F3FFFF1380008C9D00008E840300D2B8DE
+:106670000000B0A85F00E4B800007484003884E033
+:10668000BFC2FF07810084B80058F6E00000A09C5C
+:106690000300C09C0F00009D00802019000029A964
+:1066A0000000809C004867E080802019808029A934
+:1066B0000100849C004803D40030A4E5FBFFFF13D5
+:1066C0000400639C0200A59C0040A5E5F3FFFF13B6
+:1066D0008000E79C00002185040041850800818539
+:1066E0000C00C185100001861400418618008186C7
+:1066F0001C00C186004800442000219CD0FF219C42
+:10670000004801D4045001D4086001D40C7001D4B5
+:10671000108001D4149001D418A001D41CB001D46D
+:1067200020C001D424D001D428E001D42CF001D41D
+:10673000000083A90800801828E984A80800A01890
+:1067400024E9A5A8002063E00200C0185C67C6A881
+:1067500000288CE00000038600304CE10000C09F60
+:1067600000008486040060182E7163A883AFFF07C1
+:10677000000090A804006018407163A87FAFFF0775
+:10678000000094A800008A8402006019D85B6BA9FD
+:106790000200C018D45BC6A80058A4E0040060182A
+:1067A000557163A8003084E00000C5840000448671
+:1067B000028006E371AFFF07000086A8040060189E
+:1067C000657163A86DAFFF07000092A800006A849E
+:1067D0002C00238500F009E403000010000089A8C4
+:1067E0000100209D0200609C001824E403000010BA
+:1067F0000000E09C0100E09C0800601974E16BA9B6
+:106800000F0087BB0058ACE000006CA80000858436
+:106810000800601974DE6BA9070049BB020004B9C7
+:106820000000B4A80000D0A80058E8E008006019F3
+:10683000F4DC6BA90038ECE0005808E10000478563
+:1068400000400CE1000088851AFFFF0708004AB9E4
+:10685000080070B80460CAE104187CE004D063E06A
+:1068600000F0B8E51400001004A0C3E20100949DFC
+:1068700000908CE50E00000C00000015000043A9FC
+:106880000101809E0460CAE000006EA801008C9D9A
+:10689000000096A80000AEA886C2FF070000F4A87A
+:1068A00000908CE5F9FFFF130460CAE0FFFF189F1A
+:1068B0000100109E0080D8E0003090E51800000C28
+:1068C0000000609D000006AB0000809D00908CE5FC
+:1068D0000F00000C080070B80101809E04187CE0D5
+:1068E00004D043E10460CAE000006EA801008C9D62
+:1068F000000096A80000AEA86EC2FF070000F4A832
+:1069000000908CE5F9FFFF130460CAE00100109EBF
+:1069100000C090E5EDFFFF130000609D00002185A1
+:1069200004004185080081850C00C18510000186A6
+:1069300014004186180081861C00C1862000018752
+:1069400024004187280081872C00C187004800442B
+:106950003000219CC0FF219C004801D4045001D488
+:10696000086001D4000043A90800801824E984A825
+:106970000800601828E963A80018AAE000206AE06F
+:1069800000008584000063841C1801D40000A584E5
+:10699000040060182E7163A8F8AEFF07202801D408
+:1069A00004006018407163A8F4AEFF071C008184E6
+:1069B0000800A01838C5A5A80800601874E163A8ED
+:1069C00000280AE10018CAE00200A0185C67A5A828
+:1069D00004006018557163A800288AE00000209D1B
+:1069E0000000E4840200A018D45BA5A8020080186F
+:1069F000D85B84A80028A7E1002087E12C00A784A9
+:106A00000000809C002005E4030000100000609D51
+:106A10000100209D244801D40200809C2C00A78402
+:106A2000002025E403000010000000150100609D17
+:106A3000285801D40800801874DE84A80000C68499
+:106A40000800A018F4DCA5A80200C6B8000008855C
+:106A50000020E6E0940088840028C6E00038EAE0E0
+:106A6000020084B80030CAE0002884E000208AE0F8
+:106A7000000084842C2001D49400A884080080188D
+:106A800074DE84A80000C6840200A5B8343001D4A6
+:106A90000020A5E00000E7840000809C0028AAE018
+:106AA0003C2001D4383801D40000A584302801D41A
+:106AB00000008C8500004D85B0AEFF0700008CA85B
+:106AC00004006018657163A8ACAEFF0700008AA8D7
+:106AD0000040A0182008A5A81C008184000065843F
+:106AE0000000C5840220C6E00000A5842000818447
+:106AF000181801D402208CE10C00619C102801D4EC
+:106B00000C3001D408C2FF07146001D400002185B5
+:106B10000400418508008185004800444000219C14
+:106B2000FCFF219C004801D40200A0185C67A5A8C6
+:106B3000002883E00000A4841800C5840200809C23
+:106B4000002026E40600001000000015ECFEFF0700
+:106B50000000001504000000000000157EFFFF0784
+:106B60000000001500002185004800440400219C1D
+:106B700070FF219C004801D4045001D4086001D466
+:106B80000C7001D4108001D4149001D418A001D449
+:106B90001CB001D420C001D424D001D428E001D4F9
+:106BA0002CF001D4000044AA0800A0188CE2A5A88B
+:106BB0000800E0180CE9E7A8002884E00800E019C4
+:106BC00000E2EFA90000C4850038D2E00078B2E00E
+:106BD0000000809C08000019F4E108A90800601971
+:106BE000FCE16BA90040B2E108002019F8E129A9F5
+:106BF0000058F2E00800201A1CE231AA002006D456
+:106C0000002005D4004892E1008812E108006019D4
+:106C100010E96BA904008018808484A80800E0199A
+:106C200064E8EFA90000A09C005832E1007852E12E
+:106C30000800201A50E631AA009004D4008872E1BE
+:106C400000280AD4004080181C2084A8FF0063A4F8
+:106C50000000809FFFFFC09C002807D400280CD4B0
+:106C600000280DD4002808D4002809D400280BD40B
+:106C7000002804D4741801D46C3001D40100409D64
+:106C800000502EE40600001058E001D40800E0187F
+:106C900090E2E7A8003872E000E003D40800001991
+:106CA00000E708A96C006185004072E00800201927
+:106CB000A8E229A97400E185004832E10000A09D06
+:106CC000005803D406004FBB544801D4046812D4C2
+:106CD000006809D4CBAFFF0700006AA8EDB7FF0733
+:106CE0000000609C0040A0186420A5A80800201A9D
+:106CF000B0E431AA00287AE0008892E000006384C2
+:106D00005800C184003003E4FF0C000C001804D4C8
+:106D100000406018140B63A800008384005024E432
+:106D2000F00C00100000001500406018580063A827
+:106D300000008384005004E4EA0C00105800018530
+:106D400000408018540884A800006484040063A4F0
+:106D5000004003E4DD0C0010000000150040601846
+:106D6000080563A8004080180C0584A80000A384CF
+:106D7000000064844B00A5B84B0063B8682801D4B8
+:106D8000641801D400402019402029A90800601986
+:106D90005CE66BA900489AE0005812E200006484A7
+:106DA0000000A09C0200409D500063B80000908449
+:106DB000005024E4030000100700C3A60100A09CBB
+:106DC000005036E4030000100000609C0100609C4D
+:106DD000031865E00000809D006003E49B0C000C3C
+:106DE00000000015005024E4030000100000A09CE7
+:106DF0000100A09C0500C09D007036E40300001057
+:106E00000000609C0100609C031865E0006003E4E2
+:106E1000850C000C0100A09D0100A09C002824E42A
+:106E200010000010007036E4030000100000809C89
+:106E3000000085A8005036E4030000100000609CAC
+:106E4000000065A8041864E0006003E4040000107A
+:106E500000000015082812D40300C09E0100A09C69
+:106E6000002836E43B0C00100400609C0800E01988
+:106E70004CE6EFA90000609C0078D2E300009E84FD
+:106E8000001804E42D0C000C0000001500408018D0
+:106E9000682084A800209AE100006C840000809C97
+:106EA0004E0063B8010063A4002003E40700001053
+:106EB000FE00769C0100809CFF0063A4002043E458
+:106EC000080C000C000000150040601948206BA958
+:106ED0000000A09C00589AE000006484002823E48D
+:106EE00013000010000000150800A01954E2ADA91D
+:106EF000006892E000006484002823E4030000108E
+:106F00000000C09C0100C09C0200609C001836E498
+:106F1000030000100000809C0100809C032066E0BC
+:106F2000002803E4E90B000C0000E09D0040201A5B
+:106F3000482031AA0000809C00887AE00000A384E9
+:106F4000002005E40F000010FE00769C0000708415
+:106F50000100A09C002803E40A000010FE00769CBB
+:106F60000800801854E284A8002072E000008384A6
+:106F7000002804E41100000C0100009FFE00769C34
+:106F80000100C09CFF0063A4003043E40B0000102C
+:106F90000100009F0800E01854E2E7A80038B2E0C2
+:106FA0000000609C00008584001824E4C20B000CE3
+:106FB0000300C09E0100009F00C036E4590B001082
+:106FC0000400609C00400019682008A9080080188F
+:106FD0008CE284A800407AE008006019ECE46BA918
+:106FE0000000E384002092E208002019ECE629A9C1
+:106FF0000000C3840058D2E10800A019F0E6ADA952
+:107000000000A384004812E20068F2E100008384DB
+:107010000800201AF8E431AA0800001990E208A933
+:107020000800601994E26BA90088B2E1004092E187
+:10703000005832E108006018A0E263A85000A5B82B
+:107040000800201A98E231AA001872E10C00089D8D
+:10705000FF3FA5A4004072E0008852E15E00C6B880
+:107060004F0084B80800201A48E631AA002803D44B
+:107070005F00E7B80000CE850000609C03C0C6E05A
+:107080000000AD8503C084E0008812E1007010D4D8
+:1070900000680FD4003814D4003009D4002008D47C
+:1070A00000180CD400180AD400280BD400C01ED439
+:1070B0000800C018F4E6C6A80000A09C0030D2E08A
+:1070C0000300609C00008684001824E40300001084
+:1070D000503001D40100A09C0100809D006016E4A6
+:1070E000030000100000809C00008CA8032085E0B5
+:1070F0000000609C001804E4560A000C000092A8EE
+:107100000100609C001816E4110000100000A09C13
+:1071100008006018ECE663A8001892E000006484A0
+:10712000400063A4002803E40900001000000015DB
+:1071300008008018FCE484A8002072E0000083842A
+:10714000002804E43F0A000C000000150800A01805
+:107150005CDCA5A80800C01860DCC6A808002019DF
+:107160009CDC29A90028B2E00030D2E00100E09CBC
+:107170000000009D004832E1003805D4004006D4EC
+:10718000482801D4443001D4404801D40040001ABA
+:10719000240210AA20BBFF07000000150800A01958
+:1071A00098DCADA90040601944206BA90068B2E0EA
+:1071B00000587AE0000085840040E0194C20EFA9D7
+:1071C0000800201AB8DC31AA000023850800A018A6
+:1071D00094DCA5A80078DAE0002812E1010060182C
+:1071E000FFFF63A80000A684031829E10088F2E0ED
+:1071F0000040C0180000C6A800006784003084E08A
+:107200000200609D0100E018FFFFE7A8004804D4D9
+:107210000338A5E1003063E00000E09D006803D47E
+:107220000000888500406018000163A800408018B5
+:10723000200184A8005803D41800ACB804006018DA
+:10724000748463A8007804D40000C38400408018CC
+:10725000180184A800400019582008A9002804D467
+:1072600004006018788463A80040FAE00000A3845A
+:107270000040201A000031AA00400019300208A97D
+:107280000000878400FC609C0088C6E0031884E04E
+:107290000088A5E0004060181C0163A80800201ABF
+:1072A000C4DC31AA002003D4008832E2004806D4AE
+:1072B000004080185C2084A8006805D400207AE192
+:1072C0000800A018ACDCA5A800406018200263A844
+:1072D000002892E0007803D4000044850800639CF5
+:1072E0000040C0180C04C6A8007810D400408018D4
+:1072F0002C0284A8007803D43C8801D4007804D4FC
+:10730000006811D4000067840800E01948E6EFA97E
+:107310000040C0190002CEA94A0063B80800E01876
+:10732000CCE4E7A80078B2E0080063B8003892E047
+:107330000000E09D006063E00000E584001808D4D0
+:10734000000084840040A0183402A5A84000618495
+:10735000004803D4602001D400006B844A0063B865
+:10736000080063B8005063E0001805D4000088846A
+:107370000080A0180000A5A8042884E0004000199F
+:10738000000008A9002006D400006684044063E0E1
+:10739000001806D400780ED4007807E4A409001081
+:1073A000000000150000D0840B006DB8020086B804
+:1073B000001884E0002884E000006484007823E45E
+:1073C0000C00000C09006DB80000809C003063E0E8
+:1073D000020063B80028A3E01000A59C0400C69C2E
+:1073E00000006584002023E4FCFFFF13000000156B
+:1073F00000406018240263A8003003D40000A09D60
+:1074000000406018100263A80100209E006803D4A9
+:107410000040E0194420EFA900406018000163A873
+:1074200000785AE1008803D40800A01864E8A5A8F1
+:1074300000406018482063A800008A8400189AE180
+:107440000028D2E06000E1840B0084B8FF0F00192F
+:10745000FFFF08A90000AC84034084E00000609CAA
+:107460000028A7E0D6B6FF070340A5E0004060185B
+:10747000200163A80040801808C584A8005803D4E0
+:107480000100209D000072A8004804D46AF8FF079C
+:107490000000001500006A84FF0F6019FFFF6BA950
+:1074A0000000A09D00008C840B0063B8FFFF409D8E
+:1074B0006000E1850358C4E10358E3E000002AA915
+:1074C00000006AA90078CEE10100809DFCFF209EAB
+:1074D0000080A0180000A5A8038867E0030087A427
+:1074E000002863E00000A384006004E44E0900105B
+:1074F000006084E44A090010000000150200609C4E
+:10750000001804E444090010900065B80300609C72
+:10751000001804E43E090010000000150100AD9DB4
+:1075200000708DE51C09000C0100E79C0100809CA7
+:10753000002025E420000010000000150000C09C81
+:10754000003029E4030000100000009D000004A9A1
+:1075500000302AE4030000100000609C000064A8D2
+:10756000031868E0003003E4050000100000809C70
+:1075700000302BE40409000C0300C09C002029E427
+:10758000030000100000C09C0100C09C00202AE401
+:10759000030000100000609C0100609C031866E07E
+:1075A000002003E40400001000200BE40600000C9F
+:1075B0000000001500006AA9000049A9C4FFFF03EC
+:1075C000000025A9FDFFAD9D0200209D5C6801D44F
+:1075D0006C4801D47400818461F8FF07000072A830
+:1075E0000000609C00182BE4D908000C0000209ECD
+:1075F000588801D4480081840000A09C0000648465
+:10760000002803E452020010480021864400C1848F
+:1076100000006684002823E44D02001000000015DD
+:1076200000406018240263A80000C09C0000A384EE
+:107630000100009E0800639C00008384008036E403
+:10764000030000100220C5E10000D0A80000609CEB
+:1076500000182EE404000010031866E0000070A873
+:10766000031866E00000E09C003803E4A308000C67
+:107670000000009D00406EE50800001000000015AD
+:10768000004020195C2029A900489AE00000648489
+:10769000420063B80018CEE10800601920E96BA928
+:1076A0000000A09D005852E100008A84006804E4B4
+:1076B0004608000C00000015080060198CE26BA958
+:1076C000005892E2000074840100409D005023E4C1
+:1076D0003C0800100000C09C0400B284003025E487
+:1076E0000A0000100000809C0800A01990E2ADA9DB
+:1076F000006872E000008384003004E42B08000C72
+:10770000740081840000809C002005E42008000CA7
+:107710005400C18400006684002003E41108000CBA
+:10772000000012A90300609C0018AEE5E9010010FA
+:107730000400609C0800E01890E1E7A80038F2E03F
+:1077400000006784002023E4E1010010303801D4F8
+:1077500008000019F4E108A9004012E33C0021856B
+:10776000004060182C0263A80080A0190000ADA999
+:10777000000089841F00E019FEFFEFA90000609D52
+:10778000000023850B0084B8020069B860002186E0
+:10779000002063E0005818D4006863E0000083878D
+:1077A00003787CE09D009CB89500BCB89800DCB8DC
+:1077B0000200E3B8030084A40700A5A4702001D44C
+:1077C0000000609C001811E4E40700101F0086A769
+:1077D0005C0061840018A5E0FFFF719C002827E28F
+:1077E000001871E404000010FEFF9C9CFFFF809FC6
+:1077F000FEFF9C9C0200609C001844E40300001003
+:107800000100809C002018D400007E840100A09C10
+:10781000002823E4110000100500E09C00283CE44F
+:10782000030000100000C09C0000C5A80500609C7B
+:1078300000183CE4030000100000809C000085A8B4
+:10784000042086E00000609C001804E4030000109F
+:107850000500E09CFFFF809F00383CE4030000101F
+:107860000000809C0100809C7000C1840000A09CEE
+:10787000002826E4030000100000609C0100609CCA
+:10788000031864E0002803E404000010F0FF7C9C6F
+:107890000100009D004018D40100009D004043E419
+:1078A000030000100000C09C0000C8A81400609CE9
+:1078B0000018BCE5030000100000809C000088A8B0
+:1078C000042066E0002803E4030000100000001517
+:1078D000004018D400007E84003823E41900001012
+:1078E00000000015080060199CE26BA90800A019AF
+:1078F000A0E2ADA90058F2E00800E01998E2EFA973
+:107900000800C01830EDC6A8006872E0007892E068
+:107910000030B2E0080060192CED6BA90000638410
+:107920000000A09D0058D2E00200E09D001807D49E
+:10793000006804D4004005D4006806D400781ED442
+:1079400000007884004023E47707000C0100299DA3
+:107950003C0061840080E0180000E7A800008384F8
+:10796000000048A9FFFF809D0B0084B8020069B8A1
+:107970004000C1840200A09D002063E00000A684B6
+:10798000003863E00300E09D0000C3840B00A5B84D
+:107990000000609D6C000185003071E0004063E0F4
+:1079A000006003E1FCFF809C0080E0180000E7A875
+:1079B000032068E0002863E0030088A4003863E047
+:1079C0000000E384005004E453070010480067B847
+:1079D000005084E452070010006804E44E070010D1
+:1079E000500067B8007804E4490700100000001553
+:1079F00001008C9D005807E4EBFFFF13FFFF089D7B
+:107A00006C0061851F00E019FFFFEFA90260A6E18D
+:107A1000005871E00040A0180404A5A8070083A442
+:107A2000420063B8180084B8037863E0042063E080
+:107A3000FF008018FFFF84A80320CDE000408018DD
+:107A4000000484A8001804D4003005D40000609C11
+:107A500000180CE4550000100300609C0018ADE411
+:107A6000530000103C0061854000A1840100089D86
+:107A70000000409D000065840100009E0B00E3B9FA
+:107A80000200A09CFCFFC09C0080E0180000E7A85A
+:107A9000033068E0030088A4007863E0003863E006
+:107AA0000000E384008004E417070010008084E4F1
+:107AB00013070010002804E40F070010500067B8F7
+:107AC0000300609C001804E4090700100000001582
+:107AD000FFFF089D0000A09C00282AE4030000107E
+:107AE0000000C09C0100C09C0300609C001807E4DB
+:107AF000030000100000809C0100809C032066E0D1
+:107B0000002803E41E00000C0100809C00202AE4F1
+:107B1000030000100000C09C0000C4A8002807E477
+:107B2000030000100000609C000064A8031866E0D9
+:107B3000002803E41200000C0200C09C00302AE47C
+:107B4000030000100000609D000064A9002807E405
+:107B5000030000100000609C000064A803186BE0A4
+:107B6000002803E40700000C0300609C01004A9D0C
+:107B70000030AAE5C4FFFF130000A6A80300609C24
+:107B800000182AE40A0000103C00618501006D9C89
+:107B9000FF000019FFFF08A900408018040484A812
+:107BA000034063E0001804D43C0061850100299D76
+:107BB0000800601854E663A800008B840200A9B88E
+:107BC000001812E20B0084B80100299D0080001902
+:107BD000000008A9020069B80020A5E0FF00E01934
+:107BE000FFFFEFA90040A5E0002063E00000A584AE
+:107BF000004063E00800E01858E6E7A8000083842E
+:107C00000378CDE0003892E2842801D4010084A4F6
+:107C1000006010D4003014D40100299D0000A09C05
+:107C20000000609C00183CE403000010882001D490
+:107C30000100A09C0C00609C0018BCE50300001033
+:107C40000000809C0100809C042085E00000609C76
+:107C5000001804E4030000100100609D005818D4CF
+:107C60000040401904044AA90000609D00006A8495
+:107C7000005823E404000010000000150100A09D3E
+:107C8000006818D40040E0195C20EFA900789AE061
+:107C900000006484420063B8001889E40300001007
+:107CA000000000150000209D004060182C0263A811
+:107CB0000000A09C004803D40800809C0020BCE584
+:107CC00003000010000000150100A09C00583CE4D7
+:107CD000030000100000609C0100609C041865E037
+:107CE000005803E40C0000100000001508006018A4
+:107CF00050E663A800008A840018D2E00000B08437
+:107D000000006684002884E0002063E00200639C99
+:107D1000001806D400007E840100E09C003823E4B3
+:107D2000030000100000809C000087A80600009D52
+:107D300000403CE4030000100000609C000067A8C5
+:107D4000031864E0005803E40D0000100000001563
+:107D50000800A01850E6A5A800008A840028D2E0F8
+:107D6000FFFF809F0000B08400006684002884E04C
+:107D7000002063E00200639C001806D4003816E47B
+:107D8000290000100800609C00403CE42600001020
+:107D9000000000150800C018ECE6C6A8003092E00C
+:107DA00000006484080063A4005803E41E0000106F
+:107DB0000800609C000094840800E018FCE6E7A836
+:107DC000FCFF009D0500849C0038B2E09F0064B871
+:107DD0000000C5845E0063B8001884E0034084E0BE
+:107DE0002800A49C003065E53A06000C000072A84B
+:107DF0000800A01974E1ADA90800E019DCE5EFA9BD
+:107E0000006852E100006A84001872E0007863E0C4
+:107E10000000838C005824E42606000C00000015A6
+:107E20000800609C00185CE5100000100000A09C99
+:107E300000007884002823E4030000100000C09CA8
+:107E40000100C09CFFFF609C00181CE403000010B0
+:107E50000000809C0100809C032066E0002803E471
+:107E60009A02000C8400818400406018240263A8F8
+:107E70000000C09C0000A3840800639C0000838471
+:107E80000220C5E100306EE5090000100300609C8F
+:107E9000004000195C2008A900409AE000006484BA
+:107EA000420063B80018CEE10300609C0018AEE504
+:107EB000080000100400609C3000218500006984E7
+:107EC000003023E426FEFF0F000000150400609C34
+:107ED00000184EE51D0000104800218608006019BA
+:107EE000A0E16BA90040A0182002A5A80058F2E06C
+:107EF0000000A58400406018280263A80100809C4F
+:107F00000000C784002803D4002026E40F000010DE
+:107F1000480021860800A019A47DADA90000E09DBD
+:107F2000006872E0007807D40000A3840000809C01
+:107F3000002005E46102000C00000015F427000495
+:107F4000000072A8480021860000A09C00007184F7
+:107F5000002803E4000100104400818400006484D0
+:107F6000002803E4FC0000100100609C08009284DB
+:107F7000001824E44802000C989980A80800C01852
+:107F800020E2C6A8003052E100006A84002803E421
+:107F90000D000010000000150800E018A47DE7A8FF
+:107FA000003872E000008384002804E43602000CEC
+:107FB00000000015D6270004000072A80000009DF4
+:107FC00000400AD40800201964DC29A90000809C24
+:107FD0000048D2E100006E84002003E42602001075
+:107FE000000000150800601934C56BA9005812E1A3
+:107FF0000000A884002005E4EA010010000000153C
+:108000000200A0195C67ADA910008584006892E1A8
+:108010000000EC8468006784001824E4E10100108B
+:108020000000CCA82C00E7840100209D004827E434
+:10803000060000100200609C00008584001804E423
+:108040000900001000000015001827E4D5010010F9
+:108050000000001500006584004803E4D101000C15
+:1080600000000015000066840200E019C85BEFA95B
+:108070000000A09C007863E00000C384002806E4B0
+:108080000700001000000015000068840C008384C5
+:10809000002824E40A00001000000015002826E44F
+:1080A000C001001000000015000068840C008384EB
+:1080B000002824E4BB010010000000150800201A6D
+:1080C00068DC31AA0000A09C008892E00800C0187B
+:1080D00074E1C6A8000072A8002804D4990A00041C
+:1080E000003052E100008A84FFFF609C001804E425
+:1080F000990000100100A09C00006E84002823E479
+:10810000770100100000609C0800C01898E1C6A824
+:10811000003072E000008384002824E46C01001029
+:108120000200809C0200E0185C67E7A8003892E13A
+:1081300000006C841800A384002025E40A000010CD
+:108140000000809C0800001968DC08A9004072E06B
+:108150000000A384002005E45901000C0000001574
+:1081600000006C84BA0C0004000092A8080060199A
+:10817000E87B6BA9005872E00000A38404008584AA
+:108180006300609C0018A4E40E01000C00000015C0
+:1081900008006018E47B63A8001852E10000809C8E
+:1081A00000406018280863A800200ED4002003D4E3
+:1081B0000400639C002003D400006C849535000407
+:1081C000000092A800000C8502006018005C63A803
+:1081D0000200A0190C5CADA90000EA84001888E038
+:1081E0000800E01980E2EFA90C00E784006868E06D
+:1081F000007832E1003803D40200201A045C31AA6E
+:1082000002006019085C6BA90800E8850088A8E0F6
+:108210000058C8E0000084840000E09C18006884D6
+:10822000007806D42C002886002005D4341808D401
+:108230004800C1840000A09C004060180C4063A866
+:10824000308808D400008984002803D4002824E45E
+:1082500003000010002806D40100E09C0200609C8E
+:10826000001824E4030000100000C09C0100C09C22
+:10827000043067E0002803E4B5000010000000159A
+:1082800018006884002823E4B10000100100E09C7D
+:1082900000408018000A84A80040A0185408A5A82F
+:1082A000003804D400006584043863E0001805D465
+:1082B0000100409DC30B0004000072A800502BE495
+:1082C0009F00000C0000001508006019ECE66BA987
+:1082D0000000C09C005892E000006484010063A488
+:1082E000003003E40F000010000000150800A01982
+:1082F00078E2ADA90800E0197CE2EFA9006892E0FD
+:1083000000406018300C63A8000084840078B2E05C
+:10831000002003D40000A5840400639C002803D43B
+:108320000800201A707D31AA008872E00000838462
+:10833000003024E4770000100000809C00406018AA
+:10834000080863A800008AA8005003D4E5A2FF072C
+:108350000808609C00406018484063A800008384BF
+:108360000000609C800084A4001804E44300001016
+:108370005800A18400406018180463A80800E018A1
+:1083800058E6E7A8000083840038D2E00400009D8E
+:1083900000406018140463A80700849C0000A384B4
+:1083A000430084B80000C6840020E5E0023067E0A6
+:1083B0000040A3E505000010023866E00040A3E598
+:1083C0000300000C000000150000E6A808000019DA
+:1083D00054E608A90800201950E629A9004092E0B7
+:1083E0000048B2E0000064840000609D0040C018B6
+:1083F0000000C6A8001867E0000085840200E39C26
+:10840000FB03209E003884E000406018182063A819
+:10841000002005D4002003D44800A1850040601846
+:108420000C0863A8FF03809C005803D40100E09D62
+:10843000008806D444006184002006D4005803D488
+:1084400000408018080484A8000072A8005804D4D2
+:10845000A00D000400780DD4740081842000609C7D
+:108460005800A09C0000C09C0000E09C31EEFF077B
+:10847000000012A95800A1841027609C0100A59C4F
+:10848000001825E45CFCFF13582801D40400601890
+:10849000717163A839A8FF073133809C0800C018A8
+:1084A00050E6C6A800406018182063A80030B2E06B
+:1084B00000408018240284A80000A584002803D46A
+:1084C0000000A484004060182C0263A8000083848C
+:1084D000002025E40B00000C74008184000012A928
+:1084E0002000609C5800A09C0000C09C0000E09C04
+:1084F00010EEFF070000001509070000000000153E
+:10850000000012A92000609CF8FFFF037C00A09CE3
+:1085100048006184005003D44400A18400406018E6
+:10852000080463A8002003D4002005D4690D0004CA
+:10853000000072A888FFFF0300000015F4B0FF07D9
+:108540000000001561FFFF030000001500006984B2
+:108550000100C09CFFFF639C003043E40F0000104B
+:108560000000001500006C8418008384003024E4AF
+:108570000A0000100000001500408018000A84A8BE
+:108580000040A0185408A5A8003004D40000658459
+:1085900047FFFF03043063E000408018000A84A80E
+:1085A0000000009D0040A0185408A5A8004004D475
+:1085B000FEFF209D000065843DFFFF03034863E04C
+:1085C0000800A019E47BADA9000085A8006852E16D
+:1085D0000000B2A89C0D000400006A840800E019A5
+:1085E00070E2EFA90000A09C007872E03F00C09C00
+:1085F0000000638400408018001084A800002386D7
+:108600000100A59C008804D40400639C0030A5E50B
+:10861000FBFFFF130400849C0800801874E284A808
+:108620000000A09C002072E03F00C09C000063841A
+:1086300000408018001184A80000E3840100A59C7C
+:10864000003804D40400639C0030A5E5FBFFFF1351
+:108650000400849C0800A01958E2ADA90000209DE8
+:108660000F00E09C0500609D0012009D0068D2E0B4
+:108670000040E0190000EFA9000066840000A09C03
+:10868000007888E0000023860100A59C008804D4BF
+:108690000400639C0038A5E5FBFFFF130400849CE5
+:1086A0004000089D0100299D0058A9E5F1FFFF1336
+:1086B0000400C69CBBFEFF030000809C142600043F
+:1086C000000072A8A8FEFF0300006C8402002019BD
+:1086D0005C6729A9A3FEFF03004892E10200A018ED
+:1086E0005C67A5A8002892E10000CC843C00868449
+:1086F000001804E41F0000100000ECA83800A68455
+:1087000002000019D45B08A90040C6E0140065848B
+:10871000000086840A2363E0010063B800408018EB
+:10872000280884A8001804D4000087840200A01937
+:10873000D45BADA908006019E47B6BA938006484A0
+:10874000005852E1006884E01400A3840000C4844F
+:108750000A3365E0004080182C0884A8063363E0E3
+:108760000218A5E0002804D495FEFF0300006C84E5
+:108770003800A68402002019D45B29A90048C6E06D
+:1087800014006584000086840040A0182808A5A86D
+:108790000A2363E0001805D4E5FFFF030000878487
+:1087A0000800E01874E1E7A8FFFF809D003852E15F
+:1087B00000008A84006004E42B00000C0000001517
+:1087C000020064B808000019EC7B08A90700209D8E
+:1087D000004063E0001872E0006004E40A0000104A
+:1087E000004803D45800609C0800601950D16BA960
+:1087F000061B64E00100A09D005863E0001872E0D1
+:10880000006803D40800E01968DCEFA90100209E8D
+:10881000007872E00500809C00203CE432FEFF13EB
+:10882000008803D4020060185C6763A80200801807
+:10883000EC5B84A8001892E100006C84002063E0E7
+:108840000000A3840000809C002025E426FEFF1386
+:1088500000000015AE250004000072A823FEFF03EF
+:1088600000008A84B7080004000072A8D5FFFF0347
+:1088700000008A840800A01874E1A5A81AFEFF036E
+:10888000002852E1250A0004000072A8CAFDFF0377
+:108890000000001504006018867163A837A7FF0761
+:1088A00000000015740061842B060004000092A8EB
+:1088B0001B06000000000015180A0004000072A842
+:1088C0009FFDFF030000001500406018080463A826
+:1088D0000000A09C0100E09C8800C184002803D413
+:1088E000782001D48C0001857800A19C7C3001D4D3
+:1088F000003803D47000818400007CA80000D2A856
+:1089000040090004804001D4FAFF9C9C0200609C56
+:10891000001844E41D0000100400009D0040601891
+:10892000180463A80000F4840000838400406018E9
+:10893000140463A80700849C0000A384430084B847
+:108940000020C5E0023866E00040A3E50500001005
+:10895000023067E00040A3E50300000C00000015B2
+:108960000000C7A8000070840800201950E629A95B
+:108970000048B2E0001866E0000085840200C39C55
+:10898000003084E0002005D4020060195C676BA908
+:108990000200A09C005892E100006C8418008384BF
+:1089A000002804E40C00001000000CAA0800A01924
+:1089B000A4E1ADA90100809C006872E0000063841E
+:1089C000002003E404000010002803E40700000C6A
+:1089D000000000150800E01950E2EFA90100209EF8
+:1089E000007872E0008803D40800601898E163A85A
+:1089F0000000A09C001892E200009484002804E487
+:108A00000C0000100200C09C0000708418006384F9
+:108A1000003023E4FA020010002823E40800A01824
+:108A200040E2A5A80000C09C002892E0003004D4D9
+:108A30000100809D00603CE43F02000C000072A831
+:108A40000500609C00183CE4D901000C000072A8ED
+:108A50000800201AF8E131AA0000A09C0088D2E0AA
+:108A600000006684002823E41000001000000015B8
+:108A700008008018FCE184A8002072E000008384D4
+:108A8000002824E409000010000000150800E01888
+:108A900000E2E7A8003872E000008384002824E4A4
+:108AA000BE01000C0000A09D080000191CE208A9EE
+:108AB0000100209D004052E100480AD400009E843D
+:108AC0000100609C001824E40D0000100000E09CF0
+:108AD00000006684003823E49701001000000015B0
+:108AE0000800E019FCE1EFA9007872E0000083843F
+:108AF000003824E490010010000000150000EA8412
+:108B00000100809C002027E45601000C00203CE47A
+:108B1000030000100000C09C0000C4A80500609C79
+:108B200000183CE4030000100000A09C0000A4A872
+:108B3000042866E00000409D005003E4120000108D
+:108B4000000000150800801840E284A8002072E0B0
+:108B500000008384005024E40B000010005027E440
+:108B600009000010000000150800A01850E2A5A898
+:108B7000002872E000008384005004E40800000C28
+:108B8000000072A800406018080463A80000E09C80
+:108B9000003803D4B5FCFF03000000150800C0181E
+:108BA00064DCC6A8003092E086090004000084AAB4
+:108BB00000500BE485000010005814D40800E018A1
+:108BC000A47DE7A8003872E00000C384005006E4EA
+:108BD00017000010000000150000F08402000019CA
+:108BE000105C08A9004067E09C00A6840000838414
+:108BF000002025E4140100100000001502002019D7
+:108C0000145C29A9A000A684004867E000008384C2
+:108C1000002025E40C01001000000015020060197E
+:108C2000185C6BA9005867E0005003D40000308541
+:108C30000200201A645C31AA0000809D008849E18E
+:108C400000006A84006003E41300001000000015B7
+:108C5000020060186C5C63A80200A018D05BA5A895
+:108C60000018E9E00200C018705CC6A8002869E09E
+:108C7000003009E1680089840000A7840000C384F3
+:108C8000002884E00A3364E0063363E0021884E0DD
+:108C9000002008D40200E018C45BE7A8003869E0AF
+:108CA00000008384006004E4070000100000001549
+:108CB00002000019705C08A968006985004069E03D
+:108CC000005803D400006A84006023E41D000010F3
+:108CD000000000156800E98458008984002007E43A
+:108CE000180000100100849C0200A019D05BADA9FF
+:108CF0000068C9E00000A6840A2B64E0062B63E04C
+:108D0000021884E0002007E40E00001000000015A7
+:108D10000800E019E87BEFA9007872E00000838486
+:108D20001008A484006025E4730000100000809CFB
+:108D30000800201A20E231AA008872E0002003D443
+:108D40000000708401EAFF07000092A80000D084B0
+:108D500002000019705C08A9004066E06800A68463
+:108D600000008384002824E40E0000100000001599
+:108D700002002019745C29A9FF7F6018FFFF63A817
+:108D80000048A6E000008584001824E405000010D7
+:108D9000000000156400C684003005D40000D084B3
+:108DA00002006019C85B6BA90000809C005866E057
+:108DB0000000A384002005E404000010000000155A
+:108DC0006800A685586806D4000094840000609C62
+:108DD000001824E40D000010000000150000B0840D
+:108DE0001800858434006584001824E4070000100E
+:108DF00000000015300085842C006584002023E4E9
+:108E00003800000C0100A09C0800E0196CDCEFA900
+:108E10000100209E007872E0008803D40000D08416
+:108E20000000B2A80000409D3800668410008384D2
+:108E3000C1120004180066840000D0840000B2A8AB
+:108E400018006684F3180004380086840000B0849B
+:108E50002C006584005023E41E00000C0000001567
+:108E60003C006584005003E417000010000000156A
+:108E70003800858414006484010063B8001805D4A8
+:108E80000800C01800E2C6A80000809C003072E014
+:108E90000000A384002025E43BFFFF130000A09CFA
+:108EA000000070840100209E02008018645C84A889
+:108EB0004400E185002063E000880FD404FCFF0338
+:108EC000002803D438006584EDFFFF031400638499
+:108ED0004B160004000072A8E2FFFF030000B084FC
+:108EE000080080186CDC84A8002072E0CCFFFF032F
+:108EF000002803D47400A1840200409D000069A8EA
+:108F000068270004000092A800502BE43E00000CEB
+:108F100000602BE48BFFFF135000A1840300C09C72
+:108F2000D0A7FF07003005D40800E01854E2E7A8F6
+:108F30000100609C0038B2E000008584001824E441
+:108F400004000010000000150000009D004005D442
+:108F5000530C0004000072A80800201978E129A928
+:108F600008006019F4DD6BA9004892E00800A01920
+:108F700074DFADA900006484000012A9020063B888
+:108F80006800E185005883E064002186006863E0A2
+:108F9000002092E0001872E00000A4840000C38466
+:108FA0000028AFE000406018102063A80030D1E036
+:108FB000002803D40C00F2840400639C0040A01835
+:108FC0001820A5A8003003D40200E79C0800639C89
+:108FD0000000C09C005003D40C3812D4003005D4DB
+:108FE0002400E09C0040C0182C20C6A87400818496
+:108FF0000500609C0000A09C003806D43CFDFF03E7
+:109000000000C09C04006018AA7163A85BA5FF075C
+:109010003333809C0800E01950E6EFA90078B2E0F5
+:109020000000A58400406018182063A8000012A961
+:10903000002803D4740081842000609C2BFDFF0372
+:109040007D00A09C000070840200A019185CADA9EE
+:109050000100E09D006863E0F5FEFF03007803D4A3
+:109060000800001950E608A90800E0180CE9E7A874
+:10907000004092E0003892E10000848400406018D3
+:10908000182063A80000E09C0000AC84002003D4FA
+:10909000003805E42100000C74008184000066841F
+:1090A000003803E41800000C0000609D0800A019BF
+:1090B000FCE1ADA9006892E000006484003803E49C
+:1090C0000D000010000012A90000E09D007804D4FB
+:1090D0002000609C740081848200A09C0000C09CE1
+:1090E00014EBFF070000E09C0000209E0C04000031
+:1090F00000880AD4740081842000609CF8FFFF037C
+:109100008300A09C000012A92000609C005806D497
+:10911000F3FFFF038100A09C000012A92000609CC7
+:1091200004EBFF070000C09C0000209DEFFFFF0341
+:1091300000480CD40800801850E684A80800201AC3
+:109140000CE931AA0020B2E0008872E00000A5849A
+:1091500000408018182084A8002804D400006384EC
+:109160000000A09C003803E40700000C00281ED477
+:1091700074008184000012A92000609CDBFCFF03C6
+:109180003400A09C0000A3A874008184000012A9F0
+:10919000D6FCFF032000609C080060191CE26BA94C
+:1091A000005852E146FEFF0300680AD40800C018C8
+:1091B00064DCC6A8003092E002080004000084A924
+:1091C0000800E01840E2E7A80000009D003892E0A7
+:1091D0000000D0840800201948E229A90200E01903
+:1091E000C85BEFA9004004D400580CD40048B2E09A
+:1091F0006800A685007866E0080060194CE26BA95B
+:10920000006805D4005812E100006384001808D4F7
+:109210006C0086840100609C001824E4410000106A
+:109220000000809C0800201A44E231AA2C00C68469
+:10923000008852E100300AD400006C840100209DB7
+:10924000004823E403FEFF13000000150800E018A7
+:10925000CCE1E7A80800A01988E2ADA90038D2E067
+:109260000000A584006872E100006684004863E0A5
+:109270000000F084001806D468008784002025E4EC
+:10928000260000100000809D2C00A784004825E4E3
+:10929000060000100200609C00008A84001804E4AC
+:1092A0000900001000000015001825E41B00001044
+:1092B0000000001500006A84004803E41700000C59
+:1092C00000000015000070840200E019C85BEFA9DF
+:1092D0000000A09C007863E000008384002804E480
+:1092E000060000100000001500006884002823E438
+:1092F0000900001000000015002824E407000010F9
+:109300000000001500006884002823E4030000101A
+:10931000000000150100809DCEFDFF0300600BD40E
+:109320000800601844E263A8001852E1C3FFFF037D
+:1093300000200AD40800801864DC84A8A107000477
+:10934000002052E100602BE4BEFDFF1300580AD458
+:109350000800C018CCE1C6A80800E01848E2E7A859
+:109360000030B2E0003892E0000065840800001987
+:1093700088E208A90000E09C006063E00000D0845F
+:10938000004012E1342001D4001805D40000848488
+:1093900068006684001824E492000010384001D46C
+:1093A0002C00A684006025E48A0000100200609C66
+:1093B0000800601944E26BA9005852E100008A8459
+:1093C000001804E40A000010000000150200609C70
+:1093D000001825E47B0000100000001500006A84DE
+:1093E000006003E47300000C0000001500007084AE
+:1093F0000200E019C85BEFA90000A09C007863E0C0
+:1094000000008384002804E46600001000000015BA
+:109410000800201A4CE231AA008892E100006C8416
+:10942000002823E40900001000000015002824E4AF
+:10943000080000103800218500006C84002823E417
+:10944000050000100000C09C0100E09C3800218550
+:109450000000C09C003027E44E000010003809D402
+:1094600000007484003023E4460000107000618521
+:1094700000302BE43D0000100100E09C0800A01922
+:1094800008E2ADA9006892E000006484003823E49B
+:1094900036000010000000150800E01910E2EFA9E6
+:1094A0000078B2E000006584003023E42F00001053
+:1094B000000000150800C01818C5C6A80800201A2A
+:1094C00040E231AA003072E0008892E0000063843C
+:1094D000003804D4001805D4000064840100809E84
+:1094E00000A023E41D00000C000000153800A18539
+:1094F0000000609C00008D84001804E40D00001042
+:109500000000001500180AD4000070840200A018A2
+:10951000C85BA5A86800838434002186002863E026
+:10952000002011D40000638446FDFF0300180CD412
+:10953000000090846C00648400A023E40500001007
+:109540000000E09D2C008484F0FFFF0300200AD47B
+:10955000EEFFFF0300780AD45E090004000072A841
+:10956000E4FFFF033800A1850800E01840E2E7A807
+:109570000000009D003892E0D8FFFF03004004D4B3
+:109580000800601940E26BA9D4FFFF03005892E085
+:109590000800201940E229A9D0FFFF03004892E00B
+:1095A000080060184CE263A8A1FFFF03001892E1D5
+:1095B000080000194CE208A9A5FFFF03004092E152
+:1095C0000800C0184CE2C6A8A1FFFF03003092E1DA
+:1095D0000800A01944E2ADA97DFFFF03006852E135
+:1095E0000800801844E284A80800A0184CE2A5A84E
+:1095F000002052E196FFFF03002892E113000010C3
+:109600000100E09C0100609C001824E407000010A9
+:10961000003024E40800E01840E2E7A8003892E0B7
+:1096200004FDFF03001804D403FDFF130100809D17
+:109630000800001940E208A90000209D004092E0C7
+:10964000FDFCFF03004804D4003823E4FAFCFF13B8
+:109650000100809D003024E4030000100000009D04
+:10966000000007A97000618500280BE403000010CA
+:109670000000609C000067A8031868E0002803E46D
+:10968000070000100000E09D0800A01940E2ADA90D
+:10969000006892E0E7FCFF03007804D40800201A79
+:1096A00040E231AA008892E0E2FCFF03003804D4D3
+:1096B0009AFF209E008803D804006018CC7163A82C
+:1096C000AEA3FF07000085A8D7F9FF030800609C40
+:1096D00040002185000089840B0084B81EEEFF073E
+:1096E000008884E0D0F9FF030800609CF9F8FF03CC
+:1096F0005800E7B8F7F8FF03FF00E3A4F5F8FF030D
+:10970000FF00E7A4FCFFFF03480067B8B9F8FF03B8
+:109710005800E7B8B7F8FF03FF00E3A4B5F8FF036C
+:10972000FF00E7A40800601950E66BA9004060182C
+:10973000182063A8005892E00000A09D00008484D7
+:10974000000012A98000A09C002003D4006818D457
+:1097500090FEFF037400818426F8FF03002827E2AF
+:109760000800201950E629A900406018182063A8B5
+:109770000048B2E0740081840000A584002803D46E
+:109780002000609C59FBFF030000A09C74008184B2
+:10979000000072A86800A184820300046400C184F0
+:1097A0005F020000000000151D030004000072A805
+:1097B00004006018A08063A8590200000C5003D474
+:1097C000D1F7FF030400B2840200E0195C67EFA93F
+:1097D00004006018DD7163A868A3FF07007892E1B8
+:1097E0000800201A28E931AA0800801824E984A872
+:1097F000008872E00020F2E000000C850200A01852
+:10980000D45BA5A8080060198CE26BA900008384D2
+:10981000002828E10040C0180000C6A800006984A4
+:109820001B00A09D005892E2061B84E00000A78464
+:109830000000E09DFF03209E006806D400780AD453
+:10984000008806D400007484008003E40300001044
+:109850000020A5E0048012D408006018ECE663A89C
+:10986000001892E0000064840000809C020063A461
+:10987000002003E494F7FF13000000150200C01855
+:10988000E85BC6A82C008884003068E00000E09CFB
+:10989000003824E40D0000100000C384003065E4AB
+:1098A00089F7FF13000065A8000086A808000019CA
+:1098B00030E908A90000D0A8C0E8FF070040B2E0E6
+:1098C00082F7FF0300007484410086B8002065E43D
+:1098D0007DF7FF13000065A80000C9840800201967
+:1098E00030E929A90048B2E0C9E8FF070000F0A864
+:1098F00076F7FF030000748408007284008023E47C
+:109900000F00000C000012A9740081842000609CEC
+:1099100000381ED43400A09C06E9FF070000C09C5C
+:1099200004006018FB7163A8009080A813A3FF07D0
+:1099300000000015FA010000000000150400601886
+:10994000297263A8D6FBFF03999980A804006018C8
+:10995000487263A809A3FF073333809C0040601856
+:10996000182063A80000E09C74008184000012A904
+:109970005300A09C003803D40000C09CDDFAFF0314
+:109980002000609CFCFFAD9D5C6801D412F7FF03D2
+:109990006C3001D40100609C001836E40B00000C10
+:1099A0000000001504006018657263A8F3A2FF07A9
+:1099B0005300809C74008184000012A92000609CE8
+:1099C000CAFAFF037B00A09C04006018797263A8A8
+:1099D000EAA2FF075200809C0000009D7400818471
+:1099E0002000609C3400A09C00401ED40000C09C5D
+:1099F000000012A9CFE8FF070000E09C04006018F7
+:109A0000897263A8CAFFFF03029080A8C4F6FF030F
+:109A10005800A5B8C2F6FF03FF00A3A4C0F6FF03D9
+:109A2000FF00A5A4FCFFFF03880065B800016019D2
+:109A300003186BA900580ED472F6FF030000A09D16
+:109A400003EBFF07000072A8C1F5FF03000000153B
+:109A50000800E01874E1E7A898260004003852E1F5
+:109A60000000CAA908000019B4E408A900580ED4DF
+:109A7000FFFF609C00182BE46C00000C004012E318
+:109A800000180BE42F0000100000009E0800201AB0
+:109A9000ACE231AA008892E200007484001890E5DC
+:109AA0002500000C08588CE000406018602063A876
+:109AB0000018BAE000004BA900006584032063E0B1
+:109AC000008003E41B00000C00008AA84C2801D48D
+:109AD0000000609C0000B2A83D2600040100109E1A
+:109AE00000008AA80000609CFF2500040000B2A8C6
+:109AF0000000609C71260004000092A8000074849D
+:109B000008588CE000004BA9001890E50900000CF3
+:109B100000580ED44C00A1840000C09C0000658455
+:109B2000032063E0003003E4EAFFFF1300008AA88B
+:109B300000007484001890E53400000C000000154B
+:109B40000000EE8408002019ECE629A90800E019BD
+:109B50008CE8EFA90200C7B8004812E15000618507
+:109B6000007886E00000A09D00006884002092E05C
+:109B70000000A09C00680BD4020063A4002803E44A
+:109B80000C000010006804D40800201A30E931AA43
+:109B9000FE00809C008872E00000209D0100A59CD2
+:109BA000004803D40020A5E5FDFFFF130400639CDB
+:109BB000000068840000809C5F0063A4002003E430
+:109BC00051F5FF130100609C08006019FCE66BA9C9
+:109BD0005C00B885005872E000C0C6E0006803D49D
+:109BE0000800E019F8E6EFA96000C684007892E06A
+:109BF00000C0A7E0003004D40000209E288905D8CA
+:109C000040F5FF03488905D804006018AA7163A8CD
+:109C10005AA2FF073233809C0800E01850E6E7A8FC
+:109C200000FDFF030038B2E08EA4FF07000000151E
+:109C30000800201954E229A9004892E00000648439
+:109C4000006023E4030000100000609D005804D46D
+:109C50000800A019A4E2ADA9000072A8006892E073
+:109C600075EEFF07006004D40D090004000072A81F
+:109C70000800E01978E1EFA90800201AF4DD31AA04
+:109C8000007892E00800A01874DFA5A800006484A2
+:109C90000200609D0000A09D020063B8680001857D
+:109CA0002400E09D008883E064002185002863E0B3
+:109CB000002092E0001872E00000A4840000C38439
+:109CC0000028A8E000406018102063A80030C9E018
+:109CD000002803D40C00F2840400639C0040A01808
+:109CE0001820A5A8003003D40200E79C0800639C5C
+:109CF0000040C0182C20C6A8005803D474008184EA
+:109D0000000012A90500609C006805D40C3812D42C
+:109D10000000A09C007806D4F5F9FF030000C09C69
+:109D2000001836E45F00000C0300809D006036E4FC
+:109D3000E0F4FF130000609C0800801854E284A83F
+:109D4000002052E100008A84001824E4040000107E
+:109D500000000015D7F4FF0300C00AD441A4FF0798
+:109D60000000001534EEFF07000072A8CC080004C4
+:109D7000000072A80800A01878E1A5A8004080188B
+:109D8000182084A8002872E00000C09C0000A38472
+:109D9000003004D4FFFF609C001825E42B00001065
+:109DA000020065B80000708400C023E41C000010AD
+:109DB0000000E09C003010D400300AD400301ED4E3
+:109DC000004060181C2063A80200809C006003D43F
+:109DD00000202CE40C000010000000151000639C13
+:109DE0002300809C002003D40C00B284000012A940
+:109DF0000500609C0200A59C7400818462FEFF0344
+:109E00000C2812D4004060182C2063A80300A09CEA
+:109E1000002803D4F6FFFF030C00B2840500009D68
+:109E2000000072A800380AD4380B000400401ED489
+:109E30000000209D084812D4E1240004000072A80C
+:109E4000E0FFFF030000001508006019F4DD6BA9B6
+:109E50000800A01974DFADA9005883E06800E1850F
+:109E6000002092E0006863E00000A484001872E023
+:109E70000200809D000083840028AFE0004060184D
+:109E8000102063A864002186002803D4002091E0FC
+:109E90000400639C002003D4CAFFFF0300000015E8
+:109EA0007400818496EAFF07000072A89C000000FD
+:109EB00000000015003005D415200004000072A831
+:109EC0003EF4FF030100009F00406018182063A8C3
+:109ED00074008184007803D4B9FEFF03000012A946
+:109EE00000004C85FFBFA09C0000809C040060180F
+:109EF000B17263A8A1A1FF0703284AE10500C09C35
+:109F0000000072A8010B000400301ED40000E09C89
+:109F1000000072A8AA240004083812D4080000190E
+:109F200054E208A90000209D004072E000500CD4CB
+:109F3000E6F3FF03004803D40000928C0600A09CC7
+:109F40004DA6FF0774006184750000000000001535
+:109F5000001836E41D000010FE00769C0800201A50
+:109F60004CE631AA0000E09C0088D2E300009E8409
+:109F7000003824E41200000C0500609C001824E462
+:109F8000030000100000009D000005A90200609C75
+:109F9000001824E4030000100000C09C0000C5A8C5
+:109FA000043068E0003803E4B9F3FF130000001543
+:109FB0000000928CE3FFFF030900A09C0000928C3C
+:109FC000E0FFFF030800A09CFF0063A4002843E417
+:109FD0001200001000000015080060184CE663A88D
+:109FE0000018D2E300009E840000609C001824E466
+:109FF0000700000C002824E4A5F3FF13000000155F
+:10A000000000928CCFFFFF030C00A09C0000928CFC
+:10A01000CCFFFF030B00A09C0000928CC9FFFF0344
+:10A020000200A09C0201809C086812D4006810D431
+:10A0300004006018CC7263A850A1FF070300C09E03
+:10A0400076F3FF0300009084080060187C7D63A80D
+:10A050000800601918C56BA9001892E00800E01903
+:10A06000787DEFA9005872E00800201A64E631AA52
+:10A070000800201968E629A9000084840078D2E04D
+:10A080000800A01960E6ADA9000063840088F2E032
+:10A090000048B2E00000C684006812E1002007D446
+:10A0A000001805D40101809C003008D4086012D447
+:10A0B00004006018EA7263A830A1FF07006010D4A2
+:10A0C00049F3FF0300009084004060180C0563A86A
+:10A0D00000408018080584A825F3FF030000001540
+:10A0E00000406018080563A8000083840000A38472
+:10A0F0004B0084B84B00A5B8682001D422F3FF03BD
+:10A10000642801D40800E018B4E4E7A82AA5FF07F2
+:10A11000003892E0FFF2FF030000001500002185E7
+:10A1200004004185080081850C00C185100001866E
+:10A1300014004186180081861C00C186200001871A
+:10A1400024004187280081872C00C18700480044F3
+:10A150009000219CD4FF219C004801D4045001D4DC
+:10A16000086001D40C7001D4108001D4149001D483
+:10A1700018A001D41CB001D420C001D424D001D433
+:10A1800028E001D4000084A90800A018E87BA5A855
+:10A190000800C018787DC6A8002884E00800E018F0
+:10A1A0007C7DE7A80000C485FF0083A700300CE396
+:10A1B00019AFFF0700384CE32AA3FF070000001582
+:10A1C000000058854D00609C04008E84001804E453
+:10A1D0008100001000009A86001844E47900001005
+:10A1E0006400609C4200609C001804E403000010BE
+:10A1F0000000809C0300809C18006E840800601999
+:10A2000030E66BA9080063B80058ACE01C08CE84A7
+:10A21000042063E00000809C002006E4670000103A
+:10A22000001805D40000409E08006018D4E463A81C
+:10A230000800C018D8E4C6A800188CE00800E01890
+:10A2400018C5E7A80040C01A1C20D6AA0030ACE010
+:10A2500000380CE200006CA8009016D471EAFF07E9
+:10A260000000001500406018082063A80000B084BA
+:10A27000004080180C2084A80800601934E66BA9FF
+:10A28000005003D40200A59C00406018042063A87D
+:10A2900000A003D400006AA8002804D400584CE1B0
+:10A2A00091AFFF07000094A8080060185CE663A85F
+:10A2B00000580AD400188CE0F403CE850000A48472
+:10A2C000080080183CE684A800206CE0007003D4ED
+:10A2D000FFFF859C0100609C001844E414000010FE
+:10A2E0000000E09C040085B8040060180B7363A8AC
+:10A2F000042052E2A1A0FF07000092A8009016D40B
+:10A3000000406018080463A80000A09C00009CA8FE
+:10A31000002803D400000CA900406018182063A88E
+:10A32000002803D42E0000000500609C0800C0181F
+:10A33000ACE2C6A800406018080463A800302CE115
+:10A340000800601960E66BA9003803D40800C01843
+:10A3500064E6C6A800586CE00030ACE00800E018E5
+:10A3600068E6E7A80800601950E66BA90038CCE061
+:10A37000000018870058ECE00000108500C003D4EE
+:10A3800000005A870200889C00406018182063A8CB
+:10A390000000E784002009D400D005D4004006D492
+:10A3A000003803D400009CA800000CA90400609CA5
+:10A3B0000B0000000000A09C9CFFFF030800409ED3
+:10A3C000001804E48CFFFF0F0200809C8CFFFF0349
+:10A3D00018006E8489FFFF030100809C0000C09C70
+:10A3E00054E6FF070000E09C000021850400418541
+:10A3F000080081850C00C18510000186140041868B
+:10A40000180081861C00C186200001872400418736
+:10A4100028008187004800442C00219CF4FF219CE7
+:10A42000004801D4045001D4086001D4000043A9BD
+:10A4300079AEFF07FF0084A58AA2FF070000001580
+:10A440000800801894DC84A80600CCB800206AE0DC
+:10A450000040E0181801E7A80000838400400019BC
+:10A46000582008A900FC209D180084B80040A6E0F0
+:10A47000004060195C206BA9002007D40800001977
+:10A48000ACDC08A900006584004080181C0184A889
+:10A490000058C6E0034863E0001804D40000209D83
+:10A4A00000406018200263A80000809C002003D4B4
+:10A4B0000400639C00408AE0004803D400006485E7
+:10A4C0000400639C00000AA9004803D400408018DF
+:10A4D0002C0284A8004804D400006584000087840E
+:10A4E0004A0063B8580084B8080063B80C00AA8416
+:10A4F0000000E09C002063E00200A59C0040801862
+:10A50000300284A80C280AD4001804D40000A09CAF
+:10A51000000026850800601850E663A800008CA89B
+:10A520004A0029B90018AAE10000C09C080029B916
+:10A530000040401934024AA90000AD85005829E1C5
+:10A540000600609C00480AD4004060190C046BA906
+:10A5500000402019000229A900380BD400404019FE
+:10A560001C204AA9003809D400380AD40040201918
+:10A570002C2029A90040401918204AA9003809D4E4
+:10A5800000680AD4EBE5FF070000001500002185F4
+:10A590000400418508008185004800440C00219C8E
+:10A5A000CCFF219C004801D4045001D4086001D4A0
+:10A5B0000C7001D4108001D4149001D418A001D4DF
+:10A5C0001CB001D408000019A47D08A9000085AAC8
+:10A5D0000040E3E0000083A90000A7840000C6AAB1
+:10A5E0000000409D005005E44401000CFF0044A61B
+:10A5F000020060185C6763A80018CCE100006E845C
+:10A600002C008384005004E40A00001000000015B0
+:10A610000800801888E284A800206CE00000A38471
+:10A620000100809C002005E40C00000C00000015D7
+:10A630009B06000400006CA80800A01854E2A5A81E
+:10A640000100809C00286CE00000A384002025E429
+:10A650002601000C0000001500006E840000809CA4
+:10A660002C00A384002025E4090100100100609C57
+:10A6700008000019F4E608A900404CE100006A84D3
+:10A68000030063A800180AD400008A840300609CB9
+:10A69000001824E40B000010000000150800001949
+:10A6A000ECE608A900406CE0000083840000609C98
+:10A6B000020084A4001804E4F100000C000000155E
+:10A6C0000800601874E163A80800A018FCE5A5A8BC
+:10A6D00000180CE20000C09C00009084002884E078
+:10A6E00000006A8400208CE00300A09C002823E482
+:10A6F000030000100000848C0100C09C0000409DFD
+:10A70000005004E4030000100000609C0100609C05
+:10A71000031866E0005003E4BC00000C1400C09C69
+:10A7200000408018280B84A800006484005003E4D3
+:10A73000030000100000A09C002804D4B6ADFF0761
+:10A7400000000015C7A1FF07000000150800001950
+:10A7500094DC08A90600F2B800406CE00040A018A4
+:10A760005C20A5A80000838400400019180108A9F6
+:10A77000180084B800406018582063A8002008D44E
+:10A780000018C7E000FC809C000066840028E7E019
+:10A79000032063E00800A018ACDCA5A800408018E6
+:10A7A0001C0184A8001804D400406018200263A88B
+:10A7B0000000809C002003D400288CE00400639CEF
+:10A7C0000000A09C00002485002803D40400639CA2
+:10A7D000002803D40040A0182C02A5A80000609C0B
+:10A7E000001805D4000086840400A59C000068843D
+:10A7F0004A0084B8580063B8080084B80000CE84CA
+:10A80000001884E02C000685002005D40000678431
+:10A8100000408018340284A80040A0180C04A5A8A9
+:10A820004A0063B8080063B8004863E0001804D425
+:10A830000000809C00406018000263A8002005D43E
+:10A84000002003D4005008E4090000100100809C9F
+:10A850000800A01888E2A5A800286CE00000A384E6
+:10A86000002005E41D00000C0000209D08000019D8
+:10A8700078E108A9FFFF809C00406CE00000638441
+:10A88000002023E41500000C0000209D020063B8A6
+:10A890000800A018F4DDA5A80800001974DF08A9B5
+:10A8A000002883E00100209D00208CE0004063E050
+:10A8B0000000A48400186CE0000083840028B4E049
+:10A8C00000406018102063A8002096E0002803D400
+:10A8D0000400639C002003D4004080181C2084A83E
+:10A8E000000070840800A018F4DDA5A8004804D476
+:10A8F000020063B80800801850E684A800200CE12C
+:10A90000002883E0000008850800A01874DFA5A8CF
+:10A9100000208CE0002863E00000C48400186CE094
+:10A920000040A0181820A5A80000E3840030D4E05F
+:10A93000004005D400008E8400406018242063A8E5
+:10A940000038F6E0003003D42C00A4840400639C9B
+:10A950000000809C003803D4002005E40A000010A9
+:10A960000100809C0800001988E208A900406CE002
+:10A970000000A384002005E40300000C0000809C7C
+:10A980000100809C0100609C001829E40300001075
+:10A9900000000015200084A8004060182C2063A847
+:10A9A000002003D400006E840000809C2C00A3844F
+:10A9B000002025E40A00000C0000001508008018A3
+:10A9C00088E284A800206CE00000A3840100809C41
+:10A9D000002025E409000010000000150C00AC84E4
+:10A9E000000092A800000CA90200A59C0500609C34
+:10A9F000460000000C280CD4000092A800000CA90E
+:10AA0000420000000500609C08000019B4E408A999
+:10AA100000408CE0E0006484E8000485E400A48445
+:10AA20006C1904D4744104D4702904D40000609CCF
+:10AA300008000019F8E608A9683104D4781904D48C
+:10AA40000040ACE000006584E800A4842C2801D418
+:10AA5000E0000485203001D4244001D4E400848443
+:10AA6000282001D40000809C302001D4F6ADFF07DF
+:10AA70002000819C2BFFFF0300000015E4E5FF0789
+:10AA800000006CA80FFFFF0300000015001825E46C
+:10AA9000080000100000001508006018F4E663A824
+:10AAA00000184CE100006A84F7FEFF03010063A870
+:10AAB0000200609C001825E408000010000000154A
+:10AAC00008008018F4E684A800204CE100006A84A5
+:10AAD000EDFEFF03020063A80800A018F4E6A5A895
+:10AAE000EAFEFF0300284CE1091D000400006CA8E9
+:10AAF000DBFEFF0300006E848801000400000015E7
+:10AB0000BCFEFF03000000150000A09C0000C09CDC
+:10AB100088E4FF070000E09C0000218504004185D7
+:10AB2000080081850C00C185100001861400418653
+:10AB3000180081861C00C186004800443400219C16
+:10AB40000000A3A800406018280B63A800008384BD
+:10AB50000800601874E163A80018C5E00000609C5C
+:10AB6000001824E443000010000000150000668473
+:10AB7000020063B80800C01874DEC6A8003083E085
+:10AB80000800C018F4DCC6A8002085E0003063E0AF
+:10AB90000000E484001865E00000A3840200C5B84A
+:10ABA0003F00609C0018A5E42A000010000086A861
+:10ABB00000406018000663A8001886E00000A48426
+:10ABC000004060180C0563A8000083840B00A5B842
+:10ABD0000040C0180006C6A8004060182C0B63A8EF
+:10ABE000002884E0002003D4020067B80030A3E00E
+:10ABF0003F00609C0018A7E4110000100000001541
+:10AC000000008584004060180C0563A80000A38440
+:10AC10000B0084B800406018300B63A80020A5E04A
+:10AC2000002803D40100809C00406018280B63A812
+:10AC3000002003D40F0000000000001500008584F0
+:10AC400000406018080563A8F1FFFF03000000152D
+:10AC50000040C0180006C6A800406018080563A898
+:10AC6000003084E00000A484D8FFFF03000000153A
+:10AC70000048004400000015F0FF219C004801D46A
+:10AC8000045001D4086001D40C7001D4000083A9E1
+:10AC900008008018ACE284A80000C09D002063E09A
+:10ACA0000000438508006018EC7C63A80000E09C6D
+:10ACB0000000809C0018ACE0005084E51100000CFE
+:10ACC0000000C09C00006584003023E40600000CF6
+:10ACD0000000001500FF6584003023E40500000C2F
+:10ACE0000000609C0400A59CF4FFFF030100849C0D
+:10ACF000003005D47C2100040000ACA80100E09CD9
+:10AD0000007027E4E8FFFF130000609D000021852C
+:10AD100004004185080081850C00C185004800447D
+:10AD20001000219CFCFF219C004801D4000003A9D5
+:10AD30000800A0181CC5A5A80000E09C002864E03D
+:10AD400000006384001887E52B00000C0000609D64
+:10AD5000000023A90200609D0800601828C463A8B1
+:10AD60000000E09D0018C4E00000A09D0000868463
+:10AD70000100E79C00006484005843E51C000010BB
+:10AD80000100A3A4007805E40A000010020063A4F7
+:10AD90004800648494008384002028E41200000C9E
+:10ADA000000000150000868400006484020063A493
+:10ADB000006803E407000010000000154C006484E4
+:10ADC00094008384002028E40700000C0000001594
+:10ADD000004887E5E6FFFF130400C69C060000005C
+:10ADE0000000609D040000000100609DF5FFFF036E
+:10ADF0004400648400002185004800440400219C34
+:10AE0000ECFF219C004801D4045001D4086001D417
+:10AE10000C7001D4108001D4000024A9000065A9A1
+:10AE20000000E3A8000046A90040A0182003A5A840
+:10AE30000100809C00006584002023E4FEFFFF13D6
+:10AE40000000001500406018200363A80C00809CDF
+:10AE50000000A384002047E4A9000010020067B8A6
+:10AE600004008018447384A8002063E000008384F9
+:10AE700000200044000000150500A09D006827E4A4
+:10AE80000B000010000000150800A01830EDA5A868
+:10AE90000800C0182CEDC6A800286AE000308AE03F
+:10AEA0000000A09C002803D4002804D40200C0188D
+:10AEB0005C67C6A802008018645C84A800308AE140
+:10AEC0000000CC840000A09C002066E00000838489
+:10AED000002804E4030000100000009D0100009D14
+:10AEE000006827E4030000100000609C0100609CE3
+:10AEF000041868E0002803E40A00001000000015B0
+:10AF000002006018685C63A8001886E00000648492
+:10AF1000002823E4030000100100A09C002804D4B2
+:10AF200000000C850200C018685CC6A80000009EE6
+:10AF3000003068E000008384008024E408000010F2
+:10AF40000500609C0800E01800E2E7A80100809C72
+:10AF500000386AE06A000000002003D40200A01854
+:10AF6000C45BA5A8002888E0001827E403000010AF
+:10AF70000000A09C0100A09C0200C018C85BC6A8ED
+:10AF8000002804D4003068E00000809C008029E4A0
+:10AF900003000010004803D40100809C0200E01868
+:10AFA000145CE7A8402008D40038A8E03800688482
+:10AFB0000200E018105CE7A80038C8E00800E018BC
+:10AFC000F8E1E7A800388AE00000E09C003803D4EC
+:10AFD0001C3803D40100E09C183803D40400EB842F
+:10AFE0000800601800E263A800006B850018CAE141
+:10AFF000003805D4005806D4000064840000809C0A
+:10B00000008023E43E00001000200ED40800A018A9
+:10B01000FCE1A5A800286AE000008384008024E405
+:10B02000370000100000001571DBFF0700006AA860
+:10B0300000006E84008003E43100000C00008AA848
+:10B0400000006C843800A384832700043C036584DB
+:10B0500000006E84008003E42900000C000000154D
+:10B0600001DCFF0700006AA82500000000000015B1
+:10B070009130000400006AA82100000000000015C3
+:10B080000800E018F8E1E7A80800A018FCE1A5A86E
+:10B0900000386AE000288AE00800C01800E2C6A86C
+:10B0A0000800E018ECE1E7A80030AAE00038CAE0A8
+:10B0B0000000E09C003803D4003804D4003805D4E4
+:10B0C000003806D4D221000400006AA80C00000059
+:10B0D000000000150800C018F8E1C6A80000809C18
+:10B0E00000306AE00000A384002005E40400000CA6
+:10B0F000000000159F24000400006AA800002185BC
+:10B1000004004185080081850C00C185100001867E
+:10B11000004800441400219CF4FF219C004801D405
+:10B12000045001D4086001D4000043A9080060184D
+:10B13000A47D63A800008AA800188AE1851600048F
+:10B1400000006C84020080185C6784A800206AE01C
+:10B150000000C3840000809C0800601848E263A8D7
+:10B1600000200CD40018EAE002006018F85B63A825
+:10B17000001886E00800601838DC63A80000A4848A
+:10B1800000184AE10000609C001805E4050000106A
+:10B190000000809C581806D400180AD4001807D460
+:10B1A00098ED609C042006D4001806D40000218588
+:10B1B0000400418508008185004800440C00219C62
+:10B1C000FCFF219C004801D4000003A90000609D01
+:10B1D00008006018A47D63A8001888E0000064845B
+:10B1E000005823E4030000100000A09D0100609DB2
+:10B1F000020080185C6784A80800A01858DCA5A885
+:10B20000002028E10028C8E00000E9843800878495
+:10B210000000A6843C036484001805E403000010C9
+:10B220000000001501006BA90800C01838DCC6A892
+:10B230006800A784003068E000008384002804E4EC
+:10B24000030000100000001501006BA90800801821
+:10B2500030DC84A8002068E06C00878400006384F0
+:10B26000002003E4030000100000001501006BA99A
+:10B27000006804E40D000010006803E40B000010F7
+:10B28000000000150800A01834DCA5A8002868E01C
+:10B290007000A78400008384002804E403000010E9
+:10B2A0000000001501006BA90800C0183CDCC6A80E
+:10B2B00000006984003088E00200C018C85BC6A89E
+:10B2C00000008484003063E000006384001804E41C
+:10B2D000080000100000A09C002804E404000010F6
+:10B2E000002823E403000010000000150100A09CCA
+:10B2F0000800601850DC63A804286BE10000C984D2
+:10B30000001888E00200A018C45BA5A8000084848F
+:10B31000002866E000006384001804E403000010C5
+:10B320000000A09C01006BA9002803E4100000109D
+:10B33000002804E40E000010000000150200601850
+:10B34000CC5B63A8001886E00800C01854DCC6A8CF
+:10B350000030A8E00000C48400006584003003E4ED
+:10B36000030000100000001501006BA90800601820
+:10B37000E87B63A80000809C0018E8E00000678478
+:10B38000F403A384002025E4180000100100809C31
+:10B390000800801840DC84A80000C984002068E010
+:10B3A000740086840000A384002005E403000010DC
+:10B3B0000000001501006BA90800A01844DCA5A836
+:10B3C000002868E07800A68400008384002804E454
+:10B3D000030000100000001501006BA90000678445
+:10B3E0000100809CF403A384002025E415000010D4
+:10B3F000000000150800801848DC84A80000C984FB
+:10B40000002068E07C0086840000A384002005E41E
+:10B41000030000100000001501006BA90800A0182F
+:10B420004CDCA5A8002868E08000A6840000838486
+:10B43000002804E4030000100000001501006BA9BF
+:10B4400000002185004800440400219CE8FF219C65
+:10B45000044801D4085001D40C6001D4107001D408
+:10B46000148001D4000043A9000084A908006018DA
+:10B4700074E163A80800A018A47DA5A8001884E0C2
+:10B480000028CCE12C006A84000004861C00AA84F9
+:10B49000000090A82000CA842400EA8428000A85BD
+:10B4A00032070004006001D40800C018B4E1C6A847
+:10B4B0000100A09C00308CE000580ED40000648491
+:10B4C000002863E0001804D418008A84002804E4EB
+:10B4D00047010010002844E53E0100100200609C76
+:10B4E0000000609C001804E4330100100000001507
+:10B4F0005C006A8402000019CC5B08A9080080186F
+:10B50000E47B84A80000EE840040CAE00020ACE0A8
+:10B510000C1807D438008A8460000A85104007D4CC
+:10B5200064006A840100009D081807D40000658447
+:10B530000800AA84842807D408008484902007D4B3
+:10B540006C048384882007D4700463848C1807D427
+:10B550000000C684A83007D42C008A84004004E48C
+:10B5600004010010020070B8004044E5EB00001038
+:10B570000200609C0000609C001804E4C9000010F8
+:10B58000020070B80200609C5604000400008CA801
+:10B590000000609C18008A8404180AD40400609C8F
+:10B5A0000018A4E5030000100000809C18200AD4B5
+:10B5B0000000EE840200A018C85BA5A80000209D32
+:10B5C0001800CA8400288AE0543007D4000064843C
+:10B5D000004803E4030000100000A09C0100A09CB0
+:10B5E00002000019C45B08A92C2807D400406AE0B7
+:10B5F0000200A018EC5BA5A80000638400288AE084
+:10B600000200C018F05BC6A8581807D40030AAE0A2
+:10B610000000848408000019E87B08A95C2007D496
+:10B620000040CCE00000A58402008018F45B84A8F0
+:10B630000000C68400206AE0602807D42008068540
+:10B640000800A0181CDCA5A80000638400288CE07A
+:10B65000641807D4484007D40200A018D45BA5A8FA
+:10B660000000848400286AE002000019705C08A9C8
+:10B67000AC2007D40040AAE0000063844C1807D433
+:10B6800068006A84141807D468008A84202007D4CC
+:10B690000000858468006A84002023E40300001011
+:10B6A0000000009D0100009D244007D42C006A8406
+:10B6B000004823E4030000100000809C0100809CEF
+:10B6C000442007D4280866842000A6841C08068528
+:10B6D000682807D46C4007D4004803E40A0000102F
+:10B6E000701807D42C08A684742807D4300806855F
+:10B6F000784007D4340866847C1807D43808C68498
+:10B70000803007D4080080189CE184A800206CE0F9
+:10B7100000006384004823E4530000100100A09C53
+:10B720000200A018105CA5A80200C018145CC6A8EE
+:10B7300000286AE002000019185C08A90030AAE09D
+:10B7400000408AE000006384000084840000A58437
+:10B750009C1807D4A42007D4A02807D40200E0181E
+:10B76000605CE7A800006E840038AAE008000019B9
+:10B77000F4E608A9000085840040CCE00000409D6C
+:10B78000982003D400006584010063AC001805D440
+:10B7900000008684005024E4990000100000001589
+:10B7A0000800A018ECE6A5A80028CCE100008E84D3
+:10B7B000100064A4005003E42700000C00000015F2
+:10B7C000010064A4005003E41F00000C00000015F9
+:10B7D0000800C018787DC6A8020070B800308CE060
+:10B7E0000800E0187C7DE7A80200C4940038ACE0B3
+:10B7F000080000196CE608A900188CE00200E59426
+:10B800001000C6B8004063E00438C6E00800001924
+:10B8100084E708A900186CE00040A4E00800E018E4
+:10B8200004E7E7A8003003D4003884E0FDE4FF0714
+:10B8300000006CA8FDE3FF0700006CA8700000008A
+:10B840000000001543E5FF0700006CA8E1FFFF03BF
+:10B8500000000015E4E2FF0700006CA8D9FFFF0319
+:10B8600000008E84002823E4BDFFFF1300000015B4
+:10B8700002006018105C63A80200C018145CC6A81F
+:10B8800000188AE0A42807D400306AE0000084840D
+:10B89000000063849C2007D4B1FFFF03A01807D4E5
+:10B8A0006400AA840800C018B8E4C6A8042807D415
+:10B8B00008000019B0E208A90030ECE0004083E085
+:10B8C0000000E7840800C01830E3C6A800208CE020
+:10B8D0000030A3E0003804D40028ACE0FFFF809CD7
+:10B8E00008000019B0E308A9002005D40040C3E017
+:10B8F0005C00EA840030CCE00800A01830E4A5A881
+:10B90000003806D4002863E060000A8500186CE067
+:10B9100020FFFF03004003D4001804E41BFFFF0FC7
+:10B920000200609C6000AA84020070B80800C01881
+:10B93000B8E4C6A8042807D40800001930E408A910
+:10B940000800E01830E3E7A80030ACE0003883E0FE
+:10B950000000A58400208CE0004063E0002804D4AF
+:10B9600000186CE060008A840AFFFF03002003D403
+:10B970005C00AA840800C018B8E4C6A8042807D44C
+:10B9800008000019B0E308A90800E018B0E2E7A831
+:10B990000030ACE0003883E00000A58400208CE09B
+:10B9A000004063E0002804D400186CE0EFFFFF03C0
+:10B9B0005C008A8408000019BCE108A900408CE002
+:10B9C000000064840100639CCAFEFF03001804D4D5
+:10B9D000001804E4C7FEFF0F000000150800E0187F
+:10B9E000B8E1E7A8F7FFFF0300388CE00800601813
+:10B9F000C0E163A8F3FFFF0300188CE00400218579
+:10BA0000080041850C0081851000C1851400018665
+:10BA1000004800441800219CF8FF219C004801D4F4
+:10BA2000045001D40800A01848DCA5A8FF7FE01846
+:10BA3000FFFFE7A8002883E00800001930DC08A910
+:10BA4000003804D40040A3E00800C0184CDCC6A8AD
+:10BA50000800201958DC29A9003043E1004883E0A0
+:10BA60000800601938DC6BA90C00089D0058C3E081
+:10BA70000040E3E00800201950DC29A908006B9D74
+:10BA8000004803E1005823E104006B9D005863E087
+:10BA90000000609D005805D4005808D4FF7FA0180E
+:10BAA000FFFFA5A8002806D4002804D4FFFFC09CEF
+:10BAB000002807D4003009D4002803D400280AD471
+:10BAC0000000218504004185004800440800219CB5
+:10BAD000FCFF219C004801D40200A0185C67A5A8C7
+:10BAE0000800201958DC29A9002883E00048C3E099
+:10BAF000000004850800A01B3CDCBDAB0800601AF8
+:10BB000038DC73AA3800888400E823E20098E3E078
+:10BB10003C0384840200A018C85BA5A80800201973
+:10BB2000E87B29A9002006D40800601A30DC73AA3B
+:10BB30006800A8870028E8E10048A3E200E807D4ED
+:10BB40000098A3E06C00A8870800201950DC29A900
+:10BB500002008018C45B84A800E805D40048E3E034
+:10BB60000800A01840DCA5A81800739E0800201942
+:10BB700034DC29A90028E3E20020C8E00200A01B71
+:10BB8000CC5BBDAB009863E30048A3E008008018DD
+:10BB90004CDC84A80C00739E00E828E1002023E31D
+:10BBA0000098A3E10800A01B44DCBDAB6C008884B6
+:10BBB0000000609D005804E40400001000E863E207
+:10BBC00070006884001805D40000EF85007811D457
+:10BBD00000008684002007D400006684005803E437
+:10BBE00004000010000000150000298500480DD455
+:10BBF00000009584F4036484005823E406000010D8
+:10BC0000000000157400A884002817D47800288547
+:10BC1000004813D4F40384840100609C001824E4D9
+:10BC200006000010000000157C00688600981BD4F8
+:10BC300080000885004019D4000021850048004498
+:10BC40000400219CFCFF219C004801D41400E386E1
+:10BC5000000063AA0000609C001837E40B0100108C
+:10BC6000000024AA2400A486001835E41600001061
+:10BC70000000E09C0800801858E284A8002065E0DD
+:10BC80000500C09C0700A09C04008018188D84A8A3
+:10BC9000003047E50400000C000000150400801887
+:10BCA000588D84A8002003D40100E79C0028A7E554
+:10BCB000F6FFFF130400639CF6000000000000156F
+:10BCC0000000609C001815E42F0000100000609C2C
+:10BCD0000000E09CC8FBB19DC803119D0000209DA1
+:10BCE0004800719D0500609C001847E5CA000010DF
+:10BCF0000000809C60FC68840000C09C003023E44D
+:10BD0000B2000010008869E0003027E40300001052
+:10BD10000000E09D0100E09D0300609C001827E406
+:10BD2000030000100000809C0100809C04206FE054
+:10BD3000003003E49A00001000000015080080188D
+:10BD400058E284A8002069E0003027E49000000C4D
+:10BD5000001865E004008018D88A84A8002003D465
+:10BD60000001AD9D0400089D0400299D0100E79C91
+:10BD70000700609C0018A7E5DBFFFF1340006B9DE8
+:10BD80000000609C001817E4C20000100000E09C56
+:10BD90000800601858E263A8B8FBF39D0018A5E1FD
+:10BDA0001800139D0000209D3800739D0500609CC5
+:10BDB000001847E54B0000100000C09C000068849C
+:10BDC000003023E434000010009869E0003027E4DC
+:10BDD000030000100000209E0100209E0300609CD4
+:10BDE000001827E4030000100000809C0100809CE4
+:10BDF000042071E0003003E41C000010003035E442
+:10BE00000B000010000000150800801858E284A8FC
+:10BE1000002069E0003027E41000000C001865E005
+:10BE200004008018D88A84A8002003D40001EF9D64
+:10BE30000400AD9D0400089D0400299D0100E79CBD
+:10BE40000700609C0018A7E5D9FFFF1340006B9D19
+:10BE5000900000000000001504008018988A84A853
+:10BE6000F3FFFF03002003D40800C01858E2C6A85F
+:10BE7000003089E00800C01854E2C6A8002085E020
+:10BE8000003069E0001865E000006384E8FFFF030C
+:10BE9000001804D4B8038384003004E40B000010BD
+:10BEA000000000150800801858E284A8002069E00E
+:10BEB0000200809C002047E5DAFFFF13001865E0D0
+:10BEC000E6FFFF03000000150800C01858E2C6A8EE
+:10BED000003069E0001865E0D5FFFF03005803D487
+:10BEE00000006884003023E410000010009869E02E
+:10BEF000003035E4CEFFFF130600609C001827E4F5
+:10BF00000600001000008DA804006018188B63A8BC
+:10BF1000C7FFFF03001804D404006018188C63A83E
+:10BF2000C3FFFF03001804D4B8038384003004E483
+:10BF300011000010000000150800801858E284A8C5
+:10BF4000002069E00600809C002027E40600001025
+:10BF5000001865E004008018188B84A8B4FFFF0364
+:10BF6000002003D404008018188C84A8B0FFFF03BD
+:10BF7000002003D40800C01858E2C6A8003069E0C9
+:10BF8000001865E0AAFFFF03007803D404008018BE
+:10BF9000988A84A873FFFF03002003D40800C01808
+:10BFA00058E2C6A8003089E00800C01854E2C6A8CC
+:10BFB000002085E0003069E0001865E0000063843F
+:10BFC00068FFFF03001804D4C8038384003004E42E
+:10BFD0000B000010000000150800801858E284A82B
+:10BFE000002069E00200809C002047E55AFFFF1313
+:10BFF000001865E0E6FFFF03000000150800C01808
+:10C0000058E2C6A8003069E0001865E055FFFF035C
+:10C01000005803D460FC6884002003E4060000108C
+:10C020000000001500006884002023E41100000CCB
+:10C03000000000150800801858E284A8002069E07C
+:10C040000600809C002027E406000010001865E030
+:10C0500004008018188B84A842FFFF03002003D43B
+:10C0600004008018188C84A83EFFFF03002003D42E
+:10C070000800C01858E2C6A8003069E0001865E062
+:10C0800038FFFF03006803D40EFFFF032400A486DB
+:10C0900000002185004800440400219CE8FF219C09
+:10C0A000004801D4045001D4086001D40C7001D4BC
+:10C0B000108001D4149001D4000043A9020060183C
+:10C0C0005C6763A800008AA80018AAE000006584E5
+:10C0D0000800A01878E1A5A8CE25000400288AE170
+:10C0E000B09AFF070100609C0100609CF31C0004F3
+:10C0F00000008AA80800601894E263A800580CD4D5
+:10C100000018AAE0000085840100609C001824E467
+:10C110001B0000100000C09C08008018A4E284A846
+:10C120000020EAE000006784003003E414000010FF
+:10C13000FFFF609C00180BE41100001000000015C8
+:10C140000800801898E284A800206AE00000838438
+:10C15000003004E4A700001000000015080060187B
+:10C160009CE263A800188AE000006484FFFF639CDF
+:10C17000001804D40000809C002007D400006584CF
+:10C180000100C09D007023E40F00001000000015A6
+:10C190000800A01898E2A5A800280AE20000708410
+:10C1A0000000A09C002803E47D000010FFFF609CBD
+:10C1B00000006C84FFFF409E009023E46100000CAF
+:10C1C0000000001500008C84FFFFC09D007004E497
+:10C1D0005800000C0100609C04006018BC8063A83B
+:10C1E0000000809C0000A384002005E406000010ED
+:10C1F0000000001500006C84007003E44900000C8E
+:10C20000000000150800A01824E2A5A80100609C09
+:10C2100000288AE00000AC847A9AFF07002804D442
+:10C2200000008C84FFFF609C001804E408000010EC
+:10C23000020064B80100A09C080080186C7C84A8EF
+:10C24000002063E000186AE0002803D48BFAFF079F
+:10C2500000006AA808008018ACE284A80000C09C16
+:10C2600000206AE000006384001886E51900000CD5
+:10C27000000000150800A0186C7CA5A8000023A9E8
+:10C280000000609D0800E018EC7BE7A800288AE029
+:10C29000000064840100C69C005803E409000010FB
+:10C2A000FFFFA39C00380AE1005825E405000010B8
+:10C2B000002804D400006884030063A4001808D494
+:10C2C0000400E79C004886E5F2FFFF130400849C0D
+:10C2D00000008C84FFFF609C001804E44B000010F9
+:10C2E000020064B8080080186CE684A8002063E0AF
+:10C2F00000186AE000408018042084A80000A3848D
+:10C300005000C5B800406018082063A8FFFFA5A42E
+:10C31000003003D4002804D43C00000000000015C5
+:10C320000301000400006AA8B7FFFF030000001526
+:10C33000271C00040000AAA8A8FFFF0300000015A6
+:10C340003B15000400006AA800006EA85B1C0004F6
+:10C3500000008AA800902BE49BFFFF1300580CD428
+:10C36000080060189CE263A808008018A0E284A876
+:10C370000018CAE00020AAE000006684007063E0B4
+:10C3800000008584002023E48FFFFF13001806D4EB
+:10C390000000A09C8CFFFF03002810D400008C84B8
+:10C3A000001824E489FFFF1300000015080060183E
+:10C3B0009CE263A800188AE0000064840028A3E5DA
+:10C3C00004000010FFFF639C7FFFFF03001804D4EC
+:10C3D0001715000400006AA800006EA8371C0004AE
+:10C3E00000008AA8007010D477FFFF0300580CD417
+:10C3F000080060189CE263A800188AE000006484CA
+:10C400005CFFFF030100639C00002185040041855F
+:10C41000080081850C00C18510000186140041864A
+:10C42000004800441800219CFCFF219C004801D4D6
+:10C4300000408018080884A80000A4840800801820
+:10C4400060DC84A81800A5B89800A5B80020E3E037
+:10C45000080080185CDC84A80020C3E00000809CF9
+:10C46000002025E40D0000100000A09C0040801872
+:10C470000C0884A8002807D4002804D40100809C5C
+:10C48000002006D400408018080484A8002804D4A2
+:10C4900090FDFF07000000150000218500480044C2
+:10C4A0000400219C0000C3A80000609C001825E443
+:10C4B0006600000C0300609DE001E09C003804E48D
+:10C4C00045000010D002609C003844E520000010B8
+:10C4D000D002009DF000609C001804E40E000010E3
+:10C4E0003000639C001804E45800000C6001609C5C
+:10C4F000001826E455000010000000150200609DA1
+:10C50000005825E45100000C000000154F00000009
+:10C510000300609D6001609C001826E44B00001041
+:10C520000300609D005825E4040000100500609C95
+:10C53000460000000200609D001825E44300000C46
+:10C5400000000015410000000300609D004004E46D
+:10C550003E0000100300609D004044E53B000010D9
+:10C560004002609C001804E43800000C004026E4FF
+:10C57000070000100200609D005825E43300000C05
+:10C5800000000015310000000300609D2002609C47
+:10C59000001826E408000010003826E40400609C1F
+:10C5A000001825E4E3FFFF0F00000015270000003E
+:10C5B0000300609DFBFFFF0F0A00609C6001609C10
+:10C5C000001826E4210000100300609DF5FFFF0322
+:10C5D0000600609C001826E40B0000108002609C9E
+:10C5E0000300609D005825E4D2FFFF0F0500609C0A
+:10C5F000001825E4150000100000001513000000CD
+:10C6000000000015001826E4E6FFFF0F0100609C03
+:10C610002002609C001826E404000010003826E484
+:10C62000E0FFFF030500609CDEFFFF0F0B00609C36
+:10C630006001609C001826E4040000100300609D67
+:10C64000D8FFFF030700609C00480044000000156D
+:10C65000092363E0EDFF839C6500609C001844E4BF
+:10C660001E0000100000609D020064B804008018E5
+:10C67000787384A8002063E00000838400200044D5
+:10C6800000000015150000000A00609D1300000066
+:10C690001400609D110000001700609D0F00000055
+:10C6A0001800609D0D0000001900609D0B00000047
+:10C6B0001D00609D090000001E00609D0700000035
+:10C6C0003200609D050000000000609D0300000036
+:10C6D0003B00609D3C00609D004800440000001548
+:10C6E000FCFF219C004801D45B96FF070000001569
+:10C6F00000002185004800440400219C004060188F
+:10C70000040063A80000809C002003D4004800447B
+:10C710000000001500406018180263A80000809C0B
+:10C72000002003D40048004400000015F4FF219CC1
+:10C73000004801D4045001D4086001D408008018D6
+:10C7400078E184A8004040190C164AA90020A3E013
+:10C7500000400019101608A90000858400408019C7
+:10C7600024168CA90200A0185C67A5A8020084B852
+:10C770000028C3E00000E6840800C01874DEC6A8E4
+:10C780000030A4E00800C018F4DCC6A80028A3E02C
+:10C79000003084E00000C584002083E00200A0187F
+:10C7A000DC5BA5A80800C6B8002827E10800A0188F
+:10C7B000E87BA5A8002863E1000064840018C6E0B7
+:10C7C00002008018D45B84A800300AD400406018AE
+:10C7D000141663A80000C09C0020E7E0003008D4D5
+:10C7E0000000898400004A850400C4B8005003D4C6
+:10C7F0000000A7840400639C04008018508384A870
+:10C80000000008850400A5B8004003D40000609C27
+:10C81000001804D4E002609C001826E40300001015
+:10C820004400E5B8D002C09C4004609C001826E497
+:10C83000080000100100809C00006B842808A3847D
+:10C84000002025E404000010040066B83004C09CF9
+:10C85000040066B8004080181C1684A8003863E005
+:10C86000001804D40100809C00406018001663A8E2
+:10C8700000200CD4002003D46097FF0700000015AF
+:10C880000000A09C00406018041663A800408018B7
+:10C890002C1684A8002803D404000019649008A969
+:10C8A00000280CD42400639C0000A8840000C384EA
+:10C8B0000200A59C0000E48400406018302063A8BA
+:10C8C000003003D4002808D40400639C003803D44B
+:10C8D000000021850400418508008185004800444E
+:10C8E0000C00219CF0FF219C004801D4045001D48D
+:10C8F000086001D40C7001D4000003A9080060187E
+:10C90000E87B63A8001888E100006C841808838421
+:10C910000100E49C1C08A3840000809C002005E426
+:10C920006F0000101408C384010066B8003063E093
+:10C93000070063B88001639C063BC3E100006C8480
+:10C94000180083842A00609CF7FF849C001844E44C
+:10C950000B0000100000609D020064B80400801805
+:10C96000107584A8002063E0000083840020004448
+:10C97000000000150200601900526BA90A736BE1F8
+:10C980000000409D00502BE41700000C0000001533
+:10C990001000609C0018ABE40300001000000015BC
+:10C9A000000063A900008C840000A09C3C08648403
+:10C9B000002803E44F00001000000015D80B648429
+:10C9C000002803E44B00001000000015F40B648500
+:10C9D00000282BE44700001000000015450000006F
+:10C9E0000100609D08006018B0E463A8001888E0AA
+:10C9F0004C9CFF070000648400500BE4060000100C
+:10CA00000000001569006018007863A8E1FFFF03CB
+:10CA10000A7363E1C0006018000063A8DDFFFF0334
+:10CA20000A7363E10500601900466BA9D5FFFF0397
+:10CA30000A736BE10D00601900EC6BA9D1FFFF03D5
+:10CA40000A736BE11B00601900D86BA9CDFFFF03CF
+:10CA50000A736BE12F00601900766BA9C9FFFF0311
+:10CA60000A736BE16900601900786BA9C5FFFF03C9
+:10CA70000A736BE17800601900006BA9C1FFFF0326
+:10CA80000A736BE1C000601900006BA9BDFFFF03D2
+:10CA90000A736BE100006C846400809C0400A38432
+:10CAA000002025E4F8FFFF1300000015CC006019FA
+:10CAB00000006BA9B3FFFF030A736BE186026019E4
+:10CAC00000E06BA9AFFFFF030A736BE13804601944
+:10CAD00000006BA9ABFFFF030A736BE1010066B8AE
+:10CAE000003063E0080063B894FFFF030003639C19
+:10CAF0000000218504004185080081850C00C18566
+:10CB0000004800441000219CD8FF219C004801D41B
+:10CB1000045001D4086001D40C7001D4108001D4F9
+:10CB2000149001D418A001D41CB001D420C001D4A9
+:10CB300024D001D46CFFFF07000043A9080060184F
+:10CB4000E87B63A80800801818C584A800180AE2CA
+:10CB50000020EAE00000B0840800C01830C5C6A874
+:10CB6000005807D400308AE00C080585004004D442
+:10CB70000C08658400186BE5070000100100809C1C
+:10CB800008006019F8E16BA900586AE06B01000029
+:10CB9000002003D40800A0181CC5A5A8080000198F
+:10CBA00020C508A900286AE00800C01834C5C6A836
+:10CBB0000040AAE000308AE00400089D0040CAE07E
+:10CBC0000000009D004003D4004004D4004005D480
+:10CBD00001006B9C0000809C001884E51B00000C89
+:10CBE000004006D408006019C8C46BA9080060188A
+:10CBF00070C963A80058CAE00018AAE00000009DB0
+:10CC0000602FE6D7004005D4044005D4084005D481
+:10CC10000C4005D4204005D4444005D4000067846E
+:10CC20000100849C484005D44C4005D4B047E6D769
+:10CC3000004006D40100639C0400C69C001884E5F3
+:10CC4000F0FFFF135000A59C0800601958C96BA99C
+:10CC50000000C09C2000E09C0500209D0058AAE038
+:10CC60000400009D050066B80800601938C56BA96E
+:10CC70000000809C003063E0064363E0005063E006
+:10CC8000005863E00000609D0100849C005803D4BC
+:10CC90000038A4E5FDFFFF130400639C005805D491
+:10CCA0000100C69C0048A6E5EFFFFF130400A59C09
+:10CCB000020060185C6763A80800C01828C5C6A8F1
+:10CCC00000188AE00030AAE00080E0180000E7A821
+:10CCD0000000648402006019605C6BA90000C09CC5
+:10CCE000003805D4005883E00200A018F85BA5A81E
+:10CCF00008000019787D08A9002863E000404AE296
+:10CD0000003003D4003004D40004609C00009284FE
+:10CD10000018A4E5010100100000809C0800E01844
+:10CD20007C7DE7A800406018000563A80400009D12
+:10CD300000388AE2004003D40800A018ACE2A5A89D
+:10CD40001000809C00286AE00000A3840020A5E574
+:10CD5000030000100000C09C4000C09C0800E018C8
+:10CD6000807DE7A800406018304063A800384AE39F
+:10CD70000000B28400009A84003003D4002025E42F
+:10CD8000150000100000001508000019847D08A996
+:10CD90000000B48400406AE000008384002025E4A1
+:10CDA0000D00001000000015080060188C7D63A8BD
+:10CDB00008006019887D6BA90018AAE000588AE075
+:10CDC000000065840000C484001826E4DB00000C29
+:10CDD00000000015000090840000A09C0000C09E90
+:10CDE0003C0864840100009F0000809D006003E413
+:10CDF000120000100000C09D40086484006003E43D
+:10CE000003000010000000154408A4840000728490
+:10CE10000000CAA8A4FDFF070000948400009084CD
+:10CE200080086484006003E4040000100000001522
+:10CE3000840804878808C486080080189CE184A8B8
+:10CE40000000A09C00206AE000008384002824E405
+:10CE5000AC00000C0100609C001824E421000010CC
+:10CE60000000609C000070841C088384002824E477
+:10CE70009F0000100600809C0800A018A4E1A5A84F
+:10CE800000286AE00000A384002025E49800001038
+:10CE90003200609C0800C018ACE1C6A80030AAE0CF
+:10CEA00000008584001804E48F000010001884E45A
+:10CEB000090000103B00609C001804E4080000100A
+:10CEC0001D00C09D3C00609C001804E4040000109C
+:10CED0001E00C09D000065844100C3B90000609C35
+:10CEE00000182EE404000010FFFF8E9C1E00C09D61
+:10CEF000FFFF8E9C3B00609C001844E47100001012
+:10CF00000000C09C03008EB804006018588E63A80F
+:10CF10000800001930E208A90018A4E00040CAE0A7
+:10CF2000000085A8080060190CE26BA90000A58428
+:10CF300000586AE0002806D404008484002003D44A
+:10CF40001700609C00182EE42000000C1800609C64
+:10CF500000182EE41D00000C1900609C00182EE43F
+:10CF60001A00000C1D00609C00182EE41700000C35
+:10CF70001E00609C00182EE41400000C3200609C1F
+:10CF800000182EE41100000C3B00609C00182EE4F9
+:10CF90000E00000C3C00609C00182EE40B00000CFE
+:10CFA000FCFF8E9C1A00609C001844E40700000CF3
+:10CFB0000100009D0800E018F8E1E7A800386AE0E9
+:10CFC0005E000000004003D40000B2847007609C43
+:10CFD000F0FF859C001844E4180000100F00609CCE
+:10CFE000000094840018A4E5140000104004609C24
+:10CFF000001844E5110000100005609C001845E58C
+:10D0000005000010D002609C001844E51600000CDA
+:10D010000000001508000019B0E408A900408AE0EB
+:10D02000C09AFF07000064840000609C00180BE4B5
+:10D030000D00001000000015080060190CE96BA934
+:10D040000800A018F8E1A5A800586AE000288AE0C6
+:10D050001C00C09C0100E09C003003D4370000009D
+:10D06000003804D4080060188C7D63A80800E0181C
+:10D07000887DE7A80018AAE008000019B0E108A917
+:10D0800008006019847D6BA900386AE00040CAE09E
+:10D0900000588AE0000052860000009D0100609D5B
+:10D0A000000094860000638400901AD400A004D489
+:10D0B000001805D4004006D42000000008580AD407
+:10D0C0000800801830E284A80800A0180CE2A5A887
+:10D0D00000206AE000288AE0003003D499FFFF03B3
+:10D0E000003004D47EFFFF031900C09D0800E01843
+:10D0F000ACE1E7A800386AE079FFFF030000C385D0
+:10D10000000076A8000098A852FDFF070000AAA81A
+:10D1100073FFFF030000CBA9080060197C7D6BA999
+:10D1200000406018000563A800588AE2002003D47C
+:10D1300002FFFF0300000015000021850400418567
+:10D14000080081850C00C18510000186140041860D
+:10D15000180081861C00C1862000018724004187B9
+:10D16000004800442800219CFCFF219C004801D479
+:10D17000000024AA0000A3A93402809C0400218599
+:10D180000000609C00182DE411000010062391E0BF
+:10D19000002069E008008018A87D84A8002023E111
+:10D1A0005F0066B85F0088B8000069A90018E6E172
+:10D1B0000000609C00180DE413000010002088E0BF
+:10D1C0008100CFB810000000810004B90100609C0C
+:10D1D00000182DE408000010000000153402609CC7
+:10D1E00008008018647E84A8061B71E0ECFFFF0332
+:10D1F000001869E008008018207F84A8FBFFFF0367
+:10D200003402609C063385E00000609C006809D40D
+:10D21000141809D4201809D41C1809D4181809D4D2
+:10D220002C1809D4281809D4301809D4B01809D4F6
+:10D23000B41809D4B81809D4441809D4481809D422
+:10D24000342809D49F0064B8383009D43C3809D454
+:10D25000580063B8404009D4948809D4001884E089
+:10D26000880084B8502009D400002185004800447B
+:10D270000400219C000083840000A3A80000C09C3F
+:10D28000010064A4003003E40A000010020064A45A
+:10D2900048006584003003E404000010000000151D
+:10D2A0002C3003D400008584020064A40000C09CDC
+:10D2B000003003E4090000100300609C4C0065840A
+:10D2C000003003E404000010000000152C3003D4EB
+:10D2D000000085840300609C001824E40F00001007
+:10D2E0000000809C48006584002003E408000010D2
+:10D2F000000000154C00C584002006E40400001066
+:10D30000000000152C2003D42C2006D44400658492
+:10D310000000809C2C2003D40000609C041805D4DD
+:10D320000048004400000015000083840000A3A80A
+:10D330000000C09C010064A4003003E40B00001056
+:10D34000020064A448006584003003E40500001076
+:10D3500000000015283003D42C3003D4000085844D
+:10D36000020064A40000C09C003003E40A00001026
+:10D370000300609C4C006584003003E4050000104D
+:10D3800000000015283003D42C3003D4000085841D
+:10D390000300609C001824E4120000100000C09CF0
+:10D3A00048006584003003E40A0000100000001506
+:10D3B0004C008584003004E40600001000000015D5
+:10D3C000283003D42C3003D4283004D42C3004D497
+:10D3D000440065840000809C282003D42C2003D4C2
+:10D3E0000000C09C083005D4043005D40048004437
+:10D3F000000000150000A3840000648414008584EC
+:10D4000014006384001864E50600000C0100609DB0
+:10D410000018A4E50300000CFFFF609D0000609D64
+:10D4200000480044000000150000A384000064844C
+:10D430001800858418006384001864E50600000C59
+:10D44000FFFF609D0018A4E50300000C0100609D33
+:10D450000000609D00480044000000150000A38407
+:10D46000000064841800858418006384001864E553
+:10D470000600000C0100609D0018A4E50300000CEC
+:10D48000FFFF609D0000609D004800440000001503
+:10D490000000A384000064841C0085841C00638455
+:10D4A000001864E50600000CFFFF609D0018A4E56D
+:10D4B0000300000C0100609D0000609D00480044D6
+:10D4C000000000150000A38400006484040085842B
+:10D4D00004006384001864E50600000CFFFF609DF3
+:10D4E0000018A4E50300000C0100609D0000609D91
+:10D4F00000480044000000150000A384000064847C
+:10D500000400858404006384001864E50600000CB0
+:10D510000100609D0018A4E50300000CFFFF609D62
+:10D520000000609D00480044000000150000A38436
+:10D53000000064842400858424006384001864E56A
+:10D540000600000CFFFF609D0018A4E50300000C1E
+:10D550000100609D0000609D00480044000000152F
+:10D560000000A38400006484240085842400638474
+:10D57000001864E50600000C0100609D0018A4E599
+:10D580000300000CFFFF609D0000609D0048004408
+:10D5900000000015000083A80000609D2C0063843B
+:10D5A000005803E407000010000000152800648400
+:10D5B000005823E403000010000000150100609DE6
+:10D5C0000048004400000015000083A80000609D92
+:10D5D0002C006384005803E40700001000000015CD
+:10D5E00028006484005803E40300001000000015C4
+:10D5F0000100609D0048004400000015D0FF219C00
+:10D60000004801D4045001D4086001D40C7001D446
+:10D61000108001D4149001D418A001D41CB001D4FE
+:10D6200020C001D424D001D428E001D42CF001D4AE
+:10D63000000083AB000004AB0000C5A90000C6AB2E
+:10D64000000047AB0000009E008008E4A800001026
+:10D650000000409E0100C01AC8D5D6AA0100609CF7
+:10D6600000183CE4510000100200609C007072E55C
+:10D67000030000100000609C0100609C007070E5D9
+:10D68000030000100000809C0100809C042083E0C7
+:10D690000000609C001824E44300000C007092E538
+:10D6A0000F00000C020072B80000809E00C043E131
+:10D6B00000008AA900008A8400006484010063A439
+:10D6C00000A003E42800000C04004A9D0100529EC3
+:10D6D000007092E5F8FFFF1304008C9D007090E548
+:10D6E000E3FFFF0F020070B80000809E00C043E11E
+:10D6F00000008AA900008A8400006484020063A4F8
+:10D7000000A003E40800000C04004A9D0100109EE4
+:10D71000007090E5F8FFFF1304008C9DD4FFFF0319
+:10D720000000001500B000484C00648400A00BE429
+:10D73000F8FFFF130100109EFFFF109E00007A8487
+:10D740000100109E0000AC84020083B84C00A58448
+:10D750000100639C00F084E000181AD4C4FFFF03AA
+:10D76000002804D400B000484800648400A00BE402
+:10D77000D8FFFF130100529EFFFF529E00007A84E3
+:10D780000100529E0000AC84020083B84800A584CA
+:10D790000100639C00F084E000181AD4D0FFFF035E
+:10D7A000002804D40200609C00183CE454000010DF
+:10D7B00000000015007072E5030000100000609C7E
+:10D7C0000100609C007070E5030000100000809C68
+:10D7D0000100809C042083E00000609C001824E489
+:10D7E0004700000C007090E50F00000C020070B8BC
+:10D7F0000000809E00C043E100008AA900008A84E6
+:10D8000000006484020063A400A003E42800000C6C
+:10D8100004004A9D0100109E007090E5F8FFFF1380
+:10D8200004008C9D007092E5E3FFFF0F020072B8C8
+:10D830000000809E00C043E100008AA900008A84A5
+:10D8400000006484010063A400A003E40800000C4D
+:10D8500004004A9D0100529E007092E5F8FFFF13FC
+:10D8600004008C9DD4FFFF030000001500B00048A9
+:10D870004800648400A00BE4F8FFFF130100529EEF
+:10D88000FFFF529E00007A840100529E0000AC848B
+:10D89000020083B84800A5840100639C00F084E086
+:10D8A00000181AD4C4FFFF03002804D400B00048B5
+:10D8B0004C00648400A00BE4D8FFFF130100109E0D
+:10D8C000FFFF109E00007A840100109E0000AC84CF
+:10D8D000020083B84C00A5840100639C00F084E042
+:10D8E00000181AD4D0FFFF03002804D40100C01A86
+:10D8F00094D5D6AA5BFFFF030100609C0000218540
+:10D9000004004185080081850C00C1851000018656
+:10D9100014004186180081861C00C1862000018702
+:10D9200024004187280081872C00C18700480044DB
+:10D930003000219C44FE219C004801D4045001D4B5
+:10D94000086001D40C7001D4108001D4149001D46B
+:10D9500018A001D41CB001D420C001D424D001D41B
+:10D9600028E001D42CF001D40800C018E87BC6A838
+:10D97000000085A90000A3A90030A5E00100E09CFB
+:10D980000000C584000004AB0000C09EF003668464
+:10D990000000809F0400639C00E024E42303001047
+:10D9A000081847E20800E01820C5E7A800380CE294
+:10D9B000000070840000E09C001887E52700000C40
+:10D9C000000030A90800601878C463A80300609DB7
+:10D9D0000018CCE00000A68400006584005823E411
+:10D9E000190000100000009D440085842C00648410
+:10D9F000004003E41400001000000015020060184D
+:10DA00005C6763A80018CCE128006484004023E42C
+:10DA10000D0000100000001500008E841000058528
+:10DA2000680064840018A8E4FE020010029048E137
+:10DA3000185005D40000868444006484180084844F
+:10DA4000142003D4000069840100E79C001887E5D6
+:10DA5000E1FFFF130400C69C0800801824C584A8B9
+:10DA60000000E09C00204CE300007A84001887E569
+:10DA70001800000C0000DAA808006018C8C463A8E9
+:10DA80000300009D0000209D0018ACE0000085848C
+:10DA90000100E79C00006484004023E409000010BA
+:10DAA0000400A59C4400848428006484004803E4A6
+:10DAB00004000010000000151C006484181804D431
+:10DAC00000006684001887E5F1FFFF1300000015D1
+:10DAD0000200609C00182DE4030000100000A09CD0
+:10DAE0000100A09C0400609C00182DE403000010BD
+:10DAF0000000809C0100809C042065E00000809C68
+:10DB0000002003E40C00001000202DE40800801821
+:10DB100058C984A80000C09C00206CE00800A01830
+:10DB20005CC9A5A8003003D400288CE026030000BF
+:10DB3000003004D4030000100000A09C0100A09C51
+:10DB40000300C09C00302DE4030000100000609C26
+:10DB50000100609C041865E0002003E4140100103B
+:10DB6000002038E4002038E4BC0000100000E09CF5
+:10DB700000009084002087E52100000C020076B8A8
+:10DB80000800201978C429A9000004A9006063E0F6
+:10DB90000048ACE00800801838C584A8000046A9F9
+:10DBA000002023E1000085840100E79C0000C09C68
+:10DBB00000006484005023E40E0000100400A59CC3
+:10DBC000440084842C006484003003E409000010C5
+:10DBD0000000001528006484003023E405000010D4
+:10DBE00000000015002009D40100D69E0400299DE4
+:10DBF000004087E5ECFFFF13000000150800A018A7
+:10DC000038C5A5A80800E01858C9E7A800286CE0A6
+:10DC100000384CE2000096A80400A09C0100C01847
+:10DC2000F4D3C6A8151500040000D2A900009A84F8
+:10DC30000000E09C002087E51E00000C00B012D41C
+:10DC4000020076B8000004A90800A018C8C4A5A85E
+:10DC50000800801838C584A8006063E00300209D98
+:10DC60000020C3E00000409D00288CE00000A48458
+:10DC70000100E79C00006584004823E40A000010CE
+:10DC80000400849C4400A58428006584005003E4BB
+:10DC90000500001000000015002806D40100D69EE3
+:10DCA0000400C69C004087E5F1FFFF13000000154B
+:10DCB00000008E840800E01838C5E7A80100C018ED
+:10DCC00028D4C6A8020064B80400A09C00186CE028
+:10DCD000022096E0E9140004003863E000B00ED49E
+:10DCE000080060185CC963A8020080185C6784A8FB
+:10DCF00000188CE20000A09C0020CCE1002814D485
+:10DD00000000928400007484001824E424000010B1
+:10DD10000100609C0018A4E5210000100000009D97
+:10DD2000002088E51000000C0000C09C080060186E
+:10DD3000BCC563A80000E4A80018ACE07CFF8584A3
+:10DD40000100C69C00006584001804E40300001074
+:10DD50000400A59C0100009D003886E5F8FFFF1334
+:10DD6000000000150000609C001828E40C00001062
+:10DD70000000001508008018BCC584A80800A01881
+:10DD8000C0C5A5A800206CE000288CE00000A3849A
+:10DD90000000C484003003D4002804D400006E8442
+:10DDA0000000D2844400A3840030A5E503000010E5
+:10DDB000000000150000A6A8002812D448006384C3
+:10DDC000000094840020A3E503000010000000156B
+:10DDD000000064A8001814D42000809C0000F28485
+:10DDE0000020A7E50C00000C0000A09C020067B812
+:10DDF0000800201938C529A9006063E0004863E0E5
+:10DE00000100E79C002803D40020A7E5FDFFFF13D5
+:10DE10000400639C0000F4842000809C0020A7E59F
+:10DE20006902000C020067B80800C018BCC5C6A88B
+:10DE3000006063E0003063E00000209D0100E79C8B
+:10DE4000004803D40020A7E5FDFFFF130400639CF6
+:10DE50005D0200000000001500009084002087E5AE
+:10DE60005100000C020076B83C01E19D000004A9BD
+:10DE70000078C3E00000209D0800601878C463A803
+:10DE800000188CE00000A4840100E79C0400658475
+:10DE9000004803E4050000100400849C002806D418
+:10DEA0000100D69E0400C69C004087E5F6FFFF13E4
+:10DEB000000000150800E01858C9E7A800006FA886
+:10DEC00000384CE2307801D4000096A80400A09CF1
+:10DED0000100C0185CD4C6A8681400040000D2A9D0
+:10DEE0000800201938C529A90000809C00486CE072
+:10DEF0003000E185000043A90000B6A8002012D43C
+:10DF00000000F2A800008FA8000078A80000CAA8AE
+:10DF1000BBFDFF070000009D0000BA840000E09CEC
+:10DF2000002887E51E00000C02007CB83C00C19E62
+:10DF30000800C018C8C4C6A800B063E000308CE078
+:10DF40000000248501009C9F0100E79C004803D449
+:10DF50000400849C002887E5FAFFFF130400639CFB
+:10DF6000000076A800009CA80100C01890D4C6A8A4
+:10DF7000421400040400A09C000078A8000096A8A9
+:10DF80000000BCA80000CAA80000EEA89CFDFF0786
+:10DF90000100009D53FFFF0300000015F1FFFF0388
+:10DFA0003C00C19EC4FFFF033C01E19DDB0000106B
+:10DFB0000000A09C000090840000E09C002087E509
+:10DFC000D200000C000066A9020076B80200C0185A
+:10DFD0005C67C6A8000024A9006063E00030CCE1C3
+:10DFE0000800801838C584A80800A01878C4A5A81F
+:10DFF000002043E10028CCE0000086840100E79C7B
+:10E000000000A09C00006484005823E41400001069
+:10E010000400C69C440004852C006884002803E4A6
+:10E020000F0000100000001528006884002823E479
+:10E030000B0000100000001500006E840400A8848E
+:10E04000640083840028A4E505000010000000158A
+:10E0500000400AD40100D69E04004A9D004887E58E
+:10E06000E6FFFF13000000150800E01838C5E7A818
+:10E07000000096A800386CE00400A09C0100C018C5
+:10E08000F8D4C6A8FD130004000056A9000090842F
+:10E090000000E09C002087E52700000C020076B815
+:10E0A000000024A90800A01838C5A5A8006063E0F6
+:10E0B0000800801878C484A80300A09D0020CCE04C
+:10E0C000002863E1000086840100E79C0000A09C1A
+:10E0D00000006484006823E4140000100400C69C5F
+:10E0E000440004852C006884002803E40F0000101D
+:10E0F0000000001528006884002823E40B000010AD
+:10E100000000001500006E840400A884640083846D
+:10E11000002864E5050000100000001500400BD445
+:10E120000100D69E04006B9D004887E5E6FFFF13C3
+:10E130000000001502006AB80800C01838C5C6A85B
+:10E14000025016E200186CE00400A09C003063E06E
+:10E150000100C018C4D4C6A8C8130004000090A8C9
+:10E160000000C09C005086E51000000C020070B852
+:10E170000800E01838C5E7A808002019BCC529A97F
+:10E18000006063E00038ACE0004863E00000858494
+:10E190000100C69C002003D40400A59C005086E525
+:10E1A000FBFFFF130400639C00B08AE51100000C24
+:10E1B0000000CAA802006AB80800A018BCC5A5A83B
+:10E1C0000800E01838C5E7A8006063E000288CE08C
+:10E1D000003863E0000023850100C69C004804D499
+:10E1E0000400639C00B086E5FBFFFF130400849CE1
+:10E1F000080060185CC963A80800801858C984A882
+:10E2000000188CE200204CE200B014D400009A8484
+:10E21000000012AA000014AB0000E09C002087E57B
+:10E220002000000C00B012D4020076B80800A0183C
+:10E23000BCC5A5A80800C018C8C4C6A8006063E093
+:10E24000000024A9002803E10300409D0000609D18
+:10E250000030ACE0000085840100E79C000064848D
+:10E26000005023E40C0000100400A59C4400C4846A
+:10E2700028006684005803E4070000100000001521
+:10E280007C37E8D70100D69E44008484002008D45F
+:10E290000400089D004887E5EFFFFF13000000150C
+:10E2A000000090840800E01838C5E7A80400409DED
+:10E2B000020064B80100C01828D4C6A80000AAA8AB
+:10E2C00000186CE0022096E06C130004003863E054
+:10E2D0000000908408002019BCC529A90000AAA844
+:10E2E000020064B80100C01828D4C6A800186CE069
+:10E2F000004863E061130004022096E000B018D4E7
+:10E3000080FEFF0300B010D40200C0185C67C6A8EE
+:10E3100056FFFF030030CCE10800601858C963A81D
+:10E32000080080185CC984A800184CE200208CE228
+:10E33000002812D40100C09C000090840000D2ABE1
+:10E340000000E09C003014D4002087E5B000000CF1
+:10E3500038A001D4020076B83C01E19D000044A938
+:10E36000007823E10800801878C484A802006018AF
+:10E370005C6763A80000609D0018CCE100200CE100
+:10E380000000C8840100E79C00006684005803E494
+:10E390000B0000100400089D00006E842400A68479
+:10E3A000B4008384002884E50500001000000015F7
+:10E3B000003009D40100D69E0400299D005087E555
+:10E3C000F0FFFF130000001500006FA8000096A8E2
+:10E3D000307801D40400A09C0100C01860D5C6A804
+:10E3E00026130004000056A9000090840000E09C61
+:10E3F000002087E51B00000C3000E185020076B8A4
+:10E400000800C01878C4C6A8000064A90000A09D38
+:10E41000007823E100300CE10000C8840100E79C93
+:10E4200000006684006803E40B0000100400089DEF
+:10E4300000006E842400A684B4008384002864E570
+:10E440000500001000000015003009D40100D69E20
+:10E450000400299D005887E5F0FFFF130000001518
+:10E4600002006AB8025016E20100C0182CD5C6A8F6
+:10E4700000186FE0307801D40400A09CFF12000463
+:10E48000000090A80000C09C005086E55E00000CD3
+:10E490003000E185020070B8BC00619D0000AFA8AB
+:10E4A000005863E00000E5840100C69C003803D4F6
+:10E4B0000400A59C005086E5FBFFFF130400639C4D
+:10E4C00000B08AE50C00000C0000CAA802006AB87F
+:10E4D00000008BA8007863E0000023850100C69C43
+:10E4E000004804D40400639C00B086E5FBFFFF13E2
+:10E4F0000400849C0000609C3800A18408008018FF
+:10E5000038C584A808002019BCC529A900181ED444
+:10E5100000200CE2001805D400008FA800484CE150
+:10E52000345801D4000078A80000B6A80000D0A894
+:10E530000000FEA832FCFF070000009D340061854A
+:10E540000000B6A8000078A83800E18400008BA87D
+:10E550000000CAA82AFCFF070000009D0000BA8442
+:10E560000000E09C002887E52500000C02007CB834
+:10E570003C00C19E0800C018C8C4C6A800B063E033
+:10E5800000308CE00000248501009C9F0100E79C86
+:10E59000004803D40400849C002887E5FAFFFF1399
+:10E5A0000400639C000076A800009CA80100C0182D
+:10E5B00090D4C6A8B11200040400A09C000078A862
+:10E5C000000096A80000BCA80000D0A80000FEA88B
+:10E5D0000BFCFF070100009D3800E184000078A8D3
+:10E5E000000096A80000BCA80000CAA804FCFF0711
+:10E5F0000100009DC4FDFF0300009284EAFFFF03B9
+:10E600003C00C19EAFFFFF03BC00619D0200A0184B
+:10E610005C67A5A83C01E19D6CFFFF030028CCE1ED
+:10E6200005FDFF03184005D4003824E46400001001
+:10E63000000027AA0000E7A90000209E080080181B
+:10E6400020C584A80000E09C00200CE2000070843B
+:10E65000001887E53000000C000050A90800A01841
+:10E6600078C4A5A80000609D00280CE10200C01835
+:10E670005C67C6A80030CCE10000C8840400668452
+:10E68000005803E41F0000100000001500008E84F5
+:10E690001000A684680064840018A5E446000010F9
+:10E6A000029025E1184806D40000A8840000C09C10
+:10E6B00004006584010063A4003003E40700001037
+:10E6C0000000001518006584010063B848008584C7
+:10E6D000007863E0141804D404006584020063A485
+:10E6E000003003E4070000100000001518006584E6
+:10E6F000010063B84C008584008863E0141804D4DA
+:10E7000000006A840100E79C001887E5D8FFFF132A
+:10E710000400089D0800E01824C5E7A800384CE371
+:10E7200000007A840000E09C001887E5E9FCFF0FF8
+:10E7300000003AA908006018C8C463A80000009D42
+:10E740000018CCE00000A6840100E79C0800658466
+:10E75000010063A4004003E4070000100400C69C0D
+:10E76000480085841C006484010063B8007863E07D
+:10E77000181804D408006584020063A4004003E470
+:10E7800007000010000000154C0085841C00648404
+:10E79000010063B8008863E0181804D4000069849D
+:10E7A000001887E5E8FFFF130200609CCAFCFF0326
+:10E7B00000000015BDFFFF03182806D4A0FFFF03CB
+:10E7C0000000E09D0000218504004185080081854E
+:10E7D0000C00C18510000186140041861800818656
+:10E7E0001C00C18620000187240041872800818702
+:10E7F0002C00C18700480044BC01219CFCFF219CE7
+:10E80000004801D4040080187C8484A80000A3AAD6
+:10E81000000004850200209D2000C09C0500A09DF2
+:10E820002003E09C0400609D050069B80000A09CE6
+:10E83000004863E0065B63E0004063E00000E09DA9
+:10E840000100A59C007803D40030A5E5FDFFFF136F
+:10E850000400639C000064840100299D003863E08B
+:10E860000400E79C0068A9E5F0FFFF13007803D4DB
+:10E870000800801858C984A80400A0187C84A5A8A2
+:10E88000002075E01000C09C000083840030A4E5E7
+:10E89000030000100000E584000086A808000019AD
+:10E8A0005CC908A9182307D4004075E00000638400
+:10E8B0000030A3E5030000100000209D000066A8C2
+:10E8C000002089E52700000C1C1B07D408006018F5
+:10E8D00038C563A8000025AB000064AA0000E09ED4
+:10E8E0001402209E1002E09D0C01A09D0801609D75
+:10E8F000001815E10000888400B804E4120000103C
+:10E900000100299D0000B984B0008484005865E0AE
+:10E910000068C5E0002003D40078E5E000008884AA
+:10E920000088A5E0B4008484002006D40000688438
+:10E93000B4006384001807D400008884B000848485
+:10E94000002005D40800319E0800EF9D0800AD9D11
+:10E9500008006B9D009889E5E7FFFF130400089D00
+:10E960000400C0187C84C6A80000209D00006684B6
+:10E9700018038384010084B81C03A384202303D4D8
+:10E98000002889E52900000C282303D408008018FA
+:10E99000BCC584A80000609E9802209E9402E09D61
+:10E9A0009001A09D8C01609D002015E100008884ED
+:10E9B000009804E4120000100100299D0000A684C4
+:10E9C000B0008484005865E00068C5E0002003D4EE
+:10E9D0000078E5E0000088840088A5E0B400848425
+:10E9E000002006D400006884B4006384001807D4B3
+:10E9F00000008884B0008484002005D40400C0187E
+:10EA00007C84C6A80800319E000086840800EF9D23
+:10EA10000800AD9D1C03648408006B9D001889E507
+:10EA2000E3FFFF130400089D040060187C8463A8C2
+:10EA30000800C01858C9C6A8000083840030B5E09B
+:10EA40000000209D1C0364840500009D0000E4A8D4
+:10EA5000010063B81803C09C241B04D42C1B04D4ED
+:10EA6000003067E00100299D000063840400C69C1B
+:10EA7000001805D40040A9E5FAFFFF130400A59C87
+:10EA8000040060187C8463A80000209D000063845B
+:10EA900018038384002089E51300000C1402639C92
+:10EAA0000000A4A8080000194CC708A9004095E080
+:10EAB000F4FEE3850100299DF47EE4D7F8FEC384CB
+:10EAC000F836E4D7FCFF0385FC47E4D70000E38574
+:10EAD000007804D40800639C002889E5F5FFFF1343
+:10EAE0000800849C040060187C8463A80000209DBA
+:10EAF000000063841C038384002089E51300000C5C
+:10EB00000000A4A80800C018D0C7C6A89802639C3B
+:10EB1000003095E0F4FE03850100299DF446E4D71A
+:10EB2000F8FEE385F87EE4D7FCFFC384FC37E4D726
+:10EB300000000385004004D40800639C002889E598
+:10EB4000F5FFFF130800849C000021850048004465
+:10EB50000400219CFCFF219C004801D40000A4A9D2
+:10EB6000000063AA0800801820C584A80000E09C6B
+:10EB700000206DE000008384002087E54900000C40
+:10EB80000000609D0200A0185C67A5A8000024AAF0
+:10EB900000286DE00000209D000083840000009D9F
+:10EBA0000300A09E0800601878C463A82C00E485C8
+:10EBB0000018CDE000482FE41700001000000015F9
+:10EBC000000086840400648400A823E40B00001085
+:10EBD000000000154400648528006B84004823E48D
+:10EBE000060000100000001514006B84009823E458
+:10EBF0002C00000C000000150400C69C0100E79CDE
+:10EC0000008887E5ECFFFF130400089D2500000045
+:10EC10000000609D0000A68404006584010063A4D8
+:10EC2000004803E40B000010000088A84800658538
+:10EC300028006B84004823E4060000100000001543
+:10EC400014006B84009823E41600000C00000015EB
+:10EC50000800A01878C4A5A8002884E000208DE052
+:10EC60000000A09C0000848404006484020063A46B
+:10EC7000002803E4E1FFFF13000000154C00648549
+:10EC800028006B84002823E4DCFFFF13000000153C
+:10EC900014006B84009823E4D9FFFF130400C69C82
+:10ECA00000002185004800440400219CFCFF219CB9
+:10ECB000004801D40000A4A9000063AA080080183D
+:10ECC00024C584A80000E09C00206DE0000083843F
+:10ECD000002087E54900000C0000609D0200A0189C
+:10ECE0005C67A5A8000024AA00286DE00000209D14
+:10ECF000000083840000009D0300A09E08006018AF
+:10ED0000C8C463A82C00E4850018CDE000482FE4B7
+:10ED100017000010000000150000868404006484C1
+:10ED200000A823E40B0000100000001544006485D7
+:10ED300028006B84004803E4060000100000001562
+:10ED400018006B84009823E42C00000C00000015D0
+:10ED50000400C69C0100E79C008887E5ECFFFF13D8
+:10ED60000400089D250000000000609D0000A684AE
+:10ED700004006584010063A4004803E40B00001054
+:10ED8000000088A84800658528006B84004803E4DB
+:10ED9000060000100000001518006B84009823E4A2
+:10EDA0001600000C000000150800A018C8C4A5A893
+:10EDB000002884E000208DE00000A09C00008484F6
+:10EDC00004006484020063A4002803E4E1FFFF134D
+:10EDD000000000154C00648528006B84002803E4C3
+:10EDE000DCFFFF130000001518006B84009823E47B
+:10EDF000D9FFFF130400C69C000021850048004491
+:10EE00000400219CECFF219C004801D4045001D453
+:10EE1000086001D40C7001D4108001D4000044A912
+:10EE2000000083A9000087A80000C6A9000005AA69
+:10EE300049FFFF07000065A801008A9C0000CE84FE
+:10EE4000003044E50D00000C000024A9020064B865
+:10EE50000000E09C006063E0FCFFA384003805E450
+:10EE600003000010FFFF849C002803D4003044E519
+:10EE7000FAFFFF13FCFF639C020066B80100869C4A
+:10EE8000006063E000200ED40048A4E51800000CE8
+:10EE9000005803D4020064B80000009D0060C3E085
+:10EEA0000000E6A80000A6840100849C004005E460
+:10EEB0000C0000100400C69C28006584004023E478
+:10EEC000060000100000001514006584008023E493
+:10EED0000400000C00000015002807D40400E79C83
+:10EEE0000048A4E5F0FFFF13000000150000218595
+:10EEF00004004185080081850C00C1851000018651
+:10EF0000004800441400219CECFF219C004801D4DF
+:10EF1000045001D4086001D40C7001D4108001D4D5
+:10EF2000000044A9000083A9000005AA000087A8EA
+:10EF30000000C6A95EFFFF07000065A801008A9CCB
+:10EF40000000AE84002844E50A00000C000024A95B
+:10EF5000020064B8006063E0FCFFC384FFFF849C90
+:10EF6000003003D4002844E5FCFFFF13FCFF639C42
+:10EF7000020065B80100859C006063E000200ED4AB
+:10EF80000048A4E51800000C005803D4020064B83F
+:10EF90000000009D0060C3E00000E6A80000A68419
+:10EFA0000100849C004005E40C0000100400C69C95
+:10EFB00028006584004003E40600001000000015EE
+:10EFC00018006584008023E40400000C0000001594
+:10EFD000002807D40400E79C0048A4E5F0FFFF13D5
+:10EFE000000000150000218504004185080081858E
+:10EFF0000C00C18510000186004800441400219CCB
+:10F00000CCFF219C004801D4045001D4086001D4F5
+:10F010000C7001D4108001D4149001D418A001D434
+:10F020001CB001D420C001D424D001D428E001D4E4
+:10F030002CF001D40000C4AB34000187020080181A
+:10F040005C6784A80000C3AA000085AA002078E0BD
+:10F050000000A09C00002385000086A9000047ABAB
+:10F060002C008984000088AB0000609C001824E418
+:10F0700051000010302801D402008018D05B84A811
+:10F0800068004986002069E00000038600006C8467
+:10F09000000052A90300C09C003023E42700000CAC
+:10F0A0000000C09D0000A09C006065E0000083841B
+:10F0B0000030A4E53A00000C0100609C001844E513
+:10F0C0002E0000100000C09C003024E4230000103B
+:10F0D00000D065E00000838402206AE0FFFFA39C6B
+:10F0E000003065E504000010000045A9008063E0E1
+:10F0F000FFFF439D0090AAE513000010000076A8D2
+:10F100000280AAE0000094A83000C19C3EFFFF07E7
+:10F110000000F8A80100CE9D0300C09C02006EB85C
+:10F120000000A3A8006083E000006484003023E4B2
+:10F13000DFFFFF13006065E00100749C2700000002
+:10F1400000181ED4000094A8F0FFFF030000AAA836
+:10F15000E9FFFF03000045A90000838400206AE066
+:10F160000100A39C008085E5FAFFFF13028063E0A5
+:10F17000E1FFFF030100439D00E085E0000076A869
+:10F180000000A4843000C19C0000F8A85FFFFF07C6
+:10F19000000094A8E1FFFF030100CE9D0800A01825
+:10F1A00014E2A5A80100809C002878E00B00000074
+:10F1B000002003D40200A018D05BA5A868006984D1
+:10F1C000002889E00000A484010063B8010005BAAA
+:10F1D000AFFFFF030100439E00002185040041852D
+:10F1E000080081850C00C18510000186140041864D
+:10F1F000180081861C00C1862000018724004187F9
+:10F20000280081872C00C187004800443400219CDD
+:10F21000E0FF219C044801D4085001D40C6001D4C3
+:10F22000107001D4148001D4189001D41CA001D412
+:10F23000000083A9000045A9000004AA0200609C08
+:10F2400000180CE4030000100000A09C0100A09C2A
+:10F250000400609C00180CE4030000100000809C77
+:10F260000100809C032065E00000409E009003E4C4
+:10F270002D0000100100609C20007084009003E4C9
+:10F280006B00000C2400D09C0800601858C963A8CB
+:10F29000020080185C6784A800188AE20020CAE196
+:10F2A00000006E844400A384020085B80800601842
+:10F2B00034C563A8001884E000208AE0000064845C
+:10F2C000009023E41400001000000015FFFF859C4F
+:10F2D0000000C09C0020A6E50F00000C00000015F7
+:10F2E0000800601838C563A80000E09C0018AAE078
+:10F2F00000006584003823E4040000100100C69C6F
+:10F30000FCFF6584001805D40020A6E5F9FFFF1373
+:10F310000400A59C00006E8444006384001814D48B
+:10F320000100609C00182CE4540000100000409E76
+:10F33000A8017084009003E42A00000CB002109D24
+:10F34000020060185C6763A8080080185CC984A884
+:10F350000018CAE100208AE100006E844800A384FE
+:10F36000020085B808006018B8C563A8001884E0DA
+:10F3700000208AE000006484009023E4150000105F
+:10F3800000000015FFFF859C0000C09C0020A6E542
+:10F390001000000C000000150000A4A80800601870
+:10F3A000BCC563A80000E09C00188AE000006484EB
+:10F3B000003823E4040000100100C69CFCFF6484B4
+:10F3C000001804D40028A6E5F9FFFF130400849C6C
+:10F3D00000006E84480063842800000000180CD4EC
+:10F3E0000800A018BCC5A5A8020080185C6784A806
+:10F3F00000286AE00020CAE10800A0185CC9A5A89E
+:10F4000000008E8400288AE14800A484AC01D09CCE
+:10F410003002F09CFFFFA59C005001D4F9FEFF07CD
+:10F4200000008CA8CEFFFF0300006E84020060186D
+:10F430005C6763A80800801838C584A80018CAE172
+:10F440000800A01858C9A5A800206AE000288AE290
+:10F4500000008E84A800F09C4400A4842801109D24
+:10F46000FFFFA59C005001D4E6FEFF07000094A812
+:10F470008DFFFF0300006E84040021850800418594
+:10F480000C0081851000C18514000186180041869A
+:10F490001C008186004800442000219CE0FF219C44
+:10F4A000004801D4045001D4086001D40C7001D488
+:10F4B000108001D4149001D418A001D41CB001D440
+:10F4C000000003AA080060181CC563A80000C09DC6
+:10F4D000001890E20000748400188EE51800000CFB
+:10F4E0000000409E0800801828C484A80800A018C6
+:10F4F00078C4A5A80000C09E002050E1002890E13B
+:10F5000000006A84000090A89A0700040100529E3F
+:10F5100000B00BE4060000100000001500006A8433
+:10F520000100CE9D00180CD404008C9D0000748452
+:10F53000001892E5F3FFFF1304004A9D08008018AD
+:10F5400018C584A80800A01820C5A5A8002070E050
+:10F55000002890E00000A38400288EE50D00000C38
+:10F56000007004D402006EB80800801878C484A823
+:10F57000008063E0002063E00000809C0100CE9DDD
+:10F58000002003D400288EE5FDFFFF130400639CD8
+:10F590000000218504004185080081850C00C1859B
+:10F5A0001000018614004186180081861C00C18667
+:10F5B000004800442000219CE0FF219C004801D429
+:10F5C000045001D4086001D40C7001D4108001D41F
+:10F5D000149001D418A001D41CB001D4000003AAD7
+:10F5E000080060181CC563A80000C09D001890E2C8
+:10F5F0000000748400188EE51800000C0000409E86
+:10F600000800801828C484A80800A018C8C4A5A8A9
+:10F610000000C09E002050E1002890E100006A84B4
+:10F62000000090A8880700040100529E00B00BE47F
+:10F63000060000100000001500006A840100CE9D45
+:10F6400000180CD404008C9D00007484001892E50E
+:10F65000F3FFFF1304004A9D0800801818C584A812
+:10F660000800A01824C5A5A8002070E0002890E09C
+:10F670000000A38400288EE50D00000C007004D467
+:10F6800002006EB808008018C8C484A8008063E037
+:10F69000002063E00000809C0100CE9D002003D488
+:10F6A00000288EE5FDFFFF130400639C0000218508
+:10F6B00004004185080081850C00C1851000018689
+:10F6C00014004186180081861C00C1860048004451
+:10F6D0002000219CE4FF219C004801D4045001D467
+:10F6E000086001D40C7001D4108001D4149001D4AE
+:10F6F00018A001D40000C4A9000043AA5C008384C0
+:10F700000000609C001804E46D000010000000156B
+:10F71000080060181CC563A80000409D00180EE298
+:10F720000000708400188AE51A00000C0000001523
+:10F730000800801828C484A80000809E00208EE164
+:10F740000000CC8401004A9D0000609C200086845B
+:10F7500000A024E45500000C0000AEA80000A09C0E
+:10F7600004008C9D002806D4042806D4082806D45A
+:10F770000C2806D4202806D44C2806D40000708417
+:10F78000442806D400188AE5EEFFFF13482806D463
+:10F790000800801820C584A80000409D00206EE06D
+:10F7A0000000638400188AE50B00000C00000015BF
+:10F7B0000800A01878C4A5A800288EE00000A09C2E
+:10F7C00001004A9D002804D400188AE5FDFFFF13BC
+:10F7D0000400849C0800801824C584A80000409D73
+:10F7E00000206EE00000638400188AE50B00000C26
+:10F7F000000000150800A018C8C4A5A800288EE0C5
+:10F800000000A09C01004A9D002804D400188AE54D
+:10F81000FDFFFF130400849C0000609C001810D4BE
+:10F820000800A01834C5A5A800006EA800288EE026
+:10F830000000A09C1AFFFF07002804D45FFFFF0709
+:10F8400000006EA80800801828C584A80080A018B1
+:10F850000000A5A800206EE0002803D46000928478
+:10F860000000609C001804E40A000010FFFFA09C48
+:10F87000080080182CC584A80000A09C00206EE021
+:10F88000002803D41C2812D4110000000100609C41
+:10F89000080080182CC584A800206EE0002803D43E
+:10F8A0000B0000000000609C4400C6848E0E000423
+:10F8B00094008684AAFFFF030000CC84940900040E
+:10F8C00000006EA8D7FFFF0300000015281812D40F
+:10F8D0000000218504004185080081850C00C18558
+:10F8E00010000186140041861800818600480044FB
+:10F8F0001C00219CF4FF219C004801D4045001D439
+:10F90000086001D4000083A9000044A90800601821
+:10F9100030C563A8001884E00800601824C563A8F7
+:10F920000018EAE0000064840800801820C584A85C
+:10F930000020AAE0000087840000C584022063E064
+:10F94000001826E4200000100000C09C0800601889
+:10F950001CC563A80018EAE000006784001886E56B
+:10F960001900000C0000009D0800801828C484A81D
+:10F970000020AAE0000085840100C69C0400648485
+:10F98000004003E4060000100400A59C0800648405
+:10F99000004023E40800000C000064A80000678415
+:10F9A000001886E5F4FFFF130000609C08000000CB
+:10F9B00028180CD430F6FF0700008AA8B8FEFF070D
+:10F9C00000006AA80000609C28180CD40000218563
+:10F9D0000400418508008185004800440C00219CFA
+:10F9E0000000A4A8000063A9000083840000609CBC
+:10F9F000001824E4040000100000001505000000B9
+:10FA000020006B8420006B84010063B80100639CBC
+:10FA1000022863E1FFFF6B9D0048004400000015D1
+:10FA2000F4FF219C004801D4045001D4086001D4A3
+:10FA3000000085A9EBFFFF07000043A9080060183C
+:10FA400020C563A80000009D0018ECE100006F8451
+:10FA5000001888E55D00000C0000A09D08008018DB
+:10FA600078C484A800004A850020ECE00000209DB6
+:10FA700000682AE41C0000100300609C0000A784BA
+:10FA800004008584001824E40B0000100000001519
+:10FA900008006584006823E40700001000000015DA
+:10FAA0004400658414008384005824E40A00000C98
+:10FAB000000065A800006F840400E79C0100089D19
+:10FAC000001888E5EBFFFF130400299D3F000000AC
+:10FAD00000000015E8F5FF0700008CA83B000000BF
+:10FAE000000000150000C78404006684010063A4C0
+:10FAF000006803E40C000010000089A80800668478
+:10FB0000010063A4006823E4070000100000001552
+:10FB10004800A68414006584005823E42300000CE8
+:10FB20000000609C0800601878C463A80000A09CD6
+:10FB3000001884E000208CE00000C4840400668487
+:10FB4000020063A4002803E4DBFFFF13000000159C
+:10FB500008006684020063A4002823E4D6FFFF1394
+:10FB6000000000154C00868414006484005823E4CF
+:10FB7000D1FFFF13000000152C2804D40400668474
+:10FB80000300809C010063A40000A684002025E4FB
+:10FB90000E000010041806D4440066840000809C07
+:10FBA0000A0000002C2003D40300809C2C1805D4EC
+:10FBB00004006684020063A40000A684002025E4FB
+:10FBC000F6FFFF0F041806D40000218504004185CC
+:10FBD00008008185004800440C00219CDCFF219C2A
+:10FBE000004801D4045001D4086001D40C7001D441
+:10FBF000108001D4149001D418A001D41CB001D4F9
+:10FC000020C001D40000C3AA000045AA0800601863
+:10FC100024C563A8001885E20000809D000074845C
+:10FC200000188CE56700000C000004AB0800801889
+:10FC3000C8C484A80000009E002045E10000C09DCB
+:10FC400000007684008023E41C0000100300809CE8
+:10FC50000000AA8404006584002023E40B00001047
+:10FC60000000001508006584002023E40700001050
+:10FC700000000015440065841800838400C024E45B
+:10FC80000A00000C000065A80000748404004A9D6E
+:10FC900001008C9D00188CE5EAFFFF130400CE9D47
+:10FCA0004800000000000015A0F5FF07000092A822
+:10FCB000F7FFFF03000074840000CA840400668418
+:10FCC000010063A4008003E40C00001000008EA873
+:10FCD00008006684010063A4008003E407000010AC
+:10FCE000000000154800A6841800658400C023E4C5
+:10FCF0002800000C0000609C08006018C8C463A8BD
+:10FD00000000A09C001884E0002092E00000C48461
+:10FD100004006684020063A4002803E4DBFFFF13F1
+:10FD20000000001508006684020063A4002803E4B4
+:10FD3000D6FFFF13000000154C0086841800648471
+:10FD400000C023E4D1FFFF1300000015282804D4CD
+:10FD50002C2804D40400668408008684010063A46F
+:10FD6000010084A4041806D40000A6840300609C4B
+:10FD7000001825E413000010082006D4440066840F
+:10FD80000000809C282003D40E0000002C2003D407
+:10FD9000281805D42C1805D404006684080086842D
+:10FDA000020063A4020084A4041806D40000A68400
+:10FDB0000300609C001825E4F1FFFF0F082006D423
+:10FDC0000000218504004185080081850C00C18563
+:10FDD0001000018614004186180081861C00C1862F
+:10FDE00020000187004800442400219CE8FF219C5A
+:10FDF000004801D4045001D4086001D40C7001D42F
+:10FE0000108001D4149001D4000043AA08006018A7
+:10FE100024C563A80000809D001804E200007084DF
+:10FE200000188CE51600000C0000C4A9080060183A
+:10FE3000C8C463A8001844E100006A8401008C9DD6
+:10FE400000008EA81C00A384009025E40800000C8C
+:10FE500004004A9D0000708400188CE5F7FFFF1332
+:10FE60000000001506000000000000152FF5FF0738
+:10FE700000000015F9FFFF030000708400002185D9
+:10FE800004004185080081850C00C18510000186B1
+:10FE900014004186004800441800219CD4FF219C96
+:10FEA000004801D4045001D4086001D40C7001D47E
+:10FEB000108001D4149001D418A001D41CB001D436
+:10FEC00020C001D424D001D428E001D4000083AAAA
+:10FED000000044AA0000C5AA000046AB0000609CD8
+:10FEE000001867E50C000010000088A902008018C7
+:10FEF0005C6784A80200C018D05BC6A8002068E038
+:10FF000000008384003084E000006484010063B852
+:10FF10000018E7E00800601824C563A80000C09D31
+:10FF200000180CE20000708400188EE55A00000CE6
+:10FF30005F0067B808008018C8C484A8001867E08C
+:10FF400000204CE1810003BB000098AB00008A84D4
+:10FF50001C006484009023E43C0000100100C09C5D
+:10FF6000003034E41B0000100300609C0800A484EF
+:10FF7000001825E41400000C003025E41200000CE9
+:10FF80000000A09C002816E43D00001000000015B1
+:10FF90000800C01834C5C6A800306CE000006384B7
+:10FFA000002803E408000010002023E406000010ED
+:10FFB000000000151000638400D023E40600000C4C
+:10FFC0000200C09C000064A8D8F4FF0700008CA8C1
+:10FFD0000200C09C003034E41C0000100300609C50
+:10FFE0000000AA8408008584001824E41400000C92
+:10FFF000003024E41200000C0000809C002016E475
+:020000022000DC
+:1000000019000010000000150800C01834C5C6A86B
+:1000100000306CE000006384002003E4080000105E
+:10002000002823E40600001000000015100063847F
+:1000300000D023E40500000C00000015000065A8B6
+:10004000BAF4FF0700008CA8000070840100CE9D68
+:1000500000188EE5BEFFFF1304004A9D0E0000004D
+:10006000000000151000658400E003E4F7FFFF13B3
+:10007000000065A8F3FFFF03000000151000648472
+:1000800000C003E4D4FFFF130200C09CCFFFFF03B6
+:10009000000064A8000021850400418508008185D6
+:1000A0000C00C1851000018614004186180081866D
+:1000B0001C00C18620000187240041872800818719
+:1000C000004800442C00219CFCFF219C004801D4E6
+:1000D0000000E4A9000083840000609C001824E470
+:1000E000380000100100609C0800601820C563A85B
+:1000F0000000209D001886E000006484001889E557
+:100100008900000C000064A90800A01978C4ADA9FA
+:10011000006886E00300A09D0000E4840100299DA2
+:1001200004006784006823E40B0000100000C09CFA
+:100130004400078528006884003023E4060000108E
+:100140000000001514006884002823E40800000C57
+:100150000100609C00006B84001889E5EFFFFF132D
+:100160000400849C70000000000000151C7808D476
+:100170001C7807D44800A784281808D4003005E468
+:100180000C000010187808D44C006784003003E499
+:10019000080000100100C09C1C7803D4283003D450
+:1001A000187805D4283005D4187803D41C7805D4E1
+:1001B000000064840300A09D5B000000086803D475
+:1001C000001824E4560000100000E3A8000003A972
+:1001D0000000E09C0800601820C563A80000209D76
+:1001E000001866E100006B84001889E54E00000CE1
+:1001F00001006FB80800A01978C4ADA9006886E0B6
+:10020000003863E20000A09D004023E20000E48487
+:100210000100299D04006784010063A4006803E4D1
+:100220000C0000100000009D4800C7842800668470
+:10023000006823E407000010000000151400668425
+:10024000002823E42700000C0100609C0000E484E7
+:1002500004006784020063A4004003E40B00001064
+:100260000400849C4C00C78428006684004023E47A
+:10027000060000100000001514006684002823E426
+:100280000800000C0000001500006B84001889E5D0
+:10029000DFFFFF1300000015230000000000001521
+:1002A0001C7806D40100A09D1C7807D40300809C14
+:1002B000189806D4286806D408006784020063A84A
+:1002C000002023E418000010081807D444006784B5
+:1002D0001C7803D4286803D413000000187803D4D2
+:1002E0001C7806D41C7807D40300809C188806D498
+:1002F000281806D408006784010063A8002023E4BE
+:1003000009000010081807D4440067840100809C8D
+:100310001C7803D4F1FFFF03282003D4AEFFFF03B2
+:100320000000009D00002185004800440400219C3D
+:10033000ECFF219C004801D4045001D4086001D492
+:100340000C7001D4108001D40000C5A9000003AADC
+:10035000000086A9A3FDFF070000A6A80000908466
+:100360000000609C001824E44000000C00004BA931
+:100370000800801820C584A80000609D00206CE063
+:100380000000C09C0000E3840000209D0000009D50
+:100390000800601878C463A80018ACE0003886E54F
+:1003A0001A00000C0000609C000085840400648436
+:1003B000010063A4004803E4080000100100C69C8B
+:1003C0004800648414008384005024E42500000C59
+:1003D000000000150000858404006484020063A40A
+:1003E000004003E4EEFFFF130400A59C4C0064846E
+:1003F00014008384005024E4E9FFFF13000000157B
+:100400000200609D0000609C00182BE408000010B2
+:1004100000006BA80800801814E284A800206CE09B
+:100420000100809C16000000002003D400008EA86C
+:100430000000A09C0000C09C0000EAA898FEFF07F6
+:1004400000000CA9000070A800008EA80000AAA857
+:100450001EFFFF070000CCA80900000000000015E7
+:10046000E9FFFF030100609D00006EA860FEFF072A
+:1004700000008CA8F5FFFF03000070A80000218594
+:1004800004004185080081850C00C18510000186AB
+:10049000004800441400219CE8FF219C004801D43E
+:1004A000045001D4086001D40C7001D4108001D430
+:1004B000149001D40000C4A9FFFF639C08008018B9
+:1004C00024C584A80000809D00204EE20800849C82
+:1004D00000200EE20000928400208CE51700000C42
+:1004E000001810D408006018C8C463A800184EE1B2
+:1004F00000006A8401008C9D00008EA81C00C3844B
+:100500000000B0840028A6E50800000C04004A9D05
+:100510000000728400188CE5F6FFFF130000001540
+:10052000060000000000001580F3FF070000001522
+:10053000F9FFFF030000728400002185040041855B
+:10054000080081850C00C1851000018614004186D9
+:10055000004800441800219CFCFF219C004801D465
+:10056000000083A8CDFFFF070000609C00002185EC
+:10057000004800440400219CECFF219C004801D469
+:10058000045001D4086001D40C7001D4108001D44F
+:100590000000C3A90000809D0800601820C563A862
+:1005A00000180EE20000708400188CE50D00000CAD
+:1005B000000000150800601878C463A800184EE118
+:1005C00000006A8400008EA82BF3FF0701008C9DB9
+:1005D0000000708400188CE5FAFFFF1304004A9DA8
+:1005E000AFFBFF0700006EA80000218504004185D5
+:1005F000080081850C00C185100001860048004478
+:100600001400219CF4FF219C004801D4045001D423
+:10061000086001D400002385000043A9000065A9FB
+:10062000000005A9000084A9000069A80100A09CA1
+:100630000000C09C003029E4070000100000E09C8E
+:1006400000008BA8EAFDFF0700006CA80500000071
+:100650000100609C12FEFF071400CA840100609C28
+:100660001C600AD428180AD40000218504004185A2
+:1006700008008185004800440C00219CECFF219C6F
+:10068000004801D4045001D4086001D40C7001D496
+:10069000108001D40000C3A9000044A90200601822
+:1006A0005C6763A80000809D001804E2000070846D
+:1006B00002008018F85B84A8002063E0006003D487
+:1006C0009800AE84020065B8005063E01400838493
+:1006D00000208CE53700000C0000C5A80000609CDD
+:1006E000001805E4A800001002006CB8006063E088
+:1006F000020063B801008C9D00186AE09C02E39C34
+:10070000000087840600609C001844E498000010F4
+:10071000020064B804008018BC7584A8002063E05F
+:10072000000083840020004400000015020066B829
+:100730000100E09C005063E014008384003824E44E
+:1007400017000010020066B80800601874E163A882
+:1007500000188AE00800601838ED63A80018AAE0C5
+:1007600000006484020063B8080080188CE884A844
+:10077000003805D4002063E00018AAE0000085845A
+:100780000000609C001824E403000010AE00609C90
+:10079000001805D49800CE84020066B8005063E0CB
+:1007A0001400838400208CE5CDFFFF130000A6A871
+:1007B0000000D08402008018F85B84A8002066E066
+:1007C0000000A3840000809C002005E47400001059
+:1007D0000100609C20200ED414200ED4682006D482
+:1007E00000008E84001804E425000010001884E442
+:1007F000100000100200609C001804E409000010C2
+:100800000000809C0000908400006AA80400CE854F
+:10081000BF050004B47004D461000000000000159E
+:10082000602006D410200ED4F7FFFF0304200ED45E
+:100830000C006E840400AE8410008E84022863E0F5
+:10084000022884E00C180ED410200ED45C1806D4B4
+:1008500010006E84601806D410006E840C008E8424
+:100860000020A3E50300001000000015000064A8AC
+:1008700004180ED4E4FFFF03641806D40000609C43
+:100880005C1806D40C180ED4DFFFFF0304180ED436
+:100890000400878400006EA862FCFF070000AAA87D
+:1008A000FFFAFF0700006AA8BCFFFF039800CE8490
+:1008B000080087840000AAA8C9FCFF0700006EA8F2
+:1008C0003EFBFF0700006AA8B4FFFF039800CE8438
+:1008D0000C00A78400006EA80000CAA895FEFF07C0
+:1008E000040087840800801814E284A800206AE0CD
+:1008F0000000A3840000809C002005E42800000C78
+:1009000000000015E6FAFF0700006AA8EDFFFF03EC
+:100910000000001510006784E0FEFF0700008AA8B1
+:10092000E8FFFF030000001514FFFF0700006AA89E
+:100930000AFFFF0700006AA8000070840200801808
+:10094000F85B84A8002063E00100809C92FFFF0315
+:10095000002003D40C00878400006EA82AFFFF0744
+:100960000000AAA88DFFFF039800CE84080080181D
+:1009700014E284A800206AE00100809C08000000C6
+:10098000002003D4006063E0020063B801008C9D86
+:1009900000186AE05BFFFF031C00E39C0000218558
+:1009A00004004185080081850C00C1851000018686
+:1009B000004800441400219CF8FF219C004801D409
+:1009C000045001D4000063AA0000209D08006018B4
+:1009D000ACE263A8001873E300007B84001889E58B
+:1009E0005800000C0000001508008018EC7B84A85B
+:1009F0000020B3E100006D840000809C010063A42E
+:100A0000002003E44A0000100000E09D0800801868
+:100A10001CC584A8002073E00000638400188FE5E3
+:100A20003C00000C0000609D000023AA0300209FF2
+:100A30000800601828C463A80000409D0000E09FE3
+:100A40000200E09E0000A09F0018F3E00100A09EBD
+:100A50000000A7840400858400C824E40C00001072
+:100A60000100009D4400C58494006684004823E48E
+:100A700007000010000000152C006684005003E4FD
+:100A800003000010000000150100E09D004024E478
+:100A90000C000010000000154800C5849400668416
+:100AA000004823E407000010000000152C006684B5
+:100AB00000F803E403000010000000150000E8A99E
+:100AC00000B824E40C000010000000154C008584E0
+:100AD00094006484004823E407000010000000151F
+:100AE0002C00648400E803E40300001000000015FB
+:100AF0000100E09D00A82FE40700000C0000609CAE
+:100B000001006B9D00888BE5D2FFFF130400E79C7A
+:100B10000000609C00182FE4050000100000001584
+:100B200000006D84060063A400180DD400007B84CF
+:100B30000100299D001889E5AFFFFF130400AD9D5A
+:100B40000000218504004185004800440800219CE4
+:100B5000D8FF219C004801D4045001D4086001D47E
+:100B60000C7001D4108001D4149001D418A001D4C9
+:100B70001CB001D40200A0185C67A5A80000209D4D
+:100B80000028C4E0000084A90000A6840200C01868
+:100B9000F85BC6A80030E5E00400C69C004807D416
+:100BA000003005E10000C3840200A09C002826E478
+:100BB000030000100000C3A90100209D004808D4D4
+:100BC0000000C09C5800AE84003005E4F300000C27
+:100BD000000000152C00AE84003005E40600001073
+:100BE000000000156400AE84003005E4DD00000C58
+:100BF000000000150800A01868DCA5A800288CE0FB
+:100C0000000064840000A09C002823E4B800000CCD
+:100C10000000001558006E84002823E40A0000102C
+:100C20000000409D2C006E84002803E406000010A4
+:100C30000000001564006E84002823E4A800000C66
+:100C400000006EA8C802000400006CA800502BE44D
+:100C5000FDFFFF1300008EA894006E840800A0180A
+:100C60001CC5A5A80800E018EC7CE7A800284CE10A
+:100C7000020063B80000CA84003863E00200C6B80E
+:100C80000800E01828C4E7A800186CE00038C6E0A7
+:100C90000000ACA80100E09C0030CCE0003803D498
+:100CA000CC0000040000668400008E840000609C7C
+:100CB000001804E4850000100000809C00006A8495
+:100CC0000800C01828C4C6A80800A01834C5A5A8E4
+:100CD000020063B800288CE0003063E000186CE08C
+:100CE00000006384001804D40800A018E87BA5A8BD
+:100CF00000006A8400288CE20200C09C0100A39CD2
+:100D00000000948400280AD4F4036484003003E4CF
+:100D10002B000010000000150800E01818C5E7A817
+:100D200000380CE2000070840100639C001805E4A8
+:100D30002300000C000000150000C6AA0000409E21
+:100D40002C00CE842400619C2000819C009026E42D
+:100D5000130000100000ACA83D02000400000015C4
+:100D60002000818400006A84FFFF639C001824E453
+:100D70000B0000100200A4B80800801828C484A842
+:100D8000002065E000186CE0000083840000A4846B
+:100D900000B045E50A00000C00000015A4020004A4
+:100DA00000006CA80000708400008A840100639C2D
+:100DB000001804E4E3FFFF130000001594008E8484
+:100DC0000000609C820900040000ACA82C006E8426
+:100DD0000000809C002003E41F00001000000015AC
+:100DE00028006E84002023E41B0000100000C09C3B
+:100DF0000800A01820C5A5A800286CE000006384A6
+:100E0000001886E51400000C0000E3A80800801814
+:100E100078C484A80800601814E263A80020ACE03D
+:100E200000180CE1000065840100C69C100083845A
+:100E300020006E84001824E4040000100400A59C27
+:100E40000100609C001808D4003886E5F6FFFF1307
+:100E50000000001592F9FF0700006CA8D7F9FF0702
+:100E600000006CA8000074840200809CF403A3843A
+:100E7000002025E40D0000105800809C94006E8432
+:100E8000062363E00800801850D184A8002063E0A6
+:100E900000186CE00000809C0000A384002005E4A2
+:100EA0000600000C00000015C4FEFF0700006CA83F
+:100EB0003E000000000000155D02000400006CA868
+:100EC000FAFFFF03000000150800E01834C5E7A88A
+:100ED00000386CE085FFFF03002003D486FAFF078B
+:100EE00000008CA858FFFF030000409D0800C018B8
+:100EF00034C5C6A800008EA800304CE10000ACA8A4
+:100F00003400000400006A8465F9FF0700006CA843
+:100F1000AAF9FF0700006CA8080060181CC563A8A8
+:100F20000800E01818C5E7A80018ACE000388CE00D
+:100F3000000064840000809C0100639C00200AD4AF
+:100F400000008584001824E418000010000000153B
+:100F50003702000400006CA8140000000000001517
+:100F60000800E01838EDE7A8C5FDFF0700384CE1A0
+:100F700000008A840100609C001824E41EFFFF1317
+:100F800000006EA85CFAFF0700008CA80000609CBF
+:100F900019FFFF0300180AD4CFF9FF07000000155E
+:100FA00015FFFF03000000150000218504004185A6
+:100FB000080081850C00C18510000186140041865F
+:100FC000180081861C00C186004800442800219C2E
+:100FD000F4FF219C004801D4045001D4086001D4DE
+:100FE000000084A9000043A90000E09C00382CE424
+:100FF000030000100000809C0100809C00382AE45F
+:10100000030000100000609C0100609C041864E074
+:10101000003803E4080000100100C09C080080189C
+:1010200014E284A8002065E00100A09CA00000005C
+:10103000002803D400008C84003004E46F0000100A
+:10104000003084E4500000100300609C0200609CAB
+:10105000001804E41C000010FFFF809C44006A8418
+:101060000000809C002003E4040000100000001534
+:101070009400AC84942803D448006A84002003E4DC
+:1010800004000010000000159400AC84942803D4E0
+:101090004C006A84002003E40400001000000015E6
+:1010A00094008C84942003D41400AC8410280AD4B7
+:1010B00024006C8414180AD430008C857C00000055
+:1010C00020600AD400006A84020063A834300AD485
+:1010D00000180AD44C600AD4A8006C843C200AD4BE
+:1010E00038180AD42C006C84003803E41100001076
+:1010F0000000001504006A840C008A84020063A8C2
+:10110000020084A804180AD40C200AD428006C8495
+:10111000003803E4070000100000001508006A848E
+:10112000020063A808180AD41C006C841C180AD496
+:1011300000008A840300609C001824E40C00000C6A
+:101140000100809C0400AC8424280AD458006C84DC
+:10115000002023E4040000100000609CC0FFFF0397
+:1011600040200AD4BEFFFF0340180AD43C200AD412
+:10117000000085A84606000400006AA8B9FFFF0326
+:1011800044006A840000809C00180AD434200AD4E9
+:1011900044600AD4A8006C8438180AD4AC008C844B
+:1011A0003C200AD458006C8440180AD42C006C846B
+:1011B000003803E40D000010000085A80300809CA7
+:1011C00004200AD40C200AD428006C84003803E4DC
+:1011D000050000100000001508200AD41C006C84D3
+:1011E0001C180AD4000085A8CC05000400006AA8D9
+:1011F0009CFFFF0344006A8400006A84010063A826
+:1012000034300AD400180AD448600AD4A8008C8468
+:10121000FFFF609C38200AD43C180AD42C006C8450
+:10122000003803E4110000100000001504006A8477
+:101230000C008A84010063A8010084A804180AD461
+:101240000C200AD428006C84003803E40700001046
+:101250000000001508006A84010063A808180AD479
+:101260001C008C841C200AD400008A840300609C2B
+:10127000001824E40C00000C0200609C04008C8424
+:1012800024200AD458006C840100809C002023E4B0
+:10129000B3FFFF0F000000150000A09C70FFFF03CC
+:1012A00040280AD4B3FFFF033C180AD4000021856C
+:1012B0000400418508008185004800440C00219C01
+:1012C0000000A3A80000E09C04006384003803E44D
+:1012D0002600000C0100609D0000C5840300609C96
+:1012E000001826E407000010010066A4440065848D
+:1012F0002C008384003804E41C00000C010066A468
+:101300000000809C002003E40C000010020066A492
+:1013100048006584002003E406000010000000156A
+:101320002C006384002003E40F00000C0000001573
+:10133000020066A40000809C002003E40B00001063
+:101340000000609D4C006584002003E4070000104D
+:10135000000000152C006384002003E4030000104B
+:10136000000000150100609D0048004400000015C9
+:101370000000A3840000E3A80300609C001825E49B
+:101380000D000010010065A4440087840000C09C8B
+:101390002C006484003003E408000010010065A400
+:1013A00028006484003023E42500000C0100609DC7
+:1013B000010065A40000C09C003003E40F00001091
+:1013C000020065A448008784003004E40B0000108C
+:1013D000000000152C006484003003E407000010B6
+:1013E000020065A428006484003023E41400000C8B
+:1013F0000100609D020065A40000A09C002803E499
+:101400000F0000100000609D4C008784002804E459
+:101410000B000010000000152C006484002803E479
+:10142000070000100000001528006484002823E451
+:1014300003000010000000150100609D00480044FA
+:10144000000000150000A3840000E3A80300609CD6
+:10145000001825E40D000010010065A444008784F5
+:101460000000C09C2C006484003003E408000010DD
+:10147000010065A428006484003003E42500000C0A
+:101480000100609D010065A40000C09C003003E4E1
+:101490000F000010020065A448008784003004E4B7
+:1014A0000B000010000000152C006484003003E4E1
+:1014B00007000010020065A428006484003003E4E3
+:1014C0001400000C0100609D020065A40000A09CB7
+:1014D000002803E40F0000100000609D4C0087848A
+:1014E000002804E40B000010000000152C006484A8
+:1014F000002803E4070000100000001528006484A1
+:10150000002803E403000010000000150100609DA6
+:101510000048004400000015FCFF219C004801D455
+:101520000000E4A8020003B90800801828C484A8B9
+:10153000000023A90100C09C002068E0001867E0BB
+:10154000000083840000A484003005E43100001012
+:10155000003045E50F00000C0000609C0200609C1C
+:10156000001805E4290000100000609C0300609C46
+:10157000001805E40700000C0000609C0000A09C1F
+:10158000442804D4482804D44C2804D40000609C87
+:101590000800A0181CC5A5A80C1804D4001804D471
+:1015A000081804D4041804D40028C7E008008018E0
+:1015B00028C484A80000A9A8002068E00000868450
+:1015C000001867E0FFFF849C002089E51400000CF0
+:1015D00000000385020069B80800201928C429A961
+:1015E000003863E0004863E0040023850100A59C07
+:1015F000004803D4002085E5FCFFFF130400639C32
+:101600000800000000006684E1FFFF034C1804D4CA
+:101610000000A09CDEFFFF03482804D4000066847D
+:101620000800A01824C4A5A8020083B8002884E0FC
+:10163000FFFF639C002087E0001806D4004004D41C
+:1016400000002185004800440400219CFCFF219CEF
+:10165000004801D4000063A9000005A90800601833
+:101660001CC563A8000024A90018A5E0000085841B
+:101670000000609C001844E508000010FFFF609C1B
+:101680000800801814E284A80100A09C002068E0F3
+:1016900032000000002803D4FF7F8018FFFF84A8D9
+:1016A000001809D40000E09C00200BD40000A585A0
+:1016B000006887E52900000C0000E3A90000609E97
+:1016C0000000209E0200C7B80800A01828C4A5A8E2
+:1016D00000006984007803E41E000010002886E002
+:1016E000002068E0000083844000A484009805E4A2
+:1016F0001A00000C000000150800801828C484A8F7
+:10170000002066E0001868E000008B84000063841D
+:101710002400A3840028A4E50800001000000015A0
+:1017200020006384008823E40400001000000015FA
+:1017300000280BD4003809D40100E79C006887E535
+:10174000E2FFFF130200C7B804000000000000150C
+:10175000EAFFFF030200C7B80000218500480044EB
+:101760000400219CE8FF219C004801D4045001D4CE
+:10177000086001D40C7001D4108001D4149001D4FD
+:101780000000C3A90000809D080060181CC563A864
+:1017900000180EE20000708400188CE51C00000C9C
+:1017A0000000609D0800601828C463A80000409EE7
+:1017B00000184EE10000CA8400008EA82000A68414
+:1017C000000066A8009005E40900000C04004A9D92
+:1017D0000000708401008C9D00188CE5F6FFFF135B
+:1017E0000000609D0A00000000000015B5FEFF0724
+:1017F0000000001500902BE4F6FFFF1300006CA81A
+:1018000046FFFF0700008EA80100609D00002185B3
+:1018100004004185080081850C00C1851000018607
+:1018200014004186004800441800219CE4FF219CDC
+:10183000004801D4045001D4086001D40C7001D4D4
+:10184000108001D4000003AA0000409D0800601829
+:101850001CC563A8001890E100006C84005043E5AB
+:10186000070000100100A09C0800801814E284A862
+:10187000002070E09F010000002803D41800619C44
+:101880001400819C72FFFF070000B0A8140081843F
+:10189000FFFF609C001824E422000010020064B8DE
+:1018A00000006C8400188AE50D00000C0000C09D4B
+:1018B0000800E01828C4E7A8003850E100006A8456
+:1018C000000090A86CEEFF070100CE9D00006C8424
+:1018D00000188EE5FAFFFF1304004A9DA2FFFF07E0
+:1018E000000070A80000609C00182BE4FCFFFF13B0
+:1018F0000100A09C0800001914E208A90800601962
+:1019000028C56BA9004070E0005890E00080E01806
+:101910000000E7A8002803D476010000003804D4B2
+:101920000800001928C408A9004063E0001870E00E
+:101930000000A384000085840200609C001844E538
+:101940006C01000C0100609C440085849400848537
+:101950000000B0A86406000400008CA85800809C19
+:10196000140021850623CCE00800601928C46BA967
+:10197000020069B8005863E0001810E1080060191F
+:1019800020D16BA9000088840058A6E04400E484BC
+:101990000028B0E004006B9D080080181CD184A8CA
+:1019A000002066E000008784001870E0002003D467
+:1019B00004006784005886E0001805D4002090E0F9
+:1019C000080067850800A01828D1A5A8005804D4ED
+:1019D000002866E00C006785001870E00400A59CF4
+:1019E000005803D4002886E010006785002090E0AE
+:1019F0000400A59C005804D4002866E034006785E4
+:101A0000001870E00400A59C005803D4002886E06C
+:101A100038006785002090E0080060183CD163A87A
+:101A2000005804D40018A6E0700067850028B0E0D4
+:101A30000800801838D184A8005805D4002066E03A
+:101A40006C00A784001870E000500BE41A0000102E
+:101A5000002803D40800601940D16BA90800801841
+:101A600044D184A8005866E00020A6E07400678591
+:101A7000001870E00028B0E0005803D478006785B3
+:101A80000800601848D163A8005805D4001886E003
+:101A90007C006785002090E00800A0184CD1A5A824
+:101AA000005804D4002866E08000E784001870E045
+:101AB000003803D40000688414008384005004E4D8
+:101AC000080100100100A09C08008018747D84A803
+:101AD000002070E0002803D400006384005003E479
+:101AE000FA0000100100A09C0800001954D108A9B8
+:101AF0000000609D004066E0001870E0005803D4CC
+:101B00000800E0189CE1E7A80000A09C003870E005
+:101B100000006384002823E47D0000100100009D84
+:101B20005800809C020069B806238CE00800001968
+:101B300028C408A90800601958D16BA9004063E0C7
+:101B40000800E01860D1E7A8001870E0080000194C
+:101B50005CD108A90000C3840058A4E0003864E008
+:101B600030006685001870E0004084E0005803D41F
+:101B7000002090E0280066840028B0E02C00C68495
+:101B8000001805D4003004D45800809C020069B8C5
+:101B90000623ECE00800A01864D1A5A808000019ED
+:101BA00068D108A90800801828C484A8002063E030
+:101BB000001870E0002887E00000C384002090E057
+:101BC0000040A7E0340066850028B0E0005804D447
+:101BD00038000685080080186CD184A8004005D420
+:101BE000002067E03C006685001870E0005803D4D0
+:101BF000000086840300609C001824E43D0000106F
+:101C0000000000150800801870D184A8002067E04B
+:101C100044008684001870E048008484002003D4C7
+:101C2000020069B80800601928C46BA90200ACB8AA
+:101C300008008018EC7B84A8005863E008000019B5
+:101C400028C508A90020A5E0001870E00040F0E0D9
+:101C5000000083840100009D0028B0E0204004D4EF
+:101C600000006584050063A40000C784001805D443
+:101C700018008184002086E50700001018006184A8
+:101C80000800601914E26BA9005870E0004003D40A
+:101C9000180061840800801828C484A8001807D49C
+:101CA00014006184020063B8002063E0001870E053
+:101CB0000000A384000085840300609C001824E4D5
+:101CC0008C000010000065A87EFDFF07000090A8B2
+:101CD0000000609C00182BE4860000101400618452
+:101CE0000EFEFF07000090A8820000000000001513
+:101CF0000800A01870D1A5A8002867E00000E09CAB
+:101D0000001870E0C7FFFF03003803D4004023E44D
+:101D10009FFFFF135800809C0800801898E184A85A
+:101D2000002070E000008384002824E448000010B4
+:101D30005800609C0800A0189C7DA5A8180061842C
+:101D4000002850E100008A840018A4E52300001058
+:101D50005800609C020089B8061B6CE008006019FE
+:101D600028C46BA9080000192CE208A9005884E0D7
+:101D70000040F0E0002090E00800001960D108A9C0
+:101D80000000A484080060195CD16BA908008018C9
+:101D900058D184A80020C3E0004083E00030D0E0A8
+:101DA000005863E030000585001870E0002090E0E6
+:101DB0002C006585005803D4004004D428006584B5
+:101DC000001806D42800A584002807D418006185CF
+:101DD0006EFFFF0300580AD4080080182CE284A884
+:101DE0000800601960D16BA90020F0E00800A0187D
+:101DF00030E2A5A85800809C0028D0E006238CE0A3
+:101E0000005864E0080060195CD16BA9001870E00C
+:101E10000058A4E0004003D40028B0E00000609C1B
+:101E2000001805D40800A01858D1A5A800006784A0
+:101E3000002884E00000A684002090E0002863E0F1
+:101E4000001807D4E2FFFF03001804D4020089B889
+:101E5000061B6CE00800601928C46BA90800A018D4
+:101E60009C7DA5A8005884E0080000192CE208A970
+:101E7000002090E0002850E10040F0E00000A48441
+:101E80000800601960D16BA90800001958D108A991
+:101E9000005883E00040C3E0300065850400089DE1
+:101EA000002090E0004063E0005804D4280005853D
+:101EB000001870E00030D0E02C008584004006D48B
+:101EC000C1FFFF03002003D40800801854D184A868
+:101ED000002066E0001870E00AFFFF03002803D42A
+:101EE0000800E018747DE7A8FCFEFF03003870E0EE
+:101EF0000000218504004185080081850C00C18512
+:101F000010000186004800441C00219CECFF219C2D
+:101F1000004801D4045001D4086001D40C7001D4ED
+:101F2000108001D4000083A90000C09D0800601843
+:101F30001CC563A800180CE20000708400188EE530
+:101F40000D00000C000000150800801828C484A8AB
+:101F500000204CE100006A8400008CA8C6ECFF075A
+:101F60000100CE9D0000708400188EE5FAFFFF137B
+:101F700004004A9DFCFDFF0700006CA80000809C47
+:101F800000202BE4FCFFFF1300000015000070840C
+:101F9000002023E40900000C000000150000409D13
+:101FA00023FEFF0700006CA800007084005023E4AB
+:101FB000FCFFFF13000000150800801828C584A846
+:101FC00000206CE000808018000084A8002003D46A
+:101FD0000000218504004185080081850C00C18531
+:101FE00010000186004800441400219CE4FF219C5D
+:101FF000004801D4045001D4086001D40C7001D40D
+:10200000108001D4149001D418A001D4000083A939
+:10201000000063840000C09D007023E43001000CC8
+:10202000000044A90800601800D063A80100409E89
+:10203000001884E20000948400006484030063A418
+:10204000001804D40000AC84009025E405000010C2
+:10205000049063E0486004D4001804D40000AC8409
+:102060000200609C001825E4060000100000001526
+:1020700000006484020063A84C6004D4001804D4F7
+:10208000000084840300609C001824E41A020010FD
+:102090000000AAA894008C84CD0400040000609C79
+:1020A000000074847A02000400008AA894000C8660
+:1020B000000072A80000AAA88B040004000090A8E9
+:1020C0000800A018747DA5A8020090B80800C018E8
+:1020D000EC7BC6A800286AE0003084E00000A384FE
+:1020E00000208AE000006484050063A4007005E419
+:1020F000F3000010001804D45800609C0800E01899
+:1021000054D1E7A8061B70E00000809C003863E013
+:1021100000186AE0002003D45800609C0800801872
+:1021200020D184A8061B10E10000F4840000209D4B
+:102130004400C784002068E00400849C00186AE022
+:102140000020A8E0040086840028AAE0002003D430
+:102150000800601828D163A8001888E00800668489
+:1021600000208AE0001805D40800A0182CD1A5A8EA
+:10217000002868E00C00A68400186AE0002804D457
+:102180000800A01830D1A5A8002888E01000A68477
+:1021900000208AE0002803D40800A01834D1A5A8A4
+:1021A000002868E03400A68400186AE0002804D4FF
+:1021B0003800C6840800A0183CD1A5A8003003D47C
+:1021C000002888E00800C01838D1C6A87000AC8488
+:1021D00000208AE0003068E0002804D400186AE09B
+:1021E0006C00CC84004805E419000010003003D4D2
+:1021F0000800801840D184A80800C01844D1C6A89F
+:10220000002068E00030A8E074008C8400186AE0C8
+:102210000028AAE0002003D40400C69C78006C8447
+:10222000003088E0001805D400208AE07C00CC84CF
+:102230000800A0184CD1A5A8003004D4002868E0FC
+:1022400080008C8400186AE0002003D40800A018E5
+:102250009CE1A5A800286AE000006384004823E40C
+:102260003D0000100100A09C0800C01858D1C6A86D
+:102270000800A01860D1A5A8003068E0002888E018
+:102280000400C69C00208AE00030A8E000186AE044
+:102290003000C7840028AAE0003004D428008784D6
+:1022A0002C00E784002003D4003805D45800609C3B
+:1022B0000800A01864D1A5A8061B70E00100C09C0E
+:1022C0000800E01868D1E7A8002883E000208AE031
+:1022D0000038A3E0003004D40028AAE008008018E9
+:1022E0006CD184A8A800EC84002063E000188AE088
+:1022F000003805D4FFFF609C001804D400006C84F3
+:10230000003023E4120000100200A09C002804D436
+:102310005800609C0800E01870D1E7A8061B70E028
+:1023200048008C850000C09C00009484443004D494
+:10233000483004D44C3004D4003863E000186AE01C
+:10234000006003D46C010000003004D4F1FFFF03EF
+:10235000003004D4002823E4D6FFFF135800609C0B
+:102360000800C01898E1C6A800306AE00000838425
+:10237000004824E43F000010000000150800601829
+:102380009C7D63A804008C8400182AE10000698405
+:102390000020A3E51C000010000000150800C01874
+:1023A00060D1C6A80800801858D184A8003068E021
+:1023B0000020A8E00800C0185CD1C6A800186AE098
+:1023C000003088E00028AAE03000C78400208AE0BE
+:1023D000003003D42C006784001804D428008784BC
+:1023E000002005D40800A0182CE2A5A800286AE067
+:1023F0002800E784003803D40400EC84ACFFFF031A
+:10240000003809D40800C01860D1C6A80800E01838
+:102410005CD1E7A8003068E0003888E000186AE086
+:1024200000208AE0002803D40000609C0800A01867
+:1024300030E2A5A8001804D40028CAE008008018DB
+:102440002CE284A80800A01858D1A5A80020EAE032
+:10245000002888E00000678400208AE00000A6844D
+:10246000002863E0001807D4E4FFFF03001804D439
+:102470000800C01858D1C6A80800801860D184A8E8
+:102480000030A8E0002068E00400C69C00186AE064
+:10249000003088E00028AAE03000C78400208AE0ED
+:1024A000003003D42C0067840800C0189C7DC6A8A7
+:1024B000001804D4CAFFFF0300302AE15800609CD2
+:1024C0000800A01854D1A5A8061B70E0002863E0FE
+:1024D00000186AE011FFFF03009003D494008C847D
+:1024E0000000609CBA0300040000AAA894000C86B7
+:1024F0000100609C0000AAA87B030004000090A8D3
+:102500000800A018747DA5A8020090B80800C018A3
+:10251000EC7BC6A800286AE0003084E00000A384B9
+:1025200000208AE000006484050063A4007005E4D4
+:10253000E8000010001804D45800609C0800E0185F
+:1025400054D1E7A8061B70E00000809C003863E0CF
+:1025500000186AE0002003D45800609C0800E018CE
+:1025600020D1E7A8061B10E10000C09C003888E0DD
+:102570000800601824D163A80400EC8400208AE0DD
+:102580000018A8E0003804D40028AAE00800EC8471
+:102590000800801828D184A8003805D4002068E0FD
+:1025A0000C00EC8400186AE00800A0182CD1A5A843
+:1025B000003803D4002888E01000EC8400208AE072
+:1025C0000400A59C003804D4002868E03400EC84A2
+:1025D00000186AE00400A59C003803D4002888E0B5
+:1025E0003800EC8400208AE0080060183CD163A821
+:1025F000003804D40018A8E07000EC840028AAE099
+:102600000800801838D184A8003805D4002068E07C
+:102610006C00AC8400186AE0003007E41A00001077
+:10262000002803D40800E01840D1E7A8080080186B
+:1026300044D184A8003868E00020A8E07400EC844D
+:1026400000186AE00028AAE0003803D47800EC847F
+:102650000800601848D163A8003805D4001888E045
+:102660007C00EC8400208AE00800A0184CD1A5A8CA
+:10267000003804D4002868E080008C8400186AE0E8
+:10268000002003D40800A0189CE1A5A800286AE057
+:1026900000006384003023E42D0000100100A09CA2
+:1026A0000800E01860D1E7A80800C01858D1C6A8F3
+:1026B000003888E0003068E0A400EC8400208AE064
+:1026C0000400C69C003804D40030A8E0A0008C842C
+:1026D0000028AAE000186AE0002005D49C00AC8421
+:1026E000002803D45800609C0800A01864D1A5A855
+:1026F000061B70E00800E01868D1E7A8002883E016
+:102700000038C3E000208AE00000A09C0030CAE04E
+:10271000002804D40400E79CA8008C840038A3E0BF
+:10272000002006D40028AAE0AC00EC840800C01801
+:1027300070D1C6A8003805D4003063E048008C850D
+:1027400000186AE06C000000006003D4002823E455
+:10275000E6FFFF135800609C0800E01898E1E7A826
+:1027600000386AE000008384003024E43F00001059
+:1027700000000015080060189C7D63A804008C848C
+:1027800000182AE1000069840020A3E51C00001065
+:10279000000000150800C01860D1C6A80800801805
+:1027A00058D184A8003068E00020A8E00800E018B4
+:1027B0005CD1E7A8A400CC8400186AE0003888E067
+:1027C000003003D4A000EC8400208AE00028AAE0B6
+:1027D0009C006C84003804D4001805D408008018CC
+:1027E0002CE284A89C00AC8400206AE0002803D47A
+:1027F00004006C84BCFFFF03001809D40800C01853
+:1028000060D1C6A80800E0185CD1E7A8003068E0F5
+:10281000003888E000186AE000208AE0002803D42D
+:102820000000609C0800A01830E2A5A8001804D49D
+:102830000028CAE0080080182CE284A80800A0182C
+:1028400058D1A5A80020EAE0002888E000006784AD
+:1028500000208AE00000A684002863E0001807D466
+:10286000E4FFFF03001804D40800E01860D1E7A8D3
+:102870000800C01858D1C6A8003868E00030A8E0A9
+:10288000A400EC8400186AE00400C69C003803D45D
+:10289000003088E0A0006C8400208AE00028AAE0D4
+:1028A000001804D40800C0189C7DC6A89C008C8425
+:1028B00000302AE1002005D40800A0182CE2A5A8C9
+:1028C0009C00EC8400286AE0CAFFFF03003803D4B0
+:1028D0005800609C0800A01854D1A5A8061B70E001
+:1028E0000100C09C002863E000186AE01BFFFF03A2
+:1028F000003003D400002185040041850800818553
+:102900000C00C185100001861400418618008186E4
+:10291000004800441C00219CF0FF219C044801D485
+:10292000085001D40C6001D444002385000084A920
+:10293000000043A9040089840100609C24200AD47B
+:1029400040000985940089843400A9843800C98432
+:102950003C00E98405EAFF07006001D444002A85B1
+:102960000200609C40000985940089843400A98499
+:102970003800C9843C00E98448580AD4FBE9FF07C1
+:10298000006001D444006A8448008A840C00A38457
+:102990000800C384042804D4083004D4A000A3840D
+:1029A0002C280AD49C00C384A400A38428300AD411
+:1029B00030280AD44C580AD40800C38408300BD4F9
+:1029C000100023850C00C3841C00A3842C00E38426
+:1029D000280003850C300BD41C280BD410480BD4D2
+:1029E0002C380BD428400BD40C3004D41C2804D42D
+:1029F000104804D42C3804D4284004D404480BD400
+:102A00000100C09C1C280AD40100A09C44280BD4BF
+:102A1000B02003D44800A384443004D444006A8422
+:102A20004C00CA84B43003D448280BD448006A84CC
+:102A30004C00CA84482804D4B43003D448006A84C3
+:102A400044008A84B82003D44C008A844800AA84B5
+:102A5000B02804D44C006A844400CA84B83003D43B
+:102A600044008A846800A4844C006A8448008A84F4
+:102A7000682803D4682804D404002185080041850F
+:102A80000C008185004800441000219CF0FF219C2F
+:102A9000044801D4085001D40C6001D448002385B7
+:102AA000000044A9000083A9400009850000609C43
+:102AB0003800C984010008B9940089840100C6B8AF
+:102AC0003400A9843C00E984A8E9FF07005001D440
+:102AD00048008C846C006484000024A94C00CC84E1
+:102AE0006C180BD40400A484040066840028A3E5B9
+:102AF0000300001044580CD4000065A804180BD43F
+:102B000008180BD424180CD49C00A6849C00E484E0
+:102B1000003805E44D0000100000609C001805E43A
+:102B20004400001000000015A4000485A000848467
+:102B300028380CD430400CD42C200CD404008684CB
+:102B40000000E09C102009D444006C8404008984B7
+:102B50000000A3A8082003D40C2003D40400068599
+:102B6000082009D42C006984104005D4082006D41C
+:102B7000003803E4070000100C2006D42C00668403
+:102B8000003803E403000010000000150100E09C81
+:102B9000280069840000809C002003E407000010E6
+:102BA0002C3805D428006684002003E404000010BB
+:102BB0000000C09C0100809C0000C09C003004E428
+:102BC00004000010282005D41C006C841C1805D4B7
+:102BD00048008C84B02005D444006C844C000C85E3
+:102BE000B44003D444008C840000609C4800AC8452
+:102BF000441804D47000058568006584704004D4CE
+:102C0000003008E41F000010681804D47C0005851B
+:102C1000800065847C4004D4801804D47400058549
+:102C200078006584744004D416000000781804D439
+:102C3000A0006684A400868428280CD42C180CD408
+:102C4000BFFFFF0330200CD4A0000685A0006484E1
+:102C50000018A8E40600001000000015A4008484F9
+:102C60002C180CD4F7FFFF0328380CD42C400CD4BC
+:102C700028280CD4A4000685B1FFFF0330400CD4F3
+:102C80004C006C84B82003D4B82005D404002185FE
+:102C9000080041850C008185004800441000219CFB
+:102CA000B4FF219C044801D4085001D40C6001D425
+:102CB000107001D4148001D4189001D41CA001D448
+:102CC00020B001D424C001D428D001D42CE001D4F8
+:102CD00030F001D4000004AA0000C3A95800838486
+:102CE0000800C01874E1C6A8FF00A5A4020060187F
+:102CF000D05B63A80030D0E00018CEE33C3001D4B4
+:102D00000100849C0000DE840A3364E0482801D47A
+:102D10007C00EE848000AE84443801D4402801D485
+:102D20000000E09C3C00A1847C380ED480380ED496
+:102D3000063363E068008E87021844E200903CE4AA
+:102D40008300000C000085850800C01868DCC6A858
+:102D50000800E018E87BE7A80030D0E00038F0E099
+:102D6000383001D4343801D4380061840200ACB862
+:102D70000100809C0800C018EC7BC6A8002003D48A
+:102D80000030A5E0008001D40028B0E00100E09C04
+:102D90000000609C003805D400008CA81C00AE84A4
+:102DA0002000CE842400EE84F0E8FF0728000E8582
+:102DB0000000809C0100609C3400A18458200BD44A
+:102DC00064200BD444180BD430180BD42C180BD41B
+:102DD00014900BD420900BD4000085840000609CDC
+:102DE00068900ED4F403A484001805E49000000C4D
+:102DF00000004BA95C00CE845800A09C00006AA88B
+:102E0000062BACE00C300AD46000EE8410380AD4F3
+:102E100064008E840800E01850D1E7A808200AD486
+:102E20006400CE84000090A80038A5E004300AD4E5
+:102E30000028B0E00000C09C46F7FF07003005D432
+:102E40000000BE840100D29C000070A8092B86E01F
+:102E500058900ED4062B84E088DFFF07022046E25C
+:102E60000000609C95010004000090A8FFFF609C9A
+:102E700000182BE46C00000C00008BA900180BE478
+:102E8000300000100000809E0800E018ACE2E7A8C7
+:102E9000003850E100006A84001894E42600000C19
+:102EA000480081840040E0186020E7A80100C09C31
+:102EB000060064B80038A3E0085886E00000658486
+:102EC000032063E000A003E41A00000C00008CA8BB
+:102ED0000000C5AA000046AB0000009F0000609CF7
+:102EE0000000B0A83A0100040100949E00008CA8E4
+:102EF0000000609CFC0000040000B0A80000609C82
+:102F00006E010004000090A808589AE000006A844E
+:102F1000001894E40800000C00008BA900007684DF
+:102F2000032063E000C003E4EDFFFF1300008CA862
+:102F300000006A84001894E43900000C00000015B9
+:102F400000903CE48AFFFF13380061840800601899
+:102F5000ECE663A83C0081840018F0E00000009DCE
+:102F6000000067845F0063A4004003E421000010B8
+:102F7000006004D40800A018B4E4A5A80800C01894
+:102F8000FCE6C6A8002890E002006CB80030B0E073
+:102F90005C00C484002063E0003005D40800A01861
+:102FA000F8E6A5A8600063840028D0E0001806D4E5
+:102FB0000020ACE00000C09C283105D8483105D87D
+:102FC00000006784400063A4004003E40A0000108E
+:102FD000440061840800E018FCE4E7A8003870E0D1
+:102FE00000008384004004E40900000C0000001588
+:102FF000440061840100609D4000818468E00ED43B
+:103000007C180ED40F00000080200ED490C5FF075E
+:10301000000070A8F8FFFF0344006184090000006D
+:103020000200609D070000000000609D00006EA887
+:1030300046C1FF07000090A870FFFF035C00CE842C
+:1030400004002185080041850C0081851000C185A0
+:1030500014000186180041861C0081862000C1866C
+:1030600024000187280041872C0081873000C18718
+:10307000004800444C00219CD4FF219C004801D40E
+:10308000045001D4086001D40C7001D4108001D424
+:10309000149001D418A001D41CB001D420C001D4D4
+:1030A00024D001D428E001D4000043AB000084AB5D
+:1030B000000045AA0100609C0018A4E43300001041
+:1030C0000000C6AA000003AAFFFF849C0300609CC6
+:1030D0000A1B84E0002090E40500000C010070B899
+:1030E000008003E2FCFFFF030100109E069310E244
+:1030F00006939CE300E090E41D00000C000090AA01
+:103100000000009F0280D4E100709AE100804CE151
+:1031100000006CA800B0004800008AA800C04BE581
+:103120000F00000C000092A80000A09C00006C9012
+:10313000FFFF849C0000CA8C00300CD801008C9DDD
+:1031400000180AD8002824E4F9FFFF1301004A9D63
+:1031500000806EE4EDFFFF130280CEE1009094E268
+:1031600000E094E4E9FFFF130280D4E1029070E0F4
+:103170000300809C0000A09C0A2303E2002830E4A6
+:10318000DDFFFF13000000150000218504004185CC
+:10319000080081850C00C18510000186140041865D
+:1031A000180081861C00C186200001872400418709
+:1031B00028008187004800442C00219CF0FF219CBE
+:1031C000004801D4045001D4086001D40C7001D42B
+:1031D0000000C3A90000E09C0800601814D063A898
+:1031E0001F00C09C0100009D00188EE00000AEA8EA
+:1031F0000000209D0000409DF04FE4D7F84FE4D739
+:10320000004804D4080020191CD029A9004865E012
+:10321000FFFF209D01004A9D004803D40030AAE52D
+:10322000FDFFFF130400639C0400849C0100E79CE5
+:103230000040A7E5EFFFFF138000A59C0800601881
+:10324000ACE263A80000409D00188EE100006C8491
+:1032500000188AE51400001000008AA800008C8481
+:103260000000E09C002087E51900000C0000209D74
+:103270000800A0186C7CA5A800286EE00100E79C5F
+:10328000804FE3D7804803D4004803D4002087E56B
+:10329000FBFFFF130400639C0D00000000000015FD
+:1032A00000008AA80000609C0000AEA80E00000488
+:1032B00001004A9D00006C8400188AE5F9FFFF13A5
+:1032C00000000015E7FFFF0300008C84000021854B
+:1032D00004004185080081850C00C1850048004438
+:1032E0001000219CFCFF219C004801D40000E4A8B0
+:1032F0000200A3B9080080187CE184A80000C3A8DC
+:10330000002025E10800601814D063A80000E09DAB
+:10331000007826E40D00001000188DE00800601809
+:1033200080E163A8001805E100006984001827E423
+:1033300007000010FFFF609C00006884007803E431
+:103340002000000C0000609DFFFF609C001807E457
+:103350001B000010002005E1080080180CD084A894
+:10336000050026B900206DE00100609D0000888402
+:103370000018A5E11F00609C001844E51000001033
+:103380000058C4E000006D84005883E0003008D489
+:10339000001869E00800C0181CD0C6A8020063B875
+:1033A000DFFF209D003063E0034884E0001865E003
+:1033B00000200DD403000000003803D40000609DFD
+:1033C00000002185004800440400219CFCFF219C52
+:1033D000004801D40000C5A8000024A90800A018D6
+:1033E0007CE1A5A80800601904D06BA90028E6E0DC
+:1033F0000800201A14D031AA0200A3B80500E3B9CE
+:103400000000009D005885E00088A5E00020A6E1AE
+:10341000004023E40D0000100028A6E0080060181A
+:1034200080E163A8001886E000006784001829E4A2
+:10343000060000100000001500006484004003E452
+:103440001B00000C0000609D000085840000609C53
+:103450000018A4E5160000100000609D00006D84B7
+:10346000FFFF049DDFFF209E0100839C00186FE09A
+:103470000388E4E0020063B8080080181CD084A828
+:10348000002063E0001866E000008384002029E447
+:103490000700001000000015004005D400380DD4CE
+:1034A000FFFFA09C0100609D002803D4000021853F
+:1034B000004800440400219C0500E3B80000A4A8D3
+:1034C0000800C01804D0C6A8020063B8003083E02A
+:1034D0001000C69C003063E00020C5E0001865E0E5
+:1034E000000083840000609C0018A4E50A0000101E
+:1034F000FFFF609D00006684080080181CD084A82F
+:10350000001867E0020063B8002063E0001865E07F
+:103510000000638500480044000000150500E3B882
+:103520000000A4A80800C01804D0C6A8020063B810
+:10353000003083E01000C69C003063E00020C5E04E
+:10354000001865E0000083840100609C0018A4E579
+:103550000D000010FFFF609D00006684DFFF809C6F
+:103560000100639C0800C0181CD0C6A8032063E0BB
+:10357000001867E0020063B8003063E0001865E0FF
+:10358000000063850048004400000015FCFF219CFA
+:10359000004801D4000003A9000024A900406018DD
+:1035A000140463A80000609D0000A384005805E493
+:1035B0003F00000C0000001500408018180484A88B
+:1035C0000000A4849F0065B800408018040484A80B
+:1035D0005D0063B80000E484001865E08300C3B8B0
+:1035E000030086B8023067E00048A3E43000000C16
+:1035F0000220A5E0004060180C0463A8FFBF20195A
+:10360000FFFF29A900008384034884E0002003D43D
+:10361000005825E4190000100800809C0100609CFF
+:103620000100609D0038A6E50B00000C001808D8CA
+:103630000040A0182003A5A800008584005868E079
+:103640000100C69C002003D80038A6E5FBFFFF134D
+:1036500001006B9D004060180C0463A80040A01896
+:103660000000A5A800008384042884E0002003D47F
+:103670000F000000000000150100609C022884E09B
+:1036800000402019000329A91F00A4A4000063A979
+:103690000200A5B8082083E00018C6E00048A5E0B5
+:1036A00000006584E0FFFF03042063E00000218543
+:1036B000004800440400219CD8FF219C004801D40C
+:1036C000045001D4086001D40C7001D4108001D4DE
+:1036D000149001D418A001D41CB001D420C001D48E
+:1036E00024D001D40800809E0000C3AA000084A951
+:1036F000000045AB000006AB0000C09D00208EE539
+:103700003700000C000074A90400401AE87552AAA2
+:103710000400001AD87510AA1000609C00182CE450
+:103720002D000010000000150000508D0000609C6E
+:1037300000180BE41200000C0000001502008AB80B
+:103740000000ABA80000609C00182BE403000010F0
+:1037500000B084E00000B4A8002804D4000085AACA
+:103760000100529E0100CE9D00608EE5EBFFFF132D
+:103770000100109E1A000000000000159A130004BA
+:10378000000078A8005874E100FFA09C00016B9D28
+:103790000000809C9F006BB8580063B800186BE075
+:1037A000032863E000202AE40300001002186BE104
+:1037B0000100809C0000609C00182BE404000010B5
+:1037C000031864E00100609C031864E0DCFFFF0361
+:1037D00000181AD4D6FFFF030000528D0000218587
+:1037E00004004185080081850C00C1851000018618
+:1037F00014004186180081861C00C18620000187C4
+:1038000024004187004800442800219CD0FF219CCF
+:10381000004801D4045001D4086001D40C7001D4D4
+:10382000108001D4149001D418A001D41CB001D48C
+:1038300020C001D424D001D428E001D42CF001D43C
+:103840000000C3A90300A01860E7A5A8080060183D
+:1038500014E263A80000C09C00188EE0000064849D
+:10386000003003E40300001000284EE1003004D4CF
+:103870000040A0182003A5A800408018040384A8D5
+:10388000000085850200E0185C67E7A80800601862
+:10389000F8E163A80000C48600388EE300184EE308
+:1038A0000000C4870200E018645CE7A800000487F9
+:1038B00000007C8400008486003863E00100809C66
+:1038C0000000E09C002003D400408018100384A86E
+:1038D00000381AD400006484003003E403000010B0
+:1038E0000100609C00181AD4000005864200609C0C
+:1038F00000180CE4030000100000A09C0100A09C34
+:103900004D00609C00180CE4030000100000809C37
+:103910000100809C032065E0003003E416000010E5
+:103920000800609C5800609C00180CE40300001024
+:103930000000A09C0100A09C6400609C00180CE4A6
+:10394000030000100000809C0100809C032065E0C3
+:10395000003003E4080000100800609C0800801894
+:1039600010E984A8A600A09C00206EE0002803D4E3
+:103970000800609C001850E5030000100000C09C87
+:103980000100C09CF2FF909C0500609C001844E47C
+:10399000030000100000A09C0100A09C042866E029
+:1039A0000000A09C002823E413000010E9FF709C95
+:1039B0000600809C0020A3E40F000010DFFF709C35
+:1039C000002043E4030000100000C09C0100C09CE4
+:1039D0003300609C0018B0E5030000100000809CDC
+:1039E0000100809C042066E0002823E40800000C0D
+:1039F0004200609C0800E01810E9E7A8A700809C3E
+:103A000000386EE0002003D44200609C00182CE4D3
+:103A1000030000100000A09C0100A09C4D00609CD1
+:103A200000182CE4030000100000809C0100809C22
+:103A3000042065E00000A09C002803E410000010B2
+:103A40000B00609C001830E4030000100000C09CD4
+:103A50000100C09C0100809C002034E403000010A1
+:103A60000000609C000064A8031866E0002803E4DE
+:103A700003000010000000150900009EA6120004BB
+:103A800000006EA81F00609C0018ABE5030000104A
+:103A90000100A09C00281AD400007A840000409EF7
+:103AA000009003E44201000C0100E09C00007C84D3
+:103AB0000200A0185C5CA5A820380AD4002883E086
+:103AC0000200E018485CE7A804600AD4E8930AD42E
+:103AD00018800AD41C580AD4EC930AD4003863E046
+:103AE000009004D4009003D408B00AD404008A845F
+:103AF0006400609C0CF00AD410C00AD4001824E4BE
+:103B0000E500000C14A00AD400006EA88212000484
+:103B10000C00809D0060ABE404000010F05B0AD450
+:103B20000100609C00181AD47B12000400006EA8EB
+:103B30000200609C0018ABE404000010F45B0AD49F
+:103B40000100809C00201AD4F4038A840000609C49
+:103B5000001824E4C800000C000000150100809D3E
+:103B6000006024E49B00000C00006EA86A120004B0
+:103B700000006EA81000609C0018ABE40400001068
+:103B80000C582AD40100E09C00381AD40040801957
+:103B900004038CA900006EA800008C840000009E25
+:103BA0005D12000410202AD414582AD45A1200049A
+:103BB00000006EA80000AC8418582AD41C282AD40F
+:103BC000008025E40400001020802AD40000EC844A
+:103BD00020382AD400006C8400008C8424182AD455
+:103BE000008004E46E00000C28202AD40000A09C71
+:103BF0000800E018ECE6E7A8F82B2AD400388EE09D
+:103C000000008C8500006484100063A4008003E43D
+:103C10005D0000103C602AD400800CE44B00000CD6
+:103C200040088A9D00009A840000609C001804E40B
+:103C3000440000100100809C00180AD40800A0185D
+:103C4000E87BA5A80000009E00288EE10000AC845F
+:103C5000008005E407000010000000151C008A84A5
+:103C60001C006584001824E42200000C000085A8D4
+:103C700000006A840000009E008003E41800000C2D
+:103C800000008AA80800A0184CE6A5A800007C84C3
+:103C900000288EE00200E018405CE7A80000A48441
+:103CA000003863E004008A84002003D40100809C73
+:103CB000002025E4BE0000100000001500006C8408
+:103CC000008023E4BA00001000006AA8B0020004DB
+:103CD00000008EA8B6000000000000151C006A84D9
+:103CE000A90600040000AEA8E7FFFF0300000015CE
+:103CF00000006AA89F0400040000AEA800802BE426
+:103D0000DCFFFF13000000150800E018A47DE7A801
+:103D100000386EE000008384008004E40500000C9D
+:103D2000000000150000609CD2FFFF0300180CD4B7
+:103D3000FADCFF0700006EA8FCFFFF030000609C98
+:103D4000BFFFFF0300200AD4B803809CFC632AD481
+:103D50000FFEFF0700006CA800802BE40500000C9C
+:103D6000F85B2AD40000609CAFFFFF033C182AD404
+:103D700000006CA89C00000400008EA8ABFFFF03AD
+:103D800000009A843C086A84008003E4A6FFFF13C5
+:103D900040086A9CF8FFFF0300000015DE110004D4
+:103DA00000006EA800006EA8DB1100042C582AD475
+:103DB00000006EA8D811000430582AD434582AD4F0
+:103DC000D511000400006EA889FFFF0338582AD4DB
+:103DD00000408018040384A80000848402120004B8
+:103DE000FC230AD400006EA8FF110004005C0AD472
+:103DF00000006EA8C8110004045C0AD4FF00609C97
+:103E00000018ABE404000010085C0AD4680000004D
+:103E100000601AD4000083AA0000009E0000409EAB
+:103E20000C048A9D08048A8400006EA80000C09CCF
+:103E3000002070E4030000100000A09C0100C09C62
+:103E400000A050E404000010032886E00100A09CBC
+:103E5000032886E0009024E445FFFF0F0100109E38
+:103E6000E11100040000001500580CD4EEFFFF0320
+:103E700004008C9DA811000400006EA80060ABE453
+:103E80003BFFFF13F85B0AD40100A09C38FFFF033F
+:103E900000281AD4A011000400006EA80300609C42
+:103EA00000182BE40A00001020580AD400007C847B
+:103EB000020080185C5C84A8002063E00040801849
+:103EC000040384A800008484002003D49211000419
+:103ED00000006EA800006EA88F110004E85B0AD4F1
+:103EE00000408018040384A800007C840200A0180D
+:103EF000485CA5A80000E484002863E000008484F6
+:103F0000EC5B0AD424200AD4009004E4FFFEFF13E3
+:103F1000003803D4C8030A9F0000009EC8FBCA9E55
+:103F2000000098AA48004A9E28008A9D0040601818
+:103F3000040363A80000638400180CD4000083A865
+:103F40000000609C001804E40E000010000072A83D
+:103F50001000809C0000B4A80500E09C003850E4EC
+:103F60000600000C0000CEA8000076A80000B8A84B
+:103F70004000809C0000CEA8D0FDFF070000001587
+:103F80000400189F0001D69E0400949E4000529E9B
+:103F90000100109E0700609C0018B0E4E4FFFF13CE
+:103FA00004008C9DDAFEFF0300006EA8000021854E
+:103FB00004004185080081850C00C1851000018640
+:103FC00014004186180081861C00C18620000187EC
+:103FD00024004187280081872C00C18700480044C5
+:103FE0003000219CECFF219C004801D4045001D4F6
+:103FF000086001D40C7001D4108001D4000043A9E2
+:10400000000004AA00406018040363A80000638451
+:1040100000180AD4000083A80000609C001804E483
+:10402000110000100000001500406018200363A874
+:104030000000638404180AD4000083A8FF00609C79
+:10404000001824E40800001000000015004060186B
+:10405000400363A8000083840000638408200AD41E
+:104060000C180AD400408018040384A80000A09C07
+:1040700000006484002803E40400001010180AD42F
+:104080000000648414180AD400006484002803E447
+:104090001400001018180AD4004060180C0363A81C
+:1040A000000063841C180AD4000064840000848427
+:1040B00020180AD4002804E40A00001024200AD49E
+:1040C00000406018200363A80000838428200AD4DD
+:1040D00000008384000063842C200AD430180AD4A2
+:1040E0000040C0190403CEA90000809D00006E842A
+:1040F000006003E44A00000C34180AD400008E84E7
+:10410000006004E40A00001040200AD40040601857
+:10411000000363A8000083840000638448180AD465
+:1041200044200AD400006E844C180AD400008E8407
+:10413000006004E43500000C50200AD400006E84B6
+:10414000006003E42C00000CF0190AD450006A84CB
+:10415000006023E40600001000000015F0016A84EE
+:10416000006023E40400000C000000150000CE8570
+:1041700090730AD40040A0180403A5A80000858409
+:104180000000658494230AD4981B0AD4000083A8F5
+:104190000000609C001804E42800001000000015D6
+:1041A0000000A584000070A8DB1000049C2B0AD43A
+:1041B000000070A8D8100004A05B0AD4000070A80A
+:1041C000D5100004A45B0AD4000070A8D21000042B
+:1041D000A85B0AD4000070A8CF100004AC5B0AD41E
+:1041E000B05B0AD4CC100004000070A813000000DB
+:1041F000B45B0AD4F4016A9C17000004000090A884
+:10420000D4FFFF0350006A8454006A9C120000042B
+:10421000000090A8CAFFFF0300000015BE100004B4
+:10422000000070A838580AD4BB100004000070A821
+:10423000B3FFFF033C580AD40000218504004185E8
+:10424000080081850C00C1851000018600480044EB
+:104250001400219CE4FF219C004801D4045001D4A7
+:10426000086001D40C7001D4108001D4149001D4E2
+:1042700018A001D40000C3A9000004AA000064A88B
+:10428000A51000040000409E00406018100363A8C1
+:104290000C018E9D000083841F00809E8C004E9D2B
+:1042A0000000638400580ED404200ED408180ED4E5
+:1042B00000008E84000070A80000C09C002052E422
+:1042C000030000100000A09C0100C09C00A052E46C
+:1042D000040000100328A6E00100A09C0328A6E02B
+:1042E0000000809C002025E40F00000C0100529E7D
+:1042F0008910000400000015805FEAD786100004D2
+:10430000000070A800406018040363A800580AD495
+:104310000000638404004A9D00180CD4E5FFFF03ED
+:1043200004008C9D00406018140363A8000083847F
+:104330008C210ED40000838490210ED4000083844D
+:104340000000638494210ED498190ED400002185B6
+:1043500004004185080081850C00C185100001869C
+:104360001400418618008186004800441C00219CEE
+:10437000DCFF219C004801D4045001D4086001D422
+:104380000C7001D4108001D4149001D418A001D471
+:104390001CB001D420C001D45F100004000083A928
+:1043A000FF00609C0018ABE50800001000004BA95E
+:1043B00008008018FCE184A800206CE00100809CCB
+:1043C000E8000000002003D408006018FCE163A8A6
+:1043D0000000809C00184CE21F00009E002012D4B8
+:1043E00000006CA808008018607784A84A100004B8
+:1043F0000020CCE10080ABE40500001008580ED48A
+:104400000100609CD7000000001812D40040801802
+:10441000040384A804500ED4000064840000848443
+:104420000C180ED4D8230ED43B10000400006CA846
+:104430000000809C00200BE404000010DC5B0ED424
+:104440000100609C001812D4DC036E84002003E499
+:104450000900001000000015080080180CE984A86D
+:1044600000206CE00100809C002012D4D5FFFF03E7
+:104470001B00809C2810000400006CA800006CA8A1
+:1044800025100004545C0ED454046E84008043E470
+:1044900005000010585C0ED400804BE40400000CB2
+:1044A000000000150100609C001812D40040401963
+:1044B00004034AA900006CA800008A843300009E0F
+:1044C0005C240ED400408018080384A80000848473
+:1044D0004510000460240ED4645C0ED41A006B9D59
+:1044E0000080ABE4030000100100609C001812D4AF
+:1044F0003D10000400006CA8685C0ED41A006B9D8F
+:104500000080ABE4030000100100809C002012D466
+:104510003510000400006CA86C5C0ED41800609C80
+:104520000C006B9D0018ABE4030000100100609CC0
+:10453000001812D400008A840000C09C00006A8425
+:1045400074240ED4781C0ED40000809C00006A8471
+:1045500010200ED414200ED400408018080484A823
+:1045600000006484480063B80000809C200063A4BD
+:10457000003023E40A0000107C240ED400406018B0
+:10458000800363A800808018000084A80000A38432
+:10459000002025E47000000C0000001500006A8473
+:1045A00000004A8510180ED400300AE435000010CF
+:1045B00014500ED41000EE840000009EB8FB0E9F35
+:1045C000B803CE9E38008E9E18004E9D010067B83D
+:1045D000020010B90000C09C0600639C0000809C93
+:1045E000001870E4030000100000A09C0100C09CB3
+:1045F0000700609C001850E404000010032066E0EF
+:104600000100809C032066E0002823E41D00000CCC
+:104610000000001500406018040363A800006384D4
+:10462000002803E40E00001000180AD40040AEE099
+:10463000000074A8B803A59C1000809C0500E09CB5
+:10464000003850E40C0000100000CCA80000B6A810
+:104650001AFCFF07000000151000EE840001189FEF
+:104660000400D69E4000949E04004A9DD8FFFF039C
+:104670000100109E000078A8F6FFFF034000809C18
+:10468000D90F000400006CA8705C0ED40000928466
+:104690000000609C001804E40300000C00000015FA
+:1046A0000100609C08008018E47B84A800180ED4E8
+:1046B00000200CE20000409D0000B084005005E4A2
+:1046C000070000100000001504008E8404006584BB
+:1046D000001824E40C00000C000085A800008E8463
+:1046E0000000609C001804E41E00001000008EA86A
+:1046F00004006E84360400040000ACA81900000019
+:104700000000001500006EA8230300040000ACA800
+:1047100000502BE4F2FFFF13000000150800801882
+:10472000A47D84A800206CE000008384005004E491
+:104730000500000C000000150000609CE8FFFF036E
+:10474000001810D475DAFF0700006CA8FCFFFF0307
+:104750000000609C6C048E84CDFFFF0370240ED497
+:104760000000218504004185080081850C00C18579
+:104770001000018614004186180081861C00C18645
+:1047800020000187004800442400219CD0FF219C88
+:10479000004801D4045001D4086001D40C7001D445
+:1047A000108001D4149001D418A001D41CB001D4FD
+:1047B00020C001D424D001D428E001D42CF001D4AD
+:1047C000000003AA0000C4A908006018E87B63A8E1
+:1047D0000000809F001884E20100009F00007484A4
+:1047E000008003E41D0100100000409E08008018B6
+:1047F000A47D84A800206EE000008384009004E47F
+:104800001201000C000000150200A0185C67A5A8AA
+:104810000800C0181CDCC6A80028CEE200306EE0FC
+:10482000FFFF809C0000B6850200A018245CA5A8AC
+:10483000002003D40028CDE00000609C0200801816
+:10484000205C84A824180DD4001806D428180DD490
+:104850000020ADE0E80370840800639C008014D45D
+:10486000001805D420009084009004E40500001096
+:1048700000000015EC0370840800639C001806D447
+:10488000F00370840200C018D05BC6A80200801834
+:10489000D45B84A80400639C0030ADE0081878E085
+:1048A00000200DE11C08D0840400849C001805D46D
+:1048B00000208DE11408B08402006018E85B63A852
+:1048C0000200809C0100A59C00186DE1002808D41E
+:1048D000023084E0180870840400E5B80200C018B3
+:1048E000DC5BC6A80100639C00302DE1061B84E060
+:1048F0000200C018445CC6A800180CD400304DE17A
+:10490000000014850800C018787DC6A800304EE36A
+:104910000400C69C0030CEE33C08C8840623A5E012
+:10492000002009D400280BD4040084B8200070842F
+:1049300020200DD41C380DD400180AD400381AD405
+:104940002000AD85009006E40800001000681ED429
+:1049500080086884009003E4040000100000001543
+:104960008408088788088887080080189CE184A844
+:104970000000A09C00206EE000008384002824E456
+:10498000AC00000C0100609C001824E42100001021
+:104990000000609C000074841C088384002824E4C8
+:1049A0009F0000100600809C0800A018A4E1A5A8A4
+:1049B00000286EE00000A384002025E49800001089
+:1049C0003200609C0800C018ACE1C6A80030AEE020
+:1049D00000008584001804E48F000010001884E4AF
+:1049E000090000103B00609C001804E4080000105F
+:1049F0001D00409E3C00609C001804E40400001070
+:104A00001E00409E00006584410043BA0000609C87
+:104A1000001832E403000010000000151E00409E44
+:104A20000800A018887DA5A800286EE0009003D497
+:104A3000200090840100609C001824E461000010B4
+:104A40000200609C0000B6841C0065842000858400
+:104A50005F00C3B85F00E4B8003063E0003884E072
+:104A6000810063B8810084B8241805D4282005D4B7
+:104A7000000076840200C018EC5BC6A80000809D90
+:104A8000003063E000008384006024E44900000CEF
+:104A9000000000150800801818C584A800006EA842
+:104AA0001AE0FF0700204EE10800A018F8E1A5A8D1
+:104AB00000286EE000008384006004E4040000101D
+:104AC0000000C09C65000000003014D4080080186D
+:104AD0004CE684A800206EE00000A3840100809CC6
+:104AE000002005E45D0000100000CA840800A01842
+:104AF00060E6A5A800286EE00000BA840000838468
+:104B0000002824E41100001000000015080080189F
+:104B100064E684A80000BE8400206EE00000838468
+:104B2000002824E409000010000000150800A01867
+:104B300068E6A5A800286EE000008384003024E425
+:104B40001100000C0000001504006018287663A80E
+:104B50008A76FF070000809C0800C0185CE6C6A8A3
+:104B60000200A09C00306EE00100809C002803D46D
+:104B700008200ED44700000400006EA83700000093
+:104B800000000015040060183B7663A87B76FF07E1
+:104B90000000809C0800C0185CE6C6A80000809C4D
+:104BA00000306EE008200ED42C000000002003D45A
+:104BB000D7F4FF0700006EA8B7FFFF030000001541
+:104BC000001824E40B0000100300609C00007684B1
+:104BD0001C0083845F00A4B82000C384002884E004
+:104BE000283003D4810084B8A2FFFF03242003D41B
+:104BF000001824E49FFFFF130000001500007684D6
+:104C0000200083841C00A384282003D499FFFF0381
+:104C1000242803D47EFFFF031900409E080080185B
+:104C2000ACE184A800206EE079FFFF03000043861A
+:104C300000007CA8000098A886DEFF070000AEA850
+:104C400073FFFF0300004BAA34D9FF0700006EA8D2
+:104C5000EEFEFF03000000150000218504004185E1
+:104C6000080081850C00C185100001861400418672
+:104C7000180081861C00C18620000187240041871E
+:104C8000280081872C00C187004800443000219C07
+:104C9000E8FF219C004801D4045001D4086001D4ED
+:104CA0000C7001D4108001D4149001D4000003AA28
+:104CB00008008018787D84A80800A0187C7DA5A82D
+:104CC000002063E0002890E0000083850000448518
+:104CD00000006CA80485FF0700008AA841008AB87C
+:104CE00000006CA80000CBA9FF84FF0742004AB96E
+:104CF00000006CA800008AA8FB84FF0700004BAAF4
+:104D00000800601814E963A8001890E00400639C90
+:104D10000018B0E0080060185CE663A80018D0E056
+:104D20000000648400184EE4180000100100809C0C
+:104D3000080080181CE984A800006584001852E46B
+:104D4000110000100020F0E00800A01818C5A5A868
+:104D50000800601868E663A8002890E00018B0E03A
+:104D60000000678400184BE40700001000000015E5
+:104D70000000848400006584001844E50400000CF1
+:104D8000000000150100809C002006D40000218551
+:104D900004004185080081850C00C1851000018652
+:104DA00014004186004800441800219CF0FF219C1B
+:104DB000004801D4045001D4086001D40C7001D41F
+:104DC000000083A9000044A908006018E47B63A8E0
+:104DD0000018C4E108008018A47D84A800006E8437
+:104DE000006003E4160000100020AAE00000A58483
+:104DF0000000809C002005E40D00000C00006AA863
+:104E0000020060185C6763A800600ED400188AE096
+:104E100010008C8500006484020080183C5C84A82B
+:104E2000002063E006000000006003D4BBD8FF0749
+:104E300000000015F3FFFF030000001500002185AE
+:104E400004004185080081850C00C18500480044AC
+:104E50001000219CF4FF219C004801D4045001D48F
+:104E6000086001D40000A3A8FF00C09C0030A3E5A7
+:104E70002400000C000044A98404609C0000E09C15
+:104E8000061BA5E00300601860F363A8002884E017
+:104E9000001884E100006C84003823E41900000C41
+:104EA000000000150300801868F384A8002065E066
+:104EB00000186AE01F00809C0000A3840020A5E485
+:104EC0001000000C010065B802008018606784A81B
+:104ED000002863E00A0063B800186AE00020A3E03D
+:104EE00000008584003824E40600000C0200609C69
+:104EF000F40385840018A4E4080000100100E09C7D
+:104F00000800801800E284A800206AE00100809C6C
+:104F100013000000002003D4003824E40B0000102C
+:104F2000000065A8080465840030A3E407000010B1
+:104F3000000065A80800801800E284A800206AE04C
+:104F400007000000003803D411FEFF0700008AA804
+:104F500000006CA896FFFF0700008AA800002185CA
+:104F60000400418508008185004800440C00219C14
+:104F7000FCFF219C004801D40000C3A80000E4A865
+:104F8000000063840000809C002003E49D0000106A
+:104F90000100609D00006784002023E49900000C5C
+:104FA000000000150400868404006784001824E4CF
+:104FB0000300000C000000150000609D08008684BE
+:104FC00008006784001824E4EE00001000000015BB
+:104FD00001006BA50C0086840C006784001824E493
+:104FE000E60000100000001501006BA5100086848B
+:104FF00010006784001824E4DE0000100000001593
+:1050000001006BA51800868418006784001824E44A
+:10501000D60000100000001501006BA51C0086845E
+:105020001C006784001824E4CE0000100000001566
+:1050300001006BA5F0038684F0036784001824E464
+:10504000C60000100000001501006BA5F403868463
+:10505000F4036784001824E4BE000010000000156B
+:1050600001006BA50000609C00182BE4C700000C39
+:10507000001824E47F0000100100609CF80386847F
+:10508000F8036784001824E478000010000000157D
+:1050900001006BA50C0886840C086784001824E4C2
+:1050A000700000100000001501006BA51008868438
+:1050B00010086784001824E4680000100000001540
+:1050C00001006BA51408868414086784001824E482
+:1050D000600000100000001501006BA51808868410
+:1050E00018086784001824E4580000100000001518
+:1050F00001006BA51C0886841C086784001824E442
+:10510000500000100000001501006BA50000609C1D
+:1051100000182BE49D00000C001824E40800001087
+:10512000000000152008868420086784001824E405
+:10513000420000100000001501006BA524088684C1
+:1051400024086784001824E43A00001000000015C9
+:1051500001006BA52808868428086784001824E4C9
+:10516000320000100000001501006BA50000609CDB
+:1051700000182BE48500000C001804E41A0000104D
+:10518000000000152C0886842C086784001824E48D
+:10519000240000100000001501006BA53008868473
+:1051A00030086784001824E41C000010000000157B
+:1051B00001006BA53408868434086784001824E451
+:1051C000140000100000001501006BA5380886844B
+:1051D00038086784001824E40C0000100000001553
+:1051E00001006BA53C0886843C086784001824E411
+:1051F00004000010000000156400000001006BA511
+:10520000620000000000609DF7FFFF030000609D4A
+:10521000EFFFFF030000609DE7FFFF030000609DBC
+:10522000DFFFFF030000609DD1FFFF030000609DD2
+:10523000C9FFFF030000609DC1FFFF030000609DE8
+:10524000B3FFFF030000609DABFFFF030000609D04
+:10525000A3FFFF030000609D9BFFFF030000609D14
+:1052600093FFFF030000609D8BFFFF030000609D24
+:10527000001824E488FFFF1300000015FC03868457
+:10528000FC036784001824E43000001000000015BF
+:1052900001006BA50004868400046784001824E4E0
+:1052A000280000100000001501006BA5040486848E
+:1052B00004046784001824E4200000100000001596
+:1052C00001006BA50804A6850804678400182DE476
+:1052D000180000100000001501006BA50000609C84
+:1052E00000182BE42900000C0000209D006889E4D0
+:1052F00069FFFF0F0C04009D004066E0004087E05E
+:105300000000A38400006484001825E40300000C5E
+:1053100001006BA50000609D0100299D006889E4E3
+:10532000F6FFFF130400089D5CFFFF030C08868452
+:10533000EBFFFF030000609DE3FFFF030000609DA3
+:10534000DBFFFF030000609DD3FFFF030000609DB3
+:1053500045FFFF030000609D3DFFFF030000609DCF
+:1053600035FFFF030000609D2DFFFF030000609DDF
+:1053700025FFFF030000609D1DFFFF030000609DEF
+:1053800015FFFF030000609D0000218500480044D8
+:105390000400219CFCFF219C004801D40000E3A8EC
+:1053A000000004A9000063840000809C002003E446
+:1053B000810000100100609D00006884002023E44B
+:1053C0007D00000C00000015040087840400688440
+:1053D000001824E40300000C000000150000609D8C
+:1053E0000800878408006884001824E4E1000010A5
+:1053F0000000001501006BA50C0087840C00688478
+:10540000001824E4D90000100000001501006BA56D
+:10541000D8038784D8036884001824E4D1000010DE
+:105420000000001501006BA5DC032785DC03688400
+:10543000001829E4C90000100000001501006BA548
+:105440000000609C00182BE4CC00000C001809E45C
+:105450001C00001000000015E0038784E00368844E
+:10546000001824E4BB0000100000001501006BA52B
+:105470000000609C00182BE4C000000C001824E41D
+:10548000610000100200A09C0000A09DE403C09CED
+:10549000003067E0003088E00000A38400006484EE
+:1054A000001825E40300000C01006BA50000609DBE
+:1054B0000100AD9D0048ADE4F6FFFF130400C69C5B
+:1054C0005404878454046884001824E44C000010B9
+:1054D0000000001501006BA55804878458046884F7
+:1054E000001824E4440000100000001501006BA522
+:1054F0005C0487845C046884001824E43C00001089
+:105500000000001501006BA56004878460046884B6
+:10551000001824E4340000100000001501006BA501
+:105520006404878464046884001824E42C00001058
+:105530000000001501006BA5680487846804688476
+:10554000001824E4240000100000001501006BA5E1
+:105550006C0487846C046884001824E41C00001028
+:105560000000001501006BA574048784740468842E
+:10557000001824E4140000100000001501006BA5C1
+:105580007804878478046884001824E40C000010F0
+:105590000000001501006BA57C0487847C046884EE
+:1055A000001824E40400001000000015730000003F
+:1055B00001006BA5710000000000609DF7FFFF0374
+:1055C0000000609DEFFFFF030000609DE7FFFF0309
+:1055D0000000609DDFFFFF030000609DD7FFFF0319
+:1055E0000000609DCFFFFF030000609DC7FFFF0329
+:1055F0000000609DBFFFFF030000609DB7FFFF0339
+:105600000000609D002824E41E000010FDFF649C43
+:105610000000A09D00488DE4AAFFFF0F2404209EF7
+:105620000404E09D007867E0007888E00000A3842F
+:1056300000006484001825E40300000C01006BA541
+:105640000000609D0088A7E00088C8E00000858415
+:1056500000006684001824E40300000C01006BA520
+:105660000000609D0400319E0100AD9D00488DE466
+:10567000EDFFFF130400EF9D93FFFF0354048784A5
+:10568000002843E4130000100600609C4404878453
+:1056900044046884001824E40C0000100000001585
+:1056A00001006BA54804878448046884001824E43A
+:1056B000040000100000001582FFFF0301006BA52D
+:1056C00080FFFF030000609DF7FFFF030000609D67
+:1056D000001824E47BFFFF13000000154C0427860C
+:1056E0004C046884001831E4180000100000001514
+:1056F00001006BA50000609C00182BE41F00000C4B
+:105700000000A09D5004E7855004288502006DB874
+:105710000048A3E0007863E00000C58400008384B3
+:10572000003024E40300000C01006BA50000609D24
+:105730000100AD9D0088ADE4F6FFFF1302006DB8D7
+:1057400061FFFF0354048784EBFFFF030000609DAB
+:1057500048FFFF030000609D3AFFFF030000609DCB
+:1057600032FFFF030000609D2AFFFF030000609DE1
+:1057700022FFFF030000609D0000218500480044D7
+:105780000400219C0100C3B8FF0BE09C0018C6E098
+:105790000A00C6B8FFFF609C0030A5E00200C018F8
+:1057A0006067C6A80030A5E00000C48CFFFFE79C3E
+:1057B000003005D80100849C001827E4FBFFFF138C
+:1057C0000100A59C00480044000000158404C09C12
+:1057D000FFFFE09C063363E00018A5E08304C09C53
+:1057E0000300601860F363A80018A5E00000648C53
+:1057F000FFFFC69C001805D80100849C003826E4F1
+:10580000FBFFFF130100A59C0048004400000015A9
+:10581000E0FF219C004801D4045001D4086001D469
+:105820000C7001D4108001D4149001D418A001D4BC
+:10583000000043A90000C4A908006018E47B63A825
+:1058400038004A86001884E20100C09C0000809C59
+:105850001C2001D4000094846004A484003025E45A
+:10586000060000100000001518006A84003003E4F0
+:105870009B010010000000155C0464840000E09CA3
+:10588000003803E4060000100200609C18008A84BF
+:10589000001824E48E01001000000015001825E413
+:1058A000870100100000001518006A84003023E40E
+:1058B0007F0100100000001520007284003823E4EE
+:1058C0007701001000000015A8017284003823E45D
+:1058D0006F010010000000150800A0186CDCA5A8DE
+:1058E00000280EE200007084003823E40500000C5C
+:1058F0000000001500006AA86806000400008EA8D9
+:1059000002006018005C63A80800E018A47DE7A806
+:105910000018AAE000388EE00000A584004060185E
+:10592000084063A80000809D0000C484002803D4C0
+:10593000006006E45201000C1C00619C00007084B1
+:10594000006023E40E0000100000001520007284A7
+:10595000006023E40A00001000000015A801728412
+:10596000006003E4700000100100609C18008A844D
+:10597000001804E46C00000C000000153C006A8470
+:105980000000809C002003E4240100100000209D02
+:105990006C006A84002023E4210100101F00C09CD9
+:1059A0000000E09D0100009D0000E09C04006018E4
+:1059B000108863A807008FB80018A7E00000209D9A
+:1059C00000406018005263A8001884E0000065845D
+:1059D0000100299DFF0F63A40400A59C001804D4B6
+:1059E0000030A9E5FAFFFF130400849C0100EF9D3D
+:1059F0000040AFE5EEFFFF138000E79C0000209D14
+:105A00000F00C09C0040A0180053A5A804008018F7
+:105A1000908784A8000064840100299DFF0F63A47F
+:105A20000400849C001805D40030A9E5FAFFFF1398
+:105A30000400A59C0000E09D1F00209E0400A0190A
+:105A40009084ADA90400601990866BA90100009EA6
+:105A50000400809D05006FB807008FB80000209DEE
+:105A60000663C3E000406018000963A80018E4E082
+:105A7000005866E00068A6E0000083840400C69C2D
+:105A80000100299D080084B800006584002003E11E
+:105A9000004007D40088A9E5F6FFFF130400E79C47
+:105AA0000100EF9D0080AFE5ECFFFF1305006FB82C
+:105AB0000000209D3F00A09C00408018005084A85A
+:105AC00004006018908563A80000C3840100299D2C
+:105AD000003004D40400639C0028A9E5FBFFFF13F9
+:105AE0000400849C08006018ACE263A80040E01841
+:105AF0003040E7A80018AEE0C0FF809C000067843B
+:105B0000032063E00000C5841C0081841000A09C79
+:105B10000028A6E503000010042063E0400063A80D
+:105B2000001807D400406018040863A80000A09C77
+:105B30006C00CA840000609D002803D470008A8431
+:105B40003800639C003003D4005824E403000010A4
+:105B5000000000150100A09C00406018400863A8E8
+:105B60001400EA8400408018004084A8002803D470
+:105B70000000148502006018C85B63A8003804D4D4
+:105B80003C00AA8400188AE000406018044063A822
+:105B90007804C884002803D41000639C0000A48407
+:105BA000003003D4005805E4030000100000C09C3E
+:105BB0000100C09C7004888400406018184063A8ED
+:105BC000003003D40C00E8841F0084A40400639C0C
+:105BD0006C04A884050084B8003803D41F00A5A471
+:105BE0000400639C0420A5E0002803D40040801832
+:105BF000244084A804007284001804D40C00B284E9
+:105C000002008018D45B84A800406018340863A8A0
+:105C10000020EAE0002803D40000E7840040601878
+:105C2000200863A8003803D44400AA840200E018C6
+:105C3000E05BE7A80400639C0038CAE0FFFFA59C76
+:105C40000000C684003003D448008A8400406018F5
+:105C5000284063A8002803D4FFFF849C0800601834
+:105C600074E163A80018CEE0004060182C4063A8DF
+:105C70000000A684002003D4020025B95C048884B7
+:105C80000800639C0800A01888DCA5A8002003D4A5
+:105C9000600408850400639C0028CEE0004003D423
+:105CA000BC008A84080060187CDC63A80018EEE061
+:105CB0000000A684004060183C4063A80800C0189B
+:105CC000F4DFC6A8002003D4C0004A85003089E074
+:105CD0000400639C0000C78400208EE01800A5B873
+:105CE000005003D43003F28400406018480863A8D1
+:105CF0001000C6B8003803D40000048508006018FE
+:105D00005CC963A80030A5E00018EEE0340392847B
+:105D1000004060184C0863A8004005E1002003D44F
+:105D2000380352860400639C00008784009003D4EB
+:105D3000005804E40F000010000000150800A0182F
+:105D4000BCC5A5A80800C018F4DFC6A800288EE0CE
+:105D50000000A48494006584020063B8003063E00E
+:105D600000186EE000008384080084B8002008E179
+:105D70000800E01874DEE7A80800A018F4DCA5A865
+:105D8000003869E0002889E000186EE00800C018BB
+:105D9000E87BC6A800208EE00000A3840030EEE07F
+:105DA0004D00209D0000C484004060180C0B63A8C7
+:105DB0000800A5B8004003D400008784003005E146
+:105DC00000406018080B63A804008484004003D4DA
+:105DD000004804E408000010004844E40A000010F1
+:105DE0006400609C4200609C001804E40400001001
+:105DF000000000153E0000000000009D3C00000077
+:105E00000200009D001804E4FBFFFF0F00000015D6
+:105E1000370000000100009D1F00C09C0040A0183A
+:105E20000052A5A804008018908784A8000064840C
+:105E30000100299DFF0F63A40400849C001805D471
+:105E40000030A9E5FAFFFF130400A59C0000209D87
+:105E50002F00809C00406018805263A80000A09C26
+:105E60000100299D002803D40020A9E5FCFFFF13B1
+:105E70000400639CF1FEFF030000E09D3700000476
+:105E800000008EA8AFFEFF03000070840800801899
+:105E90006CDC84A898FEFF0300200EE20800601866
+:105EA0006CDC63A894FEFF0300180EE20800C01823
+:105EB0006CDCC6A893FEFF0300300EE20800A018B9
+:105EC0006CDCA5A88FFEFF0300280EE20800E01896
+:105ED0006CDCE7A888FEFF0300380EE20800C0185B
+:105EE0006CDCC6A884FEFF0300300EE20000C7840D
+:105EF0000000B484FF00E09C2000668410008584CC
+:105F0000020063B81800A684040084B8041868E08E
+:105F10000800A5B8042063E000408018300884A879
+:105F2000042863E00040A0184C40A5A8001804D441
+:105F3000003805D4000021850400418508008185D2
+:105F40000C00C1851000018614004186180081866E
+:105F5000004800442000219CF4FF219C004801D40B
+:105F6000045001D4086001D4000083A90800A018DF
+:105F70006CDCA5A8020060185C6763A8000064AA36
+:105F8000001844E1002884E00000CA840000A09CBE
+:105F900000006484002823E40E000010380086848A
+:105FA00020006484002823E40A000010000000158B
+:105FB000A8016484002803E4E40100100100609C4F
+:105FC00018008684001804E4E001000C00000015AD
+:105FD0000800E018ACE2E7A81000809C003873E0ED
+:105FE0000000A3840020A5E5030000100F00209FFF
+:105FF0001F00209F0000A09E3F00809C04006018AE
+:10600000908563A80000A09C0100B59E002803D4E1
+:106010000020B5E5FDFFFF130400639C0400A01BF6
+:106020009085BDAB0800E01858C9E7A80000A09E05
+:106030000400601B90847BAB0000FDAB0000E09E81
+:10604000003833E2020077B8070095B80800A018BE
+:10605000B4C5A5A8009863E00400E0180C85E7A883
+:106060001F00A09D7C00C49C002823E1003804E1AF
+:106070000000718400186DE5AE0100100000E09C86
+:106080000000A9840000609D005805E49B010010F9
+:106090000000E09D000085840200609C001824E45C
+:1060A00003000010000000150100E09D94006584CD
+:1060B0000800E018F4DCE7A800D886E0020063B826
+:1060C000003863E0001873E00000E38400580FE438
+:1060D00003000010000067A88000679C001804D42B
+:1060E00004006018908663A8001886E09400658418
+:1060F000020063B80800A01874DEA5A8002863E0B9
+:10610000001873E000580FE40300001000006384DF
+:106110008000639C001804D40000A09C002835E493
+:106120000D0000100000001508008018A47D84A850
+:10613000002073E100006B8444008384002804E4A1
+:106140006901001003C867E0020063B800F863E06B
+:10615000006803D4FCFF089DFCFFC69CFFFFAD9DBB
+:106160000000809C00206DE5C2FFFF13FCFF299D0D
+:106170002100F79E0100B59E0100609C0018B5E566
+:10618000B1FFFF130400319E08006018BCC563A86E
+:10619000001813E100006884002003E4540000109C
+:1061A000000000150800801858C984A80000A09DB0
+:1061B000002033E20000718400188DE54C00000CD3
+:1061C000000000150800A018A47DA5A80800E0188C
+:1061D00038C5E7A8002873E10038F3E10000AB867A
+:1061E0000000AF8480FFC09C040085840400758497
+:1061F000022063E0003083E53901001002006DB930
+:10620000000023A97F00609C0018A9E5030000108E
+:1062100000000015000023A90000C88480FFE09C56
+:1062200000008F840400A68404006484021865E0E2
+:10623000003883E5080000100000C7A80000C3A8CC
+:106240007F00609C0018A6E5040000100000A09CE0
+:106250000000C3A80000A09C002806E41B01001059
+:106260000000001500006F8428008384002824E4C7
+:106270001601001000FCA09C5F0066B8001866E0E4
+:106280009F0083B8810063B8051864E0022063E0D2
+:106290000040639C093363E0061B89E02000849C76
+:1062A000860064B8002883E508000010000085A877
+:1062B000000083A8FF03609C0018A4E50300001001
+:1062C00000000015000083A80400A0189087A5A86E
+:1062D00000286BE0002003D4000071840100AD9D14
+:1062E00000188DE5BFFFFF130400EF9D00006A84D6
+:1062F0000000809C3C00A384002005E49F00001067
+:10630000000000150000A09E0000609C001835E40D
+:10631000030000100400209F0200209F0500F9BA2E
+:106320000800E018BCC5E7A800C8B7E0020065B8DF
+:10633000003863E00018D3E0000086840000609C11
+:10634000001804E488000010020079B808008018E2
+:1063500058C984A80000A09D002063E00018F3E065
+:106360000000878400208DE57F00000C020065B8E6
+:10637000000067AB070095B8009863E00800E018DC
+:1063800038C5E7A80400A0181088A5A80038E3E1E4
+:106390000000A6AB08006018A47D63A8002824E2D2
+:1063A000001873E100C877E00800801838C584A899
+:1063B000006863E0020063B8002063E0001873E047
+:1063C000000083840000609C001815E4BC000010ED
+:1063D0000400A48400006B8410008384022884E0FD
+:1063E00080FF609C001864E52400000C80FF209D65
+:1063F00000C877E00800A01838C5A5A8006863E0C9
+:10640000020063B8002863E0001873E00000838492
+:106410000000609C001815E4A60000100400A4848D
+:1064200000006B8410008384022884E07F00609C5D
+:106430000018A4E51100000C7F00209D00C877E043
+:106440000800E01838C5E7A8006863E0020063B8F8
+:10645000003863E0001873E0000083840000609C53
+:10646000001815E4900000100400A48400006B8460
+:1064700010008384022824E10000DD8480FFE09C7A
+:1064800000008F840400A68404006484021865E080
+:10649000003883E5080000100000C7A80000C3A86A
+:1064A0007F00609C0018A6E5040000100000E09C3E
+:1064B0000000C3A80000E09C003806E4780000104B
+:1064C0000001A09C00C877E00800801838C584A8A7
+:1064D000006863E0020063B8002063E0001873E026
+:1064E000000083842800A484003825E46C00001098
+:1064F0000001A09C5F0066B800FCA09C001866E04C
+:106500009F0083B8810063B8051864E0022063E04F
+:106510000040639C093363E0061B89E02000849CF3
+:10652000860064B8002883E508000010000085A8F4
+:10653000000083A8FF03609C0018A4E5030000107E
+:1065400000000015000083A8002011D400007B8407
+:106550000400319E0100AD9D00188DE592FFFF13F0
+:106560000400EF9D0100B59E0100609C0018B5E598
+:1065700066FFFF13000000150000C8840000E09CC7
+:10658000003806E4440000100000001508008018E0
+:10659000A47D84A8002073E00000A38444008584C7
+:1065A000003804E42F00001000000015040065848A
+:1065B0000C008684021864E100386BE503000010CB
+:1065C00000000015022063E1100086840218A4E098
+:1065D000003885E51D00001000288BE50300001041
+:1065E0000000209D0100209D0800A018E87BA5A8C0
+:1065F00000000885002873E0020029B90000E38448
+:106600004800888444006884010084B82408A78472
+:10661000002063E01C08C7840400A5B8004863E0BC
+:106620000500C6B8002863E02800E8840000809CCC
+:10663000002027E403000010003063E00800639CA2
+:106640004200000000180CD4022063E000188BE523
+:10665000E6FFFF130000209DE4FFFF030100209DE3
+:1066600044006684003803E40900001000000015AF
+:10667000000065840100209D004823E4DBFFFF1338
+:1066800000000015D9FFFF030000209DFAFFFF0363
+:10669000000066842D00000000380CD4ACFFFF031E
+:1066A000002811D400006B8473FFFF030C00838467
+:1066B00000006B845DFFFF030C00838400006B848B
+:1066C00047FFFF030C0083840400E0189087E7A8CD
+:1066D0000001809C00FFFF0300386BE0CFFEFF034A
+:1066E000000026A9010063B8007863E0020063B8E7
+:1066F00098FEFF0300E863E00800E018F4DCE7A878
+:1067000004008018908684A8003873E00020A6E07A
+:106710000000E3840800601874DE63A8003808D421
+:10672000001893E0000084847CFEFF03002005D461
+:106730000400A0189086A5A8002866E0003808D4B8
+:1067400085FEFF03003803D4000021850400418545
+:1067500008008185004800440C00219CE0FF219C3A
+:10676000004801D4045001D4086001D40C7001D455
+:10677000108001D4149001D418A001D41CB001D40D
+:10678000000004AA000023AB180083840100C09C11
+:10679000003024E4030000100000009D000006A962
+:1067A0000000A09C002824E4030000100300609C6B
+:1067B0000000A6A8001824E4030000100000E09CDC
+:1067C0000000E6A8043825E100206018000063A856
+:1067D0000000A09DFF07809C0000A09C0100AD9DD3
+:1067E000002803D80020ADE5FDFFFF130100639CE6
+:1067F0004800F9854400798600986FE50300001091
+:106800000000AFAA0000F3A908008018E47B84A868
+:10681000002070E00200E09C0000A3846004658416
+:10682000003823E4030000100000C09C0100C09C5D
+:106830000000809C002008E4030000100000609C21
+:106840000100609C031866E0002003E404000010CF
+:106850000500609CBC1819D4C01819D4002008E4A5
+:1068600050020010002009E4600485840100609C4F
+:10687000001824E459000010003824E40000E09ED1
+:10688000060097B80000A09D00788DE52100000C5F
+:10689000000044A9020084B80040A0180054A5A834
+:1068A000010077B8002824E100B863E00040A01898
+:1068B0000064A5A8070063B8002804E100C863E0ED
+:1068C00001008018C43284A8C409C39C0020E3E0FE
+:1068D0000300668C0100AD9D03F7868C080063B849
+:1068E0000000A784001884E00C00C69C002009D496
+:1068F0000100A5A40400299D002808D40C00E79CF1
+:1069000000788DE5F3FFFF130400089D0000A09DB3
+:1069100000788DE52A00000C20008A9C020084B8D3
+:106920000040A0180054A5A8010077B8002864E131
+:1069300000B863E00040A0180064A5A8070063B891
+:10694000002844E100C863E001008018CC3284A82C
+:10695000CC09039D002023E1FFFF888C0100AD9D41
+:1069600003F7C88C080084B8FFF6688C1000C6B81E
+:106970000300E88C002063E00000A9841800E7B859
+:10698000003063E0FCFF89840100A5A4003863E0C7
+:106990000100A5B8010084A400180BD4002884E0ED
+:1069A00004006B9D00200AD40C00299D04004A9D20
+:1069B00000788DE5E9FFFF130C00089D0100F79EAC
+:1069C0000100609C0018B7E5AFFFFF13060097B801
+:1069D0002802000000000015260200100000A09D03
+:1069E00000988DE55100000C000000150800A0186B
+:1069F00038C5A5A8002870E30000BBAB0000FBABC6
+:106A00000000E09E00A897E54200000C05006DB86C
+:106A100000208018000484A80800A018BCC5A5A800
+:106A2000002043E100003FAA0000FDA9000063A987
+:106A30000000DBA92000809D00000AA9002830E1A9
+:106A40000000C98480FFE09C000091840400A684BB
+:106A500004006484021865E0003883E50800001033
+:106A6000000000150000E3A87F00609C0018A7E567
+:106A700003000010000000150000E3A800006F8470
+:106A800080FFC09C0400A384B4009984022884E0A1
+:106A9000003084E5070000100000A6A87F00609C7D
+:106AA0000018A4E5030000100000A4A80000A3A89B
+:106AB0000000C09C003007E40D0000100000609C46
+:106AC0000000698428008384003024E4080000105A
+:106AD0000000609C00006E8428008384003024E461
+:106AE0008401000C5F0067B80000609C0064E8DB74
+:106AF000001808D801004A9D01006B9D0100089D07
+:106B00000100F79E00A897E5CEFFFF130400299D22
+:106B100004007B9F0400BD9F0100AD9D00988DE5A2
+:106B2000B8FFFF130400FF9F3C00D9850000609C64
+:106B300000182EE4030000100200809D0300809DD9
+:106B40000000E09E00A897E54800000C0000609C53
+:106B50000000A09D00988DE54000000C086097E0C3
+:106B6000020064B80040A0180054A5A8000077A94E
+:106B700000408018006484A8002823E20020E3E19C
+:106B80000020A0182000A5A80400AD9D00286BE0FF
+:106B90002000A59C00288BE00000A38C0000C48C82
+:106BA00000206018000063A80800A5B80018EBE0FA
+:106BB00000208018200484A800206018600063A8CA
+:106BC00000204BE100180BE12000849C0000678C42
+:106BD00000202BE11000C6B80000888C002863E07C
+:106BE0000020A0180004A5A8180084B80028EBE035
+:106BF000003063E00020A0186004A5A8002063E036
+:106C000000280BE1001811D480006B9D0000AA8CB5
+:106C10000400319E0000C98C0100A5A40000678C0F
+:106C20000100A5B80100C6A40000888C010063A47F
+:106C30000200C6B8010084A4002863E0030084B801
+:106C4000003063E0002063E000180FD400988DE569
+:106C5000CCFFFF130400EF9D0100F79E00A897E50D
+:106C6000BCFFFF130000609C00180EE481010010BF
+:106C70000100D5BA0000E09E00B097E57D01000C50
+:106C8000010073BB08006018CCC763A80800801817
+:106C9000C4C684A80018B0E30020F0E300005FAA97
+:106CA00000009DAA0000A09D00D88DE55D00000CAD
+:106CB000030077B80020601920016BA90800A01814
+:106CC00048C7A5A8000092A90000BFAA0000DDA93E
+:106CD00000202019800029A900004BA9002810E1FC
+:106CE0000020E0190001EFA90020201A000031AABD
+:106CF000000074AA0000CC8480FFE09CF8FE888429
+:106D00000400A68404006484021865E0003883E56A
+:106D1000080000100000A09C0000E3A87F00609C19
+:106D20000018A7E503000010000000150000E3A80C
+:106D3000002807E40D0000100000609C000075842E
+:106D400028008384002824E4080000100000609CD0
+:106D5000F8FE888428006484002823E4B300000C33
+:106D600080FFA09C0000609C2000809CE01FEADB6C
+:106D70008027E9D70000CE8480FFE09C0000888453
+:106D80000400A68404006484021865E0003883E5EA
+:106D9000080000100000A09C0000E3A87F00609C99
+:106DA0000018A7E503000010000000150000E3A88C
+:106DB000002807E40D0000100000609C00007384B0
+:106DC00028008384002824E4080000100000609C50
+:106DD0000000888428006484002823E46100000CFB
+:106DE00080FFA09C0000609C2000809C00180AD8B6
+:106DF000002009D401006B9D0400299D01004A9DDB
+:106E00000400089D0100EF9D0100AD9D00D88DE5B7
+:106E1000B9FFFF130400319E030077B80000A09D66
+:106E20004001A39C00D88DE54500000C4000839CE8
+:106E3000020065B8020084B80020601923016BA924
+:106E40000040A0180054A5A8002040198C004AA9B1
+:106E50000028A3E2002864E20040A0180064A5A86E
+:106E6000002823E20028E4E17BFFAA8C0400AD9D0A
+:106E70007FFFCA8C0800A5B877FF6A8C1000C6B8DF
+:106E800083FF8A8C002863E0180084B8003063E038
+:106E9000FBFF0A8D002063E0001813D4FFFF2A8D4A
+:106EA000080008B90400739EDEFFAB90100029B9FA
+:106EB000DDFF8B900100A5B8DFFFEB90002884E098
+:106EC000E0FFCB900200E7B8F7FF6A8C0300C6B87A
+:106ED000003884E00300AA8C004063E0003084E0C6
+:106EE0001800A5B8004863E000200FD4002863E034
+:106EF0000400EF9D001815D410004A9DFEFFAB90D2
+:106F00000400B59EFFFFCB900100A5B8FDFF6B907C
+:106F10000200C6B800008B90002863E0030084B82C
+:106F2000003063E004006B9D002063E0001811D482
+:106F300000D88DE5CDFFFF130400319E0400BD9FF6
+:106F40000400FF9F0400529E0100F79E00B097E5E9
+:106F500055FFFF130400949EC600000000000015BA
+:106F60000400848460007984022063E0002883E5C3
+:106F700008000010000000150000A3A87F00609C1E
+:106F80000018A5E503000010000000150000A3A8EC
+:106F90005F0067B800FCC09C001867E09F0083B8E2
+:106FA000810063B8051864E0022063E00040639C40
+:106FB000093B63E0062B83E02000849C860064B8D4
+:106FC000003083E517000010FF03809C0020A3E53C
+:106FD000040000108200A3B8000064A88200A3B8D7
+:106FE0000000C09C8000809C4000609C022863E000
+:106FF000002023E403000010001809D40100C09C05
+:107000004000859CC000609C0018A4E47AFFFF1338
+:1070100000300BD82000A09C77FFFF03002809D484
+:10702000EFFFFF03000066A8040084845C007984FD
+:10703000022063E0002883E508000010000000152E
+:107040000000A3A87F00609C0018A5E503000010C5
+:10705000000000150000A3A85F0067B800FCC09CFA
+:10706000001867E09F0083B8810063B8051864E0EA
+:10707000022063E00040639C093B63E0062B83E051
+:107080002000849C860064B8003083E5170000105F
+:10709000FF03809C0020A3E5040000108200A3B839
+:1070A000000064A88200A3B80000C09C8000809CFF
+:1070B0004000609C022863E0002023E403000010ED
+:1070C000801FE9D70100C09C4000859CC000609CE7
+:1070D0000018A4E428FFFF1300300FD82000A09C64
+:1070E00025FFFF03002811D4EFFFFF03000066A86F
+:1070F00000FCC09C001867E09F0083B8810063B863
+:10710000051864E0022063E00040639C093B63E0F3
+:10711000062B83E02000849C860064B8003083E561
+:107120001E000010FF03809C0020A3E50400001057
+:107130008200A3B8000064A88200A3B88000809CED
+:107140004000609C0228C3E0002026E403000010F9
+:107150000000E09C0100E09C4000859CC000609C19
+:107160000018A4E40800001000380AD80020801895
+:10717000000084A82000A09C00206BE05EFEFF03BE
+:10718000002803D800208018000084A800206BE0AD
+:1071900059FEFF03003003D8E8FFFF03000066A894
+:1071A000340000100000809C007884E53100000C61
+:1071B0000000A09D01006018CC3263A8CC09599D45
+:1071C000001879E10040E01A8064F7AA0040A01A94
+:1071D0008054B5AA0040601A006473AA0040201AC7
+:1071E000005431AAFFFFEA8C0100AD9DFBFF8A8CA1
+:1071F0000800E7B8FFF66A8C080084B803F70A8D28
+:10720000003863E0FBF62A8D100008B90300AA8C51
+:10721000002029E1004063E00000CB841800A5B8FD
+:107220000C004A9DF8FFEB840100C6A4002863E02F
+:10723000FCFF8B840100E7A40100C6B8004811D40C
+:10724000010084A4003813D4003084E0001815D461
+:107250000400739E002017D40400B59E0400F79E1E
+:107260000400319E00788DE5DFFFFF130C006B9D5D
+:107270000000218504004185080081850C00C1853E
+:107280001000018614004186180081861C00C1860A
+:10729000004800442000219CFCFF219C004801D4B0
+:1072A0002FFDFF0700000015000021850048004465
+:1072B0000400219CE8FF219C004801D4045001D423
+:1072C000086001D40C7001D4108001D4149001D452
+:1072D00000408018040484A80000C3A9000044866C
+:1072E00000406018200363A80200409D0000A384B2
+:1072F00004008018108984A80100609CFF00A5A4E8
+:10730000001804D40800801804E284A800200EE2CB
+:10731000FF00E09C003805E40A00000C0000809C9F
+:107320000040C0182003C6A800006684FF00849CAB
+:10733000FF00A3A4003805E4FCFFFF1301004A9DF1
+:107340000040C0182003C6A8002884E0000066841E
+:107350000000809DFF00A3A4FF00E09C003805E42E
+:107360000800000C01004A9D00006684FF008C9D0F
+:10737000FF00A3A4003805E4FCFFFF1301004A9DB1
+:107380000000609C001810D41200609C001844E4B7
+:107390009500001000288CE1020064B804008018F9
+:1073A000547684A8002063E0000083840020004419
+:1073B000000000157D02000400006EA804006018A3
+:1073C000108963A80000809C0000A384002025E4AD
+:1073D0008F00000C03006CB80000809C025863E032
+:1073E000FF00A3A4002005E41900001000604AE19A
+:1073F000430005B9FF00C8A4003084E50A00000C72
+:10740000030068B80040E0182003E7A80000678484
+:107410000100849C003084E5FDFFFF13030068B881
+:107420000000809C021865E0FF00A3A4002005E492
+:10743000070000101F0065A400408018000384A806
+:10744000020063B8002063E0000083840090AAE596
+:107450006F00000C01004A9D00406018200363A8E3
+:10746000000083848000609CFF00A4A4001825E431
+:10747000A8FFFF13000000156500000000000015C4
+:10748000B902000400006EA804006018108963A807
+:107490000000809C0000A384002025E4D0FFFF139F
+:1074A00003006CB85A0000000000001542010004FF
+:1074B00000006EA8C9FFFF0303006CB800006CA8B1
+:1074C000F300000400008EA8C4FFFF0303006CB8A3
+:1074D00000006CA81C01000400008EA8BFFFFF0381
+:1074E00003006CB800006CA8FC00000400008EA82B
+:1074F00004006018108963A80000809C0000A38429
+:10750000002025E4B6FFFF1303006CB84000000024
+:10751000000000156301000400006EA8AFFFFF0328
+:1075200003006CB88101000400006EA8ABFFFF03EC
+:1075300003006CB83E00000400006EA8A7FFFF0324
+:1075400003006CB8BD00000400006EA8A3FFFF0399
+:1075500003006CB83900000400006EA89FFFFF0311
+:1075600003006CB85500000400006EA89BFFFF03E9
+:1075700003006CB87300000400006EA897FFFF03BF
+:1075800003006CB8B201000400006EA893FFFF0373
+:1075900003006CB8B401000400006EA88FFFFF0365
+:1075A00003006CB8B601000400006EA88BFFFF0357
+:1075B00003006CB8BF01000400006EA887FFFF0342
+:1075C00003006CB8CA01000400006EA883FFFF032B
+:1075D00003006CB8D301000400006EA87FFFFF0316
+:1075E00003006CB800006CA8D501000400008EA850
+:1075F00004006018108963A80000809C0000A38428
+:10760000002025E476FFFF1303006CB800002185FD
+:1076100004004185080081850C00C18510000186A9
+:1076200014004186004800441800219C0000609D21
+:107630000048004400000015F4FF219C004801D4DC
+:10764000045001D4086001D4000043A9B20300042F
+:107650000000809DB003000400006AA8004080186C
+:10766000040384A800006AA80000A4840000C48465
+:107670000000E4840000A484006005E4040000101D
+:1076800000000015A4030004000000150800801885
+:1076900004E284A800206AE0000083840400849D42
+:1076A00000006CA900002185040041850800818547
+:1076B000004800440C00219CF4FF219C004801D4A8
+:1076C000045001D4086001D4000083A9920300048F
+:1076D0000000409D01006B9D00588AE50E00000CE3
+:1076E0000000A09C0040E0180403E7A80040C01878
+:1076F0004003C6A80000678421004A9D0100A59CA4
+:107700000000668400008684005885E5FAFFFF13B8
+:10771000000000150800801804E284A800206CE036
+:107720000000838400204AE100006AA9000021854E
+:107730000400418508008185004800440C00219C1C
+:10774000E8FF219C004801D4045001D4086001D412
+:107750000C7001D4108001D4149001D40040401A60
+:10776000040352AA6C030004000083A900006CA863
+:10777000690300040000C09D00007284007003E4EF
+:10778000050000100000001500406018000363A809
+:1077900000008384000092840000609C001804E4D0
+:1077A000080000100200C09D000092840040601894
+:1077B000400363A80300C09D000083840000A384ED
+:1077C00000006CA8540300040000409D00588AE5A6
+:1077D0000C00000C00000BAA00006CA84E03000473
+:1077E0000100CE9D00006CA84B03000401004A9DDF
+:1077F0000000728400808AE5F9FFFF1300006CA886
+:107800000800801804E284A800206CE00000838453
+:107810000020CEE100006EA9000021850400418512
+:10782000080081850C00C185100001861400418686
+:10783000004800441800219CF8FF219C004801D416
+:10784000045001D434030004000043A932030004AF
+:1078500000006AA80300809C0020ABE50400001033
+:1078600000006AA82C03000400000015080080181E
+:1078700004E284A800206AE00000638500002185FE
+:1078800004004185004800440800219C0000C3A872
+:107890000000609D00188BE50900000C0000A09C12
+:1078A0000040E0182003E7A8000067840100A59CC1
+:1078B000003085E5FDFFFF1308006B9D0800A01850
+:1078C00004E2A5A8002864E00000838400206BE1A6
+:1078D00000480044000000150000A3A80000C09C60
+:1078E0000F00609C001845E5060000100000609D38
+:1078F00004006018108963A811000000005803D428
+:1079000000288BE50900000C000000150040E0187D
+:107910002003E7A8000067840100C69C002886E5D4
+:10792000FDFFFF1308006B9D0800A01804E2A5A846
+:10793000002864E00000838400206BE100480044DC
+:107940000000001500400019200308A90000E3A86A
+:107950000000A8840100C09CFF00A5A4FF00609C5B
+:10796000001825E4050000100800609D00006884F0
+:107970000200C09C1000609D003886E50700000CE6
+:107980000000A8A8000065840100C69C003886E5B8
+:10799000FDFFFF1308006B9D0800A01804E2A5A8D6
+:1079A000002864E00000838400206BE1004800446C
+:1079B00000000015E8FF219C004801D4045001D4C8
+:1079C000086001D40C7001D4108001D4149001D44B
+:1079D000000043A9D00200040000809D0040601810
+:1079E000040363A800008384006024E41E000010E8
+:1079F00000006AA8C80200040200409E0000CBA953
+:107A00000000009E00006AA80000A09C00704CE5E9
+:107A1000030000100000809C0100A09C00904CE539
+:107A200004000010032085E00100809C032085E015
+:107A3000008024E40C00000C01008C9DEA0200048C
+:107A400000000015E802000400006AA8E602000435
+:107A500000006AA8E402000400006AA8EBFFFF032C
+:107A600000006AA8AC02000400006AA808008018A0
+:107A700004E284A800206AE00000838500006CA96D
+:107A80000000218504004185080081850C00C18526
+:107A90001000018614004186004800441800219C13
+:107AA000F8FF219C004801D4045001D49A0200043C
+:107AB000000043A9020060185C6763A80200C018B8
+:107AC0006C5CC6A800188AE00040A0180403A5A8B2
+:107AD000000064840800801804E284A800204AE1C1
+:107AE000003083E00200C018645CC6A8005804D4CB
+:107AF000003063E00100809C002003D400008584F6
+:107B00000000658400006A8500406018080363A8CF
+:107B100004006B9D000083840000218504004185E2
+:107B2000004800440800219CDCFF219C004801D44F
+:107B3000045001D4086001D40C7001D4108001D429
+:107B4000149001D418A001D41CB001D420C001D4D9
+:107B500000408018040384A8000083A90000C486A4
+:107B60000100409D020080185C6784A86A0200043E
+:107B70000020C3E10000AE8402002019F45B29A9B3
+:107B80000200C018C45BC6A8004805E10030E5E06B
+:107B900002002019EC5B29A9000007870048C5E016
+:107BA00000006AA80400299D000006860048A5E0A0
+:107BB00000008CA80000458600008886AFADFF0756
+:107BC00000B007D40800801804E284A800006E8486
+:107BD00000208CE10200A018F45BA5A80200E018C8
+:107BE000C45BE7A80028C3E0003883E00200201946
+:107BF000EC5B29A92C00E79C0048A3E000C004D45A
+:107C0000003863E0008005D4009003D400A006D4BF
+:107C100000504BE100006C8400184AE100006AA9A2
+:107C20000000218504004185080081850C00C18584
+:107C30001000018614004186180081861C00C18650
+:107C400020000187004800442400219C080080187F
+:107C500004E284A8002063E000006385004800443B
+:107C6000000000150800801804E284A8002063E0EA
+:107C7000000063850048004400000015F8FF219CC7
+:107C8000004801D4045001D423020004000043A999
+:107C90000800601804E263A800184AE100006A8541
+:107CA0000000218504004185004800440800219C13
+:107CB000F8FF219C004801D4045001D416020004AE
+:107CC000000043A91402000400006AA8080060181C
+:107CD00004E263A800184AE100006A8500002185DB
+:107CE00004004185004800440800219CF8FF219CC5
+:107CF000004801D4045001D407020004000043A945
+:107D00000800601804E263A800184AE100006A85D0
+:107D10000000218504004185004800440800219CA2
+:107D200004006018108963A80000809C002003D420
+:107D30000000609D00480044000000150000A3A85A
+:107D40000000C09C0F00609C001845E50600001074
+:107D50000000609D04006018108963A811000000F5
+:107D6000005803D400288BE50900000C0000001522
+:107D70000040E0182003E7A8000067840100C69CCB
+:107D8000002886E5FDFFFF1308006B9D0800A01882
+:107D900004E2A5A8002864E00000838400206BE1D1
+:107DA0000048004400000015ECFF219C004801D46D
+:107DB000045001D4086001D40C7001D4108001D4A7
+:107DC000000003AA0000809DD30100041F00C09D95
+:107DD0000070ABE40C00000C01006BB802008018CE
+:107DE000606784A8005863E00A0063B8001870E078
+:107DF000002043E100008A84006024E407000010B2
+:107E000000006AA80000609D04006018108963A843
+:107E10004E000000005803D45DF2FF07000090A858
+:107E200090086A84006003E42000001000000EA99E
+:107E30009408CA840000A09C0000E09C0000809C84
+:107E4000003045E4030000100000609C0100809CAD
+:107E5000004045E404000010031864E00100609C49
+:107E6000031864E0003823E41000000C0100A59C16
+:107E7000200A8A8400402019000329A90100649C7B
+:107E8000010084B81F0063A4020063B800208CE0E6
+:107E9000004863E00200849D000083840000638446
+:107EA000E8FFFF030000809C300A8A840000609C89
+:107EB000001804E4200000100000A09C340ACA84CA
+:107EC0001F00009D0000E09C0000809C003045E405
+:107ED000030000100000609C0100809C004045E40D
+:107EE00004000010031864E00100609C031864E0C3
+:107EF000003823E41000000C0100A59CC00B8A840C
+:107F000000402019000329A90100649C010084B8E5
+:107F10001F0063A4020063B800208CE0004863E007
+:107F20000200849D0000838400006384E8FFFF0357
+:107F30000000809C0800801804E284A8002070E003
+:107F40000000838400206CE100002185040041854D
+:107F5000080081850C00C18510000186004800449E
+:107F60001400219CFCFF219C004801D40000E3A9DF
+:107F70001800C09C08006018E87B63A80000209EE1
+:107F800000182FE1000089840000609D005824E45F
+:107F900006000010000006A904006018108963A8FC
+:107FA000A6000000005803D43C086484005803E491
+:107FB0000B0000100000E09C90086484005823E44B
+:107FC0000600001000000015300A6484005823E405
+:107FD0000400000C0000A09C0100E09C0000A09C9C
+:107FE000002807E40F00001000000015000089843D
+:107FF0003C086484002803E40B0000100000001516
+:1080000090086484002803E4850000100000001537
+:10801000280A6484240A84840100039D0100C49C0E
+:10802000000089840000A09C90086484002823E458
+:10803000060000101F0066A4300A6484002823E4B0
+:108040000C00000C1F0066A41F0088A4020063B887
+:10805000020084B80040A0180003A5A8004066E113
+:10806000002884E0002863E00000A3840000C484AA
+:10807000000069840000809CD40BA384002005E4E8
+:108080004800001000000015080080181CDC84A8BF
+:1080900004006B9D00206FE000408018100384A84E
+:1080A00000008484002003D4000064A80800809CA1
+:1080B000002043E40B0000100000E09C020063B8C5
+:1080C0000400A018A076A5A8002863E0000083841F
+:1080D00000200044000000150100209E0000E09CEC
+:1080E000008887E52F00000C000000150040C01834
+:1080F0000403C6A80000A09D0040201B080339AB64
+:108100000040E01A1803F7AA0040A01A2003B5AAFD
+:108110000000609E00006684006803E41D000010FB
+:1081200001006B9D0000798400400019140308A928
+:1081300013006B9D00006684000088840000668444
+:10814000000086840000A68400009584006803E493
+:108150001A000010000000150000778411006B9DCC
+:108160000000778400008884000069842C0A6384FE
+:10817000009803E4070000101F0063A4004080186B
+:10818000000384A8020063B8002063E00000838439
+:108190000100E79C008887E5DFFFFF130000001562
+:1081A0000800A01804E2A5A800286FE0000083845E
+:1081B0002200000000206BE100006684006803E4F8
+:1081C000EAFFFF1301006B9D00408018180384A88C
+:1081D00007006B9D0000648400006684006803E46F
+:1081E000E2FFFF13000000150000648407006B9D90
+:1081F00000006684006803E4DCFFFF130000001544
+:1082000000008884D9FFFF0305006B9DB4FFFF03C6
+:108210000200209EB2FFFF030300209E300A648408
+:10822000002803E47FFFFF1300000015C80B6484DF
+:108230007AFFFF03C40B84840000218500480044BA
+:108240000400219CECFF219C004801D4045001D47F
+:10825000086001D40C7001D4108001D40000609C2F
+:108260000040001A0C0810AA0000809D001810D4CD
+:1082700000406018484063A800008384180084B858
+:10828000980084B87E0044A500600AE47600000CE3
+:10829000FF0084A40400C0198084CEA90150609C12
+:1082A0008E67FF070000809C0000EE8408006018C5
+:1082B000ECE663A80000C09C001887E00800A01846
+:1082C0005CDCA5A800006484003010D4080080188D
+:1082D00060DC84A80028C7E00020A7E00100809CA3
+:1082E000002006D4032063E00000C09C006003E48B
+:1082F0000F000010003005D4080080187CE284A82C
+:10830000002067E000008384006004E4080000109F
+:108310000000809C0040A018380CA5A800006584CF
+:10832000002023E4FEFFFF1300000015004060184A
+:10833000180463A80000AE840800C01858E6C6A858
+:108340000400E09C000083840030A5E00040601839
+:10835000140463A80700849C0000C384430084B80D
+:108360000000A584002006E1022868E00038A3E5AB
+:1083700005000010024065E00038A3E50300000C92
+:1083800000000015000005A900006E840800801898
+:1083900054E684A80800A01850E6A5A80020C3E071
+:1083A0000028E3E000408018080484A80000A684A8
+:1083B0000000C09C0028A8E0003004D40200059D05
+:1083C00000008784004084E0C2CDFF07002007D46E
+:1083D0000000EE84080060188CE263A80100009D94
+:1083E0000018C7E000006684004023E40600001087
+:1083F000000000150800801890E284A8002067E0C3
+:10840000004003D4020060185C6763A80040201994
+:10841000444029A90018A7E0000089840000658471
+:10842000500084B80200A018E05BA5A8002863E013
+:108430000000A384002824E40300001000000015BD
+:10844000044007D4000086840000609C001824E4E7
+:108450002A000010000000150000698427000000B9
+:10846000000000150400C0198084CEA90800A018DF
+:1084700074E1A5A80000EE8404006018C47663A827
+:108480000028C7E00000A6840200A5B80800C018B4
+:108490008CE8C6A80030A5E00028E7E0A500A09C75
+:1084A0003668FF07002807D400008E840800C01833
+:1084B00028E9C6A80800601824E963A80030A4E0F1
+:1084C0000018C4E000406018280863A80000638416
+:1084D000001805D4004060182C0863A80800A018F4
+:1084E00020E9A5A800006384002884E0001806D4D1
+:1084F0006BFFFF03005004D4000021850400418578
+:10850000080081850C00C1851000018600480044E8
+:108510001400219C0000E3A80100809C004060182A
+:108520000C4063A80040A0181040A5A8002003D468
+:108530000000809C0000C584800066A4002003E445
+:10854000FDFFFF130000009D3F00A6A4004005E4CE
+:1085500009000010400066A41F0066A400408018B7
+:10856000000384A8020063B8002063E00000838455
+:10857000400066A4004003E4120000100100659C66
+:108580000800C01804E2C6A81F0063A40030E7E09A
+:10859000020063B8000087840040C0180003C6A82A
+:1085A0000100A5B8003063E0002884E00000C38427
+:1085B0000100849CFFFF669D09000000002007D495
+:1085C0000800601804E263A8480066B9001887E054
+:1085D00000006484002863E0001804D400480044CC
+:1085E00000000015000003A90300809C00406018F3
+:1085F0000C4063A80040A0181040A5A8002003D498
+:108600000000809C0000658580006BA4002003E4CE
+:10861000FDFFFF133F00CBA40000E09C003806E400
+:108620000900001040006BA41F006BA400408018DC
+:10863000000384A8020063B8002063E00000838484
+:1086400040006BA4003803E431000010010086B83C
+:108650000800601804E263A80018A8E00000658420
+:10866000002063E00100639C1F00809C0020A6E5C1
+:1086700016000010001805D400406018040363A819
+:108680000100A09C0000838400406018000363A8E0
+:1086900000008384002824E4060000100000001578
+:1086A0000080601900006BA9200000000000001588
+:1086B0000800801814E284A80000609D002068E093
+:1086C0001A000000002803D40100669C00408018B6
+:1086D000000384A81F0063A4020063B8002063E0C5
+:1086E00000008384FFFF849C010064A4003803E43D
+:1086F00004000010410064B80C0000000100639DFC
+:10870000410064B909000000025860E108006018E7
+:1087100004E263A888006BB9001888E00000648454
+:10872000003063E0001804D4004800440000001545
+:108730000048004400000015000003A90000E4A860
+:108740000000609C001845E527000010000085A887
+:108750009F0065B8052083E00000A784021884E02C
+:10876000022085E0000068840220A3E00000809CD5
+:108770000020A5E5180000100000001503000019F6
+:10878000E86E08A99F0085B8052864E00220E3E0B0
+:10879000004067E4170000100000609D080080188A
+:1087A0000CE284A8002066E0000083840020A7E596
+:1087B000100000100000609C0018A5E504000010E7
+:1087C000000000150B0000000200609D0900000081
+:1087D0000100609D06000019D0DD08A9EBFFFF0332
+:1087E0009F0085B800006784DFFFFF03002883E057
+:1087F00000480044000000154C0083840000A3A83A
+:10880000B001E09C0040601880C163A80040C0181F
+:1088100010C1C6A8003803D40000609C001824E4EE
+:10882000100000100000001550008584001824E49A
+:1088300008000010000000150040601820C163A867
+:108840000800809C002003D40A00000000000015EE
+:108850000040601820C163A8FBFFFF030000001563
+:108860000F00E09C5000A584003806D4002806D4F0
+:108870000048004400000015FCFF219C004801D482
+:108880004C00A384B501809C0040601880C163A89F
+:10889000002003D40000809C002025E40600001086
+:1088A0002211809C0040601834C163A805000000BC
+:1088B000000000150040601834C163A82215809C98
+:1088C000002003D4330F000400000015004060189E
+:1088D00080C163A80001809C002003D40000218592
+:1088E000004800440400219CFCFF219C004801D466
+:1088F0002001A09C0040801880C184A80000C3A86B
+:10890000002804D44C0063840000A09C002823E4C9
+:1089100028000010000000150040601864C163A822
+:1089200001000019119108A9004003D43402068502
+:108930000040601840C163A80040A01834C1A5A839
+:10894000004003D40040E01804C1E7A800406018CC
+:108950000CC163A80500009D6C008684004003D410
+:10896000010084A4440066840100009D001805D421
+:1089700048006684004007D4C401C684001805D4AA
+:10898000004060181CC163A85000A09C002803D4BC
+:10899000003007D40000609C004007D4001824E495
+:1089A0000B00000C00000015090000000000009DF5
+:1089B0000040601864C163A811008018119184A858
+:1089C000002003D4DBFFFF0334020685004007D4F8
+:1089D0000040601810C163A80000809C002003D4F0
+:1089E000EC0E000400000015000021850048004442
+:1089F0000400219CF0FF219C004801D4045001D4C4
+:108A0000086001D4000083A9B601A09C0040601852
+:108A100080C163A8000044A9002803D40300609C1F
+:108A2000001824E4690000100100C09C0040601898
+:108A300008C163A8003003D434008C840000609C1B
+:108A4000001824E40C00000C0C2001D40040C018D5
+:108A500004C1C6A80000A09CFFFF649C0100809C8C
+:108A6000002006D4002823E4FCFFFF13000083A8A5
+:108A70000C1801D40040A01808C1A5A80100C09C92
+:108A800034026C840C00819C003005D46810000412
+:108A9000000000150C0061840040A01800C1A5A8CA
+:108AA0000040801804C184A8020063B82800CC8468
+:108AB000002863E0003003D40100609C001804D457
+:108AC0000300609C00182AE43D0000100100C09CD7
+:108AD0000000A09C002804D40300609C00180AE455
+:108AE000330000100100609C00182AE4050000100B
+:108AF0000000809C0040601804C163A8002003D4DB
+:108B0000C801AC84004060180CC163A80000809CC0
+:108B1000002803D49C00CC840800639C003003D45C
+:108B200000200AE42E00001000000015C401AC84EF
+:108B3000002025E41B00001000000015BC016C841F
+:108B40000C1801D40C008184004060180CC163A88B
+:108B5000002003D40200809C00202AE420000010A2
+:108B60000000609C001825E40A00001000000015B9
+:108B7000C0018C850C6001D40C00A18400406018F9
+:108B80000CC163A8002803D41500000000000015E4
+:108B9000C0016C840100639CF8FFFF030C1801D432
+:108BA000BC016C84E7FFFF030100639C790E0004A5
+:108BB000000000150A00000000000015003004D479
+:108BC000C7FFFF030300609C0040601808C163A852
+:108BD000002003D49AFFFF0334008C840000218519
+:108BE0000400418508008185004800441000219C54
+:108BF000FCFF219C004801D44400A3840000E3A8AA
+:108C0000000024A90F0065A40000809C002023E43C
+:108C1000080000100100C09C480067840F0063A496
+:108C2000002023E4040000100000609C0000C09CB1
+:108C30000000609C001826E462000010000000158F
+:108C4000180087840800609C001824E45D00001070
+:108C50000000609C1C0087840600609C001824E4CF
+:108C6000580000100000609C0100C09C004060188B
+:108C700058C163A82000809C0040001914C108A9B5
+:108C8000002003D4280087840040601820C163A816
+:108C9000002003D41000809C0700609C002008D4B2
+:108CA000001826E43700001000000015004080186E
+:108CB0000CC184A8001804D40000609C001829E4AA
+:108CC0002D000010000000150100609C001804D465
+:108CD0000040601848C163A803008018080084A8F9
+:108CE000002003D4004060180CC163A80040801825
+:108CF0001CC184A8004803D40200609C001804D45E
+:108D00000000609C001829E4110000108200A5B842
+:108D10000040601810C163A80200809C0040C01889
+:108D200024C1C6A8002003D4FFFFA59C4800878467
+:108D30000040601804C163A8002806D4820084B8EB
+:108D40000100A09C002803D4002006D49C00E784E6
+:108D50000040601814C163A80040801804C184A8B2
+:108D6000003803D40000609C001804D452000000B6
+:108D700000000015001804D4DBFFFF0300000015FD
+:108D8000004060180CC163A80040801804C184A88A
+:108D9000003003D49C00E7840400639C004804D4A2
+:108DA0000000809C002003D4003808D400406018E4
+:108DB00008C163A8002003D43F0000000000001594
+:108DC000001826E40E0000100000609C1800878444
+:108DD0000B00609C001824E4090000100000609C57
+:108DE0001C0087840900609C001824E40400001023
+:108DF0000000609C9EFFFF030200C09C001826E458
+:108E00000E0000100000609C180087841600609C13
+:108E1000001824E4090000100000609C1C008784F6
+:108E20001200609C001824E4040000100000609C04
+:108E30008FFFFF030300C09C001826E40E00001003
+:108E40000000609C180087842C00609C001824E4BB
+:108E5000090000100000609C1C0087842400609CB6
+:108E6000001824E4040000100000609C80FFFF0351
+:108E70000400C09C001826E40D0000105800609CFF
+:108E800018008784001824E479FFFF130700C09CB2
+:108E90001C0087844800609C001824E474FFFF13C2
+:108EA0000000001572FFFF030500C09C70FFFF0368
+:108EB0000700C09C00002185004800440400219C5C
+:108EC000ECFF219C004801D4045001D4086001D477
+:108ED0000C7001D4000083A9000024A9200263843F
+:108EE000000005A90100809C002023E46D00001013
+:108EF0000000C7A968026C843C02AC840A2B83E0A2
+:108F0000062B84E0022063E0101801D41000818455
+:108F10000000609C001824E4030000100000A09CE6
+:108F20000100A09C020069B8020088B80040E01867
+:108F300000C1E7A8003863E0003884E00100E09C4D
+:108F4000003803D4003004D40040601814C163A872
+:108F50009C008C840040E01804C1E7A8002003D4E2
+:108F6000002807D40100609C001825E44F00001081
+:108F70000000609C34008C84001824E40C00000C79
+:108F8000102001D40000C7A80000A09CFFFF649C33
+:108F90000100E09C000083A8003806D4002823E4E8
+:108FA000FBFFFF1300000015101801D40100A09C66
+:108FB0000040401908C14AA934026C841000819C09
+:108FC00000280AD41A0F0004000000151000618464
+:108FD0000040E01800C1E7A80000A09C020063B8B0
+:108FE00028008C84003863E0002003D40100E09C5A
+:108FF0000040801804C184A8004060180CC163A818
+:10900000003804D4C8018C8400700AD4002003D432
+:1090100000280EE42500001000000015C401CC84D7
+:10902000002826E41B00001000000015BC01AC84E1
+:10903000102801D41000E184004060180CC163A81E
+:109040000200809C003803D400202EE4170000109A
+:109050000000609C001826E40A00001000000015C3
+:10906000C0018C85106001D410008184004060181C
+:109070000CC163A8002003D40C0000000000001500
+:10908000C0016C840100639CF8FFFF03101801D439
+:10909000BC016C840100639CE7FFFF03101801D43E
+:1090A0009BFFFF03102001D40000218504004185AF
+:1090B000080081850C00C185004800441400219CF3
+:1090C0000040A01844C1A5A80100C09C003005D4F0
+:1090D0000040C01814C1C6A82400A384002006D4F0
+:1090E0009C0063840040801808C184A8002804D430
+:1090F000001806D40048004400000015D8FF219C49
+:10910000004801D4045001D4086001D40C7001D48B
+:10911000108001D4149001D418A001D41CB001D443
+:1091200020C001D4000043A9000024A920026384C8
+:10913000000005AA000046AA0000C7AAFF0008A771
+:109140000100809C002023E4860100100700C09DE0
+:1091500068026A843C02AA840A2B83E0062B84E01E
+:10916000022063E0241801D4240081840000609C64
+:10917000001824E4030000100000809E0100809E7F
+:10918000020069B80040801800C184A80100C09C9A
+:10919000002063E00040801824C584A8003003D478
+:1091A000000064840000809C080083A500200CE47B
+:1091B00019000010020070B838036A840030A3E080
+:1091C00008038A840600609C001824E457010010FC
+:1091D000382B0AD434036A8424038A84002863E089
+:1091E0000000A3A8002083E544010010241801D446
+:1091F0000800C09D000065A888008A84F176FF07FA
+:109200000000AEA80700609C00180EE45701000C97
+:10921000020070B80040C01800C1C6A80040801805
+:1092200024C584A8003063E0009003D40000648467
+:109230000000809C080083A500200CE419000010A9
+:109240000000001538036A840100A39C08038A8487
+:109250000600609C001824E41A010010382B0AD480
+:1092600034036A8424038A84002863E00000A3A8EE
+:10927000002083E507010010241801D40800C09DD8
+:10928000000065A888008A84CE76FF070000AEA89B
+:109290000700609C00180EE43501000C00006EA968
+:1092A0009C00CA840040601814C163A80040A01844
+:1092B00004C1A5A8003003D400A005D40100609C1F
+:1092C000001834E4800000100000609C34008A84A0
+:1092D000001824E40B00000C242001D40000C5A8D1
+:1092E0000000A09CFFFF649C0100809C002006D42D
+:1092F000002823E4FCFFFF13000083A8241801D4F6
+:109300000100C09C0040A01808C1A5A834026A84CE
+:109310002400819C003005D4450E00040000001597
+:10932000240061840040801800C184A8020063B852
+:109330002800CA84002063E00040801824C584A867
+:10934000003003D4000064840000809C080083A5E2
+:1093500000200CE4190000100000001538036A8496
+:109360000100A39C08038A840600609C001824E482
+:10937000BA000010382B0AD434036A8424038A8488
+:10938000002863E00000A3A8002083E5A7000010E8
+:10939000241801D40800C09D000065A888008A84B4
+:1093A0008876FF070000AEA80700609C00180EE456
+:1093B000EF00000C00006EA90040601804C163A813
+:1093C0000100C09C0040801808C184A8003003D46C
+:1093D00000B004D40800639CC8018A84002003D430
+:1093E0000040801824C584A8000064840000809C8C
+:1093F000080083A500200CE4190000100000609C08
+:1094000038036A840030A3E008038A840600609C65
+:10941000001824E477000010382B0AD434036A843F
+:1094200024038A84002863E00000A3A8002083E5C9
+:1094300064000010241801D40800C09D000065A835
+:1094400088008A845F76FF070000AEA80700609C52
+:1094500000180EE4C500000C0000609C001816E423
+:109460001900001000000015C401AA84001825E4AA
+:109470005000001000000015BC01CA84243001D443
+:1094800024008184004060180CC163A8002003D42C
+:109490000200809C002036E40B0000100000609C5D
+:1094A000001825E43F00001000000015C001CA8428
+:1094B000243001D424008184004060180CC163A8CA
+:1094C000002003D40040601824C563A800008384F2
+:1094D0000000609C080084A500180CE4A4000010A3
+:1094E00000006EA938036A840100A39C08038A84E3
+:1094F0000600609C001824E41C000010382B0AD4DD
+:1095000034036A8424038A84002863E00000A3A84B
+:10951000002083E509000010241801D40800C09D34
+:10952000000065A888008A842676FF070000AEA8A0
+:109530008F00000000006EA9020085B80C036A8449
+:109540000080C0180000C6A81C03AA84002863E09D
+:10955000001884E0003084E000008484242001D4DA
+:10956000F0FFFF030000A4A83E66FF0700000015FF
+:109570008800CA84CC01AA9C00406018002063A81F
+:1095800040004A8500008CA80000E6A8005003D4E3
+:10959000AC75FF07000078A8740000000000CBA99C
+:1095A000C0016A840100639CC3FFFF03241801D437
+:1095B000BC016A840100639CB2FFFF03241801D43C
+:1095C000020085B80C036A840080C0180000C6A899
+:1095D0001C03AA84002863E0001884E0003084E0C3
+:1095E00000008484242001D495FFFF030000A4A878
+:1095F0001C66FF070000001540008A8400406018C8
+:10960000002063A8CC01AA9C8800CA84002003D44F
+:109610000000E6A800008CA88A75FF07000078A863
+:109620008BFFFF030000CBA9020085B80C036A84FE
+:109630001C03AA84002863E0001884E000806018FE
+:10964000000063A8001884E000008484242001D472
+:1096500052FFFF030000A4A80266FF0700000015E8
+:1096600040008A8400406018002063A8CC01AA9CB6
+:109670008800CA84002003D40000E6A800008CA85B
+:109680007075FF07000078A848FFFF030000CBA912
+:109690001C03AA84020063B80C038A84002884E0B7
+:1096A000002063E000808018000084A8002063E0B0
+:1096B00000008384242001D4F2FEFF030000A4A84C
+:1096C000E865FF070000001540008A84004060182C
+:1096D000002063A8CC01AA9C8800CA84002003D47F
+:1096E0000000E6A800008CA85675FF07000078A8C7
+:1096F000E8FEFF030000CBA91C03AA84020063B8A4
+:109700000C038A84002884E0002063E00080801835
+:10971000000084A8002063E000008384242001D49A
+:10972000B5FEFF030000A4A8CE65FF0700000015EA
+:1097300040008A8400406018002063A8CC01AA9CE5
+:109740008800CA84002003D40000E6A800008CA88A
+:109750003C75FF07000078A8ABFEFF030000CBA913
+:1097600082FEFF03242001D400006EA900002185A1
+:1097700004004185080081850C00C1851000018628
+:1097800014004186180081861C00C18620000187D4
+:10979000004800442800219CE8FF219C004801D497
+:1097A000045001D4086001D40C7001D4108001D49D
+:1097B000149001D40040C01844C1C6A80100E09C28
+:1097C000000043A9003806D4000004AA0040C018D5
+:1097D00024C5C6A8FF0045A60000E6840000609CE2
+:1097E000080087A500180CE4180000100700C09DB1
+:1097F00038036A840100A39C08038A840600609CE5
+:10980000001824E458000010382B0AD434036A846A
+:1098100024038A840028A3E0002085E54800001086
+:10982000020085B80800C09D000065A888008A84F1
+:109830006475FF070000AEA80700609C00180EE4E6
+:109840005800000C00006EA90040801814C184A8C4
+:109850002400AA840040601808C163A8008004D4D2
+:109860009C00EA84002803D40040601824C563A843
+:10987000003804D4000083840000609C080084A5A4
+:1098800000180CE44700001000006EA938036A8439
+:109890000100A39C08038A840600609C001824E44D
+:1098A00019000010382B0AD434036A8424038A84F4
+:1098B0000028A3E0002085E509000010020085B81B
+:1098C0000800C09D000065A888008A843D75FF07D8
+:1098D0000000AEA83300000000006EA90C036A84EB
+:1098E0001C03AA84002863E0001884E0008060184C
+:1098F000000063A8001884E00000A484F3FFFF03C5
+:10990000000065A85765FF07000000158800CA849D
+:10991000CC01AA9C00406018002063A840004A8542
+:1099200000008CA80000E6A8005003D4C574FF070F
+:10993000000072A81A0000000000CBA90C036A8482
+:109940001C03AA84002863E0001884E000806018EB
+:10995000000063A8001884E00000A484B4FFFF03A3
+:10996000000065A83F65FF070000001540008A84DD
+:1099700000406018002063A8CC01AA9C8800CA841B
+:10998000002003D40000E6A800008CA8AD74FF07F7
+:10999000000072A8A9FFFF030000CBA900006EA978
+:1099A0000000218504004185080081850C00C185E7
+:1099B0001000018614004186004800441800219CD4
+:1099C000E0FF219C004801D4045001D4086001D478
+:1099D0000C7001D4108001D4149001D418A001D4CB
+:1099E0001CB001D4FF0003A6000084A90000609C05
+:1099F0000600D0B93C1B04D40C1B04D4101B04D4A7
+:109A00000040C0186420C6A800408018402084A8E8
+:109A10000030AEE000206EE00000E09C0000838497
+:109A20000000C09E0600609D500084B80000A58420
+:109A30000C00609C070084A4143B0CD4181B0CD4AD
+:109A4000102A0CD41C3B0CD4203B0CD4243B0CD44B
+:109A5000281B0CD42C3B0CD4303B0CD4343B0CD402
+:109A6000005824E43500001008230CD40000C5A8D9
+:109A70000080E018A400E7A8004080184C2084A8CB
+:109A8000003866E000202EE1000063840040A0184A
+:109A90005820A5A800808018A80084A800284EE1BE
+:109AA0000C1B0CD40020A6E000806018AC0063A85A
+:109AB0000000A5840018E6E00000E784008060183C
+:109AC0002C0063A8102B0CD4143B0CD40040A0181D
+:109AD0006820A5A80C038C8400280EE10080E01803
+:109AE0000800E7A80018C6E00038A4E00000A5843C
+:109AF000FF7FE018F8FFE7A8040065B8202B0CD41E
+:109B00001400639C001884E01C1B0CD40038A4E0F3
+:109B1000FF7F6018FCFF63A80000A584001884E0A4
+:109B200000008484002009D4242B0CD400B00AD473
+:109B300000B008D400B006D400408018442084A8A7
+:109B40000040A0185020A5A808030C8500004BA9D0
+:109B500000208EE200284EE2005028E4260000108B
+:109B6000000070A80C038C840080E0180000E7A8B7
+:109B70000040C0185420C6A81C036C8400300EE1BD
+:109B8000001864E01803AC84003863E000006384CC
+:109B9000002884E0001814D40038C4E01002AC841B
+:109BA0000000C684003012D40080C0180400C6A88B
+:109BB000003064E00030E5E000006384001808D461
+:109BC00000806018080063A80018C4E00000C68484
+:109BD0002800639C003007D40018A5E00080C0185E
+:109BE0000C00C6A8003084E000008484002005D466
+:109BF000000070A8BE00000400008CA80803EC84DC
+:109C00000000A09C005027E403000010000007A9FA
+:109C10000100A09C0700609C00182BE403000010CA
+:109C20000000809C0100809C032085E00000609C77
+:109C3000001804E4200000100600609C18036C84E7
+:109C40000100209D2C038C841000639C004884E05C
+:109C50006402AC84181B0CD4004825E40F000010EB
+:109C60002C230CD438036C841C038C84020063B84E
+:109C70002803AC84001884E03003CC840018A5E0ED
+:109C80000400849C2800A59C0048C6E01C230CD43A
+:109C9000282B0CD430330CD42C038C8420036C84FC
+:109CA000001884E574000010000000150000C9AA27
+:109CB0000600609C001807E4030000100000A09C50
+:109CC0000100A09C0100609C001836E40300001015
+:109CD0000000809C000083A8042085E00000609CB8
+:109CE000001824E4050000100800609C00180BE434
+:109CF0009AFFFF0F000000150600609C001827E483
+:109D00006C0000100800609C00182BE41700001085
+:109D10000000209D70036C844C02CC84003023E44E
+:109D20005300000C0400E09C70038C9C0100299DF2
+:109D30003000849C0038A9E54B00000C0100A9B854
+:109D400000006484003023E4F9FFFF1300000015D5
+:109D5000004865E0FF7FE018FFFFE7A8040063B854
+:109D6000006063E0703B03D410034C8500806018F2
+:109D7000000063A800808018080084A80C036C858C
+:109D80000018CAE00020EAE000186BE02803AC8469
+:109D90000000209D0000638400288AE0001806D49B
+:109DA00024030C85005065E03003CC84003007D4D8
+:109DB0000080E0180000E7A83403CC84003884E079
+:109DC0002C03EC84023008E1003804D400808018B1
+:109DD000040084A8002063E00800859C004003D4B0
+:109DE000004089E51300000C28230CD41C036C846C
+:109DF0000080C0180000C6A80000A4A800186BE0EE
+:109E0000005084E0003063E00030C4E00000838450
+:109E10000400A59C0100299D002006D40400639C39
+:109E2000004089E5FAFFFF130400C69C282B0CD4E0
+:109E30003C03AC840080E0180400E7A8000090A870
+:109E400028038C8500386AE00000C09C006003D4C1
+:109E50000000E09CF463FF070E00609C150000000A
+:109E600000000015BCFFFF03004865E0B9FFFF03D9
+:109E70000000A09C2403CC843403AC84022866E058
+:109E800028038C84020063B8001884E0003065E584
+:109E90009AFFFF132800849C14036C84002083E540
+:109EA00084FFFF0F0600609C95FFFF030000001574
+:109EB00000408018402084A8FFFFA0A800206EE08A
+:109EC000002803D400002185040041850800818515
+:109ED0000C00C1851000018614004186180081869F
+:109EE0001C00C186004800442000219CE0FF219C0A
+:109EF000004801D4045001D4086001D40C7001D48E
+:109F0000108001D4149001D418A001D41CB001D445
+:109F10004C024485000084A90000C09C00408018C9
+:109F200044C584A80400A09CFF0003A6002804D414
+:109F300078320CD4D0320CD438330CD4D4320CD484
+:109F4000D8320CD4DC320CD4E0320CD4E4320CD451
+:109F5000E8320CD4EC320CD4F0320CD4FFFFC09DAC
+:109F60000000E09D00780AE4070000100700409E12
+:109F700064028C840100609C001804E40D00000C55
+:109F80000600D0B80600D0B80040E0184420E7A88A
+:109F90000040A0184C20A5A8003866E0002886E004
+:109FA0000000638400008484CC190CD488200CD475
+:109FB0000040E0185020E7A80040A0185420A5A8B1
+:109FC000003866E0002886E0000063840800E79C13
+:109FD0000100409D000084840038A6E0E4210CD4F8
+:109FE0000000C58600408018642084A8E0190CD4C5
+:109FF0000040A0186820A5A8002066E008036C8631
+:10A00000002886E0000063840000E485101A0CD468
+:10A010004E008FB85F006FB8035084E2005033E405
+:10A02000B305000C7C1A0CD41002AC850000209EF5
+:10A0300000880DE4310000100000ADAA005033E4A8
+:10A0400054050010000000150080C0182800C6A8A4
+:10A050000080E0183400E7A800306DE00080A01810
+:10A06000A000A5A80000E38500388DE000282DE1C0
+:10A0700000806018700063A80000848450006FB9ED
+:10A080004300AFB84100CFB800180DE101004FA563
+:10A090003C220CD40000E8850100A5A40300C6A45E
+:10A0A00046006FB8000089843F000FA53F0063A4FD
+:10A0B0006C00EC84010084A40100E7A4145A0CD4C1
+:10A0C000182A0CD41C320CD420520CD470420CD45C
+:10A0D000741A0CD4008827E42605001090210CD4B3
+:10A0E000F48A0CD40080A0183000A5A8002875E0E0
+:10A0F000000063842C1A0CD4CC010C85004060183D
+:10A100007CC063A888008C840B00E8B85F00C4B8EA
+:10A11000003803D48B00A4B800406018140663A86C
+:10A12000003084E0004003D4810084B8004060180F
+:10A1300000C063A80030A5E0002003D48100A5B8CA
+:10A140000020E7E00040601880C063A8002808E114
+:10A15000003803D400408018180684A80100C09C71
+:10A16000004004D400406018140B63A8004080181D
+:10A17000000884A8003003D40200E09C003004D41E
+:10A1800000406018040863A83800849C003803D499
+:10A190000800A09C0000609C0000E09C001804D413
+:10A1A000004060183CC563A80900809C002003D4CF
+:10A1B0000040801808C084A80040601810C063A840
+:10A1C000003004D4003003D40040801860C084A85C
+:10A1D0000040601888C063A8002804D40D00C09C0B
+:10A1E0000040801854C084A8003003D49000AC8490
+:10A1F0000040601828C563A80100C09C003804D442
+:10A2000084008C842C01E09C002003D40040801842
+:10A210005CC084A800406018480863A8002804D4E3
+:10A22000003003D400408018DCD084A800406018BF
+:10A230001CD063A8003004D42100A09C003803D4B3
+:10A240000040801820D084A8AA00609C0200E09CF6
+:10A25000001804D40040601828D063A8004080187B
+:10A2600010D084A8003003D4002804D40000C09C7F
+:10A2700000406018D8D063A800408018609084A87F
+:10A28000003003D40600A09C003004D400406018C5
+:10A29000749063A80040801824D084A8003803D4A8
+:10A2A000003004D40040601850C563A80500809CAD
+:10A2B0000100E09C002003D4000047A90040801862
+:10A2C00054C584A81000639C002804D4003003D433
+:10A2D0001000849C0400C09C00406018100B63A810
+:10A2E000003004D40040A018040AA5A8003803D404
+:10A2F00054008C8400406018000A63A80000C09CD1
+:10A30000002003D4003005D4003824E404000010F9
+:10A3100000000015003805D4003005D40040601856
+:10A32000000063A8FB03E09CFF03A09C003803D45B
+:10A330000040801884C084A8002803D40000C09C7A
+:10A34000005004D4003004D4005033E44A04000C1C
+:10A350000800609C40038C84001824E43D01001038
+:10A360000B00809C3C230CD40040A018280BA5A80F
+:10A370000100609C00008584001824E405000010A2
+:10A380000600609C0000C09C003005D40600609C64
+:10A39000001813E42B01000C000000154000EC84B1
+:10A3A00000406018002063A80700809C003803D498
+:10A3B000002032E41E0100100000809C0040801844
+:10A3C00048C084A8D002AC8400006484430063B811
+:10A3D00000408018042084A8022863E0001804D4F8
+:10A3E0005402AC8400406018082063A864028C8486
+:10A3F000002803D40000A4A80400639C0040801837
+:10A4000014C084A800008484002003D40100809C30
+:10A41000002025E404010010000000150300C09C8A
+:10A4200000302EE4F00000100000609C0000C09D91
+:10A4300000406018102063A80100809C007003D4C5
+:10A44000002025E4DF0000100000809CE001CC84A7
+:10A450000400639C00408018182084A8E401EC8468
+:10A46000003003D4003804D40600409D005013E4AB
+:10A47000D000000C000000151002EC840000609C6D
+:10A48000001807E4150000100700609C08036C84A6
+:10A49000005003E4110000100700609C0080C01809
+:10A4A0000800C6A8008080180C0084A8003067E06F
+:10A4B0000020A7E00000C09C003003D4003005D489
+:10A4C000008060183C0063A80403AC84001887E097
+:10A4D000002804D40700609C001832E40B00001030
+:10A4E0000000E09D78028C849F0064B88800AC84F2
+:10A4F0005D0063B8001884E0830084B8092B64E031
+:10A50000062B63E00218E4E13C03CC849400609CD9
+:10A51000FFFF869C001844E4A300000C0000A6A8DE
+:10A5200008030C850100609C001828E49900000CC9
+:10A53000000090A860026C840000A09C002823E426
+:10A54000920000100000001564028C84002824E4AE
+:10A550008900000C000000150100609C001824E434
+:10A56000160000100700609C0000609C001807E4C3
+:10A57000120000100700609C0600609C001808E4B0
+:10A580000E0000100700609C00808018080084A85E
+:10A590005C026C840020A7E0010083B8001884E00E
+:10A5A000040084B85403849C00208CE00000848460
+:10A5B000002005D40700609C001832E46A000010F7
+:10A5C000000090A80000A6A80000CFA80500609C8D
+:10A5D0001562FF070000E09C64026C840100A09CEF
+:10A5E000002823E4460400100600609C08038C84C5
+:10A5F000001824E4030000100000C09C0000C5A85F
+:10A600000700609C001832E4030000100000809CEA
+:10A61000000085A8032086E00000609C001804E488
+:10A62000370400100000A09D10038C840080E01807
+:10A630000000E7A828036C8438032C85001824E266
+:10A640000200A9B8003891E05C02CC842800E59DA6
+:10A650000100299D3003EC84010066B80080A01839
+:10A660000400A5A8003804D4003063E0002891E07D
+:10A670000080C0180800C6A8007804D40030B1E0FB
+:10A68000E0018C84040063B8002005D47802EC84D7
+:10A690000080A0180C00A5A8006063E0002891E0ED
+:10A6A0009F00C7B8E401AC845D00C6B8002804D49C
+:10A6B0005403E38500808018100084A80030E7E090
+:10A6C0000020B1E00080C0181800C6A854028C8495
+:10A6D000008060181C0063A88300E7B8002005D440
+:10A6E0000080A0181400A5A8001891E0002811E12E
+:10A6F0000030B1E0007008D4007805D4003804D4EC
+:10A7000000808018200084A8002071E0004803D455
+:10A7100000488DE5FA03000C0C00C69C1C036C84F9
+:10A720000080E0180000E7A80C038C840030B1E042
+:10A73000001884E034036C84003884E00000E48571
+:10A740000100639C0100AD9D007805D40400849C49
+:10A7500000488DE5FAFFFF130400A59CE803000004
+:10A76000341B0CD40000A6A80D00609C99FFFF03C9
+:10A770000000C09C0000A6A8000090A80000CFA880
+:10A7800094FFFF030700609C74FFFF0364028C8446
+:10A790000900E09C403B0CD40000CFA88DFFFF03D4
+:10A7A0000400609C000090A8F1FFFF032000609C63
+:10A7B000B561FF070000001531FFFF031002EC84B4
+:10A7C00000406018142063A80000A09C002003D45F
+:10A7D00000408018182084A8002804D424FFFF0318
+:10A7E0000600409D00182EE40400001000202EE416
+:10A7F00010FFFF030000C4A9040000100200609CC9
+:10A800000CFFFF030200C09D00182EE4040000109E
+:10A810000000001507FFFF030000C6A905FFFF03A6
+:10A820000400C09D03FFFF03FFFFC09D00406018B0
+:10A83000042063A8002003D4EBFEFF035402AC8481
+:10A840008861FF0700000015D5FEFF0308036C8632
+:10A8500090006C84005023E4050000100200A09CCE
+:10A860000040601858C063A8002803D4005034E4A6
+:10A87000FD02000C000000150300609C001833E48A
+:10A88000080000100100E09DE0018C840000609C45
+:10A89000001824E403000010000000150000E09DF3
+:10A8A00060026C840100A09C002823E403000010D7
+:10A8B0000000C09C0000C5A800282FE40300001081
+:10A8C0000000809C000085A8032086E00000609CBA
+:10A8D000001804E4E20200100000A09D0400C09CE7
+:10A8E000FF7FA018FFFFA5A870038C9C0030ADE58A
+:10A8F0000C00000C0000001500006484002823E414
+:10A900000500000C000000153000849CF8FFFF03D8
+:10A910000100AD9D4C02CC84506A0CD4003004D4AC
+:10A920005002AC8600808018000084A8010075B831
+:10A930002C02AC8500A863E00320EDE0040063B8BE
+:10A94000E001CC84006083E0443304D40000A4A878
+:10A950000000C4A8E4018C844C2305D4000085A821
+:10A960002402AC84542B06D40000A6A80000C09C8E
+:10A97000583304D428028C845C2305D40000809CC6
+:10A98000002007E4A302001068B305D458008C84AB
+:10A990000100609C001804E404000010FF00809C8B
+:10A9A00090006DB8FF7F83A44C024C85FFFF6DA41F
+:10A9B00034220CD4381A0CD434026C8588026C848E
+:10A9C000005803E4180000100000A09CA4006C8450
+:10A9D0000100809C002023E41300001008280CD400
+:10A9E000AC026C84002023E4070000100000609C8F
+:10A9F000B8028C84001804E4030000100000001565
+:10AA0000A8200CD4A8006C840000C09C0A1B6BE03A
+:10AA10008C320CD490320CD498320CD49C320CD49E
+:10AA2000A01A0CD43802EC840000609C010095B898
+:10AA30000800AC841000CBB800A884E00038A5E082
+:10AA4000A41A0CD4095B05E18C026C84040084B860
+:10AA50000000209E003863E0006024E10000E09CDC
+:10AA60008C1A0CD4943A0CD400806018000063A8AF
+:10AA700008280CD40318EDE00100E09E0000A09D22
+:10AA8000065B68E0644309D40218E5E10478C6E097
+:10AA9000603309D4008807E421000010000000158D
+:10AAA000A4006C8400B823E41D0000100000001511
+:10AAB0008C026C8490028C840020A3E503000010BB
+:10AAC0000000E09D0220E3E1A002AC840028AFE496
+:10AAD0004E0200100000609C0100C09C94320CD417
+:10AAE00098026C84002884E00100639CA800EC8537
+:10AAF00090220CD4007823E409000010981A0CD49A
+:10AB00009C026C840000809C0100639C98220CD401
+:10AB10009C1A0CD4061B8BE090220CD494026C84FB
+:10AB2000006823E40600000C010075B8A4026C84E0
+:10AB30000100639CD8FFFF03A41A0CD43402AC8438
+:10AB400000A863E0A402CC84040063B8882A0CD473
+:10AB5000006063E06C3303D464006C84005023E431
+:10AB6000030000100100609C641A0CD464026C8421
+:10AB70000100809C002023E41D020010000000154D
+:10AB8000000044A9DC05000400006CA80000EC846F
+:10AB90000000CBA9005027E4030000100000A09C97
+:10ABA0000000AAA80300609C00182EE40300001017
+:10ABB0000000809C0100809C042085E00000609CD7
+:10ABC000001824E4090000100400609C00180EE442
+:10ABD0000600001000000015C0026C84005003E461
+:10ABE000F801000C0200609C58028C8454220CD4A2
+:10ABF0000000A09C70036C840000A09D5C2A0CD413
+:10AC00005402AC84002823E40B00000C0400C09C18
+:10AC100070038C9C0100AD9D0030ADE50600000C7A
+:10AC20003000849C00006484002823E4FAFFFF13B2
+:10AC30005C6A0CD40500609C00182DE4C70100106C
+:10AC40000000809CCC026C840100809C002023E4E6
+:10AC50001300000C0000C09CCC220CD464300CD437
+:10AC6000C4026C840100809C002023E4C6FFFF1313
+:10AC70000000E09C18220CD4C43A0CD4C03A0CD486
+:10AC800000200CD404380CD430380CD4350A00041D
+:10AC900000006CA8BCFFFF03000000150000E09C52
+:10ACA000643A0CD4603A0CD4A0006C840000809C00
+:10ACB000002023E40A00001000000015A4006C84AA
+:10ACC000002023E40600001000202EE49A0100106A
+:10ACD0000200609C6C026C849C180CD464028C840E
+:10ACE0000100609C001824E48A0100100100C09C4F
+:10ACF0005C028C84081864E080022C85002063E0EC
+:10AD000084020C85040063B8006083E06803A484B7
+:10AD1000000044A90000E4A84C036A84410085B8FF
+:10AD20006003C7840100A5A4010084A45000E6B814
+:10AD3000042829E16C036A85042008E1FFFFC6A40A
+:10AD40004403AA84E4190CD46403EA850200609CDD
+:10AD5000E0290CD4804A0CD484420CD428300CD482
+:10AD6000343A0CD400180EE403000010A45A0CD49A
+:10AD70002C780CD430006C8402186FE034180CD49A
+:10AD8000A4028C840000609C001824E45F01001081
+:10AD90000100C09C941A0CD4B801EC840000609CA3
+:10ADA000001827E457010010000000159402CC841D
+:10ADB000001826E45100000C000000150000609C03
+:10ADC000001826E4140000100100609C0100009DA2
+:10ADD000004027E410000010000000155C026C84A5
+:10ADE0000040A01800C5A5A8084083E0004005D495
+:10ADF000001884E00000609C040084B8001805D4AA
+:10AE0000006084E0FF7FA018FFFFA5A8702B04D48A
+:10AE10000100609C001806E404000010001807E41C
+:10AE20001400000C0100A09C44018C840000009DD3
+:10AE300098016C840218A4E0004065E5030000104E
+:10AE4000000000150000A09CA0016C8480018C848F
+:10AE5000022063E044290CD4004063E503000010A5
+:10AE6000A0190CD40000609CA0190CD40100A09C77
+:10AE7000002826E4070000100000609C88016C8414
+:10AE800098018C84002063E088190CD40000609C39
+:10AE9000001826E4060000100100609C002827E44A
+:10AEA0001200000C000000150100609C001826E450
+:10AEB0000600001000000015A4026C84FFFF639CD4
+:10AEC000B0FFFF03A41A0CD408036C865802AC84AC
+:10AED0000100659C4C024C85581A0CD401006A9CF8
+:10AEE00022FDFF034C1A0CD45D0D000400006CA879
+:10AEF000EEFFFF039402CC8420006C84007003E416
+:10AF000006000010000070A824006C840100639CFF
+:10AF100024180CD4000070A800008CA803020004C0
+:10AF20000000AEA80700609C00182BE4F30000109E
+:10AF300000004BAA90008C840100609C001804E47F
+:10AF4000EC0000100300609C08036C86001813E4FA
+:10AF50004000000C0600609C004060184CC063A8D4
+:10AF60004000A09C000083844300E4B90028AFE4C3
+:10AF70000C00000C00000015D0026C84004080180A
+:10AF800080C184A8FFFFE09C0400EF9D003804D43A
+:10AF90000028AFE4FCFFFF130400639CD01A0CD41C
+:10AFA0000040601858C063A80100809C0040801ACF
+:10AFB0002CC594AA002003D40040601824C563A8BF
+:10AFC000000083840000609C080044A500180AE487
+:10AFD000140000100000001538036C840100A39CCD
+:10AFE0000600609C001833E4B4000010382B0CD429
+:10AFF00034036C840028E3E124038C8400208FE474
+:10B00000A40000100200AFB80800409E88008C84A5
+:10B0100000006FA86B6FFF070000B2A808036C86E2
+:10B020000040601818C063A8000083840000609C82
+:10B03000100084A4001804E4E0FFFF131F00609CCC
+:10B040000000809C001814D4002014D40600609CDA
+:10B05000001833E4030000100000A09C0100A09C35
+:10B060000700809C002012E4030000100000609C98
+:10B070000100609C031865E00000C09C003003E400
+:10B080009F01000C002012E4030000100000A09CAF
+:10B090000100A09C0200609C00180EE40300001058
+:10B0A0000000809C0100809C032065E0003003E4E8
+:10B0B000750000100400E09C5802AC840000C09CA5
+:10B0C0000000A09D70036C84542A0CD4002823E453
+:10B0D0000C00000C5C320CD47003CC9C0100AD9DC4
+:10B0E0000038ADE50700000C3000C69C00008684E7
+:10B0F00054026C84001824E4F9FFFF135C6A0CD43A
+:10B100005C02CC84010066B8003063E0040063B8E0
+:10B11000006083E0000064A84C03848444036384DB
+:10B12000E4210CD4E0190CD4010066B8FF7F80182C
+:10B13000FFFF84A8003063E0040063B8006063E0B0
+:10B14000702303D40700809C002032E40300001029
+:10B150000000E09C0100E09C0200C09C00302EE456
+:10B16000030000100000809C0100809C042087E008
+:10B170000000609C001804E43A0000100300609C8A
+:10B180000100609C00182EE406000010000000156D
+:10B190008C006C8478008C84002063E08C180CD4C4
+:10B1A00038006C848C008C84FFFF639C002063E576
+:10B1B000030000100000E09C8C380CD434026C8436
+:10B1C00020700CD400302EE42C000010C81A0CD4CF
+:10B1D00010006C840100639C10180CD410008C8447
+:10B1E00064006C84001824E4030000100000C09C7C
+:10B1F0000100C09C0300609C00182EE403000010B6
+:10B200000000809C0100809C042086E00000609C7F
+:10B21000001804E4040000100100609C2C00CC84A1
+:10B2200030300CD400184EE4080000100000001567
+:10B2300014006C840C008C840100639C0100849CCD
+:10B2400014180CD40C200CD404006C840000E09C76
+:10B250000100639C00380CD404180CD40300609CDB
+:10B26000001833E41CFFFF130100659C0000609C84
+:10B2700018FFFF03601A0CD40000809CD8FFFF0366
+:10B2800010200CD45802AC84A8FFFF035C02CC84CD
+:10B290000C036C841C038C84002063E0001865E0C0
+:10B2A0000080A0180000A5A8002863E00000E38546
+:10B2B00058FFFF0388008C84EA5EFF07000000153A
+:10B2C0004000EC8400408018002084A8000070A892
+:10B2D0008800CC84CC01AC9C003804D400008AA83F
+:10B2E000586EFF070000E6A84DFFFF0300004BAAC1
+:10B2F0001AFFFF0308036C8655FFFF0308036C86E3
+:10B30000AFFEFF039402CC84A4FEFF0394320CD45E
+:10B310000040601800C563A80000E09C003003D422
+:10B3200008036C865802AC84003803D4EAFEFF039D
+:10B330000100659C00182EE40500001000000015B7
+:10B3400074028C8466FEFF039C200CD47002AC84D3
+:10B3500063FEFF039C280CD4002027E453FEFF1358
+:10B360000000001558006C84002023E44FFEFF13FA
+:10B37000000000155C028C84010064B8C802AC8433
+:10B38000002063E0040063B8006063E0600383941E
+:10B39000002005E445FEFF1334220CD4C0026C8467
+:10B3A0000100809C002023E4040000100000001530
+:10B3B0002CFEFF03C4220CD42AFEFF03C0220CD4AF
+:10B3C00000182EE406000010000000155802AC849E
+:10B3D000FFFF659C07FEFF03541A0CD45802AC848F
+:10B3E00064006C84FCFFFF03001865E000406018F7
+:10B3F00000C563A8002003D40000809C002003D473
+:10B40000B8FEFF0301006A9CB6FDFF03941A0CD43A
+:10B4100058008C840100609C001824E40300001094
+:10B420001E00809CFF00809C4C024C850000609CAC
+:10B4300000180AE40300001034220CD40100609CC0
+:10B440000100809C002014E4030000100000A09C78
+:10B450000000A4A858FDFF03032863E0BFFDFF031D
+:10B460004C024C853105000400006CA803FDFF036D
+:10B4700008036C860800E09C60520CD4403B0CD45E
+:10B480003808000400006CA89000AC84005025E44B
+:10B49000050000100200809C0040601858C063A89E
+:10B4A000002003D40040601800C563A80000C09CC1
+:10B4B000005003D458008C84003003D4003024E4BE
+:10B4C000130000100100809C2C028C840080A018C6
+:10B4D0000000A5A8032864E0003003E40400001085
+:10B4E000900064B8FF7F63A4341A0CD4C3F4FF0740
+:10B4F00000006CA8E1F4FF0700006CA8FBF4FF0754
+:10B5000000006CA89000AC840100809C002025E421
+:10B5100012000010000000150040601858C063A819
+:10B520000040A01818C0A5A8002003D40040C018EF
+:10B530002CC5C6A80000809C00006584100063A490
+:10B54000002003E4FDFFFF131F00E09C0000609C4F
+:10B55000003806D4001806D40040601848C063A81C
+:10B5600008036C860000638480FBFF03781A0CD408
+:10B570000080C0183800C6A800308DE00000648448
+:10B58000450063B8010063A4D7FAFF03F41A0CD492
+:10B590000080E0180400E7A80080A0182C00A5A8EF
+:10B5A00000386DE000288DE0000063840000848492
+:10B5B000241A0CD4010064A4008803E408000010DD
+:10B5C00028220CD40080C0189800C6A8B0520CD411
+:10B5D00000306DE000006384BC1A0CD4020064A447
+:10B5E000008803E409000010040064A40080E0184F
+:10B5F0009400E7A8AC520CD400386DE000006384DE
+:10B60000B81A0CD4040064A4008803E408000010F5
+:10B610000000001500808018900084A8A8520CD467
+:10B6200000206DE000006384B41A0CD4F4026C8432
+:10B63000005023E4ACFAFF13000000150080A018AE
+:10B640004400A5A80080C0180000C6A800286DE02E
+:10B650000080E0180400E7A8000083840B00E4B930
+:10B6600000306FE000388FE0000063841400C69C57
+:10B670001400E79CD41A0CD4000084840080601865
+:10B68000080063A80018AFE0D8220CD40000A584FD
+:10B69000008080180C0084A8DC2A0CD400206FE005
+:10B6A0000080A0181000A5A80000638400288FE087
+:10B6B000000084840030AFE0E4220CD40000A584B4
+:10B6C0000038CFE0008080181C0084A8E01A0CD459
+:10B6D0000000C68400206FE000006384E82A0CD4D8
+:10B6E000EC320CD480FAFF03F01A0CD4DA00000418
+:10B6F00000006CA84DFAFF0308036C86000072A9D5
+:10B700000000218504004185080081850C00C18569
+:10B710001000018614004186180081861C00C18635
+:10B72000004800442000219CE8FF219C004801D4EF
+:10B73000045001D4086001D40C7001D4108001D4ED
+:10B74000149001D4FF0043A6000044A9000064A89F
+:10B75000000085A98C0200040700009E74008A8402
+:10B760000707609C001844E503000010F8F8E49C0B
+:10B770000000E09C5800AA840040601838C563A807
+:10B780004C00CA84050085B8000005A9003803D420
+:10B79000043084E000406018300863A8C401AA8423
+:10B7A000002003D40100A5B818008A840040601866
+:10B7B000200863A8002003D4C801CA840040801870
+:10B7C000240884A81C006A84001804D4004060186F
+:10B7D000440863A8BC018A84002803D40040601890
+:10B7E00000E063A8002003D4C0016A8400408018F0
+:10B7F00004E084A8001804D40700609C001826E424
+:10B800008800001000000015004060180CE063A8DC
+:10B810000000809C002003D454008A840100609CB6
+:10B82000001824E47B0000100000001500406018A0
+:10B83000540863A80300809C002003D40100C09D2D
+:10B84000007028E40B00001000006AA80040601897
+:10B8500008E063A80000809C002003D4004080180A
+:10B86000440884A80000609C001804D400006AA862
+:10B870005C03000400008CA80200609C00182CE40B
+:10B880005F0000100000809C0040601830C563A875
+:10B89000007003D40000C09D00702CE45400000C24
+:10B8A0000000001500006AA89808000400008CA899
+:10B8B0000040601800C563A80100809C5800AA845D
+:10B8C000002003D40000809C002003D4007025E4F5
+:10B8D000080000100100809C18028A840100609C0E
+:10B8E000001824E43400000C000000150100809CC6
+:10B8F0000040601878C063A8002003D40000809C3A
+:10B90000002025E42800001000006AA83AF4FF0790
+:10B9100000008CA800406018340863A80300809CD5
+:10B92000006003D400200CE40700000C000072A8A3
+:10B930000040601848C063A8000063843D00000018
+:10B94000781A0AD40000ACA80805000400008AA8F0
+:10B95000A4006A8400000BAA0100A09C002823E434
+:10B96000030000100000C09C0000C5A80700609CF8
+:10B97000001830E4030000100000809C000085A83F
+:10B98000032086E00000609C001804E429000010F9
+:10B9900000006AA8AB09000400008CA82600000083
+:10B9A000000070A993F4FF0700008CA8DAFFFF03E2
+:10B9B0000000001591F3FF0700006AA8AFF3FF072E
+:10B9C00000006AA8C9F3FF0700006AA800406018D9
+:10B9D00048C063A85800AA8400006384781A0AD477
+:10B9E0000000609CC2FFFF03181A0AD41808000464
+:10B9F00000006AA8ADFFFF0300006AA800406018BD
+:10BA000030C563A8002003D4A4FFFF030000C09D3D
+:10BA100000406018540863A888FFFF030200809C60
+:10BA2000004060180CE063A87BFFFF030100809CCE
+:10BA3000000070A90000218504004185080081856F
+:10BA40000C00C185100001861400418600480044A6
+:10BA50001800219CF4FF219C004801D4045001D41B
+:10BA6000086001D4000083A9004080181C0884A845
+:10BA700000406018180863A80000638444180CD4C0
+:10BA80000000848400406018300863A800006385CB
+:10BA90008800ABB80100EBA50040601804C563A89E
+:10BAA00048200CD400006385004080180CC584A891
+:10BAB000FF00A5A5000084840C00639C9000EBB8F7
+:10BAC00000006384FFFF4BA50300E7A46C200CD4A7
+:10BAD00070180CD40040801814C584A80040601869
+:10BAE00018C563A800008484000003850400639CDB
+:10BAF00074200CD4000063840040801820C584A802
+:10BB0000FFFF08A57C180CD4000084840040601856
+:10BB100088C563A880200CD400006384004080188E
+:10BB20008CC584A894180CD400008484004060184C
+:10BB3000A0C563A8000063850400639C98200CD412
+:10BB40000000C3848900ABB888008BB80400639CF4
+:10BB50003F002BA500006384010084A40100A5A47C
+:10BB6000AC180CD4FFFFC6A400406018ACC563A895
+:10BB7000A0200CD400006385A4280CD4A8300CD4D9
+:10BB800060500CD464380CD478400CD49C480CD44D
+:10BB90000400639C4C780CD488008BB8000063844C
+:10BBA0003F00ABA43F0084A4B8180CD450680CD458
+:10BBB00000406018B4C563A8B4280CD400006384A6
+:10BBC0000100C09CBC180CD4B0200CD400406018FC
+:10BBD000C4C563A800006384003065E5030000105D
+:10BBE000C4180CD40000A6A81F00609C0018A4E58F
+:10BBF00003000010B4280CD4000083A80040601893
+:10BC000008E063A858006C850000A09C00006384D5
+:10BC1000B0200CD400282BE4A5000010C4190CD4CB
+:10BC200000282FE4A200001000282DE403000010DB
+:10BC30000000E09C0000E6A80900609C00182DE4CC
+:10BC4000030000100000809C000086A8042067E02C
+:10BC5000002803E4970000100700809C0000609C0F
+:10BC6000C8190CD40100809C00200BE416000010C1
+:10BC70000100A09C4C006C840000A09C002823E4E0
+:10BC8000890000100300609C5000CC84002826E44A
+:10BC9000030000100000009D000004A90900609C42
+:10BCA000001826E4030000100000E09C0000E4A857
+:10BCB000043868E0002823E47B00000C0300609C4B
+:10BCC0000100A09CBC290CD49C008C840000E09C4A
+:10BCD00010026C84003823E4040000106C220CD4A1
+:10BCE00070220CD474220CD400406018000663A8A3
+:10BCF00000408018100684A800006384D4190CD476
+:10BD00000000848400406018040663A80000638477
+:10BD1000DC190CD4D8210CD4004060181C0663A890
+:10BD200048008C84000063840F00849CE8190CD4C4
+:10BD3000840004B900406018000763A84400AC8484
+:10BD400000408018040784A8000063840F00A59CAD
+:10BD5000EC190CD48400A5B800406018200663A834
+:10BD60001C400CD4000063840643C5E0F0190CD4D9
+:10BD70000000848400406018100763A8F4210CD4EC
+:10BD80000000638400408018080784A8F8190CD4C8
+:10BD90000000848400406018140763A8FC210CD4C0
+:10BDA00000006384004080180C0784A8001A0CD49B
+:10BDB00000008484004060182C0663A804220CD480
+:10BDC0000000638400408018300684A8081A0CD450
+:10BDD000000084840040601808C563A800006384E4
+:10BDE0000C220CD438300CD468180CD40100809C80
+:10BDF00000202BE41900001018280CD40000A09C8F
+:10BE00006C006C8464280CD4032063E0FF00A09CC9
+:10BE1000003803E411000010342A0CD41900609C8F
+:10BE2000001848E5190000103200609C000064A969
+:10BE300018006C84004080180CC584A80100A09CE8
+:10BE4000065B63E0002804D46C280CD40400849CB6
+:10BE500070180CD4001804D4A4008C840100609CD9
+:10BE6000001824E4150000100000609CA8008C84D9
+:10BE7000001804E4110000100000001534026C8466
+:10BE80000E0000000A2363E0001848E504000010DB
+:10BE900000000015E7FFFF030200609DE5FFFF03C0
+:10BEA0000400609D89FFFF03BC190CD40700809C2F
+:10BEB0006DFFFF03C8210CD4A01A0CD408000004A5
+:10BEC00000006CA83C5B0CD4000021850400418577
+:10BED00008008185004800440C00219CF4FF219C4F
+:10BEE000004801D4045001D4086001D4A800838420
+:10BEF000000043A90100A09CA4006384002823E45F
+:10BF00001A0000100000C09C003024E4040000105F
+:10BF10001F00009D970000003E00609DB0008A84D5
+:10BF20000040A4E5030000100000E09C0000E5A82C
+:10BF3000003024E4030000100000609C000065A8AD
+:10BF4000041867E0003023E48A0000103F00609D81
+:10BF5000B4006A84004043E586000010003023E40A
+:10BF60008400000C000000156C028A841F00609C95
+:10BF70000018A4E5030000100000A09C0100A09C94
+:10BF80000000809D006024E4030000100000609C1D
+:10BF90000100609C041865E0006003E404000010E8
+:10BFA0000005609C730000003F00609D4400AA846F
+:10BFB000001845E506000010D002609C48008A8405
+:10BFC000001844E50900000C8007609CD55EFF075F
+:10BFD00010026A8400600BE46600000C1C00609D87
+:10BFE0004400AA848007609C001845E561000010A9
+:10BFF0001C00609D4800CA844004609C001846E50F
+:10C000005C0000100100809C58006A84002023E43A
+:10C010002B0000100000001550006A843C00809C3A
+:10C02000F6FF639C002043E452000010A700609DCF
+:10C03000020063B804008018E07684A8002063E062
+:10C04000000083840020004400000015B000609CC4
+:10C05000001845E547000010B600609D9000609C08
+:10C06000001846E50400000C000000154100000027
+:10C07000B600609D3F0000000000609D6001609C74
+:10C08000001845E53B000010B600609DF5FFFF037A
+:10C090002001609CFBFFFF03D002609C3500000084
+:10C0A000A700609DD002609C001845E5310000109B
+:10C0B000B600609DEBFFFF034002609C4C00AA8429
+:10C0C000002045E42B000010A600609D50008A84EB
+:10C0D0000900609C001844E426000010A700609D41
+:10C0E000020064B804008018D47784A8002063E0BC
+:10C0F00000008384002000440000001538008A847A
+:10C100006300609C0018A4E5DBFFFF13000000152E
+:10C1100018000000B600609D38008A84FAFFFF0313
+:10C120008C01609C38008A84F7FFFF031803609C31
+:10C1300038008A84F4FFFF035406609C0100609C71
+:10C14000001825E40B00000CA700609D38008A84CD
+:10C15000EDFFFF03100E609C0100609C001825E4B9
+:10C1600004000010A700609DEDFFFF0338008A84E3
+:10C1700000002185040041850800818500480044B5
+:10C180000C00219C4400C38400408018180884A837
+:10C190008C00A384003004D41000A5B87800C384B8
+:10C1A0000400849C4800E3840428C6E0003804D4DA
+:10C1B0006C00A384004080180CC584A8002804D417
+:10C1C0008000E3840040A01818C5A5A81000849C36
+:10C1D000003005D47C00C3840800A59C003004D442
+:10C1E000003805D40040801888C584A89400A38432
+:10C1F000002804D49800C3840040A0188CC5A5A8CA
+:10C200000040801808E084A8C401E384003005D40D
+:10C21000003804D40040A0180006A5A8D4018384E7
+:10C22000002005D4DC01C38400408018100684A8D7
+:10C23000D801A384002804D4E801E3840040A018B6
+:10C240000406A5A80C00849C003005D4003804D452
+:10C250000040A0180007A5A8EC018384002005D4A5
+:10C26000F401C38400408018200684A8F001A38450
+:10C27000002804D4F801E3840040A0180407A5A80E
+:10C2800000408018100784A8003005D4003804D47A
+:10C290000400A59CFC018384002005D40402C3840F
+:10C2A00000408018140784A80002A384002804D446
+:10C2B0000802E3840040A0180C07A5A800408018DD
+:10C2C0002C0684A8003005D4003804D40040A018FF
+:10C2D0003006A5A80C028384002005D4680063847E
+:10C2E0000040801808C584A8001804D40048004401
+:10C2F00000000015F4FF219C004801D4045001D433
+:10C30000086001D46000A384000043A90000609C81
+:10C31000001825E49400001000000015FFFFA09C09
+:10C3200010008A8464006A84001804E40800001085
+:10C330000000609C20008A840300609C001804E4D4
+:10C340000700000C0200809D0000609C001825E49E
+:10C35000030000100100809D0000809D00006A84A1
+:10C360000100809C002023E4790000100000609C04
+:10C370000000809D14180AD480026A840100A09CE9
+:10C38000002823E4030000100000C09C0000C5A8A2
+:10C3900000284CE4030000100000809C000085A8E9
+:10C3A000032086E00000609C001804E405000010F3
+:10C3B0000000001514180AD4801A0AD40000809DC9
+:10C3C00000284CE42F00001000000015B002EA84A1
+:10C3D000002807E45C00001000000015AC026A842D
+:10C3E000002803E45600001000000015A802CA84CB
+:10C3F000002806E42300000C000000150100809CCA
+:10C40000002027E40400001000000015BC02AA84EC
+:10C4100060280AD4002023E4080000100100609C7A
+:10C42000B8028A840000609C001804E40300001035
+:10C430000100609CA8200AD4001826E40A0000101D
+:10C440000000A09CAC008A840000609C001804E4FA
+:10C45000060000100000809DB4026A84AC180AD463
+:10C460000000A09C0000809D14280AD4B02A0AD4A1
+:10C47000AC2A0AD4A82A0AD43A04000400006AA804
+:10C48000C0026A840100809C002003E406000010C2
+:10C4900000000015CC026A84002003E40300000CB5
+:10C4A00000000015000084A984026A840100809CB9
+:10C4B000002023E4030000100000A09C0000A4A8BA
+:10C4C00000202CE4030000100000609C000064A821
+:10C4D000031865E00000A09C002803E4040000109D
+:10C4E00000000015842A0AD40300809D00282CE453
+:10C4F000030000100000E09C0000E4A80200609C23
+:10C5000000182CE4030000100000C09C0000C4A828
+:10C51000043067E0002803E4030000100000609C82
+:10C52000B8190AD4B8016A84002023E4140000106A
+:10C5300000006CA9110000000400809DB0FFFF0303
+:10C54000A802CA84FEFFFF03AC026A8404006A8466
+:10C55000002023E489FFFF130000001587FFFF037D
+:10C56000000084A914008A84092B64E0062B63E090
+:10C570006CFFFF030218A4E000006CA900002185F5
+:10C580000400418508008185004800440C00219C7E
+:10C590000040601804C163A80000809C0800A09CB3
+:10C5A000002003D4004080184CC084A8000064849C
+:10C5B000070063A4021865E0002803E407000010E8
+:10C5C000020083B80040A01800C1A5A8002864E0BC
+:10C5D000FF00809C002003D40048004400000015A8
+:10C5E000B8FF219C004801D4045001D46400238783
+:10C5F0000000E3A90000A4AA0700609C4400809CFE
+:10C60000381801D43C2001D40800609C0100849CAF
+:10C61000401801D4442001D43800639C4200809C1F
+:10C62000281801D42C2001D40100639C0100849CB3
+:10C63000301801D4342001D40700609C0800809C8D
+:10C64000181801D4201801D41C2001D43900639C8F
+:10C65000242001D4081801D43900849C101801D476
+:10C660000C2001D40000609C001839E4A7000010E1
+:10C67000142001D41800E19E0800619E0200609C15
+:10C68000001835E49E0000100C00EF84FEFF679C4C
+:10C69000FFFF879C030063A4030084A4020023BA65
+:10C6A0000200A4B80300E7A4009871E0009885E0B8
+:10C6B0000000038500B8D1E00200A7B9000024857E
+:10C6C00000B8A5E0004060186CC563A8000046856E
+:10C6D000070088B80700E9B800006585045084E0C9
+:10C6E000080008B9002003D40458E7E00400639C64
+:10C6F0000098ADE0003803D4045008E10040601811
+:10C70000000B63A80000C584080029B900B88DE0BB
+:10C71000004003D40700A6B80400639C045829E134
+:10C720000000E4840800C6B8004803D40438A5E03B
+:10C730000040601874C563A800408018080B84A8E6
+:10C74000002803D40438C6E000406018280B63A812
+:10C75000003004D40000A3840000809C002025E465
+:10C76000320000100000609C0200609C001815E47C
+:10C770002D0000103D00639C0018A7E55C00001030
+:10C7800000000015004060180C0563A80000E38459
+:10C790000098ADE000B86DE00000C584000083841F
+:10C7A000020084B800406018000663A8001884E006
+:10C7B000000064840B0063B8004080182C0B84A830
+:10C7C0000018A7E03F00609C002804D40018A6E5EC
+:10C7D0004300001000000015004060180C0563A81D
+:10C7E0000000E38400988DE000006484020063B8D8
+:10C7F00000408018000684A8002063E000008384C5
+:10C800000B0084B800406018300B63A80020A7E03C
+:10C81000002803D400408018280B84A80100609CE5
+:10C82000001804D40000609C001819E420000010D7
+:10C830000000001500406018080563A8004080183B
+:10C840000C0584A80000A38400006484001825E47B
+:10C85000170000100100A09C002835E4140000100F
+:10C860000000001500B891E000006484BCFF639CE8
+:10C87000002843E40E00001000000015E0018F8442
+:10C8800000406018240663A8002003D4E401EF856B
+:10C8900000408018280684A80040601868C563A876
+:10C8A000007804D41C0000000905809CE0018F84FE
+:10C8B00000406018180763A8002003D4E401EF8546
+:10C8C000004080181C0784A80040601868C563A851
+:10C8D000007804D410000000C623809C004060183B
+:10C8E000080563A8BFFFFF030000001500406018A3
+:10C8F000080563A8A6FFFF0300000015FFFF679C63
+:10C9000065FFFF03FEFF879C3800E19E5CFFFF038D
+:10C910002800619E002003D4000021850400418589
+:10C92000004800444800219C0000809C0100A09C1D
+:10C93000042003D4002803D40C2003D4102003D4F3
+:10C94000142003D4202003D4242003D48C2003D427
+:10C950004C2203D4502203D4542203D4582203D4AB
+:10C96000642203D45C2203D4682203D40400A09C74
+:10C970007003639CFF7FC018FFFFC6A80100849C62
+:10C98000003003D40028A4E5FDFFFF133000639CB2
+:10C990000048004400000015ECFF219C004801D431
+:10C9A000045001D4086001D40C7001D4108001D46B
+:10C9B000FF0083A50000C5A9000006AA10006018AA
+:10C9C000000063A80018A7E405000010000047A9B4
+:10C9D00000806018000063A8041847E10000C09CB4
+:10C9E00000302AE4030000100000E09C0100E09CFD
+:10C9F0003304609C001848E4030000100000A09C71
+:10CA00000100A09C042867E0003003E48100000CD2
+:10CA10001000609D005004D400006AA80000809CB3
+:10CA2000DD5EFF073404A09C0000609C0300C09CF6
+:10CA300008180AD4BC310AD4C0310AD428180AD440
+:10CA40002C180AD430180AD434180AD4C8190AD4B5
+:10CA500068180AD41F00C09C0100609C84300AD46E
+:10CA600090180AD4E0180AD4DC180AD40000C09C3C
+:10CA70000D00609C60310AD4E4300AD4D8180AD47E
+:10CA80000900C09C0600609CD4300AD4D0180AD497
+:10CA90003700C69C1800609CE8300AD4EC180AD411
+:10CAA000F8180AD42400C69C3600609CF0300AD4E2
+:10CAB000F4300AD4FC180AD43200C09C2000609CD8
+:10CAC00000310AD404190AD40100C09C0800609CFB
+:10CAD00008310AD40C190AD46400C09C2000609C60
+:10CAE00010310AD414190AD418190AD440600AD48F
+:10CAF00058700AD43A00C09C1C190AD40000809CCB
+:10CB00000400A09C20310AD470036A9CFF7FC018E7
+:10CB1000FFFFC6A80100849C003003D40028A4E5D0
+:10CB2000FDFFFF133000639C0000609C0100C09C6F
+:10CB3000601A0AD4141A0AD4181A0AD41C1A0AD46D
+:10CB4000201A0AD43C320AD4241A0AD4281A0AD445
+:10CB50002C1A0AD4301A0AD438320AD41E00609C27
+:10CB60000000C09C341A0AD4881A0AD468320AD445
+:10CB70006C320AD470320AD474320AD47C320AD4A9
+:10CB800080320AD484320AD48C320AD490320AD445
+:10CB900094320AD498320AD49C320AD4A0320AD4ED
+:10CBA000A4320AD4A8320AD4AC320AD4B0320AD49D
+:10CBB000B4320AD4B8320AD4BC320AD40300609C1E
+:10CBC000C0320AD4C4320AD4C8320AD4CC320AD40D
+:10CBD00090310AD4F4320AD4F8320AD4FC320AD49E
+:10CBE00000330AD4001830E40700001004330AD4DC
+:10CBF00054300AD44DFFFF0700006AA8050000006A
+:10CC00000000609D0100609CFBFFFF0354180AD4E4
+:10CC10000000218504004185080081850C00C18544
+:10CC200010000186004800441400219CFFFFA39CD3
+:10CC30000000609C001865E5030000100000C4A817
+:10CC40000000A09C008085A40000609C001804E403
+:10CC500004000010004085A4410000001000609C0A
+:10CC6000001804E404000010002085A43C0000002B
+:10CC70000F00609C0000609C001804E40400001099
+:10CC8000001085A4360000000E00609C001804E42B
+:10CC900004000010000885A4310000000D00609C15
+:10CCA0000000609C001804E4040000100000E09CF8
+:10CCB0002B0000000C00609C000465A4003803E415
+:10CCC0002700000C0B00609C000265A4003803E400
+:10CCD0002300000C0A00609C000165A4003803E4F6
+:10CCE0001F00000C0900609C800065A4003803E46C
+:10CCF0001B00000C0800609C400065A4003803E4A1
+:10CD00001700000C0700609C200065A4003803E4B5
+:10CD10001300000C0600609C100065A4003803E4BA
+:10CD20000F00000C0500609C080065A4003803E4B7
+:10CD30000B00000C0400609C040065A4003803E4B0
+:10CD40000700000C0300609C020065A4003803E4A7
+:10CD50000300000C0200609C0100609C001806D4D7
+:10CD60000048004400000015C0FF219C004801D489
+:10CD7000045001D4086001D40C7001D4108001D497
+:10CD8000149001D418A001D41CB001D420C001D447
+:10CD900024D001D428E001D42CF001D4000084A9CF
+:10CDA000FF00C3A76C0084840000609C0000409FCB
+:10CDB000382801D43C180CD4010084A40700409EFC
+:10CDC0000000809E00D004E40900001034D001D49B
+:10CDD00000D025E4CB0100101100A09C342801D420
+:10CDE00038006C8492FFFF073C00819C58006C84E3
+:10CDF0000000009D004023E4C00100104000609C42
+:10CE00008000E09C303801D418006C840040801809
+:10CE1000280884A8091BB4E0061B65E0002804D498
+:10CE20000400849C021874E00040A01834C5A5A832
+:10CE3000001804D470008C840000609C002005D48D
+:10CE4000001814E467000010000000157C026C84D8
+:10CE50000100E09C003823E4980100104000A09CF1
+:10CE6000004060184CC063A800008384430004B9EC
+:10CE70000028A8E50C00000C00000015D0026C840E
+:10CE80000040801880C184A8FFFFC09C0400089D5A
+:10CE9000003004D40028A8E5FCFFFF130400639CC5
+:10CEA000D01A0CD40040601858C063A80100E09C60
+:10CEB000CC01CC9E003803D40040001A24C510AA2F
+:10CEC0000040801B2CC59CAB0000C09D0040001B97
+:10CED000002018AB00007084080043A500700AE42D
+:10CEE0006601000C000000150040601818C063A81F
+:10CEF000000083840000609C100084A4001804E4F7
+:10CF0000F5FFFF131F00809C00201CD400181CD4C8
+:10CF1000D457FF070800409D78020C850040601838
+:10CF2000002063A89F00C8B888002C8500008AA84C
+:10CF30005D00C6B84000AC84003008E1002803D48E
+:10CF4000830008B900007EA80000B6A8094BE8E0FD
+:10CF50000000C9A8064BE7E0023808E13967FF077F
+:10CF60000000E8A80700609C00180BE46E01000CAC
+:10CF700000004BAA0000C09C78320CD400408018FE
+:10CF800078C084A80100E09C58006C840000A09C3C
+:10CF9000003804D4002823E4280100100100609C1C
+:10CFA000003826E41E0100103400818400006CA8C3
+:10CFB0000000D4A83C00A18400001EA950F0FF0787
+:10CFC0003800E1840700609C00180BE45601000C57
+:10CFD00000004BAA68026C840100639C681A0CD4A0
+:10CFE00000406018080863A80100809C002003D45A
+:10CFF000004080180C0884A80100609C0000A484F4
+:10D00000001825E42800000C00000015CC01CC9D80
+:10D010000040601824C563A8000083840000609C61
+:10D02000080044A500180AE41800001000000015CC
+:10D0300038036C840100A39C08038C840600609C68
+:10D04000001824E4E8000010382B0CD434036C845E
+:10D05000002803E124038C84002088E5D800001018
+:10D060000200A8B80800409E88008C84000068A8D0
+:10D070005467FF070000B2A80700609C001812E484
+:10D080002A01000C000072A9004060180C0863A877
+:10D090000100809C0000A384002025E4DDFFFF1335
+:10D0A00000000015004060180C0863A80000809C78
+:10D0B000002003D4002034E4BB0000100000001561
+:10D0C0007802EC840000409D004060184CC063A8CA
+:10D0D0003C00CC8401005A9F000083840000A3849C
+:10D0E000002087E00028C6E00040601840C563A823
+:10D0F0003800AC840000838678220CD400A045E57B
+:10D100005900000C3C300CD40100809C00203AE413
+:10D110005300001000000015F402EC84002027E406
+:10D12000280000100100C09CD4026C843400009DD3
+:10D130000040A3E447000010B500A09CD8026C8416
+:10D140000080C0180000C6A81800A09C003083E032
+:10D15000F82A0CD40400C69C0030A3E01800C09C40
+:10D16000003004D400808018080084A80020C3E0A8
+:10D17000E8028C84002005D40080A0180C00A5A82B
+:10D18000002883E0EC02AC84002806D40080C0189C
+:10D190001000C6A80030A3E0F002CC84003004D414
+:10D1A00000808018140084A80400C09C002063E064
+:10D1B000003005D40000809C002003D40100C09CF6
+:10D1C000003027E411FFFF130000609C00038C84F3
+:10D1D000001824E40DFFFF130000001578026C8492
+:10D1E0009F0083B8F802EC845D0084B8D402AC845C
+:10D1F0001C00079D002063E0830063B80040A5E4A5
+:10D200000600000C025063E1B500609C00330CD4B2
+:10D21000FEFEFF033C1B0CD4D8026C840800A79CC4
+:10D22000003863E0F82A0CD40080E0180000E7A87A
+:10D2300004330CD4003883E00400E79C005004D48D
+:10D24000003863E0005803D4F1FEFF0318006C843B
+:10D2500000230CD4DAFFFF033C2B0CD4D8FFFF03D0
+:10D26000F402EC84F4026C840100C09C003023E4DE
+:10D27000AD0000100000609C00038C84001824E4C2
+:10D28000AA000010000072A904036C84003023E49B
+:10D29000A60000100000001578026C849F0083B87F
+:10D2A000F802EC845D0084B8D402AC841C00079DB5
+:10D2B000002063E0830063B80040A5E4360000105E
+:10D2C000025063E1D802AC840800279D000007A942
+:10D2D000003865E00080C0180000C6A80080E01893
+:10D2E0000400E7A8003083E0F4FF089D005004D458
+:10D2F0000038C3E000808018000084A8005806D4DD
+:10D300000020E5E00080C0181000C6A8004807D43F
+:10D31000003085E00080E0181400E7A8004004D445
+:10D320000038A5E000808018080084A800D005D44B
+:10D330000020C3E01400E09C0080A0180C00A5A809
+:10D34000003806D4002883E0DC02EC840080C0189A
+:10D350001000C6A8003804D40030A3E0E002EC843A
+:10D3600000808018140084A8003805D40020C3E091
+:10D37000E402AC840400849C002806D4002063E00E
+:10D380000000C09CF84A0CD4003003D467000000B1
+:10D39000000072A9B500E09C00330CD462000000CC
+:10D3A0003C3B0CD47802EC849F0067B85D0063B806
+:10D3B000001867E045FFFF03830043B90C036C844A
+:10D3C0001C038C84002063E0001865E00080A01836
+:10D3D0000000A5A8002863E00000038524FFFF03E8
+:10D3E00088008C849F56FF07000000154000EC84E5
+:10D3F00000408018002084A800007EA88800CC840B
+:10D400000000AEA8003804D400008AA80D66FF070B
+:10D410000000E6A819FFFF0300004BAA00006CA85B
+:10D420000000D4A83C00A184A6EEFF073800E184E8
+:10D43000EAFEFF0368026C84001826E40B0000106B
+:10D4400000006CA800009AA8D4F0FF070000BEA856
+:10D450000700609C00180BE4E2FEFF1300004BAADB
+:10D4600032000000000072A916EFFF0700009AA822
+:10D47000DCFEFF03000000157A56FF0700000015D0
+:10D4800040006C8400008AA80000B6A88800CC8404
+:10D49000001818D40000E6A8EA65FF0700007EA87F
+:10D4A0000700609C00180BE490FEFF1300004BAADD
+:10D4B0001E000000000072A988008C843803AC8430
+:10D4C0000300C4B878026C84062B84E03000A18489
+:10D4D000030084B8002863E0022003E10030A8E5DF
+:10D4E0000400001000000015A5FEFF030000C7A8FF
+:10D4F000A3FEFF030000C09C44FEFF03301801D4CC
+:10D50000BC018C841000C49CC4016C8400D003E472
+:10D5100034FEFF13343001D41100849C31FEFF032C
+:10D52000342001D4000072A9000021850400418547
+:10D53000080081850C00C185100001861400418619
+:10D54000180081861C00C1862000018724004187C5
+:10D55000280081872C00C187004800444000219C9E
+:10D56000F4FF219C004801D4045001D4086001D488
+:10D57000AC00C384000043A90000A09CA8008384E1
+:10D580000A2386E0380063840A1B64E0420063B823
+:10D59000001885E40D00000C80210AD4002823E443
+:10D5A0000A00000C0000809C0100A59C001885E486
+:10D5B0000600000C00000015022863E0002023E4B0
+:10D5C000FAFFFF13000000150100809C002065E4B5
+:10D5D00003000010000085A9000084A960002A85CE
+:10D5E000002029E402010010FFFFA99C0000609CBC
+:10D5F00070210AD474210AD478190AD47C190AD467
+:10D600007300609C70010A850A1B66E08001EA8451
+:10D610002A00C09C063B08E1020083B80400A3B8BE
+:10D62000001884E00218A5E0050084B80200A5B83F
+:10D6300064210AD468290AD40633C3E084410AD499
+:10D640000100609C001829E4260000106C310AD407
+:10D650000300609C0000809C0A1B68E028410AD4FB
+:10D6600030210AD42C190AD40000609C0A00809C46
+:10D6700088190AD48C210AD4E602000400006AA8A2
+:10D680008001CA847800609CB800AA844100E6B892
+:10D690000A6303E170018A840633A5E00000609C00
+:10D6A000063B84E04500A5B8002884E0001808E4A3
+:10D6B0000A000010C4200AD41F00A09C0028A8E47F
+:10D6C00003000010000068A8000065A8062363E0BE
+:10D6D000CF000000030063B8CD000000030064B871
+:10D6E0007C012A850000609C001829E45600001087
+:10D6F0000000001541006018378963A8001848E44D
+:10D700001D000010E803809C7401AA847701609CCE
+:10D710000623A5E07801EA84061B67E0062388E07B
+:10D720000018A5E00A2B84E028210AD40000609CA0
+:10D73000001807E40B0000100000C09C28018A8438
+:10D7400084016A84001824E4080000100000001519
+:10D750000300609C0A1B64E02C190AD40000C09CE2
+:10D76000C2FFFF0330310AD4022063E0FBFFFF0356
+:10D770000A3B63E08F026018285C63A8001848E445
+:10D7800013000010E803609C7401AA84010088B8AB
+:10D79000061BA5E07801EA84004084E0050064B837
+:10D7A000001884E07701609C004084E0061B67E07D
+:10D7B0000018A5E00A2B84E0030064B8002063E0B1
+:10D7C000002063E0DAFFFF0328190AD499196018D2
+:10D7D000999963A8001848E412000010E803A09C7F
+:10D7E0007401AA84E803609C030088B8061BA5E0C6
+:10D7F0007801EA84004084E0004084E07701609C86
+:10D80000061B67E00018A5E00A2B84E0010064B85D
+:10D81000002063E00500A3B8EAFFFF03002863E0EF
+:10D8200074016A847701809C7801EA84062B63E0A6
+:10D83000062387E0002063E00A1B68E0E2FFFF03A5
+:10D84000062B63E041006018378963A8001848E49C
+:10D850001F000010E803C09C7401AA847701809C1B
+:10D860000633A5E07801EA84060069B8004863E061
+:10D87000020063B8004863E0004863E00623E7E085
+:10D880000633C8E00038A5E00018A5E00A2BC6E082
+:10D8900028310AD428018A847701A09CE803C09C1F
+:10D8A000062BA4E0060064B8002063E0020063B821
+:10D8B000002063E0002063E00A33A5E00A3363E060
+:10D8C0002C290AD469FFFF0330190AD48F0260188B
+:10D8D000285C63A8001848E419000010E803809C45
+:10D8E0007401CA84060069B80623C6E07801EA8498
+:10D8F000004863E0020063B8004863E0004863E06A
+:10D90000010088B8004084E00500A4B8002884E045
+:10D910007701A09C004084E0062BE7E00038C6E0D9
+:10D920000018C6E00A3384E0030064B8002063E016
+:10D93000002063E0D8FFFF0328190AD49919601862
+:10D94000999963A8001848E419000010E803E09CC6
+:10D950007401CA84E803809C060069B80623C6E007
+:10D960007801EA84004863E00300A8B8020063B8C5
+:10D970000040A5E0004863E00040A5E0004863E007
+:10D980007701809C0623E7E00038C6E00018C6E077
+:10D990000A33A5E0010065B8002863E0050083B8FC
+:10D9A000002063E0E4FFFF03002863E074018A8441
+:10D9B0007701A09C7801CA84063B84E0060069B820
+:10D9C000004863E0020063B8004863E0004863E099
+:10D9D000062BC6E0003084E0001884E00A2388E0CB
+:10D9E000063B84E0ACFFFF0328210AD464006A846C
+:10D9F000061B69E074210AD478290AD4001889E04A
+:10DA00007C190AD4FFFEFF0370210AD4D101809C47
+:10DA10002C01AA840A2383E00000C09C5C290AD45C
+:10DA200060310AD4010065B8410084B8002863E081
+:10DA300044210AD458190AD40000218504004185E4
+:10DA400008008185004800440C00219C000003A9C7
+:10DA50000100A09C90016384002823E42900000CAD
+:10DA60000000001560008884002824E41D000010D8
+:10DA7000FFFFC49C0000609C702908D4742908D45E
+:10DA8000781908D47C1908D4AC00A8847300609C71
+:10DA90000A1BA5E0800188847001E8848801C8849D
+:10DAA0000623E7E0020065B8002863E0050063B8DC
+:10DAB000641908D42A00609C040085B80038C6E0C8
+:10DAC000022884E0843108D4061BA5E0020084B853
+:10DAD000883108D4682108D40A0000006C2908D4D1
+:10DAE00064006884061B64E0742908D4783108D483
+:10DAF000001884E07C1908D4E4FFFF03702108D4E7
+:10DB00000048004400000015F8FF219C004801D4A3
+:10DB1000045001D4000024A9A40043850100809C86
+:10DB200000202AE4DD0000100000A3A99001638416
+:10DB3000002023E44E000010002009E4002009E446
+:10DB400047000010002049E53D0000100200609CE5
+:10DB50000000609C001809E433000010000000156C
+:10DB60003800CD844C016D840000809C0A3363E052
+:10DB70000000AD84002025E42800001048190DD4D1
+:10DB8000C0006D840200A09C54018D84022063E0DB
+:10DB90000028A3E50600000C00000015FEFFA09C75
+:10DBA000002863E50300001000000015000065A8D0
+:10DBB000B400ED84001864E0003863E51100001043
+:10DBC00000000015B000AD84000067A89C180DD4BB
+:10DBD0009C006D8454190DD40000609C001829E449
+:10DBE000050000100100809CDC180DD4B900000075
+:10DBF000E0180DD4DC200DD4B6000000E0200DD4D8
+:10DC0000B000AD840028A3E5F1FFFF13000000156C
+:10DC1000EFFFFF03000065A8B400ED84EDFFFF03F4
+:10DC2000B000AD8428016D843800CD844C190DD42A
+:10DC3000D0008D84CCFFFF0350210DD4001809E4DF
+:10DC4000C8FFFF0F000000153800CD8430016D843F
+:10DC5000D8008D84F8FFFF034C190DD42C016D847E
+:10DC60003800CD84FCFFFF03D4008D8474000010C5
+:10DC70000000609C002049E5600000100200609CEC
+:10DC80000000609C001809E4B6FFFF0F00000015BB
+:10DC900088016D8500184BE5060000100000001596
+:10DCA00038006D844C190DD4E2FFFF033800CD8499
+:10DCB00041006018378963A800184BE41000001079
+:10DCC000E803C09C74016D847701809C063363E097
+:10DCD0007801ED84BB00A09C7C010D850623E7E064
+:10DCE000062B08E1003863E00633CBE0004063E038
+:10DCF0000A1BC6E0EDFFFF034C310DD48F02601804
+:10DD0000285C63A800184BE416000010E803609C30
+:10DD10007401CD8401008BB8061BC6E078010D8527
+:10DD2000005884E0BB00A09C7C01ED84050064B831
+:10DD3000062BE7E0001884E07701609C005884E03F
+:10DD4000061B08E10040C6E00038C6E00A3384E064
+:10DD5000030064B8002063E0D3FFFF03002063E00A
+:10DD600099196018999963A800184BE416000010DF
+:10DD7000E803009D7401CD84E803609CBB00A09C77
+:10DD8000061BC6E078010D8503008BB87C01ED848D
+:10DD9000005884E0005884E07701609C062BE7E09F
+:10DDA000061B08E10040C6E00038C6E00A3384E004
+:10DDB000010064B8002063E00500A3B8E7FFFF039B
+:10DDC000002863E074016D847701809C7801ED8404
+:10DDD000064363E0BB00A09C7C01CD840623E7E002
+:10DDE000062BC6E0003863E0003063E00A1B6BE0FE
+:10DDF000ADFFFF03064363E0001809E459FFFF0F7E
+:10DE00000000609C8801AD84001845E50500001005
+:10DE1000000000153800CD848EFFFF03000066A8C7
+:10DE200078016D847C018D84010063B83800CD8455
+:10DE3000001884E087FFFF030A2365E088010D8551
+:10DE4000001848E5080000100300A8B83800CD8489
+:10DE50000000A6A8D4006D844C290DD442FFFF0316
+:10DE600050190DD47801CD847C01ED84030066B88F
+:10DE70000040A5E0020087B8003063E00040A5E064
+:10DE8000003063E0003884E03800CD84002063E097
+:10DE9000F1FFFF030A1BA5E09C00A3840000609C27
+:10DEA0000018A5E507000010000064A81F00809C72
+:10DEB0000020A5E503000010000065A8000064A88C
+:10DEC000B400ED84B000AD8444FFFF039C180DD472
+:10DED000A0006D8409008AB80800A5B8080063B8DE
+:10DEE0009C00CD840438A5E0041884E0B8002D859A
+:10DEF000043084E000406018A0C563A80C01ED84E4
+:10DF0000002003D45001CD840C00639C1C00E7B8B2
+:10DF1000002803D4BC008D840400639C1000C6B8A4
+:10DF2000004803D4EC00AD840400639C002003D4BB
+:10DF3000C4002D851000A5B81000639CE0008D84FE
+:10DF40000428E7E048010D850C0084B8004803D49C
+:10DF50000440C6E000406018BCC563A80420E7E0A8
+:10DF6000003003D444018D840400639C002003D45A
+:10DF7000E400AD84DC006D840800A5B8F4002D85B4
+:10DF8000070063B800018D84100029B90418A5E0CA
+:10DF9000F8004D85042029E100406018C8C563A839
+:10DFA0000450E7E00801CD8410018D841000C6B84C
+:10DFB000003803D41C010D85080084B80400639C5C
+:10DFC00020014D85100008B90420C6E0004803D4A4
+:10DFD000045008E10400639C14018D8418016D85D0
+:10DFE0000420C6E0004003D40458A5E00800639C68
+:10DFF00000408018DCC584A8002803D4003004D475
+:10E000000800639CF000AD84FC00CD840800A5B836
+:10E0100004018D840430A5E0080084B8E800ED8494
+:10E02000002803D4043884E00400639C002003D457
+:10E030000000218504004185004800440800219C1F
+:10E04000F4FF219C004801D4045001D4086001D49D
+:10E050003C00E384000043A9900163840100A09C7C
+:10E06000002823E41200000C0000C4A888016A8480
+:10E0700000408018B8C584A800008484023863E09A
+:10E080008C210AD4002806E45200001088190AD412
+:10E09000002846E5450000100200609C0000609CDE
+:10E0A000001806E43A0000100000001544016A84DC
+:10E0B0000000809D4C018A84003863E00220A3E0C8
+:10E0C000006065E503000010000000150000A09C42
+:10E0D000A0016A8480018A84003863E0022063E042
+:10E0E00044290AD4A0190AD4006063E50300001093
+:10E0F000000083A80000809C1C026A84006003E486
+:10E100001F00000CA0210AD444018A845C01AA8467
+:10E11000002864E4080000100000001560016A8413
+:10E12000022085E0002063E044290AD4300000008A
+:10E1300060190AD45801AA840028A4E42C00001015
+:10E140000000001560016A84006003E428000010EC
+:10E150000228C4E00030A3E4040000100000001511
+:10E16000F2FFFF03023063E0021864E00000809CCD
+:10E1700044190AD41E00000060210AD4B80000042B
+:10E1800000006AA8E2FFFF0344018A848C018A84AC
+:10E19000063B84E074016A84FFFF639C74190AD40F
+:10E1A000C3FFFF0364210AD4001806E4C0FFFF0F79
+:10E1B000000000158C018A84063B84E07C016A849F
+:10E1C000FFFF639C7C190AD4B9FFFF036C210AD4BA
+:10E1D0008C018A84063B84E078016A84FFFF639C9B
+:10E1E00078190AD4B2FFFF0368210AD400406018EE
+:10E1F000B8C563A800006384C0180AD40000218554
+:10E200000400418508008185004800440C00219CE1
+:10E21000F8FF219C004801D4045001D40000809CE8
+:10E22000000043A9A02103D4B02103D4B42103D416
+:10E2300028018384942103D42C0183841B000004CF
+:10E24000982103D41C028A840100609C001824E4F5
+:10E250000B0000100200609CA401AA840500609CD1
+:10E260000A00809C0300C5B8091BA5E00923C6E08D
+:10E27000AC290AD409000000A8310AD4001824E40B
+:10E28000060000100500609CA4018A84A8210AD41D
+:10E29000091B84E0AC210AD40000218504004185DB
+:10E2A000004800440800219C0000A3A80000809CB6
+:10E2B00058006384002023E43E0000100000001595
+:10E2C0004C006584002023E42E0000100700609CB1
+:10E2D000500085840900609C001844E41B00001075
+:10E2E000F800609C020064B804008018FC7784A8E1
+:10E2F000002063E00000838400200044000000153B
+:10E300001400809C9C2105D41C0285840100609C23
+:10E31000001824E4060000100200609C9C01658443
+:10E320000E0063B84C000000A41905D4001824E4C2
+:10E33000490000100000001514026584FAFFFF0375
+:10E340000A0063B80A00609CF0FFFF039C1905D423
+:10E35000EDFFFF030A00809CFCFFFF032800609C88
+:10E36000E9FFFF032800809CF8FFFF035000609C3A
+:10E37000E5FFFF037000809CF4FFFF03F800609C42
+:10E3800050008584001844E4FAFFFF13020064B8CB
+:10E3900004008018247884A8002063E000008384AF
+:10E3A0000020004400000015E8FFFF034100609CCE
+:10E3B000500065843C00809CF6FF639C002043E491
+:10E3C0002100001000000015020063B8040080184E
+:10E3D000447884A8002063E0000083840020004487
+:10E3E000000000150002609C9C1905D41C02858465
+:10E3F0000100609C001824E40800001000000015D3
+:10E400009C01658480018584080063B8002063E076
+:10E41000C5FFFF03020063B80200609C001824E4FB
+:10E42000C6FFFF0F000000150B00000000000015E4
+:10E43000EEFFFF038000609C0002809CECFFFF0366
+:10E440009C2105D4E9FFFF030004609CFCFFFF034F
+:10E450000004809C0048004400000015A001A38433
+:10E46000000083A8A8016384001885E5050000105A
+:10E470000000609CB41904D40B0000000100609CF3
+:10E48000AC016484001845E5050000100100609CA3
+:10E49000B41904D4040000000000609C0000609CDB
+:10E4A000B41904D4B81904D4B01904D400480044F1
+:10E4B000000000150000609D005823E40900000CD6
+:10E4C0000100809C002043E50600000C00000015C0
+:10E4D000010084B8002043E5FEFFFF1301006B9D9F
+:10E4E00000480044000000150100E59C000066A9FA
+:10E4F0004838E6E00220A5E0000004A92000C09C06
+:10E500000100A59C0220C6E00828E7E0FFFF809CF0
+:10E51000483084E00418E7E00000609C001808E43C
+:10E520000300000C03208BE00000809C084067E0A3
+:10E53000042063E10048004400000015FCFF219C1A
+:10E54000004801D4000066A90000E3A8000004A967
+:10E550000000C09C00302BE426000010000025A91C
+:10E56000420065B9005886E40F00000C0000001559
+:10E5700000806018000063A80018A7E0001884E07D
+:10E58000000064840400089D0400E79C001805D482
+:10E590000400849C0100C69C005886E4F9FFFF1328
+:10E5A0000400A59C030029A50000C09C004886E447
+:10E5B0005F00000C0000001500806018000063A8D8
+:10E5C0000018E7E0001808E10000688C0100C69C14
+:10E5D000FF0063A40100089D001807D8004886E4E6
+:10E5E000FAFFFF130100E79C510000000000001536
+:10E5F0000100C09C00302BE4230000100200C09CEE
+:10E600004200A5B80000C09C002886E40D00000C64
+:10E610000000001500806018000063A8001887E063
+:10E62000000068840400E79C0100C69C001804D424
+:10E630000400089D002886E4FAFFFF130400849C70
+:10E64000030029A50000C09C004886E43800000CA7
+:10E650000000001500806018000063A80018E7E0C3
+:10E66000000068900100C69C001807D80100089DB2
+:10E67000004886E4FBFFFF130100E79C2C0000002C
+:10E680000000001500302BE42300001000000015EE
+:10E690004830A5E00000C09C002886E40D00000C76
+:10E6A0000000001500806018000063A8001884E0D6
+:10E6B000000064840400089D0100C69C001807D473
+:10E6C0000400849C002886E4FAFFFF130400E79C02
+:10E6D000030029A50000C09C004886E41400000C3B
+:10E6E0000000001500806018000063A8001808E111
+:10E6F0000000688C0100C69C001807D80100089D26
+:10E70000004886E4FBFFFF130100E79C08000000BF
+:10E71000000000150300C09C00302BE40400001032
+:10E72000000000157B4EFF0700000015000021854A
+:10E73000004800440400219CF8FF219C004801D4BB
+:10E74000045001D400406018180463A800004385F9
+:10E750007E5EFF07000000150040E018E003E7A818
+:10E760000100C09C00006784003023E40900000C15
+:10E77000000000150040A0182003A5A80000858413
+:10E7800000006784003023E4FDFFFF130000001544
+:10E7900000406018180463A80000638502506BE114
+:10E7A00007006B9D9F006BB85D0063B800186BE1BC
+:10E7B00083006BB9000021850400418500480044B6
+:10E7C0000800219CECFF219C004801D4045001D496
+:10E7D000086001D40C7001D4108001D4000083A91A
+:10E7E0000000009E00406018180463A80000C38564
+:10E7F00007008E9C9F0064B85D0063B8001884E039
+:10E80000525EFF07830044B904006018387963A89A
+:10E810005A4FFF0700008AA80040C018C403C6A8CA
+:10E820000100A09C00408018200384A8000066849A
+:10E83000002823E40700000C000000150000648499
+:10E8400001004A9D00608AE4F9FFFF1300000015F3
+:10E8500000606AE405000010000000150040601828
+:10E86000440363A800000386040060184E7963A87F
+:10E87000424FFF07000090A804006018617963A868
+:10E880003E4FFF0700008CA800406018180463A8E2
+:10E890000000638502706BE107006B9D9F006BB801
+:10E8A0005D0063B800186BE183006BB9000021853F
+:10E8B00004004185080081850C00C1851000018697
+:10E8C000004800441400219CA80583840000A3A8EC
+:10E8D000FFFF609C001804E40F0000100200C4B8A1
+:10E8E0000028E6E00415A784FF00809C002025E4B2
+:10E8F000130000100000609D841487841F00609C3A
+:10E90000001824E40E000010000000150C000000A8
+:10E91000A600609D80148584FF00609C001824E49C
+:10E92000070000100000609D7C1485841F00609C1F
+:10E93000001824E4F6FFFF0F000000150048004413
+:10E94000000000150F00849C0F00639C440084B8F5
+:10E95000440063B8FF1FA018E0FFA5A81F00849C17
+:10E960003F00639C032884E0460063B82000849C39
+:10E97000062363E0060063B8000063A90048004472
+:10E9800000000015E0FF219C004801D4045001D490
+:10E99000086001D4000043A9000084A984026384B4
+:10E9A000E9FFFF0788028A841017AA841800CB9C0D
+:10E9B00090006584101801D49800858400006CA82C
+:10E9C000182001D49400A5840C00819C142801D443
+:10E9D0000C3001D41400A09C1C5801D4D8FEFF07B1
+:10E9E0000100C09C0C006185000021850400418568
+:10E9F00008008185004800442000219CE8FF219CFC
+:10EA0000004801D41017C3840000E09C000064A8F3
+:10EA100084008684082001D48C00A6840400819C94
+:10EA2000102801D48800C6841400A09C0C3001D4A6
+:10EA3000042801D40100C09CC1FEFF07143801D492
+:10EA400000002185004800441800219CE8FF219C1B
+:10EA5000004801D43C16C3841017A3849C0065842D
+:10EA6000081801D4000064A8A4008584102001D4F3
+:10EA7000A000A5841700869C0C2801D4143001D472
+:10EA8000FCFFA09C0100C09C032884E0042001D46A
+:10EA90001400A09CAAFEFF070400819C040061856D
+:10EAA00000002185004800441800219CE8FF219CBB
+:10EAB000004801D4045001D4086001D40C7001D482
+:10EAC000108001D4149001D4A805A384000043A9A8
+:10EAD0000000609D020085B81017E3840000409E8E
+:10EAE0000018C4E00038A5E0003884E0CC00858D33
+:10EAF0000400C4854100ACB868148384009004E429
+:10EB0000050000108C160686009025E41100000C0C
+:10EB100000808EE04200ACB838166A840000809C09
+:10EB2000002003E40F00001000588EE1002025E4CF
+:10EB30000400000C00006AA80C00000000808CE0BB
+:10EB4000C3FFFF0700808CE00600000000004BAA16
+:10EB50008DFFFF0700000015F0FFFF034200ACB877
+:10EB600000808CE000006AA8A5FFFF07009084E009
+:10EB70000000218504004185080081850C00C185C5
+:10EB80001000018614004186004800441800219CB2
+:10EB9000F4FF219C004801D4045001D4086001D442
+:10EBA000000043A970178A9D6C1463844A5AFF07BA
+:10EBB00000008CA864146A84460083B80200A3A4F1
+:10EBC00010674AD4010063A4010084A4382E4AD4FB
+:10EBD000681C4AD42C264AD40000218504004185B3
+:10EBE00008008185004800440C00219C000063A9B6
+:10EBF0000048004400000015F0FF219C004801D4AB
+:10EC0000045001D4086001D40C7001D484028384C0
+:10EC1000000043A9880263840F00849C0F00639C5A
+:10EC20009F00A4B89F00C3B85C00A5B85C00C6B83C
+:10EC3000002884E0003063E0840084B8840063B876
+:10EC4000061BC4E11CFEFF0700006EA81F006BA599
+:10EC500000406018800363A802006BB900186BE1E4
+:10EC600000006B842D050004FFFF83A50100609C5C
+:10EC700000182BE404000010000000150300000041
+:10EC80004C664AD44C764AD4000021850400418564
+:10EC9000080081850C00C185004800441000219CBB
+:10ECA000FCFF219C004801D484028384000063A9F6
+:10ECB0000000009D880263840F00849C0F00639C09
+:10ECC0009F00A4B89F00C3B8B405EB855C00A5B84D
+:10ECD0005C00C6B81017EB84002884E0003063E0C5
+:10ECE000840084B8840063B80200AFB80000C78411
+:10ECF000061BA4E10038A5E058162B850400A58466
+:10ED00000248C6E007006D9C40168B84430063B840
+:10ED1000004024E4040000103C1E4BD4FFFF6D9C17
+:10ED20008C1C0BD48C046B84004063E50300001042
+:10ED30000000609C8C1C0BD43C166B842800639CE8
+:10ED4000001886E462000010CC008F9C004825E289
+:10ED500000400019200808A98C04EB840000609C86
+:10ED60001400F19D0000A8840A2B87E0441E4BD4B8
+:10ED700000406018240863A8000023850000C884B0
+:10ED8000062BA4E0063384E00228E7E0003864E0C4
+:10ED90000100839C0100609C001824E40400001022
+:10EDA0000700649C0000809C0700649C4300C3B87B
+:10EDB0000000A09C003085E40C00000C00000FA9AE
+:10EDC0000080E0181400E7A8003871E00000E09C23
+:10EDD0000100089D003803D80100A59C003085E49F
+:10EDE000FBFFFF130100639C0000A4A80700E4A43C
+:10EDF0000000809C002007E403000010FFFF6D9CD2
+:10EE0000FFFFA59C0000209D022863E00800639C92
+:10EE1000002007E4030000104300C3B80100209D58
+:10EE2000002005E4030000100000609C0100609CCD
+:10EE3000031869E0002003E40E0000100000A09C0D
+:10EE4000FF00609CFFFF089D883863E00080A018E9
+:10EE50000000A5A8FFFFC69CFF0063A4002888E06F
+:10EE6000083863E00100089D001804D80000A09C49
+:10EE7000003085E40B00000C000000150080E01855
+:10EE80000000E7A8003888E0FFFF609C0100A59C17
+:10EE9000001804D8003085E4FCFFFF130100849CB7
+:10EEA0003C166B840100E09C58168B841400639C14
+:10EEB000B405AB84001884E01017CB8458264BD4DB
+:10EEC0000030A5E006000000EC3805D8002087E0FF
+:10EED0000000648C040063A8001804D80000218599
+:10EEE000004800440400219CCCFF219C004801D430
+:10EEF000045001D4086001D40C7001D4108001D4F6
+:10EF0000149001D418A001D41CB001D4B405C3845A
+:10EF1000000043A90000009E020066B81017AA84F2
+:10EF20000000809D005083E000004586002863E0DB
+:10EF3000040083860000D2A95C176A846017EA8403
+:10EF40008C8644D4341E4AD4008003E40800000CAC
+:10EF5000303E4AD4002866E00000E09CEC3803D83C
+:10EF60000000609C4D0000000C1F4AD42000C19E90
+:10EF7000000087A8000076A81400A09C70FDFF0781
+:10EF80000200C09C1017EA842C0061848C008784E6
+:10EF9000002023E44100000C20008184006074E024
+:10EFA0000000C09C0000A4A81400849C00206EE413
+:10EFB000250000100100009DB4056A84003863E05C
+:10EFC000CC4003D80000609C00180CE4180000102E
+:10EFD0000C474AD410178A84B4056A84002063E081
+:10EFE000EC4003D820006184001810E230168A84B7
+:10EFF000000076A81400A09C006084E00200C09C81
+:10F00000008084E04EFDFF070260D2E11017EA8421
+:10F010002C0061848C008784002023E4E0FFFF1330
+:10F02000200081841E000000B4056A8410178A84C1
+:10F03000B4056A84002063E00000809CEAFFFF03BF
+:10F04000EC2003D830168A843DFDFF07006084E081
+:10F050000000E09CB405AA840C3F4AD4020085B8A5
+:10F0600020006184005084E01017CA8400188CE1ED
+:10F070000030A5E08C6644D40000609CCC1805D814
+:10F0800010178A84B4056A84002063E00100809C24
+:10F09000D7FFFF03EC2003D8B4056A84020063B8ED
+:10F0A00058168A84005063E08C16A384002884E0FC
+:10F0B00058264AD400002185040041850800818536
+:10F0C0000C00C1851000018614004186180081865D
+:10F0D0001C00C186004800443400219CECFF219CA8
+:10F0E000004801D4045001D4086001D40C7001D44C
+:10F0F000108001D4B405A384000083A90200A5B840
+:10F1000010176384006085E0000043850000A4A818
+:10F110008C16048684026C8402804AE188028C8406
+:10F1200009FEFF07A80EC5852C006B9C00186AE439
+:10F130000D00001018006B9D0C178C840000609C63
+:10F14000001824E42F0000100000001510178C8414
+:10F15000B4056C84002063E00200809C290000005C
+:10F16000CC2003D802008EB80040A0180006A5A845
+:10F17000B405EC8400400019080508A9FFFF609C55
+:10F18000001807E41F000010002884E070146C844D
+:10F190001017CC84020063B80000A4840030E7E0BC
+:10F1A000003063E0000088840B00A5B80400C3842D
+:10F1B000002884E0000068840100A09C003063E027
+:10F1C000FC2A4CD4022063E0008063E01400639CBE
+:10F1D000430063B8F81A4CD40000609CCC1807D8E0
+:10F1E00010178C84B4056C84002063E00100809CBF
+:10F1F000EC2003D858168C84005884E058264CD450
+:10F200000000218504004185080081850C00C1852E
+:10F2100010000186004800441400219CF4FF219C4A
+:10F22000004801D4045001D4086001D4FF0044A573
+:10F230000000A09CFFFF809C06004AB9B42503D4BF
+:10F24000A82503D4AC2D03D400408018682084A8DE
+:10F25000FFFFA09C00204AE1000083A900008A84EF
+:10F26000B02D03D4B82D03D4BC2D03D44300000427
+:10F27000882503D80000AA840000609CBA4BFF07D1
+:10F280000F00809C0100609C00580AD4281C4CD4BC
+:10F290000000218504004185080081850048004464
+:10F2A0000C00219CFFFF809CBC2503D4B42503D413
+:10F2B000A82503D40000809CAC2503D4FFFF809CCC
+:10F2C000B02503D4B82503D400480044000000153D
+:10F2D000B40583840000A3A8FFFF609C001804E429
+:10F2E000070000100200C4B8002866E08014C5843E
+:10F2F0007C14A584043543D4842C43D400480044B2
+:10F3000000000015F4FF219C004801D4045001D4F2
+:10F31000086001D4A805C384000043A90000809CB4
+:10F32000020086B9FFFF609C001806E40E00001082
+:10F330000400A09C0050ECE09018CA846BFCFF070E
+:10F340008414678400508CE00000CBA8041564840A
+:10F350000F00A09C90586AD464FCFF070800809CB2
+:10F3600090586AD4000021850400418508008185F9
+:10F37000004800440C00219CF0FF219C004801D46F
+:10F38000045001D4086001D40C7001D4000043A9DA
+:10F390000000809D0000609C8805AA8C001E0AD891
+:10F3A000011E0AD8021E0AD8DC1D0AD8DD1D0AD8A3
+:10F3B00000288CE50B00000CDE1D0AD80006CA9D53
+:10F3C00000008CA800006EA88054FF0701008C9DEF
+:10F3D0008805AA8C00288CE5FBFFFF1300008CA891
+:10F3E0000000218504004185080081850C00C1854D
+:10F3F000004800441000219CECFF219C004801D4EF
+:10F40000045001D4086001D40C7001D4108001D4E0
+:10F41000B8058384000043A9DC05839D8805A38C7F
+:10F420000000009E6954FF0700006CA8B8058A849C
+:10F43000040064B80413AA84022063E0020063B8E5
+:10F4400000186AE0008005E41B00000C2806C39D3C
+:10F450001014AA840200609C001825E40700001024
+:10F46000008025E418176A840C148A84141C4AD47A
+:10F47000170000001C244AD4030000101414609CE0
+:10F480001814609C18178A8400186AE0002003D4BE
+:10F490000000809C002025E4030000101C14609CE8
+:10F4A0002014609C0C148A8400186AE00800000094
+:10F4B000002003D4C8058A8400006CA84354FF07C9
+:10F4C0008805AA8CE4FFFF031014AA840400609C42
+:10F4D0000100809C03180ED878240AD400002185EE
+:10F4E00004004185080081850C00C185100001865B
+:10F4F000004800441400219CFCFF219C004801D4DA
+:10F500002406A3840000C3A81404E3840100009D22
+:10F51000004047E4030000100000209D000028A9DF
+:10F520000300609C001827E4030000100000809C8A
+:10F53000000088A8042089E00000609C001824E4F2
+:10F540000A0000100000001584166684004023E4C1
+:10F550002A0000100000609C0200609C001807E474
+:10F560002600000C0000609C064005D804006018CE
+:10F570006C9063A80400E0184083E7A8000083842F
+:10F5800000006784001824E4170000100000001534
+:10F590000000609C04008018408384A8381805D4BB
+:10F5A00000008484040060186C9063A80100E09C53
+:10F5B000002003D41704668C031805D81005668450
+:10F5C000FFFF639C003843E40400001000000015B6
+:10F5D0000C000000243805D4F404668409000000FF
+:10F5E000241805D40400E784301805D4343805D431
+:10F5F000E9FFFF030100609CDDFFFF03061805D84B
+:10F600000000609C281805D4781C06D400002185D1
+:10F61000004800440400219C0000A3A80000809C36
+:10F6200078046384002023E4220000100000001509
+:10F63000E4036584002023E41A0000100000001594
+:10F6400000406018209063A80100809C002003D433
+:10F650000000609CB4048584941D05D400406018AB
+:10F66000280863A84C04A584002003D40040801817
+:10F670002C0884A80000609C001804D40040601886
+:10F68000689063A800408018080884A8002803D464
+:10F690000100609C001804D409000000000000155F
+:10F6A00000406018209063A8E9FFFF030000809CE1
+:10F6B00000406018080463A8002003D400480044F8
+:10F6C00000000015FCFF219C004801D478048384CD
+:10F6D000000023A90000609C001824E42A00001008
+:10F6E0000000809C00406018200863A88C04A98456
+:10F6F000000083840A23C5E00400639C9402E9842B
+:10F70000000003850400639C062386E0003003D4D8
+:10F710000400639C0220A5E0002803D40040801868
+:10F72000689084A84C046984001804D40200609C8A
+:10F73000001827E40D00001000000015C4046998AB
+:10F74000FF7FA0180000A5A8100063B8C604899820
+:10F75000032863E0FF7F84A40040A0186490A5A85C
+:10F76000042063E0001805D400406018080863A86E
+:10F770000100809C0000A09C002003D40500000034
+:10F78000942D09D400406018080463A8002003D415
+:10F7900000002185004800440400219C0000A3A82B
+:10F7A000BDA2839C6F00609C001844E4040000101C
+:10F7B0004DA2859C330000000100609D0002609C0A
+:10F7C000001844E4040000104CA0859C2D000000AB
+:10F7D0000200609DE703609C001844E404000010F0
+:10F7E000649C859C270000000300609D8411609C40
+:10F7F000001844E42300000C0400609DDF8A859C0F
+:10F800003623609C001844E41E00000C0500609D37
+:10F81000FFFF6018A86763A8001885E0DF2E609CD2
+:10F82000001844E41700000C0600609DFFFF6018FC
+:10F83000C83863A8001885E00A23609C001844E4D7
+:10F840001000000C0700609DFFFF6018BE1563A844
+:10F85000001885E0010060188E1163A8001844E4C8
+:10F86000040000100000609C060000000800609D7D
+:10F87000001825E40300000C0900609D0400609D51
+:10F880000048004400000015F8FF219C004801D406
+:10F89000045001D4000043A90500809C0000609C36
+:10F8A000B0220AD4101A0AD41C1A0AD4201A0AD474
+:10F8B000041C0AD408180AD41C1C0AD4181C0AD424
+:10F8C000701C0AD46C1C0AD4BC1B0AD4481D0AD470
+:10F8D0004C1D0AD4501D0AD4541D0AD4581D0AD4F4
+:10F8E0005C1D0AD4601D0AD4641D0AD4681D0AD4A4
+:10F8F000841A0AD4881A0AD40000809C0800609CEC
+:10F90000B8220AD4B41A0AD40100809C0F00609C6B
+:10F91000C8220AD4781A0AD4F0240AD40000609CC1
+:10F9200004008018B48084A8781C0AD4D81A0AD499
+:10F93000781D0AD4C41A0AD4081D0AD40C1D0AD48E
+:10F94000FC1C0AD4000064840100809C00250AD4B9
+:10F950000000809C92FFFF0704250AD40040601835
+:10F96000209063A80100809C105D0AD4002003D47D
+:10F970000000609CFF0F809C441D0AD4004060186A
+:10F980008C9063A8002003D40000609C0100809C40
+:10F99000181A0AD4141D0AD4181D0AD41C1D0AD41E
+:10F9A000201D0AD4241D0AD42C1D0AD4301D0AD4CB
+:10F9B000341D0AD428250AD4FFFF609C0000809CD7
+:10F9C000381D0AD48C220AD40100609C3C250AD43C
+:10F9D00080240AD47C240AD4F41C0AD40000218593
+:10F9E00004004185004800440800219CD4FF219C6C
+:10F9F000004801D4045001D4086001D40C7001D433
+:10FA0000108001D4149001D418A001D41CB001D4EA
+:10FA100020C001D4000044A9FF0003A7FFFF809C81
+:10FA20000413EA840000609C282001D4B8050A86EB
+:10FA3000242001D4001807E47C000010BC058A864D
+:10FA4000C8054A8688056A8C0000C09DFF00C3A4D3
+:10FA500000308EE54800000C0000A3A8FFFFC09E08
+:10FA60002800618400B023E46800000C000078A83E
+:10FA700004138A840000609C001804E4070000104E
+:10FA80000000001524006184FFFF809D006023E4D6
+:10FA90005500000C000078A828006184008003E471
+:10FAA0000A000010000000152800618400A003E493
+:10FAB000060000100000001528006184009003E497
+:10FAC0000C00000C000000152800818400066A9CD0
+:10FAD000BE52FF07FF00A5A4FFFF609C00182BE4A7
+:10FAE0003B00000C000000158805AA8C281801D4E2
+:10FAF0000413EA840000609C001807E4180000105A
+:10FB00000000001524006184008003E40A00001056
+:10FB1000000000152400618400A003E4060000102A
+:10FB20000000001524006184009003E40C00000C28
+:10FB3000000000152400818400066A9CA352FF0780
+:10FB4000FF00A5A4FFFF609C00182BE42000000C20
+:10FB5000000000158805AA8C241801D40100CE9D50
+:10FB6000FF00C5A400308EE5BEFFFF1300000015A6
+:10FB70000413EA8428006184040083B8B41D0AD405
+:10FB8000701C4AD4021884E0020084B80000609C13
+:10FB900000208AE02806849C001807E40A00001070
+:10FBA00024260AD424008184040064B8C0250AD421
+:10FBB000022063E0020063B800186AE02806639C34
+:10FBC000D01D0AD41B0000000000609D7D00609CD9
+:10FBD0000100809CF41A4AD4F0224AD41500000097
+:10FBE000000063A9FF00C5A400068A9CA952FF0774
+:10FBF0002400A19C00602BE4F6FFFF0F7D00609CB9
+:10FC0000A6FFFF038805AA8C00068A9CA152FF0765
+:10FC10002800A19C00B02BE4EEFFFF0F7D00609C4C
+:10FC200094FFFF038805AA8C87FFFF03FFFF409E18
+:10FC30000000218504004185080081850C00C185F4
+:10FC40001000018614004186180081861C00C186C0
+:10FC500020000187004800442C00219CF0FF219CDB
+:10FC6000004801D4045001D4086001D40C7001D4C0
+:10FC7000C011A484000044A9FF00C3A5A818C4842F
+:10FC800000006EA80000809D2C178484DF53FF07BE
+:10FC90000230A5E0FCFF6B9D00602BE40800001023
+:10FCA0005C5C4AD40000609D00406018080463A8B2
+:10FCB000005803D413010000000000152C1A0004A2
+:10FCC00000006AA890056A84006023E40B0100101C
+:10FCD0000000C09C14046A84006003E40701001063
+:10FCE0000100609CAB00809C841E4AD488264AD4C4
+:10FCF0000600AEB800408018682084A80000809DEF
+:10FD00000020A5E00F00609C000085841049FF07DB
+:10FD10000000001500600BE4F400000C00006AA86D
+:10FD200028146A84006023E4060000100000001517
+:10FD30007C166A84006023E40600000C00000015B5
+:10FD400014048A84006004E4DF00000C0000001545
+:10FD500010026A840000809D006003E40900000C2A
+:10FD600000006EA800406018080463A80000809C92
+:10FD70000100609D002003D4E20000000000001597
+:10FD80001BFFFF0700008AA884166A84006003E452
+:10FD9000060000107D00609CB4056A84B81D0AD47A
+:10FDA000BC1D0AD47D00609C00182BE4D500000C1B
+:10FDB0000000609D47FDFF0700006AA864146A8484
+:10FDC000006003E4060000100000C09C10178A8445
+:10FDD000B4056A84002063E0EC3003D82C166A84F2
+:10FDE000006003E4B400000C0000001568146A848D
+:10FDF000006003E4AC00000C000000150100809CD2
+:10FE0000B405AA840000609C9C250AD4101A0AD468
+:10FE1000040085B8A01D0AD4022884E000006AA866
+:10FE2000020084B800208AE02806849CB3FDFF0706
+:10FE300024260AD47B1E000400006AA80040601833
+:10FE4000280B63A800008384006024E42D000010C8
+:10FE50000000001500408018080B84A80000A4844E
+:10FE6000000064847F00A5A4480063B83F00809C24
+:10FE70000020A5E4850000107F00C3A4020065B83F
+:10FE800000408018000684A8002063E00040A0180D
+:10FE90000C05A5A800008384000065840B0084B8CD
+:10FEA0000040A0182C0BA5A8002063E0001805D482
+:10FEB0003F00609C0018A6E46E000010020066B8C7
+:10FEC0000040A0180C05A5A80040C0180006C6A850
+:10FED000003063E000008384000065840B0084B878
+:10FEE0000100C09C0040A018300BA5A8002063E0D2
+:10FEF000001805D400406018280B63A8003003D414
+:10FF0000B4056A840000809D020063B80C14CA84A2
+:10FF1000005083E02814AA84000064A88C3344D4E1
+:10FF200018178A84006025E4060000100C2343D4CF
+:10FF30007C166A84006023E40600000C00000015B3
+:10FF400014048A84006024E42700000C00000015DB
+:10FF500084168A840000609C001824E416000010B7
+:10FF60000100809C941D0AD40100C09C00406018D0
+:10FF7000080863A8003003D49201000400006AA8B6
+:10FF80005800609C00182BE45E00000C0000609D8F
+:10FF900038168A840000609C001804E472FFFF1386
+:10FFA000000000153FFBFF0700006AA86EFFFF037B
+:10FFB00000000015B4056A840000C09C701E4AD47D
+:10FFC00094350AD400406018080863A8002003D4C0
+:10FFD0007C01000400006AA80000609CE9FFFF03A8
+:10FFE000841E4AD404006018797963A86349FF0726
+:10FFF0000000001584166A84006023E411000010DC
+:020000023000CC
+:100000000100809C00406018080863A80000C09CA4
+:10001000002003D494350AD46A01000400006AA8C1
+:100020005800609C00182BE43600000C0000609D16
+:100030000000809C28244AD4D6FFFF037C264AD4A3
+:10004000B405CA8400406018080863A870364AD412
+:10005000002003D40000C09C00006AA859010004DD
+:1000600094350AD40000609CEEFFFF03841E4AD43E
+:1000700000408018000684A80040A0180805A5A824
+:1000800095FFFF03002063E0020065B80040801880
+:10009000000684A80040A0180805A5A87EFFFF035D
+:1000A000002063E00EFCFF0700006AA855FFFF0375
+:1000B0000100809C8DFBFF0700006AA84DFFFF0335
+:1000C00068146A8404006018A27963A82B49FF07AA
+:1000D000000000150100C09CE852FF07A4350AD4B7
+:1000E000080000000100609D4DFCFF0700008EA885
+:1000F0000DFFFF0328146A84FEFEFF0384364AD4F2
+:100100000000218504004185080081850C00C1851F
+:10011000004800441000219C00406018889063A8AB
+:100120000100609D000083840000609C001084A496
+:10013000001804E40300000C000000150000609D9E
+:100140000048004400000015F4FF219C004801D441
+:10015000045001D4086001D4BC0383840100809D55
+:10016000006024E414000010000043A9B404838458
+:100170000000609D006084E0B004A384002864E572
+:100180002B000010B42403D400408018080484A875
+:10019000006004D4C813000400000015D7FCFF075A
+:1001A00000006AA81DFDFF0700006AA820000000EB
+:1001B00000006CA968166384006003E41500000C5D
+:1001C00000000015AC18AA840000809C002025E4E3
+:1001D0000400000C00006AA8150000000000609DEB
+:1001E000AF1900040000001504006018C47963A86A
+:1001F000E248FF078C048A84C0FCFF0700006AA85D
+:1002000031FDFF0700006AA80900000000006CA98A
+:10021000C2FFFF070000001500600BE40400000CA3
+:100220000000609DE9FFFF03AC18AA84000021854F
+:100230000400418508008185004800440C00219C91
+:10024000ECFF219C004801D4045001D4086001D483
+:100250000C7001D4108001D4FF00C3A5000006AAD1
+:10026000000047A910006018000063A80018A7E468
+:1002700005000010FF0085A500806018000063A83D
+:10028000041847E10000C09C00302AE4030000107D
+:100290000000E09C0100E09CAF18609C001848E45E
+:1002A000030000100000A09C0100A09C042867E04F
+:1002B000003003E48A00000C1000609D005004D45C
+:1002C000B018A09C00006AA8B350FF070000809CF3
+:1002D00004006018588363A80000809C0000C09C44
+:1002E000002003D48E350ADC040080185C8384A8C7
+:1002F00004006018548363A8003004D4003003D491
+:1003000004008018608384A804006018648363A8D4
+:10031000003004D4003003D40000809C0000609CB6
+:1003200040250AD490250AD489350AD8FFFF809C3D
+:10033000FFFFC09CB4250AD4A8250AD48C1D0ADC72
+:100340000000809C0000609CB8214AD8FF00809C7F
+:10035000B0350AD4B8350AD4BC350AD4D4350AD459
+:10036000D8350AD4101A0AD4AC1D0AD4C4194AD4F8
+:10037000281C4AD42C1C4AD4301C4AD4341C4AD4DD
+:10038000481C4AD4441C4AD4541C4AD4581C4AD44D
+:10039000401C4AD4601C4AD480244AD41F00C09C0C
+:1003A00004700AD87C344AD42C1E4AD4301E4AD455
+:1003B000341E4AD40C1F4AD4641E4AD46B4AFF0729
+:1003C000F41A4AD44352FF07000000150200609C53
+:1003D00000182CE43900000C000000150100609C9E
+:1003E00000182CE4280000101200C09C84350AD4A8
+:1003F0000100809C04006018508363A800200AD488
+:10040000002003D40000C09C00834AD424344AD482
+:100410000000809C1F00A09C8C166A9CFFFFC09C63
+:100420000100849C8034E3D70000C09C0035E3D7F2
+:100430007836E3D7F835E3D7003003D40028A4E5B5
+:10044000F7FFFF130400639C0200609C0000809C87
+:10045000101C4AD40100A09C1C146A9CFFFFC09C85
+:100460000100849CF837E3D70000C09C003003D41F
+:100470000028A4E5FAFFFF130400639C18000000A5
+:100480000000609D0300609C00182CE40400001034
+:100490001400609CD7FFFF03841D0AD40400609CF5
+:1004A00000182CE4D2FFFF130000C09C1600809CB3
+:1004B000D0FFFF0384250AD404006018D97963A80B
+:1004C0002E48FF070000809C1000609C0100809C6B
+:1004D000841D0AD4C8FFFF0308200AD40000218528
+:1004E00004004185080081850C00C185100001864B
+:1004F000004800441400219CFCFF219C004801D4CA
+:1005000000406018849063A80000C09C00008384B1
+:100510000000A384FFFF04A500406018200863A822
+:10052000500025B9000083842800639C0000838468
+:10053000003004E41C0000100000001500406018AA
+:100540002C0C63A8000083840000A3845000E4B84E
+:1005500000406018200863A8FFFFC5A40000838442
+:10056000003028E4030000100000A09C0100A09CC3
+:10057000003829E4030000100000809C0100809CEA
+:10058000032085E00000609C001804E404000010D3
+:1005900000000015080000000100609D060000003A
+:1005A0000000609D00406018280C63A8E6FFFF0370
+:1005B0000000001500002185004800440400219C33
+:1005C000E8FF219C004801D4045001D4086001D404
+:1005D0000C7001D4108001D4000043A914006018ED
+:1005E000804363A8141801D484026A8488028A8430
+:1005F0000F00639C0F00849C9F00A3B89F00C4B8A9
+:100600005C00A5B85C00C6B8002863E0003084E058
+:10061000840063B8840084B8062363E04C1E4AD487
+:10062000541E4AD40000809C0808609CF0224AD4E2
+:100630002C42FF070100809CCE00000400006AA845
+:10064000F0128A840000609C001804E41800000C7A
+:1006500000000BAA0000C09C50166A841400801889
+:10066000804384A80000809DF0324AD40100639C3E
+:10067000142001D4501E4AD4A0FFFF07000000152B
+:100680005800809C1400619C00600BE40A00000C80
+:100690000000AAA86B07000400000015F0126A848D
+:1006A000006003E4F5FFFF13000000153E000000AA
+:1006B000F4126A850000C09C14006018804363A88F
+:1006C000F0324AD40040A0181005A5A8141801D48F
+:1006D000000085840000609C001824E40F00000CDA
+:1006E0001400619C0000C5A90000809D5800809CFA
+:1006F000540700040000AAA8F0126A84006003E412
+:10070000EBFFFF0F0000001500006E84006023E483
+:10071000F7FFFF131400619CFC126A840000809CA8
+:10072000002003E419000010000000150040A0188C
+:10073000380CA5A8F0224AD41400C0188043C6A8DB
+:1007400000006584002023E41000000C143001D464
+:100750000000C5A90000809D1400619C5800809C89
+:10076000380700040000AAA8F0126A84006003E4BD
+:10077000CFFFFF0F0000001500006E84006023E42F
+:10078000F7FFFF131400619C70FEFF0700006AA8CA
+:100790000000609C00182BE4A4FFFF130000809C65
+:1007A000000070A9000021850400418508008185B2
+:1007B0000C00C18510000186004800441800219CEF
+:1007C000F0FF219C004801D4045001D4086001D4FA
+:1007D0000C7001D42406C385000043A9CC02838495
+:1007E0000100609C001824E40700001000000015C0
+:1007F000BC036A840000809D006023E45000000C6C
+:100800000000001508006A840100809C002003E4B9
+:10081000120000100100609CBC036A84002023E4E5
+:100820000800001000000015B0046A84B4048A8433
+:10083000FFFF639C001804E4080000100100609CA6
+:10084000CC028A840000609C001824E4430000105D
+:10085000000000150100609C0000809C1C1D0AD453
+:100860000000809D00406018080463A8002003D4A5
+:1008700006006E8C006003E423000010FFFF609C04
+:10088000B8058A84001804E41300000CDC05CA9D36
+:1008900004138A84B8056A84BC1D0AD4B4056A842A
+:1008A000B81D0AD40000609C001804E40700001082
+:1008B0000100809CC8058A84C0056A84CC250AD4BE
+:1008C000C81D0AD40100809CA0250AD42300000082
+:1008D000A4250AD48805AA8C3C4FFF0700006EA807
+:1008E00004138A84006004E4EBFFFF1300006EA889
+:1008F000C8058A84354FFF078805AA8CE6FFFF03E9
+:1009000004138A84DC05CA9DB4058A8400006EA89D
+:100910002E4FFF078805AA8C04136A84006003E445
+:10092000E9FFFF1300006EA8C0058A84274FFF0768
+:100930008805AA8CE5FFFF030100809CF7FDFF07F7
+:100940000000001500602BE4C3FFFF0F000000153E
+:10095000AEFFFF0308006A84000021850400418582
+:10096000080081850C00C185004800441000219CCE
+:10097000E4FF219C004801D4045001D4086001D454
+:100980000C7001D4108001D4149001D4000043A94C
+:100990000000009E14006018804363A8181801D45A
+:1009A00008008A840100609C001824E40D000010F7
+:1009B0000000409E14046A84008023E409000010B3
+:1009C0000000001500406018C40363A800006384A1
+:1009D000008023E488000010010063A4F0940AD48E
+:1009E000004060180C0863A80000809C002003D41D
+:1009F00000408018889084A800008485C755FF07B0
+:100A0000000000155C148A840400609C585C4AD481
+:100A1000025864E100184BE47100000C000000155E
+:100A20000040A0188490A5A80000E09C00008584E8
+:100A3000FE0FCCA40000C09D00006584500084B867
+:100A4000FFFF63A4683E4AD4403E4AD478264AD485
+:100A5000007006E42E00000C741E4AD40000A09C16
+:100A6000F02A4AD4982D0AD40000E09C00006AA81D
+:100A7000103A0AD46A0000040000809D60166A845F
+:100A8000006023E4060000100000CBA900602BE406
+:100A90001800000C000000150000009E0100A09C42
+:100AA00000282EE4030000100000609C000065A8F0
+:100AB000002832E4030000100000809C000085A89C
+:100AC000042083E00000609C001824E4040000106F
+:100AD000002810E40500000C0100609C39FFFF07AE
+:100AE00000006AA80100609C45000000941D0AD423
+:100AF0008AFDFF070000001500602BE4E7FFFF13ED
+:100B00000100009EE7FFFF030100A09C00008CA8ED
+:100B100004006018E17963A89846FF070100409E31
+:100B200000408018000084A8FB03609CB405AA84E0
+:100B3000FF03E09C0040C0181005C6A8001804D4AC
+:100B4000702E4AD4020065B8003804D4F0724AD43A
+:100B5000B805EA84005063E0A500A09C00008684EC
+:100B6000842D43D440964AD46C3E4AD4007024E489
+:100B70001200000C98950AD40000C6A90000809DC0
+:100B80000000609C5800809CF01A4AD40000AAA87B
+:100B90002C0600041800619CF0126A84006003E4D3
+:100BA0000D00000C0000001500006E84006023E4BE
+:100BB000F5FFFF130000609C0000809C004060185F
+:100BC000889063A8F0224AD4002003D4A8FFFF0332
+:100BD0000000E09C0A000000F4126A85040060181E
+:100BE000E97963A86546FF0758244AD48DFFFF03BF
+:100BF000000000157BFFFF03F01C0AD400002185D4
+:100C000004004185080081850C00C1851000018623
+:100C100014004186004800441C00219CE4FF219CF4
+:100C2000004801D4045001D4086001D40C7001D4F0
+:100C3000108001D4149001D418A001D484028384BC
+:100C4000000043A90040E0188490E7A8880263856B
+:100C50000F00849C0000809D0F00CB9C9F0064B817
+:100C60009F00A6B8000007855C0063B85C00A5B8CB
+:100C700000002785001884E00028C6E0840084B8BE
+:100C80008400C6B800406018C40363A85000C8B907
+:100C9000063384E00000A384FFFF09A644146A849D
+:100CA000006003E41800000CFFFF449E006025E490
+:100CB0003100000C000000150F006B9C9F0083B8F2
+:100CC0005C0084B8002063E0840063B8FFFF639C8D
+:100CD00000182EE40E0000100000001584026A8443
+:100CE0000F00639C9F0083B85C0084B8002063E021
+:100CF000840063B8FFFF639C001830E40400001018
+:100D000000000015200000000100609D60166A844C
+:100D10000000809E00A023E40400000C00000015E9
+:100D2000190000000000609D00406018200863A8C2
+:100D30000000838406238EE0F8FCFF07008084E136
+:100D40005C166A840100809C002023E4F5FFFF13F9
+:100D5000645E4AD4FEFF729C00188CE5F1FFFF131D
+:100D600000A02BE4EFFFFF130000001506000000B9
+:100D7000000064A9F554FF0700000015CFFFFF0332
+:100D800088026A850000218504004185080081856C
+:100D90000C00C18510000186140041861800818670
+:100DA000004800441C00219CA805E3840000A3A87F
+:100DB000FFFF809C040067B8023863E0020063B85C
+:100DC000001865E0002007E43B0000102806C39CE3
+:100DD000101405850200609C001808E43300001020
+:100DE000020067B80300868C0400609C001824E4AD
+:100DF0002E000010020067B8020068B81C14839C23
+:100E00001414639C002085E0001865E00000C48491
+:100E1000283745D4000084840000C384242745D4A7
+:100E2000203745D41C3745D4780465840100C09C24
+:100E3000003023E41A0000100200609C1014858426
+:100E4000001824E4100000100000609C0000809C4A
+:100E5000102445D4641485840000609C001804E4C8
+:100E60001B00001000000015A8058584101765847C
+:100E7000542745D4001867E0EC00838C1400000070
+:100E8000502745D4001824E403000010000000158A
+:100E9000000066A8F0FFFF03101C45D40200C09CB0
+:100EA000EDFFFF03103445D48C13839CD6FFFF0362
+:100EB0000C13639C0000609C202745D41C2745D45C
+:100EC000241F45D4D9FFFF03281F45D44002658461
+:100ED00044028584100063B83C02C584042063E0AA
+:100EE000A03065D4A41865D4004800440000001563
+:100EF000F8FF219C004801D4045001D4B405838438
+:100F00000000C3A8FFFF609C001824E45200000CFE
+:100F1000020084B80413A68404006018508363A8F8
+:100F20000030E4E00000809C002005E44100001057
+:100F3000002003D4C0056684020063B80030A3E03B
+:100F4000280F8584004060180C1663A8A80EC5847D
+:100F5000080084B8003084E0002003D40040C018AA
+:100F60001016C6A80000609C0040A0180C16A5A88A
+:100F7000001806D400408018181684A80000A58424
+:100F800000406018141663A80040401924164AA9AE
+:100F9000002803D40000C68400406018240863A819
+:100FA0000040A0182008A5A8003004D400008384C5
+:100FB0000000C584080084B8004060181C1663A8AF
+:100FC000003084E0002003D40100809C00406018C1
+:100FD000001663A800200AD4002003D48745FF0729
+:100FE000000000150000609C0000809C00180AD4DE
+:100FF0000040A0182C16A5A800406018041663A88D
+:10100000002003D400408018281684A800406018EF
+:10101000302063A800008484002003D40000A5844D
+:101020000400639C002803D40B000000000000159E
+:10103000280F6784004080180C1684A8A80EA78487
+:10104000080063B8002863E0001804D4C4FFFF035D
+:10105000000000150000218504004185004800447F
+:101060000800219CF8FF219C004801D4045001D4C1
+:1010700004006018C08063A8000044A90000A38495
+:1010800000FF859C1F00609C001844E41400000CC5
+:101090000000609DE0FE859C0F00609C001844E409
+:1010A0003400000CFF0065A41400809C50FF639C7A
+:1010B000002043E40A000010020063B80400801816
+:1010C000087A84A8002063E00000838400200044A4
+:1010D000000000151C10000400006AA80000609CBD
+:1010E00000180BE4070000107300609C0100809C56
+:1010F000F41A4AD4F0224AD42C000000000063A95C
+:101100002A0000000000609D1C10000400006AA876
+:10111000F4FFFF030000609CA010000400006AA818
+:10112000F0FFFF030000609CA910000400006AA803
+:10113000ECFFFF030000609C5413000400006AA849
+:101140000000609C00182BE4E6FFFF130100809C68
+:10115000E4FFFF0304240AD40100609C201A0AD48F
+:10116000BD10000400006AA8DEFFFF030000609CC1
+:101170003E11000400006AA80000609C00182BE4E7
+:10118000060000107300809C0100609C1C1A0AD4A9
+:10119000DCFFFF03201A0AD40100609CF4224AD429
+:1011A000D8FFFF03F01A4AD40000218504004185CE
+:1011B000004800440800219CE0FF219C004801D425
+:1011C000045001D4086001D40C7001D4108001D403
+:1011D000149001D418A001D41CB001D4FF0043A680
+:1011E000000084A90000609C2C1784840000009EED
+:1011F000A8186CD4C011AC84844EFF07000072A8FC
+:10120000FCFFCB9D4DF5FF075C744CD4060072B813
+:1012100000408018482084A8002063E000008384F8
+:1012200000208BE40600001000802EE40100A09C4A
+:10123000602C4CD43E0000000000609D3C00000C7F
+:101240000000609D00804EE42500000C00000015A9
+:101250000400801AC08094AA0040C01A1804D6AABC
+:101260000040A0188003A5A8000072A80000A58473
+:1012700000008CA8002814D40000C5A8B601A09CCA
+:10128000002826E4060000100100609D1C02AC84CA
+:10129000005825E42600000C000000150400A018EA
+:1012A000C080A5A80000C58400FFA09C0328C6E05C
+:1012B0000001A09C002826E41000000C000000158E
+:1012C00000406018200363A80100109E0000A38462
+:1012D00000804EE4E3FFFF13000000151C026C8445
+:1012E0000100609D005823E41100000C000000156F
+:1012F0000F0000000000609D000056850040A0180F
+:101300000003A5A80000A58457FFFF0700000015F3
+:101310008E53FF070000001500007684025063E042
+:10132000430063B8EBFFFF03001810E200002185C3
+:1013300004004185080081850C00C18510000186EC
+:1013400014004186180081861C00C18600480044B4
+:101350002000219CECFF219C004801D4045001D4C2
+:10136000086001D40C7001D4108001D4A805C38496
+:10137000000043A9DC05C39D0006839D0000009E7C
+:1013800000006CA8FFFFA09C002806E42400000CCD
+:10139000000086A804136A84008003E4080000109B
+:1013A000FFFFA09CC405CA8400068A9D000086A891
+:1013B000002806E41000000C00006CA88805AA8C28
+:1013C000A8058A9C074DFF0700006EA80413CA8475
+:1013D000C4058A9C0000A09C002806E41B000010A5
+:1013E00000006EA8FF4CFF078805AA8C17000000BC
+:1013F00000000015324DFF078805AA8C00802BE401
+:10140000EFFFFF1300006CA8C4058A846F4CFF0730
+:101410008805AA8CEBFFFF038805AA8C284DFF07DF
+:101420008805AA8C0000809C00202BE4DAFFFF13C3
+:1014300000006CA8A8058A84644CFF078805AA8C64
+:10144000D6FFFF0304136A84000021850400418550
+:10145000080081850C00C185100001860048004409
+:101460001400219C1404C3840000009D0100E09C32
+:10147000004026E40300000C0900609C0A00609C08
+:10148000020063B800408018000384A80020A3E095
+:1014900000408018800384A8002063E0000083845B
+:1014A000003824E4050000100000001500006584E9
+:1014B000F0FFFF0300000015004800440000001585
+:1014C000D8FF219C004801D4045001D4086001D405
+:1014D0000C7001D4108001D4149001D418A001D450
+:1014E0001CB001D420C001D424D001D4C011A484E4
+:1014F000000084A9FF0003A7A818C484000078A8EE
+:101500000000009E2C1784840230A5E0BF4DFF0729
+:101510000000C09DFCFF4B9D00802AE404000010E9
+:101520005C544CD4A70100000000609D00804AE498
+:101530002000000C000000150400C01AC080D6AACC
+:101540000000409F00406018800363A80080C09C9A
+:10155000000063840040401A180452AA00008CA8BE
+:10156000001816D40000B6840330E5E000FFC09CEC
+:101570000330A5E00001C09C003025E47601000C9A
+:10158000000078A8008060A8001827E46C01000C17
+:101590000000001500406018200363A80100CE9DE4
+:1015A0000000A38400704AE4E7FFFF130000001569
+:1015B000DA52FF070000001508136C8400186BE472
+:1015C00008000010585C4CD45C168C840000609CB1
+:1015D000001804E40300001001006B9D585C4CD41B
+:1015E00020026C840000809C002023E4070000108F
+:1015F0000000609D00406018080463A8005803D4F0
+:10160000700100000000001590056C84002023E4A8
+:10161000490100100000A09C14046C84002003E425
+:10162000450100100100609CAB00809C841E4CD4DE
+:1016300088264CD444146C840100409DFFFF639CB9
+:10164000005043E4050000100000C09DA4550CD4D8
+:101650005C0100000100609D0600B8B80040C018A1
+:101660006820C6A80030A5E00F00609C00008584BB
+:10167000B742FF070000001500700BE42A01000CC0
+:1016800000006CA828146C84007023E4060000108D
+:10169000000000157C166C84007023E40600000C2A
+:1016A0000000001514048C84007004E41601000C82
+:1016B0000000001504046C840000409D005003E409
+:1016C0000B0100100000001524046C84005023E47A
+:1016D0000201000C00501AE4140000100100A09C4C
+:1016E00000408018080484A800006CA8002804D4D6
+:1016F0006B1400040000001580F7FF0700006CA8C1
+:10170000F1F7FF0700006CA8AEFBFF0700006CA814
+:101710005800609C00182BE483FFFF0F00000015A9
+:10172000280100000100609D000078A8B0F8FF07C4
+:1017300000008CA884166C84005003E4050000109F
+:1017400000000BAAB405CC84B8350CD4BC350CD43D
+:101750007D00609C001830E41A01000C0000609DC0
+:10176000DCF6FF0700006CA864146C84005003E4EE
+:10177000070000100000001510178C84B4056C845D
+:10178000002063E00000809CEC2003D82C166C84C1
+:10179000005003E4CD00000C0000001568146C84B8
+:1017A000005003E4C500000C0000001553F7FF07CC
+:1017B00000006CA80000C09C0100A09C04340CD464
+:1017C0009C2D0CD4A0350CD478046C840000409D72
+:1017D000005023E4A900001000000015004060182C
+:1017E000280B63A800008384005024E4300000101C
+:1017F00000006CA804136C84005003E49D000010EA
+:1018000000000015C0056C84020063B8006083E02E
+:10181000280FC4843F00609CA80E84840018A4E4B0
+:101820008C000010020064B80040A0180C05A5A8A8
+:1018300000408018000684A8002063E00000838434
+:10184000000065840B0084B80040A0182C0BA5A8EC
+:10185000002063E0001805D43F00609C0018A6E457
+:1018600076000010020066B80040A0180C05A5A87C
+:101870000040C0180006C6A8003063E00000838462
+:10188000000065840B0084B80040A018300BA5A8A8
+:10189000002063E0001805D400406018280B63A8FE
+:1018A0000100A09C002803D400006CA826150004A9
+:1018B0000000409DB4056C84020063B80C14CC8415
+:1018C000006083E02814AC84000064A88C3344D406
+:1018D00094550CD418178C8498550CD4005025E4DA
+:1018E000060000100C2343D47C166C84005023E4C3
+:1018F0000600000C0000001514048C84005024E441
+:101900002900000C00000015D7FEFF0700006CA89E
+:1019100084168C840000609C001824E417000010DA
+:101920000100809C00408018080884A80100A09C49
+:1019300000006CA8002804D422FBFF07000000155B
+:1019400000000BAA5800609C001830E49D00000CB9
+:101950000000609D38168C840000609C001804E430
+:101960003CFFFF1300000015CEF4FF0700006CA839
+:10197000940000000100609D00406018080863A802
+:10198000B405CC84002003D470364CD40DFBFF0783
+:1019900000006CA80000A09C00000BAAEAFFFF0357
+:1019A000842E4CD404006018797963A8F342FF07B1
+:1019B00000000015ACFEFF0700006CA884166C84C4
+:1019C000005023E4120000100100809C00408018A9
+:1019D000080884A80100A09C00006CA8002804D47A
+:1019E000F8FAFF070000001500000BAA5800609CE1
+:1019F000001830E47300000C0000609D0000C09CE3
+:101A000028344CD4D4FFFF037C364CD400406018FB
+:101A1000080863A8B405CC84002003D470364CD4E5
+:101A2000E8FAFF0700006CA80000A09C00000BAAC9
+:101A3000EFFFFF03842E4CD400408018000684A8DA
+:101A40000040A0180805A5A88DFFFF03002063E053
+:101A50000040A0180006A5A8002863E000008384C9
+:101A60000040A0180805A5A876FFFF030000001598
+:101A700066FFFF03B4056C84804CFF07000000156F
+:101A80000100C09C0000809C28146C8494350CD408
+:101A9000005023E40600001098250CD47C166C84BA
+:101AA000005023E4EBFEFF0F000000150100A09C96
+:101AB000E8FEFF03A42D0CD489F5FF0700006CA8F5
+:101AC0003BFFFF030000001508F5FF0700006CA8AE
+:101AD00034FFFF0368146C8448F6FF0700006CA80D
+:101AE0000100609C39FFFF03A41D0CD404006018A2
+:101AF0005C7A63A8A142FF070100809C31000000CE
+:101B00000100609D04006018A27963A89B42FF0752
+:101B100000000015594CFF07A4550CD42900000003
+:101B20000100609DBEF5FF07000098A8D7FEFF03E7
+:101B300028146C84C0FEFF03842E4CD4004060182F
+:101B4000440363A80100409F0000A38499FEFF03A3
+:101B500000000015000092860040A0180003A5A810
+:101B60000000A58440FDFF07000000157300609C85
+:101B700000182BE41000000C0100C09C04046C84CD
+:101B800000D003E40900000C000000156F51FF07AE
+:101B9000000000150000728402A063E0430063B8F7
+:101BA00081FEFF030018CEE10000728481FEFF0376
+:101BB00000000015F41A4CD45BFEFF03F0324CD445
+:101BC0000000218504004185080081850C00C18545
+:101BD0001000018614004186180081861C00C18611
+:101BE0002000018724004187004800442800219CF0
+:101BF0000000A3A874058584F501609C001804E426
+:101C00000E000010001844E512000010F701609C5F
+:101C1000F401609C001804E40800001000000015A6
+:101C20008405A58400406018300863A8002803D408
+:101C3000170000000000001500406018300863A87D
+:101C40001400809C002003D4110000000000001547
+:101C5000001804E4F3FFFF0F0000609C7C058584FE
+:101C6000001804E406000010000000150040601891
+:101C7000300863A8F4FFFF030000809C0040601858
+:101C8000300863A8F0FFFF031600809C0048004462
+:101C900000000015E8FF219C004801D4045001D445
+:101CA000086001D40C7001D4108001D4149001D4C8
+:101CB0000040A0183008A5A8FF0003A60000C584B6
+:101CC000000044A90000409E3E00C6A41000609C95
+:101CD000001826E4740000100000C09D4E50FF075D
+:101CE000060090B95F44FF0700000015004080180F
+:101CF000542084A80040A0185020A5A800206CE023
+:101D00000000638400288CE0841A0AD400008484D4
+:101D100000406018000563A888220AD40000C3842C
+:101D200000408018002084A80400AA8C004060189D
+:101D3000082063A8002804D40413CA8484028A8477
+:101D4000002003D48802AA8400408018042084A8BC
+:101D50000300609C002804D4881D0AD80100609C00
+:101D6000001826E44B0000100300A09C00406018FF
+:101D70000C2063A80600809C002003D42000E09C77
+:101D8000A80D6A9C280E8A9CA80EAA9C3B4CFF07B3
+:101D9000280FCA9C0040C0184020C6A888028A8428
+:101DA0000030ACE0FFFFC0A884026A84003005D494
+:101DB000CD50FF0700000015B04BFF0794586AD4C0
+:101DC000FAFBFF0700006AA824146A843D46FF0757
+:101DD00014178A9C2C44FF07000000158402AA8473
+:101DE0000005609C001845E506000010D002609CCC
+:101DF00088028A84001844E50A00000C0008609CF0
+:101E00004847FF0724146A840000609C00180BE414
+:101E10000C00000C000000158402AA840008609CDD
+:101E2000001845E5070000100000001588028A84AC
+:101E30004004609C001844E50700000C00000015F9
+:101E40001C00C09D000090A80000AEA8A9000000E2
+:101E50002000609C8C028A840000609C001804E4CE
+:101E60000A000010000000150800809C0040601867
+:101E70001C2063A80000A09C002003D4000090A8B0
+:101E80009C0000000400609CF9FFFF030000809CA0
+:101E9000004060180C2063A8002803D4B9FFFF039A
+:101EA0002000E09CC5FCFF07000070A89B50FF07C6
+:101EB00000008BA900406018182063A860148A8471
+:101EC000005803D40100609C001824E404000010B2
+:101ED000585C4AD43400C09D0000809D8402AA84CE
+:101EE0000005609C001845E506000010D002609CCB
+:101EF00088028A84001844E50800000C0008609CF1
+:101F00000847FF0724146A8400900BE40A00000CC1
+:101F10000008609C8402AA84001845E506000010B1
+:101F20004004609C88028A84001844E50400000C88
+:101F3000000000151C00C09D0000809DF4128A84E2
+:101F40000000609C001804E4040000100100409EA2
+:101F50000000C4A90000809D00902CE453000010F4
+:101F600000000015AC4FFF0700000015BD43FF0740
+:101F7000000000150400AA8C00406018002063A82F
+:101F800000408018082084A8002803D40400C09CC6
+:101F900084026A84001804D40413AA8400406018E0
+:101FA000042063A888028A84002003D4009025E4DA
+:101FB0003800001088350AD80800639C0800809C0F
+:101FC000002003D42000E09CA80D6A9C280E8A9C67
+:101FD000A80EAA9CA94BFF07280FCA9C0600B0B800
+:101FE0000040C0184020C6A888028A840030A5E0BE
+:101FF000FFFFC0A884026A84003005D43A50FF076E
+:102000000000001594586AD468FBFF0700006AA816
+:102010007C146A840000809C0400A09C33F1FF07BC
+:102020009018CA8480146A840000CBA80F00A09C7A
+:102030000800809C2DF1FF0790586AD400006AA820
+:1020400022F2FF0790586AD424146A8414178A9CD9
+:102050009C45FF0700004BAA8B43FF0700000015BB
+:102060008C028A840000609C001804E407000010C1
+:10207000000000150800809C004060181C2063A828
+:102080007EFFFF031000B2B8FCFFFF030000809C3E
+:10209000004060180C2063A80400A09C002803D412
+:1020A000CAFFFF032000E09C5B4FFF070000001504
+:1020B0006C43FF070000001504006A8C0040A01864
+:1020C0000020A5A8060090B8001805D400406018AC
+:1020D000402063A8FFFFA0A8001884E0002804D4D3
+:1020E0006943FF070000001558FFFF03000090A898
+:1020F0000000C09C4C43FF070000E09C00002185CD
+:1021000004004185080081850C00C185100001860E
+:1021100014004186004800441800219CF8FF219CCF
+:10212000004801D4045001D4000045A9FF0084A454
+:102130000200609C0000A4A87D4EFF0700008AA852
+:102140004005AA840000809C002025E406000010C1
+:1021500000006AA8CDF5FF07000000150100609C93
+:10216000401D0AD400002185040041850048004438
+:102170000800219CFFFF809CD82503D4B42503D4FC
+:10218000A82503D40000809CAC2503D4FFFF809CCD
+:10219000B02503D4B82503D4BC2503D4D42503D457
+:1021A0000048004400000015F4FF219C004801D4C1
+:1021B000045001D4086001D4B8058384000083A9C9
+:1021C000DC05439D8805A38C0049FF0700006AA831
+:1021D0000413AC840000809C002005E4050000107E
+:1021E00000006AA88805AC8CF848FF07C8058C84F5
+:1021F00000002185040041850800818500480044D5
+:102200000C00219CF4FF219C004801D4045001D40F
+:10221000086001D4000084A9000043A90000809C4C
+:10222000482443D4442443D42C2443D4D2FFFF076E
+:10223000302443D4004060181C2063A80300A09CF5
+:1022400048148A84002803D45814AA8400406018D3
+:10225000182063A8002803D4040060187D7A63A8BE
+:10226000C640FF0700000015EB4EFF0700000015F9
+:10227000FC42FF07000000150400AA8C00408018F3
+:10228000002084A806006CB8002804D404164A9DD7
+:1022900000408018402084A8FFFFA0A8002063E031
+:1022A000002803D4F842FF0700000015344BFF0755
+:1022B00000006AA800008CA80500609C0000A09C9B
+:1022C0000000C09CD842FF070000E09C0000218570
+:1022D0000400418508008185004800440C00219CD1
+:1022E000F8FF219C004801D4045001D44414A38475
+:1022F0000200809C002025E40D000010000043A98E
+:102300004814A3840500809C002005E40800001008
+:102310000000809CA5FFFF07442443D496FFFF07DD
+:1023200000006AA80100609C401C4AD4000021857E
+:1023300004004185004800440800219CFCFF219CCA
+:10234000004801D4FF00C4A40100809C002026E4C2
+:1023500006000010FF00E3A42C146584002023E491
+:102360003200000C000000150400609C001826E4F8
+:102370000700001000000015301485840100609CE7
+:10238000001824E42600000C0400609C001826E4D9
+:10239000070000100200609C2C1485840000609CE3
+:1023A000001824E41B00000C0200609C001826E4C6
+:1023B000070000100200609C2C1485840000609CC3
+:1023C000001824E41000000C0200609C001826E4B1
+:1023D000190000100000609D301485840000609C8E
+:1023E000001824E414000010000000150400858C7F
+:1023F0000C00A09C2045FF07000067A80E0000000D
+:10240000FFFF609D0400858CFBFFFF030B00A09C79
+:102410000400858CF8FFFF030800A09C0400858C55
+:10242000F5FFFF030900A09C0400858CF2FFFF0369
+:102430000600A09C00002185004800440400219C67
+:102440000000C5A80000A384FFFFA59C002803D4BA
+:102450000000609C001845E5040000100100609C2D
+:10246000F42246D4F01A46D4004800440000001577
+:10247000F4FF219C0300A09C0200C09C002801D80E
+:102480000C00E19C0700A4A4013001D8022884E0DC
+:102490000028C7E0002063E00100A09C0000E09C51
+:1024A000022801D80700809C0600A09C033801D8B0
+:1024B0000500E09C042001D80400809C052801D878
+:1024C0000B00A09C063801D8072001D8082801D8A5
+:1024D000F4FF868C0080C0180000C6A8002063E0CE
+:1024E000003063E00000638D004800440C00219C34
+:1024F000D8FF219C004801D4045001D4000044A915
+:102500000100A09C0000809CFF0063A4082001D46F
+:102510000C2801D40300809C060063B80040A0187A
+:102520004420A5A8102001D40000609D002883E06D
+:102530000000E09C0400A59C0000C09C002863E013
+:102540000000A4840700809C0B00A5B8142001D4CF
+:102550000F00809C182001D4000083841F00609C21
+:102560001C1801D42000639C201801D47F00609CBB
+:10257000003805E403000010241801D40100C09CB9
+:10258000003804E4030000100000609C0100609C1F
+:10259000031866E0003803E41400000CFFFF849C7D
+:1025A0000700C09C0000809C0000A6A95C264AD4BD
+:1025B000FF00209D0000009D2400A19C02306DE0E2
+:1025C00000008584881869E0FFFFC69C0358E3E09B
+:1025D000002027E409000010FCFFA59C0100609C7E
+:1025E000060000005C1E4AD4A2FFFF07000065A899
+:1025F000ECFFFF03FF006BA5004066E5F1FFFF1352
+:1026000002306DE00000218504004185004800444F
+:102610002800219CF0FF219C004801D4045001D4E3
+:10262000086001D40C7001D4000043A966F0FF07D4
+:102630000000C4A900508BE505000010FFFF609C5E
+:102640000000809C3500000068264ED40100609C8C
+:1026500084024E85681E4ED40F004A9D88026E8407
+:102660009F008AB80F00639C5C0084B89F00A3B8E9
+:1026700000204AE15C00A5B884004AB9002863E064
+:10268000840063B8061B4AE18BEFFF0700006AA8CD
+:102690001F006BA500408018800384A802006BB95E
+:1026A000040060189E7A63A800206BE100008B8410
+:1026B000FFFF84A5B13FFF0700008CA80040601811
+:1026C000200863A80000C09C000083840000A09C38
+:1026D0000A236CE10400639C4C664ED400008384A2
+:1026E00000508CE4030000100000809C0100C09C9E
+:1026F00000202CE404000010042866E00100A09CE7
+:10270000042866E0002003E40400001000006BA829
+:10271000FFFF609D00006BA8000063A900002185F9
+:1027200004004185080081850C00C18500480044F3
+:102730001000219CE8FF219C004801D4045001D4E2
+:10274000086001D40C7001D4108001D4149001D41D
+:10275000020084B8000083A9000006AA001864E003
+:102760000400C5B97012E3840400C6B80000AEA826
+:10277000F01143850B0047BA84026C840B004AB900
+:102780007F52FF0788028C8400584AE10000C09CF9
+:102790000300A09C0F00E09C00800019000008A925
+:1027A0000000809C00406AE080802019808029A978
+:1027B0000100849C004803D40028A4E5FBFFFF131C
+:1027C0000400639C0100C69C0038A6E5F3FFFF13DC
+:1027D00040004A9D88028C840300D0B80000AEA857
+:1027E0005F00E4B884026C84003884E06452FF0720
+:1027F000810084B80058F2E00000C09C0300A09C57
+:102800000700009D00802019000029A90000809C7D
+:10281000004867E080802019808029A90100849CFD
+:10282000004803D40028A4E5FBFFFF130400639CC9
+:102830000100C69C0040A6E5F3FFFF134000E79CA3
+:102840000000218504004185080081850C00C185B8
+:102850001000018614004186004800441800219CA5
+:10286000D8FF219C004801D4045001D4086001D451
+:102870000C7001D4108001D4149001D418A001D49C
+:102880001CB001D420C001D424D001D40040801851
+:10289000280884A80040401924084AA90000048799
+:1028A0000040E0182008E7A80400849C0000D8A895
+:1028B00000000486080058BB541683840000B0A8AA
+:1028C0000480DAE24C2643D400006A8570168384C3
+:1028D00000004786020004B900006A850018E8E09D
+:1028E000280F478502C0CBE1A80E878592FFFF071E
+:1028F00008004AB90000609C0018AEE51200001004
+:1029000004604AE10100909D00908CE50C00000CF1
+:102910000460DAE00101809E00006AA801008C9D3D
+:10292000000096A80000AAA86252FF070000F4A8C1
+:1029300000908CE5F9FFFF130460DAE0FFFFCE9D05
+:102940000100189F00C06EE0001898E51700000C09
+:10295000000018AA000003AB0000809D00908CE5E9
+:102960000E00000C000000150800D0B90101809E87
+:102970000460CEE000006AA801008C9D000096A8CB
+:102980000000AAA84B52FF070000F4A800908CE5B5
+:10299000F9FFFF130460CEE00100109E00C090E537
+:1029A000EEFFFF13000000150000609D0000218570
+:1029B00004004185080081850C00C1851000018656
+:1029C00014004186180081861C00C1862000018702
+:1029D00024004187004800442800219CC4FF219C1A
+:1029E000004801D4045001D400408018280884A86D
+:1029F0000040C0182408C6A8000084840000A3A8D2
+:102A00000040401920084AA91C2001D40040801829
+:102A10002C0884A8000084840000A68500006A8435
+:102A2000182001D40000A6850000809C54166584FF
+:102A30004C1E45D4202001D4382001D40800619CCC
+:102A40006C16C58400008A840200C6B8142001D424
+:102A5000002826E17016E584A80EC9840200E7B8B4
+:102A6000283001D400000A85002867E1280F298555
+:102A7000180081842C4801D4022008E1A80EEB84C0
+:102A80001C008184303801D400004A8502208DE08A
+:102A9000280F6B85084001D4345801D4102001D48C
+:102AA0002152FF070C5001D400002185040041850C
+:102AB000004800443C00219CFCFF219C004801D4BC
+:102AC000140483840000609D005824E40600001074
+:102AD0000000001563FFFF07000000150400000060
+:102AE00000000015BEFFFF07000000150000218553
+:102AF000004800440400219CE0FF219C004801D4D0
+:102B0000045001D4086001D40C7001D4108001D4A9
+:102B1000149001D418A001D41CB001D47016838481
+:102B20000040C0182008C6A80000A09C020004B9FC
+:102B3000000046860000009E001868E10400C69C64
+:102B4000280F4B850000C68508004AB9A80E8B8562
+:102B50000000C09C0000CEAAF7FEFF0704604AE117
+:102B60000080AEE5130000100080CEE00100809DE3
+:102B700000908CE50C00000C0000CCA80101809EA8
+:102B800000006AA801008C9D0000809C0000AAA89B
+:102B9000C851FF070000F4A800908CE5F9FFFF136F
+:102BA0000000CCA8FFFFD69D0100009E0080CEE073
+:102BB000003090E51600000C0000C6AA0000809DC1
+:102BC00000908CE50E00000C000000150800D0B944
+:102BD0000101809E0460CEE000006AA801008C9D87
+:102BE0000000809C0000AAA8B251FF070000F4A8D2
+:102BF00000908CE5F9FFFF130460CEE00100109E09
+:102C000000B090E5EFFFFF130000809D00002185DC
+:102C100004004185080081850C00C18510000186F3
+:102C200014004186180081861C00C18600480044BB
+:102C30002000219CF8FF219C004801D4045001D4BD
+:102C400022EFFF07000043A9A805AA840000C09C4A
+:102C5000020065B864148A848415639C00186AE0D5
+:102C600000006385003004E41C000010003003D431
+:102C700010178A84002065E0CC00638C003003E4E8
+:102C80000300001000000015000063A90100609C13
+:102C900000182BE4070000100200609C9C00609D5F
+:102CA000002065E00000809C0C000000CC2003D8D0
+:102CB00000182BE4040000100400609CF9FFFF03DF
+:102CC0009700609D00182BE4F7FFFF13002065E0DC
+:102CD000F5FFFF039800609D0000218504004185F9
+:102CE000004800440800219C881683840000609DF1
+:102CF000005804E4080000100000A3A81404638432
+:102D0000005823E40400001000000015885E45D43C
+:102D10000000809C000064A90048004400000015E9
+:102D2000CCFF219C0C4801D4105001D4146001D474
+:102D3000187001D41C8001D4209001D424A001D4A7
+:102D400028B001D42CC001D430D001D4FF00C3A5D9
+:102D5000000084A9000064A80200A09C0040801824
+:102D6000040884A806004EBA002804D4A1FBFF077B
+:102D70000000C09E0000009D00408018402084A8F4
+:102D800058444CD4002072E000400019642008A987
+:102D9000000083840040B2E00000809E500084B8B0
+:102DA0000000A5840200609C070004A6242C4CD4DB
+:102DB000B847FF070000009F14176C9C04168C9CFA
+:102DC000041801D4082001D4BC11AC9C24146C84D8
+:102DD00000008EA8C011CC9C001801D4C811EC9C36
+:102DE0000200609C324AFF0708130C9D44148C8437
+:102DF0000100609C001824E40B00001000006EA885
+:102E00000200609C001830E40700001000006EA86B
+:102E100048146C8400C023E40300001000006EA876
+:102E20000500009E000090A845FDFF070000ACA82B
+:102E3000FF006BA50000609C00180BE46B04000C05
+:102E400000000015B01F2CD40500609C001850E451
+:102E50002E0000100300609C020070B8040080186F
+:102E6000587C84A8002063E0000083840020004494
+:102E70000000001500406018480863A80000809C0E
+:102E80000000A384002005E44E0000100000009D17
+:102E90000100A09C042B4CD40000ACA800006EA83C
+:102EA0009FFCFF07000090A800006EA87AFBFF07B8
+:102EB00000008CA800408018682084A84C170C855E
+:102EC000002072E058178C846C244CD464444CD499
+:102ED000000083840100009D5F0084B86014AC840E
+:102EE0000000609C2C444CD4001825E40300001022
+:102EF00060264CD4000068A82C1C4CD40000609CB8
+:102F0000601C4CD40300609C001830E407000010E3
+:102F100000000015C4116C840000C09D007023E403
+:102F20000600000C0100A09C1548FF0704166C9CCD
+:102F30002E0400000000001524064C8504006018D3
+:102F4000B47A63A80000809C8C3DFF07C4294CD450
+:102F500006006A8C007003E410000010DC054C9D34
+:102F6000B4058C8400006AA89845FF078805AC8CDE
+:102F700004136C84007003E4ECFFFF1300000015E1
+:102F8000C0058C848805AC8C9045FF0700006AA8BA
+:102F9000E6FFFF0300000015B8058C8400006AA856
+:102FA0008A45FF078805AC8C04136C84007003E429
+:102FB000DEFFFF1300000015F3FFFF03C8058C843C
+:102FC000B6FFFF0304434CD404006018B97A63A829
+:102FD0000100809C693DFF070000409D80166C84C5
+:102FE000005023E40400001004540CD40100609C41
+:102FF000801E4CD40000809C00006EA864264CD437
+:1030000050264CD48C240CD458264CD439FDFF07C0
+:1030100000008CA800006EA8000090A840FCFF07EC
+:103020000000ACA800406018300863A80100A09C14
+:10303000000083843E0084A41000609C001824E4F7
+:103040001B020010342C4CD400400019482008A961
+:10305000004060184C2063A8004092E00018B2E0E5
+:103060000000C48400800019000008A90000E09C52
+:1030700000006584FF0F8018FFFF84A80B0063B871
+:103080000320C6E00000A09C032063E0A42D0CD424
+:10309000004083E0C411AC840400089D004063E05C
+:1030A00000810019000008A9004004D4003003D4B6
+:1030B000004080182C0284A800406018240263A8F5
+:1030C000003804D40400809C002003D4005025E480
+:1030D000030000100300609C0100E09C001830E435
+:1030E000030000100000809C0100809C032067E02A
+:1030F000005003E4070000100000609C08136C847B
+:10310000005023E4D901000CDC054C9F0000609CBA
+:103110000000809CA8186CD4002025E40B0000104F
+:10312000AC186CD408136C84002023E40700001052
+:103130000100809C7B00009DA4250CD4F0224CD47F
+:10314000F4424CD40000C09EA4056C840000809C16
+:10315000002023E40F000010002025E40D000010E3
+:103160000000409D00006EA8BDF2FF0700008CA883
+:10317000A4056C84005023E4060000100000CBAAD4
+:10318000C4116C84005023E4F8FFFF0F00006EA808
+:1031900000408018280B84A80000409D0000648433
+:1031A000005003E40300001000000015005004D498
+:1031B000005036E40700001000000015C4116C84B4
+:1031C0000100C09E00B003E47501000C0000001572
+:1031D000114BFF0700000015223FFF0700000015FC
+:1031E0005DF8FF0700006CA8A8058C84FFFF609CB9
+:1031F000001824E40E0100100000A09C004060189C
+:10320000102063A854148C84002803D40400639C09
+:10321000002803D4005004E4F50000100200609C74
+:1032200044148C84001824E4E90000100100609C20
+:10323000004060181C2063A82000009D004003D4BB
+:103240000000A09C00406018182063A8402D0CD4FA
+:10325000002803D404006018DD7A63A8C73CFF0788
+:103260000100809C78046C840100209D004803E4E8
+:10327000D500001000000015B4056C84020063B88E
+:103280000040C0182420C6A80040E0182820E7A865
+:10329000F011839C0040A0180C05A5A87012639C37
+:1032A00000208CE000186CE000008484000063843F
+:1032B000002006D4C4110C85001807D400008584B2
+:1032C000000066844B0084B80040A0180805A5A83B
+:1032D000002063E0001806D40000858400006784A5
+:1032E0004B0084B8002063E00000809C001807D4E5
+:1032F000002008E403000010000069A80300609C9F
+:103300000000A3A88C028C840000609C001804E4D8
+:1033100003000010000000150800A5A80040601878
+:103320002C2063A80100809C002803D404006018AE
+:10333000077B63A8913CFF07000000159005AC8453
+:1033400004006018BC8063A800408018002084A896
+:103350000400EC8C0100A59C0000009D0000C384CB
+:10336000003804D4004006E412000010902D0CD464
+:1033700078046C84004023E40E0000100000001567
+:10338000C4116C84004023E40A0000100000001502
+:103390007C166C84004023E4060000100000001539
+:1033A00028146C84004023E47E00000C00006CA80C
+:1033B0005814AC8400408018182084A804006018B9
+:1033C000307B63A8002804D46C3CFF070100809C7C
+:1033D0002A46FF070000001578048C840000609CDA
+:1033E000001824E46D0000100000001514046C8423
+:1033F0000100839C00406018202063A8002003D4B3
+:103400006AF6FF0700006CA8BFEFFF0700006CA87A
+:1034100024146C84AB40FF0714178C9C00400019E7
+:10342000402008A9FFFF80A8004072E0002003D4DC
+:10343000953EFF070000001504006018597B63A843
+:103440004E3CFF070100809CF0126C840000A09CA1
+:10345000002823E44F0000100000001528148C847D
+:10346000002824E432000010000000157C166C8453
+:10347000002823E42E000010FFFF609CA8058C8428
+:10348000001804E42500000C0000001517FEFF07DB
+:1034900000006CA81000D8B800008EA80500609C41
+:1034A0000430ABE00000C09C5F3EFF070000E09CE2
+:1034B00004006018807B63A8303CFF070100809CFB
+:1034C000C4116C840100A09C002823E407000010B4
+:1034D00000000015A8058C84FFFF609C001824E400
+:1034E0000800000C0000009D04006018A07B63A889
+:1034F000223CFF070100809C84FEFF030300609CC8
+:103500007C2E4CD4C4414CD467EFFF0700006CA85C
+:10351000F6FFFF0300000015C7FDFF0700006CA8C1
+:10352000DBFFFF0300000BAB0000A09C002824E49D
+:1035300006000010AB00809E7C166C84002823E4FB
+:103540000C00000C000000150000A09C0400601896
+:10355000C77B63A8042C0CD4083CFF07000094A888
+:1035600000008EA80000B4A8CFFFFF032000609CDD
+:1035700004006018EA7B63A8003CFF070000809C01
+:103580000000009DF4128C86F6FFFF03F0424CD43D
+:10359000E6FFFF0328148C8497FFFF030000809C44
+:1035A0000040A0182C20A5A800008584200084A835
+:1035B000002005D44FF6FF07000000157EFFFF0333
+:1035C0005814AC842EFFFF03A8056C84001824E473
+:1035D0001CFFFF131000809C004060181C2063A893
+:1035E000002003D418FFFF030000A09CC4116C84CA
+:1035F000005003E4030000100000609C0300609C86
+:103600000000A3A88C028C840000609C001804E4D5
+:1036100003000010000000150800A5A80040601875
+:103620001C2063A80BFFFF030000001564146C84CA
+:10363000005003E4080000100000001510176C840F
+:10364000001864E0EC00838C005004E45000000C8F
+:103650000000001540148C840100609C001824E4D4
+:1036600040000010000000153C140C85004060185C
+:10367000082063A8004003D438148C840000609CA8
+:10368000401C4CD48402AC8400406018042063A821
+:1036900088020C85002003D43C2C4CD438444CD4F4
+:1036A00004138C840000609C001804E42B000010BC
+:1036B00000000015C4056C84020063B80040801847
+:1036C000102084A80040A0181420A5A8F011C39CC5
+:1036D0000040E0181420E7A87012639C0030CCE092
+:1036E00000186CE00000C68400006384003004D43D
+:1036F000C4110C850040C0181020C6A8001805D4BD
+:10370000004060180C0563A80040A0180805A5A893
+:1037100000008384000066844B0084B8002063E0CE
+:10372000001806D400008584000067844B0084B82C
+:10373000002063E00000809C001807D4002008E40B
+:103740000400001000000015AEFFFF030200609CA3
+:10375000ACFFFF030100609CD8FFFF03A8056C8449
+:1037600084028C8400406018082063A8002003D4E1
+:1037700088020C8500406018042063A83C244CD4C7
+:10378000004003D4C7FFFF0338444CD4C8ECFF0704
+:1037900000006CA8B1FFFF0340148C849E49FF0712
+:1037A00000000015AF3DFF07000000150040601845
+:1037B000402063A804008C8C0018B2E00040601820
+:1037C000002063A8002003D4FFFF80A8002005D4B8
+:1037D0002A45FF070000001574F5FF0700006CA8DC
+:1037E00024146C84B73FFF0714178C9C04006018E6
+:1037F000F17B63A8613BFF070000809CA23DFF07AF
+:103800000000001528146C84005023E4060000100A
+:10381000000000157C166C84005023E40B00000CA3
+:1038200000000015AB00809E00008EA80000B4A828
+:103830002000609C0000C09C7B3DFF070000E09CD6
+:1038400021FFFF03C4116C84F0126C8400B023E4E8
+:10385000F7FFFF1300008EA80000A09CF4128C86D6
+:10386000F3FFFF03F02A4CD40100A09CC4294CD4E0
+:10387000B8058C8400007AA85443FF078805AC8CF7
+:1038800004136C84005003E40400000C00007AA8C8
+:103890001FFEFF03C411AC84C8058C844B43FF0793
+:1038A0008805AC8C1AFEFF03C411AC840000609C38
+:1038B000C411AC840000E09C0000809C002025E442
+:1038C00003000010A41D0CD40100E09C0300609CC8
+:1038D000001830E4030000100000C09C0100C09CF0
+:1038E000033067E0002003E4070000100000009DA3
+:1038F00008136C84002023E4DC00000C0100809C91
+:103900000000009D0000809CA8406CD4002025E4AD
+:103910000B000010AC406CD408136C84002023E42E
+:10392000070000100100609C7B00809CA41D0CD44B
+:10393000F01A4CD4F4224CD40000C09EA4056C8430
+:103940000000809C002023E412FEFF13002025E4E9
+:1039500010FEFF130000001548148C840500609CC5
+:10396000001824E4BD00000C00006CA85DFAFF07FD
+:1039700000006CA800008CA8D2F6FF0700006EA81B
+:103980000000CBAAA6F4FF0700006CA80100809CF1
+:1039900000200BE40600001000000015F0126C84FB
+:1039A000002003E40300000C00000015A4250CD443
+:1039B00060166C840000A09C002823E4A500001081
+:1039C00000000015A4058C84002824E406000010E3
+:1039D0000000409D0100A09CA42D0CD4000085A8EF
+:1039E0000000409D005016E4050000100000609C9F
+:1039F000005024E45D00000C00000015001824E4D1
+:103A00003D00000C000000150000809C0040601884
+:103A10002C2063A8002003D40100809C002036E401
+:103A2000200000100000609CA4058C84001824E491
+:103A30001C000010000000150040A0184020A5A8A0
+:103A4000002892E0FFFFA0A800006484002803E49F
+:103A5000FEFFFF131417CC9C00400019402008A95A
+:103A6000004072E00416AC9C00008384C811EC9CFA
+:103A700008130C9D500084B8043001D4082801D4E8
+:103A8000030004A60400609C24148C84BC11AC9C2C
+:103A9000C011CC9C002001D40547FF0700008EA870
+:103AA00024046C840000809C002023E406000010A5
+:103AB0000000001504046C84002003E40C00000CDA
+:103AC0000000009DA4056C84002023E4B1FDFF13D9
+:103AD00000000015C4116C84002023E49FFFFF0F39
+:103AE00000000015ABFDFF0300000015A9FDFF035A
+:103AF00004440CD4C848FF070000001504006018F7
+:103B0000F87B63A89D3AFF070100809CD53CFF0726
+:103B10000000001504006C8C00408018002084A870
+:103B200000400019402008A9001804D40040B2E069
+:103B3000FFFF60A8001805D4D33CFF070000001564
+:103B40002000609C00008EA80000A09C0000C09C8B
+:103B5000B53CFF070000E09C9B3CFF070000001500
+:103B6000ABFFFF030000809CAB48FF07000000157F
+:103B7000040060180A7C63A8803AFF070100809C5B
+:103B8000B83CFF0700000015004060181C2063A827
+:103B900000400019402008A9005003D40040B2E0C2
+:103BA00004008C8C00406018002063A8002003D41F
+:103BB000FFFF60A8001805D4B33CFF070000001504
+:103BC000F0126C84005023E4200000100000001567
+:103BD00028148C84005024E4070000100000A09CEE
+:103BE0007C166C84005023E41400000C0600609CDA
+:103BF0000000A09C002824E406000010AB00809E7A
+:103C00007C166C84002823E40600000C00000015DC
+:103C10002000609C00008EA8CDFFFF030000B4A828
+:103C20000000A09CF4128C86F02A4CD4AC286CD4F2
+:103C3000F8FFFF03042C0CD40100809CAC206CD452
+:103C4000C1FFFF0304240CD4EAFFFF0328148C8473
+:103C500064FFFF03A4058C846BF9FF0700008EA8A6
+:103C6000E20000000000001500006CA84FF9FF07FB
+:103C7000C4214CD423FFFF03C411AC840040A0181E
+:103C80006820A5A800006CA8002892E00000409DD4
+:103C90000000A484B9EDFF07882D0CD868170C85A7
+:103CA00064176C84000088A88402AC848802CC84E9
+:103CB0004C1C4CD43649FF0750444CD400500BE404
+:103CC00003000010000000154700409D64146C8440
+:103CD0000000809C002003E4090000100000001593
+:103CE0006C146C84002003E44100000C00202AE4E2
+:103CF00003000010000000154D00409D00406018BA
+:103D0000300863A8000083841000609C3E0084A4F7
+:103D1000001824E4330000100000001588058C8C86
+:103D20000200609C001844E403000010000000152D
+:103D30004A00409D00008CA80000B0A85B48FF0727
+:103D40000200609C473CFF0700000015004060181F
+:103D5000402063A804008C8C0018B2E0004060187A
+:103D6000002063A8002003D4FFFF80A800006CA8F7
+:103D7000002005D40DF4FF070000001524146C8406
+:103D8000503EFF0714178C9C0000609C00182AE42A
+:103D90000D0000100000AAA80000A09C00008EA842
+:103DA0000F00609C0000C09C1F3CFF070000E09CCF
+:103DB0000300A09C0100009D00280CD452FCFF03CE
+:103DC00030444CD400008EA82000609C0000C09CB1
+:103DD000153CFF070000E09C4CFCFF030300609CC7
+:103DE00088058C8CD0FFFF030300609C69EBFF0704
+:103DF00000006CA8C2FFFF0300000015040060185B
+:103E00002B7C63A8DD39FF07000090A800006CA898
+:103E1000E6F8FF0748844CD44FF5FF0700006CA874
+:103E200004138C840000609C001804E46D000010F2
+:103E300000000015C4056C84020063B800408018BF
+:103E4000102084A80040A0181420A5A8F011C39C3D
+:103E500000400019102008A97012639C0030CCE0CB
+:103E600000186CE00000C6840040E0180805E7A8D0
+:103E70000040401914204AA900006384003004D493
+:103E8000001805D40100809C004060180C0563A850
+:103E90000000C3840000A8844B00C6B8040060186A
+:103EA000397C63A80030A5E0002808D40000C7844E
+:103EB0000000AA844B00C6B80030A5E000280AD450
+:103EC000AE39FF070000001564146C840000C09C2C
+:103ED000003003E4090000100000001510176C8486
+:103EE000A8058C84001884E0EC00A48C003005E464
+:103EF0003800000C00000015004060181C2063A86A
+:103F00000200809C5814AC84002003D40040601848
+:103F1000182063A890058C84002803D40100849C99
+:103F20000400AC8C00406018002063A890250CD4DD
+:103F3000002803D45143FF07000000159BF3FF073F
+:103F400000006CA8F0ECFF0700006CA824146C843F
+:103F5000DC3DFF0714178C9C00400019402008A985
+:103F6000FFFF80A8004072E0002003D4C63BFF079B
+:103F70000000001504006018597B63A87F39FF0713
+:103F80000100809C51EAFF0700006CA868146C8453
+:103F90000000A09C002803E40A00001000000BAB06
+:103FA00010178C84A8056C84002063E0CC00638C1F
+:103FB000002803E40300001000000015000003AB1C
+:103FC0001000B8B800008EA881FFFF030500609CB8
+:103FD000B7EAFF0700006CA8C8FFFF030000001548
+:103FE00096FFFF03A8056C840C0021851000418515
+:103FF000140081851800C1851C00018620004186BF
+:10400000240081862800C1862C000187300041876A
+:10401000004800443400219C0000609D005823E4C7
+:104020000900000C0100809C002043E50600000C04
+:1040300000000015010084B8002043E5FEFFFF13D7
+:1040400001006B9D00480044000000155F00A4B80B
+:104050000028A4E08100A5B8002863E0092363E0FC
+:10406000000063A9004800440000001500406018EB
+:10407000080363A80100A09C00008384002804E4D6
+:1040800027000010002884E4290000100000609D33
+:104090000200609C001804E41C0000100300609CF7
+:1040A000001804E42200000C000000150040C018B5
+:1040B0000403C6A80500609D000086840000609C83
+:1040C000001804E40C0000100F00609C0E00A09C7F
+:1040D0000000809C00006684002003E405000010BE
+:1040E00001006B9D0028ABE5FBFFFF1300000015EE
+:1040F0000F00609C00182BE40D000010000000155C
+:104100000B000000FFFF609D00406018040363A8DF
+:1041100000008384060000000300649D00406018D6
+:10412000040363A8000083840100649D00480044E8
+:10413000000000150000C3A80100E09C0000609C86
+:10414000001826E41700000C0000609D0040801855
+:10415000040384A8FFFF669C0000A484081867E19C
+:10416000003825E40400000C083087E0022067E1F5
+:10417000FFFF669C00408018000384A81F0063A412
+:10418000020063B8002063E00100809C0020A6E5E7
+:1041900004000010000000150000638400186BE1AB
+:1041A0000048004400000015000083A80100009DA5
+:1041B0000000609CF81A04D400406018080363A84B
+:1041C00000006384F01A04D40000609CF002E484D0
+:1041D000FC1A04D4001B04D4041B04D4081B04D40C
+:1041E0000C1B04D4141B04D4181B04D41C1B04D4AF
+:1041F000201B04D4281B04D42C1B04D4301B04D44F
+:10420000341B04D43C1B04D4401B04D4441B04D4EE
+:10421000481B04D44C1B04D4501B04D4581B04D496
+:10422000004047E44A0000105C1B04D40040A01882
+:104230000403A5A80000C09C00006584003023E4AE
+:104240000E000010F41A04D400006584F81A04D497
+:1042500000006584FC1A04D400006584001B04D4AB
+:1042600000006584041B04D400006584081B04D48A
+:10427000000065840C1B04D400006584003023E436
+:104280000A000010101B04D400006584141B04D421
+:1042900000006584181B04D4000065841C1B04D432
+:1042A00000006584201B04D4000065840000658440
+:1042B000003023E40A000010241B04D400006584AD
+:1042C000281B04D4000065842C1B04D400006584E2
+:1042D000301B04D400006584341B04D400006584C2
+:1042E000003023E40E000010381B04D40000658465
+:1042F0003C1B04D400006584401B04D4000065848A
+:10430000441B04D400006584481B04D40000658469
+:104310004C1B04D400006584501B04D40000658449
+:10432000004027E40A00001000000015000065842A
+:10433000003023E406000010541B04D40000658400
+:104340000000A584581B04D45C2B04D4004800440E
+:1043500000000015F00283840000A3A80100609C07
+:10436000001844E4A00200100000809C1404C584DE
+:10437000002026E46E00001000000015F80265849D
+:10438000002003E406000010000000150040601843
+:10439000200363A800006384601B05D4FC028584AD
+:1043A0000000609C001804E40600001000000015E6
+:1043B00000406018200363A800006384641B05D4D8
+:1043C000000385840000609C001804E406000010CF
+:1043D0000000001500406018200363A800006384FB
+:1043E000681B05D4040365840000809C002003E45E
+:1043F000060000100000001500406018200363A8AC
+:10440000000063846C1B05D408036584002003E46A
+:10441000060000100000001500406018200363A88B
+:1044200000006384701B05D40C036584002003E442
+:10443000060000100000001500406018200363A86B
+:1044400000006384741B05D414036584002003E416
+:10445000060000100000001500406018200363A84B
+:1044600000006384781B05D420036584002003E4E6
+:10447000060000100000001500406018200363A82B
+:10448000000063847C1B05D428036584002003E4BA
+:10449000060000100000001500406018200363A80B
+:1044A00000006384801B05D42C036584002003E492
+:1044B000060000100000001500406018200363A8EB
+:1044C00000006384841B05D430036584002003E46A
+:1044D000060000100000001500406018200363A8CB
+:1044E00000006384881B05D434036584002003E442
+:1044F000060000100000001500406018100363A8BB
+:10450000000063848C1B05D458036584002003E4F9
+:10451000070000100100609C00406018200363A8A1
+:1045200000006384901B05D40100609C001826E401
+:10453000B70000100200609CF80285840000609CB7
+:10454000001804E406000010000000150040601888
+:10455000200363A800006384601B05D4FC028584EB
+:104560000000609C001804E4060000100000001524
+:1045700000406018200363A800006384641B05D416
+:10458000000385840000609C001804E4060000100D
+:104590000000001500406018200363A80000638439
+:1045A000681B05D4040385840000609C001804E4A3
+:1045B000060000100000001500406018200363A8EA
+:1045C000000063846C1B05D4080385840000609C94
+:1045D000001804E4060000100000001500406018F8
+:1045E000200363A800006384701B05D40C0385843A
+:1045F0000000609C001804E4060000100000001594
+:1046000000406018200363A800006384741B05D475
+:10461000140385840000609C001804E40600001068
+:104620000000001500406018200363A800006384A8
+:10463000781B05D4200385840000609C001804E4E6
+:10464000060000100000001500406018200363A859
+:10465000000063847C1B05D4280385840000609CD3
+:10466000001804E406000010000000150040601867
+:10467000200363A800006384801B05D42C03858479
+:104680000000609C001804E4060000100000001503
+:1046900000406018200363A800006384841B05D4D5
+:1046A000300385840000609C001804E406000010BC
+:1046B0000000001500406018200363A80000638418
+:1046C000881B05D4340365840000809C002003E42B
+:1046D000060000100000001500406018100363A8D9
+:1046E000000063848C1B05D418036584002003E458
+:1046F000060000100000001500406018200363A8A9
+:1047000000006384941B05D41C036584002003E42B
+:10471000060000100000001500406018200363A888
+:1047200000006384981B05D43C036584002003E4E7
+:10473000060000100000001500406018200363A868
+:10474000000063849C1B05D440036584002003E4BF
+:10475000060000100000001500406018200363A848
+:1047600000006384A01B05D448036584002003E493
+:10477000060000100000001500406018200363A828
+:1047800000006384A41B05D44C036584002003E46B
+:10479000060000100000001500406018200363A808
+:1047A00000006384A81B05D450036584002003E443
+:1047B000060000100000001500406018200363A8E8
+:1047C00000006384AC1B05D458036584002003E417
+:1047D000060000100000001500406018200363A8C8
+:1047E00000006384901B05D45C036584002003E40F
+:1047F000070000100200609C00406018200363A8BE
+:1048000000006384B01B05D40200609C001826E4FD
+:10481000C00000100300609CF80285840000609CCA
+:10482000001804E4060000100000001500406018A5
+:10483000200363A800006384601B05D4FC02858408
+:104840000000609C001804E4060000100000001541
+:1048500000406018200363A800006384641B05D433
+:10486000000385840000609C001804E4060000102A
+:104870000000001500406018200363A80000638456
+:10488000681B05D4040385840000609C001804E4C0
+:10489000060000100000001500406018200363A807
+:1048A000000063846C1B05D4080385840000609CB1
+:1048B000001804E406000010000000150040601815
+:1048C000200363A800006384701B05D40C03858457
+:1048D0000000609C001804E40600001000000015B1
+:1048E00000406018200363A800006384741B05D493
+:1048F000140385840000609C001804E40600001086
+:104900000000001500406018200363A800006384C5
+:10491000781B05D4200385840000609C001804E403
+:10492000060000100000001500406018200363A876
+:10493000000063847C1B05D4280385840000609CF0
+:10494000001804E406000010000000150040601884
+:10495000200363A800006384801B05D42C03858496
+:104960000000609C001804E4060000100000001520
+:1049700000406018200363A800006384841B05D4F2
+:10498000300385840000609C001804E406000010D9
+:104990000000001500406018200363A80000638435
+:1049A000881B05D4340385840000609C001804E44F
+:1049B000060000100000001500406018100363A8F6
+:1049C000000063848C1B05D4180365840000809C60
+:1049D000002003E4060000100000001500406018ED
+:1049E000200363A800006384941B05D41C03658422
+:1049F000002003E4060000100000001500406018CD
+:104A0000200363A800006384981B05D43C036584DD
+:104A1000002003E4060000100000001500406018AC
+:104A2000200363A8000063849C1B05D440036584B5
+:104A3000002003E40600001000000015004060188C
+:104A4000200363A800006384A01B05D44803658489
+:104A5000002003E40600001000000015004060186C
+:104A6000200363A800006384A41B05D44C03658461
+:104A7000002003E40600001000000015004060184C
+:104A8000200363A800006384A81B05D45003658439
+:104A9000002003E40600001000000015004060182C
+:104AA000200363A800006384AC1B05D44403658421
+:104AB000002003E40600001000000015004060180C
+:104AC000200363A800006384B41B05D458036584E5
+:104AD000002003E4060000100000001500406018EC
+:104AE000200363A800006384901B05D45C036584E5
+:104AF000002003E4070000100300609C00406018E1
+:104B0000200363A800006384B01B05D40300609CED
+:104B1000001826E47D0000100300609C9402858448
+:104B20000100609C001824E4780000100300609CE1
+:104B3000140385840000609C001804E40600001043
+:104B40000000001500406018200363A80000638483
+:104B5000781B05D4200385840000609C001804E4C1
+:104B6000060000100000001500406018200363A834
+:104B7000000063847C1B05D4280385840000609CAE
+:104B8000001804E406000010000000150040601842
+:104B9000200363A800006384801B05D42C03858454
+:104BA0000000609C001804E40600001000000015DE
+:104BB00000406018200363A800006384841B05D4B0
+:104BC000300365840000809C002003E40600001090
+:104BD0000000001500406018200363A800006384F3
+:104BE000881B05D434036584002003E4060000100C
+:104BF0000000001500406018100363A800006384E3
+:104C00008C1B05D418036584002003E40600001003
+:104C10000000001500406018200363A800006384B2
+:104C2000941B05D41C036584002003E406000010D7
+:104C30000000001500406018200363A80000638492
+:104C4000981B05D43C036584002003E40600001093
+:104C50000000001500406018200363A80000638472
+:104C60009C1B05D440036584002003E4060000106B
+:104C70000000001500406018200363A80000638452
+:104C8000A01B05D448036584002003E4060000103F
+:104C90000000001500406018200363A80000638432
+:104CA000A41B05D44C036584002003E40600001017
+:104CB0000000001500406018200363A80000638412
+:104CC000A81B05D450036584002003E406000010EF
+:104CD0000000001500406018200363A800006384F2
+:104CE000AC1B05D444036584002003E43E0000109F
+:104CF0000000001500406018200363A800006384D2
+:104D000039000000B41B05D4001826E4360000105A
+:104D10000200609C94028584001824E43200001094
+:104D20000000809C14036584002003E4060000104A
+:104D30000000001500406018200363A80000638491
+:104D4000781B05D420036584002003E406000010CE
+:104D50000000001500406018200363A80000638471
+:104D60007C1B05D428036584002003E406000010A2
+:104D70000000001500406018200363A80000638451
+:104D8000801B05D42C036584002003E4060000107A
+:104D90000000001500406018200363A80000638431
+:104DA000841B05D430036584002003E40600001052
+:104DB0000000001500406018200363A80000638411
+:104DC000881B05D434036584002003E4060000102A
+:104DD0000000001500406018100363A80000638401
+:104DE0008C1B05D40048004400000015E4FF219C02
+:104DF000004801D4045001D4086001D40C7001D4DF
+:104E0000108001D4149001D418A001D474058384B7
+:104E1000000083A9F401609C001824E40B0000103A
+:104E20000000409E78058C847101609C0018A4E508
+:104E3000060000102C00639C001844E503000010DD
+:104E4000000000150100409EC0048C840300609C9B
+:104E50000018A4E4040000100000009E24000000DC
+:104E60000200609D002090E52100000C0000609D84
+:104E70000000C09DC4044C9D0040801A040394AA05
+:104E80007BFCFF070100109E00706BE5F4FFFF0F35
+:104E900000006BA8A8FCFF0700000015007032E4BA
+:104EA0000300001000580ADC0000748470FCFF0747
+:104EB0000000001500706BE5E9FFFF0F0000001512
+:104EC0009DFCFF0700006BA800406018040363A866
+:104ED00002580ADC04004A9D0000A384C0048C84AC
+:104EE000002090E5E7FFFF130000609D0000218592
+:104EF00004004185080081850C00C18510000186F1
+:104F00001400418618008186004800441C00219C42
+:104F10000040E0180403E7A80000809C00006784BC
+:104F2000002003E40C0000100400609C0300C09CFF
+:104F30000000A09C00006784002803E40500001026
+:104F40000100849C0030A4E5FBFFFF130000001566
+:104F50000400609C001844E43F0000100000609DC5
+:104F6000020064B804008018707C84A8002063E00C
+:104F700000008384002000440000001500406018F9
+:104F8000040363A80000809C0000A384002005E4C3
+:104F9000050000100C00639C000083842E000000BC
+:104FA0000100649D00406018100363A80000838422
+:104FB00029000000F0FF649D00406018040363A80E
+:104FC0000000809C0000A384002005E40500001080
+:104FD0001000639C000083841F0000001100649D8A
+:104FE00000406018140363A8000083841A000000C6
+:104FF000D0FF649D00406018040363A80000809CFB
+:105000000000A384002005E4050000101400639C48
+:1050100000008384100000003100649D004060188F
+:10502000180363A8000083840B00000090FF649DB8
+:1050300000406018240363A8000083840600000079
+:105040007100649D00406018280363A800008384F9
+:105050007102649D00480044000000150040C01823
+:105060000403C6A80000E09C00006684003803E446
+:105070000F00001000000015004060180C0363A82A
+:1050800000400019200308A9000083840000A684C2
+:1050900000006684003803E40500001000000015DD
+:1050A0000000688400008884000068840048004490
+:1050B00000000015E803E3840000C3A80100609C21
+:1050C000E41B06D4000063A90000609C001807E4FC
+:1050D0001A0000100100679C00406018C40363A818
+:1050E00000400019140308A90000A384005825E417
+:1050F000120000100100679C00406018440363A880
+:10510000000083840000609CE41B06D400006884D7
+:10511000E81B06D400406018080363A8E803E6848F
+:105120000000638400000885EC1B06D4EC4206D422
+:105130004C4406D40100679CE81B06D40048004498
+:10514000000000150040A0182003A5A80000609DE5
+:105150000000A584000085A8142A03D40F0084A4AD
+:105160008400A5B8802443D40100A5A47C2C43D49A
+:105170000048004400000015FCFF219C004801D4B9
+:10518000000063A976588018446984A8004060181C
+:10519000000363A80000A384002025E40A00001097
+:1051A000F701609C0100809C741D0BD47C250BD4FE
+:1051B00000406018300863A8002003D47400000089
+:1051C0000000609D69446018587663A8001805E4E3
+:1051D0006E00000C0000001500406018600363A81A
+:1051E00035008018623084A80000A384002025E4E4
+:1051F0003D0000102000639CF401A09C000023856A
+:1052000000FF6018000063A8742D0BD4031889E018
+:1052100000406018300863A81400A09C002803D444
+:1052200000D06018000063A8FF00A018FFFFA5A829
+:10523000001884E0032829E1042029E1FFFFA018D9
+:10524000FF00A5A8500069B800FF8018FFFF84A8E0
+:10525000D0FF639C032029E1FF0063A4100063B822
+:10526000041829E1480089B8D0FF849C032829E16B
+:10527000FF0084A4080084B8042029E100FF809C7A
+:10528000D0FF699C032029E1FF0063A4041829E1F1
+:10529000580089B8E803609C500009B9061B84E0F7
+:1052A0004800C9B8FF0008A5FF00C6A4FF0029A553
+:1052B0000300A6B80030A5E00030A5E0010068B802
+:1052C000004063E00500E3B8003863E0004063E0BD
+:1052D000001884E0002884E0004864E02B0000000F
+:1052E000781D0BD4CAFF6018CFCF63A8001885E0E3
+:1052F0000100609C001844E40E000010000000153E
+:1053000000406018200363A800408018800384A830
+:105310000000A3840000248500FFA0180000A5A8B9
+:10532000F501809C74250BD4BAFFFF03032889E0A4
+:1053300035006018333063A8001825E4130000100E
+:105340000000001500406018200363A8004080188A
+:10535000800384A80000A384F701A09C000024859A
+:105360000000609C742D0BD47C1D0BD400FFA01892
+:105370000000A5A800406018300863A8032889E051
+:10538000A7FFFF031600A09C0000609D0000218580
+:10539000004800440400219C00408018480384A871
+:1053A0000040A0180403A5A8000084840000609DAC
+:1053B000F82303D4000085840000A584FC2303D4D3
+:1053C000002C03D40048004400000015FCFF219C81
+:1053D000004801D40000A3A800406018040363A89B
+:1053E00000006384181A05D4000083A80000609CA4
+:1053F000001804E40A0000100000001500406018C6
+:10540000100363A8004080180C0384A80000638484
+:1054100000008484341A05D4382205D40040601872
+:10542000100363A8000083840100609CFFFF849C3C
+:10543000001844E4050000100000609D08FFFF070D
+:10544000000000150000609D000021850048004418
+:105450000400219CF8FF219C004801D4045001D491
+:10546000000043A900406018040363A8000083847F
+:10547000C4230AD40100809CBC230AD40000838486
+:10548000C8230AD4000063840701809C74250AD4D1
+:10549000CC1B0AD4004080180C0384A80500609C33
+:1054A00000008484001844E44F000010D0230AD484
+:1054B000020064B804008018847C84A8002063E0A3
+:1054C0000000838400200044000000158000609CE0
+:1054D0006000809C841A0AD488220AD40800609C48
+:1054E0000600809CAC1C0AD400406018040363A82A
+:1054F000B0240AD400006384D41B0AD4000083A81B
+:105500000000609C001824E40300000C000000155B
+:105510000100609C141C0AD40040A0180403A5A834
+:1055200000406018100363A80100E09C0000638441
+:10553000D81B0AD400406018140363A800006384D9
+:10554000DC1B0AD400006584DC038A8400006584C7
+:10555000003803E40900000C4C240AD40040C018B1
+:105560002003C6A80000868400006584003803E498
+:10557000FDFFFF13000000150000609C0100809CEF
+:10558000701A0AD4B81A0AD4D01A0AD4D41A0AD46F
+:105590002C1C0AD48C1A0AD4481C0AD4E81A0AD43F
+:1055A000AC1A0AD490220AD4CC220AD450240AD4A9
+:1055B00024240AD4C8220AD40800609C0000809CDD
+:1055C000B41A0AD4B4240AD400006AA8BAFEFF07A9
+:1055D000E8230AD40100609C0000609D1F000000C9
+:1055E000101A0AD41D0000000200609DB000609CEB
+:1055F0009000809C841A0AD488220AD40B00609CF4
+:10560000B9FFFF030900809C6001609C2001809C21
+:10561000841A0AD488220AD41600609CAC1C0AD4CE
+:10562000B2FFFF031200809CC002609C4002809C7D
+:10563000841A0AD488220AD4F9FFFF035800609C18
+:105640008005609C8004809C841A0AD488220AD435
+:10565000F3FFFF036001609C000021850400418589
+:10566000004800440800219CE8FF219C004801D428
+:10567000045001D4086001D40C7001D4108001D40E
+:10568000149001D4000043A90000C09C00406018A1
+:10569000040363A8BC330AD4000083840000A09CE8
+:1056A00028220AD400408018200384A800008484A3
+:1056B000000063842C220AD4002803E4E4010010D3
+:1056C000301A0AD400406018100363A80040801804
+:1056D0000C0384A80000638400008484341A0AD474
+:1056E00038220AD400406018100363A800006384C5
+:1056F0003C1A0AD4000083A80F00609C001844E400
+:105700000A0000100100C09C020064B80400801868
+:105710009C7C84A8002063E0000083840020004477
+:10572000000000150100C09C40320AD444320AD463
+:105730000040C0180403C6A80000809C00006684D6
+:10574000002003E423000010481A0AD40040601827
+:10575000080363A8000063844C1A0AD4000066841E
+:10576000501A0AD400006684002003E419000010D7
+:10577000541A0AD40040A0183C03A5A80000858450
+:1057800000006684000065845C1A0AD458220AD49A
+:105790000000668400008584004060180C0363A844
+:1057A00060220AD4000086840000638400408018D0
+:1057B0002C0384A800008484641A0AD468220AD4C2
+:1057C000000066840000A584000066846C2A0AD468
+:1057D00000406018080363A800006384701A0AD4AC
+:1057E0000000E3A80000609C001807E40600001019
+:1057F0000300609C0100C09C0C300AD49B01000097
+:105800000400609D001827E40A0000100100609C5D
+:1058100034028A84001804E4060000100000001519
+:1058200000406018100363A800006384741A0AD44F
+:1058300000408018040384A80000809D0000648458
+:1058400000406018400363A8000063840000A48443
+:1058500000008484781A0AD4006004E45601000C25
+:105860007C220AD40200609C001807E42F0100107B
+:105870000000609C001827E40B00001000000015D9
+:1058800000406018040363A800408018340384A813
+:105890000000A384000044860000A3840000048666
+:1058A0000000A3840040A0180403A5A878026A841D
+:1058B0000100809C0000C5848C320AD40000C5849D
+:1058C000002043E40300001090320AD490220AD44E
+:1058D00034022A85002029E432010010000069A961
+:1058E0000000A584942A0AD494020A850100609CD1
+:1058F000FFFF889C001844E4280000100200809DEF
+:10590000006008E40E000010000000150040601860
+:10591000340363A800408018040384A80000A38413
+:105920000000C4840000A3840000C4840000A38499
+:105930000000C4840000A3840000C48400406018F8
+:10594000180363A800006384C01C0AD4000083A865
+:105950000300609C001824E4030000103D00639CD9
+:105960000C180AD400406018080363A8004080188F
+:10597000040384A8000063840000C484D41C0AD4F7
+:10598000006008E404000010D8340AD400008484C5
+:10599000E0240AD40100609C001828E4D000000C28
+:1059A00000180BE4090000100000609C001807E4D8
+:1059B000060000100000001500406018040363A8F2
+:1059C00000006384A81A0AD40040A0180403A5A804
+:1059D0000000C09C00006584003003E40C0000104F
+:1059E000AC1A0AD400406018100363A80400809C1D
+:1059F0000000C384000064A9000063840C200AD462
+:105A0000B0320AD419010000B41A0AD40500609C0F
+:105A10000800809CB01A0AD40300609C001827E498
+:105A200005000010B4220AD40000658400008584BB
+:105A30000000658400006584003003E478000010F5
+:105A4000B81A0AD40000A584003005E4CE00001086
+:105A5000BC2A0AD40000C09C0040601920036BA936
+:105A60003F00209D0400E0187090E7A800006784C4
+:105A70000100C69C0000009D020063B800008B84FA
+:105A80000400E79C005063E0004846E50300001076
+:105A9000102003D40100009D0000A09C002804E415
+:105AA000030000100000609C0100609C031868E087
+:105AB000002823E4EEFFFF133F00809C002046E512
+:105AC0000300001000000015FFFFC69C0020A6E5A3
+:105AD0001500000C000004A9020066B8040080183C
+:105AE000709084A80020A3E0040080186C9084A823
+:105AF0000020E3E0000067840100C69C000085846C
+:105B0000020063B8020084B8005063E00400A59C62
+:105B100010006384005084E00040A6E5F6FFFF1308
+:105B2000101804D400406018040363A800006384C4
+:105B3000C01A0AD4000083A80000609C001804E486
+:105B40008B00001010016A9C0000C09C004060198E
+:105B500020036BA93F00209D0400E0187090E7A887
+:105B6000000067840100C69C0000009D020063B82D
+:105B700000008B840400E79C005063E0004846E589
+:105B800003000010102103D40100009D0000A09C20
+:105B9000002804E4030000100000609C0100609CE9
+:105BA000031868E0002823E4EEFFFF133F00809C09
+:105BB000002046E50300001000000015FFFFC69C12
+:105BC0000020A6E51500000C020066B8000004A93C
+:105BD00004008018709084A80020A3E004008018BE
+:105BE0006C9084A80020E3E0000067840100C69C5C
+:105BF00000008584020063B8020084B8005063E0AE
+:105C00000400A59C10016384005084E00040A6E5D8
+:105C1000F6FFFF13101904D434022A850100609C9A
+:105C2000001809E4500000100000C09C00406018FB
+:105C3000040363A800006384C41A0AD400408019D6
+:105C400004038CA90000C09D00006C84007023E454
+:105C50004100000CC81A0AD400008C840000CC84D7
+:105C6000CC220AD4007006E438000010D0320AD4E6
+:105C700000008C85D4620AD40100C09C003009E485
+:105C8000190000100000609C0040A0180403A5A8A3
+:105C900000008584001804E40C000010D8220AD407
+:105CA00000406018080363A80800C09C00006384DB
+:105CB0000400609D0000A5840C300AD4DC1A0AD4CC
+:105CC0006A000000E02A0AD40000A584003025E420
+:105CD00005000010E42A0AD42000609CC8FEFF03DF
+:105CE0000C180AD400406018040363A80000638401
+:105CF000E81A0AD4000083A80000609C001804E49D
+:105D00000B000010FFFFC09C74058A849C01609CFE
+:105D1000001804E40700001000006AA81000809C2E
+:105D2000B7FEFF030C200AD4FFFFC09C00006AA846
+:105D300074340AD4000092A89E0300040000B0A8A6
+:105D40004A0000000000609D0000609CCBFFFF0344
+:105D5000D41A0AD415F9FF0700006AA8BFFFFF0391
+:105D600034022A85B6FFFF03C4320AD40400801827
+:105D7000709284A8E730FF070001A09CA8FFFF03F2
+:105D800034022A8510006A9C04008018709184A84F
+:105D9000E030FF070001A09C63FFFF030000001537
+:105DA00000406018080363A800006384CFFEFF036F
+:105DB000941A0AD499F8FF0778026A8400604BE5C8
+:105DC000040000101F006BA40100609D1F006BA465
+:105DD00000408018000384A8020063B87002EA84BF
+:105DE000002063E0000063849FFEFF03801A0AD452
+:105DF0000C00609C0B00809C401A0AD44DFEFF03EF
+:105E000044220AD40A00C09C0B00609C40320AD491
+:105E100048FEFF03441A0AD41000809C0B00C09C6B
+:105E200043FEFF0340220AD42800609CF3FFFF03D7
+:105E30002100809C00406018200363A80000C384F8
+:105E400000006384F3FFFF0340320AD418026A841F
+:105E5000002823E424FEFF130100609C341A0AD4B6
+:105E600021FEFF03381A0AD4000021850400418571
+:105E7000080081850C00C185100001861400418650
+:105E8000004800441800219CECFF219C004801D4EC
+:105E9000045001D4086001D40C7001D4108001D4E6
+:105EA000000083A900408018080384A818056384B3
+:105EB0000000C4850100639C0200809C00200EE469
+:105EC000A2010010181D0CD414056C841C048C84D1
+:105ED0000100639C18240CD4000044A9141D0CD4A8
+:105EE00000408018040384A80100A09C0000648482
+:105EF000002803E40D00000C0000C4A80200809CF0
+:105F000000200EE40500001001004A9D1C046C8472
+:105F10000100639C1C1C0CD400006684002803E470
+:105F2000F8FFFF13000000150040001A040310AA38
+:105F300078026C840000908438F8FF070000001598
+:105F40000000009D00404BE503000010000000151C
+:105F50000100609D7802EC841F006BA40040C01813
+:105F60000003C6A8063BAAE0020063B880048C8444
+:105F7000003063E0000063840000C3A8022083E0D7
+:105F8000201C0CD47C240CD40000708480340CD4ED
+:105F90000200609C00180EE449010010003045E149
+:105FA00028046C84004003E4040000100000001585
+:105FB0006C046C84701C0CD470046C8400180AE4AB
+:105FC000040000106C540CD402186AE0601C0CD45D
+:105FD000E803609C00400019040308A9061B66E062
+:105FE0000000888424240CD40200809C093B63E0D8
+:105FF00000200EE4040000100C1C4CD42404AC84DB
+:10600000282C0CD424046C840000A09C002823E4D9
+:106010000700001000200EE4030000100100C09CE7
+:1060200084340CD44B0100000000609D84046C8417
+:10603000002803E4030000100000E09C083C0CD49E
+:1060400000200EE4030000100000E09C08740CD453
+:1060500010046C84002003E403000010843C0CD482
+:106060000C1C0CD4D8026C8410740CD4002803E4EB
+:106070001400001014740CD40300669C0F00809C64
+:106080000020A3E5040000101F0063A4000064A822
+:106090001F0063A400408018000384A8020063B8B6
+:1060A0000020C3E00000868400006884002803E428
+:1060B00004000010000000150000668400008884C1
+:1060C0007002EC840200A09C002807E4F900001094
+:1060D0000000C7A814048C840100609C001804E42C
+:1060E000090000100300609C001824E4F100001077
+:1060F0000000001594026C84002803E4EE00000CFC
+:106100000000A09C00406018040363A800006384A2
+:106110002C1C0CD40000A09C002806E40D01000CEF
+:106120000000609D002806E42B0000100200609C27
+:1061300094028C840100609C001824E40600001086
+:106140000000001514046C84002823E41200000CE5
+:106150000000001500406018340363A80040801858
+:10616000040384A80000A384842A0CD40000A4841F
+:106170000000A384882A0CD40000A4840000A38417
+:10618000302C0CD40000A484000063840000A4849C
+:10619000341C0CD400406018040363A800008384FE
+:1061A0000000638438240CD43C1C0CD4000083A869
+:1061B0000000609C001804E4070000100200609CCE
+:1061C00000406018200363A800006384401C0CD4C6
+:1061D0000200609C001806E4080000100000A09C6B
+:1061E000C8028C840000609C001824E4AD00000C00
+:1061F000000000150000A09C0200609C001807E44D
+:1062000010000010F82C0CD4004080180C0384A857
+:106210008C026C840100A09C00008484002823E48C
+:106220000800001044240CD400406018040363A844
+:106230000000C38400006384F4340CD4F81C0CD434
+:106240001404AC840300609C001825E41C000010BA
+:106250000200409D94026C840100809CFFFF639CBF
+:10626000002043E41600001000000015C0046C84F8
+:106270000000409D0050A3E58300000C00000015C5
+:10628000D8048C840000609C001804E47A00000CA0
+:106290000000001594028C840100609C001824E426
+:1062A000050000100200E09C0400609DA9000000B1
+:1062B0000C380CD47002EC840200409D005007E4BE
+:1062C0003D00000C000000151404AC840040601870
+:1062D000300863A8000083841000609C300084A410
+:1062E000001824E40C0000100000E09C0000609CFA
+:1062F000001805E40500000C000000151100609C6A
+:1063000049FFFF03BC1C0CD450046C84FDFFFF0349
+:106310001000639C003825E4040000101100C09CAC
+:1063200041FFFF03BC340CD40100809C002025E415
+:10633000030000100000009D000004A90300609C01
+:10634000001825E4030000100000C09C0000C4A851
+:10635000043068E0003803E4ECFFFF0F0000001594
+:106360005004CC845404AC84002886E50C00001052
+:106370000F00859C0F00869C1100609C0018A4E50E
+:1063800005000010000000151000869C26FFFF038A
+:10639000BC240CD4FEFFFF031200809C1100609C03
+:1063A0000018A4E5FCFFFF1300000015F8FFFF0331
+:1063B0001000859CB0026C840040A0180003A5A8C2
+:1063C0001F0063A444048C84085063E0002863E049
+:1063D00000006384FE0000044C1C0CD41404AC8444
+:1063E0000000C09C485C0CD4003005E40A0000109A
+:1063F0000000E5A8004060180C0363A80000638457
+:10640000003023E404000010501C0CD451000000A4
+:1064100000006AA90200609C001827E40600001032
+:1064200000000015004060180C0363A8000063849E
+:10643000541C0CD4E8026C840000809C002023E4EF
+:10644000A3FFFF130000001570026C84002003E41A
+:106450009FFFFF13002007E49DFFFF1300000015BE
+:1064600000406018040363A80000638498FFFF03E2
+:10647000581C0CD4A7FAFF070000001586FFFF0385
+:10648000DC5C0CD45AFAFF0700006CA800500BE447
+:106490003000000C000000157BFFFF03D8048C8443
+:1064A000ADF7FF0700006CA853FFFF037002EC84F8
+:1064B0000000A09C18FFFF032C2C0CD470046C84EB
+:1064C0000218AAE08C028C84004004E4C1FEFF1391
+:1064D0005C2C0CD474048C84FFFF609C001824E4B2
+:1064E0000400001000000015742C0CD4000085A8D6
+:1064F000D7F6FF0700006AA870046C8400004BA95F
+:10650000D3F6FF0774048C8402584AE16C046C844F
+:1065100001004AB974048C84CDF6FF0764540CD48E
+:1065200070046C8400004BA9C9F6FF0774048C84C6
+:1065300002584AE17802EC8401004AB92004CC8474
+:10654000A4FEFF0368540CD466FEFF0318044C85B8
+:106550000000218504004185080081850C00C1856B
+:1065600010000186004800441400219CFCFF219C7F
+:10657000004801D40000C3A800402019080329A93D
+:106580001404638400400019140308A90000E09C6F
+:1065900000008984081C06D4142406D40000A884B2
+:1065A00018056684140586840100639C4C2C06D46F
+:1065B0000100849C1404A684181D06D4003825E428
+:1065C0004C000010142506D40100609C00000885D2
+:1065D0002C1C06D4EC4406D400406018880363A841
+:1065E000000083840200609C001804E43B0000105B
+:1065F000001884E4320000100000A09C0300609C9E
+:10660000001804E42A0000100100A09C004060185B
+:10661000880363A80200A09C00008384002804E48F
+:106620001B000010002884E4120000100000609C91
+:106630000300609C001804E4070000100100809C27
+:1066400000406018040363A8000063845A0000003F
+:10665000581D06D400406018080363A8502506D4CE
+:106660000100A09C00008384F6FFFF03542D06D494
+:10667000501D06D400406018040363A80000838402
+:106680000000809CF1FFFF03542506D400406018F1
+:10669000080363A80100A09C000083840000609CA4
+:1066A000502D06D4E7FFFF03541D06D40000698473
+:1066B000482D06D4D6FFFF034C2D06D40000809C45
+:1066C00000406018040363A8482506D400008384B2
+:1066D000CFFFFF034C2D06D4000069840000809C8E
+:1066E0000100609C4C2506D4C9FFFF03481D06D459
+:1066F000F0046684003803E4050000100000609C8C
+:106700002C0486840100609C022063E00040E018B5
+:106710000403E7A82C1C06D40000878400406018FE
+:10672000880363A80200A09CE82406D400008384A8
+:10673000002804E4190000100100609C002884E493
+:10674000130000100000A09C0300609C001804E4EB
+:10675000090000100100A09C00406018040363A819
+:106760000000838400006384642506D412000000C6
+:10677000681D06D400406018080363A800008384E5
+:106780005C2D06D4F5FFFF03602D06D4000067845E
+:10679000FDFFFF035C2D06D45C1D06D4004060188D
+:1067A000080363A8000083840000809CEBFFFF03C4
+:1067B000602506D40100A09C0000609D102A06D42C
+:1067C00000002185004800440400219C0000A3A88B
+:1067D0000000609C001824E42F00000C0100609D64
+:1067E0000700609C001844E40A0000100C00609C44
+:1067F000020064B804008018DC7C84A8002063E0F8
+:106800000000838400200044000000150C00609C00
+:106810000018A5E520000010000000151E00000073
+:106820000000609D0E00609C0018A5E51A00001095
+:1068300000000015180000000000609D1000609C22
+:106840000018A5E51400001000000015120000005B
+:106850000000609D1200609C0018A5E50E0000106D
+:10686000000000150C0000000000609D1400609CFA
+:106870000018A5E508000010000000150600000043
+:106880000000609D1600609C0018A5E5E4FFFF0F66
+:10689000000000150048004400000015F0FF219C96
+:1068A000004801D4045001D4086001D40C7001D414
+:1068B000000043A90000809D8402638488028A84CA
+:1068C0000F00639C0F00849C9F00A3B89F00C4B876
+:1068D0005C00A5B85C00C6B8002863E0003084E026
+:1068E000840063B8840084B8981C0AD49C240AD419
+:1068F000062363E0C9F5FF07941C0AD41F006BA4AC
+:1069000000408018000384A8020063B80040A0186B
+:106910000403A5A8B85C0AD4002063E00000C5A861
+:10692000000063841400849C000084848C1C0AD4BE
+:106930004C240AD400006584006003E45400001075
+:10694000901C0AD400408018300884A80000648499
+:10695000300063A4006023E4710000100000001503
+:10696000000065840100809C002003E40600000C08
+:106970000000001500006684002003E4FEFFFF1302
+:10698000000000150040C0190403CEA978026A84F3
+:1069900000008E84A1F5FF07000000150000609C38
+:1069A00000184BE5040000101F006BA40100609D5F
+:1069B0001F006BA400408018000384A8020063B885
+:1069C000002063E00000838500008E840040601892
+:1069D000080363A81404AA8400008384002804E444
+:1069E0006E00000C0200609D70028A840200609CB0
+:1069F000001804E4260000100300809C004060188A
+:106A00000C0363A800008385002025E40600001025
+:106A10000000609CC0048A840018A4E53C00000CBF
+:106A20000000001544046A8400180CE43300000CD4
+:106A300000008CA81404CA840000609C001806E4BE
+:106A4000090000100200609D004080180C0384A81B
+:106A500050046A840000A484001805E44F00000C70
+:106A600000000015005826E4090000100000001581
+:106A7000004080180C0384A854046A840000A48495
+:106A8000001805E44500000C00000015D8026A84D7
+:106A90000000E09C003803E4160000100F00809C0A
+:106AA00020046A840300639C0020A3E50400001016
+:106AB0001F0063A4000064A81F0063A400408018A6
+:106AC000000384A8020063B80040C0180403C6A8ED
+:106AD0000020A3E00000858400006684003803E401
+:106AE00003000010000000150000658400006684AB
+:106AF0002A0000000000609D4C046A8434FFFF07F8
+:106B000044640AD4CCFFFF03485C0AD4B8F8FF07FA
+:106B100000006AA8C5FFFF0344046A84000065847E
+:106B20000100C09C003003E40800000C00000015C8
+:106B30001C048A8400006584003003E4FEFFFF1318
+:106B40000100849C1C240AD40040801904038CA9F1
+:106B500078026A8400008C8430F5FF07000000157D
+:106B60000000609C00184BE5040000101F006BA49F
+:106B70000100609D1F006BA400408018000384A8E2
+:106B8000020063B8002063E00000638400008C848E
+:106B90008FFFFF03201C0AD40000218504004185DB
+:106BA000080081850C00C185004800441000219C2C
+:106BB000DCFF219C004801D4045001D4086001D4BA
+:106BC0000C7001D4108001D4149001D418A001D409
+:106BD0001CB001D420C001D4000043A9000084A946
+:106BE000000064A80000C5A9000085A83E3DFF077D
+:106BF0000000809E41008EB800004BAA3A3DFF077E
+:106C000000006CA864170A8600000BAB90058A840C
+:106C100000A004E40E0000106817CA8684026A848B
+:106C200000182CE4060000100000001588026A8499
+:106C300000182EE40600000C0000001554146A84AD
+:106C400000A023E40C00000C0000001584620AD4AC
+:106C50000000609C001824E40500001088720AD42B
+:106C60003C644AD438744AD40000609C2A00000076
+:106C7000541C4AD404006018FC7C63A83F2EFF0714
+:106C8000000092A804006018157D63A83B2EFF0742
+:106C9000000090A80080B2E4030000100000809C77
+:106CA0000100809C00B0B8E4030000100000609C6C
+:106CB0000100609C041864E000A003E408000010D8
+:106CC000008072E40100609C441C4AD4541C4AD4E5
+:106CD00088720AD41000000084620AD403000010F5
+:106CE0000000809C0100809C00B078E4030000104C
+:106CF0000000609C0100609C041864E000A003E4B4
+:106D0000F4FFFF130200609C441C4AD4F0FFFF0311
+:106D10000100609C0000609D000021850400418509
+:106D2000080081850C00C185100001861400418691
+:106D3000180081861C00C18620000187004800449D
+:106D40002400219CF4FF219C004801D4045001D46C
+:106D5000086001D49402E385000043A9FF1F809CD2
+:106D6000004060188C9063A88C02CA848100AFB880
+:106D7000002003D40100A5A400406018380863A8CF
+:106D8000D002EA8400408018049084A8003003D424
+:106D9000D4020A8500406018009063A8002803D43C
+:106DA000003804D40800639C0200809C004003D497
+:106DB00000202FE4040000100400639CD4048A84A3
+:106DC000002003D4C0048A840000609C001824E4DE
+:106DD000820200100100C09C00406018109063A85F
+:106DE0000000A09C002803D484022A850F00C99CBF
+:106DF00088026A859F0066B89F0009B90F00EB9C66
+:106E00005C0063B89F0087B89F00ABB80018C6E06D
+:106E10005C0084B88400C6B800406018200863A8ED
+:106E20005C00A5B85C0008B90020E7E0003003D49E
+:106E3000004009E18400E7B80028ABE00400639C4F
+:106E40008400A5B8840088B8003803D40F0029A5B1
+:106E50000000C09C003009E4030000100F006BA488
+:106E60000100849C003003E45A0200100100659C7C
+:106E7000061BA4E0FFFF659C0100809C002043E40A
+:106E80000A02000C0000809DFDFF659C002043E489
+:106E900002020010FBFF659C0200809D004060180C
+:106EA000A49063A800408018300884A8006003D430
+:106EB000000064841200809C1E0063A4002023E470
+:106EC000E7010010000000158402EA840040601809
+:106ED000180863A8004080181C0884A888020A8546
+:106EE000003803D4004004D4B8028A8400406018FB
+:106EF000040C63A8002003D40100609C001824E463
+:106F0000BC0100103F00C09CBC02EA84001827E4CA
+:106F1000A60100100000609C0000A09C3F00C09CE7
+:106F200010006A9C00408018001084A800000385AF
+:106F30000100A59C004004D40400639C0030A5E53A
+:106F4000FBFFFF130400849CC0028A840100609C44
+:106F5000001824E4830100100000609C0000A09C45
+:106F60003F00C09C10016A9C00408018001184A85A
+:106F70000000E3840100A59C003804D40400639C55
+:106F80000030A5E5FBFFFF130400849C0000609C1B
+:106F900014040A851C1A0AD40000A8A9004060182D
+:106FA000340863A8004003D40200609C001828E461
+:106FB00006000010000000150804AA8400406018B4
+:106FC000609063A8002803D48C02CA840000609CEF
+:106FD000001806E40600001000000015F404EA841E
+:106FE000004060181C0C63A8003803D4F8040A851C
+:106FF00000406018080C63A80040A0183008A5A83D
+:10700000004003D4000085841000609C300084A4FC
+:10701000001824E44E010010DA3BE09C0000658477
+:107020000600809C0E0063A4002023E443010010AE
+:107030008038A09C00406018749063A88030809CC9
+:10704000002003D404136A840000A09C002803E4F9
+:107050000A0000100200609C0100009D00406018C2
+:10706000480863A800408018400884A8004003D462
+:10707000004004D40200609C00182DE4230000109E
+:10708000002826E42A0100100000001560046A852B
+:107090005C04AA840800E5B80100859C01000B9DF2
+:1070A000080084B8095BE7E0FFFFC59C004060185A
+:1070B000489063A80258A5E00800C6B80800A5B823
+:1070C000FFFF2B9D094384E0003803D40400639C38
+:1070D000095BE5E0002003D40400639C00408018B5
+:1070E0005C9084A8094305E1094BC6E0094BA5E083
+:1070F000003003D40400639C003803D40400639C74
+:10710000004003D4002804D444048A84004060185A
+:10711000149063A80000C09C002003D400300DE44C
+:10712000060000100200809C5004AA840400639CA6
+:10713000002803D40200809C00202DE406000010EB
+:10714000000000155404EA84004060181C9063A8F5
+:10715000003803D400202FE40D00001000000015BB
+:10716000C4046A98FF7F0019000008A90040A01815
+:107170006490A5A8100063B8C6048A98034063E031
+:10718000FF7F84A4042063E0001805D40040601849
+:10719000209063A80100809C0000A09C002003D4E4
+:1071A0000000E09C00408018280884A8002804D42F
+:1071B0000400849C0040A0183008A5A8003804D41E
+:1071C000000065841600809C3E0063A4002023E438
+:1071D000060000100100609CC4028A84001804E4C8
+:1071E0000C0000100000001500006584300063A44E
+:1071F000003023E4C800001000000015C4028A8497
+:107200000100609C001804E4C400000C000000159C
+:1072100000406018440863A80200009D004003D4A9
+:10722000BC046A8400408018000C84A82C04CA8422
+:10723000EFFF639C003004D44C04EA84010063B87F
+:1072400000408018689084A8CC02AA840E0063A431
+:10725000003804D40100A5A40400849C0418A5E00F
+:10726000002804D4AA35FF070000001500138A8403
+:107270000000C09C003024E4030000100000E09CEB
+:107280000100E09C0200609C001824E40300001050
+:107290000000A09C0100A09C042867E0003003E4EB
+:1072A0009B0000100100E09C14040A85003828E4CB
+:1072B000030000100000209D000027A90300609C2F
+:1072C000001828E4030000100000A09C0000A7A8FC
+:1072D000042869E0003003E473000010FFFF649CA1
+:1072E00000408018000A84A80040A0185408A5A8EF
+:1072F000003804D400006584010063A8001805D498
+:107300002B00809C78056A848EFE639C002043E4F9
+:107310005F0000100000C09C00406018789063A8D7
+:107320000100A09C002803D404138A840000609C00
+:10733000001804E40C00001000000015C0056A8469
+:10734000020063B80050A3E0280F85840040601855
+:10735000809063A8A80EC584080084B8003084E03B
+:10736000002003D4B4056A84020063B80050A3E08F
+:10737000280F858400406018080B63A8A80EC584F8
+:10738000080084B80200A09C003084E0002003D4F0
+:10739000002828E4200000100100A09CB8058A8481
+:1073A000FFFF209D004824E404000010020084B880
+:1073B0000000809C020084B8BC05EA840050A4E070
+:1073C000280F658400408018040B84A8A80EC5848B
+:1073D000080063B8003063E0001804D4004827E4D4
+:1073E00004000010020067B80000E09C020067B8CB
+:1073F0000050A3E0280F858400406018000B63A8AC
+:10740000A80EC584080084B8003084E0002003D4AE
+:107410000100A09C002828E4030000100000C09C8C
+:107420000000C5A80300609C001828E403000010B9
+:107430000000809C000085A8042086E00000609C7D
+:10744000001804E4EA000010FFFF609CB805EA841D
+:10745000001827E404000010020067B80000E09C58
+:10746000020067B80050A3E0280F85840040601830
+:10747000000B63A8A80EC584080084B8003084E01F
+:10748000002003D4DB000000F812EA8400406018FA
+:10749000789063A8003003D4A5FFFF0304138A8407
+:1074A000FFFF649C0100C09C003043E40E0000100C
+:1074B000000000150200609C001828E40A0000107B
+:1074C0000000001500408018000A84A80040A018A1
+:1074D0005408A5A8003004D40000658488FFFF0389
+:1074E000043063E000408018000A84A80000609C1B
+:1074F0000040A0185408A5A8001804D40000658412
+:10750000FEFF809C7EFFFF03032063E0E5FFFF0397
+:1075100014040A85C4028A8400406018440863A8E1
+:10752000002003D440FFFF03BC046A8468046A851A
+:10753000D9FEFF036404AA8400406018749063A815
+:10754000002803D4C1FEFF0304136A8400406018BE
+:10755000749063A8003803D4BCFEFF0304136A844C
+:10756000001827E48BFEFF130000609C0000A09C25
+:107570003F00C09C00408018001184A804006018DF
+:10758000709263A8000003850100A59C004004D40C
+:107590000400639C0030A5E5FBFFFF130400849CFE
+:1075A0007CFEFF030000609C001827E467FEFF13C9
+:1075B000000000150000A09C3F00C09C0040801807
+:1075C000001084A804006018709163A8000003856F
+:1075D0000100A59C004004D40400639C0030A5E594
+:1075E000FBFFFF130400849C59FEFF03C0028A8442
+:1075F0000000A09C00408018001084A804006018BF
+:10760000709163A80000E3840100A59C003804D4B5
+:107610000400639C0030A5E5FBFFFF130400849C7D
+:107620000000A09C3F00C09C00408018001184A86E
+:1076300004006018709263A8000003850100A59CF7
+:10764000004004D40400639C0030A5E5FBFFFF1359
+:107650000400849C4FFEFF030000609C00408018E3
+:10766000200884A80040A0182408A5A8000064846D
+:10767000040063B800408018180884A8001804D4D7
+:10768000000065840400849C040063B8001804D4DE
+:1076900017FEFF03B8028A840300809C002043E4A5
+:1076A00004000010F7FF659CFDFDFF03000084A9A6
+:1076B0000700C09C003043E404000010EFFF859CED
+:1076C000F7FDFF030400809D0F00609C001844E458
+:1076D00004000010DFFF859CF1FDFF030500809D85
+:1076E0001F00609C001844E404000010BFFF859C4C
+:1076F000EBFDFF030600809D3F00609C001844E402
+:10770000040000107FFF859CE5FDFF03000086A9B3
+:107710007F00609C001844E404000010FFFE859C7C
+:10772000DFFDFF030800809DFF00609C001844E41B
+:1077300004000010FFFD859CD9FDFF030900809D1A
+:10774000FF01609C001844E404000010FFFB859CCE
+:10775000D3FDFF030A00809DFF03609C001844E4F2
+:1077600004000010FFF7859CCDFDFF030B00809DFA
+:10777000FF07609C001844E404000010FFEF859CA4
+:10778000C7FDFF030C00809DFF0F609C001844E4C0
+:1077900004000010FFDF859CC1FDFF030D00809DEC
+:1077A000FF1F609C001844E4040000100000001556
+:1077B000BBFDFF030E00809D04006018307D63A8B0
+:1077C0006E2BFF07000085A8B5FDFF039402EA8534
+:1077D000A9FDFF03062BA4E000406018109063A8E9
+:1077E000003003D482FDFF0384022A85F812EA8464
+:1077F00000406018300C63A800408018340C84A846
+:10780000FC124A85003803D4005004D400002185BE
+:107810000400418508008185004800440C00219C3B
+:10782000F8FF219C004801D4045001D48402C38491
+:10783000000043A9FF1F809C004060188C9063A843
+:107840001404EA840F00C69C002003D48802AA8492
+:1078500000406018340863A8840086B8003803D458
+:107860000F00A59C0804EA8400406018609063A89B
+:10787000003803D400406018200863A88400E5B8ED
+:10788000002003D4F0FF609CF0FF809C0318C6E04A
+:107890000320A5E000406018240863A80040801879
+:1078A0001C0884A8003803D400406018180863A896
+:1078B000E804EA84003003D4002804D400406018AF
+:1078C000689063A84C04AA8400408018209084A883
+:1078D000002803D4003804D400406018249063A822
+:1078E00048058A84002003D44C05AA8400408018EF
+:1078F000289084A80800639C5005EA84002804D4DA
+:10790000003803D40800849C54056A84001804D409
+:107910005C05AA8400406018349063A858058A84E6
+:10792000002003D46005EA8400408018389084A8C1
+:107930000800639C002804D4003803D40800849C09
+:1079400064056A840000E09C001804D42C04AA8416
+:1079500000406018449063A868058A84002003D41E
+:1079600000408018000C84A800406018280863A814
+:10797000002804D4003803D4004080182C0884A8C0
+:10798000003804D4E233FF070000001500138A8496
+:107990000000C09C003024E4030000100000E09CC4
+:1079A0000100E09C0200609C001824E40300001029
+:1079B0000000A09C0100A09C042867E0003003E4C4
+:1079C000A00000100000001514042A850100609C2E
+:1079D000001829E4910000100000001500408018F4
+:1079E000000A84A80040A0185408A5A8001804D4D0
+:1079F00000006584010063A8001805D404130A85FB
+:107A00000000609C001808E4080000100100A09C21
+:107A100000406018480863A800408018400884A807
+:107A2000002803D4002804D4004060181C0863A870
+:107A3000EC04EA840000A09C000083840F00849C76
+:107A40001800609C001827E45B000010440084B814
+:107A5000EAFF679C0A1BC4E00010E0180000E7A8DA
+:107A6000080086B87F0066A4803F84A4043884E0C0
+:107A70000418A4E000406018709063A80000809C87
+:107A8000002803D4002008E40C00001000000015BA
+:107A9000C0056A84020063B80050A3E0280F858403
+:107AA00000406018809063A8A80EC584080084B8C0
+:107AB000003084E0002003D4B4056A84020063B877
+:107AC0000050A3E0280F858400406018080B63A8CD
+:107AD000A80EC584080084B80200A09C003084E091
+:107AE000002003D4002829E4200000100100609C3D
+:107AF000B8058A84FFFF009D004024E404000010C4
+:107B0000020084B80000809C020084B8BC05EA84AE
+:107B10000050A4E0280F658400408018040B84A85E
+:107B2000A80EC584080063B8003063E0001804D4D0
+:107B3000004027E404000010020067B80000E09C49
+:107B4000020067B80050A3E0280F85840040601849
+:107B5000000B63A8A80EC584080084B8003084E038
+:107B6000002003D40100609C001829E437000010B5
+:107B7000FFFF609CB805EA84001827E404000010A9
+:107B8000020067B80000E09C020067B80050A3E064
+:107B9000280F858400406018000B63A8A80EC584D8
+:107BA000080084B8003084E0002003D428000000DE
+:107BB000F8128A841A00609C001827E4AEFFFF13B5
+:107BC000EAFF679C0A1BC4E0E00FE0180000E7A88A
+:107BD000170066B8010086B80800A6B8033863E04D
+:107BE000003084E00020E0180000E7A80E0084B810
+:107BF000043863E0803FA5A41F00E01800C0E7A898
+:107C00007F00C6A4033884E0042063E0042863E016
+:107C100099FFFF030430A3E000408018000A84A805
+:107C20000000609C0040A0185408A5A8001804D4C7
+:107C300000006584FEFF809C70FFFF03032063E06B
+:107C4000F6FFFF0314042A85F8128A8400406018A6
+:107C5000300C63A8002003D4FC124A850040801831
+:107C6000340C84A8005004D4000021850400418510
+:107C7000004800440800219CECFF219C004801D4EE
+:107C8000045001D4086001D40C7001D4108001D4D8
+:107C9000000043A90000C09D0000609C1C03AA8C4A
+:107CA000A01D0AD80000609C741D2AD440186AD414
+:107CB000A11D0AD80100609CF8180AD40000609C3D
+:107CC000201B0AD4A21D0AD8FFFF609CFC180AD40E
+:107CD000781B0AD40000609C7C1D0AD80000609CC0
+:107CE00000190AD4FFFF609C04190AD40000609CAC
+:107CF0007D1D0AD80000609C10190AD414190AD4FA
+:107D00007E1D0AD80000609C941D2AD4FFFF609C51
+:107D100008190AD400288EE50E00000C0C190AD4AC
+:107D2000A0050A9E7F058A9D00008EA8000070A80D
+:107D30002632FF070100CE9DFFFF609C1C03AA8C2A
+:107D400000180CD800288EE5F8FFFF1301008C9D69
+:107D50000000218504004185080081850C00C18553
+:107D600010000186004800441400219CFCFF219C67
+:107D7000004801D40000E3A80000609C001824E43F
+:107D80001B000010000064A91400678C0100839C94
+:107D9000000003A9142007D80000609C001805E427
+:107DA0001000001000000015DC00A68CDB00C68C63
+:107DB0001400889C003828E10000609C00182BE427
+:107DC00005000010002087E0032804D80D00000003
+:107DD000013004D81A3009D80A0000001C2809D83C
+:107DE000DA00A68CF3FFFF03D900C68C1900678C5C
+:107DF0000100839C000003A9E8FFFF03192007D8B6
+:107E000000002185004800440400219CECFF219CD7
+:107E1000004801D4045001D4086001D40C7001D48E
+:107E2000108001D4C8058385000043A90100009E8D
+:107E3000C405C3857C00638C008023E456000010D9
+:107E40000200A09C7B006A8C002823E448000010FC
+:107E50000000609C85006A8C0000809C002023E468
+:107E60001E00001000000015D8006A8C002023E4DA
+:107E70001100000C008023E40B00000C002823E418
+:107E80004500001000006CA8000090A80000CAA8DF
+:107E90000000A09CB6FFFF07000000153E00000098
+:107EA0000000001500006CA80000CAA8F9FFFF033D
+:107EB0000000809C00006CA80000CAA8ACFFFF076F
+:107EC0000000A09C00006CA8000090A80000B0A8D2
+:107ED000F1FFFF030000CAA886006A8C008023E43B
+:107EE0001200001000000015D8006A8C002023E466
+:107EF0000A00000C008023E40600000C002823E4A4
+:107F00002500001000006CA8E1FFFF03000090A80E
+:107F1000E6FFFF0300006EA800006EA80000CAA8DC
+:107F2000E7FFFF030000809CD8006A8C002023E458
+:107F30000800000C008023E4DBFFFF0F002823E48F
+:107F40001500001000006EA8D1FFFF03000090A8EC
+:107F500000006CA80000CAA80000809C84FFFF07F6
+:107F60000000A09CD9FFFF0300006EA8D8008A8CF7
+:107F7000001824E4080000100000A09C0000CAA81B
+:107F800000006CA87AFFFF070000809CBFFFFF0382
+:107F900000006CA80000218504004185080081854F
+:107FA0000C00C18510000186004800441400219C8B
+:107FB000F4FF219C004801D4045001D4086001D48E
+:107FC0007803C384000043A9A005839D000086A810
+:107FD000FFFFA09C002806E40B00001000006CA826
+:107FE0003732FF071C03AA8C0000809C00202BE482
+:107FF0000500001000006CA878038A847331FF0725
+:108000001C03AA8C1C03AA8C7C056A9CF531FF0713
+:1080100078038A9C00002185040041850800818541
+:10802000004800440C00219CF4FF219C004801D42E
+:10803000045001D4086001D4000043A908016384FE
+:10804000040083B8021884E0020084B80400609C35
+:1080500000208AE0D005849C0000A48C031804D87A
+:10806000041804D8051804D80200609C012804D81C
+:108070007B00CA8C003004D8E410AA84001825E4E0
+:108080001D0000100000609C24116A84E8184AD486
+:10809000880D8A8C0000609C001804E41400001015
+:1080A0000000A09CE0108A84F0204AD408018A8451
+:1080B000FFFF609C001804E42A0000107C058A9DE4
+:1080C0001C03AA8C4131FF0700006CA8FFFF609CD5
+:1080D00000180BE40400000C00000015F9FFFF037A
+:1080E00008018A841F00000008018A84F0FFFF0352
+:1080F000F0284AD4001825E403000010E810609C22
+:10810000EC10609C2411CA8400186AE0003003D48B
+:10811000880D8A8C0000609C001804E40A0000109E
+:10812000001825E4001825E403000010F010609CFE
+:10813000F410609CE0108A8400186AE0DCFFFF0302
+:10814000002003D403000010F010609CF410609C29
+:1081500000186AE00000A09CD5FFFF03002803D4AC
+:10816000040064B80801AA840100C09C022063E0F6
+:108170007A300AD8020063B80C290AD400186AE0E1
+:10818000D005639CCC1D0AD4C81D0AD400002185EB
+:108190000400418508008185004800440C00219CB2
+:1081A000FCFF219C004801D40000E3A80400A018B3
+:1081B000D081A5A80000609CC405C7847A1807D8A0
+:1081C0000D00609C00008584001824E4310000103C
+:1081D0008100609C7B00878C002006D87B00678C28
+:1081E000011806D88900678C241806D48A00878C69
+:1081F000282006D48800878C022006D84000678497
+:10820000101806D40D00878C072006D80E00678C46
+:10821000081806D8700067940100639C010063B8D9
+:108220000A1806DC0000609C720087940100849CA0
+:10823000141806D8010084B8191806D8151806D8DD
+:10824000171806D8161806D8181806D81A1806D8F7
+:108250001C1806D81B1806D81D1806D80C2006DCDA
+:108260007500878C1E2006D87600678C1F1806D8EC
+:108270007700878C202006D80000809C7800678CCF
+:10828000222006D8211806D8000085848100609C31
+:10829000001824E421000010000000157B00678C0A
+:1082A000001806D87B00878C012006D88900678CCF
+:1082B000241806D40D00678C071806D80E00878C8A
+:1082C000082006D83A0067940A1806DC0000609C73
+:1082D00036008794141806D80C2006DC191806D826
+:1082E000151806D8171806D8161806D8181806D85C
+:1082F0001A1806D81C1806D81B1806D81D1806D838
+:108300001E1806D81F1806D8201806D8211806D817
+:10831000F200878C222006D87B00878C0200609CAC
+:10832000001824E4770000100000609C8600878C11
+:10833000001824E470000010000000157C00678C19
+:10834000041806D88400878C0000609C001804E4A0
+:10835000030000100000A09C0100A09C032806D888
+:108360000300609C8400878C001844E40300001024
+:108370000000A09C0100A09C062806D8C300678CC2
+:108380000E1806D844006784FFFF8018000084A8F8
+:10839000032063E000018018000084A8002023E48B
+:1083A000260000100200609C7C00078D004023E442
+:1083B0000E00001000000015C80567841000A68498
+:1083C00010008384002025E4070000100100609C59
+:1083D000CC05678410008384002025E40300000C92
+:1083E0000100609C7A1807D87B00678C0200809C93
+:1083F000002023E411000010000000158400678CA9
+:10840000002023E40D000010FF0068A40100009D7F
+:10841000004023E40900001000000015C80567842F
+:10842000100086841000A384002804E403000010D8
+:10843000000000157A4007D804006018749363A800
+:108440000400A0184083A5A800008384040065846C
+:10845000001824E4220000100000809C382006D47C
+:1084600004008018408384A804006018749363A8F3
+:10847000000084840100A09C002003D47C00878C31
+:10848000032006D83C036784FFFF639C002843E475
+:108490001000001000000015242806D40000609C85
+:1084A0000100809C281806D47C00678CFF00639C28
+:1084B000FF0063A4002043E4240000100000001526
+:1084C00053FEFF07000067A8200000000000001511
+:1084D0008900678CF2FFFF03241806D4341806D4F1
+:1084E0000000A5840100609C302806D4DDFFFF0356
+:1084F000381806D47C00878C93FFFF03052006D82C
+:108500007C00878C032006D80100809C7C00678C4F
+:10851000041806D87C00678C051806D87C00678C88
+:10852000FE00639CFF0063A40020A3E4030000108E
+:108530000000A09C0000A4A80000809C062806D88B
+:1085400091FFFF030E2006D800002185004800445B
+:108550000400219CE0FF219C004801D4045001D478
+:10856000086001D40C7001D4108001D4149001D49F
+:1085700018A001D4FF0043A6000044A90000609C9D
+:1085800004008018D08184A8741D2AD4000084843B
+:108590000D00609C001804E4030000100000C09C63
+:1085A0000100C09C8100609C001804E403000010DE
+:1085B0000000A09C0100A09C032886E00000609CB5
+:1085C000001804E43E00000C0000809D1C03CA8CCF
+:1085D000A005CA9D1C00819E000072A8FF00C6A4D1
+:1085E0000000B4A800008EA82A30FF07FFFF009EFD
+:1085F00004006018517D63A800802BE41800000C73
+:10860000000000151C00A18408018A84002005E4F4
+:1086100007000010000000151C00A1840C018A84D2
+:10862000002005E40E00000C000000151C008184F1
+:10863000D227FF07000000151C00818400006EA8EF
+:10864000E22FFF071C03AA8C1C03CA8C00302CE409
+:10865000E2FFFF1301008C9D1C8001D41C0061848B
+:10866000FFFF809D006023E4030000107D00609CFC
+:10867000741D2AD41C00818404006018597D63A8ED
+:10868000BE27FF07000000151C006184000083A8BE
+:10869000FC180AD47803AA84040063B8022063E0BB
+:1086A000020063B800186AE0D005639C002824E447
+:1086B00003000010C41D0AD474652AD4000021856B
+:1086C00004004185080081850C00C18510000186E9
+:1086D0001400418618008186004800442000219C37
+:1086E000E0FF219C004801D4045001D4086001D46B
+:1086F0000C7001D4108001D4149001D418A001D4BE
+:108700001CB001D4000004AAFF0043A6880D848495
+:1087100000FF601800FF63A80000E09C031884E0DD
+:10872000003824E4260000100000209D004060185E
+:108730002C0263A8900DB0840000C09D0400C01AF4
+:10874000C880D6AA0000438502008AB90100CE9DE8
+:10875000000072A800008EA8B130FF0704004A9DF7
+:10876000000076840080A0180000A5A80000009DED
+:10877000006063E0900D9084002863E010008C9D01
+:108780000000E3840000A4A8580067B8420084B841
+:108790001000C3A400208AE4040000101F0023A5D9
+:1087A0000000809D0000409D00402BE48700000CED
+:1087B000004026E4E6FFFF13000000150000609C67
+:1087C000701D30D400406018200863A80000838426
+:1087D0000B00609C001829E457000010FFFF449D27
+:1087E0007C00908C0400609C001804E4520000108F
+:1087F0000000609DE0008018000084A81F00A01801
+:10880000FFFFA5A8032067E0032887E05500A3B871
+:1088100008147084005803E404000010020084B8B7
+:108820000C147084001884E00028A4E00400601890
+:10883000908063A80400A59C04002019487D29A904
+:108840000700E5A400008384004807E10238A5E0A2
+:108850000000C88C002884E000806018000063A835
+:108860000030C4E00100A88C0018C6E0FF006018CA
+:10887000FFFF63A8002884E0031894E20080A0189A
+:108880000000A5A80000668C002884E0180063B8EA
+:108890000000A48C041894E21000A5B800FF601832
+:1088A000FFFF63A88500D08C031894E2042894E2AB
+:1088B000580094B8570074B8010084B8010063A44C
+:1088C000041884E0005806E410000010FFFFA49C88
+:1088D00000406018240863A8000083840220A5E0FB
+:1088E0000000609C041810D8100065B80040801883
+:1088F000C08084A8102C50D4045063E0001804D425
+:10890000340000000000001500408018240884A8EE
+:1089100000006484001885E4F3FFFF130000609CEE
+:10892000000064840100809CFFFFA39CEDFFFF0317
+:10893000702530D47B00908C0200A09C002804E4B9
+:10894000030000100000C09C0100C09C0C00E09CD3
+:10895000003809E4030000100000609C0100609CE6
+:10896000041866E0002824E413000010041810D84E
+:108970008500708C0000809C002023E40300001020
+:108980000000A09C0100A09C003809E40300001036
+:108990000000609C0100609C031865E0002003E477
+:1089A000050000100100609C0000A09C042810D865
+:1089B000701D30D400406018240863A80000838430
+:1089C000CAFFFF03FFFFA49C7B00809C742530D46A
+:1089D0000000218504004185080081850C00C185C7
+:1089E0001000018614004186180081861C00C18693
+:1089F000004800442000219CECFF219C004801D449
+:108A0000045001D4086001D40C7001D4108001D44A
+:108A1000FF00C3A5000006AA000047A910006018C7
+:108A2000000063A80018A7E405000010FF0085A55A
+:108A300000806018000063A8041847E10000C09C93
+:108A400000302AE4030000100000E09C0100E09CDC
+:108A50004318609C001848E4030000100000A09C2C
+:108A60000100A09C042867E0003003E49800000C9B
+:108A70001900609D005004D400006AA80000809C8A
+:108A8000C52EFF074418A09C0100809C00202CE408
+:108A9000740000100200609C0000C09C88252AD849
+:108AA00089352AD88A352AD80000609C0000C09CED
+:108AB0001D1B0AD80000809C04006018588363A81E
+:108AC00079300AD80000E09C28300AD80C300AD847
+:108AD0000100C09C002003D440206AD40400601828
+:108AE000548363A8040080185C8384A8003803D4EE
+:108AF000003804D404006018648363A8040080185C
+:108B0000608384A8003803D4F8300AD4FFFF609C47
+:108B1000003804D4FC180AD4781B0AD404190AD4E7
+:108B200008190AD40C190AD4743D2AD4203B0AD45B
+:108B300000390AD410390AD414390AD4943D2AD4FD
+:108B4000143C4AD48928FF0708700AD46130FF0713
+:108B50000000001504006018BC8063A804008018A1
+:108B6000508384A80000A3840100C09C0000609C86
+:108B7000001805E403000010003004D47C1D2AD442
+:108B80000100609C0000809C0000E09C00180AD45A
+:108B9000E0204AD404380AD80000A09C1F00C09CE2
+:108BA000D8862AD468128A9C60106A9C0000E09CD7
+:108BB0000100A59CE03FE4DBFFFFE09C803EE3D7A3
+:108BC000003FE3D70000E09C003804D80000E09CA0
+:108BD0000100849C803FE3D7003803D40030A5E532
+:108BE000F3FFFF130400639C0200609C0000A09C44
+:108BF000E4184AD40100809CF0106A9CFFFFC09CDE
+:108C00000000E09CF837E3D7003803D40100A59CAE
+:108C10000020A5E5FCFFFF130400639C0000609C9E
+:108C20000000809C70180ADC0100C09C0000609C61
+:108C300008244AD408314AD472380ADC0000609D06
+:108C4000F8184AD4FC184AD400194AD4C41E2AD4AD
+:108C5000C01E2AD410194AD41D00000014194AD489
+:108C600000182CE40F0000100300609C0000E09C42
+:108C700089252AD800406018082063A888252AD8AA
+:108C800000408018042084A88A3D2AD8000063840C
+:108C90000000848438180AD484FFFF0334200AD4E7
+:108CA00000182CE4060000100000609C881D2AD8E3
+:108CB000891D2AD87DFFFF038A252AD80000809CC1
+:108CC00088252AD8FCFFFF0389252AD800002185A2
+:108CD00004004185080081850C00C18510000186D3
+:108CE000004800441400219CF8FF219C004801D456
+:108CF000045001D4E1FBFF07000043A90000609C81
+:108D00000000A09C04180AD81F00C09C68128A9C0E
+:108D100060106A9C0000E09C0100A59CE03FE4DB41
+:108D2000FFFFE09C803EE3D7003FE3D70000E09CDC
+:108D3000003804D80000E09C0100849C803FE3D709
+:108D4000003803D40030A5E5F3FFFF130400639C53
+:108D50000200609C0000A09CE4184AD40100809CA2
+:108D6000F0106A9CFFFFC09C0000E09CF837E3D73E
+:108D7000003803D40100A59C0020A5E5FCFFFF13EB
+:108D80000400639C0000C09C0000609C0100E09C0B
+:108D900079180AD814344AD440386AD400314AD4F5
+:108DA0000000218504004185004800440800219C02
+:108DB0000000E3844800A7B8580087B80800C7B887
+:108DC00000FFA5A4042884E01800E7B8FF00A0185D
+:108DD0000000A5A80328C6E0043084E0043884E03D
+:108DE000002003D40048004400000015F0FF219C3F
+:108DF000004801D4045001D4086001D40C7001D49F
+:108E00000400A018D081A5A8FF0083A50000A584B8
+:108E10000F00609C001805E4B9000010000044A990
+:108E2000001845E4870000108000609C0C00609CE6
+:108E3000001805E461000010001845E4230000104C
+:108E40000D00609C0B00609C001805E405000010FC
+:108E50000000609C0000609CB000000079180AD8F7
+:108E60007900848C001804E4AC00001000000015A8
+:108E700000406018240363A800408018040384A8FD
+:108E80000000C3840000A4840100609CEE300ADC72
+:108E9000FF0085A4001824E40800000CF0280AD87C
+:108EA00000006CA800008AA80EFEFF070000001555
+:108EB0009A00000000000015151E000400006AA8BA
+:108EC000F9FFFF0300006CA8001805E4180000106B
+:108ED0000000C09D0E00609C001805E4DFFFFF0F3E
+:108EE0000000609C0C00648C0000809D006003E426
+:108EF0008A00001000000015C61B0004000064A8D2
+:108F00003C006A8C006003E4070000100000809CB5
+:108F100040006A840100639C08614AD440180AD466
+:108F20000000809C7D00000079200AD80C00648C31
+:108F3000007003E479000010000000153C00648C10
+:108F4000007003E4750000100000A09C000064A8FD
+:108F5000852804D8E22804D8E32804D8D32804D8E4
+:108F6000D42804D8D52804D8DD2804D8DE2804D88D
+:108F7000DF2804D8E02804D8E51D0004E12804D83F
+:108F80000100609C7B008A8C79180AD80200609CE2
+:108F9000001824E4070000100000809C89006A8CFF
+:108FA000007023E403000010000000150100809C05
+:108FB000BCFFFF0386200AD80C00648C0000809C54
+:108FC000002003E455000010000000153C006A8CEE
+:108FD000002003E4510000100000001579006A8CA5
+:108FE000002003E44D0000100100609CE2200AD83C
+:108FF00085180AD800006AA8E3200AD8D3200AD826
+:10900000D4200AD8D5200AD8DD200AD8DE200AD8F4
+:10901000DF200AD8E0200AD81D1C0004E1200AD86D
+:1090200089006A8C0100809C002023E4030000106A
+:109030000000A09C0000A4A89AFFFF0386280AD87D
+:10904000001805E427000010001845E4090000108E
+:109050008100609CE5FF859C0400609C001844E44E
+:109060007EFFFF130000609C2C0000000000001534
+:10907000001805E479FFFF0F0000609C2800848C35
+:109080000000609C001804E4240000100000809C94
+:1090900000006AA885200AD8E2200AD8E3200AD86E
+:1090A000D3200AD8D4200AD8D5200AD8DD200AD85F
+:1090B000DE200AD8DF200AD8E0200AD8C71E000424
+:1090C000E1200AD80100A09C00006CA879280AD8E9
+:1090D00000008AA80000A09C74FFFF0386280AD81D
+:1090E000C71D0004000064A80000A09C0000609C54
+:1090F00079280AD80900000008194AD4741A000413
+:10910000000064A80000A09C0000609C3C280AD8D5
+:1091100084FFFF0308194AD400002185040041851B
+:10912000080081850C00C185004800441000219C86
+:10913000F0FF219C004801D4045001D4086001D400
+:109140000C7001D47B00838C000043A900402019DF
+:109150000C1629A90040601910166BA90040C0190F
+:109160002416CEA90200609C001824E4030000101D
+:109170000000809D0100809D89008A8C0700CCB88A
+:1091800085006A8CFC00AA84052063E0020085B893
+:10919000FFFF63AC0F0063B80050E4E0FFFF809C6A
+:1091A000002025E44800000C0030C3E004006018F3
+:1091B000508363A80000A09CFC048784002803D48B
+:1091C000080084B87C046784001884E0002009D477
+:1091D00000406018141663A800300BD400408018BB
+:1091E000181684A800002985004803D400006B8568
+:1091F00000406018240863A8005804D40000A38429
+:1092000000408018200884A80800A5B80000C48485
+:10921000004060181C1663A80030A5E00100809C87
+:10922000002803D40100609C00180ED40040601890
+:10923000001663A8002003D4F024FF0700000015E7
+:109240000000A09C0000809C00280ED400200CE4AC
+:10925000140000100000001585006A8C002023E433
+:109260001000000C0000001500406018281663A8CC
+:10927000004080182C1684A80000638400008484B9
+:10928000D01E2AD4D4262AD400406018041663A81D
+:109290000000809C002003D40B000000000000159B
+:1092A00000406018281663A8004080182C1684A877
+:1092B0000000638400008484C81E2AD4F3FFFF03E7
+:1092C000CC262AD400002185040041850800818530
+:1092D0000C00C185004800441000219CECFF219C3B
+:1092E000004801D4045001D4086001D40C7001D4AA
+:1092F000108001D4C4050386000043A90000809CAF
+:10930000004060180C0863A8002003D4700D8A8404
+:109310000000609C001824E4D00000100000809C35
+:1093200000406018080463A8002003D4004080199E
+:10933000C8808CA90000C09D00008C84FE0064A43D
+:10934000007003E46400000C0000001504006A8C47
+:109350000000809C002003E4CA0000100100609C13
+:109360001011AA84020065A4002003E41B00001071
+:109370000000609C3C188A840100609C001824E472
+:10938000160000100000609C20186A840000C09C39
+:10939000001886E41100000C0000609C1814AA9CC0
+:1093A00018186A8400808018000084A8003063E0E8
+:1093B000002063E00100C69C0000858C002003D8DB
+:1093C00020188A84002086E4F6FFFF130100A59C84
+:1093D0001011AA840000609C001805E40A00001027
+:1093E0000100609CFC00CA840100809C005066E083
+:1093F0006812A38C002025E43000000C20116A9C28
+:109400000100609C481B0AD40600908C0000609C00
+:10941000001804E423000010FFFF609C08018A8408
+:10942000001804E41A00000C00000015FC00CA84B7
+:109430000000A4A80C210AD4040065B8040086B872
+:1094400008310AD4022863E0023084E0020063B8E5
+:10945000020084B800186AE000208AE0D005639C0E
+:10946000D005849CCC1D0AD4C8250AD40000838C66
+:10947000012003D80100809C0000609C74230AD462
+:10948000581B0AD47E000000F8200AD41C03AA8CC2
+:109490004E2CFF077C056A9CE5FFFF0308018A84C8
+:1094A000FC008A847C056A9C482CFF071C03AA8C5C
+:1094B000F2FFFF030100809C1811AA841506000426
+:1094C000000086A818116A84005863E0CDFFFF03EE
+:1094D00018194AD404006018617D63A82724FF0787
+:1094E0000000001500408018C48084A800700CD4CF
+:1094F0000100609C0000C48404000019B88008A921
+:109500000000A4847F00C6A4781D2AD408018A84A0
+:1095100004006018C48063A85000A5B8002003D4DC
+:109520003C18EA847F00A5A4040080183C8384A82A
+:10953000FC006A84001808D4002804D804006018CD
+:10954000E08263A8007007E406000010003003D832
+:1095500000006884A5FF809C005063E0482243D847
+:1095600010116A84020063A4007003E41600001066
+:109570000100609D005827E4130000100000001552
+:1095800024180A8530186A8438188A84064363E0F0
+:109590002C18AA843418CA847B00EA8C064384E021
+:1095A000002823E10200609C001807E4240000105A
+:1095B000003084E01814AA9C000069A8C3110004BC
+:1095C0000000CBA800406018000063A8FB03809C4B
+:1095D0000040E0181005E7A8002003D41400C018CC
+:1095E0007F43C6A8000067840000809C002023E41D
+:1095F0000C00000C0100609C0000A09C0100849CF9
+:109600000030A4E50700000C0100609C00006784A6
+:10961000002823E4FBFFFF130100849C0100609CF1
+:10962000FF03809C681D2AD400406018000063A8D6
+:10963000002003D447FFFF0304006A8C1814AA9C7F
+:10964000000069A80000C8A8B51100040000EBA83C
+:10965000DDFFFF030000001500406018040363A84D
+:1096600000408018100484A80000A3840100609CBE
+:10967000001804D42EFFFF03000000150100609CB9
+:109680006C1D2AD4000021850400418508008185D5
+:109690000C00C18510000186004800441400219C84
+:1096A000FCFF219C004801D400406018C48063A8DE
+:1096B00000402019200829A90000E3840040001977
+:1096C0002C0C08A90100609D00008384FFFFE7A423
+:1096D0000000C984500084B800006884063384E028
+:1096E0000000A884500063B8FFFFA5A40000C9844F
+:1096F000003884E0063363E0002863E0005863E04C
+:10970000001824E40300000C000000150000609D18
+:1097100000002185004800440400219CECFF219CAE
+:10972000004801D4045001D4086001D40C7001D465
+:10973000108001D400008385000043A90000A09C94
+:1097400000406018040463A8880D8C8C0000C38559
+:10975000002804E4030000100808609CFEFFCE9D72
+:10976000E01DFF070100809C00006A8400180CE4E3
+:109770000300001000000015000083A90000609C99
+:109780006632FF07781D2CD46B32FF0700004BA90F
+:109790000058AAE00000609C02284EE100188AE50B
+:1097A00047000010027085E00400609C0018AAE5E4
+:1097B0003F0000100000001504116C84002863E0D5
+:1097C00004194CD4C6FEFF0700006CA8780D8C84E9
+:1097D0000000609C001824E40D0000100000409D73
+:1097E0001400001A7F4310AA0000C09D0080AAE563
+:1097F0000700000C00000015AAFFFF0701004A9DAA
+:1098000000700BE4FAFFFF13000000150040C018C1
+:109810001005C6A80000409D000066841400A01832
+:109820007F43A5A8005023E40A00000C0000809CA0
+:1098300001004A9D0028AAE50600000C0000001562
+:1098400000006684002023E4FBFFFF1301004A9D13
+:10985000C40E8C840000609C001804E41F000010FB
+:109860000000409D0040C018380CC6A80000668467
+:109870001400A0187F43A5A8005023E41600000C94
+:109880000000809C01004A9D0028AAE51300000CFE
+:109890000000609C00006684002023E4FAFFFF13B0
+:1098A0000000609C0E000000781D2CD404116C8414
+:1098B000005085E0C3FFFF03002063E00400609CCC
+:1098C0000018A4E5BDFFFF0F00000015F9FFFF031E
+:1098D00004116C840000609C781D2CD4000021854C
+:1098E00004004185080081850C00C18510000186B7
+:1098F000004800441400219C00408018000484A803
+:109900000C14A3840000C484580066B8430085B8D2
+:109910000700E3A40700A5A400406018040463A89E
+:10992000010084B8000003850038A5E00700609CB2
+:109930000018A5E408000010000000150318A5E0B9
+:109940000200849C1F006018FFFF63A80300000052
+:109950000318C6E00238A5E0180065B80100609D54
+:10996000041864E00040A0180804A5A80018C6E088
+:1099700000408018000484A800406018040463A814
+:10998000003004D4004003D40000609C001805D4CB
+:10999000005805D40048004400000015E4FF219C55
+:1099A000004801D4045001D4086001D40C7001D4E3
+:1099B000108001D4149001D418A001D4000084A90F
+:1099C000FF00C3A5081484840000009E008004E406
+:1099D0006D0000100000809E0040001A000410AAD4
+:1099E000900DAC8400006EA80D2CFF070100809C38
+:1099F000700DAC8400004BA90000809C002025E481
+:109A00005D00000C00006EA804006018D08163A8FF
+:109A10000C00809C0000A09C002003D4702D2CD44E
+:109A2000000070841F00A018FFFFA5A8000090840C
+:109A3000032863E0580084B80200C3B80000609CAB
+:109A400000182AE44900000C0700A4A40C146C843C
+:109A5000003063E008148C84002863E0002083E475
+:109A6000E0FFFF1300000015A4FFFF0700006CA833
+:109A70000000409E009034E43800000C0000001507
+:109A8000880DAC8C009025E4050000100000001546
+:109A900000406018000363A800008384009005E480
+:109AA0000300001000006EA8FEFF949ED0FCFF078C
+:109AB00000008CA89931FF07000000159E31FF07B8
+:109AC00000004BA900580AE2028054E100908AE5A8
+:109AD0001C00001002A090E00400609C0018AAE5A1
+:109AE000140000100000001504116C84008063E075
+:109AF00004194CD404006018697D63A89F22FF07F5
+:109B000004118C840C006C8C0100609D005803E4EF
+:109B1000330000100000001528006C8C005803E48E
+:109B20002F000010000000152D0000000000609DB7
+:109B300004116C84005090E0EEFFFF03002063E00E
+:109B40000400609C0018A4E5E8FFFF0F000000156A
+:109B5000F9FFFF0304116C84482CFF070000001577
+:109B60001F0000000000609D7B00609CEFFFFF0372
+:109B7000741D2CD4DB2BFF07900D8C84A9FFFF03F1
+:109B800000008BAA900DAC840000609CA42BFF0702
+:109B90000100809C00802BE4F5FFFF0F7B00609CA0
+:109BA000700D6C84008023E40800000C0C00809C85
+:109BB00004006018D08163A80000A09C002003D49A
+:109BC000ACFFFF03702D2CD4900D8C84C52BFF07A8
+:109BD00000006EA8A7FFFF0300008BAA00002185EC
+:109BE00004004185080081850C00C18510000186B4
+:109BF0001400418618008186004800441C00219C06
+:109C0000E8FF219C004801D4045001D4086001D42D
+:109C10000C7001D4108001D4149001D4000084A9E8
+:109C2000FF00C3A5081484840000409D005004E494
+:109C30005D0000100000409E0040001A000410AAC1
+:109C4000900DAC8400006EA8752BFF070100809C6E
+:109C5000700DAC8400004BA90000809C002025E41E
+:109C60004D00000C00006EA804006018D08163A8AD
+:109C70000C00809C0000A09C002003D4702D2CD4EC
+:109C8000000070841F00A018FFFFA5A800009084AA
+:109C9000032863E0580084B80200C3B80000609C49
+:109CA00000182AE43900000C0700A4A40C146C84EA
+:109CB000003063E008148C84002863E0002083E413
+:109CC000E0FFFF13000000150CFFFF0700006CA869
+:109CD0000000009E008032E40600001000006EA824
+:109CE000E62BFF0700000015450000000000609D06
+:109CF00000408018000384A80000A4843CFCFF07F7
+:109D000000008CA80531FF07000000150A31FF078D
+:109D100000004BA900584AE10250B2E0008085E5FE
+:109D20001400001002908AE00400609C0018A5E571
+:109D30000C0000100000001504116C84005063E05A
+:109D400004194CD40100609D3C006C8C005823E445
+:109D5000E6FFFF13000000152900000000000015B9
+:109D600004116C8400288AE0F6FFFF03002063E002
+:109D70000400609C0018A4E5F0FFFF0F0000001530
+:109D8000F9FFFF0304116C847B00609CD7FFFF0385
+:109D9000741D2CD4532BFF07900D8C84B9FFFF0347
+:109DA00000004BAA900DAC840000609C1C2BFF07A8
+:109DB0000100809C00502BE4F5FFFF0F7B00609CAE
+:109DC000700D6C84005023E40800000C0C00809C93
+:109DD00004006018D08163A80000A09C002003D478
+:109DE000BCFFFF03702D2CD4900D8C843D2BFF07FE
+:109DF00000006EA8B7FFFF0300004BAA00002185FA
+:109E000004004185080081850C00C1851000018691
+:109E100014004186004800441800219CC0FF219C8A
+:109E2000084801D40C5001D4106001D4147001D43E
+:109E3000188001D41C9001D420A001D424B001D4F6
+:109E400028C001D400008485FF0003A608146C8498
+:109E50000000409E009003E41E0300100000C4AA0E
+:109E60000040C0190004CEA9900DAC84000070A879
+:109E70000400001BD08118ABE92AFF070100809C79
+:109E8000700DAC8400004BA90000809C002025E4EC
+:109E90000C03000C000070A80C00609C0000809C6B
+:109EA000001818D470252CD400006E841F00A01850
+:109EB000FFFFA5A800008E84032863E0580084B843
+:109EC0000200C3B80000609C00182AE4FA02000CEB
+:109ED0000700A4A40C146C84003063E008148C8484
+:109EE000002863E0002083E4E0FFFF13000000157A
+:109EF0000400001BD08118AB80FEFF0700006CA897
+:109F0000000098848100609C001804E405000010A3
+:109F10000000609C001832E42B00000C0000609DE3
+:109F2000880DAC8C0000609C002823E40F0000101A
+:109F30000000409D000098840D00609C001824E4FF
+:109F4000060000100100609C8A0D8C8C001824E42F
+:109F50000600000C0000001500406018000363A814
+:109F6000000083840000409D00280AE403000010E4
+:109F7000000070A8FEFF529E9DFBFF0700008CA80A
+:109F80000C006C8C005023E406000010000000154B
+:109F900028006C8C005023E40B00000C0000609D36
+:109FA0003C006C8C0000809C002023E40B0000101F
+:109FB0000000001528006C8C002023E4070000102E
+:109FC0000000609D00406018080463A8005803D496
+:109FD000D80200000000001579006C8C0000809E03
+:109FE00000A003E4990200100400C09D7C006C8C6A
+:109FF000007023E47402000C000000150000988437
+:10A000000200C09DF5FF649C007043E40300001053
+:10A010000000A09C0100A09C8100409D005024E411
+:10A02000030000100000609C0100609C041865E0C3
+:10A0300000A003E4BF0200100000609D0040601813
+:10A04000080463A80000838400A004E40400000C5A
+:10A05000000070A8B70200000000609D3EF9FF07F5
+:10A0600000008CA8000098840D00609C001824E477
+:10A07000030000100000A09C0100A09C005024E4FC
+:10A08000030000100000609C0100609C041865E063
+:10A0900000A003E41D0000100100809C08116C84E6
+:10A0A000002023E427020010000000157C006C8CC7
+:10A0B000007023E418020010002023E40801AC849F
+:10A0C000FFFF609C001825E411020010000000153D
+:10A0D0000C018C84001824E4F90100100000001524
+:10A0E000FC008C84040064B808210CD40C210CD42E
+:10A0F000022063E0020063B800186CE0D005639CA6
+:10A10000CC1D0CD4C81D0CD4740D6C847D00609DD6
+:10A11000005823E48702000C00000015FFFF609D3B
+:10A12000005823E48302000C8100609C0000B88486
+:10A13000001825E4030000100000C09C0100C09C32
+:10A140000D00609C001825E4030000100000809CB6
+:10A150000100809C042086E00000609C001824E43C
+:10A16000080000100C00609C001805E405000010B9
+:10A170000B00609C001805E4B600000C0000001500
+:10A18000FC00CC840000609D0000009E020066B8C8
+:10A19000006083E0C00DA4848011C48500582EE4C3
+:10A1A000030000100B0085BA10814CD40000988485
+:10A1B0000D00609C001824E4030000100000E09CE7
+:10A1C0000100E09C8100609C001824E40300001062
+:10A1D0000000A09C0100A09C042867E0005803E454
+:10A1E00006000010006066E00000809C0000A09C5B
+:10A1F00018214CD4682A43D81011AC84400065A4BF
+:10A20000005803E429000010040065A468116C8460
+:10A21000005803E425000010040065A400009884A1
+:10A220000B00609C001804E420000010040065A4EA
+:10A2300018118C8420114C9E7C116C840020CEE17E
+:10A24000ECFF439D0000AAA80000F0A800006EA843
+:10A250008931FF07000092A80000A09C02584AE143
+:10A2600000280BE40A000010005810E2FC00CC8427
+:10A270000058CEE118116C84006086E0005863E05D
+:10A280000100C09C18194CD4683244D800282BE433
+:10A290000400000C00000015EBFFFF03FC00CC8461
+:10A2A0001011AC84040065A40000409D005003E43C
+:10A2B000100000100D00609C00009884001824E439
+:10A2C000030000100000E09C0100E09C8100609C05
+:10A2D000001824E4030000100000C09C0100C09C92
+:10A2E000043067E0005003E46101000C20118C9CF5
+:10A2F000000098840D00609C001824E40300001006
+:10A300000000C09C0100C09C8100E09C003824E457
+:10A31000030000100000609C0100609C041866E0CF
+:10A320000000C09C003003E422000010010065A47E
+:10A33000003003E44C010010003824E43A0100101E
+:10A340000000001538006C8434008C840F00639C7E
+:10A350000F00849C440023B9440084B8FC00CC84E2
+:10A360002011AC9CC40EEC9C00A001D418116C848C
+:10A37000041801D4000069A8F9010004C00E0C9D66
+:10A380000000609C00180BE425010010000000157F
+:10A39000FC006C840100A09C18118C84006063E0B8
+:10A3A000682A43D8005884E01011AC8418214CD49A
+:10A3B000020085A40000609C001804E42500001041
+:10A3C0000100609C04008C8C001824E42100001023
+:10A3D0008100609C00009884001824E400010010B3
+:10A3E0000000C09D38006C8434008C840F00639C96
+:10A3F0000F00849C4400C3B8440084B8062366E080
+:10A4000024306CD428206CD47C11AC841811EC84DA
+:10A410000238A5E00700639C4300C3B8FF3F601803
+:10A42000FCFF63A81700869C0318C4E10028AEE473
+:10A43000B60000100100809CFC006C840000809C31
+:10A4400098FFA09C006063E03C206CD4482A43D86D
+:10A45000000098840B00609C001804E4A700000C26
+:10A46000000000157A006C8C0000A09C002823E4FA
+:10A47000970000100000001500406018280B63A82A
+:10A4800000008384002824E42C0000100000001544
+:10A49000FC006C84020063B8006083E0FC04C484A8
+:10A4A0007C0464843F00809C0020A3E47F000010B3
+:10A4B00000000015020063B800408018000684A860
+:10A4C0000040A0180C05A5A8002063E000008384CC
+:10A4D000000065840B0084B80040A0182C0BA5A8D0
+:10A4E000002063E0001805D43F00609C0018A6E43B
+:10A4F00068000010020066B80040A0180C05A5A86E
+:10A500000040C0180006C6A8003063E00000838445
+:10A51000000065840B0084B80040A018300BA5A88B
+:10A52000002063E0001805D400406018280B63A8E1
+:10A530000100A09C002803D4000078842A1C000499
+:10A5400000008CA80000C09C7B008C8C0200609CEA
+:10A550006C352CD4001824E44500001068352CD448
+:10A5600086008C8C0000609C001824E43A000010E7
+:10A5700000000015FC00CC84020066B824118C8415
+:10A58000006063E0E02623D4880D8C8C0000609C82
+:10A59000001804E42B000010020066B8020086B820
+:10A5A000E00F649C006084E000186CE0E0108C8593
+:10A5B000006003D4606044D400408018080884A878
+:10A5C0000100C09C000076A8003004D454FCFF07B2
+:10A5D0000000001504006018BC8063A800408018CB
+:10A5E0002C2084A80000A3840000609C001804D4E0
+:10A5F000001805E44F0100100100609D0040601844
+:10A60000C08063A800408018240884A80000A384A8
+:10A61000000064845000A5B8FFFF639C001825E487
+:10A620000400000C00000015420100000100609DC4
+:10A63000C0FAFF07000076843E0100000100609D23
+:10A640008700AC8C006083E0602844D4DBFFFF030C
+:10A65000E02F24D4FC00CC84020066B82411AC8422
+:10A66000006063E0C9FFFF03602F23D4FC00CC84AB
+:10A67000020086B82411AC84E00E649C006084E083
+:10A6800000186CE0602F24D4C0FFFF03002803D41F
+:10A6900000408018000684A80040A0180805A5A85E
+:10A6A0009BFFFF03002063E0020063B80040A01896
+:10A6B0000006A5A8002863E0000083840040A018DD
+:10A6C0000805A5A883FFFF0300000015040060181B
+:10A6D0008D7D63A8A91FFF070000809C6729FF07E5
+:10A6E000000000150000809C0100A09C68252CD46F
+:10A6F000CEFFFF036C2D2CD4AAF6FF0700006CA838
+:10A700005AFFFF037A006C8CFC006C8420114C9D76
+:10A71000020063B83C206CD40000A09C005063E0B1
+:10A7200060008384007085E40900000C003804E2B6
+:10A7300018146C9C0000809C0100A59C002003D88C
+:10A74000007085E4FDFFFF130100639CF800AA84FC
+:10A75000FC006A8400018A846C290AD470190AD426
+:10A7600074210AD478310AD468710AD42C00819CEF
+:10A7700020306CD4000070A86801AA842C2801D471
+:10A780006C01CA84303001D47001AA84342801D409
+:10A790007401CA84383001D47801AA84AA2EFF0734
+:10A7A0003C2801D4FC006C840000C09C1400B09CC8
+:10A7B000005063E0283103D80100C09C18116C845C
+:10A7C000FC008C84007063E0006084E018194CD4B5
+:10A7D000683244D81FFFFF0318286CD4840D6C84A2
+:10A7E000800D8C840F00639C0F00849C4400C3B8D0
+:10A7F0007B00AC8C0200609C001825E400FFFF1376
+:10A80000440084B8010064A4007003E4FDFEFF135B
+:10A81000062366E0FAFEFF030100849CE5FEFF03C9
+:10A820001011AC84840D6C84800D8C840F00639CAB
+:10A830000F00849C440023B97B00AC8C0200609C18
+:10A84000001825E4C6FEFF13440084B8010064A488
+:10A85000003003E4C2FEFF1300000015C0FEFF033A
+:10A860000100849CD3FEFF03C4362CD4FC00AC84CE
+:10A8700000006CA81811EC84470100040000D4A863
+:10A8800000500BE40B00001000000015FC006C846D
+:10A890000100A09C18118C84006063E0682A43D8F2
+:10A8A000005884E01011AC8492FEFF0318214CD4B0
+:10A8B00090FEFF031011AC84FFFF609C001825E49C
+:10A8C0000A000010001824E40C01AC84040064B8F1
+:10A8D00008290CD4022063E0020063B800186CE081
+:10A8E00009FEFF03D005639C08FEFF13040065B852
+:10A8F0000C290CD4022863E0020063B800186CE055
+:10A90000D005639C01FEFF03CC1D0CD4EBFFFF03BD
+:10A910000C018C84FDFDFF130000001508018C84E0
+:10A92000FFFF609C001824E4F8FDFF1300000015F1
+:10A93000FC008C84040064B8E7FFFF0308210CD4FA
+:10A940007C006C8C007023E40C000010002023E4D9
+:10A950000C018C84FFFF609C001824E4EBFDFF13C6
+:10A960000000001508018C84040064B80C210CD48C
+:10A97000E2FFFF03022063E0E4FDFF130000001587
+:10A980007B006C8C007003E409000010FFFF609CEA
+:10A9900008018C84001824E4DCFDFF13AB00C09C8C
+:10A9A00074352CD463000000000066A985006C8C0F
+:10A9B00000A023E4D5FDFF1300000015D9FFFF031D
+:10A9C00008018C8404006018957D63A8EB1EFF07C6
+:10A9D0000000809C95F5FF0700006CA8CF2DFF07B5
+:10A9E00000000015D42DFF0700004BA900584AE1D4
+:10A9F000025092E000A084E50F00001002906AE08F
+:10AA00000070A4E5080000100000001504116C841B
+:10AA1000005063E00100A09C04194CD403FFFF0325
+:10AA2000742B0CD404116C8400208AE0FAFFFF031D
+:10AA3000002063E00070A3E5F5FFFF0F00000015A4
+:10AA4000FAFFFF0304116C84B42DFF07000000150A
+:10AA5000B92DFF0700004BA90058AAE0022852E1D7
+:10AA600000A08AE50E000010029085E00400609CC2
+:10AA70000018AAE5060000100000001504116C84FF
+:10AA8000002863E074FDFF0304194CD404116C84A6
+:10AA9000005085E0FCFFFF03002063E00400609CA1
+:10AAA0000018A4E5F6FFFF0F00000015F9FFFF03F3
+:10AAB00004116C847B00C09C67FDFF0374352CD4AB
+:10AAC0000828FF07900D8C84F8FCFF0300004BAAB8
+:10AAD000900DAC84000070A8D127FF070100809C76
+:10AAE00000902BE4F5FFFF0F7B00C09C700D6C8481
+:10AAF000009023E40800000C0C00609C0400001B84
+:10AB0000D08118AB0000809C001818D4FDFCFF0316
+:10AB100070252CD4900D8C840400001BD08118ABC0
+:10AB2000F027FF07000070A8F6FCFF0300004BAA07
+:10AB3000080021850C004185100081851400C18525
+:10AB4000180001861C004186200081862400C186F1
+:10AB500028000187004800444000219CC8FF219C38
+:10AB6000004801D4045001D4086001D40C7001D411
+:10AB7000108001D4149001D418A001D41CB001D4C9
+:10AB800020C001D43F00239D1F00849C9F0049B931
+:10AB90009F0064B83C0081855A004AB95B0063B8E5
+:10ABA0000000C5A9005029E1001884E0860029B9F9
+:10ABB000E0FF609C000046AA031884E00000C7AADA
+:10ABC0002000849C000008AB062329E104006018E3
+:10ABD0009A7D63A8060009BA000090A8671EFF07C7
+:10ABE0001800909E020092B85C00AE841400D49CC1
+:10ABF0000070E4E004006018AC7D63A8007012E10E
+:10AC00000260A5E00028A6E40B000010000086A862
+:10AC100097FF609C281908D804006018BB7D63A8C2
+:10AC2000561EFF07000000150000609D2E0000006A
+:10AC3000005816D46000478500008AA800604AE1E9
+:10AC40004E1EFF0738008185EC008E8402608AE189
+:10AC50006C210ED4F0006E84F4008E8470190ED432
+:10AC600074210ED404006018CB7D63A800008AA86C
+:10AC700078810ED4411EFF0768A10ED400008CA875
+:10AC800004006018D77D63A83C1EFF0714008C9D4C
+:10AC900068016E8443008CB9241801D46C018E8441
+:10ACA000282001D470016E842C1801D474018E8484
+:10ACB000302001D478016E842400819C341801D4A2
+:10ACC000612DFF0700006AA8007072E00000809C00
+:10ACD000282103D80100609C006018D4001816D405
+:10ACE00068016E850000218504004185080081858A
+:10ACF0000C00C18510000186140041861800818671
+:10AD00001C00C18620000187004800443800219CB7
+:10AD1000E8FF219C004801D4E800C384020084B805
+:10AD2000103001D4001884E06000C4841400809CBA
+:10AD30000028C6E0682103D4E00083846C2103D49A
+:10AD4000E4008384702103D4E8008384742103D455
+:10AD50000000809C782103D41400809C042001D43E
+:10AD6000E0008384082001D4E40063840400819C13
+:10AD70000C1801D40000609C141801D4322DFF0778
+:10AD8000000066A81400609D000021850048004472
+:10AD90001800219CD0FF219C004801D4045001D40C
+:10ADA000086001D40C7001D4108001D4149001D437
+:10ADB00018A001D4000084A9B000C09D000083AA9F
+:10ADC000000005AA000047AA04006018ED7D63A8F2
+:10ADD000EA1DFF0700008EA8020090B85C00AC845A
+:10ADE00004006018007E63A80060C4E00060F0E02A
+:10ADF0000290A5E00028AEE40A00001000008EA832
+:10AE000099FF609C281907D804006018107E63A879
+:10AE1000DA1DFF0700000015240000000000609DFF
+:10AE200004018C846C210CD46000468508018C845C
+:10AE300000904AE170210CD468710CD40C018C8410
+:10AE400074210CD49800809C78210CD4CB1DFF0772
+:10AE500000008AA868016C841C1801D46C018C84E1
+:10AE6000202001D470016C84241801D474018C84D6
+:10AE7000282001D478016C841C00819C2C1801D4FA
+:10AE800000006AA8F02CFF0714004A9D000094A857
+:10AE90000F00000400006AA8006070E00000809CC1
+:10AEA00068016C85282103D80000218504004185B4
+:10AEB000080081850C00C1851000018614004186C0
+:10AEC00018008186004800443000219C54FF219CDA
+:10AED000004801D4045001D4086001D40C7001D49E
+:10AEE000108001D4000063AA000084A97500648C5E
+:10AEF0007600848C070063B87700AC8C040084B8BB
+:10AF00000300A5B8042063E07800CC8C042863E03B
+:10AF1000043063E0C2004C8DF4008C8C8800AC8C53
+:10AF20008900CC8C8A00EC8C1C000C8DC1002C8D0F
+:10AF30001D006C8D141801D4185001D41C2001D4AC
+:10AF4000202801D4243001D4283801D42C4001D445
+:10AF50000000609C00180BE425010010304801D46B
+:10AF60001E006C9420008C94341801D4382001D435
+:10AF7000880D8C8C0000609C001824E413010010E4
+:10AF80000000809C4C1801D4501801D41400CC94BB
+:10AF900016006C9470008C947200AC943C3001D418
+:10AFA000401801D4442001D4482801D422008C8CBC
+:10AFB0000000609C001804E4000100100000009DE7
+:10AFC00023008C8C0F00609C001824E4F700001014
+:10AFD000542001D424006C8C25008C8C581801D48A
+:10AFE0005C2001D40000C09C0300809C9C00619CFC
+:10AFF0000000209D0100C69CD04FE3D7E04FE3D76F
+:10B00000F04FE3D7004803D40020A6E5FAFFFF1372
+:10B010000400639C46006C8C8C008C8C601801D4FE
+:10B020000000609C001804E4DD000010642001D4DE
+:10B030008B002C8D0000C09C004886E51300000C9E
+:10B04000684801D49C00A19CA0000C9DB800EC9C19
+:10B05000F0FF68850100C69CD05FE5D7F8FF8794B4
+:10B060000000A885000067940400089DE06FE5D704
+:10B07000F027E5D7001805D40200E79C004886E5D4
+:10B08000F4FFFF130400A59C00808018000084A832
+:10B090001400A184002073E04000339E002803D4F4
+:10B0A000002011E20080C0180400C6A81800E18446
+:10B0B000003073E00400319E003803D40020F1E139
+:10B0C00000800019080008A90400319E004073E0C8
+:10B0D0001C002185002011E1008060190C006BA983
+:10B0E000004803D40400319E2000A185005873E07D
+:10B0F0000020D1E1006803D40080A0180000A5A8BA
+:10B100000400319E1000849C2400C1840028B1E119
+:10B11000002073E00400319E003003D40080E0186A
+:10B120001400E7A828002185003873E0002891E189
+:10B13000004803D40400319E0C006B9D2C008184D8
+:10B140000028F1E0005873E01C00A59C002003D407
+:10B150003000C184002893E000802019200029A934
+:10B16000003004D40400319E00808018000084A8C0
+:10B17000004873E03400A184002071E10080C01811
+:10B180002400C6A838002185003093E00400319ED9
+:10B19000002803D40080C0180000C6A8004804D4CA
+:10B1A0000030B1E000808018280084A83C00218590
+:10B1B000002073E00400319E004803D44000C184A5
+:10B1C000008060182C0063A800802019300029A995
+:10B1D000001893E0003004D4004873E04400C184B8
+:10B1E00000808018000084A80400299D003003D44A
+:10B1F000002051E148006184004893E00400319E42
+:10B20000001804D400802019000029A900808018AB
+:10B21000380084A80048D1E0002073E03C00299D5C
+:10B220004C0081840400319E002003D450006184CE
+:10B23000004893E0001804D4540061840080801812
+:10B24000000084A8001810D4002031E15800818447
+:10B250000400319E00200FD400808018000084A8D4
+:10B26000002071E05C0081840400319E002008D43D
+:10B270006000018500808018000084A800400ED482
+:10B28000002011E1640081840400319E00200DD46F
+:10B290006800A18500680CD40080A0190000ADA949
+:10B2A000006891E06C00A1850400319E006807D41D
+:10B2B0007C00E1848C00A18500380BD4006805D4A3
+:10B2C0000080601900006BA99C00A1840058F1E087
+:10B2D00000280AD40400319E8000A1850058B1E006
+:10B2E000700061850400319E005806D4006809D4BE
+:10B2F0009000618500802019000029A9A000A18587
+:10B300000048D1E0005803D40400319E006808D4FE
+:10B31000004871E0740001850080601900006BA98D
+:10B320000400319E84002185004004D49400A1854E
+:10B33000005891E0004807D40400319E006805D40D
+:10B34000A400A184002806D47800C1840058B1E08C
+:10B350008800E1840400319E003003D49800018508
+:10B36000005871E0003804D4A8002185070093A498
+:10B370000400319E004005D4004803D40000609CC6
+:10B38000001804E41D000010005871E00000609DEA
+:10B39000005803D419000000000000158B006C8CCD
+:10B3A0003AFFFF03681801D40000E09C583801D42C
+:10B3B0000DFFFF035C3801D4544001D4584001D440
+:10B3C00009FFFF035C4001D43C2001D4402001D49C
+:10B3D000442001D4482001D43800AC844C2801D446
+:10B3E0003400CC84F2FEFF03503001D4341801D471
+:10B3F000E0FEFF03381801D40000218504004185D8
+:10B40000080081850C00C1851000018600480044B9
+:10B41000AC00219CFCFF219C004801D478030385EB
+:10B420000000E3A8FFFF809C040068B8024063E0CE
+:10B43000020063B8001867E0002008E44D00001027
+:10B44000D005239DE410A7840200609C001805E449
+:10B450003E000010020068B80300898C0400609C64
+:10B46000001824E439000010020068B8020065B832
+:10B47000F010839C002087E0E810639C0000A48407
+:10B48000001867E0342947D4000084840000A384B6
+:10B49000302147D42C2947D4282947D40700898C48
+:10B4A0000300609C001804E40300000C0000001579
+:10B4B0000200809C0800698C080063B80100A09C11
+:10B4C000042063E09C1A47D47A00678C002823E4A8
+:10B4D0001C0000100200609CE4108784001824E423
+:10B4E000140000100000609C0000A09CE42847D4D9
+:10B4F000101187840000609C001804E42B000010E9
+:10B50000FFFF609C001808E4070000100000A09CEA
+:10B51000003888E0604147D46812648C2300000042
+:10B520005C1947D4604147D4200000005C2947D40F
+:10B53000001824E40300001000000015000065A8B6
+:10B54000ECFFFF03E41847D40038C3E0E00E868424
+:10B55000600FA684E00F66846010C684282147D45B
+:10B560002C2947D4301947D4CDFFFF03343147D4B9
+:10B570000000609C0D00A78C301947D4341947D4C3
+:10B580002C2147D40300609C001805E4050000103E
+:10B59000282147D4000085A8C8FFFF030E00678C50
+:10B5A000FEFFFF030200809C00002185004800444C
+:10B5B0000400219C0801C3840C01E384040086B8C4
+:10B5C0000400A7B8023084E00238A5E0020084B885
+:10B5D0000200A5B8002083E00028A3E0D005849CE9
+:10B5E000D005A59CC82503D4CC2D03D40048004425
+:10B5F00000000015ECFF219C004801D4045001D448
+:10B60000086001D40C7001D4108001D4FF0083A520
+:10B61000000044A90000C6A9FF29FF07000005AAF1
+:10B62000101EFF0700000015AB00609C00182EE400
+:10B63000110000100800A09C0000809C00406018D1
+:10B64000102063A8002003D40400639C002003D4CE
+:10B650007B008A8C0000609C001804E40300000C4E
+:10B66000000000150000A09C004060181C2063A88A
+:10B67000002803D406006CB80040A0184020A5A8FC
+:10B6800000408018002084A8002863E00800AA84F5
+:10B69000002804D4FFFF80A8002003D47725FF07EB
+:10B6A000000000155CFFFF0700006AA81C116A84F7
+:10B6B0000420FF0720118A9CF31DFF0700000015DE
+:10B6C000000070A800008CA80000AEA80000C09C7C
+:10B6D000D51DFF070000E09C000021850400418586
+:10B6E000080081850C00C1851000018600480044D7
+:10B6F0001400219CE8FF219C004801D4045001D48F
+:10B70000086001D40C7001D4108001D4149001D4CD
+:10B71000FF0003A6000084A9000070A8A0F8FF079E
+:10B720000000409E880D6C8C009003E49100001096
+:10B730000000CBA938006C8434008C846A2AFF078F
+:10B7400000000015880DAC8C0000609C002803E40C
+:10B750000B000010A05A4CD438008C848007609CE9
+:10B76000001844E4150000103804609C34008C84F8
+:10B77000001844E4110000100000609C002823E43D
+:10B78000100000108007809C14006C94010063B8C6
+:10B790000200639C002043E5080000103804809CF0
+:10B7A00016006C94010063B80200639C002043E51E
+:10B7B0000400000C0000609C1C00409E0000609C87
+:10B7C000002823E46700000C000070A80D008C8C9A
+:10B7D0000300609C001804E40300000C0000001546
+:10B7E0000200809C0E006C8C0000409D080063B835
+:10B7F000042063E000502EE4030000109C1A4CD497
+:10B800003400409E0000609C0000A09C0100809CD1
+:10B8100000202EE403000010141C4CD40000A4A847
+:10B82000005032E4030000100000609C000064A897
+:10B83000031865E0005003E444000010000070A805
+:10B840007529FF0700000015861DFF070000001581
+:10B85000840D8C8400406018082063A8002003D465
+:10B86000800DAC8400408018042084A8002804D4F3
+:10B8700019006C8C005003E4320000100000001529
+:10B880000800809C004060181C2063A80040E0185D
+:10B890000C20E7A8002003D40400A09C0400609CB6
+:10B8A00008008C84000043A9FC04CC9C001807D439
+:10B8B00000406018002063A8002003D41C2B0CD883
+:10B8C0007C036C9CFC038C9C005007D47C04AC9CD7
+:10B8D0006A25FF072000E09C0411AC84004080181A
+:10B8E000182084A8060070B8002804D42800849C7E
+:10B8F000FFFFA0A8002063E0002803D4DF24FF0797
+:10B9000000000015C4FEFF0700006CA81C116C8429
+:10B910006C1FFF0720118C9C5B1DFF0700000015AA
+:10B9200000006AA8000090A80000B2A80000C09C17
+:10B930003D1DFF070000E09C1500000000006EA9FF
+:10B94000D1FFFF030000809C00008CA80000D2A85B
+:10B9500029FFFF072000A09C0D00000000006EA939
+:10B96000A8F8FF0700008CA899FFFF030000CBA9EF
+:10B9700014006C9416008C94010063B8010084B824
+:10B980000200639C6EFFFF030200849C000021857F
+:10B9900004004185080081850C00C18510000186E6
+:10B9A00014004186004800441800219CE8FF219CB7
+:10B9B000004801D4045001D4086001D40C7001D4B3
+:10B9C000108001D4FF0003A6000064A90000609C61
+:10B9D000700D84840000409D0000C09D741B0BD43A
+:10B9E000005024E405000010145801D40000809C8D
+:10B9F00079200BD8140061850000C09C74036B840F
+:10BA0000005023E44A00001070352BD4940D6B8451
+:10BA1000005023E4460000100000001500116B8464
+:10BA2000005023E442000010000070A80000809D38
+:10BA3000FBF8FF071400819C0000609C00182BE4B9
+:10BA4000E601001000004BA9140061850100609C14
+:10BA500008118B84001824E4160000107D00609CFF
+:10BA600004006018D08163A80F00809C0000A384AC
+:10BA7000002005E40F0000107D00609C0E00609C1B
+:10BA8000001805E40B0000107D00609C1F00609C06
+:10BA9000001805E4070000107D00609C1E00609CFB
+:10BAA000001805E42200000C000000157D00609CD9
+:10BAB00000182AE4C701000C7B00809C740D6B8485
+:10BAC000002023E4C101000C000000153000849C1C
+:10BAD000002023E4BD01000C00000015FFFF809C46
+:10BAE000002023E4B901000C0000001574036B84EE
+:10BAF000006023E40E00001000000015940D6B841C
+:10BB0000006023E40A00001000000015700D6B8433
+:10BB1000006023E4060000100000001500116B8493
+:10BB2000006023E4C3FFFF0F000070A80040A018CE
+:10BB3000280BA5A80000809C00006584002003E479
+:10BB40000300001000000015002005D4DC0E6B84FB
+:10BB5000002023E40800001000000015940D6B8401
+:10BB6000002003E4050000100000809C0000609CA1
+:10BB700004194BD40000809C00202AE40B00001024
+:10BB80000000409D940D6B84002023E4070000100A
+:10BB90000000001500116B84002023E40600000C57
+:10BBA0000000609C0000409D00502EE40E00000C40
+:10BBB0000000609C00180EE40300000C00008BA83D
+:10BBC000A500C09D000070A80000CEA82000A09C89
+:10BBD00089FEFF070000409D14006185810100007F
+:10BBE00074552BD48C28FF07000000159D1CFF07FF
+:10BBF000000000151400618504006B8C005023E4E4
+:10BC0000060000100000ABA800116B84005023E474
+:10BC10005701000C0000809CE6F0FF0700006BA8B5
+:10BC200014006185FFFF609C78038B84001804E496
+:10BC30004D01001000002BA900116B84005003E49B
+:10BC40000E01001000000015940DAB84005025E497
+:10BC50000A010010000000150000809C00406018E0
+:10BC6000102063A80000C09C002003D4004080186E
+:10BC7000142084A8003004D4005005E40300001010
+:10BC80000000809C0300809C7B00698C0000A09CCD
+:10BC9000002803E40300001000000015080084A839
+:10BCA000004060181C2063A80000C09C002003D442
+:10BCB00000408018082084A80000609C001804D46C
+:10BCC00000406018042063A800118984003003D468
+:10BCD000002804E40F00001000000015940D698492
+:10BCE000002823E40B0000100200609C001824E4EC
+:10BCF000D90000100300609C004080181C2084A81C
+:10BD0000043149D400006484100063A8001804D4EE
+:10BD1000001169840000809C002003E4C30000102F
+:10BD200000000015940D6984002003E4BF0000109A
+:10BD3000FFFF809C0000609C0100C09C0C2109D486
+:10BD4000003009D4001949D4941D29D4082109D4FC
+:10BD5000FC006B8400408018182084A80040A018C4
+:10BD60002420A5A80411CB84020063B8003004D4B9
+:10BD7000940DEB84C00D839C0040C0182820C6A8F9
+:10BD8000400E639C00208BE000186BE00000848470
+:10BD900000006384002005D4001806D400408018F9
+:10BDA0000C0584A800006484000085844B0063B8FF
+:10BDB000001884E000406018080563A8002005D43E
+:10BDC00000008384000066844B0084B8002063E098
+:10BDD0000000809C001806D4002007E40300001037
+:10BDE0000100809C0300809C7B006B8C0000A09C69
+:10BDF000002803E40300001000000015080084A8D8
+:10BE0000004060182C2063A8002003D47A008B8C9B
+:10BE1000002824E4040000100000809C7C006B8C4F
+:10BE20000100839C00406018202063A8002003D4F8
+:10BE300004008018BC8084A8000064840000809CFA
+:10BE4000002003E426000010000000157A006B8C2F
+:10BE5000002023E422000010000000157B006B8C02
+:10BE60000200C09C003023E46400001000000015B4
+:10BE7000C80E8B8400406018302063A80040A018D2
+:10BE80002C20A5A8002003D4CC0E6B840040801881
+:10BE9000342084A8001804D4D00E8B84004060188D
+:10BEA000382063A8002003D4D40E8B840400639C44
+:10BEB000002003D4000085847B006B8C003023E4D9
+:10BEC0000300001000000015100084A8002005D415
+:10BED00000006584200063A8001805D408006B8565
+:10BEE00000408018002084A8060070B8005804D4D0
+:10BEF000FFFFC0A800408018402084A8002063E015
+:10BF0000003003D45D23FF070000001542FDFF074A
+:10BF100014006184140081841C116484E91DFF07EE
+:10BF20002011849CD81BFF070000001514006185B8
+:10BF30000000809C780D6B84002023E42300001017
+:10BF40000000CBA8740D6B84002023E420000010B7
+:10BF50000000609C78038B840000A09CFFFF609C25
+:10BF6000001804E4120000100000E09C005864E097
+:10BF70004812638C002803E40D0000100000001537
+:10BF80000000A3A81000E09C0838A5E0000090A8DD
+:10BF90000500609C0000C09C0000E09CA21BFF0705
+:10BFA0000100409D8F000000140061850811868407
+:10BFB0000000609C001804E4F4FFFF13000000156B
+:10BFC000F2FFFF03AB00A09C0000609C0811868478
+:10BFD000781D26D40100609C001824E403000010A2
+:10BFE000A500C09DAB00C09D000090A80000AEA8B9
+:10BFF000E9FFFF032000609CC80ECB84004060185E
+:10C00000302063A800408018342084A8003003D476
+:10C010000040A0182C20A5A8CC0E6B84001804D4D6
+:10C02000ACFFFF0300000015940D89840000609CA4
+:10C03000001804E447FFFF1300000015941D29D4E5
+:10C04000000069A829F3FF070000001541FFFF0366
+:10C0500014006185001824E42EFFFF130000609C8B
+:10C06000004080181C2084A8041949D4000064846E
+:10C0700027FFFF03200063A87803A9840040E0188D
+:10C080001020E7A800400019142008A9020065B894
+:10C090000400C5B8C00D839C0228C6E0002089E0DA
+:10C0A000400E639C00008484001869E00200C6B85A
+:10C0B000000063840030C9E0002007D4940D298576
+:10C0C000D005469D001808D4004060180C0563A8F0
+:10C0D000000083840000A7844B0084B800406018EF
+:10C0E000080563A80020A5E0002807D40000838489
+:10C0F000000068844B0084B8002063E00000809C4E
+:10C10000001808D4002009E4030000100100609C1E
+:10C110000200609C0000A3A800008A8C0000609CC4
+:10C12000001804E403000010000000150800A5A892
+:10C13000004060181C2063A80A00CA9400408018C0
+:10C14000042084A8002803D400406018082063A8B5
+:10C150000C00AA94003003D4002804D4FEFEFF0390
+:10C16000FC006B84BDFEFF03940DAB84004060189F
+:10C17000102063A80000C09C002003D40040801859
+:10C18000142084A8003004D47B006B8C005003E49E
+:10C190000C000010000000150800809C0040601892
+:10C1A0001C2063A80411A584002003D4004080183B
+:10C1B000182084A8002804D44AFFFF0308006B85D8
+:10C1C000F7FFFF030000809C59FEFF030000C4A995
+:10C1D00057FEFF030000C3A935FEFF03140061856D
+:10C1E0006723FF07B4126B9C00006AA90000218539
+:10C1F00004004185080081850C00C185100001867E
+:10C20000004800441800219CE4FF219C0C4801D404
+:10C21000105001D4146001D4187001D4FF00C3A5DC
+:10C22000000045A9FF0084A59A22FF070100609C39
+:10C2300020116A9CB4128A9C041801D4082001D4ED
+:10C24000900DCA9C1C116A84980DEA9CDC0E0A9D14
+:10C25000001801D48C0DAA9C0100609C1425FF07D6
+:10C2600000008EA800008AA80000ACA83026FF07B6
+:10C270000100609CD0FCFF0700006AA80040601825
+:10C2800008C563A80100809C002003D4880D8A8C17
+:10C290000000609C001824E4090000100200609C6B
+:10C2A00000182CE43D0000100100609C8A0D8A8C6F
+:10C2B000001804E43900000C000000150100609C27
+:10C2C000B221FF070000809C06008EB80040601875
+:10C2D000482063A80100E09C0018A4E00400639CCF
+:10C2E0000000C584001884E000006484FF0F8018FB
+:10C2F000FFFF84A80B0063B80320C6E000382CE4DD
+:10C3000014000010032083E00080A0180000A5A8FE
+:10C31000002864E0002803D40080A0180400A5A829
+:10C32000002864E0003003D4004080182C0284A868
+:10C330000000609C001804D400406018240263A828
+:10C340000400809C002003D4410000000000001580
+:10C350008A0D6A8C003823E40900001000000015E3
+:10C360000080A0180000A5A8002864E0000DA01817
+:10C370000000A5A8E8FFFF03000000150080A0183A
+:10C380000000A5A8002864E00081A0180000A5A86E
+:10C39000E1FFFF03000000150C116A840000A09C5F
+:10C3A000002803E42700001006006EB80040801843
+:10C3B0004C2084A8002063E00000838400406018C3
+:10C3C000240263A80B0084B800004385FF0F6018A7
+:10C3D000FFFF63A8031884E000806018000063A8D2
+:10C3E000005084E0001884E000006484002823E406
+:10C3F0000900000C0100609C0400849C04004A9D1C
+:10C4000000006484002823E4FDFFFF130400849CE3
+:10C410000100609C5D21FF070000809C0000809C63
+:10C42000004060182C0263A8002003D4004080184C
+:10C43000240284A8005004D4050000000000001568
+:10C440000100609C5121FF07000083A80C0021859A
+:10C4500010004185140081851800C1850048004402
+:10C460001C00219C00408018008084A80040A01877
+:10C470000480A5A8000084840040C018A880C6A835
+:10C48000DC2243D40000A58400408018088084A8E2
+:10C49000E02A43D4000084840040A0180C80A5A8A2
+:10C4A000E42243D40000A58400408018108084A8B2
+:10C4B000E82A43D4000084840040A0181480A5A872
+:10C4C000EC2243D40000A58400408018188084A882
+:10C4D000F02A43D4000084840040A0181C80A5A842
+:10C4E000F42243D40000A58400408018208084A852
+:10C4F000F82A43D4000084840040A0182480A5A812
+:10C50000FC2243D40000A58400408018288084A821
+:10C51000002B43D4000084840040A0182C80A5A8E0
+:10C52000042343D40000A58400408018308084A8F0
+:10C53000082B43D4000084840040A0183880A5A8AC
+:10C540000C2343D40000A584004080183C8084A8BC
+:10C55000102B43D4000084840040A0184080A5A87C
+:10C56000142343D40000A58400408018448084A88C
+:10C5700000008484182B43D41C2343D40040A0180B
+:10C580004880A5A8004080184C8084A80000A5849D
+:10C59000202B43D4000084840040A0185080A5A81C
+:10C5A000242343D40000A58400408018548084A82C
+:10C5B000282B43D4000084840040A0185880A5A8EC
+:10C5C0002C2343D40000A584004080185C8084A8FC
+:10C5D000302B43D4000084840040A0186080A5A8BC
+:10C5E000342343D40000A58400408018648084A8CC
+:10C5F000382B43D4000084840040A0186880A5A88C
+:10C600003C2343D40000A584004080186C8084A89B
+:10C61000402B43D4000084840040A0187080A5A85B
+:10C62000442343D40000A58400408018748084A86B
+:10C63000482B43D4000084840040A0187880A5A82B
+:10C640004C2343D40000A584004080187C8084A83B
+:10C65000502B43D4000084840040A0188080A5A8FB
+:10C66000542343D40000A58400408018848084A80B
+:10C67000582B43D4000084840040A0188880A5A8CB
+:10C680000000A5845C2343D4602B43D40040801871
+:10C690008C8084A80040A0189080A5A80000848405
+:10C6A000642343D40000A58400408018948084A8AB
+:10C6B000682B43D4000084840040A0189880A5A86B
+:10C6C0006C2343D40000A584004080189C8084A87B
+:10C6D00000008484742343D4702B43D400008684E8
+:10C6E0000040A018A480A5A800408018A08084A8BD
+:10C6F000000084840000A584782343D40000C6840D
+:10C7000000408018AC8084A87C2B43D40000848433
+:10C710000040A018B080A5A8842343D40000A584BD
+:10C7200000408018B48084A8882B43D400008484FF
+:10C730000040A018B880A5A88C2343D40000A5848D
+:10C7400000408018BC8084A8902B43D400008484CF
+:10C750000040A018C080A5A8942343D40000A5845D
+:10C7600000408018C48084A8982B43D4000084849F
+:10C770000040A018C880A5A89C2343D40000A5842D
+:10C7800000408018300884A800008484A02B43D483
+:10C79000803343D40040A0183808A5A8A42343D46C
+:10C7A0000000A58400408018340884A8A82B43D436
+:10C7B000000084840040A0184008A5A8AC2343D4FE
+:10C7C0000000A584004080181C0C84A8B02B43D422
+:10C7D000000084840040A0181808A5A8B42343D4FE
+:10C7E0000000A584004080181C0884A8B82B43D4FE
+:10C7F000000084840040A0182808A5A8BC2343D4C6
+:10C800000000A58400408018240884A8C02B43D4CD
+:10C81000000084840040A0182008A5A8C42343D4A5
+:10C820000000A58400408018000C84A8C82B43D4C5
+:10C83000000084840040A0184408A5A8CC2343D459
+:10C840000000A584004080180C0C84A8D02B43D491
+:10C85000000084840040A018100CA5A8D42343D461
+:10C860000000A58400408018140C84A8D82B43D461
+:10C87000000084840040A018180CA5A8DC2343D431
+:10C880000000A58400408018040B84A8E02B43D44A
+:10C89000000084840040A018000BA5A80000A58417
+:10C8A000E42343D4E82B43D400408018480884A8EC
+:10C8B0000040A0180C0BA5A800008484EC2343D4EE
+:10C8C0000000A58400408018080B84A8F02B43D4F6
+:10C8D000000084840040A018240CA5A8F42343D4AD
+:10C8E0000000A58400408018140884A8F82B43D4C5
+:10C8F000000084840040A0180C08A5A8FC2343D4A1
+:10C900000000A58400408018100884A800008484DA
+:10C91000002C43D4042443D40048004400000015F4
+:10C92000DC12A38400408018008084A80040C01856
+:10C93000A880C6A8002804D4E01283840040A01870
+:10C940000480A5A8002005D4E412A3840040801828
+:10C95000088084A8002804D4E81283840040A0182A
+:10C960000C80A5A8002005D4EC12A38400408018F8
+:10C97000108084A8002804D4F01283840040A018FA
+:10C980001480A5A8002005D4F412A38400408018C8
+:10C99000188084A8002804D4F81283840040A018CA
+:10C9A0001C80A5A8002005D4FC12A3840040801898
+:10C9B000208084A8002804D4001383840040A01899
+:10C9C0002480A5A8002005D40413A3840040801867
+:10C9D000288084A8002804D4081383840040A01869
+:10C9E0002C80A5A8002005D40C13A3840040801837
+:10C9F000308084A8002804D4101383840040A01839
+:10CA00003880A5A8002005D41413A3840040801802
+:10CA10003C8084A8002804D4181383840040A01804
+:10CA20004080A5A8002005D41C13A38400408018D2
+:10CA3000448084A8002804D4201383840040A018D4
+:10CA40004880A5A8002005D42413A38400408018A2
+:10CA50004C8084A8002804D4281383840040A018A4
+:10CA60005080A5A8002005D42C13A3840040801872
+:10CA7000548084A8002804D4301383840040A01874
+:10CA80005880A5A8002005D43413A3840040801842
+:10CA90005C8084A8002804D4381383840040A01844
+:10CAA0006080A5A8002005D43C13A3840040801812
+:10CAB000648084A8002804D4401383840040A01814
+:10CAC0006880A5A8002005D44413A38400408018E2
+:10CAD0006C8084A8002804D4481383840040A018E4
+:10CAE0007080A5A8002005D44C13A38400408018B2
+:10CAF000748084A8002804D4501383840040A018B4
+:10CB00007880A5A8002005D45413A3840040801881
+:10CB10007C8084A8002804D4581383840040A01883
+:10CB20008080A5A8002005D45C13A3840040801851
+:10CB3000848084A8002804D4601383840040A01853
+:10CB40008880A5A8002005D46413A3840040801821
+:10CB50008C8084A8002804D4681383840040A01823
+:10CB60009080A5A8002005D46C13A38400408018F1
+:10CB7000948084A8002804D4701383840040A018F3
+:10CB80009880A5A8002005D47413A38400408018C1
+:10CB90009C8084A8002804D480138384002006D4B9
+:10CBA0007813A38400408018A08084A8002804D4AF
+:10CBB0007C1383840040A018A480A5A8002005D47D
+:10CBC0008013A38400408018AC8084A8002806D479
+:10CBD0008413A3842000C69C002804D48813838473
+:10CBE0000040A018B080A5A8002005D48C13A38411
+:10CBF00000408018B48084A8002804D49013838453
+:10CC00000040A018B880A5A8002005D49413A384E0
+:10CC100000408018BC8084A8002804D49813A38402
+:10CC20000400849C002804D49C1383840040A01832
+:10CC3000C480A5A8002005D4A013A38400408018B8
+:10CC4000300884A8002806D4002806D4A413A3849E
+:10CC5000002804D4A81383840040A0183808A5A88D
+:10CC6000002005D4AC13A38400408018340884A8A5
+:10CC7000002804D4B01383840040A0184008A5A85D
+:10CC8000002005D4B413A384004080181C0C84A891
+:10CC9000002804D4B81383840040A0181808A5A85D
+:10CCA000002005D4BC13A384004080181C0884A86D
+:10CCB000002804D4C01383840040A0182808A5A825
+:10CCC000002005D4C413A38400408018240884A83D
+:10CCD000002804D4C81383840040A0182008A5A805
+:10CCE000002005D4CC13A38400408018000C84A835
+:10CCF000002804D4D01383840040A0184408A5A8B9
+:10CD0000002005D4D413A384004080180C0C84A800
+:10CD1000002804D4D81383840040A018100CA5A8C0
+:10CD2000002005D4DC13A38400408018140C84A8D0
+:10CD3000002804D4E01383840040A018180CA5A890
+:10CD4000002005D4E413A38400408018040B84A8B9
+:10CD5000002804D4E81383840040A018000BA5A881
+:10CD6000002005D4EC13A38400408018480884A850
+:10CD7000002804D4F01383840040A0180C0BA5A84D
+:10CD8000002005D4F413A38400408018080B84A865
+:10CD9000002804D4F81383840040A018240CA5A80C
+:10CDA000002005D4FC13A38400408018140884A834
+:10CDB000002804D4001483840040A0180C08A5A8FF
+:10CDC000002005D40414638400408018100884A84F
+:10CDD000001804D40048004400000015E0FF219C26
+:10CDE000004801D4045001D4086001D40C7001D46F
+:10CDF000108001D4149001D418A001D41CB001D427
+:10CE0000000084A90400A0187093A5A8FF0043A601
+:10CE10000000858404006018257E63A8D715FF07ED
+:10CE2000060092BA00406018402063A80100A09C50
+:10CE3000001894E00000C09C00406018040863A83B
+:10CE400004314CD4002803D40000009E0000A484C8
+:10CE500000006CA85000A5B8040080184C8384A87A
+:10CE60000700C5A5AFFEFF07003004D800408018BA
+:10CE7000642084A8002074E000006384008003E440
+:10CE8000CE01000C1C194CD400406018240263A889
+:10CE90000000A09C3811CC84002803D400008C84AE
+:10CEA0000200609C001804E40F01001008344CD408
+:10CEB000001844E4710000100300C09E0100A09C13
+:10CEC000002804E42400001000282EE466FDFF077B
+:10CED00000006CA80300609C00182EE412000010F3
+:10CEE0000000809C940D6C84002023E40E00001050
+:10CEF0000100A09CC4056C84002003E40A0000101B
+:10CF0000942D2CD40600638C002003E41000001044
+:10CF100000000015FC008C841C03AC8CAB1DFF07CB
+:10CF20007C056C9C04006018709363A804008C8DD1
+:10CF30000400A0184C83A5A8000083840100849CF1
+:10CF4000006005D8A1010000002003D4F3FFFF0317
+:10CF500008018C84360000100400609C004080189A
+:10CF6000682084A85811CC84002074E064118C845B
+:10CF700014214CD4880DAC8C000083844F0084B8FD
+:10CF800010314CD4010084A4008025E41400000C6E
+:10CF90000C214CD438116C84008003E40300001091
+:10CFA0000000ACA80C1C4CD4000072A897FCFF0732
+:10CFB00000008EA8000072A8CFF9FF0700008CA81F
+:10CFC00000004BA90100609C00182AE4C0FFFF1379
+:10CFD0000200A09CBEFFFF0300280CD438118C84F3
+:10CFE00084010004000072A8FFFF609C00180BE49D
+:10CFF000080000100000ACA808148C84000072A87F
+:10D00000005884E00C5C4CD4E9FFFF0308244CD4A6
+:10D01000000072A800008CA82000A09C76F9FF07F1
+:10D020003400C09CE9FFFF030100609C00182EE45F
+:10D03000090000100800009E000072A80000D0A89F
+:10D0400000008CA86CF9FF072000A09CA0FFFF0344
+:10D0500000000015FE006E9CFF0063A4002843E45E
+:10D060000400001000000015F4FFFF030B00009EF9
+:10D07000F2FFFF037500009E00B004E494FFFF0F71
+:10D08000FE008E9C004060181C2063A80000A09C3D
+:10D09000FF0084A4002803D40100409D005044E414
+:10D0A000030000100500609C0000AAA800182EE4F0
+:10D0B000030000100000809C00008AA8042065E0A6
+:10D0C000008003E40B00000C0400609C00182EE4B8
+:10D0D0000400001000502EE4D8FFFF030900009E5A
+:10D0E000E4FFFF1300000015D4FFFF030600009EBD
+:10D0F00000008EA80000ACA844FCFF07000072A846
+:10D10000940DAC84008025E4030000100000809C96
+:10D1100000008AA800B02EE4030000100000609C0C
+:10D1200000006AA8031864E0008003E40700001010
+:10D130000000809CDC0E6C84008023E46300000C03
+:10D140007C056C9C0000809C002005E4070000101A
+:10D150000000001504006C8C002023E40300001084
+:10D160000100C09C04300CD800118C840000C09CCD
+:10D17000003004E4150000100000009E0500609CD3
+:10D1800000180EE40A000010000000150200609C68
+:10D1900000182EE444000010001824E4420000109F
+:10D1A000003025E440000010000000150100A09CA4
+:10D1B00008018C847C056C9C942D2CD4031DFF07E6
+:10D1C0001C03AC8C0000009EB620FF07000072A874
+:10D1D00000800BE42100000C00006CA840186C8457
+:10D1E0000000A09C002803E4040000100100C09C83
+:10D1F00040286CD408314CD408148C84002804E4F2
+:10D2000008000010000072A8880D6C8C002803E450
+:10D2100008000010000000150C244CD4000072A877
+:10D22000E3F9FF0700008CA829FFFF0300000015A9
+:10D23000F0000004000072A8FFFF609C00182BE4BF
+:10D24000F7FFFF130C5C4CD40000609C7B00009E39
+:10D250007AFFFF030C1C4CD40040C0184820C6A81D
+:10D26000003094E000004485FF0F8018FFFF84A881
+:10D2700082EAFF0703204AE10100A09C00802AE423
+:10D28000D7FFFF1308294CD4000072A800008CA817
+:10D290002000A09CD8F8FF077B00C09CCB000000BA
+:10D2A0000000001500182EE4C8FFFF130000009EC8
+:10D2B0000000609C001825E4C4FFFF130000001567
+:10D2C000C2FFFF0300194CD41C03AC8C08018C84F2
+:10D2D00004500CD8BD1CFF0794552CD49AFFFF03B3
+:10D2E000940DAC840400609C00182EE4A90000108A
+:10D2F0000100809C0040C0186820C6A8003074E07F
+:10D300000000A384FC00859CFF0084A41C00609C9A
+:10D310000018A4E49B0000101C2B0CD84A00009EAF
+:10D3200010118C840000409D5F0064A4005003E451
+:10D330008600000C0000001570116C840000AEA87F
+:10D3400074118C84F8184CD4FC204CD40100609CDF
+:10D35000D622FF0700008CA8FC108C84F8106C8487
+:10D36000840DAC848A23FF07800DCC840000809C50
+:10D3700000200BE403000010000000154700009E91
+:10D38000A00D6C84002003E41A00001000000015BA
+:10D39000A40D6C84002003E41600001000000015AA
+:10D3A000A80D6C84002003E412000010000000159A
+:10D3B000AC0D6C84002003E40E000010000000158A
+:10D3C000B00D6C84002003E40A000010000000157A
+:10D3D000B40D6C84002003E406000010000000156A
+:10D3E000B80D6C84002023E4090000100000001533
+:10D3F00000406018080563A80000809C0000A3841A
+:10D40000002025E4B2FEFF0F000000151C03AC8CC9
+:10D410000000C09C002886E52800000C0000609CED
+:10D42000C00D6C84003023E44000000C020066B89C
+:10D43000FF0025A50000009D006063E00000409D06
+:10D44000C00DA39C0040601908056BA90040A019FD
+:10D450000C05ADA9006068E00100C69C400E838405
+:10D46000020006B90400A59C005024E40600001048
+:10D470000000E09C00006B84005023E40D00000CD1
+:10D4800000000015004886E50C00000C0000609CC0
+:10D4900000006584003823E4F0FFFF13006068E0BB
+:10D4A00000006D84003823E4ECFFFF13006068E0A7
+:10D4B0004E00009E0000609C001830E4DFFEFF1369
+:10D4C000000000156716FF07000000150040A018B7
+:10D4D0004020A5A80800CC84002894E000406018F3
+:10D4E000002063A8FFFFA0A8003003D4002804D4C4
+:10D4F000C9F7FF0700006CA81C116C847118FF07A6
+:10D5000020118C9C0000C09C000092A80F00609C21
+:10D510000000A09C4416FF070000E09C0300C09C94
+:10D520006BFEFF0300300CD4004060180C0563A8AC
+:10D5300000008384003024E4BEFFFF13020066B8BD
+:10D54000DDFFFF034E00009E040060182D7E63A8DF
+:10D550000A14FF070000001514116C84005003E446
+:10D560000400000C0000001574FFFF034D00009E36
+:10D57000D91FFF077C118C9C71FFFF0370116C8415
+:10D58000BEE9FF0700006CA867FFFF0310118C8441
+:10D5900000202EE4A9FEFF0F0600009EFE006E9CF8
+:10D5A000FF0063A4002043E4B2FEFF130000001557
+:10D5B000A2FEFF030C00009EFF17FF0720118C9CAA
+:10D5C00032FEFF03000000150000218504004185A4
+:10D5D000080081850C00C185100001861400418679
+:10D5E000180081861C00C186004800442000219C50
+:10D5F000FCFF219C004801D4FF0063A40040A01858
+:10D600004420A5A8060063B80040C0184820C6A85A
+:10D610000000609D0028E3E00400A01A487DB5AA40
+:10D620000000A784003063E00000C384FF0FE0180F
+:10D63000FFFFE7A80B00A5B80338C6E0033825E2D2
+:10D640000020E6E203006B9E00B8B3E45600000C35
+:10D6500007002BA50100EB9D00A869E00248ABE1A3
+:10D660000000838C07002FA50068B1E000A8E9E066
+:10D670000248AFE10000678C02000B9D0020A5E08E
+:10D68000070028A50080E0180000E7A800A8C9E06E
+:10D690000038A5E0006891E00000E68C0248A8E1AF
+:10D6A000001884E00080C0180000C6A8006871E07F
+:10D6B000003084E0003863E00000C58C0080E01892
+:10D6C0000000E7A80000209D0000A48C003863E063
+:10D6D000FF00C6A40000838CFF00A5A40000E09C0E
+:10D6E000003826E403000010FF0084A40100209D00
+:10D6F000003825E4030000100000609C0100609CDD
+:10D70000031869E0003803E4060000100000E09C04
+:10D710000100609C001824E42400000C00000015A7
+:10D72000003826E4030000100000209D0100209D29
+:10D73000003825E4030000100000609C0100609C9C
+:10D74000031869E0003803E4150000100300609C32
+:10D75000001824E412000010070033A5040080180C
+:10D76000487D84A8F8FF609C0020A9E00318B3E17D
+:10D770000000858C006871E00080A0180000A5A85A
+:10D78000002063E0002863E00100809C0000A38C7F
+:10D79000002824E40500000C00000015AAFFFF0388
+:10D7A00000006FA9FFFF609D000021850048004434
+:10D7B0000400219CE8FF219C004801D4045001D4BE
+:10D7C000086001D40C7001D4108001D4149001D4ED
+:10D7D000020084B8000083A9000006AA001864E0D3
+:10D7E0000400C5B9400EE3840400C6B80000AEA82A
+:10D7F000C00D43850B0047BA840D6C840B004AB9F9
+:10D800005F26FF07800D8C847B008C8C0200609C5F
+:10D81000001804E42F00001000584AE10000A09C0A
+:10D820000300C09C0F00E09C00800019000008A9C4
+:10D830000000809C00406AE080802019808029A937
+:10D840000100849C004803D40030A4E5FBFFFF13D3
+:10D850000400639C0100A59C0038A5E5F3FFFF13BD
+:10D8600040004A9D800D8C840300D0B80000AEA813
+:10D87000410084B84226FF07840D6C840058F2E012
+:10D880000000A09C0300C09C0700009D00802019A0
+:10D89000000029A90000809C004867E080802019D2
+:10D8A000808029A90100849C004803D40030A4E5AD
+:10D8B000FBFFFF130400639C0100A59C0040A5E54D
+:10D8C000F3FFFF134000E79C2D000000000000154F
+:10D8D0000000A09C0300C09C1F00E09C0080001979
+:10D8E000000008A90000809C00406AE080802019A8
+:10D8F000808029A90100849C004803D40030A4E55D
+:10D90000FBFFFF130400639C0200A59C0038A5E503
+:10D91000F3FFFF1380004A9D800D8C840300D0B874
+:10D920000000AEA8410084B81526FF07840D6C8462
+:10D930000058F2E00000A09C0300C09C0F00009D76
+:10D9400000802019000029A90000809C004867E0A1
+:10D9500080802019808029A90100849C004803D47C
+:10D960000030A4E5FBFFFF130400639C0200A59CAC
+:10D970000040A5E5F3FFFF138000E79C0000218530
+:10D9800004004185080081850C00C18510000186D6
+:10D9900014004186004800441800219CD0FF219CBF
+:10D9A000004801D4045001D4086001D40C7001D4A3
+:10D9B000108001D4149001D418A001D41CB001D45B
+:10D9C00020C001D424D001D428E001D42CF001D40B
+:10D9D000004080182C0884A81014C385000003AAF6
+:10D9E0000000209D0000848600408018280884A83C
+:10D9F0007B00A38C0000048700408018200884A8C6
+:10DA000002C04EE3000044860200809C002025E412
+:10DA100003000010000000150100209D8900908C7B
+:10DA20000100A09C002804E4030000100000009DF9
+:10DA3000000005A9FC0090840F00C8BB070089BB4B
+:10DA40000200E4B80000B4A80000D8A8008007E1F4
+:10DA5000FC0448857C04888557FFFF0708004AB905
+:10DA6000080078B8387070D42CA070D404187EE008
+:10DA70000460CAE104E083E030C070D4349070D414
+:10DA80000000609C0018BAE51400001004A0C4E275
+:10DA90000100949D00908CE50E00000C0000001524
+:10DAA000000044A90101809E0460CAE000006EA845
+:10DAB00001008C9D000096A80000AEA8FD25FF0780
+:10DAC0000000F4A800908CE5F9FFFF130460CAE0A1
+:10DAD000FFFF5A9F0100189F00C07AE0001898E5E8
+:10DAE0001800000C000018AA000003AB0000809D85
+:10DAF00000908CE50F00000C080070B80101809EBA
+:10DB000004187EE004E043E10460CAE000006EA86F
+:10DB100001008C9D000096A80000AEA8E525FF0737
+:10DB20000000F4A800908CE5F9FFFF130460CAE040
+:10DB30000100109E00C090E5EDFFFF1300000015EE
+:10DB40000000609D0000218504004185080081855A
+:10DB50000C00C185100001861400418618008186E2
+:10DB60001C00C1862000018724004187280081878E
+:10DB70002C00C187004800443000219CC4FF219C38
+:10DB8000004801D4045001D40000A3A9004080182B
+:10DB9000280884A8004060182C0863A80040E019F9
+:10DBA0002008EFA9000063840000E09C0000A09E14
+:10DBB00000008484000063AA0100C09C181801D4EE
+:10DBC0001C2001D4000024AA7B00AD8C0200809CA4
+:10DBD000002025E4030000100800619C0000E6A876
+:10DBE00089008D8C003004E403000010203801D43B
+:10DBF0000000A6AA0000809C00006F85382001D498
+:10DC00000801AD8410144D850200A5B8FC00CD8438
+:10DC10000068E5E002880AE100008F840200C6B8CF
+:10DC2000142001D424A801D4006826E17C04A78430
+:10DC3000282801D400008F84FC04E784029884E043
+:10DC40002C3801D40000EF857C04C984303001D425
+:10DC5000FC042985082001D4344801D4104001D4A3
+:10DC60000C7801D42C986DD430886DD434586DD490
+:10DC7000AD25FF0738506DD4000021850400418593
+:10DC8000004800443C00219CFCFF219C004801D43A
+:10DC90007C00838C0000609D005824E40600001086
+:10DCA000000000153EFFFF07000000150400000003
+:10DCB00000000015B2FFFF070000001500002185DD
+:10DCC000004800440400219CFCFF219C004801D432
+:10DCD000000004A9000025A9FF00C6A4002083E4D9
+:10DCE0000C00000C0000E3A84300A7B8070087A4BD
+:10DCF0000028A9E0082086E00000658C0100E79C70
+:10DD0000042063E0004087E4F8FFFF13001805D803
+:10DD100000002185004800440400219CFCFF219C58
+:10DD2000004801D40000E4A90000A5A9000026A92C
+:10DD3000FF0067A5002083E41700000C000003A982
+:10DD40000A4B88E0064B84E0002088E04300E4B8FA
+:10DD50000700A4A40100089D0038EDE0004884E01D
+:10DD60000000678C0828ABE04300C4B8042863E0D7
+:10DD70000030CDE0001807D8070084A40000668CAE
+:10DD800008208BE0042063E0007888E4EDFFFF13B7
+:10DD9000001806D800002185004800440400219C9A
+:10DDA000E0FF219C004801D4045001D4086001D454
+:10DDB0000C7001D4108001D4149001D418A001D4A7
+:10DDC0001CB001D40200A4B80040C0182008C6A8A6
+:10DDD0000040E0182408E7A8001805E10000468686
+:10DDE0000000A09C0000009EFC0448850000C09C30
+:10DDF0007C04888508004AB90000C78504604AE1B0
+:10DE00006DFEFF070000CEAA0080AEE513000010F3
+:10DE10000080EEE00100809D00908CE50C00000C7D
+:10DE20000000CCA80101809E00006AA801008C9D22
+:10DE30000000809C0000AAA81E25FF070000F4A88F
+:10DE400000908CE5F9FFFF130000CCA8FFFFD69DE2
+:10DE50000100009E0080EEE0003890E51600000C06
+:10DE60000000C7AA0000809D00908CE50E00000C09
+:10DE7000000000150800D0B90101809E0460CEE0CA
+:10DE800000006AA801008C9D0000809C0000AAA8E8
+:10DE90000825FF070000F4A800908CE5F9FFFF13A8
+:10DEA0000460CEE00100109E00B090E5EFFFFF138C
+:10DEB0000000809D000021850400418508008185C7
+:10DEC0000C00C1851000018614004186180081866F
+:10DED0001C00C186004800442000219CFCFF219CBE
+:10DEE000004801D40000C3A80000609C8000868424
+:10DEF000EB1806D80100609C001844E40600000CF2
+:10DF00000000A09C0200609C001824E404000010A3
+:10DF10000200E09C4B00A68C0200E09C003825E447
+:10DF2000170000100100009D004060180C0363A85A
+:10DF30000000A3840700609CFF0085A4001824E46F
+:10DF40000A000010E42806D800406018140363A8F3
+:10DF500000008384E62006D8E52006D80F00809CC8
+:10DF600052000000EC2006D8CB00668C002863E04D
+:10DF70000100639CFAFFFF03E61806D80040201951
+:10DF8000040329A900006984E71806D8FF0063A4E8
+:10DF9000004023E4420000100000609C0040801814
+:10DFA000080384A800006484FF00A3A4003825E4CB
+:10DFB00025000010E81806D800008484FF0064A43F
+:10DFC000E92006D8081868E0EC1806D8E80066844E
+:10DFD00000FF8018FF0084A8032063E0000380187E
+:10DFE000000084A8002003E41500001000000015C4
+:10DFF000004060180C0363A80000A3840700609C25
+:10E00000FF0085A4001824E408000010E42806D8C6
+:10E0100000406018140363A800008384E62006D83B
+:10E0200022000000E52006D8CB00668C002863E0C3
+:10E030000100639C1D000000E61806D8FEFFFF03E8
+:10E04000CB00668C004025E40C0000100000001599
+:10E05000000084840300609CFF00A4A4EA2006D88A
+:10E06000082863E0100083A4840084B80F0063A430
+:10E07000D6FFFF03002063E00300609C001825E446
+:10E08000D2FFFF130F00609C000069841000809C89
+:10E09000EB1806D8CEFFFF03EC2006D8CB00868C09
+:10E0A000E62006D8EC1806D8000021850048004478
+:10E0B0000400219CF0FF219C004801D4045001D4AD
+:10E0C000086001D40C7001D400408018040384A8B7
+:10E0D000000043A90000E09D000064840000C09D92
+:10E0E000007023E43C0200100100609C7C180AD8F8
+:10E0F0007C00AA8D0000A09CFF00CDA4002826E48F
+:10E10000030000100100609C141C4AD414146A849B
+:10E11000002823E4030000100100809C08214AD459
+:10E1200008118A840100609C001824E40800001093
+:10E13000FF008DA4002826E4060000100400609C67
+:10E140000000A09C08294AD4FF008DA40400609C14
+:10E15000001804E40A0000100000609C1A008A8C79
+:10E16000001804E41A0200100000609C00406018CF
+:10E17000200363A80000838487200AD844036A84AC
+:10E18000FF00ADA40200809C0100639C002005E418
+:10E1900005000010441B0AD440036A840100639CFC
+:10E1A000401B0AD41800CA8C0000809C003004E494
+:10E1B000050200100100609C19006A8C002003E435
+:10E1C000060000100100609C1C008A8C001804E40A
+:10E1D000F601000C0000001500406018080363A859
+:10E1E0000100A09C0000838489280AD888200AD8CE
+:10E1F00046006A8C0100A09C002823E42B0000103C
+:10E200000000001500408018040384A80000648406
+:10E210008C180AD8FF0063A4002823E42300001010
+:10E220000000001519006A8C002823E4D7010010B3
+:10E23000FF0066A4002823E4040000100200E09D13
+:10E240008A006A8C0200E39D0000009D007888E54A
+:10E250001600000CB800AA9C0040601948036BA986
+:10E2600000402019380329A9A000EA9C9000CA9C0C
+:10E2700000008B840100089D00006B84002006D400
+:10E28000001807D4000089840400C69C0400E79CA1
+:10E2900000006984F827E5DF001805DC007888E5D0
+:10E2A000F4FFFF130200A59CFF00ADA40400609CD6
+:10E2B000001825E4DB01000C8B780AD80040C01858
+:10E2C0000403C6A819008A8C0100E09C0000668443
+:10E2D000003824E404000010C0180AD80000668446
+:10E2E000C1180AD81B006A8C003823E4050000100E
+:10E2F0000200609C00006684C2180AD80200609C7C
+:10E30000001825E41B0000100700809C00406018E6
+:10E310000C0363A800006384002003E48C01001058
+:10E32000020063B80400A0187893A5A8002883E031
+:10E330000300848C0400A0189493A5A8C4200AD8D4
+:10E34000002863E00300638CC5180AD8C5006A8CF6
+:10E350000400A0181C94A5A8020063B8C4008A8C0D
+:10E36000002863E00000A384062B84E0C6200ADCBA
+:10E3700000406018140363A800008384C8200AD8F2
+:10E380000800609CFF0084A4001844E46E010010A3
+:10E390000000609C00406018040363A800008384B0
+:10E3A000C9200AD84E00AA8C0100609C001825E400
+:10E3B000070000100000609C00406018040363A880
+:10E3C00000008384CA200AD80000609C001805E47D
+:10E3D0005501001000000015C8008A8CCB200AD817
+:10E3E00012006A8C0100C09C003023E4070000107A
+:10E3F000FF008DA400406018080363A80000838418
+:10E40000CC200AD8FF008DA40000A09C002824E4A2
+:10E41000030000100000009D000006A90300E09C1E
+:10E42000003824E4030000100000609C000066A88F
+:10E43000041868E0002803E46B000010003024E4B6
+:10E440000040C0180080C6A800406018080463A8F7
+:10E45000003806D400008384002804E40C00001077
+:10E46000000000150000A09C742D2AD400006684D2
+:10E47000100083A4200063A4002803E45700000CCC
+:10E48000002804E4FAFFFF1300000015740DCA848D
+:10E490005900609C001826E40300001000000015DD
+:10E4A0000000C3A94D008A8C0100609C001824E480
+:10E4B0002D0000100800609CCB008A8C001844E4FA
+:10E4C000290000100000A09C00408018040384A8CC
+:10E4D00000006484002823E4390000100000609CE0
+:10E4E000CD180AD8CD008A8C0300609C001824E463
+:10E4F0001D0000100500809C0040E0180080E7A887
+:10E5000000406018080463A8002007D40000A3841A
+:10E510000000809C002005E40F0000105900609C62
+:10E5200074252AD40000C7A80000A09C00006684BF
+:10E53000100083A4200063A4002803E41C00000C46
+:10E54000002804E4FAFFFF1300000015740DCA84CC
+:10E550005900609C001826E403000010000000151C
+:10E560000000C3A97304000400006AA88104000429
+:10E5700000006AA800406018040363A84B00AA8C3E
+:10E58000000083840000609C001805E40400000C77
+:10E59000D0200AD82301000074752AD450FEFF074A
+:10E5A00000006AA81F01000074752AD45900A09CBD
+:10E5B000742D2AD4E7FFFF030000C5A8000064847F
+:10E5C000002823E4C7FFFF130300609C0200809C27
+:10E5D000C5FFFF03CD200AD85900A09CACFFFF0364
+:10E5E000742D2AD4850000100200609C4A006A8CB9
+:10E5F000003023E47D00000C0000A09CD3280AD842
+:10E600009404000400006AA8D600CA8C0400609C30
+:10E61000003023E46A00000C0000609CFFFF609C57
+:10E62000D8180AD8FF0066A40300A09C002803E4C1
+:10E63000060000100304609CD6008A94001804E4CD
+:10E640001C00000C0500809C0040C0180080C6A87B
+:10E6500000406018080463A8002806D40000809CCD
+:10E660000000A384002005E40B0000100000A09C23
+:10E6700074252AD400006684100083A4200063A4BB
+:10E68000002803E44B00000C002804E4FAFFFF1309
+:10E6900000000015740D6A845900809C002023E45A
+:10E6A00003000010000000150000C4A90500809CB4
+:10E6B0000040C0180080C6A800406018080463A885
+:10E6C000002006D40000A3840000809C002005E404
+:10E6D0000B0000100000A09C74252AD40000668462
+:10E6E000100083A4200063A4002803E42E00000C83
+:10E6F000002804E4FAFFFF1300000015740D6A847B
+:10E700005900809C002023E4030000100000001545
+:10E710005900C09D0040801908038CA94B00AA8CA9
+:10E7200000006C84DE180AD80000609C00008C8415
+:10E73000001805E41800000CDF200AD84C006A8C91
+:10E740000100A09C002823E40C000010000000152C
+:10E7500000408018040384A800006484E2180AD8EA
+:10E76000FF0063A4002823E404000010000000154B
+:10E7700000006C84E3180AD8EE03000400006AA8C5
+:10E7800000406018040363A80000838482FFFF0335
+:10E79000D0200AD8D2FDFF0700006AA8E9FFFF03D6
+:10E7A0004C006A8C5900A09CD5FFFF03742D2AD41D
+:10E7B0005900809CB8FFFF0374252AD4D8180AD8C2
+:10E7C0009304000400006AA800406018180363A8BE
+:10E7D000D600CA8C00008384D9200AD80000A38404
+:10E7E00091FFFF03DA280AD8F203000400006AA8A8
+:10E7F00084FFFF0300000015001824E466FFFF13E8
+:10E80000000000154A006A8C003023E44200000C2E
+:10E810000000809CD3200AD80E04000400006AA8DF
+:10E820000300A09C0040C0180080C6A800406018EB
+:10E83000080463A8002806D40000809C0000A3847C
+:10E84000002005E40B0000100000A09C74252AD4D1
+:10E8500000006684100083A4200063A4002803E461
+:10E860002A00000C002804E4FAFFFF130000001542
+:10E87000740DCA845900609C001826E4030000103F
+:10E88000000000150000C3A90500609C0040E018CE
+:10E890000080E7A80000809C001807D400406018A2
+:10E8A000080463A80000A384002005E40E00001003
+:10E8B0005900609C74252AD40000C7A80000A09CC1
+:10E8C00000006684100083A4200063A4002803E4F1
+:10E8D0000A00000C002804E4FAFFFF135900609CB2
+:10E8E000740DCA84001826E48BFFFF130000001586
+:10E8F00089FFFF035900C09D5900609C741D2AD4F4
+:10E90000F9FFFF030000C3A85900A09CD9FFFF0333
+:10E91000742D2AD4A703000400006AA8BFFFFF03D8
+:10E9200000000015C8006A8C04008018409484A878
+:10E93000020063B8002063E00300638CA9FEFF03BC
+:10E94000CB180AD898FEFF03C9180AD800406018EF
+:10E95000100363A80400A018B093A5A80000638466
+:10E96000020083B8002864E00300638C0400A01850
+:10E97000E893A5A8C4180AD8002884E00300848C72
+:10E9800073FEFF03C5200AD8002823E40500001009
+:10E990000000001588006A8C2CFEFF030100E39D37
+:10E9A0002AFEFF030000E5A900406018040363A8E5
+:10E9B0000000838489200AD80000A3840DFEFF0391
+:10E9C0008A280AD80BFEFF0389180AD8ECFDFF033A
+:10E9D00087180AD800006484007023E40500001042
+:10E9E000000000150200809CC2FDFF037C200AD8B5
+:10E9F00000006484007023E4040000100000A09C68
+:10EA0000BCFDFF037C280AD800006484007023E466
+:10EA1000B7FDFF0F0300609CF4FFFF030400809C20
+:10EA20000000218504004185080081850C00C18516
+:10EA3000004800441000219CF0FF219C004801D4B4
+:10EA4000045001D4086001D40C7001D40040A01817
+:10EA50000403A5A8000043A90000E09D0000658410
+:10EA60000000809C002023E43F0200100100609C15
+:10EA70007C180AD87C00AA8D0000A09CFF00CDA4C1
+:10EA8000002826E4030000100100609C141C4AD4F6
+:10EA900014146A84002823E4030000100100809C01
+:10EAA00008214AD408118A840100609C001824E4DB
+:10EAB00006000010002826E4290200100000609CD7
+:10EAC0000000A09C08294AD444036A84FF00ADA436
+:10EAD0000400809C0100639C002005E40B000010F2
+:10EAE000441B0AD41A008A8C0000609C001804E4BD
+:10EAF000050000100000809C00406018200363A8FF
+:10EB00000000838487200AD8FF008DA40200609C47
+:10EB1000001804E4050000100000001540036A849A
+:10EB20000100639C401B0AD41800CA8C0000809C22
+:10EB3000003004E4080200100100A09C19006A8C57
+:10EB4000002003E4060000100100609C1C008A8C79
+:10EB5000001804E4F901000C0000001500406018E2
+:10EB6000080363A80000838488200AD846006A8CC2
+:10EB70000100A09C002823E42D000010FF008DA4BC
+:10EB800000408018040384A8000064848C180AD80C
+:10EB9000FF0063A4002823E42400001000000015F7
+:10EBA00019006A8C002823E4DC010010FF0066A431
+:10EBB000002823E4040000100200E09D8A006A8C13
+:10EBC0000200E39D0000009D007888E51800000C1D
+:10EBD000FF008DA40040601948036BA90040201974
+:10EBE000380329A9B800AA9CA000EA9C9000CA9CFE
+:10EBF00000006B840100089D00008B84002007D476
+:10EC0000001806D4000089840400C69C0400E79C18
+:10EC100000006984F827E5DF001805DC007888E546
+:10EC2000F4FFFF130200A59CFF008DA40400609C6C
+:10EC3000001824E4E001000C8B780AD80040C018CA
+:10EC40000403C6A80040A0181403A5A80000668409
+:10EC5000C0180AD800008684C1200AD80800809C09
+:10EC600000006584C8180AD8FF0063A4002043E4AC
+:10EC7000A80100100000A09C00006684C9180AD8F2
+:10EC80004E00AA8C0100609C001825E407000010CB
+:10EC90000000609C00406018040363A800008384A7
+:10ECA000CA200AD80000609C001805E492010010F8
+:10ECB00000000015C8006A8CCB180AD80100C09C5F
+:10ECC00012006A8C003023E407000010FF008DA4BE
+:10ECD00000406018080363A800008384CC200AD891
+:10ECE000FF008DA40000A09C002824E40300001075
+:10ECF0000000009D000006A90300E09C003824E409
+:10ED0000030000100000609C000066A8041868E082
+:10ED1000002803E473000010003024E40040C01811
+:10ED20000080C6A800406018080463A8003806D414
+:10ED300000008384002804E40D0000100500609C9E
+:10ED40000000A09C742D2AD400006684100083A4C7
+:10ED5000200063A4002803E45F00000C002804E402
+:10ED6000FAFFFF13000000150500609C0040C0186A
+:10ED70000080C6A80000809C001806D400406018DF
+:10ED8000080463A80000A384002005E40C00001020
+:10ED90000000001574252AD40000A09C00006684A1
+:10EDA000100083A4200063A4002803E44700000CA3
+:10EDB000002804E4FAFFFF13000000154D008A8CC0
+:10EDC0000100609C001824E4260000100800609CEC
+:10EDD000CB008A8C001844E4220000100000A09CA4
+:10EDE00000408018040384A800006484002823E401
+:10EDF0002F000010000000150000809CCD200AD8D4
+:10EE0000CD008A8C0300609C001824E415000010DB
+:10EE10000900A09C0040C0180080C6A800406018EF
+:10EE2000080463A8002806D40000809C0000A38486
+:10EE3000002005E40B0000100000A09C74252AD4DB
+:10EE400000006684100083A4200063A4002803E46B
+:10EE50001400000C002804E4FAFFFF130000001562
+:10EE60003402000400006AA84202000400006AA8FC
+:10EE700000406018040363A84B00AA8C0000838440
+:10EE80000000609C001805E44B010010D0200AD857
+:10EE900013FCFF0700006AA84701000000000015EE
+:10EEA0005900609CEFFFFF03741D2AD400006484A6
+:10EEB000002823E4D2FFFF130300809C0200A09CE3
+:10EEC000D0FFFF03CD280AD85900A09CBCFFFF0348
+:10EED000742D2AD45900809CA4FFFF0374252AD4E2
+:10EEE000700000100200609C4A006A8C003023E42D
+:10EEF0006800000C0000609CD3180AD874008A8C4B
+:10EF00000100609C001824E45E00000C0000809C5E
+:10EF1000D4200AD800406018040363A8000083844A
+:10EF2000D5200AD80000809C00006384002003E400
+:10EF300052000010FFFF809C0000A09C0040601861
+:10EF4000180363A8D8280AD800008384D9200AD8D7
+:10EF50000000A384DA280AD80300A09C0040C0184F
+:10EF60000080C6A800406018080463A8002806D4E2
+:10EF70000000809C0000A384002005E40C00001029
+:10EF80000000001574252AD40000A09C00006684AF
+:10EF9000100083A4200063A4002803E43400000CC4
+:10EFA000002804E4FAFFFF13000000150040801958
+:10EFB00008038CA90100C09D00008C84DD200AD8C4
+:10EFC000004080180C0384A800006C84DE180AD866
+:10EFD00000006484DF180AD800008C84D5006A8C95
+:10EFE000007023E404000010E0200AD800006C84C4
+:10EFF000E1180AD84B008A8C0000609C001804E4D9
+:10F000001700000C000000154C006A8C007023E40F
+:10F010000C0000100000001500408018040384A8B4
+:10F0200000006484E2180AD8FF0063A4007023E49F
+:10F03000040000100000001500006C84E3180AD8DA
+:10F04000BC01000400006AA800406018040363A823
+:10F0500000008384D8000000D0200AD8A0FBFF075E
+:10F0600000006AA8EAFFFF034C006A8C5900609C0C
+:10F07000CFFFFF03741D2AD4B8FFFF03D8200AD89E
+:10F08000E001000400006AA8A3FFFF0300000015D0
+:10F09000C801000400006AA89AFFFF0374008A8C6C
+:10F0A000001824E4C40000100700809C0040601891
+:10F0B0000C0363A800006384002003E47F000010B9
+:10F0C000020063B80400A0187893A5A8002883E084
+:10F0D0000300848C0400A0189493A5A8C4200AD827
+:10F0E000002863E00300638CC5180AD8C5006A8C49
+:10F0F000040080181C9484A8020063B8C400AA8C81
+:10F10000002063E04A00CA8C000083840623A5E047
+:10F110000100609C001826E46400000CC6280ADC8C
+:10F120000000A09CD3280AD874008A8C0100609C3F
+:10F13000001824E45900000C0000A09CD4280AD830
+:10F1400000406018040363A80040C0180080C6A8EF
+:10F15000000063840000809C0300609C001806D4BB
+:10F1600000406018080463A80000A384002005E4A0
+:10F170000B0000100000A09C74252AD400006684B7
+:10F18000100083A4200063A4002803E44000000CC6
+:10F19000002804E4FAFFFF13000000150500809C1E
+:10F1A0000040C0180080C6A800406018080463A88A
+:10F1B000002006D40000A3840000809C002005E409
+:10F1C0000B0000100000A09C74252AD40000668467
+:10F1D000100083A4200063A4002803E42900000C8D
+:10F1E000002804E4FAFFFF13000000150040801916
+:10F1F00008038CA94B00AA8C00006C84DD180AD887
+:10F20000004060180C0363A800008C84DE200AD83C
+:10F2100000008384DF200AD800006C84E0180AD83C
+:10F220000000609C00008C84001805E41100000CB4
+:10F23000E1200AD84C006A8C0100A09C002823E43D
+:10F2400080FFFF130000001500408018040384A80D
+:10F2500000006484E2180AD8FF0063A4002823E4B5
+:10F2600078FFFF130000001574FFFF030000001576
+:10F270001BFBFF0700006AA8F0FFFF034C006A8C2D
+:10F280005900809CDAFFFF0374252AD45900609C42
+:10F29000C3FFFF03741D2AD45A01000400006AA8AA
+:10F2A000A8FFFF03000000154201000400006AA847
+:10F2B0009FFFFF0374008A8C00406018100363A84E
+:10F2C0000400A018B093A5A800006384020083B8CE
+:10F2D000002864E00300638C0400A018E893A5A84C
+:10F2E000C4180AD8002884E00300848C80FFFF0340
+:10F2F000C5200AD8C8006A8C04008018409484A8ED
+:10F30000020063B8002063E06CFEFF030300638C1F
+:10F310005CFEFF03C9280AD8002823E4050000107A
+:10F320000000001588006A8C27FEFF030100E39DA2
+:10F3300025FEFF030000E5A900406018040363A850
+:10F340000000838489200AD80000A38408FEFF03FC
+:10F350008A280AD806FEFF0389280AD8160000006A
+:10F3600079180AD800006584002023E40500001005
+:10F37000000000150200809CBFFDFF037C200AD81E
+:10F3800000006584002023E4050000100000001543
+:10F390000000A09CB8FDFF037C280AD8000065840B
+:10F3A000002023E4B3FDFF0F0300609CF3FFFF0385
+:10F3B0000400809C000021850400418508008185AF
+:10F3C0000C00C185004800441000219CFCFF219CDA
+:10F3D000004801D40000C3A8004080180C0384A892
+:10F3E000440363840000E09D0200E09C0000A484CC
+:10F3F0000100639C842806D8FF00A5A4003805E41A
+:10F4000005000010441B06D4400366840100639C81
+:10F41000401B06D48400268EFF00B1A4003845E4CA
+:10F42000030000100100609C141C46D41414668470
+:10F43000007823E4030000100100609C081946D402
+:10F44000081186840100609C001824E40500001067
+:10F45000003845E4030000100000A09C082946D4B1
+:10F460001A00868C0000609C001804E4AC000010B8
+:10F470000000609C00406018200363A800008384A3
+:10F48000872006D81800E68C0000809C003804E431
+:10F49000A10000100100A09C1900668C002003E46C
+:10F4A000060000100100609C1C00868C001804E41B
+:10F4B0009200000C0000001500406018080363A8CB
+:10F4C00000008384882006D84600668C0100A09C3A
+:10F4D000002823E42B0000100000001500408018D5
+:10F4E000040384A8000064848C1806D8FF0063A479
+:10F4F000002823E423000010000000151900668C8A
+:10F50000002823E475000010FF0067A4002823E40E
+:10F51000040000100200E09D8A00668C0200E39D5A
+:10F520000000209D007889E51600000CA000069DD3
+:10F530000040A0194803ADA90040601938036BA929
+:10F54000B800A69C9000E69C00006D840100299DF7
+:10F55000001807D400006D840400E79C00008B8431
+:10F56000001808D4F827E5DF0400089D00006B842C
+:10F57000001805DC007889E5F4FFFF130200A59C64
+:10F580008B7806D800400019040308A90100209DCB
+:10F5900000006884C01806D8000088844700668C84
+:10F5A000004823E44A000010C12006D8FF0071A4DF
+:10F5B0000300809C002043E445000010000000157B
+:10F5C00000406018080363A80000E384002027E4DB
+:10F5D000100000100000809C00406018080463A820
+:10F5E0000000A384002005E40A00001000000015BC
+:10F5F00000006884004803E40600000C00000015C9
+:10F6000000006884004803E4FEFFFF130100E79C4C
+:10F61000C33806D8FF0091A40300609C0018A4E43E
+:10F62000410000100700809C004060180C0363A894
+:10F630000000E384002007E416000010020067B811
+:10F640000400A0187893A5A8002883E00300848C08
+:10F650000400A0189493A5A8C42006D8002863E04D
+:10F660000300638CC51806D8C500668C0400A0187A
+:10F670001C94A5A8020063B8C400868C002863E02F
+:10F680000000A384062B84E027000000C62006DCCF
+:10F6900000406018100363A80400A018B093A5A848
+:10F6A0000000E384020087B8002864E00300638C54
+:10F6B0000400A018E893A5A8C41806D8002884E080
+:10F6C0000300848CE9FFFF03C52006D80000A09C3E
+:10F6D000D1FFFF03C32806D8002823E4050000104B
+:10F6E000000000158800668C8EFFFF030100E39D7B
+:10F6F0008CFFFF030000E5A900406018040363A825
+:10F7000000008384892006D80000A3846FFFFF03D4
+:10F710008A2806D86DFFFF03892806D85AFFFF0301
+:10F72000871806D800002185004800440400219C69
+:10F730000040C0180403C6A8000083A80000A09CD5
+:10F7400000006684002823E40700000C0000609C91
+:10F7500000006684002823E40300000C0100609C84
+:10F760000200609CCE1804D8004800440000001538
+:10F770000040C0180403C6A8000083A80000A09C95
+:10F7800000006684002823E40700000C0000609C51
+:10F7900000006684002823E40300000C0100609C44
+:10F7A0000200609CCF1804D80048004400000015F7
+:10F7B0000040A0180403A5A80000C3A80000809C76
+:10F7C00000006584002023E40B00000C0000609C16
+:10F7D00000006584002023E40700000C0100609C09
+:10F7E00000006584002023E40300000C0200609CFC
+:10F7F0000300609CD31806D80048004400000015A0
+:10F800000040A0180403A5A80000C3A80000809C25
+:10F8100000006584002023E40B00000C0000609CC5
+:10F8200000006584002023E40700000C0100609CB8
+:10F8300000006584002023E40300000C0200609CAB
+:10F840000300609CD41806D800480044000000154E
+:10F850000000A3A80200E09C7C00638C003823E435
+:10F860003D0000100C00609C7B00658C0000C09C7B
+:10F87000003023E40D0000100C00609C0040601874
+:10F88000040363A800008384003024E40300000C18
+:10F890000000609C0100609C5B000000D61805D849
+:10F8A000FEFFFF030000609CCB00858C0018A4E4E1
+:10F8B000170000100100809C00408018040384A8F9
+:10F8C0000100C09C00006484003023E4F3FFFF0FBC
+:10F8D0000000609C00006484003023E404000010F9
+:10F8E0000000001548000000D63005D800006484F0
+:10F8F000003023E40400000C00000015E7FFFF03C4
+:10F900000300609C40000000D63805D80040C018B5
+:10F910000403C6A800006684002023E40C00000C49
+:10F920000000001500006684002023E4DBFFFF0FC9
+:10F930000300609C00006684002023E4F2FFFF0FB8
+:10F940000000609C30000000D61805D82E00000092
+:10F95000D62005D8CB00858C0018A4E41600001032
+:10F960000100809C0040C0180403C6A80000668403
+:10F97000002023E4C9FFFF0F0000609C00006684A4
+:10F98000002023E4F2FFFF0F000000150000668452
+:10F99000002023E4DCFFFF0F000000150000668458
+:10F9A000002023E4D6FFFF1300000015BBFFFF0378
+:10F9B0000400609C0040C0180403C6A800006684D0
+:10F9C000002023E4E2FFFF0F000000150000668422
+:10F9D000002023E4B1FFFF0F0300609C0000668459
+:10F9E000002023E4C8FFFF0F00000015000066841C
+:10F9F000002023E4ABFFFF1300000015A7FFFF0367
+:10FA00000400609C0048004400000015CB00838C7B
+:10FA10000000A3A80C00609C0018A4E418000010CB
+:10FA20000100809C00408018040384A80100C09C51
+:10FA300000006484003023E40D00000C0000609C92
+:10FA400000006484003023E404000010000000156E
+:10FA50001D000000D73005D800006484003023E486
+:10FA60000300000C0200609C0300609C1600000074
+:10FA7000D71805D8FEFFFF030000609C0040C018A7
+:10FA80000403C6A800006684002023E404000010DC
+:10FA9000000000150C000000D72005D80000668487
+:10FAA000002023E4F2FFFF0F0300609C0000668447
+:10FAB000002023E4F0FFFF1300000015ECFFFF031C
+:10FAC0000200609C0048004400000015FCFF219CDF
+:10FAD000004801D4000003A90040C0180803C6A8CC
+:10FAE0000040A0180C03A5A800006684004020195F
+:10FAF000040329A90040E0183003E7A80D1808D82E
+:10FB00000000609D000085840E2008D800006684F7
+:10FB10000F1808D800406018140363A800008584FB
+:10FB2000102008D800008384112008D800006984C0
+:10FB3000121808D80000A7840000C7840000698458
+:10FB4000181808D800008984192008D80000698492
+:10FB50001A1808D8000089841B2008D80000E984FE
+:10FB6000000069841C1808D800008984142808DC67
+:10FB7000FF0064A4163008DC005803E4680000109D
+:10FB80001D2008D800406018380363A80000A38433
+:10FB90000000C384000089841E2808DCFF0064A4E0
+:10FBA000203008DC005803E45A000010222008D856
+:10FBB00000406018100363A800008384232008D845
+:10FBC0000F00609CFF0084A4001824E408000010CB
+:10FBD0000000001500406018200363A80000838423
+:10FBE000242008D80000A384252808D800408018C5
+:10FBF000040384A80000A09C00006484002803E49F
+:10FC0000090000100000001500006484002823E4AF
+:10FC10003C0000100000001500406018300363A88D
+:10FC20000000638400406018040363A80000809C07
+:10FC30000000A384002005E4070000100000001568
+:10FC400000406018600363A80000638400406018EF
+:10FC5000040363A800008384262008D80000609C69
+:10FC6000FF0084A4001804E4140000100000A09C0D
+:10FC700000406018140363A8000083840C00639C98
+:10FC8000272008D8FF0084A400006384002085E5B5
+:10FC90000A00000C000000150040C0184003C6A870
+:10FCA000000066840100A59C00006684002085E5B4
+:10FCB000FCFFFF13000000151900688C0000809CF9
+:10FCC000002023E4030000100000A09C0100A09C81
+:10FCD00014006894002003E406000010602D28D46E
+:10FCE00016006894002023E40400001000000015B2
+:10FCF0000E0000000000609C0C0000000100609CF1
+:10FD000000406018400363A8C6FFFF030000001511
+:10FD10000000609CB6FFFF03231808D80000609C19
+:10FD2000CBFFFF03221808D80C1808D80000218543
+:10FD3000004800440400219CE8FF219C004801D4B5
+:10FD4000045001D4086001D40C7001D4108001D497
+:10FD5000149001D4000046A9000003AA000044AAA0
+:10FD6000000085A9000065A8000086A8DE18FF072E
+:10FD700041004AB90000CBA900008AA8DA18FF07A1
+:10FD800000006CA80080AEE4030000100000809C1E
+:10FD90000100809C0090ABE4030000100000609C18
+:10FDA0000100609C041864E00000809C002003E4D3
+:10FDB0000400001000806EE40E0000000200609D50
+:10FDC000030000100000A09C0100A09C00906BE4C8
+:10FDD000030000100000609C0100609C041865E0B6
+:10FDE000002003E40300000C0300609D0000609D00
+:10FDF0000000218504004185080081850C00C18533
+:10FE00001000018614004186004800441800219C1F
+:10FE1000ECFF219C004801D4045001D4086001D4B7
+:10FE20000C7001D4108001D40040A0180403A5A8D0
+:10FE3000000043A9000085840040C0180803C6A83C
+:10FE40000000009E442003D80000658445180AD8AD
+:10FE50000000858446200AD80000658447180AD827
+:10FE60000000858448200AD80000658449180AD813
+:10FE7000000085844A200AD8000066844B180AD8FE
+:10FE8000000085844C200AD8000065844D180AD8EB
+:10FE90000100609C000086842600AA8C001825E4DE
+:10FEA0000C0000104E200AD82700AA8C002890E5EC
+:10FEB0000800000C0000809C1800C69C00006684AE
+:10FEC0000100849C002884E5FDFFFF13000000155D
+:10FED00000406018040363A80000809C0000A38415
+:10FEE000002005E45F0000102C00639C14008A943D
+:10FEF000000083850000C38500204CE5060000104B
+:10FF00000000001516006A9400184EE50300000C6E
+:10FF1000000000150100009E70006A940000809CA3
+:10FF2000002003E412000010000000157200AA94E3
+:10FF3000002005E40E00001000182CE4040000105E
+:10FF400000282EE40B00000CFFFF6CA40100AC9C09
+:10FF50000100CE9C0100A5B80100C6B8F8106A8463
+:10FF600076FFFF07FC108A8400594AD4FFFF6CA477
+:10FF7000FFFF8EA4010063B8010084B84A00AA8C78
+:10FF80000200639C0200849C841D2AD480252AD40C
+:10FF900070600ADC0000609C001805E42E00001070
+:10FFA00072700ADC00406018040363A800008384B8
+:10FFB00074200AD800406018040363A80000809CE5
+:10FFC0000000A384002005E4200000100000609CD5
+:10FFD0000100609C75180AD8004060180C0363A8E3
+:10FFE0000000838476200AD800406018040363A8C8
+:10FFF0000000809C0000A384002005E41000001095
+:020000024000BC
+:100000000000609C0100609C77180AD800406018CE
+:100010000C0363A80000838478200AD80000609C49
+:10002000001830E40400001000000015100000006B
+:100030000100609C0E0000000000609C77180AD848
+:10004000F7FFFF0378180AD875180AD8E7FFFF03EF
+:1000500076180AD80000609CD7FFFF0374180AD8EE
+:1000600014008A95ADFFFF031600CA953C180AD804
+:100070000000218504004185080081850C00C185B0
+:1000800010000186004800441400219CF8FF219CC8
+:10009000004801D4045001D48500838C000043A99A
+:1000A0000000609C001824E471010010000000159D
+:1000B00084006A8C04008018C09484A8020063B88D
+:1000C000002063E00300638C7C180AD800406018AD
+:1000D000140363A800008384C8200AD80800609C29
+:1000E000FF0084A4001844E45F0100100000609C3D
+:1000F00000406018040363A800008384C9200AD864
+:100100004E00AA8C0100609C001825E40700001036
+:100110000000609C00406018040363A80000838412
+:10012000CA200AD80000609C001805E446010010AF
+:1001300000000015C8008A8CCB200AD812006A8CF7
+:100140000100009D004023E406000010000000159F
+:1001500000406018080363A800008384CC200AD8FC
+:100160007C00AA8C0200609D005805E40500001088
+:100170000000209D40036A840100639C401B0AD458
+:100180000000C09C003025E403000010000085A89A
+:10019000000028A90300E09C003824E403000010BC
+:1001A0000000609C000068A8041869E0003003E4C7
+:1001B0005C000010004024E40040A0180080A5A8C6
+:1001C00000406018080463A8003805D40000838448
+:1001D000003004E40D0000100000609C0000C5A881
+:1001E000741D2AD40000A09C00006684100083A423
+:1001F000200063A4002803E44700000C002804E466
+:10020000FAFFFF13000000154D008A8C0100609C6E
+:10021000001824E4260000100800609CCB008A8CA3
+:10022000001844E4220000100000A09C0040801848
+:10023000040384A800006484002823E42F00001035
+:10024000000000150000809CCD200AD8CD008A8CCB
+:100250000300609C001824E4150000100500809C39
+:100260000040C0180080C6A800406018080463A8B9
+:10027000002006D40000A3840000809C002005E438
+:100280000B0000100000A09C74252AD40000668496
+:10029000100083A4200063A4002803E41400000CD1
+:1002A000002804E4FAFFFF130000001521FDFF07FA
+:1002B00000006AA82FFDFF0700006AA80040601830
+:1002C000040363A84B00AA8C000083840000609C98
+:1002D000001805E4EA000010D0200AD800F7FF0754
+:1002E00000006AA8E6000000000000155900809C8C
+:1002F000EFFFFF0374252AD400006484002823E460
+:10030000030000100300609C0200609CD0FFFF030C
+:10031000CD180AD85900609CBCFFFF03741D2AD475
+:100320008D000010005825E400408018040384A8C4
+:1003300000006484D1180AD8FF0063A4003023E4CD
+:10034000030000100000609C00006484D2180AD8EA
+:100350000100609C4A008A8C001824E47A00000C9A
+:10036000000000150000809CD3200AD874008A8CFD
+:100370000100609C001824E46F00000C0000609CE9
+:10038000D4180AD833FDFF0700006AA8D600CA8C2B
+:100390000400609C003023E44400000CFFFF809CBC
+:1003A000D8200AD80040E0180C03E7A8D1006A8CD6
+:1003B0000100A09C00008784002823E43600001080
+:1003C000DD200AD800006784DE180AD800406018D3
+:1003D0000C0363A8FF00A6A4000083840300609CB4
+:1003E000001805E407000010DF200AD8D6008A9420
+:1003F0000304609C001804E40600000C00000015D3
+:1004000000406018080363A800008384E1200AD834
+:100410004B008A8C0000609C001804E41A00000C59
+:10042000000000154C006A8C0100A09C002823E409
+:100430000E0000100000001500408018040384A87E
+:1004400000006484E2180AD8FF0063A4002823E4B3
+:10045000060000100000001500406018080363A8A3
+:1004600000008384E3200AD8B2FCFF0700006AA8DA
+:1004700000406018040363A800008384800000002B
+:10048000D0200AD896F6FF0700006AA8E7FFFF030E
+:100490004C006A8C00406018080363A80000838445
+:1004A000CBFFFF03DE200AD859FDFF0700006AA832
+:1004B0000040A0180403A5A80100809C00006584EA
+:1004C000002023E416000010000000150000809CAE
+:1004D000D8200AD80040C0181803C6A8D800AA8C93
+:1004E00000006684D9180AD80000609C0000868449
+:1004F000001825E408000010DA200AD800006684FD
+:10050000DB180AD800008684D600CA8CA6FFFF0339
+:10051000DC200AD8A4FFFF03D600CA8C0000658443
+:10052000002023E4EBFFFF130200609CEAFFFF03BF
+:10053000D8180AD8B3FCFF0700006AA892FFFF038F
+:10054000000000159BFCFF0700006AA889FFFF035D
+:1005500074008A8C4A000010000000154A006A8C62
+:10056000004023E43400000C0000609CD3180AD83B
+:1005700074008A8C0100609C001824E42A00000C9E
+:100580000000609CD4180AD8B2FCFF0700006AA8DB
+:100590000300809C0040C0180080C6A8004060187E
+:1005A000080463A8002006D40000A3840000809CF7
+:1005B000002005E40B0000100000A09C74252AD444
+:1005C00000006684100083A4200063A4002803E4D4
+:1005D0001200000C002804E4FAFFFF1300000015CD
+:1005E0000040A0180C03A5A8D600CA8C00006584A2
+:1005F000DD180AD800008584DE200AD80300809C1C
+:1006000000006584002026E482FFFF13DF180AD86B
+:100610007CFFFF03000000155900809CF1FFFF03E1
+:1006200074252AD477FCFF0700006AA8D7FFFF03D0
+:10063000000000155FFCFF0700006AA8CEFFFF0363
+:1006400074008A8CC8006A8C04008018409484A8C6
+:10065000020063B8002063E00300638CB8FEFF0370
+:10066000CB180AD8A7FEFF03C9180AD804008018BF
+:10067000E09484A892FEFF0384006A8C0000218528
+:1006800004004185004800440800219CF4FF219C9F
+:10069000004801D4045001D4086001D40000C3A86C
+:1006A0000200809C70006394010063B87B00A68CFC
+:1006B000002025E4050000100200839D720066946E
+:1006C000050000000100439D72006694010063B8BC
+:1006D0000200439D00006CA89003000400008AA85B
+:1006E00000406018180863A8004080181C0884A8FF
+:1006F000006003D4005004D400002185040041852B
+:1007000008008185004800440C00219CF8FF219CD2
+:10071000004801D4045001D4000043A90100C09C4A
+:100720000000609C89180AD88A180AD888180AD844
+:1007300019006A8C003023E42B0000100000609C3C
+:1007400000408018040384A80000A09C000064847A
+:10075000002823E42400000C0000609C0000648456
+:10076000002823E41F000010000000157B300AD889
+:100770000200609C80180AD4C5FFFF0700006AA829
+:10078000FFFF609C7B008A8CD8180AD80000609C10
+:10079000001824E40F00000C0100609C001824E401
+:1007A0000600001000000015A4F8FF0700006AA86A
+:1007B0000F0000000000001505FBFF0700006AA8FD
+:1007C00033FEFF0700006AA80900000000000015C2
+:1007D00039F6FF0700006AA80500000000000015B8
+:1007E0000200609CE3FFFF037B180AD8000021850C
+:1007F00004004185004800440800219CECFF219C36
+:10080000004801D4045001D4086001D40C7001D414
+:10081000890D038D000083A90000409D0000C09D4C
+:1008200000402EE40B000010000088A80040601873
+:10083000000363A80000C385C500609CFF00CEA52F
+:1008400000182EE4030000100000C09D0100C09DB0
+:10085000FF0084A40000609C001824E40B0000103A
+:100860000500809C00406018200363A80000A3845A
+:10087000002025E4A700000C0000809C00406018C8
+:10088000600363A8000083840040C0180803C6A862
+:100890000040E0180C03E7A8000066840040A018A0
+:1008A0000403A5A8FF0008A50D180CD80000209D82
+:1008B0000000668429180CD800406018140363A84F
+:1008C0000000878410200CD80000838411200CD8ED
+:1008D0000000658448180CD8000085842A200CD8B4
+:1008E000000065842B180CD8000085842C200CD8BF
+:1008F0000000658449180CD8000085844A200CD873
+:10090000000066844B180CD8000085844C200CD85D
+:10091000000065842D180CD8000085844D200CD86B
+:10092000000065842E180CD8000085842F200CD878
+:100930000000678430180CD8000086844E200CD844
+:10094000000065841B180CD800008584004828E44A
+:100950006700001031200CD800480AE405000010A0
+:100960000000001500406018200363A80000838485
+:100970000040E0182003E7A81000019D0000278533
+:10098000004808D8FF0029A50000A784012808D83E
+:10099000FF00A5A4000067840800A5B8021808D8C5
+:1009A000FF0063A400008784100063B8032008D808
+:1009B000180084B800004785001884E0005008D86B
+:1009C000002884E0FF004AA50000C784004884E0B6
+:1009D000013008D8FF00C6A40000A7840800C6B8EC
+:1009E000022808D8FF00A5A4000027851000A5B89C
+:1009F000180069B834200CD4002863E0034808D8F4
+:100A0000003063E0005063E038180CD438008C8468
+:100A100004006018377E63A8D806FF0734004C85B1
+:100A2000040060183F7E63A8D406FF0700008AA870
+:100A300038008C840000E09C84252CD4890D6C8CBB
+:100A400034008C8480252CD40100809C60252CD41B
+:100A5000003823E4030000100000809C0100809C0B
+:100A60000100009D00402EE4030000100000609C87
+:100A7000000068A8031864E0003803E410000010C8
+:100A8000000000150040A0180003A5A80040601851
+:100A9000600363A8000085840000C38400408018C0
+:100AA0000C0384A8000064840800849C0E180CD8F1
+:100AB000000064840000C5840000658438006C84F4
+:100AC000003803E4060000100000609C34006C84D1
+:100AD000003823E4040000100000609C13000000B4
+:100AE00028180CD81100000028400CD800406018CD
+:100AF000082063A800408018042084A800006384B4
+:100B00000000848438180CD4C1FFFF0334200CD4B7
+:100B100004006018477E63A89806FF070100409D07
+:100B200057FFFF03890D0C8D0000218504004185CE
+:100B3000080081850C00C185004800441400219CF8
+:100B4000FCFF219C004801D4F400838C0000209D10
+:100B50003400C384020004A5380063848100A6B871
+:100B6000010084A48100E3B8004804E405000010FB
+:100B70000F00A59C0F00679CF0FF809C032063E0A2
+:100B8000004808E403000010F0FF809C0320C5E04B
+:100B900062020004000086A800408018200884A893
+:100BA0000040A0182408A5A800006484040063B8CD
+:100BB00000408018180884A8001804D40000658438
+:100BC0000400849C040063B8001804D4000021854C
+:100BD000004800440400219CF4FF219C004801D4FB
+:100BE000045001D4086001D4000043A90100809C96
+:100BF0000000609C0000E09CD8180AD80040A018B3
+:100C00000404A5A80100609C80200AD489180AD891
+:100C10000000C09C0200609C7B380AD800008584DC
+:100C2000001804E4070000100400809C0000858484
+:100C30000300609C001804E40400000C0400809C85
+:100C4000310200007C200AD844036A840100639CBE
+:100C50001B008A8C003004E406000010441B0AD4F8
+:100C600000406018040363A800008384C2200AD8EF
+:100C700000408018080384A82F006A8C0000A48418
+:100C8000003003E41D020010F1280AD8004060186B
+:100C9000040363A800008384F2200AD80040C0182F
+:100CA0000403C6A80100609C0000A684001825E487
+:100CB0000E02000C0000809C30006A8C002023E4AF
+:100CC000050200100000E09C7C380AD808116A84F4
+:100CD0000000809C002003E4FD01001000000015CE
+:100CE0007C00CA8C003024E40300001000000015D2
+:100CF00008214AD4FF0086A40200A09C002804E436
+:100D0000050000100000001540036A840100639C88
+:100D1000401B0AD4002824E41D000010FF0086A414
+:100D2000004060180C0363A80700809C0000A384A7
+:100D3000002005E4D1010010020065B80400E018AD
+:100D40009493E7A80400A0187893A5A8002883E04E
+:100D50000300848C003863E0C4200AD80300638C4D
+:100D6000C5180AD8C5006A8C0400A0181C94A5A850
+:100D7000020063B8C4008A8C002863E00000A384EA
+:100D8000062B84E0C6200ADCFF0086A40000E09C5D
+:100D9000003824E4030000100000009D0100009DC5
+:100DA0000300609C001824E4030000100000A09CD5
+:100DB0000100A09C042868E0003803E4A8010010AA
+:100DC0000100609C0100E09CC0380AD8FF0086A4A6
+:100DD0000000609C001824E4510000100300609C97
+:100DE000004060181C0363A80040A0181403A5A8C5
+:100DF00000008384F3200AD80800809C00006584EA
+:100E0000C8180AD8FF0063A4002043E44200001081
+:100E10000000609C00406018040363A80000838405
+:100E2000C9200AD84E00AA8C0100609C001825E455
+:100E3000070000100000609C00406018040363A8D5
+:100E400000008384CA200AD80000609C001805E4D2
+:100E50002900001000000015C8008A8CCB200AD899
+:100E60000000609CCB00EA8CEC180AD8EB180AD87A
+:100E70000000609C4A008A8C001804E41A00000CF0
+:100E8000E6380AD80000809CD3200AD82B008A8C30
+:100E90000100609C001824E4110000100000A09CD8
+:100EA00000406018080363A800008384F4200AD877
+:100EB00020FAFF0700006AA82EFAFF0700006AA8C0
+:100EC00020FFFF0700006AA800406018040363A821
+:100ED000000083848C010000D0200AD8F5FFFF03B6
+:100EE000F4280AD833FAFF0700006AA8E9FFFF03D5
+:100EF0002B008A8CC8006A8C0400A0184094A5A816
+:100F0000020063B8002863E00300638CD5FFFF0391
+:100F1000CB180AD8C4FFFF03C9180AD8001824E464
+:100F20003B0000100100609C004060181C0363A897
+:100F30000040A0181403A5A800008384F3200AD859
+:100F40000800809C00006584C8180AD8FF0063A4CC
+:100F5000002043E42C0000100000E09C00406018DA
+:100F6000040363A800008384C9200AD84E00AA8C19
+:100F70000100609C001825E4070000100000609C40
+:100F800000406018040363A800008384CA200AD8C4
+:100F90000000609C001805E414000010000000151B
+:100FA000C8006A8CCB180AD80000E09C0000609C46
+:100FB000CB00AA8C4A008A8CE6280AD8EC380AD8DA
+:100FC000001804E40500000CEB380AD80000609C0F
+:100FD000B8FFFF03D3180AD8F6F9FF0700006AA884
+:100FE000B4FFFF0300000015C8006A8C04008018DD
+:100FF000409484A8020063B8002063E0EAFFFF0386
+:101000000300638CDAFFFF03C9380AD8001824E410
+:10101000A90000100200609C00406018140363A83F
+:1010200000008384C8200AD80800609CFF0084A4C4
+:10103000001844E4050000100000809C0040601887
+:10104000040363A8000083844E00AA8C0100609C06
+:10105000001825E406000010C9200AD800406018D6
+:10106000040363A800008384CA200AD80000609C9F
+:10107000001805E48800001000000015C800AA8CC4
+:10108000CB280AD84A008A8C0000609C001804E42F
+:101090007D00000C0000609CD3180AD82B008A8CBD
+:1010A0000100609C001824E4050000100000809CF2
+:1010B00000406018080363A800008384F4200AD865
+:1010C000A0FEFF0700006AA8E2F9FF0700006AA877
+:1010D000D600CA8C0400609C003023E45E00000C43
+:1010E000FFFF809CD8200AD8FF0066A40300A09CC4
+:1010F000002803E4060000100304609CD6008A94D4
+:10110000001804E41700000C000000150040C0188F
+:101110000080C6A800406018080463A8002806D410
+:101120000000809C0000A384002005E40E00001055
+:101130000500A09C0000E6A874252AD40000C09CED
+:101140000000A784200065A4003003E43F00000CE9
+:10115000100085A4003004E4FAFFFF13000000151E
+:101160000500A09C0040C0180080C6A80040601880
+:10117000080463A8002806D40000809C0000A38413
+:10118000002005E40D000010000000150000E6A896
+:1011900074252AD40000C09C0000A784200065A408
+:1011A000003003E42600000C100085A4003004E4A5
+:1011B000FAFFFF13000000150040801908038CA9F6
+:1011C0004B00AA8C00006C84DE180AD80000609CDA
+:1011D00000008C84001805E41500000CDF200AD8FC
+:1011E0004C006A8C0100A09C002823E40C00001035
+:1011F0000000001500408018040384A800006484E7
+:10120000E2180AD8FF0063A4002823E404000010B9
+:101210000000001500006C84E3180AD845F9FF07A8
+:1012200000006AA829FFFF03000000152CF3FF0748
+:1012300000006AA8ECFFFF034C006A8C5900609C18
+:10124000DEFFFF03741D2AD45900E09CC5FFFF0395
+:10125000743D2AD40000A09C00006AA8ECF9FF07A6
+:10126000D8280AD800406018180363A8D600CA8C92
+:1012700000008384D9200AD80000A3849BFFFF03C9
+:10128000DA280AD84BF9FF0700006AA885FFFF0398
+:101290002B008A8CC8006A8C0400E0184094E7A8F0
+:1012A000020063B8003863E00300638C76FFFF033D
+:1012B000CB180AD8001824E404FFFF13000000151F
+:1012C00000406018140363A800008384C8200AD873
+:1012D0000800609CFF0084A4001844E45E00001035
+:1012E0000000E09C00406018040363A800008384B1
+:1012F000C9200AD84E00AA8C0100609C001825E481
+:10130000070000100000609C00406018040363A800
+:1013100000008384CA200AD80000609C001805E4FD
+:101320004600001000000015C8006A8CCB180AD8CF
+:101330000000609C4A008A8C001804E43B00000C0A
+:101340000000609CD3180AD842F9FF0700006AA881
+:10135000FCFDFF0700006AA80300809C0040C01845
+:101360000080C6A800406018080463A8002006D4C6
+:101370000000A3840000809C002005E40E00001003
+:101380000500A09C0000E6A874252AD40000C09C9B
+:101390000000A784200065A4003003E42000000CB6
+:1013A000100085A4003004E4FAFFFF1300000015CC
+:1013B0000500A09C0040C0180080C6A8004060182E
+:1013C000080463A8002806D40000809C0000A384C1
+:1013D000002005E479FFFF13000000150000E6A8D7
+:1013E00074252AD40000C09C0000A784200065A4B6
+:1013F000003003E40700000C100085A4003004E472
+:10140000FAFFFF13000000156CFFFF03000000153A
+:101410005900E09C69FFFF03743D2AD45900A09C49
+:10142000E4FFFF03742D2AD4E2F8FF0700006AA846
+:10143000C6FFFF0300000015C8006A8C0400801876
+:10144000409484A8020063B8002063E0B8FFFF0363
+:101450000300638CA8FFFF03C9380AD8001824E4EE
+:101460005CFEFF13FF0086A4C0006A8C010063AC21
+:1014700058FEFF03C0180AD800408018100384A843
+:101480000400E018B093E7A80000A484020065B847
+:10149000003883E00300848C0400E018E893E7A898
+:1014A000C4200AD8003863E00F00809C0300638CDE
+:1014B000002025E42CFEFF13C5180AD80300609C09
+:1014C0000300C09C28FEFF037C180AD80AFEFF0315
+:1014D0007C00CA8C0000A684002025E405000010D2
+:1014E0000000809C0200609CF9FDFF037C180AD874
+:1014F000F7FDFF037C200AD80000A09CE8FDFF0355
+:10150000F2280AD800002185040041850800818561
+:10151000004800440C00219CF8FF219C004801D4A5
+:10152000045001D40F00849C0300409D8400E4B863
+:101530000040A0182408A5A80F00639C095307E1E8
+:10154000003805D4850084B80040A0180C80A5A8F8
+:10155000840023B90100C4B8002005D4850063B815
+:101560000230C7E000408018108084A8003004D406
+:101570000400849C0100C3B8095349E10100A8B8E4
+:10158000004004D40230C9E00040A5E00400849C7F
+:101590000228E7E00040A0182008A5A8003804D4DD
+:1015A000004805D40400849C001804D4004060184E
+:1015B000208063A801008AB8003003D40400639C33
+:1015C000005084E0005003D4022029E10400639C11
+:1015D000004803D4000021850400418500480044F0
+:1015E0000800219CF8FF219C004801D4045001D43C
+:1015F000000044A90000C3A8800084840000209D4E
+:101600000000009D0100609C001844E40600000CEE
+:10161000000064A90200609C001824E4040000108B
+:10162000000000154B000A8D4E002A8D80008A8430
+:1016300000406018300863A8002003D47B008A8C27
+:101640000000609C001824E40B0300100100A09C23
+:1016500000406018380863A80000809C002003D474
+:10166000004080183C0884A80000609C001804D446
+:101670007C00AA8C00408018340884A8002804D478
+:1016800086006A8C0C00849CFFFF63AC001804D4B5
+:101690008900AA8C004060181C0C63A80B00809C79
+:1016A000002803D4002026E4EE0200100000809CF5
+:1016B0000000609C85008A8C001804E4060000107D
+:1016C000EE00AA9400406018240863A800008384F8
+:1016D0000220A5E000406018280863A8002803D471
+:1016E000CE00AA8C0000609C001825E408000010C1
+:1016F000000085A8C8008A8C0800609C0018A4E43B
+:101700000300000C0300809C000085A800406018C6
+:101710002C8063A80000C09C002003D40000A09C83
+:101720007C008A8C002824E4030000100300E09C65
+:101730000100C09C003824E4030000100000609CFD
+:101740000100609C041866E0002803E4BE0200105B
+:1017500000000015CF00CA8C002826E40800001005
+:10176000000086A8C8008A8C0800609C0018A4E4C9
+:101770000300000C000087A8000086A80040601845
+:10178000308063A8002003D4D000AA8C00406018E9
+:10179000348063A800408018388084A8002803D4CF
+:1017A000004004D40000609C001808E4A20200106D
+:1017B00000000015EC008A8C004060183C8063A893
+:1017C000002003D40000A09CCB006A8C004080184D
+:1017D000408084A8001804D4002808E49402001073
+:1017E00000000015E6008A8C00406018448063A861
+:1017F000002003D4C8008A8C00406018488063A889
+:10180000002003D4C900AA8C0400639C0000809CC3
+:10181000002803D4002009E47B0200100800609C2B
+:101820000100609C001809E475020010000000151A
+:10183000FEFF899C00406018040C63A8002003D4BC
+:101840000000609C001808E4690200100000001508
+:10185000EB008A8C00406018508063A8002003D4FD
+:101860000100609C00182BE40500000C0200609C45
+:1018700000182BE406000010000000154C008A8CB4
+:1018800000406018548063A8002003D4E2008A8CD2
+:1018900000406018588063A8002003D4E300AA8C9D
+:1018A0000400639C002803D4C0008A8C00406018A8
+:1018B000000C63A8002003D4D300AA8C0040601859
+:1018C000608063A8002803D4D4008A8C0400639C41
+:1018D000002003D40E0CFF0700000015D80E8A84E8
+:1018E0000000C09C003024E4030000100000E09CD5
+:1018F0000100E09C0200609C001824E4030000103A
+:101900000000A09C0100A09C042867E0003003E4D4
+:1019100007000010FFFF649C7C006A8C0100C09CE3
+:10192000003023E40B00000CFFFF649C0100C09C0E
+:10193000003043E424020010000000157C008A8C73
+:101940000200609C001824E41F0200100000001533
+:1019500000408018000A84A80040A0185408A5A8D8
+:10196000003004D400006584043063E0001805D41E
+:101970007C006A8C0100A09CFF00639CFF0063A4B4
+:10198000002843E4030200100000809C7B006A8C66
+:10199000002803E4F601001000000015D6008A8C30
+:1019A0000400609C001824E4E3010010000000150E
+:1019B000D7006A8C00408018688084A8001804D47E
+:1019C000D7006A8C0000809C002003E40300001014
+:1019D00000000015000085A800406018440863A8B6
+:1019E000002003D4D7008A8C010084AC004060182A
+:1019F0006C8063A8010084A4002003D44602000484
+:101A000000006AA8D5008A8C00406018708063A826
+:101A1000002003D480006A850400639CDD00AA8C4A
+:101A2000002803D4DE008A8C0400639C002003D4C9
+:101A3000DF008A8C0400639C002003D4E000AA8CA1
+:101A40000400639C0100809C002803D4E100CA8C40
+:101A50000400639C003003D400202BE40500000C3C
+:101A60000200609C00182BE4060000100000001526
+:101A700049008A8C00406018888063A8002003D445
+:101A80007C006A8C0200809C002023E49C010010F2
+:101A9000000000157B006A8C002023E495010010F3
+:101AA0000000A09C86008A8C0000609C001824E442
+:101AB0008D01001000000015C8056A840400838CA5
+:101AC0000100609C001824E40300001000000015D1
+:101AD0000000A3A8004060188C8063A8C6008A9408
+:101AE000002803D400406018908063A80000A09CE8
+:101AF000002003D4C4006A8CC5008A8C010063B83E
+:101B0000001844E503000010000000150100A09C2F
+:101B100000406018948063A8002803D44D008A8C8C
+:101B20000200009D7C00AA8C004025E40300001008
+:101B30000000E09C0100E09C0000C09C003024E418
+:101B4000030000100000609C0100609C041867E026
+:101B5000003003E46001000C00000015CB008A8C0B
+:101B60000800609C0018A4E445010010003025E442
+:101B700000406018988063A8004003D47B008A8CE2
+:101B80000200609C001824E43901001000000015D8
+:101B9000C3008A8C004060189C8063A8002003D496
+:101BA0007C008A8C0100609C001824E4260100104F
+:101BB000000000157B008A8C0200609C001824E461
+:101BC0002101001000000015D1008A8C004060182F
+:101BD000A08063A8002003D4D200AA8C0400639CD8
+:101BE000002803D47C006A8C0200809C002023E43F
+:101BF0000F010010000000157B006A8C002023E418
+:101C00000B01001000000015C8058A84C6006A9404
+:101C10000E00A48C062B63E0880083B80220A5E0A8
+:101C20000000609CFFFFA59C001865E50400001003
+:101C3000080065B80000A09C080065B8002063E0BB
+:101C400000408018A88084A8001804D47B006A8C07
+:101C50000200A09C002823E4BC0000100000001536
+:101C60007C008A8C002025E42D000010FF0084A455
+:101C70000801AA84020085B8C805EA840050A4E0DF
+:101C8000FC04658400408018040B84A87C04C5848F
+:101C9000080063B8003063E0001804D40000A78C8B
+:101CA00000406018B88063A8002803D485008A8C9F
+:101CB0000000609C001824E487000010FFFF609C77
+:101CC0000C01EA84020067B80050A3E0CC05EA8466
+:101CD000FC0485847C04C584180064B81000A6B890
+:101CE000080084B8002863E0002063E0004080180A
+:101CF000000B84A8003063E0001804D40100A78C16
+:101D0000020065B8002863E000408018BC8084A809
+:101D1000001804D47C008A8CFF0084A40100609C1D
+:101D2000001824E41D0000100000001585008A8CB6
+:101D30000000609C001824E44A000010FFFF609C33
+:101D40000801EA84020067B80050A3E0C805EA84ED
+:101D5000FC0485847C04C584180064B81000A6B80F
+:101D6000080084B8002863E0002063E00040801889
+:101D7000000B84A8003063E0001804D40000A78C96
+:101D8000020065B8002863E000408018BC8084A889
+:101D9000001804D40100609C00182BE40500000C1E
+:101DA0000200609C00182BE4070000100100A09CBA
+:101DB00048008A8C00406018480863A8002003D4BB
+:101DC0000100A09C00282BE4210000100000809C52
+:101DD0007C006A8C002823E41B0000100000001522
+:101DE000C805CA84F2008A8C2200668C001804E4BC
+:101DF000110000100000001500406018B08063A8BA
+:101E0000002803D42200868C0400639C002003D4A5
+:101E10000040A018B080A5A804006018527E63A8F6
+:101E200000008584D501FF07000000152501000092
+:101E3000FC006A8400406018B08063A8F4FFFF03D0
+:101E40000000809CE8FFFF03CC05CA8400406018B6
+:101E5000B08063A8002003D41A010000FC006A844B
+:101E60000801EA84001827E403000010FC00AA849B
+:101E70000000E5A8020087B80200E5B8005064E061
+:101E80007C04A3840050C7E0FC0463841000A5B860
+:101E9000FC048684180063B8080084B8002863E056
+:101EA0007C04C684002063E000408018000B84A8F6
+:101EB000003063E0C805EA84001804D4C405AA848D
+:101EC0000000678C0000C58C020063B8AFFFFF0301
+:101ED000003063E00C01EA84001827E403000010DE
+:101EE000FC00AA840000E5A8020087B80200E5B85B
+:101EF000005064E07C04A3840050C7E0FC046384C9
+:101F00001000A5B8FC048684180063B8080084B8E3
+:101F1000002863E07C04C684002063E00040801851
+:101F2000000B84A8003063E0CC05EA84001804D4D8
+:101F3000C405AA840100678C0000C58C020063B848
+:101F400072FFFF03003063E07C008A8C002025E4F0
+:101F500022000010FF0084A40801AA84020065B8D2
+:101F60000C01EA840050A3E00200E7B8FC04858479
+:101F700000406018040B63A8005007E17C04C5848E
+:101F8000080084B8C8052A85003084E0FC04A884D1
+:101F9000002003D47C04C88400406018B88063A883
+:101FA0000800A5B80000898C0030A5E0002003D40B
+:101FB000CC05CA8400406018000B63A8002803D435
+:101FC0000100868C00406018BC8063A8002003D408
+:101FD0007C008A8CFF0084A40100609C001824E42B
+:101FE0006EFFFF13000000150801EA84020087B8A5
+:101FF0000050A4E0C805EA8400408018000B84A8C3
+:10200000FC0465847C04C584080063B8003063E088
+:10201000001804D40000A78C00406018BC8063A89E
+:10202000002803D45DFFFF030100609C004060189E
+:10203000A88063A80000809C002003D405FFFF0354
+:102040007B006A8C00406018A08063A80000809C20
+:10205000002003D400408018A48084A80000609C65
+:10206000001804D4E1FEFF037C006A8C0040601875
+:102070009C8063A8CAFEFF030000809C0300001040
+:102080000000E09C0100E09C0300609C001825E437
+:10209000030000100000809C0100809C042067E089
+:1020A000003003E40C00001000402BE40800001096
+:1020B00000000015CD008A8C00406018988063A84D
+:1020C000002003D4AFFEFF037B008A8CFBFFFF03DD
+:1020D0000000809C00406018988063A8F9FFFF030F
+:1020E0000000809CC8056A8476FEFF030500838C8F
+:1020F000C8056A8473FEFF030300838C00406018E8
+:102100008C8063A80000809C002003D400408018CD
+:10211000908084A80000609C001804D400406018DF
+:10212000948063A80000809C002003D47DFEFF0300
+:102130004D008A8C00406018688063A8002003D49A
+:10214000D6006A8C0000809C002003E4030000108D
+:1021500000000015000085A800406018440863A82E
+:10216000002003D421FEFF03D6008A8C00406018B3
+:10217000688063A8002003D400408018440884A825
+:102180000400639C002804D41CFEFF030000809C14
+:1021900000406018688063A8002003D400408018C5
+:1021A000440884A80000609C001804D40040601813
+:1021B0006C8063A80000809C002003D413FEFF0302
+:1021C000D5008A8C00408018000A84A80000609C1A
+:1021D0000040A0185408A5A8001804D40000658485
+:1021E000FEFF809CE2FDFF03032063E000406018D7
+:1021F000508063A89AFDFF030000809C8EFDFF03C2
+:10220000CA008A8CC8008A8C001844E403000010BD
+:102210000000A09C0100A09C00406018040C63A872
+:10222000002803D488FDFF030000609C6FFDFF03BE
+:10223000CB008A8C004060183C8063A861FDFF03DE
+:102240000000809C004080182C8084A8004060180A
+:10225000308063A8000084844BFDFF03000000155C
+:1022600000406018280863A8002003D41EFDFF0367
+:10227000CE00AA8C002824E4070000100200609C15
+:1022800000406018380863A8002803D4F5FCFF0359
+:1022900000000015001824E4F6FCFF1300000015F0
+:1022A00000406018380863A8004080183C0884A8E3
+:1022B000002803D4002804D4EFFCFF037C00AA8C80
+:1022C000020063B80050A3E0FC048584004060185D
+:1022D000080B63A87C04C584080084B80040A018DB
+:1022E000300CA5A8003084E0002003D4C00E6A841E
+:1022F000001805D4C40E4A8500406018340C63A849
+:10230000005003D4000021850400418500480044AA
+:102310000800219CF4FF219C004801D4045001D402
+:10232000086001D4000043A90200809C7B00638CFC
+:10233000002023E461000010000000157C006A8C7E
+:10234000001824E42600000C00000015FF0063A420
+:102350000100809D006023E4800000100000809C4C
+:1023600085006A8C002023E41B00000C000000158F
+:1023700086006A8C002003E41200001000000015A3
+:10238000C4056A840000809C7900000400000015E8
+:10239000C8056A840040A018180CA5A800008CA8E5
+:1023A000005805D4720000040000001500406018B9
+:1023B000140C63A8005803D4680000000000001546
+:1023C000C8056A846A0000040000809CF2FFFF03D5
+:1023D000C4056A84EDFFFF03C8056A84C8056A84E2
+:1023E000630000040000809C0040A018100CA5A809
+:1023F000C8056A840100809C005805D45C00000474
+:1024000000000015004060180C0C63A80000809CC0
+:10241000005803D485006A8C002023E41E00000CC1
+:102420000000001586006A8C002003E40E000010F6
+:102430000000C09C0040A018180CA5A8CC056A8418
+:102440000100809C003005D4490000040000001504
+:1024500000406018140C63A8005803D4BCFFFF03AD
+:102460007C006A8CCC056A84410000040000809CDA
+:1024700000406018180C63A800408018140C84A851
+:10248000005803D40000609C001804D4B0FFFF0380
+:102490007C006A8C36000004CC056A840040A018D9
+:1024A000180CA5A8CC056A840100809C005805D4AE
+:1024B000E6FFFF03000000157C006A8C001824E48E
+:1024C0000900000C00000015FF0063A40100809DBE
+:1024D000006023E42100001000000015AAFFFF03A4
+:1024E000C8056A84C8056A84210000040000809C35
+:1024F0000040A018100CA5A8C8056A840100809CA3
+:10250000005805D41A000004000000150040A0186F
+:102510000C0CA5A8CC056A840000809C005805D44A
+:1025200013000004000000150040A018180CA5A816
+:10253000CC056A840100809C005805D40C0000047E
+:102540000000001500406018140C63A8005803D464
+:10255000DEFFFF037C006A8C0000218504004185BA
+:1025600008008185004800440C00219C0000609D0B
+:10257000005824E416000010000000151400038D1C
+:1025800000408BE52400000C0000E09C1400C39C7C
+:102590000300668C0400A7B80100868C080063B8AD
+:1025A0000100E79C010084B80100C69C002063E0A4
+:1025B0000100639C082863E0004087E5F5FFFF13F6
+:1025C00000186BE114000000000000151900038DD5
+:1025D00000408BE51000000C0000E09C1A00C39C3A
+:1025E0000200668C0400A7B80000868C080063B85F
+:1025F0000100E79C010084B80100C69C002063E054
+:102600000100639C082863E0004087E5F5FFFF13A5
+:1026100000186BE10048004400000015E4FF219C15
+:10262000004801D4045001D4086001D40C7001D4D6
+:10263000108001D4149001D418A001D4000003AA82
+:10264000000044A9C01063841400A59C0000C09D34
+:102650000028A3E4030000100000809DECFF839D90
+:1026600000406018640063A80900809C6410909E7C
+:10267000002003D40000409E6C00D0840000ACA871
+:102680000000EEA800006A847B10FF07000094A8F9
+:1026900002588CE100900BE4050000100058CEE1D8
+:1026A00000006A84005863E000180AD400902BE40C
+:1026B000F2FFFF1300006EA9000021850400418590
+:1026C000080081850C00C185100001861400418638
+:1026D00018008186004800441C00219CF4FF219CC6
+:1026E000044801D4085001D40000E3A8000044A924
+:1026F0006410639CC010C784000083A8022866E0B1
+:102700001400A59C0028A6E4030000100000209DF2
+:10271000ECFF239D2A0007950000609C0000A9A8FB
+:10272000001801D46C00C78400006A84FE0FFF0704
+:102730002800E7940700809C00406018640063A8AC
+:10274000002003D40000809C00200BE40500001052
+:102750000000001500006A84005863E000180AD4E5
+:102760000400218508004185004800440C00219C9C
+:10277000FCFF219C004801D40000E3A8000064A9EC
+:102780006410639CC010C784000083A8022866E020
+:102790001400A59C0028A6E4030000100000209D62
+:1027A000ECFF239D2A0007950000A9A86C00C784B0
+:1027B00000006B84CF10FF072800E79400002185FC
+:1027C000004800440400219CFCFF219C004801D4E7
+:1027D000000004A9C010C3846410839C0028A6E4F0
+:1027E000030000100000E09C0228E6E06C00C384B7
+:1027F0000000A7A82E0FFF070000688400002185B5
+:10280000004800440400219CDCFF219C004801D4C6
+:10281000045001D4086001D40C7001D4108001D49C
+:10282000149001D418A001D41CB001D46C0083848E
+:102830000000009D000043A90200A4B80018E4E0D5
+:102840000000409E0018C5E0AC4147D80000C09E83
+:102850000800009D940D86840000009E0000809D6D
+:10286000C410A6840B0084BA202801D4004080182C
+:10287000640084A80000A09CF811C3848C2947D868
+:102880004000A6A4004004D4006005E40600001047
+:1028900000000015AC108384006004E43E00000CCE
+:1028A0002000819C0000609C0A00809CA41E2AD409
+:1028B0000000C09D00406018640063A8002003D49D
+:1028C000010066A4007003E42200000C0000B0A820
+:1028D0000000009D009090E1020066A40000809C32
+:1028E000002003E40600001074424AD420006184F2
+:1028F00064224AD4681A4AD46C624AD4A40E6A8408
+:10290000002003E4030000100000A09C0100A09C34
+:10291000002016E4030000100000609C0100609C91
+:10292000041865E0002003E42500001000006AA8F8
+:102930002000819CA5FFFF070000ACA86C006A8402
+:102940000100809C005063E01D000000AC2143D8D2
+:1029500000006AA862FFFF072000819C00700BE462
+:102960000B00001000004BAA0100A09CF811CA84C3
+:10297000A42E2AD42000618402A063E01400639C8A
+:10298000430063B8D3FFFF03A01E2AD4D1FFFF0387
+:10299000F811CA8422FFFF070000A09C00600BE42E
+:1029A0000500001000000BAAF811CA84BEFFFF0347
+:1029B0000100C09EBCFFFF03F811CA8400002185FE
+:1029C00004004185080081850C00C1851000018646
+:1029D00014004186180081861C00C186004800440E
+:1029E0002400219C0000A3A80100E09C2400639423
+:1029F000003863E0C000C584083863E00A1806DCCC
+:102A000026008594003884E0083884E00C2006DC39
+:102A10000E00658C003843E4040000100000609C48
+:102A200004000000063806D8061806D80000609C8E
+:102A30003D1805D800480044000000156C00A38430
+:102A40000200A5B80018A5E0B02725D4004800442E
+:102A5000000000156C008384020084B8B00F849CD1
+:102A6000002063E0000063850000809CFFFF6BA5F1
+:102A7000002003D40048004400000015FCFF219C06
+:102A8000004801D4540DE384000003A90200609CB7
+:102A9000001847E4030000100000609D4A00609D9C
+:102AA000F81168840000809C002003E407000010F7
+:102AB0000000C09CFC116884002023E40300001087
+:102AC000000000154D00609D0040A0190805ADA94B
+:102AD000004020190C0529A9940DA89C003886E413
+:102AE0001000000C0000809C80006584002023E41E
+:102AF0000B00000C0100C69C00006584002023E44C
+:102B0000F7FFFF130400A59C00008D84000069847A
+:102B1000001824E4F2FFFF13000000154E00609D32
+:102B2000740D68840000809C002003E40E000010F7
+:102B300000000015780D6884002003E40A000010EE
+:102B4000000000157C0D6884002003E406000010DE
+:102B500000000015800D6884002023E403000010AD
+:102B6000000000154E00609D0000218500480044D3
+:102B70000400219CF4FF219C004801D4045001D49E
+:102B8000086001D460008384000043A99C00839DF9
+:102B900004006018597E63A878FEFE070000001547
+:102BA0006000CA8400006CA8FFFFA09C002806E417
+:102BB00010000010000086A84107FF07540DAA84EA
+:102BC00004006018657E63A80000809C00202BE450
+:102BD000080000100000001568FEFE0760008A84EF
+:102BE00060008A8400006CA87806FF07540DAA8450
+:102BF000540DAA8478006A9CFA06FF0760008A9C3C
+:102C000000002185040041850800818500480044BA
+:102C10000C00219CE8FF219C004801D4045001D401
+:102C2000086001D40C7001D4108001D4149001D438
+:102C3000004080180C0884A80000A09C000083A914
+:102C4000002804D40040001A889010AAC0004C86C6
+:102C50000000809C00007084FE0F63A4002003E449
+:102C60002B00000C0000409D4204000400006CA8F2
+:102C700000500BE4580000100100809CE6040004A2
+:102C800000006CA804006018717E63A83BFEFE077C
+:102C90000000809C0600728C005003E417000010B6
+:102CA00078006C9C70008C84FFFF609C001804E42A
+:102CB0000900000C000000156C00AC8474200CD4DA
+:102CC00070280CD40100609C54180CD44100000002
+:102CD00050180CD4540DAC843C06FF0778006C9C53
+:102CE00004006018797E63A824FEFE0770008C84BF
+:102CF000F2FFFF0370008C846C008C843306FF07A6
+:102D0000540DAC84F1FFFF030100609C00404019AA
+:102D100084904AA904006018887E63A800008A8411
+:102D20000000C09D15FEFE07FF0084A400008A84F9
+:102D300004006018947E63A8500084B80FFEFE075C
+:102D4000FF0084A40000908404006018A07E63A8A3
+:102D50000AFEFE07000000150100609C00001086BE
+:102D6000FB03809C0F27C09C5C180CD460824CD461
+:102D700000406018000063A80040A0181005A5A836
+:102D8000002003D40000809C00006EA80030A3E463
+:102D90000600000C0100CE9D00006584002023E4A5
+:102DA000FBFFFF1300006EA800406018000063A83E
+:102DB000FF03A09C00408018889084A8002803D4BA
+:102DC0000000609C001804D4A8FFFF030000409D91
+:102DD0000100809C58200CD400002185040041850E
+:102DE000080081850C00C185100001861400418611
+:102DF000004800441800219CFCFF219C004801D49D
+:102E000000406018849063A800400019200808A9B9
+:102E10000000A3840040E0182C0CE7A80000E09D0F
+:102E20000000C384FFFFA5A40000A09D00006884EB
+:102E3000500026B90100609D00008784000067846F
+:102E4000500084B80000C884FFFF63A4001825E484
+:102E500003000010000000150000EBA9002029E489
+:102E60000400001003688FE00100A09D03688FE05C
+:102E70000000609C001804E40300000C0000001532
+:102E80000000609D00002185004800440400219C52
+:102E9000E8FF219C004801D4045001D4086001D40B
+:102EA0000C7001D4108001D4149001D400008385EB
+:102EB000000043AA0808609C0AF8FE070100809CF5
+:102EC00000406018640063A80800A09C0000928481
+:102ED000002803D400200CE40300001000000015BB
+:102EE000000084A90000609C9C1E2CD44AFFFF07B0
+:102EF00000006CA89C0E8C840000609C001824E4E8
+:102F00000C0000100000409D0F27009E0000C09D97
+:102F10000080AAE50700000C00000015B7FFFF07BE
+:102F200001004A9D00700BE4FAFFFF13000000153A
+:102F30000040C0181005C6A80000409D000066842F
+:102F4000005023E40B00000C0F27A09C0000809C85
+:102F500001004A9D0028AAE50600000C00000015AB
+:102F600000006684002023E4FAFFFF130000001530
+:102F7000F8116C840000809C010063A4002003E42D
+:102F800011000010000000150040C018380CC6A841
+:102F90000000409D00006684005023E40A00000CFD
+:102FA0000F27A09C01004A9D0028AAE50600000CFE
+:102FB0000000001500006684002023E4FAFFFF13E0
+:102FC000000000157E00000400006CA80000609C5A
+:102FD00000182BE4B9FFFF130808609C000021854E
+:102FE00004004185080081850C00C1851000018620
+:102FF00014004186004800441800219CFCFF219CDD
+:10300000004801D45C00C3840000A09C002806E4B2
+:103010003A00000C0000001500406018D80363A8B7
+:103020000100C018FFFFC6A8000083840000E09CD8
+:103030000100609D450064B80330A3E0005825E41A
+:10304000030000101F0084A40000EBA80000C09C37
+:10305000003024E4030000100000609C00006BA816
+:10306000031867E0003003E42200000C005825E458
+:10307000030000100000009D00000BA91F00609CD1
+:10308000001824E4030000100000E09C0000EBA8FE
+:10309000033868E0003003E41600000C005825E413
+:1030A000030000100000E09C0000EBA8003004E4E6
+:1030B000030000100000609C00006BA8031867E08C
+:1030C000003003E41800000C005825E4090000104B
+:1030D0000000001500408018180484A800006484D3
+:1030E000070063A4003003E40F00000C000000158B
+:1030F0000D0000000000609DC703000400000015E3
+:103100000040A0188003A5A804006018AB7E63A847
+:103110000000858419FDFE0700000015BFFFFF03B6
+:103120000000001500002185004800440400219C97
+:10313000F8FF219C004801D4045001D40000C3A82A
+:103140001700638C0100809C002023E40F00001016
+:103150000000409D34006684002023E40B00001032
+:1031600000000015280066942A008694062363E078
+:103170003800A6840018A5E40A000010000066A824
+:10318000070000007900409D2100868C2A0066948B
+:103190000018A4E4FBFFFF0F00000015000066A864
+:1031A00027FEFF0700008AA800006AA90000218509
+:1031B00004004185004800440800219CF4FF219C44
+:1031C000004801D4045001D4086001D4000043A990
+:1031D0008BFFFF070000809D00600BE421000010C2
+:1031E0000100A09C17008A8C002824E4060000102F
+:1031F00000006AA834008A84002824E41500000C2A
+:10320000000000152B0D000400000015C9FFFF078A
+:1032100000006AA800008BA900006AA80000809C3A
+:1032200000200CE4050000100000609D0100609C7F
+:103230000D000000781A4AD4EBFDFF0700000015CE
+:103240000E00000400006AA8070000000100609D55
+:103250003D0B000400000015EDFFFF03000000150A
+:103260000000609D000021850400418508008185E3
+:10327000004800440C00219CECFF219C004801D434
+:10328000045001D4086001D40C7001D42A00E394E6
+:10329000000043A9FFFF87A41900609C001844E4C4
+:1032A000A70000103200609C0100A09C3D008A8CA9
+:1032B0000000609C001824E49D0000100000001530
+:1032C00017006A8C0100809C002023E48D00001010
+:1032D0000000001534006A84002023E489000010F7
+:1032E0000000001528008A9400406018280863A890
+:1032F0003800AA840A23C5E0062386E0003003D400
+:103300000400639C0220A5E0002803D403008A8CFB
+:1033100000406018689063A80000C09C002003D49F
+:103320005C00AA8400406018640063A80900809CC7
+:10333000002003D4003005E43A0000100100809C16
+:1033400017006A8C002023E41A0000100000609C23
+:1033500034006A84002023E4160000100000609C02
+:1033600048126A84003003E41000001000000015C9
+:10337000FFFF639C501A4AD44C128A840000609C60
+:10338000001804E4030000100000A09CFFFFA49CB0
+:1033900028008A94FFFF67A4542A4AD45C1A4AD4AE
+:1033A0006E00000058224AD4F3FFFF030000609C27
+:1033B0004C128A84001804E450000010501A4AD4B9
+:1033C000FFFFC49C00406018280863A82800AA9446
+:1033D0000000809DF8118A8400006384020084A4A8
+:1033E0005C1A4AD454324AD4006004E40B00001042
+:1033F000582A4AD464126A84006023E42300000C33
+:1034000000006AA874128A840000609C001804E41A
+:103410001400000C000000150000809C5C200AD401
+:10342000004060182C0863A800408018280884A871
+:1034300000006384481A4AD4000084840000609C21
+:103440004C224AD458180AD40100809C00406018CD
+:10345000080863A8002003D4400000000000001505
+:103460005C120A8570126A84FFFF089D28008A9406
+:103470005012AA845412CA84590DFF075812EA84C4
+:10348000E7FFFF030000809C6C12CA8568128A84E3
+:103490000000AEA8102001D4B6FCFF071000819CEC
+:1034A00000600BE40500000C0100809C0100609CA2
+:1034B000D5FFFF03641A4AD4100061840058CEE19E
+:1034C00074224AD40000AEA8005883E01400639C24
+:1034D000102001D4701A4AD41000819CBBFCFF0755
+:1034E00000006AA86C006A840100809C005063E0C0
+:1034F000EFFFFF03AC2143D8B3FFFF030000C09CE4
+:1035000021006A8C00408018280884A8062B63E0FC
+:10351000001804D40040A0182C08A5A80000609C46
+:10352000001805D47BFFFF0303008A8C004060185D
+:10353000080463A8C8FFFF030000809C001844E44F
+:10354000040000100000001559FFFF030200A09CBA
+:1035500057FFFF030400A09C000021850400418563
+:10356000080081850C00C185004800441400219C9E
+:10357000ECFF219C004801D4045001D4086001D420
+:103580000C7001D4108001D4FF00C3A5000084A9F1
+:10359000000006AA10006018000063A80018A7E445
+:1035A00005000010000047A900806018000063A813
+:1035B000041847E10000A09C00282AE40300001042
+:1035C0000000C09C0100C09C7B12609C001848E475
+:1035D000030000100000809C0100809C042066E035
+:1035E000002803E46B00000C1000609D04006018CC
+:1035F000B27E63A8E1FBFE077C12809C7C12A09C3B
+:1036000000006AA80000809CE303FF0700500CD470
+:103610000000609C0100E09C48180AD450380AD48D
+:103620000100609CFFFFE09C3E180AD80000809CCF
+:10363000FFFF609C6C380AD460380AD468380AD41A
+:1036400070180AD474180AD40000E09C0000609C32
+:1036500001200AD83C200AD80000809C40380ADCAF
+:1036600042380ADC24380ADC0000E09CA01E2AD480
+:10367000A41E2AD430384AD40100609C5C380AD495
+:103680003C384AD440384AD444384AD448384AD4DA
+:103690004C384AD450384AD454384AD45C384AD486
+:1036A000F8394AD464200AD45C252AD498262AD42E
+:1036B00026200ADC040080185C8384A834184AD4CD
+:1036C00038184AD400700AD804006018588363A8D8
+:1036D000FC394AD4003803D4003804D404006018FC
+:1036E000548363A804008018608384A8003803D43E
+:1036F000003804D404006018648363A89BFDFE07AF
+:10370000003803D47305FF0700000015040060189B
+:10371000508363A80100809C0000E09C002003D43B
+:10372000A8862AD460384AD40000A09C1F00C09C00
+:10373000B00F6A9CAC118A9C0000E09C0100A59C23
+:10374000E03FE4DBFFFFE09C003FE3D70000E09CAC
+:10375000803FE3D7003804D80000E09C0100849C3F
+:10376000943AE3D7143BE3D7003803D40030A5E5FF
+:10377000F2FFFF130400639C783A4AD4483A4AD4D3
+:103780004C3A4AD4603A4AD4743A4AD40000609D14
+:103790000000218504004185080081850C00C18559
+:1037A00010000186004800441400219CE8FF219C81
+:1037B000004801D4045001D4086001D40C7001D435
+:1037C000108001D4149001D4020084B8000083A9B1
+:1037D000000006AA001864E00400C5B9140EE384D2
+:1037E0000400C6B80000AEA8940D43850B0047BA8C
+:1037F00024006C940B004AB9610EFF0726008C94DC
+:1038000000584AE10000C09C0300A09C0F00E09C0F
+:1038100000800019000008A90000809C00406AE0B8
+:1038200080802019808029A90100849C004803D44D
+:103830000028A4E5FBFFFF130400639C0100C69C65
+:103840000038A6E5F3FFFF1340004A9D26008C9444
+:103850000300D0B80000AEA8410084B8480EFF07AE
+:1038600024006C940058F2E00000C09C0300A09C6F
+:103870000700009D00802019000029A90000809CFD
+:10388000004867E080802019808029A90100849C7D
+:10389000004803D40028A4E5FBFFFF130400639C49
+:1038A0000100C69C0040A6E5F3FFFF134000E79C23
+:1038B0000000218504004185080081850C00C18538
+:1038C0001000018614004186004800441800219C25
+:1038D000D4FF219C004801D4045001D4086001D4D5
+:1038E0000C7001D4108001D4149001D418A001D41C
+:1038F0001CB001D420C001D424D001D428E001D4CC
+:1039000050128386000043A9280083940020B4E568
+:10391000030000105412C3850000809E2A006A94A0
+:103920000018AEE503000010000000150000C09D67
+:1039300058120A860020B0E5030000105C120A87C6
+:10394000000004AA0018B8E50300001000000015EC
+:10395000000003AB04006018BB7E63A8000094A8BD
+:1039600006FBFE07027058E204006018C37E63A8DD
+:1039700002FBFE0700008EA804006018CB7E63A83F
+:10398000FEFAFE07000090A804006018D37E63A82A
+:10399000FAFAFE07000098A82A006A940018B2E517
+:1039A0000300001000000015000043AA4412CA845E
+:1039B000020066B8540DAA84005083E0C4098485CF
+:1039C0000028A6E404000010440944873D000000DC
+:1039D000FFFF609D000086A800006AA80000B4A850
+:1039E0000000CEA872FFFF0708008EBB08008CB84D
+:1039F00004A0DCE20000609C0018B2E51100001099
+:103A000004D084E1008094E50D00000C000054A96E
+:103A10000101809E0450DCE000006CA801004A9D7A
+:103A2000000096A80000ACA8220EFF070000F4A832
+:103A300000808AE5F9FFFF130450DCE00100CE9D11
+:103A400004006018C37E63A800008EA8CBFAFE07AE
+:103A500000004EAA04006018D37E63A8C7FAFE07D0
+:103A6000000098A800C08EE51600000C0000609DC4
+:103A70000000409D00808AE50E00000C000000154B
+:103A80000800D2B90101809E0450CEE000006CA86D
+:103A900001004A9D000096A80000ACA8050EFF0793
+:103AA0000000F4A800808AE5F9FFFF130450CEE07F
+:103AB0000100529E00C092E5EEFFFF130000609DE2
+:103AC0000000218504004185080081850C00C18526
+:103AD0001000018614004186180081861C00C186F2
+:103AE0002000018724004187280081870048004486
+:103AF0002C00219CBCFF219C004801D4045001D41F
+:103B0000086001D40C7001D4000043A90000609C3F
+:103B10002800AA95281801D450126A84201801D4CC
+:103B200054126A84241801D40000609C2C1801D41B
+:103B3000200061840068A3E5030000100000609C81
+:103B4000201801D42A006A95240061840058A3E556
+:103B5000030000100000609C241801D44012EA8485
+:103B60000000609C401801D4020067B844122A8506
+:103B70000050A3E0540D0A85020089B84409658409
+:103B80000050C4E0301801D4C409A584342801D4FD
+:103B900044098684382001D4C409C684004047E41F
+:103BA000050000103C3001D4004049E40400000C42
+:103BB0000000001526000000FFFF609D58128A8556
+:103BC0000068ACE5030000105C12CA8500008DA9F6
+:103BD0000058AEE503000010000000150000CBA95E
+:103BE00004006018BB7E63A864FAFE07200081848D
+:103BF00004006018DB7E63A860FAFE07240081845D
+:103C000004006018CB7E63A85CFAFE0700008CA855
+:103C100004006018E27E63A858FAFE0700008EA830
+:103C20002800CA941000619C2000A1842400818493
+:103C30000228A6E002208EE0102801D4182001D42A
+:103C4000143001D4B80DFF071C3001D400002185C9
+:103C500004004185080081850C00C18500480044AE
+:103C60004400219CFCFF219C004801D40E00838C61
+:103C70000000609D005824E40600001000000015BC
+:103C800014FFFF07000000150400000000000015ED
+:103C900099FFFF070000001500002185004800443F
+:103CA0000400219CECFF219C004801D4045001D465
+:103CB000086001D40C7001D4108001D4000083A9E5
+:103CC0000000C09D0000609C540DAC849C180CD872
+:103CD0009D180CD89E180CD878180CD879180CD8C8
+:103CE00000288EE40E00000C7A180CD89C000C9E64
+:103CF0007B004C9D00008EA8000070A83302FF07D7
+:103D00000100CE9DFFFF609C540DAC8400180AD8C2
+:103D100000288EE4F8FFFF1301004A9D0000218572
+:103D200004004185080081850C00C18510000186D2
+:103D3000004800441400219CF8FF219C004801D455
+:103D4000045001D4000043A970008384540DAA8458
+:103D50001E02FF077800639C0100609C3D180AD892
+:103D60000000218504004185004800440800219C92
+:103D7000F0FF219C004801D4045001D4086001D414
+:103D80000C7001D400408018849084A8000083A99E
+:103D90000000A48400406018C40363A80000C48429
+:103DA000500045B9000083840000609C001824E4A2
+:103DB0001200000CFFFFC6A526006C940F00639C48
+:103DC000840063B8FFFF639C00182AE40F00001012
+:103DD0000000609D24006C940F00639C840063B815
+:103DE000FFFF639C00182EE408000010000000157F
+:103DF000060000000100609DD408FF0700000015C8
+:103E0000EFFFFF0326006C9400002185040041852C
+:103E1000080081850C00C185004800441000219CE9
+:103E2000E4FF219C004801D4045001D4086001D46F
+:103E30000C7001D4108001D4149001D4540DC484AA
+:103E4000000044A9FF0003A60000809D9C00C49DC3
+:103E50001800419E000070A800008EA80D02FF0708
+:103E60000000B2A804006018E97E63A8FFFF809CF0
+:103E700000202BE4300000100000001518008184A1
+:103E8000BEF9FE07000000151800A18470008A84A6
+:103E9000002005E40700001000006EA81800A184AF
+:103EA00074008A84002005E40500000C0000001561
+:103EB00018008184C501FF07540DAA8400006CA876
+:103EC000540DCA84003083E4E3FFFF1301008C9D8E
+:103ED0000030ACE408000010000000150400601879
+:103EE000F77E63A8A5F9FE0700008CA81400000067
+:103EF000FFFF609D1800818404006018017F63A8A3
+:103F00009EF9FE0700000015180061840000609D06
+:103F1000000083A86C180AD4040063B8022063E090
+:103F2000020063B800186AE0C400639C040000004B
+:103F3000C0180AD4E7FFFF03540DCA84000021858E
+:103F400004004185080081850C00C18510000186B0
+:103F500014004186004800441C00219CF4FF219C71
+:103F6000004801D4045001D4086001D42400839493
+:103F7000000043A90005609C002083E407000010B6
+:103F80000000809D2600AA94D002609C002883E453
+:103F90000A00000CFFFF84A4E2FEFE0760106A84A2
+:103FA00000600BE41500000C000000152600AA9428
+:103FB00024008A94FFFF84A48007609C0018A4E476
+:103FC000030000100000C09C0100C09CFFFF85A4FE
+:103FD0004004609C0018A4E4030000100000A09CB2
+:103FE0000100A09C042886E00000609C001804E406
+:103FF0000400001000006CA91C00809D00006CA94A
+:1040000000002185040041850800818500480044A6
+:104010000C00219CE8FF219C004801D4045001D4ED
+:10402000086001D40C7001D4108001D4149001D424
+:10403000000043A900406018180463A800004386EC
+:104040004208FF07000000150040A018C403A5A8FF
+:104050000100809C00006584002023E41200000C15
+:1040600000000015000084A9000005AA0040C01946
+:104070002003CEA901006A8C00008AA80000AE844B
+:104080005F0100040000001500602BE40F00000C2D
+:10409000FFFF609D00007084006023E4F6FFFF13C3
+:1040A0000000001500406018180463A80000838415
+:1040B000029084E00700849C9F0064B85D0063B8B0
+:1040C000001884E0830064B9000021850400418564
+:1040D000080081850C00C18510000186140041860E
+:1040E000004800441800219CF4FF219C004801D4A2
+:1040F000045001D4086001D4000084A9FF0043A546
+:104100007C1084840000A09CC002FF0700006AA805
+:10411000C1FFFF0700006CA80600CAB80040A01845
+:104120004820A5A800006AA80028C6E000008CA8C6
+:104130000000A68400288BE41100000C0000E09C25
+:10414000BB060004000000150100A09C00282BE421
+:104150000B0000100000E09C3C006C8C002823E465
+:1041600008000010000067A924008C940000E5A856
+:1041700026006C944C204CD450184CD4000067A9F5
+:104180000000218504004185080081850048004425
+:104190000C00219CE4FF219C004801D4045001D470
+:1041A000086001D40C7001D4108001D4149001D4A3
+:1041B00018A001D4000044850000C4A9FF0083A515
+:1041C0007C108A8400006CA80000A09C8F02FF076E
+:1041D000FFFF009E90FFFF0700006AA800802BE40D
+:1041E0000400001000008AA8D90000003400609D7F
+:1041F00000006CA88E0600040000409E3C006A8C03
+:10420000009023E4F9FFFF0F0100809E00A02BE443
+:104210002800000C00900BE40400000C00000015C6
+:10422000CB0000000100609D4609000400006AA860
+:1042300004006018097F63A8D0F8FE070000809C86
+:10424000E9F9FF0700006AA8BAFBFF0700006AA8A7
+:1042500000900BE4050000100000001578A24AD47D
+:10426000BB0000000000609D04FCFF0700006AA87E
+:1042700008FBFF0700006EA8040060180F7F63A80A
+:10428000BEF8FE070000809C78126A84009003E468
+:10429000E4FFFF130000001504006018197F63A8F5
+:1042A000B6F8FE070000809CA90000000000609D99
+:1042B0002BFFFF0700006AA800900BE4A400000C8D
+:1042C0001C00609D2400AA944C106A9C50108A9C8B
+:1042D0002600CA943C10EA841108FF0740100A85A2
+:1042E000FEFF6B9C00A043E49900000C00006CA84A
+:1042F000CCFEFF0700008AA800802BE49000000C91
+:1043000000006AA8F8116A84009003E48800000C99
+:1043100000000015B4F9FF0700006AA8004060180B
+:10432000640063A80600809C0000A09C002003D4C9
+:104330000000609D3D006A8C4CA00AD450280AD42D
+:10434000009023E4760000103C580AD80040601822
+:10435000280B63A800008384009024E42D00001043
+:10436000000000156C006A84020063B8005083E00E
+:10437000C409C484440964843F00809C0020A3E4F1
+:104380005E00001000000015020063B800408018B5
+:10439000000684A80040A0180C05A5A8002063E032
+:1043A00000008384000065840B0084B80040A018DE
+:1043B0002C0BA5A8002063E0001805D43F00609CEA
+:1043C0000018A6E44600001000000015020066B8C0
+:1043D0000040601900066BA90040A0180C05A5A8B4
+:1043E000005863E000008384000065840B0084B8FB
+:1043F0000040A018300BA5A8002063E0001805D4E9
+:1044000000406018280B63A80100A09C002803D47A
+:10441000CC08000400006AA86C006A840000609D5B
+:104420000700809C58580AD4020063B85C580AD42C
+:1044300002000A8D005023E168106A850040601870
+:10444000640063A8B05E29D42400EA942600CA94CC
+:104450007000AA846C006A85002003D4304729D4F8
+:1044600000006AA8443A29D4C43229D4402A4AD444
+:1044700030FBFF07445A4AD40000609C00180BE44C
+:104480000E0000100100609C781A4AD40040801889
+:10449000640084A80A00609D78126A840000A09CD1
+:1044A000005804D4002803E45EFFFF130000001549
+:1044B000270000000000609D00408018080884A8C4
+:1044C0000100A09C00006EA8002804D471FAFF0728
+:1044D00000000015EEFFFF0300000015020066B8A3
+:1044E00000408018000684A80040A0180805A5A870
+:1044F000BDFFFF03002063E0020063B80040A01886
+:104500000006A5A8002863E0000083840040A018EE
+:104510000805A5A8A4FFFF0300000015D701FF07A9
+:10452000000000153FFFFF0358A00AD4B7F8FF07AB
+:1045300000006AA878FFFF030000001540F9FF079C
+:104540007D00809C47FFFF0354A00AD40000218512
+:1045500004004185080081850C00C185100001869A
+:104560001400418618008186004800441C00219CEC
+:104570006000C3840000A3A8FFFF809C002006E425
+:1045800017000010020066B8300F839C002085E001
+:10459000B00E639C0000E484001865E0783845D4D0
+:1045A000000084840000E384742045D4703845D42E
+:1045B0006C3845D4F81185840000609C001804E430
+:1045C0000D0000100028C6E0AC11668C60008584E8
+:1045D000A01845D408000000A42045D40000609C29
+:1045E000702045D46C2045D4741845D4F2FFFF03E5
+:1045F000781845D40048004400000015FF0063A46B
+:1046000000408018482084A8060063B80100609D1F
+:10461000002063E00000A38400408018180484A8F0
+:1046200000006484430063B8002883E40300000CA6
+:10463000000000150000609D0048004400000015C7
+:10464000F8FF219C004801D4045001D40000809C54
+:10465000000043A994FDFF07982623D4FFFF809C08
+:104660000100609C70200AD434184AD474200AD403
+:1046700060200AD4000021850400418500480044E0
+:104680000800219CF8FF219C004801D4045001D46B
+:104690006C0083840000C3A8004000190C1608A910
+:1046A00000402019101629A90040401924164AA9D3
+:1046B000FFFF609C001824E43900000C0200E4B8FD
+:1046C00004006018508363A80000809C0030A7E0BD
+:1046D000002003D4C409858444096584080084B893
+:1046E000001884E00000609C002008D4001809D461
+:1046F00000408018181684A8000008850040601843
+:10470000141663A8004003D40000298500406018F7
+:10471000240863A8004804D40000A3840040801843
+:10472000200884A80800A5B80000C48400406018D0
+:104730001C1663A80030A5E00100809C002803D46B
+:1047400000200AD400406018001663A8002003D49B
+:10475000AAF7FE07000000150000609C00408018CA
+:10476000281684A800180AD40040A0182C16A5A862
+:104770000000848400406018302063A8002003D427
+:104780000000A5840400639C00408018041684A8DF
+:10479000002803D40000609C001804D40000218588
+:1047A00004004185004800440800219CBCFF219C76
+:1047B0000C4801D4105001D4146001D4187001D4F5
+:1047C0001C8001D4209001D424A001D428B001D4AD
+:1047D0002CC001D430D001D434E001D438F001D45D
+:1047E000402001D4000084A90040001A640010AAEF
+:1047F0000100809CFF00C3A6002010D4060096BBD9
+:1048000001B00CD80040A0184020A5A80000009DD1
+:104810004000818400285CE20000C09C584044D4E1
+:104820003C3004D800406018040863A80200A09C33
+:104830005C4004D4002803D400408018300884A8C9
+:104840002000C09F0040E0186420E7A800F004D4D6
+:104850000038DCE00000B2840400609CFFFF809E12
+:10486000400081845000A5B80100C09D0000C684AE
+:10487000FF0045A70701FF07603044D44000418591
+:104880000400609C000096A86010CA8400122A9D53
+:104890006C0DEA9C003001D4640DAA9C680DCA9C82
+:1048A000AC0E0A9D084801D464104A9D8003FF079E
+:1048B000045001D40200E09C003810D400703AE4A7
+:1048C000D10000100400009F4000E184381067848C
+:1048D000007003E409000010000087A80000878C26
+:1048E000000076A80600A09CE3FBFE070000001570
+:1048F000C10400000000001500400019682008A94C
+:10490000A810A78400407CE00000C3849C1067844A
+:104910005F00C6B8F81947D4FC2947D45C3047D4A7
+:104920000000BAA88204FF070400609C4000818454
+:10493000EEFDFF07000076A80300C09C4000418503
+:1049400000008BAA003010D4F405FF07000000150A
+:1049500058106A840000E09C005863E040008184A5
+:10496000FCFF639CE03944D4007034E48100001003
+:1049700058184AD404006018217F63A8FFF6FE0788
+:104980000000848C2405FF070000001535F9FE07A0
+:1049900000000015400041850040E0180820E7A80D
+:1049A00000400019042008A924006A95C409CA9C83
+:1049B00044086A9C26002A95C4088A9C4409AA9C3B
+:1049C000005807D4004808D40400E79C0300009D69
+:1049D000004007D454452AD42801FF070000FEA850
+:1049E0004000818400406018182063A8FFFFC0A821
+:1049F0005810A484002803D40000A48C0040601840
+:104A0000002063A8002803D4003012D49B00FF07C5
+:104A1000000000154000418524006A94B205FF079C
+:104A200026008A944000A184040060182E7F63A8A9
+:104A3000E4594AD4D1F6FE07E4118584CDFEFF0780
+:104A40004000618440008184601064841DFBFE0787
+:104A50006410849C0CF9FE070000001540FDFF0760
+:104A6000400061840000609C00180BE40A00001004
+:104A70000000E09C00007EA8000096A81C00A09CFE
+:104A80000000C09CE8F8FE070000E09C5A0400000B
+:104A900000000015000096A80400609C0000A09C87
+:104AA000E1F8FE070000C09C400081850200E09C08
+:104AB00038384CD40300609C00183AE4070000101A
+:104AC00000000015980E6C840000C09D007023E467
+:104AD0001200000C0100609C004060181C2063A8BC
+:104AE000000083840300609C070084A4001824E471
+:104AF0000600000C000000152101FF0700126C9C4D
+:104B00003D04000000000015CEFEFF0700006CA869
+:104B1000FAFFFF0340008185C0004C85000083A898
+:104B2000981E2CD4040060183A7F63A893F6FE0701
+:104B30000000001506006A8C007003E409000010F4
+:104B40004000C184540DA6847800669C6C00868465
+:104B50009EFEFE0700000015E0FFFF034000818578
+:104B6000540DA6847800669CFAFFFF0370008684CB
+:104B7000A904FF0700000015BAF8FE0700000015A1
+:104B80004000818400406018182063A858100485F4
+:104B9000004003D40000A48C00406018002063A8EB
+:104BA000002803D40000809CFFFF60A8001812D4E6
+:104BB000004060181C2063A8002003D42F00FF07CA
+:104BC000000000156BFEFF074000618440008184F7
+:104BD00060106484BBFAFE076410849CAAF8FE0788
+:104BE0000000001500007EA8000096A83400A09CDC
+:104BF0000000C09C8CF8FE070000E09CAEFFFF03A5
+:104C00004000818500C03AE464000010FE007A9CF8
+:104C10004000818538106C84007023E45B00000C38
+:104C20000000809E0300A09C002823E45400000C98
+:104C3000000076A8F8118C845F0064A400A003E44F
+:104C40004500000C000000150040C0186820C6A8F0
+:104C5000B8100C850030BCE000006CA80000858412
+:104C6000B410EC84FF3F84A440404CD43C384CD476
+:104C70000DFCFF0754252CD440008184000078A847
+:104C80008A04FF070000BAA84000E1843C10678452
+:104C90002600C794401087842400A79400C010D435
+:104CA0003B05FF07000000154000618474F7FF0713
+:104CB00000004BA900702AE40300001000008BAA3A
+:104CC0004700809E67F8FE070000001540008184C1
+:104CD000B410A484000064A83C2844D40000C48C10
+:104CE0000040A0180020A5A8003005D4FFFFC0A8F0
+:104CF000003012D41FFEFF07000000154000818421
+:104D0000601064846FFAFE076410849C5EF8FE07EE
+:104D1000000000150000609C001834E40B00001037
+:104D200000007EA80000E09C000096A80F00609C98
+:104D30000000A09C3CF8FE070000C09C400081855C
+:104D40005CFFFF030300E09C000096A8A9FFFF039F
+:104D50000000B4A804006018437F63A807F6FE07AC
+:104D60000000001540008184FC116484DA01FF0713
+:104D7000C010849CB5FFFF034000818500008C8C2F
+:104D8000DAFEFF030900A09C00008C8C000076A8CE
+:104D9000D6FEFF030800A09CFF0063A4007043E45C
+:104DA000030000100000A09C0000AEA80500609C5D
+:104DB00000183AE4030000100000809C00008EA858
+:104DC000042065E00000409D005003E43AFFFF131B
+:104DD00040008185400081843810A484007025E45F
+:104DE0008203000C000076A80200609C001825E4F5
+:104DF00005000010000076A80000848CBBFEFF03B5
+:104E00000C00A09C000078A84903FF070000BAA886
+:104E1000400081850000A09C980E6C84005023E423
+:104E20000300001054280CD40000AEA80300609CBE
+:104E300000183AE4030000100000809C00008EA8D7
+:104E4000032065E0005003E4070000100500609CAB
+:104E5000AC0E6C84005023E45E03000C78006C9C64
+:104E60000500609C00181AE40D0000100200809CF0
+:104E700000203AE4460300100000001554106C8432
+:104E8000002023E4420300100000609C980E8C84F4
+:104E9000001824E43E030010000000150100009DEE
+:104EA000540DAC8478006C9C70008C84C7FDFE07A8
+:104EB00098462CD44000818500406018640063A8A7
+:104EC0000500C09C54008C840000A09C003003D4DA
+:104ED000002824E43C00001000000015980E6C84AB
+:104EE000002823E4380000100000001554106C84E2
+:104EF000002823E434000010000000150000009E8C
+:104F00006801FF07000076A800800BE41203000C84
+:104F10000000001540008185AC0E6C840000809C70
+:104F2000002023E4030000100300609C0100809C2B
+:104F300000181AE4030000100000A09C0100A09CCF
+:104F4000032864E0008003E40003000C000076A85E
+:104F500091FCFF074000819C3400A09C00282BE4BA
+:104F6000F602000C00008BAA1C00A09C00282BE479
+:104F7000F302000C4000C184FEFF6B9C0100409DC9
+:104F8000005043E4940100104000818554584CD4F3
+:104F900054006C840000809C002023E40A00001070
+:104FA00000000015980E6C84002023E40600001019
+:104FB0000000001554106C84002023E4D1FFFF0F83
+:104FC0000000001500408018280B84A80000409DB8
+:104FD00000006484005003E403000010000000158A
+:104FE000005004D44D04FF0700000015005034E4C5
+:104FF0007701001058584CD440008185980E6C847D
+:10500000005023E4060000100000001554106C84CA
+:10501000005023E42A01000C1000009D9C0E8C849B
+:10502000040060184D7F63A854F5FE070000409D02
+:1050300000406018640063A80C00809C002003D42A
+:105040007503FF070000001586F7FE070000001536
+:10505000400081850E006C8C005023E4030000109A
+:105060000000001534504CD434106C84005003E41C
+:105070000F01000C00006CA854006C84005023E465
+:105080000A00001000000015980E6C84005023E404
+:1050900006000010000000159C0E6C84005023E4F4
+:1050A0000500000C00000015B3F6FF0700006CA817
+:1050B00040008185040060185C7F63A82FF5FE071F
+:1050C00060008C84400081850000809CFFFF609C14
+:1050D0006000AC84001825E40300001000004CA917
+:1050E0000100809C0200209D004834E40300001071
+:1050F0000000609C0100609C041864E00000609D5A
+:10510000005823E4050000100300609C001814E41C
+:10511000B700000C0200A5B800406018102063A87A
+:105120000000A09C980E8C84002803D40400639C8B
+:10513000002803D4005804E4030000100000809C01
+:105140000300809C004060181C2063A8002003D44A
+:105150000200809C002034E49B000010000083A823
+:105160000000C09C0000638458304AD4100063A83B
+:10517000001804D454106A840000809C002003E4CA
+:105180000C00001000000015980E6A84002003E453
+:1051900008000010FFFF609C0100009D54204AD4CD
+:1051A00038404AD498262AD470180AD474180AD4DD
+:1051B0006C006A840040C0182420C6A80040E01893
+:1051C0002820E7A8020063B80040A0180C05A5A895
+:1051D000980E0A85940D839C140E639C00208AE02F
+:1051E00000186AE00000848400006384002006D474
+:1051F000001807D400008584000066844B0084B842
+:105200000040A0180805A5A8002063E0001806D4F7
+:1052100000008584000067844B0084B8002063E0B0
+:105220000000809C001807D4002008E40300001050
+:105230000100809C0300809C004060182C2063A823
+:105240005810AA840000E09C002003D4004080187D
+:10525000182084A804006018BC8063A8002804D427
+:105260000000CA8C00408018002084A80000A3849D
+:10527000003004D4003805E40A00001000000015D6
+:10528000980E6A84003823E4060000100000001520
+:1052900054006A84003803E43E00000C0D00C09CFA
+:1052A00076FEFE070000409D4000618400408018AB
+:1052B000202084A80040A0186400A5A80E00C38C7C
+:1052C0000E00E09C0100C69C003004D4003805D4D8
+:1052D000A8FCFF0700000015400081846010648472
+:1052E000F8F8FE076410849C00400019402008A9CB
+:1052F000FFFF80A800407CE0002003D4E2F6FE0718
+:1053000000000015400081849C0E6484005023E45A
+:10531000180000100000E09CCFF5FF07000064A813
+:105320004000C184FFFF609C60008684001804E494
+:105330000D0000100000ABA88C11649C001886E0E2
+:105340000000648C005003E407000010000000150A
+:10535000100063B8FFFFABA40000C09C0418A5E0D8
+:10536000003004D8000096A822FEFF030500609CD0
+:10537000000064A89C3E24D4B7F5FF070000001588
+:105380000000ABA8000096A81AFEFF032000609C56
+:1053900000406018640063A80040A0182C20A5A855
+:1053A000003003D40000858400006AA8200084A88F
+:1053B000002005D4B4FCFF0700000015B9FFFF036F
+:1053C000000000150300609C001834E46AFFFF131E
+:1053D0000000E09C004080181C2084A80000648429
+:1053E00058384AD463FFFF03200063A800406018C8
+:1053F000082063A800400019142008A9440A859CCD
+:10540000C40AC59C00208CE00030CCE000008484FD
+:10541000940DE59C002003D40000C6840040601871
+:10542000042063A80038ECE0140EA59C003003D4DF
+:105430000028ACE00000E7840040C0181020C6A897
+:10544000004080180C0584A80000A584003806D40C
+:10545000002808D400006484000086844B0063B8F0
+:10546000980EAC84001884E000406018080563A81A
+:10547000002006D400008384000068844B0084B8B8
+:10548000002063E0001808D4005805E40300001071
+:105490000100809C000089A8004060181C2063A8BF
+:1054A000002003D444FFFF036C006A8464F5FF0707
+:1054B000AB00809CF1FEFF03400081850040601836
+:1054C000640063A8004003D45302FF0700000015E6
+:1054D00064F6FE07000000154000818534106C84DE
+:1054E000005003E43600000C00006CA854006C84EB
+:1054F000005023E40A00001000000015980E6C8490
+:10550000005023E406000010000000159C0E6C847F
+:10551000005023E40500000C0000001596F5FF077D
+:1055200000006CA84000818558108C8400406018F1
+:10553000182063A80040C0184020C6A8002003D44B
+:105540000030BCE000008C8C00406018002063A894
+:10555000FFFFE0A8002003D4003805D4C7FDFE07F4
+:1055600000000015400081850040A0182020A5A85B
+:105570000E006C8C0100639C001805D4000085842B
+:105580000100609C001824E4030000100000009D4E
+:1055900034404CD4F7FBFF0700006CA84000818426
+:1055A0006010648447F8FE076410849C36F6FE079A
+:1055B0000000001571FFFF034000618420F5FF0724
+:1055C000AB00809CCAFFFF034000818594FEFF036F
+:1055D0004000818578126C84008003E45301000C44
+:1055E0000000809C54006C84008023E406000010BE
+:1055F000000000155C106C84008023E44201000C64
+:1056000000008CA85C006C840000C09D007023E446
+:10561000B80000100100409DD6F9FF0700006CA8FB
+:1056200000502BE4AC00000C000000154000818508
+:1056300054106C84007023E456FEFF130000001524
+:105640005C106C84007003E452FEFF13007014E4DD
+:10565000060000100000001554006C84007023E464
+:105660006500000C0B00809C54008C840000609C42
+:10567000001824E43B00000C0000001500406018F6
+:10568000402063A80000A09C00189CE00040601827
+:105690002C2063A8002803D4FFFFA0A80000648486
+:1056A000002803E4FEFFFF1300122C9D0040C018E9
+:1056B0004020C6A86010EC8400307CE000008384A9
+:1056C000680DCC9C640DAC9C500084B864106C9C3C
+:1056D000003801D4041801D4030044A76C0DEC9CDD
+:1056E000AC0E0C9D0400609C084801D4F0FFFE073E
+:1056F000000096A8400081850000809C980E6C8474
+:10570000002023E4030000100000C09C0100C09CA6
+:105710000300609C00183AE4030000100000A09C05
+:105720000100A09C032866E0002003E419FEFF139B
+:1057300000000015AC0E6C84002023E415FEFF135E
+:105740000100009D540DAC8478006C9C70008C842A
+:105750009EFBFE0798462CD40EFEFF034000818579
+:105760006E02FF0700000015AB01FF0758584CD42C
+:10577000BCF5FE07000000154000A1840040601841
+:10578000182063A80040E0184020E7A85810C584FE
+:10579000FFFF00A9003003D40000858C0040601892
+:1057A000002063A80038DCE0002003D4004006D4C9
+:1057B00032FDFE0700000015B3F5FE0700000015DE
+:1057C00040006184A4F4FF07000000150000ABA8AE
+:1057D0002000609C000096A80000C09C92F5FE0787
+:1057E0000000E09C78F5FE0700000015A4FFFF0311
+:1057F0004000818500406018640063A8002003D445
+:105800004602FF07000000158301FF0758584CD4DB
+:1058100094F5FE07000000154000A18400406018C8
+:10582000182063A80000E09C5810C5840040801830
+:105830001C2084A800400019402008A9003003D48F
+:10584000003804D400406018002063A80000858C54
+:105850000040DCE0002003D4FFFF60A8001806D45D
+:1058600006FDFE070000001587F5FE070000001585
+:10587000400081859C0E6C84007023E406000010BB
+:105880000000ACA834106C84007023E40F00000CFE
+:105890000600609C341085840000609C001804E4BD
+:1058A0000500000C0000809C9C2625D4C6FFFF0349
+:1058B00000006CA8000065A861F4FF07AB00809CA5
+:1058C000FBFFFF0340008185000096A8C3FFFF0394
+:1058D0000000A09C04006018647F63A827F3FE0703
+:1058E0000000809C4000818552FFFF0354500CD47F
+:1058F0000100609CC0000C860000A09C54180CD4D1
+:105900005C006C84002803E4760000100100809C99
+:1059100017006C8C002023E46F00001000000015BD
+:1059200034006C84002023E46C0000100000809C94
+:1059300048126C84002803E4650000100000001584
+:10594000FFFF639C501A4CD44C128C840000609C66
+:10595000001804E40300001000000015FFFF649C21
+:10596000541A4CD428008C94A5FFC09C0000C09D04
+:105970006C006C842A00AC94006063E058224CD424
+:105980008C3143D85C2A4CD44000818564126C84ED
+:10599000007023E40700001000000015F8116C846B
+:1059A000020063A4007003E42B00000C00006CA84C
+:1059B00074126C840000409D005003E41C00000C35
+:1059C000000000150000C09C5C300CD40600708CF8
+:1059D000005003E410000010FFFF609C70008C84F6
+:1059E000001804E40700000C000000157000EC84AF
+:1059F0006C000C8574380CD473FDFF0370400CD41C
+:105A0000540DAC84F1FAFE0778006C9CF8FFFF039C
+:105A100040008185540DAC8478006C9CEBFAFE0745
+:105A20006C008C8468FDFF03400081855C120C854E
+:105A300070126C84FFFF089D28008C945012AC8477
+:105A40005412CC84E603FF075812EC84DEFFFF03F8
+:105A5000400081856C124C853C00819C6812EC846E
+:105A60000000AAA843F3FF073C3801D400700BE400
+:105A70000600000C3C00A184400081850100A09C30
+:105A8000CCFFFF03642A4CD400584AE10100009D7A
+:105A9000400061841400C59C3C00819C0058A5E036
+:105AA000703243D4744243D43C2801D447F3FF07F7
+:105AB0000000AAA8400081846C006484002063E098
+:105AC0000100809CEDFFFF03AC2143D89EFFFF0344
+:105AD0000000609C0000809C9CFFFF0350224CD47F
+:105AE0000040A0188490A5A800008584000065846B
+:105AF000FF0084A4500063B850224CD499FFFF03E8
+:105B0000FF0063A4BEFAFF07000076A800500BE474
+:105B10000400001000000015BBFEFF03400081855B
+:105B200074FFFF0340008185540DAC849C006C9C85
+:105B3000BBFFFF0378224CD44000C184000076A84C
+:105B40006AFBFF030000868C00008C8C67FBFF0360
+:105B50007B00A09C040060186E7F63A887F2FE079C
+:105B60000000809C50F8FF07400061844000818560
+:105B7000FFFFE09C0100009D70380CD474380CD4F9
+:105B800060380CD4E5FCFF0334404CD4980E6C8490
+:105B90000000A09C002823E4030000100000C09C2B
+:105BA0000100C09C0200609C00183AE40300001051
+:105BB0000000809C0100809C032066E0002803E434
+:105BC000BEFCFF130000A09CBCFCFF0354284CD477
+:105BD000540DAC8470008C847CFAFE0798762CD42B
+:105BE000A0FCFF03400081850000848C3FFBFF0385
+:105BF0000B00A09C0C0021851000418514008185BC
+:105C00001800C1851C000186200041862400818681
+:105C10002800C1862C00018730004187340081872D
+:105C20003800C187004800444400219CF4FF219CB7
+:105C3000004801D4045001D4086001D40040601829
+:105C4000D80363A8000084A90000609D000083843D
+:105C50001F00609C1F0044A500182AE41E00000CD1
+:105C600000006CA80000809C00202AE41200000CB8
+:105C70000100A09C17008C8C002824E40600001072
+:105C80000000001534008C84002824E40600000C79
+:105C90000000001587020004000000150E0000003F
+:105CA00001006A9DA8000004000000150A00000021
+:105CB00001006A9D00408018580384A80000A48455
+:105CC000BF000004000000150000609CF4FFFF030B
+:105CD00021180CD800002185040041850800818529
+:105CE000004800440C00219CFFFF839C2F00609C17
+:105CF000001844E4040000106200609C1A000000D8
+:105D00000600609D001844E4040000108B01609CB4
+:105D1000150000000700609D001844E40400001016
+:105D20002F06609C100000000900609D001844E4EC
+:105D300004000010BF18609C0B0000000B00609D69
+:105D4000001844E404000010FF23609C06000000DB
+:105D50000D00609D001844E40300000C0E00609DDF
+:105D60000000609D0048004400000015FCFF219CDD
+:105D7000004801D40C00838C0000A3A80500609C9F
+:105D8000001844E42C00001000000015020064B864
+:105D9000040080187C7F84A8002063E000008384D6
+:105DA00000200044000000150600609D02006B9C6E
+:105DB00000408018800384A81F0063A42100C09CB9
+:105DC000020063B80258C6E02200A09C002063E0F5
+:105DD0000100EB9C000083840258A5E00000009DB8
+:105DE0000830C4E04838E4E00100609D482866E0DF
+:105DF000005807E403000010035884E000000BA9DA
+:105E00000000A09C002803E4030000100000C09CD8
+:105E10000000CBA8043068E0002823E40400001050
+:105E2000005824E41200000C0000001510000000CF
+:105E30000000609D2A00859428006594ABFFFF0751
+:105E4000062363E0DBFFFF0302006B9CD8FFFF0328
+:105E50000700609DD6FFFF030900609DD4FFFF038C
+:105E60000B00609DD2FFFF030D00609D00002185A7
+:105E7000004800440400219CFCFF219C004801D400
+:105E80000C00838C0000A3A80500609C001844E46B
+:105E90000E00001000000015020064B80400801815
+:105EA000947F84A8002063E00000838400200044E5
+:105EB0000000001500406018180363A80000638507
+:105EC0001E000000000000152A008594280065943B
+:105ED00086FFFF07062363E01F006BA500406018E4
+:105EE000000363A802006BB900186BE100006B852A
+:105EF0001200000000000015004060181C0363A899
+:105F0000EFFFFF030000001500406018240363A8A2
+:105F1000EBFFFF0300000015004060182C0363A88E
+:105F2000E7FFFF030000001500406018340363A87A
+:105F3000E3FFFF0300000015000021850048004436
+:105F40000400219CF4FF219C004801D4045001D49A
+:105F5000086001D400408018440384A800408019E0
+:105F600004038CA90000A484000043A900008C84D1
+:105F7000C2FFFF070000001500406018140363A86B
+:105F800038580AD40000838403200AD800406018DF
+:105F9000080363A80000AC84000083840100609CB7
+:105FA00022200AD83C180AD8000021850400418527
+:105FB00008008185004800440C00219CECFF219CD6
+:105FC000004801D4045001D4086001D40C7001D4FD
+:105FD000108001D4000003AA00400019040308A99E
+:105FE00000406018200363A80040C0180C03C6A836
+:105FF000000083840000209E0000E09D022010D855
+:10600000000068840000888400006884091810D8A3
+:10601000000088840A2010D8000068840B1810D86B
+:106020000700609C0000A684001825E459010010B8
+:10603000FF0065A40100609C0100609E0D1810D84F
+:1060400000002686009831E4480000100100609CA2
+:1060500000406018480363A80000E09E0000E3854C
+:106060000000A09E8F006FB98E008FB98D00AFB970
+:106070008C004FB98B00CFB98A006FB889008FB8F8
+:106080008800AFB88700CFB88600EFB885000FB999
+:1060900084002FB90398ADE107006BA503988CE14C
+:1060A00003984AE10398CEE1039863E0039884E003
+:1060B0000398A5E00398C6E00398E7E0039808E199
+:1060C000039829E10C5810D8146010D8115010D83A
+:1060D000151810D8162010D8172810D81A3010D834
+:1060E0001B3810D8184010D8194810D80F6810D88D
+:1060F000127010D800A80DE403000010106810D82A
+:106100000000F3AA00A82EE40300000C2EB810D85B
+:106110000000B3A91200708C0000C09C0000A09C7D
+:10612000002803E4030000100F6810D80100C09C91
+:106130001600908C002025E40300000C2D3010D8B0
+:106140000100A09D0F6810D8FF0084A40000609C8F
+:10615000001804E4030000100000A09C0100A09CB3
+:106160002D2810D80100609C001851E41400001084
+:106170000200C09C00406018240363A80000A384B0
+:10618000860085B8830065B8070084A4010063A475
+:106190000E2010D8003024E4FB0000101C1810D88A
+:1061A000133010D8840065B8850085B8010063A459
+:1061B000010084A41E1810D81D2010D800406018BB
+:1061C000040363A8000083840000609C001811E4AD
+:1061D000EB000010042010D80C00D08C0600609C4E
+:1061E000003023E41A000010FF0086A4004080184D
+:1061F0005C0384A8000064848800A3B8FF0183A422
+:10620000930063B8020084B8FC07A5A40F0063A440
+:106210000400A59C262010DC0F00809C242810DCA4
+:10622000002023E408000010051810D80040601872
+:10623000200363A800008384062010D80000A384F4
+:10624000072810D8FF0086A40600609C001804E40C
+:106250000C000010020064B80400A0182095A5A846
+:106260000400C0180495C6A8002883E0003063E04D
+:106270000200849402006394262010DC241810DCB1
+:10628000240070940040AFA40000C09C26009094AD
+:106290000F00639C0F00849C840063B8840084B862
+:1062A000281810DC003005E4150000102A2010DC4E
+:1062B000003011E40F0000100000001500406018CD
+:1062C000040363A80040A0181C03A5A80000838451
+:1062D0000000C5840800849C0807609C0623C6E073
+:1062E000093363E0E803809C062363E0081810D8B4
+:1062F00000406018080363A8000063840000809CCD
+:10630000002011E40F0000100000609C2E00708C33
+:106310000100A09C002823E40A0000100000609CFB
+:106320000040C0180403C6A800006684002003E4EF
+:10633000900000100000609C2C1810D80000609C99
+:10634000001811E4890000100100609C1700F08C17
+:10635000003823E408000010000000150040601819
+:10636000040363A8000083841F2010D80000A384C6
+:10637000202810D80E00B08C0200809CFD00659C87
+:10638000FF0063A4002043E40A0000100000001591
+:1063900000408018100384A8000064840000609C02
+:1063A000001811E4030000100000001500006484D0
+:1063B0001A00708C0000C09C003003E4170000102D
+:1063C000003011E4050000100000001500406018C6
+:1063D0000C0363A80000638400400019040308A9AB
+:1063E00000006884003003E4050000100000001580
+:1063F00000406018280363A8000063840040601810
+:10640000840363A800008384003004E45200001079
+:10641000000000150000688400406018140363A8A1
+:1064200000008384032010D8FF0085A40200609C34
+:10643000001804E4060000100000609C1300908C1B
+:10644000001824E40D00000C000000151400908CCE
+:106450000000609C001804E43B00001000000015E0
+:1064600000406018140363A80000638400406018B3
+:10647000080363A80000638400406018040363A855
+:1064800000006384010083A40000609C001824E4E1
+:106490000A00000C0100609C0040A0182403A5A87D
+:1064A0000000809C00006584010063A4002023E4B8
+:1064B000FDFFFF130100609C0100409D3C1810D8B7
+:1064C0003E00708C005023E406000010FF0067A41B
+:1064D0000C00908C0000A09C302010D83E2810D8D2
+:1064E000005023E41200000C0000C09CFF0067A4D1
+:1064F000005023E468000010000000153400708490
+:10650000005023E464000010000070A8004040190F
+:1065100004034AA900008A8458FEFF070000001502
+:1065200000006A845C000000385810D4000070A895
+:106530000FFEFF07343010D41700F08CECFFFF0380
+:10654000345810D4004060180C0363A8C7FFFF0341
+:106550000000001500406018080363A80000638471
+:10656000AEFFFF030000001583FFFF031700F08C50
+:106570000000668472FFFF032C2810D832FFFF034F
+:106580000C00D08C0000809C07FFFF03132010D864
+:106590000000809C020063B80D2010D80400C018D1
+:1065A0002095C6A80000409D003083E01C5010D804
+:1065B0000400C0180495C6A80C2810D8003063E069
+:1065C0000200A394020063940F00A59C0200C494EF
+:1065D0008400A5B8241810DC0F00C69C0000688455
+:1065E0008400C6B8020084940E1810D800002885D4
+:1065F0000F4810D8FF00E9A400006884262010DCB2
+:10660000111810D800008884122010D80000688467
+:10661000282810DC2A3010DC131810D8008807E472
+:1066200003000010104810D80100409DFF0064A432
+:10663000008823E4160000102E5010D80000E9A8AE
+:106640001200908C0000A09C0000609C001804E4E4
+:10665000030000100F3810D80100A09C2D2810D87E
+:1066600000406018140363A8000083840040601891
+:10667000040363A8032010D8000083841700F08C63
+:106680000E00B08C69FFFF03042010D8EDFFFF035C
+:106690000100E09C000021850400418508008185FF
+:1066A0000C00C18510000186004800441400219CA4
+:1066B00000408018440384A80040C0181403C6A8F2
+:1066C0000000A484000086840040A0180803A5A848
+:1066D000212003D8000085840100A09C232003D83A
+:1066E000222003D80100809C2F2803D80000A68414
+:1066F0003C2003D8032803D80048004400000015BC
+:106700000040E018C403E7A80100C09C00006784B3
+:10671000003023E40900000C000000150040A01820
+:106720000403A5A80000858400006784003023E4EA
+:10673000FDFFFF1300000015004800440000001595
+:10674000F8FF219C004801D4045001D4000043A963
+:106750000040A0182008A5A8240063940040C01899
+:106760002408C6A80100E09C26008A940F00639CC0
+:106770000F00849C840063B8840084B8001805D49A
+:10678000002006D400006584040063B80040A0180F
+:106790001808A5A8001805D40000868400406018D9
+:1067A0001C0863A8040084B8002003D41700AA8C36
+:1067B000003825E4BE0000100000001534006A8493
+:1067C000003823E4BA0000100000001528008A9465
+:1067D00000406018280863A83800AA840A23C5E08E
+:1067E000062386E0003003D40400639C0220A5E069
+:1067F000002803D4004060182C0863A86C008A8429
+:1068000000006384020084B8481A4AD40E00EA8C5F
+:1068100000406018280863A80050C4E000006384AA
+:1068200000408018809084A84C1A4AD4C409A684D9
+:1068300000406018340863A8003803D40800A5B8E5
+:106840001C00EA8C00406018000C63A84409C68450
+:10685000003803D40030A5E000406018080B63A89E
+:10686000002804D4002803D40E008A8C0100609C08
+:10687000001824E410000010FFFF609C70008A8460
+:10688000001824E404000010020064B80000809C9A
+:10689000020064B80050A3E0C40985840040601879
+:1068A000000B63A84409C584080084B8003084E064
+:1068B000002003D403008A8C00406018689063A80D
+:1068C000002003D412F8FE0700000015A80E8A84E9
+:1068D0000000C09C003024E4030000100000E09C95
+:1068E0000100E09C0200609C001824E403000010FA
+:1068F0000000A09C0100A09C042867E0003003E495
+:10690000610000100100C09C0E006A8C003023E47E
+:106910005D0000100000001500408018000A84A8E7
+:106920000040A0185408A5A8003004D400006584D5
+:10693000043063E0001805D40100C09C0D008A8C6F
+:1069400000406018909063A8002003D41000AA8C27
+:106950000400639C002803D412008A8C0400639C0A
+:10696000002003D41600AA8C00406018480863A8D1
+:10697000002803D415008A8C004060189C9063A8FE
+:10698000002003D41900AA8C0400639C00408018E6
+:10699000380884A8002803D40000609C001804D4A0
+:1069A000004060183C0863A80000809C002003D4CD
+:1069B00000408018400884A800406018080C63A8B4
+:1069C000003004D40000809C002003D400408018D4
+:1069D0001C0C84A80000609C001804D400406018BF
+:1069E000049063A80000809C002003D4004080181D
+:1069F000089084A80000609C001804D40000809CCB
+:106A000000406018040C63A8002003D40E008A8C98
+:106A1000003024E4170000100000809C0040601843
+:106A2000189063A8003003D4004060186C9063A8ED
+:106A30000100809C002003D4FF1F609C0040801850
+:106A40008C9084A8001804D41600AA8C0000609CC6
+:106A5000001805E4200000100100809C0040601830
+:106A6000480863A8002003D41C000000A00E8A84FC
+:106A700000406018189063A8002003D4EBFFFF03C8
+:106A80000000001500408018000A84A80000609CE7
+:106A90000040A0185408A5A8001804D4000065847C
+:106AA000FEFF809CA4FFFF03032063E021006A8CAB
+:106AB00000408018280884A80040A0182C08A5A829
+:106AC000001804D40000609C001805D44AFFFF039E
+:106AD00000000015A00E8A8400406018300C63A8E6
+:106AE000002003D4A40E4A8500408018340C84A8EA
+:106AF000005004D400002185040041850048004472
+:106B00000800219C0100809C1D0000000000001571
+:106B1000F0FF219C004801D4045001D4086001D446
+:106B20000C7001D4000043A9800063840000C09D64
+:106B3000007003E406000010000084A984008A9C11
+:106B40000200609C2F0000040000A09C00700CE478
+:106B50000300000C00008CA80100809C360000049B
+:106B600000006AA800002185040041850800818595
+:106B70000C00C185004800441000219C040803D487
+:106B8000081003D40C1803D4102003D4143003D4F9
+:106B9000182803D41C3803D4204003D4244803D439
+:106BA000285003D42C5803D4306003D4346803D461
+:106BB000387003D43C7803D4408003D4448803D491
+:106BC000489003D44C9803D450A003D454A803D4C1
+:106BD00058B003D45CB803D460C003D464C803D4F1
+:106BE00068D003D46CD803D470E003D474E803D421
+:106BF00078F003D47CF803D42D00000000000015C9
+:106C00007E00609D010000200000001500F0609CE7
+:106C10000018ABE406000010025880E00400601881
+:106C20003C9563A8FFFF609D002003D4004800440A
+:106C30000000001504002384080043841400A3848A
+:106C40001800C3841C00E3842000038524002385EE
+:106C500028004385300083853400A3853800C38530
+:106C60003C00E385400003864400238648004386B9
+:106C700050006386540083865800A3865C00C38658
+:106C80006000E38664000387680023876C00438705
+:106C900070006387740083877800A3877C00C387B4
+:106CA0008000E387004800440000649DF4FF219CBD
+:106CB000004801D4045001D4086001D4000083A925
+:106CC0000000C4A88400A39C0000809C0000409D9C
+:106CD000005006E4080000100000609CC9FFFF0798
+:106CE0000000001500502BE4030000100000001508
+:106CF0000100409D80500CD40000609D0000218563
+:106D00000400418508008185004800440C00219C56
+:106D1000040060193C956BA9004800440000001570
+:106D2000746961775D78255B00000000B431000074
+:106D3000C4300000CC310000443200009832000022
+:106D4000603300005F7275635F7165735B6D756EB4
+:106D5000005D64255F68746F5F7165735B6D756E50
+:106D6000005D64253131314300000000732D655210
+:106D70007472617469614D206162006E255B657398
+:106D80004E005D7850535F4F5F454341415441444D
+:106D9000454E4F4E5D78255B5F4B4F0061746144FB
+:106DA000656E6F4E5D78255B5F444D007264646173
+:106DB0005D78255B5F505100535F4F4E4543415016
+:106DC0005D78255B54584500415F41525B52444415
+:106DD000005D782561746144656E6F4E5D78255B5A
+:106DE0005F4B4F005254584578255B414F4E005D34
+:106DF0004150535F455F4543415254585D78255B90
+:106E0000535F430078255B785F43005D255B7953D2
+:106E100043005D785B78455F005D782579455F4389
+:106E20005D78255B6E6F63006C616563415F424D09
+:106E30005B524444005D7825535F4F4E45434150BB
+:106E40006E6F635F6C6165635B424D5F005D7825CB
+:106E5000635F4B4F65636E6F4D5F6C6178255B427E
+:106E60000000005D61766E4920646C697571655340
+:106E700065636E656165482000726564E0A7000087
+:106E800014A6000048A600007CA60000E0A70000B1
+:106E9000E0A7000014A7000044A70000E0A700003E
+:106EA000E0A70000B8A70000C4B200003CB2000098
+:106EB0004CB200005CB200006CB200007CB200007A
+:106EC000C4B200008CB200009CB20000ACB2000062
+:106ED000BCB2000068F6000068F6000088F600000A
+:106EE00088F6000088F60000B0F60000B0F600005A
+:106EF000B0F60000B0F60000B0F60000B0F60000FA
+:106F000088F6000090F6000098F60000B0F6000049
+:106F1000B0F60000B0F60000B0F60000B0F60000D9
+:106F2000B0F60000B0F6000098F60000A0F60000F1
+:106F3000A8F60000B0F60000B0F60000B0F60000C1
+:106F4000B0F60000B0F60000B0F60000B0F60000A9
+:106F5000B8F600000C1D0100A81C0100181D01005E
+:106F6000201D0100281D0100481D0100481D0100D1
+:106F7000481D0100481D0100481D0100481D010079
+:106F8000301D0100381D0100401D0100481D010099
+:106F9000481D0100481D0100481D0100481D010059
+:106FA000481D0100481D0100501D0100581D010031
+:106FB000434E4F434D4C41454F4E5F424150535F0E
+:106FC000255B454356005D784E5F495550535F4FF2
+:106FD0005B454341005D7825636F7250697373654B
+:106FE0005020676E207373616F72687420686775D4
+:106FF0006174656D617461645845203A5F41525413
+:10700000524444415D78255B545845004D5F4152E0
+:10701000444154455F4154414E004B4F50535F4FE4
+:107020005F4543415254584578255B416146005DB8
+:1070300074206C697270206F7365636F6E69207362
+:10704000625F7469656666756F6320726E616D6DEF
+:10705000255B206453005D7869726F746F20676EE2
+:1070600050442066646120427365726420736573C6
+:107070005D78255B5F444D00255B4E454E005D7895
+:107080005320746F6F7070756465747272686320DA
+:1070900020616D6F6D726F66695F74615B20636400
+:1070A000005D64254E5F505150535F4F5B45434137
+:1070B000005D7825616E79442063696D746E6F435D
+:1070C000207478656F6C6C416974616346206E6FE3
+:1070D000656C69612021216475716552646572690E
+:1070E0006E6F4320747865747A695320255B3D6523
+:1070F00044005D786D616E794320636965746E6FDD
+:1071000041207478636F6C6C6F6974617553206E85
+:10711000736563636C7566736F43202C7865746E5A
+:10712000695320743D20657A78255B20424D005DCF
+:1071300074732078207472615B776F72005D7825BC
+:107140002079424D726174736F6320746E6D756C3B
+:107150005D78255B78424D00646E6520776F722004
+:107160005D78255B79424D006C6F63205D78255B0F
+:10717000726946007261776D614820656465676E6B
+:1071800078255B206553005D6E65757148206563E9
+:10719000656461656E6120727246206420656D6170
+:1071A00065646F4D78255B207542005D726566668B
+:1071B000746F4E206C657220657361656F72662016
+:1071C0006F68206D5B207473005D78255F494553BF
+:1071D000535F4F4E454341505D78255B6E6F4300D2
+:1071E0006C616563746E656D616C66206C632067AD
+:1071F00065726165255B206446005D78696C696134
+:107200006120676E657320746E65757168206563B3
+:1072100065646165617020726E6973727473206752
+:10722000206567615D78255B6C6E4F006553207942
+:107230006E65757148206563656461656F4D207288
+:107240005B206564005D782574706D456544207928
+:1072500069726373726F7470746E45202073656910
+:107260005D78255B206F4E006D617246614420653C
+:1072700066206174646E756F206F4E00646165688E
+:1072800066207265646E756F69614600676E696C31
+:10729000207461207571655365636E656165682052
+:1072A000207265647372617020676E695D78255B1A
+:1072B0006F7250007373656320676E6973756C46F7
+:1072C000704F206874617265006E6F69412D655260
+:1072D000636F6C6C646F6D206572206568632073EA
+:1072E00065676E6164255B207254005D70736E612A
+:1072F0006E6572616F6D20747220656463207365C2
+:10730000676E6168255B206543005D64676E616838
+:10731000666F206573655220666E6920656D726FB9
+:107320006F742064736F68206977207464206874B8
+:107330005F707369746174733D20737578255B2089
+:107340000000205DFCB0010078AE0100FCB001003F
+:10735000FCB00100FCB0010078AE010070B001008B
+:1073600080B00100D4B00100FCB00100FCB001000D
+:10737000FCB00100FCB0010084C6010084C601001D
+:10738000C4C60100C4C6010094C601009CC6010029
+:10739000A4C60100C4C60100C4C60100C4C60100E1
+:1073A000ACC60100B4C60100C4C60100C4C60100D9
+:1073B000C4C60100C4C60100C4C60100C4C60100A1
+:1073C000C4C60100C4C601008CC601008CC6010001
+:1073D000C4C60100C4C60100C4C60100C4C6010081
+:1073E000C4C60100C4C6010094C601009CC60100C9
+:1073F000A4C60100A4C60100C4C60100C4C60100A1
+:10740000C4C60100C4C60100C4C60100C4C6010050
+:10741000C4C60100C4C60100ACC60100B4C6010068
+:10742000C4C60100C4C60100C4C60100C4C6010030
+:10743000C4C60100C4C60100C4C60100C4C6010020
+:10744000C4C60100C4C60100C4C60100C4C6010010
+:10745000C4C60100C4C60100C4C60100C4C6010000
+:10746000C4C60100C4C60100C4C60100C4C60100F0
+:10747000C4C60100C4C60100C4C60100C4C60100E0
+:10748000C4C60100C4C60100C4C60100C4C60100D0
+:10749000C4C60100C4C60100C4C60100C4C60100C0
+:1074A000C4C60100C4C60100C4C60100C4C60100B0
+:1074B000C4C60100C4C60100C4C60100BCC60100A8
+:1074C000C4C60100C4C60100C4C60100C4C6010090
+:1074D000C4C60100C4C60100C4C60100C4C6010080
+:1074E000C4C60100C4C60100C4C60100C4C6010070
+:1074F000C4C60100C4C60100C4C60100C4C6010060
+:10750000C4C60100C4C60100CCC60100D4C6010037
+:1075100074C9010074C9010024CA010034CA010001
+:1075200034CA01007CC901007CC901007CC901008A
+:107530007CC901007CC901007CC9010034CA01007A
+:1075400044CA010054CA01007CC901007CC9010081
+:107550007CC901007CC901007CC901007CC9010013
+:107560007CC9010054CA010064CA010074CA010048
+:107570007CC901007CC901007CC901007CC90100F3
+:107580007CC901007CC901007CC9010084CA0100DA
+:1075900084CA010094CA01007CC901007CC90100B1
+:1075A0007CC901007CC901007CC901007CC90100C3
+:1075B0007CC90100BCCA0100CCCA01002C07020032
+:1075C00090080200B0080200D0080200140902006E
+:1075D00028090200540902000804010006030205FC
+:1075E0000A0D0C090F0E0B07100801000A0302090F
+:1075F0001920181105040B12211A130C2229302806
+:10760000060D141B1C150E0738312A23242B323982
+:10761000170F161D332C251E2D343B3A2E271F26FF
+:10762000363D3C353F3E372F6F7365526974756C3C
+:1076300063206E6F676E6168520064656C6F73657E
+:107640006F6974756F4E206E6863207465676E6134
+:1076500000000064B473020080740200AC74020085
+:10766000BC740200D0740200E474020014750200BD
+:10767000247502003475020044750200547502003E
+:10768000647502007475020084750200947502002E
+:10769000A4750200B4750200C4750200D47502001E
+:1076A000D8800200D8800200D88002000C8202003C
+:1076B0000C82020014820200148202000C8202007A
+:1076C000148202005F4745525F43454434363248D6
+:1076D0005252455F4154535F5B535554005D7825CA
+:1076E0004CC002009CC002009CC002009CC0020072
+:1076F0009CC002009CC002009CC002009CC0020012
+:107700009CC002009CC002007CC002009CC0020021
+:107710009CC002009CC002009CC002009CC00200F1
+:107720009CC002009CC002009CC002009CC00200E1
+:107730007CC002009CC002009CC002009CC00200F1
+:107740009CC002009CC002009CC002009CC00200C1
+:107750009CC002009CC002007CC002009CC00200D1
+:107760009CC002009CC002009CC002004CC00200F1
+:107770009CC002009CC002009CC002009CC0020091
+:107780007CC002009CC002009CC002009CC00200A1
+:107790009CC002009CC002009CC002009CC0020071
+:1077A0009CC002009CC0020094C002009CC0020069
+:1077B0009CC002009CC002009CC002009CC0020051
+:1077C0009CC002009CC002009CC002009CC0020041
+:1077D000A4C00200FCC00200FCC0020018C10200EC
+:1077E00018C1020024C1020030C102003CC10200E5
+:1077F00058C102009CC00200FCC0020044E3020029
+:1078000050E3020058E3020060E3020068E3020074
+:1078100070E3020078E3020078E3020078E30200FC
+:1078200000E3020044E3020050E3020058E30200D8
+:1078300060E3020068E3020070E3020070E302000C
+:10784000A8E3020030E4020044E4020044E4020041
+:1078500044E4020044E4020044E4020044E4020080
+:1078600044E4020044E4020044E4020038E402007C
+:1078700044E4020044E4020044E4020044E4020060
+:1078800044E4020044E4020044E4020044E4020050
+:1078900044E40200E4E3020044E4020044E40200A1
+:1078A00044E4020044E4020044E4020044E4020030
+:1078B00044E4020044E4020044E4020038E402002C
+:1078C00044E4020044E4020044E4020044E4020010
+:1078D00030E4020044E4020044E4020044E4020014
+:1078E00044E4020038E4020044E4020044E40200FC
+:1078F00044E4020044E4020044E4020044E40200E0
+:1079000044E4020044E4020044E4020044E40200CF
+:1079100044E4020044E4020044E4020044E40200BF
+:1079200044E4020044E4020044E4020044E40200AF
+:1079300044E402004CE40200666542205F65726F19
+:107940005F6D756E6574796264253D737220000AFF
+:107950006E797365616D5F6372656B720A64253D54
+:107960007063200075625F6272665F665F656D615D
+:10797000657A69730A64253D4D74730034676570D8
+:107980006174614472703E2D636964656E6F6974E1
+:107990007079745F5F495F6520504F566425203DC4
+:1079A00072700020636964656E6F69747079745FCA
+:1079B0005F2020655F4E4F4E4F565F49253D20505A
+:1079C00000200A647263616D6F6C626F6E5F6B633F
+:1079D00065626D7564253A725649440031313358F9
+:1079E000525245005D78255B4D74730034676570B5
+:1079F0006174614465643E2D72665F6369735F6D97
+:107A0000253D657A00000A64D4100300DC100300F1
+:107A10000811030018110300DC10030028110300F3
+:107A200038110300DC100300DC100300DC1003003D
+:107A3000DC100300DC100300DC100300DC1003008A
+:107A4000DC100300DC100300DC100300DC1003007A
+:107A5000DC100300DC1003005811030020646E45A5
+:107A60007320666F34706D5F7261705F665F6573FF
+:107A7000656D6172203D206C200A64254D74730091
+:107A8000346765706174614473493E2D526D72466E
+:107A90006C6C61653D20636F0A642520616D002078
+:107AA000626F72636B636F6C6D756E5F3D72656262
+:107AB000000A64255453414C2A2A2A002A2A2A2AD9
+:107AC000636564202065646F6D6172662A2A206593
+:107AD0002A2A2A2A203D202A200A64252A2A2A0026
+:107AE0002A2A2A2A6574666169642072616C70733F
+:107AF00064612079737365722A2A2A2A202A2A2A25
+:107B00006425203D2A00200A2A2A2A2A66612A2A78
+:107B1000207265746F636564612065647365726467
+:107B20002A2A2A732A2A2A2A25203D2000200A648C
+:107B30002A2A2A2A422A2A2A726F6665722020651A
+:107B4000746573657365765F2A2A75702A2A2A2AF6
+:107B5000203D202A200A64252A2A2A002A2A2A2AA5
+:107B600065746661632020726320646D7261656C68
+:107B70002A2A2A202A2A2A2A25203D2000200A648F
+:107B80002A2A2A2A632A2A2A7320646D20646E65B1
+:107B90002A2A2A202A2A2A2A25203D2000200A646F
+:107BA0002A2A2A2A612A2A2A72657466746E692032
+:107BB0006F483272202074732A2A2A2A202A2A2AFD
+:107BC0006425203D2A00200A4E59532A4F505F4316
+:107BD0005F544E495F544F4E4543455244455649C4
+:107BE0003D202A2A0A642520706D00205252455FEC
+:107BF0005F4448000052524541462A2A2045534CD2
+:107C00003D202A2A0A6425202A2A0020534C414676
+:107C100026262045414548205F524544444145526F
+:107C2000202A2A596425203D6500200A54636544B2
+:107C3000206570790A64253D492A2A0072662073FE
+:107C400020656D616C61657220636F6C3D202A2A2E
+:107C50000A64252000000020042F0300742E030076
+:107C6000C82F0300C82F03007C3C0300FC3D030029
+:107C70007C4F0300B84F0300F44F03003050030063
+:107C800044500300E4550300CC540300EC550300BA
+:107C900008560300285603004056030024570300EB
+:107CA00024570300F05D0300045E0300185E030028
+:107CB000285E0300245703002457030024570300C1
+:107CC00024570300245703002457030024570300BC
+:107CD0002457030024570300345E03000C6803009C
+:107CE0000C680300246803003C6803005468030028
+:107CF0006C680300846803001C6803005F77656E8E
+:107D00006D61726675625F65726566667A69735FDA
+:107D100064253D656572700072665F765F656D61B2
+:107D200066667562735F72653D657A6900006425F9
+:107D300061766E492C64696C5F424D205F4D554EF3
+:107D4000455A495300642520000102030405060733
+:107D500057454E0B5D64255B434544005D64255BE0
+:107D6000525245005D78255B747370004431635650
+:107D70002D6174616365643E6D72665F7A69735FDD
+:107D800066612065207265745D64255B204E41004C
+:107D900050494B53494B530070710050616C705FF8
+:107DA000735F656E5B657A69005D7825425F444D5F
+:107DB00064416675255B726451005D784F4E5F507B
+:107DC0004150535F255B45434D005D7864615F44DE
+:107DD000255B726463005D78715F7275756F5F74A7
+:107DE000666F5F74746573665D78255B31635600FA
+:107DF0004E726150536465655B657A69005D7825F4
+:107E0000565F444D615F31435B726464005D782569
+:107E10005F3143565F524150535F4F4E454341508F
+:107E20005D78255B544E43005D64255B5F444D00E7
+:107E3000255B4E4548005D78255B524F56005D78C6
+:107E4000255B52455B005D785D357830756C615619
+:107E5000445200655D64255B727563007369645FFD
+:107E60005D64255B747570007369645F5D64255B98
+:107E7000434544004D4F435F747570007369645F00
+:107E80005B6C735F005D6425585F424D5B534F50E0
+:107E9000005D6425595F424D5B534F50005D642582
+:107EA00054415453255B535553005D7878255B430B
+:107EB0004953005D255B455A73005D78255B785F0B
+:107EC00073005D78255B795F65005D78255B785F81
+:107ED00065005D78255B795F73005D787825795F53
+:107EE0005F65005D5D78257946554200504D455FE0
+:107EF000255B595463005D64746E756F5D78255B16
+:107F0000434544005D64255B4F475B005B005D4279
+:107F1000645F77685D656E6F726468007272655F3A
+:107F2000514553006E6F442064255B65696D005DAB
+:107F300070645F6E78255B62414C005D255B545335
+:107F40004D005D784E455F445D78255B617246006B
+:107F50004420656D5B656E6F005D64255B5349442D
+:107F6000005D64256D61724665445F65445B006336
+:107F7000465F42504853554C0000005D345E04009B
+:107F8000A85D04004C5E0400545E04005C5E0400C6
+:107F9000645E0400C85E0400B45E0400F85E040081
+:107FA000085F0400185F0400285F04000000000060
+:107FB00000000000000000000000000000000000C1
+:107FC00000000000000000000000000000000000B1
+:107FD00000000000000000000000000000000000A1
+:107FE0000000000000000000000000000000000091
+:107FF0000000000000000000000000000000000081
+:108000000000000000000000000000000000000070
+:108010000000000000000000000000000000000060
+:108020000000000000000000000000000000000050
+:108030000000000000000000000000000000000040
+:108040000000000000000000000000000000000030
+:108050000000000000000000000000000000000020
+:108060000000000000000000000000000000000010
+:108070000000000000000000000000000000000000
+:1080800000000000000000000000000000000000F0
+:1080900000000000000000000000000000000000E0
+:1080A00000000000000000000000000000000000D0
+:1080B00000000000000000000000000000000000C0
+:1080C00000000000000000000000000000000000B0
+:1080D00000000000000000000000000000000000A0
+:1080E0000000000000000000000000000000000090
+:1080F0000000000000000000000000000000000080
+:10810000000000000000000000000000000000006F
+:10811000000000000000000000000000000000005F
+:10812000000000000000000000000000000000004F
+:10813000000000000000000000000000000000003F
+:10814000000000000000000000000000000000002F
+:10815000000000000000000000000000000000001F
+:10816000000000000000000000000000000000000F
+:1081700000000000000000000000000000000000FF
+:1081800000000000000000000000000000000000EF
+:1081900000000000000000000000000000000000DF
+:1081A00000000000000000000000000000000000CF
+:1081B00000000000000000000000000000000000BF
+:1081C00000000000000000000000000000000000AF
+:1081D000000000000000000000000000000000009F
+:1081E000000000000000000000000000000000008F
+:1081F000000000000000000000000000000000007F
+:10820000000000000000000000000000000000006E
+:10821000000000000000000000000000000000005E
+:10822000000000000000000000000000000000004E
+:10823000000000000000000000000000000000003E
+:10824000000000000000000000000000000000002E
+:10825000000000000000000000000000000000001E
+:10826000000000000000000000000000000000000E
+:1082700000000000000000000000000000000000FE
+:1082800000000000000000000000000000000000EE
+:1082900000000000000000000000000000000000DE
+:1082A00000000000000000000000000000000000CE
+:1082B00000000000000000000000000000000000BE
+:1082C00000000000000000000000000000000000AE
+:1082D000000000000000000000000000000000009E
+:1082E000000000000000000000000000000000008E
+:1082F000000000000000000000000000000000007E
+:10830000000000000000000000000000000000006D
+:10831000000000000000000000000000000000005D
+:10832000000000000000000000000000000000004D
+:10833000000000000000000000000000000000003D
+:10834000000000000000000000000000000000002D
+:10835000000000000000000000000000000000001D
+:10836000000000000000000000000000000000000D
+:1083700000000000000000000000000000000000FD
+:1083800000000000000000000000000000000000ED
+:1083900000000000000000000000000000000000DD
+:1083A00000000000000000000000000000000000CD
+:1083B00000000000000000000000000000000000BD
+:1083C00000000000000000000000000000000000AD
+:1083D000000000000000000000000000000000009D
+:1083E000000000000000000000000000000000008D
+:1083F000000000000000000000000000000000007D
+:10840000000000000000000000000000000000006C
+:10841000000000000000000000000000000000005C
+:10842000000000000000000000000000000000004C
+:10843000000000000000000000000000000000003C
+:10844000000000000000000000000000000000002C
+:10845000000000000000000000000000000000001C
+:10846000000000000000000000000000000000000C
+:1084700000000000000000000000000000000000FC
+:1084800000000000000000000000000000000000EC
+:1084900000000000000000000000000000000000DC
+:1084A00000000000000000000000000000000000CC
+:1084B00000000000000000000000000000000000BC
+:1084C00000000000000000000000000000000000AC
+:1084D000000000000000000000000000000000009C
+:1084E000000000000000000000000000000000008C
+:1084F000000000000000000000000000000000007C
+:10850000000000000000000000000000000000006B
+:10851000000000000000000000000000000000005B
+:10852000000000000000000000000000000000004B
+:10853000000000000000000000000000000000003B
+:10854000000000000000000000000000000000002B
+:10855000000000000000000000000000000000001B
+:10856000000000000000000000000000000000000B
+:1085700000000000000000000000000000000000FB
+:1085800000000000000000000000000000000000EB
+:1085900000000000000000000000000000000000DB
+:1085A00000000000000000000000000000000000CB
+:1085B00000000000000000000000000000000000BB
+:1085C00000000000000000000000000000000000AB
+:1085D000000000000000000000000000000000009B
+:1085E000000000000000000000000000000000008B
+:1085F000000000000000000000000000000000007B
+:10860000000000000000000000000000000000006A
+:10861000000000000000000000000000000000005A
+:10862000000000000000000000000000000000004A
+:10863000000000000000000000000000000000003A
+:10864000000000000000000000000000000000002A
+:10865000000000000000000000000000000000001A
+:10866000000000000000000000000000000000000A
+:1086700000000000000000000000000000000000FA
+:1086800000000000000000000000000000000000EA
+:1086900000000000000000000000000000000000DA
+:1086A00000000000000000000000000000000000CA
+:1086B00000000000000000000000000000000000BA
+:1086C00000000000000000000000000000000000AA
+:1086D000000000000000000000000000000000009A
+:1086E000000000000000000000000000000000008A
+:1086F000000000000000000000000000000000007A
+:108700000000000000000000000000000000000069
+:108710000000000000000000000000000000000059
+:108720000000000000000000000000000000000049
+:108730000000000000000000000000000000000039
+:108740000000000000000000000000000000000029
+:108750000000000000000000000000000000000019
+:108760000000000000000000000000000000000009
+:1087700000000000000000000000000000000000F9
+:1087800000000000000000000000000000000000E9
+:1087900000000000000000000000000000000000D9
+:1087A00000000000000000000000000000000000C9
+:1087B00000000000000000000000000000000000B9
+:1087C00000000000000000000000000000000000A9
+:1087D0000000000000000000000000000000000099
+:1087E0000000000000000000000000000000000089
+:1087F0000000000000000000000000000000000079
+:108800000000000000000000000000000000000068
+:108810000000000000000000000000000000000058
+:108820000000000000000000000000000000000048
+:108830000000000000000000000000000000000038
+:108840000000000000000000000000000000000028
+:108850000000000000000000000000000000000018
+:108860000000000000000000000000000000000008
+:1088700000000000000000000000000000000000F8
+:1088800000000000000000000000000000000000E8
+:1088900000000000000000000000000000000000D8
+:1088A00000000000000000000000000000000000C8
+:1088B00000000000000000000000000000000000B8
+:1088C00000000000000000000000000000000000A8
+:1088D0000000000000000000000000000000000098
+:1088E0000000000000000000000000000000000088
+:1088F0000000000000000000000000000000000078
+:108900000000000000000000000000000000000067
+:108910000000000000000000000000000000000057
+:108920000000000000000000A8590100F8890300C1
+:1089300040020300388D000070350400F001010092
+:1089400098C90200706B0100DCCD0300202D0300EC
+:10895000F4A70000AC4704000CCC0000C099020052
+:108960000100000000000000010000000080000085
+:10897000B601000000010000820100008201000039
+:10898000BC6E0000C86E0000D46E0000E06E0000F7
+:10899000EC6E0000F86E0000046F0000206B010018
+:1089A00088DC0300B82A030018960000643C040029
+:1089B000106F00001C6F0000100801000A0302097C
+:1089C0001920181105040B12211A130C2229302822
+:1089D000060D141B1C150E0738312A23242B32399F
+:1089E000170F161D332C251E2D343B3A2E271F261C
+:1089F000363D3C353F3E372F181008000A0209016A
+:108A00002820191131393830121A21290C040B038E
+:108A10002A221B132B233A321C143B330E060D055E
+:108A20002C241D152D253C341E163D351F170F0710
+:108A30003E362E263F372F2716131008221D1B1AED
+:108A40001816101025221D1B1B1A16132622221D74
+:108A50001B1A16162825221D1D1B1A163028232026
+:108A6000201D1B1A3A302823221D1B1A45382E269A
+:108A700026231D1B5345382E03020100070605045B
+:108A80000E0C0A081614121024201C1834302C283E
+:108A90005048403870686058060000000D00000023
+:108AA000140000001C0000000D0000001400000075
+:108AB0001C00000020000000140000001C0000004A
+:108AC00020000000250000001C0000002000000025
+:108AD000250000002A0000000A0000000E0000002F
+:108AE00014000000180000000E0000001400000038
+:108AF000180000001B000000140000001800000017
+:108B00001B0000001E000000180000001B000000F9
+:108B10001E00000022000000060000000A00000005
+:108B20000D000000100000001200000017000000FF
+:108B3000190000001B0000000A0000000B000000EC
+:108B400010000000120000001700000019000000D3
+:108B50001B0000001D0000000D00000010000000C0
+:108B60001200000017000000190000001B000000A8
+:108B70001D0000001F000000100000001200000097
+:108B800017000000190000001B0000001D0000007D
+:108B90001F0000002100000012000000170000006C
+:108BA000190000001B0000001D0000001F00000055
+:108BB0002100000024000000170000001900000040
+:108BC0001B0000001D0000001F000000210000002D
+:108BD0002400000026000000190000001B00000017
+:108BE0001D0000001F000000210000002400000004
+:108BF00026000000280000001B0000001D000000EF
+:108C00001F000000210000002400000026000000DA
+:108C1000280000002A000000090000000D000000EC
+:108C20000F000000110000001300000015000000FC
+:108C300016000000180000000D0000000D000000EC
+:108C400011000000130000001500000016000000D5
+:108C500018000000190000000F00000011000000C3
+:108C600013000000150000001600000018000000AE
+:108C7000190000001B00000011000000130000009C
+:108C80001500000016000000180000001900000088
+:108C90001B0000001C000000130000001500000075
+:108CA0001600000018000000190000001B00000062
+:108CB0001C0000001E00000015000000160000004F
+:108CC00018000000190000001B0000001C0000003C
+:108CD0001E00000020000000160000001800000028
+:108CE000190000001B0000001C0000001E00000016
+:108CF0002000000021000000180000001900000002
+:108D00001B0000001C0000001E00000020000000EE
+:108D100021000000230000001000000010000000EF
+:108D20001000000010000000100000001000000003
+:108D300010000000100000001000000010000000F3
+:108D400010000000100000001000000010000000E3
+:108D500010000000100000001000000010000000D3
+:108D600010000000100000001000000010000000C3
+:108D700010000000100000001000000010000000B3
+:108D800010000000100000001000000010000000A3
+:108D90001000000010000000100000001000000093
+:108DA0001000000010000000100000001000000083
+:108DB0001000000010000000100000001000000073
+:108DC0001000000010000000100000001000000063
+:108DD0001000000010000000100000001000000053
+:108DE0001000000010000000100000001000000043
+:108DF0001000000010000000100000001000000033
+:108E00001000000010000000100000001000000022
+:108E10001000000010000000100000001000000012
+:108E20001000000010000000100000001000000002
+:108E300010000000100000001000000010000000F2
+:108E400010000000100000001000000010000000E2
+:108E500010000000100000000000000000000000F2
+:108E6000C8AF0000E4570000E4570000F22B0000F8
+:108E7000983A00004C1D0000F22B0000F91500008C
+:108E800028230000941100004C1D0000A60E0000D5
+:108E90001C1900008E0C0000F9150000FE0A0000ED
+:108EA00088130000C409000094110000CA080000E3
+:108EB000FA0F0000FE070000A60E00005307000096
+:108EC000850D0000C40600008E0C0000480600005E
+:108ED000B80B0000DC050000FC0A00008005000063
+:108EE000570A00002C050000C4090000E20400003D
+:108EF00040090000A2040000CA0800006504000048
+:108F00005E08000030040000FD07000000040000BF
+:108F100055070000AC03000053070000AC0300003D
+:108F20000807000084030000C2060000620300007E
+:108F300082060000420300004706000024030000F0
+:108F4000DE050000F0020000DC050000EE0200007B
+:108F5000AB050000D60200007E050000C002000044
+:108F600053050000AA0200002B0500009602000035
+:108F70000505000084020000E20400007202000007
+:108F8000C004000062020000A004000052020000C1
+:108F90008104000042020000650400003402000069
+:108FA00049040000260200002F04000018020000FF
+:108FB000160400000C020000FE0300000002000086
+:108FC000E8030000F4010000D2030000EA01000001
+:108FD000BD030000E0010000A9030000D60100006D
+:108FE00096030000CC01000084030000C2010000D1
+:108FF00072030000BA01000061030000B20100002A
+:1090000051030000A801000041030000A20100007C
+:10901000320300009A0100002303000092010000C7
+:10902000150300008C01000007030000840100000C
+:10903000EF02000078010000EE020000780100005D
+:1090400000000030000000000000000000000000F0
+:109050000000000000000000000000000000000010
+:109060000000000000000000000000000000000000
+:1090700000000000010000000800000010000000D7
+:109080000900000002000000030000000A000000C8
+:10909000110000001800000020000000190000006E
+:1090A000120000000B00000004000000050000009A
+:1090B0000C000000130000001A0000002100000056
+:1090C00028000000300000002900000022000000FD
+:1090D0001B000000140000000D000000060000004E
+:1090E000070000000E000000150000001C0000003A
+:1090F000230000002A0000003100000038000000BA
+:1091000039000000320000002B00000024000000A5
+:109110001D000000160000000F00000017000000F6
+:109120001E000000250000002C000000330000009D
+:109130003A0000003B000000340000002D00000059
+:10914000260000001F000000270000002E00000085
+:10915000350000003C0000003D000000360000002B
+:109160002F000000370000003E0000003F0000001C
+:1091700008000000110000001200000013000000B1
+:109180001500000017000000190000001B0000007F
+:109190001100000012000000130000001500000084
+:1091A00017000000190000001B0000001C00000058
+:1091B0001400000015000000160000001700000059
+:1091C000180000001A0000001C0000001E00000033
+:1091D0001500000016000000170000001800000035
+:1091E0001A0000001C0000001E000000200000000B
+:1091F0001600000017000000180000001A00000010
+:109200001C0000001E0000002000000023000000E1
+:1092100017000000180000001A0000001C000000E9
+:109220001E000000200000002300000026000000B7
+:10923000190000001A0000001C0000001E000000C1
+:10924000200000002300000026000000290000008C
+:109250001B0000001C0000001E0000002000000099
+:109260002300000026000000290000002D0000005F
+:1092700010000000110000001200000013000000A8
+:109280001400000015000000160000001700000088
+:109290001100000012000000130000001400000084
+:1092A0001500000016000000170000001800000064
+:1092B0001200000013000000140000001500000060
+:1092C0001600000017000000180000001900000040
+:1092D000130000001400000015000000160000003C
+:1092E00017000000180000001A0000001B0000001A
+:1092F0001400000015000000160000001700000018
+:10930000190000001A0000001B0000001C000000F3
+:1093100015000000160000001700000018000000F3
+:109320001A0000001B0000001C0000001E000000CE
+:109330001600000017000000180000001A000000CE
+:109340001B0000001C0000001E0000001F000000A9
+:109350001700000018000000190000001B000000AA
+:109360001C0000001E0000001F0000002100000083
+:1093700000000000000000000100000001000000EB
+:1093800002000000010000000300000001000000D6
+:1093900002000000020000000300000003000000C3
+:1093A00004000000040000000500000005000000AB
+:1093B00003000000040000000100000005000000A0
+:1093C0000100000002000000030000000400000093
+:1093D000050000000600000001000000030000007E
+:1093E0000500000007000000050000000500000067
+:1093F0000600000006000000070000000700000053
+:109400000700000007000000070000000700000040
+:10941000080000000800000008000000080000002C
+:109420000001000080000000550000004000000026
+:10943000330000002B000000250000002000000089
+:109440000000000001000000020000000300000016
+:1094500004000000050000000600000007000000F6
+:1094600008000000060000000700000008000000DF
+:10947000090000000A0000000B0000000C000000C2
+:109480000D0000000E0000000F00000010000000A2
+:109490001100000012000000130000001400000082
+:1094A0001500000016000000170000001800000062
+:1094B000190000001B0000001D0000001F0000003C
+:1094C000000000000000000001000000010000009A
+:1094D0000200000002000000030000000300000082
+:1094E000000000000100000000000000010000007A
+:1094F0000200000003000000020000000300000062
+:1095000001000000FFFFFFFF80000000B00000002E
+:1095100060010000C002000080050000FFFFFFFFA7
+:10952000FFFFFFFF6000000090000000200100002E
+:109530004002000080040000FFFFFFFF0000000069
+:00000001FF
diff --git a/fs/aio.c b/fs/aio.c
index b4a88cc..278ed7d 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1395,6 +1395,10 @@ static ssize_t aio_setup_vectored_rw(int type, struct kiocb *kiocb, bool compat)
if (ret < 0)
goto out;
+ ret = rw_verify_area(type, kiocb->ki_filp, &kiocb->ki_pos, ret);
+ if (ret < 0)
+ goto out;
+
kiocb->ki_nr_segs = kiocb->ki_nbytes;
kiocb->ki_cur_seg = 0;
/* ki_nbytes/left now reflect bytes instead of segs */
@@ -1406,11 +1410,17 @@ out:
return ret;
}
-static ssize_t aio_setup_single_vector(struct kiocb *kiocb)
+static ssize_t aio_setup_single_vector(int type, struct file * file, struct kiocb *kiocb)
{
+ int bytes;
+
+ bytes = rw_verify_area(type, file, &kiocb->ki_pos, kiocb->ki_left);
+ if (bytes < 0)
+ return bytes;
+
kiocb->ki_iovec = &kiocb->ki_inline_vec;
kiocb->ki_iovec->iov_base = kiocb->ki_buf;
- kiocb->ki_iovec->iov_len = kiocb->ki_left;
+ kiocb->ki_iovec->iov_len = bytes;
kiocb->ki_nr_segs = 1;
kiocb->ki_cur_seg = 0;
return 0;
@@ -1435,10 +1445,7 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb, bool compat)
if (unlikely(!access_ok(VERIFY_WRITE, kiocb->ki_buf,
kiocb->ki_left)))
break;
- ret = security_file_permission(file, MAY_READ);
- if (unlikely(ret))
- break;
- ret = aio_setup_single_vector(kiocb);
+ ret = aio_setup_single_vector(READ, file, kiocb);
if (ret)
break;
ret = -EINVAL;
@@ -1453,10 +1460,7 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb, bool compat)
if (unlikely(!access_ok(VERIFY_READ, kiocb->ki_buf,
kiocb->ki_left)))
break;
- ret = security_file_permission(file, MAY_WRITE);
- if (unlikely(ret))
- break;
- ret = aio_setup_single_vector(kiocb);
+ ret = aio_setup_single_vector(WRITE, file, kiocb);
if (ret)
break;
ret = -EINVAL;
@@ -1467,9 +1471,6 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb, bool compat)
ret = -EBADF;
if (unlikely(!(file->f_mode & FMODE_READ)))
break;
- ret = security_file_permission(file, MAY_READ);
- if (unlikely(ret))
- break;
ret = aio_setup_vectored_rw(READ, kiocb, compat);
if (ret)
break;
@@ -1481,9 +1482,6 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb, bool compat)
ret = -EBADF;
if (unlikely(!(file->f_mode & FMODE_WRITE)))
break;
- ret = security_file_permission(file, MAY_WRITE);
- if (unlikely(ret))
- break;
ret = aio_setup_vectored_rw(WRITE, kiocb, compat);
if (ret)
break;
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index f55ae23..790fa63 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -392,10 +392,12 @@ static struct vfsmount *autofs4_d_automount(struct path *path)
ino->flags |= AUTOFS_INF_PENDING;
spin_unlock(&sbi->fs_lock);
status = autofs4_mount_wait(dentry);
- if (status)
- return ERR_PTR(status);
spin_lock(&sbi->fs_lock);
ino->flags &= ~AUTOFS_INF_PENDING;
+ if (status) {
+ spin_unlock(&sbi->fs_lock);
+ return ERR_PTR(status);
+ }
}
done:
if (!(ino->flags & AUTOFS_INF_EXPIRING)) {
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 618493e..7e8299f 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -1669,30 +1669,19 @@ static int elf_note_info_init(struct elf_note_info *info)
return 0;
info->psinfo = kmalloc(sizeof(*info->psinfo), GFP_KERNEL);
if (!info->psinfo)
- goto notes_free;
+ return 0;
info->prstatus = kmalloc(sizeof(*info->prstatus), GFP_KERNEL);
if (!info->prstatus)
- goto psinfo_free;
+ return 0;
info->fpu = kmalloc(sizeof(*info->fpu), GFP_KERNEL);
if (!info->fpu)
- goto prstatus_free;
+ return 0;
#ifdef ELF_CORE_COPY_XFPREGS
info->xfpu = kmalloc(sizeof(*info->xfpu), GFP_KERNEL);
if (!info->xfpu)
- goto fpu_free;
+ return 0;
#endif
return 1;
-#ifdef ELF_CORE_COPY_XFPREGS
- fpu_free:
- kfree(info->fpu);
-#endif
- prstatus_free:
- kfree(info->prstatus);
- psinfo_free:
- kfree(info->psinfo);
- notes_free:
- kfree(info->notes);
- return 0;
}
static int fill_note_info(struct elfhdr *elf, int phdrs,
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 74fc5ed..a580028 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -64,7 +64,7 @@ static void bdev_inode_switch_bdi(struct inode *inode,
spin_unlock(&inode_wb_list_lock);
}
-static sector_t max_block(struct block_device *bdev)
+sector_t blkdev_max_block(struct block_device *bdev)
{
sector_t retval = ~((sector_t)0);
loff_t sz = i_size_read(bdev->bd_inode);
@@ -135,7 +135,7 @@ static int
blkdev_get_block(struct inode *inode, sector_t iblock,
struct buffer_head *bh, int create)
{
- if (iblock >= max_block(I_BDEV(inode))) {
+ if (iblock >= blkdev_max_block(I_BDEV(inode))) {
if (create)
return -EIO;
@@ -157,7 +157,7 @@ static int
blkdev_get_blocks(struct inode *inode, sector_t iblock,
struct buffer_head *bh, int create)
{
- sector_t end_block = max_block(I_BDEV(inode));
+ sector_t end_block = blkdev_max_block(I_BDEV(inode));
unsigned long max_blocks = bh->b_size >> inode->i_blkbits;
if ((iblock + max_blocks) > end_block) {
diff --git a/fs/btrfs/async-thread.c b/fs/btrfs/async-thread.c
index 7ec1409..8006a28 100644
--- a/fs/btrfs/async-thread.c
+++ b/fs/btrfs/async-thread.c
@@ -212,10 +212,17 @@ static noinline int run_ordered_completions(struct btrfs_workers *workers,
work->ordered_func(work);
- /* now take the lock again and call the freeing code */
+ /* now take the lock again and drop our item from the list */
spin_lock(&workers->order_lock);
list_del(&work->order_list);
+ spin_unlock(&workers->order_lock);
+
+ /*
+ * we don't want to call the ordered free functions
+ * with the lock held though
+ */
work->ordered_free(work);
+ spin_lock(&workers->order_lock);
}
spin_unlock(&workers->order_lock);
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 1ac8db5d..57106a9 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -801,7 +801,8 @@ static int btree_submit_bio_hook(struct inode *inode, int rw, struct bio *bio,
#ifdef CONFIG_MIGRATION
static int btree_migratepage(struct address_space *mapping,
- struct page *newpage, struct page *page)
+ struct page *newpage, struct page *page,
+ enum migrate_mode mode)
{
/*
* we can't safely write a btree page from here,
@@ -816,7 +817,7 @@ static int btree_migratepage(struct address_space *mapping,
if (page_has_private(page) &&
!try_to_release_page(page, GFP_KERNEL))
return -EAGAIN;
- return migrate_page(mapping, newpage, page);
+ return migrate_page(mapping, newpage, page, mode);
}
#endif
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 7fa128d..faf7d0b 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -691,6 +691,8 @@ static noinline int drop_one_dir_item(struct btrfs_trans_handle *trans,
kfree(name);
iput(inode);
+
+ btrfs_run_delayed_items(trans, root);
return ret;
}
@@ -896,6 +898,7 @@ again:
ret = btrfs_unlink_inode(trans, root, dir,
inode, victim_name,
victim_name_len);
+ btrfs_run_delayed_items(trans, root);
}
kfree(victim_name);
ptr = (unsigned long)(victim_ref + 1) + victim_name_len;
@@ -1476,6 +1479,9 @@ again:
ret = btrfs_unlink_inode(trans, root, dir, inode,
name, name_len);
BUG_ON(ret);
+
+ btrfs_run_delayed_items(trans, root);
+
kfree(name);
iput(inode);
diff --git a/fs/buffer.c b/fs/buffer.c
index 1a80b04..166028b 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -961,13 +961,14 @@ link_dev_buffers(struct page *page, struct buffer_head *head)
/*
* Initialise the state of a blockdev page's buffers.
*/
-static void
+static sector_t
init_page_buffers(struct page *page, struct block_device *bdev,
sector_t block, int size)
{
struct buffer_head *head = page_buffers(page);
struct buffer_head *bh = head;
int uptodate = PageUptodate(page);
+ sector_t end_block = blkdev_max_block(I_BDEV(bdev->bd_inode));
do {
if (!buffer_mapped(bh)) {
@@ -976,38 +977,47 @@ init_page_buffers(struct page *page, struct block_device *bdev,
bh->b_blocknr = block;
if (uptodate)
set_buffer_uptodate(bh);
- set_buffer_mapped(bh);
+ if (block < end_block)
+ set_buffer_mapped(bh);
}
block++;
bh = bh->b_this_page;
} while (bh != head);
+
+ /*
+ * Caller needs to validate requested block against end of device.
+ */
+ return end_block;
}
/*
* Create the page-cache page that contains the requested block.
*
- * This is user purely for blockdev mappings.
+ * This is used purely for blockdev mappings.
*/
-static struct page *
+static int
grow_dev_page(struct block_device *bdev, sector_t block,
- pgoff_t index, int size)
+ pgoff_t index, int size, int sizebits)
{
struct inode *inode = bdev->bd_inode;
struct page *page;
struct buffer_head *bh;
+ sector_t end_block;
+ int ret = 0; /* Will call free_more_memory() */
page = find_or_create_page(inode->i_mapping, index,
(mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS)|__GFP_MOVABLE);
if (!page)
- return NULL;
+ return ret;
BUG_ON(!PageLocked(page));
if (page_has_buffers(page)) {
bh = page_buffers(page);
if (bh->b_size == size) {
- init_page_buffers(page, bdev, block, size);
- return page;
+ end_block = init_page_buffers(page, bdev,
+ index << sizebits, size);
+ goto done;
}
if (!try_to_free_buffers(page))
goto failed;
@@ -1027,15 +1037,15 @@ grow_dev_page(struct block_device *bdev, sector_t block,
*/
spin_lock(&inode->i_mapping->private_lock);
link_dev_buffers(page, bh);
- init_page_buffers(page, bdev, block, size);
+ end_block = init_page_buffers(page, bdev, index << sizebits, size);
spin_unlock(&inode->i_mapping->private_lock);
- return page;
+done:
+ ret = (block < end_block) ? 1 : -ENXIO;
failed:
- BUG();
unlock_page(page);
page_cache_release(page);
- return NULL;
+ return ret;
}
/*
@@ -1045,7 +1055,6 @@ failed:
static int
grow_buffers(struct block_device *bdev, sector_t block, int size)
{
- struct page *page;
pgoff_t index;
int sizebits;
@@ -1069,14 +1078,9 @@ grow_buffers(struct block_device *bdev, sector_t block, int size)
bdevname(bdev, b));
return -EIO;
}
- block = index << sizebits;
+
/* Create a page with the proper size buffers.. */
- page = grow_dev_page(bdev, block, index, size);
- if (!page)
- return 0;
- unlock_page(page);
- page_cache_release(page);
- return 1;
+ return grow_dev_page(bdev, block, index, size, sizebits);
}
static struct buffer_head *
@@ -1095,7 +1099,7 @@ __getblk_slow(struct block_device *bdev, sector_t block, int size)
}
for (;;) {
- struct buffer_head * bh;
+ struct buffer_head *bh;
int ret;
bh = __find_get_block(bdev, block, size);
@@ -1363,10 +1367,6 @@ EXPORT_SYMBOL(__find_get_block);
* which corresponds to the passed block_device, block and size. The
* returned buffer has its reference count incremented.
*
- * __getblk() cannot fail - it just keeps trying. If you pass it an
- * illegal block number, __getblk() will happily return a buffer_head
- * which represents the non-existent block. Very weird.
- *
* __getblk() will lock up the machine if grow_dev_page's try_to_free_buffers()
* attempt is failing. FIXME, perhaps?
*/
diff --git a/fs/ceph/export.c b/fs/ceph/export.c
index f67b687..a080779 100644
--- a/fs/ceph/export.c
+++ b/fs/ceph/export.c
@@ -84,7 +84,7 @@ static int ceph_encode_fh(struct dentry *dentry, u32 *rawfh, int *max_len,
* FIXME: we should try harder by querying the mds for the ino.
*/
static struct dentry *__fh_to_dentry(struct super_block *sb,
- struct ceph_nfs_fh *fh)
+ struct ceph_nfs_fh *fh, int fh_len)
{
struct ceph_mds_client *mdsc = ceph_sb_to_client(sb)->mdsc;
struct inode *inode;
@@ -92,6 +92,9 @@ static struct dentry *__fh_to_dentry(struct super_block *sb,
struct ceph_vino vino;
int err;
+ if (fh_len < sizeof(*fh) / 4)
+ return ERR_PTR(-ESTALE);
+
dout("__fh_to_dentry %llx\n", fh->ino);
vino.ino = fh->ino;
vino.snap = CEPH_NOSNAP;
@@ -136,7 +139,7 @@ static struct dentry *__fh_to_dentry(struct super_block *sb,
* convert connectable fh to dentry
*/
static struct dentry *__cfh_to_dentry(struct super_block *sb,
- struct ceph_nfs_confh *cfh)
+ struct ceph_nfs_confh *cfh, int fh_len)
{
struct ceph_mds_client *mdsc = ceph_sb_to_client(sb)->mdsc;
struct inode *inode;
@@ -144,6 +147,9 @@ static struct dentry *__cfh_to_dentry(struct super_block *sb,
struct ceph_vino vino;
int err;
+ if (fh_len < sizeof(*cfh) / 4)
+ return ERR_PTR(-ESTALE);
+
dout("__cfh_to_dentry %llx (%llx/%x)\n",
cfh->ino, cfh->parent_ino, cfh->parent_name_hash);
@@ -193,9 +199,11 @@ static struct dentry *ceph_fh_to_dentry(struct super_block *sb, struct fid *fid,
int fh_len, int fh_type)
{
if (fh_type == 1)
- return __fh_to_dentry(sb, (struct ceph_nfs_fh *)fid->raw);
+ return __fh_to_dentry(sb, (struct ceph_nfs_fh *)fid->raw,
+ fh_len);
else
- return __cfh_to_dentry(sb, (struct ceph_nfs_confh *)fid->raw);
+ return __cfh_to_dentry(sb, (struct ceph_nfs_confh *)fid->raw,
+ fh_len);
}
/*
@@ -216,6 +224,8 @@ static struct dentry *ceph_fh_to_parent(struct super_block *sb,
if (fh_type == 1)
return ERR_PTR(-ESTALE);
+ if (fh_len < sizeof(*cfh) / 4)
+ return ERR_PTR(-ESTALE);
pr_debug("fh_to_parent %llx/%d\n", cfh->parent_ino,
cfh->parent_name_hash);
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 6255fa8..7cb9dd2 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -43,6 +43,7 @@
#define CIFS_MIN_RCV_POOL 4
+#define MAX_REOPEN_ATT 5 /* these many maximum attempts to reopen a file */
/*
* default attribute cache timeout (jiffies)
*/
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index a9b4a24..9040cb0 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -973,10 +973,11 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
bool fsuid_only)
{
- struct cifsFileInfo *open_file;
+ struct cifsFileInfo *open_file, *inv_file = NULL;
struct cifs_sb_info *cifs_sb;
bool any_available = false;
int rc;
+ unsigned int refind = 0;
/* Having a null inode here (because mapping->host was set to zero by
the VFS or MM) should not happen but we had reports of on oops (due to
@@ -996,40 +997,25 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
spin_lock(&cifs_file_list_lock);
refind_writable:
+ if (refind > MAX_REOPEN_ATT) {
+ spin_unlock(&cifs_file_list_lock);
+ return NULL;
+ }
list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
if (!any_available && open_file->pid != current->tgid)
continue;
if (fsuid_only && open_file->uid != current_fsuid())
continue;
if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
- cifsFileInfo_get(open_file);
-
if (!open_file->invalidHandle) {
/* found a good writable file */
+ cifsFileInfo_get(open_file);
spin_unlock(&cifs_file_list_lock);
return open_file;
+ } else {
+ if (!inv_file)
+ inv_file = open_file;
}
-
- spin_unlock(&cifs_file_list_lock);
-
- /* Had to unlock since following call can block */
- rc = cifs_reopen_file(open_file, false);
- if (!rc)
- return open_file;
-
- /* if it fails, try another handle if possible */
- cFYI(1, "wp failed on reopen file");
- cifsFileInfo_put(open_file);
-
- spin_lock(&cifs_file_list_lock);
-
- /* else we simply continue to the next entry. Thus
- we do not loop on reopen errors. If we
- can not reopen the file, for example if we
- reconnected to a server with another client
- racing to delete or lock the file we would not
- make progress if we restarted before the beginning
- of the loop here. */
}
}
/* couldn't find useable FH with same pid, try any available */
@@ -1037,7 +1023,30 @@ refind_writable:
any_available = true;
goto refind_writable;
}
+
+ if (inv_file) {
+ any_available = false;
+ cifsFileInfo_get(inv_file);
+ }
+
spin_unlock(&cifs_file_list_lock);
+
+ if (inv_file) {
+ rc = cifs_reopen_file(inv_file, false);
+ if (!rc)
+ return inv_file;
+ else {
+ spin_lock(&cifs_file_list_lock);
+ list_move_tail(&inv_file->flist,
+ &cifs_inode->openFileList);
+ spin_unlock(&cifs_file_list_lock);
+ cifsFileInfo_put(inv_file);
+ spin_lock(&cifs_file_list_lock);
+ ++refind;
+ goto refind_writable;
+ }
+ }
+
return NULL;
}
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 6751e74..c71032b 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -85,9 +85,12 @@ cifs_readdir_lookup(struct dentry *parent, struct qstr *name,
dentry = d_lookup(parent, name);
if (dentry) {
- /* FIXME: check for inode number changes? */
- if (dentry->d_inode != NULL)
+ inode = dentry->d_inode;
+ /* update inode in place if i_ino didn't change */
+ if (inode && CIFS_I(inode)->uniqueid == fattr->cf_uniqueid) {
+ cifs_fattr_to_inode(inode, fattr);
return dentry;
+ }
d_drop(dentry);
dput(dentry);
}
diff --git a/fs/compat.c b/fs/compat.c
index 0ea0083..e5358c2 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1177,11 +1177,14 @@ compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec,
struct file *file;
int fput_needed;
ssize_t ret;
+ loff_t pos;
file = fget_light(fd, &fput_needed);
if (!file)
return -EBADF;
- ret = compat_readv(file, vec, vlen, &file->f_pos);
+ pos = file->f_pos;
+ ret = compat_readv(file, vec, vlen, &pos);
+ file->f_pos = pos;
fput_light(file, fput_needed);
return ret;
}
@@ -1236,11 +1239,14 @@ compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec,
struct file *file;
int fput_needed;
ssize_t ret;
+ loff_t pos;
file = fget_light(fd, &fput_needed);
if (!file)
return -EBADF;
- ret = compat_writev(file, vec, vlen, &file->f_pos);
+ pos = file->f_pos;
+ ret = compat_writev(file, vec, vlen, &pos);
+ file->f_pos = pos;
fput_light(file, fput_needed);
return ret;
}
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index 61abb63..3deb58d 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -208,6 +208,8 @@ static int do_video_set_spu_palette(unsigned int fd, unsigned int cmd,
err = get_user(palp, &up->palette);
err |= get_user(length, &up->length);
+ if (err)
+ return -EFAULT;
up_native = compat_alloc_user_space(sizeof(struct video_spu_palette));
err = put_user(compat_ptr(palp), &up_native->palette);
diff --git a/fs/dcache.c b/fs/dcache.c
index 0b51cfc..8b64f38 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -290,7 +290,7 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent)
* Inform try_to_ascend() that we are no longer attached to the
* dentry tree
*/
- dentry->d_flags |= DCACHE_DISCONNECTED;
+ dentry->d_flags |= DCACHE_DENTRY_KILLED;
if (parent)
spin_unlock(&parent->d_lock);
dentry_iput(dentry);
@@ -1015,7 +1015,7 @@ static struct dentry *try_to_ascend(struct dentry *old, int locked, unsigned seq
* or deletion
*/
if (new != old->d_parent ||
- (old->d_flags & DCACHE_DISCONNECTED) ||
+ (old->d_flags & DCACHE_DENTRY_KILLED) ||
(!locked && read_seqretry(&rename_lock, seq))) {
spin_unlock(&new->d_lock);
new = NULL;
@@ -1101,6 +1101,8 @@ positive:
return 1;
rename_retry:
+ if (locked)
+ goto again;
locked = 1;
write_seqlock(&rename_lock);
goto again;
@@ -1203,6 +1205,8 @@ out:
rename_retry:
if (found)
return found;
+ if (locked)
+ goto again;
locked = 1;
write_seqlock(&rename_lock);
goto again;
@@ -2990,6 +2994,8 @@ resume:
return;
rename_retry:
+ if (locked)
+ goto again;
locked = 1;
write_seqlock(&rename_lock);
goto again;
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 2717329..4a91a05 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -653,6 +653,7 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct dentry *lower_old_dir_dentry;
struct dentry *lower_new_dir_dentry;
struct dentry *trap = NULL;
+ struct inode *target_inode;
lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry);
@@ -660,6 +661,7 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
dget(lower_new_dentry);
lower_old_dir_dentry = dget_parent(lower_old_dentry);
lower_new_dir_dentry = dget_parent(lower_new_dentry);
+ target_inode = new_dentry->d_inode;
trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
/* source should not be ancestor of target */
if (trap == lower_old_dentry) {
@@ -675,6 +677,9 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
lower_new_dir_dentry->d_inode, lower_new_dentry);
if (rc)
goto out_lock;
+ if (target_inode)
+ fsstack_copy_attr_all(target_inode,
+ ecryptfs_inode_to_lower(target_inode));
fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode);
if (new_dir != old_dir)
fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode);
diff --git a/fs/ecryptfs/kthread.c b/fs/ecryptfs/kthread.c
index 69f994a..0dbe58a 100644
--- a/fs/ecryptfs/kthread.c
+++ b/fs/ecryptfs/kthread.c
@@ -149,7 +149,7 @@ int ecryptfs_privileged_open(struct file **lower_file,
(*lower_file) = dentry_open(lower_dentry, lower_mnt, flags, cred);
if (!IS_ERR(*lower_file))
goto out;
- if (flags & O_RDONLY) {
+ if ((flags & O_ACCMODE) == O_RDONLY) {
rc = PTR_ERR((*lower_file));
goto out;
}
diff --git a/fs/ecryptfs/miscdev.c b/fs/ecryptfs/miscdev.c
index 0dc5a3d..de42310 100644
--- a/fs/ecryptfs/miscdev.c
+++ b/fs/ecryptfs/miscdev.c
@@ -49,7 +49,10 @@ ecryptfs_miscdev_poll(struct file *file, poll_table *pt)
mutex_lock(&ecryptfs_daemon_hash_mux);
/* TODO: Just use file->private_data? */
rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns());
- BUG_ON(rc || !daemon);
+ if (rc || !daemon) {
+ mutex_unlock(&ecryptfs_daemon_hash_mux);
+ return -EINVAL;
+ }
mutex_lock(&daemon->mux);
mutex_unlock(&ecryptfs_daemon_hash_mux);
if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) {
@@ -122,6 +125,7 @@ ecryptfs_miscdev_open(struct inode *inode, struct file *file)
goto out_unlock_daemon;
}
daemon->flags |= ECRYPTFS_DAEMON_MISCDEV_OPEN;
+ file->private_data = daemon;
atomic_inc(&ecryptfs_num_miscdev_opens);
out_unlock_daemon:
mutex_unlock(&daemon->mux);
@@ -152,9 +156,9 @@ ecryptfs_miscdev_release(struct inode *inode, struct file *file)
mutex_lock(&ecryptfs_daemon_hash_mux);
rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns());
- BUG_ON(rc || !daemon);
+ if (rc || !daemon)
+ daemon = file->private_data;
mutex_lock(&daemon->mux);
- BUG_ON(daemon->pid != task_pid(current));
BUG_ON(!(daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN));
daemon->flags &= ~ECRYPTFS_DAEMON_MISCDEV_OPEN;
atomic_dec(&ecryptfs_num_miscdev_opens);
@@ -191,31 +195,32 @@ int ecryptfs_send_miscdev(char *data, size_t data_size,
struct ecryptfs_msg_ctx *msg_ctx, u8 msg_type,
u16 msg_flags, struct ecryptfs_daemon *daemon)
{
- int rc = 0;
+ struct ecryptfs_message *msg;
- mutex_lock(&msg_ctx->mux);
- msg_ctx->msg = kmalloc((sizeof(*msg_ctx->msg) + data_size),
- GFP_KERNEL);
- if (!msg_ctx->msg) {
- rc = -ENOMEM;
+ msg = kmalloc((sizeof(*msg) + data_size), GFP_KERNEL);
+ if (!msg) {
printk(KERN_ERR "%s: Out of memory whilst attempting "
"to kmalloc(%zd, GFP_KERNEL)\n", __func__,
- (sizeof(*msg_ctx->msg) + data_size));
- goto out_unlock;
+ (sizeof(*msg) + data_size));
+ return -ENOMEM;
}
+
+ mutex_lock(&msg_ctx->mux);
+ msg_ctx->msg = msg;
msg_ctx->msg->index = msg_ctx->index;
msg_ctx->msg->data_len = data_size;
msg_ctx->type = msg_type;
memcpy(msg_ctx->msg->data, data, data_size);
msg_ctx->msg_size = (sizeof(*msg_ctx->msg) + data_size);
- mutex_lock(&daemon->mux);
list_add_tail(&msg_ctx->daemon_out_list, &daemon->msg_ctx_out_queue);
+ mutex_unlock(&msg_ctx->mux);
+
+ mutex_lock(&daemon->mux);
daemon->num_queued_msg_ctx++;
wake_up_interruptible(&daemon->wait);
mutex_unlock(&daemon->mux);
-out_unlock:
- mutex_unlock(&msg_ctx->mux);
- return rc;
+
+ return 0;
}
/**
@@ -246,8 +251,16 @@ ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count,
mutex_lock(&ecryptfs_daemon_hash_mux);
/* TODO: Just use file->private_data? */
rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns());
- BUG_ON(rc || !daemon);
+ if (rc || !daemon) {
+ mutex_unlock(&ecryptfs_daemon_hash_mux);
+ return -EINVAL;
+ }
mutex_lock(&daemon->mux);
+ if (task_pid(current) != daemon->pid) {
+ mutex_unlock(&daemon->mux);
+ mutex_unlock(&ecryptfs_daemon_hash_mux);
+ return -EPERM;
+ }
if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) {
rc = 0;
mutex_unlock(&ecryptfs_daemon_hash_mux);
@@ -284,9 +297,6 @@ check_list:
* message from the queue; try again */
goto check_list;
}
- BUG_ON(euid != daemon->euid);
- BUG_ON(current_user_ns() != daemon->user_ns);
- BUG_ON(task_pid(current) != daemon->pid);
msg_ctx = list_first_entry(&daemon->msg_ctx_out_queue,
struct ecryptfs_msg_ctx, daemon_out_list);
BUG_ON(!msg_ctx);
diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
index bfc2dc4..0b3da7c 100644
--- a/fs/ext3/ialloc.c
+++ b/fs/ext3/ialloc.c
@@ -561,8 +561,12 @@ got:
if (IS_DIRSYNC(inode))
handle->h_sync = 1;
if (insert_inode_locked(inode) < 0) {
- err = -EINVAL;
- goto fail_drop;
+ /*
+ * Likely a bitmap corruption causing inode to be allocated
+ * twice.
+ */
+ err = -EIO;
+ goto fail;
}
spin_lock(&sbi->s_next_gen_lock);
inode->i_generation = sbi->s_next_generation++;
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index db9ba1a..0aedb27 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -3013,6 +3013,8 @@ static int ext3_do_update_inode(handle_t *handle,
struct ext3_inode_info *ei = EXT3_I(inode);
struct buffer_head *bh = iloc->bh;
int err = 0, rc, block;
+ int need_datasync = 0;
+ __le32 disksize;
again:
/* we can't allow multiple procs in here at once, its a bit racey */
@@ -3050,7 +3052,11 @@ again:
raw_inode->i_gid_high = 0;
}
raw_inode->i_links_count = cpu_to_le16(inode->i_nlink);
- raw_inode->i_size = cpu_to_le32(ei->i_disksize);
+ disksize = cpu_to_le32(ei->i_disksize);
+ if (disksize != raw_inode->i_size) {
+ need_datasync = 1;
+ raw_inode->i_size = disksize;
+ }
raw_inode->i_atime = cpu_to_le32(inode->i_atime.tv_sec);
raw_inode->i_ctime = cpu_to_le32(inode->i_ctime.tv_sec);
raw_inode->i_mtime = cpu_to_le32(inode->i_mtime.tv_sec);
@@ -3066,8 +3072,11 @@ again:
if (!S_ISREG(inode->i_mode)) {
raw_inode->i_dir_acl = cpu_to_le32(ei->i_dir_acl);
} else {
- raw_inode->i_size_high =
- cpu_to_le32(ei->i_disksize >> 32);
+ disksize = cpu_to_le32(ei->i_disksize >> 32);
+ if (disksize != raw_inode->i_size_high) {
+ raw_inode->i_size_high = disksize;
+ need_datasync = 1;
+ }
if (ei->i_disksize > 0x7fffffffULL) {
struct super_block *sb = inode->i_sb;
if (!EXT3_HAS_RO_COMPAT_FEATURE(sb,
@@ -3120,6 +3129,8 @@ again:
ext3_clear_inode_state(inode, EXT3_STATE_NEW);
atomic_set(&ei->i_sync_tid, handle->h_transaction->t_tid);
+ if (need_datasync)
+ atomic_set(&ei->i_datasync_tid, handle->h_transaction->t_tid);
out_brelse:
brelse (bh);
ext3_std_error(inode->i_sb, err);
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 264f694..ebe95f5 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -514,7 +514,8 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb)
if (bitmap_bh == NULL)
continue;
- x = ext4_count_free(bitmap_bh, sb->s_blocksize);
+ x = ext4_count_free(bitmap_bh->b_data,
+ EXT4_BLOCKS_PER_GROUP(sb) / 8);
printk(KERN_DEBUG "group %u: stored = %d, counted = %u\n",
i, ext4_free_blks_count(sb, gdp), x);
bitmap_count += x;
diff --git a/fs/ext4/bitmap.c b/fs/ext4/bitmap.c
index fa3af81..012faaa 100644
--- a/fs/ext4/bitmap.c
+++ b/fs/ext4/bitmap.c
@@ -15,15 +15,13 @@
static const int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
-unsigned int ext4_count_free(struct buffer_head *map, unsigned int numchars)
+unsigned int ext4_count_free(char *bitmap, unsigned int numchars)
{
unsigned int i, sum = 0;
- if (!map)
- return 0;
for (i = 0; i < numchars; i++)
- sum += nibblemap[map->b_data[i] & 0xf] +
- nibblemap[(map->b_data[i] >> 4) & 0xf];
+ sum += nibblemap[bitmap[i] & 0xf] +
+ nibblemap[(bitmap[i] >> 4) & 0xf];
return sum;
}
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 1a34c1c..e0113aa 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1713,7 +1713,7 @@ struct mmpd_data {
# define NORET_AND noreturn,
/* bitmap.c */
-extern unsigned int ext4_count_free(struct buffer_head *, unsigned);
+extern unsigned int ext4_count_free(char *bitmap, unsigned numchars);
/* balloc.c */
extern unsigned int ext4_block_group(struct super_block *sb,
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 21bb2f6..29272de 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -1021,8 +1021,12 @@ got:
if (IS_DIRSYNC(inode))
ext4_handle_sync(handle);
if (insert_inode_locked(inode) < 0) {
- err = -EINVAL;
- goto fail_drop;
+ /*
+ * Likely a bitmap corruption causing inode to be allocated
+ * twice.
+ */
+ err = -EIO;
+ goto fail;
}
spin_lock(&sbi->s_next_gen_lock);
inode->i_generation = sbi->s_next_generation++;
@@ -1189,7 +1193,8 @@ unsigned long ext4_count_free_inodes(struct super_block *sb)
if (!bitmap_bh)
continue;
- x = ext4_count_free(bitmap_bh, EXT4_INODES_PER_GROUP(sb) / 8);
+ x = ext4_count_free(bitmap_bh->b_data,
+ EXT4_INODES_PER_GROUP(sb) / 8);
printk(KERN_DEBUG "group %lu: stored = %d, counted = %lu\n",
(unsigned long) i, ext4_free_inodes_count(sb, gdp), x);
bitmap_count += x;
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index c1e6a72..1dbf758 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1134,6 +1134,15 @@ void ext4_da_update_reserve_space(struct inode *inode,
used = ei->i_reserved_data_blocks;
}
+ if (unlikely(ei->i_allocated_meta_blocks > ei->i_reserved_meta_blocks)) {
+ ext4_msg(inode->i_sb, KERN_NOTICE, "%s: ino %lu, allocated %d "
+ "with only %d reserved metadata blocks\n", __func__,
+ inode->i_ino, ei->i_allocated_meta_blocks,
+ ei->i_reserved_meta_blocks);
+ WARN_ON(1);
+ ei->i_allocated_meta_blocks = ei->i_reserved_meta_blocks;
+ }
+
/* Update per-inode reservations */
ei->i_reserved_data_blocks -= used;
ei->i_reserved_meta_blocks -= ei->i_allocated_meta_blocks;
@@ -5142,6 +5151,7 @@ static int ext4_do_update_inode(handle_t *handle,
struct ext4_inode_info *ei = EXT4_I(inode);
struct buffer_head *bh = iloc->bh;
int err = 0, rc, block;
+ int need_datasync = 0;
/* For fields not not tracking in the in-memory inode,
* initialise them to zero for new inodes. */
@@ -5190,7 +5200,10 @@ static int ext4_do_update_inode(handle_t *handle,
raw_inode->i_file_acl_high =
cpu_to_le16(ei->i_file_acl >> 32);
raw_inode->i_file_acl_lo = cpu_to_le32(ei->i_file_acl);
- ext4_isize_set(raw_inode, ei->i_disksize);
+ if (ei->i_disksize != ext4_isize(raw_inode)) {
+ ext4_isize_set(raw_inode, ei->i_disksize);
+ need_datasync = 1;
+ }
if (ei->i_disksize > 0x7fffffffULL) {
struct super_block *sb = inode->i_sb;
if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
@@ -5243,7 +5256,7 @@ static int ext4_do_update_inode(handle_t *handle,
err = rc;
ext4_clear_inode_state(inode, EXT4_STATE_NEW);
- ext4_update_inode_fsync_trans(handle, inode, 0);
+ ext4_update_inode_fsync_trans(handle, inode, need_datasync);
out_brelse:
brelse(bh);
ext4_std_error(inode->i_sb, err);
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index 808c554..4cbe1c2 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -35,7 +35,7 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
handle_t *handle = NULL;
int err, migrate = 0;
struct ext4_iloc iloc;
- unsigned int oldflags;
+ unsigned int oldflags, mask, i;
unsigned int jflag;
if (!inode_owner_or_capable(inode))
@@ -112,9 +112,14 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
if (err)
goto flags_err;
- flags = flags & EXT4_FL_USER_MODIFIABLE;
- flags |= oldflags & ~EXT4_FL_USER_MODIFIABLE;
- ei->i_flags = flags;
+ for (i = 0, mask = 1; i < 32; i++, mask <<= 1) {
+ if (!(mask & EXT4_FL_USER_MODIFIABLE))
+ continue;
+ if (mask & flags)
+ ext4_set_inode_flag(inode, i);
+ else
+ ext4_clear_inode_flag(inode, i);
+ }
ext4_set_inode_flags(inode);
inode->i_ctime = ext4_current_time(inode);
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 0f1be7f..b6adf68 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -2528,6 +2528,9 @@ int ext4_mb_release(struct super_block *sb)
struct ext4_sb_info *sbi = EXT4_SB(sb);
struct kmem_cache *cachep = get_groupinfo_cache(sb->s_blocksize_bits);
+ if (sbi->s_proc)
+ remove_proc_entry("mb_groups", sbi->s_proc);
+
if (sbi->s_group_info) {
for (i = 0; i < ngroups; i++) {
grinfo = ext4_get_group_info(sb, i);
@@ -2575,8 +2578,6 @@ int ext4_mb_release(struct super_block *sb)
}
free_percpu(sbi->s_locality_groups);
- if (sbi->s_proc)
- remove_proc_entry("mb_groups", sbi->s_proc);
return 0;
}
@@ -4583,6 +4584,7 @@ do_more:
*/
new_entry = kmem_cache_alloc(ext4_free_ext_cachep, GFP_NOFS);
if (!new_entry) {
+ ext4_mb_unload_buddy(&e4b);
err = -ENOMEM;
goto error_return;
}
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
index f57455a..72f9732 100644
--- a/fs/ext4/move_extent.c
+++ b/fs/ext4/move_extent.c
@@ -1209,7 +1209,12 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp,
orig_inode->i_ino, donor_inode->i_ino);
return -EINVAL;
}
-
+ /* TODO: This is non obvious task to swap blocks for inodes with full
+ jornaling enabled */
+ if (ext4_should_journal_data(orig_inode) ||
+ ext4_should_journal_data(donor_inode)) {
+ return -EINVAL;
+ }
/* Protect orig and donor inodes against a truncate */
ret1 = mext_inode_double_lock(orig_inode, donor_inode);
if (ret1 < 0)
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 3d36d5a..78585fc 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -1799,9 +1799,7 @@ retry:
err = PTR_ERR(inode);
if (!IS_ERR(inode)) {
init_special_inode(inode, inode->i_mode, rdev);
-#ifdef CONFIG_EXT4_FS_XATTR
inode->i_op = &ext4_special_inode_operations;
-#endif
err = ext4_add_nondir(handle, dentry, inode);
}
ext4_journal_stop(handle);
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 63fe3ca..489d406 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -860,6 +860,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
ei->i_reserved_meta_blocks = 0;
ei->i_allocated_meta_blocks = 0;
ei->i_da_metadata_calc_len = 0;
+ ei->i_da_metadata_calc_last_lblock = 0;
spin_lock_init(&(ei->i_block_reservation_lock));
#ifdef CONFIG_QUOTA
ei->i_reserved_quota = 0;
@@ -3619,7 +3620,8 @@ no_journal:
goto failed_mount4;
}
- ext4_setup_super(sb, es, sb->s_flags & MS_RDONLY);
+ if (ext4_setup_super(sb, es, sb->s_flags & MS_RDONLY))
+ sb->s_flags |= MS_RDONLY;
/* determine the minimum size of new large inodes, if present */
if (sbi->s_inode_size > EXT4_GOOD_OLD_INODE_SIZE) {
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index 19fe4e3..c2865cc 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -487,18 +487,19 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode,
ext4_free_blocks(handle, inode, bh, 0, 1,
EXT4_FREE_BLOCKS_METADATA |
EXT4_FREE_BLOCKS_FORGET);
+ unlock_buffer(bh);
} else {
le32_add_cpu(&BHDR(bh)->h_refcount, -1);
+ if (ce)
+ mb_cache_entry_release(ce);
+ unlock_buffer(bh);
error = ext4_handle_dirty_metadata(handle, inode, bh);
if (IS_SYNC(inode))
ext4_handle_sync(handle);
dquot_free_block(inode, 1);
ea_bdebug(bh, "refcount now=%d; releasing",
le32_to_cpu(BHDR(bh)->h_refcount));
- if (ce)
- mb_cache_entry_release(ce);
}
- unlock_buffer(bh);
out:
ext4_std_error(inode->i_sb, error);
return;
diff --git a/fs/fifo.c b/fs/fifo.c
index b1a524d..cf6f434 100644
--- a/fs/fifo.c
+++ b/fs/fifo.c
@@ -14,7 +14,7 @@
#include <linux/sched.h>
#include <linux/pipe_fs_i.h>
-static void wait_for_partner(struct inode* inode, unsigned int *cnt)
+static int wait_for_partner(struct inode* inode, unsigned int *cnt)
{
int cur = *cnt;
@@ -23,6 +23,7 @@ static void wait_for_partner(struct inode* inode, unsigned int *cnt)
if (signal_pending(current))
break;
}
+ return cur == *cnt ? -ERESTARTSYS : 0;
}
static void wake_up_partner(struct inode* inode)
@@ -67,8 +68,7 @@ static int fifo_open(struct inode *inode, struct file *filp)
* seen a writer */
filp->f_version = pipe->w_counter;
} else {
- wait_for_partner(inode, &pipe->w_counter);
- if(signal_pending(current))
+ if (wait_for_partner(inode, &pipe->w_counter))
goto err_rd;
}
}
@@ -90,8 +90,7 @@ static int fifo_open(struct inode *inode, struct file *filp)
wake_up_partner(inode);
if (!pipe->readers) {
- wait_for_partner(inode, &pipe->r_counter);
- if (signal_pending(current))
+ if (wait_for_partner(inode, &pipe->r_counter))
goto err_wr;
}
break;
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index c858b5c..947b822 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -1528,6 +1528,7 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode,
req->pages[req->num_pages] = page;
req->num_pages++;
+ offset = 0;
num -= this_num;
total_len += this_num;
index++;
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index d5016071..c04a025 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -858,6 +858,7 @@ int fuse_update_attributes(struct inode *inode, struct kstat *stat,
if (stat) {
generic_fillattr(inode, stat);
stat->mode = fi->orig_i_mode;
+ stat->ino = fi->orig_ino;
}
}
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 82a6646..79fca8d 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -1710,7 +1710,7 @@ static int fuse_verify_ioctl_iov(struct iovec *iov, size_t count)
size_t n;
u32 max = FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT;
- for (n = 0; n < count; n++) {
+ for (n = 0; n < count; n++, iov++) {
if (iov->iov_len > (size_t) max)
return -ENOMEM;
max -= iov->iov_len;
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index b788bec..f621550 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -82,6 +82,9 @@ struct fuse_inode {
preserve the original mode */
mode_t orig_i_mode;
+ /** 64 bit inode number */
+ u64 orig_ino;
+
/** Version of last attribute change */
u64 attr_version;
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 38f84cd..69a1e0f 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -91,6 +91,7 @@ static struct inode *fuse_alloc_inode(struct super_block *sb)
fi->nlookup = 0;
fi->attr_version = 0;
fi->writectr = 0;
+ fi->orig_ino = 0;
INIT_LIST_HEAD(&fi->write_files);
INIT_LIST_HEAD(&fi->queued_writes);
INIT_LIST_HEAD(&fi->writepages);
@@ -140,6 +141,18 @@ static int fuse_remount_fs(struct super_block *sb, int *flags, char *data)
return 0;
}
+/*
+ * ino_t is 32-bits on 32-bit arch. We have to squash the 64-bit value down
+ * so that it will fit.
+ */
+static ino_t fuse_squash_ino(u64 ino64)
+{
+ ino_t ino = (ino_t) ino64;
+ if (sizeof(ino_t) < sizeof(u64))
+ ino ^= ino64 >> (sizeof(u64) - sizeof(ino_t)) * 8;
+ return ino;
+}
+
void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
u64 attr_valid)
{
@@ -149,7 +162,7 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
fi->attr_version = ++fc->attr_version;
fi->i_time = attr_valid;
- inode->i_ino = attr->ino;
+ inode->i_ino = fuse_squash_ino(attr->ino);
inode->i_mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
inode->i_nlink = attr->nlink;
inode->i_uid = attr->uid;
@@ -175,6 +188,8 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
fi->orig_i_mode = inode->i_mode;
if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS))
inode->i_mode &= ~S_ISVTX;
+
+ fi->orig_ino = attr->ino;
}
void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
diff --git a/fs/gfs2/export.c b/fs/gfs2/export.c
index fe9945f..5235d6e 100644
--- a/fs/gfs2/export.c
+++ b/fs/gfs2/export.c
@@ -167,6 +167,8 @@ static struct dentry *gfs2_fh_to_dentry(struct super_block *sb, struct fid *fid,
case GFS2_SMALL_FH_SIZE:
case GFS2_LARGE_FH_SIZE:
case GFS2_OLD_FH_SIZE:
+ if (fh_len < GFS2_SMALL_FH_SIZE)
+ return NULL;
this.no_formal_ino = ((u64)be32_to_cpu(fh[0])) << 32;
this.no_formal_ino |= be32_to_cpu(fh[1]);
this.no_addr = ((u64)be32_to_cpu(fh[2])) << 32;
@@ -186,6 +188,8 @@ static struct dentry *gfs2_fh_to_parent(struct super_block *sb, struct fid *fid,
switch (fh_type) {
case GFS2_LARGE_FH_SIZE:
case GFS2_OLD_FH_SIZE:
+ if (fh_len < GFS2_LARGE_FH_SIZE)
+ return NULL;
parent.no_formal_ino = ((u64)be32_to_cpu(fh[4])) << 32;
parent.no_formal_ino |= be32_to_cpu(fh[5]);
parent.no_addr = ((u64)be32_to_cpu(fh[6])) << 32;
diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c
index 7b8112d..aac1563 100644
--- a/fs/hfsplus/wrapper.c
+++ b/fs/hfsplus/wrapper.c
@@ -56,7 +56,7 @@ int hfsplus_submit_bio(struct super_block *sb, sector_t sector,
DECLARE_COMPLETION_ONSTACK(wait);
struct bio *bio;
int ret = 0;
- unsigned int io_size;
+ u64 io_size;
loff_t start;
int offset;
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 8b0c875..6327a06 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -568,7 +568,8 @@ static int hugetlbfs_set_page_dirty(struct page *page)
}
static int hugetlbfs_migrate_page(struct address_space *mapping,
- struct page *newpage, struct page *page)
+ struct page *newpage, struct page *page,
+ enum migrate_mode mode)
{
int rc;
diff --git a/fs/ioprio.c b/fs/ioprio.c
index 7da2a06..95a6c2b 100644
--- a/fs/ioprio.c
+++ b/fs/ioprio.c
@@ -30,7 +30,7 @@
int set_task_ioprio(struct task_struct *task, int ioprio)
{
- int err;
+ int err, i;
struct io_context *ioc;
const struct cred *cred = current_cred(), *tcred;
@@ -60,12 +60,17 @@ int set_task_ioprio(struct task_struct *task, int ioprio)
err = -ENOMEM;
break;
}
+ /* let other ioc users see the new values */
+ smp_wmb();
task->io_context = ioc;
} while (1);
if (!err) {
ioc->ioprio = ioprio;
- ioc->ioprio_changed = 1;
+ /* make sure schedulers see the new ioprio value */
+ wmb();
+ for (i = 0; i < IOC_IOPRIO_CHANGED_BITS; i++)
+ set_bit(i, ioc->ioprio_changed);
}
task_unlock(task);
diff --git a/fs/isofs/export.c b/fs/isofs/export.c
index dd4687f..516eb21 100644
--- a/fs/isofs/export.c
+++ b/fs/isofs/export.c
@@ -179,7 +179,7 @@ static struct dentry *isofs_fh_to_parent(struct super_block *sb,
{
struct isofs_fid *ifid = (struct isofs_fid *)fid;
- if (fh_type != 2)
+ if (fh_len < 2 || fh_type != 2)
return NULL;
return isofs_export_iget(sb,
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
index 72ffa97..dcd23f8 100644
--- a/fs/jbd/commit.c
+++ b/fs/jbd/commit.c
@@ -85,7 +85,12 @@ nope:
static void release_data_buffer(struct buffer_head *bh)
{
if (buffer_freed(bh)) {
+ WARN_ON_ONCE(buffer_dirty(bh));
clear_buffer_freed(bh);
+ clear_buffer_mapped(bh);
+ clear_buffer_new(bh);
+ clear_buffer_req(bh);
+ bh->b_bdev = NULL;
release_buffer_page(bh);
} else
put_bh(bh);
@@ -840,17 +845,35 @@ restart_loop:
* there's no point in keeping a checkpoint record for
* it. */
- /* A buffer which has been freed while still being
- * journaled by a previous transaction may end up still
- * being dirty here, but we want to avoid writing back
- * that buffer in the future after the "add to orphan"
- * operation been committed, That's not only a performance
- * gain, it also stops aliasing problems if the buffer is
- * left behind for writeback and gets reallocated for another
- * use in a different page. */
- if (buffer_freed(bh) && !jh->b_next_transaction) {
- clear_buffer_freed(bh);
- clear_buffer_jbddirty(bh);
+ /*
+ * A buffer which has been freed while still being journaled by
+ * a previous transaction.
+ */
+ if (buffer_freed(bh)) {
+ /*
+ * If the running transaction is the one containing
+ * "add to orphan" operation (b_next_transaction !=
+ * NULL), we have to wait for that transaction to
+ * commit before we can really get rid of the buffer.
+ * So just clear b_modified to not confuse transaction
+ * credit accounting and refile the buffer to
+ * BJ_Forget of the running transaction. If the just
+ * committed transaction contains "add to orphan"
+ * operation, we can completely invalidate the buffer
+ * now. We are rather throughout in that since the
+ * buffer may be still accessible when blocksize <
+ * pagesize and it is attached to the last partial
+ * page.
+ */
+ jh->b_modified = 0;
+ if (!jh->b_next_transaction) {
+ clear_buffer_freed(bh);
+ clear_buffer_jbddirty(bh);
+ clear_buffer_mapped(bh);
+ clear_buffer_new(bh);
+ clear_buffer_req(bh);
+ bh->b_bdev = NULL;
+ }
}
if (buffer_jbddirty(bh)) {
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c
index f7ee81a..b0161a6 100644
--- a/fs/jbd/transaction.c
+++ b/fs/jbd/transaction.c
@@ -1837,15 +1837,16 @@ static int __dispose_buffer(struct journal_head *jh, transaction_t *transaction)
* We're outside-transaction here. Either or both of j_running_transaction
* and j_committing_transaction may be NULL.
*/
-static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh)
+static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh,
+ int partial_page)
{
transaction_t *transaction;
struct journal_head *jh;
int may_free = 1;
- int ret;
BUFFER_TRACE(bh, "entry");
+retry:
/*
* It is safe to proceed here without the j_list_lock because the
* buffers cannot be stolen by try_to_free_buffers as long as we are
@@ -1873,10 +1874,18 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh)
* clear the buffer dirty bit at latest at the moment when the
* transaction marking the buffer as freed in the filesystem
* structures is committed because from that moment on the
- * buffer can be reallocated and used by a different page.
+ * block can be reallocated and used by a different page.
* Since the block hasn't been freed yet but the inode has
* already been added to orphan list, it is safe for us to add
* the buffer to BJ_Forget list of the newest transaction.
+ *
+ * Also we have to clear buffer_mapped flag of a truncated buffer
+ * because the buffer_head may be attached to the page straddling
+ * i_size (can happen only when blocksize < pagesize) and thus the
+ * buffer_head can be reused when the file is extended again. So we end
+ * up keeping around invalidated buffers attached to transactions'
+ * BJ_Forget list just to stop checkpointing code from cleaning up
+ * the transaction this buffer was modified in.
*/
transaction = jh->b_transaction;
if (transaction == NULL) {
@@ -1903,13 +1912,9 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh)
* committed, the buffer won't be needed any
* longer. */
JBUFFER_TRACE(jh, "checkpointed: add to BJ_Forget");
- ret = __dispose_buffer(jh,
+ may_free = __dispose_buffer(jh,
journal->j_running_transaction);
- journal_put_journal_head(jh);
- spin_unlock(&journal->j_list_lock);
- jbd_unlock_bh_state(bh);
- spin_unlock(&journal->j_state_lock);
- return ret;
+ goto zap_buffer;
} else {
/* There is no currently-running transaction. So the
* orphan record which we wrote for this file must have
@@ -1917,13 +1922,9 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh)
* the committing transaction, if it exists. */
if (journal->j_committing_transaction) {
JBUFFER_TRACE(jh, "give to committing trans");
- ret = __dispose_buffer(jh,
+ may_free = __dispose_buffer(jh,
journal->j_committing_transaction);
- journal_put_journal_head(jh);
- spin_unlock(&journal->j_list_lock);
- jbd_unlock_bh_state(bh);
- spin_unlock(&journal->j_state_lock);
- return ret;
+ goto zap_buffer;
} else {
/* The orphan record's transaction has
* committed. We can cleanse this buffer */
@@ -1944,10 +1945,24 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh)
}
/*
* The buffer is committing, we simply cannot touch
- * it. So we just set j_next_transaction to the
- * running transaction (if there is one) and mark
- * buffer as freed so that commit code knows it should
- * clear dirty bits when it is done with the buffer.
+ * it. If the page is straddling i_size we have to wait
+ * for commit and try again.
+ */
+ if (partial_page) {
+ tid_t tid = journal->j_committing_transaction->t_tid;
+
+ journal_put_journal_head(jh);
+ spin_unlock(&journal->j_list_lock);
+ jbd_unlock_bh_state(bh);
+ spin_unlock(&journal->j_state_lock);
+ log_wait_commit(journal, tid);
+ goto retry;
+ }
+ /*
+ * OK, buffer won't be reachable after truncate. We just set
+ * j_next_transaction to the running transaction (if there is
+ * one) and mark buffer as freed so that commit code knows it
+ * should clear dirty bits when it is done with the buffer.
*/
set_buffer_freed(bh);
if (journal->j_running_transaction && buffer_jbddirty(bh))
@@ -1970,6 +1985,14 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh)
}
zap_buffer:
+ /*
+ * This is tricky. Although the buffer is truncated, it may be reused
+ * if blocksize < pagesize and it is attached to the page straddling
+ * EOF. Since the buffer might have been added to BJ_Forget list of the
+ * running transaction, journal_get_write_access() won't clear
+ * b_modified and credit accounting gets confused. So clear b_modified
+ * here. */
+ jh->b_modified = 0;
journal_put_journal_head(jh);
zap_buffer_no_jh:
spin_unlock(&journal->j_list_lock);
@@ -2018,7 +2041,8 @@ void journal_invalidatepage(journal_t *journal,
if (offset <= curr_off) {
/* This block is wholly outside the truncation point */
lock_buffer(bh);
- may_free &= journal_unmap_buffer(journal, bh);
+ may_free &= journal_unmap_buffer(journal, bh,
+ offset > 0);
unlock_buffer(bh);
}
curr_off = next_off;
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
index 36c2e80..2ace3c4 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -345,6 +345,15 @@ void jbd2_journal_commit_transaction(journal_t *journal)
jbd_debug(3, "superblock not updated\n");
}
+ if (journal->j_running_transaction == NULL) {
+ /* If we're going to trigger the J_ASSERT below, let's
+ print some debugging information to figure out why
+ kjournald decided to wake up and call us */
+ printk(KERN_ERR "JBD2 ASSERT DEBUG: commit_sequence=%d, "
+ "commit_request=%d\n", journal->j_commit_sequence,
+ journal->j_commit_request);
+ }
+
J_ASSERT(journal->j_running_transaction != NULL);
J_ASSERT(journal->j_committing_transaction == NULL);
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index 31dce61..4bbd521 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -225,8 +225,8 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
return 0;
D1(printk(KERN_DEBUG "No progress from erasing blocks; doing GC anyway\n"));
- spin_lock(&c->erase_completion_lock);
mutex_lock(&c->alloc_sem);
+ spin_lock(&c->erase_completion_lock);
}
/* First, work out which block we're garbage-collecting */
diff --git a/fs/lockd/clntxdr.c b/fs/lockd/clntxdr.c
index 36057ce..6e2a2d5 100644
--- a/fs/lockd/clntxdr.c
+++ b/fs/lockd/clntxdr.c
@@ -223,7 +223,7 @@ static void encode_nlm_stat(struct xdr_stream *xdr,
{
__be32 *p;
- BUG_ON(be32_to_cpu(stat) > NLM_LCK_DENIED_GRACE_PERIOD);
+ WARN_ON_ONCE(be32_to_cpu(stat) > NLM_LCK_DENIED_GRACE_PERIOD);
p = xdr_reserve_space(xdr, 4);
*p = stat;
}
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index d27aab1..d413af3 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -67,7 +67,8 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
/* Obtain file pointer. Not used by FREE_ALL call. */
if (filp != NULL) {
- if ((error = nlm_lookup_file(rqstp, &file, &lock->fh)) != 0)
+ error = cast_status(nlm_lookup_file(rqstp, &file, &lock->fh));
+ if (error != 0)
goto no_locks;
*filp = file;
diff --git a/fs/locks.c b/fs/locks.c
index b286539..35388d5 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -315,7 +315,7 @@ static int flock_make_lock(struct file *filp, struct file_lock **lock,
return 0;
}
-static int assign_type(struct file_lock *fl, int type)
+static int assign_type(struct file_lock *fl, long type)
{
switch (type) {
case F_RDLCK:
@@ -452,7 +452,7 @@ static const struct lock_manager_operations lease_manager_ops = {
/*
* Initialize a lease, use the default lock manager operations
*/
-static int lease_init(struct file *filp, int type, struct file_lock *fl)
+static int lease_init(struct file *filp, long type, struct file_lock *fl)
{
if (assign_type(fl, type) != 0)
return -EINVAL;
@@ -470,7 +470,7 @@ static int lease_init(struct file *filp, int type, struct file_lock *fl)
}
/* Allocate a file_lock initialised to this type of lease */
-static struct file_lock *lease_alloc(struct file *filp, int type)
+static struct file_lock *lease_alloc(struct file *filp, long type)
{
struct file_lock *fl = locks_alloc_lock();
int error = -ENOMEM;
diff --git a/fs/namespace.c b/fs/namespace.c
index edc1c4a..b3d8f51 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1244,8 +1244,9 @@ void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill)
list_del_init(&p->mnt_expire);
list_del_init(&p->mnt_list);
__touch_mnt_namespace(p->mnt_ns);
+ if (p->mnt_ns)
+ __mnt_make_shortterm(p);
p->mnt_ns = NULL;
- __mnt_make_shortterm(p);
list_del_init(&p->mnt_child);
if (p->mnt_parent != p) {
p->mnt_parent->mnt_ghosts++;
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index dd2f130..6c6e2c4 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -493,8 +493,11 @@ static int nfs_release_page(struct page *page, gfp_t gfp)
dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page);
- /* Only do I/O if gfp is a superset of GFP_KERNEL */
- if (mapping && (gfp & GFP_KERNEL) == GFP_KERNEL) {
+ /* Only do I/O if gfp is a superset of GFP_KERNEL, and we're not
+ * doing this memory reclaim for a fs-related allocation.
+ */
+ if (mapping && (gfp & GFP_KERNEL) == GFP_KERNEL &&
+ !(current->flags & PF_FSTRANS)) {
int how = FLUSH_SYNC;
/* Don't let kswapd deadlock waiting for OOM RPC calls */
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index c48f9f6..873c6f2 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -150,7 +150,7 @@ static void nfs_zap_caches_locked(struct inode *inode)
nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);
nfsi->attrtimeo_timestamp = jiffies;
- memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode)));
+ memset(NFS_I(inode)->cookieverf, 0, sizeof(NFS_I(inode)->cookieverf));
if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))
nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE;
else
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 2a55347..4f10d81 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -315,7 +315,7 @@ void nfs_commit_release_pages(struct nfs_write_data *data);
#ifdef CONFIG_MIGRATION
extern int nfs_migrate_page(struct address_space *,
- struct page *, struct page *);
+ struct page *, struct page *, enum migrate_mode);
#else
#define nfs_migrate_page NULL
#endif
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 771741f..f0a6990 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -68,7 +68,7 @@ do_proc_get_root(struct rpc_clnt *client, struct nfs_fh *fhandle,
nfs_fattr_init(info->fattr);
status = rpc_call_sync(client, &msg, 0);
dprintk("%s: reply fsinfo: %d\n", __func__, status);
- if (!(info->fattr->valid & NFS_ATTR_FATTR)) {
+ if (status == 0 && !(info->fattr->valid & NFS_ATTR_FATTR)) {
msg.rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR];
msg.rpc_resp = info->fattr;
status = rpc_call_sync(client, &msg, 0);
@@ -633,7 +633,7 @@ nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
u64 cookie, struct page **pages, unsigned int count, int plus)
{
struct inode *dir = dentry->d_inode;
- __be32 *verf = NFS_COOKIEVERF(dir);
+ __be32 *verf = NFS_I(dir)->cookieverf;
struct nfs3_readdirargs arg = {
.fh = NFS_FH(dir),
.cookie = cookie,
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 3d67302..c722905 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -94,6 +94,8 @@ static int nfs4_map_errors(int err)
case -NFS4ERR_BADOWNER:
case -NFS4ERR_BADNAME:
return -EINVAL;
+ case -NFS4ERR_SHARE_DENIED:
+ return -EACCES;
default:
dprintk("%s could not handle NFSv4 error %d\n",
__func__, -err);
@@ -1771,6 +1773,7 @@ static int _nfs4_do_open(struct inode *dir, struct path *path, fmode_t fmode, in
nfs_setattr_update_inode(state->inode, sattr);
nfs_post_op_update_inode(state->inode, opendata->o_res.f_attr);
}
+ nfs_revalidate_inode(server, state->inode);
nfs4_opendata_put(opendata);
nfs4_put_state_owner(sp);
*res = state;
@@ -3015,11 +3018,11 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
dentry->d_parent->d_name.name,
dentry->d_name.name,
(unsigned long long)cookie);
- nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args);
+ nfs4_setup_readdir(cookie, NFS_I(dir)->cookieverf, dentry, &args);
res.pgbase = args.pgbase;
status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &msg, &args.seq_args, &res.seq_res, 0);
if (status >= 0) {
- memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE);
+ memcpy(NFS_I(dir)->cookieverf, res.verifier.data, NFS4_VERIFIER_SIZE);
status += args.pgbase;
}
@@ -5763,12 +5766,8 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
return;
}
spin_lock(&lo->plh_inode->i_lock);
- if (task->tk_status == 0) {
- if (lrp->res.lrs_present) {
- pnfs_set_layout_stateid(lo, &lrp->res.stateid, true);
- } else
- BUG_ON(!list_empty(&lo->plh_segs));
- }
+ if (task->tk_status == 0 && lrp->res.lrs_present)
+ pnfs_set_layout_stateid(lo, &lrp->res.stateid, true);
lo->plh_block_lgets--;
spin_unlock(&lo->plh_inode->i_lock);
dprintk("<-- %s\n", __func__);
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index fc97fd5..5fcc67b 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -5745,7 +5745,8 @@ static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
status = decode_open(xdr, res);
if (status)
goto out;
- if (decode_getfh(xdr, &res->fh) != 0)
+ status = decode_getfh(xdr, &res->fh);
+ if (status)
goto out;
if (decode_getfattr(xdr, res->f_attr, res->server,
!RPC_IS_ASYNC(rqstp->rq_task)) != 0)
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 8e7b61d..a1f3d6e 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -1815,6 +1815,7 @@ static int nfs_validate_mount_data(void *options,
memcpy(sap, &data->addr, sizeof(data->addr));
args->nfs_server.addrlen = sizeof(data->addr);
+ args->nfs_server.port = ntohs(data->addr.sin_port);
if (!nfs_verify_server_address(sap))
goto out_no_address;
@@ -2528,6 +2529,7 @@ static int nfs4_validate_mount_data(void *options,
return -EFAULT;
if (!nfs_verify_server_address(sap))
goto out_no_address;
+ args->nfs_server.port = ntohs(((struct sockaddr_in *)sap)->sin_port);
if (data->auth_flavourlen) {
if (data->auth_flavourlen > 1)
@@ -3096,4 +3098,6 @@ static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type,
return res;
}
+MODULE_ALIAS("nfs4");
+
#endif /* CONFIG_NFS_V4 */
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index f2f80c0..58bb999 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1662,7 +1662,7 @@ out_error:
#ifdef CONFIG_MIGRATION
int nfs_migrate_page(struct address_space *mapping, struct page *newpage,
- struct page *page)
+ struct page *page, enum migrate_mode mode)
{
/*
* If PagePrivate is set, then the page is currently associated with
@@ -1677,7 +1677,7 @@ int nfs_migrate_page(struct address_space *mapping, struct page *newpage,
nfs_fscache_release_page(page, GFP_KERNEL);
- return migrate_page(mapping, newpage, page);
+ return migrate_page(mapping, newpage, page, mode);
}
#endif
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 6c74097..f91d589 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -2010,7 +2010,7 @@ out_acl:
if (bmval0 & FATTR4_WORD0_CASE_INSENSITIVE) {
if ((buflen -= 4) < 0)
goto out_resource;
- WRITE32(1);
+ WRITE32(0);
}
if (bmval0 & FATTR4_WORD0_CASE_PRESERVING) {
if ((buflen -= 4) < 0)
diff --git a/fs/nilfs2/gcinode.c b/fs/nilfs2/gcinode.c
index 08a07a2..57ceaf3 100644
--- a/fs/nilfs2/gcinode.c
+++ b/fs/nilfs2/gcinode.c
@@ -191,6 +191,8 @@ void nilfs_remove_all_gcinodes(struct the_nilfs *nilfs)
while (!list_empty(head)) {
ii = list_first_entry(head, struct nilfs_inode_info, i_dirty);
list_del_init(&ii->i_dirty);
+ truncate_inode_pages(&ii->vfs_inode.i_data, 0);
+ nilfs_btnode_cache_clear(&ii->i_btnode_cache);
iput(&ii->vfs_inode);
}
}
diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c
index 3e65427..0d1c9bd 100644
--- a/fs/nilfs2/ioctl.c
+++ b/fs/nilfs2/ioctl.c
@@ -182,7 +182,7 @@ static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp,
if (copy_from_user(&cpmode, argp, sizeof(cpmode)))
goto out;
- down_read(&inode->i_sb->s_umount);
+ mutex_lock(&nilfs->ns_snapshot_mount_mutex);
nilfs_transaction_begin(inode->i_sb, &ti, 0);
ret = nilfs_cpfile_change_cpmode(
@@ -192,7 +192,7 @@ static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp,
else
nilfs_transaction_commit(inode->i_sb); /* never fails */
- up_read(&inode->i_sb->s_umount);
+ mutex_unlock(&nilfs->ns_snapshot_mount_mutex);
out:
mnt_drop_write(filp->f_path.mnt);
return ret;
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
index bb24ab6..6f24e67 100644
--- a/fs/nilfs2/segment.c
+++ b/fs/nilfs2/segment.c
@@ -2309,6 +2309,8 @@ nilfs_remove_written_gcinodes(struct the_nilfs *nilfs, struct list_head *head)
if (!test_bit(NILFS_I_UPDATED, &ii->i_state))
continue;
list_del_init(&ii->i_dirty);
+ truncate_inode_pages(&ii->vfs_inode.i_data, 0);
+ nilfs_btnode_cache_clear(&ii->i_btnode_cache);
iput(&ii->vfs_inode);
}
}
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c
index 8351c44..97bfbdd 100644
--- a/fs/nilfs2/super.c
+++ b/fs/nilfs2/super.c
@@ -951,6 +951,8 @@ static int nilfs_attach_snapshot(struct super_block *s, __u64 cno,
struct nilfs_root *root;
int ret;
+ mutex_lock(&nilfs->ns_snapshot_mount_mutex);
+
down_read(&nilfs->ns_segctor_sem);
ret = nilfs_cpfile_is_snapshot(nilfs->ns_cpfile, cno);
up_read(&nilfs->ns_segctor_sem);
@@ -975,6 +977,7 @@ static int nilfs_attach_snapshot(struct super_block *s, __u64 cno,
ret = nilfs_get_root_dentry(s, root, root_dentry);
nilfs_put_root(root);
out:
+ mutex_unlock(&nilfs->ns_snapshot_mount_mutex);
return ret;
}
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c
index 35a8970..1c98f53 100644
--- a/fs/nilfs2/the_nilfs.c
+++ b/fs/nilfs2/the_nilfs.c
@@ -76,6 +76,7 @@ struct the_nilfs *alloc_nilfs(struct block_device *bdev)
nilfs->ns_bdev = bdev;
atomic_set(&nilfs->ns_ndirtyblks, 0);
init_rwsem(&nilfs->ns_sem);
+ mutex_init(&nilfs->ns_snapshot_mount_mutex);
INIT_LIST_HEAD(&nilfs->ns_dirty_files);
INIT_LIST_HEAD(&nilfs->ns_gc_inodes);
spin_lock_init(&nilfs->ns_inode_lock);
diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h
index 9992b11..de7435f 100644
--- a/fs/nilfs2/the_nilfs.h
+++ b/fs/nilfs2/the_nilfs.h
@@ -47,6 +47,7 @@ enum {
* @ns_flags: flags
* @ns_bdev: block device
* @ns_sem: semaphore for shared states
+ * @ns_snapshot_mount_mutex: mutex to protect snapshot mounts
* @ns_sbh: buffer heads of on-disk super blocks
* @ns_sbp: pointers to super block data
* @ns_sbwtime: previous write time of super block
@@ -99,6 +100,7 @@ struct the_nilfs {
struct block_device *ns_bdev;
struct rw_semaphore ns_sem;
+ struct mutex ns_snapshot_mount_mutex;
/*
* used for
diff --git a/fs/open.c b/fs/open.c
index b52cf01..bf00a86 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -396,10 +396,10 @@ SYSCALL_DEFINE1(fchdir, unsigned int, fd)
{
struct file *file;
struct inode *inode;
- int error;
+ int error, fput_needed;
error = -EBADF;
- file = fget(fd);
+ file = fget_raw_light(fd, &fput_needed);
if (!file)
goto out;
@@ -413,7 +413,7 @@ SYSCALL_DEFINE1(fchdir, unsigned int, fd)
if (!error)
set_fs_pwd(current->fs, &file->f_path);
out_putf:
- fput(file);
+ fput_light(file, fput_needed);
out:
return error;
}
@@ -900,9 +900,10 @@ static inline int build_open_flags(int flags, int mode, struct open_flags *op)
int lookup_flags = 0;
int acc_mode;
- if (!(flags & O_CREAT))
- mode = 0;
- op->mode = mode;
+ if (flags & O_CREAT)
+ op->mode = (mode & S_IALLUGO) | S_IFREG;
+ else
+ op->mode = 0;
/* Must never be set by userspace */
flags &= ~FMODE_NONOTIFY;
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c
index fbb0b47..d5378d0 100644
--- a/fs/ramfs/file-nommu.c
+++ b/fs/ramfs/file-nommu.c
@@ -110,6 +110,7 @@ int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize)
/* prevent the page from being discarded on memory pressure */
SetPageDirty(page);
+ SetPageUptodate(page);
unlock_page(page);
put_page(page);
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 4fd5bb3..0363aa4 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -1568,8 +1568,10 @@ struct dentry *reiserfs_fh_to_dentry(struct super_block *sb, struct fid *fid,
reiserfs_warning(sb, "reiserfs-13077",
"nfsd/reiserfs, fhtype=%d, len=%d - odd",
fh_type, fh_len);
- fh_type = 5;
+ fh_type = fh_len;
}
+ if (fh_len < 2)
+ return NULL;
return reiserfs_get_dentry(sb, fid->raw[0], fid->raw[1],
(fh_type == 3 || fh_type >= 5) ? fid->raw[2] : 0);
@@ -1578,6 +1580,8 @@ struct dentry *reiserfs_fh_to_dentry(struct super_block *sb, struct fid *fid,
struct dentry *reiserfs_fh_to_parent(struct super_block *sb, struct fid *fid,
int fh_len, int fh_type)
{
+ if (fh_type > fh_len)
+ fh_type = fh_len;
if (fh_type < 4)
return NULL;
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
index 7438850..b5a8636 100644
--- a/fs/squashfs/super.c
+++ b/fs/squashfs/super.c
@@ -290,7 +290,7 @@ handle_fragments:
check_directory_table:
/* Sanity check directory_table */
- if (msblk->directory_table >= next_table) {
+ if (msblk->directory_table > next_table) {
err = -EINVAL;
goto failed_mount;
}
diff --git a/fs/stat.c b/fs/stat.c
index 02a6061..aec24ec 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -57,7 +57,7 @@ EXPORT_SYMBOL(vfs_getattr);
int vfs_fstat(unsigned int fd, struct kstat *stat)
{
- struct file *f = fget(fd);
+ struct file *f = fget_raw(fd);
int error = -EBADF;
if (f) {
diff --git a/fs/super.c b/fs/super.c
index ab3d672..caf4dfa 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -1009,6 +1009,8 @@ int freeze_super(struct super_block *sb)
printk(KERN_ERR
"VFS:Filesystem freeze failed\n");
sb->s_frozen = SB_UNFROZEN;
+ smp_wmb();
+ wake_up(&sb->s_wait_unfrozen);
deactivate_locked_super(sb);
return ret;
}
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index ea9120a..567b3db 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -404,20 +404,18 @@ int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
/**
* sysfs_pathname - return full path to sysfs dirent
* @sd: sysfs_dirent whose path we want
- * @path: caller allocated buffer
+ * @path: caller allocated buffer of size PATH_MAX
*
* Gives the name "/" to the sysfs_root entry; any path returned
* is relative to wherever sysfs is mounted.
- *
- * XXX: does no error checking on @path size
*/
static char *sysfs_pathname(struct sysfs_dirent *sd, char *path)
{
if (sd->s_parent) {
sysfs_pathname(sd->s_parent, path);
- strcat(path, "/");
+ strlcat(path, "/", PATH_MAX);
}
- strcat(path, sd->s_name);
+ strlcat(path, sd->s_name, PATH_MAX);
return path;
}
@@ -450,9 +448,11 @@ int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
char *path = kzalloc(PATH_MAX, GFP_KERNEL);
WARN(1, KERN_WARNING
"sysfs: cannot create duplicate filename '%s'\n",
- (path == NULL) ? sd->s_name :
- strcat(strcat(sysfs_pathname(acxt->parent_sd, path), "/"),
- sd->s_name));
+ (path == NULL) ? sd->s_name
+ : (sysfs_pathname(acxt->parent_sd, path),
+ strlcat(path, "/", PATH_MAX),
+ strlcat(path, sd->s_name, PATH_MAX),
+ path));
kfree(path);
}
diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c
index c606f01..1250016 100644
--- a/fs/ubifs/sb.c
+++ b/fs/ubifs/sb.c
@@ -715,8 +715,12 @@ static int fixup_free_space(struct ubifs_info *c)
lnum = ubifs_next_log_lnum(c, lnum);
}
- /* Fixup the current log head */
- err = fixup_leb(c, c->lhead_lnum, c->lhead_offs);
+ /*
+ * Fixup the log head which contains the only a CS node at the
+ * beginning.
+ */
+ err = fixup_leb(c, c->lhead_lnum,
+ ALIGN(UBIFS_CS_NODE_SZ, c->min_io_size));
if (err)
goto out;
diff --git a/fs/udf/file.c b/fs/udf/file.c
index 3438b00..8eb9628 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -39,20 +39,24 @@
#include "udf_i.h"
#include "udf_sb.h"
-static int udf_adinicb_readpage(struct file *file, struct page *page)
+static void __udf_adinicb_readpage(struct page *page)
{
struct inode *inode = page->mapping->host;
char *kaddr;
struct udf_inode_info *iinfo = UDF_I(inode);
- BUG_ON(!PageLocked(page));
-
kaddr = kmap(page);
- memset(kaddr, 0, PAGE_CACHE_SIZE);
memcpy(kaddr, iinfo->i_ext.i_data + iinfo->i_lenEAttr, inode->i_size);
+ memset(kaddr + inode->i_size, 0, PAGE_CACHE_SIZE - inode->i_size);
flush_dcache_page(page);
SetPageUptodate(page);
kunmap(page);
+}
+
+static int udf_adinicb_readpage(struct file *file, struct page *page)
+{
+ BUG_ON(!PageLocked(page));
+ __udf_adinicb_readpage(page);
unlock_page(page);
return 0;
@@ -77,6 +81,25 @@ static int udf_adinicb_writepage(struct page *page,
return 0;
}
+static int udf_adinicb_write_begin(struct file *file,
+ struct address_space *mapping, loff_t pos,
+ unsigned len, unsigned flags, struct page **pagep,
+ void **fsdata)
+{
+ struct page *page;
+
+ if (WARN_ON_ONCE(pos >= PAGE_CACHE_SIZE))
+ return -EIO;
+ page = grab_cache_page_write_begin(mapping, 0, flags);
+ if (!page)
+ return -ENOMEM;
+ *pagep = page;
+
+ if (!PageUptodate(page) && len != PAGE_CACHE_SIZE)
+ __udf_adinicb_readpage(page);
+ return 0;
+}
+
static int udf_adinicb_write_end(struct file *file,
struct address_space *mapping,
loff_t pos, unsigned len, unsigned copied,
@@ -98,8 +121,8 @@ static int udf_adinicb_write_end(struct file *file,
const struct address_space_operations udf_adinicb_aops = {
.readpage = udf_adinicb_readpage,
.writepage = udf_adinicb_writepage,
- .write_begin = simple_write_begin,
- .write_end = udf_adinicb_write_end,
+ .write_begin = udf_adinicb_write_begin,
+ .write_end = udf_adinicb_write_end,
};
static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 7f0e18a..b0c7b53 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -56,6 +56,7 @@
#include <linux/seq_file.h>
#include <linux/bitmap.h>
#include <linux/crc-itu-t.h>
+#include <linux/log2.h>
#include <asm/byteorder.h>
#include "udf_sb.h"
@@ -1244,16 +1245,65 @@ out_bh:
return ret;
}
+static int udf_load_sparable_map(struct super_block *sb,
+ struct udf_part_map *map,
+ struct sparablePartitionMap *spm)
+{
+ uint32_t loc;
+ uint16_t ident;
+ struct sparingTable *st;
+ struct udf_sparing_data *sdata = &map->s_type_specific.s_sparing;
+ int i;
+ struct buffer_head *bh;
+
+ map->s_partition_type = UDF_SPARABLE_MAP15;
+ sdata->s_packet_len = le16_to_cpu(spm->packetLength);
+ if (!is_power_of_2(sdata->s_packet_len)) {
+ udf_error(sb, __func__, "error loading logical volume descriptor: "
+ "Invalid packet length %u\n",
+ (unsigned)sdata->s_packet_len);
+ return -EIO;
+ }
+ if (spm->numSparingTables > 4) {
+ udf_error(sb, __func__, "error loading logical volume descriptor: "
+ "Too many sparing tables (%d)\n",
+ (int)spm->numSparingTables);
+ return -EIO;
+ }
+
+ for (i = 0; i < spm->numSparingTables; i++) {
+ loc = le32_to_cpu(spm->locSparingTable[i]);
+ bh = udf_read_tagged(sb, loc, loc, &ident);
+ if (!bh)
+ continue;
+
+ st = (struct sparingTable *)bh->b_data;
+ if (ident != 0 ||
+ strncmp(st->sparingIdent.ident, UDF_ID_SPARING,
+ strlen(UDF_ID_SPARING)) ||
+ sizeof(*st) + le16_to_cpu(st->reallocationTableLen) >
+ sb->s_blocksize) {
+ brelse(bh);
+ continue;
+ }
+
+ sdata->s_spar_map[i] = bh;
+ }
+ map->s_partition_func = udf_get_pblock_spar15;
+ return 0;
+}
+
static int udf_load_logicalvol(struct super_block *sb, sector_t block,
struct kernel_lb_addr *fileset)
{
struct logicalVolDesc *lvd;
- int i, j, offset;
+ int i, offset;
uint8_t type;
struct udf_sb_info *sbi = UDF_SB(sb);
struct genericPartitionMap *gpm;
uint16_t ident;
struct buffer_head *bh;
+ unsigned int table_len;
int ret = 0;
bh = udf_read_tagged(sb, block, block, &ident);
@@ -1261,15 +1311,21 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block,
return 1;
BUG_ON(ident != TAG_IDENT_LVD);
lvd = (struct logicalVolDesc *)bh->b_data;
-
- i = udf_sb_alloc_partition_maps(sb, le32_to_cpu(lvd->numPartitionMaps));
- if (i != 0) {
- ret = i;
+ table_len = le32_to_cpu(lvd->mapTableLength);
+ if (sizeof(*lvd) + table_len > sb->s_blocksize) {
+ udf_error(sb, __func__, "error loading logical volume descriptor: "
+ "Partition table too long (%u > %lu)\n", table_len,
+ sb->s_blocksize - sizeof(*lvd));
+ ret = 1;
goto out_bh;
}
+ ret = udf_sb_alloc_partition_maps(sb, le32_to_cpu(lvd->numPartitionMaps));
+ if (ret)
+ goto out_bh;
+
for (i = 0, offset = 0;
- i < sbi->s_partitions && offset < le32_to_cpu(lvd->mapTableLength);
+ i < sbi->s_partitions && offset < table_len;
i++, offset += gpm->partitionMapLength) {
struct udf_part_map *map = &sbi->s_partmaps[i];
gpm = (struct genericPartitionMap *)
@@ -1304,38 +1360,11 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block,
} else if (!strncmp(upm2->partIdent.ident,
UDF_ID_SPARABLE,
strlen(UDF_ID_SPARABLE))) {
- uint32_t loc;
- struct sparingTable *st;
- struct sparablePartitionMap *spm =
- (struct sparablePartitionMap *)gpm;
-
- map->s_partition_type = UDF_SPARABLE_MAP15;
- map->s_type_specific.s_sparing.s_packet_len =
- le16_to_cpu(spm->packetLength);
- for (j = 0; j < spm->numSparingTables; j++) {
- struct buffer_head *bh2;
-
- loc = le32_to_cpu(
- spm->locSparingTable[j]);
- bh2 = udf_read_tagged(sb, loc, loc,
- &ident);
- map->s_type_specific.s_sparing.
- s_spar_map[j] = bh2;
-
- if (bh2 == NULL)
- continue;
-
- st = (struct sparingTable *)bh2->b_data;
- if (ident != 0 || strncmp(
- st->sparingIdent.ident,
- UDF_ID_SPARING,
- strlen(UDF_ID_SPARING))) {
- brelse(bh2);
- map->s_type_specific.s_sparing.
- s_spar_map[j] = NULL;
- }
+ if (udf_load_sparable_map(sb, map,
+ (struct sparablePartitionMap *)gpm) < 0) {
+ ret = 1;
+ goto out_bh;
}
- map->s_partition_func = udf_get_pblock_spar15;
} else if (!strncmp(upm2->partIdent.ident,
UDF_ID_METADATA,
strlen(UDF_ID_METADATA))) {
diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/linux-2.6/xfs_export.c
index fed3f3c..844b22b 100644
--- a/fs/xfs/linux-2.6/xfs_export.c
+++ b/fs/xfs/linux-2.6/xfs_export.c
@@ -195,6 +195,9 @@ xfs_fs_fh_to_parent(struct super_block *sb, struct fid *fid,
struct xfs_fid64 *fid64 = (struct xfs_fid64 *)fid;
struct inode *inode = NULL;
+ if (fh_len < xfs_fileid_length(fileid_type))
+ return NULL;
+
switch (fileid_type) {
case FILEID_INO32_GEN_PARENT:
inode = xfs_nfs_get_inode(sb, fid->i32.parent_ino,
diff --git a/fs/yaffs2/yaffs_vfs.c b/fs/yaffs2/yaffs_vfs.c
index d5b8753..73fab7b 100644
--- a/fs/yaffs2/yaffs_vfs.c
+++ b/fs/yaffs2/yaffs_vfs.c
@@ -43,7 +43,6 @@
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/proc_fs.h>
-#include <linux/smp_lock.h>
#include <linux/pagemap.h>
#include <linux/mtd/mtd.h>
#include <linux/interrupt.h>
@@ -2375,19 +2374,19 @@ static int yaffs_internal_read_super_mtd(struct super_block *sb, void *data,
return yaffs_internal_read_super(1, sb, data, silent) ? 0 : -EINVAL;
}
-static int yaffs_read_super(struct file_system_type *fs,
- int flags, const char *dev_name,
- void *data, struct vfsmount *mnt)
+static struct dentry *yaffs_read_super(struct file_system_type *fs,
+ int flags, const char *dev_name,
+ void *data)
{
- return get_sb_bdev(fs, flags, dev_name, data,
- yaffs_internal_read_super_mtd, mnt);
+ return mount_bdev(fs, flags, dev_name, data,
+ yaffs_internal_read_super_mtd);
}
static struct file_system_type yaffs_fs_type = {
.owner = THIS_MODULE,
.name = "yaffs",
- .get_sb = yaffs_read_super,
+ .mount = yaffs_read_super,
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV,
};
@@ -2400,18 +2399,17 @@ static int yaffs2_internal_read_super_mtd(struct super_block *sb, void *data,
return yaffs_internal_read_super(2, sb, data, silent) ? 0 : -EINVAL;
}
-static int yaffs2_read_super(struct file_system_type *fs,
- int flags, const char *dev_name, void *data,
- struct vfsmount *mnt)
+static struct dentry *yaffs2_read_super(struct file_system_type *fs, int flags,
+ const char *dev_name, void *data)
{
- return get_sb_bdev(fs, flags, dev_name, data,
- yaffs2_internal_read_super_mtd, mnt);
+ return mount_bdev(fs, flags, dev_name, data,
+ yaffs2_internal_read_super_mtd);
}
static struct file_system_type yaffs2_fs_type = {
.owner = THIS_MODULE,
.name = "yaffs2",
- .get_sb = yaffs2_read_super,
+ .mount = yaffs2_read_super,
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV,
};
diff --git a/include/asm-generic/mutex-xchg.h b/include/asm-generic/mutex-xchg.h
index 580a6d3..c04e0db 100644
--- a/include/asm-generic/mutex-xchg.h
+++ b/include/asm-generic/mutex-xchg.h
@@ -26,7 +26,13 @@ static inline void
__mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
{
if (unlikely(atomic_xchg(count, 0) != 1))
- fail_fn(count);
+ /*
+ * We failed to acquire the lock, so mark it contended
+ * to ensure that any waiting tasks are woken up by the
+ * unlock slow path.
+ */
+ if (likely(atomic_xchg(count, -1) != 1))
+ fail_fn(count);
}
/**
@@ -43,7 +49,8 @@ static inline int
__mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
{
if (unlikely(atomic_xchg(count, 0) != 1))
- return fail_fn(count);
+ if (likely(atomic_xchg(count, -1) != 1))
+ return fail_fn(count);
return 0;
}
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index a03c098..831924a 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -445,6 +445,18 @@ static inline int pmd_write(pmd_t pmd)
#endif /* __HAVE_ARCH_PMD_WRITE */
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
+#ifndef pmd_read_atomic
+static inline pmd_t pmd_read_atomic(pmd_t *pmdp)
+{
+ /*
+ * Depend on compiler for an atomic pmd read. NOTE: this is
+ * only going to work, if the pmdval_t isn't larger than
+ * an unsigned long.
+ */
+ return *pmdp;
+}
+#endif
+
/*
* This function is meant to be used by sites walking pagetables with
* the mmap_sem hold in read mode to protect against MADV_DONTNEED and
@@ -458,11 +470,17 @@ static inline int pmd_write(pmd_t pmd)
* undefined so behaving like if the pmd was none is safe (because it
* can return none anyway). The compiler level barrier() is critically
* important to compute the two checks atomically on the same pmdval.
+ *
+ * For 32bit kernels with a 64bit large pmd_t this automatically takes
+ * care of reading the pmd atomically to avoid SMP race conditions
+ * against pmd_populate() when the mmap_sem is hold for reading by the
+ * caller (a special atomic read not done by "gcc" as in the generic
+ * version above, is also needed when THP is disabled because the page
+ * fault can populate the pmd from under us).
*/
static inline int pmd_none_or_trans_huge_or_clear_bad(pmd_t *pmd)
{
- /* depend on compiler for an atomic pmd read */
- pmd_t pmdval = *pmd;
+ pmd_t pmdval = pmd_read_atomic(pmd);
/*
* The barrier will stabilize the pmdval in a register or on
* the stack so that it will stop changing under the code.
diff --git a/include/asm-generic/statfs.h b/include/asm-generic/statfs.h
index 0fd28e0..c749af9 100644
--- a/include/asm-generic/statfs.h
+++ b/include/asm-generic/statfs.h
@@ -15,7 +15,7 @@ typedef __kernel_fsid_t fsid_t;
* with a 10' pole.
*/
#ifndef __statfs_word
-#if BITS_PER_LONG == 64
+#if __BITS_PER_LONG == 64
#define __statfs_word long
#else
#define __statfs_word __u32
diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h
index 14b6cd0..4306811 100644
--- a/include/drm/drm_pciids.h
+++ b/include/drm/drm_pciids.h
@@ -181,6 +181,7 @@
{0x1002, 0x6747, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6748, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6749, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \
+ {0x1002, 0x674A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6750, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6751, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6758, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \
@@ -198,6 +199,7 @@
{0x1002, 0x6767, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6768, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6770, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \
+ {0x1002, 0x6771, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6772, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6778, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6779, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \
diff --git a/include/linux/bld.h b/include/linux/bld.h
new file mode 100644
index 0000000..0026cf2
--- /dev/null
+++ b/include/linux/bld.h
@@ -0,0 +1,17 @@
+/* include/linux/bld.h */
+
+#ifndef _LINUX_BLD_H
+#define _LINUX_BLD_H
+
+#define BLD_TOUCHKEYS_POSITION 950
+
+struct bld_implementation
+{
+ void (* enable)(void);
+ void (* disable)(void);
+};
+
+void register_bld_implementation(struct bld_implementation * imp);
+void touchkey_pressed(void);
+
+#endif
diff --git a/include/linux/bln.h b/include/linux/bln.h
new file mode 100644
index 0000000..a5de5e4
--- /dev/null
+++ b/include/linux/bln.h
@@ -0,0 +1,13 @@
+/* include/linux/bln.h */
+
+#ifndef _LINUX_BLN_H
+#define _LINUX_BLN_H
+
+struct bln_implementation {
+ void (*enable)(void);
+ void (*disable)(void);
+};
+
+void register_bln_implementation(struct bln_implementation *imp);
+bool bln_is_ongoing(void);
+#endif
diff --git a/include/linux/cgroup_subsys.h b/include/linux/cgroup_subsys.h
index ac663c1..c966638 100644
--- a/include/linux/cgroup_subsys.h
+++ b/include/linux/cgroup_subsys.h
@@ -64,3 +64,9 @@ SUBSYS(perf)
#endif
/* */
+
+#ifdef CONFIG_CGROUP_BFQIO
+SUBSYS(bfqio)
+#endif
+
+/* */
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index 97f1ca7..111797a 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -66,8 +66,9 @@ enum {
/* migration should happen before other stuff but after perf */
CPU_PRI_PERF = 20,
CPU_PRI_MIGRATION = 10,
- /* prepare workqueues for other notifiers */
- CPU_PRI_WORKQUEUE = 5,
+ /* bring up workqueues before normal notifiers and down after */
+ CPU_PRI_WORKQUEUE_UP = 5,
+ CPU_PRI_WORKQUEUE_DOWN = -5,
};
#ifdef CONFIG_SMP
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index ae06dc9..193bfdf 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -393,6 +393,7 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu);
struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu);
void cpufreq_cpu_put(struct cpufreq_policy *data);
+extern unsigned int uIsSuspended;
/* the following are really really optional */
extern struct freq_attr cpufreq_freq_attr_scaling_available_freqs;
diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h
index e9eaec5..7a7e5fd 100644
--- a/include/linux/cpuset.h
+++ b/include/linux/cpuset.h
@@ -89,42 +89,33 @@ extern void rebuild_sched_domains(void);
extern void cpuset_print_task_mems_allowed(struct task_struct *p);
/*
- * reading current mems_allowed and mempolicy in the fastpath must protected
- * by get_mems_allowed()
+ * get_mems_allowed is required when making decisions involving mems_allowed
+ * such as during page allocation. mems_allowed can be updated in parallel
+ * and depending on the new value an operation can fail potentially causing
+ * process failure. A retry loop with get_mems_allowed and put_mems_allowed
+ * prevents these artificial failures.
*/
-static inline void get_mems_allowed(void)
+static inline unsigned int get_mems_allowed(void)
{
- current->mems_allowed_change_disable++;
-
- /*
- * ensure that reading mems_allowed and mempolicy happens after the
- * update of ->mems_allowed_change_disable.
- *
- * the write-side task finds ->mems_allowed_change_disable is not 0,
- * and knows the read-side task is reading mems_allowed or mempolicy,
- * so it will clear old bits lazily.
- */
- smp_mb();
+ return read_seqcount_begin(&current->mems_allowed_seq);
}
-static inline void put_mems_allowed(void)
+/*
+ * If this returns false, the operation that took place after get_mems_allowed
+ * may have failed. It is up to the caller to retry the operation if
+ * appropriate.
+ */
+static inline bool put_mems_allowed(unsigned int seq)
{
- /*
- * ensure that reading mems_allowed and mempolicy before reducing
- * mems_allowed_change_disable.
- *
- * the write-side task will know that the read-side task is still
- * reading mems_allowed or mempolicy, don't clears old bits in the
- * nodemask.
- */
- smp_mb();
- --ACCESS_ONCE(current->mems_allowed_change_disable);
+ return !read_seqcount_retry(&current->mems_allowed_seq, seq);
}
static inline void set_mems_allowed(nodemask_t nodemask)
{
task_lock(current);
+ write_seqcount_begin(&current->mems_allowed_seq);
current->mems_allowed = nodemask;
+ write_seqcount_end(&current->mems_allowed_seq);
task_unlock(current);
}
@@ -234,12 +225,14 @@ static inline void set_mems_allowed(nodemask_t nodemask)
{
}
-static inline void get_mems_allowed(void)
+static inline unsigned int get_mems_allowed(void)
{
+ return 0;
}
-static inline void put_mems_allowed(void)
+static inline bool put_mems_allowed(unsigned int seq)
{
+ return true;
}
#endif /* !CONFIG_CPUSETS */
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index f13bb6d..7d6a6b8 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -220,6 +220,8 @@ struct dentry_operations {
#define DCACHE_MANAGED_DENTRY \
(DCACHE_MOUNTED|DCACHE_NEED_AUTOMOUNT|DCACHE_MANAGE_TRANSIT)
+#define DCACHE_DENTRY_KILLED 0x100000
+
extern seqlock_t rename_lock;
static inline int dname_external(struct dentry *dentry)
diff --git a/include/linux/deep_idle.h b/include/linux/deep_idle.h
new file mode 100644
index 0000000..7c24c7f
--- /dev/null
+++ b/include/linux/deep_idle.h
@@ -0,0 +1,9 @@
+/* include/linux/deep_idle.h */
+
+#ifndef _LINUX_DEEPIDLE_H
+#define _LINUX_DEEPIDLE_H
+
+bool deepidle_is_enabled(void);
+void report_idle_time(int idle_state, int idle_time);
+
+#endif
diff --git a/include/linux/earlysuspend.h b/include/linux/earlysuspend.h
index 8343b81..fac1d8a 100755
--- a/include/linux/earlysuspend.h
+++ b/include/linux/earlysuspend.h
@@ -20,6 +20,8 @@
#include <linux/list.h>
#endif
+extern unsigned int is_device_lcd;
+
/* The early_suspend structure defines suspend and resume hooks to be called
* when the user visible sleep state of the system changes, and a level to
* control the order. They can be used to turn off the screen and input
diff --git a/include/linux/fs.h b/include/linux/fs.h
index d8ecb01..212ea7b 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -523,6 +523,7 @@ enum positive_aop_returns {
struct page;
struct address_space;
struct writeback_control;
+enum migrate_mode;
struct iov_iter {
const struct iovec *iov;
@@ -607,9 +608,12 @@ struct address_space_operations {
loff_t offset, unsigned long nr_segs);
int (*get_xip_mem)(struct address_space *, pgoff_t, int,
void **, unsigned long *);
- /* migrate the contents of a page to the specified target */
+ /*
+ * migrate the contents of a page to the specified target. If sync
+ * is false, it must not block.
+ */
int (*migratepage) (struct address_space *,
- struct page *, struct page *);
+ struct page *, struct page *, enum migrate_mode);
int (*launder_page) (struct page *);
int (*is_partially_uptodate) (struct page *, read_descriptor_t *,
unsigned long);
@@ -2029,6 +2033,7 @@ extern void unregister_blkdev(unsigned int, const char *);
extern struct block_device *bdget(dev_t);
extern struct block_device *bdgrab(struct block_device *bdev);
extern void bd_set_size(struct block_device *, loff_t size);
+extern sector_t blkdev_max_block(struct block_device *bdev);
extern void bd_forget(struct inode *inode);
extern void bdput(struct block_device *);
extern void invalidate_bdev(struct block_device *);
@@ -2477,7 +2482,8 @@ extern int generic_check_addressable(unsigned, u64);
#ifdef CONFIG_MIGRATION
extern int buffer_migrate_page(struct address_space *,
- struct page *, struct page *);
+ struct page *, struct page *,
+ enum migrate_mode);
#else
#define buffer_migrate_page NULL
#endif
diff --git a/include/linux/fsa9480.h b/include/linux/fsa9480.h
new file mode 100644
index 0000000..1097ee6
--- /dev/null
+++ b/include/linux/fsa9480.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2010 Samsung Electronics
+ * Minkyu Kang <mk7.kang@samsung.com>
+ * Wonguk Jeong <wonguk.jeong@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
+ *
+ */
+
+#ifndef _FSA9480_H_
+#define _FSA9480_H_
+
+enum {
+ FSA9480_DETACHED,
+ FSA9480_ATTACHED
+};
+
+struct fsa9480_platform_data {
+ void (*cfg_gpio) (void);
+ void (*usb_cb) (bool attached);
+ void (*uart_cb) (bool attached);
+ void (*charger_cb) (bool attached);
+ void (*jig_cb) (bool attached);
+ void (*deskdock_cb) (bool attached);
+ void (*cardock_cb) (bool attached);
+ void (*reset_cb) (void);
+};
+
+#endif /* _FSA9480_H_ */
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 6f43b14..7a1ce18 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -221,12 +221,6 @@ static inline void part_pack_uuid(const u8 *uuid_str, u8 *to)
}
}
-static inline char *part_unpack_uuid(const u8 *uuid, char *out)
-{
- sprintf(out, "%pU", uuid);
- return out;
-}
-
static inline int disk_max_parts(struct gendisk *disk)
{
if (disk->flags & GENHD_FL_EXT_DEVT)
diff --git a/include/linux/gp2a.h b/include/linux/gp2a.h
new file mode 100644
index 0000000..bf937aa
--- /dev/null
+++ b/include/linux/gp2a.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2010 Samsung Electronics. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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
+ */
+
+
+#ifndef __LINUX_GP2A_H
+#define __LINUX_GP2A_H
+
+#include <linux/types.h>
+
+#ifdef __KERNEL__
+#define GP2A_OPT "gp2a-opt"
+struct gp2a_platform_data {
+ int p_out; /* proximity-sensor-output gpio */
+ int (*power)(bool); /* power to the chip */
+ int (*light_adc_value)(void); /* get light level from adc */
+ int light_adc_max;
+ int light_adc_fuzz;
+};
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/include/linux/host_notify.h b/include/linux/host_notify.h
new file mode 100755
index 0000000..1ea0cd3
--- /dev/null
+++ b/include/linux/host_notify.h
@@ -0,0 +1,53 @@
+/*
+ * Host notify class driver
+ *
+ * Copyright (C) 2011 Samsung, Inc.
+ * Author: Dongrak Shin <dongrak.shin@samsung.com>
+ *
+*/
+
+#ifndef __LINUX_HOST_NOTIFY_H__
+#define __LINUX_HOST_NOTIFY_H__
+
+enum host_uevent_state {
+ NOTIFY_HOST_NONE,
+ NOTIFY_HOST_ADD,
+ NOTIFY_HOST_REMOVE,
+ NOTIFY_HOST_OVERCURRENT,
+ NOTIFY_HOST_LOWBATT,
+ NOTIFY_HOST_UNKNOWN,
+};
+
+enum otg_mode {
+ NOTIFY_NONE_MODE,
+ NOTIFY_HOST_MODE,
+ NOTIFY_PERIPHERAL_MODE,
+ NOTIFY_TEST_MODE,
+};
+
+enum booster_power{
+ NOTIFY_POWER_OFF,
+ NOTIFY_POWER_ON,
+};
+
+enum set_command{
+ NOTIFY_SET_OFF,
+ NOTIFY_SET_ON,
+};
+
+struct host_notify_dev {
+ const char *name;
+ struct device *dev;
+ int index;
+ int state;
+ int mode;
+ int booster;
+ void (*set_mode)(int);
+ void (*set_booster)(int);
+};
+
+extern void host_state_notify(struct host_notify_dev *ndev, int state);
+extern int host_notify_dev_register(struct host_notify_dev *ndev);
+extern void host_notify_dev_unregister(struct host_notify_dev *ndev);
+
+#endif /* __LINUX_HOST_NOTIFY_H__ */
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index fd0dc30..cc07d27 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -165,6 +165,7 @@ enum hrtimer_base_type {
* @lock: lock protecting the base and associated clock bases
* and timers
* @active_bases: Bitfield to mark bases with active timers
+ * @clock_was_set: Indicates that clock was set from irq context.
* @expires_next: absolute time of the next event which was scheduled
* via clock_set_next_event()
* @hres_active: State of high resolution mode
@@ -177,7 +178,8 @@ enum hrtimer_base_type {
*/
struct hrtimer_cpu_base {
raw_spinlock_t lock;
- unsigned long active_bases;
+ unsigned int active_bases;
+ unsigned int clock_was_set;
#ifdef CONFIG_HIGH_RES_TIMERS
ktime_t expires_next;
int hres_active;
@@ -286,6 +288,8 @@ extern void hrtimer_peek_ahead_timers(void);
# define MONOTONIC_RES_NSEC HIGH_RES_NSEC
# define KTIME_MONOTONIC_RES KTIME_HIGH_RES
+extern void clock_was_set_delayed(void);
+
#else
# define MONOTONIC_RES_NSEC LOW_RES_NSEC
@@ -306,6 +310,9 @@ static inline int hrtimer_is_hres_active(struct hrtimer *timer)
{
return 0;
}
+
+static inline void clock_was_set_delayed(void) { }
+
#endif
extern void clock_was_set(void);
@@ -320,6 +327,7 @@ extern ktime_t ktime_get(void);
extern ktime_t ktime_get_real(void);
extern ktime_t ktime_get_boottime(void);
extern ktime_t ktime_get_monotonic_offset(void);
+extern ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot);
DECLARE_PER_CPU(struct tick_device, tick_cpu_device);
diff --git a/include/linux/i2c/ak8973.h b/include/linux/i2c/ak8973.h
new file mode 100644
index 0000000..3f6a28b
--- /dev/null
+++ b/include/linux/i2c/ak8973.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2010 Samsung Electronics. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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
+ */
+#ifndef AKM8973_H
+#define AKM8973_H
+
+#include <linux/ioctl.h>
+
+#define AKM8973_I2C_NAME "ak8973"
+
+#define AKMIO 0xA1
+
+/* IOCTLs for AKM library */
+/* WRITE and READ sizes don't include data. On WRITE, the first value is data
+ * size plus one and the second value is the register address. On READ
+ * the first value is the data size and second value is the register
+ * address and the data is written back into the buffer starting at
+ * the second byte (the length is unchanged).
+ */
+#define ECS_IOCTL_WRITE _IOW(AKMIO, 0x01, char[2])
+#define ECS_IOCTL_READ _IOWR(AKMIO, 0x02, char[2])
+#define ECS_IOCTL_RESET _IO(AKMIO, 0x03)
+#define ECS_IOCTL_SET_MODE _IOW(AKMIO, 0x04, short)
+#define ECS_IOCTL_GETDATA _IOR(AKMIO, 0x05, char[5])
+#define ECS_IOCTL_SET_YPR _IOW(AKMIO, 0x06, short[12])
+#define ECS_IOCTL_GET_OPEN_STATUS _IOR(AKMIO, 0x07, int)
+#define ECS_IOCTL_GET_CLOSE_STATUS _IOR(AKMIO, 0x08, int)
+#define ECS_IOCTL_GET_DELAY _IOR(AKMIO, 0x30, int64_t)
+#define ECS_IOCTL_GET_PROJECT_NAME _IOR(AKMIO, 0x0D, char[64])
+#define ECS_IOCTL_GET_MATRIX _IOR(AKMIO, 0x0E, short[4][3][3])
+
+/* IOCTLs for APPs */
+#define ECS_IOCTL_APP_SET_MODE _IOW(AKMIO, 0x10, short)
+#define ECS_IOCTL_APP_SET_MFLAG _IOW(AKMIO, 0x11, short)
+#define ECS_IOCTL_APP_GET_MFLAG _IOR(AKMIO, 0x12, short)
+#define ECS_IOCTL_APP_SET_AFLAG _IOW(AKMIO, 0x13, short)
+#define ECS_IOCTL_APP_GET_AFLAG _IOR(AKMIO, 0x14, short)
+#define ECS_IOCTL_APP_SET_TFLAG _IOW(AKMIO, 0x15, short)
+#define ECS_IOCTL_APP_GET_TFLAG _IOR(AKMIO, 0x16, short)
+#define ECS_IOCTL_APP_RESET_PEDOMETER _IO(AKMIO, 0x17)
+#define ECS_IOCTL_APP_SET_DELAY _IOW(AKMIO, 0x18, int64_t)
+#define ECS_IOCTL_APP_GET_DELAY ECS_IOCTL_GET_DELAY
+
+/* Set raw magnetic vector flag */
+#define ECS_IOCTL_APP_SET_MVFLAG _IOW(AKMIO, 0x19, short)
+
+/* Get raw magnetic vector flag */
+#define ECS_IOCTL_APP_GET_MVFLAG _IOR(AKMIO, 0x1A, short)
+
+#ifdef __KERNEL__
+struct akm8973_platform_data {
+ int reset_line;
+ int reset_asserted;
+ int gpio_data_ready_int;
+};
+#endif
+
+#endif
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 580f70c..921336f 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -30,6 +30,13 @@ extern struct fs_struct init_fs;
#define INIT_THREADGROUP_FORK_LOCK(sig)
#endif
+#ifdef CONFIG_CPUSETS
+#define INIT_CPUSET_SEQ \
+ .mems_allowed_seq = SEQCNT_ZERO,
+#else
+#define INIT_CPUSET_SEQ
+#endif
+
#define INIT_SIGNALS(sig) { \
.nr_threads = 1, \
.wait_chldexit = __WAIT_QUEUE_HEAD_INITIALIZER(sig.wait_chldexit),\
@@ -117,8 +124,17 @@ extern struct group_info init_groups;
extern struct cred init_cred;
+extern struct task_group root_task_group;
+
+#ifdef CONFIG_CGROUP_SCHED
+# define INIT_CGROUP_SCHED(tsk) \
+ .sched_task_group = &root_task_group,
+#else
+# define INIT_CGROUP_SCHED(tsk)
+#endif
+
#ifdef CONFIG_PERF_EVENTS
-# define INIT_PERF_EVENTS(tsk) \
+# define INIT_PERF_EVENTS(tsk) \
.perf_event_mutex = \
__MUTEX_INITIALIZER(tsk.perf_event_mutex), \
.perf_event_list = LIST_HEAD_INIT(tsk.perf_event_list),
@@ -153,6 +169,7 @@ extern struct cred init_cred;
}, \
.tasks = LIST_HEAD_INIT(tsk.tasks), \
INIT_PUSHABLE_TASKS(tsk) \
+ INIT_CGROUP_SCHED(tsk) \
.ptraced = LIST_HEAD_INIT(tsk.ptraced), \
.ptrace_entry = LIST_HEAD_INIT(tsk.ptrace_entry), \
.real_parent = &tsk, \
@@ -193,6 +210,7 @@ extern struct cred init_cred;
INIT_FTRACE_GRAPH \
INIT_TRACE_RECURSION \
INIT_TASK_RCU_PREEMPT(tsk) \
+ INIT_CPUSET_SEQ \
}
diff --git a/include/linux/input/cypress-touchkey.h b/include/linux/input/cypress-touchkey.h
new file mode 100755
index 0000000..cd4ff4d
--- /dev/null
+++ b/include/linux/input/cypress-touchkey.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2006-2010, Cypress Semiconductor Corporation.
+ * Copyright (C) 2010, Samsung Electronics Co. Ltd. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef _CYPRESS_TOUCHKEY_H__
+#define _CYPRESS_TOUCHKEY_H__
+
+#define CYPRESS_TOUCHKEY_DEV_NAME "cypress_touchkey"
+
+struct touchkey_platform_data {
+ int keycode_cnt;
+ const int *keycode;
+ void (*touchkey_onoff) (int);
+ void (*touchkey_sleep_onoff) (int);
+ const char *fw_name;
+ int scl_pin;
+ int sda_pin;
+ int en_pin;
+};
+
+enum {
+ TOUCHKEY_OFF,
+ TOUCHKEY_ON,
+};
+
+extern int touchkey_flash_firmware(struct touchkey_platform_data *, const u8 *);
+
+#endif /* _CYPRESS_TOUCHKEY_H__ */
diff --git a/include/linux/input/k3g.h b/include/linux/input/k3g.h
new file mode 100644
index 0000000..66eb2c9
--- /dev/null
+++ b/include/linux/input/k3g.h
@@ -0,0 +1,40 @@
+/*
+ * STMicroelectronics K3G gyro sensor header file
+ *
+ * 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.
+ *
+ * THE PRESENT SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES
+ * OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, FOR THE SOLE
+ * PURPOSE TO SUPPORT YOUR APPLICATION DEVELOPMENT.
+ * AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
+ * CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
+ * INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+ *
+ * THIS SOFTWARE IS SPECIFICALLY DESIGNED FOR EXCLUSIVE USE WITH ST PARTS.
+ *
+ */
+
+#ifndef __K3G_H__
+#define __K3G_H__
+
+#ifdef __KERNEL__
+struct k3g_platform_data {
+ u8 fs_range;
+ u8 axis_map_x;
+ u8 axis_map_y;
+ u8 axis_map_z;
+ u8 negate_x;
+ u8 negate_y;
+ u8 negate_z;
+ int (*init)(void);
+ void (*exit)(void);
+ int (*power_on)(void);
+ int (*power_off)(void);
+};
+
+#endif /* __KERNEL__ */
+
+#endif /* __K3G_H__ */
diff --git a/include/linux/input/mxt224.h b/include/linux/input/mxt224.h
new file mode 100644
index 0000000..b4d17d3
--- /dev/null
+++ b/include/linux/input/mxt224.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2010, Samsung Electronics Co. Ltd. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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 __MXT224_H__
+#define __MXT224_H__
+
+#define MXT224_DEV_NAME "Atmel MXT224"
+
+enum {
+ RESERVED_T0 = 0,
+ RESERVED_T1,
+ DEBUG_DELTAS_T2,
+ DEBUG_REFERENCES_T3,
+ DEBUG_SIGNALS_T4,
+ GEN_MESSAGEPROCESSOR_T5,
+ GEN_COMMANDPROCESSOR_T6,
+ GEN_POWERCONFIG_T7,
+ GEN_ACQUISITIONCONFIG_T8,
+ TOUCH_MULTITOUCHSCREEN_T9,
+ TOUCH_SINGLETOUCHSCREEN_T10,
+ TOUCH_XSLIDER_T11,
+ TOUCH_YSLIDER_T12,
+ TOUCH_XWHEEL_T13,
+ TOUCH_YWHEEL_T14,
+ TOUCH_KEYARRAY_T15,
+ PROCG_SIGNALFILTER_T16,
+ PROCI_LINEARIZATIONTABLE_T17,
+ SPT_COMCONFIG_T18,
+ SPT_GPIOPWM_T19,
+ PROCI_GRIPFACESUPPRESSION_T20,
+ RESERVED_T21,
+ PROCG_NOISESUPPRESSION_T22,
+ TOUCH_PROXIMITY_T23,
+ PROCI_ONETOUCHGESTUREPROCESSOR_T24,
+ SPT_SELFTEST_T25,
+ DEBUG_CTERANGE_T26,
+ PROCI_TWOTOUCHGESTUREPROCESSOR_T27,
+ SPT_CTECONFIG_T28,
+ SPT_GPI_T29,
+ SPT_GATE_T30,
+ TOUCH_KEYSET_T31,
+ TOUCH_XSLIDERSET_T32,
+ RESERVED_T33,
+ GEN_MESSAGEBLOCK_T34,
+ SPT_GENERICDATA_T35,
+ RESERVED_T36,
+ DEBUG_DIAGNOSTIC_T37,
+ SPARE_T38,
+ SPARE_T39,
+ SPARE_T40,
+ SPARE_T41,
+ SPARE_T42,
+ SPARE_T43,
+ SPARE_T44,
+ SPARE_T45,
+ SPARE_T46,
+ SPARE_T47,
+ SPARE_T48,
+ SPARE_T49,
+ SPARE_T50,
+ RESERVED_T255 = 255,
+};
+
+struct mxt224_platform_data {
+ int max_finger_touches;
+ const u8 **config;
+ int gpio_read_done;
+ int min_x;
+ int max_x;
+ int min_y;
+ int max_y;
+ int min_z;
+ int max_z;
+ int min_w;
+ int max_w;
+ void (*power_on)(void);
+ void (*power_off)(void);
+};
+
+#endif
diff --git a/include/linux/iocontext.h b/include/linux/iocontext.h
index b2eee89..7cbace3 100644
--- a/include/linux/iocontext.h
+++ b/include/linux/iocontext.h
@@ -1,14 +1,14 @@
#ifndef IOCONTEXT_H
#define IOCONTEXT_H
+#include <linux/bitmap.h>
#include <linux/radix-tree.h>
#include <linux/rcupdate.h>
-struct cfq_queue;
struct cfq_io_context {
void *key;
- struct cfq_queue *cfqq[2];
+ void *cfqq[2];
struct io_context *ioc;
@@ -28,6 +28,16 @@ struct cfq_io_context {
};
/*
+ * Indexes into the ioprio_changed bitmap. A bit set indicates that
+ * the corresponding I/O scheduler needs to see a ioprio update.
+ */
+enum {
+ IOC_CFQ_IOPRIO_CHANGED,
+ IOC_BFQ_IOPRIO_CHANGED,
+ IOC_IOPRIO_CHANGED_BITS
+};
+
+/*
* I/O subsystem state of the associated processes. It is refcounted
* and kmalloc'ed. These could be shared between processes.
*/
@@ -39,7 +49,7 @@ struct io_context {
spinlock_t lock;
unsigned short ioprio;
- unsigned short ioprio_changed;
+ DECLARE_BITMAP(ioprio_changed, IOC_IOPRIO_CHANGED_BITS);
#if defined(CONFIG_BLK_CGROUP) || defined(CONFIG_BLK_CGROUP_MODULE)
unsigned short cgroup_changed;
@@ -53,6 +63,8 @@ struct io_context {
struct radix_tree_root radix_root;
struct hlist_head cic_list;
+ struct radix_tree_root bfq_radix_root;
+ struct hlist_head bfq_cic_list;
void __rcu *ioc_data;
};
diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h
index 2d921b3..d0a3100 100644
--- a/include/linux/irqdesc.h
+++ b/include/linux/irqdesc.h
@@ -38,7 +38,6 @@ struct timer_rand_state;
*/
struct irq_desc {
struct irq_data irq_data;
- struct timer_rand_state *timer_rand_state;
unsigned int __percpu *kstat_irqs;
irq_flow_handler_t handle_irq;
#ifdef CONFIG_IRQ_PREFLOW_FASTEOI
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 9229b64..b557c78 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -228,7 +228,7 @@ static inline int kobject_uevent_env(struct kobject *kobj,
static inline __attribute__((format(printf, 2, 3)))
int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...)
-{ return 0; }
+{ return -ENOMEM; }
static inline int kobject_action_type(const char *buf, size_t count,
enum kobject_action *type)
diff --git a/include/linux/kr3dm.h b/include/linux/kr3dm.h
new file mode 100644
index 0000000..d404d28
--- /dev/null
+++ b/include/linux/kr3dm.h
@@ -0,0 +1,46 @@
+/*
+ * STMicroelectronics kr3dm acceleration sensor driver
+ *
+ * Copyright (C) 2010 Samsung Electronics Co.Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 __KR3DM_ACC_HEADER__
+#define __KR3DM__ACC_HEADER__
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+struct kr3dm_acceldata {
+ __s16 x;
+ __s16 y;
+ __s16 z;
+};
+
+/* dev info */
+#define ACC_DEV_NAME "accelerometer"
+
+/* kr3dm ioctl command label */
+#define KR3DM_IOCTL_BASE 'a'
+#define KR3DM_IOCTL_SET_DELAY _IOW(KR3DM_IOCTL_BASE, 0, int64_t)
+#define KR3DM_IOCTL_GET_DELAY _IOR(KR3DM_IOCTL_BASE, 1, int64_t)
+#define KR3DM_IOCTL_READ_ACCEL_XYZ _IOR(KR3DM_IOCTL_BASE, 8, \
+ struct kr3dm_acceldata)
+
+#ifdef __KERNEL__
+struct kr3dm_platform_data {
+ int gpio_acc_int; /* gpio for kr3dm int output */
+ s8 *rotation; /* rotation matrix, if NULL assume Id */
+};
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/include/linux/ktime.h b/include/linux/ktime.h
index 603bec2..06177ba10 100644
--- a/include/linux/ktime.h
+++ b/include/linux/ktime.h
@@ -58,13 +58,6 @@ union ktime {
typedef union ktime ktime_t; /* Kill this */
-#define KTIME_MAX ((s64)~((u64)1 << 63))
-#if (BITS_PER_LONG == 64)
-# define KTIME_SEC_MAX (KTIME_MAX / NSEC_PER_SEC)
-#else
-# define KTIME_SEC_MAX LONG_MAX
-#endif
-
/*
* ktime_t definitions when using the 64-bit scalar representation:
*/
diff --git a/include/linux/max17040_battery.h b/include/linux/max17040_battery.h
index ad97b06..968da52 100644..100755
--- a/include/linux/max17040_battery.h
+++ b/include/linux/max17040_battery.h
@@ -14,6 +14,10 @@ struct max17040_platform_data {
int (*battery_online)(void);
int (*charger_online)(void);
int (*charger_enable)(void);
+ int (*power_supply_register)(struct device *parent,
+ struct power_supply *psy);
+ void (*power_supply_unregister)(struct power_supply *psy);
+ u16 rcomp_value;
};
#endif
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index 313a00e..4a8da84 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -35,7 +35,8 @@ enum mem_cgroup_page_stat_item {
extern unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan,
struct list_head *dst,
unsigned long *scanned, int order,
- int mode, struct zone *z,
+ isolate_mode_t mode,
+ struct zone *z,
struct mem_cgroup *mem_cont,
int active, int file);
diff --git a/include/linux/memory.h b/include/linux/memory.h
index 935699b..6bea2c2 100644
--- a/include/linux/memory.h
+++ b/include/linux/memory.h
@@ -20,7 +20,7 @@
#include <linux/compiler.h>
#include <linux/mutex.h>
-#define MIN_MEMORY_BLOCK_SIZE (1 << SECTION_SIZE_BITS)
+#define MIN_MEMORY_BLOCK_SIZE (1UL << SECTION_SIZE_BITS)
struct memory_block {
unsigned long start_section_nr;
diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h
index 7978eec..3e8f2f7 100644
--- a/include/linux/mempolicy.h
+++ b/include/linux/mempolicy.h
@@ -188,7 +188,7 @@ struct sp_node {
struct shared_policy {
struct rb_root root;
- spinlock_t lock;
+ struct mutex mutex;
};
void mpol_shared_policy_init(struct shared_policy *sp, struct mempolicy *mpol);
diff --git a/include/linux/mfd/ezx-pcap.h b/include/linux/mfd/ezx-pcap.h
index 40c37216..32a1b5c 100644
--- a/include/linux/mfd/ezx-pcap.h
+++ b/include/linux/mfd/ezx-pcap.h
@@ -16,6 +16,7 @@ struct pcap_subdev {
struct pcap_platform_data {
unsigned int irq_base;
unsigned int config;
+ int gpio;
void (*init) (void *); /* board specific init */
int num_subdevs;
struct pcap_subdev *subdevs;
diff --git a/include/linux/mfd/max8998-private.h b/include/linux/mfd/max8998-private.h
index effa5d3..1877d15 100644..100755
--- a/include/linux/mfd/max8998-private.h
+++ b/include/linux/mfd/max8998-private.h
@@ -132,6 +132,147 @@ enum {
#define MAX8998_ENRAMP (1 << 4)
+/* IRQ1 */
+#define MAX8998_SHIFT_PWRONR 7
+#define MAX8998_SHIFT_PWRONF 6
+#define MAX8998_SHIFT_JIGR 5
+#define MAX8998_SHIFT_JIGF 4
+#define MAX8998_SHIFT_DCINR 3
+#define MAX8998_SHIFT_DCINF 2
+
+#define MAX8998_MASK_PWRONR (0x1 << MAX8998_SHIFT_PWRONR)
+#define MAX8998_MASK_PWRONF (0x1 << MAX8998_SHIFT_PWRONF)
+#define MAX8998_MASK_JIGR (0x1 << MAX8998_SHIFT_JIGR)
+#define MAX8998_MASK_JIGF (0x1 << MAX8998_SHIFT_JIGF)
+#define MAX8998_MASK_DCINR (0x1 << MAX8998_SHIFT_DCINR)
+#define MAX8998_MASK_DCINF (0x1 << MAX8998_SHIFT_DCINF)
+
+/* STATUS1 */
+#define MAX8998_SHIFT_ENDKEY 7
+#define MAX8998_SHIFT_JIGON 6
+#define MAX8998_SHIFT_ALARM0 5
+#define MAX8998_SHIFT_ALARM1 4
+#define MAX8998_SHIFT_SMPL 3
+#define MAX8998_SHIFT_WTSR 2
+#define MAX8998_SHIFT_LOWBAT2 1
+#define MAX8998_SHIFT_LOWBAT1 0
+
+#define MAX8998_MASK_ENDKEY (0x1 << MAX8998_SHIFT_ENDKEY)
+#define MAX8998_MASK_JIGON (0x1 << MAX8998_SHIFT_JIGON)
+#define MAX8998_MASK_ALARM0 (0x1 << MAX8998_SHIFT_ALARM0)
+#define MAX8998_MASK_ALARM1 (0x1 << MAX8998_SHIFT_ALARM1)
+#define MAX8998_MASK_SMPL (0x1 << MAX8998_SHIFT_SMPL)
+#define MAX8998_MASK_WTSR (0x1 << MAX8998_SHIFT_WTSR)
+#define MAX8998_MASK_LOWBAT2 (0x1 << MAX8998_SHIFT_LOWBAT2)
+#define MAX8998_MASK_LOWBAT1 (0x1 << MAX8998_SHIFT_LOWBAT1)
+
+/* STATUS2 */
+#define MAX8998_SHIFT_CHGDONE 6
+#define MAX8998_SHIFT_VDCIN 5
+#define MAX8998_SHIFT_DETBAT 4
+#define MAX8998_SHIFT_CHGON 3
+#define MAX8998_SHIFT_FCHG 2
+#define MAX8998_SHIFT_PQL 1
+
+#define MAX8998_MASK_CHGDONE (0x1 << MAX8998_SHIFT_CHGDONE)
+#define MAX8998_MASK_VDCIN (0x1 << MAX8998_SHIFT_VDCIN)
+#define MAX8998_MASK_DETBAT (0x1 << MAX8998_SHIFT_DETBAT)
+#define MAX8998_MASK_CHGON (0x1 << MAX8998_SHIFT_CHGON)
+#define MAX8998_MASK_FCHG (0x1 << MAX8998_SHIFT_FCHG)
+#define MAX8998_MASK_PQL (0x1 << MAX8998_SHIFT_PQL)
+
+/* CHGR1 */
+#define MAX8998_SHIFT_TOPOFF 5
+#define MAX8998_SHIFT_RSTR 3
+#define MAX8998_SHIFT_ICHG 0
+
+#define MAX8998_MASK_TOPOFF (0x7 << MAX8998_SHIFT_TOPOFF)
+#define MAX8998_MASK_RSTR (0x3 << MAX8998_SHIFT_RSTR)
+#define MAX8998_MASK_ICHG (0x7 << MAX8998_SHIFT_ICHG)
+
+/* CHGR2 */
+#define MAX8998_SHIFT_ESAFEOUT 6
+#define MAX8998_SHIFT_FT 4
+#define MAX8998_SHIFT_BATTSL 3
+#define MAX8998_SHIFT_TMP 1
+#define MAX8998_SHIFT_CHGEN 0
+
+#define MAX8998_MASK_ESAFEOUT (0x3 << MAX8998_SHIFT_ESAFEOUT)
+#define MAX8998_MASK_FT (0x3 << MAX8998_SHIFT_FT)
+#define MAX8998_MASK_BATTSL (0x1 << MAX8998_SHIFT_BATTSL)
+#define MAX8998_MASK_TMP (0x3 << MAX8998_SHIFT_TMP)
+#define MAX8998_MASK_CHGEN (0x1 << MAX8998_SHIFT_CHGEN)
+
+/* ONOFF1 */
+#define MAX8998_SHIFT_EN1 7
+#define MAX8998_SHIFT_EN2 6
+#define MAX8998_SHIFT_EN3 5
+#define MAX8998_SHIFT_EN4 4
+#define MAX8998_SHIFT_ELDO2 3
+#define MAX8998_SHIFT_ELDO3 2
+#define MAX8998_SHIFT_ELDO4 1
+#define MAX8998_SHIFT_ELDO5 0
+
+#define MAX8998_MASK_EN1 (0x1 << MAX8998_SHIFT_EN1)
+#define MAX8998_MASK_EN2 (0x1 << MAX8998_SHIFT_EN2)
+#define MAX8998_MASK_EN3 (0x1 << MAX8998_SHIFT_EN3)
+#define MAX8998_MASK_EN4 (0x1 << MAX8998_SHIFT_EN4)
+#define MAX8998_MASK_ELDO2 (0x1 << MAX8998_SHIFT_ELDO2)
+#define MAX8998_MASK_ELDO3 (0x1 << MAX8998_SHIFT_ELDO3)
+#define MAX8998_MASK_ELDO4 (0x1 << MAX8998_SHIFT_ELDO4)
+#define MAX8998_MASK_ELDO5 (0x1 << MAX8998_SHIFT_ELDO5)
+
+/* ONOFF2 */
+#define MAX8998_SHIFT_ELDO6 7
+#define MAX8998_SHIFT_ELDO7 6
+#define MAX8998_SHIFT_ELDO8 5
+#define MAX8998_SHIFT_ELDO9 4
+#define MAX8998_SHIFT_ELDO10 3
+#define MAX8998_SHIFT_ELDO11 2
+#define MAX8998_SHIFT_ELDO12 1
+#define MAX8998_SHIFT_ELDO13 0
+
+#define MAX8998_MASK_ELDO6 (0x1 << MAX8998_SHIFT_ELDO6)
+#define MAX8998_MASK_ELDO7 (0x1 << MAX8998_SHIFT_ELDO7)
+#define MAX8998_MASK_ELDO8 (0x1 << MAX8998_SHIFT_ELDO8)
+#define MAX8998_MASK_ELDO9 (0x1 << MAX8998_SHIFT_ELDO9)
+#define MAX8998_MASK_ELDO10 (0x1 << MAX8998_SHIFT_ELDO10)
+#define MAX8998_MASK_ELDO11 (0x1 << MAX8998_SHIFT_ELDO11)
+#define MAX8998_MASK_ELDO12 (0x1 << MAX8998_SHIFT_ELDO12)
+#define MAX8998_MASK_ELDO13 (0x1 << MAX8998_SHIFT_ELDO13)
+
+/* ONOFF3 */
+#define MAX8998_SHIFT_ELDO14 7
+#define MAX8998_SHIFT_ELDO15 6
+#define MAX8998_SHIFT_ELDO16 5
+#define MAX8998_SHIFT_ELDO17 4
+#define MAX8998_SHIFT_EPWRHOLD 3
+#define MAX8998_SHIFT_ENBATTMON 2
+#define MAX8998_SHIFT_ELBCNFG2 1
+#define MAX8998_SHIFT_ELBCNFG1 0
+
+#define MAX8998_MASK_ELDO14 (0x1 << MAX8998_SHIFT_ELDO14)
+#define MAX8998_MASK_ELDO15 (0x1 << MAX8998_SHIFT_ELDO15)
+#define MAX8998_MASK_ELDO16 (0x1 << MAX8998_SHIFT_ELDO16)
+#define MAX8998_MASK_ELDO17 (0x1 << MAX8998_SHIFT_ELDO17)
+#define MAX8998_MASK_EPWRHOLD (0x1 << MAX8998_SHIFT_EPWRHOLD)
+#define MAX8998_MASK_ENBATTMON (0x1 << MAX8998_SHIFT_ENBATTMON)
+#define MAX8998_MASK_ELBCNFG2 (0x1 << MAX8998_SHIFT_ELBCNFG2)
+#define MAX8998_MASK_ELBCNFG1 (0x1 << MAX8998_SHIFT_ELBCNFG1)
+
+/* ONOFF4 */
+#define MAX8998_SHIFT_EN32KHZAP 7
+#define MAX8998_SHIFT_EN32KHZCP 6
+#define MAX8998_SHIFT_ENVICHG 5
+#define MAX8998_SHIFT_ENRAMP 4
+#define MAX8998_SHIFT_RAMP 0
+
+#define MAX8998_MASK_EN32KHZAP (0x1 << MAX8998_SHIFT_EN32KHZAP)
+#define MAX8998_MASK_EN32KHZCP (0x1 << MAX8998_SHIFT_EN32KHZCP)
+#define MAX8998_MASK_ENVICHG (0x1 << MAX8998_SHIFT_ENVICHG)
+#define MAX8998_MASK_ENRAMP (0x1 << MAX8998_SHIFT_ENRAMP)
+#define MAX8998_MASK_RAMP (0xF << MAX8998_SHIFT_RAMP)
+
/**
* struct max8998_dev - max8998 master device for sub-drivers
* @dev: master device of the chip (can be used to access platform data)
diff --git a/include/linux/mfd/max8998.h b/include/linux/mfd/max8998.h
index 61daa16..67db8b6 100644..100755
--- a/include/linux/mfd/max8998.h
+++ b/include/linux/mfd/max8998.h
@@ -64,6 +64,39 @@ struct max8998_regulator_data {
struct regulator_init_data *initdata;
};
+enum cable_type_t {
+ CABLE_TYPE_NONE = 0,
+ CABLE_TYPE_USB,
+ CABLE_TYPE_AC,
+};
+
+/**
+ * max8998_adc_table_data
+ * @adc_value : max8998 adc value
+ * @temperature : temperature(C) * 10
+ */
+struct max8998_adc_table_data {
+ int adc_value;
+ int temperature;
+};
+struct max8998_charger_callbacks {
+ void (*set_cable)(struct max8998_charger_callbacks *ptr,
+ enum cable_type_t status);
+};
+
+/**
+ * max8998_charger_data - charger data
+ * @id: charger id
+ * @initdata: charger init data (contraints, supplies, ...)
+ * @adc_table: adc_table must be ascending adc value order
+ */
+struct max8998_charger_data {
+ struct power_supply *psy_fuelgauge;
+ void (*register_callbacks)(struct max8998_charger_callbacks *ptr);
+ struct max8998_adc_table_data *adc_table;
+ int adc_array_size;
+};
+
/**
* struct max8998_board - packages regulator init data
* @regulators: array of defined regulators
@@ -107,6 +140,7 @@ struct max8998_platform_data {
int buck2_default_idx;
bool wakeup;
bool rtc_delay;
+ struct max8998_charger_data *charger;
};
#endif /* __LINUX_MFD_MAX8998_H */
diff --git a/include/linux/mfd/wm8994/wm8994_pdata.h b/include/linux/mfd/wm8994/wm8994_pdata.h
new file mode 100755
index 0000000..d79a7cc
--- /dev/null
+++ b/include/linux/mfd/wm8994/wm8994_pdata.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2008 Samsung Electronics, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __S5PC110_WM8994_H
+#define __S5PC110_WM8994_H
+
+struct wm8994_platform_data {
+ int ldo;
+ int ear_sel;
+ void (*set_mic_bias)(bool on);
+};
+
+#endif
diff --git a/include/linux/migrate.h b/include/linux/migrate.h
index e39aeec..eaf8674 100644
--- a/include/linux/migrate.h
+++ b/include/linux/migrate.h
@@ -6,18 +6,31 @@
typedef struct page *new_page_t(struct page *, unsigned long private, int **);
+/*
+ * MIGRATE_ASYNC means never block
+ * MIGRATE_SYNC_LIGHT in the current implementation means to allow blocking
+ * on most operations but not ->writepage as the potential stall time
+ * is too significant
+ * MIGRATE_SYNC will block when migrating pages
+ */
+enum migrate_mode {
+ MIGRATE_ASYNC,
+ MIGRATE_SYNC_LIGHT,
+ MIGRATE_SYNC,
+};
+
#ifdef CONFIG_MIGRATION
#define PAGE_MIGRATION 1
extern void putback_lru_pages(struct list_head *l);
extern int migrate_page(struct address_space *,
- struct page *, struct page *);
+ struct page *, struct page *, enum migrate_mode);
extern int migrate_pages(struct list_head *l, new_page_t x,
unsigned long private, bool offlining,
- bool sync);
+ enum migrate_mode mode);
extern int migrate_huge_pages(struct list_head *l, new_page_t x,
unsigned long private, bool offlining,
- bool sync);
+ enum migrate_mode mode);
extern int fail_migrate_page(struct address_space *,
struct page *, struct page *);
@@ -36,10 +49,10 @@ extern int migrate_huge_page_move_mapping(struct address_space *mapping,
static inline void putback_lru_pages(struct list_head *l) {}
static inline int migrate_pages(struct list_head *l, new_page_t x,
unsigned long private, bool offlining,
- bool sync) { return -ENOSYS; }
+ enum migrate_mode mode) { return -ENOSYS; }
static inline int migrate_huge_pages(struct list_head *l, new_page_t x,
unsigned long private, bool offlining,
- bool sync) { return -ENOSYS; }
+ enum migrate_mode mode) { return -ENOSYS; }
static inline int migrate_prep(void) { return -ENOSYS; }
static inline int migrate_prep_local(void) { return -ENOSYS; }
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 2cfa8d0..7a4960e 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -133,6 +133,7 @@ struct mmc_host_ops {
int (*get_cd)(struct mmc_host *host);
void (*enable_sdio_irq)(struct mmc_host *host, int enable);
+ void (*adjust_cfg)(struct mmc_host *host, int rw);
/* optional callback for HC quirks */
void (*init_card)(struct mmc_host *host, struct mmc_card *card);
@@ -273,6 +274,7 @@ struct mmc_host {
unsigned int sdio_irqs;
struct task_struct *sdio_irq_thread;
+ bool sdio_irq_pending;
atomic_t sdio_irq_thread_abort;
mmc_pm_flag_t pm_flags; /* requested pm features */
@@ -347,6 +349,7 @@ extern void mmc_request_done(struct mmc_host *, struct mmc_request *);
static inline void mmc_signal_sdio_irq(struct mmc_host *host)
{
host->ops->enable_sdio_irq(host, 0);
+ host->sdio_irq_pending = true;
wake_up_process(host->sdio_irq_thread);
}
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
index 6a68c4e..b27792a 100644
--- a/include/linux/mmc/sdhci.h
+++ b/include/linux/mmc/sdhci.h
@@ -21,7 +21,7 @@ struct sdhci_host {
/* Data set by hardware interface driver */
const char *hw_name; /* Hardware bus name */
- unsigned int quirks; /* Deviations from spec. */
+ u64 quirks; /* Deviations from spec. */
/* Controller doesn't honor resets unless we touch the clock register */
#define SDHCI_QUIRK_CLOCK_BEFORE_RESET (1<<0)
@@ -87,6 +87,8 @@ struct sdhci_host {
#define SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC (1<<30)
/* The read-only detection via SDHCI_PRESENT_STATE register is unstable */
#define SDHCI_QUIRK_UNSTABLE_RO_DETECT (1<<31)
+/* Controller must maintain clock when no activity */
+#define SDHCI_QUIRK_MUST_MAINTAIN_CLOCK (1ULL<<32)
int irq; /* Device IRQ */
void __iomem *ioaddr; /* Mapped address */
@@ -145,6 +147,7 @@ struct sdhci_host {
struct tasklet_struct finish_tasklet;
struct timer_list timer; /* Timer for timeouts */
+ struct timer_list busy_check_timer;
unsigned int caps; /* Alternative capabilities */
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 9f7c3eb..b32f3f9 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -158,6 +158,20 @@ static inline int is_unevictable_lru(enum lru_list l)
return (l == LRU_UNEVICTABLE);
}
+/* Isolate inactive pages */
+#define ISOLATE_INACTIVE ((__force isolate_mode_t)0x1)
+/* Isolate active pages */
+#define ISOLATE_ACTIVE ((__force isolate_mode_t)0x2)
+/* Isolate clean file */
+#define ISOLATE_CLEAN ((__force isolate_mode_t)0x4)
+/* Isolate unmapped file */
+#define ISOLATE_UNMAPPED ((__force isolate_mode_t)0x8)
+/* Isolate for asynchronous migration */
+#define ISOLATE_ASYNC_MIGRATE ((__force isolate_mode_t)0x10)
+
+/* LRU Isolation modes. */
+typedef unsigned __bitwise__ isolate_mode_t;
+
enum zone_watermarks {
WMARK_MIN,
WMARK_LOW,
@@ -633,7 +647,7 @@ typedef struct pglist_data {
range, including holes */
int node_id;
wait_queue_head_t kswapd_wait;
- struct task_struct *kswapd;
+ struct task_struct *kswapd; /* Protected by lock_memory_hotplug() */
int kswapd_max_order;
enum zone_type classzone_idx;
} pg_data_t;
diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
index 52b6f18..a27b6b3 100644
--- a/include/linux/mtd/onenand.h
+++ b/include/linux/mtd/onenand.h
@@ -103,6 +103,7 @@ struct onenand_chip {
unsigned int bufferram_index;
struct onenand_bufferram bufferram[MAX_BUFFERRAM];
+ struct clk *clk;
int (*command)(struct mtd_info *mtd, int cmd, loff_t address, size_t len);
int (*wait)(struct mtd_info *mtd, int state);
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 33b5968..c037215 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1329,6 +1329,8 @@ struct net_device {
/* for setting kernel sock attribute on TCP connection setup */
#define GSO_MAX_SIZE 65536
unsigned int gso_max_size;
+#define GSO_MAX_SEGS 65535
+ u16 gso_max_segs;
#ifdef CONFIG_DCB
/* Data Center Bridging netlink ops */
@@ -1453,15 +1455,6 @@ static inline bool netdev_uses_dsa_tags(struct net_device *dev)
return 0;
}
-#ifndef CONFIG_NET_NS
-static inline void skb_set_dev(struct sk_buff *skb, struct net_device *dev)
-{
- skb->dev = dev;
-}
-#else /* CONFIG_NET_NS */
-void skb_set_dev(struct sk_buff *skb, struct net_device *dev);
-#endif
-
static inline bool netdev_uses_trailer_tags(struct net_device *dev)
{
#ifdef CONFIG_NET_DSA_TAG_TRAILER
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index acdc370..af625d8 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -261,11 +261,6 @@ static inline const struct nfs_rpc_ops *NFS_PROTO(const struct inode *inode)
return NFS_SERVER(inode)->nfs_client->rpc_ops;
}
-static inline __be32 *NFS_COOKIEVERF(const struct inode *inode)
-{
- return NFS_I(inode)->cookieverf;
-}
-
static inline unsigned NFS_MINATTRTIMEO(const struct inode *inode)
{
struct nfs_server *nfss = NFS_SERVER(inode);
diff --git a/include/linux/nt35580.h b/include/linux/nt35580.h
new file mode 100755
index 0000000..2c429fa
--- /dev/null
+++ b/include/linux/nt35580.h
@@ -0,0 +1,27 @@
+/*include/linux/nt35580.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Header file for Sony LCD Panel(TFT) driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+#include <linux/types.h>
+
+#define SLEEPMSEC 0x1000
+#define ENDDEF 0x2000
+#define DEFMASK 0xFF00
+
+struct s5p_tft_panel_data {
+ const u16 *seq_set;
+ const u16 *sleep_in;
+ const u16 *display_on;
+ const u16 *display_off;
+ u16 *brightness_set;
+ int pwm_reg_offset;
+};
+
+
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index f8910e1..864daf3 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1818,7 +1818,6 @@
#define PCI_DEVICE_ID_SIIG_8S_20x_650 0x2081
#define PCI_DEVICE_ID_SIIG_8S_20x_850 0x2082
#define PCI_SUBDEVICE_ID_SIIG_QUARTET_SERIAL 0x2050
-#define PCI_SUBDEVICE_ID_SIIG_DUAL_SERIAL 0x2530
#define PCI_VENDOR_ID_RADISYS 0x1331
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index e0786e3..effadd6 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -807,7 +807,7 @@ struct perf_event {
struct hw_perf_event hw;
struct perf_event_context *ctx;
- struct file *filp;
+ atomic_long_t refcount;
/*
* These accumulate total time (in nanoseconds) that children
diff --git a/include/linux/pn544.h b/include/linux/pn544.h
new file mode 100755
index 0000000..9285000
--- /dev/null
+++ b/include/linux/pn544.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2010 Trusted Logic S.A.
+ *
+ * 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
+ */
+
+#define PN544_MAGIC 0xE9
+
+/*
+ * PN544 power control via ioctl
+ * PN544_SET_PWR(0): power off
+ * PN544_SET_PWR(1): power on
+ * PN544_SET_PWR(2): reset and power on with firmware download enabled
+ */
+#define PN544_SET_PWR _IOW(PN544_MAGIC, 0x01, unsigned int)
+
+struct pn544_i2c_platform_data {
+ unsigned int irq_gpio;
+ unsigned int ven_gpio;
+ unsigned int firm_gpio;
+};
diff --git a/include/linux/random.h b/include/linux/random.h
index d13059f..ac621ce 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -48,13 +48,13 @@ struct rnd_state {
#ifdef __KERNEL__
-extern void rand_initialize_irq(int irq);
-
+extern void add_device_randomness(const void *, unsigned int);
extern void add_input_randomness(unsigned int type, unsigned int code,
unsigned int value);
-extern void add_interrupt_randomness(int irq);
+extern void add_interrupt_randomness(int irq, int irq_flags);
extern void get_random_bytes(void *buf, int nbytes);
+extern void get_random_bytes_arch(void *buf, int nbytes);
void generate_random_uuid(unsigned char uuid_out[16]);
#ifndef MODULE
@@ -91,6 +91,19 @@ static inline void prandom32_seed(struct rnd_state *state, u64 seed)
state->s3 = __seed(i, 15);
}
+#ifdef CONFIG_ARCH_RANDOM
+# include <asm/archrandom.h>
+#else
+static inline int arch_get_random_long(unsigned long *v)
+{
+ return 0;
+}
+static inline int arch_get_random_int(unsigned int *v)
+{
+ return 0;
+}
+#endif
+
#endif /* __KERNEL___ */
#endif /* _LINUX_RANDOM_H */
diff --git a/include/linux/regulator/max8893.h b/include/linux/regulator/max8893.h
new file mode 100644
index 0000000..d8a3f49
--- /dev/null
+++ b/include/linux/regulator/max8893.h
@@ -0,0 +1,53 @@
+/*
+ * max8893.h -- Voltage regulation for the Maxim 8893
+ *
+ * based on max8660.h
+ *
+ * Copyright (C) 2009 Wolfram Sang, Pengutronix e.K.
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __LINUX_REGULATOR_MAX8893_H
+#define __LINUX_REGULATOR_MAX8893_H
+
+#include <linux/regulator/machine.h>
+
+enum {
+ MAX8893_BUCK,
+ MAX8893_LDO1,
+ MAX8893_LDO2,
+ MAX8893_LDO3,
+ MAX8893_LDO4,
+ MAX8893_LDO5,
+ MAX8893_END,
+};
+
+/**
+ * max8893_subdev_data - regulator subdev data
+ * @id: regulator id
+ * @initdata: regulator init data
+ */
+struct max8893_subdev_data {
+ int id;
+ struct regulator_init_data *initdata;
+};
+
+/**
+ * max8893_platform_data - platform data for max8893
+ * @num_subdevs: number of regulators used
+ * @subdevs: pointer to regulators used
+ */
+struct max8893_platform_data {
+ int num_subdevs;
+ struct max8893_subdev_data *subdevs;
+};
+#endif
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 35895e3..5039e0a 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1235,6 +1235,9 @@ struct task_struct {
const struct sched_class *sched_class;
struct sched_entity se;
struct sched_rt_entity rt;
+#ifdef CONFIG_CGROUP_SCHED
+ struct task_group *sched_task_group;
+#endif
#ifdef CONFIG_PREEMPT_NOTIFIERS
/* list of struct preempt_notifier: */
@@ -1484,7 +1487,7 @@ struct task_struct {
#endif
#ifdef CONFIG_CPUSETS
nodemask_t mems_allowed; /* Protected by alloc_lock */
- int mems_allowed_change_disable;
+ seqcount_t mems_allowed_seq; /* Seqence no to catch updates */
int cpuset_mem_spread_rotor;
int cpuset_slab_spread_rotor;
#endif
@@ -2616,7 +2619,7 @@ extern int sched_group_set_rt_period(struct task_group *tg,
extern long sched_group_rt_period(struct task_group *tg);
extern int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk);
#endif
-#endif
+#endif /* CONFIG_CGROUP_SCHED */
extern int task_can_switch_user(struct user_struct *up,
struct task_struct *tsk);
diff --git a/include/linux/sec_jack.h b/include/linux/sec_jack.h
new file mode 100755
index 0000000..d8182e3
--- /dev/null
+++ b/include/linux/sec_jack.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2008 Samsung Electronics, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __ASM_ARCH_SEC_HEADSET_H
+#define __ASM_ARCH_SEC_HEADSET_H
+
+#ifdef __KERNEL__
+
+enum {
+ SEC_JACK_NO_DEVICE = 0x0,
+ SEC_HEADSET_4POLE = 0x01 << 0,
+ SEC_HEADSET_3POLE = 0x01 << 1,
+ SEC_TTY_DEVICE = 0x01 << 2,
+ SEC_FM_HEADSET = 0x01 << 3,
+ SEC_FM_SPEAKER = 0x01 << 4,
+ SEC_TVOUT_DEVICE = 0x01 << 5,
+ SEC_EXTRA_DOCK_SPEAKER = 0x01 << 6,
+ SEC_EXTRA_CAR_DOCK_SPEAKER = 0x01 << 7,
+ SEC_UNKNOWN_DEVICE = 0x01 << 8,
+};
+
+struct sec_jack_zone {
+ unsigned int adc_high;
+ unsigned int delay_ms;
+ unsigned int check_count;
+ unsigned int jack_type;
+};
+
+struct sec_jack_buttons_zone {
+ unsigned int code;
+ unsigned int adc_low;
+ unsigned int adc_high;
+};
+
+struct sec_jack_platform_data {
+ void (*set_micbias_state) (bool);
+ int (*get_adc_value) (void);
+ struct sec_jack_zone *zones;
+ struct sec_jack_buttons_zone *buttons_zones;
+ int num_zones;
+ int num_buttons_zones;
+ int det_gpio;
+ int send_end_gpio;
+ bool det_active_high;
+ bool send_end_active_high;
+};
+#endif
+
+#endif
diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h
index c6db9fb..bb1fac5 100644
--- a/include/linux/seqlock.h
+++ b/include/linux/seqlock.h
@@ -141,7 +141,7 @@ static inline unsigned __read_seqcount_begin(const seqcount_t *s)
unsigned ret;
repeat:
- ret = s->sequence;
+ ret = ACCESS_ONCE(s->sequence);
if (unlikely(ret & 1)) {
cpu_relax();
goto repeat;
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index f13b52b..37b643b 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1633,8 +1633,6 @@ static inline int __skb_cow(struct sk_buff *skb, unsigned int headroom,
{
int delta = 0;
- if (headroom < NET_SKB_PAD)
- headroom = NET_SKB_PAD;
if (headroom > skb_headroom(skb))
delta = headroom - skb_headroom(skb);
diff --git a/include/linux/swap.h b/include/linux/swap.h
index a273468..e73799d 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -243,11 +243,6 @@ static inline void lru_cache_add_file(struct page *page)
__lru_cache_add(page, LRU_INACTIVE_FILE);
}
-/* LRU Isolation modes. */
-#define ISOLATE_INACTIVE 0 /* Isolate inactive pages. */
-#define ISOLATE_ACTIVE 1 /* Isolate active pages. */
-#define ISOLATE_BOTH 2 /* Isolate both active and inactive pages. */
-
/* linux/mm/vmscan.c */
extern unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
gfp_t gfp_mask, nodemask_t *mask);
@@ -259,7 +254,7 @@ extern unsigned long mem_cgroup_shrink_node_zone(struct mem_cgroup *mem,
unsigned int swappiness,
struct zone *zone,
unsigned long *nr_scanned);
-extern int __isolate_lru_page(struct page *page, int mode, int file);
+extern int __isolate_lru_page(struct page *page, isolate_mode_t mode, int file);
extern unsigned long shrink_all_memory(unsigned long nr_pages);
extern int vm_swappiness;
extern int remove_mapping(struct address_space *mapping, struct page *page);
diff --git a/include/linux/time.h b/include/linux/time.h
index b306178..8c0216e 100644
--- a/include/linux/time.h
+++ b/include/linux/time.h
@@ -107,11 +107,36 @@ static inline struct timespec timespec_sub(struct timespec lhs,
return ts_delta;
}
+#define KTIME_MAX ((s64)~((u64)1 << 63))
+#if (BITS_PER_LONG == 64)
+# define KTIME_SEC_MAX (KTIME_MAX / NSEC_PER_SEC)
+#else
+# define KTIME_SEC_MAX LONG_MAX
+#endif
+
/*
* Returns true if the timespec is norm, false if denorm:
*/
-#define timespec_valid(ts) \
- (((ts)->tv_sec >= 0) && (((unsigned long) (ts)->tv_nsec) < NSEC_PER_SEC))
+static inline bool timespec_valid(const struct timespec *ts)
+{
+ /* Dates before 1970 are bogus */
+ if (ts->tv_sec < 0)
+ return false;
+ /* Can't have more nanoseconds then a second */
+ if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC)
+ return false;
+ return true;
+}
+
+static inline bool timespec_valid_strict(const struct timespec *ts)
+{
+ if (!timespec_valid(ts))
+ return false;
+ /* Disallow values that could overflow ktime_t */
+ if ((unsigned long long)ts->tv_sec >= KTIME_SEC_MAX)
+ return false;
+ return true;
+}
extern void read_persistent_clock(struct timespec *ts);
extern void read_boot_clock(struct timespec *ts);
diff --git a/include/linux/timex.h b/include/linux/timex.h
index aa60fe7..08e90fb 100644
--- a/include/linux/timex.h
+++ b/include/linux/timex.h
@@ -266,7 +266,7 @@ static inline int ntp_synced(void)
/* Returns how long ticks are at present, in ns / 2^NTP_SCALE_SHIFT. */
extern u64 tick_length;
-extern void second_overflow(void);
+extern int second_overflow(unsigned long secs);
extern void update_ntp_one_tick(void);
extern int do_adjtimex(struct timex *);
extern void hardpps(const struct timespec *, const struct timespec *);
diff --git a/include/linux/tl2796.h b/include/linux/tl2796.h
new file mode 100755
index 0000000..2abeef6
--- /dev/null
+++ b/include/linux/tl2796.h
@@ -0,0 +1,68 @@
+/*inclue/linux/tl2796.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Header file for Samsung Display Panel(AMOLED) driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+#include <linux/types.h>
+
+struct gamma_entry {
+ u32 brightness;
+ u32 v[3];
+};
+
+struct tl2796_gamma_adj_points {
+ const u32 v0;
+ const u32 v1;
+ const u32 v19;
+ const u32 v43;
+ const u32 v87;
+ const u32 v171;
+ const u32 v255;
+};
+
+struct tl2796_color_adj {
+ u32 mult[3];
+ int rshift;
+};
+
+struct s5p_panel_data {
+ const u16 *seq_display_set;
+ const u16 *seq_etc_set;
+ const u16 *standby_on;
+ const u16 *standby_off;
+
+ int gpio_dcx;
+ int gpio_rdx;
+ int gpio_csx;
+ int gpio_wrx;
+ int gpio_rst;
+ int gpio_db[8];
+ int (*configure_mtp_gpios)(struct s5p_panel_data *pdata, bool enable);
+ u16 factory_v255_regs[3];
+ struct tl2796_color_adj color_adj;
+
+ const struct tl2796_gamma_adj_points *gamma_adj_points;
+#ifdef CONFIG_FB_VOODOO
+ struct gamma_entry *gamma_table;
+#else
+ const struct gamma_entry *gamma_table;
+#endif
+ int gamma_table_size;
+};
+
+enum {
+ BV_0 = 0,
+ BV_1 = 0x552D,
+ BV_19 = 0xD8722A,
+ BV_43 = 0x51955E1,
+ BV_87 = 0x18083FB0,
+ BV_171 = 0x6A472534,
+ BV_255 = 0xFFFFFFFF,
+};
+
diff --git a/include/linux/usb.h b/include/linux/usb.h
index b08e04c..6cd1576 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -757,6 +757,27 @@ static inline int usb_make_path(struct usb_device *dev, char *buf, size_t size)
.bInterfaceSubClass = (sc), \
.bInterfaceProtocol = (pr)
+/**
+ * USB_VENDOR_AND_INTERFACE_INFO - describe a specific usb vendor with a class of usb interfaces
+ * @vend: the 16 bit USB Vendor ID
+ * @cl: bInterfaceClass value
+ * @sc: bInterfaceSubClass value
+ * @pr: bInterfaceProtocol value
+ *
+ * This macro is used to create a struct usb_device_id that matches a
+ * specific vendor with a specific class of interfaces.
+ *
+ * This is especially useful when explicitly matching devices that have
+ * vendor specific bDeviceClass values, but standards-compliant interfaces.
+ */
+#define USB_VENDOR_AND_INTERFACE_INFO(vend, cl, sc, pr) \
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO \
+ | USB_DEVICE_ID_MATCH_VENDOR, \
+ .idVendor = (vend), \
+ .bInterfaceClass = (cl), \
+ .bInterfaceSubClass = (sc), \
+ .bInterfaceProtocol = (pr)
+
/* ----------------------------------------------------------------------- */
/* Stuff for dynamic usb ids */
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index dd1571d..4f97fe4 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -16,6 +16,7 @@
#define __LINUX_USB_GADGET_H
#include <linux/slab.h>
+#include <linux/device.h>
struct usb_ep;
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index 32ba8c5..1d3f413 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -22,6 +22,7 @@
#ifdef __KERNEL__
#include <linux/rwsem.h>
+#include <linux/host_notify.h>
#define MAX_TOPO_LEVEL 6
@@ -128,8 +129,6 @@ struct usb_hcd {
unsigned wireless:1; /* Wireless USB HCD */
unsigned authorized_default:1;
unsigned has_tt:1; /* Integrated TT in root hub */
- unsigned broken_pci_sleep:1; /* Don't put the
- controller in PCI-D3 for system sleep */
int irq; /* irq allocated */
void __iomem *regs; /* device memory/io */
@@ -175,6 +174,14 @@ struct usb_hcd {
* input size of periodic table to an interrupt scheduler.
* (ohci 32, uhci 1024, ehci 256/512/1024).
*/
+#ifdef CONFIG_USB_HOST_NOTIFY
+ struct host_notify_dev ndev;
+ int host_notify;
+#endif
+#ifdef CONFIG_USB_SEC_WHITELIST
+ int sec_whlist_table_num;
+#endif
+
/* The HC driver's private data is stored at the end of
* this structure.
diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h
index 605b0aa..76f4396 100644
--- a/include/linux/usb/usbnet.h
+++ b/include/linux/usb/usbnet.h
@@ -191,7 +191,8 @@ extern void usbnet_cdc_status(struct usbnet *, struct urb *);
enum skb_state {
illegal = 0,
tx_start, tx_done,
- rx_start, rx_done, rx_cleanup
+ rx_start, rx_done, rx_cleanup,
+ unlink_start
};
struct skb_data { /* skb->cb is one of these */
diff --git a/include/linux/videodev2_samsung.h b/include/linux/videodev2_samsung.h
new file mode 100755
index 0000000..9a5ff62
--- /dev/null
+++ b/include/linux/videodev2_samsung.h
@@ -0,0 +1,624 @@
+/*
+ * Video for Linux Two header file for samsung
+ *
+ * Copyright (C) 2009, Samsung Electronics
+ *
+ * This header file contains several v4l2 APIs to be proposed to v4l2
+ * community and until bein accepted, will be used restrictly in Samsung's
+ * camera interface driver FIMC.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __LINUX_VIDEODEV2_SAMSUNG_H
+#define __LINUX_VIDEODEV2_SAMSUNG_H
+
+/* Values for 'capabilities' field */
+/* Object detection device */
+#define V4L2_CAP_OBJ_RECOGNITION 0x10000000
+/* strobe control */
+#define V4L2_CAP_STROBE 0x20000000
+
+#define V4L2_CID_FOCUS_MODE (V4L2_CID_CAMERA_CLASS_BASE + 17)
+/* Focus Methods */
+enum v4l2_focus_mode {
+ V4L2_FOCUS_MODE_AUTO = 0,
+ V4L2_FOCUS_MODE_MACRO = 1,
+ V4L2_FOCUS_MODE_MANUAL = 2,
+ V4L2_FOCUS_MODE_LASTP = 2,
+};
+
+#define V4L2_CID_ZOOM_MODE (V4L2_CID_CAMERA_CLASS_BASE + 18)
+/* Zoom Methods */
+enum v4l2_zoom_mode {
+ V4L2_ZOOM_MODE_CONTINUOUS = 0,
+ V4L2_ZOOM_MODE_OPTICAL = 1,
+ V4L2_ZOOM_MODE_DIGITAL = 2,
+ V4L2_ZOOM_MODE_LASTP = 2,
+};
+
+/* Exposure Methods */
+#define V4L2_CID_PHOTOMETRY (V4L2_CID_CAMERA_CLASS_BASE + 19)
+enum v4l2_photometry_mode {
+ V4L2_PHOTOMETRY_MULTISEG = 0, /*Multi Segment */
+ V4L2_PHOTOMETRY_CWA = 1, /*Centre Weighted Average */
+ V4L2_PHOTOMETRY_SPOT = 2,
+ V4L2_PHOTOMETRY_AFSPOT = 3, /*Spot metering on focused point */
+ V4L2_PHOTOMETRY_LASTP = V4L2_PHOTOMETRY_AFSPOT,
+};
+
+/* Manual exposure control items menu type: iris, shutter, iso */
+#define V4L2_CID_CAM_APERTURE (V4L2_CID_CAMERA_CLASS_BASE + 20)
+#define V4L2_CID_CAM_SHUTTER (V4L2_CID_CAMERA_CLASS_BASE + 21)
+#define V4L2_CID_CAM_ISO (V4L2_CID_CAMERA_CLASS_BASE + 22)
+
+/* Following CIDs are menu type */
+#define V4L2_CID_SCENEMODE (V4L2_CID_CAMERA_CLASS_BASE + 23)
+#define V4L2_CID_CAM_STABILIZE (V4L2_CID_CAMERA_CLASS_BASE + 24)
+#define V4L2_CID_CAM_MULTISHOT (V4L2_CID_CAMERA_CLASS_BASE + 25)
+
+/* Control dynamic range */
+#define V4L2_CID_CAM_DR (V4L2_CID_CAMERA_CLASS_BASE + 26)
+
+/* White balance preset control */
+#define V4L2_CID_WHITE_BALANCE_PRESET (V4L2_CID_CAMERA_CLASS_BASE + 27)
+
+/* CID extensions */
+#define V4L2_CID_ROTATION (V4L2_CID_PRIVATE_BASE + 0)
+#define V4L2_CID_PADDR_Y (V4L2_CID_PRIVATE_BASE + 1)
+#define V4L2_CID_PADDR_CB (V4L2_CID_PRIVATE_BASE + 2)
+#define V4L2_CID_PADDR_CR (V4L2_CID_PRIVATE_BASE + 3)
+#define V4L2_CID_PADDR_CBCR (V4L2_CID_PRIVATE_BASE + 4)
+#define V4L2_CID_OVERLAY_AUTO (V4L2_CID_PRIVATE_BASE + 5)
+#define V4L2_CID_OVERLAY_VADDR0 (V4L2_CID_PRIVATE_BASE + 6)
+#define V4L2_CID_OVERLAY_VADDR1 (V4L2_CID_PRIVATE_BASE + 7)
+#define V4L2_CID_OVERLAY_VADDR2 (V4L2_CID_PRIVATE_BASE + 8)
+#define V4L2_CID_OVLY_MODE (V4L2_CID_PRIVATE_BASE + 9)
+#define V4L2_CID_DST_INFO (V4L2_CID_PRIVATE_BASE + 10)
+#define V4L2_CID_IMAGE_EFFECT_FN (V4L2_CID_PRIVATE_BASE + 16)
+#define V4L2_CID_IMAGE_EFFECT_APPLY (V4L2_CID_PRIVATE_BASE + 17)
+#define V4L2_CID_IMAGE_EFFECT_CB (V4L2_CID_PRIVATE_BASE + 18)
+#define V4L2_CID_IMAGE_EFFECT_CR (V4L2_CID_PRIVATE_BASE + 19)
+#define V4L2_CID_RESERVED_MEM_BASE_ADDR (V4L2_CID_PRIVATE_BASE + 20)
+#define V4L2_CID_FIMC_VERSION (V4L2_CID_PRIVATE_BASE + 21)
+
+#define V4L2_CID_STREAM_PAUSE (V4L2_CID_PRIVATE_BASE + 53)
+
+/* CID Extensions for camera sensor operations */
+#define V4L2_CID_CAM_PREVIEW_ONOFF (V4L2_CID_PRIVATE_BASE + 64)
+#define V4L2_CID_CAM_CAPTURE (V4L2_CID_PRIVATE_BASE + 65)
+#define V4L2_CID_CAM_JPEG_MEMSIZE (V4L2_CID_PRIVATE_BASE + 66)
+
+#define V4L2_CID_CAM_DATE_INFO_YEAR (V4L2_CID_PRIVATE_BASE + 14)
+#define V4L2_CID_CAM_DATE_INFO_MONTH (V4L2_CID_PRIVATE_BASE + 15)
+#define V4L2_CID_CAM_DATE_INFO_DATE (V4L2_CID_PRIVATE_BASE + 22)
+#define V4L2_CID_CAM_SENSOR_VER (V4L2_CID_PRIVATE_BASE + 23)
+#define V4L2_CID_CAM_FW_MINOR_VER (V4L2_CID_PRIVATE_BASE + 24)
+#define V4L2_CID_CAM_FW_MAJOR_VER (V4L2_CID_PRIVATE_BASE + 25)
+#define V4L2_CID_CAM_PRM_MINOR_VER (V4L2_CID_PRIVATE_BASE + 26)
+#define V4L2_CID_CAM_PRM_MAJOR_VER (V4L2_CID_PRIVATE_BASE + 27)
+#define V4L2_CID_CAM_FW_VER (V4L2_CID_PRIVATE_BASE + 28)
+#define V4L2_CID_CAM_SET_FW_ADDR (V4L2_CID_PRIVATE_BASE + 29)
+#define V4L2_CID_CAM_SET_FW_SIZE (V4L2_CID_PRIVATE_BASE + 30)
+#define V4L2_CID_CAM_UPDATE_FW (V4L2_CID_PRIVATE_BASE + 31)
+#define V4L2_CID_CAM_JPEG_MAIN_SIZE (V4L2_CID_PRIVATE_BASE + 32)
+#define V4L2_CID_CAM_JPEG_MAIN_OFFSET (V4L2_CID_PRIVATE_BASE + 33)
+#define V4L2_CID_CAM_JPEG_THUMB_SIZE (V4L2_CID_PRIVATE_BASE + 34)
+#define V4L2_CID_CAM_JPEG_THUMB_OFFSET (V4L2_CID_PRIVATE_BASE + 35)
+#define V4L2_CID_CAM_JPEG_POSTVIEW_OFFSET (V4L2_CID_PRIVATE_BASE + 36)
+#define V4L2_CID_CAM_JPEG_QUALITY (V4L2_CID_PRIVATE_BASE + 37)
+#define V4L2_CID_CAM_SENSOR_MAKER (V4L2_CID_PRIVATE_BASE + 38)
+#define V4L2_CID_CAM_SENSOR_OPTICAL (V4L2_CID_PRIVATE_BASE + 39)
+#define V4L2_CID_CAM_AF_VER_LOW (V4L2_CID_PRIVATE_BASE + 40)
+#define V4L2_CID_CAM_AF_VER_HIGH (V4L2_CID_PRIVATE_BASE + 41)
+#define V4L2_CID_CAM_GAMMA_RG_LOW (V4L2_CID_PRIVATE_BASE + 42)
+#define V4L2_CID_CAM_GAMMA_RG_HIGH (V4L2_CID_PRIVATE_BASE + 43)
+#define V4L2_CID_CAM_GAMMA_BG_LOW (V4L2_CID_PRIVATE_BASE + 44)
+#define V4L2_CID_CAM_GAMMA_BG_HIGH (V4L2_CID_PRIVATE_BASE + 45)
+#define V4L2_CID_CAM_DUMP_FW (V4L2_CID_PRIVATE_BASE + 46)
+#define V4L2_CID_CAM_GET_DUMP_SIZE (V4L2_CID_PRIVATE_BASE + 47)
+#define V4L2_CID_CAMERA_VT_MODE (V4L2_CID_PRIVATE_BASE + 48)
+#define V4L2_CID_CAMERA_VGA_BLUR (V4L2_CID_PRIVATE_BASE + 49)
+#define V4L2_CID_CAMERA_CAPTURE (V4L2_CID_PRIVATE_BASE + 50)
+
+#define V4L2_CID_MAIN_SW_DATE_INFO_YEAR (V4L2_CID_PRIVATE_BASE + 54)
+#define V4L2_CID_MAIN_SW_DATE_INFO_MONTH (V4L2_CID_PRIVATE_BASE + 55)
+#define V4L2_CID_MAIN_SW_DATE_INFO_DATE (V4L2_CID_PRIVATE_BASE + 56)
+#define V4L2_CID_MAIN_SW_FW_MINOR_VER (V4L2_CID_PRIVATE_BASE + 57)
+#define V4L2_CID_MAIN_SW_FW_MAJOR_VER (V4L2_CID_PRIVATE_BASE + 58)
+#define V4L2_CID_MAIN_SW_PRM_MINOR_VER (V4L2_CID_PRIVATE_BASE + 59)
+#define V4L2_CID_MAIN_SW_PRM_MAJOR_VER (V4L2_CID_PRIVATE_BASE + 60)
+
+enum v4l2_blur {
+ BLUR_LEVEL_0 = 0,
+ BLUR_LEVEL_1,
+ BLUR_LEVEL_2,
+ BLUR_LEVEL_3,
+ BLUR_LEVEL_MAX,
+};
+
+#define V4L2_CID_CAMERA_SCENE_MODE (V4L2_CID_PRIVATE_BASE + 70)
+enum v4l2_scene_mode {
+ SCENE_MODE_BASE,
+ SCENE_MODE_NONE,
+ SCENE_MODE_PORTRAIT,
+ SCENE_MODE_NIGHTSHOT,
+ SCENE_MODE_BACK_LIGHT,
+ SCENE_MODE_LANDSCAPE,
+ SCENE_MODE_SPORTS,
+ SCENE_MODE_PARTY_INDOOR,
+ SCENE_MODE_BEACH_SNOW,
+ SCENE_MODE_SUNSET,
+ SCENE_MODE_DUST_DAWN,
+ SCENE_MODE_FALL_COLOR,
+ SCENE_MODE_FIREWORKS,
+ SCENE_MODE_TEXT,
+ SCENE_MODE_CANDLE_LIGHT,
+ SCENE_MODE_MAX,
+};
+
+#define V4L2_CID_CAMERA_FLASH_MODE (V4L2_CID_PRIVATE_BASE + 71)
+enum v4l2_flash_mode {
+ FLASH_MODE_BASE,
+ FLASH_MODE_OFF,
+ FLASH_MODE_AUTO,
+ FLASH_MODE_ON,
+ FLASH_MODE_TORCH,
+ FLASH_MODE_MAX,
+};
+
+#define V4L2_CID_CAMERA_BRIGHTNESS (V4L2_CID_PRIVATE_BASE + 72)
+enum v4l2_ev_mode {
+ EV_MINUS_4 = 0,
+ EV_MINUS_3,
+ EV_MINUS_2,
+ EV_MINUS_1,
+ EV_DEFAULT,
+ EV_PLUS_1,
+ EV_PLUS_2,
+ EV_PLUS_3,
+ EV_PLUS_4,
+ EV_MAX,
+};
+
+#define V4L2_CID_CAMERA_WHITE_BALANCE (V4L2_CID_PRIVATE_BASE + 73)
+enum v4l2_wb_mode {
+ WHITE_BALANCE_BASE = 0,
+ WHITE_BALANCE_AUTO,
+ WHITE_BALANCE_SUNNY,
+ WHITE_BALANCE_CLOUDY,
+ WHITE_BALANCE_TUNGSTEN,
+ WHITE_BALANCE_FLUORESCENT,
+ WHITE_BALANCE_MAX,
+};
+
+#define V4L2_CID_CAMERA_EFFECT (V4L2_CID_PRIVATE_BASE + 74)
+enum v4l2_effect_mode {
+ IMAGE_EFFECT_BASE = 0,
+ IMAGE_EFFECT_NONE,
+ IMAGE_EFFECT_BNW,
+ IMAGE_EFFECT_SEPIA,
+ IMAGE_EFFECT_AQUA,
+ IMAGE_EFFECT_ANTIQUE,
+ IMAGE_EFFECT_NEGATIVE,
+ IMAGE_EFFECT_SHARPEN,
+ IMAGE_EFFECT_MAX,
+};
+
+#define V4L2_CID_CAMERA_ISO (V4L2_CID_PRIVATE_BASE + 75)
+enum v4l2_iso_mode {
+ ISO_AUTO = 0,
+ ISO_50,
+ ISO_100,
+ ISO_200,
+ ISO_400,
+ ISO_800,
+ ISO_1600,
+ ISO_SPORTS,
+ ISO_NIGHT,
+ ISO_MOVIE,
+ ISO_MAX,
+};
+
+#define V4L2_CID_CAMERA_METERING (V4L2_CID_PRIVATE_BASE + 76)
+enum v4l2_metering_mode {
+ METERING_BASE = 0,
+ METERING_MATRIX,
+ METERING_CENTER,
+ METERING_SPOT,
+ METERING_MAX,
+};
+
+#define V4L2_CID_CAMERA_CONTRAST (V4L2_CID_PRIVATE_BASE + 77)
+enum v4l2_contrast_mode {
+ CONTRAST_MINUS_2 = 0,
+ CONTRAST_MINUS_1,
+ CONTRAST_DEFAULT,
+ CONTRAST_PLUS_1,
+ CONTRAST_PLUS_2,
+ CONTRAST_MAX,
+};
+
+#define V4L2_CID_CAMERA_SATURATION (V4L2_CID_PRIVATE_BASE + 78)
+enum v4l2_saturation_mode {
+ SATURATION_MINUS_2 = 0,
+ SATURATION_MINUS_1,
+ SATURATION_DEFAULT,
+ SATURATION_PLUS_1,
+ SATURATION_PLUS_2,
+ SATURATION_MAX,
+};
+
+#define V4L2_CID_CAMERA_SHARPNESS (V4L2_CID_PRIVATE_BASE + 79)
+enum v4l2_sharpness_mode {
+ SHARPNESS_MINUS_2 = 0,
+ SHARPNESS_MINUS_1,
+ SHARPNESS_DEFAULT,
+ SHARPNESS_PLUS_1,
+ SHARPNESS_PLUS_2,
+ SHARPNESS_MAX,
+};
+
+#define V4L2_CID_CAMERA_WDR (V4L2_CID_PRIVATE_BASE + 80)
+enum v4l2_wdr_mode {
+ WDR_OFF,
+ WDR_ON,
+ WDR_MAX,
+};
+
+#define V4L2_CID_CAMERA_ANTI_SHAKE (V4L2_CID_PRIVATE_BASE + 81)
+enum v4l2_anti_shake_mode {
+ ANTI_SHAKE_OFF,
+ ANTI_SHAKE_STILL_ON,
+ ANTI_SHAKE_MOVIE_ON,
+ ANTI_SHAKE_MAX,
+};
+
+#define V4L2_CID_CAMERA_TOUCH_AF_START_STOP (V4L2_CID_PRIVATE_BASE + 82)
+enum v4l2_touch_af {
+ TOUCH_AF_STOP = 0,
+ TOUCH_AF_START,
+ TOUCH_AF_MAX,
+};
+
+#define V4L2_CID_CAMERA_SMART_AUTO (V4L2_CID_PRIVATE_BASE + 83)
+enum v4l2_smart_auto {
+ SMART_AUTO_OFF = 0,
+ SMART_AUTO_ON,
+ SMART_AUTO_MAX,
+};
+
+#define V4L2_CID_CAMERA_VINTAGE_MODE (V4L2_CID_PRIVATE_BASE + 84)
+enum v4l2_vintage_mode {
+ VINTAGE_MODE_BASE,
+ VINTAGE_MODE_OFF,
+ VINTAGE_MODE_NORMAL,
+ VINTAGE_MODE_WARM,
+ VINTAGE_MODE_COOL,
+ VINTAGE_MODE_BNW,
+ VINTAGE_MODE_MAX,
+};
+
+#define V4L2_CID_CAMERA_JPEG_QUALITY (V4L2_CID_PRIVATE_BASE + 85)
+#define V4L2_CID_CAMERA_GPS_LATITUDE (V4L2_CID_CAMERA_CLASS_BASE + 30)
+#define V4L2_CID_CAMERA_GPS_LONGITUDE (V4L2_CID_CAMERA_CLASS_BASE + 31)
+#define V4L2_CID_CAMERA_GPS_TIMESTAMP (V4L2_CID_CAMERA_CLASS_BASE + 32)
+#define V4L2_CID_CAMERA_GPS_ALTITUDE (V4L2_CID_CAMERA_CLASS_BASE + 33)
+#define V4L2_CID_CAMERA_EXIF_TIME_INFO (V4L2_CID_CAMERA_CLASS_BASE + 34)
+#define V4L2_CID_CAMERA_ZOOM (V4L2_CID_PRIVATE_BASE + 90)
+enum v4l2_zoom_level {
+ ZOOM_LEVEL_0 = 0,
+ ZOOM_LEVEL_1,
+ ZOOM_LEVEL_2,
+ ZOOM_LEVEL_3,
+ ZOOM_LEVEL_4,
+ ZOOM_LEVEL_5,
+ ZOOM_LEVEL_6,
+ ZOOM_LEVEL_7,
+ ZOOM_LEVEL_8,
+ ZOOM_LEVEL_9,
+ ZOOM_LEVEL_10,
+ ZOOM_LEVEL_11,
+ ZOOM_LEVEL_12,
+ ZOOM_LEVEL_MAX,
+};
+
+#define V4L2_CID_CAMERA_FACE_DETECTION (V4L2_CID_PRIVATE_BASE + 91)
+enum v4l2_face_detection {
+ FACE_DETECTION_OFF = 0,
+ FACE_DETECTION_ON,
+ FACE_DETECTION_NOLINE,
+ FACE_DETECTION_ON_BEAUTY,
+ FACE_DETECTION_MAX,
+};
+
+#define V4L2_CID_CAMERA_SMART_AUTO_STATUS (V4L2_CID_PRIVATE_BASE + 92)
+enum v4l2_smart_auto_status {
+ SMART_AUTO_STATUS_AUTO = 0,
+ SMART_AUTO_STATUS_LANDSCAPE,
+ SMART_AUTO_STATUS_PORTRAIT,
+ SMART_AUTO_STATUS_MACRO,
+ SMART_AUTO_STATUS_NIGHT,
+ SMART_AUTO_STATUS_PORTRAIT_NIGHT,
+ SMART_AUTO_STATUS_BACKLIT,
+ SMART_AUTO_STATUS_PORTRAIT_BACKLIT,
+ SMART_AUTO_STATUS_ANTISHAKE,
+ SMART_AUTO_STATUS_PORTRAIT_ANTISHAKE,
+ SMART_AUTO_STATUS_MAX,
+};
+
+#define V4L2_CID_CAMERA_SET_AUTO_FOCUS (V4L2_CID_PRIVATE_BASE + 93)
+enum v4l2_auto_focus {
+ AUTO_FOCUS_OFF = 0,
+ AUTO_FOCUS_ON,
+ AUTO_FOCUS_MAX,
+};
+
+#define V4L2_CID_CAMERA_BEAUTY_SHOT (V4L2_CID_PRIVATE_BASE + 94)
+enum v4l2_beauty_shot {
+ BEAUTY_SHOT_OFF = 0,
+ BEAUTY_SHOT_ON,
+ BEAUTY_SHOT_MAX,
+};
+
+#define V4L2_CID_CAMERA_AEAWB_LOCK_UNLOCK (V4L2_CID_PRIVATE_BASE + 95)
+enum v4l2_ae_awb_lockunlock {
+ AE_UNLOCK_AWB_UNLOCK = 0,
+ AE_LOCK_AWB_UNLOCK,
+ AE_UNLOCK_AWB_LOCK,
+ AE_LOCK_AWB_LOCK,
+ AE_AWB_MAX
+};
+
+#define V4L2_CID_CAMERA_FACEDETECT_LOCKUNLOCK (V4L2_CID_PRIVATE_BASE + 96)
+enum v4l2_face_lock {
+ FACE_LOCK_OFF = 0,
+ FACE_LOCK_ON,
+ FIRST_FACE_TRACKING,
+ FACE_LOCK_MAX,
+};
+
+#define V4L2_CID_CAMERA_OBJECT_POSITION_X (V4L2_CID_PRIVATE_BASE + 97)
+#define V4L2_CID_CAMERA_OBJECT_POSITION_Y (V4L2_CID_PRIVATE_BASE + 98)
+#define V4L2_CID_CAMERA_FOCUS_MODE (V4L2_CID_PRIVATE_BASE + 99)
+enum v4l2_focusmode {
+ FOCUS_MODE_AUTO = 0,
+ FOCUS_MODE_MACRO,
+ FOCUS_MODE_FACEDETECT,
+ FOCUS_MODE_AUTO_DEFAULT,
+ FOCUS_MODE_MACRO_DEFAULT,
+ FOCUS_MODE_FACEDETECT_DEFAULT,
+ FOCUS_MODE_INFINITY,
+ FOCUS_MODE_MAX,
+};
+
+#define V4L2_CID_CAMERA_OBJ_TRACKING_STATUS (V4L2_CID_PRIVATE_BASE + 100)
+enum v4l2_obj_tracking_status {
+ OBJECT_TRACKING_STATUS_BASE,
+ OBJECT_TRACKING_STATUS_PROGRESSING,
+ OBJECT_TRACKING_STATUS_SUCCESS,
+ OBJECT_TRACKING_STATUS_FAIL,
+ OBJECT_TRACKING_STATUS_MISSING,
+ OBJECT_TRACKING_STATUS_MAX,
+};
+
+#define V4L2_CID_CAMERA_OBJ_TRACKING_START_STOP (V4L2_CID_PRIVATE_BASE + 101)
+enum v4l2_ot_start_stop {
+ OT_STOP = 0,
+ OT_START,
+ OT_MAX,
+};
+
+#define V4L2_CID_CAMERA_CAF_START_STOP (V4L2_CID_PRIVATE_BASE + 102)
+enum v4l2_caf_start_stop {
+ CAF_STOP = 0,
+ CAF_START,
+ CAF_MAX,
+};
+
+#define V4L2_CID_CAMERA_AUTO_FOCUS_RESULT_FIRST (V4L2_CID_PRIVATE_BASE + 103)
+#define V4L2_CID_CAMERA_AUTO_FOCUS_RESULT_SECOND (V4L2_CID_PRIVATE_BASE + 120)
+#define V4L2_CID_CAMERA_FINISH_AUTO_FOCUS (V4L2_CID_PRIVATE_BASE + 121)
+#define V4L2_CID_CAMERA_FRAME_RATE (V4L2_CID_PRIVATE_BASE + 104)
+enum v4l2_frame_rate {
+ FRAME_RATE_AUTO = 0,
+ FRAME_RATE_7 = 7,
+ FRAME_RATE_15 = 15,
+ FRAME_RATE_30 = 30,
+ FRAME_RATE_60 = 60,
+ FRAME_RATE_120 = 120,
+ FRAME_RATE_MAX
+};
+
+#define V4L2_CID_CAMERA_ANTI_BANDING (V4L2_CID_PRIVATE_BASE + 105)
+enum v4l2_anti_banding {
+ ANTI_BANDING_AUTO = 0,
+ ANTI_BANDING_50HZ = 1,
+ ANTI_BANDING_60HZ = 2,
+ ANTI_BANDING_OFF = 3,
+};
+
+#define V4L2_CID_CAMERA_SET_GAMMA (V4L2_CID_PRIVATE_BASE + 106)
+enum v4l2_gamma_mode {
+ GAMMA_OFF = 0,
+ GAMMA_ON = 1,
+ GAMMA_MAX,
+};
+
+#define V4L2_CID_CAMERA_SET_SLOW_AE (V4L2_CID_PRIVATE_BASE + 107)
+enum v4l2_slow_ae_mode {
+ SLOW_AE_OFF,
+ SLOW_AE_ON,
+ SLOW_AE_MAX,
+};
+
+#define V4L2_CID_CAMERA_BATCH_REFLECTION (V4L2_CID_PRIVATE_BASE + 108)
+#define V4L2_CID_CAMERA_EXIF_ORIENTATION (V4L2_CID_PRIVATE_BASE + 109)
+
+#define V4L2_CID_CAMERA_RESET (V4L2_CID_PRIVATE_BASE + 111)
+#define V4L2_CID_CAMERA_CHECK_DATALINE (V4L2_CID_PRIVATE_BASE + 112)
+#define V4L2_CID_CAMERA_CHECK_DATALINE_STOP (V4L2_CID_PRIVATE_BASE + 113)
+#define V4L2_CID_CAMERA_GET_ISO (V4L2_CID_PRIVATE_BASE + 114)
+#define V4L2_CID_CAMERA_GET_SHT_TIME (V4L2_CID_PRIVATE_BASE + 115)
+#define V4L2_CID_CAMERA_SENSOR_MODE (V4L2_CID_PRIVATE_BASE + 116)
+#define V4L2_CID_ESD_INT (V4L2_CID_PRIVATE_BASE + 117)
+#define V4L2_CID_CAMERA_GET_FLASH_ONOFF (V4L2_CID_PRIVATE_BASE + 118)
+#define V4L2_CID_CAMERA_RETURN_FOCUS (V4L2_CID_PRIVATE_BASE + 119)
+
+/* Pixel format FOURCC depth Description */
+/* 12 Y/CbCr 4:2:0 64x32 macroblocks */
+#define V4L2_PIX_FMT_NV12T v4l2_fourcc('T', 'V', '1', '2')
+
+/*
+ * * V4L2 extention for digital camera
+ * */
+/* Strobe flash light */
+enum v4l2_strobe_control {
+ /* turn off the flash light */
+ V4L2_STROBE_CONTROL_OFF = 0,
+ /* turn on the flash light */
+ V4L2_STROBE_CONTROL_ON = 1,
+ /* act guide light before splash */
+ V4L2_STROBE_CONTROL_AFGUIDE = 2,
+ /* charge the flash light */
+ V4L2_STROBE_CONTROL_CHARGE = 3,
+};
+
+enum v4l2_strobe_conf {
+ V4L2_STROBE_OFF = 0, /* Always off */
+ V4L2_STROBE_ON = 1, /* Always splashes */
+ /* Auto control presets */
+ V4L2_STROBE_AUTO = 2,
+ V4L2_STROBE_REDEYE_REDUCTION = 3,
+ V4L2_STROBE_SLOW_SYNC = 4,
+ V4L2_STROBE_FRONT_CURTAIN = 5,
+ V4L2_STROBE_REAR_CURTAIN = 6,
+ /* Extra manual control presets */
+ /* keep turned on until turning off */
+ V4L2_STROBE_PERMANENT = 7,
+ V4L2_STROBE_EXTERNAL = 8,
+};
+
+enum v4l2_strobe_status {
+ V4L2_STROBE_STATUS_OFF = 0,
+ /* while processing configurations */
+ V4L2_STROBE_STATUS_BUSY = 1,
+ V4L2_STROBE_STATUS_ERR = 2,
+ V4L2_STROBE_STATUS_CHARGING = 3,
+ V4L2_STROBE_STATUS_CHARGED = 4,
+};
+
+/* capabilities field */
+/* No strobe supported */
+#define V4L2_STROBE_CAP_NONE 0x0000
+/* Always flash off mode */
+#define V4L2_STROBE_CAP_OFF 0x0001
+/* Always use flash light mode */
+#define V4L2_STROBE_CAP_ON 0x0002
+/* Flashlight works automatic */
+#define V4L2_STROBE_CAP_AUTO 0x0004
+/* Red-eye reduction */
+#define V4L2_STROBE_CAP_REDEYE 0x0008
+/* Slow sync */
+#define V4L2_STROBE_CAP_SLOWSYNC 0x0010
+/* Front curtain */
+#define V4L2_STROBE_CAP_FRONT_CURTAIN 0x0020
+/* Rear curtain */
+#define V4L2_STROBE_CAP_REAR_CURTAIN 0x0040
+/* keep turned on until turning off */
+#define V4L2_STROBE_CAP_PERMANENT 0x0080
+/* use external strobe */
+#define V4L2_STROBE_CAP_EXTERNAL 0x0100
+
+/* Set mode and Get status */
+struct v4l2_strobe {
+ /* off/on/charge:0/1/2 */
+ enum v4l2_strobe_control control;
+ /* supported strobe capabilities */
+ __u32 capabilities;
+ enum v4l2_strobe_conf mode;
+ enum v4l2_strobe_status status; /* read only */
+ /* default is 0 and range of value varies from each models */
+ __u32 flash_ev;
+ __u32 reserved[4];
+};
+
+#define VIDIOC_S_STROBE _IOWR('V', 83, struct v4l2_strobe)
+#define VIDIOC_G_STROBE _IOR('V', 84, struct v4l2_strobe)
+
+/* Object recognition and collateral actions */
+enum v4l2_recog_mode {
+ V4L2_RECOGNITION_MODE_OFF = 0,
+ V4L2_RECOGNITION_MODE_ON = 1,
+ V4L2_RECOGNITION_MODE_LOCK = 2,
+};
+
+enum v4l2_recog_action {
+ V4L2_RECOGNITION_ACTION_NONE = 0, /* only recognition */
+ V4L2_RECOGNITION_ACTION_BLINK = 1, /* Capture on blinking */
+ V4L2_RECOGNITION_ACTION_SMILE = 2, /* Capture on smiling */
+};
+
+enum v4l2_recog_pattern {
+ V4L2_RECOG_PATTERN_FACE = 0, /* Face */
+ V4L2_RECOG_PATTERN_HUMAN = 1, /* Human */
+ V4L2_RECOG_PATTERN_CHAR = 2, /* Character */
+};
+
+struct v4l2_recog_rect {
+ enum v4l2_recog_pattern p; /* detected pattern */
+ struct v4l2_rect o; /* detected area */
+ __u32 reserved[4];
+};
+
+struct v4l2_recog_data {
+ __u8 detect_cnt; /* detected object counter */
+ struct v4l2_rect o; /* detected area */
+ __u32 reserved[4];
+};
+
+struct v4l2_recognition {
+ enum v4l2_recog_mode mode;
+
+ /* Which pattern to detect */
+ enum v4l2_recog_pattern pattern;
+
+ /* How many object to detect */
+ __u8 obj_num;
+
+ /* select detected object */
+ __u32 detect_idx;
+
+ /* read only :Get object coordination */
+ struct v4l2_recog_data data;
+
+ enum v4l2_recog_action action;
+ __u32 reserved[4];
+};
+
+#define VIDIOC_S_RECOGNITION _IOWR('V', 85, struct v4l2_recognition)
+#define VIDIOC_G_RECOGNITION _IOR('V', 86, struct v4l2_recognition)
+
+/* We use this struct as the v4l2_streamparm raw_data for
+ * VIDIOC_G_PARM and VIDIOC_S_PARM
+ */
+struct sec_cam_parm {
+ struct v4l2_captureparm capture;
+ int contrast;
+ int effects;
+ int brightness;
+ int flash_mode;
+ int focus_mode;
+ int iso;
+ int metering;
+ int saturation;
+ int scene_mode;
+ int sharpness;
+ int white_balance;
+ int fps;
+};
+
+#endif /* __LINUX_VIDEODEV2_SAMSUNG_H */
diff --git a/include/linux/wimax/samsung/wimax732.h b/include/linux/wimax/samsung/wimax732.h
new file mode 100644
index 0000000..94d5620
--- /dev/null
+++ b/include/linux/wimax/samsung/wimax732.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2008 Samsung Electronics, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/miscdevice.h>
+
+#ifndef __WIMAX_CMC732_H
+#define __WIMAX_CMC732_H
+
+#ifdef __KERNEL__
+
+#define WIMAX_POWER_SUCCESS 0
+#define WIMAX_ALREADY_POWER_ON -1
+#define WIMAX_PROBE_FAIL -2
+#define WIMAX_ALREADY_POWER_OFF -3
+
+/* wimax mode */
+enum {
+ SDIO_MODE = 0,
+ WTM_MODE,
+ MAC_IMEI_WRITE_MODE,
+ USIM_RELAY_MODE,
+ DM_MODE,
+ USB_MODE,
+ AUTH_MODE
+};
+
+/* wimax state */
+enum {
+ WIMAX_STATE_NOT_READY,
+ WIMAX_STATE_READY,
+ WIMAX_STATE_VIRTUAL_IDLE,
+ WIMAX_STATE_NORMAL,
+ WIMAX_STATE_IDLE,
+ WIMAX_STATE_RESET_REQUESTED,
+ WIMAX_STATE_RESET_ACKED,
+ WIMAX_STATE_AWAKE_REQUESTED,
+};
+
+struct wimax_cfg {
+ int temp_tgid; /* handles unexpected close */
+ struct wake_lock wimax_wake_lock; /* resume wake lock */
+ struct wake_lock wimax_rxtx_lock;/* sdio wake lock */
+ struct wake_lock wimax_tx_lock;/* sdio tx lock */
+ struct mutex suspend_mutex;
+ u8 wimax_status;
+ u8 wimax_mode;/* wimax mode (SDIO, USB, etc..) */
+ u8 sleep_mode;/* suspend mode (0: VI, 1: IDLE) */
+ u8 card_removed;/*
+ * set if host has acknowledged
+ * card removal
+ */
+};
+
+struct wimax732_platform_data {
+ int (*power) (int);
+ void (*set_mode) (void);
+ void (*signal_ap_active) (int);
+ int (*get_sleep_mode) (void);
+ int (*is_modem_awake) (void);
+ void (*wakeup_assert) (int);
+ struct wimax_cfg *g_cfg;
+ struct miscdevice swmxctl_dev;
+ int wimax_int;
+};
+
+#endif
+
+#endif
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
index 22e61fd..28e493b 100644
--- a/include/linux/xfrm.h
+++ b/include/linux/xfrm.h
@@ -84,6 +84,8 @@ struct xfrm_replay_state {
__u32 bitmap;
};
+#define XFRMA_REPLAY_ESN_MAX 4096
+
struct xfrm_replay_state_esn {
unsigned int bmp_len;
__u32 oseq;
diff --git a/include/media/s5k4ecgx.h b/include/media/s5k4ecgx.h
new file mode 100644
index 0000000..3902ef5
--- /dev/null
+++ b/include/media/s5k4ecgx.h
@@ -0,0 +1,24 @@
+/* include/media/s5k4ecgx.h
+ *
+ * Copyright (C) 2010, SAMSUNG ELECTRONICS
+ *
+ * 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.
+ */
+
+#define S5K4ECGX_DRIVER_NAME "S5K4ECGX"
+
+struct s5k4ecgx_platform_data {
+ unsigned int default_width;
+ unsigned int default_height;
+ unsigned int pixelformat;
+ int freq; /* MCLK in Hz */
+
+ int (*flash_onoff)(int);
+ int (*af_assist_onoff)(int);
+ int (*torch_onoff)(int);
+};
+
+
diff --git a/include/media/s5ka3dfx_platform.h b/include/media/s5ka3dfx_platform.h
new file mode 100644
index 0000000..6da199f
--- /dev/null
+++ b/include/media/s5ka3dfx_platform.h
@@ -0,0 +1,22 @@
+/*
+ * Driver for S5KA3DFX (VGA camera) from SAMSUNG ELECTRONICS
+ *
+ * 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.
+ */
+
+struct s5ka3dfx_platform_data {
+ unsigned int default_width;
+ unsigned int default_height;
+ unsigned int pixelformat;
+ int freq; /* MCLK in Hz */
+
+ /* This SoC supports Parallel & CSI-2 */
+ int is_mipi;
+
+ /* Board specific power pin control */
+ int (*cam_power)(int onoff);
+};
+
diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h
index abd4436..4af554b 100644
--- a/include/net/cipso_ipv4.h
+++ b/include/net/cipso_ipv4.h
@@ -42,6 +42,7 @@
#include <net/netlabel.h>
#include <net/request_sock.h>
#include <asm/atomic.h>
+#include <asm/unaligned.h>
/* known doi values */
#define CIPSO_V4_DOI_UNKNOWN 0x00000000
@@ -285,7 +286,33 @@ static inline int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
static inline int cipso_v4_validate(const struct sk_buff *skb,
unsigned char **option)
{
- return -ENOSYS;
+ unsigned char *opt = *option;
+ unsigned char err_offset = 0;
+ u8 opt_len = opt[1];
+ u8 opt_iter;
+
+ if (opt_len < 8) {
+ err_offset = 1;
+ goto out;
+ }
+
+ if (get_unaligned_be32(&opt[2]) == 0) {
+ err_offset = 2;
+ goto out;
+ }
+
+ for (opt_iter = 6; opt_iter < opt_len;) {
+ if (opt[opt_iter + 1] > (opt_len - opt_iter)) {
+ err_offset = opt_iter + 1;
+ goto out;
+ }
+ opt_iter += opt[opt_iter + 1];
+ }
+
+out:
+ *option = opt + err_offset;
+ return err_offset;
+
}
#endif /* CONFIG_NETLABEL */
diff --git a/include/net/dst.h b/include/net/dst.h
index d020134..7907ff1 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -78,6 +78,7 @@ struct dst_entry {
#define DST_NOHASH 0x0008
#define DST_NOCACHE 0x0010
#define DST_NOCOUNT 0x0020
+#define DST_XFRM_TUNNEL 0x0100
union {
struct dst_entry *next;
struct rtable __rcu *rt_next;
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 481f856..15b62bb 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -1361,7 +1361,7 @@ static inline void ip_vs_notrack(struct sk_buff *skb)
struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
if (!ct || !nf_ct_is_untracked(ct)) {
- nf_reset(skb);
+ nf_conntrack_put(skb->nfct);
skb->nfct = &nf_ct_untracked_get()->ct_general;
skb->nfctinfo = IP_CT_NEW;
nf_conntrack_get(skb->nfct);
diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h
index 4283508..3a0feb1 100644
--- a/include/net/netfilter/nf_conntrack_ecache.h
+++ b/include/net/netfilter/nf_conntrack_ecache.h
@@ -18,6 +18,7 @@ struct nf_conntrack_ecache {
u16 ctmask; /* bitmask of ct events to be delivered */
u16 expmask; /* bitmask of expect events to be delivered */
u32 pid; /* netlink pid of destroyer */
+ struct timer_list timeout;
};
static inline struct nf_conntrack_ecache *
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index f1fbe2d..af2e047 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -219,13 +219,16 @@ struct tcf_proto {
struct qdisc_skb_cb {
unsigned int pkt_len;
- unsigned char data[24];
+ u16 bond_queue_mapping;
+ u16 _pad;
+ unsigned char data[20];
};
static inline void qdisc_cb_private_validate(const struct sk_buff *skb, int sz)
{
struct qdisc_skb_cb *qcb;
- BUILD_BUG_ON(sizeof(skb->cb) < sizeof(unsigned int) + sz);
+
+ BUILD_BUG_ON(sizeof(skb->cb) < offsetof(struct qdisc_skb_cb, data) + sz);
BUILD_BUG_ON(sizeof(qcb->data) < sz);
}
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index b2c2366..f686066 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -700,4 +700,17 @@ static inline void sctp_v4_map_v6(union sctp_addr *addr)
addr->v6.sin6_addr.s6_addr32[2] = htonl(0x0000ffff);
}
+/* The cookie is always 0 since this is how it's used in the
+ * pmtu code.
+ */
+static inline struct dst_entry *sctp_transport_dst_check(struct sctp_transport *t)
+{
+ if (t->dst && !dst_check(t->dst, 0)) {
+ dst_release(t->dst);
+ t->dst = NULL;
+ }
+
+ return t->dst;
+}
+
#endif /* __net_sctp_h__ */
diff --git a/include/net/sock.h b/include/net/sock.h
index c0b938c..b2deeab 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -194,6 +194,7 @@ struct sock_common {
* @sk_route_nocaps: forbidden route capabilities (e.g NETIF_F_GSO_MASK)
* @sk_gso_type: GSO type (e.g. %SKB_GSO_TCPV4)
* @sk_gso_max_size: Maximum GSO segment size to build
+ * @sk_gso_max_segs: Maximum number of GSO segments
* @sk_lingertime: %SO_LINGER l_linger setting
* @sk_backlog: always used with the per-socket spinlock held
* @sk_callback_lock: used with the callbacks in the end of this struct
@@ -310,6 +311,7 @@ struct sock {
int sk_route_nocaps;
int sk_gso_type;
unsigned int sk_gso_max_size;
+ u16 sk_gso_max_segs;
int sk_rcvlowat;
unsigned long sk_lingertime;
struct sk_buff_head sk_error_queue;
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index b203e14..921f627 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -269,6 +269,9 @@ struct xfrm_replay {
int (*check)(struct xfrm_state *x,
struct sk_buff *skb,
__be32 net_seq);
+ int (*recheck)(struct xfrm_state *x,
+ struct sk_buff *skb,
+ __be32 net_seq);
void (*notify)(struct xfrm_state *x, int event);
int (*overflow)(struct xfrm_state *x, struct sk_buff *skb);
};
diff --git a/include/trace/events/kmem.h b/include/trace/events/kmem.h
index a9c87ad..a9536da 100644
--- a/include/trace/events/kmem.h
+++ b/include/trace/events/kmem.h
@@ -214,7 +214,7 @@ TRACE_EVENT(mm_page_alloc,
TP_printk("page=%p pfn=%lu order=%d migratetype=%d gfp_flags=%s",
__entry->page,
- page_to_pfn(__entry->page),
+ __entry->page ? page_to_pfn(__entry->page) : 0,
__entry->order,
__entry->migratetype,
show_gfp_flags(__entry->gfp_flags))
@@ -240,7 +240,7 @@ DECLARE_EVENT_CLASS(mm_page,
TP_printk("page=%p pfn=%lu order=%u migratetype=%d percpu_refill=%d",
__entry->page,
- page_to_pfn(__entry->page),
+ __entry->page ? page_to_pfn(__entry->page) : 0,
__entry->order,
__entry->migratetype,
__entry->order == 0)
diff --git a/include/trace/events/random.h b/include/trace/events/random.h
new file mode 100644
index 0000000..422df19
--- /dev/null
+++ b/include/trace/events/random.h
@@ -0,0 +1,134 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM random
+
+#if !defined(_TRACE_RANDOM_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_RANDOM_H
+
+#include <linux/writeback.h>
+#include <linux/tracepoint.h>
+
+DECLARE_EVENT_CLASS(random__mix_pool_bytes,
+ TP_PROTO(const char *pool_name, int bytes, unsigned long IP),
+
+ TP_ARGS(pool_name, bytes, IP),
+
+ TP_STRUCT__entry(
+ __field( const char *, pool_name )
+ __field( int, bytes )
+ __field(unsigned long, IP )
+ ),
+
+ TP_fast_assign(
+ __entry->pool_name = pool_name;
+ __entry->bytes = bytes;
+ __entry->IP = IP;
+ ),
+
+ TP_printk("%s pool: bytes %d caller %pF",
+ __entry->pool_name, __entry->bytes, (void *)__entry->IP)
+);
+
+DEFINE_EVENT(random__mix_pool_bytes, mix_pool_bytes,
+ TP_PROTO(const char *pool_name, int bytes, unsigned long IP),
+
+ TP_ARGS(pool_name, bytes, IP)
+);
+
+DEFINE_EVENT(random__mix_pool_bytes, mix_pool_bytes_nolock,
+ TP_PROTO(const char *pool_name, int bytes, unsigned long IP),
+
+ TP_ARGS(pool_name, bytes, IP)
+);
+
+TRACE_EVENT(credit_entropy_bits,
+ TP_PROTO(const char *pool_name, int bits, int entropy_count,
+ int entropy_total, unsigned long IP),
+
+ TP_ARGS(pool_name, bits, entropy_count, entropy_total, IP),
+
+ TP_STRUCT__entry(
+ __field( const char *, pool_name )
+ __field( int, bits )
+ __field( int, entropy_count )
+ __field( int, entropy_total )
+ __field(unsigned long, IP )
+ ),
+
+ TP_fast_assign(
+ __entry->pool_name = pool_name;
+ __entry->bits = bits;
+ __entry->entropy_count = entropy_count;
+ __entry->entropy_total = entropy_total;
+ __entry->IP = IP;
+ ),
+
+ TP_printk("%s pool: bits %d entropy_count %d entropy_total %d "
+ "caller %pF", __entry->pool_name, __entry->bits,
+ __entry->entropy_count, __entry->entropy_total,
+ (void *)__entry->IP)
+);
+
+TRACE_EVENT(get_random_bytes,
+ TP_PROTO(int nbytes, unsigned long IP),
+
+ TP_ARGS(nbytes, IP),
+
+ TP_STRUCT__entry(
+ __field( int, nbytes )
+ __field(unsigned long, IP )
+ ),
+
+ TP_fast_assign(
+ __entry->nbytes = nbytes;
+ __entry->IP = IP;
+ ),
+
+ TP_printk("nbytes %d caller %pF", __entry->nbytes, (void *)__entry->IP)
+);
+
+DECLARE_EVENT_CLASS(random__extract_entropy,
+ TP_PROTO(const char *pool_name, int nbytes, int entropy_count,
+ unsigned long IP),
+
+ TP_ARGS(pool_name, nbytes, entropy_count, IP),
+
+ TP_STRUCT__entry(
+ __field( const char *, pool_name )
+ __field( int, nbytes )
+ __field( int, entropy_count )
+ __field(unsigned long, IP )
+ ),
+
+ TP_fast_assign(
+ __entry->pool_name = pool_name;
+ __entry->nbytes = nbytes;
+ __entry->entropy_count = entropy_count;
+ __entry->IP = IP;
+ ),
+
+ TP_printk("%s pool: nbytes %d entropy_count %d caller %pF",
+ __entry->pool_name, __entry->nbytes, __entry->entropy_count,
+ (void *)__entry->IP)
+);
+
+
+DEFINE_EVENT(random__extract_entropy, extract_entropy,
+ TP_PROTO(const char *pool_name, int nbytes, int entropy_count,
+ unsigned long IP),
+
+ TP_ARGS(pool_name, nbytes, entropy_count, IP)
+);
+
+DEFINE_EVENT(random__extract_entropy, extract_entropy_user,
+ TP_PROTO(const char *pool_name, int nbytes, int entropy_count,
+ unsigned long IP),
+
+ TP_ARGS(pool_name, nbytes, entropy_count, IP)
+);
+
+
+
+#endif /* _TRACE_RANDOM_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/include/trace/events/vmscan.h b/include/trace/events/vmscan.h
index b2c33bd..edc4b3d 100644
--- a/include/trace/events/vmscan.h
+++ b/include/trace/events/vmscan.h
@@ -179,6 +179,83 @@ DEFINE_EVENT(mm_vmscan_direct_reclaim_end_template, mm_vmscan_memcg_softlimit_re
TP_ARGS(nr_reclaimed)
);
+TRACE_EVENT(mm_shrink_slab_start,
+ TP_PROTO(struct shrinker *shr, struct shrink_control *sc,
+ long nr_objects_to_shrink, unsigned long pgs_scanned,
+ unsigned long lru_pgs, unsigned long cache_items,
+ unsigned long long delta, unsigned long total_scan),
+
+ TP_ARGS(shr, sc, nr_objects_to_shrink, pgs_scanned, lru_pgs,
+ cache_items, delta, total_scan),
+
+ TP_STRUCT__entry(
+ __field(struct shrinker *, shr)
+ __field(void *, shrink)
+ __field(long, nr_objects_to_shrink)
+ __field(gfp_t, gfp_flags)
+ __field(unsigned long, pgs_scanned)
+ __field(unsigned long, lru_pgs)
+ __field(unsigned long, cache_items)
+ __field(unsigned long long, delta)
+ __field(unsigned long, total_scan)
+ ),
+
+ TP_fast_assign(
+ __entry->shr = shr;
+ __entry->shrink = shr->shrink;
+ __entry->nr_objects_to_shrink = nr_objects_to_shrink;
+ __entry->gfp_flags = sc->gfp_mask;
+ __entry->pgs_scanned = pgs_scanned;
+ __entry->lru_pgs = lru_pgs;
+ __entry->cache_items = cache_items;
+ __entry->delta = delta;
+ __entry->total_scan = total_scan;
+ ),
+
+ TP_printk("%pF %p: objects to shrink %ld gfp_flags %s pgs_scanned %ld lru_pgs %ld cache items %ld delta %lld total_scan %ld",
+ __entry->shrink,
+ __entry->shr,
+ __entry->nr_objects_to_shrink,
+ show_gfp_flags(__entry->gfp_flags),
+ __entry->pgs_scanned,
+ __entry->lru_pgs,
+ __entry->cache_items,
+ __entry->delta,
+ __entry->total_scan)
+);
+
+TRACE_EVENT(mm_shrink_slab_end,
+ TP_PROTO(struct shrinker *shr, int shrinker_retval,
+ long unused_scan_cnt, long new_scan_cnt),
+
+ TP_ARGS(shr, shrinker_retval, unused_scan_cnt, new_scan_cnt),
+
+ TP_STRUCT__entry(
+ __field(struct shrinker *, shr)
+ __field(void *, shrink)
+ __field(long, unused_scan)
+ __field(long, new_scan)
+ __field(int, retval)
+ __field(long, total_scan)
+ ),
+
+ TP_fast_assign(
+ __entry->shr = shr;
+ __entry->shrink = shr->shrink;
+ __entry->unused_scan = unused_scan_cnt;
+ __entry->new_scan = new_scan_cnt;
+ __entry->retval = shrinker_retval;
+ __entry->total_scan = new_scan_cnt - unused_scan_cnt;
+ ),
+
+ TP_printk("%pF %p: unused scan count %ld new scan count %ld total_scan %ld last shrinker return val %d",
+ __entry->shrink,
+ __entry->shr,
+ __entry->unused_scan,
+ __entry->new_scan,
+ __entry->total_scan,
+ __entry->retval)
+);
DECLARE_EVENT_CLASS(mm_vmscan_lru_isolate_template,
@@ -189,7 +266,7 @@ DECLARE_EVENT_CLASS(mm_vmscan_lru_isolate_template,
unsigned long nr_lumpy_taken,
unsigned long nr_lumpy_dirty,
unsigned long nr_lumpy_failed,
- int isolate_mode),
+ isolate_mode_t isolate_mode),
TP_ARGS(order, nr_requested, nr_scanned, nr_taken, nr_lumpy_taken, nr_lumpy_dirty, nr_lumpy_failed, isolate_mode),
@@ -201,7 +278,7 @@ DECLARE_EVENT_CLASS(mm_vmscan_lru_isolate_template,
__field(unsigned long, nr_lumpy_taken)
__field(unsigned long, nr_lumpy_dirty)
__field(unsigned long, nr_lumpy_failed)
- __field(int, isolate_mode)
+ __field(isolate_mode_t, isolate_mode)
),
TP_fast_assign(
@@ -235,7 +312,7 @@ DEFINE_EVENT(mm_vmscan_lru_isolate_template, mm_vmscan_lru_isolate,
unsigned long nr_lumpy_taken,
unsigned long nr_lumpy_dirty,
unsigned long nr_lumpy_failed,
- int isolate_mode),
+ isolate_mode_t isolate_mode),
TP_ARGS(order, nr_requested, nr_scanned, nr_taken, nr_lumpy_taken, nr_lumpy_dirty, nr_lumpy_failed, isolate_mode)
@@ -250,7 +327,7 @@ DEFINE_EVENT(mm_vmscan_lru_isolate_template, mm_vmscan_memcg_isolate,
unsigned long nr_lumpy_taken,
unsigned long nr_lumpy_dirty,
unsigned long nr_lumpy_failed,
- int isolate_mode),
+ isolate_mode_t isolate_mode),
TP_ARGS(order, nr_requested, nr_scanned, nr_taken, nr_lumpy_taken, nr_lumpy_dirty, nr_lumpy_failed, isolate_mode)
diff --git a/init/do_mounts.c b/init/do_mounts.c
index ef6478f..8959eb3 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -432,7 +432,7 @@ void __init change_floppy(char *fmt, ...)
void __init mount_root(void)
{
#ifdef CONFIG_ROOT_NFS
- if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) {
+ if (ROOT_DEV == Root_NFS) {
if (mount_nfs_root())
return;
diff --git a/init/main.c b/init/main.c
index d7211fa..841e344 100644
--- a/init/main.c
+++ b/init/main.c
@@ -549,9 +549,6 @@ asmlinkage void __init start_kernel(void)
early_boot_irqs_disabled = false;
local_irq_enable();
- /* Interrupts are enabled now so all GFP allocations are safe. */
- gfp_allowed_mask = __GFP_BITS_MASK;
-
kmem_cache_init_late();
/*
@@ -783,6 +780,10 @@ static int __init kernel_init(void * unused)
* Wait until kthreadd is all set-up.
*/
wait_for_completion(&kthreadd_done);
+
+ /* Now the scheduler is fully set up and can do blocking allocations */
+ gfp_allowed_mask = __GFP_BITS_MASK;
+
/*
* init can allocate pages on any node
*/
diff --git a/kernel/async.c b/kernel/async.c
index cd9dbb9..04f66e3 100644
--- a/kernel/async.c
+++ b/kernel/async.c
@@ -87,6 +87,13 @@ static async_cookie_t __lowest_in_progress(struct list_head *running)
{
struct async_entry *entry;
+ if (!running) { /* just check the entry count */
+ if (atomic_read(&entry_count))
+ return 0; /* smaller than any cookie */
+ else
+ return next_cookie;
+ }
+
if (!list_empty(running)) {
entry = list_first_entry(running,
struct async_entry, list);
@@ -236,9 +243,7 @@ EXPORT_SYMBOL_GPL(async_schedule_domain);
*/
void async_synchronize_full(void)
{
- do {
- async_synchronize_cookie(next_cookie);
- } while (!list_empty(&async_running) || !list_empty(&async_pending));
+ async_synchronize_cookie_domain(next_cookie, NULL);
}
EXPORT_SYMBOL_GPL(async_synchronize_full);
@@ -258,7 +263,7 @@ EXPORT_SYMBOL_GPL(async_synchronize_full_domain);
/**
* async_synchronize_cookie_domain - synchronize asynchronous function calls within a certain domain with cookie checkpointing
* @cookie: async_cookie_t to use as checkpoint
- * @running: running list to synchronize on
+ * @running: running list to synchronize on, NULL indicates all lists
*
* This function waits until all asynchronous function calls for the
* synchronization domain specified by the running list @list submitted
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c
index e99dda0..f6b4ac7 100644
--- a/kernel/audit_tree.c
+++ b/kernel/audit_tree.c
@@ -256,7 +256,6 @@ static void untag_chunk(struct node *p)
spin_unlock(&hash_lock);
spin_unlock(&entry->lock);
fsnotify_destroy_mark(entry);
- fsnotify_put_mark(entry);
goto out;
}
@@ -265,7 +264,7 @@ static void untag_chunk(struct node *p)
fsnotify_duplicate_mark(&new->mark, entry);
if (fsnotify_add_mark(&new->mark, new->mark.group, new->mark.i.inode, NULL, 1)) {
- free_chunk(new);
+ fsnotify_put_mark(&new->mark);
goto Fallback;
}
@@ -299,7 +298,6 @@ static void untag_chunk(struct node *p)
spin_unlock(&hash_lock);
spin_unlock(&entry->lock);
fsnotify_destroy_mark(entry);
- fsnotify_put_mark(entry);
goto out;
Fallback:
@@ -328,7 +326,7 @@ static int create_chunk(struct inode *inode, struct audit_tree *tree)
entry = &chunk->mark;
if (fsnotify_add_mark(entry, audit_tree_group, inode, NULL, 0)) {
- free_chunk(chunk);
+ fsnotify_put_mark(entry);
return -ENOSPC;
}
@@ -338,6 +336,7 @@ static int create_chunk(struct inode *inode, struct audit_tree *tree)
spin_unlock(&hash_lock);
chunk->dead = 1;
spin_unlock(&entry->lock);
+ fsnotify_get_mark(entry);
fsnotify_destroy_mark(entry);
fsnotify_put_mark(entry);
return 0;
@@ -402,7 +401,7 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree)
fsnotify_duplicate_mark(chunk_entry, old_entry);
if (fsnotify_add_mark(chunk_entry, chunk_entry->group, chunk_entry->i.inode, NULL, 1)) {
spin_unlock(&old_entry->lock);
- free_chunk(chunk);
+ fsnotify_put_mark(chunk_entry);
fsnotify_put_mark(old_entry);
return -ENOSPC;
}
@@ -418,6 +417,7 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree)
spin_unlock(&chunk_entry->lock);
spin_unlock(&old_entry->lock);
+ fsnotify_get_mark(chunk_entry);
fsnotify_destroy_mark(chunk_entry);
fsnotify_put_mark(chunk_entry);
@@ -451,7 +451,6 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree)
spin_unlock(&old_entry->lock);
fsnotify_destroy_mark(old_entry);
fsnotify_put_mark(old_entry); /* pair to fsnotify_find mark_entry */
- fsnotify_put_mark(old_entry); /* and kill it */
return 0;
}
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 5083a09..739553e 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -1803,9 +1803,8 @@ static int cgroup_task_migrate(struct cgroup *cgrp, struct cgroup *oldcgrp,
* trading it for newcg is protected by cgroup_mutex, we're safe to drop
* it here; it will be freed under RCU.
*/
- put_css_set(oldcg);
-
set_bit(CGRP_RELEASABLE, &oldcgrp->flags);
+ put_css_set(oldcg);
return 0;
}
diff --git a/kernel/compat.c b/kernel/compat.c
index fc9eb093..3507c93 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -318,25 +318,54 @@ asmlinkage long compat_sys_sigpending(compat_old_sigset_t __user *set)
#ifdef __ARCH_WANT_SYS_SIGPROCMASK
-asmlinkage long compat_sys_sigprocmask(int how, compat_old_sigset_t __user *set,
- compat_old_sigset_t __user *oset)
+/*
+ * sys_sigprocmask SIG_SETMASK sets the first (compat) word of the
+ * blocked set of signals to the supplied signal set
+ */
+static inline void compat_sig_setmask(sigset_t *blocked, compat_sigset_word set)
{
- old_sigset_t s;
- long ret;
- mm_segment_t old_fs;
+ memcpy(blocked->sig, &set, sizeof(set));
+}
- if (set && get_user(s, set))
- return -EFAULT;
- old_fs = get_fs();
- set_fs(KERNEL_DS);
- ret = sys_sigprocmask(how,
- set ? (old_sigset_t __user *) &s : NULL,
- oset ? (old_sigset_t __user *) &s : NULL);
- set_fs(old_fs);
- if (ret == 0)
- if (oset)
- ret = put_user(s, oset);
- return ret;
+asmlinkage long compat_sys_sigprocmask(int how,
+ compat_old_sigset_t __user *nset,
+ compat_old_sigset_t __user *oset)
+{
+ old_sigset_t old_set, new_set;
+ sigset_t new_blocked;
+
+ old_set = current->blocked.sig[0];
+
+ if (nset) {
+ if (get_user(new_set, nset))
+ return -EFAULT;
+ new_set &= ~(sigmask(SIGKILL) | sigmask(SIGSTOP));
+
+ new_blocked = current->blocked;
+
+ switch (how) {
+ case SIG_BLOCK:
+ sigaddsetmask(&new_blocked, new_set);
+ break;
+ case SIG_UNBLOCK:
+ sigdelsetmask(&new_blocked, new_set);
+ break;
+ case SIG_SETMASK:
+ compat_sig_setmask(&new_blocked, new_set);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ set_current_blocked(&new_blocked);
+ }
+
+ if (oset) {
+ if (put_user(old_set, oset))
+ return -EFAULT;
+ }
+
+ return 0;
}
#endif
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 9c9b754..6cbe033 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -123,6 +123,19 @@ static inline struct cpuset *task_cs(struct task_struct *task)
struct cpuset, css);
}
+#ifdef CONFIG_NUMA
+static inline bool task_has_mempolicy(struct task_struct *task)
+{
+ return task->mempolicy;
+}
+#else
+static inline bool task_has_mempolicy(struct task_struct *task)
+{
+ return false;
+}
+#endif
+
+
/* bits in struct cpuset flags field */
typedef enum {
CS_CPU_EXCLUSIVE,
@@ -949,7 +962,8 @@ static void cpuset_migrate_mm(struct mm_struct *mm, const nodemask_t *from,
static void cpuset_change_task_nodemask(struct task_struct *tsk,
nodemask_t *newmems)
{
-repeat:
+ bool need_loop;
+
/*
* Allow tasks that have access to memory reserves because they have
* been OOM killed to get memory anywhere.
@@ -960,46 +974,27 @@ repeat:
return;
task_lock(tsk);
- nodes_or(tsk->mems_allowed, tsk->mems_allowed, *newmems);
- mpol_rebind_task(tsk, newmems, MPOL_REBIND_STEP1);
-
-
/*
- * ensure checking ->mems_allowed_change_disable after setting all new
- * allowed nodes.
- *
- * the read-side task can see an nodemask with new allowed nodes and
- * old allowed nodes. and if it allocates page when cpuset clears newly
- * disallowed ones continuous, it can see the new allowed bits.
- *
- * And if setting all new allowed nodes is after the checking, setting
- * all new allowed nodes and clearing newly disallowed ones will be done
- * continuous, and the read-side task may find no node to alloc page.
+ * Determine if a loop is necessary if another thread is doing
+ * get_mems_allowed(). If at least one node remains unchanged and
+ * tsk does not have a mempolicy, then an empty nodemask will not be
+ * possible when mems_allowed is larger than a word.
*/
- smp_mb();
+ need_loop = task_has_mempolicy(tsk) ||
+ !nodes_intersects(*newmems, tsk->mems_allowed);
- /*
- * Allocation of memory is very fast, we needn't sleep when waiting
- * for the read-side.
- */
- while (ACCESS_ONCE(tsk->mems_allowed_change_disable)) {
- task_unlock(tsk);
- if (!task_curr(tsk))
- yield();
- goto repeat;
- }
+ if (need_loop)
+ write_seqcount_begin(&tsk->mems_allowed_seq);
- /*
- * ensure checking ->mems_allowed_change_disable before clearing all new
- * disallowed nodes.
- *
- * if clearing newly disallowed bits before the checking, the read-side
- * task may find no node to alloc page.
- */
- smp_mb();
+ nodes_or(tsk->mems_allowed, tsk->mems_allowed, *newmems);
+ mpol_rebind_task(tsk, newmems, MPOL_REBIND_STEP1);
mpol_rebind_task(tsk, newmems, MPOL_REBIND_STEP2);
tsk->mems_allowed = *newmems;
+
+ if (need_loop)
+ write_seqcount_end(&tsk->mems_allowed_seq);
+
task_unlock(tsk);
}
@@ -2085,6 +2080,9 @@ static void scan_for_empty_cpusets(struct cpuset *root)
* (of no affect) on systems that are actively using CPU hotplug
* but making no active use of cpusets.
*
+ * The only exception to this is suspend/resume, where we don't
+ * modify cpusets at all.
+ *
* This routine ensures that top_cpuset.cpus_allowed tracks
* cpu_active_mask on each CPU hotplug (cpuhp) event.
*
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 32a6151..7b344be 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -2969,12 +2969,12 @@ EXPORT_SYMBOL_GPL(perf_event_release_kernel);
/*
* Called when the last reference to the file is gone.
*/
-static int perf_release(struct inode *inode, struct file *file)
+static void put_event(struct perf_event *event)
{
- struct perf_event *event = file->private_data;
struct task_struct *owner;
- file->private_data = NULL;
+ if (!atomic_long_dec_and_test(&event->refcount))
+ return;
rcu_read_lock();
owner = ACCESS_ONCE(event->owner);
@@ -3009,7 +3009,13 @@ static int perf_release(struct inode *inode, struct file *file)
put_task_struct(owner);
}
- return perf_event_release_kernel(event);
+ perf_event_release_kernel(event);
+}
+
+static int perf_release(struct inode *inode, struct file *file)
+{
+ put_event(file->private_data);
+ return 0;
}
u64 perf_event_read_value(struct perf_event *event, u64 *enabled, u64 *running)
@@ -3241,7 +3247,7 @@ unlock:
static const struct file_operations perf_fops;
-static struct perf_event *perf_fget_light(int fd, int *fput_needed)
+static struct file *perf_fget_light(int fd, int *fput_needed)
{
struct file *file;
@@ -3255,7 +3261,7 @@ static struct perf_event *perf_fget_light(int fd, int *fput_needed)
return ERR_PTR(-EBADF);
}
- return file->private_data;
+ return file;
}
static int perf_event_set_output(struct perf_event *event,
@@ -3287,19 +3293,21 @@ static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case PERF_EVENT_IOC_SET_OUTPUT:
{
+ struct file *output_file = NULL;
struct perf_event *output_event = NULL;
int fput_needed = 0;
int ret;
if (arg != -1) {
- output_event = perf_fget_light(arg, &fput_needed);
- if (IS_ERR(output_event))
- return PTR_ERR(output_event);
+ output_file = perf_fget_light(arg, &fput_needed);
+ if (IS_ERR(output_file))
+ return PTR_ERR(output_file);
+ output_event = output_file->private_data;
}
ret = perf_event_set_output(event, output_event);
if (output_event)
- fput_light(output_event->filp, fput_needed);
+ fput_light(output_file, fput_needed);
return ret;
}
@@ -6181,6 +6189,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
mutex_init(&event->mmap_mutex);
+ atomic_long_set(&event->refcount, 1);
event->cpu = cpu;
event->attr = *attr;
event->group_leader = group_leader;
@@ -6455,12 +6464,12 @@ SYSCALL_DEFINE5(perf_event_open,
return event_fd;
if (group_fd != -1) {
- group_leader = perf_fget_light(group_fd, &fput_needed);
- if (IS_ERR(group_leader)) {
- err = PTR_ERR(group_leader);
+ group_file = perf_fget_light(group_fd, &fput_needed);
+ if (IS_ERR(group_file)) {
+ err = PTR_ERR(group_file);
goto err_fd;
}
- group_file = group_leader->filp;
+ group_leader = group_file->private_data;
if (flags & PERF_FLAG_FD_OUTPUT)
output_event = group_leader;
if (flags & PERF_FLAG_FD_NO_GROUP)
@@ -6594,7 +6603,6 @@ SYSCALL_DEFINE5(perf_event_open,
put_ctx(gctx);
}
- event->filp = event_file;
WARN_ON_ONCE(ctx->parent_ctx);
mutex_lock(&ctx->mutex);
@@ -6682,7 +6690,6 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
goto err_free;
}
- event->filp = NULL;
WARN_ON_ONCE(ctx->parent_ctx);
mutex_lock(&ctx->mutex);
perf_install_in_context(ctx, event, cpu);
@@ -6731,7 +6738,7 @@ static void sync_child_event(struct perf_event *child_event,
* Release the parent event, if this was the last
* reference to it.
*/
- fput(parent_event->filp);
+ put_event(parent_event);
}
static void
@@ -6807,9 +6814,8 @@ static void perf_event_exit_task_context(struct task_struct *child, int ctxn)
*
* __perf_event_exit_task()
* sync_child_event()
- * fput(parent_event->filp)
- * perf_release()
- * mutex_lock(&ctx->mutex)
+ * put_event()
+ * mutex_lock(&ctx->mutex)
*
* But since its the parent context it won't be the same instance.
*/
@@ -6877,7 +6883,7 @@ static void perf_free_event(struct perf_event *event,
list_del_init(&event->child_list);
mutex_unlock(&parent->child_mutex);
- fput(parent->filp);
+ put_event(parent);
perf_group_detach(event);
list_del_event(event, ctx);
@@ -6957,6 +6963,12 @@ inherit_event(struct perf_event *parent_event,
NULL);
if (IS_ERR(child_event))
return child_event;
+
+ if (!atomic_long_inc_not_zero(&parent_event->refcount)) {
+ free_event(child_event);
+ return NULL;
+ }
+
get_ctx(child_ctx);
/*
@@ -6996,14 +7008,6 @@ inherit_event(struct perf_event *parent_event,
raw_spin_unlock_irqrestore(&child_ctx->lock, flags);
/*
- * Get a reference to the parent filp - we will fput it
- * when the child event exits. This is safe to do because
- * we are in the parent and we know that the filp still
- * exists and has a nonzero count:
- */
- atomic_long_inc(&parent_event->filp->f_count);
-
- /*
* Link this into the parent event's child list
*/
WARN_ON_ONCE(parent_event->ctx->parent_ctx);
diff --git a/kernel/exit.c b/kernel/exit.c
index 303bed2..97dd317 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -1049,6 +1049,22 @@ NORET_TYPE void do_exit(long code)
preempt_disable();
exit_rcu();
+
+ /*
+ * The setting of TASK_RUNNING by try_to_wake_up() may be delayed
+ * when the following two conditions become true.
+ * - There is race condition of mmap_sem (It is acquired by
+ * exit_mm()), and
+ * - SMI occurs before setting TASK_RUNINNG.
+ * (or hypervisor of virtual machine switches to other guest)
+ * As a result, we may become TASK_RUNNING after becoming TASK_DEAD
+ *
+ * To avoid it, we have to wait for releasing tsk->pi_lock which
+ * is held by try_to_wake_up()
+ */
+ smp_mb();
+ raw_spin_unlock_wait(&tsk->pi_lock);
+
/* causes final put_task_struct in finish_task_switch(). */
tsk->state = TASK_DEAD;
schedule();
diff --git a/kernel/fork.c b/kernel/fork.c
index 06909a9..158ca4f 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -48,6 +48,7 @@
#include <linux/audit.h>
#include <linux/memcontrol.h>
#include <linux/ftrace.h>
+#include <linux/proc_fs.h>
#include <linux/profile.h>
#include <linux/rmap.h>
#include <linux/ksm.h>
@@ -1000,6 +1001,9 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
#ifdef CONFIG_CGROUPS
init_rwsem(&sig->threadgroup_fork_lock);
#endif
+#ifdef CONFIG_CPUSETS
+ seqcount_init(&tsk->mems_allowed_seq);
+#endif
sig->oom_adj = current->signal->oom_adj;
sig->oom_score_adj = current->signal->oom_score_adj;
@@ -1394,6 +1398,8 @@ bad_fork_cleanup_io:
if (p->io_context)
exit_io_context(p);
bad_fork_cleanup_namespaces:
+ if (unlikely(clone_flags & CLONE_NEWPID))
+ pid_ns_release_proc(p->nsproxy->pid_ns);
exit_task_namespaces(p);
bad_fork_cleanup_mm:
if (p->mm) {
diff --git a/kernel/futex.c b/kernel/futex.c
index b2d51a7..e45efe7 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -2231,11 +2231,11 @@ int handle_early_requeue_pi_wakeup(struct futex_hash_bucket *hb,
* @uaddr2: the pi futex we will take prior to returning to user-space
*
* The caller will wait on uaddr and will be requeued by futex_requeue() to
- * uaddr2 which must be PI aware. Normal wakeup will wake on uaddr2 and
- * complete the acquisition of the rt_mutex prior to returning to userspace.
- * This ensures the rt_mutex maintains an owner when it has waiters; without
- * one, the pi logic wouldn't know which task to boost/deboost, if there was a
- * need to.
+ * uaddr2 which must be PI aware and unique from uaddr. Normal wakeup will wake
+ * on uaddr2 and complete the acquisition of the rt_mutex prior to returning to
+ * userspace. This ensures the rt_mutex maintains an owner when it has waiters;
+ * without one, the pi logic would not know which task to boost/deboost, if
+ * there was a need to.
*
* We call schedule in futex_wait_queue_me() when we enqueue and return there
* via the following:
@@ -2272,6 +2272,9 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
struct futex_q q = futex_q_init;
int res, ret;
+ if (uaddr == uaddr2)
+ return -EINVAL;
+
if (!bitset)
return -EINVAL;
@@ -2343,7 +2346,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
* signal. futex_unlock_pi() will not destroy the lock_ptr nor
* the pi_state.
*/
- WARN_ON(!&q.pi_state);
+ WARN_ON(!q.pi_state);
pi_mutex = &q.pi_state->pi_mutex;
ret = rt_mutex_finish_proxy_lock(pi_mutex, to, &rt_waiter, 1);
debug_rt_mutex_free_waiter(&rt_waiter);
@@ -2370,7 +2373,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
* fault, unlock the rt_mutex and return the fault to userspace.
*/
if (ret == -EFAULT) {
- if (rt_mutex_owner(pi_mutex) == current)
+ if (pi_mutex && rt_mutex_owner(pi_mutex) == current)
rt_mutex_unlock(pi_mutex);
} else if (ret == -EINTR) {
/*
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index 2043c08..957869f 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -657,6 +657,14 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
return 0;
}
+static inline ktime_t hrtimer_update_base(struct hrtimer_cpu_base *base)
+{
+ ktime_t *offs_real = &base->clock_base[HRTIMER_BASE_REALTIME].offset;
+ ktime_t *offs_boot = &base->clock_base[HRTIMER_BASE_BOOTTIME].offset;
+
+ return ktime_get_update_offsets(offs_real, offs_boot);
+}
+
/*
* Retrigger next event is called after clock was set
*
@@ -665,22 +673,12 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
static void retrigger_next_event(void *arg)
{
struct hrtimer_cpu_base *base = &__get_cpu_var(hrtimer_bases);
- struct timespec realtime_offset, xtim, wtm, sleep;
if (!hrtimer_hres_active())
return;
- /* Optimized out for !HIGH_RES */
- get_xtime_and_monotonic_and_sleep_offset(&xtim, &wtm, &sleep);
- set_normalized_timespec(&realtime_offset, -wtm.tv_sec, -wtm.tv_nsec);
-
- /* Adjust CLOCK_REALTIME offset */
raw_spin_lock(&base->lock);
- base->clock_base[HRTIMER_BASE_REALTIME].offset =
- timespec_to_ktime(realtime_offset);
- base->clock_base[HRTIMER_BASE_BOOTTIME].offset =
- timespec_to_ktime(sleep);
-
+ hrtimer_update_base(base);
hrtimer_force_reprogram(base, 0);
raw_spin_unlock(&base->lock);
}
@@ -710,13 +708,25 @@ static int hrtimer_switch_to_hres(void)
base->clock_base[i].resolution = KTIME_HIGH_RES;
tick_setup_sched_timer();
-
/* "Retrigger" the interrupt to get things going */
retrigger_next_event(NULL);
local_irq_restore(flags);
return 1;
}
+/*
+ * Called from timekeeping code to reprogramm the hrtimer interrupt
+ * device. If called from the timer interrupt context we defer it to
+ * softirq context.
+ */
+void clock_was_set_delayed(void)
+{
+ struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
+
+ cpu_base->clock_was_set = 1;
+ __raise_softirq_irqoff(HRTIMER_SOFTIRQ);
+}
+
#else
static inline int hrtimer_hres_active(void) { return 0; }
@@ -1250,11 +1260,10 @@ void hrtimer_interrupt(struct clock_event_device *dev)
cpu_base->nr_events++;
dev->next_event.tv64 = KTIME_MAX;
- entry_time = now = ktime_get();
+ raw_spin_lock(&cpu_base->lock);
+ entry_time = now = hrtimer_update_base(cpu_base);
retry:
expires_next.tv64 = KTIME_MAX;
-
- raw_spin_lock(&cpu_base->lock);
/*
* We set expires_next to KTIME_MAX here with cpu_base->lock
* held to prevent that a timer is enqueued in our queue via
@@ -1330,8 +1339,12 @@ retry:
* We need to prevent that we loop forever in the hrtimer
* interrupt routine. We give it 3 attempts to avoid
* overreacting on some spurious event.
+ *
+ * Acquire base lock for updating the offsets and retrieving
+ * the current time.
*/
- now = ktime_get();
+ raw_spin_lock(&cpu_base->lock);
+ now = hrtimer_update_base(cpu_base);
cpu_base->nr_retries++;
if (++retries < 3)
goto retry;
@@ -1343,6 +1356,7 @@ retry:
*/
cpu_base->nr_hangs++;
cpu_base->hang_detected = 1;
+ raw_spin_unlock(&cpu_base->lock);
delta = ktime_sub(now, entry_time);
if (delta.tv64 > cpu_base->max_hang_time.tv64)
cpu_base->max_hang_time = delta;
@@ -1395,6 +1409,13 @@ void hrtimer_peek_ahead_timers(void)
static void run_hrtimer_softirq(struct softirq_action *h)
{
+ struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
+
+ if (cpu_base->clock_was_set) {
+ cpu_base->clock_was_set = 0;
+ clock_was_set();
+ }
+
hrtimer_peek_ahead_timers();
}
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 990965e..3863523 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -327,8 +327,10 @@ static void cond_unmask_irq(struct irq_desc *desc)
* spurious interrupt or a primary handler handling it
* completely).
*/
- if (!irqd_irq_disabled(&desc->irq_data) &&
- irqd_irq_masked(&desc->irq_data) && !desc->threads_oneshot)
+ // FIXME
+ // if (!irqd_irq_disabled(&desc->irq_data) &&
+ // irqd_irq_masked(&desc->irq_data) && !desc->threads_oneshot)
+ if (!irqd_irq_disabled(&desc->irq_data) && !(desc->istate & IRQS_ONESHOT))
unmask_irq(desc);
}
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index 470d08c..10e0772 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -117,7 +117,7 @@ irqreturn_t
handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action)
{
irqreturn_t retval = IRQ_NONE;
- unsigned int random = 0, irq = desc->irq_data.irq;
+ unsigned int flags = 0, irq = desc->irq_data.irq;
do {
irqreturn_t res;
@@ -145,7 +145,7 @@ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action)
/* Fall through to add to randomness */
case IRQ_HANDLED:
- random |= action->flags;
+ flags |= action->flags;
break;
default:
@@ -156,8 +156,7 @@ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action)
action = action->next;
} while (action);
- if (random & IRQF_SAMPLE_RANDOM)
- add_interrupt_randomness(irq);
+ add_interrupt_randomness(irq, flags);
if (!noirqdebug)
note_interrupt(irq, desc, retval);
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index df8136f..fa4a70e 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -886,22 +886,6 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
if (desc->irq_data.chip == &no_irq_chip)
return -ENOSYS;
- /*
- * Some drivers like serial.c use request_irq() heavily,
- * so we have to be careful not to interfere with a
- * running system.
- */
- if (new->flags & IRQF_SAMPLE_RANDOM) {
- /*
- * This function might sleep, we want to call it first,
- * outside of the atomic block.
- * Yes, this might clear the entropy pool if the wrong
- * driver is attempted to be loaded, without actually
- * installing a new handler, but is this really a problem,
- * only the sysadmin is able to do this.
- */
- rand_initialize_irq(irq);
- }
/*
* Check whether the interrupt nests into another interrupt
@@ -1325,7 +1309,6 @@ EXPORT_SYMBOL(free_irq);
* Flags:
*
* IRQF_SHARED Interrupt is shared
- * IRQF_SAMPLE_RANDOM The interrupt can be used for entropy
* IRQF_TRIGGER_* Specify active edge(s) or level
*
*/
diff --git a/kernel/module.c b/kernel/module.c
index b9d0667..a8bd215 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -2605,6 +2605,10 @@ static int check_module_license_and_versions(struct module *mod)
if (strcmp(mod->name, "driverloader") == 0)
add_taint_module(mod, TAINT_PROPRIETARY_MODULE);
+ /* lve claims to be GPL but upstream won't provide source */
+ if (strcmp(mod->name, "lve") == 0)
+ add_taint_module(mod, TAINT_PROPRIETARY_MODULE);
+
#ifdef CONFIG_MODVERSIONS
if ((mod->num_syms && !mod->crcs)
|| (mod->num_gpl_syms && !mod->gpl_crcs)
diff --git a/kernel/power/earlysuspend.c b/kernel/power/earlysuspend.c
index b15f02e..34af445 100644
--- a/kernel/power/earlysuspend.c
+++ b/kernel/power/earlysuspend.c
@@ -20,9 +20,18 @@
#include <linux/syscalls.h> /* sys_sync */
#include <linux/wakelock.h>
#include <linux/workqueue.h>
-
+#ifdef CONFIG_CPU_DIDLE
+#include <linux/cpufreq.h>
+#include <linux/deep_idle.h>
+#endif
#include "power.h"
+#ifdef CONFIG_CPU_DIDLE
+static unsigned long lMinOldFreq;
+static unsigned long lPolicyMinOldFreq;
+unsigned int uIsSuspended;
+#endif
+
enum {
DEBUG_USER_STATE = 1U << 0,
DEBUG_SUSPEND = 1U << 2,
@@ -156,6 +165,7 @@ void request_suspend_state(suspend_state_t new_state)
spin_lock_irqsave(&state_lock, irqflags);
old_sleep = state & SUSPEND_REQUESTED;
+
if (debug_mask & DEBUG_USER_STATE) {
struct timespec ts;
struct rtc_time tm;
@@ -178,6 +188,34 @@ void request_suspend_state(suspend_state_t new_state)
queue_work(suspend_work_queue, &late_resume_work);
}
requested_suspend_state = new_state;
+#ifdef CONFIG_CPU_DIDLE
+ /* Increases the CPU min speed if we have deepidle enabled and we go into
+ suspend mode. This is fully independent of the governor, so we can add
+ or remove our favourite governor */
+ struct cpufreq_policy *policy;
+
+ if (deepidle_is_enabled()) {
+ policy = cpufreq_cpu_get(0);
+ if ((new_state == PM_SUSPEND_MEM) && (uIsSuspended == 0)) {
+ lMinOldFreq = policy->max;
+ lPolicyMinOldFreq = policy->user_policy.max;
+ policy->user_policy.max = 800000;
+ policy->max = 800000;
+ cpufreq_cpu_put(policy);
+ uIsSuspended = 1;
+ } else {
+ if (lMinOldFreq < 100000) {
+ lMinOldFreq = policy->max;
+ lPolicyMinOldFreq = policy->user_policy.max;
+ uIsSuspended = 0;
+ }
+ policy->max = lMinOldFreq;
+ policy->user_policy.max = lPolicyMinOldFreq;
+ cpufreq_cpu_put(policy);
+ uIsSuspended = 0;
+ }
+ }
+#endif
spin_unlock_irqrestore(&state_lock, irqflags);
}
diff --git a/kernel/power/fbearlysuspend.c b/kernel/power/fbearlysuspend.c
index 1513765..c327311 100644
--- a/kernel/power/fbearlysuspend.c
+++ b/kernel/power/fbearlysuspend.c
@@ -13,6 +13,7 @@
*
*/
+#include <linux/delay.h>
#include <linux/earlysuspend.h>
#include <linux/module.h>
#include <linux/wait.h>
@@ -33,6 +34,8 @@ static void stop_drawing_early_suspend(struct early_suspend *h)
int ret;
unsigned long irq_flags;
+ if(is_device_lcd)
+ msleep(500);
spin_lock_irqsave(&fb_state_lock, irq_flags);
fb_state = FB_STATE_REQUEST_STOP_DRAWING;
spin_unlock_irqrestore(&fb_state_lock, irq_flags);
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index 8884c27..32f1590 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -344,6 +344,7 @@ int hibernation_snapshot(int platform_mode)
goto Complete_devices;
suspend_console();
+ ftrace_stop();
pm_restrict_gfp_mask();
error = dpm_suspend(PMSG_FREEZE);
if (error)
@@ -369,6 +370,7 @@ int hibernation_snapshot(int platform_mode)
if (error || !in_suspend)
pm_restore_gfp_mask();
+ ftrace_start();
resume_console();
Complete_devices:
@@ -471,6 +473,7 @@ int hibernation_restore(int platform_mode)
pm_prepare_console();
suspend_console();
+ ftrace_stop();
pm_restrict_gfp_mask();
error = dpm_suspend_start(PMSG_QUIESCE);
if (!error) {
@@ -478,6 +481,7 @@ int hibernation_restore(int platform_mode)
dpm_resume_end(PMSG_RECOVER);
}
pm_restore_gfp_mask();
+ ftrace_start();
resume_console();
pm_restore_console();
return error;
@@ -504,6 +508,7 @@ int hibernation_platform_enter(void)
entering_platform_hibernation = true;
suspend_console();
+ ftrace_stop();
error = dpm_suspend_start(PMSG_HIBERNATE);
if (error) {
if (hibernation_ops->recover)
@@ -547,6 +552,7 @@ int hibernation_platform_enter(void)
Resume_devices:
entering_platform_hibernation = false;
dpm_resume_end(PMSG_RESTORE);
+ ftrace_start();
resume_console();
Close:
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
index 61e6347..44c78d5 100644
--- a/kernel/power/suspend.c
+++ b/kernel/power/suspend.c
@@ -23,6 +23,7 @@
#include <linux/slab.h>
#include <linux/suspend.h>
#include <linux/syscore_ops.h>
+#include <linux/ftrace.h>
#include <trace/events/power.h>
#include "power.h"
@@ -213,6 +214,7 @@ int suspend_devices_and_enter(suspend_state_t state)
goto Close;
}
suspend_console();
+ ftrace_stop();
suspend_test_start();
error = dpm_suspend_start(PMSG_SUSPEND);
if (error) {
@@ -229,6 +231,7 @@ int suspend_devices_and_enter(suspend_state_t state)
suspend_test_start();
dpm_resume_end(PMSG_RESUME);
suspend_test_finish("resume devices");
+ ftrace_start();
resume_console();
Close:
if (suspend_ops->end)
@@ -315,3 +318,11 @@ int pm_suspend(suspend_state_t state)
return -EINVAL;
}
EXPORT_SYMBOL(pm_suspend);
+
+#ifdef CONFIG_CPU_DIDLE
+bool suspend_ongoing(void)
+{
+ return mutex_is_locked(&pm_mutex);
+}
+EXPORT_SYMBOL(suspend_ongoing);
+#endif
diff --git a/kernel/rcutree.c b/kernel/rcutree.c
index ba06207..fe7a9b0 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -283,7 +283,9 @@ cpu_has_callbacks_ready_to_invoke(struct rcu_data *rdp)
static int
cpu_needs_another_gp(struct rcu_state *rsp, struct rcu_data *rdp)
{
- return *rdp->nxttail[RCU_DONE_TAIL] && !rcu_gp_in_progress(rsp);
+ return *rdp->nxttail[RCU_DONE_TAIL +
+ ACCESS_ONCE(rsp->completed) != rdp->completed] &&
+ !rcu_gp_in_progress(rsp);
}
/*
diff --git a/kernel/sched.c b/kernel/sched.c
index d488880..e788b66 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -606,22 +606,19 @@ static inline int cpu_of(struct rq *rq)
/*
* Return the group to which this tasks belongs.
*
- * We use task_subsys_state_check() and extend the RCU verification with
- * pi->lock and rq->lock because cpu_cgroup_attach() holds those locks for each
- * task it moves into the cgroup. Therefore by holding either of those locks,
- * we pin the task to the current cgroup.
+ * We cannot use task_subsys_state() and friends because the cgroup
+ * subsystem changes that value before the cgroup_subsys::attach() method
+ * is called, therefore we cannot pin it and might observe the wrong value.
+ *
+ * The same is true for autogroup's p->signal->autogroup->tg, the autogroup
+ * core changes this before calling sched_move_task().
+ *
+ * Instead we use a 'copy' which is updated from sched_move_task() while
+ * holding both task_struct::pi_lock and rq::lock.
*/
static inline struct task_group *task_group(struct task_struct *p)
{
- struct task_group *tg;
- struct cgroup_subsys_state *css;
-
- css = task_subsys_state_check(p, cpu_cgroup_subsys_id,
- lockdep_is_held(&p->pi_lock) ||
- lockdep_is_held(&task_rq(p)->lock));
- tg = container_of(css, struct task_group, css);
-
- return autogroup_task_group(p, tg);
+ return p->sched_task_group;
}
/* Change a task's cfs_rq and parent entity if it moves across CPUs/groups */
@@ -2207,7 +2204,7 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
* a task's CPU. ->pi_lock for waking tasks, rq->lock for runnable tasks.
*
* sched_move_task() holds both and thus holding either pins the cgroup,
- * see set_task_rq().
+ * see task_group().
*
* Furthermore, all task_rq users should acquire both locks, see
* task_rq_lock().
@@ -7221,11 +7218,8 @@ int sched_domain_level_max;
static int __init setup_relax_domain_level(char *str)
{
- unsigned long val;
-
- val = simple_strtoul(str, NULL, 0);
- if (val < sched_domain_level_max)
- default_relax_domain_level = val;
+ if (kstrtoint(str, 0, &default_relax_domain_level))
+ pr_warn("Unable to set relax_domain_level\n");
return 1;
}
@@ -7418,7 +7412,6 @@ struct sched_domain *build_sched_domain(struct sched_domain_topology_level *tl,
if (!sd)
return child;
- set_domain_attribute(sd, attr);
cpumask_and(sched_domain_span(sd), cpu_map, tl->mask(cpu));
if (child) {
sd->level = child->level + 1;
@@ -7426,6 +7419,7 @@ struct sched_domain *build_sched_domain(struct sched_domain_topology_level *tl,
child->parent = sd;
}
sd->child = child;
+ set_domain_attribute(sd, attr);
return sd;
}
@@ -7784,34 +7778,66 @@ int __init sched_create_sysfs_power_savings_entries(struct sysdev_class *cls)
}
#endif /* CONFIG_SCHED_MC || CONFIG_SCHED_SMT */
+static int num_cpus_frozen; /* used to mark begin/end of suspend/resume */
+
/*
* Update cpusets according to cpu_active mask. If cpusets are
* disabled, cpuset_update_active_cpus() becomes a simple wrapper
* around partition_sched_domains().
+ *
+ * If we come here as part of a suspend/resume, don't touch cpusets because we
+ * want to restore it back to its original state upon resume anyway.
*/
static int cpuset_cpu_active(struct notifier_block *nfb, unsigned long action,
void *hcpu)
{
- switch (action & ~CPU_TASKS_FROZEN) {
+ switch (action) {
+ case CPU_ONLINE_FROZEN:
+ case CPU_DOWN_FAILED_FROZEN:
+
+ /*
+ * num_cpus_frozen tracks how many CPUs are involved in suspend
+ * resume sequence. As long as this is not the last online
+ * operation in the resume sequence, just build a single sched
+ * domain, ignoring cpusets.
+ */
+ num_cpus_frozen--;
+ if (likely(num_cpus_frozen)) {
+ partition_sched_domains(1, NULL, NULL);
+ break;
+ }
+
+ /*
+ * This is the last CPU online operation. So fall through and
+ * restore the original sched domains by considering the
+ * cpuset configurations.
+ */
+
case CPU_ONLINE:
case CPU_DOWN_FAILED:
cpuset_update_active_cpus();
- return NOTIFY_OK;
+ break;
default:
return NOTIFY_DONE;
}
+ return NOTIFY_OK;
}
static int cpuset_cpu_inactive(struct notifier_block *nfb, unsigned long action,
void *hcpu)
{
- switch (action & ~CPU_TASKS_FROZEN) {
+ switch (action) {
case CPU_DOWN_PREPARE:
cpuset_update_active_cpus();
- return NOTIFY_OK;
+ break;
+ case CPU_DOWN_PREPARE_FROZEN:
+ num_cpus_frozen++;
+ partition_sched_domains(1, NULL, NULL);
+ break;
default:
return NOTIFY_DONE;
}
+ return NOTIFY_OK;
}
static int update_runtime(struct notifier_block *nfb,
@@ -8560,6 +8586,7 @@ void sched_destroy_group(struct task_group *tg)
*/
void sched_move_task(struct task_struct *tsk)
{
+ struct task_group *tg;
int on_rq, running;
unsigned long flags;
struct rq *rq;
@@ -8574,6 +8601,12 @@ void sched_move_task(struct task_struct *tsk)
if (unlikely(running))
tsk->sched_class->put_prev_task(rq, tsk);
+ tg = container_of(task_subsys_state_check(tsk, cpu_cgroup_subsys_id,
+ lockdep_is_held(&tsk->sighand->siglock)),
+ struct task_group, css);
+ tg = autogroup_task_group(tsk, tg);
+ tsk->sched_task_group = tg;
+
#ifdef CONFIG_FAIR_GROUP_SCHED
if (tsk->sched_class->task_move_group)
tsk->sched_class->task_move_group(tsk, on_rq);
diff --git a/kernel/sys.c b/kernel/sys.c
index f88dadc..84e353b 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -334,6 +334,7 @@ void kernel_restart_prepare(char *cmd)
void kernel_restart(char *cmd)
{
kernel_restart_prepare(cmd);
+ disable_nonboot_cpus();
if (!cmd)
printk(KERN_EMERG "Restarting system.\n");
else
@@ -1132,15 +1133,16 @@ DECLARE_RWSEM(uts_sem);
* Work around broken programs that cannot handle "Linux 3.0".
* Instead we map 3.x to 2.6.40+x, so e.g. 3.0 would be 2.6.40
*/
-static int override_release(char __user *release, int len)
+static int override_release(char __user *release, size_t len)
{
int ret = 0;
- char buf[65];
if (current->personality & UNAME26) {
- char *rest = UTS_RELEASE;
+ const char *rest = UTS_RELEASE;
+ char buf[65] = { 0 };
int ndots = 0;
unsigned v;
+ size_t copy;
while (*rest) {
if (*rest == '.' && ++ndots >= 3)
@@ -1150,8 +1152,9 @@ static int override_release(char __user *release, int len)
rest++;
}
v = ((LINUX_VERSION_CODE >> 8) & 0xff) + 40;
- snprintf(buf, len, "2.6.%u%s", v, rest);
- ret = copy_to_user(release, buf, len);
+ copy = clamp_t(size_t, len, 1, sizeof(buf));
+ copy = scnprintf(buf, copy, "2.6.%u%s", v, rest);
+ ret = copy_to_user(release, buf, copy + 1);
}
return ret;
}
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index 4b85a7a..61fc450 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -31,8 +31,6 @@ unsigned long tick_nsec;
u64 tick_length;
static u64 tick_length_base;
-static struct hrtimer leap_timer;
-
#define MAX_TICKADJ 500LL /* usecs */
#define MAX_TICKADJ_SCALED \
(((MAX_TICKADJ * NSEC_PER_USEC) << NTP_SCALE_SHIFT) / NTP_INTERVAL_FREQ)
@@ -350,60 +348,64 @@ void ntp_clear(void)
}
/*
- * Leap second processing. If in leap-insert state at the end of the
- * day, the system clock is set back one second; if in leap-delete
- * state, the system clock is set ahead one second.
+ * this routine handles the overflow of the microsecond field
+ *
+ * The tricky bits of code to handle the accurate clock support
+ * were provided by Dave Mills (Mills@UDEL.EDU) of NTP fame.
+ * They were originally developed for SUN and DEC kernels.
+ * All the kudos should go to Dave for this stuff.
+ *
+ * Also handles leap second processing, and returns leap offset
*/
-static enum hrtimer_restart ntp_leap_second(struct hrtimer *timer)
+int second_overflow(unsigned long secs)
{
- enum hrtimer_restart res = HRTIMER_NORESTART;
-
- write_seqlock(&xtime_lock);
+ int leap = 0;
+ s64 delta;
+ /*
+ * Leap second processing. If in leap-insert state at the end of the
+ * day, the system clock is set back one second; if in leap-delete
+ * state, the system clock is set ahead one second.
+ */
switch (time_state) {
case TIME_OK:
+ if (time_status & STA_INS)
+ time_state = TIME_INS;
+ else if (time_status & STA_DEL)
+ time_state = TIME_DEL;
break;
case TIME_INS:
- timekeeping_leap_insert(-1);
- time_state = TIME_OOP;
- printk(KERN_NOTICE
- "Clock: inserting leap second 23:59:60 UTC\n");
- hrtimer_add_expires_ns(&leap_timer, NSEC_PER_SEC);
- res = HRTIMER_RESTART;
+ if (!(time_status & STA_INS))
+ time_state = TIME_OK;
+ else if (secs % 86400 == 0) {
+ leap = -1;
+ time_state = TIME_OOP;
+ time_tai++;
+ printk(KERN_NOTICE
+ "Clock: inserting leap second 23:59:60 UTC\n");
+ }
break;
case TIME_DEL:
- timekeeping_leap_insert(1);
- time_tai--;
- time_state = TIME_WAIT;
- printk(KERN_NOTICE
- "Clock: deleting leap second 23:59:59 UTC\n");
+ if (!(time_status & STA_DEL))
+ time_state = TIME_OK;
+ else if ((secs + 1) % 86400 == 0) {
+ leap = 1;
+ time_tai--;
+ time_state = TIME_WAIT;
+ printk(KERN_NOTICE
+ "Clock: deleting leap second 23:59:59 UTC\n");
+ }
break;
case TIME_OOP:
- time_tai++;
time_state = TIME_WAIT;
- /* fall through */
+ break;
+
case TIME_WAIT:
if (!(time_status & (STA_INS | STA_DEL)))
time_state = TIME_OK;
break;
}
- write_sequnlock(&xtime_lock);
-
- return res;
-}
-
-/*
- * this routine handles the overflow of the microsecond field
- *
- * The tricky bits of code to handle the accurate clock support
- * were provided by Dave Mills (Mills@UDEL.EDU) of NTP fame.
- * They were originally developed for SUN and DEC kernels.
- * All the kudos should go to Dave for this stuff.
- */
-void second_overflow(void)
-{
- s64 delta;
/* Bump the maxerror field */
time_maxerror += MAXFREQ / NSEC_PER_USEC;
@@ -423,23 +425,25 @@ void second_overflow(void)
pps_dec_valid();
if (!time_adjust)
- return;
+ goto out;
if (time_adjust > MAX_TICKADJ) {
time_adjust -= MAX_TICKADJ;
tick_length += MAX_TICKADJ_SCALED;
- return;
+ goto out;
}
if (time_adjust < -MAX_TICKADJ) {
time_adjust += MAX_TICKADJ;
tick_length -= MAX_TICKADJ_SCALED;
- return;
+ goto out;
}
tick_length += (s64)(time_adjust * NSEC_PER_USEC / NTP_INTERVAL_FREQ)
<< NTP_SCALE_SHIFT;
time_adjust = 0;
+out:
+ return leap;
}
#ifdef CONFIG_GENERIC_CMOS_UPDATE
@@ -501,27 +505,6 @@ static void notify_cmos_timer(void)
static inline void notify_cmos_timer(void) { }
#endif
-/*
- * Start the leap seconds timer:
- */
-static inline void ntp_start_leap_timer(struct timespec *ts)
-{
- long now = ts->tv_sec;
-
- if (time_status & STA_INS) {
- time_state = TIME_INS;
- now += 86400 - now % 86400;
- hrtimer_start(&leap_timer, ktime_set(now, 0), HRTIMER_MODE_ABS);
-
- return;
- }
-
- if (time_status & STA_DEL) {
- time_state = TIME_DEL;
- now += 86400 - (now + 1) % 86400;
- hrtimer_start(&leap_timer, ktime_set(now, 0), HRTIMER_MODE_ABS);
- }
-}
/*
* Propagate a new txc->status value into the NTP state:
@@ -546,22 +529,6 @@ static inline void process_adj_status(struct timex *txc, struct timespec *ts)
time_status &= STA_RONLY;
time_status |= txc->status & ~STA_RONLY;
- switch (time_state) {
- case TIME_OK:
- ntp_start_leap_timer(ts);
- break;
- case TIME_INS:
- case TIME_DEL:
- time_state = TIME_OK;
- ntp_start_leap_timer(ts);
- case TIME_WAIT:
- if (!(time_status & (STA_INS | STA_DEL)))
- time_state = TIME_OK;
- break;
- case TIME_OOP:
- hrtimer_restart(&leap_timer);
- break;
- }
}
/*
* Called with the xtime lock held, so we can access and modify
@@ -643,9 +610,6 @@ int do_adjtimex(struct timex *txc)
(txc->tick < 900000/USER_HZ ||
txc->tick > 1100000/USER_HZ))
return -EINVAL;
-
- if (txc->modes & ADJ_STATUS && time_state != TIME_OK)
- hrtimer_cancel(&leap_timer);
}
if (txc->modes & ADJ_SETOFFSET) {
@@ -967,6 +931,4 @@ __setup("ntp_tick_adj=", ntp_tick_adj_setup);
void __init ntp_init(void)
{
ntp_clear();
- hrtimer_init(&leap_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
- leap_timer.function = ntp_leap_second;
}
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 06a5f31..343ab2a 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -161,23 +161,43 @@ static struct timespec xtime __attribute__ ((aligned (16)));
static struct timespec wall_to_monotonic __attribute__ ((aligned (16)));
static struct timespec total_sleep_time;
+/* Offset clock monotonic -> clock realtime */
+static ktime_t offs_real;
+
+/* Offset clock monotonic -> clock boottime */
+static ktime_t offs_boot;
+
/*
* The raw monotonic time for the CLOCK_MONOTONIC_RAW posix clock.
*/
static struct timespec raw_time;
-/* flag for if timekeeping is suspended */
-int __read_mostly timekeeping_suspended;
+/* must hold write on xtime_lock */
+static void update_rt_offset(void)
+{
+ struct timespec tmp, *wtm = &wall_to_monotonic;
+
+ set_normalized_timespec(&tmp, -wtm->tv_sec, -wtm->tv_nsec);
+ offs_real = timespec_to_ktime(tmp);
+}
-/* must hold xtime_lock */
-void timekeeping_leap_insert(int leapsecond)
+/* must hold write on xtime_lock */
+static void timekeeping_update(bool clearntp)
{
- xtime.tv_sec += leapsecond;
- wall_to_monotonic.tv_sec -= leapsecond;
- update_vsyscall(&xtime, &wall_to_monotonic, timekeeper.clock,
- timekeeper.mult);
+ if (clearntp) {
+ timekeeper.ntp_error = 0;
+ ntp_clear();
+ }
+ update_rt_offset();
+ update_vsyscall(&xtime, &wall_to_monotonic,
+ timekeeper.clock, timekeeper.mult);
}
+
+
+/* flag for if timekeeping is suspended */
+int __read_mostly timekeeping_suspended;
+
/**
* timekeeping_forward_now - update clock to the current time
*
@@ -362,7 +382,7 @@ int do_settimeofday(const struct timespec *tv)
struct timespec ts_delta;
unsigned long flags;
- if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
+ if (!timespec_valid_strict(tv))
return -EINVAL;
write_seqlock_irqsave(&xtime_lock, flags);
@@ -375,11 +395,7 @@ int do_settimeofday(const struct timespec *tv)
xtime = *tv;
- timekeeper.ntp_error = 0;
- ntp_clear();
-
- update_vsyscall(&xtime, &wall_to_monotonic, timekeeper.clock,
- timekeeper.mult);
+ timekeeping_update(true);
write_sequnlock_irqrestore(&xtime_lock, flags);
@@ -401,6 +417,8 @@ EXPORT_SYMBOL(do_settimeofday);
int timekeeping_inject_offset(struct timespec *ts)
{
unsigned long flags;
+ struct timespec tmp;
+ int ret = 0;
if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC)
return -EINVAL;
@@ -409,21 +427,24 @@ int timekeeping_inject_offset(struct timespec *ts)
timekeeping_forward_now();
+ tmp = timespec_add(xtime, *ts);
+ if (!timespec_valid_strict(&tmp)) {
+ ret = -EINVAL;
+ goto error;
+ }
+
xtime = timespec_add(xtime, *ts);
wall_to_monotonic = timespec_sub(wall_to_monotonic, *ts);
- timekeeper.ntp_error = 0;
- ntp_clear();
-
- update_vsyscall(&xtime, &wall_to_monotonic, timekeeper.clock,
- timekeeper.mult);
+error: /* even if we error out, we forwarded the time, so call update */
+ timekeeping_update(true);
write_sequnlock_irqrestore(&xtime_lock, flags);
/* signal hrtimers about time change */
clock_was_set();
- return 0;
+ return ret;
}
EXPORT_SYMBOL(timekeeping_inject_offset);
@@ -570,7 +591,20 @@ void __init timekeeping_init(void)
struct timespec now, boot;
read_persistent_clock(&now);
+ if (!timespec_valid_strict(&now)) {
+ pr_warn("WARNING: Persistent clock returned invalid value!\n"
+ " Check your CMOS/BIOS settings.\n");
+ now.tv_sec = 0;
+ now.tv_nsec = 0;
+ }
+
read_boot_clock(&boot);
+ if (!timespec_valid_strict(&boot)) {
+ pr_warn("WARNING: Boot clock returned invalid value!\n"
+ " Check your CMOS/BIOS settings.\n");
+ boot.tv_sec = 0;
+ boot.tv_nsec = 0;
+ }
write_seqlock_irqsave(&xtime_lock, flags);
@@ -591,6 +625,7 @@ void __init timekeeping_init(void)
}
set_normalized_timespec(&wall_to_monotonic,
-boot.tv_sec, -boot.tv_nsec);
+ update_rt_offset();
total_sleep_time.tv_sec = 0;
total_sleep_time.tv_nsec = 0;
write_sequnlock_irqrestore(&xtime_lock, flags);
@@ -599,6 +634,12 @@ void __init timekeeping_init(void)
/* time in seconds when suspend began */
static struct timespec timekeeping_suspend_time;
+static void update_sleep_time(struct timespec t)
+{
+ total_sleep_time = t;
+ offs_boot = timespec_to_ktime(t);
+}
+
/**
* __timekeeping_inject_sleeptime - Internal function to add sleep interval
* @delta: pointer to a timespec delta value
@@ -616,7 +657,7 @@ static void __timekeeping_inject_sleeptime(struct timespec *delta)
xtime = timespec_add(xtime, *delta);
wall_to_monotonic = timespec_sub(wall_to_monotonic, *delta);
- total_sleep_time = timespec_add(total_sleep_time, *delta);
+ update_sleep_time(timespec_add(total_sleep_time, *delta));
}
@@ -645,10 +686,7 @@ void timekeeping_inject_sleeptime(struct timespec *delta)
__timekeeping_inject_sleeptime(delta);
- timekeeper.ntp_error = 0;
- ntp_clear();
- update_vsyscall(&xtime, &wall_to_monotonic, timekeeper.clock,
- timekeeper.mult);
+ timekeeping_update(true);
write_sequnlock_irqrestore(&xtime_lock, flags);
@@ -683,6 +721,7 @@ static void timekeeping_resume(void)
timekeeper.clock->cycle_last = timekeeper.clock->read(timekeeper.clock);
timekeeper.ntp_error = 0;
timekeeping_suspended = 0;
+ timekeeping_update(false);
write_sequnlock_irqrestore(&xtime_lock, flags);
touch_softlockup_watchdog();
@@ -834,9 +873,14 @@ static cycle_t logarithmic_accumulation(cycle_t offset, int shift)
timekeeper.xtime_nsec += timekeeper.xtime_interval << shift;
while (timekeeper.xtime_nsec >= nsecps) {
+ int leap;
timekeeper.xtime_nsec -= nsecps;
xtime.tv_sec++;
- second_overflow();
+ leap = second_overflow(xtime.tv_sec);
+ xtime.tv_sec += leap;
+ wall_to_monotonic.tv_sec -= leap;
+ if (leap)
+ clock_was_set_delayed();
}
/* Accumulate raw time */
@@ -881,6 +925,10 @@ static void update_wall_time(void)
#else
offset = (clock->read(clock) - clock->cycle_last) & clock->mask;
#endif
+ /* Check if there's really nothing to do */
+ if (offset < timekeeper.cycle_interval)
+ return;
+
timekeeper.xtime_nsec = (s64)xtime.tv_nsec << timekeeper.shift;
/*
@@ -942,14 +990,17 @@ static void update_wall_time(void)
* xtime.tv_nsec isn't larger then NSEC_PER_SEC
*/
if (unlikely(xtime.tv_nsec >= NSEC_PER_SEC)) {
+ int leap;
xtime.tv_nsec -= NSEC_PER_SEC;
xtime.tv_sec++;
- second_overflow();
+ leap = second_overflow(xtime.tv_sec);
+ xtime.tv_sec += leap;
+ wall_to_monotonic.tv_sec -= leap;
+ if (leap)
+ clock_was_set_delayed();
}
- /* check to see if there is a new clocksource to use */
- update_vsyscall(&xtime, &wall_to_monotonic, timekeeper.clock,
- timekeeper.mult);
+ timekeeping_update(false);
}
/**
@@ -1108,6 +1159,40 @@ void get_xtime_and_monotonic_and_sleep_offset(struct timespec *xtim,
} while (read_seqretry(&xtime_lock, seq));
}
+#ifdef CONFIG_HIGH_RES_TIMERS
+/**
+ * ktime_get_update_offsets - hrtimer helper
+ * @real: pointer to storage for monotonic -> realtime offset
+ * @_boot: pointer to storage for monotonic -> boottime offset
+ *
+ * Returns current monotonic time and updates the offsets
+ * Called from hrtimer_interupt() or retrigger_next_event()
+ */
+ktime_t ktime_get_update_offsets(ktime_t *real, ktime_t *boot)
+{
+ ktime_t now;
+ unsigned int seq;
+ u64 secs, nsecs;
+
+ do {
+ seq = read_seqbegin(&xtime_lock);
+
+ secs = xtime.tv_sec;
+ nsecs = xtime.tv_nsec;
+ nsecs += timekeeping_get_ns();
+ /* If arch requires, add in gettimeoffset() */
+ nsecs += arch_gettimeoffset();
+
+ *real = offs_real;
+ *boot = offs_boot;
+ } while (read_seqretry(&xtime_lock, seq));
+
+ now = ktime_add_ns(ktime_set(secs, 0), nsecs);
+ now = ktime_sub(now, *real);
+ return now;
+}
+#endif
+
/**
* ktime_get_monotonic_offset() - get wall_to_monotonic in ktime_t format
*/
diff --git a/kernel/timer.c b/kernel/timer.c
index 8cff361..27982d9 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -63,6 +63,7 @@ EXPORT_SYMBOL(jiffies_64);
#define TVR_SIZE (1 << TVR_BITS)
#define TVN_MASK (TVN_SIZE - 1)
#define TVR_MASK (TVR_SIZE - 1)
+#define MAX_TVAL ((unsigned long)((1ULL << (TVR_BITS + 4*TVN_BITS)) - 1))
struct tvec {
struct list_head vec[TVN_SIZE];
@@ -356,11 +357,12 @@ static void internal_add_timer(struct tvec_base *base, struct timer_list *timer)
vec = base->tv1.vec + (base->timer_jiffies & TVR_MASK);
} else {
int i;
- /* If the timeout is larger than 0xffffffff on 64-bit
- * architectures then we use the maximum timeout:
+ /* If the timeout is larger than MAX_TVAL (on 64-bit
+ * architectures or with CONFIG_BASE_SMALL=1) then we
+ * use the maximum timeout.
*/
- if (idx > 0xffffffffUL) {
- idx = 0xffffffffUL;
+ if (idx > MAX_TVAL) {
+ idx = MAX_TVAL;
expires = idx + base->timer_jiffies;
}
i = (expires >> (TVR_BITS + 3 * TVN_BITS)) & TVN_MASK;
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 0731e81a..672a749 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -2432,10 +2432,12 @@ tracing_cpumask_write(struct file *filp, const char __user *ubuf,
if (cpumask_test_cpu(cpu, tracing_cpumask) &&
!cpumask_test_cpu(cpu, tracing_cpumask_new)) {
atomic_inc(&global_trace.data[cpu]->disabled);
+ ring_buffer_record_disable_cpu(global_trace.buffer, cpu);
}
if (!cpumask_test_cpu(cpu, tracing_cpumask) &&
cpumask_test_cpu(cpu, tracing_cpumask_new)) {
atomic_dec(&global_trace.data[cpu]->disabled);
+ ring_buffer_record_enable_cpu(global_trace.buffer, cpu);
}
}
arch_spin_unlock(&ftrace_max_lock);
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 1456dab..aef9452 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -1214,8 +1214,13 @@ static void worker_enter_idle(struct worker *worker)
} else
wake_up_all(&gcwq->trustee_wait);
- /* sanity check nr_running */
- WARN_ON_ONCE(gcwq->nr_workers == gcwq->nr_idle &&
+ /*
+ * Sanity check nr_running. Because trustee releases gcwq->lock
+ * between setting %WORKER_ROGUE and zapping nr_running, the
+ * warning may trigger spuriously. Check iff trustee is idle.
+ */
+ WARN_ON_ONCE(gcwq->trustee_state == TRUSTEE_DONE &&
+ gcwq->nr_workers == gcwq->nr_idle &&
atomic_read(get_gcwq_nr_running(gcwq->cpu)));
}
@@ -1863,7 +1868,9 @@ __acquires(&gcwq->lock)
spin_unlock_irq(&gcwq->lock);
+ smp_wmb(); /* paired with test_and_set_bit(PENDING) */
work_clear_pending(work);
+
lock_map_acquire_read(&cwq->wq->lockdep_map);
lock_map_acquire(&lockdep_map);
trace_workqueue_execute_start(work);
@@ -3407,14 +3414,17 @@ static int __cpuinit trustee_thread(void *__gcwq)
for_each_busy_worker(worker, i, pos, gcwq) {
struct work_struct *rebind_work = &worker->rebind_work;
+ unsigned long worker_flags = worker->flags;
/*
* Rebind_work may race with future cpu hotplug
* operations. Use a separate flag to mark that
- * rebinding is scheduled.
+ * rebinding is scheduled. The morphing should
+ * be atomic.
*/
- worker->flags |= WORKER_REBIND;
- worker->flags &= ~WORKER_ROGUE;
+ worker_flags |= WORKER_REBIND;
+ worker_flags &= ~WORKER_ROGUE;
+ ACCESS_ONCE(worker->flags) = worker_flags;
/* queue rebind_work, wq doesn't matter, use the default one */
if (test_and_set_bit(WORK_STRUCT_PENDING_BIT,
@@ -3556,21 +3566,55 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
return notifier_from_errno(0);
}
+/*
+ * Workqueues should be brought up before normal priority CPU notifiers.
+ * This will be registered high priority CPU notifier.
+ */
+static int __devinit workqueue_cpu_up_callback(struct notifier_block *nfb,
+ unsigned long action,
+ void *hcpu)
+{
+ switch (action & ~CPU_TASKS_FROZEN) {
+ case CPU_UP_PREPARE:
+ case CPU_UP_CANCELED:
+ case CPU_DOWN_FAILED:
+ case CPU_ONLINE:
+ return workqueue_cpu_callback(nfb, action, hcpu);
+ }
+ return NOTIFY_OK;
+}
+
+/*
+ * Workqueues should be brought down after normal priority CPU notifiers.
+ * This will be registered as low priority CPU notifier.
+ */
+static int __devinit workqueue_cpu_down_callback(struct notifier_block *nfb,
+ unsigned long action,
+ void *hcpu)
+{
+ switch (action & ~CPU_TASKS_FROZEN) {
+ case CPU_DOWN_PREPARE:
+ case CPU_DYING:
+ case CPU_POST_DEAD:
+ return workqueue_cpu_callback(nfb, action, hcpu);
+ }
+ return NOTIFY_OK;
+}
+
#ifdef CONFIG_SMP
struct work_for_cpu {
- struct completion completion;
+ struct work_struct work;
long (*fn)(void *);
void *arg;
long ret;
};
-static int do_work_for_cpu(void *_wfc)
+static void work_for_cpu_fn(struct work_struct *work)
{
- struct work_for_cpu *wfc = _wfc;
+ struct work_for_cpu *wfc = container_of(work, struct work_for_cpu, work);
+
wfc->ret = wfc->fn(wfc->arg);
- complete(&wfc->completion);
- return 0;
}
/**
@@ -3585,19 +3629,11 @@ static int do_work_for_cpu(void *_wfc)
*/
long work_on_cpu(unsigned int cpu, long (*fn)(void *), void *arg)
{
- struct task_struct *sub_thread;
- struct work_for_cpu wfc = {
- .completion = COMPLETION_INITIALIZER_ONSTACK(wfc.completion),
- .fn = fn,
- .arg = arg,
- };
+ struct work_for_cpu wfc = { .fn = fn, .arg = arg };
- sub_thread = kthread_create(do_work_for_cpu, &wfc, "work_for_cpu");
- if (IS_ERR(sub_thread))
- return PTR_ERR(sub_thread);
- kthread_bind(sub_thread, cpu);
- wake_up_process(sub_thread);
- wait_for_completion(&wfc.completion);
+ INIT_WORK_ONSTACK(&wfc.work, work_for_cpu_fn);
+ schedule_work_on(cpu, &wfc.work);
+ flush_work(&wfc.work);
return wfc.ret;
}
EXPORT_SYMBOL_GPL(work_on_cpu);
@@ -3749,7 +3785,8 @@ static int __init init_workqueues(void)
unsigned int cpu;
int i;
- cpu_notifier(workqueue_cpu_callback, CPU_PRI_WORKQUEUE);
+ cpu_notifier(workqueue_cpu_up_callback, CPU_PRI_WORKQUEUE_UP);
+ cpu_notifier(workqueue_cpu_down_callback, CPU_PRI_WORKQUEUE_DOWN);
/* initialize gcwqs */
for_each_gcwq_cpu(cpu) {
diff --git a/lib/btree.c b/lib/btree.c
index 2a34392..297124d 100644
--- a/lib/btree.c
+++ b/lib/btree.c
@@ -319,8 +319,8 @@ void *btree_get_prev(struct btree_head *head, struct btree_geo *geo,
if (head->height == 0)
return NULL;
-retry:
longcpy(key, __key, geo->keylen);
+retry:
dec_key(geo, key);
node = head->node;
@@ -351,7 +351,7 @@ retry:
}
miss:
if (retry_key) {
- __key = retry_key;
+ longcpy(key, retry_key, geo->keylen);
retry_key = NULL;
goto retry;
}
diff --git a/lib/gcd.c b/lib/gcd.c
index f879033..433d89b 100644
--- a/lib/gcd.c
+++ b/lib/gcd.c
@@ -9,6 +9,9 @@ unsigned long gcd(unsigned long a, unsigned long b)
if (a < b)
swap(a, b);
+
+ if (!b)
+ return a;
while ((r = a % b) != 0) {
a = b;
b = r;
diff --git a/lib/genalloc.c b/lib/genalloc.c
index 577ddf8..cbb294c 100644
--- a/lib/genalloc.c
+++ b/lib/genalloc.c
@@ -57,7 +57,7 @@ int gen_pool_add_virt(struct gen_pool *pool, unsigned long virt, phys_addr_t phy
struct gen_pool_chunk *chunk;
int nbits = size >> pool->min_alloc_order;
int nbytes = sizeof(struct gen_pool_chunk) +
- (nbits + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
+ BITS_TO_LONGS(nbits) * sizeof(long);
chunk = kmalloc_node(nbytes, GFP_KERNEL | __GFP_ZERO, nid);
if (unlikely(chunk == NULL))
diff --git a/lib/xz/xz_dec_stream.c b/lib/xz/xz_dec_stream.c
index ac809b1..9a60cc2 100644
--- a/lib/xz/xz_dec_stream.c
+++ b/lib/xz/xz_dec_stream.c
@@ -9,6 +9,7 @@
#include "xz_private.h"
#include "xz_stream.h"
+#include <linux/kernel.h>
/* Hash used to validate the Index field */
struct xz_dec_hash {
diff --git a/mm/compaction.c b/mm/compaction.c
index c4bc5ac..88d55f4 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -35,10 +35,6 @@ struct compact_control {
unsigned long migrate_pfn; /* isolate_migratepages search base */
bool sync; /* Synchronous migration */
- /* Account for isolated anon and file pages */
- unsigned long nr_anon;
- unsigned long nr_file;
-
unsigned int order; /* order a direct compactor needs */
int migratetype; /* MOVABLE, RECLAIMABLE etc */
struct zone *zone;
@@ -85,6 +81,11 @@ static unsigned long isolate_freepages_block(struct zone *zone,
if (!pfn_valid_within(blockpfn))
continue;
+
+ /* Watch for unexpected holes punched in the memmap */
+ if (!memmap_valid_within(blockpfn, page, zone))
+ continue;
+
nr_scanned++;
if (!PageBuddy(page))
@@ -179,6 +180,11 @@ static void isolate_freepages(struct zone *zone,
* pages do not belong to a single zone.
*/
page = pfn_to_page(pfn);
+
+ /* Watch for unexpected holes punched in the memmap */
+ if (!memmap_valid_within(pfn, page, zone))
+ continue;
+
if (page_zone(page) != zone)
continue;
@@ -223,17 +229,13 @@ static void isolate_freepages(struct zone *zone,
static void acct_isolated(struct zone *zone, struct compact_control *cc)
{
struct page *page;
- unsigned int count[NR_LRU_LISTS] = { 0, };
+ unsigned int count[2] = { 0, };
- list_for_each_entry(page, &cc->migratepages, lru) {
- int lru = page_lru_base_type(page);
- count[lru]++;
- }
+ list_for_each_entry(page, &cc->migratepages, lru)
+ count[!!page_is_file_cache(page)]++;
- cc->nr_anon = count[LRU_ACTIVE_ANON] + count[LRU_INACTIVE_ANON];
- cc->nr_file = count[LRU_ACTIVE_FILE] + count[LRU_INACTIVE_FILE];
- __mod_zone_page_state(zone, NR_ISOLATED_ANON, cc->nr_anon);
- __mod_zone_page_state(zone, NR_ISOLATED_FILE, cc->nr_file);
+ __mod_zone_page_state(zone, NR_ISOLATED_ANON, count[0]);
+ __mod_zone_page_state(zone, NR_ISOLATED_FILE, count[1]);
}
/* Similar to reclaim, but different enough that they don't share logic */
@@ -269,6 +271,7 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone,
unsigned long last_pageblock_nr = 0, pageblock_nr;
unsigned long nr_scanned = 0, nr_isolated = 0;
struct list_head *migratelist = &cc->migratepages;
+ isolate_mode_t mode = ISOLATE_ACTIVE|ISOLATE_INACTIVE;
/* Do not scan outside zone boundaries */
low_pfn = max(cc->migrate_pfn, zone->zone_start_pfn);
@@ -344,6 +347,11 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone,
* as memory compaction should not move pages between nodes.
*/
page = pfn_to_page(low_pfn);
+
+ /* Watch for unexpected holes punched in the memmap */
+ if (!memmap_valid_within(low_pfn, page, zone))
+ continue;
+
if (page_zone(page) != zone)
continue;
@@ -378,8 +386,11 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone,
continue;
}
+ if (!cc->sync)
+ mode |= ISOLATE_ASYNC_MIGRATE;
+
/* Try isolate the page */
- if (__isolate_lru_page(page, ISOLATE_BOTH, 0) != 0)
+ if (__isolate_lru_page(page, mode, 0) != 0)
continue;
VM_BUG_ON(PageTransCompound(page));
@@ -581,7 +592,7 @@ static int compact_zone(struct zone *zone, struct compact_control *cc)
nr_migrate = cc->nr_migratepages;
err = migrate_pages(&cc->migratepages, compaction_alloc,
(unsigned long)cc, false,
- cc->sync);
+ cc->sync ? MIGRATE_SYNC_LIGHT : MIGRATE_ASYNC);
update_nr_listpages(cc);
nr_remaining = cc->nr_migratepages;
@@ -596,8 +607,11 @@ static int compact_zone(struct zone *zone, struct compact_control *cc)
if (err) {
putback_lru_pages(&cc->migratepages);
cc->nr_migratepages = 0;
+ if (err == -ENOMEM) {
+ ret = COMPACT_PARTIAL;
+ goto out;
+ }
}
-
}
out:
diff --git a/mm/filemap.c b/mm/filemap.c
index b7d8603..10481eb 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -516,10 +516,13 @@ struct page *__page_cache_alloc(gfp_t gfp)
struct page *page;
if (cpuset_do_page_mem_spread()) {
- get_mems_allowed();
- n = cpuset_mem_spread_node();
- page = alloc_pages_exact_node(n, gfp, 0);
- put_mems_allowed();
+ unsigned int cpuset_mems_cookie;
+ do {
+ cpuset_mems_cookie = get_mems_allowed();
+ n = cpuset_mem_spread_node();
+ page = alloc_pages_exact_node(n, gfp, 0);
+ } while (!put_mems_allowed(cpuset_mems_cookie) && !page);
+
return page;
}
return alloc_pages(gfp, 0);
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index f7001ac..037f077 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -460,8 +460,10 @@ static struct page *dequeue_huge_page_vma(struct hstate *h,
struct zonelist *zonelist;
struct zone *zone;
struct zoneref *z;
+ unsigned int cpuset_mems_cookie;
- get_mems_allowed();
+retry_cpuset:
+ cpuset_mems_cookie = get_mems_allowed();
zonelist = huge_zonelist(vma, address,
htlb_alloc_mask, &mpol, &nodemask);
/*
@@ -488,10 +490,15 @@ static struct page *dequeue_huge_page_vma(struct hstate *h,
}
}
}
-err:
+
mpol_cond_put(mpol);
- put_mems_allowed();
+ if (unlikely(!put_mems_allowed(cpuset_mems_cookie) && !page))
+ goto retry_cpuset;
return page;
+
+err:
+ mpol_cond_put(mpol);
+ return NULL;
}
static void update_and_free_page(struct hstate *h, struct page *page)
@@ -2060,6 +2067,15 @@ static void hugetlb_vm_op_open(struct vm_area_struct *vma)
kref_get(&reservations->refs);
}
+static void resv_map_put(struct vm_area_struct *vma)
+{
+ struct resv_map *reservations = vma_resv_map(vma);
+
+ if (!reservations)
+ return;
+ kref_put(&reservations->refs, resv_map_release);
+}
+
static void hugetlb_vm_op_close(struct vm_area_struct *vma)
{
struct hstate *h = hstate_vma(vma);
@@ -2075,7 +2091,7 @@ static void hugetlb_vm_op_close(struct vm_area_struct *vma)
reserve = (end - start) -
region_count(&reservations->regions, start, end);
- kref_put(&reservations->refs, resv_map_release);
+ resv_map_put(vma);
if (reserve) {
hugetlb_acct_memory(h, -reserve);
@@ -2285,6 +2301,22 @@ void unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start,
{
mutex_lock(&vma->vm_file->f_mapping->i_mmap_mutex);
__unmap_hugepage_range(vma, start, end, ref_page);
+ /*
+ * Clear this flag so that x86's huge_pmd_share page_table_shareable
+ * test will fail on a vma being torn down, and not grab a page table
+ * on its way out. We're lucky that the flag has such an appropriate
+ * name, and can in fact be safely cleared here. We could clear it
+ * before the __unmap_hugepage_range above, but all that's necessary
+ * is to clear it before releasing the i_mmap_mutex below.
+ *
+ * This works because in the contexts this is called, the VMA is
+ * going to be destroyed. It is not vunerable to madvise(DONTNEED)
+ * because madvise is not supported on hugetlbfs. The same applies
+ * for direct IO. unmap_hugepage_range() is only being called just
+ * before free_pgtables() so clearing VM_MAYSHARE will not cause
+ * surprises later.
+ */
+ vma->vm_flags &= ~VM_MAYSHARE;
mutex_unlock(&vma->vm_file->f_mapping->i_mmap_mutex);
}
@@ -2398,7 +2430,6 @@ retry_avoidcopy:
if (outside_reserve) {
BUG_ON(huge_pte_none(pte));
if (unmap_ref_private(mm, vma, old_page, address)) {
- BUG_ON(page_count(old_page) != 1);
BUG_ON(huge_pte_none(pte));
spin_lock(&mm->page_table_lock);
goto retry_avoidcopy;
@@ -2838,9 +2869,14 @@ void hugetlb_change_protection(struct vm_area_struct *vma,
}
}
spin_unlock(&mm->page_table_lock);
- mutex_unlock(&vma->vm_file->f_mapping->i_mmap_mutex);
-
+ /*
+ * Must flush TLB before releasing i_mmap_mutex: x86's huge_pmd_unshare
+ * may have cleared our pud entry and done put_page on the page table:
+ * once we release i_mmap_mutex, another task can do the final put_page
+ * and that page table be reused and filled with junk.
+ */
flush_tlb_range(vma, start, end);
+ mutex_unlock(&vma->vm_file->f_mapping->i_mmap_mutex);
}
int hugetlb_reserve_pages(struct inode *inode,
@@ -2878,12 +2914,16 @@ int hugetlb_reserve_pages(struct inode *inode,
set_vma_resv_flags(vma, HPAGE_RESV_OWNER);
}
- if (chg < 0)
- return chg;
+ if (chg < 0) {
+ ret = chg;
+ goto out_err;
+ }
/* There must be enough filesystem quota for the mapping */
- if (hugetlb_get_quota(inode->i_mapping, chg))
- return -ENOSPC;
+ if (hugetlb_get_quota(inode->i_mapping, chg)) {
+ ret = -ENOSPC;
+ goto out_err;
+ }
/*
* Check enough hugepages are available for the reservation.
@@ -2892,7 +2932,7 @@ int hugetlb_reserve_pages(struct inode *inode,
ret = hugetlb_acct_memory(h, chg);
if (ret < 0) {
hugetlb_put_quota(inode->i_mapping, chg);
- return ret;
+ goto out_err;
}
/*
@@ -2909,6 +2949,10 @@ int hugetlb_reserve_pages(struct inode *inode,
if (!vma || vma->vm_flags & VM_MAYSHARE)
region_add(&inode->i_mapping->private_list, from, to);
return 0;
+out_err:
+ if (vma)
+ resv_map_put(vma);
+ return ret;
}
void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed)
diff --git a/mm/madvise.c b/mm/madvise.c
index 2221491..deabe5f6 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -13,6 +13,7 @@
#include <linux/hugetlb.h>
#include <linux/sched.h>
#include <linux/ksm.h>
+#include <linux/file.h>
/*
* Any behaviour which results in changes to the vma->vm_flags needs to
@@ -197,14 +198,16 @@ static long madvise_remove(struct vm_area_struct *vma,
struct address_space *mapping;
loff_t offset, endoff;
int error;
+ struct file *f;
*prev = NULL; /* tell sys_madvise we drop mmap_sem */
if (vma->vm_flags & (VM_LOCKED|VM_NONLINEAR|VM_HUGETLB))
return -EINVAL;
- if (!vma->vm_file || !vma->vm_file->f_mapping
- || !vma->vm_file->f_mapping->host) {
+ f = vma->vm_file;
+
+ if (!f || !f->f_mapping || !f->f_mapping->host) {
return -EINVAL;
}
@@ -218,9 +221,16 @@ static long madvise_remove(struct vm_area_struct *vma,
endoff = (loff_t)(end - vma->vm_start - 1)
+ ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
- /* vmtruncate_range needs to take i_mutex and i_alloc_sem */
+ /*
+ * vmtruncate_range may need to take i_mutex and i_alloc_sem.
+ * We need to explicitly grab a reference because the vma (and
+ * hence the vma's reference to the file) can go away as soon as
+ * we drop mmap_sem.
+ */
+ get_file(f);
up_read(&current->mm->mmap_sem);
error = vmtruncate_range(mapping->host, offset, endoff);
+ fput(f);
down_read(&current->mm->mmap_sem);
return error;
}
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 283068f..57cdf5a 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -1251,7 +1251,8 @@ mem_cgroup_get_reclaim_stat_from_page(struct page *page)
unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan,
struct list_head *dst,
unsigned long *scanned, int order,
- int mode, struct zone *z,
+ isolate_mode_t mode,
+ struct zone *z,
struct mem_cgroup *mem_cont,
int active, int file)
{
@@ -4605,6 +4606,12 @@ static void mem_cgroup_usage_unregister_event(struct cgroup *cgrp,
swap_buffers:
/* Swap primary and spare array */
thresholds->spare = thresholds->primary;
+ /* If all events are unregistered, free the spare array */
+ if (!new) {
+ kfree(thresholds->spare);
+ thresholds->spare = NULL;
+ }
+
rcu_assign_pointer(thresholds->primary, new);
/* To be sure that nobody uses thresholds */
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 740c4f5..2f49dcf 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -1334,8 +1334,8 @@ static int soft_offline_huge_page(struct page *page, int flags)
/* Keep page count to indicate a given hugepage is isolated. */
list_add(&hpage->lru, &pagelist);
- ret = migrate_huge_pages(&pagelist, new_page, MPOL_MF_MOVE_ALL, 0,
- true);
+ ret = migrate_huge_pages(&pagelist, new_page, MPOL_MF_MOVE_ALL, false,
+ MIGRATE_SYNC);
if (ret) {
struct page *page1, *page2;
list_for_each_entry_safe(page1, page2, &pagelist, lru)
@@ -1464,7 +1464,7 @@ int soft_offline_page(struct page *page, int flags)
page_is_file_cache(page));
list_add(&page->lru, &pagelist);
ret = migrate_pages(&pagelist, new_page, MPOL_MF_MOVE_ALL,
- 0, true);
+ false, MIGRATE_SYNC);
if (ret) {
putback_lru_pages(&pagelist);
pr_info("soft offline: %#lx: migration failed %d, type %lx\n",
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index c46887b..e0a3e51 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -116,9 +116,6 @@ static void register_page_bootmem_info_section(unsigned long start_pfn)
struct mem_section *ms;
struct page *page, *memmap;
- if (!pfn_valid(start_pfn))
- return;
-
section_nr = pfn_to_section_nr(start_pfn);
ms = __nr_to_section(section_nr);
@@ -177,9 +174,16 @@ void register_page_bootmem_info_node(struct pglist_data *pgdat)
end_pfn = pfn + pgdat->node_spanned_pages;
/* register_section info */
- for (; pfn < end_pfn; pfn += PAGES_PER_SECTION)
- register_page_bootmem_info_section(pfn);
-
+ for (; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
+ /*
+ * Some platforms can assign the same pfn to multiple nodes - on
+ * node0 as well as nodeN. To avoid registering a pfn against
+ * multiple nodes we check that this pfn does not already
+ * reside in some other node.
+ */
+ if (pfn_valid(pfn) && (pfn_to_nid(pfn) == node))
+ register_page_bootmem_info_section(pfn);
+ }
}
#endif /* !CONFIG_SPARSEMEM_VMEMMAP */
@@ -747,7 +751,7 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)
}
/* this function returns # of failed pages */
ret = migrate_pages(&source, hotremove_migrate_alloc, 0,
- true, true);
+ true, MIGRATE_SYNC);
if (ret)
putback_lru_pages(&source);
}
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index a85171d..5dce7d4 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -606,24 +606,39 @@ check_range(struct mm_struct *mm, unsigned long start, unsigned long end,
return first;
}
-/* Apply policy to a single VMA */
-static int policy_vma(struct vm_area_struct *vma, struct mempolicy *new)
+/*
+ * Apply policy to a single VMA
+ * This must be called with the mmap_sem held for writing.
+ */
+static int vma_replace_policy(struct vm_area_struct *vma,
+ struct mempolicy *pol)
{
- int err = 0;
- struct mempolicy *old = vma->vm_policy;
+ int err;
+ struct mempolicy *old;
+ struct mempolicy *new;
pr_debug("vma %lx-%lx/%lx vm_ops %p vm_file %p set_policy %p\n",
vma->vm_start, vma->vm_end, vma->vm_pgoff,
vma->vm_ops, vma->vm_file,
vma->vm_ops ? vma->vm_ops->set_policy : NULL);
- if (vma->vm_ops && vma->vm_ops->set_policy)
+ new = mpol_dup(pol);
+ if (IS_ERR(new))
+ return PTR_ERR(new);
+
+ if (vma->vm_ops && vma->vm_ops->set_policy) {
err = vma->vm_ops->set_policy(vma, new);
- if (!err) {
- mpol_get(new);
- vma->vm_policy = new;
- mpol_put(old);
+ if (err)
+ goto err_out;
}
+
+ old = vma->vm_policy;
+ vma->vm_policy = new; /* protected by mmap_sem */
+ mpol_put(old);
+
+ return 0;
+ err_out:
+ mpol_put(new);
return err;
}
@@ -666,7 +681,7 @@ static int mbind_range(struct mm_struct *mm, unsigned long start,
if (err)
goto out;
}
- err = policy_vma(vma, new_pol);
+ err = vma_replace_policy(vma, new_pol);
if (err)
goto out;
}
@@ -933,7 +948,7 @@ static int migrate_to_node(struct mm_struct *mm, int source, int dest,
if (!list_empty(&pagelist)) {
err = migrate_pages(&pagelist, new_node_page, dest,
- false, true);
+ false, MIGRATE_SYNC);
if (err)
putback_lru_pages(&pagelist);
}
@@ -1496,8 +1511,18 @@ struct mempolicy *get_vma_policy(struct task_struct *task,
addr);
if (vpol)
pol = vpol;
- } else if (vma->vm_policy)
+ } else if (vma->vm_policy) {
pol = vma->vm_policy;
+
+ /*
+ * shmem_alloc_page() passes MPOL_F_SHARED policy with
+ * a pseudo vma whose vma->vm_ops=NULL. Take a reference
+ * count on these policies which will be dropped by
+ * mpol_cond_put() later
+ */
+ if (mpol_needs_cond_ref(pol))
+ mpol_get(pol);
+ }
}
if (!pol)
pol = &default_policy;
@@ -1817,18 +1842,24 @@ struct page *
alloc_pages_vma(gfp_t gfp, int order, struct vm_area_struct *vma,
unsigned long addr, int node)
{
- struct mempolicy *pol = get_vma_policy(current, vma, addr);
+ struct mempolicy *pol;
struct zonelist *zl;
struct page *page;
+ unsigned int cpuset_mems_cookie;
+
+retry_cpuset:
+ pol = get_vma_policy(current, vma, addr);
+ cpuset_mems_cookie = get_mems_allowed();
- get_mems_allowed();
if (unlikely(pol->mode == MPOL_INTERLEAVE)) {
unsigned nid;
nid = interleave_nid(pol, vma, addr, PAGE_SHIFT + order);
mpol_cond_put(pol);
page = alloc_page_interleave(gfp, order, nid);
- put_mems_allowed();
+ if (unlikely(!put_mems_allowed(cpuset_mems_cookie) && !page))
+ goto retry_cpuset;
+
return page;
}
zl = policy_zonelist(gfp, pol, node);
@@ -1839,7 +1870,8 @@ alloc_pages_vma(gfp_t gfp, int order, struct vm_area_struct *vma,
struct page *page = __alloc_pages_nodemask(gfp, order,
zl, policy_nodemask(gfp, pol));
__mpol_put(pol);
- put_mems_allowed();
+ if (unlikely(!put_mems_allowed(cpuset_mems_cookie) && !page))
+ goto retry_cpuset;
return page;
}
/*
@@ -1847,7 +1879,8 @@ alloc_pages_vma(gfp_t gfp, int order, struct vm_area_struct *vma,
*/
page = __alloc_pages_nodemask(gfp, order, zl,
policy_nodemask(gfp, pol));
- put_mems_allowed();
+ if (unlikely(!put_mems_allowed(cpuset_mems_cookie) && !page))
+ goto retry_cpuset;
return page;
}
@@ -1874,11 +1907,14 @@ struct page *alloc_pages_current(gfp_t gfp, unsigned order)
{
struct mempolicy *pol = current->mempolicy;
struct page *page;
+ unsigned int cpuset_mems_cookie;
if (!pol || in_interrupt() || (gfp & __GFP_THISNODE))
pol = &default_policy;
- get_mems_allowed();
+retry_cpuset:
+ cpuset_mems_cookie = get_mems_allowed();
+
/*
* No reference counting needed for current->mempolicy
* nor system default_policy
@@ -1889,7 +1925,10 @@ struct page *alloc_pages_current(gfp_t gfp, unsigned order)
page = __alloc_pages_nodemask(gfp, order,
policy_zonelist(gfp, pol, numa_node_id()),
policy_nodemask(gfp, pol));
- put_mems_allowed();
+
+ if (unlikely(!put_mems_allowed(cpuset_mems_cookie) && !page))
+ goto retry_cpuset;
+
return page;
}
EXPORT_SYMBOL(alloc_pages_current);
@@ -1992,7 +2031,7 @@ int __mpol_equal(struct mempolicy *a, struct mempolicy *b)
*/
/* lookup first element intersecting start-end */
-/* Caller holds sp->lock */
+/* Caller holds sp->mutex */
static struct sp_node *
sp_lookup(struct shared_policy *sp, unsigned long start, unsigned long end)
{
@@ -2056,36 +2095,50 @@ mpol_shared_policy_lookup(struct shared_policy *sp, unsigned long idx)
if (!sp->root.rb_node)
return NULL;
- spin_lock(&sp->lock);
+ mutex_lock(&sp->mutex);
sn = sp_lookup(sp, idx, idx+1);
if (sn) {
mpol_get(sn->policy);
pol = sn->policy;
}
- spin_unlock(&sp->lock);
+ mutex_unlock(&sp->mutex);
return pol;
}
+static void sp_free(struct sp_node *n)
+{
+ mpol_put(n->policy);
+ kmem_cache_free(sn_cache, n);
+}
+
static void sp_delete(struct shared_policy *sp, struct sp_node *n)
{
pr_debug("deleting %lx-l%lx\n", n->start, n->end);
rb_erase(&n->nd, &sp->root);
- mpol_put(n->policy);
- kmem_cache_free(sn_cache, n);
+ sp_free(n);
}
static struct sp_node *sp_alloc(unsigned long start, unsigned long end,
struct mempolicy *pol)
{
- struct sp_node *n = kmem_cache_alloc(sn_cache, GFP_KERNEL);
+ struct sp_node *n;
+ struct mempolicy *newpol;
+ n = kmem_cache_alloc(sn_cache, GFP_KERNEL);
if (!n)
return NULL;
+
+ newpol = mpol_dup(pol);
+ if (IS_ERR(newpol)) {
+ kmem_cache_free(sn_cache, n);
+ return NULL;
+ }
+ newpol->flags |= MPOL_F_SHARED;
+
n->start = start;
n->end = end;
- mpol_get(pol);
- pol->flags |= MPOL_F_SHARED; /* for unref */
- n->policy = pol;
+ n->policy = newpol;
+
return n;
}
@@ -2093,10 +2146,10 @@ static struct sp_node *sp_alloc(unsigned long start, unsigned long end,
static int shared_policy_replace(struct shared_policy *sp, unsigned long start,
unsigned long end, struct sp_node *new)
{
- struct sp_node *n, *new2 = NULL;
+ struct sp_node *n;
+ int ret = 0;
-restart:
- spin_lock(&sp->lock);
+ mutex_lock(&sp->mutex);
n = sp_lookup(sp, start, end);
/* Take care of old policies in the same range. */
while (n && n->start < end) {
@@ -2109,16 +2162,14 @@ restart:
} else {
/* Old policy spanning whole new range. */
if (n->end > end) {
+ struct sp_node *new2;
+ new2 = sp_alloc(end, n->end, n->policy);
if (!new2) {
- spin_unlock(&sp->lock);
- new2 = sp_alloc(end, n->end, n->policy);
- if (!new2)
- return -ENOMEM;
- goto restart;
+ ret = -ENOMEM;
+ goto out;
}
n->end = start;
sp_insert(sp, new2);
- new2 = NULL;
break;
} else
n->end = start;
@@ -2129,12 +2180,9 @@ restart:
}
if (new)
sp_insert(sp, new);
- spin_unlock(&sp->lock);
- if (new2) {
- mpol_put(new2->policy);
- kmem_cache_free(sn_cache, new2);
- }
- return 0;
+out:
+ mutex_unlock(&sp->mutex);
+ return ret;
}
/**
@@ -2152,7 +2200,7 @@ void mpol_shared_policy_init(struct shared_policy *sp, struct mempolicy *mpol)
int ret;
sp->root = RB_ROOT; /* empty tree == default mempolicy */
- spin_lock_init(&sp->lock);
+ mutex_init(&sp->mutex);
if (mpol) {
struct vm_area_struct pvma;
@@ -2206,7 +2254,7 @@ int mpol_set_shared_policy(struct shared_policy *info,
}
err = shared_policy_replace(info, vma->vm_pgoff, vma->vm_pgoff+sz, new);
if (err && new)
- kmem_cache_free(sn_cache, new);
+ sp_free(new);
return err;
}
@@ -2218,16 +2266,14 @@ void mpol_free_shared_policy(struct shared_policy *p)
if (!p->root.rb_node)
return;
- spin_lock(&p->lock);
+ mutex_lock(&p->mutex);
next = rb_first(&p->root);
while (next) {
n = rb_entry(next, struct sp_node, nd);
next = rb_next(&n->nd);
- rb_erase(&n->nd, &p->root);
- mpol_put(n->policy);
- kmem_cache_free(sn_cache, n);
+ sp_delete(p, n);
}
- spin_unlock(&p->lock);
+ mutex_unlock(&p->mutex);
}
/* assumes fs == KERNEL_DS */
@@ -2493,7 +2539,7 @@ int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol, int no_context)
break;
default:
- BUG();
+ return -EINVAL;
}
l = strlen(policy_modes[mode]);
diff --git a/mm/migrate.c b/mm/migrate.c
index 14d0a6a..480714b 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -220,6 +220,56 @@ out:
pte_unmap_unlock(ptep, ptl);
}
+#ifdef CONFIG_BLOCK
+/* Returns true if all buffers are successfully locked */
+static bool buffer_migrate_lock_buffers(struct buffer_head *head,
+ enum migrate_mode mode)
+{
+ struct buffer_head *bh = head;
+
+ /* Simple case, sync compaction */
+ if (mode != MIGRATE_ASYNC) {
+ do {
+ get_bh(bh);
+ lock_buffer(bh);
+ bh = bh->b_this_page;
+
+ } while (bh != head);
+
+ return true;
+ }
+
+ /* async case, we cannot block on lock_buffer so use trylock_buffer */
+ do {
+ get_bh(bh);
+ if (!trylock_buffer(bh)) {
+ /*
+ * We failed to lock the buffer and cannot stall in
+ * async migration. Release the taken locks
+ */
+ struct buffer_head *failed_bh = bh;
+ put_bh(failed_bh);
+ bh = head;
+ while (bh != failed_bh) {
+ unlock_buffer(bh);
+ put_bh(bh);
+ bh = bh->b_this_page;
+ }
+ return false;
+ }
+
+ bh = bh->b_this_page;
+ } while (bh != head);
+ return true;
+}
+#else
+static inline bool buffer_migrate_lock_buffers(struct buffer_head *head,
+ enum migrate_mode mode)
+{
+ return true;
+}
+#endif /* CONFIG_BLOCK */
+
/*
* Replace the page in the mapping.
*
@@ -229,7 +279,8 @@ out:
* 3 for pages with a mapping and PagePrivate/PagePrivate2 set.
*/
static int migrate_page_move_mapping(struct address_space *mapping,
- struct page *newpage, struct page *page)
+ struct page *newpage, struct page *page,
+ struct buffer_head *head, enum migrate_mode mode)
{
int expected_count;
void **pslot;
@@ -259,6 +310,20 @@ static int migrate_page_move_mapping(struct address_space *mapping,
}
/*
+ * In the async migration case of moving a page with buffers, lock the
+ * buffers using trylock before the mapping is moved. If the mapping
+ * was moved, we later failed to lock the buffers and could not move
+ * the mapping back due to an elevated page count, we would have to
+ * block waiting on other references to be dropped.
+ */
+ if (mode == MIGRATE_ASYNC && head &&
+ !buffer_migrate_lock_buffers(head, mode)) {
+ page_unfreeze_refs(page, expected_count);
+ spin_unlock_irq(&mapping->tree_lock);
+ return -EAGAIN;
+ }
+
+ /*
* Now we know that no one else is looking at the page.
*/
get_page(newpage); /* add cache reference */
@@ -415,13 +480,14 @@ EXPORT_SYMBOL(fail_migrate_page);
* Pages are locked upon entry and exit.
*/
int migrate_page(struct address_space *mapping,
- struct page *newpage, struct page *page)
+ struct page *newpage, struct page *page,
+ enum migrate_mode mode)
{
int rc;
BUG_ON(PageWriteback(page)); /* Writeback must be complete */
- rc = migrate_page_move_mapping(mapping, newpage, page);
+ rc = migrate_page_move_mapping(mapping, newpage, page, NULL, mode);
if (rc)
return rc;
@@ -438,28 +504,28 @@ EXPORT_SYMBOL(migrate_page);
* exist.
*/
int buffer_migrate_page(struct address_space *mapping,
- struct page *newpage, struct page *page)
+ struct page *newpage, struct page *page, enum migrate_mode mode)
{
struct buffer_head *bh, *head;
int rc;
if (!page_has_buffers(page))
- return migrate_page(mapping, newpage, page);
+ return migrate_page(mapping, newpage, page, mode);
head = page_buffers(page);
- rc = migrate_page_move_mapping(mapping, newpage, page);
+ rc = migrate_page_move_mapping(mapping, newpage, page, head, mode);
if (rc)
return rc;
- bh = head;
- do {
- get_bh(bh);
- lock_buffer(bh);
- bh = bh->b_this_page;
-
- } while (bh != head);
+ /*
+ * In the async case, migrate_page_move_mapping locked the buffers
+ * with an IRQ-safe spinlock held. In the sync case, the buffers
+ * need to be locked now
+ */
+ if (mode != MIGRATE_ASYNC)
+ BUG_ON(!buffer_migrate_lock_buffers(head, mode));
ClearPagePrivate(page);
set_page_private(newpage, page_private(page));
@@ -536,10 +602,14 @@ static int writeout(struct address_space *mapping, struct page *page)
* Default handling if a filesystem does not provide a migration function.
*/
static int fallback_migrate_page(struct address_space *mapping,
- struct page *newpage, struct page *page)
+ struct page *newpage, struct page *page, enum migrate_mode mode)
{
- if (PageDirty(page))
+ if (PageDirty(page)) {
+ /* Only writeback pages in full synchronous migration */
+ if (mode != MIGRATE_SYNC)
+ return -EBUSY;
return writeout(mapping, page);
+ }
/*
* Buffers may be managed in a filesystem specific way.
@@ -549,7 +619,7 @@ static int fallback_migrate_page(struct address_space *mapping,
!try_to_release_page(page, GFP_KERNEL))
return -EAGAIN;
- return migrate_page(mapping, newpage, page);
+ return migrate_page(mapping, newpage, page, mode);
}
/*
@@ -564,7 +634,7 @@ static int fallback_migrate_page(struct address_space *mapping,
* == 0 - success
*/
static int move_to_new_page(struct page *newpage, struct page *page,
- int remap_swapcache, bool sync)
+ int remap_swapcache, enum migrate_mode mode)
{
struct address_space *mapping;
int rc;
@@ -585,29 +655,18 @@ static int move_to_new_page(struct page *newpage, struct page *page,
mapping = page_mapping(page);
if (!mapping)
- rc = migrate_page(mapping, newpage, page);
- else {
+ rc = migrate_page(mapping, newpage, page, mode);
+ else if (mapping->a_ops->migratepage)
/*
- * Do not writeback pages if !sync and migratepage is
- * not pointing to migrate_page() which is nonblocking
- * (swapcache/tmpfs uses migratepage = migrate_page).
+ * Most pages have a mapping and most filesystems provide a
+ * migratepage callback. Anonymous pages are part of swap
+ * space which also has its own migratepage callback. This
+ * is the most common path for page migration.
*/
- if (PageDirty(page) && !sync &&
- mapping->a_ops->migratepage != migrate_page)
- rc = -EBUSY;
- else if (mapping->a_ops->migratepage)
- /*
- * Most pages have a mapping and most filesystems
- * should provide a migration function. Anonymous
- * pages are part of swap space which also has its
- * own migration function. This is the most common
- * path for page migration.
- */
- rc = mapping->a_ops->migratepage(mapping,
- newpage, page);
- else
- rc = fallback_migrate_page(mapping, newpage, page);
- }
+ rc = mapping->a_ops->migratepage(mapping,
+ newpage, page, mode);
+ else
+ rc = fallback_migrate_page(mapping, newpage, page, mode);
if (rc) {
newpage->mapping = NULL;
@@ -621,38 +680,18 @@ static int move_to_new_page(struct page *newpage, struct page *page,
return rc;
}
-/*
- * Obtain the lock on page, remove all ptes and migrate the page
- * to the newly allocated page in newpage.
- */
-static int unmap_and_move(new_page_t get_new_page, unsigned long private,
- struct page *page, int force, bool offlining, bool sync)
+static int __unmap_and_move(struct page *page, struct page *newpage,
+ int force, bool offlining, enum migrate_mode mode)
{
- int rc = 0;
- int *result = NULL;
- struct page *newpage = get_new_page(page, private, &result);
+ int rc = -EAGAIN;
int remap_swapcache = 1;
int charge = 0;
struct mem_cgroup *mem;
struct anon_vma *anon_vma = NULL;
- if (!newpage)
- return -ENOMEM;
-
- if (page_count(page) == 1) {
- /* page was freed from under us. So we are done. */
- goto move_newpage;
- }
- if (unlikely(PageTransHuge(page)))
- if (unlikely(split_huge_page(page)))
- goto move_newpage;
-
- /* prepare cgroup just returns 0 or -ENOMEM */
- rc = -EAGAIN;
-
if (!trylock_page(page)) {
- if (!force || !sync)
- goto move_newpage;
+ if (!force || mode == MIGRATE_ASYNC)
+ goto out;
/*
* It's not safe for direct compaction to call lock_page.
@@ -668,7 +707,7 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private,
* altogether.
*/
if (current->flags & PF_MEMALLOC)
- goto move_newpage;
+ goto out;
lock_page(page);
}
@@ -697,10 +736,12 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private,
if (PageWriteback(page)) {
/*
- * For !sync, there is no point retrying as the retry loop
- * is expected to be too short for PageWriteback to be cleared
+ * Only in the case of a full syncronous migration is it
+ * necessary to wait for PageWriteback. In the async case,
+ * the retry loop is too short and in the sync-light case,
+ * the overhead of stalling is too much
*/
- if (!sync) {
+ if (mode != MIGRATE_SYNC) {
rc = -EBUSY;
goto uncharge;
}
@@ -771,7 +812,7 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private,
skip_unmap:
if (!page_mapped(page))
- rc = move_to_new_page(newpage, page, remap_swapcache, sync);
+ rc = move_to_new_page(newpage, page, remap_swapcache, mode);
if (rc && remap_swapcache)
remove_migration_ptes(page, page);
@@ -785,27 +826,53 @@ uncharge:
mem_cgroup_end_migration(mem, page, newpage, rc == 0);
unlock:
unlock_page(page);
+out:
+ return rc;
+}
-move_newpage:
+/*
+ * Obtain the lock on page, remove all ptes and migrate the page
+ * to the newly allocated page in newpage.
+ */
+static int unmap_and_move(new_page_t get_new_page, unsigned long private,
+ struct page *page, int force, bool offlining,
+ enum migrate_mode mode)
+{
+ int rc = 0;
+ int *result = NULL;
+ struct page *newpage = get_new_page(page, private, &result);
+
+ if (!newpage)
+ return -ENOMEM;
+
+ if (page_count(page) == 1) {
+ /* page was freed from under us. So we are done. */
+ goto out;
+ }
+
+ if (unlikely(PageTransHuge(page)))
+ if (unlikely(split_huge_page(page)))
+ goto out;
+
+ rc = __unmap_and_move(page, newpage, force, offlining, mode);
+out:
if (rc != -EAGAIN) {
- /*
- * A page that has been migrated has all references
- * removed and will be freed. A page that has not been
- * migrated will have kepts its references and be
- * restored.
- */
- list_del(&page->lru);
+ /*
+ * A page that has been migrated has all references
+ * removed and will be freed. A page that has not been
+ * migrated will have kepts its references and be
+ * restored.
+ */
+ list_del(&page->lru);
dec_zone_page_state(page, NR_ISOLATED_ANON +
page_is_file_cache(page));
putback_lru_page(page);
}
-
/*
* Move the new page to the LRU. If migration was not successful
* then this will free the page.
*/
putback_lru_page(newpage);
-
if (result) {
if (rc)
*result = rc;
@@ -835,7 +902,8 @@ move_newpage:
*/
static int unmap_and_move_huge_page(new_page_t get_new_page,
unsigned long private, struct page *hpage,
- int force, bool offlining, bool sync)
+ int force, bool offlining,
+ enum migrate_mode mode)
{
int rc = 0;
int *result = NULL;
@@ -848,7 +916,7 @@ static int unmap_and_move_huge_page(new_page_t get_new_page,
rc = -EAGAIN;
if (!trylock_page(hpage)) {
- if (!force || !sync)
+ if (!force || mode != MIGRATE_SYNC)
goto out;
lock_page(hpage);
}
@@ -859,7 +927,7 @@ static int unmap_and_move_huge_page(new_page_t get_new_page,
try_to_unmap(hpage, TTU_MIGRATION|TTU_IGNORE_MLOCK|TTU_IGNORE_ACCESS);
if (!page_mapped(hpage))
- rc = move_to_new_page(new_hpage, hpage, 1, sync);
+ rc = move_to_new_page(new_hpage, hpage, 1, mode);
if (rc)
remove_migration_ptes(hpage, hpage);
@@ -902,7 +970,7 @@ out:
*/
int migrate_pages(struct list_head *from,
new_page_t get_new_page, unsigned long private, bool offlining,
- bool sync)
+ enum migrate_mode mode)
{
int retry = 1;
int nr_failed = 0;
@@ -923,7 +991,7 @@ int migrate_pages(struct list_head *from,
rc = unmap_and_move(get_new_page, private,
page, pass > 2, offlining,
- sync);
+ mode);
switch(rc) {
case -ENOMEM:
@@ -953,7 +1021,7 @@ out:
int migrate_huge_pages(struct list_head *from,
new_page_t get_new_page, unsigned long private, bool offlining,
- bool sync)
+ enum migrate_mode mode)
{
int retry = 1;
int nr_failed = 0;
@@ -970,7 +1038,7 @@ int migrate_huge_pages(struct list_head *from,
rc = unmap_and_move_huge_page(get_new_page,
private, page, pass > 2, offlining,
- sync);
+ mode);
switch(rc) {
case -ENOMEM:
@@ -1099,7 +1167,7 @@ set_status:
err = 0;
if (!list_empty(&pagelist)) {
err = migrate_pages(&pagelist, new_page_node,
- (unsigned long)pm, 0, true);
+ (unsigned long)pm, 0, MIGRATE_SYNC);
if (err)
putback_lru_pages(&pagelist);
}
diff --git a/mm/mmu_notifier.c b/mm/mmu_notifier.c
index 8d032de..71c7811 100644
--- a/mm/mmu_notifier.c
+++ b/mm/mmu_notifier.c
@@ -33,6 +33,24 @@
void __mmu_notifier_release(struct mm_struct *mm)
{
struct mmu_notifier *mn;
+ struct hlist_node *n;
+
+ /*
+ * RCU here will block mmu_notifier_unregister until
+ * ->release returns.
+ */
+ rcu_read_lock();
+ hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist)
+ /*
+ * if ->release runs before mmu_notifier_unregister it
+ * must be handled as it's the only way for the driver
+ * to flush all existing sptes and stop the driver
+ * from establishing any more sptes before all the
+ * pages in the mm are freed.
+ */
+ if (mn->ops->release)
+ mn->ops->release(mn, mm);
+ rcu_read_unlock();
spin_lock(&mm->mmu_notifier_mm->lock);
while (unlikely(!hlist_empty(&mm->mmu_notifier_mm->list))) {
@@ -46,23 +64,6 @@ void __mmu_notifier_release(struct mm_struct *mm)
* mmu_notifier_unregister to return.
*/
hlist_del_init_rcu(&mn->hlist);
- /*
- * RCU here will block mmu_notifier_unregister until
- * ->release returns.
- */
- rcu_read_lock();
- spin_unlock(&mm->mmu_notifier_mm->lock);
- /*
- * if ->release runs before mmu_notifier_unregister it
- * must be handled as it's the only way for the driver
- * to flush all existing sptes and stop the driver
- * from establishing any more sptes before all the
- * pages in the mm are freed.
- */
- if (mn->ops->release)
- mn->ops->release(mn, mm);
- rcu_read_unlock();
- spin_lock(&mm->mmu_notifier_mm->lock);
}
spin_unlock(&mm->mmu_notifier_mm->lock);
@@ -284,16 +285,13 @@ void mmu_notifier_unregister(struct mmu_notifier *mn, struct mm_struct *mm)
{
BUG_ON(atomic_read(&mm->mm_count) <= 0);
- spin_lock(&mm->mmu_notifier_mm->lock);
if (!hlist_unhashed(&mn->hlist)) {
- hlist_del_rcu(&mn->hlist);
-
/*
* RCU here will force exit_mmap to wait ->release to finish
* before freeing the pages.
*/
rcu_read_lock();
- spin_unlock(&mm->mmu_notifier_mm->lock);
+
/*
* exit_mmap will block in mmu_notifier_release to
* guarantee ->release is called before freeing the
@@ -302,8 +300,11 @@ void mmu_notifier_unregister(struct mmu_notifier *mn, struct mm_struct *mm)
if (mn->ops->release)
mn->ops->release(mn, mm);
rcu_read_unlock();
- } else
+
+ spin_lock(&mm->mmu_notifier_mm->lock);
+ hlist_del_rcu(&mn->hlist);
spin_unlock(&mm->mmu_notifier_mm->lock);
+ }
/*
* Wait any running method to finish, of course including
diff --git a/mm/nobootmem.c b/mm/nobootmem.c
index 6e93dc7..e39e3ef 100644
--- a/mm/nobootmem.c
+++ b/mm/nobootmem.c
@@ -83,8 +83,7 @@ void __init free_bootmem_late(unsigned long addr, unsigned long size)
static void __init __free_pages_memory(unsigned long start, unsigned long end)
{
- int i;
- unsigned long start_aligned, end_aligned;
+ unsigned long i, start_aligned, end_aligned;
int order = ilog2(BITS_PER_LONG);
start_aligned = (start + (BITS_PER_LONG - 1)) & ~(BITS_PER_LONG - 1);
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index e2f474d..bfe7894 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -555,7 +555,7 @@ static inline void __free_one_page(struct page *page,
combined_idx = buddy_idx & page_idx;
higher_page = page + (combined_idx - page_idx);
buddy_idx = __find_buddy_index(combined_idx, order + 1);
- higher_buddy = page + (buddy_idx - combined_idx);
+ higher_buddy = higher_page + (buddy_idx - combined_idx);
if (page_is_buddy(higher_page, higher_buddy, order + 1)) {
list_add_tail(&page->lru,
&zone->free_area[order].free_list[migratetype]);
@@ -1912,14 +1912,20 @@ static struct page *
__alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order,
struct zonelist *zonelist, enum zone_type high_zoneidx,
nodemask_t *nodemask, int alloc_flags, struct zone *preferred_zone,
- int migratetype, unsigned long *did_some_progress,
- bool sync_migration)
+ int migratetype, bool sync_migration,
+ bool *deferred_compaction,
+ unsigned long *did_some_progress)
{
struct page *page;
- if (!order || compaction_deferred(preferred_zone))
+ if (!order)
return NULL;
+ if (compaction_deferred(preferred_zone)) {
+ *deferred_compaction = true;
+ return NULL;
+ }
+
current->flags |= PF_MEMALLOC;
*did_some_progress = try_to_compact_pages(zonelist, order, gfp_mask,
nodemask, sync_migration);
@@ -1947,7 +1953,13 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order,
* but not enough to satisfy watermarks.
*/
count_vm_event(COMPACTFAIL);
- defer_compaction(preferred_zone);
+
+ /*
+ * As async compaction considers a subset of pageblocks, only
+ * defer if the failure was a sync compaction failure.
+ */
+ if (sync_migration)
+ defer_compaction(preferred_zone);
cond_resched();
}
@@ -1959,8 +1971,9 @@ static inline struct page *
__alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order,
struct zonelist *zonelist, enum zone_type high_zoneidx,
nodemask_t *nodemask, int alloc_flags, struct zone *preferred_zone,
- int migratetype, unsigned long *did_some_progress,
- bool sync_migration)
+ int migratetype, bool sync_migration,
+ bool *deferred_compaction,
+ unsigned long *did_some_progress)
{
return NULL;
}
@@ -2110,6 +2123,7 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
unsigned long pages_reclaimed = 0;
unsigned long did_some_progress;
bool sync_migration = false;
+ bool deferred_compaction = false;
/*
* In the slowpath, we sanity check order to avoid ever trying to
@@ -2190,12 +2204,22 @@ rebalance:
zonelist, high_zoneidx,
nodemask,
alloc_flags, preferred_zone,
- migratetype, &did_some_progress,
- sync_migration);
+ migratetype, sync_migration,
+ &deferred_compaction,
+ &did_some_progress);
if (page)
goto got_pg;
sync_migration = true;
+ /*
+ * If compaction is deferred for high-order allocations, it is because
+ * sync compaction recently failed. In this is the case and the caller
+ * has requested the system not be heavily disrupted, fail the
+ * allocation now instead of entering direct reclaim
+ */
+ if (deferred_compaction && (gfp_mask & __GFP_NO_KSWAPD))
+ goto nopage;
+
/* Try direct reclaim and then allocating */
page = __alloc_pages_direct_reclaim(gfp_mask, order,
zonelist, high_zoneidx,
@@ -2266,8 +2290,9 @@ rebalance:
zonelist, high_zoneidx,
nodemask,
alloc_flags, preferred_zone,
- migratetype, &did_some_progress,
- sync_migration);
+ migratetype, sync_migration,
+ &deferred_compaction,
+ &did_some_progress);
if (page)
goto got_pg;
}
@@ -2291,8 +2316,9 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order,
{
enum zone_type high_zoneidx = gfp_zone(gfp_mask);
struct zone *preferred_zone;
- struct page *page;
+ struct page *page = NULL;
int migratetype = allocflags_to_migratetype(gfp_mask);
+ unsigned int cpuset_mems_cookie;
gfp_mask &= gfp_allowed_mask;
@@ -2311,15 +2337,15 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order,
if (unlikely(!zonelist->_zonerefs->zone))
return NULL;
- get_mems_allowed();
+retry_cpuset:
+ cpuset_mems_cookie = get_mems_allowed();
+
/* The preferred zone is used for statistics later */
first_zones_zonelist(zonelist, high_zoneidx,
nodemask ? : &cpuset_current_mems_allowed,
&preferred_zone);
- if (!preferred_zone) {
- put_mems_allowed();
- return NULL;
- }
+ if (!preferred_zone)
+ goto out;
/* First allocation attempt */
page = get_page_from_freelist(gfp_mask|__GFP_HARDWALL, nodemask, order,
@@ -2329,9 +2355,19 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order,
page = __alloc_pages_slowpath(gfp_mask, order,
zonelist, high_zoneidx, nodemask,
preferred_zone, migratetype);
- put_mems_allowed();
trace_mm_page_alloc(page, order, gfp_mask, migratetype);
+
+out:
+ /*
+ * When updating a task's mems_allowed, it is possible to race with
+ * parallel threads in such a way that an allocation can fail while
+ * the mask is being updated. If a page allocation is about to fail,
+ * check if the cpuset changed during allocation and if so, retry.
+ */
+ if (unlikely(!put_mems_allowed(cpuset_mems_cookie) && !page))
+ goto retry_cpuset;
+
return page;
}
EXPORT_SYMBOL(__alloc_pages_nodemask);
@@ -2555,13 +2591,15 @@ void si_meminfo_node(struct sysinfo *val, int nid)
bool skip_free_areas_node(unsigned int flags, int nid)
{
bool ret = false;
+ unsigned int cpuset_mems_cookie;
if (!(flags & SHOW_MEM_FILTER_NODES))
goto out;
- get_mems_allowed();
- ret = !node_isset(nid, cpuset_current_mems_allowed);
- put_mems_allowed();
+ do {
+ cpuset_mems_cookie = get_mems_allowed();
+ ret = !node_isset(nid, cpuset_current_mems_allowed);
+ } while (!put_mems_allowed(cpuset_mems_cookie));
out:
return ret;
}
@@ -3441,25 +3479,33 @@ static void setup_zone_migrate_reserve(struct zone *zone)
if (page_to_nid(page) != zone_to_nid(zone))
continue;
- /* Blocks with reserved pages will never free, skip them. */
- block_end_pfn = min(pfn + pageblock_nr_pages, end_pfn);
- if (pageblock_is_reserved(pfn, block_end_pfn))
- continue;
-
block_migratetype = get_pageblock_migratetype(page);
- /* If this block is reserved, account for it */
- if (reserve > 0 && block_migratetype == MIGRATE_RESERVE) {
- reserve--;
- continue;
- }
+ /* Only test what is necessary when the reserves are not met */
+ if (reserve > 0) {
+ /*
+ * Blocks with reserved pages will never free, skip
+ * them.
+ */
+ block_end_pfn = min(pfn + pageblock_nr_pages, end_pfn);
+ if (pageblock_is_reserved(pfn, block_end_pfn))
+ continue;
- /* Suitable for reserving if this block is movable */
- if (reserve > 0 && block_migratetype == MIGRATE_MOVABLE) {
- set_pageblock_migratetype(page, MIGRATE_RESERVE);
- move_freepages_block(zone, page, MIGRATE_RESERVE);
- reserve--;
- continue;
+ /* If this block is reserved, account for it */
+ if (block_migratetype == MIGRATE_RESERVE) {
+ reserve--;
+ continue;
+ }
+
+ /* Suitable for reserving if this block is movable */
+ if (block_migratetype == MIGRATE_MOVABLE) {
+ set_pageblock_migratetype(page,
+ MIGRATE_RESERVE);
+ move_freepages_block(zone, page,
+ MIGRATE_RESERVE);
+ reserve--;
+ continue;
+ }
}
/*
diff --git a/mm/percpu.c b/mm/percpu.c
index 0ae7a09..af0cc7a 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -1630,6 +1630,16 @@ int __init pcpu_embed_first_chunk(size_t reserved_size, size_t dyn_size,
areas[group] = ptr;
base = min(ptr, base);
+ }
+
+ /*
+ * Copy data and free unused parts. This should happen after all
+ * allocations are complete; otherwise, we may end up with
+ * overlapping groups.
+ */
+ for (group = 0; group < ai->nr_groups; group++) {
+ struct pcpu_group_info *gi = &ai->groups[group];
+ void *ptr = areas[group];
for (i = 0; i < gi->nr_units; i++, ptr += ai->unit_size) {
if (gi->cpu_map[i] == NR_CPUS) {
diff --git a/mm/shmem.c b/mm/shmem.c
index 883e98f..df31a44 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -2348,12 +2348,14 @@ static struct dentry *shmem_fh_to_dentry(struct super_block *sb,
{
struct inode *inode;
struct dentry *dentry = NULL;
- u64 inum = fid->raw[2];
- inum = (inum << 32) | fid->raw[1];
+ u64 inum;
if (fh_len < 3)
return NULL;
+ inum = fid->raw[2];
+ inum = (inum << 32) | fid->raw[1];
+
inode = ilookup5(sb, (unsigned long)(inum + fid->raw[0]),
shmem_match, fid->raw);
if (inode) {
diff --git a/mm/slab.c b/mm/slab.c
index d96e223..a67f812 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -3218,12 +3218,10 @@ static void *alternate_node_alloc(struct kmem_cache *cachep, gfp_t flags)
if (in_interrupt() || (flags & __GFP_THISNODE))
return NULL;
nid_alloc = nid_here = numa_mem_id();
- get_mems_allowed();
if (cpuset_do_slab_mem_spread() && (cachep->flags & SLAB_MEM_SPREAD))
nid_alloc = cpuset_slab_spread_node();
else if (current->mempolicy)
nid_alloc = slab_node(current->mempolicy);
- put_mems_allowed();
if (nid_alloc != nid_here)
return ____cache_alloc_node(cachep, flags, nid_alloc);
return NULL;
@@ -3246,14 +3244,17 @@ static void *fallback_alloc(struct kmem_cache *cache, gfp_t flags)
enum zone_type high_zoneidx = gfp_zone(flags);
void *obj = NULL;
int nid;
+ unsigned int cpuset_mems_cookie;
if (flags & __GFP_THISNODE)
return NULL;
- get_mems_allowed();
- zonelist = node_zonelist(slab_node(current->mempolicy), flags);
local_flags = flags & (GFP_CONSTRAINT_MASK|GFP_RECLAIM_MASK);
+retry_cpuset:
+ cpuset_mems_cookie = get_mems_allowed();
+ zonelist = node_zonelist(slab_node(current->mempolicy), flags);
+
retry:
/*
* Look through allowed nodes for objects available
@@ -3306,7 +3307,9 @@ retry:
}
}
}
- put_mems_allowed();
+
+ if (unlikely(!put_mems_allowed(cpuset_mems_cookie) && !obj))
+ goto retry_cpuset;
return obj;
}
diff --git a/mm/slub.c b/mm/slub.c
index 10ab233..ae6e80e 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1457,6 +1457,7 @@ static struct page *get_any_partial(struct kmem_cache *s, gfp_t flags)
struct zone *zone;
enum zone_type high_zoneidx = gfp_zone(flags);
struct page *page;
+ unsigned int cpuset_mems_cookie;
/*
* The defrag ratio allows a configuration of the tradeoffs between
@@ -1480,23 +1481,32 @@ static struct page *get_any_partial(struct kmem_cache *s, gfp_t flags)
get_cycles() % 1024 > s->remote_node_defrag_ratio)
return NULL;
- get_mems_allowed();
- zonelist = node_zonelist(slab_node(current->mempolicy), flags);
- for_each_zone_zonelist(zone, z, zonelist, high_zoneidx) {
- struct kmem_cache_node *n;
-
- n = get_node(s, zone_to_nid(zone));
-
- if (n && cpuset_zone_allowed_hardwall(zone, flags) &&
- n->nr_partial > s->min_partial) {
- page = get_partial_node(n);
- if (page) {
- put_mems_allowed();
- return page;
+ do {
+ cpuset_mems_cookie = get_mems_allowed();
+ zonelist = node_zonelist(slab_node(current->mempolicy), flags);
+ for_each_zone_zonelist(zone, z, zonelist, high_zoneidx) {
+ struct kmem_cache_node *n;
+
+ n = get_node(s, zone_to_nid(zone));
+
+ if (n && cpuset_zone_allowed_hardwall(zone, flags) &&
+ n->nr_partial > s->min_partial) {
+ page = get_partial_node(n);
+ if (page) {
+ /*
+ * Return the object even if
+ * put_mems_allowed indicated that
+ * the cpuset mems_allowed was
+ * updated in parallel. It's a
+ * harmless race between the alloc
+ * and the cpuset update.
+ */
+ put_mems_allowed(cpuset_mems_cookie);
+ return page;
+ }
}
}
- }
- put_mems_allowed();
+ } while (!put_mems_allowed(cpuset_mems_cookie));
#endif
return NULL;
}
diff --git a/mm/truncate.c b/mm/truncate.c
index e13f22e..3e9829f 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -398,11 +398,12 @@ invalidate_complete_page2(struct address_space *mapping, struct page *page)
if (page_has_private(page) && !try_to_release_page(page, GFP_KERNEL))
return 0;
+ clear_page_mlock(page);
+
spin_lock_irq(&mapping->tree_lock);
if (PageDirty(page))
goto failed;
- clear_page_mlock(page);
BUG_ON(page_has_private(page));
__delete_from_page_cache(page);
spin_unlock_irq(&mapping->tree_lock);
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 43b44db..bdb7004 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -256,7 +256,7 @@ struct vmap_area {
struct rb_node rb_node; /* address sorted rbtree */
struct list_head list; /* address sorted list */
struct list_head purge_list; /* "lazy purge" list */
- void *private;
+ struct vm_struct *vm;
struct rcu_head rcu_head;
};
@@ -1174,9 +1174,10 @@ void __init vmalloc_init(void)
/* Import existing vmlist entries. */
for (tmp = vmlist; tmp; tmp = tmp->next) {
va = kzalloc(sizeof(struct vmap_area), GFP_NOWAIT);
- va->flags = tmp->flags | VM_VM_AREA;
+ va->flags = VM_VM_AREA;
va->va_start = (unsigned long)tmp->addr;
va->va_end = va->va_start + tmp->size;
+ va->vm = tmp;
__insert_vmap_area(va);
}
@@ -1274,7 +1275,7 @@ static void setup_vmalloc_vm(struct vm_struct *vm, struct vmap_area *va,
vm->addr = (void *)va->va_start;
vm->size = va->va_end - va->va_start;
vm->caller = caller;
- va->private = vm;
+ va->vm = vm;
va->flags |= VM_VM_AREA;
}
@@ -1397,7 +1398,7 @@ static struct vm_struct *find_vm_area(const void *addr)
va = find_vmap_area((unsigned long)addr);
if (va && va->flags & VM_VM_AREA)
- return va->private;
+ return va->vm;
return NULL;
}
@@ -1416,7 +1417,7 @@ struct vm_struct *remove_vm_area(const void *addr)
va = find_vmap_area((unsigned long)addr);
if (va && va->flags & VM_VM_AREA) {
- struct vm_struct *vm = va->private;
+ struct vm_struct *vm = va->vm;
if (!(vm->flags & VM_UNLIST)) {
struct vm_struct *tmp, **p;
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 6072d74..5326f98 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -248,35 +248,66 @@ unsigned long shrink_slab(struct shrink_control *shrink,
list_for_each_entry(shrinker, &shrinker_list, list) {
unsigned long long delta;
- unsigned long total_scan;
- unsigned long max_pass;
+ long total_scan;
+ long max_pass;
+ int shrink_ret = 0;
+ long nr;
+ long new_nr;
max_pass = do_shrinker_shrink(shrinker, shrink, 0);
+ if (max_pass <= 0)
+ continue;
+
+ /*
+ * copy the current shrinker scan count into a local variable
+ * and zero it so that other concurrent shrinker invocations
+ * don't also do this scanning work.
+ */
+ do {
+ nr = shrinker->nr;
+ } while (cmpxchg(&shrinker->nr, nr, 0) != nr);
+
+ total_scan = nr;
delta = (4 * nr_pages_scanned) / shrinker->seeks;
delta *= max_pass;
do_div(delta, lru_pages + 1);
- shrinker->nr += delta;
- if (shrinker->nr < 0) {
+ total_scan += delta;
+ if (total_scan < 0) {
printk(KERN_ERR "shrink_slab: %pF negative objects to "
"delete nr=%ld\n",
- shrinker->shrink, shrinker->nr);
- shrinker->nr = max_pass;
+ shrinker->shrink, total_scan);
+ total_scan = max_pass;
}
/*
+ * We need to avoid excessive windup on filesystem shrinkers
+ * due to large numbers of GFP_NOFS allocations causing the
+ * shrinkers to return -1 all the time. This results in a large
+ * nr being built up so when a shrink that can do some work
+ * comes along it empties the entire cache due to nr >>>
+ * max_pass. This is bad for sustaining a working set in
+ * memory.
+ *
+ * Hence only allow the shrinker to scan the entire cache when
+ * a large delta change is calculated directly.
+ */
+ if (delta < max_pass / 4)
+ total_scan = min(total_scan, max_pass / 2);
+
+ /*
* Avoid risking looping forever due to too large nr value:
* never try to free more than twice the estimate number of
* freeable entries.
*/
- if (shrinker->nr > max_pass * 2)
- shrinker->nr = max_pass * 2;
+ if (total_scan > max_pass * 2)
+ total_scan = max_pass * 2;
- total_scan = shrinker->nr;
- shrinker->nr = 0;
+ trace_mm_shrink_slab_start(shrinker, shrink, nr,
+ nr_pages_scanned, lru_pages,
+ max_pass, delta, total_scan);
while (total_scan >= SHRINK_BATCH) {
long this_scan = SHRINK_BATCH;
- int shrink_ret;
int nr_before;
nr_before = do_shrinker_shrink(shrinker, shrink, 0);
@@ -292,7 +323,19 @@ unsigned long shrink_slab(struct shrink_control *shrink,
cond_resched();
}
- shrinker->nr += total_scan;
+ /*
+ * move the unused scan count back into the shrinker in a
+ * manner that handles concurrent updates. If we exhausted the
+ * scan, there is no need to do an update.
+ */
+ do {
+ nr = shrinker->nr;
+ new_nr = total_scan + nr;
+ if (total_scan <= 0)
+ break;
+ } while (cmpxchg(&shrinker->nr, nr, new_nr) != nr);
+
+ trace_mm_shrink_slab_end(shrinker, shrink_ret, nr, new_nr);
}
up_read(&shrinker_rwsem);
out:
@@ -665,7 +708,7 @@ static enum page_references page_check_references(struct page *page,
return PAGEREF_RECLAIM;
if (referenced_ptes) {
- if (PageAnon(page))
+ if (PageSwapBacked(page))
return PAGEREF_ACTIVATE;
/*
* All mapped pages start out with page table
@@ -683,7 +726,13 @@ static enum page_references page_check_references(struct page *page,
*/
SetPageReferenced(page);
- if (referenced_page)
+ if (referenced_page || referenced_ptes > 1)
+ return PAGEREF_ACTIVATE;
+
+ /*
+ * Activate file-backed executable pages after first usage.
+ */
+ if (vm_flags & VM_EXEC)
return PAGEREF_ACTIVATE;
return PAGEREF_KEEP;
@@ -972,23 +1021,27 @@ keep_lumpy:
*
* returns 0 on success, -ve errno on failure.
*/
-int __isolate_lru_page(struct page *page, int mode, int file)
+int __isolate_lru_page(struct page *page, isolate_mode_t mode, int file)
{
+ bool all_lru_mode;
int ret = -EINVAL;
/* Only take pages on the LRU. */
if (!PageLRU(page))
return ret;
+ all_lru_mode = (mode & (ISOLATE_ACTIVE|ISOLATE_INACTIVE)) ==
+ (ISOLATE_ACTIVE|ISOLATE_INACTIVE);
+
/*
* When checking the active state, we need to be sure we are
* dealing with comparible boolean values. Take the logical not
* of each.
*/
- if (mode != ISOLATE_BOTH && (!PageActive(page) != !mode))
+ if (!all_lru_mode && !PageActive(page) != !(mode & ISOLATE_ACTIVE))
return ret;
- if (mode != ISOLATE_BOTH && page_is_file_cache(page) != file)
+ if (!all_lru_mode && !!page_is_file_cache(page) != file)
return ret;
/*
@@ -1001,6 +1054,43 @@ int __isolate_lru_page(struct page *page, int mode, int file)
ret = -EBUSY;
+ /*
+ * To minimise LRU disruption, the caller can indicate that it only
+ * wants to isolate pages it will be able to operate on without
+ * blocking - clean pages for the most part.
+ *
+ * ISOLATE_CLEAN means that only clean pages should be isolated. This
+ * is used by reclaim when it is cannot write to backing storage
+ *
+ * ISOLATE_ASYNC_MIGRATE is used to indicate that it only wants to pages
+ * that it is possible to migrate without blocking
+ */
+ if (mode & (ISOLATE_CLEAN|ISOLATE_ASYNC_MIGRATE)) {
+ /* All the caller can do on PageWriteback is block */
+ if (PageWriteback(page))
+ return ret;
+
+ if (PageDirty(page)) {
+ struct address_space *mapping;
+
+ /* ISOLATE_CLEAN means only clean pages */
+ if (mode & ISOLATE_CLEAN)
+ return ret;
+
+ /*
+ * Only pages without mappings or that have a
+ * ->migratepage callback are possible to migrate
+ * without blocking
+ */
+ mapping = page_mapping(page);
+ if (mapping && !mapping->a_ops->migratepage)
+ return ret;
+ }
+ }
+
+ if ((mode & ISOLATE_UNMAPPED) && page_mapped(page))
+ return ret;
+
if (likely(get_page_unless_zero(page))) {
/*
* Be careful not to clear PageLRU until after we're
@@ -1036,7 +1126,8 @@ int __isolate_lru_page(struct page *page, int mode, int file)
*/
static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
struct list_head *src, struct list_head *dst,
- unsigned long *scanned, int order, int mode, int file)
+ unsigned long *scanned, int order, isolate_mode_t mode,
+ int file)
{
unsigned long nr_taken = 0;
unsigned long nr_lumpy_taken = 0;
@@ -1111,7 +1202,7 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
* anon page which don't already have a swap slot is
* pointless.
*/
- if (nr_swap_pages <= 0 && PageAnon(cursor_page) &&
+ if (nr_swap_pages <= 0 && PageSwapBacked(cursor_page) &&
!PageSwapCache(cursor_page))
break;
@@ -1161,8 +1252,8 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
static unsigned long isolate_pages_global(unsigned long nr,
struct list_head *dst,
unsigned long *scanned, int order,
- int mode, struct zone *z,
- int active, int file)
+ isolate_mode_t mode,
+ struct zone *z, int active, int file)
{
int lru = LRU_BASE;
if (active)
@@ -1408,6 +1499,7 @@ shrink_inactive_list(unsigned long nr_to_scan, struct zone *zone,
unsigned long nr_taken;
unsigned long nr_anon;
unsigned long nr_file;
+ isolate_mode_t reclaim_mode = ISOLATE_INACTIVE;
while (unlikely(too_many_isolated(zone, file, sc))) {
congestion_wait(BLK_RW_ASYNC, HZ/10);
@@ -1418,15 +1510,21 @@ shrink_inactive_list(unsigned long nr_to_scan, struct zone *zone,
}
set_reclaim_mode(priority, sc, false);
+ if (sc->reclaim_mode & RECLAIM_MODE_LUMPYRECLAIM)
+ reclaim_mode |= ISOLATE_ACTIVE;
+
lru_add_drain();
+
+ if (!sc->may_unmap)
+ reclaim_mode |= ISOLATE_UNMAPPED;
+ if (!sc->may_writepage)
+ reclaim_mode |= ISOLATE_CLEAN;
+
spin_lock_irq(&zone->lru_lock);
if (scanning_global_lru(sc)) {
- nr_taken = isolate_pages_global(nr_to_scan,
- &page_list, &nr_scanned, sc->order,
- sc->reclaim_mode & RECLAIM_MODE_LUMPYRECLAIM ?
- ISOLATE_BOTH : ISOLATE_INACTIVE,
- zone, 0, file);
+ nr_taken = isolate_pages_global(nr_to_scan, &page_list,
+ &nr_scanned, sc->order, reclaim_mode, zone, 0, file);
zone->pages_scanned += nr_scanned;
if (current_is_kswapd())
__count_zone_vm_events(PGSCAN_KSWAPD, zone,
@@ -1435,12 +1533,9 @@ shrink_inactive_list(unsigned long nr_to_scan, struct zone *zone,
__count_zone_vm_events(PGSCAN_DIRECT, zone,
nr_scanned);
} else {
- nr_taken = mem_cgroup_isolate_pages(nr_to_scan,
- &page_list, &nr_scanned, sc->order,
- sc->reclaim_mode & RECLAIM_MODE_LUMPYRECLAIM ?
- ISOLATE_BOTH : ISOLATE_INACTIVE,
- zone, sc->mem_cgroup,
- 0, file);
+ nr_taken = mem_cgroup_isolate_pages(nr_to_scan, &page_list,
+ &nr_scanned, sc->order, reclaim_mode, zone,
+ sc->mem_cgroup, 0, file);
/*
* mem_cgroup_isolate_pages() keeps track of
* scanned pages on its own.
@@ -1542,19 +1637,26 @@ static void shrink_active_list(unsigned long nr_pages, struct zone *zone,
struct page *page;
struct zone_reclaim_stat *reclaim_stat = get_reclaim_stat(zone, sc);
unsigned long nr_rotated = 0;
+ isolate_mode_t reclaim_mode = ISOLATE_ACTIVE;
lru_add_drain();
+
+ if (!sc->may_unmap)
+ reclaim_mode |= ISOLATE_UNMAPPED;
+ if (!sc->may_writepage)
+ reclaim_mode |= ISOLATE_CLEAN;
+
spin_lock_irq(&zone->lru_lock);
if (scanning_global_lru(sc)) {
nr_taken = isolate_pages_global(nr_pages, &l_hold,
&pgscanned, sc->order,
- ISOLATE_ACTIVE, zone,
+ reclaim_mode, zone,
1, file);
zone->pages_scanned += pgscanned;
} else {
nr_taken = mem_cgroup_isolate_pages(nr_pages, &l_hold,
&pgscanned, sc->order,
- ISOLATE_ACTIVE, zone,
+ reclaim_mode, zone,
sc->mem_cgroup, 1, file);
/*
* mem_cgroup_isolate_pages() keeps track of
@@ -1747,23 +1849,16 @@ static void get_scan_count(struct zone *zone, struct scan_control *sc,
u64 fraction[2], denominator;
enum lru_list l;
int noswap = 0;
- int force_scan = 0;
+ bool force_scan = false;
unsigned long nr_force_scan[2];
-
- anon = zone_nr_lru_pages(zone, sc, LRU_ACTIVE_ANON) +
- zone_nr_lru_pages(zone, sc, LRU_INACTIVE_ANON);
- file = zone_nr_lru_pages(zone, sc, LRU_ACTIVE_FILE) +
- zone_nr_lru_pages(zone, sc, LRU_INACTIVE_FILE);
-
- if (((anon + file) >> priority) < SWAP_CLUSTER_MAX) {
- /* kswapd does zone balancing and need to scan this zone */
- if (scanning_global_lru(sc) && current_is_kswapd())
- force_scan = 1;
- /* memcg may have small limit and need to avoid priority drop */
- if (!scanning_global_lru(sc))
- force_scan = 1;
- }
+ /* kswapd does zone balancing and needs to scan this zone */
+ if (scanning_global_lru(sc) && current_is_kswapd() &&
+ zone->all_unreclaimable)
+ force_scan = true;
+ /* memcg may have small limit and need to avoid priority drop */
+ if (!scanning_global_lru(sc))
+ force_scan = true;
/* If we have no swap space, do not bother scanning anon pages. */
if (!sc->may_swap || (nr_swap_pages <= 0)) {
@@ -1776,6 +1871,11 @@ static void get_scan_count(struct zone *zone, struct scan_control *sc,
goto out;
}
+ anon = zone_nr_lru_pages(zone, sc, LRU_ACTIVE_ANON) +
+ zone_nr_lru_pages(zone, sc, LRU_INACTIVE_ANON);
+ file = zone_nr_lru_pages(zone, sc, LRU_ACTIVE_FILE) +
+ zone_nr_lru_pages(zone, sc, LRU_INACTIVE_FILE);
+
if (scanning_global_lru(sc)) {
free = zone_page_state(zone, NR_FREE_PAGES);
/* If we have very few page cache pages,
@@ -1912,8 +2012,9 @@ static inline bool should_continue_reclaim(struct zone *zone,
* inactive lists are large enough, continue reclaiming
*/
pages_for_compaction = (2UL << sc->order);
- inactive_lru_pages = zone_nr_lru_pages(zone, sc, LRU_INACTIVE_ANON) +
- zone_nr_lru_pages(zone, sc, LRU_INACTIVE_FILE);
+ inactive_lru_pages = zone_nr_lru_pages(zone, sc, LRU_INACTIVE_FILE);
+ if (nr_swap_pages > 0)
+ inactive_lru_pages += zone_nr_lru_pages(zone, sc, LRU_INACTIVE_ANON);
if (sc->nr_reclaimed < pages_for_compaction &&
inactive_lru_pages > pages_for_compaction)
return true;
@@ -1985,6 +2086,42 @@ restart:
throttle_vm_writeout(sc->gfp_mask);
}
+/* Returns true if compaction should go ahead for a high-order request */
+static inline bool compaction_ready(struct zone *zone, struct scan_control *sc)
+{
+ unsigned long balance_gap, watermark;
+ bool watermark_ok;
+
+ /* Do not consider compaction for orders reclaim is meant to satisfy */
+ if (sc->order <= PAGE_ALLOC_COSTLY_ORDER)
+ return false;
+
+ /*
+ * Compaction takes time to run and there are potentially other
+ * callers using the pages just freed. Continue reclaiming until
+ * there is a buffer of free pages available to give compaction
+ * a reasonable chance of completing and allocating the page
+ */
+ balance_gap = min(low_wmark_pages(zone),
+ (zone->present_pages + KSWAPD_ZONE_BALANCE_GAP_RATIO-1) /
+ KSWAPD_ZONE_BALANCE_GAP_RATIO);
+ watermark = high_wmark_pages(zone) + balance_gap + (2UL << sc->order);
+ watermark_ok = zone_watermark_ok_safe(zone, 0, watermark, 0, 0);
+
+ /*
+ * If compaction is deferred, reclaim up to a point where
+ * compaction will have a chance of success when re-enabled
+ */
+ if (compaction_deferred(zone))
+ return watermark_ok;
+
+ /* If compaction is not ready to start, keep reclaiming */
+ if (!compaction_suitable(zone, sc->order))
+ return false;
+
+ return watermark_ok;
+}
+
/*
* This is the direct reclaim path, for page-allocating processes. We only
* try to reclaim pages from zones which will satisfy the caller's allocation
@@ -2000,14 +2137,20 @@ restart:
*
* If a zone is deemed to be full of pinned pages then just give it a light
* scan then give up on it.
+ *
+ * This function returns true if a zone is being reclaimed for a costly
+ * high-order allocation and compaction is ready to begin. This indicates to
+ * the caller that it should consider retrying the allocation instead of
+ * further reclaim.
*/
-static void shrink_zones(int priority, struct zonelist *zonelist,
+static bool shrink_zones(int priority, struct zonelist *zonelist,
struct scan_control *sc)
{
struct zoneref *z;
struct zone *zone;
unsigned long nr_soft_reclaimed;
unsigned long nr_soft_scanned;
+ bool aborted_reclaim = false;
for_each_zone_zonelist_nodemask(zone, z, zonelist,
gfp_zone(sc->gfp_mask), sc->nodemask) {
@@ -2022,6 +2165,21 @@ static void shrink_zones(int priority, struct zonelist *zonelist,
continue;
if (zone->all_unreclaimable && priority != DEF_PRIORITY)
continue; /* Let kswapd poll it */
+ if (COMPACTION_BUILD) {
+ /*
+ * If we already have plenty of memory free for
+ * compaction in this zone, don't free any more.
+ * Even though compaction is invoked for any
+ * non-zero order, only frequent costly order
+ * reclamation is disruptive enough to become a
+ * noticable problem, like transparent huge page
+ * allocations.
+ */
+ if (compaction_ready(zone, sc)) {
+ aborted_reclaim = true;
+ continue;
+ }
+ }
/*
* This steals pages from memory cgroups over softlimit
* and returns the number of reclaimed pages and
@@ -2039,6 +2197,8 @@ static void shrink_zones(int priority, struct zonelist *zonelist,
shrink_zone(priority, zone, sc);
}
+
+ return aborted_reclaim;
}
static bool zone_reclaimable(struct zone *zone)
@@ -2092,8 +2252,8 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist,
struct zoneref *z;
struct zone *zone;
unsigned long writeback_threshold;
+ bool aborted_reclaim;
- get_mems_allowed();
delayacct_freepages_start();
if (scanning_global_lru(sc))
@@ -2103,7 +2263,8 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist,
sc->nr_scanned = 0;
if (!priority)
disable_swap_token(sc->mem_cgroup);
- shrink_zones(priority, zonelist, sc);
+ aborted_reclaim = shrink_zones(priority, zonelist, sc);
+
/*
* Don't shrink slabs when reclaiming memory from
* over limit cgroups
@@ -2155,7 +2316,6 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist,
out:
delayacct_freepages_end();
- put_mems_allowed();
if (sc->nr_reclaimed)
return sc->nr_reclaimed;
@@ -2168,6 +2328,10 @@ out:
if (oom_killer_disabled)
return 0;
+ /* Aborted reclaim to try compaction? don't OOM, then */
+ if (aborted_reclaim)
+ return 1;
+
/* top priority shrink_zones still had more to do? don't OOM, then */
if (scanning_global_lru(sc) && !all_unreclaimable(zonelist, sc))
return 1;
@@ -2459,6 +2623,9 @@ loop_again:
high_wmark_pages(zone), 0, 0)) {
end_zone = i;
break;
+ } else {
+ /* If balanced, clear the congested flag */
+ zone_clear_flag(zone, ZONE_CONGESTED);
}
}
if (i < 0)
@@ -2695,7 +2862,10 @@ static void kswapd_try_to_sleep(pg_data_t *pgdat, int order, int classzone_idx)
* them before going back to sleep.
*/
set_pgdat_percpu_threshold(pgdat, calculate_normal_threshold);
- schedule();
+
+ if (!kthread_should_stop())
+ schedule();
+
set_pgdat_percpu_threshold(pgdat, calculate_pressure_threshold);
} else {
if (remaining)
@@ -2722,7 +2892,9 @@ static void kswapd_try_to_sleep(pg_data_t *pgdat, int order, int classzone_idx)
static int kswapd(void *p)
{
unsigned long order, new_order;
+ unsigned balanced_order;
int classzone_idx, new_classzone_idx;
+ int balanced_classzone_idx;
pg_data_t *pgdat = (pg_data_t*)p;
struct task_struct *tsk = current;
@@ -2753,7 +2925,9 @@ static int kswapd(void *p)
set_freezable();
order = new_order = 0;
+ balanced_order = 0;
classzone_idx = new_classzone_idx = pgdat->nr_zones - 1;
+ balanced_classzone_idx = classzone_idx;
for ( ; ; ) {
int ret;
@@ -2762,7 +2936,8 @@ static int kswapd(void *p)
* new request of a similar or harder type will succeed soon
* so consider going to sleep on the basis we reclaimed at
*/
- if (classzone_idx >= new_classzone_idx && order == new_order) {
+ if (balanced_classzone_idx >= new_classzone_idx &&
+ balanced_order == new_order) {
new_order = pgdat->kswapd_max_order;
new_classzone_idx = pgdat->classzone_idx;
pgdat->kswapd_max_order = 0;
@@ -2777,9 +2952,12 @@ static int kswapd(void *p)
order = new_order;
classzone_idx = new_classzone_idx;
} else {
- kswapd_try_to_sleep(pgdat, order, classzone_idx);
+ kswapd_try_to_sleep(pgdat, balanced_order,
+ balanced_classzone_idx);
order = pgdat->kswapd_max_order;
classzone_idx = pgdat->classzone_idx;
+ new_order = order;
+ new_classzone_idx = classzone_idx;
pgdat->kswapd_max_order = 0;
pgdat->classzone_idx = pgdat->nr_zones - 1;
}
@@ -2794,7 +2972,9 @@ static int kswapd(void *p)
*/
if (!ret) {
trace_mm_vmscan_kswapd_wake(pgdat->node_id, order);
- order = balance_pgdat(pgdat, order, &classzone_idx);
+ balanced_classzone_idx = classzone_idx;
+ balanced_order = balance_pgdat(pgdat, order,
+ &balanced_classzone_idx);
}
}
return 0;
@@ -2952,14 +3132,17 @@ int kswapd_run(int nid)
}
/*
- * Called by memory hotplug when all memory in a node is offlined.
+ * Called by memory hotplug when all memory in a node is offlined. Caller must
+ * hold lock_memory_hotplug().
*/
void kswapd_stop(int nid)
{
struct task_struct *kswapd = NODE_DATA(nid)->kswapd;
- if (kswapd)
+ if (kswapd) {
kthread_stop(kswapd);
+ NODE_DATA(nid)->kswapd = NULL;
+ }
}
static int __init kswapd_init(void)
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 20c18b7..6559013 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -78,7 +78,7 @@ void vm_events_fold_cpu(int cpu)
*
* vm_stat contains the global counters
*/
-atomic_long_t vm_stat[NR_VM_ZONE_STAT_ITEMS];
+atomic_long_t vm_stat[NR_VM_ZONE_STAT_ITEMS] __cacheline_aligned_in_smp;
EXPORT_SYMBOL(vm_stat);
#ifdef CONFIG_SMP
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c
index 27263fb..c177f9e 100644
--- a/net/8021q/vlan_core.c
+++ b/net/8021q/vlan_core.c
@@ -106,7 +106,6 @@ static struct sk_buff *vlan_reorder_header(struct sk_buff *skb)
return NULL;
memmove(skb->data - ETH_HLEN, skb->data - VLAN_ETH_HLEN, 2 * ETH_ALEN);
skb->mac_header += VLAN_HLEN;
- skb_reset_mac_len(skb);
return skb;
}
@@ -173,6 +172,8 @@ struct sk_buff *vlan_untag(struct sk_buff *skb)
skb_reset_network_header(skb);
skb_reset_transport_header(skb);
+ skb_reset_mac_len(skb);
+
return skb;
err_free:
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 5b4f51d..d548456 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -154,7 +154,7 @@ static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb,
skb = __vlan_hwaccel_put_tag(skb, vlan_tci);
}
- skb_set_dev(skb, vlan_dev_info(dev)->real_dev);
+ skb->dev = vlan_dev_info(dev)->real_dev;
len = skb->len;
ret = dev_queue_xmit(skb);
diff --git a/net/atm/common.c b/net/atm/common.c
index 22b963d..cc859ad 100644
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -784,6 +784,7 @@ int vcc_getsockopt(struct socket *sock, int level, int optname,
if (!vcc->dev || !test_bit(ATM_VF_ADDR, &vcc->flags))
return -ENOTCONN;
+ memset(&pvc, 0, sizeof(pvc));
pvc.sap_family = AF_ATMPVC;
pvc.sap_addr.itf = vcc->dev->number;
pvc.sap_addr.vpi = vcc->vpi;
diff --git a/net/atm/pvc.c b/net/atm/pvc.c
index 437ee70..db0dd47 100644
--- a/net/atm/pvc.c
+++ b/net/atm/pvc.c
@@ -94,6 +94,7 @@ static int pvc_getname(struct socket *sock, struct sockaddr *sockaddr,
return -ENOTCONN;
*sockaddr_len = sizeof(struct sockaddr_atmpvc);
addr = (struct sockaddr_atmpvc *)sockaddr;
+ memset(addr, 0, sizeof(*addr));
addr->sap_family = AF_ATMPVC;
addr->sap_addr.itf = vcc->dev->number;
addr->sap_addr.vpi = vcc->vpi;
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index ff02cf5..ce1424a 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -374,6 +374,7 @@ static int hci_sock_getname(struct socket *sock, struct sockaddr *addr, int *add
*addr_len = sizeof(*haddr);
haddr->hci_family = AF_BLUETOOTH;
haddr->hci_dev = hdev->id;
+ haddr->hci_channel= 0;
release_sock(sk);
return 0;
@@ -586,6 +587,7 @@ static int hci_sock_setsockopt(struct socket *sock, int level, int optname, char
{
struct hci_filter *f = &hci_pi(sk)->filter;
+ memset(&uf, 0, sizeof(uf));
uf.type_mask = f->type_mask;
uf.opcode = f->opcode;
uf.event_mask[0] = *((u32 *) f->event_mask + 0);
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 61f1f62..785e84f 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -290,6 +290,7 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l
BT_DBG("sock %p, sk %p", sock, sk);
+ memset(la, 0, sizeof(struct sockaddr_l2));
addr->sa_family = AF_BLUETOOTH;
*len = sizeof(struct sockaddr_l2);
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index b02f0d4..927f418 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -544,6 +544,7 @@ static int rfcomm_sock_getname(struct socket *sock, struct sockaddr *addr, int *
BT_DBG("sock %p, sk %p", sock, sk);
+ memset(sa, 0, sizeof(*sa));
sa->rc_family = AF_BLUETOOTH;
sa->rc_channel = rfcomm_pi(sk)->channel;
if (peer)
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index c258796..bc1eb56 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -471,7 +471,7 @@ static int rfcomm_get_dev_list(void __user *arg)
size = sizeof(*dl) + dev_num * sizeof(*di);
- dl = kmalloc(size, GFP_KERNEL);
+ dl = kzalloc(size, GFP_KERNEL);
if (!dl)
return -ENOMEM;
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 4490873..eae6a4e 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -241,6 +241,7 @@ int br_add_bridge(struct net *net, const char *name)
return -ENOMEM;
dev_net_set(dev, net);
+ dev->rtnl_link_ops = &br_link_ops;
res = register_netdev(dev);
if (res)
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 2c16055..71861a9 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -203,7 +203,7 @@ static int br_validate(struct nlattr *tb[], struct nlattr *data[])
return 0;
}
-static struct rtnl_link_ops br_link_ops __read_mostly = {
+struct rtnl_link_ops br_link_ops __read_mostly = {
.kind = "bridge",
.priv_size = sizeof(struct net_bridge),
.setup = br_dev_setup,
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 1ca1b1c..7c1f3a0 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -529,6 +529,7 @@ extern int (*br_fdb_test_addr_hook)(struct net_device *dev, unsigned char *addr)
#endif
/* br_netlink.c */
+extern struct rtnl_link_ops br_link_ops;
extern int br_netlink_init(void);
extern void br_netlink_fini(void);
extern void br_ifinfo_notify(int event, struct net_bridge_port *port);
diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c
index 5ba4366..804e50f 100644
--- a/net/caif/caif_dev.c
+++ b/net/caif/caif_dev.c
@@ -424,9 +424,9 @@ static int __init caif_device_init(void)
static void __exit caif_device_exit(void)
{
- unregister_pernet_subsys(&caif_net_ops);
unregister_netdevice_notifier(&caif_device_notifier);
dev_remove_pack(&caif_packet_type);
+ unregister_pernet_subsys(&caif_net_ops);
}
module_init(caif_device_init);
diff --git a/net/core/dev.c b/net/core/dev.c
index f134f88..5b84eaf 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1045,6 +1045,8 @@ rollback:
*/
int dev_set_alias(struct net_device *dev, const char *alias, size_t len)
{
+ char *new_ifalias;
+
ASSERT_RTNL();
if (len >= IFALIASZ)
@@ -1058,9 +1060,10 @@ int dev_set_alias(struct net_device *dev, const char *alias, size_t len)
return 0;
}
- dev->ifalias = krealloc(dev->ifalias, len + 1, GFP_KERNEL);
- if (!dev->ifalias)
+ new_ifalias = krealloc(dev->ifalias, len + 1, GFP_KERNEL);
+ if (!new_ifalias)
return -ENOMEM;
+ dev->ifalias = new_ifalias;
strlcpy(dev->ifalias, alias, len+1);
return len;
@@ -1163,6 +1166,7 @@ static int __dev_open(struct net_device *dev)
net_dmaengine_get();
dev_set_rx_mode(dev);
dev_activate(dev);
+ add_device_randomness(dev->dev_addr, dev->addr_len);
}
return ret;
@@ -1406,14 +1410,34 @@ EXPORT_SYMBOL(register_netdevice_notifier);
* register_netdevice_notifier(). The notifier is unlinked into the
* kernel structures and may then be reused. A negative errno code
* is returned on a failure.
+ *
+ * After unregistering unregister and down device events are synthesized
+ * for all devices on the device list to the removed notifier to remove
+ * the need for special case cleanup code.
*/
int unregister_netdevice_notifier(struct notifier_block *nb)
{
+ struct net_device *dev;
+ struct net *net;
int err;
rtnl_lock();
err = raw_notifier_chain_unregister(&netdev_chain, nb);
+ if (err)
+ goto unlock;
+
+ for_each_net(net) {
+ for_each_netdev(net, dev) {
+ if (dev->flags & IFF_UP) {
+ nb->notifier_call(nb, NETDEV_GOING_DOWN, dev);
+ nb->notifier_call(nb, NETDEV_DOWN, dev);
+ }
+ nb->notifier_call(nb, NETDEV_UNREGISTER, dev);
+ nb->notifier_call(nb, NETDEV_UNREGISTER_BATCH, dev);
+ }
+ }
+unlock:
rtnl_unlock();
return err;
}
@@ -1513,10 +1537,14 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb)
kfree_skb(skb);
return NET_RX_DROP;
}
- skb_set_dev(skb, dev);
+ skb->dev = dev;
+ skb_dst_drop(skb);
skb->tstamp.tv64 = 0;
skb->pkt_type = PACKET_HOST;
skb->protocol = eth_type_trans(skb, dev);
+ skb->mark = 0;
+ secpath_reset(skb);
+ nf_reset(skb);
return netif_rx(skb);
}
EXPORT_SYMBOL_GPL(dev_forward_skb);
@@ -1771,36 +1799,6 @@ void netif_device_attach(struct net_device *dev)
}
EXPORT_SYMBOL(netif_device_attach);
-/**
- * skb_dev_set -- assign a new device to a buffer
- * @skb: buffer for the new device
- * @dev: network device
- *
- * If an skb is owned by a device already, we have to reset
- * all data private to the namespace a device belongs to
- * before assigning it a new device.
- */
-#ifdef CONFIG_NET_NS
-void skb_set_dev(struct sk_buff *skb, struct net_device *dev)
-{
- skb_dst_drop(skb);
- if (skb->dev && !net_eq(dev_net(skb->dev), dev_net(dev))) {
- secpath_reset(skb);
- nf_reset(skb);
- skb_init_secmark(skb);
- skb->mark = 0;
- skb->priority = 0;
- skb->nf_trace = 0;
- skb->ipvs_property = 0;
-#ifdef CONFIG_NET_SCHED
- skb->tc_index = 0;
-#endif
- }
- skb->dev = dev;
-}
-EXPORT_SYMBOL(skb_set_dev);
-#endif /* CONFIG_NET_NS */
-
/*
* Invalidate hardware checksum when packet is to be mangled, and
* complete checksum manually on outgoing path.
@@ -2040,7 +2038,8 @@ static bool can_checksum_protocol(unsigned long features, __be16 protocol)
static u32 harmonize_features(struct sk_buff *skb, __be16 protocol, u32 features)
{
- if (!can_checksum_protocol(features, protocol)) {
+ if (skb->ip_summed != CHECKSUM_NONE &&
+ !can_checksum_protocol(features, protocol)) {
features &= ~NETIF_F_ALL_CSUM;
features &= ~NETIF_F_SG;
} else if (illegal_highdma(skb->dev, skb)) {
@@ -2055,6 +2054,9 @@ u32 netif_skb_features(struct sk_buff *skb)
__be16 protocol = skb->protocol;
u32 features = skb->dev->features;
+ if (skb_shinfo(skb)->gso_segs > skb->dev->gso_max_segs)
+ features &= ~NETIF_F_GSO_MASK;
+
if (protocol == htons(ETH_P_8021Q)) {
struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;
protocol = veh->h_vlan_encapsulated_proto;
@@ -2558,16 +2560,17 @@ __u32 __skb_get_rxhash(struct sk_buff *skb)
poff = proto_ports_offset(ip_proto);
if (poff >= 0) {
nhoff += ihl * 4 + poff;
- if (pskb_may_pull(skb, nhoff + 4)) {
+ if (pskb_may_pull(skb, nhoff + 4))
ports.v32 = * (__force u32 *) (skb->data + nhoff);
- if (ports.v16[1] < ports.v16[0])
- swap(ports.v16[0], ports.v16[1]);
- }
}
/* get a consistent hash (same value on both flow directions) */
- if (addr2 < addr1)
+ if (addr2 < addr1 ||
+ (addr2 == addr1 &&
+ ports.v16[1] < ports.v16[0])) {
swap(addr1, addr2);
+ swap(ports.v16[0], ports.v16[1]);
+ }
hash = jhash_3words(addr1, addr2, ports.v32, hashrnd);
if (!hash)
@@ -4736,6 +4739,7 @@ int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa)
err = ops->ndo_set_mac_address(dev, sa);
if (!err)
call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
+ add_device_randomness(dev->dev_addr, dev->addr_len);
return err;
}
EXPORT_SYMBOL(dev_set_mac_address);
@@ -5513,6 +5517,7 @@ int register_netdevice(struct net_device *dev)
dev_init_scheduler(dev);
dev_hold(dev);
list_netdevice(dev);
+ add_device_randomness(dev->dev_addr, dev->addr_len);
/* Notify protocols, that a new device appeared. */
ret = call_netdevice_notifiers(NETDEV_REGISTER, dev);
@@ -5873,6 +5878,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
dev_net_set(dev, &init_net);
dev->gso_max_size = GSO_MAX_SIZE;
+ dev->gso_max_segs = GSO_MAX_SEGS;
INIT_LIST_HEAD(&dev->ethtool_ntuple_list.list);
dev->ethtool_ntuple_list.count = 0;
@@ -6256,7 +6262,8 @@ static struct hlist_head *netdev_create_hash(void)
/* Initialize per network namespace state */
static int __net_init netdev_init(struct net *net)
{
- INIT_LIST_HEAD(&net->dev_base_head);
+ if (net != &init_net)
+ INIT_LIST_HEAD(&net->dev_base_head);
net->dev_name_head = netdev_create_hash();
if (net->dev_name_head == NULL)
diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c
index 7f36b38..b856f87 100644
--- a/net/core/drop_monitor.c
+++ b/net/core/drop_monitor.c
@@ -33,22 +33,19 @@
#define TRACE_ON 1
#define TRACE_OFF 0
-static void send_dm_alert(struct work_struct *unused);
-
-
/*
* Globals, our netlink socket pointer
* and the work handle that will send up
* netlink alerts
*/
static int trace_state = TRACE_OFF;
-static DEFINE_SPINLOCK(trace_state_lock);
+static DEFINE_MUTEX(trace_state_mutex);
struct per_cpu_dm_data {
- struct work_struct dm_alert_work;
- struct sk_buff *skb;
- atomic_t dm_hit_count;
- struct timer_list send_timer;
+ spinlock_t lock;
+ struct sk_buff *skb;
+ struct work_struct dm_alert_work;
+ struct timer_list send_timer;
};
struct dm_hw_stat_delta {
@@ -74,56 +71,59 @@ static int dm_delay = 1;
static unsigned long dm_hw_check_delta = 2*HZ;
static LIST_HEAD(hw_stats_list);
-static void reset_per_cpu_data(struct per_cpu_dm_data *data)
+static struct sk_buff *reset_per_cpu_data(struct per_cpu_dm_data *data)
{
size_t al;
struct net_dm_alert_msg *msg;
struct nlattr *nla;
+ struct sk_buff *skb;
+ unsigned long flags;
al = sizeof(struct net_dm_alert_msg);
al += dm_hit_limit * sizeof(struct net_dm_drop_point);
al += sizeof(struct nlattr);
- data->skb = genlmsg_new(al, GFP_KERNEL);
- genlmsg_put(data->skb, 0, 0, &net_drop_monitor_family,
- 0, NET_DM_CMD_ALERT);
- nla = nla_reserve(data->skb, NLA_UNSPEC, sizeof(struct net_dm_alert_msg));
- msg = nla_data(nla);
- memset(msg, 0, al);
- atomic_set(&data->dm_hit_count, dm_hit_limit);
+ skb = genlmsg_new(al, GFP_KERNEL);
+
+ if (skb) {
+ genlmsg_put(skb, 0, 0, &net_drop_monitor_family,
+ 0, NET_DM_CMD_ALERT);
+ nla = nla_reserve(skb, NLA_UNSPEC,
+ sizeof(struct net_dm_alert_msg));
+ msg = nla_data(nla);
+ memset(msg, 0, al);
+ } else {
+ mod_timer(&data->send_timer, jiffies + HZ / 10);
+ }
+
+ spin_lock_irqsave(&data->lock, flags);
+ swap(data->skb, skb);
+ spin_unlock_irqrestore(&data->lock, flags);
+
+ return skb;
}
-static void send_dm_alert(struct work_struct *unused)
+static void send_dm_alert(struct work_struct *work)
{
struct sk_buff *skb;
- struct per_cpu_dm_data *data = &__get_cpu_var(dm_cpu_data);
+ struct per_cpu_dm_data *data;
- /*
- * Grab the skb we're about to send
- */
- skb = data->skb;
+ data = container_of(work, struct per_cpu_dm_data, dm_alert_work);
- /*
- * Replace it with a new one
- */
- reset_per_cpu_data(data);
-
- /*
- * Ship it!
- */
- genlmsg_multicast(skb, 0, NET_DM_GRP_ALERT, GFP_KERNEL);
+ skb = reset_per_cpu_data(data);
+ if (skb)
+ genlmsg_multicast(skb, 0, NET_DM_GRP_ALERT, GFP_KERNEL);
}
/*
* This is the timer function to delay the sending of an alert
* in the event that more drops will arrive during the
- * hysteresis period. Note that it operates under the timer interrupt
- * so we don't need to disable preemption here
+ * hysteresis period.
*/
-static void sched_send_work(unsigned long unused)
+static void sched_send_work(unsigned long _data)
{
- struct per_cpu_dm_data *data = &__get_cpu_var(dm_cpu_data);
+ struct per_cpu_dm_data *data = (struct per_cpu_dm_data *)_data;
schedule_work(&data->dm_alert_work);
}
@@ -134,17 +134,19 @@ static void trace_drop_common(struct sk_buff *skb, void *location)
struct nlmsghdr *nlh;
struct nlattr *nla;
int i;
- struct per_cpu_dm_data *data = &__get_cpu_var(dm_cpu_data);
+ struct sk_buff *dskb;
+ struct per_cpu_dm_data *data;
+ unsigned long flags;
+ local_irq_save(flags);
+ data = &__get_cpu_var(dm_cpu_data);
+ spin_lock(&data->lock);
+ dskb = data->skb;
- if (!atomic_add_unless(&data->dm_hit_count, -1, 0)) {
- /*
- * we're already at zero, discard this hit
- */
+ if (!dskb)
goto out;
- }
- nlh = (struct nlmsghdr *)data->skb->data;
+ nlh = (struct nlmsghdr *)dskb->data;
nla = genlmsg_data(nlmsg_data(nlh));
msg = nla_data(nla);
for (i = 0; i < msg->entries; i++) {
@@ -153,11 +155,12 @@ static void trace_drop_common(struct sk_buff *skb, void *location)
goto out;
}
}
-
+ if (msg->entries == dm_hit_limit)
+ goto out;
/*
* We need to create a new entry
*/
- __nla_reserve_nohdr(data->skb, sizeof(struct net_dm_drop_point));
+ __nla_reserve_nohdr(dskb, sizeof(struct net_dm_drop_point));
nla->nla_len += NLA_ALIGN(sizeof(struct net_dm_drop_point));
memcpy(msg->points[msg->entries].pc, &location, sizeof(void *));
msg->points[msg->entries].count = 1;
@@ -165,11 +168,11 @@ static void trace_drop_common(struct sk_buff *skb, void *location)
if (!timer_pending(&data->send_timer)) {
data->send_timer.expires = jiffies + dm_delay * HZ;
- add_timer_on(&data->send_timer, smp_processor_id());
+ add_timer(&data->send_timer);
}
out:
- return;
+ spin_unlock_irqrestore(&data->lock, flags);
}
static void trace_kfree_skb_hit(void *ignore, struct sk_buff *skb, void *location)
@@ -213,7 +216,7 @@ static int set_all_monitor_traces(int state)
struct dm_hw_stat_delta *new_stat = NULL;
struct dm_hw_stat_delta *temp;
- spin_lock(&trace_state_lock);
+ mutex_lock(&trace_state_mutex);
if (state == trace_state) {
rc = -EAGAIN;
@@ -252,7 +255,7 @@ static int set_all_monitor_traces(int state)
rc = -EINPROGRESS;
out_unlock:
- spin_unlock(&trace_state_lock);
+ mutex_unlock(&trace_state_mutex);
return rc;
}
@@ -295,12 +298,12 @@ static int dropmon_net_event(struct notifier_block *ev_block,
new_stat->dev = dev;
new_stat->last_rx = jiffies;
- spin_lock(&trace_state_lock);
+ mutex_lock(&trace_state_mutex);
list_add_rcu(&new_stat->list, &hw_stats_list);
- spin_unlock(&trace_state_lock);
+ mutex_unlock(&trace_state_mutex);
break;
case NETDEV_UNREGISTER:
- spin_lock(&trace_state_lock);
+ mutex_lock(&trace_state_mutex);
list_for_each_entry_safe(new_stat, tmp, &hw_stats_list, list) {
if (new_stat->dev == dev) {
new_stat->dev = NULL;
@@ -311,7 +314,7 @@ static int dropmon_net_event(struct notifier_block *ev_block,
}
}
}
- spin_unlock(&trace_state_lock);
+ mutex_unlock(&trace_state_mutex);
break;
}
out:
@@ -367,13 +370,15 @@ static int __init init_net_drop_monitor(void)
for_each_present_cpu(cpu) {
data = &per_cpu(dm_cpu_data, cpu);
- reset_per_cpu_data(data);
INIT_WORK(&data->dm_alert_work, send_dm_alert);
init_timer(&data->send_timer);
- data->send_timer.data = cpu;
+ data->send_timer.data = (unsigned long)data;
data->send_timer.function = sched_send_work;
+ spin_lock_init(&data->lock);
+ reset_per_cpu_data(data);
}
+
goto out;
out_unreg:
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 4fb7704..891b19f 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -1964,6 +1964,7 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
case ETHTOOL_GRXCSUM:
case ETHTOOL_GTXCSUM:
case ETHTOOL_GSG:
+ case ETHTOOL_GSSET_INFO:
case ETHTOOL_GSTRINGS:
case ETHTOOL_GTSO:
case ETHTOOL_GPERMADDR:
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 96bb0a3..eb8857a 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -1313,8 +1313,6 @@ int neigh_resolve_output(struct sk_buff *skb)
if (!dst)
goto discard;
- __skb_pull(skb, skb_network_offset(skb));
-
if (!neigh_event_send(neigh, skb)) {
int err;
struct net_device *dev = neigh->dev;
@@ -1326,6 +1324,7 @@ int neigh_resolve_output(struct sk_buff *skb)
neigh_hh_init(neigh, dst, dst->ops->protocol);
do {
+ __skb_pull(skb, skb_network_offset(skb));
seq = read_seqbegin(&neigh->ha_lock);
err = dev_hard_header(skb, dev, ntohs(skb->protocol),
neigh->ha, NULL, skb->len);
@@ -1358,9 +1357,8 @@ int neigh_connected_output(struct sk_buff *skb)
struct net_device *dev = neigh->dev;
unsigned int seq;
- __skb_pull(skb, skb_network_offset(skb));
-
do {
+ __skb_pull(skb, skb_network_offset(skb));
seq = read_seqbegin(&neigh->ha_lock);
err = dev_hard_header(skb, dev, ntohs(skb->protocol),
neigh->ha, NULL, skb->len);
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 2772ed1..1642c30 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -24,7 +24,9 @@ static DEFINE_MUTEX(net_mutex);
LIST_HEAD(net_namespace_list);
EXPORT_SYMBOL_GPL(net_namespace_list);
-struct net init_net;
+struct net init_net = {
+ .dev_base_head = LIST_HEAD_INIT(init_net.dev_base_head),
+};
EXPORT_SYMBOL(init_net);
#define INITIAL_NET_GEN_PTRS 13 /* +1 for len +2 for rcu_head */
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 05db410..207a178 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -357,22 +357,23 @@ EXPORT_SYMBOL(netpoll_send_skb_on_dev);
void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
{
- int total_len, eth_len, ip_len, udp_len;
+ int total_len, ip_len, udp_len;
struct sk_buff *skb;
struct udphdr *udph;
struct iphdr *iph;
struct ethhdr *eth;
udp_len = len + sizeof(*udph);
- ip_len = eth_len = udp_len + sizeof(*iph);
- total_len = eth_len + ETH_HLEN + NET_IP_ALIGN;
+ ip_len = udp_len + sizeof(*iph);
+ total_len = ip_len + LL_RESERVED_SPACE(np->dev);
- skb = find_skb(np, total_len, total_len - len);
+ skb = find_skb(np, total_len + np->dev->needed_tailroom,
+ total_len - len);
if (!skb)
return;
skb_copy_to_linear_data(skb, msg, len);
- skb->len += len;
+ skb_put(skb, len);
skb_push(skb, sizeof(*udph));
skb_reset_transport_header(skb);
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index e35a6fb..01890e1 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -1932,7 +1932,7 @@ static int pktgen_device_event(struct notifier_block *unused,
{
struct net_device *dev = ptr;
- if (!net_eq(dev_net(dev), &init_net))
+ if (!net_eq(dev_net(dev), &init_net) || pktgen_exiting)
return NOTIFY_DONE;
/* It is OK that we do not hold the group lock right now,
@@ -2932,7 +2932,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
sizeof(struct ipv6hdr) - sizeof(struct udphdr) -
pkt_dev->pkt_overhead;
- if (datalen < sizeof(struct pktgen_hdr)) {
+ if (datalen < 0 || datalen < sizeof(struct pktgen_hdr)) {
datalen = sizeof(struct pktgen_hdr);
if (net_ratelimit())
pr_info("increased datalen to %d\n", datalen);
@@ -3755,12 +3755,18 @@ static void __exit pg_cleanup(void)
{
struct pktgen_thread *t;
struct list_head *q, *n;
+ LIST_HEAD(list);
/* Stop all interfaces & threads */
pktgen_exiting = true;
- list_for_each_safe(q, n, &pktgen_threads) {
+ mutex_lock(&pktgen_thread_lock);
+ list_splice_init(&pktgen_threads, &list);
+ mutex_unlock(&pktgen_thread_lock);
+
+ list_for_each_safe(q, n, &list) {
t = list_entry(q, struct pktgen_thread, th_list);
+ list_del(&t->th_list);
kthread_stop(t->tsk);
kfree(t);
}
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index abd936d..ac49ad5 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -647,6 +647,12 @@ static void set_operstate(struct net_device *dev, unsigned char transition)
}
}
+static unsigned int rtnl_dev_get_flags(const struct net_device *dev)
+{
+ return (dev->flags & ~(IFF_PROMISC | IFF_ALLMULTI)) |
+ (dev->gflags & (IFF_PROMISC | IFF_ALLMULTI));
+}
+
static unsigned int rtnl_dev_combine_flags(const struct net_device *dev,
const struct ifinfomsg *ifm)
{
@@ -655,7 +661,7 @@ static unsigned int rtnl_dev_combine_flags(const struct net_device *dev,
/* bugwards compatibility: ifi_change == 0 is treated as ~0 */
if (ifm->ifi_change)
flags = (flags & ifm->ifi_change) |
- (dev->flags & ~ifm->ifi_change);
+ (rtnl_dev_get_flags(dev) & ~ifm->ifi_change);
return flags;
}
@@ -1298,6 +1304,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
goto errout;
send_addr_notify = 1;
modified = 1;
+ add_device_randomness(dev->dev_addr, dev->addr_len);
}
if (tb[IFLA_MTU]) {
diff --git a/net/core/sock.c b/net/core/sock.c
index aebb419..3da11ba 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -594,7 +594,8 @@ set_rcvbuf:
case SO_KEEPALIVE:
#ifdef CONFIG_INET
- if (sk->sk_protocol == IPPROTO_TCP)
+ if (sk->sk_protocol == IPPROTO_TCP &&
+ sk->sk_type == SOCK_STREAM)
tcp_set_keepalive(sk, valbool);
#endif
sock_valbool_flag(sk, SOCK_KEEPOPEN, valbool);
@@ -1312,6 +1313,7 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
} else {
sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM;
sk->sk_gso_max_size = dst->dev->gso_max_size;
+ sk->sk_gso_max_segs = dst->dev->gso_max_segs;
}
}
}
@@ -1501,6 +1503,11 @@ struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len,
gfp_t gfp_mask;
long timeo;
int err;
+ int npages = (data_len + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+
+ err = -EMSGSIZE;
+ if (npages > MAX_SKB_FRAGS)
+ goto failure;
gfp_mask = sk->sk_allocation;
if (gfp_mask & __GFP_WAIT)
@@ -1519,14 +1526,12 @@ struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len,
if (atomic_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf) {
skb = alloc_skb(header_len, gfp_mask);
if (skb) {
- int npages;
int i;
/* No pages, we're done... */
if (!data_len)
break;
- npages = (data_len + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
skb->truesize += data_len;
skb_shinfo(skb)->nr_frags = npages;
for (i = 0; i < npages; i++) {
diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h
index 75c3582..fb85d37 100644
--- a/net/dccp/ccid.h
+++ b/net/dccp/ccid.h
@@ -246,7 +246,7 @@ static inline int ccid_hc_rx_getsockopt(struct ccid *ccid, struct sock *sk,
u32 __user *optval, int __user *optlen)
{
int rc = -ENOPROTOOPT;
- if (ccid->ccid_ops->ccid_hc_rx_getsockopt != NULL)
+ if (ccid != NULL && ccid->ccid_ops->ccid_hc_rx_getsockopt != NULL)
rc = ccid->ccid_ops->ccid_hc_rx_getsockopt(sk, optname, len,
optval, optlen);
return rc;
@@ -257,7 +257,7 @@ static inline int ccid_hc_tx_getsockopt(struct ccid *ccid, struct sock *sk,
u32 __user *optval, int __user *optlen)
{
int rc = -ENOPROTOOPT;
- if (ccid->ccid_ops->ccid_hc_tx_getsockopt != NULL)
+ if (ccid != NULL && ccid->ccid_ops->ccid_hc_tx_getsockopt != NULL)
rc = ccid->ccid_ops->ccid_hc_tx_getsockopt(sk, optname, len,
optval, optlen);
return rc;
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index 3d604e1..4caf63f 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -532,6 +532,7 @@ static int ccid3_hc_tx_getsockopt(struct sock *sk, const int optname, int len,
case DCCP_SOCKOPT_CCID_TX_INFO:
if (len < sizeof(tfrc))
return -EINVAL;
+ memset(&tfrc, 0, sizeof(tfrc));
tfrc.tfrctx_x = hc->tx_x;
tfrc.tfrctx_x_recv = hc->tx_x_recv;
tfrc.tfrctx_x_calc = hc->tx_x_calc;
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index 2b3c23c..062876b 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -1725,8 +1725,10 @@ int cipso_v4_validate(const struct sk_buff *skb, unsigned char **option)
case CIPSO_V4_TAG_LOCAL:
/* This is a non-standard tag that we only allow for
* local connections, so if the incoming interface is
- * not the loopback device drop the packet. */
- if (!(skb->dev->flags & IFF_LOOPBACK)) {
+ * not the loopback device drop the packet. Further,
+ * there is no legitimate reason for setting this from
+ * userspace so reject it if skb is NULL. */
+ if (skb == NULL || !(skb->dev->flags & IFF_LOOPBACK)) {
err_offset = opt_iter;
goto validate_return_locked;
}
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index a5b4134..530787b 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -457,28 +457,22 @@ static u32 esp4_get_mtu(struct xfrm_state *x, int mtu)
struct esp_data *esp = x->data;
u32 blksize = ALIGN(crypto_aead_blocksize(esp->aead), 4);
u32 align = max_t(u32, blksize, esp->padlen);
- u32 rem;
-
- mtu -= x->props.header_len + crypto_aead_authsize(esp->aead);
- rem = mtu & (align - 1);
- mtu &= ~(align - 1);
+ unsigned int net_adj;
switch (x->props.mode) {
- case XFRM_MODE_TUNNEL:
- break;
- default:
case XFRM_MODE_TRANSPORT:
- /* The worst case */
- mtu -= blksize - 4;
- mtu += min_t(u32, blksize - 4, rem);
- break;
case XFRM_MODE_BEET:
- /* The worst case. */
- mtu += min_t(u32, IPV4_BEET_PHMAXLEN, rem);
+ net_adj = sizeof(struct iphdr);
break;
+ case XFRM_MODE_TUNNEL:
+ net_adj = 0;
+ break;
+ default:
+ BUG();
}
- return mtu - 2;
+ return ((mtu - x->props.header_len - crypto_aead_authsize(esp->aead) -
+ net_adj) & ~(align - 1)) + (net_adj - 2);
}
static void esp4_err(struct sk_buff *skb, u32 info)
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 33e2c35..7e454ba 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -142,6 +142,18 @@ const struct fib_prop fib_props[RTN_MAX + 1] = {
};
/* Release a nexthop info record */
+static void free_fib_info_rcu(struct rcu_head *head)
+{
+ struct fib_info *fi = container_of(head, struct fib_info, rcu);
+
+ change_nexthops(fi) {
+ if (nexthop_nh->nh_dev)
+ dev_put(nexthop_nh->nh_dev);
+ } endfor_nexthops(fi);
+
+ release_net(fi->fib_net);
+ kfree(fi);
+}
void free_fib_info(struct fib_info *fi)
{
@@ -149,14 +161,8 @@ void free_fib_info(struct fib_info *fi)
pr_warning("Freeing alive fib_info %p\n", fi);
return;
}
- change_nexthops(fi) {
- if (nexthop_nh->nh_dev)
- dev_put(nexthop_nh->nh_dev);
- nexthop_nh->nh_dev = NULL;
- } endfor_nexthops(fi);
fib_info_cnt--;
- release_net(fi->fib_net);
- kfree_rcu(fi, rcu);
+ call_rcu(&fi->rcu, free_fib_info_rcu);
}
void fib_release_info(struct fib_info *fi)
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 58c25ea..0d884eb 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1371,6 +1371,8 @@ static int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l,
if (fa->fa_tos && fa->fa_tos != flp->flowi4_tos)
continue;
+ if (fi->fib_dead)
+ continue;
if (fa->fa_info->fib_scope < flp->flowi4_scope)
continue;
fib_alias_accessed(fa);
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index f81af8d..ec7d8e7 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -124,6 +124,8 @@ static DEFINE_SPINLOCK(mfc_unres_lock);
static struct kmem_cache *mrt_cachep __read_mostly;
static struct mr_table *ipmr_new_table(struct net *net, u32 id);
+static void ipmr_free_table(struct mr_table *mrt);
+
static int ip_mr_forward(struct net *net, struct mr_table *mrt,
struct sk_buff *skb, struct mfc_cache *cache,
int local);
@@ -131,6 +133,7 @@ static int ipmr_cache_report(struct mr_table *mrt,
struct sk_buff *pkt, vifi_t vifi, int assert);
static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
struct mfc_cache *c, struct rtmsg *rtm);
+static void mroute_clean_tables(struct mr_table *mrt);
static void ipmr_expire_process(unsigned long arg);
#ifdef CONFIG_IP_MROUTE_MULTIPLE_TABLES
@@ -271,7 +274,7 @@ static void __net_exit ipmr_rules_exit(struct net *net)
list_for_each_entry_safe(mrt, next, &net->ipv4.mr_tables, list) {
list_del(&mrt->list);
- kfree(mrt);
+ ipmr_free_table(mrt);
}
fib_rules_unregister(net->ipv4.mr_rules_ops);
}
@@ -299,7 +302,7 @@ static int __net_init ipmr_rules_init(struct net *net)
static void __net_exit ipmr_rules_exit(struct net *net)
{
- kfree(net->ipv4.mrt);
+ ipmr_free_table(net->ipv4.mrt);
}
#endif
@@ -336,6 +339,13 @@ static struct mr_table *ipmr_new_table(struct net *net, u32 id)
return mrt;
}
+static void ipmr_free_table(struct mr_table *mrt)
+{
+ del_timer_sync(&mrt->ipmr_expire_timer);
+ mroute_clean_tables(mrt);
+ kfree(mrt);
+}
+
/* Service routines creating virtual interfaces: DVMRP tunnels and PIMREG */
static void ipmr_del_tunnel(struct net_device *dev, struct vifctl *v)
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index de9da21..d7d63f4 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -84,6 +84,14 @@ static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
*dataoff = nhoff + (iph->ihl << 2);
*protonum = iph->protocol;
+ /* Check bogus IP headers */
+ if (*dataoff > skb->len) {
+ pr_debug("nf_conntrack_ipv4: bogus IPv4 packet: "
+ "nhoff %u, ihl %u, skblen %u\n",
+ nhoff, iph->ihl << 2, skb->len);
+ return -NF_ACCEPT;
+ }
+
return NF_ACCEPT;
}
diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c
index e40cf78..cd6881e 100644
--- a/net/ipv4/netfilter/nf_nat_sip.c
+++ b/net/ipv4/netfilter/nf_nat_sip.c
@@ -148,7 +148,7 @@ static unsigned int ip_nat_sip(struct sk_buff *skb, unsigned int dataoff,
if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen,
hdr, NULL, &matchoff, &matchlen,
&addr, &port) > 0) {
- unsigned int matchend, poff, plen, buflen, n;
+ unsigned int olen, matchend, poff, plen, buflen, n;
char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
/* We're only interested in headers related to this
@@ -163,11 +163,12 @@ static unsigned int ip_nat_sip(struct sk_buff *skb, unsigned int dataoff,
goto next;
}
+ olen = *datalen;
if (!map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen,
&addr, port))
return NF_DROP;
- matchend = matchoff + matchlen;
+ matchend = matchoff + matchlen + *datalen - olen;
/* The maddr= parameter (RFC 2361) specifies where to send
* the reply. */
@@ -501,7 +502,10 @@ static unsigned int ip_nat_sdp_media(struct sk_buff *skb, unsigned int dataoff,
ret = nf_ct_expect_related(rtcp_exp);
if (ret == 0)
break;
- else if (ret != -EBUSY) {
+ else if (ret == -EBUSY) {
+ nf_ct_unexpect_related(rtp_exp);
+ continue;
+ } else if (ret < 0) {
nf_ct_unexpect_related(rtp_exp);
port = 0;
break;
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index c9893d4..3d8bb18 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -130,18 +130,20 @@ found:
* 0 - deliver
* 1 - block
*/
-static __inline__ int icmp_filter(struct sock *sk, struct sk_buff *skb)
+static int icmp_filter(const struct sock *sk, const struct sk_buff *skb)
{
- int type;
+ struct icmphdr _hdr;
+ const struct icmphdr *hdr;
- if (!pskb_may_pull(skb, sizeof(struct icmphdr)))
+ hdr = skb_header_pointer(skb, skb_transport_offset(skb),
+ sizeof(_hdr), &_hdr);
+ if (!hdr)
return 1;
- type = icmp_hdr(skb)->type;
- if (type < 32) {
+ if (hdr->type < 32) {
__u32 data = raw_sk(sk)->filter.data;
- return ((1 << type) & data) != 0;
+ return ((1U << hdr->type) & data) != 0;
}
/* Do not block unknown ICMP types */
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index b0e5330..08d2244 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -743,7 +743,9 @@ static unsigned int tcp_xmit_size_goal(struct sock *sk, u32 mss_now,
old_size_goal + mss_now > xmit_size_goal)) {
xmit_size_goal = old_size_goal;
} else {
- tp->xmit_size_goal_segs = xmit_size_goal / mss_now;
+ tp->xmit_size_goal_segs =
+ min_t(u16, xmit_size_goal / mss_now,
+ sk->sk_gso_max_segs);
xmit_size_goal = tp->xmit_size_goal_segs * mss_now;
}
}
@@ -854,8 +856,7 @@ new_segment:
wait_for_sndbuf:
set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
wait_for_memory:
- if (copied)
- tcp_push(sk, flags & ~MSG_MORE, mss_now, TCP_NAGLE_PUSH);
+ tcp_push(sk, flags & ~MSG_MORE, mss_now, TCP_NAGLE_PUSH);
if ((err = sk_stream_wait_memory(sk, &timeo)) != 0)
goto do_error;
@@ -1601,8 +1602,14 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
}
#ifdef CONFIG_NET_DMA
- if (tp->ucopy.dma_chan)
- dma_async_memcpy_issue_pending(tp->ucopy.dma_chan);
+ if (tp->ucopy.dma_chan) {
+ if (tp->rcv_wnd == 0 &&
+ !skb_queue_empty(&sk->sk_async_wait_queue)) {
+ tcp_service_net_dma(sk, true);
+ tcp_cleanup_rbuf(sk, copied);
+ } else
+ dma_async_memcpy_issue_pending(tp->ucopy.dma_chan);
+ }
#endif
if (copied >= target) {
/* Do not sleep, just process backlog. */
@@ -2410,7 +2417,10 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
/* Cap the max timeout in ms TCP will retry/retrans
* before giving up and aborting (ETIMEDOUT) a connection.
*/
- icsk->icsk_user_timeout = msecs_to_jiffies(val);
+ if (val < 0)
+ err = -EINVAL;
+ else
+ icsk->icsk_user_timeout = msecs_to_jiffies(val);
break;
default:
err = -ENOPROTOOPT;
@@ -3236,7 +3246,7 @@ void __init tcp_init(void)
{
struct sk_buff *skb = NULL;
unsigned long limit;
- int i, max_share, cnt;
+ int i, max_rshare, max_wshare, cnt;
unsigned long jiffy = jiffies;
BUILD_BUG_ON(sizeof(struct tcp_skb_cb) > sizeof(skb->cb));
@@ -3300,15 +3310,16 @@ void __init tcp_init(void)
/* Set per-socket limits to no more than 1/128 the pressure threshold */
limit = ((unsigned long)sysctl_tcp_mem[1]) << (PAGE_SHIFT - 7);
- max_share = min(4UL*1024*1024, limit);
+ max_wshare = min(4UL*1024*1024, limit);
+ max_rshare = min(6UL*1024*1024, limit);
sysctl_tcp_wmem[0] = SK_MEM_QUANTUM;
sysctl_tcp_wmem[1] = 16*1024;
- sysctl_tcp_wmem[2] = max(64*1024, max_share);
+ sysctl_tcp_wmem[2] = max(64*1024, max_wshare);
sysctl_tcp_rmem[0] = SK_MEM_QUANTUM;
sysctl_tcp_rmem[1] = 87380;
- sysctl_tcp_rmem[2] = max(87380, max_share);
+ sysctl_tcp_rmem[2] = max(87380, max_rshare);
printk(KERN_INFO "TCP: Hash tables configured "
"(established %u bind %u)\n",
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c
index 850c737..6cebfd2 100644
--- a/net/ipv4/tcp_cong.c
+++ b/net/ipv4/tcp_cong.c
@@ -290,7 +290,8 @@ int tcp_is_cwnd_limited(const struct sock *sk, u32 in_flight)
left = tp->snd_cwnd - in_flight;
if (sk_can_gso(sk) &&
left * sysctl_tcp_tso_win_divisor < tp->snd_cwnd &&
- left * tp->mss_cache < sk->sk_gso_max_size)
+ left * tp->mss_cache < sk->sk_gso_max_size &&
+ left < sk->sk_gso_max_segs)
return 1;
return left <= tcp_max_burst(tp);
}
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index c3a9f03..b76aa2d 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -83,7 +83,7 @@ int sysctl_tcp_ecn __read_mostly = 2;
EXPORT_SYMBOL(sysctl_tcp_ecn);
int sysctl_tcp_dsack __read_mostly = 1;
int sysctl_tcp_app_win __read_mostly = 31;
-int sysctl_tcp_adv_win_scale __read_mostly = 2;
+int sysctl_tcp_adv_win_scale __read_mostly = 1;
EXPORT_SYMBOL(sysctl_tcp_adv_win_scale);
int sysctl_tcp_stdurg __read_mostly;
@@ -5340,7 +5340,9 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
if (tp->copied_seq == tp->rcv_nxt &&
len - tcp_header_len <= tp->ucopy.len) {
#ifdef CONFIG_NET_DMA
- if (tcp_dma_try_early_copy(sk, skb, tcp_header_len)) {
+ if (tp->ucopy.task == current &&
+ sock_owned_by_user(sk) &&
+ tcp_dma_try_early_copy(sk, skb, tcp_header_len)) {
copied_early = 1;
eaten = 1;
}
@@ -5761,6 +5763,8 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
goto discard;
if (th->syn) {
+ if (th->fin)
+ goto discard;
if (icsk->icsk_af_ops->conn_request(sk, skb) < 0)
return 1;
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 53a5af6..d645c6f 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -651,10 +651,11 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
arg.csumoffset = offsetof(struct tcphdr, check) / 2;
arg.flags = (sk && inet_sk(sk)->transparent) ? IP_REPLY_ARG_NOSRCCHECK : 0;
/* When socket is gone, all binding information is lost.
- * routing might fail in this case. using iif for oif to
- * make sure we can deliver it
+ * routing might fail in this case. No choice here, if we choose to force
+ * input interface, we will misroute in case of asymmetric route.
*/
- arg.bound_dev_if = sk ? sk->sk_bound_dev_if : inet_iif(skb);
+ if (sk)
+ arg.bound_dev_if = sk->sk_bound_dev_if;
net = dev_net(skb_dst(skb)->dev);
ip_send_reply(net->ipv4.tcp_sock, skb, ip_hdr(skb)->saddr,
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index faf257b..e0b8bd1 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -1310,21 +1310,21 @@ static void tcp_cwnd_validate(struct sock *sk)
* when we would be allowed to send the split-due-to-Nagle skb fully.
*/
static unsigned int tcp_mss_split_point(struct sock *sk, struct sk_buff *skb,
- unsigned int mss_now, unsigned int cwnd)
+ unsigned int mss_now, unsigned int max_segs)
{
struct tcp_sock *tp = tcp_sk(sk);
- u32 needed, window, cwnd_len;
+ u32 needed, window, max_len;
window = tcp_wnd_end(tp) - TCP_SKB_CB(skb)->seq;
- cwnd_len = mss_now * cwnd;
+ max_len = mss_now * max_segs;
- if (likely(cwnd_len <= window && skb != tcp_write_queue_tail(sk)))
- return cwnd_len;
+ if (likely(max_len <= window && skb != tcp_write_queue_tail(sk)))
+ return max_len;
needed = min(skb->len, window);
- if (cwnd_len <= needed)
- return cwnd_len;
+ if (max_len <= needed)
+ return max_len;
return needed - needed % mss_now;
}
@@ -1551,7 +1551,8 @@ static int tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb)
limit = min(send_win, cong_win);
/* If a full-sized TSO skb can be sent, do it. */
- if (limit >= sk->sk_gso_max_size)
+ if (limit >= min_t(unsigned int, sk->sk_gso_max_size,
+ sk->sk_gso_max_segs * tp->mss_cache))
goto send_now;
/* Middle in queue won't get any more data, full sendable already? */
@@ -1777,7 +1778,9 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
limit = mss_now;
if (tso_segs > 1 && !tcp_urg_mode(tp))
limit = tcp_mss_split_point(sk, skb, mss_now,
- cwnd_quota);
+ min_t(unsigned int,
+ cwnd_quota,
+ sk->sk_gso_max_segs));
if (skb->len > limit &&
unlikely(tso_fragment(sk, skb, limit, mss_now, gfp)))
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 8a4bf71..036bcee 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -492,8 +492,7 @@ static void addrconf_forward_change(struct net *net, __s32 newf)
struct net_device *dev;
struct inet6_dev *idev;
- rcu_read_lock();
- for_each_netdev_rcu(net, dev) {
+ for_each_netdev(net, dev) {
idev = __in6_dev_get(dev);
if (idev) {
int changed = (!idev->cnf.forwarding) ^ (!newf);
@@ -502,7 +501,6 @@ static void addrconf_forward_change(struct net *net, __s32 newf)
dev_forward_change(idev);
}
}
- rcu_read_unlock();
}
static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old)
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 1ac7938..65dd543 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -411,19 +411,15 @@ static u32 esp6_get_mtu(struct xfrm_state *x, int mtu)
struct esp_data *esp = x->data;
u32 blksize = ALIGN(crypto_aead_blocksize(esp->aead), 4);
u32 align = max_t(u32, blksize, esp->padlen);
- u32 rem;
+ unsigned int net_adj;
- mtu -= x->props.header_len + crypto_aead_authsize(esp->aead);
- rem = mtu & (align - 1);
- mtu &= ~(align - 1);
-
- if (x->props.mode != XFRM_MODE_TUNNEL) {
- u32 padsize = ((blksize - 1) & 7) + 1;
- mtu -= blksize - padsize;
- mtu += min_t(u32, blksize - padsize, rem);
- }
+ if (x->props.mode != XFRM_MODE_TUNNEL)
+ net_adj = sizeof(struct ipv6hdr);
+ else
+ net_adj = 0;
- return mtu - 2;
+ return ((mtu - x->props.header_len - crypto_aead_authsize(esp->aead) -
+ net_adj) & ~(align - 1)) + (net_adj - 2);
}
static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 9cbf176..ae9f6d4 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1194,6 +1194,29 @@ static inline struct ipv6_rt_hdr *ip6_rthdr_dup(struct ipv6_rt_hdr *src,
return src ? kmemdup(src, (src->hdrlen + 1) * 8, gfp) : NULL;
}
+static void ip6_append_data_mtu(int *mtu,
+ int *maxfraglen,
+ unsigned int fragheaderlen,
+ struct sk_buff *skb,
+ struct rt6_info *rt)
+{
+ if (!(rt->dst.flags & DST_XFRM_TUNNEL)) {
+ if (skb == NULL) {
+ /* first fragment, reserve header_len */
+ *mtu = *mtu - rt->dst.header_len;
+
+ } else {
+ /*
+ * this fragment is not first, the headers
+ * space is regarded as data space.
+ */
+ *mtu = dst_mtu(rt->dst.path);
+ }
+ *maxfraglen = ((*mtu - fragheaderlen) & ~7)
+ + fragheaderlen - sizeof(struct frag_hdr);
+ }
+}
+
int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
int offset, int len, int odd, struct sk_buff *skb),
void *from, int length, int transhdrlen,
@@ -1203,7 +1226,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
struct inet_sock *inet = inet_sk(sk);
struct ipv6_pinfo *np = inet6_sk(sk);
struct inet_cork *cork;
- struct sk_buff *skb;
+ struct sk_buff *skb, *skb_prev = NULL;
unsigned int maxfraglen, fragheaderlen;
int exthdrlen;
int hh_len;
@@ -1260,8 +1283,12 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
inet->cork.fl.u.ip6 = *fl6;
np->cork.hop_limit = hlimit;
np->cork.tclass = tclass;
- mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ?
- rt->dst.dev->mtu : dst_mtu(rt->dst.path);
+ if (rt->dst.flags & DST_XFRM_TUNNEL)
+ mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ?
+ rt->dst.dev->mtu : dst_mtu(&rt->dst);
+ else
+ mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ?
+ rt->dst.dev->mtu : dst_mtu(rt->dst.path);
if (np->frag_size < mtu) {
if (np->frag_size)
mtu = np->frag_size;
@@ -1356,38 +1383,43 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
unsigned int fraglen;
unsigned int fraggap;
unsigned int alloclen;
- struct sk_buff *skb_prev;
alloc_new_skb:
- skb_prev = skb;
-
/* There's no room in the current skb */
- if (skb_prev)
- fraggap = skb_prev->len - maxfraglen;
+ if (skb)
+ fraggap = skb->len - maxfraglen;
else
fraggap = 0;
+ /* update mtu and maxfraglen if necessary */
+ if (skb == NULL || skb_prev == NULL)
+ ip6_append_data_mtu(&mtu, &maxfraglen,
+ fragheaderlen, skb, rt);
+
+ skb_prev = skb;
/*
* If remaining data exceeds the mtu,
* we know we need more fragment(s).
*/
datalen = length + fraggap;
- if (datalen > (cork->length <= mtu && !(cork->flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - fragheaderlen)
- datalen = maxfraglen - fragheaderlen;
- fraglen = datalen + fragheaderlen;
+ if (datalen > (cork->length <= mtu && !(cork->flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - fragheaderlen)
+ datalen = maxfraglen - fragheaderlen - rt->dst.trailer_len;
if ((flags & MSG_MORE) &&
!(rt->dst.dev->features&NETIF_F_SG))
alloclen = mtu;
else
alloclen = datalen + fragheaderlen;
- /*
- * The last fragment gets additional space at tail.
- * Note: we overallocate on fragments with MSG_MODE
- * because we have no idea if we're the last one.
- */
- if (datalen == length + fraggap)
- alloclen += rt->dst.trailer_len;
+ if (datalen != length + fraggap) {
+ /*
+ * this is not the last fragment, the trailer
+ * space is regarded as data space.
+ */
+ datalen += rt->dst.trailer_len;
+ }
+
+ alloclen += rt->dst.trailer_len;
+ fraglen = datalen + fragheaderlen;
/*
* We just reserve space for fragment header.
diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c
index 43242e6..42853c4 100644
--- a/net/ipv6/mip6.c
+++ b/net/ipv6/mip6.c
@@ -84,28 +84,30 @@ static int mip6_mh_len(int type)
static int mip6_mh_filter(struct sock *sk, struct sk_buff *skb)
{
- struct ip6_mh *mh;
+ struct ip6_mh _hdr;
+ const struct ip6_mh *mh;
- if (!pskb_may_pull(skb, (skb_transport_offset(skb)) + 8) ||
- !pskb_may_pull(skb, (skb_transport_offset(skb) +
- ((skb_transport_header(skb)[1] + 1) << 3))))
+ mh = skb_header_pointer(skb, skb_transport_offset(skb),
+ sizeof(_hdr), &_hdr);
+ if (!mh)
return -1;
- mh = (struct ip6_mh *)skb_transport_header(skb);
+ if (((mh->ip6mh_hdrlen + 1) << 3) > skb->len)
+ return -1;
if (mh->ip6mh_hdrlen < mip6_mh_len(mh->ip6mh_type)) {
LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH message too short: %d vs >=%d\n",
mh->ip6mh_hdrlen, mip6_mh_len(mh->ip6mh_type));
- mip6_param_prob(skb, 0, ((&mh->ip6mh_hdrlen) -
- skb_network_header(skb)));
+ mip6_param_prob(skb, 0, offsetof(struct ip6_mh, ip6mh_hdrlen) +
+ skb_network_header_len(skb));
return -1;
}
if (mh->ip6mh_proto != IPPROTO_NONE) {
LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH invalid payload proto = %d\n",
mh->ip6mh_proto);
- mip6_param_prob(skb, 0, ((&mh->ip6mh_proto) -
- skb_network_header(skb)));
+ mip6_param_prob(skb, 0, offsetof(struct ip6_mh, ip6mh_proto) +
+ skb_network_header_len(skb));
return -1;
}
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index cc7313b..fb812a6 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -106,21 +106,20 @@ found:
* 0 - deliver
* 1 - block
*/
-static __inline__ int icmpv6_filter(struct sock *sk, struct sk_buff *skb)
+static int icmpv6_filter(const struct sock *sk, const struct sk_buff *skb)
{
- struct icmp6hdr *icmph;
- struct raw6_sock *rp = raw6_sk(sk);
-
- if (pskb_may_pull(skb, sizeof(struct icmp6hdr))) {
- __u32 *data = &rp->filter.data[0];
- int bit_nr;
+ struct icmp6hdr *_hdr;
+ const struct icmp6hdr *hdr;
- icmph = (struct icmp6hdr *) skb->data;
- bit_nr = icmph->icmp6_type;
+ hdr = skb_header_pointer(skb, skb_transport_offset(skb),
+ sizeof(_hdr), &_hdr);
+ if (hdr) {
+ const __u32 *data = &raw6_sk(sk)->filter.data[0];
+ unsigned int type = hdr->icmp6_type;
- return (data[bit_nr >> 5] & (1 << (bit_nr & 31))) != 0;
+ return (data[type >> 5] & (1U << (type & 31))) != 0;
}
- return 0;
+ return 1;
}
#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 7ef5d08..6a96cad 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1401,17 +1401,18 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info)
struct fib6_table *table;
struct net *net = dev_net(rt->rt6i_dev);
- if (rt == net->ipv6.ip6_null_entry)
- return -ENOENT;
+ if (rt == net->ipv6.ip6_null_entry) {
+ err = -ENOENT;
+ goto out;
+ }
table = rt->rt6i_table;
write_lock_bh(&table->tb6_lock);
-
err = fib6_del(rt, info);
- dst_release(&rt->dst);
-
write_unlock_bh(&table->tb6_lock);
+out:
+ dst_release(&rt->dst);
return err;
}
@@ -2848,10 +2849,6 @@ static int __net_init ip6_route_net_init(struct net *net)
net->ipv6.sysctl.ip6_rt_mtu_expires = 10*60*HZ;
net->ipv6.sysctl.ip6_rt_min_advmss = IPV6_MIN_MTU - 20 - 40;
-#ifdef CONFIG_PROC_FS
- proc_net_fops_create(net, "ipv6_route", 0, &ipv6_route_proc_fops);
- proc_net_fops_create(net, "rt6_stats", S_IRUGO, &rt6_stats_seq_fops);
-#endif
net->ipv6.ip6_rt_gc_expire = 30*HZ;
ret = 0;
@@ -2872,10 +2869,6 @@ out_ip6_dst_ops:
static void __net_exit ip6_route_net_exit(struct net *net)
{
-#ifdef CONFIG_PROC_FS
- proc_net_remove(net, "ipv6_route");
- proc_net_remove(net, "rt6_stats");
-#endif
kfree(net->ipv6.ip6_null_entry);
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
kfree(net->ipv6.ip6_prohibit_entry);
@@ -2884,11 +2877,33 @@ static void __net_exit ip6_route_net_exit(struct net *net)
dst_entries_destroy(&net->ipv6.ip6_dst_ops);
}
+static int __net_init ip6_route_net_init_late(struct net *net)
+{
+#ifdef CONFIG_PROC_FS
+ proc_net_fops_create(net, "ipv6_route", 0, &ipv6_route_proc_fops);
+ proc_net_fops_create(net, "rt6_stats", S_IRUGO, &rt6_stats_seq_fops);
+#endif
+ return 0;
+}
+
+static void __net_exit ip6_route_net_exit_late(struct net *net)
+{
+#ifdef CONFIG_PROC_FS
+ proc_net_remove(net, "ipv6_route");
+ proc_net_remove(net, "rt6_stats");
+#endif
+}
+
static struct pernet_operations ip6_route_net_ops = {
.init = ip6_route_net_init,
.exit = ip6_route_net_exit,
};
+static struct pernet_operations ip6_route_net_late_ops = {
+ .init = ip6_route_net_init_late,
+ .exit = ip6_route_net_exit_late,
+};
+
static struct notifier_block ip6_route_dev_notifier = {
.notifier_call = ip6_route_dev_notify,
.priority = 0,
@@ -2938,19 +2953,25 @@ int __init ip6_route_init(void)
if (ret)
goto xfrm6_init;
+ ret = register_pernet_subsys(&ip6_route_net_late_ops);
+ if (ret)
+ goto fib6_rules_init;
+
ret = -ENOBUFS;
if (__rtnl_register(PF_INET6, RTM_NEWROUTE, inet6_rtm_newroute, NULL) ||
__rtnl_register(PF_INET6, RTM_DELROUTE, inet6_rtm_delroute, NULL) ||
__rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL))
- goto fib6_rules_init;
+ goto out_register_late_subsys;
ret = register_netdevice_notifier(&ip6_route_dev_notifier);
if (ret)
- goto fib6_rules_init;
+ goto out_register_late_subsys;
out:
return ret;
+out_register_late_subsys:
+ unregister_pernet_subsys(&ip6_route_net_late_ops);
fib6_rules_init:
fib6_rules_cleanup();
xfrm6_init:
@@ -2969,6 +2990,7 @@ out_kmem_cache:
void ip6_route_cleanup(void)
{
unregister_netdevice_notifier(&ip6_route_dev_notifier);
+ unregister_pernet_subsys(&ip6_route_net_late_ops);
fib6_rules_cleanup();
xfrm6_fini();
fib6_gc_cleanup();
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 848f963..a6d5850 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1060,7 +1060,8 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
__tcp_v6_send_check(buff, &fl6.saddr, &fl6.daddr);
fl6.flowi6_proto = IPPROTO_TCP;
- fl6.flowi6_oif = inet6_iif(skb);
+ if (ipv6_addr_type(&fl6.daddr) & IPV6_ADDR_LINKLOCAL)
+ fl6.flowi6_oif = inet6_iif(skb);
fl6.fl6_dport = t1->dest;
fl6.fl6_sport = t1->source;
security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index 71c292e..6a3d680 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -1252,11 +1252,10 @@ static void l2tp_tunnel_free(struct l2tp_tunnel *tunnel)
/* Remove from tunnel list */
spin_lock_bh(&pn->l2tp_tunnel_list_lock);
list_del_rcu(&tunnel->list);
+ kfree_rcu(tunnel, rcu);
spin_unlock_bh(&pn->l2tp_tunnel_list_lock);
- synchronize_rcu();
atomic_dec(&l2tp_tunnel_count);
- kfree(tunnel);
}
/* Create a socket for the tunnel, if one isn't set up by
diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h
index a16a48e..4393794 100644
--- a/net/l2tp/l2tp_core.h
+++ b/net/l2tp/l2tp_core.h
@@ -157,6 +157,7 @@ struct l2tp_tunnel_cfg {
struct l2tp_tunnel {
int magic; /* Should be L2TP_TUNNEL_MAGIC */
+ struct rcu_head rcu;
rwlock_t hlist_lock; /* protect session_hlist */
struct hlist_head session_hlist[L2TP_HASH_SIZE];
/* hashed list of sessions,
diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c
index d2726a7..2cef50b 100644
--- a/net/l2tp/l2tp_eth.c
+++ b/net/l2tp/l2tp_eth.c
@@ -132,7 +132,7 @@ static void l2tp_eth_dev_recv(struct l2tp_session *session, struct sk_buff *skb,
printk("\n");
}
- if (!pskb_may_pull(skb, sizeof(ETH_HLEN)))
+ if (!pskb_may_pull(skb, ETH_HLEN))
goto error;
secpath_reset(skb);
@@ -167,6 +167,7 @@ static void l2tp_eth_delete(struct l2tp_session *session)
if (dev) {
unregister_netdev(dev);
spriv->dev = NULL;
+ module_put(THIS_MODULE);
}
}
}
@@ -254,6 +255,7 @@ static int l2tp_eth_create(struct net *net, u32 tunnel_id, u32 session_id, u32 p
if (rc < 0)
goto out_del_dev;
+ __module_get(THIS_MODULE);
/* Must be done after register_netdev() */
strlcpy(session->ifname, dev->name, IFNAMSIZ);
diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c
index 858ca23..78bc442 100644
--- a/net/l2tp/l2tp_ip.c
+++ b/net/l2tp/l2tp_ip.c
@@ -251,9 +251,16 @@ static int l2tp_ip_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
{
struct inet_sock *inet = inet_sk(sk);
struct sockaddr_l2tpip *addr = (struct sockaddr_l2tpip *) uaddr;
- int ret = -EINVAL;
+ int ret;
int chk_addr_ret;
+ if (!sock_flag(sk, SOCK_ZAPPED))
+ return -EINVAL;
+ if (addr_len < sizeof(struct sockaddr_l2tpip))
+ return -EINVAL;
+ if (addr->l2tp_family != AF_INET)
+ return -EINVAL;
+
ret = -EADDRINUSE;
read_lock_bh(&l2tp_ip_lock);
if (__l2tp_ip_bind_lookup(&init_net, addr->l2tp_addr.s_addr, sk->sk_bound_dev_if, addr->l2tp_conn_id))
@@ -283,6 +290,8 @@ static int l2tp_ip_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
sk_del_node_init(sk);
write_unlock_bh(&l2tp_ip_lock);
ret = 0;
+ sock_reset_flag(sk, SOCK_ZAPPED);
+
out:
release_sock(sk);
@@ -303,13 +312,14 @@ static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len
__be32 saddr;
int oif, rc;
- rc = -EINVAL;
+ if (sock_flag(sk, SOCK_ZAPPED)) /* Must bind first - autobinding does not work */
+ return -EINVAL;
+
if (addr_len < sizeof(*lsa))
- goto out;
+ return -EINVAL;
- rc = -EAFNOSUPPORT;
if (lsa->l2tp_family != AF_INET)
- goto out;
+ return -EAFNOSUPPORT;
lock_sock(sk);
@@ -363,6 +373,14 @@ out:
return rc;
}
+static int l2tp_ip_disconnect(struct sock *sk, int flags)
+{
+ if (sock_flag(sk, SOCK_ZAPPED))
+ return 0;
+
+ return udp_disconnect(sk, flags);
+}
+
static int l2tp_ip_getname(struct socket *sock, struct sockaddr *uaddr,
int *uaddr_len, int peer)
{
@@ -441,8 +459,9 @@ static int l2tp_ip_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m
daddr = lip->l2tp_addr.s_addr;
} else {
+ rc = -EDESTADDRREQ;
if (sk->sk_state != TCP_ESTABLISHED)
- return -EDESTADDRREQ;
+ goto out;
daddr = inet->inet_daddr;
connected = 1;
@@ -590,7 +609,7 @@ static struct proto l2tp_ip_prot = {
.close = l2tp_ip_close,
.bind = l2tp_ip_bind,
.connect = l2tp_ip_connect,
- .disconnect = udp_disconnect,
+ .disconnect = l2tp_ip_disconnect,
.ioctl = udp_ioctl,
.destroy = l2tp_ip_destroy_sock,
.setsockopt = ip_setsockopt,
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
index a18e6c3..99a60d5 100644
--- a/net/llc/af_llc.c
+++ b/net/llc/af_llc.c
@@ -966,14 +966,13 @@ static int llc_ui_getname(struct socket *sock, struct sockaddr *uaddr,
struct sockaddr_llc sllc;
struct sock *sk = sock->sk;
struct llc_sock *llc = llc_sk(sk);
- int rc = 0;
+ int rc = -EBADF;
memset(&sllc, 0, sizeof(sllc));
lock_sock(sk);
if (sock_flag(sk, SOCK_ZAPPED))
goto out;
*uaddrlen = sizeof(sllc);
- memset(uaddr, 0, *uaddrlen);
if (peer) {
rc = -ENOTCONN;
if (sk->sk_state != TCP_ESTABLISHED)
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 895eec1..65f3764c 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -498,6 +498,18 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
ieee80211_configure_filter(local);
break;
default:
+ mutex_lock(&local->mtx);
+ if (local->hw_roc_dev == sdata->dev &&
+ local->hw_roc_channel) {
+ /* ignore return value since this is racy */
+ drv_cancel_remain_on_channel(local);
+ ieee80211_queue_work(&local->hw, &local->hw_roc_done);
+ }
+ mutex_unlock(&local->mtx);
+
+ flush_work(&local->hw_roc_start);
+ flush_work(&local->hw_roc_done);
+
flush_work(&sdata->work);
/*
* When we get here, the interface is marked down.
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 29e9980..370aa94 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -490,6 +490,7 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
del_timer_sync(&sdata->u.mesh.housekeeping_timer);
del_timer_sync(&sdata->u.mesh.mesh_path_root_timer);
+ del_timer_sync(&sdata->u.mesh.mesh_path_timer);
/*
* If the timer fired while we waited for it, it will have
* requeued the work. Now the work will be running again
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index 13427b1..c55eb9d 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -251,6 +251,22 @@ static void ieee80211_hw_roc_done(struct work_struct *work)
return;
}
+ /* was never transmitted */
+ if (local->hw_roc_skb) {
+ u64 cookie;
+
+ cookie = local->hw_roc_cookie ^ 2;
+
+ cfg80211_mgmt_tx_status(local->hw_roc_dev, cookie,
+ local->hw_roc_skb->data,
+ local->hw_roc_skb->len, false,
+ GFP_KERNEL);
+
+ kfree_skb(local->hw_roc_skb);
+ local->hw_roc_skb = NULL;
+ local->hw_roc_skb_for_status = NULL;
+ }
+
if (!local->hw_roc_for_tx)
cfg80211_remain_on_channel_expired(local->hw_roc_dev,
local->hw_roc_cookie,
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 4100065..667f559 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2291,7 +2291,7 @@ ieee80211_rx_h_action_return(struct ieee80211_rx_data *rx)
* frames that we didn't handle, including returning unknown
* ones. For all other modes we will return them to the sender,
* setting the 0x80 bit in the action category, as required by
- * 802.11-2007 7.3.1.11.
+ * 802.11-2012 9.24.4.
* Newer versions of hostapd shall also use the management frame
* registration mechanisms, but older ones still use cooked
* monitor interfaces so push all frames there.
@@ -2301,6 +2301,9 @@ ieee80211_rx_h_action_return(struct ieee80211_rx_data *rx)
sdata->vif.type == NL80211_IFTYPE_AP_VLAN))
return RX_DROP_MONITOR;
+ if (is_multicast_ether_addr(mgmt->da))
+ return RX_DROP_MONITOR;
+
/* do not return rejected action frames */
if (mgmt->u.action.category & 0x80)
return RX_DROP_UNUSABLE;
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 2124db8..11d9d49 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1254,6 +1254,12 @@ int ieee80211_reconfig(struct ieee80211_local *local)
}
}
+ /* add back keys */
+ list_for_each_entry(sdata, &local->interfaces, list)
+ if (ieee80211_sdata_running(sdata))
+ ieee80211_enable_keys(sdata);
+
+ wake_up:
/*
* Clear the WLAN_STA_BLOCK_BA flag so new aggregation
* sessions can be established after a resume.
@@ -1275,12 +1281,6 @@ int ieee80211_reconfig(struct ieee80211_local *local)
mutex_unlock(&local->sta_mtx);
}
- /* add back keys */
- list_for_each_entry(sdata, &local->interfaces, list)
- if (ieee80211_sdata_running(sdata))
- ieee80211_enable_keys(sdata);
-
- wake_up:
ieee80211_wake_queues_by_reason(hw,
IEEE80211_QUEUE_STOP_REASON_SUSPEND);
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index aa1c40a..d9e03cf 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -109,7 +109,8 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
if (status->flag & RX_FLAG_MMIC_ERROR)
goto mic_fail;
- if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key)
+ if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key &&
+ rx->key->conf.cipher == WLAN_CIPHER_SUITE_TKIP)
goto update_iv;
return RX_CONTINUE;
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index a178cb3..d75eb39 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -1520,11 +1520,12 @@ static int ip_vs_dst_event(struct notifier_block *this, unsigned long event,
{
struct net_device *dev = ptr;
struct net *net = dev_net(dev);
+ struct netns_ipvs *ipvs = net_ipvs(net);
struct ip_vs_service *svc;
struct ip_vs_dest *dest;
unsigned int idx;
- if (event != NETDEV_UNREGISTER)
+ if (event != NETDEV_UNREGISTER || !ipvs)
return NOTIFY_DONE;
IP_VS_DBG(3, "%s() dev=%s\n", __func__, dev->name);
EnterFunction(2);
@@ -1550,7 +1551,7 @@ static int ip_vs_dst_event(struct notifier_block *this, unsigned long event,
}
}
- list_for_each_entry(dest, &net_ipvs(net)->dest_trash, n_list) {
+ list_for_each_entry(dest, &ipvs->dest_trash, n_list) {
__ip_vs_dev_reset(dest, dev);
}
mutex_unlock(&__ip_vs_mutex);
@@ -2675,6 +2676,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
{
struct ip_vs_timeout_user t;
+ memset(&t, 0, sizeof(t));
__ip_vs_get_timeouts(net, &t);
if (copy_to_user(user, &t, sizeof(t)) != 0)
ret = -EFAULT;
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index f7af8b8..dff164e 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -247,12 +247,15 @@ static void death_by_event(unsigned long ul_conntrack)
{
struct nf_conn *ct = (void *)ul_conntrack;
struct net *net = nf_ct_net(ct);
+ struct nf_conntrack_ecache *ecache = nf_ct_ecache_find(ct);
+
+ BUG_ON(ecache == NULL);
if (nf_conntrack_event(IPCT_DESTROY, ct) < 0) {
/* bad luck, let's retry again */
- ct->timeout.expires = jiffies +
+ ecache->timeout.expires = jiffies +
(random32() % net->ct.sysctl_events_retry_timeout);
- add_timer(&ct->timeout);
+ add_timer(&ecache->timeout);
return;
}
/* we've got the event delivered, now it's dying */
@@ -266,6 +269,9 @@ static void death_by_event(unsigned long ul_conntrack)
void nf_ct_insert_dying_list(struct nf_conn *ct)
{
struct net *net = nf_ct_net(ct);
+ struct nf_conntrack_ecache *ecache = nf_ct_ecache_find(ct);
+
+ BUG_ON(ecache == NULL);
/* add this conntrack to the dying list */
spin_lock_bh(&nf_conntrack_lock);
@@ -273,10 +279,10 @@ void nf_ct_insert_dying_list(struct nf_conn *ct)
&net->ct.dying);
spin_unlock_bh(&nf_conntrack_lock);
/* set a new timer to retry event delivery */
- setup_timer(&ct->timeout, death_by_event, (unsigned long)ct);
- ct->timeout.expires = jiffies +
+ setup_timer(&ecache->timeout, death_by_event, (unsigned long)ct);
+ ecache->timeout.expires = jiffies +
(random32() % net->ct.sysctl_events_retry_timeout);
- add_timer(&ct->timeout);
+ add_timer(&ecache->timeout);
}
EXPORT_SYMBOL_GPL(nf_ct_insert_dying_list);
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index cd1e8e0..a3dffab 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -364,23 +364,6 @@ static void evict_oldest_expect(struct nf_conn *master,
}
}
-static inline int refresh_timer(struct nf_conntrack_expect *i)
-{
- struct nf_conn_help *master_help = nfct_help(i->master);
- const struct nf_conntrack_expect_policy *p;
-
- if (!del_timer(&i->timeout))
- return 0;
-
- p = &rcu_dereference_protected(
- master_help->helper,
- lockdep_is_held(&nf_conntrack_lock)
- )->expect_policy[i->class];
- i->timeout.expires = jiffies + p->timeout * HZ;
- add_timer(&i->timeout);
- return 1;
-}
-
static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect)
{
const struct nf_conntrack_expect_policy *p;
@@ -388,7 +371,7 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect)
struct nf_conn *master = expect->master;
struct nf_conn_help *master_help = nfct_help(master);
struct net *net = nf_ct_exp_net(expect);
- struct hlist_node *n;
+ struct hlist_node *n, *next;
unsigned int h;
int ret = 1;
@@ -399,12 +382,12 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect)
goto out;
}
h = nf_ct_expect_dst_hash(&expect->tuple);
- hlist_for_each_entry(i, n, &net->ct.expect_hash[h], hnode) {
+ hlist_for_each_entry_safe(i, n, next, &net->ct.expect_hash[h], hnode) {
if (expect_matches(i, expect)) {
- /* Refresh timer: if it's dying, ignore.. */
- if (refresh_timer(i)) {
- ret = 0;
- goto out;
+ if (del_timer(&i->timeout)) {
+ nf_ct_unlink_expect(i);
+ nf_ct_expect_put(i);
+ break;
}
} else if (expect_clash(i, expect)) {
ret = -EBUSY;
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index 9228ee0..6092b0c 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -392,8 +392,7 @@ static void htable_put(struct xt_hashlimit_htable *hinfo)
#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
/* Precision saver. */
-static inline u_int32_t
-user2credits(u_int32_t user)
+static u32 user2credits(u32 user)
{
/* If multiplying would overflow... */
if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
@@ -403,7 +402,7 @@ user2credits(u_int32_t user)
return (user * HZ * CREDITS_PER_JIFFY) / XT_HASHLIMIT_SCALE;
}
-static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now)
+static void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now)
{
dh->rateinfo.credit += (now - dh->rateinfo.prev) * CREDITS_PER_JIFFY;
if (dh->rateinfo.credit > dh->rateinfo.credit_cap)
@@ -534,8 +533,7 @@ hashlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
dh->rateinfo.prev = jiffies;
dh->rateinfo.credit = user2credits(hinfo->cfg.avg *
hinfo->cfg.burst);
- dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg *
- hinfo->cfg.burst);
+ dh->rateinfo.credit_cap = dh->rateinfo.credit;
dh->rateinfo.cost = user2credits(hinfo->cfg.avg);
} else {
/* update expiration timeout */
diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c
index 32b7a57..a4c1e45 100644
--- a/net/netfilter/xt_limit.c
+++ b/net/netfilter/xt_limit.c
@@ -88,8 +88,7 @@ limit_mt(const struct sk_buff *skb, struct xt_action_param *par)
}
/* Precision saver. */
-static u_int32_t
-user2credits(u_int32_t user)
+static u32 user2credits(u32 user)
{
/* If multiplying would overflow... */
if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
@@ -118,12 +117,12 @@ static int limit_mt_check(const struct xt_mtchk_param *par)
/* For SMP, we only want to use one set of state. */
r->master = priv;
+ /* User avg in seconds * XT_LIMIT_SCALE: convert to jiffies *
+ 128. */
+ priv->prev = jiffies;
+ priv->credit = user2credits(r->avg * r->burst); /* Credits full. */
if (r->cost == 0) {
- /* User avg in seconds * XT_LIMIT_SCALE: convert to jiffies *
- 128. */
- priv->prev = jiffies;
- priv->credit = user2credits(r->avg * r->burst); /* Credits full. */
- r->credit_cap = user2credits(r->avg * r->burst); /* Credits full. */
+ r->credit_cap = priv->credit; /* Credits full. */
r->cost = user2credits(r->avg);
}
return 0;
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 24bc620..16a94a3 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1345,7 +1345,8 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
dst_pid = addr->nl_pid;
dst_group = ffs(addr->nl_groups);
err = -EPERM;
- if (dst_group && !netlink_capable(sock, NL_NONROOT_SEND))
+ if ((dst_group || dst_pid) &&
+ !netlink_capable(sock, NL_NONROOT_SEND))
goto out;
} else {
dst_pid = nlk->dst_pid;
@@ -2098,6 +2099,7 @@ static void __init netlink_add_usersock_entry(void)
rcu_assign_pointer(nl_table[NETLINK_USERSOCK].listeners, listeners);
nl_table[NETLINK_USERSOCK].module = THIS_MODULE;
nl_table[NETLINK_USERSOCK].registered = 1;
+ nl_table[NETLINK_USERSOCK].nl_nonroot = NL_NONROOT_SEND;
netlink_table_ungrab();
}
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index 732152f..f156382 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -1170,7 +1170,12 @@ static int nr_recvmsg(struct kiocb *iocb, struct socket *sock,
msg->msg_flags |= MSG_TRUNC;
}
- skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+ er = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+ if (er < 0) {
+ skb_free_datagram(sk, skb);
+ release_sock(sk);
+ return er;
+ }
if (sax != NULL) {
sax->sax25_family = AF_NETROM;
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index fafb968..1ab5a02 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -866,7 +866,6 @@ static void tpacket_destruct_skb(struct sk_buff *skb)
if (likely(po->tx_ring.pg_vec)) {
ph = skb_shinfo(skb)->destructor_arg;
- BUG_ON(__packet_get_status(po, ph) != TP_STATUS_SENDING);
BUG_ON(atomic_read(&po->tx_ring.pending) == 0);
atomic_dec(&po->tx_ring.pending);
__packet_set_status(po, ph, TP_STATUS_AVAILABLE);
diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c
index c6fffd9..7737ad3 100644
--- a/net/phonet/af_phonet.c
+++ b/net/phonet/af_phonet.c
@@ -68,7 +68,7 @@ static int pn_socket_create(struct net *net, struct socket *sock, int protocol,
struct phonet_protocol *pnp;
int err;
- if (!capable(CAP_SYS_ADMIN))
+ if (!capable(CAP_SYS_ADMIN) && !capable(CAP_NET_ADMIN))
return -EPERM;
if (protocol == 0) {
diff --git a/net/phonet/socket.c b/net/phonet/socket.c
index ab07711..b24bf54 100644
--- a/net/phonet/socket.c
+++ b/net/phonet/socket.c
@@ -506,7 +506,7 @@ int pn_sock_get_port(struct sock *sk, unsigned short sport)
phonet_get_local_port_range(&pmin, &pmax);
for (port = pmin; port <= pmax; port++) {
- port_cur++;
+ port_cur += PN_HASHSIZE;
if (port_cur < pmin || port_cur > pmax)
port_cur = pmin;
diff --git a/net/rds/recv.c b/net/rds/recv.c
index 596689e..51a8f8e 100644
--- a/net/rds/recv.c
+++ b/net/rds/recv.c
@@ -409,6 +409,8 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
rdsdebug("size %zu flags 0x%x timeo %ld\n", size, msg_flags, timeo);
+ msg->msg_namelen = 0;
+
if (msg_flags & MSG_OOB)
goto out;
@@ -484,6 +486,7 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
sin->sin_port = inc->i_hdr.h_sport;
sin->sin_addr.s_addr = inc->i_saddr;
memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
+ msg->msg_namelen = sizeof(*sin);
}
break;
}
diff --git a/net/rds/send.c b/net/rds/send.c
index c803341..f6bdfb0 100644
--- a/net/rds/send.c
+++ b/net/rds/send.c
@@ -1121,7 +1121,7 @@ rds_send_pong(struct rds_connection *conn, __be16 dport)
rds_stats_inc(s_send_pong);
if (!test_bit(RDS_LL_SEND_FULL, &conn->c_flags))
- rds_send_xmit(conn);
+ queue_delayed_work(rds_wq, &conn->c_send_w, 0);
rds_message_put(rm);
return 0;
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index 2b4ab4b..89ddcb5 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -67,6 +67,9 @@ static int tcf_gact_init(struct nlattr *nla, struct nlattr *est,
struct tcf_common *pc;
int ret = 0;
int err;
+#ifdef CONFIG_GACT_PROB
+ struct tc_gact_p *p_parm = NULL;
+#endif
if (nla == NULL)
return -EINVAL;
@@ -82,6 +85,12 @@ static int tcf_gact_init(struct nlattr *nla, struct nlattr *est,
#ifndef CONFIG_GACT_PROB
if (tb[TCA_GACT_PROB] != NULL)
return -EOPNOTSUPP;
+#else
+ if (tb[TCA_GACT_PROB]) {
+ p_parm = nla_data(tb[TCA_GACT_PROB]);
+ if (p_parm->ptype >= MAX_RAND)
+ return -EINVAL;
+ }
#endif
pc = tcf_hash_check(parm->index, a, bind, &gact_hash_info);
@@ -103,8 +112,7 @@ static int tcf_gact_init(struct nlattr *nla, struct nlattr *est,
spin_lock_bh(&gact->tcf_lock);
gact->tcf_action = parm->action;
#ifdef CONFIG_GACT_PROB
- if (tb[TCA_GACT_PROB] != NULL) {
- struct tc_gact_p *p_parm = nla_data(tb[TCA_GACT_PROB]);
+ if (p_parm) {
gact->tcfg_paction = p_parm->paction;
gact->tcfg_pval = p_parm->pval;
gact->tcfg_ptype = p_parm->ptype;
@@ -132,7 +140,7 @@ static int tcf_gact(struct sk_buff *skb, struct tc_action *a, struct tcf_result
spin_lock(&gact->tcf_lock);
#ifdef CONFIG_GACT_PROB
- if (gact->tcfg_ptype && gact_rand[gact->tcfg_ptype] != NULL)
+ if (gact->tcfg_ptype)
action = gact_rand[gact->tcfg_ptype](gact);
else
action = gact->tcf_action;
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index 24d94c0..599f67a 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -250,10 +250,11 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
else if ((cl = defmap[res.classid & TC_PRIO_MAX]) == NULL)
cl = defmap[TC_PRIO_BESTEFFORT];
- if (cl == NULL || cl->level >= head->level)
+ if (cl == NULL)
goto fallback;
}
-
+ if (cl->level >= head->level)
+ goto fallback;
#ifdef CONFIG_NET_CLS_ACT
switch (result) {
case TC_ACT_QUEUED:
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 2f68459..945f3dd 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -350,10 +350,8 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
if (q->corrupt && q->corrupt >= get_crandom(&q->corrupt_cor)) {
if (!(skb = skb_unshare(skb, GFP_ATOMIC)) ||
(skb->ip_summed == CHECKSUM_PARTIAL &&
- skb_checksum_help(skb))) {
- sch->qstats.drops++;
- return NET_XMIT_DROP;
- }
+ skb_checksum_help(skb)))
+ return qdisc_drop(skb, sch);
skb->data[net_random() % skb_headlen(skb)] ^= 1<<(net_random() % 8);
}
diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c
index 1033434..f86bc72 100644
--- a/net/sched/sch_qfq.c
+++ b/net/sched/sch_qfq.c
@@ -829,7 +829,10 @@ static void qfq_update_start(struct qfq_sched *q, struct qfq_class *cl)
if (mask) {
struct qfq_group *next = qfq_ffs(q, mask);
if (qfq_gt(roundedF, next->F)) {
- cl->S = next->F;
+ if (qfq_gt(limit, next->F))
+ cl->S = next->F;
+ else /* preserve timestamp correctness */
+ cl->S = limit;
return;
}
}
diff --git a/net/sched/sch_sfb.c b/net/sched/sch_sfb.c
index 47ee29f..e85b2487 100644
--- a/net/sched/sch_sfb.c
+++ b/net/sched/sch_sfb.c
@@ -556,6 +556,8 @@ static int sfb_dump(struct Qdisc *sch, struct sk_buff *skb)
sch->qstats.backlog = q->qdisc->qstats.backlog;
opts = nla_nest_start(skb, TCA_OPTIONS);
+ if (opts == NULL)
+ goto nla_put_failure;
NLA_PUT(skb, TCA_SFB_PARMS, sizeof(opt), &opt);
return nla_nest_end(skb, opts);
diff --git a/net/sctp/input.c b/net/sctp/input.c
index 741ed16..cd9eded 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -737,15 +737,12 @@ static void __sctp_unhash_endpoint(struct sctp_endpoint *ep)
epb = &ep->base;
- if (hlist_unhashed(&epb->node))
- return;
-
epb->hashent = sctp_ep_hashfn(epb->bind_addr.port);
head = &sctp_ep_hashtable[epb->hashent];
sctp_write_lock(&head->lock);
- __hlist_del(&epb->node);
+ hlist_del_init(&epb->node);
sctp_write_unlock(&head->lock);
}
@@ -826,7 +823,7 @@ static void __sctp_unhash_established(struct sctp_association *asoc)
head = &sctp_assoc_hashtable[epb->hashent];
sctp_write_lock(&head->lock);
- __hlist_del(&epb->node);
+ hlist_del_init(&epb->node);
sctp_write_unlock(&head->lock);
}
diff --git a/net/sctp/output.c b/net/sctp/output.c
index 817174e..32ba8d0 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -334,6 +334,25 @@ finish:
return retval;
}
+static void sctp_packet_release_owner(struct sk_buff *skb)
+{
+ sk_free(skb->sk);
+}
+
+static void sctp_packet_set_owner_w(struct sk_buff *skb, struct sock *sk)
+{
+ skb_orphan(skb);
+ skb->sk = sk;
+ skb->destructor = sctp_packet_release_owner;
+
+ /*
+ * The data chunks have already been accounted for in sctp_sendmsg(),
+ * therefore only reserve a single byte to keep socket around until
+ * the packet has been transmitted.
+ */
+ atomic_inc(&sk->sk_wmem_alloc);
+}
+
/* All packets are sent to the network through this function from
* sctp_outq_tail().
*
@@ -375,11 +394,9 @@ int sctp_packet_transmit(struct sctp_packet *packet)
/* Set the owning socket so that we know where to get the
* destination IP address.
*/
- skb_set_owner_w(nskb, sk);
+ sctp_packet_set_owner_w(nskb, sk);
- /* The 'obsolete' field of dst is set to 2 when a dst is freed. */
- if (!dst || (dst->obsolete > 1)) {
- dst_release(dst);
+ if (!sctp_transport_dst_check(tp)) {
sctp_transport_route(tp, NULL, sctp_sk(sk));
if (asoc && (asoc->param_flags & SPP_PMTUD_ENABLE)) {
sctp_assoc_sync_pmtu(asoc);
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 4434853..b70a3ee 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -1160,8 +1160,14 @@ out_free:
SCTP_DEBUG_PRINTK("About to exit __sctp_connect() free asoc: %p"
" kaddrs: %p err: %d\n",
asoc, kaddrs, err);
- if (asoc)
+ if (asoc) {
+ /* sctp_primitive_ASSOCIATE may have added this association
+ * To the hash table, try to unhash it, just in case, its a noop
+ * if it wasn't hashed so we're safe
+ */
+ sctp_unhash_established(asoc);
sctp_association_free(asoc);
+ }
return err;
}
@@ -1871,8 +1877,10 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
goto out_unlock;
out_free:
- if (new_asoc)
+ if (new_asoc) {
+ sctp_unhash_established(asoc);
sctp_association_free(asoc);
+ }
out_unlock:
sctp_release_sock(sk);
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index 394c57c..8da4481 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -226,23 +226,6 @@ void sctp_transport_pmtu(struct sctp_transport *transport, struct sock *sk)
transport->pathmtu = SCTP_DEFAULT_MAXSEGMENT;
}
-/* this is a complete rip-off from __sk_dst_check
- * the cookie is always 0 since this is how it's used in the
- * pmtu code
- */
-static struct dst_entry *sctp_transport_dst_check(struct sctp_transport *t)
-{
- struct dst_entry *dst = t->dst;
-
- if (dst && dst->obsolete && dst->ops->check(dst, 0) == NULL) {
- dst_release(t->dst);
- t->dst = NULL;
- return NULL;
- }
-
- return dst;
-}
-
void sctp_transport_update_pmtu(struct sctp_transport *t, u32 pmtu)
{
struct dst_entry *dst;
diff --git a/net/socket.c b/net/socket.c
index cf41afc..1b0f0fc 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -2645,6 +2645,7 @@ static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32)
if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf)))
return -EFAULT;
+ memset(&ifc, 0, sizeof(ifc));
if (ifc32.ifcbuf == 0) {
ifc32.ifc_len = 0;
ifc.ifc_len = 0;
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index 4530a91..237a2ee 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -1404,11 +1404,11 @@ static ssize_t read_flush(struct file *file, char __user *buf,
size_t count, loff_t *ppos,
struct cache_detail *cd)
{
- char tbuf[20];
+ char tbuf[22];
unsigned long p = *ppos;
size_t len;
- sprintf(tbuf, "%lu\n", convert_to_wallclock(cd->flush_time));
+ snprintf(tbuf, sizeof(tbuf), "%lu\n", convert_to_wallclock(cd->flush_time));
len = strlen(tbuf);
if (p >= len)
return 0;
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index e45d2fb..bf0a7f6 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -193,7 +193,7 @@ static int rpcb_create_local_unix(void)
if (IS_ERR(clnt)) {
dprintk("RPC: failed to create AF_LOCAL rpcbind "
"client (errno %ld).\n", PTR_ERR(clnt));
- result = -PTR_ERR(clnt);
+ result = PTR_ERR(clnt);
goto out;
}
@@ -242,7 +242,7 @@ static int rpcb_create_local_net(void)
if (IS_ERR(clnt)) {
dprintk("RPC: failed to create local rpcbind "
"client (errno %ld).\n", PTR_ERR(clnt));
- result = -PTR_ERR(clnt);
+ result = PTR_ERR(clnt);
goto out;
}
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index b6bb225..c57f97f 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -713,7 +713,9 @@ void rpc_execute(struct rpc_task *task)
static void rpc_async_schedule(struct work_struct *work)
{
+ current->flags |= PF_FSTRANS;
__rpc_execute(container_of(work, struct rpc_task, u.tk_work));
+ current->flags &= ~PF_FSTRANS;
}
/**
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index ce5f111..54c59ab 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -1302,7 +1302,8 @@ bc_svc_process(struct svc_serv *serv, struct rpc_rqst *req,
sizeof(req->rq_snd_buf));
return bc_send(req);
} else {
- /* Nothing to do to drop request */
+ /* drop request */
+ xprt_free_bc_request(req);
return 0;
}
}
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
index 9d7ed0b..05dbccf 100644
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
@@ -323,7 +323,6 @@ static bool svc_xprt_has_something_to_do(struct svc_xprt *xprt)
*/
void svc_xprt_enqueue(struct svc_xprt *xprt)
{
- struct svc_serv *serv = xprt->xpt_server;
struct svc_pool *pool;
struct svc_rqst *rqstp;
int cpu;
@@ -369,8 +368,6 @@ void svc_xprt_enqueue(struct svc_xprt *xprt)
rqstp, rqstp->rq_xprt);
rqstp->rq_xprt = xprt;
svc_xprt_get(xprt);
- rqstp->rq_reserved = serv->sv_max_mesg;
- atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved);
pool->sp_stats.threads_woken++;
wake_up(&rqstp->rq_wait);
} else {
@@ -650,8 +647,6 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
if (xprt) {
rqstp->rq_xprt = xprt;
svc_xprt_get(xprt);
- rqstp->rq_reserved = serv->sv_max_mesg;
- atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved);
/* As there is a shortage of threads and this request
* had to be queued, don't allow the thread to wait so
@@ -748,6 +743,8 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
else
len = xprt->xpt_ops->xpo_recvfrom(rqstp);
dprintk("svc: got len=%d\n", len);
+ rqstp->rq_reserved = serv->sv_max_mesg;
+ atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved);
}
svc_xprt_received(xprt);
@@ -804,7 +801,8 @@ int svc_send(struct svc_rqst *rqstp)
/* Grab mutex to serialize outgoing data. */
mutex_lock(&xprt->xpt_mutex);
- if (test_bit(XPT_DEAD, &xprt->xpt_flags))
+ if (test_bit(XPT_DEAD, &xprt->xpt_flags)
+ || test_bit(XPT_CLOSE, &xprt->xpt_flags))
len = -ENOTCONN;
else
len = xprt->xpt_ops->xpo_sendto(rqstp);
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index af04f77..80c6c96 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -1122,9 +1122,9 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
if (len >= 0)
svsk->sk_tcplen += len;
if (len != want) {
+ svc_tcp_save_pages(svsk, rqstp);
if (len < 0 && len != -EAGAIN)
goto err_other;
- svc_tcp_save_pages(svsk, rqstp);
dprintk("svc: incomplete TCP record (%d of %d)\n",
svsk->sk_tcplen, svsk->sk_reclen);
goto err_noclose;
diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c
index 0867070..d0b5210 100644
--- a/net/sunrpc/xprtrdma/transport.c
+++ b/net/sunrpc/xprtrdma/transport.c
@@ -200,6 +200,7 @@ xprt_rdma_connect_worker(struct work_struct *work)
int rc = 0;
if (!xprt->shutdown) {
+ current->flags |= PF_FSTRANS;
xprt_clear_connected(xprt);
dprintk("RPC: %s: %sconnect\n", __func__,
@@ -212,10 +213,10 @@ xprt_rdma_connect_worker(struct work_struct *work)
out:
xprt_wake_pending_tasks(xprt, rc);
-
out_clear:
dprintk("RPC: %s: exit\n", __func__);
xprt_clear_connecting(xprt);
+ current->flags &= ~PF_FSTRANS;
}
/*
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index ea75079..2202a14 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -243,7 +243,6 @@ struct sock_xprt {
void (*old_data_ready)(struct sock *, int);
void (*old_state_change)(struct sock *);
void (*old_write_space)(struct sock *);
- void (*old_error_report)(struct sock *);
};
/*
@@ -726,10 +725,10 @@ static int xs_tcp_send_request(struct rpc_task *task)
dprintk("RPC: sendmsg returned unrecognized error %d\n",
-status);
case -ECONNRESET:
- case -EPIPE:
xs_tcp_shutdown(xprt);
case -ECONNREFUSED:
case -ENOTCONN:
+ case -EPIPE:
clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
}
@@ -768,7 +767,6 @@ static void xs_save_old_callbacks(struct sock_xprt *transport, struct sock *sk)
transport->old_data_ready = sk->sk_data_ready;
transport->old_state_change = sk->sk_state_change;
transport->old_write_space = sk->sk_write_space;
- transport->old_error_report = sk->sk_error_report;
}
static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *sk)
@@ -776,7 +774,6 @@ static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *s
sk->sk_data_ready = transport->old_data_ready;
sk->sk_state_change = transport->old_state_change;
sk->sk_write_space = transport->old_write_space;
- sk->sk_error_report = transport->old_error_report;
}
static void xs_reset_transport(struct sock_xprt *transport)
@@ -1015,6 +1012,16 @@ static void xs_udp_data_ready(struct sock *sk, int len)
read_unlock_bh(&sk->sk_callback_lock);
}
+/*
+ * Helper function to force a TCP close if the server is sending
+ * junk and/or it has put us in CLOSE_WAIT
+ */
+static void xs_tcp_force_close(struct rpc_xprt *xprt)
+{
+ set_bit(XPRT_CONNECTION_CLOSE, &xprt->state);
+ xprt_force_disconnect(xprt);
+}
+
static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, struct xdr_skb_reader *desc)
{
struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
@@ -1041,7 +1048,7 @@ static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, struct xdr_skb_rea
/* Sanity check of the record length */
if (unlikely(transport->tcp_reclen < 8)) {
dprintk("RPC: invalid TCP record fragment length\n");
- xprt_force_disconnect(xprt);
+ xs_tcp_force_close(xprt);
return;
}
dprintk("RPC: reading TCP record fragment of length %d\n",
@@ -1122,7 +1129,7 @@ static inline void xs_tcp_read_calldir(struct sock_xprt *transport,
break;
default:
dprintk("RPC: invalid request message type\n");
- xprt_force_disconnect(&transport->xprt);
+ xs_tcp_force_close(&transport->xprt);
}
xs_tcp_check_fraghdr(transport);
}
@@ -1442,12 +1449,19 @@ static void xs_tcp_cancel_linger_timeout(struct rpc_xprt *xprt)
xprt_clear_connecting(xprt);
}
-static void xs_sock_mark_closed(struct rpc_xprt *xprt)
+static void xs_sock_reset_connection_flags(struct rpc_xprt *xprt)
{
smp_mb__before_clear_bit();
+ clear_bit(XPRT_CONNECTION_ABORT, &xprt->state);
+ clear_bit(XPRT_CONNECTION_CLOSE, &xprt->state);
clear_bit(XPRT_CLOSE_WAIT, &xprt->state);
clear_bit(XPRT_CLOSING, &xprt->state);
smp_mb__after_clear_bit();
+}
+
+static void xs_sock_mark_closed(struct rpc_xprt *xprt)
+{
+ xs_sock_reset_connection_flags(xprt);
/* Mark transport as closed and wake up all pending tasks */
xprt_disconnect_done(xprt);
}
@@ -1502,8 +1516,9 @@ static void xs_tcp_state_change(struct sock *sk)
break;
case TCP_CLOSE_WAIT:
/* The server initiated a shutdown of the socket */
- xprt_force_disconnect(xprt);
xprt->connect_cookie++;
+ clear_bit(XPRT_CONNECTED, &xprt->state);
+ xs_tcp_force_close(xprt);
case TCP_CLOSING:
/*
* If the server closed down the connection, make sure that
@@ -1527,25 +1542,6 @@ static void xs_tcp_state_change(struct sock *sk)
read_unlock_bh(&sk->sk_callback_lock);
}
-/**
- * xs_error_report - callback mainly for catching socket errors
- * @sk: socket
- */
-static void xs_error_report(struct sock *sk)
-{
- struct rpc_xprt *xprt;
-
- read_lock_bh(&sk->sk_callback_lock);
- if (!(xprt = xprt_from_sock(sk)))
- goto out;
- dprintk("RPC: %s client %p...\n"
- "RPC: error %d\n",
- __func__, xprt, sk->sk_err);
- xprt_wake_pending_tasks(xprt, -EAGAIN);
-out:
- read_unlock_bh(&sk->sk_callback_lock);
-}
-
static void xs_write_space(struct sock *sk)
{
struct socket *sock;
@@ -1845,7 +1841,6 @@ static int xs_local_finish_connecting(struct rpc_xprt *xprt,
sk->sk_user_data = xprt;
sk->sk_data_ready = xs_local_data_ready;
sk->sk_write_space = xs_udp_write_space;
- sk->sk_error_report = xs_error_report;
sk->sk_allocation = GFP_ATOMIC;
xprt_clear_connected(xprt);
@@ -1882,6 +1877,8 @@ static void xs_local_setup_socket(struct work_struct *work)
if (xprt->shutdown)
goto out;
+ current->flags |= PF_FSTRANS;
+
clear_bit(XPRT_CONNECTION_ABORT, &xprt->state);
status = __sock_create(xprt->xprt_net, AF_LOCAL,
SOCK_STREAM, 0, &sock, 1);
@@ -1915,6 +1912,7 @@ static void xs_local_setup_socket(struct work_struct *work)
out:
xprt_clear_connecting(xprt);
xprt_wake_pending_tasks(xprt, status);
+ current->flags &= ~PF_FSTRANS;
}
static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
@@ -1931,7 +1929,6 @@ static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
sk->sk_user_data = xprt;
sk->sk_data_ready = xs_udp_data_ready;
sk->sk_write_space = xs_udp_write_space;
- sk->sk_error_report = xs_error_report;
sk->sk_no_check = UDP_CSUM_NORCV;
sk->sk_allocation = GFP_ATOMIC;
@@ -1957,6 +1954,8 @@ static void xs_udp_setup_socket(struct work_struct *work)
if (xprt->shutdown)
goto out;
+ current->flags |= PF_FSTRANS;
+
/* Start by resetting any existing state */
xs_reset_transport(transport);
sock = xs_create_sock(xprt, transport,
@@ -1975,6 +1974,7 @@ static void xs_udp_setup_socket(struct work_struct *work)
out:
xprt_clear_connecting(xprt);
xprt_wake_pending_tasks(xprt, status);
+ current->flags &= ~PF_FSTRANS;
}
/*
@@ -1996,10 +1996,8 @@ static void xs_abort_connection(struct sock_xprt *transport)
any.sa_family = AF_UNSPEC;
result = kernel_connect(transport->sock, &any, sizeof(any), 0);
if (!result)
- xs_sock_mark_closed(&transport->xprt);
- else
- dprintk("RPC: AF_UNSPEC connect return code %d\n",
- result);
+ xs_sock_reset_connection_flags(&transport->xprt);
+ dprintk("RPC: AF_UNSPEC connect return code %d\n", result);
}
static void xs_tcp_reuse_connection(struct sock_xprt *transport)
@@ -2044,7 +2042,6 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
sk->sk_data_ready = xs_tcp_data_ready;
sk->sk_state_change = xs_tcp_state_change;
sk->sk_write_space = xs_tcp_write_space;
- sk->sk_error_report = xs_error_report;
sk->sk_allocation = GFP_ATOMIC;
/* socket options */
@@ -2100,6 +2097,8 @@ static void xs_tcp_setup_socket(struct work_struct *work)
if (xprt->shutdown)
goto out;
+ current->flags |= PF_FSTRANS;
+
if (!sock) {
clear_bit(XPRT_CONNECTION_ABORT, &xprt->state);
sock = xs_create_sock(xprt, transport,
@@ -2138,8 +2137,7 @@ static void xs_tcp_setup_socket(struct work_struct *work)
/* We're probably in TIME_WAIT. Get rid of existing socket,
* and retry
*/
- set_bit(XPRT_CONNECTION_CLOSE, &xprt->state);
- xprt_force_disconnect(xprt);
+ xs_tcp_force_close(xprt);
break;
case -ECONNREFUSED:
case -ECONNRESET:
@@ -2149,6 +2147,7 @@ static void xs_tcp_setup_socket(struct work_struct *work)
case -EINPROGRESS:
case -EALREADY:
xprt_clear_connecting(xprt);
+ current->flags &= ~PF_FSTRANS;
return;
case -EINVAL:
/* Happens, for instance, if the user specified a link
@@ -2161,6 +2160,7 @@ out_eagain:
out:
xprt_clear_connecting(xprt);
xprt_wake_pending_tasks(xprt, status);
+ current->flags &= ~PF_FSTRANS;
}
/**
diff --git a/net/wanrouter/wanmain.c b/net/wanrouter/wanmain.c
index 788a12c..2ab7850 100644
--- a/net/wanrouter/wanmain.c
+++ b/net/wanrouter/wanmain.c
@@ -602,36 +602,31 @@ static int wanrouter_device_new_if(struct wan_device *wandev,
* successfully, add it to the interface list.
*/
- if (dev->name == NULL) {
- err = -EINVAL;
- } else {
+#ifdef WANDEBUG
+ printk(KERN_INFO "%s: registering interface %s...\n",
+ wanrouter_modname, dev->name);
+#endif
- #ifdef WANDEBUG
- printk(KERN_INFO "%s: registering interface %s...\n",
- wanrouter_modname, dev->name);
- #endif
-
- err = register_netdev(dev);
- if (!err) {
- struct net_device *slave = NULL;
- unsigned long smp_flags=0;
-
- lock_adapter_irq(&wandev->lock, &smp_flags);
-
- if (wandev->dev == NULL) {
- wandev->dev = dev;
- } else {
- for (slave=wandev->dev;
- DEV_TO_SLAVE(slave);
- slave = DEV_TO_SLAVE(slave))
- DEV_TO_SLAVE(slave) = dev;
- }
- ++wandev->ndev;
-
- unlock_adapter_irq(&wandev->lock, &smp_flags);
- err = 0; /* done !!! */
- goto out;
+ err = register_netdev(dev);
+ if (!err) {
+ struct net_device *slave = NULL;
+ unsigned long smp_flags=0;
+
+ lock_adapter_irq(&wandev->lock, &smp_flags);
+
+ if (wandev->dev == NULL) {
+ wandev->dev = dev;
+ } else {
+ for (slave=wandev->dev;
+ DEV_TO_SLAVE(slave);
+ slave = DEV_TO_SLAVE(slave))
+ DEV_TO_SLAVE(slave) = dev;
}
+ ++wandev->ndev;
+
+ unlock_adapter_irq(&wandev->lock, &smp_flags);
+ err = 0; /* done !!! */
+ goto out;
}
if (wandev->del_if)
wandev->del_if(wandev, dev);
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 8ba1553..b6d7652 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -967,6 +967,11 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
*/
synchronize_rcu();
INIT_LIST_HEAD(&wdev->list);
+ /*
+ * Ensure that all events have been processed and
+ * freed.
+ */
+ cfg80211_process_wdev_events(wdev);
break;
case NETDEV_PRE_UP:
if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype)))
diff --git a/net/wireless/core.h b/net/wireless/core.h
index a020d38..4430e67 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -428,6 +428,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
struct net_device *dev, enum nl80211_iftype ntype,
u32 *flags, struct vif_params *params);
void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev);
+void cfg80211_process_wdev_events(struct wireless_dev *wdev);
int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev,
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 72f7fee..bcd9624 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -331,6 +331,9 @@ static void reg_regdb_search(struct work_struct *work)
struct reg_regdb_search_request *request;
const struct ieee80211_regdomain *curdom, *regdom;
int i, r;
+ bool set_reg = false;
+
+ mutex_lock(&cfg80211_mutex);
mutex_lock(&reg_regdb_search_mutex);
while (!list_empty(&reg_regdb_search_list)) {
@@ -346,9 +349,7 @@ static void reg_regdb_search(struct work_struct *work)
r = reg_copy_regd(&regdom, curdom);
if (r)
break;
- mutex_lock(&cfg80211_mutex);
- set_regdom(regdom);
- mutex_unlock(&cfg80211_mutex);
+ set_reg = true;
break;
}
}
@@ -356,6 +357,11 @@ static void reg_regdb_search(struct work_struct *work)
kfree(request);
}
mutex_unlock(&reg_regdb_search_mutex);
+
+ if (set_reg)
+ set_regdom(regdom);
+
+ mutex_unlock(&cfg80211_mutex);
}
static DECLARE_WORK(reg_regdb_work, reg_regdb_search);
@@ -379,7 +385,15 @@ static void reg_regdb_query(const char *alpha2)
schedule_work(&reg_regdb_work);
}
+
+/* Feel free to add any other sanity checks here */
+static void reg_regdb_size_check(void)
+{
+ /* We should ideally BUILD_BUG_ON() but then random builds would fail */
+ WARN_ONCE(!reg_regdb_size, "db.txt is empty, you should update it...");
+}
#else
+static inline void reg_regdb_size_check(void) {}
static inline void reg_regdb_query(const char *alpha2) {}
#endif /* CONFIG_CFG80211_INTERNAL_REGDB */
@@ -1350,7 +1364,7 @@ static void reg_set_request_processed(void)
spin_unlock(&reg_requests_lock);
if (last_request->initiator == NL80211_REGDOM_SET_BY_USER)
- cancel_delayed_work_sync(&reg_timeout);
+ cancel_delayed_work(&reg_timeout);
if (need_more_processing)
schedule_work(&reg_work);
@@ -2228,6 +2242,8 @@ int __init regulatory_init(void)
spin_lock_init(&reg_requests_lock);
spin_lock_init(&reg_pending_beacons_lock);
+ reg_regdb_size_check();
+
cfg80211_regdomain = cfg80211_world_regdom;
user_alpha2[0] = '9';
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 9c22330..18e22be 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -719,7 +719,7 @@ void cfg80211_upload_connect_keys(struct wireless_dev *wdev)
wdev->connect_keys = NULL;
}
-static void cfg80211_process_wdev_events(struct wireless_dev *wdev)
+void cfg80211_process_wdev_events(struct wireless_dev *wdev)
{
struct cfg80211_event *ev;
unsigned long flags;
@@ -807,7 +807,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
ntype == NL80211_IFTYPE_P2P_CLIENT))
return -EBUSY;
- if (ntype != otype) {
+ if (ntype != otype && netif_running(dev)) {
err = cfg80211_can_change_interface(rdev, dev->ieee80211_ptr,
ntype);
if (err)
@@ -937,6 +937,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
enum nl80211_iftype iftype)
{
struct wireless_dev *wdev_iter;
+ u32 used_iftypes = BIT(iftype);
int num[NUM_NL80211_IFTYPES];
int total = 1;
int i, j;
@@ -970,12 +971,17 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
num[wdev_iter->iftype]++;
total++;
+ used_iftypes |= BIT(wdev_iter->iftype);
}
mutex_unlock(&rdev->devlist_mtx);
+ if (total == 1)
+ return 0;
+
for (i = 0; i < rdev->wiphy.n_iface_combinations; i++) {
const struct ieee80211_iface_combination *c;
struct ieee80211_iface_limit *limits;
+ u32 all_iftypes = 0;
c = &rdev->wiphy.iface_combinations[i];
@@ -990,6 +996,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
if (rdev->wiphy.software_iftypes & BIT(iftype))
continue;
for (j = 0; j < c->n_limits; j++) {
+ all_iftypes |= limits[j].types;
if (!(limits[j].types & BIT(iftype)))
continue;
if (limits[j].max < num[iftype])
@@ -997,7 +1004,20 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
limits[j].max -= num[iftype];
}
}
- /* yay, it fits */
+
+ /*
+ * Finally check that all iftypes that we're currently
+ * using are actually part of this combination. If they
+ * aren't then we can't use this combination and have
+ * to continue to the next.
+ */
+ if ((all_iftypes & used_iftypes) != used_iftypes)
+ goto cont;
+
+ /*
+ * This combination covered all interface types and
+ * supported the requested numbers, so we're good.
+ */
kfree(limits);
return 0;
cont:
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 54a0dc2..ab2bb42 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -212,7 +212,7 @@ resume:
/* only the first xfrm gets the encap type */
encap_type = 0;
- if (async && x->repl->check(x, skb, seq)) {
+ if (async && x->repl->recheck(x, skb, seq)) {
XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATESEQERROR);
goto drop_unlock;
}
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 1b906c3..6b9e4e1 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1761,7 +1761,7 @@ static struct dst_entry *make_blackhole(struct net *net, u16 family,
if (!afinfo) {
dst_release(dst_orig);
- ret = ERR_PTR(-EINVAL);
+ return ERR_PTR(-EINVAL);
} else {
ret = afinfo->blackhole_route(net, dst_orig);
}
@@ -1919,6 +1919,9 @@ no_transform:
}
ok:
xfrm_pols_put(pols, drop_pols);
+ if (dst && dst->xfrm &&
+ dst->xfrm->props.mode == XFRM_MODE_TUNNEL)
+ dst->flags |= DST_XFRM_TUNNEL;
return dst;
nopol:
diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c
index 3235023..379c176 100644
--- a/net/xfrm/xfrm_replay.c
+++ b/net/xfrm/xfrm_replay.c
@@ -437,6 +437,18 @@ err:
return -EINVAL;
}
+static int xfrm_replay_recheck_esn(struct xfrm_state *x,
+ struct sk_buff *skb, __be32 net_seq)
+{
+ if (unlikely(XFRM_SKB_CB(skb)->seq.input.hi !=
+ htonl(xfrm_replay_seqhi(x, net_seq)))) {
+ x->stats.replay_window++;
+ return -EINVAL;
+ }
+
+ return xfrm_replay_check_esn(x, skb, net_seq);
+}
+
static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq)
{
unsigned int bitnr, nr, i;
@@ -508,6 +520,7 @@ static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq)
static struct xfrm_replay xfrm_replay_legacy = {
.advance = xfrm_replay_advance,
.check = xfrm_replay_check,
+ .recheck = xfrm_replay_check,
.notify = xfrm_replay_notify,
.overflow = xfrm_replay_overflow,
};
@@ -515,6 +528,7 @@ static struct xfrm_replay xfrm_replay_legacy = {
static struct xfrm_replay xfrm_replay_bmp = {
.advance = xfrm_replay_advance_bmp,
.check = xfrm_replay_check_bmp,
+ .recheck = xfrm_replay_check_bmp,
.notify = xfrm_replay_notify_bmp,
.overflow = xfrm_replay_overflow_bmp,
};
@@ -522,6 +536,7 @@ static struct xfrm_replay xfrm_replay_bmp = {
static struct xfrm_replay xfrm_replay_esn = {
.advance = xfrm_replay_advance_esn,
.check = xfrm_replay_check_esn,
+ .recheck = xfrm_replay_recheck_esn,
.notify = xfrm_replay_notify_bmp,
.overflow = xfrm_replay_overflow_esn,
};
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index c658cb3..05f82e6 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -123,9 +123,21 @@ static inline int verify_replay(struct xfrm_usersa_info *p,
struct nlattr **attrs)
{
struct nlattr *rt = attrs[XFRMA_REPLAY_ESN_VAL];
+ struct xfrm_replay_state_esn *rs;
- if ((p->flags & XFRM_STATE_ESN) && !rt)
- return -EINVAL;
+ if (p->flags & XFRM_STATE_ESN) {
+ if (!rt)
+ return -EINVAL;
+
+ rs = nla_data(rt);
+
+ if (rs->bmp_len > XFRMA_REPLAY_ESN_MAX / sizeof(rs->bmp[0]) / 8)
+ return -EINVAL;
+
+ if (nla_len(rt) < xfrm_replay_state_esn_len(rs) &&
+ nla_len(rt) != sizeof(*rs))
+ return -EINVAL;
+ }
if (!rt)
return 0;
@@ -370,14 +382,15 @@ static inline int xfrm_replay_verify_len(struct xfrm_replay_state_esn *replay_es
struct nlattr *rp)
{
struct xfrm_replay_state_esn *up;
+ int ulen;
if (!replay_esn || !rp)
return 0;
up = nla_data(rp);
+ ulen = xfrm_replay_state_esn_len(up);
- if (xfrm_replay_state_esn_len(replay_esn) !=
- xfrm_replay_state_esn_len(up))
+ if (nla_len(rp) < ulen || xfrm_replay_state_esn_len(replay_esn) != ulen)
return -EINVAL;
return 0;
@@ -388,22 +401,28 @@ static int xfrm_alloc_replay_state_esn(struct xfrm_replay_state_esn **replay_esn
struct nlattr *rta)
{
struct xfrm_replay_state_esn *p, *pp, *up;
+ int klen, ulen;
if (!rta)
return 0;
up = nla_data(rta);
+ klen = xfrm_replay_state_esn_len(up);
+ ulen = nla_len(rta) >= klen ? klen : sizeof(*up);
- p = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL);
+ p = kzalloc(klen, GFP_KERNEL);
if (!p)
return -ENOMEM;
- pp = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL);
+ pp = kzalloc(klen, GFP_KERNEL);
if (!pp) {
kfree(p);
return -ENOMEM;
}
+ memcpy(p, up, ulen);
+ memcpy(pp, up, ulen);
+
*replay_esn = p;
*preplay_esn = pp;
@@ -442,10 +461,11 @@ static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *
* somehow made shareable and move it to xfrm_state.c - JHS
*
*/
-static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs)
+static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs,
+ int update_esn)
{
struct nlattr *rp = attrs[XFRMA_REPLAY_VAL];
- struct nlattr *re = attrs[XFRMA_REPLAY_ESN_VAL];
+ struct nlattr *re = update_esn ? attrs[XFRMA_REPLAY_ESN_VAL] : NULL;
struct nlattr *lt = attrs[XFRMA_LTIME_VAL];
struct nlattr *et = attrs[XFRMA_ETIMER_THRESH];
struct nlattr *rt = attrs[XFRMA_REPLAY_THRESH];
@@ -555,7 +575,7 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
goto error;
/* override default values from above */
- xfrm_update_ae_params(x, attrs);
+ xfrm_update_ae_params(x, attrs, 0);
return x;
@@ -689,6 +709,7 @@ out:
static void copy_to_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p)
{
+ memset(p, 0, sizeof(*p));
memcpy(&p->id, &x->id, sizeof(p->id));
memcpy(&p->sel, &x->sel, sizeof(p->sel));
memcpy(&p->lft, &x->lft, sizeof(p->lft));
@@ -742,7 +763,7 @@ static int copy_to_user_auth(struct xfrm_algo_auth *auth, struct sk_buff *skb)
return -EMSGSIZE;
algo = nla_data(nla);
- strcpy(algo->alg_name, auth->alg_name);
+ strncpy(algo->alg_name, auth->alg_name, sizeof(algo->alg_name));
memcpy(algo->alg_key, auth->alg_key, (auth->alg_key_len + 7) / 8);
algo->alg_key_len = auth->alg_key_len;
@@ -862,6 +883,7 @@ static struct sk_buff *xfrm_state_netlink(struct sk_buff *in_skb,
{
struct xfrm_dump_info info;
struct sk_buff *skb;
+ int err;
skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
if (!skb)
@@ -872,9 +894,10 @@ static struct sk_buff *xfrm_state_netlink(struct sk_buff *in_skb,
info.nlmsg_seq = seq;
info.nlmsg_flags = 0;
- if (dump_one_state(x, 0, &info)) {
+ err = dump_one_state(x, 0, &info);
+ if (err) {
kfree_skb(skb);
- return NULL;
+ return ERR_PTR(err);
}
return skb;
@@ -1297,6 +1320,7 @@ static void copy_from_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy
static void copy_to_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy_info *p, int dir)
{
+ memset(p, 0, sizeof(*p));
memcpy(&p->sel, &xp->selector, sizeof(p->sel));
memcpy(&p->lft, &xp->lft, sizeof(p->lft));
memcpy(&p->curlft, &xp->curlft, sizeof(p->curlft));
@@ -1401,6 +1425,7 @@ static int copy_to_user_tmpl(struct xfrm_policy *xp, struct sk_buff *skb)
struct xfrm_user_tmpl *up = &vec[i];
struct xfrm_tmpl *kp = &xp->xfrm_vec[i];
+ memset(up, 0, sizeof(*up));
memcpy(&up->id, &kp->id, sizeof(up->id));
up->family = kp->encap_family;
memcpy(&up->saddr, &kp->saddr, sizeof(up->saddr));
@@ -1529,6 +1554,7 @@ static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb,
{
struct xfrm_dump_info info;
struct sk_buff *skb;
+ int err;
skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (!skb)
@@ -1539,9 +1565,10 @@ static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb,
info.nlmsg_seq = seq;
info.nlmsg_flags = 0;
- if (dump_one_policy(xp, dir, 0, &info) < 0) {
+ err = dump_one_policy(xp, dir, 0, &info);
+ if (err) {
kfree_skb(skb);
- return NULL;
+ return ERR_PTR(err);
}
return skb;
@@ -1794,7 +1821,7 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
goto out;
spin_lock_bh(&x->lock);
- xfrm_update_ae_params(x, attrs);
+ xfrm_update_ae_params(x, attrs, 1);
spin_unlock_bh(&x->lock);
c.event = nlh->nlmsg_type;
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index ce8844f..2c18edd 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -205,7 +205,7 @@ endif
# >$< substitution to preserve $ when reloading .cmd file
# note: when using inline perl scripts [perl -e '...$$t=1;...']
# in $(cmd_xxx) double $$ your perl vars
-make-cmd = $(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1)))))
+make-cmd = $(subst \\,\\\\,$(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1))))))
# Find any prerequisites that is newer than target or that does not exist.
# PHONY targets skipped in both cases.
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 3545934..27a9673 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -1241,6 +1241,7 @@ static int sel_make_bools(void)
kfree(bool_pending_names[i]);
kfree(bool_pending_names);
kfree(bool_pending_values);
+ bool_num = 0;
bool_pending_names = NULL;
bool_pending_values = NULL;
diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c
index a0da775..5eab948 100644
--- a/sound/drivers/aloop.c
+++ b/sound/drivers/aloop.c
@@ -119,6 +119,7 @@ struct loopback_pcm {
unsigned int period_size_frac;
unsigned long last_jiffies;
struct timer_list timer;
+ spinlock_t timer_lock;
};
static struct platform_device *devices[SNDRV_CARDS];
@@ -169,6 +170,7 @@ static void loopback_timer_start(struct loopback_pcm *dpcm)
unsigned long tick;
unsigned int rate_shift = get_rate_shift(dpcm);
+ spin_lock(&dpcm->timer_lock);
if (rate_shift != dpcm->pcm_rate_shift) {
dpcm->pcm_rate_shift = rate_shift;
dpcm->period_size_frac = frac_pos(dpcm, dpcm->pcm_period_size);
@@ -181,12 +183,15 @@ static void loopback_timer_start(struct loopback_pcm *dpcm)
tick = (tick + dpcm->pcm_bps - 1) / dpcm->pcm_bps;
dpcm->timer.expires = jiffies + tick;
add_timer(&dpcm->timer);
+ spin_unlock(&dpcm->timer_lock);
}
static inline void loopback_timer_stop(struct loopback_pcm *dpcm)
{
+ spin_lock(&dpcm->timer_lock);
del_timer(&dpcm->timer);
dpcm->timer.expires = 0;
+ spin_unlock(&dpcm->timer_lock);
}
#define CABLE_VALID_PLAYBACK (1 << SNDRV_PCM_STREAM_PLAYBACK)
@@ -658,6 +663,7 @@ static int loopback_open(struct snd_pcm_substream *substream)
dpcm->substream = substream;
setup_timer(&dpcm->timer, loopback_timer_function,
(unsigned long)dpcm);
+ spin_lock_init(&dpcm->timer_lock);
cable = loopback->cables[substream->number][dev];
if (!cable) {
diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c
index 2af0999..74f5a3d 100644
--- a/sound/drivers/mpu401/mpu401_uart.c
+++ b/sound/drivers/mpu401/mpu401_uart.c
@@ -554,6 +554,7 @@ int snd_mpu401_uart_new(struct snd_card *card, int device,
spin_lock_init(&mpu->output_lock);
spin_lock_init(&mpu->timer_lock);
mpu->hardware = hardware;
+ mpu->irq = -1;
if (! (info_flags & MPU401_INFO_INTEGRATED)) {
int res_size = hardware == MPU401_HW_PC98II ? 4 : 2;
mpu->res = request_region(port, res_size, "MPU401 UART");
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index 7f4d619..11ccc23 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -1271,6 +1271,8 @@ static int snd_ac97_cvol_new(struct snd_card *card, char *name, int reg, unsigne
tmp.index = ac97->num;
kctl = snd_ctl_new1(&tmp, ac97);
}
+ if (!kctl)
+ return -ENOMEM;
if (reg >= AC97_PHONE && reg <= AC97_PCM)
set_tlv_db_scale(kctl, db_scale_5bit_12db_max);
else
diff --git a/sound/pci/echoaudio/echoaudio_dsp.c b/sound/pci/echoaudio/echoaudio_dsp.c
index 64417a7..d8c670c 100644
--- a/sound/pci/echoaudio/echoaudio_dsp.c
+++ b/sound/pci/echoaudio/echoaudio_dsp.c
@@ -475,7 +475,7 @@ static int load_firmware(struct echoaudio *chip)
const struct firmware *fw;
int box_type, err;
- if (snd_BUG_ON(!chip->dsp_code_to_load || !chip->comm_page))
+ if (snd_BUG_ON(!chip->comm_page))
return -EPERM;
/* See if the ASIC is present and working - only if the DSP is already loaded */
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index 15f0161..0800bcc 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -1415,6 +1415,15 @@ static struct snd_emu_chip_details emu_chip_details[] = {
.ca0108_chip = 1,
.spk71 = 1,
.emu_model = EMU_MODEL_EMU1010B}, /* EMU 1010 new revision */
+ /* Tested by Maxim Kachur <mcdebugger@duganet.ru> 17th Oct 2012. */
+ /* This is MAEM8986, 0202 is MAEM8980 */
+ {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40071102,
+ .driver = "Audigy2", .name = "E-mu 1010 PCIe [MAEM8986]",
+ .id = "EMU1010",
+ .emu10k2_chip = 1,
+ .ca0108_chip = 1,
+ .spk71 = 1,
+ .emu_model = EMU_MODEL_EMU1010B}, /* EMU 1010 PCIe */
/* Tested by James@superbug.co.uk 8th July 2005. */
/* This is MAEM8810, 0202 is MAEM8820 */
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40011102,
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 981b6fd..c5c9788 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -702,11 +702,13 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
{
struct azx *chip = bus->private_data;
unsigned long timeout;
+ unsigned long loopcounter;
int do_poll = 0;
again:
timeout = jiffies + msecs_to_jiffies(1000);
- for (;;) {
+
+ for (loopcounter = 0;; loopcounter++) {
if (chip->polling_mode || do_poll) {
spin_lock_irq(&chip->reg_lock);
azx_update_rirb(chip);
@@ -722,7 +724,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
}
if (time_after(jiffies, timeout))
break;
- if (bus->needs_damn_long_delay)
+ if (bus->needs_damn_long_delay || loopcounter > 3000)
msleep(2); /* temporary workaround */
else {
udelay(10);
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c
index 6fe944a..d0e5dec 100644
--- a/sound/pci/hda/hda_proc.c
+++ b/sound/pci/hda/hda_proc.c
@@ -406,7 +406,7 @@ static void print_digital_conv(struct snd_info_buffer *buffer,
if (digi1 & AC_DIG1_EMPHASIS)
snd_iprintf(buffer, " Preemphasis");
if (digi1 & AC_DIG1_COPYRIGHT)
- snd_iprintf(buffer, " Copyright");
+ snd_iprintf(buffer, " Non-Copyright");
if (digi1 & AC_DIG1_NONAUDIO)
snd_iprintf(buffer, " Non-Audio");
if (digi1 & AC_DIG1_PROFESSIONAL)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 51412e1..8d288a7 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -20132,6 +20132,8 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = {
{ .id = 0x10ec0272, .name = "ALC272", .patch = patch_alc662 },
{ .id = 0x10ec0275, .name = "ALC275", .patch = patch_alc269 },
{ .id = 0x10ec0276, .name = "ALC276", .patch = patch_alc269 },
+ { .id = 0x10ec0280, .name = "ALC280", .patch = patch_alc269 },
+ { .id = 0x10ec0282, .name = "ALC282", .patch = patch_alc269 },
{ .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
.patch = patch_alc861 },
{ .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
diff --git a/sound/pci/ice1712/prodigy_hifi.c b/sound/pci/ice1712/prodigy_hifi.c
index 764cc93..075d5aa 100644
--- a/sound/pci/ice1712/prodigy_hifi.c
+++ b/sound/pci/ice1712/prodigy_hifi.c
@@ -297,6 +297,7 @@ static int ak4396_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem
}
static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
+static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0);
static struct snd_kcontrol_new prodigy_hd2_controls[] __devinitdata = {
{
@@ -307,7 +308,7 @@ static struct snd_kcontrol_new prodigy_hd2_controls[] __devinitdata = {
.info = ak4396_dac_vol_info,
.get = ak4396_dac_vol_get,
.put = ak4396_dac_vol_put,
- .tlv = { .p = db_scale_wm_dac },
+ .tlv = { .p = ak4396_db_scale },
},
};
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index 8224db5..fbcd4f9 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -58,6 +58,8 @@ source "sound/soc/sh/Kconfig"
source "sound/soc/tegra/Kconfig"
source "sound/soc/txx9/Kconfig"
+source "sound/soc/codecs/Kconfig.voodoo"
+
# Supported codecs
source "sound/soc/codecs/Kconfig"
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 98175a0..abfd23b 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -356,6 +356,9 @@ config SND_SOC_WM8993
config SND_SOC_WM8994
tristate
+config SND_SOC_WM8994_SAMSUNG
+ tristate
+
config SND_SOC_WM8995
tristate
diff --git a/sound/soc/codecs/Kconfig.voodoo b/sound/soc/codecs/Kconfig.voodoo
new file mode 100644
index 0000000..6672bed
--- /dev/null
+++ b/sound/soc/codecs/Kconfig.voodoo
@@ -0,0 +1,60 @@
+menuconfig SND_VOODOO
+ bool "Voodoo sound driver"
+ depends on SND_UNIVERSAL_WM8994 || SND_S3C24XX_SOC || SND_SOC_WM8994_P3 || SND_SOC_SAMSUNG_HERRING_WM8994
+ default y
+ help
+ With this option enabled, the kernel compile an additionnal driver
+ that extend the existing sound driver
+
+config SND_VOODOO_HP_LEVEL_CONTROL
+ bool "Add headphone amplifier level control"
+ depends on SND_VOODOO
+ default y
+ help
+ Adds a control allowing to adjust the analog gain of the headphone
+ amplifier
+
+config SND_VOODOO_HP_LEVEL
+ int "default level at boot 0-62"
+ depends on SND_VOODOO_HP_LEVEL_CONTROL
+ default 54 if MACH_HERRING=y || M110S=y
+ default 47
+ range 0 62
+ help
+ Default headphone amplifier level. Take care not setting it to high,
+ it would introduce hiss for people not using the control app
+
+config SND_VOODOO_RECORD_PRESETS
+ bool "Microphone recording presets"
+ depends on SND_VOODOO
+ default y
+ help
+ Recording presets with Dynamic Range Compression auto-gain
+ on microphone:
+ - Original
+ - High sensitivity
+ - Balanced (recommanded, default)
+ - Loud environment - concert
+
+config SND_VOODOO_FM
+ bool "FM radio: frequency response and levels optimizations"
+ depends on SND_VOODOO && ARIES_EUR
+ default n
+ help
+ Adds a control to enable or disable the high-pass filter on FM radio
+
+config SND_VOODOO_MODULE
+ tristate "Build also as module (incomplete)"
+ depends on SND_VOODOO && m && n
+ default n
+ help
+ requires additionnal source
+
+config SND_VOODOO_DEVELOPMENT
+ bool "Codec development tools (unsafe)"
+ depends on SND_VOODOO
+ default n
+ help
+ Allow to codec dump registers and load register-address/value batchs
+ Powerful but also dangerous tool
+
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index fd85584..fa6ba22 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -73,8 +73,14 @@ snd-soc-wm8988-objs := wm8988.o
snd-soc-wm8990-objs := wm8990.o
snd-soc-wm8991-objs := wm8991.o
snd-soc-wm8993-objs := wm8993.o
-snd-soc-wm8994-objs := wm8994.o wm8994-tables.o wm8958-dsp2.o
snd-soc-wm8995-objs := wm8995.o
+ifeq ($(CONFIG_SND_VOODOO),y)
+snd-soc-wm8994-objs := wm8994_samsung.o wm8994_herring.o wm8994_voodoo.o
+snd-soc-wm8994-samsung-objs := wm8994_samsung.o wm8994_herring.o wm8994_voodoo.o
+else
+snd-soc-wm8994-objs := wm8994.o wm8994-tables.o wm8958-dsp2.o
+snd-soc-wm8994-samsung-objs := wm8994_samsung.o wm8994_herring.o
+endif
snd-soc-wm9081-objs := wm9081.o
snd-soc-wm9705-objs := wm9705.o
snd-soc-wm9712-objs := wm9712.o
@@ -166,6 +172,7 @@ obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o
obj-$(CONFIG_SND_SOC_WM8991) += snd-soc-wm8991.o
obj-$(CONFIG_SND_SOC_WM8993) += snd-soc-wm8993.o
obj-$(CONFIG_SND_SOC_WM8994) += snd-soc-wm8994.o
+obj-$(CONFIG_SND_SOC_WM8994_SAMSUNG) += snd-soc-wm8994-samsung.o
obj-$(CONFIG_SND_SOC_WM8995) += snd-soc-wm8995.o
obj-$(CONFIG_SND_SOC_WM9081) += snd-soc-wm9081.o
obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o
@@ -179,3 +186,7 @@ obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o
obj-$(CONFIG_SND_SOC_TPA6130A2) += snd-soc-tpa6130a2.o
obj-$(CONFIG_SND_SOC_WM2000) += snd-soc-wm2000.o
obj-$(CONFIG_SND_SOC_WM9090) += snd-soc-wm9090.o
+
+ifeq ($(CONFIG_SND_VOODOO_MODULE),m)
+obj-$(CONFIG_SND_VOODOO_MODULE) += voodoo-sound-tegrak-module/
+endif
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 789453d..0b08bb7 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -949,9 +949,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
}
found:
- data = snd_soc_read(codec, AIC3X_PLL_PROGA_REG);
- snd_soc_write(codec, AIC3X_PLL_PROGA_REG,
- data | (pll_p << PLLP_SHIFT));
+ snd_soc_update_bits(codec, AIC3X_PLL_PROGA_REG, PLLP_MASK, pll_p);
snd_soc_write(codec, AIC3X_OVRF_STATUS_AND_PLLR_REG,
pll_r << PLLR_SHIFT);
snd_soc_write(codec, AIC3X_PLL_PROGB_REG, pll_j << PLLJ_SHIFT);
diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h
index 06a1978..16d9999 100644
--- a/sound/soc/codecs/tlv320aic3x.h
+++ b/sound/soc/codecs/tlv320aic3x.h
@@ -166,6 +166,7 @@
/* PLL registers bitfields */
#define PLLP_SHIFT 0
+#define PLLP_MASK 7
#define PLLQ_SHIFT 3
#define PLLR_SHIFT 0
#define PLLJ_SHIFT 2
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index c850e3d..f16f587 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -2890,6 +2890,9 @@ static int wm8962_set_bias_level(struct snd_soc_codec *codec,
/* VMID 2*250k */
snd_soc_update_bits(codec, WM8962_PWR_MGMT_1,
WM8962_VMID_SEL_MASK, 0x100);
+
+ if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
+ msleep(100);
break;
case SND_SOC_BIAS_OFF:
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index 2194912..1f7616d 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -2127,7 +2127,7 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
- bclk_rate = params_rate(params) * 2;
+ bclk_rate = params_rate(params) * 4;
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
bclk_rate *= 16;
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h
index 0a1db04..13257dc 100644
--- a/sound/soc/codecs/wm8994.h
+++ b/sound/soc/codecs/wm8994.h
@@ -1,145 +1,120 @@
-/*
- * wm8994.h -- WM8994 Soc Audio driver
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef _WM8994_H
-#define _WM8994_H
-
-#include <sound/soc.h>
-#include <linux/firmware.h>
-
-#include "wm_hubs.h"
-
-/* Sources for AIF1/2 SYSCLK - use with set_dai_sysclk() */
-#define WM8994_SYSCLK_MCLK1 1
-#define WM8994_SYSCLK_MCLK2 2
-#define WM8994_SYSCLK_FLL1 3
-#define WM8994_SYSCLK_FLL2 4
-
-/* OPCLK is also configured with set_dai_sysclk, specify division*10 as rate. */
-#define WM8994_SYSCLK_OPCLK 5
-
-#define WM8994_FLL1 1
-#define WM8994_FLL2 2
-
-#define WM8994_FLL_SRC_MCLK1 1
-#define WM8994_FLL_SRC_MCLK2 2
-#define WM8994_FLL_SRC_LRCLK 3
-#define WM8994_FLL_SRC_BCLK 4
-
-typedef void (*wm8958_micdet_cb)(u16 status, void *data);
-
-int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
- int micbias, int det, int shrt);
-int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
- wm8958_micdet_cb cb, void *cb_data);
-
-#define WM8994_CACHE_SIZE 1570
-
-struct wm8994_access_mask {
- unsigned short readable; /* Mask of readable bits */
- unsigned short writable; /* Mask of writable bits */
-};
-
-extern const struct wm8994_access_mask wm8994_access_masks[WM8994_CACHE_SIZE];
-extern const u16 wm8994_reg_defaults[WM8994_CACHE_SIZE];
-
-int wm8958_aif_ev(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event);
-
-void wm8958_dsp2_init(struct snd_soc_codec *codec);
-
-struct wm8994_micdet {
- struct snd_soc_jack *jack;
- int det;
- int shrt;
-};
-
-/* codec private data */
-struct wm8994_fll_config {
- int src;
- int in;
- int out;
-};
-
-#define WM8994_NUM_DRC 3
-#define WM8994_NUM_EQ 3
-
-struct wm8994_priv {
- struct wm_hubs_data hubs;
- enum snd_soc_control_type control_type;
- void *control_data;
- struct snd_soc_codec *codec;
- int sysclk[2];
- int sysclk_rate[2];
- int mclk[2];
- int aifclk[2];
- struct wm8994_fll_config fll[2], fll_suspend[2];
-
- int dac_rates[2];
- int lrclk_shared[2];
-
- int mbc_ena[3];
- int hpf1_ena[3];
- int hpf2_ena[3];
- int vss_ena[3];
- int enh_eq_ena[3];
-
- /* Platform dependant DRC configuration */
- const char **drc_texts;
- int drc_cfg[WM8994_NUM_DRC];
- struct soc_enum drc_enum;
-
- /* Platform dependant ReTune mobile configuration */
- int num_retune_mobile_texts;
- const char **retune_mobile_texts;
- int retune_mobile_cfg[WM8994_NUM_EQ];
- struct soc_enum retune_mobile_enum;
-
- /* Platform dependant MBC configuration */
- int mbc_cfg;
- const char **mbc_texts;
- struct soc_enum mbc_enum;
-
- /* Platform dependant VSS configuration */
- int vss_cfg;
- const char **vss_texts;
- struct soc_enum vss_enum;
-
- /* Platform dependant VSS HPF configuration */
- int vss_hpf_cfg;
- const char **vss_hpf_texts;
- struct soc_enum vss_hpf_enum;
-
- /* Platform dependant enhanced EQ configuration */
- int enh_eq_cfg;
- const char **enh_eq_texts;
- struct soc_enum enh_eq_enum;
-
- struct wm8994_micdet micdet[2];
-
- wm8958_micdet_cb jack_cb;
- void *jack_cb_data;
- int micdet_irq;
-
- int revision;
- struct wm8994_pdata *pdata;
-
- unsigned int aif1clk_enable:1;
- unsigned int aif2clk_enable:1;
-
- unsigned int aif1clk_disable:1;
- unsigned int aif2clk_disable:1;
-
- int dsp_active;
- const struct firmware *cur_fw;
- const struct firmware *mbc;
- const struct firmware *mbc_vss;
- const struct firmware *enh_eq;
-};
-
-#endif
+/*
+ * wm8994.h -- WM8994 Soc Audio driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _WM8994_H
+#define _WM8994_H
+
+#include <sound/soc.h>
+
+extern struct snd_soc_codec_device soc_codec_dev_wm8994;
+// We don't use array - DW Shim.
+//extern struct snd_soc_dai wm8994_dai[];
+
+/* Sources for AIF1/2 SYSCLK - use with set_dai_sysclk() */
+#define WM8994_SYSCLK_MCLK1 1
+#define WM8994_SYSCLK_MCLK2 2
+#define WM8994_SYSCLK_FLL1 3
+#define WM8994_SYSCLK_FLL2 4
+
+#define WM8994_FLL1 1
+#define WM8994_FLL2 2
+
+//-----------------------------------------------------------
+// Added belows codes by Samsung Electronics.
+
+#include "wm8994_def.h"
+
+extern struct snd_soc_dai wm8994_dai;
+
+#define WM8994_SYSCLK_MCLK 1
+#define WM8994_SYSCLK_FLL 2
+
+#define AUDIO_COMMON_DEBUG 0
+//#define WM8994_REGISTER_DUMP
+#if defined CONFIG_SND_SOC_WM8994_PCM
+#define ATTACH_ADDITINAL_PCM_DRIVER // for VT call.
+#endif
+//------------------------------------------------
+// Definitions of enum type
+//------------------------------------------------
+enum audio_path { OFF, RCV, SPK, HP, BT, SPK_HP};
+enum mic_path { MAIN, SUB, MIC_OFF};
+enum fmradio_audio_path { FMR_OFF, FMR_SPK, FMR_HP, FMR_SPK_MIX, FMR_HP_MIX, FMR_SPK_HP_MIX};
+enum call_state { DISCONNECT, CONNECT};
+enum power_state { CODEC_OFF, CODEC_ON };
+enum mic_state { MIC_NO_USE, MIC_USE};
+
+typedef void (*select_route)(struct snd_soc_codec *);
+typedef void (*select_mic_route)(struct snd_soc_codec *);
+
+struct wm8994_setup_data {
+ int i2c_bus;
+ unsigned short i2c_address;
+};
+
+struct wm8994_priv {
+ //u16 reg_cache[WM8994_REGISTER_COUNT];
+ struct snd_soc_codec codec;
+ int master;
+ int sysclk_source;
+ unsigned int mclk_rate;
+ unsigned int sysclk_rate;
+ unsigned int fs;
+ unsigned int bclk;
+ unsigned int hw_version; // For wolfson H/W version. 1 = Rev B, 3 = Rev D
+ enum audio_path cur_path;
+ enum mic_path rec_path;
+ enum fmradio_audio_path fmradio_path;
+ enum call_state call_state;
+ enum power_state power_state;
+ enum mic_state mic_state;
+ select_route *universal_playback_path;
+ select_route *universal_voicecall_path;
+ select_mic_route *universal_mic_path;
+ int testmode_config_flag; // for testmode.
+};
+
+#if AUDIO_COMMON_DEBUG
+#define DEBUG_LOG(format,...)\
+ printk ("[ "SUBJECT " (%s,%d) ] " format "\n", __func__, __LINE__, ## __VA_ARGS__);
+#else
+#define DEBUG_LOG(format,...)
+#endif
+
+#define DEBUG_LOG_ERR(format,...)\
+ printk (KERN_ERR "[ "SUBJECT " (%s,%d) ] " format "\n", __func__, __LINE__, ## __VA_ARGS__);
+
+// Definitions of function prototype.
+inline unsigned int wm8994_read(struct snd_soc_codec *codec,unsigned int reg);
+int wm8994_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int value);
+int audio_init(void);
+int audio_power(int en);
+void audio_ctrl_mic_bias_gpio(int enable);
+void wm8994_set_off(struct snd_soc_codec *codec);
+void wm8994_disable_playback_path(struct snd_soc_codec *codec, enum audio_path path);
+void wm8994_disable_fmradio_path(struct snd_soc_codec *codec, enum fmradio_audio_path path);
+void wm8994_disable_rec_path(struct snd_soc_codec *codec,enum mic_path rec_path);
+void wm8994_record_main_mic( struct snd_soc_codec *codec);
+void wm8994_record_headset_mic( struct snd_soc_codec *codec);
+void wm8994_set_playback_receiver(struct snd_soc_codec *codec);
+void wm8994_set_playback_headset(struct snd_soc_codec *codec);
+void wm8994_set_playback_speaker(struct snd_soc_codec *codec);
+void wm8994_set_playback_speaker_headset(struct snd_soc_codec *codec);
+void wm8994_set_voicecall_receiver(struct snd_soc_codec *codec);
+void wm8994_set_voicecall_headset(struct snd_soc_codec *codec);
+void wm8994_set_voicecall_speaker(struct snd_soc_codec *codec);
+void wm8994_set_voicecall_bluetooth(struct snd_soc_codec *codec);
+void wm8994_set_fmradio_headset(struct snd_soc_codec *codec);
+void wm8994_set_fmradio_speaker(struct snd_soc_codec *codec);
+void wm8994_set_fmradio_headset_mix(struct snd_soc_codec *codec);
+void wm8994_set_fmradio_speaker_mix(struct snd_soc_codec *codec);
+void wm8994_set_fmradio_speaker_headset_mix(struct snd_soc_codec *codec);
+#if defined WM8994_REGISTER_DUMP
+void wm8994_register_dump(struct snd_soc_codec *codec);
+#endif
+#endif
diff --git a/sound/soc/codecs/wm8994_def.h b/sound/soc/codecs/wm8994_def.h
new file mode 100644
index 0000000..a375950
--- /dev/null
+++ b/sound/soc/codecs/wm8994_def.h
@@ -0,0 +1,9147 @@
+/*
+ * wm8994_def.h -- WM8994 ALSA Soc Audio driver
+ *
+ * Copyright 2010 Samsung Electronics.
+ *
+ * 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.
+ *
+ * Note :
+ * Definitions of WM8994 Register names and values.
+ */
+
+/*
+ * Register values.
+ */
+#define WM8994_SOFTWARE_RESET 0x00
+#define WM8994_POWER_MANAGEMENT_1 0x01
+#define WM8994_POWER_MANAGEMENT_2 0x02
+#define WM8994_POWER_MANAGEMENT_3 0x03
+#define WM8994_POWER_MANAGEMENT_4 0x04
+#define WM8994_POWER_MANAGEMENT_5 0x05
+#define WM8994_POWER_MANAGEMENT_6 0x06
+#define WM8994_INPUT_MIXER_1 0x15
+#define WM8994_LEFT_LINE_INPUT_1_2_VOLUME 0x18
+#define WM8994_LEFT_LINE_INPUT_3_4_VOLUME 0x19
+#define WM8994_RIGHT_LINE_INPUT_1_2_VOLUME 0x1A
+#define WM8994_RIGHT_LINE_INPUT_3_4_VOLUME 0x1B
+#define WM8994_LEFT_OUTPUT_VOLUME 0x1C
+#define WM8994_RIGHT_OUTPUT_VOLUME 0x1D
+#define WM8994_LINE_OUTPUTS_VOLUME 0x1E
+#define WM8994_HPOUT2_VOLUME 0x1F
+#define WM8994_LEFT_OPGA_VOLUME 0x20
+#define WM8994_RIGHT_OPGA_VOLUME 0x21
+#define WM8994_SPKMIXL_ATTENUATION 0x22
+#define WM8994_SPKMIXR_ATTENUATION 0x23
+#define WM8994_SPKOUT_MIXERS 0x24
+#define WM8994_CLASSD 0x25
+#define WM8994_SPEAKER_VOLUME_LEFT 0x26
+#define WM8994_SPEAKER_VOLUME_RIGHT 0x27
+#define WM8994_INPUT_MIXER_2 0x28
+#define WM8994_INPUT_MIXER_3 0x29
+#define WM8994_INPUT_MIXER_4 0x2A
+#define WM8994_INPUT_MIXER_5 0x2B
+#define WM8994_INPUT_MIXER_6 0x2C
+#define WM8994_OUTPUT_MIXER_1 0x2D
+#define WM8994_OUTPUT_MIXER_2 0x2E
+#define WM8994_OUTPUT_MIXER_3 0x2F
+#define WM8994_OUTPUT_MIXER_4 0x30
+#define WM8994_OUTPUT_MIXER_5 0x31
+#define WM8994_OUTPUT_MIXER_6 0x32
+#define WM8994_HPOUT2_MIXER 0x33
+#define WM8994_LINE_MIXER_1 0x34
+#define WM8994_LINE_MIXER_2 0x35
+#define WM8994_SPEAKER_MIXER 0x36
+#define WM8994_ADDITIONAL_CONTROL 0x37
+#define WM8994_ANTIPOP_1 0x38
+#define WM8994_ANTIPOP_2 0x39
+#define WM8994_MICBIAS 0x3A
+#define WM8994_LDO_1 0x3B
+#define WM8994_LDO_2 0x3C
+#define WM8994_CHARGE_PUMP_1 0x4C
+#define WM8994_CLASS_W_1 0x51
+#define WM8994_DC_SERVO_1 0x54
+#define WM8994_DC_SERVO_2 0x55
+#define WM8994_DC_SERVO_4 0x57
+#define WM8994_DC_SERVO_READBACK 0x58
+#define WM8994_DC_SERVO_ANA_1 0x5B
+#define WM8994_DC_SERVO_ANA_2 0x5C
+#define WM8994_ANALOGUE_HP_1 0x60
+#define WM8958_MIC_DETECT_1 0xD0
+#define WM8958_MIC_DETECT_2 0xD1
+#define WM8958_MIC_DETECT_3 0xD2
+#define WM8994_CHIP_REVISION 0x100
+#define WM8994_CONTROL_INTERFACE 0x101
+#define WM8994_WRITE_SEQUENCER_CTRL_1 0x110
+#define WM8994_WRITE_SEQUENCER_CTRL_2 0x111
+#define WM8994_AIF1_CLOCKING_1 0x200
+#define WM8994_AIF1_CLOCKING_2 0x201
+#define WM8994_AIF2_CLOCKING_1 0x204
+#define WM8994_AIF2_CLOCKING_2 0x205
+#define WM8994_CLOCKING_1 0x208
+#define WM8994_CLOCKING_2 0x209
+#define WM8994_AIF1_RATE 0x210
+#define WM8994_AIF2_RATE 0x211
+#define WM8994_RATE_STATUS 0x212
+#define WM8994_FLL1_CONTROL_1 0x220
+#define WM8994_FLL1_CONTROL_2 0x221
+#define WM8994_FLL1_CONTROL_3 0x222
+#define WM8994_FLL1_CONTROL_4 0x223
+#define WM8994_FLL1_CONTROL_5 0x224
+#define WM8994_FLL2_CONTROL_1 0x240
+#define WM8994_FLL2_CONTROL_2 0x241
+#define WM8994_FLL2_CONTROL_3 0x242
+#define WM8994_FLL2_CONTROL_4 0x243
+#define WM8994_FLL2_CONTROL_5 0x244
+#define WM8994_AIF1_CONTROL_1 0x300
+#define WM8994_AIF1_CONTROL_2 0x301
+#define WM8994_AIF1_MASTER_SLAVE 0x302
+#define WM8994_AIF1_BCLK 0x303
+#define WM8994_AIF1ADC_LRCLK 0x304
+#define WM8994_AIF1DAC_LRCLK 0x305
+#define WM8994_AIF1DAC_DATA 0x306
+#define WM8994_AIF1ADC_DATA 0x307
+#define WM8994_AIF2_CONTROL_1 0x310
+#define WM8994_AIF2_CONTROL_2 0x311
+#define WM8994_AIF2_MASTER_SLAVE 0x312
+#define WM8994_AIF2_BCLK 0x313
+#define WM8994_AIF2ADC_LRCLK 0x314
+#define WM8994_AIF2DAC_LRCLK 0x315
+#define WM8994_AIF2DAC_DATA 0x316
+#define WM8994_AIF2ADC_DATA 0x317
+#define WM8994_AIF1_ADC1_LEFT_VOLUME 0x400
+#define WM8994_AIF1_ADC1_RIGHT_VOLUME 0x401
+#define WM8994_AIF1_DAC1_LEFT_VOLUME 0x402
+#define WM8994_AIF1_DAC1_RIGHT_VOLUME 0x403
+#define WM8994_AIF1_ADC2_LEFT_VOLUME 0x404
+#define WM8994_AIF1_ADC2_RIGHT_VOLUME 0x405
+#define WM8994_AIF1_DAC2_LEFT_VOLUME 0x406
+#define WM8994_AIF1_DAC2_RIGHT_VOLUME 0x407
+#define WM8994_AIF1_ADC1_FILTERS 0x410
+#define WM8994_AIF1_ADC2_FILTERS 0x411
+#define WM8994_AIF1_DAC1_FILTERS_1 0x420
+#define WM8994_AIF1_DAC1_FILTERS_2 0x421
+#define WM8994_AIF1_DAC2_FILTERS_1 0x422
+#define WM8994_AIF1_DAC2_FILTERS_2 0x423
+#define WM8994_AIF1_DRC1_1 0x440
+#define WM8994_AIF1_DRC1_2 0x441
+#define WM8994_AIF1_DRC1_3 0x442
+#define WM8994_AIF1_DRC1_4 0x443
+#define WM8994_AIF1_DRC1_5 0x444
+#define WM8994_AIF1_DRC2_1 0x450
+#define WM8994_AIF1_DRC2_2 0x451
+#define WM8994_AIF1_DRC2_3 0x452
+#define WM8994_AIF1_DRC2_4 0x453
+#define WM8994_AIF1_DRC2_5 0x454
+#define WM8994_AIF1_DAC1_EQ_GAINS_1 0x480
+#define WM8994_AIF1_DAC1_EQ_GAINS_2 0x481
+#define WM8994_AIF1_DAC1_EQ_BAND_1_A 0x482
+#define WM8994_AIF1_DAC1_EQ_BAND_1_B 0x483
+#define WM8994_AIF1_DAC1_EQ_BAND_1_PG 0x484
+#define WM8994_AIF1_DAC1_EQ_BAND_2_A 0x485
+#define WM8994_AIF1_DAC1_EQ_BAND_2_B 0x486
+#define WM8994_AIF1_DAC1_EQ_BAND_2_C 0x487
+#define WM8994_AIF1_DAC1_EQ_BAND_2_PG 0x488
+#define WM8994_AIF1_DAC1_EQ_BAND_3_A 0x489
+#define WM8994_AIF1_DAC1_EQ_BAND_3_B 0x48A
+#define WM8994_AIF1_DAC1_EQ_BAND_3_C 0x48B
+#define WM8994_AIF1_DAC1_EQ_BAND_3_PG 0x48C
+#define WM8994_AIF1_DAC1_EQ_BAND_4_A 0x48D
+#define WM8994_AIF1_DAC1_EQ_BAND_4_B 0x48E
+#define WM8994_AIF1_DAC1_EQ_BAND_4_C 0x48F
+#define WM8994_AIF1_DAC1_EQ_BAND_4_PG 0x490
+#define WM8994_AIF1_DAC1_EQ_BAND_5_A 0x491
+#define WM8994_AIF1_DAC1_EQ_BAND_5_B 0x492
+#define WM8994_AIF1_DAC1_EQ_BAND_5_PG 0x493
+#define WM8994_AIF1_DAC2_EQ_GAINS_1 0x4A0
+#define WM8994_AIF1_DAC2_EQ_GAINS_2 0x4A1
+#define WM8994_AIF1_DAC2_EQ_BAND_1_A 0x4A2
+#define WM8994_AIF1_DAC2_EQ_BAND_1_B 0x4A3
+#define WM8994_AIF1_DAC2_EQ_BAND_1_PG 0x4A4
+#define WM8994_AIF1_DAC2_EQ_BAND_2_A 0x4A5
+#define WM8994_AIF1_DAC2_EQ_BAND_2_B 0x4A6
+#define WM8994_AIF1_DAC2_EQ_BAND_2_C 0x4A7
+#define WM8994_AIF1_DAC2_EQ_BAND_2_PG 0x4A8
+#define WM8994_AIF1_DAC2_EQ_BAND_3_A 0x4A9
+#define WM8994_AIF1_DAC2_EQ_BAND_3_B 0x4AA
+#define WM8994_AIF1_DAC2_EQ_BAND_3_C 0x4AB
+#define WM8994_AIF1_DAC2_EQ_BAND_3_PG 0x4AC
+#define WM8994_AIF1_DAC2_EQ_BAND_4_A 0x4AD
+#define WM8994_AIF1_DAC2_EQ_BAND_4_B 0x4AE
+#define WM8994_AIF1_DAC2_EQ_BAND_4_C 0x4AF
+#define WM8994_AIF1_DAC2_EQ_BAND_4_PG 0x4B0
+#define WM8994_AIF1_DAC2_EQ_BAND_5_A 0x4B1
+#define WM8994_AIF1_DAC2_EQ_BAND_5_B 0x4B2
+#define WM8994_AIF1_DAC2_EQ_BAND_5_PG 0x4B3
+#define WM8994_AIF2_ADC_LEFT_VOLUME 0x500
+#define WM8994_AIF2_ADC_RIGHT_VOLUME 0x501
+#define WM8994_AIF2_DAC_LEFT_VOLUME 0x502
+#define WM8994_AIF2_DAC_RIGHT_VOLUME 0x503
+#define WM8994_AIF2_ADC_FILTERS 0x510
+#define WM8994_AIF2_DAC_FILTERS_1 0x520
+#define WM8994_AIF2_DAC_FILTERS_2 0x521
+#define WM8994_AIF2_DRC_1 0x540
+#define WM8994_AIF2_DRC_2 0x541
+#define WM8994_AIF2_DRC_3 0x542
+#define WM8994_AIF2_DRC_4 0x543
+#define WM8994_AIF2_DRC_5 0x544
+#define WM8994_AIF2_EQ_GAINS_1 0x580
+#define WM8994_AIF2_EQ_GAINS_2 0x581
+#define WM8994_AIF2_EQ_BAND_1_A 0x582
+#define WM8994_AIF2_EQ_BAND_1_B 0x583
+#define WM8994_AIF2_EQ_BAND_1_PG 0x584
+#define WM8994_AIF2_EQ_BAND_2_A 0x585
+#define WM8994_AIF2_EQ_BAND_2_B 0x586
+#define WM8994_AIF2_EQ_BAND_2_C 0x587
+#define WM8994_AIF2_EQ_BAND_2_PG 0x588
+#define WM8994_AIF2_EQ_BAND_3_A 0x589
+#define WM8994_AIF2_EQ_BAND_3_B 0x58A
+#define WM8994_AIF2_EQ_BAND_3_C 0x58B
+#define WM8994_AIF2_EQ_BAND_3_PG 0x58C
+#define WM8994_AIF2_EQ_BAND_4_A 0x58D
+#define WM8994_AIF2_EQ_BAND_4_B 0x58E
+#define WM8994_AIF2_EQ_BAND_4_C 0x58F
+#define WM8994_AIF2_EQ_BAND_4_PG 0x590
+#define WM8994_AIF2_EQ_BAND_5_A 0x591
+#define WM8994_AIF2_EQ_BAND_5_B 0x592
+#define WM8994_AIF2_EQ_BAND_5_PG 0x593
+#define WM8994_DAC1_MIXER_VOLUMES 0x600
+#define WM8994_DAC1_LEFT_MIXER_ROUTING 0x601
+#define WM8994_DAC1_RIGHT_MIXER_ROUTING 0x602
+#define WM8994_DAC2_MIXER_VOLUMES 0x603
+#define WM8994_DAC2_LEFT_MIXER_ROUTING 0x604
+#define WM8994_DAC2_RIGHT_MIXER_ROUTING 0x605
+#define WM8994_AIF1_ADC1_LEFT_MIXER_ROUTING 0x606
+#define WM8994_AIF1_ADC1_RIGHT_MIXER_ROUTING 0x607
+#define WM8994_AIF1_ADC2_LEFT_MIXER_ROUTING 0x608
+#define WM8994_AIF1_ADC2_RIGHT_MIXER_ROUTING 0x609
+#define WM8994_DAC1_LEFT_VOLUME 0x610
+#define WM8994_DAC1_RIGHT_VOLUME 0x611
+#define WM8994_DAC2_LEFT_VOLUME 0x612
+#define WM8994_DAC2_RIGHT_VOLUME 0x613
+#define WM8994_DAC_SOFTMUTE 0x614
+#define WM8994_OVERSAMPLING 0x620
+#define WM8994_SIDETONE 0x621
+#define WM8994_GPIO_1 0x700
+#define WM8994_GPIO_2 0x701
+#define WM8994_GPIO_3 0x702
+#define WM8994_GPIO_4 0x703
+#define WM8994_GPIO_5 0x704
+#define WM8994_GPIO_6 0x705
+#define WM8994_GPIO_7 0x706
+#define WM8994_GPIO_8 0x707
+#define WM8994_GPIO_9 0x708
+#define WM8994_GPIO_10 0x709
+#define WM8994_GPIO_11 0x70A
+#define WM8994_DIGITAL_PULLS 0x720
+#define WM8994_INTERRUPT_STATUS_1 0x730
+#define WM8994_INTERRUPT_STATUS_2 0x731
+#define WM8994_INTERRUPT_STATUS_1_MASK 0x738
+#define WM8994_INTERRUPT_STATUS_2_MASK 0x739
+#define WM8994_INTERRUPT_CONTROL 0x740
+#define WM8994_IRQ_DEBOUNCE 0x748
+#define WM8994_IRQ_POLARITY 0x749
+#define WM8958_DSP2_EXECCONTROL 0xA0D
+#define WM8994_WRITE_SEQUENCER_0 0x3000
+#define WM8994_WRITE_SEQUENCER_1 0x3001
+#define WM8994_WRITE_SEQUENCER_2 0x3002
+#define WM8994_WRITE_SEQUENCER_3 0x3003
+#define WM8994_WRITE_SEQUENCER_4 0x3004
+#define WM8994_WRITE_SEQUENCER_5 0x3005
+#define WM8994_WRITE_SEQUENCER_6 0x3006
+#define WM8994_WRITE_SEQUENCER_7 0x3007
+#define WM8994_WRITE_SEQUENCER_8 0x3008
+#define WM8994_WRITE_SEQUENCER_9 0x3009
+#define WM8994_WRITE_SEQUENCER_10 0x300A
+#define WM8994_WRITE_SEQUENCER_11 0x300B
+#define WM8994_WRITE_SEQUENCER_12 0x300C
+#define WM8994_WRITE_SEQUENCER_13 0x300D
+#define WM8994_WRITE_SEQUENCER_14 0x300E
+#define WM8994_WRITE_SEQUENCER_15 0x300F
+#define WM8994_WRITE_SEQUENCER_16 0x3010
+#define WM8994_WRITE_SEQUENCER_17 0x3011
+#define WM8994_WRITE_SEQUENCER_18 0x3012
+#define WM8994_WRITE_SEQUENCER_19 0x3013
+#define WM8994_WRITE_SEQUENCER_20 0x3014
+#define WM8994_WRITE_SEQUENCER_21 0x3015
+#define WM8994_WRITE_SEQUENCER_22 0x3016
+#define WM8994_WRITE_SEQUENCER_23 0x3017
+#define WM8994_WRITE_SEQUENCER_24 0x3018
+#define WM8994_WRITE_SEQUENCER_25 0x3019
+#define WM8994_WRITE_SEQUENCER_26 0x301A
+#define WM8994_WRITE_SEQUENCER_27 0x301B
+#define WM8994_WRITE_SEQUENCER_28 0x301C
+#define WM8994_WRITE_SEQUENCER_29 0x301D
+#define WM8994_WRITE_SEQUENCER_30 0x301E
+#define WM8994_WRITE_SEQUENCER_31 0x301F
+#define WM8994_WRITE_SEQUENCER_32 0x3020
+#define WM8994_WRITE_SEQUENCER_33 0x3021
+#define WM8994_WRITE_SEQUENCER_34 0x3022
+#define WM8994_WRITE_SEQUENCER_35 0x3023
+#define WM8994_WRITE_SEQUENCER_36 0x3024
+#define WM8994_WRITE_SEQUENCER_37 0x3025
+#define WM8994_WRITE_SEQUENCER_38 0x3026
+#define WM8994_WRITE_SEQUENCER_39 0x3027
+#define WM8994_WRITE_SEQUENCER_40 0x3028
+#define WM8994_WRITE_SEQUENCER_41 0x3029
+#define WM8994_WRITE_SEQUENCER_42 0x302A
+#define WM8994_WRITE_SEQUENCER_43 0x302B
+#define WM8994_WRITE_SEQUENCER_44 0x302C
+#define WM8994_WRITE_SEQUENCER_45 0x302D
+#define WM8994_WRITE_SEQUENCER_46 0x302E
+#define WM8994_WRITE_SEQUENCER_47 0x302F
+#define WM8994_WRITE_SEQUENCER_48 0x3030
+#define WM8994_WRITE_SEQUENCER_49 0x3031
+#define WM8994_WRITE_SEQUENCER_50 0x3032
+#define WM8994_WRITE_SEQUENCER_51 0x3033
+#define WM8994_WRITE_SEQUENCER_52 0x3034
+#define WM8994_WRITE_SEQUENCER_53 0x3035
+#define WM8994_WRITE_SEQUENCER_54 0x3036
+#define WM8994_WRITE_SEQUENCER_55 0x3037
+#define WM8994_WRITE_SEQUENCER_56 0x3038
+#define WM8994_WRITE_SEQUENCER_57 0x3039
+#define WM8994_WRITE_SEQUENCER_58 0x303A
+#define WM8994_WRITE_SEQUENCER_59 0x303B
+#define WM8994_WRITE_SEQUENCER_60 0x303C
+#define WM8994_WRITE_SEQUENCER_61 0x303D
+#define WM8994_WRITE_SEQUENCER_62 0x303E
+#define WM8994_WRITE_SEQUENCER_63 0x303F
+#define WM8994_WRITE_SEQUENCER_64 0x3040
+#define WM8994_WRITE_SEQUENCER_65 0x3041
+#define WM8994_WRITE_SEQUENCER_66 0x3042
+#define WM8994_WRITE_SEQUENCER_67 0x3043
+#define WM8994_WRITE_SEQUENCER_68 0x3044
+#define WM8994_WRITE_SEQUENCER_69 0x3045
+#define WM8994_WRITE_SEQUENCER_70 0x3046
+#define WM8994_WRITE_SEQUENCER_71 0x3047
+#define WM8994_WRITE_SEQUENCER_72 0x3048
+#define WM8994_WRITE_SEQUENCER_73 0x3049
+#define WM8994_WRITE_SEQUENCER_74 0x304A
+#define WM8994_WRITE_SEQUENCER_75 0x304B
+#define WM8994_WRITE_SEQUENCER_76 0x304C
+#define WM8994_WRITE_SEQUENCER_77 0x304D
+#define WM8994_WRITE_SEQUENCER_78 0x304E
+#define WM8994_WRITE_SEQUENCER_79 0x304F
+#define WM8994_WRITE_SEQUENCER_80 0x3050
+#define WM8994_WRITE_SEQUENCER_81 0x3051
+#define WM8994_WRITE_SEQUENCER_82 0x3052
+#define WM8994_WRITE_SEQUENCER_83 0x3053
+#define WM8994_WRITE_SEQUENCER_84 0x3054
+#define WM8994_WRITE_SEQUENCER_85 0x3055
+#define WM8994_WRITE_SEQUENCER_86 0x3056
+#define WM8994_WRITE_SEQUENCER_87 0x3057
+#define WM8994_WRITE_SEQUENCER_88 0x3058
+#define WM8994_WRITE_SEQUENCER_89 0x3059
+#define WM8994_WRITE_SEQUENCER_90 0x305A
+#define WM8994_WRITE_SEQUENCER_91 0x305B
+#define WM8994_WRITE_SEQUENCER_92 0x305C
+#define WM8994_WRITE_SEQUENCER_93 0x305D
+#define WM8994_WRITE_SEQUENCER_94 0x305E
+#define WM8994_WRITE_SEQUENCER_95 0x305F
+#define WM8994_WRITE_SEQUENCER_96 0x3060
+#define WM8994_WRITE_SEQUENCER_97 0x3061
+#define WM8994_WRITE_SEQUENCER_98 0x3062
+#define WM8994_WRITE_SEQUENCER_99 0x3063
+#define WM8994_WRITE_SEQUENCER_100 0x3064
+#define WM8994_WRITE_SEQUENCER_101 0x3065
+#define WM8994_WRITE_SEQUENCER_102 0x3066
+#define WM8994_WRITE_SEQUENCER_103 0x3067
+#define WM8994_WRITE_SEQUENCER_104 0x3068
+#define WM8994_WRITE_SEQUENCER_105 0x3069
+#define WM8994_WRITE_SEQUENCER_106 0x306A
+#define WM8994_WRITE_SEQUENCER_107 0x306B
+#define WM8994_WRITE_SEQUENCER_108 0x306C
+#define WM8994_WRITE_SEQUENCER_109 0x306D
+#define WM8994_WRITE_SEQUENCER_110 0x306E
+#define WM8994_WRITE_SEQUENCER_111 0x306F
+#define WM8994_WRITE_SEQUENCER_112 0x3070
+#define WM8994_WRITE_SEQUENCER_113 0x3071
+#define WM8994_WRITE_SEQUENCER_114 0x3072
+#define WM8994_WRITE_SEQUENCER_115 0x3073
+#define WM8994_WRITE_SEQUENCER_116 0x3074
+#define WM8994_WRITE_SEQUENCER_117 0x3075
+#define WM8994_WRITE_SEQUENCER_118 0x3076
+#define WM8994_WRITE_SEQUENCER_119 0x3077
+#define WM8994_WRITE_SEQUENCER_120 0x3078
+#define WM8994_WRITE_SEQUENCER_121 0x3079
+#define WM8994_WRITE_SEQUENCER_122 0x307A
+#define WM8994_WRITE_SEQUENCER_123 0x307B
+#define WM8994_WRITE_SEQUENCER_124 0x307C
+#define WM8994_WRITE_SEQUENCER_125 0x307D
+#define WM8994_WRITE_SEQUENCER_126 0x307E
+#define WM8994_WRITE_SEQUENCER_127 0x307F
+#define WM8994_WRITE_SEQUENCER_128 0x3080
+#define WM8994_WRITE_SEQUENCER_129 0x3081
+#define WM8994_WRITE_SEQUENCER_130 0x3082
+#define WM8994_WRITE_SEQUENCER_131 0x3083
+#define WM8994_WRITE_SEQUENCER_132 0x3084
+#define WM8994_WRITE_SEQUENCER_133 0x3085
+#define WM8994_WRITE_SEQUENCER_134 0x3086
+#define WM8994_WRITE_SEQUENCER_135 0x3087
+#define WM8994_WRITE_SEQUENCER_136 0x3088
+#define WM8994_WRITE_SEQUENCER_137 0x3089
+#define WM8994_WRITE_SEQUENCER_138 0x308A
+#define WM8994_WRITE_SEQUENCER_139 0x308B
+#define WM8994_WRITE_SEQUENCER_140 0x308C
+#define WM8994_WRITE_SEQUENCER_141 0x308D
+#define WM8994_WRITE_SEQUENCER_142 0x308E
+#define WM8994_WRITE_SEQUENCER_143 0x308F
+#define WM8994_WRITE_SEQUENCER_144 0x3090
+#define WM8994_WRITE_SEQUENCER_145 0x3091
+#define WM8994_WRITE_SEQUENCER_146 0x3092
+#define WM8994_WRITE_SEQUENCER_147 0x3093
+#define WM8994_WRITE_SEQUENCER_148 0x3094
+#define WM8994_WRITE_SEQUENCER_149 0x3095
+#define WM8994_WRITE_SEQUENCER_150 0x3096
+#define WM8994_WRITE_SEQUENCER_151 0x3097
+#define WM8994_WRITE_SEQUENCER_152 0x3098
+#define WM8994_WRITE_SEQUENCER_153 0x3099
+#define WM8994_WRITE_SEQUENCER_154 0x309A
+#define WM8994_WRITE_SEQUENCER_155 0x309B
+#define WM8994_WRITE_SEQUENCER_156 0x309C
+#define WM8994_WRITE_SEQUENCER_157 0x309D
+#define WM8994_WRITE_SEQUENCER_158 0x309E
+#define WM8994_WRITE_SEQUENCER_159 0x309F
+#define WM8994_WRITE_SEQUENCER_160 0x30A0
+#define WM8994_WRITE_SEQUENCER_161 0x30A1
+#define WM8994_WRITE_SEQUENCER_162 0x30A2
+#define WM8994_WRITE_SEQUENCER_163 0x30A3
+#define WM8994_WRITE_SEQUENCER_164 0x30A4
+#define WM8994_WRITE_SEQUENCER_165 0x30A5
+#define WM8994_WRITE_SEQUENCER_166 0x30A6
+#define WM8994_WRITE_SEQUENCER_167 0x30A7
+#define WM8994_WRITE_SEQUENCER_168 0x30A8
+#define WM8994_WRITE_SEQUENCER_169 0x30A9
+#define WM8994_WRITE_SEQUENCER_170 0x30AA
+#define WM8994_WRITE_SEQUENCER_171 0x30AB
+#define WM8994_WRITE_SEQUENCER_172 0x30AC
+#define WM8994_WRITE_SEQUENCER_173 0x30AD
+#define WM8994_WRITE_SEQUENCER_174 0x30AE
+#define WM8994_WRITE_SEQUENCER_175 0x30AF
+#define WM8994_WRITE_SEQUENCER_176 0x30B0
+#define WM8994_WRITE_SEQUENCER_177 0x30B1
+#define WM8994_WRITE_SEQUENCER_178 0x30B2
+#define WM8994_WRITE_SEQUENCER_179 0x30B3
+#define WM8994_WRITE_SEQUENCER_180 0x30B4
+#define WM8994_WRITE_SEQUENCER_181 0x30B5
+#define WM8994_WRITE_SEQUENCER_182 0x30B6
+#define WM8994_WRITE_SEQUENCER_183 0x30B7
+#define WM8994_WRITE_SEQUENCER_184 0x30B8
+#define WM8994_WRITE_SEQUENCER_185 0x30B9
+#define WM8994_WRITE_SEQUENCER_186 0x30BA
+#define WM8994_WRITE_SEQUENCER_187 0x30BB
+#define WM8994_WRITE_SEQUENCER_188 0x30BC
+#define WM8994_WRITE_SEQUENCER_189 0x30BD
+#define WM8994_WRITE_SEQUENCER_190 0x30BE
+#define WM8994_WRITE_SEQUENCER_191 0x30BF
+#define WM8994_WRITE_SEQUENCER_192 0x30C0
+#define WM8994_WRITE_SEQUENCER_193 0x30C1
+#define WM8994_WRITE_SEQUENCER_194 0x30C2
+#define WM8994_WRITE_SEQUENCER_195 0x30C3
+#define WM8994_WRITE_SEQUENCER_196 0x30C4
+#define WM8994_WRITE_SEQUENCER_197 0x30C5
+#define WM8994_WRITE_SEQUENCER_198 0x30C6
+#define WM8994_WRITE_SEQUENCER_199 0x30C7
+#define WM8994_WRITE_SEQUENCER_200 0x30C8
+#define WM8994_WRITE_SEQUENCER_201 0x30C9
+#define WM8994_WRITE_SEQUENCER_202 0x30CA
+#define WM8994_WRITE_SEQUENCER_203 0x30CB
+#define WM8994_WRITE_SEQUENCER_204 0x30CC
+#define WM8994_WRITE_SEQUENCER_205 0x30CD
+#define WM8994_WRITE_SEQUENCER_206 0x30CE
+#define WM8994_WRITE_SEQUENCER_207 0x30CF
+#define WM8994_WRITE_SEQUENCER_208 0x30D0
+#define WM8994_WRITE_SEQUENCER_209 0x30D1
+#define WM8994_WRITE_SEQUENCER_210 0x30D2
+#define WM8994_WRITE_SEQUENCER_211 0x30D3
+#define WM8994_WRITE_SEQUENCER_212 0x30D4
+#define WM8994_WRITE_SEQUENCER_213 0x30D5
+#define WM8994_WRITE_SEQUENCER_214 0x30D6
+#define WM8994_WRITE_SEQUENCER_215 0x30D7
+#define WM8994_WRITE_SEQUENCER_216 0x30D8
+#define WM8994_WRITE_SEQUENCER_217 0x30D9
+#define WM8994_WRITE_SEQUENCER_218 0x30DA
+#define WM8994_WRITE_SEQUENCER_219 0x30DB
+#define WM8994_WRITE_SEQUENCER_220 0x30DC
+#define WM8994_WRITE_SEQUENCER_221 0x30DD
+#define WM8994_WRITE_SEQUENCER_222 0x30DE
+#define WM8994_WRITE_SEQUENCER_223 0x30DF
+#define WM8994_WRITE_SEQUENCER_224 0x30E0
+#define WM8994_WRITE_SEQUENCER_225 0x30E1
+#define WM8994_WRITE_SEQUENCER_226 0x30E2
+#define WM8994_WRITE_SEQUENCER_227 0x30E3
+#define WM8994_WRITE_SEQUENCER_228 0x30E4
+#define WM8994_WRITE_SEQUENCER_229 0x30E5
+#define WM8994_WRITE_SEQUENCER_230 0x30E6
+#define WM8994_WRITE_SEQUENCER_231 0x30E7
+#define WM8994_WRITE_SEQUENCER_232 0x30E8
+#define WM8994_WRITE_SEQUENCER_233 0x30E9
+#define WM8994_WRITE_SEQUENCER_234 0x30EA
+#define WM8994_WRITE_SEQUENCER_235 0x30EB
+#define WM8994_WRITE_SEQUENCER_236 0x30EC
+#define WM8994_WRITE_SEQUENCER_237 0x30ED
+#define WM8994_WRITE_SEQUENCER_238 0x30EE
+#define WM8994_WRITE_SEQUENCER_239 0x30EF
+#define WM8994_WRITE_SEQUENCER_240 0x30F0
+#define WM8994_WRITE_SEQUENCER_241 0x30F1
+#define WM8994_WRITE_SEQUENCER_242 0x30F2
+#define WM8994_WRITE_SEQUENCER_243 0x30F3
+#define WM8994_WRITE_SEQUENCER_244 0x30F4
+#define WM8994_WRITE_SEQUENCER_245 0x30F5
+#define WM8994_WRITE_SEQUENCER_246 0x30F6
+#define WM8994_WRITE_SEQUENCER_247 0x30F7
+#define WM8994_WRITE_SEQUENCER_248 0x30F8
+#define WM8994_WRITE_SEQUENCER_249 0x30F9
+#define WM8994_WRITE_SEQUENCER_250 0x30FA
+#define WM8994_WRITE_SEQUENCER_251 0x30FB
+#define WM8994_WRITE_SEQUENCER_252 0x30FC
+#define WM8994_WRITE_SEQUENCER_253 0x30FD
+#define WM8994_WRITE_SEQUENCER_254 0x30FE
+#define WM8994_WRITE_SEQUENCER_255 0x30FF
+#define WM8994_WRITE_SEQUENCER_256 0x3100
+#define WM8994_WRITE_SEQUENCER_257 0x3101
+#define WM8994_WRITE_SEQUENCER_258 0x3102
+#define WM8994_WRITE_SEQUENCER_259 0x3103
+#define WM8994_WRITE_SEQUENCER_260 0x3104
+#define WM8994_WRITE_SEQUENCER_261 0x3105
+#define WM8994_WRITE_SEQUENCER_262 0x3106
+#define WM8994_WRITE_SEQUENCER_263 0x3107
+#define WM8994_WRITE_SEQUENCER_264 0x3108
+#define WM8994_WRITE_SEQUENCER_265 0x3109
+#define WM8994_WRITE_SEQUENCER_266 0x310A
+#define WM8994_WRITE_SEQUENCER_267 0x310B
+#define WM8994_WRITE_SEQUENCER_268 0x310C
+#define WM8994_WRITE_SEQUENCER_269 0x310D
+#define WM8994_WRITE_SEQUENCER_270 0x310E
+#define WM8994_WRITE_SEQUENCER_271 0x310F
+#define WM8994_WRITE_SEQUENCER_272 0x3110
+#define WM8994_WRITE_SEQUENCER_273 0x3111
+#define WM8994_WRITE_SEQUENCER_274 0x3112
+#define WM8994_WRITE_SEQUENCER_275 0x3113
+#define WM8994_WRITE_SEQUENCER_276 0x3114
+#define WM8994_WRITE_SEQUENCER_277 0x3115
+#define WM8994_WRITE_SEQUENCER_278 0x3116
+#define WM8994_WRITE_SEQUENCER_279 0x3117
+#define WM8994_WRITE_SEQUENCER_280 0x3118
+#define WM8994_WRITE_SEQUENCER_281 0x3119
+#define WM8994_WRITE_SEQUENCER_282 0x311A
+#define WM8994_WRITE_SEQUENCER_283 0x311B
+#define WM8994_WRITE_SEQUENCER_284 0x311C
+#define WM8994_WRITE_SEQUENCER_285 0x311D
+#define WM8994_WRITE_SEQUENCER_286 0x311E
+#define WM8994_WRITE_SEQUENCER_287 0x311F
+#define WM8994_WRITE_SEQUENCER_288 0x3120
+#define WM8994_WRITE_SEQUENCER_289 0x3121
+#define WM8994_WRITE_SEQUENCER_290 0x3122
+#define WM8994_WRITE_SEQUENCER_291 0x3123
+#define WM8994_WRITE_SEQUENCER_292 0x3124
+#define WM8994_WRITE_SEQUENCER_293 0x3125
+#define WM8994_WRITE_SEQUENCER_294 0x3126
+#define WM8994_WRITE_SEQUENCER_295 0x3127
+#define WM8994_WRITE_SEQUENCER_296 0x3128
+#define WM8994_WRITE_SEQUENCER_297 0x3129
+#define WM8994_WRITE_SEQUENCER_298 0x312A
+#define WM8994_WRITE_SEQUENCER_299 0x312B
+#define WM8994_WRITE_SEQUENCER_300 0x312C
+#define WM8994_WRITE_SEQUENCER_301 0x312D
+#define WM8994_WRITE_SEQUENCER_302 0x312E
+#define WM8994_WRITE_SEQUENCER_303 0x312F
+#define WM8994_WRITE_SEQUENCER_304 0x3130
+#define WM8994_WRITE_SEQUENCER_305 0x3131
+#define WM8994_WRITE_SEQUENCER_306 0x3132
+#define WM8994_WRITE_SEQUENCER_307 0x3133
+#define WM8994_WRITE_SEQUENCER_308 0x3134
+#define WM8994_WRITE_SEQUENCER_309 0x3135
+#define WM8994_WRITE_SEQUENCER_310 0x3136
+#define WM8994_WRITE_SEQUENCER_311 0x3137
+#define WM8994_WRITE_SEQUENCER_312 0x3138
+#define WM8994_WRITE_SEQUENCER_313 0x3139
+#define WM8994_WRITE_SEQUENCER_314 0x313A
+#define WM8994_WRITE_SEQUENCER_315 0x313B
+#define WM8994_WRITE_SEQUENCER_316 0x313C
+#define WM8994_WRITE_SEQUENCER_317 0x313D
+#define WM8994_WRITE_SEQUENCER_318 0x313E
+#define WM8994_WRITE_SEQUENCER_319 0x313F
+#define WM8994_WRITE_SEQUENCER_320 0x3140
+#define WM8994_WRITE_SEQUENCER_321 0x3141
+#define WM8994_WRITE_SEQUENCER_322 0x3142
+#define WM8994_WRITE_SEQUENCER_323 0x3143
+#define WM8994_WRITE_SEQUENCER_324 0x3144
+#define WM8994_WRITE_SEQUENCER_325 0x3145
+#define WM8994_WRITE_SEQUENCER_326 0x3146
+#define WM8994_WRITE_SEQUENCER_327 0x3147
+#define WM8994_WRITE_SEQUENCER_328 0x3148
+#define WM8994_WRITE_SEQUENCER_329 0x3149
+#define WM8994_WRITE_SEQUENCER_330 0x314A
+#define WM8994_WRITE_SEQUENCER_331 0x314B
+#define WM8994_WRITE_SEQUENCER_332 0x314C
+#define WM8994_WRITE_SEQUENCER_333 0x314D
+#define WM8994_WRITE_SEQUENCER_334 0x314E
+#define WM8994_WRITE_SEQUENCER_335 0x314F
+#define WM8994_WRITE_SEQUENCER_336 0x3150
+#define WM8994_WRITE_SEQUENCER_337 0x3151
+#define WM8994_WRITE_SEQUENCER_338 0x3152
+#define WM8994_WRITE_SEQUENCER_339 0x3153
+#define WM8994_WRITE_SEQUENCER_340 0x3154
+#define WM8994_WRITE_SEQUENCER_341 0x3155
+#define WM8994_WRITE_SEQUENCER_342 0x3156
+#define WM8994_WRITE_SEQUENCER_343 0x3157
+#define WM8994_WRITE_SEQUENCER_344 0x3158
+#define WM8994_WRITE_SEQUENCER_345 0x3159
+#define WM8994_WRITE_SEQUENCER_346 0x315A
+#define WM8994_WRITE_SEQUENCER_347 0x315B
+#define WM8994_WRITE_SEQUENCER_348 0x315C
+#define WM8994_WRITE_SEQUENCER_349 0x315D
+#define WM8994_WRITE_SEQUENCER_350 0x315E
+#define WM8994_WRITE_SEQUENCER_351 0x315F
+#define WM8994_WRITE_SEQUENCER_352 0x3160
+#define WM8994_WRITE_SEQUENCER_353 0x3161
+#define WM8994_WRITE_SEQUENCER_354 0x3162
+#define WM8994_WRITE_SEQUENCER_355 0x3163
+#define WM8994_WRITE_SEQUENCER_356 0x3164
+#define WM8994_WRITE_SEQUENCER_357 0x3165
+#define WM8994_WRITE_SEQUENCER_358 0x3166
+#define WM8994_WRITE_SEQUENCER_359 0x3167
+#define WM8994_WRITE_SEQUENCER_360 0x3168
+#define WM8994_WRITE_SEQUENCER_361 0x3169
+#define WM8994_WRITE_SEQUENCER_362 0x316A
+#define WM8994_WRITE_SEQUENCER_363 0x316B
+#define WM8994_WRITE_SEQUENCER_364 0x316C
+#define WM8994_WRITE_SEQUENCER_365 0x316D
+#define WM8994_WRITE_SEQUENCER_366 0x316E
+#define WM8994_WRITE_SEQUENCER_367 0x316F
+#define WM8994_WRITE_SEQUENCER_368 0x3170
+#define WM8994_WRITE_SEQUENCER_369 0x3171
+#define WM8994_WRITE_SEQUENCER_370 0x3172
+#define WM8994_WRITE_SEQUENCER_371 0x3173
+#define WM8994_WRITE_SEQUENCER_372 0x3174
+#define WM8994_WRITE_SEQUENCER_373 0x3175
+#define WM8994_WRITE_SEQUENCER_374 0x3176
+#define WM8994_WRITE_SEQUENCER_375 0x3177
+#define WM8994_WRITE_SEQUENCER_376 0x3178
+#define WM8994_WRITE_SEQUENCER_377 0x3179
+#define WM8994_WRITE_SEQUENCER_378 0x317A
+#define WM8994_WRITE_SEQUENCER_379 0x317B
+#define WM8994_WRITE_SEQUENCER_380 0x317C
+#define WM8994_WRITE_SEQUENCER_381 0x317D
+#define WM8994_WRITE_SEQUENCER_382 0x317E
+#define WM8994_WRITE_SEQUENCER_383 0x317F
+#define WM8994_WRITE_SEQUENCER_384 0x3180
+#define WM8994_WRITE_SEQUENCER_385 0x3181
+#define WM8994_WRITE_SEQUENCER_386 0x3182
+#define WM8994_WRITE_SEQUENCER_387 0x3183
+#define WM8994_WRITE_SEQUENCER_388 0x3184
+#define WM8994_WRITE_SEQUENCER_389 0x3185
+#define WM8994_WRITE_SEQUENCER_390 0x3186
+#define WM8994_WRITE_SEQUENCER_391 0x3187
+#define WM8994_WRITE_SEQUENCER_392 0x3188
+#define WM8994_WRITE_SEQUENCER_393 0x3189
+#define WM8994_WRITE_SEQUENCER_394 0x318A
+#define WM8994_WRITE_SEQUENCER_395 0x318B
+#define WM8994_WRITE_SEQUENCER_396 0x318C
+#define WM8994_WRITE_SEQUENCER_397 0x318D
+#define WM8994_WRITE_SEQUENCER_398 0x318E
+#define WM8994_WRITE_SEQUENCER_399 0x318F
+#define WM8994_WRITE_SEQUENCER_400 0x3190
+#define WM8994_WRITE_SEQUENCER_401 0x3191
+#define WM8994_WRITE_SEQUENCER_402 0x3192
+#define WM8994_WRITE_SEQUENCER_403 0x3193
+#define WM8994_WRITE_SEQUENCER_404 0x3194
+#define WM8994_WRITE_SEQUENCER_405 0x3195
+#define WM8994_WRITE_SEQUENCER_406 0x3196
+#define WM8994_WRITE_SEQUENCER_407 0x3197
+#define WM8994_WRITE_SEQUENCER_408 0x3198
+#define WM8994_WRITE_SEQUENCER_409 0x3199
+#define WM8994_WRITE_SEQUENCER_410 0x319A
+#define WM8994_WRITE_SEQUENCER_411 0x319B
+#define WM8994_WRITE_SEQUENCER_412 0x319C
+#define WM8994_WRITE_SEQUENCER_413 0x319D
+#define WM8994_WRITE_SEQUENCER_414 0x319E
+#define WM8994_WRITE_SEQUENCER_415 0x319F
+#define WM8994_WRITE_SEQUENCER_416 0x31A0
+#define WM8994_WRITE_SEQUENCER_417 0x31A1
+#define WM8994_WRITE_SEQUENCER_418 0x31A2
+#define WM8994_WRITE_SEQUENCER_419 0x31A3
+#define WM8994_WRITE_SEQUENCER_420 0x31A4
+#define WM8994_WRITE_SEQUENCER_421 0x31A5
+#define WM8994_WRITE_SEQUENCER_422 0x31A6
+#define WM8994_WRITE_SEQUENCER_423 0x31A7
+#define WM8994_WRITE_SEQUENCER_424 0x31A8
+#define WM8994_WRITE_SEQUENCER_425 0x31A9
+#define WM8994_WRITE_SEQUENCER_426 0x31AA
+#define WM8994_WRITE_SEQUENCER_427 0x31AB
+#define WM8994_WRITE_SEQUENCER_428 0x31AC
+#define WM8994_WRITE_SEQUENCER_429 0x31AD
+#define WM8994_WRITE_SEQUENCER_430 0x31AE
+#define WM8994_WRITE_SEQUENCER_431 0x31AF
+#define WM8994_WRITE_SEQUENCER_432 0x31B0
+#define WM8994_WRITE_SEQUENCER_433 0x31B1
+#define WM8994_WRITE_SEQUENCER_434 0x31B2
+#define WM8994_WRITE_SEQUENCER_435 0x31B3
+#define WM8994_WRITE_SEQUENCER_436 0x31B4
+#define WM8994_WRITE_SEQUENCER_437 0x31B5
+#define WM8994_WRITE_SEQUENCER_438 0x31B6
+#define WM8994_WRITE_SEQUENCER_439 0x31B7
+#define WM8994_WRITE_SEQUENCER_440 0x31B8
+#define WM8994_WRITE_SEQUENCER_441 0x31B9
+#define WM8994_WRITE_SEQUENCER_442 0x31BA
+#define WM8994_WRITE_SEQUENCER_443 0x31BB
+#define WM8994_WRITE_SEQUENCER_444 0x31BC
+#define WM8994_WRITE_SEQUENCER_445 0x31BD
+#define WM8994_WRITE_SEQUENCER_446 0x31BE
+#define WM8994_WRITE_SEQUENCER_447 0x31BF
+#define WM8994_WRITE_SEQUENCER_448 0x31C0
+#define WM8994_WRITE_SEQUENCER_449 0x31C1
+#define WM8994_WRITE_SEQUENCER_450 0x31C2
+#define WM8994_WRITE_SEQUENCER_451 0x31C3
+#define WM8994_WRITE_SEQUENCER_452 0x31C4
+#define WM8994_WRITE_SEQUENCER_453 0x31C5
+#define WM8994_WRITE_SEQUENCER_454 0x31C6
+#define WM8994_WRITE_SEQUENCER_455 0x31C7
+#define WM8994_WRITE_SEQUENCER_456 0x31C8
+#define WM8994_WRITE_SEQUENCER_457 0x31C9
+#define WM8994_WRITE_SEQUENCER_458 0x31CA
+#define WM8994_WRITE_SEQUENCER_459 0x31CB
+#define WM8994_WRITE_SEQUENCER_460 0x31CC
+#define WM8994_WRITE_SEQUENCER_461 0x31CD
+#define WM8994_WRITE_SEQUENCER_462 0x31CE
+#define WM8994_WRITE_SEQUENCER_463 0x31CF
+#define WM8994_WRITE_SEQUENCER_464 0x31D0
+#define WM8994_WRITE_SEQUENCER_465 0x31D1
+#define WM8994_WRITE_SEQUENCER_466 0x31D2
+#define WM8994_WRITE_SEQUENCER_467 0x31D3
+#define WM8994_WRITE_SEQUENCER_468 0x31D4
+#define WM8994_WRITE_SEQUENCER_469 0x31D5
+#define WM8994_WRITE_SEQUENCER_470 0x31D6
+#define WM8994_WRITE_SEQUENCER_471 0x31D7
+#define WM8994_WRITE_SEQUENCER_472 0x31D8
+#define WM8994_WRITE_SEQUENCER_473 0x31D9
+#define WM8994_WRITE_SEQUENCER_474 0x31DA
+#define WM8994_WRITE_SEQUENCER_475 0x31DB
+#define WM8994_WRITE_SEQUENCER_476 0x31DC
+#define WM8994_WRITE_SEQUENCER_477 0x31DD
+#define WM8994_WRITE_SEQUENCER_478 0x31DE
+#define WM8994_WRITE_SEQUENCER_479 0x31DF
+#define WM8994_WRITE_SEQUENCER_480 0x31E0
+#define WM8994_WRITE_SEQUENCER_481 0x31E1
+#define WM8994_WRITE_SEQUENCER_482 0x31E2
+#define WM8994_WRITE_SEQUENCER_483 0x31E3
+#define WM8994_WRITE_SEQUENCER_484 0x31E4
+#define WM8994_WRITE_SEQUENCER_485 0x31E5
+#define WM8994_WRITE_SEQUENCER_486 0x31E6
+#define WM8994_WRITE_SEQUENCER_487 0x31E7
+#define WM8994_WRITE_SEQUENCER_488 0x31E8
+#define WM8994_WRITE_SEQUENCER_489 0x31E9
+#define WM8994_WRITE_SEQUENCER_490 0x31EA
+#define WM8994_WRITE_SEQUENCER_491 0x31EB
+#define WM8994_WRITE_SEQUENCER_492 0x31EC
+#define WM8994_WRITE_SEQUENCER_493 0x31ED
+#define WM8994_WRITE_SEQUENCER_494 0x31EE
+#define WM8994_WRITE_SEQUENCER_495 0x31EF
+#define WM8994_WRITE_SEQUENCER_496 0x31F0
+#define WM8994_WRITE_SEQUENCER_497 0x31F1
+#define WM8994_WRITE_SEQUENCER_498 0x31F2
+#define WM8994_WRITE_SEQUENCER_499 0x31F3
+#define WM8994_WRITE_SEQUENCER_500 0x31F4
+#define WM8994_WRITE_SEQUENCER_501 0x31F5
+#define WM8994_WRITE_SEQUENCER_502 0x31F6
+#define WM8994_WRITE_SEQUENCER_503 0x31F7
+#define WM8994_WRITE_SEQUENCER_504 0x31F8
+#define WM8994_WRITE_SEQUENCER_505 0x31F9
+#define WM8994_WRITE_SEQUENCER_506 0x31FA
+#define WM8994_WRITE_SEQUENCER_507 0x31FB
+#define WM8994_WRITE_SEQUENCER_508 0x31FC
+#define WM8994_WRITE_SEQUENCER_509 0x31FD
+#define WM8994_WRITE_SEQUENCER_510 0x31FE
+#define WM8994_WRITE_SEQUENCER_511 0x31FF
+
+#define WM8994_REGISTER_COUNT 736
+#define WM8994_MAX_REGISTER 0x31FF
+
+
+/*
+ * Field Definitions.
+ */
+
+/*
+ * R0 (0x00) - Software Reset
+ */
+#define WM8994_SW_RESET_MASK 0xFFFF /* SW_RESET - [15:0] */
+#define WM8994_SW_RESET_SHIFT 0 /* SW_RESET - [15:0] */
+#define WM8994_SW_RESET_WIDTH 16 /* SW_RESET - [15:0] */
+
+/*
+ * R1 (0x01) - Power Management (1)
+ */
+#define WM8994_SPKOUTR_ENA 0x2000 /* SPKOUTR_ENA */
+#define WM8994_SPKOUTR_ENA_MASK 0x2000 /* SPKOUTR_ENA */
+#define WM8994_SPKOUTR_ENA_SHIFT 13 /* SPKOUTR_ENA */
+#define WM8994_SPKOUTR_ENA_WIDTH 1 /* SPKOUTR_ENA */
+#define WM8994_SPKOUTL_ENA 0x1000 /* SPKOUTL_ENA */
+#define WM8994_SPKOUTL_ENA_MASK 0x1000 /* SPKOUTL_ENA */
+#define WM8994_SPKOUTL_ENA_SHIFT 12 /* SPKOUTL_ENA */
+#define WM8994_SPKOUTL_ENA_WIDTH 1 /* SPKOUTL_ENA */
+#define WM8994_HPOUT2_ENA 0x0800 /* HPOUT2_ENA */
+#define WM8994_HPOUT2_ENA_MASK 0x0800 /* HPOUT2_ENA */
+#define WM8994_HPOUT2_ENA_SHIFT 11 /* HPOUT2_ENA */
+#define WM8994_HPOUT2_ENA_WIDTH 1 /* HPOUT2_ENA */
+#define WM8994_HPOUT1L_ENA 0x0200 /* HPOUT1L_ENA */
+#define WM8994_HPOUT1L_ENA_MASK 0x0200 /* HPOUT1L_ENA */
+#define WM8994_HPOUT1L_ENA_SHIFT 9 /* HPOUT1L_ENA */
+#define WM8994_HPOUT1L_ENA_WIDTH 1 /* HPOUT1L_ENA */
+#define WM8994_HPOUT1R_ENA 0x0100 /* HPOUT1R_ENA */
+#define WM8994_HPOUT1R_ENA_MASK 0x0100 /* HPOUT1R_ENA */
+#define WM8994_HPOUT1R_ENA_SHIFT 8 /* HPOUT1R_ENA */
+#define WM8994_HPOUT1R_ENA_WIDTH 1 /* HPOUT1R_ENA */
+#define WM8994_MICB2_ENA 0x0020 /* MICB2_ENA */
+#define WM8994_MICB2_ENA_MASK 0x0020 /* MICB2_ENA */
+#define WM8994_MICB2_ENA_SHIFT 5 /* MICB2_ENA */
+#define WM8994_MICB2_ENA_WIDTH 1 /* MICB2_ENA */
+#define WM8994_MICB1_ENA 0x0010 /* MICB1_ENA */
+#define WM8994_MICB1_ENA_MASK 0x0010 /* MICB1_ENA */
+#define WM8994_MICB1_ENA_SHIFT 4 /* MICB1_ENA */
+#define WM8994_MICB1_ENA_WIDTH 1 /* MICB1_ENA */
+#define WM8994_VMID_SEL_NORMAL 0x0002
+#define WM8994_VMID_SEL_MASK 0x0006 /* VMID_SEL - [2:1] */
+#define WM8994_VMID_SEL_SHIFT 1 /* VMID_SEL - [2:1] */
+#define WM8994_VMID_SEL_WIDTH 2 /* VMID_SEL - [2:1] */
+#define WM8994_BIAS_ENA 0x0001 /* BIAS_ENA */
+#define WM8994_BIAS_ENA_MASK 0x0001 /* BIAS_ENA */
+#define WM8994_BIAS_ENA_SHIFT 0 /* BIAS_ENA */
+#define WM8994_BIAS_ENA_WIDTH 1 /* BIAS_ENA */
+
+/*
+ * R2 (0x02) - Power Management (2)
+ */
+#define WM8994_TSHUT_ENA 0x4000 /* TSHUT_ENA */
+#define WM8994_TSHUT_ENA_MASK 0x4000 /* TSHUT_ENA */
+#define WM8994_TSHUT_ENA_SHIFT 14 /* TSHUT_ENA */
+#define WM8994_TSHUT_ENA_WIDTH 1 /* TSHUT_ENA */
+#define WM8994_TSHUT_OPDIS 0x2000 /* TSHUT_OPDIS */
+#define WM8994_TSHUT_OPDIS_MASK 0x2000 /* TSHUT_OPDIS */
+#define WM8994_TSHUT_OPDIS_SHIFT 13 /* TSHUT_OPDIS */
+#define WM8994_TSHUT_OPDIS_WIDTH 1 /* TSHUT_OPDIS */
+#define WM8994_OPCLK_ENA 0x0800 /* OPCLK_ENA */
+#define WM8994_OPCLK_ENA_MASK 0x0800 /* OPCLK_ENA */
+#define WM8994_OPCLK_ENA_SHIFT 11 /* OPCLK_ENA */
+#define WM8994_OPCLK_ENA_WIDTH 1 /* OPCLK_ENA */
+#define WM8994_MIXINL_ENA 0x0200 /* MIXINL_ENA */
+#define WM8994_MIXINL_ENA_MASK 0x0200 /* MIXINL_ENA */
+#define WM8994_MIXINL_ENA_SHIFT 9 /* MIXINL_ENA */
+#define WM8994_MIXINL_ENA_WIDTH 1 /* MIXINL_ENA */
+#define WM8994_MIXINR_ENA 0x0100 /* MIXINR_ENA */
+#define WM8994_MIXINR_ENA_MASK 0x0100 /* MIXINR_ENA */
+#define WM8994_MIXINR_ENA_SHIFT 8 /* MIXINR_ENA */
+#define WM8994_MIXINR_ENA_WIDTH 1 /* MIXINR_ENA */
+#define WM8994_IN2L_ENA 0x0080 /* IN2L_ENA */
+#define WM8994_IN2L_ENA_MASK 0x0080 /* IN2L_ENA */
+#define WM8994_IN2L_ENA_SHIFT 7 /* IN2L_ENA */
+#define WM8994_IN2L_ENA_WIDTH 1 /* IN2L_ENA */
+#define WM8994_IN1L_ENA 0x0040 /* IN1L_ENA */
+#define WM8994_IN1L_ENA_MASK 0x0040 /* IN1L_ENA */
+#define WM8994_IN1L_ENA_SHIFT 6 /* IN1L_ENA */
+#define WM8994_IN1L_ENA_WIDTH 1 /* IN1L_ENA */
+#define WM8994_IN2R_ENA 0x0020 /* IN2R_ENA */
+#define WM8994_IN2R_ENA_MASK 0x0020 /* IN2R_ENA */
+#define WM8994_IN2R_ENA_SHIFT 5 /* IN2R_ENA */
+#define WM8994_IN2R_ENA_WIDTH 1 /* IN2R_ENA */
+#define WM8994_IN1R_ENA 0x0010 /* IN1R_ENA */
+#define WM8994_IN1R_ENA_MASK 0x0010 /* IN1R_ENA */
+#define WM8994_IN1R_ENA_SHIFT 4 /* IN1R_ENA */
+#define WM8994_IN1R_ENA_WIDTH 1 /* IN1R_ENA */
+
+/*
+ * R3 (0x03) - Power Management (3)
+ */
+#define WM8994_LINEOUT1N_ENA 0x2000 /* LINEOUT1N_ENA */
+#define WM8994_LINEOUT1N_ENA_MASK 0x2000 /* LINEOUT1N_ENA */
+#define WM8994_LINEOUT1N_ENA_SHIFT 13 /* LINEOUT1N_ENA */
+#define WM8994_LINEOUT1N_ENA_WIDTH 1 /* LINEOUT1N_ENA */
+#define WM8994_LINEOUT1P_ENA 0x1000 /* LINEOUT1P_ENA */
+#define WM8994_LINEOUT1P_ENA_MASK 0x1000 /* LINEOUT1P_ENA */
+#define WM8994_LINEOUT1P_ENA_SHIFT 12 /* LINEOUT1P_ENA */
+#define WM8994_LINEOUT1P_ENA_WIDTH 1 /* LINEOUT1P_ENA */
+#define WM8994_LINEOUT2N_ENA 0x0800 /* LINEOUT2N_ENA */
+#define WM8994_LINEOUT2N_ENA_MASK 0x0800 /* LINEOUT2N_ENA */
+#define WM8994_LINEOUT2N_ENA_SHIFT 11 /* LINEOUT2N_ENA */
+#define WM8994_LINEOUT2N_ENA_WIDTH 1 /* LINEOUT2N_ENA */
+#define WM8994_LINEOUT2P_ENA 0x0400 /* LINEOUT2P_ENA */
+#define WM8994_LINEOUT2P_ENA_MASK 0x0400 /* LINEOUT2P_ENA */
+#define WM8994_LINEOUT2P_ENA_SHIFT 10 /* LINEOUT2P_ENA */
+#define WM8994_LINEOUT2P_ENA_WIDTH 1 /* LINEOUT2P_ENA */
+#define WM8994_SPKRVOL_ENA 0x0200 /* SPKRVOL_ENA */
+#define WM8994_SPKRVOL_ENA_MASK 0x0200 /* SPKRVOL_ENA */
+#define WM8994_SPKRVOL_ENA_SHIFT 9 /* SPKRVOL_ENA */
+#define WM8994_SPKRVOL_ENA_WIDTH 1 /* SPKRVOL_ENA */
+#define WM8994_SPKLVOL_ENA 0x0100 /* SPKLVOL_ENA */
+#define WM8994_SPKLVOL_ENA_MASK 0x0100 /* SPKLVOL_ENA */
+#define WM8994_SPKLVOL_ENA_SHIFT 8 /* SPKLVOL_ENA */
+#define WM8994_SPKLVOL_ENA_WIDTH 1 /* SPKLVOL_ENA */
+#define WM8994_MIXOUTLVOL_ENA 0x0080 /* MIXOUTLVOL_ENA */
+#define WM8994_MIXOUTLVOL_ENA_MASK 0x0080 /* MIXOUTLVOL_ENA */
+#define WM8994_MIXOUTLVOL_ENA_SHIFT 7 /* MIXOUTLVOL_ENA */
+#define WM8994_MIXOUTLVOL_ENA_WIDTH 1 /* MIXOUTLVOL_ENA */
+#define WM8994_MIXOUTRVOL_ENA 0x0040 /* MIXOUTRVOL_ENA */
+#define WM8994_MIXOUTRVOL_ENA_MASK 0x0040 /* MIXOUTRVOL_ENA */
+#define WM8994_MIXOUTRVOL_ENA_SHIFT 6 /* MIXOUTRVOL_ENA */
+#define WM8994_MIXOUTRVOL_ENA_WIDTH 1 /* MIXOUTRVOL_ENA */
+#define WM8994_MIXOUTL_ENA 0x0020 /* MIXOUTL_ENA */
+#define WM8994_MIXOUTL_ENA_MASK 0x0020 /* MIXOUTL_ENA */
+#define WM8994_MIXOUTL_ENA_SHIFT 5 /* MIXOUTL_ENA */
+#define WM8994_MIXOUTL_ENA_WIDTH 1 /* MIXOUTL_ENA */
+#define WM8994_MIXOUTR_ENA 0x0010 /* MIXOUTR_ENA */
+#define WM8994_MIXOUTR_ENA_MASK 0x0010 /* MIXOUTR_ENA */
+#define WM8994_MIXOUTR_ENA_SHIFT 4 /* MIXOUTR_ENA */
+#define WM8994_MIXOUTR_ENA_WIDTH 1 /* MIXOUTR_ENA */
+
+/*
+ * R4 (0x04) - Power Management (4)
+ */
+#define WM8994_AIF2ADCL_ENA 0x2000 /* AIF2ADCL_ENA */
+#define WM8994_AIF2ADCL_ENA_MASK 0x2000 /* AIF2ADCL_ENA */
+#define WM8994_AIF2ADCL_ENA_SHIFT 13 /* AIF2ADCL_ENA */
+#define WM8994_AIF2ADCL_ENA_WIDTH 1 /* AIF2ADCL_ENA */
+#define WM8994_AIF2ADCR_ENA 0x1000 /* AIF2ADCR_ENA */
+#define WM8994_AIF2ADCR_ENA_MASK 0x1000 /* AIF2ADCR_ENA */
+#define WM8994_AIF2ADCR_ENA_SHIFT 12 /* AIF2ADCR_ENA */
+#define WM8994_AIF2ADCR_ENA_WIDTH 1 /* AIF2ADCR_ENA */
+#define WM8994_AIF1ADC2L_ENA 0x0800 /* AIF1ADC2L_ENA */
+#define WM8994_AIF1ADC2L_ENA_MASK 0x0800 /* AIF1ADC2L_ENA */
+#define WM8994_AIF1ADC2L_ENA_SHIFT 11 /* AIF1ADC2L_ENA */
+#define WM8994_AIF1ADC2L_ENA_WIDTH 1 /* AIF1ADC2L_ENA */
+#define WM8994_AIF1ADC2R_ENA 0x0400 /* AIF1ADC2R_ENA */
+#define WM8994_AIF1ADC2R_ENA_MASK 0x0400 /* AIF1ADC2R_ENA */
+#define WM8994_AIF1ADC2R_ENA_SHIFT 10 /* AIF1ADC2R_ENA */
+#define WM8994_AIF1ADC2R_ENA_WIDTH 1 /* AIF1ADC2R_ENA */
+#define WM8994_AIF1ADC1L_ENA 0x0200 /* AIF1ADC1L_ENA */
+#define WM8994_AIF1ADC1L_ENA_MASK 0x0200 /* AIF1ADC1L_ENA */
+#define WM8994_AIF1ADC1L_ENA_SHIFT 9 /* AIF1ADC1L_ENA */
+#define WM8994_AIF1ADC1L_ENA_WIDTH 1 /* AIF1ADC1L_ENA */
+#define WM8994_AIF1ADC1R_ENA 0x0100 /* AIF1ADC1R_ENA */
+#define WM8994_AIF1ADC1R_ENA_MASK 0x0100 /* AIF1ADC1R_ENA */
+#define WM8994_AIF1ADC1R_ENA_SHIFT 8 /* AIF1ADC1R_ENA */
+#define WM8994_AIF1ADC1R_ENA_WIDTH 1 /* AIF1ADC1R_ENA */
+#define WM8994_DMIC2L_ENA 0x0020 /* DMIC2L_ENA */
+#define WM8994_DMIC2L_ENA_MASK 0x0020 /* DMIC2L_ENA */
+#define WM8994_DMIC2L_ENA_SHIFT 5 /* DMIC2L_ENA */
+#define WM8994_DMIC2L_ENA_WIDTH 1 /* DMIC2L_ENA */
+#define WM8994_DMIC2R_ENA 0x0010 /* DMIC2R_ENA */
+#define WM8994_DMIC2R_ENA_MASK 0x0010 /* DMIC2R_ENA */
+#define WM8994_DMIC2R_ENA_SHIFT 4 /* DMIC2R_ENA */
+#define WM8994_DMIC2R_ENA_WIDTH 1 /* DMIC2R_ENA */
+#define WM8994_DMIC1L_ENA 0x0008 /* DMIC1L_ENA */
+#define WM8994_DMIC1L_ENA_MASK 0x0008 /* DMIC1L_ENA */
+#define WM8994_DMIC1L_ENA_SHIFT 3 /* DMIC1L_ENA */
+#define WM8994_DMIC1L_ENA_WIDTH 1 /* DMIC1L_ENA */
+#define WM8994_DMIC1R_ENA 0x0004 /* DMIC1R_ENA */
+#define WM8994_DMIC1R_ENA_MASK 0x0004 /* DMIC1R_ENA */
+#define WM8994_DMIC1R_ENA_SHIFT 2 /* DMIC1R_ENA */
+#define WM8994_DMIC1R_ENA_WIDTH 1 /* DMIC1R_ENA */
+#define WM8994_ADCL_ENA 0x0002 /* ADCL_ENA */
+#define WM8994_ADCL_ENA_MASK 0x0002 /* ADCL_ENA */
+#define WM8994_ADCL_ENA_SHIFT 1 /* ADCL_ENA */
+#define WM8994_ADCL_ENA_WIDTH 1 /* ADCL_ENA */
+#define WM8994_ADCR_ENA 0x0001 /* ADCR_ENA */
+#define WM8994_ADCR_ENA_MASK 0x0001 /* ADCR_ENA */
+#define WM8994_ADCR_ENA_SHIFT 0 /* ADCR_ENA */
+#define WM8994_ADCR_ENA_WIDTH 1 /* ADCR_ENA */
+
+/*
+ * R5 (0x05) - Power Management (5)
+ */
+#define WM8994_AIF2DACL_ENA 0x2000 /* AIF2DACL_ENA */
+#define WM8994_AIF2DACL_ENA_MASK 0x2000 /* AIF2DACL_ENA */
+#define WM8994_AIF2DACL_ENA_SHIFT 13 /* AIF2DACL_ENA */
+#define WM8994_AIF2DACL_ENA_WIDTH 1 /* AIF2DACL_ENA */
+#define WM8994_AIF2DACR_ENA 0x1000 /* AIF2DACR_ENA */
+#define WM8994_AIF2DACR_ENA_MASK 0x1000 /* AIF2DACR_ENA */
+#define WM8994_AIF2DACR_ENA_SHIFT 12 /* AIF2DACR_ENA */
+#define WM8994_AIF2DACR_ENA_WIDTH 1 /* AIF2DACR_ENA */
+#define WM8994_AIF1DAC2L_ENA 0x0800 /* AIF1DAC2L_ENA */
+#define WM8994_AIF1DAC2L_ENA_MASK 0x0800 /* AIF1DAC2L_ENA */
+#define WM8994_AIF1DAC2L_ENA_SHIFT 11 /* AIF1DAC2L_ENA */
+#define WM8994_AIF1DAC2L_ENA_WIDTH 1 /* AIF1DAC2L_ENA */
+#define WM8994_AIF1DAC2R_ENA 0x0400 /* AIF1DAC2R_ENA */
+#define WM8994_AIF1DAC2R_ENA_MASK 0x0400 /* AIF1DAC2R_ENA */
+#define WM8994_AIF1DAC2R_ENA_SHIFT 10 /* AIF1DAC2R_ENA */
+#define WM8994_AIF1DAC2R_ENA_WIDTH 1 /* AIF1DAC2R_ENA */
+#define WM8994_AIF1DAC1L_ENA 0x0200 /* AIF1DAC1L_ENA */
+#define WM8994_AIF1DAC1L_ENA_MASK 0x0200 /* AIF1DAC1L_ENA */
+#define WM8994_AIF1DAC1L_ENA_SHIFT 9 /* AIF1DAC1L_ENA */
+#define WM8994_AIF1DAC1L_ENA_WIDTH 1 /* AIF1DAC1L_ENA */
+#define WM8994_AIF1DAC1R_ENA 0x0100 /* AIF1DAC1R_ENA */
+#define WM8994_AIF1DAC1R_ENA_MASK 0x0100 /* AIF1DAC1R_ENA */
+#define WM8994_AIF1DAC1R_ENA_SHIFT 8 /* AIF1DAC1R_ENA */
+#define WM8994_AIF1DAC1R_ENA_WIDTH 1 /* AIF1DAC1R_ENA */
+#define WM8994_DAC2L_ENA 0x0008 /* DAC2L_ENA */
+#define WM8994_DAC2L_ENA_MASK 0x0008 /* DAC2L_ENA */
+#define WM8994_DAC2L_ENA_SHIFT 3 /* DAC2L_ENA */
+#define WM8994_DAC2L_ENA_WIDTH 1 /* DAC2L_ENA */
+#define WM8994_DAC2R_ENA 0x0004 /* DAC2R_ENA */
+#define WM8994_DAC2R_ENA_MASK 0x0004 /* DAC2R_ENA */
+#define WM8994_DAC2R_ENA_SHIFT 2 /* DAC2R_ENA */
+#define WM8994_DAC2R_ENA_WIDTH 1 /* DAC2R_ENA */
+#define WM8994_DAC1L_ENA 0x0002 /* DAC1L_ENA */
+#define WM8994_DAC1L_ENA_MASK 0x0002 /* DAC1L_ENA */
+#define WM8994_DAC1L_ENA_SHIFT 1 /* DAC1L_ENA */
+#define WM8994_DAC1L_ENA_WIDTH 1 /* DAC1L_ENA */
+#define WM8994_DAC1R_ENA 0x0001 /* DAC1R_ENA */
+#define WM8994_DAC1R_ENA_MASK 0x0001 /* DAC1R_ENA */
+#define WM8994_DAC1R_ENA_SHIFT 0 /* DAC1R_ENA */
+#define WM8994_DAC1R_ENA_WIDTH 1 /* DAC1R_ENA */
+
+/*
+ * R6 (0x06) - Power Management (6)
+ */
+#define WM8994_AIF3_TRIS 0x0020 /* AIF3_TRIS */
+#define WM8994_AIF3_TRIS_MASK 0x0020 /* AIF3_TRIS */
+#define WM8994_AIF3_TRIS_SHIFT 5 /* AIF3_TRIS */
+#define WM8994_AIF3_TRIS_WIDTH 1 /* AIF3_TRIS */
+#define WM8994_AIF3_ADCDAT_SRC_MASK 0x0018 /* AIF3_ADCDAT_SRC - [4:3] */
+#define WM8994_AIF3_ADCDAT_SRC_SHIFT 3 /* AIF3_ADCDAT_SRC - [4:3] */
+#define WM8994_AIF3_ADCDAT_SRC_WIDTH 2 /* AIF3_ADCDAT_SRC - [4:3] */
+#define WM8994_AIF2_ADCDAT_SRC 0x0004 /* AIF2_ADCDAT_SRC */
+#define WM8994_AIF2_ADCDAT_SRC_MASK 0x0004 /* AIF2_ADCDAT_SRC */
+#define WM8994_AIF2_ADCDAT_SRC_SHIFT 2 /* AIF2_ADCDAT_SRC */
+#define WM8994_AIF2_ADCDAT_SRC_WIDTH 1 /* AIF2_ADCDAT_SRC */
+#define WM8994_AIF2_DACDAT_SRC 0x0002 /* AIF2_DACDAT_SRC */
+#define WM8994_AIF2_DACDAT_SRC_MASK 0x0002 /* AIF2_DACDAT_SRC */
+#define WM8994_AIF2_DACDAT_SRC_SHIFT 1 /* AIF2_DACDAT_SRC */
+#define WM8994_AIF2_DACDAT_SRC_WIDTH 1 /* AIF2_DACDAT_SRC */
+#define WM8994_AIF1_DACDAT_SRC 0x0001 /* AIF1_DACDAT_SRC */
+#define WM8994_AIF1_DACDAT_SRC_MASK 0x0001 /* AIF1_DACDAT_SRC */
+#define WM8994_AIF1_DACDAT_SRC_SHIFT 0 /* AIF1_DACDAT_SRC */
+#define WM8994_AIF1_DACDAT_SRC_WIDTH 1 /* AIF1_DACDAT_SRC */
+
+/*
+ * R21 (0x15) - Input Mixer (1)
+ */
+#define WM8994_INPUTS_CLAMP 0x0040 /* INPUTS_CLAMP */
+#define WM8994_INPUTS_CLAMP_MASK 0x0040 /* INPUTS_CLAMP */
+#define WM8994_INPUTS_CLAMP_SHIFT 6 /* INPUTS_CLAMP */
+#define WM8994_INPUTS_CLAMP_WIDTH 1 /* INPUTS_CLAMP */
+
+/*
+ * R24 (0x18) - Left Line Input 1&2 Volume
+ */
+#define WM8994_IN1L_VU 0x0100 /* IN1_VU */
+#define WM8994_IN1L_VU_MASK 0x0100 /* IN1_VU */
+#define WM8994_IN1L_VU_SHIFT 8 /* IN1_VU */
+#define WM8994_IN1L_VU_WIDTH 1 /* IN1_VU */
+#define WM8994_IN1L_MUTE 0x0080 /* IN1L_MUTE */
+#define WM8994_IN1L_MUTE_MASK 0x0080 /* IN1L_MUTE */
+#define WM8994_IN1L_MUTE_SHIFT 7 /* IN1L_MUTE */
+#define WM8994_IN1L_MUTE_WIDTH 1 /* IN1L_MUTE */
+#define WM8994_IN1L_ZC 0x0040 /* IN1L_ZC */
+#define WM8994_IN1L_ZC_MASK 0x0040 /* IN1L_ZC */
+#define WM8994_IN1L_ZC_SHIFT 6 /* IN1L_ZC */
+#define WM8994_IN1L_ZC_WIDTH 1 /* IN1L_ZC */
+#define WM8994_IN1L_VOL_30dB 0x001F
+#define WM8994_IN1L_VOL_25_5dB 0x001C
+#define WM8994_IN1L_VOL_21dB 0x0019
+#define WM8994_IN1L_VOL_16_5dB 0x0016
+#define WM8994_IN1L_VOL_12dB 0x0013
+#define WM8994_IN1L_VOL_7_5dB 0x0010
+#define WM8994_IN1L_VOL_3dB 0x000D
+#define WM8994_IN1L_VOL_n1_5dB 0x000A
+#define WM8994_IN1L_VOL_n6dB 0x0007
+#define WM8994_IN1L_VOL_n10_5dB 0x0004
+#define WM8994_IN1L_VOL_n13_5dB 0x0002
+#define WM8994_IN1L_VOL_n16_5dB 0x0000
+#define WM8994_IN1L_VOL_MASK 0x001F /* IN1L_VOL - [4:0] */
+#define WM8994_IN1L_VOL_SHIFT 0 /* IN1L_VOL - [4:0] */
+#define WM8994_IN1L_VOL_WIDTH 5 /* IN1L_VOL - [4:0] */
+
+/*
+ * R25 (0x19) - Left Line Input 3&4 Volume
+ */
+#define WM8994_IN2L_VU 0x0100 /* IN2_VU */
+#define WM8994_IN2L_VU_MASK 0x0100 /* IN2_VU */
+#define WM8994_IN2L_VU_SHIFT 8 /* IN2_VU */
+#define WM8994_IN2L_VU_WIDTH 1 /* IN2_VU */
+#define WM8994_IN2L_MUTE 0x0080 /* IN2L_MUTE */
+#define WM8994_IN2L_MUTE_MASK 0x0080 /* IN2L_MUTE */
+#define WM8994_IN2L_MUTE_SHIFT 7 /* IN2L_MUTE */
+#define WM8994_IN2L_MUTE_WIDTH 1 /* IN2L_MUTE */
+#define WM8994_IN2L_ZC 0x0040 /* IN2L_ZC */
+#define WM8994_IN2L_ZC_MASK 0x0040 /* IN2L_ZC */
+#define WM8994_IN2L_ZC_SHIFT 6 /* IN2L_ZC */
+#define WM8994_IN2L_ZC_WIDTH 1 /* IN2L_ZC */
+#define WM8994_IN2L_VOL_30dB 0x001F
+#define WM8994_IN2L_VOL_25_5dB 0x001C
+#define WM8994_IN2L_VOL_21dB 0x0019
+#define WM8994_IN2L_VOL_16_5dB 0x0016
+#define WM8994_IN2L_VOL_12dB 0x0013
+#define WM8994_IN2L_VOL_7_5dB 0x0010
+#define WM8994_IN2L_VOL_3dB 0x000D
+#define WM8994_IN2L_VOL_n1_5dB 0x000A
+#define WM8994_IN2L_VOL_n6dB 0x0007
+#define WM8994_IN2L_VOL_n10_5dB 0x0004
+#define WM8994_IN2L_VOL_n13_5dB 0x0002
+#define WM8994_IN2L_VOL_n16_5dB 0x0000
+#define WM8994_IN2L_VOL_MASK 0x001F /* IN2L_VOL - [4:0] */
+#define WM8994_IN2L_VOL_SHIFT 0 /* IN2L_VOL - [4:0] */
+#define WM8994_IN2L_VOL_WIDTH 5 /* IN2L_VOL - [4:0] */
+
+/*
+ * R26 (0x1A) - Right Line Input 1&2 Volume
+ */
+#define WM8994_IN1R_VU 0x0100 /* IN1_VU */
+#define WM8994_IN1R_VU_MASK 0x0100 /* IN1_VU */
+#define WM8994_IN1R_VU_SHIFT 8 /* IN1_VU */
+#define WM8994_IN1R_VU_WIDTH 1 /* IN1_VU */
+#define WM8994_IN1R_MUTE 0x0080 /* IN1R_MUTE */
+#define WM8994_IN1R_MUTE_MASK 0x0080 /* IN1R_MUTE */
+#define WM8994_IN1R_MUTE_SHIFT 7 /* IN1R_MUTE */
+#define WM8994_IN1R_MUTE_WIDTH 1 /* IN1R_MUTE */
+#define WM8994_IN1R_ZC 0x0040 /* IN1R_ZC */
+#define WM8994_IN1R_ZC_MASK 0x0040 /* IN1R_ZC */
+#define WM8994_IN1R_ZC_SHIFT 6 /* IN1R_ZC */
+#define WM8994_IN1R_ZC_WIDTH 1 /* IN1R_ZC */
+#define WM8994_IN1R_VOL_30dB 0x001F
+#define WM8994_IN1R_VOL_25_5dB 0x001C
+#define WM8994_IN1R_VOL_21dB 0x0019
+#define WM8994_IN1R_VOL_16_5dB 0x0016
+#define WM8994_IN1R_VOL_12dB 0x0013
+#define WM8994_IN1R_VOL_7_5dB 0x0010
+#define WM8994_IN1R_VOL_3dB 0x000D
+#define WM8994_IN1R_VOL_n1_5dB 0x000A
+#define WM8994_IN1R_VOL_n6dB 0x0007
+#define WM8994_IN1R_VOL_n10_5dB 0x0004
+#define WM8994_IN1R_VOL_n13_5dB 0x0002
+#define WM8994_IN1R_VOL_n16_5dB 0x0000
+#define WM8994_IN1R_VOL_MASK 0x001F /* IN1R_VOL - [4:0] */
+#define WM8994_IN1R_VOL_SHIFT 0 /* IN1R_VOL - [4:0] */
+#define WM8994_IN1R_VOL_WIDTH 5 /* IN1R_VOL - [4:0] */
+
+/*
+ * R27 (0x1B) - Right Line Input 3&4 Volume
+ */
+#define WM8994_IN2R_VU 0x0100 /* IN2_VU */
+#define WM8994_IN2R_VU_MASK 0x0100 /* IN2_VU */
+#define WM8994_IN2R_VU_SHIFT 8 /* IN2_VU */
+#define WM8994_IN2R_VU_WIDTH 1 /* IN2_VU */
+#define WM8994_IN2R_MUTE 0x0080 /* IN2R_MUTE */
+#define WM8994_IN2R_MUTE_MASK 0x0080 /* IN2R_MUTE */
+#define WM8994_IN2R_MUTE_SHIFT 7 /* IN2R_MUTE */
+#define WM8994_IN2R_MUTE_WIDTH 1 /* IN2R_MUTE */
+#define WM8994_IN2R_ZC 0x0040 /* IN2R_ZC */
+#define WM8994_IN2R_ZC_MASK 0x0040 /* IN2R_ZC */
+#define WM8994_IN2R_ZC_SHIFT 6 /* IN2R_ZC */
+#define WM8994_IN2R_ZC_WIDTH 1 /* IN2R_ZC */
+#define WM8994_IN2R_VOL_30dB 0x001F
+#define WM8994_IN2R_VOL_25_5dB 0x001C
+#define WM8994_IN2R_VOL_21dB 0x0019
+#define WM8994_IN2R_VOL_16_5dB 0x0016
+#define WM8994_IN2R_VOL_12dB 0x0013
+#define WM8994_IN2R_VOL_7_5dB 0x0010
+#define WM8994_IN2R_VOL_3dB 0x000D
+#define WM8994_IN2R_VOL_n1_5dB 0x000A
+#define WM8994_IN2R_VOL_n6dB 0x0007
+#define WM8994_IN2R_VOL_n10_5dB 0x0004
+#define WM8994_IN2R_VOL_n13_5dB 0x0002
+#define WM8994_IN2R_VOL_n16_5dB 0x0000
+#define WM8994_IN2R_VOL_MASK 0x001F /* IN2R_VOL - [4:0] */
+#define WM8994_IN2R_VOL_SHIFT 0 /* IN2R_VOL - [4:0] */
+#define WM8994_IN2R_VOL_WIDTH 5 /* IN2R_VOL - [4:0] */
+
+/*
+ * R28 (0x1C) - Left Output Volume
+ */
+#define WM8994_HPOUT1_VU 0x0100 /* HPOUT1_VU */
+#define WM8994_HPOUT1_VU_MASK 0x0100 /* HPOUT1_VU */
+#define WM8994_HPOUT1_VU_SHIFT 8 /* HPOUT1_VU */
+#define WM8994_HPOUT1_VU_WIDTH 1 /* HPOUT1_VU */
+#define WM8994_HPOUT1L_ZC 0x0080 /* HPOUT1L_ZC */
+#define WM8994_HPOUT1L_ZC_MASK 0x0080 /* HPOUT1L_ZC */
+#define WM8994_HPOUT1L_ZC_SHIFT 7 /* HPOUT1L_ZC */
+#define WM8994_HPOUT1L_ZC_WIDTH 1 /* HPOUT1L_ZC */
+#define WM8994_HPOUT1L_MUTE_N 0x0040 /* HPOUT1L_MUTE_N */
+#define WM8994_HPOUT1L_MUTE_N_MASK 0x0040 /* HPOUT1L_MUTE_N */
+#define WM8994_HPOUT1L_MUTE_N_SHIFT 6 /* HPOUT1L_MUTE_N */
+#define WM8994_HPOUT1L_MUTE_N_WIDTH 1 /* HPOUT1L_MUTE_N */
+#define WM8994_HPOUT1L_VOL_6dB 0x003F
+#define WM8994_HPOUT1L_VOL_n10dB 0x002F
+#define WM8994_HPOUT1L_VOL_n26dB 0x001F
+#define WM8994_HPOUT1L_VOL_n42dB 0x000F
+#define WM8994_HPOUT1L_VOL_n57dB 0x0000
+#define WM8994_HPOUT1L_VOL_MASK 0x003F /* HPOUT1L_VOL - [5:0] */
+#define WM8994_HPOUT1L_VOL_SHIFT 0 /* HPOUT1L_VOL - [5:0] */
+#define WM8994_HPOUT1L_VOL_WIDTH 6 /* HPOUT1L_VOL - [5:0] */
+
+/*
+ * R29 (0x1D) - Right Output Volume
+ */
+#define WM8994_HPOUT1_VU 0x0100 /* HPOUT1_VU */
+#define WM8994_HPOUT1_VU_MASK 0x0100 /* HPOUT1_VU */
+#define WM8994_HPOUT1_VU_SHIFT 8 /* HPOUT1_VU */
+#define WM8994_HPOUT1_VU_WIDTH 1 /* HPOUT1_VU */
+#define WM8994_HPOUT1R_ZC 0x0080 /* HPOUT1R_ZC */
+#define WM8994_HPOUT1R_ZC_MASK 0x0080 /* HPOUT1R_ZC */
+#define WM8994_HPOUT1R_ZC_SHIFT 7 /* HPOUT1R_ZC */
+#define WM8994_HPOUT1R_ZC_WIDTH 1 /* HPOUT1R_ZC */
+#define WM8994_HPOUT1R_MUTE_N 0x0040 /* HPOUT1R_MUTE_N */
+#define WM8994_HPOUT1R_MUTE_N_MASK 0x0040 /* HPOUT1R_MUTE_N */
+#define WM8994_HPOUT1R_MUTE_N_SHIFT 6 /* HPOUT1R_MUTE_N */
+#define WM8994_HPOUT1R_MUTE_N_WIDTH 1 /* HPOUT1R_MUTE_N */
+#define WM8994_HPOUT1R_VOL_6dB 0x003F
+#define WM8994_HPOUT1R_VOL_n10dB 0x002F
+#define WM8994_HPOUT1R_VOL_n26dB 0x001F
+#define WM8994_HPOUT1R_VOL_n42dB 0x000F
+#define WM8994_HPOUT1R_VOL_n57dB 0x0000
+#define WM8994_HPOUT1R_VOL_MASK 0x003F /* HPOUT1R_VOL - [5:0] */
+#define WM8994_HPOUT1R_VOL_SHIFT 0 /* HPOUT1R_VOL - [5:0] */
+#define WM8994_HPOUT1R_VOL_WIDTH 6 /* HPOUT1R_VOL - [5:0] */
+
+/*
+ * R30 (0x1E) - Line Outputs Volume
+ */
+#define WM8994_LINEOUT1N_MUTE 0x0040 /* LINEOUT1N_MUTE */
+#define WM8994_LINEOUT1N_MUTE_MASK 0x0040 /* LINEOUT1N_MUTE */
+#define WM8994_LINEOUT1N_MUTE_SHIFT 6 /* LINEOUT1N_MUTE */
+#define WM8994_LINEOUT1N_MUTE_WIDTH 1 /* LINEOUT1N_MUTE */
+#define WM8994_LINEOUT1P_MUTE 0x0020 /* LINEOUT1P_MUTE */
+#define WM8994_LINEOUT1P_MUTE_MASK 0x0020 /* LINEOUT1P_MUTE */
+#define WM8994_LINEOUT1P_MUTE_SHIFT 5 /* LINEOUT1P_MUTE */
+#define WM8994_LINEOUT1P_MUTE_WIDTH 1 /* LINEOUT1P_MUTE */
+#define WM8994_LINEOUT1_VOL 0x0010 /* LINEOUT1_VOL */
+#define WM8994_LINEOUT1_VOL_MASK 0x0010 /* LINEOUT1_VOL */
+#define WM8994_LINEOUT1_VOL_SHIFT 4 /* LINEOUT1_VOL */
+#define WM8994_LINEOUT1_VOL_WIDTH 1 /* LINEOUT1_VOL */
+#define WM8994_LINEOUT2N_MUTE 0x0004 /* LINEOUT2N_MUTE */
+#define WM8994_LINEOUT2N_MUTE_MASK 0x0004 /* LINEOUT2N_MUTE */
+#define WM8994_LINEOUT2N_MUTE_SHIFT 2 /* LINEOUT2N_MUTE */
+#define WM8994_LINEOUT2N_MUTE_WIDTH 1 /* LINEOUT2N_MUTE */
+#define WM8994_LINEOUT2P_MUTE 0x0002 /* LINEOUT2P_MUTE */
+#define WM8994_LINEOUT2P_MUTE_MASK 0x0002 /* LINEOUT2P_MUTE */
+#define WM8994_LINEOUT2P_MUTE_SHIFT 1 /* LINEOUT2P_MUTE */
+#define WM8994_LINEOUT2P_MUTE_WIDTH 1 /* LINEOUT2P_MUTE */
+#define WM8994_LINEOUT2_VOL 0x0001 /* LINEOUT2_VOL */
+#define WM8994_LINEOUT2_VOL_MASK 0x0001 /* LINEOUT2_VOL */
+#define WM8994_LINEOUT2_VOL_SHIFT 0 /* LINEOUT2_VOL */
+#define WM8994_LINEOUT2_VOL_WIDTH 1 /* LINEOUT2_VOL */
+
+/*
+ * R31 (0x1F) - HPOUT2 Volume
+ */
+#define WM8994_HPOUT2_MUTE 0x0020 /* HPOUT2_MUTE */
+#define WM8994_HPOUT2_MUTE_MASK 0x0020 /* HPOUT2_MUTE */
+#define WM8994_HPOUT2_MUTE_SHIFT 5 /* HPOUT2_MUTE */
+#define WM8994_HPOUT2_MUTE_WIDTH 1 /* HPOUT2_MUTE */
+#define WM8994_HPOUT2_VOL 0x0010 /* HPOUT2_VOL */
+#define WM8994_HPOUT2_VOL_MASK 0x0010 /* HPOUT2_VOL */
+#define WM8994_HPOUT2_VOL_SHIFT 4 /* HPOUT2_VOL */
+#define WM8994_HPOUT2_VOL_WIDTH 1 /* HPOUT2_VOL */
+
+/*
+ * R32 (0x20) - Left OPGA Volume
+ */
+#define WM8994_MIXOUT_VU 0x0100 /* MIXOUT_VU */
+#define WM8994_MIXOUT_VU_MASK 0x0100 /* MIXOUT_VU */
+#define WM8994_MIXOUT_VU_SHIFT 8 /* MIXOUT_VU */
+#define WM8994_MIXOUT_VU_WIDTH 1 /* MIXOUT_VU */
+#define WM8994_MIXOUTL_ZC 0x0080 /* MIXOUTL_ZC */
+#define WM8994_MIXOUTL_ZC_MASK 0x0080 /* MIXOUTL_ZC */
+#define WM8994_MIXOUTL_ZC_SHIFT 7 /* MIXOUTL_ZC */
+#define WM8994_MIXOUTL_ZC_WIDTH 1 /* MIXOUTL_ZC */
+#define WM8994_MIXOUTL_MUTE_N 0x0040 /* MIXOUTL_MUTE_N */
+#define WM8994_MIXOUTL_MUTE_N_MASK 0x0040 /* MIXOUTL_MUTE_N */
+#define WM8994_MIXOUTL_MUTE_N_SHIFT 6 /* MIXOUTL_MUTE_N */
+#define WM8994_MIXOUTL_MUTE_N_WIDTH 1 /* MIXOUTL_MUTE_N */
+#define WM8994_MIXOUTL_VOL_MASK 0x003F /* MIXOUTL_VOL - [5:0] */
+#define WM8994_MIXOUTL_VOL_SHIFT 0 /* MIXOUTL_VOL - [5:0] */
+#define WM8994_MIXOUTL_VOL_WIDTH 6 /* MIXOUTL_VOL - [5:0] */
+
+/*
+ * R33 (0x21) - Right OPGA Volume
+ */
+#define WM8994_MIXOUT_VU 0x0100 /* MIXOUT_VU */
+#define WM8994_MIXOUT_VU_MASK 0x0100 /* MIXOUT_VU */
+#define WM8994_MIXOUT_VU_SHIFT 8 /* MIXOUT_VU */
+#define WM8994_MIXOUT_VU_WIDTH 1 /* MIXOUT_VU */
+#define WM8994_MIXOUTR_ZC 0x0080 /* MIXOUTR_ZC */
+#define WM8994_MIXOUTR_ZC_MASK 0x0080 /* MIXOUTR_ZC */
+#define WM8994_MIXOUTR_ZC_SHIFT 7 /* MIXOUTR_ZC */
+#define WM8994_MIXOUTR_ZC_WIDTH 1 /* MIXOUTR_ZC */
+#define WM8994_MIXOUTR_MUTE_N 0x0040 /* MIXOUTR_MUTE_N */
+#define WM8994_MIXOUTR_MUTE_N_MASK 0x0040 /* MIXOUTR_MUTE_N */
+#define WM8994_MIXOUTR_MUTE_N_SHIFT 6 /* MIXOUTR_MUTE_N */
+#define WM8994_MIXOUTR_MUTE_N_WIDTH 1 /* MIXOUTR_MUTE_N */
+#define WM8994_MIXOUTR_VOL_MASK 0x003F /* MIXOUTR_VOL - [5:0] */
+#define WM8994_MIXOUTR_VOL_SHIFT 0 /* MIXOUTR_VOL - [5:0] */
+#define WM8994_MIXOUTR_VOL_WIDTH 6 /* MIXOUTR_VOL - [5:0] */
+
+/*
+ * R34 (0x22) - SPKMIXL Attenuation
+ */
+#define WM8994_DAC2L_SPKMIXL_VOL 0x0040 /* DAC2L_SPKMIXL_VOL */
+#define WM8994_DAC2L_SPKMIXL_VOL_MASK 0x0040 /* DAC2L_SPKMIXL_VOL */
+#define WM8994_DAC2L_SPKMIXL_VOL_SHIFT 6 /* DAC2L_SPKMIXL_VOL */
+#define WM8994_DAC2L_SPKMIXL_VOL_WIDTH 1 /* DAC2L_SPKMIXL_VOL */
+#define WM8994_MIXINL_SPKMIXL_VOL 0x0020 /* MIXINL_SPKMIXL_VOL */
+#define WM8994_MIXINL_SPKMIXL_VOL_MASK 0x0020 /* MIXINL_SPKMIXL_VOL */
+#define WM8994_MIXINL_SPKMIXL_VOL_SHIFT 5 /* MIXINL_SPKMIXL_VOL */
+#define WM8994_MIXINL_SPKMIXL_VOL_WIDTH 1 /* MIXINL_SPKMIXL_VOL */
+#define WM8994_IN1LP_SPKMIXL_VOL 0x0010 /* IN1LP_SPKMIXL_VOL */
+#define WM8994_IN1LP_SPKMIXL_VOL_MASK 0x0010 /* IN1LP_SPKMIXL_VOL */
+#define WM8994_IN1LP_SPKMIXL_VOL_SHIFT 4 /* IN1LP_SPKMIXL_VOL */
+#define WM8994_IN1LP_SPKMIXL_VOL_WIDTH 1 /* IN1LP_SPKMIXL_VOL */
+#define WM8994_MIXOUTL_SPKMIXL_VOL 0x0008 /* MIXOUTL_SPKMIXL_VOL */
+#define WM8994_MIXOUTL_SPKMIXL_VOL_MASK 0x0008 /* MIXOUTL_SPKMIXL_VOL */
+#define WM8994_MIXOUTL_SPKMIXL_VOL_SHIFT 3 /* MIXOUTL_SPKMIXL_VOL */
+#define WM8994_MIXOUTL_SPKMIXL_VOL_WIDTH 1 /* MIXOUTL_SPKMIXL_VOL */
+#define WM8994_DAC1L_SPKMIXL_VOL 0x0004 /* DAC1L_SPKMIXL_VOL */
+#define WM8994_DAC1L_SPKMIXL_VOL_MASK 0x0004 /* DAC1L_SPKMIXL_VOL */
+#define WM8994_DAC1L_SPKMIXL_VOL_SHIFT 2 /* DAC1L_SPKMIXL_VOL */
+#define WM8994_DAC1L_SPKMIXL_VOL_WIDTH 1 /* DAC1L_SPKMIXL_VOL */
+#define WM8994_SPKMIXL_VOL_MASK 0x0003 /* SPKMIXL_VOL - [1:0] */
+#define WM8994_SPKMIXL_VOL_SHIFT 0 /* SPKMIXL_VOL - [1:0] */
+#define WM8994_SPKMIXL_VOL_WIDTH 2 /* SPKMIXL_VOL - [1:0] */
+
+/*
+ * R35 (0x23) - SPKMIXR Attenuation
+ */
+#define WM8994_SPKOUT_CLASSAB 0x0100 /* SPKOUT_CLASSAB */
+#define WM8994_SPKOUT_CLASSAB_MASK 0x0100 /* SPKOUT_CLASSAB */
+#define WM8994_SPKOUT_CLASSAB_SHIFT 8 /* SPKOUT_CLASSAB */
+#define WM8994_SPKOUT_CLASSAB_WIDTH 1 /* SPKOUT_CLASSAB */
+#define WM8994_DAC2R_SPKMIXR_VOL 0x0040 /* DAC2R_SPKMIXR_VOL */
+#define WM8994_DAC2R_SPKMIXR_VOL_MASK 0x0040 /* DAC2R_SPKMIXR_VOL */
+#define WM8994_DAC2R_SPKMIXR_VOL_SHIFT 6 /* DAC2R_SPKMIXR_VOL */
+#define WM8994_DAC2R_SPKMIXR_VOL_WIDTH 1 /* DAC2R_SPKMIXR_VOL */
+#define WM8994_MIXINR_SPKMIXR_VOL 0x0020 /* MIXINR_SPKMIXR_VOL */
+#define WM8994_MIXINR_SPKMIXR_VOL_MASK 0x0020 /* MIXINR_SPKMIXR_VOL */
+#define WM8994_MIXINR_SPKMIXR_VOL_SHIFT 5 /* MIXINR_SPKMIXR_VOL */
+#define WM8994_MIXINR_SPKMIXR_VOL_WIDTH 1 /* MIXINR_SPKMIXR_VOL */
+#define WM8994_IN1RP_SPKMIXR_VOL 0x0010 /* IN1RP_SPKMIXR_VOL */
+#define WM8994_IN1RP_SPKMIXR_VOL_MASK 0x0010 /* IN1RP_SPKMIXR_VOL */
+#define WM8994_IN1RP_SPKMIXR_VOL_SHIFT 4 /* IN1RP_SPKMIXR_VOL */
+#define WM8994_IN1RP_SPKMIXR_VOL_WIDTH 1 /* IN1RP_SPKMIXR_VOL */
+#define WM8994_MIXOUTR_SPKMIXR_VOL 0x0008 /* MIXOUTR_SPKMIXR_VOL */
+#define WM8994_MIXOUTR_SPKMIXR_VOL_MASK 0x0008 /* MIXOUTR_SPKMIXR_VOL */
+#define WM8994_MIXOUTR_SPKMIXR_VOL_SHIFT 3 /* MIXOUTR_SPKMIXR_VOL */
+#define WM8994_MIXOUTR_SPKMIXR_VOL_WIDTH 1 /* MIXOUTR_SPKMIXR_VOL */
+#define WM8994_DAC1R_SPKMIXR_VOL 0x0004 /* DAC1R_SPKMIXR_VOL */
+#define WM8994_DAC1R_SPKMIXR_VOL_MASK 0x0004 /* DAC1R_SPKMIXR_VOL */
+#define WM8994_DAC1R_SPKMIXR_VOL_SHIFT 2 /* DAC1R_SPKMIXR_VOL */
+#define WM8994_DAC1R_SPKMIXR_VOL_WIDTH 1 /* DAC1R_SPKMIXR_VOL */
+#define WM8994_SPKMIXR_VOL_MASK 0x0003 /* SPKMIXR_VOL - [1:0] */
+#define WM8994_SPKMIXR_VOL_SHIFT 0 /* SPKMIXR_VOL - [1:0] */
+#define WM8994_SPKMIXR_VOL_WIDTH 2 /* SPKMIXR_VOL - [1:0] */
+
+/*
+ * R36 (0x24) - SPKOUT Mixers
+ */
+#define WM8994_IN2LP_TO_SPKOUTL 0x0020 /* IN2LP_TO_SPKOUTL */
+#define WM8994_IN2LP_TO_SPKOUTL_MASK 0x0020 /* IN2LP_TO_SPKOUTL */
+#define WM8994_IN2LP_TO_SPKOUTL_SHIFT 5 /* IN2LP_TO_SPKOUTL */
+#define WM8994_IN2LP_TO_SPKOUTL_WIDTH 1 /* IN2LP_TO_SPKOUTL */
+#define WM8994_SPKMIXL_TO_SPKOUTL 0x0010 /* SPKMIXL_TO_SPKOUTL */
+#define WM8994_SPKMIXL_TO_SPKOUTL_MASK 0x0010 /* SPKMIXL_TO_SPKOUTL */
+#define WM8994_SPKMIXL_TO_SPKOUTL_SHIFT 4 /* SPKMIXL_TO_SPKOUTL */
+#define WM8994_SPKMIXL_TO_SPKOUTL_WIDTH 1 /* SPKMIXL_TO_SPKOUTL */
+#define WM8994_SPKMIXR_TO_SPKOUTL 0x0008 /* SPKMIXR_TO_SPKOUTL */
+#define WM8994_SPKMIXR_TO_SPKOUTL_MASK 0x0008 /* SPKMIXR_TO_SPKOUTL */
+#define WM8994_SPKMIXR_TO_SPKOUTL_SHIFT 3 /* SPKMIXR_TO_SPKOUTL */
+#define WM8994_SPKMIXR_TO_SPKOUTL_WIDTH 1 /* SPKMIXR_TO_SPKOUTL */
+#define WM8994_IN2LP_TO_SPKOUTR 0x0004 /* IN2LP_TO_SPKOUTR */
+#define WM8994_IN2LP_TO_SPKOUTR_MASK 0x0004 /* IN2LP_TO_SPKOUTR */
+#define WM8994_IN2LP_TO_SPKOUTR_SHIFT 2 /* IN2LP_TO_SPKOUTR */
+#define WM8994_IN2LP_TO_SPKOUTR_WIDTH 1 /* IN2LP_TO_SPKOUTR */
+#define WM8994_SPKMIXL_TO_SPKOUTR 0x0002 /* SPKMIXL_TO_SPKOUTR */
+#define WM8994_SPKMIXL_TO_SPKOUTR_MASK 0x0002 /* SPKMIXL_TO_SPKOUTR */
+#define WM8994_SPKMIXL_TO_SPKOUTR_SHIFT 1 /* SPKMIXL_TO_SPKOUTR */
+#define WM8994_SPKMIXL_TO_SPKOUTR_WIDTH 1 /* SPKMIXL_TO_SPKOUTR */
+#define WM8994_SPKMIXR_TO_SPKOUTR 0x0001 /* SPKMIXR_TO_SPKOUTR */
+#define WM8994_SPKMIXR_TO_SPKOUTR_MASK 0x0001 /* SPKMIXR_TO_SPKOUTR */
+#define WM8994_SPKMIXR_TO_SPKOUTR_SHIFT 0 /* SPKMIXR_TO_SPKOUTR */
+#define WM8994_SPKMIXR_TO_SPKOUTR_WIDTH 1 /* SPKMIXR_TO_SPKOUTR */
+
+/*
+ * R37 (0x25) - ClassD
+ */
+#define WM8994_CLASSD_DEFAULT 0x0140 /* Default Setting - [8:6] */
+#define WM8994_SPKOUTL_BOOST_MASK 0x0038 /* SPKOUTL_BOOST - [5:3] */
+#define WM8994_SPKOUTL_BOOST_SHIFT 3 /* SPKOUTL_BOOST - [5:3] */
+#define WM8994_SPKOUTL_BOOST_WIDTH 3 /* SPKOUTL_BOOST - [5:3] */
+#define WM8994_SPKOUTR_BOOST_MASK 0x0007 /* SPKOUTR_BOOST - [2:0] */
+#define WM8994_SPKOUTR_BOOST_SHIFT 0 /* SPKOUTR_BOOST - [2:0] */
+#define WM8994_SPKOUTR_BOOST_WIDTH 3 /* SPKOUTR_BOOST - [2:0] */
+
+/*
+ * R38 (0x26) - Speaker Volume Left
+ */
+#define WM8994_SPKOUT_VU 0x0100 /* SPKOUT_VU */
+#define WM8994_SPKOUT_VU_MASK 0x0100 /* SPKOUT_VU */
+#define WM8994_SPKOUT_VU_SHIFT 8 /* SPKOUT_VU */
+#define WM8994_SPKOUT_VU_WIDTH 1 /* SPKOUT_VU */
+#define WM8994_SPKOUTL_ZC 0x0080 /* SPKOUTL_ZC */
+#define WM8994_SPKOUTL_ZC_MASK 0x0080 /* SPKOUTL_ZC */
+#define WM8994_SPKOUTL_ZC_SHIFT 7 /* SPKOUTL_ZC */
+#define WM8994_SPKOUTL_ZC_WIDTH 1 /* SPKOUTL_ZC */
+#define WM8994_SPKOUTL_MUTE_N 0x0040 /* SPKOUTL_MUTE_N */
+#define WM8994_SPKOUTL_MUTE_N_MASK 0x0040 /* SPKOUTL_MUTE_N */
+#define WM8994_SPKOUTL_MUTE_N_SHIFT 6 /* SPKOUTL_MUTE_N */
+#define WM8994_SPKOUTL_MUTE_N_WIDTH 1 /* SPKOUTL_MUTE_N */
+#define WM8994_SPKOUTL_VOL_MASK 0x003F /* SPKOUTL_VOL - [5:0] */
+#define WM8994_SPKOUTL_VOL_SHIFT 0 /* SPKOUTL_VOL - [5:0] */
+#define WM8994_SPKOUTL_VOL_WIDTH 6 /* SPKOUTL_VOL - [5:0] */
+
+/*
+ * R39 (0x27) - Speaker Volume Right
+ */
+#define WM8994_SPKOUT_VU 0x0100 /* SPKOUT_VU */
+#define WM8994_SPKOUT_VU_MASK 0x0100 /* SPKOUT_VU */
+#define WM8994_SPKOUT_VU_SHIFT 8 /* SPKOUT_VU */
+#define WM8994_SPKOUT_VU_WIDTH 1 /* SPKOUT_VU */
+#define WM8994_SPKOUTR_ZC 0x0080 /* SPKOUTR_ZC */
+#define WM8994_SPKOUTR_ZC_MASK 0x0080 /* SPKOUTR_ZC */
+#define WM8994_SPKOUTR_ZC_SHIFT 7 /* SPKOUTR_ZC */
+#define WM8994_SPKOUTR_ZC_WIDTH 1 /* SPKOUTR_ZC */
+#define WM8994_SPKOUTR_MUTE_N 0x0040 /* SPKOUTR_MUTE_N */
+#define WM8994_SPKOUTR_MUTE_N_MASK 0x0040 /* SPKOUTR_MUTE_N */
+#define WM8994_SPKOUTR_MUTE_N_SHIFT 6 /* SPKOUTR_MUTE_N */
+#define WM8994_SPKOUTR_MUTE_N_WIDTH 1 /* SPKOUTR_MUTE_N */
+#define WM8994_SPKOUTR_VOL_MASK 0x003F /* SPKOUTR_VOL - [5:0] */
+#define WM8994_SPKOUTR_VOL_SHIFT 0 /* SPKOUTR_VOL - [5:0] */
+#define WM8994_SPKOUTR_VOL_WIDTH 6 /* SPKOUTR_VOL - [5:0] */
+
+/*
+ * R40 (0x28) - Input Mixer (2)
+ */
+#define WM8994_IN2LP_TO_IN2L 0x0080 /* IN2LP_TO_IN2L */
+#define WM8994_IN2LP_TO_IN2L_MASK 0x0080 /* IN2LP_TO_IN2L */
+#define WM8994_IN2LP_TO_IN2L_SHIFT 7 /* IN2LP_TO_IN2L */
+#define WM8994_IN2LP_TO_IN2L_WIDTH 1 /* IN2LP_TO_IN2L */
+#define WM8994_IN2LN_TO_IN2L 0x0040 /* IN2LN_TO_IN2L */
+#define WM8994_IN2LN_TO_IN2L_MASK 0x0040 /* IN2LN_TO_IN2L */
+#define WM8994_IN2LN_TO_IN2L_SHIFT 6 /* IN2LN_TO_IN2L */
+#define WM8994_IN2LN_TO_IN2L_WIDTH 1 /* IN2LN_TO_IN2L */
+#define WM8994_IN1LP_TO_IN1L 0x0020 /* IN1LP_TO_IN1L */
+#define WM8994_IN1LP_TO_IN1L_MASK 0x0020 /* IN1LP_TO_IN1L */
+#define WM8994_IN1LP_TO_IN1L_SHIFT 5 /* IN1LP_TO_IN1L */
+#define WM8994_IN1LP_TO_IN1L_WIDTH 1 /* IN1LP_TO_IN1L */
+#define WM8994_IN1LN_TO_IN1L 0x0010 /* IN1LN_TO_IN1L */
+#define WM8994_IN1LN_TO_IN1L_MASK 0x0010 /* IN1LN_TO_IN1L */
+#define WM8994_IN1LN_TO_IN1L_SHIFT 4 /* IN1LN_TO_IN1L */
+#define WM8994_IN1LN_TO_IN1L_WIDTH 1 /* IN1LN_TO_IN1L */
+#define WM8994_IN2RP_TO_IN2R 0x0008 /* IN2RP_TO_IN2R */
+#define WM8994_IN2RP_TO_IN2R_MASK 0x0008 /* IN2RP_TO_IN2R */
+#define WM8994_IN2RP_TO_IN2R_SHIFT 3 /* IN2RP_TO_IN2R */
+#define WM8994_IN2RP_TO_IN2R_WIDTH 1 /* IN2RP_TO_IN2R */
+#define WM8994_IN2RN_TO_IN2R 0x0004 /* IN2RN_TO_IN2R */
+#define WM8994_IN2RN_TO_IN2R_MASK 0x0004 /* IN2RN_TO_IN2R */
+#define WM8994_IN2RN_TO_IN2R_SHIFT 2 /* IN2RN_TO_IN2R */
+#define WM8994_IN2RN_TO_IN2R_WIDTH 1 /* IN2RN_TO_IN2R */
+#define WM8994_IN1RP_TO_IN1R 0x0002 /* IN1RP_TO_IN1R */
+#define WM8994_IN1RP_TO_IN1R_MASK 0x0002 /* IN1RP_TO_IN1R */
+#define WM8994_IN1RP_TO_IN1R_SHIFT 1 /* IN1RP_TO_IN1R */
+#define WM8994_IN1RP_TO_IN1R_WIDTH 1 /* IN1RP_TO_IN1R */
+#define WM8994_IN1RN_TO_IN1R 0x0001 /* IN1RN_TO_IN1R */
+#define WM8994_IN1RN_TO_IN1R_MASK 0x0001 /* IN1RN_TO_IN1R */
+#define WM8994_IN1RN_TO_IN1R_SHIFT 0 /* IN1RN_TO_IN1R */
+#define WM8994_IN1RN_TO_IN1R_WIDTH 1 /* IN1RN_TO_IN1R */
+
+/*
+ * R41 (0x29) - Input Mixer (3)
+ */
+#define WM8994_IN2L_TO_MIXINL 0x0100 /* IN2L_TO_MIXINL */
+#define WM8994_IN2L_TO_MIXINL_MASK 0x0100 /* IN2L_TO_MIXINL */
+#define WM8994_IN2L_TO_MIXINL_SHIFT 8 /* IN2L_TO_MIXINL */
+#define WM8994_IN2L_TO_MIXINL_WIDTH 1 /* IN2L_TO_MIXINL */
+#define WM8994_IN2L_MIXINL_VOL 0x0080 /* IN2L_MIXINL_VOL */
+#define WM8994_IN2L_MIXINL_VOL_MASK 0x0080 /* IN2L_MIXINL_VOL */
+#define WM8994_IN2L_MIXINL_VOL_SHIFT 7 /* IN2L_MIXINL_VOL */
+#define WM8994_IN2L_MIXINL_VOL_WIDTH 1 /* IN2L_MIXINL_VOL */
+#define WM8994_IN1L_TO_MIXINL 0x0020 /* IN1L_TO_MIXINL */
+#define WM8994_IN1L_TO_MIXINL_MASK 0x0020 /* IN1L_TO_MIXINL */
+#define WM8994_IN1L_TO_MIXINL_SHIFT 5 /* IN1L_TO_MIXINL */
+#define WM8994_IN1L_TO_MIXINL_WIDTH 1 /* IN1L_TO_MIXINL */
+#define WM8994_IN1L_MIXINL_VOL 0x0010 /* IN1L_MIXINL_VOL */
+#define WM8994_IN1L_MIXINL_VOL_MASK 0x0010 /* IN1L_MIXINL_VOL */
+#define WM8994_IN1L_MIXINL_VOL_SHIFT 4 /* IN1L_MIXINL_VOL */
+#define WM8994_IN1L_MIXINL_VOL_WIDTH 1 /* IN1L_MIXINL_VOL */
+#define WM8994_MIXOUTL_MIXINL_VOL_MASK 0x0007 /* MIXOUTL_MIXINL_VOL - [2:0] */
+#define WM8994_MIXOUTL_MIXINL_VOL_SHIFT 0 /* MIXOUTL_MIXINL_VOL - [2:0] */
+#define WM8994_MIXOUTL_MIXINL_VOL_WIDTH 3 /* MIXOUTL_MIXINL_VOL - [2:0] */
+
+/*
+ * R42 (0x2A) - Input Mixer (4)
+ */
+#define WM8994_IN2R_TO_MIXINR 0x0100 /* IN2R_TO_MIXINR */
+#define WM8994_IN2R_TO_MIXINR_MASK 0x0100 /* IN2R_TO_MIXINR */
+#define WM8994_IN2R_TO_MIXINR_SHIFT 8 /* IN2R_TO_MIXINR */
+#define WM8994_IN2R_TO_MIXINR_WIDTH 1 /* IN2R_TO_MIXINR */
+#define WM8994_IN2R_MIXINR_VOL 0x0080 /* IN2R_MIXINR_VOL */
+#define WM8994_IN2R_MIXINR_VOL_MASK 0x0080 /* IN2R_MIXINR_VOL */
+#define WM8994_IN2R_MIXINR_VOL_SHIFT 7 /* IN2R_MIXINR_VOL */
+#define WM8994_IN2R_MIXINR_VOL_WIDTH 1 /* IN2R_MIXINR_VOL */
+#define WM8994_IN1R_TO_MIXINR 0x0020 /* IN1R_TO_MIXINR */
+#define WM8994_IN1R_TO_MIXINR_MASK 0x0020 /* IN1R_TO_MIXINR */
+#define WM8994_IN1R_TO_MIXINR_SHIFT 5 /* IN1R_TO_MIXINR */
+#define WM8994_IN1R_TO_MIXINR_WIDTH 1 /* IN1R_TO_MIXINR */
+#define WM8994_IN1R_MIXINR_VOL 0x0010 /* IN1R_MIXINR_VOL */
+#define WM8994_IN1R_MIXINR_VOL_MASK 0x0010 /* IN1R_MIXINR_VOL */
+#define WM8994_IN1R_MIXINR_VOL_SHIFT 4 /* IN1R_MIXINR_VOL */
+#define WM8994_IN1R_MIXINR_VOL_WIDTH 1 /* IN1R_MIXINR_VOL */
+#define WM8994_MIXOUTR_MIXINR_VOL_MASK 0x0007 /* MIXOUTR_MIXINR_VOL - [2:0] */
+#define WM8994_MIXOUTR_MIXINR_VOL_SHIFT 0 /* MIXOUTR_MIXINR_VOL - [2:0] */
+#define WM8994_MIXOUTR_MIXINR_VOL_WIDTH 3 /* MIXOUTR_MIXINR_VOL - [2:0] */
+
+/*
+ * R43 (0x2B) - Input Mixer (5)
+ */
+#define WM8994_IN1LP_MIXINL_VOL_MASK 0x01C0 /* IN1LP_MIXINL_VOL - [8:6] */
+#define WM8994_IN1LP_MIXINL_VOL_SHIFT 6 /* IN1LP_MIXINL_VOL - [8:6] */
+#define WM8994_IN1LP_MIXINL_VOL_WIDTH 3 /* IN1LP_MIXINL_VOL - [8:6] */
+#define WM8994_IN2LP_MIXINL_VOL_MASK 0x0007 /* IN2LP_MIXINL_VOL - [2:0] */
+#define WM8994_IN2LP_MIXINL_VOL_SHIFT 0 /* IN2LP_MIXINL_VOL - [2:0] */
+#define WM8994_IN2LP_MIXINL_VOL_WIDTH 3 /* IN2LP_MIXINL_VOL - [2:0] */
+
+/*
+ * R44 (0x2C) - Input Mixer (6)
+ */
+#define WM8994_IN1RP_MIXINR_VOL_MASK 0x01C0 /* IN1RP_MIXINR_VOL - [8:6] */
+#define WM8994_IN1RP_MIXINR_VOL_SHIFT 6 /* IN1RP_MIXINR_VOL - [8:6] */
+#define WM8994_IN1RP_MIXINR_VOL_WIDTH 3 /* IN1RP_MIXINR_VOL - [8:6] */
+#define WM8994_IN2LP_MIXINR_VOL_MASK 0x0007 /* IN2LP_MIXINR_VOL - [2:0] */
+#define WM8994_IN2LP_MIXINR_VOL_SHIFT 0 /* IN2LP_MIXINR_VOL - [2:0] */
+#define WM8994_IN2LP_MIXINR_VOL_WIDTH 3 /* IN2LP_MIXINR_VOL - [2:0] */
+
+/*
+ * R45 (0x2D) - Output Mixer (1)
+ */
+#define WM8994_DAC1L_TO_HPOUT1L 0x0100 /* DAC1L_TO_HPOUT1L */
+#define WM8994_DAC1L_TO_HPOUT1L_MASK 0x0100 /* DAC1L_TO_HPOUT1L */
+#define WM8994_DAC1L_TO_HPOUT1L_SHIFT 8 /* DAC1L_TO_HPOUT1L */
+#define WM8994_DAC1L_TO_HPOUT1L_WIDTH 1 /* DAC1L_TO_HPOUT1L */
+#define WM8994_MIXINR_TO_MIXOUTL 0x0080 /* MIXINR_TO_MIXOUTL */
+#define WM8994_MIXINR_TO_MIXOUTL_MASK 0x0080 /* MIXINR_TO_MIXOUTL */
+#define WM8994_MIXINR_TO_MIXOUTL_SHIFT 7 /* MIXINR_TO_MIXOUTL */
+#define WM8994_MIXINR_TO_MIXOUTL_WIDTH 1 /* MIXINR_TO_MIXOUTL */
+#define WM8994_MIXINL_TO_MIXOUTL 0x0040 /* MIXINL_TO_MIXOUTL */
+#define WM8994_MIXINL_TO_MIXOUTL_MASK 0x0040 /* MIXINL_TO_MIXOUTL */
+#define WM8994_MIXINL_TO_MIXOUTL_SHIFT 6 /* MIXINL_TO_MIXOUTL */
+#define WM8994_MIXINL_TO_MIXOUTL_WIDTH 1 /* MIXINL_TO_MIXOUTL */
+#define WM8994_IN2RN_TO_MIXOUTL 0x0020 /* IN2RN_TO_MIXOUTL */
+#define WM8994_IN2RN_TO_MIXOUTL_MASK 0x0020 /* IN2RN_TO_MIXOUTL */
+#define WM8994_IN2RN_TO_MIXOUTL_SHIFT 5 /* IN2RN_TO_MIXOUTL */
+#define WM8994_IN2RN_TO_MIXOUTL_WIDTH 1 /* IN2RN_TO_MIXOUTL */
+#define WM8994_IN2LN_TO_MIXOUTL 0x0010 /* IN2LN_TO_MIXOUTL */
+#define WM8994_IN2LN_TO_MIXOUTL_MASK 0x0010 /* IN2LN_TO_MIXOUTL */
+#define WM8994_IN2LN_TO_MIXOUTL_SHIFT 4 /* IN2LN_TO_MIXOUTL */
+#define WM8994_IN2LN_TO_MIXOUTL_WIDTH 1 /* IN2LN_TO_MIXOUTL */
+#define WM8994_IN1R_TO_MIXOUTL 0x0008 /* IN1R_TO_MIXOUTL */
+#define WM8994_IN1R_TO_MIXOUTL_MASK 0x0008 /* IN1R_TO_MIXOUTL */
+#define WM8994_IN1R_TO_MIXOUTL_SHIFT 3 /* IN1R_TO_MIXOUTL */
+#define WM8994_IN1R_TO_MIXOUTL_WIDTH 1 /* IN1R_TO_MIXOUTL */
+#define WM8994_IN1L_TO_MIXOUTL 0x0004 /* IN1L_TO_MIXOUTL */
+#define WM8994_IN1L_TO_MIXOUTL_MASK 0x0004 /* IN1L_TO_MIXOUTL */
+#define WM8994_IN1L_TO_MIXOUTL_SHIFT 2 /* IN1L_TO_MIXOUTL */
+#define WM8994_IN1L_TO_MIXOUTL_WIDTH 1 /* IN1L_TO_MIXOUTL */
+#define WM8994_IN2LP_TO_MIXOUTL 0x0002 /* IN2LP_TO_MIXOUTL */
+#define WM8994_IN2LP_TO_MIXOUTL_MASK 0x0002 /* IN2LP_TO_MIXOUTL */
+#define WM8994_IN2LP_TO_MIXOUTL_SHIFT 1 /* IN2LP_TO_MIXOUTL */
+#define WM8994_IN2LP_TO_MIXOUTL_WIDTH 1 /* IN2LP_TO_MIXOUTL */
+#define WM8994_DAC1L_TO_MIXOUTL 0x0001 /* DAC1L_TO_MIXOUTL */
+#define WM8994_DAC1L_TO_MIXOUTL_MASK 0x0001 /* DAC1L_TO_MIXOUTL */
+#define WM8994_DAC1L_TO_MIXOUTL_SHIFT 0 /* DAC1L_TO_MIXOUTL */
+#define WM8994_DAC1L_TO_MIXOUTL_WIDTH 1 /* DAC1L_TO_MIXOUTL */
+
+/*
+ * R46 (0x2E) - Output Mixer (2)
+ */
+#define WM8994_DAC1R_TO_HPOUT1R 0x0100 /* DAC1R_TO_HPOUT1R */
+#define WM8994_DAC1R_TO_HPOUT1R_MASK 0x0100 /* DAC1R_TO_HPOUT1R */
+#define WM8994_DAC1R_TO_HPOUT1R_SHIFT 8 /* DAC1R_TO_HPOUT1R */
+#define WM8994_DAC1R_TO_HPOUT1R_WIDTH 1 /* DAC1R_TO_HPOUT1R */
+#define WM8994_MIXINL_TO_MIXOUTR 0x0080 /* MIXINL_TO_MIXOUTR */
+#define WM8994_MIXINL_TO_MIXOUTR_MASK 0x0080 /* MIXINL_TO_MIXOUTR */
+#define WM8994_MIXINL_TO_MIXOUTR_SHIFT 7 /* MIXINL_TO_MIXOUTR */
+#define WM8994_MIXINL_TO_MIXOUTR_WIDTH 1 /* MIXINL_TO_MIXOUTR */
+#define WM8994_MIXINR_TO_MIXOUTR 0x0040 /* MIXINR_TO_MIXOUTR */
+#define WM8994_MIXINR_TO_MIXOUTR_MASK 0x0040 /* MIXINR_TO_MIXOUTR */
+#define WM8994_MIXINR_TO_MIXOUTR_SHIFT 6 /* MIXINR_TO_MIXOUTR */
+#define WM8994_MIXINR_TO_MIXOUTR_WIDTH 1 /* MIXINR_TO_MIXOUTR */
+#define WM8994_IN2LN_TO_MIXOUTR 0x0020 /* IN2LN_TO_MIXOUTR */
+#define WM8994_IN2LN_TO_MIXOUTR_MASK 0x0020 /* IN2LN_TO_MIXOUTR */
+#define WM8994_IN2LN_TO_MIXOUTR_SHIFT 5 /* IN2LN_TO_MIXOUTR */
+#define WM8994_IN2LN_TO_MIXOUTR_WIDTH 1 /* IN2LN_TO_MIXOUTR */
+#define WM8994_IN2RN_TO_MIXOUTR 0x0010 /* IN2RN_TO_MIXOUTR */
+#define WM8994_IN2RN_TO_MIXOUTR_MASK 0x0010 /* IN2RN_TO_MIXOUTR */
+#define WM8994_IN2RN_TO_MIXOUTR_SHIFT 4 /* IN2RN_TO_MIXOUTR */
+#define WM8994_IN2RN_TO_MIXOUTR_WIDTH 1 /* IN2RN_TO_MIXOUTR */
+#define WM8994_IN1L_TO_MIXOUTR 0x0008 /* IN1L_TO_MIXOUTR */
+#define WM8994_IN1L_TO_MIXOUTR_MASK 0x0008 /* IN1L_TO_MIXOUTR */
+#define WM8994_IN1L_TO_MIXOUTR_SHIFT 3 /* IN1L_TO_MIXOUTR */
+#define WM8994_IN1L_TO_MIXOUTR_WIDTH 1 /* IN1L_TO_MIXOUTR */
+#define WM8994_IN1R_TO_MIXOUTR 0x0004 /* IN1R_TO_MIXOUTR */
+#define WM8994_IN1R_TO_MIXOUTR_MASK 0x0004 /* IN1R_TO_MIXOUTR */
+#define WM8994_IN1R_TO_MIXOUTR_SHIFT 2 /* IN1R_TO_MIXOUTR */
+#define WM8994_IN1R_TO_MIXOUTR_WIDTH 1 /* IN1R_TO_MIXOUTR */
+#define WM8994_IN2RP_TO_MIXOUTR 0x0002 /* IN2RP_TO_MIXOUTR */
+#define WM8994_IN2RP_TO_MIXOUTR_MASK 0x0002 /* IN2RP_TO_MIXOUTR */
+#define WM8994_IN2RP_TO_MIXOUTR_SHIFT 1 /* IN2RP_TO_MIXOUTR */
+#define WM8994_IN2RP_TO_MIXOUTR_WIDTH 1 /* IN2RP_TO_MIXOUTR */
+#define WM8994_DAC1R_TO_MIXOUTR 0x0001 /* DAC1R_TO_MIXOUTR */
+#define WM8994_DAC1R_TO_MIXOUTR_MASK 0x0001 /* DAC1R_TO_MIXOUTR */
+#define WM8994_DAC1R_TO_MIXOUTR_SHIFT 0 /* DAC1R_TO_MIXOUTR */
+#define WM8994_DAC1R_TO_MIXOUTR_WIDTH 1 /* DAC1R_TO_MIXOUTR */
+
+/*
+ * R47 (0x2F) - Output Mixer (3)
+ */
+#define WM8994_IN2LP_MIXOUTL_VOL_MASK 0x0E00 /* IN2LP_MIXOUTL_VOL - [11:9] */
+#define WM8994_IN2LP_MIXOUTL_VOL_SHIFT 9 /* IN2LP_MIXOUTL_VOL - [11:9] */
+#define WM8994_IN2LP_MIXOUTL_VOL_WIDTH 3 /* IN2LP_MIXOUTL_VOL - [11:9] */
+#define WM8994_IN2LN_MIXOUTL_VOL_MASK 0x01C0 /* IN2LN_MIXOUTL_VOL - [8:6] */
+#define WM8994_IN2LN_MIXOUTL_VOL_SHIFT 6 /* IN2LN_MIXOUTL_VOL - [8:6] */
+#define WM8994_IN2LN_MIXOUTL_VOL_WIDTH 3 /* IN2LN_MIXOUTL_VOL - [8:6] */
+#define WM8994_IN1R_MIXOUTL_VOL_MASK 0x0038 /* IN1R_MIXOUTL_VOL - [5:3] */
+#define WM8994_IN1R_MIXOUTL_VOL_SHIFT 3 /* IN1R_MIXOUTL_VOL - [5:3] */
+#define WM8994_IN1R_MIXOUTL_VOL_WIDTH 3 /* IN1R_MIXOUTL_VOL - [5:3] */
+#define WM8994_IN1L_MIXOUTL_VOL_MASK 0x0007 /* IN1L_MIXOUTL_VOL - [2:0] */
+#define WM8994_IN1L_MIXOUTL_VOL_SHIFT 0 /* IN1L_MIXOUTL_VOL - [2:0] */
+#define WM8994_IN1L_MIXOUTL_VOL_WIDTH 3 /* IN1L_MIXOUTL_VOL - [2:0] */
+
+/*
+ * R48 (0x30) - Output Mixer (4)
+ */
+#define WM8994_IN2RP_MIXOUTR_VOL_MASK 0x0E00 /* IN2RP_MIXOUTR_VOL - [11:9] */
+#define WM8994_IN2RP_MIXOUTR_VOL_SHIFT 9 /* IN2RP_MIXOUTR_VOL - [11:9] */
+#define WM8994_IN2RP_MIXOUTR_VOL_WIDTH 3 /* IN2RP_MIXOUTR_VOL - [11:9] */
+#define WM8994_IN2RN_MIXOUTR_VOL_MASK 0x01C0 /* IN2RN_MIXOUTR_VOL - [8:6] */
+#define WM8994_IN2RN_MIXOUTR_VOL_SHIFT 6 /* IN2RN_MIXOUTR_VOL - [8:6] */
+#define WM8994_IN2RN_MIXOUTR_VOL_WIDTH 3 /* IN2RN_MIXOUTR_VOL - [8:6] */
+#define WM8994_IN1L_MIXOUTR_VOL_MASK 0x0038 /* IN1L_MIXOUTR_VOL - [5:3] */
+#define WM8994_IN1L_MIXOUTR_VOL_SHIFT 3 /* IN1L_MIXOUTR_VOL - [5:3] */
+#define WM8994_IN1L_MIXOUTR_VOL_WIDTH 3 /* IN1L_MIXOUTR_VOL - [5:3] */
+#define WM8994_IN1R_MIXOUTR_VOL_MASK 0x0007 /* IN1R_MIXOUTR_VOL - [2:0] */
+#define WM8994_IN1R_MIXOUTR_VOL_SHIFT 0 /* IN1R_MIXOUTR_VOL - [2:0] */
+#define WM8994_IN1R_MIXOUTR_VOL_WIDTH 3 /* IN1R_MIXOUTR_VOL - [2:0] */
+
+/*
+ * R49 (0x31) - Output Mixer (5)
+ */
+#define WM8994_DACL_MIXOUTL_VOL_MASK 0x0E00 /* DACL_MIXOUTL_VOL - [11:9] */
+#define WM8994_DACL_MIXOUTL_VOL_SHIFT 9 /* DACL_MIXOUTL_VOL - [11:9] */
+#define WM8994_DACL_MIXOUTL_VOL_WIDTH 3 /* DACL_MIXOUTL_VOL - [11:9] */
+#define WM8994_IN2RN_MIXOUTL_VOL_MASK 0x01C0 /* IN2RN_MIXOUTL_VOL - [8:6] */
+#define WM8994_IN2RN_MIXOUTL_VOL_SHIFT 6 /* IN2RN_MIXOUTL_VOL - [8:6] */
+#define WM8994_IN2RN_MIXOUTL_VOL_WIDTH 3 /* IN2RN_MIXOUTL_VOL - [8:6] */
+#define WM8994_MIXINR_MIXOUTL_VOL_MASK 0x0038 /* MIXINR_MIXOUTL_VOL - [5:3] */
+#define WM8994_MIXINR_MIXOUTL_VOL_SHIFT 3 /* MIXINR_MIXOUTL_VOL - [5:3] */
+#define WM8994_MIXINR_MIXOUTL_VOL_WIDTH 3 /* MIXINR_MIXOUTL_VOL - [5:3] */
+#define WM8994_MIXINL_MIXOUTL_VOL_MASK 0x0007 /* MIXINL_MIXOUTL_VOL - [2:0] */
+#define WM8994_MIXINL_MIXOUTL_VOL_SHIFT 0 /* MIXINL_MIXOUTL_VOL - [2:0] */
+#define WM8994_MIXINL_MIXOUTL_VOL_WIDTH 3 /* MIXINL_MIXOUTL_VOL - [2:0] */
+
+/*
+ * R50 (0x32) - Output Mixer (6)
+ */
+#define WM8994_DACR_MIXOUTR_VOL_MASK 0x0E00 /* DACR_MIXOUTR_VOL - [11:9] */
+#define WM8994_DACR_MIXOUTR_VOL_SHIFT 9 /* DACR_MIXOUTR_VOL - [11:9] */
+#define WM8994_DACR_MIXOUTR_VOL_WIDTH 3 /* DACR_MIXOUTR_VOL - [11:9] */
+#define WM8994_IN2LN_MIXOUTR_VOL_MASK 0x01C0 /* IN2LN_MIXOUTR_VOL - [8:6] */
+#define WM8994_IN2LN_MIXOUTR_VOL_SHIFT 6 /* IN2LN_MIXOUTR_VOL - [8:6] */
+#define WM8994_IN2LN_MIXOUTR_VOL_WIDTH 3 /* IN2LN_MIXOUTR_VOL - [8:6] */
+#define WM8994_MIXINL_MIXOUTR_VOL_MASK 0x0038 /* MIXINL_MIXOUTR_VOL - [5:3] */
+#define WM8994_MIXINL_MIXOUTR_VOL_SHIFT 3 /* MIXINL_MIXOUTR_VOL - [5:3] */
+#define WM8994_MIXINL_MIXOUTR_VOL_WIDTH 3 /* MIXINL_MIXOUTR_VOL - [5:3] */
+#define WM8994_MIXINR_MIXOUTR_VOL_MASK 0x0007 /* MIXINR_MIXOUTR_VOL - [2:0] */
+#define WM8994_MIXINR_MIXOUTR_VOL_SHIFT 0 /* MIXINR_MIXOUTR_VOL - [2:0] */
+#define WM8994_MIXINR_MIXOUTR_VOL_WIDTH 3 /* MIXINR_MIXOUTR_VOL - [2:0] */
+
+/*
+ * R51 (0x33) - HPOUT2 Mixer
+ */
+#define WM8994_IN2LRP_TO_HPOUT2 0x0020 /* IN2LRP_TO_HPOUT2 */
+#define WM8994_IN2LRP_TO_HPOUT2_MASK 0x0020 /* IN2LRP_TO_HPOUT2 */
+#define WM8994_IN2LRP_TO_HPOUT2_SHIFT 5 /* IN2LRP_TO_HPOUT2 */
+#define WM8994_IN2LRP_TO_HPOUT2_WIDTH 1 /* IN2LRP_TO_HPOUT2 */
+#define WM8994_MIXOUTLVOL_TO_HPOUT2 0x0010 /* MIXOUTLVOL_TO_HPOUT2 */
+#define WM8994_MIXOUTLVOL_TO_HPOUT2_MASK 0x0010 /* MIXOUTLVOL_TO_HPOUT2 */
+#define WM8994_MIXOUTLVOL_TO_HPOUT2_SHIFT 4 /* MIXOUTLVOL_TO_HPOUT2 */
+#define WM8994_MIXOUTLVOL_TO_HPOUT2_WIDTH 1 /* MIXOUTLVOL_TO_HPOUT2 */
+#define WM8994_MIXOUTRVOL_TO_HPOUT2 0x0008 /* MIXOUTRVOL_TO_HPOUT2 */
+#define WM8994_MIXOUTRVOL_TO_HPOUT2_MASK 0x0008 /* MIXOUTRVOL_TO_HPOUT2 */
+#define WM8994_MIXOUTRVOL_TO_HPOUT2_SHIFT 3 /* MIXOUTRVOL_TO_HPOUT2 */
+#define WM8994_MIXOUTRVOL_TO_HPOUT2_WIDTH 1 /* MIXOUTRVOL_TO_HPOUT2 */
+
+/*
+ * R52 (0x34) - Line Mixer (1)
+ */
+#define WM8994_MIXOUTL_TO_LINEOUT1N 0x0040 /* MIXOUTL_TO_LINEOUT1N */
+#define WM8994_MIXOUTL_TO_LINEOUT1N_MASK 0x0040 /* MIXOUTL_TO_LINEOUT1N */
+#define WM8994_MIXOUTL_TO_LINEOUT1N_SHIFT 6 /* MIXOUTL_TO_LINEOUT1N */
+#define WM8994_MIXOUTL_TO_LINEOUT1N_WIDTH 1 /* MIXOUTL_TO_LINEOUT1N */
+#define WM8994_MIXOUTR_TO_LINEOUT1N 0x0020 /* MIXOUTR_TO_LINEOUT1N */
+#define WM8994_MIXOUTR_TO_LINEOUT1N_MASK 0x0020 /* MIXOUTR_TO_LINEOUT1N */
+#define WM8994_MIXOUTR_TO_LINEOUT1N_SHIFT 5 /* MIXOUTR_TO_LINEOUT1N */
+#define WM8994_MIXOUTR_TO_LINEOUT1N_WIDTH 1 /* MIXOUTR_TO_LINEOUT1N */
+#define WM8994_LINEOUT1_MODE 0x0010 /* LINEOUT1_MODE */
+#define WM8994_LINEOUT1_MODE_MASK 0x0010 /* LINEOUT1_MODE */
+#define WM8994_LINEOUT1_MODE_SHIFT 4 /* LINEOUT1_MODE */
+#define WM8994_LINEOUT1_MODE_WIDTH 1 /* LINEOUT1_MODE */
+#define WM8994_IN1R_TO_LINEOUT1P 0x0004 /* IN1R_TO_LINEOUT1P */
+#define WM8994_IN1R_TO_LINEOUT1P_MASK 0x0004 /* IN1R_TO_LINEOUT1P */
+#define WM8994_IN1R_TO_LINEOUT1P_SHIFT 2 /* IN1R_TO_LINEOUT1P */
+#define WM8994_IN1R_TO_LINEOUT1P_WIDTH 1 /* IN1R_TO_LINEOUT1P */
+#define WM8994_IN1L_TO_LINEOUT1P 0x0002 /* IN1L_TO_LINEOUT1P */
+#define WM8994_IN1L_TO_LINEOUT1P_MASK 0x0002 /* IN1L_TO_LINEOUT1P */
+#define WM8994_IN1L_TO_LINEOUT1P_SHIFT 1 /* IN1L_TO_LINEOUT1P */
+#define WM8994_IN1L_TO_LINEOUT1P_WIDTH 1 /* IN1L_TO_LINEOUT1P */
+#define WM8994_MIXOUTL_TO_LINEOUT1P 0x0001 /* MIXOUTL_TO_LINEOUT1P */
+#define WM8994_MIXOUTL_TO_LINEOUT1P_MASK 0x0001 /* MIXOUTL_TO_LINEOUT1P */
+#define WM8994_MIXOUTL_TO_LINEOUT1P_SHIFT 0 /* MIXOUTL_TO_LINEOUT1P */
+#define WM8994_MIXOUTL_TO_LINEOUT1P_WIDTH 1 /* MIXOUTL_TO_LINEOUT1P */
+
+/*
+ * R53 (0x35) - Line Mixer (2)
+ */
+#define WM8994_MIXOUTR_TO_LINEOUT2N 0x0040 /* MIXOUTR_TO_LINEOUT2N */
+#define WM8994_MIXOUTR_TO_LINEOUT2N_MASK 0x0040 /* MIXOUTR_TO_LINEOUT2N */
+#define WM8994_MIXOUTR_TO_LINEOUT2N_SHIFT 6 /* MIXOUTR_TO_LINEOUT2N */
+#define WM8994_MIXOUTR_TO_LINEOUT2N_WIDTH 1 /* MIXOUTR_TO_LINEOUT2N */
+#define WM8994_MIXOUTL_TO_LINEOUT2N 0x0020 /* MIXOUTL_TO_LINEOUT2N */
+#define WM8994_MIXOUTL_TO_LINEOUT2N_MASK 0x0020 /* MIXOUTL_TO_LINEOUT2N */
+#define WM8994_MIXOUTL_TO_LINEOUT2N_SHIFT 5 /* MIXOUTL_TO_LINEOUT2N */
+#define WM8994_MIXOUTL_TO_LINEOUT2N_WIDTH 1 /* MIXOUTL_TO_LINEOUT2N */
+#define WM8994_LINEOUT2_MODE 0x0010 /* LINEOUT2_MODE */
+#define WM8994_LINEOUT2_MODE_MASK 0x0010 /* LINEOUT2_MODE */
+#define WM8994_LINEOUT2_MODE_SHIFT 4 /* LINEOUT2_MODE */
+#define WM8994_LINEOUT2_MODE_WIDTH 1 /* LINEOUT2_MODE */
+#define WM8994_IN1L_TO_LINEOUT2P 0x0004 /* IN1L_TO_LINEOUT2P */
+#define WM8994_IN1L_TO_LINEOUT2P_MASK 0x0004 /* IN1L_TO_LINEOUT2P */
+#define WM8994_IN1L_TO_LINEOUT2P_SHIFT 2 /* IN1L_TO_LINEOUT2P */
+#define WM8994_IN1L_TO_LINEOUT2P_WIDTH 1 /* IN1L_TO_LINEOUT2P */
+#define WM8994_IN1R_TO_LINEOUT2P 0x0002 /* IN1R_TO_LINEOUT2P */
+#define WM8994_IN1R_TO_LINEOUT2P_MASK 0x0002 /* IN1R_TO_LINEOUT2P */
+#define WM8994_IN1R_TO_LINEOUT2P_SHIFT 1 /* IN1R_TO_LINEOUT2P */
+#define WM8994_IN1R_TO_LINEOUT2P_WIDTH 1 /* IN1R_TO_LINEOUT2P */
+#define WM8994_MIXOUTR_TO_LINEOUT2P 0x0001 /* MIXOUTR_TO_LINEOUT2P */
+#define WM8994_MIXOUTR_TO_LINEOUT2P_MASK 0x0001 /* MIXOUTR_TO_LINEOUT2P */
+#define WM8994_MIXOUTR_TO_LINEOUT2P_SHIFT 0 /* MIXOUTR_TO_LINEOUT2P */
+#define WM8994_MIXOUTR_TO_LINEOUT2P_WIDTH 1 /* MIXOUTR_TO_LINEOUT2P */
+
+/*
+ * R54 (0x36) - Speaker Mixer
+ */
+#define WM8994_DAC2L_TO_SPKMIXL 0x0200 /* DAC2L_TO_SPKMIXL */
+#define WM8994_DAC2L_TO_SPKMIXL_MASK 0x0200 /* DAC2L_TO_SPKMIXL */
+#define WM8994_DAC2L_TO_SPKMIXL_SHIFT 9 /* DAC2L_TO_SPKMIXL */
+#define WM8994_DAC2L_TO_SPKMIXL_WIDTH 1 /* DAC2L_TO_SPKMIXL */
+#define WM8994_DAC2R_TO_SPKMIXR 0x0100 /* DAC2R_TO_SPKMIXR */
+#define WM8994_DAC2R_TO_SPKMIXR_MASK 0x0100 /* DAC2R_TO_SPKMIXR */
+#define WM8994_DAC2R_TO_SPKMIXR_SHIFT 8 /* DAC2R_TO_SPKMIXR */
+#define WM8994_DAC2R_TO_SPKMIXR_WIDTH 1 /* DAC2R_TO_SPKMIXR */
+#define WM8994_MIXINL_TO_SPKMIXL 0x0080 /* MIXINL_TO_SPKMIXL */
+#define WM8994_MIXINL_TO_SPKMIXL_MASK 0x0080 /* MIXINL_TO_SPKMIXL */
+#define WM8994_MIXINL_TO_SPKMIXL_SHIFT 7 /* MIXINL_TO_SPKMIXL */
+#define WM8994_MIXINL_TO_SPKMIXL_WIDTH 1 /* MIXINL_TO_SPKMIXL */
+#define WM8994_MIXINR_TO_SPKMIXR 0x0040 /* MIXINR_TO_SPKMIXR */
+#define WM8994_MIXINR_TO_SPKMIXR_MASK 0x0040 /* MIXINR_TO_SPKMIXR */
+#define WM8994_MIXINR_TO_SPKMIXR_SHIFT 6 /* MIXINR_TO_SPKMIXR */
+#define WM8994_MIXINR_TO_SPKMIXR_WIDTH 1 /* MIXINR_TO_SPKMIXR */
+#define WM8994_IN1LP_TO_SPKMIXL 0x0020 /* IN1LP_TO_SPKMIXL */
+#define WM8994_IN1LP_TO_SPKMIXL_MASK 0x0020 /* IN1LP_TO_SPKMIXL */
+#define WM8994_IN1LP_TO_SPKMIXL_SHIFT 5 /* IN1LP_TO_SPKMIXL */
+#define WM8994_IN1LP_TO_SPKMIXL_WIDTH 1 /* IN1LP_TO_SPKMIXL */
+#define WM8994_IN1RP_TO_SPKMIXR 0x0010 /* IN1RP_TO_SPKMIXR */
+#define WM8994_IN1RP_TO_SPKMIXR_MASK 0x0010 /* IN1RP_TO_SPKMIXR */
+#define WM8994_IN1RP_TO_SPKMIXR_SHIFT 4 /* IN1RP_TO_SPKMIXR */
+#define WM8994_IN1RP_TO_SPKMIXR_WIDTH 1 /* IN1RP_TO_SPKMIXR */
+#define WM8994_MIXOUTL_TO_SPKMIXL 0x0008 /* MIXOUTL_TO_SPKMIXL */
+#define WM8994_MIXOUTL_TO_SPKMIXL_MASK 0x0008 /* MIXOUTL_TO_SPKMIXL */
+#define WM8994_MIXOUTL_TO_SPKMIXL_SHIFT 3 /* MIXOUTL_TO_SPKMIXL */
+#define WM8994_MIXOUTL_TO_SPKMIXL_WIDTH 1 /* MIXOUTL_TO_SPKMIXL */
+#define WM8994_MIXOUTR_TO_SPKMIXR 0x0004 /* MIXOUTR_TO_SPKMIXR */
+#define WM8994_MIXOUTR_TO_SPKMIXR_MASK 0x0004 /* MIXOUTR_TO_SPKMIXR */
+#define WM8994_MIXOUTR_TO_SPKMIXR_SHIFT 2 /* MIXOUTR_TO_SPKMIXR */
+#define WM8994_MIXOUTR_TO_SPKMIXR_WIDTH 1 /* MIXOUTR_TO_SPKMIXR */
+#define WM8994_DAC1L_TO_SPKMIXL 0x0002 /* DAC1L_TO_SPKMIXL */
+#define WM8994_DAC1L_TO_SPKMIXL_MASK 0x0002 /* DAC1L_TO_SPKMIXL */
+#define WM8994_DAC1L_TO_SPKMIXL_SHIFT 1 /* DAC1L_TO_SPKMIXL */
+#define WM8994_DAC1L_TO_SPKMIXL_WIDTH 1 /* DAC1L_TO_SPKMIXL */
+#define WM8994_DAC1R_TO_SPKMIXR 0x0001 /* DAC1R_TO_SPKMIXR */
+#define WM8994_DAC1R_TO_SPKMIXR_MASK 0x0001 /* DAC1R_TO_SPKMIXR */
+#define WM8994_DAC1R_TO_SPKMIXR_SHIFT 0 /* DAC1R_TO_SPKMIXR */
+#define WM8994_DAC1R_TO_SPKMIXR_WIDTH 1 /* DAC1R_TO_SPKMIXR */
+
+/*
+ * R55 (0x37) - Additional Control
+ */
+#define WM8994_LINEOUT1_FB 0x0080 /* LINEOUT1_FB */
+#define WM8994_LINEOUT1_FB_MASK 0x0080 /* LINEOUT1_FB */
+#define WM8994_LINEOUT1_FB_SHIFT 7 /* LINEOUT1_FB */
+#define WM8994_LINEOUT1_FB_WIDTH 1 /* LINEOUT1_FB */
+#define WM8994_LINEOUT2_FB 0x0040 /* LINEOUT2_FB */
+#define WM8994_LINEOUT2_FB_MASK 0x0040 /* LINEOUT2_FB */
+#define WM8994_LINEOUT2_FB_SHIFT 6 /* LINEOUT2_FB */
+#define WM8994_LINEOUT2_FB_WIDTH 1 /* LINEOUT2_FB */
+#define WM8994_VROI 0x0001 /* VROI */
+#define WM8994_VROI_MASK 0x0001 /* VROI */
+#define WM8994_VROI_SHIFT 0 /* VROI */
+#define WM8994_VROI_WIDTH 1 /* VROI */
+
+/*
+ * R56 (0x38) - AntiPOP (1)
+ */
+#define WM8994_LINEOUT_VMID_BUF_ENA 0x0080 /* LINEOUT_VMID_BUF_ENA */
+#define WM8994_LINEOUT_VMID_BUF_ENA_MASK 0x0080 /* LINEOUT_VMID_BUF_ENA */
+#define WM8994_LINEOUT_VMID_BUF_ENA_SHIFT 7 /* LINEOUT_VMID_BUF_ENA */
+#define WM8994_LINEOUT_VMID_BUF_ENA_WIDTH 1 /* LINEOUT_VMID_BUF_ENA */
+#define WM8994_HPOUT2_IN_ENA 0x0040 /* HPOUT2_IN_ENA */
+#define WM8994_HPOUT2_IN_ENA_MASK 0x0040 /* HPOUT2_IN_ENA */
+#define WM8994_HPOUT2_IN_ENA_SHIFT 6 /* HPOUT2_IN_ENA */
+#define WM8994_HPOUT2_IN_ENA_WIDTH 1 /* HPOUT2_IN_ENA */
+#define WM8994_LINEOUT1_DISCH 0x0020 /* LINEOUT1_DISCH */
+#define WM8994_LINEOUT1_DISCH_MASK 0x0020 /* LINEOUT1_DISCH */
+#define WM8994_LINEOUT1_DISCH_SHIFT 5 /* LINEOUT1_DISCH */
+#define WM8994_LINEOUT1_DISCH_WIDTH 1 /* LINEOUT1_DISCH */
+#define WM8994_LINEOUT2_DISCH 0x0010 /* LINEOUT2_DISCH */
+#define WM8994_LINEOUT2_DISCH_MASK 0x0010 /* LINEOUT2_DISCH */
+#define WM8994_LINEOUT2_DISCH_SHIFT 4 /* LINEOUT2_DISCH */
+#define WM8994_LINEOUT2_DISCH_WIDTH 1 /* LINEOUT2_DISCH */
+
+/*
+ * R57 (0x39) - AntiPOP (2)
+ */
+#define WM8994_VMID_RAMP_MASK 0x0060 /* VMID_RAMP - [6:5] */
+#define WM8994_VMID_RAMP_SHIFT 5 /* VMID_RAMP - [6:5] */
+#define WM8994_VMID_RAMP_WIDTH 2 /* VMID_RAMP - [6:5] */
+#define WM8994_VMID_BUF_ENA 0x0008 /* VMID_BUF_ENA */
+#define WM8994_VMID_BUF_ENA_MASK 0x0008 /* VMID_BUF_ENA */
+#define WM8994_VMID_BUF_ENA_SHIFT 3 /* VMID_BUF_ENA */
+#define WM8994_VMID_BUF_ENA_WIDTH 1 /* VMID_BUF_ENA */
+#define WM8994_STARTUP_BIAS_ENA 0x0004 /* STARTUP_BIAS_ENA */
+#define WM8994_STARTUP_BIAS_ENA_MASK 0x0004 /* STARTUP_BIAS_ENA */
+#define WM8994_STARTUP_BIAS_ENA_SHIFT 2 /* STARTUP_BIAS_ENA */
+#define WM8994_STARTUP_BIAS_ENA_WIDTH 1 /* STARTUP_BIAS_ENA */
+#define WM8994_BIAS_SRC 0x0002 /* BIAS_SRC */
+#define WM8994_BIAS_SRC_MASK 0x0002 /* BIAS_SRC */
+#define WM8994_BIAS_SRC_SHIFT 1 /* BIAS_SRC */
+#define WM8994_BIAS_SRC_WIDTH 1 /* BIAS_SRC */
+#define WM8994_VMID_DISCH 0x0001 /* VMID_DISCH */
+#define WM8994_VMID_DISCH_MASK 0x0001 /* VMID_DISCH */
+#define WM8994_VMID_DISCH_SHIFT 0 /* VMID_DISCH */
+#define WM8994_VMID_DISCH_WIDTH 1 /* VMID_DISCH */
+
+/*
+ * R58 (0x3A) - MICBIAS
+ */
+#define WM8994_MICD_SCTHR_MASK 0x00C0 /* MICD_SCTHR - [7:6] */
+#define WM8994_MICD_SCTHR_SHIFT 6 /* MICD_SCTHR - [7:6] */
+#define WM8994_MICD_SCTHR_WIDTH 2 /* MICD_SCTHR - [7:6] */
+#define WM8994_MICD_THR_MASK 0x0038 /* MICD_THR - [5:3] */
+#define WM8994_MICD_THR_SHIFT 3 /* MICD_THR - [5:3] */
+#define WM8994_MICD_THR_WIDTH 3 /* MICD_THR - [5:3] */
+#define WM8994_MICD_ENA 0x0004 /* MICD_ENA */
+#define WM8994_MICD_ENA_MASK 0x0004 /* MICD_ENA */
+#define WM8994_MICD_ENA_SHIFT 2 /* MICD_ENA */
+#define WM8994_MICD_ENA_WIDTH 1 /* MICD_ENA */
+#define WM8994_MICB2_LVL 0x0002 /* MICB2_LVL */
+#define WM8994_MICB2_LVL_MASK 0x0002 /* MICB2_LVL */
+#define WM8994_MICB2_LVL_SHIFT 1 /* MICB2_LVL */
+#define WM8994_MICB2_LVL_WIDTH 1 /* MICB2_LVL */
+#define WM8994_MICB1_LVL 0x0001 /* MICB1_LVL */
+#define WM8994_MICB1_LVL_MASK 0x0001 /* MICB1_LVL */
+#define WM8994_MICB1_LVL_SHIFT 0 /* MICB1_LVL */
+#define WM8994_MICB1_LVL_WIDTH 1 /* MICB1_LVL */
+
+/*
+ * R59 (0x3B) - LDO 1
+ */
+#define WM8994_LDO1_VSEL_MASK 0x000E /* LDO1_VSEL - [3:1] */
+#define WM8994_LDO1_VSEL_SHIFT 1 /* LDO1_VSEL - [3:1] */
+#define WM8994_LDO1_VSEL_WIDTH 3 /* LDO1_VSEL - [3:1] */
+#define WM8994_LDO1_DISCH 0x0001 /* LDO1_DISCH */
+#define WM8994_LDO1_DISCH_MASK 0x0001 /* LDO1_DISCH */
+#define WM8994_LDO1_DISCH_SHIFT 0 /* LDO1_DISCH */
+#define WM8994_LDO1_DISCH_WIDTH 1 /* LDO1_DISCH */
+
+/*
+ * R60 (0x3C) - LDO 2
+ */
+#define WM8994_LDO2_VSEL_MASK 0x0006 /* LDO2_VSEL - [2:1] */
+#define WM8994_LDO2_VSEL_SHIFT 1 /* LDO2_VSEL - [2:1] */
+#define WM8994_LDO2_VSEL_WIDTH 2 /* LDO2_VSEL - [2:1] */
+#define WM8994_LDO2_DISCH 0x0001 /* LDO2_DISCH */
+#define WM8994_LDO2_DISCH_MASK 0x0001 /* LDO2_DISCH */
+#define WM8994_LDO2_DISCH_SHIFT 0 /* LDO2_DISCH */
+#define WM8994_LDO2_DISCH_WIDTH 1 /* LDO2_DISCH */
+
+/*
+ * R76 (0x4C) - Charge Pump (1)
+ */
+#define WM8994_CP_ENA 0x8000 /* CP_ENA */
+#define WM8994_CP_ENA_MASK 0x8000 /* CP_ENA */
+#define WM8994_CP_ENA_SHIFT 15 /* CP_ENA */
+#define WM8994_CP_ENA_WIDTH 1 /* CP_ENA */
+#define WM8994_CP_ENA_DEFAULT 0x1F25
+
+/*
+ * R81 (0x51) - Class W (1)
+ */
+#define WM8994_CP_DYN_SRC_SEL_MASK 0x0300 /* CP_DYN_SRC_SEL - [9:8] */
+#define WM8994_CP_DYN_SRC_SEL_SHIFT 8 /* CP_DYN_SRC_SEL - [9:8] */
+#define WM8994_CP_DYN_SRC_SEL_WIDTH 2 /* CP_DYN_SRC_SEL - [9:8] */
+#define WM8994_CP_DYN_PWR 0x0001 /* CP_DYN_PWR */
+#define WM8994_CP_DYN_PWR_MASK 0x0001 /* CP_DYN_PWR */
+#define WM8994_CP_DYN_PWR_SHIFT 0 /* CP_DYN_PWR */
+#define WM8994_CP_DYN_PWR_WIDTH 1 /* CP_DYN_PWR */
+
+/*
+ * R84 (0x54) - DC Servo (1)
+ */
+#define WM8994_DCS_TRIG_SINGLE_1 0x2000 /* DCS_TRIG_SINGLE_1 */
+#define WM8994_DCS_TRIG_SINGLE_1_MASK 0x2000 /* DCS_TRIG_SINGLE_1 */
+#define WM8994_DCS_TRIG_SINGLE_1_SHIFT 13 /* DCS_TRIG_SINGLE_1 */
+#define WM8994_DCS_TRIG_SINGLE_1_WIDTH 1 /* DCS_TRIG_SINGLE_1 */
+#define WM8994_DCS_TRIG_SINGLE_0 0x1000 /* DCS_TRIG_SINGLE_0 */
+#define WM8994_DCS_TRIG_SINGLE_0_MASK 0x1000 /* DCS_TRIG_SINGLE_0 */
+#define WM8994_DCS_TRIG_SINGLE_0_SHIFT 12 /* DCS_TRIG_SINGLE_0 */
+#define WM8994_DCS_TRIG_SINGLE_0_WIDTH 1 /* DCS_TRIG_SINGLE_0 */
+#define WM8994_DCS_TRIG_SERIES_1 0x0200 /* DCS_TRIG_SERIES_1 */
+#define WM8994_DCS_TRIG_SERIES_1_MASK 0x0200 /* DCS_TRIG_SERIES_1 */
+#define WM8994_DCS_TRIG_SERIES_1_SHIFT 9 /* DCS_TRIG_SERIES_1 */
+#define WM8994_DCS_TRIG_SERIES_1_WIDTH 1 /* DCS_TRIG_SERIES_1 */
+#define WM8994_DCS_TRIG_SERIES_0 0x0100 /* DCS_TRIG_SERIES_0 */
+#define WM8994_DCS_TRIG_SERIES_0_MASK 0x0100 /* DCS_TRIG_SERIES_0 */
+#define WM8994_DCS_TRIG_SERIES_0_SHIFT 8 /* DCS_TRIG_SERIES_0 */
+#define WM8994_DCS_TRIG_SERIES_0_WIDTH 1 /* DCS_TRIG_SERIES_0 */
+#define WM8994_DCS_TRIG_STARTUP_1 0x0020 /* DCS_TRIG_STARTUP_1 */
+#define WM8994_DCS_TRIG_STARTUP_1_MASK 0x0020 /* DCS_TRIG_STARTUP_1 */
+#define WM8994_DCS_TRIG_STARTUP_1_SHIFT 5 /* DCS_TRIG_STARTUP_1 */
+#define WM8994_DCS_TRIG_STARTUP_1_WIDTH 1 /* DCS_TRIG_STARTUP_1 */
+#define WM8994_DCS_TRIG_STARTUP_0 0x0010 /* DCS_TRIG_STARTUP_0 */
+#define WM8994_DCS_TRIG_STARTUP_0_MASK 0x0010 /* DCS_TRIG_STARTUP_0 */
+#define WM8994_DCS_TRIG_STARTUP_0_SHIFT 4 /* DCS_TRIG_STARTUP_0 */
+#define WM8994_DCS_TRIG_STARTUP_0_WIDTH 1 /* DCS_TRIG_STARTUP_0 */
+#define WM8994_DCS_TRIG_DAC_WR_1 0x0008 /* DCS_TRIG_DAC_WR_1 */
+#define WM8994_DCS_TRIG_DAC_WR_1_MASK 0x0008 /* DCS_TRIG_DAC_WR_1 */
+#define WM8994_DCS_TRIG_DAC_WR_1_SHIFT 3 /* DCS_TRIG_DAC_WR_1 */
+#define WM8994_DCS_TRIG_DAC_WR_1_WIDTH 1 /* DCS_TRIG_DAC_WR_1 */
+#define WM8994_DCS_TRIG_DAC_WR_0 0x0004 /* DCS_TRIG_DAC_WR_0 */
+#define WM8994_DCS_TRIG_DAC_WR_0_MASK 0x0004 /* DCS_TRIG_DAC_WR_0 */
+#define WM8994_DCS_TRIG_DAC_WR_0_SHIFT 2 /* DCS_TRIG_DAC_WR_0 */
+#define WM8994_DCS_TRIG_DAC_WR_0_WIDTH 1 /* DCS_TRIG_DAC_WR_0 */
+#define WM8994_DCS_ENA_CHAN_1 0x0002 /* DCS_ENA_CHAN_1 */
+#define WM8994_DCS_ENA_CHAN_1_MASK 0x0002 /* DCS_ENA_CHAN_1 */
+#define WM8994_DCS_ENA_CHAN_1_SHIFT 1 /* DCS_ENA_CHAN_1 */
+#define WM8994_DCS_ENA_CHAN_1_WIDTH 1 /* DCS_ENA_CHAN_1 */
+#define WM8994_DCS_ENA_CHAN_0 0x0001 /* DCS_ENA_CHAN_0 */
+#define WM8994_DCS_ENA_CHAN_0_MASK 0x0001 /* DCS_ENA_CHAN_0 */
+#define WM8994_DCS_ENA_CHAN_0_SHIFT 0 /* DCS_ENA_CHAN_0 */
+#define WM8994_DCS_ENA_CHAN_0_WIDTH 1 /* DCS_ENA_CHAN_0 */
+
+/*
+ * R85 (0x55) - DC Servo (2)
+ */
+#define WM8994_DCS_SERIES_NO_01_MASK 0x0FE0 /* DCS_SERIES_NO_01 - [11:5] */
+#define WM8994_DCS_SERIES_NO_01_SHIFT 5 /* DCS_SERIES_NO_01 - [11:5] */
+#define WM8994_DCS_SERIES_NO_01_WIDTH 7 /* DCS_SERIES_NO_01 - [11:5] */
+#define WM8994_DCS_TIMER_PERIOD_01_MASK 0x000F /* DCS_TIMER_PERIOD_01 - [3:0] */
+#define WM8994_DCS_TIMER_PERIOD_01_SHIFT 0 /* DCS_TIMER_PERIOD_01 - [3:0] */
+#define WM8994_DCS_TIMER_PERIOD_01_WIDTH 4 /* DCS_TIMER_PERIOD_01 - [3:0] */
+
+/*
+ * R87 (0x57) - DC Servo (4)
+ */
+#define WM8994_DCS_DAC_WR_VAL_1_MASK 0xFF00 /* DCS_DAC_WR_VAL_1 - [15:8] */
+#define WM8994_DCS_DAC_WR_VAL_1_SHIFT 8 /* DCS_DAC_WR_VAL_1 - [15:8] */
+#define WM8994_DCS_DAC_WR_VAL_1_WIDTH 8 /* DCS_DAC_WR_VAL_1 - [15:8] */
+#define WM8994_DCS_DAC_WR_VAL_0_MASK 0x00FF /* DCS_DAC_WR_VAL_0 - [7:0] */
+#define WM8994_DCS_DAC_WR_VAL_0_SHIFT 0 /* DCS_DAC_WR_VAL_0 - [7:0] */
+#define WM8994_DCS_DAC_WR_VAL_0_WIDTH 8 /* DCS_DAC_WR_VAL_0 - [7:0] */
+
+/*
+ * R88 (0x58) - DC Servo Readback
+ */
+#define WM8994_DCS_CAL_COMPLETE_MASK 0x0300 /* DCS_CAL_COMPLETE - [9:8] */
+#define WM8994_DCS_CAL_COMPLETE_SHIFT 8 /* DCS_CAL_COMPLETE - [9:8] */
+#define WM8994_DCS_CAL_COMPLETE_WIDTH 2 /* DCS_CAL_COMPLETE - [9:8] */
+#define WM8994_DCS_DAC_WR_COMPLETE_MASK 0x0030 /* DCS_DAC_WR_COMPLETE - [5:4] */
+#define WM8994_DCS_DAC_WR_COMPLETE_SHIFT 4 /* DCS_DAC_WR_COMPLETE - [5:4] */
+#define WM8994_DCS_DAC_WR_COMPLETE_WIDTH 2 /* DCS_DAC_WR_COMPLETE - [5:4] */
+#define WM8994_DCS_STARTUP_COMPLETE_MASK 0x0003 /* DCS_STARTUP_COMPLETE - [1:0] */
+#define WM8994_DCS_STARTUP_COMPLETE_SHIFT 0 /* DCS_STARTUP_COMPLETE - [1:0] */
+#define WM8994_DCS_STARTUP_COMPLETE_WIDTH 2 /* DCS_STARTUP_COMPLETE - [1:0] */
+
+/*
+ * R91 (0x5B) - DC Servo ANA (1)
+ */
+#define WM8994_DCS_IDAC_VAL_1_MASK 0x00FF /* DCS_IDAC_VAL_1 - [7:0] */
+#define WM8994_DCS_IDAC_VAL_1_SHIFT 0 /* DCS_IDAC_VAL_1 - [7:0] */
+#define WM8994_DCS_IDAC_VAL_1_WIDTH 8 /* DCS_IDAC_VAL_1 - [7:0] */
+
+/*
+ * R92 (0x5C) - DC Servo ANA (2)
+ */
+#define WM8994_DCS_IDAC_VAL_0_MASK 0x00FF /* DCS_IDAC_VAL_0 - [7:0] */
+#define WM8994_DCS_IDAC_VAL_0_SHIFT 0 /* DCS_IDAC_VAL_0 - [7:0] */
+#define WM8994_DCS_IDAC_VAL_0_WIDTH 8 /* DCS_IDAC_VAL_0 - [7:0] */
+
+/*
+ * R96 (0x60) - Analogue HP (1)
+ */
+#define WM8994_HPOUT1L_RMV_SHORT 0x0080 /* HPOUT1L_RMV_SHORT */
+#define WM8994_HPOUT1L_RMV_SHORT_MASK 0x0080 /* HPOUT1L_RMV_SHORT */
+#define WM8994_HPOUT1L_RMV_SHORT_SHIFT 7 /* HPOUT1L_RMV_SHORT */
+#define WM8994_HPOUT1L_RMV_SHORT_WIDTH 1 /* HPOUT1L_RMV_SHORT */
+#define WM8994_HPOUT1L_OUTP 0x0040 /* HPOUT1L_OUTP */
+#define WM8994_HPOUT1L_OUTP_MASK 0x0040 /* HPOUT1L_OUTP */
+#define WM8994_HPOUT1L_OUTP_SHIFT 6 /* HPOUT1L_OUTP */
+#define WM8994_HPOUT1L_OUTP_WIDTH 1 /* HPOUT1L_OUTP */
+#define WM8994_HPOUT1L_DLY 0x0020 /* HPOUT1L_DLY */
+#define WM8994_HPOUT1L_DLY_MASK 0x0020 /* HPOUT1L_DLY */
+#define WM8994_HPOUT1L_DLY_SHIFT 5 /* HPOUT1L_DLY */
+#define WM8994_HPOUT1L_DLY_WIDTH 1 /* HPOUT1L_DLY */
+#define WM8994_HPOUT1R_RMV_SHORT 0x0008 /* HPOUT1R_RMV_SHORT */
+#define WM8994_HPOUT1R_RMV_SHORT_MASK 0x0008 /* HPOUT1R_RMV_SHORT */
+#define WM8994_HPOUT1R_RMV_SHORT_SHIFT 3 /* HPOUT1R_RMV_SHORT */
+#define WM8994_HPOUT1R_RMV_SHORT_WIDTH 1 /* HPOUT1R_RMV_SHORT */
+#define WM8994_HPOUT1R_OUTP 0x0004 /* HPOUT1R_OUTP */
+#define WM8994_HPOUT1R_OUTP_MASK 0x0004 /* HPOUT1R_OUTP */
+#define WM8994_HPOUT1R_OUTP_SHIFT 2 /* HPOUT1R_OUTP */
+#define WM8994_HPOUT1R_OUTP_WIDTH 1 /* HPOUT1R_OUTP */
+#define WM8994_HPOUT1R_DLY 0x0002 /* HPOUT1R_DLY */
+#define WM8994_HPOUT1R_DLY_MASK 0x0002 /* HPOUT1R_DLY */
+#define WM8994_HPOUT1R_DLY_SHIFT 1 /* HPOUT1R_DLY */
+#define WM8994_HPOUT1R_DLY_WIDTH 1 /* HPOUT1R_DLY */
+
+/*
+ * R257 (0x101) - Control Interface
+ */
+#define WM8994_REG_SYNC 0x8000 /* REG_SYNC */
+#define WM8994_REG_SYNC_MASK 0x8000 /* REG_SYNC */
+#define WM8994_REG_SYNC_SHIFT 15 /* REG_SYNC */
+#define WM8994_REG_SYNC_WIDTH 1 /* REG_SYNC */
+#define WM8994_SPI_CONTRD 0x0040 /* SPI_CONTRD */
+#define WM8994_SPI_CONTRD_MASK 0x0040 /* SPI_CONTRD */
+#define WM8994_SPI_CONTRD_SHIFT 6 /* SPI_CONTRD */
+#define WM8994_SPI_CONTRD_WIDTH 1 /* SPI_CONTRD */
+#define WM8994_SPI_4WIRE 0x0020 /* SPI_4WIRE */
+#define WM8994_SPI_4WIRE_MASK 0x0020 /* SPI_4WIRE */
+#define WM8994_SPI_4WIRE_SHIFT 5 /* SPI_4WIRE */
+#define WM8994_SPI_4WIRE_WIDTH 1 /* SPI_4WIRE */
+#define WM8994_SPI_CFG 0x0010 /* SPI_CFG */
+#define WM8994_SPI_CFG_MASK 0x0010 /* SPI_CFG */
+#define WM8994_SPI_CFG_SHIFT 4 /* SPI_CFG */
+#define WM8994_SPI_CFG_WIDTH 1 /* SPI_CFG */
+#define WM8994_AUTO_INC 0x0004 /* AUTO_INC */
+#define WM8994_AUTO_INC_MASK 0x0004 /* AUTO_INC */
+#define WM8994_AUTO_INC_SHIFT 2 /* AUTO_INC */
+#define WM8994_AUTO_INC_WIDTH 1 /* AUTO_INC */
+
+/*
+ * R272 (0x110) - Write Sequencer Ctrl (1)
+ */
+#define WM8994_WSEQ_ENA 0x8000 /* WSEQ_ENA */
+#define WM8994_WSEQ_ENA_MASK 0x8000 /* WSEQ_ENA */
+#define WM8994_WSEQ_ENA_SHIFT 15 /* WSEQ_ENA */
+#define WM8994_WSEQ_ENA_WIDTH 1 /* WSEQ_ENA */
+#define WM8994_WSEQ_ABORT 0x0200 /* WSEQ_ABORT */
+#define WM8994_WSEQ_ABORT_MASK 0x0200 /* WSEQ_ABORT */
+#define WM8994_WSEQ_ABORT_SHIFT 9 /* WSEQ_ABORT */
+#define WM8994_WSEQ_ABORT_WIDTH 1 /* WSEQ_ABORT */
+#define WM8994_WSEQ_START 0x0100 /* WSEQ_START */
+#define WM8994_WSEQ_START_MASK 0x0100 /* WSEQ_START */
+#define WM8994_WSEQ_START_SHIFT 8 /* WSEQ_START */
+#define WM8994_WSEQ_START_WIDTH 1 /* WSEQ_START */
+#define WM8994_WSEQ_START_INDEX_MASK 0x007F /* WSEQ_START_INDEX - [6:0] */
+#define WM8994_WSEQ_START_INDEX_SHIFT 0 /* WSEQ_START_INDEX - [6:0] */
+#define WM8994_WSEQ_START_INDEX_WIDTH 7 /* WSEQ_START_INDEX - [6:0] */
+
+/*
+ * R273 (0x111) - Write Sequencer Ctrl (2)
+ */
+#define WM8994_WSEQ_BUSY 0x0100 /* WSEQ_BUSY */
+#define WM8994_WSEQ_BUSY_MASK 0x0100 /* WSEQ_BUSY */
+#define WM8994_WSEQ_BUSY_SHIFT 8 /* WSEQ_BUSY */
+#define WM8994_WSEQ_BUSY_WIDTH 1 /* WSEQ_BUSY */
+#define WM8994_WSEQ_CURRENT_INDEX_MASK 0x007F /* WSEQ_CURRENT_INDEX - [6:0] */
+#define WM8994_WSEQ_CURRENT_INDEX_SHIFT 0 /* WSEQ_CURRENT_INDEX - [6:0] */
+#define WM8994_WSEQ_CURRENT_INDEX_WIDTH 7 /* WSEQ_CURRENT_INDEX - [6:0] */
+
+/*
+ * R512 (0x200) - AIF1 Clocking (1)
+ */
+#define WM8994_AIF1CLK_SRC_FLL1 0x0010
+#define WM8994_AIF1CLK_SRC_MASK 0x0018 /* AIF1CLK_SRC - [4:3] */
+#define WM8994_AIF1CLK_SRC_SHIFT 3 /* AIF1CLK_SRC - [4:3] */
+#define WM8994_AIF1CLK_SRC_WIDTH 2 /* AIF1CLK_SRC - [4:3] */
+#define WM8994_AIF1CLK_INV 0x0004 /* AIF1CLK_INV */
+#define WM8994_AIF1CLK_INV_MASK 0x0004 /* AIF1CLK_INV */
+#define WM8994_AIF1CLK_INV_SHIFT 2 /* AIF1CLK_INV */
+#define WM8994_AIF1CLK_INV_WIDTH 1 /* AIF1CLK_INV */
+#define WM8994_AIF1CLK_DIV 0x0002 /* AIF1CLK_DIV */
+#define WM8994_AIF1CLK_DIV_MASK 0x0002 /* AIF1CLK_DIV */
+#define WM8994_AIF1CLK_DIV_SHIFT 1 /* AIF1CLK_DIV */
+#define WM8994_AIF1CLK_DIV_WIDTH 1 /* AIF1CLK_DIV */
+#define WM8994_AIF1CLK_ENA 0x0001 /* AIF1CLK_ENA */
+#define WM8994_AIF1CLK_ENA_MASK 0x0001 /* AIF1CLK_ENA */
+#define WM8994_AIF1CLK_ENA_SHIFT 0 /* AIF1CLK_ENA */
+#define WM8994_AIF1CLK_ENA_WIDTH 1 /* AIF1CLK_ENA */
+
+/*
+ * R513 (0x201) - AIF1 Clocking (2)
+ */
+#define WM8994_AIF1DAC_DIV_MASK 0x0038 /* AIF1DAC_DIV - [5:3] */
+#define WM8994_AIF1DAC_DIV_SHIFT 3 /* AIF1DAC_DIV - [5:3] */
+#define WM8994_AIF1DAC_DIV_WIDTH 3 /* AIF1DAC_DIV - [5:3] */
+#define WM8994_AIF1ADC_DIV_MASK 0x0007 /* AIF1ADC_DIV - [2:0] */
+#define WM8994_AIF1ADC_DIV_SHIFT 0 /* AIF1ADC_DIV - [2:0] */
+#define WM8994_AIF1ADC_DIV_WIDTH 3 /* AIF1ADC_DIV - [2:0] */
+
+/*
+ * R516 (0x204) - AIF2 Clocking (1)
+ */
+#define WM8994_AIF2CLK_SRC_MASK 0x0018 /* AIF2CLK_SRC - [4:3] */
+#define WM8994_AIF2CLK_SRC_SHIFT 3 /* AIF2CLK_SRC - [4:3] */
+#define WM8994_AIF2CLK_SRC_WIDTH 2 /* AIF2CLK_SRC - [4:3] */
+#define WM8994_AIF2CLK_INV 0x0004 /* AIF2CLK_INV */
+#define WM8994_AIF2CLK_INV_MASK 0x0004 /* AIF2CLK_INV */
+#define WM8994_AIF2CLK_INV_SHIFT 2 /* AIF2CLK_INV */
+#define WM8994_AIF2CLK_INV_WIDTH 1 /* AIF2CLK_INV */
+#define WM8994_AIF2CLK_DIV 0x0002 /* AIF2CLK_DIV */
+#define WM8994_AIF2CLK_DIV_MASK 0x0002 /* AIF2CLK_DIV */
+#define WM8994_AIF2CLK_DIV_SHIFT 1 /* AIF2CLK_DIV */
+#define WM8994_AIF2CLK_DIV_WIDTH 1 /* AIF2CLK_DIV */
+#define WM8994_AIF2CLK_ENA 0x0001 /* AIF2CLK_ENA */
+#define WM8994_AIF2CLK_ENA_MASK 0x0001 /* AIF2CLK_ENA */
+#define WM8994_AIF2CLK_ENA_SHIFT 0 /* AIF2CLK_ENA */
+#define WM8994_AIF2CLK_ENA_WIDTH 1 /* AIF2CLK_ENA */
+
+/*
+ * R517 (0x205) - AIF2 Clocking (2)
+ */
+#define WM8994_AIF2DAC_DIV_MASK 0x0038 /* AIF2DAC_DIV - [5:3] */
+#define WM8994_AIF2DAC_DIV_SHIFT 3 /* AIF2DAC_DIV - [5:3] */
+#define WM8994_AIF2DAC_DIV_WIDTH 3 /* AIF2DAC_DIV - [5:3] */
+#define WM8994_AIF2ADC_DIV_MASK 0x0007 /* AIF2ADC_DIV - [2:0] */
+#define WM8994_AIF2ADC_DIV_SHIFT 0 /* AIF2ADC_DIV - [2:0] */
+#define WM8994_AIF2ADC_DIV_WIDTH 3 /* AIF2ADC_DIV - [2:0] */
+
+/*
+ * R520 (0x208) - Clocking (1)
+ */
+#define WM8994_TOCLK_ENA 0x0010 /* TOCLK_ENA */
+#define WM8994_TOCLK_ENA_MASK 0x0010 /* TOCLK_ENA */
+#define WM8994_TOCLK_ENA_SHIFT 4 /* TOCLK_ENA */
+#define WM8994_TOCLK_ENA_WIDTH 1 /* TOCLK_ENA */
+#define WM8994_DSP_FS1CLK_ENA 0x0008 /* DSP_FS1CLK_ENA */
+#define WM8994_DSP_FS1CLK_ENA_MASK 0x0008 /* DSP_FS1CLK_ENA */
+#define WM8994_DSP_FS1CLK_ENA_SHIFT 3 /* DSP_FS1CLK_ENA */
+#define WM8994_DSP_FS1CLK_ENA_WIDTH 1 /* DSP_FS1CLK_ENA */
+#define WM8994_DSP_FS2CLK_ENA 0x0004 /* DSP_FS2CLK_ENA */
+#define WM8994_DSP_FS2CLK_ENA_MASK 0x0004 /* DSP_FS2CLK_ENA */
+#define WM8994_DSP_FS2CLK_ENA_SHIFT 2 /* DSP_FS2CLK_ENA */
+#define WM8994_DSP_FS2CLK_ENA_WIDTH 1 /* DSP_FS2CLK_ENA */
+#define WM8994_DSP_FSINTCLK_ENA 0x0002 /* DSP_FSINTCLK_ENA */
+#define WM8994_DSP_FSINTCLK_ENA_MASK 0x0002 /* DSP_FSINTCLK_ENA */
+#define WM8994_DSP_FSINTCLK_ENA_SHIFT 1 /* DSP_FSINTCLK_ENA */
+#define WM8994_DSP_FSINTCLK_ENA_WIDTH 1 /* DSP_FSINTCLK_ENA */
+#define WM8994_SYSCLK_SRC 0x0001 /* SYSCLK_SRC */
+#define WM8994_SYSCLK_SRC_MASK 0x0001 /* SYSCLK_SRC */
+#define WM8994_SYSCLK_SRC_SHIFT 0 /* SYSCLK_SRC */
+#define WM8994_SYSCLK_SRC_WIDTH 1 /* SYSCLK_SRC */
+
+/*
+ * R521 (0x209) - Clocking (2)
+ */
+#define WM8994_TOCLK_DIV_MASK 0x0700 /* TOCLK_DIV - [10:8] */
+#define WM8994_TOCLK_DIV_SHIFT 8 /* TOCLK_DIV - [10:8] */
+#define WM8994_TOCLK_DIV_WIDTH 3 /* TOCLK_DIV - [10:8] */
+#define WM8994_DBCLK_DIV_MASK 0x0070 /* DBCLK_DIV - [6:4] */
+#define WM8994_DBCLK_DIV_SHIFT 4 /* DBCLK_DIV - [6:4] */
+#define WM8994_DBCLK_DIV_WIDTH 3 /* DBCLK_DIV - [6:4] */
+#define WM8994_OPCLK_DIV_MASK 0x0007 /* OPCLK_DIV - [2:0] */
+#define WM8994_OPCLK_DIV_SHIFT 0 /* OPCLK_DIV - [2:0] */
+#define WM8994_OPCLK_DIV_WIDTH 3 /* OPCLK_DIV - [2:0] */
+
+/*
+ * R528 (0x210) - AIF1 Rate
+ */
+#define WM8994_AIF1_SR_MASK 0x00F0 /* AIF1_SR - [7:4] */
+#define WM8994_AIF1_SR_SHIFT 4 /* AIF1_SR - [7:4] */
+#define WM8994_AIF1_SR_WIDTH 4 /* AIF1_SR - [7:4] */
+#define WM8994_AIF1CLK_RATE_MASK 0x000F /* AIF1CLK_RATE - [3:0] */
+#define WM8994_AIF1CLK_RATE_SHIFT 0 /* AIF1CLK_RATE - [3:0] */
+#define WM8994_AIF1CLK_RATE_WIDTH 4 /* AIF1CLK_RATE - [3:0] */
+
+/*
+ * R529 (0x211) - AIF2 Rate
+ */
+#define WM8994_AIF2_SR_MASK 0x00F0 /* AIF2_SR - [7:4] */
+#define WM8994_AIF2_SR_SHIFT 4 /* AIF2_SR - [7:4] */
+#define WM8994_AIF2_SR_WIDTH 4 /* AIF2_SR - [7:4] */
+#define WM8994_AIF2CLK_RATE_MASK 0x000F /* AIF2CLK_RATE - [3:0] */
+#define WM8994_AIF2CLK_RATE_SHIFT 0 /* AIF2CLK_RATE - [3:0] */
+#define WM8994_AIF2CLK_RATE_WIDTH 4 /* AIF2CLK_RATE - [3:0] */
+
+/*
+ * R530 (0x212) - Rate Status
+ */
+#define WM8994_SR_ERROR_MASK 0x000F /* SR_ERROR - [3:0] */
+#define WM8994_SR_ERROR_SHIFT 0 /* SR_ERROR - [3:0] */
+#define WM8994_SR_ERROR_WIDTH 4 /* SR_ERROR - [3:0] */
+
+/*
+ * R544 (0x220) - FLL1 Control (1)
+ */
+#define WM8994_FLL1_FRACN_ENA 0x0004 /* FLL1_FRACN_ENA */
+#define WM8994_FLL1_FRACN_ENA_MASK 0x0004 /* FLL1_FRACN_ENA */
+#define WM8994_FLL1_FRACN_ENA_SHIFT 2 /* FLL1_FRACN_ENA */
+#define WM8994_FLL1_FRACN_ENA_WIDTH 1 /* FLL1_FRACN_ENA */
+#define WM8994_FLL1_OSC_ENA 0x0002 /* FLL1_OSC_ENA */
+#define WM8994_FLL1_OSC_ENA_MASK 0x0002 /* FLL1_OSC_ENA */
+#define WM8994_FLL1_OSC_ENA_SHIFT 1 /* FLL1_OSC_ENA */
+#define WM8994_FLL1_OSC_ENA_WIDTH 1 /* FLL1_OSC_ENA */
+#define WM8994_FLL1_ENA 0x0001 /* FLL1_ENA */
+#define WM8994_FLL1_ENA_MASK 0x0001 /* FLL1_ENA */
+#define WM8994_FLL1_ENA_SHIFT 0 /* FLL1_ENA */
+#define WM8994_FLL1_ENA_WIDTH 1 /* FLL1_ENA */
+
+/*
+ * R545 (0x221) - FLL1 Control (2)
+ */
+#define WM8994_FLL1_OUTDIV_8 0x0700
+#define WM8994_FLL1_OUTDIV_MASK 0x3F00 /* FLL1_OUTDIV - [13:8] */
+#define WM8994_FLL1_OUTDIV_SHIFT 8 /* FLL1_OUTDIV - [13:8] */
+#define WM8994_FLL1_OUTDIV_WIDTH 6 /* FLL1_OUTDIV - [13:8] */
+#define WM8994_FLL1_CTRL_RATE_MASK 0x0070 /* FLL1_CTRL_RATE - [6:4] */
+#define WM8994_FLL1_CTRL_RATE_SHIFT 4 /* FLL1_CTRL_RATE - [6:4] */
+#define WM8994_FLL1_CTRL_RATE_WIDTH 3 /* FLL1_CTRL_RATE - [6:4] */
+#define WM8994_FLL1_FRATIO_MASK 0x0007 /* FLL1_FRATIO - [2:0] */
+#define WM8994_FLL1_FRATIO_SHIFT 0 /* FLL1_FRATIO - [2:0] */
+#define WM8994_FLL1_FRATIO_WIDTH 3 /* FLL1_FRATIO - [2:0] */
+
+/*
+ * R546 (0x222) - FLL1 Control (3)
+ */
+#define WM8994_FLL1_K_MASK 0xFFFF /* FLL1_K - [15:0] */
+#define WM8994_FLL1_K_SHIFT 0 /* FLL1_K - [15:0] */
+#define WM8994_FLL1_K_WIDTH 16 /* FLL1_K - [15:0] */
+
+/*
+ * R547 (0x223) - FLL1 Control (4)
+ */
+#define WM8994_FLL1_N_MASK 0x7FE0 /* FLL1_N - [14:5] */
+#define WM8994_FLL1_N_SHIFT 5 /* FLL1_N - [14:5] */
+#define WM8994_FLL1_N_WIDTH 10 /* FLL1_N - [14:5] */
+#define WM8994_FLL1_GAIN_MASK 0x000F /* FLL1_GAIN - [3:0] */
+#define WM8994_FLL1_GAIN_SHIFT 0 /* FLL1_GAIN - [3:0] */
+#define WM8994_FLL1_GAIN_WIDTH 4 /* FLL1_GAIN - [3:0] */
+
+/*
+ * R548 (0x224) - FLL1 Control (5)
+ */
+#define WM8994_FLL1_FRC_NCO_VAL_MASK 0x1F80 /* FLL1_FRC_NCO_VAL - [12:7] */
+#define WM8994_FLL1_FRC_NCO_VAL_SHIFT 7 /* FLL1_FRC_NCO_VAL - [12:7] */
+#define WM8994_FLL1_FRC_NCO_VAL_WIDTH 6 /* FLL1_FRC_NCO_VAL - [12:7] */
+#define WM8994_FLL1_FRC_NCO 0x0040 /* FLL1_FRC_NCO */
+#define WM8994_FLL1_FRC_NCO_MASK 0x0040 /* FLL1_FRC_NCO */
+#define WM8994_FLL1_FRC_NCO_SHIFT 6 /* FLL1_FRC_NCO */
+#define WM8994_FLL1_FRC_NCO_WIDTH 1 /* FLL1_FRC_NCO */
+#define WM8994_FLL1_CLK_REF_DIV_MASK 0x0018 /* FLL1_CLK_REF_DIV - [4:3] */
+#define WM8994_FLL1_CLK_REF_DIV_SHIFT 3 /* FLL1_CLK_REF_DIV - [4:3] */
+#define WM8994_FLL1_CLK_REF_DIV_WIDTH 2 /* FLL1_CLK_REF_DIV - [4:3] */
+#define WM8994_FLL1_CLK_REF_SRC_MASK 0x0003 /* FLL1_CLK_REF_SRC - [1:0] */
+#define WM8994_FLL1_CLK_REF_SRC_SHIFT 0 /* FLL1_CLK_REF_SRC - [1:0] */
+#define WM8994_FLL1_CLK_REF_SRC_WIDTH 2 /* FLL1_CLK_REF_SRC - [1:0] */
+
+/*
+ * R576 (0x240) - FLL2 Control (1)
+ */
+#define WM8994_FLL2_FRACN_ENA 0x0004 /* FLL2_FRACN_ENA */
+#define WM8994_FLL2_FRACN_ENA_MASK 0x0004 /* FLL2_FRACN_ENA */
+#define WM8994_FLL2_FRACN_ENA_SHIFT 2 /* FLL2_FRACN_ENA */
+#define WM8994_FLL2_FRACN_ENA_WIDTH 1 /* FLL2_FRACN_ENA */
+#define WM8994_FLL2_OSC_ENA 0x0002 /* FLL2_OSC_ENA */
+#define WM8994_FLL2_OSC_ENA_MASK 0x0002 /* FLL2_OSC_ENA */
+#define WM8994_FLL2_OSC_ENA_SHIFT 1 /* FLL2_OSC_ENA */
+#define WM8994_FLL2_OSC_ENA_WIDTH 1 /* FLL2_OSC_ENA */
+#define WM8994_FLL2_ENA 0x0001 /* FLL2_ENA */
+#define WM8994_FLL2_ENA_MASK 0x0001 /* FLL2_ENA */
+#define WM8994_FLL2_ENA_SHIFT 0 /* FLL2_ENA */
+#define WM8994_FLL2_ENA_WIDTH 1 /* FLL2_ENA */
+
+/*
+ * R577 (0x241) - FLL2 Control (2)
+ */
+#define WM8994_FLL2_OUTDIV_MASK 0x3F00 /* FLL2_OUTDIV - [13:8] */
+#define WM8994_FLL2_OUTDIV_SHIFT 8 /* FLL2_OUTDIV - [13:8] */
+#define WM8994_FLL2_OUTDIV_WIDTH 6 /* FLL2_OUTDIV - [13:8] */
+#define WM8994_FLL2_CTRL_RATE_MASK 0x0070 /* FLL2_CTRL_RATE - [6:4] */
+#define WM8994_FLL2_CTRL_RATE_SHIFT 4 /* FLL2_CTRL_RATE - [6:4] */
+#define WM8994_FLL2_CTRL_RATE_WIDTH 3 /* FLL2_CTRL_RATE - [6:4] */
+#define WM8994_FLL2_FRATIO_MASK 0x0007 /* FLL2_FRATIO - [2:0] */
+#define WM8994_FLL2_FRATIO_SHIFT 0 /* FLL2_FRATIO - [2:0] */
+#define WM8994_FLL2_FRATIO_WIDTH 3 /* FLL2_FRATIO - [2:0] */
+
+/*
+ * R578 (0x242) - FLL2 Control (3)
+ */
+#define WM8994_FLL2_K_MASK 0xFFFF /* FLL2_K - [15:0] */
+#define WM8994_FLL2_K_SHIFT 0 /* FLL2_K - [15:0] */
+#define WM8994_FLL2_K_WIDTH 16 /* FLL2_K - [15:0] */
+
+/*
+ * R579 (0x243) - FLL2 Control (4)
+ */
+#define WM8994_FLL2_N_MASK 0x7FE0 /* FLL2_N - [14:5] */
+#define WM8994_FLL2_N_SHIFT 5 /* FLL2_N - [14:5] */
+#define WM8994_FLL2_N_WIDTH 10 /* FLL2_N - [14:5] */
+#define WM8994_FLL2_GAIN_MASK 0x000F /* FLL2_GAIN - [3:0] */
+#define WM8994_FLL2_GAIN_SHIFT 0 /* FLL2_GAIN - [3:0] */
+#define WM8994_FLL2_GAIN_WIDTH 4 /* FLL2_GAIN - [3:0] */
+
+/*
+ * R580 (0x244) - FLL2 Control (5)
+ */
+#define WM8994_FLL2_FRC_NCO_VAL_MASK 0x1F80 /* FLL2_FRC_NCO_VAL - [12:7] */
+#define WM8994_FLL2_FRC_NCO_VAL_SHIFT 7 /* FLL2_FRC_NCO_VAL - [12:7] */
+#define WM8994_FLL2_FRC_NCO_VAL_WIDTH 6 /* FLL2_FRC_NCO_VAL - [12:7] */
+#define WM8994_FLL2_FRC_NCO 0x0040 /* FLL2_FRC_NCO */
+#define WM8994_FLL2_FRC_NCO_MASK 0x0040 /* FLL2_FRC_NCO */
+#define WM8994_FLL2_FRC_NCO_SHIFT 6 /* FLL2_FRC_NCO */
+#define WM8994_FLL2_FRC_NCO_WIDTH 1 /* FLL2_FRC_NCO */
+#define WM8994_FLL2_CLK_REF_DIV_MASK 0x0018 /* FLL2_CLK_REF_DIV - [4:3] */
+#define WM8994_FLL2_CLK_REF_DIV_SHIFT 3 /* FLL2_CLK_REF_DIV - [4:3] */
+#define WM8994_FLL2_CLK_REF_DIV_WIDTH 2 /* FLL2_CLK_REF_DIV - [4:3] */
+#define WM8994_FLL2_CLK_REF_SRC_MASK 0x0003 /* FLL2_CLK_REF_SRC - [1:0] */
+#define WM8994_FLL2_CLK_REF_SRC_SHIFT 0 /* FLL2_CLK_REF_SRC - [1:0] */
+#define WM8994_FLL2_CLK_REF_SRC_WIDTH 2 /* FLL2_CLK_REF_SRC - [1:0] */
+
+/*
+ * R768 (0x300) - AIF1 Control (1)
+ */
+#define WM8994_AIF1ADCL_SRC 0x8000 /* AIF1ADCL_SRC */
+#define WM8994_AIF1ADCL_SRC_MASK 0x8000 /* AIF1ADCL_SRC */
+#define WM8994_AIF1ADCL_SRC_SHIFT 15 /* AIF1ADCL_SRC */
+#define WM8994_AIF1ADCL_SRC_WIDTH 1 /* AIF1ADCL_SRC */
+#define WM8994_AIF1ADCR_SRC 0x4000 /* AIF1ADCR_SRC */
+#define WM8994_AIF1ADCR_SRC_MASK 0x4000 /* AIF1ADCR_SRC */
+#define WM8994_AIF1ADCR_SRC_SHIFT 14 /* AIF1ADCR_SRC */
+#define WM8994_AIF1ADCR_SRC_WIDTH 1 /* AIF1ADCR_SRC */
+#define WM8994_AIF1ADC_TDM 0x2000 /* AIF1ADC_TDM */
+#define WM8994_AIF1ADC_TDM_MASK 0x2000 /* AIF1ADC_TDM */
+#define WM8994_AIF1ADC_TDM_SHIFT 13 /* AIF1ADC_TDM */
+#define WM8994_AIF1ADC_TDM_WIDTH 1 /* AIF1ADC_TDM */
+#define WM8994_AIF1_BCLK_INV 0x0100 /* AIF1_BCLK_INV */
+#define WM8994_AIF1_BCLK_INV_MASK 0x0100 /* AIF1_BCLK_INV */
+#define WM8994_AIF1_BCLK_INV_SHIFT 8 /* AIF1_BCLK_INV */
+#define WM8994_AIF1_BCLK_INV_WIDTH 1 /* AIF1_BCLK_INV */
+#define WM8994_AIF1_LRCLK_INV 0x0080 /* AIF1_LRCLK_INV */
+#define WM8994_AIF1_LRCLK_INV_MASK 0x0080 /* AIF1_LRCLK_INV */
+#define WM8994_AIF1_LRCLK_INV_SHIFT 7 /* AIF1_LRCLK_INV */
+#define WM8994_AIF1_LRCLK_INV_WIDTH 1 /* AIF1_LRCLK_INV */
+#define WM8994_AIF1_WL_MASK 0x0060 /* AIF1_WL - [6:5] */
+#define WM8994_AIF1_WL_SHIFT 5 /* AIF1_WL - [6:5] */
+#define WM8994_AIF1_WL_WIDTH 2 /* AIF1_WL - [6:5] */
+#define WM8994_AIF1_FMT_MASK 0x0018 /* AIF1_FMT - [4:3] */
+#define WM8994_AIF1_FMT_SHIFT 3 /* AIF1_FMT - [4:3] */
+#define WM8994_AIF1_FMT_WIDTH 2 /* AIF1_FMT - [4:3] */
+
+/*
+ * R769 (0x301) - AIF1 Control (2)
+ */
+#define WM8994_AIF1DACL_SRC 0x8000 /* AIF1DACL_SRC */
+#define WM8994_AIF1DACL_SRC_MASK 0x8000 /* AIF1DACL_SRC */
+#define WM8994_AIF1DACL_SRC_SHIFT 15 /* AIF1DACL_SRC */
+#define WM8994_AIF1DACL_SRC_WIDTH 1 /* AIF1DACL_SRC */
+#define WM8994_AIF1DACR_SRC 0x4000 /* AIF1DACR_SRC */
+#define WM8994_AIF1DACR_SRC_MASK 0x4000 /* AIF1DACR_SRC */
+#define WM8994_AIF1DACR_SRC_SHIFT 14 /* AIF1DACR_SRC */
+#define WM8994_AIF1DACR_SRC_WIDTH 1 /* AIF1DACR_SRC */
+#define WM8994_AIF1DAC_BOOST_MASK 0x0C00 /* AIF1DAC_BOOST - [11:10] */
+#define WM8994_AIF1DAC_BOOST_SHIFT 10 /* AIF1DAC_BOOST - [11:10] */
+#define WM8994_AIF1DAC_BOOST_WIDTH 2 /* AIF1DAC_BOOST - [11:10] */
+#define WM8994_AIF1DAC_COMP 0x0010 /* AIF1DAC_COMP */
+#define WM8994_AIF1DAC_COMP_MASK 0x0010 /* AIF1DAC_COMP */
+#define WM8994_AIF1DAC_COMP_SHIFT 4 /* AIF1DAC_COMP */
+#define WM8994_AIF1DAC_COMP_WIDTH 1 /* AIF1DAC_COMP */
+#define WM8994_AIF1DAC_COMPMODE 0x0008 /* AIF1DAC_COMPMODE */
+#define WM8994_AIF1DAC_COMPMODE_MASK 0x0008 /* AIF1DAC_COMPMODE */
+#define WM8994_AIF1DAC_COMPMODE_SHIFT 3 /* AIF1DAC_COMPMODE */
+#define WM8994_AIF1DAC_COMPMODE_WIDTH 1 /* AIF1DAC_COMPMODE */
+#define WM8994_AIF1ADC_COMP 0x0004 /* AIF1ADC_COMP */
+#define WM8994_AIF1ADC_COMP_MASK 0x0004 /* AIF1ADC_COMP */
+#define WM8994_AIF1ADC_COMP_SHIFT 2 /* AIF1ADC_COMP */
+#define WM8994_AIF1ADC_COMP_WIDTH 1 /* AIF1ADC_COMP */
+#define WM8994_AIF1ADC_COMPMODE 0x0002 /* AIF1ADC_COMPMODE */
+#define WM8994_AIF1ADC_COMPMODE_MASK 0x0002 /* AIF1ADC_COMPMODE */
+#define WM8994_AIF1ADC_COMPMODE_SHIFT 1 /* AIF1ADC_COMPMODE */
+#define WM8994_AIF1ADC_COMPMODE_WIDTH 1 /* AIF1ADC_COMPMODE */
+#define WM8994_AIF1_LOOPBACK 0x0001 /* AIF1_LOOPBACK */
+#define WM8994_AIF1_LOOPBACK_MASK 0x0001 /* AIF1_LOOPBACK */
+#define WM8994_AIF1_LOOPBACK_SHIFT 0 /* AIF1_LOOPBACK */
+#define WM8994_AIF1_LOOPBACK_WIDTH 1 /* AIF1_LOOPBACK */
+
+/*
+ * R770 (0x302) - AIF1 Master/Slave
+ */
+#define WM8994_AIF1_TRI 0x8000 /* AIF1_TRI */
+#define WM8994_AIF1_TRI_MASK 0x8000 /* AIF1_TRI */
+#define WM8994_AIF1_TRI_SHIFT 15 /* AIF1_TRI */
+#define WM8994_AIF1_TRI_WIDTH 1 /* AIF1_TRI */
+#define WM8994_AIF1_MSTR 0x4000 /* AIF1_MSTR */
+#define WM8994_AIF1_MSTR_MASK 0x4000 /* AIF1_MSTR */
+#define WM8994_AIF1_MSTR_SHIFT 14 /* AIF1_MSTR */
+#define WM8994_AIF1_MSTR_WIDTH 1 /* AIF1_MSTR */
+#define WM8994_AIF1_CLK_FRC 0x2000 /* AIF1_CLK_FRC */
+#define WM8994_AIF1_CLK_FRC_MASK 0x2000 /* AIF1_CLK_FRC */
+#define WM8994_AIF1_CLK_FRC_SHIFT 13 /* AIF1_CLK_FRC */
+#define WM8994_AIF1_CLK_FRC_WIDTH 1 /* AIF1_CLK_FRC */
+#define WM8994_AIF1_LRCLK_FRC 0x1000 /* AIF1_LRCLK_FRC */
+#define WM8994_AIF1_LRCLK_FRC_MASK 0x1000 /* AIF1_LRCLK_FRC */
+#define WM8994_AIF1_LRCLK_FRC_SHIFT 12 /* AIF1_LRCLK_FRC */
+#define WM8994_AIF1_LRCLK_FRC_WIDTH 1 /* AIF1_LRCLK_FRC */
+
+/*
+ * R771 (0x303) - AIF1 BCLK
+ */
+#define WM8994_AIF1_BCLK_DIV_MASK 0x00F0 /* AIF1_BCLK_DIV - [7:4] */
+#define WM8994_AIF1_BCLK_DIV_SHIFT 4 /* AIF1_BCLK_DIV - [7:4] */
+#define WM8994_AIF1_BCLK_DIV_WIDTH 4 /* AIF1_BCLK_DIV - [7:4] */
+
+/*
+ * R772 (0x304) - AIF1ADC LRCLK
+ */
+#define WM8994_AIF1ADC_LRCLK_DIR 0x0800 /* AIF1ADC_LRCLK_DIR */
+#define WM8994_AIF1ADC_LRCLK_DIR_MASK 0x0800 /* AIF1ADC_LRCLK_DIR */
+#define WM8994_AIF1ADC_LRCLK_DIR_SHIFT 11 /* AIF1ADC_LRCLK_DIR */
+#define WM8994_AIF1ADC_LRCLK_DIR_WIDTH 1 /* AIF1ADC_LRCLK_DIR */
+#define WM8994_AIF1ADC_RATE_MASK 0x07FF /* AIF1ADC_RATE - [10:0] */
+#define WM8994_AIF1ADC_RATE_SHIFT 0 /* AIF1ADC_RATE - [10:0] */
+#define WM8994_AIF1ADC_RATE_WIDTH 11 /* AIF1ADC_RATE - [10:0] */
+
+/*
+ * R773 (0x305) - AIF1DAC LRCLK
+ */
+#define WM8994_AIF1DAC_LRCLK_DIR 0x0800 /* AIF1DAC_LRCLK_DIR */
+#define WM8994_AIF1DAC_LRCLK_DIR_MASK 0x0800 /* AIF1DAC_LRCLK_DIR */
+#define WM8994_AIF1DAC_LRCLK_DIR_SHIFT 11 /* AIF1DAC_LRCLK_DIR */
+#define WM8994_AIF1DAC_LRCLK_DIR_WIDTH 1 /* AIF1DAC_LRCLK_DIR */
+#define WM8994_AIF1DAC_RATE_MASK 0x07FF /* AIF1DAC_RATE - [10:0] */
+#define WM8994_AIF1DAC_RATE_SHIFT 0 /* AIF1DAC_RATE - [10:0] */
+#define WM8994_AIF1DAC_RATE_WIDTH 11 /* AIF1DAC_RATE - [10:0] */
+
+/*
+ * R774 (0x306) - AIF1DAC Data
+ */
+#define WM8994_AIF1DACL_DAT_INV 0x0002 /* AIF1DACL_DAT_INV */
+#define WM8994_AIF1DACL_DAT_INV_MASK 0x0002 /* AIF1DACL_DAT_INV */
+#define WM8994_AIF1DACL_DAT_INV_SHIFT 1 /* AIF1DACL_DAT_INV */
+#define WM8994_AIF1DACL_DAT_INV_WIDTH 1 /* AIF1DACL_DAT_INV */
+#define WM8994_AIF1DACR_DAT_INV 0x0001 /* AIF1DACR_DAT_INV */
+#define WM8994_AIF1DACR_DAT_INV_MASK 0x0001 /* AIF1DACR_DAT_INV */
+#define WM8994_AIF1DACR_DAT_INV_SHIFT 0 /* AIF1DACR_DAT_INV */
+#define WM8994_AIF1DACR_DAT_INV_WIDTH 1 /* AIF1DACR_DAT_INV */
+
+/*
+ * R775 (0x307) - AIF1ADC Data
+ */
+#define WM8994_AIF1ADCL_DAT_INV 0x0002 /* AIF1ADCL_DAT_INV */
+#define WM8994_AIF1ADCL_DAT_INV_MASK 0x0002 /* AIF1ADCL_DAT_INV */
+#define WM8994_AIF1ADCL_DAT_INV_SHIFT 1 /* AIF1ADCL_DAT_INV */
+#define WM8994_AIF1ADCL_DAT_INV_WIDTH 1 /* AIF1ADCL_DAT_INV */
+#define WM8994_AIF1ADCR_DAT_INV 0x0001 /* AIF1ADCR_DAT_INV */
+#define WM8994_AIF1ADCR_DAT_INV_MASK 0x0001 /* AIF1ADCR_DAT_INV */
+#define WM8994_AIF1ADCR_DAT_INV_SHIFT 0 /* AIF1ADCR_DAT_INV */
+#define WM8994_AIF1ADCR_DAT_INV_WIDTH 1 /* AIF1ADCR_DAT_INV */
+
+/*
+ * R784 (0x310) - AIF2 Control (1)
+ */
+#define WM8994_AIF2ADCL_SRC 0x8000 /* AIF2ADCL_SRC */
+#define WM8994_AIF2ADCL_SRC_MASK 0x8000 /* AIF2ADCL_SRC */
+#define WM8994_AIF2ADCL_SRC_SHIFT 15 /* AIF2ADCL_SRC */
+#define WM8994_AIF2ADCL_SRC_WIDTH 1 /* AIF2ADCL_SRC */
+#define WM8994_AIF2ADCR_SRC 0x4000 /* AIF2ADCR_SRC */
+#define WM8994_AIF2ADCR_SRC_MASK 0x4000 /* AIF2ADCR_SRC */
+#define WM8994_AIF2ADCR_SRC_SHIFT 14 /* AIF2ADCR_SRC */
+#define WM8994_AIF2ADCR_SRC_WIDTH 1 /* AIF2ADCR_SRC */
+#define WM8994_AIF2ADC_TDM 0x2000 /* AIF2ADC_TDM */
+#define WM8994_AIF2ADC_TDM_MASK 0x2000 /* AIF2ADC_TDM */
+#define WM8994_AIF2ADC_TDM_SHIFT 13 /* AIF2ADC_TDM */
+#define WM8994_AIF2ADC_TDM_WIDTH 1 /* AIF2ADC_TDM */
+#define WM8994_AIF2ADC_TDM_CHAN 0x1000 /* AIF2ADC_TDM_CHAN */
+#define WM8994_AIF2ADC_TDM_CHAN_MASK 0x1000 /* AIF2ADC_TDM_CHAN */
+#define WM8994_AIF2ADC_TDM_CHAN_SHIFT 12 /* AIF2ADC_TDM_CHAN */
+#define WM8994_AIF2ADC_TDM_CHAN_WIDTH 1 /* AIF2ADC_TDM_CHAN */
+#define WM8994_AIF2_BCLK_INV 0x0100 /* AIF2_BCLK_INV */
+#define WM8994_AIF2_BCLK_INV_MASK 0x0100 /* AIF2_BCLK_INV */
+#define WM8994_AIF2_BCLK_INV_SHIFT 8 /* AIF2_BCLK_INV */
+#define WM8994_AIF2_BCLK_INV_WIDTH 1 /* AIF2_BCLK_INV */
+#define WM8994_AIF2_LRCLK_INV 0x0080 /* AIF2_LRCLK_INV */
+#define WM8994_AIF2_LRCLK_INV_MASK 0x0080 /* AIF2_LRCLK_INV */
+#define WM8994_AIF2_LRCLK_INV_SHIFT 7 /* AIF2_LRCLK_INV */
+#define WM8994_AIF2_LRCLK_INV_WIDTH 1 /* AIF2_LRCLK_INV */
+#define WM8994_AIF2_WL_MASK 0x0060 /* AIF2_WL - [6:5] */
+#define WM8994_AIF2_WL_SHIFT 5 /* AIF2_WL - [6:5] */
+#define WM8994_AIF2_WL_WIDTH 2 /* AIF2_WL - [6:5] */
+#define WM8994_AIF2_FMT_MASK 0x0018 /* AIF2_FMT - [4:3] */
+#define WM8994_AIF2_FMT_SHIFT 3 /* AIF2_FMT - [4:3] */
+#define WM8994_AIF2_FMT_WIDTH 2 /* AIF2_FMT - [4:3] */
+
+/*
+ * R785 (0x311) - AIF2 Control (2)
+ */
+#define WM8994_AIF2DACL_SRC 0x8000 /* AIF2DACL_SRC */
+#define WM8994_AIF2DACL_SRC_MASK 0x8000 /* AIF2DACL_SRC */
+#define WM8994_AIF2DACL_SRC_SHIFT 15 /* AIF2DACL_SRC */
+#define WM8994_AIF2DACL_SRC_WIDTH 1 /* AIF2DACL_SRC */
+#define WM8994_AIF2DACR_SRC 0x4000 /* AIF2DACR_SRC */
+#define WM8994_AIF2DACR_SRC_MASK 0x4000 /* AIF2DACR_SRC */
+#define WM8994_AIF2DACR_SRC_SHIFT 14 /* AIF2DACR_SRC */
+#define WM8994_AIF2DACR_SRC_WIDTH 1 /* AIF2DACR_SRC */
+#define WM8994_AIF2DAC_TDM 0x2000 /* AIF2DAC_TDM */
+#define WM8994_AIF2DAC_TDM_MASK 0x2000 /* AIF2DAC_TDM */
+#define WM8994_AIF2DAC_TDM_SHIFT 13 /* AIF2DAC_TDM */
+#define WM8994_AIF2DAC_TDM_WIDTH 1 /* AIF2DAC_TDM */
+#define WM8994_AIF2DAC_TDM_CHAN 0x1000 /* AIF2DAC_TDM_CHAN */
+#define WM8994_AIF2DAC_TDM_CHAN_MASK 0x1000 /* AIF2DAC_TDM_CHAN */
+#define WM8994_AIF2DAC_TDM_CHAN_SHIFT 12 /* AIF2DAC_TDM_CHAN */
+#define WM8994_AIF2DAC_TDM_CHAN_WIDTH 1 /* AIF2DAC_TDM_CHAN */
+#define WM8994_AIF2DAC_BOOST_MASK 0x0C00 /* AIF2DAC_BOOST - [11:10] */
+#define WM8994_AIF2DAC_BOOST_SHIFT 10 /* AIF2DAC_BOOST - [11:10] */
+#define WM8994_AIF2DAC_BOOST_WIDTH 2 /* AIF2DAC_BOOST - [11:10] */
+#define WM8994_AIF2DAC_COMP 0x0010 /* AIF2DAC_COMP */
+#define WM8994_AIF2DAC_COMP_MASK 0x0010 /* AIF2DAC_COMP */
+#define WM8994_AIF2DAC_COMP_SHIFT 4 /* AIF2DAC_COMP */
+#define WM8994_AIF2DAC_COMP_WIDTH 1 /* AIF2DAC_COMP */
+#define WM8994_AIF2DAC_COMPMODE 0x0008 /* AIF2DAC_COMPMODE */
+#define WM8994_AIF2DAC_COMPMODE_MASK 0x0008 /* AIF2DAC_COMPMODE */
+#define WM8994_AIF2DAC_COMPMODE_SHIFT 3 /* AIF2DAC_COMPMODE */
+#define WM8994_AIF2DAC_COMPMODE_WIDTH 1 /* AIF2DAC_COMPMODE */
+#define WM8994_AIF2ADC_COMP 0x0004 /* AIF2ADC_COMP */
+#define WM8994_AIF2ADC_COMP_MASK 0x0004 /* AIF2ADC_COMP */
+#define WM8994_AIF2ADC_COMP_SHIFT 2 /* AIF2ADC_COMP */
+#define WM8994_AIF2ADC_COMP_WIDTH 1 /* AIF2ADC_COMP */
+#define WM8994_AIF2ADC_COMPMODE 0x0002 /* AIF2ADC_COMPMODE */
+#define WM8994_AIF2ADC_COMPMODE_MASK 0x0002 /* AIF2ADC_COMPMODE */
+#define WM8994_AIF2ADC_COMPMODE_SHIFT 1 /* AIF2ADC_COMPMODE */
+#define WM8994_AIF2ADC_COMPMODE_WIDTH 1 /* AIF2ADC_COMPMODE */
+#define WM8994_AIF2_LOOPBACK 0x0001 /* AIF2_LOOPBACK */
+#define WM8994_AIF2_LOOPBACK_MASK 0x0001 /* AIF2_LOOPBACK */
+#define WM8994_AIF2_LOOPBACK_SHIFT 0 /* AIF2_LOOPBACK */
+#define WM8994_AIF2_LOOPBACK_WIDTH 1 /* AIF2_LOOPBACK */
+
+/*
+ * R786 (0x312) - AIF2 Master/Slave
+ */
+#define WM8994_AIF2_TRI 0x8000 /* AIF2_TRI */
+#define WM8994_AIF2_TRI_MASK 0x8000 /* AIF2_TRI */
+#define WM8994_AIF2_TRI_SHIFT 15 /* AIF2_TRI */
+#define WM8994_AIF2_TRI_WIDTH 1 /* AIF2_TRI */
+#define WM8994_AIF2_MSTR 0x4000 /* AIF2_MSTR */
+#define WM8994_AIF2_MSTR_MASK 0x4000 /* AIF2_MSTR */
+#define WM8994_AIF2_MSTR_SHIFT 14 /* AIF2_MSTR */
+#define WM8994_AIF2_MSTR_WIDTH 1 /* AIF2_MSTR */
+#define WM8994_AIF2_CLK_FRC 0x2000 /* AIF2_CLK_FRC */
+#define WM8994_AIF2_CLK_FRC_MASK 0x2000 /* AIF2_CLK_FRC */
+#define WM8994_AIF2_CLK_FRC_SHIFT 13 /* AIF2_CLK_FRC */
+#define WM8994_AIF2_CLK_FRC_WIDTH 1 /* AIF2_CLK_FRC */
+#define WM8994_AIF2_LRCLK_FRC 0x1000 /* AIF2_LRCLK_FRC */
+#define WM8994_AIF2_LRCLK_FRC_MASK 0x1000 /* AIF2_LRCLK_FRC */
+#define WM8994_AIF2_LRCLK_FRC_SHIFT 12 /* AIF2_LRCLK_FRC */
+#define WM8994_AIF2_LRCLK_FRC_WIDTH 1 /* AIF2_LRCLK_FRC */
+
+/*
+ * R787 (0x313) - AIF2 BCLK
+ */
+#define WM8994_AIF2_BCLK_DIV_MASK 0x00F0 /* AIF2_BCLK_DIV - [7:4] */
+#define WM8994_AIF2_BCLK_DIV_SHIFT 4 /* AIF2_BCLK_DIV - [7:4] */
+#define WM8994_AIF2_BCLK_DIV_WIDTH 4 /* AIF2_BCLK_DIV - [7:4] */
+
+/*
+ * R788 (0x314) - AIF2ADC LRCLK
+ */
+#define WM8994_AIF2ADC_LRCLK_DIR 0x0800 /* AIF2ADC_LRCLK_DIR */
+#define WM8994_AIF2ADC_LRCLK_DIR_MASK 0x0800 /* AIF2ADC_LRCLK_DIR */
+#define WM8994_AIF2ADC_LRCLK_DIR_SHIFT 11 /* AIF2ADC_LRCLK_DIR */
+#define WM8994_AIF2ADC_LRCLK_DIR_WIDTH 1 /* AIF2ADC_LRCLK_DIR */
+#define WM8994_AIF2ADC_RATE_MASK 0x07FF /* AIF2ADC_RATE - [10:0] */
+#define WM8994_AIF2ADC_RATE_SHIFT 0 /* AIF2ADC_RATE - [10:0] */
+#define WM8994_AIF2ADC_RATE_WIDTH 11 /* AIF2ADC_RATE - [10:0] */
+
+/*
+ * R789 (0x315) - AIF2DAC LRCLK
+ */
+#define WM8994_AIF2DAC_LRCLK_DIR 0x0800 /* AIF2DAC_LRCLK_DIR */
+#define WM8994_AIF2DAC_LRCLK_DIR_MASK 0x0800 /* AIF2DAC_LRCLK_DIR */
+#define WM8994_AIF2DAC_LRCLK_DIR_SHIFT 11 /* AIF2DAC_LRCLK_DIR */
+#define WM8994_AIF2DAC_LRCLK_DIR_WIDTH 1 /* AIF2DAC_LRCLK_DIR */
+#define WM8994_AIF2DAC_RATE_MASK 0x07FF /* AIF2DAC_RATE - [10:0] */
+#define WM8994_AIF2DAC_RATE_SHIFT 0 /* AIF2DAC_RATE - [10:0] */
+#define WM8994_AIF2DAC_RATE_WIDTH 11 /* AIF2DAC_RATE - [10:0] */
+
+/*
+ * R790 (0x316) - AIF2DAC Data
+ */
+#define WM8994_AIF2DACL_DAT_INV 0x0002 /* AIF2DACL_DAT_INV */
+#define WM8994_AIF2DACL_DAT_INV_MASK 0x0002 /* AIF2DACL_DAT_INV */
+#define WM8994_AIF2DACL_DAT_INV_SHIFT 1 /* AIF2DACL_DAT_INV */
+#define WM8994_AIF2DACL_DAT_INV_WIDTH 1 /* AIF2DACL_DAT_INV */
+#define WM8994_AIF2DACR_DAT_INV 0x0001 /* AIF2DACR_DAT_INV */
+#define WM8994_AIF2DACR_DAT_INV_MASK 0x0001 /* AIF2DACR_DAT_INV */
+#define WM8994_AIF2DACR_DAT_INV_SHIFT 0 /* AIF2DACR_DAT_INV */
+#define WM8994_AIF2DACR_DAT_INV_WIDTH 1 /* AIF2DACR_DAT_INV */
+
+/*
+ * R791 (0x317) - AIF2ADC Data
+ */
+#define WM8994_AIF2ADCL_DAT_INV 0x0002 /* AIF2ADCL_DAT_INV */
+#define WM8994_AIF2ADCL_DAT_INV_MASK 0x0002 /* AIF2ADCL_DAT_INV */
+#define WM8994_AIF2ADCL_DAT_INV_SHIFT 1 /* AIF2ADCL_DAT_INV */
+#define WM8994_AIF2ADCL_DAT_INV_WIDTH 1 /* AIF2ADCL_DAT_INV */
+#define WM8994_AIF2ADCR_DAT_INV 0x0001 /* AIF2ADCR_DAT_INV */
+#define WM8994_AIF2ADCR_DAT_INV_MASK 0x0001 /* AIF2ADCR_DAT_INV */
+#define WM8994_AIF2ADCR_DAT_INV_SHIFT 0 /* AIF2ADCR_DAT_INV */
+#define WM8994_AIF2ADCR_DAT_INV_WIDTH 1 /* AIF2ADCR_DAT_INV */
+
+/*
+ * R1024 (0x400) - AIF1 ADC1 Left Volume
+ */
+#define WM8994_AIF1ADC1_VU 0x0100 /* AIF1ADC1_VU */
+#define WM8994_AIF1ADC1_VU_MASK 0x0100 /* AIF1ADC1_VU */
+#define WM8994_AIF1ADC1_VU_SHIFT 8 /* AIF1ADC1_VU */
+#define WM8994_AIF1ADC1_VU_WIDTH 1 /* AIF1ADC1_VU */
+#define WM8994_AIF1ADC1L_VOL_MASK 0x00FF /* AIF1ADC1L_VOL - [7:0] */
+#define WM8994_AIF1ADC1L_VOL_SHIFT 0 /* AIF1ADC1L_VOL - [7:0] */
+#define WM8994_AIF1ADC1L_VOL_WIDTH 8 /* AIF1ADC1L_VOL - [7:0] */
+
+/*
+ * R1025 (0x401) - AIF1 ADC1 Right Volume
+ */
+#define WM8994_AIF1ADC1_VU 0x0100 /* AIF1ADC1_VU */
+#define WM8994_AIF1ADC1_VU_MASK 0x0100 /* AIF1ADC1_VU */
+#define WM8994_AIF1ADC1_VU_SHIFT 8 /* AIF1ADC1_VU */
+#define WM8994_AIF1ADC1_VU_WIDTH 1 /* AIF1ADC1_VU */
+#define WM8994_AIF1ADC1R_VOL_MASK 0x00FF /* AIF1ADC1R_VOL - [7:0] */
+#define WM8994_AIF1ADC1R_VOL_SHIFT 0 /* AIF1ADC1R_VOL - [7:0] */
+#define WM8994_AIF1ADC1R_VOL_WIDTH 8 /* AIF1ADC1R_VOL - [7:0] */
+
+/*
+ * R1026 (0x402) - AIF1 DAC1 Left Volume
+ */
+#define WM8994_AIF1DAC1_VU 0x0100 /* AIF1DAC1_VU */
+#define WM8994_AIF1DAC1_VU_MASK 0x0100 /* AIF1DAC1_VU */
+#define WM8994_AIF1DAC1_VU_SHIFT 8 /* AIF1DAC1_VU */
+#define WM8994_AIF1DAC1_VU_WIDTH 1 /* AIF1DAC1_VU */
+#define WM8994_AIF1DAC1L_VOL_MASK 0x00FF /* AIF1DAC1L_VOL - [7:0] */
+#define WM8994_AIF1DAC1L_VOL_SHIFT 0 /* AIF1DAC1L_VOL - [7:0] */
+#define WM8994_AIF1DAC1L_VOL_WIDTH 8 /* AIF1DAC1L_VOL - [7:0] */
+
+/*
+ * R1027 (0x403) - AIF1 DAC1 Right Volume
+ */
+#define WM8994_AIF1DAC1_VU 0x0100 /* AIF1DAC1_VU */
+#define WM8994_AIF1DAC1_VU_MASK 0x0100 /* AIF1DAC1_VU */
+#define WM8994_AIF1DAC1_VU_SHIFT 8 /* AIF1DAC1_VU */
+#define WM8994_AIF1DAC1_VU_WIDTH 1 /* AIF1DAC1_VU */
+#define WM8994_AIF1DAC1R_VOL_MASK 0x00FF /* AIF1DAC1R_VOL - [7:0] */
+#define WM8994_AIF1DAC1R_VOL_SHIFT 0 /* AIF1DAC1R_VOL - [7:0] */
+#define WM8994_AIF1DAC1R_VOL_WIDTH 8 /* AIF1DAC1R_VOL - [7:0] */
+
+/*
+ * R1028 (0x404) - AIF1 ADC2 Left Volume
+ */
+#define WM8994_AIF1ADC2_VU 0x0100 /* AIF1ADC2_VU */
+#define WM8994_AIF1ADC2_VU_MASK 0x0100 /* AIF1ADC2_VU */
+#define WM8994_AIF1ADC2_VU_SHIFT 8 /* AIF1ADC2_VU */
+#define WM8994_AIF1ADC2_VU_WIDTH 1 /* AIF1ADC2_VU */
+#define WM8994_AIF1ADC2L_VOL_MASK 0x00FF /* AIF1ADC2L_VOL - [7:0] */
+#define WM8994_AIF1ADC2L_VOL_SHIFT 0 /* AIF1ADC2L_VOL - [7:0] */
+#define WM8994_AIF1ADC2L_VOL_WIDTH 8 /* AIF1ADC2L_VOL - [7:0] */
+
+/*
+ * R1029 (0x405) - AIF1 ADC2 Right Volume
+ */
+#define WM8994_AIF1ADC2_VU 0x0100 /* AIF1ADC2_VU */
+#define WM8994_AIF1ADC2_VU_MASK 0x0100 /* AIF1ADC2_VU */
+#define WM8994_AIF1ADC2_VU_SHIFT 8 /* AIF1ADC2_VU */
+#define WM8994_AIF1ADC2_VU_WIDTH 1 /* AIF1ADC2_VU */
+#define WM8994_AIF1ADC2R_VOL_MASK 0x00FF /* AIF1ADC2R_VOL - [7:0] */
+#define WM8994_AIF1ADC2R_VOL_SHIFT 0 /* AIF1ADC2R_VOL - [7:0] */
+#define WM8994_AIF1ADC2R_VOL_WIDTH 8 /* AIF1ADC2R_VOL - [7:0] */
+
+/*
+ * R1030 (0x406) - AIF1 DAC2 Left Volume
+ */
+#define WM8994_AIF1DAC2_VU 0x0100 /* AIF1DAC2_VU */
+#define WM8994_AIF1DAC2_VU_MASK 0x0100 /* AIF1DAC2_VU */
+#define WM8994_AIF1DAC2_VU_SHIFT 8 /* AIF1DAC2_VU */
+#define WM8994_AIF1DAC2_VU_WIDTH 1 /* AIF1DAC2_VU */
+#define WM8994_AIF1DAC2L_VOL_MASK 0x00FF /* AIF1DAC2L_VOL - [7:0] */
+#define WM8994_AIF1DAC2L_VOL_SHIFT 0 /* AIF1DAC2L_VOL - [7:0] */
+#define WM8994_AIF1DAC2L_VOL_WIDTH 8 /* AIF1DAC2L_VOL - [7:0] */
+
+/*
+ * R1031 (0x407) - AIF1 DAC2 Right Volume
+ */
+#define WM8994_AIF1DAC2_VU 0x0100 /* AIF1DAC2_VU */
+#define WM8994_AIF1DAC2_VU_MASK 0x0100 /* AIF1DAC2_VU */
+#define WM8994_AIF1DAC2_VU_SHIFT 8 /* AIF1DAC2_VU */
+#define WM8994_AIF1DAC2_VU_WIDTH 1 /* AIF1DAC2_VU */
+#define WM8994_AIF1DAC2R_VOL_MASK 0x00FF /* AIF1DAC2R_VOL - [7:0] */
+#define WM8994_AIF1DAC2R_VOL_SHIFT 0 /* AIF1DAC2R_VOL - [7:0] */
+#define WM8994_AIF1DAC2R_VOL_WIDTH 8 /* AIF1DAC2R_VOL - [7:0] */
+
+/*
+ * R1040 (0x410) - AIF1 ADC1 Filters
+ */
+#define WM8994_AIF1ADC1_HPF_CUT_MASK 0x6000 /* AIF1ADC1_HPF_CUT - [14:13] */
+#define WM8994_AIF1ADC1_HPF_CUT_SHIFT 13 /* AIF1ADC1_HPF_CUT - [14:13] */
+#define WM8994_AIF1ADC1_HPF_CUT_WIDTH 2 /* AIF1ADC1_HPF_CUT - [14:13] */
+#define WM8994_AIF1ADC1L_HPF 0x1000 /* AIF1ADC1L_HPF */
+#define WM8994_AIF1ADC1L_HPF_MASK 0x1000 /* AIF1ADC1L_HPF */
+#define WM8994_AIF1ADC1L_HPF_SHIFT 12 /* AIF1ADC1L_HPF */
+#define WM8994_AIF1ADC1L_HPF_WIDTH 1 /* AIF1ADC1L_HPF */
+#define WM8994_AIF1ADC1R_HPF 0x0800 /* AIF1ADC1R_HPF */
+#define WM8994_AIF1ADC1R_HPF_MASK 0x0800 /* AIF1ADC1R_HPF */
+#define WM8994_AIF1ADC1R_HPF_SHIFT 11 /* AIF1ADC1R_HPF */
+#define WM8994_AIF1ADC1R_HPF_WIDTH 1 /* AIF1ADC1R_HPF */
+
+/*
+ * R1041 (0x411) - AIF1 ADC2 Filters
+ */
+#define WM8994_AIF1ADC2_HPF_CUT_MASK 0x6000 /* AIF1ADC2_HPF_CUT - [14:13] */
+#define WM8994_AIF1ADC2_HPF_CUT_SHIFT 13 /* AIF1ADC2_HPF_CUT - [14:13] */
+#define WM8994_AIF1ADC2_HPF_CUT_WIDTH 2 /* AIF1ADC2_HPF_CUT - [14:13] */
+#define WM8994_AIF1ADC2L_HPF 0x1000 /* AIF1ADC2L_HPF */
+#define WM8994_AIF1ADC2L_HPF_MASK 0x1000 /* AIF1ADC2L_HPF */
+#define WM8994_AIF1ADC2L_HPF_SHIFT 12 /* AIF1ADC2L_HPF */
+#define WM8994_AIF1ADC2L_HPF_WIDTH 1 /* AIF1ADC2L_HPF */
+#define WM8994_AIF1ADC2R_HPF 0x0800 /* AIF1ADC2R_HPF */
+#define WM8994_AIF1ADC2R_HPF_MASK 0x0800 /* AIF1ADC2R_HPF */
+#define WM8994_AIF1ADC2R_HPF_SHIFT 11 /* AIF1ADC2R_HPF */
+#define WM8994_AIF1ADC2R_HPF_WIDTH 1 /* AIF1ADC2R_HPF */
+
+/*
+ * R1056 (0x420) - AIF1 DAC1 Filters (1)
+ */
+ #define WM8994_AIF1DAC1_UNMUTE 0x0000 /* AIF1DAC1_MUTE */
+#define WM8994_AIF1DAC1_MUTE 0x0200 /* AIF1DAC1_MUTE */
+#define WM8994_AIF1DAC1_MUTE_MASK 0x0200 /* AIF1DAC1_MUTE */
+#define WM8994_AIF1DAC1_MUTE_SHIFT 9 /* AIF1DAC1_MUTE */
+#define WM8994_AIF1DAC1_MUTE_WIDTH 1 /* AIF1DAC1_MUTE */
+#define WM8994_AIF1DAC1_MONO 0x0080 /* AIF1DAC1_MONO */
+#define WM8994_AIF1DAC1_MONO_MASK 0x0080 /* AIF1DAC1_MONO */
+#define WM8994_AIF1DAC1_MONO_SHIFT 7 /* AIF1DAC1_MONO */
+#define WM8994_AIF1DAC1_MONO_WIDTH 1 /* AIF1DAC1_MONO */
+#define WM8994_AIF1DAC1_MUTERATE 0x0020 /* AIF1DAC1_MUTERATE */
+#define WM8994_AIF1DAC1_MUTERATE_MASK 0x0020 /* AIF1DAC1_MUTERATE */
+#define WM8994_AIF1DAC1_MUTERATE_SHIFT 5 /* AIF1DAC1_MUTERATE */
+#define WM8994_AIF1DAC1_MUTERATE_WIDTH 1 /* AIF1DAC1_MUTERATE */
+#define WM8994_AIF1DAC1_UNMUTE_RAMP 0x0010 /* AIF1DAC1_UNMUTE_RAMP */
+#define WM8994_AIF1DAC1_UNMUTE_RAMP_MASK 0x0010 /* AIF1DAC1_UNMUTE_RAMP */
+#define WM8994_AIF1DAC1_UNMUTE_RAMP_SHIFT 4 /* AIF1DAC1_UNMUTE_RAMP */
+#define WM8994_AIF1DAC1_UNMUTE_RAMP_WIDTH 1 /* AIF1DAC1_UNMUTE_RAMP */
+#define WM8994_AIF1DAC1_DEEMP_MASK 0x0006 /* AIF1DAC1_DEEMP - [2:1] */
+#define WM8994_AIF1DAC1_DEEMP_SHIFT 1 /* AIF1DAC1_DEEMP - [2:1] */
+#define WM8994_AIF1DAC1_DEEMP_WIDTH 2 /* AIF1DAC1_DEEMP - [2:1] */
+
+/*
+ * R1057 (0x421) - AIF1 DAC1 Filters (2)
+ */
+#define WM8994_AIF1DAC1_3D_GAIN_MASK 0x3E00 /* AIF1DAC1_3D_GAIN - [13:9] */
+#define WM8994_AIF1DAC1_3D_GAIN_SHIFT 9 /* AIF1DAC1_3D_GAIN - [13:9] */
+#define WM8994_AIF1DAC1_3D_GAIN_WIDTH 5 /* AIF1DAC1_3D_GAIN - [13:9] */
+#define WM8994_AIF1DAC1_3D_ENA 0x0100 /* AIF1DAC1_3D_ENA */
+#define WM8994_AIF1DAC1_3D_ENA_MASK 0x0100 /* AIF1DAC1_3D_ENA */
+#define WM8994_AIF1DAC1_3D_ENA_SHIFT 8 /* AIF1DAC1_3D_ENA */
+#define WM8994_AIF1DAC1_3D_ENA_WIDTH 1 /* AIF1DAC1_3D_ENA */
+
+/*
+ * R1058 (0x422) - AIF1 DAC2 Filters (1)
+ */
+ #define WM8994_AIF1DAC2_UNMUTE 0x0000 /* AIF1DAC2_MUTE */
+#define WM8994_AIF1DAC2_MUTE 0x0200 /* AIF1DAC2_MUTE */
+#define WM8994_AIF1DAC2_MUTE_MASK 0x0200 /* AIF1DAC2_MUTE */
+#define WM8994_AIF1DAC2_MUTE_SHIFT 9 /* AIF1DAC2_MUTE */
+#define WM8994_AIF1DAC2_MUTE_WIDTH 1 /* AIF1DAC2_MUTE */
+#define WM8994_AIF1DAC2_MONO 0x0080 /* AIF1DAC2_MONO */
+#define WM8994_AIF1DAC2_MONO_MASK 0x0080 /* AIF1DAC2_MONO */
+#define WM8994_AIF1DAC2_MONO_SHIFT 7 /* AIF1DAC2_MONO */
+#define WM8994_AIF1DAC2_MONO_WIDTH 1 /* AIF1DAC2_MONO */
+#define WM8994_AIF1DAC2_MUTERATE 0x0020 /* AIF1DAC2_MUTERATE */
+#define WM8994_AIF1DAC2_MUTERATE_MASK 0x0020 /* AIF1DAC2_MUTERATE */
+#define WM8994_AIF1DAC2_MUTERATE_SHIFT 5 /* AIF1DAC2_MUTERATE */
+#define WM8994_AIF1DAC2_MUTERATE_WIDTH 1 /* AIF1DAC2_MUTERATE */
+#define WM8994_AIF1DAC2_UNMUTE_RAMP 0x0010 /* AIF1DAC2_UNMUTE_RAMP */
+#define WM8994_AIF1DAC2_UNMUTE_RAMP_MASK 0x0010 /* AIF1DAC2_UNMUTE_RAMP */
+#define WM8994_AIF1DAC2_UNMUTE_RAMP_SHIFT 4 /* AIF1DAC2_UNMUTE_RAMP */
+#define WM8994_AIF1DAC2_UNMUTE_RAMP_WIDTH 1 /* AIF1DAC2_UNMUTE_RAMP */
+#define WM8994_AIF1DAC2_DEEMP_MASK 0x0006 /* AIF1DAC2_DEEMP - [2:1] */
+#define WM8994_AIF1DAC2_DEEMP_SHIFT 1 /* AIF1DAC2_DEEMP - [2:1] */
+#define WM8994_AIF1DAC2_DEEMP_WIDTH 2 /* AIF1DAC2_DEEMP - [2:1] */
+
+/*
+ * R1059 (0x423) - AIF1 DAC2 Filters (2)
+ */
+#define WM8994_AIF1DAC2_3D_GAIN_MASK 0x3E00 /* AIF1DAC2_3D_GAIN - [13:9] */
+#define WM8994_AIF1DAC2_3D_GAIN_SHIFT 9 /* AIF1DAC2_3D_GAIN - [13:9] */
+#define WM8994_AIF1DAC2_3D_GAIN_WIDTH 5 /* AIF1DAC2_3D_GAIN - [13:9] */
+#define WM8994_AIF1DAC2_3D_ENA 0x0100 /* AIF1DAC2_3D_ENA */
+#define WM8994_AIF1DAC2_3D_ENA_MASK 0x0100 /* AIF1DAC2_3D_ENA */
+#define WM8994_AIF1DAC2_3D_ENA_SHIFT 8 /* AIF1DAC2_3D_ENA */
+#define WM8994_AIF1DAC2_3D_ENA_WIDTH 1 /* AIF1DAC2_3D_ENA */
+
+/*
+ * R1088 (0x440) - AIF1 DRC1 (1)
+ */
+#define WM8994_AIF1DRC1_SIG_DET_RMS_MASK 0xF800 /* AIF1DRC1_SIG_DET_RMS - [15:11] */
+#define WM8994_AIF1DRC1_SIG_DET_RMS_SHIFT 11 /* AIF1DRC1_SIG_DET_RMS - [15:11] */
+#define WM8994_AIF1DRC1_SIG_DET_RMS_WIDTH 5 /* AIF1DRC1_SIG_DET_RMS - [15:11] */
+#define WM8994_AIF1DRC1_SIG_DET_PK_MASK 0x0600 /* AIF1DRC1_SIG_DET_PK - [10:9] */
+#define WM8994_AIF1DRC1_SIG_DET_PK_SHIFT 9 /* AIF1DRC1_SIG_DET_PK - [10:9] */
+#define WM8994_AIF1DRC1_SIG_DET_PK_WIDTH 2 /* AIF1DRC1_SIG_DET_PK - [10:9] */
+#define WM8994_AIF1DRC1_NG_ENA 0x0100 /* AIF1DRC1_NG_ENA */
+#define WM8994_AIF1DRC1_NG_ENA_MASK 0x0100 /* AIF1DRC1_NG_ENA */
+#define WM8994_AIF1DRC1_NG_ENA_SHIFT 8 /* AIF1DRC1_NG_ENA */
+#define WM8994_AIF1DRC1_NG_ENA_WIDTH 1 /* AIF1DRC1_NG_ENA */
+#define WM8994_AIF1DRC1_SIG_DET_MODE 0x0080 /* AIF1DRC1_SIG_DET_MODE */
+#define WM8994_AIF1DRC1_SIG_DET_MODE_MASK 0x0080 /* AIF1DRC1_SIG_DET_MODE */
+#define WM8994_AIF1DRC1_SIG_DET_MODE_SHIFT 7 /* AIF1DRC1_SIG_DET_MODE */
+#define WM8994_AIF1DRC1_SIG_DET_MODE_WIDTH 1 /* AIF1DRC1_SIG_DET_MODE */
+#define WM8994_AIF1DRC1_SIG_DET 0x0040 /* AIF1DRC1_SIG_DET */
+#define WM8994_AIF1DRC1_SIG_DET_MASK 0x0040 /* AIF1DRC1_SIG_DET */
+#define WM8994_AIF1DRC1_SIG_DET_SHIFT 6 /* AIF1DRC1_SIG_DET */
+#define WM8994_AIF1DRC1_SIG_DET_WIDTH 1 /* AIF1DRC1_SIG_DET */
+#define WM8994_AIF1DRC1_KNEE2_OP_ENA 0x0020 /* AIF1DRC1_KNEE2_OP_ENA */
+#define WM8994_AIF1DRC1_KNEE2_OP_ENA_MASK 0x0020 /* AIF1DRC1_KNEE2_OP_ENA */
+#define WM8994_AIF1DRC1_KNEE2_OP_ENA_SHIFT 5 /* AIF1DRC1_KNEE2_OP_ENA */
+#define WM8994_AIF1DRC1_KNEE2_OP_ENA_WIDTH 1 /* AIF1DRC1_KNEE2_OP_ENA */
+#define WM8994_AIF1DRC1_QR 0x0010 /* AIF1DRC1_QR */
+#define WM8994_AIF1DRC1_QR_MASK 0x0010 /* AIF1DRC1_QR */
+#define WM8994_AIF1DRC1_QR_SHIFT 4 /* AIF1DRC1_QR */
+#define WM8994_AIF1DRC1_QR_WIDTH 1 /* AIF1DRC1_QR */
+#define WM8994_AIF1DRC1_ANTICLIP 0x0008 /* AIF1DRC1_ANTICLIP */
+#define WM8994_AIF1DRC1_ANTICLIP_MASK 0x0008 /* AIF1DRC1_ANTICLIP */
+#define WM8994_AIF1DRC1_ANTICLIP_SHIFT 3 /* AIF1DRC1_ANTICLIP */
+#define WM8994_AIF1DRC1_ANTICLIP_WIDTH 1 /* AIF1DRC1_ANTICLIP */
+#define WM8994_AIF1DAC1_DRC_ENA 0x0004 /* AIF1DAC1_DRC_ENA */
+#define WM8994_AIF1DAC1_DRC_ENA_MASK 0x0004 /* AIF1DAC1_DRC_ENA */
+#define WM8994_AIF1DAC1_DRC_ENA_SHIFT 2 /* AIF1DAC1_DRC_ENA */
+#define WM8994_AIF1DAC1_DRC_ENA_WIDTH 1 /* AIF1DAC1_DRC_ENA */
+#define WM8994_AIF1ADC1L_DRC_ENA 0x0002 /* AIF1ADC1L_DRC_ENA */
+#define WM8994_AIF1ADC1L_DRC_ENA_MASK 0x0002 /* AIF1ADC1L_DRC_ENA */
+#define WM8994_AIF1ADC1L_DRC_ENA_SHIFT 1 /* AIF1ADC1L_DRC_ENA */
+#define WM8994_AIF1ADC1L_DRC_ENA_WIDTH 1 /* AIF1ADC1L_DRC_ENA */
+#define WM8994_AIF1ADC1R_DRC_ENA 0x0001 /* AIF1ADC1R_DRC_ENA */
+#define WM8994_AIF1ADC1R_DRC_ENA_MASK 0x0001 /* AIF1ADC1R_DRC_ENA */
+#define WM8994_AIF1ADC1R_DRC_ENA_SHIFT 0 /* AIF1ADC1R_DRC_ENA */
+#define WM8994_AIF1ADC1R_DRC_ENA_WIDTH 1 /* AIF1ADC1R_DRC_ENA */
+
+/*
+ * R1089 (0x441) - AIF1 DRC1 (2)
+ */
+#define WM8994_AIF1DRC1_ATK_MASK 0x1E00 /* AIF1DRC1_ATK - [12:9] */
+#define WM8994_AIF1DRC1_ATK_SHIFT 9 /* AIF1DRC1_ATK - [12:9] */
+#define WM8994_AIF1DRC1_ATK_WIDTH 4 /* AIF1DRC1_ATK - [12:9] */
+#define WM8994_AIF1DRC1_DCY_MASK 0x01E0 /* AIF1DRC1_DCY - [8:5] */
+#define WM8994_AIF1DRC1_DCY_SHIFT 5 /* AIF1DRC1_DCY - [8:5] */
+#define WM8994_AIF1DRC1_DCY_WIDTH 4 /* AIF1DRC1_DCY - [8:5] */
+#define WM8994_AIF1DRC1_MINGAIN_MASK 0x001C /* AIF1DRC1_MINGAIN - [4:2] */
+#define WM8994_AIF1DRC1_MINGAIN_SHIFT 2 /* AIF1DRC1_MINGAIN - [4:2] */
+#define WM8994_AIF1DRC1_MINGAIN_WIDTH 3 /* AIF1DRC1_MINGAIN - [4:2] */
+#define WM8994_AIF1DRC1_MAXGAIN_MASK 0x0003 /* AIF1DRC1_MAXGAIN - [1:0] */
+#define WM8994_AIF1DRC1_MAXGAIN_SHIFT 0 /* AIF1DRC1_MAXGAIN - [1:0] */
+#define WM8994_AIF1DRC1_MAXGAIN_WIDTH 2 /* AIF1DRC1_MAXGAIN - [1:0] */
+
+/*
+ * R1090 (0x442) - AIF1 DRC1 (3)
+ */
+#define WM8994_AIF1DRC1_NG_MINGAIN_MASK 0xF000 /* AIF1DRC1_NG_MINGAIN - [15:12] */
+#define WM8994_AIF1DRC1_NG_MINGAIN_SHIFT 12 /* AIF1DRC1_NG_MINGAIN - [15:12] */
+#define WM8994_AIF1DRC1_NG_MINGAIN_WIDTH 4 /* AIF1DRC1_NG_MINGAIN - [15:12] */
+#define WM8994_AIF1DRC1_NG_EXP_MASK 0x0C00 /* AIF1DRC1_NG_EXP - [11:10] */
+#define WM8994_AIF1DRC1_NG_EXP_SHIFT 10 /* AIF1DRC1_NG_EXP - [11:10] */
+#define WM8994_AIF1DRC1_NG_EXP_WIDTH 2 /* AIF1DRC1_NG_EXP - [11:10] */
+#define WM8994_AIF1DRC1_QR_THR_MASK 0x0300 /* AIF1DRC1_QR_THR - [9:8] */
+#define WM8994_AIF1DRC1_QR_THR_SHIFT 8 /* AIF1DRC1_QR_THR - [9:8] */
+#define WM8994_AIF1DRC1_QR_THR_WIDTH 2 /* AIF1DRC1_QR_THR - [9:8] */
+#define WM8994_AIF1DRC1_QR_DCY_MASK 0x00C0 /* AIF1DRC1_QR_DCY - [7:6] */
+#define WM8994_AIF1DRC1_QR_DCY_SHIFT 6 /* AIF1DRC1_QR_DCY - [7:6] */
+#define WM8994_AIF1DRC1_QR_DCY_WIDTH 2 /* AIF1DRC1_QR_DCY - [7:6] */
+#define WM8994_AIF1DRC1_HI_COMP_MASK 0x0038 /* AIF1DRC1_HI_COMP - [5:3] */
+#define WM8994_AIF1DRC1_HI_COMP_SHIFT 3 /* AIF1DRC1_HI_COMP - [5:3] */
+#define WM8994_AIF1DRC1_HI_COMP_WIDTH 3 /* AIF1DRC1_HI_COMP - [5:3] */
+#define WM8994_AIF1DRC1_LO_COMP_MASK 0x0007 /* AIF1DRC1_LO_COMP - [2:0] */
+#define WM8994_AIF1DRC1_LO_COMP_SHIFT 0 /* AIF1DRC1_LO_COMP - [2:0] */
+#define WM8994_AIF1DRC1_LO_COMP_WIDTH 3 /* AIF1DRC1_LO_COMP - [2:0] */
+
+/*
+ * R1091 (0x443) - AIF1 DRC1 (4)
+ */
+#define WM8994_AIF1DRC1_KNEE_IP_MASK 0x07E0 /* AIF1DRC1_KNEE_IP - [10:5] */
+#define WM8994_AIF1DRC1_KNEE_IP_SHIFT 5 /* AIF1DRC1_KNEE_IP - [10:5] */
+#define WM8994_AIF1DRC1_KNEE_IP_WIDTH 6 /* AIF1DRC1_KNEE_IP - [10:5] */
+#define WM8994_AIF1DRC1_KNEE_OP_MASK 0x001F /* AIF1DRC1_KNEE_OP - [4:0] */
+#define WM8994_AIF1DRC1_KNEE_OP_SHIFT 0 /* AIF1DRC1_KNEE_OP - [4:0] */
+#define WM8994_AIF1DRC1_KNEE_OP_WIDTH 5 /* AIF1DRC1_KNEE_OP - [4:0] */
+
+/*
+ * R1092 (0x444) - AIF1 DRC1 (5)
+ */
+#define WM8994_AIF1DRC1_KNEE2_IP_MASK 0x03E0 /* AIF1DRC1_KNEE2_IP - [9:5] */
+#define WM8994_AIF1DRC1_KNEE2_IP_SHIFT 5 /* AIF1DRC1_KNEE2_IP - [9:5] */
+#define WM8994_AIF1DRC1_KNEE2_IP_WIDTH 5 /* AIF1DRC1_KNEE2_IP - [9:5] */
+#define WM8994_AIF1DRC1_KNEE2_OP_MASK 0x001F /* AIF1DRC1_KNEE2_OP - [4:0] */
+#define WM8994_AIF1DRC1_KNEE2_OP_SHIFT 0 /* AIF1DRC1_KNEE2_OP - [4:0] */
+#define WM8994_AIF1DRC1_KNEE2_OP_WIDTH 5 /* AIF1DRC1_KNEE2_OP - [4:0] */
+
+/*
+ * R1104 (0x450) - AIF1 DRC2 (1)
+ */
+#define WM8994_AIF1DRC2_SIG_DET_RMS_MASK 0xF800 /* AIF1DRC2_SIG_DET_RMS - [15:11] */
+#define WM8994_AIF1DRC2_SIG_DET_RMS_SHIFT 11 /* AIF1DRC2_SIG_DET_RMS - [15:11] */
+#define WM8994_AIF1DRC2_SIG_DET_RMS_WIDTH 5 /* AIF1DRC2_SIG_DET_RMS - [15:11] */
+#define WM8994_AIF1DRC2_SIG_DET_PK_MASK 0x0600 /* AIF1DRC2_SIG_DET_PK - [10:9] */
+#define WM8994_AIF1DRC2_SIG_DET_PK_SHIFT 9 /* AIF1DRC2_SIG_DET_PK - [10:9] */
+#define WM8994_AIF1DRC2_SIG_DET_PK_WIDTH 2 /* AIF1DRC2_SIG_DET_PK - [10:9] */
+#define WM8994_AIF1DRC2_NG_ENA 0x0100 /* AIF1DRC2_NG_ENA */
+#define WM8994_AIF1DRC2_NG_ENA_MASK 0x0100 /* AIF1DRC2_NG_ENA */
+#define WM8994_AIF1DRC2_NG_ENA_SHIFT 8 /* AIF1DRC2_NG_ENA */
+#define WM8994_AIF1DRC2_NG_ENA_WIDTH 1 /* AIF1DRC2_NG_ENA */
+#define WM8994_AIF1DRC2_SIG_DET_MODE 0x0080 /* AIF1DRC2_SIG_DET_MODE */
+#define WM8994_AIF1DRC2_SIG_DET_MODE_MASK 0x0080 /* AIF1DRC2_SIG_DET_MODE */
+#define WM8994_AIF1DRC2_SIG_DET_MODE_SHIFT 7 /* AIF1DRC2_SIG_DET_MODE */
+#define WM8994_AIF1DRC2_SIG_DET_MODE_WIDTH 1 /* AIF1DRC2_SIG_DET_MODE */
+#define WM8994_AIF1DRC2_SIG_DET 0x0040 /* AIF1DRC2_SIG_DET */
+#define WM8994_AIF1DRC2_SIG_DET_MASK 0x0040 /* AIF1DRC2_SIG_DET */
+#define WM8994_AIF1DRC2_SIG_DET_SHIFT 6 /* AIF1DRC2_SIG_DET */
+#define WM8994_AIF1DRC2_SIG_DET_WIDTH 1 /* AIF1DRC2_SIG_DET */
+#define WM8994_AIF1DRC2_KNEE2_OP_ENA 0x0020 /* AIF1DRC2_KNEE2_OP_ENA */
+#define WM8994_AIF1DRC2_KNEE2_OP_ENA_MASK 0x0020 /* AIF1DRC2_KNEE2_OP_ENA */
+#define WM8994_AIF1DRC2_KNEE2_OP_ENA_SHIFT 5 /* AIF1DRC2_KNEE2_OP_ENA */
+#define WM8994_AIF1DRC2_KNEE2_OP_ENA_WIDTH 1 /* AIF1DRC2_KNEE2_OP_ENA */
+#define WM8994_AIF1DRC2_QR 0x0010 /* AIF1DRC2_QR */
+#define WM8994_AIF1DRC2_QR_MASK 0x0010 /* AIF1DRC2_QR */
+#define WM8994_AIF1DRC2_QR_SHIFT 4 /* AIF1DRC2_QR */
+#define WM8994_AIF1DRC2_QR_WIDTH 1 /* AIF1DRC2_QR */
+#define WM8994_AIF1DRC2_ANTICLIP 0x0008 /* AIF1DRC2_ANTICLIP */
+#define WM8994_AIF1DRC2_ANTICLIP_MASK 0x0008 /* AIF1DRC2_ANTICLIP */
+#define WM8994_AIF1DRC2_ANTICLIP_SHIFT 3 /* AIF1DRC2_ANTICLIP */
+#define WM8994_AIF1DRC2_ANTICLIP_WIDTH 1 /* AIF1DRC2_ANTICLIP */
+#define WM8994_AIF1DAC2_DRC_ENA 0x0004 /* AIF1DAC2_DRC_ENA */
+#define WM8994_AIF1DAC2_DRC_ENA_MASK 0x0004 /* AIF1DAC2_DRC_ENA */
+#define WM8994_AIF1DAC2_DRC_ENA_SHIFT 2 /* AIF1DAC2_DRC_ENA */
+#define WM8994_AIF1DAC2_DRC_ENA_WIDTH 1 /* AIF1DAC2_DRC_ENA */
+#define WM8994_AIF1ADC2L_DRC_ENA 0x0002 /* AIF1ADC2L_DRC_ENA */
+#define WM8994_AIF1ADC2L_DRC_ENA_MASK 0x0002 /* AIF1ADC2L_DRC_ENA */
+#define WM8994_AIF1ADC2L_DRC_ENA_SHIFT 1 /* AIF1ADC2L_DRC_ENA */
+#define WM8994_AIF1ADC2L_DRC_ENA_WIDTH 1 /* AIF1ADC2L_DRC_ENA */
+#define WM8994_AIF1ADC2R_DRC_ENA 0x0001 /* AIF1ADC2R_DRC_ENA */
+#define WM8994_AIF1ADC2R_DRC_ENA_MASK 0x0001 /* AIF1ADC2R_DRC_ENA */
+#define WM8994_AIF1ADC2R_DRC_ENA_SHIFT 0 /* AIF1ADC2R_DRC_ENA */
+#define WM8994_AIF1ADC2R_DRC_ENA_WIDTH 1 /* AIF1ADC2R_DRC_ENA */
+
+/*
+ * R1105 (0x451) - AIF1 DRC2 (2)
+ */
+#define WM8994_AIF1DRC2_ATK_MASK 0x1E00 /* AIF1DRC2_ATK - [12:9] */
+#define WM8994_AIF1DRC2_ATK_SHIFT 9 /* AIF1DRC2_ATK - [12:9] */
+#define WM8994_AIF1DRC2_ATK_WIDTH 4 /* AIF1DRC2_ATK - [12:9] */
+#define WM8994_AIF1DRC2_DCY_MASK 0x01E0 /* AIF1DRC2_DCY - [8:5] */
+#define WM8994_AIF1DRC2_DCY_SHIFT 5 /* AIF1DRC2_DCY - [8:5] */
+#define WM8994_AIF1DRC2_DCY_WIDTH 4 /* AIF1DRC2_DCY - [8:5] */
+#define WM8994_AIF1DRC2_MINGAIN_MASK 0x001C /* AIF1DRC2_MINGAIN - [4:2] */
+#define WM8994_AIF1DRC2_MINGAIN_SHIFT 2 /* AIF1DRC2_MINGAIN - [4:2] */
+#define WM8994_AIF1DRC2_MINGAIN_WIDTH 3 /* AIF1DRC2_MINGAIN - [4:2] */
+#define WM8994_AIF1DRC2_MAXGAIN_MASK 0x0003 /* AIF1DRC2_MAXGAIN - [1:0] */
+#define WM8994_AIF1DRC2_MAXGAIN_SHIFT 0 /* AIF1DRC2_MAXGAIN - [1:0] */
+#define WM8994_AIF1DRC2_MAXGAIN_WIDTH 2 /* AIF1DRC2_MAXGAIN - [1:0] */
+
+/*
+ * R1106 (0x452) - AIF1 DRC2 (3)
+ */
+#define WM8994_AIF1DRC2_NG_MINGAIN_MASK 0xF000 /* AIF1DRC2_NG_MINGAIN - [15:12] */
+#define WM8994_AIF1DRC2_NG_MINGAIN_SHIFT 12 /* AIF1DRC2_NG_MINGAIN - [15:12] */
+#define WM8994_AIF1DRC2_NG_MINGAIN_WIDTH 4 /* AIF1DRC2_NG_MINGAIN - [15:12] */
+#define WM8994_AIF1DRC2_NG_EXP_MASK 0x0C00 /* AIF1DRC2_NG_EXP - [11:10] */
+#define WM8994_AIF1DRC2_NG_EXP_SHIFT 10 /* AIF1DRC2_NG_EXP - [11:10] */
+#define WM8994_AIF1DRC2_NG_EXP_WIDTH 2 /* AIF1DRC2_NG_EXP - [11:10] */
+#define WM8994_AIF1DRC2_QR_THR_MASK 0x0300 /* AIF1DRC2_QR_THR - [9:8] */
+#define WM8994_AIF1DRC2_QR_THR_SHIFT 8 /* AIF1DRC2_QR_THR - [9:8] */
+#define WM8994_AIF1DRC2_QR_THR_WIDTH 2 /* AIF1DRC2_QR_THR - [9:8] */
+#define WM8994_AIF1DRC2_QR_DCY_MASK 0x00C0 /* AIF1DRC2_QR_DCY - [7:6] */
+#define WM8994_AIF1DRC2_QR_DCY_SHIFT 6 /* AIF1DRC2_QR_DCY - [7:6] */
+#define WM8994_AIF1DRC2_QR_DCY_WIDTH 2 /* AIF1DRC2_QR_DCY - [7:6] */
+#define WM8994_AIF1DRC2_HI_COMP_MASK 0x0038 /* AIF1DRC2_HI_COMP - [5:3] */
+#define WM8994_AIF1DRC2_HI_COMP_SHIFT 3 /* AIF1DRC2_HI_COMP - [5:3] */
+#define WM8994_AIF1DRC2_HI_COMP_WIDTH 3 /* AIF1DRC2_HI_COMP - [5:3] */
+#define WM8994_AIF1DRC2_LO_COMP_MASK 0x0007 /* AIF1DRC2_LO_COMP - [2:0] */
+#define WM8994_AIF1DRC2_LO_COMP_SHIFT 0 /* AIF1DRC2_LO_COMP - [2:0] */
+#define WM8994_AIF1DRC2_LO_COMP_WIDTH 3 /* AIF1DRC2_LO_COMP - [2:0] */
+
+/*
+ * R1107 (0x453) - AIF1 DRC2 (4)
+ */
+#define WM8994_AIF1DRC2_KNEE_IP_MASK 0x07E0 /* AIF1DRC2_KNEE_IP - [10:5] */
+#define WM8994_AIF1DRC2_KNEE_IP_SHIFT 5 /* AIF1DRC2_KNEE_IP - [10:5] */
+#define WM8994_AIF1DRC2_KNEE_IP_WIDTH 6 /* AIF1DRC2_KNEE_IP - [10:5] */
+#define WM8994_AIF1DRC2_KNEE_OP_MASK 0x001F /* AIF1DRC2_KNEE_OP - [4:0] */
+#define WM8994_AIF1DRC2_KNEE_OP_SHIFT 0 /* AIF1DRC2_KNEE_OP - [4:0] */
+#define WM8994_AIF1DRC2_KNEE_OP_WIDTH 5 /* AIF1DRC2_KNEE_OP - [4:0] */
+
+/*
+ * R1108 (0x454) - AIF1 DRC2 (5)
+ */
+#define WM8994_AIF1DRC2_KNEE2_IP_MASK 0x03E0 /* AIF1DRC2_KNEE2_IP - [9:5] */
+#define WM8994_AIF1DRC2_KNEE2_IP_SHIFT 5 /* AIF1DRC2_KNEE2_IP - [9:5] */
+#define WM8994_AIF1DRC2_KNEE2_IP_WIDTH 5 /* AIF1DRC2_KNEE2_IP - [9:5] */
+#define WM8994_AIF1DRC2_KNEE2_OP_MASK 0x001F /* AIF1DRC2_KNEE2_OP - [4:0] */
+#define WM8994_AIF1DRC2_KNEE2_OP_SHIFT 0 /* AIF1DRC2_KNEE2_OP - [4:0] */
+#define WM8994_AIF1DRC2_KNEE2_OP_WIDTH 5 /* AIF1DRC2_KNEE2_OP - [4:0] */
+
+/*
+ * R1152 (0x480) - AIF1 DAC1 EQ Gains (1)
+ */
+#define WM8994_AIF1DAC1_EQ_B1_GAIN_MASK 0xF800 /* AIF1DAC1_EQ_B1_GAIN - [15:11] */
+#define WM8994_AIF1DAC1_EQ_B1_GAIN_SHIFT 11 /* AIF1DAC1_EQ_B1_GAIN - [15:11] */
+#define WM8994_AIF1DAC1_EQ_B1_GAIN_WIDTH 5 /* AIF1DAC1_EQ_B1_GAIN - [15:11] */
+#define WM8994_AIF1DAC1_EQ_B2_GAIN_MASK 0x07C0 /* AIF1DAC1_EQ_B2_GAIN - [10:6] */
+#define WM8994_AIF1DAC1_EQ_B2_GAIN_SHIFT 6 /* AIF1DAC1_EQ_B2_GAIN - [10:6] */
+#define WM8994_AIF1DAC1_EQ_B2_GAIN_WIDTH 5 /* AIF1DAC1_EQ_B2_GAIN - [10:6] */
+#define WM8994_AIF1DAC1_EQ_B3_GAIN_MASK 0x003E /* AIF1DAC1_EQ_B3_GAIN - [5:1] */
+#define WM8994_AIF1DAC1_EQ_B3_GAIN_SHIFT 1 /* AIF1DAC1_EQ_B3_GAIN - [5:1] */
+#define WM8994_AIF1DAC1_EQ_B3_GAIN_WIDTH 5 /* AIF1DAC1_EQ_B3_GAIN - [5:1] */
+#define WM8994_AIF1DAC1_EQ_ENA 0x0001 /* AIF1DAC1_EQ_ENA */
+#define WM8994_AIF1DAC1_EQ_ENA_MASK 0x0001 /* AIF1DAC1_EQ_ENA */
+#define WM8994_AIF1DAC1_EQ_ENA_SHIFT 0 /* AIF1DAC1_EQ_ENA */
+#define WM8994_AIF1DAC1_EQ_ENA_WIDTH 1 /* AIF1DAC1_EQ_ENA */
+
+/*
+ * R1153 (0x481) - AIF1 DAC1 EQ Gains (2)
+ */
+#define WM8994_AIF1DAC1_EQ_B4_GAIN_MASK 0xF800 /* AIF1DAC1_EQ_B4_GAIN - [15:11] */
+#define WM8994_AIF1DAC1_EQ_B4_GAIN_SHIFT 11 /* AIF1DAC1_EQ_B4_GAIN - [15:11] */
+#define WM8994_AIF1DAC1_EQ_B4_GAIN_WIDTH 5 /* AIF1DAC1_EQ_B4_GAIN - [15:11] */
+#define WM8994_AIF1DAC1_EQ_B5_GAIN_MASK 0x07C0 /* AIF1DAC1_EQ_B5_GAIN - [10:6] */
+#define WM8994_AIF1DAC1_EQ_B5_GAIN_SHIFT 6 /* AIF1DAC1_EQ_B5_GAIN - [10:6] */
+#define WM8994_AIF1DAC1_EQ_B5_GAIN_WIDTH 5 /* AIF1DAC1_EQ_B5_GAIN - [10:6] */
+
+/*
+ * R1154 (0x482) - AIF1 DAC1 EQ Band 1 A
+ */
+#define WM8994_AIF1DAC1_EQ_B1_A_MASK 0xFFFF /* AIF1DAC1_EQ_B1_A - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B1_A_SHIFT 0 /* AIF1DAC1_EQ_B1_A - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B1_A_WIDTH 16 /* AIF1DAC1_EQ_B1_A - [15:0] */
+
+/*
+ * R1155 (0x483) - AIF1 DAC1 EQ Band 1 B
+ */
+#define WM8994_AIF1DAC1_EQ_B1_B_MASK 0xFFFF /* AIF1DAC1_EQ_B1_B - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B1_B_SHIFT 0 /* AIF1DAC1_EQ_B1_B - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B1_B_WIDTH 16 /* AIF1DAC1_EQ_B1_B - [15:0] */
+
+/*
+ * R1156 (0x484) - AIF1 DAC1 EQ Band 1 PG
+ */
+#define WM8994_AIF1DAC1_EQ_B1_PG_MASK 0xFFFF /* AIF1DAC1_EQ_B1_PG - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B1_PG_SHIFT 0 /* AIF1DAC1_EQ_B1_PG - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B1_PG_WIDTH 16 /* AIF1DAC1_EQ_B1_PG - [15:0] */
+
+/*
+ * R1157 (0x485) - AIF1 DAC1 EQ Band 2 A
+ */
+#define WM8994_AIF1DAC1_EQ_B2_A_MASK 0xFFFF /* AIF1DAC1_EQ_B2_A - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B2_A_SHIFT 0 /* AIF1DAC1_EQ_B2_A - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B2_A_WIDTH 16 /* AIF1DAC1_EQ_B2_A - [15:0] */
+
+/*
+ * R1158 (0x486) - AIF1 DAC1 EQ Band 2 B
+ */
+#define WM8994_AIF1DAC1_EQ_B2_B_MASK 0xFFFF /* AIF1DAC1_EQ_B2_B - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B2_B_SHIFT 0 /* AIF1DAC1_EQ_B2_B - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B2_B_WIDTH 16 /* AIF1DAC1_EQ_B2_B - [15:0] */
+
+/*
+ * R1159 (0x487) - AIF1 DAC1 EQ Band 2 C
+ */
+#define WM8994_AIF1DAC1_EQ_B2_C_MASK 0xFFFF /* AIF1DAC1_EQ_B2_C - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B2_C_SHIFT 0 /* AIF1DAC1_EQ_B2_C - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B2_C_WIDTH 16 /* AIF1DAC1_EQ_B2_C - [15:0] */
+
+/*
+ * R1160 (0x488) - AIF1 DAC1 EQ Band 2 PG
+ */
+#define WM8994_AIF1DAC1_EQ_B2_PG_MASK 0xFFFF /* AIF1DAC1_EQ_B2_PG - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B2_PG_SHIFT 0 /* AIF1DAC1_EQ_B2_PG - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B2_PG_WIDTH 16 /* AIF1DAC1_EQ_B2_PG - [15:0] */
+
+/*
+ * R1161 (0x489) - AIF1 DAC1 EQ Band 3 A
+ */
+#define WM8994_AIF1DAC1_EQ_B3_A_MASK 0xFFFF /* AIF1DAC1_EQ_B3_A - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B3_A_SHIFT 0 /* AIF1DAC1_EQ_B3_A - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B3_A_WIDTH 16 /* AIF1DAC1_EQ_B3_A - [15:0] */
+
+/*
+ * R1162 (0x48A) - AIF1 DAC1 EQ Band 3 B
+ */
+#define WM8994_AIF1DAC1_EQ_B3_B_MASK 0xFFFF /* AIF1DAC1_EQ_B3_B - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B3_B_SHIFT 0 /* AIF1DAC1_EQ_B3_B - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B3_B_WIDTH 16 /* AIF1DAC1_EQ_B3_B - [15:0] */
+
+/*
+ * R1163 (0x48B) - AIF1 DAC1 EQ Band 3 C
+ */
+#define WM8994_AIF1DAC1_EQ_B3_C_MASK 0xFFFF /* AIF1DAC1_EQ_B3_C - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B3_C_SHIFT 0 /* AIF1DAC1_EQ_B3_C - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B3_C_WIDTH 16 /* AIF1DAC1_EQ_B3_C - [15:0] */
+
+/*
+ * R1164 (0x48C) - AIF1 DAC1 EQ Band 3 PG
+ */
+#define WM8994_AIF1DAC1_EQ_B3_PG_MASK 0xFFFF /* AIF1DAC1_EQ_B3_PG - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B3_PG_SHIFT 0 /* AIF1DAC1_EQ_B3_PG - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B3_PG_WIDTH 16 /* AIF1DAC1_EQ_B3_PG - [15:0] */
+
+/*
+ * R1165 (0x48D) - AIF1 DAC1 EQ Band 4 A
+ */
+#define WM8994_AIF1DAC1_EQ_B4_A_MASK 0xFFFF /* AIF1DAC1_EQ_B4_A - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B4_A_SHIFT 0 /* AIF1DAC1_EQ_B4_A - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B4_A_WIDTH 16 /* AIF1DAC1_EQ_B4_A - [15:0] */
+
+/*
+ * R1166 (0x48E) - AIF1 DAC1 EQ Band 4 B
+ */
+#define WM8994_AIF1DAC1_EQ_B4_B_MASK 0xFFFF /* AIF1DAC1_EQ_B4_B - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B4_B_SHIFT 0 /* AIF1DAC1_EQ_B4_B - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B4_B_WIDTH 16 /* AIF1DAC1_EQ_B4_B - [15:0] */
+
+/*
+ * R1167 (0x48F) - AIF1 DAC1 EQ Band 4 C
+ */
+#define WM8994_AIF1DAC1_EQ_B4_C_MASK 0xFFFF /* AIF1DAC1_EQ_B4_C - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B4_C_SHIFT 0 /* AIF1DAC1_EQ_B4_C - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B4_C_WIDTH 16 /* AIF1DAC1_EQ_B4_C - [15:0] */
+
+/*
+ * R1168 (0x490) - AIF1 DAC1 EQ Band 4 PG
+ */
+#define WM8994_AIF1DAC1_EQ_B4_PG_MASK 0xFFFF /* AIF1DAC1_EQ_B4_PG - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B4_PG_SHIFT 0 /* AIF1DAC1_EQ_B4_PG - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B4_PG_WIDTH 16 /* AIF1DAC1_EQ_B4_PG - [15:0] */
+
+/*
+ * R1169 (0x491) - AIF1 DAC1 EQ Band 5 A
+ */
+#define WM8994_AIF1DAC1_EQ_B5_A_MASK 0xFFFF /* AIF1DAC1_EQ_B5_A - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B5_A_SHIFT 0 /* AIF1DAC1_EQ_B5_A - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B5_A_WIDTH 16 /* AIF1DAC1_EQ_B5_A - [15:0] */
+
+/*
+ * R1170 (0x492) - AIF1 DAC1 EQ Band 5 B
+ */
+#define WM8994_AIF1DAC1_EQ_B5_B_MASK 0xFFFF /* AIF1DAC1_EQ_B5_B - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B5_B_SHIFT 0 /* AIF1DAC1_EQ_B5_B - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B5_B_WIDTH 16 /* AIF1DAC1_EQ_B5_B - [15:0] */
+
+/*
+ * R1171 (0x493) - AIF1 DAC1 EQ Band 5 PG
+ */
+#define WM8994_AIF1DAC1_EQ_B5_PG_MASK 0xFFFF /* AIF1DAC1_EQ_B5_PG - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B5_PG_SHIFT 0 /* AIF1DAC1_EQ_B5_PG - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B5_PG_WIDTH 16 /* AIF1DAC1_EQ_B5_PG - [15:0] */
+
+/*
+ * R1184 (0x4A0) - AIF1 DAC2 EQ Gains (1)
+ */
+#define WM8994_AIF1DAC2_EQ_B1_GAIN_MASK 0xF800 /* AIF1DAC2_EQ_B1_GAIN - [15:11] */
+#define WM8994_AIF1DAC2_EQ_B1_GAIN_SHIFT 11 /* AIF1DAC2_EQ_B1_GAIN - [15:11] */
+#define WM8994_AIF1DAC2_EQ_B1_GAIN_WIDTH 5 /* AIF1DAC2_EQ_B1_GAIN - [15:11] */
+#define WM8994_AIF1DAC2_EQ_B2_GAIN_MASK 0x07C0 /* AIF1DAC2_EQ_B2_GAIN - [10:6] */
+#define WM8994_AIF1DAC2_EQ_B2_GAIN_SHIFT 6 /* AIF1DAC2_EQ_B2_GAIN - [10:6] */
+#define WM8994_AIF1DAC2_EQ_B2_GAIN_WIDTH 5 /* AIF1DAC2_EQ_B2_GAIN - [10:6] */
+#define WM8994_AIF1DAC2_EQ_B3_GAIN_MASK 0x003E /* AIF1DAC2_EQ_B3_GAIN - [5:1] */
+#define WM8994_AIF1DAC2_EQ_B3_GAIN_SHIFT 1 /* AIF1DAC2_EQ_B3_GAIN - [5:1] */
+#define WM8994_AIF1DAC2_EQ_B3_GAIN_WIDTH 5 /* AIF1DAC2_EQ_B3_GAIN - [5:1] */
+#define WM8994_AIF1DAC2_EQ_ENA 0x0001 /* AIF1DAC2_EQ_ENA */
+#define WM8994_AIF1DAC2_EQ_ENA_MASK 0x0001 /* AIF1DAC2_EQ_ENA */
+#define WM8994_AIF1DAC2_EQ_ENA_SHIFT 0 /* AIF1DAC2_EQ_ENA */
+#define WM8994_AIF1DAC2_EQ_ENA_WIDTH 1 /* AIF1DAC2_EQ_ENA */
+
+/*
+ * R1185 (0x4A1) - AIF1 DAC2 EQ Gains (2)
+ */
+#define WM8994_AIF1DAC2_EQ_B4_GAIN_MASK 0xF800 /* AIF1DAC2_EQ_B4_GAIN - [15:11] */
+#define WM8994_AIF1DAC2_EQ_B4_GAIN_SHIFT 11 /* AIF1DAC2_EQ_B4_GAIN - [15:11] */
+#define WM8994_AIF1DAC2_EQ_B4_GAIN_WIDTH 5 /* AIF1DAC2_EQ_B4_GAIN - [15:11] */
+#define WM8994_AIF1DAC2_EQ_B5_GAIN_MASK 0x07C0 /* AIF1DAC2_EQ_B5_GAIN - [10:6] */
+#define WM8994_AIF1DAC2_EQ_B5_GAIN_SHIFT 6 /* AIF1DAC2_EQ_B5_GAIN - [10:6] */
+#define WM8994_AIF1DAC2_EQ_B5_GAIN_WIDTH 5 /* AIF1DAC2_EQ_B5_GAIN - [10:6] */
+
+/*
+ * R1186 (0x4A2) - AIF1 DAC2 EQ Band 1 A
+ */
+#define WM8994_AIF1DAC2_EQ_B1_A_MASK 0xFFFF /* AIF1DAC2_EQ_B1_A - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B1_A_SHIFT 0 /* AIF1DAC2_EQ_B1_A - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B1_A_WIDTH 16 /* AIF1DAC2_EQ_B1_A - [15:0] */
+
+/*
+ * R1187 (0x4A3) - AIF1 DAC2 EQ Band 1 B
+ */
+#define WM8994_AIF1DAC2_EQ_B1_B_MASK 0xFFFF /* AIF1DAC2_EQ_B1_B - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B1_B_SHIFT 0 /* AIF1DAC2_EQ_B1_B - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B1_B_WIDTH 16 /* AIF1DAC2_EQ_B1_B - [15:0] */
+
+/*
+ * R1188 (0x4A4) - AIF1 DAC2 EQ Band 1 PG
+ */
+#define WM8994_AIF1DAC2_EQ_B1_PG_MASK 0xFFFF /* AIF1DAC2_EQ_B1_PG - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B1_PG_SHIFT 0 /* AIF1DAC2_EQ_B1_PG - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B1_PG_WIDTH 16 /* AIF1DAC2_EQ_B1_PG - [15:0] */
+
+/*
+ * R1189 (0x4A5) - AIF1 DAC2 EQ Band 2 A
+ */
+#define WM8994_AIF1DAC2_EQ_B2_A_MASK 0xFFFF /* AIF1DAC2_EQ_B2_A - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B2_A_SHIFT 0 /* AIF1DAC2_EQ_B2_A - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B2_A_WIDTH 16 /* AIF1DAC2_EQ_B2_A - [15:0] */
+
+/*
+ * R1190 (0x4A6) - AIF1 DAC2 EQ Band 2 B
+ */
+#define WM8994_AIF1DAC2_EQ_B2_B_MASK 0xFFFF /* AIF1DAC2_EQ_B2_B - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B2_B_SHIFT 0 /* AIF1DAC2_EQ_B2_B - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B2_B_WIDTH 16 /* AIF1DAC2_EQ_B2_B - [15:0] */
+
+/*
+ * R1191 (0x4A7) - AIF1 DAC2 EQ Band 2 C
+ */
+#define WM8994_AIF1DAC2_EQ_B2_C_MASK 0xFFFF /* AIF1DAC2_EQ_B2_C - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B2_C_SHIFT 0 /* AIF1DAC2_EQ_B2_C - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B2_C_WIDTH 16 /* AIF1DAC2_EQ_B2_C - [15:0] */
+
+/*
+ * R1192 (0x4A8) - AIF1 DAC2 EQ Band 2 PG
+ */
+#define WM8994_AIF1DAC2_EQ_B2_PG_MASK 0xFFFF /* AIF1DAC2_EQ_B2_PG - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B2_PG_SHIFT 0 /* AIF1DAC2_EQ_B2_PG - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B2_PG_WIDTH 16 /* AIF1DAC2_EQ_B2_PG - [15:0] */
+
+/*
+ * R1193 (0x4A9) - AIF1 DAC2 EQ Band 3 A
+ */
+#define WM8994_AIF1DAC2_EQ_B3_A_MASK 0xFFFF /* AIF1DAC2_EQ_B3_A - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B3_A_SHIFT 0 /* AIF1DAC2_EQ_B3_A - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B3_A_WIDTH 16 /* AIF1DAC2_EQ_B3_A - [15:0] */
+
+/*
+ * R1194 (0x4AA) - AIF1 DAC2 EQ Band 3 B
+ */
+#define WM8994_AIF1DAC2_EQ_B3_B_MASK 0xFFFF /* AIF1DAC2_EQ_B3_B - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B3_B_SHIFT 0 /* AIF1DAC2_EQ_B3_B - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B3_B_WIDTH 16 /* AIF1DAC2_EQ_B3_B - [15:0] */
+
+/*
+ * R1195 (0x4AB) - AIF1 DAC2 EQ Band 3 C
+ */
+#define WM8994_AIF1DAC2_EQ_B3_C_MASK 0xFFFF /* AIF1DAC2_EQ_B3_C - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B3_C_SHIFT 0 /* AIF1DAC2_EQ_B3_C - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B3_C_WIDTH 16 /* AIF1DAC2_EQ_B3_C - [15:0] */
+
+/*
+ * R1196 (0x4AC) - AIF1 DAC2 EQ Band 3 PG
+ */
+#define WM8994_AIF1DAC2_EQ_B3_PG_MASK 0xFFFF /* AIF1DAC2_EQ_B3_PG - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B3_PG_SHIFT 0 /* AIF1DAC2_EQ_B3_PG - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B3_PG_WIDTH 16 /* AIF1DAC2_EQ_B3_PG - [15:0] */
+
+/*
+ * R1197 (0x4AD) - AIF1 DAC2 EQ Band 4 A
+ */
+#define WM8994_AIF1DAC2_EQ_B4_A_MASK 0xFFFF /* AIF1DAC2_EQ_B4_A - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B4_A_SHIFT 0 /* AIF1DAC2_EQ_B4_A - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B4_A_WIDTH 16 /* AIF1DAC2_EQ_B4_A - [15:0] */
+
+/*
+ * R1198 (0x4AE) - AIF1 DAC2 EQ Band 4 B
+ */
+#define WM8994_AIF1DAC2_EQ_B4_B_MASK 0xFFFF /* AIF1DAC2_EQ_B4_B - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B4_B_SHIFT 0 /* AIF1DAC2_EQ_B4_B - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B4_B_WIDTH 16 /* AIF1DAC2_EQ_B4_B - [15:0] */
+
+/*
+ * R1199 (0x4AF) - AIF1 DAC2 EQ Band 4 C
+ */
+#define WM8994_AIF1DAC2_EQ_B4_C_MASK 0xFFFF /* AIF1DAC2_EQ_B4_C - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B4_C_SHIFT 0 /* AIF1DAC2_EQ_B4_C - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B4_C_WIDTH 16 /* AIF1DAC2_EQ_B4_C - [15:0] */
+
+/*
+ * R1200 (0x4B0) - AIF1 DAC2 EQ Band 4 PG
+ */
+#define WM8994_AIF1DAC2_EQ_B4_PG_MASK 0xFFFF /* AIF1DAC2_EQ_B4_PG - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B4_PG_SHIFT 0 /* AIF1DAC2_EQ_B4_PG - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B4_PG_WIDTH 16 /* AIF1DAC2_EQ_B4_PG - [15:0] */
+
+/*
+ * R1201 (0x4B1) - AIF1 DAC2 EQ Band 5 A
+ */
+#define WM8994_AIF1DAC2_EQ_B5_A_MASK 0xFFFF /* AIF1DAC2_EQ_B5_A - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B5_A_SHIFT 0 /* AIF1DAC2_EQ_B5_A - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B5_A_WIDTH 16 /* AIF1DAC2_EQ_B5_A - [15:0] */
+
+/*
+ * R1202 (0x4B2) - AIF1 DAC2 EQ Band 5 B
+ */
+#define WM8994_AIF1DAC2_EQ_B5_B_MASK 0xFFFF /* AIF1DAC2_EQ_B5_B - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B5_B_SHIFT 0 /* AIF1DAC2_EQ_B5_B - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B5_B_WIDTH 16 /* AIF1DAC2_EQ_B5_B - [15:0] */
+
+/*
+ * R1203 (0x4B3) - AIF1 DAC2 EQ Band 5 PG
+ */
+#define WM8994_AIF1DAC2_EQ_B5_PG_MASK 0xFFFF /* AIF1DAC2_EQ_B5_PG - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B5_PG_SHIFT 0 /* AIF1DAC2_EQ_B5_PG - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B5_PG_WIDTH 16 /* AIF1DAC2_EQ_B5_PG - [15:0] */
+
+/*
+ * R1280 (0x500) - AIF2 ADC Left Volume
+ */
+#define WM8994_AIF2ADC_VU 0x0100 /* AIF2ADC_VU */
+#define WM8994_AIF2ADC_VU_MASK 0x0100 /* AIF2ADC_VU */
+#define WM8994_AIF2ADC_VU_SHIFT 8 /* AIF2ADC_VU */
+#define WM8994_AIF2ADC_VU_WIDTH 1 /* AIF2ADC_VU */
+#define WM8994_AIF2ADCL_VOL_MASK 0x00FF /* AIF2ADCL_VOL - [7:0] */
+#define WM8994_AIF2ADCL_VOL_SHIFT 0 /* AIF2ADCL_VOL - [7:0] */
+#define WM8994_AIF2ADCL_VOL_WIDTH 8 /* AIF2ADCL_VOL - [7:0] */
+
+/*
+ * R1281 (0x501) - AIF2 ADC Right Volume
+ */
+#define WM8994_AIF2ADC_VU 0x0100 /* AIF2ADC_VU */
+#define WM8994_AIF2ADC_VU_MASK 0x0100 /* AIF2ADC_VU */
+#define WM8994_AIF2ADC_VU_SHIFT 8 /* AIF2ADC_VU */
+#define WM8994_AIF2ADC_VU_WIDTH 1 /* AIF2ADC_VU */
+#define WM8994_AIF2ADCR_VOL_MASK 0x00FF /* AIF2ADCR_VOL - [7:0] */
+#define WM8994_AIF2ADCR_VOL_SHIFT 0 /* AIF2ADCR_VOL - [7:0] */
+#define WM8994_AIF2ADCR_VOL_WIDTH 8 /* AIF2ADCR_VOL - [7:0] */
+
+/*
+ * R1282 (0x502) - AIF2 DAC Left Volume
+ */
+#define WM8994_AIF2DAC_VU 0x0100 /* AIF2DAC_VU */
+#define WM8994_AIF2DAC_VU_MASK 0x0100 /* AIF2DAC_VU */
+#define WM8994_AIF2DAC_VU_SHIFT 8 /* AIF2DAC_VU */
+#define WM8994_AIF2DAC_VU_WIDTH 1 /* AIF2DAC_VU */
+#define WM8994_AIF2DACL_VOL_MASK 0x00FF /* AIF2DACL_VOL - [7:0] */
+#define WM8994_AIF2DACL_VOL_SHIFT 0 /* AIF2DACL_VOL - [7:0] */
+#define WM8994_AIF2DACL_VOL_WIDTH 8 /* AIF2DACL_VOL - [7:0] */
+
+/*
+ * R1283 (0x503) - AIF2 DAC Right Volume
+ */
+#define WM8994_AIF2DAC_VU 0x0100 /* AIF2DAC_VU */
+#define WM8994_AIF2DAC_VU_MASK 0x0100 /* AIF2DAC_VU */
+#define WM8994_AIF2DAC_VU_SHIFT 8 /* AIF2DAC_VU */
+#define WM8994_AIF2DAC_VU_WIDTH 1 /* AIF2DAC_VU */
+#define WM8994_AIF2DACR_VOL_MASK 0x00FF /* AIF2DACR_VOL - [7:0] */
+#define WM8994_AIF2DACR_VOL_SHIFT 0 /* AIF2DACR_VOL - [7:0] */
+#define WM8994_AIF2DACR_VOL_WIDTH 8 /* AIF2DACR_VOL - [7:0] */
+
+/*
+ * R1296 (0x510) - AIF2 ADC Filters
+ */
+#define WM8994_AIF2ADC_4FS 0x8000 /* AIF2ADC_4FS */
+#define WM8994_AIF2ADC_4FS_MASK 0x8000 /* AIF2ADC_4FS */
+#define WM8994_AIF2ADC_4FS_SHIFT 15 /* AIF2ADC_4FS */
+#define WM8994_AIF2ADC_4FS_WIDTH 1 /* AIF2ADC_4FS */
+#define WM8994_AIF2ADC_HPF_CUT_MASK 0x6000 /* AIF2ADC_HPF_CUT - [14:13] */
+#define WM8994_AIF2ADC_HPF_CUT_SHIFT 13 /* AIF2ADC_HPF_CUT - [14:13] */
+#define WM8994_AIF2ADC_HPF_CUT_WIDTH 2 /* AIF2ADC_HPF_CUT - [14:13] */
+#define WM8994_AIF2ADCL_HPF 0x1000 /* AIF2ADCL_HPF */
+#define WM8994_AIF2ADCL_HPF_MASK 0x1000 /* AIF2ADCL_HPF */
+#define WM8994_AIF2ADCL_HPF_SHIFT 12 /* AIF2ADCL_HPF */
+#define WM8994_AIF2ADCL_HPF_WIDTH 1 /* AIF2ADCL_HPF */
+#define WM8994_AIF2ADCR_HPF 0x0800 /* AIF2ADCR_HPF */
+#define WM8994_AIF2ADCR_HPF_MASK 0x0800 /* AIF2ADCR_HPF */
+#define WM8994_AIF2ADCR_HPF_SHIFT 11 /* AIF2ADCR_HPF */
+#define WM8994_AIF2ADCR_HPF_WIDTH 1 /* AIF2ADCR_HPF */
+
+/*
+ * R1312 (0x520) - AIF2 DAC Filters (1)
+ */
+#define WM8994_AIF2DAC_MUTE 0x0200 /* AIF2DAC_MUTE */
+#define WM8994_AIF2DAC_MUTE_MASK 0x0200 /* AIF2DAC_MUTE */
+#define WM8994_AIF2DAC_MUTE_SHIFT 9 /* AIF2DAC_MUTE */
+#define WM8994_AIF2DAC_MUTE_WIDTH 1 /* AIF2DAC_MUTE */
+#define WM8994_AIF2DAC_MONO 0x0080 /* AIF2DAC_MONO */
+#define WM8994_AIF2DAC_MONO_MASK 0x0080 /* AIF2DAC_MONO */
+#define WM8994_AIF2DAC_MONO_SHIFT 7 /* AIF2DAC_MONO */
+#define WM8994_AIF2DAC_MONO_WIDTH 1 /* AIF2DAC_MONO */
+#define WM8994_AIF2DAC_MUTERATE 0x0020 /* AIF2DAC_MUTERATE */
+#define WM8994_AIF2DAC_MUTERATE_MASK 0x0020 /* AIF2DAC_MUTERATE */
+#define WM8994_AIF2DAC_MUTERATE_SHIFT 5 /* AIF2DAC_MUTERATE */
+#define WM8994_AIF2DAC_MUTERATE_WIDTH 1 /* AIF2DAC_MUTERATE */
+#define WM8994_AIF2DAC_UNMUTE_RAMP 0x0010 /* AIF2DAC_UNMUTE_RAMP */
+#define WM8994_AIF2DAC_UNMUTE_RAMP_MASK 0x0010 /* AIF2DAC_UNMUTE_RAMP */
+#define WM8994_AIF2DAC_UNMUTE_RAMP_SHIFT 4 /* AIF2DAC_UNMUTE_RAMP */
+#define WM8994_AIF2DAC_UNMUTE_RAMP_WIDTH 1 /* AIF2DAC_UNMUTE_RAMP */
+#define WM8994_AIF2DAC_DEEMP_MASK 0x0006 /* AIF2DAC_DEEMP - [2:1] */
+#define WM8994_AIF2DAC_DEEMP_SHIFT 1 /* AIF2DAC_DEEMP - [2:1] */
+#define WM8994_AIF2DAC_DEEMP_WIDTH 2 /* AIF2DAC_DEEMP - [2:1] */
+
+/*
+ * R1313 (0x521) - AIF2 DAC Filters (2)
+ */
+#define WM8994_AIF2DAC_3D_GAIN_MASK 0x3E00 /* AIF2DAC_3D_GAIN - [13:9] */
+#define WM8994_AIF2DAC_3D_GAIN_SHIFT 9 /* AIF2DAC_3D_GAIN - [13:9] */
+#define WM8994_AIF2DAC_3D_GAIN_WIDTH 5 /* AIF2DAC_3D_GAIN - [13:9] */
+#define WM8994_AIF2DAC_3D_ENA 0x0100 /* AIF2DAC_3D_ENA */
+#define WM8994_AIF2DAC_3D_ENA_MASK 0x0100 /* AIF2DAC_3D_ENA */
+#define WM8994_AIF2DAC_3D_ENA_SHIFT 8 /* AIF2DAC_3D_ENA */
+#define WM8994_AIF2DAC_3D_ENA_WIDTH 1 /* AIF2DAC_3D_ENA */
+
+/*
+ * R1344 (0x540) - AIF2 DRC (1)
+ */
+#define WM8994_AIF2DRC_SIG_DET_RMS_MASK 0xF800 /* AIF2DRC_SIG_DET_RMS - [15:11] */
+#define WM8994_AIF2DRC_SIG_DET_RMS_SHIFT 11 /* AIF2DRC_SIG_DET_RMS - [15:11] */
+#define WM8994_AIF2DRC_SIG_DET_RMS_WIDTH 5 /* AIF2DRC_SIG_DET_RMS - [15:11] */
+#define WM8994_AIF2DRC_SIG_DET_PK_MASK 0x0600 /* AIF2DRC_SIG_DET_PK - [10:9] */
+#define WM8994_AIF2DRC_SIG_DET_PK_SHIFT 9 /* AIF2DRC_SIG_DET_PK - [10:9] */
+#define WM8994_AIF2DRC_SIG_DET_PK_WIDTH 2 /* AIF2DRC_SIG_DET_PK - [10:9] */
+#define WM8994_AIF2DRC_NG_ENA 0x0100 /* AIF2DRC_NG_ENA */
+#define WM8994_AIF2DRC_NG_ENA_MASK 0x0100 /* AIF2DRC_NG_ENA */
+#define WM8994_AIF2DRC_NG_ENA_SHIFT 8 /* AIF2DRC_NG_ENA */
+#define WM8994_AIF2DRC_NG_ENA_WIDTH 1 /* AIF2DRC_NG_ENA */
+#define WM8994_AIF2DRC_SIG_DET_MODE 0x0080 /* AIF2DRC_SIG_DET_MODE */
+#define WM8994_AIF2DRC_SIG_DET_MODE_MASK 0x0080 /* AIF2DRC_SIG_DET_MODE */
+#define WM8994_AIF2DRC_SIG_DET_MODE_SHIFT 7 /* AIF2DRC_SIG_DET_MODE */
+#define WM8994_AIF2DRC_SIG_DET_MODE_WIDTH 1 /* AIF2DRC_SIG_DET_MODE */
+#define WM8994_AIF2DRC_SIG_DET 0x0040 /* AIF2DRC_SIG_DET */
+#define WM8994_AIF2DRC_SIG_DET_MASK 0x0040 /* AIF2DRC_SIG_DET */
+#define WM8994_AIF2DRC_SIG_DET_SHIFT 6 /* AIF2DRC_SIG_DET */
+#define WM8994_AIF2DRC_SIG_DET_WIDTH 1 /* AIF2DRC_SIG_DET */
+#define WM8994_AIF2DRC_KNEE2_OP_ENA 0x0020 /* AIF2DRC_KNEE2_OP_ENA */
+#define WM8994_AIF2DRC_KNEE2_OP_ENA_MASK 0x0020 /* AIF2DRC_KNEE2_OP_ENA */
+#define WM8994_AIF2DRC_KNEE2_OP_ENA_SHIFT 5 /* AIF2DRC_KNEE2_OP_ENA */
+#define WM8994_AIF2DRC_KNEE2_OP_ENA_WIDTH 1 /* AIF2DRC_KNEE2_OP_ENA */
+#define WM8994_AIF2DRC_QR 0x0010 /* AIF2DRC_QR */
+#define WM8994_AIF2DRC_QR_MASK 0x0010 /* AIF2DRC_QR */
+#define WM8994_AIF2DRC_QR_SHIFT 4 /* AIF2DRC_QR */
+#define WM8994_AIF2DRC_QR_WIDTH 1 /* AIF2DRC_QR */
+#define WM8994_AIF2DRC_ANTICLIP 0x0008 /* AIF2DRC_ANTICLIP */
+#define WM8994_AIF2DRC_ANTICLIP_MASK 0x0008 /* AIF2DRC_ANTICLIP */
+#define WM8994_AIF2DRC_ANTICLIP_SHIFT 3 /* AIF2DRC_ANTICLIP */
+#define WM8994_AIF2DRC_ANTICLIP_WIDTH 1 /* AIF2DRC_ANTICLIP */
+#define WM8994_AIF2DAC_DRC_ENA 0x0004 /* AIF2DAC_DRC_ENA */
+#define WM8994_AIF2DAC_DRC_ENA_MASK 0x0004 /* AIF2DAC_DRC_ENA */
+#define WM8994_AIF2DAC_DRC_ENA_SHIFT 2 /* AIF2DAC_DRC_ENA */
+#define WM8994_AIF2DAC_DRC_ENA_WIDTH 1 /* AIF2DAC_DRC_ENA */
+#define WM8994_AIF2ADCL_DRC_ENA 0x0002 /* AIF2ADCL_DRC_ENA */
+#define WM8994_AIF2ADCL_DRC_ENA_MASK 0x0002 /* AIF2ADCL_DRC_ENA */
+#define WM8994_AIF2ADCL_DRC_ENA_SHIFT 1 /* AIF2ADCL_DRC_ENA */
+#define WM8994_AIF2ADCL_DRC_ENA_WIDTH 1 /* AIF2ADCL_DRC_ENA */
+#define WM8994_AIF2ADCR_DRC_ENA 0x0001 /* AIF2ADCR_DRC_ENA */
+#define WM8994_AIF2ADCR_DRC_ENA_MASK 0x0001 /* AIF2ADCR_DRC_ENA */
+#define WM8994_AIF2ADCR_DRC_ENA_SHIFT 0 /* AIF2ADCR_DRC_ENA */
+#define WM8994_AIF2ADCR_DRC_ENA_WIDTH 1 /* AIF2ADCR_DRC_ENA */
+
+/*
+ * R1345 (0x541) - AIF2 DRC (2)
+ */
+#define WM8994_AIF2DRC_ATK_MASK 0x1E00 /* AIF2DRC_ATK - [12:9] */
+#define WM8994_AIF2DRC_ATK_SHIFT 9 /* AIF2DRC_ATK - [12:9] */
+#define WM8994_AIF2DRC_ATK_WIDTH 4 /* AIF2DRC_ATK - [12:9] */
+#define WM8994_AIF2DRC_DCY_MASK 0x01E0 /* AIF2DRC_DCY - [8:5] */
+#define WM8994_AIF2DRC_DCY_SHIFT 5 /* AIF2DRC_DCY - [8:5] */
+#define WM8994_AIF2DRC_DCY_WIDTH 4 /* AIF2DRC_DCY - [8:5] */
+#define WM8994_AIF2DRC_MINGAIN_MASK 0x001C /* AIF2DRC_MINGAIN - [4:2] */
+#define WM8994_AIF2DRC_MINGAIN_SHIFT 2 /* AIF2DRC_MINGAIN - [4:2] */
+#define WM8994_AIF2DRC_MINGAIN_WIDTH 3 /* AIF2DRC_MINGAIN - [4:2] */
+#define WM8994_AIF2DRC_MAXGAIN_MASK 0x0003 /* AIF2DRC_MAXGAIN - [1:0] */
+#define WM8994_AIF2DRC_MAXGAIN_SHIFT 0 /* AIF2DRC_MAXGAIN - [1:0] */
+#define WM8994_AIF2DRC_MAXGAIN_WIDTH 2 /* AIF2DRC_MAXGAIN - [1:0] */
+
+/*
+ * R1346 (0x542) - AIF2 DRC (3)
+ */
+#define WM8994_AIF2DRC_NG_MINGAIN_MASK 0xF000 /* AIF2DRC_NG_MINGAIN - [15:12] */
+#define WM8994_AIF2DRC_NG_MINGAIN_SHIFT 12 /* AIF2DRC_NG_MINGAIN - [15:12] */
+#define WM8994_AIF2DRC_NG_MINGAIN_WIDTH 4 /* AIF2DRC_NG_MINGAIN - [15:12] */
+#define WM8994_AIF2DRC_NG_EXP_MASK 0x0C00 /* AIF2DRC_NG_EXP - [11:10] */
+#define WM8994_AIF2DRC_NG_EXP_SHIFT 10 /* AIF2DRC_NG_EXP - [11:10] */
+#define WM8994_AIF2DRC_NG_EXP_WIDTH 2 /* AIF2DRC_NG_EXP - [11:10] */
+#define WM8994_AIF2DRC_QR_THR_MASK 0x0300 /* AIF2DRC_QR_THR - [9:8] */
+#define WM8994_AIF2DRC_QR_THR_SHIFT 8 /* AIF2DRC_QR_THR - [9:8] */
+#define WM8994_AIF2DRC_QR_THR_WIDTH 2 /* AIF2DRC_QR_THR - [9:8] */
+#define WM8994_AIF2DRC_QR_DCY_MASK 0x00C0 /* AIF2DRC_QR_DCY - [7:6] */
+#define WM8994_AIF2DRC_QR_DCY_SHIFT 6 /* AIF2DRC_QR_DCY - [7:6] */
+#define WM8994_AIF2DRC_QR_DCY_WIDTH 2 /* AIF2DRC_QR_DCY - [7:6] */
+#define WM8994_AIF2DRC_HI_COMP_MASK 0x0038 /* AIF2DRC_HI_COMP - [5:3] */
+#define WM8994_AIF2DRC_HI_COMP_SHIFT 3 /* AIF2DRC_HI_COMP - [5:3] */
+#define WM8994_AIF2DRC_HI_COMP_WIDTH 3 /* AIF2DRC_HI_COMP - [5:3] */
+#define WM8994_AIF2DRC_LO_COMP_MASK 0x0007 /* AIF2DRC_LO_COMP - [2:0] */
+#define WM8994_AIF2DRC_LO_COMP_SHIFT 0 /* AIF2DRC_LO_COMP - [2:0] */
+#define WM8994_AIF2DRC_LO_COMP_WIDTH 3 /* AIF2DRC_LO_COMP - [2:0] */
+
+/*
+ * R1347 (0x543) - AIF2 DRC (4)
+ */
+#define WM8994_AIF2DRC_KNEE_IP_MASK 0x07E0 /* AIF2DRC_KNEE_IP - [10:5] */
+#define WM8994_AIF2DRC_KNEE_IP_SHIFT 5 /* AIF2DRC_KNEE_IP - [10:5] */
+#define WM8994_AIF2DRC_KNEE_IP_WIDTH 6 /* AIF2DRC_KNEE_IP - [10:5] */
+#define WM8994_AIF2DRC_KNEE_OP_MASK 0x001F /* AIF2DRC_KNEE_OP - [4:0] */
+#define WM8994_AIF2DRC_KNEE_OP_SHIFT 0 /* AIF2DRC_KNEE_OP - [4:0] */
+#define WM8994_AIF2DRC_KNEE_OP_WIDTH 5 /* AIF2DRC_KNEE_OP - [4:0] */
+
+/*
+ * R1348 (0x544) - AIF2 DRC (5)
+ */
+#define WM8994_AIF2DRC_KNEE2_IP_MASK 0x03E0 /* AIF2DRC_KNEE2_IP - [9:5] */
+#define WM8994_AIF2DRC_KNEE2_IP_SHIFT 5 /* AIF2DRC_KNEE2_IP - [9:5] */
+#define WM8994_AIF2DRC_KNEE2_IP_WIDTH 5 /* AIF2DRC_KNEE2_IP - [9:5] */
+#define WM8994_AIF2DRC_KNEE2_OP_MASK 0x001F /* AIF2DRC_KNEE2_OP - [4:0] */
+#define WM8994_AIF2DRC_KNEE2_OP_SHIFT 0 /* AIF2DRC_KNEE2_OP - [4:0] */
+#define WM8994_AIF2DRC_KNEE2_OP_WIDTH 5 /* AIF2DRC_KNEE2_OP - [4:0] */
+
+/*
+ * R1408 (0x580) - AIF2 EQ Gains (1)
+ */
+#define WM8994_AIF2DAC_EQ_B1_GAIN_MASK 0xF800 /* AIF2DAC_EQ_B1_GAIN - [15:11] */
+#define WM8994_AIF2DAC_EQ_B1_GAIN_SHIFT 11 /* AIF2DAC_EQ_B1_GAIN - [15:11] */
+#define WM8994_AIF2DAC_EQ_B1_GAIN_WIDTH 5 /* AIF2DAC_EQ_B1_GAIN - [15:11] */
+#define WM8994_AIF2DAC_EQ_B2_GAIN_MASK 0x07C0 /* AIF2DAC_EQ_B2_GAIN - [10:6] */
+#define WM8994_AIF2DAC_EQ_B2_GAIN_SHIFT 6 /* AIF2DAC_EQ_B2_GAIN - [10:6] */
+#define WM8994_AIF2DAC_EQ_B2_GAIN_WIDTH 5 /* AIF2DAC_EQ_B2_GAIN - [10:6] */
+#define WM8994_AIF2DAC_EQ_B3_GAIN_MASK 0x003E /* AIF2DAC_EQ_B3_GAIN - [5:1] */
+#define WM8994_AIF2DAC_EQ_B3_GAIN_SHIFT 1 /* AIF2DAC_EQ_B3_GAIN - [5:1] */
+#define WM8994_AIF2DAC_EQ_B3_GAIN_WIDTH 5 /* AIF2DAC_EQ_B3_GAIN - [5:1] */
+#define WM8994_AIF2DAC_EQ_ENA 0x0001 /* AIF2DAC_EQ_ENA */
+#define WM8994_AIF2DAC_EQ_ENA_MASK 0x0001 /* AIF2DAC_EQ_ENA */
+#define WM8994_AIF2DAC_EQ_ENA_SHIFT 0 /* AIF2DAC_EQ_ENA */
+#define WM8994_AIF2DAC_EQ_ENA_WIDTH 1 /* AIF2DAC_EQ_ENA */
+
+/*
+ * R1409 (0x581) - AIF2 EQ Gains (2)
+ */
+#define WM8994_AIF2DAC_EQ_B4_GAIN_MASK 0xF800 /* AIF2DAC_EQ_B4_GAIN - [15:11] */
+#define WM8994_AIF2DAC_EQ_B4_GAIN_SHIFT 11 /* AIF2DAC_EQ_B4_GAIN - [15:11] */
+#define WM8994_AIF2DAC_EQ_B4_GAIN_WIDTH 5 /* AIF2DAC_EQ_B4_GAIN - [15:11] */
+#define WM8994_AIF2DAC_EQ_B5_GAIN_MASK 0x07C0 /* AIF2DAC_EQ_B5_GAIN - [10:6] */
+#define WM8994_AIF2DAC_EQ_B5_GAIN_SHIFT 6 /* AIF2DAC_EQ_B5_GAIN - [10:6] */
+#define WM8994_AIF2DAC_EQ_B5_GAIN_WIDTH 5 /* AIF2DAC_EQ_B5_GAIN - [10:6] */
+
+/*
+ * R1410 (0x582) - AIF2 EQ Band 1 A
+ */
+#define WM8994_AIF2DAC_EQ_B1_A_MASK 0xFFFF /* AIF2DAC_EQ_B1_A - [15:0] */
+#define WM8994_AIF2DAC_EQ_B1_A_SHIFT 0 /* AIF2DAC_EQ_B1_A - [15:0] */
+#define WM8994_AIF2DAC_EQ_B1_A_WIDTH 16 /* AIF2DAC_EQ_B1_A - [15:0] */
+
+/*
+ * R1411 (0x583) - AIF2 EQ Band 1 B
+ */
+#define WM8994_AIF2DAC_EQ_B1_B_MASK 0xFFFF /* AIF2DAC_EQ_B1_B - [15:0] */
+#define WM8994_AIF2DAC_EQ_B1_B_SHIFT 0 /* AIF2DAC_EQ_B1_B - [15:0] */
+#define WM8994_AIF2DAC_EQ_B1_B_WIDTH 16 /* AIF2DAC_EQ_B1_B - [15:0] */
+
+/*
+ * R1412 (0x584) - AIF2 EQ Band 1 PG
+ */
+#define WM8994_AIF2DAC_EQ_B1_PG_MASK 0xFFFF /* AIF2DAC_EQ_B1_PG - [15:0] */
+#define WM8994_AIF2DAC_EQ_B1_PG_SHIFT 0 /* AIF2DAC_EQ_B1_PG - [15:0] */
+#define WM8994_AIF2DAC_EQ_B1_PG_WIDTH 16 /* AIF2DAC_EQ_B1_PG - [15:0] */
+
+/*
+ * R1413 (0x585) - AIF2 EQ Band 2 A
+ */
+#define WM8994_AIF2DAC_EQ_B2_A_MASK 0xFFFF /* AIF2DAC_EQ_B2_A - [15:0] */
+#define WM8994_AIF2DAC_EQ_B2_A_SHIFT 0 /* AIF2DAC_EQ_B2_A - [15:0] */
+#define WM8994_AIF2DAC_EQ_B2_A_WIDTH 16 /* AIF2DAC_EQ_B2_A - [15:0] */
+
+/*
+ * R1414 (0x586) - AIF2 EQ Band 2 B
+ */
+#define WM8994_AIF2DAC_EQ_B2_B_MASK 0xFFFF /* AIF2DAC_EQ_B2_B - [15:0] */
+#define WM8994_AIF2DAC_EQ_B2_B_SHIFT 0 /* AIF2DAC_EQ_B2_B - [15:0] */
+#define WM8994_AIF2DAC_EQ_B2_B_WIDTH 16 /* AIF2DAC_EQ_B2_B - [15:0] */
+
+/*
+ * R1415 (0x587) - AIF2 EQ Band 2 C
+ */
+#define WM8994_AIF2DAC_EQ_B2_C_MASK 0xFFFF /* AIF2DAC_EQ_B2_C - [15:0] */
+#define WM8994_AIF2DAC_EQ_B2_C_SHIFT 0 /* AIF2DAC_EQ_B2_C - [15:0] */
+#define WM8994_AIF2DAC_EQ_B2_C_WIDTH 16 /* AIF2DAC_EQ_B2_C - [15:0] */
+
+/*
+ * R1416 (0x588) - AIF2 EQ Band 2 PG
+ */
+#define WM8994_AIF2DAC_EQ_B2_PG_MASK 0xFFFF /* AIF2DAC_EQ_B2_PG - [15:0] */
+#define WM8994_AIF2DAC_EQ_B2_PG_SHIFT 0 /* AIF2DAC_EQ_B2_PG - [15:0] */
+#define WM8994_AIF2DAC_EQ_B2_PG_WIDTH 16 /* AIF2DAC_EQ_B2_PG - [15:0] */
+
+/*
+ * R1417 (0x589) - AIF2 EQ Band 3 A
+ */
+#define WM8994_AIF2DAC_EQ_B3_A_MASK 0xFFFF /* AIF2DAC_EQ_B3_A - [15:0] */
+#define WM8994_AIF2DAC_EQ_B3_A_SHIFT 0 /* AIF2DAC_EQ_B3_A - [15:0] */
+#define WM8994_AIF2DAC_EQ_B3_A_WIDTH 16 /* AIF2DAC_EQ_B3_A - [15:0] */
+
+/*
+ * R1418 (0x58A) - AIF2 EQ Band 3 B
+ */
+#define WM8994_AIF2DAC_EQ_B3_B_MASK 0xFFFF /* AIF2DAC_EQ_B3_B - [15:0] */
+#define WM8994_AIF2DAC_EQ_B3_B_SHIFT 0 /* AIF2DAC_EQ_B3_B - [15:0] */
+#define WM8994_AIF2DAC_EQ_B3_B_WIDTH 16 /* AIF2DAC_EQ_B3_B - [15:0] */
+
+/*
+ * R1419 (0x58B) - AIF2 EQ Band 3 C
+ */
+#define WM8994_AIF2DAC_EQ_B3_C_MASK 0xFFFF /* AIF2DAC_EQ_B3_C - [15:0] */
+#define WM8994_AIF2DAC_EQ_B3_C_SHIFT 0 /* AIF2DAC_EQ_B3_C - [15:0] */
+#define WM8994_AIF2DAC_EQ_B3_C_WIDTH 16 /* AIF2DAC_EQ_B3_C - [15:0] */
+
+/*
+ * R1420 (0x58C) - AIF2 EQ Band 3 PG
+ */
+#define WM8994_AIF2DAC_EQ_B3_PG_MASK 0xFFFF /* AIF2DAC_EQ_B3_PG - [15:0] */
+#define WM8994_AIF2DAC_EQ_B3_PG_SHIFT 0 /* AIF2DAC_EQ_B3_PG - [15:0] */
+#define WM8994_AIF2DAC_EQ_B3_PG_WIDTH 16 /* AIF2DAC_EQ_B3_PG - [15:0] */
+
+/*
+ * R1421 (0x58D) - AIF2 EQ Band 4 A
+ */
+#define WM8994_AIF2DAC_EQ_B4_A_MASK 0xFFFF /* AIF2DAC_EQ_B4_A - [15:0] */
+#define WM8994_AIF2DAC_EQ_B4_A_SHIFT 0 /* AIF2DAC_EQ_B4_A - [15:0] */
+#define WM8994_AIF2DAC_EQ_B4_A_WIDTH 16 /* AIF2DAC_EQ_B4_A - [15:0] */
+
+/*
+ * R1422 (0x58E) - AIF2 EQ Band 4 B
+ */
+#define WM8994_AIF2DAC_EQ_B4_B_MASK 0xFFFF /* AIF2DAC_EQ_B4_B - [15:0] */
+#define WM8994_AIF2DAC_EQ_B4_B_SHIFT 0 /* AIF2DAC_EQ_B4_B - [15:0] */
+#define WM8994_AIF2DAC_EQ_B4_B_WIDTH 16 /* AIF2DAC_EQ_B4_B - [15:0] */
+
+/*
+ * R1423 (0x58F) - AIF2 EQ Band 4 C
+ */
+#define WM8994_AIF2DAC_EQ_B4_C_MASK 0xFFFF /* AIF2DAC_EQ_B4_C - [15:0] */
+#define WM8994_AIF2DAC_EQ_B4_C_SHIFT 0 /* AIF2DAC_EQ_B4_C - [15:0] */
+#define WM8994_AIF2DAC_EQ_B4_C_WIDTH 16 /* AIF2DAC_EQ_B4_C - [15:0] */
+
+/*
+ * R1424 (0x590) - AIF2 EQ Band 4 PG
+ */
+#define WM8994_AIF2DAC_EQ_B4_PG_MASK 0xFFFF /* AIF2DAC_EQ_B4_PG - [15:0] */
+#define WM8994_AIF2DAC_EQ_B4_PG_SHIFT 0 /* AIF2DAC_EQ_B4_PG - [15:0] */
+#define WM8994_AIF2DAC_EQ_B4_PG_WIDTH 16 /* AIF2DAC_EQ_B4_PG - [15:0] */
+
+/*
+ * R1425 (0x591) - AIF2 EQ Band 5 A
+ */
+#define WM8994_AIF2DAC_EQ_B5_A_MASK 0xFFFF /* AIF2DAC_EQ_B5_A - [15:0] */
+#define WM8994_AIF2DAC_EQ_B5_A_SHIFT 0 /* AIF2DAC_EQ_B5_A - [15:0] */
+#define WM8994_AIF2DAC_EQ_B5_A_WIDTH 16 /* AIF2DAC_EQ_B5_A - [15:0] */
+
+/*
+ * R1426 (0x592) - AIF2 EQ Band 5 B
+ */
+#define WM8994_AIF2DAC_EQ_B5_B_MASK 0xFFFF /* AIF2DAC_EQ_B5_B - [15:0] */
+#define WM8994_AIF2DAC_EQ_B5_B_SHIFT 0 /* AIF2DAC_EQ_B5_B - [15:0] */
+#define WM8994_AIF2DAC_EQ_B5_B_WIDTH 16 /* AIF2DAC_EQ_B5_B - [15:0] */
+
+/*
+ * R1427 (0x593) - AIF2 EQ Band 5 PG
+ */
+#define WM8994_AIF2DAC_EQ_B5_PG_MASK 0xFFFF /* AIF2DAC_EQ_B5_PG - [15:0] */
+#define WM8994_AIF2DAC_EQ_B5_PG_SHIFT 0 /* AIF2DAC_EQ_B5_PG - [15:0] */
+#define WM8994_AIF2DAC_EQ_B5_PG_WIDTH 16 /* AIF2DAC_EQ_B5_PG - [15:0] */
+
+/*
+ * R1536 (0x600) - DAC1 Mixer Volumes
+ */
+#define WM8994_ADC2_DAC1_VOL_MASK 0x01E0 /* ADC2_DAC1_VOL - [8:5] */
+#define WM8994_ADC2_DAC1_VOL_SHIFT 5 /* ADC2_DAC1_VOL - [8:5] */
+#define WM8994_ADC2_DAC1_VOL_WIDTH 4 /* ADC2_DAC1_VOL - [8:5] */
+#define WM8994_ADC1_DAC1_VOL_MASK 0x000F /* ADC1_DAC1_VOL - [3:0] */
+#define WM8994_ADC1_DAC1_VOL_SHIFT 0 /* ADC1_DAC1_VOL - [3:0] */
+#define WM8994_ADC1_DAC1_VOL_WIDTH 4 /* ADC1_DAC1_VOL - [3:0] */
+
+/*
+ * R1537 (0x601) - DAC1 Left Mixer Routing
+ */
+#define WM8994_ADC2_TO_DAC1L 0x0020 /* ADC2_TO_DAC1L */
+#define WM8994_ADC2_TO_DAC1L_MASK 0x0020 /* ADC2_TO_DAC1L */
+#define WM8994_ADC2_TO_DAC1L_SHIFT 5 /* ADC2_TO_DAC1L */
+#define WM8994_ADC2_TO_DAC1L_WIDTH 1 /* ADC2_TO_DAC1L */
+#define WM8994_ADC1_TO_DAC1L 0x0010 /* ADC1_TO_DAC1L */
+#define WM8994_ADC1_TO_DAC1L_MASK 0x0010 /* ADC1_TO_DAC1L */
+#define WM8994_ADC1_TO_DAC1L_SHIFT 4 /* ADC1_TO_DAC1L */
+#define WM8994_ADC1_TO_DAC1L_WIDTH 1 /* ADC1_TO_DAC1L */
+#define WM8994_AIF2DACL_TO_DAC1L 0x0004 /* AIF2DACL_TO_DAC1L */
+#define WM8994_AIF2DACL_TO_DAC1L_MASK 0x0004 /* AIF2DACL_TO_DAC1L */
+#define WM8994_AIF2DACL_TO_DAC1L_SHIFT 2 /* AIF2DACL_TO_DAC1L */
+#define WM8994_AIF2DACL_TO_DAC1L_WIDTH 1 /* AIF2DACL_TO_DAC1L */
+#define WM8994_AIF1DAC2L_TO_DAC1L 0x0002 /* AIF1DAC2L_TO_DAC1L */
+#define WM8994_AIF1DAC2L_TO_DAC1L_MASK 0x0002 /* AIF1DAC2L_TO_DAC1L */
+#define WM8994_AIF1DAC2L_TO_DAC1L_SHIFT 1 /* AIF1DAC2L_TO_DAC1L */
+#define WM8994_AIF1DAC2L_TO_DAC1L_WIDTH 1 /* AIF1DAC2L_TO_DAC1L */
+#define WM8994_AIF1DAC1L_TO_DAC1L 0x0001 /* AIF1DAC1L_TO_DAC1L */
+#define WM8994_AIF1DAC1L_TO_DAC1L_MASK 0x0001 /* AIF1DAC1L_TO_DAC1L */
+#define WM8994_AIF1DAC1L_TO_DAC1L_SHIFT 0 /* AIF1DAC1L_TO_DAC1L */
+#define WM8994_AIF1DAC1L_TO_DAC1L_WIDTH 1 /* AIF1DAC1L_TO_DAC1L */
+
+/*
+ * R1538 (0x602) - DAC1 Right Mixer Routing
+ */
+#define WM8994_ADC2_TO_DAC1R 0x0020 /* ADC2_TO_DAC1R */
+#define WM8994_ADC2_TO_DAC1R_MASK 0x0020 /* ADC2_TO_DAC1R */
+#define WM8994_ADC2_TO_DAC1R_SHIFT 5 /* ADC2_TO_DAC1R */
+#define WM8994_ADC2_TO_DAC1R_WIDTH 1 /* ADC2_TO_DAC1R */
+#define WM8994_ADC1_TO_DAC1R 0x0010 /* ADC1_TO_DAC1R */
+#define WM8994_ADC1_TO_DAC1R_MASK 0x0010 /* ADC1_TO_DAC1R */
+#define WM8994_ADC1_TO_DAC1R_SHIFT 4 /* ADC1_TO_DAC1R */
+#define WM8994_ADC1_TO_DAC1R_WIDTH 1 /* ADC1_TO_DAC1R */
+#define WM8994_AIF2DACR_TO_DAC1R 0x0004 /* AIF2DACR_TO_DAC1R */
+#define WM8994_AIF2DACR_TO_DAC1R_MASK 0x0004 /* AIF2DACR_TO_DAC1R */
+#define WM8994_AIF2DACR_TO_DAC1R_SHIFT 2 /* AIF2DACR_TO_DAC1R */
+#define WM8994_AIF2DACR_TO_DAC1R_WIDTH 1 /* AIF2DACR_TO_DAC1R */
+#define WM8994_AIF1DAC2R_TO_DAC1R 0x0002 /* AIF1DAC2R_TO_DAC1R */
+#define WM8994_AIF1DAC2R_TO_DAC1R_MASK 0x0002 /* AIF1DAC2R_TO_DAC1R */
+#define WM8994_AIF1DAC2R_TO_DAC1R_SHIFT 1 /* AIF1DAC2R_TO_DAC1R */
+#define WM8994_AIF1DAC2R_TO_DAC1R_WIDTH 1 /* AIF1DAC2R_TO_DAC1R */
+#define WM8994_AIF1DAC1R_TO_DAC1R 0x0001 /* AIF1DAC1R_TO_DAC1R */
+#define WM8994_AIF1DAC1R_TO_DAC1R_MASK 0x0001 /* AIF1DAC1R_TO_DAC1R */
+#define WM8994_AIF1DAC1R_TO_DAC1R_SHIFT 0 /* AIF1DAC1R_TO_DAC1R */
+#define WM8994_AIF1DAC1R_TO_DAC1R_WIDTH 1 /* AIF1DAC1R_TO_DAC1R */
+
+/*
+ * R1539 (0x603) - DAC2 Mixer Volumes
+ */
+#define WM8994_ADC2_DAC2_VOL_MASK 0x01E0 /* ADC2_DAC2_VOL - [8:5] */
+#define WM8994_ADC2_DAC2_VOL_SHIFT 5 /* ADC2_DAC2_VOL - [8:5] */
+#define WM8994_ADC2_DAC2_VOL_WIDTH 4 /* ADC2_DAC2_VOL - [8:5] */
+#define WM8994_ADC1_DAC2_VOL_MASK 0x000F /* ADC1_DAC2_VOL - [3:0] */
+#define WM8994_ADC1_DAC2_VOL_SHIFT 0 /* ADC1_DAC2_VOL - [3:0] */
+#define WM8994_ADC1_DAC2_VOL_WIDTH 4 /* ADC1_DAC2_VOL - [3:0] */
+
+/*
+ * R1540 (0x604) - DAC2 Left Mixer Routing
+ */
+#define WM8994_ADC2_TO_DAC2L 0x0020 /* ADC2_TO_DAC2L */
+#define WM8994_ADC2_TO_DAC2L_MASK 0x0020 /* ADC2_TO_DAC2L */
+#define WM8994_ADC2_TO_DAC2L_SHIFT 5 /* ADC2_TO_DAC2L */
+#define WM8994_ADC2_TO_DAC2L_WIDTH 1 /* ADC2_TO_DAC2L */
+#define WM8994_ADC1_TO_DAC2L 0x0010 /* ADC1_TO_DAC2L */
+#define WM8994_ADC1_TO_DAC2L_MASK 0x0010 /* ADC1_TO_DAC2L */
+#define WM8994_ADC1_TO_DAC2L_SHIFT 4 /* ADC1_TO_DAC2L */
+#define WM8994_ADC1_TO_DAC2L_WIDTH 1 /* ADC1_TO_DAC2L */
+#define WM8994_AIF2DACL_TO_DAC2L 0x0004 /* AIF2DACL_TO_DAC2L */
+#define WM8994_AIF2DACL_TO_DAC2L_MASK 0x0004 /* AIF2DACL_TO_DAC2L */
+#define WM8994_AIF2DACL_TO_DAC2L_SHIFT 2 /* AIF2DACL_TO_DAC2L */
+#define WM8994_AIF2DACL_TO_DAC2L_WIDTH 1 /* AIF2DACL_TO_DAC2L */
+#define WM8994_AIF1DAC2L_TO_DAC2L 0x0002 /* AIF1DAC2L_TO_DAC2L */
+#define WM8994_AIF1DAC2L_TO_DAC2L_MASK 0x0002 /* AIF1DAC2L_TO_DAC2L */
+#define WM8994_AIF1DAC2L_TO_DAC2L_SHIFT 1 /* AIF1DAC2L_TO_DAC2L */
+#define WM8994_AIF1DAC2L_TO_DAC2L_WIDTH 1 /* AIF1DAC2L_TO_DAC2L */
+#define WM8994_AIF1DAC1L_TO_DAC2L 0x0001 /* AIF1DAC1L_TO_DAC2L */
+#define WM8994_AIF1DAC1L_TO_DAC2L_MASK 0x0001 /* AIF1DAC1L_TO_DAC2L */
+#define WM8994_AIF1DAC1L_TO_DAC2L_SHIFT 0 /* AIF1DAC1L_TO_DAC2L */
+#define WM8994_AIF1DAC1L_TO_DAC2L_WIDTH 1 /* AIF1DAC1L_TO_DAC2L */
+
+/*
+ * R1541 (0x605) - DAC2 Right Mixer Routing
+ */
+#define WM8994_ADC2_TO_DAC2R 0x0020 /* ADC2_TO_DAC2R */
+#define WM8994_ADC2_TO_DAC2R_MASK 0x0020 /* ADC2_TO_DAC2R */
+#define WM8994_ADC2_TO_DAC2R_SHIFT 5 /* ADC2_TO_DAC2R */
+#define WM8994_ADC2_TO_DAC2R_WIDTH 1 /* ADC2_TO_DAC2R */
+#define WM8994_ADC1_TO_DAC2R 0x0010 /* ADC1_TO_DAC2R */
+#define WM8994_ADC1_TO_DAC2R_MASK 0x0010 /* ADC1_TO_DAC2R */
+#define WM8994_ADC1_TO_DAC2R_SHIFT 4 /* ADC1_TO_DAC2R */
+#define WM8994_ADC1_TO_DAC2R_WIDTH 1 /* ADC1_TO_DAC2R */
+#define WM8994_AIF2DACR_TO_DAC2R 0x0004 /* AIF2DACR_TO_DAC2R */
+#define WM8994_AIF2DACR_TO_DAC2R_MASK 0x0004 /* AIF2DACR_TO_DAC2R */
+#define WM8994_AIF2DACR_TO_DAC2R_SHIFT 2 /* AIF2DACR_TO_DAC2R */
+#define WM8994_AIF2DACR_TO_DAC2R_WIDTH 1 /* AIF2DACR_TO_DAC2R */
+#define WM8994_AIF1DAC2R_TO_DAC2R 0x0002 /* AIF1DAC2R_TO_DAC2R */
+#define WM8994_AIF1DAC2R_TO_DAC2R_MASK 0x0002 /* AIF1DAC2R_TO_DAC2R */
+#define WM8994_AIF1DAC2R_TO_DAC2R_SHIFT 1 /* AIF1DAC2R_TO_DAC2R */
+#define WM8994_AIF1DAC2R_TO_DAC2R_WIDTH 1 /* AIF1DAC2R_TO_DAC2R */
+#define WM8994_AIF1DAC1R_TO_DAC2R 0x0001 /* AIF1DAC1R_TO_DAC2R */
+#define WM8994_AIF1DAC1R_TO_DAC2R_MASK 0x0001 /* AIF1DAC1R_TO_DAC2R */
+#define WM8994_AIF1DAC1R_TO_DAC2R_SHIFT 0 /* AIF1DAC1R_TO_DAC2R */
+#define WM8994_AIF1DAC1R_TO_DAC2R_WIDTH 1 /* AIF1DAC1R_TO_DAC2R */
+
+/*
+ * R1542 (0x606) - AIF1 ADC1 Left Mixer Routing
+ */
+#define WM8994_ADC1L_TO_AIF1ADC1L 0x0002 /* ADC1L_TO_AIF1ADC1L */
+#define WM8994_ADC1L_TO_AIF1ADC1L_MASK 0x0002 /* ADC1L_TO_AIF1ADC1L */
+#define WM8994_ADC1L_TO_AIF1ADC1L_SHIFT 1 /* ADC1L_TO_AIF1ADC1L */
+#define WM8994_ADC1L_TO_AIF1ADC1L_WIDTH 1 /* ADC1L_TO_AIF1ADC1L */
+#define WM8994_AIF2DACL_TO_AIF1ADC1L 0x0001 /* AIF2DACL_TO_AIF1ADC1L */
+#define WM8994_AIF2DACL_TO_AIF1ADC1L_MASK 0x0001 /* AIF2DACL_TO_AIF1ADC1L */
+#define WM8994_AIF2DACL_TO_AIF1ADC1L_SHIFT 0 /* AIF2DACL_TO_AIF1ADC1L */
+#define WM8994_AIF2DACL_TO_AIF1ADC1L_WIDTH 1 /* AIF2DACL_TO_AIF1ADC1L */
+
+/*
+ * R1543 (0x607) - AIF1 ADC1 Right Mixer Routing
+ */
+#define WM8994_ADC1R_TO_AIF1ADC1R 0x0002 /* ADC1R_TO_AIF1ADC1R */
+#define WM8994_ADC1R_TO_AIF1ADC1R_MASK 0x0002 /* ADC1R_TO_AIF1ADC1R */
+#define WM8994_ADC1R_TO_AIF1ADC1R_SHIFT 1 /* ADC1R_TO_AIF1ADC1R */
+#define WM8994_ADC1R_TO_AIF1ADC1R_WIDTH 1 /* ADC1R_TO_AIF1ADC1R */
+#define WM8994_AIF2DACR_TO_AIF1ADC1R 0x0001 /* AIF2DACR_TO_AIF1ADC1R */
+#define WM8994_AIF2DACR_TO_AIF1ADC1R_MASK 0x0001 /* AIF2DACR_TO_AIF1ADC1R */
+#define WM8994_AIF2DACR_TO_AIF1ADC1R_SHIFT 0 /* AIF2DACR_TO_AIF1ADC1R */
+#define WM8994_AIF2DACR_TO_AIF1ADC1R_WIDTH 1 /* AIF2DACR_TO_AIF1ADC1R */
+
+/*
+ * R1544 (0x608) - AIF1 ADC2 Left Mixer Routing
+ */
+#define WM8994_ADC2L_TO_AIF1ADC2L 0x0002 /* ADC2L_TO_AIF1ADC2L */
+#define WM8994_ADC2L_TO_AIF1ADC2L_MASK 0x0002 /* ADC2L_TO_AIF1ADC2L */
+#define WM8994_ADC2L_TO_AIF1ADC2L_SHIFT 1 /* ADC2L_TO_AIF1ADC2L */
+#define WM8994_ADC2L_TO_AIF1ADC2L_WIDTH 1 /* ADC2L_TO_AIF1ADC2L */
+#define WM8994_AIF2DACL_TO_AIF1ADC2L 0x0001 /* AIF2DACL_TO_AIF1ADC2L */
+#define WM8994_AIF2DACL_TO_AIF1ADC2L_MASK 0x0001 /* AIF2DACL_TO_AIF1ADC2L */
+#define WM8994_AIF2DACL_TO_AIF1ADC2L_SHIFT 0 /* AIF2DACL_TO_AIF1ADC2L */
+#define WM8994_AIF2DACL_TO_AIF1ADC2L_WIDTH 1 /* AIF2DACL_TO_AIF1ADC2L */
+
+/*
+ * R1545 (0x609) - AIF1 ADC2 Right mixer Routing
+ */
+#define WM8994_ADC2R_TO_AIF1ADC2R 0x0002 /* ADC2R_TO_AIF1ADC2R */
+#define WM8994_ADC2R_TO_AIF1ADC2R_MASK 0x0002 /* ADC2R_TO_AIF1ADC2R */
+#define WM8994_ADC2R_TO_AIF1ADC2R_SHIFT 1 /* ADC2R_TO_AIF1ADC2R */
+#define WM8994_ADC2R_TO_AIF1ADC2R_WIDTH 1 /* ADC2R_TO_AIF1ADC2R */
+#define WM8994_AIF2DACR_TO_AIF1ADC2R 0x0001 /* AIF2DACR_TO_AIF1ADC2R */
+#define WM8994_AIF2DACR_TO_AIF1ADC2R_MASK 0x0001 /* AIF2DACR_TO_AIF1ADC2R */
+#define WM8994_AIF2DACR_TO_AIF1ADC2R_SHIFT 0 /* AIF2DACR_TO_AIF1ADC2R */
+#define WM8994_AIF2DACR_TO_AIF1ADC2R_WIDTH 1 /* AIF2DACR_TO_AIF1ADC2R */
+
+/*
+ * R1552 (0x610) - DAC1 Left Volume
+ */
+#define WM8994_DAC1L_MUTE 0x0200 /* DAC1L_MUTE */
+#define WM8994_DAC1L_MUTE_MASK 0x0200 /* DAC1L_MUTE */
+#define WM8994_DAC1L_MUTE_SHIFT 9 /* DAC1L_MUTE */
+#define WM8994_DAC1L_MUTE_WIDTH 1 /* DAC1L_MUTE */
+#define WM8994_DAC1_VU 0x0100 /* DAC1_VU */
+#define WM8994_DAC1_VU_MASK 0x0100 /* DAC1_VU */
+#define WM8994_DAC1_VU_SHIFT 8 /* DAC1_VU */
+#define WM8994_DAC1_VU_WIDTH 1 /* DAC1_VU */
+#define WM8994_DAC1L_VOL_MASK 0x00FF /* DAC1L_VOL - [7:0] */
+#define WM8994_DAC1L_VOL_SHIFT 0 /* DAC1L_VOL - [7:0] */
+#define WM8994_DAC1L_VOL_WIDTH 8 /* DAC1L_VOL - [7:0] */
+
+/*
+ * R1553 (0x611) - DAC1 Right Volume
+ */
+#define WM8994_DAC1R_MUTE 0x0200 /* DAC1R_MUTE */
+#define WM8994_DAC1R_MUTE_MASK 0x0200 /* DAC1R_MUTE */
+#define WM8994_DAC1R_MUTE_SHIFT 9 /* DAC1R_MUTE */
+#define WM8994_DAC1R_MUTE_WIDTH 1 /* DAC1R_MUTE */
+#define WM8994_DAC1_VU 0x0100 /* DAC1_VU */
+#define WM8994_DAC1_VU_MASK 0x0100 /* DAC1_VU */
+#define WM8994_DAC1_VU_SHIFT 8 /* DAC1_VU */
+#define WM8994_DAC1_VU_WIDTH 1 /* DAC1_VU */
+#define WM8994_DAC1R_VOL_MASK 0x00FF /* DAC1R_VOL - [7:0] */
+#define WM8994_DAC1R_VOL_SHIFT 0 /* DAC1R_VOL - [7:0] */
+#define WM8994_DAC1R_VOL_WIDTH 8 /* DAC1R_VOL - [7:0] */
+
+/*
+ * R1554 (0x612) - DAC2 Left Volume
+ */
+#define WM8994_DAC2L_MUTE 0x0200 /* DAC2L_MUTE */
+#define WM8994_DAC2L_MUTE_MASK 0x0200 /* DAC2L_MUTE */
+#define WM8994_DAC2L_MUTE_SHIFT 9 /* DAC2L_MUTE */
+#define WM8994_DAC2L_MUTE_WIDTH 1 /* DAC2L_MUTE */
+#define WM8994_DAC2_VU 0x0100 /* DAC2_VU */
+#define WM8994_DAC2_VU_MASK 0x0100 /* DAC2_VU */
+#define WM8994_DAC2_VU_SHIFT 8 /* DAC2_VU */
+#define WM8994_DAC2_VU_WIDTH 1 /* DAC2_VU */
+#define WM8994_DAC2L_VOL_MASK 0x00FF /* DAC2L_VOL - [7:0] */
+#define WM8994_DAC2L_VOL_SHIFT 0 /* DAC2L_VOL - [7:0] */
+#define WM8994_DAC2L_VOL_WIDTH 8 /* DAC2L_VOL - [7:0] */
+
+/*
+ * R1555 (0x613) - DAC2 Right Volume
+ */
+#define WM8994_DAC2R_MUTE 0x0200 /* DAC2R_MUTE */
+#define WM8994_DAC2R_MUTE_MASK 0x0200 /* DAC2R_MUTE */
+#define WM8994_DAC2R_MUTE_SHIFT 9 /* DAC2R_MUTE */
+#define WM8994_DAC2R_MUTE_WIDTH 1 /* DAC2R_MUTE */
+#define WM8994_DAC2_VU 0x0100 /* DAC2_VU */
+#define WM8994_DAC2_VU_MASK 0x0100 /* DAC2_VU */
+#define WM8994_DAC2_VU_SHIFT 8 /* DAC2_VU */
+#define WM8994_DAC2_VU_WIDTH 1 /* DAC2_VU */
+#define WM8994_DAC2R_VOL_MASK 0x00FF /* DAC2R_VOL - [7:0] */
+#define WM8994_DAC2R_VOL_SHIFT 0 /* DAC2R_VOL - [7:0] */
+#define WM8994_DAC2R_VOL_WIDTH 8 /* DAC2R_VOL - [7:0] */
+
+/*
+ * R1556 (0x614) - DAC Softmute
+ */
+#define WM8994_DAC_SOFTMUTEMODE 0x0002 /* DAC_SOFTMUTEMODE */
+#define WM8994_DAC_SOFTMUTEMODE_MASK 0x0002 /* DAC_SOFTMUTEMODE */
+#define WM8994_DAC_SOFTMUTEMODE_SHIFT 1 /* DAC_SOFTMUTEMODE */
+#define WM8994_DAC_SOFTMUTEMODE_WIDTH 1 /* DAC_SOFTMUTEMODE */
+#define WM8994_DAC_MUTERATE 0x0001 /* DAC_MUTERATE */
+#define WM8994_DAC_MUTERATE_MASK 0x0001 /* DAC_MUTERATE */
+#define WM8994_DAC_MUTERATE_SHIFT 0 /* DAC_MUTERATE */
+#define WM8994_DAC_MUTERATE_WIDTH 1 /* DAC_MUTERATE */
+
+/*
+ * R1568 (0x620) - Oversampling
+ */
+#define WM8994_ADC_OSR128 0x0002 /* ADC_OSR128 */
+#define WM8994_ADC_OSR128_MASK 0x0002 /* ADC_OSR128 */
+#define WM8994_ADC_OSR128_SHIFT 1 /* ADC_OSR128 */
+#define WM8994_ADC_OSR128_WIDTH 1 /* ADC_OSR128 */
+#define WM8994_DAC_OSR128 0x0001 /* DAC_OSR128 */
+#define WM8994_DAC_OSR128_MASK 0x0001 /* DAC_OSR128 */
+#define WM8994_DAC_OSR128_SHIFT 0 /* DAC_OSR128 */
+#define WM8994_DAC_OSR128_WIDTH 1 /* DAC_OSR128 */
+
+/*
+ * R1569 (0x621) - Sidetone
+ */
+#define WM8994_ST_HPF_CUT_MASK 0x0380 /* ST_HPF_CUT - [9:7] */
+#define WM8994_ST_HPF_CUT_SHIFT 7 /* ST_HPF_CUT - [9:7] */
+#define WM8994_ST_HPF_CUT_WIDTH 3 /* ST_HPF_CUT - [9:7] */
+#define WM8994_ST_HPF 0x0040 /* ST_HPF */
+#define WM8994_ST_HPF_MASK 0x0040 /* ST_HPF */
+#define WM8994_ST_HPF_SHIFT 6 /* ST_HPF */
+#define WM8994_ST_HPF_WIDTH 1 /* ST_HPF */
+#define WM8994_ST2_SEL 0x0002 /* ST2_SEL */
+#define WM8994_ST2_SEL_MASK 0x0002 /* ST2_SEL */
+#define WM8994_ST2_SEL_SHIFT 1 /* ST2_SEL */
+#define WM8994_ST2_SEL_WIDTH 1 /* ST2_SEL */
+#define WM8994_ST1_SEL 0x0001 /* ST1_SEL */
+#define WM8994_ST1_SEL_MASK 0x0001 /* ST1_SEL */
+#define WM8994_ST1_SEL_SHIFT 0 /* ST1_SEL */
+#define WM8994_ST1_SEL_WIDTH 1 /* ST1_SEL */
+
+/*
+ * R1792 (0x700) - GPIO 1
+ */
+#define WM8994_GP1_DIR 0x8000 /* GP1_DIR */
+#define WM8994_GP1_DIR_MASK 0x8000 /* GP1_DIR */
+#define WM8994_GP1_DIR_SHIFT 15 /* GP1_DIR */
+#define WM8994_GP1_DIR_WIDTH 1 /* GP1_DIR */
+#define WM8994_GP1_PU 0x4000 /* GP1_PU */
+#define WM8994_GP1_PU_MASK 0x4000 /* GP1_PU */
+#define WM8994_GP1_PU_SHIFT 14 /* GP1_PU */
+#define WM8994_GP1_PU_WIDTH 1 /* GP1_PU */
+#define WM8994_GP1_PD 0x2000 /* GP1_PD */
+#define WM8994_GP1_PD_MASK 0x2000 /* GP1_PD */
+#define WM8994_GP1_PD_SHIFT 13 /* GP1_PD */
+#define WM8994_GP1_PD_WIDTH 1 /* GP1_PD */
+#define WM8994_GP1_POL 0x0400 /* GP1_POL */
+#define WM8994_GP1_POL_MASK 0x0400 /* GP1_POL */
+#define WM8994_GP1_POL_SHIFT 10 /* GP1_POL */
+#define WM8994_GP1_POL_WIDTH 1 /* GP1_POL */
+#define WM8994_GP1_OP_CFG 0x0200 /* GP1_OP_CFG */
+#define WM8994_GP1_OP_CFG_MASK 0x0200 /* GP1_OP_CFG */
+#define WM8994_GP1_OP_CFG_SHIFT 9 /* GP1_OP_CFG */
+#define WM8994_GP1_OP_CFG_WIDTH 1 /* GP1_OP_CFG */
+#define WM8994_GP1_DB 0x0100 /* GP1_DB */
+#define WM8994_GP1_DB_MASK 0x0100 /* GP1_DB */
+#define WM8994_GP1_DB_SHIFT 8 /* GP1_DB */
+#define WM8994_GP1_DB_WIDTH 1 /* GP1_DB */
+#define WM8994_GP1_LVL 0x0040 /* GP1_LVL */
+#define WM8994_GP1_LVL_MASK 0x0040 /* GP1_LVL */
+#define WM8994_GP1_LVL_SHIFT 6 /* GP1_LVL */
+#define WM8994_GP1_LVL_WIDTH 1 /* GP1_LVL */
+#define WM8994_GP1_FN_LOGIC_INOUT 0x0001
+#define WM8994_GP1_FN_MASK 0x001F /* GP1_FN - [4:0] */
+#define WM8994_GP1_FN_SHIFT 0 /* GP1_FN - [4:0] */
+#define WM8994_GP1_FN_WIDTH 5 /* GP1_FN - [4:0] */
+
+/*
+ * R1793 (0x701) - GPIO 2
+ */
+#define WM8994_GP2_PU 0x4000 /* GP2_PU */
+#define WM8994_GP2_PU_MASK 0x4000 /* GP2_PU */
+#define WM8994_GP2_PU_SHIFT 14 /* GP2_PU */
+#define WM8994_GP2_PU_WIDTH 1 /* GP2_PU */
+#define WM8994_GP2_PD 0x2000 /* GP2_PD */
+#define WM8994_GP2_PD_MASK 0x2000 /* GP2_PD */
+#define WM8994_GP2_PD_SHIFT 13 /* GP2_PD */
+#define WM8994_GP2_PD_WIDTH 1 /* GP2_PD */
+#define WM8994_GP2_POL 0x0400 /* GP2_POL */
+#define WM8994_GP2_POL_MASK 0x0400 /* GP2_POL */
+#define WM8994_GP2_POL_SHIFT 10 /* GP2_POL */
+#define WM8994_GP2_POL_WIDTH 1 /* GP2_POL */
+#define WM8994_GP2_OP_CFG 0x0200 /* GP2_OP_CFG */
+#define WM8994_GP2_OP_CFG_MASK 0x0200 /* GP2_OP_CFG */
+#define WM8994_GP2_OP_CFG_SHIFT 9 /* GP2_OP_CFG */
+#define WM8994_GP2_OP_CFG_WIDTH 1 /* GP2_OP_CFG */
+#define WM8994_GP2_LVL 0x0040 /* GP2_LVL */
+#define WM8994_GP2_LVL_MASK 0x0040 /* GP2_LVL */
+#define WM8994_GP2_LVL_SHIFT 6 /* GP2_LVL */
+#define WM8994_GP2_LVL_WIDTH 1 /* GP2_LVL */
+#define WM8994_GP2_FN_MASK 0x001F /* GP2_FN - [4:0] */
+#define WM8994_GP2_FN_SHIFT 0 /* GP2_FN - [4:0] */
+#define WM8994_GP2_FN_WIDTH 5 /* GP2_FN - [4:0] */
+
+/*
+ * R1794 (0x702) - GPIO 3
+ */
+#define WM8994_GP3_DIR 0x8000 /* GP3_DIR */
+#define WM8994_GP3_DIR_MASK 0x8000 /* GP3_DIR */
+#define WM8994_GP3_DIR_SHIFT 15 /* GP3_DIR */
+#define WM8994_GP3_DIR_WIDTH 1 /* GP3_DIR */
+#define WM8994_GP3_PU 0x4000 /* GP3_PU */
+#define WM8994_GP3_PU_MASK 0x4000 /* GP3_PU */
+#define WM8994_GP3_PU_SHIFT 14 /* GP3_PU */
+#define WM8994_GP3_PU_WIDTH 1 /* GP3_PU */
+#define WM8994_GP3_PD 0x2000 /* GP3_PD */
+#define WM8994_GP3_PD_MASK 0x2000 /* GP3_PD */
+#define WM8994_GP3_PD_SHIFT 13 /* GP3_PD */
+#define WM8994_GP3_PD_WIDTH 1 /* GP3_PD */
+#define WM8994_GP3_POL 0x0400 /* GP3_POL */
+#define WM8994_GP3_POL_MASK 0x0400 /* GP3_POL */
+#define WM8994_GP3_POL_SHIFT 10 /* GP3_POL */
+#define WM8994_GP3_POL_WIDTH 1 /* GP3_POL */
+#define WM8994_GP3_OP_CFG 0x0200 /* GP3_OP_CFG */
+#define WM8994_GP3_OP_CFG_MASK 0x0200 /* GP3_OP_CFG */
+#define WM8994_GP3_OP_CFG_SHIFT 9 /* GP3_OP_CFG */
+#define WM8994_GP3_OP_CFG_WIDTH 1 /* GP3_OP_CFG */
+#define WM8994_GP3_DB 0x0100 /* GP3_DB */
+#define WM8994_GP3_DB_MASK 0x0100 /* GP3_DB */
+#define WM8994_GP3_DB_SHIFT 8 /* GP3_DB */
+#define WM8994_GP3_DB_WIDTH 1 /* GP3_DB */
+#define WM8994_GP3_LVL 0x0040 /* GP3_LVL */
+#define WM8994_GP3_LVL_MASK 0x0040 /* GP3_LVL */
+#define WM8994_GP3_LVL_SHIFT 6 /* GP3_LVL */
+#define WM8994_GP3_LVL_WIDTH 1 /* GP3_LVL */
+#define WM8994_GP3_FN_MASK 0x001F /* GP3_FN - [4:0] */
+#define WM8994_GP3_FN_SHIFT 0 /* GP3_FN - [4:0] */
+#define WM8994_GP3_FN_WIDTH 5 /* GP3_FN - [4:0] */
+
+/*
+ * R1795 (0x703) - GPIO 4
+ */
+#define WM8994_GP4_DIR 0x8000 /* GP4_DIR */
+#define WM8994_GP4_DIR_MASK 0x8000 /* GP4_DIR */
+#define WM8994_GP4_DIR_SHIFT 15 /* GP4_DIR */
+#define WM8994_GP4_DIR_WIDTH 1 /* GP4_DIR */
+#define WM8994_GP4_PU 0x4000 /* GP4_PU */
+#define WM8994_GP4_PU_MASK 0x4000 /* GP4_PU */
+#define WM8994_GP4_PU_SHIFT 14 /* GP4_PU */
+#define WM8994_GP4_PU_WIDTH 1 /* GP4_PU */
+#define WM8994_GP4_PD 0x2000 /* GP4_PD */
+#define WM8994_GP4_PD_MASK 0x2000 /* GP4_PD */
+#define WM8994_GP4_PD_SHIFT 13 /* GP4_PD */
+#define WM8994_GP4_PD_WIDTH 1 /* GP4_PD */
+#define WM8994_GP4_POL 0x0400 /* GP4_POL */
+#define WM8994_GP4_POL_MASK 0x0400 /* GP4_POL */
+#define WM8994_GP4_POL_SHIFT 10 /* GP4_POL */
+#define WM8994_GP4_POL_WIDTH 1 /* GP4_POL */
+#define WM8994_GP4_OP_CFG 0x0200 /* GP4_OP_CFG */
+#define WM8994_GP4_OP_CFG_MASK 0x0200 /* GP4_OP_CFG */
+#define WM8994_GP4_OP_CFG_SHIFT 9 /* GP4_OP_CFG */
+#define WM8994_GP4_OP_CFG_WIDTH 1 /* GP4_OP_CFG */
+#define WM8994_GP4_DB 0x0100 /* GP4_DB */
+#define WM8994_GP4_DB_MASK 0x0100 /* GP4_DB */
+#define WM8994_GP4_DB_SHIFT 8 /* GP4_DB */
+#define WM8994_GP4_DB_WIDTH 1 /* GP4_DB */
+#define WM8994_GP4_LVL 0x0040 /* GP4_LVL */
+#define WM8994_GP4_LVL_MASK 0x0040 /* GP4_LVL */
+#define WM8994_GP4_LVL_SHIFT 6 /* GP4_LVL */
+#define WM8994_GP4_LVL_WIDTH 1 /* GP4_LVL */
+#define WM8994_GP4_FN_MASK 0x001F /* GP4_FN - [4:0] */
+#define WM8994_GP4_FN_SHIFT 0 /* GP4_FN - [4:0] */
+#define WM8994_GP4_FN_WIDTH 5 /* GP4_FN - [4:0] */
+
+/*
+ * R1796 (0x704) - GPIO 5
+ */
+#define WM8994_GP5_DIR 0x8000 /* GP5_DIR */
+#define WM8994_GP5_DIR_MASK 0x8000 /* GP5_DIR */
+#define WM8994_GP5_DIR_SHIFT 15 /* GP5_DIR */
+#define WM8994_GP5_DIR_WIDTH 1 /* GP5_DIR */
+#define WM8994_GP5_PU 0x4000 /* GP5_PU */
+#define WM8994_GP5_PU_MASK 0x4000 /* GP5_PU */
+#define WM8994_GP5_PU_SHIFT 14 /* GP5_PU */
+#define WM8994_GP5_PU_WIDTH 1 /* GP5_PU */
+#define WM8994_GP5_PD 0x2000 /* GP5_PD */
+#define WM8994_GP5_PD_MASK 0x2000 /* GP5_PD */
+#define WM8994_GP5_PD_SHIFT 13 /* GP5_PD */
+#define WM8994_GP5_PD_WIDTH 1 /* GP5_PD */
+#define WM8994_GP5_POL 0x0400 /* GP5_POL */
+#define WM8994_GP5_POL_MASK 0x0400 /* GP5_POL */
+#define WM8994_GP5_POL_SHIFT 10 /* GP5_POL */
+#define WM8994_GP5_POL_WIDTH 1 /* GP5_POL */
+#define WM8994_GP5_OP_CFG 0x0200 /* GP5_OP_CFG */
+#define WM8994_GP5_OP_CFG_MASK 0x0200 /* GP5_OP_CFG */
+#define WM8994_GP5_OP_CFG_SHIFT 9 /* GP5_OP_CFG */
+#define WM8994_GP5_OP_CFG_WIDTH 1 /* GP5_OP_CFG */
+#define WM8994_GP5_DB 0x0100 /* GP5_DB */
+#define WM8994_GP5_DB_MASK 0x0100 /* GP5_DB */
+#define WM8994_GP5_DB_SHIFT 8 /* GP5_DB */
+#define WM8994_GP5_DB_WIDTH 1 /* GP5_DB */
+#define WM8994_GP5_LVL 0x0040 /* GP5_LVL */
+#define WM8994_GP5_LVL_MASK 0x0040 /* GP5_LVL */
+#define WM8994_GP5_LVL_SHIFT 6 /* GP5_LVL */
+#define WM8994_GP5_LVL_WIDTH 1 /* GP5_LVL */
+#define WM8994_GP5_FN_MASK 0x001F /* GP5_FN - [4:0] */
+#define WM8994_GP5_FN_SHIFT 0 /* GP5_FN - [4:0] */
+#define WM8994_GP5_FN_WIDTH 5 /* GP5_FN - [4:0] */
+
+/*
+ * R1797 (0x705) - GPIO 6
+ */
+#define WM8994_GP6_DIR 0x8000 /* GP6_DIR */
+#define WM8994_GP6_DIR_MASK 0x8000 /* GP6_DIR */
+#define WM8994_GP6_DIR_SHIFT 15 /* GP6_DIR */
+#define WM8994_GP6_DIR_WIDTH 1 /* GP6_DIR */
+#define WM8994_GP6_PU 0x4000 /* GP6_PU */
+#define WM8994_GP6_PU_MASK 0x4000 /* GP6_PU */
+#define WM8994_GP6_PU_SHIFT 14 /* GP6_PU */
+#define WM8994_GP6_PU_WIDTH 1 /* GP6_PU */
+#define WM8994_GP6_PD 0x2000 /* GP6_PD */
+#define WM8994_GP6_PD_MASK 0x2000 /* GP6_PD */
+#define WM8994_GP6_PD_SHIFT 13 /* GP6_PD */
+#define WM8994_GP6_PD_WIDTH 1 /* GP6_PD */
+#define WM8994_GP6_POL 0x0400 /* GP6_POL */
+#define WM8994_GP6_POL_MASK 0x0400 /* GP6_POL */
+#define WM8994_GP6_POL_SHIFT 10 /* GP6_POL */
+#define WM8994_GP6_POL_WIDTH 1 /* GP6_POL */
+#define WM8994_GP6_OP_CFG 0x0200 /* GP6_OP_CFG */
+#define WM8994_GP6_OP_CFG_MASK 0x0200 /* GP6_OP_CFG */
+#define WM8994_GP6_OP_CFG_SHIFT 9 /* GP6_OP_CFG */
+#define WM8994_GP6_OP_CFG_WIDTH 1 /* GP6_OP_CFG */
+#define WM8994_GP6_DB 0x0100 /* GP6_DB */
+#define WM8994_GP6_DB_MASK 0x0100 /* GP6_DB */
+#define WM8994_GP6_DB_SHIFT 8 /* GP6_DB */
+#define WM8994_GP6_DB_WIDTH 1 /* GP6_DB */
+#define WM8994_GP6_LVL 0x0040 /* GP6_LVL */
+#define WM8994_GP6_LVL_MASK 0x0040 /* GP6_LVL */
+#define WM8994_GP6_LVL_SHIFT 6 /* GP6_LVL */
+#define WM8994_GP6_LVL_WIDTH 1 /* GP6_LVL */
+#define WM8994_GP6_FN_MASK 0x001F /* GP6_FN - [4:0] */
+#define WM8994_GP6_FN_SHIFT 0 /* GP6_FN - [4:0] */
+#define WM8994_GP6_FN_WIDTH 5 /* GP6_FN - [4:0] */
+
+/*
+ * R1798 (0x706) - GPIO 7
+ */
+#define WM8994_GP7_DIR 0x8000 /* GP7_DIR */
+#define WM8994_GP7_DIR_MASK 0x8000 /* GP7_DIR */
+#define WM8994_GP7_DIR_SHIFT 15 /* GP7_DIR */
+#define WM8994_GP7_DIR_WIDTH 1 /* GP7_DIR */
+#define WM8994_GP7_PU 0x4000 /* GP7_PU */
+#define WM8994_GP7_PU_MASK 0x4000 /* GP7_PU */
+#define WM8994_GP7_PU_SHIFT 14 /* GP7_PU */
+#define WM8994_GP7_PU_WIDTH 1 /* GP7_PU */
+#define WM8994_GP7_PD 0x2000 /* GP7_PD */
+#define WM8994_GP7_PD_MASK 0x2000 /* GP7_PD */
+#define WM8994_GP7_PD_SHIFT 13 /* GP7_PD */
+#define WM8994_GP7_PD_WIDTH 1 /* GP7_PD */
+#define WM8994_GP7_POL 0x0400 /* GP7_POL */
+#define WM8994_GP7_POL_MASK 0x0400 /* GP7_POL */
+#define WM8994_GP7_POL_SHIFT 10 /* GP7_POL */
+#define WM8994_GP7_POL_WIDTH 1 /* GP7_POL */
+#define WM8994_GP7_OP_CFG 0x0200 /* GP7_OP_CFG */
+#define WM8994_GP7_OP_CFG_MASK 0x0200 /* GP7_OP_CFG */
+#define WM8994_GP7_OP_CFG_SHIFT 9 /* GP7_OP_CFG */
+#define WM8994_GP7_OP_CFG_WIDTH 1 /* GP7_OP_CFG */
+#define WM8994_GP7_DB 0x0100 /* GP7_DB */
+#define WM8994_GP7_DB_MASK 0x0100 /* GP7_DB */
+#define WM8994_GP7_DB_SHIFT 8 /* GP7_DB */
+#define WM8994_GP7_DB_WIDTH 1 /* GP7_DB */
+#define WM8994_GP7_LVL 0x0040 /* GP7_LVL */
+#define WM8994_GP7_LVL_MASK 0x0040 /* GP7_LVL */
+#define WM8994_GP7_LVL_SHIFT 6 /* GP7_LVL */
+#define WM8994_GP7_LVL_WIDTH 1 /* GP7_LVL */
+#define WM8994_GP7_FN_MASK 0x001F /* GP7_FN - [4:0] */
+#define WM8994_GP7_FN_SHIFT 0 /* GP7_FN - [4:0] */
+#define WM8994_GP7_FN_WIDTH 5 /* GP7_FN - [4:0] */
+
+/*
+ * R1799 (0x707) - GPIO 8
+ */
+#define WM8994_GP8_DIR 0x8000 /* GP8_DIR */
+#define WM8994_GP8_DIR_MASK 0x8000 /* GP8_DIR */
+#define WM8994_GP8_DIR_SHIFT 15 /* GP8_DIR */
+#define WM8994_GP8_DIR_WIDTH 1 /* GP8_DIR */
+#define WM8994_GP8_PU 0x4000 /* GP8_PU */
+#define WM8994_GP8_PU_MASK 0x4000 /* GP8_PU */
+#define WM8994_GP8_PU_SHIFT 14 /* GP8_PU */
+#define WM8994_GP8_PU_WIDTH 1 /* GP8_PU */
+#define WM8994_GP8_PD 0x2000 /* GP8_PD */
+#define WM8994_GP8_PD_MASK 0x2000 /* GP8_PD */
+#define WM8994_GP8_PD_SHIFT 13 /* GP8_PD */
+#define WM8994_GP8_PD_WIDTH 1 /* GP8_PD */
+#define WM8994_GP8_POL 0x0400 /* GP8_POL */
+#define WM8994_GP8_POL_MASK 0x0400 /* GP8_POL */
+#define WM8994_GP8_POL_SHIFT 10 /* GP8_POL */
+#define WM8994_GP8_POL_WIDTH 1 /* GP8_POL */
+#define WM8994_GP8_OP_CFG 0x0200 /* GP8_OP_CFG */
+#define WM8994_GP8_OP_CFG_MASK 0x0200 /* GP8_OP_CFG */
+#define WM8994_GP8_OP_CFG_SHIFT 9 /* GP8_OP_CFG */
+#define WM8994_GP8_OP_CFG_WIDTH 1 /* GP8_OP_CFG */
+#define WM8994_GP8_DB 0x0100 /* GP8_DB */
+#define WM8994_GP8_DB_MASK 0x0100 /* GP8_DB */
+#define WM8994_GP8_DB_SHIFT 8 /* GP8_DB */
+#define WM8994_GP8_DB_WIDTH 1 /* GP8_DB */
+#define WM8994_GP8_LVL 0x0040 /* GP8_LVL */
+#define WM8994_GP8_LVL_MASK 0x0040 /* GP8_LVL */
+#define WM8994_GP8_LVL_SHIFT 6 /* GP8_LVL */
+#define WM8994_GP8_LVL_WIDTH 1 /* GP8_LVL */
+#define WM8994_GP8_FN_MASK 0x001F /* GP8_FN - [4:0] */
+#define WM8994_GP8_FN_SHIFT 0 /* GP8_FN - [4:0] */
+#define WM8994_GP8_FN_WIDTH 5 /* GP8_FN - [4:0] */
+
+/*
+ * R1800 (0x708) - GPIO 9
+ */
+#define WM8994_GP9_DIR 0x8000 /* GP9_DIR */
+#define WM8994_GP9_DIR_MASK 0x8000 /* GP9_DIR */
+#define WM8994_GP9_DIR_SHIFT 15 /* GP9_DIR */
+#define WM8994_GP9_DIR_WIDTH 1 /* GP9_DIR */
+#define WM8994_GP9_PU 0x4000 /* GP9_PU */
+#define WM8994_GP9_PU_MASK 0x4000 /* GP9_PU */
+#define WM8994_GP9_PU_SHIFT 14 /* GP9_PU */
+#define WM8994_GP9_PU_WIDTH 1 /* GP9_PU */
+#define WM8994_GP9_PD 0x2000 /* GP9_PD */
+#define WM8994_GP9_PD_MASK 0x2000 /* GP9_PD */
+#define WM8994_GP9_PD_SHIFT 13 /* GP9_PD */
+#define WM8994_GP9_PD_WIDTH 1 /* GP9_PD */
+#define WM8994_GP9_POL 0x0400 /* GP9_POL */
+#define WM8994_GP9_POL_MASK 0x0400 /* GP9_POL */
+#define WM8994_GP9_POL_SHIFT 10 /* GP9_POL */
+#define WM8994_GP9_POL_WIDTH 1 /* GP9_POL */
+#define WM8994_GP9_OP_CFG 0x0200 /* GP9_OP_CFG */
+#define WM8994_GP9_OP_CFG_MASK 0x0200 /* GP9_OP_CFG */
+#define WM8994_GP9_OP_CFG_SHIFT 9 /* GP9_OP_CFG */
+#define WM8994_GP9_OP_CFG_WIDTH 1 /* GP9_OP_CFG */
+#define WM8994_GP9_DB 0x0100 /* GP9_DB */
+#define WM8994_GP9_DB_MASK 0x0100 /* GP9_DB */
+#define WM8994_GP9_DB_SHIFT 8 /* GP9_DB */
+#define WM8994_GP9_DB_WIDTH 1 /* GP9_DB */
+#define WM8994_GP9_LVL 0x0040 /* GP9_LVL */
+#define WM8994_GP9_LVL_MASK 0x0040 /* GP9_LVL */
+#define WM8994_GP9_LVL_SHIFT 6 /* GP9_LVL */
+#define WM8994_GP9_LVL_WIDTH 1 /* GP9_LVL */
+#define WM8994_GP9_FN_MASK 0x001F /* GP9_FN - [4:0] */
+#define WM8994_GP9_FN_SHIFT 0 /* GP9_FN - [4:0] */
+#define WM8994_GP9_FN_WIDTH 5 /* GP9_FN - [4:0] */
+
+/*
+ * R1801 (0x709) - GPIO 10
+ */
+#define WM8994_GP10_DIR 0x8000 /* GP10_DIR */
+#define WM8994_GP10_DIR_MASK 0x8000 /* GP10_DIR */
+#define WM8994_GP10_DIR_SHIFT 15 /* GP10_DIR */
+#define WM8994_GP10_DIR_WIDTH 1 /* GP10_DIR */
+#define WM8994_GP10_PU 0x4000 /* GP10_PU */
+#define WM8994_GP10_PU_MASK 0x4000 /* GP10_PU */
+#define WM8994_GP10_PU_SHIFT 14 /* GP10_PU */
+#define WM8994_GP10_PU_WIDTH 1 /* GP10_PU */
+#define WM8994_GP10_PD 0x2000 /* GP10_PD */
+#define WM8994_GP10_PD_MASK 0x2000 /* GP10_PD */
+#define WM8994_GP10_PD_SHIFT 13 /* GP10_PD */
+#define WM8994_GP10_PD_WIDTH 1 /* GP10_PD */
+#define WM8994_GP10_POL 0x0400 /* GP10_POL */
+#define WM8994_GP10_POL_MASK 0x0400 /* GP10_POL */
+#define WM8994_GP10_POL_SHIFT 10 /* GP10_POL */
+#define WM8994_GP10_POL_WIDTH 1 /* GP10_POL */
+#define WM8994_GP10_OP_CFG 0x0200 /* GP10_OP_CFG */
+#define WM8994_GP10_OP_CFG_MASK 0x0200 /* GP10_OP_CFG */
+#define WM8994_GP10_OP_CFG_SHIFT 9 /* GP10_OP_CFG */
+#define WM8994_GP10_OP_CFG_WIDTH 1 /* GP10_OP_CFG */
+#define WM8994_GP10_DB 0x0100 /* GP10_DB */
+#define WM8994_GP10_DB_MASK 0x0100 /* GP10_DB */
+#define WM8994_GP10_DB_SHIFT 8 /* GP10_DB */
+#define WM8994_GP10_DB_WIDTH 1 /* GP10_DB */
+#define WM8994_GP10_LVL 0x0040 /* GP10_LVL */
+#define WM8994_GP10_LVL_MASK 0x0040 /* GP10_LVL */
+#define WM8994_GP10_LVL_SHIFT 6 /* GP10_LVL */
+#define WM8994_GP10_LVL_WIDTH 1 /* GP10_LVL */
+#define WM8994_GP10_FN_MASK 0x001F /* GP10_FN - [4:0] */
+#define WM8994_GP10_FN_SHIFT 0 /* GP10_FN - [4:0] */
+#define WM8994_GP10_FN_WIDTH 5 /* GP10_FN - [4:0] */
+
+/*
+ * R1802 (0x70A) - GPIO 11
+ */
+#define WM8994_GP11_DIR 0x8000 /* GP11_DIR */
+#define WM8994_GP11_DIR_MASK 0x8000 /* GP11_DIR */
+#define WM8994_GP11_DIR_SHIFT 15 /* GP11_DIR */
+#define WM8994_GP11_DIR_WIDTH 1 /* GP11_DIR */
+#define WM8994_GP11_PU 0x4000 /* GP11_PU */
+#define WM8994_GP11_PU_MASK 0x4000 /* GP11_PU */
+#define WM8994_GP11_PU_SHIFT 14 /* GP11_PU */
+#define WM8994_GP11_PU_WIDTH 1 /* GP11_PU */
+#define WM8994_GP11_PD 0x2000 /* GP11_PD */
+#define WM8994_GP11_PD_MASK 0x2000 /* GP11_PD */
+#define WM8994_GP11_PD_SHIFT 13 /* GP11_PD */
+#define WM8994_GP11_PD_WIDTH 1 /* GP11_PD */
+#define WM8994_GP11_POL 0x0400 /* GP11_POL */
+#define WM8994_GP11_POL_MASK 0x0400 /* GP11_POL */
+#define WM8994_GP11_POL_SHIFT 10 /* GP11_POL */
+#define WM8994_GP11_POL_WIDTH 1 /* GP11_POL */
+#define WM8994_GP11_OP_CFG 0x0200 /* GP11_OP_CFG */
+#define WM8994_GP11_OP_CFG_MASK 0x0200 /* GP11_OP_CFG */
+#define WM8994_GP11_OP_CFG_SHIFT 9 /* GP11_OP_CFG */
+#define WM8994_GP11_OP_CFG_WIDTH 1 /* GP11_OP_CFG */
+#define WM8994_GP11_DB 0x0100 /* GP11_DB */
+#define WM8994_GP11_DB_MASK 0x0100 /* GP11_DB */
+#define WM8994_GP11_DB_SHIFT 8 /* GP11_DB */
+#define WM8994_GP11_DB_WIDTH 1 /* GP11_DB */
+#define WM8994_GP11_LVL 0x0040 /* GP11_LVL */
+#define WM8994_GP11_LVL_MASK 0x0040 /* GP11_LVL */
+#define WM8994_GP11_LVL_SHIFT 6 /* GP11_LVL */
+#define WM8994_GP11_LVL_WIDTH 1 /* GP11_LVL */
+#define WM8994_GP11_FN_MASK 0x001F /* GP11_FN - [4:0] */
+#define WM8994_GP11_FN_SHIFT 0 /* GP11_FN - [4:0] */
+#define WM8994_GP11_FN_WIDTH 5 /* GP11_FN - [4:0] */
+
+/*
+ * R1824 (0x720) - Digital Pulls
+ */
+#define WM8994_DMICDAT2_PU 0x0800 /* DMICDAT2_PU */
+#define WM8994_DMICDAT2_PU_MASK 0x0800 /* DMICDAT2_PU */
+#define WM8994_DMICDAT2_PU_SHIFT 11 /* DMICDAT2_PU */
+#define WM8994_DMICDAT2_PU_WIDTH 1 /* DMICDAT2_PU */
+#define WM8994_DMICDAT2_PD 0x0400 /* DMICDAT2_PD */
+#define WM8994_DMICDAT2_PD_MASK 0x0400 /* DMICDAT2_PD */
+#define WM8994_DMICDAT2_PD_SHIFT 10 /* DMICDAT2_PD */
+#define WM8994_DMICDAT2_PD_WIDTH 1 /* DMICDAT2_PD */
+#define WM8994_DMICDAT1_PU 0x0200 /* DMICDAT1_PU */
+#define WM8994_DMICDAT1_PU_MASK 0x0200 /* DMICDAT1_PU */
+#define WM8994_DMICDAT1_PU_SHIFT 9 /* DMICDAT1_PU */
+#define WM8994_DMICDAT1_PU_WIDTH 1 /* DMICDAT1_PU */
+#define WM8994_DMICDAT1_PD 0x0100 /* DMICDAT1_PD */
+#define WM8994_DMICDAT1_PD_MASK 0x0100 /* DMICDAT1_PD */
+#define WM8994_DMICDAT1_PD_SHIFT 8 /* DMICDAT1_PD */
+#define WM8994_DMICDAT1_PD_WIDTH 1 /* DMICDAT1_PD */
+#define WM8994_MCLK1_PU 0x0080 /* MCLK1_PU */
+#define WM8994_MCLK1_PU_MASK 0x0080 /* MCLK1_PU */
+#define WM8994_MCLK1_PU_SHIFT 7 /* MCLK1_PU */
+#define WM8994_MCLK1_PU_WIDTH 1 /* MCLK1_PU */
+#define WM8994_MCLK1_PD 0x0040 /* MCLK1_PD */
+#define WM8994_MCLK1_PD_MASK 0x0040 /* MCLK1_PD */
+#define WM8994_MCLK1_PD_SHIFT 6 /* MCLK1_PD */
+#define WM8994_MCLK1_PD_WIDTH 1 /* MCLK1_PD */
+#define WM8994_DACDAT1_PU 0x0020 /* DACDAT1_PU */
+#define WM8994_DACDAT1_PU_MASK 0x0020 /* DACDAT1_PU */
+#define WM8994_DACDAT1_PU_SHIFT 5 /* DACDAT1_PU */
+#define WM8994_DACDAT1_PU_WIDTH 1 /* DACDAT1_PU */
+#define WM8994_DACDAT1_PD 0x0010 /* DACDAT1_PD */
+#define WM8994_DACDAT1_PD_MASK 0x0010 /* DACDAT1_PD */
+#define WM8994_DACDAT1_PD_SHIFT 4 /* DACDAT1_PD */
+#define WM8994_DACDAT1_PD_WIDTH 1 /* DACDAT1_PD */
+#define WM8994_DACLRCLK1_PU 0x0008 /* DACLRCLK1_PU */
+#define WM8994_DACLRCLK1_PU_MASK 0x0008 /* DACLRCLK1_PU */
+#define WM8994_DACLRCLK1_PU_SHIFT 3 /* DACLRCLK1_PU */
+#define WM8994_DACLRCLK1_PU_WIDTH 1 /* DACLRCLK1_PU */
+#define WM8994_DACLRCLK1_PD 0x0004 /* DACLRCLK1_PD */
+#define WM8994_DACLRCLK1_PD_MASK 0x0004 /* DACLRCLK1_PD */
+#define WM8994_DACLRCLK1_PD_SHIFT 2 /* DACLRCLK1_PD */
+#define WM8994_DACLRCLK1_PD_WIDTH 1 /* DACLRCLK1_PD */
+#define WM8994_BCLK1_PU 0x0002 /* BCLK1_PU */
+#define WM8994_BCLK1_PU_MASK 0x0002 /* BCLK1_PU */
+#define WM8994_BCLK1_PU_SHIFT 1 /* BCLK1_PU */
+#define WM8994_BCLK1_PU_WIDTH 1 /* BCLK1_PU */
+#define WM8994_BCLK1_PD 0x0001 /* BCLK1_PD */
+#define WM8994_BCLK1_PD_MASK 0x0001 /* BCLK1_PD */
+#define WM8994_BCLK1_PD_SHIFT 0 /* BCLK1_PD */
+#define WM8994_BCLK1_PD_WIDTH 1 /* BCLK1_PD */
+
+/*
+ * R1840 (0x730) - Interrupt Status 1
+ */
+#define WM8994_GP11_EINT 0x0400 /* GP11_EINT */
+#define WM8994_GP11_EINT_MASK 0x0400 /* GP11_EINT */
+#define WM8994_GP11_EINT_SHIFT 10 /* GP11_EINT */
+#define WM8994_GP11_EINT_WIDTH 1 /* GP11_EINT */
+#define WM8994_GP10_EINT 0x0200 /* GP10_EINT */
+#define WM8994_GP10_EINT_MASK 0x0200 /* GP10_EINT */
+#define WM8994_GP10_EINT_SHIFT 9 /* GP10_EINT */
+#define WM8994_GP10_EINT_WIDTH 1 /* GP10_EINT */
+#define WM8994_GP9_EINT 0x0100 /* GP9_EINT */
+#define WM8994_GP9_EINT_MASK 0x0100 /* GP9_EINT */
+#define WM8994_GP9_EINT_SHIFT 8 /* GP9_EINT */
+#define WM8994_GP9_EINT_WIDTH 1 /* GP9_EINT */
+#define WM8994_GP8_EINT 0x0080 /* GP8_EINT */
+#define WM8994_GP8_EINT_MASK 0x0080 /* GP8_EINT */
+#define WM8994_GP8_EINT_SHIFT 7 /* GP8_EINT */
+#define WM8994_GP8_EINT_WIDTH 1 /* GP8_EINT */
+#define WM8994_GP7_EINT 0x0040 /* GP7_EINT */
+#define WM8994_GP7_EINT_MASK 0x0040 /* GP7_EINT */
+#define WM8994_GP7_EINT_SHIFT 6 /* GP7_EINT */
+#define WM8994_GP7_EINT_WIDTH 1 /* GP7_EINT */
+#define WM8994_GP6_EINT 0x0020 /* GP6_EINT */
+#define WM8994_GP6_EINT_MASK 0x0020 /* GP6_EINT */
+#define WM8994_GP6_EINT_SHIFT 5 /* GP6_EINT */
+#define WM8994_GP6_EINT_WIDTH 1 /* GP6_EINT */
+#define WM8994_GP5_EINT 0x0010 /* GP5_EINT */
+#define WM8994_GP5_EINT_MASK 0x0010 /* GP5_EINT */
+#define WM8994_GP5_EINT_SHIFT 4 /* GP5_EINT */
+#define WM8994_GP5_EINT_WIDTH 1 /* GP5_EINT */
+#define WM8994_GP4_EINT 0x0008 /* GP4_EINT */
+#define WM8994_GP4_EINT_MASK 0x0008 /* GP4_EINT */
+#define WM8994_GP4_EINT_SHIFT 3 /* GP4_EINT */
+#define WM8994_GP4_EINT_WIDTH 1 /* GP4_EINT */
+#define WM8994_GP3_EINT 0x0004 /* GP3_EINT */
+#define WM8994_GP3_EINT_MASK 0x0004 /* GP3_EINT */
+#define WM8994_GP3_EINT_SHIFT 2 /* GP3_EINT */
+#define WM8994_GP3_EINT_WIDTH 1 /* GP3_EINT */
+#define WM8994_GP2_EINT 0x0002 /* GP2_EINT */
+#define WM8994_GP2_EINT_MASK 0x0002 /* GP2_EINT */
+#define WM8994_GP2_EINT_SHIFT 1 /* GP2_EINT */
+#define WM8994_GP2_EINT_WIDTH 1 /* GP2_EINT */
+#define WM8994_GP1_EINT 0x0001 /* GP1_EINT */
+#define WM8994_GP1_EINT_MASK 0x0001 /* GP1_EINT */
+#define WM8994_GP1_EINT_SHIFT 0 /* GP1_EINT */
+#define WM8994_GP1_EINT_WIDTH 1 /* GP1_EINT */
+
+/*
+ * R1841 (0x731) - Interrupt Status 2
+ */
+#define WM8994_WSEQ_DONE_EINT 0x2000 /* WSEQ_DONE_EINT */
+#define WM8994_WSEQ_DONE_EINT_MASK 0x2000 /* WSEQ_DONE_EINT */
+#define WM8994_WSEQ_DONE_EINT_SHIFT 13 /* WSEQ_DONE_EINT */
+#define WM8994_WSEQ_DONE_EINT_WIDTH 1 /* WSEQ_DONE_EINT */
+#define WM8994_FIFOS_ERR_EINT 0x1000 /* FIFOS_ERR_EINT */
+#define WM8994_FIFOS_ERR_EINT_MASK 0x1000 /* FIFOS_ERR_EINT */
+#define WM8994_FIFOS_ERR_EINT_SHIFT 12 /* FIFOS_ERR_EINT */
+#define WM8994_FIFOS_ERR_EINT_WIDTH 1 /* FIFOS_ERR_EINT */
+#define WM8994_DRC3_ACTDET_EINT 0x0800 /* DRC3_ACTDET_EINT */
+#define WM8994_DRC3_ACTDET_EINT_MASK 0x0800 /* DRC3_ACTDET_EINT */
+#define WM8994_DRC3_ACTDET_EINT_SHIFT 11 /* DRC3_ACTDET_EINT */
+#define WM8994_DRC3_ACTDET_EINT_WIDTH 1 /* DRC3_ACTDET_EINT */
+#define WM8994_DRC2_ACTDET_EINT 0x0400 /* DRC2_ACTDET_EINT */
+#define WM8994_DRC2_ACTDET_EINT_MASK 0x0400 /* DRC2_ACTDET_EINT */
+#define WM8994_DRC2_ACTDET_EINT_SHIFT 10 /* DRC2_ACTDET_EINT */
+#define WM8994_DRC2_ACTDET_EINT_WIDTH 1 /* DRC2_ACTDET_EINT */
+#define WM8994_DRC1_ACTDET_EINT 0x0200 /* DRC1_ACTDET_EINT */
+#define WM8994_DRC1_ACTDET_EINT_MASK 0x0200 /* DRC1_ACTDET_EINT */
+#define WM8994_DRC1_ACTDET_EINT_SHIFT 9 /* DRC1_ACTDET_EINT */
+#define WM8994_DRC1_ACTDET_EINT_WIDTH 1 /* DRC1_ACTDET_EINT */
+#define WM8994_SRC2_LOCK_EINT 0x0100 /* SRC2_LOCK_EINT */
+#define WM8994_SRC2_LOCK_EINT_MASK 0x0100 /* SRC2_LOCK_EINT */
+#define WM8994_SRC2_LOCK_EINT_SHIFT 8 /* SRC2_LOCK_EINT */
+#define WM8994_SRC2_LOCK_EINT_WIDTH 1 /* SRC2_LOCK_EINT */
+#define WM8994_SRC1_LOCK_EINT 0x0080 /* SRC1_LOCK_EINT */
+#define WM8994_SRC1_LOCK_EINT_MASK 0x0080 /* SRC1_LOCK_EINT */
+#define WM8994_SRC1_LOCK_EINT_SHIFT 7 /* SRC1_LOCK_EINT */
+#define WM8994_SRC1_LOCK_EINT_WIDTH 1 /* SRC1_LOCK_EINT */
+#define WM8994_FLL2_LOCK_EINT 0x0040 /* FLL2_LOCK_EINT */
+#define WM8994_FLL2_LOCK_EINT_MASK 0x0040 /* FLL2_LOCK_EINT */
+#define WM8994_FLL2_LOCK_EINT_SHIFT 6 /* FLL2_LOCK_EINT */
+#define WM8994_FLL2_LOCK_EINT_WIDTH 1 /* FLL2_LOCK_EINT */
+#define WM8994_FLL1_LOCK_EINT 0x0020 /* FLL1_LOCK_EINT */
+#define WM8994_FLL1_LOCK_EINT_MASK 0x0020 /* FLL1_LOCK_EINT */
+#define WM8994_FLL1_LOCK_EINT_SHIFT 5 /* FLL1_LOCK_EINT */
+#define WM8994_FLL1_LOCK_EINT_WIDTH 1 /* FLL1_LOCK_EINT */
+#define WM8994_MIC2_SHRT_EINT 0x0010 /* MIC2_SHRT_EINT */
+#define WM8994_MIC2_SHRT_EINT_MASK 0x0010 /* MIC2_SHRT_EINT */
+#define WM8994_MIC2_SHRT_EINT_SHIFT 4 /* MIC2_SHRT_EINT */
+#define WM8994_MIC2_SHRT_EINT_WIDTH 1 /* MIC2_SHRT_EINT */
+#define WM8994_MIC2_DET_EINT 0x0008 /* MIC2_DET_EINT */
+#define WM8994_MIC2_DET_EINT_MASK 0x0008 /* MIC2_DET_EINT */
+#define WM8994_MIC2_DET_EINT_SHIFT 3 /* MIC2_DET_EINT */
+#define WM8994_MIC2_DET_EINT_WIDTH 1 /* MIC2_DET_EINT */
+#define WM8994_MIC1_SHRT_EINT 0x0004 /* MIC1_SHRT_EINT */
+#define WM8994_MIC1_SHRT_EINT_MASK 0x0004 /* MIC1_SHRT_EINT */
+#define WM8994_MIC1_SHRT_EINT_SHIFT 2 /* MIC1_SHRT_EINT */
+#define WM8994_MIC1_SHRT_EINT_WIDTH 1 /* MIC1_SHRT_EINT */
+#define WM8994_MIC1_DET_EINT 0x0002 /* MIC1_DET_EINT */
+#define WM8994_MIC1_DET_EINT_MASK 0x0002 /* MIC1_DET_EINT */
+#define WM8994_MIC1_DET_EINT_SHIFT 1 /* MIC1_DET_EINT */
+#define WM8994_MIC1_DET_EINT_WIDTH 1 /* MIC1_DET_EINT */
+#define WM8994_TEMP_SHUT_EINT 0x0001 /* TEMP_SHUT_EINT */
+#define WM8994_TEMP_SHUT_EINT_MASK 0x0001 /* TEMP_SHUT_EINT */
+#define WM8994_TEMP_SHUT_EINT_SHIFT 0 /* TEMP_SHUT_EINT */
+#define WM8994_TEMP_SHUT_EINT_WIDTH 1 /* TEMP_SHUT_EINT */
+
+/*
+ * R1848 (0x738) - Interrupt Status 1 Mask
+ */
+#define WM8994_IM_GP11_EINT 0x0400 /* IM_GP11_EINT */
+#define WM8994_IM_GP11_EINT_MASK 0x0400 /* IM_GP11_EINT */
+#define WM8994_IM_GP11_EINT_SHIFT 10 /* IM_GP11_EINT */
+#define WM8994_IM_GP11_EINT_WIDTH 1 /* IM_GP11_EINT */
+#define WM8994_IM_GP10_EINT 0x0200 /* IM_GP10_EINT */
+#define WM8994_IM_GP10_EINT_MASK 0x0200 /* IM_GP10_EINT */
+#define WM8994_IM_GP10_EINT_SHIFT 9 /* IM_GP10_EINT */
+#define WM8994_IM_GP10_EINT_WIDTH 1 /* IM_GP10_EINT */
+#define WM8994_IM_GP9_EINT 0x0100 /* IM_GP9_EINT */
+#define WM8994_IM_GP9_EINT_MASK 0x0100 /* IM_GP9_EINT */
+#define WM8994_IM_GP9_EINT_SHIFT 8 /* IM_GP9_EINT */
+#define WM8994_IM_GP9_EINT_WIDTH 1 /* IM_GP9_EINT */
+#define WM8994_IM_GP8_EINT 0x0080 /* IM_GP8_EINT */
+#define WM8994_IM_GP8_EINT_MASK 0x0080 /* IM_GP8_EINT */
+#define WM8994_IM_GP8_EINT_SHIFT 7 /* IM_GP8_EINT */
+#define WM8994_IM_GP8_EINT_WIDTH 1 /* IM_GP8_EINT */
+#define WM8994_IM_GP7_EINT 0x0040 /* IM_GP7_EINT */
+#define WM8994_IM_GP7_EINT_MASK 0x0040 /* IM_GP7_EINT */
+#define WM8994_IM_GP7_EINT_SHIFT 6 /* IM_GP7_EINT */
+#define WM8994_IM_GP7_EINT_WIDTH 1 /* IM_GP7_EINT */
+#define WM8994_IM_GP6_EINT 0x0020 /* IM_GP6_EINT */
+#define WM8994_IM_GP6_EINT_MASK 0x0020 /* IM_GP6_EINT */
+#define WM8994_IM_GP6_EINT_SHIFT 5 /* IM_GP6_EINT */
+#define WM8994_IM_GP6_EINT_WIDTH 1 /* IM_GP6_EINT */
+#define WM8994_IM_GP5_EINT 0x0010 /* IM_GP5_EINT */
+#define WM8994_IM_GP5_EINT_MASK 0x0010 /* IM_GP5_EINT */
+#define WM8994_IM_GP5_EINT_SHIFT 4 /* IM_GP5_EINT */
+#define WM8994_IM_GP5_EINT_WIDTH 1 /* IM_GP5_EINT */
+#define WM8994_IM_GP4_EINT 0x0008 /* IM_GP4_EINT */
+#define WM8994_IM_GP4_EINT_MASK 0x0008 /* IM_GP4_EINT */
+#define WM8994_IM_GP4_EINT_SHIFT 3 /* IM_GP4_EINT */
+#define WM8994_IM_GP4_EINT_WIDTH 1 /* IM_GP4_EINT */
+#define WM8994_IM_GP3_EINT 0x0004 /* IM_GP3_EINT */
+#define WM8994_IM_GP3_EINT_MASK 0x0004 /* IM_GP3_EINT */
+#define WM8994_IM_GP3_EINT_SHIFT 2 /* IM_GP3_EINT */
+#define WM8994_IM_GP3_EINT_WIDTH 1 /* IM_GP3_EINT */
+#define WM8994_IM_GP2_EINT 0x0002 /* IM_GP2_EINT */
+#define WM8994_IM_GP2_EINT_MASK 0x0002 /* IM_GP2_EINT */
+#define WM8994_IM_GP2_EINT_SHIFT 1 /* IM_GP2_EINT */
+#define WM8994_IM_GP2_EINT_WIDTH 1 /* IM_GP2_EINT */
+#define WM8994_IM_GP1_EINT 0x0001 /* IM_GP1_EINT */
+#define WM8994_IM_GP1_EINT_MASK 0x0001 /* IM_GP1_EINT */
+#define WM8994_IM_GP1_EINT_SHIFT 0 /* IM_GP1_EINT */
+#define WM8994_IM_GP1_EINT_WIDTH 1 /* IM_GP1_EINT */
+
+/*
+ * R1849 (0x739) - Interrupt Status 2 Mask
+ */
+#define WM8994_IM_WSEQ_DONE_EINT 0x2000 /* IM_WSEQ_DONE_EINT */
+#define WM8994_IM_WSEQ_DONE_EINT_MASK 0x2000 /* IM_WSEQ_DONE_EINT */
+#define WM8994_IM_WSEQ_DONE_EINT_SHIFT 13 /* IM_WSEQ_DONE_EINT */
+#define WM8994_IM_WSEQ_DONE_EINT_WIDTH 1 /* IM_WSEQ_DONE_EINT */
+#define WM8994_IM_FIFOS_ERR_EINT 0x1000 /* IM_FIFOS_ERR_EINT */
+#define WM8994_IM_FIFOS_ERR_EINT_MASK 0x1000 /* IM_FIFOS_ERR_EINT */
+#define WM8994_IM_FIFOS_ERR_EINT_SHIFT 12 /* IM_FIFOS_ERR_EINT */
+#define WM8994_IM_FIFOS_ERR_EINT_WIDTH 1 /* IM_FIFOS_ERR_EINT */
+#define WM8994_IM_DRC3_ACTDET_EINT 0x0800 /* IM_DRC3_ACTDET_EINT */
+#define WM8994_IM_DRC3_ACTDET_EINT_MASK 0x0800 /* IM_DRC3_ACTDET_EINT */
+#define WM8994_IM_DRC3_ACTDET_EINT_SHIFT 11 /* IM_DRC3_ACTDET_EINT */
+#define WM8994_IM_DRC3_ACTDET_EINT_WIDTH 1 /* IM_DRC3_ACTDET_EINT */
+#define WM8994_IM_DRC2_ACTDET_EINT 0x0400 /* IM_DRC2_ACTDET_EINT */
+#define WM8994_IM_DRC2_ACTDET_EINT_MASK 0x0400 /* IM_DRC2_ACTDET_EINT */
+#define WM8994_IM_DRC2_ACTDET_EINT_SHIFT 10 /* IM_DRC2_ACTDET_EINT */
+#define WM8994_IM_DRC2_ACTDET_EINT_WIDTH 1 /* IM_DRC2_ACTDET_EINT */
+#define WM8994_IM_DRC1_ACTDET_EINT 0x0200 /* IM_DRC1_ACTDET_EINT */
+#define WM8994_IM_DRC1_ACTDET_EINT_MASK 0x0200 /* IM_DRC1_ACTDET_EINT */
+#define WM8994_IM_DRC1_ACTDET_EINT_SHIFT 9 /* IM_DRC1_ACTDET_EINT */
+#define WM8994_IM_DRC1_ACTDET_EINT_WIDTH 1 /* IM_DRC1_ACTDET_EINT */
+#define WM8994_IM_SRC2_LOCK_EINT 0x0100 /* IM_SRC2_LOCK_EINT */
+#define WM8994_IM_SRC2_LOCK_EINT_MASK 0x0100 /* IM_SRC2_LOCK_EINT */
+#define WM8994_IM_SRC2_LOCK_EINT_SHIFT 8 /* IM_SRC2_LOCK_EINT */
+#define WM8994_IM_SRC2_LOCK_EINT_WIDTH 1 /* IM_SRC2_LOCK_EINT */
+#define WM8994_IM_SRC1_LOCK_EINT 0x0080 /* IM_SRC1_LOCK_EINT */
+#define WM8994_IM_SRC1_LOCK_EINT_MASK 0x0080 /* IM_SRC1_LOCK_EINT */
+#define WM8994_IM_SRC1_LOCK_EINT_SHIFT 7 /* IM_SRC1_LOCK_EINT */
+#define WM8994_IM_SRC1_LOCK_EINT_WIDTH 1 /* IM_SRC1_LOCK_EINT */
+#define WM8994_IM_FLL2_LOCK_EINT 0x0040 /* IM_FLL2_LOCK_EINT */
+#define WM8994_IM_FLL2_LOCK_EINT_MASK 0x0040 /* IM_FLL2_LOCK_EINT */
+#define WM8994_IM_FLL2_LOCK_EINT_SHIFT 6 /* IM_FLL2_LOCK_EINT */
+#define WM8994_IM_FLL2_LOCK_EINT_WIDTH 1 /* IM_FLL2_LOCK_EINT */
+#define WM8994_IM_FLL1_LOCK_EINT 0x0020 /* IM_FLL1_LOCK_EINT */
+#define WM8994_IM_FLL1_LOCK_EINT_MASK 0x0020 /* IM_FLL1_LOCK_EINT */
+#define WM8994_IM_FLL1_LOCK_EINT_SHIFT 5 /* IM_FLL1_LOCK_EINT */
+#define WM8994_IM_FLL1_LOCK_EINT_WIDTH 1 /* IM_FLL1_LOCK_EINT */
+#define WM8994_IM_MIC2_SHRT_EINT 0x0010 /* IM_MIC2_SHRT_EINT */
+#define WM8994_IM_MIC2_SHRT_EINT_MASK 0x0010 /* IM_MIC2_SHRT_EINT */
+#define WM8994_IM_MIC2_SHRT_EINT_SHIFT 4 /* IM_MIC2_SHRT_EINT */
+#define WM8994_IM_MIC2_SHRT_EINT_WIDTH 1 /* IM_MIC2_SHRT_EINT */
+#define WM8994_IM_MIC2_DET_EINT 0x0008 /* IM_MIC2_DET_EINT */
+#define WM8994_IM_MIC2_DET_EINT_MASK 0x0008 /* IM_MIC2_DET_EINT */
+#define WM8994_IM_MIC2_DET_EINT_SHIFT 3 /* IM_MIC2_DET_EINT */
+#define WM8994_IM_MIC2_DET_EINT_WIDTH 1 /* IM_MIC2_DET_EINT */
+#define WM8994_IM_MIC1_SHRT_EINT 0x0004 /* IM_MIC1_SHRT_EINT */
+#define WM8994_IM_MIC1_SHRT_EINT_MASK 0x0004 /* IM_MIC1_SHRT_EINT */
+#define WM8994_IM_MIC1_SHRT_EINT_SHIFT 2 /* IM_MIC1_SHRT_EINT */
+#define WM8994_IM_MIC1_SHRT_EINT_WIDTH 1 /* IM_MIC1_SHRT_EINT */
+#define WM8994_IM_MIC1_DET_EINT 0x0002 /* IM_MIC1_DET_EINT */
+#define WM8994_IM_MIC1_DET_EINT_MASK 0x0002 /* IM_MIC1_DET_EINT */
+#define WM8994_IM_MIC1_DET_EINT_SHIFT 1 /* IM_MIC1_DET_EINT */
+#define WM8994_IM_MIC1_DET_EINT_WIDTH 1 /* IM_MIC1_DET_EINT */
+#define WM8994_IM_TEMP_SHUT_EINT 0x0001 /* IM_TEMP_SHUT_EINT */
+#define WM8994_IM_TEMP_SHUT_EINT_MASK 0x0001 /* IM_TEMP_SHUT_EINT */
+#define WM8994_IM_TEMP_SHUT_EINT_SHIFT 0 /* IM_TEMP_SHUT_EINT */
+#define WM8994_IM_TEMP_SHUT_EINT_WIDTH 1 /* IM_TEMP_SHUT_EINT */
+
+/*
+ * R1856 (0x740) - Interrupt Control
+ */
+#define WM8994_IRQ_POL 0x0001 /* IRQ_POL */
+#define WM8994_IRQ_POL_MASK 0x0001 /* IRQ_POL */
+#define WM8994_IRQ_POL_SHIFT 0 /* IRQ_POL */
+#define WM8994_IRQ_POL_WIDTH 1 /* IRQ_POL */
+
+/*
+ * R1864 (0x748) - IRQ Debounce
+ */
+#define WM8994_MIC2_SHRT_DB 0x0010 /* MIC2_SHRT_DB */
+#define WM8994_MIC2_SHRT_DB_MASK 0x0010 /* MIC2_SHRT_DB */
+#define WM8994_MIC2_SHRT_DB_SHIFT 4 /* MIC2_SHRT_DB */
+#define WM8994_MIC2_SHRT_DB_WIDTH 1 /* MIC2_SHRT_DB */
+#define WM8994_MIC2_DET_DB 0x0008 /* MIC2_DET_DB */
+#define WM8994_MIC2_DET_DB_MASK 0x0008 /* MIC2_DET_DB */
+#define WM8994_MIC2_DET_DB_SHIFT 3 /* MIC2_DET_DB */
+#define WM8994_MIC2_DET_DB_WIDTH 1 /* MIC2_DET_DB */
+#define WM8994_MIC1_SHRT_DB 0x0004 /* MIC1_SHRT_DB */
+#define WM8994_MIC1_SHRT_DB_MASK 0x0004 /* MIC1_SHRT_DB */
+#define WM8994_MIC1_SHRT_DB_SHIFT 2 /* MIC1_SHRT_DB */
+#define WM8994_MIC1_SHRT_DB_WIDTH 1 /* MIC1_SHRT_DB */
+#define WM8994_MIC1_DET_DB 0x0002 /* MIC1_DET_DB */
+#define WM8994_MIC1_DET_DB_MASK 0x0002 /* MIC1_DET_DB */
+#define WM8994_MIC1_DET_DB_SHIFT 1 /* MIC1_DET_DB */
+#define WM8994_MIC1_DET_DB_WIDTH 1 /* MIC1_DET_DB */
+#define WM8994_TEMP_SHUT_DB 0x0001 /* TEMP_SHUT_DB */
+#define WM8994_TEMP_SHUT_DB_MASK 0x0001 /* TEMP_SHUT_DB */
+#define WM8994_TEMP_SHUT_DB_SHIFT 0 /* TEMP_SHUT_DB */
+#define WM8994_TEMP_SHUT_DB_WIDTH 1 /* TEMP_SHUT_DB */
+
+/*
+ * R1865 (0x749) - IRQ Polarity
+ */
+#define WM8994_WSEQ_DONE_POL 0x2000 /* WSEQ_DONE_POL */
+#define WM8994_WSEQ_DONE_POL_MASK 0x2000 /* WSEQ_DONE_POL */
+#define WM8994_WSEQ_DONE_POL_SHIFT 13 /* WSEQ_DONE_POL */
+#define WM8994_WSEQ_DONE_POL_WIDTH 1 /* WSEQ_DONE_POL */
+#define WM8994_FIFOS_ERR_POL 0x1000 /* FIFOS_ERR_POL */
+#define WM8994_FIFOS_ERR_POL_MASK 0x1000 /* FIFOS_ERR_POL */
+#define WM8994_FIFOS_ERR_POL_SHIFT 12 /* FIFOS_ERR_POL */
+#define WM8994_FIFOS_ERR_POL_WIDTH 1 /* FIFOS_ERR_POL */
+#define WM8994_DRC3_ACTDET_POL 0x0800 /* DRC3_ACTDET_POL */
+#define WM8994_DRC3_ACTDET_POL_MASK 0x0800 /* DRC3_ACTDET_POL */
+#define WM8994_DRC3_ACTDET_POL_SHIFT 11 /* DRC3_ACTDET_POL */
+#define WM8994_DRC3_ACTDET_POL_WIDTH 1 /* DRC3_ACTDET_POL */
+#define WM8994_DRC2_ACTDET_POL 0x0400 /* DRC2_ACTDET_POL */
+#define WM8994_DRC2_ACTDET_POL_MASK 0x0400 /* DRC2_ACTDET_POL */
+#define WM8994_DRC2_ACTDET_POL_SHIFT 10 /* DRC2_ACTDET_POL */
+#define WM8994_DRC2_ACTDET_POL_WIDTH 1 /* DRC2_ACTDET_POL */
+#define WM8994_DRC1_ACTDET_POL 0x0200 /* DRC1_ACTDET_POL */
+#define WM8994_DRC1_ACTDET_POL_MASK 0x0200 /* DRC1_ACTDET_POL */
+#define WM8994_DRC1_ACTDET_POL_SHIFT 9 /* DRC1_ACTDET_POL */
+#define WM8994_DRC1_ACTDET_POL_WIDTH 1 /* DRC1_ACTDET_POL */
+#define WM8994_SRC2_LOCK_POL 0x0100 /* SRC2_LOCK_POL */
+#define WM8994_SRC2_LOCK_POL_MASK 0x0100 /* SRC2_LOCK_POL */
+#define WM8994_SRC2_LOCK_POL_SHIFT 8 /* SRC2_LOCK_POL */
+#define WM8994_SRC2_LOCK_POL_WIDTH 1 /* SRC2_LOCK_POL */
+#define WM8994_SRC1_LOCK_POL 0x0080 /* SRC1_LOCK_POL */
+#define WM8994_SRC1_LOCK_POL_MASK 0x0080 /* SRC1_LOCK_POL */
+#define WM8994_SRC1_LOCK_POL_SHIFT 7 /* SRC1_LOCK_POL */
+#define WM8994_SRC1_LOCK_POL_WIDTH 1 /* SRC1_LOCK_POL */
+#define WM8994_FLL2_LOCK_POL 0x0040 /* FLL2_LOCK_POL */
+#define WM8994_FLL2_LOCK_POL_MASK 0x0040 /* FLL2_LOCK_POL */
+#define WM8994_FLL2_LOCK_POL_SHIFT 6 /* FLL2_LOCK_POL */
+#define WM8994_FLL2_LOCK_POL_WIDTH 1 /* FLL2_LOCK_POL */
+#define WM8994_FLL1_LOCK_POL 0x0020 /* FLL1_LOCK_POL */
+#define WM8994_FLL1_LOCK_POL_MASK 0x0020 /* FLL1_LOCK_POL */
+#define WM8994_FLL1_LOCK_POL_SHIFT 5 /* FLL1_LOCK_POL */
+#define WM8994_FLL1_LOCK_POL_WIDTH 1 /* FLL1_LOCK_POL */
+#define WM8994_MIC2_SHRT_POL 0x0010 /* MIC2_SHRT_POL */
+#define WM8994_MIC2_SHRT_POL_MASK 0x0010 /* MIC2_SHRT_POL */
+#define WM8994_MIC2_SHRT_POL_SHIFT 4 /* MIC2_SHRT_POL */
+#define WM8994_MIC2_SHRT_POL_WIDTH 1 /* MIC2_SHRT_POL */
+#define WM8994_MIC2_DET_POL 0x0008 /* MIC2_DET_POL */
+#define WM8994_MIC2_DET_POL_MASK 0x0008 /* MIC2_DET_POL */
+#define WM8994_MIC2_DET_POL_SHIFT 3 /* MIC2_DET_POL */
+#define WM8994_MIC2_DET_POL_WIDTH 1 /* MIC2_DET_POL */
+#define WM8994_MIC1_SHRT_POL 0x0004 /* MIC1_SHRT_POL */
+#define WM8994_MIC1_SHRT_POL_MASK 0x0004 /* MIC1_SHRT_POL */
+#define WM8994_MIC1_SHRT_POL_SHIFT 2 /* MIC1_SHRT_POL */
+#define WM8994_MIC1_SHRT_POL_WIDTH 1 /* MIC1_SHRT_POL */
+#define WM8994_MIC1_DET_POL 0x0002 /* MIC1_DET_POL */
+#define WM8994_MIC1_DET_POL_MASK 0x0002 /* MIC1_DET_POL */
+#define WM8994_MIC1_DET_POL_SHIFT 1 /* MIC1_DET_POL */
+#define WM8994_MIC1_DET_POL_WIDTH 1 /* MIC1_DET_POL */
+#define WM8994_TEMP_SHUT_POL 0x0001 /* TEMP_SHUT_POL */
+#define WM8994_TEMP_SHUT_POL_MASK 0x0001 /* TEMP_SHUT_POL */
+#define WM8994_TEMP_SHUT_POL_SHIFT 0 /* TEMP_SHUT_POL */
+#define WM8994_TEMP_SHUT_POL_WIDTH 1 /* TEMP_SHUT_POL */
+
+/*
+ * R12288 (0x3000) - Write Sequencer 0
+ */
+#define WM8994_WSEQ_ADDR0_MASK 0x3FFF /* WSEQ_ADDR0 - [13:0] */
+#define WM8994_WSEQ_ADDR0_SHIFT 0 /* WSEQ_ADDR0 - [13:0] */
+#define WM8994_WSEQ_ADDR0_WIDTH 14 /* WSEQ_ADDR0 - [13:0] */
+
+/*
+ * R12289 (0x3001) - Write Sequencer 1
+ */
+#define WM8994_WSEQ_DATA0_MASK 0x00FF /* WSEQ_DATA0 - [7:0] */
+#define WM8994_WSEQ_DATA0_SHIFT 0 /* WSEQ_DATA0 - [7:0] */
+#define WM8994_WSEQ_DATA0_WIDTH 8 /* WSEQ_DATA0 - [7:0] */
+
+/*
+ * R12290 (0x3002) - Write Sequencer 2
+ */
+#define WM8994_WSEQ_DATA_WIDTH0_MASK 0x0700 /* WSEQ_DATA_WIDTH0 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH0_SHIFT 8 /* WSEQ_DATA_WIDTH0 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH0_WIDTH 3 /* WSEQ_DATA_WIDTH0 - [10:8] */
+#define WM8994_WSEQ_DATA_START0_MASK 0x000F /* WSEQ_DATA_START0 - [3:0] */
+#define WM8994_WSEQ_DATA_START0_SHIFT 0 /* WSEQ_DATA_START0 - [3:0] */
+#define WM8994_WSEQ_DATA_START0_WIDTH 4 /* WSEQ_DATA_START0 - [3:0] */
+
+/*
+ * R12291 (0x3003) - Write Sequencer 3
+ */
+#define WM8994_WSEQ_EOS0 0x0100 /* WSEQ_EOS0 */
+#define WM8994_WSEQ_EOS0_MASK 0x0100 /* WSEQ_EOS0 */
+#define WM8994_WSEQ_EOS0_SHIFT 8 /* WSEQ_EOS0 */
+#define WM8994_WSEQ_EOS0_WIDTH 1 /* WSEQ_EOS0 */
+#define WM8994_WSEQ_DELAY0_MASK 0x000F /* WSEQ_DELAY0 - [3:0] */
+#define WM8994_WSEQ_DELAY0_SHIFT 0 /* WSEQ_DELAY0 - [3:0] */
+#define WM8994_WSEQ_DELAY0_WIDTH 4 /* WSEQ_DELAY0 - [3:0] */
+
+/*
+ * R12292 (0x3004) - Write Sequencer 4
+ */
+#define WM8994_WSEQ_ADDR1_MASK 0x3FFF /* WSEQ_ADDR1 - [13:0] */
+#define WM8994_WSEQ_ADDR1_SHIFT 0 /* WSEQ_ADDR1 - [13:0] */
+#define WM8994_WSEQ_ADDR1_WIDTH 14 /* WSEQ_ADDR1 - [13:0] */
+
+/*
+ * R12293 (0x3005) - Write Sequencer 5
+ */
+#define WM8994_WSEQ_DATA1_MASK 0x00FF /* WSEQ_DATA1 - [7:0] */
+#define WM8994_WSEQ_DATA1_SHIFT 0 /* WSEQ_DATA1 - [7:0] */
+#define WM8994_WSEQ_DATA1_WIDTH 8 /* WSEQ_DATA1 - [7:0] */
+
+/*
+ * R12294 (0x3006) - Write Sequencer 6
+ */
+#define WM8994_WSEQ_DATA_WIDTH1_MASK 0x0700 /* WSEQ_DATA_WIDTH1 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH1_SHIFT 8 /* WSEQ_DATA_WIDTH1 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH1_WIDTH 3 /* WSEQ_DATA_WIDTH1 - [10:8] */
+#define WM8994_WSEQ_DATA_START1_MASK 0x000F /* WSEQ_DATA_START1 - [3:0] */
+#define WM8994_WSEQ_DATA_START1_SHIFT 0 /* WSEQ_DATA_START1 - [3:0] */
+#define WM8994_WSEQ_DATA_START1_WIDTH 4 /* WSEQ_DATA_START1 - [3:0] */
+
+/*
+ * R12295 (0x3007) - Write Sequencer 7
+ */
+#define WM8994_WSEQ_EOS1 0x0100 /* WSEQ_EOS1 */
+#define WM8994_WSEQ_EOS1_MASK 0x0100 /* WSEQ_EOS1 */
+#define WM8994_WSEQ_EOS1_SHIFT 8 /* WSEQ_EOS1 */
+#define WM8994_WSEQ_EOS1_WIDTH 1 /* WSEQ_EOS1 */
+#define WM8994_WSEQ_DELAY1_MASK 0x000F /* WSEQ_DELAY1 - [3:0] */
+#define WM8994_WSEQ_DELAY1_SHIFT 0 /* WSEQ_DELAY1 - [3:0] */
+#define WM8994_WSEQ_DELAY1_WIDTH 4 /* WSEQ_DELAY1 - [3:0] */
+
+/*
+ * R12296 (0x3008) - Write Sequencer 8
+ */
+#define WM8994_WSEQ_ADDR2_MASK 0x3FFF /* WSEQ_ADDR2 - [13:0] */
+#define WM8994_WSEQ_ADDR2_SHIFT 0 /* WSEQ_ADDR2 - [13:0] */
+#define WM8994_WSEQ_ADDR2_WIDTH 14 /* WSEQ_ADDR2 - [13:0] */
+
+/*
+ * R12297 (0x3009) - Write Sequencer 9
+ */
+#define WM8994_WSEQ_DATA2_MASK 0x00FF /* WSEQ_DATA2 - [7:0] */
+#define WM8994_WSEQ_DATA2_SHIFT 0 /* WSEQ_DATA2 - [7:0] */
+#define WM8994_WSEQ_DATA2_WIDTH 8 /* WSEQ_DATA2 - [7:0] */
+
+/*
+ * R12298 (0x300A) - Write Sequencer 10
+ */
+#define WM8994_WSEQ_DATA_WIDTH2_MASK 0x0700 /* WSEQ_DATA_WIDTH2 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH2_SHIFT 8 /* WSEQ_DATA_WIDTH2 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH2_WIDTH 3 /* WSEQ_DATA_WIDTH2 - [10:8] */
+#define WM8994_WSEQ_DATA_START2_MASK 0x000F /* WSEQ_DATA_START2 - [3:0] */
+#define WM8994_WSEQ_DATA_START2_SHIFT 0 /* WSEQ_DATA_START2 - [3:0] */
+#define WM8994_WSEQ_DATA_START2_WIDTH 4 /* WSEQ_DATA_START2 - [3:0] */
+
+/*
+ * R12299 (0x300B) - Write Sequencer 11
+ */
+#define WM8994_WSEQ_EOS2 0x0100 /* WSEQ_EOS2 */
+#define WM8994_WSEQ_EOS2_MASK 0x0100 /* WSEQ_EOS2 */
+#define WM8994_WSEQ_EOS2_SHIFT 8 /* WSEQ_EOS2 */
+#define WM8994_WSEQ_EOS2_WIDTH 1 /* WSEQ_EOS2 */
+#define WM8994_WSEQ_DELAY2_MASK 0x000F /* WSEQ_DELAY2 - [3:0] */
+#define WM8994_WSEQ_DELAY2_SHIFT 0 /* WSEQ_DELAY2 - [3:0] */
+#define WM8994_WSEQ_DELAY2_WIDTH 4 /* WSEQ_DELAY2 - [3:0] */
+
+/*
+ * R12300 (0x300C) - Write Sequencer 12
+ */
+#define WM8994_WSEQ_ADDR3_MASK 0x3FFF /* WSEQ_ADDR3 - [13:0] */
+#define WM8994_WSEQ_ADDR3_SHIFT 0 /* WSEQ_ADDR3 - [13:0] */
+#define WM8994_WSEQ_ADDR3_WIDTH 14 /* WSEQ_ADDR3 - [13:0] */
+
+/*
+ * R12301 (0x300D) - Write Sequencer 13
+ */
+#define WM8994_WSEQ_DATA3_MASK 0x00FF /* WSEQ_DATA3 - [7:0] */
+#define WM8994_WSEQ_DATA3_SHIFT 0 /* WSEQ_DATA3 - [7:0] */
+#define WM8994_WSEQ_DATA3_WIDTH 8 /* WSEQ_DATA3 - [7:0] */
+
+/*
+ * R12302 (0x300E) - Write Sequencer 14
+ */
+#define WM8994_WSEQ_DATA_WIDTH3_MASK 0x0700 /* WSEQ_DATA_WIDTH3 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH3_SHIFT 8 /* WSEQ_DATA_WIDTH3 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH3_WIDTH 3 /* WSEQ_DATA_WIDTH3 - [10:8] */
+#define WM8994_WSEQ_DATA_START3_MASK 0x000F /* WSEQ_DATA_START3 - [3:0] */
+#define WM8994_WSEQ_DATA_START3_SHIFT 0 /* WSEQ_DATA_START3 - [3:0] */
+#define WM8994_WSEQ_DATA_START3_WIDTH 4 /* WSEQ_DATA_START3 - [3:0] */
+
+/*
+ * R12303 (0x300F) - Write Sequencer 15
+ */
+#define WM8994_WSEQ_EOS3 0x0100 /* WSEQ_EOS3 */
+#define WM8994_WSEQ_EOS3_MASK 0x0100 /* WSEQ_EOS3 */
+#define WM8994_WSEQ_EOS3_SHIFT 8 /* WSEQ_EOS3 */
+#define WM8994_WSEQ_EOS3_WIDTH 1 /* WSEQ_EOS3 */
+#define WM8994_WSEQ_DELAY3_MASK 0x000F /* WSEQ_DELAY3 - [3:0] */
+#define WM8994_WSEQ_DELAY3_SHIFT 0 /* WSEQ_DELAY3 - [3:0] */
+#define WM8994_WSEQ_DELAY3_WIDTH 4 /* WSEQ_DELAY3 - [3:0] */
+
+/*
+ * R12304 (0x3010) - Write Sequencer 16
+ */
+#define WM8994_WSEQ_ADDR4_MASK 0x3FFF /* WSEQ_ADDR4 - [13:0] */
+#define WM8994_WSEQ_ADDR4_SHIFT 0 /* WSEQ_ADDR4 - [13:0] */
+#define WM8994_WSEQ_ADDR4_WIDTH 14 /* WSEQ_ADDR4 - [13:0] */
+
+/*
+ * R12305 (0x3011) - Write Sequencer 17
+ */
+#define WM8994_WSEQ_DATA4_MASK 0x00FF /* WSEQ_DATA4 - [7:0] */
+#define WM8994_WSEQ_DATA4_SHIFT 0 /* WSEQ_DATA4 - [7:0] */
+#define WM8994_WSEQ_DATA4_WIDTH 8 /* WSEQ_DATA4 - [7:0] */
+
+/*
+ * R12306 (0x3012) - Write Sequencer 18
+ */
+#define WM8994_WSEQ_DATA_WIDTH4_MASK 0x0700 /* WSEQ_DATA_WIDTH4 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH4_SHIFT 8 /* WSEQ_DATA_WIDTH4 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH4_WIDTH 3 /* WSEQ_DATA_WIDTH4 - [10:8] */
+#define WM8994_WSEQ_DATA_START4_MASK 0x000F /* WSEQ_DATA_START4 - [3:0] */
+#define WM8994_WSEQ_DATA_START4_SHIFT 0 /* WSEQ_DATA_START4 - [3:0] */
+#define WM8994_WSEQ_DATA_START4_WIDTH 4 /* WSEQ_DATA_START4 - [3:0] */
+
+/*
+ * R12307 (0x3013) - Write Sequencer 19
+ */
+#define WM8994_WSEQ_EOS4 0x0100 /* WSEQ_EOS4 */
+#define WM8994_WSEQ_EOS4_MASK 0x0100 /* WSEQ_EOS4 */
+#define WM8994_WSEQ_EOS4_SHIFT 8 /* WSEQ_EOS4 */
+#define WM8994_WSEQ_EOS4_WIDTH 1 /* WSEQ_EOS4 */
+#define WM8994_WSEQ_DELAY4_MASK 0x000F /* WSEQ_DELAY4 - [3:0] */
+#define WM8994_WSEQ_DELAY4_SHIFT 0 /* WSEQ_DELAY4 - [3:0] */
+#define WM8994_WSEQ_DELAY4_WIDTH 4 /* WSEQ_DELAY4 - [3:0] */
+
+/*
+ * R12308 (0x3014) - Write Sequencer 20
+ */
+#define WM8994_WSEQ_ADDR5_MASK 0x3FFF /* WSEQ_ADDR5 - [13:0] */
+#define WM8994_WSEQ_ADDR5_SHIFT 0 /* WSEQ_ADDR5 - [13:0] */
+#define WM8994_WSEQ_ADDR5_WIDTH 14 /* WSEQ_ADDR5 - [13:0] */
+
+/*
+ * R12309 (0x3015) - Write Sequencer 21
+ */
+#define WM8994_WSEQ_DATA5_MASK 0x00FF /* WSEQ_DATA5 - [7:0] */
+#define WM8994_WSEQ_DATA5_SHIFT 0 /* WSEQ_DATA5 - [7:0] */
+#define WM8994_WSEQ_DATA5_WIDTH 8 /* WSEQ_DATA5 - [7:0] */
+
+/*
+ * R12310 (0x3016) - Write Sequencer 22
+ */
+#define WM8994_WSEQ_DATA_WIDTH5_MASK 0x0700 /* WSEQ_DATA_WIDTH5 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH5_SHIFT 8 /* WSEQ_DATA_WIDTH5 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH5_WIDTH 3 /* WSEQ_DATA_WIDTH5 - [10:8] */
+#define WM8994_WSEQ_DATA_START5_MASK 0x000F /* WSEQ_DATA_START5 - [3:0] */
+#define WM8994_WSEQ_DATA_START5_SHIFT 0 /* WSEQ_DATA_START5 - [3:0] */
+#define WM8994_WSEQ_DATA_START5_WIDTH 4 /* WSEQ_DATA_START5 - [3:0] */
+
+/*
+ * R12311 (0x3017) - Write Sequencer 23
+ */
+#define WM8994_WSEQ_EOS5 0x0100 /* WSEQ_EOS5 */
+#define WM8994_WSEQ_EOS5_MASK 0x0100 /* WSEQ_EOS5 */
+#define WM8994_WSEQ_EOS5_SHIFT 8 /* WSEQ_EOS5 */
+#define WM8994_WSEQ_EOS5_WIDTH 1 /* WSEQ_EOS5 */
+#define WM8994_WSEQ_DELAY5_MASK 0x000F /* WSEQ_DELAY5 - [3:0] */
+#define WM8994_WSEQ_DELAY5_SHIFT 0 /* WSEQ_DELAY5 - [3:0] */
+#define WM8994_WSEQ_DELAY5_WIDTH 4 /* WSEQ_DELAY5 - [3:0] */
+
+/*
+ * R12312 (0x3018) - Write Sequencer 24
+ */
+#define WM8994_WSEQ_ADDR6_MASK 0x3FFF /* WSEQ_ADDR6 - [13:0] */
+#define WM8994_WSEQ_ADDR6_SHIFT 0 /* WSEQ_ADDR6 - [13:0] */
+#define WM8994_WSEQ_ADDR6_WIDTH 14 /* WSEQ_ADDR6 - [13:0] */
+
+/*
+ * R12313 (0x3019) - Write Sequencer 25
+ */
+#define WM8994_WSEQ_DATA6_MASK 0x00FF /* WSEQ_DATA6 - [7:0] */
+#define WM8994_WSEQ_DATA6_SHIFT 0 /* WSEQ_DATA6 - [7:0] */
+#define WM8994_WSEQ_DATA6_WIDTH 8 /* WSEQ_DATA6 - [7:0] */
+
+/*
+ * R12314 (0x301A) - Write Sequencer 26
+ */
+#define WM8994_WSEQ_DATA_WIDTH6_MASK 0x0700 /* WSEQ_DATA_WIDTH6 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH6_SHIFT 8 /* WSEQ_DATA_WIDTH6 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH6_WIDTH 3 /* WSEQ_DATA_WIDTH6 - [10:8] */
+#define WM8994_WSEQ_DATA_START6_MASK 0x000F /* WSEQ_DATA_START6 - [3:0] */
+#define WM8994_WSEQ_DATA_START6_SHIFT 0 /* WSEQ_DATA_START6 - [3:0] */
+#define WM8994_WSEQ_DATA_START6_WIDTH 4 /* WSEQ_DATA_START6 - [3:0] */
+
+/*
+ * R12315 (0x301B) - Write Sequencer 27
+ */
+#define WM8994_WSEQ_EOS6 0x0100 /* WSEQ_EOS6 */
+#define WM8994_WSEQ_EOS6_MASK 0x0100 /* WSEQ_EOS6 */
+#define WM8994_WSEQ_EOS6_SHIFT 8 /* WSEQ_EOS6 */
+#define WM8994_WSEQ_EOS6_WIDTH 1 /* WSEQ_EOS6 */
+#define WM8994_WSEQ_DELAY6_MASK 0x000F /* WSEQ_DELAY6 - [3:0] */
+#define WM8994_WSEQ_DELAY6_SHIFT 0 /* WSEQ_DELAY6 - [3:0] */
+#define WM8994_WSEQ_DELAY6_WIDTH 4 /* WSEQ_DELAY6 - [3:0] */
+
+/*
+ * R12316 (0x301C) - Write Sequencer 28
+ */
+#define WM8994_WSEQ_ADDR7_MASK 0x3FFF /* WSEQ_ADDR7 - [13:0] */
+#define WM8994_WSEQ_ADDR7_SHIFT 0 /* WSEQ_ADDR7 - [13:0] */
+#define WM8994_WSEQ_ADDR7_WIDTH 14 /* WSEQ_ADDR7 - [13:0] */
+
+/*
+ * R12317 (0x301D) - Write Sequencer 29
+ */
+#define WM8994_WSEQ_DATA7_MASK 0x00FF /* WSEQ_DATA7 - [7:0] */
+#define WM8994_WSEQ_DATA7_SHIFT 0 /* WSEQ_DATA7 - [7:0] */
+#define WM8994_WSEQ_DATA7_WIDTH 8 /* WSEQ_DATA7 - [7:0] */
+
+/*
+ * R12318 (0x301E) - Write Sequencer 30
+ */
+#define WM8994_WSEQ_DATA_WIDTH7_MASK 0x0700 /* WSEQ_DATA_WIDTH7 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH7_SHIFT 8 /* WSEQ_DATA_WIDTH7 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH7_WIDTH 3 /* WSEQ_DATA_WIDTH7 - [10:8] */
+#define WM8994_WSEQ_DATA_START7_MASK 0x000F /* WSEQ_DATA_START7 - [3:0] */
+#define WM8994_WSEQ_DATA_START7_SHIFT 0 /* WSEQ_DATA_START7 - [3:0] */
+#define WM8994_WSEQ_DATA_START7_WIDTH 4 /* WSEQ_DATA_START7 - [3:0] */
+
+/*
+ * R12319 (0x301F) - Write Sequencer 31
+ */
+#define WM8994_WSEQ_EOS7 0x0100 /* WSEQ_EOS7 */
+#define WM8994_WSEQ_EOS7_MASK 0x0100 /* WSEQ_EOS7 */
+#define WM8994_WSEQ_EOS7_SHIFT 8 /* WSEQ_EOS7 */
+#define WM8994_WSEQ_EOS7_WIDTH 1 /* WSEQ_EOS7 */
+#define WM8994_WSEQ_DELAY7_MASK 0x000F /* WSEQ_DELAY7 - [3:0] */
+#define WM8994_WSEQ_DELAY7_SHIFT 0 /* WSEQ_DELAY7 - [3:0] */
+#define WM8994_WSEQ_DELAY7_WIDTH 4 /* WSEQ_DELAY7 - [3:0] */
+
+/*
+ * R12320 (0x3020) - Write Sequencer 32
+ */
+#define WM8994_WSEQ_ADDR8_MASK 0x3FFF /* WSEQ_ADDR8 - [13:0] */
+#define WM8994_WSEQ_ADDR8_SHIFT 0 /* WSEQ_ADDR8 - [13:0] */
+#define WM8994_WSEQ_ADDR8_WIDTH 14 /* WSEQ_ADDR8 - [13:0] */
+
+/*
+ * R12321 (0x3021) - Write Sequencer 33
+ */
+#define WM8994_WSEQ_DATA8_MASK 0x00FF /* WSEQ_DATA8 - [7:0] */
+#define WM8994_WSEQ_DATA8_SHIFT 0 /* WSEQ_DATA8 - [7:0] */
+#define WM8994_WSEQ_DATA8_WIDTH 8 /* WSEQ_DATA8 - [7:0] */
+
+/*
+ * R12322 (0x3022) - Write Sequencer 34
+ */
+#define WM8994_WSEQ_DATA_WIDTH8_MASK 0x0700 /* WSEQ_DATA_WIDTH8 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH8_SHIFT 8 /* WSEQ_DATA_WIDTH8 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH8_WIDTH 3 /* WSEQ_DATA_WIDTH8 - [10:8] */
+#define WM8994_WSEQ_DATA_START8_MASK 0x000F /* WSEQ_DATA_START8 - [3:0] */
+#define WM8994_WSEQ_DATA_START8_SHIFT 0 /* WSEQ_DATA_START8 - [3:0] */
+#define WM8994_WSEQ_DATA_START8_WIDTH 4 /* WSEQ_DATA_START8 - [3:0] */
+
+/*
+ * R12323 (0x3023) - Write Sequencer 35
+ */
+#define WM8994_WSEQ_EOS8 0x0100 /* WSEQ_EOS8 */
+#define WM8994_WSEQ_EOS8_MASK 0x0100 /* WSEQ_EOS8 */
+#define WM8994_WSEQ_EOS8_SHIFT 8 /* WSEQ_EOS8 */
+#define WM8994_WSEQ_EOS8_WIDTH 1 /* WSEQ_EOS8 */
+#define WM8994_WSEQ_DELAY8_MASK 0x000F /* WSEQ_DELAY8 - [3:0] */
+#define WM8994_WSEQ_DELAY8_SHIFT 0 /* WSEQ_DELAY8 - [3:0] */
+#define WM8994_WSEQ_DELAY8_WIDTH 4 /* WSEQ_DELAY8 - [3:0] */
+
+/*
+ * R12324 (0x3024) - Write Sequencer 36
+ */
+#define WM8994_WSEQ_ADDR9_MASK 0x3FFF /* WSEQ_ADDR9 - [13:0] */
+#define WM8994_WSEQ_ADDR9_SHIFT 0 /* WSEQ_ADDR9 - [13:0] */
+#define WM8994_WSEQ_ADDR9_WIDTH 14 /* WSEQ_ADDR9 - [13:0] */
+
+/*
+ * R12325 (0x3025) - Write Sequencer 37
+ */
+#define WM8994_WSEQ_DATA9_MASK 0x00FF /* WSEQ_DATA9 - [7:0] */
+#define WM8994_WSEQ_DATA9_SHIFT 0 /* WSEQ_DATA9 - [7:0] */
+#define WM8994_WSEQ_DATA9_WIDTH 8 /* WSEQ_DATA9 - [7:0] */
+
+/*
+ * R12326 (0x3026) - Write Sequencer 38
+ */
+#define WM8994_WSEQ_DATA_WIDTH9_MASK 0x0700 /* WSEQ_DATA_WIDTH9 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH9_SHIFT 8 /* WSEQ_DATA_WIDTH9 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH9_WIDTH 3 /* WSEQ_DATA_WIDTH9 - [10:8] */
+#define WM8994_WSEQ_DATA_START9_MASK 0x000F /* WSEQ_DATA_START9 - [3:0] */
+#define WM8994_WSEQ_DATA_START9_SHIFT 0 /* WSEQ_DATA_START9 - [3:0] */
+#define WM8994_WSEQ_DATA_START9_WIDTH 4 /* WSEQ_DATA_START9 - [3:0] */
+
+/*
+ * R12327 (0x3027) - Write Sequencer 39
+ */
+#define WM8994_WSEQ_EOS9 0x0100 /* WSEQ_EOS9 */
+#define WM8994_WSEQ_EOS9_MASK 0x0100 /* WSEQ_EOS9 */
+#define WM8994_WSEQ_EOS9_SHIFT 8 /* WSEQ_EOS9 */
+#define WM8994_WSEQ_EOS9_WIDTH 1 /* WSEQ_EOS9 */
+#define WM8994_WSEQ_DELAY9_MASK 0x000F /* WSEQ_DELAY9 - [3:0] */
+#define WM8994_WSEQ_DELAY9_SHIFT 0 /* WSEQ_DELAY9 - [3:0] */
+#define WM8994_WSEQ_DELAY9_WIDTH 4 /* WSEQ_DELAY9 - [3:0] */
+
+/*
+ * R12328 (0x3028) - Write Sequencer 40
+ */
+#define WM8994_WSEQ_ADDR10_MASK 0x3FFF /* WSEQ_ADDR10 - [13:0] */
+#define WM8994_WSEQ_ADDR10_SHIFT 0 /* WSEQ_ADDR10 - [13:0] */
+#define WM8994_WSEQ_ADDR10_WIDTH 14 /* WSEQ_ADDR10 - [13:0] */
+
+/*
+ * R12329 (0x3029) - Write Sequencer 41
+ */
+#define WM8994_WSEQ_DATA10_MASK 0x00FF /* WSEQ_DATA10 - [7:0] */
+#define WM8994_WSEQ_DATA10_SHIFT 0 /* WSEQ_DATA10 - [7:0] */
+#define WM8994_WSEQ_DATA10_WIDTH 8 /* WSEQ_DATA10 - [7:0] */
+
+/*
+ * R12330 (0x302A) - Write Sequencer 42
+ */
+#define WM8994_WSEQ_DATA_WIDTH10_MASK 0x0700 /* WSEQ_DATA_WIDTH10 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH10_SHIFT 8 /* WSEQ_DATA_WIDTH10 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH10_WIDTH 3 /* WSEQ_DATA_WIDTH10 - [10:8] */
+#define WM8994_WSEQ_DATA_START10_MASK 0x000F /* WSEQ_DATA_START10 - [3:0] */
+#define WM8994_WSEQ_DATA_START10_SHIFT 0 /* WSEQ_DATA_START10 - [3:0] */
+#define WM8994_WSEQ_DATA_START10_WIDTH 4 /* WSEQ_DATA_START10 - [3:0] */
+
+/*
+ * R12331 (0x302B) - Write Sequencer 43
+ */
+#define WM8994_WSEQ_EOS10 0x0100 /* WSEQ_EOS10 */
+#define WM8994_WSEQ_EOS10_MASK 0x0100 /* WSEQ_EOS10 */
+#define WM8994_WSEQ_EOS10_SHIFT 8 /* WSEQ_EOS10 */
+#define WM8994_WSEQ_EOS10_WIDTH 1 /* WSEQ_EOS10 */
+#define WM8994_WSEQ_DELAY10_MASK 0x000F /* WSEQ_DELAY10 - [3:0] */
+#define WM8994_WSEQ_DELAY10_SHIFT 0 /* WSEQ_DELAY10 - [3:0] */
+#define WM8994_WSEQ_DELAY10_WIDTH 4 /* WSEQ_DELAY10 - [3:0] */
+
+/*
+ * R12332 (0x302C) - Write Sequencer 44
+ */
+#define WM8994_WSEQ_ADDR11_MASK 0x3FFF /* WSEQ_ADDR11 - [13:0] */
+#define WM8994_WSEQ_ADDR11_SHIFT 0 /* WSEQ_ADDR11 - [13:0] */
+#define WM8994_WSEQ_ADDR11_WIDTH 14 /* WSEQ_ADDR11 - [13:0] */
+
+/*
+ * R12333 (0x302D) - Write Sequencer 45
+ */
+#define WM8994_WSEQ_DATA11_MASK 0x00FF /* WSEQ_DATA11 - [7:0] */
+#define WM8994_WSEQ_DATA11_SHIFT 0 /* WSEQ_DATA11 - [7:0] */
+#define WM8994_WSEQ_DATA11_WIDTH 8 /* WSEQ_DATA11 - [7:0] */
+
+/*
+ * R12334 (0x302E) - Write Sequencer 46
+ */
+#define WM8994_WSEQ_DATA_WIDTH11_MASK 0x0700 /* WSEQ_DATA_WIDTH11 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH11_SHIFT 8 /* WSEQ_DATA_WIDTH11 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH11_WIDTH 3 /* WSEQ_DATA_WIDTH11 - [10:8] */
+#define WM8994_WSEQ_DATA_START11_MASK 0x000F /* WSEQ_DATA_START11 - [3:0] */
+#define WM8994_WSEQ_DATA_START11_SHIFT 0 /* WSEQ_DATA_START11 - [3:0] */
+#define WM8994_WSEQ_DATA_START11_WIDTH 4 /* WSEQ_DATA_START11 - [3:0] */
+
+/*
+ * R12335 (0x302F) - Write Sequencer 47
+ */
+#define WM8994_WSEQ_EOS11 0x0100 /* WSEQ_EOS11 */
+#define WM8994_WSEQ_EOS11_MASK 0x0100 /* WSEQ_EOS11 */
+#define WM8994_WSEQ_EOS11_SHIFT 8 /* WSEQ_EOS11 */
+#define WM8994_WSEQ_EOS11_WIDTH 1 /* WSEQ_EOS11 */
+#define WM8994_WSEQ_DELAY11_MASK 0x000F /* WSEQ_DELAY11 - [3:0] */
+#define WM8994_WSEQ_DELAY11_SHIFT 0 /* WSEQ_DELAY11 - [3:0] */
+#define WM8994_WSEQ_DELAY11_WIDTH 4 /* WSEQ_DELAY11 - [3:0] */
+
+/*
+ * R12336 (0x3030) - Write Sequencer 48
+ */
+#define WM8994_WSEQ_ADDR12_MASK 0x3FFF /* WSEQ_ADDR12 - [13:0] */
+#define WM8994_WSEQ_ADDR12_SHIFT 0 /* WSEQ_ADDR12 - [13:0] */
+#define WM8994_WSEQ_ADDR12_WIDTH 14 /* WSEQ_ADDR12 - [13:0] */
+
+/*
+ * R12337 (0x3031) - Write Sequencer 49
+ */
+#define WM8994_WSEQ_DATA12_MASK 0x00FF /* WSEQ_DATA12 - [7:0] */
+#define WM8994_WSEQ_DATA12_SHIFT 0 /* WSEQ_DATA12 - [7:0] */
+#define WM8994_WSEQ_DATA12_WIDTH 8 /* WSEQ_DATA12 - [7:0] */
+
+/*
+ * R12338 (0x3032) - Write Sequencer 50
+ */
+#define WM8994_WSEQ_DATA_WIDTH12_MASK 0x0700 /* WSEQ_DATA_WIDTH12 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH12_SHIFT 8 /* WSEQ_DATA_WIDTH12 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH12_WIDTH 3 /* WSEQ_DATA_WIDTH12 - [10:8] */
+#define WM8994_WSEQ_DATA_START12_MASK 0x000F /* WSEQ_DATA_START12 - [3:0] */
+#define WM8994_WSEQ_DATA_START12_SHIFT 0 /* WSEQ_DATA_START12 - [3:0] */
+#define WM8994_WSEQ_DATA_START12_WIDTH 4 /* WSEQ_DATA_START12 - [3:0] */
+
+/*
+ * R12339 (0x3033) - Write Sequencer 51
+ */
+#define WM8994_WSEQ_EOS12 0x0100 /* WSEQ_EOS12 */
+#define WM8994_WSEQ_EOS12_MASK 0x0100 /* WSEQ_EOS12 */
+#define WM8994_WSEQ_EOS12_SHIFT 8 /* WSEQ_EOS12 */
+#define WM8994_WSEQ_EOS12_WIDTH 1 /* WSEQ_EOS12 */
+#define WM8994_WSEQ_DELAY12_MASK 0x000F /* WSEQ_DELAY12 - [3:0] */
+#define WM8994_WSEQ_DELAY12_SHIFT 0 /* WSEQ_DELAY12 - [3:0] */
+#define WM8994_WSEQ_DELAY12_WIDTH 4 /* WSEQ_DELAY12 - [3:0] */
+
+/*
+ * R12340 (0x3034) - Write Sequencer 52
+ */
+#define WM8994_WSEQ_ADDR13_MASK 0x3FFF /* WSEQ_ADDR13 - [13:0] */
+#define WM8994_WSEQ_ADDR13_SHIFT 0 /* WSEQ_ADDR13 - [13:0] */
+#define WM8994_WSEQ_ADDR13_WIDTH 14 /* WSEQ_ADDR13 - [13:0] */
+
+/*
+ * R12341 (0x3035) - Write Sequencer 53
+ */
+#define WM8994_WSEQ_DATA13_MASK 0x00FF /* WSEQ_DATA13 - [7:0] */
+#define WM8994_WSEQ_DATA13_SHIFT 0 /* WSEQ_DATA13 - [7:0] */
+#define WM8994_WSEQ_DATA13_WIDTH 8 /* WSEQ_DATA13 - [7:0] */
+
+/*
+ * R12342 (0x3036) - Write Sequencer 54
+ */
+#define WM8994_WSEQ_DATA_WIDTH13_MASK 0x0700 /* WSEQ_DATA_WIDTH13 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH13_SHIFT 8 /* WSEQ_DATA_WIDTH13 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH13_WIDTH 3 /* WSEQ_DATA_WIDTH13 - [10:8] */
+#define WM8994_WSEQ_DATA_START13_MASK 0x000F /* WSEQ_DATA_START13 - [3:0] */
+#define WM8994_WSEQ_DATA_START13_SHIFT 0 /* WSEQ_DATA_START13 - [3:0] */
+#define WM8994_WSEQ_DATA_START13_WIDTH 4 /* WSEQ_DATA_START13 - [3:0] */
+
+/*
+ * R12343 (0x3037) - Write Sequencer 55
+ */
+#define WM8994_WSEQ_EOS13 0x0100 /* WSEQ_EOS13 */
+#define WM8994_WSEQ_EOS13_MASK 0x0100 /* WSEQ_EOS13 */
+#define WM8994_WSEQ_EOS13_SHIFT 8 /* WSEQ_EOS13 */
+#define WM8994_WSEQ_EOS13_WIDTH 1 /* WSEQ_EOS13 */
+#define WM8994_WSEQ_DELAY13_MASK 0x000F /* WSEQ_DELAY13 - [3:0] */
+#define WM8994_WSEQ_DELAY13_SHIFT 0 /* WSEQ_DELAY13 - [3:0] */
+#define WM8994_WSEQ_DELAY13_WIDTH 4 /* WSEQ_DELAY13 - [3:0] */
+
+/*
+ * R12344 (0x3038) - Write Sequencer 56
+ */
+#define WM8994_WSEQ_ADDR14_MASK 0x3FFF /* WSEQ_ADDR14 - [13:0] */
+#define WM8994_WSEQ_ADDR14_SHIFT 0 /* WSEQ_ADDR14 - [13:0] */
+#define WM8994_WSEQ_ADDR14_WIDTH 14 /* WSEQ_ADDR14 - [13:0] */
+
+/*
+ * R12345 (0x3039) - Write Sequencer 57
+ */
+#define WM8994_WSEQ_DATA14_MASK 0x00FF /* WSEQ_DATA14 - [7:0] */
+#define WM8994_WSEQ_DATA14_SHIFT 0 /* WSEQ_DATA14 - [7:0] */
+#define WM8994_WSEQ_DATA14_WIDTH 8 /* WSEQ_DATA14 - [7:0] */
+
+/*
+ * R12346 (0x303A) - Write Sequencer 58
+ */
+#define WM8994_WSEQ_DATA_WIDTH14_MASK 0x0700 /* WSEQ_DATA_WIDTH14 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH14_SHIFT 8 /* WSEQ_DATA_WIDTH14 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH14_WIDTH 3 /* WSEQ_DATA_WIDTH14 - [10:8] */
+#define WM8994_WSEQ_DATA_START14_MASK 0x000F /* WSEQ_DATA_START14 - [3:0] */
+#define WM8994_WSEQ_DATA_START14_SHIFT 0 /* WSEQ_DATA_START14 - [3:0] */
+#define WM8994_WSEQ_DATA_START14_WIDTH 4 /* WSEQ_DATA_START14 - [3:0] */
+
+/*
+ * R12347 (0x303B) - Write Sequencer 59
+ */
+#define WM8994_WSEQ_EOS14 0x0100 /* WSEQ_EOS14 */
+#define WM8994_WSEQ_EOS14_MASK 0x0100 /* WSEQ_EOS14 */
+#define WM8994_WSEQ_EOS14_SHIFT 8 /* WSEQ_EOS14 */
+#define WM8994_WSEQ_EOS14_WIDTH 1 /* WSEQ_EOS14 */
+#define WM8994_WSEQ_DELAY14_MASK 0x000F /* WSEQ_DELAY14 - [3:0] */
+#define WM8994_WSEQ_DELAY14_SHIFT 0 /* WSEQ_DELAY14 - [3:0] */
+#define WM8994_WSEQ_DELAY14_WIDTH 4 /* WSEQ_DELAY14 - [3:0] */
+
+/*
+ * R12348 (0x303C) - Write Sequencer 60
+ */
+#define WM8994_WSEQ_ADDR15_MASK 0x3FFF /* WSEQ_ADDR15 - [13:0] */
+#define WM8994_WSEQ_ADDR15_SHIFT 0 /* WSEQ_ADDR15 - [13:0] */
+#define WM8994_WSEQ_ADDR15_WIDTH 14 /* WSEQ_ADDR15 - [13:0] */
+
+/*
+ * R12349 (0x303D) - Write Sequencer 61
+ */
+#define WM8994_WSEQ_DATA15_MASK 0x00FF /* WSEQ_DATA15 - [7:0] */
+#define WM8994_WSEQ_DATA15_SHIFT 0 /* WSEQ_DATA15 - [7:0] */
+#define WM8994_WSEQ_DATA15_WIDTH 8 /* WSEQ_DATA15 - [7:0] */
+
+/*
+ * R12350 (0x303E) - Write Sequencer 62
+ */
+#define WM8994_WSEQ_DATA_WIDTH15_MASK 0x0700 /* WSEQ_DATA_WIDTH15 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH15_SHIFT 8 /* WSEQ_DATA_WIDTH15 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH15_WIDTH 3 /* WSEQ_DATA_WIDTH15 - [10:8] */
+#define WM8994_WSEQ_DATA_START15_MASK 0x000F /* WSEQ_DATA_START15 - [3:0] */
+#define WM8994_WSEQ_DATA_START15_SHIFT 0 /* WSEQ_DATA_START15 - [3:0] */
+#define WM8994_WSEQ_DATA_START15_WIDTH 4 /* WSEQ_DATA_START15 - [3:0] */
+
+/*
+ * R12351 (0x303F) - Write Sequencer 63
+ */
+#define WM8994_WSEQ_EOS15 0x0100 /* WSEQ_EOS15 */
+#define WM8994_WSEQ_EOS15_MASK 0x0100 /* WSEQ_EOS15 */
+#define WM8994_WSEQ_EOS15_SHIFT 8 /* WSEQ_EOS15 */
+#define WM8994_WSEQ_EOS15_WIDTH 1 /* WSEQ_EOS15 */
+#define WM8994_WSEQ_DELAY15_MASK 0x000F /* WSEQ_DELAY15 - [3:0] */
+#define WM8994_WSEQ_DELAY15_SHIFT 0 /* WSEQ_DELAY15 - [3:0] */
+#define WM8994_WSEQ_DELAY15_WIDTH 4 /* WSEQ_DELAY15 - [3:0] */
+
+/*
+ * R12352 (0x3040) - Write Sequencer 64
+ */
+#define WM8994_WSEQ_ADDR16_MASK 0x3FFF /* WSEQ_ADDR16 - [13:0] */
+#define WM8994_WSEQ_ADDR16_SHIFT 0 /* WSEQ_ADDR16 - [13:0] */
+#define WM8994_WSEQ_ADDR16_WIDTH 14 /* WSEQ_ADDR16 - [13:0] */
+
+/*
+ * R12353 (0x3041) - Write Sequencer 65
+ */
+#define WM8994_WSEQ_DATA16_MASK 0x00FF /* WSEQ_DATA16 - [7:0] */
+#define WM8994_WSEQ_DATA16_SHIFT 0 /* WSEQ_DATA16 - [7:0] */
+#define WM8994_WSEQ_DATA16_WIDTH 8 /* WSEQ_DATA16 - [7:0] */
+
+/*
+ * R12354 (0x3042) - Write Sequencer 66
+ */
+#define WM8994_WSEQ_DATA_WIDTH16_MASK 0x0700 /* WSEQ_DATA_WIDTH16 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH16_SHIFT 8 /* WSEQ_DATA_WIDTH16 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH16_WIDTH 3 /* WSEQ_DATA_WIDTH16 - [10:8] */
+#define WM8994_WSEQ_DATA_START16_MASK 0x000F /* WSEQ_DATA_START16 - [3:0] */
+#define WM8994_WSEQ_DATA_START16_SHIFT 0 /* WSEQ_DATA_START16 - [3:0] */
+#define WM8994_WSEQ_DATA_START16_WIDTH 4 /* WSEQ_DATA_START16 - [3:0] */
+
+/*
+ * R12355 (0x3043) - Write Sequencer 67
+ */
+#define WM8994_WSEQ_EOS16 0x0100 /* WSEQ_EOS16 */
+#define WM8994_WSEQ_EOS16_MASK 0x0100 /* WSEQ_EOS16 */
+#define WM8994_WSEQ_EOS16_SHIFT 8 /* WSEQ_EOS16 */
+#define WM8994_WSEQ_EOS16_WIDTH 1 /* WSEQ_EOS16 */
+#define WM8994_WSEQ_DELAY16_MASK 0x000F /* WSEQ_DELAY16 - [3:0] */
+#define WM8994_WSEQ_DELAY16_SHIFT 0 /* WSEQ_DELAY16 - [3:0] */
+#define WM8994_WSEQ_DELAY16_WIDTH 4 /* WSEQ_DELAY16 - [3:0] */
+
+/*
+ * R12356 (0x3044) - Write Sequencer 68
+ */
+#define WM8994_WSEQ_ADDR17_MASK 0x3FFF /* WSEQ_ADDR17 - [13:0] */
+#define WM8994_WSEQ_ADDR17_SHIFT 0 /* WSEQ_ADDR17 - [13:0] */
+#define WM8994_WSEQ_ADDR17_WIDTH 14 /* WSEQ_ADDR17 - [13:0] */
+
+/*
+ * R12357 (0x3045) - Write Sequencer 69
+ */
+#define WM8994_WSEQ_DATA17_MASK 0x00FF /* WSEQ_DATA17 - [7:0] */
+#define WM8994_WSEQ_DATA17_SHIFT 0 /* WSEQ_DATA17 - [7:0] */
+#define WM8994_WSEQ_DATA17_WIDTH 8 /* WSEQ_DATA17 - [7:0] */
+
+/*
+ * R12358 (0x3046) - Write Sequencer 70
+ */
+#define WM8994_WSEQ_DATA_WIDTH17_MASK 0x0700 /* WSEQ_DATA_WIDTH17 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH17_SHIFT 8 /* WSEQ_DATA_WIDTH17 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH17_WIDTH 3 /* WSEQ_DATA_WIDTH17 - [10:8] */
+#define WM8994_WSEQ_DATA_START17_MASK 0x000F /* WSEQ_DATA_START17 - [3:0] */
+#define WM8994_WSEQ_DATA_START17_SHIFT 0 /* WSEQ_DATA_START17 - [3:0] */
+#define WM8994_WSEQ_DATA_START17_WIDTH 4 /* WSEQ_DATA_START17 - [3:0] */
+
+/*
+ * R12359 (0x3047) - Write Sequencer 71
+ */
+#define WM8994_WSEQ_EOS17 0x0100 /* WSEQ_EOS17 */
+#define WM8994_WSEQ_EOS17_MASK 0x0100 /* WSEQ_EOS17 */
+#define WM8994_WSEQ_EOS17_SHIFT 8 /* WSEQ_EOS17 */
+#define WM8994_WSEQ_EOS17_WIDTH 1 /* WSEQ_EOS17 */
+#define WM8994_WSEQ_DELAY17_MASK 0x000F /* WSEQ_DELAY17 - [3:0] */
+#define WM8994_WSEQ_DELAY17_SHIFT 0 /* WSEQ_DELAY17 - [3:0] */
+#define WM8994_WSEQ_DELAY17_WIDTH 4 /* WSEQ_DELAY17 - [3:0] */
+
+/*
+ * R12360 (0x3048) - Write Sequencer 72
+ */
+#define WM8994_WSEQ_ADDR18_MASK 0x3FFF /* WSEQ_ADDR18 - [13:0] */
+#define WM8994_WSEQ_ADDR18_SHIFT 0 /* WSEQ_ADDR18 - [13:0] */
+#define WM8994_WSEQ_ADDR18_WIDTH 14 /* WSEQ_ADDR18 - [13:0] */
+
+/*
+ * R12361 (0x3049) - Write Sequencer 73
+ */
+#define WM8994_WSEQ_DATA18_MASK 0x00FF /* WSEQ_DATA18 - [7:0] */
+#define WM8994_WSEQ_DATA18_SHIFT 0 /* WSEQ_DATA18 - [7:0] */
+#define WM8994_WSEQ_DATA18_WIDTH 8 /* WSEQ_DATA18 - [7:0] */
+
+/*
+ * R12362 (0x304A) - Write Sequencer 74
+ */
+#define WM8994_WSEQ_DATA_WIDTH18_MASK 0x0700 /* WSEQ_DATA_WIDTH18 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH18_SHIFT 8 /* WSEQ_DATA_WIDTH18 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH18_WIDTH 3 /* WSEQ_DATA_WIDTH18 - [10:8] */
+#define WM8994_WSEQ_DATA_START18_MASK 0x000F /* WSEQ_DATA_START18 - [3:0] */
+#define WM8994_WSEQ_DATA_START18_SHIFT 0 /* WSEQ_DATA_START18 - [3:0] */
+#define WM8994_WSEQ_DATA_START18_WIDTH 4 /* WSEQ_DATA_START18 - [3:0] */
+
+/*
+ * R12363 (0x304B) - Write Sequencer 75
+ */
+#define WM8994_WSEQ_EOS18 0x0100 /* WSEQ_EOS18 */
+#define WM8994_WSEQ_EOS18_MASK 0x0100 /* WSEQ_EOS18 */
+#define WM8994_WSEQ_EOS18_SHIFT 8 /* WSEQ_EOS18 */
+#define WM8994_WSEQ_EOS18_WIDTH 1 /* WSEQ_EOS18 */
+#define WM8994_WSEQ_DELAY18_MASK 0x000F /* WSEQ_DELAY18 - [3:0] */
+#define WM8994_WSEQ_DELAY18_SHIFT 0 /* WSEQ_DELAY18 - [3:0] */
+#define WM8994_WSEQ_DELAY18_WIDTH 4 /* WSEQ_DELAY18 - [3:0] */
+
+/*
+ * R12364 (0x304C) - Write Sequencer 76
+ */
+#define WM8994_WSEQ_ADDR19_MASK 0x3FFF /* WSEQ_ADDR19 - [13:0] */
+#define WM8994_WSEQ_ADDR19_SHIFT 0 /* WSEQ_ADDR19 - [13:0] */
+#define WM8994_WSEQ_ADDR19_WIDTH 14 /* WSEQ_ADDR19 - [13:0] */
+
+/*
+ * R12365 (0x304D) - Write Sequencer 77
+ */
+#define WM8994_WSEQ_DATA19_MASK 0x00FF /* WSEQ_DATA19 - [7:0] */
+#define WM8994_WSEQ_DATA19_SHIFT 0 /* WSEQ_DATA19 - [7:0] */
+#define WM8994_WSEQ_DATA19_WIDTH 8 /* WSEQ_DATA19 - [7:0] */
+
+/*
+ * R12366 (0x304E) - Write Sequencer 78
+ */
+#define WM8994_WSEQ_DATA_WIDTH19_MASK 0x0700 /* WSEQ_DATA_WIDTH19 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH19_SHIFT 8 /* WSEQ_DATA_WIDTH19 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH19_WIDTH 3 /* WSEQ_DATA_WIDTH19 - [10:8] */
+#define WM8994_WSEQ_DATA_START19_MASK 0x000F /* WSEQ_DATA_START19 - [3:0] */
+#define WM8994_WSEQ_DATA_START19_SHIFT 0 /* WSEQ_DATA_START19 - [3:0] */
+#define WM8994_WSEQ_DATA_START19_WIDTH 4 /* WSEQ_DATA_START19 - [3:0] */
+
+/*
+ * R12367 (0x304F) - Write Sequencer 79
+ */
+#define WM8994_WSEQ_EOS19 0x0100 /* WSEQ_EOS19 */
+#define WM8994_WSEQ_EOS19_MASK 0x0100 /* WSEQ_EOS19 */
+#define WM8994_WSEQ_EOS19_SHIFT 8 /* WSEQ_EOS19 */
+#define WM8994_WSEQ_EOS19_WIDTH 1 /* WSEQ_EOS19 */
+#define WM8994_WSEQ_DELAY19_MASK 0x000F /* WSEQ_DELAY19 - [3:0] */
+#define WM8994_WSEQ_DELAY19_SHIFT 0 /* WSEQ_DELAY19 - [3:0] */
+#define WM8994_WSEQ_DELAY19_WIDTH 4 /* WSEQ_DELAY19 - [3:0] */
+
+/*
+ * R12368 (0x3050) - Write Sequencer 80
+ */
+#define WM8994_WSEQ_ADDR20_MASK 0x3FFF /* WSEQ_ADDR20 - [13:0] */
+#define WM8994_WSEQ_ADDR20_SHIFT 0 /* WSEQ_ADDR20 - [13:0] */
+#define WM8994_WSEQ_ADDR20_WIDTH 14 /* WSEQ_ADDR20 - [13:0] */
+
+/*
+ * R12369 (0x3051) - Write Sequencer 81
+ */
+#define WM8994_WSEQ_DATA20_MASK 0x00FF /* WSEQ_DATA20 - [7:0] */
+#define WM8994_WSEQ_DATA20_SHIFT 0 /* WSEQ_DATA20 - [7:0] */
+#define WM8994_WSEQ_DATA20_WIDTH 8 /* WSEQ_DATA20 - [7:0] */
+
+/*
+ * R12370 (0x3052) - Write Sequencer 82
+ */
+#define WM8994_WSEQ_DATA_WIDTH20_MASK 0x0700 /* WSEQ_DATA_WIDTH20 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH20_SHIFT 8 /* WSEQ_DATA_WIDTH20 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH20_WIDTH 3 /* WSEQ_DATA_WIDTH20 - [10:8] */
+#define WM8994_WSEQ_DATA_START20_MASK 0x000F /* WSEQ_DATA_START20 - [3:0] */
+#define WM8994_WSEQ_DATA_START20_SHIFT 0 /* WSEQ_DATA_START20 - [3:0] */
+#define WM8994_WSEQ_DATA_START20_WIDTH 4 /* WSEQ_DATA_START20 - [3:0] */
+
+/*
+ * R12371 (0x3053) - Write Sequencer 83
+ */
+#define WM8994_WSEQ_EOS20 0x0100 /* WSEQ_EOS20 */
+#define WM8994_WSEQ_EOS20_MASK 0x0100 /* WSEQ_EOS20 */
+#define WM8994_WSEQ_EOS20_SHIFT 8 /* WSEQ_EOS20 */
+#define WM8994_WSEQ_EOS20_WIDTH 1 /* WSEQ_EOS20 */
+#define WM8994_WSEQ_DELAY20_MASK 0x000F /* WSEQ_DELAY20 - [3:0] */
+#define WM8994_WSEQ_DELAY20_SHIFT 0 /* WSEQ_DELAY20 - [3:0] */
+#define WM8994_WSEQ_DELAY20_WIDTH 4 /* WSEQ_DELAY20 - [3:0] */
+
+/*
+ * R12372 (0x3054) - Write Sequencer 84
+ */
+#define WM8994_WSEQ_ADDR21_MASK 0x3FFF /* WSEQ_ADDR21 - [13:0] */
+#define WM8994_WSEQ_ADDR21_SHIFT 0 /* WSEQ_ADDR21 - [13:0] */
+#define WM8994_WSEQ_ADDR21_WIDTH 14 /* WSEQ_ADDR21 - [13:0] */
+
+/*
+ * R12373 (0x3055) - Write Sequencer 85
+ */
+#define WM8994_WSEQ_DATA21_MASK 0x00FF /* WSEQ_DATA21 - [7:0] */
+#define WM8994_WSEQ_DATA21_SHIFT 0 /* WSEQ_DATA21 - [7:0] */
+#define WM8994_WSEQ_DATA21_WIDTH 8 /* WSEQ_DATA21 - [7:0] */
+
+/*
+ * R12374 (0x3056) - Write Sequencer 86
+ */
+#define WM8994_WSEQ_DATA_WIDTH21_MASK 0x0700 /* WSEQ_DATA_WIDTH21 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH21_SHIFT 8 /* WSEQ_DATA_WIDTH21 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH21_WIDTH 3 /* WSEQ_DATA_WIDTH21 - [10:8] */
+#define WM8994_WSEQ_DATA_START21_MASK 0x000F /* WSEQ_DATA_START21 - [3:0] */
+#define WM8994_WSEQ_DATA_START21_SHIFT 0 /* WSEQ_DATA_START21 - [3:0] */
+#define WM8994_WSEQ_DATA_START21_WIDTH 4 /* WSEQ_DATA_START21 - [3:0] */
+
+/*
+ * R12375 (0x3057) - Write Sequencer 87
+ */
+#define WM8994_WSEQ_EOS21 0x0100 /* WSEQ_EOS21 */
+#define WM8994_WSEQ_EOS21_MASK 0x0100 /* WSEQ_EOS21 */
+#define WM8994_WSEQ_EOS21_SHIFT 8 /* WSEQ_EOS21 */
+#define WM8994_WSEQ_EOS21_WIDTH 1 /* WSEQ_EOS21 */
+#define WM8994_WSEQ_DELAY21_MASK 0x000F /* WSEQ_DELAY21 - [3:0] */
+#define WM8994_WSEQ_DELAY21_SHIFT 0 /* WSEQ_DELAY21 - [3:0] */
+#define WM8994_WSEQ_DELAY21_WIDTH 4 /* WSEQ_DELAY21 - [3:0] */
+
+/*
+ * R12376 (0x3058) - Write Sequencer 88
+ */
+#define WM8994_WSEQ_ADDR22_MASK 0x3FFF /* WSEQ_ADDR22 - [13:0] */
+#define WM8994_WSEQ_ADDR22_SHIFT 0 /* WSEQ_ADDR22 - [13:0] */
+#define WM8994_WSEQ_ADDR22_WIDTH 14 /* WSEQ_ADDR22 - [13:0] */
+
+/*
+ * R12377 (0x3059) - Write Sequencer 89
+ */
+#define WM8994_WSEQ_DATA22_MASK 0x00FF /* WSEQ_DATA22 - [7:0] */
+#define WM8994_WSEQ_DATA22_SHIFT 0 /* WSEQ_DATA22 - [7:0] */
+#define WM8994_WSEQ_DATA22_WIDTH 8 /* WSEQ_DATA22 - [7:0] */
+
+/*
+ * R12378 (0x305A) - Write Sequencer 90
+ */
+#define WM8994_WSEQ_DATA_WIDTH22_MASK 0x0700 /* WSEQ_DATA_WIDTH22 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH22_SHIFT 8 /* WSEQ_DATA_WIDTH22 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH22_WIDTH 3 /* WSEQ_DATA_WIDTH22 - [10:8] */
+#define WM8994_WSEQ_DATA_START22_MASK 0x000F /* WSEQ_DATA_START22 - [3:0] */
+#define WM8994_WSEQ_DATA_START22_SHIFT 0 /* WSEQ_DATA_START22 - [3:0] */
+#define WM8994_WSEQ_DATA_START22_WIDTH 4 /* WSEQ_DATA_START22 - [3:0] */
+
+/*
+ * R12379 (0x305B) - Write Sequencer 91
+ */
+#define WM8994_WSEQ_EOS22 0x0100 /* WSEQ_EOS22 */
+#define WM8994_WSEQ_EOS22_MASK 0x0100 /* WSEQ_EOS22 */
+#define WM8994_WSEQ_EOS22_SHIFT 8 /* WSEQ_EOS22 */
+#define WM8994_WSEQ_EOS22_WIDTH 1 /* WSEQ_EOS22 */
+#define WM8994_WSEQ_DELAY22_MASK 0x000F /* WSEQ_DELAY22 - [3:0] */
+#define WM8994_WSEQ_DELAY22_SHIFT 0 /* WSEQ_DELAY22 - [3:0] */
+#define WM8994_WSEQ_DELAY22_WIDTH 4 /* WSEQ_DELAY22 - [3:0] */
+
+/*
+ * R12380 (0x305C) - Write Sequencer 92
+ */
+#define WM8994_WSEQ_ADDR23_MASK 0x3FFF /* WSEQ_ADDR23 - [13:0] */
+#define WM8994_WSEQ_ADDR23_SHIFT 0 /* WSEQ_ADDR23 - [13:0] */
+#define WM8994_WSEQ_ADDR23_WIDTH 14 /* WSEQ_ADDR23 - [13:0] */
+
+/*
+ * R12381 (0x305D) - Write Sequencer 93
+ */
+#define WM8994_WSEQ_DATA23_MASK 0x00FF /* WSEQ_DATA23 - [7:0] */
+#define WM8994_WSEQ_DATA23_SHIFT 0 /* WSEQ_DATA23 - [7:0] */
+#define WM8994_WSEQ_DATA23_WIDTH 8 /* WSEQ_DATA23 - [7:0] */
+
+/*
+ * R12382 (0x305E) - Write Sequencer 94
+ */
+#define WM8994_WSEQ_DATA_WIDTH23_MASK 0x0700 /* WSEQ_DATA_WIDTH23 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH23_SHIFT 8 /* WSEQ_DATA_WIDTH23 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH23_WIDTH 3 /* WSEQ_DATA_WIDTH23 - [10:8] */
+#define WM8994_WSEQ_DATA_START23_MASK 0x000F /* WSEQ_DATA_START23 - [3:0] */
+#define WM8994_WSEQ_DATA_START23_SHIFT 0 /* WSEQ_DATA_START23 - [3:0] */
+#define WM8994_WSEQ_DATA_START23_WIDTH 4 /* WSEQ_DATA_START23 - [3:0] */
+
+/*
+ * R12383 (0x305F) - Write Sequencer 95
+ */
+#define WM8994_WSEQ_EOS23 0x0100 /* WSEQ_EOS23 */
+#define WM8994_WSEQ_EOS23_MASK 0x0100 /* WSEQ_EOS23 */
+#define WM8994_WSEQ_EOS23_SHIFT 8 /* WSEQ_EOS23 */
+#define WM8994_WSEQ_EOS23_WIDTH 1 /* WSEQ_EOS23 */
+#define WM8994_WSEQ_DELAY23_MASK 0x000F /* WSEQ_DELAY23 - [3:0] */
+#define WM8994_WSEQ_DELAY23_SHIFT 0 /* WSEQ_DELAY23 - [3:0] */
+#define WM8994_WSEQ_DELAY23_WIDTH 4 /* WSEQ_DELAY23 - [3:0] */
+
+/*
+ * R12384 (0x3060) - Write Sequencer 96
+ */
+#define WM8994_WSEQ_ADDR24_MASK 0x3FFF /* WSEQ_ADDR24 - [13:0] */
+#define WM8994_WSEQ_ADDR24_SHIFT 0 /* WSEQ_ADDR24 - [13:0] */
+#define WM8994_WSEQ_ADDR24_WIDTH 14 /* WSEQ_ADDR24 - [13:0] */
+
+/*
+ * R12385 (0x3061) - Write Sequencer 97
+ */
+#define WM8994_WSEQ_DATA24_MASK 0x00FF /* WSEQ_DATA24 - [7:0] */
+#define WM8994_WSEQ_DATA24_SHIFT 0 /* WSEQ_DATA24 - [7:0] */
+#define WM8994_WSEQ_DATA24_WIDTH 8 /* WSEQ_DATA24 - [7:0] */
+
+/*
+ * R12386 (0x3062) - Write Sequencer 98
+ */
+#define WM8994_WSEQ_DATA_WIDTH24_MASK 0x0700 /* WSEQ_DATA_WIDTH24 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH24_SHIFT 8 /* WSEQ_DATA_WIDTH24 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH24_WIDTH 3 /* WSEQ_DATA_WIDTH24 - [10:8] */
+#define WM8994_WSEQ_DATA_START24_MASK 0x000F /* WSEQ_DATA_START24 - [3:0] */
+#define WM8994_WSEQ_DATA_START24_SHIFT 0 /* WSEQ_DATA_START24 - [3:0] */
+#define WM8994_WSEQ_DATA_START24_WIDTH 4 /* WSEQ_DATA_START24 - [3:0] */
+
+/*
+ * R12387 (0x3063) - Write Sequencer 99
+ */
+#define WM8994_WSEQ_EOS24 0x0100 /* WSEQ_EOS24 */
+#define WM8994_WSEQ_EOS24_MASK 0x0100 /* WSEQ_EOS24 */
+#define WM8994_WSEQ_EOS24_SHIFT 8 /* WSEQ_EOS24 */
+#define WM8994_WSEQ_EOS24_WIDTH 1 /* WSEQ_EOS24 */
+#define WM8994_WSEQ_DELAY24_MASK 0x000F /* WSEQ_DELAY24 - [3:0] */
+#define WM8994_WSEQ_DELAY24_SHIFT 0 /* WSEQ_DELAY24 - [3:0] */
+#define WM8994_WSEQ_DELAY24_WIDTH 4 /* WSEQ_DELAY24 - [3:0] */
+
+/*
+ * R12388 (0x3064) - Write Sequencer 100
+ */
+#define WM8994_WSEQ_ADDR25_MASK 0x3FFF /* WSEQ_ADDR25 - [13:0] */
+#define WM8994_WSEQ_ADDR25_SHIFT 0 /* WSEQ_ADDR25 - [13:0] */
+#define WM8994_WSEQ_ADDR25_WIDTH 14 /* WSEQ_ADDR25 - [13:0] */
+
+/*
+ * R12389 (0x3065) - Write Sequencer 101
+ */
+#define WM8994_WSEQ_DATA25_MASK 0x00FF /* WSEQ_DATA25 - [7:0] */
+#define WM8994_WSEQ_DATA25_SHIFT 0 /* WSEQ_DATA25 - [7:0] */
+#define WM8994_WSEQ_DATA25_WIDTH 8 /* WSEQ_DATA25 - [7:0] */
+
+/*
+ * R12390 (0x3066) - Write Sequencer 102
+ */
+#define WM8994_WSEQ_DATA_WIDTH25_MASK 0x0700 /* WSEQ_DATA_WIDTH25 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH25_SHIFT 8 /* WSEQ_DATA_WIDTH25 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH25_WIDTH 3 /* WSEQ_DATA_WIDTH25 - [10:8] */
+#define WM8994_WSEQ_DATA_START25_MASK 0x000F /* WSEQ_DATA_START25 - [3:0] */
+#define WM8994_WSEQ_DATA_START25_SHIFT 0 /* WSEQ_DATA_START25 - [3:0] */
+#define WM8994_WSEQ_DATA_START25_WIDTH 4 /* WSEQ_DATA_START25 - [3:0] */
+
+/*
+ * R12391 (0x3067) - Write Sequencer 103
+ */
+#define WM8994_WSEQ_EOS25 0x0100 /* WSEQ_EOS25 */
+#define WM8994_WSEQ_EOS25_MASK 0x0100 /* WSEQ_EOS25 */
+#define WM8994_WSEQ_EOS25_SHIFT 8 /* WSEQ_EOS25 */
+#define WM8994_WSEQ_EOS25_WIDTH 1 /* WSEQ_EOS25 */
+#define WM8994_WSEQ_DELAY25_MASK 0x000F /* WSEQ_DELAY25 - [3:0] */
+#define WM8994_WSEQ_DELAY25_SHIFT 0 /* WSEQ_DELAY25 - [3:0] */
+#define WM8994_WSEQ_DELAY25_WIDTH 4 /* WSEQ_DELAY25 - [3:0] */
+
+/*
+ * R12392 (0x3068) - Write Sequencer 104
+ */
+#define WM8994_WSEQ_ADDR26_MASK 0x3FFF /* WSEQ_ADDR26 - [13:0] */
+#define WM8994_WSEQ_ADDR26_SHIFT 0 /* WSEQ_ADDR26 - [13:0] */
+#define WM8994_WSEQ_ADDR26_WIDTH 14 /* WSEQ_ADDR26 - [13:0] */
+
+/*
+ * R12393 (0x3069) - Write Sequencer 105
+ */
+#define WM8994_WSEQ_DATA26_MASK 0x00FF /* WSEQ_DATA26 - [7:0] */
+#define WM8994_WSEQ_DATA26_SHIFT 0 /* WSEQ_DATA26 - [7:0] */
+#define WM8994_WSEQ_DATA26_WIDTH 8 /* WSEQ_DATA26 - [7:0] */
+
+/*
+ * R12394 (0x306A) - Write Sequencer 106
+ */
+#define WM8994_WSEQ_DATA_WIDTH26_MASK 0x0700 /* WSEQ_DATA_WIDTH26 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH26_SHIFT 8 /* WSEQ_DATA_WIDTH26 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH26_WIDTH 3 /* WSEQ_DATA_WIDTH26 - [10:8] */
+#define WM8994_WSEQ_DATA_START26_MASK 0x000F /* WSEQ_DATA_START26 - [3:0] */
+#define WM8994_WSEQ_DATA_START26_SHIFT 0 /* WSEQ_DATA_START26 - [3:0] */
+#define WM8994_WSEQ_DATA_START26_WIDTH 4 /* WSEQ_DATA_START26 - [3:0] */
+
+/*
+ * R12395 (0x306B) - Write Sequencer 107
+ */
+#define WM8994_WSEQ_EOS26 0x0100 /* WSEQ_EOS26 */
+#define WM8994_WSEQ_EOS26_MASK 0x0100 /* WSEQ_EOS26 */
+#define WM8994_WSEQ_EOS26_SHIFT 8 /* WSEQ_EOS26 */
+#define WM8994_WSEQ_EOS26_WIDTH 1 /* WSEQ_EOS26 */
+#define WM8994_WSEQ_DELAY26_MASK 0x000F /* WSEQ_DELAY26 - [3:0] */
+#define WM8994_WSEQ_DELAY26_SHIFT 0 /* WSEQ_DELAY26 - [3:0] */
+#define WM8994_WSEQ_DELAY26_WIDTH 4 /* WSEQ_DELAY26 - [3:0] */
+
+/*
+ * R12396 (0x306C) - Write Sequencer 108
+ */
+#define WM8994_WSEQ_ADDR27_MASK 0x3FFF /* WSEQ_ADDR27 - [13:0] */
+#define WM8994_WSEQ_ADDR27_SHIFT 0 /* WSEQ_ADDR27 - [13:0] */
+#define WM8994_WSEQ_ADDR27_WIDTH 14 /* WSEQ_ADDR27 - [13:0] */
+
+/*
+ * R12397 (0x306D) - Write Sequencer 109
+ */
+#define WM8994_WSEQ_DATA27_MASK 0x00FF /* WSEQ_DATA27 - [7:0] */
+#define WM8994_WSEQ_DATA27_SHIFT 0 /* WSEQ_DATA27 - [7:0] */
+#define WM8994_WSEQ_DATA27_WIDTH 8 /* WSEQ_DATA27 - [7:0] */
+
+/*
+ * R12398 (0x306E) - Write Sequencer 110
+ */
+#define WM8994_WSEQ_DATA_WIDTH27_MASK 0x0700 /* WSEQ_DATA_WIDTH27 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH27_SHIFT 8 /* WSEQ_DATA_WIDTH27 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH27_WIDTH 3 /* WSEQ_DATA_WIDTH27 - [10:8] */
+#define WM8994_WSEQ_DATA_START27_MASK 0x000F /* WSEQ_DATA_START27 - [3:0] */
+#define WM8994_WSEQ_DATA_START27_SHIFT 0 /* WSEQ_DATA_START27 - [3:0] */
+#define WM8994_WSEQ_DATA_START27_WIDTH 4 /* WSEQ_DATA_START27 - [3:0] */
+
+/*
+ * R12399 (0x306F) - Write Sequencer 111
+ */
+#define WM8994_WSEQ_EOS27 0x0100 /* WSEQ_EOS27 */
+#define WM8994_WSEQ_EOS27_MASK 0x0100 /* WSEQ_EOS27 */
+#define WM8994_WSEQ_EOS27_SHIFT 8 /* WSEQ_EOS27 */
+#define WM8994_WSEQ_EOS27_WIDTH 1 /* WSEQ_EOS27 */
+#define WM8994_WSEQ_DELAY27_MASK 0x000F /* WSEQ_DELAY27 - [3:0] */
+#define WM8994_WSEQ_DELAY27_SHIFT 0 /* WSEQ_DELAY27 - [3:0] */
+#define WM8994_WSEQ_DELAY27_WIDTH 4 /* WSEQ_DELAY27 - [3:0] */
+
+/*
+ * R12400 (0x3070) - Write Sequencer 112
+ */
+#define WM8994_WSEQ_ADDR28_MASK 0x3FFF /* WSEQ_ADDR28 - [13:0] */
+#define WM8994_WSEQ_ADDR28_SHIFT 0 /* WSEQ_ADDR28 - [13:0] */
+#define WM8994_WSEQ_ADDR28_WIDTH 14 /* WSEQ_ADDR28 - [13:0] */
+
+/*
+ * R12401 (0x3071) - Write Sequencer 113
+ */
+#define WM8994_WSEQ_DATA28_MASK 0x00FF /* WSEQ_DATA28 - [7:0] */
+#define WM8994_WSEQ_DATA28_SHIFT 0 /* WSEQ_DATA28 - [7:0] */
+#define WM8994_WSEQ_DATA28_WIDTH 8 /* WSEQ_DATA28 - [7:0] */
+
+/*
+ * R12402 (0x3072) - Write Sequencer 114
+ */
+#define WM8994_WSEQ_DATA_WIDTH28_MASK 0x0700 /* WSEQ_DATA_WIDTH28 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH28_SHIFT 8 /* WSEQ_DATA_WIDTH28 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH28_WIDTH 3 /* WSEQ_DATA_WIDTH28 - [10:8] */
+#define WM8994_WSEQ_DATA_START28_MASK 0x000F /* WSEQ_DATA_START28 - [3:0] */
+#define WM8994_WSEQ_DATA_START28_SHIFT 0 /* WSEQ_DATA_START28 - [3:0] */
+#define WM8994_WSEQ_DATA_START28_WIDTH 4 /* WSEQ_DATA_START28 - [3:0] */
+
+/*
+ * R12403 (0x3073) - Write Sequencer 115
+ */
+#define WM8994_WSEQ_EOS28 0x0100 /* WSEQ_EOS28 */
+#define WM8994_WSEQ_EOS28_MASK 0x0100 /* WSEQ_EOS28 */
+#define WM8994_WSEQ_EOS28_SHIFT 8 /* WSEQ_EOS28 */
+#define WM8994_WSEQ_EOS28_WIDTH 1 /* WSEQ_EOS28 */
+#define WM8994_WSEQ_DELAY28_MASK 0x000F /* WSEQ_DELAY28 - [3:0] */
+#define WM8994_WSEQ_DELAY28_SHIFT 0 /* WSEQ_DELAY28 - [3:0] */
+#define WM8994_WSEQ_DELAY28_WIDTH 4 /* WSEQ_DELAY28 - [3:0] */
+
+/*
+ * R12404 (0x3074) - Write Sequencer 116
+ */
+#define WM8994_WSEQ_ADDR29_MASK 0x3FFF /* WSEQ_ADDR29 - [13:0] */
+#define WM8994_WSEQ_ADDR29_SHIFT 0 /* WSEQ_ADDR29 - [13:0] */
+#define WM8994_WSEQ_ADDR29_WIDTH 14 /* WSEQ_ADDR29 - [13:0] */
+
+/*
+ * R12405 (0x3075) - Write Sequencer 117
+ */
+#define WM8994_WSEQ_DATA29_MASK 0x00FF /* WSEQ_DATA29 - [7:0] */
+#define WM8994_WSEQ_DATA29_SHIFT 0 /* WSEQ_DATA29 - [7:0] */
+#define WM8994_WSEQ_DATA29_WIDTH 8 /* WSEQ_DATA29 - [7:0] */
+
+/*
+ * R12406 (0x3076) - Write Sequencer 118
+ */
+#define WM8994_WSEQ_DATA_WIDTH29_MASK 0x0700 /* WSEQ_DATA_WIDTH29 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH29_SHIFT 8 /* WSEQ_DATA_WIDTH29 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH29_WIDTH 3 /* WSEQ_DATA_WIDTH29 - [10:8] */
+#define WM8994_WSEQ_DATA_START29_MASK 0x000F /* WSEQ_DATA_START29 - [3:0] */
+#define WM8994_WSEQ_DATA_START29_SHIFT 0 /* WSEQ_DATA_START29 - [3:0] */
+#define WM8994_WSEQ_DATA_START29_WIDTH 4 /* WSEQ_DATA_START29 - [3:0] */
+
+/*
+ * R12407 (0x3077) - Write Sequencer 119
+ */
+#define WM8994_WSEQ_EOS29 0x0100 /* WSEQ_EOS29 */
+#define WM8994_WSEQ_EOS29_MASK 0x0100 /* WSEQ_EOS29 */
+#define WM8994_WSEQ_EOS29_SHIFT 8 /* WSEQ_EOS29 */
+#define WM8994_WSEQ_EOS29_WIDTH 1 /* WSEQ_EOS29 */
+#define WM8994_WSEQ_DELAY29_MASK 0x000F /* WSEQ_DELAY29 - [3:0] */
+#define WM8994_WSEQ_DELAY29_SHIFT 0 /* WSEQ_DELAY29 - [3:0] */
+#define WM8994_WSEQ_DELAY29_WIDTH 4 /* WSEQ_DELAY29 - [3:0] */
+
+/*
+ * R12408 (0x3078) - Write Sequencer 120
+ */
+#define WM8994_WSEQ_ADDR30_MASK 0x3FFF /* WSEQ_ADDR30 - [13:0] */
+#define WM8994_WSEQ_ADDR30_SHIFT 0 /* WSEQ_ADDR30 - [13:0] */
+#define WM8994_WSEQ_ADDR30_WIDTH 14 /* WSEQ_ADDR30 - [13:0] */
+
+/*
+ * R12409 (0x3079) - Write Sequencer 121
+ */
+#define WM8994_WSEQ_DATA30_MASK 0x00FF /* WSEQ_DATA30 - [7:0] */
+#define WM8994_WSEQ_DATA30_SHIFT 0 /* WSEQ_DATA30 - [7:0] */
+#define WM8994_WSEQ_DATA30_WIDTH 8 /* WSEQ_DATA30 - [7:0] */
+
+/*
+ * R12410 (0x307A) - Write Sequencer 122
+ */
+#define WM8994_WSEQ_DATA_WIDTH30_MASK 0x0700 /* WSEQ_DATA_WIDTH30 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH30_SHIFT 8 /* WSEQ_DATA_WIDTH30 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH30_WIDTH 3 /* WSEQ_DATA_WIDTH30 - [10:8] */
+#define WM8994_WSEQ_DATA_START30_MASK 0x000F /* WSEQ_DATA_START30 - [3:0] */
+#define WM8994_WSEQ_DATA_START30_SHIFT 0 /* WSEQ_DATA_START30 - [3:0] */
+#define WM8994_WSEQ_DATA_START30_WIDTH 4 /* WSEQ_DATA_START30 - [3:0] */
+
+/*
+ * R12411 (0x307B) - Write Sequencer 123
+ */
+#define WM8994_WSEQ_EOS30 0x0100 /* WSEQ_EOS30 */
+#define WM8994_WSEQ_EOS30_MASK 0x0100 /* WSEQ_EOS30 */
+#define WM8994_WSEQ_EOS30_SHIFT 8 /* WSEQ_EOS30 */
+#define WM8994_WSEQ_EOS30_WIDTH 1 /* WSEQ_EOS30 */
+#define WM8994_WSEQ_DELAY30_MASK 0x000F /* WSEQ_DELAY30 - [3:0] */
+#define WM8994_WSEQ_DELAY30_SHIFT 0 /* WSEQ_DELAY30 - [3:0] */
+#define WM8994_WSEQ_DELAY30_WIDTH 4 /* WSEQ_DELAY30 - [3:0] */
+
+/*
+ * R12412 (0x307C) - Write Sequencer 124
+ */
+#define WM8994_WSEQ_ADDR31_MASK 0x3FFF /* WSEQ_ADDR31 - [13:0] */
+#define WM8994_WSEQ_ADDR31_SHIFT 0 /* WSEQ_ADDR31 - [13:0] */
+#define WM8994_WSEQ_ADDR31_WIDTH 14 /* WSEQ_ADDR31 - [13:0] */
+
+/*
+ * R12413 (0x307D) - Write Sequencer 125
+ */
+#define WM8994_WSEQ_DATA31_MASK 0x00FF /* WSEQ_DATA31 - [7:0] */
+#define WM8994_WSEQ_DATA31_SHIFT 0 /* WSEQ_DATA31 - [7:0] */
+#define WM8994_WSEQ_DATA31_WIDTH 8 /* WSEQ_DATA31 - [7:0] */
+
+/*
+ * R12414 (0x307E) - Write Sequencer 126
+ */
+#define WM8994_WSEQ_DATA_WIDTH31_MASK 0x0700 /* WSEQ_DATA_WIDTH31 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH31_SHIFT 8 /* WSEQ_DATA_WIDTH31 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH31_WIDTH 3 /* WSEQ_DATA_WIDTH31 - [10:8] */
+#define WM8994_WSEQ_DATA_START31_MASK 0x000F /* WSEQ_DATA_START31 - [3:0] */
+#define WM8994_WSEQ_DATA_START31_SHIFT 0 /* WSEQ_DATA_START31 - [3:0] */
+#define WM8994_WSEQ_DATA_START31_WIDTH 4 /* WSEQ_DATA_START31 - [3:0] */
+
+/*
+ * R12415 (0x307F) - Write Sequencer 127
+ */
+#define WM8994_WSEQ_EOS31 0x0100 /* WSEQ_EOS31 */
+#define WM8994_WSEQ_EOS31_MASK 0x0100 /* WSEQ_EOS31 */
+#define WM8994_WSEQ_EOS31_SHIFT 8 /* WSEQ_EOS31 */
+#define WM8994_WSEQ_EOS31_WIDTH 1 /* WSEQ_EOS31 */
+#define WM8994_WSEQ_DELAY31_MASK 0x000F /* WSEQ_DELAY31 - [3:0] */
+#define WM8994_WSEQ_DELAY31_SHIFT 0 /* WSEQ_DELAY31 - [3:0] */
+#define WM8994_WSEQ_DELAY31_WIDTH 4 /* WSEQ_DELAY31 - [3:0] */
+
+/*
+ * R12416 (0x3080) - Write Sequencer 128
+ */
+#define WM8994_WSEQ_ADDR32_MASK 0x3FFF /* WSEQ_ADDR32 - [13:0] */
+#define WM8994_WSEQ_ADDR32_SHIFT 0 /* WSEQ_ADDR32 - [13:0] */
+#define WM8994_WSEQ_ADDR32_WIDTH 14 /* WSEQ_ADDR32 - [13:0] */
+
+/*
+ * R12417 (0x3081) - Write Sequencer 129
+ */
+#define WM8994_WSEQ_DATA32_MASK 0x00FF /* WSEQ_DATA32 - [7:0] */
+#define WM8994_WSEQ_DATA32_SHIFT 0 /* WSEQ_DATA32 - [7:0] */
+#define WM8994_WSEQ_DATA32_WIDTH 8 /* WSEQ_DATA32 - [7:0] */
+
+/*
+ * R12418 (0x3082) - Write Sequencer 130
+ */
+#define WM8994_WSEQ_DATA_WIDTH32_MASK 0x0700 /* WSEQ_DATA_WIDTH32 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH32_SHIFT 8 /* WSEQ_DATA_WIDTH32 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH32_WIDTH 3 /* WSEQ_DATA_WIDTH32 - [10:8] */
+#define WM8994_WSEQ_DATA_START32_MASK 0x000F /* WSEQ_DATA_START32 - [3:0] */
+#define WM8994_WSEQ_DATA_START32_SHIFT 0 /* WSEQ_DATA_START32 - [3:0] */
+#define WM8994_WSEQ_DATA_START32_WIDTH 4 /* WSEQ_DATA_START32 - [3:0] */
+
+/*
+ * R12419 (0x3083) - Write Sequencer 131
+ */
+#define WM8994_WSEQ_EOS32 0x0100 /* WSEQ_EOS32 */
+#define WM8994_WSEQ_EOS32_MASK 0x0100 /* WSEQ_EOS32 */
+#define WM8994_WSEQ_EOS32_SHIFT 8 /* WSEQ_EOS32 */
+#define WM8994_WSEQ_EOS32_WIDTH 1 /* WSEQ_EOS32 */
+#define WM8994_WSEQ_DELAY32_MASK 0x000F /* WSEQ_DELAY32 - [3:0] */
+#define WM8994_WSEQ_DELAY32_SHIFT 0 /* WSEQ_DELAY32 - [3:0] */
+#define WM8994_WSEQ_DELAY32_WIDTH 4 /* WSEQ_DELAY32 - [3:0] */
+
+/*
+ * R12420 (0x3084) - Write Sequencer 132
+ */
+#define WM8994_WSEQ_ADDR33_MASK 0x3FFF /* WSEQ_ADDR33 - [13:0] */
+#define WM8994_WSEQ_ADDR33_SHIFT 0 /* WSEQ_ADDR33 - [13:0] */
+#define WM8994_WSEQ_ADDR33_WIDTH 14 /* WSEQ_ADDR33 - [13:0] */
+
+/*
+ * R12421 (0x3085) - Write Sequencer 133
+ */
+#define WM8994_WSEQ_DATA33_MASK 0x00FF /* WSEQ_DATA33 - [7:0] */
+#define WM8994_WSEQ_DATA33_SHIFT 0 /* WSEQ_DATA33 - [7:0] */
+#define WM8994_WSEQ_DATA33_WIDTH 8 /* WSEQ_DATA33 - [7:0] */
+
+/*
+ * R12422 (0x3086) - Write Sequencer 134
+ */
+#define WM8994_WSEQ_DATA_WIDTH33_MASK 0x0700 /* WSEQ_DATA_WIDTH33 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH33_SHIFT 8 /* WSEQ_DATA_WIDTH33 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH33_WIDTH 3 /* WSEQ_DATA_WIDTH33 - [10:8] */
+#define WM8994_WSEQ_DATA_START33_MASK 0x000F /* WSEQ_DATA_START33 - [3:0] */
+#define WM8994_WSEQ_DATA_START33_SHIFT 0 /* WSEQ_DATA_START33 - [3:0] */
+#define WM8994_WSEQ_DATA_START33_WIDTH 4 /* WSEQ_DATA_START33 - [3:0] */
+
+/*
+ * R12423 (0x3087) - Write Sequencer 135
+ */
+#define WM8994_WSEQ_EOS33 0x0100 /* WSEQ_EOS33 */
+#define WM8994_WSEQ_EOS33_MASK 0x0100 /* WSEQ_EOS33 */
+#define WM8994_WSEQ_EOS33_SHIFT 8 /* WSEQ_EOS33 */
+#define WM8994_WSEQ_EOS33_WIDTH 1 /* WSEQ_EOS33 */
+#define WM8994_WSEQ_DELAY33_MASK 0x000F /* WSEQ_DELAY33 - [3:0] */
+#define WM8994_WSEQ_DELAY33_SHIFT 0 /* WSEQ_DELAY33 - [3:0] */
+#define WM8994_WSEQ_DELAY33_WIDTH 4 /* WSEQ_DELAY33 - [3:0] */
+
+/*
+ * R12424 (0x3088) - Write Sequencer 136
+ */
+#define WM8994_WSEQ_ADDR34_MASK 0x3FFF /* WSEQ_ADDR34 - [13:0] */
+#define WM8994_WSEQ_ADDR34_SHIFT 0 /* WSEQ_ADDR34 - [13:0] */
+#define WM8994_WSEQ_ADDR34_WIDTH 14 /* WSEQ_ADDR34 - [13:0] */
+
+/*
+ * R12425 (0x3089) - Write Sequencer 137
+ */
+#define WM8994_WSEQ_DATA34_MASK 0x00FF /* WSEQ_DATA34 - [7:0] */
+#define WM8994_WSEQ_DATA34_SHIFT 0 /* WSEQ_DATA34 - [7:0] */
+#define WM8994_WSEQ_DATA34_WIDTH 8 /* WSEQ_DATA34 - [7:0] */
+
+/*
+ * R12426 (0x308A) - Write Sequencer 138
+ */
+#define WM8994_WSEQ_DATA_WIDTH34_MASK 0x0700 /* WSEQ_DATA_WIDTH34 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH34_SHIFT 8 /* WSEQ_DATA_WIDTH34 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH34_WIDTH 3 /* WSEQ_DATA_WIDTH34 - [10:8] */
+#define WM8994_WSEQ_DATA_START34_MASK 0x000F /* WSEQ_DATA_START34 - [3:0] */
+#define WM8994_WSEQ_DATA_START34_SHIFT 0 /* WSEQ_DATA_START34 - [3:0] */
+#define WM8994_WSEQ_DATA_START34_WIDTH 4 /* WSEQ_DATA_START34 - [3:0] */
+
+/*
+ * R12427 (0x308B) - Write Sequencer 139
+ */
+#define WM8994_WSEQ_EOS34 0x0100 /* WSEQ_EOS34 */
+#define WM8994_WSEQ_EOS34_MASK 0x0100 /* WSEQ_EOS34 */
+#define WM8994_WSEQ_EOS34_SHIFT 8 /* WSEQ_EOS34 */
+#define WM8994_WSEQ_EOS34_WIDTH 1 /* WSEQ_EOS34 */
+#define WM8994_WSEQ_DELAY34_MASK 0x000F /* WSEQ_DELAY34 - [3:0] */
+#define WM8994_WSEQ_DELAY34_SHIFT 0 /* WSEQ_DELAY34 - [3:0] */
+#define WM8994_WSEQ_DELAY34_WIDTH 4 /* WSEQ_DELAY34 - [3:0] */
+
+/*
+ * R12428 (0x308C) - Write Sequencer 140
+ */
+#define WM8994_WSEQ_ADDR35_MASK 0x3FFF /* WSEQ_ADDR35 - [13:0] */
+#define WM8994_WSEQ_ADDR35_SHIFT 0 /* WSEQ_ADDR35 - [13:0] */
+#define WM8994_WSEQ_ADDR35_WIDTH 14 /* WSEQ_ADDR35 - [13:0] */
+
+/*
+ * R12429 (0x308D) - Write Sequencer 141
+ */
+#define WM8994_WSEQ_DATA35_MASK 0x00FF /* WSEQ_DATA35 - [7:0] */
+#define WM8994_WSEQ_DATA35_SHIFT 0 /* WSEQ_DATA35 - [7:0] */
+#define WM8994_WSEQ_DATA35_WIDTH 8 /* WSEQ_DATA35 - [7:0] */
+
+/*
+ * R12430 (0x308E) - Write Sequencer 142
+ */
+#define WM8994_WSEQ_DATA_WIDTH35_MASK 0x0700 /* WSEQ_DATA_WIDTH35 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH35_SHIFT 8 /* WSEQ_DATA_WIDTH35 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH35_WIDTH 3 /* WSEQ_DATA_WIDTH35 - [10:8] */
+#define WM8994_WSEQ_DATA_START35_MASK 0x000F /* WSEQ_DATA_START35 - [3:0] */
+#define WM8994_WSEQ_DATA_START35_SHIFT 0 /* WSEQ_DATA_START35 - [3:0] */
+#define WM8994_WSEQ_DATA_START35_WIDTH 4 /* WSEQ_DATA_START35 - [3:0] */
+
+/*
+ * R12431 (0x308F) - Write Sequencer 143
+ */
+#define WM8994_WSEQ_EOS35 0x0100 /* WSEQ_EOS35 */
+#define WM8994_WSEQ_EOS35_MASK 0x0100 /* WSEQ_EOS35 */
+#define WM8994_WSEQ_EOS35_SHIFT 8 /* WSEQ_EOS35 */
+#define WM8994_WSEQ_EOS35_WIDTH 1 /* WSEQ_EOS35 */
+#define WM8994_WSEQ_DELAY35_MASK 0x000F /* WSEQ_DELAY35 - [3:0] */
+#define WM8994_WSEQ_DELAY35_SHIFT 0 /* WSEQ_DELAY35 - [3:0] */
+#define WM8994_WSEQ_DELAY35_WIDTH 4 /* WSEQ_DELAY35 - [3:0] */
+
+/*
+ * R12432 (0x3090) - Write Sequencer 144
+ */
+#define WM8994_WSEQ_ADDR36_MASK 0x3FFF /* WSEQ_ADDR36 - [13:0] */
+#define WM8994_WSEQ_ADDR36_SHIFT 0 /* WSEQ_ADDR36 - [13:0] */
+#define WM8994_WSEQ_ADDR36_WIDTH 14 /* WSEQ_ADDR36 - [13:0] */
+
+/*
+ * R12433 (0x3091) - Write Sequencer 145
+ */
+#define WM8994_WSEQ_DATA36_MASK 0x00FF /* WSEQ_DATA36 - [7:0] */
+#define WM8994_WSEQ_DATA36_SHIFT 0 /* WSEQ_DATA36 - [7:0] */
+#define WM8994_WSEQ_DATA36_WIDTH 8 /* WSEQ_DATA36 - [7:0] */
+
+/*
+ * R12434 (0x3092) - Write Sequencer 146
+ */
+#define WM8994_WSEQ_DATA_WIDTH36_MASK 0x0700 /* WSEQ_DATA_WIDTH36 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH36_SHIFT 8 /* WSEQ_DATA_WIDTH36 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH36_WIDTH 3 /* WSEQ_DATA_WIDTH36 - [10:8] */
+#define WM8994_WSEQ_DATA_START36_MASK 0x000F /* WSEQ_DATA_START36 - [3:0] */
+#define WM8994_WSEQ_DATA_START36_SHIFT 0 /* WSEQ_DATA_START36 - [3:0] */
+#define WM8994_WSEQ_DATA_START36_WIDTH 4 /* WSEQ_DATA_START36 - [3:0] */
+
+/*
+ * R12435 (0x3093) - Write Sequencer 147
+ */
+#define WM8994_WSEQ_EOS36 0x0100 /* WSEQ_EOS36 */
+#define WM8994_WSEQ_EOS36_MASK 0x0100 /* WSEQ_EOS36 */
+#define WM8994_WSEQ_EOS36_SHIFT 8 /* WSEQ_EOS36 */
+#define WM8994_WSEQ_EOS36_WIDTH 1 /* WSEQ_EOS36 */
+#define WM8994_WSEQ_DELAY36_MASK 0x000F /* WSEQ_DELAY36 - [3:0] */
+#define WM8994_WSEQ_DELAY36_SHIFT 0 /* WSEQ_DELAY36 - [3:0] */
+#define WM8994_WSEQ_DELAY36_WIDTH 4 /* WSEQ_DELAY36 - [3:0] */
+
+/*
+ * R12436 (0x3094) - Write Sequencer 148
+ */
+#define WM8994_WSEQ_ADDR37_MASK 0x3FFF /* WSEQ_ADDR37 - [13:0] */
+#define WM8994_WSEQ_ADDR37_SHIFT 0 /* WSEQ_ADDR37 - [13:0] */
+#define WM8994_WSEQ_ADDR37_WIDTH 14 /* WSEQ_ADDR37 - [13:0] */
+
+/*
+ * R12437 (0x3095) - Write Sequencer 149
+ */
+#define WM8994_WSEQ_DATA37_MASK 0x00FF /* WSEQ_DATA37 - [7:0] */
+#define WM8994_WSEQ_DATA37_SHIFT 0 /* WSEQ_DATA37 - [7:0] */
+#define WM8994_WSEQ_DATA37_WIDTH 8 /* WSEQ_DATA37 - [7:0] */
+
+/*
+ * R12438 (0x3096) - Write Sequencer 150
+ */
+#define WM8994_WSEQ_DATA_WIDTH37_MASK 0x0700 /* WSEQ_DATA_WIDTH37 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH37_SHIFT 8 /* WSEQ_DATA_WIDTH37 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH37_WIDTH 3 /* WSEQ_DATA_WIDTH37 - [10:8] */
+#define WM8994_WSEQ_DATA_START37_MASK 0x000F /* WSEQ_DATA_START37 - [3:0] */
+#define WM8994_WSEQ_DATA_START37_SHIFT 0 /* WSEQ_DATA_START37 - [3:0] */
+#define WM8994_WSEQ_DATA_START37_WIDTH 4 /* WSEQ_DATA_START37 - [3:0] */
+
+/*
+ * R12439 (0x3097) - Write Sequencer 151
+ */
+#define WM8994_WSEQ_EOS37 0x0100 /* WSEQ_EOS37 */
+#define WM8994_WSEQ_EOS37_MASK 0x0100 /* WSEQ_EOS37 */
+#define WM8994_WSEQ_EOS37_SHIFT 8 /* WSEQ_EOS37 */
+#define WM8994_WSEQ_EOS37_WIDTH 1 /* WSEQ_EOS37 */
+#define WM8994_WSEQ_DELAY37_MASK 0x000F /* WSEQ_DELAY37 - [3:0] */
+#define WM8994_WSEQ_DELAY37_SHIFT 0 /* WSEQ_DELAY37 - [3:0] */
+#define WM8994_WSEQ_DELAY37_WIDTH 4 /* WSEQ_DELAY37 - [3:0] */
+
+/*
+ * R12440 (0x3098) - Write Sequencer 152
+ */
+#define WM8994_WSEQ_ADDR38_MASK 0x3FFF /* WSEQ_ADDR38 - [13:0] */
+#define WM8994_WSEQ_ADDR38_SHIFT 0 /* WSEQ_ADDR38 - [13:0] */
+#define WM8994_WSEQ_ADDR38_WIDTH 14 /* WSEQ_ADDR38 - [13:0] */
+
+/*
+ * R12441 (0x3099) - Write Sequencer 153
+ */
+#define WM8994_WSEQ_DATA38_MASK 0x00FF /* WSEQ_DATA38 - [7:0] */
+#define WM8994_WSEQ_DATA38_SHIFT 0 /* WSEQ_DATA38 - [7:0] */
+#define WM8994_WSEQ_DATA38_WIDTH 8 /* WSEQ_DATA38 - [7:0] */
+
+/*
+ * R12442 (0x309A) - Write Sequencer 154
+ */
+#define WM8994_WSEQ_DATA_WIDTH38_MASK 0x0700 /* WSEQ_DATA_WIDTH38 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH38_SHIFT 8 /* WSEQ_DATA_WIDTH38 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH38_WIDTH 3 /* WSEQ_DATA_WIDTH38 - [10:8] */
+#define WM8994_WSEQ_DATA_START38_MASK 0x000F /* WSEQ_DATA_START38 - [3:0] */
+#define WM8994_WSEQ_DATA_START38_SHIFT 0 /* WSEQ_DATA_START38 - [3:0] */
+#define WM8994_WSEQ_DATA_START38_WIDTH 4 /* WSEQ_DATA_START38 - [3:0] */
+
+/*
+ * R12443 (0x309B) - Write Sequencer 155
+ */
+#define WM8994_WSEQ_EOS38 0x0100 /* WSEQ_EOS38 */
+#define WM8994_WSEQ_EOS38_MASK 0x0100 /* WSEQ_EOS38 */
+#define WM8994_WSEQ_EOS38_SHIFT 8 /* WSEQ_EOS38 */
+#define WM8994_WSEQ_EOS38_WIDTH 1 /* WSEQ_EOS38 */
+#define WM8994_WSEQ_DELAY38_MASK 0x000F /* WSEQ_DELAY38 - [3:0] */
+#define WM8994_WSEQ_DELAY38_SHIFT 0 /* WSEQ_DELAY38 - [3:0] */
+#define WM8994_WSEQ_DELAY38_WIDTH 4 /* WSEQ_DELAY38 - [3:0] */
+
+/*
+ * R12444 (0x309C) - Write Sequencer 156
+ */
+#define WM8994_WSEQ_ADDR39_MASK 0x3FFF /* WSEQ_ADDR39 - [13:0] */
+#define WM8994_WSEQ_ADDR39_SHIFT 0 /* WSEQ_ADDR39 - [13:0] */
+#define WM8994_WSEQ_ADDR39_WIDTH 14 /* WSEQ_ADDR39 - [13:0] */
+
+/*
+ * R12445 (0x309D) - Write Sequencer 157
+ */
+#define WM8994_WSEQ_DATA39_MASK 0x00FF /* WSEQ_DATA39 - [7:0] */
+#define WM8994_WSEQ_DATA39_SHIFT 0 /* WSEQ_DATA39 - [7:0] */
+#define WM8994_WSEQ_DATA39_WIDTH 8 /* WSEQ_DATA39 - [7:0] */
+
+/*
+ * R12446 (0x309E) - Write Sequencer 158
+ */
+#define WM8994_WSEQ_DATA_WIDTH39_MASK 0x0700 /* WSEQ_DATA_WIDTH39 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH39_SHIFT 8 /* WSEQ_DATA_WIDTH39 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH39_WIDTH 3 /* WSEQ_DATA_WIDTH39 - [10:8] */
+#define WM8994_WSEQ_DATA_START39_MASK 0x000F /* WSEQ_DATA_START39 - [3:0] */
+#define WM8994_WSEQ_DATA_START39_SHIFT 0 /* WSEQ_DATA_START39 - [3:0] */
+#define WM8994_WSEQ_DATA_START39_WIDTH 4 /* WSEQ_DATA_START39 - [3:0] */
+
+/*
+ * R12447 (0x309F) - Write Sequencer 159
+ */
+#define WM8994_WSEQ_EOS39 0x0100 /* WSEQ_EOS39 */
+#define WM8994_WSEQ_EOS39_MASK 0x0100 /* WSEQ_EOS39 */
+#define WM8994_WSEQ_EOS39_SHIFT 8 /* WSEQ_EOS39 */
+#define WM8994_WSEQ_EOS39_WIDTH 1 /* WSEQ_EOS39 */
+#define WM8994_WSEQ_DELAY39_MASK 0x000F /* WSEQ_DELAY39 - [3:0] */
+#define WM8994_WSEQ_DELAY39_SHIFT 0 /* WSEQ_DELAY39 - [3:0] */
+#define WM8994_WSEQ_DELAY39_WIDTH 4 /* WSEQ_DELAY39 - [3:0] */
+
+/*
+ * R12448 (0x30A0) - Write Sequencer 160
+ */
+#define WM8994_WSEQ_ADDR40_MASK 0x3FFF /* WSEQ_ADDR40 - [13:0] */
+#define WM8994_WSEQ_ADDR40_SHIFT 0 /* WSEQ_ADDR40 - [13:0] */
+#define WM8994_WSEQ_ADDR40_WIDTH 14 /* WSEQ_ADDR40 - [13:0] */
+
+/*
+ * R12449 (0x30A1) - Write Sequencer 161
+ */
+#define WM8994_WSEQ_DATA40_MASK 0x00FF /* WSEQ_DATA40 - [7:0] */
+#define WM8994_WSEQ_DATA40_SHIFT 0 /* WSEQ_DATA40 - [7:0] */
+#define WM8994_WSEQ_DATA40_WIDTH 8 /* WSEQ_DATA40 - [7:0] */
+
+/*
+ * R12450 (0x30A2) - Write Sequencer 162
+ */
+#define WM8994_WSEQ_DATA_WIDTH40_MASK 0x0700 /* WSEQ_DATA_WIDTH40 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH40_SHIFT 8 /* WSEQ_DATA_WIDTH40 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH40_WIDTH 3 /* WSEQ_DATA_WIDTH40 - [10:8] */
+#define WM8994_WSEQ_DATA_START40_MASK 0x000F /* WSEQ_DATA_START40 - [3:0] */
+#define WM8994_WSEQ_DATA_START40_SHIFT 0 /* WSEQ_DATA_START40 - [3:0] */
+#define WM8994_WSEQ_DATA_START40_WIDTH 4 /* WSEQ_DATA_START40 - [3:0] */
+
+/*
+ * R12451 (0x30A3) - Write Sequencer 163
+ */
+#define WM8994_WSEQ_EOS40 0x0100 /* WSEQ_EOS40 */
+#define WM8994_WSEQ_EOS40_MASK 0x0100 /* WSEQ_EOS40 */
+#define WM8994_WSEQ_EOS40_SHIFT 8 /* WSEQ_EOS40 */
+#define WM8994_WSEQ_EOS40_WIDTH 1 /* WSEQ_EOS40 */
+#define WM8994_WSEQ_DELAY40_MASK 0x000F /* WSEQ_DELAY40 - [3:0] */
+#define WM8994_WSEQ_DELAY40_SHIFT 0 /* WSEQ_DELAY40 - [3:0] */
+#define WM8994_WSEQ_DELAY40_WIDTH 4 /* WSEQ_DELAY40 - [3:0] */
+
+/*
+ * R12452 (0x30A4) - Write Sequencer 164
+ */
+#define WM8994_WSEQ_ADDR41_MASK 0x3FFF /* WSEQ_ADDR41 - [13:0] */
+#define WM8994_WSEQ_ADDR41_SHIFT 0 /* WSEQ_ADDR41 - [13:0] */
+#define WM8994_WSEQ_ADDR41_WIDTH 14 /* WSEQ_ADDR41 - [13:0] */
+
+/*
+ * R12453 (0x30A5) - Write Sequencer 165
+ */
+#define WM8994_WSEQ_DATA41_MASK 0x00FF /* WSEQ_DATA41 - [7:0] */
+#define WM8994_WSEQ_DATA41_SHIFT 0 /* WSEQ_DATA41 - [7:0] */
+#define WM8994_WSEQ_DATA41_WIDTH 8 /* WSEQ_DATA41 - [7:0] */
+
+/*
+ * R12454 (0x30A6) - Write Sequencer 166
+ */
+#define WM8994_WSEQ_DATA_WIDTH41_MASK 0x0700 /* WSEQ_DATA_WIDTH41 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH41_SHIFT 8 /* WSEQ_DATA_WIDTH41 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH41_WIDTH 3 /* WSEQ_DATA_WIDTH41 - [10:8] */
+#define WM8994_WSEQ_DATA_START41_MASK 0x000F /* WSEQ_DATA_START41 - [3:0] */
+#define WM8994_WSEQ_DATA_START41_SHIFT 0 /* WSEQ_DATA_START41 - [3:0] */
+#define WM8994_WSEQ_DATA_START41_WIDTH 4 /* WSEQ_DATA_START41 - [3:0] */
+
+/*
+ * R12455 (0x30A7) - Write Sequencer 167
+ */
+#define WM8994_WSEQ_EOS41 0x0100 /* WSEQ_EOS41 */
+#define WM8994_WSEQ_EOS41_MASK 0x0100 /* WSEQ_EOS41 */
+#define WM8994_WSEQ_EOS41_SHIFT 8 /* WSEQ_EOS41 */
+#define WM8994_WSEQ_EOS41_WIDTH 1 /* WSEQ_EOS41 */
+#define WM8994_WSEQ_DELAY41_MASK 0x000F /* WSEQ_DELAY41 - [3:0] */
+#define WM8994_WSEQ_DELAY41_SHIFT 0 /* WSEQ_DELAY41 - [3:0] */
+#define WM8994_WSEQ_DELAY41_WIDTH 4 /* WSEQ_DELAY41 - [3:0] */
+
+/*
+ * R12456 (0x30A8) - Write Sequencer 168
+ */
+#define WM8994_WSEQ_ADDR42_MASK 0x3FFF /* WSEQ_ADDR42 - [13:0] */
+#define WM8994_WSEQ_ADDR42_SHIFT 0 /* WSEQ_ADDR42 - [13:0] */
+#define WM8994_WSEQ_ADDR42_WIDTH 14 /* WSEQ_ADDR42 - [13:0] */
+
+/*
+ * R12457 (0x30A9) - Write Sequencer 169
+ */
+#define WM8994_WSEQ_DATA42_MASK 0x00FF /* WSEQ_DATA42 - [7:0] */
+#define WM8994_WSEQ_DATA42_SHIFT 0 /* WSEQ_DATA42 - [7:0] */
+#define WM8994_WSEQ_DATA42_WIDTH 8 /* WSEQ_DATA42 - [7:0] */
+
+/*
+ * R12458 (0x30AA) - Write Sequencer 170
+ */
+#define WM8994_WSEQ_DATA_WIDTH42_MASK 0x0700 /* WSEQ_DATA_WIDTH42 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH42_SHIFT 8 /* WSEQ_DATA_WIDTH42 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH42_WIDTH 3 /* WSEQ_DATA_WIDTH42 - [10:8] */
+#define WM8994_WSEQ_DATA_START42_MASK 0x000F /* WSEQ_DATA_START42 - [3:0] */
+#define WM8994_WSEQ_DATA_START42_SHIFT 0 /* WSEQ_DATA_START42 - [3:0] */
+#define WM8994_WSEQ_DATA_START42_WIDTH 4 /* WSEQ_DATA_START42 - [3:0] */
+
+/*
+ * R12459 (0x30AB) - Write Sequencer 171
+ */
+#define WM8994_WSEQ_EOS42 0x0100 /* WSEQ_EOS42 */
+#define WM8994_WSEQ_EOS42_MASK 0x0100 /* WSEQ_EOS42 */
+#define WM8994_WSEQ_EOS42_SHIFT 8 /* WSEQ_EOS42 */
+#define WM8994_WSEQ_EOS42_WIDTH 1 /* WSEQ_EOS42 */
+#define WM8994_WSEQ_DELAY42_MASK 0x000F /* WSEQ_DELAY42 - [3:0] */
+#define WM8994_WSEQ_DELAY42_SHIFT 0 /* WSEQ_DELAY42 - [3:0] */
+#define WM8994_WSEQ_DELAY42_WIDTH 4 /* WSEQ_DELAY42 - [3:0] */
+
+/*
+ * R12460 (0x30AC) - Write Sequencer 172
+ */
+#define WM8994_WSEQ_ADDR43_MASK 0x3FFF /* WSEQ_ADDR43 - [13:0] */
+#define WM8994_WSEQ_ADDR43_SHIFT 0 /* WSEQ_ADDR43 - [13:0] */
+#define WM8994_WSEQ_ADDR43_WIDTH 14 /* WSEQ_ADDR43 - [13:0] */
+
+/*
+ * R12461 (0x30AD) - Write Sequencer 173
+ */
+#define WM8994_WSEQ_DATA43_MASK 0x00FF /* WSEQ_DATA43 - [7:0] */
+#define WM8994_WSEQ_DATA43_SHIFT 0 /* WSEQ_DATA43 - [7:0] */
+#define WM8994_WSEQ_DATA43_WIDTH 8 /* WSEQ_DATA43 - [7:0] */
+
+/*
+ * R12462 (0x30AE) - Write Sequencer 174
+ */
+#define WM8994_WSEQ_DATA_WIDTH43_MASK 0x0700 /* WSEQ_DATA_WIDTH43 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH43_SHIFT 8 /* WSEQ_DATA_WIDTH43 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH43_WIDTH 3 /* WSEQ_DATA_WIDTH43 - [10:8] */
+#define WM8994_WSEQ_DATA_START43_MASK 0x000F /* WSEQ_DATA_START43 - [3:0] */
+#define WM8994_WSEQ_DATA_START43_SHIFT 0 /* WSEQ_DATA_START43 - [3:0] */
+#define WM8994_WSEQ_DATA_START43_WIDTH 4 /* WSEQ_DATA_START43 - [3:0] */
+
+/*
+ * R12463 (0x30AF) - Write Sequencer 175
+ */
+#define WM8994_WSEQ_EOS43 0x0100 /* WSEQ_EOS43 */
+#define WM8994_WSEQ_EOS43_MASK 0x0100 /* WSEQ_EOS43 */
+#define WM8994_WSEQ_EOS43_SHIFT 8 /* WSEQ_EOS43 */
+#define WM8994_WSEQ_EOS43_WIDTH 1 /* WSEQ_EOS43 */
+#define WM8994_WSEQ_DELAY43_MASK 0x000F /* WSEQ_DELAY43 - [3:0] */
+#define WM8994_WSEQ_DELAY43_SHIFT 0 /* WSEQ_DELAY43 - [3:0] */
+#define WM8994_WSEQ_DELAY43_WIDTH 4 /* WSEQ_DELAY43 - [3:0] */
+
+/*
+ * R12464 (0x30B0) - Write Sequencer 176
+ */
+#define WM8994_WSEQ_ADDR44_MASK 0x3FFF /* WSEQ_ADDR44 - [13:0] */
+#define WM8994_WSEQ_ADDR44_SHIFT 0 /* WSEQ_ADDR44 - [13:0] */
+#define WM8994_WSEQ_ADDR44_WIDTH 14 /* WSEQ_ADDR44 - [13:0] */
+
+/*
+ * R12465 (0x30B1) - Write Sequencer 177
+ */
+#define WM8994_WSEQ_DATA44_MASK 0x00FF /* WSEQ_DATA44 - [7:0] */
+#define WM8994_WSEQ_DATA44_SHIFT 0 /* WSEQ_DATA44 - [7:0] */
+#define WM8994_WSEQ_DATA44_WIDTH 8 /* WSEQ_DATA44 - [7:0] */
+
+/*
+ * R12466 (0x30B2) - Write Sequencer 178
+ */
+#define WM8994_WSEQ_DATA_WIDTH44_MASK 0x0700 /* WSEQ_DATA_WIDTH44 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH44_SHIFT 8 /* WSEQ_DATA_WIDTH44 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH44_WIDTH 3 /* WSEQ_DATA_WIDTH44 - [10:8] */
+#define WM8994_WSEQ_DATA_START44_MASK 0x000F /* WSEQ_DATA_START44 - [3:0] */
+#define WM8994_WSEQ_DATA_START44_SHIFT 0 /* WSEQ_DATA_START44 - [3:0] */
+#define WM8994_WSEQ_DATA_START44_WIDTH 4 /* WSEQ_DATA_START44 - [3:0] */
+
+/*
+ * R12467 (0x30B3) - Write Sequencer 179
+ */
+#define WM8994_WSEQ_EOS44 0x0100 /* WSEQ_EOS44 */
+#define WM8994_WSEQ_EOS44_MASK 0x0100 /* WSEQ_EOS44 */
+#define WM8994_WSEQ_EOS44_SHIFT 8 /* WSEQ_EOS44 */
+#define WM8994_WSEQ_EOS44_WIDTH 1 /* WSEQ_EOS44 */
+#define WM8994_WSEQ_DELAY44_MASK 0x000F /* WSEQ_DELAY44 - [3:0] */
+#define WM8994_WSEQ_DELAY44_SHIFT 0 /* WSEQ_DELAY44 - [3:0] */
+#define WM8994_WSEQ_DELAY44_WIDTH 4 /* WSEQ_DELAY44 - [3:0] */
+
+/*
+ * R12468 (0x30B4) - Write Sequencer 180
+ */
+#define WM8994_WSEQ_ADDR45_MASK 0x3FFF /* WSEQ_ADDR45 - [13:0] */
+#define WM8994_WSEQ_ADDR45_SHIFT 0 /* WSEQ_ADDR45 - [13:0] */
+#define WM8994_WSEQ_ADDR45_WIDTH 14 /* WSEQ_ADDR45 - [13:0] */
+
+/*
+ * R12469 (0x30B5) - Write Sequencer 181
+ */
+#define WM8994_WSEQ_DATA45_MASK 0x00FF /* WSEQ_DATA45 - [7:0] */
+#define WM8994_WSEQ_DATA45_SHIFT 0 /* WSEQ_DATA45 - [7:0] */
+#define WM8994_WSEQ_DATA45_WIDTH 8 /* WSEQ_DATA45 - [7:0] */
+
+/*
+ * R12470 (0x30B6) - Write Sequencer 182
+ */
+#define WM8994_WSEQ_DATA_WIDTH45_MASK 0x0700 /* WSEQ_DATA_WIDTH45 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH45_SHIFT 8 /* WSEQ_DATA_WIDTH45 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH45_WIDTH 3 /* WSEQ_DATA_WIDTH45 - [10:8] */
+#define WM8994_WSEQ_DATA_START45_MASK 0x000F /* WSEQ_DATA_START45 - [3:0] */
+#define WM8994_WSEQ_DATA_START45_SHIFT 0 /* WSEQ_DATA_START45 - [3:0] */
+#define WM8994_WSEQ_DATA_START45_WIDTH 4 /* WSEQ_DATA_START45 - [3:0] */
+
+/*
+ * R12471 (0x30B7) - Write Sequencer 183
+ */
+#define WM8994_WSEQ_EOS45 0x0100 /* WSEQ_EOS45 */
+#define WM8994_WSEQ_EOS45_MASK 0x0100 /* WSEQ_EOS45 */
+#define WM8994_WSEQ_EOS45_SHIFT 8 /* WSEQ_EOS45 */
+#define WM8994_WSEQ_EOS45_WIDTH 1 /* WSEQ_EOS45 */
+#define WM8994_WSEQ_DELAY45_MASK 0x000F /* WSEQ_DELAY45 - [3:0] */
+#define WM8994_WSEQ_DELAY45_SHIFT 0 /* WSEQ_DELAY45 - [3:0] */
+#define WM8994_WSEQ_DELAY45_WIDTH 4 /* WSEQ_DELAY45 - [3:0] */
+
+/*
+ * R12472 (0x30B8) - Write Sequencer 184
+ */
+#define WM8994_WSEQ_ADDR46_MASK 0x3FFF /* WSEQ_ADDR46 - [13:0] */
+#define WM8994_WSEQ_ADDR46_SHIFT 0 /* WSEQ_ADDR46 - [13:0] */
+#define WM8994_WSEQ_ADDR46_WIDTH 14 /* WSEQ_ADDR46 - [13:0] */
+
+/*
+ * R12473 (0x30B9) - Write Sequencer 185
+ */
+#define WM8994_WSEQ_DATA46_MASK 0x00FF /* WSEQ_DATA46 - [7:0] */
+#define WM8994_WSEQ_DATA46_SHIFT 0 /* WSEQ_DATA46 - [7:0] */
+#define WM8994_WSEQ_DATA46_WIDTH 8 /* WSEQ_DATA46 - [7:0] */
+
+/*
+ * R12474 (0x30BA) - Write Sequencer 186
+ */
+#define WM8994_WSEQ_DATA_WIDTH46_MASK 0x0700 /* WSEQ_DATA_WIDTH46 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH46_SHIFT 8 /* WSEQ_DATA_WIDTH46 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH46_WIDTH 3 /* WSEQ_DATA_WIDTH46 - [10:8] */
+#define WM8994_WSEQ_DATA_START46_MASK 0x000F /* WSEQ_DATA_START46 - [3:0] */
+#define WM8994_WSEQ_DATA_START46_SHIFT 0 /* WSEQ_DATA_START46 - [3:0] */
+#define WM8994_WSEQ_DATA_START46_WIDTH 4 /* WSEQ_DATA_START46 - [3:0] */
+
+/*
+ * R12475 (0x30BB) - Write Sequencer 187
+ */
+#define WM8994_WSEQ_EOS46 0x0100 /* WSEQ_EOS46 */
+#define WM8994_WSEQ_EOS46_MASK 0x0100 /* WSEQ_EOS46 */
+#define WM8994_WSEQ_EOS46_SHIFT 8 /* WSEQ_EOS46 */
+#define WM8994_WSEQ_EOS46_WIDTH 1 /* WSEQ_EOS46 */
+#define WM8994_WSEQ_DELAY46_MASK 0x000F /* WSEQ_DELAY46 - [3:0] */
+#define WM8994_WSEQ_DELAY46_SHIFT 0 /* WSEQ_DELAY46 - [3:0] */
+#define WM8994_WSEQ_DELAY46_WIDTH 4 /* WSEQ_DELAY46 - [3:0] */
+
+/*
+ * R12476 (0x30BC) - Write Sequencer 188
+ */
+#define WM8994_WSEQ_ADDR47_MASK 0x3FFF /* WSEQ_ADDR47 - [13:0] */
+#define WM8994_WSEQ_ADDR47_SHIFT 0 /* WSEQ_ADDR47 - [13:0] */
+#define WM8994_WSEQ_ADDR47_WIDTH 14 /* WSEQ_ADDR47 - [13:0] */
+
+/*
+ * R12477 (0x30BD) - Write Sequencer 189
+ */
+#define WM8994_WSEQ_DATA47_MASK 0x00FF /* WSEQ_DATA47 - [7:0] */
+#define WM8994_WSEQ_DATA47_SHIFT 0 /* WSEQ_DATA47 - [7:0] */
+#define WM8994_WSEQ_DATA47_WIDTH 8 /* WSEQ_DATA47 - [7:0] */
+
+/*
+ * R12478 (0x30BE) - Write Sequencer 190
+ */
+#define WM8994_WSEQ_DATA_WIDTH47_MASK 0x0700 /* WSEQ_DATA_WIDTH47 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH47_SHIFT 8 /* WSEQ_DATA_WIDTH47 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH47_WIDTH 3 /* WSEQ_DATA_WIDTH47 - [10:8] */
+#define WM8994_WSEQ_DATA_START47_MASK 0x000F /* WSEQ_DATA_START47 - [3:0] */
+#define WM8994_WSEQ_DATA_START47_SHIFT 0 /* WSEQ_DATA_START47 - [3:0] */
+#define WM8994_WSEQ_DATA_START47_WIDTH 4 /* WSEQ_DATA_START47 - [3:0] */
+
+/*
+ * R12479 (0x30BF) - Write Sequencer 191
+ */
+#define WM8994_WSEQ_EOS47 0x0100 /* WSEQ_EOS47 */
+#define WM8994_WSEQ_EOS47_MASK 0x0100 /* WSEQ_EOS47 */
+#define WM8994_WSEQ_EOS47_SHIFT 8 /* WSEQ_EOS47 */
+#define WM8994_WSEQ_EOS47_WIDTH 1 /* WSEQ_EOS47 */
+#define WM8994_WSEQ_DELAY47_MASK 0x000F /* WSEQ_DELAY47 - [3:0] */
+#define WM8994_WSEQ_DELAY47_SHIFT 0 /* WSEQ_DELAY47 - [3:0] */
+#define WM8994_WSEQ_DELAY47_WIDTH 4 /* WSEQ_DELAY47 - [3:0] */
+
+/*
+ * R12480 (0x30C0) - Write Sequencer 192
+ */
+#define WM8994_WSEQ_ADDR48_MASK 0x3FFF /* WSEQ_ADDR48 - [13:0] */
+#define WM8994_WSEQ_ADDR48_SHIFT 0 /* WSEQ_ADDR48 - [13:0] */
+#define WM8994_WSEQ_ADDR48_WIDTH 14 /* WSEQ_ADDR48 - [13:0] */
+
+/*
+ * R12481 (0x30C1) - Write Sequencer 193
+ */
+#define WM8994_WSEQ_DATA48_MASK 0x00FF /* WSEQ_DATA48 - [7:0] */
+#define WM8994_WSEQ_DATA48_SHIFT 0 /* WSEQ_DATA48 - [7:0] */
+#define WM8994_WSEQ_DATA48_WIDTH 8 /* WSEQ_DATA48 - [7:0] */
+
+/*
+ * R12482 (0x30C2) - Write Sequencer 194
+ */
+#define WM8994_WSEQ_DATA_WIDTH48_MASK 0x0700 /* WSEQ_DATA_WIDTH48 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH48_SHIFT 8 /* WSEQ_DATA_WIDTH48 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH48_WIDTH 3 /* WSEQ_DATA_WIDTH48 - [10:8] */
+#define WM8994_WSEQ_DATA_START48_MASK 0x000F /* WSEQ_DATA_START48 - [3:0] */
+#define WM8994_WSEQ_DATA_START48_SHIFT 0 /* WSEQ_DATA_START48 - [3:0] */
+#define WM8994_WSEQ_DATA_START48_WIDTH 4 /* WSEQ_DATA_START48 - [3:0] */
+
+/*
+ * R12483 (0x30C3) - Write Sequencer 195
+ */
+#define WM8994_WSEQ_EOS48 0x0100 /* WSEQ_EOS48 */
+#define WM8994_WSEQ_EOS48_MASK 0x0100 /* WSEQ_EOS48 */
+#define WM8994_WSEQ_EOS48_SHIFT 8 /* WSEQ_EOS48 */
+#define WM8994_WSEQ_EOS48_WIDTH 1 /* WSEQ_EOS48 */
+#define WM8994_WSEQ_DELAY48_MASK 0x000F /* WSEQ_DELAY48 - [3:0] */
+#define WM8994_WSEQ_DELAY48_SHIFT 0 /* WSEQ_DELAY48 - [3:0] */
+#define WM8994_WSEQ_DELAY48_WIDTH 4 /* WSEQ_DELAY48 - [3:0] */
+
+/*
+ * R12484 (0x30C4) - Write Sequencer 196
+ */
+#define WM8994_WSEQ_ADDR49_MASK 0x3FFF /* WSEQ_ADDR49 - [13:0] */
+#define WM8994_WSEQ_ADDR49_SHIFT 0 /* WSEQ_ADDR49 - [13:0] */
+#define WM8994_WSEQ_ADDR49_WIDTH 14 /* WSEQ_ADDR49 - [13:0] */
+
+/*
+ * R12485 (0x30C5) - Write Sequencer 197
+ */
+#define WM8994_WSEQ_DATA49_MASK 0x00FF /* WSEQ_DATA49 - [7:0] */
+#define WM8994_WSEQ_DATA49_SHIFT 0 /* WSEQ_DATA49 - [7:0] */
+#define WM8994_WSEQ_DATA49_WIDTH 8 /* WSEQ_DATA49 - [7:0] */
+
+/*
+ * R12486 (0x30C6) - Write Sequencer 198
+ */
+#define WM8994_WSEQ_DATA_WIDTH49_MASK 0x0700 /* WSEQ_DATA_WIDTH49 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH49_SHIFT 8 /* WSEQ_DATA_WIDTH49 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH49_WIDTH 3 /* WSEQ_DATA_WIDTH49 - [10:8] */
+#define WM8994_WSEQ_DATA_START49_MASK 0x000F /* WSEQ_DATA_START49 - [3:0] */
+#define WM8994_WSEQ_DATA_START49_SHIFT 0 /* WSEQ_DATA_START49 - [3:0] */
+#define WM8994_WSEQ_DATA_START49_WIDTH 4 /* WSEQ_DATA_START49 - [3:0] */
+
+/*
+ * R12487 (0x30C7) - Write Sequencer 199
+ */
+#define WM8994_WSEQ_EOS49 0x0100 /* WSEQ_EOS49 */
+#define WM8994_WSEQ_EOS49_MASK 0x0100 /* WSEQ_EOS49 */
+#define WM8994_WSEQ_EOS49_SHIFT 8 /* WSEQ_EOS49 */
+#define WM8994_WSEQ_EOS49_WIDTH 1 /* WSEQ_EOS49 */
+#define WM8994_WSEQ_DELAY49_MASK 0x000F /* WSEQ_DELAY49 - [3:0] */
+#define WM8994_WSEQ_DELAY49_SHIFT 0 /* WSEQ_DELAY49 - [3:0] */
+#define WM8994_WSEQ_DELAY49_WIDTH 4 /* WSEQ_DELAY49 - [3:0] */
+
+/*
+ * R12488 (0x30C8) - Write Sequencer 200
+ */
+#define WM8994_WSEQ_ADDR50_MASK 0x3FFF /* WSEQ_ADDR50 - [13:0] */
+#define WM8994_WSEQ_ADDR50_SHIFT 0 /* WSEQ_ADDR50 - [13:0] */
+#define WM8994_WSEQ_ADDR50_WIDTH 14 /* WSEQ_ADDR50 - [13:0] */
+
+/*
+ * R12489 (0x30C9) - Write Sequencer 201
+ */
+#define WM8994_WSEQ_DATA50_MASK 0x00FF /* WSEQ_DATA50 - [7:0] */
+#define WM8994_WSEQ_DATA50_SHIFT 0 /* WSEQ_DATA50 - [7:0] */
+#define WM8994_WSEQ_DATA50_WIDTH 8 /* WSEQ_DATA50 - [7:0] */
+
+/*
+ * R12490 (0x30CA) - Write Sequencer 202
+ */
+#define WM8994_WSEQ_DATA_WIDTH50_MASK 0x0700 /* WSEQ_DATA_WIDTH50 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH50_SHIFT 8 /* WSEQ_DATA_WIDTH50 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH50_WIDTH 3 /* WSEQ_DATA_WIDTH50 - [10:8] */
+#define WM8994_WSEQ_DATA_START50_MASK 0x000F /* WSEQ_DATA_START50 - [3:0] */
+#define WM8994_WSEQ_DATA_START50_SHIFT 0 /* WSEQ_DATA_START50 - [3:0] */
+#define WM8994_WSEQ_DATA_START50_WIDTH 4 /* WSEQ_DATA_START50 - [3:0] */
+
+/*
+ * R12491 (0x30CB) - Write Sequencer 203
+ */
+#define WM8994_WSEQ_EOS50 0x0100 /* WSEQ_EOS50 */
+#define WM8994_WSEQ_EOS50_MASK 0x0100 /* WSEQ_EOS50 */
+#define WM8994_WSEQ_EOS50_SHIFT 8 /* WSEQ_EOS50 */
+#define WM8994_WSEQ_EOS50_WIDTH 1 /* WSEQ_EOS50 */
+#define WM8994_WSEQ_DELAY50_MASK 0x000F /* WSEQ_DELAY50 - [3:0] */
+#define WM8994_WSEQ_DELAY50_SHIFT 0 /* WSEQ_DELAY50 - [3:0] */
+#define WM8994_WSEQ_DELAY50_WIDTH 4 /* WSEQ_DELAY50 - [3:0] */
+
+/*
+ * R12492 (0x30CC) - Write Sequencer 204
+ */
+#define WM8994_WSEQ_ADDR51_MASK 0x3FFF /* WSEQ_ADDR51 - [13:0] */
+#define WM8994_WSEQ_ADDR51_SHIFT 0 /* WSEQ_ADDR51 - [13:0] */
+#define WM8994_WSEQ_ADDR51_WIDTH 14 /* WSEQ_ADDR51 - [13:0] */
+
+/*
+ * R12493 (0x30CD) - Write Sequencer 205
+ */
+#define WM8994_WSEQ_DATA51_MASK 0x00FF /* WSEQ_DATA51 - [7:0] */
+#define WM8994_WSEQ_DATA51_SHIFT 0 /* WSEQ_DATA51 - [7:0] */
+#define WM8994_WSEQ_DATA51_WIDTH 8 /* WSEQ_DATA51 - [7:0] */
+
+/*
+ * R12494 (0x30CE) - Write Sequencer 206
+ */
+#define WM8994_WSEQ_DATA_WIDTH51_MASK 0x0700 /* WSEQ_DATA_WIDTH51 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH51_SHIFT 8 /* WSEQ_DATA_WIDTH51 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH51_WIDTH 3 /* WSEQ_DATA_WIDTH51 - [10:8] */
+#define WM8994_WSEQ_DATA_START51_MASK 0x000F /* WSEQ_DATA_START51 - [3:0] */
+#define WM8994_WSEQ_DATA_START51_SHIFT 0 /* WSEQ_DATA_START51 - [3:0] */
+#define WM8994_WSEQ_DATA_START51_WIDTH 4 /* WSEQ_DATA_START51 - [3:0] */
+
+/*
+ * R12495 (0x30CF) - Write Sequencer 207
+ */
+#define WM8994_WSEQ_EOS51 0x0100 /* WSEQ_EOS51 */
+#define WM8994_WSEQ_EOS51_MASK 0x0100 /* WSEQ_EOS51 */
+#define WM8994_WSEQ_EOS51_SHIFT 8 /* WSEQ_EOS51 */
+#define WM8994_WSEQ_EOS51_WIDTH 1 /* WSEQ_EOS51 */
+#define WM8994_WSEQ_DELAY51_MASK 0x000F /* WSEQ_DELAY51 - [3:0] */
+#define WM8994_WSEQ_DELAY51_SHIFT 0 /* WSEQ_DELAY51 - [3:0] */
+#define WM8994_WSEQ_DELAY51_WIDTH 4 /* WSEQ_DELAY51 - [3:0] */
+
+/*
+ * R12496 (0x30D0) - Write Sequencer 208
+ */
+#define WM8994_WSEQ_ADDR52_MASK 0x3FFF /* WSEQ_ADDR52 - [13:0] */
+#define WM8994_WSEQ_ADDR52_SHIFT 0 /* WSEQ_ADDR52 - [13:0] */
+#define WM8994_WSEQ_ADDR52_WIDTH 14 /* WSEQ_ADDR52 - [13:0] */
+
+/*
+ * R12497 (0x30D1) - Write Sequencer 209
+ */
+#define WM8994_WSEQ_DATA52_MASK 0x00FF /* WSEQ_DATA52 - [7:0] */
+#define WM8994_WSEQ_DATA52_SHIFT 0 /* WSEQ_DATA52 - [7:0] */
+#define WM8994_WSEQ_DATA52_WIDTH 8 /* WSEQ_DATA52 - [7:0] */
+
+/*
+ * R12498 (0x30D2) - Write Sequencer 210
+ */
+#define WM8994_WSEQ_DATA_WIDTH52_MASK 0x0700 /* WSEQ_DATA_WIDTH52 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH52_SHIFT 8 /* WSEQ_DATA_WIDTH52 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH52_WIDTH 3 /* WSEQ_DATA_WIDTH52 - [10:8] */
+#define WM8994_WSEQ_DATA_START52_MASK 0x000F /* WSEQ_DATA_START52 - [3:0] */
+#define WM8994_WSEQ_DATA_START52_SHIFT 0 /* WSEQ_DATA_START52 - [3:0] */
+#define WM8994_WSEQ_DATA_START52_WIDTH 4 /* WSEQ_DATA_START52 - [3:0] */
+
+/*
+ * R12499 (0x30D3) - Write Sequencer 211
+ */
+#define WM8994_WSEQ_EOS52 0x0100 /* WSEQ_EOS52 */
+#define WM8994_WSEQ_EOS52_MASK 0x0100 /* WSEQ_EOS52 */
+#define WM8994_WSEQ_EOS52_SHIFT 8 /* WSEQ_EOS52 */
+#define WM8994_WSEQ_EOS52_WIDTH 1 /* WSEQ_EOS52 */
+#define WM8994_WSEQ_DELAY52_MASK 0x000F /* WSEQ_DELAY52 - [3:0] */
+#define WM8994_WSEQ_DELAY52_SHIFT 0 /* WSEQ_DELAY52 - [3:0] */
+#define WM8994_WSEQ_DELAY52_WIDTH 4 /* WSEQ_DELAY52 - [3:0] */
+
+/*
+ * R12500 (0x30D4) - Write Sequencer 212
+ */
+#define WM8994_WSEQ_ADDR53_MASK 0x3FFF /* WSEQ_ADDR53 - [13:0] */
+#define WM8994_WSEQ_ADDR53_SHIFT 0 /* WSEQ_ADDR53 - [13:0] */
+#define WM8994_WSEQ_ADDR53_WIDTH 14 /* WSEQ_ADDR53 - [13:0] */
+
+/*
+ * R12501 (0x30D5) - Write Sequencer 213
+ */
+#define WM8994_WSEQ_DATA53_MASK 0x00FF /* WSEQ_DATA53 - [7:0] */
+#define WM8994_WSEQ_DATA53_SHIFT 0 /* WSEQ_DATA53 - [7:0] */
+#define WM8994_WSEQ_DATA53_WIDTH 8 /* WSEQ_DATA53 - [7:0] */
+
+/*
+ * R12502 (0x30D6) - Write Sequencer 214
+ */
+#define WM8994_WSEQ_DATA_WIDTH53_MASK 0x0700 /* WSEQ_DATA_WIDTH53 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH53_SHIFT 8 /* WSEQ_DATA_WIDTH53 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH53_WIDTH 3 /* WSEQ_DATA_WIDTH53 - [10:8] */
+#define WM8994_WSEQ_DATA_START53_MASK 0x000F /* WSEQ_DATA_START53 - [3:0] */
+#define WM8994_WSEQ_DATA_START53_SHIFT 0 /* WSEQ_DATA_START53 - [3:0] */
+#define WM8994_WSEQ_DATA_START53_WIDTH 4 /* WSEQ_DATA_START53 - [3:0] */
+
+/*
+ * R12503 (0x30D7) - Write Sequencer 215
+ */
+#define WM8994_WSEQ_EOS53 0x0100 /* WSEQ_EOS53 */
+#define WM8994_WSEQ_EOS53_MASK 0x0100 /* WSEQ_EOS53 */
+#define WM8994_WSEQ_EOS53_SHIFT 8 /* WSEQ_EOS53 */
+#define WM8994_WSEQ_EOS53_WIDTH 1 /* WSEQ_EOS53 */
+#define WM8994_WSEQ_DELAY53_MASK 0x000F /* WSEQ_DELAY53 - [3:0] */
+#define WM8994_WSEQ_DELAY53_SHIFT 0 /* WSEQ_DELAY53 - [3:0] */
+#define WM8994_WSEQ_DELAY53_WIDTH 4 /* WSEQ_DELAY53 - [3:0] */
+
+/*
+ * R12504 (0x30D8) - Write Sequencer 216
+ */
+#define WM8994_WSEQ_ADDR54_MASK 0x3FFF /* WSEQ_ADDR54 - [13:0] */
+#define WM8994_WSEQ_ADDR54_SHIFT 0 /* WSEQ_ADDR54 - [13:0] */
+#define WM8994_WSEQ_ADDR54_WIDTH 14 /* WSEQ_ADDR54 - [13:0] */
+
+/*
+ * R12505 (0x30D9) - Write Sequencer 217
+ */
+#define WM8994_WSEQ_DATA54_MASK 0x00FF /* WSEQ_DATA54 - [7:0] */
+#define WM8994_WSEQ_DATA54_SHIFT 0 /* WSEQ_DATA54 - [7:0] */
+#define WM8994_WSEQ_DATA54_WIDTH 8 /* WSEQ_DATA54 - [7:0] */
+
+/*
+ * R12506 (0x30DA) - Write Sequencer 218
+ */
+#define WM8994_WSEQ_DATA_WIDTH54_MASK 0x0700 /* WSEQ_DATA_WIDTH54 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH54_SHIFT 8 /* WSEQ_DATA_WIDTH54 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH54_WIDTH 3 /* WSEQ_DATA_WIDTH54 - [10:8] */
+#define WM8994_WSEQ_DATA_START54_MASK 0x000F /* WSEQ_DATA_START54 - [3:0] */
+#define WM8994_WSEQ_DATA_START54_SHIFT 0 /* WSEQ_DATA_START54 - [3:0] */
+#define WM8994_WSEQ_DATA_START54_WIDTH 4 /* WSEQ_DATA_START54 - [3:0] */
+
+/*
+ * R12507 (0x30DB) - Write Sequencer 219
+ */
+#define WM8994_WSEQ_EOS54 0x0100 /* WSEQ_EOS54 */
+#define WM8994_WSEQ_EOS54_MASK 0x0100 /* WSEQ_EOS54 */
+#define WM8994_WSEQ_EOS54_SHIFT 8 /* WSEQ_EOS54 */
+#define WM8994_WSEQ_EOS54_WIDTH 1 /* WSEQ_EOS54 */
+#define WM8994_WSEQ_DELAY54_MASK 0x000F /* WSEQ_DELAY54 - [3:0] */
+#define WM8994_WSEQ_DELAY54_SHIFT 0 /* WSEQ_DELAY54 - [3:0] */
+#define WM8994_WSEQ_DELAY54_WIDTH 4 /* WSEQ_DELAY54 - [3:0] */
+
+/*
+ * R12508 (0x30DC) - Write Sequencer 220
+ */
+#define WM8994_WSEQ_ADDR55_MASK 0x3FFF /* WSEQ_ADDR55 - [13:0] */
+#define WM8994_WSEQ_ADDR55_SHIFT 0 /* WSEQ_ADDR55 - [13:0] */
+#define WM8994_WSEQ_ADDR55_WIDTH 14 /* WSEQ_ADDR55 - [13:0] */
+
+/*
+ * R12509 (0x30DD) - Write Sequencer 221
+ */
+#define WM8994_WSEQ_DATA55_MASK 0x00FF /* WSEQ_DATA55 - [7:0] */
+#define WM8994_WSEQ_DATA55_SHIFT 0 /* WSEQ_DATA55 - [7:0] */
+#define WM8994_WSEQ_DATA55_WIDTH 8 /* WSEQ_DATA55 - [7:0] */
+
+/*
+ * R12510 (0x30DE) - Write Sequencer 222
+ */
+#define WM8994_WSEQ_DATA_WIDTH55_MASK 0x0700 /* WSEQ_DATA_WIDTH55 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH55_SHIFT 8 /* WSEQ_DATA_WIDTH55 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH55_WIDTH 3 /* WSEQ_DATA_WIDTH55 - [10:8] */
+#define WM8994_WSEQ_DATA_START55_MASK 0x000F /* WSEQ_DATA_START55 - [3:0] */
+#define WM8994_WSEQ_DATA_START55_SHIFT 0 /* WSEQ_DATA_START55 - [3:0] */
+#define WM8994_WSEQ_DATA_START55_WIDTH 4 /* WSEQ_DATA_START55 - [3:0] */
+
+/*
+ * R12511 (0x30DF) - Write Sequencer 223
+ */
+#define WM8994_WSEQ_EOS55 0x0100 /* WSEQ_EOS55 */
+#define WM8994_WSEQ_EOS55_MASK 0x0100 /* WSEQ_EOS55 */
+#define WM8994_WSEQ_EOS55_SHIFT 8 /* WSEQ_EOS55 */
+#define WM8994_WSEQ_EOS55_WIDTH 1 /* WSEQ_EOS55 */
+#define WM8994_WSEQ_DELAY55_MASK 0x000F /* WSEQ_DELAY55 - [3:0] */
+#define WM8994_WSEQ_DELAY55_SHIFT 0 /* WSEQ_DELAY55 - [3:0] */
+#define WM8994_WSEQ_DELAY55_WIDTH 4 /* WSEQ_DELAY55 - [3:0] */
+
+/*
+ * R12512 (0x30E0) - Write Sequencer 224
+ */
+#define WM8994_WSEQ_ADDR56_MASK 0x3FFF /* WSEQ_ADDR56 - [13:0] */
+#define WM8994_WSEQ_ADDR56_SHIFT 0 /* WSEQ_ADDR56 - [13:0] */
+#define WM8994_WSEQ_ADDR56_WIDTH 14 /* WSEQ_ADDR56 - [13:0] */
+
+/*
+ * R12513 (0x30E1) - Write Sequencer 225
+ */
+#define WM8994_WSEQ_DATA56_MASK 0x00FF /* WSEQ_DATA56 - [7:0] */
+#define WM8994_WSEQ_DATA56_SHIFT 0 /* WSEQ_DATA56 - [7:0] */
+#define WM8994_WSEQ_DATA56_WIDTH 8 /* WSEQ_DATA56 - [7:0] */
+
+/*
+ * R12514 (0x30E2) - Write Sequencer 226
+ */
+#define WM8994_WSEQ_DATA_WIDTH56_MASK 0x0700 /* WSEQ_DATA_WIDTH56 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH56_SHIFT 8 /* WSEQ_DATA_WIDTH56 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH56_WIDTH 3 /* WSEQ_DATA_WIDTH56 - [10:8] */
+#define WM8994_WSEQ_DATA_START56_MASK 0x000F /* WSEQ_DATA_START56 - [3:0] */
+#define WM8994_WSEQ_DATA_START56_SHIFT 0 /* WSEQ_DATA_START56 - [3:0] */
+#define WM8994_WSEQ_DATA_START56_WIDTH 4 /* WSEQ_DATA_START56 - [3:0] */
+
+/*
+ * R12515 (0x30E3) - Write Sequencer 227
+ */
+#define WM8994_WSEQ_EOS56 0x0100 /* WSEQ_EOS56 */
+#define WM8994_WSEQ_EOS56_MASK 0x0100 /* WSEQ_EOS56 */
+#define WM8994_WSEQ_EOS56_SHIFT 8 /* WSEQ_EOS56 */
+#define WM8994_WSEQ_EOS56_WIDTH 1 /* WSEQ_EOS56 */
+#define WM8994_WSEQ_DELAY56_MASK 0x000F /* WSEQ_DELAY56 - [3:0] */
+#define WM8994_WSEQ_DELAY56_SHIFT 0 /* WSEQ_DELAY56 - [3:0] */
+#define WM8994_WSEQ_DELAY56_WIDTH 4 /* WSEQ_DELAY56 - [3:0] */
+
+/*
+ * R12516 (0x30E4) - Write Sequencer 228
+ */
+#define WM8994_WSEQ_ADDR57_MASK 0x3FFF /* WSEQ_ADDR57 - [13:0] */
+#define WM8994_WSEQ_ADDR57_SHIFT 0 /* WSEQ_ADDR57 - [13:0] */
+#define WM8994_WSEQ_ADDR57_WIDTH 14 /* WSEQ_ADDR57 - [13:0] */
+
+/*
+ * R12517 (0x30E5) - Write Sequencer 229
+ */
+#define WM8994_WSEQ_DATA57_MASK 0x00FF /* WSEQ_DATA57 - [7:0] */
+#define WM8994_WSEQ_DATA57_SHIFT 0 /* WSEQ_DATA57 - [7:0] */
+#define WM8994_WSEQ_DATA57_WIDTH 8 /* WSEQ_DATA57 - [7:0] */
+
+/*
+ * R12518 (0x30E6) - Write Sequencer 230
+ */
+#define WM8994_WSEQ_DATA_WIDTH57_MASK 0x0700 /* WSEQ_DATA_WIDTH57 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH57_SHIFT 8 /* WSEQ_DATA_WIDTH57 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH57_WIDTH 3 /* WSEQ_DATA_WIDTH57 - [10:8] */
+#define WM8994_WSEQ_DATA_START57_MASK 0x000F /* WSEQ_DATA_START57 - [3:0] */
+#define WM8994_WSEQ_DATA_START57_SHIFT 0 /* WSEQ_DATA_START57 - [3:0] */
+#define WM8994_WSEQ_DATA_START57_WIDTH 4 /* WSEQ_DATA_START57 - [3:0] */
+
+/*
+ * R12519 (0x30E7) - Write Sequencer 231
+ */
+#define WM8994_WSEQ_EOS57 0x0100 /* WSEQ_EOS57 */
+#define WM8994_WSEQ_EOS57_MASK 0x0100 /* WSEQ_EOS57 */
+#define WM8994_WSEQ_EOS57_SHIFT 8 /* WSEQ_EOS57 */
+#define WM8994_WSEQ_EOS57_WIDTH 1 /* WSEQ_EOS57 */
+#define WM8994_WSEQ_DELAY57_MASK 0x000F /* WSEQ_DELAY57 - [3:0] */
+#define WM8994_WSEQ_DELAY57_SHIFT 0 /* WSEQ_DELAY57 - [3:0] */
+#define WM8994_WSEQ_DELAY57_WIDTH 4 /* WSEQ_DELAY57 - [3:0] */
+
+/*
+ * R12520 (0x30E8) - Write Sequencer 232
+ */
+#define WM8994_WSEQ_ADDR58_MASK 0x3FFF /* WSEQ_ADDR58 - [13:0] */
+#define WM8994_WSEQ_ADDR58_SHIFT 0 /* WSEQ_ADDR58 - [13:0] */
+#define WM8994_WSEQ_ADDR58_WIDTH 14 /* WSEQ_ADDR58 - [13:0] */
+
+/*
+ * R12521 (0x30E9) - Write Sequencer 233
+ */
+#define WM8994_WSEQ_DATA58_MASK 0x00FF /* WSEQ_DATA58 - [7:0] */
+#define WM8994_WSEQ_DATA58_SHIFT 0 /* WSEQ_DATA58 - [7:0] */
+#define WM8994_WSEQ_DATA58_WIDTH 8 /* WSEQ_DATA58 - [7:0] */
+
+/*
+ * R12522 (0x30EA) - Write Sequencer 234
+ */
+#define WM8994_WSEQ_DATA_WIDTH58_MASK 0x0700 /* WSEQ_DATA_WIDTH58 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH58_SHIFT 8 /* WSEQ_DATA_WIDTH58 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH58_WIDTH 3 /* WSEQ_DATA_WIDTH58 - [10:8] */
+#define WM8994_WSEQ_DATA_START58_MASK 0x000F /* WSEQ_DATA_START58 - [3:0] */
+#define WM8994_WSEQ_DATA_START58_SHIFT 0 /* WSEQ_DATA_START58 - [3:0] */
+#define WM8994_WSEQ_DATA_START58_WIDTH 4 /* WSEQ_DATA_START58 - [3:0] */
+
+/*
+ * R12523 (0x30EB) - Write Sequencer 235
+ */
+#define WM8994_WSEQ_EOS58 0x0100 /* WSEQ_EOS58 */
+#define WM8994_WSEQ_EOS58_MASK 0x0100 /* WSEQ_EOS58 */
+#define WM8994_WSEQ_EOS58_SHIFT 8 /* WSEQ_EOS58 */
+#define WM8994_WSEQ_EOS58_WIDTH 1 /* WSEQ_EOS58 */
+#define WM8994_WSEQ_DELAY58_MASK 0x000F /* WSEQ_DELAY58 - [3:0] */
+#define WM8994_WSEQ_DELAY58_SHIFT 0 /* WSEQ_DELAY58 - [3:0] */
+#define WM8994_WSEQ_DELAY58_WIDTH 4 /* WSEQ_DELAY58 - [3:0] */
+
+/*
+ * R12524 (0x30EC) - Write Sequencer 236
+ */
+#define WM8994_WSEQ_ADDR59_MASK 0x3FFF /* WSEQ_ADDR59 - [13:0] */
+#define WM8994_WSEQ_ADDR59_SHIFT 0 /* WSEQ_ADDR59 - [13:0] */
+#define WM8994_WSEQ_ADDR59_WIDTH 14 /* WSEQ_ADDR59 - [13:0] */
+
+/*
+ * R12525 (0x30ED) - Write Sequencer 237
+ */
+#define WM8994_WSEQ_DATA59_MASK 0x00FF /* WSEQ_DATA59 - [7:0] */
+#define WM8994_WSEQ_DATA59_SHIFT 0 /* WSEQ_DATA59 - [7:0] */
+#define WM8994_WSEQ_DATA59_WIDTH 8 /* WSEQ_DATA59 - [7:0] */
+
+/*
+ * R12526 (0x30EE) - Write Sequencer 238
+ */
+#define WM8994_WSEQ_DATA_WIDTH59_MASK 0x0700 /* WSEQ_DATA_WIDTH59 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH59_SHIFT 8 /* WSEQ_DATA_WIDTH59 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH59_WIDTH 3 /* WSEQ_DATA_WIDTH59 - [10:8] */
+#define WM8994_WSEQ_DATA_START59_MASK 0x000F /* WSEQ_DATA_START59 - [3:0] */
+#define WM8994_WSEQ_DATA_START59_SHIFT 0 /* WSEQ_DATA_START59 - [3:0] */
+#define WM8994_WSEQ_DATA_START59_WIDTH 4 /* WSEQ_DATA_START59 - [3:0] */
+
+/*
+ * R12527 (0x30EF) - Write Sequencer 239
+ */
+#define WM8994_WSEQ_EOS59 0x0100 /* WSEQ_EOS59 */
+#define WM8994_WSEQ_EOS59_MASK 0x0100 /* WSEQ_EOS59 */
+#define WM8994_WSEQ_EOS59_SHIFT 8 /* WSEQ_EOS59 */
+#define WM8994_WSEQ_EOS59_WIDTH 1 /* WSEQ_EOS59 */
+#define WM8994_WSEQ_DELAY59_MASK 0x000F /* WSEQ_DELAY59 - [3:0] */
+#define WM8994_WSEQ_DELAY59_SHIFT 0 /* WSEQ_DELAY59 - [3:0] */
+#define WM8994_WSEQ_DELAY59_WIDTH 4 /* WSEQ_DELAY59 - [3:0] */
+
+/*
+ * R12528 (0x30F0) - Write Sequencer 240
+ */
+#define WM8994_WSEQ_ADDR60_MASK 0x3FFF /* WSEQ_ADDR60 - [13:0] */
+#define WM8994_WSEQ_ADDR60_SHIFT 0 /* WSEQ_ADDR60 - [13:0] */
+#define WM8994_WSEQ_ADDR60_WIDTH 14 /* WSEQ_ADDR60 - [13:0] */
+
+/*
+ * R12529 (0x30F1) - Write Sequencer 241
+ */
+#define WM8994_WSEQ_DATA60_MASK 0x00FF /* WSEQ_DATA60 - [7:0] */
+#define WM8994_WSEQ_DATA60_SHIFT 0 /* WSEQ_DATA60 - [7:0] */
+#define WM8994_WSEQ_DATA60_WIDTH 8 /* WSEQ_DATA60 - [7:0] */
+
+/*
+ * R12530 (0x30F2) - Write Sequencer 242
+ */
+#define WM8994_WSEQ_DATA_WIDTH60_MASK 0x0700 /* WSEQ_DATA_WIDTH60 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH60_SHIFT 8 /* WSEQ_DATA_WIDTH60 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH60_WIDTH 3 /* WSEQ_DATA_WIDTH60 - [10:8] */
+#define WM8994_WSEQ_DATA_START60_MASK 0x000F /* WSEQ_DATA_START60 - [3:0] */
+#define WM8994_WSEQ_DATA_START60_SHIFT 0 /* WSEQ_DATA_START60 - [3:0] */
+#define WM8994_WSEQ_DATA_START60_WIDTH 4 /* WSEQ_DATA_START60 - [3:0] */
+
+/*
+ * R12531 (0x30F3) - Write Sequencer 243
+ */
+#define WM8994_WSEQ_EOS60 0x0100 /* WSEQ_EOS60 */
+#define WM8994_WSEQ_EOS60_MASK 0x0100 /* WSEQ_EOS60 */
+#define WM8994_WSEQ_EOS60_SHIFT 8 /* WSEQ_EOS60 */
+#define WM8994_WSEQ_EOS60_WIDTH 1 /* WSEQ_EOS60 */
+#define WM8994_WSEQ_DELAY60_MASK 0x000F /* WSEQ_DELAY60 - [3:0] */
+#define WM8994_WSEQ_DELAY60_SHIFT 0 /* WSEQ_DELAY60 - [3:0] */
+#define WM8994_WSEQ_DELAY60_WIDTH 4 /* WSEQ_DELAY60 - [3:0] */
+
+/*
+ * R12532 (0x30F4) - Write Sequencer 244
+ */
+#define WM8994_WSEQ_ADDR61_MASK 0x3FFF /* WSEQ_ADDR61 - [13:0] */
+#define WM8994_WSEQ_ADDR61_SHIFT 0 /* WSEQ_ADDR61 - [13:0] */
+#define WM8994_WSEQ_ADDR61_WIDTH 14 /* WSEQ_ADDR61 - [13:0] */
+
+/*
+ * R12533 (0x30F5) - Write Sequencer 245
+ */
+#define WM8994_WSEQ_DATA61_MASK 0x00FF /* WSEQ_DATA61 - [7:0] */
+#define WM8994_WSEQ_DATA61_SHIFT 0 /* WSEQ_DATA61 - [7:0] */
+#define WM8994_WSEQ_DATA61_WIDTH 8 /* WSEQ_DATA61 - [7:0] */
+
+/*
+ * R12534 (0x30F6) - Write Sequencer 246
+ */
+#define WM8994_WSEQ_DATA_WIDTH61_MASK 0x0700 /* WSEQ_DATA_WIDTH61 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH61_SHIFT 8 /* WSEQ_DATA_WIDTH61 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH61_WIDTH 3 /* WSEQ_DATA_WIDTH61 - [10:8] */
+#define WM8994_WSEQ_DATA_START61_MASK 0x000F /* WSEQ_DATA_START61 - [3:0] */
+#define WM8994_WSEQ_DATA_START61_SHIFT 0 /* WSEQ_DATA_START61 - [3:0] */
+#define WM8994_WSEQ_DATA_START61_WIDTH 4 /* WSEQ_DATA_START61 - [3:0] */
+
+/*
+ * R12535 (0x30F7) - Write Sequencer 247
+ */
+#define WM8994_WSEQ_EOS61 0x0100 /* WSEQ_EOS61 */
+#define WM8994_WSEQ_EOS61_MASK 0x0100 /* WSEQ_EOS61 */
+#define WM8994_WSEQ_EOS61_SHIFT 8 /* WSEQ_EOS61 */
+#define WM8994_WSEQ_EOS61_WIDTH 1 /* WSEQ_EOS61 */
+#define WM8994_WSEQ_DELAY61_MASK 0x000F /* WSEQ_DELAY61 - [3:0] */
+#define WM8994_WSEQ_DELAY61_SHIFT 0 /* WSEQ_DELAY61 - [3:0] */
+#define WM8994_WSEQ_DELAY61_WIDTH 4 /* WSEQ_DELAY61 - [3:0] */
+
+/*
+ * R12536 (0x30F8) - Write Sequencer 248
+ */
+#define WM8994_WSEQ_ADDR62_MASK 0x3FFF /* WSEQ_ADDR62 - [13:0] */
+#define WM8994_WSEQ_ADDR62_SHIFT 0 /* WSEQ_ADDR62 - [13:0] */
+#define WM8994_WSEQ_ADDR62_WIDTH 14 /* WSEQ_ADDR62 - [13:0] */
+
+/*
+ * R12537 (0x30F9) - Write Sequencer 249
+ */
+#define WM8994_WSEQ_DATA62_MASK 0x00FF /* WSEQ_DATA62 - [7:0] */
+#define WM8994_WSEQ_DATA62_SHIFT 0 /* WSEQ_DATA62 - [7:0] */
+#define WM8994_WSEQ_DATA62_WIDTH 8 /* WSEQ_DATA62 - [7:0] */
+
+/*
+ * R12538 (0x30FA) - Write Sequencer 250
+ */
+#define WM8994_WSEQ_DATA_WIDTH62_MASK 0x0700 /* WSEQ_DATA_WIDTH62 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH62_SHIFT 8 /* WSEQ_DATA_WIDTH62 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH62_WIDTH 3 /* WSEQ_DATA_WIDTH62 - [10:8] */
+#define WM8994_WSEQ_DATA_START62_MASK 0x000F /* WSEQ_DATA_START62 - [3:0] */
+#define WM8994_WSEQ_DATA_START62_SHIFT 0 /* WSEQ_DATA_START62 - [3:0] */
+#define WM8994_WSEQ_DATA_START62_WIDTH 4 /* WSEQ_DATA_START62 - [3:0] */
+
+/*
+ * R12539 (0x30FB) - Write Sequencer 251
+ */
+#define WM8994_WSEQ_EOS62 0x0100 /* WSEQ_EOS62 */
+#define WM8994_WSEQ_EOS62_MASK 0x0100 /* WSEQ_EOS62 */
+#define WM8994_WSEQ_EOS62_SHIFT 8 /* WSEQ_EOS62 */
+#define WM8994_WSEQ_EOS62_WIDTH 1 /* WSEQ_EOS62 */
+#define WM8994_WSEQ_DELAY62_MASK 0x000F /* WSEQ_DELAY62 - [3:0] */
+#define WM8994_WSEQ_DELAY62_SHIFT 0 /* WSEQ_DELAY62 - [3:0] */
+#define WM8994_WSEQ_DELAY62_WIDTH 4 /* WSEQ_DELAY62 - [3:0] */
+
+/*
+ * R12540 (0x30FC) - Write Sequencer 252
+ */
+#define WM8994_WSEQ_ADDR63_MASK 0x3FFF /* WSEQ_ADDR63 - [13:0] */
+#define WM8994_WSEQ_ADDR63_SHIFT 0 /* WSEQ_ADDR63 - [13:0] */
+#define WM8994_WSEQ_ADDR63_WIDTH 14 /* WSEQ_ADDR63 - [13:0] */
+
+/*
+ * R12541 (0x30FD) - Write Sequencer 253
+ */
+#define WM8994_WSEQ_DATA63_MASK 0x00FF /* WSEQ_DATA63 - [7:0] */
+#define WM8994_WSEQ_DATA63_SHIFT 0 /* WSEQ_DATA63 - [7:0] */
+#define WM8994_WSEQ_DATA63_WIDTH 8 /* WSEQ_DATA63 - [7:0] */
+
+/*
+ * R12542 (0x30FE) - Write Sequencer 254
+ */
+#define WM8994_WSEQ_DATA_WIDTH63_MASK 0x0700 /* WSEQ_DATA_WIDTH63 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH63_SHIFT 8 /* WSEQ_DATA_WIDTH63 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH63_WIDTH 3 /* WSEQ_DATA_WIDTH63 - [10:8] */
+#define WM8994_WSEQ_DATA_START63_MASK 0x000F /* WSEQ_DATA_START63 - [3:0] */
+#define WM8994_WSEQ_DATA_START63_SHIFT 0 /* WSEQ_DATA_START63 - [3:0] */
+#define WM8994_WSEQ_DATA_START63_WIDTH 4 /* WSEQ_DATA_START63 - [3:0] */
+
+/*
+ * R12543 (0x30FF) - Write Sequencer 255
+ */
+#define WM8994_WSEQ_EOS63 0x0100 /* WSEQ_EOS63 */
+#define WM8994_WSEQ_EOS63_MASK 0x0100 /* WSEQ_EOS63 */
+#define WM8994_WSEQ_EOS63_SHIFT 8 /* WSEQ_EOS63 */
+#define WM8994_WSEQ_EOS63_WIDTH 1 /* WSEQ_EOS63 */
+#define WM8994_WSEQ_DELAY63_MASK 0x000F /* WSEQ_DELAY63 - [3:0] */
+#define WM8994_WSEQ_DELAY63_SHIFT 0 /* WSEQ_DELAY63 - [3:0] */
+#define WM8994_WSEQ_DELAY63_WIDTH 4 /* WSEQ_DELAY63 - [3:0] */
+
+/*
+ * R12544 (0x3100) - Write Sequencer 256
+ */
+#define WM8994_WSEQ_ADDR64_MASK 0x3FFF /* WSEQ_ADDR64 - [13:0] */
+#define WM8994_WSEQ_ADDR64_SHIFT 0 /* WSEQ_ADDR64 - [13:0] */
+#define WM8994_WSEQ_ADDR64_WIDTH 14 /* WSEQ_ADDR64 - [13:0] */
+
+/*
+ * R12545 (0x3101) - Write Sequencer 257
+ */
+#define WM8994_WSEQ_DATA64_MASK 0x00FF /* WSEQ_DATA64 - [7:0] */
+#define WM8994_WSEQ_DATA64_SHIFT 0 /* WSEQ_DATA64 - [7:0] */
+#define WM8994_WSEQ_DATA64_WIDTH 8 /* WSEQ_DATA64 - [7:0] */
+
+/*
+ * R12546 (0x3102) - Write Sequencer 258
+ */
+#define WM8994_WSEQ_DATA_WIDTH64_MASK 0x0700 /* WSEQ_DATA_WIDTH64 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH64_SHIFT 8 /* WSEQ_DATA_WIDTH64 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH64_WIDTH 3 /* WSEQ_DATA_WIDTH64 - [10:8] */
+#define WM8994_WSEQ_DATA_START64_MASK 0x000F /* WSEQ_DATA_START64 - [3:0] */
+#define WM8994_WSEQ_DATA_START64_SHIFT 0 /* WSEQ_DATA_START64 - [3:0] */
+#define WM8994_WSEQ_DATA_START64_WIDTH 4 /* WSEQ_DATA_START64 - [3:0] */
+
+/*
+ * R12547 (0x3103) - Write Sequencer 259
+ */
+#define WM8994_WSEQ_EOS64 0x0100 /* WSEQ_EOS64 */
+#define WM8994_WSEQ_EOS64_MASK 0x0100 /* WSEQ_EOS64 */
+#define WM8994_WSEQ_EOS64_SHIFT 8 /* WSEQ_EOS64 */
+#define WM8994_WSEQ_EOS64_WIDTH 1 /* WSEQ_EOS64 */
+#define WM8994_WSEQ_DELAY64_MASK 0x000F /* WSEQ_DELAY64 - [3:0] */
+#define WM8994_WSEQ_DELAY64_SHIFT 0 /* WSEQ_DELAY64 - [3:0] */
+#define WM8994_WSEQ_DELAY64_WIDTH 4 /* WSEQ_DELAY64 - [3:0] */
+
+/*
+ * R12548 (0x3104) - Write Sequencer 260
+ */
+#define WM8994_WSEQ_ADDR65_MASK 0x3FFF /* WSEQ_ADDR65 - [13:0] */
+#define WM8994_WSEQ_ADDR65_SHIFT 0 /* WSEQ_ADDR65 - [13:0] */
+#define WM8994_WSEQ_ADDR65_WIDTH 14 /* WSEQ_ADDR65 - [13:0] */
+
+/*
+ * R12549 (0x3105) - Write Sequencer 261
+ */
+#define WM8994_WSEQ_DATA65_MASK 0x00FF /* WSEQ_DATA65 - [7:0] */
+#define WM8994_WSEQ_DATA65_SHIFT 0 /* WSEQ_DATA65 - [7:0] */
+#define WM8994_WSEQ_DATA65_WIDTH 8 /* WSEQ_DATA65 - [7:0] */
+
+/*
+ * R12550 (0x3106) - Write Sequencer 262
+ */
+#define WM8994_WSEQ_DATA_WIDTH65_MASK 0x0700 /* WSEQ_DATA_WIDTH65 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH65_SHIFT 8 /* WSEQ_DATA_WIDTH65 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH65_WIDTH 3 /* WSEQ_DATA_WIDTH65 - [10:8] */
+#define WM8994_WSEQ_DATA_START65_MASK 0x000F /* WSEQ_DATA_START65 - [3:0] */
+#define WM8994_WSEQ_DATA_START65_SHIFT 0 /* WSEQ_DATA_START65 - [3:0] */
+#define WM8994_WSEQ_DATA_START65_WIDTH 4 /* WSEQ_DATA_START65 - [3:0] */
+
+/*
+ * R12551 (0x3107) - Write Sequencer 263
+ */
+#define WM8994_WSEQ_EOS65 0x0100 /* WSEQ_EOS65 */
+#define WM8994_WSEQ_EOS65_MASK 0x0100 /* WSEQ_EOS65 */
+#define WM8994_WSEQ_EOS65_SHIFT 8 /* WSEQ_EOS65 */
+#define WM8994_WSEQ_EOS65_WIDTH 1 /* WSEQ_EOS65 */
+#define WM8994_WSEQ_DELAY65_MASK 0x000F /* WSEQ_DELAY65 - [3:0] */
+#define WM8994_WSEQ_DELAY65_SHIFT 0 /* WSEQ_DELAY65 - [3:0] */
+#define WM8994_WSEQ_DELAY65_WIDTH 4 /* WSEQ_DELAY65 - [3:0] */
+
+/*
+ * R12552 (0x3108) - Write Sequencer 264
+ */
+#define WM8994_WSEQ_ADDR66_MASK 0x3FFF /* WSEQ_ADDR66 - [13:0] */
+#define WM8994_WSEQ_ADDR66_SHIFT 0 /* WSEQ_ADDR66 - [13:0] */
+#define WM8994_WSEQ_ADDR66_WIDTH 14 /* WSEQ_ADDR66 - [13:0] */
+
+/*
+ * R12553 (0x3109) - Write Sequencer 265
+ */
+#define WM8994_WSEQ_DATA66_MASK 0x00FF /* WSEQ_DATA66 - [7:0] */
+#define WM8994_WSEQ_DATA66_SHIFT 0 /* WSEQ_DATA66 - [7:0] */
+#define WM8994_WSEQ_DATA66_WIDTH 8 /* WSEQ_DATA66 - [7:0] */
+
+/*
+ * R12554 (0x310A) - Write Sequencer 266
+ */
+#define WM8994_WSEQ_DATA_WIDTH66_MASK 0x0700 /* WSEQ_DATA_WIDTH66 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH66_SHIFT 8 /* WSEQ_DATA_WIDTH66 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH66_WIDTH 3 /* WSEQ_DATA_WIDTH66 - [10:8] */
+#define WM8994_WSEQ_DATA_START66_MASK 0x000F /* WSEQ_DATA_START66 - [3:0] */
+#define WM8994_WSEQ_DATA_START66_SHIFT 0 /* WSEQ_DATA_START66 - [3:0] */
+#define WM8994_WSEQ_DATA_START66_WIDTH 4 /* WSEQ_DATA_START66 - [3:0] */
+
+/*
+ * R12555 (0x310B) - Write Sequencer 267
+ */
+#define WM8994_WSEQ_EOS66 0x0100 /* WSEQ_EOS66 */
+#define WM8994_WSEQ_EOS66_MASK 0x0100 /* WSEQ_EOS66 */
+#define WM8994_WSEQ_EOS66_SHIFT 8 /* WSEQ_EOS66 */
+#define WM8994_WSEQ_EOS66_WIDTH 1 /* WSEQ_EOS66 */
+#define WM8994_WSEQ_DELAY66_MASK 0x000F /* WSEQ_DELAY66 - [3:0] */
+#define WM8994_WSEQ_DELAY66_SHIFT 0 /* WSEQ_DELAY66 - [3:0] */
+#define WM8994_WSEQ_DELAY66_WIDTH 4 /* WSEQ_DELAY66 - [3:0] */
+
+/*
+ * R12556 (0x310C) - Write Sequencer 268
+ */
+#define WM8994_WSEQ_ADDR67_MASK 0x3FFF /* WSEQ_ADDR67 - [13:0] */
+#define WM8994_WSEQ_ADDR67_SHIFT 0 /* WSEQ_ADDR67 - [13:0] */
+#define WM8994_WSEQ_ADDR67_WIDTH 14 /* WSEQ_ADDR67 - [13:0] */
+
+/*
+ * R12557 (0x310D) - Write Sequencer 269
+ */
+#define WM8994_WSEQ_DATA67_MASK 0x00FF /* WSEQ_DATA67 - [7:0] */
+#define WM8994_WSEQ_DATA67_SHIFT 0 /* WSEQ_DATA67 - [7:0] */
+#define WM8994_WSEQ_DATA67_WIDTH 8 /* WSEQ_DATA67 - [7:0] */
+
+/*
+ * R12558 (0x310E) - Write Sequencer 270
+ */
+#define WM8994_WSEQ_DATA_WIDTH67_MASK 0x0700 /* WSEQ_DATA_WIDTH67 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH67_SHIFT 8 /* WSEQ_DATA_WIDTH67 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH67_WIDTH 3 /* WSEQ_DATA_WIDTH67 - [10:8] */
+#define WM8994_WSEQ_DATA_START67_MASK 0x000F /* WSEQ_DATA_START67 - [3:0] */
+#define WM8994_WSEQ_DATA_START67_SHIFT 0 /* WSEQ_DATA_START67 - [3:0] */
+#define WM8994_WSEQ_DATA_START67_WIDTH 4 /* WSEQ_DATA_START67 - [3:0] */
+
+/*
+ * R12559 (0x310F) - Write Sequencer 271
+ */
+#define WM8994_WSEQ_EOS67 0x0100 /* WSEQ_EOS67 */
+#define WM8994_WSEQ_EOS67_MASK 0x0100 /* WSEQ_EOS67 */
+#define WM8994_WSEQ_EOS67_SHIFT 8 /* WSEQ_EOS67 */
+#define WM8994_WSEQ_EOS67_WIDTH 1 /* WSEQ_EOS67 */
+#define WM8994_WSEQ_DELAY67_MASK 0x000F /* WSEQ_DELAY67 - [3:0] */
+#define WM8994_WSEQ_DELAY67_SHIFT 0 /* WSEQ_DELAY67 - [3:0] */
+#define WM8994_WSEQ_DELAY67_WIDTH 4 /* WSEQ_DELAY67 - [3:0] */
+
+/*
+ * R12560 (0x3110) - Write Sequencer 272
+ */
+#define WM8994_WSEQ_ADDR68_MASK 0x3FFF /* WSEQ_ADDR68 - [13:0] */
+#define WM8994_WSEQ_ADDR68_SHIFT 0 /* WSEQ_ADDR68 - [13:0] */
+#define WM8994_WSEQ_ADDR68_WIDTH 14 /* WSEQ_ADDR68 - [13:0] */
+
+/*
+ * R12561 (0x3111) - Write Sequencer 273
+ */
+#define WM8994_WSEQ_DATA68_MASK 0x00FF /* WSEQ_DATA68 - [7:0] */
+#define WM8994_WSEQ_DATA68_SHIFT 0 /* WSEQ_DATA68 - [7:0] */
+#define WM8994_WSEQ_DATA68_WIDTH 8 /* WSEQ_DATA68 - [7:0] */
+
+/*
+ * R12562 (0x3112) - Write Sequencer 274
+ */
+#define WM8994_WSEQ_DATA_WIDTH68_MASK 0x0700 /* WSEQ_DATA_WIDTH68 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH68_SHIFT 8 /* WSEQ_DATA_WIDTH68 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH68_WIDTH 3 /* WSEQ_DATA_WIDTH68 - [10:8] */
+#define WM8994_WSEQ_DATA_START68_MASK 0x000F /* WSEQ_DATA_START68 - [3:0] */
+#define WM8994_WSEQ_DATA_START68_SHIFT 0 /* WSEQ_DATA_START68 - [3:0] */
+#define WM8994_WSEQ_DATA_START68_WIDTH 4 /* WSEQ_DATA_START68 - [3:0] */
+
+/*
+ * R12563 (0x3113) - Write Sequencer 275
+ */
+#define WM8994_WSEQ_EOS68 0x0100 /* WSEQ_EOS68 */
+#define WM8994_WSEQ_EOS68_MASK 0x0100 /* WSEQ_EOS68 */
+#define WM8994_WSEQ_EOS68_SHIFT 8 /* WSEQ_EOS68 */
+#define WM8994_WSEQ_EOS68_WIDTH 1 /* WSEQ_EOS68 */
+#define WM8994_WSEQ_DELAY68_MASK 0x000F /* WSEQ_DELAY68 - [3:0] */
+#define WM8994_WSEQ_DELAY68_SHIFT 0 /* WSEQ_DELAY68 - [3:0] */
+#define WM8994_WSEQ_DELAY68_WIDTH 4 /* WSEQ_DELAY68 - [3:0] */
+
+/*
+ * R12564 (0x3114) - Write Sequencer 276
+ */
+#define WM8994_WSEQ_ADDR69_MASK 0x3FFF /* WSEQ_ADDR69 - [13:0] */
+#define WM8994_WSEQ_ADDR69_SHIFT 0 /* WSEQ_ADDR69 - [13:0] */
+#define WM8994_WSEQ_ADDR69_WIDTH 14 /* WSEQ_ADDR69 - [13:0] */
+
+/*
+ * R12565 (0x3115) - Write Sequencer 277
+ */
+#define WM8994_WSEQ_DATA69_MASK 0x00FF /* WSEQ_DATA69 - [7:0] */
+#define WM8994_WSEQ_DATA69_SHIFT 0 /* WSEQ_DATA69 - [7:0] */
+#define WM8994_WSEQ_DATA69_WIDTH 8 /* WSEQ_DATA69 - [7:0] */
+
+/*
+ * R12566 (0x3116) - Write Sequencer 278
+ */
+#define WM8994_WSEQ_DATA_WIDTH69_MASK 0x0700 /* WSEQ_DATA_WIDTH69 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH69_SHIFT 8 /* WSEQ_DATA_WIDTH69 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH69_WIDTH 3 /* WSEQ_DATA_WIDTH69 - [10:8] */
+#define WM8994_WSEQ_DATA_START69_MASK 0x000F /* WSEQ_DATA_START69 - [3:0] */
+#define WM8994_WSEQ_DATA_START69_SHIFT 0 /* WSEQ_DATA_START69 - [3:0] */
+#define WM8994_WSEQ_DATA_START69_WIDTH 4 /* WSEQ_DATA_START69 - [3:0] */
+
+/*
+ * R12567 (0x3117) - Write Sequencer 279
+ */
+#define WM8994_WSEQ_EOS69 0x0100 /* WSEQ_EOS69 */
+#define WM8994_WSEQ_EOS69_MASK 0x0100 /* WSEQ_EOS69 */
+#define WM8994_WSEQ_EOS69_SHIFT 8 /* WSEQ_EOS69 */
+#define WM8994_WSEQ_EOS69_WIDTH 1 /* WSEQ_EOS69 */
+#define WM8994_WSEQ_DELAY69_MASK 0x000F /* WSEQ_DELAY69 - [3:0] */
+#define WM8994_WSEQ_DELAY69_SHIFT 0 /* WSEQ_DELAY69 - [3:0] */
+#define WM8994_WSEQ_DELAY69_WIDTH 4 /* WSEQ_DELAY69 - [3:0] */
+
+/*
+ * R12568 (0x3118) - Write Sequencer 280
+ */
+#define WM8994_WSEQ_ADDR70_MASK 0x3FFF /* WSEQ_ADDR70 - [13:0] */
+#define WM8994_WSEQ_ADDR70_SHIFT 0 /* WSEQ_ADDR70 - [13:0] */
+#define WM8994_WSEQ_ADDR70_WIDTH 14 /* WSEQ_ADDR70 - [13:0] */
+
+/*
+ * R12569 (0x3119) - Write Sequencer 281
+ */
+#define WM8994_WSEQ_DATA70_MASK 0x00FF /* WSEQ_DATA70 - [7:0] */
+#define WM8994_WSEQ_DATA70_SHIFT 0 /* WSEQ_DATA70 - [7:0] */
+#define WM8994_WSEQ_DATA70_WIDTH 8 /* WSEQ_DATA70 - [7:0] */
+
+/*
+ * R12570 (0x311A) - Write Sequencer 282
+ */
+#define WM8994_WSEQ_DATA_WIDTH70_MASK 0x0700 /* WSEQ_DATA_WIDTH70 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH70_SHIFT 8 /* WSEQ_DATA_WIDTH70 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH70_WIDTH 3 /* WSEQ_DATA_WIDTH70 - [10:8] */
+#define WM8994_WSEQ_DATA_START70_MASK 0x000F /* WSEQ_DATA_START70 - [3:0] */
+#define WM8994_WSEQ_DATA_START70_SHIFT 0 /* WSEQ_DATA_START70 - [3:0] */
+#define WM8994_WSEQ_DATA_START70_WIDTH 4 /* WSEQ_DATA_START70 - [3:0] */
+
+/*
+ * R12571 (0x311B) - Write Sequencer 283
+ */
+#define WM8994_WSEQ_EOS70 0x0100 /* WSEQ_EOS70 */
+#define WM8994_WSEQ_EOS70_MASK 0x0100 /* WSEQ_EOS70 */
+#define WM8994_WSEQ_EOS70_SHIFT 8 /* WSEQ_EOS70 */
+#define WM8994_WSEQ_EOS70_WIDTH 1 /* WSEQ_EOS70 */
+#define WM8994_WSEQ_DELAY70_MASK 0x000F /* WSEQ_DELAY70 - [3:0] */
+#define WM8994_WSEQ_DELAY70_SHIFT 0 /* WSEQ_DELAY70 - [3:0] */
+#define WM8994_WSEQ_DELAY70_WIDTH 4 /* WSEQ_DELAY70 - [3:0] */
+
+/*
+ * R12572 (0x311C) - Write Sequencer 284
+ */
+#define WM8994_WSEQ_ADDR71_MASK 0x3FFF /* WSEQ_ADDR71 - [13:0] */
+#define WM8994_WSEQ_ADDR71_SHIFT 0 /* WSEQ_ADDR71 - [13:0] */
+#define WM8994_WSEQ_ADDR71_WIDTH 14 /* WSEQ_ADDR71 - [13:0] */
+
+/*
+ * R12573 (0x311D) - Write Sequencer 285
+ */
+#define WM8994_WSEQ_DATA71_MASK 0x00FF /* WSEQ_DATA71 - [7:0] */
+#define WM8994_WSEQ_DATA71_SHIFT 0 /* WSEQ_DATA71 - [7:0] */
+#define WM8994_WSEQ_DATA71_WIDTH 8 /* WSEQ_DATA71 - [7:0] */
+
+/*
+ * R12574 (0x311E) - Write Sequencer 286
+ */
+#define WM8994_WSEQ_DATA_WIDTH71_MASK 0x0700 /* WSEQ_DATA_WIDTH71 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH71_SHIFT 8 /* WSEQ_DATA_WIDTH71 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH71_WIDTH 3 /* WSEQ_DATA_WIDTH71 - [10:8] */
+#define WM8994_WSEQ_DATA_START71_MASK 0x000F /* WSEQ_DATA_START71 - [3:0] */
+#define WM8994_WSEQ_DATA_START71_SHIFT 0 /* WSEQ_DATA_START71 - [3:0] */
+#define WM8994_WSEQ_DATA_START71_WIDTH 4 /* WSEQ_DATA_START71 - [3:0] */
+
+/*
+ * R12575 (0x311F) - Write Sequencer 287
+ */
+#define WM8994_WSEQ_EOS71 0x0100 /* WSEQ_EOS71 */
+#define WM8994_WSEQ_EOS71_MASK 0x0100 /* WSEQ_EOS71 */
+#define WM8994_WSEQ_EOS71_SHIFT 8 /* WSEQ_EOS71 */
+#define WM8994_WSEQ_EOS71_WIDTH 1 /* WSEQ_EOS71 */
+#define WM8994_WSEQ_DELAY71_MASK 0x000F /* WSEQ_DELAY71 - [3:0] */
+#define WM8994_WSEQ_DELAY71_SHIFT 0 /* WSEQ_DELAY71 - [3:0] */
+#define WM8994_WSEQ_DELAY71_WIDTH 4 /* WSEQ_DELAY71 - [3:0] */
+
+/*
+ * R12576 (0x3120) - Write Sequencer 288
+ */
+#define WM8994_WSEQ_ADDR72_MASK 0x3FFF /* WSEQ_ADDR72 - [13:0] */
+#define WM8994_WSEQ_ADDR72_SHIFT 0 /* WSEQ_ADDR72 - [13:0] */
+#define WM8994_WSEQ_ADDR72_WIDTH 14 /* WSEQ_ADDR72 - [13:0] */
+
+/*
+ * R12577 (0x3121) - Write Sequencer 289
+ */
+#define WM8994_WSEQ_DATA72_MASK 0x00FF /* WSEQ_DATA72 - [7:0] */
+#define WM8994_WSEQ_DATA72_SHIFT 0 /* WSEQ_DATA72 - [7:0] */
+#define WM8994_WSEQ_DATA72_WIDTH 8 /* WSEQ_DATA72 - [7:0] */
+
+/*
+ * R12578 (0x3122) - Write Sequencer 290
+ */
+#define WM8994_WSEQ_DATA_WIDTH72_MASK 0x0700 /* WSEQ_DATA_WIDTH72 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH72_SHIFT 8 /* WSEQ_DATA_WIDTH72 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH72_WIDTH 3 /* WSEQ_DATA_WIDTH72 - [10:8] */
+#define WM8994_WSEQ_DATA_START72_MASK 0x000F /* WSEQ_DATA_START72 - [3:0] */
+#define WM8994_WSEQ_DATA_START72_SHIFT 0 /* WSEQ_DATA_START72 - [3:0] */
+#define WM8994_WSEQ_DATA_START72_WIDTH 4 /* WSEQ_DATA_START72 - [3:0] */
+
+/*
+ * R12579 (0x3123) - Write Sequencer 291
+ */
+#define WM8994_WSEQ_EOS72 0x0100 /* WSEQ_EOS72 */
+#define WM8994_WSEQ_EOS72_MASK 0x0100 /* WSEQ_EOS72 */
+#define WM8994_WSEQ_EOS72_SHIFT 8 /* WSEQ_EOS72 */
+#define WM8994_WSEQ_EOS72_WIDTH 1 /* WSEQ_EOS72 */
+#define WM8994_WSEQ_DELAY72_MASK 0x000F /* WSEQ_DELAY72 - [3:0] */
+#define WM8994_WSEQ_DELAY72_SHIFT 0 /* WSEQ_DELAY72 - [3:0] */
+#define WM8994_WSEQ_DELAY72_WIDTH 4 /* WSEQ_DELAY72 - [3:0] */
+
+/*
+ * R12580 (0x3124) - Write Sequencer 292
+ */
+#define WM8994_WSEQ_ADDR73_MASK 0x3FFF /* WSEQ_ADDR73 - [13:0] */
+#define WM8994_WSEQ_ADDR73_SHIFT 0 /* WSEQ_ADDR73 - [13:0] */
+#define WM8994_WSEQ_ADDR73_WIDTH 14 /* WSEQ_ADDR73 - [13:0] */
+
+/*
+ * R12581 (0x3125) - Write Sequencer 293
+ */
+#define WM8994_WSEQ_DATA73_MASK 0x00FF /* WSEQ_DATA73 - [7:0] */
+#define WM8994_WSEQ_DATA73_SHIFT 0 /* WSEQ_DATA73 - [7:0] */
+#define WM8994_WSEQ_DATA73_WIDTH 8 /* WSEQ_DATA73 - [7:0] */
+
+/*
+ * R12582 (0x3126) - Write Sequencer 294
+ */
+#define WM8994_WSEQ_DATA_WIDTH73_MASK 0x0700 /* WSEQ_DATA_WIDTH73 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH73_SHIFT 8 /* WSEQ_DATA_WIDTH73 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH73_WIDTH 3 /* WSEQ_DATA_WIDTH73 - [10:8] */
+#define WM8994_WSEQ_DATA_START73_MASK 0x000F /* WSEQ_DATA_START73 - [3:0] */
+#define WM8994_WSEQ_DATA_START73_SHIFT 0 /* WSEQ_DATA_START73 - [3:0] */
+#define WM8994_WSEQ_DATA_START73_WIDTH 4 /* WSEQ_DATA_START73 - [3:0] */
+
+/*
+ * R12583 (0x3127) - Write Sequencer 295
+ */
+#define WM8994_WSEQ_EOS73 0x0100 /* WSEQ_EOS73 */
+#define WM8994_WSEQ_EOS73_MASK 0x0100 /* WSEQ_EOS73 */
+#define WM8994_WSEQ_EOS73_SHIFT 8 /* WSEQ_EOS73 */
+#define WM8994_WSEQ_EOS73_WIDTH 1 /* WSEQ_EOS73 */
+#define WM8994_WSEQ_DELAY73_MASK 0x000F /* WSEQ_DELAY73 - [3:0] */
+#define WM8994_WSEQ_DELAY73_SHIFT 0 /* WSEQ_DELAY73 - [3:0] */
+#define WM8994_WSEQ_DELAY73_WIDTH 4 /* WSEQ_DELAY73 - [3:0] */
+
+/*
+ * R12584 (0x3128) - Write Sequencer 296
+ */
+#define WM8994_WSEQ_ADDR74_MASK 0x3FFF /* WSEQ_ADDR74 - [13:0] */
+#define WM8994_WSEQ_ADDR74_SHIFT 0 /* WSEQ_ADDR74 - [13:0] */
+#define WM8994_WSEQ_ADDR74_WIDTH 14 /* WSEQ_ADDR74 - [13:0] */
+
+/*
+ * R12585 (0x3129) - Write Sequencer 297
+ */
+#define WM8994_WSEQ_DATA74_MASK 0x00FF /* WSEQ_DATA74 - [7:0] */
+#define WM8994_WSEQ_DATA74_SHIFT 0 /* WSEQ_DATA74 - [7:0] */
+#define WM8994_WSEQ_DATA74_WIDTH 8 /* WSEQ_DATA74 - [7:0] */
+
+/*
+ * R12586 (0x312A) - Write Sequencer 298
+ */
+#define WM8994_WSEQ_DATA_WIDTH74_MASK 0x0700 /* WSEQ_DATA_WIDTH74 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH74_SHIFT 8 /* WSEQ_DATA_WIDTH74 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH74_WIDTH 3 /* WSEQ_DATA_WIDTH74 - [10:8] */
+#define WM8994_WSEQ_DATA_START74_MASK 0x000F /* WSEQ_DATA_START74 - [3:0] */
+#define WM8994_WSEQ_DATA_START74_SHIFT 0 /* WSEQ_DATA_START74 - [3:0] */
+#define WM8994_WSEQ_DATA_START74_WIDTH 4 /* WSEQ_DATA_START74 - [3:0] */
+
+/*
+ * R12587 (0x312B) - Write Sequencer 299
+ */
+#define WM8994_WSEQ_EOS74 0x0100 /* WSEQ_EOS74 */
+#define WM8994_WSEQ_EOS74_MASK 0x0100 /* WSEQ_EOS74 */
+#define WM8994_WSEQ_EOS74_SHIFT 8 /* WSEQ_EOS74 */
+#define WM8994_WSEQ_EOS74_WIDTH 1 /* WSEQ_EOS74 */
+#define WM8994_WSEQ_DELAY74_MASK 0x000F /* WSEQ_DELAY74 - [3:0] */
+#define WM8994_WSEQ_DELAY74_SHIFT 0 /* WSEQ_DELAY74 - [3:0] */
+#define WM8994_WSEQ_DELAY74_WIDTH 4 /* WSEQ_DELAY74 - [3:0] */
+
+/*
+ * R12588 (0x312C) - Write Sequencer 300
+ */
+#define WM8994_WSEQ_ADDR75_MASK 0x3FFF /* WSEQ_ADDR75 - [13:0] */
+#define WM8994_WSEQ_ADDR75_SHIFT 0 /* WSEQ_ADDR75 - [13:0] */
+#define WM8994_WSEQ_ADDR75_WIDTH 14 /* WSEQ_ADDR75 - [13:0] */
+
+/*
+ * R12589 (0x312D) - Write Sequencer 301
+ */
+#define WM8994_WSEQ_DATA75_MASK 0x00FF /* WSEQ_DATA75 - [7:0] */
+#define WM8994_WSEQ_DATA75_SHIFT 0 /* WSEQ_DATA75 - [7:0] */
+#define WM8994_WSEQ_DATA75_WIDTH 8 /* WSEQ_DATA75 - [7:0] */
+
+/*
+ * R12590 (0x312E) - Write Sequencer 302
+ */
+#define WM8994_WSEQ_DATA_WIDTH75_MASK 0x0700 /* WSEQ_DATA_WIDTH75 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH75_SHIFT 8 /* WSEQ_DATA_WIDTH75 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH75_WIDTH 3 /* WSEQ_DATA_WIDTH75 - [10:8] */
+#define WM8994_WSEQ_DATA_START75_MASK 0x000F /* WSEQ_DATA_START75 - [3:0] */
+#define WM8994_WSEQ_DATA_START75_SHIFT 0 /* WSEQ_DATA_START75 - [3:0] */
+#define WM8994_WSEQ_DATA_START75_WIDTH 4 /* WSEQ_DATA_START75 - [3:0] */
+
+/*
+ * R12591 (0x312F) - Write Sequencer 303
+ */
+#define WM8994_WSEQ_EOS75 0x0100 /* WSEQ_EOS75 */
+#define WM8994_WSEQ_EOS75_MASK 0x0100 /* WSEQ_EOS75 */
+#define WM8994_WSEQ_EOS75_SHIFT 8 /* WSEQ_EOS75 */
+#define WM8994_WSEQ_EOS75_WIDTH 1 /* WSEQ_EOS75 */
+#define WM8994_WSEQ_DELAY75_MASK 0x000F /* WSEQ_DELAY75 - [3:0] */
+#define WM8994_WSEQ_DELAY75_SHIFT 0 /* WSEQ_DELAY75 - [3:0] */
+#define WM8994_WSEQ_DELAY75_WIDTH 4 /* WSEQ_DELAY75 - [3:0] */
+
+/*
+ * R12592 (0x3130) - Write Sequencer 304
+ */
+#define WM8994_WSEQ_ADDR76_MASK 0x3FFF /* WSEQ_ADDR76 - [13:0] */
+#define WM8994_WSEQ_ADDR76_SHIFT 0 /* WSEQ_ADDR76 - [13:0] */
+#define WM8994_WSEQ_ADDR76_WIDTH 14 /* WSEQ_ADDR76 - [13:0] */
+
+/*
+ * R12593 (0x3131) - Write Sequencer 305
+ */
+#define WM8994_WSEQ_DATA76_MASK 0x00FF /* WSEQ_DATA76 - [7:0] */
+#define WM8994_WSEQ_DATA76_SHIFT 0 /* WSEQ_DATA76 - [7:0] */
+#define WM8994_WSEQ_DATA76_WIDTH 8 /* WSEQ_DATA76 - [7:0] */
+
+/*
+ * R12594 (0x3132) - Write Sequencer 306
+ */
+#define WM8994_WSEQ_DATA_WIDTH76_MASK 0x0700 /* WSEQ_DATA_WIDTH76 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH76_SHIFT 8 /* WSEQ_DATA_WIDTH76 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH76_WIDTH 3 /* WSEQ_DATA_WIDTH76 - [10:8] */
+#define WM8994_WSEQ_DATA_START76_MASK 0x000F /* WSEQ_DATA_START76 - [3:0] */
+#define WM8994_WSEQ_DATA_START76_SHIFT 0 /* WSEQ_DATA_START76 - [3:0] */
+#define WM8994_WSEQ_DATA_START76_WIDTH 4 /* WSEQ_DATA_START76 - [3:0] */
+
+/*
+ * R12595 (0x3133) - Write Sequencer 307
+ */
+#define WM8994_WSEQ_EOS76 0x0100 /* WSEQ_EOS76 */
+#define WM8994_WSEQ_EOS76_MASK 0x0100 /* WSEQ_EOS76 */
+#define WM8994_WSEQ_EOS76_SHIFT 8 /* WSEQ_EOS76 */
+#define WM8994_WSEQ_EOS76_WIDTH 1 /* WSEQ_EOS76 */
+#define WM8994_WSEQ_DELAY76_MASK 0x000F /* WSEQ_DELAY76 - [3:0] */
+#define WM8994_WSEQ_DELAY76_SHIFT 0 /* WSEQ_DELAY76 - [3:0] */
+#define WM8994_WSEQ_DELAY76_WIDTH 4 /* WSEQ_DELAY76 - [3:0] */
+
+/*
+ * R12596 (0x3134) - Write Sequencer 308
+ */
+#define WM8994_WSEQ_ADDR77_MASK 0x3FFF /* WSEQ_ADDR77 - [13:0] */
+#define WM8994_WSEQ_ADDR77_SHIFT 0 /* WSEQ_ADDR77 - [13:0] */
+#define WM8994_WSEQ_ADDR77_WIDTH 14 /* WSEQ_ADDR77 - [13:0] */
+
+/*
+ * R12597 (0x3135) - Write Sequencer 309
+ */
+#define WM8994_WSEQ_DATA77_MASK 0x00FF /* WSEQ_DATA77 - [7:0] */
+#define WM8994_WSEQ_DATA77_SHIFT 0 /* WSEQ_DATA77 - [7:0] */
+#define WM8994_WSEQ_DATA77_WIDTH 8 /* WSEQ_DATA77 - [7:0] */
+
+/*
+ * R12598 (0x3136) - Write Sequencer 310
+ */
+#define WM8994_WSEQ_DATA_WIDTH77_MASK 0x0700 /* WSEQ_DATA_WIDTH77 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH77_SHIFT 8 /* WSEQ_DATA_WIDTH77 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH77_WIDTH 3 /* WSEQ_DATA_WIDTH77 - [10:8] */
+#define WM8994_WSEQ_DATA_START77_MASK 0x000F /* WSEQ_DATA_START77 - [3:0] */
+#define WM8994_WSEQ_DATA_START77_SHIFT 0 /* WSEQ_DATA_START77 - [3:0] */
+#define WM8994_WSEQ_DATA_START77_WIDTH 4 /* WSEQ_DATA_START77 - [3:0] */
+
+/*
+ * R12599 (0x3137) - Write Sequencer 311
+ */
+#define WM8994_WSEQ_EOS77 0x0100 /* WSEQ_EOS77 */
+#define WM8994_WSEQ_EOS77_MASK 0x0100 /* WSEQ_EOS77 */
+#define WM8994_WSEQ_EOS77_SHIFT 8 /* WSEQ_EOS77 */
+#define WM8994_WSEQ_EOS77_WIDTH 1 /* WSEQ_EOS77 */
+#define WM8994_WSEQ_DELAY77_MASK 0x000F /* WSEQ_DELAY77 - [3:0] */
+#define WM8994_WSEQ_DELAY77_SHIFT 0 /* WSEQ_DELAY77 - [3:0] */
+#define WM8994_WSEQ_DELAY77_WIDTH 4 /* WSEQ_DELAY77 - [3:0] */
+
+/*
+ * R12600 (0x3138) - Write Sequencer 312
+ */
+#define WM8994_WSEQ_ADDR78_MASK 0x3FFF /* WSEQ_ADDR78 - [13:0] */
+#define WM8994_WSEQ_ADDR78_SHIFT 0 /* WSEQ_ADDR78 - [13:0] */
+#define WM8994_WSEQ_ADDR78_WIDTH 14 /* WSEQ_ADDR78 - [13:0] */
+
+/*
+ * R12601 (0x3139) - Write Sequencer 313
+ */
+#define WM8994_WSEQ_DATA78_MASK 0x00FF /* WSEQ_DATA78 - [7:0] */
+#define WM8994_WSEQ_DATA78_SHIFT 0 /* WSEQ_DATA78 - [7:0] */
+#define WM8994_WSEQ_DATA78_WIDTH 8 /* WSEQ_DATA78 - [7:0] */
+
+/*
+ * R12602 (0x313A) - Write Sequencer 314
+ */
+#define WM8994_WSEQ_DATA_WIDTH78_MASK 0x0700 /* WSEQ_DATA_WIDTH78 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH78_SHIFT 8 /* WSEQ_DATA_WIDTH78 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH78_WIDTH 3 /* WSEQ_DATA_WIDTH78 - [10:8] */
+#define WM8994_WSEQ_DATA_START78_MASK 0x000F /* WSEQ_DATA_START78 - [3:0] */
+#define WM8994_WSEQ_DATA_START78_SHIFT 0 /* WSEQ_DATA_START78 - [3:0] */
+#define WM8994_WSEQ_DATA_START78_WIDTH 4 /* WSEQ_DATA_START78 - [3:0] */
+
+/*
+ * R12603 (0x313B) - Write Sequencer 315
+ */
+#define WM8994_WSEQ_EOS78 0x0100 /* WSEQ_EOS78 */
+#define WM8994_WSEQ_EOS78_MASK 0x0100 /* WSEQ_EOS78 */
+#define WM8994_WSEQ_EOS78_SHIFT 8 /* WSEQ_EOS78 */
+#define WM8994_WSEQ_EOS78_WIDTH 1 /* WSEQ_EOS78 */
+#define WM8994_WSEQ_DELAY78_MASK 0x000F /* WSEQ_DELAY78 - [3:0] */
+#define WM8994_WSEQ_DELAY78_SHIFT 0 /* WSEQ_DELAY78 - [3:0] */
+#define WM8994_WSEQ_DELAY78_WIDTH 4 /* WSEQ_DELAY78 - [3:0] */
+
+/*
+ * R12604 (0x313C) - Write Sequencer 316
+ */
+#define WM8994_WSEQ_ADDR79_MASK 0x3FFF /* WSEQ_ADDR79 - [13:0] */
+#define WM8994_WSEQ_ADDR79_SHIFT 0 /* WSEQ_ADDR79 - [13:0] */
+#define WM8994_WSEQ_ADDR79_WIDTH 14 /* WSEQ_ADDR79 - [13:0] */
+
+/*
+ * R12605 (0x313D) - Write Sequencer 317
+ */
+#define WM8994_WSEQ_DATA79_MASK 0x00FF /* WSEQ_DATA79 - [7:0] */
+#define WM8994_WSEQ_DATA79_SHIFT 0 /* WSEQ_DATA79 - [7:0] */
+#define WM8994_WSEQ_DATA79_WIDTH 8 /* WSEQ_DATA79 - [7:0] */
+
+/*
+ * R12606 (0x313E) - Write Sequencer 318
+ */
+#define WM8994_WSEQ_DATA_WIDTH79_MASK 0x0700 /* WSEQ_DATA_WIDTH79 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH79_SHIFT 8 /* WSEQ_DATA_WIDTH79 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH79_WIDTH 3 /* WSEQ_DATA_WIDTH79 - [10:8] */
+#define WM8994_WSEQ_DATA_START79_MASK 0x000F /* WSEQ_DATA_START79 - [3:0] */
+#define WM8994_WSEQ_DATA_START79_SHIFT 0 /* WSEQ_DATA_START79 - [3:0] */
+#define WM8994_WSEQ_DATA_START79_WIDTH 4 /* WSEQ_DATA_START79 - [3:0] */
+
+/*
+ * R12607 (0x313F) - Write Sequencer 319
+ */
+#define WM8994_WSEQ_EOS79 0x0100 /* WSEQ_EOS79 */
+#define WM8994_WSEQ_EOS79_MASK 0x0100 /* WSEQ_EOS79 */
+#define WM8994_WSEQ_EOS79_SHIFT 8 /* WSEQ_EOS79 */
+#define WM8994_WSEQ_EOS79_WIDTH 1 /* WSEQ_EOS79 */
+#define WM8994_WSEQ_DELAY79_MASK 0x000F /* WSEQ_DELAY79 - [3:0] */
+#define WM8994_WSEQ_DELAY79_SHIFT 0 /* WSEQ_DELAY79 - [3:0] */
+#define WM8994_WSEQ_DELAY79_WIDTH 4 /* WSEQ_DELAY79 - [3:0] */
+
+/*
+ * R12608 (0x3140) - Write Sequencer 320
+ */
+#define WM8994_WSEQ_ADDR80_MASK 0x3FFF /* WSEQ_ADDR80 - [13:0] */
+#define WM8994_WSEQ_ADDR80_SHIFT 0 /* WSEQ_ADDR80 - [13:0] */
+#define WM8994_WSEQ_ADDR80_WIDTH 14 /* WSEQ_ADDR80 - [13:0] */
+
+/*
+ * R12609 (0x3141) - Write Sequencer 321
+ */
+#define WM8994_WSEQ_DATA80_MASK 0x00FF /* WSEQ_DATA80 - [7:0] */
+#define WM8994_WSEQ_DATA80_SHIFT 0 /* WSEQ_DATA80 - [7:0] */
+#define WM8994_WSEQ_DATA80_WIDTH 8 /* WSEQ_DATA80 - [7:0] */
+
+/*
+ * R12610 (0x3142) - Write Sequencer 322
+ */
+#define WM8994_WSEQ_DATA_WIDTH80_MASK 0x0700 /* WSEQ_DATA_WIDTH80 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH80_SHIFT 8 /* WSEQ_DATA_WIDTH80 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH80_WIDTH 3 /* WSEQ_DATA_WIDTH80 - [10:8] */
+#define WM8994_WSEQ_DATA_START80_MASK 0x000F /* WSEQ_DATA_START80 - [3:0] */
+#define WM8994_WSEQ_DATA_START80_SHIFT 0 /* WSEQ_DATA_START80 - [3:0] */
+#define WM8994_WSEQ_DATA_START80_WIDTH 4 /* WSEQ_DATA_START80 - [3:0] */
+
+/*
+ * R12611 (0x3143) - Write Sequencer 323
+ */
+#define WM8994_WSEQ_EOS80 0x0100 /* WSEQ_EOS80 */
+#define WM8994_WSEQ_EOS80_MASK 0x0100 /* WSEQ_EOS80 */
+#define WM8994_WSEQ_EOS80_SHIFT 8 /* WSEQ_EOS80 */
+#define WM8994_WSEQ_EOS80_WIDTH 1 /* WSEQ_EOS80 */
+#define WM8994_WSEQ_DELAY80_MASK 0x000F /* WSEQ_DELAY80 - [3:0] */
+#define WM8994_WSEQ_DELAY80_SHIFT 0 /* WSEQ_DELAY80 - [3:0] */
+#define WM8994_WSEQ_DELAY80_WIDTH 4 /* WSEQ_DELAY80 - [3:0] */
+
+/*
+ * R12612 (0x3144) - Write Sequencer 324
+ */
+#define WM8994_WSEQ_ADDR81_MASK 0x3FFF /* WSEQ_ADDR81 - [13:0] */
+#define WM8994_WSEQ_ADDR81_SHIFT 0 /* WSEQ_ADDR81 - [13:0] */
+#define WM8994_WSEQ_ADDR81_WIDTH 14 /* WSEQ_ADDR81 - [13:0] */
+
+/*
+ * R12613 (0x3145) - Write Sequencer 325
+ */
+#define WM8994_WSEQ_DATA81_MASK 0x00FF /* WSEQ_DATA81 - [7:0] */
+#define WM8994_WSEQ_DATA81_SHIFT 0 /* WSEQ_DATA81 - [7:0] */
+#define WM8994_WSEQ_DATA81_WIDTH 8 /* WSEQ_DATA81 - [7:0] */
+
+/*
+ * R12614 (0x3146) - Write Sequencer 326
+ */
+#define WM8994_WSEQ_DATA_WIDTH81_MASK 0x0700 /* WSEQ_DATA_WIDTH81 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH81_SHIFT 8 /* WSEQ_DATA_WIDTH81 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH81_WIDTH 3 /* WSEQ_DATA_WIDTH81 - [10:8] */
+#define WM8994_WSEQ_DATA_START81_MASK 0x000F /* WSEQ_DATA_START81 - [3:0] */
+#define WM8994_WSEQ_DATA_START81_SHIFT 0 /* WSEQ_DATA_START81 - [3:0] */
+#define WM8994_WSEQ_DATA_START81_WIDTH 4 /* WSEQ_DATA_START81 - [3:0] */
+
+/*
+ * R12615 (0x3147) - Write Sequencer 327
+ */
+#define WM8994_WSEQ_EOS81 0x0100 /* WSEQ_EOS81 */
+#define WM8994_WSEQ_EOS81_MASK 0x0100 /* WSEQ_EOS81 */
+#define WM8994_WSEQ_EOS81_SHIFT 8 /* WSEQ_EOS81 */
+#define WM8994_WSEQ_EOS81_WIDTH 1 /* WSEQ_EOS81 */
+#define WM8994_WSEQ_DELAY81_MASK 0x000F /* WSEQ_DELAY81 - [3:0] */
+#define WM8994_WSEQ_DELAY81_SHIFT 0 /* WSEQ_DELAY81 - [3:0] */
+#define WM8994_WSEQ_DELAY81_WIDTH 4 /* WSEQ_DELAY81 - [3:0] */
+
+/*
+ * R12616 (0x3148) - Write Sequencer 328
+ */
+#define WM8994_WSEQ_ADDR82_MASK 0x3FFF /* WSEQ_ADDR82 - [13:0] */
+#define WM8994_WSEQ_ADDR82_SHIFT 0 /* WSEQ_ADDR82 - [13:0] */
+#define WM8994_WSEQ_ADDR82_WIDTH 14 /* WSEQ_ADDR82 - [13:0] */
+
+/*
+ * R12617 (0x3149) - Write Sequencer 329
+ */
+#define WM8994_WSEQ_DATA82_MASK 0x00FF /* WSEQ_DATA82 - [7:0] */
+#define WM8994_WSEQ_DATA82_SHIFT 0 /* WSEQ_DATA82 - [7:0] */
+#define WM8994_WSEQ_DATA82_WIDTH 8 /* WSEQ_DATA82 - [7:0] */
+
+/*
+ * R12618 (0x314A) - Write Sequencer 330
+ */
+#define WM8994_WSEQ_DATA_WIDTH82_MASK 0x0700 /* WSEQ_DATA_WIDTH82 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH82_SHIFT 8 /* WSEQ_DATA_WIDTH82 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH82_WIDTH 3 /* WSEQ_DATA_WIDTH82 - [10:8] */
+#define WM8994_WSEQ_DATA_START82_MASK 0x000F /* WSEQ_DATA_START82 - [3:0] */
+#define WM8994_WSEQ_DATA_START82_SHIFT 0 /* WSEQ_DATA_START82 - [3:0] */
+#define WM8994_WSEQ_DATA_START82_WIDTH 4 /* WSEQ_DATA_START82 - [3:0] */
+
+/*
+ * R12619 (0x314B) - Write Sequencer 331
+ */
+#define WM8994_WSEQ_EOS82 0x0100 /* WSEQ_EOS82 */
+#define WM8994_WSEQ_EOS82_MASK 0x0100 /* WSEQ_EOS82 */
+#define WM8994_WSEQ_EOS82_SHIFT 8 /* WSEQ_EOS82 */
+#define WM8994_WSEQ_EOS82_WIDTH 1 /* WSEQ_EOS82 */
+#define WM8994_WSEQ_DELAY82_MASK 0x000F /* WSEQ_DELAY82 - [3:0] */
+#define WM8994_WSEQ_DELAY82_SHIFT 0 /* WSEQ_DELAY82 - [3:0] */
+#define WM8994_WSEQ_DELAY82_WIDTH 4 /* WSEQ_DELAY82 - [3:0] */
+
+/*
+ * R12620 (0x314C) - Write Sequencer 332
+ */
+#define WM8994_WSEQ_ADDR83_MASK 0x3FFF /* WSEQ_ADDR83 - [13:0] */
+#define WM8994_WSEQ_ADDR83_SHIFT 0 /* WSEQ_ADDR83 - [13:0] */
+#define WM8994_WSEQ_ADDR83_WIDTH 14 /* WSEQ_ADDR83 - [13:0] */
+
+/*
+ * R12621 (0x314D) - Write Sequencer 333
+ */
+#define WM8994_WSEQ_DATA83_MASK 0x00FF /* WSEQ_DATA83 - [7:0] */
+#define WM8994_WSEQ_DATA83_SHIFT 0 /* WSEQ_DATA83 - [7:0] */
+#define WM8994_WSEQ_DATA83_WIDTH 8 /* WSEQ_DATA83 - [7:0] */
+
+/*
+ * R12622 (0x314E) - Write Sequencer 334
+ */
+#define WM8994_WSEQ_DATA_WIDTH83_MASK 0x0700 /* WSEQ_DATA_WIDTH83 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH83_SHIFT 8 /* WSEQ_DATA_WIDTH83 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH83_WIDTH 3 /* WSEQ_DATA_WIDTH83 - [10:8] */
+#define WM8994_WSEQ_DATA_START83_MASK 0x000F /* WSEQ_DATA_START83 - [3:0] */
+#define WM8994_WSEQ_DATA_START83_SHIFT 0 /* WSEQ_DATA_START83 - [3:0] */
+#define WM8994_WSEQ_DATA_START83_WIDTH 4 /* WSEQ_DATA_START83 - [3:0] */
+
+/*
+ * R12623 (0x314F) - Write Sequencer 335
+ */
+#define WM8994_WSEQ_EOS83 0x0100 /* WSEQ_EOS83 */
+#define WM8994_WSEQ_EOS83_MASK 0x0100 /* WSEQ_EOS83 */
+#define WM8994_WSEQ_EOS83_SHIFT 8 /* WSEQ_EOS83 */
+#define WM8994_WSEQ_EOS83_WIDTH 1 /* WSEQ_EOS83 */
+#define WM8994_WSEQ_DELAY83_MASK 0x000F /* WSEQ_DELAY83 - [3:0] */
+#define WM8994_WSEQ_DELAY83_SHIFT 0 /* WSEQ_DELAY83 - [3:0] */
+#define WM8994_WSEQ_DELAY83_WIDTH 4 /* WSEQ_DELAY83 - [3:0] */
+
+/*
+ * R12624 (0x3150) - Write Sequencer 336
+ */
+#define WM8994_WSEQ_ADDR84_MASK 0x3FFF /* WSEQ_ADDR84 - [13:0] */
+#define WM8994_WSEQ_ADDR84_SHIFT 0 /* WSEQ_ADDR84 - [13:0] */
+#define WM8994_WSEQ_ADDR84_WIDTH 14 /* WSEQ_ADDR84 - [13:0] */
+
+/*
+ * R12625 (0x3151) - Write Sequencer 337
+ */
+#define WM8994_WSEQ_DATA84_MASK 0x00FF /* WSEQ_DATA84 - [7:0] */
+#define WM8994_WSEQ_DATA84_SHIFT 0 /* WSEQ_DATA84 - [7:0] */
+#define WM8994_WSEQ_DATA84_WIDTH 8 /* WSEQ_DATA84 - [7:0] */
+
+/*
+ * R12626 (0x3152) - Write Sequencer 338
+ */
+#define WM8994_WSEQ_DATA_WIDTH84_MASK 0x0700 /* WSEQ_DATA_WIDTH84 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH84_SHIFT 8 /* WSEQ_DATA_WIDTH84 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH84_WIDTH 3 /* WSEQ_DATA_WIDTH84 - [10:8] */
+#define WM8994_WSEQ_DATA_START84_MASK 0x000F /* WSEQ_DATA_START84 - [3:0] */
+#define WM8994_WSEQ_DATA_START84_SHIFT 0 /* WSEQ_DATA_START84 - [3:0] */
+#define WM8994_WSEQ_DATA_START84_WIDTH 4 /* WSEQ_DATA_START84 - [3:0] */
+
+/*
+ * R12627 (0x3153) - Write Sequencer 339
+ */
+#define WM8994_WSEQ_EOS84 0x0100 /* WSEQ_EOS84 */
+#define WM8994_WSEQ_EOS84_MASK 0x0100 /* WSEQ_EOS84 */
+#define WM8994_WSEQ_EOS84_SHIFT 8 /* WSEQ_EOS84 */
+#define WM8994_WSEQ_EOS84_WIDTH 1 /* WSEQ_EOS84 */
+#define WM8994_WSEQ_DELAY84_MASK 0x000F /* WSEQ_DELAY84 - [3:0] */
+#define WM8994_WSEQ_DELAY84_SHIFT 0 /* WSEQ_DELAY84 - [3:0] */
+#define WM8994_WSEQ_DELAY84_WIDTH 4 /* WSEQ_DELAY84 - [3:0] */
+
+/*
+ * R12628 (0x3154) - Write Sequencer 340
+ */
+#define WM8994_WSEQ_ADDR85_MASK 0x3FFF /* WSEQ_ADDR85 - [13:0] */
+#define WM8994_WSEQ_ADDR85_SHIFT 0 /* WSEQ_ADDR85 - [13:0] */
+#define WM8994_WSEQ_ADDR85_WIDTH 14 /* WSEQ_ADDR85 - [13:0] */
+
+/*
+ * R12629 (0x3155) - Write Sequencer 341
+ */
+#define WM8994_WSEQ_DATA85_MASK 0x00FF /* WSEQ_DATA85 - [7:0] */
+#define WM8994_WSEQ_DATA85_SHIFT 0 /* WSEQ_DATA85 - [7:0] */
+#define WM8994_WSEQ_DATA85_WIDTH 8 /* WSEQ_DATA85 - [7:0] */
+
+/*
+ * R12630 (0x3156) - Write Sequencer 342
+ */
+#define WM8994_WSEQ_DATA_WIDTH85_MASK 0x0700 /* WSEQ_DATA_WIDTH85 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH85_SHIFT 8 /* WSEQ_DATA_WIDTH85 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH85_WIDTH 3 /* WSEQ_DATA_WIDTH85 - [10:8] */
+#define WM8994_WSEQ_DATA_START85_MASK 0x000F /* WSEQ_DATA_START85 - [3:0] */
+#define WM8994_WSEQ_DATA_START85_SHIFT 0 /* WSEQ_DATA_START85 - [3:0] */
+#define WM8994_WSEQ_DATA_START85_WIDTH 4 /* WSEQ_DATA_START85 - [3:0] */
+
+/*
+ * R12631 (0x3157) - Write Sequencer 343
+ */
+#define WM8994_WSEQ_EOS85 0x0100 /* WSEQ_EOS85 */
+#define WM8994_WSEQ_EOS85_MASK 0x0100 /* WSEQ_EOS85 */
+#define WM8994_WSEQ_EOS85_SHIFT 8 /* WSEQ_EOS85 */
+#define WM8994_WSEQ_EOS85_WIDTH 1 /* WSEQ_EOS85 */
+#define WM8994_WSEQ_DELAY85_MASK 0x000F /* WSEQ_DELAY85 - [3:0] */
+#define WM8994_WSEQ_DELAY85_SHIFT 0 /* WSEQ_DELAY85 - [3:0] */
+#define WM8994_WSEQ_DELAY85_WIDTH 4 /* WSEQ_DELAY85 - [3:0] */
+
+/*
+ * R12632 (0x3158) - Write Sequencer 344
+ */
+#define WM8994_WSEQ_ADDR86_MASK 0x3FFF /* WSEQ_ADDR86 - [13:0] */
+#define WM8994_WSEQ_ADDR86_SHIFT 0 /* WSEQ_ADDR86 - [13:0] */
+#define WM8994_WSEQ_ADDR86_WIDTH 14 /* WSEQ_ADDR86 - [13:0] */
+
+/*
+ * R12633 (0x3159) - Write Sequencer 345
+ */
+#define WM8994_WSEQ_DATA86_MASK 0x00FF /* WSEQ_DATA86 - [7:0] */
+#define WM8994_WSEQ_DATA86_SHIFT 0 /* WSEQ_DATA86 - [7:0] */
+#define WM8994_WSEQ_DATA86_WIDTH 8 /* WSEQ_DATA86 - [7:0] */
+
+/*
+ * R12634 (0x315A) - Write Sequencer 346
+ */
+#define WM8994_WSEQ_DATA_WIDTH86_MASK 0x0700 /* WSEQ_DATA_WIDTH86 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH86_SHIFT 8 /* WSEQ_DATA_WIDTH86 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH86_WIDTH 3 /* WSEQ_DATA_WIDTH86 - [10:8] */
+#define WM8994_WSEQ_DATA_START86_MASK 0x000F /* WSEQ_DATA_START86 - [3:0] */
+#define WM8994_WSEQ_DATA_START86_SHIFT 0 /* WSEQ_DATA_START86 - [3:0] */
+#define WM8994_WSEQ_DATA_START86_WIDTH 4 /* WSEQ_DATA_START86 - [3:0] */
+
+/*
+ * R12635 (0x315B) - Write Sequencer 347
+ */
+#define WM8994_WSEQ_EOS86 0x0100 /* WSEQ_EOS86 */
+#define WM8994_WSEQ_EOS86_MASK 0x0100 /* WSEQ_EOS86 */
+#define WM8994_WSEQ_EOS86_SHIFT 8 /* WSEQ_EOS86 */
+#define WM8994_WSEQ_EOS86_WIDTH 1 /* WSEQ_EOS86 */
+#define WM8994_WSEQ_DELAY86_MASK 0x000F /* WSEQ_DELAY86 - [3:0] */
+#define WM8994_WSEQ_DELAY86_SHIFT 0 /* WSEQ_DELAY86 - [3:0] */
+#define WM8994_WSEQ_DELAY86_WIDTH 4 /* WSEQ_DELAY86 - [3:0] */
+
+/*
+ * R12636 (0x315C) - Write Sequencer 348
+ */
+#define WM8994_WSEQ_ADDR87_MASK 0x3FFF /* WSEQ_ADDR87 - [13:0] */
+#define WM8994_WSEQ_ADDR87_SHIFT 0 /* WSEQ_ADDR87 - [13:0] */
+#define WM8994_WSEQ_ADDR87_WIDTH 14 /* WSEQ_ADDR87 - [13:0] */
+
+/*
+ * R12637 (0x315D) - Write Sequencer 349
+ */
+#define WM8994_WSEQ_DATA87_MASK 0x00FF /* WSEQ_DATA87 - [7:0] */
+#define WM8994_WSEQ_DATA87_SHIFT 0 /* WSEQ_DATA87 - [7:0] */
+#define WM8994_WSEQ_DATA87_WIDTH 8 /* WSEQ_DATA87 - [7:0] */
+
+/*
+ * R12638 (0x315E) - Write Sequencer 350
+ */
+#define WM8994_WSEQ_DATA_WIDTH87_MASK 0x0700 /* WSEQ_DATA_WIDTH87 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH87_SHIFT 8 /* WSEQ_DATA_WIDTH87 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH87_WIDTH 3 /* WSEQ_DATA_WIDTH87 - [10:8] */
+#define WM8994_WSEQ_DATA_START87_MASK 0x000F /* WSEQ_DATA_START87 - [3:0] */
+#define WM8994_WSEQ_DATA_START87_SHIFT 0 /* WSEQ_DATA_START87 - [3:0] */
+#define WM8994_WSEQ_DATA_START87_WIDTH 4 /* WSEQ_DATA_START87 - [3:0] */
+
+/*
+ * R12639 (0x315F) - Write Sequencer 351
+ */
+#define WM8994_WSEQ_EOS87 0x0100 /* WSEQ_EOS87 */
+#define WM8994_WSEQ_EOS87_MASK 0x0100 /* WSEQ_EOS87 */
+#define WM8994_WSEQ_EOS87_SHIFT 8 /* WSEQ_EOS87 */
+#define WM8994_WSEQ_EOS87_WIDTH 1 /* WSEQ_EOS87 */
+#define WM8994_WSEQ_DELAY87_MASK 0x000F /* WSEQ_DELAY87 - [3:0] */
+#define WM8994_WSEQ_DELAY87_SHIFT 0 /* WSEQ_DELAY87 - [3:0] */
+#define WM8994_WSEQ_DELAY87_WIDTH 4 /* WSEQ_DELAY87 - [3:0] */
+
+/*
+ * R12640 (0x3160) - Write Sequencer 352
+ */
+#define WM8994_WSEQ_ADDR88_MASK 0x3FFF /* WSEQ_ADDR88 - [13:0] */
+#define WM8994_WSEQ_ADDR88_SHIFT 0 /* WSEQ_ADDR88 - [13:0] */
+#define WM8994_WSEQ_ADDR88_WIDTH 14 /* WSEQ_ADDR88 - [13:0] */
+
+/*
+ * R12641 (0x3161) - Write Sequencer 353
+ */
+#define WM8994_WSEQ_DATA88_MASK 0x00FF /* WSEQ_DATA88 - [7:0] */
+#define WM8994_WSEQ_DATA88_SHIFT 0 /* WSEQ_DATA88 - [7:0] */
+#define WM8994_WSEQ_DATA88_WIDTH 8 /* WSEQ_DATA88 - [7:0] */
+
+/*
+ * R12642 (0x3162) - Write Sequencer 354
+ */
+#define WM8994_WSEQ_DATA_WIDTH88_MASK 0x0700 /* WSEQ_DATA_WIDTH88 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH88_SHIFT 8 /* WSEQ_DATA_WIDTH88 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH88_WIDTH 3 /* WSEQ_DATA_WIDTH88 - [10:8] */
+#define WM8994_WSEQ_DATA_START88_MASK 0x000F /* WSEQ_DATA_START88 - [3:0] */
+#define WM8994_WSEQ_DATA_START88_SHIFT 0 /* WSEQ_DATA_START88 - [3:0] */
+#define WM8994_WSEQ_DATA_START88_WIDTH 4 /* WSEQ_DATA_START88 - [3:0] */
+
+/*
+ * R12643 (0x3163) - Write Sequencer 355
+ */
+#define WM8994_WSEQ_EOS88 0x0100 /* WSEQ_EOS88 */
+#define WM8994_WSEQ_EOS88_MASK 0x0100 /* WSEQ_EOS88 */
+#define WM8994_WSEQ_EOS88_SHIFT 8 /* WSEQ_EOS88 */
+#define WM8994_WSEQ_EOS88_WIDTH 1 /* WSEQ_EOS88 */
+#define WM8994_WSEQ_DELAY88_MASK 0x000F /* WSEQ_DELAY88 - [3:0] */
+#define WM8994_WSEQ_DELAY88_SHIFT 0 /* WSEQ_DELAY88 - [3:0] */
+#define WM8994_WSEQ_DELAY88_WIDTH 4 /* WSEQ_DELAY88 - [3:0] */
+
+/*
+ * R12644 (0x3164) - Write Sequencer 356
+ */
+#define WM8994_WSEQ_ADDR89_MASK 0x3FFF /* WSEQ_ADDR89 - [13:0] */
+#define WM8994_WSEQ_ADDR89_SHIFT 0 /* WSEQ_ADDR89 - [13:0] */
+#define WM8994_WSEQ_ADDR89_WIDTH 14 /* WSEQ_ADDR89 - [13:0] */
+
+/*
+ * R12645 (0x3165) - Write Sequencer 357
+ */
+#define WM8994_WSEQ_DATA89_MASK 0x00FF /* WSEQ_DATA89 - [7:0] */
+#define WM8994_WSEQ_DATA89_SHIFT 0 /* WSEQ_DATA89 - [7:0] */
+#define WM8994_WSEQ_DATA89_WIDTH 8 /* WSEQ_DATA89 - [7:0] */
+
+/*
+ * R12646 (0x3166) - Write Sequencer 358
+ */
+#define WM8994_WSEQ_DATA_WIDTH89_MASK 0x0700 /* WSEQ_DATA_WIDTH89 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH89_SHIFT 8 /* WSEQ_DATA_WIDTH89 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH89_WIDTH 3 /* WSEQ_DATA_WIDTH89 - [10:8] */
+#define WM8994_WSEQ_DATA_START89_MASK 0x000F /* WSEQ_DATA_START89 - [3:0] */
+#define WM8994_WSEQ_DATA_START89_SHIFT 0 /* WSEQ_DATA_START89 - [3:0] */
+#define WM8994_WSEQ_DATA_START89_WIDTH 4 /* WSEQ_DATA_START89 - [3:0] */
+
+/*
+ * R12647 (0x3167) - Write Sequencer 359
+ */
+#define WM8994_WSEQ_EOS89 0x0100 /* WSEQ_EOS89 */
+#define WM8994_WSEQ_EOS89_MASK 0x0100 /* WSEQ_EOS89 */
+#define WM8994_WSEQ_EOS89_SHIFT 8 /* WSEQ_EOS89 */
+#define WM8994_WSEQ_EOS89_WIDTH 1 /* WSEQ_EOS89 */
+#define WM8994_WSEQ_DELAY89_MASK 0x000F /* WSEQ_DELAY89 - [3:0] */
+#define WM8994_WSEQ_DELAY89_SHIFT 0 /* WSEQ_DELAY89 - [3:0] */
+#define WM8994_WSEQ_DELAY89_WIDTH 4 /* WSEQ_DELAY89 - [3:0] */
+
+/*
+ * R12648 (0x3168) - Write Sequencer 360
+ */
+#define WM8994_WSEQ_ADDR90_MASK 0x3FFF /* WSEQ_ADDR90 - [13:0] */
+#define WM8994_WSEQ_ADDR90_SHIFT 0 /* WSEQ_ADDR90 - [13:0] */
+#define WM8994_WSEQ_ADDR90_WIDTH 14 /* WSEQ_ADDR90 - [13:0] */
+
+/*
+ * R12649 (0x3169) - Write Sequencer 361
+ */
+#define WM8994_WSEQ_DATA90_MASK 0x00FF /* WSEQ_DATA90 - [7:0] */
+#define WM8994_WSEQ_DATA90_SHIFT 0 /* WSEQ_DATA90 - [7:0] */
+#define WM8994_WSEQ_DATA90_WIDTH 8 /* WSEQ_DATA90 - [7:0] */
+
+/*
+ * R12650 (0x316A) - Write Sequencer 362
+ */
+#define WM8994_WSEQ_DATA_WIDTH90_MASK 0x0700 /* WSEQ_DATA_WIDTH90 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH90_SHIFT 8 /* WSEQ_DATA_WIDTH90 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH90_WIDTH 3 /* WSEQ_DATA_WIDTH90 - [10:8] */
+#define WM8994_WSEQ_DATA_START90_MASK 0x000F /* WSEQ_DATA_START90 - [3:0] */
+#define WM8994_WSEQ_DATA_START90_SHIFT 0 /* WSEQ_DATA_START90 - [3:0] */
+#define WM8994_WSEQ_DATA_START90_WIDTH 4 /* WSEQ_DATA_START90 - [3:0] */
+
+/*
+ * R12651 (0x316B) - Write Sequencer 363
+ */
+#define WM8994_WSEQ_EOS90 0x0100 /* WSEQ_EOS90 */
+#define WM8994_WSEQ_EOS90_MASK 0x0100 /* WSEQ_EOS90 */
+#define WM8994_WSEQ_EOS90_SHIFT 8 /* WSEQ_EOS90 */
+#define WM8994_WSEQ_EOS90_WIDTH 1 /* WSEQ_EOS90 */
+#define WM8994_WSEQ_DELAY90_MASK 0x000F /* WSEQ_DELAY90 - [3:0] */
+#define WM8994_WSEQ_DELAY90_SHIFT 0 /* WSEQ_DELAY90 - [3:0] */
+#define WM8994_WSEQ_DELAY90_WIDTH 4 /* WSEQ_DELAY90 - [3:0] */
+
+/*
+ * R12652 (0x316C) - Write Sequencer 364
+ */
+#define WM8994_WSEQ_ADDR91_MASK 0x3FFF /* WSEQ_ADDR91 - [13:0] */
+#define WM8994_WSEQ_ADDR91_SHIFT 0 /* WSEQ_ADDR91 - [13:0] */
+#define WM8994_WSEQ_ADDR91_WIDTH 14 /* WSEQ_ADDR91 - [13:0] */
+
+/*
+ * R12653 (0x316D) - Write Sequencer 365
+ */
+#define WM8994_WSEQ_DATA91_MASK 0x00FF /* WSEQ_DATA91 - [7:0] */
+#define WM8994_WSEQ_DATA91_SHIFT 0 /* WSEQ_DATA91 - [7:0] */
+#define WM8994_WSEQ_DATA91_WIDTH 8 /* WSEQ_DATA91 - [7:0] */
+
+/*
+ * R12654 (0x316E) - Write Sequencer 366
+ */
+#define WM8994_WSEQ_DATA_WIDTH91_MASK 0x0700 /* WSEQ_DATA_WIDTH91 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH91_SHIFT 8 /* WSEQ_DATA_WIDTH91 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH91_WIDTH 3 /* WSEQ_DATA_WIDTH91 - [10:8] */
+#define WM8994_WSEQ_DATA_START91_MASK 0x000F /* WSEQ_DATA_START91 - [3:0] */
+#define WM8994_WSEQ_DATA_START91_SHIFT 0 /* WSEQ_DATA_START91 - [3:0] */
+#define WM8994_WSEQ_DATA_START91_WIDTH 4 /* WSEQ_DATA_START91 - [3:0] */
+
+/*
+ * R12655 (0x316F) - Write Sequencer 367
+ */
+#define WM8994_WSEQ_EOS91 0x0100 /* WSEQ_EOS91 */
+#define WM8994_WSEQ_EOS91_MASK 0x0100 /* WSEQ_EOS91 */
+#define WM8994_WSEQ_EOS91_SHIFT 8 /* WSEQ_EOS91 */
+#define WM8994_WSEQ_EOS91_WIDTH 1 /* WSEQ_EOS91 */
+#define WM8994_WSEQ_DELAY91_MASK 0x000F /* WSEQ_DELAY91 - [3:0] */
+#define WM8994_WSEQ_DELAY91_SHIFT 0 /* WSEQ_DELAY91 - [3:0] */
+#define WM8994_WSEQ_DELAY91_WIDTH 4 /* WSEQ_DELAY91 - [3:0] */
+
+/*
+ * R12656 (0x3170) - Write Sequencer 368
+ */
+#define WM8994_WSEQ_ADDR92_MASK 0x3FFF /* WSEQ_ADDR92 - [13:0] */
+#define WM8994_WSEQ_ADDR92_SHIFT 0 /* WSEQ_ADDR92 - [13:0] */
+#define WM8994_WSEQ_ADDR92_WIDTH 14 /* WSEQ_ADDR92 - [13:0] */
+
+/*
+ * R12657 (0x3171) - Write Sequencer 369
+ */
+#define WM8994_WSEQ_DATA92_MASK 0x00FF /* WSEQ_DATA92 - [7:0] */
+#define WM8994_WSEQ_DATA92_SHIFT 0 /* WSEQ_DATA92 - [7:0] */
+#define WM8994_WSEQ_DATA92_WIDTH 8 /* WSEQ_DATA92 - [7:0] */
+
+/*
+ * R12658 (0x3172) - Write Sequencer 370
+ */
+#define WM8994_WSEQ_DATA_WIDTH92_MASK 0x0700 /* WSEQ_DATA_WIDTH92 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH92_SHIFT 8 /* WSEQ_DATA_WIDTH92 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH92_WIDTH 3 /* WSEQ_DATA_WIDTH92 - [10:8] */
+#define WM8994_WSEQ_DATA_START92_MASK 0x000F /* WSEQ_DATA_START92 - [3:0] */
+#define WM8994_WSEQ_DATA_START92_SHIFT 0 /* WSEQ_DATA_START92 - [3:0] */
+#define WM8994_WSEQ_DATA_START92_WIDTH 4 /* WSEQ_DATA_START92 - [3:0] */
+
+/*
+ * R12659 (0x3173) - Write Sequencer 371
+ */
+#define WM8994_WSEQ_EOS92 0x0100 /* WSEQ_EOS92 */
+#define WM8994_WSEQ_EOS92_MASK 0x0100 /* WSEQ_EOS92 */
+#define WM8994_WSEQ_EOS92_SHIFT 8 /* WSEQ_EOS92 */
+#define WM8994_WSEQ_EOS92_WIDTH 1 /* WSEQ_EOS92 */
+#define WM8994_WSEQ_DELAY92_MASK 0x000F /* WSEQ_DELAY92 - [3:0] */
+#define WM8994_WSEQ_DELAY92_SHIFT 0 /* WSEQ_DELAY92 - [3:0] */
+#define WM8994_WSEQ_DELAY92_WIDTH 4 /* WSEQ_DELAY92 - [3:0] */
+
+/*
+ * R12660 (0x3174) - Write Sequencer 372
+ */
+#define WM8994_WSEQ_ADDR93_MASK 0x3FFF /* WSEQ_ADDR93 - [13:0] */
+#define WM8994_WSEQ_ADDR93_SHIFT 0 /* WSEQ_ADDR93 - [13:0] */
+#define WM8994_WSEQ_ADDR93_WIDTH 14 /* WSEQ_ADDR93 - [13:0] */
+
+/*
+ * R12661 (0x3175) - Write Sequencer 373
+ */
+#define WM8994_WSEQ_DATA93_MASK 0x00FF /* WSEQ_DATA93 - [7:0] */
+#define WM8994_WSEQ_DATA93_SHIFT 0 /* WSEQ_DATA93 - [7:0] */
+#define WM8994_WSEQ_DATA93_WIDTH 8 /* WSEQ_DATA93 - [7:0] */
+
+/*
+ * R12662 (0x3176) - Write Sequencer 374
+ */
+#define WM8994_WSEQ_DATA_WIDTH93_MASK 0x0700 /* WSEQ_DATA_WIDTH93 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH93_SHIFT 8 /* WSEQ_DATA_WIDTH93 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH93_WIDTH 3 /* WSEQ_DATA_WIDTH93 - [10:8] */
+#define WM8994_WSEQ_DATA_START93_MASK 0x000F /* WSEQ_DATA_START93 - [3:0] */
+#define WM8994_WSEQ_DATA_START93_SHIFT 0 /* WSEQ_DATA_START93 - [3:0] */
+#define WM8994_WSEQ_DATA_START93_WIDTH 4 /* WSEQ_DATA_START93 - [3:0] */
+
+/*
+ * R12663 (0x3177) - Write Sequencer 375
+ */
+#define WM8994_WSEQ_EOS93 0x0100 /* WSEQ_EOS93 */
+#define WM8994_WSEQ_EOS93_MASK 0x0100 /* WSEQ_EOS93 */
+#define WM8994_WSEQ_EOS93_SHIFT 8 /* WSEQ_EOS93 */
+#define WM8994_WSEQ_EOS93_WIDTH 1 /* WSEQ_EOS93 */
+#define WM8994_WSEQ_DELAY93_MASK 0x000F /* WSEQ_DELAY93 - [3:0] */
+#define WM8994_WSEQ_DELAY93_SHIFT 0 /* WSEQ_DELAY93 - [3:0] */
+#define WM8994_WSEQ_DELAY93_WIDTH 4 /* WSEQ_DELAY93 - [3:0] */
+
+/*
+ * R12664 (0x3178) - Write Sequencer 376
+ */
+#define WM8994_WSEQ_ADDR94_MASK 0x3FFF /* WSEQ_ADDR94 - [13:0] */
+#define WM8994_WSEQ_ADDR94_SHIFT 0 /* WSEQ_ADDR94 - [13:0] */
+#define WM8994_WSEQ_ADDR94_WIDTH 14 /* WSEQ_ADDR94 - [13:0] */
+
+/*
+ * R12665 (0x3179) - Write Sequencer 377
+ */
+#define WM8994_WSEQ_DATA94_MASK 0x00FF /* WSEQ_DATA94 - [7:0] */
+#define WM8994_WSEQ_DATA94_SHIFT 0 /* WSEQ_DATA94 - [7:0] */
+#define WM8994_WSEQ_DATA94_WIDTH 8 /* WSEQ_DATA94 - [7:0] */
+
+/*
+ * R12666 (0x317A) - Write Sequencer 378
+ */
+#define WM8994_WSEQ_DATA_WIDTH94_MASK 0x0700 /* WSEQ_DATA_WIDTH94 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH94_SHIFT 8 /* WSEQ_DATA_WIDTH94 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH94_WIDTH 3 /* WSEQ_DATA_WIDTH94 - [10:8] */
+#define WM8994_WSEQ_DATA_START94_MASK 0x000F /* WSEQ_DATA_START94 - [3:0] */
+#define WM8994_WSEQ_DATA_START94_SHIFT 0 /* WSEQ_DATA_START94 - [3:0] */
+#define WM8994_WSEQ_DATA_START94_WIDTH 4 /* WSEQ_DATA_START94 - [3:0] */
+
+/*
+ * R12667 (0x317B) - Write Sequencer 379
+ */
+#define WM8994_WSEQ_EOS94 0x0100 /* WSEQ_EOS94 */
+#define WM8994_WSEQ_EOS94_MASK 0x0100 /* WSEQ_EOS94 */
+#define WM8994_WSEQ_EOS94_SHIFT 8 /* WSEQ_EOS94 */
+#define WM8994_WSEQ_EOS94_WIDTH 1 /* WSEQ_EOS94 */
+#define WM8994_WSEQ_DELAY94_MASK 0x000F /* WSEQ_DELAY94 - [3:0] */
+#define WM8994_WSEQ_DELAY94_SHIFT 0 /* WSEQ_DELAY94 - [3:0] */
+#define WM8994_WSEQ_DELAY94_WIDTH 4 /* WSEQ_DELAY94 - [3:0] */
+
+/*
+ * R12668 (0x317C) - Write Sequencer 380
+ */
+#define WM8994_WSEQ_ADDR95_MASK 0x3FFF /* WSEQ_ADDR95 - [13:0] */
+#define WM8994_WSEQ_ADDR95_SHIFT 0 /* WSEQ_ADDR95 - [13:0] */
+#define WM8994_WSEQ_ADDR95_WIDTH 14 /* WSEQ_ADDR95 - [13:0] */
+
+/*
+ * R12669 (0x317D) - Write Sequencer 381
+ */
+#define WM8994_WSEQ_DATA95_MASK 0x00FF /* WSEQ_DATA95 - [7:0] */
+#define WM8994_WSEQ_DATA95_SHIFT 0 /* WSEQ_DATA95 - [7:0] */
+#define WM8994_WSEQ_DATA95_WIDTH 8 /* WSEQ_DATA95 - [7:0] */
+
+/*
+ * R12670 (0x317E) - Write Sequencer 382
+ */
+#define WM8994_WSEQ_DATA_WIDTH95_MASK 0x0700 /* WSEQ_DATA_WIDTH95 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH95_SHIFT 8 /* WSEQ_DATA_WIDTH95 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH95_WIDTH 3 /* WSEQ_DATA_WIDTH95 - [10:8] */
+#define WM8994_WSEQ_DATA_START95_MASK 0x000F /* WSEQ_DATA_START95 - [3:0] */
+#define WM8994_WSEQ_DATA_START95_SHIFT 0 /* WSEQ_DATA_START95 - [3:0] */
+#define WM8994_WSEQ_DATA_START95_WIDTH 4 /* WSEQ_DATA_START95 - [3:0] */
+
+/*
+ * R12671 (0x317F) - Write Sequencer 383
+ */
+#define WM8994_WSEQ_EOS95 0x0100 /* WSEQ_EOS95 */
+#define WM8994_WSEQ_EOS95_MASK 0x0100 /* WSEQ_EOS95 */
+#define WM8994_WSEQ_EOS95_SHIFT 8 /* WSEQ_EOS95 */
+#define WM8994_WSEQ_EOS95_WIDTH 1 /* WSEQ_EOS95 */
+#define WM8994_WSEQ_DELAY95_MASK 0x000F /* WSEQ_DELAY95 - [3:0] */
+#define WM8994_WSEQ_DELAY95_SHIFT 0 /* WSEQ_DELAY95 - [3:0] */
+#define WM8994_WSEQ_DELAY95_WIDTH 4 /* WSEQ_DELAY95 - [3:0] */
+
+/*
+ * R12672 (0x3180) - Write Sequencer 384
+ */
+#define WM8994_WSEQ_ADDR96_MASK 0x3FFF /* WSEQ_ADDR96 - [13:0] */
+#define WM8994_WSEQ_ADDR96_SHIFT 0 /* WSEQ_ADDR96 - [13:0] */
+#define WM8994_WSEQ_ADDR96_WIDTH 14 /* WSEQ_ADDR96 - [13:0] */
+
+/*
+ * R12673 (0x3181) - Write Sequencer 385
+ */
+#define WM8994_WSEQ_DATA96_MASK 0x00FF /* WSEQ_DATA96 - [7:0] */
+#define WM8994_WSEQ_DATA96_SHIFT 0 /* WSEQ_DATA96 - [7:0] */
+#define WM8994_WSEQ_DATA96_WIDTH 8 /* WSEQ_DATA96 - [7:0] */
+
+/*
+ * R12674 (0x3182) - Write Sequencer 386
+ */
+#define WM8994_WSEQ_DATA_WIDTH96_MASK 0x0700 /* WSEQ_DATA_WIDTH96 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH96_SHIFT 8 /* WSEQ_DATA_WIDTH96 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH96_WIDTH 3 /* WSEQ_DATA_WIDTH96 - [10:8] */
+#define WM8994_WSEQ_DATA_START96_MASK 0x000F /* WSEQ_DATA_START96 - [3:0] */
+#define WM8994_WSEQ_DATA_START96_SHIFT 0 /* WSEQ_DATA_START96 - [3:0] */
+#define WM8994_WSEQ_DATA_START96_WIDTH 4 /* WSEQ_DATA_START96 - [3:0] */
+
+/*
+ * R12675 (0x3183) - Write Sequencer 387
+ */
+#define WM8994_WSEQ_EOS96 0x0100 /* WSEQ_EOS96 */
+#define WM8994_WSEQ_EOS96_MASK 0x0100 /* WSEQ_EOS96 */
+#define WM8994_WSEQ_EOS96_SHIFT 8 /* WSEQ_EOS96 */
+#define WM8994_WSEQ_EOS96_WIDTH 1 /* WSEQ_EOS96 */
+#define WM8994_WSEQ_DELAY96_MASK 0x000F /* WSEQ_DELAY96 - [3:0] */
+#define WM8994_WSEQ_DELAY96_SHIFT 0 /* WSEQ_DELAY96 - [3:0] */
+#define WM8994_WSEQ_DELAY96_WIDTH 4 /* WSEQ_DELAY96 - [3:0] */
+
+/*
+ * R12676 (0x3184) - Write Sequencer 388
+ */
+#define WM8994_WSEQ_ADDR97_MASK 0x3FFF /* WSEQ_ADDR97 - [13:0] */
+#define WM8994_WSEQ_ADDR97_SHIFT 0 /* WSEQ_ADDR97 - [13:0] */
+#define WM8994_WSEQ_ADDR97_WIDTH 14 /* WSEQ_ADDR97 - [13:0] */
+
+/*
+ * R12677 (0x3185) - Write Sequencer 389
+ */
+#define WM8994_WSEQ_DATA97_MASK 0x00FF /* WSEQ_DATA97 - [7:0] */
+#define WM8994_WSEQ_DATA97_SHIFT 0 /* WSEQ_DATA97 - [7:0] */
+#define WM8994_WSEQ_DATA97_WIDTH 8 /* WSEQ_DATA97 - [7:0] */
+
+/*
+ * R12678 (0x3186) - Write Sequencer 390
+ */
+#define WM8994_WSEQ_DATA_WIDTH97_MASK 0x0700 /* WSEQ_DATA_WIDTH97 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH97_SHIFT 8 /* WSEQ_DATA_WIDTH97 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH97_WIDTH 3 /* WSEQ_DATA_WIDTH97 - [10:8] */
+#define WM8994_WSEQ_DATA_START97_MASK 0x000F /* WSEQ_DATA_START97 - [3:0] */
+#define WM8994_WSEQ_DATA_START97_SHIFT 0 /* WSEQ_DATA_START97 - [3:0] */
+#define WM8994_WSEQ_DATA_START97_WIDTH 4 /* WSEQ_DATA_START97 - [3:0] */
+
+/*
+ * R12679 (0x3187) - Write Sequencer 391
+ */
+#define WM8994_WSEQ_EOS97 0x0100 /* WSEQ_EOS97 */
+#define WM8994_WSEQ_EOS97_MASK 0x0100 /* WSEQ_EOS97 */
+#define WM8994_WSEQ_EOS97_SHIFT 8 /* WSEQ_EOS97 */
+#define WM8994_WSEQ_EOS97_WIDTH 1 /* WSEQ_EOS97 */
+#define WM8994_WSEQ_DELAY97_MASK 0x000F /* WSEQ_DELAY97 - [3:0] */
+#define WM8994_WSEQ_DELAY97_SHIFT 0 /* WSEQ_DELAY97 - [3:0] */
+#define WM8994_WSEQ_DELAY97_WIDTH 4 /* WSEQ_DELAY97 - [3:0] */
+
+/*
+ * R12680 (0x3188) - Write Sequencer 392
+ */
+#define WM8994_WSEQ_ADDR98_MASK 0x3FFF /* WSEQ_ADDR98 - [13:0] */
+#define WM8994_WSEQ_ADDR98_SHIFT 0 /* WSEQ_ADDR98 - [13:0] */
+#define WM8994_WSEQ_ADDR98_WIDTH 14 /* WSEQ_ADDR98 - [13:0] */
+
+/*
+ * R12681 (0x3189) - Write Sequencer 393
+ */
+#define WM8994_WSEQ_DATA98_MASK 0x00FF /* WSEQ_DATA98 - [7:0] */
+#define WM8994_WSEQ_DATA98_SHIFT 0 /* WSEQ_DATA98 - [7:0] */
+#define WM8994_WSEQ_DATA98_WIDTH 8 /* WSEQ_DATA98 - [7:0] */
+
+/*
+ * R12682 (0x318A) - Write Sequencer 394
+ */
+#define WM8994_WSEQ_DATA_WIDTH98_MASK 0x0700 /* WSEQ_DATA_WIDTH98 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH98_SHIFT 8 /* WSEQ_DATA_WIDTH98 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH98_WIDTH 3 /* WSEQ_DATA_WIDTH98 - [10:8] */
+#define WM8994_WSEQ_DATA_START98_MASK 0x000F /* WSEQ_DATA_START98 - [3:0] */
+#define WM8994_WSEQ_DATA_START98_SHIFT 0 /* WSEQ_DATA_START98 - [3:0] */
+#define WM8994_WSEQ_DATA_START98_WIDTH 4 /* WSEQ_DATA_START98 - [3:0] */
+
+/*
+ * R12683 (0x318B) - Write Sequencer 395
+ */
+#define WM8994_WSEQ_EOS98 0x0100 /* WSEQ_EOS98 */
+#define WM8994_WSEQ_EOS98_MASK 0x0100 /* WSEQ_EOS98 */
+#define WM8994_WSEQ_EOS98_SHIFT 8 /* WSEQ_EOS98 */
+#define WM8994_WSEQ_EOS98_WIDTH 1 /* WSEQ_EOS98 */
+#define WM8994_WSEQ_DELAY98_MASK 0x000F /* WSEQ_DELAY98 - [3:0] */
+#define WM8994_WSEQ_DELAY98_SHIFT 0 /* WSEQ_DELAY98 - [3:0] */
+#define WM8994_WSEQ_DELAY98_WIDTH 4 /* WSEQ_DELAY98 - [3:0] */
+
+/*
+ * R12684 (0x318C) - Write Sequencer 396
+ */
+#define WM8994_WSEQ_ADDR99_MASK 0x3FFF /* WSEQ_ADDR99 - [13:0] */
+#define WM8994_WSEQ_ADDR99_SHIFT 0 /* WSEQ_ADDR99 - [13:0] */
+#define WM8994_WSEQ_ADDR99_WIDTH 14 /* WSEQ_ADDR99 - [13:0] */
+
+/*
+ * R12685 (0x318D) - Write Sequencer 397
+ */
+#define WM8994_WSEQ_DATA99_MASK 0x00FF /* WSEQ_DATA99 - [7:0] */
+#define WM8994_WSEQ_DATA99_SHIFT 0 /* WSEQ_DATA99 - [7:0] */
+#define WM8994_WSEQ_DATA99_WIDTH 8 /* WSEQ_DATA99 - [7:0] */
+
+/*
+ * R12686 (0x318E) - Write Sequencer 398
+ */
+#define WM8994_WSEQ_DATA_WIDTH99_MASK 0x0700 /* WSEQ_DATA_WIDTH99 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH99_SHIFT 8 /* WSEQ_DATA_WIDTH99 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH99_WIDTH 3 /* WSEQ_DATA_WIDTH99 - [10:8] */
+#define WM8994_WSEQ_DATA_START99_MASK 0x000F /* WSEQ_DATA_START99 - [3:0] */
+#define WM8994_WSEQ_DATA_START99_SHIFT 0 /* WSEQ_DATA_START99 - [3:0] */
+#define WM8994_WSEQ_DATA_START99_WIDTH 4 /* WSEQ_DATA_START99 - [3:0] */
+
+/*
+ * R12687 (0x318F) - Write Sequencer 399
+ */
+#define WM8994_WSEQ_EOS99 0x0100 /* WSEQ_EOS99 */
+#define WM8994_WSEQ_EOS99_MASK 0x0100 /* WSEQ_EOS99 */
+#define WM8994_WSEQ_EOS99_SHIFT 8 /* WSEQ_EOS99 */
+#define WM8994_WSEQ_EOS99_WIDTH 1 /* WSEQ_EOS99 */
+#define WM8994_WSEQ_DELAY99_MASK 0x000F /* WSEQ_DELAY99 - [3:0] */
+#define WM8994_WSEQ_DELAY99_SHIFT 0 /* WSEQ_DELAY99 - [3:0] */
+#define WM8994_WSEQ_DELAY99_WIDTH 4 /* WSEQ_DELAY99 - [3:0] */
+
+/*
+ * R12688 (0x3190) - Write Sequencer 400
+ */
+#define WM8994_WSEQ_ADDR100_MASK 0x3FFF /* WSEQ_ADDR100 - [13:0] */
+#define WM8994_WSEQ_ADDR100_SHIFT 0 /* WSEQ_ADDR100 - [13:0] */
+#define WM8994_WSEQ_ADDR100_WIDTH 14 /* WSEQ_ADDR100 - [13:0] */
+
+/*
+ * R12689 (0x3191) - Write Sequencer 401
+ */
+#define WM8994_WSEQ_DATA100_MASK 0x00FF /* WSEQ_DATA100 - [7:0] */
+#define WM8994_WSEQ_DATA100_SHIFT 0 /* WSEQ_DATA100 - [7:0] */
+#define WM8994_WSEQ_DATA100_WIDTH 8 /* WSEQ_DATA100 - [7:0] */
+
+/*
+ * R12690 (0x3192) - Write Sequencer 402
+ */
+#define WM8994_WSEQ_DATA_WIDTH100_MASK 0x0700 /* WSEQ_DATA_WIDTH100 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH100_SHIFT 8 /* WSEQ_DATA_WIDTH100 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH100_WIDTH 3 /* WSEQ_DATA_WIDTH100 - [10:8] */
+#define WM8994_WSEQ_DATA_START100_MASK 0x000F /* WSEQ_DATA_START100 - [3:0] */
+#define WM8994_WSEQ_DATA_START100_SHIFT 0 /* WSEQ_DATA_START100 - [3:0] */
+#define WM8994_WSEQ_DATA_START100_WIDTH 4 /* WSEQ_DATA_START100 - [3:0] */
+
+/*
+ * R12691 (0x3193) - Write Sequencer 403
+ */
+#define WM8994_WSEQ_EOS100 0x0100 /* WSEQ_EOS100 */
+#define WM8994_WSEQ_EOS100_MASK 0x0100 /* WSEQ_EOS100 */
+#define WM8994_WSEQ_EOS100_SHIFT 8 /* WSEQ_EOS100 */
+#define WM8994_WSEQ_EOS100_WIDTH 1 /* WSEQ_EOS100 */
+#define WM8994_WSEQ_DELAY100_MASK 0x000F /* WSEQ_DELAY100 - [3:0] */
+#define WM8994_WSEQ_DELAY100_SHIFT 0 /* WSEQ_DELAY100 - [3:0] */
+#define WM8994_WSEQ_DELAY100_WIDTH 4 /* WSEQ_DELAY100 - [3:0] */
+
+/*
+ * R12692 (0x3194) - Write Sequencer 404
+ */
+#define WM8994_WSEQ_ADDR101_MASK 0x3FFF /* WSEQ_ADDR101 - [13:0] */
+#define WM8994_WSEQ_ADDR101_SHIFT 0 /* WSEQ_ADDR101 - [13:0] */
+#define WM8994_WSEQ_ADDR101_WIDTH 14 /* WSEQ_ADDR101 - [13:0] */
+
+/*
+ * R12693 (0x3195) - Write Sequencer 405
+ */
+#define WM8994_WSEQ_DATA101_MASK 0x00FF /* WSEQ_DATA101 - [7:0] */
+#define WM8994_WSEQ_DATA101_SHIFT 0 /* WSEQ_DATA101 - [7:0] */
+#define WM8994_WSEQ_DATA101_WIDTH 8 /* WSEQ_DATA101 - [7:0] */
+
+/*
+ * R12694 (0x3196) - Write Sequencer 406
+ */
+#define WM8994_WSEQ_DATA_WIDTH101_MASK 0x0700 /* WSEQ_DATA_WIDTH101 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH101_SHIFT 8 /* WSEQ_DATA_WIDTH101 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH101_WIDTH 3 /* WSEQ_DATA_WIDTH101 - [10:8] */
+#define WM8994_WSEQ_DATA_START101_MASK 0x000F /* WSEQ_DATA_START101 - [3:0] */
+#define WM8994_WSEQ_DATA_START101_SHIFT 0 /* WSEQ_DATA_START101 - [3:0] */
+#define WM8994_WSEQ_DATA_START101_WIDTH 4 /* WSEQ_DATA_START101 - [3:0] */
+
+/*
+ * R12695 (0x3197) - Write Sequencer 407
+ */
+#define WM8994_WSEQ_EOS101 0x0100 /* WSEQ_EOS101 */
+#define WM8994_WSEQ_EOS101_MASK 0x0100 /* WSEQ_EOS101 */
+#define WM8994_WSEQ_EOS101_SHIFT 8 /* WSEQ_EOS101 */
+#define WM8994_WSEQ_EOS101_WIDTH 1 /* WSEQ_EOS101 */
+#define WM8994_WSEQ_DELAY101_MASK 0x000F /* WSEQ_DELAY101 - [3:0] */
+#define WM8994_WSEQ_DELAY101_SHIFT 0 /* WSEQ_DELAY101 - [3:0] */
+#define WM8994_WSEQ_DELAY101_WIDTH 4 /* WSEQ_DELAY101 - [3:0] */
+
+/*
+ * R12696 (0x3198) - Write Sequencer 408
+ */
+#define WM8994_WSEQ_ADDR102_MASK 0x3FFF /* WSEQ_ADDR102 - [13:0] */
+#define WM8994_WSEQ_ADDR102_SHIFT 0 /* WSEQ_ADDR102 - [13:0] */
+#define WM8994_WSEQ_ADDR102_WIDTH 14 /* WSEQ_ADDR102 - [13:0] */
+
+/*
+ * R12697 (0x3199) - Write Sequencer 409
+ */
+#define WM8994_WSEQ_DATA102_MASK 0x00FF /* WSEQ_DATA102 - [7:0] */
+#define WM8994_WSEQ_DATA102_SHIFT 0 /* WSEQ_DATA102 - [7:0] */
+#define WM8994_WSEQ_DATA102_WIDTH 8 /* WSEQ_DATA102 - [7:0] */
+
+/*
+ * R12698 (0x319A) - Write Sequencer 410
+ */
+#define WM8994_WSEQ_DATA_WIDTH102_MASK 0x0700 /* WSEQ_DATA_WIDTH102 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH102_SHIFT 8 /* WSEQ_DATA_WIDTH102 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH102_WIDTH 3 /* WSEQ_DATA_WIDTH102 - [10:8] */
+#define WM8994_WSEQ_DATA_START102_MASK 0x000F /* WSEQ_DATA_START102 - [3:0] */
+#define WM8994_WSEQ_DATA_START102_SHIFT 0 /* WSEQ_DATA_START102 - [3:0] */
+#define WM8994_WSEQ_DATA_START102_WIDTH 4 /* WSEQ_DATA_START102 - [3:0] */
+
+/*
+ * R12699 (0x319B) - Write Sequencer 411
+ */
+#define WM8994_WSEQ_EOS102 0x0100 /* WSEQ_EOS102 */
+#define WM8994_WSEQ_EOS102_MASK 0x0100 /* WSEQ_EOS102 */
+#define WM8994_WSEQ_EOS102_SHIFT 8 /* WSEQ_EOS102 */
+#define WM8994_WSEQ_EOS102_WIDTH 1 /* WSEQ_EOS102 */
+#define WM8994_WSEQ_DELAY102_MASK 0x000F /* WSEQ_DELAY102 - [3:0] */
+#define WM8994_WSEQ_DELAY102_SHIFT 0 /* WSEQ_DELAY102 - [3:0] */
+#define WM8994_WSEQ_DELAY102_WIDTH 4 /* WSEQ_DELAY102 - [3:0] */
+
+/*
+ * R12700 (0x319C) - Write Sequencer 412
+ */
+#define WM8994_WSEQ_ADDR103_MASK 0x3FFF /* WSEQ_ADDR103 - [13:0] */
+#define WM8994_WSEQ_ADDR103_SHIFT 0 /* WSEQ_ADDR103 - [13:0] */
+#define WM8994_WSEQ_ADDR103_WIDTH 14 /* WSEQ_ADDR103 - [13:0] */
+
+/*
+ * R12701 (0x319D) - Write Sequencer 413
+ */
+#define WM8994_WSEQ_DATA103_MASK 0x00FF /* WSEQ_DATA103 - [7:0] */
+#define WM8994_WSEQ_DATA103_SHIFT 0 /* WSEQ_DATA103 - [7:0] */
+#define WM8994_WSEQ_DATA103_WIDTH 8 /* WSEQ_DATA103 - [7:0] */
+
+/*
+ * R12702 (0x319E) - Write Sequencer 414
+ */
+#define WM8994_WSEQ_DATA_WIDTH103_MASK 0x0700 /* WSEQ_DATA_WIDTH103 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH103_SHIFT 8 /* WSEQ_DATA_WIDTH103 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH103_WIDTH 3 /* WSEQ_DATA_WIDTH103 - [10:8] */
+#define WM8994_WSEQ_DATA_START103_MASK 0x000F /* WSEQ_DATA_START103 - [3:0] */
+#define WM8994_WSEQ_DATA_START103_SHIFT 0 /* WSEQ_DATA_START103 - [3:0] */
+#define WM8994_WSEQ_DATA_START103_WIDTH 4 /* WSEQ_DATA_START103 - [3:0] */
+
+/*
+ * R12703 (0x319F) - Write Sequencer 415
+ */
+#define WM8994_WSEQ_EOS103 0x0100 /* WSEQ_EOS103 */
+#define WM8994_WSEQ_EOS103_MASK 0x0100 /* WSEQ_EOS103 */
+#define WM8994_WSEQ_EOS103_SHIFT 8 /* WSEQ_EOS103 */
+#define WM8994_WSEQ_EOS103_WIDTH 1 /* WSEQ_EOS103 */
+#define WM8994_WSEQ_DELAY103_MASK 0x000F /* WSEQ_DELAY103 - [3:0] */
+#define WM8994_WSEQ_DELAY103_SHIFT 0 /* WSEQ_DELAY103 - [3:0] */
+#define WM8994_WSEQ_DELAY103_WIDTH 4 /* WSEQ_DELAY103 - [3:0] */
+
+/*
+ * R12704 (0x31A0) - Write Sequencer 416
+ */
+#define WM8994_WSEQ_ADDR104_MASK 0x3FFF /* WSEQ_ADDR104 - [13:0] */
+#define WM8994_WSEQ_ADDR104_SHIFT 0 /* WSEQ_ADDR104 - [13:0] */
+#define WM8994_WSEQ_ADDR104_WIDTH 14 /* WSEQ_ADDR104 - [13:0] */
+
+/*
+ * R12705 (0x31A1) - Write Sequencer 417
+ */
+#define WM8994_WSEQ_DATA104_MASK 0x00FF /* WSEQ_DATA104 - [7:0] */
+#define WM8994_WSEQ_DATA104_SHIFT 0 /* WSEQ_DATA104 - [7:0] */
+#define WM8994_WSEQ_DATA104_WIDTH 8 /* WSEQ_DATA104 - [7:0] */
+
+/*
+ * R12706 (0x31A2) - Write Sequencer 418
+ */
+#define WM8994_WSEQ_DATA_WIDTH104_MASK 0x0700 /* WSEQ_DATA_WIDTH104 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH104_SHIFT 8 /* WSEQ_DATA_WIDTH104 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH104_WIDTH 3 /* WSEQ_DATA_WIDTH104 - [10:8] */
+#define WM8994_WSEQ_DATA_START104_MASK 0x000F /* WSEQ_DATA_START104 - [3:0] */
+#define WM8994_WSEQ_DATA_START104_SHIFT 0 /* WSEQ_DATA_START104 - [3:0] */
+#define WM8994_WSEQ_DATA_START104_WIDTH 4 /* WSEQ_DATA_START104 - [3:0] */
+
+/*
+ * R12707 (0x31A3) - Write Sequencer 419
+ */
+#define WM8994_WSEQ_EOS104 0x0100 /* WSEQ_EOS104 */
+#define WM8994_WSEQ_EOS104_MASK 0x0100 /* WSEQ_EOS104 */
+#define WM8994_WSEQ_EOS104_SHIFT 8 /* WSEQ_EOS104 */
+#define WM8994_WSEQ_EOS104_WIDTH 1 /* WSEQ_EOS104 */
+#define WM8994_WSEQ_DELAY104_MASK 0x000F /* WSEQ_DELAY104 - [3:0] */
+#define WM8994_WSEQ_DELAY104_SHIFT 0 /* WSEQ_DELAY104 - [3:0] */
+#define WM8994_WSEQ_DELAY104_WIDTH 4 /* WSEQ_DELAY104 - [3:0] */
+
+/*
+ * R12708 (0x31A4) - Write Sequencer 420
+ */
+#define WM8994_WSEQ_ADDR105_MASK 0x3FFF /* WSEQ_ADDR105 - [13:0] */
+#define WM8994_WSEQ_ADDR105_SHIFT 0 /* WSEQ_ADDR105 - [13:0] */
+#define WM8994_WSEQ_ADDR105_WIDTH 14 /* WSEQ_ADDR105 - [13:0] */
+
+/*
+ * R12709 (0x31A5) - Write Sequencer 421
+ */
+#define WM8994_WSEQ_DATA105_MASK 0x00FF /* WSEQ_DATA105 - [7:0] */
+#define WM8994_WSEQ_DATA105_SHIFT 0 /* WSEQ_DATA105 - [7:0] */
+#define WM8994_WSEQ_DATA105_WIDTH 8 /* WSEQ_DATA105 - [7:0] */
+
+/*
+ * R12710 (0x31A6) - Write Sequencer 422
+ */
+#define WM8994_WSEQ_DATA_WIDTH105_MASK 0x0700 /* WSEQ_DATA_WIDTH105 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH105_SHIFT 8 /* WSEQ_DATA_WIDTH105 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH105_WIDTH 3 /* WSEQ_DATA_WIDTH105 - [10:8] */
+#define WM8994_WSEQ_DATA_START105_MASK 0x000F /* WSEQ_DATA_START105 - [3:0] */
+#define WM8994_WSEQ_DATA_START105_SHIFT 0 /* WSEQ_DATA_START105 - [3:0] */
+#define WM8994_WSEQ_DATA_START105_WIDTH 4 /* WSEQ_DATA_START105 - [3:0] */
+
+/*
+ * R12711 (0x31A7) - Write Sequencer 423
+ */
+#define WM8994_WSEQ_EOS105 0x0100 /* WSEQ_EOS105 */
+#define WM8994_WSEQ_EOS105_MASK 0x0100 /* WSEQ_EOS105 */
+#define WM8994_WSEQ_EOS105_SHIFT 8 /* WSEQ_EOS105 */
+#define WM8994_WSEQ_EOS105_WIDTH 1 /* WSEQ_EOS105 */
+#define WM8994_WSEQ_DELAY105_MASK 0x000F /* WSEQ_DELAY105 - [3:0] */
+#define WM8994_WSEQ_DELAY105_SHIFT 0 /* WSEQ_DELAY105 - [3:0] */
+#define WM8994_WSEQ_DELAY105_WIDTH 4 /* WSEQ_DELAY105 - [3:0] */
+
+/*
+ * R12712 (0x31A8) - Write Sequencer 424
+ */
+#define WM8994_WSEQ_ADDR106_MASK 0x3FFF /* WSEQ_ADDR106 - [13:0] */
+#define WM8994_WSEQ_ADDR106_SHIFT 0 /* WSEQ_ADDR106 - [13:0] */
+#define WM8994_WSEQ_ADDR106_WIDTH 14 /* WSEQ_ADDR106 - [13:0] */
+
+/*
+ * R12713 (0x31A9) - Write Sequencer 425
+ */
+#define WM8994_WSEQ_DATA106_MASK 0x00FF /* WSEQ_DATA106 - [7:0] */
+#define WM8994_WSEQ_DATA106_SHIFT 0 /* WSEQ_DATA106 - [7:0] */
+#define WM8994_WSEQ_DATA106_WIDTH 8 /* WSEQ_DATA106 - [7:0] */
+
+/*
+ * R12714 (0x31AA) - Write Sequencer 426
+ */
+#define WM8994_WSEQ_DATA_WIDTH106_MASK 0x0700 /* WSEQ_DATA_WIDTH106 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH106_SHIFT 8 /* WSEQ_DATA_WIDTH106 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH106_WIDTH 3 /* WSEQ_DATA_WIDTH106 - [10:8] */
+#define WM8994_WSEQ_DATA_START106_MASK 0x000F /* WSEQ_DATA_START106 - [3:0] */
+#define WM8994_WSEQ_DATA_START106_SHIFT 0 /* WSEQ_DATA_START106 - [3:0] */
+#define WM8994_WSEQ_DATA_START106_WIDTH 4 /* WSEQ_DATA_START106 - [3:0] */
+
+/*
+ * R12715 (0x31AB) - Write Sequencer 427
+ */
+#define WM8994_WSEQ_EOS106 0x0100 /* WSEQ_EOS106 */
+#define WM8994_WSEQ_EOS106_MASK 0x0100 /* WSEQ_EOS106 */
+#define WM8994_WSEQ_EOS106_SHIFT 8 /* WSEQ_EOS106 */
+#define WM8994_WSEQ_EOS106_WIDTH 1 /* WSEQ_EOS106 */
+#define WM8994_WSEQ_DELAY106_MASK 0x000F /* WSEQ_DELAY106 - [3:0] */
+#define WM8994_WSEQ_DELAY106_SHIFT 0 /* WSEQ_DELAY106 - [3:0] */
+#define WM8994_WSEQ_DELAY106_WIDTH 4 /* WSEQ_DELAY106 - [3:0] */
+
+/*
+ * R12716 (0x31AC) - Write Sequencer 428
+ */
+#define WM8994_WSEQ_ADDR107_MASK 0x3FFF /* WSEQ_ADDR107 - [13:0] */
+#define WM8994_WSEQ_ADDR107_SHIFT 0 /* WSEQ_ADDR107 - [13:0] */
+#define WM8994_WSEQ_ADDR107_WIDTH 14 /* WSEQ_ADDR107 - [13:0] */
+
+/*
+ * R12717 (0x31AD) - Write Sequencer 429
+ */
+#define WM8994_WSEQ_DATA107_MASK 0x00FF /* WSEQ_DATA107 - [7:0] */
+#define WM8994_WSEQ_DATA107_SHIFT 0 /* WSEQ_DATA107 - [7:0] */
+#define WM8994_WSEQ_DATA107_WIDTH 8 /* WSEQ_DATA107 - [7:0] */
+
+/*
+ * R12718 (0x31AE) - Write Sequencer 430
+ */
+#define WM8994_WSEQ_DATA_WIDTH107_MASK 0x0700 /* WSEQ_DATA_WIDTH107 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH107_SHIFT 8 /* WSEQ_DATA_WIDTH107 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH107_WIDTH 3 /* WSEQ_DATA_WIDTH107 - [10:8] */
+#define WM8994_WSEQ_DATA_START107_MASK 0x000F /* WSEQ_DATA_START107 - [3:0] */
+#define WM8994_WSEQ_DATA_START107_SHIFT 0 /* WSEQ_DATA_START107 - [3:0] */
+#define WM8994_WSEQ_DATA_START107_WIDTH 4 /* WSEQ_DATA_START107 - [3:0] */
+
+/*
+ * R12719 (0x31AF) - Write Sequencer 431
+ */
+#define WM8994_WSEQ_EOS107 0x0100 /* WSEQ_EOS107 */
+#define WM8994_WSEQ_EOS107_MASK 0x0100 /* WSEQ_EOS107 */
+#define WM8994_WSEQ_EOS107_SHIFT 8 /* WSEQ_EOS107 */
+#define WM8994_WSEQ_EOS107_WIDTH 1 /* WSEQ_EOS107 */
+#define WM8994_WSEQ_DELAY107_MASK 0x000F /* WSEQ_DELAY107 - [3:0] */
+#define WM8994_WSEQ_DELAY107_SHIFT 0 /* WSEQ_DELAY107 - [3:0] */
+#define WM8994_WSEQ_DELAY107_WIDTH 4 /* WSEQ_DELAY107 - [3:0] */
+
+/*
+ * R12720 (0x31B0) - Write Sequencer 432
+ */
+#define WM8994_WSEQ_ADDR108_MASK 0x3FFF /* WSEQ_ADDR108 - [13:0] */
+#define WM8994_WSEQ_ADDR108_SHIFT 0 /* WSEQ_ADDR108 - [13:0] */
+#define WM8994_WSEQ_ADDR108_WIDTH 14 /* WSEQ_ADDR108 - [13:0] */
+
+/*
+ * R12721 (0x31B1) - Write Sequencer 433
+ */
+#define WM8994_WSEQ_DATA108_MASK 0x00FF /* WSEQ_DATA108 - [7:0] */
+#define WM8994_WSEQ_DATA108_SHIFT 0 /* WSEQ_DATA108 - [7:0] */
+#define WM8994_WSEQ_DATA108_WIDTH 8 /* WSEQ_DATA108 - [7:0] */
+
+/*
+ * R12722 (0x31B2) - Write Sequencer 434
+ */
+#define WM8994_WSEQ_DATA_WIDTH108_MASK 0x0700 /* WSEQ_DATA_WIDTH108 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH108_SHIFT 8 /* WSEQ_DATA_WIDTH108 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH108_WIDTH 3 /* WSEQ_DATA_WIDTH108 - [10:8] */
+#define WM8994_WSEQ_DATA_START108_MASK 0x000F /* WSEQ_DATA_START108 - [3:0] */
+#define WM8994_WSEQ_DATA_START108_SHIFT 0 /* WSEQ_DATA_START108 - [3:0] */
+#define WM8994_WSEQ_DATA_START108_WIDTH 4 /* WSEQ_DATA_START108 - [3:0] */
+
+/*
+ * R12723 (0x31B3) - Write Sequencer 435
+ */
+#define WM8994_WSEQ_EOS108 0x0100 /* WSEQ_EOS108 */
+#define WM8994_WSEQ_EOS108_MASK 0x0100 /* WSEQ_EOS108 */
+#define WM8994_WSEQ_EOS108_SHIFT 8 /* WSEQ_EOS108 */
+#define WM8994_WSEQ_EOS108_WIDTH 1 /* WSEQ_EOS108 */
+#define WM8994_WSEQ_DELAY108_MASK 0x000F /* WSEQ_DELAY108 - [3:0] */
+#define WM8994_WSEQ_DELAY108_SHIFT 0 /* WSEQ_DELAY108 - [3:0] */
+#define WM8994_WSEQ_DELAY108_WIDTH 4 /* WSEQ_DELAY108 - [3:0] */
+
+/*
+ * R12724 (0x31B4) - Write Sequencer 436
+ */
+#define WM8994_WSEQ_ADDR109_MASK 0x3FFF /* WSEQ_ADDR109 - [13:0] */
+#define WM8994_WSEQ_ADDR109_SHIFT 0 /* WSEQ_ADDR109 - [13:0] */
+#define WM8994_WSEQ_ADDR109_WIDTH 14 /* WSEQ_ADDR109 - [13:0] */
+
+/*
+ * R12725 (0x31B5) - Write Sequencer 437
+ */
+#define WM8994_WSEQ_DATA109_MASK 0x00FF /* WSEQ_DATA109 - [7:0] */
+#define WM8994_WSEQ_DATA109_SHIFT 0 /* WSEQ_DATA109 - [7:0] */
+#define WM8994_WSEQ_DATA109_WIDTH 8 /* WSEQ_DATA109 - [7:0] */
+
+/*
+ * R12726 (0x31B6) - Write Sequencer 438
+ */
+#define WM8994_WSEQ_DATA_WIDTH109_MASK 0x0700 /* WSEQ_DATA_WIDTH109 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH109_SHIFT 8 /* WSEQ_DATA_WIDTH109 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH109_WIDTH 3 /* WSEQ_DATA_WIDTH109 - [10:8] */
+#define WM8994_WSEQ_DATA_START109_MASK 0x000F /* WSEQ_DATA_START109 - [3:0] */
+#define WM8994_WSEQ_DATA_START109_SHIFT 0 /* WSEQ_DATA_START109 - [3:0] */
+#define WM8994_WSEQ_DATA_START109_WIDTH 4 /* WSEQ_DATA_START109 - [3:0] */
+
+/*
+ * R12727 (0x31B7) - Write Sequencer 439
+ */
+#define WM8994_WSEQ_EOS109 0x0100 /* WSEQ_EOS109 */
+#define WM8994_WSEQ_EOS109_MASK 0x0100 /* WSEQ_EOS109 */
+#define WM8994_WSEQ_EOS109_SHIFT 8 /* WSEQ_EOS109 */
+#define WM8994_WSEQ_EOS109_WIDTH 1 /* WSEQ_EOS109 */
+#define WM8994_WSEQ_DELAY109_MASK 0x000F /* WSEQ_DELAY109 - [3:0] */
+#define WM8994_WSEQ_DELAY109_SHIFT 0 /* WSEQ_DELAY109 - [3:0] */
+#define WM8994_WSEQ_DELAY109_WIDTH 4 /* WSEQ_DELAY109 - [3:0] */
+
+/*
+ * R12728 (0x31B8) - Write Sequencer 440
+ */
+#define WM8994_WSEQ_ADDR110_MASK 0x3FFF /* WSEQ_ADDR110 - [13:0] */
+#define WM8994_WSEQ_ADDR110_SHIFT 0 /* WSEQ_ADDR110 - [13:0] */
+#define WM8994_WSEQ_ADDR110_WIDTH 14 /* WSEQ_ADDR110 - [13:0] */
+
+/*
+ * R12729 (0x31B9) - Write Sequencer 441
+ */
+#define WM8994_WSEQ_DATA110_MASK 0x00FF /* WSEQ_DATA110 - [7:0] */
+#define WM8994_WSEQ_DATA110_SHIFT 0 /* WSEQ_DATA110 - [7:0] */
+#define WM8994_WSEQ_DATA110_WIDTH 8 /* WSEQ_DATA110 - [7:0] */
+
+/*
+ * R12730 (0x31BA) - Write Sequencer 442
+ */
+#define WM8994_WSEQ_DATA_WIDTH110_MASK 0x0700 /* WSEQ_DATA_WIDTH110 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH110_SHIFT 8 /* WSEQ_DATA_WIDTH110 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH110_WIDTH 3 /* WSEQ_DATA_WIDTH110 - [10:8] */
+#define WM8994_WSEQ_DATA_START110_MASK 0x000F /* WSEQ_DATA_START110 - [3:0] */
+#define WM8994_WSEQ_DATA_START110_SHIFT 0 /* WSEQ_DATA_START110 - [3:0] */
+#define WM8994_WSEQ_DATA_START110_WIDTH 4 /* WSEQ_DATA_START110 - [3:0] */
+
+/*
+ * R12731 (0x31BB) - Write Sequencer 443
+ */
+#define WM8994_WSEQ_EOS110 0x0100 /* WSEQ_EOS110 */
+#define WM8994_WSEQ_EOS110_MASK 0x0100 /* WSEQ_EOS110 */
+#define WM8994_WSEQ_EOS110_SHIFT 8 /* WSEQ_EOS110 */
+#define WM8994_WSEQ_EOS110_WIDTH 1 /* WSEQ_EOS110 */
+#define WM8994_WSEQ_DELAY110_MASK 0x000F /* WSEQ_DELAY110 - [3:0] */
+#define WM8994_WSEQ_DELAY110_SHIFT 0 /* WSEQ_DELAY110 - [3:0] */
+#define WM8994_WSEQ_DELAY110_WIDTH 4 /* WSEQ_DELAY110 - [3:0] */
+
+/*
+ * R12732 (0x31BC) - Write Sequencer 444
+ */
+#define WM8994_WSEQ_ADDR111_MASK 0x3FFF /* WSEQ_ADDR111 - [13:0] */
+#define WM8994_WSEQ_ADDR111_SHIFT 0 /* WSEQ_ADDR111 - [13:0] */
+#define WM8994_WSEQ_ADDR111_WIDTH 14 /* WSEQ_ADDR111 - [13:0] */
+
+/*
+ * R12733 (0x31BD) - Write Sequencer 445
+ */
+#define WM8994_WSEQ_DATA111_MASK 0x00FF /* WSEQ_DATA111 - [7:0] */
+#define WM8994_WSEQ_DATA111_SHIFT 0 /* WSEQ_DATA111 - [7:0] */
+#define WM8994_WSEQ_DATA111_WIDTH 8 /* WSEQ_DATA111 - [7:0] */
+
+/*
+ * R12734 (0x31BE) - Write Sequencer 446
+ */
+#define WM8994_WSEQ_DATA_WIDTH111_MASK 0x0700 /* WSEQ_DATA_WIDTH111 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH111_SHIFT 8 /* WSEQ_DATA_WIDTH111 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH111_WIDTH 3 /* WSEQ_DATA_WIDTH111 - [10:8] */
+#define WM8994_WSEQ_DATA_START111_MASK 0x000F /* WSEQ_DATA_START111 - [3:0] */
+#define WM8994_WSEQ_DATA_START111_SHIFT 0 /* WSEQ_DATA_START111 - [3:0] */
+#define WM8994_WSEQ_DATA_START111_WIDTH 4 /* WSEQ_DATA_START111 - [3:0] */
+
+/*
+ * R12735 (0x31BF) - Write Sequencer 447
+ */
+#define WM8994_WSEQ_EOS111 0x0100 /* WSEQ_EOS111 */
+#define WM8994_WSEQ_EOS111_MASK 0x0100 /* WSEQ_EOS111 */
+#define WM8994_WSEQ_EOS111_SHIFT 8 /* WSEQ_EOS111 */
+#define WM8994_WSEQ_EOS111_WIDTH 1 /* WSEQ_EOS111 */
+#define WM8994_WSEQ_DELAY111_MASK 0x000F /* WSEQ_DELAY111 - [3:0] */
+#define WM8994_WSEQ_DELAY111_SHIFT 0 /* WSEQ_DELAY111 - [3:0] */
+#define WM8994_WSEQ_DELAY111_WIDTH 4 /* WSEQ_DELAY111 - [3:0] */
+
+/*
+ * R12736 (0x31C0) - Write Sequencer 448
+ */
+#define WM8994_WSEQ_ADDR112_MASK 0x3FFF /* WSEQ_ADDR112 - [13:0] */
+#define WM8994_WSEQ_ADDR112_SHIFT 0 /* WSEQ_ADDR112 - [13:0] */
+#define WM8994_WSEQ_ADDR112_WIDTH 14 /* WSEQ_ADDR112 - [13:0] */
+
+/*
+ * R12737 (0x31C1) - Write Sequencer 449
+ */
+#define WM8994_WSEQ_DATA112_MASK 0x00FF /* WSEQ_DATA112 - [7:0] */
+#define WM8994_WSEQ_DATA112_SHIFT 0 /* WSEQ_DATA112 - [7:0] */
+#define WM8994_WSEQ_DATA112_WIDTH 8 /* WSEQ_DATA112 - [7:0] */
+
+/*
+ * R12738 (0x31C2) - Write Sequencer 450
+ */
+#define WM8994_WSEQ_DATA_WIDTH112_MASK 0x0700 /* WSEQ_DATA_WIDTH112 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH112_SHIFT 8 /* WSEQ_DATA_WIDTH112 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH112_WIDTH 3 /* WSEQ_DATA_WIDTH112 - [10:8] */
+#define WM8994_WSEQ_DATA_START112_MASK 0x000F /* WSEQ_DATA_START112 - [3:0] */
+#define WM8994_WSEQ_DATA_START112_SHIFT 0 /* WSEQ_DATA_START112 - [3:0] */
+#define WM8994_WSEQ_DATA_START112_WIDTH 4 /* WSEQ_DATA_START112 - [3:0] */
+
+/*
+ * R12739 (0x31C3) - Write Sequencer 451
+ */
+#define WM8994_WSEQ_EOS112 0x0100 /* WSEQ_EOS112 */
+#define WM8994_WSEQ_EOS112_MASK 0x0100 /* WSEQ_EOS112 */
+#define WM8994_WSEQ_EOS112_SHIFT 8 /* WSEQ_EOS112 */
+#define WM8994_WSEQ_EOS112_WIDTH 1 /* WSEQ_EOS112 */
+#define WM8994_WSEQ_DELAY112_MASK 0x000F /* WSEQ_DELAY112 - [3:0] */
+#define WM8994_WSEQ_DELAY112_SHIFT 0 /* WSEQ_DELAY112 - [3:0] */
+#define WM8994_WSEQ_DELAY112_WIDTH 4 /* WSEQ_DELAY112 - [3:0] */
+
+/*
+ * R12740 (0x31C4) - Write Sequencer 452
+ */
+#define WM8994_WSEQ_ADDR113_MASK 0x3FFF /* WSEQ_ADDR113 - [13:0] */
+#define WM8994_WSEQ_ADDR113_SHIFT 0 /* WSEQ_ADDR113 - [13:0] */
+#define WM8994_WSEQ_ADDR113_WIDTH 14 /* WSEQ_ADDR113 - [13:0] */
+
+/*
+ * R12741 (0x31C5) - Write Sequencer 453
+ */
+#define WM8994_WSEQ_DATA113_MASK 0x00FF /* WSEQ_DATA113 - [7:0] */
+#define WM8994_WSEQ_DATA113_SHIFT 0 /* WSEQ_DATA113 - [7:0] */
+#define WM8994_WSEQ_DATA113_WIDTH 8 /* WSEQ_DATA113 - [7:0] */
+
+/*
+ * R12742 (0x31C6) - Write Sequencer 454
+ */
+#define WM8994_WSEQ_DATA_WIDTH113_MASK 0x0700 /* WSEQ_DATA_WIDTH113 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH113_SHIFT 8 /* WSEQ_DATA_WIDTH113 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH113_WIDTH 3 /* WSEQ_DATA_WIDTH113 - [10:8] */
+#define WM8994_WSEQ_DATA_START113_MASK 0x000F /* WSEQ_DATA_START113 - [3:0] */
+#define WM8994_WSEQ_DATA_START113_SHIFT 0 /* WSEQ_DATA_START113 - [3:0] */
+#define WM8994_WSEQ_DATA_START113_WIDTH 4 /* WSEQ_DATA_START113 - [3:0] */
+
+/*
+ * R12743 (0x31C7) - Write Sequencer 455
+ */
+#define WM8994_WSEQ_EOS113 0x0100 /* WSEQ_EOS113 */
+#define WM8994_WSEQ_EOS113_MASK 0x0100 /* WSEQ_EOS113 */
+#define WM8994_WSEQ_EOS113_SHIFT 8 /* WSEQ_EOS113 */
+#define WM8994_WSEQ_EOS113_WIDTH 1 /* WSEQ_EOS113 */
+#define WM8994_WSEQ_DELAY113_MASK 0x000F /* WSEQ_DELAY113 - [3:0] */
+#define WM8994_WSEQ_DELAY113_SHIFT 0 /* WSEQ_DELAY113 - [3:0] */
+#define WM8994_WSEQ_DELAY113_WIDTH 4 /* WSEQ_DELAY113 - [3:0] */
+
+/*
+ * R12744 (0x31C8) - Write Sequencer 456
+ */
+#define WM8994_WSEQ_ADDR114_MASK 0x3FFF /* WSEQ_ADDR114 - [13:0] */
+#define WM8994_WSEQ_ADDR114_SHIFT 0 /* WSEQ_ADDR114 - [13:0] */
+#define WM8994_WSEQ_ADDR114_WIDTH 14 /* WSEQ_ADDR114 - [13:0] */
+
+/*
+ * R12745 (0x31C9) - Write Sequencer 457
+ */
+#define WM8994_WSEQ_DATA114_MASK 0x00FF /* WSEQ_DATA114 - [7:0] */
+#define WM8994_WSEQ_DATA114_SHIFT 0 /* WSEQ_DATA114 - [7:0] */
+#define WM8994_WSEQ_DATA114_WIDTH 8 /* WSEQ_DATA114 - [7:0] */
+
+/*
+ * R12746 (0x31CA) - Write Sequencer 458
+ */
+#define WM8994_WSEQ_DATA_WIDTH114_MASK 0x0700 /* WSEQ_DATA_WIDTH114 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH114_SHIFT 8 /* WSEQ_DATA_WIDTH114 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH114_WIDTH 3 /* WSEQ_DATA_WIDTH114 - [10:8] */
+#define WM8994_WSEQ_DATA_START114_MASK 0x000F /* WSEQ_DATA_START114 - [3:0] */
+#define WM8994_WSEQ_DATA_START114_SHIFT 0 /* WSEQ_DATA_START114 - [3:0] */
+#define WM8994_WSEQ_DATA_START114_WIDTH 4 /* WSEQ_DATA_START114 - [3:0] */
+
+/*
+ * R12747 (0x31CB) - Write Sequencer 459
+ */
+#define WM8994_WSEQ_EOS114 0x0100 /* WSEQ_EOS114 */
+#define WM8994_WSEQ_EOS114_MASK 0x0100 /* WSEQ_EOS114 */
+#define WM8994_WSEQ_EOS114_SHIFT 8 /* WSEQ_EOS114 */
+#define WM8994_WSEQ_EOS114_WIDTH 1 /* WSEQ_EOS114 */
+#define WM8994_WSEQ_DELAY114_MASK 0x000F /* WSEQ_DELAY114 - [3:0] */
+#define WM8994_WSEQ_DELAY114_SHIFT 0 /* WSEQ_DELAY114 - [3:0] */
+#define WM8994_WSEQ_DELAY114_WIDTH 4 /* WSEQ_DELAY114 - [3:0] */
+
+/*
+ * R12748 (0x31CC) - Write Sequencer 460
+ */
+#define WM8994_WSEQ_ADDR115_MASK 0x3FFF /* WSEQ_ADDR115 - [13:0] */
+#define WM8994_WSEQ_ADDR115_SHIFT 0 /* WSEQ_ADDR115 - [13:0] */
+#define WM8994_WSEQ_ADDR115_WIDTH 14 /* WSEQ_ADDR115 - [13:0] */
+
+/*
+ * R12749 (0x31CD) - Write Sequencer 461
+ */
+#define WM8994_WSEQ_DATA115_MASK 0x00FF /* WSEQ_DATA115 - [7:0] */
+#define WM8994_WSEQ_DATA115_SHIFT 0 /* WSEQ_DATA115 - [7:0] */
+#define WM8994_WSEQ_DATA115_WIDTH 8 /* WSEQ_DATA115 - [7:0] */
+
+/*
+ * R12750 (0x31CE) - Write Sequencer 462
+ */
+#define WM8994_WSEQ_DATA_WIDTH115_MASK 0x0700 /* WSEQ_DATA_WIDTH115 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH115_SHIFT 8 /* WSEQ_DATA_WIDTH115 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH115_WIDTH 3 /* WSEQ_DATA_WIDTH115 - [10:8] */
+#define WM8994_WSEQ_DATA_START115_MASK 0x000F /* WSEQ_DATA_START115 - [3:0] */
+#define WM8994_WSEQ_DATA_START115_SHIFT 0 /* WSEQ_DATA_START115 - [3:0] */
+#define WM8994_WSEQ_DATA_START115_WIDTH 4 /* WSEQ_DATA_START115 - [3:0] */
+
+/*
+ * R12751 (0x31CF) - Write Sequencer 463
+ */
+#define WM8994_WSEQ_EOS115 0x0100 /* WSEQ_EOS115 */
+#define WM8994_WSEQ_EOS115_MASK 0x0100 /* WSEQ_EOS115 */
+#define WM8994_WSEQ_EOS115_SHIFT 8 /* WSEQ_EOS115 */
+#define WM8994_WSEQ_EOS115_WIDTH 1 /* WSEQ_EOS115 */
+#define WM8994_WSEQ_DELAY115_MASK 0x000F /* WSEQ_DELAY115 - [3:0] */
+#define WM8994_WSEQ_DELAY115_SHIFT 0 /* WSEQ_DELAY115 - [3:0] */
+#define WM8994_WSEQ_DELAY115_WIDTH 4 /* WSEQ_DELAY115 - [3:0] */
+
+/*
+ * R12752 (0x31D0) - Write Sequencer 464
+ */
+#define WM8994_WSEQ_ADDR116_MASK 0x3FFF /* WSEQ_ADDR116 - [13:0] */
+#define WM8994_WSEQ_ADDR116_SHIFT 0 /* WSEQ_ADDR116 - [13:0] */
+#define WM8994_WSEQ_ADDR116_WIDTH 14 /* WSEQ_ADDR116 - [13:0] */
+
+/*
+ * R12753 (0x31D1) - Write Sequencer 465
+ */
+#define WM8994_WSEQ_DATA116_MASK 0x00FF /* WSEQ_DATA116 - [7:0] */
+#define WM8994_WSEQ_DATA116_SHIFT 0 /* WSEQ_DATA116 - [7:0] */
+#define WM8994_WSEQ_DATA116_WIDTH 8 /* WSEQ_DATA116 - [7:0] */
+
+/*
+ * R12754 (0x31D2) - Write Sequencer 466
+ */
+#define WM8994_WSEQ_DATA_WIDTH116_MASK 0x0700 /* WSEQ_DATA_WIDTH116 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH116_SHIFT 8 /* WSEQ_DATA_WIDTH116 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH116_WIDTH 3 /* WSEQ_DATA_WIDTH116 - [10:8] */
+#define WM8994_WSEQ_DATA_START116_MASK 0x000F /* WSEQ_DATA_START116 - [3:0] */
+#define WM8994_WSEQ_DATA_START116_SHIFT 0 /* WSEQ_DATA_START116 - [3:0] */
+#define WM8994_WSEQ_DATA_START116_WIDTH 4 /* WSEQ_DATA_START116 - [3:0] */
+
+/*
+ * R12755 (0x31D3) - Write Sequencer 467
+ */
+#define WM8994_WSEQ_EOS116 0x0100 /* WSEQ_EOS116 */
+#define WM8994_WSEQ_EOS116_MASK 0x0100 /* WSEQ_EOS116 */
+#define WM8994_WSEQ_EOS116_SHIFT 8 /* WSEQ_EOS116 */
+#define WM8994_WSEQ_EOS116_WIDTH 1 /* WSEQ_EOS116 */
+#define WM8994_WSEQ_DELAY116_MASK 0x000F /* WSEQ_DELAY116 - [3:0] */
+#define WM8994_WSEQ_DELAY116_SHIFT 0 /* WSEQ_DELAY116 - [3:0] */
+#define WM8994_WSEQ_DELAY116_WIDTH 4 /* WSEQ_DELAY116 - [3:0] */
+
+/*
+ * R12756 (0x31D4) - Write Sequencer 468
+ */
+#define WM8994_WSEQ_ADDR117_MASK 0x3FFF /* WSEQ_ADDR117 - [13:0] */
+#define WM8994_WSEQ_ADDR117_SHIFT 0 /* WSEQ_ADDR117 - [13:0] */
+#define WM8994_WSEQ_ADDR117_WIDTH 14 /* WSEQ_ADDR117 - [13:0] */
+
+/*
+ * R12757 (0x31D5) - Write Sequencer 469
+ */
+#define WM8994_WSEQ_DATA117_MASK 0x00FF /* WSEQ_DATA117 - [7:0] */
+#define WM8994_WSEQ_DATA117_SHIFT 0 /* WSEQ_DATA117 - [7:0] */
+#define WM8994_WSEQ_DATA117_WIDTH 8 /* WSEQ_DATA117 - [7:0] */
+
+/*
+ * R12758 (0x31D6) - Write Sequencer 470
+ */
+#define WM8994_WSEQ_DATA_WIDTH117_MASK 0x0700 /* WSEQ_DATA_WIDTH117 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH117_SHIFT 8 /* WSEQ_DATA_WIDTH117 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH117_WIDTH 3 /* WSEQ_DATA_WIDTH117 - [10:8] */
+#define WM8994_WSEQ_DATA_START117_MASK 0x000F /* WSEQ_DATA_START117 - [3:0] */
+#define WM8994_WSEQ_DATA_START117_SHIFT 0 /* WSEQ_DATA_START117 - [3:0] */
+#define WM8994_WSEQ_DATA_START117_WIDTH 4 /* WSEQ_DATA_START117 - [3:0] */
+
+/*
+ * R12759 (0x31D7) - Write Sequencer 471
+ */
+#define WM8994_WSEQ_EOS117 0x0100 /* WSEQ_EOS117 */
+#define WM8994_WSEQ_EOS117_MASK 0x0100 /* WSEQ_EOS117 */
+#define WM8994_WSEQ_EOS117_SHIFT 8 /* WSEQ_EOS117 */
+#define WM8994_WSEQ_EOS117_WIDTH 1 /* WSEQ_EOS117 */
+#define WM8994_WSEQ_DELAY117_MASK 0x000F /* WSEQ_DELAY117 - [3:0] */
+#define WM8994_WSEQ_DELAY117_SHIFT 0 /* WSEQ_DELAY117 - [3:0] */
+#define WM8994_WSEQ_DELAY117_WIDTH 4 /* WSEQ_DELAY117 - [3:0] */
+
+/*
+ * R12760 (0x31D8) - Write Sequencer 472
+ */
+#define WM8994_WSEQ_ADDR118_MASK 0x3FFF /* WSEQ_ADDR118 - [13:0] */
+#define WM8994_WSEQ_ADDR118_SHIFT 0 /* WSEQ_ADDR118 - [13:0] */
+#define WM8994_WSEQ_ADDR118_WIDTH 14 /* WSEQ_ADDR118 - [13:0] */
+
+/*
+ * R12761 (0x31D9) - Write Sequencer 473
+ */
+#define WM8994_WSEQ_DATA118_MASK 0x00FF /* WSEQ_DATA118 - [7:0] */
+#define WM8994_WSEQ_DATA118_SHIFT 0 /* WSEQ_DATA118 - [7:0] */
+#define WM8994_WSEQ_DATA118_WIDTH 8 /* WSEQ_DATA118 - [7:0] */
+
+/*
+ * R12762 (0x31DA) - Write Sequencer 474
+ */
+#define WM8994_WSEQ_DATA_WIDTH118_MASK 0x0700 /* WSEQ_DATA_WIDTH118 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH118_SHIFT 8 /* WSEQ_DATA_WIDTH118 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH118_WIDTH 3 /* WSEQ_DATA_WIDTH118 - [10:8] */
+#define WM8994_WSEQ_DATA_START118_MASK 0x000F /* WSEQ_DATA_START118 - [3:0] */
+#define WM8994_WSEQ_DATA_START118_SHIFT 0 /* WSEQ_DATA_START118 - [3:0] */
+#define WM8994_WSEQ_DATA_START118_WIDTH 4 /* WSEQ_DATA_START118 - [3:0] */
+
+/*
+ * R12763 (0x31DB) - Write Sequencer 475
+ */
+#define WM8994_WSEQ_EOS118 0x0100 /* WSEQ_EOS118 */
+#define WM8994_WSEQ_EOS118_MASK 0x0100 /* WSEQ_EOS118 */
+#define WM8994_WSEQ_EOS118_SHIFT 8 /* WSEQ_EOS118 */
+#define WM8994_WSEQ_EOS118_WIDTH 1 /* WSEQ_EOS118 */
+#define WM8994_WSEQ_DELAY118_MASK 0x000F /* WSEQ_DELAY118 - [3:0] */
+#define WM8994_WSEQ_DELAY118_SHIFT 0 /* WSEQ_DELAY118 - [3:0] */
+#define WM8994_WSEQ_DELAY118_WIDTH 4 /* WSEQ_DELAY118 - [3:0] */
+
+/*
+ * R12764 (0x31DC) - Write Sequencer 476
+ */
+#define WM8994_WSEQ_ADDR119_MASK 0x3FFF /* WSEQ_ADDR119 - [13:0] */
+#define WM8994_WSEQ_ADDR119_SHIFT 0 /* WSEQ_ADDR119 - [13:0] */
+#define WM8994_WSEQ_ADDR119_WIDTH 14 /* WSEQ_ADDR119 - [13:0] */
+
+/*
+ * R12765 (0x31DD) - Write Sequencer 477
+ */
+#define WM8994_WSEQ_DATA119_MASK 0x00FF /* WSEQ_DATA119 - [7:0] */
+#define WM8994_WSEQ_DATA119_SHIFT 0 /* WSEQ_DATA119 - [7:0] */
+#define WM8994_WSEQ_DATA119_WIDTH 8 /* WSEQ_DATA119 - [7:0] */
+
+/*
+ * R12766 (0x31DE) - Write Sequencer 478
+ */
+#define WM8994_WSEQ_DATA_WIDTH119_MASK 0x0700 /* WSEQ_DATA_WIDTH119 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH119_SHIFT 8 /* WSEQ_DATA_WIDTH119 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH119_WIDTH 3 /* WSEQ_DATA_WIDTH119 - [10:8] */
+#define WM8994_WSEQ_DATA_START119_MASK 0x000F /* WSEQ_DATA_START119 - [3:0] */
+#define WM8994_WSEQ_DATA_START119_SHIFT 0 /* WSEQ_DATA_START119 - [3:0] */
+#define WM8994_WSEQ_DATA_START119_WIDTH 4 /* WSEQ_DATA_START119 - [3:0] */
+
+/*
+ * R12767 (0x31DF) - Write Sequencer 479
+ */
+#define WM8994_WSEQ_EOS119 0x0100 /* WSEQ_EOS119 */
+#define WM8994_WSEQ_EOS119_MASK 0x0100 /* WSEQ_EOS119 */
+#define WM8994_WSEQ_EOS119_SHIFT 8 /* WSEQ_EOS119 */
+#define WM8994_WSEQ_EOS119_WIDTH 1 /* WSEQ_EOS119 */
+#define WM8994_WSEQ_DELAY119_MASK 0x000F /* WSEQ_DELAY119 - [3:0] */
+#define WM8994_WSEQ_DELAY119_SHIFT 0 /* WSEQ_DELAY119 - [3:0] */
+#define WM8994_WSEQ_DELAY119_WIDTH 4 /* WSEQ_DELAY119 - [3:0] */
+
+/*
+ * R12768 (0x31E0) - Write Sequencer 480
+ */
+#define WM8994_WSEQ_ADDR120_MASK 0x3FFF /* WSEQ_ADDR120 - [13:0] */
+#define WM8994_WSEQ_ADDR120_SHIFT 0 /* WSEQ_ADDR120 - [13:0] */
+#define WM8994_WSEQ_ADDR120_WIDTH 14 /* WSEQ_ADDR120 - [13:0] */
+
+/*
+ * R12769 (0x31E1) - Write Sequencer 481
+ */
+#define WM8994_WSEQ_DATA120_MASK 0x00FF /* WSEQ_DATA120 - [7:0] */
+#define WM8994_WSEQ_DATA120_SHIFT 0 /* WSEQ_DATA120 - [7:0] */
+#define WM8994_WSEQ_DATA120_WIDTH 8 /* WSEQ_DATA120 - [7:0] */
+
+/*
+ * R12770 (0x31E2) - Write Sequencer 482
+ */
+#define WM8994_WSEQ_DATA_WIDTH120_MASK 0x0700 /* WSEQ_DATA_WIDTH120 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH120_SHIFT 8 /* WSEQ_DATA_WIDTH120 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH120_WIDTH 3 /* WSEQ_DATA_WIDTH120 - [10:8] */
+#define WM8994_WSEQ_DATA_START120_MASK 0x000F /* WSEQ_DATA_START120 - [3:0] */
+#define WM8994_WSEQ_DATA_START120_SHIFT 0 /* WSEQ_DATA_START120 - [3:0] */
+#define WM8994_WSEQ_DATA_START120_WIDTH 4 /* WSEQ_DATA_START120 - [3:0] */
+
+/*
+ * R12771 (0x31E3) - Write Sequencer 483
+ */
+#define WM8994_WSEQ_EOS120 0x0100 /* WSEQ_EOS120 */
+#define WM8994_WSEQ_EOS120_MASK 0x0100 /* WSEQ_EOS120 */
+#define WM8994_WSEQ_EOS120_SHIFT 8 /* WSEQ_EOS120 */
+#define WM8994_WSEQ_EOS120_WIDTH 1 /* WSEQ_EOS120 */
+#define WM8994_WSEQ_DELAY120_MASK 0x000F /* WSEQ_DELAY120 - [3:0] */
+#define WM8994_WSEQ_DELAY120_SHIFT 0 /* WSEQ_DELAY120 - [3:0] */
+#define WM8994_WSEQ_DELAY120_WIDTH 4 /* WSEQ_DELAY120 - [3:0] */
+
+/*
+ * R12772 (0x31E4) - Write Sequencer 484
+ */
+#define WM8994_WSEQ_ADDR121_MASK 0x3FFF /* WSEQ_ADDR121 - [13:0] */
+#define WM8994_WSEQ_ADDR121_SHIFT 0 /* WSEQ_ADDR121 - [13:0] */
+#define WM8994_WSEQ_ADDR121_WIDTH 14 /* WSEQ_ADDR121 - [13:0] */
+
+/*
+ * R12773 (0x31E5) - Write Sequencer 485
+ */
+#define WM8994_WSEQ_DATA121_MASK 0x00FF /* WSEQ_DATA121 - [7:0] */
+#define WM8994_WSEQ_DATA121_SHIFT 0 /* WSEQ_DATA121 - [7:0] */
+#define WM8994_WSEQ_DATA121_WIDTH 8 /* WSEQ_DATA121 - [7:0] */
+
+/*
+ * R12774 (0x31E6) - Write Sequencer 486
+ */
+#define WM8994_WSEQ_DATA_WIDTH121_MASK 0x0700 /* WSEQ_DATA_WIDTH121 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH121_SHIFT 8 /* WSEQ_DATA_WIDTH121 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH121_WIDTH 3 /* WSEQ_DATA_WIDTH121 - [10:8] */
+#define WM8994_WSEQ_DATA_START121_MASK 0x000F /* WSEQ_DATA_START121 - [3:0] */
+#define WM8994_WSEQ_DATA_START121_SHIFT 0 /* WSEQ_DATA_START121 - [3:0] */
+#define WM8994_WSEQ_DATA_START121_WIDTH 4 /* WSEQ_DATA_START121 - [3:0] */
+
+/*
+ * R12775 (0x31E7) - Write Sequencer 487
+ */
+#define WM8994_WSEQ_EOS121 0x0100 /* WSEQ_EOS121 */
+#define WM8994_WSEQ_EOS121_MASK 0x0100 /* WSEQ_EOS121 */
+#define WM8994_WSEQ_EOS121_SHIFT 8 /* WSEQ_EOS121 */
+#define WM8994_WSEQ_EOS121_WIDTH 1 /* WSEQ_EOS121 */
+#define WM8994_WSEQ_DELAY121_MASK 0x000F /* WSEQ_DELAY121 - [3:0] */
+#define WM8994_WSEQ_DELAY121_SHIFT 0 /* WSEQ_DELAY121 - [3:0] */
+#define WM8994_WSEQ_DELAY121_WIDTH 4 /* WSEQ_DELAY121 - [3:0] */
+
+/*
+ * R12776 (0x31E8) - Write Sequencer 488
+ */
+#define WM8994_WSEQ_ADDR122_MASK 0x3FFF /* WSEQ_ADDR122 - [13:0] */
+#define WM8994_WSEQ_ADDR122_SHIFT 0 /* WSEQ_ADDR122 - [13:0] */
+#define WM8994_WSEQ_ADDR122_WIDTH 14 /* WSEQ_ADDR122 - [13:0] */
+
+/*
+ * R12777 (0x31E9) - Write Sequencer 489
+ */
+#define WM8994_WSEQ_DATA122_MASK 0x00FF /* WSEQ_DATA122 - [7:0] */
+#define WM8994_WSEQ_DATA122_SHIFT 0 /* WSEQ_DATA122 - [7:0] */
+#define WM8994_WSEQ_DATA122_WIDTH 8 /* WSEQ_DATA122 - [7:0] */
+
+/*
+ * R12778 (0x31EA) - Write Sequencer 490
+ */
+#define WM8994_WSEQ_DATA_WIDTH122_MASK 0x0700 /* WSEQ_DATA_WIDTH122 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH122_SHIFT 8 /* WSEQ_DATA_WIDTH122 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH122_WIDTH 3 /* WSEQ_DATA_WIDTH122 - [10:8] */
+#define WM8994_WSEQ_DATA_START122_MASK 0x000F /* WSEQ_DATA_START122 - [3:0] */
+#define WM8994_WSEQ_DATA_START122_SHIFT 0 /* WSEQ_DATA_START122 - [3:0] */
+#define WM8994_WSEQ_DATA_START122_WIDTH 4 /* WSEQ_DATA_START122 - [3:0] */
+
+/*
+ * R12779 (0x31EB) - Write Sequencer 491
+ */
+#define WM8994_WSEQ_EOS122 0x0100 /* WSEQ_EOS122 */
+#define WM8994_WSEQ_EOS122_MASK 0x0100 /* WSEQ_EOS122 */
+#define WM8994_WSEQ_EOS122_SHIFT 8 /* WSEQ_EOS122 */
+#define WM8994_WSEQ_EOS122_WIDTH 1 /* WSEQ_EOS122 */
+#define WM8994_WSEQ_DELAY122_MASK 0x000F /* WSEQ_DELAY122 - [3:0] */
+#define WM8994_WSEQ_DELAY122_SHIFT 0 /* WSEQ_DELAY122 - [3:0] */
+#define WM8994_WSEQ_DELAY122_WIDTH 4 /* WSEQ_DELAY122 - [3:0] */
+
+/*
+ * R12780 (0x31EC) - Write Sequencer 492
+ */
+#define WM8994_WSEQ_ADDR123_MASK 0x3FFF /* WSEQ_ADDR123 - [13:0] */
+#define WM8994_WSEQ_ADDR123_SHIFT 0 /* WSEQ_ADDR123 - [13:0] */
+#define WM8994_WSEQ_ADDR123_WIDTH 14 /* WSEQ_ADDR123 - [13:0] */
+
+/*
+ * R12781 (0x31ED) - Write Sequencer 493
+ */
+#define WM8994_WSEQ_DATA123_MASK 0x00FF /* WSEQ_DATA123 - [7:0] */
+#define WM8994_WSEQ_DATA123_SHIFT 0 /* WSEQ_DATA123 - [7:0] */
+#define WM8994_WSEQ_DATA123_WIDTH 8 /* WSEQ_DATA123 - [7:0] */
+
+/*
+ * R12782 (0x31EE) - Write Sequencer 494
+ */
+#define WM8994_WSEQ_DATA_WIDTH123_MASK 0x0700 /* WSEQ_DATA_WIDTH123 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH123_SHIFT 8 /* WSEQ_DATA_WIDTH123 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH123_WIDTH 3 /* WSEQ_DATA_WIDTH123 - [10:8] */
+#define WM8994_WSEQ_DATA_START123_MASK 0x000F /* WSEQ_DATA_START123 - [3:0] */
+#define WM8994_WSEQ_DATA_START123_SHIFT 0 /* WSEQ_DATA_START123 - [3:0] */
+#define WM8994_WSEQ_DATA_START123_WIDTH 4 /* WSEQ_DATA_START123 - [3:0] */
+
+/*
+ * R12783 (0x31EF) - Write Sequencer 495
+ */
+#define WM8994_WSEQ_EOS123 0x0100 /* WSEQ_EOS123 */
+#define WM8994_WSEQ_EOS123_MASK 0x0100 /* WSEQ_EOS123 */
+#define WM8994_WSEQ_EOS123_SHIFT 8 /* WSEQ_EOS123 */
+#define WM8994_WSEQ_EOS123_WIDTH 1 /* WSEQ_EOS123 */
+#define WM8994_WSEQ_DELAY123_MASK 0x000F /* WSEQ_DELAY123 - [3:0] */
+#define WM8994_WSEQ_DELAY123_SHIFT 0 /* WSEQ_DELAY123 - [3:0] */
+#define WM8994_WSEQ_DELAY123_WIDTH 4 /* WSEQ_DELAY123 - [3:0] */
+
+/*
+ * R12784 (0x31F0) - Write Sequencer 496
+ */
+#define WM8994_WSEQ_ADDR124_MASK 0x3FFF /* WSEQ_ADDR124 - [13:0] */
+#define WM8994_WSEQ_ADDR124_SHIFT 0 /* WSEQ_ADDR124 - [13:0] */
+#define WM8994_WSEQ_ADDR124_WIDTH 14 /* WSEQ_ADDR124 - [13:0] */
+
+/*
+ * R12785 (0x31F1) - Write Sequencer 497
+ */
+#define WM8994_WSEQ_DATA124_MASK 0x00FF /* WSEQ_DATA124 - [7:0] */
+#define WM8994_WSEQ_DATA124_SHIFT 0 /* WSEQ_DATA124 - [7:0] */
+#define WM8994_WSEQ_DATA124_WIDTH 8 /* WSEQ_DATA124 - [7:0] */
+
+/*
+ * R12786 (0x31F2) - Write Sequencer 498
+ */
+#define WM8994_WSEQ_DATA_WIDTH124_MASK 0x0700 /* WSEQ_DATA_WIDTH124 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH124_SHIFT 8 /* WSEQ_DATA_WIDTH124 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH124_WIDTH 3 /* WSEQ_DATA_WIDTH124 - [10:8] */
+#define WM8994_WSEQ_DATA_START124_MASK 0x000F /* WSEQ_DATA_START124 - [3:0] */
+#define WM8994_WSEQ_DATA_START124_SHIFT 0 /* WSEQ_DATA_START124 - [3:0] */
+#define WM8994_WSEQ_DATA_START124_WIDTH 4 /* WSEQ_DATA_START124 - [3:0] */
+
+/*
+ * R12787 (0x31F3) - Write Sequencer 499
+ */
+#define WM8994_WSEQ_EOS124 0x0100 /* WSEQ_EOS124 */
+#define WM8994_WSEQ_EOS124_MASK 0x0100 /* WSEQ_EOS124 */
+#define WM8994_WSEQ_EOS124_SHIFT 8 /* WSEQ_EOS124 */
+#define WM8994_WSEQ_EOS124_WIDTH 1 /* WSEQ_EOS124 */
+#define WM8994_WSEQ_DELAY124_MASK 0x000F /* WSEQ_DELAY124 - [3:0] */
+#define WM8994_WSEQ_DELAY124_SHIFT 0 /* WSEQ_DELAY124 - [3:0] */
+#define WM8994_WSEQ_DELAY124_WIDTH 4 /* WSEQ_DELAY124 - [3:0] */
+
+/*
+ * R12788 (0x31F4) - Write Sequencer 500
+ */
+#define WM8994_WSEQ_ADDR125_MASK 0x3FFF /* WSEQ_ADDR125 - [13:0] */
+#define WM8994_WSEQ_ADDR125_SHIFT 0 /* WSEQ_ADDR125 - [13:0] */
+#define WM8994_WSEQ_ADDR125_WIDTH 14 /* WSEQ_ADDR125 - [13:0] */
+
+/*
+ * R12789 (0x31F5) - Write Sequencer 501
+ */
+#define WM8994_WSEQ_DATA125_MASK 0x00FF /* WSEQ_DATA125 - [7:0] */
+#define WM8994_WSEQ_DATA125_SHIFT 0 /* WSEQ_DATA125 - [7:0] */
+#define WM8994_WSEQ_DATA125_WIDTH 8 /* WSEQ_DATA125 - [7:0] */
+
+/*
+ * R12790 (0x31F6) - Write Sequencer 502
+ */
+#define WM8994_WSEQ_DATA_WIDTH125_MASK 0x0700 /* WSEQ_DATA_WIDTH125 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH125_SHIFT 8 /* WSEQ_DATA_WIDTH125 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH125_WIDTH 3 /* WSEQ_DATA_WIDTH125 - [10:8] */
+#define WM8994_WSEQ_DATA_START125_MASK 0x000F /* WSEQ_DATA_START125 - [3:0] */
+#define WM8994_WSEQ_DATA_START125_SHIFT 0 /* WSEQ_DATA_START125 - [3:0] */
+#define WM8994_WSEQ_DATA_START125_WIDTH 4 /* WSEQ_DATA_START125 - [3:0] */
+
+/*
+ * R12791 (0x31F7) - Write Sequencer 503
+ */
+#define WM8994_WSEQ_EOS125 0x0100 /* WSEQ_EOS125 */
+#define WM8994_WSEQ_EOS125_MASK 0x0100 /* WSEQ_EOS125 */
+#define WM8994_WSEQ_EOS125_SHIFT 8 /* WSEQ_EOS125 */
+#define WM8994_WSEQ_EOS125_WIDTH 1 /* WSEQ_EOS125 */
+#define WM8994_WSEQ_DELAY125_MASK 0x000F /* WSEQ_DELAY125 - [3:0] */
+#define WM8994_WSEQ_DELAY125_SHIFT 0 /* WSEQ_DELAY125 - [3:0] */
+#define WM8994_WSEQ_DELAY125_WIDTH 4 /* WSEQ_DELAY125 - [3:0] */
+
+/*
+ * R12792 (0x31F8) - Write Sequencer 504
+ */
+#define WM8994_WSEQ_ADDR126_MASK 0x3FFF /* WSEQ_ADDR126 - [13:0] */
+#define WM8994_WSEQ_ADDR126_SHIFT 0 /* WSEQ_ADDR126 - [13:0] */
+#define WM8994_WSEQ_ADDR126_WIDTH 14 /* WSEQ_ADDR126 - [13:0] */
+
+/*
+ * R12793 (0x31F9) - Write Sequencer 505
+ */
+#define WM8994_WSEQ_DATA126_MASK 0x00FF /* WSEQ_DATA126 - [7:0] */
+#define WM8994_WSEQ_DATA126_SHIFT 0 /* WSEQ_DATA126 - [7:0] */
+#define WM8994_WSEQ_DATA126_WIDTH 8 /* WSEQ_DATA126 - [7:0] */
+
+/*
+ * R12794 (0x31FA) - Write Sequencer 506
+ */
+#define WM8994_WSEQ_DATA_WIDTH126_MASK 0x0700 /* WSEQ_DATA_WIDTH126 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH126_SHIFT 8 /* WSEQ_DATA_WIDTH126 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH126_WIDTH 3 /* WSEQ_DATA_WIDTH126 - [10:8] */
+#define WM8994_WSEQ_DATA_START126_MASK 0x000F /* WSEQ_DATA_START126 - [3:0] */
+#define WM8994_WSEQ_DATA_START126_SHIFT 0 /* WSEQ_DATA_START126 - [3:0] */
+#define WM8994_WSEQ_DATA_START126_WIDTH 4 /* WSEQ_DATA_START126 - [3:0] */
+
+/*
+ * R12795 (0x31FB) - Write Sequencer 507
+ */
+#define WM8994_WSEQ_EOS126 0x0100 /* WSEQ_EOS126 */
+#define WM8994_WSEQ_EOS126_MASK 0x0100 /* WSEQ_EOS126 */
+#define WM8994_WSEQ_EOS126_SHIFT 8 /* WSEQ_EOS126 */
+#define WM8994_WSEQ_EOS126_WIDTH 1 /* WSEQ_EOS126 */
+#define WM8994_WSEQ_DELAY126_MASK 0x000F /* WSEQ_DELAY126 - [3:0] */
+#define WM8994_WSEQ_DELAY126_SHIFT 0 /* WSEQ_DELAY126 - [3:0] */
+#define WM8994_WSEQ_DELAY126_WIDTH 4 /* WSEQ_DELAY126 - [3:0] */
+
+/*
+ * R12796 (0x31FC) - Write Sequencer 508
+ */
+#define WM8994_WSEQ_ADDR127_MASK 0x3FFF /* WSEQ_ADDR127 - [13:0] */
+#define WM8994_WSEQ_ADDR127_SHIFT 0 /* WSEQ_ADDR127 - [13:0] */
+#define WM8994_WSEQ_ADDR127_WIDTH 14 /* WSEQ_ADDR127 - [13:0] */
+
+/*
+ * R12797 (0x31FD) - Write Sequencer 509
+ */
+#define WM8994_WSEQ_DATA127_MASK 0x00FF /* WSEQ_DATA127 - [7:0] */
+#define WM8994_WSEQ_DATA127_SHIFT 0 /* WSEQ_DATA127 - [7:0] */
+#define WM8994_WSEQ_DATA127_WIDTH 8 /* WSEQ_DATA127 - [7:0] */
+
+/*
+ * R12798 (0x31FE) - Write Sequencer 510
+ */
+#define WM8994_WSEQ_DATA_WIDTH127_MASK 0x0700 /* WSEQ_DATA_WIDTH127 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH127_SHIFT 8 /* WSEQ_DATA_WIDTH127 - [10:8] */
+#define WM8994_WSEQ_DATA_WIDTH127_WIDTH 3 /* WSEQ_DATA_WIDTH127 - [10:8] */
+#define WM8994_WSEQ_DATA_START127_MASK 0x000F /* WSEQ_DATA_START127 - [3:0] */
+#define WM8994_WSEQ_DATA_START127_SHIFT 0 /* WSEQ_DATA_START127 - [3:0] */
+#define WM8994_WSEQ_DATA_START127_WIDTH 4 /* WSEQ_DATA_START127 - [3:0] */
+
+/*
+ * R12799 (0x31FF) - Write Sequencer 511
+ */
+#define WM8994_WSEQ_EOS127 0x0100 /* WSEQ_EOS127 */
+#define WM8994_WSEQ_EOS127_MASK 0x0100 /* WSEQ_EOS127 */
+#define WM8994_WSEQ_EOS127_SHIFT 8 /* WSEQ_EOS127 */
+#define WM8994_WSEQ_EOS127_WIDTH 1 /* WSEQ_EOS127 */
+#define WM8994_WSEQ_DELAY127_MASK 0x000F /* WSEQ_DELAY127 - [3:0] */
+#define WM8994_WSEQ_DELAY127_SHIFT 0 /* WSEQ_DELAY127 - [3:0] */
+#define WM8994_WSEQ_DELAY127_WIDTH 4 /* WSEQ_DELAY127 - [3:0] */
+
diff --git a/sound/soc/codecs/wm8994_herring.c b/sound/soc/codecs/wm8994_herring.c
new file mode 100755
index 0000000..28e2320
--- /dev/null
+++ b/sound/soc/codecs/wm8994_herring.c
@@ -0,0 +1,3988 @@
+/*
+ * wm8994_crespo.c -- WM8994 ALSA Soc Audio driver related Aries
+ *
+ * Copyright (C) 2010 Samsung Electronics.
+ *
+ * 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 <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <plat/gpio-cfg.h>
+#include <plat/map-base.h>
+#include <mach/regs-clock.h>
+#include "wm8994_samsung.h"
+#include "../../../arch/arm/mach-s5pv210/herring.h"
+#ifdef CONFIG_SND_VOODOO
+#include "wm8994_voodoo.h"
+#endif
+
+/*
+ * Debug Feature
+ */
+#define SUBJECT "wm8994_crespo.c"
+
+/*
+ * Definitions of tunning volumes for wm8994
+ */
+
+struct gain_info_t cdma_playback_gain_table[PLAYBACK_GAIN_NUM] = {
+ { /* COMMON */
+ .mode = COMMON_SET_BIT,
+ .reg = WM8994_DAC1_LEFT_VOLUME, /* 610h */
+ .mask = WM8994_DAC1L_VOL_MASK,
+ .gain = WM8994_DAC1_VU | 0xC0
+ }, {
+ .mode = COMMON_SET_BIT,
+ .reg = WM8994_DAC1_RIGHT_VOLUME, /* 611h */
+ .mask = WM8994_DAC1R_VOL_MASK,
+ .gain = WM8994_DAC1_VU | 0xC0
+ }, {
+ .mode = COMMON_SET_BIT,
+ .reg = WM8994_AIF1_DAC1_LEFT_VOLUME, /* 402h */
+ .mask = WM8994_AIF1DAC1L_VOL_MASK,
+ .gain = WM8994_AIF1DAC1_VU | 0xC0
+ }, {
+ .mode = COMMON_SET_BIT,
+ .reg = WM8994_AIF1_DAC1_RIGHT_VOLUME, /* 403h */
+ .mask = WM8994_AIF1DAC1R_VOL_MASK,
+ .gain = WM8994_AIF1DAC1_VU | 0xC0
+ }, { /* RCV */
+ .mode = PLAYBACK_RCV,
+ .reg = WM8994_OUTPUT_MIXER_5, /* 31h */
+ .mask = WM8994_DACL_MIXOUTL_VOL_MASK,
+ .gain = 0x0 << WM8994_DACL_MIXOUTL_VOL_SHIFT
+ }, {
+ .mode = PLAYBACK_RCV,
+ .reg = WM8994_OUTPUT_MIXER_6, /* 32h */
+ .mask = WM8994_DACR_MIXOUTR_VOL_MASK,
+ .gain = 0x0 << WM8994_DACR_MIXOUTR_VOL_SHIFT
+ }, {
+ .mode = PLAYBACK_RCV,
+ .reg = WM8994_LEFT_OPGA_VOLUME, /* 20h */
+ .mask = WM8994_MIXOUTL_VOL_MASK,
+ .gain = WM8994_MIXOUT_VU | 0x3D
+ }, {
+ .mode = PLAYBACK_RCV,
+ .reg = WM8994_RIGHT_OPGA_VOLUME, /* 21h */
+ .mask = WM8994_MIXOUTR_VOL_MASK,
+ .gain = WM8994_MIXOUT_VU | 0x3D
+ }, {
+ .mode = PLAYBACK_RCV,
+ .reg = WM8994_HPOUT2_VOLUME, /* 1Fh */
+ .mask = WM8994_HPOUT2_VOL_MASK,
+ .gain = 0x0 << WM8994_HPOUT2_VOL_SHIFT
+ }, { /* SPK */
+ .mode = PLAYBACK_SPK,
+ .reg = WM8994_SPKMIXL_ATTENUATION, /* 22h */
+ .mask = WM8994_SPKMIXL_VOL_MASK,
+ .gain = 0x0
+ }, {
+ .mode = PLAYBACK_SPK,
+ .reg = WM8994_SPKMIXR_ATTENUATION, /* 23h */
+ .mask = WM8994_SPKMIXR_VOL_MASK,
+ .gain = 0x0
+ }, {
+ .mode = PLAYBACK_SPK,
+ .reg = WM8994_SPEAKER_VOLUME_LEFT, /* 26h */
+ .mask = WM8994_SPKOUTL_VOL_MASK,
+ .gain = WM8994_SPKOUT_VU | 0x3E /* +5dB */
+ }, {
+ .mode = PLAYBACK_SPK,
+ .reg = WM8994_SPEAKER_VOLUME_RIGHT, /* 27h */
+ .mask = WM8994_SPKOUTR_VOL_MASK,
+ .gain = 0
+ }, {
+ .mode = PLAYBACK_SPK,
+ .reg = WM8994_CLASSD, /* 25h */
+ .mask = WM8994_SPKOUTL_BOOST_MASK,
+ .gain = 0x05 << WM8994_SPKOUTL_BOOST_SHIFT /* +7.5dB */
+ }, {
+ .mode = PLAYBACK_SPK,
+ .reg = WM8994_AIF1_DAC1_LEFT_VOLUME, /* 402h */
+ .mask = WM8994_AIF1DAC1L_VOL_MASK,
+ .gain = WM8994_AIF1DAC1_VU | 0xB8 /* -2.625dB */
+ }, {
+ .mode = PLAYBACK_SPK,
+ .reg = WM8994_AIF1_DAC1_RIGHT_VOLUME, /* 403h */
+ .mask = WM8994_AIF1DAC1R_VOL_MASK,
+ .gain = WM8994_AIF1DAC1_VU | 0xB8 /* -2.625dB */
+ }, { /* HP */
+ .mode = PLAYBACK_HP,
+ .reg = WM8994_LEFT_OUTPUT_VOLUME, /* 1Ch */
+ .mask = WM8994_HPOUT1L_VOL_MASK,
+ .gain = WM8994_HPOUT1_VU | 0x31 /* -8dB */
+ }, {
+ .mode = PLAYBACK_HP,
+ .reg = WM8994_RIGHT_OUTPUT_VOLUME, /* 1Dh */
+ .mask = WM8994_HPOUT1R_VOL_MASK,
+ .gain = WM8994_HPOUT1_VU | 0x31 /* -8dB */
+ }, {
+ .mode = PLAYBACK_HP,
+ .reg = WM8994_LEFT_OPGA_VOLUME, /* 20h */
+ .mask = WM8994_MIXOUTL_VOL_MASK,
+ .gain = WM8994_MIXOUT_VU | 0x39
+ }, {
+ .mode = PLAYBACK_HP,
+ .reg = WM8994_RIGHT_OPGA_VOLUME, /* 21h */
+ .mask = WM8994_MIXOUTR_VOL_MASK,
+ .gain = WM8994_MIXOUT_VU | 0x39
+ }, { /* SPK_HP */
+ .mode = PLAYBACK_SPK_HP,
+ .reg = WM8994_SPKMIXL_ATTENUATION, /* 22h */
+ .mask = WM8994_SPKMIXL_VOL_MASK,
+ .gain = 0x0
+ }, {
+ .mode = PLAYBACK_SPK_HP,
+ .reg = WM8994_SPKMIXR_ATTENUATION, /* 23h */
+ .mask = WM8994_SPKMIXR_VOL_MASK,
+ .gain = 0x0
+ }, {
+ .mode = PLAYBACK_SPK_HP,
+ .reg = WM8994_SPEAKER_VOLUME_LEFT, /* 26h */
+ .mask = WM8994_SPKOUTL_VOL_MASK,
+ .gain = WM8994_SPKOUT_VU | 0x3E
+ }, {
+ .mode = PLAYBACK_SPK_HP,
+ .reg = WM8994_SPEAKER_VOLUME_RIGHT, /* 27h */
+ .mask = WM8994_SPKOUTR_VOL_MASK,
+ .gain = 0x0
+ }, {
+ .mode = PLAYBACK_SPK_HP,
+ .reg = WM8994_CLASSD, /* 25h */
+ .mask = WM8994_SPKOUTL_BOOST_MASK,
+ .gain = 0x5 << WM8994_SPKOUTL_BOOST_SHIFT
+ }, {
+ .mode = PLAYBACK_SPK_HP,
+ .reg = WM8994_LEFT_OUTPUT_VOLUME, /* 1Ch */
+ .mask = WM8994_HPOUT1L_VOL_MASK,
+ .gain = WM8994_HPOUT1_VU | 0x1E
+ }, {
+ .mode = PLAYBACK_SPK_HP,
+ .reg = WM8994_RIGHT_OUTPUT_VOLUME, /* 1Dh */
+ .mask = WM8994_HPOUT1R_VOL_MASK,
+ .gain = WM8994_HPOUT1_VU | 0x1E
+ }, {
+ .mode = PLAYBACK_SPK_HP,
+ .reg = WM8994_LEFT_OPGA_VOLUME, /* 20h */
+ .mask = WM8994_MIXOUTL_VOL_MASK,
+ .gain = WM8994_MIXOUT_VU | 0x39
+ }, {
+ .mode = PLAYBACK_SPK_HP,
+ .reg = WM8994_RIGHT_OPGA_VOLUME, /* 21h */
+ .mask = WM8994_MIXOUTR_VOL_MASK,
+ .gain = WM8994_MIXOUT_VU | 0x39
+ }, { /* RING_SPK */
+ .mode = PLAYBACK_RING_SPK,
+ .reg = WM8994_SPEAKER_VOLUME_LEFT, /* 26h */
+ .mask = WM8994_SPKOUTL_VOL_MASK,
+ .gain = WM8994_SPKOUT_VU | 0x3E
+ }, {
+ .mode = PLAYBACK_RING_SPK,
+ .reg = WM8994_CLASSD, /* 25h */
+ .mask = WM8994_SPKOUTL_BOOST_MASK,
+ .gain = 0x5 << WM8994_SPKOUTL_BOOST_SHIFT
+ }, { /* RING_HP */
+ .mode = PLAYBACK_RING_HP,
+ .reg = WM8994_LEFT_OUTPUT_VOLUME, /* 1Ch */
+ .mask = WM8994_HPOUT1L_VOL_MASK,
+ .gain = WM8994_HPOUT1_VU | 0x34
+ }, {
+ .mode = PLAYBACK_RING_HP,
+ .reg = WM8994_RIGHT_OUTPUT_VOLUME, /* 1Dh */
+ .mask = WM8994_HPOUT1R_VOL_MASK,
+ .gain = WM8994_HPOUT1_VU | 0x34
+ }, {
+ .mode = PLAYBACK_RING_HP,
+ .reg = WM8994_LEFT_OPGA_VOLUME, /* 20h */
+ .mask = WM8994_MIXOUTL_VOL_MASK,
+ .gain = WM8994_MIXOUT_VU | 0x39
+ }, {
+ .mode = PLAYBACK_RING_HP,
+ .reg = WM8994_RIGHT_OPGA_VOLUME, /* 21h */
+ .mask = WM8994_MIXOUTR_VOL_MASK,
+ .gain = WM8994_MIXOUT_VU | 0x39
+ }, { /* RING_SPK_HP */
+ .mode = PLAYBACK_RING_SPK_HP,
+ .reg = WM8994_SPEAKER_VOLUME_LEFT, /* 26h */
+ .mask = WM8994_SPKOUTL_VOL_MASK,
+ .gain = WM8994_SPKOUT_VU | 0x3E
+ }, {
+ .mode = PLAYBACK_RING_SPK_HP,
+ .reg = WM8994_CLASSD, /* 25h */
+ .mask = WM8994_SPKOUTL_BOOST_MASK,
+ .gain = 0x5 << WM8994_SPKOUTL_BOOST_SHIFT
+ }, {
+ .mode = PLAYBACK_RING_SPK_HP,
+ .reg = WM8994_LEFT_OUTPUT_VOLUME, /* 1Ch */
+ .mask = WM8994_HPOUT1L_VOL_MASK,
+ .gain = WM8994_HPOUT1_VU | 0x1E
+ }, {
+ .mode = PLAYBACK_RING_SPK_HP,
+ .reg = WM8994_RIGHT_OUTPUT_VOLUME, /* 1Dh */
+ .mask = WM8994_HPOUT1R_VOL_MASK,
+ .gain = WM8994_HPOUT1_VU | 0x1E
+ }, { /* HP_NO_MIC */
+ .mode = PLAYBACK_HP_NO_MIC,
+ .reg = WM8994_LEFT_OUTPUT_VOLUME, /* 1Ch */
+ .mask = WM8994_HPOUT1L_VOL_MASK,
+ .gain = WM8994_HPOUT1_VU | 0x36 /* -3dB */
+ }, {
+ .mode = PLAYBACK_HP_NO_MIC,
+ .reg = WM8994_RIGHT_OUTPUT_VOLUME, /* 1Dh */
+ .mask = WM8994_HPOUT1R_VOL_MASK,
+ .gain = WM8994_HPOUT1_VU | 0x36 /* -3dB */
+ }, {
+ .mode = PLAYBACK_HP_NO_MIC,
+ .reg = WM8994_LEFT_OPGA_VOLUME, /* 20h */
+ .mask = WM8994_MIXOUTL_VOL_MASK,
+ .gain = WM8994_MIXOUT_VU | 0x39
+ }, {
+ .mode = PLAYBACK_HP_NO_MIC,
+ .reg = WM8994_RIGHT_OPGA_VOLUME, /* 21h */
+ .mask = WM8994_MIXOUTR_VOL_MASK,
+ .gain = WM8994_MIXOUT_VU | 0x39
+ },
+};
+
+struct gain_info_t cdma_voicecall_gain_table[VOICECALL_GAIN_NUM] = {
+ { /* COMMON */
+ .mode = COMMON_SET_BIT,
+ .reg = WM8994_DAC1_LEFT_VOLUME, /* 610h */
+ .mask = WM8994_DAC1L_VOL_MASK,
+ .gain = WM8994_DAC1_VU | 0xC0 /* 0dB */
+ }, {
+ .mode = COMMON_SET_BIT,
+ .reg = WM8994_DAC1_RIGHT_VOLUME, /* 611h */
+ .mask = WM8994_DAC1R_VOL_MASK,
+ .gain = WM8994_DAC1_VU | 0xC0 /* 0dB */
+ }, {
+ .mode = COMMON_SET_BIT,
+ .reg = WM8994_AIF1_DAC1_LEFT_VOLUME, /* 402h */
+ .mask = WM8994_AIF1DAC1L_VOL_MASK,
+ .gain = WM8994_AIF1DAC1_VU | 0xC0 /* 0dB */
+ }, {
+ .mode = COMMON_SET_BIT,
+ .reg = WM8994_AIF1_DAC1_RIGHT_VOLUME, /* 403h */
+ .mask = WM8994_AIF1DAC1R_VOL_MASK,
+ .gain = WM8994_AIF1DAC1_VU | 0xC0 /* 0dB */
+ }, {
+ .mode = COMMON_SET_BIT,
+ .reg = WM8994_DAC2_LEFT_VOLUME, /* 612h */
+ .mask = WM8994_DAC2L_VOL_MASK,
+ .gain = WM8994_DAC2_VU | 0xC0 /* 0dB */
+ }, {
+ .mode = COMMON_SET_BIT,
+ .reg = WM8994_DAC2_RIGHT_VOLUME, /* 613h */
+ .mask = WM8994_DAC2R_VOL_MASK,
+ .gain = WM8994_DAC2_VU | 0xC0 /* 0dB */
+ }, { /* RCV */
+ .mode = VOICECALL_RCV,
+ .reg = WM8994_LEFT_LINE_INPUT_1_2_VOLUME, /* 18h */
+ .mask = WM8994_IN1L_VOL_MASK,
+ .gain = WM8994_IN1L_VU | 0x0C /* +15dB */
+ }, {
+ .mode = VOICECALL_RCV,
+ .reg = WM8994_INPUT_MIXER_3, /* 29h */
+ .mask = WM8994_IN1L_MIXINL_VOL_MASK | WM8994_MIXOUTL_MIXINL_VOL_MASK,
+ .gain = 0x10 /* +30dB */
+ }, {
+ .mode = VOICECALL_RCV,
+ .reg = WM8994_OUTPUT_MIXER_5, /* 31h */
+ .mask = WM8994_DACL_MIXOUTL_VOL_MASK,
+ .gain = 0x0 << WM8994_DACL_MIXOUTL_VOL_SHIFT
+ }, {
+ .mode = VOICECALL_RCV,
+ .reg = WM8994_OUTPUT_MIXER_6, /* 32h */
+ .mask = WM8994_DACR_MIXOUTR_VOL_MASK,
+ .gain = 0x0 << WM8994_DACR_MIXOUTR_VOL_SHIFT
+ }, {
+ .mode = VOICECALL_RCV,
+ .reg = WM8994_LEFT_OPGA_VOLUME, /* 20h */
+ .mask = WM8994_MIXOUTL_VOL_MASK,
+ .gain = WM8994_MIXOUT_VU | 0x3F
+ }, {
+ .mode = VOICECALL_RCV,
+ .reg = WM8994_RIGHT_OPGA_VOLUME, /* 21h */
+ .mask = WM8994_MIXOUTR_VOL_MASK,
+ .gain = WM8994_MIXOUT_VU | 0x3F
+ }, {
+ .mode = VOICECALL_RCV,
+ .reg = WM8994_HPOUT2_VOLUME, /* 1Fh */
+ .mask = WM8994_HPOUT2_VOL_MASK,
+ .gain = 0x0 << WM8994_HPOUT2_VOL_SHIFT
+ }, { /* SPK */
+ .mode = VOICECALL_SPK,
+ .reg = WM8994_INPUT_MIXER_3, /* 29h */
+ .mask = WM8994_IN1L_MIXINL_VOL_MASK | WM8994_MIXOUTL_MIXINL_VOL_MASK,
+ .gain = 0x10 /* Mic +7.5dB */
+ }, {
+ .mode = VOICECALL_SPK,
+ .reg = WM8994_LEFT_LINE_INPUT_1_2_VOLUME, /* 18h */
+ .mask = WM8994_IN1L_VOL_MASK,
+ .gain = WM8994_IN1L_VU | 0x12 /* Mic +30dB */
+ }, {
+ .mode = VOICECALL_SPK,
+ .reg = WM8994_SPKMIXL_ATTENUATION, /* 22h */
+ .mask = WM8994_SPKMIXL_VOL_MASK,
+ .gain = 0x0 /* Speaker +0dB */
+ }, {
+ .mode = VOICECALL_SPK,
+ .reg = WM8994_SPKMIXR_ATTENUATION, /* 23h */
+ .mask = WM8994_SPKMIXR_VOL_MASK,
+ .gain = 0x0 /* Speaker +0dB */
+ }, {
+ .mode = VOICECALL_SPK,
+ .reg = WM8994_SPEAKER_VOLUME_LEFT, /* 26h */
+ .mask = WM8994_SPKOUTL_VOL_MASK,
+ .gain = WM8994_SPKOUT_VU | 0x3F /* Left Speaker +3dB */
+ }, {
+ .mode = VOICECALL_SPK,
+ .reg = WM8994_SPEAKER_VOLUME_RIGHT, /* 27h */
+ .mask = WM8994_SPKOUTR_VOL_MASK, /* Right Speaker -57dB */
+ .gain = 0x0
+ }, {
+ .mode = VOICECALL_SPK,
+ .reg = WM8994_CLASSD, /* 25h */
+ .mask = WM8994_SPKOUTL_BOOST_MASK,
+ .gain = 0x7 << WM8994_SPKOUTL_BOOST_SHIFT /* Left spaker +12dB */
+ }, { /* HP */
+ .mode = VOICECALL_HP,
+ .reg = WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, /* 1Ah */
+ .mask = WM8994_IN1R_VOL_MASK,
+ .gain = WM8994_IN1R_VU | 0x1D
+ }, {
+ .mode = VOICECALL_HP,
+ .reg = WM8994_INPUT_MIXER_4, /* 2Ah */
+ .mask = WM8994_IN1R_MIXINR_VOL_MASK | WM8994_MIXOUTR_MIXINR_VOL_MASK,
+ .gain = 0x0
+ }, {
+ .mode = VOICECALL_HP,
+ .reg = WM8994_LEFT_OPGA_VOLUME, /* 20h */
+ .mask = WM8994_MIXOUTL_VOL_MASK,
+ .gain = WM8994_MIXOUT_VU | 0x39
+ }, {
+ .mode = VOICECALL_HP,
+ .reg = WM8994_RIGHT_OPGA_VOLUME, /* 21h */
+ .mask = WM8994_MIXOUTR_VOL_MASK,
+ .gain = WM8994_MIXOUT_VU | 0x39
+ }, {
+ .mode = VOICECALL_HP,
+ .reg = WM8994_LEFT_OUTPUT_VOLUME, /* 1Ch */
+ .mask = WM8994_HPOUT1L_VOL_MASK,
+ .gain = WM8994_HPOUT1_VU | 0x30
+ }, {
+ .mode = VOICECALL_HP,
+ .reg = WM8994_RIGHT_OUTPUT_VOLUME, /* 1Dh */
+ .mask = WM8994_HPOUT1R_VOL_MASK,
+ .gain = WM8994_HPOUT1_VU | 0x30
+ }, { /* HP_NO_MIC */
+ .mode = VOICECALL_HP_NO_MIC,
+ .reg = WM8994_LEFT_LINE_INPUT_1_2_VOLUME, /* 18h */
+ .mask = WM8994_IN1L_VOL_MASK,
+ .gain = WM8994_IN1L_VU | 0x12 /* +10.5dB */
+ }, {
+ .mode = VOICECALL_HP_NO_MIC,
+ .reg = WM8994_INPUT_MIXER_3, /* 29h */
+ .mask = WM8994_IN1L_MIXINL_VOL_MASK | WM8994_MIXOUTL_MIXINL_VOL_MASK,
+ .gain = 0x10
+ }, {
+ .mode = VOICECALL_HP_NO_MIC,
+ .reg = WM8994_LEFT_OPGA_VOLUME, /* 20h */
+ .mask = WM8994_MIXOUTL_VOL_MASK,
+ .gain = WM8994_MIXOUT_VU | 0x39
+ }, {
+ .mode = VOICECALL_HP_NO_MIC,
+ .reg = WM8994_RIGHT_OPGA_VOLUME, /* 21h */
+ .mask = WM8994_MIXOUTR_VOL_MASK,
+ .gain = WM8994_MIXOUT_VU | 0x39
+ }, {
+ .mode = VOICECALL_HP_NO_MIC,
+ .reg = WM8994_LEFT_OUTPUT_VOLUME, /* 1Ch */
+ .mask = WM8994_HPOUT1L_VOL_MASK,
+ .gain = WM8994_HPOUT1_VU | 0x30
+ }, {
+ .mode = VOICECALL_HP_NO_MIC,
+ .reg = WM8994_RIGHT_OUTPUT_VOLUME, /* 1Dh */
+ .mask = WM8994_HPOUT1R_VOL_MASK,
+ .gain = WM8994_HPOUT1_VU | 0x30
+ }, { /* TTY_VCO */
+ .mode = VOICECALL_TTY_VCO,
+ .reg = WM8994_LEFT_LINE_INPUT_1_2_VOLUME, /* 18h */
+ .mask = WM8994_IN1L_VOL_MASK,
+ .gain = WM8994_IN1L_VU | 0x15 /* +10.5dB */
+ }, {
+ .mode = VOICECALL_TTY_VCO,
+ .reg = WM8994_INPUT_MIXER_3, /* 29h */
+ .mask = WM8994_IN1L_MIXINL_VOL_MASK | WM8994_MIXOUTL_MIXINL_VOL_MASK,
+ .gain = 0x0
+ }, { /* TTY_HCO */
+ .mode = VOICECALL_TTY_HCO,
+ .reg = WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, /* 1Ah */
+ .mask = WM8994_IN1R_VOL_MASK,
+ .gain = WM8994_IN1R_VU | 0x13 /* +12dB */
+ }, {
+ .mode = VOICECALL_TTY_HCO,
+ .reg = WM8994_INPUT_MIXER_4, /* 2Ah */
+ .mask = WM8994_IN1R_MIXINR_VOL_MASK | WM8994_MIXOUTR_MIXINR_VOL_MASK,
+ .gain = 0x0
+ }, { /* TTY_FULL */
+ .mode = VOICECALL_TTY_FULL,
+ .reg = WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, /* 1Ah */
+ .mask = WM8994_IN1R_VOL_MASK,
+ .gain = WM8994_IN1R_VU | 0x13 /* +12dB */
+ }, {
+ .mode = VOICECALL_TTY_FULL,
+ .reg = WM8994_INPUT_MIXER_4, /* 2Ah */
+ .mask = WM8994_IN1R_MIXINR_VOL_MASK | WM8994_MIXOUTR_MIXINR_VOL_MASK,
+ .gain = 0x0
+ },
+};
+
+struct gain_info_t playback_gain_table[PLAYBACK_GAIN_NUM] = {
+ { /* COMMON */
+ .mode = COMMON_SET_BIT,
+ .reg = WM8994_DAC1_LEFT_VOLUME, /* 610h */
+ .mask = WM8994_DAC1L_VOL_MASK,
+ .gain = WM8994_DAC1_VU | 0xC0
+ }, {
+ .mode = COMMON_SET_BIT,
+ .reg = WM8994_DAC1_RIGHT_VOLUME, /* 611h */
+ .mask = WM8994_DAC1R_VOL_MASK,
+ .gain = WM8994_DAC1_VU | 0xC0
+ }, {
+ .mode = COMMON_SET_BIT,
+ .reg = WM8994_AIF1_DAC1_LEFT_VOLUME, /* 402h */
+ .mask = WM8994_AIF1DAC1L_VOL_MASK,
+ .gain = WM8994_AIF1DAC1_VU | 0xC0
+ }, {
+ .mode = COMMON_SET_BIT,
+ .reg = WM8994_AIF1_DAC1_RIGHT_VOLUME, /* 403h */
+ .mask = WM8994_AIF1DAC1R_VOL_MASK,
+ .gain = WM8994_AIF1DAC1_VU | 0xC0
+ }, { /* RCV */
+ .mode = PLAYBACK_RCV,
+ .reg = WM8994_OUTPUT_MIXER_5, /* 31h */
+ .mask = WM8994_DACL_MIXOUTL_VOL_MASK,
+ .gain = 0x0 << WM8994_DACL_MIXOUTL_VOL_SHIFT
+ }, {
+ .mode = PLAYBACK_RCV,
+ .reg = WM8994_OUTPUT_MIXER_6, /* 32h */
+ .mask = WM8994_DACR_MIXOUTR_VOL_MASK,
+ .gain = 0x0 << WM8994_DACR_MIXOUTR_VOL_SHIFT
+ }, {
+ .mode = PLAYBACK_RCV,
+ .reg = WM8994_LEFT_OPGA_VOLUME, /* 20h */
+ .mask = WM8994_MIXOUTL_VOL_MASK,
+ .gain = WM8994_MIXOUT_VU | 0x3D
+ }, {
+ .mode = PLAYBACK_RCV,
+ .reg = WM8994_RIGHT_OPGA_VOLUME, /* 21h */
+ .mask = WM8994_MIXOUTR_VOL_MASK,
+ .gain = WM8994_MIXOUT_VU | 0x3D
+ }, {
+ .mode = PLAYBACK_RCV,
+ .reg = WM8994_HPOUT2_VOLUME, /* 1Fh */
+ .mask = WM8994_HPOUT2_VOL_MASK,
+ .gain = 0x0 << WM8994_HPOUT2_VOL_SHIFT
+ }, { /* SPK */
+ .mode = PLAYBACK_SPK,
+ .reg = WM8994_SPKMIXL_ATTENUATION, /* 22h */
+ .mask = WM8994_SPKMIXL_VOL_MASK,
+ .gain = 0x0
+ }, {
+ .mode = PLAYBACK_SPK,
+ .reg = WM8994_SPKMIXR_ATTENUATION, /* 23h */
+ .mask = WM8994_SPKMIXR_VOL_MASK,
+ .gain = 0x0
+ }, {
+ .mode = PLAYBACK_SPK,
+ .reg = WM8994_SPEAKER_VOLUME_LEFT, /* 26h */
+ .mask = WM8994_SPKOUTL_VOL_MASK,
+ .gain = WM8994_SPKOUT_VU | 0x3E /* +5dB */
+ }, {
+ .mode = PLAYBACK_SPK,
+ .reg = WM8994_SPEAKER_VOLUME_RIGHT, /* 27h */
+ .mask = WM8994_SPKOUTR_VOL_MASK,
+ .gain = 0
+ }, {
+ .mode = PLAYBACK_SPK,
+ .reg = WM8994_CLASSD, /* 25h */
+ .mask = WM8994_SPKOUTL_BOOST_MASK,
+ .gain = 0x05 << WM8994_SPKOUTL_BOOST_SHIFT /* +7.5dB */
+ }, {
+ .mode = PLAYBACK_SPK,
+ .reg = WM8994_AIF1_DAC1_LEFT_VOLUME, /* 402h */
+ .mask = WM8994_AIF1DAC1L_VOL_MASK,
+ .gain = WM8994_AIF1DAC1_VU | 0xB8 /* -2.625dB */
+ }, {
+ .mode = PLAYBACK_SPK,
+ .reg = WM8994_AIF1_DAC1_RIGHT_VOLUME, /* 403h */
+ .mask = WM8994_AIF1DAC1R_VOL_MASK,
+ .gain = WM8994_AIF1DAC1_VU | 0xB8 /* -2.625dB */
+ }, { /* HP */
+ .mode = PLAYBACK_HP,
+ .reg = WM8994_LEFT_OUTPUT_VOLUME, /* 1Ch */
+ .mask = WM8994_HPOUT1L_VOL_MASK,
+ .gain = WM8994_HPOUT1_VU | 0x31 /* -8dB */
+ }, {
+ .mode = PLAYBACK_HP,
+ .reg = WM8994_RIGHT_OUTPUT_VOLUME, /* 1Dh */
+ .mask = WM8994_HPOUT1R_VOL_MASK,
+ .gain = WM8994_HPOUT1_VU | 0x31 /* -8dB */
+ }, {
+ .mode = PLAYBACK_HP,
+ .reg = WM8994_LEFT_OPGA_VOLUME, /* 20h */
+ .mask = WM8994_MIXOUTL_VOL_MASK,
+ .gain = WM8994_MIXOUT_VU | 0x39
+ }, {
+ .mode = PLAYBACK_HP,
+ .reg = WM8994_RIGHT_OPGA_VOLUME, /* 21h */
+ .mask = WM8994_MIXOUTR_VOL_MASK,
+ .gain = WM8994_MIXOUT_VU | 0x39
+ }, { /* SPK_HP */
+ .mode = PLAYBACK_SPK_HP,
+ .reg = WM8994_SPKMIXL_ATTENUATION, /* 22h */
+ .mask = WM8994_SPKMIXL_VOL_MASK,
+ .gain = 0x0
+ }, {
+ .mode = PLAYBACK_SPK_HP,
+ .reg = WM8994_SPKMIXR_ATTENUATION, /* 23h */
+ .mask = WM8994_SPKMIXR_VOL_MASK,
+ .gain = 0x0
+ }, {
+ .mode = PLAYBACK_SPK_HP,
+ .reg = WM8994_SPEAKER_VOLUME_LEFT, /* 26h */
+ .mask = WM8994_SPKOUTL_VOL_MASK,
+ .gain = WM8994_SPKOUT_VU | 0x3E
+ }, {
+ .mode = PLAYBACK_SPK_HP,
+ .reg = WM8994_SPEAKER_VOLUME_RIGHT, /* 27h */
+ .mask = WM8994_SPKOUTR_VOL_MASK,
+ .gain = 0x0
+ }, {
+ .mode = PLAYBACK_SPK_HP,
+ .reg = WM8994_CLASSD, /* 25h */
+ .mask = WM8994_SPKOUTL_BOOST_MASK,
+ .gain = 0x5 << WM8994_SPKOUTL_BOOST_SHIFT
+ }, {
+ .mode = PLAYBACK_SPK_HP,
+ .reg = WM8994_LEFT_OUTPUT_VOLUME, /* 1Ch */
+ .mask = WM8994_HPOUT1L_VOL_MASK,
+ .gain = WM8994_HPOUT1_VU | 0x1E
+ }, {
+ .mode = PLAYBACK_SPK_HP,
+ .reg = WM8994_RIGHT_OUTPUT_VOLUME, /* 1Dh */
+ .mask = WM8994_HPOUT1R_VOL_MASK,
+ .gain = WM8994_HPOUT1_VU | 0x1E
+ }, {
+ .mode = PLAYBACK_SPK_HP,
+ .reg = WM8994_LEFT_OPGA_VOLUME, /* 20h */
+ .mask = WM8994_MIXOUTL_VOL_MASK,
+ .gain = WM8994_MIXOUT_VU | 0x39
+ }, {
+ .mode = PLAYBACK_SPK_HP,
+ .reg = WM8994_RIGHT_OPGA_VOLUME, /* 21h */
+ .mask = WM8994_MIXOUTR_VOL_MASK,
+ .gain = WM8994_MIXOUT_VU | 0x39
+ }, { /* RING_SPK */
+ .mode = PLAYBACK_RING_SPK,
+ .reg = WM8994_SPEAKER_VOLUME_LEFT, /* 26h */
+ .mask = WM8994_SPKOUTL_VOL_MASK,
+ .gain = WM8994_SPKOUT_VU | 0x3E
+ }, {
+ .mode = PLAYBACK_RING_SPK,
+ .reg = WM8994_CLASSD, /* 25h */
+ .mask = WM8994_SPKOUTL_BOOST_MASK,
+ .gain = 0x5 << WM8994_SPKOUTL_BOOST_SHIFT
+ }, { /* RING_HP */
+ .mode = PLAYBACK_RING_HP,
+ .reg = WM8994_LEFT_OUTPUT_VOLUME, /* 1Ch */
+ .mask = WM8994_HPOUT1L_VOL_MASK,
+ .gain = WM8994_HPOUT1_VU | 0x34
+ }, {
+ .mode = PLAYBACK_RING_HP,
+ .reg = WM8994_RIGHT_OUTPUT_VOLUME, /* 1Dh */
+ .mask = WM8994_HPOUT1R_VOL_MASK,
+ .gain = WM8994_HPOUT1_VU | 0x34
+ }, {
+ .mode = PLAYBACK_RING_HP,
+ .reg = WM8994_LEFT_OPGA_VOLUME, /* 20h */
+ .mask = WM8994_MIXOUTL_VOL_MASK,
+ .gain = WM8994_MIXOUT_VU | 0x39
+ }, {
+ .mode = PLAYBACK_RING_HP,
+ .reg = WM8994_RIGHT_OPGA_VOLUME, /* 21h */
+ .mask = WM8994_MIXOUTR_VOL_MASK,
+ .gain = WM8994_MIXOUT_VU | 0x39
+ }, { /* RING_SPK_HP */
+ .mode = PLAYBACK_RING_SPK_HP,
+ .reg = WM8994_SPEAKER_VOLUME_LEFT, /* 26h */
+ .mask = WM8994_SPKOUTL_VOL_MASK,
+ .gain = WM8994_SPKOUT_VU | 0x3E
+ }, {
+ .mode = PLAYBACK_RING_SPK_HP,
+ .reg = WM8994_CLASSD, /* 25h */
+ .mask = WM8994_SPKOUTL_BOOST_MASK,
+ .gain = 0x5 << WM8994_SPKOUTL_BOOST_SHIFT
+ }, {
+ .mode = PLAYBACK_RING_SPK_HP,
+ .reg = WM8994_LEFT_OUTPUT_VOLUME, /* 1Ch */
+ .mask = WM8994_HPOUT1L_VOL_MASK,
+ .gain = WM8994_HPOUT1_VU | 0x1E
+ }, {
+ .mode = PLAYBACK_RING_SPK_HP,
+ .reg = WM8994_RIGHT_OUTPUT_VOLUME, /* 1Dh */
+ .mask = WM8994_HPOUT1R_VOL_MASK,
+ .gain = WM8994_HPOUT1_VU | 0x1E
+ }, { /* HP_NO_MIC */
+ .mode = PLAYBACK_HP_NO_MIC,
+ .reg = WM8994_LEFT_OUTPUT_VOLUME, /* 1Ch */
+ .mask = WM8994_HPOUT1L_VOL_MASK,
+ .gain = WM8994_HPOUT1_VU | 0x36 /* -3dB */
+ }, {
+ .mode = PLAYBACK_HP_NO_MIC,
+ .reg = WM8994_RIGHT_OUTPUT_VOLUME, /* 1Dh */
+ .mask = WM8994_HPOUT1R_VOL_MASK,
+ .gain = WM8994_HPOUT1_VU | 0x36 /* -3dB */
+ }, {
+ .mode = PLAYBACK_HP_NO_MIC,
+ .reg = WM8994_LEFT_OPGA_VOLUME, /* 20h */
+ .mask = WM8994_MIXOUTL_VOL_MASK,
+ .gain = WM8994_MIXOUT_VU | 0x39
+ }, {
+ .mode = PLAYBACK_HP_NO_MIC,
+ .reg = WM8994_RIGHT_OPGA_VOLUME, /* 21h */
+ .mask = WM8994_MIXOUTR_VOL_MASK,
+ .gain = WM8994_MIXOUT_VU | 0x39
+ },
+};
+
+struct gain_info_t voicecall_gain_table[VOICECALL_GAIN_NUM] = {
+ { /* COMMON */
+ .mode = COMMON_SET_BIT,
+ .reg = WM8994_DAC1_LEFT_VOLUME, /* 610h */
+ .mask = WM8994_DAC1L_VOL_MASK,
+ .gain = WM8994_DAC1_VU | 0xC0 /* 0dB */
+ }, {
+ .mode = COMMON_SET_BIT,
+ .reg = WM8994_DAC1_RIGHT_VOLUME, /* 611h */
+ .mask = WM8994_DAC1R_VOL_MASK,
+ .gain = WM8994_DAC1_VU | 0xC0 /* 0dB */
+ }, {
+ .mode = COMMON_SET_BIT,
+ .reg = WM8994_AIF1_DAC1_LEFT_VOLUME, /* 402h */
+ .mask = WM8994_AIF1DAC1L_VOL_MASK,
+ .gain = WM8994_AIF1DAC1_VU | 0xC0 /* 0dB */
+ }, {
+ .mode = COMMON_SET_BIT,
+ .reg = WM8994_AIF1_DAC1_RIGHT_VOLUME, /* 403h */
+ .mask = WM8994_AIF1DAC1R_VOL_MASK,
+ .gain = WM8994_AIF1DAC1_VU | 0xC0 /* 0dB */
+ }, {
+ .mode = COMMON_SET_BIT,
+ .reg = WM8994_DAC2_LEFT_VOLUME, /* 612h */
+ .mask = WM8994_DAC2L_VOL_MASK,
+ .gain = WM8994_DAC2_VU | 0xC0 /* 0dB */
+ }, {
+ .mode = COMMON_SET_BIT,
+ .reg = WM8994_DAC2_RIGHT_VOLUME, /* 613h */
+ .mask = WM8994_DAC2R_VOL_MASK,
+ .gain = WM8994_DAC2_VU | 0xC0 /* 0dB */
+ }, { /* RCV */
+ .mode = VOICECALL_RCV,
+ .reg = WM8994_LEFT_LINE_INPUT_1_2_VOLUME, /* 18h */
+ .mask = WM8994_IN1L_VOL_MASK,
+ .gain = WM8994_IN1L_VU | 0x15 /* +15dB */
+ }, {
+ .mode = VOICECALL_RCV,
+ .reg = WM8994_INPUT_MIXER_3, /* 29h */
+ .mask = WM8994_IN1L_MIXINL_VOL_MASK | WM8994_MIXOUTL_MIXINL_VOL_MASK,
+ .gain = 0x10 /* +30dB */
+ }, {
+ .mode = VOICECALL_RCV,
+ .reg = WM8994_OUTPUT_MIXER_5, /* 31h */
+ .mask = WM8994_DACL_MIXOUTL_VOL_MASK,
+ .gain = 0x0 << WM8994_DACL_MIXOUTL_VOL_SHIFT
+ }, {
+ .mode = VOICECALL_RCV,
+ .reg = WM8994_OUTPUT_MIXER_6, /* 32h */
+ .mask = WM8994_DACR_MIXOUTR_VOL_MASK,
+ .gain = 0x0 << WM8994_DACR_MIXOUTR_VOL_SHIFT
+ }, {
+ .mode = VOICECALL_RCV,
+ .reg = WM8994_LEFT_OPGA_VOLUME, /* 20h */
+ .mask = WM8994_MIXOUTL_VOL_MASK,
+ .gain = WM8994_MIXOUT_VU | 0x3F
+ }, {
+ .mode = VOICECALL_RCV,
+ .reg = WM8994_RIGHT_OPGA_VOLUME, /* 21h */
+ .mask = WM8994_MIXOUTR_VOL_MASK,
+ .gain = WM8994_MIXOUT_VU | 0x3F
+ }, {
+ .mode = VOICECALL_RCV,
+ .reg = WM8994_HPOUT2_VOLUME, /* 1Fh */
+ .mask = WM8994_HPOUT2_VOL_MASK,
+ .gain = 0x0 << WM8994_HPOUT2_VOL_SHIFT
+ }, { /* SPK */
+ .mode = VOICECALL_SPK,
+ .reg = WM8994_INPUT_MIXER_3, /* 29h */
+ .mask = WM8994_IN1L_MIXINL_VOL_MASK | WM8994_MIXOUTL_MIXINL_VOL_MASK,
+ .gain = 0x10 /* Mic +7.5dB */
+ }, {
+ .mode = VOICECALL_SPK,
+ .reg = WM8994_LEFT_LINE_INPUT_1_2_VOLUME, /* 18h */
+ .mask = WM8994_IN1L_VOL_MASK,
+ .gain = WM8994_IN1L_VU | 0x12 /* Mic +30dB */
+ }, {
+ .mode = VOICECALL_SPK,
+ .reg = WM8994_SPKMIXL_ATTENUATION, /* 22h */
+ .mask = WM8994_SPKMIXL_VOL_MASK,
+ .gain = 0x0 /* Speaker +0dB */
+ }, {
+ .mode = VOICECALL_SPK,
+ .reg = WM8994_SPKMIXR_ATTENUATION, /* 23h */
+ .mask = WM8994_SPKMIXR_VOL_MASK,
+ .gain = 0x0 /* Speaker +0dB */
+ }, {
+ .mode = VOICECALL_SPK,
+ .reg = WM8994_SPEAKER_VOLUME_LEFT, /* 26h */
+ .mask = WM8994_SPKOUTL_VOL_MASK,
+ .gain = WM8994_SPKOUT_VU | 0x3C /* Left Speaker +3dB */
+ }, {
+ .mode = VOICECALL_SPK,
+ .reg = WM8994_SPEAKER_VOLUME_RIGHT, /* 27h */
+ .mask = WM8994_SPKOUTR_VOL_MASK, /* Right Speaker -57dB */
+ .gain = 0x0
+ }, {
+ .mode = VOICECALL_SPK,
+ .reg = WM8994_CLASSD, /* 25h */
+ .mask = WM8994_SPKOUTL_BOOST_MASK,
+ .gain = 0x7 << WM8994_SPKOUTL_BOOST_SHIFT /* Left spaker +12dB */
+ }, { /* HP */
+ .mode = VOICECALL_HP,
+ .reg = WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, /* 1Ah */
+ .mask = WM8994_IN1R_VOL_MASK,
+ .gain = WM8994_IN1R_VU | 0x1D
+ }, {
+ .mode = VOICECALL_HP,
+ .reg = WM8994_INPUT_MIXER_4, /* 2Ah */
+ .mask = WM8994_IN1R_MIXINR_VOL_MASK | WM8994_MIXOUTR_MIXINR_VOL_MASK,
+ .gain = 0x0
+ }, {
+ .mode = VOICECALL_HP,
+ .reg = WM8994_LEFT_OPGA_VOLUME, /* 20h */
+ .mask = WM8994_MIXOUTL_VOL_MASK,
+ .gain = WM8994_MIXOUT_VU | 0x39
+ }, {
+ .mode = VOICECALL_HP,
+ .reg = WM8994_RIGHT_OPGA_VOLUME, /* 21h */
+ .mask = WM8994_MIXOUTR_VOL_MASK,
+ .gain = WM8994_MIXOUT_VU | 0x39
+ }, {
+ .mode = VOICECALL_HP,
+ .reg = WM8994_LEFT_OUTPUT_VOLUME, /* 1Ch */
+ .mask = WM8994_HPOUT1L_VOL_MASK,
+ .gain = WM8994_HPOUT1_VU | 0x30
+ }, {
+ .mode = VOICECALL_HP,
+ .reg = WM8994_RIGHT_OUTPUT_VOLUME, /* 1Dh */
+ .mask = WM8994_HPOUT1R_VOL_MASK,
+ .gain = WM8994_HPOUT1_VU | 0x30
+ }, { /* HP_NO_MIC */
+ .mode = VOICECALL_HP_NO_MIC,
+ .reg = WM8994_LEFT_LINE_INPUT_1_2_VOLUME, /* 18h */
+ .mask = WM8994_IN1L_VOL_MASK,
+ .gain = WM8994_IN1L_VU | 0x12 /* +10.5dB */
+ }, {
+ .mode = VOICECALL_HP_NO_MIC,
+ .reg = WM8994_INPUT_MIXER_3, /* 29h */
+ .mask = WM8994_IN1L_MIXINL_VOL_MASK | WM8994_MIXOUTL_MIXINL_VOL_MASK,
+ .gain = 0x10
+ }, {
+ .mode = VOICECALL_HP_NO_MIC,
+ .reg = WM8994_LEFT_OPGA_VOLUME, /* 20h */
+ .mask = WM8994_MIXOUTL_VOL_MASK,
+ .gain = WM8994_MIXOUT_VU | 0x39
+ }, {
+ .mode = VOICECALL_HP_NO_MIC,
+ .reg = WM8994_RIGHT_OPGA_VOLUME, /* 21h */
+ .mask = WM8994_MIXOUTR_VOL_MASK,
+ .gain = WM8994_MIXOUT_VU | 0x39
+ }, {
+ .mode = VOICECALL_HP_NO_MIC,
+ .reg = WM8994_LEFT_OUTPUT_VOLUME, /* 1Ch */
+ .mask = WM8994_HPOUT1L_VOL_MASK,
+ .gain = WM8994_HPOUT1_VU | 0x30
+ }, {
+ .mode = VOICECALL_HP_NO_MIC,
+ .reg = WM8994_RIGHT_OUTPUT_VOLUME, /* 1Dh */
+ .mask = WM8994_HPOUT1R_VOL_MASK,
+ .gain = WM8994_HPOUT1_VU | 0x30
+ }, { /* TTY_VCO */
+ .mode = VOICECALL_TTY_VCO,
+ .reg = WM8994_LEFT_LINE_INPUT_1_2_VOLUME, /* 18h */
+ .mask = WM8994_IN1L_VOL_MASK,
+ .gain = WM8994_IN1L_VU | 0x15 /* +10.5dB */
+ }, {
+ .mode = VOICECALL_TTY_VCO,
+ .reg = WM8994_INPUT_MIXER_3, /* 29h */
+ .mask = WM8994_IN1L_MIXINL_VOL_MASK | WM8994_MIXOUTL_MIXINL_VOL_MASK,
+ .gain = 0x0
+ }, { /* TTY_HCO */
+ .mode = VOICECALL_TTY_HCO,
+ .reg = WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, /* 1Ah */
+ .mask = WM8994_IN1R_VOL_MASK,
+ .gain = WM8994_IN1R_VU | 0x13 /* +12dB */
+ }, {
+ .mode = VOICECALL_TTY_HCO,
+ .reg = WM8994_INPUT_MIXER_4, /* 2Ah */
+ .mask = WM8994_IN1R_MIXINR_VOL_MASK | WM8994_MIXOUTR_MIXINR_VOL_MASK,
+ .gain = 0x0
+ }, { /* TTY_FULL */
+ .mode = VOICECALL_TTY_FULL,
+ .reg = WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, /* 1Ah */
+ .mask = WM8994_IN1R_VOL_MASK,
+ .gain = WM8994_IN1R_VU | 0x13 /* +12dB */
+ }, {
+ .mode = VOICECALL_TTY_FULL,
+ .reg = WM8994_INPUT_MIXER_4, /* 2Ah */
+ .mask = WM8994_IN1R_MIXINR_VOL_MASK | WM8994_MIXOUTR_MIXINR_VOL_MASK,
+ .gain = 0x0
+ },
+};
+
+struct gain_info_t recording_gain_table[RECORDING_GAIN_NUM] = {
+ { /* MAIN */
+ .mode = RECORDING_MAIN,
+ .reg = WM8994_LEFT_LINE_INPUT_1_2_VOLUME, /* 18h */
+ .mask = WM8994_IN1L_VOL_MASK,
+ .gain = WM8994_IN1L_VU | 0x12 /* +10.5dB */
+ }, {
+ .mode = RECORDING_MAIN,
+ .reg = WM8994_INPUT_MIXER_3, /* 29h */
+ .mask = WM8994_IN1L_MIXINL_VOL_MASK | WM8994_MIXOUTL_MIXINL_VOL_MASK,
+ .gain = 0x10 /* +30dB */
+ }, {
+ .mode = RECORDING_MAIN,
+ .reg = WM8994_AIF1_ADC1_LEFT_VOLUME, /* 400h */
+ .mask = WM8994_AIF1ADC1L_VOL_MASK,
+ .gain = WM8994_AIF1ADC1_VU | 0xC0 /* 0dB */
+ }, {
+ .mode = RECORDING_MAIN,
+ .reg = WM8994_AIF1_ADC1_RIGHT_VOLUME, /* 401h */
+ .mask = WM8994_AIF1ADC1R_VOL_MASK,
+ .gain = WM8994_AIF1ADC1_VU | 0xC0 /* 0dB */
+ }, { /* HP */
+ .mode = RECORDING_HP,
+ .reg = WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, /* 1Ah */
+ .mask = WM8994_IN1R_VOL_MASK,
+ .gain = WM8994_IN1R_VU | 0x15
+ }, {
+ .mode = RECORDING_HP,
+ .reg = WM8994_INPUT_MIXER_4, /* 2Ah */
+ .mask = WM8994_IN1R_MIXINR_VOL_MASK | WM8994_MIXOUTR_MIXINR_VOL_MASK,
+ .gain = 0x10
+ }, {
+ .mode = RECORDING_HP,
+ .reg = WM8994_AIF1_ADC1_LEFT_VOLUME, /* 400h */
+ .mask = WM8994_AIF1ADC1L_VOL_MASK,
+ .gain = WM8994_AIF1ADC1_VU | 0xC0
+ }, {
+ .mode = RECORDING_HP,
+ .reg = WM8994_AIF1_ADC1_RIGHT_VOLUME, /* 401h */
+ .mask = WM8994_AIF1ADC1R_VOL_MASK,
+ .gain = WM8994_AIF1ADC1_VU | 0xC0
+ }, { /* RECOGNITION_MAIN */
+ .mode = RECORDING_REC_MAIN,
+ .reg = WM8994_LEFT_LINE_INPUT_1_2_VOLUME, /* 18h */
+ .mask = WM8994_IN1L_VOL_MASK,
+ .gain = WM8994_IN1L_VU | 0x0D /* +3dB */
+ }, {
+ .mode = RECORDING_REC_MAIN,
+ .reg = WM8994_INPUT_MIXER_3, /* 29h */
+ .mask = WM8994_IN1L_MIXINL_VOL_MASK | WM8994_MIXOUTL_MIXINL_VOL_MASK,
+ .gain = 0x10 /* 30dB */
+ }, {
+ .mode = RECORDING_REC_MAIN,
+ .reg = WM8994_AIF1_ADC1_LEFT_VOLUME, /* 400h */
+ .mask = WM8994_AIF1ADC1L_VOL_MASK,
+ .gain = WM8994_AIF1ADC1_VU | 0xc0 /* +0dB */
+ }, {
+ .mode = RECORDING_REC_MAIN,
+ .reg = WM8994_AIF1_ADC1_RIGHT_VOLUME, /* 401h */
+ .mask = WM8994_AIF1ADC1R_VOL_MASK,
+ .gain = WM8994_AIF1ADC1_VU | 0xc0 /* +0dB */
+ }, { /* RECOGNITION_HP */
+ .mode = RECORDING_REC_HP,
+ .reg = WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, /* 1Ah */
+ .mask = WM8994_IN1R_VOL_MASK,
+ .gain = WM8994_IN1R_VU | 0x12 /* +10.5dB */
+ }, {
+ .mode = RECORDING_REC_HP,
+ .reg = WM8994_INPUT_MIXER_4, /* 2Ah */
+ .mask = WM8994_IN1R_MIXINR_VOL_MASK | WM8994_MIXOUTR_MIXINR_VOL_MASK,
+ .gain = 0x10 /* +30dB */
+ }, {
+ .mode = RECORDING_REC_HP,
+ .reg = WM8994_AIF1_ADC1_LEFT_VOLUME, /* 400h */
+ .mask = WM8994_AIF1ADC1L_VOL_MASK,
+ .gain = WM8994_AIF1ADC1_VU | 0xC0
+ }, {
+ .mode = RECORDING_REC_HP,
+ .reg = WM8994_AIF1_ADC1_RIGHT_VOLUME, /* 401h */
+ .mask = WM8994_AIF1ADC1R_VOL_MASK,
+ .gain = WM8994_AIF1ADC1_VU | 0xC0
+ }, { /* CAMCORDER_MAIN */
+ .mode = RECORDING_CAM_MAIN,
+ .reg = WM8994_LEFT_LINE_INPUT_1_2_VOLUME, /* 18h */
+ .mask = WM8994_IN1L_VOL_MASK,
+ .gain = WM8994_IN1L_VU | 0x17 /* +18dB */
+ }, {
+ .mode = RECORDING_CAM_MAIN,
+ .reg = WM8994_INPUT_MIXER_3, /* 29h */
+ .mask = WM8994_IN1L_MIXINL_VOL_MASK | WM8994_MIXOUTL_MIXINL_VOL_MASK,
+ .gain = 0x10 /* 30dB */
+ }, {
+ .mode = RECORDING_CAM_MAIN,
+ .reg = WM8994_AIF1_ADC1_LEFT_VOLUME, /* 400h */
+ .mask = WM8994_AIF1ADC1L_VOL_MASK,
+ .gain = WM8994_AIF1ADC1_VU | 0xC0 /* +0dB */
+ }, {
+ .mode = RECORDING_CAM_MAIN,
+ .reg = WM8994_AIF1_ADC1_RIGHT_VOLUME, /* 401h */
+ .mask = WM8994_AIF1ADC1R_VOL_MASK,
+ .gain = WM8994_AIF1ADC1_VU | 0xC0 /* +0dB */
+ }, { /* CAMCORDER_HP */
+ .mode = RECORDING_CAM_HP,
+ .reg = WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, /* 1Ah */
+ .mask = WM8994_IN1R_VOL_MASK,
+ .gain = WM8994_IN1R_VU | 0x15 /* +15dB */
+ }, {
+ .mode = RECORDING_CAM_HP,
+ .reg = WM8994_INPUT_MIXER_4, /* 2Ah */
+ .mask = WM8994_IN1R_MIXINR_VOL_MASK | WM8994_MIXOUTR_MIXINR_VOL_MASK,
+ .gain = 0x10 /* +30dB */
+ }, {
+ .mode = RECORDING_CAM_HP,
+ .reg = WM8994_AIF1_ADC1_LEFT_VOLUME, /* 400h */
+ .mask = WM8994_AIF1ADC1L_VOL_MASK,
+ .gain = WM8994_AIF1ADC1_VU | 0xC0
+ }, {
+ .mode = RECORDING_CAM_HP,
+ .reg = WM8994_AIF1_ADC1_RIGHT_VOLUME, /* 401h */
+ .mask = WM8994_AIF1ADC1R_VOL_MASK,
+ .gain = WM8994_AIF1ADC1_VU | 0xC0
+ }, { /* VOICE COMMUNICATION MAIN */
+ .mode = RECORDING_VC_MAIN,
+ .reg = WM8994_LEFT_LINE_INPUT_1_2_VOLUME, /* 18h */
+ .mask = WM8994_IN1L_VOL_MASK,
+ .gain = WM8994_IN1L_VU | 0x12 /* +10.5dB */
+ }, {
+ .mode = RECORDING_VC_MAIN,
+ .reg = WM8994_INPUT_MIXER_3, /* 29h */
+ .mask = WM8994_IN1L_MIXINL_VOL_MASK | WM8994_MIXOUTL_MIXINL_VOL_MASK,
+ .gain = 0x10 /* +30dB */
+ }, {
+ .mode = RECORDING_VC_MAIN,
+ .reg = WM8994_AIF1_ADC1_LEFT_VOLUME, /* 400h */
+ .mask = WM8994_AIF1ADC1L_VOL_MASK,
+ .gain = WM8994_AIF1ADC1_VU | 0xC0 /* 0dB */
+ }, {
+ .mode = RECORDING_VC_MAIN,
+ .reg = WM8994_AIF1_ADC1_RIGHT_VOLUME, /* 401h */
+ .mask = WM8994_AIF1ADC1R_VOL_MASK,
+ .gain = WM8994_AIF1ADC1_VU | 0xC0 /* 0dB */
+ }, { /* VOICE COMMUNICATION HP */
+ .mode = RECORDING_VC_HP,
+ .reg = WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, /* 1Ah */
+ .mask = WM8994_IN1R_VOL_MASK,
+ .gain = WM8994_IN1R_VU | 0x15
+ }, {
+ .mode = RECORDING_VC_HP,
+ .reg = WM8994_INPUT_MIXER_4, /* 2Ah */
+ .mask = WM8994_IN1R_MIXINR_VOL_MASK | WM8994_MIXOUTR_MIXINR_VOL_MASK,
+ .gain = 0x10
+ }, {
+ .mode = RECORDING_VC_HP,
+ .reg = WM8994_AIF1_ADC1_LEFT_VOLUME, /* 400h */
+ .mask = WM8994_AIF1ADC1L_VOL_MASK,
+ .gain = WM8994_AIF1ADC1_VU | 0xC0
+ }, {
+ .mode = RECORDING_VC_HP,
+ .reg = WM8994_AIF1_ADC1_RIGHT_VOLUME, /* 401h */
+ .mask = WM8994_AIF1ADC1R_VOL_MASK,
+ .gain = WM8994_AIF1ADC1_VU | 0xC0
+ }
+};
+
+struct gain_info_t gain_code_table[GAIN_CODE_NUM] = {
+ /* Playback */
+ {/* HP */
+ .mode = PLAYBACK_HP | PLAYBACK_MODE | GAIN_DIVISION_BIT_1,
+ .reg = WM8994_LEFT_OUTPUT_VOLUME, /* 1Ch */
+ .mask = WM8994_HPOUT1L_VOL_MASK,
+ .gain = WM8994_HPOUT1_VU | 0x31 /* -8dB */
+ }, {
+ .mode = PLAYBACK_HP | PLAYBACK_MODE | GAIN_DIVISION_BIT_1,
+ .reg = WM8994_RIGHT_OUTPUT_VOLUME, /* 1Dh */
+ .mask = WM8994_HPOUT1R_VOL_MASK,
+ .gain = WM8994_HPOUT1_VU | 0x31 /* -8dB */
+ }, {/* HP_NO_MIC */
+ .mode = PLAYBACK_HP_NO_MIC | PLAYBACK_MODE | GAIN_DIVISION_BIT_1,
+ .reg = WM8994_LEFT_OUTPUT_VOLUME, /* 1Ch */
+ .mask = WM8994_HPOUT1L_VOL_MASK,
+ .gain = WM8994_HPOUT1_VU | 0x31 /* -8dB */
+ }, {
+ .mode = PLAYBACK_HP_NO_MIC | PLAYBACK_MODE | GAIN_DIVISION_BIT_1,
+ .reg = WM8994_RIGHT_OUTPUT_VOLUME, /* 1Dh */
+ .mask = WM8994_HPOUT1R_VOL_MASK,
+ .gain = WM8994_HPOUT1_VU | 0x31 /* -8dB */
+ }, {/* Voicecall RCV */
+ .mode = VOICECALL_RCV | VOICECALL_MODE | GAIN_DIVISION_BIT_1,
+ .reg = WM8994_LEFT_LINE_INPUT_1_2_VOLUME, /* 18h */
+ .mask = WM8994_IN1L_VOL_MASK,
+ .gain = WM8994_IN1L_VU | 0x14 /* +13.5dB */
+ }, {/* SPK */
+ .mode = VOICECALL_SPK | VOICECALL_MODE | GAIN_DIVISION_BIT_1,
+ .reg = WM8994_LEFT_LINE_INPUT_1_2_VOLUME, /* 18h */
+ .mask = WM8994_IN1L_VOL_MASK,
+ .gain = WM8994_IN1L_VU | 0x0D /* +3dB */
+ }, {
+ .mode = VOICECALL_SPK | VOICECALL_MODE | GAIN_DIVISION_BIT_1,
+ .reg = WM8994_SPEAKER_VOLUME_LEFT, /* 26h */
+ .mask = WM8994_SPKOUTL_VOL_MASK,
+ .gain = WM8994_SPKOUT_VU | 0x3A /* +1dB */
+ }, {/* HP */
+ .mode = VOICECALL_HP | VOICECALL_MODE | GAIN_DIVISION_BIT_1,
+ .reg = WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, /* 1Ah */
+ .mask = WM8994_IN1R_VOL_MASK,
+ .gain = WM8994_IN1R_VU | 0x1D /* +27dB */
+ }, {
+ .mode = VOICECALL_HP | VOICECALL_MODE | GAIN_DIVISION_BIT_1,
+ .reg = WM8994_LEFT_OUTPUT_VOLUME, /* 1Ch */
+ .mask = WM8994_HPOUT1L_VOL_MASK,
+ .gain = WM8994_HPOUT1_VU | 0x3a /* +1dB */
+ }, {
+ .mode = VOICECALL_HP | VOICECALL_MODE | GAIN_DIVISION_BIT_1,
+ .reg = WM8994_RIGHT_OUTPUT_VOLUME, /* 1Dh */
+ .mask = WM8994_HPOUT1R_VOL_MASK,
+ .gain = WM8994_HPOUT1_VU | 0x3a /* +1dB */
+ }, {/* HP_NO_MIC */
+ .mode = VOICECALL_HP_NO_MIC | VOICECALL_MODE | GAIN_DIVISION_BIT_1,
+ .reg = WM8994_LEFT_LINE_INPUT_1_2_VOLUME, /* 18h */
+ .mask = WM8994_IN1L_VOL_MASK,
+ .gain = WM8994_IN1L_VU | 0x12 /* +10.5dB */
+ }, {
+ .mode = VOICECALL_HP_NO_MIC | VOICECALL_MODE | GAIN_DIVISION_BIT_1,
+ .reg = WM8994_LEFT_OUTPUT_VOLUME, /* 1Ch */
+ .mask = WM8994_HPOUT1L_VOL_MASK,
+ .gain = WM8994_HPOUT1_VU | 0x3a /* +1dB */
+ }, {
+ .mode = VOICECALL_HP_NO_MIC | VOICECALL_MODE | GAIN_DIVISION_BIT_1,
+ .reg = WM8994_RIGHT_OUTPUT_VOLUME, /* 1Dh */
+ .mask = WM8994_HPOUT1R_VOL_MASK,
+ .gain = WM8994_HPOUT1_VU | 0x3a /* +1dB */
+ },
+};
+
+static void wait_for_dc_servo(struct snd_soc_codec *codec, unsigned int op)
+{
+ unsigned int reg;
+ int count = 0;
+ unsigned int val, start;
+
+ val = op | WM8994_DCS_ENA_CHAN_0 | WM8994_DCS_ENA_CHAN_1;
+
+ /* Trigger the command */
+ snd_soc_write(codec, WM8994_DC_SERVO_1, val);
+
+ start = jiffies;
+ pr_debug("Waiting for DC servo...\n");
+
+ do {
+ count++;
+ msleep(1);
+ reg = snd_soc_read(codec, WM8994_DC_SERVO_1);
+ pr_debug("DC servo: %x\n", reg);
+ } while (reg & op && count < 400);
+
+ pr_info("DC servo took %dms\n", jiffies_to_msecs(jiffies - start));
+
+ if (reg & op)
+ pr_err("Timed out waiting for DC Servo\n");
+}
+
+/* S5P_SLEEP_CONFIG must be controlled by codec if codec use XUSBTI */
+int wm8994_configure_clock(struct snd_soc_codec *codec, int en)
+{
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+ if (en) {
+ clk_enable(wm8994->codec_clk);
+ DEBUG_LOG("USBOSC Enabled in Sleep Mode\n");
+ } else {
+ clk_disable(wm8994->codec_clk);
+ DEBUG_LOG("USBOSC disable in Sleep Mode\n");
+ }
+
+ return 0;
+}
+
+void audio_ctrl_mic_bias_gpio(struct wm8994_platform_data *pdata, int enable)
+{
+ DEBUG_LOG("enable = [%d]", enable);
+
+ if (!pdata)
+ pr_err("failed to turn off micbias pin\n");
+ else {
+ if (enable)
+ pdata->set_mic_bias(true);
+ else
+ pdata->set_mic_bias(false);
+ }
+}
+
+static int wm8994_earsel_control(struct wm8994_platform_data *pdata, int en)
+{
+
+ if (!pdata) {
+ pr_err("failed to control wm8994 ear selection\n");
+ return -EINVAL;
+ }
+
+ gpio_set_value(pdata->ear_sel, en);
+
+ return 0;
+
+}
+
+/* Audio Routing routines for the universal board..wm8994 codec*/
+void wm8994_disable_path(struct snd_soc_codec *codec)
+{
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+ u16 val;
+ enum audio_path path = wm8994->cur_path;
+
+ DEBUG_LOG("Path = [%d]", path);
+
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_1);
+
+ switch (path) {
+ case RCV:
+ /* Disbale the HPOUT2 */
+ val &= ~(WM8994_HPOUT2_ENA_MASK);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, val);
+
+ /* Disable left MIXOUT */
+ val = wm8994_read(codec, WM8994_OUTPUT_MIXER_1);
+ val &= ~(WM8994_DAC1L_TO_MIXOUTL_MASK);
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_1, val);
+
+ /* Disable right MIXOUT */
+ val = wm8994_read(codec, WM8994_OUTPUT_MIXER_2);
+ val &= ~(WM8994_DAC1R_TO_MIXOUTR_MASK);
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_2, val);
+
+ /* Disable HPOUT Mixer */
+ val = wm8994_read(codec, WM8994_HPOUT2_MIXER);
+ val &= ~(WM8994_MIXOUTLVOL_TO_HPOUT2_MASK |
+ WM8994_MIXOUTRVOL_TO_HPOUT2_MASK);
+ wm8994_write(codec, WM8994_HPOUT2_MIXER, val);
+
+ /* Disable mixout volume control */
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_3);
+ val &= ~(WM8994_MIXOUTLVOL_ENA_MASK |
+ WM8994_MIXOUTRVOL_ENA_MASK |
+ WM8994_MIXOUTL_ENA_MASK |
+ WM8994_MIXOUTR_ENA_MASK);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, val);
+ break;
+
+ case SPK:
+ /* Disbale the SPKOUTL */
+ val &= ~(WM8994_SPKOUTL_ENA_MASK);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, val);
+
+ /* Disable SPKLVOL */
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_3);
+ val &= ~(WM8994_SPKLVOL_ENA_MASK);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, val);
+
+ /* Disable SPKOUT mixer */
+ val = wm8994_read(codec, WM8994_SPKOUT_MIXERS);
+ val &= ~(WM8994_SPKMIXL_TO_SPKOUTL_MASK |
+ WM8994_SPKMIXR_TO_SPKOUTL_MASK |
+ WM8994_SPKMIXR_TO_SPKOUTR_MASK);
+ wm8994_write(codec, WM8994_SPKOUT_MIXERS, val);
+
+ /* Mute Speaker mixer */
+ val = wm8994_read(codec, WM8994_SPEAKER_MIXER);
+ val &= ~(WM8994_DAC1L_TO_SPKMIXL_MASK);
+ wm8994_write(codec, WM8994_SPEAKER_MIXER, val);
+ break;
+
+ case HP:
+ case HP_NO_MIC:
+ val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME);
+ val &= ~(0x02C0);
+ val |= 0x02C0;
+ wm8994_write(codec, WM8994_DAC1_LEFT_VOLUME, 0x02C0);
+
+ val = wm8994_read(codec, WM8994_DAC1_RIGHT_VOLUME);
+ val &= ~(0x02C0);
+ val |= 0x02C0;
+ wm8994_write(codec, WM8994_DAC1_RIGHT_VOLUME, 0x02C0);
+
+ val = wm8994_read(codec, WM8994_ANALOGUE_HP_1);
+ val &= ~(0x0022);
+ val |= 0x0022;
+ wm8994_write(codec, WM8994_ANALOGUE_HP_1, 0x0022);
+
+ val = wm8994_read(codec, WM8994_OUTPUT_MIXER_1);
+ val &= ~(0x0);
+ val |= 0x0;
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_1, 0x0);
+
+ val = wm8994_read(codec, WM8994_OUTPUT_MIXER_2);
+ val &= ~(0x0);
+ val |= 0x0;
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_2, 0x0);
+
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_5);
+ val &= ~(0x0300);
+ val |= 0x0300;
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_5, 0x0300);
+
+ val = wm8994_read(codec, WM8994_CHARGE_PUMP_1);
+ val &= ~(0x1F25);
+ val |= 0x1F25;
+ wm8994_write(codec, WM8994_CHARGE_PUMP_1, 0x1F25);
+ break;
+
+ case BT:
+ val = wm8994_read(codec, WM8994_AIF1_DAC1_FILTERS_1);
+ val &= ~(WM8994_AIF1DAC1_MUTE_MASK | WM8994_AIF1DAC1_MONO_MASK);
+ val |= (WM8994_AIF1DAC1_MUTE);
+ wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, val);
+ break;
+
+ case SPK_HP:
+ val &= ~(WM8994_HPOUT1L_ENA_MASK | WM8994_HPOUT1R_ENA_MASK |
+ WM8994_SPKOUTL_ENA_MASK);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, val);
+
+ /* Disable DAC1L to HPOUT1L path */
+ val = wm8994_read(codec, WM8994_OUTPUT_MIXER_1);
+ val &= ~(WM8994_DAC1L_TO_HPOUT1L_MASK |
+ WM8994_DAC1L_TO_MIXOUTL_MASK);
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_1, val);
+
+ /* Disable DAC1R to HPOUT1R path */
+ val = wm8994_read(codec, WM8994_OUTPUT_MIXER_2);
+ val &= ~(WM8994_DAC1R_TO_HPOUT1R_MASK |
+ WM8994_DAC1R_TO_MIXOUTR_MASK);
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_2, val);
+
+ /* Disable Charge Pump */
+ val = wm8994_read(codec, WM8994_CHARGE_PUMP_1);
+ val &= ~WM8994_CP_ENA_MASK;
+ val |= WM8994_CP_ENA_DEFAULT;
+ wm8994_write(codec, WM8994_CHARGE_PUMP_1, val);
+
+ /* Intermediate HP settings */
+ val = wm8994_read(codec, WM8994_ANALOGUE_HP_1);
+ val &= ~(WM8994_HPOUT1R_DLY_MASK | WM8994_HPOUT1R_OUTP_MASK |
+ WM8994_HPOUT1R_RMV_SHORT_MASK | WM8994_HPOUT1L_DLY_MASK |
+ WM8994_HPOUT1L_OUTP_MASK | WM8994_HPOUT1L_RMV_SHORT_MASK);
+ wm8994_write(codec, WM8994_ANALOGUE_HP_1, val);
+
+ /* Disable SPKLVOL */
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_3);
+ val &= ~(WM8994_SPKLVOL_ENA_MASK);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, val);
+
+ /* Disable SPKOUT mixer */
+ val = wm8994_read(codec, WM8994_SPKOUT_MIXERS);
+ val &= ~(WM8994_SPKMIXL_TO_SPKOUTL_MASK |
+ WM8994_SPKMIXR_TO_SPKOUTL_MASK |
+ WM8994_SPKMIXR_TO_SPKOUTR_MASK);
+ wm8994_write(codec, WM8994_SPKOUT_MIXERS, val);
+
+ /* Mute Speaker mixer */
+ val = wm8994_read(codec, WM8994_SPEAKER_MIXER);
+ val &= ~(WM8994_DAC1L_TO_SPKMIXL_MASK);
+ wm8994_write(codec, WM8994_SPEAKER_MIXER, val);
+ break;
+
+ default:
+ DEBUG_LOG_ERR("Path[%d] is not invaild!\n", path);
+ return;
+ break;
+ }
+}
+
+void wm8994_disable_rec_path(struct snd_soc_codec *codec)
+{
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+ u16 val;
+ enum mic_path mic = wm8994->rec_path;
+
+ wm8994->rec_path = MIC_OFF;
+
+ if (!(wm8994->codec_state & CALL_ACTIVE))
+ audio_ctrl_mic_bias_gpio(wm8994->pdata, 0);
+
+ switch (mic) {
+ case MAIN:
+ DEBUG_LOG("Disabling MAIN Mic Path..\n");
+
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_2);
+ val &= ~(WM8994_IN1L_ENA_MASK | WM8994_MIXINL_ENA_MASK);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_2, val);
+
+ /* Mute IN1L PGA, update volume */
+ val = wm8994_read(codec,
+ WM8994_LEFT_LINE_INPUT_1_2_VOLUME);
+ val &= ~(WM8994_IN1L_MUTE_MASK | WM8994_IN1L_VOL_MASK);
+ val |= (WM8994_IN1L_VU | WM8994_IN1L_MUTE);
+ wm8994_write(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME,
+ val);
+
+ /*Mute the PGA */
+ val = wm8994_read(codec, WM8994_INPUT_MIXER_3);
+ val &= ~(WM8994_IN1L_TO_MIXINL_MASK |
+ WM8994_IN1L_MIXINL_VOL_MASK |
+ WM8994_MIXOUTL_MIXINL_VOL_MASK);
+ wm8994_write(codec, WM8994_INPUT_MIXER_3, val);
+
+ /* Disconnect IN1LN ans IN1LP to the inputs */
+ val = wm8994_read(codec, WM8994_INPUT_MIXER_2);
+ val &= (WM8994_IN1LN_TO_IN1L_MASK | WM8994_IN1LP_TO_IN1L_MASK);
+ wm8994_write(codec, WM8994_INPUT_MIXER_2, val);
+
+ /* Digital Paths */
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_4);
+ val &= ~(WM8994_ADCL_ENA_MASK | WM8994_AIF1ADC1L_ENA_MASK);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_4, val);
+
+ /* Disable timeslots */
+ val = wm8994_read(codec, WM8994_AIF1_ADC1_LEFT_MIXER_ROUTING);
+ val &= ~(WM8994_ADC1L_TO_AIF1ADC1L);
+ wm8994_write(codec, WM8994_AIF1_ADC1_LEFT_MIXER_ROUTING, val);
+ break;
+
+ case SUB:
+ DEBUG_LOG("Disbaling SUB Mic path..\n");
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_2);
+ val &= ~(WM8994_IN1R_ENA_MASK | WM8994_MIXINR_ENA_MASK);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_2, val);
+
+ /* Disable volume,unmute Right Line */
+ val = wm8994_read(codec,
+ WM8994_RIGHT_LINE_INPUT_1_2_VOLUME);
+ val &= ~WM8994_IN1R_MUTE_MASK; /* Unmute IN1R */
+ val |= (WM8994_IN1R_VU | WM8994_IN1R_MUTE);
+ wm8994_write(codec, WM8994_RIGHT_LINE_INPUT_1_2_VOLUME,
+ val);
+
+ /* Mute right pga, set volume */
+ val = wm8994_read(codec, WM8994_INPUT_MIXER_4);
+ val &= ~(WM8994_IN1R_TO_MIXINR_MASK |
+ WM8994_IN1R_MIXINR_VOL_MASK |
+ WM8994_MIXOUTR_MIXINR_VOL_MASK);
+ wm8994_write(codec, WM8994_INPUT_MIXER_4, val);
+
+ /* Disconnect in1rn to inr1 and in1rp to inrp */
+ val = wm8994_read(codec, WM8994_INPUT_MIXER_2);
+ val &= ~(WM8994_IN1RN_TO_IN1R_MASK | WM8994_IN1RP_TO_IN1R_MASK);
+ wm8994_write(codec, WM8994_INPUT_MIXER_2, val);
+
+ /* Digital Paths */
+ /* Disable right ADC and time slot */
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_4);
+ val &= ~(WM8994_ADCR_ENA_MASK | WM8994_AIF1ADC1R_ENA_MASK);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_4, val);
+
+ /* ADC Right mixer routing */
+ val = wm8994_read(codec, WM8994_AIF1_ADC1_RIGHT_MIXER_ROUTING);
+ val &= ~(WM8994_ADC1R_TO_AIF1ADC1R_MASK);
+ wm8994_write(codec, WM8994_AIF1_ADC1_RIGHT_MIXER_ROUTING, val);
+ break;
+
+ case BT_REC:
+ DEBUG_LOG("Disbaling BT Mic path..\n");
+ val = wm8994_read(codec, WM8994_AIF1_ADC1_LEFT_MIXER_ROUTING);
+ val &= ~(WM8994_AIF2DACL_TO_AIF1ADC1L_MASK |
+ WM8994_ADC1L_TO_AIF1ADC1L_MASK);
+ wm8994_write(codec, WM8994_AIF1_ADC1_LEFT_MIXER_ROUTING, val);
+
+ val = wm8994_read(codec, WM8994_AIF1_ADC1_RIGHT_MIXER_ROUTING);
+ val &= ~(WM8994_AIF2DACR_TO_AIF1ADC1R_MASK |
+ WM8994_ADC1R_TO_AIF1ADC1R_MASK);
+ wm8994_write(codec, WM8994_AIF1_ADC1_RIGHT_MIXER_ROUTING, val);
+
+ val = wm8994_read(codec, WM8994_AIF2_DAC_FILTERS_1);
+ val &= ~(WM8994_AIF2DAC_MUTE_MASK);
+ val |= (WM8994_AIF2DAC_MUTE);
+ wm8994_write(codec, WM8994_AIF2_DAC_FILTERS_1, val);
+ break;
+
+ case MIC_OFF:
+ DEBUG_LOG("Mic is already OFF!\n");
+ break;
+
+ default:
+ DEBUG_LOG_ERR("Path[%d] is not invaild!\n", mic);
+ break;
+ }
+}
+
+void wm8994_set_bluetooth_common_setting(struct snd_soc_codec *codec)
+{
+ u32 val;
+
+ wm8994_write(codec, WM8994_GPIO_1, 0xA101);
+ wm8994_write(codec, WM8994_GPIO_2, 0x8100);
+ wm8994_write(codec, WM8994_GPIO_3, 0x0100);
+ wm8994_write(codec, WM8994_GPIO_4, 0x0100);
+ wm8994_write(codec, WM8994_GPIO_5, 0x8100);
+ wm8994_write(codec, WM8994_GPIO_6, 0xA101);
+ wm8994_write(codec, WM8994_GPIO_7, 0x0100);
+ wm8994_write(codec, WM8994_GPIO_8, 0xA101);
+ wm8994_write(codec, WM8994_GPIO_9, 0xA101);
+ wm8994_write(codec, WM8994_GPIO_10, 0xA101);
+ wm8994_write(codec, WM8994_GPIO_11, 0xA101);
+
+ wm8994_write(codec, WM8994_FLL2_CONTROL_2, 0x0700);
+ wm8994_write(codec, WM8994_FLL2_CONTROL_3, 0x3126);
+ wm8994_write(codec, WM8994_FLL2_CONTROL_4, 0x0100);
+ wm8994_write(codec, WM8994_FLL2_CONTROL_5, 0x0C88);
+ wm8994_write(codec, WM8994_FLL2_CONTROL_1,
+ WM8994_FLL2_FRACN_ENA | WM8994_FLL2_ENA);
+
+ val = wm8994_read(codec, WM8994_AIF2_CLOCKING_1);
+ if (!(val & WM8994_AIF2CLK_ENA))
+ wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0018);
+
+ wm8994_write(codec, WM8994_AIF2_RATE, 0x9 << WM8994_AIF2CLK_RATE_SHIFT);
+
+ /* AIF2 Interface - PCM Stereo mode */
+ /* Left Justified, BCLK invert, LRCLK Invert */
+ wm8994_write(codec, WM8994_AIF2_CONTROL_1,
+ WM8994_AIF2ADCR_SRC | WM8994_AIF2_BCLK_INV | 0x18);
+
+ wm8994_write(codec, WM8994_AIF2_BCLK, 0x70);
+ wm8994_write(codec, WM8994_AIF2_CONTROL_2, 0x0000);
+ wm8994_write(codec, WM8994_AIF2_MASTER_SLAVE, WM8994_AIF2_MSTR |
+ WM8994_AIF2_CLK_FRC | WM8994_AIF2_LRCLK_FRC);
+
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_5);
+ val &= ~(WM8994_AIF2DACL_ENA_MASK | WM8994_AIF2DACR_ENA_MASK |
+ WM8994_AIF1DAC1L_ENA_MASK | WM8994_AIF1DAC1R_ENA_MASK |
+ WM8994_DAC1L_ENA_MASK | WM8994_DAC1R_ENA_MASK);
+ val |= (WM8994_AIF2DACL_ENA | WM8994_AIF2DACR_ENA |
+ WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA |
+ WM8994_DAC1L_ENA | WM8994_DAC1R_ENA);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_5, val);
+
+ /* Clocking */
+ val = wm8994_read(codec, WM8994_CLOCKING_1);
+ val |= (WM8994_DSP_FS2CLK_ENA | WM8994_SYSCLK_SRC);
+ wm8994_write(codec, WM8994_CLOCKING_1, val);
+
+ /* AIF1 & AIF2 Output is connected to DAC1 */
+ val = wm8994_read(codec, WM8994_DAC1_LEFT_MIXER_ROUTING);
+ val &= ~(WM8994_AIF1DAC1L_TO_DAC1L_MASK |
+ WM8994_AIF2DACL_TO_DAC1L_MASK);
+ val |= (WM8994_AIF1DAC1L_TO_DAC1L | WM8994_AIF2DACL_TO_DAC1L);
+ wm8994_write(codec, WM8994_DAC1_LEFT_MIXER_ROUTING, val);
+
+ val = wm8994_read(codec, WM8994_DAC1_RIGHT_MIXER_ROUTING);
+ val &= ~(WM8994_AIF1DAC1R_TO_DAC1R_MASK |
+ WM8994_AIF2DACR_TO_DAC1R_MASK);
+ val |= (WM8994_AIF1DAC1R_TO_DAC1R | WM8994_AIF2DACR_TO_DAC1R);
+ wm8994_write(codec, WM8994_DAC1_RIGHT_MIXER_ROUTING, val);
+}
+
+void wm8994_record_headset_mic(struct snd_soc_codec *codec)
+{
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+ u16 val;
+
+ DEBUG_LOG("Recording through Headset Mic\n");
+
+ wm8994_write(codec, WM8994_ANTIPOP_2, 0x68);
+
+ /* Enable high pass filter to control bounce on startup */
+ val = wm8994_read(codec, WM8994_AIF1_ADC1_FILTERS);
+ val &= ~(WM8994_AIF1ADC1L_HPF_MASK | WM8994_AIF1ADC1R_HPF_MASK);
+ val |= (WM8994_AIF1ADC1R_HPF);
+ wm8994_write(codec, WM8994_AIF1_ADC1_FILTERS, val);
+
+ /* Enable mic bias, vmid, bias generator */
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_1);
+ val &= ~(WM8994_BIAS_ENA_MASK | WM8994_VMID_SEL_MASK);
+ val |= (WM8994_BIAS_ENA | WM8994_VMID_SEL_NORMAL);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, val);
+
+ val = wm8994_read(codec, WM8994_INPUT_MIXER_1);
+ val &= ~(WM8994_INPUTS_CLAMP_MASK);
+ val |= (WM8994_INPUTS_CLAMP);
+ wm8994_write(codec, WM8994_INPUT_MIXER_1, val);
+
+ val = (WM8994_MIXINR_ENA | WM8994_IN1R_ENA);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_2, val);
+
+
+ val = (WM8994_IN1RN_TO_IN1R | WM8994_IN1RP_TO_IN1R);
+ wm8994_write(codec, WM8994_INPUT_MIXER_2, val);
+
+ val = wm8994_read(codec, WM8994_RIGHT_LINE_INPUT_1_2_VOLUME);
+ val &= ~(WM8994_IN1R_MUTE_MASK);
+ wm8994_write(codec, WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_INPUT_MIXER_4);
+ val &= ~(WM8994_IN1R_TO_MIXINR_MASK);
+ val |= (WM8994_IN1R_TO_MIXINR);
+ wm8994_write(codec, WM8994_INPUT_MIXER_4 , val);
+
+ val = wm8994_read(codec, WM8994_INPUT_MIXER_1);
+ val &= ~(WM8994_INPUTS_CLAMP_MASK);
+ wm8994_write(codec, WM8994_INPUT_MIXER_1, val);
+
+ val = wm8994_read(codec, WM8994_AIF1_ADC1_RIGHT_VOLUME);
+ val |= (WM8994_AIF1ADC1_VU);
+ wm8994_write(codec, WM8994_AIF1_ADC1_RIGHT_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_AIF1_ADC1_FILTERS);
+ val &= ~(WM8994_AIF1ADC1L_HPF_MASK | WM8994_AIF1ADC1R_HPF_MASK);
+ val |= (WM8994_AIF1ADC1R_HPF | 0x2000);
+ wm8994_write(codec, WM8994_AIF1_ADC1_FILTERS, val);
+
+ val = wm8994_read(codec, WM8994_AIF1_MASTER_SLAVE);
+ val |= (WM8994_AIF1_MSTR | WM8994_AIF1_CLK_FRC | WM8994_AIF1_LRCLK_FRC);
+ wm8994_write(codec, WM8994_AIF1_MASTER_SLAVE, val);
+
+ wm8994_write(codec, WM8994_GPIO_1, 0xA101);
+
+ /* Mixing left channel output to right channel */
+ val = wm8994_read(codec, WM8994_AIF1_CONTROL_1);
+ val &= ~(WM8994_AIF1ADCL_SRC_MASK | WM8994_AIF1ADCR_SRC_MASK);
+ val |= (WM8994_AIF1ADCL_SRC | WM8994_AIF1ADCR_SRC);
+ wm8994_write(codec, WM8994_AIF1_CONTROL_1, val);
+
+ /* Digital Paths */
+ /* Enable right ADC and time slot */
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_4);
+ val &= ~(WM8994_ADCR_ENA_MASK | WM8994_AIF1ADC1R_ENA_MASK);
+ val |= (WM8994_AIF1ADC1R_ENA | WM8994_ADCR_ENA);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_4, val);
+
+
+ /* ADC Right mixer routing */
+ val = wm8994_read(codec, WM8994_AIF1_ADC1_RIGHT_MIXER_ROUTING);
+ val &= ~(WM8994_ADC1R_TO_AIF1ADC1R_MASK);
+ val |= WM8994_ADC1R_TO_AIF1ADC1R;
+ wm8994_write(codec, WM8994_AIF1_ADC1_RIGHT_MIXER_ROUTING, val);
+
+ val = wm8994_read(codec, WM8994_SPEAKER_MIXER);
+ val &= ~WM8994_MIXINL_TO_SPKMIXL_MASK;
+ wm8994_write(codec, WM8994_SPEAKER_MIXER, val);
+
+ val = wm8994_read(codec, WM8994_OUTPUT_MIXER_1);
+ val &= ~WM8994_MIXINL_TO_MIXOUTL_MASK;
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_1, val);
+
+ val = wm8994_read(codec, WM8994_OUTPUT_MIXER_2);
+ val &= ~WM8994_MIXINR_TO_MIXOUTR_MASK;
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_2, val);
+
+ val = wm8994_read(codec, WM8994_DAC2_LEFT_MIXER_ROUTING);
+ val &= ~(WM8994_ADC1_TO_DAC2L_MASK);
+ wm8994_write(codec, WM8994_DAC2_LEFT_MIXER_ROUTING, val);
+
+ val = wm8994_read(codec, WM8994_DAC2_RIGHT_MIXER_ROUTING);
+ val &= ~(WM8994_ADC1_TO_DAC2R_MASK);
+ wm8994_write(codec, WM8994_DAC2_RIGHT_MIXER_ROUTING, val);
+
+ if (wm8994->input_source == RECOGNITION)
+ wm8994_set_codec_gain(codec, RECORDING_MODE, RECORDING_REC_HP);
+ else if (wm8994->input_source == CAMCORDER)
+ wm8994_set_codec_gain(codec, RECORDING_MODE, RECORDING_CAM_HP);
+ else if (wm8994->input_source == VOICE_COMMUNICATION)
+ wm8994_set_codec_gain(codec, RECORDING_MODE, RECORDING_VC_HP);
+ else
+ wm8994_set_codec_gain(codec, RECORDING_MODE, RECORDING_HP);
+
+}
+
+void wm8994_record_main_mic(struct snd_soc_codec *codec)
+{
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+ u16 val;
+
+ DEBUG_LOG("Recording through Main Mic\n");
+ audio_ctrl_mic_bias_gpio(wm8994->pdata, 1);
+
+ /* Main mic volume issue fix: requested H/W */
+ wm8994_write(codec, WM8994_ANTIPOP_2, 0x68);
+
+ /* High pass filter to control bounce on enable */
+ val = wm8994_read(codec, WM8994_AIF1_ADC1_FILTERS);
+ val &= ~(WM8994_AIF1ADC1L_HPF_MASK | WM8994_AIF1ADC1R_HPF_MASK);
+ val |= (WM8994_AIF1ADC1L_HPF);
+ wm8994_write(codec, WM8994_AIF1_ADC1_FILTERS, val);
+
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_1);
+ val &= ~(WM8994_BIAS_ENA_MASK | WM8994_VMID_SEL_MASK);
+ val |= (WM8994_BIAS_ENA | WM8994_VMID_SEL_NORMAL);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, val);
+
+ val = wm8994_read(codec, WM8994_INPUT_MIXER_1);
+ val &= ~(WM8994_INPUTS_CLAMP_MASK);
+ val |= (WM8994_INPUTS_CLAMP);
+ wm8994_write(codec, WM8994_INPUT_MIXER_1, val);
+
+ val = (WM8994_MIXINL_ENA | WM8994_IN1L_ENA);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_2, val);
+
+ val = (WM8994_IN1LP_TO_IN1L | WM8994_IN1LN_TO_IN1L);
+ wm8994_write(codec, WM8994_INPUT_MIXER_2, val);
+
+
+ val = wm8994_read(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME);
+ val &= ~(WM8994_IN1L_MUTE_MASK);
+ wm8994_write(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_INPUT_MIXER_3);
+ val &= ~(WM8994_IN1L_TO_MIXINL_MASK);
+ val |= (WM8994_IN1L_TO_MIXINL);
+ wm8994_write(codec, WM8994_INPUT_MIXER_3, val);
+
+ val = wm8994_read(codec, WM8994_INPUT_MIXER_1);
+ val &= ~(WM8994_INPUTS_CLAMP_MASK);
+ wm8994_write(codec, WM8994_INPUT_MIXER_1, val);
+
+
+ val = wm8994_read(codec, WM8994_AIF1_ADC1_LEFT_VOLUME);
+ val |= (WM8994_AIF1ADC1_VU);
+ wm8994_write(codec, WM8994_AIF1_ADC1_LEFT_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_AIF1_ADC1_FILTERS);
+ val &= ~(WM8994_AIF1ADC1L_HPF_MASK | WM8994_AIF1ADC1R_HPF_MASK);
+ val |= (WM8994_AIF1ADC1L_HPF | 0x2000);
+ wm8994_write(codec, WM8994_AIF1_ADC1_FILTERS, val);
+
+ val = wm8994_read(codec, WM8994_AIF1_MASTER_SLAVE);
+ val |= (WM8994_AIF1_MSTR | WM8994_AIF1_CLK_FRC | WM8994_AIF1_LRCLK_FRC);
+ wm8994_write(codec, WM8994_AIF1_MASTER_SLAVE, val);
+
+ wm8994_write(codec, WM8994_GPIO_1, 0xA101);
+
+ val = wm8994_read(codec, WM8994_AIF1_CONTROL_1);
+ val &= ~(WM8994_AIF1ADCL_SRC_MASK | WM8994_AIF1ADCR_SRC_MASK);
+ val |= (WM8994_AIF1ADCR_SRC);
+ wm8994_write(codec, WM8994_AIF1_CONTROL_1, val);
+
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_4);
+ val &= ~(WM8994_ADCL_ENA_MASK | WM8994_AIF1ADC1L_ENA_MASK);
+ val |= (WM8994_AIF1ADC1L_ENA | WM8994_ADCL_ENA);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_4, val);
+
+ /* Enable timeslots */
+ val = wm8994_read(codec, WM8994_AIF1_ADC1_LEFT_MIXER_ROUTING);
+ val |= WM8994_ADC1L_TO_AIF1ADC1L;
+ wm8994_write(codec, WM8994_AIF1_ADC1_LEFT_MIXER_ROUTING, val);
+
+ val = wm8994_read(codec, WM8994_SPEAKER_MIXER);
+ val &= ~WM8994_MIXINL_TO_SPKMIXL_MASK;
+ wm8994_write(codec, WM8994_SPEAKER_MIXER, val);
+
+ val = wm8994_read(codec, WM8994_OUTPUT_MIXER_1);
+ val &= ~WM8994_MIXINL_TO_MIXOUTL_MASK;
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_1, val);
+
+ val = wm8994_read(codec, WM8994_OUTPUT_MIXER_2);
+ val &= ~WM8994_MIXINR_TO_MIXOUTR_MASK;
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_2, val);
+
+ val = wm8994_read(codec, WM8994_DAC2_LEFT_MIXER_ROUTING);
+ val &= ~(WM8994_ADC1_TO_DAC2L_MASK);
+ wm8994_write(codec, WM8994_DAC2_LEFT_MIXER_ROUTING, val);
+
+ val = wm8994_read(codec, WM8994_DAC2_RIGHT_MIXER_ROUTING);
+ val &= ~(WM8994_ADC1_TO_DAC2R_MASK);
+ wm8994_write(codec, WM8994_DAC2_RIGHT_MIXER_ROUTING, val);
+
+ if (wm8994->input_source == RECOGNITION)
+ wm8994_set_codec_gain(codec, RECORDING_MODE,
+ RECORDING_REC_MAIN);
+ else if (wm8994->input_source == CAMCORDER)
+ wm8994_set_codec_gain(codec, RECORDING_MODE,
+ RECORDING_CAM_MAIN);
+ else if (wm8994->input_source == VOICE_COMMUNICATION)
+ wm8994_set_codec_gain(codec, RECORDING_MODE,
+ RECORDING_VC_MAIN);
+ else
+ wm8994_set_codec_gain(codec, RECORDING_MODE, RECORDING_MAIN);
+
+}
+
+void wm8994_record_bluetooth(struct snd_soc_codec *codec)
+{
+ u16 val;
+
+ DEBUG_LOG("BT Record Path for Voice Command\n");
+
+ wm8994_set_bluetooth_common_setting(codec);
+
+ val = wm8994_read(codec, WM8994_DAC2_LEFT_MIXER_ROUTING);
+ val &= ~(WM8994_ADC1_TO_DAC2L_MASK);
+ wm8994_write(codec, WM8994_DAC2_LEFT_MIXER_ROUTING, val);
+
+ val = wm8994_read(codec, WM8994_DAC2_RIGHT_MIXER_ROUTING);
+ val &= ~(WM8994_ADC1_TO_DAC2R_MASK);
+ wm8994_write(codec, WM8994_DAC2_RIGHT_MIXER_ROUTING, val);
+
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_1);
+ val &= ~(WM8994_BIAS_ENA_MASK | WM8994_VMID_SEL_MASK);
+ val |= (WM8994_BIAS_ENA | WM8994_VMID_SEL_NORMAL);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, val);
+
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_2, 0x0000);
+
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, 0x0000);
+
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_4);
+ val &= ~(WM8994_AIF1ADC1L_ENA_MASK | WM8994_AIF1ADC1R_ENA_MASK);
+ val |= (WM8994_AIF1ADC1L_ENA | WM8994_AIF1ADC1R_ENA);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_4 , val);
+
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_5);
+ val &= ~(WM8994_AIF2DACL_ENA_MASK | WM8994_AIF2DACR_ENA_MASK);
+ val |= (WM8994_AIF2DACL_ENA | WM8994_AIF2DACR_ENA);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_5, val);
+
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_6);
+ val &= ~(WM8994_AIF3_ADCDAT_SRC_MASK | WM8994_AIF2_DACDAT_SRC_MASK);
+ val |= (0x1 << WM8994_AIF3_ADCDAT_SRC_SHIFT | WM8994_AIF2_DACDAT_SRC);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_6, val);
+
+ val = wm8994_read(codec, WM8994_AIF2_DAC_FILTERS_1);
+ val &= ~(WM8994_AIF2DAC_MUTE_MASK);
+ wm8994_write(codec, WM8994_AIF2_DAC_FILTERS_1, val);
+
+ val = wm8994_read(codec, WM8994_AIF1_ADC1_LEFT_MIXER_ROUTING);
+ val &= ~(WM8994_AIF2DACL_TO_AIF1ADC1L_MASK);
+ val |= (WM8994_AIF2DACL_TO_AIF1ADC1L);
+ wm8994_write(codec, WM8994_AIF1_ADC1_LEFT_MIXER_ROUTING, val);
+
+ val = wm8994_read(codec, WM8994_AIF1_ADC1_RIGHT_MIXER_ROUTING);
+ val &= ~(WM8994_AIF2DACR_TO_AIF1ADC1R_MASK);
+ val |= (WM8994_AIF2DACR_TO_AIF1ADC1R);
+ wm8994_write(codec, WM8994_AIF1_ADC1_RIGHT_MIXER_ROUTING, val);
+
+ wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0019);
+
+ wm8994_write(codec, WM8994_OVERSAMPLING, 0X0000);
+
+ wm8994_write(codec, WM8994_GPIO_8, WM8994_GP8_DIR | WM8994_GP8_DB);
+ wm8994_write(codec, WM8994_GPIO_9, WM8994_GP9_DB);
+ wm8994_write(codec, WM8994_GPIO_10, WM8994_GP10_DB);
+ wm8994_write(codec, WM8994_GPIO_11, WM8994_GP11_DB);
+}
+void wm8994_set_playback_receiver(struct snd_soc_codec *codec)
+{
+ u16 val;
+
+ DEBUG_LOG("");
+
+ val = wm8994_read(codec, WM8994_LEFT_OPGA_VOLUME);
+ val &= ~(WM8994_MIXOUTL_MUTE_N_MASK);
+ val |= (WM8994_MIXOUTL_MUTE_N);
+ wm8994_write(codec, WM8994_LEFT_OPGA_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_RIGHT_OPGA_VOLUME);
+ val &= ~(WM8994_MIXOUTR_MUTE_N_MASK);
+ val |= (WM8994_MIXOUTR_MUTE_N);
+ wm8994_write(codec, WM8994_RIGHT_OPGA_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_HPOUT2_VOLUME);
+ val &= ~(WM8994_HPOUT2_MUTE_MASK);
+ wm8994_write(codec, WM8994_HPOUT2_VOLUME, val);
+
+ /* Unmute DAC1 left */
+ val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME);
+ val &= ~(WM8994_DAC1L_MUTE_MASK);
+ wm8994_write(codec, WM8994_DAC1_LEFT_VOLUME, val);
+
+ /* Unmute and volume ctrl RightDAC */
+ val = wm8994_read(codec, WM8994_DAC1_RIGHT_VOLUME);
+ val &= ~(WM8994_DAC1R_MUTE_MASK);
+ wm8994_write(codec, WM8994_DAC1_RIGHT_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_OUTPUT_MIXER_1);
+ val &= ~(WM8994_DAC1L_TO_MIXOUTL_MASK);
+ val |= (WM8994_DAC1L_TO_MIXOUTL);
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_1, val);
+
+ val = wm8994_read(codec, WM8994_OUTPUT_MIXER_2);
+ val &= ~(WM8994_DAC1R_TO_MIXOUTR_MASK);
+ val |= (WM8994_DAC1R_TO_MIXOUTR);
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_2, val);
+
+ val = wm8994_read(codec, WM8994_HPOUT2_MIXER);
+ val &= ~(WM8994_MIXOUTLVOL_TO_HPOUT2_MASK |
+ WM8994_MIXOUTRVOL_TO_HPOUT2_MASK);
+ val |= (WM8994_MIXOUTRVOL_TO_HPOUT2 | WM8994_MIXOUTLVOL_TO_HPOUT2);
+ wm8994_write(codec, WM8994_HPOUT2_MIXER, val);
+
+ wm8994_set_codec_gain(codec, PLAYBACK_MODE, PLAYBACK_RCV);
+
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_5);
+ val &= ~(WM8994_DAC1R_ENA_MASK | WM8994_DAC1L_ENA_MASK |
+ WM8994_AIF1DAC1R_ENA_MASK | WM8994_AIF1DAC1L_ENA_MASK);
+ val |= (WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA |
+ WM8994_DAC1L_ENA | WM8994_DAC1R_ENA);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_5, val);
+
+ val = wm8994_read(codec, WM8994_DAC1_LEFT_MIXER_ROUTING);
+ val &= ~(WM8994_AIF1DAC1L_TO_DAC1L_MASK);
+ val |= (WM8994_AIF1DAC1L_TO_DAC1L);
+ wm8994_write(codec, WM8994_DAC1_LEFT_MIXER_ROUTING, val);
+
+ val = wm8994_read(codec, WM8994_DAC1_RIGHT_MIXER_ROUTING);
+ val &= ~(WM8994_AIF1DAC1R_TO_DAC1R_MASK);
+ val |= (WM8994_AIF1DAC1R_TO_DAC1R);
+ wm8994_write(codec, WM8994_DAC1_RIGHT_MIXER_ROUTING, val);
+
+ val = wm8994_read(codec, WM8994_CLOCKING_1);
+ val &= ~(WM8994_DSP_FS1CLK_ENA_MASK | WM8994_DSP_FSINTCLK_ENA_MASK);
+ val |= (WM8994_DSP_FS1CLK_ENA | WM8994_DSP_FSINTCLK_ENA);
+ wm8994_write(codec, WM8994_CLOCKING_1, val);
+
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_3);
+ val &= ~(WM8994_MIXOUTLVOL_ENA_MASK | WM8994_MIXOUTRVOL_ENA_MASK |
+ WM8994_MIXOUTL_ENA_MASK | WM8994_MIXOUTR_ENA_MASK);
+ val |= (WM8994_MIXOUTL_ENA | WM8994_MIXOUTR_ENA |
+ WM8994_MIXOUTRVOL_ENA | WM8994_MIXOUTLVOL_ENA);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, val);
+
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_1);
+ val &= ~(WM8994_BIAS_ENA_MASK | WM8994_VMID_SEL_MASK |
+ WM8994_HPOUT2_ENA_MASK | WM8994_HPOUT1L_ENA_MASK |
+ WM8994_HPOUT1R_ENA_MASK | WM8994_SPKOUTL_ENA_MASK);
+ val |= (WM8994_BIAS_ENA | WM8994_VMID_SEL_NORMAL | WM8994_HPOUT2_ENA);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, val);
+
+ val = wm8994_read(codec, WM8994_AIF1_DAC1_FILTERS_1);
+ val &= ~(WM8994_AIF1DAC1_MUTE_MASK | WM8994_AIF1DAC1_MONO_MASK);
+ val |= (WM8994_AIF1DAC1_UNMUTE | WM8994_AIF1DAC1_MONO);
+ wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, val);
+
+}
+
+void wm8994_set_playback_headset(struct snd_soc_codec *codec)
+{
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+ u16 val;
+
+ u16 testreturn1 = 0;
+ u16 testreturn2 = 0;
+ u16 testlow1 = 0;
+ u16 testhigh1 = 0;
+ u8 testlow = 0;
+ u8 testhigh = 0;
+
+ DEBUG_LOG("");
+
+ wm8994_earsel_control(wm8994->pdata, 0);
+
+ /* Enable the Timeslot0 to DAC1L */
+ val = wm8994_read(codec, WM8994_DAC1_LEFT_MIXER_ROUTING);
+ val &= ~(WM8994_AIF1DAC1L_TO_DAC1L_MASK);
+ val |= WM8994_AIF1DAC1L_TO_DAC1L;
+ wm8994_write(codec, WM8994_DAC1_LEFT_MIXER_ROUTING, val);
+
+ /* Enable the Timeslot0 to DAC1R */
+ val = wm8994_read(codec, WM8994_DAC1_RIGHT_MIXER_ROUTING);
+ val &= ~(WM8994_AIF1DAC1R_TO_DAC1R_MASK);
+ val |= WM8994_AIF1DAC1R_TO_DAC1R;
+ wm8994_write(codec, WM8994_DAC1_RIGHT_MIXER_ROUTING, val);
+
+ val = wm8994_read(codec, 0x102);
+ val &= ~(0x0003);
+ val = 0x0003;
+ wm8994_write(codec, 0x102, val);
+
+ val = wm8994_read(codec, 0x56);
+ val &= ~(0x0003);
+ val = 0x0003;
+ wm8994_write(codec, 0x56, val);
+
+ val = wm8994_read(codec, 0x102);
+ val &= ~(0x0000);
+ val = 0x0000;
+ wm8994_write(codec, 0x102, val);
+
+ val = wm8994_read(codec, WM8994_CLASS_W_1);
+ val &= ~(0x0005);
+ val |= 0x0005;
+ wm8994_write(codec, WM8994_CLASS_W_1, val);
+
+ val = wm8994_read(codec, WM8994_LEFT_OUTPUT_VOLUME);
+ val &= ~(WM8994_HPOUT1L_MUTE_N_MASK);
+ val |= (WM8994_HPOUT1L_MUTE_N);
+ wm8994_write(codec, WM8994_LEFT_OUTPUT_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_RIGHT_OUTPUT_VOLUME);
+ val &= ~(WM8994_HPOUT1R_MUTE_N_MASK);
+ val |= (WM8994_HPOUT1R_MUTE_N);
+ wm8994_write(codec, WM8994_RIGHT_OUTPUT_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_LEFT_OPGA_VOLUME);
+ val &= ~(WM8994_MIXOUTL_MUTE_N_MASK);
+ val |= (WM8994_MIXOUTL_MUTE_N);
+ wm8994_write(codec, WM8994_LEFT_OPGA_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_RIGHT_OPGA_VOLUME);
+ val &= ~(WM8994_MIXOUTR_MUTE_N_MASK);
+ val |= (WM8994_MIXOUTR_MUTE_N);
+ wm8994_write(codec, WM8994_RIGHT_OPGA_VOLUME, val);
+
+ if (wm8994->ringtone_active)
+ wm8994_set_codec_gain(codec, PLAYBACK_MODE, PLAYBACK_RING_HP);
+ else if (wm8994->cur_path == HP_NO_MIC)
+ wm8994_set_codec_gain(codec, PLAYBACK_MODE, PLAYBACK_HP_NO_MIC);
+ else
+ wm8994_set_codec_gain(codec, PLAYBACK_MODE, PLAYBACK_HP);
+
+ val = wm8994_read(codec, WM8994_DC_SERVO_2);
+ val &= ~(0x03E0);
+ val = 0x03E0;
+ wm8994_write(codec, WM8994_DC_SERVO_2, val);
+
+ /* Enable vmid,bias, hp left and right */
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_1);
+ val &= ~(WM8994_BIAS_ENA_MASK | WM8994_VMID_SEL_MASK |
+ WM8994_HPOUT1L_ENA_MASK | WM8994_HPOUT1R_ENA_MASK |
+ WM8994_SPKOUTR_ENA_MASK | WM8994_SPKOUTL_ENA_MASK);
+ val |= (WM8994_BIAS_ENA | WM8994_VMID_SEL_NORMAL |
+ WM8994_HPOUT1R_ENA | WM8994_HPOUT1L_ENA);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, val);
+
+ val = wm8994_read(codec, WM8994_ANALOGUE_HP_1);
+ val &= ~(0x0022);
+ val = 0x0022;
+ wm8994_write(codec, WM8994_ANALOGUE_HP_1, val);
+
+ /* Enable Charge Pump */
+ /* this is from wolfson */
+ val = wm8994_read(codec, WM8994_CHARGE_PUMP_1);
+ val &= ~WM8994_CP_ENA_MASK ;
+ val |= WM8994_CP_ENA | WM8994_CP_ENA_DEFAULT;
+ wm8994_write(codec, WM8994_CHARGE_PUMP_1, val);
+
+ msleep(5);
+
+ /* Enable Dac1 and DAC2 and the Timeslot0 for AIF1 */
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_5);
+ val &= ~(WM8994_DAC1R_ENA_MASK | WM8994_DAC1L_ENA_MASK |
+ WM8994_AIF1DAC1R_ENA_MASK | WM8994_AIF1DAC1L_ENA_MASK);
+ val |= (WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA |
+ WM8994_DAC1L_ENA | WM8994_DAC1R_ENA);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_5, val);
+
+ /* Enable DAC1L to HPOUT1L path */
+ val = wm8994_read(codec, WM8994_OUTPUT_MIXER_1);
+ val &= ~(WM8994_DAC1L_TO_HPOUT1L_MASK | WM8994_DAC1L_TO_MIXOUTL_MASK);
+ val |= WM8994_DAC1L_TO_MIXOUTL;
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_1, val);
+
+ /* Enable DAC1R to HPOUT1R path */
+ val = wm8994_read(codec, WM8994_OUTPUT_MIXER_2);
+ val &= ~(WM8994_DAC1R_TO_HPOUT1R_MASK | WM8994_DAC1R_TO_MIXOUTR_MASK);
+ val |= WM8994_DAC1R_TO_MIXOUTR;
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_2, val);
+
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_3);
+ val &= ~(WM8994_MIXOUTLVOL_ENA_MASK | WM8994_MIXOUTRVOL_ENA_MASK |
+ WM8994_MIXOUTL_ENA_MASK | WM8994_MIXOUTR_ENA_MASK |
+ WM8994_SPKRVOL_ENA_MASK | WM8994_SPKLVOL_ENA_MASK);
+ val |= (WM8994_MIXOUTLVOL_ENA | WM8994_MIXOUTRVOL_ENA |
+ WM8994_MIXOUTL_ENA | WM8994_MIXOUTR_ENA);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, 0x0030);
+
+ if (!wm8994->dc_servo[DCS_MEDIA]) {
+ wait_for_dc_servo(codec,
+ WM8994_DCS_TRIG_SERIES_0 |
+ WM8994_DCS_TRIG_SERIES_1);
+
+ testreturn1 = wm8994_read(codec, WM8994_DC_SERVO_4);
+
+ testlow = (signed char)(testreturn1 & 0xff);
+ testhigh = (signed char)((testreturn1>>8) & 0xff);
+
+ testlow1 = ((signed short)(testlow-5)) & 0x00ff;
+ testhigh1 = (((signed short)(testhigh-5)<<8) & 0xff00);
+ testreturn2 = testlow1|testhigh1;
+ } else {
+ testreturn2 = wm8994->dc_servo[DCS_MEDIA];
+ }
+
+ wm8994_write(codec, WM8994_DC_SERVO_4, testreturn2);
+ wm8994->dc_servo[DCS_MEDIA] = testreturn2;
+
+ wait_for_dc_servo(codec,
+ WM8994_DCS_TRIG_DAC_WR_0 | WM8994_DCS_TRIG_DAC_WR_1);
+
+ /* Intermediate HP settings */
+ val = wm8994_read(codec, WM8994_ANALOGUE_HP_1);
+ val &= ~(WM8994_HPOUT1R_DLY_MASK | WM8994_HPOUT1R_OUTP_MASK |
+ WM8994_HPOUT1R_RMV_SHORT_MASK | WM8994_HPOUT1L_DLY_MASK |
+ WM8994_HPOUT1L_OUTP_MASK | WM8994_HPOUT1L_RMV_SHORT_MASK);
+ val = (WM8994_HPOUT1L_RMV_SHORT | WM8994_HPOUT1L_OUTP|
+ WM8994_HPOUT1L_DLY | WM8994_HPOUT1R_RMV_SHORT |
+ WM8994_HPOUT1R_OUTP | WM8994_HPOUT1R_DLY);
+ wm8994_write(codec, WM8994_ANALOGUE_HP_1, val);
+
+ /* Unmute DAC1 left */
+ val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME);
+ val &= ~(WM8994_DAC1L_MUTE_MASK);
+ wm8994_write(codec, WM8994_DAC1_LEFT_VOLUME, val);
+
+ /* Unmute and volume ctrl RightDAC */
+ val = wm8994_read(codec, WM8994_DAC1_RIGHT_VOLUME);
+ val &= ~(WM8994_DAC1R_MUTE_MASK);
+ wm8994_write(codec, WM8994_DAC1_RIGHT_VOLUME, val);
+
+ /* Unmute the AF1DAC1 */
+ val = wm8994_read(codec, WM8994_AIF1_DAC1_FILTERS_1);
+ val &= ~(WM8994_AIF1DAC1_MUTE_MASK | WM8994_AIF1DAC1_MONO_MASK);
+ val |= WM8994_AIF1DAC1_UNMUTE;
+ wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, val);
+
+}
+
+void wm8994_set_playback_speaker(struct snd_soc_codec *codec)
+{
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+ u16 val;
+
+ DEBUG_LOG("");
+
+ /* Disable end point for preventing pop up noise.*/
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_1);
+ val &= ~(WM8994_SPKOUTL_ENA_MASK);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, val);
+
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_3);
+ val &= ~(WM8994_MIXOUTLVOL_ENA_MASK | WM8994_MIXOUTRVOL_ENA_MASK |
+ WM8994_MIXOUTL_ENA_MASK | WM8994_MIXOUTR_ENA_MASK |
+ WM8994_SPKRVOL_ENA_MASK | WM8994_SPKLVOL_ENA_MASK);
+ val |= WM8994_SPKLVOL_ENA;
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, val);
+
+ /* Speaker Volume Control */
+ /* Unmute the SPKMIXVOLUME */
+ val = wm8994_read(codec, WM8994_SPEAKER_VOLUME_LEFT);
+ val &= ~(WM8994_SPKOUTL_MUTE_N_MASK);
+ val |= (WM8994_SPKOUTL_MUTE_N);
+ wm8994_write(codec, WM8994_SPEAKER_VOLUME_LEFT, val);
+
+ val = wm8994_read(codec, WM8994_SPEAKER_VOLUME_RIGHT);
+ val &= ~(WM8994_SPKOUTR_MUTE_N_MASK);
+ wm8994_write(codec, WM8994_SPEAKER_VOLUME_RIGHT, val);
+
+ /* Unmute DAC1 left */
+ val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME);
+ val &= ~(WM8994_DAC1L_MUTE_MASK);
+ wm8994_write(codec, WM8994_DAC1_LEFT_VOLUME, val);
+
+ /* Unmute and volume ctrl RightDAC */
+ val = wm8994_read(codec, WM8994_DAC1_RIGHT_VOLUME);
+ val &= ~(WM8994_DAC1R_MUTE_MASK);
+ wm8994_write(codec, WM8994_DAC1_RIGHT_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_SPKOUT_MIXERS);
+ val &= ~(WM8994_SPKMIXL_TO_SPKOUTL_MASK |
+ WM8994_SPKMIXR_TO_SPKOUTL_MASK |
+ WM8994_SPKMIXR_TO_SPKOUTR_MASK);
+ val |= WM8994_SPKMIXL_TO_SPKOUTL;
+ wm8994_write(codec, WM8994_SPKOUT_MIXERS, val);
+
+ /* Unmute the DAC path */
+ val = wm8994_read(codec, WM8994_SPEAKER_MIXER);
+ val &= ~(WM8994_DAC1L_TO_SPKMIXL_MASK);
+ val |= WM8994_DAC1L_TO_SPKMIXL;
+ wm8994_write(codec, WM8994_SPEAKER_MIXER, val);
+
+ /* Eable DAC1 Left and timeslot left */
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_5);
+ val &= ~(WM8994_DAC1L_ENA_MASK | WM8994_AIF1DAC1R_ENA_MASK |
+ WM8994_AIF1DAC1L_ENA_MASK);
+ val |= (WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA | WM8994_DAC1L_ENA);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_5, val);
+
+ /* DRC setting */
+ wm8994_write(codec, WM8994_AIF1_DRC1_1, 0x00BC);
+ wm8994_write(codec, WM8994_AIF1_DRC1_3, 0x0028);
+ wm8994_write(codec, WM8994_AIF1_DRC1_4, 0x0186);
+
+ /* EQ AIF1 setting */
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_GAINS_1, 0x0019);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_GAINS_2, 0x6280);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_1_A, 0x0FC3);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_1_B, 0x03FD);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_1_PG, 0x00F4);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_2_A, 0x1F30);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_2_B, 0xF0CD);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_2_C, 0x040A);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_2_PG, 0x032C);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_3_A, 0x1C52);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_3_B, 0xF379);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_3_C, 0x040A);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_3_PG, 0x0DC1);
+
+ if (wm8994->ringtone_active)
+ wm8994_set_codec_gain(codec, PLAYBACK_MODE, PLAYBACK_RING_SPK);
+ else
+ wm8994_set_codec_gain(codec, PLAYBACK_MODE, PLAYBACK_SPK);
+
+ /* enable timeslot0 to left dac */
+ val = wm8994_read(codec, WM8994_DAC1_LEFT_MIXER_ROUTING);
+ val &= ~(WM8994_AIF1DAC1L_TO_DAC1L_MASK);
+ val |= WM8994_AIF1DAC1L_TO_DAC1L;
+ wm8994_write(codec, WM8994_DAC1_LEFT_MIXER_ROUTING, val);
+
+#ifdef CONFIG_SND_VOODOO
+ voodoo_hook_playback_speaker();
+#endif
+
+ /* Enbale bias,vmid and Left speaker */
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_1);
+ val &= ~(WM8994_BIAS_ENA_MASK | WM8994_VMID_SEL_MASK |
+ WM8994_HPOUT1L_ENA_MASK | WM8994_HPOUT1R_ENA_MASK |
+ WM8994_SPKOUTR_ENA_MASK | WM8994_SPKOUTL_ENA_MASK);
+ val |= (WM8994_BIAS_ENA | WM8994_VMID_SEL_NORMAL | WM8994_SPKOUTL_ENA);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, val);
+
+ /* Unmute */
+ val = wm8994_read(codec, WM8994_AIF1_DAC1_FILTERS_1);
+ val &= ~(WM8994_AIF1DAC1_MUTE_MASK | WM8994_AIF1DAC1_MONO_MASK);
+ val |= (WM8994_AIF1DAC1_UNMUTE | WM8994_AIF1DAC1_MONO);
+ wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, val);
+
+}
+
+void wm8994_set_playback_speaker_headset(struct snd_soc_codec *codec)
+{
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+ u16 val;
+
+ u16 nreadservo4val = 0;
+ u16 ncompensationresult = 0;
+ u16 ncompensationresultlow = 0;
+ u16 ncompensationresulthigh = 0;
+ u8 nservo4low = 0;
+ u8 nservo4high = 0;
+
+ wm8994_earsel_control(wm8994->pdata, 0);
+
+ /* Enable the Timeslot0 to DAC1L */
+ val = wm8994_read(codec, WM8994_DAC1_LEFT_MIXER_ROUTING);
+ val &= ~(WM8994_AIF1DAC1L_TO_DAC1L_MASK);
+ val |= WM8994_AIF1DAC1L_TO_DAC1L;
+ wm8994_write(codec, WM8994_DAC1_LEFT_MIXER_ROUTING, val);
+
+ /* Enable the Timeslot0 to DAC1R */
+ val = wm8994_read(codec, WM8994_DAC1_RIGHT_MIXER_ROUTING);
+ val &= ~(WM8994_AIF1DAC1R_TO_DAC1R_MASK);
+ val |= WM8994_AIF1DAC1R_TO_DAC1R;
+ wm8994_write(codec, WM8994_DAC1_RIGHT_MIXER_ROUTING, val);
+
+ /* Speaker Volume Control */
+ val = wm8994_read(codec, WM8994_SPEAKER_VOLUME_LEFT);
+ val &= ~(WM8994_SPKOUTL_MUTE_N_MASK);
+ val |= (WM8994_SPKOUTL_MUTE_N);
+ wm8994_write(codec, WM8994_SPEAKER_VOLUME_LEFT, val);
+
+ val = wm8994_read(codec, WM8994_SPEAKER_VOLUME_RIGHT);
+ val &= ~(WM8994_SPKOUTR_MUTE_N_MASK);
+ wm8994_write(codec, WM8994_SPEAKER_VOLUME_RIGHT, val);
+
+ val = wm8994_read(codec, WM8994_SPKOUT_MIXERS);
+ val &= ~(WM8994_SPKMIXL_TO_SPKOUTL_MASK |
+ WM8994_SPKMIXR_TO_SPKOUTL_MASK |
+ WM8994_SPKMIXR_TO_SPKOUTR_MASK);
+ val |= WM8994_SPKMIXL_TO_SPKOUTL;
+ wm8994_write(codec, WM8994_SPKOUT_MIXERS, val);
+
+ /* Unmute the DAC path */
+ val = wm8994_read(codec, WM8994_SPEAKER_MIXER);
+ val &= ~(WM8994_DAC1L_TO_SPKMIXL_MASK);
+ val |= WM8994_DAC1L_TO_SPKMIXL;
+ wm8994_write(codec, WM8994_SPEAKER_MIXER, val);
+
+ /* Configuring the Digital Paths */
+ val = wm8994_read(codec, 0x102);
+ val &= ~(0x0003);
+ val = 0x0003;
+ wm8994_write(codec, 0x102, val);
+
+ val = wm8994_read(codec, 0x56);
+ val &= ~(0x0003);
+ val = 0x0003;
+ wm8994_write(codec, 0x56, val);
+
+ val = wm8994_read(codec, 0x102);
+ val &= ~(0x0000);
+ val = 0x0000;
+ wm8994_write(codec, 0x102, val);
+
+ val = wm8994_read(codec, WM8994_CLASS_W_1);
+ val &= ~(0x0005);
+ val = 0x0005;
+ wm8994_write(codec, WM8994_CLASS_W_1, val);
+
+ val = wm8994_read(codec, WM8994_LEFT_OUTPUT_VOLUME);
+ val &= ~(WM8994_HPOUT1L_MUTE_N_MASK);
+ val |= (WM8994_HPOUT1L_MUTE_N);
+ wm8994_write(codec, WM8994_LEFT_OUTPUT_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_RIGHT_OUTPUT_VOLUME);
+ val &= ~(WM8994_HPOUT1R_MUTE_N_MASK);
+ val |= (WM8994_HPOUT1R_MUTE_N);
+ wm8994_write(codec, WM8994_RIGHT_OUTPUT_VOLUME, val);
+
+ /* DC Servo Series Count */
+ val = 0x03E0;
+ wm8994_write(codec, WM8994_DC_SERVO_2, val);
+
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_1);
+ val &= ~(WM8994_BIAS_ENA_MASK | WM8994_VMID_SEL_MASK |
+ WM8994_HPOUT1L_ENA_MASK | WM8994_HPOUT1R_ENA_MASK |
+ WM8994_SPKOUTL_ENA_MASK);
+ val |= (WM8994_BIAS_ENA | WM8994_VMID_SEL_NORMAL |
+ WM8994_HPOUT1R_ENA | WM8994_HPOUT1L_ENA |
+ WM8994_SPKOUTL_ENA);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, val);
+
+ val = (WM8994_HPOUT1L_DLY | WM8994_HPOUT1R_DLY);
+ wm8994_write(codec, WM8994_ANALOGUE_HP_1, val);
+
+ /* Enable Charge Pump */
+ /* this is from wolfson */
+ val = wm8994_read(codec, WM8994_CHARGE_PUMP_1);
+ val &= ~WM8994_CP_ENA_MASK ;
+ val |= WM8994_CP_ENA | WM8994_CP_ENA_DEFAULT;
+ wm8994_write(codec, WM8994_CHARGE_PUMP_1, val);
+
+ msleep(5);
+
+ /* Enable DAC1 and DAC2 and the Timeslot0 for AIF1 */
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_5);
+ val &= ~(WM8994_DAC1R_ENA_MASK | WM8994_DAC1L_ENA_MASK |
+ WM8994_AIF1DAC1R_ENA_MASK | WM8994_AIF1DAC1L_ENA_MASK);
+ val |= (WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA |
+ WM8994_DAC1L_ENA | WM8994_DAC1R_ENA);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_5, val);
+
+ /* Enbale DAC1L to HPOUT1L path */
+ val = wm8994_read(codec, WM8994_OUTPUT_MIXER_1);
+ val &= ~(WM8994_DAC1L_TO_HPOUT1L_MASK | WM8994_DAC1L_TO_MIXOUTL_MASK);
+ val |= WM8994_DAC1L_TO_MIXOUTL;
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_1, val);
+
+ /* Enbale DAC1R to HPOUT1R path */
+ val = wm8994_read(codec, WM8994_OUTPUT_MIXER_2);
+ val &= ~(WM8994_DAC1R_TO_HPOUT1R_MASK | WM8994_DAC1R_TO_MIXOUTR_MASK);
+ val |= WM8994_DAC1R_TO_MIXOUTR;
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_2, val);
+
+ /* Enbale bias,vmid, hp left and right and Left speaker */
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_3);
+ val &= ~(WM8994_MIXOUTLVOL_ENA_MASK | WM8994_MIXOUTRVOL_ENA_MASK |
+ WM8994_MIXOUTL_ENA_MASK | WM8994_MIXOUTR_ENA_MASK |
+ WM8994_SPKLVOL_ENA_MASK);
+ val |= (WM8994_MIXOUTL_ENA | WM8994_MIXOUTR_ENA | WM8994_SPKLVOL_ENA);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, val);
+
+ /* DC Servo */
+ if (!wm8994->dc_servo[DCS_SPK_HP]) {
+ wait_for_dc_servo(codec,
+ WM8994_DCS_TRIG_SERIES_0 |
+ WM8994_DCS_TRIG_SERIES_1);
+
+ nreadservo4val = wm8994_read(codec, WM8994_DC_SERVO_4);
+ nservo4low = (signed char)(nreadservo4val & 0xff);
+ nservo4high = (signed char)((nreadservo4val>>8) & 0xff);
+
+ ncompensationresultlow = ((signed short)nservo4low - 5)
+ & 0x00ff;
+ ncompensationresulthigh = ((signed short)(nservo4high - 5)<<8)
+ & 0xff00;
+ ncompensationresult = ncompensationresultlow |
+ ncompensationresulthigh;
+ } else {
+ ncompensationresult = wm8994->dc_servo[DCS_SPK_HP];
+ }
+
+ wm8994_write(codec, WM8994_DC_SERVO_4, ncompensationresult);
+ wm8994->dc_servo[DCS_SPK_HP] = ncompensationresult;
+
+ wait_for_dc_servo(codec,
+ WM8994_DCS_TRIG_DAC_WR_1 | WM8994_DCS_TRIG_DAC_WR_0);
+
+ val = wm8994_read(codec, WM8994_ANALOGUE_HP_1);
+ val &= ~(WM8994_HPOUT1R_DLY_MASK | WM8994_HPOUT1R_OUTP_MASK |
+ WM8994_HPOUT1R_RMV_SHORT_MASK | WM8994_HPOUT1L_DLY_MASK |
+ WM8994_HPOUT1L_OUTP_MASK | WM8994_HPOUT1L_RMV_SHORT_MASK);
+ val |= (WM8994_HPOUT1L_RMV_SHORT | WM8994_HPOUT1L_OUTP |
+ WM8994_HPOUT1L_DLY | WM8994_HPOUT1R_RMV_SHORT |
+ WM8994_HPOUT1R_OUTP | WM8994_HPOUT1R_DLY);
+ wm8994_write(codec, WM8994_ANALOGUE_HP_1, val);
+
+ if (wm8994->ringtone_active)
+ wm8994_set_codec_gain(codec, PLAYBACK_MODE,
+ PLAYBACK_RING_SPK_HP);
+ else
+ wm8994_set_codec_gain(codec, PLAYBACK_MODE, PLAYBACK_SPK_HP);
+
+ val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME);
+ val &= ~(WM8994_DAC1L_MUTE_MASK);
+ wm8994_write(codec, WM8994_DAC1_LEFT_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_DAC1_RIGHT_VOLUME);
+ val &= ~(WM8994_DAC1R_MUTE_MASK);
+ wm8994_write(codec, WM8994_DAC1_RIGHT_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_AIF1_DAC1_FILTERS_1);
+ val &= ~(WM8994_AIF1DAC1_MUTE_MASK | WM8994_AIF1DAC1_MONO_MASK);
+ val |= (WM8994_AIF1DAC1_UNMUTE | WM8994_AIF1DAC1_MONO);
+ wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, val);
+
+}
+
+void wm8994_set_playback_bluetooth(struct snd_soc_codec *codec)
+{
+ u16 val;
+
+ DEBUG_LOG("BT Playback Path for SCO\n");
+
+ wm8994_set_bluetooth_common_setting(codec);
+
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_1);
+ val &= ~(WM8994_BIAS_ENA_MASK | WM8994_VMID_SEL_MASK);
+ val |= (WM8994_BIAS_ENA | WM8994_VMID_SEL_NORMAL);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, val);
+
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_2, 0x0000);
+
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, 0x0000);
+
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_4);
+ val &= ~(WM8994_AIF2ADCL_ENA_MASK | WM8994_AIF2ADCR_ENA_MASK);
+ val |= (WM8994_AIF2ADCL_ENA | WM8994_AIF2ADCR_ENA);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_4, val);
+
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_5);
+ val &= ~(WM8994_AIF2DACL_ENA_MASK | WM8994_AIF2DACR_ENA_MASK |
+ WM8994_AIF1DAC1L_ENA_MASK | WM8994_AIF1DAC1R_ENA_MASK |
+ WM8994_DAC1L_ENA_MASK | WM8994_DAC1R_ENA_MASK);
+ val |= (WM8994_AIF2DACL_ENA | WM8994_AIF2DACR_ENA |
+ WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA |
+ WM8994_DAC1L_ENA | WM8994_DAC1R_ENA);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_5, val);
+
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_6);
+ val &= ~(WM8994_AIF3_ADCDAT_SRC_MASK);
+ val |= (0x0001 << WM8994_AIF3_ADCDAT_SRC_SHIFT);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_6, val);
+
+ /* Mixer Routing*/
+ val = wm8994_read(codec, WM8994_DAC2_LEFT_MIXER_ROUTING);
+ val &= ~(WM8994_AIF1DAC1L_TO_DAC2L_MASK);
+ val |= (WM8994_AIF1DAC1L_TO_DAC2L);
+ wm8994_write(codec, WM8994_DAC2_LEFT_MIXER_ROUTING, val);
+
+ val = wm8994_read(codec, WM8994_DAC2_RIGHT_MIXER_ROUTING);
+ val &= ~(WM8994_AIF1DAC1R_TO_DAC2R_MASK);
+ val |= (WM8994_AIF1DAC1R_TO_DAC2R);
+ wm8994_write(codec, WM8994_DAC2_RIGHT_MIXER_ROUTING, val);
+
+ /* Volume*/
+ wm8994_write(codec, WM8994_DAC2_LEFT_VOLUME, 0x01C0);
+ wm8994_write(codec, WM8994_DAC2_RIGHT_VOLUME, 0x01C0);
+
+ wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0019);
+
+ wm8994_write(codec, WM8994_OVERSAMPLING, 0X0000);
+
+ /* GPIO Configuration*/
+ wm8994_write(codec, WM8994_GPIO_8, WM8994_GP8_DIR | WM8994_GP8_DB);
+ wm8994_write(codec, WM8994_GPIO_9, WM8994_GP9_DB);
+ wm8994_write(codec, WM8994_GPIO_10, WM8994_GP10_DB);
+ wm8994_write(codec, WM8994_GPIO_11, WM8994_GP11_DB);
+
+ /* Un-Mute*/
+ val = wm8994_read(codec, WM8994_AIF1_DAC1_FILTERS_1);
+ val &= ~(WM8994_AIF1DAC1_MUTE_MASK | WM8994_AIF1DAC1_MONO_MASK);
+ val |= (WM8994_AIF1DAC1_UNMUTE);
+ wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, val);
+
+}
+
+static void wm8994_set_cdma_voicecall_common_setting(struct snd_soc_codec *codec)
+{
+ int val;
+
+ wm8994_write(codec, WM8994_ANTIPOP_2, 0x0068);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, 0x0003);
+ msleep(50);
+ /* GPIO Configuration */
+ wm8994_write(codec, WM8994_GPIO_1, 0xA101);
+ wm8994_write(codec, WM8994_GPIO_2, 0x8100);
+ wm8994_write(codec, WM8994_GPIO_3, 0x8100);
+ wm8994_write(codec, WM8994_GPIO_4, 0x8100);
+ wm8994_write(codec, WM8994_GPIO_5, 0x8100);
+ wm8994_write(codec, WM8994_GPIO_6, 0xA101);
+ wm8994_write(codec, WM8994_GPIO_7, 0x0100);
+ wm8994_write(codec, WM8994_GPIO_8, 0xA101);
+ wm8994_write(codec, WM8994_GPIO_9, 0xA101);
+ wm8994_write(codec, WM8994_GPIO_10, 0xA101);
+ wm8994_write(codec, WM8994_GPIO_11, 0xA101);
+
+ wm8994_write(codec, WM8994_FLL2_CONTROL_2, 0x2F00);
+ wm8994_write(codec, WM8994_FLL2_CONTROL_3, 0x3126);
+ wm8994_write(codec, WM8994_FLL2_CONTROL_4, 0x0600);
+ wm8994_write(codec, WM8994_FLL2_CONTROL_5, 0x0C81);
+ wm8994_write(codec, WM8994_FLL2_CONTROL_1, 0x0001);
+
+ val = wm8994_read(codec, WM8994_AIF2_CLOCKING_1);
+ if (!(val & WM8994_AIF2CLK_ENA))
+ wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0009);
+
+ wm8994_write(codec, WM8994_AIF2_RATE, 0x0003);
+
+ /* AIF2 Interface - PCM Stereo mode */
+ /* Left Justified, BCLK invert, LRCLK Invert */
+ wm8994_write(codec, WM8994_AIF2_CONTROL_1, 0x4118);
+
+ wm8994_write(codec, WM8994_AIF2_BCLK, 0x70);
+ wm8994_write(codec, WM8994_AIF2_CONTROL_2, 0x0000);
+ wm8994_write(codec, WM8994_AIF2_MASTER_SLAVE, 0);
+
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_5);
+ val &= ~(WM8994_AIF2DACL_ENA_MASK | WM8994_AIF2DACR_ENA_MASK |
+ WM8994_AIF1DAC1L_ENA_MASK | WM8994_AIF1DAC1R_ENA_MASK |
+ WM8994_DAC1L_ENA_MASK | WM8994_DAC1R_ENA_MASK);
+ val |= (WM8994_AIF2DACL_ENA | WM8994_AIF2DACR_ENA |
+ WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA |
+ WM8994_DAC1L_ENA | WM8994_DAC1R_ENA);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_5, val);
+
+ /* Clocking */
+ val = wm8994_read(codec, WM8994_CLOCKING_1);
+ val |= (WM8994_DSP_FS2CLK_ENA);
+ wm8994_write(codec, WM8994_CLOCKING_1, 0x000F);
+
+ /* AIF1 & AIF2 Output is connected to DAC1 */
+ val = wm8994_read(codec, WM8994_DAC1_LEFT_MIXER_ROUTING);
+ val &= ~(WM8994_AIF1DAC1L_TO_DAC1L_MASK |
+ WM8994_AIF2DACL_TO_DAC1L_MASK);
+ val |= (WM8994_AIF1DAC1L_TO_DAC1L | WM8994_AIF2DACL_TO_DAC1L);
+ wm8994_write(codec, WM8994_DAC1_LEFT_MIXER_ROUTING, val);
+
+ val = wm8994_read(codec, WM8994_DAC1_RIGHT_MIXER_ROUTING);
+ val &= ~(WM8994_AIF1DAC1R_TO_DAC1R_MASK |
+ WM8994_AIF2DACR_TO_DAC1R_MASK);
+ val |= (WM8994_AIF1DAC1R_TO_DAC1R | WM8994_AIF2DACR_TO_DAC1R);
+ wm8994_write(codec, WM8994_DAC1_RIGHT_MIXER_ROUTING, val);
+
+ wm8994_write(codec, 0x6, 0x0);
+}
+
+static void wm8994_set_gsm_voicecall_common_setting(struct snd_soc_codec *codec)
+{
+ int val;
+
+ /* GPIO Configuration */
+ wm8994_write(codec, WM8994_GPIO_1, 0xA101);
+ wm8994_write(codec, WM8994_GPIO_2, 0x8100);
+ wm8994_write(codec, WM8994_GPIO_3, 0x0100);
+ wm8994_write(codec, WM8994_GPIO_4, 0x0100);
+ wm8994_write(codec, WM8994_GPIO_5, 0x8100);
+ wm8994_write(codec, WM8994_GPIO_6, 0xA101);
+ wm8994_write(codec, WM8994_GPIO_7, 0x0100);
+ wm8994_write(codec, WM8994_GPIO_8, 0xA101);
+ wm8994_write(codec, WM8994_GPIO_9, 0xA101);
+ wm8994_write(codec, WM8994_GPIO_10, 0xA101);
+ wm8994_write(codec, WM8994_GPIO_11, 0xA101);
+
+ wm8994_write(codec, WM8994_FLL2_CONTROL_2, 0x2F00);
+ wm8994_write(codec, WM8994_FLL2_CONTROL_3, 0x3126);
+ wm8994_write(codec, WM8994_FLL2_CONTROL_4, 0x0100);
+ wm8994_write(codec, WM8994_FLL2_CONTROL_5, 0x0C88);
+ wm8994_write(codec, WM8994_FLL2_CONTROL_1,
+ WM8994_FLL2_FRACN_ENA | WM8994_FLL2_ENA);
+
+ val = wm8994_read(codec, WM8994_AIF2_CLOCKING_1);
+ if (!(val & WM8994_AIF2CLK_ENA))
+ wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0018);
+
+ wm8994_write(codec, WM8994_AIF2_RATE, 0x3 << WM8994_AIF2CLK_RATE_SHIFT);
+
+ /* AIF2 Interface - PCM Stereo mode */
+ /* Left Justified, BCLK invert, LRCLK Invert */
+ wm8994_write(codec, WM8994_AIF2_CONTROL_1,
+ WM8994_AIF2ADCR_SRC | WM8994_AIF2_BCLK_INV | 0x18);
+
+ wm8994_write(codec, WM8994_AIF2_BCLK, 0x70);
+ wm8994_write(codec, WM8994_AIF2_CONTROL_2, 0x0000);
+ wm8994_write(codec, WM8994_AIF2_MASTER_SLAVE, WM8994_AIF2_MSTR |
+ WM8994_AIF2_CLK_FRC | WM8994_AIF2_LRCLK_FRC);
+
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_5);
+ val &= ~(WM8994_AIF2DACL_ENA_MASK | WM8994_AIF2DACR_ENA_MASK |
+ WM8994_AIF1DAC1L_ENA_MASK | WM8994_AIF1DAC1R_ENA_MASK |
+ WM8994_DAC1L_ENA_MASK | WM8994_DAC1R_ENA_MASK);
+ val |= (WM8994_AIF2DACL_ENA | WM8994_AIF2DACR_ENA |
+ WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA |
+ WM8994_DAC1L_ENA | WM8994_DAC1R_ENA);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_5, val);
+
+ /* Clocking */
+ val = wm8994_read(codec, WM8994_CLOCKING_1);
+ val |= (WM8994_DSP_FS2CLK_ENA);
+ wm8994_write(codec, WM8994_CLOCKING_1, val);
+
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_6, 0x0);
+
+ /* AIF1 & AIF2 Output is connected to DAC1 */
+ val = wm8994_read(codec, WM8994_DAC1_LEFT_MIXER_ROUTING);
+ val &= ~(WM8994_AIF1DAC1L_TO_DAC1L_MASK |
+ WM8994_AIF2DACL_TO_DAC1L_MASK);
+ val |= (WM8994_AIF1DAC1L_TO_DAC1L | WM8994_AIF2DACL_TO_DAC1L);
+ wm8994_write(codec, WM8994_DAC1_LEFT_MIXER_ROUTING, val);
+
+ val = wm8994_read(codec, WM8994_DAC1_RIGHT_MIXER_ROUTING);
+ val &= ~(WM8994_AIF1DAC1R_TO_DAC1R_MASK |
+ WM8994_AIF2DACR_TO_DAC1R_MASK);
+ val |= (WM8994_AIF1DAC1R_TO_DAC1R | WM8994_AIF2DACR_TO_DAC1R);
+ wm8994_write(codec, WM8994_DAC1_RIGHT_MIXER_ROUTING, val);
+
+ wm8994_write(codec, 0x6, 0x0);
+}
+
+
+void wm8994_set_voicecall_common_setting(struct snd_soc_codec *codec)
+{
+ if (herring_is_cdma_wimax_dev())
+ wm8994_set_cdma_voicecall_common_setting(codec);
+ else
+ wm8994_set_gsm_voicecall_common_setting(codec);
+
+#ifdef CONFIG_SND_VOODOO_RECORD_PRESETS
+ voodoo_hook_record_main_mic();
+#endif
+}
+
+static void wm8994_set_cdma_voicecall_receiver(struct snd_soc_codec *codec)
+{
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+ int val;
+
+ DEBUG_LOG("");
+
+ audio_ctrl_mic_bias_gpio(wm8994->pdata, 1);
+
+ wm8994_write(codec, 0x0039, 0x0068); /* Anti Pop2 */
+ wm8994_write(codec, 0x0001, 0x0003); /* Power Management 1 */
+ msleep(50);
+ wm8994_write(codec, 0x0015, 0x0040);
+ wm8994_write(codec, 0x0702, 0x8100); /* GPIO 3. Speech PCM Clock */
+ wm8994_write(codec, 0x0703, 0x8100); /* GPIO 4. Speech PCM Sync */
+ /* GPIO 5. Speech PCM Data Out */
+ wm8994_write(codec, 0x0704, 0x8100);
+ /* GPIO 7. Speech PCM Data Input */
+ wm8994_write(codec, 0x0706, 0x0100);
+ wm8994_write(codec, 0x0244, 0x0C81); /* FLL2 Control 5 */
+ wm8994_write(codec, 0x0241, 0x2F00); /* FLL2 Control 2 */
+ wm8994_write(codec, 0x0243, 0x0600); /* FLL2 Control 4 */
+ wm8994_write(codec, 0x0240, 0x0001); /* FLL2 Control 1 */
+ msleep(3);
+
+ /* AIF2 Clocking 1. Clock Source Select */
+ wm8994_write(codec, 0x0204, 0x0008);
+
+ /* Clocking 1. '0x000A' is added for a playback. (original = 0x0007) */
+ wm8994_write(codec, 0x0208, 0x000F);
+
+ wm8994_write(codec, 0x0620, 0x0000); /* Oversampling */
+ wm8994_write(codec, 0x0211, 0x0003); /* AIF2 Rate */
+ wm8994_write(codec, 0x0310, 0x4118); /* AIF2 Control 1 */
+ /* AIF2 Control 2 pcm format is changed ulaw to linear */
+ wm8994_write(codec, 0x0311, 0x0000);
+ wm8994_write(codec, 0x0520, 0x0000); /* AIF2 DAC Filter 1 */
+ /* AIF2 Clocking 1. AIF2 Clock Enable */
+ wm8994_write(codec, 0x0204, 0x0009);
+
+ wm8994_write(codec, 0x0601, 0x0005); /* DAC1 Left Mixer Routing */
+ /* DAC1 Right Mixer Routing(Playback) */
+ wm8994_write(codec, 0x0602, 0x0001);
+ wm8994_write(codec, 0x0603, 0x018C); /* DAC2 Mixer Volumes */
+ wm8994_write(codec, 0x0604, 0x0030); /* DAC2 Left Mixer Routing */
+ wm8994_write(codec, 0x0605, 0x0010); /* DAC2 Right Mixer Routing */
+ wm8994_write(codec, 0x0621, 0x01C0); /* Sidetone */
+ wm8994_write(codec, 0x0002, 0x6240); /* Power Management 2 */
+ wm8994_write(codec, 0x0028, 0x0030); /* Input Mixer 2 */
+ wm8994_write(codec, 0x0018, 0x010A);
+
+ /* Output Mixer 5 */
+ val = wm8994_read(codec, 0x0031);
+ val &= ~(WM8994_DACL_MIXOUTL_VOL_MASK);
+ val |= 0x0000 << 0x0009;
+ wm8994_write(codec, 0x0031, val);
+
+ /* Output Mixer 6 */
+ val = wm8994_read(codec, 0x0032);
+ val &= ~(WM8994_DACR_MIXOUTR_VOL_MASK);
+ val |= 0x0000 << 0x0009;
+ wm8994_write(codec, 0x0032, val);
+
+ /* Left OPGA Volume */
+ val = wm8994_read(codec, 0x0020);
+ val &= ~(WM8994_MIXOUTL_MUTE_N_MASK | WM8994_MIXOUTL_VOL_MASK);
+ val |= (0x0100 | 0x0040 | 0x3D);
+ /* 05.24 Maximum ´ëºñ -6dB HAC ¿ë test -2 3B -> 39 */
+ wm8994_write(codec, 0x0020, 0x01F9);
+
+ /* Right OPGA Volume */
+ val = wm8994_read(codec, 0x0021);
+ val &= ~(WM8994_MIXOUTR_MUTE_N_MASK | WM8994_MIXOUTR_VOL_MASK);
+ val |= (0x0100 | 0x0040 | 0x3D);
+ wm8994_write(codec, 0x0021, 0x01F9);
+
+ wm8994_write(codec, 0x0312, 0x0000); /* Slave */
+ /* sub mic */
+ wm8994_write(codec, 0x0029, 0x0030); /* Input Mixer 3 */
+
+ wm8994_write(codec, 0x0015, 0x0000);
+ wm8994_write(codec, 0x0500, 0x0100); /* AIF2 ADC Left Volume */
+ wm8994_write(codec, 0x0004, 0x2002); /* Power Management 4 */
+ /* Power Management 5.'0x0303' added for a playback.(Original=0x2002) */
+ wm8994_write(codec, 0x0005, 0x2303);
+ /* Power Management 3.'0x00F0' added for a playback.(Original=0x00A0) */
+ wm8994_write(codec, 0x0003, 0x00F0);
+ wm8994_write(codec, 0x002D, 0x0001); /* Output Mixer 1 */
+ wm8994_write(codec, 0x002E, 0x0001); /* Output Mixer 2(Playback) */
+ /* HPOUT2 Mixer. '0x0008' added for a playback.(Original=0x0010) */
+ wm8994_write(codec, 0x0033, 0x0018);
+ wm8994_write(codec, 0x0038, 0x0040); /* Anti Pop 1 */
+ wm8994_write(codec, 0x0420, 0x0080); /* AIF1 DAC1 FIlter(Playback) */
+
+ /* HPOUT2 Volume */
+ wm8994_write(codec, 0x001F, 0x0000); /* HPOUT2 Volume */
+
+ wm8994_write(codec, 0x0001, 0x0803); /* Power Management 1 */
+
+ /* DAC1 Left Volume */
+ val = wm8994_read(codec, 0x0610);
+ val &= ~(WM8994_DAC1L_MUTE_MASK | WM8994_DAC1L_VOL_MASK);
+ val |= 0xC0;
+ wm8994_write(codec, 0x0610, 0x01C0);
+
+ /* DAC1 Right Volume */
+ val = wm8994_read(codec, 0x0611);
+ val &= ~(WM8994_DAC1R_MUTE_MASK | WM8994_DAC1R_VOL_MASK);
+ val |= 0xC0;
+ wm8994_write(codec, 0x0611, 0x01C0);
+
+ /* Power Management 3(Playback) */
+ wm8994_write(codec, 0x0003, 0x00F0);
+
+ wm8994_write(codec, 0x06, 0x0000);
+ wm8994_write(codec, 0x0612, 0x01C0); /* DAC2 Left Volume */
+ wm8994_write(codec, 0x0613, 0x01C0); /* DAC2 Right Volume */
+ wm8994_write(codec, 0x0500, 0x01C0); /* AIF2 ADC Left Volume */
+}
+
+static void wm8994_set_gsm_voicecall_receiver(struct snd_soc_codec *codec)
+{
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+ int val;
+
+ DEBUG_LOG("");
+
+ audio_ctrl_mic_bias_gpio(wm8994->pdata, 1);
+
+ wm8994_set_voicecall_common_setting(codec);
+
+ wm8994_write(codec, WM8994_CHARGE_PUMP_1, WM8994_CP_ENA_DEFAULT);
+
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_2,
+ WM8994_TSHUT_ENA | WM8994_TSHUT_OPDIS | WM8994_MIXINL_ENA |
+ WM8994_IN1L_ENA);
+
+ wm8994_write(codec, WM8994_INPUT_MIXER_2,
+ WM8994_IN1LP_TO_IN1L | WM8994_IN1LN_TO_IN1L);
+
+ /* Digital Path Enables and Unmutes */
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_4,
+ WM8994_AIF2ADCL_ENA | WM8994_ADCL_ENA);
+
+ wm8994_write(codec, WM8994_DAC2_MIXER_VOLUMES, 0x000C);
+ wm8994_write(codec, WM8994_DAC2_LEFT_VOLUME, 0x01C0);
+ wm8994_write(codec, WM8994_DAC2_RIGHT_VOLUME, 0x01C0);
+
+ /* Tx -> AIF2 Path */
+ wm8994_write(codec, WM8994_DAC2_LEFT_MIXER_ROUTING,
+ WM8994_ADC1_TO_DAC2L);
+ wm8994_write(codec, WM8994_DAC2_RIGHT_MIXER_ROUTING,
+ WM8994_ADC1_TO_DAC2R);
+
+ wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0019);
+
+ /* Unmute IN1L PGA, update volume */
+ val = wm8994_read(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME);
+ val &= ~(WM8994_IN1L_MUTE_MASK);
+ wm8994_write(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME, val);
+
+ /* Unmute the PGA */
+ val = wm8994_read(codec, WM8994_INPUT_MIXER_3);
+ val &= ~(WM8994_IN1L_TO_MIXINL_MASK);
+ val |= (WM8994_IN1L_TO_MIXINL);
+ wm8994_write(codec, WM8994_INPUT_MIXER_3, val);
+
+ /* Volume Control - Output */
+ val = wm8994_read(codec, WM8994_LEFT_OPGA_VOLUME);
+ val &= ~(WM8994_MIXOUTL_MUTE_N_MASK);
+ val |= (WM8994_MIXOUTL_MUTE_N);
+ wm8994_write(codec, WM8994_LEFT_OPGA_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_RIGHT_OPGA_VOLUME);
+ val &= ~(WM8994_MIXOUTR_MUTE_N_MASK);
+ val |= (WM8994_MIXOUTR_MUTE_N);
+ wm8994_write(codec, WM8994_RIGHT_OPGA_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_HPOUT2_VOLUME);
+ val &= ~(WM8994_HPOUT2_MUTE_MASK);
+ wm8994_write(codec, WM8994_HPOUT2_VOLUME, val);
+
+ wm8994_set_codec_gain(codec, VOICECALL_MODE, VOICECALL_RCV);
+
+ /* Unmute DAC1 left */
+ val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME);
+ val &= ~(WM8994_DAC1L_MUTE_MASK);
+ wm8994_write(codec, WM8994_DAC1_LEFT_VOLUME, val);
+
+ /* Unmute and volume ctrl RightDAC */
+ val = wm8994_read(codec, WM8994_DAC1_RIGHT_VOLUME);
+ val &= ~(WM8994_DAC1R_MUTE_MASK);
+ wm8994_write(codec, WM8994_DAC1_RIGHT_VOLUME, val);
+
+ /* Output Mixing */
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_1, WM8994_DAC1L_TO_MIXOUTL);
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_2, WM8994_DAC1R_TO_MIXOUTR);
+
+ /* Analogue Output Configuration */
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_3,
+ WM8994_MIXOUTLVOL_ENA | WM8994_MIXOUTRVOL_ENA |
+ WM8994_MIXOUTL_ENA | WM8994_MIXOUTR_ENA);
+ wm8994_write(codec, WM8994_HPOUT2_MIXER, WM8994_MIXOUTLVOL_TO_HPOUT2 |
+ WM8994_MIXOUTRVOL_TO_HPOUT2);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_1,
+ WM8994_HPOUT2_ENA | WM8994_VMID_SEL_NORMAL | WM8994_BIAS_ENA);
+
+ wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, 0x0000);
+ wm8994_write(codec, WM8994_AIF2_DAC_FILTERS_1, 0x0000);
+
+}
+
+
+void wm8994_set_voicecall_receiver(struct snd_soc_codec *codec)
+{
+ if (herring_is_cdma_wimax_dev())
+ wm8994_set_cdma_voicecall_receiver(codec);
+ else
+ wm8994_set_gsm_voicecall_receiver(codec);
+}
+
+void wm8994_set_voicecall_headset(struct snd_soc_codec *codec)
+{
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+ int val;
+
+ u16 testreturn1 = 0;
+ u16 testreturn2 = 0;
+ u16 testlow1 = 0;
+ u16 testhigh1 = 0;
+ u8 testlow = 0;
+ u8 testhigh = 0;
+
+ DEBUG_LOG("");
+
+ wm8994_earsel_control(wm8994->pdata, 1);
+
+ wm8994_set_voicecall_common_setting(codec);
+
+ /* Digital Path Enables and Unmutes */
+ if (wm8994->hw_version == 3) { /* H/W Rev D */
+ wm8994_write(codec, WM8994_DAC2_LEFT_MIXER_ROUTING,
+ WM8994_ADC2_TO_DAC2L);
+ wm8994_write(codec, WM8994_DAC2_MIXER_VOLUMES, 0x0180);
+ wm8994_write(codec, WM8994_SIDETONE, 0x01C0);
+ } else { /* H/W Rev B */
+ wm8994_write(codec, WM8994_DAC2_MIXER_VOLUMES, 0x000C);
+ wm8994_write(codec, WM8994_DAC2_LEFT_MIXER_ROUTING,
+ WM8994_ADC1_TO_DAC2L);
+ wm8994_write(codec, WM8994_SIDETONE, 0x01C1);
+ }
+
+ /* Analogue Input Configuration */
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_2);
+ val &= ~(WM8994_TSHUT_ENA_MASK | WM8994_TSHUT_OPDIS_MASK |
+ WM8994_MIXINR_ENA_MASK | WM8994_IN1R_ENA_MASK);
+ val |= (WM8994_TSHUT_ENA | WM8994_TSHUT_OPDIS |
+ WM8994_MIXINR_ENA | WM8994_IN1R_ENA);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_2, 0x6110);
+
+ val = wm8994_read(codec, WM8994_RIGHT_LINE_INPUT_1_2_VOLUME);
+ val &= ~(WM8994_IN1R_MUTE_MASK);
+ wm8994_write(codec, WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_INPUT_MIXER_4);
+ val &= ~(WM8994_IN1R_TO_MIXINR_MASK);
+ val |= (WM8994_IN1R_TO_MIXINR);
+ wm8994_write(codec, WM8994_INPUT_MIXER_4, val);
+
+ val = wm8994_read(codec, WM8994_INPUT_MIXER_2);
+ val &= ~(WM8994_IN1RP_TO_IN1R_MASK | WM8994_IN1RN_TO_IN1R_MASK);
+ val |= (WM8994_IN1RP_TO_IN1R | WM8994_IN1RN_TO_IN1R);
+ wm8994_write(codec, WM8994_INPUT_MIXER_2, 0x0003);
+
+ /* Unmute*/
+ val = wm8994_read(codec, WM8994_LEFT_OPGA_VOLUME);
+ val &= ~(WM8994_MIXOUTL_MUTE_N_MASK);
+ val |= (WM8994_MIXOUTL_MUTE_N);
+ wm8994_write(codec, WM8994_LEFT_OPGA_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_RIGHT_OPGA_VOLUME);
+ val &= ~(WM8994_MIXOUTR_MUTE_N_MASK);
+ val |= (WM8994_MIXOUTR_MUTE_N);
+ wm8994_write(codec, WM8994_RIGHT_OPGA_VOLUME, val);
+
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_4, 0x2001);
+
+ val = wm8994_read(codec, 0x102);
+ val &= ~(0x0003);
+ val = 0x0003;
+ wm8994_write(codec, 0x102, val);
+
+ val = wm8994_read(codec, 0x56);
+ val &= ~(0x0003);
+ val = 0x0003;
+ wm8994_write(codec, 0x56, val);
+
+ val = wm8994_read(codec, 0x102);
+ val &= ~(0x0000);
+ val = 0x0000;
+ wm8994_write(codec, 0x102, val);
+
+ val = wm8994_read(codec, WM8994_CLASS_W_1);
+ val &= ~(0x0005);
+ val |= 0x0005;
+ wm8994_write(codec, WM8994_CLASS_W_1, val);
+
+ val = wm8994_read(codec, WM8994_LEFT_OUTPUT_VOLUME);
+ val &= ~(WM8994_HPOUT1L_MUTE_N_MASK);
+ val |= (WM8994_HPOUT1L_MUTE_N);
+ wm8994_write(codec, WM8994_LEFT_OUTPUT_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_RIGHT_OUTPUT_VOLUME);
+ val &= ~(WM8994_HPOUT1R_MUTE_N_MASK);
+ val |= (WM8994_HPOUT1R_MUTE_N);
+ wm8994_write(codec, WM8994_RIGHT_OUTPUT_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_DC_SERVO_2);
+ val &= ~(0x03E0);
+ val = 0x03E0;
+ wm8994_write(codec, WM8994_DC_SERVO_2, val);
+
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, 0x0303);
+
+ wm8994_write(codec, WM8994_ANALOGUE_HP_1, 0x0022);
+ wm8994_write(codec, WM8994_CHARGE_PUMP_1, 0x9F25);
+
+ msleep(5);
+
+ /* Analogue Output Configuration */
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_1, 0x0001);
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_2, 0x0001);
+
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, 0x0030);
+
+ if (herring_is_cdma_wimax_dev())
+ wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0009);
+ else
+ wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0019);
+
+ if (!wm8994->dc_servo[DCS_VOICE]) {
+ wait_for_dc_servo(codec,
+ WM8994_DCS_TRIG_SERIES_0 |
+ WM8994_DCS_TRIG_SERIES_1);
+
+ testreturn1 = wm8994_read(codec, WM8994_DC_SERVO_4);
+
+ testlow = (signed char)(testreturn1 & 0xff);
+ testhigh = (signed char)((testreturn1>>8) & 0xff);
+
+ testlow1 = ((signed short)testlow - 5) & 0x00ff;
+ testhigh1 = (((signed short)(testhigh - 5)<<8) & 0xff00);
+ testreturn2 = testlow1|testhigh1;
+ } else {
+ testreturn2 = wm8994->dc_servo[DCS_VOICE];
+ }
+
+ wm8994_write(codec, WM8994_DC_SERVO_4, testreturn2);
+
+ wait_for_dc_servo(codec,
+ WM8994_DCS_TRIG_DAC_WR_0 | WM8994_DCS_TRIG_DAC_WR_1);
+
+ wm8994->dc_servo[DCS_VOICE] = testreturn2;
+
+ wm8994_write(codec, WM8994_ANALOGUE_HP_1, 0x00EE);
+
+ wm8994_set_codec_gain(codec, VOICECALL_MODE, VOICECALL_HP);
+
+ /* Unmute DAC1 left */
+ val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME);
+ val &= ~(WM8994_DAC1L_MUTE_MASK);
+ wm8994_write(codec, WM8994_DAC1_LEFT_VOLUME, val);
+
+ /* Unmute and volume ctrl RightDAC */
+ val = wm8994_read(codec, WM8994_DAC1_RIGHT_VOLUME);
+ val &= ~(WM8994_DAC1R_MUTE_MASK);
+ wm8994_write(codec, WM8994_DAC1_RIGHT_VOLUME, val);
+
+ wm8994_write(codec, WM8994_DAC2_LEFT_VOLUME, 0x01C0);
+
+ wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, 0x0000);
+ wm8994_write(codec, WM8994_AIF2_DAC_FILTERS_1, 0x0000);
+
+}
+
+void wm8994_set_voicecall_headphone(struct snd_soc_codec *codec)
+{
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+ int val;
+
+ u16 testreturn1 = 0;
+ u16 testreturn2 = 0;
+ u16 testlow1 = 0;
+ u16 testhigh1 = 0;
+ u8 testlow = 0;
+ u8 testhigh = 0;
+
+ DEBUG_LOG("");
+ audio_ctrl_mic_bias_gpio(wm8994->pdata, 1);
+
+ wm8994_earsel_control(wm8994->pdata, 1);
+
+ wm8994_set_voicecall_common_setting(codec);
+
+ /* Digital Path Enables and Unmutes */
+ wm8994_write(codec, WM8994_DAC2_MIXER_VOLUMES, 0x000C);
+ wm8994_write(codec, WM8994_DAC2_LEFT_MIXER_ROUTING,
+ WM8994_ADC1_TO_DAC2L);
+
+ /* Analogue Input Configuration */
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_2,
+ WM8994_TSHUT_ENA | WM8994_TSHUT_OPDIS | WM8994_MIXINL_ENA |
+ WM8994_IN1L_ENA);
+
+ /* Unmute IN1L PGA, update volume */
+ val = wm8994_read(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME);
+ val &= ~(WM8994_IN1L_MUTE_MASK);
+ wm8994_write(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME, val);
+
+ /* Unmute the PGA */
+ val = wm8994_read(codec, WM8994_INPUT_MIXER_3);
+ val &= ~(WM8994_IN1L_TO_MIXINL_MASK);
+ val |= (WM8994_IN1L_TO_MIXINL);
+ wm8994_write(codec, WM8994_INPUT_MIXER_3, val);
+
+ wm8994_write(codec, WM8994_INPUT_MIXER_2,
+ WM8994_IN1LP_TO_IN1L | WM8994_IN1LN_TO_IN1L);
+
+ /* Unmute*/
+ val = wm8994_read(codec, WM8994_LEFT_OPGA_VOLUME);
+ val &= ~(WM8994_MIXOUTL_MUTE_N_MASK);
+ val |= (WM8994_MIXOUTL_MUTE_N);
+ wm8994_write(codec, WM8994_LEFT_OPGA_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_RIGHT_OPGA_VOLUME);
+ val &= ~(WM8994_MIXOUTR_MUTE_N_MASK);
+ val |= (WM8994_MIXOUTR_MUTE_N);
+ wm8994_write(codec, WM8994_RIGHT_OPGA_VOLUME, val);
+
+ /* Digital Path Enables and Unmutes */
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_4,
+ WM8994_AIF2ADCL_ENA | WM8994_ADCL_ENA);
+
+ val = wm8994_read(codec, 0x102);
+ val &= ~(0x0003);
+ val = 0x0003;
+ wm8994_write(codec, 0x102, val);
+
+ val = wm8994_read(codec, 0x56);
+ val &= ~(0x0003);
+ val = 0x0003;
+ wm8994_write(codec, 0x56, val);
+
+ val = wm8994_read(codec, 0x102);
+ val &= ~(0x0000);
+ val = 0x0000;
+ wm8994_write(codec, 0x102, val);
+
+ val = wm8994_read(codec, WM8994_CLASS_W_1);
+ val &= ~(0x0005);
+ val |= 0x0005;
+ wm8994_write(codec, WM8994_CLASS_W_1, val);
+
+ val = wm8994_read(codec, WM8994_LEFT_OUTPUT_VOLUME);
+ val &= ~(WM8994_HPOUT1L_MUTE_N_MASK);
+ val |= (WM8994_HPOUT1L_MUTE_N);
+ wm8994_write(codec, WM8994_LEFT_OUTPUT_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_RIGHT_OUTPUT_VOLUME);
+ val &= ~(WM8994_HPOUT1R_MUTE_N_MASK);
+ val |= (WM8994_HPOUT1R_MUTE_N);
+ wm8994_write(codec, WM8994_RIGHT_OUTPUT_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_DC_SERVO_2);
+ val &= ~(0x03E0);
+ val = 0x03E0;
+ wm8994_write(codec, WM8994_DC_SERVO_2, val);
+
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, 0x0303);
+
+ wm8994_write(codec, WM8994_ANALOGUE_HP_1, 0x0022);
+ wm8994_write(codec, WM8994_CHARGE_PUMP_1, 0x9F25);
+
+ msleep(5);
+
+ /* Analogue Output Configuration */
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_1, 0x0001);
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_2, 0x0001);
+
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, 0x0030);
+
+ if (herring_is_cdma_wimax_dev())
+ wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0009);
+ else
+ wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0019);
+
+ if (!wm8994->dc_servo[DCS_VOICE]) {
+ wait_for_dc_servo(codec,
+ WM8994_DCS_TRIG_SERIES_0 |
+ WM8994_DCS_TRIG_SERIES_1);
+
+ testreturn1 = wm8994_read(codec, WM8994_DC_SERVO_4);
+
+ testlow = (signed char)(testreturn1 & 0xff);
+ testhigh = (signed char)((testreturn1>>8) & 0xff);
+
+ testlow1 = ((signed short)testlow - 5) & 0x00ff;
+ testhigh1 = (((signed short)(testhigh - 5)<<8) & 0xff00);
+ testreturn2 = testlow1|testhigh1;
+ } else {
+ testreturn2 = wm8994->dc_servo[DCS_VOICE];
+ }
+
+ wm8994_write(codec, WM8994_DC_SERVO_4, testreturn2);
+
+ wait_for_dc_servo(codec,
+ WM8994_DCS_TRIG_DAC_WR_0 | WM8994_DCS_TRIG_DAC_WR_1);
+
+ wm8994->dc_servo[DCS_VOICE] = testreturn2;
+
+ wm8994_write(codec, WM8994_ANALOGUE_HP_1, 0x00EE);
+
+ wm8994_set_codec_gain(codec, VOICECALL_MODE, VOICECALL_HP_NO_MIC);
+
+ /* Unmute DAC1 left */
+ val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME);
+ val &= ~(WM8994_DAC1L_MUTE_MASK);
+ wm8994_write(codec, WM8994_DAC1_LEFT_VOLUME, val);
+
+ /* Unmute and volume ctrl RightDAC */
+ val = wm8994_read(codec, WM8994_DAC1_RIGHT_VOLUME);
+ val &= ~(WM8994_DAC1R_MUTE_MASK);
+ wm8994_write(codec, WM8994_DAC1_RIGHT_VOLUME, val);
+
+ wm8994_write(codec, WM8994_DAC2_LEFT_VOLUME, 0x01C0);
+
+ wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, 0x0000);
+ wm8994_write(codec, WM8994_AIF2_DAC_FILTERS_1, 0x0000);
+
+}
+
+void wm8994_set_voicecall_speaker(struct snd_soc_codec *codec)
+{
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+ int val;
+
+ DEBUG_LOG("");
+
+ audio_ctrl_mic_bias_gpio(wm8994->pdata, 1);
+
+ wm8994_set_voicecall_common_setting(codec);
+
+ wm8994_write(codec, 0x601, 0x0005);
+ wm8994_write(codec, 0x602, 0x0005);
+ wm8994_write(codec, 0x603, 0x000C);
+ /* Tx -> AIF2 Path */
+ wm8994_write(codec, WM8994_DAC2_LEFT_MIXER_ROUTING,
+ WM8994_ADC1_TO_DAC2L);
+
+ /* Analogue Input Configuration*/
+ wm8994_write(codec, 0x02, 0x6240);
+ wm8994_write(codec, WM8994_INPUT_MIXER_2, WM8994_IN1LP_TO_IN1L |
+ WM8994_IN1LN_TO_IN1L);
+
+ val = wm8994_read(codec, WM8994_INPUT_MIXER_3);
+ val &= ~(WM8994_IN1L_TO_MIXINL_MASK);
+ val |= (WM8994_IN1L_TO_MIXINL);
+ wm8994_write(codec, WM8994_INPUT_MIXER_3, val);
+
+ val = wm8994_read(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME);
+ val &= ~(WM8994_IN1L_MUTE_MASK);
+ wm8994_write(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME, val);
+
+ /* Analogue Output Configuration*/
+ wm8994_write(codec, 0x03, 0x0300);
+
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_4,
+ WM8994_AIF2ADCL_ENA | WM8994_ADCL_ENA);
+
+ if (herring_is_cdma_wimax_dev())
+ wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0009);
+ else
+ wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0019);
+
+ val = wm8994_read(codec, WM8994_SPEAKER_VOLUME_LEFT);
+ val &= ~(WM8994_SPKOUTL_MUTE_N_MASK);
+ val |= (WM8994_SPKOUTL_MUTE_N);
+ wm8994_write(codec, WM8994_SPEAKER_VOLUME_LEFT, val);
+
+ val = wm8994_read(codec, WM8994_SPEAKER_VOLUME_RIGHT);
+ val &= ~(WM8994_SPKOUTR_MUTE_N_MASK | WM8994_SPKOUTR_VOL_MASK);
+ wm8994_write(codec, WM8994_SPEAKER_VOLUME_RIGHT, val);
+
+ val = wm8994_read(codec, WM8994_SPKOUT_MIXERS);
+ val &= ~(WM8994_SPKMIXL_TO_SPKOUTL_MASK |
+ WM8994_SPKMIXR_TO_SPKOUTL_MASK |
+ WM8994_SPKMIXR_TO_SPKOUTR_MASK);
+ val |= WM8994_SPKMIXL_TO_SPKOUTL;
+ wm8994_write(codec, WM8994_SPKOUT_MIXERS, val);
+
+ wm8994_write(codec, 0x36, 0x0003);
+ /* Digital Path Enables and Unmutes*/
+
+ wm8994_write(codec, WM8994_SIDETONE, 0x01C0);
+
+
+ wm8994_write(codec, WM8994_ANALOGUE_HP_1, 0x0000);
+ wm8994_write(codec, WM8994_DC_SERVO_1, 0x0000);
+
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_1,
+ WM8994_SPKOUTL_ENA | WM8994_VMID_SEL_NORMAL | WM8994_BIAS_ENA);
+
+ wm8994_set_codec_gain(codec, VOICECALL_MODE, VOICECALL_SPK);
+
+ /* Unmute DAC1 left */
+ val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME);
+ val &= ~(WM8994_DAC1L_MUTE_MASK);
+ wm8994_write(codec, WM8994_DAC1_LEFT_VOLUME, val);
+
+ /* Unmute and volume ctrl RightDAC */
+ val = wm8994_read(codec, WM8994_DAC1_RIGHT_VOLUME);
+ val &= ~(WM8994_DAC1R_MUTE_MASK);
+ wm8994_write(codec, WM8994_DAC1_RIGHT_VOLUME, val);
+
+ wm8994_write(codec, WM8994_DAC2_LEFT_VOLUME, 0x01C0);
+ wm8994_write(codec, WM8994_AIF2_DAC_FILTERS_1, WM8994_AIF1DAC1_UNMUTE);
+ wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, WM8994_AIF1DAC2_UNMUTE);
+}
+
+void wm8994_set_voicecall_bluetooth(struct snd_soc_codec *codec)
+{
+ int val;
+
+ DEBUG_LOG("");
+
+ wm8994_set_voicecall_common_setting(codec);
+
+ /* GPIO Configuration */
+ wm8994_write(codec, WM8994_GPIO_8, WM8994_GP8_DIR | WM8994_GP8_DB);
+ wm8994_write(codec, WM8994_GPIO_9, WM8994_GP9_DB);
+ wm8994_write(codec, WM8994_GPIO_10, WM8994_GP10_DB);
+ wm8994_write(codec, WM8994_GPIO_11, WM8994_GP11_DB);
+
+ /* Digital Path Enables and Unmutes */
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_1);
+ val &= ~(WM8994_SPKOUTL_ENA_MASK | WM8994_HPOUT2_ENA_MASK |
+ WM8994_HPOUT1L_ENA_MASK | WM8994_HPOUT1R_ENA_MASK);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, val);
+
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_4,
+ WM8994_AIF2ADCL_ENA | WM8994_ADCL_ENA);
+
+ /* If Input MIC is enabled, bluetooth Rx is muted. */
+ wm8994_write(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME,
+ WM8994_IN1L_MUTE);
+ wm8994_write(codec, WM8994_RIGHT_LINE_INPUT_1_2_VOLUME,
+ WM8994_IN1R_MUTE);
+ wm8994_write(codec, WM8994_INPUT_MIXER_2, 0x00);
+ wm8994_write(codec, WM8994_INPUT_MIXER_3, 0x00);
+ wm8994_write(codec, WM8994_INPUT_MIXER_4, 0x00);
+
+ /*
+ * for BT DTMF Play
+ * Rx Path: AIF2ADCDAT2 select
+ * CP(CALL) Path:GPIO5/DACDAT2 select
+ * AP(DTMF) Path: DACDAT1 select
+ * Tx Path: GPIO8/DACDAT3 select
+ */
+
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_6, 0x000C);
+
+ /* AIF1 & AIF2 Output is connected to DAC1 */
+ wm8994_write(codec, WM8994_DAC2_LEFT_MIXER_ROUTING,
+ WM8994_AIF2DACL_TO_DAC2L | WM8994_AIF1DAC1L_TO_DAC2L);
+ wm8994_write(codec, WM8994_DAC2_RIGHT_MIXER_ROUTING,
+ WM8994_AIF2DACR_TO_DAC2R | WM8994_AIF1DAC1R_TO_DAC2R);
+
+ if (herring_is_cdma_wimax_dev())
+ wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0009);
+ else
+ wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0019);
+
+ wm8994_write(codec, WM8994_DAC2_MIXER_VOLUMES, 0x000C);
+
+ wm8994_write(codec, WM8994_DAC2_LEFT_VOLUME, 0x01C0);
+ wm8994_write(codec, WM8994_DAC2_RIGHT_VOLUME, 0x01C0);
+
+ wm8994_write(codec, WM8994_OVERSAMPLING, 0X0000);
+
+ wm8994_set_codec_gain(codec, VOICECALL_MODE, VOICECALL_BT);
+
+ /* Unmute DAC1 left */
+ val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME);
+ val &= ~(WM8994_DAC1L_MUTE_MASK);
+ wm8994_write(codec, WM8994_DAC1_LEFT_VOLUME, val);
+
+ /* Unmute and volume ctrl RightDAC */
+ val = wm8994_read(codec, WM8994_DAC1_RIGHT_VOLUME);
+ val &= ~(WM8994_DAC1R_MUTE_MASK);
+ wm8994_write(codec, WM8994_DAC1_RIGHT_VOLUME, val);
+
+ wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, 0x0000);
+ wm8994_write(codec, WM8994_AIF2_DAC_FILTERS_1, 0x0000);
+}
+
+void wm8994_set_voicecall_tty_vco(struct snd_soc_codec *codec)
+{
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+ int val;
+
+ u16 testreturn1 = 0;
+ u16 testreturn2 = 0;
+ u16 testlow1 = 0;
+ u16 testhigh1 = 0;
+ u8 testlow = 0;
+ u8 testhigh = 0;
+
+ DEBUG_LOG("");
+ audio_ctrl_mic_bias_gpio(wm8994->pdata, 1);
+
+ wm8994_earsel_control(wm8994->pdata, 1);
+
+ wm8994_set_voicecall_common_setting(codec);
+
+ /* Digital Path Enables and Unmutes */
+ wm8994_write(codec, WM8994_DAC2_MIXER_VOLUMES, 0x000C);
+ wm8994_write(codec, WM8994_DAC2_LEFT_MIXER_ROUTING,
+ WM8994_ADC1_TO_DAC2L);
+
+ /* Analogue Input Configuration */
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_2,
+ WM8994_TSHUT_ENA | WM8994_TSHUT_OPDIS | WM8994_MIXINL_ENA |
+ WM8994_IN1L_ENA);
+
+ /* Unmute IN1L PGA, update volume */
+ val = wm8994_read(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME);
+ val &= ~(WM8994_IN1L_MUTE_MASK);
+ wm8994_write(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME, val);
+
+ /* Unmute the PGA */
+ val = wm8994_read(codec, WM8994_INPUT_MIXER_3);
+ val &= ~(WM8994_IN1L_TO_MIXINL_MASK);
+ val |= (WM8994_IN1L_TO_MIXINL);
+ wm8994_write(codec, WM8994_INPUT_MIXER_3, val);
+
+ wm8994_write(codec, WM8994_INPUT_MIXER_2,
+ WM8994_IN1LP_TO_IN1L | WM8994_IN1LN_TO_IN1L);
+
+ /* Unmute*/
+ val = wm8994_read(codec, WM8994_LEFT_OPGA_VOLUME);
+ val &= ~(WM8994_MIXOUTL_MUTE_N_MASK);
+ val |= (WM8994_MIXOUTL_MUTE_N);
+ wm8994_write(codec, WM8994_LEFT_OPGA_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_RIGHT_OPGA_VOLUME);
+ val &= ~(WM8994_MIXOUTR_MUTE_N_MASK);
+ val |= (WM8994_MIXOUTR_MUTE_N);
+ wm8994_write(codec, WM8994_RIGHT_OPGA_VOLUME, val);
+
+ /* Digital Path Enables and Unmutes */
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_4,
+ WM8994_AIF2ADCL_ENA | WM8994_ADCL_ENA);
+
+ val = wm8994_read(codec, 0x102);
+ val &= ~(0x0003);
+ val = 0x0003;
+ wm8994_write(codec, 0x102, val);
+
+ val = wm8994_read(codec, 0x56);
+ val &= ~(0x0003);
+ val = 0x0003;
+ wm8994_write(codec, 0x56, val);
+
+ val = wm8994_read(codec, 0x102);
+ val &= ~(0x0000);
+ val = 0x0000;
+ wm8994_write(codec, 0x102, val);
+
+ val = wm8994_read(codec, WM8994_CLASS_W_1);
+ val &= ~(0x0005);
+ val |= 0x0005;
+ wm8994_write(codec, WM8994_CLASS_W_1, val);
+
+ val = wm8994_read(codec, WM8994_LEFT_OUTPUT_VOLUME);
+ val &= ~(WM8994_HPOUT1L_MUTE_N_MASK);
+ val |= (WM8994_HPOUT1L_MUTE_N);
+ wm8994_write(codec, WM8994_LEFT_OUTPUT_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_RIGHT_OUTPUT_VOLUME);
+ val &= ~(WM8994_HPOUT1R_MUTE_N_MASK);
+ val |= (WM8994_HPOUT1R_MUTE_N);
+ wm8994_write(codec, WM8994_RIGHT_OUTPUT_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_DC_SERVO_2);
+ val &= ~(0x03E0);
+ val = 0x03E0;
+ wm8994_write(codec, WM8994_DC_SERVO_2, val);
+
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, 0x0303);
+
+ wm8994_write(codec, WM8994_ANALOGUE_HP_1, 0x0022);
+ wm8994_write(codec, WM8994_CHARGE_PUMP_1, 0x9F25);
+
+ msleep(5);
+
+ /* Analogue Output Configuration */
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_1, 0x0001);
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_2, 0x0001);
+
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, 0x0030);
+
+ if (herring_is_cdma_wimax_dev())
+ wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0009);
+ else
+ wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0019);
+
+ if (!wm8994->dc_servo[DCS_VOICE]) {
+ wait_for_dc_servo(codec,
+ WM8994_DCS_TRIG_SERIES_0 |
+ WM8994_DCS_TRIG_SERIES_1);
+
+ testreturn1 = wm8994_read(codec, WM8994_DC_SERVO_4);
+
+ testlow = (signed char)(testreturn1 & 0xff);
+ testhigh = (signed char)((testreturn1>>8) & 0xff);
+
+ testlow1 = ((signed short)testlow - 5) & 0x00ff;
+ testhigh1 = (((signed short)(testhigh - 5)<<8) & 0xff00);
+ testreturn2 = testlow1|testhigh1;
+ } else {
+ testreturn2 = wm8994->dc_servo[DCS_VOICE];
+ }
+
+ wm8994_write(codec, WM8994_DC_SERVO_4, testreturn2);
+
+ wait_for_dc_servo(codec,
+ WM8994_DCS_TRIG_DAC_WR_0 | WM8994_DCS_TRIG_DAC_WR_1);
+
+ wm8994->dc_servo[DCS_VOICE] = testreturn2;
+
+ wm8994_write(codec, WM8994_ANALOGUE_HP_1, 0x00EE);
+
+ wm8994_set_codec_gain(codec, VOICECALL_MODE, VOICECALL_TTY_VCO);
+
+ /* Unmute DAC1 left */
+ val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME);
+ val &= ~(WM8994_DAC1L_MUTE_MASK);
+ wm8994_write(codec, WM8994_DAC1_LEFT_VOLUME, val);
+
+ /* Unmute and volume ctrl RightDAC */
+ val = wm8994_read(codec, WM8994_DAC1_RIGHT_VOLUME);
+ val &= ~(WM8994_DAC1R_MUTE_MASK);
+ wm8994_write(codec, WM8994_DAC1_RIGHT_VOLUME, val);
+
+ wm8994_write(codec, WM8994_DAC2_LEFT_VOLUME, 0x01C0);
+
+ wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, 0x0000);
+ wm8994_write(codec, WM8994_AIF2_DAC_FILTERS_1, 0x0000);
+
+}
+
+void wm8994_set_voicecall_tty_hco(struct snd_soc_codec *codec)
+{
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+ int val;
+
+ u16 testreturn1 = 0;
+ u16 testreturn2 = 0;
+ u16 testlow1 = 0;
+ u16 testhigh1 = 0;
+ u8 testlow = 0;
+ u8 testhigh = 0;
+
+ DEBUG_LOG("");
+
+ wm8994_earsel_control(wm8994->pdata, 1);
+
+ wm8994_set_voicecall_common_setting(codec);
+
+ /* Digital Path Enables and Unmutes */
+ if (wm8994->hw_version == 3) { /* H/W Rev D */
+ wm8994_write(codec, WM8994_DAC2_LEFT_MIXER_ROUTING,
+ WM8994_ADC2_TO_DAC2L);
+ wm8994_write(codec, WM8994_DAC2_MIXER_VOLUMES, 0x0180);
+ wm8994_write(codec, WM8994_SIDETONE, 0x01C0);
+ } else { /* H/W Rev B */
+ wm8994_write(codec, WM8994_DAC2_MIXER_VOLUMES, 0x000C);
+ wm8994_write(codec, WM8994_DAC2_LEFT_MIXER_ROUTING,
+ WM8994_ADC1_TO_DAC2L);
+ wm8994_write(codec, WM8994_SIDETONE, 0x01C1);
+ }
+
+ /* Analogue Input Configuration */
+ val = (WM8994_TSHUT_ENA | WM8994_TSHUT_OPDIS |
+ WM8994_MIXINR_ENA | WM8994_IN1R_ENA);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_2, val);
+
+ val = wm8994_read(codec, WM8994_RIGHT_LINE_INPUT_1_2_VOLUME);
+ val &= ~(WM8994_IN1R_MUTE_MASK);
+ wm8994_write(codec, WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_INPUT_MIXER_4);
+ val &= ~(WM8994_IN1R_TO_MIXINR_MASK);
+ val |= (WM8994_IN1R_TO_MIXINR);
+ wm8994_write(codec, WM8994_INPUT_MIXER_4, val);
+
+ val = (WM8994_IN1RP_TO_IN1R | WM8994_IN1RN_TO_IN1R);
+ wm8994_write(codec, WM8994_INPUT_MIXER_2, val);
+
+ /* Unmute*/
+ val = wm8994_read(codec, WM8994_LEFT_OPGA_VOLUME);
+ val &= ~(WM8994_MIXOUTL_MUTE_N_MASK);
+ val |= (WM8994_MIXOUTL_MUTE_N);
+ wm8994_write(codec, WM8994_LEFT_OPGA_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_RIGHT_OPGA_VOLUME);
+ val &= ~(WM8994_MIXOUTR_MUTE_N_MASK);
+ val |= (WM8994_MIXOUTR_MUTE_N);
+ wm8994_write(codec, WM8994_RIGHT_OPGA_VOLUME, val);
+
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_4,
+ WM8994_AIF2ADCL_ENA | WM8994_ADCR_ENA);
+
+ val = wm8994_read(codec, 0x102);
+ val &= ~(0x0003);
+ val = 0x0003;
+ wm8994_write(codec, 0x102, val);
+
+ val = wm8994_read(codec, 0x56);
+ val &= ~(0x0003);
+ val = 0x0003;
+ wm8994_write(codec, 0x56, val);
+
+ val = wm8994_read(codec, 0x102);
+ val &= ~(0x0000);
+ val = 0x0000;
+ wm8994_write(codec, 0x102, val);
+
+ val = wm8994_read(codec, WM8994_CLASS_W_1);
+ val &= ~(0x0005);
+ val |= 0x0005;
+ wm8994_write(codec, WM8994_CLASS_W_1, val);
+
+ val = wm8994_read(codec, WM8994_LEFT_OUTPUT_VOLUME);
+ val &= ~(WM8994_HPOUT1L_MUTE_N_MASK);
+ val |= (WM8994_HPOUT1L_MUTE_N);
+ wm8994_write(codec, WM8994_LEFT_OUTPUT_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_RIGHT_OUTPUT_VOLUME);
+ val &= ~(WM8994_HPOUT1R_MUTE_N_MASK);
+ val |= (WM8994_HPOUT1R_MUTE_N);
+ wm8994_write(codec, WM8994_RIGHT_OUTPUT_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_DC_SERVO_2);
+ val &= ~(0x03E0);
+ val = 0x03E0;
+ wm8994_write(codec, WM8994_DC_SERVO_2, val);
+
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_1,
+ WM8994_HPOUT2_ENA | WM8994_VMID_SEL_NORMAL | WM8994_BIAS_ENA);
+
+ wm8994_write(codec, WM8994_ANALOGUE_HP_1, 0x0022);
+ wm8994_write(codec, WM8994_CHARGE_PUMP_1, 0x9F25);
+
+ msleep(5);
+
+ /* Analogue Output Configuration */
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_1, 0x0001);
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_2, 0x0001);
+ wm8994_write(codec, WM8994_HPOUT2_MIXER, WM8994_MIXOUTLVOL_TO_HPOUT2 |
+ WM8994_MIXOUTRVOL_TO_HPOUT2);
+
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_3,
+ WM8994_MIXOUTLVOL_ENA | WM8994_MIXOUTRVOL_ENA |
+ WM8994_MIXOUTL_ENA | WM8994_MIXOUTR_ENA);
+
+ if (herring_is_cdma_wimax_dev())
+ wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0009);
+ else
+ wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0019);
+
+ if (!wm8994->dc_servo[DCS_VOICE]) {
+ wait_for_dc_servo(codec,
+ WM8994_DCS_TRIG_SERIES_0 |
+ WM8994_DCS_TRIG_SERIES_1);
+
+ testreturn1 = wm8994_read(codec, WM8994_DC_SERVO_4);
+
+ testlow = (signed char)(testreturn1 & 0xff);
+ testhigh = (signed char)((testreturn1>>8) & 0xff);
+
+ testlow1 = ((signed short)testlow - 5) & 0x00ff;
+ testhigh1 = (((signed short)(testhigh - 5)<<8) & 0xff00);
+ testreturn2 = testlow1|testhigh1;
+ } else {
+ testreturn2 = wm8994->dc_servo[DCS_VOICE];
+ }
+
+ wm8994_write(codec, WM8994_DC_SERVO_4, testreturn2);
+
+ wait_for_dc_servo(codec,
+ WM8994_DCS_TRIG_DAC_WR_0 | WM8994_DCS_TRIG_DAC_WR_1);
+
+ wm8994->dc_servo[DCS_VOICE] = testreturn2;
+
+ wm8994_write(codec, WM8994_ANALOGUE_HP_1, 0x00EE);
+
+ val = wm8994_read(codec, WM8994_HPOUT2_VOLUME);
+ val &= ~(WM8994_HPOUT2_MUTE_MASK);
+ wm8994_write(codec, WM8994_HPOUT2_VOLUME, val);
+
+ wm8994_set_codec_gain(codec, VOICECALL_MODE, VOICECALL_TTY_HCO);
+
+ /* Unmute DAC1 left */
+ val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME);
+ val &= ~(WM8994_DAC1L_MUTE_MASK);
+ wm8994_write(codec, WM8994_DAC1_LEFT_VOLUME, val);
+
+ /* Unmute and volume ctrl RightDAC */
+ val = wm8994_read(codec, WM8994_DAC1_RIGHT_VOLUME);
+ val &= ~(WM8994_DAC1R_MUTE_MASK);
+ wm8994_write(codec, WM8994_DAC1_RIGHT_VOLUME, val);
+
+ wm8994_write(codec, WM8994_DAC2_LEFT_VOLUME, 0x01C0);
+
+ wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, 0x0000);
+ wm8994_write(codec, WM8994_AIF2_DAC_FILTERS_1, 0x0000);
+
+}
+
+void wm8994_set_voicecall_tty_full(struct snd_soc_codec *codec)
+{
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+ int val;
+
+ u16 testreturn1 = 0;
+ u16 testreturn2 = 0;
+ u16 testlow1 = 0;
+ u16 testhigh1 = 0;
+ u8 testlow = 0;
+ u8 testhigh = 0;
+
+ DEBUG_LOG("");
+
+ wm8994_earsel_control(wm8994->pdata, 1);
+
+ wm8994_set_voicecall_common_setting(codec);
+
+ /* Digital Path Enables and Unmutes */
+ if (wm8994->hw_version == 3) { /* H/W Rev D */
+ wm8994_write(codec, WM8994_DAC2_LEFT_MIXER_ROUTING,
+ WM8994_ADC2_TO_DAC2L);
+ wm8994_write(codec, WM8994_DAC2_MIXER_VOLUMES, 0x0180);
+ wm8994_write(codec, WM8994_SIDETONE, 0x01C0);
+ } else { /* H/W Rev B */
+ wm8994_write(codec, WM8994_DAC2_MIXER_VOLUMES, 0x000C);
+ wm8994_write(codec, WM8994_DAC2_LEFT_MIXER_ROUTING,
+ WM8994_ADC1_TO_DAC2L);
+ wm8994_write(codec, WM8994_SIDETONE, 0x01C1);
+ }
+
+ /* Analogue Input Configuration */
+ val = (WM8994_TSHUT_ENA | WM8994_TSHUT_OPDIS |
+ WM8994_MIXINR_ENA | WM8994_IN1R_ENA);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_2, val);
+
+ val = wm8994_read(codec, WM8994_RIGHT_LINE_INPUT_1_2_VOLUME);
+ val &= ~(WM8994_IN1R_MUTE_MASK);
+ wm8994_write(codec, WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_INPUT_MIXER_4);
+ val &= ~(WM8994_IN1R_TO_MIXINR_MASK);
+ val |= (WM8994_IN1R_TO_MIXINR);
+ wm8994_write(codec, WM8994_INPUT_MIXER_4, val);
+
+ val = (WM8994_IN1RP_TO_IN1R | WM8994_IN1RN_TO_IN1R);
+ wm8994_write(codec, WM8994_INPUT_MIXER_2, val);
+
+ /* Unmute*/
+ val = wm8994_read(codec, WM8994_LEFT_OPGA_VOLUME);
+ val &= ~(WM8994_MIXOUTL_MUTE_N_MASK);
+ val |= (WM8994_MIXOUTL_MUTE_N);
+ wm8994_write(codec, WM8994_LEFT_OPGA_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_RIGHT_OPGA_VOLUME);
+ val &= ~(WM8994_MIXOUTR_MUTE_N_MASK);
+ val |= (WM8994_MIXOUTR_MUTE_N);
+ wm8994_write(codec, WM8994_RIGHT_OPGA_VOLUME, val);
+
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_4, 0x2001);
+
+ val = wm8994_read(codec, 0x102);
+ val &= ~(0x0003);
+ val = 0x0003;
+ wm8994_write(codec, 0x102, val);
+
+ val = wm8994_read(codec, 0x56);
+ val &= ~(0x0003);
+ val = 0x0003;
+ wm8994_write(codec, 0x56, val);
+
+ val = wm8994_read(codec, 0x102);
+ val &= ~(0x0000);
+ val = 0x0000;
+ wm8994_write(codec, 0x102, val);
+
+ val = wm8994_read(codec, WM8994_CLASS_W_1);
+ val &= ~(0x0005);
+ val |= 0x0005;
+ wm8994_write(codec, WM8994_CLASS_W_1, val);
+
+ val = wm8994_read(codec, WM8994_LEFT_OUTPUT_VOLUME);
+ val &= ~(WM8994_HPOUT1L_MUTE_N_MASK);
+ val |= (WM8994_HPOUT1L_MUTE_N);
+ wm8994_write(codec, WM8994_LEFT_OUTPUT_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_RIGHT_OUTPUT_VOLUME);
+ val &= ~(WM8994_HPOUT1R_MUTE_N_MASK);
+ val |= (WM8994_HPOUT1R_MUTE_N);
+ wm8994_write(codec, WM8994_RIGHT_OUTPUT_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_DC_SERVO_2);
+ val &= ~(0x03E0);
+ val = 0x03E0;
+ wm8994_write(codec, WM8994_DC_SERVO_2, val);
+
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, 0x0303);
+
+ wm8994_write(codec, WM8994_ANALOGUE_HP_1, 0x0022);
+ wm8994_write(codec, WM8994_CHARGE_PUMP_1, 0x9F25);
+
+ msleep(5);
+
+ /* Analogue Output Configuration */
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_1, 0x0001);
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_2, 0x0001);
+
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, 0x0030);
+
+ if (herring_is_cdma_wimax_dev())
+ wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0009);
+ else
+ wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0019);
+
+ if (!wm8994->dc_servo[DCS_VOICE]) {
+ wait_for_dc_servo(codec,
+ WM8994_DCS_TRIG_SERIES_0 |
+ WM8994_DCS_TRIG_SERIES_1);
+
+ testreturn1 = wm8994_read(codec, WM8994_DC_SERVO_4);
+
+ testlow = (signed char)(testreturn1 & 0xff);
+ testhigh = (signed char)((testreturn1>>8) & 0xff);
+
+ testlow1 = ((signed short)testlow - 5) & 0x00ff;
+ testhigh1 = (((signed short)(testhigh - 5)<<8) & 0xff00);
+ testreturn2 = testlow1|testhigh1;
+ } else {
+ testreturn2 = wm8994->dc_servo[DCS_VOICE];
+ }
+
+ wm8994_write(codec, WM8994_DC_SERVO_4, testreturn2);
+
+ wait_for_dc_servo(codec,
+ WM8994_DCS_TRIG_DAC_WR_0 | WM8994_DCS_TRIG_DAC_WR_1);
+
+ wm8994->dc_servo[DCS_VOICE] = testreturn2;
+
+ wm8994_write(codec, WM8994_ANALOGUE_HP_1, 0x00EE);
+
+ wm8994_set_codec_gain(codec, VOICECALL_MODE, VOICECALL_TTY_FULL);
+
+ /* Unmute DAC1 left */
+ val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME);
+ val &= ~(WM8994_DAC1L_MUTE_MASK);
+ wm8994_write(codec, WM8994_DAC1_LEFT_VOLUME, val);
+
+ /* Unmute and volume ctrl RightDAC */
+ val = wm8994_read(codec, WM8994_DAC1_RIGHT_VOLUME);
+ val &= ~(WM8994_DAC1R_MUTE_MASK);
+ wm8994_write(codec, WM8994_DAC1_RIGHT_VOLUME, val);
+
+ wm8994_write(codec, WM8994_DAC2_LEFT_VOLUME, 0x01C0);
+
+ wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, 0x0000);
+ wm8994_write(codec, WM8994_AIF2_DAC_FILTERS_1, 0x0000);
+
+}
+
+int wm8994_set_codec_gain(struct snd_soc_codec *codec, u16 mode, u16 device)
+{
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+ int i;
+ u32 gain_set_bits = COMMON_SET_BIT;
+ u16 val;
+ struct gain_info_t *default_gain_table_p = NULL;
+ int table_num = 0;
+
+ if (mode == PLAYBACK_MODE) {
+
+ if (herring_is_cdma_wimax_dev())
+ default_gain_table_p = cdma_playback_gain_table;
+ else
+ default_gain_table_p = playback_gain_table;
+
+ table_num = PLAYBACK_GAIN_NUM;
+
+ switch (device) {
+ case PLAYBACK_RCV:
+ gain_set_bits |= PLAYBACK_RCV;
+ break;
+ case PLAYBACK_SPK:
+ gain_set_bits |= PLAYBACK_SPK;
+ break;
+ case PLAYBACK_HP:
+ gain_set_bits |= PLAYBACK_HP;
+ break;
+ case PLAYBACK_BT:
+ gain_set_bits |= PLAYBACK_BT;
+ break;
+ case PLAYBACK_SPK_HP:
+ gain_set_bits |= PLAYBACK_SPK_HP;
+ break;
+ case PLAYBACK_RING_SPK:
+ gain_set_bits |= (PLAYBACK_SPK | PLAYBACK_RING_SPK);
+ break;
+ case PLAYBACK_RING_HP:
+ gain_set_bits |= (PLAYBACK_HP | PLAYBACK_RING_HP);
+ break;
+ case PLAYBACK_RING_SPK_HP:
+ gain_set_bits |= (PLAYBACK_SPK_HP |
+ PLAYBACK_RING_SPK_HP);
+ break;
+ case PLAYBACK_HP_NO_MIC:
+ gain_set_bits |= PLAYBACK_HP_NO_MIC;
+ break;
+ default:
+ pr_err("playback modo gain flag is wrong\n");
+ break;
+ }
+ } else if (mode == VOICECALL_MODE) {
+ if (herring_is_cdma_wimax_dev())
+ default_gain_table_p = cdma_voicecall_gain_table;
+ else
+ default_gain_table_p = voicecall_gain_table;
+ table_num = VOICECALL_GAIN_NUM;
+
+ switch (device) {
+ case VOICECALL_RCV:
+ gain_set_bits |= VOICECALL_RCV;
+ break;
+ case VOICECALL_SPK:
+ gain_set_bits |= VOICECALL_SPK;
+ break;
+ case VOICECALL_HP:
+ gain_set_bits |= VOICECALL_HP;
+ break;
+ case VOICECALL_HP_NO_MIC:
+ gain_set_bits |= VOICECALL_HP_NO_MIC;
+ break;
+ case VOICECALL_BT:
+ gain_set_bits |= VOICECALL_BT;
+ break;
+ case VOICECALL_TTY_VCO:
+ gain_set_bits |= (VOICECALL_HP_NO_MIC | VOICECALL_TTY_VCO);
+ break;
+ case VOICECALL_TTY_HCO:
+ gain_set_bits |= (VOICECALL_RCV | VOICECALL_TTY_HCO);
+ break;
+ case VOICECALL_TTY_FULL:
+ gain_set_bits |= (VOICECALL_HP | VOICECALL_TTY_FULL);
+ break;
+ default:
+ pr_err("voicemode gain flag is wrong\n");
+ }
+ } else if (mode == RECORDING_MODE) {
+ default_gain_table_p = recording_gain_table;
+ table_num = RECORDING_GAIN_NUM;
+
+ switch (device) {
+ case RECORDING_MAIN:
+ gain_set_bits |= RECORDING_MAIN;
+ break;
+ case RECORDING_HP:
+ gain_set_bits |= RECORDING_HP;
+ break;
+ case RECORDING_BT:
+ gain_set_bits |= RECORDING_BT;
+ break;
+ case RECORDING_REC_MAIN:
+ gain_set_bits |= RECORDING_REC_MAIN;
+ break;
+ case RECORDING_REC_HP:
+ gain_set_bits |= RECORDING_REC_HP;
+ break;
+ case RECORDING_REC_BT:
+ gain_set_bits |= RECORDING_REC_BT;
+ break;
+ case RECORDING_CAM_MAIN:
+ gain_set_bits |= RECORDING_CAM_MAIN;
+ break;
+ case RECORDING_CAM_HP:
+ gain_set_bits |= RECORDING_CAM_HP;
+ break;
+ case RECORDING_CAM_BT:
+ gain_set_bits |= RECORDING_CAM_BT;
+ break;
+ case RECORDING_VC_MAIN:
+ gain_set_bits |= RECORDING_VC_MAIN;
+ break;
+ case RECORDING_VC_HP:
+ gain_set_bits |= RECORDING_VC_HP;
+ break;
+ case RECORDING_VC_BT:
+ gain_set_bits |= RECORDING_VC_BT;
+ break;
+ default:
+ pr_err("recording gain flag is wrong\n");
+ }
+
+ }
+
+ DEBUG_LOG("Set gain mode = 0x%x, device = 0x%x, gain_bits = 0x%x,\
+ table_num=%d, gain_code = %d\n",
+ mode, device, gain_set_bits, table_num, wm8994->gain_code);
+
+ /* default gain table setting */
+ for (i = 0; i < table_num; i++) {
+ if ((default_gain_table_p + i)->mode & gain_set_bits) {
+ val = wm8994_read(codec, (default_gain_table_p + i)->reg);
+ val &= ~((default_gain_table_p + i)->mask);
+ val |= (default_gain_table_p + i)->gain;
+ wm8994_write(codec, (default_gain_table_p + i)->reg, val);
+ }
+ }
+
+ if (wm8994->gain_code) {
+ gain_set_bits &= ~(COMMON_SET_BIT);
+
+ switch (wm8994->gain_code) {
+ case 1:
+ gain_set_bits |= (mode | GAIN_DIVISION_BIT_1);
+ break;
+ case 2:
+ gain_set_bits |= (mode | GAIN_DIVISION_BIT_2);
+ break;
+ case 3:
+ /* eur and eur tft device are same gain values currently
+ * but gain code is different because of modem.
+ */
+ gain_set_bits |= (mode | GAIN_DIVISION_BIT_1);
+ break;
+ default:
+ DEBUG_LOG_ERR("gain_code(%d) isn't support", wm8994->gain_code);
+ return 0;
+ }
+
+ default_gain_table_p = gain_code_table;
+ table_num = GAIN_CODE_NUM;
+
+ for (i = 0; i < table_num; i++) {
+ if ((default_gain_table_p + i)->mode == gain_set_bits) {
+ val = wm8994_read(codec, (default_gain_table_p + i)->reg);
+ val &= ~((default_gain_table_p + i)->mask);
+ val |= (default_gain_table_p + i)->gain;
+ wm8994_write(codec, (default_gain_table_p + i)->reg, val);
+ }
+ }
+
+ }
+ return 0;
+
+}
+
diff --git a/sound/soc/codecs/wm8994_samsung.c b/sound/soc/codecs/wm8994_samsung.c
new file mode 100755
index 0000000..4b646e0
--- /dev/null
+++ b/sound/soc/codecs/wm8994_samsung.c
@@ -0,0 +1,3219 @@
+/*
+ * wm8994_samsung.c -- WM8994 ALSA Soc Audio driver
+ *
+ * Copyright 2010 Wolfson Microelectronics PLC.
+ *
+ * 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.
+ *
+ * Notes:
+ * The WM8994 is a multichannel codec with S/PDIF support, featuring six
+ * DAC channels and two ADC channels.
+ *
+ * Currently only the primary audio interface is supported - S/PDIF and
+ * the secondary audio interfaces are not.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+#include <sound/initval.h>
+#include <asm/div64.h>
+#include <linux/io.h>
+#include <plat/map-base.h>
+#include <linux/gpio.h>
+#include <plat/gpio-cfg.h>
+#include <mach/regs-clock.h>
+#include "wm8994_samsung.h"
+#include "../../../arch/arm/mach-s5pv210/herring.h"
+#ifdef CONFIG_SND_VOODOO
+#include "wm8994_voodoo.h"
+#endif
+
+#define WM8994_VERSION "0.1"
+#define SUBJECT "wm8994_samsung.c"
+
+#if defined(CONFIG_VIDEO_TV20) && defined(CONFIG_SND_S5P_WM8994_MASTER)
+#define HDMI_USE_AUDIO
+#endif
+
+//extern const u16 wm8994_reg_defaults[WM8994_CACHE_SIZE];
+
+/*
+ *Definitions of clock related.
+*/
+
+static struct {
+ int ratio;
+ int clk_sys_rate;
+} clk_sys_rates[] = {
+ { 64, 0 },
+ { 128, 1 },
+ { 192, 2 },
+ { 256, 3 },
+ { 384, 4 },
+ { 512, 5 },
+ { 768, 6 },
+ { 1024, 7 },
+ { 1408, 8 },
+ { 1536, 9 },
+};
+
+static struct {
+ int rate;
+ int sample_rate;
+} sample_rates[] = {
+ { 8000, 0 },
+ { 11025, 1 },
+ { 12000, 2 },
+ { 16000, 3 },
+ { 22050, 4 },
+ { 24000, 5 },
+ { 32000, 6 },
+ { 44100, 7 },
+ { 48000, 8 },
+ { 88200, 9 },
+ { 96000, 10 },
+};
+
+static struct {
+ int div;
+ int bclk_div;
+} bclk_divs[] = {
+ { 1, 0 },
+ { 2, 1 },
+ { 4, 2 },
+ { 6, 3 },
+ { 8, 4 },
+ { 12, 5 },
+ { 16, 6 },
+ { 24, 7 },
+ { 32, 8 },
+ { 48, 9 },
+};
+
+//struct snd_soc_dai wm8994_dai;
+//EXPORT_SYMBOL_GPL(wm8994_dai);
+
+//struct snd_soc_codec_device soc_codec_dev_pcm_wm8994;
+//EXPORT_SYMBOL_GPL(soc_codec_dev_pcm_wm8994);
+
+//struct snd_soc_codec_device soc_codec_dev_wm8994;
+//EXPORT_SYMBOL_GPL(soc_codec_dev_wm8994);
+
+/*
+ * Definitions of sound path
+ */
+select_route universal_wm8994_playback_paths[] = {
+ wm8994_disable_path, wm8994_set_playback_receiver,
+ wm8994_set_playback_speaker, wm8994_set_playback_headset,
+ wm8994_set_playback_headset, wm8994_set_playback_bluetooth,
+ wm8994_set_playback_speaker_headset
+};
+
+select_route universal_wm8994_voicecall_paths[] = {
+ wm8994_disable_path, wm8994_set_voicecall_receiver,
+ wm8994_set_voicecall_speaker, wm8994_set_voicecall_headset,
+ wm8994_set_voicecall_headphone, wm8994_set_voicecall_bluetooth,
+ wm8994_set_voicecall_tty_vco, wm8994_set_voicecall_tty_hco,
+ wm8994_set_voicecall_tty_full,
+};
+
+select_mic_route universal_wm8994_mic_paths[] = {
+ wm8994_record_main_mic,
+ wm8994_record_headset_mic,
+ wm8994_record_bluetooth,
+};
+
+select_clock_control universal_clock_controls = wm8994_configure_clock;
+
+int gain_code;
+
+/*
+ * Implementation of I2C functions
+ */
+static unsigned int wm8994_read_hw(struct snd_soc_codec *codec, u16 reg)
+{
+ struct i2c_msg xfer[2];
+ u16 data;
+ int ret;
+ struct i2c_client *i2c = codec->control_data;
+
+ data = ((reg & 0xff00) >> 8) | ((reg & 0xff) << 8);
+
+ xfer[0].addr = i2c->addr;
+ xfer[0].flags = 0;
+ xfer[0].len = 2;
+ xfer[0].buf = (void *)&data;
+
+ xfer[1].addr = i2c->addr;
+ xfer[1].flags = I2C_M_RD;
+ xfer[1].len = 2;
+ xfer[1].buf = (u8 *)&data;
+ ret = i2c_transfer(i2c->adapter, xfer, 2);
+ if (ret != 2) {
+ dev_err(codec->dev, "Failed to read 0x%x: %d\n", reg, ret);
+ return 0;
+ }
+
+ return (data >> 8) | ((data & 0xff) << 8);
+}
+
+int wm8994_write(struct snd_soc_codec *codec, unsigned int reg,
+ unsigned int value)
+{
+ u8 data[4];
+ int ret;
+
+#ifdef CONFIG_SND_VOODOO
+ value = voodoo_hook_wm8994_write(codec, reg, value);
+#endif
+
+ /* data is
+ * D15..D9 WM8993 register offset
+ * D8...D0 register data
+ */
+ data[0] = (reg & 0xff00) >> 8;
+ data[1] = reg & 0x00ff;
+ data[2] = value >> 8;
+ data[3] = value & 0x00ff;
+ ret = codec->hw_write(codec->control_data, data, 4);
+
+ if (ret == 4)
+ return 0;
+ else {
+ pr_err("i2c write problem occured\n");
+ return ret;
+ }
+}
+
+unsigned int wm8994_read(struct snd_soc_codec *codec, unsigned int reg)
+{
+ return wm8994_read_hw(codec, reg);
+}
+
+static int wm8994_ldo_control(struct wm8994_platform_data *pdata, int en)
+{
+
+ if (!pdata) {
+ pr_err("failed to control wm8994 ldo\n");
+ return -EINVAL;
+ }
+
+ gpio_set_value(pdata->ldo, en);
+
+ if (en)
+ msleep(10);
+ else
+ msleep(125);
+
+ return 0;
+
+}
+
+/*
+ * Functions related volume.
+ */
+static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
+
+static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ret;
+ u16 val;
+
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ int reg = mc->reg;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+ DEBUG_LOG("");
+
+ ret = snd_soc_put_volsw_2r(kcontrol, ucontrol);
+ if (ret < 0)
+ return ret;
+
+ /* Volume changes in the headphone path mean we need to
+ * recallibrate DC servo */
+ if (strcmp(kcontrol->id.name, "Playback Spkr Volume") == 0 ||
+ strcmp(kcontrol->id.name, "Playback Volume") == 0)
+ memset(wm8994->dc_servo, 0, sizeof(wm8994->dc_servo));
+
+ val = wm8994_read(codec, reg);
+
+ return wm8994_write(codec, reg, val | 0x0100);
+}
+
+static int wm899x_inpga_put_volsw_vu(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ int reg = mc->reg;
+ int ret;
+ u16 val;
+
+ ret = snd_soc_put_volsw(kcontrol, ucontrol);
+
+ if (ret < 0)
+ return ret;
+
+ val = wm8994_read(codec, reg);
+
+ return wm8994_write(codec, reg, val | 0x0100);
+
+}
+
+/*
+ * Implementation of sound path
+ */
+#define MAX_PLAYBACK_PATHS 10
+#define MAX_VOICECALL_PATH 8
+static const char *playback_path[] = {
+ "OFF", "RCV", "SPK", "HP", "HP_NO_MIC", "BT", "SPK_HP",
+ "RING_SPK", "RING_HP", "RING_NO_MIC", "RING_SPK_HP"
+};
+static const char *voicecall_path[] = { "OFF", "RCV", "SPK", "HP",
+ "HP_NO_MIC", "BT", "TTY_VCO",
+ "TTY_HCO", "TTY_FULL"};
+static const char *mic_path[] = { "Main Mic", "Hands Free Mic",
+ "BT Sco Mic", "MIC OFF" };
+static const char *input_source_state[] = { "Default", "Voice Recognition",
+ "Camcorder", "Voice Communication"};
+
+static int wm8994_get_mic_path(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+ ucontrol->value.integer.value[0] = wm8994->rec_path;
+
+ return 0;
+}
+
+static int wm8994_set_mic_path(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+ DEBUG_LOG("");
+
+ wm8994->codec_state |= CAPTURE_ACTIVE;
+
+ switch (ucontrol->value.integer.value[0]) {
+ case 0:
+ wm8994->rec_path = MAIN;
+ break;
+ case 1:
+ wm8994->rec_path = SUB;
+ break;
+ case 2:
+ wm8994->rec_path = BT_REC;
+ break;
+ case 3:
+ wm8994_disable_rec_path(codec);
+ return 0;
+ default:
+ return -EINVAL;
+ }
+
+ wm8994->universal_mic_path[wm8994->rec_path] (codec);
+
+ return 0;
+}
+
+static int wm8994_get_path(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+ ucontrol->value.integer.value[0] = wm8994->cur_path;
+
+ return 0;
+}
+
+static int wm8994_set_path(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+ struct soc_enum *mc = (struct soc_enum *)kcontrol->private_value;
+ int val;
+ int path_num = ucontrol->value.integer.value[0];
+
+ if (strcmp(mc->texts[path_num], playback_path[path_num])) {
+ DEBUG_LOG_ERR("Unknown path %s\n", mc->texts[path_num]);
+ return -ENODEV;
+ }
+
+ if (path_num > MAX_PLAYBACK_PATHS) {
+ DEBUG_LOG_ERR("Unknown Path\n");
+ return -ENODEV;
+ }
+
+ switch (path_num) {
+ case OFF:
+ DEBUG_LOG("Switching off output path\n");
+ break;
+ case RCV:
+ case SPK:
+ case HP:
+ case HP_NO_MIC:
+ case BT:
+ case SPK_HP:
+ DEBUG_LOG("routing to %s\n", mc->texts[path_num]);
+ wm8994->ringtone_active = RING_OFF;
+ break;
+ case RING_SPK:
+ case RING_HP:
+ case RING_NO_MIC:
+ DEBUG_LOG("routing to %s\n", mc->texts[path_num]);
+ wm8994->ringtone_active = RING_ON;
+ path_num -= 5;
+ break;
+ case RING_SPK_HP:
+ DEBUG_LOG("routing to %s\n", mc->texts[path_num]);
+ wm8994->ringtone_active = RING_ON;
+ path_num -= 4;
+ break;
+ default:
+ DEBUG_LOG_ERR("audio path[%d] does not exists!!\n", path_num);
+ return -ENODEV;
+ break;
+ }
+
+ wm8994->codec_state |= PLAYBACK_ACTIVE;
+
+ if (wm8994->codec_state & CALL_ACTIVE) {
+ wm8994->codec_state &= ~(CALL_ACTIVE);
+
+ val = wm8994_read(codec, WM8994_CLOCKING_1);
+ val &= ~(WM8994_DSP_FS2CLK_ENA_MASK | WM8994_SYSCLK_SRC_MASK);
+ wm8994_write(codec, WM8994_CLOCKING_1, val);
+ }
+
+ wm8994->cur_path = path_num;
+ wm8994->universal_playback_path[wm8994->cur_path] (codec);
+
+ return 0;
+}
+
+static int wm8994_get_voice_path(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+ ucontrol->value.integer.value[0] = wm8994->cur_path;
+
+ return 0;
+}
+
+static int wm8994_set_voice_path(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+ struct soc_enum *mc = (struct soc_enum *)kcontrol->private_value;
+
+ int path_num = ucontrol->value.integer.value[0];
+
+ if (strcmp(mc->texts[path_num], voicecall_path[path_num])) {
+ DEBUG_LOG_ERR("Unknown path %s\n", mc->texts[path_num]);
+ return -ENODEV;
+ }
+
+ switch (path_num) {
+ case CALL_OFF:
+ DEBUG_LOG("Switching off output path\n");
+ break;
+ case CALL_RCV:
+ case CALL_SPK:
+ case CALL_HP:
+ case CALL_HP_NO_MIC:
+ case CALL_BT:
+ case CALL_TTY_VCO:
+ case CALL_TTY_HCO:
+ case CALL_TTY_FULL:
+ DEBUG_LOG("routing voice path to %s\n", mc->texts[path_num]);
+ break;
+ default:
+ DEBUG_LOG_ERR("path[%d] does not exists!\n", path_num);
+ return -ENODEV;
+ break;
+ }
+
+ if (wm8994->cur_path != path_num ||
+ !(wm8994->codec_state & CALL_ACTIVE)) {
+ wm8994->codec_state |= CALL_ACTIVE;
+ wm8994->cur_path = path_num;
+ wm8994->universal_voicecall_path[wm8994->cur_path] (codec);
+ } else {
+ int val;
+ val = wm8994_read(codec, WM8994_AIF1_DAC1_FILTERS_1);
+ val &= ~(WM8994_AIF1DAC1_MUTE_MASK);
+ val |= (WM8994_AIF1DAC1_UNMUTE);
+ wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, val);
+ }
+
+ return 0;
+}
+
+static int wm8994_get_input_source(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+ DEBUG_LOG("input_source_state = [%d]", wm8994->input_source);
+
+ return wm8994->input_source;
+}
+
+static int wm8994_set_input_source(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+ int control_flag = ucontrol->value.integer.value[0];
+
+ DEBUG_LOG("Changed input_source state [%d] => [%d]",
+ wm8994->input_source, control_flag);
+
+ wm8994->input_source = control_flag;
+
+ return 0;
+}
+
+#define SOC_WM899X_OUTPGA_DOUBLE_R_TLV(xname, reg_left, reg_right,\
+ xshift, xmax, xinvert, tlv_array) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
+ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
+ SNDRV_CTL_ELEM_ACCESS_READWRITE,\
+ .tlv.p = (tlv_array), \
+ .info = snd_soc_info_volsw_2r, \
+ .get = snd_soc_get_volsw_2r, .put = wm899x_outpga_put_volsw_vu, \
+ .private_value = (unsigned long)&(struct soc_mixer_control) \
+ {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
+ .max = xmax, .invert = xinvert} }
+
+#define SOC_WM899X_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert,\
+ tlv_array) {\
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
+ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
+ SNDRV_CTL_ELEM_ACCESS_READWRITE,\
+ .tlv.p = (tlv_array), \
+ .info = snd_soc_info_volsw, \
+ .get = snd_soc_get_volsw, .put = wm899x_inpga_put_volsw_vu, \
+ .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
+
+static const DECLARE_TLV_DB_SCALE(digital_tlv, -7162, 37, 1);
+static const DECLARE_TLV_DB_LINEAR(digital_tlv_spkr, -5700, 600);
+static const DECLARE_TLV_DB_LINEAR(digital_tlv_rcv, -5700, 600);
+static const DECLARE_TLV_DB_LINEAR(digital_tlv_headphone, -5700, 600);
+static const DECLARE_TLV_DB_LINEAR(digital_tlv_mic, -7162, 7162);
+
+static const struct soc_enum path_control_enum[] = {
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(playback_path), playback_path),
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(voicecall_path), voicecall_path),
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mic_path), mic_path),
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(input_source_state), input_source_state),
+};
+
+static const struct snd_kcontrol_new wm8994_snd_controls[] = {
+ SOC_WM899X_OUTPGA_DOUBLE_R_TLV("Playback Volume",
+ WM8994_LEFT_OPGA_VOLUME,
+ WM8994_RIGHT_OPGA_VOLUME, 0, 0x3F, 0,
+ digital_tlv_rcv),
+ SOC_WM899X_OUTPGA_DOUBLE_R_TLV("Playback Spkr Volume",
+ WM8994_SPEAKER_VOLUME_LEFT,
+ WM8994_SPEAKER_VOLUME_RIGHT, 1, 0x3F, 0,
+ digital_tlv_spkr),
+ SOC_WM899X_OUTPGA_DOUBLE_R_TLV("Playback Headset Volume",
+ WM8994_LEFT_OUTPUT_VOLUME,
+ WM8994_RIGHT_OUTPUT_VOLUME, 1, 0x3F, 0,
+ digital_tlv_headphone),
+ SOC_WM899X_OUTPGA_SINGLE_R_TLV("Capture Volume",
+ WM8994_AIF1_ADC1_LEFT_VOLUME,
+ 0, 0xEF, 0, digital_tlv_mic),
+ /* Path Control */
+ SOC_ENUM_EXT("Playback Path", path_control_enum[0],
+ wm8994_get_path, wm8994_set_path),
+
+ SOC_ENUM_EXT("Voice Call Path", path_control_enum[1],
+ wm8994_get_voice_path, wm8994_set_voice_path),
+
+ SOC_ENUM_EXT("Capture MIC Path", path_control_enum[2],
+ wm8994_get_mic_path, wm8994_set_mic_path),
+
+#if defined USE_INFINIEON_EC_FOR_VT
+ SOC_ENUM_EXT("Clock Control", clock_control_enum[0],
+ s3c_pcmdev_get_clock, s3c_pcmdev_set_clock),
+#endif
+ SOC_ENUM_EXT("Input Source", path_control_enum[3],
+ wm8994_get_input_source, wm8994_set_input_source),
+
+};
+
+/* Add non-DAPM controls */
+static int wm8994_add_controls(struct snd_soc_codec *codec)
+{
+ return snd_soc_add_controls(codec, wm8994_snd_controls,
+ ARRAY_SIZE(wm8994_snd_controls));
+}
+static const struct snd_soc_dapm_widget wm8994_dapm_widgets[] = {
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+};
+
+static int wm8994_add_widgets(struct snd_soc_codec *codec)
+{
+ snd_soc_dapm_new_controls(&codec->dapm, wm8994_dapm_widgets,
+ ARRAY_SIZE(wm8994_dapm_widgets));
+
+ snd_soc_dapm_add_routes(&codec->dapm, audio_map, ARRAY_SIZE(audio_map));
+
+ snd_soc_dapm_new_widgets(&codec->dapm);
+ return 0;
+}
+
+static int configure_clock(struct snd_soc_codec *codec)
+{
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+ unsigned int reg;
+
+ DEBUG_LOG("");
+
+ if (wm8994->codec_state != DEACTIVE) {
+ DEBUG_LOG("Codec is already actvied. Skip clock setting.");
+ return 0;
+ }
+
+ reg = wm8994_read(codec, WM8994_AIF1_CLOCKING_1);
+ reg &= ~WM8994_AIF1CLK_ENA;
+ reg &= ~WM8994_AIF1CLK_SRC_MASK;
+ wm8994_write(codec, WM8994_AIF1_CLOCKING_1, reg);
+
+ switch (wm8994->sysclk_source) {
+ case WM8994_SYSCLK_MCLK:
+ dev_dbg(codec->dev, "Using %dHz MCLK\n", wm8994->mclk_rate);
+
+ reg = wm8994_read(codec, WM8994_AIF1_CLOCKING_1);
+ reg &= ~WM8994_AIF1CLK_ENA;
+ wm8994_write(codec, WM8994_AIF1_CLOCKING_1, reg);
+
+ reg = wm8994_read(codec, WM8994_AIF1_CLOCKING_1);
+ reg &= 0x07;
+
+ if (wm8994->mclk_rate > 13500000) {
+ reg |= WM8994_AIF1CLK_DIV;
+ wm8994->sysclk_rate = wm8994->mclk_rate / 2;
+ } else {
+ reg &= ~WM8994_AIF1CLK_DIV;
+ wm8994->sysclk_rate = wm8994->mclk_rate;
+ }
+ reg |= WM8994_AIF1CLK_ENA;
+ wm8994_write(codec, WM8994_AIF1_CLOCKING_1, reg);
+
+ /* Enable clocks to the Audio core and sysclk of wm8994 */
+ reg = wm8994_read(codec, WM8994_CLOCKING_1);
+ reg &= ~(WM8994_SYSCLK_SRC_MASK | WM8994_DSP_FSINTCLK_ENA_MASK
+ | WM8994_DSP_FS1CLK_ENA_MASK);
+ reg |= (WM8994_DSP_FS1CLK_ENA | WM8994_DSP_FSINTCLK_ENA);
+ wm8994_write(codec, WM8994_CLOCKING_1, reg);
+ break;
+
+ case WM8994_SYSCLK_FLL:
+ switch (wm8994->fs) {
+ case 8000:
+ wm8994_write(codec, WM8994_FLL1_CONTROL_2, 0x2F00);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_3, 0x3126);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_4, 0x0100);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_5, 0x0C88);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_1,
+ WM8994_FLL1_FRACN_ENA | WM8994_FLL1_ENA);
+ break;
+
+ case 11025:
+ wm8994_write(codec, WM8994_FLL1_CONTROL_2, 0x1F00);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_3, 0x86C2);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_5, 0x0C88);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_4, 0x00e0);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_1,
+ WM8994_FLL1_FRACN_ENA | WM8994_FLL1_ENA);
+ break;
+
+ case 12000:
+ wm8994_write(codec, WM8994_FLL1_CONTROL_2, 0x1F00);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_3, 0x3126);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_5, 0x0C88);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_4, 0x0100);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_1,
+ WM8994_FLL1_FRACN_ENA | WM8994_FLL1_ENA);
+ break;
+
+ case 16000:
+ wm8994_write(codec, WM8994_FLL1_CONTROL_2, 0x1900);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_3, 0xE23E);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_5, 0x0C88);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_4, 0x0100);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_1,
+ WM8994_FLL1_FRACN_ENA | WM8994_FLL1_ENA);
+ break;
+
+ case 22050:
+ wm8994_write(codec, WM8994_FLL1_CONTROL_2, 0x0F00);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_3, 0x86C2);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_5, 0x0C88);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_4, 0x00E0);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_1,
+ WM8994_FLL1_FRACN_ENA | WM8994_FLL1_ENA);
+ break;
+
+ case 24000:
+ wm8994_write(codec, WM8994_FLL1_CONTROL_2, 0x0F00);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_3, 0x3126);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_5, 0x0C88);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_4, 0x0100);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_1,
+ WM8994_FLL1_FRACN_ENA | WM8994_FLL1_ENA);
+ break;
+
+ case 32000:
+ wm8994_write(codec, WM8994_FLL1_CONTROL_2, 0x0C00);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_3, 0xE23E);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_5, 0x0C88);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_4, 0x0100);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_1,
+ WM8994_FLL1_FRACN_ENA | WM8994_FLL1_ENA);
+ break;
+
+ case 44100:
+ wm8994_write(codec, WM8994_FLL1_CONTROL_2, 0x0700);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_3, 0x86C2);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_5, 0x0C88);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_4, 0x00E0);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_1,
+ WM8994_FLL1_FRACN_ENA | WM8994_FLL1_ENA);
+ break;
+
+ case 48000:
+ wm8994_write(codec, WM8994_FLL1_CONTROL_2, 0x0700);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_3, 0x3126);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_5, 0x0C88);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_4, 0x0100);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_1,
+ WM8994_FLL1_FRACN_ENA | WM8994_FLL1_ENA);
+ break;
+
+ default:
+ DEBUG_LOG_ERR("Unsupported Frequency\n");
+ break;
+ }
+
+ reg = wm8994_read(codec, WM8994_AIF1_CLOCKING_1);
+ reg |= WM8994_AIF1CLK_ENA;
+ reg |= WM8994_AIF1CLK_SRC_FLL1;
+ wm8994_write(codec, WM8994_AIF1_CLOCKING_1, reg);
+
+ /* Enable clocks to the Audio core and sysclk of wm8994*/
+ reg = wm8994_read(codec, WM8994_CLOCKING_1);
+ reg &= ~(WM8994_SYSCLK_SRC_MASK | WM8994_DSP_FSINTCLK_ENA_MASK |
+ WM8994_DSP_FS1CLK_ENA_MASK);
+ reg |= (WM8994_DSP_FS1CLK_ENA | WM8994_DSP_FSINTCLK_ENA);
+ wm8994_write(codec, WM8994_CLOCKING_1, reg);
+ break;
+
+ default:
+ dev_err(codec->dev, "System clock not configured\n");
+ return -EINVAL;
+ }
+
+ dev_dbg(codec->dev, "CLK_SYS is %dHz\n", wm8994->sysclk_rate);
+
+ return 0;
+}
+
+static int wm8994_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ DEBUG_LOG("");
+
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ case SND_SOC_BIAS_PREPARE:
+ /* VMID=2*40k */
+ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
+ WM8994_VMID_SEL_MASK, 0x2);
+ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_2,
+ WM8994_TSHUT_ENA, WM8994_TSHUT_ENA);
+ break;
+
+ case SND_SOC_BIAS_STANDBY:
+ if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+ /* Bring up VMID with fast soft start */
+ snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+ WM8994_STARTUP_BIAS_ENA |
+ WM8994_VMID_BUF_ENA |
+ WM8994_VMID_RAMP_MASK |
+ WM8994_BIAS_SRC,
+ WM8994_STARTUP_BIAS_ENA |
+ WM8994_VMID_BUF_ENA |
+ WM8994_VMID_RAMP_MASK |
+ WM8994_BIAS_SRC);
+ /* VMID=2*40k */
+ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
+ WM8994_VMID_SEL_MASK |
+ WM8994_BIAS_ENA,
+ WM8994_BIAS_ENA | 0x2);
+
+ /* Switch to normal bias */
+ snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+ WM8994_BIAS_SRC |
+ WM8994_STARTUP_BIAS_ENA, 0);
+ }
+
+ /* VMID=2*240k */
+ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
+ WM8994_VMID_SEL_MASK, 0x4);
+
+ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_2,
+ WM8994_TSHUT_ENA, 0);
+ break;
+
+ case SND_SOC_BIAS_OFF:
+ snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
+ WM8994_LINEOUT_VMID_BUF_ENA, 0);
+
+ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
+ WM8994_VMID_SEL_MASK | WM8994_BIAS_ENA, 0);
+ break;
+ }
+
+ codec->dapm.bias_level = level;
+
+ return 0;
+}
+
+static int wm8994_set_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+ DEBUG_LOG("clk_id =%d ", clk_id);
+
+ switch (clk_id) {
+ case WM8994_SYSCLK_MCLK:
+ wm8994->mclk_rate = freq;
+ wm8994->sysclk_source = clk_id;
+ break;
+ case WM8994_SYSCLK_FLL:
+ wm8994->sysclk_rate = freq;
+ wm8994->sysclk_source = clk_id;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+ unsigned int aif1 = wm8994_read(codec, WM8994_AIF1_CONTROL_1);
+ unsigned int aif2 = wm8994_read(codec, WM8994_AIF1_MASTER_SLAVE);
+
+ DEBUG_LOG("");
+
+ aif1 &= ~(WM8994_AIF1_LRCLK_INV | WM8994_AIF1_BCLK_INV |
+ WM8994_AIF1_WL_MASK | WM8994_AIF1_FMT_MASK);
+
+ aif2 &= ~(WM8994_AIF1_LRCLK_FRC_MASK |
+ WM8994_AIF1_CLK_FRC | WM8994_AIF1_MSTR);
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBS_CFS:
+ wm8994->master = 0;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFM:
+ aif2 |= (WM8994_AIF1_MSTR | WM8994_AIF1_LRCLK_FRC);
+ wm8994->master = 1;
+ break;
+ case SND_SOC_DAIFMT_CBM_CFS:
+ aif2 |= (WM8994_AIF1_MSTR | WM8994_AIF1_CLK_FRC);
+ wm8994->master = 1;
+ break;
+ case SND_SOC_DAIFMT_CBM_CFM:
+ aif2 |= (WM8994_AIF1_MSTR | WM8994_AIF1_CLK_FRC |
+ WM8994_AIF1_LRCLK_FRC);
+ wm8994->master = 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_DSP_B:
+ aif1 |= WM8994_AIF1_LRCLK_INV;
+ case SND_SOC_DAIFMT_DSP_A:
+ aif1 |= 0x18;
+ break;
+ case SND_SOC_DAIFMT_I2S:
+ aif1 |= 0x10;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ aif1 |= 0x8;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_DSP_A:
+ case SND_SOC_DAIFMT_DSP_B:
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ aif1 |= WM8994_AIF1_BCLK_INV;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+
+ case SND_SOC_DAIFMT_I2S:
+ case SND_SOC_DAIFMT_RIGHT_J:
+ case SND_SOC_DAIFMT_LEFT_J:
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ aif1 |= WM8994_AIF1_BCLK_INV | WM8994_AIF1_LRCLK_INV;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ aif1 |= WM8994_AIF1_BCLK_INV;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ aif1 |= WM8994_AIF1_LRCLK_INV;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ aif1 |= 0x4000;
+ wm8994_write(codec, WM8994_AIF1_CONTROL_1, aif1);
+ wm8994_write(codec, WM8994_AIF1_MASTER_SLAVE, aif2);
+ wm8994_write(codec, WM8994_AIF1_CONTROL_2, 0x4000);
+
+ return 0;
+}
+
+static int wm8994_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+ int ret, i, best, best_val, cur_val;
+ unsigned int clocking1, clocking3, aif1, aif4, aif5;
+
+ DEBUG_LOG("");
+
+ clocking1 = wm8994_read(codec, WM8994_AIF1_BCLK);
+ clocking1 &= ~WM8994_AIF1_BCLK_DIV_MASK;
+
+ clocking3 = wm8994_read(codec, WM8994_AIF1_RATE);
+ clocking3 &= ~(WM8994_AIF1_SR_MASK | WM8994_AIF1CLK_RATE_MASK);
+
+ aif1 = wm8994_read(codec, WM8994_AIF1_CONTROL_1);
+ aif1 &= ~WM8994_AIF1_WL_MASK;
+ aif4 = wm8994_read(codec, WM8994_AIF1ADC_LRCLK);
+ aif4 &= ~WM8994_AIF1ADC_LRCLK_DIR;
+ aif5 = wm8994_read(codec, WM8994_AIF1DAC_LRCLK);
+ aif5 &= ~WM8994_AIF1DAC_LRCLK_DIR_MASK;
+
+ wm8994->fs = params_rate(params);
+ wm8994->bclk = 2 * wm8994->fs;
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ wm8994->bclk *= 16;
+ break;
+
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ wm8994->bclk *= 20;
+ aif1 |= (0x01 << WM8994_AIF1_WL_SHIFT);
+ break;
+
+ case SNDRV_PCM_FORMAT_S24_LE:
+ wm8994->bclk *= 24;
+ aif1 |= (0x10 << WM8994_AIF1_WL_SHIFT);
+ break;
+
+ case SNDRV_PCM_FORMAT_S32_LE:
+ wm8994->bclk *= 32;
+ aif1 |= (0x11 << WM8994_AIF1_WL_SHIFT);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ ret = configure_clock(codec);
+ if (ret != 0)
+ return ret;
+
+ dev_dbg(codec->dev, "Target BCLK is %dHz\n", wm8994->bclk);
+
+ /* Select nearest CLK_SYS_RATE */
+ if (wm8994->fs == 8000)
+ best = 3;
+ else {
+ best = 0;
+ best_val = abs((wm8994->sysclk_rate / clk_sys_rates[0].ratio)
+ - wm8994->fs);
+
+ for (i = 1; i < ARRAY_SIZE(clk_sys_rates); i++) {
+ cur_val = abs((wm8994->sysclk_rate /
+ clk_sys_rates[i].ratio) - wm8994->fs);
+
+ if (cur_val < best_val) {
+ best = i;
+ best_val = cur_val;
+ }
+ }
+ dev_dbg(codec->dev, "Selected CLK_SYS_RATIO of %d\n",
+ clk_sys_rates[best].ratio);
+ }
+
+ clocking3 |= (clk_sys_rates[best].clk_sys_rate
+ << WM8994_AIF1CLK_RATE_SHIFT);
+
+ /* Sampling rate */
+ best = 0;
+ best_val = abs(wm8994->fs - sample_rates[0].rate);
+ for (i = 1; i < ARRAY_SIZE(sample_rates); i++) {
+ cur_val = abs(wm8994->fs - sample_rates[i].rate);
+ if (cur_val < best_val) {
+ best = i;
+ best_val = cur_val;
+ }
+ }
+ dev_dbg(codec->dev, "Selected SAMPLE_RATE of %dHz\n",
+ sample_rates[best].rate);
+
+ clocking3 |= (sample_rates[best].sample_rate << WM8994_AIF1_SR_SHIFT);
+
+ /* BCLK_DIV */
+ best = 0;
+ best_val = INT_MAX;
+ for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) {
+ cur_val = ((wm8994->sysclk_rate) / bclk_divs[i].div)
+ - wm8994->bclk;
+ if (cur_val < 0)
+ break;
+ if (cur_val < best_val) {
+ best = i;
+ best_val = cur_val;
+ }
+ }
+ wm8994->bclk = (wm8994->sysclk_rate) / bclk_divs[best].div;
+
+ dev_dbg(codec->dev, "Selected BCLK_DIV of %d for %dHz BCLK\n",
+ bclk_divs[best].div, wm8994->bclk);
+
+ clocking1 |= bclk_divs[best].bclk_div << WM8994_AIF1_BCLK_DIV_SHIFT;
+
+ /* LRCLK is a simple fraction of BCLK */
+ dev_dbg(codec->dev, "LRCLK_RATE is %d\n", wm8994->bclk / wm8994->fs);
+
+ aif4 |= wm8994->bclk / wm8994->fs;
+ aif5 |= wm8994->bclk / wm8994->fs;
+
+#ifdef HDMI_USE_AUDIO
+ /* set bclk to 32fs for 44.1kHz 16 bit playback.*/
+ if (wm8994->fs == 44100)
+ wm8994_write(codec, WM8994_AIF1_BCLK, 0x70);
+#endif
+
+ wm8994_write(codec, WM8994_AIF1_RATE, clocking3);
+ wm8994_write(codec, WM8994_AIF1_CONTROL_1, aif1);
+
+ return 0;
+}
+
+static int wm8994_digital_mute(struct snd_soc_dai *codec_dai, int mute)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ int mute_reg;
+ int reg;
+
+ switch (codec_dai->id) {
+ case 1:
+ mute_reg = WM8994_AIF1_DAC1_FILTERS_1;
+ break;
+ case 2:
+ mute_reg = WM8994_AIF2_DAC_FILTERS_1;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (mute)
+ reg = WM8994_AIF1DAC1_MUTE;
+ else
+ reg = 0;
+
+ snd_soc_update_bits(codec, mute_reg, WM8994_AIF1DAC1_MUTE, reg);
+
+ return 0;
+}
+
+static int wm8994_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *codec_dai)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ wm8994->stream_state |= PCM_STREAM_PLAYBACK;
+ else
+ wm8994->stream_state |= PCM_STREAM_CAPTURE;
+
+
+ if (wm8994->power_state == CODEC_OFF) {
+ wm8994->power_state = CODEC_ON;
+ DEBUG_LOG("Turn on codec!! Power state =[%d]",
+ wm8994->power_state);
+
+ /* For initialize codec */
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_1,
+ 0x3 << WM8994_VMID_SEL_SHIFT | WM8994_BIAS_ENA);
+ msleep(50);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_1,
+ WM8994_VMID_SEL_NORMAL | WM8994_BIAS_ENA);
+ wm8994_write(codec, WM8994_OVERSAMPLING, 0x0000);
+ } else
+ DEBUG_LOG("Already turned on codec!!");
+
+ return 0;
+}
+
+static void wm8994_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *codec_dai)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+ DEBUG_LOG("Stream_state = [0x%X], Codec State = [0x%X]",
+ wm8994->stream_state, wm8994->codec_state);
+
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+ wm8994->stream_state &= ~(PCM_STREAM_CAPTURE);
+ wm8994->codec_state &= ~(CAPTURE_ACTIVE);
+ } else {
+ wm8994->codec_state &= ~(PLAYBACK_ACTIVE);
+ wm8994->stream_state &= ~(PCM_STREAM_PLAYBACK);
+ }
+
+ if ((wm8994->codec_state == DEACTIVE) &&
+ (wm8994->stream_state == PCM_STREAM_DEACTIVE)) {
+ DEBUG_LOG("Turn off Codec!!");
+ wm8994->pdata->set_mic_bias(false);
+ wm8994->power_state = CODEC_OFF;
+ wm8994->cur_path = OFF;
+ wm8994->rec_path = MIC_OFF;
+ wm8994->ringtone_active = RING_OFF;
+ wm8994_write(codec, WM8994_SOFTWARE_RESET, 0x0000);
+ return;
+ }
+
+ DEBUG_LOG("Preserve codec state = [0x%X], Stream State = [0x%X]",
+ wm8994->codec_state, wm8994->stream_state);
+
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+ wm8994_disable_rec_path(codec);
+ wm8994->codec_state &= ~(CAPTURE_ACTIVE);
+ } else {
+ if (wm8994->codec_state & CALL_ACTIVE) {
+ int val;
+
+ val = wm8994_read(codec, WM8994_AIF1_DAC1_FILTERS_1);
+ val &= ~(WM8994_AIF1DAC1_MUTE_MASK);
+ val |= (WM8994_AIF1DAC1_MUTE);
+ wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, val);
+ } else
+ wm8994_disable_path(codec);
+ }
+}
+
+//static struct snd_soc_device *wm8994_socdev;
+static struct snd_soc_codec *wm8994_codec;
+
+#define WM8994_RATES SNDRV_PCM_RATE_44100
+#define WM8994_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+static struct snd_soc_dai_ops wm8994_ops = {
+ .startup = wm8994_startup,
+ .shutdown = wm8994_shutdown,
+ .set_sysclk = wm8994_set_sysclk,
+ .set_fmt = wm8994_set_dai_fmt,
+ .hw_params = wm8994_hw_params,
+ .digital_mute = NULL,
+};
+
+struct snd_soc_dai_driver wm8994_dai[] = {
+ {
+ .name = "WM8994 PAIFRX",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 6,
+ .rates = WM8994_RATES,
+ .formats = WM8994_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = WM8994_RATES,
+ .formats = WM8994_FORMATS,
+ },
+ .ops = &wm8994_ops,
+ },
+};
+
+/* gain_code range : integer 0~3 */
+static int is_valid_gain_code(char *str)
+{
+ if ((*str >= 0x30) && (*str <= 0x33))
+ return 1;
+ else {
+ DEBUG_LOG_ERR("gain code is invalid (%d)", *str);
+ return 0;
+ }
+}
+
+static int __init gain_code_setup(char *str)
+{
+
+ gain_code = 0;
+
+ if (!strcmp(str, "")) {
+ pr_info("gain_code field is empty. use default value\n");
+ return 0;
+ }
+
+ if (is_valid_gain_code(str)) {
+ gain_code = *str - 0x30;
+ DEBUG_LOG("gain_code : %d", gain_code);
+ } else
+ DEBUG_LOG_ERR("gain code is invalid and so use default value");
+
+ return 0;
+}
+__setup("gain_code=", gain_code_setup);
+
+int gain_code_check(void)
+{
+ return gain_code;
+}
+
+static const struct {
+ unsigned short readable; /* Mask of readable bits */
+ unsigned short writable; /* Mask of writable bits */
+} access_masks[] = {
+ { 0xFFFF, 0xFFFF }, /* R0 - Software Reset */
+ { 0x3B37, 0x3B37 }, /* R1 - Power Management (1) */
+ { 0x6BF0, 0x6BF0 }, /* R2 - Power Management (2) */
+ { 0x3FF0, 0x3FF0 }, /* R3 - Power Management (3) */
+ { 0x3F3F, 0x3F3F }, /* R4 - Power Management (4) */
+ { 0x3F0F, 0x3F0F }, /* R5 - Power Management (5) */
+ { 0x003F, 0x003F }, /* R6 - Power Management (6) */
+ { 0x0000, 0x0000 }, /* R7 */
+ { 0x0000, 0x0000 }, /* R8 */
+ { 0x0000, 0x0000 }, /* R9 */
+ { 0x0000, 0x0000 }, /* R10 */
+ { 0x0000, 0x0000 }, /* R11 */
+ { 0x0000, 0x0000 }, /* R12 */
+ { 0x0000, 0x0000 }, /* R13 */
+ { 0x0000, 0x0000 }, /* R14 */
+ { 0x0000, 0x0000 }, /* R15 */
+ { 0x0000, 0x0000 }, /* R16 */
+ { 0x0000, 0x0000 }, /* R17 */
+ { 0x0000, 0x0000 }, /* R18 */
+ { 0x0000, 0x0000 }, /* R19 */
+ { 0x0000, 0x0000 }, /* R20 */
+ { 0x01C0, 0x01C0 }, /* R21 - Input Mixer (1) */
+ { 0x0000, 0x0000 }, /* R22 */
+ { 0x0000, 0x0000 }, /* R23 */
+ { 0x00DF, 0x01DF }, /* R24 - Left Line Input 1&2 Volume */
+ { 0x00DF, 0x01DF }, /* R25 - Left Line Input 3&4 Volume */
+ { 0x00DF, 0x01DF }, /* R26 - Right Line Input 1&2 Volume */
+ { 0x00DF, 0x01DF }, /* R27 - Right Line Input 3&4 Volume */
+ { 0x00FF, 0x01FF }, /* R28 - Left Output Volume */
+ { 0x00FF, 0x01FF }, /* R29 - Right Output Volume */
+ { 0x0077, 0x0077 }, /* R30 - Line Outputs Volume */
+ { 0x0030, 0x0030 }, /* R31 - HPOUT2 Volume */
+ { 0x00FF, 0x01FF }, /* R32 - Left OPGA Volume */
+ { 0x00FF, 0x01FF }, /* R33 - Right OPGA Volume */
+ { 0x007F, 0x007F }, /* R34 - SPKMIXL Attenuation */
+ { 0x017F, 0x017F }, /* R35 - SPKMIXR Attenuation */
+ { 0x003F, 0x003F }, /* R36 - SPKOUT Mixers */
+ { 0x003F, 0x003F }, /* R37 - ClassD */
+ { 0x00FF, 0x01FF }, /* R38 - Speaker Volume Left */
+ { 0x00FF, 0x01FF }, /* R39 - Speaker Volume Right */
+ { 0x00FF, 0x00FF }, /* R40 - Input Mixer (2) */
+ { 0x01B7, 0x01B7 }, /* R41 - Input Mixer (3) */
+ { 0x01B7, 0x01B7 }, /* R42 - Input Mixer (4) */
+ { 0x01C7, 0x01C7 }, /* R43 - Input Mixer (5) */
+ { 0x01C7, 0x01C7 }, /* R44 - Input Mixer (6) */
+ { 0x01FF, 0x01FF }, /* R45 - Output Mixer (1) */
+ { 0x01FF, 0x01FF }, /* R46 - Output Mixer (2) */
+ { 0x0FFF, 0x0FFF }, /* R47 - Output Mixer (3) */
+ { 0x0FFF, 0x0FFF }, /* R48 - Output Mixer (4) */
+ { 0x0FFF, 0x0FFF }, /* R49 - Output Mixer (5) */
+ { 0x0FFF, 0x0FFF }, /* R50 - Output Mixer (6) */
+ { 0x0038, 0x0038 }, /* R51 - HPOUT2 Mixer */
+ { 0x0077, 0x0077 }, /* R52 - Line Mixer (1) */
+ { 0x0077, 0x0077 }, /* R53 - Line Mixer (2) */
+ { 0x03FF, 0x03FF }, /* R54 - Speaker Mixer */
+ { 0x00C1, 0x00C1 }, /* R55 - Additional Control */
+ { 0x00F0, 0x00F0 }, /* R56 - AntiPOP (1) */
+ { 0x01EF, 0x01EF }, /* R57 - AntiPOP (2) */
+ { 0x00FF, 0x00FF }, /* R58 - MICBIAS */
+ { 0x000F, 0x000F }, /* R59 - LDO 1 */
+ { 0x0007, 0x0007 }, /* R60 - LDO 2 */
+ { 0x0000, 0x0000 }, /* R61 */
+ { 0x0000, 0x0000 }, /* R62 */
+ { 0x0000, 0x0000 }, /* R63 */
+ { 0x0000, 0x0000 }, /* R64 */
+ { 0x0000, 0x0000 }, /* R65 */
+ { 0x0000, 0x0000 }, /* R66 */
+ { 0x0000, 0x0000 }, /* R67 */
+ { 0x0000, 0x0000 }, /* R68 */
+ { 0x0000, 0x0000 }, /* R69 */
+ { 0x0000, 0x0000 }, /* R70 */
+ { 0x0000, 0x0000 }, /* R71 */
+ { 0x0000, 0x0000 }, /* R72 */
+ { 0x0000, 0x0000 }, /* R73 */
+ { 0x0000, 0x0000 }, /* R74 */
+ { 0x0000, 0x0000 }, /* R75 */
+ { 0x8000, 0x8000 }, /* R76 - Charge Pump (1) */
+ { 0x0000, 0x0000 }, /* R77 */
+ { 0x0000, 0x0000 }, /* R78 */
+ { 0x0000, 0x0000 }, /* R79 */
+ { 0x0000, 0x0000 }, /* R80 */
+ { 0x0301, 0x0301 }, /* R81 - Class W (1) */
+ { 0x0000, 0x0000 }, /* R82 */
+ { 0x0000, 0x0000 }, /* R83 */
+ { 0x333F, 0x333F }, /* R84 - DC Servo (1) */
+ { 0x0FEF, 0x0FEF }, /* R85 - DC Servo (2) */
+ { 0x0000, 0x0000 }, /* R86 */
+ { 0xFFFF, 0xFFFF }, /* R87 - DC Servo (4) */
+ { 0x0333, 0x0000 }, /* R88 - DC Servo Readback */
+ { 0x0000, 0x0000 }, /* R89 */
+ { 0x0000, 0x0000 }, /* R90 */
+ { 0x0000, 0x0000 }, /* R91 */
+ { 0x0000, 0x0000 }, /* R92 */
+ { 0x0000, 0x0000 }, /* R93 */
+ { 0x0000, 0x0000 }, /* R94 */
+ { 0x0000, 0x0000 }, /* R95 */
+ { 0x00EE, 0x00EE }, /* R96 - Analogue HP (1) */
+ { 0x0000, 0x0000 }, /* R97 */
+ { 0x0000, 0x0000 }, /* R98 */
+ { 0x0000, 0x0000 }, /* R99 */
+ { 0x0000, 0x0000 }, /* R100 */
+ { 0x0000, 0x0000 }, /* R101 */
+ { 0x0000, 0x0000 }, /* R102 */
+ { 0x0000, 0x0000 }, /* R103 */
+ { 0x0000, 0x0000 }, /* R104 */
+ { 0x0000, 0x0000 }, /* R105 */
+ { 0x0000, 0x0000 }, /* R106 */
+ { 0x0000, 0x0000 }, /* R107 */
+ { 0x0000, 0x0000 }, /* R108 */
+ { 0x0000, 0x0000 }, /* R109 */
+ { 0x0000, 0x0000 }, /* R110 */
+ { 0x0000, 0x0000 }, /* R111 */
+ { 0x0000, 0x0000 }, /* R112 */
+ { 0x0000, 0x0000 }, /* R113 */
+ { 0x0000, 0x0000 }, /* R114 */
+ { 0x0000, 0x0000 }, /* R115 */
+ { 0x0000, 0x0000 }, /* R116 */
+ { 0x0000, 0x0000 }, /* R117 */
+ { 0x0000, 0x0000 }, /* R118 */
+ { 0x0000, 0x0000 }, /* R119 */
+ { 0x0000, 0x0000 }, /* R120 */
+ { 0x0000, 0x0000 }, /* R121 */
+ { 0x0000, 0x0000 }, /* R122 */
+ { 0x0000, 0x0000 }, /* R123 */
+ { 0x0000, 0x0000 }, /* R124 */
+ { 0x0000, 0x0000 }, /* R125 */
+ { 0x0000, 0x0000 }, /* R126 */
+ { 0x0000, 0x0000 }, /* R127 */
+ { 0x0000, 0x0000 }, /* R128 */
+ { 0x0000, 0x0000 }, /* R129 */
+ { 0x0000, 0x0000 }, /* R130 */
+ { 0x0000, 0x0000 }, /* R131 */
+ { 0x0000, 0x0000 }, /* R132 */
+ { 0x0000, 0x0000 }, /* R133 */
+ { 0x0000, 0x0000 }, /* R134 */
+ { 0x0000, 0x0000 }, /* R135 */
+ { 0x0000, 0x0000 }, /* R136 */
+ { 0x0000, 0x0000 }, /* R137 */
+ { 0x0000, 0x0000 }, /* R138 */
+ { 0x0000, 0x0000 }, /* R139 */
+ { 0x0000, 0x0000 }, /* R140 */
+ { 0x0000, 0x0000 }, /* R141 */
+ { 0x0000, 0x0000 }, /* R142 */
+ { 0x0000, 0x0000 }, /* R143 */
+ { 0x0000, 0x0000 }, /* R144 */
+ { 0x0000, 0x0000 }, /* R145 */
+ { 0x0000, 0x0000 }, /* R146 */
+ { 0x0000, 0x0000 }, /* R147 */
+ { 0x0000, 0x0000 }, /* R148 */
+ { 0x0000, 0x0000 }, /* R149 */
+ { 0x0000, 0x0000 }, /* R150 */
+ { 0x0000, 0x0000 }, /* R151 */
+ { 0x0000, 0x0000 }, /* R152 */
+ { 0x0000, 0x0000 }, /* R153 */
+ { 0x0000, 0x0000 }, /* R154 */
+ { 0x0000, 0x0000 }, /* R155 */
+ { 0x0000, 0x0000 }, /* R156 */
+ { 0x0000, 0x0000 }, /* R157 */
+ { 0x0000, 0x0000 }, /* R158 */
+ { 0x0000, 0x0000 }, /* R159 */
+ { 0x0000, 0x0000 }, /* R160 */
+ { 0x0000, 0x0000 }, /* R161 */
+ { 0x0000, 0x0000 }, /* R162 */
+ { 0x0000, 0x0000 }, /* R163 */
+ { 0x0000, 0x0000 }, /* R164 */
+ { 0x0000, 0x0000 }, /* R165 */
+ { 0x0000, 0x0000 }, /* R166 */
+ { 0x0000, 0x0000 }, /* R167 */
+ { 0x0000, 0x0000 }, /* R168 */
+ { 0x0000, 0x0000 }, /* R169 */
+ { 0x0000, 0x0000 }, /* R170 */
+ { 0x0000, 0x0000 }, /* R171 */
+ { 0x0000, 0x0000 }, /* R172 */
+ { 0x0000, 0x0000 }, /* R173 */
+ { 0x0000, 0x0000 }, /* R174 */
+ { 0x0000, 0x0000 }, /* R175 */
+ { 0x0000, 0x0000 }, /* R176 */
+ { 0x0000, 0x0000 }, /* R177 */
+ { 0x0000, 0x0000 }, /* R178 */
+ { 0x0000, 0x0000 }, /* R179 */
+ { 0x0000, 0x0000 }, /* R180 */
+ { 0x0000, 0x0000 }, /* R181 */
+ { 0x0000, 0x0000 }, /* R182 */
+ { 0x0000, 0x0000 }, /* R183 */
+ { 0x0000, 0x0000 }, /* R184 */
+ { 0x0000, 0x0000 }, /* R185 */
+ { 0x0000, 0x0000 }, /* R186 */
+ { 0x0000, 0x0000 }, /* R187 */
+ { 0x0000, 0x0000 }, /* R188 */
+ { 0x0000, 0x0000 }, /* R189 */
+ { 0x0000, 0x0000 }, /* R190 */
+ { 0x0000, 0x0000 }, /* R191 */
+ { 0x0000, 0x0000 }, /* R192 */
+ { 0x0000, 0x0000 }, /* R193 */
+ { 0x0000, 0x0000 }, /* R194 */
+ { 0x0000, 0x0000 }, /* R195 */
+ { 0x0000, 0x0000 }, /* R196 */
+ { 0x0000, 0x0000 }, /* R197 */
+ { 0x0000, 0x0000 }, /* R198 */
+ { 0x0000, 0x0000 }, /* R199 */
+ { 0x0000, 0x0000 }, /* R200 */
+ { 0x0000, 0x0000 }, /* R201 */
+ { 0x0000, 0x0000 }, /* R202 */
+ { 0x0000, 0x0000 }, /* R203 */
+ { 0x0000, 0x0000 }, /* R204 */
+ { 0x0000, 0x0000 }, /* R205 */
+ { 0x0000, 0x0000 }, /* R206 */
+ { 0x0000, 0x0000 }, /* R207 */
+ { 0x0000, 0x0000 }, /* R208 */
+ { 0x0000, 0x0000 }, /* R209 */
+ { 0x0000, 0x0000 }, /* R210 */
+ { 0x0000, 0x0000 }, /* R211 */
+ { 0x0000, 0x0000 }, /* R212 */
+ { 0x0000, 0x0000 }, /* R213 */
+ { 0x0000, 0x0000 }, /* R214 */
+ { 0x0000, 0x0000 }, /* R215 */
+ { 0x0000, 0x0000 }, /* R216 */
+ { 0x0000, 0x0000 }, /* R217 */
+ { 0x0000, 0x0000 }, /* R218 */
+ { 0x0000, 0x0000 }, /* R219 */
+ { 0x0000, 0x0000 }, /* R220 */
+ { 0x0000, 0x0000 }, /* R221 */
+ { 0x0000, 0x0000 }, /* R222 */
+ { 0x0000, 0x0000 }, /* R223 */
+ { 0x0000, 0x0000 }, /* R224 */
+ { 0x0000, 0x0000 }, /* R225 */
+ { 0x0000, 0x0000 }, /* R226 */
+ { 0x0000, 0x0000 }, /* R227 */
+ { 0x0000, 0x0000 }, /* R228 */
+ { 0x0000, 0x0000 }, /* R229 */
+ { 0x0000, 0x0000 }, /* R230 */
+ { 0x0000, 0x0000 }, /* R231 */
+ { 0x0000, 0x0000 }, /* R232 */
+ { 0x0000, 0x0000 }, /* R233 */
+ { 0x0000, 0x0000 }, /* R234 */
+ { 0x0000, 0x0000 }, /* R235 */
+ { 0x0000, 0x0000 }, /* R236 */
+ { 0x0000, 0x0000 }, /* R237 */
+ { 0x0000, 0x0000 }, /* R238 */
+ { 0x0000, 0x0000 }, /* R239 */
+ { 0x0000, 0x0000 }, /* R240 */
+ { 0x0000, 0x0000 }, /* R241 */
+ { 0x0000, 0x0000 }, /* R242 */
+ { 0x0000, 0x0000 }, /* R243 */
+ { 0x0000, 0x0000 }, /* R244 */
+ { 0x0000, 0x0000 }, /* R245 */
+ { 0x0000, 0x0000 }, /* R246 */
+ { 0x0000, 0x0000 }, /* R247 */
+ { 0x0000, 0x0000 }, /* R248 */
+ { 0x0000, 0x0000 }, /* R249 */
+ { 0x0000, 0x0000 }, /* R250 */
+ { 0x0000, 0x0000 }, /* R251 */
+ { 0x0000, 0x0000 }, /* R252 */
+ { 0x0000, 0x0000 }, /* R253 */
+ { 0x0000, 0x0000 }, /* R254 */
+ { 0x0000, 0x0000 }, /* R255 */
+ { 0x000F, 0x0000 }, /* R256 - Chip Revision */
+ { 0x0074, 0x0074 }, /* R257 - Control Interface */
+ { 0x0000, 0x0000 }, /* R258 */
+ { 0x0000, 0x0000 }, /* R259 */
+ { 0x0000, 0x0000 }, /* R260 */
+ { 0x0000, 0x0000 }, /* R261 */
+ { 0x0000, 0x0000 }, /* R262 */
+ { 0x0000, 0x0000 }, /* R263 */
+ { 0x0000, 0x0000 }, /* R264 */
+ { 0x0000, 0x0000 }, /* R265 */
+ { 0x0000, 0x0000 }, /* R266 */
+ { 0x0000, 0x0000 }, /* R267 */
+ { 0x0000, 0x0000 }, /* R268 */
+ { 0x0000, 0x0000 }, /* R269 */
+ { 0x0000, 0x0000 }, /* R270 */
+ { 0x0000, 0x0000 }, /* R271 */
+ { 0x807F, 0x837F }, /* R272 - Write Sequencer Ctrl (1) */
+ { 0x017F, 0x0000 }, /* R273 - Write Sequencer Ctrl (2) */
+ { 0x0000, 0x0000 }, /* R274 */
+ { 0x0000, 0x0000 }, /* R275 */
+ { 0x0000, 0x0000 }, /* R276 */
+ { 0x0000, 0x0000 }, /* R277 */
+ { 0x0000, 0x0000 }, /* R278 */
+ { 0x0000, 0x0000 }, /* R279 */
+ { 0x0000, 0x0000 }, /* R280 */
+ { 0x0000, 0x0000 }, /* R281 */
+ { 0x0000, 0x0000 }, /* R282 */
+ { 0x0000, 0x0000 }, /* R283 */
+ { 0x0000, 0x0000 }, /* R284 */
+ { 0x0000, 0x0000 }, /* R285 */
+ { 0x0000, 0x0000 }, /* R286 */
+ { 0x0000, 0x0000 }, /* R287 */
+ { 0x0000, 0x0000 }, /* R288 */
+ { 0x0000, 0x0000 }, /* R289 */
+ { 0x0000, 0x0000 }, /* R290 */
+ { 0x0000, 0x0000 }, /* R291 */
+ { 0x0000, 0x0000 }, /* R292 */
+ { 0x0000, 0x0000 }, /* R293 */
+ { 0x0000, 0x0000 }, /* R294 */
+ { 0x0000, 0x0000 }, /* R295 */
+ { 0x0000, 0x0000 }, /* R296 */
+ { 0x0000, 0x0000 }, /* R297 */
+ { 0x0000, 0x0000 }, /* R298 */
+ { 0x0000, 0x0000 }, /* R299 */
+ { 0x0000, 0x0000 }, /* R300 */
+ { 0x0000, 0x0000 }, /* R301 */
+ { 0x0000, 0x0000 }, /* R302 */
+ { 0x0000, 0x0000 }, /* R303 */
+ { 0x0000, 0x0000 }, /* R304 */
+ { 0x0000, 0x0000 }, /* R305 */
+ { 0x0000, 0x0000 }, /* R306 */
+ { 0x0000, 0x0000 }, /* R307 */
+ { 0x0000, 0x0000 }, /* R308 */
+ { 0x0000, 0x0000 }, /* R309 */
+ { 0x0000, 0x0000 }, /* R310 */
+ { 0x0000, 0x0000 }, /* R311 */
+ { 0x0000, 0x0000 }, /* R312 */
+ { 0x0000, 0x0000 }, /* R313 */
+ { 0x0000, 0x0000 }, /* R314 */
+ { 0x0000, 0x0000 }, /* R315 */
+ { 0x0000, 0x0000 }, /* R316 */
+ { 0x0000, 0x0000 }, /* R317 */
+ { 0x0000, 0x0000 }, /* R318 */
+ { 0x0000, 0x0000 }, /* R319 */
+ { 0x0000, 0x0000 }, /* R320 */
+ { 0x0000, 0x0000 }, /* R321 */
+ { 0x0000, 0x0000 }, /* R322 */
+ { 0x0000, 0x0000 }, /* R323 */
+ { 0x0000, 0x0000 }, /* R324 */
+ { 0x0000, 0x0000 }, /* R325 */
+ { 0x0000, 0x0000 }, /* R326 */
+ { 0x0000, 0x0000 }, /* R327 */
+ { 0x0000, 0x0000 }, /* R328 */
+ { 0x0000, 0x0000 }, /* R329 */
+ { 0x0000, 0x0000 }, /* R330 */
+ { 0x0000, 0x0000 }, /* R331 */
+ { 0x0000, 0x0000 }, /* R332 */
+ { 0x0000, 0x0000 }, /* R333 */
+ { 0x0000, 0x0000 }, /* R334 */
+ { 0x0000, 0x0000 }, /* R335 */
+ { 0x0000, 0x0000 }, /* R336 */
+ { 0x0000, 0x0000 }, /* R337 */
+ { 0x0000, 0x0000 }, /* R338 */
+ { 0x0000, 0x0000 }, /* R339 */
+ { 0x0000, 0x0000 }, /* R340 */
+ { 0x0000, 0x0000 }, /* R341 */
+ { 0x0000, 0x0000 }, /* R342 */
+ { 0x0000, 0x0000 }, /* R343 */
+ { 0x0000, 0x0000 }, /* R344 */
+ { 0x0000, 0x0000 }, /* R345 */
+ { 0x0000, 0x0000 }, /* R346 */
+ { 0x0000, 0x0000 }, /* R347 */
+ { 0x0000, 0x0000 }, /* R348 */
+ { 0x0000, 0x0000 }, /* R349 */
+ { 0x0000, 0x0000 }, /* R350 */
+ { 0x0000, 0x0000 }, /* R351 */
+ { 0x0000, 0x0000 }, /* R352 */
+ { 0x0000, 0x0000 }, /* R353 */
+ { 0x0000, 0x0000 }, /* R354 */
+ { 0x0000, 0x0000 }, /* R355 */
+ { 0x0000, 0x0000 }, /* R356 */
+ { 0x0000, 0x0000 }, /* R357 */
+ { 0x0000, 0x0000 }, /* R358 */
+ { 0x0000, 0x0000 }, /* R359 */
+ { 0x0000, 0x0000 }, /* R360 */
+ { 0x0000, 0x0000 }, /* R361 */
+ { 0x0000, 0x0000 }, /* R362 */
+ { 0x0000, 0x0000 }, /* R363 */
+ { 0x0000, 0x0000 }, /* R364 */
+ { 0x0000, 0x0000 }, /* R365 */
+ { 0x0000, 0x0000 }, /* R366 */
+ { 0x0000, 0x0000 }, /* R367 */
+ { 0x0000, 0x0000 }, /* R368 */
+ { 0x0000, 0x0000 }, /* R369 */
+ { 0x0000, 0x0000 }, /* R370 */
+ { 0x0000, 0x0000 }, /* R371 */
+ { 0x0000, 0x0000 }, /* R372 */
+ { 0x0000, 0x0000 }, /* R373 */
+ { 0x0000, 0x0000 }, /* R374 */
+ { 0x0000, 0x0000 }, /* R375 */
+ { 0x0000, 0x0000 }, /* R376 */
+ { 0x0000, 0x0000 }, /* R377 */
+ { 0x0000, 0x0000 }, /* R378 */
+ { 0x0000, 0x0000 }, /* R379 */
+ { 0x0000, 0x0000 }, /* R380 */
+ { 0x0000, 0x0000 }, /* R381 */
+ { 0x0000, 0x0000 }, /* R382 */
+ { 0x0000, 0x0000 }, /* R383 */
+ { 0x0000, 0x0000 }, /* R384 */
+ { 0x0000, 0x0000 }, /* R385 */
+ { 0x0000, 0x0000 }, /* R386 */
+ { 0x0000, 0x0000 }, /* R387 */
+ { 0x0000, 0x0000 }, /* R388 */
+ { 0x0000, 0x0000 }, /* R389 */
+ { 0x0000, 0x0000 }, /* R390 */
+ { 0x0000, 0x0000 }, /* R391 */
+ { 0x0000, 0x0000 }, /* R392 */
+ { 0x0000, 0x0000 }, /* R393 */
+ { 0x0000, 0x0000 }, /* R394 */
+ { 0x0000, 0x0000 }, /* R395 */
+ { 0x0000, 0x0000 }, /* R396 */
+ { 0x0000, 0x0000 }, /* R397 */
+ { 0x0000, 0x0000 }, /* R398 */
+ { 0x0000, 0x0000 }, /* R399 */
+ { 0x0000, 0x0000 }, /* R400 */
+ { 0x0000, 0x0000 }, /* R401 */
+ { 0x0000, 0x0000 }, /* R402 */
+ { 0x0000, 0x0000 }, /* R403 */
+ { 0x0000, 0x0000 }, /* R404 */
+ { 0x0000, 0x0000 }, /* R405 */
+ { 0x0000, 0x0000 }, /* R406 */
+ { 0x0000, 0x0000 }, /* R407 */
+ { 0x0000, 0x0000 }, /* R408 */
+ { 0x0000, 0x0000 }, /* R409 */
+ { 0x0000, 0x0000 }, /* R410 */
+ { 0x0000, 0x0000 }, /* R411 */
+ { 0x0000, 0x0000 }, /* R412 */
+ { 0x0000, 0x0000 }, /* R413 */
+ { 0x0000, 0x0000 }, /* R414 */
+ { 0x0000, 0x0000 }, /* R415 */
+ { 0x0000, 0x0000 }, /* R416 */
+ { 0x0000, 0x0000 }, /* R417 */
+ { 0x0000, 0x0000 }, /* R418 */
+ { 0x0000, 0x0000 }, /* R419 */
+ { 0x0000, 0x0000 }, /* R420 */
+ { 0x0000, 0x0000 }, /* R421 */
+ { 0x0000, 0x0000 }, /* R422 */
+ { 0x0000, 0x0000 }, /* R423 */
+ { 0x0000, 0x0000 }, /* R424 */
+ { 0x0000, 0x0000 }, /* R425 */
+ { 0x0000, 0x0000 }, /* R426 */
+ { 0x0000, 0x0000 }, /* R427 */
+ { 0x0000, 0x0000 }, /* R428 */
+ { 0x0000, 0x0000 }, /* R429 */
+ { 0x0000, 0x0000 }, /* R430 */
+ { 0x0000, 0x0000 }, /* R431 */
+ { 0x0000, 0x0000 }, /* R432 */
+ { 0x0000, 0x0000 }, /* R433 */
+ { 0x0000, 0x0000 }, /* R434 */
+ { 0x0000, 0x0000 }, /* R435 */
+ { 0x0000, 0x0000 }, /* R436 */
+ { 0x0000, 0x0000 }, /* R437 */
+ { 0x0000, 0x0000 }, /* R438 */
+ { 0x0000, 0x0000 }, /* R439 */
+ { 0x0000, 0x0000 }, /* R440 */
+ { 0x0000, 0x0000 }, /* R441 */
+ { 0x0000, 0x0000 }, /* R442 */
+ { 0x0000, 0x0000 }, /* R443 */
+ { 0x0000, 0x0000 }, /* R444 */
+ { 0x0000, 0x0000 }, /* R445 */
+ { 0x0000, 0x0000 }, /* R446 */
+ { 0x0000, 0x0000 }, /* R447 */
+ { 0x0000, 0x0000 }, /* R448 */
+ { 0x0000, 0x0000 }, /* R449 */
+ { 0x0000, 0x0000 }, /* R450 */
+ { 0x0000, 0x0000 }, /* R451 */
+ { 0x0000, 0x0000 }, /* R452 */
+ { 0x0000, 0x0000 }, /* R453 */
+ { 0x0000, 0x0000 }, /* R454 */
+ { 0x0000, 0x0000 }, /* R455 */
+ { 0x0000, 0x0000 }, /* R456 */
+ { 0x0000, 0x0000 }, /* R457 */
+ { 0x0000, 0x0000 }, /* R458 */
+ { 0x0000, 0x0000 }, /* R459 */
+ { 0x0000, 0x0000 }, /* R460 */
+ { 0x0000, 0x0000 }, /* R461 */
+ { 0x0000, 0x0000 }, /* R462 */
+ { 0x0000, 0x0000 }, /* R463 */
+ { 0x0000, 0x0000 }, /* R464 */
+ { 0x0000, 0x0000 }, /* R465 */
+ { 0x0000, 0x0000 }, /* R466 */
+ { 0x0000, 0x0000 }, /* R467 */
+ { 0x0000, 0x0000 }, /* R468 */
+ { 0x0000, 0x0000 }, /* R469 */
+ { 0x0000, 0x0000 }, /* R470 */
+ { 0x0000, 0x0000 }, /* R471 */
+ { 0x0000, 0x0000 }, /* R472 */
+ { 0x0000, 0x0000 }, /* R473 */
+ { 0x0000, 0x0000 }, /* R474 */
+ { 0x0000, 0x0000 }, /* R475 */
+ { 0x0000, 0x0000 }, /* R476 */
+ { 0x0000, 0x0000 }, /* R477 */
+ { 0x0000, 0x0000 }, /* R478 */
+ { 0x0000, 0x0000 }, /* R479 */
+ { 0x0000, 0x0000 }, /* R480 */
+ { 0x0000, 0x0000 }, /* R481 */
+ { 0x0000, 0x0000 }, /* R482 */
+ { 0x0000, 0x0000 }, /* R483 */
+ { 0x0000, 0x0000 }, /* R484 */
+ { 0x0000, 0x0000 }, /* R485 */
+ { 0x0000, 0x0000 }, /* R486 */
+ { 0x0000, 0x0000 }, /* R487 */
+ { 0x0000, 0x0000 }, /* R488 */
+ { 0x0000, 0x0000 }, /* R489 */
+ { 0x0000, 0x0000 }, /* R490 */
+ { 0x0000, 0x0000 }, /* R491 */
+ { 0x0000, 0x0000 }, /* R492 */
+ { 0x0000, 0x0000 }, /* R493 */
+ { 0x0000, 0x0000 }, /* R494 */
+ { 0x0000, 0x0000 }, /* R495 */
+ { 0x0000, 0x0000 }, /* R496 */
+ { 0x0000, 0x0000 }, /* R497 */
+ { 0x0000, 0x0000 }, /* R498 */
+ { 0x0000, 0x0000 }, /* R499 */
+ { 0x0000, 0x0000 }, /* R500 */
+ { 0x0000, 0x0000 }, /* R501 */
+ { 0x0000, 0x0000 }, /* R502 */
+ { 0x0000, 0x0000 }, /* R503 */
+ { 0x0000, 0x0000 }, /* R504 */
+ { 0x0000, 0x0000 }, /* R505 */
+ { 0x0000, 0x0000 }, /* R506 */
+ { 0x0000, 0x0000 }, /* R507 */
+ { 0x0000, 0x0000 }, /* R508 */
+ { 0x0000, 0x0000 }, /* R509 */
+ { 0x0000, 0x0000 }, /* R510 */
+ { 0x0000, 0x0000 }, /* R511 */
+ { 0x001F, 0x001F }, /* R512 - AIF1 Clocking (1) */
+ { 0x003F, 0x003F }, /* R513 - AIF1 Clocking (2) */
+ { 0x0000, 0x0000 }, /* R514 */
+ { 0x0000, 0x0000 }, /* R515 */
+ { 0x001F, 0x001F }, /* R516 - AIF2 Clocking (1) */
+ { 0x003F, 0x003F }, /* R517 - AIF2 Clocking (2) */
+ { 0x0000, 0x0000 }, /* R518 */
+ { 0x0000, 0x0000 }, /* R519 */
+ { 0x001F, 0x001F }, /* R520 - Clocking (1) */
+ { 0x0777, 0x0777 }, /* R521 - Clocking (2) */
+ { 0x0000, 0x0000 }, /* R522 */
+ { 0x0000, 0x0000 }, /* R523 */
+ { 0x0000, 0x0000 }, /* R524 */
+ { 0x0000, 0x0000 }, /* R525 */
+ { 0x0000, 0x0000 }, /* R526 */
+ { 0x0000, 0x0000 }, /* R527 */
+ { 0x00FF, 0x00FF }, /* R528 - AIF1 Rate */
+ { 0x00FF, 0x00FF }, /* R529 - AIF2 Rate */
+ { 0x000F, 0x0000 }, /* R530 - Rate Status */
+ { 0x0000, 0x0000 }, /* R531 */
+ { 0x0000, 0x0000 }, /* R532 */
+ { 0x0000, 0x0000 }, /* R533 */
+ { 0x0000, 0x0000 }, /* R534 */
+ { 0x0000, 0x0000 }, /* R535 */
+ { 0x0000, 0x0000 }, /* R536 */
+ { 0x0000, 0x0000 }, /* R537 */
+ { 0x0000, 0x0000 }, /* R538 */
+ { 0x0000, 0x0000 }, /* R539 */
+ { 0x0000, 0x0000 }, /* R540 */
+ { 0x0000, 0x0000 }, /* R541 */
+ { 0x0000, 0x0000 }, /* R542 */
+ { 0x0000, 0x0000 }, /* R543 */
+ { 0x0007, 0x0007 }, /* R544 - FLL1 Control (1) */
+ { 0x3F77, 0x3F77 }, /* R545 - FLL1 Control (2) */
+ { 0xFFFF, 0xFFFF }, /* R546 - FLL1 Control (3) */
+ { 0x7FEF, 0x7FEF }, /* R547 - FLL1 Control (4) */
+ { 0x1FDB, 0x1FDB }, /* R548 - FLL1 Control (5) */
+ { 0x0000, 0x0000 }, /* R549 */
+ { 0x0000, 0x0000 }, /* R550 */
+ { 0x0000, 0x0000 }, /* R551 */
+ { 0x0000, 0x0000 }, /* R552 */
+ { 0x0000, 0x0000 }, /* R553 */
+ { 0x0000, 0x0000 }, /* R554 */
+ { 0x0000, 0x0000 }, /* R555 */
+ { 0x0000, 0x0000 }, /* R556 */
+ { 0x0000, 0x0000 }, /* R557 */
+ { 0x0000, 0x0000 }, /* R558 */
+ { 0x0000, 0x0000 }, /* R559 */
+ { 0x0000, 0x0000 }, /* R560 */
+ { 0x0000, 0x0000 }, /* R561 */
+ { 0x0000, 0x0000 }, /* R562 */
+ { 0x0000, 0x0000 }, /* R563 */
+ { 0x0000, 0x0000 }, /* R564 */
+ { 0x0000, 0x0000 }, /* R565 */
+ { 0x0000, 0x0000 }, /* R566 */
+ { 0x0000, 0x0000 }, /* R567 */
+ { 0x0000, 0x0000 }, /* R568 */
+ { 0x0000, 0x0000 }, /* R569 */
+ { 0x0000, 0x0000 }, /* R570 */
+ { 0x0000, 0x0000 }, /* R571 */
+ { 0x0000, 0x0000 }, /* R572 */
+ { 0x0000, 0x0000 }, /* R573 */
+ { 0x0000, 0x0000 }, /* R574 */
+ { 0x0000, 0x0000 }, /* R575 */
+ { 0x0007, 0x0007 }, /* R576 - FLL2 Control (1) */
+ { 0x3F77, 0x3F77 }, /* R577 - FLL2 Control (2) */
+ { 0xFFFF, 0xFFFF }, /* R578 - FLL2 Control (3) */
+ { 0x7FEF, 0x7FEF }, /* R579 - FLL2 Control (4) */
+ { 0x1FDB, 0x1FDB }, /* R580 - FLL2 Control (5) */
+ { 0x0000, 0x0000 }, /* R581 */
+ { 0x0000, 0x0000 }, /* R582 */
+ { 0x0000, 0x0000 }, /* R583 */
+ { 0x0000, 0x0000 }, /* R584 */
+ { 0x0000, 0x0000 }, /* R585 */
+ { 0x0000, 0x0000 }, /* R586 */
+ { 0x0000, 0x0000 }, /* R587 */
+ { 0x0000, 0x0000 }, /* R588 */
+ { 0x0000, 0x0000 }, /* R589 */
+ { 0x0000, 0x0000 }, /* R590 */
+ { 0x0000, 0x0000 }, /* R591 */
+ { 0x0000, 0x0000 }, /* R592 */
+ { 0x0000, 0x0000 }, /* R593 */
+ { 0x0000, 0x0000 }, /* R594 */
+ { 0x0000, 0x0000 }, /* R595 */
+ { 0x0000, 0x0000 }, /* R596 */
+ { 0x0000, 0x0000 }, /* R597 */
+ { 0x0000, 0x0000 }, /* R598 */
+ { 0x0000, 0x0000 }, /* R599 */
+ { 0x0000, 0x0000 }, /* R600 */
+ { 0x0000, 0x0000 }, /* R601 */
+ { 0x0000, 0x0000 }, /* R602 */
+ { 0x0000, 0x0000 }, /* R603 */
+ { 0x0000, 0x0000 }, /* R604 */
+ { 0x0000, 0x0000 }, /* R605 */
+ { 0x0000, 0x0000 }, /* R606 */
+ { 0x0000, 0x0000 }, /* R607 */
+ { 0x0000, 0x0000 }, /* R608 */
+ { 0x0000, 0x0000 }, /* R609 */
+ { 0x0000, 0x0000 }, /* R610 */
+ { 0x0000, 0x0000 }, /* R611 */
+ { 0x0000, 0x0000 }, /* R612 */
+ { 0x0000, 0x0000 }, /* R613 */
+ { 0x0000, 0x0000 }, /* R614 */
+ { 0x0000, 0x0000 }, /* R615 */
+ { 0x0000, 0x0000 }, /* R616 */
+ { 0x0000, 0x0000 }, /* R617 */
+ { 0x0000, 0x0000 }, /* R618 */
+ { 0x0000, 0x0000 }, /* R619 */
+ { 0x0000, 0x0000 }, /* R620 */
+ { 0x0000, 0x0000 }, /* R621 */
+ { 0x0000, 0x0000 }, /* R622 */
+ { 0x0000, 0x0000 }, /* R623 */
+ { 0x0000, 0x0000 }, /* R624 */
+ { 0x0000, 0x0000 }, /* R625 */
+ { 0x0000, 0x0000 }, /* R626 */
+ { 0x0000, 0x0000 }, /* R627 */
+ { 0x0000, 0x0000 }, /* R628 */
+ { 0x0000, 0x0000 }, /* R629 */
+ { 0x0000, 0x0000 }, /* R630 */
+ { 0x0000, 0x0000 }, /* R631 */
+ { 0x0000, 0x0000 }, /* R632 */
+ { 0x0000, 0x0000 }, /* R633 */
+ { 0x0000, 0x0000 }, /* R634 */
+ { 0x0000, 0x0000 }, /* R635 */
+ { 0x0000, 0x0000 }, /* R636 */
+ { 0x0000, 0x0000 }, /* R637 */
+ { 0x0000, 0x0000 }, /* R638 */
+ { 0x0000, 0x0000 }, /* R639 */
+ { 0x0000, 0x0000 }, /* R640 */
+ { 0x0000, 0x0000 }, /* R641 */
+ { 0x0000, 0x0000 }, /* R642 */
+ { 0x0000, 0x0000 }, /* R643 */
+ { 0x0000, 0x0000 }, /* R644 */
+ { 0x0000, 0x0000 }, /* R645 */
+ { 0x0000, 0x0000 }, /* R646 */
+ { 0x0000, 0x0000 }, /* R647 */
+ { 0x0000, 0x0000 }, /* R648 */
+ { 0x0000, 0x0000 }, /* R649 */
+ { 0x0000, 0x0000 }, /* R650 */
+ { 0x0000, 0x0000 }, /* R651 */
+ { 0x0000, 0x0000 }, /* R652 */
+ { 0x0000, 0x0000 }, /* R653 */
+ { 0x0000, 0x0000 }, /* R654 */
+ { 0x0000, 0x0000 }, /* R655 */
+ { 0x0000, 0x0000 }, /* R656 */
+ { 0x0000, 0x0000 }, /* R657 */
+ { 0x0000, 0x0000 }, /* R658 */
+ { 0x0000, 0x0000 }, /* R659 */
+ { 0x0000, 0x0000 }, /* R660 */
+ { 0x0000, 0x0000 }, /* R661 */
+ { 0x0000, 0x0000 }, /* R662 */
+ { 0x0000, 0x0000 }, /* R663 */
+ { 0x0000, 0x0000 }, /* R664 */
+ { 0x0000, 0x0000 }, /* R665 */
+ { 0x0000, 0x0000 }, /* R666 */
+ { 0x0000, 0x0000 }, /* R667 */
+ { 0x0000, 0x0000 }, /* R668 */
+ { 0x0000, 0x0000 }, /* R669 */
+ { 0x0000, 0x0000 }, /* R670 */
+ { 0x0000, 0x0000 }, /* R671 */
+ { 0x0000, 0x0000 }, /* R672 */
+ { 0x0000, 0x0000 }, /* R673 */
+ { 0x0000, 0x0000 }, /* R674 */
+ { 0x0000, 0x0000 }, /* R675 */
+ { 0x0000, 0x0000 }, /* R676 */
+ { 0x0000, 0x0000 }, /* R677 */
+ { 0x0000, 0x0000 }, /* R678 */
+ { 0x0000, 0x0000 }, /* R679 */
+ { 0x0000, 0x0000 }, /* R680 */
+ { 0x0000, 0x0000 }, /* R681 */
+ { 0x0000, 0x0000 }, /* R682 */
+ { 0x0000, 0x0000 }, /* R683 */
+ { 0x0000, 0x0000 }, /* R684 */
+ { 0x0000, 0x0000 }, /* R685 */
+ { 0x0000, 0x0000 }, /* R686 */
+ { 0x0000, 0x0000 }, /* R687 */
+ { 0x0000, 0x0000 }, /* R688 */
+ { 0x0000, 0x0000 }, /* R689 */
+ { 0x0000, 0x0000 }, /* R690 */
+ { 0x0000, 0x0000 }, /* R691 */
+ { 0x0000, 0x0000 }, /* R692 */
+ { 0x0000, 0x0000 }, /* R693 */
+ { 0x0000, 0x0000 }, /* R694 */
+ { 0x0000, 0x0000 }, /* R695 */
+ { 0x0000, 0x0000 }, /* R696 */
+ { 0x0000, 0x0000 }, /* R697 */
+ { 0x0000, 0x0000 }, /* R698 */
+ { 0x0000, 0x0000 }, /* R699 */
+ { 0x0000, 0x0000 }, /* R700 */
+ { 0x0000, 0x0000 }, /* R701 */
+ { 0x0000, 0x0000 }, /* R702 */
+ { 0x0000, 0x0000 }, /* R703 */
+ { 0x0000, 0x0000 }, /* R704 */
+ { 0x0000, 0x0000 }, /* R705 */
+ { 0x0000, 0x0000 }, /* R706 */
+ { 0x0000, 0x0000 }, /* R707 */
+ { 0x0000, 0x0000 }, /* R708 */
+ { 0x0000, 0x0000 }, /* R709 */
+ { 0x0000, 0x0000 }, /* R710 */
+ { 0x0000, 0x0000 }, /* R711 */
+ { 0x0000, 0x0000 }, /* R712 */
+ { 0x0000, 0x0000 }, /* R713 */
+ { 0x0000, 0x0000 }, /* R714 */
+ { 0x0000, 0x0000 }, /* R715 */
+ { 0x0000, 0x0000 }, /* R716 */
+ { 0x0000, 0x0000 }, /* R717 */
+ { 0x0000, 0x0000 }, /* R718 */
+ { 0x0000, 0x0000 }, /* R719 */
+ { 0x0000, 0x0000 }, /* R720 */
+ { 0x0000, 0x0000 }, /* R721 */
+ { 0x0000, 0x0000 }, /* R722 */
+ { 0x0000, 0x0000 }, /* R723 */
+ { 0x0000, 0x0000 }, /* R724 */
+ { 0x0000, 0x0000 }, /* R725 */
+ { 0x0000, 0x0000 }, /* R726 */
+ { 0x0000, 0x0000 }, /* R727 */
+ { 0x0000, 0x0000 }, /* R728 */
+ { 0x0000, 0x0000 }, /* R729 */
+ { 0x0000, 0x0000 }, /* R730 */
+ { 0x0000, 0x0000 }, /* R731 */
+ { 0x0000, 0x0000 }, /* R732 */
+ { 0x0000, 0x0000 }, /* R733 */
+ { 0x0000, 0x0000 }, /* R734 */
+ { 0x0000, 0x0000 }, /* R735 */
+ { 0x0000, 0x0000 }, /* R736 */
+ { 0x0000, 0x0000 }, /* R737 */
+ { 0x0000, 0x0000 }, /* R738 */
+ { 0x0000, 0x0000 }, /* R739 */
+ { 0x0000, 0x0000 }, /* R740 */
+ { 0x0000, 0x0000 }, /* R741 */
+ { 0x0000, 0x0000 }, /* R742 */
+ { 0x0000, 0x0000 }, /* R743 */
+ { 0x0000, 0x0000 }, /* R744 */
+ { 0x0000, 0x0000 }, /* R745 */
+ { 0x0000, 0x0000 }, /* R746 */
+ { 0x0000, 0x0000 }, /* R747 */
+ { 0x0000, 0x0000 }, /* R748 */
+ { 0x0000, 0x0000 }, /* R749 */
+ { 0x0000, 0x0000 }, /* R750 */
+ { 0x0000, 0x0000 }, /* R751 */
+ { 0x0000, 0x0000 }, /* R752 */
+ { 0x0000, 0x0000 }, /* R753 */
+ { 0x0000, 0x0000 }, /* R754 */
+ { 0x0000, 0x0000 }, /* R755 */
+ { 0x0000, 0x0000 }, /* R756 */
+ { 0x0000, 0x0000 }, /* R757 */
+ { 0x0000, 0x0000 }, /* R758 */
+ { 0x0000, 0x0000 }, /* R759 */
+ { 0x0000, 0x0000 }, /* R760 */
+ { 0x0000, 0x0000 }, /* R761 */
+ { 0x0000, 0x0000 }, /* R762 */
+ { 0x0000, 0x0000 }, /* R763 */
+ { 0x0000, 0x0000 }, /* R764 */
+ { 0x0000, 0x0000 }, /* R765 */
+ { 0x0000, 0x0000 }, /* R766 */
+ { 0x0000, 0x0000 }, /* R767 */
+ { 0xE1F8, 0xE1F8 }, /* R768 - AIF1 Control (1) */
+ { 0xCD1F, 0xCD1F }, /* R769 - AIF1 Control (2) */
+ { 0xF000, 0xF000 }, /* R770 - AIF1 Master/Slave */
+ { 0x01F0, 0x01F0 }, /* R771 - AIF1 BCLK */
+ { 0x0FFF, 0x0FFF }, /* R772 - AIF1ADC LRCLK */
+ { 0x0FFF, 0x0FFF }, /* R773 - AIF1DAC LRCLK */
+ { 0x0003, 0x0003 }, /* R774 - AIF1DAC Data */
+ { 0x0003, 0x0003 }, /* R775 - AIF1ADC Data */
+ { 0x0000, 0x0000 }, /* R776 */
+ { 0x0000, 0x0000 }, /* R777 */
+ { 0x0000, 0x0000 }, /* R778 */
+ { 0x0000, 0x0000 }, /* R779 */
+ { 0x0000, 0x0000 }, /* R780 */
+ { 0x0000, 0x0000 }, /* R781 */
+ { 0x0000, 0x0000 }, /* R782 */
+ { 0x0000, 0x0000 }, /* R783 */
+ { 0xF1F8, 0xF1F8 }, /* R784 - AIF2 Control (1) */
+ { 0xFD1F, 0xFD1F }, /* R785 - AIF2 Control (2) */
+ { 0xF000, 0xF000 }, /* R786 - AIF2 Master/Slave */
+ { 0x01F0, 0x01F0 }, /* R787 - AIF2 BCLK */
+ { 0x0FFF, 0x0FFF }, /* R788 - AIF2ADC LRCLK */
+ { 0x0FFF, 0x0FFF }, /* R789 - AIF2DAC LRCLK */
+ { 0x0003, 0x0003 }, /* R790 - AIF2DAC Data */
+ { 0x0003, 0x0003 }, /* R791 - AIF2ADC Data */
+ { 0x0000, 0x0000 }, /* R792 */
+ { 0x0000, 0x0000 }, /* R793 */
+ { 0x0000, 0x0000 }, /* R794 */
+ { 0x0000, 0x0000 }, /* R795 */
+ { 0x0000, 0x0000 }, /* R796 */
+ { 0x0000, 0x0000 }, /* R797 */
+ { 0x0000, 0x0000 }, /* R798 */
+ { 0x0000, 0x0000 }, /* R799 */
+ { 0x0000, 0x0000 }, /* R800 */
+ { 0x0000, 0x0000 }, /* R801 */
+ { 0x0000, 0x0000 }, /* R802 */
+ { 0x0000, 0x0000 }, /* R803 */
+ { 0x0000, 0x0000 }, /* R804 */
+ { 0x0000, 0x0000 }, /* R805 */
+ { 0x0000, 0x0000 }, /* R806 */
+ { 0x0000, 0x0000 }, /* R807 */
+ { 0x0000, 0x0000 }, /* R808 */
+ { 0x0000, 0x0000 }, /* R809 */
+ { 0x0000, 0x0000 }, /* R810 */
+ { 0x0000, 0x0000 }, /* R811 */
+ { 0x0000, 0x0000 }, /* R812 */
+ { 0x0000, 0x0000 }, /* R813 */
+ { 0x0000, 0x0000 }, /* R814 */
+ { 0x0000, 0x0000 }, /* R815 */
+ { 0x0000, 0x0000 }, /* R816 */
+ { 0x0000, 0x0000 }, /* R817 */
+ { 0x0000, 0x0000 }, /* R818 */
+ { 0x0000, 0x0000 }, /* R819 */
+ { 0x0000, 0x0000 }, /* R820 */
+ { 0x0000, 0x0000 }, /* R821 */
+ { 0x0000, 0x0000 }, /* R822 */
+ { 0x0000, 0x0000 }, /* R823 */
+ { 0x0000, 0x0000 }, /* R824 */
+ { 0x0000, 0x0000 }, /* R825 */
+ { 0x0000, 0x0000 }, /* R826 */
+ { 0x0000, 0x0000 }, /* R827 */
+ { 0x0000, 0x0000 }, /* R828 */
+ { 0x0000, 0x0000 }, /* R829 */
+ { 0x0000, 0x0000 }, /* R830 */
+ { 0x0000, 0x0000 }, /* R831 */
+ { 0x0000, 0x0000 }, /* R832 */
+ { 0x0000, 0x0000 }, /* R833 */
+ { 0x0000, 0x0000 }, /* R834 */
+ { 0x0000, 0x0000 }, /* R835 */
+ { 0x0000, 0x0000 }, /* R836 */
+ { 0x0000, 0x0000 }, /* R837 */
+ { 0x0000, 0x0000 }, /* R838 */
+ { 0x0000, 0x0000 }, /* R839 */
+ { 0x0000, 0x0000 }, /* R840 */
+ { 0x0000, 0x0000 }, /* R841 */
+ { 0x0000, 0x0000 }, /* R842 */
+ { 0x0000, 0x0000 }, /* R843 */
+ { 0x0000, 0x0000 }, /* R844 */
+ { 0x0000, 0x0000 }, /* R845 */
+ { 0x0000, 0x0000 }, /* R846 */
+ { 0x0000, 0x0000 }, /* R847 */
+ { 0x0000, 0x0000 }, /* R848 */
+ { 0x0000, 0x0000 }, /* R849 */
+ { 0x0000, 0x0000 }, /* R850 */
+ { 0x0000, 0x0000 }, /* R851 */
+ { 0x0000, 0x0000 }, /* R852 */
+ { 0x0000, 0x0000 }, /* R853 */
+ { 0x0000, 0x0000 }, /* R854 */
+ { 0x0000, 0x0000 }, /* R855 */
+ { 0x0000, 0x0000 }, /* R856 */
+ { 0x0000, 0x0000 }, /* R857 */
+ { 0x0000, 0x0000 }, /* R858 */
+ { 0x0000, 0x0000 }, /* R859 */
+ { 0x0000, 0x0000 }, /* R860 */
+ { 0x0000, 0x0000 }, /* R861 */
+ { 0x0000, 0x0000 }, /* R862 */
+ { 0x0000, 0x0000 }, /* R863 */
+ { 0x0000, 0x0000 }, /* R864 */
+ { 0x0000, 0x0000 }, /* R865 */
+ { 0x0000, 0x0000 }, /* R866 */
+ { 0x0000, 0x0000 }, /* R867 */
+ { 0x0000, 0x0000 }, /* R868 */
+ { 0x0000, 0x0000 }, /* R869 */
+ { 0x0000, 0x0000 }, /* R870 */
+ { 0x0000, 0x0000 }, /* R871 */
+ { 0x0000, 0x0000 }, /* R872 */
+ { 0x0000, 0x0000 }, /* R873 */
+ { 0x0000, 0x0000 }, /* R874 */
+ { 0x0000, 0x0000 }, /* R875 */
+ { 0x0000, 0x0000 }, /* R876 */
+ { 0x0000, 0x0000 }, /* R877 */
+ { 0x0000, 0x0000 }, /* R878 */
+ { 0x0000, 0x0000 }, /* R879 */
+ { 0x0000, 0x0000 }, /* R880 */
+ { 0x0000, 0x0000 }, /* R881 */
+ { 0x0000, 0x0000 }, /* R882 */
+ { 0x0000, 0x0000 }, /* R883 */
+ { 0x0000, 0x0000 }, /* R884 */
+ { 0x0000, 0x0000 }, /* R885 */
+ { 0x0000, 0x0000 }, /* R886 */
+ { 0x0000, 0x0000 }, /* R887 */
+ { 0x0000, 0x0000 }, /* R888 */
+ { 0x0000, 0x0000 }, /* R889 */
+ { 0x0000, 0x0000 }, /* R890 */
+ { 0x0000, 0x0000 }, /* R891 */
+ { 0x0000, 0x0000 }, /* R892 */
+ { 0x0000, 0x0000 }, /* R893 */
+ { 0x0000, 0x0000 }, /* R894 */
+ { 0x0000, 0x0000 }, /* R895 */
+ { 0x0000, 0x0000 }, /* R896 */
+ { 0x0000, 0x0000 }, /* R897 */
+ { 0x0000, 0x0000 }, /* R898 */
+ { 0x0000, 0x0000 }, /* R899 */
+ { 0x0000, 0x0000 }, /* R900 */
+ { 0x0000, 0x0000 }, /* R901 */
+ { 0x0000, 0x0000 }, /* R902 */
+ { 0x0000, 0x0000 }, /* R903 */
+ { 0x0000, 0x0000 }, /* R904 */
+ { 0x0000, 0x0000 }, /* R905 */
+ { 0x0000, 0x0000 }, /* R906 */
+ { 0x0000, 0x0000 }, /* R907 */
+ { 0x0000, 0x0000 }, /* R908 */
+ { 0x0000, 0x0000 }, /* R909 */
+ { 0x0000, 0x0000 }, /* R910 */
+ { 0x0000, 0x0000 }, /* R911 */
+ { 0x0000, 0x0000 }, /* R912 */
+ { 0x0000, 0x0000 }, /* R913 */
+ { 0x0000, 0x0000 }, /* R914 */
+ { 0x0000, 0x0000 }, /* R915 */
+ { 0x0000, 0x0000 }, /* R916 */
+ { 0x0000, 0x0000 }, /* R917 */
+ { 0x0000, 0x0000 }, /* R918 */
+ { 0x0000, 0x0000 }, /* R919 */
+ { 0x0000, 0x0000 }, /* R920 */
+ { 0x0000, 0x0000 }, /* R921 */
+ { 0x0000, 0x0000 }, /* R922 */
+ { 0x0000, 0x0000 }, /* R923 */
+ { 0x0000, 0x0000 }, /* R924 */
+ { 0x0000, 0x0000 }, /* R925 */
+ { 0x0000, 0x0000 }, /* R926 */
+ { 0x0000, 0x0000 }, /* R927 */
+ { 0x0000, 0x0000 }, /* R928 */
+ { 0x0000, 0x0000 }, /* R929 */
+ { 0x0000, 0x0000 }, /* R930 */
+ { 0x0000, 0x0000 }, /* R931 */
+ { 0x0000, 0x0000 }, /* R932 */
+ { 0x0000, 0x0000 }, /* R933 */
+ { 0x0000, 0x0000 }, /* R934 */
+ { 0x0000, 0x0000 }, /* R935 */
+ { 0x0000, 0x0000 }, /* R936 */
+ { 0x0000, 0x0000 }, /* R937 */
+ { 0x0000, 0x0000 }, /* R938 */
+ { 0x0000, 0x0000 }, /* R939 */
+ { 0x0000, 0x0000 }, /* R940 */
+ { 0x0000, 0x0000 }, /* R941 */
+ { 0x0000, 0x0000 }, /* R942 */
+ { 0x0000, 0x0000 }, /* R943 */
+ { 0x0000, 0x0000 }, /* R944 */
+ { 0x0000, 0x0000 }, /* R945 */
+ { 0x0000, 0x0000 }, /* R946 */
+ { 0x0000, 0x0000 }, /* R947 */
+ { 0x0000, 0x0000 }, /* R948 */
+ { 0x0000, 0x0000 }, /* R949 */
+ { 0x0000, 0x0000 }, /* R950 */
+ { 0x0000, 0x0000 }, /* R951 */
+ { 0x0000, 0x0000 }, /* R952 */
+ { 0x0000, 0x0000 }, /* R953 */
+ { 0x0000, 0x0000 }, /* R954 */
+ { 0x0000, 0x0000 }, /* R955 */
+ { 0x0000, 0x0000 }, /* R956 */
+ { 0x0000, 0x0000 }, /* R957 */
+ { 0x0000, 0x0000 }, /* R958 */
+ { 0x0000, 0x0000 }, /* R959 */
+ { 0x0000, 0x0000 }, /* R960 */
+ { 0x0000, 0x0000 }, /* R961 */
+ { 0x0000, 0x0000 }, /* R962 */
+ { 0x0000, 0x0000 }, /* R963 */
+ { 0x0000, 0x0000 }, /* R964 */
+ { 0x0000, 0x0000 }, /* R965 */
+ { 0x0000, 0x0000 }, /* R966 */
+ { 0x0000, 0x0000 }, /* R967 */
+ { 0x0000, 0x0000 }, /* R968 */
+ { 0x0000, 0x0000 }, /* R969 */
+ { 0x0000, 0x0000 }, /* R970 */
+ { 0x0000, 0x0000 }, /* R971 */
+ { 0x0000, 0x0000 }, /* R972 */
+ { 0x0000, 0x0000 }, /* R973 */
+ { 0x0000, 0x0000 }, /* R974 */
+ { 0x0000, 0x0000 }, /* R975 */
+ { 0x0000, 0x0000 }, /* R976 */
+ { 0x0000, 0x0000 }, /* R977 */
+ { 0x0000, 0x0000 }, /* R978 */
+ { 0x0000, 0x0000 }, /* R979 */
+ { 0x0000, 0x0000 }, /* R980 */
+ { 0x0000, 0x0000 }, /* R981 */
+ { 0x0000, 0x0000 }, /* R982 */
+ { 0x0000, 0x0000 }, /* R983 */
+ { 0x0000, 0x0000 }, /* R984 */
+ { 0x0000, 0x0000 }, /* R985 */
+ { 0x0000, 0x0000 }, /* R986 */
+ { 0x0000, 0x0000 }, /* R987 */
+ { 0x0000, 0x0000 }, /* R988 */
+ { 0x0000, 0x0000 }, /* R989 */
+ { 0x0000, 0x0000 }, /* R990 */
+ { 0x0000, 0x0000 }, /* R991 */
+ { 0x0000, 0x0000 }, /* R992 */
+ { 0x0000, 0x0000 }, /* R993 */
+ { 0x0000, 0x0000 }, /* R994 */
+ { 0x0000, 0x0000 }, /* R995 */
+ { 0x0000, 0x0000 }, /* R996 */
+ { 0x0000, 0x0000 }, /* R997 */
+ { 0x0000, 0x0000 }, /* R998 */
+ { 0x0000, 0x0000 }, /* R999 */
+ { 0x0000, 0x0000 }, /* R1000 */
+ { 0x0000, 0x0000 }, /* R1001 */
+ { 0x0000, 0x0000 }, /* R1002 */
+ { 0x0000, 0x0000 }, /* R1003 */
+ { 0x0000, 0x0000 }, /* R1004 */
+ { 0x0000, 0x0000 }, /* R1005 */
+ { 0x0000, 0x0000 }, /* R1006 */
+ { 0x0000, 0x0000 }, /* R1007 */
+ { 0x0000, 0x0000 }, /* R1008 */
+ { 0x0000, 0x0000 }, /* R1009 */
+ { 0x0000, 0x0000 }, /* R1010 */
+ { 0x0000, 0x0000 }, /* R1011 */
+ { 0x0000, 0x0000 }, /* R1012 */
+ { 0x0000, 0x0000 }, /* R1013 */
+ { 0x0000, 0x0000 }, /* R1014 */
+ { 0x0000, 0x0000 }, /* R1015 */
+ { 0x0000, 0x0000 }, /* R1016 */
+ { 0x0000, 0x0000 }, /* R1017 */
+ { 0x0000, 0x0000 }, /* R1018 */
+ { 0x0000, 0x0000 }, /* R1019 */
+ { 0x0000, 0x0000 }, /* R1020 */
+ { 0x0000, 0x0000 }, /* R1021 */
+ { 0x0000, 0x0000 }, /* R1022 */
+ { 0x0000, 0x0000 }, /* R1023 */
+ { 0x00FF, 0x01FF }, /* R1024 - AIF1 ADC1 Left Volume */
+ { 0x00FF, 0x01FF }, /* R1025 - AIF1 ADC1 Right Volume */
+ { 0x00FF, 0x01FF }, /* R1026 - AIF1 DAC1 Left Volume */
+ { 0x00FF, 0x01FF }, /* R1027 - AIF1 DAC1 Right Volume */
+ { 0x00FF, 0x01FF }, /* R1028 - AIF1 ADC2 Left Volume */
+ { 0x00FF, 0x01FF }, /* R1029 - AIF1 ADC2 Right Volume */
+ { 0x00FF, 0x01FF }, /* R1030 - AIF1 DAC2 Left Volume */
+ { 0x00FF, 0x01FF }, /* R1031 - AIF1 DAC2 Right Volume */
+ { 0x0000, 0x0000 }, /* R1032 */
+ { 0x0000, 0x0000 }, /* R1033 */
+ { 0x0000, 0x0000 }, /* R1034 */
+ { 0x0000, 0x0000 }, /* R1035 */
+ { 0x0000, 0x0000 }, /* R1036 */
+ { 0x0000, 0x0000 }, /* R1037 */
+ { 0x0000, 0x0000 }, /* R1038 */
+ { 0x0000, 0x0000 }, /* R1039 */
+ { 0xF800, 0xF800 }, /* R1040 - AIF1 ADC1 Filters */
+ { 0x7800, 0x7800 }, /* R1041 - AIF1 ADC2 Filters */
+ { 0x0000, 0x0000 }, /* R1042 */
+ { 0x0000, 0x0000 }, /* R1043 */
+ { 0x0000, 0x0000 }, /* R1044 */
+ { 0x0000, 0x0000 }, /* R1045 */
+ { 0x0000, 0x0000 }, /* R1046 */
+ { 0x0000, 0x0000 }, /* R1047 */
+ { 0x0000, 0x0000 }, /* R1048 */
+ { 0x0000, 0x0000 }, /* R1049 */
+ { 0x0000, 0x0000 }, /* R1050 */
+ { 0x0000, 0x0000 }, /* R1051 */
+ { 0x0000, 0x0000 }, /* R1052 */
+ { 0x0000, 0x0000 }, /* R1053 */
+ { 0x0000, 0x0000 }, /* R1054 */
+ { 0x0000, 0x0000 }, /* R1055 */
+ { 0x02B6, 0x02B6 }, /* R1056 - AIF1 DAC1 Filters (1) */
+ { 0x3F00, 0x3F00 }, /* R1057 - AIF1 DAC1 Filters (2) */
+ { 0x02B6, 0x02B6 }, /* R1058 - AIF1 DAC2 Filters (1) */
+ { 0x3F00, 0x3F00 }, /* R1059 - AIF1 DAC2 Filters (2) */
+ { 0x0000, 0x0000 }, /* R1060 */
+ { 0x0000, 0x0000 }, /* R1061 */
+ { 0x0000, 0x0000 }, /* R1062 */
+ { 0x0000, 0x0000 }, /* R1063 */
+ { 0x0000, 0x0000 }, /* R1064 */
+ { 0x0000, 0x0000 }, /* R1065 */
+ { 0x0000, 0x0000 }, /* R1066 */
+ { 0x0000, 0x0000 }, /* R1067 */
+ { 0x0000, 0x0000 }, /* R1068 */
+ { 0x0000, 0x0000 }, /* R1069 */
+ { 0x0000, 0x0000 }, /* R1070 */
+ { 0x0000, 0x0000 }, /* R1071 */
+ { 0x0000, 0x0000 }, /* R1072 */
+ { 0x0000, 0x0000 }, /* R1073 */
+ { 0x0000, 0x0000 }, /* R1074 */
+ { 0x0000, 0x0000 }, /* R1075 */
+ { 0x0000, 0x0000 }, /* R1076 */
+ { 0x0000, 0x0000 }, /* R1077 */
+ { 0x0000, 0x0000 }, /* R1078 */
+ { 0x0000, 0x0000 }, /* R1079 */
+ { 0x0000, 0x0000 }, /* R1080 */
+ { 0x0000, 0x0000 }, /* R1081 */
+ { 0x0000, 0x0000 }, /* R1082 */
+ { 0x0000, 0x0000 }, /* R1083 */
+ { 0x0000, 0x0000 }, /* R1084 */
+ { 0x0000, 0x0000 }, /* R1085 */
+ { 0x0000, 0x0000 }, /* R1086 */
+ { 0x0000, 0x0000 }, /* R1087 */
+ { 0xFFFF, 0xFFFF }, /* R1088 - AIF1 DRC1 (1) */
+ { 0x1FFF, 0x1FFF }, /* R1089 - AIF1 DRC1 (2) */
+ { 0xFFFF, 0xFFFF }, /* R1090 - AIF1 DRC1 (3) */
+ { 0x07FF, 0x07FF }, /* R1091 - AIF1 DRC1 (4) */
+ { 0x03FF, 0x03FF }, /* R1092 - AIF1 DRC1 (5) */
+ { 0x0000, 0x0000 }, /* R1093 */
+ { 0x0000, 0x0000 }, /* R1094 */
+ { 0x0000, 0x0000 }, /* R1095 */
+ { 0x0000, 0x0000 }, /* R1096 */
+ { 0x0000, 0x0000 }, /* R1097 */
+ { 0x0000, 0x0000 }, /* R1098 */
+ { 0x0000, 0x0000 }, /* R1099 */
+ { 0x0000, 0x0000 }, /* R1100 */
+ { 0x0000, 0x0000 }, /* R1101 */
+ { 0x0000, 0x0000 }, /* R1102 */
+ { 0x0000, 0x0000 }, /* R1103 */
+ { 0xFFFF, 0xFFFF }, /* R1104 - AIF1 DRC2 (1) */
+ { 0x1FFF, 0x1FFF }, /* R1105 - AIF1 DRC2 (2) */
+ { 0xFFFF, 0xFFFF }, /* R1106 - AIF1 DRC2 (3) */
+ { 0x07FF, 0x07FF }, /* R1107 - AIF1 DRC2 (4) */
+ { 0x03FF, 0x03FF }, /* R1108 - AIF1 DRC2 (5) */
+ { 0x0000, 0x0000 }, /* R1109 */
+ { 0x0000, 0x0000 }, /* R1110 */
+ { 0x0000, 0x0000 }, /* R1111 */
+ { 0x0000, 0x0000 }, /* R1112 */
+ { 0x0000, 0x0000 }, /* R1113 */
+ { 0x0000, 0x0000 }, /* R1114 */
+ { 0x0000, 0x0000 }, /* R1115 */
+ { 0x0000, 0x0000 }, /* R1116 */
+ { 0x0000, 0x0000 }, /* R1117 */
+ { 0x0000, 0x0000 }, /* R1118 */
+ { 0x0000, 0x0000 }, /* R1119 */
+ { 0x0000, 0x0000 }, /* R1120 */
+ { 0x0000, 0x0000 }, /* R1121 */
+ { 0x0000, 0x0000 }, /* R1122 */
+ { 0x0000, 0x0000 }, /* R1123 */
+ { 0x0000, 0x0000 }, /* R1124 */
+ { 0x0000, 0x0000 }, /* R1125 */
+ { 0x0000, 0x0000 }, /* R1126 */
+ { 0x0000, 0x0000 }, /* R1127 */
+ { 0x0000, 0x0000 }, /* R1128 */
+ { 0x0000, 0x0000 }, /* R1129 */
+ { 0x0000, 0x0000 }, /* R1130 */
+ { 0x0000, 0x0000 }, /* R1131 */
+ { 0x0000, 0x0000 }, /* R1132 */
+ { 0x0000, 0x0000 }, /* R1133 */
+ { 0x0000, 0x0000 }, /* R1134 */
+ { 0x0000, 0x0000 }, /* R1135 */
+ { 0x0000, 0x0000 }, /* R1136 */
+ { 0x0000, 0x0000 }, /* R1137 */
+ { 0x0000, 0x0000 }, /* R1138 */
+ { 0x0000, 0x0000 }, /* R1139 */
+ { 0x0000, 0x0000 }, /* R1140 */
+ { 0x0000, 0x0000 }, /* R1141 */
+ { 0x0000, 0x0000 }, /* R1142 */
+ { 0x0000, 0x0000 }, /* R1143 */
+ { 0x0000, 0x0000 }, /* R1144 */
+ { 0x0000, 0x0000 }, /* R1145 */
+ { 0x0000, 0x0000 }, /* R1146 */
+ { 0x0000, 0x0000 }, /* R1147 */
+ { 0x0000, 0x0000 }, /* R1148 */
+ { 0x0000, 0x0000 }, /* R1149 */
+ { 0x0000, 0x0000 }, /* R1150 */
+ { 0x0000, 0x0000 }, /* R1151 */
+ { 0xFFFF, 0xFFFF }, /* R1152 - AIF1 DAC1 EQ Gains (1) */
+ { 0xFFC0, 0xFFC0 }, /* R1153 - AIF1 DAC1 EQ Gains (2) */
+ { 0xFFFF, 0xFFFF }, /* R1154 - AIF1 DAC1 EQ Band 1 A */
+ { 0xFFFF, 0xFFFF }, /* R1155 - AIF1 DAC1 EQ Band 1 B */
+ { 0xFFFF, 0xFFFF }, /* R1156 - AIF1 DAC1 EQ Band 1 PG */
+ { 0xFFFF, 0xFFFF }, /* R1157 - AIF1 DAC1 EQ Band 2 A */
+ { 0xFFFF, 0xFFFF }, /* R1158 - AIF1 DAC1 EQ Band 2 B */
+ { 0xFFFF, 0xFFFF }, /* R1159 - AIF1 DAC1 EQ Band 2 C */
+ { 0xFFFF, 0xFFFF }, /* R1160 - AIF1 DAC1 EQ Band 2 PG */
+ { 0xFFFF, 0xFFFF }, /* R1161 - AIF1 DAC1 EQ Band 3 A */
+ { 0xFFFF, 0xFFFF }, /* R1162 - AIF1 DAC1 EQ Band 3 B */
+ { 0xFFFF, 0xFFFF }, /* R1163 - AIF1 DAC1 EQ Band 3 C */
+ { 0xFFFF, 0xFFFF }, /* R1164 - AIF1 DAC1 EQ Band 3 PG */
+ { 0xFFFF, 0xFFFF }, /* R1165 - AIF1 DAC1 EQ Band 4 A */
+ { 0xFFFF, 0xFFFF }, /* R1166 - AIF1 DAC1 EQ Band 4 B */
+ { 0xFFFF, 0xFFFF }, /* R1167 - AIF1 DAC1 EQ Band 4 C */
+ { 0xFFFF, 0xFFFF }, /* R1168 - AIF1 DAC1 EQ Band 4 PG */
+ { 0xFFFF, 0xFFFF }, /* R1169 - AIF1 DAC1 EQ Band 5 A */
+ { 0xFFFF, 0xFFFF }, /* R1170 - AIF1 DAC1 EQ Band 5 B */
+ { 0xFFFF, 0xFFFF }, /* R1171 - AIF1 DAC1 EQ Band 5 PG */
+ { 0x0000, 0x0000 }, /* R1172 */
+ { 0x0000, 0x0000 }, /* R1173 */
+ { 0x0000, 0x0000 }, /* R1174 */
+ { 0x0000, 0x0000 }, /* R1175 */
+ { 0x0000, 0x0000 }, /* R1176 */
+ { 0x0000, 0x0000 }, /* R1177 */
+ { 0x0000, 0x0000 }, /* R1178 */
+ { 0x0000, 0x0000 }, /* R1179 */
+ { 0x0000, 0x0000 }, /* R1180 */
+ { 0x0000, 0x0000 }, /* R1181 */
+ { 0x0000, 0x0000 }, /* R1182 */
+ { 0x0000, 0x0000 }, /* R1183 */
+ { 0xFFFF, 0xFFFF }, /* R1184 - AIF1 DAC2 EQ Gains (1) */
+ { 0xFFC0, 0xFFC0 }, /* R1185 - AIF1 DAC2 EQ Gains (2) */
+ { 0xFFFF, 0xFFFF }, /* R1186 - AIF1 DAC2 EQ Band 1 A */
+ { 0xFFFF, 0xFFFF }, /* R1187 - AIF1 DAC2 EQ Band 1 B */
+ { 0xFFFF, 0xFFFF }, /* R1188 - AIF1 DAC2 EQ Band 1 PG */
+ { 0xFFFF, 0xFFFF }, /* R1189 - AIF1 DAC2 EQ Band 2 A */
+ { 0xFFFF, 0xFFFF }, /* R1190 - AIF1 DAC2 EQ Band 2 B */
+ { 0xFFFF, 0xFFFF }, /* R1191 - AIF1 DAC2 EQ Band 2 C */
+ { 0xFFFF, 0xFFFF }, /* R1192 - AIF1 DAC2 EQ Band 2 PG */
+ { 0xFFFF, 0xFFFF }, /* R1193 - AIF1 DAC2 EQ Band 3 A */
+ { 0xFFFF, 0xFFFF }, /* R1194 - AIF1 DAC2 EQ Band 3 B */
+ { 0xFFFF, 0xFFFF }, /* R1195 - AIF1 DAC2 EQ Band 3 C */
+ { 0xFFFF, 0xFFFF }, /* R1196 - AIF1 DAC2 EQ Band 3 PG */
+ { 0xFFFF, 0xFFFF }, /* R1197 - AIF1 DAC2 EQ Band 4 A */
+ { 0xFFFF, 0xFFFF }, /* R1198 - AIF1 DAC2 EQ Band 4 B */
+ { 0xFFFF, 0xFFFF }, /* R1199 - AIF1 DAC2 EQ Band 4 C */
+ { 0xFFFF, 0xFFFF }, /* R1200 - AIF1 DAC2 EQ Band 4 PG */
+ { 0xFFFF, 0xFFFF }, /* R1201 - AIF1 DAC2 EQ Band 5 A */
+ { 0xFFFF, 0xFFFF }, /* R1202 - AIF1 DAC2 EQ Band 5 B */
+ { 0xFFFF, 0xFFFF }, /* R1203 - AIF1 DAC2 EQ Band 5 PG */
+ { 0x0000, 0x0000 }, /* R1204 */
+ { 0x0000, 0x0000 }, /* R1205 */
+ { 0x0000, 0x0000 }, /* R1206 */
+ { 0x0000, 0x0000 }, /* R1207 */
+ { 0x0000, 0x0000 }, /* R1208 */
+ { 0x0000, 0x0000 }, /* R1209 */
+ { 0x0000, 0x0000 }, /* R1210 */
+ { 0x0000, 0x0000 }, /* R1211 */
+ { 0x0000, 0x0000 }, /* R1212 */
+ { 0x0000, 0x0000 }, /* R1213 */
+ { 0x0000, 0x0000 }, /* R1214 */
+ { 0x0000, 0x0000 }, /* R1215 */
+ { 0x0000, 0x0000 }, /* R1216 */
+ { 0x0000, 0x0000 }, /* R1217 */
+ { 0x0000, 0x0000 }, /* R1218 */
+ { 0x0000, 0x0000 }, /* R1219 */
+ { 0x0000, 0x0000 }, /* R1220 */
+ { 0x0000, 0x0000 }, /* R1221 */
+ { 0x0000, 0x0000 }, /* R1222 */
+ { 0x0000, 0x0000 }, /* R1223 */
+ { 0x0000, 0x0000 }, /* R1224 */
+ { 0x0000, 0x0000 }, /* R1225 */
+ { 0x0000, 0x0000 }, /* R1226 */
+ { 0x0000, 0x0000 }, /* R1227 */
+ { 0x0000, 0x0000 }, /* R1228 */
+ { 0x0000, 0x0000 }, /* R1229 */
+ { 0x0000, 0x0000 }, /* R1230 */
+ { 0x0000, 0x0000 }, /* R1231 */
+ { 0x0000, 0x0000 }, /* R1232 */
+ { 0x0000, 0x0000 }, /* R1233 */
+ { 0x0000, 0x0000 }, /* R1234 */
+ { 0x0000, 0x0000 }, /* R1235 */
+ { 0x0000, 0x0000 }, /* R1236 */
+ { 0x0000, 0x0000 }, /* R1237 */
+ { 0x0000, 0x0000 }, /* R1238 */
+ { 0x0000, 0x0000 }, /* R1239 */
+ { 0x0000, 0x0000 }, /* R1240 */
+ { 0x0000, 0x0000 }, /* R1241 */
+ { 0x0000, 0x0000 }, /* R1242 */
+ { 0x0000, 0x0000 }, /* R1243 */
+ { 0x0000, 0x0000 }, /* R1244 */
+ { 0x0000, 0x0000 }, /* R1245 */
+ { 0x0000, 0x0000 }, /* R1246 */
+ { 0x0000, 0x0000 }, /* R1247 */
+ { 0x0000, 0x0000 }, /* R1248 */
+ { 0x0000, 0x0000 }, /* R1249 */
+ { 0x0000, 0x0000 }, /* R1250 */
+ { 0x0000, 0x0000 }, /* R1251 */
+ { 0x0000, 0x0000 }, /* R1252 */
+ { 0x0000, 0x0000 }, /* R1253 */
+ { 0x0000, 0x0000 }, /* R1254 */
+ { 0x0000, 0x0000 }, /* R1255 */
+ { 0x0000, 0x0000 }, /* R1256 */
+ { 0x0000, 0x0000 }, /* R1257 */
+ { 0x0000, 0x0000 }, /* R1258 */
+ { 0x0000, 0x0000 }, /* R1259 */
+ { 0x0000, 0x0000 }, /* R1260 */
+ { 0x0000, 0x0000 }, /* R1261 */
+ { 0x0000, 0x0000 }, /* R1262 */
+ { 0x0000, 0x0000 }, /* R1263 */
+ { 0x0000, 0x0000 }, /* R1264 */
+ { 0x0000, 0x0000 }, /* R1265 */
+ { 0x0000, 0x0000 }, /* R1266 */
+ { 0x0000, 0x0000 }, /* R1267 */
+ { 0x0000, 0x0000 }, /* R1268 */
+ { 0x0000, 0x0000 }, /* R1269 */
+ { 0x0000, 0x0000 }, /* R1270 */
+ { 0x0000, 0x0000 }, /* R1271 */
+ { 0x0000, 0x0000 }, /* R1272 */
+ { 0x0000, 0x0000 }, /* R1273 */
+ { 0x0000, 0x0000 }, /* R1274 */
+ { 0x0000, 0x0000 }, /* R1275 */
+ { 0x0000, 0x0000 }, /* R1276 */
+ { 0x0000, 0x0000 }, /* R1277 */
+ { 0x0000, 0x0000 }, /* R1278 */
+ { 0x0000, 0x0000 }, /* R1279 */
+ { 0x00FF, 0x01FF }, /* R1280 - AIF2 ADC Left Volume */
+ { 0x00FF, 0x01FF }, /* R1281 - AIF2 ADC Right Volume */
+ { 0x00FF, 0x01FF }, /* R1282 - AIF2 DAC Left Volume */
+ { 0x00FF, 0x01FF }, /* R1283 - AIF2 DAC Right Volume */
+ { 0x0000, 0x0000 }, /* R1284 */
+ { 0x0000, 0x0000 }, /* R1285 */
+ { 0x0000, 0x0000 }, /* R1286 */
+ { 0x0000, 0x0000 }, /* R1287 */
+ { 0x0000, 0x0000 }, /* R1288 */
+ { 0x0000, 0x0000 }, /* R1289 */
+ { 0x0000, 0x0000 }, /* R1290 */
+ { 0x0000, 0x0000 }, /* R1291 */
+ { 0x0000, 0x0000 }, /* R1292 */
+ { 0x0000, 0x0000 }, /* R1293 */
+ { 0x0000, 0x0000 }, /* R1294 */
+ { 0x0000, 0x0000 }, /* R1295 */
+ { 0xF800, 0xF800 }, /* R1296 - AIF2 ADC Filters */
+ { 0x0000, 0x0000 }, /* R1297 */
+ { 0x0000, 0x0000 }, /* R1298 */
+ { 0x0000, 0x0000 }, /* R1299 */
+ { 0x0000, 0x0000 }, /* R1300 */
+ { 0x0000, 0x0000 }, /* R1301 */
+ { 0x0000, 0x0000 }, /* R1302 */
+ { 0x0000, 0x0000 }, /* R1303 */
+ { 0x0000, 0x0000 }, /* R1304 */
+ { 0x0000, 0x0000 }, /* R1305 */
+ { 0x0000, 0x0000 }, /* R1306 */
+ { 0x0000, 0x0000 }, /* R1307 */
+ { 0x0000, 0x0000 }, /* R1308 */
+ { 0x0000, 0x0000 }, /* R1309 */
+ { 0x0000, 0x0000 }, /* R1310 */
+ { 0x0000, 0x0000 }, /* R1311 */
+ { 0x02B6, 0x02B6 }, /* R1312 - AIF2 DAC Filters (1) */
+ { 0x3F00, 0x3F00 }, /* R1313 - AIF2 DAC Filters (2) */
+ { 0x0000, 0x0000 }, /* R1314 */
+ { 0x0000, 0x0000 }, /* R1315 */
+ { 0x0000, 0x0000 }, /* R1316 */
+ { 0x0000, 0x0000 }, /* R1317 */
+ { 0x0000, 0x0000 }, /* R1318 */
+ { 0x0000, 0x0000 }, /* R1319 */
+ { 0x0000, 0x0000 }, /* R1320 */
+ { 0x0000, 0x0000 }, /* R1321 */
+ { 0x0000, 0x0000 }, /* R1322 */
+ { 0x0000, 0x0000 }, /* R1323 */
+ { 0x0000, 0x0000 }, /* R1324 */
+ { 0x0000, 0x0000 }, /* R1325 */
+ { 0x0000, 0x0000 }, /* R1326 */
+ { 0x0000, 0x0000 }, /* R1327 */
+ { 0x0000, 0x0000 }, /* R1328 */
+ { 0x0000, 0x0000 }, /* R1329 */
+ { 0x0000, 0x0000 }, /* R1330 */
+ { 0x0000, 0x0000 }, /* R1331 */
+ { 0x0000, 0x0000 }, /* R1332 */
+ { 0x0000, 0x0000 }, /* R1333 */
+ { 0x0000, 0x0000 }, /* R1334 */
+ { 0x0000, 0x0000 }, /* R1335 */
+ { 0x0000, 0x0000 }, /* R1336 */
+ { 0x0000, 0x0000 }, /* R1337 */
+ { 0x0000, 0x0000 }, /* R1338 */
+ { 0x0000, 0x0000 }, /* R1339 */
+ { 0x0000, 0x0000 }, /* R1340 */
+ { 0x0000, 0x0000 }, /* R1341 */
+ { 0x0000, 0x0000 }, /* R1342 */
+ { 0x0000, 0x0000 }, /* R1343 */
+ { 0xFFFF, 0xFFFF }, /* R1344 - AIF2 DRC (1) */
+ { 0x1FFF, 0x1FFF }, /* R1345 - AIF2 DRC (2) */
+ { 0xFFFF, 0xFFFF }, /* R1346 - AIF2 DRC (3) */
+ { 0x07FF, 0x07FF }, /* R1347 - AIF2 DRC (4) */
+ { 0x03FF, 0x03FF }, /* R1348 - AIF2 DRC (5) */
+ { 0x0000, 0x0000 }, /* R1349 */
+ { 0x0000, 0x0000 }, /* R1350 */
+ { 0x0000, 0x0000 }, /* R1351 */
+ { 0x0000, 0x0000 }, /* R1352 */
+ { 0x0000, 0x0000 }, /* R1353 */
+ { 0x0000, 0x0000 }, /* R1354 */
+ { 0x0000, 0x0000 }, /* R1355 */
+ { 0x0000, 0x0000 }, /* R1356 */
+ { 0x0000, 0x0000 }, /* R1357 */
+ { 0x0000, 0x0000 }, /* R1358 */
+ { 0x0000, 0x0000 }, /* R1359 */
+ { 0x0000, 0x0000 }, /* R1360 */
+ { 0x0000, 0x0000 }, /* R1361 */
+ { 0x0000, 0x0000 }, /* R1362 */
+ { 0x0000, 0x0000 }, /* R1363 */
+ { 0x0000, 0x0000 }, /* R1364 */
+ { 0x0000, 0x0000 }, /* R1365 */
+ { 0x0000, 0x0000 }, /* R1366 */
+ { 0x0000, 0x0000 }, /* R1367 */
+ { 0x0000, 0x0000 }, /* R1368 */
+ { 0x0000, 0x0000 }, /* R1369 */
+ { 0x0000, 0x0000 }, /* R1370 */
+ { 0x0000, 0x0000 }, /* R1371 */
+ { 0x0000, 0x0000 }, /* R1372 */
+ { 0x0000, 0x0000 }, /* R1373 */
+ { 0x0000, 0x0000 }, /* R1374 */
+ { 0x0000, 0x0000 }, /* R1375 */
+ { 0x0000, 0x0000 }, /* R1376 */
+ { 0x0000, 0x0000 }, /* R1377 */
+ { 0x0000, 0x0000 }, /* R1378 */
+ { 0x0000, 0x0000 }, /* R1379 */
+ { 0x0000, 0x0000 }, /* R1380 */
+ { 0x0000, 0x0000 }, /* R1381 */
+ { 0x0000, 0x0000 }, /* R1382 */
+ { 0x0000, 0x0000 }, /* R1383 */
+ { 0x0000, 0x0000 }, /* R1384 */
+ { 0x0000, 0x0000 }, /* R1385 */
+ { 0x0000, 0x0000 }, /* R1386 */
+ { 0x0000, 0x0000 }, /* R1387 */
+ { 0x0000, 0x0000 }, /* R1388 */
+ { 0x0000, 0x0000 }, /* R1389 */
+ { 0x0000, 0x0000 }, /* R1390 */
+ { 0x0000, 0x0000 }, /* R1391 */
+ { 0x0000, 0x0000 }, /* R1392 */
+ { 0x0000, 0x0000 }, /* R1393 */
+ { 0x0000, 0x0000 }, /* R1394 */
+ { 0x0000, 0x0000 }, /* R1395 */
+ { 0x0000, 0x0000 }, /* R1396 */
+ { 0x0000, 0x0000 }, /* R1397 */
+ { 0x0000, 0x0000 }, /* R1398 */
+ { 0x0000, 0x0000 }, /* R1399 */
+ { 0x0000, 0x0000 }, /* R1400 */
+ { 0x0000, 0x0000 }, /* R1401 */
+ { 0x0000, 0x0000 }, /* R1402 */
+ { 0x0000, 0x0000 }, /* R1403 */
+ { 0x0000, 0x0000 }, /* R1404 */
+ { 0x0000, 0x0000 }, /* R1405 */
+ { 0x0000, 0x0000 }, /* R1406 */
+ { 0x0000, 0x0000 }, /* R1407 */
+ { 0xFFFF, 0xFFFF }, /* R1408 - AIF2 EQ Gains (1) */
+ { 0xFFC0, 0xFFC0 }, /* R1409 - AIF2 EQ Gains (2) */
+ { 0xFFFF, 0xFFFF }, /* R1410 - AIF2 EQ Band 1 A */
+ { 0xFFFF, 0xFFFF }, /* R1411 - AIF2 EQ Band 1 B */
+ { 0xFFFF, 0xFFFF }, /* R1412 - AIF2 EQ Band 1 PG */
+ { 0xFFFF, 0xFFFF }, /* R1413 - AIF2 EQ Band 2 A */
+ { 0xFFFF, 0xFFFF }, /* R1414 - AIF2 EQ Band 2 B */
+ { 0xFFFF, 0xFFFF }, /* R1415 - AIF2 EQ Band 2 C */
+ { 0xFFFF, 0xFFFF }, /* R1416 - AIF2 EQ Band 2 PG */
+ { 0xFFFF, 0xFFFF }, /* R1417 - AIF2 EQ Band 3 A */
+ { 0xFFFF, 0xFFFF }, /* R1418 - AIF2 EQ Band 3 B */
+ { 0xFFFF, 0xFFFF }, /* R1419 - AIF2 EQ Band 3 C */
+ { 0xFFFF, 0xFFFF }, /* R1420 - AIF2 EQ Band 3 PG */
+ { 0xFFFF, 0xFFFF }, /* R1421 - AIF2 EQ Band 4 A */
+ { 0xFFFF, 0xFFFF }, /* R1422 - AIF2 EQ Band 4 B */
+ { 0xFFFF, 0xFFFF }, /* R1423 - AIF2 EQ Band 4 C */
+ { 0xFFFF, 0xFFFF }, /* R1424 - AIF2 EQ Band 4 PG */
+ { 0xFFFF, 0xFFFF }, /* R1425 - AIF2 EQ Band 5 A */
+ { 0xFFFF, 0xFFFF }, /* R1426 - AIF2 EQ Band 5 B */
+ { 0xFFFF, 0xFFFF }, /* R1427 - AIF2 EQ Band 5 PG */
+ { 0x0000, 0x0000 }, /* R1428 */
+ { 0x0000, 0x0000 }, /* R1429 */
+ { 0x0000, 0x0000 }, /* R1430 */
+ { 0x0000, 0x0000 }, /* R1431 */
+ { 0x0000, 0x0000 }, /* R1432 */
+ { 0x0000, 0x0000 }, /* R1433 */
+ { 0x0000, 0x0000 }, /* R1434 */
+ { 0x0000, 0x0000 }, /* R1435 */
+ { 0x0000, 0x0000 }, /* R1436 */
+ { 0x0000, 0x0000 }, /* R1437 */
+ { 0x0000, 0x0000 }, /* R1438 */
+ { 0x0000, 0x0000 }, /* R1439 */
+ { 0x0000, 0x0000 }, /* R1440 */
+ { 0x0000, 0x0000 }, /* R1441 */
+ { 0x0000, 0x0000 }, /* R1442 */
+ { 0x0000, 0x0000 }, /* R1443 */
+ { 0x0000, 0x0000 }, /* R1444 */
+ { 0x0000, 0x0000 }, /* R1445 */
+ { 0x0000, 0x0000 }, /* R1446 */
+ { 0x0000, 0x0000 }, /* R1447 */
+ { 0x0000, 0x0000 }, /* R1448 */
+ { 0x0000, 0x0000 }, /* R1449 */
+ { 0x0000, 0x0000 }, /* R1450 */
+ { 0x0000, 0x0000 }, /* R1451 */
+ { 0x0000, 0x0000 }, /* R1452 */
+ { 0x0000, 0x0000 }, /* R1453 */
+ { 0x0000, 0x0000 }, /* R1454 */
+ { 0x0000, 0x0000 }, /* R1455 */
+ { 0x0000, 0x0000 }, /* R1456 */
+ { 0x0000, 0x0000 }, /* R1457 */
+ { 0x0000, 0x0000 }, /* R1458 */
+ { 0x0000, 0x0000 }, /* R1459 */
+ { 0x0000, 0x0000 }, /* R1460 */
+ { 0x0000, 0x0000 }, /* R1461 */
+ { 0x0000, 0x0000 }, /* R1462 */
+ { 0x0000, 0x0000 }, /* R1463 */
+ { 0x0000, 0x0000 }, /* R1464 */
+ { 0x0000, 0x0000 }, /* R1465 */
+ { 0x0000, 0x0000 }, /* R1466 */
+ { 0x0000, 0x0000 }, /* R1467 */
+ { 0x0000, 0x0000 }, /* R1468 */
+ { 0x0000, 0x0000 }, /* R1469 */
+ { 0x0000, 0x0000 }, /* R1470 */
+ { 0x0000, 0x0000 }, /* R1471 */
+ { 0x0000, 0x0000 }, /* R1472 */
+ { 0x0000, 0x0000 }, /* R1473 */
+ { 0x0000, 0x0000 }, /* R1474 */
+ { 0x0000, 0x0000 }, /* R1475 */
+ { 0x0000, 0x0000 }, /* R1476 */
+ { 0x0000, 0x0000 }, /* R1477 */
+ { 0x0000, 0x0000 }, /* R1478 */
+ { 0x0000, 0x0000 }, /* R1479 */
+ { 0x0000, 0x0000 }, /* R1480 */
+ { 0x0000, 0x0000 }, /* R1481 */
+ { 0x0000, 0x0000 }, /* R1482 */
+ { 0x0000, 0x0000 }, /* R1483 */
+ { 0x0000, 0x0000 }, /* R1484 */
+ { 0x0000, 0x0000 }, /* R1485 */
+ { 0x0000, 0x0000 }, /* R1486 */
+ { 0x0000, 0x0000 }, /* R1487 */
+ { 0x0000, 0x0000 }, /* R1488 */
+ { 0x0000, 0x0000 }, /* R1489 */
+ { 0x0000, 0x0000 }, /* R1490 */
+ { 0x0000, 0x0000 }, /* R1491 */
+ { 0x0000, 0x0000 }, /* R1492 */
+ { 0x0000, 0x0000 }, /* R1493 */
+ { 0x0000, 0x0000 }, /* R1494 */
+ { 0x0000, 0x0000 }, /* R1495 */
+ { 0x0000, 0x0000 }, /* R1496 */
+ { 0x0000, 0x0000 }, /* R1497 */
+ { 0x0000, 0x0000 }, /* R1498 */
+ { 0x0000, 0x0000 }, /* R1499 */
+ { 0x0000, 0x0000 }, /* R1500 */
+ { 0x0000, 0x0000 }, /* R1501 */
+ { 0x0000, 0x0000 }, /* R1502 */
+ { 0x0000, 0x0000 }, /* R1503 */
+ { 0x0000, 0x0000 }, /* R1504 */
+ { 0x0000, 0x0000 }, /* R1505 */
+ { 0x0000, 0x0000 }, /* R1506 */
+ { 0x0000, 0x0000 }, /* R1507 */
+ { 0x0000, 0x0000 }, /* R1508 */
+ { 0x0000, 0x0000 }, /* R1509 */
+ { 0x0000, 0x0000 }, /* R1510 */
+ { 0x0000, 0x0000 }, /* R1511 */
+ { 0x0000, 0x0000 }, /* R1512 */
+ { 0x0000, 0x0000 }, /* R1513 */
+ { 0x0000, 0x0000 }, /* R1514 */
+ { 0x0000, 0x0000 }, /* R1515 */
+ { 0x0000, 0x0000 }, /* R1516 */
+ { 0x0000, 0x0000 }, /* R1517 */
+ { 0x0000, 0x0000 }, /* R1518 */
+ { 0x0000, 0x0000 }, /* R1519 */
+ { 0x0000, 0x0000 }, /* R1520 */
+ { 0x0000, 0x0000 }, /* R1521 */
+ { 0x0000, 0x0000 }, /* R1522 */
+ { 0x0000, 0x0000 }, /* R1523 */
+ { 0x0000, 0x0000 }, /* R1524 */
+ { 0x0000, 0x0000 }, /* R1525 */
+ { 0x0000, 0x0000 }, /* R1526 */
+ { 0x0000, 0x0000 }, /* R1527 */
+ { 0x0000, 0x0000 }, /* R1528 */
+ { 0x0000, 0x0000 }, /* R1529 */
+ { 0x0000, 0x0000 }, /* R1530 */
+ { 0x0000, 0x0000 }, /* R1531 */
+ { 0x0000, 0x0000 }, /* R1532 */
+ { 0x0000, 0x0000 }, /* R1533 */
+ { 0x0000, 0x0000 }, /* R1534 */
+ { 0x0000, 0x0000 }, /* R1535 */
+ { 0x01EF, 0x01EF }, /* R1536 - DAC1 Mixer Volumes */
+ { 0x0037, 0x0037 }, /* R1537 - DAC1 Left Mixer Routing */
+ { 0x0037, 0x0037 }, /* R1538 - DAC1 Right Mixer Routing */
+ { 0x01EF, 0x01EF }, /* R1539 - DAC2 Mixer Volumes */
+ { 0x0037, 0x0037 }, /* R1540 - DAC2 Left Mixer Routing */
+ { 0x0037, 0x0037 }, /* R1541 - DAC2 Right Mixer Routing */
+ { 0x0003, 0x0003 }, /* R1542 - AIF1 ADC1 Left Mixer Routing */
+ { 0x0003, 0x0003 }, /* R1543 - AIF1 ADC1 Right Mixer Routing */
+ { 0x0003, 0x0003 }, /* R1544 - AIF1 ADC2 Left Mixer Routing */
+ { 0x0003, 0x0003 }, /* R1545 - AIF1 ADC2 Right mixer Routing */
+ { 0x0000, 0x0000 }, /* R1546 */
+ { 0x0000, 0x0000 }, /* R1547 */
+ { 0x0000, 0x0000 }, /* R1548 */
+ { 0x0000, 0x0000 }, /* R1549 */
+ { 0x0000, 0x0000 }, /* R1550 */
+ { 0x0000, 0x0000 }, /* R1551 */
+ { 0x02FF, 0x03FF }, /* R1552 - DAC1 Left Volume */
+ { 0x02FF, 0x03FF }, /* R1553 - DAC1 Right Volume */
+ { 0x02FF, 0x03FF }, /* R1554 - DAC2 Left Volume */
+ { 0x02FF, 0x03FF }, /* R1555 - DAC2 Right Volume */
+ { 0x0003, 0x0003 }, /* R1556 - DAC Softmute */
+ { 0x0000, 0x0000 }, /* R1557 */
+ { 0x0000, 0x0000 }, /* R1558 */
+ { 0x0000, 0x0000 }, /* R1559 */
+ { 0x0000, 0x0000 }, /* R1560 */
+ { 0x0000, 0x0000 }, /* R1561 */
+ { 0x0000, 0x0000 }, /* R1562 */
+ { 0x0000, 0x0000 }, /* R1563 */
+ { 0x0000, 0x0000 }, /* R1564 */
+ { 0x0000, 0x0000 }, /* R1565 */
+ { 0x0000, 0x0000 }, /* R1566 */
+ { 0x0000, 0x0000 }, /* R1567 */
+ { 0x0003, 0x0003 }, /* R1568 - Oversampling */
+ { 0x03C3, 0x03C3 }, /* R1569 - Sidetone */
+};
+
+static int wm8994_readable(struct snd_soc_codec *codec, unsigned int reg)
+{
+ switch (reg) {
+ case WM8994_GPIO_1:
+ case WM8994_GPIO_2:
+ case WM8994_GPIO_3:
+ case WM8994_GPIO_4:
+ case WM8994_GPIO_5:
+ case WM8994_GPIO_6:
+ case WM8994_GPIO_7:
+ case WM8994_GPIO_8:
+ case WM8994_GPIO_9:
+ case WM8994_GPIO_10:
+ case WM8994_GPIO_11:
+ case WM8994_INTERRUPT_STATUS_1:
+ case WM8994_INTERRUPT_STATUS_2:
+ return 1;
+ default:
+ break;
+ }
+
+ if (reg >= ARRAY_SIZE(access_masks))
+ return 0;
+ return access_masks[reg].readable != 0;
+}
+
+static int wm8994_volatile(struct snd_soc_codec *codec, unsigned int reg)
+{
+ //if (reg >= WM8994_CACHE_SIZE)
+ // return 1;
+
+ switch (reg) {
+ case WM8994_SOFTWARE_RESET:
+ case WM8994_CHIP_REVISION:
+ case WM8994_DC_SERVO_1:
+ case WM8994_DC_SERVO_READBACK:
+ case WM8994_RATE_STATUS:
+ case WM8994_LDO_1:
+ case WM8994_LDO_2:
+ case WM8958_DSP2_EXECCONTROL:
+ case WM8958_MIC_DETECT_3:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+/*
+ * initialise the WM8994 driver
+ * register the mixer and dsp interfaces with the kernel
+ */
+static int wm8994_init(struct wm8994_priv *wm8994_private,
+ struct wm8994_platform_data *pdata)
+{
+ struct snd_soc_codec *codec = wm8994_private->codec;
+ struct wm8994_priv *wm8994;
+ int ret = 0;
+ DEBUG_LOG("");
+ wm8994 = kzalloc(sizeof(struct wm8994_priv), GFP_KERNEL);
+ if (wm8994 == NULL)
+ return -ENOMEM;
+
+ snd_soc_codec_set_drvdata(codec, wm8994);
+
+#if 0
+ mutex_init(&codec->mutex);
+ INIT_LIST_HEAD(&codec->dapm_widgets);
+ INIT_LIST_HEAD(&codec->dapm_paths);
+ codec->name = "WM8994";
+ codec->owner = THIS_MODULE;
+ codec->read = wm8994_read;
+ codec->write = wm8994_write;
+ codec->readable_register = wm8994_readable_register;
+ codec->reg_cache_size = WM8994_IRQ_POLARITY; /* Skip write sequencer */
+ codec->set_bias_level = NULL;
+ codec->dai = &wm8994_dai;
+ codec->num_dai = 1;
+#endif
+ wm8994->universal_playback_path = universal_wm8994_playback_paths;
+ wm8994->universal_voicecall_path = universal_wm8994_voicecall_paths;
+ wm8994->universal_mic_path = universal_wm8994_mic_paths;
+ wm8994->universal_clock_control = universal_clock_controls;
+ wm8994->stream_state = PCM_STREAM_DEACTIVE;
+ wm8994->cur_path = OFF;
+ wm8994->rec_path = MIC_OFF;
+ wm8994->power_state = CODEC_OFF;
+ wm8994->input_source = DEFAULT;
+ wm8994->ringtone_active = RING_OFF;
+ wm8994->pdata = pdata;
+
+ wm8994->gain_code = gain_code_check();
+
+ wm8994->codec_clk = clk_get(NULL, "usb_osc");
+
+ wm8994->universal_clock_control(codec, CODEC_ON);
+
+ if (IS_ERR(wm8994->codec_clk)) {
+ pr_err("failed to get MCLK clock from AP\n");
+ ret = PTR_ERR(wm8994->codec_clk);
+ goto card_err;
+ }
+
+ wm8994_write(codec, WM8994_SOFTWARE_RESET, 0x0000);
+
+ wm8994->hw_version = wm8994_read(codec, 0x100);
+
+ //wm8994_socdev->card->codec = codec;
+ wm8994_codec = codec;
+
+#if 0
+ ret = snd_soc_new_pcms(wm8994_socdev, SNDRV_DEFAULT_IDX1,
+ SNDRV_DEFAULT_STR1);
+ if (ret < 0) {
+ DEBUG_LOG_ERR("failed to create pcms\n");
+ goto pcm_err;
+ }
+#endif
+
+ wm8994_add_controls(codec);
+ wm8994_add_widgets(codec);
+
+ return ret;
+
+card_err:
+ //snd_soc_free_pcms(wm8994_socdev);
+ //snd_soc_dapm_free(wm8994_socdev);
+pcm_err:
+
+ return ret;
+}
+
+/* If the i2c layer weren't so broken, we could pass this kind of data
+ around */
+
+static int wm8994_codec_probe(struct snd_soc_codec *codec)
+{
+ struct wm8994_priv *wm8994_priv;
+ int ret = -ENODEV;
+ struct wm8994_platform_data *pdata;
+
+ DEBUG_LOG("");
+ pr_info("WM8994 Audio Codec %s\n", WM8994_VERSION);
+
+ wm8994_priv = kzalloc(sizeof(struct wm8994_priv), GFP_KERNEL);
+ if (wm8994_priv == NULL)
+ return -ENOMEM;
+
+ wm8994_priv->codec = codec;
+#ifdef PM_DEBUG
+ pm_codec = codec;
+#endif
+
+ pdata = dev_get_platdata(codec->dev);
+
+ if (!pdata) {
+ dev_err(codec->dev, "failed to initialize WM8994\n");
+ goto err_bad_pdata;
+ }
+
+ if (!pdata->set_mic_bias) {
+ dev_err(codec->dev, "bad pdata WM8994\n");
+ goto err_bad_pdata;
+ }
+
+ /* CODEC LDO SETTING */
+ if (gpio_is_valid(pdata->ldo)) {
+ ret = gpio_request(pdata->ldo, "WM8994 LDO");
+ if (ret) {
+ pr_err("Failed to request CODEC_LDO_EN!\n");
+ goto err_ldo;
+ }
+ gpio_direction_output(pdata->ldo, 0);
+ }
+
+ s3c_gpio_setpull(pdata->ldo, S3C_GPIO_PULL_NONE);
+
+ /* For preserving output of codec related pins */
+ s3c_gpio_slp_cfgpin(pdata->ldo, S3C_GPIO_SLP_PREV);
+ s3c_gpio_slp_setpull_updown(pdata->ldo, S3C_GPIO_PULL_NONE);
+
+ /* EAR_SEL SETTING(only crespo HW) */
+ if (gpio_is_valid(pdata->ear_sel)) {
+ ret = gpio_request(pdata->ear_sel, "EAR SEL");
+ if (ret) {
+ pr_err("Failed to request EAR_SEL!\n");
+ goto err_earsel;
+ }
+ gpio_direction_output(pdata->ear_sel, 0);
+ }
+ if (!herring_is_cdma_wimax_dev()) {
+ s3c_gpio_setpull(pdata->ear_sel, S3C_GPIO_PULL_NONE);
+
+ s3c_gpio_slp_cfgpin(pdata->ear_sel, S3C_GPIO_SLP_PREV);
+ s3c_gpio_slp_setpull_updown(pdata->ear_sel, S3C_GPIO_PULL_NONE);
+ }
+ wm8994_ldo_control(pdata, 1);
+
+ codec->hw_write = (hw_write_t) i2c_master_send;
+ //i2c_set_clientdata(i2c, wm8994_priv);
+ //codec->control_data = i2c;
+ codec->control_data = to_i2c_client(codec->dev);
+ //codec->dev = &i2c->dev;
+
+ ret = wm8994_init(wm8994_priv, pdata);
+#ifdef CONFIG_SND_VOODOO
+ voodoo_hook_wm8994_pcm_probe(codec);
+#endif
+ if (ret) {
+ dev_err(codec->dev, "failed to initialize WM8994\n");
+ goto err_init;
+ }
+
+ return ret;
+
+err_init:
+ gpio_free(pdata->ear_sel);
+err_earsel:
+ gpio_free(pdata->ldo);
+err_ldo:
+err_bad_pdata:
+ kfree(wm8994_priv);
+ return ret;
+}
+
+static int wm8994_codec_remove(struct snd_soc_codec *codec)
+{
+ struct wm8994_priv *wm8994_priv = snd_soc_codec_get_drvdata(codec);
+
+ gpio_free(wm8994_priv->pdata->ldo);
+ gpio_free(wm8994_priv->pdata->ear_sel);
+
+ kfree(wm8994_priv);
+ return 0;
+}
+
+#if 0
+/* power down chip */
+static int wm8994_remove(struct platform_device *pdev)
+{
+ //struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = wm8994_codec;
+
+ //snd_soc_free_pcms(socdev);
+ //snd_soc_dapm_free(socdev);
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ i2c_unregister_device(codec->control_data);
+ i2c_del_driver(&wm8994_i2c_driver);
+#endif
+
+ //kfree(codec->drvdata);
+
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_PM
+static int wm8994_suspend(struct snd_soc_codec *codec, pm_message_t state)
+{
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+ DEBUG_LOG("Codec State = [0x%X], Stream State = [0x%X]",
+ wm8994->codec_state, wm8994->stream_state);
+
+ if (wm8994->codec_state == DEACTIVE &&
+ wm8994->stream_state == PCM_STREAM_DEACTIVE) {
+ wm8994->power_state = CODEC_OFF;
+ wm8994_write(codec, WM8994_SOFTWARE_RESET, 0x0000);
+ wm8994_ldo_control(wm8994->pdata, 0);
+ wm8994->universal_clock_control(codec, CODEC_OFF);
+ }
+
+ return 0;
+}
+
+static int wm8994_resume(struct snd_soc_codec *codec)
+{
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+ DEBUG_LOG("%s..", __func__);
+ DEBUG_LOG_ERR("------WM8994 Revision = [%d]-------",
+ wm8994->hw_version);
+
+ if (wm8994->power_state == CODEC_OFF) {
+ /* Turn on sequence by recommend Wolfson.*/
+ wm8994_ldo_control(wm8994->pdata, 1);
+ wm8994->universal_clock_control(codec, CODEC_ON);
+ }
+ return 0;
+}
+#endif
+
+#if 0
+struct snd_soc_codec_device soc_codec_dev_wm8994 = {
+ .probe = wm8994_probe,
+ .remove = wm8994_remove,
+#ifdef CONFIG_PM
+ .suspend = wm8994_suspend,
+ .resume = wm8994_resume,
+#endif
+};
+#endif
+
+#if 0
+static int __init wm8994_modinit(void)
+{
+ int ret;
+ ret = snd_soc_register_dai(&wm8994_dai);
+ if (ret)
+ pr_err("..dai registration failed..\n");
+
+ return ret;
+}
+
+module_init(wm8994_modinit);
+
+static void __exit wm8994_exit(void)
+{
+ snd_soc_unregister_dai(&wm8994_dai);
+}
+
+module_exit(wm8994_exit);
+#endif
+
+static struct snd_soc_codec_driver soc_codec_dev_wm8994 = {
+ .probe = wm8994_codec_probe,
+ .remove = wm8994_codec_remove,
+ .suspend = wm8994_suspend,
+ .resume = wm8994_resume,
+ .read = wm8994_read,
+ .write = wm8994_write,
+ .readable_register = wm8994_readable,
+ .volatile_register = wm8994_volatile,
+ //.set_bias_level = wm8994_set_bias_level,
+
+ .reg_cache_size = WM8994_IRQ_POLARITY,
+ //.reg_cache_size = WM8994_CACHE_SIZE,
+ //.reg_cache_default = wm8994_reg_defaults,
+ .reg_word_size = 2,
+ .compress_type = SND_SOC_RBTREE_COMPRESSION,
+};
+
+static int wm8994_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ return snd_soc_register_codec(&client->dev, &soc_codec_dev_wm8994,
+ wm8994_dai, ARRAY_SIZE(wm8994_dai));
+}
+
+static int wm8994_i2c_remove(struct i2c_client *client)
+{
+ snd_soc_unregister_codec(&client->dev);
+ return 0;
+}
+
+
+static const struct i2c_device_id wm8994_i2c_id[] = {
+ {"wm8994-samsung", 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, wm8994_i2c_id);
+
+static struct i2c_driver wm8994_i2c_driver = {
+ .driver = {
+ .name = "wm8994-samsung-codec",
+ .owner = THIS_MODULE,
+ },
+ .probe = wm8994_i2c_probe,
+ .remove = wm8994_i2c_remove,
+ .id_table = wm8994_i2c_id,
+};
+
+static __init int wm8994_driver_init(void)
+{
+ return i2c_add_driver(&wm8994_i2c_driver);
+}
+module_init(wm8994_driver_init);
+
+static __exit void wm8994_driver_exit(void)
+{
+ i2c_del_driver(&wm8994_i2c_driver);
+}
+module_exit(wm8994_driver_exit);
+
+MODULE_DESCRIPTION("ASoC WM8994 driver");
+MODULE_AUTHOR("Shaju Abraham shaju.abraham@samsung.com");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8994_samsung.h b/sound/soc/codecs/wm8994_samsung.h
new file mode 100755
index 0000000..fa4fc3f
--- /dev/null
+++ b/sound/soc/codecs/wm8994_samsung.h
@@ -0,0 +1,207 @@
+/*
+ * wm8994_samsung.h -- WM8994 Soc Audio driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _WM8994_SAMSUNG_H
+#define _WM8994_SAMSUNG_H
+
+#include <sound/soc.h>
+#include <linux/mfd/wm8994/wm8994_pdata.h>
+
+/* Sources for AIF1/2 SYSCLK - use with set_dai_sysclk() */
+#define WM8994_SYSCLK_MCLK1 1
+#define WM8994_SYSCLK_MCLK2 2
+#define WM8994_SYSCLK_FLL1 3
+#define WM8994_SYSCLK_FLL2 4
+
+#define WM8994_FLL1 1
+#define WM8994_FLL2 2
+
+/* Added belows codes by Samsung Electronics.*/
+
+#include "wm8994_def.h"
+
+#define WM8994_SYSCLK_MCLK 1
+#define WM8994_SYSCLK_FLL 2
+
+//#define WM8994_CACHE_SIZE 1570
+
+#define AUDIO_COMMON_DEBUG 0
+
+#define DEACTIVE 0x00
+#define PLAYBACK_ACTIVE 0x01
+#define CAPTURE_ACTIVE 0x02
+#define CALL_ACTIVE 0x04
+
+#define PCM_STREAM_DEACTIVE 0x00
+#define PCM_STREAM_PLAYBACK 0x01
+#define PCM_STREAM_CAPTURE 0x02
+
+/*
+Codec Output Path BIT
+[0:11] : For output device
+[12:15] : For mode
+[16] : For gain code
+*/
+#define PLAYBACK_MODE (0x01 << 12)
+#define VOICECALL_MODE (0x01 << 13)
+#define RECORDING_MODE (0x01 << 14)
+#define FMRADIO_MODE (0x01 << 15)
+
+/*
+ * devide codec gain table
+ * GAIN_DIVISION_BIT_1 : EUR
+ * GAIN_DIVISION_BIT_2 : AT&T
+ * GAIN_DIVISION_BIT_3 : EUR_T
+ */
+
+#define GAIN_DIVISION_BIT_1 (0x01 << 16)
+#define GAIN_DIVISION_BIT_2 (0x01 << 17)
+#define GAIN_DIVISION_BIT_3 (0x01 << 18)
+
+#define COMMON_SET_BIT (0x01 << 0)
+#define PLAYBACK_RCV (0x01 << 1)
+#define PLAYBACK_SPK (0x01 << 2)
+#define PLAYBACK_HP (0x01 << 3)
+#define PLAYBACK_BT (0x01 << 4)
+#define PLAYBACK_SPK_HP (0x01 << 5)
+#define PLAYBACK_RING_SPK (0x01 << 6)
+#define PLAYBACK_RING_HP (0x01 << 7)
+#define PLAYBACK_RING_SPK_HP (0x01 << 8)
+#define PLAYBACK_HP_NO_MIC (0x01 << 9)
+
+#define VOICECALL_RCV (0x01 << 1)
+#define VOICECALL_SPK (0x01 << 2)
+#define VOICECALL_HP (0x01 << 3)
+#define VOICECALL_HP_NO_MIC (0x01 << 4)
+#define VOICECALL_BT (0x01 << 5)
+#define VOICECALL_TTY_VCO (0x01 << 6)
+#define VOICECALL_TTY_HCO (0x01 << 7)
+#define VOICECALL_TTY_FULL (0x01 << 8)
+
+#define RECORDING_MAIN (0x01 << 1)
+#define RECORDING_HP (0x01 << 2)
+#define RECORDING_BT (0x01 << 3)
+#define RECORDING_REC_MAIN (0x01 << 4)
+#define RECORDING_REC_HP (0x01 << 5)
+#define RECORDING_REC_BT (0x01 << 6)
+#define RECORDING_CAM_MAIN (0x01 << 7)
+#define RECORDING_CAM_HP (0x01 << 8)
+#define RECORDING_CAM_BT (0x01 << 9)
+#define RECORDING_VC_MAIN (0x01 << 10)
+#define RECORDING_VC_HP (0x01 << 11)
+#define RECORDING_VC_BT (0x01 << 12)
+
+#define PLAYBACK_GAIN_NUM 43
+#define VOICECALL_GAIN_NUM 38
+#define RECORDING_GAIN_NUM 32
+#define GAIN_CODE_NUM 13
+/*
+ * Definitions of enum type
+ */
+enum audio_path {
+ OFF, RCV, SPK, HP, HP_NO_MIC, BT, SPK_HP,
+ RING_SPK, RING_HP, RING_NO_MIC, RING_SPK_HP
+};
+enum call_path {
+ CALL_OFF, CALL_RCV, CALL_SPK, CALL_HP,
+ CALL_HP_NO_MIC, CALL_BT, CALL_TTY_VCO,
+ CALL_TTY_HCO, CALL_TTY_FULL
+};
+enum mic_path {MAIN, SUB, BT_REC, MIC_OFF};
+enum power_state {CODEC_OFF, CODEC_ON };
+enum ringtone_state {RING_OFF, RING_ON};
+enum input_source_state {DEFAULT, RECOGNITION, CAMCORDER, VOICE_COMMUNICATION};
+
+typedef void (*select_route)(struct snd_soc_codec *);
+typedef void (*select_mic_route)(struct snd_soc_codec *);
+typedef int (*select_clock_control)(struct snd_soc_codec *, int);
+
+
+struct wm8994_setup_data {
+ int i2c_bus;
+ unsigned short i2c_address;
+};
+
+enum wm8994_dc_servo_slots {
+ DCS_MEDIA = 0,
+ DCS_VOICE = 1,
+ DCS_SPK_HP = 2,
+};
+
+struct wm8994_priv {
+ struct snd_soc_codec *codec;
+ int master;
+ int sysclk_source;
+ unsigned int mclk_rate;
+ unsigned int sysclk_rate;
+ unsigned int fs;
+ unsigned int bclk;
+ unsigned int hw_version;
+ unsigned int codec_state;
+ unsigned int stream_state;
+ enum audio_path cur_path;
+ enum mic_path rec_path;
+ enum power_state power_state;
+ enum input_source_state input_source;
+ enum ringtone_state ringtone_active;
+ select_route *universal_playback_path;
+ select_route *universal_voicecall_path;
+ select_mic_route *universal_mic_path;
+ select_clock_control universal_clock_control;
+ struct wm8994_platform_data *pdata;
+ struct clk *codec_clk;
+ int gain_code;
+ u16 dc_servo[3];
+};
+
+struct gain_info_t {
+ int mode;
+ int reg;
+ int mask;
+ int gain;
+};
+
+#if AUDIO_COMMON_DEBUG
+#define DEBUG_LOG(format, ...)\
+ printk(KERN_INFO "[ "SUBJECT " (%s,%d) ] " format "\n", \
+ __func__, __LINE__, ## __VA_ARGS__);
+#else
+#define DEBUG_LOG(format, ...)
+#endif
+
+#define DEBUG_LOG_ERR(format, ...)\
+ printk(KERN_ERR "[ "SUBJECT " (%s,%d) ] " format "\n", \
+ __func__, __LINE__, ## __VA_ARGS__);
+
+/* Definitions of function prototype. */
+unsigned int wm8994_read(struct snd_soc_codec *codec, unsigned int reg);
+int wm8994_write(struct snd_soc_codec *codec,
+ unsigned int reg, unsigned int value);
+int wm8994_configure_clock(struct snd_soc_codec *codec, int en);
+void wm8994_disable_path(struct snd_soc_codec *codec);
+void wm8994_disable_rec_path(struct snd_soc_codec *codec);
+void wm8994_record_main_mic(struct snd_soc_codec *codec);
+void wm8994_record_headset_mic(struct snd_soc_codec *codec);
+void wm8994_record_bluetooth(struct snd_soc_codec *codec);
+void wm8994_set_playback_receiver(struct snd_soc_codec *codec);
+void wm8994_set_playback_headset(struct snd_soc_codec *codec);
+void wm8994_set_playback_speaker(struct snd_soc_codec *codec);
+void wm8994_set_playback_bluetooth(struct snd_soc_codec *codec);
+void wm8994_set_playback_speaker_headset(struct snd_soc_codec *codec);
+void wm8994_set_voicecall_common_setting(struct snd_soc_codec *codec);
+void wm8994_set_voicecall_receiver(struct snd_soc_codec *codec);
+void wm8994_set_voicecall_headset(struct snd_soc_codec *codec);
+void wm8994_set_voicecall_headphone(struct snd_soc_codec *codec);
+void wm8994_set_voicecall_speaker(struct snd_soc_codec *codec);
+void wm8994_set_voicecall_bluetooth(struct snd_soc_codec *codec);
+void wm8994_set_voicecall_tty_vco(struct snd_soc_codec *codec);
+void wm8994_set_voicecall_tty_hco(struct snd_soc_codec *codec);
+void wm8994_set_voicecall_tty_full(struct snd_soc_codec *codec);
+int wm8994_set_codec_gain(struct snd_soc_codec *codec, u16 mode, u16 device);
+extern int gain_code_check(void);
+#endif
diff --git a/sound/soc/codecs/wm8994_voodoo.c b/sound/soc/codecs/wm8994_voodoo.c
new file mode 100644
index 0000000..750702f
--- /dev/null
+++ b/sound/soc/codecs/wm8994_voodoo.c
@@ -0,0 +1,1872 @@
+/*
+ * voodoo_sound.c -- WM8994 ALSA Soc Audio driver related
+ *
+ * Copyright (C) 2010/11 François SIMOND / twitter & XDA-developers @supercurio
+ *
+ * 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 <sound/soc.h>
+#include <linux/delay.h>
+#include <linux/miscdevice.h>
+#include <linux/version.h>
+#include "wm8994_voodoo.h"
+
+#ifndef MODULE
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) && !defined(GALAXY_TAB)
+#include "wm8994_samsung.h"
+#else
+#include "wm8994.h"
+#endif
+#else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) && !defined(GALAXY_TAB)
+#include "../wm8994_samsung.h"
+#else
+#include "../wm8994.h"
+#endif
+#endif
+
+#define SUBJECT "wm8994_voodoo.c"
+
+#ifdef MODULE
+#include "tegrak_voodoo_sound.h"
+
+// wm8994_write -> tegrak_wm8994_write for dynamic link
+#ifdef wm8994_write
+#undef wm8994_write
+#endif
+
+// wm8994_read -> tegrak_wm8994_read for dynamic link
+#ifdef wm8994_read
+#undef wm8994_read
+#endif
+
+#define wm8994_write(codec, reg, value) tegrak_wm8994_write(codec, reg, value)
+#define wm8994_read(codec, reg) tegrak_wm8994_read(codec, reg)
+#endif
+
+bool bypass_write_hook = false;
+
+short unsigned int debug_log_level = LOG_OFF;
+
+#ifdef CONFIG_SND_VOODOO_HP_LEVEL_CONTROL
+unsigned short hp_level[2] = { CONFIG_SND_VOODOO_HP_LEVEL,
+ CONFIG_SND_VOODOO_HP_LEVEL };
+#endif
+
+#ifdef CONFIG_SND_VOODOO_FM
+bool fm_radio_headset_restore_bass = true;
+bool fm_radio_headset_restore_highs = true;
+bool fm_radio_headset_normalize_gain = true;
+#endif
+
+#ifdef CONFIG_SND_VOODOO_RECORD_PRESETS
+unsigned short recording_preset = 1;
+unsigned short origin_recgain;
+unsigned short origin_recgain_mixer;
+#endif
+
+#ifdef NEXUS_S
+bool speaker_tuning = false;
+#endif
+
+// global active or kill switch
+bool enable = false;
+
+bool dac_osr128 = true;
+bool adc_osr128 = false;
+#ifndef GALAXY_TAB_TEGRA
+bool fll_tuning = true;
+#endif
+bool dac_direct = true;
+bool mono_downmix = false;
+
+// equalizer
+
+// digital gain value in mili dB
+int digital_gain = 0;
+
+bool headphone_eq = false;
+short eq_gains[5] = { 0, 0, 0, 0, 0 };
+short eq_bands[5] = { 3, 4, 4, 4, 3 };
+char eq_band_coef_names[][2] = { "A", "B", "C", "PG" };
+
+unsigned int eq_band_values[5][4] = {
+ {0x0FCA, 0x0400, 0x00D8},
+ {0x1EB5, 0xF145, 0x0B75, 0x01C5},
+ {0x1C58, 0xF373, 0x0A54, 0x0558},
+ {0x168E, 0xF829, 0x07AD, 0x1103},
+ {0x0564, 0x0559, 0x4000}
+};
+
+// 3D effect
+bool stereo_expansion = false;
+short unsigned int stereo_expansion_gain = 16;
+
+// keep here a pointer to the codec structure
+static struct snd_soc_codec *codec;
+
+#define DECLARE_BOOL_SHOW(name) \
+static ssize_t name##_show(struct device *dev, \
+struct device_attribute *attr, char *buf) \
+{ \
+ return sprintf(buf,"%u\n",(name ? 1 : 0)); \
+}
+
+#define DECLARE_BOOL_STORE_UPDATE_WITH_MUTE(name, updater, with_mute) \
+static ssize_t name##_store(struct device *dev, struct device_attribute *attr, \
+ const char *buf, size_t size) \
+{ \
+ unsigned short state; \
+ if (sscanf(buf, "%hu", &state) == 1) { \
+ name = state == 0 ? false : true; \
+ if (debug_log(LOG_INFOS)) \
+ printk("Voodoo sound: %s: %u\n", #updater, state); \
+ updater(with_mute); \
+ } \
+ return size; \
+}
+
+#define DECLARE_EQ_GAIN_SHOW(band) \
+static ssize_t headphone_eq_b##band##_gain_show(struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+{ \
+ return sprintf(buf, "%d\n", eq_gains[band - 1]); \
+}
+
+#define DECLARE_EQ_GAIN_STORE(band) \
+static ssize_t headphone_eq_b##band##_gain_store(struct device *dev, \
+ struct device_attribute *attr, \
+ const char *buf, size_t size) \
+{ \
+ short new_gain; \
+ if (sscanf(buf, "%hd", &new_gain) == 1) { \
+ if (new_gain >= -12 && new_gain <= 12) { \
+ smooth_apply_eq_band_gain(band - 1, \
+ eq_gains[band - 1], \
+ new_gain, \
+ headphone_eq); \
+ eq_gains[band - 1] = new_gain; \
+ } \
+ } \
+ return size; \
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+#define DECLARE_WM8994(codec) struct wm8994_priv *wm8994 = \
+ snd_soc_codec_get_drvdata(codec);
+#else
+#define DECLARE_WM8994(codec) struct wm8994_priv *wm8994 = codec->private_data;
+#endif
+
+bool debug_log(short unsigned int level)
+{
+ if (debug_log_level >= level)
+ return true;
+
+ return false;
+}
+
+#ifdef CONFIG_SND_VOODOO_HP_LEVEL_CONTROL
+int hpvol(int channel)
+{
+ int vol;
+
+ vol = hp_level[channel];
+
+ if (is_path_media_or_fm_no_call_no_record()) {
+ // negative digital gain compensation
+ if (digital_gain < 0)
+ vol = (vol - ((digital_gain / 100) + 5) / 10);
+
+ if (vol > 62)
+ return 62;
+ }
+
+ return vol;
+}
+
+void write_hpvol(unsigned short l, unsigned short r)
+{
+ unsigned short val;
+
+ // we don't need the Volume Update flag when sending the first volume
+ val = (WM8994_HPOUT1L_MUTE_N | l);
+ val |= WM8994_HPOUT1L_ZC;
+ wm8994_write(codec, WM8994_LEFT_OUTPUT_VOLUME, val);
+
+ // this time we write the right volume plus the Volume Update flag.
+ // This way, both volume are set at the same time
+ val = (WM8994_HPOUT1_VU | WM8994_HPOUT1R_MUTE_N | r);
+ val |= WM8994_HPOUT1L_ZC;
+ wm8994_write(codec, WM8994_RIGHT_OUTPUT_VOLUME, val);
+}
+
+void update_hpvol(bool with_fade)
+{
+ unsigned short val;
+ unsigned short i;
+ short steps;
+ int hp_level_old[2];
+ unsigned short hp_level_registers[2] = { WM8994_LEFT_OUTPUT_VOLUME,
+ WM8994_RIGHT_OUTPUT_VOLUME };
+
+ DECLARE_WM8994(codec);
+
+ // don't affect headphone amplifier volume
+ // when not on heapdhones or if call is active
+ if (!is_path(HEADPHONES)
+ || (wm8994->codec_state & CALL_ACTIVE))
+ return;
+
+
+ if (!with_fade) {
+ bypass_write_hook = true;
+ write_hpvol(hpvol(0), hpvol(1));
+ bypass_write_hook = false;
+ return;
+ }
+
+ // read previous levels
+ for (i = 0; i < 2; i++) {
+ val = wm8994_read(codec, hp_level_registers[i]);
+ val &= ~(WM8994_HPOUT1_VU_MASK);
+ val &= ~(WM8994_HPOUT1L_ZC_MASK);
+ val &= ~(WM8994_HPOUT1L_MUTE_N_MASK);
+ hp_level_old[i] = val + (digital_gain / 1000);
+
+ if (hp_level_old[i] < 0)
+ hp_level_old[i] = 0;
+
+ if (debug_log(LOG_INFOS))
+ printk("Voodoo sound: previous hp_level[%hu]: %d\n",
+ i, hp_level_old[i]);
+ }
+
+ // calculate number of steps for volume fade
+ steps = hp_level[0] - hp_level_old[0];
+ if (debug_log(LOG_INFOS))
+ printk("Voodoo sound: volume change steps: %hd "
+ "start: %hu, end: %hu\n",
+ steps,
+ hp_level_old[0],
+ hp_level[0]);
+
+ while (steps != 0) {
+ if (hp_level[0] < hp_level_old[0])
+ steps++;
+ else
+ steps--;
+
+ if (debug_log(LOG_INFOS))
+ printk("Voodoo sound: volume: %hu\n",
+ (hpvol(0) - steps));
+
+ bypass_write_hook = true;
+ write_hpvol(hpvol(0) - steps, hpvol(1) - steps);
+ bypass_write_hook = false;
+
+ if (steps != 0)
+ udelay(1000);
+ }
+
+}
+#endif
+
+#ifdef CONFIG_SND_VOODOO_FM
+void update_fm_radio_headset_restore_freqs(bool with_mute)
+{
+ unsigned short val;
+ DECLARE_WM8994(codec);
+
+ bypass_write_hook = true;
+ // apply only when FM radio is active
+ if (wm8994->fmradio_path == FMR_OFF)
+ return;
+
+ if (with_mute) {
+ wm8994_write(codec, WM8994_AIF2_DAC_FILTERS_1,
+ WM8994_AIF2DAC_MUTE |
+ WM8994_AIF2DAC_MUTERATE |
+ WM8994_AIF2DAC_UNMUTE_RAMP |
+ WM8994_AIF2DAC_DEEMP_MASK);
+ msleep(180);
+ }
+
+ if (fm_radio_headset_restore_bass) {
+ // disable Sidetone high-pass filter
+ // was designed for voice and not FM radio
+ wm8994_write(codec, WM8994_SIDETONE, 0x0000);
+ // disable 4FS ultrasonic mode and
+ // restore the hi-fi <4Hz hi pass filter
+ wm8994_write(codec, WM8994_AIF2_ADC_FILTERS,
+ WM8994_AIF2ADCL_HPF |
+ WM8994_AIF2ADCR_HPF);
+ } else {
+ // default settings in GT-I9000 Froyo XXJPX kernel sources
+ wm8994_write(codec, WM8994_SIDETONE, 0x01c0);
+ wm8994_write(codec, WM8994_AIF2_ADC_FILTERS, 0xF800);
+ }
+
+ if (fm_radio_headset_restore_highs) {
+ val = wm8994_read(codec, WM8994_AIF2_DAC_FILTERS_1);
+ val &= ~(WM8994_AIF2DAC_DEEMP_MASK);
+ wm8994_write(codec, WM8994_AIF2_DAC_FILTERS_1, val);
+ } else {
+ wm8994_write(codec, WM8994_AIF2_DAC_FILTERS_1, 0x0036);
+ }
+
+ // un-mute
+ if (with_mute) {
+ val = wm8994_read(codec, WM8994_AIF2_DAC_FILTERS_1);
+ val &= ~(WM8994_AIF2DAC_MUTE_MASK);
+ wm8994_write(codec, WM8994_AIF2_DAC_FILTERS_1, val);
+ }
+ bypass_write_hook = false;
+}
+
+void update_fm_radio_headset_normalize_gain(bool with_mute)
+{
+ DECLARE_WM8994(codec);
+
+ bypass_write_hook = true;
+ // apply only when FM radio is active
+ if (wm8994->fmradio_path == FMR_OFF)
+ return;
+
+ if (fm_radio_headset_normalize_gain) {
+ // Bumped volume, change with Zero Cross
+ wm8994_write(codec, WM8994_LEFT_LINE_INPUT_3_4_VOLUME, 0x52);
+ wm8994_write(codec, WM8994_RIGHT_LINE_INPUT_3_4_VOLUME, 0x152);
+ wm8994_write(codec, WM8994_AIF2_DRC_2, 0x0840);
+ wm8994_write(codec, WM8994_AIF2_DRC_3, 0x2408);
+ wm8994_write(codec, WM8994_AIF2_DRC_4, 0x0082);
+ wm8994_write(codec, WM8994_AIF2_DRC_5, 0x0100);
+ wm8994_write(codec, WM8994_AIF2_DRC_1, 0x019C);
+ } else {
+ // Original volume, change with Zero Cross
+ wm8994_write(codec, WM8994_LEFT_LINE_INPUT_3_4_VOLUME, 0x4B);
+ wm8994_write(codec, WM8994_RIGHT_LINE_INPUT_3_4_VOLUME, 0x14B);
+ wm8994_write(codec, WM8994_AIF2_DRC_2, 0x0840);
+ wm8994_write(codec, WM8994_AIF2_DRC_3, 0x2400);
+ wm8994_write(codec, WM8994_AIF2_DRC_4, 0x0000);
+ wm8994_write(codec, WM8994_AIF2_DRC_5, 0x0000);
+ wm8994_write(codec, WM8994_AIF2_DRC_1, 0x019C);
+ }
+ bypass_write_hook = false;
+}
+#endif
+
+#ifdef CONFIG_SND_VOODOO_RECORD_PRESETS
+void update_recording_preset(bool with_mute)
+{
+ if (!is_path(MAIN_MICROPHONE))
+ return;
+
+ switch (recording_preset) {
+ case 0:
+ // Original:
+ // On Galaxy S: IN1L_VOL1=11000 (+19.5 dB)
+ // On Nexus S: variable value
+ wm8994_write(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME,
+ WM8994_IN1L_VU | origin_recgain);
+ wm8994_write(codec, WM8994_INPUT_MIXER_3, origin_recgain_mixer);
+ // DRC disabled
+ wm8994_write(codec, WM8994_AIF1_DRC1_1, 0x0080);
+ break;
+ case 2:
+ // High sensitivy:
+ // Original - 4.5 dB, IN1L_VOL1=10101 (+15 dB)
+ wm8994_write(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME, 0x0115);
+ wm8994_write(codec, WM8994_INPUT_MIXER_3,
+ WM8994_IN1L_TO_MIXINL |
+ WM8994_IN1L_MIXINL_VOL);
+ // DRC Input: -6dB, Ouptut -3.75dB
+ // Above knee 1/8, Below knee 1/2
+ // Max gain 24 / Min gain -12
+ wm8994_write(codec, WM8994_AIF1_DRC1_1,
+ WM8994_AIF1DRC1_SIG_DET_MODE |
+ WM8994_AIF1DRC1_QR |
+ WM8994_AIF1DRC1_ANTICLIP |
+ WM8994_AIF1ADC1L_DRC_ENA);
+ wm8994_write(codec, WM8994_AIF1_DRC1_2, 0x0426);
+ wm8994_write(codec, WM8994_AIF1_DRC1_3, 0x0019);
+ wm8994_write(codec, WM8994_AIF1_DRC1_4, 0x0105);
+ break;
+ case 3:
+ // Concert new: IN1L_VOL1=10110 (+4.5 dB)
+ // +30dB input mixer gain deactivated
+ wm8994_write(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME, 0x010F);
+ wm8994_write(codec, WM8994_INPUT_MIXER_3,
+ WM8994_IN1L_TO_MIXINL);
+ // DRC Input: -4.5dB, Ouptut -6.75dB
+ // Above knee 1/4, Below knee 1/2
+ // Max gain 24 / Min gain -12
+ wm8994_write(codec, WM8994_AIF1_DRC1_1,
+ WM8994_AIF1DRC1_SIG_DET_MODE |
+ WM8994_AIF1DRC1_QR |
+ WM8994_AIF1DRC1_ANTICLIP |
+ WM8994_AIF1ADC1L_DRC_ENA);
+ wm8994_write(codec, WM8994_AIF1_DRC1_2, 0x0846);
+ wm8994_write(codec, WM8994_AIF1_DRC1_3, 0x0011);
+ wm8994_write(codec, WM8994_AIF1_DRC1_4, 0x00C9);
+ break;
+ case 4:
+ // ULTRA LOUD:
+ // Original - 36 dB - 30 dB IN1L_VOL1=00000 (-16.5 dB)
+ // +30dB input mixer gain deactivated
+ wm8994_write(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME, 0x0100);
+ wm8994_write(codec, WM8994_INPUT_MIXER_3,
+ WM8994_IN1L_TO_MIXINL);
+ // DRC Input: -7.5dB, Ouptut -6dB
+ // Above knee 1/8, Below knee 1/4
+ // Max gain 36 / Min gain -12
+ wm8994_write(codec, WM8994_AIF1_DRC1_1,
+ WM8994_AIF1DRC1_SIG_DET_MODE |
+ WM8994_AIF1DRC1_QR |
+ WM8994_AIF1DRC1_ANTICLIP |
+ WM8994_AIF1ADC1L_DRC_ENA);
+ wm8994_write(codec, WM8994_AIF1_DRC1_2, 0x0847);
+ wm8994_write(codec, WM8994_AIF1_DRC1_3, 0x001A);
+ wm8994_write(codec, WM8994_AIF1_DRC1_4, 0x00C9);
+ break;
+ default:
+ // make sure recording_preset is the default
+ recording_preset = 1;
+ // New Balanced: Original - 16.5 dB
+ // IN1L_VOL1=01101 (+27 dB)
+ // +30dB input mixer gain deactivated
+ wm8994_write(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME, 0x055D);
+ wm8994_write(codec, WM8994_INPUT_MIXER_3,
+ WM8994_IN1L_TO_MIXINL);
+ // DRC Input: -18.5dB, Ouptut -9dB
+ // Above knee 1/8, Below knee 1/2
+ // Max gain 18 / Min gain -12
+ wm8994_write(codec, WM8994_AIF1_DRC1_1,
+ WM8994_AIF1DRC1_SIG_DET_MODE |
+ WM8994_AIF1DRC1_QR |
+ WM8994_AIF1DRC1_ANTICLIP |
+ WM8994_AIF1ADC1L_DRC_ENA);
+ wm8994_write(codec, WM8994_AIF1_DRC1_2, 0x0845);
+ wm8994_write(codec, WM8994_AIF1_DRC1_3, 0x0019);
+ wm8994_write(codec, WM8994_AIF1_DRC1_4, 0x030C);
+ break;
+ }
+}
+#endif
+
+bool is_path(int unified_path)
+{
+ DECLARE_WM8994(codec);
+
+ switch (unified_path) {
+ // speaker
+ case SPEAKER:
+#ifdef GALAXY_TAB
+ return (wm8994->cur_path == SPK
+ || wm8994->cur_path == RING_SPK
+ || wm8994->fmradio_path == FMR_SPK
+ || wm8994->fmradio_path == FMR_SPK_MIX);
+#else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+ return (wm8994->cur_path == SPK
+ || wm8994->cur_path == SPK_HP);
+#else
+ return (wm8994->cur_path == SPK
+ || wm8994->cur_path == RING_SPK);
+#endif
+#endif
+
+ // headphones
+ case HEADPHONES:
+
+#ifdef NEXUS_S
+ return (wm8994->cur_path == HP
+ || wm8994->cur_path == HP_NO_MIC);
+#else
+#ifdef GALAXY_TAB
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+ return (wm8994->cur_path == HP
+ || wm8994->cur_path == HP_NO_MIC);
+#else
+ return (wm8994->cur_path == HP3P
+ || wm8994->cur_path == HP4P
+ || wm8994->fmradio_path == FMR_HP);
+#endif
+#else
+#ifdef M110S
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+ return (wm8994->cur_path == HP
+ || wm8994->cur_path == HP_NO_MIC);
+#else
+ return (wm8994->cur_path == HP);
+#endif
+#else
+#ifdef GALAXY_TAB_TEGRA
+ return (wm8994->cur_path == HP
+ || wm8994->cur_path == HP_NO_MIC);
+#else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+ return (wm8994->cur_path == HP
+ || wm8994->cur_path == HP_NO_MIC
+ || wm8994->fmradio_path == FMR_HP);
+#else
+ return (wm8994->cur_path == HP
+ || wm8994->fmradio_path == FMR_HP);
+#endif
+#endif
+#endif
+#endif
+#endif
+
+ // FM Radio on headphones
+ case RADIO_HEADPHONES:
+#ifdef NEXUS_S
+ return false;
+#else
+#ifdef M110S
+ return false;
+#else
+#ifdef GALAXY_TAB_TEGRA
+ return false;
+#else
+#ifdef GALAXY_TAB
+ return false;
+#else
+ return (wm8994->codec_state & FMRADIO_ACTIVE)
+ && (wm8994->fmradio_path == FMR_HP);
+#endif
+#endif
+#endif
+#endif
+
+ // Standard recording presets
+ // for M110S Gingerbread: added check non call
+ case MAIN_MICROPHONE:
+ return (wm8994->codec_state & CAPTURE_ACTIVE)
+ && (wm8994->rec_path == MAIN)
+ && !(wm8994->codec_state & CALL_ACTIVE);
+
+ }
+ return false;
+}
+
+bool is_path_media_or_fm_no_call_no_record()
+{
+
+ DECLARE_WM8994(codec);
+
+ if ((is_path(HEADPHONES)
+ && (wm8994->codec_state & PLAYBACK_ACTIVE)
+ && (wm8994->stream_state & PCM_STREAM_PLAYBACK)
+ && !(wm8994->codec_state & CALL_ACTIVE)
+ && (wm8994->rec_path == MIC_OFF)
+ ) || is_path(RADIO_HEADPHONES))
+ return true;
+
+ return false;
+}
+
+#ifdef NEXUS_S
+void update_speaker_tuning(bool with_mute)
+{
+ DECLARE_WM8994(codec);
+
+ if (!(is_path(SPEAKER) || (wm8994->codec_state & CALL_ACTIVE)))
+ return;
+
+ if (speaker_tuning) {
+ // DRC settings
+ wm8994_write(codec, WM8994_AIF1_DRC1_3, 0x0010);
+ wm8994_write(codec, WM8994_AIF1_DRC1_4, 0x00EB);
+
+ // hardware EQ
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_GAINS_1, 0x041D);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_GAINS_2, 0x4C00);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_1_A, 0x0FE3);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_1_B, 0x0403);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_1_PG, 0x0074);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_2_A, 0x1F03);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_2_B, 0xF0F9);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_2_C, 0x040A);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_2_PG, 0x03DA);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_3_A, 0x1ED2);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_3_B, 0xF11A);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_3_C, 0x040A);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_3_PG, 0x045D);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_4_A, 0x0E76);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_4_B, 0xFCE4);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_4_C, 0x040A);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_4_PG, 0x330D);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_5_A, 0xFC8F);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_5_B, 0x0400);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_5_PG, 0x323C);
+
+ // Speaker Boost tuning
+ wm8994_write(codec, WM8994_CLASSD, 0x0170);
+ } else {
+ // DRC settings
+ wm8994_write(codec, WM8994_AIF1_DRC1_3, 0x0028);
+ wm8994_write(codec, WM8994_AIF1_DRC1_4, 0x0186);
+
+ // hardware EQ
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_GAINS_1, 0x0019);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_GAINS_2, 0x6280);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_1_A, 0x0FC3);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_1_B, 0x03FD);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_1_PG, 0x00F4);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_2_A, 0x1F30);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_2_B, 0xF0CD);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_2_C, 0x040A);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_2_PG, 0x032C);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_3_A, 0x1C52);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_3_B, 0xF379);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_3_C, 0x040A);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_3_PG, 0x0DC1);
+ wm8994_write(codec, WM8994_CLASSD, 0x0170);
+
+ // Speaker Boost tuning
+ wm8994_write(codec, WM8994_CLASSD, 0x0168);
+ }
+}
+#endif
+
+unsigned short osr128_get_value(unsigned short val)
+{
+ if (dac_osr128 == 1)
+ val |= WM8994_DAC_OSR128;
+ else
+ val &= ~WM8994_DAC_OSR128;
+
+ if (adc_osr128 == 1)
+ val |= WM8994_ADC_OSR128;
+ else
+ val &= ~WM8994_ADC_OSR128;
+
+ return val;
+}
+
+void update_osr128(bool with_mute)
+{
+ unsigned short val;
+ val = osr128_get_value(wm8994_read(codec, WM8994_OVERSAMPLING));
+ bypass_write_hook = true;
+ wm8994_write(codec, WM8994_OVERSAMPLING, val);
+ bypass_write_hook = false;
+}
+
+#ifndef GALAXY_TAB_TEGRA
+unsigned short fll_tuning_get_value(unsigned short val)
+{
+ val = (val >> WM8994_FLL1_GAIN_WIDTH << WM8994_FLL1_GAIN_WIDTH);
+ if (fll_tuning == 1)
+ val |= 5;
+
+ return val;
+}
+
+void update_fll_tuning(bool with_mute)
+{
+ unsigned short val;
+ val = fll_tuning_get_value(wm8994_read(codec, WM8994_FLL1_CONTROL_4));
+ bypass_write_hook = true;
+ wm8994_write(codec, WM8994_FLL1_CONTROL_4, val);
+ bypass_write_hook = false;
+}
+#endif
+
+unsigned short mono_downmix_get_value(unsigned short val, bool can_reverse)
+{
+ DECLARE_WM8994(codec);
+
+ // Takes care not switching to Stereo on speaker or during a call
+ if (!is_path(SPEAKER) && !(wm8994->codec_state & CALL_ACTIVE)) {
+ if (mono_downmix) {
+ val |= WM8994_AIF1DAC1_MONO;
+ } else {
+ if (can_reverse)
+ val &= ~WM8994_AIF1DAC1_MONO;
+ }
+ }
+
+ return val;
+}
+
+void update_mono_downmix(bool with_mute)
+{
+ unsigned short val1, val2, val3;
+ val1 = mono_downmix_get_value(wm8994_read
+ (codec, WM8994_AIF1_DAC1_FILTERS_1),
+ true);
+ val2 = mono_downmix_get_value(wm8994_read
+ (codec, WM8994_AIF1_DAC2_FILTERS_1),
+ true);
+ val3 = mono_downmix_get_value(wm8994_read
+ (codec, WM8994_AIF2_DAC_FILTERS_1),
+ true);
+
+ bypass_write_hook = true;
+ wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, val1);
+ wm8994_write(codec, WM8994_AIF1_DAC2_FILTERS_1, val2);
+ wm8994_write(codec, WM8994_AIF2_DAC_FILTERS_1, val3);
+ bypass_write_hook = false;
+}
+
+unsigned short dac_direct_get_value(unsigned short val, bool can_reverse)
+{
+ if (is_path_media_or_fm_no_call_no_record()) {
+
+ if (dac_direct) {
+ if (val == WM8994_DAC1L_TO_MIXOUTL)
+ return WM8994_DAC1L_TO_HPOUT1L;
+ } else {
+ if (val == WM8994_DAC1L_TO_HPOUT1L && can_reverse)
+ return WM8994_DAC1L_TO_MIXOUTL;
+ }
+ }
+
+ return val;
+}
+
+void update_dac_direct(bool with_mute)
+{
+ unsigned short val1, val2;
+ val1 = dac_direct_get_value(wm8994_read(codec,
+ WM8994_OUTPUT_MIXER_1), true);
+ val2 = dac_direct_get_value(wm8994_read(codec,
+ WM8994_OUTPUT_MIXER_2), true);
+
+ bypass_write_hook = true;
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_1, val1);
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_2, val2);
+ bypass_write_hook = false;
+}
+
+unsigned short digital_gain_get_value(unsigned short val)
+{
+ // AIF gain to 0dB
+ int aif_gain = 0xC0;
+ int i;
+ int step = -375;
+
+ if (is_path_media_or_fm_no_call_no_record()) {
+
+ if (digital_gain <= 0) {
+ // clear the actual DAC volume for this value
+ val &= ~(WM8994_DAC1R_VOL_MASK);
+
+ // calculation with round
+ i = ((digital_gain * 10 / step) + 5) / 10;
+ aif_gain -= i;
+ val |= aif_gain;
+
+ if (debug_log(LOG_INFOS))
+ printk("Voodoo sound: digital gain: %d mdB, "
+ "%d mdB steps: %d, "
+ "real AIF gain: %d mdB\n",
+ digital_gain, step, i, i * step);
+ }
+ }
+
+ return val;
+}
+
+void update_digital_gain(bool with_mute)
+{
+ unsigned short val1, val2;
+ val1 = digital_gain_get_value(wm8994_read(codec,
+ WM8994_AIF1_DAC1_LEFT_VOLUME));
+ val2 = digital_gain_get_value(wm8994_read(codec,
+ WM8994_AIF1_DAC1_RIGHT_VOLUME));
+
+ bypass_write_hook = true;
+ wm8994_write(codec, WM8994_AIF1_DAC1_LEFT_VOLUME,
+ WM8994_DAC1_VU | val1);
+ wm8994_write(codec, WM8994_AIF1_DAC1_RIGHT_VOLUME,
+ WM8994_DAC1_VU | val2);
+ bypass_write_hook = false;
+}
+
+void update_headphone_eq(bool update_bands)
+{
+ int gains_1;
+ int gains_2;
+
+ if (!is_path_media_or_fm_no_call_no_record()) {
+ // don't apply the EQ
+ return;
+ }
+
+ if (debug_log(LOG_INFOS))
+ printk("Voodoo sound: EQ gains (dB): %hd, %hd, %hd, %hd, %hd\n",
+ eq_gains[0], eq_gains[1], eq_gains[2],
+ eq_gains[3], eq_gains[4]);
+
+ gains_1 =
+ ((eq_gains[0] + 12) << WM8994_AIF1DAC1_EQ_B1_GAIN_SHIFT) |
+ ((eq_gains[1] + 12) << WM8994_AIF1DAC1_EQ_B2_GAIN_SHIFT) |
+ ((eq_gains[2] + 12) << WM8994_AIF1DAC1_EQ_B3_GAIN_SHIFT) |
+ headphone_eq;
+
+ gains_2 =
+ ((eq_gains[3] + 12) << WM8994_AIF1DAC1_EQ_B4_GAIN_SHIFT) |
+ ((eq_gains[4] + 12) << WM8994_AIF1DAC1_EQ_B5_GAIN_SHIFT);
+
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_GAINS_1, gains_1);
+ wm8994_write(codec, WM8994_AIF1_DAC1_EQ_GAINS_2, gains_2);
+
+ // don't send EQ configuration if its not enabled
+ if (!headphone_eq)
+ return;
+
+ if (update_bands)
+ update_headphone_eq_bands();
+}
+
+void update_headphone_eq_bands()
+{
+ int i;
+ int j;
+ int k = 0;
+ int first_reg = WM8994_AIF1_DAC1_EQ_BAND_1_A;
+
+ for (i = 0; i < ARRAY_SIZE(eq_band_values); i++) {
+ if (debug_log(LOG_INFOS))
+ printk("Voodoo sound: send EQ Band %d\n", i + 1);
+
+ for (j = 0; j < eq_bands[i]; j++) {
+ wm8994_write(codec,
+ first_reg + k, eq_band_values[i][j]);
+ k++;
+ }
+ }
+}
+
+void smooth_apply_eq_band_gain(int band, int start, int end, bool current_state)
+{
+ if (debug_log(LOG_INFOS))
+ printk("Voodoo sound: EQ smooth transition for Band %d "
+ "from %d to %d\n", band + 1, start, end);
+
+ if (start == end) {
+ if (end != 0)
+ update_headphone_eq(true);
+ else
+ update_headphone_eq(false);
+ return;
+ }
+
+ if (current_state)
+ update_headphone_eq_bands();
+
+ while (start != end) {
+ if (start < end)
+ start++;
+ else
+ start--;
+
+ eq_gains[band] = start;
+ update_headphone_eq(false);
+ }
+}
+
+void update_stereo_expansion(bool with_mute)
+{
+ short unsigned int val;
+
+ val = wm8994_read(codec, WM8994_AIF1_DAC1_FILTERS_2);
+ if (stereo_expansion) {
+ val &= ~(WM8994_AIF1DAC1_3D_GAIN_MASK);
+ val |= (stereo_expansion_gain << WM8994_AIF1DAC1_3D_GAIN_SHIFT);
+ }
+ val &= ~(WM8994_AIF1DAC1_3D_ENA_MASK);
+ val |= (stereo_expansion << WM8994_AIF1DAC1_3D_ENA_SHIFT);
+
+ wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_2, val);
+}
+
+void load_current_eq_values()
+{
+ int i;
+ int j;
+ int k = 0;
+ int first_reg = WM8994_AIF1_DAC1_EQ_BAND_1_A;
+
+ for (i = 0; i < ARRAY_SIZE(eq_band_values); i++)
+ for (j = 0; j < eq_bands[i]; j++) {
+ eq_band_values[i][j] =
+ wm8994_read(codec, first_reg + k);
+ k++;
+ }
+}
+
+void apply_saturation_prevention_drc()
+{
+ unsigned short val;
+ unsigned short drc_gain = 0;
+ int i;
+ int step = 750;
+
+ // don't apply the limiter if not playing media
+ // (exclude FM radio, it has its own DRC settings)
+ if (!is_path_media_or_fm_no_call_no_record()
+ || is_path(RADIO_HEADPHONES))
+ return;
+
+ // don't apply the limiter without stereo_expansion or headphone_eq
+ // or a positive digital gain
+ if (!(stereo_expansion
+ || headphone_eq
+ || digital_gain >= 0))
+ return;
+
+ if (debug_log(LOG_INFOS))
+ printk("Voodoo sound: apply saturation prevention DRC\n");
+
+ // configure the DRC to avoid saturation: not actually compress signal
+ // gain is unmodified. Should affect only what's higher than 0 dBFS
+
+ // tune Attack & Decacy values
+ val = wm8994_read(codec, WM8994_AIF1_DRC1_2);
+ val &= ~(WM8994_AIF1DRC1_ATK_MASK);
+ val &= ~(WM8994_AIF1DRC1_DCY_MASK);
+ val |= (0x1 << WM8994_AIF1DRC1_ATK_SHIFT);
+ val |= (0x4 << WM8994_AIF1DRC1_DCY_SHIFT);
+
+ // set DRC maximum gain to 36 dB
+ val &= ~(WM8994_AIF1DRC1_MAXGAIN_MASK);
+ val |= (0x3 << WM8994_AIF1DRC1_MAXGAIN_SHIFT);
+
+ wm8994_write(codec, WM8994_AIF1_DRC1_2, val);
+
+ // Above knee: flat (what really avoid the saturation)
+ val = wm8994_read(codec, WM8994_AIF1_DRC1_3);
+ val |= (0x5 << WM8994_AIF1DRC1_HI_COMP_SHIFT);
+ wm8994_write(codec, WM8994_AIF1_DRC1_3, val);
+
+ val = wm8994_read(codec, WM8994_AIF1_DRC1_1);
+ // disable Quick Release and Anti Clip
+ // both do do more harm than good for this particular usage
+ val &= ~(WM8994_AIF1DRC1_QR_MASK);
+ val &= ~(WM8994_AIF1DRC1_ANTICLIP_MASK);
+
+ // enable DRC
+ val &= ~(WM8994_AIF1DAC1_DRC_ENA_MASK);
+ val |= WM8994_AIF1DAC1_DRC_ENA;
+ wm8994_write(codec, WM8994_AIF1_DRC1_1, val);
+
+ val = wm8994_read(codec, WM8994_AIF1_DRC1_4);
+ val &= ~(WM8994_AIF1DRC1_KNEE_IP_MASK);
+
+ if (digital_gain >= 0) {
+ // deal with positive digital gains
+ i = ((digital_gain * 10 / step) + 5) / 10;
+ drc_gain += i;
+ val |= (drc_gain << WM8994_AIF1DRC1_KNEE_IP_SHIFT);
+
+ if (debug_log(LOG_INFOS))
+ printk("Voodoo sound: digital gain: %d mdB, "
+ "%d mdB steps: %d, real DRC gain: %d mdB\n",
+ digital_gain, step, i, i * step);
+
+ }
+ wm8994_write(codec, WM8994_AIF1_DRC1_4, val);
+}
+
+/*
+ *
+ * Declaring the controling misc devices
+ *
+ */
+static ssize_t debug_log_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%u\n", debug_log_level);
+}
+
+static ssize_t debug_log_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ sscanf(buf, "%hu", &debug_log_level);
+ return size;
+}
+
+#ifdef CONFIG_SND_VOODOO_HP_LEVEL_CONTROL
+static ssize_t headphone_amplifier_level_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ // output median of left and right headphone amplifier volumes
+ return sprintf(buf, "%u\n", (hp_level[0] + hp_level[1]) / 2);
+}
+
+static ssize_t headphone_amplifier_level_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned short vol;
+ if (sscanf(buf, "%hu", &vol) == 1) {
+
+ // hard limit to 62 because 63 introduces distortions
+ if (vol > 62)
+ vol = 62;
+
+ // left and right are set to the same volumes by this control
+ hp_level[0] = hp_level[1] = vol;
+
+ update_digital_gain(false);
+ update_hpvol(true);
+ }
+ return size;
+}
+#endif
+
+#ifdef NEXUS_S
+DECLARE_BOOL_SHOW(speaker_tuning);
+DECLARE_BOOL_STORE_UPDATE_WITH_MUTE(speaker_tuning,
+ update_speaker_tuning,
+ false);
+#endif
+
+#ifdef CONFIG_SND_VOODOO_FM
+DECLARE_BOOL_SHOW(fm_radio_headset_restore_bass);
+DECLARE_BOOL_STORE_UPDATE_WITH_MUTE(fm_radio_headset_restore_bass,
+ update_fm_radio_headset_restore_freqs,
+ true);
+
+DECLARE_BOOL_SHOW(fm_radio_headset_restore_highs);
+DECLARE_BOOL_STORE_UPDATE_WITH_MUTE(fm_radio_headset_restore_highs,
+ update_fm_radio_headset_restore_freqs,
+ true);
+
+DECLARE_BOOL_SHOW(fm_radio_headset_normalize_gain);
+DECLARE_BOOL_STORE_UPDATE_WITH_MUTE(fm_radio_headset_normalize_gain,
+ update_fm_radio_headset_normalize_gain,
+ false);
+#endif
+
+#ifdef CONFIG_SND_VOODOO_RECORD_PRESETS
+static ssize_t recording_preset_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", recording_preset);
+}
+
+static ssize_t recording_preset_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned short preset_number;
+ if (sscanf(buf, "%hu", &preset_number) == 1) {
+ recording_preset = preset_number;
+ update_recording_preset(false);
+ }
+ return size;
+}
+#endif
+
+DECLARE_BOOL_SHOW(dac_osr128);
+DECLARE_BOOL_STORE_UPDATE_WITH_MUTE(dac_osr128,
+ update_osr128,
+ false);
+
+DECLARE_BOOL_SHOW(adc_osr128);
+DECLARE_BOOL_STORE_UPDATE_WITH_MUTE(adc_osr128,
+ update_osr128,
+ false);
+
+#ifndef GALAXY_TAB_TEGRA
+DECLARE_BOOL_SHOW(fll_tuning);
+DECLARE_BOOL_STORE_UPDATE_WITH_MUTE(fll_tuning,
+ update_fll_tuning,
+ false);
+#endif
+
+DECLARE_BOOL_SHOW(mono_downmix);
+DECLARE_BOOL_STORE_UPDATE_WITH_MUTE(mono_downmix,
+ update_mono_downmix,
+ false);
+
+DECLARE_BOOL_SHOW(dac_direct);
+DECLARE_BOOL_STORE_UPDATE_WITH_MUTE(dac_direct,
+ update_dac_direct,
+ false);
+
+static ssize_t digital_gain_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", digital_gain);
+}
+
+static ssize_t digital_gain_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ int new_digital_gain;
+ if (sscanf(buf, "%d", &new_digital_gain) == 1) {
+ if (new_digital_gain <= 36000 && new_digital_gain >= -71625) {
+ if (new_digital_gain > digital_gain) {
+ // reduce analog volume first
+ digital_gain = new_digital_gain;
+#ifdef CONFIG_SND_VOODOO_HP_LEVEL_CONTROL
+ update_hpvol(false);
+#endif
+ update_digital_gain(false);
+ } else {
+ // reduce digital volume first
+ digital_gain = new_digital_gain;
+ update_digital_gain(false);
+#ifdef CONFIG_SND_VOODOO_HP_LEVEL_CONTROL
+ update_hpvol(false);
+#endif
+ }
+ }
+ apply_saturation_prevention_drc();
+ }
+ return size;
+}
+
+DECLARE_BOOL_SHOW(headphone_eq);
+static ssize_t headphone_eq_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned short state;
+ bool current_state;
+ int i;
+ short eq_gains_copy[ARRAY_SIZE(eq_gains)];
+
+ if (sscanf(buf, "%hu", &state) == 1) {
+ current_state = state == 0 ? false : true;
+ if (debug_log(LOG_INFOS))
+ printk("Voodoo sound: EQ activation: %u\n", state);
+
+ if (current_state) {
+ // fade from 0dB each EQ band
+ headphone_eq = current_state;
+ for (i = 0; i < ARRAY_SIZE(eq_bands); i++)
+ smooth_apply_eq_band_gain(i, 0, eq_gains[i],
+ current_state);
+ } else {
+ // fade to 0dB each EQ band
+ for (i = 0; i < ARRAY_SIZE(eq_bands); i++) {
+ eq_gains_copy[i] = eq_gains[i];
+ smooth_apply_eq_band_gain(i, eq_gains[i], 0,
+ current_state);
+ }
+ // restore original gains in driver memory not codec
+ for (i = 0; i < ARRAY_SIZE(eq_bands); i++)
+ eq_gains[i] = eq_gains_copy[i];
+ headphone_eq = current_state;
+ }
+ }
+ return size;
+}
+
+DECLARE_EQ_GAIN_SHOW(1);
+DECLARE_EQ_GAIN_STORE(1);
+DECLARE_EQ_GAIN_SHOW(2);
+DECLARE_EQ_GAIN_STORE(2);
+DECLARE_EQ_GAIN_SHOW(3);
+DECLARE_EQ_GAIN_STORE(3);
+DECLARE_EQ_GAIN_SHOW(4);
+DECLARE_EQ_GAIN_STORE(4);
+DECLARE_EQ_GAIN_SHOW(5);
+DECLARE_EQ_GAIN_STORE(5);
+
+static ssize_t headphone_eq_bands_values_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int i;
+ int j;
+ int k = 0;
+ int first_reg = WM8994_AIF1_DAC1_EQ_BAND_1_A;
+ int bands_size = ARRAY_SIZE(eq_bands);
+ char *name;
+
+ for (i = 0; i < bands_size; i++)
+ for (j = 0; j < eq_bands[i]; j++) {
+
+ // display 3-coef bands properly (hi & lo shelf)
+ if (j + 1 == eq_bands[i])
+ name = eq_band_coef_names[3];
+ else
+ name = eq_band_coef_names[j];
+
+ sprintf(buf, "%s%d %s 0x%04X\n", buf,
+ i + 1, name,
+ wm8994_read(codec, first_reg + k));
+ k++;
+ }
+
+ return sprintf(buf, "%s", buf);
+}
+
+static ssize_t headphone_eq_bands_values_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ int i;
+ short unsigned int val;
+ short unsigned int band;
+ char coef_name[2];
+ unsigned int bytes_read = 0;
+
+ while (sscanf(buf, "%hu %s %hx%n",
+ &band, coef_name, &val, &bytes_read) == 3) {
+
+ buf += bytes_read;
+
+ if (band < 1 || band > 5)
+ continue;
+
+ for (i = 0; i < ARRAY_SIZE(eq_band_coef_names); i++) {
+ // loop through band coefficient letters
+ if (strncmp(eq_band_coef_names[i], coef_name, 2) == 0) {
+ if (eq_bands[band - 1] == 3 && i == 3)
+ // deal with high and low shelves
+ eq_band_values[band - 1][2] = val;
+ else
+ // parametric bands
+ eq_band_values[band - 1][i] = val;
+
+ if (debug_log(LOG_INFOS))
+ printk("Voodoo sound: read EQ from "
+ "sysfs: EQ Band %hd %s: 0x%04X\n"
+ , band, coef_name, val);
+ break;
+ }
+ }
+ }
+
+ return size;
+}
+
+DECLARE_BOOL_SHOW(stereo_expansion);
+DECLARE_BOOL_STORE_UPDATE_WITH_MUTE(stereo_expansion,
+ update_stereo_expansion,
+ false);
+
+static ssize_t stereo_expansion_gain_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%u\n", stereo_expansion_gain);
+}
+
+static ssize_t stereo_expansion_gain_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ short unsigned val;
+
+ if (sscanf(buf, "%hu", &val) == 1)
+ if (val >= 0 && val < 32) {
+ stereo_expansion_gain = val;
+ update_stereo_expansion(false);
+ }
+
+ return size;
+}
+
+#ifdef CONFIG_SND_VOODOO_DEVELOPMENT
+static ssize_t show_wm8994_register_dump(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ // modified version of register_dump from wm8994_aries.c
+ // r = wm8994 register
+ int r;
+
+ for (r = 0; r <= 0x6; r++)
+ sprintf(buf, "%s0x%X 0x%X\n", buf, r, wm8994_read(codec, r));
+
+ sprintf(buf, "%s0x%X 0x%X\n", buf, 0x15, wm8994_read(codec, 0x15));
+
+ for (r = 0x18; r <= 0x3C; r++)
+ sprintf(buf, "%s0x%X 0x%X\n", buf, r, wm8994_read(codec, r));
+
+ sprintf(buf, "%s0x%X 0x%X\n", buf, 0x4C, wm8994_read(codec, 0x4C));
+
+ for (r = 0x51; r <= 0x5C; r++)
+ sprintf(buf, "%s0x%X 0x%X\n", buf, r, wm8994_read(codec, r));
+
+ sprintf(buf, "%s0x%X 0x%X\n", buf, 0x60, wm8994_read(codec, 0x60));
+ sprintf(buf, "%s0x%X 0x%X\n", buf, 0x101, wm8994_read(codec, 0x101));
+ sprintf(buf, "%s0x%X 0x%X\n", buf, 0x110, wm8994_read(codec, 0x110));
+ sprintf(buf, "%s0x%X 0x%X\n", buf, 0x111, wm8994_read(codec, 0x111));
+
+ for (r = 0x200; r <= 0x212; r++)
+ sprintf(buf, "%s0x%X 0x%X\n", buf, r, wm8994_read(codec, r));
+
+ for (r = 0x220; r <= 0x224; r++)
+ sprintf(buf, "%s0x%X 0x%X\n", buf, r, wm8994_read(codec, r));
+
+ for (r = 0x240; r <= 0x244; r++)
+ sprintf(buf, "%s0x%X 0x%X\n", buf, r, wm8994_read(codec, r));
+
+ for (r = 0x300; r <= 0x317; r++)
+ sprintf(buf, "%s0x%X 0x%X\n", buf, r, wm8994_read(codec, r));
+
+ for (r = 0x400; r <= 0x411; r++)
+ sprintf(buf, "%s0x%X 0x%X\n", buf, r, wm8994_read(codec, r));
+
+ for (r = 0x420; r <= 0x423; r++)
+ sprintf(buf, "%s0x%X 0x%X\n", buf, r, wm8994_read(codec, r));
+
+ for (r = 0x440; r <= 0x444; r++)
+ sprintf(buf, "%s0x%X 0x%X\n", buf, r, wm8994_read(codec, r));
+
+ for (r = 0x450; r <= 0x454; r++)
+ sprintf(buf, "%s0x%X 0x%X\n", buf, r, wm8994_read(codec, r));
+
+ for (r = 0x480; r <= 0x493; r++)
+ sprintf(buf, "%s0x%X 0x%X\n", buf, r, wm8994_read(codec, r));
+
+ for (r = 0x4A0; r <= 0x4B3; r++)
+ sprintf(buf, "%s0x%X 0x%X\n", buf, r, wm8994_read(codec, r));
+
+ for (r = 0x500; r <= 0x503; r++)
+ sprintf(buf, "%s0x%X 0x%X\n", buf, r, wm8994_read(codec, r));
+
+ sprintf(buf, "%s0x%X 0x%X\n", buf, 0x510, wm8994_read(codec, 0x510));
+ sprintf(buf, "%s0x%X 0x%X\n", buf, 0x520, wm8994_read(codec, 0x520));
+ sprintf(buf, "%s0x%X 0x%X\n", buf, 0x521, wm8994_read(codec, 0x521));
+
+ for (r = 0x540; r <= 0x544; r++)
+ sprintf(buf, "%s0x%X 0x%X\n", buf, r, wm8994_read(codec, r));
+
+ for (r = 0x580; r <= 0x593; r++)
+ sprintf(buf, "%s0x%X 0x%X\n", buf, r, wm8994_read(codec, r));
+
+ for (r = 0x600; r <= 0x614; r++)
+ sprintf(buf, "%s0x%X 0x%X\n", buf, r, wm8994_read(codec, r));
+
+ sprintf(buf, "%s0x%X 0x%X\n", buf, 0x620, wm8994_read(codec, 0x620));
+ sprintf(buf, "%s0x%X 0x%X\n", buf, 0x621, wm8994_read(codec, 0x621));
+
+ for (r = 0x700; r <= 0x70A; r++)
+ sprintf(buf, "%s0x%X 0x%X\n", buf, r, wm8994_read(codec, r));
+
+ return sprintf(buf, "%s", buf);
+}
+
+static ssize_t store_wm8994_write(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ short unsigned int reg = 0;
+ short unsigned int val = 0;
+ int unsigned bytes_read = 0;
+
+ while (sscanf(buf, "%hx %hx%n", &reg, &val, &bytes_read) == 2) {
+ buf += bytes_read;
+ if (debug_log(LOG_INFOS))
+ printk("Voodoo sound: read from sysfs: %X, %X\n",
+ reg, val);
+
+ bypass_write_hook = true;
+ wm8994_write(codec, reg, val);
+ bypass_write_hook = false;
+ }
+ return size;
+}
+#endif
+
+static ssize_t voodoo_sound_version(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%u\n", VOODOO_SOUND_VERSION);
+}
+
+#ifndef MODULE
+DECLARE_BOOL_SHOW(enable);
+static ssize_t enable_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t size)
+{
+ unsigned short state;
+ bool bool_state;
+ if (sscanf(buf, "%hu", &state) == 1) {
+ bool_state = state == 0 ? false : true;
+ if (state != enable) {
+ enable = bool_state;
+ update_enable();
+ }
+ }
+ return size;
+}
+#endif
+
+static DEVICE_ATTR(debug_log, S_IRUGO | S_IWUGO,
+ debug_log_show,
+ debug_log_store);
+
+#ifdef CONFIG_SND_VOODOO_HP_LEVEL_CONTROL
+static DEVICE_ATTR(headphone_amplifier_level, S_IRUGO | S_IWUGO,
+ headphone_amplifier_level_show,
+ headphone_amplifier_level_store);
+#endif
+
+#ifdef NEXUS_S
+static DEVICE_ATTR(speaker_tuning, S_IRUGO | S_IWUGO,
+ speaker_tuning_show,
+ speaker_tuning_store);
+#endif
+
+#ifdef CONFIG_SND_VOODOO_FM
+static DEVICE_ATTR(fm_radio_headset_restore_bass, S_IRUGO | S_IWUGO,
+ fm_radio_headset_restore_bass_show,
+ fm_radio_headset_restore_bass_store);
+
+static DEVICE_ATTR(fm_radio_headset_restore_highs, S_IRUGO | S_IWUGO,
+ fm_radio_headset_restore_highs_show,
+ fm_radio_headset_restore_highs_store);
+
+static DEVICE_ATTR(fm_radio_headset_normalize_gain, S_IRUGO | S_IWUGO,
+ fm_radio_headset_normalize_gain_show,
+ fm_radio_headset_normalize_gain_store);
+#endif
+
+#ifdef CONFIG_SND_VOODOO_RECORD_PRESETS
+static DEVICE_ATTR(recording_preset, S_IRUGO | S_IWUGO,
+ recording_preset_show,
+ recording_preset_store);
+#endif
+
+static DEVICE_ATTR(dac_osr128, S_IRUGO | S_IWUGO,
+ dac_osr128_show,
+ dac_osr128_store);
+
+static DEVICE_ATTR(adc_osr128, S_IRUGO | S_IWUGO,
+ adc_osr128_show,
+ adc_osr128_store);
+
+#ifndef GALAXY_TAB_TEGRA
+static DEVICE_ATTR(fll_tuning, S_IRUGO | S_IWUGO,
+ fll_tuning_show,
+ fll_tuning_store);
+#endif
+
+static DEVICE_ATTR(dac_direct, S_IRUGO | S_IWUGO,
+ dac_direct_show,
+ dac_direct_store);
+
+static DEVICE_ATTR(digital_gain, S_IRUGO | S_IWUGO,
+ digital_gain_show,
+ digital_gain_store);
+
+static DEVICE_ATTR(headphone_eq, S_IRUGO | S_IWUGO,
+ headphone_eq_show,
+ headphone_eq_store);
+
+static DEVICE_ATTR(headphone_eq_b1_gain, S_IRUGO | S_IWUGO,
+ headphone_eq_b1_gain_show,
+ headphone_eq_b1_gain_store);
+
+static DEVICE_ATTR(headphone_eq_b2_gain, S_IRUGO | S_IWUGO,
+ headphone_eq_b2_gain_show,
+ headphone_eq_b2_gain_store);
+
+static DEVICE_ATTR(headphone_eq_b3_gain, S_IRUGO | S_IWUGO,
+ headphone_eq_b3_gain_show,
+ headphone_eq_b3_gain_store);
+
+static DEVICE_ATTR(headphone_eq_b4_gain, S_IRUGO | S_IWUGO,
+ headphone_eq_b4_gain_show,
+ headphone_eq_b4_gain_store);
+
+static DEVICE_ATTR(headphone_eq_b5_gain, S_IRUGO | S_IWUGO,
+ headphone_eq_b5_gain_show,
+ headphone_eq_b5_gain_store);
+
+static DEVICE_ATTR(headphone_eq_bands_values, S_IRUGO | S_IWUGO,
+ headphone_eq_bands_values_show,
+ headphone_eq_bands_values_store);
+
+static DEVICE_ATTR(stereo_expansion, S_IRUGO | S_IWUGO,
+ stereo_expansion_show,
+ stereo_expansion_store);
+
+static DEVICE_ATTR(stereo_expansion_gain, S_IRUGO | S_IWUGO,
+ stereo_expansion_gain_show,
+ stereo_expansion_gain_store);
+
+static DEVICE_ATTR(mono_downmix, S_IRUGO | S_IWUGO,
+ mono_downmix_show,
+ mono_downmix_store);
+
+#ifdef CONFIG_SND_VOODOO_DEVELOPMENT
+static DEVICE_ATTR(wm8994_register_dump, S_IRUGO,
+ show_wm8994_register_dump,
+ NULL);
+
+static DEVICE_ATTR(wm8994_write, S_IWUSR,
+ NULL,
+ store_wm8994_write);
+#endif
+
+static DEVICE_ATTR(version, S_IRUGO,
+ voodoo_sound_version,
+ NULL);
+
+#ifndef MODULE
+static DEVICE_ATTR(enable, S_IRUGO | S_IWUGO,
+ enable_show,
+ enable_store);
+#endif
+
+#ifdef MODULE
+static DEVICE_ATTR(module, 0,
+ NULL,
+ NULL);
+#endif
+
+static struct attribute *voodoo_sound_attributes[] = {
+ &dev_attr_debug_log.attr,
+#ifdef CONFIG_SND_VOODOO_HP_LEVEL_CONTROL
+ &dev_attr_headphone_amplifier_level.attr,
+#endif
+#ifdef NEXUS_S
+ &dev_attr_speaker_tuning.attr,
+#endif
+#ifdef CONFIG_SND_VOODOO_FM
+ &dev_attr_fm_radio_headset_restore_bass.attr,
+ &dev_attr_fm_radio_headset_restore_highs.attr,
+ &dev_attr_fm_radio_headset_normalize_gain.attr,
+#endif
+#ifdef CONFIG_SND_VOODOO_RECORD_PRESETS
+ &dev_attr_recording_preset.attr,
+#endif
+ &dev_attr_dac_osr128.attr,
+ &dev_attr_adc_osr128.attr,
+#ifndef GALAXY_TAB_TEGRA
+ &dev_attr_fll_tuning.attr,
+#endif
+ &dev_attr_dac_direct.attr,
+ &dev_attr_digital_gain.attr,
+ &dev_attr_headphone_eq.attr,
+ &dev_attr_headphone_eq_b1_gain.attr,
+ &dev_attr_headphone_eq_b2_gain.attr,
+ &dev_attr_headphone_eq_b3_gain.attr,
+ &dev_attr_headphone_eq_b4_gain.attr,
+ &dev_attr_headphone_eq_b5_gain.attr,
+ &dev_attr_headphone_eq_bands_values.attr,
+ &dev_attr_stereo_expansion.attr,
+ &dev_attr_stereo_expansion_gain.attr,
+ &dev_attr_mono_downmix.attr,
+#ifdef CONFIG_SND_VOODOO_DEVELOPMENT
+ &dev_attr_wm8994_register_dump.attr,
+ &dev_attr_wm8994_write.attr,
+#endif
+#ifdef MODULE
+ &dev_attr_module.attr,
+#endif
+ &dev_attr_version.attr,
+ NULL
+};
+
+#ifndef MODULE
+static struct attribute *voodoo_sound_control_attributes[] = {
+ &dev_attr_enable.attr,
+ NULL
+};
+#endif
+
+static struct attribute_group voodoo_sound_group = {
+ .attrs = voodoo_sound_attributes,
+};
+
+#ifndef MODULE
+static struct attribute_group voodoo_sound_control_group = {
+ .attrs = voodoo_sound_control_attributes,
+};
+#endif
+
+static struct miscdevice voodoo_sound_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "voodoo_sound",
+};
+
+#ifndef MODULE
+static struct miscdevice voodoo_sound_control_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "voodoo_sound_control",
+};
+#endif
+
+void voodoo_hook_wm8994_pcm_remove()
+{
+ printk("Voodoo sound: removing driver v%d\n", VOODOO_SOUND_VERSION);
+ sysfs_remove_group(&voodoo_sound_device.this_device->kobj,
+ &voodoo_sound_group);
+ misc_deregister(&voodoo_sound_device);
+}
+
+void update_enable()
+{
+ if (enable) {
+ printk("Voodoo sound: initializing driver v%d\n",
+ VOODOO_SOUND_VERSION);
+
+#ifdef CONFIG_SND_VOODOO_DEVELOPMENT
+ printk("Voodoo sound: codec development tools enabled\n");
+#endif
+
+ misc_register(&voodoo_sound_device);
+ if (sysfs_create_group(&voodoo_sound_device.this_device->kobj,
+ &voodoo_sound_group) < 0) {
+ printk("%s sysfs_create_group fail\n", __FUNCTION__);
+ pr_err("Failed to create sysfs group for (%s)!\n",
+ voodoo_sound_device.name);
+ }
+ } else
+ voodoo_hook_wm8994_pcm_remove();
+}
+
+/*
+ *
+ * Driver Hooks
+ *
+ */
+
+#ifdef CONFIG_SND_VOODOO_FM
+void voodoo_hook_fmradio_headset()
+{
+ // global kill switch
+ if (!enable)
+ return;
+
+ if (!fm_radio_headset_restore_bass
+ && !fm_radio_headset_restore_highs
+ && !fm_radio_headset_normalize_gain)
+ return;
+
+ update_fm_radio_headset_restore_freqs(false);
+ update_fm_radio_headset_normalize_gain(false);
+}
+#endif
+
+#ifdef CONFIG_SND_VOODOO_RECORD_PRESETS
+void voodoo_hook_record_main_mic()
+{
+ // global kill switch
+ if (!enable)
+ return;
+
+ if (recording_preset == 0)
+ return;
+
+ origin_recgain = wm8994_read(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME);
+ origin_recgain_mixer = wm8994_read(codec, WM8994_INPUT_MIXER_3);
+ update_recording_preset(false);
+}
+#endif
+
+#ifdef NEXUS_S
+void voodoo_hook_playback_speaker()
+{
+ // global kill switch
+ if (!enable)
+ return;
+ if (!speaker_tuning)
+ return;
+
+ update_speaker_tuning(false);
+}
+#endif
+
+unsigned int voodoo_hook_wm8994_write(struct snd_soc_codec *codec_,
+ unsigned int reg, unsigned int value)
+{
+ DECLARE_WM8994(codec_);
+
+ // global kill switch
+ if (!enable)
+ return value;
+
+ // modify some registers before those being written to the codec
+ // be sure our pointer to codec is up to date
+ codec = codec_;
+
+ if (!bypass_write_hook) {
+
+#ifdef CONFIG_SND_VOODOO_HP_LEVEL_CONTROL
+ if (is_path(HEADPHONES)
+ && !(wm8994->codec_state & CALL_ACTIVE)) {
+
+ if (reg == WM8994_LEFT_OUTPUT_VOLUME)
+ value =
+ (WM8994_HPOUT1_VU |
+ WM8994_HPOUT1L_MUTE_N |
+ hpvol(0));
+
+ if (reg == WM8994_RIGHT_OUTPUT_VOLUME)
+ value =
+ (WM8994_HPOUT1_VU |
+ WM8994_HPOUT1R_MUTE_N |
+ hpvol(1));
+ }
+#endif
+
+#ifdef CONFIG_SND_VOODOO_FM
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+ // FM tuning virtual hook for Gingerbread
+ if (is_path(RADIO_HEADPHONES)) {
+ if (reg == WM8994_AIF2_DRC_1
+ || reg == WM8994_AIF2_DAC_FILTERS_1)
+ voodoo_hook_fmradio_headset();
+ }
+#else
+ // FM tuning virtual hook for Froyo
+ if (is_path(RADIO_HEADPHONES)) {
+ if (reg == WM8994_INPUT_MIXER_2
+ || reg == WM8994_AIF2_DRC_1
+ || reg == WM8994_ANALOGUE_HP_1)
+ voodoo_hook_fmradio_headset();
+ }
+#endif
+#endif
+ // global Oversampling tuning
+ if (reg == WM8994_OVERSAMPLING)
+ value = osr128_get_value(value);
+
+#ifndef GALAXY_TAB_TEGRA
+ // global Anti-Jitter tuning
+ if (reg == WM8994_FLL1_CONTROL_4)
+ value = fll_tuning_get_value(value);
+#endif
+
+ // global Mono downmix tuning
+ if (reg == WM8994_AIF1_DAC1_FILTERS_1
+ || reg == WM8994_AIF1_DAC2_FILTERS_1
+ || reg == WM8994_AIF2_DAC_FILTERS_1)
+ value = mono_downmix_get_value(value, false);
+
+ // DAC direct tuning virtual hook
+ if (reg == WM8994_OUTPUT_MIXER_1
+ || reg == WM8994_OUTPUT_MIXER_2)
+ value = dac_direct_get_value(value, false);
+
+ // Digital Headroom virtual hook
+ if (reg == WM8994_AIF1_DAC1_LEFT_VOLUME
+ || reg == WM8994_AIF1_DAC1_RIGHT_VOLUME)
+ value = digital_gain_get_value(value);
+
+ // Headphones EQ & 3D virtual hook
+ if (reg == WM8994_AIF1_DAC1_FILTERS_1
+ || reg == WM8994_AIF1_DAC2_FILTERS_1
+ || reg == WM8994_AIF2_DAC_FILTERS_1) {
+ bypass_write_hook = true;
+ apply_saturation_prevention_drc();
+ update_headphone_eq(true);
+ update_stereo_expansion(false);
+ bypass_write_hook = false;
+ }
+
+ }
+ if (debug_log(LOG_VERBOSE))
+ // log every write to dmesg
+ printk("Voodoo sound: wm8994_write 0x%03X 0x%04X "
+#ifdef NEXUS_S
+ "codec_state=%u, stream_state=%u, "
+ "cur_path=%i, rec_path=%i, "
+ "power_state=%i\n",
+ reg, value,
+ wm8994->codec_state, wm8994->stream_state,
+ wm8994->cur_path, wm8994->rec_path,
+ wm8994->power_state);
+#else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+ "codec_state=%u, stream_state=%u, "
+ "cur_path=%i, rec_path=%i, "
+#if !defined(M110S) && !defined(GALAXY_TAB_TEGRA)
+ "fmradio_path=%i, fmr_mix_path=%i, "
+#endif
+#ifndef GALAXY_TAB
+ "input_source=%i, "
+#endif
+#if !defined(M110S) && !defined(GALAXY_TAB_TEGRA) && !defined(GALAXY_TAB)
+ "output_source=%i, "
+#endif
+ "power_state=%i\n",
+ reg, value,
+ wm8994->codec_state, wm8994->stream_state,
+#if !defined(M110S) && !defined(GALAXY_TAB_TEGRA)
+ wm8994->fmradio_path, wm8994->fmr_mix_path,
+#endif
+ wm8994->cur_path, wm8994->rec_path,
+#ifndef GALAXY_TAB
+ wm8994->input_source,
+#endif
+#if !defined(M110S) && !defined(GALAXY_TAB_TEGRA) && !defined(GALAXY_TAB)
+ wm8994->output_source,
+#endif
+ wm8994->power_state);
+#else
+ "codec_state=%u, stream_state=%u, "
+ "cur_path=%i, rec_path=%i, "
+#if !defined(M110S) && !defined(GALAXY_TAB_TEGRA)
+ "fmradio_path=%i, fmr_mix_path=%i, "
+#endif
+#ifdef CONFIG_S5PC110_KEPLER_BOARD
+ "call_record_path=%i, call_record_ch=%i, "
+ "AUDIENCE_state=%i, "
+ "Fac_SUB_MIC_state=%i, TTY_state=%i, "
+#endif
+ "power_state=%i, "
+#if !defined(M110S) && !defined(GALAXY_TAB_TEGRA)
+ "recognition_active=%i, ringtone_active=%i"
+#endif
+ "\n",
+ reg, value,
+ wm8994->codec_state, wm8994->stream_state,
+ wm8994->cur_path, wm8994->rec_path,
+#if !defined(M110S) && !defined(GALAXY_TAB_TEGRA)
+ wm8994->fmradio_path, wm8994->fmr_mix_path,
+#endif
+#ifdef CONFIG_S5PC110_KEPLER_BOARD
+ wm8994->call_record_path, wm8994->call_record_ch,
+ wm8994->AUDIENCE_state,
+ wm8994->Fac_SUB_MIC_state, wm8994->TTY_state,
+#endif
+ wm8994->power_state
+#if !defined(M110S) && !defined(GALAXY_TAB_TEGRA)
+ ,wm8994->recognition_active,
+ wm8994->ringtone_active
+#endif
+ );
+#endif
+#endif
+ return value;
+}
+
+void voodoo_hook_wm8994_pcm_probe(struct snd_soc_codec *codec_)
+{
+ enable = true;
+ update_enable();
+
+#ifndef MODULE
+ misc_register(&voodoo_sound_control_device);
+ if (sysfs_create_group(&voodoo_sound_control_device.this_device->kobj,
+ &voodoo_sound_control_group) < 0) {
+ printk("%s sysfs_create_group fail\n", __FUNCTION__);
+ pr_err("Failed to create sysfs group for device (%s)!\n",
+ voodoo_sound_control_device.name);
+ }
+#endif
+
+ // make a copy of the codec pointer
+ codec = codec_;
+
+ // initialize eq_band_values[] from default codec EQ values
+ load_current_eq_values();
+}
diff --git a/sound/soc/codecs/wm8994_voodoo.h b/sound/soc/codecs/wm8994_voodoo.h
new file mode 100644
index 0000000..578f8e8
--- /dev/null
+++ b/sound/soc/codecs/wm8994_voodoo.h
@@ -0,0 +1,67 @@
+/*
+ * wm8994.h -- WM8994 Soc Audio driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define VOODOO_SOUND_VERSION 10
+
+#if defined(CONFIG_MACH_HERRING) || defined (CONFIG_SAMSUNG_GALAXYS) \
+ || defined (CONFIG_SAMSUNG_GALAXYSB) \
+ || defined (CONFIG_SAMSUNG_CAPTIVATE) \
+ || defined (CONFIG_SAMSUNG_VIBRANT) \
+ || defined (CONFIG_SAMSUNG_FASCINATE) \
+ || defined (CONFIG_SAMSUNG_EPIC)
+#define NEXUS_S
+#endif
+
+#if defined(CONFIG_FB_S3C_AMS701KA) || defined(CONFIG_KOR_MODEL_M180S)
+#define GALAXY_TAB
+#endif
+
+#ifdef CONFIG_M110S
+#define M110S
+#endif
+
+#ifdef CONFIG_MACH_SAMSUNG_VARIATION_TEGRA
+#define GALAXY_TAB_TEGRA
+#endif
+
+#ifdef CONFIG_TDMB_T3700
+#define M110S
+#endif
+
+enum debug_log { LOG_OFF, LOG_INFOS, LOG_VERBOSE };
+bool debug_log(short unsigned int level);
+
+enum unified_path { HEADPHONES, RADIO_HEADPHONES, SPEAKER, MAIN_MICROPHONE };
+
+bool is_path(int unified_path);
+bool is_path_media_or_fm_no_call_no_record(void);
+unsigned int voodoo_hook_wm8994_write(struct snd_soc_codec *codec,
+ unsigned int reg, unsigned int value);
+void voodoo_hook_fmradio_headset(void);
+void voodoo_hook_wm8994_pcm_probe(struct snd_soc_codec *codec);
+void voodoo_hook_wm8994_pcm_remove(void);
+void voodoo_hook_record_main_mic(void);
+void voodoo_hook_playback_speaker(void);
+
+void load_current_eq_values(void);
+void apply_saturation_prevention_drc(void);
+
+void update_hpvol(bool with_fade);
+void update_fm_radio_headset_restore_freqs(bool with_mute);
+void update_fm_radio_headset_normalize_gain(bool with_mute);
+void update_recording_preset(bool with_mute);
+void update_full_bitwidth(bool with_mute);
+void update_osr128(bool with_mute);
+void update_fll_tuning(bool with_mute);
+void update_mono_downmix(bool with_mute);
+void update_dac_direct(bool with_mute);
+void update_digital_gain(bool with_mute);
+void update_stereo_expansion(bool with_mute);
+void update_headphone_eq(bool update_bands);
+void update_headphone_eq_bands(void);
+void update_enable(void);
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
index 90117f8..520a20e 100644
--- a/sound/soc/codecs/wm9712.c
+++ b/sound/soc/codecs/wm9712.c
@@ -144,7 +144,7 @@ SOC_SINGLE("Playback Attenuate (-6dB) Switch", AC97_MASTER_TONE, 6, 1, 0),
SOC_SINGLE("Bass Volume", AC97_MASTER_TONE, 8, 15, 1),
SOC_SINGLE("Treble Volume", AC97_MASTER_TONE, 0, 15, 1),
-SOC_SINGLE("Capture ADC Switch", AC97_REC_GAIN, 15, 1, 1),
+SOC_SINGLE("Capture Switch", AC97_REC_GAIN, 15, 1, 1),
SOC_ENUM("Capture Volume Steps", wm9712_enum[6]),
SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 1),
SOC_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0),
@@ -270,7 +270,7 @@ SOC_DAPM_ENUM("Route", wm9712_enum[9]);
/* Mic select */
static const struct snd_kcontrol_new wm9712_mic_src_controls =
-SOC_DAPM_ENUM("Route", wm9712_enum[7]);
+SOC_DAPM_ENUM("Mic Source Select", wm9712_enum[7]);
/* diff select */
static const struct snd_kcontrol_new wm9712_diff_sel_controls =
@@ -289,7 +289,9 @@ SND_SOC_DAPM_MUX("Left Capture Select", SND_SOC_NOPM, 0, 0,
&wm9712_capture_selectl_controls),
SND_SOC_DAPM_MUX("Right Capture Select", SND_SOC_NOPM, 0, 0,
&wm9712_capture_selectr_controls),
-SND_SOC_DAPM_MUX("Mic Select Source", SND_SOC_NOPM, 0, 0,
+SND_SOC_DAPM_MUX("Left Mic Select Source", SND_SOC_NOPM, 0, 0,
+ &wm9712_mic_src_controls),
+SND_SOC_DAPM_MUX("Right Mic Select Source", SND_SOC_NOPM, 0, 0,
&wm9712_mic_src_controls),
SND_SOC_DAPM_MUX("Differential Source", SND_SOC_NOPM, 0, 0,
&wm9712_diff_sel_controls),
@@ -317,6 +319,7 @@ SND_SOC_DAPM_PGA("Out 3 PGA", AC97_INT_PAGING, 5, 1, NULL, 0),
SND_SOC_DAPM_PGA("Line PGA", AC97_INT_PAGING, 2, 1, NULL, 0),
SND_SOC_DAPM_PGA("Phone PGA", AC97_INT_PAGING, 1, 1, NULL, 0),
SND_SOC_DAPM_PGA("Mic PGA", AC97_INT_PAGING, 0, 1, NULL, 0),
+SND_SOC_DAPM_PGA("Differential Mic", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MICBIAS("Mic Bias", AC97_INT_PAGING, 10, 1),
SND_SOC_DAPM_OUTPUT("MONOOUT"),
SND_SOC_DAPM_OUTPUT("HPOUTL"),
@@ -377,6 +380,18 @@ static const struct snd_soc_dapm_route wm9712_audio_map[] = {
{"Mic PGA", NULL, "MIC1"},
{"Mic PGA", NULL, "MIC2"},
+ /* microphones */
+ {"Differential Mic", NULL, "MIC1"},
+ {"Differential Mic", NULL, "MIC2"},
+ {"Left Mic Select Source", "Mic 1", "MIC1"},
+ {"Left Mic Select Source", "Mic 2", "MIC2"},
+ {"Left Mic Select Source", "Stereo", "MIC1"},
+ {"Left Mic Select Source", "Differential", "Differential Mic"},
+ {"Right Mic Select Source", "Mic 1", "MIC1"},
+ {"Right Mic Select Source", "Mic 2", "MIC2"},
+ {"Right Mic Select Source", "Stereo", "MIC2"},
+ {"Right Mic Select Source", "Differential", "Differential Mic"},
+
/* left capture selector */
{"Left Capture Select", "Mic", "MIC1"},
{"Left Capture Select", "Speaker Mixer", "Speaker Mixer"},
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig
index d155cbb..8601d70 100644
--- a/sound/soc/samsung/Kconfig
+++ b/sound/soc/samsung/Kconfig
@@ -20,6 +20,9 @@ config SND_S3C2412_SOC_I2S
select SND_S3C_I2SV2_SOC
select S3C2410_DMA
+config SND_S5PC1XX_I2S
+ tristate
+
config SND_SAMSUNG_PCM
tristate
@@ -34,6 +37,12 @@ config SND_SAMSUNG_SPDIF
config SND_SAMSUNG_I2S
tristate
+config S5P_INTERNAL_DMA
+ tristate
+
+config SND_S5P_WM8994_MASTER
+ bool
+
config SND_SOC_SAMSUNG_NEO1973_WM8753
tristate "Audio support for Openmoko Neo1973 Smartphones (GTA01/GTA02)"
depends on SND_SOC_SAMSUNG && (MACH_NEO1973_GTA01 || MACH_NEO1973_GTA02)
@@ -125,6 +134,17 @@ config SND_SOC_SAMSUNG_H1940_UDA1380
help
This driver provides audio support for HP iPAQ h1940 PDA.
+config SND_SOC_SAMSUNG_HERRING_WM8994
+ tristate "SoC I2S Audio support for HERRING - WM8994"
+ depends on SND_SOC_SAMSUNG && (MACH_HERRING)
+ select SND_S5PC1XX_I2S
+ select SND_SOC_WM8994_SAMSUNG
+ select S5P_INTERNAL_DMA
+ select SND_S5P_WM8994_MASTER
+ help
+ Say Y if you want to add support for SoC audio on herring
+ with the WM8994.
+
config SND_SOC_SAMSUNG_RX1950_UDA1380
tristate "Audio support for the HP iPAQ RX1950"
depends on SND_SOC_SAMSUNG && MACH_RX1950
diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile
index 683843a..98a007e 100644
--- a/sound/soc/samsung/Makefile
+++ b/sound/soc/samsung/Makefile
@@ -1,7 +1,8 @@
# S3c24XX Platform Support
-snd-soc-s3c24xx-objs := dma.o
+snd-soc-s3c24xx-objs := dma.o s3c-dma-wrapper.o
snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o
snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o
+snd-soc-s5pc1xx-i2s-objs := s5pc1xx-i2s.o
snd-soc-ac97-objs := ac97.o
snd-soc-s3c-i2s-v2-objs := s3c-i2s-v2.o
snd-soc-samsung-spdif-objs := spdif.o
@@ -13,9 +14,11 @@ obj-$(CONFIG_SND_S3C24XX_I2S) += snd-soc-s3c24xx-i2s.o
obj-$(CONFIG_SND_SAMSUNG_AC97) += snd-soc-ac97.o
obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o
obj-$(CONFIG_SND_S3C_I2SV2_SOC) += snd-soc-s3c-i2s-v2.o
+obj-$(CONFIG_SND_S5PC1XX_I2S) += snd-soc-s5pc1xx-i2s.o
obj-$(CONFIG_SND_SAMSUNG_SPDIF) += snd-soc-samsung-spdif.o
obj-$(CONFIG_SND_SAMSUNG_PCM) += snd-soc-pcm.o
obj-$(CONFIG_SND_SAMSUNG_I2S) += snd-soc-i2s.o
+obj-$(CONFIG_S5P_INTERNAL_DMA) += s3c-idma.o s5p-i2s_sec.o
# S3C24XX Machine Support
snd-soc-jive-wm8750-objs := jive_wm8750.o
@@ -33,6 +36,7 @@ snd-soc-smdk-wm8994-objs := smdk_wm8994.o
snd-soc-smdk-wm9713-objs := smdk_wm9713.o
snd-soc-s3c64xx-smartq-wm8987-objs := smartq_wm8987.o
snd-soc-goni-wm8994-objs := goni_wm8994.o
+snd-soc-herring-wm8994-objs := herring-wm8994.o
snd-soc-smdk-spdif-objs := smdk_spdif.o
snd-soc-smdk-wm8580pcm-objs := smdk_wm8580pcm.o
snd-soc-speyside-objs := speyside.o
@@ -46,6 +50,7 @@ obj-$(CONFIG_SND_SOC_SAMSUNG_SIMTEC) += snd-soc-s3c24xx-simtec.o
obj-$(CONFIG_SND_SOC_SAMSUNG_SIMTEC_HERMES) += snd-soc-s3c24xx-simtec-hermes.o
obj-$(CONFIG_SND_SOC_SAMSUNG_SIMTEC_TLV320AIC23) += snd-soc-s3c24xx-simtec-tlv320aic23.o
obj-$(CONFIG_SND_SOC_SAMSUNG_H1940_UDA1380) += snd-soc-h1940-uda1380.o
+obj-$(CONFIG_SND_SOC_SAMSUNG_HERRING_WM8994) += snd-soc-herring-wm8994.o
obj-$(CONFIG_SND_SOC_SAMSUNG_RX1950_UDA1380) += snd-soc-rx1950-uda1380.o
obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK_WM8580) += snd-soc-smdk-wm8580.o
obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK_WM8994) += snd-soc-smdk-wm8994.o
diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c
index 5cb3b88..fc56ed0 100644
--- a/sound/soc/samsung/dma.c
+++ b/sound/soc/samsung/dma.c
@@ -42,9 +42,9 @@ static const struct snd_pcm_hardware dma_hardware = {
SNDRV_PCM_FMTBIT_S8,
.channels_min = 2,
.channels_max = 2,
- .buffer_bytes_max = 128*1024,
- .period_bytes_min = PAGE_SIZE,
- .period_bytes_max = PAGE_SIZE*2,
+ .buffer_bytes_max = 128 * 1024,
+ .period_bytes_min = 128,
+ .period_bytes_max = 32 * 1024,
.periods_min = 2,
.periods_max = 128,
.fifo_size = 32,
@@ -191,6 +191,11 @@ static int dma_hw_params(struct snd_pcm_substream *substream,
prtd->dma_start = runtime->dma_addr;
prtd->dma_pos = prtd->dma_start;
prtd->dma_end = prtd->dma_start + totbytes;
+
+ pr_debug("DmaAddr=@%x Total=%lubytes PrdSz=%u #Prds=%u dma_area=0x%x\n",
+ prtd->dma_start, totbytes, params_period_bytes(params),
+ params_periods(params), (unsigned int)runtime->dma_area);
+
spin_unlock_irq(&prtd->lock);
return 0;
@@ -408,7 +413,11 @@ static void dma_free_dma_buffers(struct snd_pcm *pcm)
pr_debug("Entered %s\n", __func__);
+#ifdef CONFIG_S5P_INTERNAL_DMA
+ for (stream = 1; stream < 2; stream++) {
+#else
for (stream = 0; stream < 2; stream++) {
+#endif
substream = pcm->streams[stream].substream;
if (!substream)
continue;
@@ -437,13 +446,14 @@ static int dma_new(struct snd_card *card,
if (!card->dev->coherent_dma_mask)
card->dev->coherent_dma_mask = 0xffffffff;
+#ifndef CONFIG_S5P_INTERNAL_DMA
if (dai->driver->playback.channels_min) {
ret = preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_PLAYBACK);
if (ret)
goto out;
}
-
+#endif
if (dai->driver->capture.channels_min) {
ret = preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_CAPTURE);
@@ -454,11 +464,14 @@ out:
return ret;
}
-static struct snd_soc_platform_driver samsung_asoc_platform = {
+struct snd_soc_platform_driver samsung_asoc_platform = {
.ops = &dma_ops,
.pcm_new = dma_new,
.pcm_free = dma_free_dma_buffers,
};
+EXPORT_SYMBOL_GPL(samsung_asoc_platform);
+
+#ifndef CONFIG_S5P_INTERNAL_DMA
static int __devinit samsung_asoc_platform_probe(struct platform_device *pdev)
{
@@ -493,6 +506,8 @@ static void __exit samsung_asoc_exit(void)
}
module_exit(samsung_asoc_exit);
+#endif
+
MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
MODULE_DESCRIPTION("Samsung ASoC DMA Driver");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/samsung/dma.h b/sound/soc/samsung/dma.h
index c506592..2bb0d44 100644
--- a/sound/soc/samsung/dma.h
+++ b/sound/soc/samsung/dma.h
@@ -19,4 +19,6 @@ struct s3c_dma_params {
int dma_size; /* Size of the DMA transfer */
};
+extern struct snd_soc_platform_driver samsung_asoc_platform;
+
#endif
diff --git a/sound/soc/samsung/herring-wm8994.c b/sound/soc/samsung/herring-wm8994.c
new file mode 100644
index 0000000..5f9dfe2
--- /dev/null
+++ b/sound/soc/samsung/herring-wm8994.c
@@ -0,0 +1,358 @@
+/*
+ * crespo_wm8994.c
+ *
+ * Copyright (C) 2010, Samsung Elect. Ltd. -
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <mach/regs-clock.h>
+#include <plat/regs-iis.h>
+#include "../codecs/wm8994.h"
+#include "s3c-dma.h"
+#include "s5pc1xx-i2s.h"
+//#include "s3c-i2s-v2.h"
+
+#include <linux/io.h>
+
+#define I2S_NUM 0
+#define SRC_CLK 66738000
+
+/* #define CONFIG_SND_DEBUG */
+#ifdef CONFIG_SND_DEBUG
+#define debug_msg(x...) printk(x)
+#else
+#define debug_msg(x...)
+#endif
+
+/* BLC(bits-per-channel) --> BFS(bit clock shud be >= FS*(Bit-per-channel)*2)*/
+/* BFS --> RFS(must be a multiple of BFS) */
+/* RFS & SRC_CLK --> Prescalar Value(SRC_CLK / RFS_VAL / fs - 1) */
+int smdkc110_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ int bfs, rfs, ret;
+ u32 ap_codec_clk;
+#ifndef CONFIG_SND_S5P_WM8994_MASTER
+ struct clk *clk_out, *clk_epll;
+ int psr;
+#endif
+ debug_msg("%s\n", __func__);
+
+ /* Choose BFS and RFS values combination that is supported by
+ * both the WM8994 codec as well as the S5P AP
+ *
+ */
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S8:
+ /* Can take any RFS value for AP */
+ bfs = 16;
+ rfs = 256;
+ break;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ /* Can take any RFS value for AP */
+ bfs = 32;
+ rfs = 256;
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ case SNDRV_PCM_FORMAT_S24_LE:
+ bfs = 48;
+ rfs = 512;
+ break;
+ /* Impossible, as the AP doesn't support 64fs or more BFS */
+ case SNDRV_PCM_FORMAT_S32_LE:
+ default:
+ return -EINVAL;
+ }
+
+#ifdef CONFIG_SND_S5P_WM8994_MASTER
+ /* Set the Codec DAI configuration */
+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
+
+ if (ret < 0) {
+ printk(KERN_ERR "smdkc110_wm8994_hw_params :\
+ Codec DAI configuration error!\n");
+ return ret;
+ }
+
+ /* Set the AP DAI configuration */
+ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
+
+ if (ret < 0) {
+ printk(KERN_ERR
+ "smdkc110_wm8994_hw_params :\
+ AP DAI configuration error!\n");
+ return ret;
+ }
+
+ /* Select the AP Sysclk */
+ ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CDCLKSRC_EXT,
+ params_rate(params), SND_SOC_CLOCK_IN);
+
+ if (ret < 0) {
+ printk(KERN_ERR
+ "smdkc110_wm8994_hw_params :\
+ AP sys clock INT setting error!\n");
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CLKSRC_I2SEXT,
+ params_rate(params), SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ printk(KERN_ERR
+ "smdkc110_wm8994_hw_params :\
+ AP sys clock I2SEXT setting error!\n");
+ return ret;
+ }
+
+ switch (params_rate(params)) {
+
+ case 8000:
+ ap_codec_clk = 4096000;
+ break;
+ case 11025:
+ ap_codec_clk = 2822400;
+ break;
+ case 12000:
+ ap_codec_clk = 6144000;
+ break;
+ case 16000:
+ ap_codec_clk = 4096000;
+ break;
+ case 22050:
+ ap_codec_clk = 6144000;
+ break;
+ case 24000:
+ ap_codec_clk = 6144000;
+ break;
+ case 32000:
+ ap_codec_clk = 8192000;
+ break;
+ case 44100:
+ ap_codec_clk = 11289600;
+ break;
+ case 48000:
+ ap_codec_clk = 12288000;
+ break;
+ default:
+ ap_codec_clk = 11289600;
+ break;
+ }
+
+ ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL,
+ ap_codec_clk, 0);
+ if (ret < 0)
+ return ret;
+#else
+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+
+ if (ret < 0)
+ return ret;
+ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+
+ if (ret < 0)
+
+ return ret;
+ ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CLKSRC_CDCLK,
+ params_rate(params), SND_SOC_CLOCK_OUT);
+ if (ret < 0)
+ return ret;
+#ifdef USE_CLKAUDIO
+ ret = snd_soc_dai_set_sysclk(cpu_dai, S3C_CLKSRC_CLKAUDIO,
+ params_rate(params), SND_SOC_CLOCK_OUT);
+
+ if (ret < 0) {
+ printk(KERN_ERR
+ "smdkc110_wm8994_hw_params : \
+ AP sys clock setting error!\n");
+ return ret;
+ }
+#endif
+ clk_out = clk_get(NULL, "clk_out");
+ if (IS_ERR(clk_out)) {
+ printk(KERN_ERR
+ "failed to get CLK_OUT\n");
+ return -EBUSY;
+ }
+
+ clk_epll = clk_get(NULL, "fout_epll");
+ if (IS_ERR(clk_epll)) {
+ printk(KERN_ERR
+ "failed to get fout_epll\n");
+ clk_put(clk_out);
+ return -EBUSY;
+ }
+
+ if (clk_set_parent(clk_out, clk_epll)) {
+ printk(KERN_ERR
+ "failed to set CLK_EPLL as parent of CLK_OUT\n");
+ clk_put(clk_out);
+ clk_put(clk_epll);
+ return -EBUSY;
+ }
+
+
+ switch (params_rate(params)) {
+ case 8000:
+ case 16000:
+ case 32000:
+ case 48000:
+ case 64000:
+ case 96000:
+ clk_set_rate(clk_out, 12288000);
+ ap_codec_clk = SRC_CLK/4;
+ break;
+ case 11025:
+ case 22050:
+ case 44100:
+ case 88200:
+ default:
+ clk_set_rate(clk_out, 11289600);
+ ap_codec_clk = SRC_CLK/6;
+ break;
+ }
+
+ ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_MCLK,
+ ap_codec_clk, 0);
+ if (ret < 0) {
+ printk(KERN_ERR
+ "smdkc110_wm8994_hw_params : \
+ Codec sys clock setting error!\n");
+ return ret;
+ }
+
+ /* Calculate Prescalare/PLL values for supported Rates */
+ psr = SRC_CLK / rfs / params_rate(params);
+ ret = SRC_CLK / rfs - psr * params_rate(params);
+ /* round off */
+ if (ret >= params_rate(params)/2)
+ psr += 1;
+
+ psr -= 1;
+ printk(KERN_INFO
+ "SRC_CLK=%d PSR=%d RFS=%d BFS=%d\n", SRC_CLK, psr, rfs, bfs);
+
+ /* Set the AP Prescalar/Pll */
+ ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C_I2SV2_DIV_PRESCALER, psr);
+
+ if (ret < 0) {
+ printk(KERN_ERR
+ "smdkc110_wm8994_hw_params :\
+ AP prescalar setting error!\n");
+ return ret;
+ }
+
+ /* Set the AP RFS */
+ ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C_I2SV2_DIV_RCLK, rfs);
+ if (ret < 0) {
+ printk(KERN_ERR
+ "smdkc110_wm8994_hw_params : AP RFS setting error!\n");
+ return ret;
+ }
+
+ /* Set the AP BFS */
+ ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C_I2SV2_DIV_BCLK, bfs);
+
+ if (ret < 0) {
+ printk(KERN_ERR
+ "smdkc110_wm8994_hw_params : AP BCLK setting error!\n");
+ return ret;
+ }
+
+ clk_put(clk_epll);
+ clk_put(clk_out);
+#endif
+ return 0;
+
+}
+
+/* machine stream operations */
+static struct snd_soc_ops smdkc110_ops = {
+ .hw_params = smdkc110_hw_params,
+};
+
+/* digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link smdkc1xx_dai = {
+ .name = "herring",
+ .stream_name = "WM8994 HiFi Playback",
+ .cpu_dai_name = "samsung-i2s.0",
+ .codec_dai_name = "WM8994 PAIFRX",
+ .platform_name = "samsung-audio",
+ .codec_name = "wm8994-samsung-codec.4-001a",
+ .ops = &smdkc110_ops,
+};
+
+static struct snd_soc_card smdkc100 = {
+ .name = "smdkc110",
+ .dai_link = &smdkc1xx_dai,
+ .num_links = 1,
+};
+
+#if 0
+static struct wm8994_setup_data smdkc110_wm8994_setup = {
+ /*
+ The I2C address of the WM89940 is 0x34. To the I2C driver
+ the address is a 7-bit number hence the right shift .
+ */
+ .i2c_address = 0x34,
+ .i2c_bus = 4,
+};
+
+/* audio subsystem */
+static struct snd_soc_device smdkc1xx_snd_devdata = {
+ .card = &smdkc100,
+ .codec_dev = &soc_codec_dev_wm8994,
+ .codec_data = &smdkc110_wm8994_setup,
+};
+#endif
+
+static struct platform_device *smdkc1xx_snd_device;
+static int __init smdkc110_audio_init(void)
+{
+ int ret;
+
+ debug_msg("%s\n", __func__);
+
+ smdkc1xx_snd_device = platform_device_alloc("soc-audio", 0);
+ if (!smdkc1xx_snd_device)
+ return -ENOMEM;
+
+ platform_set_drvdata(smdkc1xx_snd_device, &smdkc100);
+ ret = platform_device_add(smdkc1xx_snd_device);
+
+ if (ret)
+ platform_device_put(smdkc1xx_snd_device);
+
+ return ret;
+}
+
+static void __exit smdkc110_audio_exit(void)
+{
+ debug_msg("%s\n", __func__);
+
+ platform_device_unregister(smdkc1xx_snd_device);
+}
+
+module_init(smdkc110_audio_init);
+module_exit(smdkc110_audio_exit);
+
+/* Module information */
+MODULE_DESCRIPTION("ALSA SoC SMDKC110 WM8994");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index 992a732..a779185 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -14,6 +14,7 @@
#include <linux/slab.h>
#include <linux/clk.h>
#include <linux/io.h>
+#include <linux/regulator/consumer.h>
#include <sound/soc.h>
#include <sound/pcm_params.h>
@@ -146,6 +147,8 @@ struct i2s_dai {
unsigned rfs, bfs;
/* I2S Controller's core clock */
struct clk *clk;
+ /* I2S Controller's power domain */
+ struct regulator *regulator;
/* Clock for generating I2S signals */
struct clk *op_clk;
/* Array of clock names for op_clk */
@@ -572,9 +575,13 @@ static int i2s_set_fmt(struct snd_soc_dai *dai,
unsigned int fmt)
{
struct i2s_dai *i2s = to_info(dai);
- u32 mod = readl(i2s->addr + I2SMOD);
+ u32 mod;
u32 tmp = 0;
+ dev_info(&i2s->pdev->dev, "base %p\n", i2s->addr);
+
+ mod = readl(i2s->addr + I2SMOD);
+
/* Format is priority */
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_RIGHT_J:
@@ -951,6 +958,9 @@ static int i2s_resume(struct snd_soc_dai *dai)
static int samsung_i2s_dai_probe(struct snd_soc_dai *dai)
{
+ struct clk *fout_epll, *mout_epll;
+ struct clk *mout_audss = NULL;
+ struct clk *sclk_audio, *iis_clk, *iis_busclk, *iis_ipclk; /* these belong shomewhere else */
struct i2s_dai *i2s = to_info(dai);
struct i2s_dai *other = i2s->pri_dai ? : i2s->sec_dai;
@@ -971,6 +981,59 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai)
}
clk_enable(i2s->clk);
+ /* Get i2s power domain regulator */
+ i2s->regulator = regulator_get(&i2s->pdev->dev, "pd");
+ if (IS_ERR(i2s->regulator)) {
+ dev_err(&i2s->pdev->dev, "%s: failed to get resource %s\n",
+ __func__, "i2s");
+ return PTR_ERR(i2s->regulator);
+ }
+
+ /* Enable Power domain */
+ regulator_enable(i2s->regulator);
+
+ fout_epll = clk_get(&i2s->pdev->dev, "fout_epll");
+ if (IS_ERR(fout_epll))
+ dev_err(&i2s->pdev->dev, "failed to get fout_epll\n");
+
+ mout_epll = clk_get(&i2s->pdev->dev, "mout_epll");
+ if (IS_ERR(mout_epll))
+ dev_err(&i2s->pdev->dev, "failed to get mout_epll\n");
+ clk_set_parent(mout_epll, fout_epll);
+
+ sclk_audio = clk_get(&i2s->pdev->dev, "sclk_audio");
+ if (IS_ERR(sclk_audio))
+ dev_err(&i2s->pdev->dev, "failed to get sclk_audio\n");
+ clk_set_parent(sclk_audio, mout_epll);
+
+ /* Need not to enable in general */
+ clk_enable(sclk_audio);
+
+ /* When I2S V5.1 used, initialize audio subsystem clock */
+ /* CLKMUX_ASS */
+ if (&i2s->pdev->id == 0) {
+ mout_audss = clk_get(NULL, "mout_audss");
+ if (IS_ERR(mout_audss))
+ dev_err(&i2s->pdev->dev, "failed to get mout_audss\n");
+ clk_set_parent(mout_audss, fout_epll);
+ /*MUX-I2SA*/
+ iis_clk = clk_get(&i2s->pdev->dev, "audio-bus");
+ if (IS_ERR(iis_clk))
+ dev_err(&i2s->pdev->dev, "failed to get audio-bus\n");
+ clk_set_parent(iis_clk, mout_audss);
+ /*getting AUDIO BUS CLK*/
+ iis_busclk = clk_get(NULL, "dout_audio_bus_clk_i2s");
+ if (IS_ERR(iis_busclk))
+ printk(KERN_ERR "failed to get audss_hclk\n");
+ iis_ipclk = clk_get(&i2s->pdev->dev, "i2s_v50");
+ if (IS_ERR(iis_ipclk))
+ dev_err(&i2s->pdev->dev, "failed to get i2s_v50_clock\n");
+ clk_enable(iis_ipclk);
+ clk_enable(iis_clk);
+ clk_enable(iis_busclk);
+ }
+
+
if (other) {
other->addr = i2s->addr;
other->clk = i2s->clk;
diff --git a/sound/soc/samsung/s3c-dma-wrapper.c b/sound/soc/samsung/s3c-dma-wrapper.c
new file mode 100644
index 0000000..2f87b68
--- /dev/null
+++ b/sound/soc/samsung/s3c-dma-wrapper.c
@@ -0,0 +1,267 @@
+/*
+ * s3c-dma-wrapper.c -- S3C DMA Platform Wrapper Driver
+ *
+ * Copyright (c) 2010 Samsung Electronics Co. Ltd
+ * Jaswinder Singh <jassi.brar@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 <sound/soc.h>
+#include "dma.h"
+#include "s3c-idma.h"
+
+static int s3c_wrpdma_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_platform_driver *platform;
+
+#ifdef CONFIG_S5P_INTERNAL_DMA
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ platform = &idma_soc_platform;
+ else
+#endif
+ platform = &samsung_asoc_platform;
+
+ if (platform->ops->hw_params)
+ return platform->ops->hw_params(substream, params);
+ else
+ return 0;
+}
+
+static int s3c_wrpdma_hw_free(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_platform_driver *platform;
+
+#ifdef CONFIG_S5P_INTERNAL_DMA
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ platform = &idma_soc_platform;
+ else
+#endif
+ platform = &samsung_asoc_platform;
+
+ if (platform->ops->hw_free)
+ return platform->ops->hw_free(substream);
+ else
+ return 0;
+}
+
+static int s3c_wrpdma_prepare(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_platform_driver *platform;
+
+#ifdef CONFIG_S5P_INTERNAL_DMA
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ platform = &idma_soc_platform;
+ else
+#endif
+ platform = &samsung_asoc_platform;
+
+ if (platform->ops->prepare)
+ return platform->ops->prepare(substream);
+ else
+ return 0;
+}
+
+static int s3c_wrpdma_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ struct snd_soc_platform_driver *platform;
+
+#ifdef CONFIG_S5P_INTERNAL_DMA
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ platform = &idma_soc_platform;
+ else
+#endif
+ platform = &samsung_asoc_platform;
+
+ if (platform->ops->trigger)
+ return platform->ops->trigger(substream, cmd);
+ else
+ return 0;
+}
+
+static snd_pcm_uframes_t s3c_wrpdma_pointer(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_platform_driver *platform;
+
+#ifdef CONFIG_S5P_INTERNAL_DMA
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ platform = &idma_soc_platform;
+ else
+#endif
+ platform = &samsung_asoc_platform;
+
+ if (platform->ops->pointer)
+ return platform->ops->pointer(substream);
+ else
+ return 0;
+}
+
+static int s3c_wrpdma_open(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_platform_driver *platform;
+
+#ifdef CONFIG_S5P_INTERNAL_DMA
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ platform = &idma_soc_platform;
+ else
+#endif
+ platform = &samsung_asoc_platform;
+
+ if (platform->ops->open)
+ return platform->ops->open(substream);
+ else
+ return 0;
+}
+
+static int s3c_wrpdma_close(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_platform_driver *platform;
+
+#ifdef CONFIG_S5P_INTERNAL_DMA
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ platform = &idma_soc_platform;
+ else
+#endif
+ platform = &samsung_asoc_platform;
+
+ if (platform->ops->close)
+ return platform->ops->close(substream);
+ else
+ return 0;
+}
+
+static int s3c_wrpdma_ioctl(struct snd_pcm_substream *substream,
+ unsigned int cmd, void *arg)
+{
+ struct snd_soc_platform_driver *platform;
+
+#ifdef CONFIG_S5P_INTERNAL_DMA
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ platform = &idma_soc_platform;
+ else
+#endif
+ platform = &samsung_asoc_platform;
+
+ if (platform->ops->ioctl)
+ return platform->ops->ioctl(substream, cmd, arg);
+ else
+ return 0;
+}
+
+static int s3c_wrpdma_mmap(struct snd_pcm_substream *substream,
+ struct vm_area_struct *vma)
+{
+ struct snd_soc_platform_driver *platform;
+
+#ifdef CONFIG_S5P_INTERNAL_DMA
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ platform = &idma_soc_platform;
+ else
+#endif
+ platform = &samsung_asoc_platform;
+
+ if (platform->ops->mmap)
+ return platform->ops->mmap(substream, vma);
+ else
+ return 0;
+}
+
+static struct snd_pcm_ops s3c_wrpdma_ops = {
+ .open = s3c_wrpdma_open,
+ .close = s3c_wrpdma_close,
+ .ioctl = s3c_wrpdma_ioctl,
+ .hw_params = s3c_wrpdma_hw_params,
+ .hw_free = s3c_wrpdma_hw_free,
+ .prepare = s3c_wrpdma_prepare,
+ .trigger = s3c_wrpdma_trigger,
+ .pointer = s3c_wrpdma_pointer,
+ .mmap = s3c_wrpdma_mmap,
+};
+
+static void s3c_wrpdma_pcm_free(struct snd_pcm *pcm)
+{
+ struct snd_soc_platform_driver *gdma_platform;
+#ifdef CONFIG_S5P_INTERNAL_DMA
+ struct snd_soc_platform_driver *idma_platform;
+#endif
+
+#ifdef CONFIG_S5P_INTERNAL_DMA
+ idma_platform = &idma_soc_platform;
+ if (idma_platform->pcm_free)
+ idma_platform->pcm_free(pcm);
+#endif
+ gdma_platform = &samsung_asoc_platform;
+ if (gdma_platform->pcm_free)
+ gdma_platform->pcm_free(pcm);
+}
+
+static int s3c_wrpdma_pcm_new(struct snd_card *card,
+ struct snd_soc_dai *dai, struct snd_pcm *pcm)
+{
+ struct snd_soc_platform_driver *gdma_platform;
+#ifdef CONFIG_S5P_INTERNAL_DMA
+ struct snd_soc_platform_driver *idma_platform;
+#endif
+
+ /* sec_fifo i/f always use internal h/w buffers
+ * irrespective of the xfer method (iDMA or SysDMA) */
+
+#ifdef CONFIG_S5P_INTERNAL_DMA
+ idma_platform = &idma_soc_platform;
+ if (idma_platform->pcm_new)
+ idma_platform->pcm_new(card, dai, pcm);
+#endif
+ gdma_platform = &samsung_asoc_platform;
+ if (gdma_platform->pcm_new)
+ gdma_platform->pcm_new(card, dai, pcm);
+
+ return 0;
+}
+
+static struct snd_soc_platform_driver s3c_dma_wrapper = {
+ .ops = &s3c_wrpdma_ops,
+ .pcm_new = s3c_wrpdma_pcm_new,
+ .pcm_free = s3c_wrpdma_pcm_free,
+};
+//EXPORT_SYMBOL_GPL(s3c_dma_wrapper);
+
+static int __devinit s3c_dma_wrapper_platform_probe(struct platform_device *pdev)
+{
+ return snd_soc_register_platform(&pdev->dev, &s3c_dma_wrapper);
+}
+
+static int __devexit s3c_dma_wrapper_platform_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_platform(&pdev->dev);
+ return 0;
+}
+
+static struct platform_driver s3c_dma_wrapper_driver = {
+ .driver = {
+ .name = "samsung-audio",
+ .owner = THIS_MODULE,
+ },
+
+ .probe = s3c_dma_wrapper_platform_probe,
+ .remove = __devexit_p(s3c_dma_wrapper_platform_remove),
+};
+
+static int __init s3c_dma_wrapper_init(void)
+{
+ return platform_driver_register(&s3c_dma_wrapper_driver);
+}
+module_init(s3c_dma_wrapper_init);
+
+static void __exit s3c_dma_wrapper_exit(void)
+{
+ platform_driver_unregister(&s3c_dma_wrapper_driver);
+}
+module_exit(s3c_dma_wrapper_exit);
+
+MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>");
+MODULE_DESCRIPTION("Audio DMA wrapper module");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/samsung/s3c-dma.c b/sound/soc/samsung/s3c-dma.c
new file mode 100644
index 0000000..8985964
--- /dev/null
+++ b/sound/soc/samsung/s3c-dma.c
@@ -0,0 +1,478 @@
+/*
+ * s3c-dma.c -- ALSA Soc Audio Layer
+ *
+ * (c) 2006 Wolfson Microelectronics PLC.
+ * Graeme Gregory graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
+ *
+ * Copyright 2004-2005 Simtec Electronics
+ * http://armlinux.simtec.co.uk/
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * 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/init.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include <asm/dma.h>
+#include <mach/hardware.h>
+#include <mach/dma.h>
+
+#include "s3c-dma.h"
+
+static const struct snd_pcm_hardware s3c_dma_hardware = {
+ .info = SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_PAUSE |
+ SNDRV_PCM_INFO_RESUME,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_U16_LE |
+ SNDRV_PCM_FMTBIT_U8 |
+ SNDRV_PCM_FMTBIT_S8,
+ .channels_min = 2,
+ .channels_max = 2,
+ .buffer_bytes_max = 128 * 1024,
+ .period_bytes_min = 128,
+ .period_bytes_max = 32 * 1024,
+ .periods_min = 2,
+ .periods_max = 128,
+ .fifo_size = 32,
+};
+
+struct s3c24xx_runtime_data {
+ spinlock_t lock;
+ int state;
+ unsigned int dma_loaded;
+ unsigned int dma_limit;
+ unsigned int dma_period;
+ dma_addr_t dma_start;
+ dma_addr_t dma_pos;
+ dma_addr_t dma_end;
+ struct s3c_dma_params *params;
+};
+
+/* s3c_dma_enqueue
+ *
+ * place a dma buffer onto the queue for the dma system
+ * to handle.
+*/
+static void s3c_dma_enqueue(struct snd_pcm_substream *substream)
+{
+ struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
+ dma_addr_t pos = prtd->dma_pos;
+ unsigned int limit;
+ int ret;
+
+ pr_debug("Entered %s\n", __func__);
+
+ if (s3c_dma_has_circular())
+ limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period;
+ else
+ limit = prtd->dma_limit;
+
+ pr_debug("%s: loaded %d, limit %d\n",
+ __func__, prtd->dma_loaded, limit);
+
+ while (prtd->dma_loaded < limit) {
+ unsigned long len = prtd->dma_period;
+
+ pr_debug("dma_loaded: %d\n", prtd->dma_loaded);
+
+ if ((pos + len) > prtd->dma_end) {
+ len = prtd->dma_end - pos;
+ pr_debug(KERN_DEBUG "%s: corrected dma len %ld\n",
+ __func__, len);
+ }
+
+ ret = s3c2410_dma_enqueue(prtd->params->channel,
+ substream, pos, len);
+
+ if (ret == 0) {
+ prtd->dma_loaded++;
+ pos += prtd->dma_period;
+ if (pos >= prtd->dma_end)
+ pos = prtd->dma_start;
+ } else
+ break;
+ }
+
+ prtd->dma_pos = pos;
+}
+
+static void s3c24xx_audio_buffdone(struct s3c2410_dma_chan *channel,
+ void *dev_id, int size,
+ enum s3c2410_dma_buffresult result)
+{
+ struct snd_pcm_substream *substream = dev_id;
+ struct s3c24xx_runtime_data *prtd;
+
+ pr_debug("Entered %s\n", __func__);
+
+ if (result == S3C2410_RES_ABORT || result == S3C2410_RES_ERR)
+ return;
+
+ prtd = substream->runtime->private_data;
+
+ if (substream)
+ snd_pcm_period_elapsed(substream);
+
+ spin_lock(&prtd->lock);
+ if (prtd->state & ST_RUNNING && !s3c_dma_has_circular()) {
+ prtd->dma_loaded--;
+ s3c_dma_enqueue(substream);
+ }
+
+ spin_unlock(&prtd->lock);
+}
+
+static int s3c_dma_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct s3c24xx_runtime_data *prtd = runtime->private_data;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ unsigned long totbytes = params_buffer_bytes(params);
+ struct s3c_dma_params *dma =
+ snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+ int ret = 0;
+
+
+ pr_debug("Entered %s\n", __func__);
+
+ /* return if this is a bufferless transfer e.g.
+ * codec <--> BT codec or GSM modem -- lg FIXME */
+ if (!dma)
+ return 0;
+
+ /* this may get called several times by oss emulation
+ * with different params -HW */
+ if (prtd->params == NULL) {
+ /* prepare DMA */
+ prtd->params = dma;
+
+ pr_debug("params %p, client %p, channel %d\n", prtd->params,
+ prtd->params->client, prtd->params->channel);
+
+ ret = s3c2410_dma_request(prtd->params->channel,
+ prtd->params->client, NULL);
+
+ if (ret < 0) {
+ printk(KERN_ERR "failed to get dma channel\n");
+ return ret;
+ }
+
+ /* use the circular buffering if we have it available. */
+ if (s3c_dma_has_circular())
+ s3c2410_dma_setflags(prtd->params->channel,
+ S3C2410_DMAF_CIRCULAR);
+ }
+
+ s3c2410_dma_set_buffdone_fn(prtd->params->channel,
+ s3c24xx_audio_buffdone);
+
+ snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+
+ runtime->dma_bytes = totbytes;
+
+ spin_lock_irq(&prtd->lock);
+ prtd->dma_loaded = 0;
+ prtd->dma_limit = runtime->hw.periods_min;
+ prtd->dma_period = params_period_bytes(params);
+ prtd->dma_start = runtime->dma_addr;
+ prtd->dma_pos = prtd->dma_start;
+ prtd->dma_end = prtd->dma_start + totbytes;
+
+ pr_debug("DmaAddr=@%x Total=%lubytes PrdSz=%u #Prds=%u dma_area=0x%x\n",
+ prtd->dma_start, totbytes, params_period_bytes(params),
+ params_periods(params), (unsigned int)runtime->dma_area);
+
+ spin_unlock_irq(&prtd->lock);
+
+ return 0;
+}
+
+static int s3c_dma_hw_free(struct snd_pcm_substream *substream)
+{
+ struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
+
+ pr_debug("Entered %s\n", __func__);
+
+ /* TODO - do we need to ensure DMA flushed */
+ snd_pcm_set_runtime_buffer(substream, NULL);
+
+ if (prtd->params) {
+ s3c2410_dma_free(prtd->params->channel, prtd->params->client);
+ prtd->params = NULL;
+ }
+
+ return 0;
+}
+
+static int s3c_dma_prepare(struct snd_pcm_substream *substream)
+{
+ struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
+ int ret = 0;
+
+ pr_debug("Entered %s\n", __func__);
+
+ /* return if this is a bufferless transfer e.g.
+ * codec <--> BT codec or GSM modem -- lg FIXME */
+ if (!prtd->params)
+ return 0;
+
+ /* channel needs configuring for mem=>device, increment memory addr,
+ * sync to pclk, half-word transfers to the IIS-FIFO. */
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ s3c2410_dma_devconfig(prtd->params->channel,
+ S3C2410_DMASRC_MEM,
+ prtd->params->dma_addr);
+ } else {
+ s3c2410_dma_devconfig(prtd->params->channel,
+ S3C2410_DMASRC_HW,
+ prtd->params->dma_addr);
+ }
+
+ s3c2410_dma_config(prtd->params->channel,
+ prtd->params->dma_size);
+
+ /* flush the DMA channel */
+ s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_FLUSH);
+ prtd->dma_loaded = 0;
+ prtd->dma_pos = prtd->dma_start;
+
+ /* enqueue dma buffers */
+ s3c_dma_enqueue(substream);
+
+ return ret;
+}
+
+static int s3c_dma_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
+ int ret = 0;
+
+ pr_debug("Entered %s\n", __func__);
+
+ spin_lock(&prtd->lock);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ prtd->state |= ST_RUNNING;
+ s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_START);
+ break;
+
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ prtd->state &= ~ST_RUNNING;
+ s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_STOP);
+ break;
+
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ spin_unlock(&prtd->lock);
+
+ return ret;
+}
+
+static snd_pcm_uframes_t
+s3c_dma_pointer(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct s3c24xx_runtime_data *prtd = runtime->private_data;
+ unsigned long res;
+ dma_addr_t src, dst;
+
+ pr_debug("Entered %s\n", __func__);
+
+ spin_lock(&prtd->lock);
+ s3c2410_dma_getposition(prtd->params->channel, &src, &dst);
+
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+ res = dst - prtd->dma_start;
+ else
+ res = src - prtd->dma_start;
+
+ spin_unlock(&prtd->lock);
+
+ pr_debug("Pointer %x %x\n", src, dst);
+
+ /* we seem to be getting the odd error from the pcm library due
+ * to out-of-bounds pointers. this is maybe due to the dma engine
+ * not having loaded the new values for the channel before being
+ * callled... (todo - fix )
+ */
+
+ if (res >= snd_pcm_lib_buffer_bytes(substream)) {
+ if (res == snd_pcm_lib_buffer_bytes(substream))
+ res = 0;
+ }
+
+ return bytes_to_frames(substream->runtime, res);
+}
+
+static int s3c_dma_open(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct s3c24xx_runtime_data *prtd;
+
+ pr_debug("Entered %s\n", __func__);
+
+ snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+ snd_soc_set_runtime_hwparams(substream, &s3c_dma_hardware);
+
+ prtd = kzalloc(sizeof(struct s3c24xx_runtime_data), GFP_KERNEL);
+ if (prtd == NULL)
+ return -ENOMEM;
+
+ spin_lock_init(&prtd->lock);
+
+ runtime->private_data = prtd;
+ return 0;
+}
+
+static int s3c_dma_close(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct s3c24xx_runtime_data *prtd = runtime->private_data;
+
+ pr_debug("Entered %s\n", __func__);
+
+ if (!prtd)
+ pr_debug("s3c_dma_close called with prtd == NULL\n");
+
+ kfree(prtd);
+
+ return 0;
+}
+
+static int s3c_dma_mmap(struct snd_pcm_substream *substream,
+ struct vm_area_struct *vma)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ pr_debug("Entered %s\n", __func__);
+
+ return dma_mmap_writecombine(substream->pcm->card->dev, vma,
+ runtime->dma_area,
+ runtime->dma_addr,
+ runtime->dma_bytes);
+}
+
+static struct snd_pcm_ops s3c_dma_ops = {
+ .open = s3c_dma_open,
+ .close = s3c_dma_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = s3c_dma_hw_params,
+ .hw_free = s3c_dma_hw_free,
+ .prepare = s3c_dma_prepare,
+ .trigger = s3c_dma_trigger,
+ .pointer = s3c_dma_pointer,
+ .mmap = s3c_dma_mmap,
+};
+
+static int s3c_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
+{
+ struct snd_pcm_substream *substream = pcm->streams[stream].substream;
+ struct snd_dma_buffer *buf = &substream->dma_buffer;
+ size_t size = s3c_dma_hardware.buffer_bytes_max;
+
+ pr_debug("Entered %s\n", __func__);
+ buf->dev.type = SNDRV_DMA_TYPE_DEV;
+ buf->dev.dev = pcm->card->dev;
+ buf->private_data = NULL;
+ buf->area = dma_alloc_writecombine(pcm->card->dev, size,
+ &buf->addr, GFP_KERNEL);
+ if (!buf->area)
+ return -ENOMEM;
+ buf->bytes = size;
+ return 0;
+}
+
+static void s3c_dma_free_dma_buffers(struct snd_pcm *pcm)
+{
+ struct snd_pcm_substream *substream;
+ struct snd_dma_buffer *buf;
+ int stream;
+
+ pr_debug("Entered %s\n", __func__);
+
+#ifdef CONFIG_S5P_INTERNAL_DMA
+ for (stream = 1; stream < 2; stream++) {
+#else
+ for (stream = 0; stream < 2; stream++) {
+#endif
+ substream = pcm->streams[stream].substream;
+ if (!substream)
+ continue;
+
+ buf = &substream->dma_buffer;
+ if (!buf->area)
+ continue;
+
+ dma_free_writecombine(pcm->card->dev, buf->bytes,
+ buf->area, buf->addr);
+ buf->area = NULL;
+ }
+}
+
+static u64 s3c_dma_mask = DMA_BIT_MASK(32);
+
+static int s3c_dma_new(struct snd_card *card,
+ struct snd_soc_dai *dai, struct snd_pcm *pcm)
+{
+ int ret = 0;
+
+ pr_debug("Entered %s\n", __func__);
+
+ if (!card->dev->dma_mask)
+ card->dev->dma_mask = &s3c_dma_mask;
+ if (!card->dev->coherent_dma_mask)
+ card->dev->coherent_dma_mask = 0xffffffff;
+#ifndef CONFIG_S5P_INTERNAL_DMA
+ if (dai->driver->playback.channels_min) {
+ ret = s3c_preallocate_dma_buffer(pcm,
+ SNDRV_PCM_STREAM_PLAYBACK);
+ if (ret)
+ goto out;
+ }
+#endif
+ if (dai->driver->capture.channels_min) {
+ ret = s3c_preallocate_dma_buffer(pcm,
+ SNDRV_PCM_STREAM_CAPTURE);
+ if (ret)
+ goto out;
+ }
+ out:
+ return ret;
+}
+
+struct snd_soc_platform_driver s3c24xx_soc_platform = {
+ .ops = &s3c_dma_ops,
+ .pcm_new = s3c_dma_new,
+ .pcm_free = s3c_dma_free_dma_buffers,
+};
+EXPORT_SYMBOL_GPL(s3c24xx_soc_platform);
+
+MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
+MODULE_DESCRIPTION("Samsung S3C Audio DMA module");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/samsung/s3c-dma.h b/sound/soc/samsung/s3c-dma.h
new file mode 100644
index 0000000..cb869db
--- /dev/null
+++ b/sound/soc/samsung/s3c-dma.h
@@ -0,0 +1,33 @@
+/*
+ * s3c-dma.h --
+ *
+ * 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.
+ *
+ * ALSA PCM interface for the Samsung S3C24xx CPU
+ */
+
+#ifndef _S3C_AUDIO_H
+#define _S3C_AUDIO_H
+
+#define ST_RUNNING (1<<0)
+#define ST_OPENED (1<<1)
+
+struct s3c_dma_params {
+ struct s3c2410_dma_client *client; /* stream identifier */
+ int channel; /* Channel ID */
+ dma_addr_t dma_addr;
+ int dma_size; /* Size of the DMA transfer */
+};
+
+#define S3C24XX_DAI_I2S 0
+
+//#define pr_debug(fmt...) printk(fmt)
+/* platform data */
+extern struct snd_soc_platform_driver s3c24xx_soc_platform;
+extern struct snd_soc_platform s3c24xx_pcm_soc_platform;
+extern struct snd_ac97_bus_ops s3c24xx_ac97_ops;
+
+#endif
diff --git a/sound/soc/samsung/s3c-idma.c b/sound/soc/samsung/s3c-idma.c
new file mode 100644
index 0000000..c3b8c74
--- /dev/null
+++ b/sound/soc/samsung/s3c-idma.c
@@ -0,0 +1,533 @@
+/*
+ * s3c-idma.c -- I2S0's Internal Dma driver
+ *
+ * Copyright (c) 2010 Samsung Electronics Co. Ltd
+ * Jaswinder Singh <jassi.brar@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/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include <plat/regs-iis.h>
+
+#include "s3c-dma.h"
+#include "s3c-idma.h"
+
+/** Debug **/
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#define dump_i2s() do { \
+ printk(KERN_INFO \
+ "%s:%s:%d\n", \
+ __FILE__, __func__, __LINE__); \
+ printk(KERN_INFO \
+ "\tS3C_IISCON : %x", \
+ readl(s3c_idma.regs + S3C2412_IISCON));\
+ printk(KERN_INFO \
+ "\tS3C_IISMOD : %x\n", \
+ readl(s3c_idma.regs + S3C2412_IISMOD));\
+ printk(KERN_INFO \
+ "\tS3C_IISFIC : %x", \
+ readl(s3c_idma.regs + S3C2412_IISFIC));\
+ printk(KERN_INFO \
+ "\tS3C_IISFICS : %x", \
+ readl(s3c_idma.regs + S5P_IISFICS));\
+ printk(KERN_INFO \
+ "\tS3C_IISPSR : %x\n", \
+ readl(s3c_idma.regs + S3C2412_IISPSR));\
+ printk(KERN_INFO \
+ "\tS3C_IISAHB : %x\n", \
+ readl(s3c_idma.regs + S5P_IISAHB));\
+ printk(KERN_INFO \
+ "\tS3C_IISSTR : %x\n", \
+ readl(s3c_idma.regs + S5P_IISSTR));\
+ printk(KERN_INFO \
+ "\tS3C_IISSIZE : %x\n", \
+ readl(s3c_idma.regs + S5P_IISSIZE));\
+ printk(KERN_INFO \
+ "\tS3C_IISADDR0 : %x\n", \
+ readl(s3c_idma.regs + S5P_IISADDR0));\
+ printk(KERN_INFO \
+ "\tS5P_CLKGATE_D20 : %x\n", \
+ readl(S5P_CLKGATE_D20));\
+ printk(KERN_INFO \
+ "\tS5P_LPMP_MODE_SEL : %x\n",\
+ readl(S5P_LPMP_MODE_SEL));\
+ } while (0)
+
+static const struct snd_pcm_hardware s3c_idma_hardware = {
+ .info = SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_PAUSE |
+ SNDRV_PCM_INFO_RESUME,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_U16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_U24_LE |
+ SNDRV_PCM_FMTBIT_U8 |
+ SNDRV_PCM_FMTBIT_S8,
+ .channels_min = 2,
+ .channels_max = 2,
+ .buffer_bytes_max = MAX_LP_BUFF,
+ .period_bytes_min = 128,
+ .period_bytes_max = 16 * 1024,
+ .periods_min = 2,
+ .periods_max = 128,
+ .fifo_size = 64,
+};
+
+struct lpam_i2s_pdata {
+ spinlock_t lock;
+ int state;
+ dma_addr_t start;
+ dma_addr_t pos;
+ dma_addr_t end;
+ dma_addr_t period;
+
+};
+
+ /********************
+ * Internal DMA i/f *
+ ********************/
+static struct s3c_idma_info {
+ void __iomem *regs;
+ unsigned int dma_prd;
+ unsigned int dma_end;
+ spinlock_t lock;
+ void *token;
+ void (*cb)(void *dt, int bytes_xfer);
+} s3c_idma;
+
+
+static void s3c_idma_getpos(dma_addr_t *src)
+{
+ *src = LP_TXBUFF_ADDR +
+ (readl(s3c_idma.regs + S5P_IISTRNCNT) & 0xffffff) * 4;
+}
+
+void i2sdma_getpos(dma_addr_t *src)
+{
+ if (audio_clk_gated == 0 && i2s_trigger_stop == 0)
+ *src = LP_TXBUFF_ADDR +
+ (readl(s3c_idma.regs + S5P_IISTRNCNT) & 0xffffff) * 4;
+ else
+ *src = LP_TXBUFF_ADDR;
+
+}
+
+static int s3c_idma_enqueue(void *token)
+{
+ u32 val;
+
+ spin_lock(&s3c_idma.lock);
+ s3c_idma.token = token;
+ spin_unlock(&s3c_idma.lock);
+
+ pr_debug("%s: %x@%x\n", __func__, MAX_LP_BUFF, LP_TXBUFF_ADDR);
+
+ /* Internal DMA Level0 Interrupt Address */
+ val = LP_TXBUFF_ADDR + s3c_idma.dma_prd;
+ writel(val, s3c_idma.regs + S5P_IISADDR0);
+
+ /* Start address0 of I2S internal DMA operation. */
+ val = readl(s3c_idma.regs + S5P_IISSTR);
+ val = LP_TXBUFF_ADDR;
+ writel(val, s3c_idma.regs + S5P_IISSTR);
+
+ /*
+ * Transfer block size for I2S internal DMA.
+ * Should decide transfer size before start dma operation
+ */
+ val = readl(s3c_idma.regs + S5P_IISSIZE);
+ val &= ~(S5P_IISSIZE_TRNMSK << S5P_IISSIZE_SHIFT);
+
+ val |= ((((s3c_idma.dma_end & 0x1ffff) >> 2) &
+ S5P_IISSIZE_TRNMSK) << S5P_IISSIZE_SHIFT);
+ writel(val, s3c_idma.regs + S5P_IISSIZE);
+
+ return 0;
+}
+
+static void s3c_idma_setcallbk(void (*cb)(void *, int), unsigned prd)
+{
+ spin_lock(&s3c_idma.lock);
+ s3c_idma.cb = cb;
+ s3c_idma.dma_prd = prd;
+ spin_unlock(&s3c_idma.lock);
+
+ pr_debug("%s:%d dma_period=%x\n", __func__, __LINE__, s3c_idma.dma_prd);
+}
+
+static void s3c_idma_ctrl(int op)
+{
+ u32 val;
+
+ spin_lock(&s3c_idma.lock);
+
+ val = readl(s3c_idma.regs + S5P_IISAHB);
+
+ switch (op) {
+ case LPAM_DMA_START:
+ val |= (S5P_IISAHB_INTENLVL0 | S5P_IISAHB_DMAEN);
+ break;
+ case LPAM_DMA_STOP:
+ /* Disable LVL Interrupt and DMA Operation */
+ val &= ~(S5P_IISAHB_INTENLVL0 | S5P_IISAHB_DMAEN);
+ break;
+ default:
+ spin_unlock(&s3c_idma.lock);
+ return;
+ }
+
+ writel(val, s3c_idma.regs + S5P_IISAHB);
+
+ spin_unlock(&s3c_idma.lock);
+}
+
+static void s3c_idma_done(void *id, int bytes_xfer)
+{
+ struct snd_pcm_substream *substream = id;
+ struct lpam_i2s_pdata *prtd = substream->runtime->private_data;
+
+ pr_debug("%s:%d\n", __func__, __LINE__);
+
+ if (prtd && (prtd->state & ST_RUNNING))
+ snd_pcm_period_elapsed(substream);
+}
+
+static int s3c_idma_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct lpam_i2s_pdata *prtd = substream->runtime->private_data;
+ unsigned long idma_totbytes;
+
+ pr_debug("Entered %s\n", __func__);
+
+ idma_totbytes = params_buffer_bytes(params);
+ prtd->end = LP_TXBUFF_ADDR + idma_totbytes;
+ prtd->period = params_periods(params);
+ s3c_idma.dma_end = prtd->end;
+
+ snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+ memset(runtime->dma_area, 0, idma_totbytes);
+
+ runtime->dma_bytes = idma_totbytes;
+
+ s3c_idma_setcallbk(s3c_idma_done, params_period_bytes(params));
+
+ prtd->start = runtime->dma_addr;
+ prtd->pos = prtd->start;
+ prtd->end = prtd->start + idma_totbytes;
+
+ pr_debug("DmaAddr=@%x Total=%lubytes PrdSz=%u #Prds=%u dma_area=0x%x\n",
+ prtd->start, idma_totbytes, params_period_bytes(params),
+ prtd->period, (unsigned int)runtime->dma_area);
+
+ return 0;
+}
+
+static int s3c_idma_hw_free(struct snd_pcm_substream *substream)
+{
+ pr_debug("Entered %s\n", __func__);
+
+ snd_pcm_set_runtime_buffer(substream, NULL);
+
+ return 0;
+}
+
+static int s3c_idma_prepare(struct snd_pcm_substream *substream)
+{
+ struct lpam_i2s_pdata *prtd = substream->runtime->private_data;
+
+ pr_debug("Entered %s\n", __func__);
+
+ prtd->pos = prtd->start;
+
+ /* flush the DMA channel */
+ s3c_idma_ctrl(LPAM_DMA_STOP);
+ s3c_idma_enqueue((void *)substream);
+
+ return 0;
+}
+
+static int s3c_idma_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ struct lpam_i2s_pdata *prtd = substream->runtime->private_data;
+ int ret = 0;
+
+ pr_debug("Entered %s\n", __func__);
+
+ spin_lock(&prtd->lock);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ prtd->state |= ST_RUNNING;
+ s3c_idma_ctrl(LPAM_DMA_START);
+ break;
+
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ prtd->state &= ~ST_RUNNING;
+ s3c_idma_ctrl(LPAM_DMA_STOP);
+ break;
+
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ spin_unlock(&prtd->lock);
+
+ return ret;
+}
+
+static snd_pcm_uframes_t
+ s3c_idma_pointer(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct lpam_i2s_pdata *prtd = runtime->private_data;
+ dma_addr_t src;
+ unsigned long res;
+
+ spin_lock(&prtd->lock);
+
+ s3c_idma_getpos(&src);
+ res = src - prtd->start;
+
+ spin_unlock(&prtd->lock);
+
+ if (res >= snd_pcm_lib_buffer_bytes(substream)) {
+ if (res == snd_pcm_lib_buffer_bytes(substream))
+ res = 0;
+ }
+
+ return bytes_to_frames(substream->runtime, res);
+}
+
+static int s3c_idma_mmap(struct snd_pcm_substream *substream,
+ struct vm_area_struct *vma)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ unsigned long size, offset;
+ int ret;
+
+ pr_debug("Entered %s\n", __func__);
+
+ /* From snd_pcm_lib_mmap_iomem */
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ vma->vm_flags |= VM_IO;
+ size = vma->vm_end - vma->vm_start;
+ offset = vma->vm_pgoff << PAGE_SHIFT;
+ ret = io_remap_pfn_range(vma, vma->vm_start,
+ (runtime->dma_addr + offset) >> PAGE_SHIFT,
+ size, vma->vm_page_prot);
+
+ return ret;
+}
+
+static irqreturn_t s3c_iis_irq(int irqno, void *dev_id)
+{
+ u32 iiscon, iisahb, val, addr;
+
+ /* dump_i2s(); */
+ iisahb = readl(s3c_idma.regs + S5P_IISAHB);
+ iiscon = readl(s3c_idma.regs + S3C2412_IISCON);
+
+ if (iiscon & (1<<26)) {
+ pr_info("RxFIFO overflow interrupt\n");
+ writel(iiscon | (1<<26), s3c_idma.regs+S3C2412_IISCON);
+ }
+ if (iiscon & S5P_IISCON_FTXSURSTAT) {
+ iiscon |= S5P_IISCON_FTXURSTATUS;
+ writel(iiscon, s3c_idma.regs + S3C2412_IISCON);
+ pr_debug("TX_S underrun interrupt IISCON = 0x%08x\n",
+ readl(s3c_idma.regs + S3C2412_IISCON));
+ }
+
+ if (iiscon & S5P_IISCON_FTXURSTATUS) {
+ iiscon &= ~S5P_IISCON_FTXURINTEN;
+ iiscon |= S5P_IISCON_FTXURSTATUS;
+ writel(iiscon, s3c_idma.regs + S3C2412_IISCON);
+ pr_debug("TX_P underrun interrupt IISCON = 0x%08x\n",
+ readl(s3c_idma.regs + S3C2412_IISCON));
+ }
+
+ /* Check internal DMA level interrupt. */
+ if (iisahb & S5P_IISAHB_LVL0INT)
+ val = S5P_IISAHB_CLRLVL0;
+ else
+ val = 0;
+
+ if (val) {
+ iisahb |= val;
+ writel(iisahb, s3c_idma.regs + S5P_IISAHB);
+
+ addr = readl(s3c_idma.regs + S5P_IISADDR0);
+ addr += s3c_idma.dma_prd;
+
+ if (addr >= s3c_idma.dma_end)
+ addr = LP_TXBUFF_ADDR;
+
+ writel(addr, s3c_idma.regs + S5P_IISADDR0);
+
+ /* Finished dma transfer ? */
+ if (iisahb & S5P_IISLVLINTMASK) {
+ if (s3c_idma.cb)
+ s3c_idma.cb(s3c_idma.token, s3c_idma.dma_prd);
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int s3c_idma_open(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct lpam_i2s_pdata *prtd;
+ int ret;
+
+ pr_debug("Entered %s\n", __func__);
+
+ snd_soc_set_runtime_hwparams(substream, &s3c_idma_hardware);
+
+ prtd = kzalloc(sizeof(struct lpam_i2s_pdata), GFP_KERNEL);
+ if (prtd == NULL)
+ return -ENOMEM;
+
+ ret = request_irq(IRQ_I2S0, s3c_iis_irq, 0, "s3c-i2s", prtd);
+ if (ret < 0) {
+ pr_err("fail to claim i2s irq , ret = %d\n", ret);
+ kfree(prtd);
+ return ret;
+ }
+
+ spin_lock_init(&prtd->lock);
+
+ runtime->private_data = prtd;
+
+ return 0;
+}
+
+static int s3c_idma_close(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct lpam_i2s_pdata *prtd = runtime->private_data;
+
+ pr_debug("Entered %s, prtd = %p\n", __func__, prtd);
+
+ free_irq(IRQ_I2S0, prtd);
+
+ if (!prtd)
+ pr_err("s3c_idma_close called with prtd == NULL\n");
+
+ kfree(prtd);
+
+ return 0;
+}
+
+static struct snd_pcm_ops s3c_idma_ops = {
+ .open = s3c_idma_open,
+ .close = s3c_idma_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .trigger = s3c_idma_trigger,
+ .pointer = s3c_idma_pointer,
+ .mmap = s3c_idma_mmap,
+ .hw_params = s3c_idma_hw_params,
+ .hw_free = s3c_idma_hw_free,
+ .prepare = s3c_idma_prepare,
+};
+
+static void s3c_idma_pcm_free(struct snd_pcm *pcm)
+{
+ struct snd_pcm_substream *substream;
+ struct snd_dma_buffer *buf;
+
+ pr_debug("Entered %s\n", __func__);
+
+ substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+ if (!substream)
+ return;
+
+ buf = &substream->dma_buffer;
+ if (!buf->area)
+ return;;
+
+ iounmap(buf->area);
+
+ buf->area = NULL;
+ buf->addr = 0;
+}
+
+static int s3c_idma_preallocate_buffer(struct snd_pcm *pcm, int stream)
+{
+ struct snd_pcm_substream *substream = pcm->streams[stream].substream;
+ struct snd_dma_buffer *buf = &substream->dma_buffer;
+
+ pr_debug("Entered %s\n", __func__);
+ buf->dev.dev = pcm->card->dev;
+ buf->private_data = NULL;
+
+ /* Assign PCM buffer pointers */
+ buf->dev.type = SNDRV_DMA_TYPE_CONTINUOUS;
+ buf->addr = LP_TXBUFF_ADDR;
+ buf->bytes = s3c_idma_hardware.buffer_bytes_max;
+ buf->area = (unsigned char *)ioremap(buf->addr, buf->bytes);
+ pr_info("%s: VA-%p PA-%X %ubytes\n",
+ __func__, buf->area, buf->addr, buf->bytes);
+
+ return 0;
+}
+
+static u64 s3c_idma_mask = DMA_BIT_MASK(32);
+
+static int s3c_idma_pcm_new(struct snd_card *card,
+ struct snd_soc_dai *dai, struct snd_pcm *pcm)
+{
+ int ret = 0;
+
+ pr_debug("Entered %s\n", __func__);
+
+ if (!card->dev->dma_mask)
+ card->dev->dma_mask = &s3c_idma_mask;
+ if (!card->dev->coherent_dma_mask)
+ card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+
+ if (dai->driver->playback.channels_min)
+ ret = s3c_idma_preallocate_buffer(pcm,
+ SNDRV_PCM_STREAM_PLAYBACK);
+
+ return ret;
+}
+
+struct snd_soc_platform_driver idma_soc_platform = {
+ .ops = &s3c_idma_ops,
+ .pcm_new = s3c_idma_pcm_new,
+ .pcm_free = s3c_idma_pcm_free,
+};
+EXPORT_SYMBOL_GPL(idma_soc_platform);
+
+void s5p_idma_init(void *regs)
+{
+ spin_lock_init(&s3c_idma.lock);
+ s3c_idma.regs = regs;
+}
+
+MODULE_AUTHOR("Jaswinder Singh, jassi.brar@samsung.com");
+MODULE_DESCRIPTION("Samsung S5P LP-Audio DMA module");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/samsung/s3c-idma.h b/sound/soc/samsung/s3c-idma.h
new file mode 100644
index 0000000..351c3c3
--- /dev/null
+++ b/sound/soc/samsung/s3c-idma.h
@@ -0,0 +1,37 @@
+/*
+ * s3c-idma.h -- I2S0's Internal Dma driver
+ *
+ * Copyright (c) 2010 Samsung Electronics Co. Ltd
+ * Jaswinder Singh <jassi.brar@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.
+ *
+ */
+
+#ifndef __S3C_IDMA_H_
+#define __S3C_IDMA_H_
+
+#ifdef CONFIG_ARCH_S5PC1XX /* S5PC100 */
+#define MAX_LP_BUFF (128 * 1024)
+#define LP_DMA_PERIOD (105 * 1024)
+#else
+#define MAX_LP_BUFF (160 * 1024)
+#define LP_DMA_PERIOD (128 * 1024)
+#endif
+
+#define LP_TXBUFF_ADDR (0xC0000000)
+#define S5P_IISLVLINTMASK (0xf<<20)
+
+/* dma_state */
+#define LPAM_DMA_STOP 0
+#define LPAM_DMA_START 1
+
+extern struct snd_soc_platform_driver idma_soc_platform;
+extern int i2s_trigger_stop;
+extern bool audio_clk_gated ;
+void s5p_idma_init(void *regs);
+
+#endif /* __S3C_IDMA_H_ */
diff --git a/sound/soc/samsung/s5p-i2s_sec.c b/sound/soc/samsung/s5p-i2s_sec.c
new file mode 100644
index 0000000..747dd1c
--- /dev/null
+++ b/sound/soc/samsung/s5p-i2s_sec.c
@@ -0,0 +1,355 @@
+/*
+ * s5p-i2s_sec.c -- Secondary Fifo driver for I2S_v5
+ *
+ * (c) 2009 Samsung Electronics Co. Ltd
+ * - Jaswinder Singh Brar <jassi.brar@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 <linux/delay.h>
+#include <linux/clk.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <plat/regs-iis.h>
+
+#include <mach/regs-audss.h>
+#include <mach/dma.h>
+#include "s3c-dma.h"
+#include "s3c-idma.h"
+#include "s3c-i2s-v2.h"
+
+#define S3C64XX_DIV_BCLK S3C_I2SV2_DIV_BCLK
+#define S3C64XX_DIV_RCLK S3C_I2SV2_DIV_RCLK
+#define S3C64XX_DIV_PRESCALER S3C_I2SV2_DIV_PRESCALER
+
+#define S3C64XX_CLKSRC_PCLK (0)
+#define S3C64XX_CLKSRC_MUX (1)
+#define S3C64XX_CLKSRC_CDCLK (2)
+
+static void __iomem *s5p_i2s0_regs;
+
+static struct s3c2410_dma_client s5p_dma_client_outs = {
+ .name = "I2S_Sec PCM Stereo out"
+};
+
+static struct s3c_dma_params s5p_i2s_sec_pcm_out = {
+ .channel = DMACH_I2S0S_TX,
+ .client = &s5p_dma_client_outs,
+ .dma_size = 4,
+};
+
+static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai)
+{
+ return snd_soc_dai_get_drvdata(cpu_dai);
+}
+
+static void s5p_snd_rxctrl(int on)
+{
+ u32 fic, con, mod;
+
+ pr_debug("%s(%d)\n", __func__, on);
+
+ fic = readl(s5p_i2s0_regs + S3C2412_IISFIC);
+ con = readl(s5p_i2s0_regs + S3C2412_IISCON);
+ mod = readl(s5p_i2s0_regs + S3C2412_IISMOD);
+
+ pr_debug("%s: On=%d..IIS: CON=%x MOD=%x FIC=%x\n",
+ __func__, on, con, mod, fic);
+
+ if (on) {
+ con |= S3C2412_IISCON_RXDMA_ACTIVE | S3C2412_IISCON_IIS_ACTIVE;
+ con &= ~S3C2412_IISCON_RXDMA_PAUSE;
+ con &= ~S3C2412_IISCON_RXCH_PAUSE;
+
+ switch (mod & S3C2412_IISMOD_MODE_MASK) {
+ case S3C2412_IISMOD_MODE_TXRX:
+ case S3C2412_IISMOD_MODE_RXONLY:
+ /* do nothing, we are in the right mode */
+ break;
+
+ case S3C2412_IISMOD_MODE_TXONLY:
+ mod &= ~S3C2412_IISMOD_MODE_MASK;
+ mod |= S3C2412_IISMOD_MODE_TXRX;
+ break;
+
+ default:
+ printk(KERN_WARNING
+ "RXEN: Invalid MODE %x in IISMOD\n",
+ mod & S3C2412_IISMOD_MODE_MASK);
+ }
+
+ writel(mod, s5p_i2s0_regs + S3C2412_IISMOD);
+ writel(con, s5p_i2s0_regs + S3C2412_IISCON);
+ } else {
+ /* See txctrl notes on FIFOs. */
+
+ con &= ~S3C2412_IISCON_RXDMA_ACTIVE;
+ con |= S3C2412_IISCON_RXDMA_PAUSE;
+ con |= S3C2412_IISCON_RXCH_PAUSE;
+
+ switch (mod & S3C2412_IISMOD_MODE_MASK) {
+ case S3C2412_IISMOD_MODE_RXONLY:
+ con &= ~S3C2412_IISCON_IIS_ACTIVE;
+ mod &= ~S3C2412_IISMOD_MODE_MASK;
+ break;
+
+ case S3C2412_IISMOD_MODE_TXRX:
+ mod &= ~S3C2412_IISMOD_MODE_MASK;
+ mod |= S3C2412_IISMOD_MODE_TXONLY;
+ break;
+
+ default:
+ printk(KERN_WARNING
+ "RXDIS: Invalid MODE %x in IISMOD\n",
+ mod & S3C2412_IISMOD_MODE_MASK);
+ }
+
+ writel(con, s5p_i2s0_regs + S3C2412_IISCON);
+ writel(mod, s5p_i2s0_regs + S3C2412_IISMOD);
+ }
+
+ fic = readl(s5p_i2s0_regs + S3C2412_IISFIC);
+ pr_debug("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
+}
+
+static void s5p_snd_txctrl(int on)
+{
+ u32 iiscon, iismod;
+ iiscon = readl(s5p_i2s0_regs + S3C2412_IISCON);
+ iismod = readl(s5p_i2s0_regs + S3C2412_IISMOD);
+ pr_debug("%s: On=%d . IIS: CON=%x MOD=%x\n",
+ __func__, on, iiscon, iismod);
+
+ if (on) {
+ iiscon |= S3C2412_IISCON_IIS_ACTIVE;
+ iiscon &= ~S3C2412_IISCON_TXCH_PAUSE;
+ iiscon &= ~S5P_IISCON_TXSDMAPAUSE;
+ iiscon |= S5P_IISCON_TXSDMACTIVE;
+
+ switch (iismod & S3C2412_IISMOD_MODE_MASK) {
+ case S3C2412_IISMOD_MODE_TXONLY:
+ case S3C2412_IISMOD_MODE_TXRX:
+ /* do nothing, we are in the right mode */
+ break;
+
+ case S3C2412_IISMOD_MODE_RXONLY:
+ iismod &= ~S3C2412_IISMOD_MODE_MASK;
+ iismod |= S3C2412_IISMOD_MODE_TXRX;
+ break;
+
+ default:
+ printk(KERN_WARNING
+ "TXEN: Invalid MODE %x in IISMOD\n",
+ iismod & S3C2412_IISMOD_MODE_MASK);
+ break;
+ }
+
+ writel(iiscon, s5p_i2s0_regs + S3C2412_IISCON);
+ writel(iismod, s5p_i2s0_regs + S3C2412_IISMOD);
+ } else {
+ iiscon |= S5P_IISCON_TXSDMAPAUSE;
+ iiscon &= ~S5P_IISCON_TXSDMACTIVE;
+
+ /* return if primary is active */
+ if (iiscon & S3C2412_IISCON_TXDMA_ACTIVE) {
+ writel(iiscon, s5p_i2s0_regs + S3C2412_IISCON);
+ return;
+ }
+
+ iiscon |= S3C2412_IISCON_TXCH_PAUSE;
+
+ switch (iismod & S3C2412_IISMOD_MODE_MASK) {
+ case S3C2412_IISMOD_MODE_TXRX:
+ iismod &= ~S3C2412_IISMOD_MODE_MASK;
+ iismod |= S3C2412_IISMOD_MODE_RXONLY;
+ break;
+
+ case S3C2412_IISMOD_MODE_TXONLY:
+ iismod &= ~S3C2412_IISMOD_MODE_MASK;
+ iiscon &= ~S3C2412_IISCON_IIS_ACTIVE;
+ break;
+
+ default:
+ printk(KERN_WARNING
+ "TXDIS: Invalid MODE %x in IISMOD\n",
+ iismod & S3C2412_IISMOD_MODE_MASK);
+ break;
+ }
+
+
+ writel(iismod, s5p_i2s0_regs + S3C2412_IISMOD);
+ writel(iiscon, s5p_i2s0_regs + S3C2412_IISCON);
+ }
+}
+
+#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
+
+/*
+ * Wait for the LR signal to allow synchronisation to the L/R clock
+ * from the codec. May only be needed for slave mode.
+ */
+static int s5p_snd_lrsync(void)
+{
+ u32 iiscon;
+ unsigned long loops = msecs_to_loops(1);
+
+ pr_debug("Entered %s\n", __func__);
+
+ while (--loops) {
+ iiscon = readl(s5p_i2s0_regs + S3C2412_IISCON);
+ if (iiscon & S3C2412_IISCON_LRINDEX)
+ break;
+
+ cpu_relax();
+ }
+
+ if (!loops) {
+ pr_debug("%s: timeout\n", __func__);
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+int s5p_i2s_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;
+ u32 iismod;
+
+ snd_soc_dai_set_dma_data(rtd->cpu_dai,
+ substream, &s5p_i2s_sec_pcm_out);
+
+ iismod = readl(s5p_i2s0_regs + S3C2412_IISMOD);
+
+ /* Copy the same bps as Primary */
+ iismod &= ~S5P_IISMOD_BLCSMASK;
+ iismod |= ((iismod & S5P_IISMOD_BLCPMASK) << 2);
+
+ writel(iismod, s5p_i2s0_regs + S3C2412_IISMOD);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(s5p_i2s_hw_params);
+
+int s5p_i2s_startup(struct snd_soc_dai *dai)
+{
+ u32 iiscon, iisfic;
+ u32 iismod, iisahb;
+
+ iiscon = readl(s5p_i2s0_regs + S3C2412_IISCON);
+ iismod = readl(s5p_i2s0_regs + S3C2412_IISMOD);
+ iisahb = readl(s5p_i2s0_regs + S5P_IISAHB);
+
+ iisahb |= (S5P_IISAHB_DMARLD | S5P_IISAHB_DISRLDINT);
+ iismod |= S5P_IISMOD_TXSLP;
+
+ writel(iisahb, s5p_i2s0_regs + S5P_IISAHB);
+ writel(iismod, s5p_i2s0_regs + S3C2412_IISMOD);
+
+ s5p_snd_txctrl(0);
+ /*
+ * Don't turn-off RX setting as recording may be
+ * active during playback startup
+ * s5p_snd_rxctrl(0);
+ */
+
+ /* FIFOs must be flushed before enabling PSR
+ * and other MOD bits, so we do it here. */
+ if (iiscon & S5P_IISCON_TXSDMACTIVE)
+ return 0;
+
+ iisfic = readl(s5p_i2s0_regs + S5P_IISFICS);
+ iisfic |= S3C2412_IISFIC_TXFLUSH;
+ writel(iisfic, s5p_i2s0_regs + S5P_IISFICS);
+
+ do {
+ cpu_relax();
+ } while ((__raw_readl(s5p_i2s0_regs + S5P_IISFICS) >> 8) & 0x7f);
+
+ iisfic = readl(s5p_i2s0_regs + S5P_IISFICS);
+ iisfic &= ~S3C2412_IISFIC_TXFLUSH;
+ writel(iisfic, s5p_i2s0_regs + S5P_IISFICS);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(s5p_i2s_startup);
+
+int i2s_trigger_stop ;
+EXPORT_SYMBOL_GPL(i2s_trigger_stop);
+int s5p_i2s_trigger(struct snd_pcm_substream *substream,
+ int cmd, struct snd_soc_dai *dai)
+{
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ /* We don't configure clocks from this Sec i/f.
+ * So, we simply wait enough time for LRSYNC to
+ * get synced and not check return 'error'
+ */
+ s5p_snd_lrsync();
+ s5p_snd_txctrl(1);
+ i2s_trigger_stop = 0;
+ break;
+
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ i2s_trigger_stop = 1;
+ s5p_snd_txctrl(0);
+ break;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(s5p_i2s_trigger);
+
+struct snd_soc_dai i2s_sec_fifo_dai = {
+ .name = "i2s-sec-fifo",
+ .id = 0,
+};
+EXPORT_SYMBOL_GPL(i2s_sec_fifo_dai);
+
+
+void s5p_i2s_sec_init(void *regs, dma_addr_t phys_base)
+{
+ u32 val;
+#ifdef CONFIG_ARCH_S5PV210
+ /* We use I2SCLK for rate generation, so set EPLLout as
+ * the parent of I2SCLK.
+ */
+ val = readl(S5P_CLKSRC_AUDSS);
+ val &= ~(0x3<<2);
+ val |= (1<<0);
+ writel(val, S5P_CLKSRC_AUDSS);
+
+ val = readl(S5P_CLKGATE_AUDSS);
+ val |= (0x7f<<0);
+ writel(val, S5P_CLKGATE_AUDSS);
+#else
+ #error INITIALIZE HERE!
+#endif
+
+ s5p_i2s0_regs = regs;
+ s5p_i2s_sec_pcm_out.dma_addr = phys_base + S5P_IISTXDS;
+
+ s5p_snd_rxctrl(0);
+ s5p_snd_txctrl(0);
+ s5p_idma_init(regs);
+}
+
+/* Module information */
+MODULE_AUTHOR("Jaswinder Singh <jassi.brar@samsung.com>");
+MODULE_DESCRIPTION("S5P I2S-SecFifo SoC Interface");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/samsung/s5pc1xx-i2s.c b/sound/soc/samsung/s5pc1xx-i2s.c
new file mode 100644
index 0000000..674ccaa
--- /dev/null
+++ b/sound/soc/samsung/s5pc1xx-i2s.c
@@ -0,0 +1,1152 @@
+/* sound/soc/s3c24xx/s5pc1xx-i2s.c
+ *
+ * ALSA SoC Audio Layer - S3C64XX I2S driver
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ * http://armlinux.simtec.co.uk/
+ *
+ * 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/init.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/regulator/consumer.h>
+
+#include <sound/soc.h>
+#include <sound/pcm_params.h>
+
+#include <plat/regs-iis.h>
+#include <plat/audio.h>
+
+#include <mach/dma.h>
+
+#include <mach/map.h>
+#include <mach/regs-audss.h>
+#include <mach/regs-clock.h>
+#include <linux/wakelock.h>
+#include "s3c-dma.h"
+#include "s5pc1xx-i2s.h"
+
+/*
+ * The value should be set to maximum of the total number
+ * of I2Sv3 controllers that any supported SoC has.
+ */
+#define MAX_I2SV3 2
+
+static struct s3c2410_dma_client s3c64xx_dma_client_out = {
+ .name = "I2S PCM Stereo out"
+};
+
+static struct s3c2410_dma_client s3c64xx_dma_client_in = {
+ .name = "I2S PCM Stereo in"
+};
+
+static struct snd_soc_dai_ops s3c64xx_i2s_dai_ops;
+static struct s3c_dma_params s3c64xx_i2s_pcm_stereo_out[MAX_I2SV3];
+static struct s3c_dma_params s3c64xx_i2s_pcm_stereo_in[MAX_I2SV3];
+static struct s3c_i2sv2_info s3c64xx_i2s[MAX_I2SV3];
+
+static struct snd_soc_dai_driver s3c64xx_i2s_dai_driver[MAX_I2SV3];
+bool audio_clk_gated; /* At first, clock & i2s0_pd is enabled in probe() */
+//EXPORT_SYMBOL_GPL(s3c64xx_i2s_dai);
+
+/* For I2S Clock/Power Gating */
+static int tx_clk_enabled ;
+static int rx_clk_enabled ;
+static int reg_saved_ok ;
+
+void dump_i2s(struct s3c_i2sv2_info *i2s)
+{
+ printk(KERN_INFO "IISMOD=0x%x..IISCON=0x%x..IISPSR=0x%x\
+ IISAHB=0x%x..\n" , readl(i2s->regs + S3C2412_IISMOD),
+ readl(i2s->regs + S3C2412_IISCON),
+ readl(i2s->regs + S3C2412_IISPSR),
+ readl(i2s->regs + S5P_IISAHB));
+ printk(KERN_INFO "..AUDSSRC=0x%x..AUDSSDIV=0x%x..\
+ AUDSSGATE=0x%x..\n" , readl(S5P_CLKSRC_AUDSS),
+ readl(S5P_CLKDIV_AUDSS), readl(S5P_CLKGATE_AUDSS));
+}
+
+#define dump_reg(iis)
+
+static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai)
+{
+ return snd_soc_dai_get_drvdata(cpu_dai);
+}
+
+struct clk *s3c64xx_i2s_get_clock(struct snd_soc_dai *dai)
+{
+ struct s3c_i2sv2_info *i2s = to_info(dai);
+ u32 iismod = readl(i2s->regs + S3C2412_IISMOD);
+
+ if (iismod & S3C64XX_IISMOD_IMS_SYSMUX)
+ return i2s->iis_clk;
+ else
+ return i2s->iis_ipclk;
+}
+EXPORT_SYMBOL_GPL(s3c64xx_i2s_get_clock);
+
+void s5p_i2s_set_clk_enabled(struct snd_soc_dai *dai, bool state)
+{
+ struct s3c_i2sv2_info *i2s = to_info(dai);
+
+ pr_debug("..entering %s\n", __func__);
+
+ if (state) {
+ if (audio_clk_gated == 1)
+ regulator_enable(i2s->regulator);
+
+ if (dai->id == 0) { /* I2S V5.1? */
+ clk_enable(i2s->iis_ipclk);
+ clk_enable(i2s->iis_clk);
+ clk_enable(i2s->iis_busclk);
+ }
+ audio_clk_gated = 0;
+ } else {
+ if (dai->id == 0) { /* I2S V5.1? */
+ clk_disable(i2s->iis_busclk);
+ clk_disable(i2s->iis_clk);
+ clk_disable(i2s->iis_ipclk);
+ }
+
+ if (audio_clk_gated == 0)
+ regulator_disable(i2s->regulator);
+
+ audio_clk_gated = 1;
+ }
+}
+
+static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct s3c_i2sv2_info *i2s = to_info(dai);
+ u32 iismod;
+
+ pr_debug("Entered %s\n", __func__);
+
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ snd_soc_dai_set_dma_data(dai, substream,
+ i2s->dma_playback);
+ else
+ snd_soc_dai_set_dma_data(dai, substream,
+ i2s->dma_capture);
+
+ /* Working copies of register */
+ iismod = readl(i2s->regs + S3C2412_IISMOD);
+ pr_debug("%s: r: IISMOD: %x\n", __func__, iismod);
+
+ switch (params_channels(params)) {
+ case 1:
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ i2s->dma_playback->dma_size = 2;
+ else
+ i2s->dma_capture->dma_size = 2;
+ break;
+ case 2:
+ break;
+ default:
+ break;
+ }
+#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S8:
+ iismod |= S3C2412_IISMOD_8BIT;
+ break;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ iismod &= ~S3C2412_IISMOD_8BIT;
+ break;
+ }
+#endif
+
+#if defined(CONFIG_PLAT_S3C64XX) || defined(CONFIG_PLAT_S5P)
+ iismod &= ~(S3C64XX_IISMOD_BLC_MASK | S3C2412_IISMOD_BCLK_MASK);
+ /* Sample size */
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S8:
+ /* 8 bit sample, 16fs BCLK */
+ iismod |= (S3C64XX_IISMOD_BLC_8BIT | S3C2412_IISMOD_BCLK_16FS);
+ break;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ /* 16 bit sample, 32fs BCLK */
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ /* 24 bit sample, 48fs BCLK */
+ iismod |= (S3C64XX_IISMOD_BLC_24BIT | S3C2412_IISMOD_BCLK_48FS);
+ break;
+ }
+
+ /* Set the IISMOD[25:24](BLC_P) to same value */
+ iismod &= ~(S5P_IISMOD_BLCPMASK);
+ iismod |= ((iismod & S3C64XX_IISMOD_BLC_MASK) << 11);
+#endif
+
+ writel(iismod, i2s->regs + S3C2412_IISMOD);
+ pr_debug("%s: w: IISMOD: %x\n", __func__, iismod);
+ return 0;
+}
+
+static int s5p_i2s_wr_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+#ifdef CONFIG_S5P_INTERNAL_DMA
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ s5p_i2s_hw_params(substream, params, dai);
+ else
+ s3c2412_i2s_hw_params(substream, params, dai);
+
+#else
+ s3c2412_i2s_hw_params(substream, params, dai);
+#endif
+ return 0;
+}
+
+#define S3C2412_I2S_DEBUG_CON 1
+
+#define bit_set(v, b) (((v) & (b)) ? 1 : 0)
+
+#if S3C2412_I2S_DEBUG_CON
+static void dbg_showcon(const char *fn, u32 con)
+{
+ printk(KERN_DEBUG "%s: LRI=%d, TXFEMPT=%d, RXFEMPT=%d, TXFFULL=%d,\
+ RXFFULL=%d\n", fn,
+ bit_set(con, S3C2412_IISCON_LRINDEX),
+ bit_set(con, S3C2412_IISCON_TXFIFO_EMPTY),
+ bit_set(con, S3C2412_IISCON_RXFIFO_EMPTY),
+ bit_set(con, S3C2412_IISCON_TXFIFO_FULL),
+ bit_set(con, S3C2412_IISCON_RXFIFO_FULL));
+
+ printk(KERN_DEBUG "%s: PAUSE: TXDMA=%d, RXDMA=%d, TXCH=%d, RXCH=%d\n",
+ fn,
+ bit_set(con, S3C2412_IISCON_TXDMA_PAUSE),
+ bit_set(con, S3C2412_IISCON_RXDMA_PAUSE),
+ bit_set(con, S3C2412_IISCON_TXCH_PAUSE),
+ bit_set(con, S3C2412_IISCON_RXCH_PAUSE));
+ printk(KERN_DEBUG "%s: ACTIVE: TXDMA=%d, RXDMA=%d, IIS=%d\n", fn,
+ bit_set(con, S3C2412_IISCON_TXDMA_ACTIVE),
+ bit_set(con, S3C2412_IISCON_RXDMA_ACTIVE),
+ bit_set(con, S3C2412_IISCON_IIS_ACTIVE));
+}
+#else
+static inline void dbg_showcon(const char *fn, u32 con)
+{
+}
+#endif
+
+/* Turn on or off the transmission path. */
+static void s3c2412_snd_txctrl(struct s3c_i2sv2_info *i2s, int on)
+{
+ void __iomem *regs = i2s->regs;
+ u32 fic, con, mod;
+
+ pr_debug("%s(%d)\n", __func__, on);
+
+ fic = readl(regs + S3C2412_IISFIC);
+ con = readl(regs + S3C2412_IISCON);
+ mod = readl(regs + S3C2412_IISMOD);
+
+ pr_debug("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
+
+ if (on) {
+ con |= S3C2412_IISCON_TXDMA_ACTIVE | S3C2412_IISCON_IIS_ACTIVE;
+ con &= ~S3C2412_IISCON_TXDMA_PAUSE;
+ con &= ~S3C2412_IISCON_TXCH_PAUSE;
+
+ switch (mod & S3C2412_IISMOD_MODE_MASK) {
+ case S3C2412_IISMOD_MODE_TXONLY:
+ case S3C2412_IISMOD_MODE_TXRX:
+ /* do nothing, we are in the right mode */
+ break;
+
+ case S3C2412_IISMOD_MODE_RXONLY:
+ mod &= ~S3C2412_IISMOD_MODE_MASK;
+ mod |= S3C2412_IISMOD_MODE_TXRX;
+ break;
+
+ default:
+ dev_err(i2s->dev, "TXEN: Invalid MODE %x in IISMOD\n",
+ mod & S3C2412_IISMOD_MODE_MASK);
+ break;
+ }
+
+ writel(con, regs + S3C2412_IISCON);
+ writel(mod, regs + S3C2412_IISMOD);
+ } else {
+ /* Note, we do not have any indication that the FIFO problems
+ * tha the S3C2410/2440 had apply here, so we should be able
+ * to disable the DMA and TX without resetting the FIFOS.
+ */
+
+ con |= S3C2412_IISCON_TXDMA_PAUSE;
+ con &= ~S3C2412_IISCON_TXDMA_ACTIVE;
+ if (con & S5P_IISCON_TXSDMACTIVE) { /* If sec is active */
+ writel(con, regs + S3C2412_IISCON);
+ return;
+ }
+ con |= S3C2412_IISCON_TXCH_PAUSE;
+
+ switch (mod & S3C2412_IISMOD_MODE_MASK) {
+ case S3C2412_IISMOD_MODE_TXRX:
+ mod &= ~S3C2412_IISMOD_MODE_MASK;
+ mod |= S3C2412_IISMOD_MODE_RXONLY;
+ break;
+
+ case S3C2412_IISMOD_MODE_TXONLY:
+ mod &= ~S3C2412_IISMOD_MODE_MASK;
+ con &= ~S3C2412_IISCON_IIS_ACTIVE;
+ break;
+
+ default:
+ dev_err(i2s->dev, "TXDIS: Invalid MODE %x in IISMOD\n",
+ mod & S3C2412_IISMOD_MODE_MASK);
+ break;
+ }
+
+ writel(mod, regs + S3C2412_IISMOD);
+ writel(con, regs + S3C2412_IISCON);
+ }
+
+ fic = readl(regs + S3C2412_IISFIC);
+ dbg_showcon(__func__, con);
+ pr_debug("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
+}
+
+#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
+
+static void s3c2412_snd_rxctrl(struct s3c_i2sv2_info *i2s, int on)
+{
+ void __iomem *regs = i2s->regs;
+ u32 fic, con, mod;
+
+ pr_debug("%s(%d)\n", __func__, on);
+
+ fic = readl(regs + S3C2412_IISFIC);
+ con = readl(regs + S3C2412_IISCON);
+ mod = readl(regs + S3C2412_IISMOD);
+
+ pr_debug("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
+
+ if (on) {
+ con |= S3C2412_IISCON_RXDMA_ACTIVE | S3C2412_IISCON_IIS_ACTIVE;
+ con &= ~S3C2412_IISCON_RXDMA_PAUSE;
+ con &= ~S3C2412_IISCON_RXCH_PAUSE;
+
+ switch (mod & S3C2412_IISMOD_MODE_MASK) {
+ case S3C2412_IISMOD_MODE_TXRX:
+ case S3C2412_IISMOD_MODE_RXONLY:
+ /* do nothing, we are in the right mode */
+ break;
+
+ case S3C2412_IISMOD_MODE_TXONLY:
+ mod &= ~S3C2412_IISMOD_MODE_MASK;
+ mod |= S3C2412_IISMOD_MODE_TXRX;
+ break;
+
+ default:
+ dev_err(i2s->dev, "RXEN: Invalid MODE %x in IISMOD\n",
+ mod & S3C2412_IISMOD_MODE_MASK);
+ }
+
+ writel(mod, regs + S3C2412_IISMOD);
+ writel(con, regs + S3C2412_IISCON);
+ } else {
+ /* See txctrl notes on FIFOs. */
+
+ con &= ~S3C2412_IISCON_RXDMA_ACTIVE;
+ con |= S3C2412_IISCON_RXDMA_PAUSE;
+ con |= S3C2412_IISCON_RXCH_PAUSE;
+
+ switch (mod & S3C2412_IISMOD_MODE_MASK) {
+ case S3C2412_IISMOD_MODE_RXONLY:
+ con &= ~S3C2412_IISCON_IIS_ACTIVE;
+ mod &= ~S3C2412_IISMOD_MODE_MASK;
+ break;
+
+ case S3C2412_IISMOD_MODE_TXRX:
+ mod &= ~S3C2412_IISMOD_MODE_MASK;
+ mod |= S3C2412_IISMOD_MODE_TXONLY;
+ break;
+
+ default:
+ dev_err(i2s->dev, "RXDIS: Invalid MODE %x in IISMOD\n",
+ mod & S3C2412_IISMOD_MODE_MASK);
+ }
+
+ writel(con, regs + S3C2412_IISCON);
+ writel(mod, regs + S3C2412_IISMOD);
+ }
+
+ fic = readl(regs + S3C2412_IISFIC);
+ pr_debug("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
+}
+
+/*
+ * Wait for the LR signal to allow synchronisation to the L/R clock
+ * from the codec. May only be needed for slave mode.
+ */
+static int s3c2412_snd_lrsync(struct s3c_i2sv2_info *i2s)
+{
+ u32 iiscon;
+ unsigned long loops = msecs_to_loops(5);
+
+ pr_debug("Entered %s\n", __func__);
+
+ while (--loops) {
+ iiscon = readl(i2s->regs + S3C2412_IISCON);
+ if (iiscon & S3C2412_IISCON_LRINDEX)
+ break;
+
+ cpu_relax();
+ }
+
+ if (!loops) {
+ printk(KERN_ERR "%s: timeout\n", __func__);
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ struct s3c_i2sv2_info *i2s = to_info(dai);
+ int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
+ unsigned long irqs;
+ int ret = 0;
+
+ pr_debug("Entered %s\n", __func__);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ if (!i2s->master) {
+ ret = s3c2412_snd_lrsync(i2s);
+ if (ret)
+ goto exit_err;
+ }
+
+ local_irq_save(irqs);
+
+ if (capture)
+ s3c2412_snd_rxctrl(i2s, 1);
+ else
+ s3c2412_snd_txctrl(i2s, 1);
+
+ local_irq_restore(irqs);
+ break;
+
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ local_irq_save(irqs);
+
+ if (capture)
+ s3c2412_snd_rxctrl(i2s, 0);
+ else
+ s3c2412_snd_txctrl(i2s, 0);
+
+ local_irq_restore(irqs);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+exit_err:
+ return ret;
+}
+
+static int s5p_i2s_wr_trigger(struct snd_pcm_substream *substream,
+ int cmd, struct snd_soc_dai *dai)
+{
+#ifdef CONFIG_S5P_INTERNAL_DMA
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ s5p_i2s_trigger(substream, cmd, dai);
+ else
+ s3c2412_i2s_trigger(substream, cmd, dai);
+
+#else
+ s3c2412_i2s_trigger(substream, cmd, dai);
+#endif
+ return 0;
+}
+
+/*
+ * Set S3C2412 I2S DAI format
+ */
+static int s5p_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
+ unsigned int fmt)
+{
+ struct s3c_i2sv2_info *i2s = to_info(cpu_dai);
+ u32 iismod;
+
+ pr_debug("Entered %s\n", __func__);
+
+ iismod = readl(i2s->regs + S3C2412_IISMOD);
+ pr_debug("hw_params r: IISMOD: %x\n", iismod);
+
+#if defined(CONFIG_PLAT_S3C64XX) || defined(CONFIG_PLAT_S5P)
+ /* From Rev1.1 datasheet, we have two master and two slave modes:
+ * IMS[11:10]:
+ * 00 = master mode, fed from PCLK
+ * 01 = master mode, fed from CLKAUDIO
+ * 10 = slave mode, using PCLK
+ * 11 = slave mode, using I2SCLK
+ */
+#define IISMOD_MASTER_MASK (1 << 11)
+#define IISMOD_SLAVE (1 << 11)
+#define IISMOD_MASTER (0 << 11)
+#endif
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ i2s->master = 0;
+ iismod &= ~IISMOD_MASTER_MASK;
+ iismod |= IISMOD_SLAVE;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ i2s->master = 1;
+ iismod &= ~IISMOD_MASTER_MASK;
+ iismod |= IISMOD_MASTER;
+ break;
+ default:
+ pr_err("unknwon master/slave format\n");
+ return -EINVAL;
+ }
+
+ iismod &= ~S3C2412_IISMOD_SDF_MASK;
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_RIGHT_J:
+ iismod |= S3C2412_IISMOD_LR_RLOW;
+ iismod |= S3C2412_IISMOD_SDF_MSB;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ iismod |= S3C2412_IISMOD_LR_RLOW;
+ iismod |= S3C2412_IISMOD_SDF_LSB;
+ break;
+ case SND_SOC_DAIFMT_I2S:
+ iismod &= ~S3C2412_IISMOD_LR_RLOW;
+ iismod |= S3C2412_IISMOD_SDF_IIS;
+ break;
+ default:
+ pr_err("Unknown data format\n");
+ return -EINVAL;
+ }
+
+ writel(iismod, i2s->regs + S3C2412_IISMOD);
+ pr_debug("hw_params w: IISMOD: %x\n", iismod);
+ return 0;
+}
+
+static int s5p_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai,
+ int div_id, int div)
+{
+ struct s3c_i2sv2_info *i2s = to_info(cpu_dai);
+ u32 reg;
+
+ pr_debug("%s(%p, %d, %d)\n", __func__, cpu_dai, div_id, div);
+
+ switch (div_id) {
+ case S3C_I2SV2_DIV_BCLK:
+ if (div > 3) {
+ /* convert value to bit field */
+ switch (div) {
+ case 16:
+ div = S3C2412_IISMOD_BCLK_16FS;
+ break;
+ case 32:
+ div = S3C2412_IISMOD_BCLK_32FS;
+ break;
+ case 24:
+ div = S3C2412_IISMOD_BCLK_24FS;
+ break;
+ case 48:
+ div = S3C2412_IISMOD_BCLK_48FS;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ reg = readl(i2s->regs + S3C2412_IISMOD);
+ reg &= ~S3C2412_IISMOD_BCLK_MASK;
+ writel(reg | div, i2s->regs + S3C2412_IISMOD);
+ pr_debug("%s: MOD=%08x\n", __func__,
+ readl(i2s->regs + S3C2412_IISMOD));
+ break;
+
+ case S3C_I2SV2_DIV_RCLK:
+ if (div > 3) {
+ /* convert value to bit field */
+
+ switch (div) {
+ case 256:
+ div = S3C2412_IISMOD_RCLK_256FS;
+ break;
+ case 384:
+ div = S3C2412_IISMOD_RCLK_384FS;
+ break;
+ case 512:
+ div = S3C2412_IISMOD_RCLK_512FS;
+ break;
+ case 768:
+ div = S3C2412_IISMOD_RCLK_768FS;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ reg = readl(i2s->regs + S3C2412_IISMOD);
+ reg &= ~S3C2412_IISMOD_RCLK_MASK;
+ writel(reg | div, i2s->regs + S3C2412_IISMOD);
+ pr_debug("%s: MOD=%08x\n", __func__,
+ readl(i2s->regs + S3C2412_IISMOD));
+ break;
+
+ case S3C_I2SV2_DIV_PRESCALER:
+ if (div >= 0)
+ writel((div << 8) | S3C2412_IISPSR_PSREN,
+ i2s->regs + S3C2412_IISPSR);
+ else
+ writel(0x0, i2s->regs + S3C2412_IISPSR);
+ pr_debug("%s: PSR=%08x\n", __func__,
+ readl(i2s->regs + S3C2412_IISPSR));
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int s5p_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct clk *clk;
+ struct s3c_i2sv2_info *i2s = to_info(cpu_dai);
+ u32 iismod = readl(i2s->regs + S3C2412_IISMOD);
+
+ switch (clk_id) {
+ case S3C64XX_CLKSRC_PCLK:
+ iismod &= ~S3C64XX_IISMOD_IMS_SYSMUX;
+ break;
+ case S3C64XX_CLKSRC_MUX:
+ iismod |= S3C64XX_IISMOD_IMS_SYSMUX;
+ break;
+
+ case S3C64XX_CLKSRC_CDCLK:
+ switch (dir) {
+ case SND_SOC_CLOCK_IN:
+ iismod |= S3C64XX_IISMOD_CDCLKCON;
+ break;
+ case SND_SOC_CLOCK_OUT:
+ iismod &= ~S3C64XX_IISMOD_CDCLKCON;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+#ifdef USE_CLKAUDIO
+ /* IIS-IP is Master and derives its clocks from I2SCLKD2 */
+ case S3C_CLKSRC_CLKAUDIO:
+ if (!i2s->master)
+ return -EINVAL;
+ iismod &= ~S3C_IISMOD_IMSMASK;
+ iismod |= clk_id;
+ clk = clk_get(NULL, "fout_epll");
+ if (IS_ERR(clk)) {
+ printk(KERN_ERR
+ "failed to get %s\n", "fout_epll");
+ return -EBUSY;
+ }
+ clk_disable(clk);
+ switch (freq) {
+ case 8000:
+ case 16000:
+ case 32000:
+ case 48000:
+ case 64000:
+ case 96000:
+ clk_set_rate(clk, 49152000);
+ break;
+ case 11025:
+ case 22050:
+ case 44100:
+ case 88200:
+ default:
+ clk_set_rate(clk, 67738000);
+ break;
+ }
+ clk_enable(clk);
+ clk_put(clk);
+ break;
+#endif
+ /* IIS-IP is Slave and derives its clocks from the Codec Chip */
+ case S3C64XX_CLKSRC_I2SEXT:
+ iismod &= ~S3C64XX_IISMOD_IMSMASK;
+ iismod |= clk_id;
+ /* Operation clock for I2S logic selected as Audio Bus Clock */
+ iismod |= S3C64XX_IISMOD_OPPCLK;
+
+ clk = clk_get(NULL, "fout_epll");
+ if (IS_ERR(clk)) {
+ printk(KERN_ERR
+ "failed to get %s\n", "fout_epll");
+ return -EBUSY;
+ }
+ clk_disable(clk);
+ clk_set_rate(clk, 67738000);
+ clk_enable(clk);
+ clk_put(clk);
+ break;
+
+ case S3C64XX_CDCLKSRC_EXT:
+ iismod |= S3C64XX_IISMOD_CDCLKCON;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ writel(iismod, i2s->regs + S3C2412_IISMOD);
+
+ return 0;
+}
+
+static int s5p_i2s_wr_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct s3c_i2sv2_info *i2s = to_info(dai);
+ u32 iiscon, iisfic;
+
+ if (!tx_clk_enabled && !rx_clk_enabled) {
+ s5p_i2s_set_clk_enabled(dai, 1);
+ if (reg_saved_ok == true) {
+ /* Is this dai for I2Sv5? (I2S0) */
+ if (dai->id == 0) {
+ writel(i2s->suspend_audss_clksrc,
+ S5P_CLKSRC_AUDSS);
+ writel(i2s->suspend_audss_clkdiv,
+ S5P_CLKDIV_AUDSS);
+ writel(i2s->suspend_audss_clkgate,
+ S5P_CLKGATE_AUDSS);
+ }
+ writel(i2s->suspend_iismod, i2s->regs + S3C2412_IISMOD);
+ writel(i2s->suspend_iiscon, i2s->regs + S3C2412_IISCON);
+ writel(i2s->suspend_iispsr, i2s->regs + S3C2412_IISPSR);
+ writel(i2s->suspend_iisahb, i2s->regs + S5P_IISAHB);
+ reg_saved_ok = false;
+ pr_debug("I2S Audio Clock enabled and \
+ Registers restored...\n");
+ }
+ }
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ pr_debug("Inside..%s..for playback stream\n" , __func__);
+ tx_clk_enabled = 1;
+ } else {
+ pr_debug("Inside..%s..for capture stream\n" , __func__);
+ rx_clk_enabled = 1;
+ iiscon = readl(i2s->regs + S3C2412_IISCON);
+ if (iiscon & S3C2412_IISCON_RXDMA_ACTIVE)
+ return 0;
+
+ iisfic = readl(i2s->regs + S3C2412_IISFIC);
+ iisfic |= S3C2412_IISFIC_RXFLUSH;
+ writel(iisfic, i2s->regs + S3C2412_IISFIC);
+
+ do {
+ cpu_relax();
+ } while ((__raw_readl(i2s->regs + S3C2412_IISFIC) >> 0) & 0x7f);
+
+ iisfic = readl(i2s->regs + S3C2412_IISFIC);
+ iisfic &= ~S3C2412_IISFIC_RXFLUSH;
+ writel(iisfic, i2s->regs + S3C2412_IISFIC);
+ }
+
+#ifdef CONFIG_S5P_INTERNAL_DMA
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ s5p_i2s_startup(dai);
+#endif
+ dump_reg(i2s);
+ return 0;
+}
+
+static void s5p_i2s_wr_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct s3c_i2sv2_info *i2s = to_info(dai);
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ pr_debug("Inside %s for playback stream\n" , __func__);
+ tx_clk_enabled = 0;
+ } else {
+ pr_debug("Inside..%s..for capture stream\n" , __func__);
+ if (readl(i2s->regs + S3C2412_IISCON) & (1<<26)) {
+ pr_debug("\n rx overflow int in %s\n" , __func__);
+ /* clear rxfifo overflow interrupt */
+ writel(readl(i2s->regs + S3C2412_IISCON) | (1<<26),
+ i2s->regs + S3C2412_IISCON);
+ /* flush rx */
+ writel(readl(i2s->regs + S3C2412_IISFIC) | (1<<7) ,
+ i2s->regs + S3C2412_IISFIC);
+ }
+ rx_clk_enabled = 0;
+ }
+
+ if (!tx_clk_enabled && !rx_clk_enabled) {
+ i2s->suspend_iismod = readl(i2s->regs + S3C2412_IISMOD);
+ i2s->suspend_iiscon = readl(i2s->regs + S3C2412_IISCON);
+ i2s->suspend_iispsr = readl(i2s->regs + S3C2412_IISPSR);
+ i2s->suspend_iisahb = readl(i2s->regs + S5P_IISAHB);
+ /* Is this dai for I2Sv5? (I2S0) */
+ if (dai->id == 0) {
+ i2s->suspend_audss_clksrc = readl(S5P_CLKSRC_AUDSS);
+ i2s->suspend_audss_clkdiv = readl(S5P_CLKDIV_AUDSS);
+ i2s->suspend_audss_clkgate = readl(S5P_CLKGATE_AUDSS);
+ }
+ reg_saved_ok = true;
+ s5p_i2s_set_clk_enabled(dai, 0);
+ pr_debug("I2S Audio Clock disabled and Registers stored...\n");
+ pr_debug("Inside %s CLkGATE_IP3=0x%x..\n",
+ __func__ , __raw_readl(S5P_CLKGATE_IP3));
+ }
+
+ return;
+}
+
+#define S3C64XX_I2S_RATES \
+ (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
+ SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
+ SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \
+ SNDRV_PCM_RATE_KNOT)
+
+#define S3C64XX_I2S_FMTS \
+ (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
+ SNDRV_PCM_FMTBIT_S24_LE)
+
+static void s3c64xx_iis_dai_init(struct snd_soc_dai_driver *dai)
+{
+ dai->name = "s5pc1xx-i2s";
+ dai->playback.channels_min = 2;
+ dai->playback.channels_max = 2;
+ dai->playback.rates = S3C64XX_I2S_RATES;
+ dai->playback.formats = S3C64XX_I2S_FMTS;
+ dai->capture.channels_min = 1;
+ dai->capture.channels_max = 2;
+ dai->capture.rates = S3C64XX_I2S_RATES;
+ dai->capture.formats = S3C64XX_I2S_FMTS;
+ dai->ops = &s3c64xx_i2s_dai_ops;
+}
+
+/* suspend/resume are not necessary due to Clock/Pwer gating scheme... */
+#ifdef CONFIG_PM
+static int s5p_i2s_suspend(struct snd_soc_dai *dai)
+{
+ struct s3c_i2sv2_info *i2s = to_info(dai);
+
+ if (reg_saved_ok != true) {
+ dump_reg(i2s);
+ i2s->suspend_iismod = readl(i2s->regs + S3C2412_IISMOD);
+ i2s->suspend_iiscon = readl(i2s->regs + S3C2412_IISCON);
+ i2s->suspend_iispsr = readl(i2s->regs + S3C2412_IISPSR);
+ i2s->suspend_iisahb = readl(i2s->regs + S5P_IISAHB);
+ if (dai->id == 0) {
+ i2s->suspend_audss_clksrc = readl(S5P_CLKSRC_AUDSS);
+ i2s->suspend_audss_clkdiv = readl(S5P_CLKDIV_AUDSS);
+ i2s->suspend_audss_clkgate = readl(S5P_CLKGATE_AUDSS);
+ }
+ }
+ return 0;
+}
+
+static int s5p_i2s_resume(struct snd_soc_dai *dai)
+{
+ struct s3c_i2sv2_info *i2s = to_info(dai);
+
+ pr_info("dai_active %d, IISMOD %08x, IISCON %08x\n",
+ dai->active, i2s->suspend_iismod, i2s->suspend_iiscon);
+ if (reg_saved_ok != true) {
+ if (dai->id == 0) {
+ writel(i2s->suspend_audss_clksrc, S5P_CLKSRC_AUDSS);
+ writel(i2s->suspend_audss_clkdiv, S5P_CLKDIV_AUDSS);
+ writel(i2s->suspend_audss_clkgate, S5P_CLKGATE_AUDSS);
+ pr_info("Inside %s..@%d\n" , __func__ , __LINE__);
+ }
+ writel(i2s->suspend_iiscon, i2s->regs + S3C2412_IISCON);
+ writel(i2s->suspend_iismod, i2s->regs + S3C2412_IISMOD);
+ writel(i2s->suspend_iispsr, i2s->regs + S3C2412_IISPSR);
+ writel(i2s->suspend_iisahb, i2s->regs + S5P_IISAHB);
+ }
+ return 0;
+ /* Is this dai for I2Sv5? */
+ if (dai->id == 0)
+ writel(i2s->suspend_audss_clksrc, S5P_CLKSRC_AUDSS);
+
+ writel(S3C2412_IISFIC_RXFLUSH | S3C2412_IISFIC_TXFLUSH,
+ i2s->regs + S3C2412_IISFIC);
+
+ ndelay(250);
+ writel(0x0, i2s->regs + S3C2412_IISFIC);
+
+ return 0;
+}
+#else
+#define s3c2412_i2s_suspend NULL
+#define s3c2412_i2s_resume NULL
+#endif /* CONFIG_PM */
+
+int s5p_i2sv5_register_dai(struct device *dev, struct snd_soc_dai_driver *dai)
+{
+ struct snd_soc_dai_ops *ops = dai->ops;
+
+ ops->trigger = s5p_i2s_wr_trigger;
+ ops->hw_params = s5p_i2s_wr_hw_params;
+ ops->set_fmt = s5p_i2s_set_fmt;
+ ops->set_clkdiv = s5p_i2s_set_clkdiv;
+ ops->set_sysclk = s5p_i2s_set_sysclk;
+ ops->startup = s5p_i2s_wr_startup;
+ ops->shutdown = s5p_i2s_wr_shutdown;
+ /* suspend/resume are not necessary due to Clock/Pwer gating scheme */
+ dai->suspend = s5p_i2s_suspend;
+ dai->resume = s5p_i2s_resume;
+ return snd_soc_register_dai(dev, dai);
+}
+
+static __devinit int s3c64xx_iis_dev_probe(struct platform_device *pdev)
+{
+ struct s3c_audio_pdata *i2s_pdata;
+ struct s3c_i2sv2_info *i2s;
+ struct snd_soc_dai_driver *dai;
+ struct resource *res;
+ struct clk *fout_epll, *mout_epll;
+ struct clk *mout_audss = NULL;
+ unsigned long base;
+ unsigned int iismod;
+ int ret = 0;
+ if (pdev->id >= MAX_I2SV3) {
+ dev_err(&pdev->dev, "id %d out of range\n", pdev->id);
+ return -EINVAL;
+ }
+
+ i2s = &s3c64xx_i2s[pdev->id];
+ i2s->dev = &pdev->dev;
+ dai = &s3c64xx_i2s_dai_driver[pdev->id];
+ //dai->dev = &pdev->dev;
+ dai->id = pdev->id;
+ s3c64xx_iis_dai_init(dai);
+
+ i2s->dma_capture = &s3c64xx_i2s_pcm_stereo_in[pdev->id];
+ i2s->dma_playback = &s3c64xx_i2s_pcm_stereo_out[pdev->id];
+
+ res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "Unable to get I2S-TX dma resource\n");
+ return -ENXIO;
+ }
+ i2s->dma_playback->channel = res->start;
+
+ res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+ if (!res) {
+ dev_err(&pdev->dev, "Unable to get I2S-RX dma resource\n");
+ return -ENXIO;
+ }
+ i2s->dma_capture->channel = res->start;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "Unable to get I2S SFR address\n");
+ return -ENXIO;
+ }
+
+ if (!request_mem_region(res->start, resource_size(res),
+ "s3c64xx-i2s")) {
+ dev_err(&pdev->dev, "Unable to request SFR region\n");
+ return -EBUSY;
+ }
+
+ i2s->dma_capture->dma_addr = res->start + S3C2412_IISRXD;
+ i2s->dma_playback->dma_addr = res->start + S3C2412_IISTXD;
+
+ i2s->dma_capture->client = &s3c64xx_dma_client_in;
+ i2s->dma_capture->dma_size = 4;
+ i2s->dma_playback->client = &s3c64xx_dma_client_out;
+ i2s->dma_playback->dma_size = 4;
+
+ i2s_pdata = pdev->dev.platform_data;
+
+ //dai->private_data = i2s;
+ dev_set_drvdata(&pdev->dev, i2s);
+ base = i2s->dma_playback->dma_addr - S3C2412_IISTXD;
+
+ i2s->regs = ioremap(base, 0x100);
+ if (i2s->regs == NULL) {
+ dev_err(&pdev->dev, "cannot ioremap registers\n");
+ return -ENXIO;
+ }
+
+ /* Configure the I2S pins if MUX'ed */
+ if (i2s_pdata && i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) {
+ dev_err(&pdev->dev, "Unable to configure gpio\n");
+ return -EINVAL;
+ }
+
+ /* Get i2s power domain regulator */
+ i2s->regulator = regulator_get(&pdev->dev, "pd");
+ if (IS_ERR(i2s->regulator)) {
+ dev_err(&pdev->dev, "%s: failed to get resource %s\n",
+ __func__, "i2s");
+ return PTR_ERR(i2s->regulator);
+ }
+
+ /* Enable Power domain */
+ regulator_enable(i2s->regulator);
+
+ /* Audio Clock
+ * fout_epll >> mout_epll >> sclk_audio
+ * fout_epll >> mout_audss >> audio-bus(iis_clk)
+ * fout_epll >> dout_audio_bus_clk_i2s(iis_busclk)
+ */
+ fout_epll = clk_get(&pdev->dev, "fout_epll");
+ if (IS_ERR(fout_epll)) {
+ dev_err(&pdev->dev, "failed to get fout_epll\n");
+ goto err;
+ }
+
+ mout_epll = clk_get(&pdev->dev, "mout_epll");
+ if (IS_ERR(mout_epll)) {
+ dev_err(&pdev->dev, "failed to get mout_epll\n");
+ clk_put(fout_epll);
+ goto err;
+ }
+ clk_set_parent(mout_epll, fout_epll);
+
+ i2s->sclk_audio = clk_get(&pdev->dev, "sclk_audio");
+ if (IS_ERR(i2s->sclk_audio)) {
+ dev_err(&pdev->dev, "failed to get sclk_audio\n");
+ ret = PTR_ERR(i2s->sclk_audio);
+ clk_put(i2s->sclk_audio);
+ goto err;
+ }
+ clk_set_parent(i2s->sclk_audio, mout_epll);
+ /* Need not to enable in general */
+ clk_enable(i2s->sclk_audio);
+
+ /* When I2S V5.1 used, initialize audio subsystem clock */
+ /* CLKMUX_ASS */
+ if (pdev->id == 0) {
+ mout_audss = clk_get(NULL, "mout_audss");
+ if (IS_ERR(mout_audss)) {
+ dev_err(&pdev->dev, "failed to get mout_audss\n");
+ goto err1;
+ }
+ clk_set_parent(mout_audss, fout_epll);
+ /*MUX-I2SA*/
+ i2s->iis_clk = clk_get(&pdev->dev, "audio-bus");
+ if (IS_ERR(i2s->iis_clk)) {
+ dev_err(&pdev->dev, "failed to get audio-bus\n");
+ clk_put(mout_audss);
+ goto err2;
+ }
+ clk_set_parent(i2s->iis_clk, mout_audss);
+ /*getting AUDIO BUS CLK*/
+ i2s->iis_busclk = clk_get(NULL, "dout_audio_bus_clk_i2s");
+ if (IS_ERR(i2s->iis_busclk)) {
+ printk(KERN_ERR "failed to get audss_hclk\n");
+ goto err3;
+ }
+ i2s->iis_ipclk = clk_get(&pdev->dev, "i2s_v50");
+ if (IS_ERR(i2s->iis_ipclk)) {
+ dev_err(&pdev->dev, "failed to get i2s_v50_clock\n");
+ goto err4;
+ }
+ }
+
+#if defined(CONFIG_PLAT_S5P)
+ writel(((1<<0)|(1<<31)), i2s->regs + S3C2412_IISCON);
+#endif
+
+ /* Mark ourselves as in TXRX mode so we can run through our cleanup
+ * process without warnings. */
+ iismod = readl(i2s->regs + S3C2412_IISMOD);
+ iismod |= S3C2412_IISMOD_MODE_TXRX;
+ writel(iismod, i2s->regs + S3C2412_IISMOD);
+
+#ifdef CONFIG_S5P_INTERNAL_DMA
+ s5p_i2s_sec_init(i2s->regs, base);
+#endif
+
+ ret = s5p_i2sv5_register_dai(&pdev->dev, dai);
+ if (ret != 0)
+ goto err_i2sv5;
+
+ clk_put(i2s->iis_ipclk);
+ clk_put(i2s->iis_busclk);
+ clk_put(i2s->iis_clk);
+ clk_put(mout_audss);
+ clk_put(mout_epll);
+ clk_put(fout_epll);
+ return 0;
+err4:
+ clk_put(i2s->iis_busclk);
+err3:
+ clk_put(i2s->iis_clk);
+err2:
+ clk_put(mout_audss);
+err1:
+ clk_put(mout_epll);
+ clk_put(fout_epll);
+err_i2sv5:
+ /* Not implemented for I2Sv5 core yet */
+err:
+ iounmap(i2s->regs);
+
+ return ret;
+}
+
+static __devexit int s3c64xx_iis_dev_remove(struct platform_device *pdev)
+{
+ dev_err(&pdev->dev, "Device removal not yet supported\n");
+ return 0;
+}
+
+static struct platform_driver s3c64xx_iis_driver = {
+ .probe = s3c64xx_iis_dev_probe,
+ .remove = s3c64xx_iis_dev_remove,
+ .driver = {
+ .name = "samsung-i2s",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init s3c64xx_i2s_init(void)
+{
+ return platform_driver_register(&s3c64xx_iis_driver);
+}
+module_init(s3c64xx_i2s_init);
+
+static void __exit s3c64xx_i2s_exit(void)
+{
+ platform_driver_unregister(&s3c64xx_iis_driver);
+}
+module_exit(s3c64xx_i2s_exit);
+
+/* Module information */
+MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
+MODULE_DESCRIPTION("S5PC1XX I2S SoC Interface");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/samsung/s5pc1xx-i2s.h b/sound/soc/samsung/s5pc1xx-i2s.h
new file mode 100644
index 0000000..b754cd5
--- /dev/null
+++ b/sound/soc/samsung/s5pc1xx-i2s.h
@@ -0,0 +1,124 @@
+/* sound/soc/s3c24xx/s3c64xx-i2s.h
+ *
+ * ALSA SoC Audio Layer - S3C64XX I2S driver
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ * http://armlinux.simtec.co.uk/
+ *
+ * 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 __SND_SOC_S3C24XX_S3C64XX_I2S_H
+#define __SND_SOC_S3C24XX_S3C64XX_I2S_H __FILE__
+
+struct clk;
+
+//#include "s3c-i2s-v2.h"
+//==
+
+#define S3C_I2SV2_DIV_BCLK (1)
+#define S3C_I2SV2_DIV_RCLK (2)
+#define S3C_I2SV2_DIV_PRESCALER (3)
+
+/**
+ * struct s3c_i2sv2_info - S3C I2S-V2 information
+ * @dev: The parent device passed to use from the probe.
+ * @regs: The pointer to the device registe block.
+ * @master: True if the I2S core is the I2S bit clock master.
+ * @dma_playback: DMA information for playback channel.
+ * @dma_capture: DMA information for capture channel.
+ * @suspend_iismod: PM save for the IISMOD register.
+ * @suspend_iiscon: PM save for the IISCON register.
+ * @suspend_iispsr: PM save for the IISPSR register.
+ *
+ * This is the private codec state for the hardware associated with an
+ * I2S channel such as the register mappings and clock sources.
+ */
+struct s3c_i2sv2_info {
+ struct device *dev;
+ void __iomem *regs;
+
+ struct clk *sclk_audio;
+ struct clk *iis_ipclk;
+ struct clk *iis_cclk;
+ struct clk *iis_clk;
+ struct clk *iis_busclk;
+ struct regulator *regulator;
+
+ unsigned char master;
+
+ struct s3c_dma_params *dma_playback;
+ struct s3c_dma_params *dma_capture;
+
+ u32 suspend_iismod;
+ u32 suspend_iiscon;
+ u32 suspend_iispsr;
+ u32 suspend_iisahb;
+ u32 suspend_audss_clksrc;
+ u32 suspend_audss_clkdiv;
+ u32 suspend_audss_clkgate;
+};
+
+struct s3c_i2sv2_rate_calc {
+ unsigned int clk_div; /* for prescaler */
+ unsigned int fs_div; /* for root frame clock */
+};
+
+extern int s3c_i2sv2_iis_calc_rate(struct s3c_i2sv2_rate_calc *info,
+ unsigned int *fstab,
+ unsigned int rate, struct clk *clk);
+
+/**
+ * s3c_i2sv2_probe - probe for i2s device helper
+ * @pdev: The platform device supplied to the original probe.
+ * @dai: The ASoC DAI structure supplied to the original probe.
+ * @i2s: Our local i2s structure to fill in.
+ * @base: The base address for the registers.
+ */
+extern int s3c_i2sv2_probe(struct platform_device *pdev,
+ struct snd_soc_dai *dai,
+ struct s3c_i2sv2_info *i2s,
+ unsigned long base);
+
+/**
+ * s3c_i2sv2_register_dai - register dai with soc core
+ * @dai: The snd_soc_dai structure to register
+ *
+ * Fill in any missing fields and then register the given dai with the
+ * soc core.
+ */
+extern int s3c_i2sv2_register_dai(struct snd_soc_dai *dai);
+extern void s5p_idma_init(void *);
+
+//==
+
+#define USE_CLKAUDIO 1
+
+#define S3C64XX_DIV_BCLK S3C_I2SV2_DIV_BCLK
+#define S3C64XX_DIV_RCLK S3C_I2SV2_DIV_RCLK
+#define S3C64XX_DIV_PRESCALER S3C_I2SV2_DIV_PRESCALER
+
+#define S3C64XX_CLKSRC_PCLK (0)
+#define S3C64XX_CLKSRC_MUX (1)
+#define S3C64XX_CLKSRC_CDCLK (2)
+
+extern struct snd_soc_dai s3c64xx_i2s_dai[];
+
+extern struct snd_soc_dai i2s_sec_fifo_dai;
+extern struct snd_soc_dai i2s_dai;
+extern struct snd_soc_platform s3c_dma_wrapper;
+
+extern struct clk *s3c64xx_i2s_get_clock(struct snd_soc_dai *dai);
+extern int s5p_i2s_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai);
+extern int s5p_i2s_startup(struct snd_soc_dai *dai);
+extern int s5p_i2s_trigger(struct snd_pcm_substream *substream,
+ int cmd, struct snd_soc_dai *dai);
+extern void s5p_i2s_sec_init(void *, dma_addr_t);
+
+#endif /* __SND_SOC_S3C24XX_S3C64XX_I2S_H */
diff --git a/sound/usb/clock.c b/sound/usb/clock.c
index 075195e..f0ff776 100644
--- a/sound/usb/clock.c
+++ b/sound/usb/clock.c
@@ -111,7 +111,8 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, int source_id)
return 0;
/* If a clock source can't tell us whether it's valid, we assume it is */
- if (!uac2_control_is_readable(cs_desc->bmControls, UAC2_CS_CONTROL_CLOCK_VALID))
+ if (!uac2_control_is_readable(cs_desc->bmControls,
+ UAC2_CS_CONTROL_CLOCK_VALID - 1))
return 1;
err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 0de7cbd..9363a8c 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -1246,6 +1246,13 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
/* disable non-functional volume control */
master_bits &= ~UAC_CONTROL_BIT(UAC_FU_VOLUME);
break;
+ case USB_ID(0x1130, 0xf211):
+ snd_printk(KERN_INFO
+ "usbmixer: volume control quirk for Tenx TP6911 Audio Headset\n");
+ /* disable non-functional volume control */
+ channels = 0;
+ break;
+
}
if (channels > 0)
first_ch_bits = snd_usb_combine_bytes(bmaControls + csize, csize);
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index b8dcbf4..506c0fa 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -670,6 +670,9 @@ static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime,
int count = 0, needs_knot = 0;
int err;
+ kfree(subs->rate_list.list);
+ subs->rate_list.list = NULL;
+
list_for_each_entry(fp, &subs->fmt_list, list) {
if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS)
return 0;
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 0b2ae8e..7ccffb2 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -2581,6 +2581,59 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
+/* Microsoft XboxLive Headset/Xbox Communicator */
+{
+ USB_DEVICE(0x045e, 0x0283),
+ .bInterfaceClass = USB_CLASS_PER_INTERFACE,
+ .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+ .vendor_name = "Microsoft",
+ .product_name = "XboxLive Headset/Xbox Communicator",
+ .ifnum = QUIRK_ANY_INTERFACE,
+ .type = QUIRK_COMPOSITE,
+ .data = &(const struct snd_usb_audio_quirk[]) {
+ {
+ /* playback */
+ .ifnum = 0,
+ .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+ .data = &(const struct audioformat) {
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels = 1,
+ .iface = 0,
+ .altsetting = 0,
+ .altset_idx = 0,
+ .attributes = 0,
+ .endpoint = 0x04,
+ .ep_attr = 0x05,
+ .rates = SNDRV_PCM_RATE_CONTINUOUS,
+ .rate_min = 22050,
+ .rate_max = 22050
+ }
+ },
+ {
+ /* capture */
+ .ifnum = 1,
+ .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+ .data = &(const struct audioformat) {
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels = 1,
+ .iface = 1,
+ .altsetting = 0,
+ .altset_idx = 0,
+ .attributes = 0,
+ .endpoint = 0x85,
+ .ep_attr = 0x05,
+ .rates = SNDRV_PCM_RATE_CONTINUOUS,
+ .rate_min = 16000,
+ .rate_max = 16000
+ }
+ },
+ {
+ .ifnum = -1
+ }
+ }
+ }
+},
+
{
/*
* Some USB MIDI devices don't have an audio control interface,
diff --git a/tools/usb/ffs-test.c b/tools/usb/ffs-test.c
index b9c7986..f17dfee 100644
--- a/tools/usb/ffs-test.c
+++ b/tools/usb/ffs-test.c
@@ -324,7 +324,7 @@ static void *start_thread_helper(void *arg)
ret = t->in(t, t->buf, t->buf_size);
if (ret > 0) {
- ret = t->out(t, t->buf, t->buf_size);
+ ret = t->out(t, t->buf, ret);
name = out_name;
op = "write";
} else {
diff --git a/usr/gen_init_cpio.c b/usr/gen_init_cpio.c
index af0f22f..aca6edc 100644
--- a/usr/gen_init_cpio.c
+++ b/usr/gen_init_cpio.c
@@ -303,7 +303,7 @@ static int cpio_mkfile(const char *name, const char *location,
int retval;
int rc = -1;
int namesize;
- int i;
+ unsigned int i;
mode |= S_IFREG;
@@ -381,25 +381,28 @@ error:
static char *cpio_replace_env(char *new_location)
{
- char expanded[PATH_MAX + 1];
- char env_var[PATH_MAX + 1];
- char *start;
- char *end;
-
- for (start = NULL; (start = strstr(new_location, "${")); ) {
- end = strchr(start, '}');
- if (start < end) {
- *env_var = *expanded = '\0';
- strncat(env_var, start + 2, end - start - 2);
- strncat(expanded, new_location, start - new_location);
- strncat(expanded, getenv(env_var), PATH_MAX);
- strncat(expanded, end + 1, PATH_MAX);
- strncpy(new_location, expanded, PATH_MAX);
- } else
- break;
- }
-
- return new_location;
+ char expanded[PATH_MAX + 1];
+ char env_var[PATH_MAX + 1];
+ char *start;
+ char *end;
+
+ for (start = NULL; (start = strstr(new_location, "${")); ) {
+ end = strchr(start, '}');
+ if (start < end) {
+ *env_var = *expanded = '\0';
+ strncat(env_var, start + 2, end - start - 2);
+ strncat(expanded, new_location, start - new_location);
+ strncat(expanded, getenv(env_var),
+ PATH_MAX - strlen(expanded));
+ strncat(expanded, end + 1,
+ PATH_MAX - strlen(expanded));
+ strncpy(new_location, expanded, PATH_MAX);
+ new_location[PATH_MAX] = 0;
+ } else
+ break;
+ }
+
+ return new_location;
}